Skip to content

Commit 5003f91

Browse files
committed
Added VS Code debug configuration and refactoring
1 parent f3dbcd5 commit 5003f91

File tree

7 files changed

+119
-68
lines changed

7 files changed

+119
-68
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Node modules
22
node_modules/
33

4+
#custom json report
5+
global/test-run-context.json
6+
7+
48
# Output directories
59
dist/
610
build/
@@ -34,7 +38,6 @@ lcov-report/
3438
*.tsbuildinfo
3539

3640
# IDE settings
37-
.vscode/
3841
.idea/
3942

4043
# Mac system file

.vscode/launch.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
5+
{
6+
"type": "node",
7+
"request": "launch",
8+
"name": "Debug Playwright Test",
9+
"program": "${workspaceFolder}/node_modules/@playwright/test/cli.js",
10+
"args": [
11+
"test",
12+
"--headed",
13+
"--project=chromium"
14+
],
15+
"env": {
16+
"TAG": "@smoke",
17+
"BROWSER": "chromium",
18+
"WORKERS": "1",
19+
"RETRIES": "1",
20+
"TEST_ENV": "qa1"
21+
},
22+
"console": "integratedTerminal",
23+
"internalConsoleOptions": "openOnSessionStart"
24+
}
25+
]
26+
}

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ This project uses **GitHub Actions** to automate test execution and reporting.
162162

163163
---
164164

165+
TEST_ENV=qa1 npx playwright test
166+
165167

166168

167169
## 📄 License

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
"test:allure": "npm run test:params && npm run allure:generate",
99
"test:params": "sh ./run-with-params.sh",
1010
"allure:generate": "allure generate ./allure-results --clean -o ./allure-report",
11-
"allure:open": "allure open ./allure-report"
11+
"allure:open": "allure open ./allure-report",
12+
"test:env": "TAG='@smoke' BROWSER='chromium' WORKERS=2 RETRIES=1 TEST_ENV='qa1' npm run test:allure",
13+
"test:env:debug":"TAG='@smoke' BROWSER='chromium' WORKERS=2 RETRIES=1 TEST_ENV='qa1' npx playwright test $@"
1214
},
1315
"keywords": [],
1416
"author": "",

pages/BasePage.ts

Lines changed: 82 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,94 @@
1-
import { Locator } from '@playwright/test';
2-
import { logger } from '../utils/logger'; // adjust path based on your project
3-
import { expect } from '@playwright/test';
1+
import { Locator } from "@playwright/test";
2+
import { logger } from "../utils/logger";
43

