artes 1.0.52 → 1.0.54
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 +10 -7
- package/cucumber.config.js +9 -6
- package/index.js +2 -1
- package/package.json +1 -1
- package/src/helper/executers/testRunner.js +15 -6
- package/src/helper/imports/commons.js +0 -2
- package/src/helper/stepFunctions/APIActions.js +107 -95
- package/src/stepDefinitions/API.steps.js +14 -9
- package/src/stepDefinitions/assertions.steps.js +1 -1
package/README.md
CHANGED
|
@@ -42,13 +42,16 @@ npx artes [options]
|
|
|
42
42
|
|
|
43
43
|
### Options
|
|
44
44
|
|
|
45
|
-
| Option
|
|
46
|
-
|
|
|
47
|
-
| 🆘 `-h, --help`
|
|
48
|
-
| 🏷️ `-v, --version`
|
|
49
|
-
| 🏗️ `-c, --create`
|
|
50
|
-
| ✅ `-y, --yes`
|
|
51
|
-
| 📊 `-r, --report`
|
|
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
|
+
| 📁 `--features` | Specify one or more feature files to run (comma-separated) | `artes --features 'Alma, Banan'` |
|
|
53
|
+
| 🔖 `--tags` | Run tests with specified Cucumber tags | `artes --tags "@smoke or @wip"` |
|
|
54
|
+
|
|
52
55
|
|
|
53
56
|
\*\* To just run the tests: <br>
|
|
54
57
|
Globally: artes <br>
|
package/cucumber.config.js
CHANGED
|
@@ -34,9 +34,12 @@ module.exports = {
|
|
|
34
34
|
import: artesConfig.import || [], // Support code paths
|
|
35
35
|
|
|
36
36
|
// Formatting and output
|
|
37
|
-
format: process.env.REPORT_FORMAT
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
format: process.env.REPORT_FORMAT
|
|
38
|
+
? JSON.parse(process.env.REPORT_FORMAT)
|
|
39
|
+
: artesConfig.format || [
|
|
40
|
+
"rerun:@rerun.txt",
|
|
41
|
+
"allure-cucumberjs/reporter",
|
|
42
|
+
], // Formatter names/paths
|
|
40
43
|
formatOptions: artesConfig.formatOptions || {
|
|
41
44
|
resultsDir: `allure-result`,
|
|
42
45
|
}, // Formatter options
|
|
@@ -50,9 +53,9 @@ module.exports = {
|
|
|
50
53
|
backtrace: artesConfig.backtrace || false, // Show full backtrace for errors
|
|
51
54
|
|
|
52
55
|
// Filtering and organization
|
|
53
|
-
tags: process.env.RUN_TAGS
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
tags: process.env.RUN_TAGS
|
|
57
|
+
? JSON.parse(process.env.RUN_TAGS)
|
|
58
|
+
: artesConfig.tags || artesConfig.tags || "", // Tag expression to filter scenarios
|
|
56
59
|
name: artesConfig.name || [], // Run scenarios matching regex
|
|
57
60
|
order: artesConfig.order || "defined", // Run order (defined/random)
|
|
58
61
|
language: artesConfig.language || "en", // Default feature file language
|
package/index.js
CHANGED
|
@@ -9,7 +9,6 @@ const {
|
|
|
9
9
|
saveVar,
|
|
10
10
|
extractVarsFromResponse,
|
|
11
11
|
page,
|
|
12
|
-
api,
|
|
13
12
|
request,
|
|
14
13
|
random,
|
|
15
14
|
} = require("./src/helper/imports/commons");
|
|
@@ -19,6 +18,7 @@ const {
|
|
|
19
18
|
frame,
|
|
20
19
|
assert,
|
|
21
20
|
elementInteractions,
|
|
21
|
+
api,
|
|
22
22
|
} = require("./src/helper/stepFunctions/exporter");
|
|
23
23
|
|
|
24
24
|
module.exports = {
|
|
@@ -31,6 +31,7 @@ module.exports = {
|
|
|
31
31
|
saveVar,
|
|
32
32
|
extractVarsFromResponse,
|
|
33
33
|
context,
|
|
34
|
+
api,
|
|
34
35
|
random,
|
|
35
36
|
page,
|
|
36
37
|
request,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "artes",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.54",
|
|
4
4
|
"description": "The package provide step definitions and user writes feature files, and the package handles automation, with optional POM files and custom step definitions.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -3,20 +3,29 @@ const { moduleConfig } = require("../imports/commons");
|
|
|
3
3
|
const path = require("path");
|
|
4
4
|
|
|
5
5
|
function runTests(flagReport, flagTags, flagFeatures) {
|
|
6
|
-
const args = process.argv.slice(2);
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
7
|
|
|
8
8
|
const featureFiles = args[args.indexOf("--features") + 1];
|
|
9
|
-
const features =
|
|
9
|
+
const features =
|
|
10
|
+
flagFeatures &&
|
|
11
|
+
featureFiles
|
|
12
|
+
.split(",")
|
|
13
|
+
.map((f) => path.join(moduleConfig.featuresPath, `${f.trim()}.feature`));
|
|
10
14
|
|
|
11
|
-
const tags = args[args.indexOf("--tags") + 1]
|
|
15
|
+
const tags = args[args.indexOf("--tags") + 1];
|
|
12
16
|
|
|
13
|
-
flagReport
|
|
17
|
+
flagReport
|
|
18
|
+
? (process.env.REPORT_FORMAT = JSON.stringify([
|
|
19
|
+
"rerun:@rerun.txt",
|
|
20
|
+
"allure-cucumberjs/reporter",
|
|
21
|
+
]))
|
|
22
|
+
: "";
|
|
14
23
|
|
|
15
24
|
flagTags && console.log("Running tags:", tags);
|
|
16
|
-
flagTags ? process.env.RUN_TAGS = JSON.stringify(tags) : "";
|
|
25
|
+
flagTags ? (process.env.RUN_TAGS = JSON.stringify(tags)) : "";
|
|
17
26
|
|
|
18
27
|
flagFeatures && console.log("Running features:", features);
|
|
19
|
-
flagFeatures ? process.env.FEATURES = JSON.stringify(features) : "";
|
|
28
|
+
flagFeatures ? (process.env.FEATURES = JSON.stringify(features)) : "";
|
|
20
29
|
|
|
21
30
|
try {
|
|
22
31
|
console.log("🧪 Running tests...");
|
|
@@ -9,7 +9,6 @@ const {
|
|
|
9
9
|
} = require("../pomController/elementController");
|
|
10
10
|
const { faker } = require("@faker-js/faker");
|
|
11
11
|
const { context } = require("../../hooks/context");
|
|
12
|
-
const { api } = require("../stepFunctions/APIActions");
|
|
13
12
|
|
|
14
13
|
const element = getElement;
|
|
15
14
|
const selector = getSelector;
|
|
@@ -47,7 +46,6 @@ module.exports = {
|
|
|
47
46
|
random,
|
|
48
47
|
page,
|
|
49
48
|
request,
|
|
50
|
-
api,
|
|
51
49
|
context,
|
|
52
50
|
moduleConfig,
|
|
53
51
|
};
|
|
@@ -1,51 +1,63 @@
|
|
|
1
1
|
const { context, selector, resolveVariable } = require("../imports/commons");
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
function getMimeType(filePath) {
|
|
5
4
|
const ext = path.extname(filePath).toLowerCase();
|
|
6
5
|
const mimeTypes = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
".jpg": "image/jpeg",
|
|
7
|
+
".jpeg": "image/jpeg",
|
|
8
|
+
".png": "image/png",
|
|
9
|
+
".gif": "image/gif",
|
|
10
|
+
".pdf": "application/pdf",
|
|
11
|
+
".txt": "text/plain",
|
|
12
|
+
".json": "application/json",
|
|
13
|
+
".xml": "application/xml",
|
|
14
|
+
".zip": "application/zip",
|
|
15
|
+
".doc": "application/msword",
|
|
16
|
+
".docx":
|
|
17
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
18
|
+
".csv": "text/csv",
|
|
19
19
|
};
|
|
20
|
-
|
|
21
|
-
return mimeTypes[ext] ||
|
|
20
|
+
|
|
21
|
+
return mimeTypes[ext] || "application/octet-stream";
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function processForm(key, value) {
|
|
25
25
|
let formData = {};
|
|
26
26
|
|
|
27
|
-
if(typeof value ===
|
|
28
|
-
if(value.contentType) {
|
|
29
|
-
const content =
|
|
30
|
-
|
|
27
|
+
if (typeof value === "object") {
|
|
28
|
+
if (value.contentType) {
|
|
29
|
+
const content =
|
|
30
|
+
typeof value.data === "object"
|
|
31
|
+
? JSON.stringify(value.data)
|
|
32
|
+
: String(value.data);
|
|
33
|
+
console.log("Content:", content);
|
|
31
34
|
formData[key] = {
|
|
32
35
|
name: value.filename || key,
|
|
33
36
|
mimeType: value.contentType,
|
|
34
|
-
buffer: Buffer.from(content,
|
|
37
|
+
buffer: Buffer.from(content, "utf8"),
|
|
35
38
|
};
|
|
36
39
|
} else {
|
|
37
40
|
formData[key] = JSON.stringify(value);
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
|
-
|
|
41
|
-
if (
|
|
43
|
+
|
|
44
|
+
if (
|
|
45
|
+
typeof value === "string" &&
|
|
46
|
+
(value.endsWith(".pdf") ||
|
|
47
|
+
value.endsWith(".jpg") ||
|
|
48
|
+
value.endsWith(".png") ||
|
|
49
|
+
value.endsWith(".txt") ||
|
|
50
|
+
value.endsWith(".doc") ||
|
|
51
|
+
value.endsWith(".docx") ||
|
|
52
|
+
value.includes("/"))
|
|
53
|
+
) {
|
|
42
54
|
// If it looks like a file path, treat it as a file
|
|
43
55
|
try {
|
|
44
56
|
if (fs.existsSync(value)) {
|
|
45
57
|
formData[key] = {
|
|
46
58
|
name: path.basename(value),
|
|
47
59
|
mimeType: getMimeType(value),
|
|
48
|
-
buffer: fs.readFileSync(value)
|
|
60
|
+
buffer: fs.readFileSync(value),
|
|
49
61
|
};
|
|
50
62
|
return;
|
|
51
63
|
}
|
|
@@ -103,7 +115,7 @@ const api = {
|
|
|
103
115
|
const resolvedPayload = await resolveVariable(payload);
|
|
104
116
|
const payloadJSON = (await resolvedPayload) && JSON.parse(resolvedPayload);
|
|
105
117
|
|
|
106
|
-
let requestBody = {}
|
|
118
|
+
let requestBody = {};
|
|
107
119
|
|
|
108
120
|
switch (bodyType) {
|
|
109
121
|
case "multipart":
|
|
@@ -112,14 +124,14 @@ const api = {
|
|
|
112
124
|
}
|
|
113
125
|
requestBody = {
|
|
114
126
|
headers: payloadJSON.headers,
|
|
115
|
-
multipart: formData
|
|
116
|
-
}
|
|
127
|
+
multipart: formData,
|
|
128
|
+
};
|
|
117
129
|
break;
|
|
118
130
|
default:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
131
|
+
requestBody = {
|
|
132
|
+
headers: payloadJSON ? payloadJSON.headers : {},
|
|
133
|
+
data: payloadJSON ? payloadJSON.body : {},
|
|
134
|
+
};
|
|
123
135
|
}
|
|
124
136
|
|
|
125
137
|
const res = await context.request.post(resolvedURL, requestBody);
|
|
@@ -137,91 +149,91 @@ const api = {
|
|
|
137
149
|
};
|
|
138
150
|
|
|
139
151
|
context.response = response;
|
|
140
|
-
},
|
|
141
|
-
put: async (url, payload, bodyType) => {
|
|
142
|
-
|
|
143
|
-
|
|
152
|
+
},
|
|
153
|
+
put: async (url, payload, bodyType) => {
|
|
154
|
+
const URL = await selector(url);
|
|
155
|
+
const resolvedURL = await resolveVariable(URL);
|
|
144
156
|
|
|
145
|
-
|
|
146
|
-
|
|
157
|
+
const resolvedPayload = await resolveVariable(payload);
|
|
158
|
+
const payloadJSON = (await resolvedPayload) && JSON.parse(resolvedPayload);
|
|
147
159
|
|
|
148
|
-
|
|
160
|
+
let requestBody = {};
|
|
149
161
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
162
|
+
switch (bodyType) {
|
|
163
|
+
case "multipart":
|
|
164
|
+
for (const [key, value] of Object.entries(payloadJSON.body)) {
|
|
165
|
+
var formData = processForm(key, value);
|
|
166
|
+
}
|
|
167
|
+
requestBody = {
|
|
168
|
+
headers: payloadJSON.headers,
|
|
169
|
+
multipart: formData,
|
|
170
|
+
};
|
|
171
|
+
break;
|
|
172
|
+
default:
|
|
161
173
|
requestBody = {
|
|
162
174
|
headers: payloadJSON ? payloadJSON.headers : {},
|
|
163
175
|
data: payloadJSON ? payloadJSON.body : {},
|
|
164
|
-
}
|
|
165
|
-
|
|
176
|
+
};
|
|
177
|
+
}
|
|
166
178
|
|
|
167
|
-
|
|
179
|
+
const res = await context.request.put(resolvedURL, requestBody);
|
|
168
180
|
|
|
169
|
-
|
|
170
|
-
|
|
181
|
+
const header = await res.headers();
|
|
182
|
+
const body = await res.json();
|
|
171
183
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
184
|
+
const response = {
|
|
185
|
+
url: res.url(),
|
|
186
|
+
requestHeaders: payloadJSON.headers,
|
|
187
|
+
requestBody: payloadJSON.body,
|
|
188
|
+
response: res,
|
|
189
|
+
responseHeaders: header,
|
|
190
|
+
responseBody: body,
|
|
191
|
+
};
|
|
180
192
|
|
|
181
|
-
|
|
182
|
-
},
|
|
183
|
-
patch: async (url, payload, bodyType) => {
|
|
184
|
-
|
|
185
|
-
|
|
193
|
+
context.response = response;
|
|
194
|
+
},
|
|
195
|
+
patch: async (url, payload, bodyType) => {
|
|
196
|
+
const URL = await selector(url);
|
|
197
|
+
const resolvedURL = await resolveVariable(URL);
|
|
186
198
|
|
|
187
|
-
|
|
188
|
-
|
|
199
|
+
const resolvedPayload = await resolveVariable(payload);
|
|
200
|
+
const payloadJSON = (await resolvedPayload) && JSON.parse(resolvedPayload);
|
|
189
201
|
|
|
190
|
-
|
|
202
|
+
let requestBody = {};
|
|
191
203
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
switch (bodyType) {
|
|
205
|
+
case "multipart":
|
|
206
|
+
for (const [key, value] of Object.entries(payloadJSON.body)) {
|
|
207
|
+
var formData = processForm(key, value);
|
|
208
|
+
}
|
|
209
|
+
requestBody = {
|
|
210
|
+
headers: payloadJSON.headers,
|
|
211
|
+
multipart: formData,
|
|
212
|
+
};
|
|
213
|
+
break;
|
|
214
|
+
default:
|
|
203
215
|
requestBody = {
|
|
204
216
|
headers: payloadJSON ? payloadJSON.headers : {},
|
|
205
217
|
data: payloadJSON ? payloadJSON.body : {},
|
|
206
|
-
}
|
|
207
|
-
|
|
218
|
+
};
|
|
219
|
+
}
|
|
208
220
|
|
|
209
|
-
|
|
221
|
+
const res = await context.request.patch(resolvedURL, requestBody);
|
|
210
222
|
|
|
211
|
-
|
|
212
|
-
|
|
223
|
+
const header = await res.headers();
|
|
224
|
+
const body = await res.json();
|
|
213
225
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
226
|
+
const response = {
|
|
227
|
+
url: res.url(),
|
|
228
|
+
requestHeaders: payloadJSON.headers,
|
|
229
|
+
requestBody: payloadJSON.body,
|
|
230
|
+
response: res,
|
|
231
|
+
responseHeaders: header,
|
|
232
|
+
responseBody: body,
|
|
233
|
+
};
|
|
222
234
|
|
|
223
|
-
|
|
224
|
-
},
|
|
235
|
+
context.response = response;
|
|
236
|
+
},
|
|
225
237
|
delete: async (url, payload) => {
|
|
226
238
|
const URL = await selector(url);
|
|
227
239
|
const resolvedURL = await resolveVariable(URL);
|
|
@@ -55,15 +55,20 @@ When(
|
|
|
55
55
|
},
|
|
56
56
|
);
|
|
57
57
|
|
|
58
|
-
When(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
extractVarsFromResponse(vars);
|
|
65
|
-
})
|
|
58
|
+
When(
|
|
59
|
+
"User sends multipart POST request to {string} with payload:",
|
|
60
|
+
async (url, payload) => {
|
|
61
|
+
await api.post(url, payload, "multipart");
|
|
62
|
+
},
|
|
63
|
+
);
|
|
66
64
|
|
|
65
|
+
When(
|
|
66
|
+
"User sends multipart POST request to {string} with payload and {string} variables",
|
|
67
|
+
async (url, vars, payload) => {
|
|
68
|
+
await api.post(url, payload, "multipart");
|
|
69
|
+
extractVarsFromResponse(vars);
|
|
70
|
+
},
|
|
71
|
+
);
|
|
67
72
|
|
|
68
73
|
When(
|
|
69
74
|
"User sends PUT request to {string} with payload:",
|
|
@@ -74,7 +79,7 @@ When(
|
|
|
74
79
|
|
|
75
80
|
When(
|
|
76
81
|
"User sends PUT request to {string} with payload and saves {string} variables",
|
|
77
|
-
async function (url, vars,
|
|
82
|
+
async function (url, vars, payload) {
|
|
78
83
|
await api.put(url, payload);
|
|
79
84
|
extractVarsFromResponse(vars);
|
|
80
85
|
},
|