artes 1.1.21 → 1.1.24

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/README.md CHANGED
@@ -42,30 +42,32 @@ npx artes [options]
42
42
 
43
43
  ### Options
44
44
 
45
- | Option | Description | Usage Example |
46
- | ------------------ | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
47
- | 🆘 `-h, --help` | Show the usage options | `artes -h` or `artes --help` |
48
- | 🏷️ `-v, --version` | Show the current version of Artes | `artes -v` or `artes --version` |
49
- | 🏗️ `-c, --create` | Create an example project with Artes | `artes -c` or `artes --create` |
50
- | ✅ `-y, --yes` | Skip the confirmation prompt when creating an example project | `artes -c -y` or `artes --create --yes` |
51
- | 📊 `-r, --report` | Run tests and generate Allure report | `artes -r` or `artes --report` |
52
- | `--reportSuccess` | Add screenshots and video records for also Success test cases | `artes --reportSuccess` |
53
- | 📁 `--features` | Specify one or more feature files' relative paths to run (comma-separated) | `artes --features "tests/features/Alma,tests/features/Banan.feature"` |
54
- | 📜 `--stepDef` | Specify one or more step definition files' relative paths to use (comma-separated) | `artes --stepDef "tests/steps/login.js,tests/steps/home.js"` |
55
- | 🔖 `--tags` | Run tests with specified Cucumber tags | `artes --tags "@smoke or @wip"` |
56
- | 🌐 `--env` | Set the environment for the test run | `artes --env "dev"` |
57
- | 🕶️ `--headless` | Run browser in headless mode | `artes --headless` |
58
- | `--parallel` | Run tests in parallel mode | `artes --parallel 2` |
59
- | 🔁 `--retry` | Retry failed tests | `artes --retry 3` |
60
- | 🎭 `--dryRun` | Perform a dry run without executing tests | `artes --dryRun` |
61
- | 📈 `--percentage` | Set minimum success percentage to pass test run (default is 0) | `artes --percentage 85` |
62
- | 🌍 `--browser` | Specify browser to use (`chromium`, `firefox`, or `webkit`) | `artes --browser chromium` |
63
- | 🔗 `--baseURL` | Set base URL for the tests | `artes --baseURL "https://example.com"` |
64
- | 🖥️ `--maxScreen` | Maximize browser window on launch | `artes --maxScreen` |
65
- | 📏 `--width` | Set browser width (default is 1280) | `artes --width 1920` |
66
- | 📐 `--height` | Set browser height (default is 720) | `artes --height 1080` |
67
- | ⏱️ `--timeout` | Set timeout for each test step in seconds (default is 30 seconds) | `artes --timeout 10` |
68
- | 🐢 `--slowMo` | Slow down text execution for clear view (default: 0 seconds) | `artes --slowMo 1` |
45
+ | Option | Description | Usage Example |
46
+ | ------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
47
+ | 🆘 `-h, --help` | Show the usage options | `artes -h` or `artes --help` |
48
+ | 🏷️ `-v, --version` | Show the current version of Artes | `artes -v` or `artes --version` |
49
+ | 🏗️ `-c, --create` | Create an example project with Artes | `artes -c` or `artes --create` |
50
+ | ✅ `-y, --yes` | Skip the confirmation prompt when creating an example project | `artes -c -y` or `artes --create --yes` |
51
+ | 📊 `-r, --report` | Run tests and generate Allure report | `artes -r` or `artes --report` |
52
+ | `--reportSuccess` | Add screenshots and video records for also Success test cases | `artes --reportSuccess` |
53
+ | `--trace` | Enable tracing | `artes --trace ` |
54
+ | `-rwt, --reportWithTrace` | Add trace to the report | `artes -rwt` or `artes --reportWithTrace` |
55
+ | 📁 `--features` | Specify one or more feature files' relative paths to run (comma-separated) | `artes --features "tests/features/Alma,tests/features/Banan.feature"` |
56
+ | 📜 `--stepDef` | Specify one or more step definition files' relative paths to use (comma-separated) | `artes --stepDef "tests/steps/login.js,tests/steps/home.js"` |
57
+ | 🔖 `--tags` | Run tests with specified Cucumber tags | `artes --tags "@smoke or @wip"` |
58
+ | 🌐 `--env` | Set the environment for the test run | `artes --env "dev"` |
59
+ | 🕶️ `--headless` | Run browser in headless mode | `artes --headless` |
60
+ | `--parallel` | Run tests in parallel mode | `artes --parallel 2` |
61
+ | 🔁 `--retry` | Retry failed tests | `artes --retry 3` |
62
+ | 🎭 `--dryRun` | Perform a dry run without executing tests | `artes --dryRun` |
63
+ | 📈 `--percentage` | Set minimum success percentage to pass test run (default is 0) | `artes --percentage 85` |
64
+ | 🌍 `--browser` | Specify browser to use (`chromium`, `firefox`, or `webkit`) | `artes --browser chromium` |
65
+ | 🔗 `--baseURL` | Set base URL for the tests | `artes --baseURL "https://example.com"` |
66
+ | 🖥️ `--maxScreen` | Maximize browser window on launch | `artes --maxScreen` |
67
+ | 📏 `--width` | Set browser width (default is 1280) | `artes --width 1920` |
68
+ | 📐 `--height` | Set browser height (default is 720) | `artes --height 1080` |
69
+ | ⏱️ `--timeout` | Set timeout for each test step in seconds (default is 30 seconds) | `artes --timeout 10` |
70
+ | 🐢 `--slowMo` | Slow down text execution for clear view (default: 0 seconds) | `artes --slowMo 1` |
69
71
 