54
export class BasePage {
6-
/**
7-
* Waits for an element with retry and timeout support.
8-
*/
9-
async waitForElement(
10-
locator: Locator,
11-
timeout: number = 5000,
12-
maxRetries: number = 3,
13-
delayBetweenRetries: number = 1000
14-
): Promise<void> {
15-
let attempt = 0;
16-
while (attempt < maxRetries) {
17-
try {
18-
logger.info(`Attempt ${attempt + 1}: Waiting for element → ${locator.toString()}`);
19-
await locator.waitFor({ timeout });
20-
logger.info(`Element is ready: ${locator.toString()}`);
21-
return;
22-
} catch (error) {
23-
logger.warn(`Attempt ${attempt + 1} failed: ${(error as Error).message}`);
24-
attempt++;
25-
if (attempt < maxRetries) {
26-
await new Promise(res => setTimeout(res, delayBetweenRetries));
27-
} else {
28-
logger.error(`Element not found after ${maxRetries} retries: ${locator.toString()}`);
29-
throw new Error(`Failed to locate element after ${maxRetries} retries: ${locator.toString()}`);
30-
}
31-
}
32-
}
33-
}
5+
async clickElement(locator: Locator, wait: boolean = true): Promise<void> {
6+
if (wait) await this.waitForElement(locator);
7+
await locator.click();
8+
logger.info(`Clicked on element: ${locator.toString()}`);
9+
}
3410

35-
async clickElement(locator: Locator, wait: boolean = true): Promise<void> {
36-
if (wait) await this.waitForElement(locator);
37-
await locator.click();
38-
logger.info(`Clicked on element: ${locator.toString()}`);
39-
}
11+
async enterText(
12+
locator: Locator,
13+
value: string,
14+
wait: boolean = true
15+
): Promise<void> {
16+
if (wait) await this.waitForElement(locator);
17+
const response = await locator.fill(value);
4018

41-
async enterText(locator: Locator, value: string, wait: boolean = true): Promise<void> {
42-
if (wait) await this.waitForElement(locator);
43-
const response = await locator.fill(value);
44-
45-
logger.info(`Filled input ${locator.toString()} with value: ${value}`);
46-
}
19+
logger.info(`Filled input ${locator.toString()} with value: ${value}`);
20+
}
4721

48-
async typeText(locator: Locator, value: string, wait: boolean = true): Promise<void> {
49-
if (wait) await this.waitForElement(locator);
50-
await locator.type(value);
51-
logger.info(`Typed into ${locator.toString()} with value: ${value}`);
52-
}
22+
async typeText(
23+
locator: Locator,
24+
value: string,
25+
wait: boolean = true
26+
): Promise<void> {
27+
if (wait) await this.waitForElement(locator);
28+
await locator.type(value);
29+
logger.info(`Typed into ${locator.toString()} with value: ${value}`);
30+
}
5331

54-
async selectDropdown(locator: Locator, value: string, wait: boolean = true): Promise<void> {
55-
if (wait) await this.waitForElement(locator);
56-
await locator.selectOption(value);
57-
logger.info(`Selected dropdown value '${value}' on ${locator.toString()}`);
58-
}
32+
async selectDropdown(
33+
locator: Locator,
34+
value: string,
35+
wait: boolean = true
36+
): Promise<void> {
37+
if (wait) await this.waitForElement(locator);
38+
await locator.selectOption(value);
39+
logger.info(`Selected dropdown value '${value}' on ${locator.toString()}`);
40+
}
41+
42+
async getElementText(
43+
locator: Locator,
44+
wait: boolean = true
45+
): Promise<string> {
46+
if (wait) await this.waitForElement(locator);
47+
const text = await locator.textContent();
48+
logger.info(`Extracted text from ${locator.toString()}: ${text}`);
49+
return text || "";
50+
}
5951

60-
async getElementText(locator: Locator, wait: boolean = true): Promise<string> {
61-
if (wait) await this.waitForElement(locator);
62-
const text = await locator.textContent();
63-
logger.info(`Extracted text from ${locator.toString()}: ${text}`);
64-
return text || '';
52+
async isElementVisible(locator: Locator): Promise<boolean> {
53+
try {
54+
logger.info(`Verifying the visibility of locator: ${locator.toString()}`);
55+
return await locator.isVisible();
56+
} catch {
57+
return false;
6558
}
59+
}
6660

67-
async isElementVisible(locator: Locator): Promise<boolean> {
68-
try {
69-
logger.info(`Verifying the visibility of locator: ${locator.toString()}`);
70-
return await locator.isVisible();
71-
} catch {
72-
return false;
61+
async waitForElement(
62+
locator: Locator,
63+
timeout: number = 5000,
64+
maxRetries: number = 3,
65+
delayBetweenRetries: number = 1000
66+
): Promise<void> {
67+
let attempt = 0;
68+
while (attempt < maxRetries) {
69+
try {
70+
logger.info(
71+
`Attempt ${attempt + 1}: Waiting for element → ${locator.toString()}`
72+
);
73+
await locator.waitFor({ timeout });
74+
logger.info(`Element is ready: ${locator.toString()}`);
75+
return;
76+
} catch (error) {
77+
logger.warn(
78+
`Attempt ${attempt + 1} failed: ${(error as Error).message}`
79+
);
80+
attempt++;
81+
if (attempt < maxRetries) {
82+
await new Promise((res) => setTimeout(res, delayBetweenRetries));
83+
} else {
84+
logger.error(
85+
`Element not found after ${maxRetries} retries: ${locator.toString()}`
86+
);
87+
throw new Error(
88+
`Failed to locate element after ${maxRetries} retries: ${locator.toString()}`
89+
);
7390
}
91+
}
7492
}
93+
}
7594
}

pages/LoginPage.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {Page, Locator} from '@playwright/test'
22
import { BasePage } from '../pages/BasePage'
3-
import { AllureHelper } from '../utils/allureHelper';
43
import { config } from '../utils/config';
54

65
export class LoginPage extends BasePage {
@@ -30,7 +29,7 @@ export class LoginPage extends BasePage {
3029
}
3130

3231
async login(userName: string, password: string) {
33-
const response = await this.enterText(this.txtUserName, userName);
32+
await this.enterText(this.txtUserName, userName);
3433
await this.enterText(this.txtPassword, password);
3534
await this.clickElement(this.btnLogin);
3635
}

playwright.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default defineConfig({
2020
],
2121
use: {
2222
baseURL: process.env.BASE_URL || 'https://example.com',
23-
headless: true,
23+
headless: false,
2424
screenshot: 'only-on-failure',
2525
video: 'retain-on-failure',
2626
trace: 'on-first-retry',

0 commit comments

Comments
 (0)