@ucptools/validator 1.0.0 → 1.0.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.
Files changed (236) hide show
  1. package/.claude/settings.local.json +60 -0
  2. package/.vercel/README.txt +11 -0
  3. package/.vercel/project.json +1 -0
  4. package/dist/cli/index.d.ts +6 -0
  5. package/dist/cli/index.d.ts.map +1 -0
  6. package/dist/cli/index.js +279 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/compliance/compliance-generator.d.ts +34 -0
  9. package/dist/compliance/compliance-generator.d.ts.map +1 -0
  10. package/dist/compliance/compliance-generator.js +320 -0
  11. package/dist/compliance/compliance-generator.js.map +1 -0
  12. package/dist/compliance/index.d.ts +8 -0
  13. package/dist/compliance/index.d.ts.map +1 -0
  14. package/dist/compliance/index.js +17 -0
  15. package/dist/compliance/index.js.map +1 -0
  16. package/dist/compliance/templates.d.ts +34 -0
  17. package/dist/compliance/templates.d.ts.map +1 -0
  18. package/{src/compliance/templates.ts → dist/compliance/templates.js} +117 -155
  19. package/dist/compliance/templates.js.map +1 -0
  20. package/dist/compliance/types.d.ts +64 -0
  21. package/dist/compliance/types.d.ts.map +1 -0
  22. package/dist/compliance/types.js +64 -0
  23. package/dist/compliance/types.js.map +1 -0
  24. package/dist/db/index.d.ts +11 -0
  25. package/dist/db/index.d.ts.map +1 -0
  26. package/dist/db/index.js +63 -0
  27. package/dist/db/index.js.map +1 -0
  28. package/dist/db/schema.d.ts +444 -0
  29. package/dist/db/schema.d.ts.map +1 -0
  30. package/dist/db/schema.js +65 -0
  31. package/dist/db/schema.js.map +1 -0
  32. package/dist/feed-analyzer/feed-analyzer.d.ts +26 -0
  33. package/dist/feed-analyzer/feed-analyzer.d.ts.map +1 -0
  34. package/{src/feed-analyzer/feed-analyzer.ts → dist/feed-analyzer/feed-analyzer.js} +642 -726
  35. package/dist/feed-analyzer/feed-analyzer.js.map +1 -0
  36. package/dist/feed-analyzer/index.d.ts +8 -0
  37. package/dist/feed-analyzer/index.d.ts.map +1 -0
  38. package/dist/feed-analyzer/index.js +19 -0
  39. package/dist/feed-analyzer/index.js.map +1 -0
  40. package/dist/feed-analyzer/types.d.ts +204 -0
  41. package/dist/feed-analyzer/types.d.ts.map +1 -0
  42. package/dist/feed-analyzer/types.js +162 -0
  43. package/dist/feed-analyzer/types.js.map +1 -0
  44. package/{src/generator/index.ts → dist/generator/index.d.ts} +1 -1
  45. package/dist/generator/index.d.ts.map +1 -0
  46. package/dist/generator/index.js +13 -0
  47. package/dist/generator/index.js.map +1 -0
  48. package/dist/generator/key-generator.d.ts +24 -0
  49. package/dist/generator/key-generator.d.ts.map +1 -0
  50. package/dist/generator/key-generator.js +144 -0
  51. package/dist/generator/key-generator.js.map +1 -0
  52. package/dist/generator/profile-builder.d.ts +15 -0
  53. package/dist/generator/profile-builder.d.ts.map +1 -0
  54. package/dist/generator/profile-builder.js +338 -0
  55. package/dist/generator/profile-builder.js.map +1 -0
  56. package/dist/hosting/artifacts-generator.d.ts +10 -0
  57. package/dist/hosting/artifacts-generator.d.ts.map +1 -0
  58. package/{src/hosting/artifacts-generator.ts → dist/hosting/artifacts-generator.js} +191 -241
  59. package/dist/hosting/artifacts-generator.js.map +1 -0
  60. package/{src/hosting/index.ts → dist/hosting/index.d.ts} +1 -1
  61. package/dist/hosting/index.d.ts.map +1 -0
  62. package/dist/hosting/index.js +10 -0
  63. package/dist/hosting/index.js.map +1 -0
  64. package/dist/index.d.ts +18 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +78 -0
  67. package/dist/index.js.map +1 -0
  68. package/{src/security/index.ts → dist/security/index.d.ts} +8 -15
  69. package/dist/security/index.d.ts.map +1 -0
  70. package/dist/security/index.js +12 -0
  71. package/dist/security/index.js.map +1 -0
  72. package/dist/security/security-scanner.d.ts +10 -0
  73. package/dist/security/security-scanner.d.ts.map +1 -0
  74. package/dist/security/security-scanner.js +541 -0
  75. package/dist/security/security-scanner.js.map +1 -0
  76. package/dist/security/types.d.ts +48 -0
  77. package/dist/security/types.d.ts.map +1 -0
  78. package/dist/security/types.js +21 -0
  79. package/dist/security/types.js.map +1 -0
  80. package/dist/services/directory.d.ts +104 -0
  81. package/dist/services/directory.d.ts.map +1 -0
  82. package/dist/services/directory.js +333 -0
  83. package/dist/services/directory.js.map +1 -0
  84. package/dist/simulator/agent-simulator.d.ts +69 -0
  85. package/dist/simulator/agent-simulator.d.ts.map +1 -0
  86. package/{src/simulator/agent-simulator.ts → dist/simulator/agent-simulator.js} +650 -941
  87. package/dist/simulator/agent-simulator.js.map +1 -0
  88. package/{src/simulator/index.ts → dist/simulator/index.d.ts} +7 -7
  89. package/dist/simulator/index.d.ts.map +1 -0
  90. package/dist/simulator/index.js +23 -0
  91. package/dist/simulator/index.js.map +1 -0
  92. package/{src/simulator/types.ts → dist/simulator/types.d.ts} +145 -170
  93. package/dist/simulator/types.d.ts.map +1 -0
  94. package/dist/simulator/types.js +18 -0
  95. package/dist/simulator/types.js.map +1 -0
  96. package/dist/types/generator.d.ts +106 -0
  97. package/dist/types/generator.d.ts.map +1 -0
  98. package/dist/types/generator.js +6 -0
  99. package/dist/types/generator.js.map +1 -0
  100. package/{src/types/index.ts → dist/types/index.d.ts} +1 -1
  101. package/dist/types/index.d.ts.map +1 -0
  102. package/dist/types/index.js +23 -0
  103. package/dist/types/index.js.map +1 -0
  104. package/dist/types/ucp-profile.d.ts +103 -0
  105. package/dist/types/ucp-profile.d.ts.map +1 -0
  106. package/dist/types/ucp-profile.js +45 -0
  107. package/dist/types/ucp-profile.js.map +1 -0
  108. package/dist/types/validation.d.ts +68 -0
  109. package/dist/types/validation.d.ts.map +1 -0
  110. package/dist/types/validation.js +32 -0
  111. package/dist/types/validation.js.map +1 -0
  112. package/dist/validator/index.d.ts +26 -0
  113. package/dist/validator/index.d.ts.map +1 -0
  114. package/dist/validator/index.js +161 -0
  115. package/dist/validator/index.js.map +1 -0
  116. package/dist/validator/network-validator.d.ts +28 -0
  117. package/dist/validator/network-validator.d.ts.map +1 -0
  118. package/dist/validator/network-validator.js +319 -0
  119. package/dist/validator/network-validator.js.map +1 -0
  120. package/dist/validator/rules-validator.d.ts +11 -0
  121. package/dist/validator/rules-validator.d.ts.map +1 -0
  122. package/dist/validator/rules-validator.js +257 -0
  123. package/dist/validator/rules-validator.js.map +1 -0
  124. package/dist/validator/sdk-validator.d.ts +58 -0
  125. package/dist/validator/sdk-validator.d.ts.map +1 -0
  126. package/{src/validator/sdk-validator.ts → dist/validator/sdk-validator.js} +273 -330
  127. package/dist/validator/sdk-validator.js.map +1 -0
  128. package/dist/validator/structural-validator.d.ts +11 -0
  129. package/dist/validator/structural-validator.d.ts.map +1 -0
  130. package/dist/validator/structural-validator.js +415 -0
  131. package/dist/validator/structural-validator.js.map +1 -0
  132. package/package.json +1 -1
  133. package/publish-output.txt +0 -0
  134. package/CLAUDE.md +0 -109
  135. package/api/analyze-feed.js +0 -140
  136. package/api/badge.js +0 -185
  137. package/api/benchmark.js +0 -177
  138. package/api/directory-stats.ts +0 -29
  139. package/api/directory.ts +0 -73
  140. package/api/generate-compliance.js +0 -143
  141. package/api/generate-schema.js +0 -457
  142. package/api/generate.js +0 -132
  143. package/api/security-scan.js +0 -133
  144. package/api/simulate.js +0 -187
  145. package/api/tsconfig.json +0 -10
  146. package/api/validate.js +0 -1351
  147. package/apify-actor/.actor/actor.json +0 -68
  148. package/apify-actor/.actor/input_schema.json +0 -32
  149. package/apify-actor/APIFY-STORE-LISTING.md +0 -412
  150. package/apify-actor/Dockerfile +0 -8
  151. package/apify-actor/README.md +0 -166
  152. package/apify-actor/main.ts +0 -111
  153. package/apify-actor/package.json +0 -17
  154. package/apify-actor/src/main.js +0 -199
  155. package/docs/BRAND-IDENTITY.md +0 -238
  156. package/docs/BRAND-STYLE-GUIDE.md +0 -356
  157. package/drizzle/0000_black_king_cobra.sql +0 -39
  158. package/drizzle/meta/0000_snapshot.json +0 -309
  159. package/drizzle/meta/_journal.json +0 -13
  160. package/drizzle.config.ts +0 -10
  161. package/public/.well-known/ucp +0 -25
  162. package/public/android-chrome-192x192.png +0 -0
  163. package/public/android-chrome-512x512.png +0 -0
  164. package/public/apple-touch-icon.png +0 -0
  165. package/public/brand.css +0 -321
  166. package/public/directory.html +0 -701
  167. package/public/favicon-16x16.png +0 -0
  168. package/public/favicon-32x32.png +0 -0
  169. package/public/favicon.ico +0 -0
  170. package/public/guides/bigcommerce.html +0 -743
  171. package/public/guides/fastucp.html +0 -838
  172. package/public/guides/magento.html +0 -779
  173. package/public/guides/shopify.html +0 -726
  174. package/public/guides/squarespace.html +0 -749
  175. package/public/guides/wix.html +0 -747
  176. package/public/guides/woocommerce.html +0 -733
  177. package/public/index.html +0 -3835
  178. package/public/learn.html +0 -396
  179. package/public/logo.jpeg +0 -0
  180. package/public/og-image-icon.png +0 -0
  181. package/public/og-image.png +0 -0
  182. package/public/robots.txt +0 -6
  183. package/public/site.webmanifest +0 -31
  184. package/public/sitemap.xml +0 -69
  185. package/public/social/linkedin-banner-1128x191.png +0 -0
  186. package/public/social/temp.PNG +0 -0
  187. package/public/social/x-header-1500x500.png +0 -0
  188. package/public/verify.html +0 -410
  189. package/scripts/generate-favicons.js +0 -44
  190. package/scripts/generate-ico.js +0 -23
  191. package/scripts/generate-og-image.js +0 -45
  192. package/scripts/reset-db.ts +0 -77
  193. package/scripts/seed-db.ts +0 -71
  194. package/scripts/setup-benchmark-db.js +0 -70
  195. package/src/api/server.ts +0 -266
  196. package/src/cli/index.ts +0 -302
  197. package/src/compliance/compliance-generator.ts +0 -452
  198. package/src/compliance/index.ts +0 -28
  199. package/src/compliance/types.ts +0 -170
  200. package/src/db/index.ts +0 -28
  201. package/src/db/schema.ts +0 -84
  202. package/src/feed-analyzer/index.ts +0 -34
  203. package/src/feed-analyzer/types.ts +0 -354
  204. package/src/generator/key-generator.ts +0 -124
  205. package/src/generator/profile-builder.ts +0 -402
  206. package/src/index.ts +0 -105
  207. package/src/security/security-scanner.ts +0 -604
  208. package/src/security/types.ts +0 -55
  209. package/src/services/directory.ts +0 -434
  210. package/src/types/generator.ts +0 -140
  211. package/src/types/ucp-profile.ts +0 -140
  212. package/src/types/validation.ts +0 -89
  213. package/src/validator/index.ts +0 -194
  214. package/src/validator/network-validator.ts +0 -417
  215. package/src/validator/rules-validator.ts +0 -297
  216. package/src/validator/structural-validator.ts +0 -476
  217. package/tests/fixtures/non-compliant-profile.json +0 -25
  218. package/tests/fixtures/official-sample-profile.json +0 -75
  219. package/tests/integration/benchmark.test.ts +0 -207
  220. package/tests/integration/database.test.ts +0 -163
  221. package/tests/integration/directory-api.test.ts +0 -268
  222. package/tests/integration/simulate-api.test.ts +0 -230
  223. package/tests/integration/validate-api.test.ts +0 -269
  224. package/tests/setup.ts +0 -15
  225. package/tests/unit/agent-simulator.test.ts +0 -575
  226. package/tests/unit/compliance-generator.test.ts +0 -374
  227. package/tests/unit/directory-service.test.ts +0 -272
  228. package/tests/unit/feed-analyzer.test.ts +0 -517
  229. package/tests/unit/lint-suggestions.test.ts +0 -423
  230. package/tests/unit/official-samples.test.ts +0 -211
  231. package/tests/unit/pdf-report.test.ts +0 -390
  232. package/tests/unit/sdk-validator.test.ts +0 -531
  233. package/tests/unit/security-scanner.test.ts +0 -410
  234. package/tests/unit/validation.test.ts +0 -390
  235. package/vercel.json +0 -34
  236. package/vitest.config.ts +0 -22
