mkdir hung-playwright-ts-lib
cd hung-playwright-ts-lib
yarn create playwright
Log:
✔ Do you want to use TypeScript or JavaScript? · TypeScript
✔ Where to put your end-to-end tests? · tests
✔ Add a GitHub Actions workflow? (y/N) · false
✔ Install Playwright browsers (can be done manually via 'yarn playwright install')? (Y/n) · false
yarn add fs-extra
yarn add winston
npm i --save-dev @types/node
tsc
npm login
npm publish
=> OK check your package: https://www.npmjs.com/package/hung-playwright-ts-lib
- Change "version: 1.0.x" in package.json then
tsc
npm publish
again ==> OK
mkdir sample-test-proj
cd sample-test-proj
npm i
npm i --save-dev @types/node
Create "example-test-proj"
- package.js:
{
"name": "example-test-proj",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Hello: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"hung-playwright-ts-lib": "^1.0.8",
},
"devDependencies": {
"@types/node": "^20.12.3"
}
}
- Create "test-setup/page-setup.ts":
import { test as baseTest, expect } from '@playwright/test';
import { setPage } from 'hung-playwright-ts-lib/dist/utils/page-utils';
export const test = baseTest.extend<{ testHook: void }>({
testHook: [
async ({ page }, use) => {
console.log('GLOBAL: BEFORE EACH HOOK FROM FIXTURE');
setPage(page);
await use();
console.log('GLOBAL: AFTER EACH HOOK FROM FIXTURE');
},
{ auto: true },
],
});
export { expect };
- Create "testdata/test-data.ts"
export const sauceDemoCredentials = {
username: 'standard_user',
password: 'secret_sauce',
};
export const failureLoginCredentials = {
username: 'standard_user',
password: 'invalid_password',
};
- Create "test-pages/demo-login-page.ts"
import { fill, clickAndNavigate, gotoURL } from 'hung-playwright-ts-lib';
import { getLocator, getLocatorByPlaceholder, getLocatorByRole } from 'hung-playwright-ts-lib/dist/utils/locator-utils';
import { sauceDemoCredentials } from '../testdata/test-data';
const userName = `#user-name`;
const password = () => getLocator(`#password`).or(getLocatorByPlaceholder('Password', { exact: true }));
const loginButton = () => getLocatorByRole('button', { name: 'Login' });
export async function navigateToSauceDemoLoginPage() {
await gotoURL('https://www.saucedemo.com/');
}
export async function loginWithValidCredentials(validCredentials = sauceDemoCredentials) {
await fill(userName, validCredentials.username);
await fill(password(), validCredentials.password);
await clickAndNavigate(loginButton());
}
- Create "tests/demo-all.pass.spec.ts"
import { test } from '../test-setup/page-setup';
import * as LoginPage from '../test-pages/demo-login-page';
test.describe.configure({ mode: 'parallel' });
test.describe('Saucedemo tests for successful, unsuccessful logins and add products to cart @smoke', () => {
test.beforeEach('Navigating to sauce demo page', async () => {
await LoginPage.navigateToSauceDemoLoginPage();
});
test('Saucedemo tests - Successful login will display Products Page', async () => {
await LoginPage.loginWithValidCredentials();
});
});
npx playwright test
==> log:
Running 1 test using 1 worker
✓ 1 … successful, unsuccessful logins and add products to cart @smoke › Saucedemo tests - Successful login will display Products Page (1.4s)
GLOBAL: BEFORE EACH HOOK FROM FIXTURE
GLOBAL: AFTER EACH HOOK FROM FIXTURE
1 passed (2.8s)`
==> OK