links:: advanced Playwright MOC
Chapter 1.1 - Optimizing Authentication - Demoqa Site Example
Chapter 1.1 - Optimizing Authentication - Demoqa Site Example
Notes:
- Seems like when
- storage file is created using Firefox browser, it cannot be used by tests running in Chrome.
- storage file is created using Chrome browser, it can be used by tests running in Firefox.
Examples:
profile-stored-authentication.spec.ts:
import { test } from '@playwright/test';
import ProfilePage from '../pages/profile-page';
import pages from '../../utils/pages';
let profilePage: ProfilePage;
test.beforeEach(async ({ page }) => {
await page.goto(pages.profile);
profilePage = new ProfilePage(page);
});
test.describe.only('Profile - Stored Auth', () => {
test('Check logged in', async () => {
await profilePage.checkLoggedIn();
});
});
profile-page.ts:
import { type Page, type Locator , expect, type BrowserContext } from '@playwright/test';
import bookListData from '../../data/book-list-data';
import apiPaths from '../../utils/apiPaths';
class SearchPage {
readonly page: Page;
readonly bookAdminLabel: Locator;
readonly booksCollectionRequestRegExp: RegExp;
readonly bookUserLabel: Locator;
readonly gridRow1: Locator;
readonly gridRow2: Locator;
readonly notLoggedInLabel: Locator;
readonly searchField: Locator;
readonly titleHeaderLabel: Locator;
constructor(page: Page) {
this.page = page;
this.bookAdminLabel = page.getByText('Eloquent JavaScript, Second Edition');
this.booksCollectionRequestRegExp = new RegExp(apiPaths.account);
this.bookUserLabel = page.getByText('Understanding ECMAScript 6');
this.gridRow1 = page.locator('div:nth-child(1) > .rt-tr > div:nth-child(2)').last();
this.gridRow2 = page.locator('div:nth-child(2) > .rt-tr > div:nth-child(2)');
this.notLoggedInLabel = page.getByText('Currently you are not logged into the Book Store application, please visit the login page to enter or register page to register yourself.');
this.searchField = page.getByPlaceholder('Type to search');
this.titleHeaderLabel = page.getByText('Title');
}
async fillSearchField(q: string) {
await this.searchField.fill(q);
}
async checkSearchResult(q: string, items: string) {
}
async checkBooksList() {
for (const book of bookListData.books){
await expect(this.page.getByRole('link', { name: book.title })).toBeVisible();
}
}
async sortBooksList() {
await this.titleHeaderLabel.click({ clickCount: 2 });
}
async checkLoggedIn() {
await expect(this.notLoggedInLabel).not.toBeVisible();
// await expect(this.notLoggedInLabel).toBeVisible();
}
async checkLoggedInUser() {
await expect(this.notLoggedInLabel).not.toBeVisible();
await expect(this.bookUserLabel).toBeVisible();
}
async checkLoggedInAdmin() {
await expect(this.notLoggedInLabel).not.toBeVisible();
await expect(this.bookAdminLabel).toBeVisible();
}
async checkSort() {
await expect(this.gridRow1).toContainText(bookListData.books[1].title);
await expect(this.gridRow2).toContainText(bookListData.books[0].title);
}
async getBooksList() {
}
async mockBooksListResponse(context: BrowserContext) {
await context.route(this.booksCollectionRequestRegExp, (route) => route.fulfill({
body: JSON.stringify({...(bookListData)})
}));
}
}
export default SearchPage;
global-setup.ts:
import { chromium, FullConfig } from '@playwright/test';
import LoginPage from '../ui/pages/login-page';
import uiPages from '../utils/uiPages';
async function globalSetup(config: FullConfig) {
const user = process.env.USERNAME!;
const password = process.env.PASSWORD!;
const { baseURL, storageState } = config.projects[0].use;
const browser = await chromium.launch({ headless: true, timeout: 10000 });
const page = await browser.newPage();
const loginPage = new LoginPage(page);
await page.goto(baseURL+uiPages.login);
await loginPage.doLogin(user, password);
await loginPage.checkLoggedIn();
await page.context().storageState({ path: storageState as string });
await browser.close();
}
export default globalSetup;
// https://playwright.dev/docs/test-global-setup-teardown#capturing-trace-of-failures-during-global-setup
// https://playwright.dev/docs/trace-viewer
playwright.config.ts:
import { defineConfig, devices } from '@playwright/test';
import baseEnvUrl from './tests/utils/environmentBaseUrl';
require('dotenv').config();
export default defineConfig({
globalSetup: require.resolve('./tests/setup/global-setup'),
fullyParallel: false,
forbidOnly: !!process.env.CI,
retries: 0,
workers: undefined,
reporter: 'html',
// timeout: 5000,
use: {
storageState: 'storageState.json',
trace: 'on',
baseURL: process.env.ENV === 'production'
? baseEnvUrl.production.home
: process.env.ENV === 'staging'
? baseEnvUrl.staging.home
: baseEnvUrl.local.home
},
projects: [
{
name: 'auth-setup',
testMatch: /auth-setup\.ts/
},
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
storageState: 'storageState.json',
},
},
{
name: 'chromium-auth',
use: {
...devices['Desktop Chrome'] ,
// storageState: '.auth/admin.json', //use this in case you have multiple projects one per user
},
dependencies: ['auth-setup'],
},
],
});