diff --git a/packages/wxt/src/core/builders/vite/index.ts b/packages/wxt/src/core/builders/vite/index.ts index 59d59d1e..520511c6 100644 --- a/packages/wxt/src/core/builders/vite/index.ts +++ b/packages/wxt/src/core/builders/vite/index.ts @@ -218,7 +218,7 @@ export async function createViteBuilder( const baseConfig = await getBaseConfig(); const envConfig: vite.InlineConfig = { plugins: [ - wxtPlugins.webextensionPolyfillMock(wxtConfig), + wxtPlugins.extensionApiMock(wxtConfig), wxtPlugins.removeEntrypointMainFunction(wxtConfig, path), ], }; @@ -238,7 +238,7 @@ export async function createViteBuilder( baseConfig.optimizeDeps.include = []; const envConfig: vite.InlineConfig = { plugins: [ - wxtPlugins.webextensionPolyfillMock(wxtConfig), + wxtPlugins.extensionApiMock(wxtConfig), wxtPlugins.removeEntrypointMainFunction(wxtConfig, path), ], }; diff --git a/packages/wxt/src/core/builders/vite/plugins/extensionApiMock.ts b/packages/wxt/src/core/builders/vite/plugins/extensionApiMock.ts new file mode 100644 index 00000000..370d37bc --- /dev/null +++ b/packages/wxt/src/core/builders/vite/plugins/extensionApiMock.ts @@ -0,0 +1,38 @@ +import path from 'node:path'; +import type * as vite from 'vite'; +import { ResolvedConfig } from '../../../../types'; + +/** + * Mock `webextension-polyfill`, `wxt/browser`, and `wxt/browser/*` by inlining + * all dependencies that import them and adding a custom alias so that Vite + * resolves to a mocked version of the module. + * + * TODO: Detect non-wxt dependencies (like `@webext-core/*`) that import `webextension-polyfill` via + * `npm list` and inline them automatically. + */ +export function extensionApiMock(config: ResolvedConfig): vite.PluginOption { + return { + name: 'wxt:extension-api-mock', + config() { + const mockBrowser = path.resolve( + config.wxtModuleDir, + 'dist/virtual/mock-browser', + ); + return { + resolve: { + alias: { + 'webextension-polyfill': mockBrowser, + 'wxt/browser': mockBrowser, + 'wxt/browser/webextension-polyfill': mockBrowser, + 'wxt/browser/chrome': mockBrowser, + }, + }, + ssr: { + // Inline all WXT modules so vite processes them so the aliases can + // be resolved + noExternal: ['wxt'], + }, + }; + }, + }; +} diff --git a/packages/wxt/src/core/builders/vite/plugins/index.ts b/packages/wxt/src/core/builders/vite/plugins/index.ts index cbd8967b..f70dde24 100644 --- a/packages/wxt/src/core/builders/vite/plugins/index.ts +++ b/packages/wxt/src/core/builders/vite/plugins/index.ts @@ -8,7 +8,7 @@ export * from './noopBackground'; export * from './cssEntrypoints'; export * from './bundleAnalysis'; export * from './globals'; -export * from './webextensionPolyfillMock'; +export * from './extensionApiMock'; export * from './resolveExtensionApi'; export * from './entrypointGroupGlobals'; export * from './defineImportMeta'; diff --git a/packages/wxt/src/core/builders/vite/plugins/webextensionPolyfillMock.ts b/packages/wxt/src/core/builders/vite/plugins/webextensionPolyfillMock.ts deleted file mode 100644 index 99d84bf2..00000000 --- a/packages/wxt/src/core/builders/vite/plugins/webextensionPolyfillMock.ts +++ /dev/null @@ -1,43 +0,0 @@ -import path from 'node:path'; -import type * as vite from 'vite'; -import { ResolvedConfig } from '../../../../types'; - -/** - * Mock `webextension-polyfill` by inlining all dependencies that import it and adding a custom - * alias so that Vite resolves to a mocked version of the module. - * - * There are two ways to mark a module as inline: - * 1. Use partial file paths ("wxt/dist/browser.js") in the `test.server.deps.inline` option. - * 2. Use module names ("wxt" or "@webext-core/messaging") in the `ssr.noExternalize` option. - * - * This plugin uses the second approach since it's a little more intuative to understand. - * - * TODO: Detect non-wxt dependencies (like `@webext-core/*`) that import `webextension-polyfill` via - * `npm list` and inline them automatically. - */ -export function webextensionPolyfillMock( - config: ResolvedConfig, -): vite.PluginOption { - return { - name: 'wxt:testing-inline-deps', - config() { - return { - resolve: { - alias: { - // Alias to use a mocked version of the polyfill - 'webextension-polyfill': path.resolve( - config.wxtModuleDir, - 'dist/virtual/mock-browser', - ), - 'wxt/browser': 'wxt/testing', - 'wxt/browser/chrome': 'wxt/testing', - }, - }, - ssr: { - // Inline all WXT modules - noExternal: ['wxt'], - }, - }; - }, - }; -} diff --git a/packages/wxt/src/testing/wxt-vitest-plugin.ts b/packages/wxt/src/testing/wxt-vitest-plugin.ts index 2f8dd744..5495dba2 100644 --- a/packages/wxt/src/testing/wxt-vitest-plugin.ts +++ b/packages/wxt/src/testing/wxt-vitest-plugin.ts @@ -3,7 +3,7 @@ import { download, tsconfigPaths, globals, - webextensionPolyfillMock, + extensionApiMock, resolveAppConfig, } from '../core/builders/vite/plugins'; import { resolveConfig } from '../core/utils/building'; @@ -26,20 +26,23 @@ import { createUnimport } from 'unimport'; * * @param inlineConfig Customize WXT's config for testing. Any config specified here overrides the config from your `wxt.config.ts` file. */ -export function WxtVitest(inlineConfig?: InlineConfig): vite.PluginOption { - return resolveConfig(inlineConfig ?? {}, 'serve').then(async (config) => { - const plugins = [ - webextensionPolyfillMock(config), - globals(config), - download(config), - tsconfigPaths(config), - resolveAppConfig(config), - ]; - if (config.imports !== false) { - const unimport = createUnimport(config.imports); - await unimport.init(); - plugins.push(unimportPlugin(unimport)); - } - return plugins; - }); +export async function WxtVitest( + inlineConfig?: InlineConfig, +): Promise { + const config = await resolveConfig(inlineConfig ?? {}, 'serve'); + + const plugins: vite.PluginOption[] = [ + globals(config), + download(config), + tsconfigPaths(config), + resolveAppConfig(config), + extensionApiMock(config), + ]; + if (config.imports !== false) { + const unimport = createUnimport(config.imports); + await unimport.init(); + plugins.push(unimportPlugin(unimport)); + } + + return plugins; } diff --git a/packages/wxt/src/virtual/fake-browser-webextension-polyfill.ts b/packages/wxt/src/virtual/fake-browser-webextension-polyfill.ts deleted file mode 100644 index 60156bd6..00000000 --- a/packages/wxt/src/virtual/fake-browser-webextension-polyfill.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { fakeBrowser } from 'wxt/testing'; - -export const browser = fakeBrowser; diff --git a/packages/wxt/src/virtual/mock-browser.ts b/packages/wxt/src/virtual/mock-browser.ts index cf37d2f7..38024710 100644 --- a/packages/wxt/src/virtual/mock-browser.ts +++ b/packages/wxt/src/virtual/mock-browser.ts @@ -1,3 +1,4 @@ -import { fakeBrowser as mockBrowser } from 'wxt/testing'; +import { fakeBrowser } from 'wxt/testing'; -export default mockBrowser; +export const browser = fakeBrowser; +export default fakeBrowser; diff --git a/packages/wxt/src/virtual/virtual-module-globals.d.ts b/packages/wxt/src/virtual/virtual-module-globals.d.ts index ba96b54f..5199a83a 100644 --- a/packages/wxt/src/virtual/virtual-module-globals.d.ts +++ b/packages/wxt/src/virtual/virtual-module-globals.d.ts @@ -1,26 +1,22 @@ // Types required to make the virtual modules happy. declare module 'virtual:user-background-entrypoint' { - const definition: { main: () => void }; + const definition: import('wxt').BackgroundDefinition; export default definition; } declare module 'virtual:user-content-script-isolated-world-entrypoint' { - const definition: { - main: ( - ctx: import('wxt/client').ContentScriptContext, - ) => void | Promise; - }; + const definition: import('wxt').IsolatedWorldContentScriptDefinition; export default definition; } declare module 'virtual:user-content-script-main-world-entrypoint' { - const definition: { main: () => void | Promise }; + const definition: import('wxt').MainWorldContentScriptDefinition; export default definition; } declare module 'virtual:user-unlisted-script-entrypoint' { - const definition: { main: () => void | Promise }; + const definition: import('wxt').UnlistedScriptDefinition; export default definition; } @@ -28,16 +24,6 @@ declare module 'wxt/browser' { export const browser: import('webextension-polyfill').Browser; } -declare module 'wxt/client' { - export class ContentScriptContext { - constructor(name: string, options: any); - } -} - -declare module 'wxt/testing' { - export const fakeBrowser: import('webextension-polyfill').Browser; -} - declare module 'virtual:wxt-plugins' { export function initPlugins(): void; }