|
1 | 1 | import { channel, client, onCancel } from '@vitest/browser/client'
|
2 |
| -import { page, userEvent } from '@vitest/browser/context' |
| 2 | +import { page, server, userEvent } from '@vitest/browser/context' |
3 | 3 | import { collectTests, setupCommonEnv, SpyModule, startCoverageInsideWorker, startTests, stopCoverageInsideWorker } from 'vitest/browser'
|
4 |
| -import { executor, getBrowserState, getConfig, getWorkerState } from '../utils' |
| 4 | +import { CommandsManager, executor, getBrowserState, getConfig, getWorkerState } from '../utils' |
5 | 5 | import { setupDialogsSpy } from './dialog'
|
6 | 6 | import { setupExpectDom } from './expect-element'
|
7 | 7 | import { setupConsoleLogSpy } from './logger'
|
@@ -34,6 +34,8 @@ async function prepareTestEnvironment(files: string[]) {
|
34 | 34 | state.onCancel = onCancel
|
35 | 35 | state.rpc = rpc as any
|
36 | 36 |
|
| 37 | + getBrowserState().commands = new CommandsManager() |
| 38 | + |
37 | 39 | // TODO: expose `worker`
|
38 | 40 | const interceptor = createModuleMockerInterceptor()
|
39 | 41 | const mocker = new VitestBrowserClientMocker(
|
@@ -69,6 +71,8 @@ async function prepareTestEnvironment(files: string[]) {
|
69 | 71 | runner,
|
70 | 72 | config,
|
71 | 73 | state,
|
| 74 | + rpc, |
| 75 | + commands: getBrowserState().commands, |
72 | 76 | }
|
73 | 77 | }
|
74 | 78 |
|
@@ -113,12 +117,34 @@ async function executeTests(method: 'run' | 'collect', files: string[]) {
|
113 | 117 |
|
114 | 118 | debug('runner resolved successfully')
|
115 | 119 |
|
116 |
| - const { config, runner, state } = preparedData |
| 120 | + const { config, runner, state, commands, rpc } = preparedData |
117 | 121 |
|
118 | 122 | state.durations.prepare = performance.now() - state.durations.prepare
|
119 | 123 |
|
120 | 124 | debug('prepare time', state.durations.prepare, 'ms')
|
121 | 125 |
|
| 126 | + let contextSwitched = false |
| 127 | + |
| 128 | + // webdiverio context depends on the iframe state, so we need to switch the context, |
| 129 | + // we delay this in case the user doesn't use any userEvent commands to avoid the overhead |
| 130 | + if (server.provider === 'webdriverio') { |
| 131 | + let switchPromise: Promise<void> | null = null |
| 132 | + |
| 133 | + commands.onCommand(async () => { |
| 134 | + if (switchPromise) { |
| 135 | + await switchPromise |
| 136 | + } |
| 137 | + // if this is the first command, make sure we switched the command context to an iframe |
| 138 | + if (!contextSwitched) { |
| 139 | + switchPromise = rpc.wdioSwitchContext('iframe').finally(() => { |
| 140 | + switchPromise = null |
| 141 | + contextSwitched = true |
| 142 | + }) |
| 143 | + await switchPromise |
| 144 | + } |
| 145 | + }) |
| 146 | + } |
| 147 | + |
122 | 148 | try {
|
123 | 149 | await Promise.all([
|
124 | 150 | setupCommonEnv(config),
|
@@ -151,6 +177,9 @@ async function executeTests(method: 'run' | 'collect', files: string[]) {
|
151 | 177 | // need to cleanup for each tester
|
152 | 178 | // since playwright keyboard API is stateful on page instance level
|
153 | 179 | await userEvent.cleanup()
|
| 180 | + if (contextSwitched) { |
| 181 | + await rpc.wdioSwitchContext('parent') |
| 182 | + } |
154 | 183 | }
|
155 | 184 | catch (error: any) {
|
156 | 185 | await client.rpc.onUnhandledError({
|
|
0 commit comments