@qavajs/format-report-portal 0.0.3 → 0.0.5

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/CHANGELOG.MD ADDED
@@ -0,0 +1,6 @@
1
+ ## 0.0.5
2
+ - :rocket: updated step logging as nested steps instead plain logs
3
+ - :beetle: added capability to attach multiple attachment to step
4
+
5
+ ## 0.0.4
6
+ - :beetle: fixed issue with sending text plain
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 @qavajs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.MD CHANGED
@@ -15,6 +15,8 @@ module.exports = {
15
15
  ],
16
16
  formatOptions: {
17
17
  rpConfig: {
18
+ enable: true,
19
+ debug: false,
18
20
  token: 'your token',
19
21
  endpoint: 'https://your-rp-instance/api/v1',
20
22
  description: 'Description',
@@ -27,3 +29,9 @@ module.exports = {
27
29
  }
28
30
  }
29
31
  ```
32
+ Option `enable` is set to `true` even if it is not defined explicitly in rpConfig section.
33
+
34
+ ### run e2e test
35
+ add token.json file with rp token and other config
36
+ run
37
+ `npm run test-e2e`
package/index.js CHANGED
@@ -5,9 +5,12 @@ class RPFormatter extends Formatter {
5
5
 
6
6
  constructor(options) {
7
7
  super(options);
8
+ const rpEnable = options.parsedArgvOptions.rpConfig.enable;
9
+ if (rpEnable !== undefined && !rpEnable) return undefined;
8
10
  options.eventBroadcaster.on('envelope', this.processEnvelope.bind(this));
9
11
  this.rpConfig = options.parsedArgvOptions.rpConfig;
10
12
  this.rpClient = new RPClient(this.rpConfig);
13
+ this.promiseQ = [];
11
14
  }
12
15
 
13
16
  async processEnvelope(envelope) {
@@ -28,15 +31,18 @@ class RPFormatter extends Formatter {
28
31
  startTime: this.rpClient.helpers.now(),
29
32
  description: this.rpConfig.description,
30
33
  attributes: this.rpConfig.tags,
31
- mode: this.rpConfig.mode
34
+ mode: this.rpConfig.mode,
35
+ debug: this.rpConfig.debug
32
36
  });
33
37
 
34
38
  this.launchId = launchObj.tempId;
35
39
  this.features = {};
40
+ this.promiseQ.push(launchObj.promise);
36
41
  await launchObj.promise;
37
42
  }
38
43
 
39
44
  async finishLaunch() {
45
+ await Promise.allSettled(this.promiseQ);
40
46
  for (const featureName in this.features) {
41
47
  await this.rpClient.finishTestItem(this.features[featureName], { status: 'PASSED' }).promise;
42
48
  }
@@ -60,6 +66,7 @@ class RPFormatter extends Formatter {
60
66
  type: 'SUITE'
61
67
  }, this.launchId);
62
68
  this.features[featureName] = featureItem.tempId;
69
+ this.promiseQ.push(featureItem.promise);
63
70
  await featureItem.promise;
64
71
  }
65
72
 
@@ -71,34 +78,63 @@ class RPFormatter extends Formatter {
71
78
  startTime: this.rpClient.helpers.now(),
72
79
  type: 'STEP'
73
80
  }, this.launchId, featureTempId);
81
+ this.promiseQ.push(testItem.promise);
74
82
  await testItem.promise;
75
83
 
76
84
  //send steps
77
85
  const steps = this.getStepResults(testCase)
78
86
  for (const step of steps) {
79
- const attachment = step.attachment && step.attachment[0]
80
- ? {
81
- name: 'attachment',
82
- type: step.attachment[0].mediaType,
83
- content: step.attachment[0].body
87
+ const nestedTestItem = this.rpClient.startTestItem({
88
+ description: 'test description',
89
+ name: this.getStepText(step, steps),
90
+ startTime: this.rpClient.helpers.now(),
91
+ type: 'STEP',
92
+ hasStats: false
93
+ }, this.launchId, testItem.tempId);
94
+ this.promiseQ.push(nestedTestItem.promise);
95
+ await nestedTestItem.promise;
96
+ if (step.result.message) {
97
+ const log = await this.rpClient.sendLog(nestedTestItem.tempId, {
98
+ level: 'ERROR',
99
+ message: this.getMessage(step),
100
+ time: this.rpClient.helpers.now()
101
+ });
102
+ this.promiseQ.push(log.promise);
103
+ await log.promise;
104
+ }
105
+ if (step.attachment) {
106
+ for (const attachment of step.attachment) {
107
+ const attachmentData = {
108
+ name: 'attachment',
109
+ type: attachment.mediaType,
110
+ content: this.prepareContent(attachment),
111
+ };
112
+ const log = await this.rpClient.sendLog(nestedTestItem.tempId, {
113
+ level: 'INFO',
114
+ message: 'Attachment',
115
+ time: this.rpClient.helpers.now()
116
+ }, attachmentData);
117
+ this.promiseQ.push(log.promise);
118
+ await log.promise;
84
119
  }
85
- : undefined;
86
- await this.rpClient.sendLog(testItem.tempId, {
87
- level: step.result.status === Status.PASSED
88
- ? 'INFO'
89
- : 'ERROR',
90
- message: this.getMessage(step),
91
- time: this.rpClient.helpers.now()
92
- }, attachment).promise
120
+ }
121
+ const nestedItemFinish = this.rpClient.finishTestItem(nestedTestItem.tempId, {
122
+ status: this.getStatus(step),
123
+ endTime: this.rpClient.helpers.now()
124
+ });
125
+ this.promiseQ.push(nestedItemFinish.promise);
126
+ await nestedItemFinish.promise;
93
127
  }
94
128
 
95
129
  //finish test item
96
130
  const status = Object.values(testCase.stepResults).some(step => step.status !== Status.PASSED)
97
131
  ? Status.FAILED.toLowerCase()
98
132
  : Status.PASSED.toLowerCase()
99
- await this.rpClient.finishTestItem(testItem.tempId, {
133
+ const testItemFinish = this.rpClient.finishTestItem(testItem.tempId, {
100
134
  status
101
- }).promise;
135
+ });
136
+ this.promiseQ.push(testItemFinish.promise);
137
+ await testItemFinish.promise;
102
138
  }
103
139
 
104
140
  getStepResults(testCase) {
@@ -109,8 +145,8 @@ class RPFormatter extends Formatter {
109
145
  }))
110
146
  }
111
147
 
112
- getMessage(step) {
113
- if (!step.pickle) return 'Hook';
148
+ getStepText(step, steps) {
149
+ if (!step.pickle) return this.hookKeyword(step, steps);
114
150
  const messageParts = [step.pickle.text];
115
151
  if (step.pickle.argument) {
116
152
  if (step.pickle.argument.dataTable) messageParts.push(
@@ -118,11 +154,25 @@ class RPFormatter extends Formatter {
118
154
  )
119
155
  if (step.pickle.argument.docString) messageParts.push(this.formatDocString(step.pickle.argument.docString))
120
156
  }
121
- if (step.result.status === Status.FAILED) messageParts.push(step.result.message)
122
157
 
123
158
  return messageParts.join('\n')
124
159
  }
125
160
 
161
+ hookKeyword(step, steps) {
162
+ const stepsBefore = steps.slice(0, steps.findIndex((element) => element === step));
163
+ return stepsBefore.every(element => element.pickle === undefined) ? 'Before' : 'After'
164
+ }
165
+ getMessage(step) {
166
+ return step.result.message
167
+ }
168
+
169
+ getStatus(step) {
170
+ if (step.result.status !== Status.PASSED) {
171
+ return Status.FAILED.toLowerCase()
172
+ }
173
+ return Status.PASSED.toLowerCase()
174
+ }
175
+
126
176
  formatTable(dataTable) {
127
177
  const TR = '<tr>';
128
178
  const TRE = '</tr>';
@@ -139,6 +189,13 @@ class RPFormatter extends Formatter {
139
189
  formatTags(tags) {
140
190
  return tags.map(tag => '<code>' + tag.name + '</code>').join('')
141
191
  }
192
+
193
+ prepareContent(attachment) {
194
+ return ['text/plain', 'application/json'].includes(attachment.mediaType)
195
+ ? Buffer.from(attachment.body).toString('base64')
196
+ : attachment.body
197
+ }
198
+
142
199
  }
143
200
 
144
201
  module.exports = RPFormatter
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "@qavajs/format-report-portal",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "cucumber formatter for report portal",
5
5
  "main": "index.js",
6
- "scripts": {},
6
+ "scripts": {
7
+ "test-e2e": "qavajs run --config test-e2e/config.js"
8
+ },
7
9
  "repository": {
8
10
  "type": "git",
9
11
  "url": "git+https://github.com/qavajs/format-report-portal.git"
@@ -17,6 +19,13 @@
17
19
  },
18
20
  "homepage": "https://github.com/qavajs/format-report-portal#readme",
19
21
  "dependencies": {
20
- "@reportportal/client-javascript": "^5.0.6"
22
+ "@reportportal/client-javascript": "^5.0.8"
23
+ },
24
+ "devDependencies": {
25
+ "@cucumber/cucumber": "^9.0.0",
26
+ "@qavajs/cli": "^0.0.18",
27
+ "@qavajs/memory": "^1.2.0",
28
+ "@qavajs/po-playwright": "^0.0.7",
29
+ "@qavajs/steps-playwright": "^0.0.14"
21
30
  }
22
31
  }
@@ -1,32 +0,0 @@
1
- # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
- # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
3
-
4
- name: Node.js Package
5
-
6
- on:
7
- release:
8
- types: [created]
9
-
10
- jobs:
11
- build:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@v2
15
- - uses: actions/setup-node@v2
16
- with:
17
- node-version: 16
18
- - run: npm ci
19
-
20
- publish-npm:
21
- needs: build
22
- runs-on: ubuntu-latest
23
- steps:
24
- - uses: actions/checkout@v2
25
- - uses: actions/setup-node@v2
26
- with:
27
- node-version: 16
28
- registry-url: https://registry.npmjs.org/
29
- - run: npm ci
30
- - run: npm publish --access public
31
- env:
32
- NODE_AUTH_TOKEN: ${{secrets.npm_token}}