DEV Community

Eakam
Eakam

Posted on

Starchart: Shared sessions in Playwright

Last week, I worked on setting up shared authentication for end-to-end Playwright tests in starchart. This was necessary to avoid having to login before every test. The Playwright docs suggest a few different ways of doing this, such as a shared account for all tests, or setting up multiple roles.

I went with a similar setup to the setup you would have for multiple roles with a shared account across all tests that require login. Currently, all the pages do not differentiate between roles, i.e., they do not show different things based on the role. However, a design for an admin dashboard was being worked on, and will be implemented in the upcoming weeks. So, I decided to use a setup that would be easy to expand for different roles such as an admin user.

I started by adding a setup file under my e2e tests folder which would go through the login process, and save the authenticated state in a file:

import { test as setup } from '@playwright/test';
const userFile = 'test/e2e/.auth/user.json';

setup('authenticate as user', async ({ page }) => {
  ...
  // Login steps

  await page.context().storageState({ path: userFile });
});
Enter fullscreen mode Exit fullscreen mode

Then I modified playwright config and added a new project that will be a dependency of all other projects. A project has a name and defines configuration for running the tests on a specific device in this case:

projects: [
  {
    name: 'setup',
    testMatch: /.*\.setup\.ts/,
  },
  {
    name: ...,
    use: {
      ...devices['Desktop Chrome'],
    },
    dependencies: ['setup'],
  },
  ... other projects
Enter fullscreen mode Exit fullscreen mode

By setting setup as a dependency, it will be run before the tests in the project are run. testMatch defines a regex for the setup file(s), and it matches paths relative to the test directory defined in the config.

Since the setup process is run before the tests are run, we actually don't need to commit our file with the saved session to git. Thus, I added it to the .gitignore file.

I also added tests for the New DNS Record form. This form is used by a user to create a new DNS Record. Since this required a user to be logged in, we can use the saved session state generated in the setup project:

test.describe('authenticated as user', () => {
  loggedInAsUser();
Enter fullscreen mode Exit fullscreen mode

Here, loggedInAsUser() is a util function that was added based on PR reviews:

export function loggedInAsUser() {
  return test.use({ storageState: 'test/e2e/.auth/user.json' });
}
Enter fullscreen mode Exit fullscreen mode

test.use can be specified in a describe block or in a test file. It is not necessary to use this in a beforeEach or beforeAll, and doing so would result in an error.

I ran the tests locally, and they all passed. However, I encountered a strange error in CI (which uses GitHub Actions) for the Mobile Safari project:

Test timeout of 30000ms exceeded.

page.goto: Navigation failed because page was closed!
Enter fullscreen mode Exit fullscreen mode

Playwright generates a report containing a video and a trace on the first retry, depending on the configuration. I looked at the video and saw that most of it was a blank black screen. After trying a bunch of things such as upgrading playwright, and commenting out all other projects, I found this open issue on the playwright project. There was a super helpful comment left on the issue with a temporary workaround. Basically, setting isMobile to false for the iPhone configuration used by the Mobile Safari project results in the CI passing on GitHub actions.

Top comments (0)