@supernal/interface 1.0.9 → 1.0.12

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 (155) hide show
  1. package/dist/cjs/src/background/navigation/NavigationGraph.js +48 -0
  2. package/dist/cjs/src/background/navigation/NavigationGraph.js.map +1 -1
  3. package/dist/cjs/src/browser.js +42 -1
  4. package/dist/cjs/src/browser.js.map +1 -1
  5. package/dist/cjs/src/decorators/ContainerHelpers.js +16 -1
  6. package/dist/cjs/src/decorators/ContainerHelpers.js.map +1 -1
  7. package/dist/cjs/src/decorators/Tool.js +2 -3
  8. package/dist/cjs/src/decorators/Tool.js.map +1 -1
  9. package/dist/cjs/src/testing/graph-tester/core/GraphTester.js +339 -0
  10. package/dist/cjs/src/testing/graph-tester/core/GraphTester.js.map +1 -0
  11. package/dist/cjs/src/testing/graph-tester/core/TestFunction.js +189 -0
  12. package/dist/cjs/src/testing/graph-tester/core/TestFunction.js.map +1 -0
  13. package/dist/cjs/src/testing/graph-tester/core/types.js +24 -0
  14. package/dist/cjs/src/testing/graph-tester/core/types.js.map +1 -0
  15. package/dist/cjs/src/testing/graph-tester/fixtures/index.js +13 -0
  16. package/dist/cjs/src/testing/graph-tester/fixtures/index.js.map +1 -0
  17. package/dist/cjs/src/testing/graph-tester/fixtures/portPool.js +184 -0
  18. package/dist/cjs/src/testing/graph-tester/fixtures/portPool.js.map +1 -0
  19. package/dist/cjs/src/testing/graph-tester/index.js +98 -0
  20. package/dist/cjs/src/testing/graph-tester/index.js.map +1 -0
  21. package/dist/cjs/src/testing/graph-tester/modes/AccessibilityMode.js +230 -0
  22. package/dist/cjs/src/testing/graph-tester/modes/AccessibilityMode.js.map +1 -0
  23. package/dist/cjs/src/testing/graph-tester/modes/PerformanceMode.js +168 -0
  24. package/dist/cjs/src/testing/graph-tester/modes/PerformanceMode.js.map +1 -0
  25. package/dist/cjs/src/testing/graph-tester/modes/SEOMode.js +264 -0
  26. package/dist/cjs/src/testing/graph-tester/modes/SEOMode.js.map +1 -0
  27. package/dist/cjs/src/testing/graph-tester/modes/VisualRegressionMode.js +199 -0
  28. package/dist/cjs/src/testing/graph-tester/modes/VisualRegressionMode.js.map +1 -0
  29. package/dist/cjs/src/testing/graph-tester/modes/index.js +17 -0
  30. package/dist/cjs/src/testing/graph-tester/modes/index.js.map +1 -0
  31. package/dist/cjs/src/testing/graph-tester/reporters/HTMLReporter.js +411 -0
  32. package/dist/cjs/src/testing/graph-tester/reporters/HTMLReporter.js.map +1 -0
  33. package/dist/cjs/src/testing/graph-tester/reporters/JSONReporter.js +127 -0
  34. package/dist/cjs/src/testing/graph-tester/reporters/JSONReporter.js.map +1 -0
  35. package/dist/cjs/src/testing/graph-tester/reporters/MarkdownReporter.js +169 -0
  36. package/dist/cjs/src/testing/graph-tester/reporters/MarkdownReporter.js.map +1 -0
  37. package/dist/cjs/src/testing/graph-tester/reporters/UnifiedReporter.js +118 -0
  38. package/dist/cjs/src/testing/graph-tester/reporters/UnifiedReporter.js.map +1 -0
  39. package/dist/cjs/src/testing/graph-tester/reporters/index.js +17 -0
  40. package/dist/cjs/src/testing/graph-tester/reporters/index.js.map +1 -0
  41. package/dist/cjs/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.js +47 -0
  42. package/dist/cjs/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.js.map +1 -0
  43. package/dist/cjs/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.js +584 -0
  44. package/dist/cjs/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.js.map +1 -0
  45. package/dist/cjs/src/testing/graph-tester/screenshot/ScreenshotAnnotator.js +376 -0
  46. package/dist/cjs/src/testing/graph-tester/screenshot/ScreenshotAnnotator.js.map +1 -0
  47. package/dist/cjs/src/testing/graph-tester/screenshot/index.js +15 -0
  48. package/dist/cjs/src/testing/graph-tester/screenshot/index.js.map +1 -0
  49. package/dist/cjs/src/testing/graph-tester/screenshot/types.js +11 -0
  50. package/dist/cjs/src/testing/graph-tester/screenshot/types.js.map +1 -0
  51. package/dist/cjs/src/testing/selectors.js +1 -1
  52. package/dist/esm/src/background/navigation/INavigationGraph.d.ts +15 -0
  53. package/dist/esm/src/background/navigation/INavigationGraph.d.ts.map +1 -1
  54. package/dist/esm/src/background/navigation/NavigationGraph.d.ts +32 -0
  55. package/dist/esm/src/background/navigation/NavigationGraph.d.ts.map +1 -1
  56. package/dist/esm/src/background/navigation/NavigationGraph.js +48 -0
  57. package/dist/esm/src/background/navigation/NavigationGraph.js.map +1 -1
  58. package/dist/esm/src/browser.d.ts +9 -0
  59. package/dist/esm/src/browser.d.ts.map +1 -1
  60. package/dist/esm/src/browser.js +14 -0
  61. package/dist/esm/src/browser.js.map +1 -1
  62. package/dist/esm/src/decorators/ContainerHelpers.d.ts +2 -1
  63. package/dist/esm/src/decorators/ContainerHelpers.d.ts.map +1 -1
  64. package/dist/esm/src/decorators/ContainerHelpers.js +16 -1
  65. package/dist/esm/src/decorators/ContainerHelpers.js.map +1 -1
  66. package/dist/esm/src/decorators/Tool.d.ts.map +1 -1
  67. package/dist/esm/src/decorators/Tool.js +2 -3
  68. package/dist/esm/src/decorators/Tool.js.map +1 -1
  69. package/dist/esm/src/testing/graph-tester/core/GraphTester.d.ts +110 -0
  70. package/dist/esm/src/testing/graph-tester/core/GraphTester.d.ts.map +1 -0
  71. package/dist/esm/src/testing/graph-tester/core/GraphTester.js +335 -0
  72. package/dist/esm/src/testing/graph-tester/core/GraphTester.js.map +1 -0
  73. package/dist/esm/src/testing/graph-tester/core/TestFunction.d.ts +120 -0
  74. package/dist/esm/src/testing/graph-tester/core/TestFunction.d.ts.map +1 -0
  75. package/dist/esm/src/testing/graph-tester/core/TestFunction.js +184 -0
  76. package/dist/esm/src/testing/graph-tester/core/TestFunction.js.map +1 -0
  77. package/dist/esm/src/testing/graph-tester/core/types.d.ts +331 -0
  78. package/dist/esm/src/testing/graph-tester/core/types.d.ts.map +1 -0
  79. package/dist/esm/src/testing/graph-tester/core/types.js +21 -0
  80. package/dist/esm/src/testing/graph-tester/core/types.js.map +1 -0
  81. package/dist/esm/src/testing/graph-tester/fixtures/index.d.ts +8 -0
  82. package/dist/esm/src/testing/graph-tester/fixtures/index.d.ts.map +1 -0
  83. package/dist/esm/src/testing/graph-tester/fixtures/index.js +7 -0
  84. package/dist/esm/src/testing/graph-tester/fixtures/index.js.map +1 -0
  85. package/dist/esm/src/testing/graph-tester/fixtures/portPool.d.ts +40 -0
  86. package/dist/esm/src/testing/graph-tester/fixtures/portPool.d.ts.map +1 -0
  87. package/dist/esm/src/testing/graph-tester/fixtures/portPool.js +147 -0
  88. package/dist/esm/src/testing/graph-tester/fixtures/portPool.js.map +1 -0
  89. package/dist/esm/src/testing/graph-tester/index.d.ts +84 -0
  90. package/dist/esm/src/testing/graph-tester/index.d.ts.map +1 -0
  91. package/dist/esm/src/testing/graph-tester/index.js +77 -0
  92. package/dist/esm/src/testing/graph-tester/index.js.map +1 -0
  93. package/dist/esm/src/testing/graph-tester/modes/AccessibilityMode.d.ts +40 -0
  94. package/dist/esm/src/testing/graph-tester/modes/AccessibilityMode.d.ts.map +1 -0
  95. package/dist/esm/src/testing/graph-tester/modes/AccessibilityMode.js +193 -0
  96. package/dist/esm/src/testing/graph-tester/modes/AccessibilityMode.js.map +1 -0
  97. package/dist/esm/src/testing/graph-tester/modes/PerformanceMode.d.ts +42 -0
  98. package/dist/esm/src/testing/graph-tester/modes/PerformanceMode.d.ts.map +1 -0
  99. package/dist/esm/src/testing/graph-tester/modes/PerformanceMode.js +131 -0
  100. package/dist/esm/src/testing/graph-tester/modes/PerformanceMode.js.map +1 -0
  101. package/dist/esm/src/testing/graph-tester/modes/SEOMode.d.ts +39 -0
  102. package/dist/esm/src/testing/graph-tester/modes/SEOMode.d.ts.map +1 -0
  103. package/dist/esm/src/testing/graph-tester/modes/SEOMode.js +227 -0
  104. package/dist/esm/src/testing/graph-tester/modes/SEOMode.js.map +1 -0
  105. package/dist/esm/src/testing/graph-tester/modes/VisualRegressionMode.d.ts +83 -0
  106. package/dist/esm/src/testing/graph-tester/modes/VisualRegressionMode.d.ts.map +1 -0
  107. package/dist/esm/src/testing/graph-tester/modes/VisualRegressionMode.js +162 -0
  108. package/dist/esm/src/testing/graph-tester/modes/VisualRegressionMode.js.map +1 -0
  109. package/dist/esm/src/testing/graph-tester/modes/index.d.ts +14 -0
  110. package/dist/esm/src/testing/graph-tester/modes/index.d.ts.map +1 -0
  111. package/dist/esm/src/testing/graph-tester/modes/index.js +10 -0
  112. package/dist/esm/src/testing/graph-tester/modes/index.js.map +1 -0
  113. package/dist/esm/src/testing/graph-tester/reporters/HTMLReporter.d.ts +38 -0
  114. package/dist/esm/src/testing/graph-tester/reporters/HTMLReporter.d.ts.map +1 -0
  115. package/dist/esm/src/testing/graph-tester/reporters/HTMLReporter.js +374 -0
  116. package/dist/esm/src/testing/graph-tester/reporters/HTMLReporter.js.map +1 -0
  117. package/dist/esm/src/testing/graph-tester/reporters/JSONReporter.d.ts +50 -0
  118. package/dist/esm/src/testing/graph-tester/reporters/JSONReporter.d.ts.map +1 -0
  119. package/dist/esm/src/testing/graph-tester/reporters/JSONReporter.js +90 -0
  120. package/dist/esm/src/testing/graph-tester/reporters/JSONReporter.js.map +1 -0
  121. package/dist/esm/src/testing/graph-tester/reporters/MarkdownReporter.d.ts +33 -0
  122. package/dist/esm/src/testing/graph-tester/reporters/MarkdownReporter.d.ts.map +1 -0
  123. package/dist/esm/src/testing/graph-tester/reporters/MarkdownReporter.js +132 -0
  124. package/dist/esm/src/testing/graph-tester/reporters/MarkdownReporter.js.map +1 -0
  125. package/dist/esm/src/testing/graph-tester/reporters/UnifiedReporter.d.ts +30 -0
  126. package/dist/esm/src/testing/graph-tester/reporters/UnifiedReporter.d.ts.map +1 -0
  127. package/dist/esm/src/testing/graph-tester/reporters/UnifiedReporter.js +81 -0
  128. package/dist/esm/src/testing/graph-tester/reporters/UnifiedReporter.js.map +1 -0
  129. package/dist/esm/src/testing/graph-tester/reporters/index.d.ts +14 -0
  130. package/dist/esm/src/testing/graph-tester/reporters/index.d.ts.map +1 -0
  131. package/dist/esm/src/testing/graph-tester/reporters/index.js +10 -0
  132. package/dist/esm/src/testing/graph-tester/reporters/index.js.map +1 -0
  133. package/dist/esm/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.d.ts +33 -0
  134. package/dist/esm/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.d.ts.map +1 -0
  135. package/dist/esm/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.js +43 -0
  136. package/dist/esm/src/testing/graph-tester/screenshot/CanvasAnnotationRenderer.js.map +1 -0
  137. package/dist/esm/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.d.ts +70 -0
  138. package/dist/esm/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.d.ts.map +1 -0
  139. package/dist/esm/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.js +547 -0
  140. package/dist/esm/src/testing/graph-tester/screenshot/HTMLAnnotationRenderer.js.map +1 -0
  141. package/dist/esm/src/testing/graph-tester/screenshot/ScreenshotAnnotator.d.ts +83 -0
  142. package/dist/esm/src/testing/graph-tester/screenshot/ScreenshotAnnotator.d.ts.map +1 -0
  143. package/dist/esm/src/testing/graph-tester/screenshot/ScreenshotAnnotator.js +339 -0
  144. package/dist/esm/src/testing/graph-tester/screenshot/ScreenshotAnnotator.js.map +1 -0
  145. package/dist/esm/src/testing/graph-tester/screenshot/index.d.ts +11 -0
  146. package/dist/esm/src/testing/graph-tester/screenshot/index.d.ts.map +1 -0
  147. package/dist/esm/src/testing/graph-tester/screenshot/index.js +9 -0
  148. package/dist/esm/src/testing/graph-tester/screenshot/index.js.map +1 -0
  149. package/dist/esm/src/testing/graph-tester/screenshot/types.d.ts +331 -0
  150. package/dist/esm/src/testing/graph-tester/screenshot/types.d.ts.map +1 -0
  151. package/dist/esm/src/testing/graph-tester/screenshot/types.js +10 -0
  152. package/dist/esm/src/testing/graph-tester/screenshot/types.js.map +1 -0
  153. package/dist/esm/src/testing/selectors.d.ts +1 -1
  154. package/dist/esm/src/testing/selectors.js +1 -1
  155. package/package.json +19 -6
