-
Notifications
You must be signed in to change notification settings - Fork 518
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(examples): add example for reusing login with playwright (#2398)
- Loading branch information
1 parent
db60c0d
commit 65f36d3
Showing
4 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
50 changes: 50 additions & 0 deletions
50
examples/browser-playwright-reuse-authentication/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Reuse Authentication in Playwright tests | ||
|
||
Playwright allows you to use `sessionStorage` to reuse authentication in your tests. This can be especially useful in Load Testing, where you might be interested in testing other parts of the application at scale, without having to exercise the login backend (which is sometimes third-party) with every VU. | ||
|
||
This example shows you how to do that. | ||
|
||
## Pre-requisites | ||
|
||
Before running the example, install Artillery: | ||
|
||
```sh | ||
npm install artillery | ||
``` | ||
|
||
## Example | ||
|
||
The example leverages [`storageState`] similarly to [Playwright documentation](https://playwright.dev/docs/auth#basic-shared-account-in-all-tests). It's simple to set this up with Artillery, but there are some small differences: | ||
|
||
* You set the `storageState` path in [`config.engines.playwright.contextOptions`](https://www.artillery.io/docs/reference/engines/playwright#configuration), instead of a Playwright config file. | ||
* A [before hook](https://www.artillery.io/docs/reference/test-script#before-and-after-sections) will run the setup function (`loginUserAndSaveStorage` in this example), rather than referencing it as a Playwright project. | ||
* You will need to create the storageState JSON (`storage.json` in this example) file first as an empty object (`{}`), in the same directory where you run the test from. This is because the first time Artillery runs, it will run the `before` hook, and the file referenced in `config` won't be available. | ||
|
||
That's it! | ||
|
||
To run the fully configured example, run: | ||
|
||
```sh | ||
npx artillery run scenario.yml | ||
``` | ||
|
||
*Note: this example runs with headless disabled, so you can easily observe the login being reused.* | ||
|
||
## Running the example in Fargate | ||
|
||
Want to run 1,000 browsers at the same time? 10,000? more? Run your load tests on AWS Fargate with [built-in support in Artillery](https://www.artillery.io/docs/load-testing-at-scale/aws-fargate). Just make sure to tell Artillery to include the `storage.json` file. For example: | ||
|
||
```yaml | ||
config: | ||
... | ||
includeFiles: | ||
- ./storage.json | ||
``` | ||
This ensures the file is bundled to Fargate workers correctly. You will also need to make sure the test is running using headless mode. Then, run the test: | ||
```sh | ||
npx artillery run:fargate scenario.yml --count 2 | ||
``` | ||
|
||
*Note: `before` hooks run once per Fargate worker, so the authentication step will run as many times as the `--count` you set.* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
const { expect } = require('@playwright/test'); | ||
const fs = require('fs'); | ||
|
||
async function loginUserAndSaveStorage(page, context) { | ||
const storageState = JSON.parse(fs.readFileSync('./storage.json', 'utf8')); | ||
if (Object.keys(storageState).length > 0) { | ||
console.log('Already logged in. Skipping login.'); | ||
return; | ||
} | ||
|
||
//1. navigate to page and assert that we are not logged in | ||
await page.goto(context.vars.target); | ||
await expect(page.getByText('Authentication example')).toBeVisible(); | ||
|
||
//2. click login button and make sure we are redirected to `/login` | ||
await page.getByRole('link', { name: 'Login' }).click(); | ||
await page.waitForURL('**/login'); | ||
|
||
//3. fill in your github username and click login button | ||
await page.getByLabel('username').fill(context.vars.githubUsername); | ||
await page.getByRole('button', { name: 'Login' }).click(); | ||
|
||
//4. ensure we are redirected to profile page and logged in | ||
await page.waitForURL('**/profile-sg'); | ||
await expect(page.getByText('Your GitHub profile')).toBeVisible(); | ||
|
||
//5. save iron session cookie to storage.json | ||
await page.context().storageState({ path: './storage.json' }); | ||
} | ||
|
||
async function goToProfilePageAndLogout(page, context, events, test) { | ||
const { step } = test; | ||
const profileHeaderText = 'Profile (Static Generation, recommended)'; | ||
|
||
await step('go_to_page', async () => { | ||
await page.goto(context.vars.target); | ||
await expect(page.getByText(profileHeaderText)).toBeVisible(); | ||
}); | ||
|
||
await step('go_to_profile_page', async () => { | ||
await page.getByRole('link', { name: profileHeaderText }).click(); | ||
await page.waitForURL('**/profile-sg'); | ||
await expect(page.getByText('Your Github Profile')).toBeVisible(); | ||
}); | ||
|
||
await step('logout', async () => { | ||
await page.getByRole('link', { name: 'Logout' }).click(); | ||
await page.waitForURL('**/login'); | ||
}); | ||
} | ||
|
||
module.exports = { | ||
loginUserAndSaveStorage, | ||
goToProfilePageAndLogout | ||
}; |
26 changes: 26 additions & 0 deletions
26
examples/browser-playwright-reuse-authentication/scenario.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
config: | ||
target: https://iron-session-example.vercel.app/ | ||
phases: | ||
- arrivalRate: 1 | ||
duration: 10 | ||
engines: | ||
playwright: | ||
launchOptions: | ||
headless: false | ||
contextOptions: | ||
storageState: './storage.json' | ||
processor: ./flow.js | ||
variables: | ||
githubUsername: "bernardobridge" | ||
# NOTE: add this if you want to run the test in fargate. make sure to remove headless:false too | ||
# includeFiles: | ||
# - ./storage.json | ||
|
||
before: | ||
engine: playwright | ||
flowFunction: loginUserAndSaveStorage | ||
|
||
scenarios: | ||
- name: go_to_profile_page_and_logout | ||
engine: playwright | ||
flowFunction: goToProfilePageAndLogout |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{} |