From 26cb99752d06fc1fda0452af30f0585876a80358 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Wed, 8 Jul 2026 10:10:32 +0900 Subject: [PATCH] =?UTF-8?q?enhance(frontend/test):=20frontend=20e2e?= =?UTF-8?q?=E3=82=92Vitest=20Browser=20Mode=E3=81=AB=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devcontainer/init.sh | 2 +- .github/labeler.yml | 2 +- .github/workflows/check-spdx-license-id.yml | 1 - .github/workflows/test-frontend.yml | 39 +- .gitignore | 5 +- cypress.config.ts | 7 - cypress/e2e/basic.cy.ts | 265 ------- cypress/e2e/router.cy.ts | 35 - cypress/e2e/widgets.cy.ts | 76 -- cypress/fixtures/example.json | 5 - cypress/support/commands.ts | 67 -- cypress/support/e2e.ts | 34 - cypress/support/index.ts | 19 - cypress/tsconfig.json | 8 - package.json | 7 +- packages/frontend/package.json | 8 +- .../frontend/test/e2e/basic.browser.test.ts | 61 ++ .../frontend/test/e2e/browser-commands.ts | 268 +++++++ packages/frontend/test/e2e/commands.d.ts | 12 + .../frontend/test/e2e/router.browser.test.ts | 15 + packages/frontend/test/setup.e2e.ts | 26 + .../frontend/test/{init.ts => setup.unit.ts} | 0 .../test/{ => unit}/aiscript/api.test.ts | 0 .../test/{ => unit}/aiscript/common.test.ts | 0 .../test/{ => unit}/aiscript/ui.test.ts | 0 .../test/{ => unit}/autocomplete.test.ts | 0 .../frontend/test/{ => unit}/emoji.test.ts | 0 .../frontend/test/{ => unit}/home.test.ts | 0 .../frontend/test/{ => unit}/i18n.test.ts | 0 .../test/{ => unit}/intl-string.test.ts | 0 .../test/{ => unit}/is-birthday.test.ts | 0 .../{ => unit}/lib/nirax/fallbacks.test.ts | 0 .../test/{ => unit}/lib/nirax/fixture.ts | 0 .../{ => unit}/lib/nirax/navigation.test.ts | 0 .../test/{ => unit}/lib/nirax/resolve.test.ts | 0 .../frontend/test/{ => unit}/note.test.ts | 0 .../frontend/test/{ => unit}/scroll.test.ts | 0 .../frontend/test/{ => unit}/theme.test.ts | 0 .../test/{ => unit}/url-preview.test.ts | 0 packages/frontend/vite.config.ts | 17 - packages/frontend/vitest.config.e2e.ts | 28 + packages/frontend/vitest.config.unit.ts | 22 + pnpm-lock.yaml | 750 ++++-------------- 43 files changed, 612 insertions(+), 1167 deletions(-) delete mode 100644 cypress.config.ts delete mode 100644 cypress/e2e/basic.cy.ts delete mode 100644 cypress/e2e/router.cy.ts delete mode 100644 cypress/e2e/widgets.cy.ts delete mode 100644 cypress/fixtures/example.json delete mode 100644 cypress/support/commands.ts delete mode 100644 cypress/support/e2e.ts delete mode 100644 cypress/support/index.ts delete mode 100644 cypress/tsconfig.json create mode 100644 packages/frontend/test/e2e/basic.browser.test.ts create mode 100644 packages/frontend/test/e2e/browser-commands.ts create mode 100644 packages/frontend/test/e2e/commands.d.ts create mode 100644 packages/frontend/test/e2e/router.browser.test.ts create mode 100644 packages/frontend/test/setup.e2e.ts rename packages/frontend/test/{init.ts => setup.unit.ts} (100%) rename packages/frontend/test/{ => unit}/aiscript/api.test.ts (100%) rename packages/frontend/test/{ => unit}/aiscript/common.test.ts (100%) rename packages/frontend/test/{ => unit}/aiscript/ui.test.ts (100%) rename packages/frontend/test/{ => unit}/autocomplete.test.ts (100%) rename packages/frontend/test/{ => unit}/emoji.test.ts (100%) rename packages/frontend/test/{ => unit}/home.test.ts (100%) rename packages/frontend/test/{ => unit}/i18n.test.ts (100%) rename packages/frontend/test/{ => unit}/intl-string.test.ts (100%) rename packages/frontend/test/{ => unit}/is-birthday.test.ts (100%) rename packages/frontend/test/{ => unit}/lib/nirax/fallbacks.test.ts (100%) rename packages/frontend/test/{ => unit}/lib/nirax/fixture.ts (100%) rename packages/frontend/test/{ => unit}/lib/nirax/navigation.test.ts (100%) rename packages/frontend/test/{ => unit}/lib/nirax/resolve.test.ts (100%) rename packages/frontend/test/{ => unit}/note.test.ts (100%) rename packages/frontend/test/{ => unit}/scroll.test.ts (100%) rename packages/frontend/test/{ => unit}/theme.test.ts (100%) rename packages/frontend/test/{ => unit}/url-preview.test.ts (100%) create mode 100644 packages/frontend/vitest.config.e2e.ts create mode 100644 packages/frontend/vitest.config.unit.ts diff --git a/.devcontainer/init.sh b/.devcontainer/init.sh index 216292b082..12d622581b 100755 --- a/.devcontainer/init.sh +++ b/.devcontainer/init.sh @@ -12,4 +12,4 @@ pnpm install --frozen-lockfile cp .devcontainer/devcontainer.yml .config/default.yml pnpm build pnpm migrate -pnpm exec cypress install +pnpm --filter frontend exec playwright install --with-deps chromium diff --git a/.github/labeler.yml b/.github/labeler.yml index b64d726d65..78341fd6cb 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -16,7 +16,7 @@ 'packages/frontend:test': - any: - changed-files: - - any-glob-to-any-file: ['cypress/**/*'] + - any-glob-to-any-file: ['packages/frontend/test/**/*'] 'packages/sw': - any: diff --git a/.github/workflows/check-spdx-license-id.yml b/.github/workflows/check-spdx-license-id.yml index f75db131f0..d0cf6e3cf6 100644 --- a/.github/workflows/check-spdx-license-id.yml +++ b/.github/workflows/check-spdx-license-id.yml @@ -44,7 +44,6 @@ jobs: } directories=( - "cypress/e2e" "packages/backend/migration" "packages/backend/src" "packages/backend/test" diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml index 6e55760462..d63abe2f66 100644 --- a/.github/workflows/test-frontend.yml +++ b/.github/workflows/test-frontend.yml @@ -57,11 +57,6 @@ jobs: name: E2E tests (frontend) runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - browser: [chrome] - services: postgres: image: postgres:18 @@ -79,12 +74,6 @@ jobs: - uses: actions/checkout@v6.0.3 with: submodules: true - # https://github.com/cypress-io/cypress-docker-images/issues/150 - #- name: Install mplayer for FireFox - # run: sudo apt install mplayer -y - # if: ${{ matrix.browser == 'firefox' }} - #- uses: browser-actions/setup-firefox@latest - # if: ${{ matrix.browser == 'firefox' }} - name: Setup pnpm uses: pnpm/action-setup@v6.0.9 - name: Use Node.js @@ -97,29 +86,13 @@ jobs: run: cp .github/misskey/test.yml .config - name: Build run: pnpm build - # https://github.com/cypress-io/cypress/issues/4351#issuecomment-559489091 - - name: ALSA Env - run: echo -e 'pcm.!default {\n type hw\n card 0\n}\n\nctl.!default {\n type hw\n card 0\n}' > ~/.asoundrc - # XXX: This tries reinstalling Cypress if the binary is not cached - # Remove this when the cache issue is fixed - - name: Cypress install - run: pnpm exec cypress install - - name: Cypress run - uses: cypress-io/github-action@v7.4.0 + - name: Playwright install + run: pnpm --filter frontend exec playwright install --with-deps chromium + - name: Vitest Browser E2E run + run: pnpm start-server-and-test start:test http://localhost:61812 "pnpm --filter frontend test:e2e" timeout-minutes: 15 - with: - install: false - start: pnpm start:test - wait-on: 'http://localhost:61812' - headed: true - browser: ${{ matrix.browser }} - uses: actions/upload-artifact@v7 if: failure() with: - name: ${{ matrix.browser }}-cypress-screenshots - path: cypress/screenshots - - uses: actions/upload-artifact@v7 - if: always() - with: - name: ${{ matrix.browser }}-cypress-videos - path: cypress/videos + name: vitest-browser-screenshots + path: packages/frontend/test/e2e/screenshots diff --git a/.gitignore b/.gitignore index ed1daaf489..6f6d674bf8 100644 --- a/.gitignore +++ b/.gitignore @@ -23,9 +23,8 @@ packages/sw/.yarn/cache # pnpm .pnpm-store -# Cypress -cypress/screenshots -cypress/videos +# Vitest Browser Mode +packages/frontend/test/e2e/screenshots # Coverage coverage diff --git a/cypress.config.ts b/cypress.config.ts deleted file mode 100644 index 361acaf6e5..0000000000 --- a/cypress.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from 'cypress' - -export default defineConfig({ - e2e: { - baseUrl: 'http://localhost:61812', - }, -}) diff --git a/cypress/e2e/basic.cy.ts b/cypress/e2e/basic.cy.ts deleted file mode 100644 index 4f2f700146..0000000000 --- a/cypress/e2e/basic.cy.ts +++ /dev/null @@ -1,265 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -describe('Before setup instance', () => { - beforeEach(() => { - cy.resetState(); - }); - - afterEach(() => { - // テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。 - // waitを入れることでそれを防止できる - cy.wait(1000); - }); - - it('successfully loads', () => { - cy.visitHome(); - }); - - it('setup instance', () => { - cy.visitHome(); - - cy.intercept('POST', '/api/admin/accounts/create').as('signup'); - - cy.get('[data-cy-admin-initial-password] input').type('example_password_please_change_this_or_you_will_get_hacked'); - cy.get('[data-cy-admin-username] input').type('admin'); - cy.get('[data-cy-admin-password] input').type('admin1234'); - cy.get('[data-cy-admin-ok]').click(); - - // なぜか動かない - //cy.wait('@signup').should('have.property', 'response.statusCode'); - cy.wait('@signup'); - - cy.intercept('POST', '/api/admin/update-meta').as('update-meta'); - - cy.get('[data-cy-next]').click(); - cy.get('[data-cy-server-name] input').type('Testskey'); - cy.get('[data-cy-server-setup-wizard-apply]').click(); - - cy.wait('@update-meta'); - }); -}); - -describe('After setup instance', () => { - beforeEach(() => { - cy.resetState(); - - // インスタンス初期セットアップ - cy.registerUser('admin', 'pass', true); - }); - - afterEach(() => { - // テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。 - // waitを入れることでそれを防止できる - cy.wait(1000); - }); - - it('successfully loads', () => { - cy.visitHome(); - }); - - it('signup', () => { - cy.visitHome(); - - cy.intercept('POST', '/api/signup').as('signup'); - - cy.get('[data-cy-signup]').click(); - cy.get('[data-cy-signup-rules-continue]').should('be.disabled'); - cy.get('[data-cy-signup-rules-notes-agree] [data-cy-switch-toggle]').click(); - cy.get('[data-cy-modal-dialog-ok]').click(); - cy.get('[data-cy-signup-rules-continue]').should('not.be.disabled'); - cy.get('[data-cy-signup-rules-continue]').click(); - - cy.get('[data-cy-signup-submit]').should('be.disabled'); - cy.get('[data-cy-signup-username] input').type('alice'); - cy.get('[data-cy-signup-submit]').should('be.disabled'); - cy.get('[data-cy-signup-password] input').type('alice1234'); - cy.get('[data-cy-signup-submit]').should('be.disabled'); - cy.get('[data-cy-signup-password-retype] input').type('alice1234'); - cy.get('[data-cy-signup-submit]').should('be.disabled'); - cy.get('[data-cy-signup-invitation-code] input').type('test-invitation-code'); - cy.get('[data-cy-signup-submit]').should('not.be.disabled'); - cy.get('[data-cy-signup-submit]').click(); - - cy.wait('@signup'); - }); - - it('signup with duplicated username', () => { - cy.registerUser('alice', 'alice1234'); - - cy.visitHome(); - - // ユーザー名が重複している場合の挙動確認 - cy.get('[data-cy-signup]').click(); - cy.get('[data-cy-signup-rules-continue]').should('be.disabled'); - cy.get('[data-cy-signup-rules-notes-agree] [data-cy-switch-toggle]').click(); - cy.get('[data-cy-modal-dialog-ok]').click(); - cy.get('[data-cy-signup-rules-continue]').should('not.be.disabled'); - cy.get('[data-cy-signup-rules-continue]').click(); - - cy.get('[data-cy-signup-username] input').type('alice'); - cy.get('[data-cy-signup-password] input').type('alice1234'); - cy.get('[data-cy-signup-password-retype] input').type('alice1234'); - cy.get('[data-cy-signup-submit]').should('be.disabled'); - }); -}); - -describe('After user signup', () => { - beforeEach(() => { - cy.resetState(); - - // インスタンス初期セットアップ - cy.registerUser('admin', 'pass', true); - - // ユーザー作成 - cy.registerUser('alice', 'alice1234'); - }); - - afterEach(() => { - // テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。 - // waitを入れることでそれを防止できる - cy.wait(1000); - }); - - it('successfully loads', () => { - cy.visitHome(); - }); - - it('signin', () => { - cy.visitHome(); - - cy.intercept('POST', '/api/signin-flow').as('signin'); - - cy.get('[data-cy-signin]').click(); - - cy.get('[data-cy-signin-page-input]').should('be.visible', { timeout: 1000 }); - // Enterキーで続行できるかの確認も兼ねる - cy.get('[data-cy-signin-username] input').type('alice{enter}'); - - cy.get('[data-cy-signin-page-password]').should('be.visible', { timeout: 10000 }); - // Enterキーで続行できるかの確認も兼ねる - cy.get('[data-cy-signin-password] input').type('alice1234{enter}'); - - cy.wait('@signin'); - }); - - it('suspend', function() { - cy.request('POST', '/api/admin/suspend-user', { - i: this.admin.token, - userId: this.alice.id, - }); - - cy.visitHome(); - - cy.get('[data-cy-signin]').click(); - - cy.get('[data-cy-signin-page-input]').should('be.visible', { timeout: 1000 }); - cy.get('[data-cy-signin-username] input').type('alice{enter}'); - - // TODO: cypressにブラウザの言語指定できる機能が実装され次第英語のみテストするようにする - cy.contains(/アカウントが凍結されています|This account has been suspended due to/gi); - }); -}); - -describe('After user signed in', () => { - beforeEach(() => { - cy.resetState(); - - // インスタンス初期セットアップ - cy.registerUser('admin', 'pass', true); - - // ユーザー作成 - cy.registerUser('alice', 'alice1234'); - - cy.login('alice', 'alice1234'); - }); - - afterEach(() => { - // テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。 - // waitを入れることでそれを防止できる - cy.wait(1000); - }); - - it('successfully loads', () => { - // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする - cy.get('[data-cy-user-setup-continue]', { timeout: 30000 }).should('be.visible'); - }); - - it('account setup wizard', () => { - // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする - cy.get('[data-cy-user-setup-continue]', { timeout: 30000 }).click(); - - cy.get('[data-cy-user-setup-user-name] input').type('ありす'); - cy.get('[data-cy-user-setup-user-description] textarea').type('ほげ'); - // TODO: アイコン設定テスト - - cy.get('[data-cy-user-setup-continue]').click(); - - // プライバシー設定 - - cy.get('[data-cy-user-setup-continue]').click(); - - // フォローはスキップ - - cy.get('[data-cy-user-setup-continue]').click(); - - // プッシュ通知設定はスキップ - - cy.get('[data-cy-user-setup-continue]').click(); - - cy.get('[data-cy-user-setup-continue]').click(); - }); -}); - -describe('After user setup', () => { - beforeEach(() => { - cy.resetState(); - - // インスタンス初期セットアップ - cy.registerUser('admin', 'pass', true); - - // ユーザー作成 - cy.registerUser('alice', 'alice1234'); - - cy.login('alice', 'alice1234'); - - // アカウント初期設定ウィザード - // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする - cy.get('[data-cy-user-setup] [data-cy-modal-window-close]', { timeout: 30000 }).click(); - cy.get('[data-cy-modal-dialog-ok]').click(); - }); - - afterEach(() => { - // テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。 - // waitを入れることでそれを防止できる - cy.wait(1000); - }); - - it('note', () => { - cy.get('[data-cy-open-post-form]').should('be.visible'); - cy.get('[data-cy-open-post-form]').click(); - cy.get('[data-cy-post-form-text]').type('Hello, Misskey!'); - cy.get('[data-cy-open-post-form-submit]').click(); - - cy.contains('Hello, Misskey!', { timeout: 15000 }); - }); - - it('open note form with hotkey', () => { - // Wait until the page loads - cy.get('[data-cy-open-post-form]').should('be.visible'); - // Use trigger() to give different `code` to test if hotkeys also work on non-QWERTY keyboards. - cy.document().trigger("keydown", { eventConstructor: 'KeyboardEvent', key: "n", code: "KeyL" }); - // See if the form is opened - cy.get('[data-cy-post-form-text]').should('be.visible'); - // Close it - cy.focused().trigger("keydown", { eventConstructor: 'KeyboardEvent', key: "Escape", code: "Escape" }); - // See if the form is closed - cy.get('[data-cy-post-form-text]').should('not.be.visible'); - }); -}); - -// TODO: 投稿フォームの公開範囲指定のテスト -// TODO: 投稿フォームのファイル添付のテスト -// TODO: 投稿フォームのハッシュタグ保持フィールドのテスト diff --git a/cypress/e2e/router.cy.ts b/cypress/e2e/router.cy.ts deleted file mode 100644 index 8d8fb3af31..0000000000 --- a/cypress/e2e/router.cy.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -describe('Router transition', () => { - describe('Redirect', () => { - // サーバの初期化。ルートのテストに関しては各describeごとに1度だけ実行で十分だと思う(使いまわした方が早い) - before(() => { - cy.resetState(); - - // インスタンス初期セットアップ - cy.registerUser('admin', 'pass', true); - - // ユーザー作成 - cy.registerUser('alice', 'alice1234'); - - cy.login('alice', 'alice1234'); - - // アカウント初期設定ウィザード - // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする - cy.get('[data-cy-user-setup] [data-cy-modal-window-close]', { timeout: 30000 }).click(); - cy.wait(500); - cy.get('[data-cy-modal-dialog-ok]').click(); - }); - - it('redirect to user profile', () => { - // テストのためだけに用意されたリダイレクト用ルートに飛ぶ - cy.visit('/redirect-test'); - - // プロフィールページのURLであることを確認する - cy.url().should('include', '/@alice') - }); - }); -}); diff --git a/cypress/e2e/widgets.cy.ts b/cypress/e2e/widgets.cy.ts deleted file mode 100644 index 847801a69f..0000000000 --- a/cypress/e2e/widgets.cy.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -/* flaky -describe('After user signed in', () => { - beforeEach(() => { - cy.resetState(); - cy.viewport('macbook-16'); - - // インスタンス初期セットアップ - cy.registerUser('admin', 'pass', true); - - // ユーザー作成 - cy.registerUser('alice', 'alice1234'); - - cy.login('alice', 'alice1234'); - - // アカウント初期設定ウィザード - cy.get('[data-cy-user-setup] [data-cy-modal-window-close]').click(); - cy.get('[data-cy-modal-dialog-ok]').click(); - }); - - afterEach(() => { - // テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。 - // waitを入れることでそれを防止できる - cy.wait(1000); - }); - - it('widget edit toggle is visible', () => { - cy.get('[data-cy-widget-edit]').should('be.visible'); - }); - - it('widget select should be visible in edit mode', () => { - cy.get('[data-cy-widget-edit]').click(); - cy.get('[data-cy-widget-select]').should('be.visible'); - }); - - it('first widget should be removed', () => { - cy.get('[data-cy-widget-edit]').click(); - cy.get('[data-cy-customize-container]:first-child [data-cy-customize-container-remove]._button').click(); - cy.get('[data-cy-customize-container]').should('have.length', 2); - }); - - function buildWidgetTest(widgetName) { - it(`${widgetName} widget should get added`, () => { - cy.get('[data-cy-widget-edit]').click(); - cy.get('[data-cy-widget-select] select').select(widgetName, { force: true }); - cy.get('[data-cy-bg]._modalBg[data-cy-transparent]').click({ multiple: true, force: true }); - cy.get('[data-cy-widget-add]').click({ force: true }); - cy.get(`[data-cy-mkw-${widgetName}]`).should('exist'); - }); - } - - buildWidgetTest('memo'); - buildWidgetTest('notifications'); - buildWidgetTest('timeline'); - buildWidgetTest('calendar'); - buildWidgetTest('rss'); - buildWidgetTest('trends'); - buildWidgetTest('clock'); - buildWidgetTest('activity'); - buildWidgetTest('photos'); - buildWidgetTest('digitalClock'); - buildWidgetTest('federation'); - buildWidgetTest('postForm'); - buildWidgetTest('slideshow'); - buildWidgetTest('serverMetric'); - buildWidgetTest('onlineUsers'); - buildWidgetTest('jobQueue'); - buildWidgetTest('button'); - buildWidgetTest('aiscript'); - buildWidgetTest('aichan'); -}); -*/ diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json deleted file mode 100644 index 02e4254378..0000000000 --- a/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts deleted file mode 100644 index 197ff963ac..0000000000 --- a/cypress/support/commands.ts +++ /dev/null @@ -1,67 +0,0 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add('login', (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) - -Cypress.Commands.add('visitHome', () => { - cy.visit('/'); - cy.get('button', { timeout: 30000 }).should('be.visible'); -}) - -Cypress.Commands.add('resetState', () => { - // iframe.contentWindow.indexedDB.deleteDatabase() がchromeのバグで使用できないため、indexedDBを無効化している。 - // see https://github.com/misskey-dev/misskey/issues/13605#issuecomment-2053652123 - /* - cy.window().then(win => { - win.indexedDB.deleteDatabase('keyval-store'); - }); - */ - cy.request('POST', '/api/reset-db', {}).as('reset'); - cy.get('@reset').its('status').should('equal', 204); - cy.reload(true); -}); - -Cypress.Commands.add('registerUser', (username, password, isAdmin = false) => { - const route = isAdmin ? '/api/admin/accounts/create' : '/api/signup'; - - cy.request('POST', route, { - username: username, - password: password, - ...(isAdmin ? { setupPassword: 'example_password_please_change_this_or_you_will_get_hacked' } : {}), - }).its('body').as(username); -}); - -Cypress.Commands.add('login', (username, password) => { - cy.visitHome(); - - cy.intercept('POST', '/api/signin-flow').as('signin'); - - cy.get('[data-cy-signin]').click(); - cy.get('[data-cy-signin-page-input]').should('be.visible', { timeout: 1000 }); - cy.get('[data-cy-signin-username] input').type(`${username}{enter}`); - cy.get('[data-cy-signin-page-password]').should('be.visible', { timeout: 10000 }); - cy.get('[data-cy-signin-password] input').type(`${password}{enter}`); - - cy.wait('@signin').as('signedIn'); -}); diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts deleted file mode 100644 index 827a326d18..0000000000 --- a/cypress/support/e2e.ts +++ /dev/null @@ -1,34 +0,0 @@ -// *********************************************************** -// This example support/index.js is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands' - -// Alternatively you can use CommonJS syntax: -// require('./commands') - -Cypress.on('uncaught:exception', (err, runnable) => { - if ([ - 'The source image cannot be decoded', - - // Chrome - 'ResizeObserver loop limit exceeded', - - // Firefox - 'ResizeObserver loop completed with undelivered notifications', - ].some(msg => err.message.includes(msg))) { - return false; - } -}); diff --git a/cypress/support/index.ts b/cypress/support/index.ts deleted file mode 100644 index c1bed21979..0000000000 --- a/cypress/support/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -declare global { - namespace Cypress { - interface Chainable { - login(username: string, password: string): Chainable; - - registerUser( - username: string, - password: string, - isAdmin?: boolean - ): Chainable; - - resetState(): Chainable; - - visitHome(): Chainable; - } - } -} - -export {} diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json deleted file mode 100644 index b91e34dc12..0000000000 --- a/cypress/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "lib": ["dom"], - "target": "esnext", - "types": ["cypress", "node"] - }, - "include": ["./**/*.ts"] -} diff --git a/package.json b/package.json index f710f031dd..cf02c92c79 100644 --- a/package.json +++ b/package.json @@ -41,10 +41,8 @@ "dev": "node scripts/dev.mjs", "check-dts": "node scripts/check-dts.mjs", "lint": "pnpm --no-bail -r lint && pnpm check-dts", - "cy:open": "pnpm cypress open --config-file=cypress.config.ts", - "cy:run": "pnpm cypress run", - "e2e": "pnpm start-server-and-test start:test http://localhost:61812 cy:run", - "e2e-dev-container": "ncp ./.config/cypress-devcontainer.yml ./.config/test.yml && pnpm start-server-and-test start:test http://localhost:61812 cy:run", + "e2e": "pnpm start-server-and-test start:test http://localhost:61812 \"pnpm --filter frontend test:e2e\"", + "e2e-dev-container": "ncp ./.config/cypress-devcontainer.yml ./.config/test.yml && pnpm start-server-and-test start:test http://localhost:61812 \"pnpm --filter frontend test:e2e\"", "backend-unit-test": "cd packages/backend && pnpm test", "backend-unit-test-and-coverage": "cd packages/backend && pnpm test-and-coverage", "test": "pnpm -r test", @@ -68,7 +66,6 @@ "@typescript-eslint/parser": "8.62.0", "@typescript/native-preview": "7.0.0-dev.20260426.1", "cross-env": "10.1.0", - "cypress": "15.18.0", "eslint": "9.39.4", "globals": "17.7.0", "ncp": "2.0.0", diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 67a7062285..d48e47c49f 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -9,8 +9,9 @@ "build-storybook-pre": "(tsgo -p .storybook || echo done.) && node .storybook/generate.js && node .storybook/preload-locale.js && node .storybook/preload-theme.js", "build-storybook": "pnpm build-storybook-pre && storybook build --webpack-stats-json storybook-static", "chromatic": "chromatic", - "test": "vitest --run --globals", - "test-and-coverage": "vitest --run --coverage --globals", + "test": "vitest --run --globals --config vitest.config.unit.ts", + "test-and-coverage": "vitest --run --coverage --globals --config vitest.config.unit.ts", + "test:e2e": "vitest --run --globals --config vitest.config.e2e.ts", "typecheck": "vue-tsc --noEmit", "eslint": "eslint --quiet \"src/**/*.{ts,vue}\"", "lint": "pnpm typecheck && pnpm eslint" @@ -102,6 +103,8 @@ "@types/textarea-caret": "3.0.4", "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", + "@vitest/browser": "4.1.9", + "@vitest/browser-playwright": "4.1.9", "@typescript-eslint/eslint-plugin": "8.62.0", "@typescript-eslint/parser": "8.62.0", "@vitest/coverage-v8": "4.1.9", @@ -120,6 +123,7 @@ "msw-storybook-addon": "2.0.7", "nodemon": "3.1.14", "oxc-walker": "1.0.0", + "playwright": "1.56.0", "prettier": "3.9.1", "react": "19.2.7", "react-dom": "19.2.7", diff --git a/packages/frontend/test/e2e/basic.browser.test.ts b/packages/frontend/test/e2e/basic.browser.test.ts new file mode 100644 index 0000000000..55846c9455 --- /dev/null +++ b/packages/frontend/test/e2e/basic.browser.test.ts @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { commands } from 'vitest/browser'; +import { describe, it } from 'vitest'; + +describe('Before setup instance', () => { + it('successfully loads', async () => { + await commands.runScenario('before-setup-loads'); + }); + + it('setup instance', async () => { + await commands.runScenario('setup-instance'); + }); +}); + +describe('After setup instance', () => { + it('successfully loads', async () => { + await commands.runScenario('after-setup-loads'); + }); + + it('signup', async () => { + await commands.runScenario('signup'); + }); + + it('signup with duplicated username', async () => { + await commands.runScenario('signup-duplicated'); + }); +}); + +describe('After user signup', () => { + it('signin', async () => { + await commands.runScenario('signin'); + }); + + it('suspend', async () => { + await commands.runScenario('suspend'); + }); +}); + +describe('After user signed in', () => { + it('successfully loads', async () => { + await commands.runScenario('after-signed-in-loads'); + }); + + it('account setup wizard', async () => { + await commands.runScenario('account-setup-wizard'); + }); +}); + +describe('After user setup', () => { + it('note', async () => { + await commands.runScenario('note'); + }); + + it('open note form with hotkey', async () => { + await commands.runScenario('open-note-form-with-hotkey'); + }); +}); diff --git a/packages/frontend/test/e2e/browser-commands.ts b/packages/frontend/test/e2e/browser-commands.ts new file mode 100644 index 0000000000..6847fd98cd --- /dev/null +++ b/packages/frontend/test/e2e/browser-commands.ts @@ -0,0 +1,268 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import type { APIRequestContext, Page } from 'playwright'; +import type { BrowserCommand } from 'vitest/node'; +import '@vitest/browser-playwright'; + +const BASE_URL = 'http://localhost:61812'; +const ADMIN_SETUP_PASSWORD = 'example_password_please_change_this_or_you_will_get_hacked'; + +interface RegisteredUser { + id: string; + token: string; +} + +async function assertOk(status: number, body: string, route: string): Promise { + if (status >= 200 && status < 300) return; + throw new Error(`${route} failed: status=${status} body=${body}`); +} + +async function resetState(request: APIRequestContext): Promise { + const response = await request.post(`${BASE_URL}/api/reset-db`); + await assertOk(response.status(), await response.text(), '/api/reset-db'); +} + +async function registerUser( + request: APIRequestContext, + username: string, + password: string, + isAdmin = false, +): Promise { + const route = isAdmin ? '/api/admin/accounts/create' : '/api/signup'; + const response = await request.post(`${BASE_URL}${route}`, { + data: { + username, + password, + ...(isAdmin ? { setupPassword: ADMIN_SETUP_PASSWORD } : {}), + }, + }); + await assertOk(response.status(), await response.text(), route); + return await response.json() as RegisteredUser; +} + +async function waitApiResponse(page: Page, path: string): Promise { + await page.waitForResponse((response) => { + return response.url().endsWith(path) && response.request().method() === 'POST'; + }, { timeout: 30_000 }); +} + +async function visitHome(page: Page): Promise { + await page.goto(`${BASE_URL}/`); + await page.locator('button').first().waitFor({ state: 'visible', timeout: 30_000 }); +} + +async function signInFromTopPage(page: Page, username: string, password: string): Promise { + await page.getByTestId('signin').click(); + await page.getByTestId('signin-page-input').waitFor({ state: 'visible', timeout: 10_000 }); + await page.locator('[data-cy-signin-username] input').fill(username); + await page.keyboard.press('Enter'); + await page.getByTestId('signin-page-password').waitFor({ state: 'visible', timeout: 10_000 }); + await page.locator('[data-cy-signin-password] input').fill(password); + const signinResponse = waitApiResponse(page, '/api/signin-flow'); + await page.keyboard.press('Enter'); + await signinResponse; +} + +async function dismissAccountSetupWizard(page: Page): Promise { + await page.locator('[data-cy-user-setup] [data-cy-modal-window-close]').click({ timeout: 30_000 }); + await page.getByTestId('modal-dialog-ok').click(); +} + +async function prepareAfterSetup(request: APIRequestContext): Promise { + await resetState(request); + await registerUser(request, 'admin', 'pass', true); +} + +async function prepareAfterSignup(page: Page, request: APIRequestContext): Promise { + await prepareAfterSetup(request); + return await registerUser(request, 'alice', 'alice1234'); +} + +async function prepareAfterSignedIn(page: Page, request: APIRequestContext): Promise { + await prepareAfterSignup(page, request); + await visitHome(page); + await signInFromTopPage(page, 'alice', 'alice1234'); +} + +async function prepareAfterUserSetup(page: Page, request: APIRequestContext): Promise { + await prepareAfterSignedIn(page, request); + await dismissAccountSetupWizard(page); +} + +async function runBeforeSetupLoads(page: Page): Promise { + await visitHome(page); +} + +async function runSetupInstance(page: Page): Promise { + await visitHome(page); + + await page.locator('[data-cy-admin-initial-password] input').fill(ADMIN_SETUP_PASSWORD); + await page.locator('[data-cy-admin-username] input').fill('admin'); + await page.locator('[data-cy-admin-password] input').fill('admin1234'); + const signupResponse = waitApiResponse(page, '/api/admin/accounts/create'); + await page.getByTestId('admin-ok').click(); + await signupResponse; + + await page.getByTestId('next').click(); + await page.locator('[data-cy-server-name] input').fill('Testskey'); + const updateMetaResponse = waitApiResponse(page, '/api/admin/update-meta'); + await page.getByTestId('server-setup-wizard-apply').click(); + await updateMetaResponse; +} + +async function runAfterSetupLoads(page: Page, request: APIRequestContext): Promise { + await prepareAfterSetup(request); + await visitHome(page); +} + +async function runSignup(page: Page, request: APIRequestContext): Promise { + await prepareAfterSetup(request); + await visitHome(page); + + await page.getByTestId('signup').click(); + await page.getByTestId('signup-rules-continue').waitFor({ state: 'visible' }); + if (!await page.getByTestId('signup-rules-continue').isDisabled()) { + throw new Error('signup-rules-continue should be disabled before agreement'); + } + await page.locator('[data-cy-signup-rules-notes-agree] [data-cy-switch-toggle]').click(); + await page.getByTestId('modal-dialog-ok').click(); + await page.getByTestId('signup-rules-continue').click(); + + await page.locator('[data-cy-signup-username] input').fill('alice'); + await page.locator('[data-cy-signup-password] input').fill('alice1234'); + await page.locator('[data-cy-signup-password-retype] input').fill('alice1234'); + await page.locator('[data-cy-signup-invitation-code] input').fill('test-invitation-code'); + const signupResponse = waitApiResponse(page, '/api/signup'); + await page.getByTestId('signup-submit').click(); + await signupResponse; +} + +async function runSignupDuplicated(page: Page, request: APIRequestContext): Promise { + await prepareAfterSetup(request); + await registerUser(request, 'alice', 'alice1234'); + await visitHome(page); + + await page.getByTestId('signup').click(); + await page.locator('[data-cy-signup-rules-notes-agree] [data-cy-switch-toggle]').click(); + await page.getByTestId('modal-dialog-ok').click(); + await page.getByTestId('signup-rules-continue').click(); + await page.locator('[data-cy-signup-username] input').fill('alice'); + await page.locator('[data-cy-signup-password] input').fill('alice1234'); + await page.locator('[data-cy-signup-password-retype] input').fill('alice1234'); + if (!await page.getByTestId('signup-submit').isDisabled()) { + throw new Error('signup-submit should stay disabled for duplicated username'); + } +} + +async function runSignIn(page: Page, request: APIRequestContext): Promise { + await prepareAfterSignup(page, request); + await visitHome(page); + await signInFromTopPage(page, 'alice', 'alice1234'); +} + +async function runSuspend(page: Page, request: APIRequestContext): Promise { + await resetState(request); + const admin = await registerUser(request, 'admin', 'pass', true); + const alice = await registerUser(request, 'alice', 'alice1234'); + const suspendResponse = await request.post(`${BASE_URL}/api/admin/suspend-user`, { + data: { + i: admin.token, + userId: alice.id, + }, + }); + await assertOk(suspendResponse.status(), await suspendResponse.text(), '/api/admin/suspend-user'); + + await visitHome(page); + await page.getByTestId('signin').click(); + await page.getByTestId('signin-page-input').waitFor({ state: 'visible', timeout: 10_000 }); + await page.locator('[data-cy-signin-username] input').fill('alice'); + await page.keyboard.press('Enter'); + await page.getByText(/アカウントが凍結されています|This account has been suspended due to/).waitFor({ timeout: 10_000 }); +} + +async function runAfterSignedInLoads(page: Page, request: APIRequestContext): Promise { + await prepareAfterSignedIn(page, request); + await page.getByTestId('user-setup-continue').waitFor({ state: 'visible', timeout: 30_000 }); +} + +async function runAccountSetupWizard(page: Page, request: APIRequestContext): Promise { + await prepareAfterSignedIn(page, request); + await page.getByTestId('user-setup-continue').click({ timeout: 30_000 }); + await page.locator('[data-cy-user-setup-user-name] input').fill('ありす'); + await page.locator('[data-cy-user-setup-user-description] textarea').fill('ほげ'); + await page.getByTestId('user-setup-continue').click(); + await page.getByTestId('user-setup-continue').click(); + await page.getByTestId('user-setup-continue').click(); + await page.getByTestId('user-setup-continue').click(); + await page.getByTestId('user-setup-continue').click(); +} + +async function runCreateNote(page: Page, request: APIRequestContext): Promise { + await prepareAfterUserSetup(page, request); + await page.getByTestId('open-post-form').waitFor({ state: 'visible' }); + await page.getByTestId('open-post-form').click(); + await page.getByTestId('post-form-text').fill('Hello, Misskey!'); + await page.getByTestId('open-post-form-submit').click(); + await page.getByText('Hello, Misskey!').waitFor({ timeout: 15_000 }); +} + +async function runOpenNoteFormWithHotkey(page: Page, request: APIRequestContext): Promise { + await prepareAfterUserSetup(page, request); + await page.getByTestId('open-post-form').waitFor({ state: 'visible' }); + await page.evaluate(() => { + document.dispatchEvent(new KeyboardEvent('keydown', { + key: 'n', + code: 'KeyL', + bubbles: true, + })); + }); + await page.getByTestId('post-form-text').waitFor({ state: 'visible' }); + await page.keyboard.press('Escape'); + await page.getByTestId('post-form-text').waitFor({ state: 'hidden' }); +} + +async function runRedirectProfile(page: Page, request: APIRequestContext): Promise { + await prepareAfterUserSetup(page, request); + await page.goto(`${BASE_URL}/redirect-test`); + await page.waitForURL('**/@alice'); +} + +const scenarioHandlers = { + 'before-setup-loads': async (page: Page, _request: APIRequestContext) => runBeforeSetupLoads(page), + 'setup-instance': runSetupInstance, + 'after-setup-loads': runAfterSetupLoads, + signup: runSignup, + 'signup-duplicated': runSignupDuplicated, + signin: runSignIn, + suspend: runSuspend, + 'after-signed-in-loads': runAfterSignedInLoads, + 'account-setup-wizard': runAccountSetupWizard, + note: runCreateNote, + 'open-note-form-with-hotkey': runOpenNoteFormWithHotkey, + 'redirect-profile': runRedirectProfile, +} satisfies Record Promise>; + +export const runScenario: BrowserCommand<[scenario: string]> = async (ctx, scenario) => { + if (ctx.provider.name !== 'playwright') { + throw new Error(`playwright provider is required, but got ${ctx.provider.name}`); + } + + if (!(scenario in scenarioHandlers)) { + throw new Error(`unknown e2e scenario: ${scenario}`); + } + const run = scenarioHandlers[scenario as keyof typeof scenarioHandlers]; + + const testPage = await ctx.context.newPage(); + await testPage.addInitScript(() => { + (globalThis as { Cypress?: Record }).Cypress = { browserMode: true }; + }); + + try { + await run(testPage, testPage.request); + } finally { + await testPage.close(); + } +}; diff --git a/packages/frontend/test/e2e/commands.d.ts b/packages/frontend/test/e2e/commands.d.ts new file mode 100644 index 0000000000..2d7d3eb5c3 --- /dev/null +++ b/packages/frontend/test/e2e/commands.d.ts @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +declare module 'vitest/browser' { + interface BrowserCommands { + runScenario: (scenario: string) => Promise; + } +} + +export {}; diff --git a/packages/frontend/test/e2e/router.browser.test.ts b/packages/frontend/test/e2e/router.browser.test.ts new file mode 100644 index 0000000000..4a401309bc --- /dev/null +++ b/packages/frontend/test/e2e/router.browser.test.ts @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { commands } from 'vitest/browser'; +import { describe, it } from 'vitest'; + +describe('Router transition', () => { + describe('Redirect', () => { + it('redirect to user profile', async () => { + await commands.runScenario('redirect-profile'); + }); + }); +}); diff --git a/packages/frontend/test/setup.e2e.ts b/packages/frontend/test/setup.e2e.ts new file mode 100644 index 0000000000..b58f4a7cd8 --- /dev/null +++ b/packages/frontend/test/setup.e2e.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +function isIgnorableErrorMessage(message: string): boolean { + return [ + 'The source image cannot be decoded', + 'ResizeObserver loop limit exceeded', + 'ResizeObserver loop completed with undelivered notifications', + ].some((text) => message.includes(text)); +} + +window.addEventListener('error', (event) => { + if (isIgnorableErrorMessage(event.message)) { + event.preventDefault(); + } +}); + +window.addEventListener('unhandledrejection', (event) => { + const reason = event.reason; + const message = reason instanceof Error ? reason.message : String(reason); + if (isIgnorableErrorMessage(message)) { + event.preventDefault(); + } +}); diff --git a/packages/frontend/test/init.ts b/packages/frontend/test/setup.unit.ts similarity index 100% rename from packages/frontend/test/init.ts rename to packages/frontend/test/setup.unit.ts diff --git a/packages/frontend/test/aiscript/api.test.ts b/packages/frontend/test/unit/aiscript/api.test.ts similarity index 100% rename from packages/frontend/test/aiscript/api.test.ts rename to packages/frontend/test/unit/aiscript/api.test.ts diff --git a/packages/frontend/test/aiscript/common.test.ts b/packages/frontend/test/unit/aiscript/common.test.ts similarity index 100% rename from packages/frontend/test/aiscript/common.test.ts rename to packages/frontend/test/unit/aiscript/common.test.ts diff --git a/packages/frontend/test/aiscript/ui.test.ts b/packages/frontend/test/unit/aiscript/ui.test.ts similarity index 100% rename from packages/frontend/test/aiscript/ui.test.ts rename to packages/frontend/test/unit/aiscript/ui.test.ts diff --git a/packages/frontend/test/autocomplete.test.ts b/packages/frontend/test/unit/autocomplete.test.ts similarity index 100% rename from packages/frontend/test/autocomplete.test.ts rename to packages/frontend/test/unit/autocomplete.test.ts diff --git a/packages/frontend/test/emoji.test.ts b/packages/frontend/test/unit/emoji.test.ts similarity index 100% rename from packages/frontend/test/emoji.test.ts rename to packages/frontend/test/unit/emoji.test.ts diff --git a/packages/frontend/test/home.test.ts b/packages/frontend/test/unit/home.test.ts similarity index 100% rename from packages/frontend/test/home.test.ts rename to packages/frontend/test/unit/home.test.ts diff --git a/packages/frontend/test/i18n.test.ts b/packages/frontend/test/unit/i18n.test.ts similarity index 100% rename from packages/frontend/test/i18n.test.ts rename to packages/frontend/test/unit/i18n.test.ts diff --git a/packages/frontend/test/intl-string.test.ts b/packages/frontend/test/unit/intl-string.test.ts similarity index 100% rename from packages/frontend/test/intl-string.test.ts rename to packages/frontend/test/unit/intl-string.test.ts diff --git a/packages/frontend/test/is-birthday.test.ts b/packages/frontend/test/unit/is-birthday.test.ts similarity index 100% rename from packages/frontend/test/is-birthday.test.ts rename to packages/frontend/test/unit/is-birthday.test.ts diff --git a/packages/frontend/test/lib/nirax/fallbacks.test.ts b/packages/frontend/test/unit/lib/nirax/fallbacks.test.ts similarity index 100% rename from packages/frontend/test/lib/nirax/fallbacks.test.ts rename to packages/frontend/test/unit/lib/nirax/fallbacks.test.ts diff --git a/packages/frontend/test/lib/nirax/fixture.ts b/packages/frontend/test/unit/lib/nirax/fixture.ts similarity index 100% rename from packages/frontend/test/lib/nirax/fixture.ts rename to packages/frontend/test/unit/lib/nirax/fixture.ts diff --git a/packages/frontend/test/lib/nirax/navigation.test.ts b/packages/frontend/test/unit/lib/nirax/navigation.test.ts similarity index 100% rename from packages/frontend/test/lib/nirax/navigation.test.ts rename to packages/frontend/test/unit/lib/nirax/navigation.test.ts diff --git a/packages/frontend/test/lib/nirax/resolve.test.ts b/packages/frontend/test/unit/lib/nirax/resolve.test.ts similarity index 100% rename from packages/frontend/test/lib/nirax/resolve.test.ts rename to packages/frontend/test/unit/lib/nirax/resolve.test.ts diff --git a/packages/frontend/test/note.test.ts b/packages/frontend/test/unit/note.test.ts similarity index 100% rename from packages/frontend/test/note.test.ts rename to packages/frontend/test/unit/note.test.ts diff --git a/packages/frontend/test/scroll.test.ts b/packages/frontend/test/unit/scroll.test.ts similarity index 100% rename from packages/frontend/test/scroll.test.ts rename to packages/frontend/test/unit/scroll.test.ts diff --git a/packages/frontend/test/theme.test.ts b/packages/frontend/test/unit/theme.test.ts similarity index 100% rename from packages/frontend/test/theme.test.ts rename to packages/frontend/test/unit/theme.test.ts diff --git a/packages/frontend/test/url-preview.test.ts b/packages/frontend/test/unit/url-preview.test.ts similarity index 100% rename from packages/frontend/test/url-preview.test.ts rename to packages/frontend/test/unit/url-preview.test.ts diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts index 3574766f7f..b230f1818b 100644 --- a/packages/frontend/vite.config.ts +++ b/packages/frontend/vite.config.ts @@ -1,4 +1,3 @@ -/// import path from 'path'; import pluginVue from '@vitejs/plugin-vue'; import pluginGlsl from 'vite-plugin-glsl'; @@ -261,22 +260,6 @@ export function getConfig(): UserConfig { worker: { format: 'es', }, - - test: { - environment: 'happy-dom', - setupFiles: ['./test/init.ts'], - deps: { - optimizer: { - web: { - include: [ - // XXX: misskey-dev/browser-image-resizer has no "type": "module" - 'browser-image-resizer', - ], - }, - }, - }, - includeSource: ['src/**/*.ts'], - }, }; } diff --git a/packages/frontend/vitest.config.e2e.ts b/packages/frontend/vitest.config.e2e.ts new file mode 100644 index 0000000000..e316e4d051 --- /dev/null +++ b/packages/frontend/vitest.config.e2e.ts @@ -0,0 +1,28 @@ +import { defineConfig, mergeConfig } from 'vitest/config'; +import { playwright } from '@vitest/browser-playwright'; +import { runScenario } from './test/e2e/browser-commands.js'; +import { getConfig } from './vite.config.js'; + +export default mergeConfig(getConfig(), defineConfig({ + test: { + include: ['./test/e2e/**/*.test.ts'], + exclude: [], + setupFiles: ['./test/setup.e2e.ts'], + fileParallelism: false, + maxWorkers: 1, + testTimeout: 60000, + browser: { + enabled: true, + provider: playwright(), + headless: true, + screenshotFailures: true, + screenshotDirectory: './test/e2e/screenshots', + commands: { + runScenario, + }, + instances: [{ + browser: 'chromium', + }], + }, + }, +})); diff --git a/packages/frontend/vitest.config.unit.ts b/packages/frontend/vitest.config.unit.ts new file mode 100644 index 0000000000..c223dcb45a --- /dev/null +++ b/packages/frontend/vitest.config.unit.ts @@ -0,0 +1,22 @@ +import { defineConfig, mergeConfig } from 'vitest/config'; +import { getConfig } from './vite.config.js'; + +export default mergeConfig(getConfig(), defineConfig({ + test: { + include: ['./test/unit/**/*.test.ts'], + environment: 'happy-dom', + setupFiles: ['./test/init.ts'], + deps: { + optimizer: { + web: { + include: [ + // XXX: misskey-dev/browser-image-resizer has no "type": "module" + 'browser-image-resizer', + ], + }, + }, + }, + includeSource: ['src/**/*.ts'], + }, +})); + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 755bee9613..b6ac19c446 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,9 +50,6 @@ importers: cross-env: specifier: 10.1.0 version: 10.1.0 - cypress: - specifier: 15.18.0 - version: 15.18.0 eslint: specifier: 9.39.4 version: 9.39.4 @@ -446,7 +443,7 @@ importers: version: 8.62.0(eslint@9.39.4)(typescript@5.9.3) '@vitest/coverage-v8': specifier: 4.1.9 - version: 4.1.9(vitest@4.1.9) + version: 4.1.9(@vitest/browser@4.1.9)(vitest@4.1.9) aws-sdk-client-mock: specifier: 4.1.0 version: 4.1.0 @@ -482,7 +479,7 @@ importers: version: 8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4) vitest: specifier: 4.1.9 - version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) vitest-mock-extended: specifier: 4.0.0 version: 4.0.0(typescript@5.9.3)(vitest@4.1.9) @@ -794,9 +791,15 @@ importers: '@typescript-eslint/parser': specifier: 8.62.0 version: 8.62.0(eslint@9.39.4)(typescript@5.9.3) + '@vitest/browser': + specifier: 4.1.9 + version: 4.1.9(bufferutil@4.1.0)(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(utf-8-validate@6.0.6)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4))(vitest@4.1.9) + '@vitest/browser-playwright': + specifier: 4.1.9 + version: 4.1.9(bufferutil@4.1.0)(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.6)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4))(vitest@4.1.9) '@vitest/coverage-v8': specifier: 4.1.9 - version: 4.1.9(vitest@4.1.9) + version: 4.1.9(@vitest/browser@4.1.9)(vitest@4.1.9) '@vue/compiler-core': specifier: 3.5.39 version: 3.5.39 @@ -842,6 +845,9 @@ importers: oxc-walker: specifier: 1.0.0 version: 1.0.0(oxc-parser@0.127.0)(rolldown@1.1.3) + playwright: + specifier: 1.56.0 + version: 1.56.0 prettier: specifier: 3.9.1 version: 3.9.1 @@ -880,7 +886,7 @@ importers: version: 1.0.3 vitest: specifier: 4.1.9 - version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) vitest-fetch-mock: specifier: 0.4.5 version: 0.4.5(vitest@4.1.9) @@ -1008,7 +1014,7 @@ importers: version: 6.0.7(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4))(vue@3.5.39(typescript@5.9.3)) '@vitest/coverage-v8': specifier: 4.1.9 - version: 4.1.9(vitest@4.1.9) + version: 4.1.9(@vitest/browser@4.1.9)(vitest@4.1.9) '@vue/runtime-core': specifier: 3.5.39 version: 3.5.39 @@ -1208,7 +1214,7 @@ importers: version: 8.62.0(eslint@9.39.4)(typescript@5.9.3) '@vitest/coverage-v8': specifier: 4.1.9 - version: 4.1.9(vitest@4.1.9) + version: 4.1.9(@vitest/browser@4.1.9)(vitest@4.1.9) esbuild: specifier: 0.28.1 version: 0.28.1 @@ -1226,7 +1232,7 @@ importers: version: 0.33.0 vitest: specifier: 4.1.9 - version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) vitest-websocket-mock: specifier: 0.5.0 version: 0.5.0(vitest@4.1.9) @@ -1502,6 +1508,9 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} + '@blazediff/core@1.9.1': + resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==} + '@borewit/text-codec@0.2.2': resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} @@ -1560,13 +1569,6 @@ packages: resolution: {integrity: sha512-LfUFi+Vv4eDzj+XAtR89e3wwjXA/NZjUSwU5NhwbBrLecxPaBYFy3exCuc1j+D4UZeOVdqlsl8G7LmOt18V0tg==} engines: {node: '>=20'} - '@cypress/request@4.0.0': - resolution: {integrity: sha512-wGTQfwDMMMiz/muFw4YbCLwTh0uZsXKK+6zWBzftADpitSi6iM62C8GzEhNcng2srUiGPksOriQkA8zakW2R0g==} - engines: {node: '>= 14.17.0'} - - '@cypress/xvfb@1.2.4': - resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==} - '@digitalbazaar/http-client@4.3.0': resolution: {integrity: sha512-6lMpxpt9BOmqHKGs9Xm6DP4LlZTBFer/ZjHvP3FcW3IaUWYIWC7dw5RFZnvw4fP57kAVcm1dp3IF+Y50qhBvAw==} engines: {node: '>=18.0'} @@ -2958,6 +2960,9 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@readme/better-ajv-errors@2.4.0': resolution: {integrity: sha512-9WODaOAKSl/mU+MYNZ2aHCrkoRSvmQ+1YkLj589OEqqjOAhbn8j7Z+ilYoiTu/he6X63/clsxxAB4qny9/dDzg==} engines: {node: '>=18'} @@ -3903,12 +3908,6 @@ packages: '@types/sinonjs__fake-timers@15.0.1': resolution: {integrity: sha512-Ko2tjWJq8oozHzHV+reuvS5KYIRAokHnGbDwGh/J64LntgpbuylF74ipEL24HCyRjf9FOlBiBHWBR1RlVKsI1w==} - '@types/sinonjs__fake-timers@8.1.1': - resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} - - '@types/sizzle@2.3.10': - resolution: {integrity: sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==} - '@types/statuses@2.0.6': resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} @@ -4061,6 +4060,17 @@ packages: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 vue: ^3.2.25 + '@vitest/browser-playwright@4.1.9': + resolution: {integrity: sha512-Bq1rOGf9waevzG3EOkO/dene6bvKTUsZMVg8S1i+WH3JcMjuXEjiahP9rAqZRELUqjBySOJsvvSWqK/B3wjKQw==} + peerDependencies: + playwright: '*' + vitest: 4.1.9 + + '@vitest/browser@4.1.9': + resolution: {integrity: sha512-j1BKtWmPcqpMhmx/L9EPLgAJpCb0zKfwoWLmqBbxaogCXHjOwHFSEoHCBfnGtx93xKQwilZ26m+UOsHqHMkRNg==} + peerDependencies: + vitest: 4.1.9 + '@vitest/coverage-v8@4.1.9': resolution: {integrity: sha512-G9/lgqibheLVBDRuya45EbsEXTYcWoSG+TLg7i2axuzx0Eq62eXn+aWXyaVdV5vKvFSWd6ywcX8hA7la9Pvu8g==} peerDependencies: @@ -4306,10 +4316,6 @@ packages: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - ansi-escapes@7.3.0: - resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} - engines: {node: '>=18'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -4337,9 +4343,6 @@ packages: append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} - arch@2.2.0: - resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} - archiver@8.0.0: resolution: {integrity: sha512-fV1orZfsnPn9BaSByR/qE67rJCLJEy2Ox5bq7nJh+jquWaNh6Sfec75kJ2T6PtdGUbPQlrVoSVCEOa5SdiTQ1g==} engines: {node: '>=18'} @@ -4443,10 +4446,6 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} - atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -4461,12 +4460,6 @@ packages: aws-sdk-client-mock@4.1.0: resolution: {integrity: sha512-h/tOYTkXEsAcV3//6C1/7U4ifSpKyJvb6auveAepqqNJl6TdZaPFEtKjBQNf8UxQdDP850knB2i/whq4zlsxJw==} - aws-sign2@0.7.0: - resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} - - aws4@1.13.2: - resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} - axios@1.16.0: resolution: {integrity: sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==} @@ -4543,12 +4536,6 @@ packages: resolution: {integrity: sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==} hasBin: true - blob-util@2.0.2: - resolution: {integrity: sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==} - - bluebird@3.7.2: - resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} - blurhash@2.0.5: resolution: {integrity: sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==} @@ -4582,9 +4569,6 @@ packages: broadcast-channel@7.3.0: resolution: {integrity: sha512-UHPhLBQKfQ8OmMFMpmPfO5dRakyA1vsfiDGWTYNvChYol65tbuhivPEGgZZiuetorvExdvxaWiBy/ym1Ty08yA==} - buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - buffer-crc32@1.0.0: resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} engines: {node: '>=8.0.0'} @@ -4602,9 +4586,6 @@ packages: buffer@5.6.0: resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==} - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} @@ -4648,10 +4629,6 @@ packages: resolution: {integrity: sha512-rFWadDRKJs3s2eYdXlGggnBZKG7MTblkFBB0YllFds+UYnfogDp2wcR6JN97FhRkHTvq59n2vhNoHNZn29dh/Q==} engines: {node: '>=18'} - cachedir@2.4.0: - resolution: {integrity: sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==} - engines: {node: '>=6'} - call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -4683,9 +4660,6 @@ packages: canvas-confetti@1.9.4: resolution: {integrity: sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==} - caseless@0.12.0: - resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - cbor2@2.3.0: resolution: {integrity: sha512-76WB3hq8BoaGkMkBVJ27fW5LJU+qqDLEpgRNCG/SYKhODWXpVPOTD4UcUto3IEzYLA52nsvbhb0wabhHDn3qXg==} engines: {node: '>=20'} @@ -4807,25 +4781,9 @@ packages: resolution: {integrity: sha512-zFyPtyC0SZ6Zu79b9sOYtXZcgrsXe0RpePrzRyj52hYVFG1+Rk6rBqjjOEk+GNQwc3PIX+86teQMok970pod1g==} engines: {node: '>=20'} - ci-info@4.4.0: - resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} - engines: {node: '>=8'} - cjs-module-lexer@2.2.0: resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} - - cli-table3@0.6.1: - resolution: {integrity: sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==} - engines: {node: 10.* || >= 12.*} - - cli-truncate@5.2.0: - resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} - engines: {node: '>=20'} - cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} @@ -4874,16 +4832,9 @@ packages: colorette@1.4.0: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - colorjs.io@0.5.2: resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==} - colors@1.4.0: - resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} - engines: {node: '>=0.1.90'} - combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -4902,18 +4853,10 @@ packages: commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - commander@6.2.1: - resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} - engines: {node: '>= 6'} - commander@9.5.0: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} engines: {node: ^12.20.0 || >=14} - common-tags@1.8.2: - resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} - engines: {node: '>=4.0.0'} - compare-versions@6.1.1: resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} @@ -5017,11 +4960,6 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - cypress@15.18.0: - resolution: {integrity: sha512-aLfOYSLlVt1b6QSoVUjbCY27taZlYAT8ST47xQbwd9pvQrY/g5gXi12yItZTB+kxkkj+ZcvUYmRLUC95SlCJsw==} - engines: {node: ^20.1.0 || ^22.0.0 || >=24.0.0} - hasBin: true - dashdash@1.14.1: resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} engines: {node: '>=0.10'} @@ -5286,10 +5224,6 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} - error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} @@ -5488,9 +5422,6 @@ packages: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} - eventemitter2@6.4.7: - resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} - eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -5504,10 +5435,6 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - execa@4.1.0: - resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} - engines: {node: '>=10'} - execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -5520,10 +5447,6 @@ packages: resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} engines: {node: ^18.19.0 || >=20.5.0} - executable@4.1.1: - resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} - engines: {node: '>=4'} - exifreader@4.41.0: resolution: {integrity: sha512-P3nPeh6GWs5D5RZdRZ6q/LorHPmmeDgKsowduqRabtTFiqMD2bc5eTN+Dhq00O9BCuV2eksu3oOJh4ZaZvkK0A==} hasBin: true @@ -5691,9 +5614,6 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - forever-agent@0.6.1: - resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} - form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} @@ -5714,9 +5634,10 @@ packages: resolution: {integrity: sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==} engines: {node: '>=14.14'} - fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} @@ -5753,10 +5674,6 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} - get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} - get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -5792,10 +5709,6 @@ packages: resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} engines: {node: 18 || 20 || >=22} - global-dirs@3.0.1: - resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} - engines: {node: '>=10'} - globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -5876,10 +5789,6 @@ packages: hash-sum@2.0.0: resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==} - hasha@5.2.2: - resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} - engines: {node: '>=8'} - hasown@2.0.3: resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} engines: {node: '>= 0.4'} @@ -5938,10 +5847,6 @@ packages: resolution: {integrity: sha512-3cZ0SRL8fb9MUlU3mKM61FcQvPfXx2dBrZW3Vbg5CXa8jFlK8OaEpePenLe1oEXQduhz8b0QjsqfS59QP4AJDQ==} engines: {node: '>=6.0.0'} - http-signature@1.4.0: - resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==} - engines: {node: '>=0.10'} - http2-wrapper@2.2.1: resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} engines: {node: '>=10.19.0'} @@ -5954,10 +5859,6 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - human-signals@1.1.1: - resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} - engines: {node: '>=8.12.0'} - human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -6036,10 +5937,6 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - ini@2.0.0: - resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} - engines: {node: '>=10'} - insert-text-at-cursor@0.3.0: resolution: {integrity: sha512-/nPtyeX9xPUvxZf+r0518B7uqNKlP+LqNJqSiXFEaa2T71rWIwTVXGH7hB9xO/EVdwa5/pWlFCPwShOW81XIxQ==} @@ -6152,10 +6049,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@5.1.0: - resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} - engines: {node: '>=18'} - is-generator-function@1.1.2: resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} engines: {node: '>= 0.4'} @@ -6173,10 +6066,6 @@ packages: engines: {node: '>=14.16'} hasBin: true - is-installed-globally@0.4.0: - resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} - engines: {node: '>=10'} - is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -6196,10 +6085,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - is-plain-obj@1.1.0: resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} engines: {node: '>=0.10.0'} @@ -6258,9 +6143,6 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} - is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -6298,9 +6180,6 @@ packages: resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} engines: {node: '>=20'} - isstream@0.1.2: - resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} - istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -6426,10 +6305,6 @@ packages: resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} engines: {node: '>=0.6.0'} - jsprim@2.0.2: - resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} - engines: {'0': node >=0.6.0} - jstransformer@1.0.0: resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==} @@ -6560,10 +6435,6 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - listr2@9.0.5: - resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} - engines: {node: '>=20.0.0'} - load-esm@1.0.3: resolution: {integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==} engines: {node: '>=13.2.0'} @@ -6585,9 +6456,6 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.once@4.1.1: - resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - lodash@4.18.1: resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} @@ -6595,10 +6463,6 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} - longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -6871,10 +6735,6 @@ packages: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} - mimic-response@4.0.0: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -6930,6 +6790,10 @@ packages: module-details-from-path@1.0.4: resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -7166,10 +7030,6 @@ packages: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} - oniguruma-parser@0.12.2: resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==} @@ -7200,9 +7060,6 @@ packages: os-utils@0.0.14: resolution: {integrity: sha512-ajB8csaHLBvJOYsHJkp8YdO2FvlBbf/ZxaYQwXXRDyQ84UoE+uTuLXxqd0shekXMX6Qr/pt/DDyLMRAMsgfWzg==} - ospath@1.2.2: - resolution: {integrity: sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==} - otpauth@9.5.1: resolution: {integrity: sha512-fJmDAHc8wImfqqqOXIlBvT1dEKrZK0Cmb2VEgScpNTolCz0PHh6ExUZGv4sLtOsWNaHCQlD+rRqaPgnoxFoZjQ==} @@ -7341,12 +7198,6 @@ packages: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} - pend@1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - - performance-now@2.1.0: - resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} - pg-cloudflare@1.4.0: resolution: {integrity: sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A==} @@ -7400,10 +7251,6 @@ packages: resolution: {integrity: sha512-teosUBzP9q3GMZDp/QlI/HSJHwnIBiCtDWhM/OxSB2PcR20Z0uFrrsAjKbG3e4WlQTVm5oTfmvgXEp+gk/rZ0w==} engines: {node: '>=20'} - pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - pino-abstract-transport@3.0.0: resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} @@ -7421,6 +7268,16 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + playwright-core@1.56.0: + resolution: {integrity: sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.56.0: + resolution: {integrity: sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==} + engines: {node: '>=18'} + hasBin: true + plimit-lit@1.6.1: resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==} engines: {node: '>=12'} @@ -7437,6 +7294,10 @@ packages: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + pnpm@11.9.0: resolution: {integrity: sha512-vWgtXQP+Ul73yf1ngMaITR51asTJyf4AxTh4KCQxDc+Q493E9Tg18G3669UIXkGFXgvLs7YN4qxburieUDbwOw==} engines: {node: '>=22.13'} @@ -7499,10 +7360,6 @@ packages: engines: {node: '>=14'} hasBin: true - pretty-bytes@5.6.0: - resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} - engines: {node: '>=6'} - pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -7555,9 +7412,6 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - proxy-from-env@1.0.0: - resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} - proxy-from-env@2.1.0: resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} engines: {node: '>=10'} @@ -7609,9 +7463,6 @@ packages: pug@3.0.4: resolution: {integrity: sha512-kFfq5mMzrS7+wrl5pLJzZEzemx34OQ0w4SARfhy/3yxTlhbstsudDwJzhf1hP02yHzbjoVMSXUj/Sz6RNfMyXg==} - pump@3.0.4: - resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} - punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} @@ -7642,10 +7493,6 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - qs@6.14.2: - resolution: {integrity: sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==} - engines: {node: '>=0.6'} - qs@6.15.1: resolution: {integrity: sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==} engines: {node: '>=0.6'} @@ -7792,9 +7639,6 @@ packages: rename@1.0.4: resolution: {integrity: sha512-YMM6Fn3lrFOCjhORKjj+z/yizj8WSzv3F3YUlpJA20fteWCb0HbJU19nvuRBPUM5dWgxJcHP+kix3M+5NowJyA==} - request-progress@3.0.0: - resolution: {integrity: sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==} - require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -7834,10 +7678,6 @@ packages: resolution: {integrity: sha512-cGk8IbWEAnaCpdAt1BHzJ3Ahz5ewDJa0KseTsE3qIRMJ3C698W8psM7byCeWVpd/Ha7FUYzuRVzXoKoM6nRUbA==} engines: {node: '>=20'} - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} - ret@0.5.0: resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} engines: {node: '>=10'} @@ -8177,6 +8017,10 @@ packages: sinon@18.0.1: resolution: {integrity: sha512-a2N2TDY1uGviajJ6r4D1CyRAkzE9NNVlYOV1wX5xQDuAk0ONgzgRl0EjCQuRCPxOwp13ghsMwt9Gdldujs39qw==} + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + slacc-android-arm-eabi@0.1.5: resolution: {integrity: sha512-4BvH5Ut1egLORdiMfww+RyIDTMVVx3jFdcAa6gz7VglCmksyTsvuGbTgn31aC/1hjqug3eObkS+K7d3ZW8Yk/Q==} engines: {node: '>=24 || ^23.6.0 || ^22.14.0'} @@ -8266,14 +8110,6 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} - - slice-ansi@8.0.0: - resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} - engines: {node: '>=20'} - sonic-boom@4.2.1: resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} @@ -8417,10 +8253,6 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string-width@8.2.1: - resolution: {integrity: sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==} - engines: {node: '>=20'} - string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -8556,9 +8388,6 @@ packages: resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} engines: {node: '>=12.22'} - throttleit@1.0.1: - resolution: {integrity: sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==} - tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -8596,16 +8425,9 @@ packages: resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} - tldts-core@6.1.86: - resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - tldts-core@7.0.30: resolution: {integrity: sha512-uiHN8PIB1VmWyS98eZYja4xzlYqeFZVjb4OuYlJQnZAuJhMw4PbKQOKgHKhBdJR3FE/t5mUQ1Kd80++B+qhD1Q==} - tldts@6.1.86: - resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} - hasBin: true - tldts@7.0.30: resolution: {integrity: sha512-ELrFxuqsDdHUwoh0XxDbxuLD3Wnz49Z57IFvTtvWy1hJdcMZjXLIuonjilCiWHlT2GbE4Wlv1wKVTzDFnXH1aw==} hasBin: true @@ -8636,14 +8458,14 @@ packages: resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} engines: {node: '>=14.16'} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + touch@3.1.1: resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} hasBin: true - tough-cookie@5.1.2: - resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} - engines: {node: '>=16'} - tough-cookie@6.0.1: resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} engines: {node: '>=16'} @@ -8714,9 +8536,6 @@ packages: resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==} engines: {node: '>= 6.0.0'} - tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - tweetnacl@0.14.5: resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} @@ -8924,10 +8743,6 @@ packages: until-async@3.0.2: resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} - untildify@4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} - uri-js-replace@1.0.1: resolution: {integrity: sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==} @@ -9380,10 +9195,6 @@ packages: resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yauzl@3.3.1: - resolution: {integrity: sha512-RNPCUkiE/ZgO4w8i9U5yDQVHaFDdnzaFANElRvpJteCspvmv2VqrRb9lvS6odVD+jqI/zDsxAHJVsafpcheVQQ==} - engines: {node: '>=12'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -9463,7 +9274,7 @@ snapshots: '@apm-js-collab/tracing-hooks@0.10.0': dependencies: '@apm-js-collab/code-transformer': 0.15.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 module-details-from-path: 1.0.4 transitivePeerDependencies: - supports-color @@ -9732,6 +9543,8 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} + '@blazediff/core@1.9.1': {} + '@borewit/text-codec@0.2.2': {} '@bufbuild/protobuf@2.12.0': {} @@ -9814,33 +9627,6 @@ snapshots: '@cto.af/wtf8@0.0.5': {} - '@cypress/request@4.0.0': - dependencies: - aws-sign2: 0.7.0 - aws4: 1.13.2 - caseless: 0.12.0 - combined-stream: 1.0.8 - extend: 3.0.2 - forever-agent: 0.6.1 - form-data: 4.0.5 - http-signature: 1.4.0 - is-typedarray: 1.0.0 - isstream: 0.1.2 - json-stringify-safe: 5.0.1 - mime-types: 2.1.35 - performance-now: 2.1.0 - qs: 6.14.2 - safe-buffer: 5.2.1 - tough-cookie: 5.1.2 - tunnel-agent: 0.6.0 - - '@cypress/xvfb@1.2.4(supports-color@8.1.1)': - dependencies: - debug: 3.2.7(supports-color@8.1.1) - lodash.once: 4.1.1 - transitivePeerDependencies: - - supports-color - '@digitalbazaar/http-client@4.3.0': dependencies: ky: 1.14.3 @@ -9974,7 +9760,7 @@ snapshots: '@eslint/config-array@0.21.2': dependencies: '@eslint/object-schema': 2.1.7 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -9994,7 +9780,7 @@ snapshots: '@eslint/eslintrc@3.3.5': dependencies: ajv: 6.15.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 @@ -11013,6 +10799,8 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true + '@polka/url@1.0.0-next.29': {} + '@readme/better-ajv-errors@2.4.0(ajv@8.20.0)': dependencies: '@babel/code-frame': 7.29.0 @@ -11808,7 +11596,7 @@ snapshots: '@tokenizer/inflate@0.4.1': dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 token-types: 6.1.2 transitivePeerDependencies: - supports-color @@ -11969,10 +11757,6 @@ snapshots: '@types/sinonjs__fake-timers@15.0.1': {} - '@types/sinonjs__fake-timers@8.1.1': {} - - '@types/sizzle@2.3.10': {} - '@types/statuses@2.0.6': {} '@types/textarea-caret@3.0.4': {} @@ -12027,7 +11811,7 @@ snapshots: '@typescript-eslint/types': 8.62.0 '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.62.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 eslint: 9.39.4 typescript: 5.9.3 transitivePeerDependencies: @@ -12037,7 +11821,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@5.9.3) '@typescript-eslint/types': 8.62.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -12056,7 +11840,7 @@ snapshots: '@typescript-eslint/types': 8.62.0 '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) '@typescript-eslint/utils': 8.62.0(eslint@9.39.4)(typescript@5.9.3) - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 eslint: 9.39.4 ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 @@ -12071,7 +11855,7 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@5.9.3) '@typescript-eslint/types': 8.62.0 '@typescript-eslint/visitor-keys': 8.62.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 minimatch: 10.2.5 semver: 7.8.5 tinyglobby: 0.2.17 @@ -12135,7 +11919,37 @@ snapshots: vite: 8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4) vue: 3.5.39(typescript@5.9.3) - '@vitest/coverage-v8@4.1.9(vitest@4.1.9)': + '@vitest/browser-playwright@4.1.9(bufferutil@4.1.0)(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.6)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4))(vitest@4.1.9)': + dependencies: + '@vitest/browser': 4.1.9(bufferutil@4.1.0)(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(utf-8-validate@6.0.6)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4))(vitest@4.1.9) + '@vitest/mocker': 4.1.9(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + playwright: 1.56.0 + tinyrainbow: 3.1.0 + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser@4.1.9(bufferutil@4.1.0)(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(utf-8-validate@6.0.6)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4))(vitest@4.1.9)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.9(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + '@vitest/utils': 4.1.9 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.0 + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/coverage-v8@4.1.9(@vitest/browser@4.1.9)(vitest@4.1.9)': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.1.9 @@ -12147,7 +11961,9 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + optionalDependencies: + '@vitest/browser': 4.1.9(bufferutil@4.1.0)(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(utf-8-validate@6.0.6)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4))(vitest@4.1.9) '@vitest/expect@2.0.5': dependencies: @@ -12463,10 +12279,6 @@ snapshots: dependencies: type-fest: 0.21.3 - ansi-escapes@7.3.0: - dependencies: - environment: 1.1.0 - ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -12483,8 +12295,6 @@ snapshots: append-field@1.0.0: {} - arch@2.2.0: {} - archiver@8.0.0: dependencies: async: 3.2.6 @@ -12618,8 +12428,6 @@ snapshots: asynckit@0.4.0: {} - at-least-node@1.0.0: {} - atomic-sleep@1.0.0: {} available-typed-arrays@1.0.7: @@ -12637,10 +12445,6 @@ snapshots: sinon: 18.0.1 tslib: 2.8.1 - aws-sign2@0.7.0: {} - - aws4@1.13.2: {} - axios@1.16.0(debug@4.4.3): dependencies: follow-redirects: 1.16.0(debug@4.4.3) @@ -12701,10 +12505,6 @@ snapshots: bcryptjs@3.0.3: {} - blob-util@2.0.2: {} - - bluebird@3.7.2: {} - blurhash@2.0.5: {} bn.js@4.12.3: {} @@ -12713,7 +12513,7 @@ snapshots: dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 http-errors: 2.0.1 iconv-lite: 0.7.2 on-finished: 2.4.1 @@ -12751,8 +12551,6 @@ snapshots: p-queue: 6.6.2 unload: 2.4.1 - buffer-crc32@0.2.13: {} - buffer-crc32@1.0.0: {} buffer-equal-constant-time@1.0.1: {} @@ -12768,11 +12566,6 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - buffer@6.0.3: dependencies: base64-js: 1.5.1 @@ -12820,8 +12613,6 @@ snapshots: normalize-url: 8.1.1 responselike: 4.0.2 - cachedir@2.4.0: {} - call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -12853,8 +12644,6 @@ snapshots: canvas-confetti@1.9.4: {} - caseless@0.12.0: {} - cbor2@2.3.0: dependencies: '@cto.af/wtf8': 0.0.5 @@ -12965,25 +12754,8 @@ snapshots: chunk-data@0.1.0: {} - ci-info@4.4.0: {} - cjs-module-lexer@2.2.0: {} - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 - - cli-table3@0.6.1: - dependencies: - string-width: 4.2.3 - optionalDependencies: - colors: 1.4.0 - - cli-truncate@5.2.0: - dependencies: - slice-ansi: 8.0.0 - string-width: 8.2.1 - cli-width@4.1.0: {} cliui@6.0.0: @@ -13032,13 +12804,8 @@ snapshots: colorette@1.4.0: {} - colorette@2.0.20: {} - colorjs.io@0.5.2: {} - colors@1.4.0: - optional: true - combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -13052,12 +12819,8 @@ snapshots: commander@2.20.3: optional: true - commander@6.2.1: {} - commander@9.5.0: {} - common-tags@1.8.2: {} - compare-versions@6.1.1: {} compress-commons@7.0.1: @@ -13155,48 +12918,6 @@ snapshots: csstype@3.2.3: {} - cypress@15.18.0: - dependencies: - '@cypress/request': 4.0.0 - '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/sinonjs__fake-timers': 8.1.1 - '@types/sizzle': 2.3.10 - '@types/tmp': 0.2.6 - arch: 2.2.0 - blob-util: 2.0.2 - bluebird: 3.7.2 - buffer: 5.7.1 - cachedir: 2.4.0 - chalk: 4.1.2 - ci-info: 4.4.0 - cli-table3: 0.6.1 - commander: 6.2.1 - common-tags: 1.8.2 - dayjs: 1.11.20 - debug: 4.4.3(supports-color@8.1.1) - eventemitter2: 6.4.7 - execa: 4.1.0 - executable: 4.1.1 - fs-extra: 9.1.0 - hasha: 5.2.2 - is-installed-globally: 0.4.0 - listr2: 9.0.5 - lodash: 4.18.1 - log-symbols: 4.1.0 - minimist: 1.2.8 - ospath: 1.2.2 - pretty-bytes: 5.6.0 - process: 0.11.10 - proxy-from-env: 1.0.0 - request-progress: 3.0.0 - supports-color: 8.1.1 - systeminformation: 5.31.11 - tmp: 0.2.7 - tree-kill: 1.2.2 - tslib: 1.14.1 - untildify: 4.0.0 - yauzl: 3.3.1 - dashdash@1.14.1: dependencies: assert-plus: 1.0.0 @@ -13231,11 +12952,13 @@ snapshots: dependencies: ms: 2.0.0 - debug@3.2.7(supports-color@8.1.1): + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.4.3: dependencies: ms: 2.1.3 - optionalDependencies: - supports-color: 8.1.1 debug@4.4.3(supports-color@10.2.2): dependencies: @@ -13249,12 +12972,6 @@ snapshots: optionalDependencies: supports-color: 5.5.0 - debug@4.4.3(supports-color@8.1.1): - dependencies: - ms: 2.1.3 - optionalDependencies: - supports-color: 8.1.1 - decamelize-keys@1.1.1: dependencies: decamelize: 1.2.0 @@ -13451,8 +13168,6 @@ snapshots: env-paths@2.2.1: {} - environment@1.1.0: {} - error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 @@ -13609,7 +13324,7 @@ snapshots: eslint-import-resolver-node@0.3.10: dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 is-core-module: 2.16.2 resolve: 2.0.0-next.6 transitivePeerDependencies: @@ -13617,7 +13332,7 @@ snapshots: eslint-module-utils@2.12.1(@typescript-eslint/parser@8.62.0(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.4): dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.62.0(eslint@9.39.4)(typescript@5.9.3) eslint: 9.39.4 @@ -13632,7 +13347,7 @@ snapshots: array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 doctrine: 2.1.0 eslint: 9.39.4 eslint-import-resolver-node: 0.3.10 @@ -13705,7 +13420,7 @@ snapshots: ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -13765,8 +13480,6 @@ snapshots: event-target-shim@5.0.1: {} - eventemitter2@6.4.7: {} - eventemitter3@4.0.7: {} eventemitter3@5.0.4: {} @@ -13779,18 +13492,6 @@ snapshots: events@3.3.0: {} - execa@4.1.0: - dependencies: - cross-spawn: 7.0.6 - get-stream: 5.2.0 - human-signals: 1.1.1 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -13830,10 +13531,6 @@ snapshots: strip-final-newline: 4.0.0 yoctocolors: 2.1.2 - executable@4.1.1: - dependencies: - pify: 2.3.0 - exifreader@4.41.0: optionalDependencies: '@xmldom/xmldom': 0.9.10 @@ -13850,7 +13547,7 @@ snapshots: content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 @@ -14020,7 +13717,7 @@ snapshots: finalhandler@2.1.1: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -14067,7 +13764,7 @@ snapshots: follow-redirects@1.16.0(debug@4.4.3): optionalDependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 for-each@0.3.5: dependencies: @@ -14078,8 +13775,6 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - forever-agent@0.6.1: {} - form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -14102,12 +13797,8 @@ snapshots: jsonfile: 6.2.1 universalify: 2.0.1 - fs-extra@9.1.0: - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.2.1 - universalify: 2.0.1 + fsevents@2.3.2: + optional: true fsevents@2.3.3: optional: true @@ -14149,10 +13840,6 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 - get-stream@5.2.0: - dependencies: - pump: 3.0.4 - get-stream@6.0.1: {} get-stream@9.0.1: @@ -14197,10 +13884,6 @@ snapshots: minipass: 7.1.3 path-scurry: 2.0.2 - global-dirs@3.0.1: - dependencies: - ini: 2.0.0 - globals@14.0.0: {} globals@17.7.0: {} @@ -14296,11 +13979,6 @@ snapshots: hash-sum@2.0.0: {} - hasha@5.2.2: - dependencies: - is-stream: 2.0.1 - type-fest: 0.8.1 - hasown@2.0.3: dependencies: function-bind: 1.1.2 @@ -14372,12 +14050,6 @@ snapshots: http-link-header@1.1.3: {} - http-signature@1.4.0: - dependencies: - assert-plus: 1.0.0 - jsprim: 2.0.2 - sshpk: 1.18.0 - http2-wrapper@2.2.1: dependencies: quick-lru: 5.1.1 @@ -14388,7 +14060,7 @@ snapshots: https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -14399,8 +14071,6 @@ snapshots: transitivePeerDependencies: - supports-color - human-signals@1.1.1: {} - human-signals@2.1.0: {} human-signals@3.0.1: {} @@ -14459,8 +14129,6 @@ snapshots: ini@1.3.8: {} - ini@2.0.0: {} - insert-text-at-cursor@0.3.0: {} install-artifact-from-github@1.6.0: {} @@ -14477,7 +14145,7 @@ snapshots: dependencies: '@ioredis/commands': 1.5.1 cluster-key-slot: 1.1.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -14491,7 +14159,7 @@ snapshots: dependencies: '@ioredis/commands': 1.10.0 cluster-key-slot: 1.1.1 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 denque: 2.1.0 redis-errors: 1.2.0 redis-parser: 3.0.0 @@ -14582,10 +14250,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@5.1.0: - dependencies: - get-east-asian-width: 1.5.0 - is-generator-function@1.1.2: dependencies: call-bound: 1.0.4 @@ -14604,11 +14268,6 @@ snapshots: dependencies: is-docker: 3.0.0 - is-installed-globally@0.4.0: - dependencies: - global-dirs: 3.0.1 - is-path-inside: 3.0.3 - is-map@2.0.3: {} is-negative-zero@2.0.3: {} @@ -14622,8 +14281,6 @@ snapshots: is-number@7.0.0: {} - is-path-inside@3.0.3: {} - is-plain-obj@1.1.0: {} is-plain-obj@4.1.0: {} @@ -14672,8 +14329,6 @@ snapshots: dependencies: which-typed-array: 1.1.20 - is-typedarray@1.0.0: {} - is-unicode-supported@0.1.0: {} is-unicode-supported@2.1.0: {} @@ -14701,8 +14356,6 @@ snapshots: isexe@4.0.0: {} - isstream@0.1.2: {} - istanbul-lib-coverage@3.2.2: {} istanbul-lib-report@3.0.1: @@ -14833,13 +14486,6 @@ snapshots: json-schema: 0.4.0 verror: 1.10.0 - jsprim@2.0.2: - dependencies: - assert-plus: 1.0.0 - extsprintf: 1.3.0 - json-schema: 0.4.0 - verror: 1.10.0 - jstransformer@1.0.0: dependencies: is-promise: 2.2.2 @@ -14955,15 +14601,6 @@ snapshots: lines-and-columns@1.2.4: {} - listr2@9.0.5: - dependencies: - cli-truncate: 5.2.0 - colorette: 2.0.20 - eventemitter3: 5.0.4 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 9.0.2 - load-esm@1.0.3: {} locate-path@5.0.0: @@ -14980,8 +14617,6 @@ snapshots: lodash.merge@4.6.2: {} - lodash.once@4.1.1: {} - lodash@4.18.1: {} log-symbols@4.1.0: @@ -14989,14 +14624,6 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 - log-update@6.1.0: - dependencies: - ansi-escapes: 7.3.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.2 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 - longest-streak@3.1.0: {} loupe@3.2.1: {} @@ -15382,7 +15009,7 @@ snapshots: micromark@4.0.2: dependencies: '@types/debug': 4.1.13 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 decode-named-character-reference: 1.3.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 @@ -15426,8 +15053,6 @@ snapshots: mimic-fn@4.0.0: {} - mimic-function@5.0.1: {} - mimic-response@4.0.0: {} min-indent@1.0.1: {} @@ -15479,6 +15104,8 @@ snapshots: module-details-from-path@1.0.4: {} + mrmime@2.0.1: {} + ms@2.0.0: {} ms@2.1.3: {} @@ -15556,7 +15183,7 @@ snapshots: needle@2.9.1: dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 iconv-lite: 0.4.24 sax: 1.6.0 transitivePeerDependencies: @@ -15752,10 +15379,6 @@ snapshots: dependencies: mimic-fn: 4.0.0 - onetime@7.0.0: - dependencies: - mimic-function: 5.0.1 - oniguruma-parser@0.12.2: {} oniguruma-to-es@4.3.6: @@ -15803,8 +15426,6 @@ snapshots: os-utils@0.0.14: {} - ospath@1.2.2: {} - otpauth@9.5.1: dependencies: '@noble/hashes': 2.2.0 @@ -15972,10 +15593,6 @@ snapshots: pathval@2.0.1: {} - pend@1.2.0: {} - - performance-now@2.1.0: {} - pg-cloudflare@1.4.0: optional: true @@ -16023,8 +15640,6 @@ snapshots: dependencies: execa: 9.6.1 - pify@2.3.0: {} - pino-abstract-transport@3.0.0: dependencies: split2: 4.2.0 @@ -16053,6 +15668,14 @@ snapshots: mlly: 1.8.2 pathe: 2.0.3 + playwright-core@1.56.0: {} + + playwright@1.56.0: + dependencies: + playwright-core: 1.56.0 + optionalDependencies: + fsevents: 2.3.2 + plimit-lit@1.6.1: dependencies: queue-lit: 1.5.2 @@ -16065,6 +15688,8 @@ snapshots: pngjs@5.0.0: {} + pngjs@7.0.0: {} + pnpm@11.9.0: {} polished@4.3.1: @@ -16111,8 +15736,6 @@ snapshots: prettier@3.9.1: {} - pretty-bytes@5.6.0: {} - pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 @@ -16166,8 +15789,6 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 - proxy-from-env@1.0.0: {} - proxy-from-env@2.1.0: {} ps-list@8.1.1: {} @@ -16243,11 +15864,6 @@ snapshots: pug-runtime: 3.0.1 pug-strip-comments: 2.0.0 - pump@3.0.4: - dependencies: - end-of-stream: 1.4.5 - once: 1.4.0 - punycode.js@2.3.1: {} punycode@2.3.1: {} @@ -16274,10 +15890,6 @@ snapshots: pngjs: 5.0.0 yargs: 15.4.1 - qs@6.14.2: - dependencies: - side-channel: 1.1.0 - qs@6.15.1: dependencies: side-channel: 1.1.0 @@ -16460,17 +16072,13 @@ snapshots: transitivePeerDependencies: - supports-color - request-progress@3.0.0: - dependencies: - throttleit: 1.0.1 - require-directory@2.1.1: {} require-from-string@2.0.2: {} require-in-the-middle@8.0.1: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 module-details-from-path: 1.0.4 transitivePeerDependencies: - supports-color @@ -16503,11 +16111,6 @@ snapshots: dependencies: lowercase-keys: 3.0.0 - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - ret@0.5.0: {} rettime@0.11.11: {} @@ -16580,7 +16183,7 @@ snapshots: router@2.2.0: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 @@ -16762,7 +16365,7 @@ snapshots: send@1.2.1: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -16930,7 +16533,7 @@ snapshots: dependencies: '@hapi/hoek': 11.0.7 '@hapi/wreck': 18.1.1 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 joi: 17.13.3 transitivePeerDependencies: - supports-color @@ -16952,6 +16555,12 @@ snapshots: nise: 6.1.5 supports-color: 7.2.0 + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + slacc-android-arm-eabi@0.1.5: optional: true @@ -17009,16 +16618,6 @@ snapshots: slash@3.0.0: {} - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - - slice-ansi@8.0.0: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - sonic-boom@4.2.1: dependencies: atomic-sleep: 1.0.0 @@ -17079,7 +16678,7 @@ snapshots: dependencies: arg: 5.0.2 check-more-types: 2.24.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 execa: 5.1.1 lazy-ass: 2.0.3 tree-kill: 1.2.2 @@ -17184,11 +16783,6 @@ snapshots: get-east-asian-width: 1.5.0 strip-ansi: 7.2.0 - string-width@8.2.1: - dependencies: - get-east-asian-width: 1.5.0 - strip-ansi: 7.2.0 - string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.9 @@ -17338,8 +16932,6 @@ snapshots: throttle-debounce@5.0.2: {} - throttleit@1.0.1: {} - tiny-invariant@1.3.3: {} tinybench@2.9.0: {} @@ -17363,14 +16955,8 @@ snapshots: tinyspy@4.0.4: {} - tldts-core@6.1.86: {} - tldts-core@7.0.30: {} - tldts@6.1.86: - dependencies: - tldts-core: 6.1.86 - tldts@7.0.30: dependencies: tldts-core: 7.0.30 @@ -17395,11 +16981,9 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 - touch@3.1.1: {} + totalist@3.0.1: {} - tough-cookie@5.1.2: - dependencies: - tldts: 6.1.86 + touch@3.1.1: {} tough-cookie@6.0.1: dependencies: @@ -17468,10 +17052,6 @@ snapshots: dependencies: tslib: 1.14.1 - tunnel-agent@0.6.0: - dependencies: - safe-buffer: 5.2.1 - tweetnacl@0.14.5: {} type-check@0.4.0: @@ -17549,7 +17129,7 @@ snapshots: '@sqltools/formatter': 1.2.5 ansis: 4.2.0 dayjs: 1.11.20 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 dedent: 1.7.2 reflect-metadata: 0.2.2 sql-highlight: 6.1.0 @@ -17651,8 +17231,6 @@ snapshots: until-async@3.0.2: {} - untildify@4.0.0: {} - uri-js-replace@1.0.1: {} uri-js@4.4.1: @@ -17738,21 +17316,21 @@ snapshots: vitest-fetch-mock@0.4.5(vitest@4.1.9): dependencies: - vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) vitest-mock-extended@4.0.0(typescript@5.9.3)(vitest@4.1.9): dependencies: ts-essentials: 10.2.0(typescript@5.9.3) typescript: 5.9.3 - vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) vitest-websocket-mock@0.5.0(vitest@4.1.9): dependencies: '@vitest/utils': 3.2.4 mock-socket: 9.3.1 - vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) + vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) - vitest@4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)): + vitest@4.1.9(@opentelemetry/api@1.9.1)(@types/node@26.0.1)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6))(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)): dependencies: '@vitest/expect': 4.1.9 '@vitest/mocker': 4.1.9(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4)) @@ -17777,7 +17355,8 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 26.0.1 - '@vitest/coverage-v8': 4.1.9(vitest@4.1.9) + '@vitest/browser-playwright': 4.1.9(bufferutil@4.1.0)(msw@2.14.6(@types/node@26.0.1)(typescript@5.9.3))(playwright@1.56.0)(utf-8-validate@6.0.6)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.22.4))(vitest@4.1.9) + '@vitest/coverage-v8': 4.1.9(@vitest/browser@4.1.9)(vitest@4.1.9) happy-dom: 20.10.6(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: - msw @@ -17836,7 +17415,7 @@ snapshots: vue-eslint-parser@10.4.1(eslint@9.39.4): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 eslint: 9.39.4 eslint-scope: 9.1.2 eslint-visitor-keys: 5.0.1 @@ -18092,11 +17671,6 @@ snapshots: y18n: 5.0.8 yargs-parser: 22.0.0 - yauzl@3.3.1: - dependencies: - buffer-crc32: 0.2.13 - pend: 1.2.0 - yocto-queue@0.1.0: {} yoctocolors@2.1.2: {}