Skip to content

Commit 1d844ab

Browse files
committed
Project initialized
0 parents  commit 1d844ab

17 files changed

Lines changed: 562 additions & 0 deletions

.github/workflows/playwright.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Playwright Tests
2+
on:
3+
push:
4+
branches: [ main, master ]
5+
pull_request:
6+
branches: [ main, master ]
7+
jobs:
8+
test:
9+
timeout-minutes: 60
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-node@v4
14+
with:
15+
node-version: lts/*
16+
- name: Install dependencies
17+
run: npm ci
18+
- name: Install Playwright Browsers
19+
run: npx playwright install --with-deps
20+
- name: Run Playwright tests
21+
run: npx playwright test
22+
- uses: actions/upload-artifact@v4
23+
if: ${{ !cancelled() }}
24+
with:
25+
name: playwright-report
26+
path: playwright-report/
27+
retention-days: 30

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
# Playwright
3+
node_modules/
4+
/test-results/
5+
/playwright-report/
6+
/blob-report/
7+
/playwright/.cache/
8+
/playwright/.auth/

fixtures/homePage.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// import { test as base, Page } from '@playwright/test';
2+
// import { LoginPage } from '../pages/LoginPage';
3+
// import user from '../test-data/user.json'
4+
// import { HomePage } from '../pages/HomePage';
5+
6+
7+
// export const test = base.extend<{ homePage: HomePage }>({
8+
// homePage: async ({ page }, use) => {
9+
// const loginPage = new LoginPage(page);
10+
11+
// await loginPage.goto();
12+
// await loginPage.login(user.email, user.password);
13+
14+
// const homePage = new HomePage(page);
15+
16+
// await use(homePage);
17+
18+
// await page.context().clearCookies();
19+
// },
20+
// });
21+
22+
// export { expect } from '@playwright/test';

package-lock.json

Lines changed: 97 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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "automationexercise-ui-test",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {},
7+
"keywords": [],
8+
"author": "",
9+
"license": "ISC",
10+
"type": "commonjs",
11+
"devDependencies": {
12+
"@playwright/test": "^1.59.1",
13+
"@types/node": "^25.5.2"
14+
}
15+
}

pages/HomePage.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Locator, Page } from '@playwright/test';
2+
3+
export class HomePage {
4+
private readonly loggedInText: Locator;
5+
private readonly logOutButton: Locator;
6+
7+
constructor(private page: Page) {
8+
this.loggedInText = page.locator('a:has-text("Logged in as")');
9+
this.logOutButton = page.locator('a[href="/logout"]');
10+
};
11+
12+
async logout() {
13+
await this.logOutButton.click();
14+
};
15+
16+
async isLoggedIn(): Promise<boolean> {
17+
return await this.loggedInText.isVisible();
18+
};
19+
20+
async getLoggedInUserName(): Promise<string> {
21+
const text = await this.loggedInText.innerText();
22+
23+
return text.replace('Logged in as', '').trim();
24+
};
25+
};

pages/LoginPage.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Locator, Page } from '@playwright/test';
2+
3+
export class LoginPage {
4+
private readonly emailInput: Locator;
5+
private readonly passwordInput: Locator;
6+
private readonly loginButton: Locator;
7+
private readonly signUpName: Locator;
8+
private readonly signUpEmail: Locator;
9+
private readonly signUpButton: Locator;
10+
private readonly erroMessage: Locator;
11+
12+
13+
constructor(private page: Page) {
14+
this.emailInput = page.locator('[data-qa="login-email"]');
15+
this.passwordInput = page.locator('[data-qa="login-password"]');
16+
this.loginButton = page.locator('[data-qa="login-button"]');
17+
this.signUpName = page.locator('[data-qa="signup-name"]');
18+
this.signUpEmail = page.locator('[data-qa="signup-email"]');
19+
this.signUpButton = page.locator('[data-qa="signup-button"]');
20+
this.erroMessage = page.locator('.login-form p');
21+
};
22+
23+
async goto(): Promise<void> {
24+
await this.page.goto('/login');
25+
};
26+
27+
async login(email: string, password: string) {
28+
await this.emailInput.fill(email);
29+
await this.passwordInput.fill(password);
30+
await this.loginButton.click();
31+
};
32+
33+
async signup(name: string, email: string) {
34+
await this.signUpName.fill(name);
35+
await this.signUpEmail.fill(email);
36+
await this.signUpButton.click();
37+
};
38+
39+
async getEmailValidationMessage(): Promise<string> {
40+
return await this.emailInput.evaluate((el: HTMLInputElement) => el.validationMessage);
41+
};
42+
43+
async getPasswordValidationMessage(): Promise<string> {
44+
return await this.passwordInput.evaluate((el: HTMLInputElement) => el.validationMessage);
45+
};
46+
47+
async getErrorMessage(): Promise<string> {
48+
return await this.erroMessage.innerText();
49+
};
50+
51+
async isErrorVisible(): Promise<boolean> {
52+
return await this.erroMessage.isVisible();
53+
};
54+
};

pages/ProductsPage.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { expect, Locator, Page } from "@playwright/test";
2+
3+
4+
export class ProductsPage {
5+
private readonly products: Locator;
6+
7+
constructor(private page: Page) {
8+
this.products = page.locator('.features_items .col-sm-4');
9+
};
10+
11+
async goto(): Promise<void> {
12+
await this.page.goto('/products');
13+
};
14+
15+
async toHaveTitle(title: string) {
16+
await expect(this.page.getByRole('heading', { name: title })).toContainText(title);
17+
};
18+
19+
async pageWithBrandDisplayed(brand: string) {
20+
await expect(this.page.getByRole('link', { name: brand })).toBeVisible();
21+
};
22+
23+
async pageWithCategoryDisplayed(idCategory: string) {
24+
await expect(this.page.locator(`a[href="/category_products/${idCategory}"]`)).toBeVisible();
25+
};
26+
27+
async openCategory(categoryName: string) {
28+
await this.page.locator(`a[href="#${categoryName}"]`).click();
29+
}
30+
};

playwright.config.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { defineConfig, devices } from '@playwright/test';
2+
3+
/**
4+
* Read environment variables from file.
5+
* https://github.com/motdotla/dotenv
6+
*/
7+
// import dotenv from 'dotenv';
8+
// import path from 'path';
9+
// dotenv.config({ path: path.resolve(__dirname, '.env') });
10+
11+
/**
12+
* See https://playwright.dev/docs/test-configuration.
13+
*/
14+
export default defineConfig({
15+
testDir: './tests',
16+
/* Run tests in files in parallel */
17+
fullyParallel: true,
18+
/* Fail the build on CI if you accidentally left test.only in the source code. */
19+
forbidOnly: !!process.env.CI,
20+
/* Retry on CI only */
21+
retries: process.env.CI ? 2 : 0,
22+
/* Opt out of parallel tests on CI. */
23+
workers: process.env.CI ? 1 : undefined,
24+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
25+
reporter: 'html',
26+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
27+
use: {
28+
/* Base URL to use in actions like `await page.goto('')`. */
29+
baseURL: 'https://automationexercise.com',
30+
31+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
32+
trace: 'on-first-retry',
33+
},
34+
35+
/* Configure projects for major browsers */
36+
projects: [
37+
{
38+
name: 'chromium',
39+
use: { ...devices['Desktop Chrome'] },
40+
},
41+
42+
// {
43+
// name: 'firefox',
44+
// use: { ...devices['Desktop Firefox'] },
45+
// },
46+
47+
// {
48+
// name: 'webkit',
49+
// use: { ...devices['Desktop Safari'] },
50+
// },
51+
52+
/* Test against mobile viewports. */
53+
// {
54+
// name: 'Mobile Chrome',
55+
// use: { ...devices['Pixel 5'] },
56+
// },
57+
// {
58+
// name: 'Mobile Safari',
59+
// use: { ...devices['iPhone 12'] },
60+
// },
61+
62+
/* Test against branded browsers. */
63+
// {
64+
// name: 'Microsoft Edge',
65+
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
66+
// },
67+
// {
68+
// name: 'Google Chrome',
69+
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
70+
// },
71+
],
72+
73+
/* Run your local dev server before starting the tests */
74+
// webServer: {
75+
// command: 'npm run start',
76+
// url: 'http://localhost:3000',
77+
// reuseExistingServer: !process.env.CI,
78+
// },
79+
});

test-data/brandsList.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"brands": [
3+
"Polo",
4+
"H&M",
5+
"Madame",
6+
"Mast & Harbour",
7+
"Babyhug",
8+
"Allen Solly Junior",
9+
"Kookie Kids",
10+
"Biba"
11+
]
12+
}

0 commit comments

Comments
 (0)