Skip to content

Commit

Permalink
feat: added playwright/client to exposes browser context methods to t…
Browse files Browse the repository at this point in the history
…he tests

closes #540
  • Loading branch information
hugomrdias committed Oct 17, 2023
1 parent b3710e1 commit 7111801
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 3 deletions.
27 changes: 27 additions & 0 deletions client/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const config = /** @type { import('../src/types.js').RunnerOptions} */ (
/** @type { unknown } */ (process.env.PW_TEST)
)

export const mode = config.mode

export const options = config

export const context = {
/** @type {import('playwright-core').BrowserContext['setOffline']} */
setOffline(offline) {
if ('pwContextSetOffline' in globalThis === false) {
return Promise.resolve()
}
return globalThis.pwContextSetOffline(offline)
},

/** @type {import('playwright-core').BrowserContext['grantPermissions']} */
grantPermissions(permissions, options) {
return globalThis.pwContextGrantPermissions(permissions, options)
},

/** @type {import('playwright-core').BrowserContext['setGeolocation']} */
setGeolocation(geolocation) {
return globalThis.pwContextSetGeolocation(geolocation)
},
}
60 changes: 60 additions & 0 deletions client/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
declare global {
function pwContextSetOffline(offline: boolean): Promise<void>
/**
* Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if
* specified.
*
* @param permissions A permission or an array of permissions to grant. Permissions can be one of the following values:
* - `'geolocation'`
* - `'midi'`
* - `'midi-sysex'` (system-exclusive midi)
* - `'notifications'`
* - `'camera'`
* - `'microphone'`
* - `'background-sync'`
* - `'ambient-light-sensor'`
* - `'accelerometer'`
* - `'gyroscope'`
* - `'magnetometer'`
* - `'accessibility-events'`
* - `'clipboard-read'`
* - `'clipboard-write'`
* - `'payment-handler'`
* @param options
* @param options.origin
*/
function pwContextGrantPermissions(
permissions: string[],
options?: {
/**
* The [origin] to grant permissions to, e.g. "https://example.com".
*/
origin?: string
}
): Promise<void>

/**
*
* @param geolocation
*/
function pwContextSetGeolocation(
geolocation: null | {
/**
* Latitude between -90 and 90.
*/
latitude: number

/**
* Longitude between -180 and 180.
*/
longitude: number

/**
* Non-negative accuracy value. Defaults to `0`.
*/
accuracy?: number
}
): Promise<void>
}

export {}
16 changes: 16 additions & 0 deletions mocks/test.mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const { is, ok, equal } = require('uvu/assert')
const debug = require('debug')('app')
const { good, bad } = require('./lib')
const Client = require('../client')

