Skip to content

Commit

Permalink
feat: added browser sizes for playwright
Browse files Browse the repository at this point in the history
feat: browser sizes for PlaywrightWorld can be chosen by tag or with a gherkin step

feat: changed tagsMatch API in QuickPickleWorldInterface to return string[] | null
  • Loading branch information
dnotes committed Oct 21, 2024
1 parent 07920cd commit f350d15
Show file tree
Hide file tree
Showing 15 changed files with 116 additions and 7 deletions.
9 changes: 9 additions & 0 deletions .changeset/funny-items-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"quickpickle": minor
"@quickpickle/playwright": patch
---

- changed tagsMatch API for QuickPickleWorldInterface -- it now returns string[] or null,
which makes it easier for other plugins to get matching tags from a list.

- added browser sizes to PlaywrightWorld; they can be chosen with tags or set via a Gherkin step.
3 changes: 2 additions & 1 deletion packages/main/src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,5 +290,6 @@ export function explodeTags(explodeTags:string[][], testTags:string[]):string[][
* @returns boolean
*/
export function tagsMatch(confTags:string[], testTags:string[]) {
return intersection(confTags.map(t => t.toLowerCase()), testTags.map(t => t.toLowerCase()))?.length ? true : false
let tags = intersection(confTags.map(t => t.toLowerCase()), testTags.map(t => t.toLowerCase()))
return tags?.length ? tags : null
}
4 changes: 2 additions & 2 deletions packages/main/src/world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface QuickPickleWorldInterface {
[key: string]: any
}
init: () => Promise<void>
tagsMatch(tags: string[]): boolean
tagsMatch(tags: string[]): string[]|null
}

