Skip to content
This repository was archived by the owner on Sep 11, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ Running your tests using [Jest](https://github.com/facebook/jest) & [Playwright]
npm install jest-playwright-preset playwright
```

Also you can use `jest-playwright-preset` with specific playwright packages:
`playwright-webkit`, `playwright-chromium` and `playwright-firefox`

```
npm install jest-playwright-preset playwright-firefox
```

## Usage

Update your Jest configuration:
Expand Down Expand Up @@ -47,6 +54,7 @@ You can specify a `jest-playwright.config.js` at the root of the project or defi
## Browser type

You can specify browser in multiple ways:
**Note**: You should do it only if you are using whole playwright package

- With `BROWSER` environment variable
- With your `jest-playwright.config.js`
Expand All @@ -56,7 +64,7 @@ If you don't pass any value it will be use `chromium` as default
Use Playwright in your tests:

```json
"test": "BROWSER=chromium jest"
"test": "jest"
```

```js
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"format": "prettier --write \"*.{js,md}\" \"src/*.js\"",
"lint": "eslint .",
"prepublishOnly": "yarn run build",
"test": "jest"
"test:utils": "jest src/utils.test.js",
"test": "npm run test:utils && jest tests"
},
"husky": {
"hooks": {
Expand All @@ -38,8 +39,13 @@
"*.js": "eslint --fix"
},
"peerDependencies": {
"jest-environment-node": "^25.1.0",
"playwright": "*"
"jest-environment-node": "^25.1.0"
},
"optionalDependencies": {
"playwright": "*",
"playwright-chromium": "*",
"playwright-firefox": "*",
"playwright-webkit": "*"
},
"devDependencies": {
"@babel/cli": "^7.8.4",
Expand Down
22 changes: 14 additions & 8 deletions src/PlaywrightEnvironment.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import NodeEnvironment from 'jest-environment-node'
import playwright from 'playwright'
import { checkBrowserEnv, getBrowserType, readConfig } from './utils'
import {
checkBrowserEnv,
getBrowserType,
getPlaywrightInstance,
readConfig,
} from './utils'

const handleError = error => {
process.emit('uncaughtException', error)
Expand Down Expand Up @@ -32,13 +36,12 @@ function startBrowserCloseWatchdog() {
}, 50)
}

async function getBrowserPerProcess() {
async function getBrowserPerProcess(playwrightInstance, config) {
if (!browserPerProcess) {
const config = await readConfig()
const browserType = getBrowserType(config)
checkBrowserEnv(browserType)
const { launchBrowserApp } = config
browserPerProcess = await playwright[browserType].launch(launchBrowserApp)
browserPerProcess = await playwrightInstance.launch(launchBrowserApp)
}
return browserPerProcess
}
Expand All @@ -58,21 +61,24 @@ class PlaywrightEnvironment extends NodeEnvironment {
async setup() {
resetBrowserCloseWatchdog()
const config = await readConfig()
const browserType = getBrowserType(config)
checkBrowserEnv(browserType)
const { device, context } = config
const playwrightInstance = await getPlaywrightInstance(browserType)
let contextOptions = context

const availableDevices = Object.keys(playwright.devices)
const availableDevices = Object.keys(playwrightInstance.devices)
if (device) {
if (!availableDevices.includes(device)) {
throw new Error(
`Wrong device. Should be one of [${availableDevices}], but got ${device}`,
)
} else {
const { viewport, userAgent } = playwright.devices[device]
const { viewport, userAgent } = playwrightInstance.devices[device]
contextOptions = { ...contextOptions, viewport, userAgent }
}
}
this.global.browser = await getBrowserPerProcess()
this.global.browser = await getBrowserPerProcess(playwrightInstance, config)
this.global.context = await this.global.browser.newContext(contextOptions)
this.global.page = await this.global.context.newPage()
this.global.page.on('pageerror', handleError)
Expand Down
33 changes: 33 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ import { CHROMIUM, FIREFOX, WEBKIT, DEFAULT_CONFIG } from './constants'

const exists = promisify(fs.exists)

const checkDependencies = dependencies => {
if (!dependencies) return null
if (dependencies.playwright) return 'playwright'
if (dependencies[`playwright-${CHROMIUM}`]) return `playwright-${CHROMIUM}`
if (dependencies[`playwright-${FIREFOX}`]) return `playwright-${FIREFOX}`
if (dependencies[`playwright-${WEBKIT}`]) return `playwright-${WEBKIT}`
return null
}

export function checkBrowserEnv(param) {
if (param !== CHROMIUM && param !== FIREFOX && param !== WEBKIT) {
throw new Error(
Expand All @@ -21,6 +30,30 @@ export function getBrowserType(config) {
return config.browser || CHROMIUM
}

export async function readPackage() {
const packagePath = 'package.json'
const absConfigPath = path.resolve(process.cwd(), packagePath)
// eslint-disable-next-line global-require,import/no-dynamic-require
const packageConfig = await require(absConfigPath)
const playwright =
checkDependencies(packageConfig.dependencies) ||
checkDependencies(packageConfig.devDependencies)
if (!playwright) {
throw new Error('None of playwright packages was not found in dependencies')
}
return playwright
}

export async function getPlaywrightInstance(browserType) {
const playwrightPackage = await readPackage()
if (playwrightPackage === 'playwright') {
// eslint-disable-next-line global-require, import/no-dynamic-require
return require(playwrightPackage)[browserType]
}
// eslint-disable-next-line global-require, import/no-dynamic-require
return require(playwrightPackage)
}

export async function readConfig() {
const defaultConfig = DEFAULT_CONFIG

Expand Down
70 changes: 70 additions & 0 deletions src/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { checkBrowserEnv, readPackage } from './utils'

const fs = require('fs')
const path = require('path')
const { readConfig, getBrowserType } = require('./utils')
Expand Down Expand Up @@ -80,3 +82,71 @@ describe('getBrowserType', () => {
expect(browserType).toBe(CHROMIUM)
})
})

describe('checkBrowserEnv', () => {
it('should throw Error with unknown type', async () => {
fs.exists.mockImplementationOnce((_, cb) => cb(true))
jest.mock(
path.join(__dirname, '..', 'jest-playwright.config.js'),
() => ({
browser: 'unknown',
}),
{ virtual: true },
)
const config = await readConfig()
const browserType = getBrowserType(config)
expect(() => checkBrowserEnv(browserType)).toThrow()
})
})

describe('readPackage', () => {
it('should return null when dependencies does not passed', async () => {
fs.exists.mockImplementationOnce((_, cb) => cb(true))
jest.mock(
path.join(__dirname, '..', 'package.json'),
() => ({
dependencies: {},
}),
{ virtual: true },
)
let error
try {
await readPackage()
} catch (e) {
error = e
}
expect(error).toEqual(
new Error('None of playwright packages was not found in dependencies'),
)
})
it('should return playwright when it is defined', async () => {
fs.exists.mockImplementationOnce((_, cb) => cb(true))
jest.mock(
path.join(__dirname, '..', 'package.json'),
() => ({
dependencies: {
playwright: '*',
},
}),
{ virtual: true },
)

const playwright = await readPackage()
expect(playwright).toEqual('playwright')
})
it('should return playwright-firefox when it is defined', async () => {
fs.exists.mockImplementationOnce((_, cb) => cb(true))
jest.mock(
path.join(__dirname, '..', 'package.json'),
() => ({
devDependencies: {
'playwright-firefox': '*',
},
}),
{ virtual: true },
)

const playwright = await readPackage()
expect(playwright).toEqual('playwright-firefox')
})
})