Skip to content

Commit

Permalink
feat(browser): support --inspect-brk
Browse files Browse the repository at this point in the history
  • Loading branch information
AriPerkkio committed Sep 7, 2024
1 parent c321a3f commit fc16f29
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 11 deletions.
16 changes: 10 additions & 6 deletions docs/guide/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,19 @@ Then in the debug tab, ensure 'Debug Current Test File' is selected. You can the

### Browser mode

To debug [Vitest Browser Mode](/guide/browser/index.md), pass `--inspect` in CLI or define it in your Vitest configuration:
To debug [Vitest Browser Mode](/guide/browser/index.md), pass `--inspect` or `--inspect-brk` in CLI or define it in your Vitest configuration:

::: code-group
```bash [CLI]
vitest --inspect --browser
vitest --inspect-brk --browser --no-file-parallelism
```
```ts [vitest.config.js]
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
inspect: true,
inspectBrk: true,
fileParallelism: false,
browser: {
name: 'chromium',
provider: 'playwright',
Expand All @@ -61,10 +62,10 @@ export default defineConfig({
```
:::

By default Vitest will use port `9229` as debugging port. You can overwrite it with by passing value in `inspect`:
By default Vitest will use port `9229` as debugging port. You can overwrite it with by passing value in `--inspect-brk`:

```bash
vitest --inspect=127.0.0.1:3000 --browser
vitest --inspect-brk=127.0.0.1:3000 --browser --no-file-parallelism
```

Use following [VSCode Compound configuration](https://code.visualstudio.com/docs/editor/debugging#_compound-launch-configurations) for launching Vitest and attaching debugger in the browser:
Expand All @@ -79,7 +80,7 @@ Use following [VSCode Compound configuration](https://code.visualstudio.com/docs
"name": "Run Vitest Browser",
"program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
"console": "integratedTerminal",
"args": ["--inspect", "--browser"]
"args": ["--inspect-brk", "--browser", "--no-file-parallelism"]
},
{
"type": "chrome",
Expand Down Expand Up @@ -120,6 +121,9 @@ vitest --inspect-brk --pool threads --poolOptions.threads.singleThread

# To run in a single child process
vitest --inspect-brk --pool forks --poolOptions.forks.singleFork

# To run in browser mode
vitest --inspect-brk --browser --no-file-parallelism
```

If you are using Vitest 1.1 or higher, you can also just provide `--no-file-parallelism` flag:
Expand Down
23 changes: 22 additions & 1 deletion packages/browser/src/node/pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ export function createBrowserPool(ctx: Vitest): ProcessPool {
)
}

async function setBreakpoint(contextId: string, file: string) {
if (!project.config.inspector.waitForDebugger) {
return
}

if (!provider.getCDPSession) {
throw new Error('Unable to set breakpoint, CDP not supported')
}

const session = await provider.getCDPSession(contextId)
await session.send('Debugger.enable', {})
await session.send('Debugger.setBreakpointByUrl', {
lineNumber: 0,
urlRegex: escapePathToRegexp(file),
})
}

const filesPerThread = Math.ceil(files.length / threadsCount)

// TODO: make it smarter,
Expand Down Expand Up @@ -83,7 +100,7 @@ export function createBrowserPool(ctx: Vitest): ProcessPool {
const url = new URL('/', origin)
url.searchParams.set('contextId', contextId)
const page = provider
.openPage(contextId, url.toString())
.openPage(contextId, url.toString(), () => setBreakpoint(contextId, files[0]))
.then(() => waitPromise)
promises.push(page)
}
Expand Down Expand Up @@ -145,3 +162,7 @@ export function createBrowserPool(ctx: Vitest): ProcessPool {
collectTests: files => runWorkspaceTests('collect', files),
}
}

function escapePathToRegexp(path: string): string {
return path.replace(/[/\\.?*()^${}|[\]+]/g, '\\$&')
}
3 changes: 2 additions & 1 deletion packages/browser/src/node/providers/playwright.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,9 @@ export class PlaywrightBrowserProvider implements BrowserProvider {
return page
}

async openPage(contextId: string, url: string) {
async openPage(contextId: string, url: string, beforeNavigate?: () => Promise<void>) {
const browserPage = await this.openBrowserPage(contextId)
await beforeNavigate?.()
await browserPage.goto(url)
}

Expand Down
3 changes: 1 addition & 2 deletions packages/vitest/src/node/config/resolveConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,8 @@ export function resolveConfig(
&& resolved.poolOptions?.threads?.singleThread
const isSingleFork
= resolved.pool === 'forks' && resolved.poolOptions?.forks?.singleFork
const isBrowser = resolved.browser.enabled

if (resolved.fileParallelism && !isSingleThread && !isSingleFork && !isBrowser) {
if (resolved.fileParallelism && !isSingleThread && !isSingleFork) {
const inspectOption = `--inspect${resolved.inspectBrk ? '-brk' : ''}`
throw new Error(
`You cannot use ${inspectOption} without "--no-file-parallelism", "poolOptions.threads.singleThread" or "poolOptions.forks.singleFork"`,
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/types/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface BrowserProvider {
beforeCommand?: (command: string, args: unknown[]) => Awaitable<void>
afterCommand?: (command: string, args: unknown[]) => Awaitable<void>
getCommandsContext: (contextId: string) => Record<string, unknown>
openPage: (contextId: string, url: string) => Promise<void>
openPage: (contextId: string, url: string, beforeNavigate?: () => Promise<void>) => Promise<void>
getCDPSession?: (contextId: string) => Promise<CDPSession>
close: () => Awaitable<void>
// eslint-disable-next-line ts/method-signature-style -- we want to allow extended options
Expand Down
13 changes: 13 additions & 0 deletions test/config/test/failures.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,24 @@ test('inspect cannot be used with multi-threading', async () => {
expect(stderr).toMatch('Error: You cannot use --inspect without "--no-file-parallelism", "poolOptions.threads.singleThread" or "poolOptions.forks.singleFork"')
})

test('inspect in browser mode requires no-file-parallelism', async () => {
const { stderr } = await runVitest({ inspect: true, browser: { enabled: true, name: 'chromium', provider: 'playwright' } })

expect(stderr).toMatch('Error: You cannot use --inspect without "--no-file-parallelism", "poolOptions.threads.singleThread" or "poolOptions.forks.singleFork"')
})

test('inspect-brk cannot be used with multi processing', async () => {
const { stderr } = await runVitest({ inspect: true, pool: 'forks', poolOptions: { forks: { singleFork: false } } })

expect(stderr).toMatch('Error: You cannot use --inspect without "--no-file-parallelism", "poolOptions.threads.singleThread" or "poolOptions.forks.singleFork"')
})

test('inspect-brk in browser mode requires no-file-parallelism', async () => {
const { stderr } = await runVitest({ inspectBrk: true, browser: { enabled: true, name: 'chromium', provider: 'playwright' } })

expect(stderr).toMatch('Error: You cannot use --inspect-brk without "--no-file-parallelism", "poolOptions.threads.singleThread" or "poolOptions.forks.singleFork"')
})

test('inspect and --inspect-brk cannot be used when not playwright + chromium', async () => {
for (const option of ['inspect', 'inspectBrk']) {
const cli = `--inspect${option === 'inspectBrk' ? '-brk' : ''}`
Expand All @@ -78,6 +90,7 @@ test('inspect and --inspect-brk cannot be used when not playwright + chromium',

const { stderr } = await runVitest({
[option]: true,
fileParallelism: false,
browser: {
enabled: true,
provider,
Expand Down

0 comments on commit fc16f29

Please sign in to comment.