@vizzly-testing/cli 0.3.2 → 0.5.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 +50 -28
- package/dist/cli.js +34 -30
- package/dist/client/index.js +1 -1
- package/dist/commands/run.js +38 -11
- package/dist/commands/tdd.js +30 -18
- package/dist/commands/upload.js +56 -5
- package/dist/server/handlers/api-handler.js +83 -0
- package/dist/server/handlers/tdd-handler.js +138 -0
- package/dist/server/http-server.js +132 -0
- package/dist/services/api-service.js +22 -2
- package/dist/services/server-manager.js +45 -29
- package/dist/services/test-runner.js +66 -69
- package/dist/services/uploader.js +11 -4
- package/dist/types/commands/run.d.ts +4 -1
- package/dist/types/commands/tdd.d.ts +5 -1
- package/dist/types/sdk/index.d.ts +6 -6
- package/dist/types/server/handlers/api-handler.d.ts +49 -0
- package/dist/types/server/handlers/tdd-handler.d.ts +85 -0
- package/dist/types/server/http-server.d.ts +5 -0
- package/dist/types/services/api-service.d.ts +1 -0
- package/dist/types/services/server-manager.d.ts +148 -3
- package/dist/types/services/test-runner.d.ts +1 -0
- package/dist/types/services/uploader.d.ts +2 -1
- package/dist/types/utils/ci-env.d.ts +55 -0
- package/dist/types/utils/config-helpers.d.ts +1 -1
- package/dist/types/utils/console-ui.d.ts +1 -1
- package/dist/types/utils/git.d.ts +12 -0
- package/dist/utils/ci-env.js +293 -0
- package/dist/utils/console-ui.js +4 -14
- package/dist/utils/git.js +38 -0
- package/docs/api-reference.md +17 -5
- package/docs/getting-started.md +1 -1
- package/docs/tdd-mode.md +9 -9
- package/docs/test-integration.md +9 -17
- package/docs/upload-command.md +7 -0
- package/package.json +4 -5
- package/dist/screenshot-wrapper.js +0 -68
- package/dist/server/index.js +0 -522
- package/dist/services/service-utils.js +0 -171
- package/dist/types/index.js +0 -153
- package/dist/types/screenshot-wrapper.d.ts +0 -27
- package/dist/types/server/index.d.ts +0 -38
- package/dist/types/services/service-utils.d.ts +0 -45
- package/dist/types/types/index.d.ts +0 -373
- package/dist/types/utils/diagnostics.d.ts +0 -69
- package/dist/types/utils/error-messages.d.ts +0 -42
- package/dist/types/utils/framework-detector.d.ts +0 -5
- package/dist/types/utils/help.d.ts +0 -11
- package/dist/types/utils/image-comparison.d.ts +0 -42
- package/dist/types/utils/package.d.ts +0 -1
- package/dist/types/utils/project-detection.d.ts +0 -19
- package/dist/types/utils/ui-helpers.d.ts +0 -23
- package/dist/utils/diagnostics.js +0 -184
- package/dist/utils/error-messages.js +0 -34
- package/dist/utils/framework-detector.js +0 -40
- package/dist/utils/help.js +0 -66
- package/dist/utils/image-comparison.js +0 -172
- package/dist/utils/package.js +0 -9
- package/dist/utils/project-detection.js +0 -145
- package/dist/utils/ui-helpers.js +0 -86
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI Environment Detection
|
|
3
|
+
*
|
|
4
|
+
* Generic functions to extract git and PR information from any CI provider
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get the branch name from CI environment variables
|
|
9
|
+
* @returns {string|null} Branch name or null if not available
|
|
10
|
+
*/
|
|
11
|
+
export function getBranch() {
|
|
12
|
+
return process.env.VIZZLY_BRANCH ||
|
|
13
|
+
// Vizzly override
|
|
14
|
+
process.env.GITHUB_HEAD_REF ||
|
|
15
|
+
// GitHub Actions (for PRs)
|
|
16
|
+
process.env.GITHUB_REF_NAME ||
|
|
17
|
+
// GitHub Actions (for pushes)
|
|
18
|
+
process.env.CI_COMMIT_REF_NAME ||
|
|
19
|
+
// GitLab CI
|
|
20
|
+
process.env.CIRCLE_BRANCH ||
|
|
21
|
+
// CircleCI
|
|
22
|
+
process.env.TRAVIS_BRANCH ||
|
|
23
|
+
// Travis CI
|
|
24
|
+
process.env.BUILDKITE_BRANCH ||
|
|
25
|
+
// Buildkite
|
|
26
|
+
process.env.DRONE_BRANCH ||
|
|
27
|
+
// Drone CI
|
|
28
|
+
process.env.BRANCH_NAME ||
|
|
29
|
+
// Jenkins
|
|
30
|
+
process.env.GIT_BRANCH ||
|
|
31
|
+
// Jenkins (alternative)
|
|
32
|
+
process.env.BITBUCKET_BRANCH ||
|
|
33
|
+
// Bitbucket Pipelines
|
|
34
|
+
process.env.WERCKER_GIT_BRANCH ||
|
|
35
|
+
// Wercker
|
|
36
|
+
process.env.APPVEYOR_REPO_BRANCH ||
|
|
37
|
+
// AppVeyor
|
|
38
|
+
process.env.BUILD_SOURCEBRANCH?.replace(/^refs\/heads\//, '') ||
|
|
39
|
+
// Azure DevOps
|
|
40
|
+
process.env.CODEBUILD_WEBHOOK_HEAD_REF?.replace(/^refs\/heads\//, '') ||
|
|
41
|
+
// AWS CodeBuild
|
|
42
|
+
process.env.SEMAPHORE_GIT_BRANCH ||
|
|
43
|
+
// Semaphore
|
|
44
|
+
null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the commit SHA from CI environment variables
|
|
49
|
+
* @returns {string|null} Commit SHA or null if not available
|
|
50
|
+
*/
|
|
51
|
+
export function getCommit() {
|
|
52
|
+
return process.env.VIZZLY_COMMIT_SHA ||
|
|
53
|
+
// Vizzly override
|
|
54
|
+
process.env.GITHUB_SHA ||
|
|
55
|
+
// GitHub Actions
|
|
56
|
+
process.env.CI_COMMIT_SHA ||
|
|
57
|
+
// GitLab CI
|
|
58
|
+
process.env.CIRCLE_SHA1 ||
|
|
59
|
+
// CircleCI
|
|
60
|
+
process.env.TRAVIS_COMMIT ||
|
|
61
|
+
// Travis CI
|
|
62
|
+
process.env.BUILDKITE_COMMIT ||
|
|
63
|
+
// Buildkite
|
|
64
|
+
process.env.DRONE_COMMIT_SHA ||
|
|
65
|
+
// Drone CI
|
|
66
|
+
process.env.GIT_COMMIT ||
|
|
67
|
+
// Jenkins
|
|
68
|
+
process.env.BITBUCKET_COMMIT ||
|
|
69
|
+
// Bitbucket Pipelines
|
|
70
|
+
process.env.WERCKER_GIT_COMMIT ||
|
|
71
|
+
// Wercker
|
|
72
|
+
process.env.APPVEYOR_REPO_COMMIT ||
|
|
73
|
+
// AppVeyor
|
|
74
|
+
process.env.BUILD_SOURCEVERSION ||
|
|
75
|
+
// Azure DevOps
|
|
76
|
+
process.env.CODEBUILD_RESOLVED_SOURCE_VERSION ||
|
|
77
|
+
// AWS CodeBuild
|
|
78
|
+
process.env.SEMAPHORE_GIT_SHA ||
|
|
79
|
+
// Semaphore
|
|
80
|
+
process.env.HEROKU_TEST_RUN_COMMIT_VERSION ||
|
|
81
|
+
// Heroku CI
|
|
82
|
+
process.env.COMMIT_SHA ||
|
|
83
|
+
// Generic
|
|
84
|
+
process.env.HEAD_COMMIT ||
|
|
85
|
+
// Alternative generic
|
|
86
|
+
process.env.SHA ||
|
|
87
|
+
// Another generic option
|
|
88
|
+
null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get the commit message from CI environment variables
|
|
93
|
+
* @returns {string|null} Commit message or null if not available
|
|
94
|
+
*/
|
|
95
|
+
export function getCommitMessage() {
|
|
96
|
+
return process.env.VIZZLY_COMMIT_MESSAGE ||
|
|
97
|
+
// Vizzly override
|
|
98
|
+
process.env.CI_COMMIT_MESSAGE ||
|
|
99
|
+
// GitLab CI
|
|
100
|
+
process.env.TRAVIS_COMMIT_MESSAGE ||
|
|
101
|
+
// Travis CI
|
|
102
|
+
process.env.BUILDKITE_MESSAGE ||
|
|
103
|
+
// Buildkite
|
|
104
|
+
process.env.DRONE_COMMIT_MESSAGE ||
|
|
105
|
+
// Drone CI
|
|
106
|
+
process.env.APPVEYOR_REPO_COMMIT_MESSAGE ||
|
|
107
|
+
// AppVeyor
|
|
108
|
+
process.env.COMMIT_MESSAGE ||
|
|
109
|
+
// Generic
|
|
110
|
+
null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get the pull request number from CI environment variables
|
|
115
|
+
* @returns {number|null} PR number or null if not available/not a PR
|
|
116
|
+
*/
|
|
117
|
+
export function getPullRequestNumber() {
|
|
118
|
+
// Check VIZZLY override first
|
|
119
|
+
if (process.env.VIZZLY_PR_NUMBER) {
|
|
120
|
+
return parseInt(process.env.VIZZLY_PR_NUMBER, 10);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// GitHub Actions - extract from GITHUB_REF
|
|
124
|
+
if (process.env.GITHUB_ACTIONS && process.env.GITHUB_EVENT_NAME === 'pull_request') {
|
|
125
|
+
const prMatch = process.env.GITHUB_REF?.match(/refs\/pull\/(\d+)\/merge/);
|
|
126
|
+
if (prMatch?.[1]) return parseInt(prMatch[1], 10);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// GitLab CI
|
|
130
|
+
if (process.env.CI_MERGE_REQUEST_ID) {
|
|
131
|
+
return parseInt(process.env.CI_MERGE_REQUEST_ID, 10);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// CircleCI - extract from PR URL
|
|
135
|
+
if (process.env.CIRCLE_PULL_REQUEST) {
|
|
136
|
+
const prMatch = process.env.CIRCLE_PULL_REQUEST.match(/\/pull\/(\d+)$/);
|
|
137
|
+
if (prMatch?.[1]) return parseInt(prMatch[1], 10);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Travis CI
|
|
141
|
+
if (process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== 'false') {
|
|
142
|
+
return parseInt(process.env.TRAVIS_PULL_REQUEST, 10);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Buildkite
|
|
146
|
+
if (process.env.BUILDKITE_PULL_REQUEST && process.env.BUILDKITE_PULL_REQUEST !== 'false') {
|
|
147
|
+
return parseInt(process.env.BUILDKITE_PULL_REQUEST, 10);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Drone CI
|
|
151
|
+
if (process.env.DRONE_PULL_REQUEST) {
|
|
152
|
+
return parseInt(process.env.DRONE_PULL_REQUEST, 10);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Jenkins (GitHub Pull Request Builder plugin)
|
|
156
|
+
if (process.env.ghprbPullId) {
|
|
157
|
+
return parseInt(process.env.ghprbPullId, 10);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Azure DevOps
|
|
161
|
+
if (process.env.SYSTEM_PULLREQUEST_PULLREQUESTID) {
|
|
162
|
+
return parseInt(process.env.SYSTEM_PULLREQUEST_PULLREQUESTID, 10);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// AppVeyor
|
|
166
|
+
if (process.env.APPVEYOR_PULL_REQUEST_NUMBER) {
|
|
167
|
+
return parseInt(process.env.APPVEYOR_PULL_REQUEST_NUMBER, 10);
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Get the PR head SHA from CI environment variables
|
|
174
|
+
* @returns {string|null} PR head SHA or null if not available
|
|
175
|
+
*/
|
|
176
|
+
export function getPullRequestHeadSha() {
|
|
177
|
+
return process.env.VIZZLY_PR_HEAD_SHA ||
|
|
178
|
+
// Vizzly override
|
|
179
|
+
process.env.GITHUB_SHA ||
|
|
180
|
+
// GitHub Actions
|
|
181
|
+
process.env.CI_COMMIT_SHA ||
|
|
182
|
+
// GitLab CI
|
|
183
|
+
process.env.CIRCLE_SHA1 ||
|
|
184
|
+
// CircleCI
|
|
185
|
+
process.env.TRAVIS_COMMIT ||
|
|
186
|
+
// Travis CI
|
|
187
|
+
process.env.BUILDKITE_COMMIT ||
|
|
188
|
+
// Buildkite
|
|
189
|
+
process.env.DRONE_COMMIT_SHA ||
|
|
190
|
+
// Drone CI
|
|
191
|
+
process.env.ghprbActualCommit ||
|
|
192
|
+
// Jenkins
|
|
193
|
+
process.env.GIT_COMMIT ||
|
|
194
|
+
// Jenkins fallback
|
|
195
|
+
process.env.BUILD_SOURCEVERSION ||
|
|
196
|
+
// Azure DevOps
|
|
197
|
+
process.env.APPVEYOR_REPO_COMMIT ||
|
|
198
|
+
// AppVeyor
|
|
199
|
+
null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Get the PR base SHA from CI environment variables
|
|
204
|
+
* @returns {string|null} PR base SHA or null if not available
|
|
205
|
+
*/
|
|
206
|
+
export function getPullRequestBaseSha() {
|
|
207
|
+
return process.env.VIZZLY_PR_BASE_SHA ||
|
|
208
|
+
// Vizzly override
|
|
209
|
+
process.env.CI_MERGE_REQUEST_TARGET_BRANCH_SHA ||
|
|
210
|
+
// GitLab CI
|
|
211
|
+
null // Most CIs don't provide this
|
|
212
|
+
;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get the PR head ref (branch) from CI environment variables
|
|
217
|
+
* @returns {string|null} PR head ref or null if not available
|
|
218
|
+
*/
|
|
219
|
+
export function getPullRequestHeadRef() {
|
|
220
|
+
return process.env.VIZZLY_PR_HEAD_REF ||
|
|
221
|
+
// Vizzly override
|
|
222
|
+
process.env.GITHUB_HEAD_REF ||
|
|
223
|
+
// GitHub Actions
|
|
224
|
+
process.env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME ||
|
|
225
|
+
// GitLab CI
|
|
226
|
+
process.env.TRAVIS_PULL_REQUEST_BRANCH ||
|
|
227
|
+
// Travis CI
|
|
228
|
+
process.env.DRONE_SOURCE_BRANCH ||
|
|
229
|
+
// Drone CI
|
|
230
|
+
process.env.ghprbSourceBranch ||
|
|
231
|
+
// Jenkins
|
|
232
|
+
process.env.SYSTEM_PULLREQUEST_SOURCEBRANCH?.replace(/^refs\/heads\//, '') ||
|
|
233
|
+
// Azure DevOps
|
|
234
|
+
process.env.APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH ||
|
|
235
|
+
// AppVeyor
|
|
236
|
+
null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Get the PR base ref (target branch) from CI environment variables
|
|
241
|
+
* @returns {string|null} PR base ref or null if not available
|
|
242
|
+
*/
|
|
243
|
+
export function getPullRequestBaseRef() {
|
|
244
|
+
return process.env.VIZZLY_PR_BASE_REF ||
|
|
245
|
+
// Vizzly override
|
|
246
|
+
process.env.GITHUB_BASE_REF ||
|
|
247
|
+
// GitHub Actions
|
|
248
|
+
process.env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME ||
|
|
249
|
+
// GitLab CI
|
|
250
|
+
process.env.TRAVIS_BRANCH ||
|
|
251
|
+
// Travis CI (target branch)
|
|
252
|
+
process.env.BUILDKITE_PULL_REQUEST_BASE_BRANCH ||
|
|
253
|
+
// Buildkite
|
|
254
|
+
process.env.DRONE_TARGET_BRANCH ||
|
|
255
|
+
// Drone CI
|
|
256
|
+
process.env.ghprbTargetBranch ||
|
|
257
|
+
// Jenkins
|
|
258
|
+
process.env.SYSTEM_PULLREQUEST_TARGETBRANCH?.replace(/^refs\/heads\//, '') ||
|
|
259
|
+
// Azure DevOps
|
|
260
|
+
process.env.APPVEYOR_REPO_BRANCH ||
|
|
261
|
+
// AppVeyor (target branch)
|
|
262
|
+
null;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Check if we're currently in a pull request context
|
|
267
|
+
* @returns {boolean} True if in a PR context
|
|
268
|
+
*/
|
|
269
|
+
export function isPullRequest() {
|
|
270
|
+
return getPullRequestNumber() !== null;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Get the CI provider name
|
|
275
|
+
* @returns {string} CI provider name or 'unknown'
|
|
276
|
+
*/
|
|
277
|
+
export function getCIProvider() {
|
|
278
|
+
if (process.env.GITHUB_ACTIONS) return 'github-actions';
|
|
279
|
+
if (process.env.GITLAB_CI) return 'gitlab-ci';
|
|
280
|
+
if (process.env.CIRCLECI) return 'circleci';
|
|
281
|
+
if (process.env.TRAVIS) return 'travis-ci';
|
|
282
|
+
if (process.env.BUILDKITE) return 'buildkite';
|
|
283
|
+
if (process.env.DRONE) return 'drone-ci';
|
|
284
|
+
if (process.env.JENKINS_URL) return 'jenkins';
|
|
285
|
+
if (process.env.AZURE_HTTP_USER_AGENT || process.env.TF_BUILD) return 'azure-devops';
|
|
286
|
+
if (process.env.CODEBUILD_BUILD_ID) return 'aws-codebuild';
|
|
287
|
+
if (process.env.APPVEYOR) return 'appveyor';
|
|
288
|
+
if (process.env.SEMAPHORE) return 'semaphore';
|
|
289
|
+
if (process.env.WERCKER) return 'wercker';
|
|
290
|
+
if (process.env.BITBUCKET_BUILD_NUMBER) return 'bitbucket-pipelines';
|
|
291
|
+
if (process.env.HEROKU_TEST_RUN_ID) return 'heroku-ci';
|
|
292
|
+
return 'unknown';
|
|
293
|
+
}
|
package/dist/utils/console-ui.js
CHANGED
|
@@ -158,11 +158,12 @@ export class ConsoleUI {
|
|
|
158
158
|
startSpinner(message) {
|
|
159
159
|
if (this.json || !process.stdout.isTTY) return;
|
|
160
160
|
this.stopSpinner();
|
|
161
|
+
this.currentMessage = message;
|
|
161
162
|
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
162
163
|
let i = 0;
|
|
163
164
|
this.spinner = setInterval(() => {
|
|
164
165
|
const frame = frames[i++ % frames.length];
|
|
165
|
-
const line = `${this.colors.blue(frame)} ${message}`;
|
|
166
|
+
const line = `${this.colors.blue(frame)} ${this.currentMessage || message}`;
|
|
166
167
|
|
|
167
168
|
// Clear previous line and write new one
|
|
168
169
|
process.stdout.write('\r' + ' '.repeat(this.lastLine.length) + '\r');
|
|
@@ -211,16 +212,5 @@ export class ConsoleUI {
|
|
|
211
212
|
}
|
|
212
213
|
}
|
|
213
214
|
|
|
214
|
-
//
|
|
215
|
-
|
|
216
|
-
// Clear any remaining spinner
|
|
217
|
-
if (process.stdout.isTTY) {
|
|
218
|
-
process.stdout.write('\r' + ' '.repeat(80) + '\r');
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
process.on('SIGINT', () => {
|
|
222
|
-
if (process.stdout.isTTY) {
|
|
223
|
-
process.stdout.write('\r' + ' '.repeat(80) + '\r');
|
|
224
|
-
}
|
|
225
|
-
process.exit(1);
|
|
226
|
-
});
|
|
215
|
+
// Note: Global process event listeners are handled in individual commands
|
|
216
|
+
// to avoid interference between tests and proper cleanup
|
package/dist/utils/git.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { exec } from 'child_process';
|
|
2
2
|
import { promisify } from 'util';
|
|
3
|
+
import { getBranch as getCIBranch, getCommit as getCICommit, getCommitMessage as getCICommitMessage, getPullRequestNumber } from './ci-env.js';
|
|
3
4
|
const execAsync = promisify(exec);
|
|
4
5
|
export async function getCommonAncestor(commit1, commit2, cwd = process.cwd()) {
|
|
5
6
|
try {
|
|
@@ -144,6 +145,23 @@ export async function getCommitMessage(cwd = process.cwd()) {
|
|
|
144
145
|
}
|
|
145
146
|
}
|
|
146
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Detect commit message with override and environment variable support
|
|
150
|
+
* @param {string} override - Commit message override from CLI
|
|
151
|
+
* @param {string} cwd - Working directory
|
|
152
|
+
* @returns {Promise<string|null>} Commit message or null if not available
|
|
153
|
+
*/
|
|
154
|
+
export async function detectCommitMessage(override = null, cwd = process.cwd()) {
|
|
155
|
+
if (override) return override;
|
|
156
|
+
|
|
157
|
+
// Try CI environment variables first
|
|
158
|
+
const ciCommitMessage = getCICommitMessage();
|
|
159
|
+
if (ciCommitMessage) return ciCommitMessage;
|
|
160
|
+
|
|
161
|
+
// Fallback to regular git log
|
|
162
|
+
return await getCommitMessage(cwd);
|
|
163
|
+
}
|
|
164
|
+
|
|
147
165
|
/**
|
|
148
166
|
* Check if the working directory is a git repository
|
|
149
167
|
* @param {string} cwd - Working directory
|
|
@@ -193,6 +211,12 @@ export async function getGitStatus(cwd = process.cwd()) {
|
|
|
193
211
|
*/
|
|
194
212
|
export async function detectBranch(override = null, cwd = process.cwd()) {
|
|
195
213
|
if (override) return override;
|
|
214
|
+
|
|
215
|
+
// Try CI environment variables first
|
|
216
|
+
const ciBranch = getCIBranch();
|
|
217
|
+
if (ciBranch) return ciBranch;
|
|
218
|
+
|
|
219
|
+
// Fallback to git command when no CI environment variables
|
|
196
220
|
const currentBranch = await getCurrentBranch(cwd);
|
|
197
221
|
return currentBranch || 'unknown';
|
|
198
222
|
}
|
|
@@ -205,6 +229,12 @@ export async function detectBranch(override = null, cwd = process.cwd()) {
|
|
|
205
229
|
*/
|
|
206
230
|
export async function detectCommit(override = null, cwd = process.cwd()) {
|
|
207
231
|
if (override) return override;
|
|
232
|
+
|
|
233
|
+
// Try CI environment variables first
|
|
234
|
+
const ciCommit = getCICommit();
|
|
235
|
+
if (ciCommit) return ciCommit;
|
|
236
|
+
|
|
237
|
+
// Fallback to git command when no CI environment variables
|
|
208
238
|
return await getCurrentCommitSha(cwd);
|
|
209
239
|
}
|
|
210
240
|
|
|
@@ -223,4 +253,12 @@ export async function generateBuildNameWithGit(override = null, cwd = process.cw
|
|
|
223
253
|
return `${branch}-${shortCommit}`;
|
|
224
254
|
}
|
|
225
255
|
return generateBuildName();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Detect pull request number from CI environment
|
|
260
|
+
* @returns {number|null} Pull request number or null if not in PR context
|
|
261
|
+
*/
|
|
262
|
+
export function detectPullRequestNumber() {
|
|
263
|
+
return getPullRequestNumber();
|
|
226
264
|
}
|
package/docs/api-reference.md
CHANGED
|
@@ -288,6 +288,7 @@ Upload screenshots from a directory.
|
|
|
288
288
|
- `--threshold <number>` - Comparison threshold (0-1)
|
|
289
289
|
- `--token <token>` - API token override
|
|
290
290
|
- `--wait` - Wait for build completion
|
|
291
|
+
- `--upload-all` - Upload all screenshots without SHA deduplication
|
|
291
292
|
|
|
292
293
|
**Exit Codes:**
|
|
293
294
|
- `0` - Success (all approved or no changes)
|
|
@@ -316,18 +317,14 @@ Run tests with Vizzly integration.
|
|
|
316
317
|
|
|
317
318
|
*Processing Options:*
|
|
318
319
|
- `--wait` - Wait for build completion and exit with appropriate code
|
|
319
|
-
- `--eager` - Create build immediately (default: lazy creation)
|
|
320
320
|
- `--threshold <number>` - Comparison threshold (0-1, default: 0.01)
|
|
321
321
|
- `--upload-timeout <ms>` - Upload wait timeout in ms (default: from config or 30000)
|
|
322
|
+
- `--upload-all` - Upload all screenshots without SHA deduplication
|
|
322
323
|
|
|
323
324
|
*Development & Testing:*
|
|
324
|
-
- `--tdd` - Enable TDD mode with local comparisons
|
|
325
325
|
- `--allow-no-token` - Allow running without API token
|
|
326
326
|
- `--token <token>` - API token override
|
|
327
327
|
|
|
328
|
-
*Baseline Configuration:*
|
|
329
|
-
- `--baseline-build <id>` - Use specific build as baseline for comparisons
|
|
330
|
-
- `--baseline-comparison <id>` - Use specific comparison as baseline
|
|
331
328
|
|
|
332
329
|
**Environment Variables Set:**
|
|
333
330
|
- `VIZZLY_SERVER_URL` - Local server URL
|
|
@@ -484,14 +481,29 @@ Configuration loaded via cosmiconfig in this order:
|
|
|
484
481
|
|
|
485
482
|
### Environment Variables
|
|
486
483
|
|
|
484
|
+
**Core Configuration:**
|
|
487
485
|
- `VIZZLY_TOKEN` - API authentication token
|
|
488
486
|
- `VIZZLY_API_URL` - API base URL override
|
|
489
487
|
- `VIZZLY_LOG_LEVEL` - Logger level (`debug`, `info`, `warn`, `error`)
|
|
488
|
+
|
|
489
|
+
**Git Information Override (CI/CD Enhancement):**
|
|
490
|
+
- `VIZZLY_COMMIT_SHA` - Override detected commit SHA
|
|
491
|
+
- `VIZZLY_COMMIT_MESSAGE` - Override detected commit message
|
|
492
|
+
- `VIZZLY_BRANCH` - Override detected branch name
|
|
493
|
+
- `VIZZLY_PR_NUMBER` - Override detected pull request number
|
|
494
|
+
|
|
495
|
+
**Runtime (Set by CLI):**
|
|
490
496
|
- `VIZZLY_SERVER_URL` - Screenshot server URL (set by CLI)
|
|
491
497
|
- `VIZZLY_ENABLED` - Enable/disable client (set by CLI)
|
|
492
498
|
- `VIZZLY_BUILD_ID` - Current build ID (set by CLI)
|
|
493
499
|
- `VIZZLY_TDD_MODE` - TDD mode active (set by CLI)
|
|
494
500
|
|
|
501
|
+
**Priority Order for Git Information:**
|
|
502
|
+
1. CLI arguments (`--commit`, `--branch`, `--message`)
|
|
503
|
+
2. `VIZZLY_*` environment variables
|
|
504
|
+
3. CI-specific environment variables (e.g., `GITHUB_SHA`, `CI_COMMIT_SHA`)
|
|
505
|
+
4. Git command detection
|
|
506
|
+
|
|
495
507
|
## Error Handling
|
|
496
508
|
|
|
497
509
|
### Client Errors
|
package/docs/getting-started.md
CHANGED
package/docs/tdd-mode.md
CHANGED
|
@@ -145,11 +145,11 @@ vizzly tdd "npm test" --timeout 60000
|
|
|
145
145
|
npx vizzly run "npm test" --wait
|
|
146
146
|
|
|
147
147
|
# 2. Start TDD development
|
|
148
|
-
npx vizzly
|
|
148
|
+
npx vizzly tdd "npm test"
|
|
149
149
|
|
|
150
150
|
# 3. Make changes and iterate
|
|
151
151
|
# Edit code...
|
|
152
|
-
npx vizzly
|
|
152
|
+
npx vizzly tdd "npm test"
|
|
153
153
|
|
|
154
154
|
# 4. Upload when satisfied
|
|
155
155
|
npx vizzly run "npm test" --wait
|
|
@@ -159,13 +159,13 @@ npx vizzly run "npm test" --wait
|
|
|
159
159
|
|
|
160
160
|
```bash
|
|
161
161
|
# Start with latest baselines
|
|
162
|
-
npx vizzly
|
|
162
|
+
npx vizzly tdd "npm test"
|
|
163
163
|
|
|
164
164
|
# Develop new feature with immediate feedback
|
|
165
165
|
while [ $? -ne 0 ]; do
|
|
166
166
|
# Edit code to fix visual differences
|
|
167
167
|
vim src/components/NewFeature.js
|
|
168
|
-
npx vizzly
|
|
168
|
+
npx vizzly tdd "npm test"
|
|
169
169
|
done
|
|
170
170
|
|
|
171
171
|
# Upload completed feature
|
|
@@ -176,7 +176,7 @@ npx vizzly run "npm test" --build-name "Feature: New Dashboard"
|
|
|
176
176
|
|
|
177
177
|
```bash
|
|
178
178
|
# Use TDD mode to verify fixes
|
|
179
|
-
npx vizzly
|
|
179
|
+
npx vizzly tdd "npm test"
|
|
180
180
|
|
|
181
181
|
# Tests should pass when bug is fixed
|
|
182
182
|
# Then upload the fix
|
|
@@ -216,7 +216,7 @@ npx vizzly status # Shows latest build info
|
|
|
216
216
|
Download new baselines from a different build:
|
|
217
217
|
|
|
218
218
|
```bash
|
|
219
|
-
npx vizzly
|
|
219
|
+
npx vizzly tdd "npm test" --baseline-build build-xyz789
|
|
220
220
|
```
|
|
221
221
|
|
|
222
222
|
### Force Baseline Refresh
|
|
@@ -225,7 +225,7 @@ Delete local baselines to force re-download:
|
|
|
225
225
|
|
|
226
226
|
```bash
|
|
227
227
|
rm -rf .vizzly/baselines/
|
|
228
|
-
npx vizzly
|
|
228
|
+
npx vizzly tdd "npm test"
|
|
229
229
|
```
|
|
230
230
|
|
|
231
231
|
## Advanced Usage
|
|
@@ -276,7 +276,7 @@ jobs:
|
|
|
276
276
|
# Use TDD mode for PR builds (faster, no uploads)
|
|
277
277
|
- name: TDD Visual Tests (PR)
|
|
278
278
|
if: github.event_name == 'pull_request'
|
|
279
|
-
run: npx vizzly
|
|
279
|
+
run: npx vizzly tdd "npm test"
|
|
280
280
|
env:
|
|
281
281
|
VIZZLY_TOKEN: ${{ secrets.VIZZLY_TOKEN }}
|
|
282
282
|
|
|
@@ -337,7 +337,7 @@ Error: Failed to compare 'homepage': baseline image not found
|
|
|
337
337
|
**Solution**: Refresh baselines:
|
|
338
338
|
```bash
|
|
339
339
|
rm -rf .vizzly/baselines/
|
|
340
|
-
npx vizzly
|
|
340
|
+
npx vizzly tdd "npm test"
|
|
341
341
|
```
|
|
342
342
|
|
|
343
343
|
### Odiff Not Found
|
package/docs/test-integration.md
CHANGED
|
@@ -199,9 +199,9 @@ vizzly run "npm test" --branch "feature/new-ui"
|
|
|
199
199
|
vizzly run "npm test" --wait
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
-
**`--
|
|
202
|
+
**`--upload-all`** - Upload all screenshots without SHA deduplication
|
|
203
203
|
```bash
|
|
204
|
-
vizzly run "npm test" --
|
|
204
|
+
vizzly run "npm test" --upload-all
|
|
205
205
|
```
|
|
206
206
|
|
|
207
207
|
**`--threshold <number>`** - Comparison threshold (0-1, default: 0.01)
|
|
@@ -211,10 +211,7 @@ vizzly run "npm test" --threshold 0.02
|
|
|
211
211
|
|
|
212
212
|
### Development Options
|
|
213
213
|
|
|
214
|
-
|
|
215
|
-
```bash
|
|
216
|
-
vizzly run "npm test" --tdd
|
|
217
|
-
```
|
|
214
|
+
For TDD mode, use the dedicated `vizzly tdd` command. See [TDD Mode Guide](./tdd-mode.md) for details.
|
|
218
215
|
|
|
219
216
|
**`--allow-no-token`** - Allow running without API token
|
|
220
217
|
```bash
|
|
@@ -226,17 +223,6 @@ vizzly run "npm test" --allow-no-token
|
|
|
226
223
|
vizzly run "npm test" --token "your-token-here"
|
|
227
224
|
```
|
|
228
225
|
|
|
229
|
-
### Baseline Configuration
|
|
230
|
-
|
|
231
|
-
**`--baseline-build <id>`** - Use specific build as baseline
|
|
232
|
-
```bash
|
|
233
|
-
vizzly run "npm test" --baseline-build "build_123"
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
**`--baseline-comparison <id>`** - Use specific comparison as baseline
|
|
237
|
-
```bash
|
|
238
|
-
vizzly run "npm test" --baseline-comparison "comp_456"
|
|
239
|
-
```
|
|
240
226
|
|
|
241
227
|
## Screenshot Properties
|
|
242
228
|
|
|
@@ -289,8 +275,14 @@ jobs:
|
|
|
289
275
|
- run: npx vizzly run "npm test" --wait
|
|
290
276
|
env:
|
|
291
277
|
VIZZLY_TOKEN: ${{ secrets.VIZZLY_TOKEN }}
|
|
278
|
+
# Optional: Enhanced git information from GitHub context
|
|
279
|
+
VIZZLY_COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
|
|
280
|
+
VIZZLY_COMMIT_SHA: ${{ github.event.head_commit.id }}
|
|
281
|
+
VIZZLY_BRANCH: ${{ github.head_ref || github.ref_name }}
|
|
292
282
|
```
|
|
293
283
|
|
|
284
|
+
**Enhanced Git Information:** The `VIZZLY_*` environment variables ensure accurate git metadata is captured in your builds, avoiding issues with merge commits that can occur in CI environments.
|
|
285
|
+
|
|
294
286
|
### GitLab CI
|
|
295
287
|
|
|
296
288
|
```yaml
|
package/docs/upload-command.md
CHANGED
|
@@ -72,6 +72,13 @@ This will:
|
|
|
72
72
|
- Show progress and results
|
|
73
73
|
- Exit with appropriate status code
|
|
74
74
|
|
|
75
|
+
**`--upload-all`** - Upload all screenshots without SHA deduplication
|
|
76
|
+
```bash
|
|
77
|
+
vizzly upload ./screenshots --upload-all
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
By default, Vizzly deduplicates screenshots based on their SHA hash to avoid unnecessary uploads. Use this flag to force upload of all screenshots regardless of their content.
|
|
81
|
+
|
|
75
82
|
**`--metadata <json>`** - Additional metadata as JSON
|
|
76
83
|
```bash
|
|
77
84
|
vizzly upload ./screenshots --metadata '{"browser": "chrome", "viewport": "1920x1080"}'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizzly-testing/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Visual review platform for UI developers and designers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"visual-testing",
|
|
@@ -73,11 +73,11 @@
|
|
|
73
73
|
"registry": "https://registry.npmjs.org/"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"commander": "^
|
|
76
|
+
"commander": "^14.0.0",
|
|
77
77
|
"cosmiconfig": "^9.0.0",
|
|
78
78
|
"dotenv": "^17.2.1",
|
|
79
79
|
"form-data": "^4.0.0",
|
|
80
|
-
"glob": "^
|
|
80
|
+
"glob": "^11.0.3",
|
|
81
81
|
"odiff-bin": "^3.2.1"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
@@ -93,8 +93,7 @@
|
|
|
93
93
|
"eslint-config-prettier": "^10.1.8",
|
|
94
94
|
"eslint-plugin-prettier": "^5.5.3",
|
|
95
95
|
"prettier": "^3.6.2",
|
|
96
|
-
"
|
|
97
|
-
"rimraf": "^5.0.5",
|
|
96
|
+
"rimraf": "^6.0.1",
|
|
98
97
|
"typescript": "^5.0.4",
|
|
99
98
|
"vite": "^7.1.2",
|
|
100
99
|
"vitest": "^3.2.4"
|