@actuate-media/cms-core 0.25.0 → 0.26.0

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.
Files changed (39) hide show
  1. package/dist/__tests__/api/stats-routes.test.d.ts +2 -0
  2. package/dist/__tests__/api/stats-routes.test.d.ts.map +1 -0
  3. package/dist/__tests__/api/stats-routes.test.js +251 -0
  4. package/dist/__tests__/api/stats-routes.test.js.map +1 -0
  5. package/dist/__tests__/auth/password.test.js +39 -12
  6. package/dist/__tests__/auth/password.test.js.map +1 -1
  7. package/dist/__tests__/content-health/scanner.test.d.ts +2 -0
  8. package/dist/__tests__/content-health/scanner.test.d.ts.map +1 -0
  9. package/dist/__tests__/content-health/scanner.test.js +151 -0
  10. package/dist/__tests__/content-health/scanner.test.js.map +1 -0
  11. package/dist/__tests__/diagnostics/api-metrics.test.d.ts +2 -0
  12. package/dist/__tests__/diagnostics/api-metrics.test.d.ts.map +1 -0
  13. package/dist/__tests__/diagnostics/api-metrics.test.js +153 -0
  14. package/dist/__tests__/diagnostics/api-metrics.test.js.map +1 -0
  15. package/dist/api/handler-factory.d.ts.map +1 -1
  16. package/dist/api/handler-factory.js +31 -1
  17. package/dist/api/handler-factory.js.map +1 -1
  18. package/dist/api/handlers.d.ts.map +1 -1
  19. package/dist/api/handlers.js +263 -0
  20. package/dist/api/handlers.js.map +1 -1
  21. package/dist/auth/password.d.ts +11 -0
  22. package/dist/auth/password.d.ts.map +1 -1
  23. package/dist/auth/password.js +13 -0
  24. package/dist/auth/password.js.map +1 -1
  25. package/dist/content-health/cron.d.ts +67 -0
  26. package/dist/content-health/cron.d.ts.map +1 -0
  27. package/dist/content-health/cron.js +167 -0
  28. package/dist/content-health/cron.js.map +1 -0
  29. package/dist/content-health/scanner.d.ts +118 -0
  30. package/dist/content-health/scanner.d.ts.map +1 -0
  31. package/dist/content-health/scanner.js +263 -0
  32. package/dist/content-health/scanner.js.map +1 -0
  33. package/dist/diagnostics/api-metrics.d.ts +135 -0
  34. package/dist/diagnostics/api-metrics.d.ts.map +1 -0
  35. package/dist/diagnostics/api-metrics.js +374 -0
  36. package/dist/diagnostics/api-metrics.js.map +1 -0
  37. package/package.json +1 -1
  38. package/prisma/migrations/0007_dashboard_metrics/migration.sql +74 -0
  39. package/prisma/schema.prisma +180 -73
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stats-routes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats-routes.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/api/stats-routes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,251 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
2
+ import { handleActuateAPI } from '../../api/index.js';
3
+ import { createSession } from '../../auth/session.js';
4
+ import { initDB } from '../../db.js';
5
+ import { generateToken as generateCsrfToken } from '../../security/csrf.js';
6
+ /**
7
+ * Integration tests for the dashboard stats endpoints introduced for
8
+ * the "Delivery API" and "Content Health" cards on the dashboard.
9
+ *
10
+ * These tests lock down the JSON response shape the dashboard depends
11
+ * on so a future refactor can't silently regress the client. They use
12
+ * the same mock-DB pattern as `notifications-routes.test.ts`.
13
+ */
14
+ const SECRET = 'test-secret-for-stats-routes-aaaaaaaaaaaaaaaaaa';
15
+ function createMockDB(args = {}) {
16
+ const metrics = args.metrics ?? [];
17
+ const issues = args.issues ?? [];
18
+ return {
19
+ session: { findUnique: async () => ({ revokedAt: null }) },
20
+ user: {},
21
+ apiRequestMetric: {
22
+ async findMany({ where, select: _select, }) {
23
+ return metrics.filter((m) => {
24
+ if (m.bucketStart < where.bucketStart.gte)
25
+ return false;
26
+ if (where.bucketStart.lt && m.bucketStart >= where.bucketStart.lt)
27
+ return false;
28
+ return true;
29
+ });
30
+ },
31
+ },
32
+ webhookEndpoint: {
33
+ async count({ where } = {}) {
34
+ if (where?.active === true)
35
+ return 2;
36
+ return 3;
37
+ },
38
+ },
39
+ contentIssue: {
40
+ async groupBy({ by, _sum }) {
41
+ void by;
42
+ void _sum;
43
+ const grouped = new Map();
44
+ for (const i of issues)
45
+ grouped.set(i.type, (grouped.get(i.type) ?? 0) + i.count);
46
+ return Array.from(grouped, ([type, count]) => ({ type, _sum: { count } }));
47
+ },
48
+ async findFirst({ orderBy: _orderBy, select: _select }) {
49
+ if (issues.length === 0)
50
+ return null;
51
+ const latest = issues.reduce((a, b) => (a.lastSeenAt > b.lastSeenAt ? a : b));
52
+ return { lastSeenAt: latest.lastSeenAt };
53
+ },
54
+ },
55
+ };
56
+ }
57
+ async function sessionHeaders(userId = 'user-1') {
58
+ const token = await createSession({ userId, role: 'ADMIN', sessionId: `session-${userId}` }, { secret: SECRET });
59
+ const csrf = await generateCsrfToken();
60
+ return {
61
+ cookie: `actuate_session=${token}; actuate_csrf=${csrf}`,
62
+ 'x-csrf-token': csrf,
63
+ 'content-type': 'application/json',
64
+ };
65
+ }
66
+ describe('GET /api/cms/stats/api-delivery', () => {
67
+ const originalSecret = process.env.CMS_SECRET;
68
+ beforeEach(() => {
69
+ process.env.CMS_SECRET = SECRET;
70
+ });
71
+ afterEach(() => {
72
+ if (originalSecret === undefined)
73
+ delete process.env.CMS_SECRET;
74
+ else
75
+ process.env.CMS_SECRET = originalSecret;
76
+ });
77
+ it('rejects unauthenticated requests with 401', async () => {
78
+ const db = createMockDB();
79
+ initDB(db);
80
+ const handler = handleActuateAPI({ prismaClient: db });
81
+ const res = await handler(new Request('https://example.com/api/cms/stats/api-delivery'));
82
+ expect(res.status).toBe(401);
83
+ });
84
+ it('returns the empty payload (hasData=false) when no metrics exist', async () => {
85
+ const db = createMockDB();
86
+ initDB(db);
87
+ const handler = handleActuateAPI({ prismaClient: db });
88
+ const headers = await sessionHeaders();
89
+ const res = await handler(new Request('https://example.com/api/cms/stats/api-delivery', {
90
+ headers: { cookie: headers.cookie },
91
+ }));
92
+ expect(res.status).toBe(200);
93
+ const body = (await res.json());
94
+ expect(body.data).toMatchObject({
95
+ hasData: false,
96
+ requests24h: 0,
97
+ requestsPrev24h: 0,
98
+ deltaPercent: null,
99
+ errorRate: 0,
100
+ avgLatencyMs: 0,
101
+ p95LatencyMs: 0,
102
+ });
103
+ // Webhook counters still come from the mocked WebhookEndpoint table.
104
+ expect(body.data.webhookCount).toBe(3);
105
+ expect(body.data.webhookActiveCount).toBe(2);
106
+ });
107
+ it('aggregates 24h request volume, error rate, and avg latency', async () => {
108
+ // Two buckets:
109
+ // - 100 2xx requests, sumLatency 5000 (avg 50ms)
110
+ // - 10 5xx requests, sumLatency 1000 (avg 100ms)
111
+ // Total: 110 requests, 10 errors → 9.09% error rate. Avg latency
112
+ // = 6000 / 110 ≈ 54.5ms.
113
+ const now = new Date();
114
+ const bucketTime = new Date(now.getTime() - 60_000);
115
+ const hist2xx = new Array(12).fill(0);
116
+ hist2xx[6] = 100; // 32-64ms bucket
117
+ const hist5xx = new Array(12).fill(0);
118
+ hist5xx[7] = 10; // 64-128ms bucket
119
+ const db = createMockDB({
120
+ metrics: [
121
+ {
122
+ statusBucket: '2xx',
123
+ count: 100,
124
+ sumLatencyMs: 5000,
125
+ maxLatencyMs: 60,
126
+ latencyHistogram: hist2xx,
127
+ bucketStart: bucketTime,
128
+ },
129
+ {
130
+ statusBucket: '5xx',
131
+ count: 10,
132
+ sumLatencyMs: 1000,
133
+ maxLatencyMs: 110,
134
+ latencyHistogram: hist5xx,
135
+ bucketStart: bucketTime,
136
+ },
137
+ ],
138
+ });
139
+ initDB(db);
140
+ const handler = handleActuateAPI({ prismaClient: db });
141
+ const headers = await sessionHeaders();
142
+ const res = await handler(new Request('https://example.com/api/cms/stats/api-delivery', {
143
+ headers: { cookie: headers.cookie },
144
+ }));
145
+ expect(res.status).toBe(200);
146
+ const body = (await res.json());
147
+ expect(body.data.hasData).toBe(true);
148
+ expect(body.data.requests24h).toBe(110);
149
+ expect(body.data.errorRate).toBeCloseTo(0.0909, 3);
150
+ expect(body.data.avgLatencyMs).toBeCloseTo(54.5, 1);
151
+ // p95 of 100×bucket6 + 10×bucket7 = watermark at 104.5; cumulative
152
+ // hits 110 in bucket 7 → upper bound 128.
153
+ expect(body.data.p95LatencyMs).toBe(128);
154
+ });
155
+ });
156
+ describe('GET /api/cms/stats/content-health', () => {
157
+ const originalSecret = process.env.CMS_SECRET;
158
+ beforeEach(() => {
159
+ process.env.CMS_SECRET = SECRET;
160
+ });
161
+ afterEach(() => {
162
+ if (originalSecret === undefined)
163
+ delete process.env.CMS_SECRET;
164
+ else
165
+ process.env.CMS_SECRET = originalSecret;
166
+ });
167
+ it('rejects unauthenticated requests with 401', async () => {
168
+ const db = createMockDB();
169
+ initDB(db);
170
+ const handler = handleActuateAPI({ prismaClient: db });
171
+ const res = await handler(new Request('https://example.com/api/cms/stats/content-health'));
172
+ expect(res.status).toBe(401);
173
+ });
174
+ it('returns a perfect score (100, "Good") and zero counts when no issues exist', async () => {
175
+ const db = createMockDB();
176
+ initDB(db);
177
+ const handler = handleActuateAPI({ prismaClient: db });
178
+ const headers = await sessionHeaders();
179
+ const res = await handler(new Request('https://example.com/api/cms/stats/content-health', {
180
+ headers: { cookie: headers.cookie },
181
+ }));
182
+ expect(res.status).toBe(200);
183
+ const body = (await res.json());
184
+ expect(body.data.score).toBe(100);
185
+ expect(body.data.label).toBe('Good');
186
+ expect(body.data.totalIssues).toBe(0);
187
+ expect(body.data.lastScanAt).toBeNull();
188
+ expect(body.data.counts).toEqual({
189
+ MISSING_META_DESCRIPTION: 0,
190
+ MISSING_ALT_TEXT: 0,
191
+ BROKEN_INTERNAL_LINK: 0,
192
+ OUTDATED_CONTENT: 0,
193
+ });
194
+ });
195
+ it('aggregates counts and computes a penalty-weighted score', async () => {
196
+ // 5 missing meta (5×5=25 penalty)
197
+ // 12 missing alt (12×2=24 penalty)
198
+ // 2 broken links (2×10=20 penalty)
199
+ // 8 outdated (8×3=24 penalty)
200
+ // → score = 100 - 93 = 7
201
+ const db = createMockDB({
202
+ issues: [
203
+ {
204
+ type: 'MISSING_META_DESCRIPTION',
205
+ count: 5,
206
+ lastSeenAt: new Date('2026-05-28T00:00:00Z'),
207
+ },
208
+ { type: 'MISSING_ALT_TEXT', count: 12, lastSeenAt: new Date('2026-05-28T01:00:00Z') },
209
+ { type: 'BROKEN_INTERNAL_LINK', count: 2, lastSeenAt: new Date('2026-05-28T02:00:00Z') },
210
+ { type: 'OUTDATED_CONTENT', count: 8, lastSeenAt: new Date('2026-05-28T03:00:00Z') },
211
+ ],
212
+ });
213
+ initDB(db);
214
+ const handler = handleActuateAPI({ prismaClient: db });
215
+ const headers = await sessionHeaders();
216
+ const res = await handler(new Request('https://example.com/api/cms/stats/content-health', {
217
+ headers: { cookie: headers.cookie },
218
+ }));
219
+ expect(res.status).toBe(200);
220
+ const body = (await res.json());
221
+ expect(body.data.totalIssues).toBe(27);
222
+ expect(body.data.score).toBe(7);
223
+ expect(body.data.label).toBe('Poor');
224
+ expect(body.data.counts.MISSING_META_DESCRIPTION).toBe(5);
225
+ expect(body.data.counts.MISSING_ALT_TEXT).toBe(12);
226
+ expect(body.data.counts.BROKEN_INTERNAL_LINK).toBe(2);
227
+ expect(body.data.counts.OUTDATED_CONTENT).toBe(8);
228
+ expect(body.data.lastScanAt).toBe('2026-05-28T03:00:00.000Z');
229
+ });
230
+ it('floors the score at 0 when penalties exceed 100', async () => {
231
+ const db = createMockDB({
232
+ issues: [
233
+ {
234
+ type: 'BROKEN_INTERNAL_LINK',
235
+ count: 50, // 500 penalty
236
+ lastSeenAt: new Date(),
237
+ },
238
+ ],
239
+ });
240
+ initDB(db);
241
+ const handler = handleActuateAPI({ prismaClient: db });
242
+ const headers = await sessionHeaders();
243
+ const res = await handler(new Request('https://example.com/api/cms/stats/content-health', {
244
+ headers: { cookie: headers.cookie },
245
+ }));
246
+ const body = (await res.json());
247
+ expect(body.data.score).toBe(0);
248
+ expect(body.data.label).toBe('Poor');
249
+ });
250
+ });
251
+ //# sourceMappingURL=stats-routes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats-routes.test.js","sourceRoot":"","sources":["../../../src/__tests__/api/stats-routes.test.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { hashPassword, verifyPassword, validatePasswordPolicy, needsRehash, compareToDummyHash, PBKDF2_ITERATIONS, } from '../../auth/password.js';
2
+ import { hashPassword, verifyPassword, validatePasswordPolicy, needsRehash, compareToDummyHash, _waitForDummyHashReady, PBKDF2_ITERATIONS, } from '../../auth/password.js';
3
3
  describe('hashPassword', () => {
4
4
  it(`returns a string in format "pbkdf2:${PBKDF2_ITERATIONS}:salt:hash"`, async () => {
5
5
  const hash = await hashPassword('MySecret123!');
@@ -97,23 +97,50 @@ describe('compareToDummyHash', () => {
97
97
  // user-enumeration timing channel the dummy hash exists to close. The
98
98
  // fix precomputes the hash via a top-level Promise — by the time the
99
99
  // first user request arrives, the work is either done or already
100
- // in-flight. We can't directly assert "module load started the hash",
101
- // but we can verify that two back-to-back calls have the same order of
102
- // magnitude of cost (i.e. the first isn't ~2× the second).
103
- it('first call is not measurably slower than subsequent calls (eager init)', async () => {
104
- // Warm up actual first invocation in the test process.
100
+ // in-flight.
101
+ //
102
+ // Two warmups needed to measure verify-only cost on CI:
103
+ // 1. `_waitForDummyHashReady()` wait for the eager hash precompute
104
+ // so the first measured call isn't paying that extra ~150ms.
105
+ // 2. Throwaway `compareToDummyHash('worker-warmup')` — warm Node's
106
+ // libuv worker pool used by `crypto.pbkdf2`. The first PBKDF2
107
+ // call across the entire process pays a ~100-150ms cold-start
108
+ // to spawn the worker thread + initialise the C++ binding
109
+ // context; subsequent calls reuse it. Without this warmup, the
110
+ // test failed on `main` (run 26599207053) with e1=291ms vs
111
+ // e2=150ms — same ~2× ratio as the historical lazy-init bug it
112
+ // was meant to catch, but caused by worker-pool warmup rather
113
+ // than a regression in the dummy-hash path.
114
+ //
115
+ // After both warmups, e1 and e2 measure the *same* verifyPassword
116
+ // path. Reverting PR #40 (re-introducing lazy init) would make e1
117
+ // also include a fresh hashPassword call (~150ms) — still ~2× e2 —
118
+ // and the bound would catch it.
119
+ it('first measured call has parity with subsequent calls after eager init resolves', async () => {
120
+ await _waitForDummyHashReady();
121
+ // Throwaway: warm Node's libuv crypto worker pool (see comment above).
122
+ await compareToDummyHash('worker-warmup');
105
123
  const t1 = performance.now();
106
- await compareToDummyHash('warmup');
124
+ await compareToDummyHash('first');
107
125
  const e1 = performance.now() - t1;
108
126
  const t2 = performance.now();
109
- await compareToDummyHash('subsequent');
127
+ await compareToDummyHash('second');
110
128
  const e2 = performance.now() - t2;
111
- // The first call should NOT be more than 1.6× the second. Without
112
- // eager init it was ~2× because it ran hashPassword (600k iter) +
113
- // verifyPassword (600k iter); after eager init it's just verifyPassword.
114
- // We use a generous bound to avoid flakes from CI scheduler jitter.
129
+ // Both calls run only verifyPassword on a warm worker pool. The
130
+ // tolerance (1.6× + 50ms) absorbs GC pauses and scheduler quanta;
131
+ // without eager init the ratio is ~2× consistently because the
132
+ // first call would also pay for hashPassword.
115
133
  expect(e1).toBeLessThan(e2 * 1.6 + 50);
116
134
  });
135
+ it('exposes the eager-init promise for direct verification', async () => {
136
+ // Module-load contract: `_waitForDummyHashReady()` MUST return a
137
+ // promise that resolves with no work pending on the consumer side.
138
+ // If a future refactor accidentally drops the top-level invocation
139
+ // and switches back to lazy init, this test catches it because the
140
+ // promise either won't exist or won't resolve without a triggering
141
+ // call.
142
+ await expect(_waitForDummyHashReady()).resolves.toBeUndefined();
143
+ });
117
144
  });
118
145
  describe('validatePasswordPolicy', () => {
119
146
  it('passes when password meets all requirements', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"password.test.js","sourceRoot":"","sources":["../../../src/__tests__/auth/password.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"password.test.js","sourceRoot":"","sources":["../../../src/__tests__/auth/password.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scanner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/content-health/scanner.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,151 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { classifyLink, countMissingAltImages, extractLinks, scanDocument, } from '../../content-health/scanner.js';
3
+ const DAY = 24 * 60 * 60 * 1000;
4
+ function fixture(overrides = {}) {
5
+ return {
6
+ id: 'doc-1',
7
+ data: {
8
+ metaDescription: 'A perfectly fine meta description.',
9
+ body: '<h1>Title</h1><p>Body text.</p><img src="a.jpg" alt="A">',
10
+ ...overrides.data,
11
+ },
12
+ updatedAt: new Date(Date.now() - 7 * DAY),
13
+ publishedAt: new Date(Date.now() - 7 * DAY),
14
+ ...overrides,
15
+ };
16
+ }
17
+ describe('countMissingAltImages', () => {
18
+ it('returns 0 when every <img> has an alt attribute', () => {
19
+ const html = '<img src="a.jpg" alt="A"><img src="b.jpg" alt=""><img src="c.jpg" alt="C">';
20
+ expect(countMissingAltImages(html)).toBe(0);
21
+ });
22
+ it('counts <img> tags missing alt regardless of attribute order', () => {
23
+ const html = '<img src="a.jpg"><img alt="ok" src="b.jpg"><IMG SRC="c.jpg">';
24
+ expect(countMissingAltImages(html)).toBe(2);
25
+ });
26
+ it('does not falsely match `alt` substrings in other attributes', () => {
27
+ // The naive regex must not be fooled by `data-default-alt="..."`.
28
+ const html = '<img src="x.jpg" data-default-alt="hi">';
29
+ expect(countMissingAltImages(html)).toBe(1);
30
+ });
31
+ it('handles empty / non-HTML input gracefully', () => {
32
+ expect(countMissingAltImages('')).toBe(0);
33
+ expect(countMissingAltImages('no html here')).toBe(0);
34
+ });
35
+ });
36
+ describe('extractLinks', () => {
37
+ it('extracts href values across quote styles', () => {
38
+ const html = `<a href="/foo">x</a><a href='/bar'>y</a><a class="x" href="/baz">z</a>`;
39
+ expect(extractLinks(html).sort()).toEqual(['/bar', '/baz', '/foo']);
40
+ });
41
+ it('ignores anchors without href', () => {
42
+ const html = `<a>no href</a><a href="/foo">x</a>`;
43
+ expect(extractLinks(html)).toEqual(['/foo']);
44
+ });
45
+ });
46
+ describe('classifyLink', () => {
47
+ const origin = 'https://example.com';
48
+ it('treats relative paths as internal', () => {
49
+ expect(classifyLink('/about', origin)).toEqual({
50
+ isInternal: true,
51
+ resolved: 'https://example.com/about',
52
+ });
53
+ expect(classifyLink('./relative', origin).isInternal).toBe(true);
54
+ });
55
+ it('treats same-origin absolute URLs as internal', () => {
56
+ expect(classifyLink('https://example.com/page', origin).isInternal).toBe(true);
57
+ });
58
+ it('classifies cross-origin URLs as external', () => {
59
+ expect(classifyLink('https://other.com/x', origin).isInternal).toBe(false);
60
+ });
61
+ it('rejects non-http schemes and hash-only anchors', () => {
62
+ expect(classifyLink('mailto:a@b.com', origin).resolved).toBeNull();
63
+ expect(classifyLink('tel:1234', origin).resolved).toBeNull();
64
+ expect(classifyLink('javascript:alert(1)', origin).resolved).toBeNull();
65
+ expect(classifyLink('#section', origin).resolved).toBeNull();
66
+ expect(classifyLink('', origin).resolved).toBeNull();
67
+ });
68
+ it('returns nulls when siteOrigin is malformed', () => {
69
+ expect(classifyLink('/about', 'not-a-url').resolved).toBeNull();
70
+ });
71
+ });
72
+ describe('scanDocument', () => {
73
+ it('produces no issues for a healthy document', async () => {
74
+ const issues = await scanDocument(fixture(), { checkLink: null });
75
+ expect(issues).toEqual([]);
76
+ });
77
+ it('flags missing meta description', async () => {
78
+ const doc = fixture();
79
+ doc.data = { ...doc.data, metaDescription: undefined, seoDescription: undefined };
80
+ const issues = await scanDocument(doc, { checkLink: null });
81
+ expect(issues.map((i) => i.type)).toContain('MISSING_META_DESCRIPTION');
82
+ });
83
+ it('reads meta description from a nested `seo` object', async () => {
84
+ const doc = fixture();
85
+ doc.data = { body: doc.data.body, seo: { description: 'nested ok' } };
86
+ const issues = await scanDocument(doc, { checkLink: null });
87
+ expect(issues.map((i) => i.type)).not.toContain('MISSING_META_DESCRIPTION');
88
+ });
89
+ it('flags missing alt text with the per-document count', async () => {
90
+ const doc = fixture();
91
+ doc.data = {
92
+ metaDescription: 'ok',
93
+ body: '<img src="a.jpg"><img src="b.jpg"><img alt="ok" src="c.jpg">',
94
+ };
95
+ const issues = await scanDocument(doc, { checkLink: null });
96
+ const altIssue = issues.find((i) => i.type === 'MISSING_ALT_TEXT');
97
+ expect(altIssue?.count).toBe(2);
98
+ });
99
+ it('flags outdated content beyond the configured threshold', async () => {
100
+ const doc = fixture({
101
+ updatedAt: new Date(Date.now() - 200 * DAY),
102
+ publishedAt: new Date(Date.now() - 200 * DAY),
103
+ });
104
+ const issues = await scanDocument(doc, { checkLink: null });
105
+ const outdated = issues.find((i) => i.type === 'OUTDATED_CONTENT');
106
+ expect(outdated).toBeDefined();
107
+ expect(outdated?.details?.ageDays).toBeGreaterThan(180);
108
+ });
109
+ it('does NOT flag outdated content when published within the threshold', async () => {
110
+ const doc = fixture({
111
+ updatedAt: new Date(Date.now() - 10 * DAY),
112
+ publishedAt: new Date(Date.now() - 10 * DAY),
113
+ });
114
+ const issues = await scanDocument(doc, { checkLink: null });
115
+ expect(issues.find((i) => i.type === 'OUTDATED_CONTENT')).toBeUndefined();
116
+ });
117
+ it('flags broken internal links via the injected checker', async () => {
118
+ const doc = fixture();
119
+ doc.data = {
120
+ metaDescription: 'ok',
121
+ body: `<a href="/good">a</a><a href="/bad">b</a><a href="https://external.com/x">c</a>`,
122
+ };
123
+ const checkLink = vi.fn(async (url) => !url.endsWith('/bad'));
124
+ const issues = await scanDocument(doc, {
125
+ checkLink,
126
+ siteOrigin: 'https://example.com',
127
+ });
128
+ const broken = issues.find((i) => i.type === 'BROKEN_INTERNAL_LINK');
129
+ expect(broken?.count).toBe(1);
130
+ expect(broken?.details?.urls).toEqual(['https://example.com/bad']);
131
+ // External link must NOT be probed (cross-origin)
132
+ expect(checkLink).not.toHaveBeenCalledWith('https://external.com/x');
133
+ });
134
+ it('skips link checking when no checker or origin is supplied', async () => {
135
+ const doc = fixture();
136
+ doc.data = { metaDescription: 'ok', body: '<a href="/whatever">x</a>' };
137
+ const checker = vi.fn(async () => true);
138
+ await scanDocument(doc, { checkLink: checker, siteOrigin: null });
139
+ expect(checker).not.toHaveBeenCalled();
140
+ });
141
+ it('falls back to publishedAt when computing freshness, but updatedAt otherwise', async () => {
142
+ // updatedAt recent, publishedAt very old → outdated by publishedAt rule.
143
+ const doc = fixture({
144
+ updatedAt: new Date(Date.now() - 1 * DAY),
145
+ publishedAt: new Date(Date.now() - 365 * DAY),
146
+ });
147
+ const issues = await scanDocument(doc, { checkLink: null });
148
+ expect(issues.find((i) => i.type === 'OUTDATED_CONTENT')).toBeDefined();
149
+ });
150
+ });
151
+ //# sourceMappingURL=scanner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.test.js","sourceRoot":"","sources":["../../../src/__tests__/content-health/scanner.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=api-metrics.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-metrics.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/diagnostics/api-metrics.test.ts"],"names":[],"mappings":""}