Skip to content

Commit 0d8c653

Browse files
committed
feat(playwright): solidify identities, major release
1 parent e4300cf commit 0d8c653

File tree

6 files changed

+88
-40
lines changed

6 files changed

+88
-40
lines changed

.changeset/chatty-books-glow.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
"@quickpickle/playwright": major
2+
"@quickpickle/playwright": minor
33
---
44

55
Added multiple browser identities for playwright.

.changeset/red-dancers-switch.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
"@quickpickle/playwright": major
3+
---
4+
5+
## 1.0 release
6+
7+
From this point forward, the step definitions in "actions" and "outcomes"
8+
should be stable, and any changes to the step names will result in a new
9+
minor version release.
10+
11+
I was hoping to have some system for using only *some* of the step definitions
12+
provided by the module, or for overriding or deleting them, but I think that
13+
will have to wait for the next major release.
14+
15+
### Identities
16+
17+
The last thing added for this release is the functionality for multiple browsers
18+
or "identities". Switching identity starts a new browser context, with completely
19+
new local data, making it possible to test interactions between different users.
20+
21+
Each test will start with a "default" identity, and new browser contexts open
22+
on the same url as the "default" identity.
23+
24+
Note that no actual *user* is created as a result of switching identity; if you
25+
need more setup, you can create a custom world constructor extending the
26+
PlaywrightWorld class and override the "setIdentity" method.
27+
28+
The following new step definitions all simply call "world.setIdentity()", which
29+
creates a new browser context if necessary and switches to it:
30+
31+
- `(as )a/an/the (user ){string}`
32+
- `(as )a/an/the {string} user/role/browser/identity`
33+
- `I am {string}`
34+
- `I am a/an/the (user ){string}`
35+
- `I am a/an/the {string} user/role/browser/identity`
36+
- `as {string}`
37+
38+
### New step definitions
39+
40+
`I am on the home/front page` opens the base url.

packages/playwright/src/PlaywrightWorld.ts

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export class PlaywrightWorld extends VisualWorld implements VisualWorldInterface
6666
browser!: Browser
6767

6868
identities: Map<string, BrowserMap> = new Map()
69-
private _identity:string = 'default'
69+
_identity:string = 'default'
7070

7171
constructor(context:TestContext, info:InfoConstructor) {
7272
super(context, info)
@@ -79,19 +79,6 @@ export class PlaywrightWorld extends VisualWorld implements VisualWorldInterface
7979
await this.newIdentity('default')
8080
await this.setViewportSize()
8181
}
82-
83-
async newIdentity(name:string) {
84-
let context = await this.browser.newContext({
85-
serviceWorkers: 'block',
86-
javaScriptEnabled: this.tagsMatch(this.worldConfig.nojsTags) ? false : true,
87-
})
88-
let page = await context.newPage()
89-
this.identities.set(name, {
90-
context,
91-
page
92-
})
93-
}
94-
9582
get browserContext() {
9683
return this.identities.get(this.identity)!.context
9784
}
@@ -103,7 +90,26 @@ export class PlaywrightWorld extends VisualWorld implements VisualWorldInterface
10390
}
10491
set identity(name:string) {
10592
if (this.identities.has(name)) this._identity = name
106-
else throw new Error(`There is no browser for "${name}"; please call \`await world.newIdentity('${name}')\` first.`)
93+
else throw new Error(`There is no browser for "${name}"; please call \`await world.setIdentity('${name}')\` instead.`)
94+
}
95+
async newIdentity(name:string) {
96+
let context = await this.browser.newContext({
97+
serviceWorkers: 'block',
98+
javaScriptEnabled: this.tagsMatch(this.worldConfig.nojsTags) ? false : true,
99+
})
100+
let page = await context.newPage()
101+
if (name !== 'default') {
102+
let url = this.identities.get('default')!.page.url()
103+
await page.goto(url, { timeout: this.worldConfig.stepTimeout })
104+
}
105+
this.identities.set(name, {
106+
context,
107+
page
108+
})
109+
}
110+
async setIdentity(name:string) {
111+
if (!this.identities.has(name)) await this.newIdentity(name)
112+
this._identity = name
107113
}
108114

