@zest-pw/test 1.0.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.
Files changed (58) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +415 -0
  3. package/dist/config.d.ts +127 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +140 -0
  6. package/dist/fixtures/fixtures.d.ts +3 -0
  7. package/dist/fixtures/fixtures.d.ts.map +1 -0
  8. package/dist/fixtures/fixtures.js +24 -0
  9. package/dist/index.d.ts +13 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +36 -0
  12. package/dist/reporter/custom-reporter.d.ts +11 -0
  13. package/dist/reporter/custom-reporter.d.ts.map +1 -0
  14. package/dist/reporter/custom-reporter.js +19 -0
  15. package/dist/reporter/result-processor.d.ts +11 -0
  16. package/dist/reporter/result-processor.d.ts.map +1 -0
  17. package/dist/reporter/result-processor.js +52 -0
  18. package/dist/reporter/test-results-store.d.ts +31 -0
  19. package/dist/reporter/test-results-store.d.ts.map +1 -0
  20. package/dist/reporter/test-results-store.js +38 -0
  21. package/dist/utils/add-file-names.d.ts +9 -0
  22. package/dist/utils/add-file-names.d.ts.map +1 -0
  23. package/dist/utils/add-file-names.js +39 -0
  24. package/dist/utils/enrich-test-results.d.ts +6 -0
  25. package/dist/utils/enrich-test-results.d.ts.map +1 -0
  26. package/dist/utils/enrich-test-results.js +113 -0
  27. package/dist/utils/parse-test-steps.d.ts +8 -0
  28. package/dist/utils/parse-test-steps.d.ts.map +1 -0
  29. package/dist/utils/parse-test-steps.js +110 -0
  30. package/dist/utils/save-json-report.d.ts +17 -0
  31. package/dist/utils/save-json-report.d.ts.map +1 -0
  32. package/dist/utils/save-json-report.js +75 -0
  33. package/dist/utils/save-screenshots.d.ts +9 -0
  34. package/dist/utils/save-screenshots.d.ts.map +1 -0
  35. package/dist/utils/save-screenshots.js +66 -0
  36. package/dist/utils/take-screenshots.d.ts +13 -0
  37. package/dist/utils/take-screenshots.d.ts.map +1 -0
  38. package/dist/utils/take-screenshots.js +34 -0
  39. package/dist/utils/terminal-reporter.d.ts +8 -0
  40. package/dist/utils/terminal-reporter.d.ts.map +1 -0
  41. package/dist/utils/terminal-reporter.js +140 -0
  42. package/dist/utils/test-result-transformer.d.ts +13 -0
  43. package/dist/utils/test-result-transformer.d.ts.map +1 -0
  44. package/dist/utils/test-result-transformer.js +109 -0
  45. package/dist/utils/test-step-wrapper.d.ts +13 -0
  46. package/dist/utils/test-step-wrapper.d.ts.map +1 -0
  47. package/dist/utils/test-step-wrapper.js +48 -0
  48. package/dist/zephyr-api/get-results-from-json.d.ts +2 -0
  49. package/dist/zephyr-api/get-results-from-json.d.ts.map +1 -0
  50. package/dist/zephyr-api/get-results-from-json.js +71 -0
  51. package/dist/zephyr-api/update-execution-result.d.ts +2 -0
  52. package/dist/zephyr-api/update-execution-result.d.ts.map +1 -0
  53. package/dist/zephyr-api/update-execution-result.js +26 -0
  54. package/dist/zephyr-api/zephyr-api.d.ts +19 -0
  55. package/dist/zephyr-api/zephyr-api.d.ts.map +1 -0
  56. package/dist/zephyr-api/zephyr-api.js +89 -0
  57. package/package.json +69 -0
  58. package/scripts/install-config.js +92 -0
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.saveTestResultsToJson = saveTestResultsToJson;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Saves test results to JSON file
41
+ *
42
+ * This function creates a JSON report from test results and saves it to the specified directory.
43
+ * If the directory doesn't exist, it will be created automatically.
44
+ *
45
+ * @param result - Object with test results to be saved
46
+ * @param outputDir - Directory for saving (default 'test-results')
47
+ * @returns Full path to the saved JSON file
48
+ * @throws Error if file cannot be saved
49
+ *
50
+ * @example
51
+ * const filepath = saveTestResultsToJson(testResults);
52
+ * console.log(`Saved to: ${filepath}`);
53
+ */
54
+ function saveTestResultsToJson(result, outputDir = 'test-results') {
55
+ try {
56
+ // Build the full path to the results directory
57
+ const resultsPath = path.join(process.cwd(), outputDir);
58
+ // Create directory if it doesn't exist (recursive: true creates parent dirs too)
59
+ if (!fs.existsSync(resultsPath)) {
60
+ fs.mkdirSync(resultsPath, { recursive: true });
61
+ }
62
+ // Define the output filename
63
+ const filename = `test-results.json`;
64
+ // Build the full file path
65
+ const filepath = path.join(resultsPath, filename);
66
+ // Convert object to JSON string with pretty formatting (2 space indentation)
67
+ // and save to file with UTF-8 encoding
68
+ fs.writeFileSync(filepath, JSON.stringify(result, null, 2), 'utf-8');
69
+ return filepath;
70
+ }
71
+ catch (error) {
72
+ console.error(`\n⚠️ Error saving JSON report: ${error}`);
73
+ throw error;
74
+ }
75
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Зберігає скріншот з base64 рядка
3
+ * @param base64String - Base64 рядок скріншоту
4
+ * @param filename - Назва файлу
5
+ * @param outputDir - Базова директорія (за замовчуванням 'screenshots')
6
+ * @param testTitle - Назва тесту (опціонально, створює підпапку для організації)
7
+ */
8
+ export declare function saveBase64Screenshot(base64String: string, filename: string, outputDir?: string, testTitle?: string): string;
9
+ //# sourceMappingURL=save-screenshots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save-screenshots.d.ts","sourceRoot":"","sources":["../../utils/save-screenshots.ts"],"names":[],"mappings":"AAUA;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAsB,EACjC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAkBR"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.saveBase64Screenshot = saveBase64Screenshot;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Декодує base64 рядок в Buffer
41
+ */
42
+ function decodeBase64ToBuffer(base64String) {
43
+ return Buffer.from(base64String, 'base64');
44
+ }
45
+ /**
46
+ * Зберігає скріншот з base64 рядка
47
+ * @param base64String - Base64 рядок скріншоту
48
+ * @param filename - Назва файлу
49
+ * @param outputDir - Базова директорія (за замовчуванням 'screenshots')
50
+ * @param testTitle - Назва тесту (опціонально, створює підпапку для організації)
51
+ */
52
+ function saveBase64Screenshot(base64String, filename, outputDir = 'screenshots', testTitle) {
53
+ let screenshotsPath = path.join(process.cwd(), outputDir);
54
+ // Якщо вказано назву тесту, створюємо окрему підпапку
55
+ if (testTitle) {
56
+ const safeTestTitle = testTitle.replace(/[^a-z0-9]/gi, '_').toLowerCase();
57
+ screenshotsPath = path.join(screenshotsPath, safeTestTitle);
58
+ }
59
+ if (!fs.existsSync(screenshotsPath)) {
60
+ fs.mkdirSync(screenshotsPath, { recursive: true });
61
+ }
62
+ const filepath = path.join(screenshotsPath, filename);
63
+ const buffer = decodeBase64ToBuffer(base64String);
64
+ fs.writeFileSync(filepath, buffer);
65
+ return filepath;
66
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Утиліта для створення скріншотів після кроків тесту
3
+ */
4
+ import type { Page, TestInfo } from "@playwright/test";
5
+ /**
6
+ * Робить скріншот після кожного кроку тесту (завжди, незалежно від результату)
7
+ *
8
+ * Для збереження скріншотів на диск (з base64 результатів):
9
+ * 1. Додайте в .env файл: SAVE_SCREENSHOTS=true
10
+ * 2. Або передайте через команду: SAVE_SCREENSHOTS=true npx playwright test
11
+ */
12
+ export declare function takeScreenshotAfterStep(page: Page, stepInfo: any, testInfo: TestInfo, stepTitle?: string): Promise<void>;
13
+ //# sourceMappingURL=take-screenshots.d.ts.map
@@ -0,0 +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;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,GAAG,EACb,QAAQ,EAAE,QAAQ,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * Утиліта для створення скріншотів після кроків тесту
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.takeScreenshotAfterStep = takeScreenshotAfterStep;
7
+ /**
8
+ * Робить скріншот після кожного кроку тесту (завжди, незалежно від результату)
9
+ *
10
+ * Для збереження скріншотів на диск (з base64 результатів):
11
+ * 1. Додайте в .env файл: SAVE_SCREENSHOTS=true
12
+ * 2. Або передайте через команду: SAVE_SCREENSHOTS=true npx playwright test
13
+ */
14
+ async function takeScreenshotAfterStep(page, stepInfo, testInfo, stepTitle) {
15
+ try {
16
+ if (page && testInfo) {
17
+ // Робимо скріншот без збереження на диск (тільки в буфер)
18
+ const screenshotBuffer = await page.screenshot({
19
+ fullPage: true
20
+ });
21
+ // Додаємо скріншот як attachment через testInfo
22
+ // Attachment автоматично прикріплюється до поточного кроку як substep
23
+ await testInfo.attach(stepTitle || stepInfo?.title || 'screenshot', {
24
+ body: screenshotBuffer,
25
+ contentType: 'image/png',
26
+ });
27
+ // Примітка: Збереження на диск відбувається в terminal-reporter.ts (якщо PRINT_TEST_RESULTS=true)
28
+ // або можна зберегти з JSON звіту вручну
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.error('Помилка при створенні скріншота кроку:', error);
33
+ }
34
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Форматує та виводить результати тестів після їх завершення
3
+ * Вивід контролюється через змінну оточення PRINT_TEST_RESULTS
4
+ *
5
+ * Очікує що result вже збагачений запланованими кроками через enrichTestResultsWithPlannedSteps
6
+ */
7
+ export declare function printTestResults(result: any): void;
8
+ //# sourceMappingURL=terminal-reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-reporter.d.ts","sourceRoot":"","sources":["../../utils/terminal-reporter.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAyBlD"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.printTestResults = printTestResults;
37
+ const path = __importStar(require("path"));
38
+ const save_screenshots_1 = require("./save-screenshots");
39
+ const config_1 = require("../config");
40
+ /**
41
+ * Форматує та виводить результати тестів після їх завершення
42
+ * Вивід контролюється через змінну оточення PRINT_TEST_RESULTS
43
+ *
44
+ * Очікує що result вже збагачений запланованими кроками через enrichTestResultsWithPlannedSteps
45
+ */
46
+ function printTestResults(result) {
47
+ if (!result.tests || !Array.isArray(result.tests)) {
48
+ return;
49
+ }
50
+ console.log('\n=== Деталі по тестах та їх кроках ===');
51
+ result.tests.forEach((test) => {
52
+ printTestInfo(test);
53
+ // test.steps вже містить всі кроки (виконані + заплановані) після enrichTestResultsWithPlannedSteps
54
+ const allSteps = test.steps || [];
55
+ const executedSteps = allSteps.filter((step) => step.statusName !== 'In Progress');
56
+ // Створюємо outputDir точно як Playwright: test-results/{filename}-{test-title}-{project}
57
+ // test.testCaseKey тепер без розширення (наприклад "TC-002")
58
+ const testFileName = test.testCaseKey || 'test';
59
+ const sanitizedTitle = test.testTitle.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-|-$/g, '');
60
+ const outputDir = path.join('test-results', `${testFileName}-${sanitizedTitle}-chromium`);
61
+ printTestSteps(executedSteps.length, allSteps, test.testTitle, outputDir);
62
+ });
63
+ console.log('\n=== Фінальне завершення ===');
64
+ }
65
+ /**
66
+ * Виводить загальну інформацію про тест
67
+ */
68
+ function printTestInfo(test) {
69
+ console.log(`\n${test.testCaseKey}: ${test.testTitle}`);
70
+ }
71
+ /**
72
+ * Виводить інформацію про кроки тесту
73
+ */
74
+ function printTestSteps(executedCount, allSteps, testTitle, outputDir) {
75
+ if (allSteps.length === 0) {
76
+ console.log(' Steps: none');
77
+ return;
78
+ }
79
+ const totalCount = allSteps.length;
80
+ console.log(` Steps (${executedCount}/${totalCount}):`);
81
+ allSteps.forEach((step, stepIndex) => {
82
+ const statusEmoji = step.statusName === 'passed' ? 'passed - ✅' : step.statusName === 'failed' ? 'failed - ❌' : step.statusName === 'In Progress' ? 'skipped - ⏭️' : '⏱️';
83
+ console.log(` ${stepIndex + 1}. ${step.stepTitle}`);
84
+ // Спочатку показуємо помилку, якщо є
85
+ if (step.error) {
86
+ console.log(` ❌ Error: ${step.error.message}`);
87
+ if (step.error.stack) {
88
+ const stackLines = step.error.stack.split('\n').slice(0, 3);
89
+ stackLines.forEach((line) => console.log(` ${line}`));
90
+ }
91
+ }
92
+ printStepAttachments(step, testTitle, outputDir, stepIndex + 1);
93
+ console.log(` Status: ${statusEmoji}`);
94
+ // Додаємо порожній рядок після кожного кроку для кращої читабельності
95
+ console.log('');
96
+ });
97
+ }
98
+ /**
99
+ * Виводить actualResult кроку
100
+ */
101
+ function printStepAttachments(step, testTitle, outputDir, _stepNumber) {
102
+ if (!step.actualResult || step.actualResult.length === 0) {
103
+ return;
104
+ }
105
+ console.log(` Screenshot:`);
106
+ step.actualResult.forEach((att) => {
107
+ const isErrorScreenshot = att.fileName?.includes('ERROR');
108
+ const emoji = isErrorScreenshot ? '💥' : att.image === 'image/png' ? '📸' : '📄';
109
+ // Для консолі виводимо "Decode: Base64"
110
+ const displayName = att.image === 'image/png' ? 'Decode: Base64' : att.fileName;
111
+ console.log(` ${emoji} ${displayName}`);
112
+ if (att.body && att.image === 'text/plain') {
113
+ // Для текстових actualResult виводимо повний текст
114
+ console.log(` ${att.body}`);
115
+ }
116
+ // Зберігаємо скріншот на диск, якщо увімкнено в конфігурації або через змінну оточення
117
+ const config = (0, config_1.getZestConfig)();
118
+ const shouldSaveScreenshots = config.screenshots.saveToDisk || process.env.SAVE_SCREENSHOTS === 'true';
119
+ if (att.body && shouldSaveScreenshots && att.image === 'image/png') {
120
+ try {
121
+ // Використовуємо fileName з actualResult
122
+ const filename = att.fileName;
123
+ // Використовуємо outputDir від Playwright або fallback на screenshots/
124
+ if (outputDir) {
125
+ // Зберігаємо в папку тесту, яку створив Playwright
126
+ (0, save_screenshots_1.saveBase64Screenshot)(att.body, filename, outputDir);
127
+ }
128
+ else {
129
+ // Fallback: зберігаємо в screenshots/ з підпапкою тесту
130
+ (0, save_screenshots_1.saveBase64Screenshot)(att.body, filename, 'screenshots', testTitle);
131
+ }
132
+ console.log(` 💾 File saved: locally`);
133
+ console.log(` 📄 File name: ${filename}`);
134
+ }
135
+ catch (error) {
136
+ console.error(` ⚠️ Error saving screenshot: ${error}`);
137
+ }
138
+ }
139
+ });
140
+ }
@@ -0,0 +1,13 @@
1
+ import type { FullResult, TestCase, TestResult } from '@playwright/test/reporter';
2
+ /**
3
+ * Transforms test results from Playwright Reporter API into extended format with detailed information about steps and attachments
4
+ *
5
+ * @param fullResult - Full test execution result from Playwright containing overall status and statistics
6
+ * @param testResults - Array of individual test results, each containing test case information and execution result
7
+ * @returns Object with 'tests' array containing transformed test cases
8
+ */
9
+ export declare function transformTestResults(_fullResult: FullResult, testResults: Array<{
10
+ test: TestCase;
11
+ result: TestResult;
12
+ }>): any;
13
+ //# sourceMappingURL=test-result-transformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-result-transformer.d.ts","sourceRoot":"","sources":["../../utils/test-result-transformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAElF;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,UAAU,EACvB,WAAW,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,GACzD,GAAG,CAIL"}
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.transformTestResults = transformTestResults;
4
+ /**
5
+ * Transforms test results from Playwright Reporter API into extended format with detailed information about steps and attachments
6
+ *
7
+ * @param fullResult - Full test execution result from Playwright containing overall status and statistics
8
+ * @param testResults - Array of individual test results, each containing test case information and execution result
9
+ * @returns Object with 'tests' array containing transformed test cases
10
+ */
11
+ function transformTestResults(_fullResult, testResults) {
12
+ return {
13
+ tests: testResults.map(({ test, result }) => transformTestCase(test, result))
14
+ };
15
+ }
16
+ /**
17
+ * Transforms individual test case with its result
18
+ *
19
+ * @param test - Test case information from Playwright
20
+ * @param result - Test execution result containing steps and status
21
+ * @returns Transformed test object with title, key, and steps
22
+ */
23
+ function transformTestCase(test, result) {
24
+ return {
25
+ testTitle: test.title,
26
+ testCaseKey: transformLocation(test.location),
27
+ _fullPath: test.location?.file, // Used in enrich-test-results.ts to find planned test steps
28
+ steps: result.steps?.map(step => transformStep(step)) || []
29
+ };
30
+ }
31
+ /**
32
+ * Transforms test location information - returns file name as testCaseKey
33
+ *
34
+ * @param location - Location object containing file path information
35
+ * @returns Test case key (file name without .spec.ts extension) or undefined
36
+ */
37
+ function transformLocation(location) {
38
+ if (!location || !location.file) {
39
+ return undefined;
40
+ }
41
+ // Extract only the file name from the full path and remove .spec.ts extension
42
+ const fileName = location.file.split('/').pop();
43
+ return fileName?.replace('.spec.ts', '');
44
+ }
45
+ /**
46
+ * Transforms error information
47
+ *
48
+ * @param error - Error object from test execution
49
+ * @returns Object with error message and stack trace, or undefined if no error
50
+ */
51
+ function transformError(error) {
52
+ if (!error) {
53
+ return undefined;
54
+ }
55
+ return {
56
+ message: error.message,
57
+ stack: error.stack
58
+ };
59
+ }
60
+ /**
61
+ * Transforms test step with attachments
62
+ *
63
+ * @param step - Step object from test execution containing title, status, and attachments
64
+ * @returns Transformed step object with title, actual results, status, and error (if any)
65
+ */
66
+ function transformStep(step) {
67
+ // Collect attachments from the step itself
68
+ let attachments = step.attachments?.map((att) => transformAttachment(att)) || [];
69
+ // Collect attachments from substeps (Playwright creates substeps for testInfo.attach())
70
+ if (step.steps && Array.isArray(step.steps)) {
71
+ step.steps.forEach((substep) => {
72
+ if (substep.attachments && substep.attachments.length > 0) {
73
+ const substepAttachments = substep.attachments.map((att) => transformAttachment(att));
74
+ attachments = attachments.concat(substepAttachments);
75
+ }
76
+ });
77
+ }
78
+ return {
79
+ stepTitle: step.title,
80
+ actualResult: attachments,
81
+ statusName: determineStepStatus(step),
82
+ error: transformError(step.error)
83
+ };
84
+ }
85
+ /**
86
+ * Determines step status
87
+ *
88
+ * @param step - Step object from test execution
89
+ * @returns Step status ('failed' if has error, otherwise step.status or 'passed')
90
+ */
91
+ function determineStepStatus(step) {
92
+ if (step.error) {
93
+ return 'failed';
94
+ }
95
+ return step.status || 'passed';
96
+ }
97
+ /**
98
+ * Transforms attachment (screenshot, video, etc.)
99
+ *
100
+ * @param att - Attachment object containing name, content type, and body
101
+ * @returns Transformed attachment with fileName, image (content type), and base64 encoded body
102
+ */
103
+ function transformAttachment(att) {
104
+ return {
105
+ fileName: att.name,
106
+ image: att.contentType,
107
+ body: att.body ? att.body.toString('base64') : undefined
108
+ };
109
+ }
@@ -0,0 +1,13 @@
1
+ import type { TestInfo, TestType, Page } from '@playwright/test';
2
+ /**
3
+ * Застосовує обгортку до test.step для автоматичного створення скріншотів
4
+ * після кожного кроку тесту
5
+ *
6
+ * @param test - Об'єкт test з Playwright
7
+ * @param getCurrentContext - Функція для отримання поточного контексту тесту
8
+ */
9
+ export declare function wrapTestStepWithScreenshots(test: TestType<any, any>, getCurrentContext: () => {
10
+ testInfo: TestInfo;
11
+ page: Page;
12
+ } | null): void;
13
+ //# sourceMappingURL=test-step-wrapper.d.ts.map
@@ -0,0 +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,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGjE;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,EACxB,iBAAiB,EAAE,MAAM;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,GACjE,IAAI,CA2CN"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wrapTestStepWithScreenshots = wrapTestStepWithScreenshots;
4
+ const take_screenshots_1 = require("./take-screenshots");
5
+ /**
6
+ * Застосовує обгортку до test.step для автоматичного створення скріншотів
7
+ * після кожного кроку тесту
8
+ *
9
+ * @param test - Об'єкт test з Playwright
10
+ * @param getCurrentContext - Функція для отримання поточного контексту тесту
11
+ */
12
+ function wrapTestStepWithScreenshots(test, getCurrentContext) {
13
+ const originalTestStep = test.step.bind(test);
14
+ const originalTestStepSkip = test.step.skip?.bind(test);
15
+ const stepWrapper = async function (title, body, options) {
16
+ return originalTestStep(title, async (stepInfo) => {
17
+ try {
18
+ // Виконуємо крок
19
+ const result = await body(stepInfo);
20
+ // Робимо скріншот після успішного виконання кроку
21
+ const context = getCurrentContext();
22
+ if (context?.page && context?.testInfo) {
23
+ await (0, take_screenshots_1.takeScreenshotAfterStep)(context.page, stepInfo, context.testInfo, title);
24
+ }
25
+ return result;
26
+ }
27
+ catch (error) {
28
+ // Якщо крок падає, все одно робимо скріншот
29
+ const context = getCurrentContext();
30
+ if (context?.page && context?.testInfo) {
31
+ try {
32
+ await (0, take_screenshots_1.takeScreenshotAfterStep)(context.page, { ...stepInfo, error }, context.testInfo, title);
33
+ }
34
+ catch (screenshotError) {
35
+ console.error('Помилка при створенні скріншота після помилки кроку:', screenshotError);
36
+ }
37
+ }
38
+ throw error;
39
+ }
40
+ }, options);
41
+ };
42
+ // Додаємо метод skip, якщо він існує
43
+ if (originalTestStepSkip) {
44
+ stepWrapper.skip = originalTestStepSkip;
45
+ }
46
+ // Замінюємо оригінальний test.step на обгортку
47
+ test.step = stepWrapper;
48
+ }
@@ -0,0 +1,2 @@
1
+ export declare function getResultsFromJson(): Promise<any>;
2
+ //# sourceMappingURL=get-results-from-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-results-from-json.d.ts","sourceRoot":"","sources":["../../zephyr-api/get-results-from-json.ts"],"names":[],"mappings":"AAsBA,wBAAsB,kBAAkB,iBAuBvC"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getResultsFromJson = getResultsFromJson;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ // Допоміжна функція для читання результатів тестів
40
+ function readTestResults() {
41
+ // Шлях до файлу з результатами тестів
42
+ const testResultsPath = path.join(process.cwd(), 'test-results', 'test-results.json');
43
+ // Перевіряємо, чи існує файл
44
+ if (!fs.existsSync(testResultsPath)) {
45
+ console.error('Test results file not found:', testResultsPath);
46
+ return null;
47
+ }
48
+ // Читаємо та парсимо JSON файл
49
+ const testResultsContent = fs.readFileSync(testResultsPath, 'utf-8');
50
+ const testResults = JSON.parse(testResultsContent);
51
+ return testResults;
52
+ }
53
+ async function getResultsFromJson() {
54
+ console.log('Getting results for Zephyr...');
55
+ const testResults = readTestResults();
56
+ if (!testResults) {
57
+ console.error('No test results found');
58
+ return null;
59
+ }
60
+ // Виключаємо testTitle та testCaseKey з кожного тесту, stepTitle з кожного кроку
61
+ // та перетворюємо масив тестів в об'єкт з ключами testCaseKey
62
+ const processedResults = testResults.tests.reduce((acc, test) => {
63
+ const { testTitle, testCaseKey, ...testData } = test;
64
+ acc[testCaseKey] = {
65
+ ...testData,
66
+ steps: test.steps.map(({ stepTitle, ...step }) => step)
67
+ };
68
+ return acc;
69
+ }, {});
70
+ return processedResults;
71
+ }
@@ -0,0 +1,2 @@
1
+ export declare function updateTestResult(): Promise<void>;
2
+ //# sourceMappingURL=update-execution-result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-execution-result.d.ts","sourceRoot":"","sources":["../../zephyr-api/update-execution-result.ts"],"names":[],"mappings":"AAOA,wBAAsB,gBAAgB,kBAyBrC"}