newman-reporter-qase 2.0.0 → 2.0.2

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
@@ -23,11 +23,13 @@ Example:
23
23
  //qase: 10
24
24
  // Qase: 1, 2, 3
25
25
  // qase: 4 5 6 14
26
- pm.test('expect response be 200', function () {
27
- pm.response.to.be.info
26
+ pm.test('expect response be 200', function() {
27
+ pm.response.to.be.info
28
28
  })
29
29
  ```
30
+
30
31
  ### Execute rom CLI:
32
+
31
33
  ```
32
34
  QASE_MODE=testops newman run ./sample-collection.json -r qase
33
35
  ```
@@ -46,55 +48,40 @@ https://app.qase.io/run/QASE_PROJECT_CODE
46
48
  <img src="./screenshots/demo.gif">
47
49
  </p>
48
50
 
51
+ You can find more information about using the reporter [here](./docs/usage.md).
52
+
49
53
  ## Configuration
50
54
 
51
- Qase reporter supports passing parameters using two ways:
52
- using `.qaserc`/`qase.config.json` file and using ENV variables.
53
-
54
- `.qaserc` parameters, (* - required):
55
- - `mode` - `testops`/`off` Enables reporter, default - `off`
56
- - `debug` - Enables debug logging, defaule - `false`
57
- - `environment` - To execute with the sending of the envinroment information
58
- - *`testops.api.token` - Token for API access, you can find more information
59
- [here](https://developers.qase.io/#authentication)
60
- - *`testops.project` - Code of your project (can be extracted from main
61
- page of your project: `https://app.qase.io/project/DEMOTR` -
62
- `DEMOTR` is project code here)
63
- - `testops.run.id` - Pass Run ID
64
- - `testops.run.title` - Set custom Run name, when new run is created
65
- - `testops.run.description` - Set custom Run description, when new run is created
66
- - `testops.run.complete` - Whether the run should be completed
67
-
68
- Example configuration file:
55
+ Qase Newman reporter can be configured in multiple ways:
56
+
57
+ - using a separate config file `qase.config.json`,
58
+ - using environment variables (they override the values from the configuration files).
59
+
60
+ For a full list of configuration options, see
61
+ the [Configuration reference](../qase-javascript-commons/README.md#configuration).
62
+
63
+ Example `qase.config.json` config:
69
64
 
70
65
  ```json
71
66
  {
72
67
  "mode": "testops",
73
68
  "debug": true,
74
- "environment": 1,
75
69
  "testops": {
76
70
  "api": {
77
71
  "token": "api_key"
78
72
  },
79
- "projectCode": "project_code"
73
+ "project": "project_code",
74
+ "run": {
75
+ "complete": true
76
+ }
80
77
  }
81
78
  }
82
79
  ```
83
80
 
84
- Supported ENV variables:
85
-
86
- - `QASE_MODE` - Same as `mode`
87
- - `QASE_DEBUG` - Same as `debug`
88
- - `QASE_ENVIRONMENT` - Same as `environment`
89
- - `QASE_TESTOPS_API_TOKEN` - Same as `testops.api.token`
90
- - `QASE_TESTOPS_PROJECT` - Same as `testops.project`
91
- - `QASE_TESTOPS_RUN_ID` - Pass Run ID from ENV and override reporter option `testops.run.id`
92
- - `QASE_TESTOPS_RUN_TITLE` - Same as `testops.run.title`
93
- - `QASE_TESTOPS_RUN_DESCRIPTION` - Same as `testops.run.description`
94
-
95
81
  ## Requirements
96
82
 
97
- We maintain the reporter on LTS versions of Node. You can find the current versions by following the [link](https://nodejs.org/en/about/releases/)
83
+ We maintain the reporter on LTS versions of Node. You can find the current versions by following
84
+ the [link](https://nodejs.org/en/about/releases/)
98
85
 
99
86
  `newman >= 5.3.0`
100
87
 
package/changelog.md CHANGED
@@ -1,3 +1,10 @@
1
+ # qase-newman@2.0.2
2
+
3
+ ## What's new
4
+
5
+ Added support parameters from data files in Newman.
6
+ How to use parameters from data files in Newman, see [here](./docs/usage.md).
7
+
1
8
  # qase-newman@2.0.0
2
9
 
3
10
  ## What's new
@@ -0,0 +1,4 @@
1
+ import { JSONSchemaType } from 'ajv';
2
+ import { FrameworkOptionsType } from 'qase-javascript-commons';
3
+ import { ReporterOptionsType } from './options';
4
+ export declare const configSchema: JSONSchemaType<FrameworkOptionsType<'newman', ReporterOptionsType>>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configSchema = void 0;
4
+ exports.configSchema = {
5
+ type: 'object',
6
+ nullable: true,
7
+ properties: {
8
+ framework: {
9
+ type: 'object',
10
+ nullable: true,
11
+ properties: {
12
+ newman: {
13
+ type: 'object',
14
+ nullable: true,
15
+ properties: {
16
+ autoCollectParams: {
17
+ type: 'boolean',
18
+ nullable: true,
19
+ },
20
+ },
21
+ },
22
+ },
23
+ },
24
+ },
25
+ };
@@ -0,0 +1,3 @@
1
+ export interface ReporterOptionsType {
2
+ autoCollectParams?: boolean;
3
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,5 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'events';
3
+ import { NewmanRunOptions } from 'newman';
3
4
  import { ConfigType, ConfigLoader } from 'qase-javascript-commons';
4
5
  export type NewmanQaseOptionsType = ConfigType;
5
6
  /**
@@ -10,15 +11,24 @@ export declare class NewmanQaseReporter {
10
11
  * @type {RegExp}
11
12
  */
12
13
  static qaseIdRegExp: RegExp;
14
+ /**
15
+ * @type {RegExp}
16
+ */
17
+ static qaseParamRegExp: RegExp;
13
18
  /**
14
19
  * @param {EventList} eventList
15
20
  * @returns {number[]}
16
21
  * @private
17
22
  */
18
23
  private static getCaseIds;
24
+ /**
25
+ * @param {EventList} eventList
26
+ * @returns {string[]}
27
+ * @private
28
+ */
29
+ private static getParameters;
19
30
  /**
20
31
  * @param {PropertyBase<PropertyBaseDefinition>} item
21
- * @param {string[]} titles
22
32
  * @returns {string[]}
23
33
  * @private
24
34
  */
@@ -38,13 +48,23 @@ export declare class NewmanQaseReporter {
38
48
  * @private
39
49
  */
40
50
  private timerMap;
51
+ /**
52
+ * @type {Record<string, string>[]}
53
+ * @private
54
+ */
55
+ private readonly parameters;
56
+ /**
57
+ * @type {boolean}
58
+ * @private
59
+ */
60
+ private autoCollectParams;
41
61
  /**
42
62
  * @param {EventEmitter} emitter
43
63
  * @param {NewmanQaseOptionsType} options
44
- * @param {unknown} _
64
+ * @param {NewmanRunOptions} collectionOptions
45
65
  * @param {ConfigLoaderInterface} configLoader
46
66
  */
47
- constructor(emitter: EventEmitter, options: NewmanQaseOptionsType, _: unknown, configLoader?: ConfigLoader<Partial<ConfigType> & Record<string, unknown>>);
67
+ constructor(emitter: EventEmitter, options: NewmanQaseOptionsType, collectionOptions: NewmanRunOptions, configLoader?: ConfigLoader<import("qase-javascript-commons").FrameworkOptionsType<"newman", import("./options").ReporterOptionsType>>);
48
68
  /**
49
69
  * @param {EventEmitter} runner
50
70
  * @private
@@ -54,4 +74,35 @@ export declare class NewmanQaseReporter {
54
74
  * @private
55
75
  */
56
76
  private preventExit;
77
+ /**
78
+ * @param {string[]} suites
79
+ * @param {string} title
80
+ * @param {number[]} ids
81
+ * @private
82
+ */
83
+ private getSignature;
84
+ /**
85
+ * @param {EventList} events
86
+ * @param {number} iteration
87
+ * @returns {Record<string, string>}
88
+ * @private
89
+ */
90
+ private prepareParameters;
91
+ /**
92
+ * @param {any} iterationData
93
+ * @private
94
+ */
95
+ private getParameters;
96
+ /**
97
+ * @param {unknown} obj
98
+ * @param parentKey
99
+ * @returns {Record<string, string>}
100
+ * @private
101
+ */
102
+ private convertToRecord;
103
+ /**
104
+ * @param {unknown} obj
105
+ * @private
106
+ */
107
+ private isRecord;
57
108
  }
package/dist/reporter.js CHANGED
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.NewmanQaseReporter = void 0;
7
+ const configSchema_1 = require("./configSchema");
7
8
  const semver_1 = __importDefault(require("semver"));
8
9
  const qase_javascript_commons_1 = require("qase-javascript-commons");
9
10
  /**
@@ -29,9 +30,28 @@ class NewmanQaseReporter {
29
30
  });
30
31
  return ids;
31
32
  }
33
+ /**
34
+ * @param {EventList} eventList
35
+ * @returns {string[]}
36
+ * @private
37
+ */
38
+ static getParameters(eventList) {
39
+ const params = [];
40
+ eventList.each((event) => {
41
+ if (event.listen === 'test' && event.script.exec) {
42
+ event.script.exec.forEach((line) => {
43
+ const match = line.match(NewmanQaseReporter.qaseParamRegExp);
44
+ if (match) {
45
+ const parameters = match[1]?.split(/\s*,\s*/) ?? [];
46
+ params.push(...parameters);
47
+ }
48
+ });
49
+ }
50
+ });
51
+ return params;
52
+ }
32
53
  /**
33
54
  * @param {PropertyBase<PropertyBaseDefinition>} item
34
- * @param {string[]} titles
35
55
  * @returns {string[]}
36
56
  * @private
37
57
  */
@@ -49,10 +69,10 @@ class NewmanQaseReporter {
49
69
  /**
50
70
  * @param {EventEmitter} emitter
51
71
  * @param {NewmanQaseOptionsType} options
52
- * @param {unknown} _
72
+ * @param {NewmanRunOptions} collectionOptions
53
73
  * @param {ConfigLoaderInterface} configLoader
54
74
  */
55
- constructor(emitter, options, _, configLoader = new qase_javascript_commons_1.ConfigLoader()) {
75
+ constructor(emitter, options, collectionOptions, configLoader = new qase_javascript_commons_1.ConfigLoader(configSchema_1.configSchema)) {
56
76
  /**
57
77
  * @type {Map<string, TestResultType>}
58
78
  * @private
@@ -63,6 +83,11 @@ class NewmanQaseReporter {
63
83
  * @private
64
84
  */
65
85
  this.timerMap = new Map();
86
+ /**
87
+ * @type {Record<string, string>[]}
88
+ * @private
89
+ */
90
+ this.parameters = [];
66
91
  const config = configLoader.load();
67
92
  this.reporter = qase_javascript_commons_1.QaseReporter.getInstance({
68
93
  ...(0, qase_javascript_commons_1.composeOptions)(options, config),
@@ -70,6 +95,8 @@ class NewmanQaseReporter {
70
95
  frameworkName: 'newman',
71
96
  reporterName: 'newman-reporter-qase',
72
97
  });
98
+ this.autoCollectParams = config?.framework?.newman?.autoCollectParams ?? false;
99
+ this.parameters = this.getParameters(collectionOptions.iterationData);
73
100
  this.addRunnerListeners(emitter);
74
101
  }
75
102
  /**
@@ -114,9 +141,10 @@ class NewmanQaseReporter {
114
141
  message: null,
115
142
  muted: false,
116
143
  params: {},
144
+ group_params: {},
117
145
  relations: relation,
118
146
  run_id: null,
119
- signature: '',
147
+ signature: this.getSignature(suites, item.name, ids),
120
148
  steps: [],
121
149
  testops_id: ids.length > 0 ? ids : null,
122
150
  id: item.id,
@@ -142,6 +170,7 @@ class NewmanQaseReporter {
142
170
  const now = Date.now();
143
171
  pendingResult.execution.duration = now - timer;
144
172
  }
173
+ pendingResult.params = this.prepareParameters(item.events, exec.cursor.iteration);
145
174
  void this.reporter.addTestResult(pendingResult);
146
175
  }
147
176
  });
@@ -167,9 +196,100 @@ class NewmanQaseReporter {
167
196
  };
168
197
  }
169
198
  }
199
+ /**
200
+ * @param {string[]} suites
201
+ * @param {string} title
202
+ * @param {number[]} ids
203
+ * @private
204
+ */
205
+ getSignature(suites, title, ids) {
206
+ let signature = '';
207
+ for (const suite of suites) {
208
+ signature += suite.toLowerCase().replace(/\s/g, '_') + '::';
209
+ }
210
+ signature += title.toLowerCase().replace(/\s/g, '_');
211
+ if (ids.length > 0) {
212
+ signature += '::' + ids.join('::');
213
+ }
214
+ return signature;
215
+ }
216
+ /**
217
+ * @param {EventList} events
218
+ * @param {number} iteration
219
+ * @returns {Record<string, string>}
220
+ * @private
221
+ */
222
+ prepareParameters(events, iteration) {
223
+ if (this.parameters.length === 0) {
224
+ return {};
225
+ }
226
+ const availableParameters = this.parameters[iteration] ?? {};
227
+ const params = NewmanQaseReporter.getParameters(events);
228
+ if (params.length === 0) {
229
+ if (this.autoCollectParams) {
230
+ return availableParameters;
231
+ }
232
+ return {};
233
+ }
234
+ return params.reduce((filteredParams, param) => {
235
+ const value = availableParameters[param];
236
+ if (value) {
237
+ filteredParams[param] = value;
238
+ }
239
+ return filteredParams;
240
+ }, {});
241
+ }
242
+ /**
243
+ * @param {any} iterationData
244
+ * @private
245
+ */
246
+ getParameters(iterationData) {
247
+ if (!iterationData) {
248
+ return [];
249
+ }
250
+ if (Array.isArray(iterationData) && iterationData.every(item => typeof item === 'object' && item !== null)) {
251
+ return iterationData.map((item) => this.convertToRecord(item));
252
+ }
253
+ return [];
254
+ }
255
+ /**
256
+ * @param {unknown} obj
257
+ * @param parentKey
258
+ * @returns {Record<string, string>}
259
+ * @private
260
+ */
261
+ convertToRecord(obj, parentKey = '') {
262
+ const record = {};
263
+ if (this.isRecord(obj)) {
264
+ for (const key in obj) {
265
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
266
+ const value = obj[key];
267
+ const newKey = parentKey ? `${parentKey}.${key}` : key;
268
+ if (this.isRecord(value)) {
269
+ Object.assign(record, this.convertToRecord(value, newKey));
270
+ }
271
+ else {
272
+ record[newKey] = String(value);
273
+ }
274
+ }
275
+ }
276
+ }
277
+ return record;
278
+ }
279
+ /**
280
+ * @param {unknown} obj
281
+ * @private
282
+ */
283
+ isRecord(obj) {
284
+ return typeof obj === 'object' && obj !== null;
285
+ }
170
286
  }
171
287
  exports.NewmanQaseReporter = NewmanQaseReporter;
172
288
  /**
173
289
  * @type {RegExp}
174
290
  */
175
291
  NewmanQaseReporter.qaseIdRegExp = /\/\/\s*?[qQ]ase:\s?((?:[\d]+[\s,]{0,})+)/;
292
+ /**
293
+ * @type {RegExp}
294
+ */
295
+ NewmanQaseReporter.qaseParamRegExp = /qase\.parameters:\s*([\w.]+(?:\s*,\s*[\w.]+)*)/i;
package/docs/usage.md ADDED
@@ -0,0 +1,80 @@
1
+ # How to Use Parameters from Data Files in Newman
2
+
3
+ Newman allows you to leverage parameters from data files to make your API tests more dynamic and efficient. By utilizing
4
+ the `--data` or `-d` option when running a collection, you can feed your tests with various input sets. The data files
5
+ can be formatted as either JSON or CSV.
6
+
7
+ ### Example Data File
8
+
9
+ Consider the following `data.json` file, which contains user data structured as complex objects:
10
+
11
+ ```json
12
+ [
13
+ {
14
+ "userid": 1,
15
+ "user": {
16
+ "name": "John",
17
+ "age": 30
18
+ }
19
+ },
20
+ {
21
+ "userid": 2,
22
+ "user": {
23
+ "name": "Jane",
24
+ "age": 25
25
+ }
26
+ }
27
+ ]
28
+ ```
29
+
30
+ ### Example Tests
31
+
32
+ Below are example tests that utilize the data parameters defined in the data file:
33
+
34
+ ```javascript
35
+ // qase.parameters: userId, user.name
36
+ pm.test("Status code is 201", function() {
37
+ pm.response.to.have.status(201);
38
+ });
39
+
40
+ // qase.parameters: userId
41
+ pm.test("Response has correct userId", function() {
42
+ var jsonData = pm.response.json();
43
+ pm.expect(jsonData.userId).to.eql(pm.iterationData.get("userid"));
44
+ });
45
+
46
+ pm.test("Response has correct name", function() {
47
+ var jsonData = pm.response.json();
48
+ pm.expect(jsonData.user.name).to.eql(pm.iterationData.get("user.name"));
49
+ });
50
+ ```
51
+
52
+ ### Expected Behavior
53
+
54
+ When you run the tests, the following behavior is expected:
55
+
56
+ - In the **`Status code is 201`** test, both `userId` and `user.name` will be passed as parameters.
57
+ - In the **`Response has correct userId`** test, only the `userId` parameter will be passed.
58
+ - In the **`Response has correct name`** test, by default, test will not have any parameters passed. But you can enable
59
+ specific option in config file to pass all parameters from data file if test have not commented `qase.parameters`
60
+ line.
61
+
62
+ ```json
63
+ {
64
+ "debug": true,
65
+ "testops": {
66
+ "api": {
67
+ "token": "api_key"
68
+ },
69
+ "project": "project_code",
70
+ "run": {
71
+ "complete": true
72
+ }
73
+ },
74
+ "framework": {
75
+ "newman": {
76
+ "autoCollectParams": true
77
+ }
78
+ }
79
+ }
80
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newman-reporter-qase",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Qase TMS Newman Reporter",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -39,14 +39,15 @@
39
39
  "author": "Qase Team <support@qase.io>",
40
40
  "license": "Apache-2.0",
41
41
  "dependencies": {
42
- "qase-javascript-commons": "^2.0.9",
42
+ "qase-javascript-commons": "~2.2.0",
43
43
  "semver": "^7.5.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@jest/globals": "^29.5.0",
47
47
  "@types/jest": "^29.5.2",
48
- "@types/newman": "^5.3.3",
48
+ "@types/newman": "^5.3.6",
49
49
  "@types/postman-collection": "^3.5.7",
50
+ "ajv": "^8.17.1",
50
51
  "jest": "^29.5.0",
51
52
  "postman-collection": "^4.1.7",
52
53
  "ts-jest": "^29.1.0"