@kosuke-ai/cli 0.0.30 → 0.0.31

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 (38) hide show
  1. package/dist/kosuke/commands/ship.d.ts.map +1 -1
  2. package/dist/kosuke/commands/ship.js +57 -22
  3. package/dist/kosuke/commands/ship.js.map +1 -1
  4. package/dist/kosuke/commands/test.d.ts +8 -9
  5. package/dist/kosuke/commands/test.d.ts.map +1 -1
  6. package/dist/kosuke/commands/test.js +68 -288
  7. package/dist/kosuke/commands/test.js.map +1 -1
  8. package/dist/kosuke/types.d.ts +8 -16
  9. package/dist/kosuke/types.d.ts.map +1 -1
  10. package/dist/kosuke/utils/browser-agent.d.ts +33 -0
  11. package/dist/kosuke/utils/browser-agent.d.ts.map +1 -0
  12. package/dist/kosuke/utils/browser-agent.js +102 -0
  13. package/dist/kosuke/utils/browser-agent.js.map +1 -0
  14. package/dist/kosuke/utils/error-analyzer.d.ts +6 -3
  15. package/dist/kosuke/utils/error-analyzer.d.ts.map +1 -1
  16. package/dist/kosuke/utils/error-analyzer.js +35 -57
  17. package/dist/kosuke/utils/error-analyzer.js.map +1 -1
  18. package/dist/kosuke/utils/prompt-generator.d.ts +13 -0
  19. package/dist/kosuke/utils/prompt-generator.d.ts.map +1 -0
  20. package/dist/kosuke/utils/prompt-generator.js +44 -0
  21. package/dist/kosuke/utils/prompt-generator.js.map +1 -0
  22. package/dist/lib.d.ts +1 -1
  23. package/dist/lib.d.ts.map +1 -1
  24. package/dist/lib.js.map +1 -1
  25. package/dist/package.json +3 -6
  26. package/package.json +3 -6
  27. package/dist/kosuke/utils/playwright-agent.d.ts +0 -47
  28. package/dist/kosuke/utils/playwright-agent.d.ts.map +0 -1
  29. package/dist/kosuke/utils/playwright-agent.js +0 -278
  30. package/dist/kosuke/utils/playwright-agent.js.map +0 -1
  31. package/dist/kosuke/utils/test-generator.d.ts +0 -22
  32. package/dist/kosuke/utils/test-generator.d.ts.map +0 -1
  33. package/dist/kosuke/utils/test-generator.js +0 -174
  34. package/dist/kosuke/utils/test-generator.js.map +0 -1
  35. package/dist/kosuke/utils/visual-tester.d.ts +0 -71
  36. package/dist/kosuke/utils/visual-tester.d.ts.map +0 -1
  37. package/dist/kosuke/utils/visual-tester.js +0 -202
  38. package/dist/kosuke/utils/visual-tester.js.map +0 -1
