- Butch Mayhew's companion GitHub site on LinkedIn Learning's GitHub page.
- Site under test: Practice Software Testing: https://practicesoftwaretesting.com
- Official Playwright Documentation: https://playwright.dev/docs
- Official Playwright GitHub: https://github.com/microsoft/playwright
What is Playwright?
| Best for | Install | |
|---|---|---|
| Playwright Test | End-to-end testing | npm init playwright@latest |
| Playwright CLI | Coding agents (Claude Code, Copilot) | npm i -g @playwright/cli@latest |
| Playwright MCP | AI agents and LLM-driven automation | npx @playwright/mcp@latest |
| Playwright Library | Browser automation scripts | npm i playwright |
| VS Code Extension | Test authoring and debugging in VS Code | Install from Marketplace |
Getting an Authorization Cookie Through the Website
- Open up Chrome and go to https://practicesoftwaretesting.com/auth/login
- Right click on the page and select "Inspect" to open Chrome Developer Tools.
- Select the "Network" tab.
- Enter a username and password of customer@practicesoftwaretesting.com / welcome01
- Select the "Login" button, then view the Network tab.
- On the network tab, click on the "account" entry.
- Select the "Cookies" tab in Chrome Developer Tools.
"cookies": [
{
"name": "cf_clearance",
"value": "2Rv345ZtjSaGUFRwq6j2QO4Qp3EBG0T.5URv.oenfjg-1778187254-1.2.1.1-90Z63mBartyo.dUm4bwavAggVG9pgrzcYOO0zPS18qBEujmzIq3tnWwjx2b5jQypbZywJMVEIncDFSwJBaAD0ephO3cctJrLkS449MVHNO7ZSuqlAPhzVYGw8vVH4doqYc2R_5WXTY47OHVLRAgnblq7U9glSiaJUvoOKmc6I.Mo6FPl3MrhGmfMxSTVyTkcCBJn8t_C9b1margtoukM7yMuQdNPpkNItvrrZdIQT.TpGQx2sNX7cS_KS8TY2Ghyc0_QLKFZFqC_5ZgZHMad5xgzgvJEm2NZmO3RBLSPKH5bpDFbuynt7g4oIwYfIvWd4pTpTB447hpP5qMPnLOp.Q",
"domain": ".practicesoftwaretesting.com",
"path": "/",
"expires": 1809723253.921407,
"httpOnly": true,
"secure": true,
"sameSite": "None",
"partitionKey": "https://practicesoftwaretesting.com",
- Random token: 2Rv345ZtjSaGUFRwq6j2QO4Qp3EBG0T.5URv.oenfjg
- Unix timestamp: 1778187254 (Around May 4, 2026)
- Version Level: 1.2.1.1, the Clearance level encoding
- Signature payload: 90Z63mBartyo... HMAC-binding (Hash-Based Message Authentication Codes) to IP, user agent, and session.
- What is a Unix Time Stamp? "The unix time stamp is a way to track time as a running total of seconds. This count starts at the Unix Epoch on January 1st, 1970 at UTC. Therefore, the unix time stamp is merely the number of seconds between a particular date and the Unix Epoch. It should also be pointed out (thanks to the comments from visitors to this site) that this point in time technically does not change no matter where you are located on the globe. This is very useful to computer systems for tracking and sorting dated information in dynamic and distributed applications both online and client side" - UnixTimeStamp.com
Step One: Setup the Setup
projects: [
{
name: "setup",
testMatch: /.*\.setup\.ts/,
},
{
name: "chromium",
dependencies: ["setup"],
use: {
...devices["Desktop Chrome"],
permissions: ["clipboard-read", "geolocation"],
},
},According to Playwright.Dev, "Dependencies are a list of projects that need to run before the tests in another project run. They can be useful for configuring the global setup actions so that one project depends on this running first.
"When working with tests that have a dependency, the dependency will always run first and once all tests from this project have passed, then the other projects will run in parallel.
"Running order: Tests in the 'setup' project run. Once all tests from this project have passed, then the tests from the dependent projects will start running.
"Tests in the 'chromium' [...] projects run together. By default, these projects will run in parallel, subject to the maximum workers limit".
- name: "setup": A project with the name of "setup".
- testMatch: /.*setup\.ts,: This pattern matcher searches on level up for anything with "setup" in the middle of the filename, such as "auth.setup.ts" in the "tests/" directory.
- name: "chromium": A project that directs the test automation when it runs to use the Desktop Chrome browser devices.
- dependencies: ["setup"]: Before the Chrome browser has kicked off, we tell it we need to run the project called "setup" first.
- use: ...devices["Desktop Chrome"]: Playwright has an enormous list of devices in its device registry, such as various models of the Blackberry, Galaxy, iPad, iPhone, Microsoft Lumia, Nexus, Nokia, Pixel, Moto, and Desktop Devices (Chrome, Edge, Firefox, Safari) with many different user agents, viewports, and screen width and heights.
- use: permissions: Playwright's browser context, according to the official Playwright Docs, has differing sets of permissions in the permission array for each browser emulation, such as emulating the accelerometer, ambient light sensor, background sync, camera, clipboard read and write, geolocation, gyroscope, local fonts, local network access, magnetometer, microphone, midi, notifications, payment-handler, storage-access, and screen-wake-lock.
- [clipboard-read]: We need to give the Chromium browser Playwright spins up permission to read the authentication cookie that is generated the first time we log in. Note, according to notes in Playwright's source code in the permissions library, there is no "clipboard-read" in WebKit's API.
Step Two: Get and Save the Authorization Cookie
tests/ auth.setup.ts:
import { test as setup, expect } from "@playwright/test";
import { LoginPage } from "../lib/pages/login/login.page";
setup("Create customer 01 auth", async ({ page, context }) => {
const email = "customer@practicesoftwaretesting.com";
const password = "welcome01";
const customer01AuthFile = ".auth/customer01.json";
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login(email, password);
await expect(page.getByTestId("nav-menu")).toContainText("Jane Doe");
await context.storageState({ path: customer01AuthFile });
});https://github.com/LinkedInLearning/playwright-essential-training-abstractions-fixtures-and-complex-scenarios-4278224/blob/98d2080e018acb194938157cb7c2fc8993ca21a5/tests/auth.setup.tsWhat is this code doing?
- Import the test runner playwright/test into our TypeScript file, setting up an alias for the test runner, calling it "setup" to make the test more readable, and to mark this as performing initialization tasks. To learn more about how aliases work in TypeScript see FreeCodeCamp's explanation, and read about the test method in the Playwright.dev docs.
- Import the expect assertion library into the TypeScript file, so we then can use the expect method, detecting if an element is attached, checkbox is checked, element is disabled, editable, enabled, focused, not visible, visible, contains text, has certain CSS classes, DOM attributes, ids, CSS or JavaScript properties, ARIA roles, screenshots, matches text, or if pages have screenshots, titles, or URLs, failing near immediately if we don't see that condition. [ See Playwright.Dev docs about test assertions ]. We can also match if it meets any instance of a class, matches anything, of an array contains certain elements, if a number is close to equal, a string contains a substring, a string matches a certain substring. All of these expects can be negated chaining a not to it.
- setup("Create customer 01 auth" is being used by Butch Mayhew instead of saying "test("Create customer 01 auth") to make it more readable.
- async uses the JavaScript keyword async. FreeCodeCamp says that, "Async programming is a programming paradigm that allows you to write code that runs asynchronously. In contrast to synchronous programming, which executes code sequentially, async programming allows code to run in the background while the rest of the program continues to execute. This is particularly useful for tasks that may take a long time to complete, such as fetching data from a remote API".
- page, context are passing these built-in fixtures into the test. The Page instance is created for each test, used in isolation from one another. [ See Playwright.dev docs on test fixtures. ] "Test fixtures are used to establish the environment for each test, giving the test everything it needs and nothing else. Test fixtures are isolated between tests. With fixtures, you can group tests based on their meaning, instead of their common setup". The "page" fixtures uses type Page, and "context" fixtures uses type BrowserContext in order to configure context. Fixtures can encapsulate setup and teardown, are reusable between test files.
- const email, password, customer01AuthFile is declaring constant variables to store what the username, password, and where the auth cookie should be stored, to make the code more readable.
- const loginPage is instantiating a new login page using the login page object Butch has defined, not covered in this blog entry. The login page Butch set up contains methods where you can goto https://practicesoftwaretesting.com/auth/login, enter the username and password in the login method using the constants we defined, expecting that we see a greeting to the user.
- Playwright has storage and authentication methods where you can manage cookies, localStorage and sessionStorage [ See official docs ]. Session Storage is session scoped, where data is cleared out when the browser tab eventually closes.
- According to the Playwright Docs / Authentication, when you "[c]reate a new setup project in the config and declare it as a dependency for all your testing project [...]. This project will always run and authenticate before all the tests. All testing projects should use the authenticated state as storageState".
The Cookie is Temporarily Saved!
A new folder and file is created in the root folder when this command is run: .auth/customer01.json:
{
"cookies": [
{
"name": "cf_clearance",
"value": "2Rv345ZtjSaGUFRwq6j2QO4Qp3EBG0T.5URv.oenfjg-1778187254-1.2.1.1-90Z63mBartyo.dUm4bwavAggVG9pgrzcYOO0zPS18qBEujmzIq3tnWwjx2b5jQypbZywJMVEIncDFSwJBaAD0ephO3cctJrLkS449MVHNO7ZSuqlAPhzVYGw8vVH4doqYc2R_5WXTY47OHVLRAgnblq7U9glSiaJUvoOKmc6I.Mo6FPl3MrhGmfMxSTVyTkcCBJn8t_C9b1margtoukM7yMuQdNPpkNItvrrZdIQT.TpGQx2sNX7cS_KS8TY2Ghyc0_QLKFZFqC_5ZgZHMad5xgzgvJEm2NZmO3RBLSPKH5bpDFbuynt7g4oIwYfIvWd4pTpTB447hpP5qMPnLOp.Q",
"domain": ".practicesoftwaretesting.com",
"path": "/",
"expires": 1809723253.921407,
"httpOnly": true,
"secure": true,
"sameSite": "None",
"partitionKey": "https://practicesoftwaretesting.com",
"_crHasCrossSiteAncestor": false
}
],
"origins": [
{
"origin": "https://practicesoftwaretesting.com",
"localStorage": [
{
"name": "auth-token",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS5wcmFjdGljZXNvZnR3YXJldGVzdGluZy5jb20vdXNlcnMvbG9naW4iLCJpYXQiOjE3NzgxODcyNTUsImV4cCI6MTc3ODE4NzU1NSwibmJmIjoxNzc4MTg3MjU1LCJqdGkiOiJoeFJ1MmkwNWpDamVrNUdXIiwic3ViIjoiMDFLUjIwRFFYQUpTVEJEWkg2S0Q1R1QwRVQiLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3Iiwicm9sZSI6InVzZXIifQ.Iqv8TGSweXLUfk7UExbIem_kOoIde9apIrzFZ9cCVpo"
}
]
}
]
}
Step Three: Make Sure The Cookie Is Only Temporarily Saved. Do Not Upload the Cookie To GitHub!!!
- Read more about .gitignore on the Git-SCM/docs/gitignore page.
Step Four: Implement the Auth Cookie for Login
Now that the Setup function generated a new cookie, we then can then use this credential setting up the test to use storageState.tests / homepage / home.spec.ts:
test.describe("Home page customer 01 auth", () => {
test.use({ storageState: ".auth/customer01.json" });
test.beforeEach(async ({ page }) => {
await page.goto("/");
});
tests / homepage / home.spec.ts:
test("check customer 01 is signed in", async ({ page }) => {
await expect(page.getByTestId("nav-sign-in")).not.toBeVisible();
await expect(page.getByTestId("nav-menu")).toContainText("Jane Doe");
});
If we don't see the sign in page, and instead we see the nav menu for "Jane Doe", then everything has passed.
-T.J. Maher
Software Engineer in Test
BlueSky | YouTube | LinkedIn | Articles
No comments:
Post a Comment