@zest-pw/test 1.0.2 → 1.0.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"result-processor.d.ts","sourceRoot":"","sources":["../../reporter/result-processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AASlF;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,iBAwC3D"}
1
+ {"version":3,"file":"result-processor.d.ts","sourceRoot":"","sources":["../../reporter/result-processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAUlF;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,iBAiD3D"}
@@ -4,6 +4,7 @@ exports.processTestResults = processTestResults;
4
4
  const terminal_reporter_1 = require("../utils/terminal-reporter");
5
5
  const test_result_transformer_1 = require("../utils/test-result-transformer");
6
6
  const save_json_report_1 = require("../utils/save-json-report");
7
+ const save_screenshots_1 = require("../utils/save-screenshots");
7
8
  const enrich_test_results_1 = require("../utils/enrich-test-results");
8
9
  const add_file_names_1 = require("../utils/add-file-names");
9
10
  const update_execution_result_1 = require("../zephyr-api/update-execution-result");
@@ -40,6 +41,15 @@ async function processTestResults(fullResult, testResults) {
40
41
  console.error('Error printing test results:', error);
41
42
  }
42
43
  }
44
+ // Save screenshots to disk if enabled
45
+ if (config.screenshots.saveToDisk) {
46
+ try {
47
+ (0, save_screenshots_1.saveScreenshotToDisk)(finalResults);
48
+ }
49
+ catch (error) {
50
+ console.error('Error saving screenshots to disk:', error);
51
+ }
52
+ }
43
53
  // Update test results in Zephyr if enabled