@@ -1,390 +0,0 @@
1
- /**
2
- * Unit Tests for PDF Report Generation (Issue #7)
3
- * Tests the data transformation and formatting logic for PDF reports
4
- */
5
-
6
- import { describe, it, expect } from 'vitest';
7
-
8
- // Types matching the validation API response
9
- interface ValidationData {
10
- domain?: string;
11
- ucp?: {
12
- found: boolean;
13
- issues: Array<{ code: string; message: string; severity: 'error' | 'warn' }>;
14
- };
15
- schema?: {
16
- found: boolean;
17
- issues: Array<{ code: string; message: string; severity: 'error' | 'warn'; category?: string }>;
18
- stats: {
19
- products: number;
20
- returnPolicies: number;
21
- organizations?: number;
22
- };
23
- };
24
- ai_readiness?: {
25
- score: number;
26
- grade: string;
27
- label: string;
28
- };
29
- benchmark?: {
30
- percentile: number;
31
- total_sites_analyzed: number;
32
- avg_score?: number;
33
- };
34
- product_quality?: {
35
- completeness: number;
36
- };
37
- lint_suggestions?: Array<{
38
- severity: string;
39
- title: string;
40
- code: string;
41
- impact: string;
42
- fix?: string;
43
- codeSnippet?: string;
44
- docLink?: string;
45
- }>;
46
- }
47
-
48
- // Helper functions that mirror the PDF generation logic
49
- function getGradeColor(grade: string): [number, number, number] {
50
- const gradeColors: Record<string, [number, number, number]> = {
51
- 'A': [22, 163, 74], // Green
52
- 'B': [37, 99, 235], // Blue
53
- 'C': [202, 138, 4], // Yellow
54
- 'D': [234, 88, 12], // Orange
55
- 'F': [220, 38, 38] // Red
56
- };
57
- return gradeColors[grade] || gradeColors['F'];
58
- }
59
-
60
- function countIssuesBySeverity(issues: Array<{ severity: string }>): { errors: number; warnings: number } {
61
- return {
62
- errors: issues.filter(i => i.severity === 'error').length,
63
- warnings: issues.filter(i => i.severity === 'warn').length
64
- };
65
- }
66
-
67
- function truncateText(text: string, maxLength: number): string {
68
- if (text.length <= maxLength) return text;
69
- return text.substring(0, maxLength) + '...';
70
- }
71
-
72
- function generateFilename(domain: string): string {
73
- return `ucp-report-${domain.replace(/\./g, '-')}.pdf`;
74
- }
75
-
76
- function extractReportData(data: ValidationData, domain: string) {
77
- return {
78
- domain,
79
- score: data.ai_readiness?.score ?? 0,
80
- grade: data.ai_readiness?.grade ?? 'F',
81
- readinessLabel: data.ai_readiness?.label ?? 'Not Ready',
82
- ucpFound: data.ucp?.found ?? false,
83
- ucpIssues: data.ucp?.issues ?? [],
84
- schemaStats: data.schema?.stats ?? { products: 0, returnPolicies: 0 },
85
- schemaIssues: data.schema?.issues ?? [],
86
- productQuality: data.product_quality?.completeness ?? null,
87
- benchmark: data.benchmark ?? null,
88
- suggestions: data.lint_suggestions ?? [],
89
- };
90
- }
91
-
92
- describe('PDF Report Generation (Issue #7)', () => {
93
- describe('Grade Color Mapping', () => {
94
- it('should return green for grade A', () => {
95
- const color = getGradeColor('A');
96
- expect(color).toEqual([22, 163, 74]);
97
- });
98
-
99
- it('should return blue for grade B', () => {
100
- const color = getGradeColor('B');
101
- expect(color).toEqual([37, 99, 235]);
102
- });
103
-
104
- it('should return yellow for grade C', () => {
105
- const color = getGradeColor('C');
106
- expect(color).toEqual([202, 138, 4]);
107
- });
108
-
109
- it('should return orange for grade D', () => {
110
- const color = getGradeColor('D');
111
- expect(color).toEqual([234, 88, 12]);
112
- });
113
-
114
- it('should return red for grade F', () => {
115
- const color = getGradeColor('F');
116
- expect(color).toEqual([220, 38, 38]);
117
- });
118
-
119
- it('should default to red for unknown grade', () => {
120
- const color = getGradeColor('X');
121
- expect(color).toEqual([220, 38, 38]);
122
- });
123
- });
124
-
125
- describe('Issue Counting', () => {
126
- it('should correctly count errors and warnings', () => {
127
- const issues = [
128
- { severity: 'error', code: 'ERR1', message: 'Error 1' },
129
- { severity: 'error', code: 'ERR2', message: 'Error 2' },
130
- { severity: 'warn', code: 'WARN1', message: 'Warning 1' },
131
- ];
132
- const counts = countIssuesBySeverity(issues);
133
-
134
- expect(counts.errors).toBe(2);
135
- expect(counts.warnings).toBe(1);
136
- });
137
-
138
- it('should return zeros for empty array', () => {
139
- const counts = countIssuesBySeverity([]);
140
-
141
- expect(counts.errors).toBe(0);
142
- expect(counts.warnings).toBe(0);
143
- });
144
-
145
- it('should handle only errors', () => {
146
- const issues = [
147
- { severity: 'error', code: 'ERR1', message: 'Error 1' },
148
- { severity: 'error', code: 'ERR2', message: 'Error 2' },
149
- ];
150
- const counts = countIssuesBySeverity(issues);
151
-
152
- expect(counts.errors).toBe(2);
153
- expect(counts.warnings).toBe(0);
154
- });
155
-
156
- it('should handle only warnings', () => {
157
- const issues = [
158
- { severity: 'warn', code: 'WARN1', message: 'Warning 1' },
159
- { severity: 'warn', code: 'WARN2', message: 'Warning 2' },
160
- ];
161
- const counts = countIssuesBySeverity(issues);
162
-
163
- expect(counts.errors).toBe(0);
164
- expect(counts.warnings).toBe(2);
165
- });
166
- });
167
-
168
- describe('Text Truncation', () => {
169
- it('should not truncate short text', () => {
170
- const result = truncateText('Short text', 70);
171
- expect(result).toBe('Short text');
172
- });
173
-
174
- it('should truncate long text with ellipsis', () => {
175
- const longText = 'This is a very long message that should be truncated because it exceeds the maximum allowed length for display';
176
- const result = truncateText(longText, 70);
177
-
178
- expect(result.length).toBe(73); // 70 + '...'
179
- expect(result.endsWith('...')).toBe(true);
180
- });
181
-
182
- it('should handle exact length text', () => {
183
- const text = 'A'.repeat(70);
184
- const result = truncateText(text, 70);
185
-
186
- expect(result.length).toBe(70);
187
- expect(result.endsWith('...')).toBe(false);
188
- });
189
- });
190
-
191
- describe('Filename Generation', () => {
192
- it('should replace dots with dashes in domain', () => {
193
- const filename = generateFilename('example.com');
194
- expect(filename).toBe('ucp-report-example-com.pdf');
195
- });
196
-
197
- it('should handle subdomains', () => {
198
- const filename = generateFilename('shop.example.com');
199
- expect(filename).toBe('ucp-report-shop-example-com.pdf');
200
- });
201
-
202
- it('should handle multiple dots', () => {
203
- const filename = generateFilename('www.shop.example.co.uk');
204
- expect(filename).toBe('ucp-report-www-shop-example-co-uk.pdf');
205
- });
206
- });
207
-
208
- describe('Report Data Extraction', () => {
209
- it('should extract all fields from complete data', () => {
210
- const data: ValidationData = {
211
- ai_readiness: { score: 85, grade: 'B', label: 'Partially Ready' },
212
- ucp: { found: true, issues: [{ code: 'TEST', message: 'Test', severity: 'error' }] },
213
- schema: {
214
- found: true,
215
- issues: [{ code: 'SCHEMA_TEST', message: 'Schema test', severity: 'warn' }],
216
- stats: { products: 10, returnPolicies: 2 }
217
- },
218
- product_quality: { completeness: 78 },
219
- benchmark: { percentile: 75, total_sites_analyzed: 1000 },
220
- lint_suggestions: [{ severity: 'critical', title: 'Test', code: 'TEST', impact: 'Test impact' }]
221
- };
222
-
223
- const result = extractReportData(data, 'example.com');
224
-
225
- expect(result.domain).toBe('example.com');
226
- expect(result.score).toBe(85);
227
- expect(result.grade).toBe('B');
228
- expect(result.readinessLabel).toBe('Partially Ready');
229
- expect(result.ucpFound).toBe(true);
230
- expect(result.ucpIssues).toHaveLength(1);
231
- expect(result.schemaStats.products).toBe(10);
232
- expect(result.schemaStats.returnPolicies).toBe(2);
233
- expect(result.schemaIssues).toHaveLength(1);
234
- expect(result.productQuality).toBe(78);
235
- expect(result.benchmark?.percentile).toBe(75);
236
- expect(result.suggestions).toHaveLength(1);
237
- });
238
-
239
- it('should provide defaults for missing data', () => {
240
- const data: ValidationData = {};
241
-
242
- const result = extractReportData(data, 'test.com');
243
-
244
- expect(result.domain).toBe('test.com');
245
- expect(result.score).toBe(0);
246
- expect(result.grade).toBe('F');
247
- expect(result.readinessLabel).toBe('Not Ready');
248
- expect(result.ucpFound).toBe(false);
249
- expect(result.ucpIssues).toEqual([]);
250
- expect(result.schemaStats).toEqual({ products: 0, returnPolicies: 0 });
251
- expect(result.schemaIssues).toEqual([]);
252
- expect(result.productQuality).toBeNull();
253
- expect(result.benchmark).toBeNull();
254
- expect(result.suggestions).toEqual([]);
255
- });
256
-
257
- it('should handle partial data', () => {
258
- const data: ValidationData = {
259
- ai_readiness: { score: 45, grade: 'F', label: 'Not Ready' },
260
- ucp: { found: false, issues: [] },
261
- };
262
-
263
- const result = extractReportData(data, 'partial.com');
264
-
265
- expect(result.score).toBe(45);
266
- expect(result.ucpFound).toBe(false);
267
- expect(result.schemaStats).toEqual({ products: 0, returnPolicies: 0 });
268
- });
269
- });
270
-
271
- describe('PDF Content Sections', () => {
272
- it('should limit displayed issues to prevent overflow', () => {
273
- const issues = Array.from({ length: 20 }, (_, i) => ({
274
- code: `ERR${i}`,
275
- message: `Error message ${i}`,
276
- severity: 'error' as const
277
- }));
278
-
279
- // PDF logic limits to 8 issues
280
- const displayedIssues = issues.slice(0, 8);
281
- expect(displayedIssues).toHaveLength(8);
282
- });
283
-
284
- it('should limit displayed suggestions to prevent overflow', () => {
285
- const suggestions = Array.from({ length: 10 }, (_, i) => ({
286
- severity: 'warning',
287
- title: `Suggestion ${i}`,
288
- code: `SUGG${i}`,
289
- impact: `Impact ${i}`
290
- }));
291
-
292
- // PDF logic limits to 5 suggestions
293
- const displayedSuggestions = suggestions.slice(0, 5);
294
- expect(displayedSuggestions).toHaveLength(5);
295
- });
296
- });
297
-
298
- describe('Validation Data Requirements', () => {
299
- it('should validate that data is available before generating', () => {
300
- const data = null;
301
- const domain = null;
302
-
303
- const isValid = data !== null && domain !== null;
304
- expect(isValid).toBe(false);
305
- });
306
-
307
- it('should accept valid data for PDF generation', () => {
308
- const data: ValidationData = {
309
- ai_readiness: { score: 70, grade: 'C', label: 'Partially Ready' }
310
- };
311
- const domain = 'test.com';
312
-
313
- const isValid = data !== null && domain !== null;
314
- expect(isValid).toBe(true);
315
- });
316
- });
317
-
318
- describe('Brand Colors', () => {
319
- it('should use correct brand blue', () => {
320
- const brandBlue: [number, number, number] = [46, 134, 171];
321
- expect(brandBlue).toEqual([46, 134, 171]);
322
- });
323
-
324
- it('should use correct brand teal', () => {
325
- const brandTeal: [number, number, number] = [54, 181, 162];
326
- expect(brandTeal).toEqual([54, 181, 162]);
327
- });
328
-
329
- it('should use correct severity colors', () => {
330
- const severityColors = {
331
- error: [220, 38, 38],
332
- warn: [202, 138, 4]
333
- };
334
-
335
- expect(severityColors.error).toEqual([220, 38, 38]);
336
- expect(severityColors.warn).toEqual([202, 138, 4]);
337
- });
338
- });
339
- });
340
-
341
- describe('PDF Report Integration Requirements', () => {
342
- describe('Data Storage', () => {
343
- it('should store validation data in expected format', () => {
344
- // Simulates window.lastValidationData structure
345
- const storedData: ValidationData = {
346
- ai_readiness: { score: 85, grade: 'B', label: 'Partially Ready' },
347
- ucp: { found: true, issues: [] },
348
- schema: { found: true, issues: [], stats: { products: 5, returnPolicies: 1 } },
349
- lint_suggestions: []
350
- };
351
-
352
- expect(storedData.ai_readiness).toBeDefined();
353
- expect(storedData.ucp).toBeDefined();
354
- expect(storedData.schema).toBeDefined();
355
- expect(storedData.lint_suggestions).toBeDefined();
356
- });
357
-
358
- it('should store domain for filename generation', () => {
359
- // Simulates window.lastValidatedDomain
360
- const storedDomain = 'example.com';
361
-
362
- expect(storedDomain).toBeDefined();
363
- expect(typeof storedDomain).toBe('string');
364
- expect(storedDomain.length).toBeGreaterThan(0);
365
- });
366
- });
367
-
368
- describe('Download Trigger', () => {
369
- it('should generate correct filename from domain', () => {
370
- const domain = 'shop.example.com';
371
- const filename = `ucp-report-${domain.replace(/\./g, '-')}.pdf`;
372
-
373
- expect(filename).toBe('ucp-report-shop-example-com.pdf');
374
- });
375
- });
376
-
377
- describe('Analytics Event', () => {
378
- it('should include required tracking fields', () => {
379
- const eventData = {
380
- domain: 'example.com',
381
- score: 85,
382
- grade: 'B'
383
- };
384
-
385
- expect(eventData).toHaveProperty('domain');
386
- expect(eventData).toHaveProperty('score');
387
- expect(eventData).toHaveProperty('grade');
388
- });
389
- });
390
- });