Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d580083727 | |||
| 5a70d9e57d | |||
| 1b1af245bd | |||
| 874a531a62 | |||
| a3d409f250 | |||
| b6758ca9fa | |||
| 2672308946 |
@@ -42,6 +42,7 @@ jobs:
|
||||
pnpm build:all:firefox-mv3
|
||||
pnpm tsc --noEmit
|
||||
pnpm wxt zip
|
||||
pnpm vitest run
|
||||
working-directory: demo
|
||||
|
||||
- name: Tests
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# Changelog
|
||||
|
||||
## v0.8.4
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.8.3...v0.8.4)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Allow actions without a popup ([#181](https://github.com/wxt-dev/wxt/pull/181))
|
||||
|
||||
## v0.8.3
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.8.2...v0.8.3)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Add testing utils under `wxt/testing` ([#178](https://github.com/wxt-dev/wxt/pull/178))
|
||||
|
||||
## v0.8.2
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.8.1...v0.8.2)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- **firefox:** Stop extending `AbortController` to fix crash in content scripts ([#176](https://github.com/wxt-dev/wxt/pull/176))
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- Improve output consistency ([#175](https://github.com/wxt-dev/wxt/pull/175))
|
||||
|
||||
## v0.8.1
|
||||
|
||||
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.8.0...v0.8.1)
|
||||
|
||||
+4
-2
@@ -11,14 +11,16 @@
|
||||
"build:all:chrome-mv2": "wxt build --mv2",
|
||||
"build:all:firefox-mv3": "wxt build -b firefox --mv3",
|
||||
"build:all:firefox-mv2": "wxt build -b firefox",
|
||||
"test": "pnpm -w build && vitest",
|
||||
"zip": "pnpm -w build && wxt zip",
|
||||
"compile": "pnpm -w build && tsc --noEmit",
|
||||
"postinstall": "pnpm -w build && wxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"webextension-polyfill": "^0.10.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
"react-dom": "^18.2.0",
|
||||
"vitest": "^0.34.6",
|
||||
"webextension-polyfill": "^0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.14",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import background from '../background';
|
||||
|
||||
browser.i18n.getMessage = () => 'fake-message';
|
||||
|
||||
const logMock = vi.fn();
|
||||
console.log = logMock;
|
||||
|
||||
describe('Background Entrypoint', () => {
|
||||
it("should log the extenion's runtime ID", () => {
|
||||
const id = 'some-id';
|
||||
fakeBrowser.runtime.id = id;
|
||||
|
||||
background.main();
|
||||
|
||||
expect(logMock).toBeCalledWith(id);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import { WxtVitest } from 'wxt/testing';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
mockReset: true,
|
||||
restoreMocks: true,
|
||||
},
|
||||
plugins: [WxtVitest()],
|
||||
});
|
||||
@@ -15,6 +15,7 @@ Some WXT APIs can be used without importing them:
|
||||
- [`defineBackground`](/api/wxt/client/functions/defineBackground) from `wxt/client`
|
||||
- [`createContentScriptUi`](/api/wxt/client/functions/createContentScriptUi) from `wxt/client`
|
||||
- [`defineUnlistedScript`](/api/wxt/sandbox/functions/defineUnlistedScript) from `wxt/sandbox`
|
||||
- [`fakeBrowser`](/api/wxt/testing/variables/fakeBrowser) from `wxt/testing`
|
||||
|
||||
And more. All `wxt/*` APIs can be used without imports.
|
||||
|
||||
|
||||
+132
-71
@@ -1,92 +1,153 @@
|
||||
# Testing
|
||||
|
||||
WXT provides a couple of utils for unit testing your extension.
|
||||
WXT provides several utils for writing tests.
|
||||
|
||||
[[toc]]
|
||||
## Unit tests
|
||||
|
||||
## Fake Browser
|
||||
If you're using auto-imports (enabled by default), [Vitest](https://vitest.dev/) is the only testing framework that supports them.
|
||||
|
||||
The `wxt/fake-browser` package includes an in-memory implementation of the `browser` variable you can use for testing. WXT simply re-exports the `fakeBrowser` variable from [`@webext-core/fake-browser`](https://webext-core.aklinker1.io/guide/fake-browser/).
|
||||
If you want to use a different testing library/framework (like Jest, mocha, node:test, etc), you can keep using it, but you have two options:
|
||||
|
||||
Here's an example test using Vitest:
|
||||
1. Switch to Vitest (recommended)
|
||||
2. Configure the testing library manually
|
||||
- Disable auto-imports by setting `imports: false` in your `wxt.config.ts` file
|
||||
- Manually add globals normally provided by WXT (like `__BROWSER__`) that you consume to the global scope before accessing them (`globalThis.__BROWSER__ = "chrome"`)
|
||||
|
||||
```ts
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { browser } from 'wxt/browser';
|
||||
import { fakeBrowser } from 'wxt';
|
||||
### Vitest Setup
|
||||
|
||||
// Function we're testing
|
||||
function onHelloMessage(cb: () => void) {
|
||||
browser.runtime.onMessage.addEventListener((message) => {
|
||||
if (message.type === 'hello') return 'world';
|
||||
});
|
||||
}
|
||||
Install vitest and add the `WxtVitest` plugin to your `vitest.config.ts` file.
|
||||
|
||||
// Mock the real `browser` object with a fake one
|
||||
vi.mock('wxt/browser', () => import('wxt/fake-browser'));
|
||||
|
||||
describe('onHelloMessage', () => {
|
||||
it("should call the callback when the message type is 'hello'", () => {
|
||||
const cb = vi.fn();
|
||||
const expected = 'world';
|
||||
|
||||
onHelloMessage(cb);
|
||||
const actual = await fakeBrowser.runtime.sendMessage({ type: 'hello' });
|
||||
|
||||
expect(cb).toBeCalledTimes(1);
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it("should ignore the message when the message type is not 'hello'", () => {
|
||||
const cb = vi.fn();
|
||||
|
||||
onHelloMessage(cb);
|
||||
await fakeBrowser.runtime.sendMessage({ type: 'not-hello' }).catch();
|
||||
|
||||
expect(cb).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
```sh
|
||||
pnpm i -D vitest
|
||||
```
|
||||
|
||||
See [`@webext-core/fake-browser`](https://webext-core.aklinker1.io/guide/fake-browser/) for setup, implemented APIs, and example tests.
|
||||
|
||||
## Handling Auto-imports
|
||||
|
||||
By default, WXT uses auto-imports. For tests, this can cause issues if your test environment is not setup to handle them correctly.
|
||||
|
||||
:::warning 🚧 Testing utils are not implemented yet!
|
||||
Eventually, WXT will provide utilities for setting up these auto-imports. For now, you'll need to set them up manually.
|
||||
:::
|
||||
|
||||
Not all testing frameworks can handle auto-imports. If your framework or setup is not listed below, it may be easiest to disable auto-imports.
|
||||
|
||||
To setup auto-imports manually, use [`unplugin-auto-import`](https://www.npmjs.com/package/unplugin-auto-import). It uses the same tool, `unimport`, as WXT and will result in compatiple auto-imports. `unplugin-auto-import` supports lots of different tools (vite, webpack, esbuild, rollup, etc). You can try and integrate it into your build process.
|
||||
|
||||
### Vitest (Recommended)
|
||||
|
||||
Vitest is easy, simply add `uplugin-auto-import` to your project.
|
||||
|
||||
```ts
|
||||
// vitest.config.ts
|
||||
import autoImports from 'unplugin-auto-import/vite';
|
||||
// <root>/vitest.config.ts
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import { WxtVitest } from 'wxt/testing';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
autoImports({
|
||||
imports: [{ name: 'defineConfig', from: 'wxt' }],
|
||||
presets: [{ package: 'wxt/client' }, { package: 'wxt/browser' }],
|
||||
dirs: ['components', 'composables', 'hooks', 'utils'],
|
||||
}),
|
||||
],
|
||||
plugins: [WxtVitest()],
|
||||
});
|
||||
```
|
||||
|
||||
### Jest
|
||||
And that's it. You're ready to start writing tests.
|
||||
|
||||
Don't use jest and auto-imports. You could try and configure jest to be transpiled by one of `unplugin-auto-import`'s supported built tools, but I don't know of a way to configure this. See [unplugin/unplugin-auto-import#33](https://github.com/unplugin/unplugin-auto-import/issues/33) if you want to try and set it up.
|
||||
### Writing Tests
|
||||
|
||||
I would recommend disabling auto-imports or migrating to Vitest if you want to use auto-imports.
|
||||
Here's a very basic test, written with a few different testing libraries, with a few different approaches for mocking the `browser` global.
|
||||
|
||||
### Mocha
|
||||
:::code-group
|
||||
|
||||
TODO: Is this possible? Maybe with `esbuild-mocha`? I would recommend moving to Vitest.
|
||||
```ts [Vitest]
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
|
||||
function logRuntimeId() {
|
||||
// Vitest automatically mocks "browser" with "fakeBrowser"
|
||||
console.log(browser.runtime.id);
|
||||
}
|
||||
|
||||
describe('logRuntimeId', () => {
|
||||
it("should log the extension's runtime ID", () => {
|
||||
// Set a known ID on fakeBrowser for the test
|
||||
const id = 'some-runtime-id';
|
||||
fakeBrowser.runtime.id = id;
|
||||
const logSpy = vi.spyOn(console, 'log');
|
||||
|
||||
logRuntimeId();
|
||||
|
||||
expect(logSpy).toBeCalledWith(id);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```ts [Jest - Manual Mock]
|
||||
import { fakeBrowser } from 'wxt/testing';
|
||||
import { browser } from 'wxt/browser';
|
||||
|
||||
function logRuntimeId() {
|
||||
console.log(browser.runtime.id);
|
||||
}
|
||||
|
||||
// Manually mock
|
||||
jest.mock('wxt/browser', () => {
|
||||
const { fakeBrowser } = require('wxt/testing');
|
||||
return { browser: fakeBrowser };
|
||||
});
|
||||
|
||||
describe('logRuntimeId', () => {
|
||||
it("should log the extension's runtime ID", () => {
|
||||
// Set a known ID on fakeBrowser for the test
|
||||
const id = 'some-runtime-id';
|
||||
fakeBrowser.runtime.id = id;
|
||||
const logSpy = jest.spyOn(console, 'log');
|
||||
|
||||
logRuntimeId();
|
||||
|
||||
expect(logSpy).toBeCalledWith(id);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```ts [node:test - Parameterized]
|
||||
import { describe, it, mock } from 'node:test';
|
||||
import { assert } from 'node:assert';
|
||||
import { fakeBrowser } from 'wxt/testing';
|
||||
import { browser } from 'wxt/browser';
|
||||
|
||||
// Add browser as a parameter so fakeBrowser can be passed instead of browser
|
||||
function logRuntimeId(browser = browser) {
|
||||
console.log(browser.runtime.id);
|
||||
}
|
||||
|
||||
describe('logRuntimeId', () => {
|
||||
it("should log the extension's runtime ID", () => {
|
||||
// Set a known ID on fakeBrowser for the test
|
||||
const id = 'some-runtime-id';
|
||||
fakeBrowser.runtime.id = id;
|
||||
console.log = mock.fn();
|
||||
|
||||
// pass in fakeBrowser during tests
|
||||
logRuntimeId(fakeBrowser);
|
||||
|
||||
assert.deepStrictEqual(console.log.mock.calls[0].arguments, [id]);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::warning
|
||||
Without mocking the `browser` variable, you'll see errors like this:
|
||||
|
||||
```
|
||||
This script should only be loaded in a browser extension.
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
WXT provides an in-memory, partial implementation of `browser`, [`fakeBrowser`](/api/wxt/testing/variables/fakeBrowser), from the [`@webext-core/fake-browser`](https://webext-core.aklinker1.io/guide/fake-browser/) package. `fakeBrowser` works with all testing frameworks/libraries. See their docs for a list of [implemented APIs](https://webext-core.aklinker1.io/guide/fake-browser/implemented-apis.html) and more example tests.
|
||||
|
||||
## E2E Tests
|
||||
|
||||
WXT does not provide any utils for running E2E tests. There are two libraries you can use to run E2E tests for any chrome extension.
|
||||
|
||||
- [`playwright`](https://playwright.dev/docs/chrome-extensions) (recommended) - "A high-level API to automate web browsers"
|
||||
- [`puppeteer`](https://pptr.dev/guides/chrome-extensions) - "A high-level API to control headless Chrome over the DevTools Protocol"
|
||||
|
||||
:::info
|
||||
Note that both only support running tests on Chrome.
|
||||
:::
|
||||
|
||||
Before running tests with either of these tools, you must build the extension with `wxt build` and then load the extension from the output directory in a new tab.
|
||||
|
||||
To test an extension's UI, like the popup or options page, you'll need to know the extension's ID to open the URL directly.
|
||||
|
||||
> _chrome-extension://`browser.runtime.id`/popup.html_
|
||||
|
||||
- Playwright provides an API to get your extension ID after it has been installed. [See their docs](https://playwright.dev/docs/chrome-extensions#testing).
|
||||
- Puppeteer requires you know the ID before installing the extension, so you can hard code it into the URLs you open. Follow [Chrome's guide](https://developer.chrome.com/docs/extensions/mv3/manifest/key/) to setup a consistent runtime id.
|
||||
|
||||
:::info
|
||||
You cannot test popups in their normal popup window, you have to open them in a tab.
|
||||
:::
|
||||
|
||||
+2
-1
@@ -3,7 +3,8 @@
|
||||
"../src",
|
||||
"../src/client",
|
||||
"../src/client/browser.ts",
|
||||
"../src/client/sandbox"
|
||||
"../src/client/sandbox",
|
||||
"../src/testing"
|
||||
],
|
||||
"plugin": ["typedoc-plugin-markdown", "typedoc-vitepress-theme"],
|
||||
"out": "./api",
|
||||
|
||||
@@ -23,6 +23,7 @@ describe('Auto Imports', () => {
|
||||
const defineConfig: typeof import('wxt')['defineConfig']
|
||||
const defineContentScript: typeof import('wxt/client')['defineContentScript']
|
||||
const defineUnlistedScript: typeof import('wxt/sandbox')['defineUnlistedScript']
|
||||
const fakeBrowser: typeof import('wxt/testing')['fakeBrowser']
|
||||
}
|
||||
"
|
||||
`);
|
||||
|
||||
@@ -599,4 +599,29 @@ describe('Manifest Content', () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('should respect the action field in the manifest without a popup', async () => {
|
||||
const project = new TestProject();
|
||||
project.setConfigFileConfig({
|
||||
manifest: {
|
||||
action: {
|
||||
default_title: 'Hello world',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await project.build();
|
||||
|
||||
expect(await project.getOutputManifest()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"action": {
|
||||
"default_title": "Hello world",
|
||||
},
|
||||
"description": "Example description",
|
||||
"manifest_version": 3,
|
||||
"name": "E2E Extension",
|
||||
"version": "0.0.0",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
+6
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "wxt",
|
||||
"type": "module",
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.4",
|
||||
"description": "Next gen framework for developing web extensions",
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
@@ -51,6 +51,11 @@
|
||||
"./browser": {
|
||||
"import": "./dist/browser.js",
|
||||
"types": "./dist/browser.d.ts"
|
||||
},
|
||||
"./testing": {
|
||||
"require": "./dist/testing.cjs",
|
||||
"import": "./dist/testing.js",
|
||||
"types": "./dist/testing.d.ts"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
Generated
+78
-80
@@ -85,7 +85,7 @@ importers:
|
||||
version: 3.3.0
|
||||
vite:
|
||||
specifier: ^4.4.11
|
||||
version: 4.4.11(@types/node@20.8.6)
|
||||
version: 4.4.11(@types/node@20.8.6)(sass@1.64.0)
|
||||
web-ext-run:
|
||||
specifier: ^0.1.0
|
||||
version: 0.1.0
|
||||
@@ -174,6 +174,9 @@ importers:
|
||||
react-dom:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0(react@18.2.0)
|
||||
vitest:
|
||||
specifier: ^0.34.6
|
||||
version: 0.34.6(jsdom@22.1.0)(sass@1.64.0)
|
||||
webextension-polyfill:
|
||||
specifier: ^0.10.0
|
||||
version: 0.10.0
|
||||
@@ -875,7 +878,6 @@ packages:
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
dependencies:
|
||||
'@sinclair/typebox': 0.27.8
|
||||
dev: true
|
||||
|
||||
/@jridgewell/gen-mapping@0.3.3:
|
||||
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
|
||||
@@ -965,7 +967,6 @@ packages:
|
||||
|
||||
/@sinclair/typebox@0.27.8:
|
||||
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
|
||||
dev: true
|
||||
|
||||
/@sindresorhus/is@5.4.1:
|
||||
resolution: {integrity: sha512-axlrvsHlHlFmKKMEg4VyvMzFr93JWJj4eIfXY1STVuO2fsImCa7ncaiG5gC8HKOX590AW5RtRsC41/B+OfrSqw==}
|
||||
@@ -982,17 +983,14 @@ packages:
|
||||
/@tootallnate/once@2.0.0:
|
||||
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
|
||||
engines: {node: '>= 10'}
|
||||
dev: true
|
||||
|
||||
/@types/chai-subset@1.3.3:
|
||||
resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
|
||||
dependencies:
|
||||
'@types/chai': 4.3.5
|
||||
dev: true
|
||||
|
||||
/@types/chai@4.3.5:
|
||||
resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==}
|
||||
dev: true
|
||||
|
||||
/@types/estree@1.0.1:
|
||||
resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
|
||||
@@ -1106,7 +1104,6 @@ packages:
|
||||
'@vitest/spy': 0.34.6
|
||||
'@vitest/utils': 0.34.6
|
||||
chai: 4.3.10
|
||||
dev: true
|
||||
|
||||
/@vitest/runner@0.34.6:
|
||||
resolution: {integrity: sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==}
|
||||
@@ -1114,21 +1111,18 @@ packages:
|
||||
'@vitest/utils': 0.34.6
|
||||
p-limit: 4.0.0
|
||||
pathe: 1.1.1
|
||||
dev: true
|
||||
|
||||
/@vitest/snapshot@0.34.6:
|
||||
resolution: {integrity: sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==}
|
||||
dependencies:
|
||||
magic-string: 0.30.2
|
||||
magic-string: 0.30.3
|
||||
pathe: 1.1.1
|
||||
pretty-format: 29.7.0
|
||||
dev: true
|
||||
|
||||
/@vitest/spy@0.34.6:
|
||||
resolution: {integrity: sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==}
|
||||
dependencies:
|
||||
tinyspy: 2.2.0
|
||||
dev: true
|
||||
|
||||
/@vitest/utils@0.34.6:
|
||||
resolution: {integrity: sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==}
|
||||
@@ -1136,7 +1130,6 @@ packages:
|
||||
diff-sequences: 29.6.3
|
||||
loupe: 2.3.7
|
||||
pretty-format: 29.7.0
|
||||
dev: true
|
||||
|
||||
/@vue/compiler-core@3.3.4:
|
||||
resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==}
|
||||
@@ -1322,12 +1315,10 @@ packages:
|
||||
|
||||
/abab@2.0.6:
|
||||
resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
|
||||
dev: true
|
||||
|
||||
/acorn-walk@8.2.0:
|
||||
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: true
|
||||
|
||||
/acorn@8.10.0:
|
||||
resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==}
|
||||
@@ -1408,7 +1399,6 @@ packages:
|
||||
/ansi-styles@5.2.0:
|
||||
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/ansi-styles@6.2.1:
|
||||
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
|
||||
@@ -1448,7 +1438,6 @@ packages:
|
||||
|
||||
/assertion-error@1.1.0:
|
||||
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
||||
dev: true
|
||||
|
||||
/async-mutex@0.4.0:
|
||||
resolution: {integrity: sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA==}
|
||||
@@ -1462,7 +1451,6 @@ packages:
|
||||
|
||||
/asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
dev: true
|
||||
|
||||
/at-least-node@1.0.0:
|
||||
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
|
||||
@@ -1626,7 +1614,6 @@ packages:
|
||||
loupe: 2.3.7
|
||||
pathval: 1.1.1
|
||||
type-detect: 4.0.8
|
||||
dev: true
|
||||
|
||||
/chalk@2.4.2:
|
||||
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
|
||||
@@ -1644,7 +1631,6 @@ packages:
|
||||
resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==}
|
||||
dependencies:
|
||||
get-func-name: 2.0.2
|
||||
dev: true
|
||||
|
||||
/chokidar@3.5.3:
|
||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||
@@ -1743,7 +1729,6 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
dev: true
|
||||
|
||||
/commander@11.0.0:
|
||||
resolution: {integrity: sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==}
|
||||
@@ -1862,7 +1847,6 @@ packages:
|
||||
engines: {node: '>=14'}
|
||||
dependencies:
|
||||
rrweb-cssom: 0.6.0
|
||||
dev: true
|
||||
|
||||
/csstype@3.1.2:
|
||||
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
|
||||
@@ -1875,7 +1859,6 @@ packages:
|
||||
abab: 2.0.6
|
||||
whatwg-mimetype: 3.0.0
|
||||
whatwg-url: 12.0.1
|
||||
dev: true
|
||||
|
||||
/debounce@1.2.1:
|
||||
resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==}
|
||||
@@ -1905,7 +1888,6 @@ packages:
|
||||
|
||||
/decimal.js@10.4.3:
|
||||
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
|
||||
dev: true
|
||||
|
||||
/decompress-response@6.0.0:
|
||||
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
|
||||
@@ -1919,7 +1901,6 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
type-detect: 4.0.8
|
||||
dev: true
|
||||
|
||||
/deep-extend@0.6.0:
|
||||
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
|
||||
@@ -1951,7 +1932,6 @@ packages:
|
||||
/delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: true
|
||||
|
||||
/destr@2.0.0:
|
||||
resolution: {integrity: sha512-FJ9RDpf3GicEBvzI3jxc2XhHzbqD8p4ANw/1kPsFBfTvP1b7Gn/Lg1vO7R9J4IVgoMbyUmFrFGZafJ1hPZpvlg==}
|
||||
@@ -1960,7 +1940,6 @@ packages:
|
||||
/diff-sequences@29.6.3:
|
||||
resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
dev: true
|
||||
|
||||
/dir-glob@3.0.1:
|
||||
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
|
||||
@@ -1986,7 +1965,6 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
webidl-conversions: 7.0.0
|
||||
dev: true
|
||||
|
||||
/domhandler@5.0.3:
|
||||
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
|
||||
@@ -2295,7 +2273,6 @@ packages:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
dev: true
|
||||
|
||||
/fs-extra@11.1.1:
|
||||
resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==}
|
||||
@@ -2370,7 +2347,6 @@ packages:
|
||||
|
||||
/get-func-name@2.0.2:
|
||||
resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==}
|
||||
dev: true
|
||||
|
||||
/get-intrinsic@1.2.1:
|
||||
resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==}
|
||||
@@ -2571,7 +2547,6 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
whatwg-encoding: 2.0.0
|
||||
dev: true
|
||||
|
||||
/html-escaper@2.0.2:
|
||||
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
|
||||
@@ -2603,7 +2578,6 @@ packages:
|
||||
debug: 4.3.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/http2-wrapper@2.2.0:
|
||||
resolution: {integrity: sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==}
|
||||
@@ -2637,7 +2611,6 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
dev: true
|
||||
|
||||
/ieee754@1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
@@ -2658,7 +2631,6 @@ packages:
|
||||
|
||||
/immutable@4.3.1:
|
||||
resolution: {integrity: sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A==}
|
||||
dev: true
|
||||
|
||||
/import-lazy@4.0.0:
|
||||
resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==}
|
||||
@@ -2838,7 +2810,6 @@ packages:
|
||||
|
||||
/is-potential-custom-element-name@1.0.1:
|
||||
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
|
||||
dev: true
|
||||
|
||||
/is-regex@1.1.4:
|
||||
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
|
||||
@@ -3022,7 +2993,6 @@ packages:
|
||||
- bufferutil
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
dev: true
|
||||
|
||||
/json-buffer@3.0.1:
|
||||
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
|
||||
@@ -3212,7 +3182,6 @@ packages:
|
||||
resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
|
||||
dependencies:
|
||||
get-func-name: 2.0.2
|
||||
dev: true
|
||||
|
||||
/lowercase-keys@3.0.0:
|
||||
resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==}
|
||||
@@ -3290,14 +3259,12 @@ packages:
|
||||
/mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: true
|
||||
|
||||
/mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
dev: true
|
||||
|
||||
/mimic-fn@2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
@@ -3530,7 +3497,6 @@ packages:
|
||||
|
||||
/nwsapi@2.2.7:
|
||||
resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==}
|
||||
dev: true
|
||||
|
||||
/object-assign@4.1.1:
|
||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||
@@ -3616,7 +3582,6 @@ packages:
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
yocto-queue: 1.0.0
|
||||
dev: true
|
||||
|
||||
/package-json@8.1.1:
|
||||
resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==}
|
||||
@@ -3655,7 +3620,6 @@ packages:
|
||||
resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==}
|
||||
dependencies:
|
||||
entities: 4.5.0
|
||||
dev: true
|
||||
|
||||
/path-is-absolute@1.0.1:
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||
@@ -3697,7 +3661,6 @@ packages:
|
||||
|
||||
/pathval@1.1.1:
|
||||
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
|
||||
dev: true
|
||||
|
||||
/perfect-debounce@1.0.0:
|
||||
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
|
||||
@@ -3780,7 +3743,6 @@ packages:
|
||||
'@jest/schemas': 29.6.3
|
||||
ansi-styles: 5.2.0
|
||||
react-is: 18.2.0
|
||||
dev: true
|
||||
|
||||
/process-nextick-args@2.0.1:
|
||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||
@@ -3807,12 +3769,10 @@ packages:
|
||||
|
||||
/psl@1.9.0:
|
||||
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
|
||||
dev: true
|
||||
|
||||
/punycode@2.3.0:
|
||||
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/pupa@3.1.0:
|
||||
resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==}
|
||||
@@ -3823,7 +3783,6 @@ packages:
|
||||
|
||||
/querystringify@2.2.0:
|
||||
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
|
||||
dev: true
|
||||
|
||||
/queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
@@ -3863,7 +3822,6 @@ packages:
|
||||
|
||||
/react-is@18.2.0:
|
||||
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
|
||||
dev: true
|
||||
|
||||
/react@18.2.0:
|
||||
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
||||
@@ -3942,7 +3900,6 @@ packages:
|
||||
|
||||
/requires-port@1.0.0:
|
||||
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
|
||||
dev: true
|
||||
|
||||
/resolve-alpn@1.2.1:
|
||||
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
|
||||
@@ -4036,7 +3993,6 @@ packages:
|
||||
|
||||
/rrweb-cssom@0.6.0:
|
||||
resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==}
|
||||
dev: true
|
||||
|
||||
/run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
@@ -4063,7 +4019,6 @@ packages:
|
||||
|
||||
/safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
dev: true
|
||||
|
||||
/sass@1.64.0:
|
||||
resolution: {integrity: sha512-m7YtAGmQta9uANIUJwXesAJMSncqH+3INc8kdVXs6eV6GUC8Qu2IYKQSN8PRLgiQfpca697G94klm2leYMxSHw==}
|
||||
@@ -4073,7 +4028,6 @@ packages:
|
||||
chokidar: 3.5.3
|
||||
immutable: 4.3.1
|
||||
source-map-js: 1.0.2
|
||||
dev: true
|
||||
|
||||
/sax@1.2.4:
|
||||
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
|
||||
@@ -4084,7 +4038,6 @@ packages:
|
||||
engines: {node: '>=v12.22.7'}
|
||||
dependencies:
|
||||
xmlchars: 2.2.0
|
||||
dev: true
|
||||
|
||||
/scheduler@0.23.0:
|
||||
resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
|
||||
@@ -4174,7 +4127,6 @@ packages:
|
||||
|
||||
/siginfo@2.0.0:
|
||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||
dev: true
|
||||
|
||||
/signal-exit@3.0.7:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
@@ -4266,11 +4218,9 @@ packages:
|
||||
|
||||
/stackback@0.0.2:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
dev: true
|
||||
|
||||
/std-env@3.3.3:
|
||||
resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==}
|
||||
dev: true
|
||||
|
||||
/stdin-discarder@0.1.0:
|
||||
resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==}
|
||||
@@ -4432,7 +4382,6 @@ packages:
|
||||
|
||||
/symbol-tree@3.2.4:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
dev: true
|
||||
|
||||
/tabbable@6.2.0:
|
||||
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
|
||||
@@ -4476,17 +4425,14 @@ packages:
|
||||
|
||||
/tinybench@2.5.0:
|
||||
resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==}
|
||||
dev: true
|
||||
|
||||
/tinypool@0.7.0:
|
||||
resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
dev: true
|
||||
|
||||
/tinyspy@2.2.0:
|
||||
resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
dev: true
|
||||
|
||||
/tmp@0.2.1:
|
||||
resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==}
|
||||
@@ -4514,7 +4460,6 @@ packages:
|
||||
punycode: 2.3.0
|
||||
universalify: 0.2.0
|
||||
url-parse: 1.5.10
|
||||
dev: true
|
||||
|
||||
/tr46@1.0.1:
|
||||
resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
|
||||
@@ -4527,7 +4472,6 @@ packages:
|
||||
engines: {node: '>=14'}
|
||||
dependencies:
|
||||
punycode: 2.3.0
|
||||
dev: true
|
||||
|
||||
/tree-kill@1.2.2:
|
||||
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
||||
@@ -4600,7 +4544,6 @@ packages:
|
||||
/type-detect@4.0.8:
|
||||
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/type-fest@1.4.0:
|
||||
resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==}
|
||||
@@ -4721,7 +4664,6 @@ packages:
|
||||
/universalify@0.2.0:
|
||||
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
dev: true
|
||||
|
||||
/universalify@1.0.0:
|
||||
resolution: {integrity: sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==}
|
||||
@@ -4767,7 +4709,6 @@ packages:
|
||||
dependencies:
|
||||
querystringify: 2.2.0
|
||||
requires-port: 1.0.0
|
||||
dev: true
|
||||
|
||||
/util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
@@ -4794,7 +4735,7 @@ packages:
|
||||
spdx-expression-parse: 3.0.1
|
||||
dev: true
|
||||
|
||||
/vite-node@0.34.6(@types/node@20.8.6):
|
||||
/vite-node@0.34.6(@types/node@20.8.6)(sass@1.64.0):
|
||||
resolution: {integrity: sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==}
|
||||
engines: {node: '>=v14.18.0'}
|
||||
hasBin: true
|
||||
@@ -4804,7 +4745,7 @@ packages:
|
||||
mlly: 1.4.2
|
||||
pathe: 1.1.1
|
||||
picocolors: 1.0.0
|
||||
vite: 4.4.11(@types/node@20.8.6)
|
||||
vite: 4.4.11(@types/node@20.8.6)(sass@1.64.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
@@ -4814,9 +4755,8 @@ packages:
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
dev: true
|
||||
|
||||
/vite@4.4.11(@types/node@20.8.6):
|
||||
/vite@4.4.11(@types/node@20.8.6)(sass@1.64.0):
|
||||
resolution: {integrity: sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
@@ -4848,6 +4788,7 @@ packages:
|
||||
esbuild: 0.18.20
|
||||
postcss: 8.4.27
|
||||
rollup: 3.28.0
|
||||
sass: 1.64.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
@@ -4864,7 +4805,7 @@ packages:
|
||||
mark.js: 8.11.1
|
||||
minisearch: 6.1.0
|
||||
shiki: 0.14.3
|
||||
vite: 4.4.11(@types/node@20.8.6)
|
||||
vite: 4.4.11(@types/node@20.8.6)(sass@1.64.0)
|
||||
vue: 3.3.4
|
||||
transitivePeerDependencies:
|
||||
- '@algolia/client-search'
|
||||
@@ -4957,8 +4898,8 @@ packages:
|
||||
strip-literal: 1.3.0
|
||||
tinybench: 2.5.0
|
||||
tinypool: 0.7.0
|
||||
vite: 4.4.11(@types/node@20.8.6)
|
||||
vite-node: 0.34.6(@types/node@20.8.6)
|
||||
vite: 4.4.11(@types/node@20.8.6)(sass@1.64.0)
|
||||
vite-node: 0.34.6(@types/node@20.8.6)(sass@1.64.0)
|
||||
why-is-node-running: 2.2.2
|
||||
transitivePeerDependencies:
|
||||
- less
|
||||
@@ -4970,6 +4911,72 @@ packages:
|
||||
- terser
|
||||
dev: true
|
||||
|
||||
/vitest@0.34.6(jsdom@22.1.0)(sass@1.64.0):
|
||||
resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==}
|
||||
engines: {node: '>=v14.18.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@edge-runtime/vm': '*'
|
||||
'@vitest/browser': '*'
|
||||
'@vitest/ui': '*'
|
||||
happy-dom: '*'
|
||||
jsdom: '*'
|
||||
playwright: '*'
|
||||
safaridriver: '*'
|
||||
webdriverio: '*'
|
||||
peerDependenciesMeta:
|
||||
'@edge-runtime/vm':
|
||||
optional: true
|
||||
'@vitest/browser':
|
||||
optional: true
|
||||
'@vitest/ui':
|
||||
optional: true
|
||||
happy-dom:
|
||||
optional: true
|
||||
jsdom:
|
||||
optional: true
|
||||
playwright:
|
||||
optional: true
|
||||
safaridriver:
|
||||
optional: true
|
||||
webdriverio:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/chai': 4.3.5
|
||||
'@types/chai-subset': 1.3.3
|
||||
'@types/node': 20.8.6
|
||||
'@vitest/expect': 0.34.6
|
||||
'@vitest/runner': 0.34.6
|
||||
'@vitest/snapshot': 0.34.6
|
||||
'@vitest/spy': 0.34.6
|
||||
'@vitest/utils': 0.34.6
|
||||
acorn: 8.10.0
|
||||
acorn-walk: 8.2.0
|
||||
cac: 6.7.14
|
||||
chai: 4.3.10
|
||||
debug: 4.3.4
|
||||
jsdom: 22.1.0
|
||||
local-pkg: 0.4.3
|
||||
magic-string: 0.30.3
|
||||
pathe: 1.1.1
|
||||
picocolors: 1.0.0
|
||||
std-env: 3.3.3
|
||||
strip-literal: 1.3.0
|
||||
tinybench: 2.5.0
|
||||
tinypool: 0.7.0
|
||||
vite: 4.4.11(@types/node@20.8.6)(sass@1.64.0)
|
||||
vite-node: 0.34.6(@types/node@20.8.6)(sass@1.64.0)
|
||||
why-is-node-running: 2.2.2
|
||||
transitivePeerDependencies:
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
dev: false
|
||||
|
||||
/vscode-oniguruma@1.7.0:
|
||||
resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==}
|
||||
dev: true
|
||||
@@ -5008,7 +5015,6 @@ packages:
|
||||
engines: {node: '>=14'}
|
||||
dependencies:
|
||||
xml-name-validator: 4.0.0
|
||||
dev: true
|
||||
|
||||
/watchpack@2.4.0:
|
||||
resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==}
|
||||
@@ -5062,7 +5068,6 @@ packages:
|
||||
/webidl-conversions@7.0.0:
|
||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/webpack-sources@3.2.3:
|
||||
resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
|
||||
@@ -5078,12 +5083,10 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
iconv-lite: 0.6.3
|
||||
dev: true
|
||||
|
||||
/whatwg-mimetype@3.0.0:
|
||||
resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/whatwg-url@12.0.1:
|
||||
resolution: {integrity: sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==}
|
||||
@@ -5091,7 +5094,6 @@ packages:
|
||||
dependencies:
|
||||
tr46: 4.1.1
|
||||
webidl-conversions: 7.0.0
|
||||
dev: true
|
||||
|
||||
/whatwg-url@7.1.0:
|
||||
resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
|
||||
@@ -5156,7 +5158,6 @@ packages:
|
||||
dependencies:
|
||||
siginfo: 2.0.0
|
||||
stackback: 0.0.2
|
||||
dev: true
|
||||
|
||||
/widest-line@4.0.1:
|
||||
resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==}
|
||||
@@ -5218,7 +5219,6 @@ packages:
|
||||
/xml-name-validator@4.0.0:
|
||||
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/xml2js@0.5.0:
|
||||
resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==}
|
||||
@@ -5235,7 +5235,6 @@ packages:
|
||||
|
||||
/xmlchars@2.2.0:
|
||||
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
|
||||
dev: true
|
||||
|
||||
/y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
@@ -5271,7 +5270,6 @@ packages:
|
||||
/yocto-queue@1.0.0:
|
||||
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
|
||||
engines: {node: '>=12.20'}
|
||||
dev: true
|
||||
|
||||
/zip-dir@2.0.0:
|
||||
resolution: {integrity: sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg==}
|
||||
|
||||
@@ -55,6 +55,13 @@ await Promise.all([
|
||||
dts: true,
|
||||
silent: true,
|
||||
}),
|
||||
tsup.build({
|
||||
entry: { testing: 'src/testing/index.ts' },
|
||||
format: ['esm', 'cjs'],
|
||||
sourcemap: 'inline',
|
||||
dts: true,
|
||||
silent: true,
|
||||
}),
|
||||
...virtualEntrypoints.map((entryName) =>
|
||||
tsup.build({
|
||||
entry: {
|
||||
|
||||
@@ -3,23 +3,23 @@ import { browser } from '../browser';
|
||||
import { logger } from './logger';
|
||||
|
||||
/**
|
||||
* Extends [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
|
||||
* Implements [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
|
||||
* Used to detect and stop content script code when the script is invalidated.
|
||||
*
|
||||
* It also provides several utilities like `ctx.setTimeout` and `ctx.setInterval` that should be used in
|
||||
* content scripts instead of `window.setTimeout` or `window.setInterval`.
|
||||
*/
|
||||
export class ContentScriptContext extends AbortController {
|
||||
export class ContentScriptContext implements AbortController {
|
||||
private static SCRIPT_STARTED_MESSAGE_TYPE = 'wxt:content-script-started';
|
||||
|
||||
#isTopFrame = window.self === window.top;
|
||||
#abortController: AbortController;
|
||||
|
||||
constructor(
|
||||
private readonly contentScriptName: string,
|
||||
public readonly options?: Omit<ContentScriptDefinition, 'main'>,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.#abortController = new AbortController();
|
||||
if (this.#isTopFrame) {
|
||||
this.#stopOldScripts();
|
||||
}
|
||||
@@ -29,6 +29,14 @@ export class ContentScriptContext extends AbortController {
|
||||
});
|
||||
}
|
||||
|
||||
get signal() {
|
||||
return this.#abortController.signal;
|
||||
}
|
||||
|
||||
abort(reason?: any): void {
|
||||
return this.#abortController.abort(reason);
|
||||
}
|
||||
|
||||
get isInvalid(): boolean {
|
||||
if (browser.runtime.id == null) {
|
||||
this.notifyInvalidated(); // Sets `signal.aborted` to true
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { fakeBrowser as browser } from '@webext-core/fake-browser';
|
||||
import { fakeBrowser as browser } from '../../testing/fake-browser';
|
||||
|
||||
export default browser;
|
||||
|
||||
@@ -11,7 +11,7 @@ import { findEntrypoints } from '../findEntrypoints';
|
||||
import fs from 'fs-extra';
|
||||
import { importEntrypointFile } from '../../utils/importEntrypointFile';
|
||||
import glob from 'fast-glob';
|
||||
import { fakeInternalConfig } from '../../../testing/fake-objects';
|
||||
import { fakeInternalConfig } from '../../../testing-utils/fake-objects';
|
||||
import { unnormalizePath } from '../../utils/paths';
|
||||
|
||||
vi.mock('../../utils/importEntrypointFile');
|
||||
|
||||
@@ -38,11 +38,10 @@ export async function findEntrypoints(
|
||||
relativePaths.sort();
|
||||
|
||||
const pathGlobs = Object.keys(PATH_GLOB_TO_TYPE_MAP);
|
||||
const existingNames: Record<string, Entrypoint | undefined> = {};
|
||||
|
||||
const entrypoints: Entrypoint[] = [];
|
||||
let hasBackground = false;
|
||||
await Promise.all(
|
||||
// TODO: This parallelization is bad
|
||||
const possibleEntrypoints: Array<Entrypoint | undefined> = await Promise.all(
|
||||
relativePaths.map(async (relativePath) => {
|
||||
const path = resolve(config.entrypointsDir, relativePath);
|
||||
const matchingGlob = pathGlobs.find((glob) =>
|
||||
@@ -50,41 +49,35 @@ export async function findEntrypoints(
|
||||
);
|
||||
|
||||
if (matchingGlob == null) {
|
||||
return config.logger.warn(
|
||||
config.logger.warn(
|
||||
`${relativePath} does not match any known entrypoint. Known entrypoints:\n${JSON.stringify(
|
||||
PATH_GLOB_TO_TYPE_MAP,
|
||||
null,
|
||||
2,
|
||||
)}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
|
||||
if (type === 'ignored') return;
|
||||
|
||||
let entrypoint: Entrypoint;
|
||||
switch (type) {
|
||||
case 'popup':
|
||||
entrypoint = await getPopupEntrypoint(config, path);
|
||||
break;
|
||||
return await getPopupEntrypoint(config, path);
|
||||
case 'options':
|
||||
entrypoint = await getOptionsEntrypoint(config, path);
|
||||
break;
|
||||
return await getOptionsEntrypoint(config, path);
|
||||
case 'background':
|
||||
entrypoint = await getBackgroundEntrypoint(config, path);
|
||||
hasBackground = true;
|
||||
break;
|
||||
return await getBackgroundEntrypoint(config, path);
|
||||
case 'content-script':
|
||||
entrypoint = await getContentScriptEntrypoint(config, path);
|
||||
break;
|
||||
return await getContentScriptEntrypoint(config, path);
|
||||
case 'unlisted-page':
|
||||
entrypoint = await getUnlistedPageEntrypoint(config, path);
|
||||
break;
|
||||
return await getUnlistedPageEntrypoint(config, path);
|
||||
case 'unlisted-script':
|
||||
entrypoint = await getUnlistedScriptEntrypoint(config, path);
|
||||
break;
|
||||
return await getUnlistedScriptEntrypoint(config, path);
|
||||
case 'content-script-style':
|
||||
entrypoint = {
|
||||
return {
|
||||
type,
|
||||
name: getEntrypointName(config.entrypointsDir, path),
|
||||
inputPath: path,
|
||||
@@ -94,9 +87,8 @@ export async function findEntrypoints(
|
||||
exclude: undefined,
|
||||
},
|
||||
};
|
||||
break;
|
||||
default:
|
||||
entrypoint = {
|
||||
return {
|
||||
type,
|
||||
name: getEntrypointName(config.entrypointsDir, path),
|
||||
inputPath: path,
|
||||
@@ -107,22 +99,30 @@ export async function findEntrypoints(
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const withSameName = existingNames[entrypoint.name];
|
||||
if (withSameName) {
|
||||
throw Error(
|
||||
`Multiple entrypoints with the name "${
|
||||
entrypoint.name
|
||||
}" detected, but only one is allowed: ${[
|
||||
relative(config.root, withSameName.inputPath),
|
||||
relative(config.root, entrypoint.inputPath),
|
||||
].join(', ')}`,
|
||||
);
|
||||
}
|
||||
entrypoints.push(entrypoint);
|
||||
existingNames[entrypoint.name] = entrypoint;
|
||||
}),
|
||||
);
|
||||
|
||||
const entrypoints = possibleEntrypoints.filter(
|
||||
(entry) => !!entry,
|
||||
) as Entrypoint[];
|
||||
|
||||
// Report duplicate entrypoint names
|
||||
const existingNames: Record<string, Entrypoint | undefined> = {};
|
||||
entrypoints.forEach((entrypoint) => {
|
||||
const withSameName = existingNames[entrypoint.name];
|
||||
if (withSameName) {
|
||||
throw Error(
|
||||
`Multiple entrypoints with the name "${
|
||||
entrypoint.name
|
||||
}" detected, but only one is allowed: ${[
|
||||
relative(config.root, withSameName.inputPath),
|
||||
relative(config.root, entrypoint.inputPath),
|
||||
].join(', ')}`,
|
||||
);
|
||||
}
|
||||
existingNames[entrypoint.name] = entrypoint;
|
||||
});
|
||||
|
||||
if (config.command === 'serve' && !hasBackground) {
|
||||
entrypoints.push(
|
||||
await getBackgroundEntrypoint(config, VIRTUAL_NOOP_BACKGROUND_MODULE_ID),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { createExtensionRunner } from '..';
|
||||
import { fakeInternalConfig } from '../../../testing/fake-objects';
|
||||
import { fakeInternalConfig } from '../../../testing-utils/fake-objects';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
import { createSafariRunner } from '../safari';
|
||||
import { ExtensionRunner } from '../extension-runner';
|
||||
|
||||
@@ -468,17 +468,13 @@ export interface ExcludableEntrypoint {
|
||||
export type UserManifest = Partial<
|
||||
Omit<
|
||||
Manifest.WebExtensionManifest,
|
||||
| 'action'
|
||||
| 'background'
|
||||
| 'browser_action'
|
||||
| 'chrome_url_overrides'
|
||||
| 'devtools_page'
|
||||
| 'manifest_version'
|
||||
| 'options_page'
|
||||
| 'options_ui'
|
||||
| 'sandbox'
|
||||
| 'page_action'
|
||||
| 'popup'
|
||||
| 'sidepanel'
|
||||
| 'sidebar_action'
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { hashContentScriptOptions } from '../content-scripts';
|
||||
import { fakeInternalConfig } from '../../../testing/fake-objects';
|
||||
import { fakeInternalConfig } from '../../../testing-utils/fake-objects';
|
||||
|
||||
describe('Content Script Utils', () => {
|
||||
describe('hashContentScriptOptions', () => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
fakePopupEntrypoint,
|
||||
fakeRollupOutputAsset,
|
||||
fakeRollupOutputChunk,
|
||||
} from '../../../testing/fake-objects';
|
||||
} from '../../../testing-utils/fake-objects';
|
||||
import { BuildOutput, BuildStepOutput } from '../../types';
|
||||
|
||||
describe('Detect Dev Changes', () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { importEntrypointFile } from '../importEntrypointFile';
|
||||
import { fakeInternalConfig } from '../../../testing/fake-objects';
|
||||
import { fakeInternalConfig } from '../../../testing-utils/fake-objects';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
const entrypointPath = (filename: string) =>
|
||||
|
||||
@@ -9,7 +9,10 @@ export function getUnimportOptions(
|
||||
|
||||
const defaultOptions: Partial<UnimportOptions> = {
|
||||
debugLog: config.logger.debug,
|
||||
imports: [{ name: 'defineConfig', from: 'wxt' }],
|
||||
imports: [
|
||||
{ name: 'defineConfig', from: 'wxt' },
|
||||
{ name: 'fakeBrowser', from: 'wxt/testing' },
|
||||
],
|
||||
presets: [
|
||||
{ package: 'wxt/client' },
|
||||
{ package: 'wxt/browser' },
|
||||
|
||||
@@ -14,7 +14,6 @@ import * as vite from 'vite';
|
||||
import { createFsCache } from './createFsCache';
|
||||
import consola, { LogLevels } from 'consola';
|
||||
import * as plugins from '../vite-plugins';
|
||||
import { getGlobals } from './globals';
|
||||
|
||||
/**
|
||||
* Given an inline config, discover the config file if necessary, merge the results, resolve any
|
||||
@@ -251,10 +250,7 @@ async function resolveInternalViteConfig(
|
||||
if (finalConfig.analysis.enabled) {
|
||||
internalVite.plugins.push(plugins.bundleAnalysis());
|
||||
}
|
||||
internalVite.plugins.push(plugins.globals(finalConfig));
|
||||
|
||||
internalVite.define ??= {};
|
||||
for (const global of getGlobals(finalConfig)) {
|
||||
internalVite.define[global.name] = JSON.stringify(global.value);
|
||||
}
|
||||
return internalVite;
|
||||
}
|
||||
|
||||
@@ -5,42 +5,42 @@ export function getGlobals(
|
||||
): Array<{ name: string; value: any; type: string }> {
|
||||
return [
|
||||
{
|
||||
name: '__MANIFEST_VERSION__',
|
||||
name: surroundInUnderscore('MANIFEST_VERSION'),
|
||||
value: config.manifestVersion,
|
||||
type: `2 | 3`,
|
||||
},
|
||||
{
|
||||
name: '__BROWSER__',
|
||||
name: surroundInUnderscore('BROWSER'),
|
||||
value: config.browser,
|
||||
type: `string`,
|
||||
},
|
||||
{
|
||||
name: '__IS_CHROME__',
|
||||
name: surroundInUnderscore('IS_CHROME'),
|
||||
value: config.browser === 'chrome',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: '__IS_FIREFOX__',
|
||||
name: surroundInUnderscore('IS_FIREFOX'),
|
||||
value: config.browser === 'firefox',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: '__IS_SAFARI__',
|
||||
name: surroundInUnderscore('IS_SAFARI'),
|
||||
value: config.browser === 'safari',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: '__IS_EDGE__',
|
||||
name: surroundInUnderscore('IS_EDGE'),
|
||||
value: config.browser === 'edge',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: '__IS_OPERA__',
|
||||
name: surroundInUnderscore('IS_OPERA'),
|
||||
value: config.browser === 'opera',
|
||||
type: `boolean`,
|
||||
},
|
||||
{
|
||||
name: '__COMMAND__',
|
||||
name: surroundInUnderscore('COMMAND'),
|
||||
value: config.command,
|
||||
type: `"build" | "serve"`,
|
||||
},
|
||||
@@ -53,9 +53,17 @@ export function getEntrypointGlobals(
|
||||
) {
|
||||
return [
|
||||
{
|
||||
name: '__ENTRYPOINT__',
|
||||
name: surroundInUnderscore('ENTRYPOINT'),
|
||||
value: entrypointName,
|
||||
type: `string`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't hardcode the complete name so that the string litterals in this file aren't replaced during
|
||||
* tests (which causes syntax errors), only during builds.
|
||||
*/
|
||||
function surroundInUnderscore(name: string): string {
|
||||
return `__${name}__`;
|
||||
}
|
||||
|
||||
+15
-14
@@ -214,18 +214,23 @@ function addEntrypoints(
|
||||
config.outDir,
|
||||
'.html',
|
||||
);
|
||||
const options: Manifest.ActionManifest = {
|
||||
default_icon: popup.options.defaultIcon,
|
||||
default_title: popup.options.defaultTitle,
|
||||
browser_style: popup.options.browserStyle,
|
||||
};
|
||||
const options: Manifest.ActionManifest = {};
|
||||
if (popup.options.defaultIcon)
|
||||
options.default_icon = popup.options.defaultIcon;
|
||||
if (popup.options.defaultTitle)
|
||||
options.default_title = popup.options.defaultTitle;
|
||||
if (popup.options.browserStyle)
|
||||
options.browser_style = popup.options.browserStyle;
|
||||
if (manifest.manifest_version === 3) {
|
||||
manifest.action = {
|
||||
...(manifest.action ?? {}),
|
||||
...options,
|
||||
default_popup,
|
||||
};
|
||||
} else {
|
||||
manifest[popup.options.mv2Key ?? 'browser_action'] = {
|
||||
const key = popup.options.mv2Key ?? 'browser_action';
|
||||
manifest[key] = {
|
||||
...(manifest[key] ?? {}),
|
||||
...options,
|
||||
default_popup,
|
||||
};
|
||||
@@ -324,14 +329,10 @@ function addEntrypoints(
|
||||
const newContentScripts = Array.from(hashToEntrypointsMap.entries()).map(
|
||||
([, scripts]) => ({
|
||||
...mapWxtOptionsToContentScript(scripts[0].options, config),
|
||||
// TOOD: Sorting css and js arrays here so we get consistent test results... but we
|
||||
// shouldn't have to. Where is the inconsistency coming from?
|
||||
css: getContentScriptCssFiles(scripts, cssMap)?.sort(),
|
||||
js: scripts
|
||||
.map((entry) =>
|
||||
getEntrypointBundlePath(entry, config.outDir, '.js'),
|
||||
)
|
||||
.sort(),
|
||||
css: getContentScriptCssFiles(scripts, cssMap),
|
||||
js: scripts.map((entry) =>
|
||||
getEntrypointBundlePath(entry, config.outDir, '.js'),
|
||||
),
|
||||
}),
|
||||
);
|
||||
if (newContentScripts.length >= 0) {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import * as vite from 'vite';
|
||||
import { InternalConfig } from '../types';
|
||||
import { getGlobals } from '../utils/globals';
|
||||
|
||||
export function globals(config: InternalConfig): vite.PluginOption {
|
||||
return {
|
||||
name: 'wxt:globals',
|
||||
config() {
|
||||
const define: vite.InlineConfig['define'] = {};
|
||||
for (const global of getGlobals(config)) {
|
||||
define[global.name] = JSON.stringify(global.value);
|
||||
}
|
||||
return {
|
||||
define,
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -8,3 +8,5 @@ export * from './tsconfigPaths';
|
||||
export * from './noopBackground';
|
||||
export * from './cssEntrypoints';
|
||||
export * from './bundleAnalysis';
|
||||
export * from './globals';
|
||||
export * from './webextensionPolyfillAlias';
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import path from 'node:path';
|
||||
import * as vite from 'vite';
|
||||
import { InternalConfig } from '../types';
|
||||
|
||||
/**
|
||||
* Creates an alias to redirect "webextension-polyfill" imports to WXT's `fakeBrowser`.
|
||||
*
|
||||
* This should only be used during tests.
|
||||
*/
|
||||
export function webextensionPolyfillAlias(
|
||||
config: InternalConfig,
|
||||
): vite.PluginOption {
|
||||
return {
|
||||
name: 'wxt:webextension-polyfill-test-alias',
|
||||
config() {
|
||||
return {
|
||||
resolve: {
|
||||
alias: {
|
||||
'webextension-polyfill': path.resolve(
|
||||
config.root,
|
||||
'node_modules/wxt/dist/virtual-modules/fake-browser',
|
||||
),
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { fakeBrowser, type FakeBrowser } from '@webext-core/fake-browser';
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @module wxt/testing
|
||||
*/
|
||||
export * from './fake-browser';
|
||||
export * from './wxt-vitest-plugin';
|
||||
@@ -0,0 +1,35 @@
|
||||
import * as vite from 'vite';
|
||||
import {
|
||||
unimport,
|
||||
download,
|
||||
tsconfigPaths,
|
||||
globals,
|
||||
webextensionPolyfillAlias,
|
||||
} from '../core/vite-plugins';
|
||||
import { getInternalConfig } from '../core/utils/getInternalConfig';
|
||||
import { InlineConfig } from '../core/types';
|
||||
|
||||
/**
|
||||
* Vite plugin that configures Vitest with everything required to test a WXT extension, based on the `<root>/wxt.config.ts`
|
||||
*
|
||||
* ```ts
|
||||
* // vitest.config.ts
|
||||
* import { defineConfig } from 'vitest/config';
|
||||
* import { AutoImport } from 'wxt/testing';
|
||||
*
|
||||
* export default defineConfig({
|
||||
* plugins: [AutoImport()],
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @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 getInternalConfig(inlineConfig ?? {}, 'serve').then((config) => [
|
||||
webextensionPolyfillAlias(config),
|
||||
unimport(config),
|
||||
globals(config),
|
||||
download(config),
|
||||
tsconfigPaths(config),
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user