44
54
  if (config.zephyr.enabled && config.zephyr.updateResults) {
45
55
  try {
@@ -7,4 +7,9 @@
7
7
  * @returns Full path to the saved screenshot file
8
8
  */
9
9
  export declare function saveBase64Screenshot(base64String: string, filename: string, outputDir?: string, testTitle?: string): string;
10
+ /**
11
+ * Saves all screenshots from test results to disk
12
+ * @param result - Test results object containing tests array with steps and actualResult attachments
13
+ */
14
+ export declare function saveScreenshotToDisk(result: any): void;
10
15
  //# sourceMappingURL=save-screenshots.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"save-screenshots.d.ts","sourceRoot":"","sources":["../../utils/save-screenshots.ts"],"names":[],"mappings":"AAYA;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAsB,EACjC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAiBR"}
1
+ {"version":3,"file":"save-screenshots.d.ts","sourceRoot":"","sources":["../../utils/save-screenshots.ts"],"names":[],"mappings":"AAaA;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAsB,EACjC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAiBR;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAwBtD"}
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.saveBase64Screenshot = saveBase64Screenshot;
37
+ exports.saveScreenshotToDisk = saveScreenshotToDisk;
37
38
  const fs = __importStar(require("fs"));
38
39
  const path = __importStar(require("path"));
39
40
  /**
@@ -66,3 +67,32 @@ function saveBase64Screenshot(base64String, filename, outputDir = 'screenshots',
66
67
  fs.writeFileSync(filepath, buffer);
67
68
  return filepath;
68
69
  }
70
+ /**
71
+ * Saves all screenshots from test results to disk
72
+ * @param result - Test results object containing tests array with steps and actualResult attachments
73
+ */
74
+ function saveScreenshotToDisk(result) {
75
+ result.tests.forEach((test) => {
76
+ const allSteps = test.steps || [];
77
+ const testFileName = test.testCaseKey || 'test';
78
+ const sanitizedTitle = test.testTitle.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-|-$/g, '');
79
+ const projectName = test.projectName || 'chromium';
80
+ const outputDir = path.join('test-results', `${testFileName}-${sanitizedTitle}-${projectName}`);
81
+ const actualResult = allSteps.map((test) => test.actualResult);
82
+ actualResult.forEach((att) => {
83
+ try {
84
+ const filename = att[0].fileName;
85
+ const body = att[0].body;
86
+ if (outputDir) {
87
+ saveBase64Screenshot(body, filename, outputDir);
88
+ }
89
+ else {
90
+ saveBase64Screenshot(body, filename);
91
+ }
92
+ }
93
+ catch (error) {
94
+ console.error(` ⚠️ Error saving screenshot: ${error}`);
95
+ }
96
+ });
97
+ });
98
+ }
@@ -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,CAsBlD"}
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,CAqClD"}
@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.printTestResults = printTestResults;
37
37
  const path = __importStar(require("path"));
38
- const save_screenshots_1 = require("./save-screenshots");
39
38
  const config_1 = require("../config");
40
39
  /**
41
40
  * Formats and prints test results after completion
@@ -48,58 +47,74 @@ function printTestResults(result) {
48
47
  }
49
48
  result.tests.forEach((test) => {
50
49
  const allSteps = test.steps || [];
51
- const executedSteps = allSteps.filter((step) => step.statusName !== 'In Progress');
52
50
  const testFileName = test.testCaseKey || 'test';
53
51
  const sanitizedTitle = test.testTitle.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-|-$/g, '');
54
52
  const projectName = test.projectName || 'chromium';
55
53
  const outputDir = path.join('test-results', `${testFileName}-${sanitizedTitle}-${projectName}`);
56
- console.log('');
57
- console.log('');
58
- console.log(`\x1b[30m––––––––––––––––––––––––––––––––––\x1b[0m ${test.testCaseKey} \x1b[30m––––––––––––––––––––––––––––––––––\x1b[0m`);
59
- printTestInfo(test);
60
- printTestSteps(executedSteps.length, allSteps, test.testTitle, outputDir);
61
- console.log('');
54
+ const testTitle = `${projectName} › ${testFileName} › ${test.testTitle}`;
55
+ const remainder = (63 - testTitle.length) < 0 ? 0 : (63 - testTitle.length);
56
+ const spaces = '\x1b[40m \x1b[0m'.repeat(remainder);
57
+ console.log(`\n\x1b[40m${testTitle}${spaces}\x1b[0m`);
58
+ printTestSteps(allSteps, test.testTitle, outputDir);
62
59
  });
63
- }
64
- /**
65
- * Prints general test information
66
- * @param test - Test object containing testCaseKey and testTitle
67
- */
68
- function printTestInfo(test) {
69
- console.log(`\n\x1b[30mTEST CASE:\x1b[0m ${test.testTitle}`);
60
+ let passedCount = 0;
61
+ let failedCount = 0;
62
+ let skippedCount = 0;
63
+ result.tests.forEach((test) => {
64
+ for (const step of test.steps) {
65
+ switch (step.statusName) {
66
+ case 'pass':
67
+ passedCount++;
68
+ break;
69
+ case 'fail':
70
+ failedCount++;
71
+ break;
72
+ case 'In Progress':
73
+ skippedCount++;
74
+ break;
75
+ }
76
+ }
77
+ });
78
+ 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`);
79
+ console.log('\n');
70
80
  }
71
81
  /**
72
82
  * Prints test step information
73
- * @param executedCount - Number of executed steps
74
83
  * @param allSteps - Array of all steps (executed and planned)
75
84
  * @param testTitle - Title of the test
76
85
  * @param outputDir - Optional output directory path for saving screenshots
77
86
  */
78
- function printTestSteps(executedCount, allSteps, testTitle, outputDir) {
79
- const totalCount = allSteps.length;
87
+ function printTestSteps(allSteps, testTitle, outputDir) {
80
88
  console.log('');
81
89
  allSteps.forEach((step, stepIndex) => {
82
- const statusEmoji = step.statusName === 'pass' ? '\x1b[32mPASSED ✓\x1b[0m' : step.statusName === 'fail' ? '\x1b[31mFAILED ✗\x1b[0m' : step.statusName === 'In Progress' ? '\x1b[30mSKIPPED ⊘\x1b[0m' : '⏱️';
83
- if (step.error) {
84
- console.log('\x1b[31m- - - - - - - - - - - - - ERROR - - - - - - - - - - - - -\x1b[0m');
85
- console.log('');
90
+ if (step.statusName === 'In Progress') {
91
+ return;
92
+ }
93
+ let stepTitle;
94
+ switch (step.statusName) {
95
+ case 'fail':
96
+ stepTitle = `\x1b[31m${step.stepTitle}\x1b[0m`;
97
+ break;
98
+ default:
99
+ stepTitle = step.stepTitle;
100
+ break;
86
101
  }
87
- console.log(`\x1b[30mTest Step ${stepIndex + 1}:\x1b[0m ${step.stepTitle}`);
102
+ const statusEmoji = step.statusName === 'pass' ? '\x1b[32mPASSED ✓\x1b[0m' : step.statusName === 'fail' ? '\x1b[31mFAILED ✗\x1b[0m' : step.statusName === 'In Progress' ? '\x1b[30mSKIPPED ⊘\x1b[0m' : '⏱️';
103
+ console.log(`\x1b[30mSTEP ${stepIndex + 1}:\x1b[0m ${stepTitle}`);
88
104
  printStepAttachments(step, testTitle, outputDir, stepIndex + 1);
89
- console.log('');
90
- console.log(`\x1b[30mstatus:\x1b[0m ${statusEmoji}\x1b[0m`);
91
- console.log('');
92
105
  if (step.error) {
93
106
  const stackLines = step.error.message.split('\n').slice(0, 4);
107
+ console.log('\n\n\x1b[41m ERROR \x1b[0m\n');
94
108
  stackLines.forEach((line) => console.log(`${line}`));
95
- console.log('');
96
- console.log('\x1b[31m- - - - - - - - - - - - - ERROR - - - - - - - - - - - - -\x1b[0m');
97
- console.log('');
109
+ console.log('\n\x1b[41m ERROR \x1b[0m\n\n');
110
+ }
111
+ ;
112
+ if (!step.error) {
113
+ console.log(`\n\x1b[30mstatus:\x1b[0m ${statusEmoji}\x1b[0m`);
114
+ console.log('\x1b[30m‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾\x1b[0m\n\n');
98
115
  }
116
+ ;
99
117
  });
100
- console.log('');
101
- console.log(`\x1b[30mTotal results:\x1b[0m \x1b[32m${executedCount} passed,\x1b[0m \x1b[31m${totalCount - executedCount} failed\x1b[0m`);
102
- console.log('');
103
118
  }
104
119
  /**
105
120
  * Prints step attachments (screenshots, etc.)
@@ -112,28 +127,17 @@ function printStepAttachments(step, testTitle, outputDir, _stepNumber) {
112
127
  if (!step.actualResult || step.actualResult.length === 0) {
113
128
  return;
114
129
  }
115
- console.log(`\x1b[30mScreenshot:\x1b[0m`);
130
+ console.log(`\x1b[30mscreenshot:\x1b[0m`);
116
131
  step.actualResult.forEach((att) => {
117
- const isErrorScreenshot = att.fileName?.includes('ERROR');
118
- const emoji = isErrorScreenshot ? '💥' : att.image === 'image/png' ? '📸' : '📄';
119
- const displayName = att.image === 'image/png' ? '\x1b[30mDecode:\x1b[0m Base64' : att.fileName;
120
- console.log(` ${emoji} ${displayName}`);
121
- if (att.body && att.image === 'text/plain') {
122
- console.log(`${att.body}`);
123
- }
132
+ const displayName = att.image === 'image/png' ? '\x1b[30m-decode:\x1b[0m Base64' : att.fileName;
133
+ console.log(` ${displayName}`);
124
134
  const config = (0, config_1.getZestConfig)();
125
135
  const shouldSaveScreenshots = config.screenshots.saveToDisk || process.env.SAVE_SCREENSHOTS === 'true';
126
- if (att.body && shouldSaveScreenshots && att.image === 'image/png') {
136
+ if (att.body && shouldSaveScreenshots) {
127
137
  try {
128
138
  const filename = att.fileName;
129
- if (outputDir) {
130
- (0, save_screenshots_1.saveBase64Screenshot)(att.body, filename, outputDir);
131
- }
132
- else {
133
- (0, save_screenshots_1.saveBase64Screenshot)(att.body, filename, 'screenshots', testTitle);
134
- }
135
- console.log(` \x1b[30m💾 File saved:\x1b[0m locally`);
136
- console.log(` \x1b[30m📄 File name:\x1b[0m ${filename}`);
139
+ console.log(` \x1b[30m -saved:\x1b[0m Locally`);
140
+ console.log(` \x1b[30m -name:\x1b[0m ${filename}`);
137
141
  }
138
142
  catch (error) {
139
143
  console.error(` ⚠️ Error saving screenshot: ${error}`);
@@ -1 +1 @@
1
- {"version":3,"file":"get-results-from-json.d.ts","sourceRoot":"","sources":["../../zephyr-api/get-results-from-json.ts"],"names":[],"mappings":"AAqBA;;;;;GAKG;AACH,wBAAsB,kBAAkB,iBAoBvC"}
1
+ {"version":3,"file":"get-results-from-json.d.ts","sourceRoot":"","sources":["../../zephyr-api/get-results-from-json.ts"],"names":[],"mappings":"AAqBA;;;;;GAKG;AACH,wBAAsB,kBAAkB,iBA+BvC"}
@@ -67,7 +67,18 @@ async function getResultsFromJson() {
67
67
  const { projectName, testTitle, testCaseKey, ...testData } = test;
68
68
  acc[testCaseKey] = {
69
69
  ...testData,
70
- steps: test.steps.map(({ stepTitle, ...step }) => step)
70
+ steps: test.steps.map(({ stepTitle, actualResult, ...step }) => {
71
+ let processedActualResult = actualResult;
72
+ if (actualResult && Array.isArray(actualResult)) {
73
+ processedActualResult = actualResult.map(item => {
74
+ return `<img src="data:${item.image || ''};base64,${item.body || ''}" alt="${item.fileName || ''}">`;
75
+ }).join('');
76
+ }
77
+ return {
78
+ actualResult: processedActualResult,
79
+ ...step
80
+ };
81
+ })
71
82
  };
72
83
  return acc;
73
84
  }, {});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zest-pw/test",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Advanced Playwright test framework with automatic screenshots, custom reporting, and Zephyr Scale integration",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",