70
72
  \*\* To just run the tests: <br>
71
73
  Globally: artes <br>
@@ -173,6 +175,86 @@ Feature: Searching on Google 🔍
173
175
 
174
176
  ---
175
177
 
178
+ ## 🌍 Environment Variables Configuration
179
+
180
+ Artes now supports environment-specific configurations through environment variables. This feature allows you to manage different settings for development, staging, and production environments.
181
+
182
+ ### Setting Up Environment Variables
183
+
184
+ 1. **Configure Environment in artes.config.js:**
185
+
186
+ ```javascript
187
+ module.exports = {
188
+ baseURL: {
189
+ dev: "https://dev.dlp.az",
190
+ pre: "https://pre.dlp.az",
191
+ prod: "https://api.dlp.az",
192
+ },
193
+ env: "dev", // Specify which environment to use
194
+ // ... other configurations
195
+ };
196
+ ```
197
+
198
+ **Alternative single URL configuration:**
199
+
200
+ ```javascript
201
+ module.exports = {
202
+ baseURL: "https://api.example.com", // Direct string URL
203
+ env: "dev",
204
+ // ... other configurations
205
+ };
206
+ ```
207
+
208
+ 2. **Create Environment Variable Files:**
209
+ Create JSON files under `src/tests/environment-variables/` folder with names matching your environment:
210
+
211
+ **dev.json:**
212
+
213
+ ```json
214
+ {
215
+ "api_key": "dev-api-key-12345",
216
+ "auth_token": "dev-auth-token",
217
+ "database_url": "dev-db.example.com",
218
+ "timeout": 5000,
219
+ "headers": {
220
+ "Authorization": "Bearer dev-token",
221
+ "Content-Type": "application/json"
222
+ }
223
+ }
224
+ ```
225
+
226
+ **pre.json:**
227
+
228
+ ```json
229
+ {
230
+ "api_key": "pre-api-key-67890",
231
+ "auth_token": "pre-auth-token",
232
+ "database_url": "pre-db.example.com",
233
+ "timeout": 3000,
234
+ "headers": {
235
+ "Authorization": "Bearer pre-token",
236
+ "Content-Type": "application/json"
237
+ }
238
+ }
239
+ ```
240
+
241
+ ### How It Works
242
+
243
+ 1. **Environment Detection:** When Artes runs, it reads the `env` value from `artes.config.js`
244
+ 2. **Base URL Resolution:** If `baseURL` is an object, it uses the environment key to find the corresponding URL. If `baseURL` is a string, it uses it directly
245
+ 3. **Variable Loading:** Artes looks for a JSON file matching the environment name in `src/tests/environment-variables/`
246
+ 4. **Runtime Access:** All variables from the environment file become available during test execution
247
+
248
+ ### Important Notes
249
+
250
+ - ⚠️ **Base URLs must be defined in `artes.config.js`** - they cannot be set in the environment variable JSON files
251
+ - 📁 Environment variable files should be placed in `src/tests/environment-variables/`
252
+ - 🏷️ File names must exactly match the environment name (e.g., `dev.json` for `env: "dev"`)
253
+ - 🔄 Variables are loaded into variable storage and can be accessed during test runs
254
+ - 🌐 Use environment variables for headers, API keys, timeouts, and other environment-specific configurations
255
+
256
+ ---
257
+
176
258
  ## 🛠️ Customization