109115
get browserName() {

packages/playwright/src/actions.steps.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { expect } from '@playwright/test'
55
// ================
66
// Navigation
77

8+
Given('I am on the home/front page', async function (world:PlaywrightWorld) {
9+
await world.page.goto(world.baseUrl.toString(), { timeout:world.worldConfig.stepTimeout })
10+
})
811
Given('I am on {string}', async function (world:PlaywrightWorld, path) {
912
let url = new URL(path, world.baseUrl)
1013
await world.page.goto(url.href, { timeout:world.worldConfig.stepTimeout })
@@ -30,26 +33,25 @@ When('I go back/forward/forwards', async function (world:PlaywrightWorld) {
3033
})
3134

3235
// ================
33-
// Interaction
36+
// Identities
3437

35-
Given('a/an/the {string}( user)( role)( browser)( identity)', async function (world:PlaywrightWorld, identity) {
36-
await world.newIdentity(identity)
38+
Given('(as )a/an/the (user ){string}', async function (world:PlaywrightWorld, identity) {
39+
await world.setIdentity(identity)
3740
})
38-
Given('I am (logged in as ){string}', async function (world:PlaywrightWorld, identity) {
39-
if (!world.identities.has(identity)) await world.newIdentity(identity)
40-
world.identity = identity
41+
Given('(as )a/an/the {string} user/role/browser/identity', async function (world:PlaywrightWorld, identity) {
42+
await world.setIdentity(identity)
4143
})
42-
Given('I am (logged in as )a/an/the {string}( user)( role)( browser)( identity)', async function (world:PlaywrightWorld, identity) {
43-
if (!world.identities.has(identity)) await world.newIdentity(identity)
44-
world.identity = identity
44+
Given('I am {string}', async function (world:PlaywrightWorld, identity) {
45+
await world.setIdentity(identity)
4546
})
46-
Then('as {string}', async function (world:PlaywrightWorld, identity) {
47-
if (!world.identities.has(identity)) await world.newIdentity(identity)
48-
world.identity = identity
47+
Given('I am a/an/the (user ){string}', async function (world:PlaywrightWorld, identity) {
48+
await world.setIdentity(identity)
4949
})
50-
Then('as a/an/the {string}( user)( role)( browser)( identity)', async function (world:PlaywrightWorld, identity) {
51-
if (!world.identities.has(identity)) await world.newIdentity(identity)
52-
world.identity = identity
50+
Given('I am a/an/the {string} user/role/browser/identity', async function (world:PlaywrightWorld, identity) {
51+
await world.setIdentity(identity)
52+
})
53+
Then('as {string}', async function (world:PlaywrightWorld, identity) {
54+
await world.setIdentity(identity)
5355
})
5456

5557
// ================
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
@webserver
12
Feature: Multiple browsers with identities
23

34
As a developer
@@ -6,18 +7,17 @@ Feature: Multiple browsers with identities
67

78
@soft
89
Scenario: IndexedDB steps fail properly
9-
Given I am on "http://example.com"
10+
Given I am on the front page
1011
And a db record for "test" with value "does it work?"
1112
Then the db record for "test" should be "well does it?"
1213
Then error 1 should contain '"value": "does it work?"'
1314
And clear 1 error
1415

1516
Scenario: IndexedDB is separate for each identity
16-
Given I am "user1"
17-
And I am on "http://example.com"
18-
And a db record for "test" with value "user1"
19-
When I am "user2"
20-
And I am on "http://example.com"
21-
Given a db record for "test" with value "user2"
22-
When I am "user1"
17+
Given I am on the front page
18+
Given I am a user "user1"
19+
And there is a db record for "test" with value "user1"
20+
Given a user "user2"
21+
And a db record for "test" with value "user2"
22+
Then as "user1"
2323
Then the db record for "test" should be "user1"

packages/playwright/tests/playwright.steps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ Given('the following world config:', async (world:PlaywrightWorld, rawConf:DocSt
8989
})
9090

9191
// IndexedDB
92-
Given('a(n) (indexed)db record for {string} with value {string}', async (world:PlaywrightWorld, key:string, value:string) => {
92+
Given('(there is )a(n) (indexed)db record for {string} with value {string}', async (world:PlaywrightWorld, key:string, value:string) => {
9393
await world.page.evaluate(async ([key, value]) => {
9494
return new Promise<void>((resolve, reject) => {
9595
const request = indexedDB.open('testing', 1);

0 commit comments

Comments
 (0)