-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(browser): add commands to communicate betweens server and the br…
…owser
- Loading branch information
1 parent
1fa90d1
commit 015216e
Showing
12 changed files
with
239 additions
and
28 deletions.
There are no files selected for viewing
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,18 @@ | ||
declare module '$commands' { | ||
interface FsOptions { | ||
encoding?: BufferEncoding | ||
flag?: string | number | ||
} | ||
|
||
interface TypePayload { type: string } | ||
interface PressPayload { press: string } | ||
interface DownPayload { down: string } | ||
interface UpPayload { up: string } | ||
|
||
type SendKeysPayload = TypePayload | PressPayload | DownPayload | UpPayload | ||
|
||
export const readFile: (path: string, options?: BufferEncoding | FsOptions) => Promise<string | null> | ||
export const writeFile: (path: string, data: string, options?: BufferEncoding | FsOptions & { mode?: number | string }) => Promise<void> | ||
export const removeFile: (path: string) => Promise<void> | ||
export const sendKeys: (keys: SendKeysPayload) => Promise<void> | ||
} |
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,34 @@ | ||
import fs, { promises as fsp } from 'node:fs' | ||
import { dirname, resolve } from 'node:path' | ||
import { isFileServingAllowed } from 'vite' | ||
import type { WorkspaceProject } from 'vitest/node' | ||
import type { BrowserCommand } from '../types' | ||
|
||
export interface FsOptions { | ||
encoding?: BufferEncoding | ||
flag?: string | number | ||
} | ||
|
||
function assertFileAccess(path: string, project: WorkspaceProject) { | ||
const resolvedPath = resolve(path) | ||
if (!isFileServingAllowed(resolvedPath, project.server) && !isFileServingAllowed(resolvedPath, project.ctx.server)) | ||
throw new Error(`Access denied to "${resolvedPath}". See Vite config documentation for "server.fs": https://vitejs.dev/config/server-options.html#server-fs-strict.`) | ||
} | ||
|
||
export const readFile: BrowserCommand<[string, BufferEncoding | FsOptions]> = async ([path, options], { project }) => { | ||
assertFileAccess(path, project) | ||
return fsp.readFile(path, options).catch(() => null) | ||
} | ||
|
||
export const writeFile: BrowserCommand<[string, string, BufferEncoding | FsOptions & { mode?: number | string }]> = async ([path, data, options], { project }) => { | ||
assertFileAccess(path, project) | ||
const dir = dirname(path) | ||
if (!fs.existsSync(dir)) | ||
await fsp.mkdir(dir, { recursive: true }) | ||
await fsp.writeFile(path, data, options).catch(() => null) | ||
} | ||
|
||
export const removeFile: BrowserCommand<[string]> = async ([path], { project }) => { | ||
assertFileAccess(path, project) | ||
await fsp.rm(path).catch(() => null) | ||
} |
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,13 @@ | ||
import { | ||
readFile, | ||
removeFile, | ||
writeFile, | ||
} from './fs' | ||
import { sendKeys } from './keyboard' | ||
|
||
export default { | ||
readFile, | ||
removeFile, | ||
writeFile, | ||
sendKeys, | ||
} |
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,92 @@ | ||
// based on https://github.com/modernweb-dev/web/blob/f7fcf29cb79e82ad5622665d76da3f6b23d0ef43/packages/test-runner-commands/src/sendKeysPlugin.ts | ||
|
||
import type { Page } from 'playwright' | ||
import type { BrowserCommand } from '../types' | ||
|
||
// TODO: remove repetition from commands.d.ts | ||
interface TypePayload { type: string } | ||
interface PressPayload { press: string } | ||
interface DownPayload { down: string } | ||
interface UpPayload { up: string } | ||
|
||
export type SendKeysPayload = TypePayload | PressPayload | DownPayload | UpPayload | ||
|
||
function isObject(payload: unknown): payload is Record<string, unknown> { | ||
return payload != null && typeof payload === 'object' | ||
} | ||
|
||
function isSendKeysPayload(payload: unknown): boolean { | ||
const validOptions = ['type', 'press', 'down', 'up'] | ||
|
||
if (!isObject(payload)) | ||
throw new Error('You must provide a `SendKeysPayload` object') | ||
|
||
const numberOfValidOptions = Object.keys(payload).filter(key => | ||
validOptions.includes(key), | ||
).length | ||
const unknownOptions = Object.keys(payload).filter(key => !validOptions.includes(key)) | ||
|
||
if (numberOfValidOptions > 1) { | ||
throw new Error( | ||
`You must provide ONLY one of the following properties to pass to the browser runner: ${validOptions.join( | ||
', ', | ||
)}.`, | ||
) | ||
} | ||
if (numberOfValidOptions === 0) { | ||
throw new Error( | ||
`You must provide one of the following properties to pass to the browser runner: ${validOptions.join( | ||
', ', | ||
)}.`, | ||
) | ||
} | ||
if (unknownOptions.length > 0) | ||
throw new Error(`Unknown options \`${unknownOptions.join(', ')}\` present.`) | ||
|
||
return true | ||
} | ||
|
||
function isTypePayload(payload: SendKeysPayload): payload is TypePayload { | ||
return 'type' in payload | ||
} | ||
|
||
function isPressPayload(payload: SendKeysPayload): payload is PressPayload { | ||
return 'press' in payload | ||
} | ||
|
||
function isDownPayload(payload: SendKeysPayload): payload is DownPayload { | ||
return 'down' in payload | ||
} | ||
|
||
function isUpPayload(payload: SendKeysPayload): payload is UpPayload { | ||
return 'up' in payload | ||
} | ||
|
||
export const sendKeys: BrowserCommand<[SendKeysPayload]> = async ([payload], { provider }) => { | ||
if (!isSendKeysPayload(payload) || !payload) | ||
throw new Error('You must provide a `SendKeysPayload` object') | ||
|
||
if (provider.name === 'playwright') { | ||
const page = ((provider as any).page as Page) | ||
if (isTypePayload(payload)) | ||
await page.keyboard.type(payload.type) | ||
else if (isPressPayload(payload)) | ||
await page.keyboard.press(payload.press) | ||
else if (isDownPayload(payload)) | ||
await page.keyboard.down(payload.down) | ||
else if (isUpPayload(payload)) | ||
await page.keyboard.up(payload.up) | ||
} | ||
else if (provider.name === 'webdriverio') { | ||
const browser = (provider as any).browser as WebdriverIO.Browser | ||
if (isTypePayload(payload)) | ||
await browser.keys(payload.type.split('')) | ||
else if (isPressPayload(payload)) | ||
await browser.keys([payload.press]) | ||
else | ||
throw new Error('Only "press" and "type" are supported by webdriverio.') | ||
} | ||
else { | ||
throw new Error(`"sendKeys" is not supported for ${provider.name} browser provider.`) | ||
} | ||
} |
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
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
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
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,5 @@ | ||
import type { BrowserProvider, WorkspaceProject } from 'vitest/node' | ||
|
||
export interface BrowserCommand<T extends any[]> { | ||
(payload: T, options: { provider: BrowserProvider; project: WorkspaceProject }): void | ||
} |
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
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
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
Oops, something went wrong.