@vizzly-testing/cli 0.23.1 → 0.24.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 (45) hide show
  1. package/README.md +54 -586
  2. package/dist/api/client.js +3 -1
  3. package/dist/api/endpoints.js +6 -7
  4. package/dist/cli.js +15 -2
  5. package/dist/commands/finalize.js +12 -0
  6. package/dist/commands/preview.js +210 -28
  7. package/dist/commands/run.js +15 -0
  8. package/dist/commands/status.js +34 -8
  9. package/dist/commands/upload.js +13 -0
  10. package/dist/reporter/reporter-bundle.css +1 -1
  11. package/dist/reporter/reporter-bundle.iife.js +71 -63
  12. package/dist/server/handlers/tdd-handler.js +4 -9
  13. package/dist/tdd/core/region-coverage.js +115 -0
  14. package/dist/tdd/core/signature.js +3 -1
  15. package/dist/tdd/metadata/region-metadata.js +93 -0
  16. package/dist/tdd/services/comparison-service.js +40 -8
  17. package/dist/tdd/services/region-service.js +75 -0
  18. package/dist/tdd/tdd-service.js +70 -8
  19. package/package.json +3 -4
  20. package/claude-plugin/.claude-plugin/README.md +0 -270
  21. package/claude-plugin/.claude-plugin/marketplace.json +0 -28
  22. package/claude-plugin/.claude-plugin/plugin.json +0 -14
  23. package/claude-plugin/.mcp.json +0 -12
  24. package/claude-plugin/CHANGELOG.md +0 -85
  25. package/claude-plugin/commands/setup.md +0 -137
  26. package/claude-plugin/commands/suggest-screenshots.md +0 -111
  27. package/claude-plugin/mcp/vizzly-docs-server/README.md +0 -95
  28. package/claude-plugin/mcp/vizzly-docs-server/docs-fetcher.js +0 -110
  29. package/claude-plugin/mcp/vizzly-docs-server/index.js +0 -283
  30. package/claude-plugin/mcp/vizzly-server/cloud-api-provider.js +0 -399
  31. package/claude-plugin/mcp/vizzly-server/index.js +0 -927
  32. package/claude-plugin/mcp/vizzly-server/local-tdd-provider.js +0 -455
  33. package/claude-plugin/mcp/vizzly-server/token-resolver.js +0 -185
  34. package/claude-plugin/skills/check-visual-tests/SKILL.md +0 -158
  35. package/claude-plugin/skills/debug-visual-regression/SKILL.md +0 -269
  36. package/docs/api-reference.md +0 -1003
  37. package/docs/authentication.md +0 -334
  38. package/docs/doctor-command.md +0 -44
  39. package/docs/getting-started.md +0 -131
  40. package/docs/internal/SDK-API.md +0 -1018
  41. package/docs/plugins.md +0 -557
  42. package/docs/tdd-mode.md +0 -594
  43. package/docs/test-integration.md +0 -523
  44. package/docs/tui-elements.md +0 -560
  45. package/docs/upload-command.md +0 -196
