Skip to content

Commit

Permalink
fix: spy on popup apis like alert (#3076)
Browse files Browse the repository at this point in the history
Co-authored-by: Vladimir <sleuths.slews0s@icloud.com>
  • Loading branch information
Aslemammad and sheremet-va committed Mar 26, 2023
1 parent efb91e2 commit 280ad1e
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
@@ -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.
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

0 comments on commit 280ad1e

Please sign in to comment.