@@ -0,0 +1,227 @@
1
+ /**
2
+ * SEO testing mode (stub - to be implemented in Phase 2).
3
+ *
4
+ * Will validate meta tags, OpenGraph, and structured data.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ import { TestFunction } from '../core/TestFunction.js';
9
+ /**
10
+ * SEO testing mode (stub).
11
+ */
12
+ export class SEOMode extends TestFunction {
13
+ constructor(config) {
14
+ super();
15
+ this.mode = 'seo';
16
+ this.name = 'SEO';
17
+ this.description = 'Validates meta tags and SEO elements';
18
+ this.config = config;
19
+ }
20
+ async execute(page, context) {
21
+ const startTime = Date.now();
22
+ const errors = [];
23
+ try {
24
+ // Extract SEO metadata
25
+ const seoData = await page.evaluate(() => {
26
+ // Helper to get meta content
27
+ const getMeta = (name) => {
28
+ const meta = document.querySelector(`meta[name="${name}"], meta[property="${name}"]`);
29
+ return meta?.getAttribute('content') || null;
30
+ };
31
+ // Get all meta tags
32
+ const allMeta = {};
33
+ Array.from(document.querySelectorAll('meta')).forEach((meta) => {
34
+ const name = meta.getAttribute('name') || meta.getAttribute('property');
35
+ const content = meta.getAttribute('content');
36
+ if (name && content) {
37
+ allMeta[name] = content;
38
+ }
39
+ });
40
+ // Title and description
41
+ const title = document.querySelector('title')?.textContent || '';
42
+ const description = getMeta('description');
43
+ // OpenGraph
44
+ const og = {
45
+ title: getMeta('og:title'),
46
+ description: getMeta('og:description'),
47
+ image: getMeta('og:image'),
48
+ url: getMeta('og:url'),
49
+ type: getMeta('og:type'),
50
+ siteName: getMeta('og:site_name'),
51
+ };
52
+ // Twitter Cards
53
+ const twitter = {
54
+ card: getMeta('twitter:card'),
55
+ title: getMeta('twitter:title'),
56
+ description: getMeta('twitter:description'),
57
+ image: getMeta('twitter:image'),
58
+ site: getMeta('twitter:site'),
59
+ creator: getMeta('twitter:creator'),
60
+ };
61
+ // Canonical URL
62
+ const canonical = document.querySelector('link[rel="canonical"]')?.getAttribute('href');
63
+ // Heading structure
64
+ const headings = {
65
+ h1: Array.from(document.querySelectorAll('h1')).map((h) => h.textContent?.trim() || ''),
66
+ h2: Array.from(document.querySelectorAll('h2')).map((h) => h.textContent?.trim() || ''),
67
+ h3Count: document.querySelectorAll('h3').length,
68
+ h4Count: document.querySelectorAll('h4').length,
69
+ };
70
+ // Structured data (JSON-LD)
71
+ const structuredData = [];
72
+ Array.from(document.querySelectorAll('script[type="application/ld+json"]')).forEach((script) => {
73
+ try {
74
+ const data = JSON.parse(script.textContent || '{}');
75
+ structuredData.push(data);
76
+ }
77
+ catch {
78
+ // Ignore invalid JSON
79
+ }
80
+ });
81
+ // Images
82
+ const images = Array.from(document.querySelectorAll('img'));
83
+ const imagesWithoutAlt = images.filter((img) => !img.getAttribute('alt')).length;
84
+ // Links
85
+ const links = Array.from(document.querySelectorAll('a'));
86
+ const externalLinks = links.filter((a) => {
87
+ const href = a.getAttribute('href');
88
+ return href && (href.startsWith('http://') || href.startsWith('https://'));
89
+ }).length;
90
+ return {
91
+ title,
92
+ description,
93
+ canonical,
94
+ allMeta,
95
+ og,
96
+ twitter,
97
+ headings,
98
+ structuredData,
99
+ images: {
100
+ total: images.length,
101
+ withoutAlt: imagesWithoutAlt,
102
+ },
103
+ links: {
104
+ total: links.length,
105
+ external: externalLinks,
106
+ },
107
+ };
108
+ });
109
+ // Validate required meta tags
110
+ const missingTags = [];
111
+ if (this.config.requiredMetaTags) {
112
+ for (const tag of this.config.requiredMetaTags) {
113
+ if (!seoData.allMeta[tag]) {
114
+ missingTags.push(tag);
115
+ }
116
+ }
117
+ }
118
+ // Basic SEO validations
119
+ const issues = [];
120
+ if (!seoData.title) {
121
+ issues.push({ severity: 'critical', message: 'Missing page title' });
122
+ }
123
+ else if (seoData.title.length < 30 || seoData.title.length > 60) {
124
+ issues.push({
125
+ severity: 'warning',
126
+ message: `Title length ${seoData.title.length} characters (recommended: 30-60)`,
127
+ });
128
+ }
129
+ if (!seoData.description) {
130
+ issues.push({ severity: 'critical', message: 'Missing meta description' });
131
+ }
132
+ else if (seoData.description.length < 120 || seoData.description.length > 160) {
133
+ issues.push({
134
+ severity: 'warning',
135
+ message: `Description length ${seoData.description.length} characters (recommended: 120-160)`,
136
+ });
137
+ }
138
+ if (seoData.headings.h1.length === 0) {
139
+ issues.push({ severity: 'warning', message: 'Missing H1 heading' });
140
+ }
141
+ else if (seoData.headings.h1.length > 1) {
142
+ issues.push({
143
+ severity: 'warning',
144
+ message: `Multiple H1 headings found (${seoData.headings.h1.length})`,
145
+ });
146
+ }
147
+ if (seoData.images.withoutAlt > 0) {
148
+ issues.push({
149
+ severity: 'warning',
150
+ message: `${seoData.images.withoutAlt} images without alt text`,
151
+ });
152
+ }
153
+ // OpenGraph validation
154
+ if (this.config.validateOpenGraph !== false) {
155
+ if (!seoData.og.title)
156
+ issues.push({ severity: 'warning', message: 'Missing og:title' });
157
+ if (!seoData.og.description)
158
+ issues.push({ severity: 'warning', message: 'Missing og:description' });
159
+ if (!seoData.og.image)
160
+ issues.push({ severity: 'warning', message: 'Missing og:image' });
161
+ }
162
+ // Twitter Cards validation
163
+ if (this.config.validateTwitterCards !== false) {
164
+ if (!seoData.twitter.card)
165
+ issues.push({ severity: 'info', message: 'Missing twitter:card' });
166
+ }
167
+ if (missingTags.length > 0) {
168
+ issues.push({
169
+ severity: 'critical',
170
+ message: `Missing required meta tags: ${missingTags.join(', ')}`,
171
+ });
172
+ }
173
+ // Save results
174
+ const outputPath = `${this.config.outputDir}/${this.sanitizeRoute(context.route)}-seo.json`;
175
+ await this.ensureDirectory(this.config.outputDir);
176
+ await this.writeFile(outputPath, JSON.stringify({
177
+ route: context.route,
178
+ seo: seoData,
179
+ issues,
180
+ score: this.calculateScore(issues),
181
+ }, null, 2));
182
+ const duration = Date.now() - startTime;
183
+ return {
184
+ passed: issues.length === 0,
185
+ duration,
186
+ errors: issues,
187
+ metadata: {
188
+ seo: {
189
+ issueCount: issues.length,
190
+ score: this.calculateScore(issues),
191
+ hasStructuredData: seoData.structuredData.length > 0,
192
+ },
193
+ outputPath,
194
+ },
195
+ };
196
+ }
197
+ catch (error) {
198
+ errors.push({
199
+ severity: 'critical',
200
+ message: `SEO validation failed: ${error instanceof Error ? error.message : String(error)}`,
201
+ stack: error instanceof Error ? error.stack : undefined,
202
+ });
203
+ return {
204
+ passed: false,
205
+ duration: Date.now() - startTime,
206
+ errors,
207
+ metadata: {},
208
+ };
209
+ }
210
+ }
211
+ calculateScore(issues) {
212
+ // Simple scoring: 100 - (10 points per issue)
213
+ return Math.max(0, 100 - issues.length * 10);
214
+ }
215
+ sanitizeRoute(route) {
216
+ return route.replace(/^\//, '').replace(/\//g, '-') || 'home';
217
+ }
218
+ async ensureDirectory(dir) {
219
+ const fs = await import('fs/promises');
220
+ await fs.mkdir(dir, { recursive: true });
221
+ }
222
+ async writeFile(path, content) {
223
+ const fs = await import('fs/promises');
224
+ await fs.writeFile(path, content, 'utf-8');
225
+ }
226
+ }
227
+ //# sourceMappingURL=SEOMode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SEOMode.js","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/modes/SEOMode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Visual regression testing mode.
3
+ *
4
+ * Captures screenshots with element annotations for visual regression testing and AI analysis.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ import type { Page } from '@playwright/test';
9
+ import { TestFunction } from '../core/TestFunction';
10
+ import type { TestContext, TestResult } from '../core/types';
11
+ import { type ScreenshotAnnotatorConfig, type HTMLRendererConfig } from '../screenshot';
12
+ /**
13
+ * Configuration for visual regression mode.
14
+ */
15
+ export interface VisualRegressionConfig {
16
+ /** Output directory for screenshots */
17
+ outputDir: string;
18
+ /** Whether to capture full page (default: true) */
19
+ fullPage?: boolean;
20
+ /** Whether to annotate elements (default: true) */
21
+ annotate?: boolean;
22
+ /** Whether to generate HTML overlay (default: true) */
23
+ generateHTML?: boolean;
24
+ /** Whether to include invisible elements (default: false) */
25
+ includeInvisible?: boolean;
26
+ /** Minimum element size to annotate (default: 5px) */
27
+ minElementSize?: number;
28
+ /** Whether to enable AI analysis (enterprise only, default: false) */
29
+ aiAnalyze?: boolean;
30
+ /** Custom screenshot annotator config */
31
+ annotatorConfig?: Partial<ScreenshotAnnotatorConfig>;
32
+ /** Custom HTML renderer config */
33
+ htmlRendererConfig?: Partial<HTMLRendererConfig>;
34
+ }
35
+ /**
36
+ * Visual regression testing mode.
37
+ *
38
+ * Captures full-page screenshots with element annotations, bounding boxes,
39
+ * and generates interactive HTML overlays for review.
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const mode = new VisualRegressionMode({
44
+ * outputDir: './screenshots',
45
+ * annotate: true,
46
+ * generateHTML: true
47
+ * });
48
+ *
49
+ * const tester = new GraphTester({
50
+ * baseUrl: 'http://localhost:3000',
51
+ * routes: [{ route: '/' }],
52
+ * modes: []
53
+ * });
54
+ *
55
+ * tester.registerTestFunction(mode);
56
+ * const results = await tester.runTests();
57
+ * ```
58
+ */
59
+ export declare class VisualRegressionMode extends TestFunction {
60
+ readonly mode = "visual";
61
+ readonly name = "Visual Regression";
62
+ readonly description = "Captures screenshots with element annotations for visual regression testing";
63
+ private config;
64
+ private annotator;
65
+ constructor(config: VisualRegressionConfig);
66
+ /**
67
+ * Setup: Initialize screenshot annotator.
68
+ */
69
+ setup?(page: Page): Promise<void>;
70
+ /**
71
+ * Execute: Capture screenshot and annotations.
72
+ */
73
+ execute(page: Page, context: TestContext): Promise<TestResult>;
74
+ /**
75
+ * Sanitize route for filename.
76
+ */
77
+ private sanitizeRoute;
78
+ /**
79
+ * Validate configuration.
80
+ */
81
+ validate(): string[];
82
+ }
83
+ //# sourceMappingURL=VisualRegressionMode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VisualRegressionMode.d.ts","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/modes/VisualRegressionMode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAGL,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AAGvB;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAElB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,sDAAsD;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,sEAAsE;IACtE,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,yCAAyC;IACzC,eAAe,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAErD,kCAAkC;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,IAAI,uBAAuB;IACpC,QAAQ,CAAC,WAAW,iFAAiF;IAErG,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,SAAS,CAAoC;gBAEzC,MAAM,EAAE,sBAAsB;IAa1C;;OAEG;IACG,KAAK,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvC;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IA0FpE;;OAEG;IACH,OAAO,CAAC,aAAa;IAIrB;;OAEG;IACH,QAAQ,IAAI,MAAM,EAAE;CASrB"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Visual regression testing mode.
3
+ *
4
+ * Captures screenshots with element annotations for visual regression testing and AI analysis.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ import { TestFunction } from '../core/TestFunction.js';
9
+ import { ScreenshotAnnotator, HTMLAnnotationRenderer, } from '../screenshot/index.js';
10
+ import * as path from 'path';
11
+ /**
12
+ * Visual regression testing mode.
13
+ *
14
+ * Captures full-page screenshots with element annotations, bounding boxes,
15
+ * and generates interactive HTML overlays for review.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const mode = new VisualRegressionMode({
20
+ * outputDir: './screenshots',
21
+ * annotate: true,
22
+ * generateHTML: true
23
+ * });
24
+ *
25
+ * const tester = new GraphTester({
26
+ * baseUrl: 'http://localhost:3000',
27
+ * routes: [{ route: '/' }],
28
+ * modes: []
29
+ * });
30
+ *
31
+ * tester.registerTestFunction(mode);
32
+ * const results = await tester.runTests();
33
+ * ```
34
+ */
35
+ export class VisualRegressionMode extends TestFunction {
36
+ constructor(config) {
37
+ super();
38
+ this.mode = 'visual';
39
+ this.name = 'Visual Regression';
40
+ this.description = 'Captures screenshots with element annotations for visual regression testing';
41
+ this.annotator = null;
42
+ this.config = {
43
+ fullPage: true,
44
+ annotate: true,
45
+ generateHTML: true,
46
+ includeInvisible: false,
47
+ minElementSize: 5,
48
+ aiAnalyze: false,
49
+ ...config,
50
+ };
51
+ }
52
+ /**
53
+ * Setup: Initialize screenshot annotator.
54
+ */
55
+ async setup(page) {
56
+ if (this.config.annotate) {
57
+ this.annotator = new ScreenshotAnnotator({
58
+ outputDir: this.config.outputDir,
59
+ fullPage: this.config.fullPage,
60
+ includeInvisible: this.config.includeInvisible,
61
+ minElementSize: this.config.minElementSize,
62
+ ...this.config.annotatorConfig,
63
+ });
64
+ }
65
+ }
66
+ /**
67
+ * Execute: Capture screenshot and annotations.
68
+ */
69
+ async execute(page, context) {
70
+ const startTime = Date.now();
71
+ const errors = [];
72
+ const metadata = {};
73
+ try {
74
+ // Capture annotated screenshot
75
+ if (this.annotator) {
76
+ const viewportLabel = context.viewport ? ` [${context.viewport.name}]` : '';
77
+ console.log(`Capturing annotated screenshot for ${context.route}${viewportLabel}...`);
78
+ const annotatedScreenshot = await this.annotator.capture(page, context.route, context.viewport?.name);
79
+ metadata.screenshot = {
80
+ path: annotatedScreenshot.screenshotPath,
81
+ annotationCount: annotatedScreenshot.annotations.length,
82
+ interactiveElementCount: annotatedScreenshot.annotations.filter((a) => a.isInteractive)
83
+ .length,
84
+ pageSize: annotatedScreenshot.pageMetadata.pageSize,
85
+ viewport: annotatedScreenshot.pageMetadata.viewport,
86
+ };
87
+ // Generate HTML overlay
88
+ if (this.config.generateHTML) {
89
+ const htmlPath = annotatedScreenshot.screenshotPath.replace('.png', '.html');
90
+ const renderer = new HTMLAnnotationRenderer({
91
+ outputPath: htmlPath,
92
+ includeSidebar: true,
93
+ enableHover: true,
94
+ enableClickToHighlight: true,
95
+ ...this.config.htmlRendererConfig,
96
+ });
97
+ const renderResult = await renderer.render(annotatedScreenshot);
98
+ metadata.htmlOverlay = {
99
+ path: renderResult.outputPath,
100
+ fileSize: renderResult.fileSize,
101
+ duration: renderResult.duration,
102
+ };
103
+ console.log(`Generated HTML overlay: ${renderResult.outputPath}`);
104
+ }
105
+ // AI analysis (enterprise only)
106
+ if (this.config.aiAnalyze) {
107
+ errors.push({
108
+ severity: 'info',
109
+ message: 'AI analysis requires @supernalintelligence/interface-enterprise',
110
+ });
111
+ }
112
+ }
113
+ else {
114
+ // Simple screenshot without annotations
115
+ const screenshotPath = path.join(this.config.outputDir, `${this.sanitizeRoute(context.route)}.png`);
116
+ await page.screenshot({
117
+ path: screenshotPath,
118
+ fullPage: this.config.fullPage,
119
+ });
120
+ metadata.screenshot = {
121
+ path: screenshotPath,
122
+ };
123
+ }
124
+ return {
125
+ passed: true,
126
+ duration: Date.now() - startTime,
127
+ errors,
128
+ metadata,
129
+ };
130
+ }
131
+ catch (error) {
132
+ errors.push({
133
+ severity: 'critical',
134
+ message: `Visual regression failed: ${error instanceof Error ? error.message : String(error)}`,
135
+ stack: error instanceof Error ? error.stack : undefined,
136
+ });
137
+ return {
138
+ passed: false,
139
+ duration: Date.now() - startTime,
140
+ errors,
141
+ metadata,
142
+ };
143
+ }
144
+ }
145
+ /**
146
+ * Sanitize route for filename.
147
+ */
148
+ sanitizeRoute(route) {
149
+ return route.replace(/^\//, '').replace(/\//g, '-') || 'home';
150
+ }
151
+ /**
152
+ * Validate configuration.
153
+ */
154
+ validate() {
155
+ const errors = super.validate();
156
+ if (!this.config.outputDir) {
157
+ errors.push('outputDir is required');
158
+ }
159
+ return errors;
160
+ }
161
+ }
162
+ //# sourceMappingURL=VisualRegressionMode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VisualRegressionMode.js","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/modes/VisualRegressionMode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Test modes exports.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { VisualRegressionMode } from './VisualRegressionMode';
7
+ export type { VisualRegressionConfig } from './VisualRegressionMode';
8
+ export { PerformanceMode } from './PerformanceMode';
9
+ export type { PerformanceConfig } from './PerformanceMode';
10
+ export { AccessibilityMode } from './AccessibilityMode';
11
+ export type { AccessibilityConfig } from './AccessibilityMode';
12
+ export { SEOMode } from './SEOMode';
13
+ export type { SEOConfig } from './SEOMode';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/modes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Test modes exports.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { VisualRegressionMode } from './VisualRegressionMode.js';
7
+ export { PerformanceMode } from './PerformanceMode.js';
8
+ export { AccessibilityMode } from './AccessibilityMode.js';
9
+ export { SEOMode } from './SEOMode.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/modes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * HTML reporter (stub - to be implemented in Phase 2).
3
+ *
4
+ * Will generate interactive dashboard with charts and drill-down.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ import type { AggregatedTestResults, Reporter } from '../core/types';
9
+ /**
10
+ * Configuration for HTML reporter.
11
+ */
12
+ export interface HTMLReporterConfig {
13
+ /** Output directory */
14
+ outputDir: string;
15
+ /** Output filename (default: 'index.html') */
16
+ filename?: string;
17
+ /** Whether to include charts (default: true) */
18
+ includeCharts?: boolean;
19
+ }
20
+ /**
21
+ * HTML reporter (stub).
22
+ */
23
+ export declare class HTMLReporter implements Reporter {
24
+ readonly name = "HTML Reporter";
25
+ private config;
26
+ constructor(config: HTMLReporterConfig);
27
+ generate(results: AggregatedTestResults): Promise<void>;
28
+ private generateHTML;
29
+ private generateSummarySection;
30
+ private generateChartsSection;
31
+ private generateResultsTable;
32
+ private generateModeBreakdown;
33
+ private generateId;
34
+ private escapeHtml;
35
+ private ensureDirectory;
36
+ private writeFile;
37
+ }
38
+ //# sourceMappingURL=HTMLReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HTMLReporter.d.ts","sourceRoot":"","sources":["../../../../../../src/testing/graph-tester/reporters/HTMLReporter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAElB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,gDAAgD;IAChD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,YAAa,YAAW,QAAQ;IAC3C,QAAQ,CAAC,IAAI,mBAAmB;IAEhC,OAAO,CAAC,MAAM,CAAqB;gBAEvB,MAAM,EAAE,kBAAkB;IAIhC,QAAQ,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7D,OAAO,CAAC,YAAY;IAmMpB,OAAO,CAAC,sBAAsB;IA8B9B,OAAO,CAAC,qBAAqB;IAoC7B,OAAO,CAAC,oBAAoB;IAoD5B,OAAO,CAAC,qBAAqB;IAgC7B,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,UAAU;YAWJ,eAAe;YAKf,SAAS;CAIxB"}