artes 1.7.20 → 1.7.21

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 (49) hide show
  1. package/README.md +781 -781
  2. package/assets/styles.css +4 -4
  3. package/cucumber.config.js +253 -253
  4. package/docs/ciExecutors.md +198 -198
  5. package/docs/emulationDevicesList.md +152 -152
  6. package/docs/functionDefinitions.md +2401 -2401
  7. package/docs/stepDefinitions.md +435 -435
  8. package/executer.js +266 -266
  9. package/index.js +51 -51
  10. package/package.json +56 -56
  11. package/src/helper/contextManager/browserManager.js +74 -74
  12. package/src/helper/contextManager/requestManager.js +23 -23
  13. package/src/helper/controller/elementController.js +230 -230
  14. package/src/helper/controller/findDuplicateTestNames.js +69 -69
  15. package/src/helper/controller/getEnvInfo.js +97 -97
  16. package/src/helper/controller/getExecutor.js +109 -109
  17. package/src/helper/controller/pomCollector.js +83 -83
  18. package/src/helper/controller/reportCustomizer.js +511 -511
  19. package/src/helper/controller/screenComparer.js +96 -96
  20. package/src/helper/controller/status-formatter.js +137 -137
  21. package/src/helper/controller/testCoverageCalculator.js +111 -111
  22. package/src/helper/executers/cleaner.js +23 -23
  23. package/src/helper/executers/exporter.js +19 -19
  24. package/src/helper/executers/helper.js +193 -193
  25. package/src/helper/executers/projectCreator.js +226 -226
  26. package/src/helper/executers/reportGenerator.js +91 -91
  27. package/src/helper/executers/testRunner.js +28 -28
  28. package/src/helper/executers/versionChecker.js +31 -31
  29. package/src/helper/imports/commons.js +69 -69
  30. package/src/helper/stepFunctions/APIActions.js +582 -582
  31. package/src/helper/stepFunctions/assertions.js +986 -986
  32. package/src/helper/stepFunctions/browserActions.js +87 -87
  33. package/src/helper/stepFunctions/elementInteractions.js +60 -60
  34. package/src/helper/stepFunctions/exporter.js +19 -19
  35. package/src/helper/stepFunctions/frameActions.js +72 -72
  36. package/src/helper/stepFunctions/keyboardActions.js +66 -66
  37. package/src/helper/stepFunctions/mouseActions.js +84 -84
  38. package/src/helper/stepFunctions/pageActions.js +43 -43
  39. package/src/hooks/context.js +18 -18
  40. package/src/hooks/hooks.js +287 -287
  41. package/src/stepDefinitions/API.steps.js +404 -404
  42. package/src/stepDefinitions/assertions.steps.js +1358 -1349
  43. package/src/stepDefinitions/browser.steps.js +74 -74
  44. package/src/stepDefinitions/frameActions.steps.js +76 -76
  45. package/src/stepDefinitions/keyboardActions.steps.js +264 -264
  46. package/src/stepDefinitions/mouseActions.steps.js +374 -374
  47. package/src/stepDefinitions/page.steps.js +71 -71
  48. package/src/stepDefinitions/random.steps.js +199 -199
  49. package/src/stepDefinitions/report.steps.js +5 -5