177
259
 
178
260
  ## ✍️ Writing Custom Step Definitions
@@ -295,7 +377,10 @@ You can configure Artes by editing the `artes.config.js` file. Below are the def
295
377
  | `pomPath` | `moduleConfig.pomPath` | Path to Page Object Models. |
296
378
  | `import` | `[]` | Support code paths. |
297
379
  | `testPercentage` | `0` | Define test coverage percentage |
298
- | `reportSuccess` | `true` | Add screenshots and video records for also success test cases |
380
+ | `report` | `false` | Generate report |
381
+ | `reportSuccess` | `false` | Add screenshots and video records for also success test cases |
382
+ | `trace` | `false` | Enable trace |
383
+ | `reportWithTrace` | `false` | Add trace to the report |
299
384
  | `format` | `["rerun:@rerun.txt", "allure-cucumberjs/reporter"]` | Formatter names/paths. |
300
385
  | `formatOptions` | `{ "resultsDir": "allure-result" }` | Formatter options. |
301
386
  | `parallel` | `1` | Number of parallel workers. |
@@ -58,10 +58,23 @@ module.exports = {
58
58
  : moduleConfig.pomPath,
59
59
  import: artesConfig.import || [], // Support code paths
60
60
 
61
+ report:
62
+ process.env.REPORT_WITH_TRACE ??
63
+ artesConfig.reportWithTrace ??
64
+ process.env.REPORT ??
65
+ artesConfig.report ??
66
+ false, // Generate report
61
67
  // Formatting and output
62
68
  successReport: process.env.REPORT_SUCCESS
63
69
  ? true
64
70
  : artesConfig.reportSuccess || false, // Include successful tests in report
71
+
72
+ trace: process.env.TRACE ? process.env.TRACE : artesConfig.trace || false, // Enable tracing
73
+
74
+ reportWithTrace: process.env.REPORT_WITH_TRACE
75
+ ? process.env.REPORT_WITH_TRACE
76
+ : artesConfig.reportWithTrace || false, // Include trace in report
77
+
65
78
  format: finalFormats, // Formatter names/paths
66
79
  formatOptions: artesConfig.formatOptions || {
67
80
  resultsDir: `allure-result`,
@@ -103,7 +116,12 @@ module.exports = {
103
116
  // World parameters
104
117
  worldParameters: artesConfig.worldParameters || {}, // Custom world parameters
105
118
  },
106
- env: process.env.ENV ? JSON.parse(process.env.ENV) : artesConfig.env || "",
119
+ env: process.env.ENV
120
+ ? JSON.parse(process.env.ENV)
121
+ : artesConfig.env ||
122
+ (typeof artesConfig.baseURL === "object" && artesConfig.baseURL !== null
123
+ ? Object.keys(artesConfig.baseURL)[0]
124
+ : ""),
107
125
  baseURL: process.env.BASE_URL
108
126
  ? JSON.parse(process.env.BASE_URL)
109
127
  : artesConfig?.baseURL
package/executer.js CHANGED
@@ -7,6 +7,7 @@ const {
7
7
  generateReport,
8
8
  cleanUp,
9
9
  } = require("./src/helper/executers/exporter");
10
+ const artesConfig = require("../../artes.config");
10
11
  const fs = require("fs");
11
12
  const path = require("path");
12
13
 
@@ -20,6 +21,7 @@ const flags = {
20
21
  report: args.includes("-r") || args.includes("--report"),
21
22
  reportSuccess: args.includes("--reportSuccess"),
22
23
  trace: args.includes("-t") || args.includes("--trace"),
24
+ reportWithTrace: args.includes("-rwt") || args.includes("--reportWithTrace"),
23
25
  features: args.includes("--features"),
24
26
  stepDef: args.includes("--stepDef"),
25
27
  tags: args.includes("--tags"),
@@ -56,7 +58,10 @@ const slowMo = args[args.indexOf("--slowMo") + 1];
56
58
  flags.env && console.log("Running env:", env);
57
59
  flags.env ? (process.env.ENV = JSON.stringify(env)) : "";
58
60
 
59
- flags.report
61
+ flags.reportWithTrace ||
62
+ artesConfig.reportWithTrace ||
63
+ flags.report ||
64
+ artesConfig.report
60
65
  ? (process.env.REPORT_FORMAT = JSON.stringify([
61
66
  "allure-cucumberjs/reporter:./allure-results",
62
67
  ]))
@@ -73,8 +78,12 @@ flags.features ? (process.env.FEATURES = features) : "";
73
78
  flags.stepDef && console.log("Running step definitions:", flags.stepDef);
74
79
  flags.stepDef ? (process.env.STEP_DEFINITIONS = stepDef) : "";
75
80
 
81
+ flags.report ? (process.env.REPORT = true) : "";
82
+
76
83
  flags.trace ? (process.env.TRACE = true) : "";
77
84
 
85
+ flags.reportWithTrace ? (process.env.REPORT_WITH_TRACE = true) : "";
86
+
78
87
  flags.headless &&
79
88
  console.log("Running mode:", flags.headless ? "headless" : "headed");
80
89
  flags.headless ? (process.env.MODE = JSON.stringify(true)) : false;
@@ -112,25 +121,21 @@ function main() {
112
121
  if (flags.create) return createProject(flags.createYes);
113
122
 
114
123
  runTests();
115
- if (flags.report) generateReport();
124
+ if (
125
+ flags.reportWithTrace ||
126
+ artesConfig.reportWithTrace ||
127
+ flags.report ||
128
+ artesConfig.report
129
+ )
130
+ generateReport();
116
131
 
117
132
  if (
118
133
  fs.existsSync(
119
- path.join(
120
- process.cwd(),
121
- "node_modules",
122
- "artes",
123
- "EXIT_CODE.txt",
124
- ),
134
+ path.join(process.cwd(), "node_modules", "artes", "EXIT_CODE.txt"),
125
135
  )
126
136
  ) {
127
137
  const data = fs.readFileSync(
128
- path.join(
129
- process.cwd(),
130
- "node_modules",
131
- "artes",
132
- "EXIT_CODE.txt",
133
- ),
138
+ path.join(process.cwd(), "node_modules", "artes", "EXIT_CODE.txt"),
134
139
  "utf8",
135
140
  );
136
141
  process.env.EXIT_CODE = parseInt(data, 10);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "artes",
3
- "version": "1.1.21",
3
+ "version": "1.1.24",
4
4
  "description": "The simplest way to automate UI and API tests using Cucumber-style steps.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -9,7 +9,11 @@ function pomCollector() {
9
9
  `${cucumberConfig.default.pomPath}/${file}`,
10
10
  "utf-8",
11
11
  (err, content) => {
12
- addElements(JSON.parse(content));
12
+ try {
13
+ addElements(JSON.parse(content));
14
+ } catch (error) {
15
+ console.log(`Error parsing POM file ${file}:`, error.message);
16
+ }
13
17
  },
14
18
  );
15
19
  });
@@ -27,6 +27,12 @@ function showHelp() {
27
27
 
28
28
  ✅ --reportSuccess Generate screenshot and video record with also successful tests
29
29
  Usage: artes --reportSuccess
30
+
31
+ --trace Enable tracing for all tests
32
+ Usage: artes --trace
33
+
34
+ -rwt, --reportWithTrace Include trace in the report
35
+ Usage: artes --reportWithTrace
30
36
 
31
37
  📁 --features Specify one or more feature files' relative paths to run (comma-separated)
32
38
  Usage: artes --features "tests/features/Alma, tests/features/Banan.feature"
@@ -48,7 +48,10 @@ function createProject(createYes) {
48
48
  // timeout : 0, // number - Test timeout in seconds
49
49
  // slowMo: 0, // number - Slow down test execution (Default: 0 seconds)
50
50
  // parallel: 0, // number - Number of parallel workers
51
+ //report: true / boolean - Generate report
51
52
  // reportSuccess: false, // boolean - Add screenshots and video records to report also for success test cases
53
+ // trace: false, // boolean - Enable tracing
54
+ // reportWithTrace: false, // boolean - Include trace in report
52
55
  // format: [], // string[] - Formatter names/paths
53
56
  // formatOptions: {}, // object - Formatter options
54
57
  // retry: 0, // number - Retry attempts for failing tests
@@ -35,7 +35,7 @@ const moduleConfig = {
35
35
  stepsPath: path.join(projectPath, "/tests/steps/*.js"),
36
36
  pomPath: path.join(projectPath, "/tests/POMs"),
37
37
  cleanUpPaths:
38
- "allure-result allure-results test-results @rerun.txt testsStatus EXIT_CODE.txt"
38
+ "allure-result allure-results test-results @rerun.txt testsStatus EXIT_CODE.txt",
39
39
  };
40
40
 
41
41
  module.exports = {
@@ -8,26 +8,70 @@ const {
8
8
  BeforeStep,
9
9
  AfterAll,
10
10
  } = require("@cucumber/cucumber");
11
+ const { spawnSync } = require("child_process");
11
12
  const { invokeBrowser } = require("../helper/contextManager/browserManager");
12
13
  const { invokeRequest } = require("../helper/contextManager/requestManager");
13
14
  const { pomCollector } = require("../helper/controller/pomCollector");
14
15
  const cucumberConfig = require("../../cucumber.config");
15
16
  const { context } = require("./context");
16
17
  const fs = require("fs");
17
- const { moduleConfig } = require("artes/src/helper/imports/commons");
18
18
  const path = require("path");
19
+ const { moduleConfig } = require("artes/src/helper/imports/commons");
19
20
 
20
21
  const statusDir = path.join(process.cwd(), "testsStatus");
22
+ const HTTP_METHODS = ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"];
23
+
24
+ /* ------------------- Helpers ------------------- */
21
25
 
22
26
  setDefaultTimeout(cucumberConfig.default.timeout);
23
27
 
24
- BeforeAll(async function () {
28
+ async function attachResponse(attachFn) {
29
+ if (!context.response) return;
30
+
31
+ for (const [key, value] of Object.entries(context.response)) {
32
+ const text =
33
+ typeof value === "object"
34
+ ? `${key}:\n${JSON.stringify(value, null, 2)}`
35
+ : `${key}:\n${value}`;
36
+
37
+ await attachFn(text, "text/plain");
38
+ }
39
+ }
40
+
41
+ function saveTestStatus(result, pickle) {
42
+ fs.mkdirSync(statusDir, { recursive: true });
43
+ fs.writeFileSync(
44
+ path.join(statusDir, `${result.status}-${pickle.id}.txt`),
45
+ "",
46
+ );
47
+ }
48
+
49
+ /* ------------------- Hooks ------------------- */
50
+
51
+ BeforeAll(() => {
25
52
  pomCollector();
26
53
  });
27
54
 
28
55
  Before(async function () {
29
56
  context.vars = {};
30
57
 
58
+ const envFilePath = path.join(
59
+ moduleConfig.projectPath,
60
+ "tests",
61
+ "environment_variables",
62
+ `${cucumberConfig.env}.env.json`,
63
+ );
64
+
65
+ if (fs.existsSync(envFilePath)) {
66
+ let env_vars = fs.readFileSync(envFilePath, "utf-8");
67
+ try {
68
+ env_vars = JSON.parse(env_vars);
69
+ context.vars = { ...context.vars, ...env_vars };
70
+ } catch (err) {
71
+ console.log("Error parsing environment variables JSON:", err);
72
+ }
73
+ }
74
+
31
75
  const { browser, context: browserContext } = await invokeBrowser();
32
76
  const requestInstance = await invokeRequest();
33
77
 
@@ -38,130 +82,135 @@ Before(async function () {
38
82
 
39
83
  await context.page.setDefaultTimeout(cucumberConfig.default.timeout);
40
84
 
41
- process.env.TRACE &&
42
- (await context.browserContext.tracing.start({
85
+ if (
86
+ (cucumberConfig.default.reportWithTrace || cucumberConfig.default.trace) &&
87
+ !context.response
88
+ ) {
89
+ await browserContext.tracing.start({
43
90
  sources: true,
44
91
  screenshots: true,
45
92
  snapshots: true,
46
- }));
93
+ });
94
+ }
47
95
  });
48
96
 
49
- BeforeStep(async function ({ pickleStep }) {
50
- const stepText = pickleStep.text;
51
-
52
- const methods = ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"];
53
-
54
- if (methods.some((method) => stepText.includes(method))) {
97
+ BeforeStep(({ pickleStep }) => {
98
+ if (HTTP_METHODS.some((method) => pickleStep.text.includes(method))) {
55
99
  context.response = {};
56
100
  }
57
101
  });
58
102
 
59
103
  AfterStep(async function ({ pickleStep }) {
60
- const stepText = pickleStep.text;
61
-
62
- const methods = ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"];
63
-
64
- if (methods.some((method) => stepText.includes(method))) {
65
- if (await context.response) {
66
- for (const [key, value] of Object.entries(context.response)) {
67
- let text = `${key}:\n`;
68
-
69
- if (typeof value === "object") {
70
- text += JSON.stringify(value, null, 2);
71
- } else {
72
- text += value;
73
- }
74
-
75
- await this.attach(text, "text/plain");
76
- }
77
- }
104
+ if (HTTP_METHODS.some((method) => pickleStep.text.includes(method))) {
105
+ await attachResponse(this.attach);
78
106
  }
79
107
  });
80
108
 
81
109
  After(async function ({ pickle, result }) {
82
- if (process.env.REPORT_SUCCESS || result?.status !== Status.PASSED) {
83
- let img = await context.page.screenshot({
84
- path: `./test-results/visualReport/${pickle.name}/${pickle.name}.png`,
110
+ const shouldReport =
111
+ (cucumberConfig.default.successReport ||
112
+ result?.status !== Status.PASSED) &&
113
+ !context.response;
114
+
115
+ if (shouldReport) {
116
+ const screenshotPath = path.join(
117
+ "test-results",
118
+ "visualReport",
119
+ pickle.name,
120
+ `${pickle.name}.png`,
121
+ );
122
+
123
+ const img = await context.page.screenshot({
124
+ path: screenshotPath,
85
125
  type: "png",
86
126
  });
87
- await this.attach(img, "image/png");
127
+ await this.attach(img, {
128
+ mediaType: "image/png",
129
+ fileName: `${pickle.name.replaceAll(" ", "_")}.png`,
130
+ });
88
131
  }
89
132
 
90
- fs.mkdirSync(statusDir, { recursive: true });
133
+ saveTestStatus(result, pickle);
91
134
 
92
- fs.writeFileSync(
93
- path.join(statusDir, `${result.status}-${pickle.id}.txt`),
94
- "",
135
+ const tracePath = path.join(
136
+ moduleConfig.projectPath,
137
+ `./${pickle.name.replaceAll(" ", "_")}.zip`,
95
138
  );
96
139
 
97
- process.env.TRACE &&
98
- (await context.browserContext.tracing.stop({
99
- path: path.join(moduleConfig.projectPath, "./trace.zip"),
100
- }));
140
+ if (
141
+ (cucumberConfig.default.reportWithTrace || cucumberConfig.default.trace) &&
142
+ !context.response &&
143
+ shouldReport
144
+ ) {
145
+ await context.browserContext.tracing.stop({
146
+ path: tracePath,
147
+ });
101
148
 
102
- if (context.response) {
103
- for (const [key, value] of Object.entries(context.response)) {
104
- let text = `${key}:\n`;
149
+ if (cucumberConfig.default.reportWithTrace) {
150
+ const trace = fs.readFileSync(tracePath);
105
151
 
106
- if (typeof value === "object") {
107
- text += JSON.stringify(value, null, 2);
108
- } else {
109
- text += value;
110
- }
152
+ await this.attach(trace, {
153
+ mediaType: "application/zip",
154
+ fileName: `${pickle.name.replace(/\s+/g, "_")}_trace.zip`,
155
+ });
111
156
 
112
- await this.attach(text, "text/plain");
157
+ if (!cucumberConfig.default.trace) {
158
+ spawnSync("npx", ["rimraf", tracePath], {
159
+ cwd: moduleConfig.projectPath,
160
+ stdio: "inherit",
161
+ shell: true,
162
+ });
163
+ }
113
164
  }
114
165
  }
115
166
 
116
- await context.page?.close();
167
+ await attachResponse(this.attach);
117
168
 
169
+ await context.page?.close();
118
170
  await context.browserContext?.close();
119
-
120
171
  await context.browser?.close();
121
-
122
172
  await context.request?.dispose();
123
173
 
124
- if (
125
- (process.env.REPORT_SUCCESS || result?.status !== Status.PASSED) &&
126
- context.page.video()
127
- ) {
128
- const videoPath = await context.page.video().path();
129
- await new Promise((resolve) => setTimeout(resolve, 1000));
174
+ if (shouldReport && context.page.video) {
175
+ const video = context.page.video();
176
+ if (video) {
177
+ const videoPath = await video.path();
130
178
 
131
- if (fs.existsSync(videoPath)) {
132
- const webmBuffer = await fs.readFileSync(videoPath);
133
- await this.attach(webmBuffer, "video/webm");
179
+ await new Promise((resolve) => setTimeout(resolve, 1000));
180
+
181
+ if (fs.existsSync(videoPath)) {
182
+ const webmBuffer = fs.readFileSync(videoPath);
183
+ await this.attach(webmBuffer, {
184
+ mediaType: "video/webm",
185
+ fileName: `${pickle.name.replaceAll(" ", "_")}.webm`,
186
+ });
187
+ }
134
188
  }
135
189
  }
136
190
  });
137
191
 
138
- AfterAll(async function () {
139
- if (fs.existsSync(statusDir)) {
140
- const files = fs.readdirSync(statusDir);
141
- const passedCount = files.filter(
142
- (file) => file.split("-")[0] === "PASSED",
143
- ).length;
144
- const totalTests = files.length;
145
-
146
- const successPercentage = (passedCount / totalTests) * 100;
147
- const successRate =
148
- successPercentage.toFixed(2) >= cucumberConfig.default.testPercentage;
149
-
150
- if (
151
- cucumberConfig.default.testPercentage != undefined &&
152
- !isNaN(successPercentage)
153
- ) {
154
- if (successRate) {
155
- console.log(
156
- `Tests passed required ${cucumberConfig.default.testPercentage}% success rate with ${successPercentage.toFixed(2)}% !`,
157
- );
158
- fs.writeFileSync(path.join(process.cwd(), `EXIT_CODE.txt`), "0");
159
- } else {
160
- console.log(
161
- `Tests failed at required ${cucumberConfig.default.testPercentage}% success rate with ${successPercentage.toFixed(2)}%!`,
162
- );
163
- fs.writeFileSync(path.join(process.cwd(), `EXIT_CODE.txt`), "1");
164
- }
192
+ AfterAll(() => {
193
+ if (!fs.existsSync(statusDir)) return;
194
+
195
+ const files = fs.readdirSync(statusDir);
196
+ const passedCount = files.filter((f) => f.split("-")[0] === "PASSED").length;
197
+ const totalTests = files.length;
198
+ const successPercentage = (passedCount / totalTests) * 100;
199
+
200
+ if (cucumberConfig.default.testPercentage !== undefined) {
201
+ const meetsThreshold =
202
+ successPercentage >= cucumberConfig.default.testPercentage;
203
+
204
+ if (meetsThreshold) {
205
+ console.log(
206
+ `✅ Tests passed required ${cucumberConfig.default.testPercentage}% success rate with ${successPercentage.toFixed(2)}%!`,
207
+ );
208
+ fs.writeFileSync(path.join(process.cwd(), "EXIT_CODE.txt"), "0");
209
+ } else {
210
+ console.log(
211
+ `❌ Tests failed required ${cucumberConfig.default.testPercentage}% success rate with ${successPercentage.toFixed(2)}%!`,
212
+ );
213
+ fs.writeFileSync(path.join(process.cwd(), "EXIT_CODE.txt"), "1");
165
214
  }
166
215
  }
167
216
  });