Skip to content

Commit c9c39dd

Browse files
committed
Updating Test Case Status in Test Plan
1 parent 76b0858 commit c9c39dd

File tree

10 files changed

+297
-5
lines changed

10 files changed

+297
-5
lines changed

package-lock.json

Lines changed: 100 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
},
2222
"dependencies": {
2323
"@faker-js/faker": "^9.4.0",
24+
"axios": "^1.7.9",
2425
"csv-parse": "^5.6.0",
2526
"dotenv": "^16.4.7",
2627
"xlsx": "^0.18.5"

playwright.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default defineConfig({
3434
['html'],
3535
['list'],
3636
//['dot'],
37-
// ['json', { outputFile: 'json-test-report.json' }],
37+
['json', { outputFile: 'json-test-report.json' }],
3838
['junit', { outputFile: 'junit-test-report.xml' }],
3939
['allure-playwright'],
4040
],
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export interface TestResult {
2+
title: string;
3+
status: string;
4+
}
5+
6+
export interface Suite {
7+
title: string;
8+
file: string;
9+
specs: {
10+
title: string;
11+
tests: {
12+
results: {
13+
status: string;
14+
}[];
15+
}[];
16+
}[];
17+
}
18+
19+
export interface TestReport {
20+
config: any;
21+
suites: Suite[];
22+
errors: any[];
23+
stats: any;
24+
}

src/utils/AzureDevOpsHelper.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { request, expect } from '@playwright/test';
2+
import dotenv from 'dotenv';
3+
dotenv.config();
4+
5+
import axios from 'axios';
6+
7+
const credentials = Buffer.from(`${process.env.AZURE_DEVOPS_USER}:${process.env.AZURE_DEVOPS_PASS}`).toString('base64');
8+
9+
/**
10+
* Testers Talk
11+
*/
12+
class AzureDevOps {
13+
constructor() { }
14+
15+
/**
16+
* Testers Talk
17+
*/
18+
async updateTestCaseStatus(testCaseId: string, testCaseStatus: string): Promise<void> {
19+
try {
20+
const testPlanId = process.env.TEST_PLAN_ID as string;
21+
const testSuiteId = process.env.TEST_SUITE_ID as string;
22+
23+
const testPointId = await this.getTestPoint(testPlanId, testSuiteId, testCaseId);
24+
await this.updateTestPointStatus(testPlanId, testSuiteId, testPointId, testCaseStatus.charAt(0).toUpperCase() + testCaseStatus.slice(1));
25+
26+
console.log(`Updated Test Case ID - ${testCaseId} as ${testCaseStatus} in test plan`);
27+
} catch (error) {
28+
console.error('Error in updating test case status:', error);
29+
}
30+
}
31+
32+
/**
33+
* Testers Talk
34+
*/
35+
async getTestPoint(testPlanId: string, testSuiteId: string, testCaseId: string): Promise<string> {
36+
const values = [testPlanId, testSuiteId, testCaseId];
37+
const URL = process.env.TEST_PLAN_GET_API!.replace(/{(\d+)}/g, (match, number) => values[number] || match);
38+
const getTestPointResponse = await axios.get(URL, {
39+
headers: {
40+
"Content-Type": "application/json",
41+
'Authorization': `Basic ${credentials}`
42+
},
43+
});
44+
45+
const jsonResponse = await getTestPointResponse.data;
46+
expect(getTestPointResponse.status).toBe(200);
47+
return jsonResponse.value[0].id;
48+
}
49+
50+
/**
51+
* Testers Talk
52+
*/
53+
async updateTestPointStatus(testPlanId: string, testSuiteId: string, testPointId: string, testCaseStatus: string): Promise<void> {
54+
const values = [testPlanId, testSuiteId, testPointId];
55+
const URL = process.env.TEST_PLAN_PATCH_API!.replace(/{(\d+)}/g, (match, number) => values[number] || match);
56+
57+
const requestBody = {
58+
"outcome": testCaseStatus // Passed, Failed, Blocked, etc.
59+
};
60+
61+
try {
62+
const patchAPIResponse = await axios.patch(URL, requestBody, {
63+
headers: {
64+
"Content-Type": "application/json",
65+
'Authorization': `Basic ${credentials}`
66+
}
67+
});
68+
expect(patchAPIResponse.status).toBe(200);
69+
} catch (error: any) {
70+
console.error('Error occurred during API request:', error.message);
71+
console.error('Stack trace:', error.stack);
72+
}
73+
}
74+
}
75+
76+
export default AzureDevOps;

src/utils/Common.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
import { Page } from '@playwright/test';
2+
import AzureDevOps from '../../src/utils/AzureDevOpsHelper';
3+
import * as fs from 'fs';
4+
import { TestReport } from '../../src/interface/TestResults.interface';
5+
6+
import dotenv from 'dotenv';
7+
dotenv.config();
8+
29

310
/**
411
* Author Testers Talk
@@ -31,4 +38,69 @@ export async function navigateToApps(
3138
await page.goto(`/main.aspx?appid=${appId.toString()}`);
3239
await page.getByRole('button', { name: appName }).isVisible();
3340
console.log('Navigated to ' + appName + ' - Success');
41+
}
42+
43+
/**
44+
* Author Testers Talk
45+
*/
46+
async function readJsonReport() {
47+
const azureDevOps = new AzureDevOps();
48+
const filePath = 'json-test-report.json';
49+
50+
if (process.env.UPDATE_TEST_PLAN === 'Yes' && process.env.PIPELINE === 'Yes') {
51+
52+
await waitForFile(filePath);
53+
54+
try {
55+
const data: TestReport = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
56+
data.suites.forEach(suite => {
57+
suite.specs.forEach(spec => {
58+
const testCaseTitle = `${spec.title}`;
59+
spec.tests.forEach(test => {
60+
test.results.forEach(async result => {
61+
const testCaseStatus = `${result.status}`;
62+
63+
const matches = testCaseTitle.match(/\[(.*?)\]/);
64+
const numbersPart = matches?.[1];
65+
const numbersArray: number[] = numbersPart?.split(',').map(num => parseInt(num.trim(), 10)) ?? [];
66+
67+
for (const testCaseId of numbersArray) {
68+
console.log(`Test Case & Status : ${testCaseId} : ${testCaseStatus}`);
69+
await azureDevOps.updateTestCaseStatus(String(testCaseId), testCaseStatus);
70+
}
71+
});
72+
});
73+
});
74+
});
75+
} catch (error) {
76+
console.error('Error while readinf JSON report' + error)
77+
}
78+
} else {
79+
console.log('Update test plan or pipeline conditions not met.');
80+
}
81+
}
82+
83+
84+
/**
85+
* Author Testers Talk
86+
*/
87+
async function waitForFile(filePath: string) {
88+
const fs = require('fs').promises;
89+
90+
let fileExists = false;
91+
while (!fileExists) {
92+
try {
93+
await fs.access(filePath);
94+
fileExists = true; // If no error is thrown, the file exists
95+
} catch (err) {
96+
// File does not exist yet, wait and try again
97+
console.log('Waiting for the file to be available...');
98+
await new Promise(resolve => setTimeout(resolve, 5000)); // Retry every 5 seconds
99+
}
100+
}
101+
console.log(`File ${filePath} is now available!`);
102+
}
103+
104+
export async function updateTestCaseStatusInTestPlan() {
105+
await readJsonReport();
34106
}

src/utils/RunUpdate.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { updateTestCaseStatusInTestPlan } from '../../src/utils/Common';
2+
3+
async function run() {
4+
try {
5+
await updateTestCaseStatusInTestPlan();
6+
} catch (error) {
7+
console.error('Error executing updateTestCaseStatusInTestPlan:', error);
8+
}
9+
}
10+
11+
run();

tests/Chapter01/01_Record_Test.spec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { test, expect } from '@playwright/test';
33
/**
44
* Author Testers Talk
55
*/
6-
test('test', async ({ page }) => {
6+
test('[3] Record a test', { tag: ['@PlaywrightWithAzureDevOpsPipeline'] }, async ({ page }) => {
77

88
await test.step('Navigating to URL', async () => {
99
await page.goto('https://github.com/');
@@ -24,4 +24,12 @@ test('test', async ({ page }) => {
2424
await test.step('Validate error message', async () => {
2525
await expect(page.getByRole('alert')).toContainText('Incorrect username or password.');
2626
});
27+
});
28+
29+
/**
30+
* Author Testers Talk
31+
*/
32+
test('[8] Test 2 will fail', { tag: ['@PlaywrightWithAzureDevOpsPipeline'] }, async ({ page }) => {
33+
await page.goto('https://www.youtube.com/@testerstalk');
34+
expect(true).toBe(false);
2735
});

0 commit comments

Comments
 (0)