@@ -1,226 +1,226 @@
1
- #!/usr/bin/env node
2
-
3
- const fs = require("fs");
4
- const path = require("path");
5
- const { execSync } = require("child_process");
6
-
7
- function createProject(createYes, noDeps) {
8
- const projectDir = path.join(process.cwd(), "artes");
9
- const srcDir = path.join(projectDir, "tests");
10
-
11
- [
12
- projectDir,
13
- path.join(srcDir, "features"),
14
- path.join(srcDir, "POMs"),
15
- path.join(srcDir, "steps"),
16
- path.join(projectDir, ".vscode"),
17
- ].forEach((dir) => fs.mkdirSync(dir, { recursive: true }));
18
-
19
- console.log("🚀 Initializing project...");
20
- execSync(`npm init ${createYes ? "-y" : ""}`, {
21
- cwd: projectDir,
22
- stdio: "inherit",
23
- });
24
-
25
- if (!noDeps) {
26
- execSync("npm i artes@latest", { cwd: projectDir, stdio: "inherit" });
27
- console.log("📦 Setting up browsers...");
28
- execSync("npx playwright install", { cwd: projectDir, stdio: "inherit" });
29
- }
30
-
31
- const packageJsonPath = path.join(projectDir, "package.json");
32
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
33
-
34
- if (packageJson.type) {
35
- delete packageJson.type;
36
- }
37
-
38
- packageJson.scripts = {
39
- test: "npx artes",
40
- testWithReport: "npx artes -r",
41
- };
42
-
43
- packageJson.dependencies = {
44
- artes: "latest"
45
- };
46
-
47
- fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
48
-
49
- const config = `module.exports = {
50
- // Configuration options:
51
- // headless: false, // Set to true for headless browser mode
52
- // env: "", // string - Environment name for tests
53
- // variables: {} // object - Variables for tests
54
- // testPercentage: 0, // number - Minimum success rate percentage(Default: 0)
55
- // baseURL: "", // string - Base URL for API tests
56
- // paths: [], // string[] - Paths to feature files
57
- // steps: "", // string - Step definitions files
58
- // pomPath: "", // string - Path to POM files
59
- // ai: {
60
- // ai: false, // boolean - Enable AI-generated bug reports and test summaries
61
- // url: "", // string - Local AI endpoint URL (e.g., Ollama, LM Studio). Overrides model/key when set
62
- // model: "gemini 2.5 flash", // string - AI model to use (e.g., "gpt-4o", "gemini 2.5 flash", "claude sonnet", "mistral large")
63
- // key: "", // string - API key for the selected AI provider
64
- // language: "English", // string - Language for generated reports (e.g., "English", "Azerbaijani"),
65
- // maxTokens: 4000, // number - Maximum tokens for AI-generated reports (default: 4000)
66
- // maxReports: 10, // number - Maximum number of AI reports to generate per test run
67
- // },
68
- // timeout : 0, // number - Test timeout in seconds
69
- // slowMo: 0, // number - Slow down test execution (Default: 0 seconds)
70
- // parallel: 0, // number - Number of parallel workers
71
- // report: true, // boolean - Generate report
72
- // zip: false, // boolean - Generate zip of report
73
- // uploadReport: false, // boolean - Upload report to Artes Reporting System
74
- // reporterURL: "", // string - URL of the Artes Reporting System
75
- // projectName: "Artes Report", // string - Name of the project in the Artes Reporting System
76
- // projectType: "Artes", // string - Type/category of the project (e.g., UI, API)
77
- // reportPath: "./report.zip", // string - Path to the report zip file to be uploaded
78
- // logo: "", // string - Custom logo for the report sidebar. Accepts an absolute path, a relative path, or a direct image URL
79
- // brandName: "", // string - Brand name displayed next to the logo in the report sidebar
80
- // reportName: "Artes Report", // string - Report name displayed on the summary widget and in the Artes Reporting System
81
- // reportSuccess: false, // boolean - Add screenshots and video records to report also for success test cases
82
- // trace: false, // boolean - Enable tracing
83
- // reportWithTrace: false, // boolean - Include trace in report
84
- // format: [], // string[] - Formatter names/paths
85
- // formatOptions: {}, // object - Formatter options
86
- // retry: 0, // number - Retry attempts for failing tests
87
- // tags: "", // string - Tag expression to filter scenarios
88
- // backtrace: false, // boolean - Show full backtrace for errors
89
- // dryRun: false, // boolean - Prepare test run without execution
90
- // browser: "chrome", // "chrome", "firefox", "webkit"
91
- // offline: false, // boolean - Run browser in offline mode
92
- // device: "", // string - Emulate specific device (e.g., "iPhone 13", for more devices look at the documentation)
93
- // width: 1280, // number - Browser width
94
- // height: 720, // number - Browser height
95
- // maximizeScreen: true // boolean - Maximize browser window
96
- // forceExit: false, // boolean - Force process.exit() after tests
97
- // failFast: false, // boolean - Stop on first test failure
98
- // import: [], // string[] - Support code paths
99
- // language: "en", // string - Default feature file language
100
- // loader: [], // string[] - Module loader specifications
101
- // name: [], // string[] - Run scenarios matching regex
102
- // order: "defined", // string - Run order (defined/random)
103
- // publish: false, // boolean - Publish to cucumber.io
104
- // requireModule: [], // string[] - Transpilation module names
105
- // retryTagFilter: "", // string - Tag expression for retries
106
- // strict: true, // boolean - Fail on pending steps
107
- // worldParameters: {} // object - World constructor parameters
108
- };
109
- `;
110
-
111
- const featureContent = `Feature: Shopping on SauceDemo 🛒
112
-
113
- Background: Login on SauceDemo
114
- Given User is on home page of SauceDemo
115
- And User types "standard_user" in "username_input"
116
- And User types "secret_sauce" in "password_input"
117
- And User clicks "#login-button"
118
-
119
- Scenario Outline: Success Shopping
120
- And User expects to be in "https://www.saucedemo.com/inventory.html" page
121
- And User clicks "product_title"
122
- And User clicks "add_to_cart_button"
123
- And User clicks "cart_button"
124
- Then User expects "item_price" should have "$29.99" text
125
-
126
- Scenario Outline: Failed Shopping
127
- And User expects to be in "https://www.saucedemo.com/inventory.html" page
128
- And User clicks "product_title"
129
- And User clicks "add_to_cart_button"
130
- And User clicks "cart_button"
131
- Then User expects "item_price" should not have "$29.99" text
132
-
133
- `;
134
-
135
- const pomContent = JSON.stringify(
136
- {
137
- username_input: { selector: "#user-name" },
138
- password_input: "#password",
139
- login_button: "#login-button",
140
- product_title:
141
- "xpath=/html/body/div/div/div/div[2]/div/div/div/div[1]/div[2]/div[1]/a/div",
142
- add_to_cart_button: "#add-to-cart",
143
- cart_button: ".shopping_cart_link",
144
- item_price: ".inventory_item_price",
145
- },
146
- null,
147
- 2,
148
- );
149
-
150
- const stepsContent = `
151
- const {Given,context} = require("artes");
152
-
153
- // Example step definition
154
- Given("User is on home page of SauceDemo", async () => {
155
- await context.page.goto("https://www.saucedemo.com/");
156
- });
157
- `;
158
-
159
- const hooksContent = `
160
- export function BeforeStep() {
161
- // hook for before each step
162
- }
163
-
164
- export function Before() {
165
- // hook for before each test
166
- }
167
-
168
- export function BeforeAll() {
169
- // hook for before all tests
170
- }
171
-
172
- export function AfterStep() {
173
- // hook for after each step
174
- }
175
-
176
- export function After() {
177
- // hook for after each test
178
- }
179
-
180
- export function AfterAll() {
181
- // hook for after all tests
182
- }
183
- `;
184
-
185
- const vsCodeExtension = JSON.stringify({
186
- recommendations: ["CucumberOpen.cucumber-official"],
187
- });
188
-
189
- const vsCodeSettings = JSON.stringify({
190
- "cucumber.glue": [
191
- "tests/steps/*.{ts,js}",
192
- "node_modules/artes/src/stepDefinitions/*.{ts,js}",
193
- ],
194
- "cucumber.features": ["tests/features/**/*.feature"],
195
- "cucumberautocomplete.syncfeatures": true,
196
- "cucumberautocomplete.strictGherkinCompletion": true,
197
- });
198
-
199
- console.log("📂 Creating project files...");
200
-
201
- fs.writeFileSync(path.join(projectDir, "artes.config.js"), config, "utf-8");
202
- fs.writeFileSync(
203
- path.join(srcDir, "features", "example.feature"),
204
- featureContent,
205
- );
206
- fs.writeFileSync(path.join(srcDir, "POMs", "example.pom.json"), pomContent);
207
- fs.writeFileSync(path.join(srcDir, "steps", "common.steps.js"), stepsContent);
208
- fs.writeFileSync(path.join(srcDir, "steps", "hooks.js"), hooksContent);
209
-
210
- fs.writeFileSync(
211
- path.join(projectDir, ".vscode", "settings.json"),
212
- vsCodeSettings,
213
- );
214
-
215
- fs.writeFileSync(
216
- path.join(projectDir, ".vscode", "extensions.json"),
217
- vsCodeExtension,
218
- );
219
-
220
- console.log(`✨ Project created successfully in ${projectDir}!`);
221
- console.log("Happy Testing 🎉");
222
- }
223
-
224
- module.exports = {
225
- createProject,
226
- };
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { execSync } = require("child_process");
6
+
7
+ function createProject(createYes, noDeps) {
8
+ const projectDir = path.join(process.cwd(), "artes");
9
+ const srcDir = path.join(projectDir, "tests");
10
+
11
+ [
12
+ projectDir,
13
+ path.join(srcDir, "features"),
14
+ path.join(srcDir, "POMs"),
15
+ path.join(srcDir, "steps"),
16
+ path.join(projectDir, ".vscode"),
17
+ ].forEach((dir) => fs.mkdirSync(dir, { recursive: true }));
18
+
19
+ console.log("🚀 Initializing project...");
20
+ execSync(`npm init ${createYes ? "-y" : ""}`, {
21
+ cwd: projectDir,
22
+ stdio: "inherit",
23
+ });
24
+
25
+ if (!noDeps) {
26
+ execSync("npm i artes@latest", { cwd: projectDir, stdio: "inherit" });
27
+ console.log("📦 Setting up browsers...");
28
+ execSync("npx playwright install", { cwd: projectDir, stdio: "inherit" });
29
+ }
30
+
31
+ const packageJsonPath = path.join(projectDir, "package.json");
32
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
33
+
34
+ if (packageJson.type) {
35
+ delete packageJson.type;
36
+ }
37
+
38
+ packageJson.scripts = {
39
+ test: "npx artes",
40
+ testWithReport: "npx artes -r",
41
+ };
42
+
43
+ packageJson.dependencies = {
44
+ artes: "latest"
45
+ };
46
+
47
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
48
+
49
+ const config = `module.exports = {
50
+ // Configuration options:
51
+ // headless: false, // Set to true for headless browser mode
52
+ // env: "", // string - Environment name for tests
53
+ // variables: {} // object - Variables for tests
54
+ // testPercentage: 0, // number - Minimum success rate percentage(Default: 0)
55
+ // baseURL: "", // string - Base URL for API tests
56
+ // paths: [], // string[] - Paths to feature files
57
+ // steps: "", // string - Step definitions files
58
+ // pomPath: "", // string - Path to POM files
59
+ // ai: {
60
+ // ai: false, // boolean - Enable AI-generated bug reports and test summaries
61
+ // url: "", // string - Local AI endpoint URL (e.g., Ollama, LM Studio). Overrides model/key when set
62
+ // model: "gemini 2.5 flash", // string - AI model to use (e.g., "gpt-4o", "gemini 2.5 flash", "claude sonnet", "mistral large")
63
+ // key: "", // string - API key for the selected AI provider
64
+ // language: "English", // string - Language for generated reports (e.g., "English", "Azerbaijani"),
65
+ // maxTokens: 4000, // number - Maximum tokens for AI-generated reports (default: 4000)
66
+ // maxReports: 10, // number - Maximum number of AI reports to generate per test run
67
+ // },
68
+ // timeout : 0, // number - Test timeout in seconds
69
+ // slowMo: 0, // number - Slow down test execution (Default: 0 seconds)
70
+ // parallel: 0, // number - Number of parallel workers
71
+ // report: true, // boolean - Generate report
72
+ // zip: false, // boolean - Generate zip of report
73
+ // uploadReport: false, // boolean - Upload report to Artes Reporting System
74
+ // reporterURL: "", // string - URL of the Artes Reporting System
75
+ // projectName: "Artes Report", // string - Name of the project in the Artes Reporting System
76
+ // projectType: "Artes", // string - Type/category of the project (e.g., UI, API)
77
+ // reportPath: "./report.zip", // string - Path to the report zip file to be uploaded
78
+ // logo: "", // string - Custom logo for the report sidebar. Accepts an absolute path, a relative path, or a direct image URL
79
+ // brandName: "", // string - Brand name displayed next to the logo in the report sidebar
80
+ // reportName: "Artes Report", // string - Report name displayed on the summary widget and in the Artes Reporting System
81
+ // reportSuccess: false, // boolean - Add screenshots and video records to report also for success test cases
82
+ // trace: false, // boolean - Enable tracing
83
+ // reportWithTrace: false, // boolean - Include trace in report
84
+ // format: [], // string[] - Formatter names/paths
85
+ // formatOptions: {}, // object - Formatter options
86
+ // retry: 0, // number - Retry attempts for failing tests
87
+ // tags: "", // string - Tag expression to filter scenarios
88
+ // backtrace: false, // boolean - Show full backtrace for errors
89
+ // dryRun: false, // boolean - Prepare test run without execution
90
+ // browser: "chrome", // "chrome", "firefox", "webkit"
91
+ // offline: false, // boolean - Run browser in offline mode
92
+ // device: "", // string - Emulate specific device (e.g., "iPhone 13", for more devices look at the documentation)
93
+ // width: 1280, // number - Browser width
94
+ // height: 720, // number - Browser height
95
+ // maximizeScreen: true // boolean - Maximize browser window
96
+ // forceExit: false, // boolean - Force process.exit() after tests
97
+ // failFast: false, // boolean - Stop on first test failure
98
+ // import: [], // string[] - Support code paths
99
+ // language: "en", // string - Default feature file language
100
+ // loader: [], // string[] - Module loader specifications
101
+ // name: [], // string[] - Run scenarios matching regex
102
+ // order: "defined", // string - Run order (defined/random)
103
+ // publish: false, // boolean - Publish to cucumber.io
104
+ // requireModule: [], // string[] - Transpilation module names
105
+ // retryTagFilter: "", // string - Tag expression for retries
106
+ // strict: true, // boolean - Fail on pending steps
107
+ // worldParameters: {} // object - World constructor parameters
108
+ };
109
+ `;
110
+
111
+ const featureContent = `Feature: Shopping on SauceDemo 🛒
112
+
113
+ Background: Login on SauceDemo
114
+ Given User is on home page of SauceDemo
115
+ And User types "standard_user" in "username_input"
116
+ And User types "secret_sauce" in "password_input"
117
+ And User clicks "#login-button"
118
+
119
+ Scenario Outline: Success Shopping
120
+ And User expects to be in "https://www.saucedemo.com/inventory.html" page
121
+ And User clicks "product_title"
122
+ And User clicks "add_to_cart_button"
123
+ And User clicks "cart_button"
124
+ Then User expects "item_price" should have "$29.99" text
125
+
126
+ Scenario Outline: Failed Shopping
127
+ And User expects to be in "https://www.saucedemo.com/inventory.html" page
128
+ And User clicks "product_title"
129
+ And User clicks "add_to_cart_button"
130
+ And User clicks "cart_button"
131
+ Then User expects "item_price" should not have "$29.99" text
132
+
133
+ `;
134
+
135
+ const pomContent = JSON.stringify(
136
+ {
137
+ username_input: { selector: "#user-name" },
138
+ password_input: "#password",
139
+ login_button: "#login-button",
140
+ product_title:
141
+ "xpath=/html/body/div/div/div/div[2]/div/div/div/div[1]/div[2]/div[1]/a/div",
142
+ add_to_cart_button: "#add-to-cart",
143
+ cart_button: ".shopping_cart_link",
144
+ item_price: ".inventory_item_price",
145
+ },
146
+ null,
147
+ 2,
148
+ );
149
+
150
+ const stepsContent = `
151
+ const {Given,context} = require("artes");
152
+
153
+ // Example step definition
154
+ Given("User is on home page of SauceDemo", async () => {
155
+ await context.page.goto("https://www.saucedemo.com/");
156
+ });
157
+ `;
158
+
159
+ const hooksContent = `
160
+ export function BeforeStep() {
161
+ // hook for before each step
162
+ }
163
+
164
+ export function Before() {
165
+ // hook for before each test
166
+ }
167
+
168
+ export function BeforeAll() {
169
+ // hook for before all tests
170
+ }
171
+
172
+ export function AfterStep() {
173
+ // hook for after each step
174
+ }
175
+
176
+ export function After() {
177
+ // hook for after each test
178
+ }
179
+
180
+ export function AfterAll() {
181
+ // hook for after all tests
182
+ }
183
+ `;
184
+
185
+ const vsCodeExtension = JSON.stringify({
186
+ recommendations: ["CucumberOpen.cucumber-official"],
187
+ });
188
+
189
+ const vsCodeSettings = JSON.stringify({
190
+ "cucumber.glue": [
191
+ "tests/steps/*.{ts,js}",
192
+ "node_modules/artes/src/stepDefinitions/*.{ts,js}",
193
+ ],
194
+ "cucumber.features": ["tests/features/**/*.feature"],
195
+ "cucumberautocomplete.syncfeatures": true,
196
+ "cucumberautocomplete.strictGherkinCompletion": true,
197
+ });
198
+
199
+ console.log("📂 Creating project files...");
200
+
201
+ fs.writeFileSync(path.join(projectDir, "artes.config.js"), config, "utf-8");
202
+ fs.writeFileSync(
203
+ path.join(srcDir, "features", "example.feature"),
204
+ featureContent,
205
+ );
206
+ fs.writeFileSync(path.join(srcDir, "POMs", "example.pom.json"), pomContent);
207
+ fs.writeFileSync(path.join(srcDir, "steps", "common.steps.js"), stepsContent);
208
+ fs.writeFileSync(path.join(srcDir, "steps", "hooks.js"), hooksContent);
209
+
210
+ fs.writeFileSync(
211
+ path.join(projectDir, ".vscode", "settings.json"),
212
+ vsCodeSettings,
213
+ );
214
+
215
+ fs.writeFileSync(
216
+ path.join(projectDir, ".vscode", "extensions.json"),
217
+ vsCodeExtension,
218
+ );
219
+
220
+ console.log(`✨ Project created successfully in ${projectDir}!`);
221
+ console.log("Happy Testing 🎉");
222
+ }
223
+
224
+ module.exports = {
225
+ createProject,
226
+ };
@@ -1,91 +1,91 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
- const archiver = require("archiver");
4
- const { spawnSync } = require("child_process");
5
- const { moduleConfig } = require("../imports/commons");
6
- const {
7
- reportCustomizer,
8
- } = require("../../helper/controller/reportCustomizer");
9
-
10
- function generateReport() {
11
- try {
12
- console.log("📊 Generating report...");
13
-
14
- spawnSync(
15
- "allure",
16
- [
17
- "generate",
18
- "--clean",
19
- `${process.env.SINGLE_FILE_REPORT == "true" ? "--single-file" : ""}`,
20
- "allure-result",
21
- "--output",
22
- moduleConfig.reportPath,
23
- ],
24
- {
25
- cwd: moduleConfig.modulePath,
26
- stdio: "ignore",
27
- shell: true,
28
- },
29
- );
30
-
31
- console.log(
32
- `📋 Report generated successfully in ${moduleConfig.reportPath}!`,
33
- );
34
-
35
- let customizerDone = false;
36
- let customizerError = null;
37
-
38
- Promise.resolve(reportCustomizer())
39
- .then(() => {
40
- customizerDone = true;
41
- })
42
- .catch((err) => {
43
- customizerError = err;
44
- customizerDone = true;
45
- });
46
-
47
- require("deasync").loopWhile(() => !customizerDone);
48
-
49
- if (customizerError) throw customizerError;
50
-
51
- if (fs.existsSync(moduleConfig.reportPath) && process.env.ZIP === "true") {
52
- console.log(`🗜️ Zipping report folder...`);
53
-
54
- const zipPath = path.join(
55
- path.dirname(moduleConfig.reportPath),
56
- "report.zip",
57
- );
58
-
59
- let done = false;
60
- let error = null;
61
-
62
- const output = fs.createWriteStream(zipPath);
63
- const archive = archiver("zip", { zlib: { level: 9 } });
64
-
65
- output.on("close", () => {
66
- done = true;
67
- });
68
-
69
- archive.on("error", (err) => {
70
- error = err;
71
- done = true;
72
- });
73
-
74
- archive.pipe(output);
75
- archive.directory(moduleConfig.reportPath, false);
76
- archive.finalize();
77
-
78
- require("deasync").loopWhile(() => !done);
79
-
80
- console.log(
81
- `🗜️ Zipped in ${path.join(path.dirname(moduleConfig.reportPath), "report.zip")}!`,
82
- );
83
- if (error) throw error;
84
- }
85
- } catch (err) {
86
- console.error("❌ Report generation failed:", err);
87
- process.env.EXIT_CODE = 1;
88
- }
89
- }
90
-
91
- module.exports = { generateReport };
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const archiver = require("archiver");
4
+ const { spawnSync } = require("child_process");
5
+ const { moduleConfig } = require("../imports/commons");
6
+ const {
7
+ reportCustomizer,
8
+ } = require("../../helper/controller/reportCustomizer");
9
+
10
+ function generateReport() {
11
+ try {
12
+ console.log("📊 Generating report...");
13
+
14
+ spawnSync(
15
+ "allure",
16
+ [
17
+ "generate",
18
+ "--clean",
19
+ `${process.env.SINGLE_FILE_REPORT == "true" ? "--single-file" : ""}`,
20
+ "allure-result",
21
+ "--output",
22
+ moduleConfig.reportPath,
23
+ ],
24
+ {
25
+ cwd: moduleConfig.modulePath,
26
+ stdio: "ignore",
27
+ shell: true,
28
+ },
29
+ );
30
+
31
+ console.log(
32
+ `📋 Report generated successfully in ${moduleConfig.reportPath}!`,
33
+ );
34
+
35
+ let customizerDone = false;
36
+ let customizerError = null;
37
+
38
+ Promise.resolve(reportCustomizer())
39
+ .then(() => {
40
+ customizerDone = true;
41
+ })
42
+ .catch((err) => {
43
+ customizerError = err;
44
+ customizerDone = true;
45
+ });
46
+
47
+ require("deasync").loopWhile(() => !customizerDone);
48
+
49
+ if (customizerError) throw customizerError;
50
+
51
+ if (fs.existsSync(moduleConfig.reportPath) && process.env.ZIP === "true") {
52
+ console.log(`🗜️ Zipping report folder...`);
53
+
54
+ const zipPath = path.join(
55
+ path.dirname(moduleConfig.reportPath),
56
+ "report.zip",
57
+ );
58
+
59
+ let done = false;
60
+ let error = null;
61
+
62
+ const output = fs.createWriteStream(zipPath);
63
+ const archive = archiver("zip", { zlib: { level: 9 } });
64
+
65
+ output.on("close", () => {
66
+ done = true;
67
+ });
68
+
69
+ archive.on("error", (err) => {
70
+ error = err;
71
+ done = true;
72
+ });
73
+
74
+ archive.pipe(output);
75
+ archive.directory(moduleConfig.reportPath, false);
76
+ archive.finalize();
77
+
78
+ require("deasync").loopWhile(() => !done);
79
+
80
+ console.log(
81
+ `🗜️ Zipped in ${path.join(path.dirname(moduleConfig.reportPath), "report.zip")}!`,
82
+ );
83
+ if (error) throw error;
84
+ }
85
+ } catch (err) {
86
+ console.error("❌ Report generation failed:", err);
87
+ process.env.EXIT_CODE = 1;
88
+ }
89
+ }
90
+
91
+ module.exports = { generateReport };