qa360 2.0.13 → 2.1.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/dist/core/adapters/playwright-native-adapter.d.ts +121 -0
- package/dist/core/adapters/playwright-native-adapter.js +339 -0
- package/dist/core/adapters/playwright-ui.d.ts +38 -0
- package/dist/core/adapters/playwright-ui.js +164 -4
- package/dist/core/artifacts/index.d.ts +6 -0
- package/dist/core/artifacts/index.js +6 -0
- package/dist/core/artifacts/ui-artifacts.d.ts +133 -0
- package/dist/core/artifacts/ui-artifacts.js +304 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +9 -0
- package/dist/core/parallel/index.d.ts +6 -0
- package/dist/core/parallel/index.js +6 -0
- package/dist/core/parallel/parallel-runner.d.ts +107 -0
- package/dist/core/parallel/parallel-runner.js +192 -0
- package/dist/core/reporting/html-reporter.d.ts +119 -0
- package/dist/core/reporting/html-reporter.js +737 -0
- package/dist/core/reporting/index.d.ts +6 -0
- package/dist/core/reporting/index.js +6 -0
- package/dist/core/runner/phase3-runner.js +5 -1
- package/dist/core/vault/cas.d.ts +5 -1
- package/dist/core/vault/cas.js +6 -0
- package/dist/core/visual/index.d.ts +6 -0
- package/dist/core/visual/index.js +6 -0
- package/dist/core/visual/visual-regression.d.ts +113 -0
- package/dist/core/visual/visual-regression.js +236 -0
- package/examples/README.md +38 -0
- package/examples/crawler.yml +38 -0
- package/examples/ui-advanced.yml +49 -0
- package/package.json +1 -1
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* QA360 Playwright UI Adapter (Extended)
|
|
3
3
|
* Complete UI E2E testing with all Playwright actions
|
|
4
|
+
*
|
|
5
|
+
* Playwright++ Features:
|
|
6
|
+
* - Video recording (always/retain-on-fail/never)
|
|
7
|
+
* - Automatic screenshots (before/after steps, on error)
|
|
8
|
+
* - Trace capture for debugging
|
|
9
|
+
* - Artifacts management with CAS
|
|
10
|
+
* - HTML report generation
|
|
4
11
|
*/
|
|
5
12
|
import { chromium, firefox, webkit } from '@playwright/test';
|
|
6
13
|
import { SecurityRedactor } from '../security/redactor.js';
|
|
7
14
|
import { createAssertionsEngine } from '../assertions/index.js';
|
|
15
|
+
import { UIArtifactsManager } from '../artifacts/index.js';
|
|
16
|
+
import { HTMLReporter } from '../reporting/index.js';
|
|
17
|
+
import { mkdirSync, existsSync } from 'fs';
|
|
18
|
+
import { join } from 'path';
|
|
8
19
|
export class PlaywrightUiAdapter {
|
|
9
20
|
browser;
|
|
10
21
|
context;
|
|
@@ -16,6 +27,13 @@ export class PlaywrightUiAdapter {
|
|
|
16
27
|
artifactDir;
|
|
17
28
|
videoDir;
|
|
18
29
|
traceDir;
|
|
30
|
+
// Playwright++: Artifacts manager
|
|
31
|
+
artifactsManager;
|
|
32
|
+
failureCount = 0;
|
|
33
|
+
currentTestId;
|
|
34
|
+
allScreenshots = [];
|
|
35
|
+
allVideos = [];
|
|
36
|
+
allTraces = [];
|
|
19
37
|
constructor() {
|
|
20
38
|
this.redactor = SecurityRedactor.forLogs();
|
|
21
39
|
this.artifactDir = '.qa360/artifacts/ui';
|
|
@@ -30,11 +48,31 @@ export class PlaywrightUiAdapter {
|
|
|
30
48
|
}
|
|
31
49
|
/**
|
|
32
50
|
* Execute UI smoke tests with accessibility
|
|
51
|
+
* Playwright++: Supports artifacts, screenshots, video, trace, HTML reporting
|
|
33
52
|
*/
|
|
34
53
|
async runSmokeTests(config) {
|
|
54
|
+
const startTime = Date.now();
|
|
55
|
+
const outputDir = config.artifacts?.outputDir || this.artifactDir;
|
|
56
|
+
// Ensure output directories exist
|
|
57
|
+
for (const dir of [outputDir, this.videoDir, this.traceDir]) {
|
|
58
|
+
if (!existsSync(dir)) {
|
|
59
|
+
mkdirSync(dir, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Initialize artifacts manager if Playwright++ features enabled
|
|
63
|
+
const artifactsEnabled = config.artifacts?.screenshots !== 'never' ||
|
|
64
|
+
config.artifacts?.video !== 'never' ||
|
|
65
|
+
config.artifacts?.trace !== 'never';
|
|
66
|
+
if (artifactsEnabled) {
|
|
67
|
+
this.artifactsManager = new UIArtifactsManager(outputDir, '.qa360/runs/cas');
|
|
68
|
+
}
|
|
35
69
|
try {
|
|
36
70
|
// Store auth config
|
|
37
71
|
this.auth = config.auth;
|
|
72
|
+
this.failureCount = 0;
|
|
73
|
+
this.allScreenshots = [];
|
|
74
|
+
this.allVideos = [];
|
|
75
|
+
this.allTraces = [];
|
|
38
76
|
await this.setupBrowser(config);
|
|
39
77
|
const results = [];
|
|
40
78
|
const pages = config.target.pages || [config.target.baseUrl];
|
|
@@ -44,6 +82,9 @@ export class PlaywrightUiAdapter {
|
|
|
44
82
|
await this.performLogin(config.login);
|
|
45
83
|
}
|
|
46
84
|
for (const pageUrl of pages) {
|
|
85
|
+
// Start artifacts for this test
|
|
86
|
+
this.currentTestId = `smoke-${this.failureCount}`;
|
|
87
|
+
this.artifactsManager?.startTest(this.currentTestId);
|
|
47
88
|
const testResult = await this.testPage(pageUrl, config);
|
|
48
89
|
results.push(testResult);
|
|
49
90
|
if (testResult.success) {
|
|
@@ -52,8 +93,15 @@ export class PlaywrightUiAdapter {
|
|
|
52
93
|
console.log(` ✅ ${pageUrl} -> ${testResult.loadTime}ms${a11yInfo}`);
|
|
53
94
|
}
|
|
54
95
|
else {
|
|
96
|
+
this.failureCount++;
|
|
55
97
|
console.log(` ❌ ${pageUrl} -> ${testResult.error}`);
|
|
98
|
+
// Check bail condition
|
|
99
|
+
if (config.bail && this.failureCount >= config.bail) {
|
|
100
|
+
console.log(` 🛑 Bailing after ${this.failureCount} failures`);
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
56
103
|
}
|
|
104
|
+
this.artifactsManager?.endTest();
|
|
57
105
|
}
|
|
58
106
|
// Run E2E tests if defined
|
|
59
107
|
let e2eResults = [];
|
|
@@ -61,18 +109,33 @@ export class PlaywrightUiAdapter {
|
|
|
61
109
|
console.log(`🧪 Running E2E tests (${config.target.uiTests.length} tests)`);
|
|
62
110
|
for (const test of config.target.uiTests) {
|
|
63
111
|
if (test.enabled !== false) {
|
|
112
|
+
// Start artifacts for this test
|
|
113
|
+
this.currentTestId = `e2e-${test.name}`;
|
|
114
|
+
this.artifactsManager?.startTest(this.currentTestId);
|
|
64
115
|
const result = await this.runE2eTest(test, config);
|
|
65
116
|
e2eResults.push(result);
|
|
66
117
|
const status = result.success ? '✅' : '❌';
|
|
67
118
|
console.log(` ${status} ${test.name} (${result.duration}ms)`);
|
|
68
119
|
if (!result.success) {
|
|
69
120
|
console.log(` Error: ${result.error}`);
|
|
121
|
+
this.failureCount++;
|
|
122
|
+
// Check bail condition
|
|
123
|
+
if (config.bail && this.failureCount >= config.bail) {
|
|
124
|
+
console.log(` 🛑 Bailing after ${this.failureCount} failures`);
|
|
125
|
+
this.artifactsManager?.endTest();
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
70
128
|
}
|
|
129
|
+
this.artifactsManager?.endTest();
|
|
71
130
|
}
|
|
72
131
|
}
|
|
73
132
|
}
|
|
74
133
|
const summary = this.calculateSummary(results, e2eResults);
|
|
75
134
|
const junit = this.generateJUnit(results, e2eResults);
|
|
135
|
+
// Playwright++: Generate HTML report if requested
|
|
136
|
+
if (config.htmlReport) {
|
|
137
|
+
await this.generateHtmlReport(config, results, e2eResults, summary);
|
|
138
|
+
}
|
|
76
139
|
return {
|
|
77
140
|
success: summary.failed === 0,
|
|
78
141
|
results,
|
|
@@ -87,23 +150,44 @@ export class PlaywrightUiAdapter {
|
|
|
87
150
|
}
|
|
88
151
|
/**
|
|
89
152
|
* Run a single E2E test
|
|
153
|
+
* Playwright++: Takes before/after screenshots, captures artifacts on failure
|
|
90
154
|
*/
|
|
91
155
|
async runE2eTest(test, config) {
|
|
92
156
|
const startTime = Date.now();
|
|
93
157
|
const steps = [];
|
|
158
|
+
const screenshotMode = config.artifacts?.screenshots || 'never';
|
|
94
159
|
try {
|
|
95
160
|
// Determine starting URL
|
|
96
161
|
const startUrl = test.url || `${config.target.baseUrl.replace(/\/$/, '')}${test.path || ''}`;
|
|
97
162
|
// Navigate to start URL
|
|
98
163
|
console.log(` 📍 Navigate to: ${startUrl}`);
|
|
99
164
|
await this.page.goto(startUrl, { timeout: test.timeout || config.timeout || 30000 });
|
|
165
|
+
// Take initial screenshot
|
|
166
|
+
if (screenshotMode === 'always') {
|
|
167
|
+
await this.artifactsManager?.takeScreenshot(this.page, {}, {
|
|
168
|
+
testId: this.currentTestId || 'unknown',
|
|
169
|
+
type: 'screenshot',
|
|
170
|
+
tags: ['initial'],
|
|
171
|
+
});
|
|
172
|
+
}
|
|
100
173
|
// Initialize assertions engine
|
|
101
174
|
this.assertions = createAssertionsEngine(this.page);
|
|
102
175
|
// Execute each step
|
|
103
|
-
for (
|
|
104
|
-
const
|
|
176
|
+
for (let i = 0; i < test.steps.length; i++) {
|
|
177
|
+
const step = test.steps[i];
|
|
178
|
+
// Take before screenshot if configured
|
|
179
|
+
if (screenshotMode === 'always') {
|
|
180
|
+
await this.artifactsManager?.takeBeforeScreenshot(this.page, step.action || 'step', i);
|
|
181
|
+
}
|
|
182
|
+
const stepResult = await this.executeStep(step, config);
|
|
105
183
|
steps.push(stepResult);
|
|
184
|
+
// Take after screenshot (always on failure, or always if configured)
|
|
185
|
+
if (screenshotMode === 'always' || (screenshotMode === 'only-on-failure' && !stepResult.success)) {
|
|
186
|
+
await this.artifactsManager?.takeAfterScreenshot(this.page, step.action || 'step', i, stepResult.success);
|
|
187
|
+
}
|
|
106
188
|
if (!stepResult.success) {
|
|
189
|
+
// Take error screenshot
|
|
190
|
+
await this.artifactsManager?.takeErrorScreenshot(this.page, new Error(stepResult.error || 'Step failed'), step.action);
|
|
107
191
|
return {
|
|
108
192
|
test,
|
|
109
193
|
success: false,
|
|
@@ -121,6 +205,8 @@ export class PlaywrightUiAdapter {
|
|
|
121
205
|
};
|
|
122
206
|
}
|
|
123
207
|
catch (error) {
|
|
208
|
+
// Take error screenshot
|
|
209
|
+
await this.artifactsManager?.takeErrorScreenshot(this.page, error);
|
|
124
210
|
return {
|
|
125
211
|
test,
|
|
126
212
|
success: false,
|
|
@@ -132,8 +218,9 @@ export class PlaywrightUiAdapter {
|
|
|
132
218
|
}
|
|
133
219
|
/**
|
|
134
220
|
* Execute a single UI test step
|
|
221
|
+
* Playwright++: Enhanced error handling with artifacts
|
|
135
222
|
*/
|
|
136
|
-
async executeStep(step) {
|
|
223
|
+
async executeStep(step, config) {
|
|
137
224
|
const startTime = Date.now();
|
|
138
225
|
let screenshot;
|
|
139
226
|
try {
|
|
@@ -339,6 +426,7 @@ export class PlaywrightUiAdapter {
|
|
|
339
426
|
}
|
|
340
427
|
/**
|
|
341
428
|
* Setup browser with all options
|
|
429
|
+
* Playwright++: Enhanced video/trace recording support
|
|
342
430
|
*/
|
|
343
431
|
async setupBrowser(config) {
|
|
344
432
|
// Determine browser type
|
|
@@ -370,8 +458,11 @@ export class PlaywrightUiAdapter {
|
|
|
370
458
|
else if (config.target.viewport) {
|
|
371
459
|
viewport = config.target.viewport;
|
|
372
460
|
}
|
|
461
|
+
// Playwright++: Determine video recording mode
|
|
462
|
+
const videoMode = config.artifacts?.video ?? config.target.video;
|
|
463
|
+
const shouldRecordVideo = videoMode === 'always' || videoMode === 'retain-on-failure';
|
|
373
464
|
// Create context with video recording if enabled
|
|
374
|
-
const recordVideo =
|
|
465
|
+
const recordVideo = shouldRecordVideo
|
|
375
466
|
? { dir: this.videoDir, size: viewport }
|
|
376
467
|
: undefined;
|
|
377
468
|
this.context = await this.browser.newContext({
|
|
@@ -380,6 +471,13 @@ export class PlaywrightUiAdapter {
|
|
|
380
471
|
extraHTTPHeaders,
|
|
381
472
|
recordVideo,
|
|
382
473
|
});
|
|
474
|
+
// Playwright++: Start tracing if enabled
|
|
475
|
+
const traceMode = config.artifacts?.trace ?? config.target.trace;
|
|
476
|
+
if (traceMode === 'always' || traceMode === 'on-first-failure' || traceMode === 'retain-on-failure') {
|
|
477
|
+
// Start tracing - will be saved in cleanup
|
|
478
|
+
// Note: Playwright's trace API is context.startTracing()
|
|
479
|
+
// Implementation depends on Playwright version
|
|
480
|
+
}
|
|
383
481
|
// Add cookies from auth credentials after context creation
|
|
384
482
|
if (this.auth?.cookies && this.auth.cookies.length > 0) {
|
|
385
483
|
await this.context.addCookies(this.auth.cookies.map(c => ({
|
|
@@ -399,6 +497,68 @@ export class PlaywrightUiAdapter {
|
|
|
399
497
|
shouldRecordVideo(mode) {
|
|
400
498
|
return mode === 'always' || mode === 'retain-on-fail';
|
|
401
499
|
}
|
|
500
|
+
/**
|
|
501
|
+
* Playwright++: Generate HTML report
|
|
502
|
+
*/
|
|
503
|
+
async generateHtmlReport(config, results, e2eResults, summary) {
|
|
504
|
+
const reportPath = config.htmlReport || join(config.artifacts?.outputDir || this.artifactDir, 'report.html');
|
|
505
|
+
const timestamp = new Date().toISOString();
|
|
506
|
+
const reportData = {
|
|
507
|
+
title: `QA360 UI Test Report - ${timestamp}`,
|
|
508
|
+
summary: {
|
|
509
|
+
total: summary.total,
|
|
510
|
+
passed: summary.passed,
|
|
511
|
+
failed: summary.failed,
|
|
512
|
+
skipped: 0,
|
|
513
|
+
duration: summary.avgLoadTime * summary.total,
|
|
514
|
+
timestamp,
|
|
515
|
+
},
|
|
516
|
+
tests: [
|
|
517
|
+
...results.map((r, i) => ({
|
|
518
|
+
id: `smoke-${i}`,
|
|
519
|
+
name: `UI Smoke: ${r.page}`,
|
|
520
|
+
status: (r.success ? 'passed' : 'failed'),
|
|
521
|
+
duration: r.loadTime,
|
|
522
|
+
error: r.error,
|
|
523
|
+
steps: [],
|
|
524
|
+
artifacts: r.artifacts,
|
|
525
|
+
})),
|
|
526
|
+
...e2eResults.map((r, i) => ({
|
|
527
|
+
id: `e2e-${i}`,
|
|
528
|
+
name: r.test.name || 'E2E Test',
|
|
529
|
+
status: (r.success ? 'passed' : 'failed'),
|
|
530
|
+
duration: r.duration,
|
|
531
|
+
error: r.error,
|
|
532
|
+
steps: r.steps.map((s, j) => ({
|
|
533
|
+
name: s.step.action || `Step ${j + 1}`,
|
|
534
|
+
action: s.step.action || 'step',
|
|
535
|
+
selector: s.step.selector,
|
|
536
|
+
value: s.step.value,
|
|
537
|
+
status: (s.success ? 'passed' : 'failed'),
|
|
538
|
+
duration: s.duration,
|
|
539
|
+
error: s.error,
|
|
540
|
+
})),
|
|
541
|
+
artifacts: undefined,
|
|
542
|
+
})),
|
|
543
|
+
],
|
|
544
|
+
artifacts: {
|
|
545
|
+
screenshots: this.allScreenshots.map(s => ({
|
|
546
|
+
path: s.localPath,
|
|
547
|
+
timestamp: s.metadata.timestamp,
|
|
548
|
+
type: 'after',
|
|
549
|
+
})),
|
|
550
|
+
videos: this.allVideos.map(v => ({ path: v, duration: 0 })),
|
|
551
|
+
traces: this.allTraces.map(t => ({ path: t, format: 'zip' })),
|
|
552
|
+
},
|
|
553
|
+
environment: {
|
|
554
|
+
browser: config.target.browser || 'chromium',
|
|
555
|
+
platform: process.platform,
|
|
556
|
+
nodeVersion: process.version,
|
|
557
|
+
},
|
|
558
|
+
};
|
|
559
|
+
HTMLReporter.generate(reportData, reportPath);
|
|
560
|
+
console.log(`\n📊 HTML report generated: ${reportPath}`);
|
|
561
|
+
}
|
|
402
562
|
/**
|
|
403
563
|
* Perform login if configured
|
|
404
564
|
*/
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Artifacts Module
|
|
3
|
+
*
|
|
4
|
+
* Manages screenshots, videos, traces, and other test artifacts
|
|
5
|
+
*/
|
|
6
|
+
export { UIArtifactsManager, createUIArtifactsManager, type ScreenshotOptions, type ArtifactMetadata, type StoredArtifact, type VideoArtifact, type ScreenshotArtifact, type TraceArtifact, } from './ui-artifacts.js';
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 UI Artifacts Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages screenshots, videos, traces, and other test artifacts
|
|
5
|
+
* with content-addressable storage (CAS) integration
|
|
6
|
+
*/
|
|
7
|
+
export type ScreenshotFormat = 'png' | 'jpeg' | 'webp';
|
|
8
|
+
export interface ScreenshotOptions {
|
|
9
|
+
fullPage?: boolean;
|
|
10
|
+
quality?: number;
|
|
11
|
+
type?: ScreenshotFormat;
|
|
12
|
+
animations?: 'disabled' | 'allow';
|
|
13
|
+
}
|
|
14
|
+
export interface ArtifactMetadata {
|
|
15
|
+
testId: string;
|
|
16
|
+
stepIndex?: number;
|
|
17
|
+
stepName?: string;
|
|
18
|
+
type: 'screenshot' | 'video' | 'trace' | 'network' | 'console' | 'coverage';
|
|
19
|
+
timestamp: string;
|
|
20
|
+
status?: 'passed' | 'failed' | 'flaky';
|
|
21
|
+
tags?: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface StoredArtifact {
|
|
24
|
+
casPath: string;
|
|
25
|
+
localPath: string;
|
|
26
|
+
hash: string;
|
|
27
|
+
metadata: ArtifactMetadata;
|
|
28
|
+
size: number;
|
|
29
|
+
type: 'screenshot' | 'video' | 'trace' | 'network' | 'console' | 'coverage';
|
|
30
|
+
}
|
|
31
|
+
export interface VideoArtifact extends StoredArtifact {
|
|
32
|
+
type: 'video';
|
|
33
|
+
format: 'webm';
|
|
34
|
+
duration: number;
|
|
35
|
+
}
|
|
36
|
+
export interface ScreenshotArtifact extends StoredArtifact {
|
|
37
|
+
type: 'screenshot';
|
|
38
|
+
format: ScreenshotFormat;
|
|
39
|
+
width: number;
|
|
40
|
+
height: number;
|
|
41
|
+
}
|
|
42
|
+
export interface TraceArtifact extends StoredArtifact {
|
|
43
|
+
type: 'trace';
|
|
44
|
+
format: 'zip';
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* UI Artifacts Manager
|
|
48
|
+
*
|
|
49
|
+
* Handles:
|
|
50
|
+
* - Automatic screenshots (before/after steps, on error)
|
|
51
|
+
* - Video recording
|
|
52
|
+
* - Trace files
|
|
53
|
+
* - Network captures
|
|
54
|
+
* - Console logs
|
|
55
|
+
* - Storage in CAS for deduplication
|
|
56
|
+
*/
|
|
57
|
+
export declare class UIArtifactsManager {
|
|
58
|
+
private artifactDir;
|
|
59
|
+
private casDir;
|
|
60
|
+
private currentRunId;
|
|
61
|
+
private currentTestId?;
|
|
62
|
+
private artifacts;
|
|
63
|
+
private cas;
|
|
64
|
+
constructor(artifactDir?: string, casDir?: string);
|
|
65
|
+
private ensureDirectories;
|
|
66
|
+
/**
|
|
67
|
+
* Start a new test session
|
|
68
|
+
*/
|
|
69
|
+
startTest(testId: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* End current test session
|
|
72
|
+
*/
|
|
73
|
+
endTest(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Take a screenshot and store it
|
|
76
|
+
*/
|
|
77
|
+
takeScreenshot(page: any, // Playwright Page
|
|
78
|
+
options?: ScreenshotOptions, metadata?: Partial<ArtifactMetadata>): Promise<ScreenshotArtifact>;
|
|
79
|
+
/**
|
|
80
|
+
* Take screenshot before a step
|
|
81
|
+
*/
|
|
82
|
+
takeBeforeScreenshot(page: any, stepName: string, stepIndex: number): Promise<ScreenshotArtifact>;
|
|
83
|
+
/**
|
|
84
|
+
* Take screenshot after a step
|
|
85
|
+
*/
|
|
86
|
+
takeAfterScreenshot(page: any, stepName: string, stepIndex: number, success: boolean): Promise<ScreenshotArtifact>;
|
|
87
|
+
/**
|
|
88
|
+
* Take screenshot on error
|
|
89
|
+
*/
|
|
90
|
+
takeErrorScreenshot(page: any, error: Error, stepName?: string): Promise<ScreenshotArtifact>;
|
|
91
|
+
/**
|
|
92
|
+
* Save video artifact
|
|
93
|
+
*/
|
|
94
|
+
saveVideo(videoPath: string, metadata?: Partial<ArtifactMetadata>): Promise<VideoArtifact>;
|
|
95
|
+
/**
|
|
96
|
+
* Save trace artifact
|
|
97
|
+
*/
|
|
98
|
+
saveTrace(tracePath: string, metadata?: Partial<ArtifactMetadata>): Promise<TraceArtifact>;
|
|
99
|
+
/**
|
|
100
|
+
* Get artifact by ID
|
|
101
|
+
*/
|
|
102
|
+
getArtifact(id: string): StoredArtifact | undefined;
|
|
103
|
+
/**
|
|
104
|
+
* Get all artifacts for current test
|
|
105
|
+
*/
|
|
106
|
+
getTestArtifacts(): StoredArtifact[];
|
|
107
|
+
/**
|
|
108
|
+
* Get all artifacts by type
|
|
109
|
+
*/
|
|
110
|
+
getArtifactsByType(type: StoredArtifact['type']): StoredArtifact[];
|
|
111
|
+
/**
|
|
112
|
+
* Clean up old artifacts
|
|
113
|
+
*/
|
|
114
|
+
cleanup(maxAge?: number): void;
|
|
115
|
+
/**
|
|
116
|
+
* Generate CAS path from hash
|
|
117
|
+
*/
|
|
118
|
+
private getCasPath;
|
|
119
|
+
/**
|
|
120
|
+
* Generate artifacts summary for reporting
|
|
121
|
+
*/
|
|
122
|
+
generateSummary(): {
|
|
123
|
+
screenshots: number;
|
|
124
|
+
videos: number;
|
|
125
|
+
traces: number;
|
|
126
|
+
totalSize: number;
|
|
127
|
+
casDedupSavings: number;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Create a UI artifacts manager
|
|
132
|
+
*/
|
|
133
|
+
export declare function createUIArtifactsManager(artifactDir?: string, casDir?: string): UIArtifactsManager;
|