Tired of typing the same login steps in every Playwright test?
Yeah, me too.
Instead of wasting minutes (that add up to hours) on repeated UI logins, you can log in once — programmatically via API — and reuse that session everywhere.
In this guide, I’ll show you how to turn your API login helper into a reusable Playwright fixture. The result? Faster, more stable end-to-end tests and a lot less frustration.
Let’s go from clicking through the UI… to logging in like a pro.
await page.goto('/login');
await page.fill('#email', 'user@test.com');
await page.fill('#password', 'DontTestMe');
await page.click('button[type="submit"]');
To this:
await apiLogin(page, request, adminEmail, adminPassword);
await page.goto('/dashboard');
And finally, to this:
await authenticatedPage.goto('/dashboard');
No UI login. No wasted time. Just results.
The Setup: API Login via Token
Let’s say your backend gives you an accessToken after
a POST to /api/users/login. We’ll use that to inject the cookie directly.
This trick will log in your user programmatically before the test even starts.
Step 1: Your apiLogin.js helper
Create this file:
// Send login api request
const apiResponse = await apiClient.post(/api/users/login
, {
data: {
email,
password
}
});
// Convert response to json
const apiResponseJson = await apiResponse.json();
// Return accessToken for future usage
return apiResponseJson.accessToken;
}
Step 2: Create a Playwright fixture
Create this file:
import { apiLogin } from '../api/UsersApi';
export const test = base.extend({
authenticatedPage: async ({ browser }, use) => {
// Step 1: Create an API client (apiContext)
const apiClient = await request.newContext();
// Step 2: Send api login request
const token = await apiLogin(apiClient, ‘test@gmail.com’, ‘12345678’);
// Step 3: Create a browser context to add your apiToken to
const context = await browser.newContext();
// Step 4: Inject localStorage token before any page is created
await context.addInitScript((tokenValue) => {
window.localStorage.setItem('accessToken', tokenValue);
}, token);
// Step 5: Create and use new page our of context above
const page = await context.newPage();
await use(page);
await context.close();
}
});
Step 3: Write your test
test(‘should find best qa automation bootcamp’, async ({ authenticatedPage, createdListing }) => {
await authenticatedPage.goto('https://www.youtube.com/@Codemify');
await expect(authenticatedPage).toHaveText(/Best QA Bootcamp/);
});
Why This Is So Powerful
- Speed – No need to visit login page, wait for form, or click buttons.
- Stability – Removes flaky UI interactions from critical path.
- Reusability – You can now use authenticated Page anywhere.
And let’s be honest — if you’re going to scale your tests or teach others how to automate, this is the standard.
_"Use real user flows in your app once, then move all auth to the backend. You should test your login UI once — but run your actual tests with blazing-fast, headless tokens.
Automation is about speed and precision, not repeating what a human would do"_
— Sergii
Founder of Codemify
Follow us on YouTube |
Top comments (0)