javascriptplaywrightplaywright-test

Cannot pass variables from outer scope to `addInitScript` in Playwright


I am trying to create a generic login utility function in playwright. It would look something like:

const login = async (page, user) => {
  await page.addInitScript(() => {
    window.localStorage.setItem('user', JSON.stringify(user));
  })
}

Then in any given test, I can log in with a specific user:

test("Test login user 1", async ({ page }) => {
  await login(page, exampleUser1)
  // assert stuff
})

test("Test login user 2", async ({ page }) => {
  await login(page, exampleUser1)
  // assert other stuff
})

The problem here is that addInitScripts seems to not be able to take any arguments from outside its callback. I get an error that user is not defined. Apparently the code that's inside that callback is ran "as is", as if it were being stringified and then evaluated within the page.

How can I create a generic utility function that applies a variable localStorage value on page load?


Solution

  • Please see the docs for addInitScript:

    await page.addInitScript(mock => {
      window.mock = mock;
    }, mock);
    

    arg Serializable (optional) #

    Optional argument to pass to script (only supported when passing a function).

    Like any evaluate-family call, you can pass an optional argument and add it to the parameter list, assuming your data is serializable:

    //                       vvvv
    await page.addInitScript(user => {
      window.localStorage.setItem('user', JSON.stringify(user));
    }, user);
    // ^^^^
    

    Also possible:

    await page.addInitScript(
      `window.localStorage.setItem('user', '${JSON.stringify(user)}')`
    );