artes 1.4.6 → 1.4.8

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/executer.js CHANGED
@@ -292,6 +292,110 @@ function testCoverageCalculation() {
292
292
  };
293
293
  }
294
294
 
295
+ function getExecutor() {
296
+ // GitHub Actions
297
+ if (process.env.GITHUB_RUN_ID) {
298
+ return {
299
+ name: "GitHub Actions",
300
+ type: "github",
301
+ buildName: `Workflow #${process.env.GITHUB_RUN_NUMBER}`,
302
+ buildOrder: Number(process.env.GITHUB_RUN_NUMBER),
303
+ buildUrl: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
304
+ };
305
+
306
+ // Jenkins
307
+ } else if (process.env.JENKINS_HOME) {
308
+ return {
309
+ name: "Jenkins",
310
+ type: "jenkins",
311
+ buildName: process.env.JOB_NAME || "Manual Run",
312
+ buildOrder: Number(process.env.BUILD_NUMBER) || 1,
313
+ buildUrl: process.env.BUILD_URL || ""
314
+ };
315
+
316
+ // GitLab CI
317
+ } else if (process.env.CI_PIPELINE_ID) {
318
+ return {
319
+ name: "GitLab CI",
320
+ type: "gitlab",
321
+ buildName: `Pipeline #${process.env.CI_PIPELINE_IID}`,
322
+ buildOrder: Number(process.env.CI_PIPELINE_IID) || 1,
323
+ buildUrl: process.env.CI_PIPELINE_URL || ""
324
+ };
325
+
326
+ // Bitbucket Pipelines
327
+ } else if (process.env.BITBUCKET_BUILD_NUMBER) {
328
+ return {
329
+ name: "Bitbucket Pipelines",
330
+ type: "bitbucket",
331
+ buildName: `Build #${process.env.BITBUCKET_BUILD_NUMBER}`,
332
+ buildOrder: Number(process.env.BITBUCKET_BUILD_NUMBER),
333
+ buildUrl: process.env.BITBUCKET_BUILD_URL || ""
334
+ };
335
+
336
+ // CircleCI
337
+ } else if (process.env.CIRCLE_WORKFLOW_ID) {
338
+ return {
339
+ name: "CircleCI",
340
+ type: "circleci",
341
+ buildName: `Workflow #${process.env.CIRCLE_WORKFLOW_ID}`,
342
+ buildOrder: Number(process.env.CIRCLE_BUILD_NUM) || 1,
343
+ buildUrl: process.env.CIRCLE_BUILD_URL || ""
344
+ };
345
+
346
+ // Azure Pipelines
347
+ } else if (process.env.BUILD_BUILDID) {
348
+ return {
349
+ name: "Azure Pipelines",
350
+ type: "azure",
351
+ buildName: `Build #${process.env.BUILD_BUILDID}`,
352
+ buildOrder: Number(process.env.BUILD_BUILDID) || 1,
353
+ buildUrl: process.env.BUILD_BUILDURI || ""
354
+ };
355
+
356
+ // TeamCity
357
+ } else if (process.env.BUILD_NUMBER && process.env.TEAMCITY_VERSION) {
358
+ return {
359
+ name: "TeamCity",
360
+ type: "teamcity",
361
+ buildName: `Build #${process.env.BUILD_NUMBER}`,
362
+ buildOrder: Number(process.env.BUILD_NUMBER) || 1,
363
+ buildUrl: process.env.BUILD_URL || ""
364
+ };
365
+
366
+ // Travis CI
367
+ } else if (process.env.TRAVIS_BUILD_NUMBER) {
368
+ return {
369
+ name: "Travis CI",
370
+ type: "travis",
371
+ buildName: `Build #${process.env.TRAVIS_BUILD_NUMBER}`,
372
+ buildOrder: Number(process.env.TRAVIS_BUILD_NUMBER) || 1,
373
+ buildUrl: process.env.TRAVIS_BUILD_WEB_URL || ""
374
+ };
375
+
376
+ // Bamboo
377
+ } else if (process.env.bamboo_buildNumber) {
378
+ return {
379
+ name: "Bamboo",
380
+ type: "bamboo",
381
+ buildName: `Build #${process.env.bamboo_buildNumber}`,
382
+ buildOrder: Number(process.env.bamboo_buildNumber) || 1,
383
+ buildUrl: process.env.bamboo_resultsUrl || ""
384
+ };
385
+
386
+ // Default fallback (local/manual)
387
+ } else {
388
+ return {
389
+ name: "Local Run",
390
+ type: "local",
391
+ buildName: "Manual Execution",
392
+ buildOrder: 1,
393
+ buildUrl: ""
394
+ };
395
+ }
396
+ }
397
+
398
+
295
399
  function main() {
296
400
  if (flags.help) return showHelp();
297
401
  if (flags.version) return showVersion();
@@ -332,13 +436,21 @@ if (fs.existsSync(path.join(process.cwd(), "node_modules", "artes" , "@rerun.txt
332
436
  });
333
437
  }
334
438
 
439
+
440
+
335
441
  if (
336
442
  flags.reportWithTrace ||
337
443
  artesConfig.reportWithTrace ||
338
444
  flags.report ||
339
445
  artesConfig.report
340
- )
341
- generateReport();
446
+ ){
447
+ const executor = getExecutor();
448
+ fs.writeFileSync(
449
+ path.join(process.cwd(), "node_modules", "artes",'allure-result',"executor.json"),
450
+ JSON.stringify(executor, null, 2)
451
+ );
452
+ generateReport();
453
+ }
342
454
 