@@ -1,202 +0,0 @@
1
- /**
2
- * Visual Tester - Visual regression testing with screenshot comparison
3
- *
4
- * Inspired by Subito.it's approach:
5
- * - Capture screenshots of pages
6
- * - Compare against baseline images
7
- * - Detect pixel differences above threshold
8
- * - Hide dynamic content (ads, analytics)
9
- */
10
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
11
- import { join } from 'path';
12
- import { PNG } from 'pngjs';
13
- import pixelmatch from 'pixelmatch';
14
- /**
15
- * Visual Tester class for screenshot comparison
16
- */
17
- export class VisualTester {
18
- constructor(cwd = process.cwd()) {
19
- this.diffs = [];
20
- this.cwd = cwd;
21
- }
22
- /**
23
- * Hide dynamic content that shouldn't be tested
24
- */
25
- async hideDynamicContent(page) {
26
- await page.addStyleTag({
27
- content: `
28
- /* Hide common dynamic content */
29
- .advertisement,
30
- .ad-banner,
31
- .analytics-widget,
32
- .third-party-banner,
33
- [class*="ad-"],
34
- [id*="ad-"],
35
- [class*="analytics"],
36
- [id*="analytics"] {
37
- display: none !important;
38
- visibility: hidden !important;
39
- }
40
- `,
41
- });
42
- }
43
- /**
44
- * Take a screenshot and compare with baseline
45
- */
46
- async captureAndCompare(page, options) {
47
- const { ticketId, testName, threshold = 0.01, updateBaseline = false } = options;
48
- // Ensure visual test directories exist
49
- const baselineDir = join(this.cwd, '.kosuke', 'visual-tests', 'baselines', ticketId);
50
- const currentDir = join(this.cwd, '.kosuke', 'visual-tests', 'current', ticketId);
51
- const diffDir = join(this.cwd, '.kosuke', 'visual-tests', 'diffs', ticketId);
52
- this.ensureDir(baselineDir);
53
- this.ensureDir(currentDir);
54
- this.ensureDir(diffDir);
55
- const baselinePath = join(baselineDir, `${testName}.png`);
56
- const currentPath = join(currentDir, `${testName}.png`);
57
- const diffPath = join(diffDir, `${testName}.png`);
58
- // Hide dynamic content before taking screenshot
59
- await this.hideDynamicContent(page);
60
- // Wait for page to be stable
61
- await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {
62
- // Ignore timeout - some pages never reach networkidle
63
- });
64
- // Take screenshot
65
- const screenshot = await page.screenshot({ fullPage: true });
66
- writeFileSync(currentPath, screenshot);
67
- // If no baseline exists or updateBaseline flag is set, create/update baseline
68
- if (!existsSync(baselinePath) || updateBaseline) {
69
- writeFileSync(baselinePath, screenshot);
70
- console.log(` šŸ“ø ${updateBaseline ? 'Updated' : 'Created'} baseline: ${testName}`);
71
- const diff = {
72
- testName,
73
- diffPixels: 0,
74
- diffPercentage: 0,
75
- threshold,
76
- passed: true,
77
- baselinePath,
78
- currentPath,
79
- diffPath,
80
- };
81
- this.diffs.push(diff);
82
- return diff;
83
- }
84
- // Compare with baseline
85
- const result = this.compareImages(baselinePath, currentPath, diffPath, threshold);
86
- this.diffs.push(result);
87
- return result;
88
- }
89
- /**
90
- * Compare two images and generate diff
91
- */
92
- compareImages(baselinePath, currentPath, diffPath, threshold) {
93
- const testName = baselinePath.split('/').pop()?.replace('.png', '') || 'unknown';
94
- try {
95
- const baseline = PNG.sync.read(readFileSync(baselinePath));
96
- const current = PNG.sync.read(readFileSync(currentPath));
97
- // Check if dimensions match
98
- if (baseline.width !== current.width || baseline.height !== current.height) {
99
- return {
100
- testName,
101
- diffPixels: baseline.width * baseline.height, // All pixels are different
102
- diffPercentage: 1,
103
- threshold,
104
- passed: false,
105
- baselinePath,
106
- currentPath,
107
- diffPath,
108
- };
109
- }
110
- // Create diff image
111
- const diff = new PNG({ width: baseline.width, height: baseline.height });
112
- // Compare pixels
113
- const diffPixels = pixelmatch(baseline.data, current.data, diff.data, baseline.width, baseline.height, { threshold: 0.1 } // Pixel sensitivity
114
- );
115
- const totalPixels = baseline.width * baseline.height;
116
- const diffPercentage = diffPixels / totalPixels;
117
- // Save diff image if there are differences
118
- if (diffPixels > 0) {
119
- writeFileSync(diffPath, PNG.sync.write(diff));
120
- }
121
- return {
122
- testName,
123
- diffPixels,
124
- diffPercentage,
125
- threshold,
126
- passed: diffPercentage <= threshold,
127
- baselinePath,
128
- currentPath,
129
- diffPath,
130
- };
131
- }
132
- catch (error) {
133
- console.error(` āš ļø Failed to compare images: ${error}`);
134
- return {
135
- testName,
136
- diffPixels: 0,
137
- diffPercentage: 0,
138
- threshold,
139
- passed: false,
140
- baselinePath,
141
- currentPath,
142
- diffPath,
143
- };
144
- }
145
- }
146
- /**
147
- * Get all visual diffs
148
- */
149
- getDiffs() {
150
- return this.diffs;
151
- }
152
- /**
153
- * Get failed visual diffs
154
- */
155
- getFailedDiffs() {
156
- return this.diffs.filter((diff) => !diff.passed);
157
- }
158
- /**
159
- * Check if there are any visual regressions
160
- */
161
- hasRegressions() {
162
- return this.getFailedDiffs().length > 0;
163
- }
164
- /**
165
- * Format visual diff report
166
- */
167
- formatReport() {
168
- if (this.diffs.length === 0) {
169
- return 'No visual tests run';
170
- }
171
- const failed = this.getFailedDiffs();
172
- const passed = this.diffs.filter((diff) => diff.passed);
173
- const lines = [];
174
- lines.push(`\nšŸ“ø Visual Regression Report:`);
175
- lines.push(` āœ… Passed: ${passed.length}`);
176
- lines.push(` āŒ Failed: ${failed.length}`);
177
- if (failed.length > 0) {
178
- lines.push('\n Failed tests:');
179
- for (const diff of failed) {
180
- const percentage = (diff.diffPercentage * 100).toFixed(2);
181
- lines.push(` - ${diff.testName}: ${percentage}% difference (threshold: ${diff.threshold * 100}%)`);
182
- lines.push(` Diff image: ${diff.diffPath}`);
183
- }
184
- }
185
- return lines.join('\n');
186
- }
187
- /**
188
- * Clear all diffs
189
- */
190
- clear() {
191
- this.diffs = [];
192
- }
193
- /**
194
- * Ensure directory exists
195
- */
196
- ensureDir(dir) {
197
- if (!existsSync(dir)) {
198
- mkdirSync(dir, { recursive: true });
199
- }
200
- }
201
- }
202
- //# sourceMappingURL=visual-tester.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"visual-tester.js","sourceRoot":"","sources":["../../../kosuke/utils/visual-tester.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,UAAU,MAAM,YAAY,CAAC;AAoBpC;;GAEG;AACH,MAAM,OAAO,YAAY;IAIvB,YAAY,MAAc,OAAO,CAAC,GAAG,EAAE;QAF/B,UAAK,GAAiB,EAAE,CAAC;QAG/B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,IAAU;QACjC,MAAM,IAAI,CAAC,WAAW,CAAC;YACrB,OAAO,EAAE;;;;;;;;;;;;;OAaR;SACF,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CAAC,IAAU,EAAE,OAA0B;QAC5D,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI,EAAE,cAAc,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;QAEjF,uCAAuC;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;QACrF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAClF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAE7E,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAExB,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,QAAQ,MAAM,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,QAAQ,MAAM,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,QAAQ,MAAM,CAAC,CAAC;QAElD,gDAAgD;QAChD,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAEpC,6BAA6B;QAC7B,MAAM,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACxE,sDAAsD;QACxD,CAAC,CAAC,CAAC;QAEH,kBAAkB;QAClB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,aAAa,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAEvC,8EAA8E;QAC9E,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,cAAc,EAAE,CAAC;YAChD,aAAa,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,cAAc,QAAQ,EAAE,CAAC,CAAC;YAErF,MAAM,IAAI,GAAe;gBACvB,QAAQ;gBACR,UAAU,EAAE,CAAC;gBACb,cAAc,EAAE,CAAC;gBACjB,SAAS;gBACT,MAAM,EAAE,IAAI;gBACZ,YAAY;gBACZ,WAAW;gBACX,QAAQ;aACT,CAAC;YAEF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,wBAAwB;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QAElF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,aAAa,CACnB,YAAoB,EACpB,WAAmB,EACnB,QAAgB,EAChB,SAAiB;QAEjB,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;QAEjF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;YAC3D,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;YAEzD,4BAA4B;YAC5B,IAAI,QAAQ,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC3E,OAAO;oBACL,QAAQ;oBACR,UAAU,EAAE,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,2BAA2B;oBACzE,cAAc,EAAE,CAAC;oBACjB,SAAS;oBACT,MAAM,EAAE,KAAK;oBACb,YAAY;oBACZ,WAAW;oBACX,QAAQ;iBACT,CAAC;YACJ,CAAC;YAED,oBAAoB;YACpB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAEzE,iBAAiB;YACjB,MAAM,UAAU,GAAG,UAAU,CAC3B,QAAQ,CAAC,IAAI,EACb,OAAO,CAAC,IAAI,EACZ,IAAI,CAAC,IAAI,EACT,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,MAAM,EACf,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,oBAAoB;aACxC,CAAC;YAEF,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC;YACrD,MAAM,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;YAEhD,2CAA2C;YAC3C,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;gBACnB,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAChD,CAAC;YAED,OAAO;gBACL,QAAQ;gBACR,UAAU;gBACV,cAAc;gBACd,SAAS;gBACT,MAAM,EAAE,cAAc,IAAI,SAAS;gBACnC,YAAY;gBACZ,WAAW;gBACX,QAAQ;aACT,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,oCAAoC,KAAK,EAAE,CAAC,CAAC;YAC3D,OAAO;gBACL,QAAQ;gBACR,UAAU,EAAE,CAAC;gBACb,cAAc,EAAE,CAAC;gBACjB,SAAS;gBACT,MAAM,EAAE,KAAK;gBACb,YAAY;gBACZ,WAAW;gBACX,QAAQ;aACT,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,YAAY;QACV,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,qBAAqB,CAAC;QAC/B,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAExD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC7C,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAE5C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACjC,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;gBAC1B,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC1D,KAAK,CAAC,IAAI,CACR,QAAQ,IAAI,CAAC,QAAQ,KAAK,UAAU,4BAA4B,IAAI,CAAC,SAAS,GAAG,GAAG,IAAI,CACzF,CAAC;gBACF,KAAK,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,SAAS,CAAC,GAAW;QAC3B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;CACF"}