Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: spy on popup apis like alert #3076

Merged
merged 7 commits into from Mar 26, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 9 additions & 2 deletions docs/guide/browser.md
@@ -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
@@ -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.
Aslemammad marked this conversation as resolved.
Show resolved Hide resolved
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
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