← Back to Discord Forum

Fixture returning method to select user

Hi everyone ! On the documentation, there is an explanation about how to handle multiusers, especially here : https://playwright.dev/docs/auth#testing-multiple-roles-with-pom-fixtures

But I was wondering if anyone had an example to do so by offering a method to select the desired user so that instead of having :

test('admin and user', async ({ adminPage, userPage }) => {
  // ... interact with both adminPage and userPage ...
  await expect(adminPage.greeting).toHaveText('Welcome, Admin');
  await expect(userPage.greeting).toHaveText('Welcome, User');

We could have :

test('admin and user', async ({ pageFrom }) => {
  // ... interact with both adminPage and userPage ...
  await expect(pageFrom('admin').greeting).toHaveText('Welcome, Admin');
  await expect(pageFrom('user').greeting).toHaveText('Welcome, User');

The problem I am having is that I'm not sure how to create my fixture to reach this goal... Thank your for your incoming help 🙂

This thread is trying to answer question "How can I create a fixture in Playwright to handle multiusers and offer a method to select the desired user?"

6 replies

something like this based on example, not sure if everything is correct

pageFrom: async ({ browser }, use) => {
    let context: BrowserContext

    const callback = async (type: 'user' | 'admin') => {
      context = await browser.newContext({ storageState: `playwright/.auth/${type}.json` })
      if (type === 'admin') {
        return new AdminPage(await context.newPage())

      return new UserPage(await context.newPage())

    await use(callback)

    await context.close()
test('Some test', async ({ pageFrom }) => {
  await expect((await pageFrom('user')).greeting).toHaveText('Welcome, User')

and you'll have to use await on pageFrom

Thanks for your answer :). I already made something very very close to this ^^. But as I met similar issue with your code, I wanted to have a very naïve approach, which resulted in similar issue : I haveto check for path to exists, which is weird as this isn't needed in docs. Maybe I'm missing something ? Does it makes sense to you ?

Also, it just doesn't work in real testing scenario :(.

export const test = base.extend<E2eUserPagesFixture>({
  pageFrom: async ({ browser }, use) => {
    let context: BrowserContext

    await use(async (username: E2EUsername) => {
      context = await browser.newContext()

      const path = `playwright/.auth/${username}.json`
      const userPage = new UserPage(await context.newPage(), username)

      const hasStorageState = fs.existsSync(path)
      if (hasStorageState) {
        return userPage

      await userPage.login()
      context.storageState({ path })

      return userPage

    await context!.close()
test.beforeEach(async ({ pageFrom }) => {
  await (await pageFrom('default')).page.goto('/somewhere')

  await Promise.all([
    await (await pageFrom('default')).page.waitForResponse((resp) => resp.url().includes('/abc')),
    await (await pageFrom('default')).page.waitForResponse((resp) => resp.url().includes('/def')),

In the examples it is assumed that you run setup beforehand which will populate both those storage state files, https://playwright.dev/docs/auth#multiple-signed-in-roles

so when test actually starts and fixture is created it uses those created storage state files

It makes a lot more sense now ! Thank you :). I assure that as I will have a method, if I don't want to regenerate my UserPage object, I'll have to use a singleton mapping.

Thanks a lot, I'll give it a try 🙂

Related Discord Threads

AboutQuestionsDiscord ForumBrowser ExtensionTagsQA Jobs

Rayrun is a community for QA engineers. I am constantly looking for new ways to add value to people learning Playwright and other browser automation frameworks. If you have feedback, email luc@ray.run.