@qavajs/format-report-portal 0.0.4 → 0.0.6
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 +7 -0
- package/README.MD +8 -0
- package/index.js +89 -21
- package/package.json +9 -2
- package/.github/workflows/npm-publish.yml +0 -32
package/CHANGELOG.MD
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
+
## 0.0.6
|
|
2
|
+
- :rocket: enable support of cucumber logs
|
|
3
|
+
|
|
4
|
+
## 0.0.5
|
|
5
|
+
- :rocket: updated step logging as nested steps instead plain logs
|
|
6
|
+
- :beetle: added capability to attach multiple attachment to step
|
|
7
|
+
|
|
1
8
|
## 0.0.4
|
|
2
9
|
- :beetle: fixed issue with sending text plain
|
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,36 +78,52 @@ 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
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
+
await this.sendAttachment(attachment, nestedTestItem);
|
|
86
108
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}, attachment).promise
|
|
109
|
+
}
|
|
110
|
+
const nestedItemFinish = this.rpClient.finishTestItem(nestedTestItem.tempId, {
|
|
111
|
+
status: this.getStatus(step),
|
|
112
|
+
endTime: this.rpClient.helpers.now()
|
|
113
|
+
});
|
|
114
|
+
this.promiseQ.push(nestedItemFinish.promise);
|
|
115
|
+
await nestedItemFinish.promise;
|
|
95
116
|
}
|
|
96
117
|
|
|
97
118
|
//finish test item
|
|
98
119
|
const status = Object.values(testCase.stepResults).some(step => step.status !== Status.PASSED)
|
|
99
120
|
? Status.FAILED.toLowerCase()
|
|
100
121
|
: Status.PASSED.toLowerCase()
|
|
101
|
-
|
|
122
|
+
const testItemFinish = this.rpClient.finishTestItem(testItem.tempId, {
|
|
102
123
|
status
|
|
103
|
-
})
|
|
124
|
+
});
|
|
125
|
+
this.promiseQ.push(testItemFinish.promise);
|
|
126
|
+
await testItemFinish.promise;
|
|
104
127
|
}
|
|
105
128
|
|
|
106
129
|
getStepResults(testCase) {
|
|
@@ -111,8 +134,8 @@ class RPFormatter extends Formatter {
|
|
|
111
134
|
}))
|
|
112
135
|
}
|
|
113
136
|
|
|
114
|
-
|
|
115
|
-
if (!step.pickle) return
|
|
137
|
+
getStepText(step, steps) {
|
|
138
|
+
if (!step.pickle) return this.hookKeyword(step, steps);
|
|
116
139
|
const messageParts = [step.pickle.text];
|
|
117
140
|
if (step.pickle.argument) {
|
|
118
141
|
if (step.pickle.argument.dataTable) messageParts.push(
|
|
@@ -120,11 +143,26 @@ class RPFormatter extends Formatter {
|
|
|
120
143
|
)
|
|
121
144
|
if (step.pickle.argument.docString) messageParts.push(this.formatDocString(step.pickle.argument.docString))
|
|
122
145
|
}
|
|
123
|
-
if (step.result.status === Status.FAILED) messageParts.push(step.result.message)
|
|
124
146
|
|
|
125
147
|
return messageParts.join('\n')
|
|
126
148
|
}
|
|
127
149
|
|
|
150
|
+
hookKeyword(step, steps) {
|
|
151
|
+
const stepsBefore = steps.slice(0, steps.findIndex((element) => element === step));
|
|
152
|
+
return stepsBefore.every(element => element.pickle === undefined) ? 'Before' : 'After'
|
|
153
|
+
}
|
|
154
|
+
getMessage(step) {
|
|
155
|
+
return step.result.message
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
getStatus(step) {
|
|
159
|
+
switch (step.result.status) {
|
|
160
|
+
case Status.PASSED: return Status.PASSED.toLowerCase();
|
|
161
|
+
case Status.SKIPPED: return Status.SKIPPED.toLowerCase();
|
|
162
|
+
default: return Status.FAILED.toLowerCase()
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
128
166
|
formatTable(dataTable) {
|
|
129
167
|
const TR = '<tr>';
|
|
130
168
|
const TRE = '</tr>';
|
|
@@ -141,6 +179,36 @@ class RPFormatter extends Formatter {
|
|
|
141
179
|
formatTags(tags) {
|
|
142
180
|
return tags.map(tag => '<code>' + tag.name + '</code>').join('')
|
|
143
181
|
}
|
|
182
|
+
|
|
183
|
+
prepareContent(attachment) {
|
|
184
|
+
return ['text/plain', 'application/json'].includes(attachment.mediaType)
|
|
185
|
+
? Buffer.from(attachment.body).toString('base64')
|
|
186
|
+
: attachment.body
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async sendAttachment(attachment, testItem) {
|
|
190
|
+
let log;
|
|
191
|
+
if (attachment.mediaType === 'text/x.cucumber.log+plain') {
|
|
192
|
+
log = await this.rpClient.sendLog(testItem.tempId, {
|
|
193
|
+
level: 'INFO',
|
|
194
|
+
message: attachment.body,
|
|
195
|
+
time: this.rpClient.helpers.now()
|
|
196
|
+
});
|
|
197
|
+
} else {
|
|
198
|
+
const attachmentData = {
|
|
199
|
+
name: 'attachment',
|
|
200
|
+
type: attachment.mediaType,
|
|
201
|
+
content: this.prepareContent(attachment),
|
|
202
|
+
};
|
|
203
|
+
log = await this.rpClient.sendLog(testItem.tempId, {
|
|
204
|
+
level: 'INFO',
|
|
205
|
+
message: 'Attachment',
|
|
206
|
+
time: this.rpClient.helpers.now()
|
|
207
|
+
}, attachmentData);
|
|
208
|
+
}
|
|
209
|
+
this.promiseQ.push(log.promise);
|
|
210
|
+
await log.promise;
|
|
211
|
+
}
|
|
144
212
|
}
|
|
145
213
|
|
|
146
214
|
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
|
+
"version": "0.0.6",
|
|
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"
|
|
@@ -18,5 +20,10 @@
|
|
|
18
20
|
"homepage": "https://github.com/qavajs/format-report-portal#readme",
|
|
19
21
|
"dependencies": {
|
|
20
22
|
"@reportportal/client-javascript": "^5.0.8"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@cucumber/cucumber": "^9.0.0",
|
|
26
|
+
"@qavajs/cli": "^0.0.19",
|
|
27
|
+
"@qavajs/memory": "^1.2.0"
|
|
21
28
|
}
|
|
22
29
|
}
|
|
@@ -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}}
|