From 2bd7e996f64f2f4d52eb9c6b33ff3ff2814f776b Mon Sep 17 00:00:00 2001 From: Daniel Izdebski Date: Sun, 3 Dec 2023 04:41:50 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=A6=EF=B8=8F=20chore:=20Add=20example?= =?UTF-8?q?=20project=20(#1028)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/new-dawn/.env | 2 + examples/new-dawn/README.md | 63 ++++++++++++++++ examples/new-dawn/environment.d.ts | 10 +++ examples/new-dawn/package.json | 25 +++++++ examples/new-dawn/playwright.config.ts | 35 +++++++++ examples/new-dawn/test/advancedFixture.ts | 39 ++++++++++ examples/new-dawn/test/e2e/01_basic.spec.ts | 19 +++++ examples/new-dawn/test/e2e/02_simple.spec.ts | 42 +++++++++++ .../new-dawn/test/e2e/03_advanced.spec.ts | 41 ++++++++++ examples/new-dawn/test/simpleFixture.ts | 44 +++++++++++ .../new-dawn/test/wallet-setup/basic.setup.ts | 10 +++ .../test/wallet-setup/connected.setup.ts | 24 ++++++ examples/new-dawn/tsconfig.json | 14 ++++ package.json | 6 +- pnpm-lock.yaml | 75 +++++++++++++++---- 15 files changed, 431 insertions(+), 18 deletions(-) create mode 100644 examples/new-dawn/.env create mode 100644 examples/new-dawn/README.md create mode 100644 examples/new-dawn/environment.d.ts create mode 100644 examples/new-dawn/package.json create mode 100644 examples/new-dawn/playwright.config.ts create mode 100644 examples/new-dawn/test/advancedFixture.ts create mode 100644 examples/new-dawn/test/e2e/01_basic.spec.ts create mode 100644 examples/new-dawn/test/e2e/02_simple.spec.ts create mode 100644 examples/new-dawn/test/e2e/03_advanced.spec.ts create mode 100644 examples/new-dawn/test/simpleFixture.ts create mode 100644 examples/new-dawn/test/wallet-setup/basic.setup.ts create mode 100644 examples/new-dawn/test/wallet-setup/connected.setup.ts create mode 100644 examples/new-dawn/tsconfig.json diff --git a/examples/new-dawn/.env b/examples/new-dawn/.env new file mode 100644 index 000000000..aedc2934b --- /dev/null +++ b/examples/new-dawn/.env @@ -0,0 +1,2 @@ +SEED_PHRASE="test test test test test test test test test test test junk" +WALLET_PASSWORD="SynpressIsAwesomeNow!!!" diff --git a/examples/new-dawn/README.md b/examples/new-dawn/README.md new file mode 100644 index 000000000..22592de21 --- /dev/null +++ b/examples/new-dawn/README.md @@ -0,0 +1,63 @@ +

+ Synpress: New Dawn +
+ ⭐ Example Project ⭐ +

+ +# 📖 Intro + +The New Dawn version of Synpress differs in one major way from all previous versions and all other similar Web3 tools: +- We set up the browser only once, and we cache it. Thanks to this, tests not only run faster, but it also allows to use **ALL FEATURES** of [Playwright](https://playwright.dev/), such as parallel testing 🚀 + +You can define how a browser should be set up yourself. You can find setup file examples [here](./test/wallet-setup). All setup files must have the following naming structure: `*.setup.{js,ts}`. + +Once you define a setup file, you can build a cache with our CLI. By default, the cache is built in a headed mode and utilizes the setup files from `test/wallet-setup` directory. +Try running it with the `--help` flag to see all available configuration options. + +Here's how to use it: +```bash +# Build cache in a headed mode: +synpress + +# Build cache in a headless mode: +synpress --headless +``` + +# 🧑‍💻 Usage + +1. Install dependencies: +```bash +pnpm install +``` + +2. Build cache with our CLI by using a script: +```bash +# You can either build cache in a headed mode: +pnpm run build:cache + +# Or in a headless mode: +pnpm run build:cache:headless +``` + +3. Run Playwright tests as you would normally do: +```bash +# Use one of our scripts: +pnpm run test:e2e:headful +pnpm run test:e2e:headless +pnpm run test:e2e:headless:ui + +# Or use Playwright directly: +playwright test +HEADLESS=true playwright test +HEADLESS=true playwright test --ui +``` + +### ⚠️ Important note ⚠️ + +Currently, tests are triggered in a headed mode by default. Add `HEADLESS=true` to run them in a headless mode. + +This behavior will change soon! 🫡 + +# 🤔 Still want more? + +If you need more than this example project, check out our tests for MetaMask [here](../../wallets/metamask/test/e2e). diff --git a/examples/new-dawn/environment.d.ts b/examples/new-dawn/environment.d.ts new file mode 100644 index 000000000..47b50a901 --- /dev/null +++ b/examples/new-dawn/environment.d.ts @@ -0,0 +1,10 @@ +declare global { + namespace NodeJS { + interface ProcessEnv { + SEED_PHRASE: string + WALLET_PASSWORD: string + } + } +} + +export {} diff --git a/examples/new-dawn/package.json b/examples/new-dawn/package.json new file mode 100644 index 000000000..bbd0451d7 --- /dev/null +++ b/examples/new-dawn/package.json @@ -0,0 +1,25 @@ +{ + "name": "example-new-dawn", + "private": true, + "type": "module", + "scripts": { + "build:cache": "synpress", + "build:cache:force": "synpress --force", + "build:cache:headless": "synpress --headless", + "serve:test-dapp": "serve node_modules/@metamask/test-dapp/dist -p 12345", + "test:e2e:headful": "playwright test", + "test:e2e:headless": "HEADLESS=true playwright test", + "test:e2e:headless:ui": "HEADLESS=true playwright test --ui" + }, + "dependencies": { + "@playwright/test": "1.40.0", + "@synthetixio/synpress": "workspace:*", + "dotenv": "16.3.1" + }, + "devDependencies": { + "@metamask/test-dapp": "8.0.0", + "@types/node": "20.10.2", + "serve": "14.2.1", + "typescript": "5.3.2" + } +} diff --git a/examples/new-dawn/playwright.config.ts b/examples/new-dawn/playwright.config.ts new file mode 100644 index 000000000..dea88e1f7 --- /dev/null +++ b/examples/new-dawn/playwright.config.ts @@ -0,0 +1,35 @@ +import { defineConfig, devices } from '@playwright/test' + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + // Look for test files in the "test/e2e" directory, relative to this configuration file. + testDir: './test/e2e', + + // Run all tests in parallel. + fullyParallel: true, + + // Use half of the number of logical CPU cores for running tests in parallel. + workers: undefined, + + use: { + // We are using locally deployed MetaMask Test Dapp. + baseURL: 'http://localhost:12345' + }, + + // Synpress currently only supports Chromium, however, this will change in the future. + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] } + } + ], + + // Serve MetaMask Test Dapp locally before starting the tests. + webServer: { + command: 'pnpm run serve:test-dapp', + url: 'http://localhost:12345', + reuseExistingServer: true + } +}) diff --git a/examples/new-dawn/test/advancedFixture.ts b/examples/new-dawn/test/advancedFixture.ts new file mode 100644 index 000000000..3f61f9056 --- /dev/null +++ b/examples/new-dawn/test/advancedFixture.ts @@ -0,0 +1,39 @@ +import { test as base } from './simpleFixture' + +/** + * This fixture is further built upon the `simpleFixture`. + * It will serve as a foundation for the tests in the `03_advanced.spec.ts` file. + * + * You can read more about Playwright fixtures here: https://playwright.dev/docs/test-fixtures + */ +export const test = base.extend<{ + deployToken: () => Promise + deployPiggyBank: () => Promise +}>({ + deployToken: async ({ page, metamask }, use) => { + await use(async () => { + // We want to make sure we are connected to the local Anvil node. + await expect(page.locator('#network')).toHaveText('0x53a') + + await expect(page.locator('#tokenAddresses')).toBeEmpty() + await page.locator('#createToken').click() + + await metamask.confirmTransaction() + }) + }, + deployPiggyBank: async ({ page, metamask }, use) => { + await use(async () => { + // We want to make sure we are connected to the local Anvil node. + await expect(page.locator('#network')).toHaveText('0x53a') + + await expect(page.locator('#contractStatus')).toHaveText('Not clicked') + + await page.locator('#deployButton').click() + await metamask.confirmTransaction() + + await expect(page.locator('#contractStatus')).toHaveText('Deployed') + }) + } +}) + +export const { expect, describe } = test diff --git a/examples/new-dawn/test/e2e/01_basic.spec.ts b/examples/new-dawn/test/e2e/01_basic.spec.ts new file mode 100644 index 000000000..d4143e9c5 --- /dev/null +++ b/examples/new-dawn/test/e2e/01_basic.spec.ts @@ -0,0 +1,19 @@ +import { MetaMask, testWithSynpress, unlockForFixture } from '@synthetixio/synpress' +import BasicSetup from '../wallet-setup/basic.setup' + +const test = testWithSynpress(BasicSetup, unlockForFixture) + +const { expect } = test + +test('should connect wallet to the MetaMask Test Dapp', async ({ context, page, extensionId }) => { + const metamask = new MetaMask(context, page, BasicSetup.walletPassword, extensionId) + + await page.goto('/') + + await page.locator('#connectButton').click() + await metamask.connectToDapp() + await expect(page.locator('#accounts')).toHaveText('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266') + + await page.locator('#getAccounts').click() + await expect(page.locator('#getAccountsResult')).toHaveText('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266') +}) diff --git a/examples/new-dawn/test/e2e/02_simple.spec.ts b/examples/new-dawn/test/e2e/02_simple.spec.ts new file mode 100644 index 000000000..03adc09ac --- /dev/null +++ b/examples/new-dawn/test/e2e/02_simple.spec.ts @@ -0,0 +1,42 @@ +import { expect, test } from '../simpleFixture' + +test('should confirm contract deployment', async ({ page, metamask, connectToAnvil }) => { + await connectToAnvil() + + await expect(page.locator('#tokenAddresses')).toBeEmpty() + await page.locator('#createToken').click() + + await metamask.confirmTransaction() + + await expect(page.locator('#tokenAddresses')).toHaveText('0x5FbDB2315678afecb367f032d93F642f64180aa3') +}) + +test('should confirm legacy transaction', async ({ page, metamask, connectToAnvil }) => { + await connectToAnvil() + + await page.locator('#sendButton').click() + + await metamask.confirmTransaction() +}) + +test('should confirm EIP-1559 transaction', async ({ page, metamask, connectToAnvil }) => { + await connectToAnvil() + + await page.locator('#sendEIP1559Button').click() + + await metamask.confirmTransaction() +}) + +test('should sign and verify EIP-712 message', async ({ page, metamask }) => { + await page.locator('#signTypedDataV4').click() + + await metamask.confirmSignature() + + await expect(page.locator('#signTypedDataV4Result')).toHaveText( + '0x1cf422c4a319c19ecb89c960e7c296810278fa2bef256c7e9419b285c8216c547b3371fa1ec3987ce08561d3ed779845393d8d3e4311376d0bc0846f37d1b2821c' + ) + + await page.locator('#signTypedDataV4Verify').click() + + await expect(page.locator('#signTypedDataV4VerifyResult')).toHaveText('0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266') +}) diff --git a/examples/new-dawn/test/e2e/03_advanced.spec.ts b/examples/new-dawn/test/e2e/03_advanced.spec.ts new file mode 100644 index 000000000..6affb6d2e --- /dev/null +++ b/examples/new-dawn/test/e2e/03_advanced.spec.ts @@ -0,0 +1,41 @@ +import { describe, expect, test } from '../advancedFixture' + +describe('Token', () => { + test('should confirm tokens transfer', async ({ page, metamask, connectToAnvil, deployToken }) => { + await connectToAnvil() + await deployToken() + + await page.locator('#transferTokens').click() + await metamask.confirmTransaction() + }) + + test('should approve tokens', async ({ page, metamask, connectToAnvil, deployToken }) => { + await connectToAnvil() + await deployToken() + + await page.locator('#approveTokens').click() + await metamask.approvePermission() + }) +}) + +describe('Piggy Bank', () => { + test('should deposit and then withdraw ETH from the contract', async ({ + page, + metamask, + connectToAnvil, + deployPiggyBank + }) => { + await connectToAnvil() + await deployPiggyBank() + + await page.locator('#depositButton').click() + await metamask.confirmTransaction() + + await expect(page.locator('#contractStatus')).toHaveText('Deposit completed') + + await page.locator('#withdrawButton').click() + await metamask.confirmTransaction() + + await expect(page.locator('#contractStatus')).toHaveText('Withdrawn') + }) +}) diff --git a/examples/new-dawn/test/simpleFixture.ts b/examples/new-dawn/test/simpleFixture.ts new file mode 100644 index 000000000..758b6fca0 --- /dev/null +++ b/examples/new-dawn/test/simpleFixture.ts @@ -0,0 +1,44 @@ +import { MetaMask, testWithSynpress, unlockForFixture } from '@synthetixio/synpress' +import ConnectedSetup from './wallet-setup/connected.setup' + +/** + * We're creating a fixture that will serve as a foundation for tests in the `02_simple.spec.ts` file. + * + * You can read more about Playwright fixtures here: https://playwright.dev/docs/test-fixtures + */ +export const test = testWithSynpress(ConnectedSetup, unlockForFixture).extend<{ + metamask: MetaMask + connectToAnvil: () => Promise +}>({ + metamask: async ({ context, metamaskPage, extensionId }, use) => { + const metamask = new MetaMask(context, metamaskPage, ConnectedSetup.walletPassword, extensionId) + + await use(metamask) + }, + page: async ({ page }, use) => { + /** + * Refers to the home page of the locally hosted MetaMask Test Dapp. + * + * See: https://playwright.dev/docs/api/class-testoptions#test-options-base-url + */ + await page.goto('/') + + await use(page) + }, + connectToAnvil: async ({ metamask, createAnvilNode }, use) => { + await use(async () => { + const { rpcUrl, chainId } = await createAnvilNode({ + chainId: 1338 + }) + + await metamask.addNetwork({ + name: 'Local Anvil Network', + rpcUrl, + chainId, + symbol: 'ETH' + }) + }) + } +}) + +export const { expect } = test diff --git a/examples/new-dawn/test/wallet-setup/basic.setup.ts b/examples/new-dawn/test/wallet-setup/basic.setup.ts new file mode 100644 index 000000000..2886b28e1 --- /dev/null +++ b/examples/new-dawn/test/wallet-setup/basic.setup.ts @@ -0,0 +1,10 @@ +import { MetaMask, defineWalletSetup } from '@synthetixio/synpress' + +const SEED_PHRASE = 'test test test test test test test test test test test junk' +const PASSWORD = 'SynpressIsAwesomeNow!!!' + +export default defineWalletSetup(PASSWORD, async (context, walletPage) => { + const metamask = new MetaMask(context, walletPage, PASSWORD) + + await metamask.importWallet(SEED_PHRASE) +}) diff --git a/examples/new-dawn/test/wallet-setup/connected.setup.ts b/examples/new-dawn/test/wallet-setup/connected.setup.ts new file mode 100644 index 000000000..a2ed3b4ef --- /dev/null +++ b/examples/new-dawn/test/wallet-setup/connected.setup.ts @@ -0,0 +1,24 @@ +import { MetaMask, defineWalletSetup, getExtensionId } from '@synthetixio/synpress' +import 'dotenv/config' + +const SEED_PHRASE = process.env.SEED_PHRASE +const PASSWORD = process.env.WALLET_PASSWORD + +export default defineWalletSetup(PASSWORD, async (context, walletPage) => { + // This is a workaround for the fact that the MetaMask extension ID changes. + // This workaround won't be needed in the near future! 😁 + const extensionId = await getExtensionId(context, 'MetaMask') + + const metamask = new MetaMask(context, walletPage, PASSWORD, extensionId) + + await metamask.importWallet(SEED_PHRASE) + + const page = await context.newPage() + + // Go to a locally hosted MetaMask Test Dapp. + await page.goto('http://localhost:12345') + + await page.locator('#connectButton').click() + + await metamask.connectToDapp() +}) diff --git a/examples/new-dawn/tsconfig.json b/examples/new-dawn/tsconfig.json new file mode 100644 index 000000000..ae8e7d4dc --- /dev/null +++ b/examples/new-dawn/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "rootDir": "test", + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true + }, + "include": ["test"], + "files": ["environment.d.ts"] +} diff --git a/package.json b/package.json index 236d75782..abbfbae3f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "private": true, "scripts": { "build": "turbo build", - "build:cache": "turbo build:cache", + "build:cache": "turbo build:cache --filter=@synthetixio/synpress-metamask", "format": "biome format . --write", "format:check": "biome format . --error-on-warnings", "preinstall": "npx only-allow pnpm", @@ -14,8 +14,8 @@ "sort-package-json": "sort-package-json 'package.json' '{packages,wallets,examples}/*/package.json'", "sort-package-json:check": "sort-package-json 'package.json' '{packages,wallets,examples}/*/package.json' --check", "test": "turbo test", - "test:e2e:headful": "turbo test:e2e:headful", - "test:e2e:headless": "turbo test:e2e:headless" + "test:e2e:headful": "turbo test:e2e:headful --filter=@synthetixio/synpress-metamask", + "test:e2e:headless": "turbo test:e2e:headless --filter=@synthetixio/synpress-metamask" }, "lint-staged": { "package.json": "sort-package-json" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c4540230e..3f8fe1ef8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,31 @@ importers: specifier: ^3.12.10 version: 3.12.10 + examples/new-dawn: + dependencies: + '@playwright/test': + specifier: 1.40.0 + version: 1.40.0 + '@synthetixio/synpress': + specifier: workspace:* + version: link:../../release + dotenv: + specifier: 16.3.1 + version: 16.3.1 + devDependencies: + '@metamask/test-dapp': + specifier: 8.0.0 + version: 8.0.0 + '@types/node': + specifier: 20.10.2 + version: 20.10.2 + serve: + specifier: 14.2.1 + version: 14.2.1 + typescript: + specifier: 5.3.2 + version: 5.3.2 + packages/core: dependencies: axios: @@ -1008,7 +1033,7 @@ packages: resolution: {integrity: sha512-c0hrgAOVYr21EX8J0jBMXGLMgJqVf/v6yxi0dLaJboW9aQPh16Id+z6w2Tx1hm+piJOLv8xPfVKZCLfjPw/IMQ==} dependencies: '@types/jsonfile': 6.1.2 - '@types/node': 20.8.0 + '@types/node': 20.10.2 dev: true /@types/gradient-string@1.1.4: @@ -1028,13 +1053,13 @@ packages: /@types/jsonfile@6.1.2: resolution: {integrity: sha512-8t92P+oeW4d/CRQfJaSqEwXujrhH4OEeHRjGU3v1Q8mUS8GPF3yiX26sw4svv6faL2HfBtGTe2xWIoVgN3dy9w==} dependencies: - '@types/node': 20.8.0 + '@types/node': 20.10.2 dev: true /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 20.8.0 + '@types/node': 20.10.2 dev: false /@types/ms@0.7.32: @@ -1045,25 +1070,31 @@ packages: resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} dev: false + /@types/node@20.10.2: + resolution: {integrity: sha512-37MXfxkb0vuIlRKHNxwCkb60PNBpR94u4efQuN4JgIAm66zfCDXGSAFCef9XUWFovX2R1ok6Z7MHhtdVXXkkIw==} + dependencies: + undici-types: 5.26.5 + /@types/node@20.8.0: resolution: {integrity: sha512-LzcWltT83s1bthcvjBmiBvGJiiUe84NWRHkw+ZV6Fr41z2FbIzvc815dk2nQ3RAKMuN2fkenM/z3Xv2QzEpYxQ==} + dev: true /@types/readdir-glob@1.1.2: resolution: {integrity: sha512-vwAYrNN/8yhp/FJRU6HUSD0yk6xfoOS8HrZa8ZL7j+X8hJpaC1hTcAiXX2IxaAkkvrz9mLyoEhYZTE3cEYvA9Q==} dependencies: - '@types/node': 20.8.0 + '@types/node': 20.10.2 dev: true /@types/responselike@1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} dependencies: - '@types/node': 20.8.0 + '@types/node': 20.10.2 dev: false /@types/set-cookie-parser@2.4.4: resolution: {integrity: sha512-xCfTC/eL/GmvMC24b42qJpYSTdCIBwWcfskDF80ztXtnU6pKXyvuZP2EConb2K9ps0s7gMhCa0P1foy7wiItMA==} dependencies: - '@types/node': 20.8.0 + '@types/node': 20.10.2 dev: true /@types/tinycolor2@1.4.5: @@ -1072,13 +1103,13 @@ packages: /@types/unzipper@0.10.7: resolution: {integrity: sha512-1yZanW3LWgY4wA6x0MyIkyI5rGILLHjXWAvvuz+xF2JzqBLG26ySL+VrSgjz9EWIYLv+icqv5RPW6FN4BJmsHw==} dependencies: - '@types/node': 20.8.0 + '@types/node': 20.10.2 dev: true /@types/ws@8.5.5: resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} dependencies: - '@types/node': 20.8.0 + '@types/node': 20.10.2 dev: false /@viem/anvil@0.0.6: @@ -1898,6 +1929,11 @@ packages: dependencies: path-type: 4.0.0 + /dotenv@16.3.1: + resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + engines: {node: '>=12'} + dev: false + /download@8.0.0: resolution: {integrity: sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA==} engines: {node: '>=10'} @@ -4187,6 +4223,12 @@ packages: engines: {node: '>=14.17'} hasBin: true + /typescript@5.3.2: + resolution: {integrity: sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + /ufo@1.3.1: resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==} dev: true @@ -4202,6 +4244,9 @@ packages: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} dev: false + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + /universalify@2.0.0: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} @@ -4298,7 +4343,7 @@ packages: - zod dev: false - /vite-node@0.34.6(@types/node@20.8.0): + /vite-node@0.34.6(@types/node@20.10.2): resolution: {integrity: sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==} engines: {node: '>=v14.18.0'} hasBin: true @@ -4308,7 +4353,7 @@ packages: mlly: 1.4.2 pathe: 1.1.1 picocolors: 1.0.0 - vite: 4.4.9(@types/node@20.8.0) + vite: 4.4.9(@types/node@20.10.2) transitivePeerDependencies: - '@types/node' - less @@ -4320,7 +4365,7 @@ packages: - terser dev: true - /vite@4.4.9(@types/node@20.8.0): + /vite@4.4.9(@types/node@20.10.2): resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -4348,7 +4393,7 @@ packages: terser: optional: true dependencies: - '@types/node': 20.8.0 + '@types/node': 20.10.2 esbuild: 0.18.20 postcss: 8.4.31 rollup: 3.29.2 @@ -4389,7 +4434,7 @@ packages: dependencies: '@types/chai': 4.3.6 '@types/chai-subset': 1.3.3 - '@types/node': 20.8.0 + '@types/node': 20.10.2 '@vitest/expect': 0.34.6 '@vitest/runner': 0.34.6 '@vitest/snapshot': 0.34.6 @@ -4408,8 +4453,8 @@ packages: strip-literal: 1.3.0 tinybench: 2.5.1 tinypool: 0.7.0 - vite: 4.4.9(@types/node@20.8.0) - vite-node: 0.34.6(@types/node@20.8.0) + vite: 4.4.9(@types/node@20.10.2) + vite-node: 0.34.6(@types/node@20.10.2) why-is-node-running: 2.2.2 transitivePeerDependencies: - less