@cuppet/core 1.0.17 → 1.1.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.
@@ -7,7 +7,7 @@ Given('that I send a {string} request to {string}', async function (method, path
7
7
  await apiSteps.sendRequest(method, path);
8
8
  });
9
9
  When(
10
- 'I send a {string} request to {string} with http header {string} and value {string}',
10
+ 'that I send a {string} request to {string} with http header {string} and value {string}',
11
11
  async function (method, path, headerName, headerValue) {
12
12
  const name = await dataStorage.checkForSavedVariable(headerName);
13
13
  const value = await dataStorage.checkForSavedVariable(headerValue);
@@ -35,6 +35,10 @@ Given('that I have request body', async function (docString) {
35
35
  const body = JSON.stringify(docString);
36
36
  await apiSteps.prepareRequestBody(body);
37
37
  });
38
+ Given('that I have a multipart request body', async function (docString) {
39
+ const body = JSON.parse(docString);
40
+ await apiSteps.buildMultipartFormData(body);
41
+ });
38
42
  Given(
39
43
  'I put {string} to {string} property of {string} element in the body',
40
44
  async function (value, property, parentObj) {
@@ -50,3 +54,6 @@ Given('I validate that the page is a valid XML', async function () {
50
54
  const currentPath = main.extractPath(this.page, true);
51
55
  await apiSteps.validateXMLEndpoint(currentPath);
52
56
  });
57
+ Then('the response header {string} should be {string}', async function (header, value) {
58
+ await apiSteps.validateResponseHeader(header, value);
59
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cuppet/core",
3
- "version": "1.0.17",
3
+ "version": "1.1.0",
4
4
  "description": "Core testing framework components for Cuppet - BDD framework based on Cucumber and Puppeteer",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -36,6 +36,7 @@
36
36
  "chai": "^4.3.7",
37
37
  "lighthouse": "^12.1.0",
38
38
  "mime": "^3.0.0",
39
+ "mime-types": "^3.0.1",
39
40
  "moment": "^2.30.1",
40
41
  "pa11y": "^8.0.0",
41
42
  "pa11y-reporter-html": "^2.0.0",
@@ -61,8 +62,10 @@
61
62
  "scripts": {
62
63
  "test": "cucumber-js features/tests",
63
64
  "postinstall": "node postinstall.js",
64
- "lint": "eslint .",
65
- "format": "prettier --write ."
65
+ "lint:check": "eslint .",
66
+ "format:check": "prettier --check .",
67
+ "format": "eslint . --fix && prettier --write .",
68
+ "verify": "yarn lint:check && yarn format:check"
66
69
  },
67
70
  "repository": {
68
71
  "type": "git",
@@ -3,12 +3,17 @@ const config = require('config');
3
3
  const storage = require('./dataStorage');
4
4
  const xml2js = require('xml2js');
5
5
  const assert = require('chai').assert;
6
+ const fs = require('fs');
7
+ const mime = require('mime-types');
8
+ const FormData = require('form-data');
6
9
 
7
10
  module.exports = {
8
11
  /** @type {object} */
9
12
  response: null,
10
13
  /** @type {object} */
11
14
  request: null,
15
+ /** @type {object} */
16
+ formData: null,
12
17
 
13
18
  /**
14
19
  * Prepare path for API test usage
@@ -40,11 +45,15 @@ module.exports = {
40
45
  'Content-Type': 'application/json',
41
46
  Accept: 'application/json',
42
47
  };
48
+ if (this.formData) {
49
+ defaultHeaders = {};
50
+ Object.assign(defaultHeaders, this.formData.getHeaders());
51
+ }
43
52
  if (config.has('api.x-api-key')) {
44
53
  defaultHeaders['X-Api-Key'] = config.get('api.x-api-key');
45
54
  }
46
55
  if (config.has('api.Authorization')) {
47
- defaultHeaders['X-Api-Key'] = config.get('api.Authorization');
56
+ defaultHeaders['Authorization'] = config.get('api.Authorization');
48
57
  }
49
58
  if (headers && defaultHeaders) {
50
59
  defaultHeaders = {
@@ -97,6 +106,9 @@ module.exports = {
97
106
  if (this.request) {
98
107
  data = this.request;
99
108
  }
109
+ if (this.formData) {
110
+ data = this.formData;
111
+ }
100
112
  try {
101
113
  this.response = await axios.request({
102
114
  url: apiUrl,
@@ -104,9 +116,10 @@ module.exports = {
104
116
  ...(Object.keys(auth).length && { auth }),
105
117
  // The data is conditionally added to the request, because it's not used with GET requests and creates conflict.
106
118
  // The following checks if data object is not empty, returns data object if not empty or skip if empty.
107
- ...(Object.keys(data).length && { data }),
119
+ ...((data instanceof FormData || Object.keys(data).length) && { data }),
108
120
  headers: requestHeaders,
109
121
  });
122
+
110
123
  return this.response;
111
124
  } catch (error) {
112
125
  console.log('Request has failed, use response code step definition to validate the response!');
@@ -156,7 +169,7 @@ module.exports = {
156
169
  validateResponseCode: async function (code) {
157
170
  if (this.response.status !== Number(code)) {
158
171
  throw new Error(
159
- `Response code is different than expected, code: ${this.response.status}. Response: ${this.response.data}`
172
+ `Unexpected response code, code: ${this.response.status}. Response: ${JSON.stringify(this.response.data)}`
160
173
  );
161
174
  }
162
175
  },
@@ -262,32 +275,48 @@ module.exports = {
262
275
  },
263
276
 
264
277
  /**
265
- *
266
- * @param {string} method - method - GET,POST, PUT etc.
267
- * @param {string} currentUrl - url of the page/endpoint
268
- * @param {object} reqHeaders - request headers
269
- * @param {string} resHeaders - response headers
270
- * @param {boolean} flag - direction of presence (true/false)
278
+ * Validate response header
279
+ * @param {string} header - header name
280
+ * @param {string} value - header value
271
281
  * @returns {Promise<void>}
272
282
  */
273
- validateResponseHeader: async function (method, currentUrl, reqHeaders, resHeaders, flag) {
274
- const prepareUrl = await this.prepareUrl(currentUrl);
275
- const requestHeaders = await this.setHeaders(reqHeaders);
276
- const auth = await this.setBasicAuth();
277
- let response;
278
- try {
279
- response = await axios.request({
280
- url: prepareUrl,
281
- method: method,
282
- ...(Object.keys(auth).length && { auth }),
283
- headers: requestHeaders,
284
- });
285
- } catch (error) {
286
- throw new Error(`Request failed with: ${error}`);
287
- }
288
- const hasProperty = Object.prototype.hasOwnProperty.call(response.headers, resHeaders.toLowerCase());
289
- if (hasProperty !== flag) {
290
- throw new Error('The response headers are different than expected!');
283
+ validateResponseHeader: async function (header, value) {
284
+ // Resolve header and value from variables or user input.
285
+ // The header is checked directly for faster execution as it is less likely to contain variables.
286
+ const resolveHeader = await storage.checkForVariable(header);
287
+ const resolveValue = await storage.checkForSavedVariable(value);
288
+ const actualValue = this.response.headers[resolveHeader.toLowerCase()];
289
+ assert.isDefined(actualValue, `The response header "${resolveHeader}" is not found!`);
290
+ assert.strictEqual(
291
+ actualValue,
292
+ resolveValue,
293
+ `The response header "${resolveHeader}" does not have the expected value`
294
+ );
295
+ },
296
+
297
+ /**
298
+ * Build multipart/form-data request body
299
+ * If you want to send a file, you need to pass the file name (not the path) as a string.
300
+ * Please use the files from the files folder.
301
+ * @param {object} data - the data to be sent in the request body
302
+ * @returns {Promise<Object>} - returns the request body object
303
+ */
304
+ buildMultipartFormData: async function (data) {
305
+ const filePath = config.get('filePath');
306
+ const formData = new FormData();
307
+ for (const [key, value] of Object.entries(data)) {
308
+ if (key === 'file') {
309
+ const mimeType = mime.contentType(value) || 'application/octet-stream';
310
+ formData.append('file', fs.createReadStream(filePath + value), {
311
+ filename: value,
312
+ contentType: mimeType,
313
+ });
314
+ formData.append('type', mimeType);
315
+ } else {
316
+ formData.append(key, await storage.checkForSavedVariable(value));
317
+ }
291
318
  }
319
+ this.formData = formData;
320
+ return this.formData;
292
321
  },
293
322
  };