edsger 0.45.0 → 0.45.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +3 -9
- package/dist/api/__tests__/app-store.test.d.ts +0 -7
- package/dist/api/__tests__/app-store.test.js +0 -60
- package/dist/api/__tests__/intelligence.test.d.ts +0 -11
- package/dist/api/__tests__/intelligence.test.js +0 -315
- package/dist/api/features/__tests__/feature-utils.test.d.ts +0 -4
- package/dist/api/features/__tests__/feature-utils.test.js +0 -370
- package/dist/api/features/__tests__/status-updater.test.d.ts +0 -4
- package/dist/api/features/__tests__/status-updater.test.js +0 -88
- package/dist/commands/build/__tests__/build.test.d.ts +0 -5
- package/dist/commands/build/__tests__/build.test.js +0 -206
- package/dist/commands/build/__tests__/detect-project.test.d.ts +0 -6
- package/dist/commands/build/__tests__/detect-project.test.js +0 -160
- package/dist/commands/build/__tests__/run-build.test.d.ts +0 -6
- package/dist/commands/build/__tests__/run-build.test.js +0 -433
- package/dist/commands/intelligence/__tests__/command.test.d.ts +0 -4
- package/dist/commands/intelligence/__tests__/command.test.js +0 -48
- package/dist/commands/workflow/core/__tests__/feature-filter.test.d.ts +0 -5
- package/dist/commands/workflow/core/__tests__/feature-filter.test.js +0 -316
- package/dist/commands/workflow/core/__tests__/pipeline-evaluator.test.d.ts +0 -4
- package/dist/commands/workflow/core/__tests__/pipeline-evaluator.test.js +0 -397
- package/dist/commands/workflow/core/__tests__/state-manager.test.d.ts +0 -4
- package/dist/commands/workflow/core/__tests__/state-manager.test.js +0 -384
- package/dist/config/__tests__/config.test.d.ts +0 -4
- package/dist/config/__tests__/config.test.js +0 -286
- package/dist/config/__tests__/feature-status.test.d.ts +0 -4
- package/dist/config/__tests__/feature-status.test.js +0 -111
- package/dist/errors/__tests__/index.test.d.ts +0 -4
- package/dist/errors/__tests__/index.test.js +0 -349
- package/dist/phases/app-store-generation/__tests__/agent.test.d.ts +0 -5
- package/dist/phases/app-store-generation/__tests__/agent.test.js +0 -142
- package/dist/phases/app-store-generation/__tests__/context.test.d.ts +0 -4
- package/dist/phases/app-store-generation/__tests__/context.test.js +0 -284
- package/dist/phases/app-store-generation/__tests__/prompts.test.d.ts +0 -4
- package/dist/phases/app-store-generation/__tests__/prompts.test.js +0 -122
- package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.d.ts +0 -5
- package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.js +0 -826
- package/dist/phases/code-review/__tests__/diff-utils.test.d.ts +0 -1
- package/dist/phases/code-review/__tests__/diff-utils.test.js +0 -101
- package/dist/phases/intelligence-analysis/__tests__/context.test.d.ts +0 -4
- package/dist/phases/intelligence-analysis/__tests__/context.test.js +0 -192
- package/dist/phases/intelligence-analysis/__tests__/matching.test.d.ts +0 -13
- package/dist/phases/intelligence-analysis/__tests__/matching.test.js +0 -154
- package/dist/phases/intelligence-analysis/__tests__/orchestration.test.d.ts +0 -5
- package/dist/phases/intelligence-analysis/__tests__/orchestration.test.js +0 -378
- package/dist/phases/intelligence-analysis/__tests__/prompts.test.d.ts +0 -4
- package/dist/phases/intelligence-analysis/__tests__/prompts.test.js +0 -33
- package/dist/phases/pr-execution/__tests__/file-assigner.test.d.ts +0 -1
- package/dist/phases/pr-execution/__tests__/file-assigner.test.js +0 -303
- package/dist/phases/pr-resolve/__tests__/checklist-learner.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/checklist-learner.test.js +0 -157
- package/dist/phases/pr-resolve/__tests__/prompts.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/prompts.test.js +0 -116
- package/dist/phases/pr-resolve/__tests__/resolve-mapping.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/resolve-mapping.test.js +0 -138
- package/dist/phases/pr-resolve/__tests__/types.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/types.test.js +0 -43
- package/dist/phases/pr-resolve/__tests__/workspace.test.d.ts +0 -1
- package/dist/phases/pr-resolve/__tests__/workspace.test.js +0 -111
- package/dist/phases/pr-review/__tests__/prompts.test.d.ts +0 -1
- package/dist/phases/pr-review/__tests__/prompts.test.js +0 -49
- package/dist/phases/pr-review/__tests__/review-comments.test.d.ts +0 -1
- package/dist/phases/pr-review/__tests__/review-comments.test.js +0 -110
- package/dist/phases/pr-shared/__tests__/agent-utils.test.d.ts +0 -1
- package/dist/phases/pr-shared/__tests__/agent-utils.test.js +0 -91
- package/dist/phases/pr-shared/__tests__/context.test.d.ts +0 -1
- package/dist/phases/pr-shared/__tests__/context.test.js +0 -94
- package/dist/phases/pr-splitting/__tests__/import-dep-validator.test.d.ts +0 -1
- package/dist/phases/pr-splitting/__tests__/import-dep-validator.test.js +0 -331
- package/dist/phases/release-sync/__tests__/github.test.d.ts +0 -9
- package/dist/phases/release-sync/__tests__/github.test.js +0 -123
- package/dist/phases/release-sync/__tests__/snapshot.test.d.ts +0 -8
- package/dist/phases/release-sync/__tests__/snapshot.test.js +0 -93
- package/dist/phases/smoke-test/__tests__/agent.test.d.ts +0 -4
- package/dist/phases/smoke-test/__tests__/agent.test.js +0 -85
- package/dist/services/coaching/__tests__/coaching-agent.test.d.ts +0 -1
- package/dist/services/coaching/__tests__/coaching-agent.test.js +0 -74
- package/dist/services/coaching/__tests__/coaching-loop.test.d.ts +0 -1
- package/dist/services/coaching/__tests__/coaching-loop.test.js +0 -59
- package/dist/services/coaching/__tests__/self-rating.test.d.ts +0 -1
- package/dist/services/coaching/__tests__/self-rating.test.js +0 -188
- package/dist/services/phase-hooks/__tests__/bindings-fetcher.test.d.ts +0 -1
- package/dist/services/phase-hooks/__tests__/bindings-fetcher.test.js +0 -122
- package/dist/services/phase-hooks/__tests__/hook-executor.test.d.ts +0 -1
- package/dist/services/phase-hooks/__tests__/hook-executor.test.js +0 -321
- package/dist/services/phase-hooks/__tests__/hook-runner.test.d.ts +0 -1
- package/dist/services/phase-hooks/__tests__/hook-runner.test.js +0 -261
- package/dist/services/phase-hooks/__tests__/plugin-loader.test.d.ts +0 -1
- package/dist/services/phase-hooks/__tests__/plugin-loader.test.js +0 -158
- package/dist/services/video/__tests__/video-pipeline.test.d.ts +0 -6
- package/dist/services/video/__tests__/video-pipeline.test.js +0 -249
- package/dist/workspace/__tests__/workspace-manager.test.d.ts +0 -7
- package/dist/workspace/__tests__/workspace-manager.test.js +0 -52
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration tests for analyseIntelligence orchestration.
|
|
3
|
-
* Uses dependency injection to mock API calls and AI agent.
|
|
4
|
-
*/
|
|
5
|
-
import assert from 'node:assert';
|
|
6
|
-
import { describe, it } from 'node:test';
|
|
7
|
-
import { analyseIntelligence } from '../index.js';
|
|
8
|
-
// ── Helpers ────────────────────────────────────────────────────
|
|
9
|
-
const fakeConfig = {
|
|
10
|
-
patterns: ['**/*.ts'],
|
|
11
|
-
exclude: [],
|
|
12
|
-
severity: 'error',
|
|
13
|
-
maxFiles: 100,
|
|
14
|
-
claude: { timeout: 30000 },
|
|
15
|
-
workflow: {
|
|
16
|
-
maxConcurrency: 3,
|
|
17
|
-
pollInterval: 30000,
|
|
18
|
-
maxRetries: 3,
|
|
19
|
-
retryCooldown: 300000,
|
|
20
|
-
workerTimeout: 1800000,
|
|
21
|
-
maxVerificationIterations: 10,
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
const fakeProduct = {
|
|
25
|
-
id: 'prod-001',
|
|
26
|
-
name: 'TestApp',
|
|
27
|
-
description: 'A test product',
|
|
28
|
-
features: [],
|
|
29
|
-
};
|
|
30
|
-
function makeCompetitor(name, id, status = 'confirmed') {
|
|
31
|
-
return {
|
|
32
|
-
id,
|
|
33
|
-
product_id: 'prod-001',
|
|
34
|
-
name,
|
|
35
|
-
url: `https://${name.toLowerCase()}.com`,
|
|
36
|
-
app_store_url: null,
|
|
37
|
-
play_store_url: null,
|
|
38
|
-
description: `${name} desc`,
|
|
39
|
-
category: 'tools',
|
|
40
|
-
status,
|
|
41
|
-
discovery_source: status === 'suggested' ? 'ai_discovery' : 'manual',
|
|
42
|
-
discovery_reason: status === 'suggested' ? 'AI found it' : null,
|
|
43
|
-
notes: null,
|
|
44
|
-
created_by: 'user-1',
|
|
45
|
-
created_at: '2026-03-25',
|
|
46
|
-
updated_at: '2026-03-25',
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
function makeSnapshot(competitorId, id = 'snap-1') {
|
|
50
|
-
return {
|
|
51
|
-
id,
|
|
52
|
-
competitor_id: competitorId,
|
|
53
|
-
product_id: 'prod-001',
|
|
54
|
-
features: [],
|
|
55
|
-
pricing: {},
|
|
56
|
-
tech_stack: [],
|
|
57
|
-
app_rating: null,
|
|
58
|
-
app_review_count: null,
|
|
59
|
-
app_version: null,
|
|
60
|
-
app_last_updated: null,
|
|
61
|
-
recent_reviews: [],
|
|
62
|
-
social_mentions: {},
|
|
63
|
-
changes_detected: [],
|
|
64
|
-
source: 'ai_analysis',
|
|
65
|
-
raw_data: null,
|
|
66
|
-
created_at: '2026-03-25',
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
function makeReport(id = 'rpt-1') {
|
|
70
|
-
return {
|
|
71
|
-
id,
|
|
72
|
-
product_id: 'prod-001',
|
|
73
|
-
report_type: 'competitive',
|
|
74
|
-
title: 'Test Report',
|
|
75
|
-
summary: 'Summary',
|
|
76
|
-
full_report: '# Report',
|
|
77
|
-
key_findings: [],
|
|
78
|
-
recommendations: [],
|
|
79
|
-
competitor_highlights: [],
|
|
80
|
-
market_signals: [],
|
|
81
|
-
trends: [],
|
|
82
|
-
persona_updates: null,
|
|
83
|
-
pmf_score: null,
|
|
84
|
-
pmf_signals: null,
|
|
85
|
-
guidance: null,
|
|
86
|
-
status: 'completed',
|
|
87
|
-
snapshot_ids: [],
|
|
88
|
-
created_by: 'user-1',
|
|
89
|
-
created_at: '2026-03-25',
|
|
90
|
-
updated_at: '2026-03-25',
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function makeContext(confirmed = []) {
|
|
94
|
-
return {
|
|
95
|
-
product: fakeProduct,
|
|
96
|
-
confirmedCompetitors: confirmed,
|
|
97
|
-
suggestedCompetitors: [],
|
|
98
|
-
previousSnapshots: new Map(),
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
/** Create mock deps that return the given AI result */
|
|
102
|
-
function makeDeps(aiResult, contextOverride) {
|
|
103
|
-
const batchCreateCalls = [];
|
|
104
|
-
const saveSnapCalls = [];
|
|
105
|
-
const saveRptCalls = [];
|
|
106
|
-
const updateRptCalls = [];
|
|
107
|
-
let batchCreateCounter = 0;
|
|
108
|
-
return {
|
|
109
|
-
batchCreateCalls,
|
|
110
|
-
saveSnapCalls,
|
|
111
|
-
saveRptCalls,
|
|
112
|
-
updateRptCalls,
|
|
113
|
-
prepareContext: () => Promise.resolve({
|
|
114
|
-
context: contextOverride || makeContext(),
|
|
115
|
-
analysisPrompt: 'fake prompt',
|
|
116
|
-
}),
|
|
117
|
-
executeQuery: () => Promise.resolve(aiResult),
|
|
118
|
-
batchCreate: (_productId, competitors) => {
|
|
119
|
-
batchCreateCalls.push([_productId, competitors]);
|
|
120
|
-
return Promise.resolve(competitors.map((c) => makeCompetitor(c.name, `discovered-${batchCreateCounter++}`, 'suggested')));
|
|
121
|
-
},
|
|
122
|
-
saveSnap: (snap) => {
|
|
123
|
-
saveSnapCalls.push([snap]);
|
|
124
|
-
return Promise.resolve(makeSnapshot(snap.competitor_id, `snap-${saveSnapCalls.length}`));
|
|
125
|
-
},
|
|
126
|
-
saveRpt: (report) => {
|
|
127
|
-
saveRptCalls.push([report]);
|
|
128
|
-
return Promise.resolve(makeReport(`rpt-${saveRptCalls.length}`));
|
|
129
|
-
},
|
|
130
|
-
updateRpt: (_id, updates) => {
|
|
131
|
-
updateRptCalls.push([_id, updates]);
|
|
132
|
-
return Promise.resolve(makeReport(_id));
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
// ============================================================
|
|
137
|
-
// Success: full flow with discovery
|
|
138
|
-
// ============================================================
|
|
139
|
-
void describe('analyseIntelligence — discovery flow', () => {
|
|
140
|
-
const aiResult = {
|
|
141
|
-
title: 'Competitive Report',
|
|
142
|
-
summary: 'Found 2 competitors',
|
|
143
|
-
full_report: '# Report',
|
|
144
|
-
key_findings: [
|
|
145
|
-
{
|
|
146
|
-
finding: 'Competitor A is growing',
|
|
147
|
-
severity: 'important',
|
|
148
|
-
category: 'competitive',
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
recommendations: [
|
|
152
|
-
{
|
|
153
|
-
action: 'Add feature X',
|
|
154
|
-
priority: 'high',
|
|
155
|
-
effort: 'medium',
|
|
156
|
-
impact: 'high',
|
|
157
|
-
rationale: 'Gap',
|
|
158
|
-
},
|
|
159
|
-
],
|
|
160
|
-
competitor_highlights: [],
|
|
161
|
-
market_signals: [],
|
|
162
|
-
trends: [],
|
|
163
|
-
discovered_competitors: [
|
|
164
|
-
{
|
|
165
|
-
name: 'CompA',
|
|
166
|
-
url: 'https://compa.com',
|
|
167
|
-
discovery_reason: 'Top alternative',
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
name: 'CompB',
|
|
171
|
-
url: 'https://compb.com',
|
|
172
|
-
discovery_reason: 'Same category',
|
|
173
|
-
},
|
|
174
|
-
],
|
|
175
|
-
competitor_snapshots: [
|
|
176
|
-
{
|
|
177
|
-
competitor_name: 'CompA',
|
|
178
|
-
features: [{ name: 'Feat1', description: 'Desc', is_new: true }],
|
|
179
|
-
app_rating: 4.5,
|
|
180
|
-
},
|
|
181
|
-
{ competitor_name: 'CompB', features: [], app_rating: 3.8 },
|
|
182
|
-
],
|
|
183
|
-
};
|
|
184
|
-
void it('should return success status', async () => {
|
|
185
|
-
const deps = makeDeps(aiResult);
|
|
186
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
187
|
-
assert.strictEqual(result.status, 'success');
|
|
188
|
-
});
|
|
189
|
-
void it('should save discovered competitors via batchCreate', async () => {
|
|
190
|
-
const deps = makeDeps(aiResult);
|
|
191
|
-
await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
192
|
-
assert.strictEqual(deps.batchCreateCalls.length, 1);
|
|
193
|
-
const [, competitors] = deps.batchCreateCalls[0];
|
|
194
|
-
assert.strictEqual(competitors.length, 2);
|
|
195
|
-
assert.strictEqual(competitors[0].name, 'CompA');
|
|
196
|
-
assert.strictEqual(competitors[1].name, 'CompB');
|
|
197
|
-
});
|
|
198
|
-
void it('should save snapshots matched to discovered competitors', async () => {
|
|
199
|
-
const deps = makeDeps(aiResult);
|
|
200
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
201
|
-
assert.strictEqual(deps.saveSnapCalls.length, 2);
|
|
202
|
-
assert.strictEqual(result.snapshots.length, 2);
|
|
203
|
-
});
|
|
204
|
-
void it('should save the report', async () => {
|
|
205
|
-
const deps = makeDeps(aiResult);
|
|
206
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
207
|
-
assert.strictEqual(deps.saveRptCalls.length, 1);
|
|
208
|
-
assert.ok(result.report);
|
|
209
|
-
});
|
|
210
|
-
void it('should return discovered competitors in result', async () => {
|
|
211
|
-
const deps = makeDeps(aiResult);
|
|
212
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
213
|
-
assert.strictEqual(result.discoveredCompetitors.length, 2);
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
// ============================================================
|
|
217
|
-
// Success: existing competitors (no discovery needed)
|
|
218
|
-
// ============================================================
|
|
219
|
-
void describe('analyseIntelligence — existing competitors', () => {
|
|
220
|
-
const existing = [makeCompetitor('Linear', 'id-linear')];
|
|
221
|
-
const aiResult = {
|
|
222
|
-
title: 'Report',
|
|
223
|
-
summary: 'Update',
|
|
224
|
-
full_report: '# R',
|
|
225
|
-
key_findings: [],
|
|
226
|
-
recommendations: [],
|
|
227
|
-
competitor_highlights: [],
|
|
228
|
-
market_signals: [],
|
|
229
|
-
trends: [],
|
|
230
|
-
discovered_competitors: [],
|
|
231
|
-
competitor_snapshots: [
|
|
232
|
-
{
|
|
233
|
-
competitor_id: 'id-linear',
|
|
234
|
-
competitor_name: 'Linear',
|
|
235
|
-
features: [],
|
|
236
|
-
app_rating: 4.6,
|
|
237
|
-
},
|
|
238
|
-
],
|
|
239
|
-
};
|
|
240
|
-
void it('should not call batchCreate when no new competitors', async () => {
|
|
241
|
-
const deps = makeDeps(aiResult, makeContext(existing));
|
|
242
|
-
await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
243
|
-
assert.strictEqual(deps.batchCreateCalls.length, 0);
|
|
244
|
-
});
|
|
245
|
-
void it('should save snapshot matched by ID', async () => {
|
|
246
|
-
const deps = makeDeps(aiResult, makeContext(existing));
|
|
247
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
248
|
-
assert.strictEqual(result.snapshots.length, 1);
|
|
249
|
-
const [snapArg] = deps.saveSnapCalls[0];
|
|
250
|
-
assert.strictEqual(snapArg.competitor_id, 'id-linear');
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
// ============================================================
|
|
254
|
-
// Error: AI returns null
|
|
255
|
-
// ============================================================
|
|
256
|
-
void describe('analyseIntelligence — AI returns null', () => {
|
|
257
|
-
void it('should return error status', async () => {
|
|
258
|
-
const deps = makeDeps(null);
|
|
259
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
260
|
-
assert.strictEqual(result.status, 'error');
|
|
261
|
-
assert.strictEqual(result.report, null);
|
|
262
|
-
assert.strictEqual(result.discoveredCompetitors.length, 0);
|
|
263
|
-
assert.strictEqual(result.snapshots.length, 0);
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
// ============================================================
|
|
267
|
-
// Edge: AI returns empty arrays
|
|
268
|
-
// ============================================================
|
|
269
|
-
void describe('analyseIntelligence — empty AI result', () => {
|
|
270
|
-
const emptyResult = {
|
|
271
|
-
title: 'Empty',
|
|
272
|
-
summary: 'Nothing found',
|
|
273
|
-
full_report: '',
|
|
274
|
-
key_findings: [],
|
|
275
|
-
recommendations: [],
|
|
276
|
-
competitor_highlights: [],
|
|
277
|
-
market_signals: [],
|
|
278
|
-
trends: [],
|
|
279
|
-
};
|
|
280
|
-
void it('should succeed with no competitors or snapshots', async () => {
|
|
281
|
-
const deps = makeDeps(emptyResult);
|
|
282
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
283
|
-
assert.strictEqual(result.status, 'success');
|
|
284
|
-
assert.strictEqual(result.discoveredCompetitors.length, 0);
|
|
285
|
-
assert.strictEqual(result.snapshots.length, 0);
|
|
286
|
-
assert.strictEqual(deps.batchCreateCalls.length, 0);
|
|
287
|
-
assert.strictEqual(deps.saveSnapCalls.length, 0);
|
|
288
|
-
});
|
|
289
|
-
void it('should still save a report', async () => {
|
|
290
|
-
const deps = makeDeps(emptyResult);
|
|
291
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
292
|
-
assert.strictEqual(deps.saveRptCalls.length, 1);
|
|
293
|
-
assert.ok(result.report);
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
// ============================================================
|
|
297
|
-
// Edge: unmatched snapshots are skipped
|
|
298
|
-
// ============================================================
|
|
299
|
-
void describe('analyseIntelligence — unmatched snapshots', () => {
|
|
300
|
-
const aiResult = {
|
|
301
|
-
title: 'R',
|
|
302
|
-
summary: 'S',
|
|
303
|
-
full_report: '',
|
|
304
|
-
key_findings: [],
|
|
305
|
-
recommendations: [],
|
|
306
|
-
competitor_highlights: [],
|
|
307
|
-
market_signals: [],
|
|
308
|
-
trends: [],
|
|
309
|
-
discovered_competitors: [],
|
|
310
|
-
competitor_snapshots: [
|
|
311
|
-
{ competitor_name: 'Totally Unknown Product', features: [] },
|
|
312
|
-
],
|
|
313
|
-
};
|
|
314
|
-
void it('should skip snapshots for unknown competitors', async () => {
|
|
315
|
-
const deps = makeDeps(aiResult, makeContext([makeCompetitor('Linear', 'id-linear')]));
|
|
316
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
317
|
-
assert.strictEqual(result.snapshots.length, 0);
|
|
318
|
-
assert.strictEqual(deps.saveSnapCalls.length, 0);
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
// ============================================================
|
|
322
|
-
// Report update mode
|
|
323
|
-
// ============================================================
|
|
324
|
-
void describe('analyseIntelligence — update existing report', () => {
|
|
325
|
-
const aiResult = {
|
|
326
|
-
title: 'Updated',
|
|
327
|
-
summary: 'Refreshed',
|
|
328
|
-
full_report: '# Updated',
|
|
329
|
-
key_findings: [],
|
|
330
|
-
recommendations: [],
|
|
331
|
-
competitor_highlights: [],
|
|
332
|
-
market_signals: [],
|
|
333
|
-
trends: [],
|
|
334
|
-
};
|
|
335
|
-
void it('should call updateRpt instead of saveRpt when reportId given', async () => {
|
|
336
|
-
const deps = makeDeps(aiResult);
|
|
337
|
-
await analyseIntelligence({ productId: 'prod-001', reportId: 'existing-rpt' }, fakeConfig, deps);
|
|
338
|
-
assert.strictEqual(deps.updateRptCalls.length, 1);
|
|
339
|
-
assert.strictEqual(deps.saveRptCalls.length, 0);
|
|
340
|
-
const [rptId] = deps.updateRptCalls[0];
|
|
341
|
-
assert.strictEqual(rptId, 'existing-rpt');
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
// ============================================================
|
|
345
|
-
// Guidance passthrough
|
|
346
|
-
// ============================================================
|
|
347
|
-
void describe('analyseIntelligence — guidance', () => {
|
|
348
|
-
void it('should pass guidance into report payload', async () => {
|
|
349
|
-
const aiResult = {
|
|
350
|
-
title: 'R',
|
|
351
|
-
summary: 'S',
|
|
352
|
-
full_report: '',
|
|
353
|
-
key_findings: [],
|
|
354
|
-
recommendations: [],
|
|
355
|
-
competitor_highlights: [],
|
|
356
|
-
market_signals: [],
|
|
357
|
-
trends: [],
|
|
358
|
-
};
|
|
359
|
-
const deps = makeDeps(aiResult);
|
|
360
|
-
await analyseIntelligence({ productId: 'prod-001', guidance: 'Focus on pricing' }, fakeConfig, deps);
|
|
361
|
-
const [reportArg] = deps.saveRptCalls[0];
|
|
362
|
-
assert.strictEqual(reportArg.guidance, 'Focus on pricing');
|
|
363
|
-
});
|
|
364
|
-
});
|
|
365
|
-
// ============================================================
|
|
366
|
-
// Exception handling
|
|
367
|
-
// ============================================================
|
|
368
|
-
void describe('analyseIntelligence — exception in deps', () => {
|
|
369
|
-
void it('should return error when context fetch throws', async () => {
|
|
370
|
-
const deps = makeDeps(null);
|
|
371
|
-
deps.prepareContext = () => {
|
|
372
|
-
return Promise.reject(new Error('Network error'));
|
|
373
|
-
};
|
|
374
|
-
const result = await analyseIntelligence({ productId: 'prod-001' }, fakeConfig, deps);
|
|
375
|
-
assert.strictEqual(result.status, 'error');
|
|
376
|
-
assert.ok(result.error?.includes('Network error'));
|
|
377
|
-
});
|
|
378
|
-
});
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for intelligence analysis prompt generation.
|
|
3
|
-
*/
|
|
4
|
-
import assert from 'node:assert';
|
|
5
|
-
import { describe, it } from 'node:test';
|
|
6
|
-
import { createIntelligencePromptWithContext } from '../prompts.js';
|
|
7
|
-
// ============================================================
|
|
8
|
-
// Context prompt
|
|
9
|
-
// ============================================================
|
|
10
|
-
void describe('createIntelligencePromptWithContext', () => {
|
|
11
|
-
const contextInfo = '# Context\nProduct: TestApp\n## Competitors\nNone';
|
|
12
|
-
void it('should include report type', () => {
|
|
13
|
-
const result = createIntelligencePromptWithContext('p1', contextInfo, 'competitive', true);
|
|
14
|
-
assert.ok(result.includes('competitive'));
|
|
15
|
-
});
|
|
16
|
-
void it('should include discovery instructions when needed', () => {
|
|
17
|
-
const result = createIntelligencePromptWithContext('p1', contextInfo, 'competitive', true);
|
|
18
|
-
assert.ok(result.includes('Competitor Discovery Required'));
|
|
19
|
-
});
|
|
20
|
-
void it('should use softer discovery language when competitors exist', () => {
|
|
21
|
-
const result = createIntelligencePromptWithContext('p1', contextInfo, 'competitive', false);
|
|
22
|
-
assert.ok(!result.includes('Competitor Discovery Required'));
|
|
23
|
-
assert.ok(result.includes('also look for new entrants'));
|
|
24
|
-
});
|
|
25
|
-
void it('should embed the context info', () => {
|
|
26
|
-
const result = createIntelligencePromptWithContext('p1', contextInfo, 'market', false);
|
|
27
|
-
assert.ok(result.includes('Product: TestApp'));
|
|
28
|
-
});
|
|
29
|
-
void it('should instruct to use web search', () => {
|
|
30
|
-
const result = createIntelligencePromptWithContext('p1', contextInfo, 'competitive', true);
|
|
31
|
-
assert.ok(result.includes('web search'));
|
|
32
|
-
});
|
|
33
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|