question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Question] @playwright/test: is there still a way to override fixtures?

See original GitHub issue

Primarily, I’m trying to achieve one of the older methods of authentication, by overriding the context/page fixtures (as seen here). Been looking around for a bit, and can’t seem to find a nice way to do this with some of the latest fixture documentation.

Is there a 1:1 translation from that old method, to the current setup for fixtures? Specifically, getting access to browser when creating a new fixture, and overriding context/page?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
mxschmittcommented, Jun 11, 2021

In one of my projects, I was able to override it like that:

import { test as baseTest } from '@playwright/test';

const test = baseTest.extend({
  page: async ({ page }, use) => {
    await page.goto('http://localhost:3579');
    await use(page);
  },
});

export const it = test;
export const expect = test.expect;

Does this work for you?

2reactions
benjimanbrandtcommented, Jun 12, 2021

Yup, that works! I’ve been working to make it a bit more flexible. Long story short, I use projects to run tests per credential set, and a worker fixture to do the login once per worker. Then, I override the context fixture to use that auth info. Here’s a simplified version of what I came up with, in case it might help others:

// some interfaces def file

export interface AuthFile {
  [index: string]: string;
}

export interface Credentials {
  user: string;
  password: string;
}

export interface AuthorizationConfig {
  /** contextStorageState is the information gotten from context.storageState() */
  contextStorageState?: BrowserContextStorageState;
  /** sessionStorage is the information gotten from page.evaluate(() => sessionStorage) */
  sessionStorage?: Record<string, string>;
}
// playwright.config.ts

const getUserCredentials = (file: AuthFile): Array<Credentials> => { /* get creds */ };
const AUTH_CONFIG = parseAuthFileSomeHow();

const config: PlaywrightTestConfig<unknown, Credentials> = {
  projects: getUserCredentials(AUTH_CONFIG).map((credentials: Credentials) => ({
    name: credentials.user,
    use: {
      user: credentials.user,
      password: credentials.password,
      browserName: "chromium",
    }
  }))
};

export default config;
// fixtures.ts (or whatever you want to call it)

const initializeSessionStorage = async (
  context: BrowserContext,
  sessionEntries: Record<string, string>
) => {
  await context.addInitScript((entries: Record<string, string>) => {
    Object.keys(entries).forEach(key =>
      sessionStorage.setItem(key, entries[key])
    );
  }, sessionEntries);
};

const getAuthorizationConfig = async (
  browser: Browser,
  user: string,
  password: string
): Promise<AuthorizationConfig> => {
  const page = await browser.newPage();

  // whatever the login function is defined as
  await login(page, user, password);

  // store authentication data
  const contextStorageState = await page.context().storageState();
  const sessionStorage: Storage = await page.evaluate(() => sessionStorage);
  await page.close();

  return {
    contextStorageState,
    sessionStorage
  };
};

export const test = base.extend<unknown, { authConfig: AuthorizationConfig }>({
  authConfig: [
    async ({ browser }, use, workerInfo) => {
      const {
        use: { user, password }
      } = workerInfo.project as FullProject<unknown, Credentials>;

      if (user && password) {
        // get auth'd
        const authConfig = await getAuthorizationConfig(
          browser,
          user.toString(),
          password.toString()
        );

        // use the auth
        await use(authConfig);
      }

      // nothing to clean up
    },
    { scope: "worker", auto: true }
  ],

  context: async (
    {
      // typical arguments to this function omitted for brevity
      authConfig
    },
    use,
    testInfo
  ) => {
    const { contextStorageState, sessionStorage } = authConfig;

   // typical actions to set timeout and such omitted for brevity

    const options: BrowserContextOptions = {
      recordVideo: recordVideo ? { dir: testInfo.outputPath("") } : undefined,
      ...contextOptions,
      storageState: contextStorageState
    };
    // other option determinations omitted for brevity

    const context = await browser.newContext(options);

    if (sessionStorage) {
      await initializeSessionStorage(context, sessionStorage);
    }
    
    // tracing stuff omitted for brevity
    
    await use(context);

    // use the rest of the definition (playwright/src/test/index.ts::test.context) as-is from here
  }
});
// some-test.spec.ts

import { test } from "./fixtures";

test("this page is auth'd and loads", async ({ page }) => {
  expect(await page.title()).not.toBeNull();
});
Read more comments on GitHub >

github_iconTop Results From Across the Web

Advanced: fixtures | Playwright - CukeTest
This allows us to override the baseURL used by the page fixture in our tests using test. use . Fixtures can also be...
Read more >
Playwright Fixtures | POM | Playwright Tutorial - part 35
In this video, with the help of playwright fixtures, we are going to reduce the page object model complexity.Chapters:0:00 Playwright Test ...
Read more >
Playwright With TypeScript Tutorial | Part X | LambdaTest
Ever wondered what Playwright Fixtures are? Watch this video to learn the concept of Playwright Fixtures and how to implement them for the...
Read more >
Playwright Test Fixtures - ProgramsBuzz
The playwright test will set up the page fixture, which will be used to navigate to the browser and tear it down after...
Read more >
Playwright save storage state only for certain files
In that case when you are need other auth just overwrite it with keyword "use". It is described in playwright doc. https://playwright.dev/docs/test-fixtures
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found