diff --git a/packages/wxt/src/core/utils/__tests__/manifest.test.ts b/packages/wxt/src/core/utils/__tests__/manifest.test.ts index 761a3d23..b521587a 100644 --- a/packages/wxt/src/core/utils/__tests__/manifest.test.ts +++ b/packages/wxt/src/core/utils/__tests__/manifest.test.ts @@ -10,6 +10,7 @@ import { fakeOptionsEntrypoint, fakePopupEntrypoint, fakeSidepanelEntrypoint, + fakeWxtDevServer, setFakeWxt, } from '../testing/fake-objects'; import { Manifest } from 'webextension-polyfill'; @@ -1496,6 +1497,89 @@ describe('Manifest Utils', () => { expect(actual.host_permissions).toBeUndefined(); }); }); + + describe('Dev mode', () => { + it('should not add any code for production builds', async () => { + setFakeWxt({ + config: { + command: 'build', + }, + server: { + hostname: 'localhost', + port: 3000, + origin: 'http://localhost:3000', + }, + }); + const output = fakeBuildOutput(); + const entrypoints: Entrypoint[] = []; + + const { manifest: actual } = await generateManifest( + entrypoints, + output, + ); + + expect(actual.permissions).toBeUndefined(); + expect(actual.content_security_policy).toBeUndefined(); + }); + + it('should add required permissions for dev mode to function for MV2', async () => { + setFakeWxt({ + config: { + command: 'serve', + manifestVersion: 2, + }, + server: fakeWxtDevServer({ + port: 3000, + hostname: 'localhost', + origin: 'http://localhost:3000', + }), + }); + const output = fakeBuildOutput(); + const entrypoints: Entrypoint[] = []; + + const { manifest: actual } = await generateManifest( + entrypoints, + output, + ); + + expect(actual).toMatchObject({ + content_security_policy: + "script-src 'self' http://localhost:3000; object-src 'self';", + permissions: ['http://localhost/*', 'tabs'], + }); + }); + + it('should add required permissions for dev mode to function for MV3', async () => { + setFakeWxt({ + config: { + command: 'serve', + manifestVersion: 3, + browser: 'chrome', + }, + server: fakeWxtDevServer({ + hostname: 'localhost', + port: 3000, + origin: 'http://localhost:3000', + }), + }); + const output = fakeBuildOutput(); + const entrypoints: Entrypoint[] = []; + + const { manifest: actual } = await generateManifest( + entrypoints, + output, + ); + + expect(actual).toMatchObject({ + content_security_policy: { + extension_pages: + "script-src 'self' 'wasm-unsafe-eval' http://localhost:3000; object-src 'self';", + }, + host_permissions: ['http://localhost/*'], + permissions: ['tabs', 'scripting'], + }); + }); + }); }); describe('stripPathFromMatchPattern', () => { diff --git a/packages/wxt/src/core/utils/testing/fake-objects.ts b/packages/wxt/src/core/utils/testing/fake-objects.ts index a1c60b46..470325af 100644 --- a/packages/wxt/src/core/utils/testing/fake-objects.ts +++ b/packages/wxt/src/core/utils/testing/fake-objects.ts @@ -311,10 +311,27 @@ export const fakeWxt = fakeObjectCreator(() => ({ logger: mock(), reloadConfig: vi.fn(), pm: mock(), - server: faker.helpers.arrayElement([undefined, mock()]), + server: faker.helpers.arrayElement([undefined, fakeWxtDevServer()]), builder: mock(), })); +export const fakeWxtDevServer = fakeObjectCreator(() => ({ + currentOutput: fakeBuildOutput(), + hostname: 'localhost', + origin: 'http://localhost:3000', + port: 3000, + reloadContentScript: vi.fn(), + reloadExtension: vi.fn(), + reloadPage: vi.fn(), + restart: vi.fn(), + restartBrowser: vi.fn(), + start: vi.fn(), + stop: vi.fn(), + transformHtml: vi.fn(), + watcher: mock(), + ws: mock(), +})); + export function setFakeWxt(overrides?: DeepPartial) { const wxt = fakeWxt(overrides); setWxtForTesting(wxt);