Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add playwright test to check responsiveness in transactions page #235

Merged
merged 17 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,15 @@ jobs:
run: npx playwright install --with-deps chromium firefox webkit
shell: bash

- name: Run Playwright tests
- name: Run Playwright e2e tests
run: HOME=/root npm run e2e

- name: Run Playwright e2e responsive tests with mocks
run: HOME=/root npm run e2e-test-responsive
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 7

5 changes: 5 additions & 0 deletions apps/golden-sample-app-e2e/page-objects/test-runner.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { test as baseTest } from '@playwright/test';
import { VisualValidator } from '../utils/visual-validator';
import { IdentityPage } from './pages/identity-page';
import { testConfig } from '../test-config';
import 'dotenv/config';

export const test = baseTest.extend<{
// Pages
identityPage: IdentityPage;
visual: VisualValidator;
}>({
identityPage: async ({ page }, use, testInfo) => {
await use(
new IdentityPage(page, testInfo, { url: testConfig.appBaseUrl() })
);
},
visual: async ({ page }, use) => {
await use(new VisualValidator(page));
},
});
15 changes: 15 additions & 0 deletions apps/golden-sample-app-e2e/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "golden-sample-app-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"tags": [],
"implicitDependencies": ["golden-sample-app"],
"targets": {
"e2e-chrome-mobile": {
"executor": "nx:run-commands",
"options": {
"command": "npx playwright test --project 'mobile-chrome' --grep '@visual.+@responsive|@responsive.+@visual' --workers=2"
}
}
}
}
2 changes: 1 addition & 1 deletion apps/golden-sample-app-e2e/specs/login.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const i18n = {

test.describe.configure({ mode: 'parallel' });

test.describe('@feature @i18n Login tests', () => {
test.describe('@feature @i18n @e2e Login tests', () => {
test('Empty user name', async ({ identityPage }) => {
identityPage.open();
await test.step('Validate Input fields labels', async () => {
Expand Down
22 changes: 22 additions & 0 deletions apps/golden-sample-app-e2e/specs/transactions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { test } from '../page-objects/test-runner';

test.beforeEach(async ({ page }) => {
await page.goto('transactions');
});
test.describe.configure({ mode: 'parallel' });

test.describe('@feature @responsive @visual Transaction page tests', () => {
test('Validate responsiveness of the transactions page', async ({
page,
visual,
}) => {
await test.step(`Transaction page full`, async () => {
await visual.testFullPage('transactions-page-full');
});
await test.step(`Transaction page with masked data`, async () => {
await visual.testWithMask('transactions-page-with-masked-data', {
mask: ['.transaction-account-number'],
});
});
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { VisualTypes } from './visual-types';

export interface VisualPageTypes extends VisualTypes {
clip?: { x: number; y: number; width: number; height: number };
fullPage?: boolean;
}
13 changes: 13 additions & 0 deletions apps/golden-sample-app-e2e/utils/interfaces/visual-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Locator } from '@playwright/test';

export interface VisualTypes {
animations?: 'disabled' | 'allow';
caret?: 'hide' | 'initial';
mask?: Array<Locator>;
maxDiffPixelRatio?: number;
maxDiffPixels?: number;
omitBackground?: boolean;
scale?: 'css' | 'device';
threshold?: number;
timeout?: number;
}
75 changes: 75 additions & 0 deletions apps/golden-sample-app-e2e/utils/visual-validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { expect, Locator, Page } from '@playwright/test';
import { VisualPageTypes } from './interfaces/visual-page-types';
import { VisualTypes } from './interfaces/visual-types';

export class VisualValidator {
rtlPrefix: string;
constructor(
protected page: Page,
protected skip = false,
protected rtl = false
) {
this.rtlPrefix = rtl ? `rtl-` : ``;
}

async testFullPage(name: string, options?: { waitBefore: number }) {
if (this.skip) return;
if (options?.waitBefore) {
await this.page.waitForTimeout(options.waitBefore);
}
await expect(this.page).toHaveScreenshot(this.screenName(name), {
fullPage: true,
maxDiffPixelRatio: 0.01,
});
}

async test(name: string, options?: VisualPageTypes) {
if (this.skip) return;
await expect(this.page).toHaveScreenshot(this.screenName(name), options);
}

async testWithMask(name: string, options: { mask: string[] }) {
if (this.skip) return;
await expect(this.page).toHaveScreenshot(this.screenName(name), {
mask: options.mask.map((selector) => this.page.locator(selector)),
maxDiffPixelRatio: 0.01,
});
}

async testForm(name: string) {
await this.testElement('form', name);
}

async testShowcase(name: string) {
await this.testElement('bb-showcase', name);
}

async testElement(
element: Locator | string,
name: string,
options?: VisualTypes
) {
if (this.skip) return;
const locator =
typeof element === 'string' ? this.page.locator(element) : element;
await expect(locator).toHaveScreenshot(this.screenName(name), options);
}

async testElementWithMask(
element: Locator | string,
name: string,
options: { mask: string[] }
) {
if (this.skip) return;
const locator =
typeof element === 'string' ? this.page.locator(element) : element;
await expect(locator).toHaveScreenshot(this.screenName(name), {
mask: options.mask.map((selector) => locator.locator(selector)),
maxDiffPixelRatio: 0.01,
});
}

private screenName(name) {
return `${this.rtlPrefix}${name}.png`;
}
}
2 changes: 1 addition & 1 deletion apps/golden-sample-app/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
"options": {
"devServerTarget": "golden-sample-app:serve",
"command": "npx",
"args": ["playwright", "test"]
"args": ["playwright", "test", "--project", "web-chrome", "--grep", "@e2e"]
},
"configurations": {
"production": {}
Expand Down
54 changes: 49 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"affected:test": "nx affected:test",
"xi18n": "ng extract-i18n golden-sample-app --output-path=apps/golden-sample-app/src/locale && xliffmerge --profile apps/golden-sample-app/src/xliffmerge.json nl-NL",
"e2e": "nx e2e",
"e2e-test": "npx playwright test --update-snapshots",
"e2e-test": "npx playwright test --project 'Web Chrome' --grep '@e2e'",
"e2e-test-responsive": "npx playwright test --project 'mobile-chrome' --grep '@visual.+@responsive|@responsive.+@visual' --workers=2",
"lint": "nx run-many --all --target=lint",
"format": "prettier --write \"{apps,libs}/**/*.{ts,md,html}\" \"!{apps,libs}/**/coverage\" ",
"format:check": "prettier --list-different \"{apps,libs}/**/*.{ts,md}\" \"!{apps,libs}/**/coverage\""
Expand Down Expand Up @@ -88,7 +89,7 @@
"@nx/jest": "17.3.0",
"@nx/js": "17.3.0",
"@nx/workspace": "17.3.0",
"@playwright/test": "1.41.2",
"@playwright/test": "1.42.1",
"@schematics/angular": "17.1.4",
"@types/jest": "^29.4.4",
"@types/node": "^18.16.9",
Expand Down
24 changes: 23 additions & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const config: PlaywrightTestConfig = {
},
projects: [
{
name: 'Web Chrome',
name: 'web-chrome',
use: {
...devices['Desktop Chrome'],
launchOptions: {
Expand All @@ -51,6 +51,28 @@ const config: PlaywrightTestConfig = {
},
},
},
{
name: 'mobile-chrome',
use: {
...devices['Nexus 7'],
isMobile: true,
baseURL: 'http://localhost:4201',
},
},
],
webServer: [
{
command: 'npm run mock-server',
url: 'http://localhost:9999/dev-interface',
timeout: 30 * 1000,
reuseExistingServer: false,
},
{
command: 'npx nx serve -c=mocks --port=4201',
url: 'http://localhost:4201/',
timeout: 120 * 1000,
reuseExistingServer: false,
},
],
};

Expand Down
Loading