343
455
 
344
456
  if (!( process.env.TRACE === "true"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "artes",
3
- "version": "1.4.6",
3
+ "version": "1.4.8",
4
4
  "description": "The simplest way to automate UI and API tests using Cucumber-style steps.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -94,12 +94,13 @@ function getElement(element) {
94
94
  return locator;
95
95
  }
96
96
 
97
- function extractVarsFromResponse(responseBody, vars, customVarName) {
97
+ function extractVarsFromResponse(responseBody, vars, customVarNames) {
98
+
98
99
  function getValueByPath(obj, path) {
99
100
  const keys = path.split(".");
100
101
  let current = obj;
101
102
 
102
- if (typeof obj == "string") return obj;
103
+ if (typeof obj === "string") return obj;
103
104
 
104
105
  for (const key of keys) {
105
106
  if (current && typeof current === "object" && key in current) {
@@ -112,11 +113,28 @@ function extractVarsFromResponse(responseBody, vars, customVarName) {
112
113
  return current;
113
114
  }
114
115
 
115
- vars.split(",").forEach((v) => {
116
- const path = v.trim();
116
+
117
+ const varPaths = vars.split(",").map(v => v.trim());
118
+ let customNames = [];
119
+
120
+ if (typeof customVarNames === "string") {
121
+ customNames = customVarNames.split(",").map(n => n.trim());
122
+ } else if (Array.isArray(customVarNames)) {
123
+ customNames = customVarNames;
124
+ } else {
125
+ throw new Error("customVarNames must be a string or an array");
126
+ }
127
+
128
+
129
+ if (customNames.length !== varPaths.length) {
130
+ customNames = varPaths;
131
+ }
132
+
133
+
134
+ varPaths.forEach((path, index) => {
117
135
  const value = getValueByPath(responseBody, path);
118
136
  if (value !== undefined) {
119
- saveVar(value, customVarName, path);
137
+ saveVar(value, customNames[index], path);
120
138
  }
121
139
  });
122
140
  }
@@ -136,43 +154,43 @@ function saveVar(value, customName, path) {
136
154
  }
137
155
  }
138
156
 
139
- function resolveVariable(template) {
140
- if (typeof template === "string") {
141
- return template.replace(/{{\s*(\w+)\s*}}/g, (_, varName) => {
142
- let value = context.vars[varName];
143
-
144
- if (value !== undefined) {
145
- if (typeof value !== "string") {
146
- try {
147
- value = JSON.stringify(value);
148
- } catch {
149
- value = String(value);
150
- }
151
- }
152
-
153
- return value
154
- .replace(/\n/g, "\\n")
155
- .replace(/\r/g, "\\r")
156
- .replace(/\t/g, "\\t");
157
+ function extractVarsFromResponse(responseBody, vars, customVarName) {
158
+ function getValueByPath(obj, path) {
159
+ const keys = path.split(".");
160
+ let current = obj;
161
+
162
+ if (typeof obj == "string") return obj;
163
+
164
+ for (const key of keys) {
165
+ if (current && typeof current === "object" && key in current) {
166
+ current = current[key];
167
+ } else {
168
+ return undefined;
157
169
  }
170
+ }
158
171
 
159
- return `{{${varName}}}`;
160
- });
172
+ return current;
161
173
  }
162
174
 
163
- if (Array.isArray(template)) {
164
- return template.map((item) => resolveVariable(item));
165
- }
175
+ const varList = vars.split(",").map((v) => v.trim());
176
+ const customVarNames = customVarName
177
+ ? customVarName.split(",").map((n) => n.trim())
178
+ : [];
166
179
 
167
- if (template && typeof template === "object") {
168
- const result = {};
169
- for (const key in template) {
170
- result[key] = resolveVariable(template[key]);
180
+ varList.forEach((path, index) => {
181
+ const value = getValueByPath(responseBody, path);
182
+ if (value !== undefined) {
183
+ let resolvedName;
184
+ if (customVarNames.length === 0) {
185
+ resolvedName = undefined;
186
+ } else if (customVarNames.length === 1) {
187
+ resolvedName = customVarNames[0];
188
+ } else {
189
+ resolvedName = customVarNames[index] ?? path;
190
+ }
191
+ saveVar(value, resolvedName, path);
171
192
  }
172
- return result;
173
- }
174
-
175
- return template;
193
+ });
176
194
  }
177
195
 
178
196
  module.exports = {
@@ -21,7 +21,6 @@ const { moduleConfig, saveVar } = require("artes/src/helper/imports/commons");
21
21
  require("allure-cucumberjs");
22
22
  const allure = require("allure-js-commons");
23
23
 
24
- const statusDir = path.join(process.cwd(), "testsStatus");
25
24
  const HTTP_METHODS = ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"];
26
25
 
27
26
  /* ------------------- Helpers ------------------- */
@@ -37,7 +36,7 @@ async function attachResponse(attachFn) {
37
36
  ? `${key}:\n${JSON.stringify(value, null, 2)}`
38
37
  : `${key}:\n${value}`;
39
38
 
40
- await attachFn(key, text, "text/plain");
39
+ await attachFn(key, text, "application/json");
41
40
  }
42
41
  }
43
42
 
@@ -58,6 +57,23 @@ if (fs.existsSync(projectHooksPath)) {
58
57
  projectHooks = {};
59
58
  }
60
59
 
60
+ // const mergedParams = {};
61
+
62
+ // function mergeObjects(target, source) {
63
+ // for (const key in source) {
64
+ // if (
65
+ // source[key] &&
66
+ // typeof source[key] === 'object' &&
67
+ // !Array.isArray(source[key])
68
+ // ) {
69
+ // if (!target[key]) target[key] = {};
70
+ // mergeObjects(target[key], source[key]);
71
+ // } else {
72
+ // target[key] = source[key];
73
+ // }
74
+ // }
75
+ // }
76
+
61
77
  /* ------------------- Hooks ------------------- */
62
78
 
63
79
  BeforeAll(async () => {
@@ -126,6 +142,12 @@ BeforeStep(async ({ pickleStep }) => {
126
142
  context.response = {};
127
143
  }
128
144
 
145
+ // if (pickleStep.argument?.docString?.content) {
146
+ // const resolvedParams = (await pickleStep.argument.docString.content) && resolveVariable(pickleStep.argument.docString.content)
147
+ // const parsedParams = JSON.parse(resolvedParams);
148
+ // mergeObjects(mergedParams, parsedParams);
149
+ // }
150
+
129
151
  if (typeof projectHooks.BeforeStep === "function") {
130
152
  await projectHooks.BeforeStep();
131
153
  }
@@ -146,6 +168,9 @@ After(async function ({result, pickle}) {
146
168
  await projectHooks.After();
147
169
  }
148
170
 
171
+ context.response = await {};
172
+ allure.attachment('Variables', JSON.stringify(context.vars, null, 2), 'application/json')
173
+
149
174
  const shouldReport =
150
175
  cucumberConfig.default.successReport || result?.status !== Status.PASSED;
151
176
 
@@ -178,8 +203,6 @@ After(async function ({result, pickle}) {
178
203
  }
179
204
  }
180
205
 
181
- await attachResponse(allure.attachment);
182
- context.response = await {};
183
206
 
184
207
  await context.page?.close();
185
208
  await context.browserContext?.close();
@@ -24,6 +24,7 @@ When(
24
24
  "User types {string} by hand in {int} th of {string}",
25
25
  async (text, order, elements) => {
26
26
  const nthElement = await frame.nth(elements, order);
27
+ text = resolveVariable(text)
27
28
  await nthElement.pressSequentially(text);
28
29
  },
29
30
  );
@@ -55,6 +56,7 @@ When(
55
56
  "User types {string} in {int} th of {string}",
56
57
  async (text, order, elements) => {
57
58
  const nthElement = await frame.nth(elements, order);
59
+ text = resolveVariable(text)
58
60
  await nthElement.fill(text);
59
61
  },
60
62
  );
@@ -65,6 +67,7 @@ When(
65
67
  const elementCount = await frame.count(selectors);
66
68
  value = await resolveVariable(value);
67
69
  for (let i = 0; i < elementCount; i++) {
70
+ value = resolveVariable(value)
68
71
  await frame.nth(selectors, i).fill(value);
69
72
  }
70
73
  },