describe('Array', () => {
describe('#indexOf()', () => {
Expand Down Expand Up @@ -34,5 +35,20 @@ describe('Array', () => {
it('should has import.meta.env', async () => {
equal(import.meta.env, process.env)
})

it('should setoffline', async () => {
if (Client.mode === 'main' && Client.options.extension === false) {
globalThis.addEventListener('offline', () => {
console.log('offlineee')
})
// try {
// fetch('https://example.comeeee')
// } catch (error) {}
await Client.context.setOffline(true)
equal(navigator.onLine, false)
await Client.context.setOffline(false)
equal(navigator.onLine, true)
}
})
})
})
20 changes: 20 additions & 0 deletions mocks/test.mocha.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable no-undef */
// eslint-disable-next-line strict
import { is, ok, equal } from 'uvu/assert'
import * as Client from '../client'
import pdefer from 'p-defer'

it.skip('Array', () => {
describe('#indexOf()', () => {
Expand All @@ -13,3 +15,21 @@ it.skip('Array', () => {
})
})
})

it('should geolocation', async () => {
if (Client.mode === 'main') {
const deferred = pdefer()
await Client.context.setGeolocation({
latitude: 59.95,
longitude: 30.31667,
})
await Client.context.grantPermissions(['geolocation'])

navigator.geolocation.getCurrentPosition((position) => {
deferred.resolve(position)
})

const position = (await deferred.promise) as GeolocationPosition
equal(position.coords.latitude, 59.95)
}
})
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"./taps": {
"types": "./dist/src/taps/index.d.ts",
"default": "./src/taps/index.js"
},
"./client": {
"types": "./dist/client/index.d.ts",
"default": "./dist/client/index.js"
}
},
"main": "src/runner.js",
Expand All @@ -39,6 +43,9 @@
"*": {
"taps": [
"dist/src/taps/index.d.ts"
],
"client": [
"dist/client/index.d.ts"
]
}
},
Expand Down Expand Up @@ -76,6 +83,7 @@
"esbuild-plugin-wasm": "^1.1.0",
"events": "^3.3.0",
"execa": "^8.0.1",
"exit-hook": "^4.0.0",
"globby": "^13.2.2",
"kleur": "^4.1.5",
"lilconfig": "^2.1.0",
Expand Down Expand Up @@ -109,6 +117,7 @@
"hd-scripts": "^9.0.5",
"lint-staged": "^14.0.1",
"mocha": "^10.2.0",
"p-defer": "^4.0.0",
"simple-git-hooks": "^2.9.0",
"tape": "^5.6.6",
"tinybench": "^2.5.1",
Expand Down
16 changes: 16 additions & 0 deletions pnpm-lock.yaml

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

38 changes: 38 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,44 @@ Description
$ playwright-test test/** BAD
```
## Client
This client package exposes the `playwright-test` options and some Playwright browser context methods to be used in tests.
```ts
import * as Client from 'playwright-test/client'

it('should setoffline', async () => {
if (Client.mode === 'main' && Client.options.extension === false) {
globalThis.addEventListener('offline', () => {
console.log('offlineee')
})
await Client.context.setOffline(true)
equal(navigator.onLine, false)
await Client.context.setOffline(false)
equal(navigator.onLine, true)
}
})

it('should geolocation', async () => {
if (Client.mode === 'main') {
const deferred = pdefer()
await Client.context.setGeolocation({
latitude: 59.95,
longitude: 30.316_67,
})
await Client.context.grantPermissions(['geolocation'])

navigator.geolocation.getCurrentPosition((position) => {
deferred.resolve(position)
})
const position = (await deferred.promise) as GeolocationPosition
equal(position.coords.latitude, 59.95)
}
})
```
## Flow control
All test runners support automatic flow control, which means you don't need to call special function or trigger any event in your tests to stop the run. The `none` runner does not support flow control.
Expand Down
21 changes: 20 additions & 1 deletion src/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,25 @@ export class Runner {
}
)

await this.context.exposeFunction(
'pwContextGrantPermissions',
async (
/** @type {string[]} */ permissions,
/** @type {{ origin?: string | undefined; } | undefined} */ options
) => {
await this.context?.grantPermissions(permissions, options)
}
)

await this.context.exposeFunction(
'pwContextSetGeolocation',
async (
/** @type {{ latitude: number; longitude: number; accuracy?: number | undefined; } | null} */ geolocation
) => {
await this.context?.setGeolocation(geolocation)
}
)

await this.context.exposeFunction(
'PW_TEST_STDOUT_WRITE',
(/** @type {string | Uint8Array} */ msg) =>
Expand Down Expand Up @@ -412,7 +431,7 @@ export class Runner {
// Run after tests hook
await this.options.afterTests(this.options, this.beforeTestsOutput)

premove(this.dir)
await premove(this.dir)

const serverClose = new Promise((resolve, reject) => {
if (this.server) {
Expand Down
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
},
"include": [
"src",
"src/utils",
"test.js",
"cli.js",
"package.json",
"mocks/tops"
"mocks/tops",
"client"
]
}

0 comments on commit 7111801

Please sign in to comment.