Skip to content

Commit

Permalink
fix: spy on popup apis like alert (vitest-dev#3076)
Browse files Browse the repository at this point in the history
Co-authored-by: Vladimir <sleuths.slews0s@icloud.com>
  • Loading branch information
2 people authored and AriPerkkio committed Mar 28, 2023
1 parent 722d3b2 commit 13b3c94
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 91 deletions.
11 changes: 9 additions & 2 deletions docs/guide/browser.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: Browser mode | Guide
title: Browser Mode | Guide
---

# Browser mode (experimental)
# Browser Mode (experimental)

This page provides information about the experimental browser mode feature in the Vitest API, which allows you to run your tests in the browser natively, providing access to browser globals like window and document. This feature is currently under development, and APIs may change in the future.

Expand Down Expand Up @@ -87,3 +87,10 @@ npx vitest --browser.name=chrome --browser.headless
```

In this case, Vitest will run in headless mode using the Chrome browser.

## Limitations
### Thread Blocking Dialogs

When using Vitest Browser, it's important to note that thread blocking dialogs like `alert` or `confirm` cannot be used natively. This is because they block the web page, which means Vitest cannot continue communicating with the page, causing the execution to hang.

In such situations, Vitest provides default mocks with default returned values for these APIs. This ensures that if the user accidentally uses synchronous popup web APIs, the execution would not hang. However, it's still recommended for the user to mock these web APIs for better experience. Read more in [Mocking](/guide/mocking).
21 changes: 21 additions & 0 deletions packages/browser/src/client/dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const showPopupWarning = <T>(name: string, value: T, defaultValue?: T) => (...params: any[]) => {
const formatedParams = params.map(p => JSON.stringify(p)).join(', ')

console.warn(`Vitest encountered a \`${name}(${formatedParams})\` call that it cannot handle by default, so it returned \`${value}\`. Read more in https://vitest.dev/guide/browser#thread-blocking-dialogs.
If needed, mock the \`${name}\` call manually like:
\`\`\`
import { expect, vi } from "vitest"
vi.spyOn(window, "${name}")${defaultValue ? `.mockReturnValue(${JSON.stringify(defaultValue)})` : ''}
${name}(${formatedParams})
expect(${name}).toHaveBeenCalledWith(${formatedParams})
\`\`\``)
return value
}

export const setupDialogsSpy = () => {
globalThis.alert = showPopupWarning('alert', undefined)
globalThis.confirm = showPopupWarning('confirm', false, true)
globalThis.prompt = showPopupWarning('prompt', null, 'your value')
}
2 changes: 2 additions & 0 deletions packages/browser/src/client/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { BrowserSnapshotEnvironment } from './snapshot'
import { importId } from './utils'
import { setupConsoleLogSpy } from './logger'
import { createSafeRpc, rpc, rpcDone } from './rpc'
import { setupDialogsSpy } from './dialog'

// @ts-expect-error mocking some node apis
globalThis.process = { env: {}, argv: [], cwd: () => '/', stdout: { write: () => {} }, nextTick: cb => cb() }
Expand Down Expand Up @@ -71,6 +72,7 @@ ws.addEventListener('open', async () => {
iFrame.setAttribute('src', '/__vitest__/')

await setupConsoleLogSpy()
setupDialogsSpy()
await runTests(paths, config)
})

Expand Down

0 comments on commit 13b3c94

Please sign in to comment.