package/docs/plugins.md DELETED
@@ -1,557 +0,0 @@
1
- # Vizzly Plugin System
2
-
3
- The Vizzly CLI supports a powerful plugin system that allows you to extend its functionality with
4
- custom commands. This enables community contributions and specialized integrations while keeping the
5
- core CLI lean and focused.
6
-
7
- ## Overview
8
-
9
- Plugins are JavaScript modules that export a simple registration function. The CLI automatically
10
- discovers plugins from `node_modules/@vizzly-testing/*` or loads them explicitly from your config
11
- file.
12
-
13
- ## Benefits
14
-
15
- - **Zero Configuration** - Just `npm install` and the plugin is available
16
- - **Shared Infrastructure** - Plugins get access to config, output utilities, and services
17
- - **Independent Releases** - Plugins can iterate without requiring CLI updates
18
- - **Smaller Core** - Keep the main CLI lean by moving optional features to plugins
19
- - **Community Extensible** - Anyone can build and share plugins
20
-
21
- ## Using Plugins
22
-
23
- ### Official Plugins
24
-
25
- #### Claude Code Integration (Built-in)
26
-
27
- Vizzly includes a built-in plugin for [Claude Code](https://claude.com/code), providing AI-powered visual testing workflows:
28
-
29
- **Installation via Claude Code:**
30
- ```
31
- /plugin marketplace add vizzly-testing/cli
32
- ```
33
-
34
- **Available Commands:**
35
- - `/vizzly:tdd-status` - Check TDD dashboard status with AI insights
36
- - `/vizzly:debug-diff <screenshot-name>` - Analyze visual failures with AI assistance
37
- - `/vizzly:suggest-screenshots` - Get framework-specific test coverage suggestions
38
- - `/vizzly:setup` - Interactive setup wizard for Vizzly configuration
39
-
40
- The plugin automatically detects whether you're in local TDD mode or working with cloud builds, providing contextual help for your workflow.
41
-
42
- **Features:**
43
- - MCP (Model Context Protocol) server for tool integration
44
- - 15+ specialized tools for local TDD and cloud API workflows
45
- - Intelligent context detection and mode switching
46
- - Image analysis without API errors (safe baseline/current image handling)
47
-
48
- **Location:** `.claude-plugin/` directory in the repository
49
-
50
- #### Other Official Plugins
51
-
52
- Official Vizzly plugins are published under the `@vizzly-testing/*` scope and are automatically
53
- discovered:
54
-
55
- ```bash
56
- # Install plugin
57
- npm install @vizzly-testing/storybook
58
-
59
- # Use immediately - no configuration needed!
60
- vizzly storybook ./storybook-static
61
-
62
- # Plugin commands appear in help
63
- vizzly --help
64
- ```
65
-
66
- ### Community Plugins
67
-
68
- You can use community plugins or your own local plugins by configuring them explicitly:
69
-
70
- ```javascript
71
- // vizzly.config.js
72
- export default {
73
- plugins: [
74
- './my-custom-plugin.js', // Local file path
75
- 'npm-package-name', // npm package name
76
- ],
77
- };
78
- ```
79
-
80
- This is useful for:
81
- - Local plugin development and testing
82
- - Private/internal company plugins
83
- - Community plugins not in the `@vizzly-testing` scope
84
- - Custom workflow automation
85
-
86
- ## Creating a Plugin
87
-
88
- ### Basic Plugin Structure
89
-
90
- A plugin is a JavaScript module that exports an object with `name` and a `register` function:
91
-
92
- ```javascript
93
- // my-plugin.js
94
- export default {
95
- name: 'my-plugin',
96
- version: '1.0.0', // Optional but recommended
97
-
98
- register(program, { config, output, services }) {
99
- // Register your command with Commander.js
100
- program
101
- .command('my-command <arg>')
102
- .description('Description of my command')
103
- .option('--option <value>', 'An option')
104
- .action(async (arg, options) => {
105
- output.info(`Running my-command with ${arg}`);
106
-
107
- // Access shared services directly
108
- let apiService = services.apiService;
109
-
110
- // Your command logic here
111
- });
112
- }
113
- };
114
- ```
115
-
116
- ### Plugin Interface
117
-
118
- #### Required Fields
119
-
120
- - **`name`** (string) - Unique identifier for your plugin
121
- - **`register`** (function) - Called during CLI initialization to register commands
122
-
123
- #### Optional Fields
124
-
125
- - **`version`** (string) - Plugin version (recommended for debugging and compatibility)
126
-
127
- #### Register Function Parameters
128
-
129
- The `register` function receives two arguments:
130
-
131
- 1. **`program`** - [Commander.js](https://github.com/tj/commander.js) program instance for registering commands
132
- 2. **`context`** - Object containing:
133
- - `config` - Merged Vizzly configuration object
134
- - `output` - Unified output module with `.debug()`, `.info()`, `.warn()`, `.error()`, `.success()` methods
135
- - `services` - Service container with access to internal Vizzly services
136
-
137
- ### Available Services (Stable API)
138
-
139
- The `services` object provides a stable API for plugins. Only these services and methods are
140
- guaranteed to remain stable across minor versions:
141
-
142
- #### `services.testRunner`
143
-
144
- Manages build lifecycle and emits events:
145
-
146
- - **`once(event, callback)`** - Listen for a single event emission
147
- - **`on(event, callback)`** - Subscribe to events
148
- - **`off(event, callback)`** - Unsubscribe from events
149
- - **`createBuild(options, isTddMode)`** - Create a new build, returns `Promise<buildId>`
150
- - **`finalizeBuild(buildId, isTddMode, success, executionTime)`** - Finalize a build
151
-
152
- Events emitted:
153
- - `build-created` - Emitted with `{ url }` when a build is created
154
-
155
- #### `services.serverManager`
156
-
157
- Controls the screenshot capture server:
158
-
159
- - **`start(buildId, tddMode, setBaseline)`** - Start the screenshot server
160
- - **`stop()`** - Stop the screenshot server
161
-
162
- Example accessing services:
163
-
164
- ```javascript
165
- register(program, { config, output, services }) {
166
- program
167
- .command('capture')
168
- .description('Capture screenshots with custom workflow')
169
- .action(async () => {
170
- let { testRunner, serverManager } = services;
171
-
172
- // Listen for build creation
173
- testRunner.once('build-created', ({ url }) => {
174
- output.info(`Build created: ${url}`);
175
- });
176
-
177
- // Create build and start server
178
- let buildId = await testRunner.createBuild({ buildName: 'Custom' }, false);
179
- await serverManager.start(buildId, false, false);
180
-
181
- // ... capture screenshots ...
182
-
183
- // Finalize and cleanup
184
- await testRunner.finalizeBuild(buildId, false, true, Date.now());
185
- await serverManager.stop();
186
- });
187
- }
188
- ```
189
-
190
- ## Local Plugin Development
191
-
192
- ### Setup
193
-
194
- 1. Create your plugin file:
195
-
196
- ```bash
197
- mkdir -p plugins
198
- touch plugins/my-plugin.js
199
- ```
200
-
201
- 2. Write your plugin:
202
-
203
- ```javascript
204
- // plugins/my-plugin.js
205
- export default {
206
- name: 'my-plugin',
207
- version: '1.0.0',
208
- register(program, { config, output }) {
209
- program
210
- .command('greet <name>')
211
- .description('Greet someone')
212
- .action((name) => {
213
- output.info(`Hello, ${name}!`);
214
- });
215
- }
216
- };
217
- ```
218
-
219
- 3. Configure Vizzly to load your plugin:
220
-
221
- ```javascript
222
- // vizzly.config.js
223
- export default {
224
- plugins: ['./plugins/my-plugin.js'],
225
- };
226
- ```
227
-
228
- 4. Test your plugin:
229
-
230
- ```bash
231
- vizzly --help # See your command listed
232
- vizzly greet World # Test your command
233
- ```
234
-
235
- ### Package Structure (For Distribution)
236
-
237
- If you want to share your plugin via npm:
238
-
239
- ```
240
- my-vizzly-plugin/
241
- ├── package.json
242
- ├── plugin.js # Main plugin file
243
- ├── lib/ # Plugin implementation
244
- ├── README.md
245
- └── tests/
246
- ```
247
-
248
- Add a `vizzly.plugin` field to your `package.json`:
249
-
250
- ```json
251
- {
252
- "name": "vizzly-plugin-custom",
253
- "version": "1.0.0",
254
- "description": "My custom Vizzly plugin",
255
- "main": "./lib/index.js",
256
- "vizzly": {
257
- "plugin": "./plugin.js"
258
- },
259
- "keywords": ["vizzly", "vizzly-plugin"],
260
- "peerDependencies": {
261
- "@vizzly-testing/cli": "^0.9.0"
262
- }
263
- }
264
- ```
265
-
266
- Users can then install and use your plugin:
267
-
268
- ```bash
269
- npm install vizzly-plugin-custom
270
- ```
271
-
272
- ```javascript
273
- // vizzly.config.js
274
- export default {
275
- plugins: ['vizzly-plugin-custom'],
276
- };
277
- ```
278
-
279
- ## Best Practices
280
-
281
- ### Error Handling
282
-
283
- Always handle errors gracefully and provide helpful error messages:
284
-
285
- ```javascript
286
- register(program, { output }) {
287
- program
288
- .command('process <file>')
289
- .action(async (file) => {
290
- try {
291
- if (!existsSync(file)) {
292
- output.error(`File not found: ${file}`);
293
- process.exit(1);
294
- }
295
- // Process file...
296
- } catch (error) {
297
- output.error(`Failed to process file: ${error.message}`);
298
- process.exit(1);
299
- }
300
- });
301
- }
302
- ```
303
-
304
- ### Output
305
-
306
- Use the provided output module for consistent CLI output:
307
-
308
- ```javascript
309
- output.debug('Detailed debug info'); // Only shown with --verbose (stderr)
310
- output.info('Normal information'); // Info messages (stdout)
311
- output.success('Completed!'); // Success messages (stdout)
312
- output.warn('Warning message'); // Warning messages (stderr)
313
- output.error('Error message'); // Error messages (stderr)
314
- ```
315
-
316
- ### Async Operations
317
-
318
- Use async/await for asynchronous operations:
319
-
320
- ```javascript
321
- .action(async (options) => {
322
- let { testRunner } = services;
323
- let buildId = await testRunner.createBuild({ buildName: 'Test' }, false);
324
- output.info(`Created build: ${buildId}`);
325
- });
326
- ```
327
-
328
- ### Command Naming
329
-
330
- Choose clear, descriptive command names that don't conflict with core commands:
331
-
332
- ✅ **Good command names:**
333
- - `vizzly storybook`
334
- - `vizzly import-chromatic`
335
- - `vizzly generate-report`
336
-
337
- ❌ **Avoid these (conflicts with core):**
338
- - `vizzly run`
339
- - `vizzly upload`
340
- - `vizzly init`
341
- - `vizzly tdd`
342
-
343
- ### Input Validation
344
-
345
- Validate user input and provide helpful error messages:
346
-
347
- ```javascript
348
- .action(async (path, options) => {
349
- if (!path) {
350
- output.error('Path is required');
351
- process.exit(1);
352
- }
353
-
354
- if (!existsSync(path)) {
355
- output.error(`Path not found: ${path}`);
356
- output.info('Please provide a valid path to your build directory');
357
- process.exit(1);
358
- }
359
-
360
- // Continue with logic
361
- });
362
- ```
363
-
364
- ### Lazy Loading
365
-
366
- Import heavy dependencies only when needed to keep CLI startup fast:
367
-
368
- ```javascript
369
- register(program, { output }) {
370
- program
371
- .command('process-images <dir>')
372
- .action(async (dir) => {
373
- // Only import when command runs
374
- let { processImages } = await import('./heavy-dependency.js');
375
- await processImages(dir);
376
- });
377
- }
378
- ```
379
-
380
- ## Examples
381
-
382
- ### Simple Command Plugin
383
-
384
- ```javascript
385
- export default {
386
- name: 'hello',
387
- version: '1.0.0',
388
- register(program, { output }) {
389
- program
390
- .command('hello <name>')
391
- .description('Say hello')
392
- .option('-l, --loud', 'Say it loudly')
393
- .action((name, options) => {
394
- let greeting = `Hello, ${name}!`;
395
- if (options.loud) {
396
- greeting = greeting.toUpperCase();
397
- }
398
- output.info(greeting);
399
- });
400
- }
401
- };
402
- ```
403
-
404
- ### Screenshot Capture Plugin
405
-
406
- ```javascript
407
- export default {
408
- name: 'storybook',
409
- version: '1.0.0',
410
- register(program, { config, output, services }) {
411
- program
412
- .command('storybook <path>')
413
- .description('Capture screenshots from Storybook build')
414
- .option('--viewports <list>', 'Comma-separated viewports', '1280x720')
415
- .action(async (path, options) => {
416
- let { testRunner, serverManager } = services;
417
- let startTime = Date.now();
418
-
419
- // Create build and start server
420
- let buildId = await testRunner.createBuild({ buildName: 'Storybook' }, false);
421
- await serverManager.start(buildId, false, false);
422
-
423
- output.info(`Crawling Storybook at ${path}`);
424
-
425
- // Import dependencies lazily
426
- let { crawlStorybook } = await import('./crawler.js');
427
-
428
- // Capture screenshots (uses vizzlyScreenshot internally)
429
- await crawlStorybook(path, {
430
- viewports: options.viewports.split(','),
431
- });
432
-
433
- // Finalize build
434
- let executionTime = Date.now() - startTime;
435
- await testRunner.finalizeBuild(buildId, false, true, executionTime);
436
- await serverManager.stop();
437
-
438
- output.success('Upload complete!');
439
- });
440
- }
441
- };
442
- ```
443
-
444
- ### Multi-Command Plugin
445
-
446
- ```javascript
447
- export default {
448
- name: 'reports',
449
- version: '1.0.0',
450
- register(program, { output }) {
451
- let reports = program
452
- .command('reports')
453
- .description('Report generation commands');
454
-
455
- reports
456
- .command('generate')
457
- .description('Generate a new report')
458
- .action(() => {
459
- output.info('Generating report...');
460
- });
461
-
462
- reports
463
- .command('list')
464
- .description('List all reports')
465
- .action(() => {
466
- output.info('Listing reports...');
467
- });
468
- }
469
- };
470
- ```
471
-
472
- ## Troubleshooting
473
-
474
- ### Plugin Not Loading
475
-
476
- **Check plugin configuration:**
477
-
478
- ```bash
479
- vizzly --verbose --help
480
- ```
481
-
482
- This will show debug output about plugin loading.
483
-
484
- **Common issues:**
485
- - File path is incorrect (should be relative to `vizzly.config.js`)
486
- - Plugin file has syntax errors
487
- - Missing `export default` statement
488
-
489
- ### Plugin Command Not Showing
490
-
491
- **Verify plugin loaded successfully:**
492
-
493
- ```bash
494
- vizzly --verbose --help 2>&1 | grep -i plugin
495
- ```
496
-
497
- **Common issues:**
498
- - Missing `name` or `register` function
499
- - Command name conflicts with existing commands
500
- - Plugin threw an error during registration
501
-
502
- ### Type Errors in Editor
503
-
504
- If you're using TypeScript or want better IDE support, you can add JSDoc types:
505
-
506
- ```javascript
507
- /**
508
- * @param {import('commander').Command} program
509
- * @param {Object} context
510
- * @param {Object} context.config
511
- * @param {Object} context.output
512
- * @param {Object} context.services
513
- */
514
- function register(program, { config, output, services }) {
515
- // Your plugin code with full autocomplete!
516
- }
517
-
518
- export default {
519
- name: 'my-plugin',
520
- register,
521
- };
522
- ```
523
-
524
- ## Contributing a Plugin
525
-
526
- ### Share Your Plugin
527
-
528
- Built a useful plugin? We'd love to feature it! Here's how to share:
529
-
530
- 1. **Publish to npm** (optional but recommended for reusability)
531
- 2. **Add documentation** - Include a clear README with usage examples
532
- 3. **Open an issue** on the [Vizzly CLI repository](https://github.com/vizzly-testing/cli/issues) with:
533
- - Plugin name and description
534
- - Link to repository or npm package
535
- - Usage example
536
- - Screenshots/demo if applicable
537
-
538
- ### Plugin Ideas
539
-
540
- Here are some plugin ideas the community might find useful:
541
-
542
- - **Playwright integration** - Automated screenshot capture from Playwright tests
543
- - **Cypress integration** - Screenshot capture from Cypress tests
544
- - **Percy migration** - Import screenshots from Percy
545
- - **Chromatic migration** - Import screenshots from Chromatic
546
- - **Figma comparison** - Compare designs with Figma files
547
- - **Image optimization** - Compress screenshots before upload
548
- - **Custom reporters** - Generate custom HTML/PDF reports
549
- - **CI/CD integrations** - Specialized workflows for different CI platforms
550
-
551
- ## Support
552
-
553
- Need help building a plugin?
554
-
555
- - 📖 [View example plugin source](https://github.com/vizzly-testing/cli/tree/main/examples/custom-plugin)
556
- - 🐛 [Report issues](https://github.com/vizzly-testing/cli/issues)
557
- - 📧 [Email support](https://vizzly.dev/support/)