@zest-pw/test 1.0.1 → 1.0.3
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/types/types.d.ts +1 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +0 -0
- package/dist/utils/take-screenshots.d.ts +1 -1
- package/dist/utils/take-screenshots.d.ts.map +1 -1
- package/dist/utils/take-screenshots.js +3 -5
- package/dist/utils/terminal-reporter.d.ts.map +1 -1
- package/dist/utils/terminal-reporter.js +57 -31
- package/dist/utils/test-step-wrapper.d.ts +2 -2
- package/dist/utils/test-step-wrapper.d.ts.map +1 -1
- package/dist/utils/test-step-wrapper.js +12 -14
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../types/types.ts"],"names":[],"mappings":""}
|
|
File without changes
|
|
@@ -14,5 +14,5 @@ import type { Page, TestInfo } from "@playwright/test";
|
|
|
14
14
|
* @param testInfo - Playwright TestInfo object for attaching screenshots
|
|
15
15
|
* @param stepTitle - Optional step title for attachment name
|
|
16
16
|
*/
|
|
17
|
-
export declare function takeScreenshotAfterStep(page: Page,
|
|
17
|
+
export declare function takeScreenshotAfterStep(page: Page, testInfo: TestInfo, stepTitle?: string): Promise<void>;
|
|
18
18
|
//# sourceMappingURL=take-screenshots.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"take-screenshots.d.ts","sourceRoot":"","sources":["../../utils/take-screenshots.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"take-screenshots.d.ts","sourceRoot":"","sources":["../../utils/take-screenshots.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAaf"}
|
|
@@ -16,13 +16,11 @@ exports.takeScreenshotAfterStep = takeScreenshotAfterStep;
|
|
|
16
16
|
* @param testInfo - Playwright TestInfo object for attaching screenshots
|
|
17
17
|
* @param stepTitle - Optional step title for attachment name
|
|
18
18
|
*/
|
|
19
|
-
async function takeScreenshotAfterStep(page,
|
|
19
|
+
async function takeScreenshotAfterStep(page, testInfo, stepTitle) {
|
|
20
20
|
try {
|
|
21
21
|
if (page && testInfo) {
|
|
22
|
-
const screenshotBuffer = await page.screenshot({
|
|
23
|
-
|
|
24
|
-
});
|
|
25
|
-
await testInfo.attach(stepTitle || stepInfo?.title || 'screenshot', {
|
|
22
|
+
const screenshotBuffer = await page.screenshot({ fullPage: true });
|
|
23
|
+
await testInfo.attach(stepTitle || 'screenshot', {
|
|
26
24
|
body: screenshotBuffer,
|
|
27
25
|
contentType: 'image/png',
|
|
28
26
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-reporter.d.ts","sourceRoot":"","sources":["../../utils/terminal-reporter.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"terminal-reporter.d.ts","sourceRoot":"","sources":["../../utils/terminal-reporter.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAuClD"}
|
|
@@ -47,22 +47,38 @@ function printTestResults(result) {
|
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
49
|
result.tests.forEach((test) => {
|
|
50
|
-
printTestInfo(test);
|
|
51
50
|
const allSteps = test.steps || [];
|
|
52
51
|
const executedSteps = allSteps.filter((step) => step.statusName !== 'In Progress');
|
|
53
52
|
const testFileName = test.testCaseKey || 'test';
|
|
54
53
|
const sanitizedTitle = test.testTitle.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
55
54
|
const projectName = test.projectName || 'chromium';
|
|
56
55
|
const outputDir = path.join('test-results', `${testFileName}-${sanitizedTitle}-${projectName}`);
|
|
56
|
+
const testTitle = `${projectName} › ${testFileName} › ${test.testTitle}`;
|
|
57
|
+
const remainder = (63 - testTitle.length) < 0 ? 0 : (63 - testTitle.length);
|
|
58
|
+
const spaces = '\x1b[40m \x1b[0m'.repeat(remainder);
|
|
59
|
+
console.log(`\n\x1b[40m${testTitle}${spaces}\x1b[0m`);
|
|
57
60
|
printTestSteps(executedSteps.length, allSteps, test.testTitle, outputDir);
|
|
58
61
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
let passedCount = 0;
|
|
63
|
+
let failedCount = 0;
|
|
64
|
+
let skippedCount = 0;
|
|
65
|
+
result.tests.forEach((test) => {
|
|
66
|
+
for (const step of test.steps) {
|
|
67
|
+
switch (step.statusName) {
|
|
68
|
+
case 'pass':
|
|
69
|
+
passedCount++;
|
|
70
|
+
break;
|
|
71
|
+
case 'fail':
|
|
72
|
+
failedCount++;
|
|
73
|
+
break;
|
|
74
|
+
case 'In Progress':
|
|
75
|
+
skippedCount++;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
console.log(`\x1b[30mTotal results:\x1b[0m \x1b[32m${passedCount} passed\x1b[0m\x1b[30m,\x1b[0m \x1b[31m${failedCount} failed\x1b[0m\x1b[30m,\x1b[0m \x1b[30m${skippedCount} skipped\x1b[0m`);
|
|
81
|
+
console.log('\n');
|
|
66
82
|
}
|
|
67
83
|
/**
|
|
68
84
|
* Prints test step information
|
|
@@ -72,25 +88,35 @@ function printTestInfo(test) {
|
|
|
72
88
|
* @param outputDir - Optional output directory path for saving screenshots
|
|
73
89
|
*/
|
|
74
90
|
function printTestSteps(executedCount, allSteps, testTitle, outputDir) {
|
|
75
|
-
|
|
76
|
-
console.log(' Steps: none');
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
const totalCount = allSteps.length;
|
|
80
|
-
console.log(` Steps (${executedCount}/${totalCount}):`);
|
|
91
|
+
console.log('');
|
|
81
92
|
allSteps.forEach((step, stepIndex) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
if (step.statusName === 'In Progress') {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
let stepTitle;
|
|
97
|
+
switch (step.statusName) {
|
|
98
|
+
case 'fail':
|
|
99
|
+
stepTitle = `\x1b[31m ${step.stepTitle}\x1b[0m`;
|
|
100
|
+
break;
|
|
101
|
+
default:
|
|
102
|
+
stepTitle = step.stepTitle;
|
|
103
|
+
break;
|
|
90
104
|
}
|
|
105
|
+
const statusEmoji = step.statusName === 'pass' ? '\x1b[32mPASSED ✓\x1b[0m' : step.statusName === 'fail' ? '\x1b[31mFAILED ✗\x1b[0m' : step.statusName === 'In Progress' ? '\x1b[30mSKIPPED ⊘\x1b[0m' : '⏱️';
|
|
106
|
+
console.log(`\x1b[30mSTEP ${stepIndex + 1}:\x1b[0m ${stepTitle}`);
|
|
91
107
|
printStepAttachments(step, testTitle, outputDir, stepIndex + 1);
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
if (step.error) {
|
|
109
|
+
const stackLines = step.error.message.split('\n').slice(0, 4);
|
|
110
|
+
console.log('\n\n\x1b[41m ERROR \x1b[0m\n');
|
|
111
|
+
stackLines.forEach((line) => console.log(`${line}`));
|
|
112
|
+
console.log('\n\x1b[41m ERROR \x1b[0m\n\n');
|
|
113
|
+
}
|
|
114
|
+
;
|
|
115
|
+
if (!step.error) {
|
|
116
|
+
console.log(`\n\x1b[30mstatus:\x1b[0m ${statusEmoji}\x1b[0m`);
|
|
117
|
+
console.log('\x1b[30m‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾\x1b[0m\n\n');
|
|
118
|
+
}
|
|
119
|
+
;
|
|
94
120
|
});
|
|
95
121
|
}
|
|
96
122
|
/**
|
|
@@ -104,14 +130,14 @@ function printStepAttachments(step, testTitle, outputDir, _stepNumber) {
|
|
|
104
130
|
if (!step.actualResult || step.actualResult.length === 0) {
|
|
105
131
|
return;
|
|
106
132
|
}
|
|
107
|
-
console.log(`
|
|
133
|
+
console.log(`\x1b[30mscreenshot:\x1b[0m`);
|
|
108
134
|
step.actualResult.forEach((att) => {
|
|
109
135
|
const isErrorScreenshot = att.fileName?.includes('ERROR');
|
|
110
136
|
const emoji = isErrorScreenshot ? '💥' : att.image === 'image/png' ? '📸' : '📄';
|
|
111
|
-
const displayName = att.image === 'image/png' ? '
|
|
112
|
-
console.log(`
|
|
137
|
+
const displayName = att.image === 'image/png' ? '\x1b[30mDecode:\x1b[0m Base64' : att.fileName;
|
|
138
|
+
console.log(` ${emoji} ${displayName}`);
|
|
113
139
|
if (att.body && att.image === 'text/plain') {
|
|
114
|
-
console.log(
|
|
140
|
+
console.log(`${att.body}`);
|
|
115
141
|
}
|
|
116
142
|
const config = (0, config_1.getZestConfig)();
|
|
117
143
|
const shouldSaveScreenshots = config.screenshots.saveToDisk || process.env.SAVE_SCREENSHOTS === 'true';
|
|
@@ -124,11 +150,11 @@ function printStepAttachments(step, testTitle, outputDir, _stepNumber) {
|
|
|
124
150
|
else {
|
|
125
151
|
(0, save_screenshots_1.saveBase64Screenshot)(att.body, filename, 'screenshots', testTitle);
|
|
126
152
|
}
|
|
127
|
-
console.log(`
|
|
128
|
-
console.log(`
|
|
153
|
+
console.log(` \x1b[30m💾 saved:\x1b[0m Locally`);
|
|
154
|
+
console.log(` \x1b[30m📄 name:\x1b[0m ${filename}`);
|
|
129
155
|
}
|
|
130
156
|
catch (error) {
|
|
131
|
-
console.error(`
|
|
157
|
+
console.error(` ⚠️ Error saving screenshot: ${error}`);
|
|
132
158
|
}
|
|
133
159
|
}
|
|
134
160
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { TestInfo,
|
|
1
|
+
import type { TestInfo, Page, test as base } from '@playwright/test';
|
|
2
2
|
/**
|
|
3
3
|
* Wraps test.step to automatically create screenshots after each test step
|
|
4
4
|
* @param test - Playwright test object
|
|
5
5
|
* @param getCurrentContext - Function to get current test context (testInfo and page)
|
|
6
6
|
*/
|
|
7
|
-
export declare function wrapTestStepWithScreenshots(test:
|
|
7
|
+
export declare function wrapTestStepWithScreenshots(test: typeof base, getCurrentContext: () => {
|
|
8
8
|
testInfo: TestInfo;
|
|
9
9
|
page: Page;
|
|
10
10
|
} | null): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-step-wrapper.d.ts","sourceRoot":"","sources":["../../utils/test-step-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"test-step-wrapper.d.ts","sourceRoot":"","sources":["../../utils/test-step-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAgB,IAAI,IAAI,IAAI,EAAY,MAAM,kBAAkB,CAAC;AAG7F;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,OAAO,IAAI,EACjB,iBAAiB,EAAE,MAAM;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,GACjE,IAAI,CAmCN"}
|
|
@@ -9,27 +9,25 @@ const take_screenshots_1 = require("./take-screenshots");
|
|
|
9
9
|
*/
|
|
10
10
|
function wrapTestStepWithScreenshots(test, getCurrentContext) {
|
|
11
11
|
const originalTestStep = test.step.bind(test);
|
|
12
|
-
const originalTestStepSkip = test.step.skip
|
|
12
|
+
const originalTestStepSkip = test.step.skip.bind(test);
|
|
13
|
+
const takeScreenshot = async (title) => {
|
|
14
|
+
const context = getCurrentContext();
|
|
15
|
+
try {
|
|
16
|
+
await (0, take_screenshots_1.takeScreenshotAfterStep)(context.page, context.testInfo, title);
|
|
17
|
+
}
|
|
18
|
+
catch (screenshotError) {
|
|
19
|
+
console.error('Error taking screenshot after step error:', screenshotError);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
13
22
|
const stepWrapper = async function (title, body, options) {
|
|
14
23
|
return originalTestStep(title, async (stepInfo) => {
|
|
15
24
|
try {
|
|
16
25
|
const result = await body(stepInfo);
|
|
17
|
-
|
|
18
|
-
if (context?.page && context?.testInfo) {
|
|
19
|
-
await (0, take_screenshots_1.takeScreenshotAfterStep)(context.page, stepInfo, context.testInfo, title);
|
|
20
|
-
}
|
|
26
|
+
await takeScreenshot(title);
|
|
21
27
|
return result;
|
|
22
28
|
}
|
|
23
29
|
catch (error) {
|
|
24
|
-
|
|
25
|
-
if (context?.page && context?.testInfo) {
|
|
26
|
-
try {
|
|
27
|
-
await (0, take_screenshots_1.takeScreenshotAfterStep)(context.page, { ...stepInfo, error }, context.testInfo, title);
|
|
28
|
-
}
|
|
29
|
-
catch (screenshotError) {
|
|
30
|
-
console.error('Error taking screenshot after step error:', screenshotError);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
30
|
+
await takeScreenshot(title);
|
|
33
31
|
throw error;
|
|
34
32
|
}
|
|
35
33
|
}, options);
|
package/package.json
CHANGED