Skip to content

Commit

Permalink
chore: remove globals
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Feb 1, 2024
1 parent 4189f1a commit c377b58
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 59 deletions.
12 changes: 3 additions & 9 deletions packages/browser/src/client/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { channel, client } from './client'
import { rpcDone } from './rpc'
import { getConfig } from './utils'
import { getBrowserState, getConfig } from './utils'

const url = new URL(location.href)

Expand Down Expand Up @@ -45,18 +45,12 @@ interface IframeErrorEvent {
files: string[]
}

interface IframeInvalidEvent {
type: 'invalid'
id: number
}

type IframeChannelEvent = IframeDoneEvent | IframeErrorEvent | IframeInvalidEvent
type IframeChannelEvent = IframeDoneEvent | IframeErrorEvent

client.ws.addEventListener('open', async () => {
const config = getConfig()
const container = document.querySelector('#vitest-tester') as HTMLDivElement
// @ts-expect-error this is set in injector
const testFiles = window.__vi_files__ as string[]
const testFiles = getBrowserState().files

debug('test files', testFiles.join(', '))

Expand Down
26 changes: 9 additions & 17 deletions packages/browser/src/client/public/esm-client-injector.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
const moduleCache = new Map()

// this method receives a module object or "import" promise that it resolves and keeps track of
// and returns a hijacked module object that can be used to mock module exports
function wrapModule(module) {
if (module instanceof Promise) {
moduleCache.set(module, { promise: module, evaluated: false })
return module
// TODO: add a test
.then(m => '__vi_inject__' in m ? m.__vi_inject__ : m)
.finally(() => moduleCache.delete(module))
}
return '__vi_inject__' in module ? module.__vi_inject__ : module
}

function exportAll(exports, sourceModule) {
// #1120 when a module exports itself it causes
// call stack error
if (exports === sourceModule)
return

Expand All @@ -36,21 +31,18 @@ function exportAll(exports, sourceModule) {
}
}

window.__vi_export_all__ = exportAll

// TODO: allow easier rewriting of import.meta.env
window.__vi_import_meta__ = {
env: {},
url: location.href,
window.__vitest_browser_runner__ = {
exportAll,
wrapModule,
moduleCache,
config: { __VITEST_CONFIG__ },
files: { __VITEST_FILES__ },
}

window.__vi_module_cache__ = moduleCache
window.__vi_wrap_module__ = wrapModule
const config = __vitest_browser_runner__.config

window.__vi_config__ = { __VITEST_CONFIG__ }
if (window.__vi_config__.testNamePattern)
window.__vi_config__.testNamePattern = parseRegexp(window.__vi_config__.testNamePattern)
window.__vi_files__ = { __VITEST_FILES__ }
if (config.testNamePattern)
config.testNamePattern = parseRegexp(config.testNamePattern)

function parseRegexp(input) {
// Parse input
Expand Down
14 changes: 3 additions & 11 deletions packages/browser/src/client/tester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { channel, client, onCancel } from './client'
import { setupDialogsSpy } from './dialog'
import { setupConsoleLogSpy } from './logger'
import { browserHashMap, initiateRunner } from './runner'
import { getConfig, importId } from './utils'
import { getBrowserState, getConfig, importId } from './utils'
import { loadSafeRpc } from './rpc'
import { VitestBrowserClientMocker } from './mocker'
import { registerUnexpectedErrors, registerUnhandledErrors, serializeError } from './unhandled'
Expand Down Expand Up @@ -88,8 +88,7 @@ async function prepareTestEnvironment(files: string[]) {
throw new Error('Not called in the browser')
},
},
// @ts-expect-error untyped global for internal use
moduleCache: globalThis.__vi_module_cache__,
moduleCache: getBrowserState().moduleCache,
rpc,
durations: {
environment: 0,
Expand Down Expand Up @@ -182,12 +181,5 @@ async function runTests(files: string[]) {
}
}

async function invalid(id: string) {
channel.postMessage({ type: 'invalid', id })
}

// @ts-expect-error untyped global for internal use
window.__vitest_browser_runner__ = {
runTests,
invalid,
}
window.__vitest_browser_runner__.runTests = runTests
9 changes: 2 additions & 7 deletions packages/browser/src/client/unhandled.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { client } from './client'
import { channel } from './client'
import { importId } from './utils'
import { getBrowserState, importId } from './utils'

function on(event: string, listener: (...args: any[]) => void) {
window.addEventListener(event, listener)
Expand All @@ -16,15 +16,10 @@ export function serializeError(unhandledError: any) {
}
}

function getFiles(): string[] {
// @ts-expect-error this is set in injector
return window.__vi_running_tests__
}

// we can't import "processError" yet because error might've been thrown before the module was loaded
async function defaultErrorReport(type: string, unhandledError: any) {
const error = serializeError(unhandledError)
channel.postMessage({ type: 'error', files: getFiles(), error, errorType: type })
channel.postMessage({ type: 'error', files: getBrowserState().runningFiles, error, errorType: type })
}

function catchWindowErrors(cb: (e: ErrorEvent) => void) {
Expand Down
20 changes: 14 additions & 6 deletions packages/browser/src/client/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@ import type { ResolvedConfig, WorkerGlobalState } from 'vitest'

export async function importId(id: string) {
const name = `${getConfig().base || '/'}@id/${id}`
// @ts-expect-error mocking vitest apis
return __vi_wrap_module__(import(name))
return getBrowserState().wrapModule(import(name))
}

export function getConfig(): ResolvedConfig {
// @ts-expect-error not typed global
return window.__vi_config__
return getBrowserState().config
}

interface BrowserRunnerState {
files: string[]
runningFiles: string[]
moduleCache: WorkerGlobalState['moduleCache']
config: ResolvedConfig
exportAll(): void
wrapModule(module: any): any
runTests(tests: string[]): Promise<void>
}

export function getWorkerState(): WorkerGlobalState {
export function getBrowserState(): BrowserRunnerState {
// @ts-expect-error not typed global
return window.__vi_worker_state__
return window.__vitest_browser_runner__
}
4 changes: 2 additions & 2 deletions packages/browser/src/node/esmInjector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { Expression, ImportDeclaration, Node, Positioned } from '@vitest/ut

const viInjectedKey = '__vi_inject__'
// const viImportMetaKey = '__vi_import_meta__' // to allow overwrite
const viExportAllHelper = '__vi_export_all__'
const viExportAllHelper = '__vitest_browser_runner__.exportAll'

const skipHijack = [
'/@vite/client',
Expand Down Expand Up @@ -230,7 +230,7 @@ export function injectVitestModule(code: string, id: string, parse: PluginContex
// s.update(node.start, node.end, viImportMetaKey)
},
onDynamicImport(node) {
const replace = '__vi_wrap_module__(import('
const replace = '__vitest_browser_runner__.wrapModule(import('
s.overwrite(node.start, (node.source as Positioned<Expression>).start, replace)
s.overwrite(node.end - 1, node.end, '))')
},
Expand Down
6 changes: 3 additions & 3 deletions packages/browser/src/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default (project: WorkspaceProject, base = '/'): Plugin[] => {

const decodedTestFile = decodeURIComponent(url.pathname.slice(testerPrefix.length))
// if decoded test file is "__vitest_all__" or not in the list of known files, run all tests
const tests = decodedTestFile === '__vitest_all__' || !files.includes(decodedTestFile) ? 'window.__vi_files__' : JSON.stringify([decodedTestFile])
const tests = decodedTestFile === '__vitest_all__' || !files.includes(decodedTestFile) ? '__vitest_browser_runner__.files' : JSON.stringify([decodedTestFile])

const html = replacer(await testerHtml, {
__VITEST_FAVICON__: favicon,
Expand All @@ -84,8 +84,8 @@ export default (project: WorkspaceProject, base = '/'): Plugin[] => {
__VITEST_APPEND__:
// TODO: have only a single global variable to not pollute the global scope
`<script type="module">
window.__vi_running_tests__ = ${tests}
__vitest_browser_runner__.runTests(window.__vi_running_tests__)
__vitest_browser_runner__.runningFiles = ${tests}
__vitest_browser_runner__.runTests(__vitest_browser_runner__.runningFiles)
</script>`,
})
res.write(html, 'utf-8')
Expand Down
8 changes: 4 additions & 4 deletions test/core/test/injector-esm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ test('export * from', async () => {
).toMatchInlineSnapshot(`
"const __vi_inject__ = { [Symbol.toStringTag]: "Module" };
const { __vi_inject__: __vi_esm_0__ } = await import("vue");
__vi_export_all__(__vi_inject__, __vi_esm_0__);
__vitest_browser_runner__.exportAll(__vi_inject__, __vi_esm_0__);
const { __vi_inject__: __vi_esm_1__ } = await import("react");
__vi_export_all__(__vi_inject__, __vi_esm_1__);
__vitest_browser_runner__.exportAll(__vi_inject__, __vi_esm_1__);
export { __vi_inject__ }"
Expand Down Expand Up @@ -167,7 +167,7 @@ test('export then import minified', async () => {
"const __vi_inject__ = { [Symbol.toStringTag]: "Module" };
import { __vi_inject__ as __vi_esm_0__ } from 'vue'
const { __vi_inject__: __vi_esm_1__ } = await import("vue");
__vi_export_all__(__vi_inject__, __vi_esm_1__);
__vitest_browser_runner__.exportAll(__vi_inject__, __vi_esm_1__);
export { __vi_inject__ }"
`)
Expand Down Expand Up @@ -198,7 +198,7 @@ test('dynamic import', async () => {
)
expect(result).toMatchInlineSnapshot(`
"const __vi_inject__ = { [Symbol.toStringTag]: "Module" };
const i = () => __vi_wrap_module__(import('./foo'))
const i = () => __vitest_browser_runner__.wrapModule(import('./foo'))
export { __vi_inject__ }"
`)
})
Expand Down

0 comments on commit c377b58

Please sign in to comment.