@vizzly-testing/cli 0.4.0 → 0.6.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 +35 -5
- package/dist/cli.js +17 -1
- package/dist/commands/run.js +62 -21
- package/dist/commands/tdd.js +35 -35
- package/dist/commands/upload.js +4 -2
- package/dist/server/handlers/tdd-handler.js +82 -8
- package/dist/services/html-report-generator.js +377 -0
- package/dist/services/report-generator/report.css +355 -0
- package/dist/services/report-generator/viewer.js +100 -0
- package/dist/services/server-manager.js +3 -2
- package/dist/services/tdd-service.js +375 -66
- package/dist/services/test-runner.js +64 -35
- package/dist/services/uploader.js +5 -3
- package/dist/types/commands/tdd.d.ts +3 -2
- package/dist/types/server/handlers/tdd-handler.d.ts +18 -1
- package/dist/types/services/html-report-generator.d.ts +52 -0
- package/dist/types/services/report-generator/viewer.d.ts +0 -0
- package/dist/types/services/server-manager.d.ts +19 -1
- package/dist/types/services/tdd-service.d.ts +24 -3
- package/dist/types/services/uploader.d.ts +2 -1
- package/dist/types/utils/ci-env.d.ts +55 -0
- package/dist/types/utils/config-loader.d.ts +3 -0
- package/dist/types/utils/git.d.ts +12 -0
- package/dist/types/utils/security.d.ts +29 -0
- package/dist/utils/ci-env.js +293 -0
- package/dist/utils/config-loader.js +7 -0
- package/dist/utils/git.js +38 -0
- package/dist/utils/security.js +154 -0
- package/docs/api-reference.md +15 -0
- package/docs/tdd-mode.md +58 -12
- package/docs/test-integration.md +6 -0
- package/package.json +6 -6
|
@@ -39,10 +39,11 @@ export class TestRunner extends BaseService {
|
|
|
39
39
|
screenshotsCaptured: 0
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
let buildUrl = null;
|
|
43
|
+
let screenshotCount = 0;
|
|
44
|
+
let testSuccess = false;
|
|
45
|
+
let testError = null;
|
|
42
46
|
try {
|
|
43
|
-
let buildUrl = null;
|
|
44
|
-
let screenshotCount = 0;
|
|
45
|
-
|
|
46
47
|
// Create build based on mode
|
|
47
48
|
buildId = await this.createBuild(options, tdd);
|
|
48
49
|
if (!tdd && buildId) {
|
|
@@ -62,7 +63,7 @@ export class TestRunner extends BaseService {
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
// Start server with appropriate handler
|
|
65
|
-
await this.serverManager.start(buildId, tdd);
|
|
66
|
+
await this.serverManager.start(buildId, tdd, options.setBaseline);
|
|
66
67
|
|
|
67
68
|
// Forward server events
|
|
68
69
|
if (this.serverManager.server?.emitter) {
|
|
@@ -78,28 +79,46 @@ export class TestRunner extends BaseService {
|
|
|
78
79
|
VIZZLY_ENABLED: 'true',
|
|
79
80
|
VIZZLY_SET_BASELINE: options.setBaseline || options['set-baseline'] ? 'true' : 'false'
|
|
80
81
|
};
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
url: buildUrl,
|
|
89
|
-
testsPassed: 1,
|
|
90
|
-
testsFailed: 0,
|
|
91
|
-
screenshotsCaptured: screenshotCount
|
|
92
|
-
};
|
|
82
|
+
try {
|
|
83
|
+
await this.executeTestCommand(testCommand, env);
|
|
84
|
+
testSuccess = true;
|
|
85
|
+
} catch (error) {
|
|
86
|
+
testError = error;
|
|
87
|
+
testSuccess = false;
|
|
88
|
+
}
|
|
93
89
|
} catch (error) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const executionTime = Date.now() - startTime;
|
|
98
|
-
await this.finalizeBuild(buildId, tdd, false, executionTime);
|
|
99
|
-
throw error;
|
|
90
|
+
// Error in setup phase
|
|
91
|
+
testError = error;
|
|
92
|
+
testSuccess = false;
|
|
100
93
|
} finally {
|
|
101
|
-
|
|
94
|
+
// Always finalize the build and stop the server
|
|
95
|
+
const executionTime = Date.now() - startTime;
|
|
96
|
+
if (buildId) {
|
|
97
|
+
try {
|
|
98
|
+
await this.finalizeBuild(buildId, tdd, testSuccess, executionTime);
|
|
99
|
+
} catch (finalizeError) {
|
|
100
|
+
this.logger.error('Failed to finalize build:', finalizeError);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
await this.serverManager.stop();
|
|
105
|
+
} catch (stopError) {
|
|
106
|
+
this.logger.error('Failed to stop server:', stopError);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// If there was a test error, throw it now (after cleanup)
|
|
111
|
+
if (testError) {
|
|
112
|
+
this.logger.error('Test run failed:', testError);
|
|
113
|
+
throw testError;
|
|
102
114
|
}
|
|
115
|
+
return {
|
|
116
|
+
buildId: buildId,
|
|
117
|
+
url: buildUrl,
|
|
118
|
+
testsPassed: testSuccess ? 1 : 0,
|
|
119
|
+
testsFailed: testSuccess ? 0 : 1,
|
|
120
|
+
screenshotsCaptured: screenshotCount
|
|
121
|
+
};
|
|
103
122
|
}
|
|
104
123
|
async createBuild(options, tdd) {
|
|
105
124
|
if (tdd) {
|
|
@@ -114,13 +133,12 @@ export class TestRunner extends BaseService {
|
|
|
114
133
|
const apiService = await this.createApiService();
|
|
115
134
|
if (apiService) {
|
|
116
135
|
const buildResult = await apiService.createBuild({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
136
|
+
name: options.buildName || `Test Run ${new Date().toISOString()}`,
|
|
137
|
+
branch: options.branch || 'main',
|
|
138
|
+
environment: options.environment || 'test',
|
|
139
|
+
commit_sha: options.commit,
|
|
140
|
+
commit_message: options.message,
|
|
141
|
+
github_pull_request_number: options.pullRequestNumber
|
|
124
142
|
});
|
|
125
143
|
this.logger.debug(`Build created with ID: ${buildResult.id}`);
|
|
126
144
|
|
|
@@ -154,10 +172,13 @@ export class TestRunner extends BaseService {
|
|
|
154
172
|
}
|
|
155
173
|
try {
|
|
156
174
|
if (isTddMode) {
|
|
157
|
-
// TDD mode: use server handler to finalize
|
|
175
|
+
// TDD mode: use server handler to finalize (local-only)
|
|
158
176
|
if (this.serverManager.server?.finishBuild) {
|
|
159
177
|
await this.serverManager.server.finishBuild(buildId);
|
|
160
178
|
this.logger.debug(`TDD build ${buildId} finalized with success: ${success}`);
|
|
179
|
+
} else {
|
|
180
|
+
// In TDD mode without a server, just log that finalization is skipped
|
|
181
|
+
this.logger.debug(`TDD build ${buildId} finalization skipped (local-only mode)`);
|
|
161
182
|
}
|
|
162
183
|
} else {
|
|
163
184
|
// API mode: use API service to update build status
|
|
@@ -188,8 +209,11 @@ export class TestRunner extends BaseService {
|
|
|
188
209
|
this.testProcess.on('error', error => {
|
|
189
210
|
reject(new VizzlyError(`Failed to run test command: ${error.message}`), 'TEST_COMMAND_FAILED');
|
|
190
211
|
});
|
|
191
|
-
this.testProcess.on('exit', code => {
|
|
192
|
-
|
|
212
|
+
this.testProcess.on('exit', (code, signal) => {
|
|
213
|
+
// If process was killed by SIGINT, treat as interruption
|
|
214
|
+
if (signal === 'SIGINT') {
|
|
215
|
+
reject(new VizzlyError('Test command was interrupted', 'TEST_COMMAND_INTERRUPTED'));
|
|
216
|
+
} else if (code !== 0) {
|
|
193
217
|
reject(new VizzlyError(`Test command exited with code ${code}`, 'TEST_COMMAND_FAILED'));
|
|
194
218
|
} else {
|
|
195
219
|
resolve();
|
|
@@ -198,8 +222,13 @@ export class TestRunner extends BaseService {
|
|
|
198
222
|
});
|
|
199
223
|
}
|
|
200
224
|
async cancel() {
|
|
201
|
-
if (this.testProcess) {
|
|
202
|
-
this.testProcess.kill('
|
|
225
|
+
if (this.testProcess && !this.testProcess.killed) {
|
|
226
|
+
this.testProcess.kill('SIGKILL');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Stop server manager if running
|
|
230
|
+
if (this.serverManager) {
|
|
231
|
+
await this.serverManager.stop();
|
|
203
232
|
}
|
|
204
233
|
}
|
|
205
234
|
}
|
|
@@ -50,6 +50,7 @@ export function createUploader({
|
|
|
50
50
|
message,
|
|
51
51
|
environment = 'production',
|
|
52
52
|
threshold,
|
|
53
|
+
pullRequestNumber,
|
|
53
54
|
onProgress = () => {}
|
|
54
55
|
}) {
|
|
55
56
|
try {
|
|
@@ -96,10 +97,11 @@ export function createUploader({
|
|
|
96
97
|
const buildInfo = {
|
|
97
98
|
name: buildName || `Upload ${new Date().toISOString()}`,
|
|
98
99
|
branch: branch || (await getDefaultBranch()) || 'main',
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
commit_sha: commit,
|
|
101
|
+
commit_message: message,
|
|
101
102
|
environment,
|
|
102
|
-
threshold
|
|
103
|
+
threshold,
|
|
104
|
+
github_pull_request_number: pullRequestNumber
|
|
103
105
|
};
|
|
104
106
|
const build = await api.createBuild(buildInfo);
|
|
105
107
|
const buildId = build.id;
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* @param {string} testCommand - Test command to execute
|
|
4
4
|
* @param {Object} options - Command options
|
|
5
5
|
* @param {Object} globalOptions - Global CLI options
|
|
6
|
+
* @returns {Promise<{result: Object, cleanup: Function}>} Result and cleanup function
|
|
6
7
|
*/
|
|
7
8
|
export function tddCommand(testCommand: string, options?: any, globalOptions?: any): Promise<{
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
result: any;
|
|
10
|
+
cleanup: Function;
|
|
10
11
|
}>;
|
|
11
12
|
/**
|
|
12
13
|
* Validate TDD options
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
export function createTddHandler(config: any, workingDir: any, baselineBuild: any, baselineComparison: any): {
|
|
1
|
+
export function createTddHandler(config: any, workingDir: any, baselineBuild: any, baselineComparison: any, setBaseline?: boolean): {
|
|
2
2
|
initialize: () => Promise<void>;
|
|
3
3
|
registerBuild: (buildId: any) => void;
|
|
4
4
|
handleScreenshot: (buildId: any, name: any, image: any, properties?: {}) => Promise<{
|
|
5
|
+
statusCode: number;
|
|
6
|
+
body: {
|
|
7
|
+
error: string;
|
|
8
|
+
details: any;
|
|
9
|
+
tddMode: boolean;
|
|
10
|
+
comparison?: undefined;
|
|
11
|
+
status?: undefined;
|
|
12
|
+
message?: undefined;
|
|
13
|
+
success?: undefined;
|
|
14
|
+
};
|
|
15
|
+
} | {
|
|
5
16
|
statusCode: number;
|
|
6
17
|
body: {
|
|
7
18
|
error: string;
|
|
@@ -12,6 +23,8 @@ export function createTddHandler(config: any, workingDir: any, baselineBuild: an
|
|
|
12
23
|
baseline: any;
|
|
13
24
|
current: any;
|
|
14
25
|
diff: any;
|
|
26
|
+
diffPercentage: any;
|
|
27
|
+
threshold: any;
|
|
15
28
|
};
|
|
16
29
|
tddMode: boolean;
|
|
17
30
|
status?: undefined;
|
|
@@ -29,6 +42,8 @@ export function createTddHandler(config: any, workingDir: any, baselineBuild: an
|
|
|
29
42
|
baseline: any;
|
|
30
43
|
current: any;
|
|
31
44
|
diff?: undefined;
|
|
45
|
+
diffPercentage?: undefined;
|
|
46
|
+
threshold?: undefined;
|
|
32
47
|
};
|
|
33
48
|
tddMode: boolean;
|
|
34
49
|
error?: undefined;
|
|
@@ -56,6 +71,8 @@ export function createTddHandler(config: any, workingDir: any, baselineBuild: an
|
|
|
56
71
|
baseline?: undefined;
|
|
57
72
|
current?: undefined;
|
|
58
73
|
diff?: undefined;
|
|
74
|
+
diffPercentage?: undefined;
|
|
75
|
+
threshold?: undefined;
|
|
59
76
|
};
|
|
60
77
|
tddMode: boolean;
|
|
61
78
|
error?: undefined;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export class HtmlReportGenerator {
|
|
2
|
+
constructor(workingDir: any, config: any);
|
|
3
|
+
workingDir: any;
|
|
4
|
+
config: any;
|
|
5
|
+
reportDir: string;
|
|
6
|
+
reportPath: string;
|
|
7
|
+
cssPath: string;
|
|
8
|
+
/**
|
|
9
|
+
* Sanitize HTML content to prevent XSS attacks
|
|
10
|
+
* @param {string} text - Text to sanitize
|
|
11
|
+
* @returns {string} Sanitized text
|
|
12
|
+
*/
|
|
13
|
+
sanitizeHtml(text: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Sanitize build info object
|
|
16
|
+
* @param {Object} buildInfo - Build information to sanitize
|
|
17
|
+
* @returns {Object} Sanitized build info
|
|
18
|
+
*/
|
|
19
|
+
sanitizeBuildInfo(buildInfo?: any): any;
|
|
20
|
+
/**
|
|
21
|
+
* Generate HTML report from TDD results
|
|
22
|
+
* @param {Object} results - TDD comparison results
|
|
23
|
+
* @param {Object} buildInfo - Build information
|
|
24
|
+
* @returns {string} Path to generated report
|
|
25
|
+
*/
|
|
26
|
+
generateReport(results: any, buildInfo?: any): string;
|
|
27
|
+
/**
|
|
28
|
+
* Process comparison data for HTML report
|
|
29
|
+
* @param {Object} comparison - Comparison object
|
|
30
|
+
* @returns {Object} Processed comparison data
|
|
31
|
+
*/
|
|
32
|
+
processComparison(comparison: any): any;
|
|
33
|
+
/**
|
|
34
|
+
* Get relative path from report directory to image file
|
|
35
|
+
* @param {string} imagePath - Absolute path to image
|
|
36
|
+
* @param {string} reportDir - Report directory path
|
|
37
|
+
* @returns {string|null} Relative path or null if invalid
|
|
38
|
+
*/
|
|
39
|
+
getRelativePath(imagePath: string, reportDir: string): string | null;
|
|
40
|
+
/**
|
|
41
|
+
* Generate the complete HTML template
|
|
42
|
+
* @param {Object} data - Report data
|
|
43
|
+
* @returns {string} HTML content
|
|
44
|
+
*/
|
|
45
|
+
generateHtmlTemplate(data: any): string;
|
|
46
|
+
/**
|
|
47
|
+
* Generate HTML for a single comparison
|
|
48
|
+
* @param {Object} comparison - Comparison data
|
|
49
|
+
* @returns {string} HTML content
|
|
50
|
+
*/
|
|
51
|
+
generateComparisonHtml(comparison: any): string;
|
|
52
|
+
}
|
|
File without changes
|
|
@@ -9,6 +9,17 @@ export class ServerManager extends BaseService {
|
|
|
9
9
|
initialize: () => Promise<void>;
|
|
10
10
|
registerBuild: (buildId: any) => void;
|
|
11
11
|
handleScreenshot: (buildId: any, name: any, image: any, properties?: {}) => Promise<{
|
|
12
|
+
statusCode: number;
|
|
13
|
+
body: {
|
|
14
|
+
error: string;
|
|
15
|
+
details: any;
|
|
16
|
+
tddMode: boolean;
|
|
17
|
+
comparison?: undefined;
|
|
18
|
+
status?: undefined;
|
|
19
|
+
message?: undefined;
|
|
20
|
+
success?: undefined;
|
|
21
|
+
};
|
|
22
|
+
} | {
|
|
12
23
|
statusCode: number;
|
|
13
24
|
body: {
|
|
14
25
|
error: string;
|
|
@@ -19,6 +30,8 @@ export class ServerManager extends BaseService {
|
|
|
19
30
|
baseline: any;
|
|
20
31
|
current: any;
|
|
21
32
|
diff: any;
|
|
33
|
+
diffPercentage: any;
|
|
34
|
+
threshold: any;
|
|
22
35
|
};
|
|
23
36
|
tddMode: boolean;
|
|
24
37
|
status?: undefined;
|
|
@@ -36,6 +49,8 @@ export class ServerManager extends BaseService {
|
|
|
36
49
|
baseline: any;
|
|
37
50
|
current: any;
|
|
38
51
|
diff?: undefined;
|
|
52
|
+
diffPercentage?: undefined;
|
|
53
|
+
threshold?: undefined;
|
|
39
54
|
};
|
|
40
55
|
tddMode: boolean;
|
|
41
56
|
error?: undefined;
|
|
@@ -63,6 +78,8 @@ export class ServerManager extends BaseService {
|
|
|
63
78
|
baseline?: undefined;
|
|
64
79
|
current?: undefined;
|
|
65
80
|
diff?: undefined;
|
|
81
|
+
diffPercentage?: undefined;
|
|
82
|
+
threshold?: undefined;
|
|
66
83
|
};
|
|
67
84
|
tddMode: boolean;
|
|
68
85
|
error?: undefined;
|
|
@@ -139,9 +156,10 @@ export class ServerManager extends BaseService {
|
|
|
139
156
|
cleanup: () => void;
|
|
140
157
|
};
|
|
141
158
|
emitter: EventEmitter<[never]>;
|
|
142
|
-
start(buildId?: any, tddMode?: boolean): Promise<void>;
|
|
159
|
+
start(buildId?: any, tddMode?: boolean, setBaseline?: boolean): Promise<void>;
|
|
143
160
|
buildId: any;
|
|
144
161
|
tddMode: boolean;
|
|
162
|
+
setBaseline: boolean;
|
|
145
163
|
createApiService(): Promise<import("./api-service.js").ApiService>;
|
|
146
164
|
get server(): {
|
|
147
165
|
emitter: EventEmitter<[never]>;
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export function createTDDService(config: any, options?: {}): TddService;
|
|
5
5
|
export class TddService {
|
|
6
|
-
constructor(config: any, workingDir?: string);
|
|
6
|
+
constructor(config: any, workingDir?: string, setBaseline?: boolean);
|
|
7
7
|
config: any;
|
|
8
|
+
setBaseline: boolean;
|
|
8
9
|
api: ApiService;
|
|
9
10
|
workingDir: string;
|
|
10
11
|
baselinePath: string;
|
|
@@ -14,6 +15,11 @@ export class TddService {
|
|
|
14
15
|
comparisons: any[];
|
|
15
16
|
threshold: any;
|
|
16
17
|
downloadBaselines(environment?: string, branch?: any, buildId?: any, comparisonId?: any): Promise<any>;
|
|
18
|
+
/**
|
|
19
|
+
* Handle local baseline logic (either load existing or prepare for new baselines)
|
|
20
|
+
* @returns {Promise<Object|null>} Baseline data or null if no local baselines exist
|
|
21
|
+
*/
|
|
22
|
+
handleLocalBaselines(): Promise<any | null>;
|
|
17
23
|
loadBaseline(): Promise<any>;
|
|
18
24
|
compareScreenshot(name: any, imageBuffer: any, properties?: {}): Promise<{
|
|
19
25
|
name: any;
|
|
@@ -32,7 +38,7 @@ export class TddService {
|
|
|
32
38
|
comparisons: any[];
|
|
33
39
|
baseline: any;
|
|
34
40
|
};
|
|
35
|
-
printResults(): {
|
|
41
|
+
printResults(): Promise<{
|
|
36
42
|
total: number;
|
|
37
43
|
passed: number;
|
|
38
44
|
failed: number;
|
|
@@ -40,12 +46,27 @@ export class TddService {
|
|
|
40
46
|
errors: number;
|
|
41
47
|
comparisons: any[];
|
|
42
48
|
baseline: any;
|
|
43
|
-
}
|
|
49
|
+
}>;
|
|
50
|
+
/**
|
|
51
|
+
* Generate HTML report for TDD results
|
|
52
|
+
* @param {Object} results - TDD comparison results
|
|
53
|
+
*/
|
|
54
|
+
generateHtmlReport(results: any): Promise<string>;
|
|
55
|
+
/**
|
|
56
|
+
* Open HTML report in default browser
|
|
57
|
+
* @param {string} reportPath - Path to HTML report
|
|
58
|
+
*/
|
|
59
|
+
openReport(reportPath: string): Promise<void>;
|
|
44
60
|
/**
|
|
45
61
|
* Update baselines with current screenshots (accept changes)
|
|
46
62
|
* @returns {number} Number of baselines updated
|
|
47
63
|
*/
|
|
48
64
|
updateBaselines(): number;
|
|
65
|
+
/**
|
|
66
|
+
* Create a new baseline (used during --set-baseline mode)
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
private createNewBaseline;
|
|
49
70
|
/**
|
|
50
71
|
* Update a single baseline with current screenshot
|
|
51
72
|
* @private
|
|
@@ -8,7 +8,7 @@ export function createUploader({ apiKey, apiUrl, userAgent, command, upload: upl
|
|
|
8
8
|
command: any;
|
|
9
9
|
upload?: {};
|
|
10
10
|
}, options?: {}): {
|
|
11
|
-
upload: ({ screenshotsDir, buildName, branch, commit, message, environment, threshold, onProgress, }: {
|
|
11
|
+
upload: ({ screenshotsDir, buildName, branch, commit, message, environment, threshold, pullRequestNumber, onProgress, }: {
|
|
12
12
|
screenshotsDir: any;
|
|
13
13
|
buildName: any;
|
|
14
14
|
branch: any;
|
|
@@ -16,6 +16,7 @@ export function createUploader({ apiKey, apiUrl, userAgent, command, upload: upl
|
|
|
16
16
|
message: any;
|
|
17
17
|
environment?: string;
|
|
18
18
|
threshold: any;
|
|
19
|
+
pullRequestNumber: any;
|
|
19
20
|
onProgress?: () => void;
|
|
20
21
|
}) => Promise<{
|
|
21
22
|
success: boolean;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI Environment Detection
|
|
3
|
+
*
|
|
4
|
+
* Generic functions to extract git and PR information from any CI provider
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Get the branch name from CI environment variables
|
|
8
|
+
* @returns {string|null} Branch name or null if not available
|
|
9
|
+
*/
|
|
10
|
+
export function getBranch(): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Get the commit SHA from CI environment variables
|
|
13
|
+
* @returns {string|null} Commit SHA or null if not available
|
|
14
|
+
*/
|
|
15
|
+
export function getCommit(): string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Get the commit message from CI environment variables
|
|
18
|
+
* @returns {string|null} Commit message or null if not available
|
|
19
|
+
*/
|
|
20
|
+
export function getCommitMessage(): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Get the pull request number from CI environment variables
|
|
23
|
+
* @returns {number|null} PR number or null if not available/not a PR
|
|
24
|
+
*/
|
|
25
|
+
export function getPullRequestNumber(): number | null;
|
|
26
|
+
/**
|
|
27
|
+
* Get the PR head SHA from CI environment variables
|
|
28
|
+
* @returns {string|null} PR head SHA or null if not available
|
|
29
|
+
*/
|
|
30
|
+
export function getPullRequestHeadSha(): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Get the PR base SHA from CI environment variables
|
|
33
|
+
* @returns {string|null} PR base SHA or null if not available
|
|
34
|
+
*/
|
|
35
|
+
export function getPullRequestBaseSha(): string | null;
|
|
36
|
+
/**
|
|
37
|
+
* Get the PR head ref (branch) from CI environment variables
|
|
38
|
+
* @returns {string|null} PR head ref or null if not available
|
|
39
|
+
*/
|
|
40
|
+
export function getPullRequestHeadRef(): string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Get the PR base ref (target branch) from CI environment variables
|
|
43
|
+
* @returns {string|null} PR base ref or null if not available
|
|
44
|
+
*/
|
|
45
|
+
export function getPullRequestBaseRef(): string | null;
|
|
46
|
+
/**
|
|
47
|
+
* Check if we're currently in a pull request context
|
|
48
|
+
* @returns {boolean} True if in a PR context
|
|
49
|
+
*/
|
|
50
|
+
export function isPullRequest(): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Get the CI provider name
|
|
53
|
+
* @returns {string} CI provider name or 'unknown'
|
|
54
|
+
*/
|
|
55
|
+
export function getCIProvider(): string;
|
|
@@ -9,6 +9,13 @@ export function generateBuildName(): string;
|
|
|
9
9
|
* @returns {Promise<string|null>} Commit message or null if not available
|
|
10
10
|
*/
|
|
11
11
|
export function getCommitMessage(cwd?: string): Promise<string | null>;
|
|
12
|
+
/**
|
|
13
|
+
* Detect commit message with override and environment variable support
|
|
14
|
+
* @param {string} override - Commit message override from CLI
|
|
15
|
+
* @param {string} cwd - Working directory
|
|
16
|
+
* @returns {Promise<string|null>} Commit message or null if not available
|
|
17
|
+
*/
|
|
18
|
+
export function detectCommitMessage(override?: string, cwd?: string): Promise<string | null>;
|
|
12
19
|
/**
|
|
13
20
|
* Check if the working directory is a git repository
|
|
14
21
|
* @param {string} cwd - Working directory
|
|
@@ -42,3 +49,8 @@ export function detectCommit(override?: string, cwd?: string): Promise<string |
|
|
|
42
49
|
* @returns {Promise<string>}
|
|
43
50
|
*/
|
|
44
51
|
export function generateBuildNameWithGit(override?: string, cwd?: string): Promise<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Detect pull request number from CI environment
|
|
54
|
+
* @returns {number|null} Pull request number or null if not in PR context
|
|
55
|
+
*/
|
|
56
|
+
export function detectPullRequestNumber(): number | null;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitizes a screenshot name to prevent path traversal and ensure safe file naming
|
|
3
|
+
* @param {string} name - Original screenshot name
|
|
4
|
+
* @param {number} maxLength - Maximum allowed length (default: 255)
|
|
5
|
+
* @returns {string} Sanitized screenshot name
|
|
6
|
+
*/
|
|
7
|
+
export function sanitizeScreenshotName(name: string, maxLength?: number): string;
|
|
8
|
+
/**
|
|
9
|
+
* Validates that a path stays within the allowed working directory bounds
|
|
10
|
+
* @param {string} targetPath - Path to validate
|
|
11
|
+
* @param {string} workingDir - Working directory that serves as the security boundary
|
|
12
|
+
* @returns {string} Resolved and normalized path if valid
|
|
13
|
+
* @throws {Error} If path is invalid or outside bounds
|
|
14
|
+
*/
|
|
15
|
+
export function validatePathSecurity(targetPath: string, workingDir: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Safely constructs a path within the working directory
|
|
18
|
+
* @param {string} workingDir - Base working directory
|
|
19
|
+
* @param {...string} pathSegments - Path segments to join
|
|
20
|
+
* @returns {string} Safely constructed path
|
|
21
|
+
* @throws {Error} If resulting path would be outside working directory
|
|
22
|
+
*/
|
|
23
|
+
export function safePath(workingDir: string, ...pathSegments: string[]): string;
|
|
24
|
+
/**
|
|
25
|
+
* Validates screenshot properties object for safe values
|
|
26
|
+
* @param {Object} properties - Properties to validate
|
|
27
|
+
* @returns {Object} Validated properties object
|
|
28
|
+
*/
|
|
29
|
+
export function validateScreenshotProperties(properties?: any): any;
|