()
| 134 | } |
| 135 | |
| 136 | async testCategories() { |
| 137 | console.log('\n🏷️ Testing categories listing'); |
| 138 | |
| 139 | return new Promise((resolve, reject) => { |
| 140 | this.db.all( |
| 141 | 'SELECT labels, COUNT(*) as count FROM issues WHERE labels IS NOT NULL GROUP BY labels LIMIT 10', |
| 142 | (err, rows) => { |
| 143 | if (err) { |
| 144 | console.error('❌ Categories query failed:', err.message); |
| 145 | reject(err); |
| 146 | return; |
| 147 | } |
| 148 | |
| 149 | console.log(`✅ Found ${rows.length} label groups`); |
| 150 | |
| 151 | const categoryMap = new Map(); |
| 152 | |
| 153 | rows.forEach(row => { |
| 154 | if (row.labels) { |
| 155 | try { |
| 156 | const labels = JSON.parse(row.labels); |
| 157 | labels.forEach(label => { |
| 158 | categoryMap.set(label, (categoryMap.get(label) || 0) + row.count); |
| 159 | }); |
| 160 | } catch (parseErr) { |
| 161 | console.warn(`⚠️ Failed to parse labels: ${row.labels}`); |
| 162 | } |
| 163 | } |
| 164 | }); |
| 165 | |
| 166 | const topCategories = Array.from(categoryMap.entries()) |
| 167 | .sort((a, b) => b[1] - a[1]) |
| 168 | .slice(0, 10); |
| 169 | |
| 170 | console.log('📊 Top categories:'); |
| 171 | topCategories.forEach(([label, count]) => { |
| 172 | console.log(` • ${label}: ${count} articles`); |
| 173 | }); |
| 174 | |
| 175 | resolve(topCategories); |
| 176 | } |
| 177 | ); |
| 178 | }); |
| 179 | } |
| 180 | |
| 181 | close() { |
| 182 | if (this.db) { |
no test coverage detected