@vizzly-testing/cli 0.23.0 → 0.23.2
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.
- package/README.md +54 -586
- package/dist/api/client.js +3 -1
- package/dist/api/endpoints.js +6 -7
- package/dist/cli.js +15 -2
- package/dist/commands/finalize.js +12 -0
- package/dist/commands/preview.js +210 -28
- package/dist/commands/run.js +15 -0
- package/dist/commands/status.js +34 -8
- package/dist/commands/upload.js +13 -0
- package/dist/reporter/reporter-bundle.iife.js +19 -19
- package/dist/utils/ci-env.js +114 -16
- package/package.json +1 -2
- package/claude-plugin/.claude-plugin/README.md +0 -270
- package/claude-plugin/.claude-plugin/marketplace.json +0 -28
- package/claude-plugin/.claude-plugin/plugin.json +0 -14
- package/claude-plugin/.mcp.json +0 -12
- package/claude-plugin/CHANGELOG.md +0 -85
- package/claude-plugin/commands/setup.md +0 -137
- package/claude-plugin/commands/suggest-screenshots.md +0 -111
- package/claude-plugin/mcp/vizzly-docs-server/README.md +0 -95
- package/claude-plugin/mcp/vizzly-docs-server/docs-fetcher.js +0 -110
- package/claude-plugin/mcp/vizzly-docs-server/index.js +0 -283
- package/claude-plugin/mcp/vizzly-server/cloud-api-provider.js +0 -399
- package/claude-plugin/mcp/vizzly-server/index.js +0 -927
- package/claude-plugin/mcp/vizzly-server/local-tdd-provider.js +0 -455
- package/claude-plugin/mcp/vizzly-server/token-resolver.js +0 -185
- package/claude-plugin/skills/check-visual-tests/SKILL.md +0 -158
- package/claude-plugin/skills/debug-visual-regression/SKILL.md +0 -269
- package/docs/api-reference.md +0 -1003
- package/docs/authentication.md +0 -334
- package/docs/doctor-command.md +0 -44
- package/docs/getting-started.md +0 -131
- package/docs/internal/SDK-API.md +0 -1018
- package/docs/plugins.md +0 -557
- package/docs/tdd-mode.md +0 -594
- package/docs/test-integration.md +0 -523
- package/docs/tui-elements.md +0 -560
- 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/)
|