export class QuickPickleWorld implements QuickPickleWorldInterface {
Expand All @@ -30,7 +30,7 @@ export class QuickPickleWorld implements QuickPickleWorldInterface {
if (info) this.info = {...info}
}
async init() {}
tagsMatch(tags: string[]): boolean {
tagsMatch(tags: string[]) {
return tagsMatch(tags, this.info.tags)
}
}
Expand Down
7 changes: 7 additions & 0 deletions packages/playwright/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export default {
explodeTags: [
['nojs','js'],
['chromium','firefox','webkit'],
['mobile','tablet','desktop','widescreen'],
],

// PlaywrightWorld configuration
Expand All @@ -140,6 +141,7 @@ export default {
explodeTags: [
['nojs','js'],
['chromium','firefox','webkit'],
['mobile','tablet','desktop','widescreen'],
],

// PlaywrightWorld configuration
Expand All @@ -165,6 +167,11 @@ export type PlaywrightWorldConfigSetting = Partial<{
headless: boolean // whether to run the browser in headless mode (default true)
slowMo: boolean|number // whether to run the browser with slow motion enabled (default false)
slowMoMs: number // the number of milliseconds to slow down the browser by (default 500)
keyboardDelay: number // the number of milliseconds between key presses (default:20)
defaultBrowser: 'chromium'|'firefox'|'webkit' // the default browser to use (default: chromium)
browserSizes: Record<string,string> // the default browser sizes to use, in the form "widthxheight"
// (default: { mobile: "480x640", tablet: "1024x768", desktop: "1920x1080", widescreen: "3440x1440" })
defaultBrowserSize: string // the default browser size to use (default: desktop)
}>
```

Expand Down
Binary file modified packages/playwright/screenshots/playwright-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 52 additions & 4 deletions packages/playwright/src/PlaywrightWorld.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ export type PlaywrightWorldConfigSetting = Partial<{
headless: boolean // whether to run the browser in headless mode (default true)
slowMo: boolean|number // whether to run the browser with slow motion enabled (default false)
slowMoMs: number // the number of milliseconds to slow down the browser by (default 500)
keyboardDelay: number // the number of milliseconds between key presses
defaultBrowser: 'chromium'|'firefox'|'webkit' // the default browser to use
keyboardDelay: number // the number of milliseconds between key presses (default:20)
defaultBrowser: 'chromium'|'firefox'|'webkit' // the default browser to use (default: chromium)
browserSizes: Record<string,string> // the default browser sizes to use, in the form "widthxheight"
// (default: { mobile: "480x640", tablet: "1024x768", desktop: "1920x1080", widescreen: "3440x1440" })
defaultBrowserSize: string // the default browser size to use (default: desktop)
}>

export const defaultPlaywrightWorldConfig = {
Expand All @@ -30,10 +33,20 @@ export const defaultPlaywrightWorldConfig = {
slowMo: false,
slowMoMs: 500,
keyboardDelay: 20,
defaultBrowser: 'chromium'
defaultBrowser: 'chromium',
browserSizes: {
mobile: '480x640',
tablet: '1024x768',
desktop: '1920x1080',
widescreen: '3440x1440',
},
defaultBrowserSize: 'desktop',
}

export type PlaywrightWorldConfig = typeof defaultPlaywrightWorldConfig & { port?:number }
export type PlaywrightWorldConfig = typeof defaultPlaywrightWorldConfig & {
port?:number,
browserSizes: Record<string,string>
}

export class PlaywrightWorld extends QuickPickleWorld {
browser!: Browser
Expand All @@ -53,6 +66,7 @@ export class PlaywrightWorld extends QuickPickleWorld {
javaScriptEnabled: this.tagsMatch(this.playwrightConfig.nojsTags) ? false : true,
})
this.page = await this.browserContext.newPage()
await this.setViewportSize()
}

get browserName() {
Expand All @@ -61,6 +75,19 @@ export class PlaywrightWorld extends QuickPickleWorld {
))?.replace(/^@/, '') as 'chromium'|'firefox'|'webkit' ?? this.playwrightConfig.defaultBrowser ?? 'chromium'
}

get browserSize() {
let tag = this.tagsMatch(this.browserSizeTags)?.[0]?.replace(/^@/, '')
let sizeStr = (tag
? this.playwrightConfig.browserSizes[tag.replace(/^@/,'')]
: this.playwrightConfig.browserSizes[this.playwrightConfig.defaultBrowserSize]
) ?? '1920x1080'
return getDimensions(sizeStr)
}

get browserSizeTags() {
return Object.keys(this.playwrightConfig.browserSizes).map(k => `@${k}`)
}

setConfig(worldConfig:PlaywrightWorldConfigSetting) {
let newConfig = defaultsDeep(worldConfig || {}, defaultPlaywrightWorldConfig )
newConfig.nojsTags = normalizeTags(newConfig.nojsTags)
Expand All @@ -74,6 +101,22 @@ export class PlaywrightWorld extends QuickPickleWorld {
this.playwrightConfig = newConfig
}

async setViewportSize(size?:string) {
if (size) {
size = size.replace(/^['"]/, '').replace(/['"]$/, '')
if (this.playwrightConfig.browserSizes[size]) {
await this.page.setViewportSize(getDimensions(this.playwrightConfig.browserSizes[size]))
}
else if (size.match(/^\d+x\d+$/)) {
await this.page.setViewportSize(getDimensions(size))
}
else throw new Error(`Invalid browser size: ${size}
(found: ${this.playwrightConfig.browserSizes[size]})
(available: ${Object.keys(this.playwrightConfig.browserSizes).join(', ')})`)
}
else await this.page.setViewportSize(this.browserSize)
}

async startBrowser() {
this.browser = await browsers[this.browserName].launch({
headless: this.tagsMatch(this.playwrightConfig.showBrowserTags) ? false : this.playwrightConfig.headless,
Expand Down Expand Up @@ -105,6 +148,11 @@ export class PlaywrightWorld extends QuickPickleWorld {
}
}

function getDimensions(size:string) {
let [width,height] = size.split('x').map(Number)
return {width,height}
}

After(async (world:PlaywrightWorld) => {
await world.browserContext.close()
})
9 changes: 9 additions & 0 deletions packages/playwright/src/actions.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,12 @@ Then('(I )take (a )screenshot named {string}', async function (world:PlaywrightW
let path = sanitizeFilepath(`${projectRoot}/${world.playwrightConfig.screenshotDir}/${name}.png`)
await world.page.screenshot({ path })
})

// ================
// Browser size
Given('the browser size is (set to ){word}', async function (world:PlaywrightWorld, browserSizeTag:string) {
await world.setViewportSize(browserSizeTag)
})
Given('the browser size is (set to ){int} x {int}', async function (world:PlaywrightWorld, width:number, height:number) {
await world.page.setViewportSize({ width, height })
})
30 changes: 30 additions & 0 deletions packages/playwright/tests/playwright-actions-html.feature
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,33 @@ Feature: Actions step definitions on a static page
Scenario: Taking a named screenshot
Then I take a screenshot named "pickles"
And the file "screenshots/pickles.png" should exist (delete it)

Rule: Different browser sizes must be supported

Background: load the simple file
When I load the file "tests/examples/simple.html"

@mobile
Scenario: viewport size mobile
Then the screenshot "viewport-size-mobile" should match

@tablet
Scenario: viewport size tablet
When the browser size is "tablet"
Then the screenshot "viewport-size-tablet" should match

@desktop
Scenario: viewport size desktop
Then the screenshot "viewport-size-desktop" should match

Scenario: viewport size widescreen
When the browser size is widescreen
Then the screenshot "viewport-size-widescreen" should match

Scenario: viewport size custom 200x800
When the browser size is 200 x 800
Then the screenshot "viewport-size-200x800" should match

Scenario: viewport size custom 500x800
When the browser size is 500x800
Then the screenshot "viewport-size-500x800" should match
5 changes: 5 additions & 0 deletions packages/playwright/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ export default defineConfig({
plugins: [
// @ts-ignore
quickpickle({
explodeTags: [
['nojs','js'],
['chromium','firefox','webkit'],
['mobile','tablet','desktop','widescreen'],
],
worldConfig: {
slowMoMs: 500,
}
Expand Down

0 comments on commit f350d15

Please sign in to comment.