Skip to content

Commit d930ce6

Browse files
inluxcFúlvio Carvalhido
and
Fúlvio Carvalhido
authored
Add the actual result to compare, fix evidence and a few fixes. (inluxc#12)
Co-authored-by: Fúlvio Carvalhido <fulvio@diller.no>
1 parent 56c5ad4 commit d930ce6

File tree

7 files changed

+94
-25
lines changed

7 files changed

+94
-25
lines changed

README.md

+22-2
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,33 @@ test('[J79] basic test', async ({ page }) => {
8080
Then run your tests with `npx playwright test` command and you'll see the result in console:
8181

8282
```sh
83-
✅ Test cycle JARV-C2901 has been created
83+
-------------------------------------
84+
85+
✅ Test status: PROJ-104
86+
✅ Tests ran: 4
87+
✅ Tests passed: 1
88+
✅ Tests failed: 3
89+
✅ Tests todo: 0
90+
91+
-------------------------------------
92+
93+
✅ Test cycle PROJ-104 has been created
8494
👇 Check out the test result
85-
🔗 https://jira.your-company-domain.com/browser/JARV-C2901
95+
🔗 https://diller.atlassian.net/browse/PROJ-104
96+
97+
-------------------------------------
8698
```
8799

88100
And you'll see the result in the Xray:
89101

102+
![alt text](./assets/xray-result.png)
103+
104+
105+
## Notes
106+
107+
- To have the steps imported you have to create then in the test issue itself.
108+
The steps will be imported by order of execution and inserted into the test.
109+
90110
## License
91111

92112
playwright-xray is [MIT licensed](./LICENSE).

assets/xray-result.png

114 KB
Loading

assets/zephyr-result.png

-12.1 KB
Binary file not shown.

src/index.ts

+35-13
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import type { XrayTestResult, XrayTest, XrayTestSteps } from '../types/cloud.types';
1+
import type { XrayTestResult, XrayTestSteps, XrayTestEvidence, XrayTest } from '../types/cloud.types';
22
import type { XrayOptions } from '../types/xray.types';
33
import type { Reporter, TestCase, TestResult } from '@playwright/test/reporter';
4+
import * as fs from 'fs';
5+
import * as path from 'path';
46

57
import { XrayService } from './xray.service';
68

79
class XrayReporter implements Reporter {
810
private xrayService!: XrayService;
911
private testResults!: XrayTestResult;
1012
private testCaseKeyPattern = /\[(.*?)\]/;
13+
private receivedRegEx: RegExp = /Received string: "(.*?)"(?=\n)/;
1114
private options: XrayOptions;
1215
private totalDuration: number;
1316
private readonly defaultRunName = `[${new Date().toUTCString()}] - Automated run`;
@@ -16,8 +19,6 @@ class XrayReporter implements Reporter {
1619
this.options = options;
1720
this.xrayService = new XrayService(this.options);
1821
this.totalDuration = 0;
19-
20-
//const finishTime = new Date(this.xrayService.startTime.getTime() + (result.duration * 1000));
2122
const testResults: XrayTestResult = {
2223
info: {
2324
summary: this.defaultRunName,
@@ -31,15 +32,13 @@ class XrayReporter implements Reporter {
3132
this.testResults = testResults;
3233
}
3334

34-
async onBegin() {}
35-
3635
async onTestEnd(testCase: TestCase, result: TestResult) {
3736
const testCaseId = testCase.title.match(this.testCaseKeyPattern);
3837
const testCode: string = testCaseId != null ? testCaseId[1]! : '';
3938
if (testCode != '') {
4039
// @ts-ignore
4140
const browserName = testCase._pool.registrations.get('browserName').fn;
42-
const finishTime = new Date(result.startTime.getTime() + result.duration * 1000);
41+
const finishTime = new Date(result.startTime.getTime() + result.duration);
4342
this.totalDuration = this.totalDuration + result.duration;
4443

4544
let xrayTestData: XrayTest = {
@@ -49,28 +48,51 @@ class XrayReporter implements Reporter {
4948
finish: finishTime.toISOString(),
5049
steps: [] as XrayTestSteps[],
5150
};
52-
53-
// Generated step and error messages
51+
5452
await Promise.all(
5553
result.steps.map(async (step) => {
5654
if (step.category != 'hook') {
55+
// Add Step to request
56+
const errorMessage = step.error?.stack?.toString()?.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
57+
const received = this.receivedRegEx.exec(errorMessage!);
58+
let dataReceived = ""
59+
if(received?.[1] !== undefined) {
60+
dataReceived = received?.[1];
61+
}
62+
5763
const xrayTestStep: XrayTestSteps = {
58-
status: typeof step.error == 'object' ? 'FAILED' : 'SUCCESS',
59-
comment: step.title,
60-
actualResult: typeof step.error == 'object' ? step.error.message?.toString()! : '',
64+
status: typeof step.error == 'object' ? 'FAILED' : 'PASSED',
65+
comment: typeof step.error == 'object' ? errorMessage : '',
66+
actualResult: dataReceived,
6167
};
6268
xrayTestData.steps!.push(xrayTestStep);
6369
}
6470
}),
6571
);
72+
73+
// Get evidences from test results (video, images, text)
74+
const evidences: XrayTestEvidence[] = [];
75+
if (result.attachments.length > 0) {
76+
result.attachments.map(async (attach) => {
77+
const filename = path.basename(attach.path!);
78+
const attachData = fs.readFileSync(attach.path!, { encoding: 'base64' });
79+
const evid: XrayTestEvidence = {
80+
data: attachData,
81+
filename: filename,
82+
contentType: attach.contentType
83+
}
84+
evidences.push(evid);
85+
})
86+
}
87+
88+
xrayTestData.evidence = evidences;
6689
this.testResults.tests!.push(xrayTestData);
6790
}
6891
}
6992

7093
async onEnd() {
7194
// Update test Duration
72-
this.testResults.info.finishDate = new Date(new Date(this.testResults.info.startDate).getTime() + this.totalDuration).toISOString();
73-
95+
this.testResults?.info?.finishDate != new Date(new Date(this.testResults?.info?.startDate!).getTime() + this.totalDuration).toISOString();
7496
if (typeof this.testResults != 'undefined' && typeof this.testResults.tests != 'undefined' && this.testResults.tests.length > 0) {
7597
await this.xrayService.createRun(this.testResults);
7698
} else {

src/xray.service.ts

+36-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { XrayOptions } from '../types/xray.types';
2-
import { XrayTestResult } from '../types/cloud.types';
2+
import { Execution } from '../types/cloud.types';
33
import axios, { Axios, AxiosError } from 'axios';
44
import { inspect } from 'util';
5-
import { bold, green } from 'picocolors';
5+
import { blue, bold, green, red, yellow } from 'picocolors';
66

77
function isAxiosError(error: any): error is AxiosError {
88
return error.isAxiosError === true;
@@ -105,20 +105,48 @@ export class XrayService {
105105
if (!options.testPlan) throw new Error('"testPlan" option are missed. Please provide them in the config');
106106
}
107107

108-
async createRun(results: XrayTestResult) {
108+
async createRun(results: Execution) {
109109
const URL = `${this.requestUrl}/import/execution`;
110+
const total = results.tests.length;
111+
let passed = 0;
112+
let failed = 0;
113+
let todo = 0;
114+
115+
116+
results.tests!.forEach((test: { status: any; }) => {
117+
switch (test.status) {
118+
case 'PASSED':
119+
passed = passed + 1;
120+
break;
121+
case 'FAILED':
122+
failed = failed + 1;
123+
break;
124+
}
125+
});
110126

111127
try {
112128
const response = await this.axios.post(URL, JSON.stringify(results));
113129
if (response.status !== 200) throw new Error(`${response.status} - Failed to create test cycle`);
114-
115130
const {
116-
data: { key, id },
131+
data: { key },
117132
} = response;
118133

119-
console.log(`${bold(green(`✅ Test cycle ${key} has been created`))}`);
120-
console.log(`${bold(green('👇 Check out the test result'))}`);
121-
console.log(`${bold(green(`🔗 ${this.jira}/browse/${id}`))}`);
134+
// Results
135+
console.log(`${bold(blue(`-------------------------------------`))}`);
136+
console.log(`${bold(blue(` `))}`);
137+
console.log(`${bold(blue(`✅ Test status: ${key}`))}`);
138+
console.log(`${bold(blue(`✅ Tests ran: ${total}`))}`);
139+
console.log(`${bold(green(`✅ Tests passed: ${passed}`))}`);
140+
console.log(`${bold(red(`✅ Tests failed: ${failed}`))}`);
141+
console.log(`${bold(blue(` `))}`);
142+
console.log(`${bold(blue(`-------------------------------------`))}`);
143+
console.log(`${bold(blue(` `))}`);
144+
console.log(`${bold(blue(`✅ Test cycle ${key} has been created`))}`);
145+
console.log(`${bold(blue('👇 Check out the test result'))}`);
146+
console.log(`${bold(blue(`🔗 ${this.jira}/browse/${key}`))}`);
147+
console.log(`${bold(blue(` `))}`);
148+
console.log(`${bold(blue(`-------------------------------------`))}`);
149+
122150
} catch (error) {
123151
if (isAxiosError(error)) {
124152
console.error(`Config: ${inspect(error.config)}`);
Binary file not shown.

types/cloud.types.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,4 @@ export interface XrayTestEvidence {
4040
data: string,
4141
filename: string,
4242
contentType: string
43-
};
44-
43+
};

0 commit comments

Comments
 (0)