How to Convert Your API Login Helper to a Reusable Fixture in Playwright (JS Version)



If you’re still writing login steps in every single Playwright test file, you’re slowing yourself down.

Instead of wasting time on repeated UI logins, you can log in programmatically via API and reuse that session in all your tests.

In this guide, you’ll learn how to turn an API login helper into a reusable Playwright fixture — speeding up your end-to-end tests while keeping them stable.

If you're still writing login steps in every single test file, you're wasting time.

Let me show you how to go from this:

await page.goto('/login');
await page.fill('#email', '[email protected]');
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, ‘[email protected]’, ‘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 ({ auth
  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 authenticatedPage 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"
Apply to the Codemify Bootcamp — and start building your future now.
Let’s make tech simple — and profitable — for you.

See you in class,
— Sergii
Founder of Codemify
Follow us on YouTube | Join the Bootcamp
Schedule a FREE 15-minute consultation with Sergii to discuss your testing career and job opportunities.
Limited slots are available!
We help ambitious people to get into Tech with no prior experience.