@vizzly-testing/cli 0.32.0 → 0.34.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.
- package/README.md +81 -50
- package/dist/cli.js +10 -10
- package/dist/client/index.js +2 -1
- package/dist/commands/doctor.js +4 -4
- package/dist/commands/init.js +215 -3
- package/dist/commands/preview.js +3 -3
- package/dist/commands/run.js +1 -1
- package/dist/commands/tdd-daemon.js +1 -1
- package/dist/reporter/reporter-bundle.css +1 -1
- package/dist/reporter/reporter-bundle.iife.js +118 -105
- package/dist/reporter-ssr/ssr-entry.js +88 -88
- package/dist/services/static-report-generator.js +2 -2
- package/dist/tdd/tdd-service.js +14 -14
- package/dist/utils/colors.js +28 -45
- package/dist/utils/global-config.js +1 -1
- package/dist/utils/output.js +16 -16
- package/dist/utils/screenshot-options.js +1 -0
- package/docs/assets/vizzly-mascot-inspector.png +0 -0
- package/package.json +11 -8
- package/skills/vizzly/SKILL.md +99 -0
- package/skills/vizzly/agents/openai.yaml +4 -0
- package/skills/vizzly/references/cli-context.md +42 -0
- package/skills/vizzly/references/dynamic-content.md +44 -0
- package/skills/vizzly/references/public-screenshots.md +44 -0
- package/skills/vizzly/references/sdks.md +62 -0
- package/skills/vizzly/references/setup-ci.md +42 -0
package/dist/utils/colors.js
CHANGED
|
@@ -4,56 +4,47 @@
|
|
|
4
4
|
import { Ansis } from 'ansis';
|
|
5
5
|
|
|
6
6
|
// =============================================================================
|
|
7
|
-
// Vizzly
|
|
8
|
-
// Aligned with
|
|
7
|
+
// Vizzly BearDen Design System Colors
|
|
8
|
+
// Aligned with the reporter design system color tokens.
|
|
9
9
|
// =============================================================================
|
|
10
10
|
|
|
11
11
|
export let brand = {
|
|
12
|
-
// Primary brand color -
|
|
13
|
-
amber: '#
|
|
12
|
+
// Primary brand color - restrained brass on graphite
|
|
13
|
+
amber: '#D69A35',
|
|
14
14
|
// Primary brand, actions, highlights
|
|
15
|
-
amberLight: '#
|
|
15
|
+
amberLight: '#E0AD55',
|
|
16
16
|
// Hover states, emphasis
|
|
17
17
|
|
|
18
18
|
// Accent colors (semantic)
|
|
19
|
-
success: '#
|
|
19
|
+
success: '#7FD990',
|
|
20
20
|
// Approved, passed, active (--accent-success)
|
|
21
|
-
warning: '#
|
|
21
|
+
warning: '#DCAD5F',
|
|
22
22
|
// Pending, attention (--accent-warning)
|
|
23
|
-
danger: '#
|
|
23
|
+
danger: '#D77782',
|
|
24
24
|
// Rejected, failed, errors (--accent-danger)
|
|
25
|
-
info: '#
|
|
25
|
+
info: '#B7BDC6',
|
|
26
26
|
// Processing, informational (--accent-info)
|
|
27
27
|
|
|
28
28
|
// Surface colors (dark theme)
|
|
29
|
-
bg: '#
|
|
29
|
+
bg: '#07080A',
|
|
30
30
|
// Page background (--vz-bg)
|
|
31
|
-
surface: '#
|
|
31
|
+
surface: '#101216',
|
|
32
32
|
// Cards, panels (--vz-surface)
|
|
33
|
-
elevated: '#
|
|
33
|
+
elevated: '#111318',
|
|
34
34
|
// Dropdowns, modals (--vz-elevated)
|
|
35
|
-
border: '#
|
|
35
|
+
border: '#30343B',
|
|
36
36
|
// Primary borders (--vz-border)
|
|
37
|
-
borderSubtle: '#
|
|
37
|
+
borderSubtle: '#252930',
|
|
38
38
|
// Subtle dividers (--vz-border-subtle)
|
|
39
39
|
|
|
40
40
|
// Text hierarchy
|
|
41
|
-
textPrimary: '#
|
|
41
|
+
textPrimary: '#F4F6F8',
|
|
42
42
|
// Headings, important (--text-primary)
|
|
43
|
-
textSecondary: '#
|
|
43
|
+
textSecondary: '#C8CDD3',
|
|
44
44
|
// Body text (--text-secondary)
|
|
45
|
-
textTertiary: '#
|
|
45
|
+
textTertiary: '#A0A6AF',
|
|
46
46
|
// Captions, metadata (--text-tertiary)
|
|
47
|
-
textMuted: '#
|
|
48
|
-
// Disabled, placeholders (--text-muted)
|
|
49
|
-
|
|
50
|
-
// Legacy aliases (for backward compatibility)
|
|
51
|
-
green: '#10B981',
|
|
52
|
-
red: '#EF4444',
|
|
53
|
-
cyan: '#06B6D4',
|
|
54
|
-
// Still useful for links in terminals
|
|
55
|
-
slate: '#64748B',
|
|
56
|
-
dark: '#1E293B'
|
|
47
|
+
textMuted: '#7A828D' // Disabled, placeholders (--text-muted)
|
|
57
48
|
};
|
|
58
49
|
function supportsColorDefault() {
|
|
59
50
|
// Respect NO_COLOR: https://no-color.org/
|
|
@@ -124,7 +115,7 @@ export function createColors(options = {}) {
|
|
|
124
115
|
hex: () => noop,
|
|
125
116
|
bgRgb: () => noop,
|
|
126
117
|
bgHex: () => noop,
|
|
127
|
-
//
|
|
118
|
+
// BearDen brand colors (noop versions)
|
|
128
119
|
brand: {
|
|
129
120
|
// Primary
|
|
130
121
|
amber: noop,
|
|
@@ -133,6 +124,7 @@ export function createColors(options = {}) {
|
|
|
133
124
|
success: noop,
|
|
134
125
|
warning: noop,
|
|
135
126
|
danger: noop,
|
|
127
|
+
error: noop,
|
|
136
128
|
info: noop,
|
|
137
129
|
// Text hierarchy
|
|
138
130
|
textPrimary: noop,
|
|
@@ -144,12 +136,7 @@ export function createColors(options = {}) {
|
|
|
144
136
|
bgSuccess: noop,
|
|
145
137
|
bgWarning: noop,
|
|
146
138
|
bgDanger: noop,
|
|
147
|
-
bgInfo: noop
|
|
148
|
-
// Legacy aliases
|
|
149
|
-
green: noop,
|
|
150
|
-
red: noop,
|
|
151
|
-
cyan: noop,
|
|
152
|
-
slate: noop
|
|
139
|
+
bgInfo: noop
|
|
153
140
|
}
|
|
154
141
|
};
|
|
155
142
|
}
|
|
@@ -173,16 +160,16 @@ export function createColors(options = {}) {
|
|
|
173
160
|
gray: colors.gray,
|
|
174
161
|
black: colors.black,
|
|
175
162
|
// Semantic aliases (basic)
|
|
176
|
-
success: colors.
|
|
177
|
-
error: colors.
|
|
178
|
-
warning: colors.
|
|
179
|
-
info: colors.
|
|
163
|
+
success: colors.hex(brand.success),
|
|
164
|
+
error: colors.hex(brand.danger),
|
|
165
|
+
warning: colors.hex(brand.warning),
|
|
166
|
+
info: colors.hex(brand.info),
|
|
180
167
|
// Extended colors for rich styling
|
|
181
168
|
rgb: colors.rgb.bind(colors),
|
|
182
169
|
hex: colors.hex.bind(colors),
|
|
183
170
|
bgRgb: colors.bgRgb.bind(colors),
|
|
184
171
|
bgHex: colors.bgHex.bind(colors),
|
|
185
|
-
//
|
|
172
|
+
// BearDen brand colors (Truecolor) - aligned with design system
|
|
186
173
|
brand: {
|
|
187
174
|
// Primary brand color
|
|
188
175
|
amber: colors.hex(brand.amber),
|
|
@@ -191,6 +178,7 @@ export function createColors(options = {}) {
|
|
|
191
178
|
success: colors.hex(brand.success),
|
|
192
179
|
warning: colors.hex(brand.warning),
|
|
193
180
|
danger: colors.hex(brand.danger),
|
|
181
|
+
error: colors.hex(brand.danger),
|
|
194
182
|
info: colors.hex(brand.info),
|
|
195
183
|
// Text hierarchy
|
|
196
184
|
textPrimary: colors.hex(brand.textPrimary),
|
|
@@ -202,12 +190,7 @@ export function createColors(options = {}) {
|
|
|
202
190
|
bgSuccess: colors.bgHex(brand.success),
|
|
203
191
|
bgWarning: colors.bgHex(brand.warning),
|
|
204
192
|
bgDanger: colors.bgHex(brand.danger),
|
|
205
|
-
bgInfo: colors.bgHex(brand.info)
|
|
206
|
-
// Legacy aliases (backward compatibility)
|
|
207
|
-
green: colors.hex(brand.green),
|
|
208
|
-
red: colors.hex(brand.red),
|
|
209
|
-
cyan: colors.hex(brand.cyan),
|
|
210
|
-
slate: colors.hex(brand.slate)
|
|
193
|
+
bgInfo: colors.bgHex(brand.info)
|
|
211
194
|
}
|
|
212
195
|
};
|
|
213
196
|
}
|
|
@@ -121,7 +121,7 @@ export async function clearGlobalConfig() {
|
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* Save user's PATH for menubar app to use
|
|
124
|
-
* This auto-configures the menubar app so it can find
|
|
124
|
+
* This auto-configures the menubar app so it can find package runners/node
|
|
125
125
|
* @returns {Promise<void>}
|
|
126
126
|
*/
|
|
127
127
|
export async function saveUserPath() {
|
package/dist/utils/output.js
CHANGED
|
@@ -235,7 +235,7 @@ export function isVerbose() {
|
|
|
235
235
|
|
|
236
236
|
/**
|
|
237
237
|
* Show command header with distinctive branding
|
|
238
|
-
* Uses
|
|
238
|
+
* Uses BearDen's signature amber color for "vizzly"
|
|
239
239
|
* Only shows once per command execution
|
|
240
240
|
* @param {string} command - Command name (e.g., 'tdd', 'run')
|
|
241
241
|
* @param {string} [mode] - Optional mode (e.g., 'local', 'cloud')
|
|
@@ -245,7 +245,7 @@ export function header(command, mode = null) {
|
|
|
245
245
|
headerShown = true;
|
|
246
246
|
let parts = [];
|
|
247
247
|
|
|
248
|
-
// Brand "vizzly" with
|
|
248
|
+
// Brand "vizzly" with BearDen's signature amber
|
|
249
249
|
parts.push(colors.brand.amber(colors.bold('vizzly')));
|
|
250
250
|
|
|
251
251
|
// Command in info blue (processing, active)
|
|
@@ -289,7 +289,7 @@ export function success(message, data = {}) {
|
|
|
289
289
|
}));
|
|
290
290
|
} else {
|
|
291
291
|
console.error('');
|
|
292
|
-
console.error(colors.
|
|
292
|
+
console.error(colors.success('✓'), message);
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
@@ -308,7 +308,7 @@ export function result(message) {
|
|
|
308
308
|
}));
|
|
309
309
|
} else {
|
|
310
310
|
console.error('');
|
|
311
|
-
console.error(colors.
|
|
311
|
+
console.error(colors.success('✓'), `${message} ${colors.dim(`· ${elapsed}`)}`);
|
|
312
312
|
}
|
|
313
313
|
}
|
|
314
314
|
|
|
@@ -325,7 +325,7 @@ export function info(message, data = {}) {
|
|
|
325
325
|
...data
|
|
326
326
|
}));
|
|
327
327
|
} else {
|
|
328
|
-
console.log(colors.
|
|
328
|
+
console.log(colors.info('ℹ'), message);
|
|
329
329
|
}
|
|
330
330
|
}
|
|
331
331
|
|
|
@@ -375,7 +375,7 @@ export function error(message, err = null, data = {}) {
|
|
|
375
375
|
}
|
|
376
376
|
console.error(JSON.stringify(errorData));
|
|
377
377
|
} else {
|
|
378
|
-
console.error(colors.
|
|
378
|
+
console.error(colors.error('✖'), message);
|
|
379
379
|
|
|
380
380
|
// Show error details
|
|
381
381
|
if (err instanceof Error) {
|
|
@@ -456,7 +456,7 @@ export function getJsonFields() {
|
|
|
456
456
|
|
|
457
457
|
/**
|
|
458
458
|
* Start a spinner with message
|
|
459
|
-
* Uses
|
|
459
|
+
* Uses BearDen amber for the spinner animation
|
|
460
460
|
*/
|
|
461
461
|
export function startSpinner(message) {
|
|
462
462
|
if (config.json || config.silent || !process.stderr.isTTY) return;
|
|
@@ -578,12 +578,12 @@ function formatData(data) {
|
|
|
578
578
|
*/
|
|
579
579
|
/**
|
|
580
580
|
* Get a distinctive color for a component name
|
|
581
|
-
* Uses
|
|
581
|
+
* Uses BearDen design system colors for consistent styling
|
|
582
582
|
* @param {string} component - Component name
|
|
583
583
|
* @returns {Function} Color function
|
|
584
584
|
*/
|
|
585
585
|
function getComponentColor(component) {
|
|
586
|
-
// Map components to
|
|
586
|
+
// Map components to BearDen semantic colors
|
|
587
587
|
let componentColors = {
|
|
588
588
|
// Server/infrastructure - success green (active, running)
|
|
589
589
|
server: colors.brand.success,
|
|
@@ -698,7 +698,7 @@ function writeLog(level, message, data = {}) {
|
|
|
698
698
|
/**
|
|
699
699
|
* Generate a visual diff bar with color coding
|
|
700
700
|
* Shows percentage as a filled/empty bar with color based on severity
|
|
701
|
-
* Uses
|
|
701
|
+
* Uses BearDen semantic colors (success → warning → danger)
|
|
702
702
|
* @param {number} percentage - Diff percentage (0-100)
|
|
703
703
|
* @param {number} [width=10] - Bar width in characters
|
|
704
704
|
* @returns {string} Colored diff bar string
|
|
@@ -716,7 +716,7 @@ export function diffBar(percentage, width = 10) {
|
|
|
716
716
|
if (percentage > 0 && filled === 0) filled = 1;
|
|
717
717
|
let empty = width - filled;
|
|
718
718
|
|
|
719
|
-
// Color based on severity using
|
|
719
|
+
// Color based on severity using BearDen semantic colors
|
|
720
720
|
let barColor;
|
|
721
721
|
if (percentage < 1) {
|
|
722
722
|
barColor = colors.brand.success; // Green - minimal change
|
|
@@ -733,7 +733,7 @@ export function diffBar(percentage, width = 10) {
|
|
|
733
733
|
/**
|
|
734
734
|
* Generate a gradient progress bar
|
|
735
735
|
* Creates a visually appealing progress indicator with color gradient
|
|
736
|
-
* Default gradient uses
|
|
736
|
+
* Default gradient uses BearDen amber → amber-light (signature brand gradient)
|
|
737
737
|
* @param {number} current - Current progress value
|
|
738
738
|
* @param {number} total - Total value
|
|
739
739
|
* @param {number} [width=20] - Bar width in characters
|
|
@@ -745,7 +745,7 @@ export function diffBar(percentage, width = 10) {
|
|
|
745
745
|
export function progressBar(current, total, width = 20, options = {}) {
|
|
746
746
|
if (config.json || config.silent) return '';
|
|
747
747
|
|
|
748
|
-
// Default to
|
|
748
|
+
// Default to BearDen's signature amber gradient
|
|
749
749
|
let {
|
|
750
750
|
from = '#F59E0B',
|
|
751
751
|
to = '#FBBF24'
|
|
@@ -791,7 +791,7 @@ function hexToRgb(hex) {
|
|
|
791
791
|
|
|
792
792
|
/**
|
|
793
793
|
* Create a colored badge/pill for status indicators
|
|
794
|
-
* Uses
|
|
794
|
+
* Uses BearDen semantic colors for consistent meaning
|
|
795
795
|
* @param {string} text - Badge text
|
|
796
796
|
* @param {string} [type='info'] - Badge type: 'success', 'warning', 'error', 'info'
|
|
797
797
|
* @returns {string} Formatted badge string
|
|
@@ -826,7 +826,7 @@ export function badge(text, type = 'info') {
|
|
|
826
826
|
|
|
827
827
|
/**
|
|
828
828
|
* Create a colored status dot
|
|
829
|
-
* Uses
|
|
829
|
+
* Uses BearDen semantic colors for consistent meaning
|
|
830
830
|
* @param {string} [status='info'] - Status type: 'success', 'warning', 'error', 'info'
|
|
831
831
|
* @returns {string} Colored dot character
|
|
832
832
|
*/
|
|
@@ -1033,7 +1033,7 @@ export function box(content, options = {}) {
|
|
|
1033
1033
|
innerWidth = Math.max(innerWidth, titleWidth);
|
|
1034
1034
|
}
|
|
1035
1035
|
|
|
1036
|
-
// Border styling - use
|
|
1036
|
+
// Border styling - use BearDen amber for 'branded' style
|
|
1037
1037
|
let border = borderColor || (style === 'branded' ? colors.brand.amber : colors.dim);
|
|
1038
1038
|
let titleColor = style === 'branded' ? colors.bold : s => s;
|
|
1039
1039
|
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizzly-testing/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Visual
|
|
3
|
+
"version": "0.34.0",
|
|
4
|
+
"description": "Visual regression testing from your terminal",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"llm-context",
|
|
7
7
|
"visual-context",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"author": "Stubborn Mule Software <support@vizzly.dev>",
|
|
25
25
|
"type": "module",
|
|
26
|
+
"packageManager": "pnpm@11.3.0",
|
|
26
27
|
"exports": {
|
|
27
28
|
".": {
|
|
28
29
|
"types": "./dist/types/index.d.ts",
|
|
@@ -53,13 +54,15 @@
|
|
|
53
54
|
"files": [
|
|
54
55
|
"bin",
|
|
55
56
|
"dist",
|
|
57
|
+
"docs/assets",
|
|
58
|
+
"skills",
|
|
56
59
|
"README.md",
|
|
57
60
|
"LICENSE"
|
|
58
61
|
],
|
|
59
62
|
"scripts": {
|
|
60
63
|
"cli": "source .envrc && node bin/vizzly.js",
|
|
61
64
|
"start": "node src/index.js",
|
|
62
|
-
"build": "
|
|
65
|
+
"build": "pnpm run clean && pnpm run compile && pnpm run build:reporter && pnpm run build:reporter-ssr && pnpm run copy-types",
|
|
63
66
|
"clean": "rimraf dist",
|
|
64
67
|
"compile": "babel src --out-dir dist --ignore '**/*.test.js'",
|
|
65
68
|
"copy-types": "mkdir -p dist/types && cp src/types/*.d.ts dist/types/",
|
|
@@ -67,12 +70,12 @@
|
|
|
67
70
|
"build:reporter-ssr": "cd src/reporter && vite build --config vite.ssr.config.js",
|
|
68
71
|
"dev:reporter": "cd src/reporter && vite --config vite.dev.config.js",
|
|
69
72
|
"test:types": "tsd",
|
|
70
|
-
"prepublishOnly": "
|
|
73
|
+
"prepublishOnly": "pnpm run build",
|
|
71
74
|
"test": "node --experimental-test-coverage --test --test-concurrency=1 --test-reporter=spec $(find tests -name '*.test.js')",
|
|
72
75
|
"test:watch": "node --test --test-reporter=spec --watch $(find tests -name '*.test.js')",
|
|
73
76
|
"test:reporter": "playwright test --config=tests/reporter/playwright.config.js",
|
|
74
|
-
"test:reporter:visual": "node bin/vizzly.js run \"
|
|
75
|
-
"test:swift:e2e": "
|
|
77
|
+
"test:reporter:visual": "node bin/vizzly.js tdd run \"pnpm run test:reporter\" --no-open",
|
|
78
|
+
"test:swift:e2e": "pnpm run build && node clients/swift/scripts/run-e2e.js",
|
|
76
79
|
"test:tui": "node --test --test-reporter=spec tests/tui/*.test.js",
|
|
77
80
|
"test:tui:docker": "./tests/tui/run-tui-tests.sh",
|
|
78
81
|
"smoke:prod:pack": "node scripts/smoke-prod-pack.js",
|
|
@@ -80,7 +83,7 @@
|
|
|
80
83
|
"lint:fix": "biome check --write --unsafe src tests clients/storybook/src clients/storybook/tests clients/static-site/src clients/static-site/tests clients/vitest/src clients/vitest/tests clients/ember/src clients/ember/tests clients/ember/bin",
|
|
81
84
|
"format": "biome format --write src tests clients/storybook/src clients/storybook/tests clients/static-site/src clients/static-site/tests clients/vitest/src clients/vitest/tests clients/ember/src clients/ember/tests clients/ember/bin",
|
|
82
85
|
"format:check": "biome format src tests clients/storybook/src clients/storybook/tests clients/static-site/src clients/static-site/tests clients/vitest/src clients/vitest/tests clients/ember/src clients/ember/tests clients/ember/bin",
|
|
83
|
-
"fix": "
|
|
86
|
+
"fix": "pnpm run format && pnpm run lint:fix"
|
|
84
87
|
},
|
|
85
88
|
"engines": {
|
|
86
89
|
"node": ">=22.0.0"
|
|
@@ -90,6 +93,7 @@
|
|
|
90
93
|
"registry": "https://registry.npmjs.org/"
|
|
91
94
|
},
|
|
92
95
|
"dependencies": {
|
|
96
|
+
"@vizzly-testing/bear-den": "0.1.2",
|
|
93
97
|
"@vizzly-testing/honeydiff": "^0.10.3",
|
|
94
98
|
"ansis": "^4.2.0",
|
|
95
99
|
"commander": "^14.0.0",
|
|
@@ -125,7 +129,6 @@
|
|
|
125
129
|
"@tanstack/react-query": "^5.90.11",
|
|
126
130
|
"@types/node": "^25.0.2",
|
|
127
131
|
"@vitejs/plugin-react": "^6.0.1",
|
|
128
|
-
"@vizzly-testing/observatory": "^0.3.3",
|
|
129
132
|
"autoprefixer": "^10.4.21",
|
|
130
133
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
131
134
|
"babel-plugin-transform-remove-console": "^6.9.4",
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vizzly
|
|
3
|
+
description: "Use when a repo has Vizzly configured and you need screenshot memory or visual history: before/after UI changes, visual regression review, screenshot history, approved baselines, diffs, dynamic regions, docs/manual images, public screenshots, or Vizzly builds. Teaches agents to use Vizzly CLI/context for local TDD, cloud builds, review state, comments, hotspots, previews, and SDK capture patterns."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Vizzly
|
|
7
|
+
|
|
8
|
+
Vizzly is the project's screenshot memory database. It stores approved baselines, current screenshots, diffs, review state, comments, hotspots, previews, and public screenshot URLs.
|
|
9
|
+
|
|
10
|
+
Use Vizzly when you need to understand what the UI looked like before, what changed, what humans already reviewed, or which screenshots already exist. Browser automation is still useful for interacting with a live app; Vizzly is usually the faster first stop for visual history.
|
|
11
|
+
|
|
12
|
+
## First Instinct
|
|
13
|
+
|
|
14
|
+
Before changing UI, check whether Vizzly already has local screenshot context:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
vizzly context build current --source local --agent
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
If a task names a screen, component, or screenshot, inspect that screenshot's history before changing thresholds or re-capturing blindly:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
vizzly context screenshot "<screenshot-name>" --source local --json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
When you make or verify UI changes, run the focused user workflow that owns the surface:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
vizzly tdd run "<test command>" --no-open
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Then inspect what changed:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
vizzly context build current --source local --agent --json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For specific evidence, drill in:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
vizzly context comparison <comparison-id> --json
|
|
42
|
+
vizzly context screenshot "<screenshot-name>" --json
|
|
43
|
+
vizzly context review-queue --json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If local context is unavailable and the project uses cloud builds, use the build id from CI or CLI output:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
vizzly context build <build-id> --agent --json --include diffs,comments
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## What Vizzly Knows
|
|
53
|
+
|
|
54
|
+
- **Approved baselines**: expected UI.
|
|
55
|
+
- **Current screenshots**: what the latest run rendered.
|
|
56
|
+
- **Diffs**: where pixels/layout/content changed.
|
|
57
|
+
- **Review state and comments**: human context attached to builds and screenshots.
|
|
58
|
+
- **Hotspots and confirmed regions**: known dynamic areas.
|
|
59
|
+
- **Preview links**: static or deployed UI context for a build.
|
|
60
|
+
- **Public screenshots**: stable URLs for documentation and manuals.
|
|
61
|
+
|
|
62
|
+
## Acting On Visual Context
|
|
63
|
+
|
|
64
|
+
- Treat approved baselines as visual truth.
|
|
65
|
+
- Treat diffs as evidence, not as approval instructions.
|
|
66
|
+
- Do not approve or reject visual changes unless the user explicitly asks.
|
|
67
|
+
- Prefer existing E2E or user journeys over narrow screenshot-only specs.
|
|
68
|
+
- For dynamic content, inspect screenshot context before changing thresholds.
|
|
69
|
+
- Prefer deterministic test data, per-screenshot `threshold`, per-screenshot `minClusterSize`, hotspots, or confirmed regions over global tolerance changes.
|
|
70
|
+
- Report visual findings with screenshot names, build/comparison links when available, and the command you ran.
|
|
71
|
+
|
|
72
|
+
## Capturing Screenshots
|
|
73
|
+
|
|
74
|
+
Use the existing integration when one is present. For direct JavaScript capture:
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
import { vizzlyScreenshot } from '@vizzly-testing/cli/client';
|
|
78
|
+
|
|
79
|
+
let screenshot = await page.screenshot();
|
|
80
|
+
await vizzlyScreenshot('checkout-form', screenshot, {
|
|
81
|
+
properties: {
|
|
82
|
+
browser: 'chromium',
|
|
83
|
+
viewport: 'desktop',
|
|
84
|
+
state: 'valid-card'
|
|
85
|
+
},
|
|
86
|
+
threshold: 2,
|
|
87
|
+
minClusterSize: 4
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Use `properties` to separate variants such as theme, locale, viewport, role, state, component, page, or docs/manual grouping.
|
|
92
|
+
|
|
93
|
+
## When You Need More Detail
|
|
94
|
+
|
|
95
|
+
- For SDK examples and capture patterns, read `references/sdks.md`.
|
|
96
|
+
- For CLI/context commands and JSON output, read `references/cli-context.md`.
|
|
97
|
+
- For dynamic content, thresholds, and hotspots, read `references/dynamic-content.md`.
|
|
98
|
+
- For public screenshot URLs and docs/manual images, read `references/public-screenshots.md`.
|
|
99
|
+
- For project setup and CI, read `references/setup-ci.md`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# CLI And Context
|
|
2
|
+
|
|
3
|
+
Use these commands to gather Vizzly evidence before making UI assumptions.
|
|
4
|
+
|
|
5
|
+
## Local TDD
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
vizzly tdd start
|
|
9
|
+
vizzly tdd run "<test command>" --no-open
|
|
10
|
+
vizzly context build current --source local --agent
|
|
11
|
+
vizzly context build current --source local --agent --json
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Local context reads `.vizzly` state and does not require cloud auth.
|
|
15
|
+
|
|
16
|
+
## Cloud Builds
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
export VIZZLY_TOKEN="project-token"
|
|
20
|
+
vizzly run "<test command>" --wait --json
|
|
21
|
+
vizzly context build <build-id> --agent --json --include diffs,comments
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`vizzly run --wait --json` returns a `contextCommand` when a cloud build is created. Prefer that command over constructing URLs by hand.
|
|
25
|
+
|
|
26
|
+
## Drilldowns
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
vizzly context comparison <comparison-id> --json
|
|
30
|
+
vizzly context screenshot "<screenshot-name>" --json
|
|
31
|
+
vizzly context similar <fingerprint-hash> --json
|
|
32
|
+
vizzly context review-queue --json
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Use comparison context for one diff. Use screenshot context for history and recurring dynamic areas. Use review queue context when triaging unresolved visual work.
|
|
36
|
+
|
|
37
|
+
## Good Agent Behavior
|
|
38
|
+
|
|
39
|
+
- Use `--json` for automation and summaries.
|
|
40
|
+
- Use `--agent` when building prompt context or asking another agent to continue.
|
|
41
|
+
- Keep human-readable command output in final summaries only when it changes the user's next action.
|
|
42
|
+
- Do not approve/reject unless explicitly asked.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Dynamic Content
|
|
2
|
+
|
|
3
|
+
Dynamic content is common: dates, calendars, generated images, avatars, timers, randomized data, responsive text, and API-backed content.
|
|
4
|
+
|
|
5
|
+
## Order Of Operations
|
|
6
|
+
|
|
7
|
+
1. Make test data deterministic when the changing content is not what you are testing.
|
|
8
|
+
2. Inspect screenshot context before changing code:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
vizzly context screenshot "<screenshot-name>" --json
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
3. Use per-screenshot tolerances for local noise:
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
await vizzlyScreenshot('plant-calendar', screenshot, {
|
|
18
|
+
properties: { surface: 'calendar' },
|
|
19
|
+
threshold: 4,
|
|
20
|
+
minClusterSize: 12
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
4. Use hotspots or confirmed regions for recurring valid dynamic regions.
|
|
25
|
+
|
|
26
|
+
## Avoid
|
|
27
|
+
|
|
28
|
+
- Raising global project thresholds for one dynamic area.
|
|
29
|
+
- Masking a whole page when a small region changes.
|
|
30
|
+
- Treating every daily diff as product breakage.
|
|
31
|
+
- Ignoring structural changes because a region is known to be dynamic.
|
|
32
|
+
|
|
33
|
+
## How To Explain Findings
|
|
34
|
+
|
|
35
|
+
Say whether the diff looks like:
|
|
36
|
+
|
|
37
|
+
- expected dynamic content
|
|
38
|
+
- deterministic fixture drift
|
|
39
|
+
- real content disappearance
|
|
40
|
+
- layout shift
|
|
41
|
+
- screenshot timing/capture instability
|
|
42
|
+
- baseline mismatch
|
|
43
|
+
|
|
44
|
+
Then name the screenshot and include the relevant context command or link.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Public Screenshots
|
|
2
|
+
|
|
3
|
+
Public screenshots are Vizzly's path for stable image URLs in docs and manuals.
|
|
4
|
+
|
|
5
|
+
Use this when a user asks for hotlinked UI screenshots, generated manual images, docs that stay current with UI, or CDN-like screenshot URLs.
|
|
6
|
+
|
|
7
|
+
## Mental Model
|
|
8
|
+
|
|
9
|
+
Do not use arbitrary build screenshot URLs as stable docs assets. Use Public Properties.
|
|
10
|
+
|
|
11
|
+
The flow:
|
|
12
|
+
|
|
13
|
+
1. Capture screenshots with stable metadata.
|
|
14
|
+
2. Configure project Public Properties in Vizzly.
|
|
15
|
+
3. Approve/publish the baseline build.
|
|
16
|
+
4. Use the Public URLs tab to copy the stable URL.
|
|
17
|
+
|
|
18
|
+
Example capture:
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
await vizzlyScreenshot('watering-widget', screenshot, {
|
|
22
|
+
properties: {
|
|
23
|
+
manual: 'plant-care',
|
|
24
|
+
component: 'watering-widget',
|
|
25
|
+
viewport: 'desktop'
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Configure a Public Property like `manual=plant-care`. Vizzly publishes matching approved baseline screenshots and keeps stable URLs for each screenshot/property identity.
|
|
31
|
+
|
|
32
|
+
## Good Uses
|
|
33
|
+
|
|
34
|
+
- Product manuals
|
|
35
|
+
- User docs
|
|
36
|
+
- Component catalogs
|
|
37
|
+
- In-app UI examples
|
|
38
|
+
- Screenshots that should update when approved UI changes
|
|
39
|
+
|
|
40
|
+
## Cautions
|
|
41
|
+
|
|
42
|
+
- Public screenshots are public. Do not publish private user data, secrets, or internal-only UI.
|
|
43
|
+
- A new unapproved build does not automatically become the public docs image.
|
|
44
|
+
- Use stable names and properties so URLs do not churn.
|