[
  {
    "path": ".claude/agents/vitest-test-writer.md",
    "content": "---\nname: vitest-test-writer\ndescription: \"Use this agent when the user needs to write comprehensive tests for Vitest features. This includes unit tests for individual functions, integration tests for CLI functionality, and browser mode tests. The agent should be invoked when implementing new features that require test coverage, fixing bugs that need regression tests, or expanding test coverage for existing functionality.\\\\n\\\\nExamples:\\\\n\\\\n<example>\\\\nContext: User has just implemented a new utility function in the codebase.\\\\nuser: \\\"I just added a new parseConfig function to the config package\\\"\\\\nassistant: \\\"I see you've added a new function. Let me use the vitest-test-writer agent to create comprehensive tests for it.\\\"\\\\n<commentary>\\\\nSince a new function was added, use the Task tool to launch the vitest-test-writer agent to write unit tests in test/core.\\\\n</commentary>\\\\n</example>\\\\n\\\\n<example>\\\\nContext: User is working on a CLI feature.\\\\nuser: \\\"Please add a --json flag to the list command\\\"\\\\nassistant: \\\"I'll implement the --json flag for the list command.\\\"\\\\n<function call to implement the feature>\\\\nassistant: \\\"Now let me use the vitest-test-writer agent to write integration tests for this new CLI flag.\\\"\\\\n<commentary>\\\\nSince a CLI feature was implemented, use the Task tool to launch the vitest-test-writer agent to write integration tests in test/cli using runInlineTests.\\\\n</commentary>\\\\n</example>\\\\n\\\\n<example>\\\\nContext: User wants to ensure a feature works in both normal and browser modes.\\\\nuser: \\\"Can you write tests for the new snapshot feature?\\\"\\\\nassistant: \\\"I'll use the vitest-test-writer agent to write comprehensive tests for the snapshot feature, covering both normal and browser modes.\\\"\\\\n<commentary>\\\\nSince the feature needs testing in multiple modes, use the Task tool to launch the vitest-test-writer agent to write tests in test/cli (for features supporting both modes).\\\\n</commentary>\\\\n</example>\"\nmodel: opus\ncolor: green\n---\n\nYou are an expert test engineer specializing in the Vitest testing framework. You have deep knowledge of Vitest's architecture, testing patterns, and the specific conventions used in this monorepo.\n\n## Your Core Responsibilities\n\nYou write comprehensive, high-quality tests that follow the established patterns in this repository. You understand the distinction between unit tests, integration tests, and browser tests, and you place them in the correct locations.\n\n## Test Location Rules\n\n- **Unit tests**: Place in `test/core/`. These test individual functions by importing them directly, regardless of which package defines them.\n- **Integration tests**: Place in `test/cli/`. These test CLI functionality and features that require running Vitest as a process.\n- **Browser mode tests**: Place in `test/browser/`. However, if a feature supports both normal tests AND browser tests, place the tests in `test/cli/`.\n\n## Testing Patterns You Must Follow\n\n### Use runInlineTests Utility\nFor integration tests, always use the `runInlineTests` utility to create and run test scenarios. This utility allows you to define inline test files and validate their output.\n\n### Snapshot Validation with toMatchInlineSnapshot\nAlways validate output using `toMatchInlineSnapshot()`. The snapshot is automatically generated on the first run. This is the preferred method because it:\n- Captures the exact expected output\n- Makes changes visible in code review\n- Catches regressions precisely\n\n### Avoid toContain\nDo NOT use `toContain()` for output validation. This method fails to catch:\n- Extra unexpected output\n- Repeated output that shouldn't occur\n- Subtle formatting differences\n\n### Handle Dynamic Content\nWhen output contains dynamic content (timestamps, absolute paths, durations, etc.):\n1. First check `test-utils` for existing utilities that normalize this content\n2. If no utility exists, manually process with `stdout.replace(regexp, 'normalized-value')`\n3. Common patterns to normalize:\n   - Timing information (e.g., `1.234s` → `[time]`)\n   - Root paths (e.g., `/Users/name/project` → `<root>`)\n   - Process IDs or temporary file paths\n\n### Validate Test Results with testTree or errorTree\nTo ensure all tests actually passed (not just that they ran), use `testTree` or `errorTree` helpers. Pass the result to `toMatchInlineSnapshot()` to verify:\n- The correct number of tests ran\n- Tests are organized in the expected suites\n- No unexpected failures or skipped tests\n\n## Writing Unit Tests\n\nFor unit tests in `test/core/`:\n1. Import the function directly from its source package\n2. Test pure functionality without process spawning\n3. Cover edge cases, error conditions, and typical usage\n4. Use descriptive test names that explain the scenario\n\n## Writing Integration Tests\n\nFor integration tests in `test/cli/`:\n1. Use `runInlineTests` to define test scenarios\n2. Create realistic test file content\n3. Validate both stderr and the test results structure\n4. Test error scenarios and edge cases\n5. Ensure tests are deterministic (no flaky behavior)\n\n## Quality Standards\n\n- Every test should have a clear purpose\n- Test names should describe the behavior being verified\n- Group related tests in describe blocks\n- Include both positive (happy path) and negative (error) test cases\n- Consider boundary conditions and edge cases\n- Tests should be independent and not rely on execution order\n- If you encounter a bug in the behaviour, write a **failing** test and report that there is a bug or an unexpected behaviour. If possible, delegate fixing the bug to the main agent\n\n## Before Writing Tests\n\n1. Read AGENTS.md for additional context and patterns\n2. Look at existing tests in the target directory for style guidance\n3. Identify the test utilities available in the codebase\n4. Understand what behavior needs to be verified\n\n## Output Format\n\nWhen writing tests, provide:\n1. The complete test file with all imports\n2. Explanations of what each test verifies\n3. Notes on any dynamic content normalization applied\n4. Suggestions for additional test cases if relevant\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n\ntest/cli/fixtures/reporters/indicator-position.test.js eol=crlf\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [vitest-dev, sheremet-va, antfu, patak-dev]\nopen_collective: vitest\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: 🐞 Bug report\ndescription: Report an issue with Vitest\nlabels: [pending triage]\ntype: Bug\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this bug report!\n  - type: textarea\n    id: bug-description\n    attributes:\n      label: Describe the bug\n      description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!\n      placeholder: I am doing ... What I expect is ... What actually happening is ...\n    validations:\n      required: true\n  - type: textarea\n    id: reproduction\n    attributes:\n      label: Reproduction\n      description: Please provide a link to a github repository that can reproduce the problem you ran into (feel free to clone one of the [examples](https://github.com/vitest-dev/vitest/tree/main/examples)). You can also use [StackBlitz](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/basic?initialPath=__vitest__/) if it works. A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is always required no matter how easy it is to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a \"needs reproduction\" label. If no reproduction is provided after 3 days, it will be auto-closed.\n      placeholder: Reproduction\n    validations:\n      required: true\n  - type: textarea\n    id: system-info\n    attributes:\n      label: System Info\n      description: Output of `npx envinfo --system --npmPackages '{vitest*,@vitest/*,vite,@vitejs/*,playwright,webdriverio}' --binaries --browsers`\n      render: shell\n      placeholder: System, Binaries, Browsers\n    validations:\n      required: true\n  - type: dropdown\n    id: package-manager\n    attributes:\n      label: Used Package Manager\n      description: Select the used package manager\n      options:\n        - npm\n        - yarn\n        - pnpm\n        - bun\n    validations:\n      required: true\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Follow our [Code of Conduct](https://github.com/vitest-dev/vitest/blob/main/CODE_OF_CONDUCT.md)\n          required: true\n        - label: Read the [Contributing Guidelines](https://github.com/vitest-dev/vitest/blob/main/CONTRIBUTING.md).\n          required: true\n        - label: Read the [docs](https://vitest.dev/guide/).\n          required: true\n        - label: Check that there isn't [already an issue](https://github.com/vitest-dev/vitest/issues) that reports the same bug to avoid creating a duplicate.\n          required: true\n        - label: Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/vitest-dev/vitest/discussions) or join our [Discord Chat Server](https://chat.vitest.dev).\n          required: true\n        - label: The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: VS Code Extension Issues\n    url: https://github.com/vitest-dev/vscode/issues/new/choose\n    about: VS Code extension related issues should be reported on the vitest-dev/vscode repository.\n  - name: Discord Chat\n    url: https://chat.vitest.dev\n    about: Ask questions and discuss with other Vitest users in real time.\n  - name: Questions & Discussions\n    url: https://github.com/vitest-dev/vitest/discussions\n    about: Use GitHub discussions for message-board style questions and discussions.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/docs.yml",
    "content": "name: 📚 Documentation\ndescription: Suggest a change or new page to be added to vitest.dev\nlabels: [documentation]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this issue!\n  - type: checkboxes\n    id: documentation_is\n    attributes:\n      label: Documentation is\n      options:\n        - label: Missing\n        - label: Outdated\n        - label: Confusing\n        - label: Not sure?\n  - type: textarea\n    id: description\n    attributes:\n      label: Explain in Detail\n      description: A clear and concise description of your suggestion. If you intend to submit a PR for this issue, tell us in the description. Thanks!\n      placeholder: The description of ... page is not clear. I thought it meant ... but it wasn't.\n    validations:\n      required: true\n  - type: textarea\n    id: suggestion\n    attributes:\n      label: Your Suggestion for Changes\n    validations:\n      required: true\n  - type: input\n    id: reproduction\n    attributes:\n      label: Reproduction\n      description: If you have a reproduction, please provide a link via [vitest.new](https://vitest.new/) or a link to a repo that can reproduce the problem you ran into.\n      placeholder: Reproduction URL\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: 🚀 New feature proposal\ndescription: Propose a new feature to be added to Vitest\nlabels: ['enhancement: pending triage']\ntype: Feature\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for your interest in the project and taking the time to fill out this feature report!\n  - type: textarea\n    id: feature-description\n    attributes:\n      label: Clear and concise description of the problem\n      description: 'As a developer using Vitest I want [goal / wish] so that [benefit]. If you intend to submit a PR for this issue, tell us in the description. Thanks!'\n    validations:\n      required: true\n  - type: textarea\n    id: suggested-solution\n    attributes:\n      label: Suggested solution\n      description: We could provide following implementation...\n    validations:\n      required: true\n  - type: textarea\n    id: alternative\n    attributes:\n      label: Alternative\n      description: Clear and concise description of any alternative solutions or features you've considered.\n  - type: textarea\n    id: additional-context\n    attributes:\n      label: Additional context\n      description: Any other context or screenshots about the feature request here.\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Follow our [Code of Conduct](https://github.com/vitest-dev/vitest/blob/main/CODE_OF_CONDUCT.md)\n          required: true\n        - label: Read the [Contributing Guidelines](https://github.com/vitest-dev/vitest/blob/main/CONTRIBUTING.md).\n          required: true\n        - label: Read the [docs](https://vitest.dev/guide/).\n          required: true\n        - label: Check that there isn't already an issue that requests the same feature to avoid creating a duplicate.\n          required: true\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "### Description\n\n<!-- Please insert your description here and provide especially info about the \"what\" this PR is solving -->\n\nResolves #issue-number\n\n<!-- You can also add additional context here -->\n\n### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:\n- [ ] It's really useful if your PR references an issue where it is discussed ahead of time. If the feature is substantial or introduces breaking changes without a discussion, PR might be closed.\n- [ ] Ideally, include a test that fails without this PR but passes with it.\n- [ ] Please, don't make changes to `pnpm-lock.yaml` unless you introduce a new test example.\n- [ ] Please check [Allow edits by maintainers](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) to make review process faster. Note that this option is not available for repositories that are owned by Github organizations.\n\n### Tests\n- [ ] Run the tests with `pnpm test:ci`.\n\n### Documentation\n- [ ] If you introduce new functionality, document it. You can run documentation with `pnpm run docs` command.\n\n### Changesets\n- [ ] Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with `feat:`, `fix:`, `perf:`, `docs:`, or `chore:`.\n"
  },
  {
    "path": ".github/actions/setup-and-cache/action.yml",
    "content": "name: Setup and cache\ndescription: Setup for node, pnpm and cache for browser testing binaries\ninputs:\n  node-version:\n    required: false\n    description: Node version for setup-node\n    default: 24.x\n\nruns:\n  using: composite\n\n  steps:\n    - name: Install pnpm\n      uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0\n\n    - name: Set node version to ${{ inputs.node-version }}\n      uses: actions/setup-node@v6\n      with:\n        node-version: ${{ inputs.node-version }}\n        cache: pnpm\n"
  },
  {
    "path": ".github/actions/setup-playwright/action.yml",
    "content": "name: Setup Playwright\ndescription: Setup and cache Playwright browser binaries\n\nruns:\n  using: composite\n  steps:\n    - name: Resolve package versions\n      id: resolve-package-versions\n      shell: bash\n      run: >\n        echo \"$(\n          node -e \"\n            const fs = require('fs');\n            const lockfile = fs.readFileSync('./pnpm-lock.yaml', 'utf8');\n            const pattern = (name) => new RegExp(name + ':\\\\\\s+specifier: [\\\\\\s\\\\\\w\\\\\\.^]+version: (\\\\\\d+\\\\\\.\\\\\\d+\\\\\\.\\\\\\d+)');\n            const playwrightVersion = lockfile.match(pattern('playwright'))[1];\n            console.log('PLAYWRIGHT_VERSION=' + playwrightVersion);\n          \"\n        )\" >> $GITHUB_OUTPUT\n\n    - name: Print versions\n      shell: bash\n      run: echo \"${{ toJson(steps.resolve-package-versions.outputs) }}\"\n\n    - name: Check resolved package versions\n      shell: bash\n      if: |\n        contains(fromJSON('[null, \"\", \"undefined\"]'), steps.resolve-package-versions.outputs.PLAYWRIGHT_VERSION)\n      run: echo \"Failed to resolve package versions. See log above.\" && exit 1\n\n    - name: Cache Playwright v${{ steps.resolve-package-versions.outputs.PLAYWRIGHT_VERSION }}\n      uses: actions/cache@v5\n      id: playwright-cache\n      with:\n        path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }}\n        key: ${{ runner.os }}-playwright-${{ steps.resolve-package-versions.outputs.PLAYWRIGHT_VERSION }}\n        restore-keys: |\n          ${{ runner.os }}-playwright-\n\n    - name: Install Playwright Dependencies\n      shell: bash\n      if: steps.playwright-cache.outputs.cache-hit != 'true'\n      run: pnpm exec playwright install --with-deps --only-shell\n"
  },
  {
    "path": ".github/commit-convention.md",
    "content": "## Git Commit Message Convention\n\n> This is adapted from [Angular's commit convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular).\n\n### TL;DR:\n\nMessages must be matched by the following regex:\n\n<!-- prettier-ignore -->\n```js\n/^(revert: )?(feat|fix|docs|dx|refactor|perf|test|workflow|build|ci|chore|types|wip|release|deps)(\\(.+\\))?: .{1,50}/\n```\n\n#### Examples\n\nAppears under \"Features\" header, `dev` subheader:\n\n```\nfeat(dev): add 'comments' option\n```\n\nAppears under \"Bug Fixes\" header, `dev` subheader, with a link to issue #28:\n\n```\nfix(dev): fix dev error\n\nclose #28\n```\n\nAppears under \"Performance Improvements\" header, and under \"Breaking Changes\" with the breaking change explanation:\n\n```\nperf(build): remove 'foo' option\n\nBREAKING CHANGE: The 'foo' option has been removed.\n```\n\nThe following commit and commit `667ecc1` do not appear in the changelog if they are under the same release. If not, the revert commit appears under the \"Reverts\" header.\n\n```\nrevert: feat(compiler): add 'comments' option\n\nThis reverts commit 667ecc1654a317a13331b17617d973392f415f02.\n```\n\n### Full Message Format\n\nA commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**:\n\n```\n<type>(<scope>): <subject>\n<BLANK LINE>\n<body>\n<BLANK LINE>\n<footer>\n```\n\nThe **header** is mandatory and the **scope** of the header is optional.\n\n### Revert\n\nIf the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body, it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.\n\n### Type\n\nIf the prefix is `feat`, `fix` or `perf`, it will appear in the changelog. However, if there is any [BREAKING CHANGE](#footer), the commit will always appear in the changelog.\n\nOther prefixes are up to your discretion. Suggested prefixes are `docs`, `chore`, `style`, `refactor`, and `test` for non-changelog related tasks.\n\n### Scope\n\nThe scope could be anything specifying the place of the commit change. For example `dev`, `build`, `workflow`, `cli` etc...\n\n### Subject\n\nThe subject contains a succinct description of the change:\n\n- use the imperative, present tense: \"change\" not \"changed\" nor \"changes\"\n- don't capitalize the first letter\n- no dot (.) at the end\n\n### Body\n\nJust as in the **subject**, use the imperative, present tense: \"change\" not \"changed\" nor \"changes\".\nThe body should include the motivation for the change and contrast this with previous behavior.\n\n### Footer\n\nThe footer should contain any information about **Breaking Changes** and is also the place to\nreference GitHub issues that this commit **Closes**.\n\n**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.\n"
  },
  {
    "path": ".github/copilot-instructions.md",
    "content": "# copilot-instructions.md\n\nThis file provides guidance to Copilot Agent when working with code in this repository.\n\n## Codebase Overview\n\nVitest is a next-generation testing framework powered by Vite. This is a monorepo using pnpm workspaces.\n\n## Essential references\n\n- Agent-specific guide: See [AGENTS.md](../AGENTS.md)\n"
  },
  {
    "path": ".github/renovate.json5",
    "content": "{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\"config:recommended\", \"schedule:weekly\", \"group:allNonMajor\"],\n  \"labels\": [\"dependencies\"],\n  \"rangeStrategy\": \"bump\",\n  \"packageRules\": [\n    {\n      \"groupName\": \"Eslint packages\",\n      \"matchPackageNames\": [\"/eslint/\"]\n    },\n    {\n      \"matchDepTypes\": [\"peerDependencies\"],\n      \"enabled\": false\n    },\n    {\n      \"matchDepTypes\": [\"action\"],\n      \"matchPackageNames\": [\"!actions/{/,}**\", \"!github/{/,}**\"],\n      \"pinDigests\": true\n    }\n  ],\n  \"ignoreDeps\": [\n    // manually bumping\n    \"node\",\n    \"vite\",\n    // we patch these packages\n    \"@types/chai\",\n    \"@sinonjs/fake-timers\",\n    \"cac\",\n    // Transitive dependency that we patch\n    \"acorn\",\n    // Keep using codemirror 5\n    \"codemirror\",\n    \"react-18\",\n    \"react-is-18\",\n    // webdriverio removed provenance: https://github.com/webdriverio/webdriverio/issues/14887\n    \"webdriverio\"\n  ],\n  \"ignorePaths\": [\n    \"**/node_modules/**\"\n  ]\n}\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\n# Remove default permissions of GITHUB_TOKEN for security\n# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs\npermissions: {}\n\non:\n  push:\n    branches:\n      - main\n\n  pull_request:\n\n  workflow_dispatch:\n\nconcurrency:\n  group: ci-${{ github.event.pull_request.number || github.ref }}\n  cancel-in-progress: true\n\nenv:\n  PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/.cache/ms-playwright\n  VITEST_GENERATE_UI_TOKEN: 'true'\n\njobs:\n  lint:\n    timeout-minutes: 10\n    runs-on: ubuntu-latest\n    name: 'Lint: node-latest, ubuntu-latest'\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: ./.github/actions/setup-and-cache\n\n      - name: Install\n        run: pnpm i\n\n      - name: Build\n        run: pnpm run build\n\n      - name: Generate CLI docs\n        run: pnpm -C docs run cli-table\n\n      # check uncommited LICENSE.md, auto-imports.d.ts, etc...\n      - name: Check stale build artifacts\n        run: git diff --exit-code\n\n      - name: Lint\n        run: pnpm run lint\n\n      - name: Typecheck\n        run: pnpm run typecheck\n\n      - name: Typecheck UI\n        run: pnpm run -C packages/ui typecheck:client\n\n      # From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions\n      - name: Check workflow files\n        run: |\n          bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)\n          ./actionlint -color -shellcheck=\"\"\n\n  changed:\n    runs-on: ubuntu-latest\n    name: 'Diff: node-latest, ubuntu-latest'\n    outputs:\n      should_skip: ${{ steps.changed-files.outputs.only_changed == 'true' }}\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Get changed files\n        id: changed-files\n        uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5\n        with:\n          files: |\n            docs/**\n            .github/**\n            !.github/workflows/ci.yml\n            **.md\n\n  test:\n    needs: changed\n    name: 'Build&Test: node-${{ matrix.node_version }}, ${{ matrix.os }}'\n    if: needs.changed.outputs.should_skip != 'true'\n    runs-on: ${{ matrix.os }}\n\n    timeout-minutes: 30\n\n    strategy:\n      matrix:\n        os: [ubuntu-latest]\n        node_version: [20, 22, 24]\n        include:\n          - os: macos-latest\n            node_version: 24\n          - os: windows-latest\n            node_version: 24\n      fail-fast: false\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: ./.github/actions/setup-and-cache\n        with:\n          node-version: ${{ matrix.node_version }}\n\n      - uses: browser-actions/setup-chrome@4f8e94349a351df0f048634f25fec36c3c91eded # v2.1.1\n\n      - name: Install\n        run: pnpm i\n\n      - uses: ./.github/actions/setup-playwright\n\n      - name: Build\n        run: pnpm run build\n\n      - name: Test\n        run: pnpm run test:ci\n\n      - name: Test Examples\n        run: pnpm run test:examples\n\n      - uses: actions/upload-artifact@v7\n        if: ${{ !cancelled() }}\n        with:\n          name: playwright-report-${{ matrix.os }}-node-${{ matrix.node_version }}\n          path: test/ui/test-results/\n          retention-days: 30\n\n  test-cached:\n    needs: changed\n    name: 'Cache&Test: node-${{ matrix.node_version }}, ${{ matrix.os }}'\n    if: needs.changed.outputs.should_skip != 'true'\n    runs-on: ${{ matrix.os }}\n\n    timeout-minutes: 30\n\n    strategy:\n      matrix:\n        node_version: [24]\n        os:\n          - macos-latest\n          - windows-latest\n      fail-fast: false\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: ./.github/actions/setup-and-cache\n        with:\n          node-version: ${{ matrix.node_version }}\n\n      - uses: browser-actions/setup-chrome@4f8e94349a351df0f048634f25fec36c3c91eded # v2.1.1\n\n      - name: Install\n        run: pnpm i\n\n      - uses: ./.github/actions/setup-playwright\n\n      - name: Build\n        run: pnpm run build\n\n      - name: Test\n        run: pnpm run test:ci:cache\n\n  test-browser:\n    needs: changed\n    name: 'Browsers: node-${{ matrix.node_version }}, ${{ matrix.os }}'\n    if: needs.changed.outputs.should_skip != 'true'\n\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        node_version: [24]\n        os:\n          - macos-latest\n          - windows-latest\n      fail-fast: false\n\n    timeout-minutes: 30\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: ./.github/actions/setup-and-cache\n        with:\n          node-version: ${{ matrix.node_version }}\n\n      - uses: browser-actions/setup-chrome@4f8e94349a351df0f048634f25fec36c3c91eded # v2.1.1\n      - uses: browser-actions/setup-firefox@fcf821c621167805dd63a29662bd7cb5676c81a8 # v1.7.1\n\n      - name: Install\n        run: pnpm i\n\n      - uses: ./.github/actions/setup-playwright\n\n      - name: Build\n        run: pnpm run build\n\n      - name: Test Browser (playwright)\n        run: pnpm run test:browser:playwright\n\n      - name: Test Browser (webdriverio)\n        run: pnpm run test:browser:webdriverio\n\n  test-rolldown:\n    needs: changed\n    # macos-latest is the fastest one\n    name: 'Rolldown&Test: node-22, macos-latest'\n    if: needs.changed.outputs.should_skip != 'true'\n    runs-on: macos-latest\n\n    timeout-minutes: 30\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: ./.github/actions/setup-and-cache\n        with:\n          node-version: 22\n\n      - uses: browser-actions/setup-chrome@4f8e94349a351df0f048634f25fec36c3c91eded # v2.1.1\n\n      - name: Install\n        run: |\n          yq -i '.overrides.vite = \"npm:vite@8\"' pnpm-workspace.yaml\n          git add . && git commit -m \"ci\" && pnpm i --prefer-offline --no-frozen-lockfile\n\n      - uses: ./.github/actions/setup-playwright\n\n      - name: Build\n        run: pnpm run build\n\n      - name: Test\n        run: pnpm run test:ci:no-bail\n\n      - name: Test Examples\n        if: ${{ !cancelled() }}\n        run: pnpm run test:examples\n\n      - name: Test Browser (playwright)\n        if: ${{ !cancelled() }}\n        run: pnpm run test:browser:playwright\n\n      - uses: actions/upload-artifact@v7\n        if: ${{ !cancelled() }}\n        with:\n          name: playwright-report-rolldown\n          path: rolldown/test/ui/test-results/\n          retention-days: 30\n"
  },
  {
    "path": ".github/workflows/cr.yml",
    "content": "name: CR\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    types: [opened, synchronize, labeled]\n\npermissions: {}\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.number }}\n  cancel-in-progress: true\n\njobs:\n  release:\n    if: github.repository == 'vitest-dev/vitest' && (github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'cr-tracked'))\n    runs-on: ubuntu-latest\n    name: 'Release: pkg.pr.new'\n\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0\n\n      - name: Set node version to 20\n        uses: actions/setup-node@v6\n        with:\n          node-version: 20\n          registry-url: https://registry.npmjs.org/\n          cache: pnpm\n\n      - name: Install\n        run: pnpm install --frozen-lockfile --prefer-offline\n        env:\n          PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'\n\n      - name: Build\n        run: pnpm build\n        env:\n          VITEST_GENERATE_UI_TOKEN: 'true'\n          VITE_TEST_WATCHER_DEBUG: 'false'\n\n      - name: Publish to StackBlitz\n        run: pnpx pkg-pr-new publish --compact --no-template --pnpm './packages/*'\n"
  },
  {
    "path": ".github/workflows/ecosystem-ci-trigger.yml",
    "content": "name: ecosystem-ci trigger\n\non:\n  issue_comment:\n    types: [created]\n\njobs:\n  trigger:\n    runs-on: ubuntu-latest\n    if: github.repository == 'vitest-dev/vitest' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run')\n    permissions:\n      issues: write # to add / delete reactions, post comments\n      pull-requests: write # to read PR data, and to add labels\n      actions: read # to check workflow status\n      contents: read # to clone the repo\n    steps:\n      - uses: actions/github-script@v8\n        with:\n          script: |\n            const user = context.payload.sender.login\n            console.log(`Validate user: ${user}`)\n\n            let hasTriagePermission = false\n            try {\n              const { data } = await github.rest.repos.getCollaboratorPermissionLevel({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                username: user,\n              });\n              hasTriagePermission = data.user.permissions.triage\n            } catch (e) {\n              console.warn(e)\n            }\n\n            if (hasTriagePermission) {\n              console.log('Allowed')\n              await github.rest.reactions.createForIssueComment({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                comment_id: context.payload.comment.id,\n                content: '+1',\n              })\n            } else {\n              console.log('Not allowed')\n              await github.rest.reactions.createForIssueComment({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                comment_id: context.payload.comment.id,\n                content: '-1',\n              })\n              throw new Error('not allowed')\n            }\n      - uses: actions/github-script@v8\n        id: get-pr-data\n        with:\n          script: |\n            console.log(`Get PR info: ${context.repo.owner}/${context.repo.repo}#${context.issue.number}`)\n            const { data: pr } = await github.rest.pulls.get({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              pull_number: context.issue.number\n            })\n            return {\n              num: context.issue.number,\n              branchName: pr.head.ref,\n              repo: pr.head.repo.full_name\n            }\n      - id: generate-token\n        uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0\n        with:\n          app_id: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_ID }}\n          installation_retrieval_payload: '${{ github.repository_owner }}/vitest-ecosystem-ci'\n          private_key: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY }}\n      - uses: actions/github-script@v8\n        id: trigger\n        env:\n          COMMENT: ${{ github.event.comment.body }}\n          PR_DATA: ${{ steps.get-pr-data.outputs.result }}\n        with:\n          github-token: ${{ steps.generate-token.outputs.token }}\n          result-encoding: string\n          script: |\n            const comment = process.env.COMMENT.trim()\n            const prData = JSON.parse(process.env.PR_DATA)\n\n            const suite = comment.split('\\n')[0].replace(/^\\/ecosystem-ci run/, '').trim()\n\n            await github.rest.actions.createWorkflowDispatch({\n              owner: context.repo.owner,\n              repo: 'vitest-ecosystem-ci',\n              workflow_id: 'ecosystem-ci-from-pr.yml',\n              ref: 'main',\n              inputs: {\n                prNumber: '' + prData.num,\n                branchName: prData.branchName,\n                repo: prData.repo,\n                suite: suite === '' ? '-' : suite\n              }\n            })\n"
  },
  {
    "path": ".github/workflows/issue-close-require.yml",
    "content": "name: Issue Close Require\n\non:\n  schedule:\n    - cron: '0 0 * * *'\n\njobs:\n  close-issues:\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write # for actions-cool/issues-helper to update issues\n    steps:\n      - name: needs reproduction\n        uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6\n        with:\n          actions: close-issues\n          token: ${{ secrets.GITHUB_TOKEN }}\n          labels: needs reproduction\n          inactive-day: 3\n"
  },
  {
    "path": ".github/workflows/issue-labeled.yml",
    "content": "name: Issue Labeled\n\non:\n  issues:\n    types: [labeled]\n\njobs:\n  reply-labeled:\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write # for actions-cool/issues-helper to update issues\n    steps:\n      - name: needs reproduction\n        if: github.event.label.name == 'needs reproduction'\n        uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6\n        with:\n          actions: create-comment\n          token: ${{ secrets.GITHUB_TOKEN }}\n          issue-number: ${{ github.event.issue.number }}\n          body: |\n            Hello @${{ github.event.issue.user.login }}. Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository or [StackBlitz](https://vitest.new) (you can also use [examples](https://github.com/vitest-dev/vitest/tree/main/examples)). Issues marked with `needs reproduction` will be closed if they have no activity within 3 days.\n"
  },
  {
    "path": ".github/workflows/lock-closed-issues.yml",
    "content": "name: Lock Closed Issues\n\non:\n  schedule:\n    - cron: '0 0 * * *'\n\npermissions:\n  issues: write\n\njobs:\n  action:\n    if: github.repository == 'vitest-dev/vitest'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v6.0.0\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          issue-inactive-days: '14'\n          pr-inactive-days: '14'\n          issue-lock-reason: ''\n          pr-lock-reason: ''\n          process-only: issues,prs\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish Package\n\non:\n  push:\n    tags:\n      - 'v*'\n\npermissions:\n  contents: write\n  id-token: write\n\nenv:\n  VITEST_GENERATE_UI_TOKEN: 'true'\n  VITE_TEST_WATCHER_DEBUG: 'false'\n\njobs:\n  publish:\n    if: github.repository == 'vitest-dev/vitest'\n    runs-on: ubuntu-latest\n    environment: Release\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0\n\n      - name: Set node version to 20\n        uses: actions/setup-node@v6\n        with:\n          node-version: 20\n          registry-url: https://registry.npmjs.org/\n          cache: pnpm\n\n      - name: Install\n        run: pnpm install --frozen-lockfile --prefer-offline\n        env:\n          PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'\n\n      - name: Build\n        run: pnpm build\n\n      - name: Publish to npm\n        run: npm i -g npm@^11.5.2 && pnpm run publish-ci ${{ github.ref_name }}\n\n      - name: Generate Changelog\n        run: npx changelogithub\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n*.cpuprofile\n*.heapprofile\nlib-cov\ncoverage\n!**/integrations/coverage\nnode_modules\n.env\n.cache\ndist\n.idea\n.vite-node\nltex*\n.DS_Store\n.zed\nbench/test/*/*/\n**/bench.json\n**/browser/browser.json\ndocs/public/user-avatars\n.eslintcache\ndocs/.vitepress/cache/\n!test/cli/fixtures/dotted-files/**/.cache\ntest/**/__screenshots__/**/*\ntest/**/__traces__/**/*\ntest/browser/fixtures/update-snapshot/basic.test.ts\ntest/cli/fixtures/browser-multiple/basic-*\n.vitest-reports\n*.tsbuildinfo\n# exclude static html reporter folder\ntest/browser/html/\ntest/core/html/\n.vitest-attachments\nexplainFiles.txt\n.vitest-dump\n"
  },
  {
    "path": ".npmrc",
    "content": "ignore-workspace-root-check=true\nstrict-peer-dependencies=false\nprovenance=true\nshell-emulator=true\nregistry=https://registry.npmjs.org/\nVITEST_MODULE_DIRECTORIES=/node_modules/,/packages/\n"
  },
  {
    "path": ".tazerc.json",
    "content": "{\n  \"exclude\": [\n    \"vue\",\n    \"pretty-format\"\n  ],\n  \"packageMode\": {\n    \"vue\": \"minor\",\n    \"codemirror\": \"minor\",\n    \"rollup\": \"minor\"\n  }\n}\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"vitest.explorer\",\n    \"dbaeumer.vscode-eslint\"\n  ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  // Disable the default formatter, use eslint instead\n  \"prettier.enable\": false,\n  \"editor.formatOnSave\": false,\n\n  // Auto fix\n  \"editor.codeActionsOnSave\": {\n    \"source.fixAll.eslint\": \"explicit\",\n    \"source.organizeImports\": \"never\"\n  },\n\n  // Silent the stylistic rules in you IDE, but still auto fix them\n  // \"eslint.rules.customizations\": [\n  //   { \"rule\": \"style/*\", \"severity\": \"off\" },\n  //   { \"rule\": \"*-indent\", \"severity\": \"off\" },\n  //   { \"rule\": \"*-spacing\", \"severity\": \"off\" },\n  //   { \"rule\": \"*-spaces\", \"severity\": \"off\" },\n  //   { \"rule\": \"*-order\", \"severity\": \"off\" },\n  //   { \"rule\": \"*-dangle\", \"severity\": \"off\" },\n  //   { \"rule\": \"*-newline\", \"severity\": \"off\" },\n  //   { \"rule\": \"*quotes\", \"severity\": \"off\" },\n  //   { \"rule\": \"*semi\", \"severity\": \"off\" }\n  // ],\n\n  \"vitest.ignoreWorkspace\": true,\n  \"vitest.configSearchPatternInclude\": \"test/{core,cli,config,browser,reporters}/{vitest,vite}.{config.ts,config.unit.mts}\",\n  \"testing.automaticallyOpenTestResults\": \"neverOpen\",\n\n  // Enable eslint for all supported languages\n  \"eslint.validate\": [\n    \"javascript\",\n    \"javascriptreact\",\n    \"typescript\",\n    \"typescriptreact\",\n    \"vue\",\n    \"html\",\n    \"markdown\",\n    \"json\",\n    \"jsonc\",\n    \"yaml\"\n  ],\n  // Use the project's typescript version\n  \"typescript.tsdk\": \"node_modules/typescript/lib\"\n}\n"
  },
  {
    "path": ".vscode/tasks.json",
    "content": "{\n  \"version\": \"2.0.0\",\n  \"tasks\": [\n    {\n      \"type\": \"npm\",\n      \"script\": \"dev\",\n      \"label\": \"npm: dev\",\n      \"isBackground\": true,\n      \"problemMatcher\": {\n        \"owner\": \"typescript\",\n        \"fileLocation\": \"relative\",\n        \"pattern\": {\n          \"regexp\": \"^(.*):(\\\\d+):(\\\\d+):\\\\s+(warning|error):\\\\s+(.*)$\",\n          \"file\": 1,\n          \"line\": 2,\n          \"column\": 3,\n          \"severity\": 4,\n          \"message\": 5\n        },\n        \"background\": {\n          \"activeOnStart\": true,\n          \"beginsPattern\": \"bundes\",\n          \"endsPattern\": \"created\"\n        }\n      }\n    },\n    {\n      \"type\": \"npm\",\n      \"script\": \"ui:dev\",\n      \"label\": \"npm: ui\",\n      \"isBackground\": true,\n      \"dependsOn\": [\"npm: test\"],\n      \"group\": {\n        \"kind\": \"build\",\n        \"isDefault\": true\n      },\n      \"problemMatcher\": {\n        \"owner\": \"typescript\",\n        \"fileLocation\": \"relative\",\n        \"pattern\": {\n          \"regexp\": \"^(.*):(\\\\d+):(\\\\d+):\\\\s+(warning|error):\\\\s+(.*)$\",\n          \"file\": 1,\n          \"line\": 2,\n          \"column\": 3,\n          \"severity\": 4,\n          \"message\": 5\n        },\n        \"background\": {\n          \"activeOnStart\": true,\n          \"beginsPattern\": \"dev server running at\",\n          \"endsPattern\": \"ready in\"\n        }\n      }\n    },\n    {\n      \"type\": \"npm\",\n      \"script\": \"test\",\n      \"label\": \"npm: test\",\n      \"isBackground\": true,\n      \"dependsOn\": [\"npm: dev\"],\n      \"detail\": \"vitest -r test/core --api\",\n      \"problemMatcher\": {\n        \"owner\": \"typescript\",\n        \"fileLocation\": \"relative\",\n        \"pattern\": {\n          \"regexp\": \"^(.*):(\\\\d+):(\\\\d+):\\\\s+(warning|error):\\\\s+(.*)$\",\n          \"file\": 1,\n          \"line\": 2,\n          \"column\": 3,\n          \"severity\": 4,\n          \"message\": 5\n        },\n        \"background\": {\n          \"activeOnStart\": true,\n          \"beginsPattern\": \"WATCH\",\n          \"endsPattern\": \"Waiting for\"\n        }\n      }\n    },\n    {\n      \"type\": \"npm\",\n      \"script\": \"ci\",\n      \"problemMatcher\": [],\n      \"label\": \"npm: ci\"\n    }\n  ]\n}\n"
  },
  {
    "path": "AGENTS.md",
    "content": "# Vitest AI Agent Guide\n\nThis document provides comprehensive information for AI agents working on the Vitest codebase.\n\n## Project Overview\n\nVitest is a next-generation testing framework powered by Vite. This is a monorepo using pnpm workspaces with the following key characteristics:\n\n- **Language**: TypeScript/JavaScript (ESM-first)\n- **Package Manager**: pnpm (required)\n- **Node Version**: ^20.0.0 || ^22.0.0 || >=24.0.0\n- **Build System**: Vite + Rollup\n- **Monorepo Structure**: 15+ packages in `packages/` directory\n\n## Setup and Development\n\n### Initial Setup\n1. Run `pnpm install` to install dependencies\n2. Run `pnpm build` to build all packages\n3. Install Playwright browsers when working with browser features: `npx playwright install --with-deps`\n\n### Key Scripts\n- `pnpm build` - Build all packages\n- `pnpm dev` - Watch mode for development\n- `pnpm lint` - Run ESLint\n- `pnpm lint:fix` - Fix linting issues automatically\n- `pnpm typecheck` - Run TypeScript type checking\n\n## Testing\n\n### Running Tests\n- **All tests**: `CI=true pnpm test:ci`\n- **Examples**: `CI=true pnpm test:examples`\n- **Specific test suite**: `CI=true cd test/<test-folder> && pnpm test <test-file>`\n- **Core directory test**: `CI=true pnpm test <test-file>` (for `test/core`)\n- **Browser tests**: `CI=true pnpm test:browser:playwright` or `CI=true pnpm test:browser:webdriverio`\n\n**IMPORTANT: Do NOT use `--` when passing test filters to pnpm.**\nUsing `--` causes pnpm to drop the filter, resulting in a full test run instead of a filtered one.\n\n```bash\n# WRONG - runs ALL tests (filter is ignored):\npnpm test -- basic.test.ts -t 'expect'\n\n# CORRECT - runs only matching tests:\npnpm test basic.test.ts -t 'expect'\n```\n\nWhen writing tests, AVOID using `toContain` for validation. Prefer using `toMatchInlineSnapshot` to include the test error and its stack. If snapshot is failing, update the snapshot instead of reverting it to `toContain`.\n\nIf you need to typecheck tests, run `pnpm typecheck` from the root of the workspace.\n\n### Testing Utilities\n- **`runInlineTests`** from `test/test-utils/index.ts` - You must use this for complex file system setups (>1 file)\n- **`runVitest`** from `test/test-utils/index.ts` - You can use this to run Vitest programmatically\n- **No mocking policy** - You must never mock anything in tests\n\n## Project Structure\n\n### Core Packages (`packages/`)\n- `vitest` - Main testing framework\n- `browser` - Browser testing support\n- `ui` - Web UI for test results\n- `runner` - Test runner core\n- `expect` - Assertion library\n- `spy` - Mocking and spying utilities\n- `snapshot` - Snapshot testing\n- `coverage-v8` / `coverage-istanbul` - Code coverage\n- `utils` - Shared utilities\n- `mocker` - Module mocking\n\n### Test Organization (`test/`)\n- `test/core` - Core functionality tests\n- `test/browser` - Browser-specific tests\n- Various test suites organized by feature\n\n### Important Directories\n- `docs/` - Documentation (Vite-powered)\n- `examples/` - Example projects and integrations\n- `scripts/` - Build and development scripts\n- `.github/` - GitHub Actions workflows\n- `patches/` - Package patches via pnpm\n\n## Code Style and Conventions\n\n### Formatting and Linting\n- **Always run** `pnpm lint:fix` after making changes\n- Fix non-auto-fixable errors manually\n\n### TypeScript\n- Strict TypeScript configuration\n- Use `pnpm typecheck` to verify types\n- Configuration files: `tsconfig.base.json`, `tsconfig.build.json`, `tsconfig.check.json`\n\n### Code Quality\n- ESM-first approach\n- Follow existing patterns in the codebase\n- Use utilities from `@vitest/utils/*` when available. Never import from `@vitest/utils` main entry point directly.\n- Do not add comments explaining what the line does unless prompted to.\n\n## Common Workflows\n\n### Adding New Features\n1. Identify the appropriate package in `packages/`\n2. Follow existing code patterns\n3. Add tests using testing utilities\n4. Run `pnpm build && pnpm typecheck && pnpm lint:fix`\n5. Add tests with relevant test suites\n\n### Debugging\n- Use VS Code: `⇧⌘B` (Shift+Cmd+B) or `Ctrl+Shift+B` for dev tasks\n- Check `scripts/` directory for specialized development tools\n\n### Documentation\n- Main docs in `docs/` directory\n- Built with `pnpm docs:build`\n- Local dev server: `pnpm docs`\n- When adding cli options, run `pnpm -C docs run cli-table` to update the cli-generated.md file\n\n## Dependencies and Tools\n\n### Key Dependencies\n- **Vite** - Build tool and dev server\n- **Rollup** - Bundler\n- **ESLint** - Linting\n- **TypeScript** - Type checking\n- **Playwright** - Browser testing\n- **Chai/Expect** - Assertions\n- **Tinypool** - Worker threading\n- **Tinybench** - Benchmarking\n\n### Development Tools\n- **tsx** - TypeScript execution\n- **ni/nr** - Package manager abstraction\n- **bumpp** - Version bumping\n- **changelogithub** - Changelog generation\n\n## Browser Testing\n- Two modes: Playwright and WebDriverIO\n- Separate test commands for each\n- Component testing supported (Vue, React, Svelte, Lit, Marko)\n\n## Performance Considerations\n- This is a performance-critical testing framework\n- Pay attention to import costs and bundle size\n- Use lazy loading where appropriate\n- Consider worker thread implications\n\n## Troubleshooting\n\n### Common Issues\n- Ensure pnpm is used (not npm/yarn)\n- Build before running tests\n- Check Node.js version compatibility\n- Playwright browsers must be installed for browser tests\n\n### Getting Help\n- Check existing issues and documentation\n- Review CONTRIBUTING.md for detailed guidelines\n- Follow patterns in existing code\n"
  },
  {
    "path": "CLAUDE.md",
    "content": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Codebase Overview\n\nVitest is a next-generation testing framework powered by Vite. This is a monorepo using pnpm workspaces.\n\n## Essential references\n\n- Agent-specific guide: See [AGENTS.md](AGENTS.md)\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code Of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, political party, or sexual identity and orientation. Note, however, that religion, political party, or other ideological affiliation provide no exemptions for the behavior we outline as unacceptable in this Code of Conduct.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n- Using welcoming and inclusive language\n- Being respectful of differing viewpoints and experiences\n- Gracefully accepting constructive criticism\n- Focusing on what is best for the community\n- Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n- The use of sexualized language or imagery and unwelcome sexual attention or advances\n- Trolling, insulting/derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others' private information, such as a physical or electronic address, without explicit permission\n- Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team by sending an e-mail to vitest.dev@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Vitest Contributing Guide\n\nHi! We are really excited that you are interested in contributing to Vitest. Before submitting your contribution, please make sure to take a moment and read through the following guide:\n\n## Repo Setup\n\nThe Vitest repo is a monorepo using pnpm workspaces. The package manager used to install and link dependencies must be [pnpm](https://pnpm.io/).\n\nWe recommend installing [ni](https://github.com/antfu/ni) to help switching between repos using different package managers. `ni` also provides the handy `nr` command which running npm scripts easier:\n\n- `ni` is equivalent to `pnpm install`\n- `nr test` is equivalent to `pnpm run test`\n\nTo develop and test `vitest` package:\n\n1. Run `pnpm install` in `vitest`'s root folder\n\n2. Run `pnpm run build` to build all monorepo packages\n  - after this, you can use `pnpm run dev` to rebuild packages as you modify code\n\n3. Run\n   - `pnpm run test` to run core tests\n   - `pnpm run test:ci` to run all the suite\n   - `cd test/(dir) && pnpm run test` to run a specific test suite\n\n> 💡 If you use VS Code, you can hit `⇧ ⌘ B` or `Ctrl + Shift + B` to launch all the necessary dev tasks.\n\n### UI Development\n\nIf you want to improve Vitest Browser Mode, see the [Browser Mode development guide](./packages/ui/README.md) for setup instructions and development workflow.\n\n## Debugging\n\n### VS Code\n\nIf you want to use break point and explore code execution you can use the [\"Run and debug\"](https://code.visualstudio.com/docs/debugtest/debugging) feature from vscode.\n\n1. Add a `debugger` statement where you want to stop the code execution.\n\n2. Click on the \"Run and Debug\" icon in the activity bar of the editor.\n\n3. Click on the \"Javascript Debug Terminal\" button.\n\n4. It will open a terminal, then type the test command: `pnpm run test`\n\n5. The execution will stop and you'll use the [Debug toolbar](https://code.visualstudio.com/docs/debugtest/debugging#_debug-actions) to continue, step over, restart the process...\n\n## Testing Vitest against external packages\n\nYou may wish to test your locally-modified copy of Vitest against another package that is using it. For pnpm, after building Vitest, you can use [`pnpm.overrides`](https://pnpm.io/9.x/package_json#pnpmoverrides). Please note that `pnpm.overrides` must be specified in the root `package.json` and you must first list the package as a dependency in the root `package.json`:\n\n```json\n{\n  \"dependencies\": {\n    \"vitest\": \"*\"\n  },\n  \"pnpm\": {\n    \"overrides\": {\n      \"vitest\": \"link:../path/to/vitest/packages/vitest\"\n    }\n  }\n}\n```\n\nAnd re-run `pnpm install` to link the package.\n\nAdd a `.npmrc` file with following line next to the `package.json`:\n\n```sh\nVITEST_MODULE_DIRECTORIES=/node_modules/,/packages/\n```\n\n## Pull Request Guidelines\n\n- Checkout a topic branch from a base branch, e.g. `main`, and merge back against that branch.\n\n- If adding a new feature:\n\n  - Add accompanying test case.\n  - Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it.\n  - When adding cli options, run `pnpm -C docs run cli-table` to update the cli-generated.md file\n\n- If fixing bug:\n\n  - If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `fix: update entities encoding/decoding (fix #3899)`.\n  - Provide a detailed description of the bug in the PR. Live demo preferred.\n  - Add appropriate test coverage if applicable.\n\n- It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging.\n\n- Make sure tests pass!\n\n- Commit messages must follow the [commit message convention](./.github/commit-convention.md) so that changelogs can be automatically generated.\n\n- Use `pnpm run lint:fix` to format files according to the project guidelines.\n\n## Maintenance Guidelines\n\n> The following section is mostly for maintainers who have commit access, but it's helpful to go through if you intend to make non-trivial contributions to the codebase.\n\n### Issue Triaging Workflow\n\n```mermaid\nflowchart TD\n    start{Followed issue<br/>template?}\n    start --NO--> close1[Close and ask to<br/>follow template]\n    start --YES--> dupe{Is duplicate?}\n    dupe --YES--> close2[Close and point<br/>to duplicate]\n    dupe --NO--> repro{Has proper<br/>reproduction?}\n    repro --NO--> close3[Label: 'needs reproduction'<br/>bot will auto close if no update has been made in 3 days]\n    repro --YES--> real{Is actually a bug?}\n    real --NO--> intended{Is the intended<br/>behaviour?}\n    intended --YES--> explain[Explain and close<br/>point to docs if needed]\n    intended --NO--> open[Keep open for discussion<br/>Remove 'pending triage' label]\n    real --YES--> real2[\"1. Remove 'pending triage' label<br/>2. Add related feature label if<br/>applicable (e.g. 'feat: browser')<br/>3. Add priority and meta labels (see below)\"]\n    real2 --> unusable{Does the<br/>bug make Vitest<br/>unusable?}\n    unusable --YES--> maj{Does the bug<br/>affect the majority<br/>of Vitest users?}\n    maj --YES--> p5[p5: urgent]\n    maj --NO--> p4[p4: important]\n    unusable --NO--> workarounds{Are there<br/>workarounds for<br/>the bug?}\n    workarounds --YES--> p2[p2: edge case<br/>has workaround]\n    workarounds --NO--> p3[p3: minor bug]\n```\n\n### Pull Request Review Workflow\n\n```mermaid\nflowchart TD\n    start{Bug fix<br/>or<br/>feature}\n    start --BUG FIX--> strict_bug{\"Is a 'strict fix'<br/>i.e. fixes an obvious<br/>oversight with no<br/>side effects\"}\n    start --FEATURE--> feature[- Discuss feature necessity<br/>- Is this the best way to address the need<br/>- Review code quality<br/>- Add feature labels<br/>- Approve if you feel strongly<br/>that the feature is needed]\n    feature --> merge\n    strict_bug --YES--> strict[- Verify the fix locally<br/>- Review code quality<br/>- Require test case if applicable<br/>- Request changes if necessary]\n    strict_bug --NO--> non_strict[- Discuss the potential side<br/>effects of the fix, e.g.<br/>- Could it introduce implicit<br/>behavior changes in other<br/>cases?<br/>- Does it introduce too much<br/>changes?]\n    non_strict --> label[\"Add priority labels<br/>(see issue triaging workflow)\"]\n    strict --> label\n    label --> approve\n    approve --> merge[\"Merge if approved by 2 or<br/>more team members<br/>- Use 'Squash and Merge'<br/>- Edit commit message to follow convention<br/>- In commit message body, list relevant issues being fixed<br/>e.g. 'fix #1234, fix #1235'\"]\n```\n\n## Notes on Dependencies\n\nVitest aims to be lightweight, and this includes being aware of the number of npm dependencies and their size.\n\n### Think before adding a dependency\n\nMost deps should be added to `devDependencies` even if they are needed at runtime. Some exceptions are:\n\n- Type packages. Example: `@types/*`.\n- Deps that cannot be properly bundled due to binary files.\n- Deps that ships its own types and its type is used in vitest's own public types.\n\nAvoid deps that has large transitive dependencies that results in bloated size compared to the functionality it provides.\n\nIf there are libraries that are needed and don't comply with our size\nrequirements, a fork can be tried to reduce its size while we work with them to\nupstream our changes.\n\n### Think before adding yet another option\n\nWe already have many config options, and we should avoid fixing an issue by adding yet another one. Before adding an option, try to think about:\n\n- Whether the problem is really worth addressing\n- Whether the problem can be fixed with a smarter default\n- Whether the problem has workaround using existing options\n- Whether the problem can be addressed with a plugin instead\n"
  },
  {
    "path": "FUNDING.json",
    "content": "{\n  \"drips\": {\n    \"ethereum\": {\n      \"ownedBy\": \"0x929Eb10Cf1621b26199120a521C785F8271e0b78\"\n    }\n  }\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021-Present VoidZero Inc. and Vitest contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <br>\n  <br>\n  <a href=\"https://vitest.dev\" target=\"_blank\" rel=\"noopener noreferrer\">\n    <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://vitest.dev/vitest-light.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://vitest.dev/vitest-dark.svg\">\n      <img alt=\"Vitest logo\" src=\"https://vitest.dev/vitest-dark.svg\" height=\"60\">\n    </picture>\n  </a>\n  <br>\n  <br>\n  <br>\n</p>\n\n<h1 align=\"center\">\nVitest\n</h1>\n<p align=\"center\">\nNext generation testing framework powered by Vite.\n<p>\n<p align=\"center\">\n  <a href=\"https://npmx.dev/package/vitest\"><img src=\"https://img.shields.io/npm/v/vitest?color=729B1B&label=\" alt=\"current vitest version badge\"></a>\n<p>\n\n<p align=\"center\">\n<a href=\"https://chat.vitest.dev\"><b>Get involved!</b></a>\n</p>\n<p align=\"center\">\n <a href=\"https://vitest.dev\">Documentation</a> | <a href=\"https://vitest.dev/guide/\">Getting Started</a> | <a href=\"https://vitest.dev/guide/#examples\">Examples</a> | <a href=\"https://vitest.dev/guide/why\">Why Vitest?</a>\n</p>\n<p align=\"center\">\n<a href=\"https://cn.vitest.dev\">中文文档</a>\n</p>\n\n<h4 align=\"center\">\n\n</h4>\n<br>\n<br>\n\n## Features\n\n- [Vite](https://vitejs.dev/)'s config, transformers, resolvers, and plugins. Use the same setup from your app!\n- [Jest Snapshot](https://jestjs.io/docs/snapshot-testing)\n- [Chai](https://www.chaijs.com/) built-in for assertions, with [Jest expect](https://jestjs.io/docs/expect) compatible APIs\n- [Smart & instant watch mode](https://vitest.dev/guide/features.html#watch-mode), like HMR for tests!\n- [Native code coverage](https://vitest.dev/guide/features.html#coverage) via [`v8`](https://v8.dev/blog/javascript-code-coverage) or [`istanbul`](https://istanbul.js.org/).\n- [Tinyspy](https://github.com/tinylibs/tinyspy) built-in for mocking, stubbing, and spies.\n- [JSDOM](https://github.com/jsdom/jsdom) and [happy-dom](https://github.com/capricorn86/happy-dom) for DOM and browser API mocking\n- [Browser Mode](https://vitest.dev/guide/browser/) for running component tests in the browser\n- Components testing ([Vue](https://github.com/vitest-tests/browser-examples/tree/main/examples/vue), [React](https://github.com/vitest-tests/browser-examples/tree/main/examples/react), [Svelte](https://github.com/vitest-tests/browser-examples/tree/main/examples/svelte), [Lit](./examples/lit), [Marko](https://github.com/marko-js/examples/tree/master/examples/library-ts))\n- Benchmarking support with [Tinybench](https://github.com/tinylibs/tinybench)\n- [Projects](https://vitest.dev/guide/projects) support\n- [expect-type](https://github.com/mmkal/expect-type) for type-level testing\n- ESM first, top level await\n- Out-of-box TypeScript / JSX support\n- Filtering, timeouts, concurrent for suite and tests\n- Sharding support\n- Reporting Uncaught Errors\n- Run your tests in the browser natively\n\n> Vitest requires Vite >=v6.0.0 and Node >=v20.0.0\n\n```ts\nimport { assert, describe, expect, it } from 'vitest'\n\ndescribe('suite name', () => {\n  it('foo', () => {\n    expect(1 + 1).toEqual(2)\n    expect(true).to.be.true\n  })\n\n  it('bar', () => {\n    assert.equal(Math.sqrt(4), 2)\n  })\n\n  it('snapshot', () => {\n    expect({ foo: 'bar' }).toMatchSnapshot()\n  })\n})\n```\n\n```bash\n$ npx vitest\n```\n\n## Sponsors\n\n<p align=\"center\">\n  <a href=\"https://cdn.jsdelivr.net/gh/sheremet-va/static/vitest/sponsors.svg\">\n    <img src='https://cdn.jsdelivr.net/gh/sheremet-va/static/vitest/sponsors.svg' alt=\"vitest's sponsors\"/>\n  </a>\n</p>\n\n### Vladimir Sponsors\n\n<p align=\"center\">\n  <a href=\"https://cdn.jsdelivr.net/gh/sheremet-va/static/sponsors.svg\">\n    <img src='https://cdn.jsdelivr.net/gh/sheremet-va/static/sponsors.svg' alt=\"vladimir's sponsors\"/>\n  </a>\n</p>\n\n### Anthony Fu Sponsors\n\n<p align=\"center\">\n  <a href=\"https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg\">\n    <img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg' alt=\"anthony's sponsors\"/>\n  </a>\n</p>\n\n### Patak Sponsors\n\n<p align=\"center\">\n  <a href=\"https://cdn.jsdelivr.net/gh/patak-dev/static/sponsors.svg\">\n    <img src='https://cdn.jsdelivr.net/gh/patak-dev/static/sponsors.svg' alt=\"patak's sponsors\"/>\n  </a>\n</p>\n\n## Credits\n\nThanks to:\n\n- [The Jest team and community](https://jestjs.io/) for creating a delightful testing API\n- [@lukeed](https://github.com/lukeed) for the work on [uvu](https://github.com/lukeed/uvu) where we are inspired a lot from.\n- [@pi0](https://github.com/pi0) for the idea and implementation of using Vite to transform and bundle the server code.\n- [The Vite team](https://github.com/vitejs/vite) for brainstorming the initial idea.\n- [@patak-dev](https://github.com/patak-dev) for the awesome package name!\n\n## Contribution\n\nSee [Contributing Guide](https://github.com/vitest-dev/vitest/blob/main/CONTRIBUTING.md).\n\n## License\n\n[MIT](./LICENSE) License © 2021-Present VoidZero Inc. and Vitest contributors\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Reporting a Vulnerability\n\nTo report a vulnerability, please open a private vulnerability report at https://github.com/vitest-dev/vitest/security.\n\nWhile the discovery of new vulnerabilities is rare, we also recommend always using the latest versions of Vitest to ensure your application remains as secure as possible.\n"
  },
  {
    "path": "docs/.vitepress/blog.data.ts",
    "content": "import { createContentLoader } from 'vitepress'\n\ninterface Post {\n  title: string\n  url: string\n  date: {\n    time: number\n    string: string\n  }\n}\n\ndeclare const data: Post[]\nexport { data }\n\nexport default createContentLoader('blog/*.md', {\n  // excerpt: true,\n  transform(raw): Post[] {\n    return raw\n      .map(({ url, frontmatter }) => ({\n        title: frontmatter.head.find((e: any) => e[1].property === 'og:title')[1]\n          .content,\n        url,\n        date: formatDate(frontmatter.date),\n      }))\n      .sort((a, b) => b.date.time - a.date.time)\n  },\n})\n\nfunction formatDate(raw: string): Post['date'] {\n  const date = new Date(raw)\n  date.setUTCHours(12)\n  return {\n    time: +date,\n    string: date.toLocaleDateString('en-US', {\n      year: 'numeric',\n      month: 'long',\n      day: 'numeric',\n    }),\n  }\n}\n"
  },
  {
    "path": "docs/.vitepress/components/Advanced.vue",
    "content": "<template>\n  <Badge type=\"danger\" title=\"This is an advanced API intended for library authors and framework integrations. Most users should not need this.\" class=\"advanced-badge\">\n    advanced\n  </Badge>\n</template>\n\n<style scoped>\n.advanced-badge {\n  cursor: help;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/ArrowDown.vue",
    "content": "<template>\n  <span class=\"arrow-down\">\n    <span class=\"arrow-line\" />\n    <span class=\"arrow-head\" />\n  </span>\n</template>\n\n<style scoped>\n.arrow-down {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n}\n\n.arrow-line {\n  height: 1rem;\n  width: 0.2rem;\n  background-color: var(--vp-c-brand-1);\n}\n\n.arrow-head {\n  height: 1rem;\n  width: 1rem;\n  background-color: var(--vp-c-brand-1);\n  clip-path: polygon(100% 0, 0 0, 50% 100%);\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/BlogIndex.vue",
    "content": "<script setup lang=\"ts\">\nimport { data as posts } from '../blog.data'\n\nfunction getDateTime(time: number) {\n  return new Date(time).toISOString()\n}\n</script>\n\n<template>\n  <ul class=\"blog-list\">\n    <li v-for=\"post of posts\" :key=\"post.url\" class=\"blog-entry\">\n      <article>\n        <time :datetime=\"getDateTime(post.date.time)\">{{\n          post.date.string\n        }}</time>\n        <h2 class=\"title\">\n          <a :href=\"post.url\">{{ post.title }}</a>\n        </h2>\n      </article>\n    </li>\n  </ul>\n</template>\n\n<style scoped>\n.blog-list {\n  list-style-type: none;\n  padding: 0;\n}\n.blog-entry {\n  margin-top: 3em;\n  border-bottom: 1px solid var(--vp-c-divider);\n}\n.blog-entry time {\n  font-size: 14px;\n}\n.title {\n  border: none;\n  margin-top: 0;\n  padding-top: 0;\n  font-size: 22px;\n}\n.title a {\n  font-weight: 600;\n  text-decoration: none;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/Box.vue",
    "content": "<template>\n  <span class=\"box\">\n    <slot />\n  </span>\n</template>\n\n<style scoped>\n.box {\n  display: flex;\n  width: 100%;\n  align-items: center;\n  justify-content: center;\n  text-align: center;\n  border: 0.1rem solid var(--vp-c-brand-1);\n  border-radius: 15px;\n  padding: 1rem 2rem;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/CRoot.vue",
    "content": "<script setup>\nimport { Icon } from '@iconify/vue'\n</script>\n\n<template>\n  <Badge type=\"warning\" title=\"This options is only available in the top level config. You cannot specify it as an option of a test project.\" class=\"croot-badge\">\n    <Icon icon=\"carbon:document-configuration\" class=\"croot-icon\" />\n  </Badge>\n</template>\n\n<style scoped>\n.croot-badge {\n  text-decoration: underline;\n  text-decoration-style: dotted;\n  cursor: help;\n}\n.croot-icon {\n  margin-top: 0.25rem;\n  margin-bottom: 0.25rem;\n  margin-left: -0.25rem;\n  margin-right: -0.25rem;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/CourseLink.vue",
    "content": "<script setup lang=\"ts\">\nimport { Icon } from '@iconify/vue'\n\ndefineProps<{\n  href: string\n}>()\n</script>\n\n<template>\n  <a :href=\"href\" target=\"_blank\" class=\"course-link\">\n    <Icon icon=\"carbon:play-filled\" class=\"course-icon\" />\n    <slot />\n  </a>\n</template>\n\n<style scoped>\n.course-link {\n  background-color: rgb(34 197 94 / 0.1);\n  padding: 0.75rem 1rem;\n  border-radius: 0.25rem;\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  margin-top: 0.5rem;\n}\n\n.course-icon {\n  flex: none;\n  font-size: 1.125rem;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/Deprecated.vue",
    "content": "<template>\n  <Badge type=\"danger\">\n    deprecated\n  </Badge>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/components/Experimental.vue",
    "content": "<template>\n  <Badge type=\"warning\" title=\"This feature is experimental and does not follow SemVer.\" class=\"experimental-badge\">\n    experimental\n  </Badge>\n</template>\n\n<style scoped>\n.experimental-badge {\n  cursor: help;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/FeaturesList.vue",
    "content": "<script setup>\nimport ListItem from './ListItem.vue'\n</script>\n\n<template>\n  <ul\n    class=\"features-list\"\n    dir=\"auto\"\n  >\n    <ListItem><a target=\"_blank\" href=\"https://vitejs.dev\" rel=\"noopener noreferrer\">Vite</a>'s config, transformers, resolvers, and plugins</ListItem>\n    <ListItem>Use the same setup from your app to run the tests!</ListItem>\n    <ListItem>Smart & instant watch mode, like HMR for tests!</ListItem>\n    <ListItem>Component testing for Vue, React, Svelte, Lit, Marko and more</ListItem>\n    <ListItem>Out-of-the-box TypeScript / JSX support</ListItem>\n    <ListItem>ESM first, top level await</ListItem>\n    <ListItem>Benchmarking support with <a target=\"_blank\" href=\"https://github.com/tinylibs/tinybench\" rel=\"noopener noreferrer\">Tinybench</a></ListItem>\n    <ListItem>Filtering, timeouts, concurrent for suite and tests</ListItem>\n    <ListItem><a href=\"/guide/projects\">Projects</a> support</ListItem>\n    <ListItem>\n      <a href=\"/guide/snapshot\">\n        Jest-compatible Snapshot\n      </a>\n    </ListItem>\n    <ListItem><a target=\"_blank\" href=\"https://www.chaijs.com/\" rel=\"noopener noreferrer\">Chai</a> built-in for assertions + <a target=\"_blank\" href=\"https://jestjs.io/docs/expect\" rel=\"noopener noreferrer\">Jest expect</a> compatible APIs</ListItem>\n    <ListItem><a target=\"_blank\" href=\"https://github.com/tinylibs/tinyspy\" rel=\"noopener noreferrer\">Tinyspy</a> built-in for mocking</ListItem>\n    <ListItem><a target=\"_blank\" href=\"https://github.com/capricorn86/happy-dom\" rel=\"noopener noreferrer\">happy-dom</a> or <a target=\"_blank\" href=\"https://github.com/jsdom/jsdom\" rel=\"noopener noreferrer\">jsdom</a> for DOM mocking</ListItem>\n    <ListItem><a href=\"https://vitest.dev/guide/browser/\" rel=\"noopener noreferrer\">Browser Mode</a> for running component tests in the browser</ListItem>\n    <ListItem>Code coverage via <a target=\"_blank\" href=\"https://v8.dev/blog/javascript-code-coverage\" rel=\"noopener noreferrer\">v8</a> or <a target=\"_blank\" href=\"https://istanbul.js.org/\" rel=\"noopener noreferrer\">istanbul</a></ListItem>\n    <ListItem>Rust-like <a href=\"/guide/in-source\">in-source testing</a></ListItem>\n    <ListItem>Type Testing via <a target=\"_blank\" href=\"https://github.com/mmkal/expect-type\" rel=\"noopener noreferrer\">expect-type</a></ListItem>\n    <ListItem>Sharding Support</ListItem>\n    <ListItem>Reporting Uncaught Errors</ListItem>\n  </ul>\n</template>\n\n<style>\n.features-list li {\n  list-style: none;\n  display: flex;\n  gap: 0.4rem;\n  margin: 0;\n}\n\n.features-list {\n  padding: 0;\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/HomePage.vue",
    "content": "<script setup lang=\"ts\">\nimport { VPHomeSponsors } from '@voidzero-dev/vitepress-theme'\nimport { sponsors } from '../sponsors'\n</script>\n\n<template>\n  <div class=\"content\">\n    <div class=\"content-container\">\n      <main class=\"main\">\n        <VPHomeSponsors\n          v-if=\"sponsors\"\n          message=\"Vitest is free and open source, made possible by wonderful sponsors.\"\n          :data=\"sponsors\"\n        />\n        <div class=\"action\">\n          <a\n            class=\"sponsor\"\n            href=\"https://github.com/sponsors/vitest-dev\"\n            target=\"_blank\"\n            rel=\"noreferrer\"\n          >\n            Sponsor Vitest\n          </a>\n        </div>\n        <p flex flex-col items-center mt-10 class=\"text-center opacity-75\">\n          <a href=\"https://www.netlify.com\" rel=\"noopener noreferrer\">\n            <img src=\"/netlify.svg\" alt=\"Deploys by Netlify\" width=\"114\" height=\"151\" decoding=\"async\">\n          </a>\n        </p>\n      </main>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.action {\n  display: flex;\n  justify-content: center;\n  gap: 1rem;\n  padding-top: 4rem;\n}\n\n.sponsor {\n  /* .VPButton */\n  display: inline-block;\n  border: 1px solid transparent;\n  text-align: center;\n  font-weight: 600;\n  white-space: nowrap;\n  transition:\n    color 0.25s,\n    border-color 0.25s,\n    background-color 0.25s;\n  /* .VPButton.medium */\n  border-radius: 20px;\n  padding: 0 20px;\n  line-height: 38px;\n  font-size: 14px;\n  /* .VPButton.sponsor */\n  border-color: var(--vp-button-sponsor-border);\n  color: var(--vp-button-sponsor-text);\n  background-color: var(--vp-button-sponsor-bg);\n}\n\n.sponsor:hover {\n  /* .VPButton.sponsor:hover */\n  border-color: var(--vp-button-sponsor-hover-border);\n  color: var(--vp-button-sponsor-hover-text);\n  background-color: var(--vp-button-sponsor-hover-bg);\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/ListItem.vue",
    "content": "<script setup lang=\"ts\">\nimport { Icon } from '@iconify/vue'\nimport { until, useElementVisibility } from '@vueuse/core'\nimport { computed, effectScope, onMounted, ref } from 'vue'\n\nconst el = ref<HTMLDivElement>()\nconst state = ref(0)\n\nfunction reset() {\n  state.value = 0\n  setTimeout(() => {\n    state.value = Math.random() > 0.9 ? 2 : 1\n    if (state.value === 2) {\n      setTimeout(reset, 1000)\n    }\n  }, Math.round(Math.random() * 3000) + 400)\n}\n\nconst color = computed(() => {\n  return {\n    '--vp-c-brand-1': state.value === 1\n      ? 'var(--color-brand)'\n      : state.value === 2\n        ? 'var(--vp-c-red-1)'\n        : 'var(--vp-c-yellow-1)',\n  } as any\n})\n\nconst scope = effectScope()\n\nconst visibility = scope.run(() => useElementVisibility(el))\n\nonMounted(async () => {\n  await until(visibility).toBe(true)\n\n  scope.stop()\n  reset()\n})\n</script>\n\n<template>\n  <li :style=\"color\">\n    <div ref=\"el\" class=\"icon-container\">\n      <div class=\"icon-wrapper\" :class=\"state ? 'flip' : ''\">\n        <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1.2em\" height=\"1.2em\" viewBox=\"0 0 32 32\" class=\"icon-spinner\">\n          <circle cx=\"16\" cy=\"16\" r=\"13\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"8 4\" />\n        </svg>\n      </div>\n      <div class=\"icon-wrapper\" :class=\"state === 2 ? '' : 'flip'\">\n        <Icon icon=\"carbon:close-outline\" class=\"icon-error\" width=\"1.2em\" height=\"1.2em\" />\n      </div>\n      <div class=\"icon-wrapper\" :class=\"state === 1 ? '' : 'flip'\">\n        <Icon icon=\"carbon:checkmark-outline\" class=\"icon-success\" width=\"1.2em\" height=\"1.2em\" />\n      </div>\n    </div>\n    <div>\n      <slot />\n    </div>\n  </li>\n</template>\n\n<style scoped>\n.icon-container {\n  position: relative;\n  width: 1.2em;\n  height: 1.2em;\n  flex: none;\n  margin-top: auto;\n  margin-bottom: auto;\n  vertical-align: middle;\n}\n\n.icon-wrapper {\n  position: absolute;\n  transition: all 300ms;\n}\n\n.flip {\n  transform: rotateY(90deg);\n}\n\n.icon-spinner {\n  animation: spin 1s linear infinite;\n  color: var(--vp-c-yellow-1);\n}\n\n.icon-error {\n  color: var(--vp-c-red-1);\n}\n\n.icon-success {\n  color: var(--color-brand);\n}\n\n@keyframes spin {\n  from {\n    transform: rotate(0deg);\n  }\n  to {\n    transform: rotate(360deg);\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/components/Version.vue",
    "content": "<script setup lang=\"ts\">\nimport { VPBadge } from '@voidzero-dev/vitepress-theme'\n\nconst { type = 'stable' } = defineProps<{\n  type?: 'stable' | 'experimental'\n}>()\n</script>\n\n<template>\n  <VPBadge\n    :type=\"type === 'experimental' ? 'warning' : 'info'\"\n    :title=\"type === 'experimental' ? 'This feature is experimental and does not follow SemVer.' : undefined\"\n  >\n    <slot />+\n  </VPBadge>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/config.ts",
    "content": "import { transformerTwoslash } from '@shikijs/vitepress-twoslash'\nimport { transformerNotationWordHighlight } from '@shikijs/transformers'\nimport { withPwa } from '@vite-pwa/vitepress'\nimport { defineConfig } from 'vitepress'\nimport { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'\nimport {\n  groupIconMdPlugin,\n  groupIconVitePlugin,\n} from 'vitepress-plugin-group-icons'\nimport llmstxt from 'vitepress-plugin-llms'\nimport { version } from '../../package.json'\nimport { teamMembers } from './contributors'\nimport {\n  bluesky,\n  contributing,\n  discord,\n  font,\n  github,\n  mastodon,\n  ogImage,\n  ogUrl,\n  releases,\n  vitestDescription,\n  vitestName,\n} from './meta'\nimport { pwa } from './scripts/pwa'\nimport { transformHead } from './scripts/transformHead'\nimport { extendConfig } from '@voidzero-dev/vitepress-theme/config'\n\nexport default ({ mode }: { mode: string }) => {\n  return withPwa(extendConfig(defineConfig({\n    lang: 'en-US',\n    title: vitestName,\n    description: vitestDescription,\n    srcExclude: [\n      '**/guide/examples/*',\n      '**/guide/cli-generated.md',\n    ],\n    locales: {\n      root: {\n        label: 'English',\n        lang: 'en-US',\n      },\n      zh: {\n        label: '简体中文',\n        lang: 'zh',\n        link: 'https://cn.vitest.dev/',\n      },\n    },\n    head: [\n      ['meta', { name: 'theme-color', content: '#22FF84' }],\n      ['link', { rel: 'icon', href: '/favicon.ico', sizes: '48x48' }],\n      ['link', { rel: 'icon', href: '/logo-without-border.svg', type: 'image/svg+xml' }],\n      ['meta', { name: 'author', content: `${teamMembers.map(c => c.name).join(', ')} and ${vitestName} contributors` }],\n      ['meta', { name: 'keywords', content: 'vitest, vite, test, coverage, snapshot, react, vue, preact, svelte, solid, lit, marko, ruby, cypress, puppeteer, jsdom, happy-dom, test-runner, jest, typescript, esm, tinyspy, node' }],\n      ['meta', { property: 'og:title', content: vitestName }],\n      ['meta', { property: 'og:description', content: vitestDescription }],\n      ['meta', { property: 'og:url', content: ogUrl }],\n      ['meta', { property: 'og:image', content: ogImage }],\n      ['meta', { name: 'twitter:card', content: 'summary_large_image' }],\n      ['link', { rel: 'preload', as: 'style', onload: 'this.onload=null;this.rel=\\'stylesheet\\'', href: font }],\n      ['noscript', {}, `<link rel=\"stylesheet\" crossorigin=\"anonymous\" href=\"${font}\" />`],\n      ['link', { rel: 'me', href: 'https://m.webtoo.ls/@vitest' }],\n      ['link', { rel: 'mask-icon', href: '/logo.svg', color: '#ffffff' }],\n      ['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }],\n      [\n        'script',\n        {\n          'src': 'https://cdn.usefathom.com/script.js',\n          'data-site': 'BEAFAKYG',\n          'data-spa': 'auto',\n          'defer': '',\n        },\n      ],\n    ],\n    lastUpdated: true,\n    vite: {\n      plugins: [\n        groupIconVitePlugin({\n          customIcon: {\n            'CLI': 'vscode-icons:file-type-shell',\n            '.spec.ts': 'vscode-icons:file-type-testts',\n            '.test.ts': 'vscode-icons:file-type-testts',\n            '.spec.js': 'vscode-icons:file-type-testjs',\n            '.test.js': 'vscode-icons:file-type-testjs',\n            'next': '',\n          },\n        }),\n        llmstxt(),\n      ],\n    },\n    markdown: {\n      config(md) {\n        md.use(tabsMarkdownPlugin)\n        md.use(groupIconMdPlugin)\n      },\n      theme: {\n        light: 'github-light',\n        dark: 'github-dark',\n      },\n      codeTransformers: mode === 'development'\n        ? [transformerNotationWordHighlight()]\n        : [\n            transformerNotationWordHighlight(),\n            transformerTwoslash({\n              processHoverInfo: (info) => {\n                if (info.includes(process.cwd())) {\n                  return info.replace(new RegExp(process.cwd(), 'g'), '')\n                }\n                return info\n              },\n            }),\n          ],\n      languages: ['js', 'jsx', 'ts', 'tsx'],\n    },\n    themeConfig: {\n      variant: 'vitest',\n      logo: '/logo.svg',\n\n      editLink: {\n        pattern: 'https://github.com/vitest-dev/vitest/edit/main/docs/:path',\n        text: 'Suggest changes to this page',\n      },\n\n      search: {\n        provider: 'local',\n      /* provider: 'algolia',\n      options: {\n        appId: 'ZTF29HGJ69',\n        apiKey: '9c3ced6fed60d2670bb36ab7e8bed8bc',\n        indexName: 'vitest',\n        // searchParameters: {\n        //   facetFilters: ['tags:en'],\n        // },\n      }, */\n      },\n\n      banner: {\n        id: 'viteplus-alpha',\n        text: 'Announcing Vite+ Alpha: Open source. Unified. Next-gen.',\n        url: 'https://voidzero.dev/posts/announcing-vite-plus-alpha?utm_source=vitest&utm_content=top_banner',\n      },\n\n      carbonAds: {\n        code: 'CW7DVKJE',\n        placement: 'vitestdev',\n      },\n\n      socialLinks: [\n        { icon: 'bluesky', link: bluesky },\n        { icon: 'mastodon', link: mastodon },\n        { icon: 'discord', link: discord },\n        { icon: 'github', link: github },\n      ],\n\n      footer: {\n        copyright: `© ${new Date().getFullYear()} VoidZero Inc. and Vitest contributors.`,\n        nav: [\n          {\n            title: 'Vitest',\n            items: [\n              { text: 'Guides', link: '/guide/' },\n              { text: 'API', link: '/api/test' },\n              { text: 'Config', link: '/config/' },\n            ],\n          },\n          {\n            title: 'Resources',\n            items: [\n              { text: 'Team', link: '/team' },\n              { text: 'Blog', link: '/blog' },\n              { text: 'Releases', link: releases },\n            ],\n          },\n          {\n            title: 'Versions',\n            items: [\n              { text: 'Unreleased Docs', link: 'https://main.vitest.dev/' },\n              { text: 'Vitest v3 Docs', link: 'https://v3.vitest.dev/' },\n              { text: 'Vitest v2 Docs', link: 'https://v2.vitest.dev/' },\n              { text: 'Vitest v1 Docs', link: 'https://v1.vitest.dev/' },\n              { text: 'Vitest v0 Docs', link: 'https://v0.vitest.dev/' },\n            ],\n          },\n          /* {\n            title: 'Legal',\n            items: [\n              { text: 'Terms & Conditions', link: 'https://voidzero.dev/terms' },\n              { text: 'Privacy Policy', link: 'https://voidzero.dev/privacy' },\n              { text: 'Cookie Policy', link: 'https://voidzero.dev/cookies' },\n            ],\n          }, */\n        ],\n        social: [\n          { icon: 'github', link: github },\n          { icon: 'discord', link: discord },\n          // { icon: 'mastodon', link: mastodon }, -- the link shows github\n          { icon: 'bluesky', link: bluesky },\n        ],\n      },\n\n      nav: [\n        { text: 'Guides', link: '/guide/', activeMatch: '^/guide/' },\n        { text: 'API', link: '/api/test', activeMatch: '^/api/' },\n        { text: 'Config', link: '/config/', activeMatch: '^/config/' },\n        {\n          text: 'Blog',\n          link: '/blog',\n        },\n        {\n          text: `v${version}`,\n          items: [\n            {\n              items: [\n                {\n                  text: `v${version}`,\n                  link: `https://github.com/vitest-dev/vitest/releases/tag/v${version}`,\n                },\n                {\n                  text: 'Releases Notes',\n                  link: releases,\n                },\n                {\n                  text: 'Contributing',\n                  link: contributing,\n                },\n                {\n                  text: 'Team',\n                  link: '/team',\n                },\n              ],\n            },\n            {\n              items: [\n                {\n                  text: 'unreleased',\n                  link: 'https://main.vitest.dev/',\n                },\n                {\n                  text: 'v3.x',\n                  link: 'https://v3.vitest.dev/',\n                },\n                {\n                  text: 'v2.x',\n                  link: 'https://v2.vitest.dev/',\n                },\n                {\n                  text: 'v1.x',\n                  link: 'https://v1.vitest.dev/',\n                },\n                {\n                  text: 'v0.x',\n                  link: 'https://v0.vitest.dev/',\n                },\n              ],\n            },\n          ],\n        },\n      ],\n\n      sidebar: {\n        '/config': [\n          {\n            text: 'Config Reference',\n            collapsed: false,\n            items: [\n              {\n                text: 'Config File',\n                link: '/config/',\n              },\n              {\n                text: 'include',\n                link: '/config/include',\n              },\n              {\n                text: 'exclude',\n                link: '/config/exclude',\n              },\n              {\n                text: 'includeSource',\n                link: '/config/include-source',\n              },\n              {\n                text: 'name',\n                link: '/config/name',\n              },\n              {\n                text: 'server',\n                link: '/config/server',\n              },\n              {\n                text: 'deps',\n                link: '/config/deps',\n              },\n              {\n                text: 'runner',\n                link: '/config/runner',\n              },\n              {\n                text: 'benchmark',\n                link: '/config/benchmark',\n              },\n              {\n                text: 'alias',\n                link: '/config/alias',\n              },\n              {\n                text: 'globals',\n                link: '/config/globals',\n              },\n              {\n                text: 'environment',\n                link: '/config/environment',\n              },\n              {\n                text: 'environmentOptions',\n                link: '/config/environmentoptions',\n              },\n              {\n                text: 'watch',\n                link: '/config/watch',\n              },\n              {\n                text: 'watchTriggerPatterns',\n                link: '/config/watchtriggerpatterns',\n              },\n              {\n                text: 'root',\n                link: '/config/root',\n              },\n              {\n                text: 'dir',\n                link: '/config/dir',\n              },\n              {\n                text: 'reporters',\n                link: '/config/reporters',\n              },\n              {\n                text: 'outputFile',\n                link: '/config/outputfile',\n              },\n              {\n                text: 'pool',\n                link: '/config/pool',\n              },\n              {\n                text: 'execArgv',\n                link: '/config/execargv',\n              },\n              {\n                text: 'vmMemoryLimit',\n                link: '/config/vmmemorylimit',\n              },\n              {\n                text: 'fileParallelism',\n                link: '/config/fileparallelism',\n              },\n              {\n                text: 'maxWorkers',\n                link: '/config/maxworkers',\n              },\n              {\n                text: 'testTimeout',\n                link: '/config/testtimeout',\n              },\n              {\n                text: 'hookTimeout',\n                link: '/config/hooktimeout',\n              },\n              {\n                text: 'teardownTimeout',\n                link: '/config/teardowntimeout',\n              },\n              {\n                text: 'silent',\n                link: '/config/silent',\n              },\n              {\n                text: 'setupFiles',\n                link: '/config/setupfiles',\n              },\n              {\n                text: 'provide',\n                link: '/config/provide',\n              },\n              {\n                text: 'globalSetup',\n                link: '/config/globalsetup',\n              },\n              {\n                text: 'forceRerunTriggers',\n                link: '/config/forcereruntriggers',\n              },\n              {\n                text: 'coverage',\n                link: '/config/coverage',\n              },\n              {\n                text: 'testNamePattern',\n                link: '/config/testnamepattern',\n              },\n              {\n                text: 'ui',\n                link: '/config/ui',\n              },\n              {\n                text: 'open',\n                link: '/config/open',\n              },\n              {\n                text: 'api',\n                link: '/config/api',\n              },\n              {\n                text: 'clearMocks',\n                link: '/config/clearmocks',\n              },\n              {\n                text: 'mockReset',\n                link: '/config/mockreset',\n              },\n              {\n                text: 'restoreMocks',\n                link: '/config/restoremocks',\n              },\n              {\n                text: 'unstubEnvs',\n                link: '/config/unstubenvs',\n              },\n              {\n                text: 'unstubGlobals',\n                link: '/config/unstubglobals',\n              },\n              {\n                text: 'snapshotFormat',\n                link: '/config/snapshotformat',\n              },\n              {\n                text: 'snapshotSerializers',\n                link: '/config/snapshotserializers',\n              },\n              {\n                text: 'resolveSnapshotPath',\n                link: '/config/resolvesnapshotpath',\n              },\n              {\n                text: 'allowOnly',\n                link: '/config/allowonly',\n              },\n              {\n                text: 'passWithNoTests',\n                link: '/config/passwithnotests',\n              },\n              {\n                text: 'logHeapUsage',\n                link: '/config/logheapusage',\n              },\n              {\n                text: 'css',\n                link: '/config/css',\n              },\n              {\n                text: 'maxConcurrency',\n                link: '/config/maxconcurrency',\n              },\n              {\n                text: 'cache',\n                link: '/config/cache',\n              },\n              {\n                text: 'sequence',\n                link: '/config/sequence',\n              },\n              {\n                text: 'tags',\n                link: '/config/tags',\n              },\n              {\n                text: 'strictTags',\n                link: '/config/stricttags',\n              },\n              {\n                text: 'typecheck',\n                link: '/config/typecheck',\n              },\n              {\n                text: 'slowTestThreshold',\n                link: '/config/slowtestthreshold',\n              },\n              {\n                text: 'chaiConfig',\n                link: '/config/chaiconfig',\n              },\n              {\n                text: 'bail',\n                link: '/config/bail',\n              },\n              {\n                text: 'retry',\n                link: '/config/retry',\n              },\n              {\n                text: 'onConsoleLog',\n                link: '/config/onconsolelog',\n              },\n              {\n                text: 'onStackTrace',\n                link: '/config/onstacktrace',\n              },\n              {\n                text: 'onUnhandledError',\n                link: '/config/onunhandlederror',\n              },\n              {\n                text: 'dangerouslyIgnoreUnhandled...',\n                link: '/config/dangerouslyignoreunhandlederrors',\n              },\n              {\n                text: 'diff',\n                link: '/config/diff',\n              },\n              {\n                text: 'fakeTimers',\n                link: '/config/faketimers',\n              },\n              {\n                text: 'projects',\n                link: '/config/projects',\n              },\n              {\n                text: 'isolate',\n                link: '/config/isolate',\n              },\n              {\n                text: 'includeTaskLocation',\n                link: '/config/includetasklocation',\n              },\n              {\n                text: 'snapshotEnvironment',\n                link: '/config/snapshotenvironment',\n              },\n              {\n                text: 'env',\n                link: '/config/env',\n              },\n              {\n                text: 'expect',\n                link: '/config/expect',\n              },\n              {\n                text: 'printConsoleTrace',\n                link: '/config/printconsoletrace',\n              },\n              {\n                text: 'attachmentsDir',\n                link: '/config/attachmentsdir',\n              },\n              {\n                text: 'hideSkippedTests',\n                link: '/config/hideskippedtests',\n              },\n              {\n                text: 'mode',\n                link: '/config/mode',\n              },\n              {\n                text: 'expandSnapshotDiff',\n                link: '/config/expandsnapshotdiff',\n              },\n              {\n                text: 'disableConsoleIntercept',\n                link: '/config/disableconsoleintercept',\n              },\n              {\n                text: 'experimental',\n                link: '/config/experimental',\n              },\n            ],\n          },\n          {\n            text: 'Browser Mode',\n            collapsed: false,\n            items: [\n              {\n                text: 'Providers',\n                collapsed: false,\n                items: [\n                  {\n                    text: 'playwright',\n                    link: '/config/browser/playwright',\n                  },\n                  {\n                    text: 'webdriverio',\n                    link: '/config/browser/webdriverio',\n                  },\n                  {\n                    text: 'preview',\n                    link: '/config/browser/preview',\n                  },\n                ],\n              },\n              {\n                text: 'browser.enabled',\n                link: '/config/browser/enabled',\n              },\n              {\n                text: 'browser.instances',\n                link: '/config/browser/instances',\n              },\n              {\n                text: 'browser.headless',\n                link: '/config/browser/headless',\n              },\n              {\n                text: 'browser.isolate',\n                link: '/config/browser/isolate',\n              },\n              {\n                text: 'browser.testerHtmlPath',\n                link: '/config/browser/testerhtmlpath',\n              },\n              {\n                text: 'browser.api',\n                link: '/config/browser/api',\n              },\n              {\n                text: 'browser.provider',\n                link: '/config/browser/provider',\n              },\n              {\n                text: 'browser.ui',\n                link: '/config/browser/ui',\n              },\n              {\n                text: 'browser.detailsPanelPosition',\n                link: '/config/browser/detailspanelposition',\n              },\n              {\n                text: 'browser.viewport',\n                link: '/config/browser/viewport',\n              },\n              {\n                text: 'browser.locators',\n                link: '/config/browser/locators',\n              },\n              {\n                text: 'browser.screenshotDirectory',\n                link: '/config/browser/screenshotdirectory',\n              },\n              {\n                text: 'browser.screenshotFailures',\n                link: '/config/browser/screenshotfailures',\n              },\n              {\n                text: 'browser.orchestratorScripts',\n                link: '/config/browser/orchestratorscripts',\n              },\n              {\n                text: 'browser.commands',\n                link: '/config/browser/commands',\n              },\n              {\n                text: 'browser.connectTimeout',\n                link: '/config/browser/connecttimeout',\n              },\n              {\n                text: 'browser.trace',\n                link: '/config/browser/trace',\n              },\n              {\n                text: 'browser.trackUnhandledErrors',\n                link: '/config/browser/trackunhandlederrors',\n              },\n              {\n                text: 'browser.expect',\n                link: '/config/browser/expect',\n              },\n            ],\n          },\n          // {\n          //   text: '@vitest/plugin-eslint',\n          //   collapsed: true,\n          //   items: [\n          //     {\n          //       text: 'Lints',\n          //       link: '/config/eslint',\n          //     },\n          //     // TODO: generate\n          //     {\n          //       text: 'consistent-test-filename',\n          //       link: '/config/eslint/consistent-test-filename',\n          //     },\n          //     {\n          //       text: 'consistent-test-it',\n          //       link: '/config/eslint/consistent-test-it',\n          //     },\n          //   ],\n          // },\n          // {\n          //   text: 'vscode',\n          //   link: '/config/vscode',\n          // },\n        ],\n        '/guide': [\n          {\n            text: 'Introduction',\n            collapsed: false,\n            items: [\n              {\n                text: 'Why Vitest',\n                link: '/guide/why',\n              },\n              {\n                text: 'Getting Started',\n                link: '/guide/',\n              },\n              {\n                text: 'Features',\n                link: '/guide/features',\n              },\n            ],\n          },\n          {\n            text: 'Browser Mode',\n            collapsed: false,\n            items: [\n              {\n                text: 'Why Browser Mode',\n                link: '/guide/browser/why',\n                docFooterText: 'Why Browser Mode | Browser Mode',\n              },\n              {\n                text: 'Getting Started',\n                link: '/guide/browser/',\n                docFooterText: 'Getting Started | Browser Mode',\n              },\n              {\n                text: 'Multiple Setups',\n                link: '/guide/browser/multiple-setups',\n                docFooterText: 'Multiple Setups | Browser Mode',\n              },\n              {\n                text: 'Component Testing',\n                link: '/guide/browser/component-testing',\n                docFooterText: 'Component Testing | Browser Mode',\n              },\n              {\n                text: 'Visual Regression Testing',\n                link: '/guide/browser/visual-regression-testing',\n                docFooterText: 'Visual Regression Testing | Browser Mode',\n              },\n              {\n                text: 'Trace View',\n                link: '/guide/browser/trace-view',\n                docFooterText: 'Trace View | Browser Mode',\n              },\n            ],\n          },\n          {\n            text: 'Guides',\n            collapsed: false,\n            items: [\n              {\n                text: 'CLI',\n                link: '/guide/cli',\n              },\n              {\n                text: 'Test Filtering',\n                link: '/guide/filtering',\n              },\n              {\n                text: 'Test Tags',\n                link: '/guide/test-tags',\n              },\n              {\n                text: 'Test Context',\n                link: '/guide/test-context',\n              },\n              {\n                text: 'Test Environment',\n                link: '/guide/environment',\n              },\n              {\n                text: 'Test Run Lifecycle',\n                link: '/guide/lifecycle',\n              },\n              {\n                text: 'Snapshot',\n                link: '/guide/snapshot',\n              },\n              {\n                text: 'Mocking',\n                link: '/guide/mocking',\n                collapsed: true,\n                items: [\n                  {\n                    text: 'Mocking Dates',\n                    link: '/guide/mocking/dates',\n                  },\n                  {\n                    text: 'Mocking Functions',\n                    link: '/guide/mocking/functions',\n                  },\n                  {\n                    text: 'Mocking Globals',\n                    link: '/guide/mocking/globals',\n                  },\n                  {\n                    text: 'Mocking Modules',\n                    link: '/guide/mocking/modules',\n                  },\n                  {\n                    text: 'Mocking the File System',\n                    link: '/guide/mocking/file-system',\n                  },\n                  {\n                    text: 'Mocking Requests',\n                    link: '/guide/mocking/requests',\n                  },\n                  {\n                    text: 'Mocking Timers',\n                    link: '/guide/mocking/timers',\n                  },\n                  {\n                    text: 'Mocking Classes',\n                    link: '/guide/mocking/classes',\n                  },\n                ],\n              },\n              {\n                text: 'Parallelism',\n                link: '/guide/parallelism',\n              },\n              {\n                text: 'Test Projects',\n                link: '/guide/projects',\n              },\n              {\n                text: 'Reporters',\n                link: '/guide/reporters',\n              },\n              {\n                text: 'Coverage',\n                link: '/guide/coverage',\n              },\n              {\n                text: 'Testing Types',\n                link: '/guide/testing-types',\n              },\n              {\n                text: 'Vitest UI',\n                link: '/guide/ui',\n              },\n              {\n                text: 'In-Source Testing',\n                link: '/guide/in-source',\n              },\n              {\n                text: 'Test Annotations',\n                link: '/guide/test-annotations',\n              },\n              {\n                text: 'Extending Matchers',\n                link: '/guide/extending-matchers',\n              },\n              {\n                text: 'IDE Integration',\n                link: '/guide/ide',\n              },\n              {\n                text: 'Debugging',\n                link: '/guide/debugging',\n              },\n              {\n                text: 'Common Errors',\n                link: '/guide/common-errors',\n              },\n              {\n                text: 'Migration Guide',\n                link: '/guide/migration',\n                collapsed: false,\n                items: [\n                  {\n                    text: 'Migrating to Vitest 4.0',\n                    link: '/guide/migration#vitest-4',\n                  },\n                  {\n                    text: 'Migrating from Jest',\n                    link: '/guide/migration#jest',\n                  },\n                  {\n                    text: 'Migrating from Mocha + Chai + Sinon',\n                    link: '/guide/migration#mocha-chai-sinon',\n                  },\n                ],\n              },\n              {\n                text: 'Performance',\n                collapsed: false,\n                items: [\n                  {\n                    text: 'Profiling Test Performance',\n                    link: '/guide/profiling-test-performance',\n                  },\n                  {\n                    text: 'Improving Performance',\n                    link: '/guide/improving-performance',\n                  },\n                ],\n              },\n              {\n                text: 'OpenTelemetry',\n                link: '/guide/open-telemetry',\n              },\n            ],\n          },\n          {\n            text: 'Advanced',\n            collapsed: false,\n            items: [\n              {\n                text: 'Getting Started',\n                link: '/guide/advanced/',\n              },\n              {\n                text: 'Running Tests via API',\n                link: '/guide/advanced/tests',\n              },\n              {\n                text: 'Extending Reporters',\n                link: '/guide/advanced/reporters',\n              },\n              {\n                text: 'Custom Pool',\n                link: '/guide/advanced/pool',\n              },\n            ],\n          },\n          {\n            items: [\n              {\n                text: 'Recipes',\n                link: '/guide/recipes',\n              },\n              {\n                text: 'Comparisons',\n                link: '/guide/comparisons',\n              },\n            ],\n          },\n        ],\n        '/api': [\n          {\n            text: 'Test API Reference',\n            items: [\n              {\n                text: 'Test',\n                link: '/api/test',\n              },\n              {\n                text: 'Describe',\n                link: '/api/describe',\n              },\n              {\n                text: 'Hooks',\n                link: '/api/hooks',\n              },\n            ],\n          },\n          {\n            text: 'Mocks',\n            link: '/api/mock',\n          },\n          {\n            text: 'Vi Utility',\n            link: '/api/vi',\n          },\n          {\n            text: 'Expect',\n            link: '/api/expect',\n          },\n          {\n            text: 'ExpectTypeOf',\n            link: '/api/expect-typeof',\n          },\n          {\n            text: 'Assert',\n            link: '/api/assert',\n          },\n          {\n            text: 'AssertType',\n            link: '/api/assert-type',\n          },\n          {\n            text: 'Browser Mode',\n            items: [\n              {\n                text: 'Render Function',\n                collapsed: false,\n                items: [\n                  {\n                    text: 'react',\n                    link: '/api/browser/react',\n                  },\n                  {\n                    text: 'vue',\n                    link: '/api/browser/vue',\n                  },\n                  {\n                    text: 'svelte',\n                    link: '/api/browser/svelte',\n                  },\n                  // {\n                  //   text: 'angular',\n                  //   link: '/api/browser/angular',\n                  // },\n                ],\n              },\n              {\n                text: 'Context',\n                link: '/api/browser/context',\n              },\n              {\n                text: 'Interactivity',\n                link: '/api/browser/interactivity',\n              },\n              {\n                text: 'Locators',\n                link: '/api/browser/locators',\n              },\n              {\n                text: 'Assertions',\n                link: '/api/browser/assertions',\n              },\n              {\n                text: 'Commands',\n                link: '/api/browser/commands',\n              },\n            ],\n          },\n          {\n            text: 'Advanced',\n            collapsed: false,\n            items: [\n              {\n                text: 'Vitest',\n                link: '/api/advanced/vitest',\n              },\n              {\n                text: 'TestProject',\n                link: '/api/advanced/test-project',\n              },\n              {\n                text: 'TestSpecification',\n                link: '/api/advanced/test-specification',\n              },\n              {\n                text: 'TestCase',\n                link: '/api/advanced/test-case',\n              },\n              {\n                text: 'TestSuite',\n                link: '/api/advanced/test-suite',\n              },\n              {\n                text: 'TestModule',\n                link: '/api/advanced/test-module',\n              },\n              {\n                text: 'TestCollection',\n                link: '/api/advanced/test-collection',\n              },\n              {\n                text: 'VitestPlugin',\n                link: '/api/advanced/plugin',\n              },\n              {\n                text: 'VitestRunner',\n                link: '/api/advanced/runner',\n              },\n              {\n                text: 'Reporter',\n                link: '/api/advanced/reporters',\n              },\n              {\n                text: 'TaskMeta',\n                link: '/api/advanced/metadata',\n              },\n              {\n                text: 'TestArtifact',\n                link: '/api/advanced/artifacts',\n              },\n            ],\n          },\n          // {\n          //   text: 'Text Runner',\n          //   collapsed: false,\n          //   items: [\n          //     // TODO: generate\n          //     {\n          //       text: 'test',\n          //       link: '/api/test',\n          //     },\n          //     {\n          //       text: 'describe',\n          //       link: '/api/describe',\n          //     },\n          //     {\n          //       text: 'beforeEach',\n          //       link: '/api/before-each',\n          //     },\n          //     {\n          //       text: 'afterEach',\n          //       link: '/api/after-each',\n          //     },\n          //   ],\n          // },\n          // {\n          //   text: 'Assertion API',\n          //   collapsed: false,\n          //   items: [\n          //     {\n          //       text: 'expect',\n          //       link: '/api/expect',\n          //     },\n          //     {\n          //       text: 'assert',\n          //       link: '/api/assert',\n          //     },\n          //     {\n          //       text: 'expectTypeOf',\n          //       link: '/api/expect-typeof',\n          //     },\n          //     {\n          //       text: 'assertType',\n          //       link: '/api/assert-type',\n          //     },\n          //   ],\n          // },\n          // {\n          //   text: 'Vi Utility API',\n          //   collapsed: false,\n          //   items: [\n          //     {\n          //       text: 'Mock Modules',\n          //       link: '/api/vi/mock-modiles',\n          //     },\n          //     {\n          //       text: 'Mock Functions',\n          //       link: '/api/vi/mock-functions',\n          //     },\n          //     {\n          //       text: 'Mock Timers',\n          //       link: '/api/vi/mock-timers',\n          //     },\n          //     {\n          //       text: 'Miscellaneous',\n          //       link: '/api/vi/miscellaneous',\n          //     },\n          //   ],\n          // },\n          // {\n          //   text: 'Browser Mode',\n          //   collapsed: false,\n          //   items: [\n          //     // TODO: generate\n          //     {\n          //       text: 'page',\n          //       link: '/api/browser/page',\n          //     },\n          //     {\n          //       text: 'locators',\n          //       link: '/api/browser/locators',\n          //     },\n          //   ],\n          // },\n        ],\n      },\n    },\n    pwa,\n    transformHead,\n  })))\n}\n"
  },
  {
    "path": "docs/.vitepress/contributors.ts",
    "content": "import type { DefaultTheme } from 'vitepress'\n\nexport interface Contributor {\n  name: string\n  avatar: string\n}\n\nexport interface CoreTeam extends DefaultTheme.TeamMember {\n  // required to download avatars from GitHub\n  github: string\n  bluesky?: string\n  mastodon?: string\n  discord?: string\n  youtube?: string\n}\n\nfunction getAvatarUrl(name: string) {\n  return import.meta.hot ? `https://github.com/${name}.png` : `/user-avatars/${name}.png`\n}\n\nfunction createLinks(tm: CoreTeam): CoreTeam {\n  tm.links = [{ icon: 'github', link: `https://github.com/${tm.github}` }]\n  if (tm.bluesky) {\n    tm.links.push({ icon: 'bluesky', link: tm.bluesky })\n  }\n\n  if (tm.mastodon) {\n    tm.links.push({ icon: 'mastodon', link: tm.mastodon })\n  }\n\n  if (tm.discord) {\n    tm.links.push({ icon: 'discord', link: tm.discord })\n  }\n\n  if (tm.youtube) {\n    tm.links.push({ icon: 'youtube', link: `https://www.youtube.com/@${tm.youtube}` })\n  }\n\n  return tm\n}\n\nconst plainTeamMembers: CoreTeam[] = [\n  {\n    avatar: getAvatarUrl('sheremet-va'),\n    name: 'Vladimir',\n    github: 'sheremet-va',\n    bluesky: 'https://bsky.app/profile/erus.dev',\n    mastodon: 'https://elk.zone/m.webtoo.ls/@sheremet_va',\n    sponsor: 'https://github.com/sponsors/sheremet-va',\n    title: 'Open source developer',\n    desc: 'Core team member of Vitest & Vite',\n    org: 'VoidZero',\n    orgLink: 'https://voidzero.dev/',\n  },\n  {\n    avatar: getAvatarUrl('antfu'),\n    name: 'Anthony Fu',\n    github: 'antfu',\n    bluesky: 'https://bsky.app/profile/antfu.me',\n    mastodon: 'https://elk.zone/m.webtoo.ls/@antfu',\n    discord: 'https://chat.antfu.me',\n    youtube: 'antfu',\n    sponsor: 'https://github.com/sponsors/antfu',\n    title: 'A fanatical open sourceror',\n    org: 'Vercel',\n    orgLink: 'https://vercel.com/',\n    desc: 'Core team member of Vite & Vue',\n  },\n  {\n    avatar: getAvatarUrl('AriPerkkio'),\n    name: 'Ari Perkkiö',\n    github: 'AriPerkkio',\n    bluesky: 'https://bsky.app/profile/ariperkkio.dev',\n    sponsor: 'https://github.com/sponsors/AriPerkkio',\n    title: 'Open source engineer',\n    desc: 'Core team member of Vitest',\n    org: 'Chromatic',\n    orgLink: 'https://www.chromatic.com/',\n  },\n  {\n    avatar: getAvatarUrl('hi-ogawa'),\n    name: 'Hiroshi Ogawa',\n    github: 'hi-ogawa',\n    bluesky: 'https://bsky.app/profile/hiogawa.bsky.social',\n    sponsor: 'https://github.com/sponsors/hi-ogawa',\n    title: 'Open source enthusiast',\n    desc: 'Team member of Vitest',\n    org: 'VoidZero',\n    orgLink: 'https://voidzero.dev/',\n  },\n  {\n    avatar: getAvatarUrl('patak-dev'),\n    name: 'Patak',\n    github: 'patak-dev',\n    bluesky: 'https://bsky.app/profile/patak.dev',\n    mastodon: 'https://elk.zone/m.webtoo.ls/@patak',\n    sponsor: 'https://github.com/sponsors/patak-dev',\n    title: 'Independent Open Source Adventurer',\n    desc: 'Core team member of Vite & Vue',\n  },\n  {\n    avatar: getAvatarUrl('userquin'),\n    name: 'Joaquín Sánchez',\n    github: 'userquin',\n    bluesky: 'https://bsky.app/profile/userquin.bsky.social',\n    mastodon: 'https://elk.zone/m.webtoo.ls/@userquin',\n    title: 'A fullstack and android developer',\n    desc: 'Vite\\'s fanatical follower',\n  },\n]\n\nconst plainTeamEmeritiMembers: CoreTeam[] = [\n  {\n    avatar: getAvatarUrl('Dunqing'),\n    name: 'Dunqing',\n    github: 'Dunqing',\n    title: 'A passionate enthusiast of open source contributions',\n    desc: 'Team member of oxc & UnoCSS',\n  },\n  {\n    avatar: getAvatarUrl('Aslemammad'),\n    name: 'Mohammad Bagher',\n    github: 'Aslemammad',\n    bluesky: 'https://bsky.app/profile/aslemammad.bsky.social',\n    mastodon: 'https://elk.zone/m.webtoo.ls/@aslemammad',\n    title: 'An open source developer',\n    desc: 'Team member of Poimandres & Vike',\n  },\n  {\n    avatar: getAvatarUrl('Demivan'),\n    name: 'Ivan Demchuk',\n    github: 'Demivan',\n    mastodon: 'https://elk.zone/fosstodon.org/@demivan',\n    title: 'A tech lead, fullstack developer',\n    desc: 'Author of fluent-vue',\n  },\n  {\n    avatar: getAvatarUrl('poyoho'),\n    name: 'Yoho Po',\n    github: 'poyoho',\n    title: 'It\\'s no problem in my locall',\n    desc: 'Core team member of Vite & Team member of Vitest',\n  },\n  {\n    avatar: getAvatarUrl('zxch3n'),\n    name: 'Zixuan Chen',\n    github: 'zxch3n',\n    bluesky: 'https://bsky.app/profile/zxch3n.bsky.social',\n    mastodon: 'https://elk.zone/hachyderm.io/@zx',\n    title: 'A fullstack developer',\n    desc: 'Working on CRDTs & local-first software',\n  },\n]\n\nconst teamMembers = plainTeamMembers.map(tm => createLinks(tm))\nconst teamEmeritiMembers = plainTeamEmeritiMembers.map(tm => createLinks(tm))\n\nexport { teamEmeritiMembers, teamMembers }\n"
  },
  {
    "path": "docs/.vitepress/meta.ts",
    "content": "// noinspection ES6PreferShortImport: IntelliJ IDE hint to avoid warning to use `~/contributors`, will fail on build if changed\n\n/* Texts */\nexport const vitestName = 'Vitest'\nexport const vitestShortName = 'Vitest'\nexport const vitestDescription = 'Next generation testing framework powered by Vite'\n\n/* CDN fonts and styles */\nexport const googleapis = 'https://fonts.googleapis.com'\nexport const gstatic = 'https://fonts.gstatic.com'\nexport const font = `${googleapis}/css2?family=Readex+Pro:wght@200;400;600&display=swap`\n\n/* vitepress head */\nexport const ogUrl = 'https://vitest.dev/'\nexport const ogImage = `${ogUrl}og.jpg`\n\n/* GitHub and social links */\nexport const github = 'https://github.com/vitest-dev/vitest'\nexport const releases = 'https://github.com/vitest-dev/vitest/releases'\nexport const contributing = 'https://github.com/vitest-dev/vitest/blob/main/CONTRIBUTING.md'\nexport const discord = 'https://chat.vitest.dev'\nexport const bluesky = 'https://bsky.app/profile/vitest.dev'\nexport const mastodon = 'https://elk.zone/m.webtoo.ls/@vitest'\n\n/* Avatar/Image/Sponsors servers */\nexport const preconnectLinks = [googleapis, gstatic]\nexport const preconnectHomeLinks = [googleapis, gstatic]\n\n/* PWA runtime caching urlPattern regular expressions */\nexport const pwaFontsRegex = new RegExp(`^${googleapis}/.*`, 'i')\nexport const pwaFontStylesRegex = new RegExp(`^${gstatic}/.*`, 'i')\n// eslint-disable-next-line prefer-regex-literals\nexport const githubusercontentRegex = new RegExp('^https://((i.ibb.co)|((raw|user-images).githubusercontent.com))/.*', 'i')\n"
  },
  {
    "path": "docs/.vitepress/scripts/cli-generator.ts",
    "content": "import type { CLIOption, CLIOptions } from '../../../packages/vitest/src/node/cli/cli-config'\nimport { writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { cliOptionsConfig } from '../../../packages/vitest/src/node/cli/cli-config'\n\nconst docsDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')\nconst cliTablePath = resolve(docsDir, './guide/cli-generated.md')\n\nconst nonNullable = <T>(value: T): value is NonNullable<T> => value !== null && value !== undefined\n\nconst skipCli = new Set([\n  'mergeReports',\n  'changed',\n  'shard',\n])\n\nconst skipConfig = new Set([\n  'config',\n  'api.port',\n  'api.host',\n  'api.strictPort',\n  'coverage.watermarks.statements',\n  'coverage.watermarks.lines',\n  'coverage.watermarks.branches',\n  'coverage.watermarks.functions',\n  'coverage.thresholds.statements',\n  'coverage.thresholds.branches',\n  'coverage.thresholds.functions',\n  'coverage.thresholds.lines',\n  'standalone',\n  'clearScreen',\n  'configLoader',\n  'color',\n  'run',\n  'hideSkippedTests',\n  'dom',\n  'inspect',\n  'inspectBrk',\n  'project',\n  'ui',\n  'browser.name',\n  'browser.fileParallelism',\n  'clearCache',\n  'tagsFilter',\n  'listTags',\n])\n\nfunction resolveOptions(options: CLIOptions<any>, parentName?: string) {\n  return Object.entries(options).flatMap(\n    ([subcommandName, subcommandConfig]) => resolveCommand(\n      parentName ? `${parentName}.${subcommandName}` : subcommandName,\n      subcommandConfig,\n    ),\n  ).filter(nonNullable)\n}\n\nfunction resolveCommand(name: string, config: CLIOption<any> | null): any {\n  if (!config || skipCli.has(name)) {\n    return null\n  }\n\n  let title = '`'\n  if (config.shorthand) {\n    title += `-${config.shorthand}, `\n  }\n  title += `--${config.alias || name}`\n  if ('argument' in config) {\n    title += ` ${config.argument}`\n  }\n  title += '`'\n  if ('subcommands' in config && config.subcommands) {\n    return resolveOptions(config.subcommands, name)\n  }\n\n  return {\n    title: name,\n    cli: title,\n    description: config.description,\n  }\n}\n\nconst options = resolveOptions(cliOptionsConfig)\n\nconst template = options.map((option) => {\n  const title = option.title\n  const cli = option.cli\n  const [page, ...hash] = (title.startsWith('browser.') ? title.slice(8) : title).toLowerCase().split('.')\n  const config = skipConfig.has(title) ? '' : `[${title}](${title.includes('browser.') ? '/config/browser/' : '/config/'}${page}${hash.length ? `#${[page, ...hash].join('-')}` : ''})`\n  return `### ${title}\\n\\n- **CLI:** ${cli}\\n${config ? `- **Config:** ${config}\\n` : ''}\\n${option.description.replace(/https:\\/\\/vitest\\.dev\\//g, '/')}\\n`\n}).join('\\n')\n\nwriteFileSync(cliTablePath, template, 'utf-8')\n"
  },
  {
    "path": "docs/.vitepress/scripts/fetch-avatars.ts",
    "content": "import { existsSync, promises as fsp } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { dirname, join, resolve } from 'pathe'\nimport { teamEmeritiMembers, teamMembers } from '../contributors'\n\nconst docsDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')\nconst dirAvatars = resolve(docsDir, 'public/user-avatars/')\n\nasync function download(url: string, fileName: string) {\n  if (existsSync(fileName)) {\n    return\n  }\n\n  console.log('downloading', fileName)\n  try {\n    const image = await (await fetch(url)).arrayBuffer()\n    await fsp.writeFile(fileName, Buffer.from(image))\n  }\n  catch {}\n}\n\nasync function fetchAvatars() {\n  if (!existsSync(dirAvatars)) {\n    await fsp.mkdir(dirAvatars, { recursive: true })\n  }\n\n  await Promise.all([...teamEmeritiMembers, ...teamMembers].map(c => c.github).map(name => download(`https://github.com/${name}.png?size=100`, join(dirAvatars, `${name}.png`))))\n}\n\nfetchAvatars()\n"
  },
  {
    "path": "docs/.vitepress/scripts/pwa.ts",
    "content": "import type { PwaOptions } from '@vite-pwa/vitepress'\nimport {\n  githubusercontentRegex,\n  pwaFontsRegex,\n  pwaFontStylesRegex,\n  vitestDescription,\n  vitestName,\n  vitestShortName,\n} from '../meta'\n\nexport const pwa: PwaOptions = {\n  outDir: '.vitepress/dist',\n  registerType: 'autoUpdate',\n  // include all static assets under public/\n  manifest: {\n    id: '/',\n    name: vitestName,\n    short_name: vitestShortName,\n    description: vitestDescription,\n    theme_color: '#ffffff',\n    start_url: '/',\n    lang: 'en-US',\n    dir: 'ltr',\n    orientation: 'natural',\n    display: 'standalone',\n    display_override: ['window-controls-overlay'],\n    categories: ['development', 'developer tools'],\n    icons: [\n      {\n        src: 'pwa-64x64.png',\n        sizes: '64x64',\n        type: 'image/png',\n      },\n      {\n        src: 'pwa-192x192.png',\n        sizes: '192x192',\n        type: 'image/png',\n      },\n      {\n        src: 'pwa-512x512.png',\n        sizes: '512x512',\n        type: 'image/png',\n        purpose: 'any',\n      },\n      {\n        src: 'maskable-icon.png',\n        sizes: '512x512',\n        type: 'image/png',\n        purpose: 'maskable',\n      },\n    ],\n    screenshots: [{\n      src: 'og.jpg',\n      sizes: '2258x1185',\n      type: 'image/jpeg',\n      label: `Screenshot of ${vitestName}`,\n    }],\n    handle_links: 'preferred',\n    launch_handler: {\n      client_mode: ['navigate-existing', 'auto'],\n    },\n    edge_side_panel: {\n      preferred_width: 480,\n    },\n  },\n  workbox: {\n    navigateFallbackDenylist: [/^\\/new$/],\n    maximumFileSizeToCacheInBytes: 3 * 1024 * 1024, // <== 3MB\n    globPatterns: ['**/*.{css,js,html,png,svg,ico,txt,woff2,json}'],\n    // Rollup 4 change the layout: don't calculate revision (hash)\n    dontCacheBustURLsMatching: /^assets\\//,\n    runtimeCaching: [\n      {\n        urlPattern: pwaFontsRegex,\n        handler: 'CacheFirst',\n        options: {\n          cacheName: 'google-fonts-cache',\n          expiration: {\n            maxEntries: 10,\n            maxAgeSeconds: 60 * 60 * 24 * 365, // <== 365 days\n          },\n          cacheableResponse: {\n            statuses: [0, 200],\n          },\n        },\n      },\n      {\n        urlPattern: pwaFontStylesRegex,\n        handler: 'CacheFirst',\n        options: {\n          cacheName: 'gstatic-fonts-cache',\n          expiration: {\n            maxEntries: 10,\n            maxAgeSeconds: 60 * 60 * 24 * 365, // <== 365 days\n          },\n          cacheableResponse: {\n            statuses: [0, 200],\n          },\n        },\n      },\n      {\n        urlPattern: githubusercontentRegex,\n        handler: 'CacheFirst',\n        options: {\n          cacheName: 'githubusercontent-images-cache',\n          expiration: {\n            maxEntries: 10,\n            maxAgeSeconds: 60 * 60 * 24 * 365, // <== 365 days\n          },\n          cacheableResponse: {\n            statuses: [0, 200],\n          },\n        },\n      },\n    ],\n  },\n  experimental: {\n    includeAllowlist: true,\n  },\n}\n"
  },
  {
    "path": "docs/.vitepress/scripts/transformHead.ts",
    "content": "import type { HeadConfig, TransformContext } from 'vitepress'\n\nimport { preconnectHomeLinks, preconnectLinks } from '../meta'\n\nexport async function transformHead({ pageData }: TransformContext): Promise<HeadConfig[]> {\n  const head: HeadConfig[] = []\n\n  const home = pageData.relativePath === 'index.md'\n\n  ;(home ? preconnectHomeLinks : preconnectLinks).forEach((link) => {\n    head.push(['link', { rel: 'dns-prefetch', href: link }])\n    head.push(['link', { rel: 'preconnect', href: link }])\n  })\n\n  head.push(['link', { rel: 'prefetch', href: '/logo.svg', as: 'image' }])\n\n  return head\n}\n"
  },
  {
    "path": "docs/.vitepress/sponsors.ts",
    "content": "import type { SponsorTier } from '@voidzero-dev/vitepress-theme/src/types/sponsors'\n\nexport const sponsors: SponsorTier[] = [\n  {\n    tier: 'Special',\n    size: 'big',\n    items: [\n      {\n        name: 'Vercel',\n        url: 'https://vercel.com',\n        img: '/vercel.svg',\n      },\n      {\n        name: 'Chromatic',\n        url: 'https://www.chromatic.com/?utm_source=vitest&utm_medium=sponsorship&utm_campaign=vitestSponsorship',\n        img: '/chromatic.svg',\n      },\n      {\n        name: 'Zammad',\n        url: 'https://zammad.com',\n        img: '/zammad.svg',\n      },\n    ],\n  },\n  {\n    tier: 'Platinum Sponsors',\n    size: 'big',\n    items: [\n\n      {\n        name: 'Bolt',\n        url: 'https://bolt.new',\n        img: '/bolt.svg',\n      },\n    ],\n  },\n  {\n    tier: 'Gold',\n    size: 'medium',\n    items: [\n      {\n        name: 'vital',\n        url: 'https://vital.io/',\n        img: '/vital.svg',\n      },\n      {\n        name: 'OOMOL',\n        url: 'https://oomol.com/',\n        img: '/oomol.svg',\n      },\n      {\n        name: 'Mailmeteor',\n        url: 'https://mailmeteor.com/',\n        img: '/mailmeteor.svg',\n      },\n      {\n        name: 'Liminity',\n        url: 'https://www.liminity.se/',\n        img: '/liminity.svg',\n      },\n      {\n        name: 'Aerius Ventilation',\n        url: 'https://aerius.se/',\n        img: '/aerius.png',\n      },\n    ],\n  },\n]\n"
  },
  {
    "path": "docs/.vitepress/theme/FeatureGrid.vue",
    "content": "<script setup>\nimport esmAnimation from '@assets/vitest/animations/640_x_300_esm.riv'\nimport vitePoweredAnimation from '@assets/vitest/animations/650_x_300_vite_powered.riv'\nimport RiveAnimation from '@components/shared/RiveAnimation.vue'\n</script>\n\n<template>\n  <section class=\"wrapper wrapper--ticks border-t grid lg:grid-cols-2 divide-x divide-y divide-nickel\">\n    <div class=\"flex flex-col gap-3\">\n      <div class=\"p-5 sm:p-10 pb-0 sm:pb-0 flex flex-col gap-3\">\n        <h5 class=\"text-balance sm:text-pretty text-white\">\n          Vite Powered\n        </h5>\n        <p class=\"sm:max-w-[30rem] text-pretty\">\n          Reuse <code\n            class=\"mr-1 outline-none bg-nickel/50 text-vite\"\n          >Vite</code>'s config and plugins - consistent across your app and tests.\n          But it's not required to use Vitest!\n        </p>\n      </div>\n      <RiveAnimation\n        :desktop-src=\"vitePoweredAnimation\"\n        :desktop-width=\"650\"\n        :desktop-height=\"300\"\n        canvas-class=\"w-full\"\n      />\n    </div>\n    <div class=\"flex flex-col gap-3 border-r-0 justify-between\">\n      <div class=\"p-5 sm:p-10 pb-0 sm:pb-0 flex flex-col gap-3\">\n        <h5 class=\"text-white\">\n          Jest Compatible\n        </h5>\n        <p class=\"max-w-[28rem] text-pretty\">\n          Expect, snapshot, coverage, and more - migrating from <code\n            class=\"mr-1 outline-none bg-nickel/50 text-zest\"\n          >Jest</code> is\n          straightforward.\n        </p>\n      </div>\n      <div class=\"flex-1 flex items-center justify-center p-5 sm:p-10\">\n        <img src=\"@assets/vitest/vitest-jest-compatible.png\" inert loading=\"lazy\" alt=\"jest compatible\" class=\"w-full max-w-50\">\n      </div>\n    </div>\n    <div class=\"flex flex-col gap-3 justify-between\">\n      <div class=\"p-5 sm:p-10 flex flex-col gap-3\">\n        <h5 class=\"text-white\">\n          Smart & instant watch mode\n        </h5>\n        <p class=\"max-w-[23rem] text-pretty\">\n          Only rerun the related changes, just like HMR for tests!\n        </p>\n      </div>\n      <div class=\"card-bg px-5 sm:px-10 pt-5 sm:pt-10 flex justify-center\">\n        <img src=\"@assets/vitest/vitest-watcher.png\" inert loading=\"lazy\" alt=\"typed api\">\n      </div>\n    </div>\n    <div class=\"flex flex-col gap-3 justify-between\">\n      <div class=\"p-5 sm:p-10 pb-0 sm:pb-0 flex flex-col gap-3\">\n        <h5 class=\"text-white\">\n          ESM, TypeScript, JSX\n        </h5>\n        <p class=\"max-w-[25rem] text-pretty\">\n          Out-of-box ESM, TypeScript and JSX support powered by <code class=\"mx-1 outline-none bg-nickel/50 text-aqua\">Oxc</code>.\n        </p>\n      </div>\n      <RiveAnimation\n        :desktop-src=\"esmAnimation\"\n        :desktop-width=\"640\"\n        :desktop-height=\"300\"\n        canvas-class=\"w-full\"\n      />\n    </div>\n  </section>\n  <section class=\"wrapper border-t py-10 flex items-center justify-center\">\n    <a href=\"/guide/features\" class=\"button\">See full features list</a>\n  </section>\n</template>\n\n<style scoped>\n.card-bg {\n  background-image: url('@assets/vitest/vitest-watcher-background.jpg');\n  background-size: cover;\n  background-position: center;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/Hero.vue",
    "content": "<template>\n  <div class=\"wrapper wrapper--ticks grid md:grid-cols-2 w-full border-nickel divide-x\">\n    <div class=\"flex flex-col p-10 justify-center items-center md:items-start\">\n      <div class=\"flex flex-col gap-5 max-w-[30rem] text-center md:text-left items-center md:items-start\">\n        <a class=\"flex items-center gap-2\" href=\"https://voidzero.dev\" target=\"_blank\">\n          <span class=\"text-grey text-xs font-mono uppercase tracking-wide\">By</span>\n          <img src=\"@assets/logos/voidzero-light.svg\" alt=\"VoidZero\" class=\"h-2.5\">\n        </a>\n        <h1 class=\"text-white text-pretty\">\n          Next Generation Testing Framework\n        </h1>\n        <p class=\"text-white/70 text-lg max-w-[25rem] text-pretty\">\n          A Vite-native testing framework. It's fast!\n        </p>\n        <div class=\"flex items-center gap-5 mt-8\">\n          <a href=\"/guide/\" class=\"button button--primary inline-block w-fit\">\n            <span>Get Started</span>\n          </a>\n          <a href=\"https://github.com/vitest-dev/vitest\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"button inline-block w-fit\">\n            View on GitHub\n          </a>\n        </div>\n      </div>\n    </div>\n    <div class=\"flex flex-col min-h-[22rem] sm:min-h-[30rem]\">\n      <div class=\"relative pl-6 sm:pl-16 h-full flex flex-col justify-center overflow-clip py-8 sm:py-16 hero-background\">\n        <img src=\"@assets/vitest/hero-terminal.png\" alt=\"Vitest terminal\" class=\"w-full h-full object-contain\">\n      </div>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.hero-background {\n  background-image: url('@assets/vitest/hero-background.jpg');\n  background-size: cover;\n  background-position: center;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/Home.vue",
    "content": "<script setup>\nimport Footer from '@components/oss/Footer.vue'\n// import TrustedBy from '@components/oss/TrustedBy.vue'\nimport HeadingSection from '@components/oss/HeadingSection.vue'\nimport Sponsors from '@components/oss/Sponsors.vue'\nimport Spacer from '@components/shared/Spacer.vue'\nimport { sponsors } from '../sponsors'\nimport VitestFeatureGrid from './FeatureGrid.vue'\nimport Hero from './Hero.vue'\nimport Intro from './Intro.vue'\n</script>\n\n<template>\n  <Hero />\n  <!-- 'some-company' requires public/trusted-by/some-company.svg -->\n  <!-- <TrustedBy :logos=\"['some-company']\" /> -->\n  <Intro />\n  <HeadingSection heading=\"Fast. Lightweight. Integrated.\" />\n  <VitestFeatureGrid />\n  <Sponsors\n    description=\"Vitest is free and open source, made possible by wonderful sponsors.\"\n    sponsor-link=\"https://github.com/sponsors/vitest-dev\" :sponsors=\"sponsors\"\n  />\n  <Spacer />\n  <Footer\n    heading=\"Start testing with Vitest\"\n    subheading=\"Supercharge your tests with unparalleled performance made for the modern web\" button-text=\"Get started\"\n    button-link=\"/guide/\"\n  />\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/Intro.vue",
    "content": "<template>\n  <div class=\"wrapper wrapper--ticks border-t py-14 lg:py-30 px-5 sm:px-10 lg:px-20\">\n    <div class=\"flex flex-col lg:flex-row lg:justify-between lg:items-center gap-5 lg:gap-8 text-left\">\n      <div class=\"flex flex-col gap-3 max-w-md\">\n        <div class=\"flex gap-3 items-center\">\n          <img src=\"@assets/icons/vitest-light.svg\" alt=\"Vitest icon\" class=\"size-5\">\n          <span class=\"text-grey text-xs font-medium font-mono uppercase tracking-wide\">Why Vitest</span>\n        </div>\n        <h3 class=\"text-white max-w-xl text-balance\">\n          The Vite Native Test Runner\n        </h3>\n        <a href=\"/guide/why\" target=\"_blank\" class=\"button w-fit mt-8 hidden lg:block\">Learn more</a>\n      </div>\n      <div class=\"lg:max-w-lg\">\n        <p class=\"text-pretty mb-5\">\n          Vitest was created to make testing just work for <a href=\"https://vite.dev\" target=\"_blank\"><code\n            class=\"mr-1 outline-none bg-nickel/50 text-vite\"\n          >Vite</code></a> apps. By building on top of Vite, Vitest\n          natively\n          understands your Vite config and is able to reuse the same resolve and\n          transform pipelines.\n        </p>\n        <p class=\"text-pretty\">\n          You can also use Vitest even if you are not using Vite. It is Jest-compatible\n          and works for backend code too.\n        </p>\n        <a href=\"/guide/why\" target=\"_blank\" class=\"button w-fit mt-8 block lg:hidden\">Learn more</a>\n      </div>\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/index.ts",
    "content": "import type { Theme } from 'vitepress'\nimport TwoslashFloatingVue from '@shikijs/vitepress-twoslash/client'\nimport { inBrowser } from 'vitepress'\nimport VitestTheme from '@voidzero-dev/vitepress-theme/src/vitest'\nimport { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client'\nimport Version from '../components/Version.vue'\nimport CRoot from '../components/CRoot.vue'\nimport Deprecated from '../components/Deprecated.vue'\nimport Experimental from '../components/Experimental.vue'\nimport Advanced from '../components/Advanced.vue'\nimport CourseLink from '../components/CourseLink.vue'\nimport './styles.css'\nimport '@shikijs/vitepress-twoslash/style.css'\nimport 'virtual:group-icons.css'\n\nif (inBrowser) {\n  // redirect old hash links (e.g. /config/#reporters -> /config/reporters)\n  // before hydration to avoid SSG hydration mismatch\n  const redirect = getRedirectPath(new URL(location.href))\n  if (redirect) {\n    location.replace(redirect)\n  }\n  import('./pwa')\n}\n\nfunction getRedirectPath(url: URL) {\n  if (url.pathname === '/api/' || url.pathname === '/api' || url.pathname === '/api/index.html') {\n    return '/api/test'\n  }\n  if (!url.hash) {\n    return\n  }\n\n  // /config/#reporters           -> /config/reporters\n  // /config/#coverage-provider   -> /config/coverage#coverage-provider\n  // /config/#browser.enabled     -> /config/browser/enabled\n  if (url.pathname === '/config' || url.pathname === '/config/' || url.pathname === '/config.html') {\n    if (url.hash.startsWith('#browser.')) {\n      const [page, ...hash] = url.hash.slice('#browser.'.length).toLowerCase().split('-')\n      return `/config/browser/${page}${hash.length ? `#${[page, ...hash].join('-')}` : ''}`\n    }\n    const [page, ...hash] = url.hash.slice(1).toLowerCase().split('-')\n    return `/config/${page}${hash.length ? `#${[page, ...hash].join('-')}` : ''}`\n  }\n  // /guide/browser/config#browser.locators-testidattribute -> /config/browser/locators#browser-locators-testidattribute\n  if (url.pathname === '/guide/browser/config' || url.pathname === '/guide/browser/config/' || url.pathname === '/guide/browser/config.html') {\n    const [page, ...hash] = url.hash.slice('#browser.'.length).toLowerCase().split('-')\n    return `/config/browser/${page}${hash.length ? `#${[page, ...hash].join('-')}` : ''}`\n  }\n}\n\nexport default {\n  extends: VitestTheme as unknown as any,\n  enhanceApp({ app }) {\n    app.component('Version', Version)\n    app.component('CRoot', CRoot)\n    app.component('Experimental', Experimental)\n    app.component('Deprecated', Deprecated)\n    app.component('Advanced', Advanced)\n    app.component('CourseLink', CourseLink)\n    app.use(TwoslashFloatingVue)\n    enhanceAppWithTabs(app)\n  },\n} satisfies Theme\n"
  },
  {
    "path": "docs/.vitepress/theme/pwa.ts",
    "content": "import { registerSW } from 'virtual:pwa-register'\n\nregisterSW({ immediate: true })\n"
  },
  {
    "path": "docs/.vitepress/theme/styles.css",
    "content": "@import \"@voidzero-dev/vitepress-theme/src/styles/index.css\";\n\n@source \"./**/*.vue\";\n\n/* Vitest */\n:root[data-variant=\"vitest\"] {\n  --color-brand: #008039;\n  /* TODO: home page wcag-aa color contrast (remove this once fixed at void0 theme):\n   * - why vitest section and texts\n   * - vitest, resources, versions and social\n   * - footer\n   */\n  --color-grey: #867e8e;\n}\n\n:root.dark:not([data-theme])[data-variant=\"vitest\"],\n:root[data-theme=\"dark\"][data-variant=\"vitest\"] {\n  --color-brand: var(--color-zest);\n}\n\n:root[data-variant=\"vitest\"]:not(.dark):not([data-theme=\"light\"]),\n:root[data-theme=\"light\"][data-variant=\"vitest\"] {\n  --color-brand: #008039;\n  /* TODO: code block (remove this once fixed at void0 theme) */\n  --vp-code-color: #007d38;\n}\n\n\n.highlighted-word {\n  background-color: var(--vp-code-line-highlight-color);\n  transition: background-color 0.5s;\n  display: inline-block;\n}\n\n/* credit goes to https://dylanatsmith.com/wrote/styling-the-kbd-element */\nhtml:not(.dark) .VPContent kbd {\n  --kbd-color-background: #f7f7f7;\n  --kbd-color-border: #cbcccd;\n  --kbd-color-text: #222325;\n}\n\n.VPContent kbd {\n  --kbd-color-background: #898b90;\n  --kbd-color-border: #3d3e42;\n  --kbd-color-text: #222325;\n\n  background-color: var(--kbd-color-background);\n  color: var(--kbd-color-text);\n  border-radius: 0.25rem;\n  border: 1px solid var(--kbd-color-border);\n  box-shadow: 0 2px 0 1px var(--kbd-color-border);\n  font-family: var(--font-family-sans-serif);\n  font-size: 0.75em;\n  line-height: 1;\n  min-width: 0.75rem;\n  text-align: center;\n  padding: 2px 5px;\n  position: relative;\n  top: -1px;\n}\n"
  },
  {
    "path": "docs/api/advanced/artifacts.md",
    "content": "---\noutline: deep\ntitle: Test Artifacts\n---\n\n# Test Artifacts <Advanced /> <Version type=\"experimental\">4.0.11</Version> <Experimental />\n\n::: warning\nThis is an advanced API. As a user, you most likely want to use [test annotations](/guide/test-annotations) to add notes or context to your tests instead. This is primarily used internally and by library authors.\n:::\n\nTest artifacts allow attaching or recording structured data, files, or metadata during test execution. This is a low-level feature primarily designed for:\n\n- Internal use ([`annotate`](/guide/test-annotations) is built on top of the artifact system)\n- Framework authors creating custom testing tools on top of Vitest\n\nEach artifact includes:\n\n- A type discriminator which is a unique identifier for the artifact type\n- Custom data, can be any relevant information\n- Optional attachments, either files or inline content associated with the artifact\n- A source code location indicating where the artifact was created\n\nVitest automatically manages attachment serialization (files are copied to [`attachmentsDir`](/config/attachmentsdir)) and injects source location metadata, so you can focus on the data you want to record. All artifacts **must** extend from [`TestArtifactBase`](#testartifactbase) and all attachments from [`TestAttachment`](#testattachment) to be correctly handled internally.\n\n## API\n\n### `recordArtifact` <Experimental /> {#recordartifact}\n\n::: warning\n`recordArtifact` is an experimental API. Breaking changes might not follow SemVer, please pin Vitest's version when using it.\n\nThe API surface may change based on feedback. We encourage you to try it out and share your experience with the team.\n:::\n\n```ts\nfunction recordArtifact<Artifact extends TestArtifact>(task: Test, artifact: Artifact): Promise<Artifact>\n```\n\nThe `recordArtifact` function records an artifact during test execution and returns it. It expects a [task](/api/advanced/runner#tasks) as the first parameter and an object assignable to [`TestArtifact`](#testartifact) as the second.\n\n::: info\nArtifacts must be recorded before the task is reported. Any artifacts recorded after that will not be included in the task.\n:::\n\nWhen an artifact is recorded on a test, it emits an `onTestArtifactRecord` runner event and a [`onTestCaseArtifactRecord` reporter event](/api/advanced/reporters#ontestcaseartifactrecord). To retrieve recorded artifacts from a test case, use the [`artifacts()`](/api/advanced/test-case#artifacts) method.\n\nNote: annotations, [even though they're built on top of this feature](#relationship-with-annotations), won't appear in the `task.artifacts` array for backwards compatibility reasons until the next major version.\n\n### `TestArtifact`\n\nThe `TestArtifact` type is a union containing all artifacts Vitest can produce, including custom ones. All artifacts extend from [`TestArtifactBase`](#testartifactbase)\n\n### `TestArtifactBase` <Experimental /> {#testartifactbase}\n\n```ts\nexport interface TestArtifactBase {\n  /** File or data attachments associated with this artifact */\n  attachments?: TestAttachment[]\n  /** Source location where this artifact was created */\n  location?: TestArtifactLocation\n}\n```\n\nThe `TestArtifactBase` interface is the base for all test artifacts.\n\nExtend this interface when creating custom test artifacts. Vitest automatically manages the `attachments` array and injects the `location` property to indicate where the artifact was created in your test code.\n\n::: danger\nWhen running with [`api.allowWrite`](/config/api#api-allowwrite) or [`browser.api.allowWrite`](/config/browser/api#api-allowwrite) disabled, Vitest empties the `attachments` array on every artifact before reporting it.\n\nIf your custom artifact narrows the `attachments` type (e.g. to a tuple), include `| []` in the union so the type reflects what actually happens at runtime.\n:::\n\n### `TestAttachment`\n\n```ts\nexport interface TestAttachment {\n  /** MIME type of the attachment (e.g., 'image/png', 'text/plain') */\n  contentType?: string\n  /** File system path to the attachment */\n  path?: string\n  /** Inline attachment content as a string or raw binary data */\n  body?: string | Uint8Array\n}\n```\n\nThe `TestAttachment` interface represents a file or data attachment associated with a test artifact.\n\nAttachments can be either file-based (via `path`) or inline content (via `body`). The `contentType` helps consumers understand how to interpret the attachment data.\n\n### `TestArtifactLocation`\n\n```ts\nexport interface TestArtifactLocation {\n  /** Line number in the source file (1-indexed) */\n  line: number\n  /** Column number in the line (1-indexed) */\n  column: number\n  /** Path to the source file */\n  file: string\n}\n```\n\nThe `TestArtifactLocation` interface represents the source code location information for a test artifact. It indicates where in the source code the artifact originated from.\n\n### `TestArtifactRegistry`\n\nThe `TestArtifactRegistry` interface is a registry for custom test artifact types.\n\nAugmenting this interface using [TypeScript's module augmentation feature](https://typescriptlang.org/docs/handbook/declaration-merging#module-augmentation) allows registering custom artifact types that tests can produce.\n\nEach custom artifact should extend [`TestArtifactBase`](#testartifactbase) and include a unique `type` discriminator property.\n\nHere are a few guidelines or best practices to follow:\n\n- Try using a `Symbol` as the **registry key** to guarantee uniqueness\n- The `type` property should follow the pattern `'package-name:artifact-name'`, **`'internal:'` is a reserved prefix**\n- Use `attachments` to include files or data; extend [`TestAttachment`](#testattachment) for custom metadata\n- If you narrow the `attachments` type (e.g. to a tuple), include `| []` in the union since Vitest may empty the array at runtime (see [`TestArtifactBase`](#testartifactbase))\n- `location` property is automatically injected\n\n## Custom Artifacts\n\nTo use and manage artifacts in a type-safe manner, you need to create its type and register it:\n\n```ts\nimport type { TestArtifactBase, TestAttachment } from 'vitest'\n\ninterface A11yReportAttachment extends TestAttachment {\n  contentType: 'text/html'\n  path: string\n}\n\ninterface AccessibilityArtifact extends TestArtifactBase {\n  type: 'a11y:report'\n  passed: boolean\n  wcagLevel: 'A' | 'AA' | 'AAA'\n  attachments: [A11yReportAttachment] | []\n}\n\nconst a11yReportKey = Symbol('report')\n\ndeclare module 'vitest' {\n  interface TestArtifactRegistry {\n    [a11yReportKey]: AccessibilityArtifact\n  }\n}\n```\n\nAs long as the types are assignable to their bases and don't have errors, everything should work fine and you should be able to record artifacts using [`recordArtifact`](#recordartifact):\n\n```ts\nasync function toBeAccessible(\n  this: MatcherState,\n  actual: Element,\n  wcagLevel: 'A' | 'AA' | 'AAA' = 'AA'\n): AsyncExpectationResult {\n  const report = await runAccessibilityAudit(actual, wcagLevel)\n\n  await recordArtifact(this.task, {\n    type: 'a11y:report',\n    passed: report.violations.length === 0,\n    wcagLevel,\n    attachments: [{\n      contentType: 'text/html',\n      path: report.path,\n    }],\n  })\n\n  return {\n    pass: violations.length === 0,\n    message: () => `Found ${report.violations.length} accessibility violation(s)`\n  }\n}\n```\n\n## Relationship with Annotations\n\nTest annotations are built on top of the artifact system. When using annotations in tests, they create `internal:annotation` artifacts under the hood. However, annotations are:\n\n- Simpler to use\n- Designed for end-users, not developers\n\nUse annotations if you just want to add notes to your tests. Use artifacts if you need custom data.\n"
  },
  {
    "path": "docs/api/advanced/import-example.md",
    "content": "```ts\nfunction import<T>(moduleId: string): Promise<T>\n```\n"
  },
  {
    "path": "docs/api/advanced/metadata.md",
    "content": "# Task Metadata <Badge type=\"danger\">advanced</Badge>\n\nIf you are developing a custom reporter or using Vitest Node.js API, you might find it useful to pass data from tests that are being executed in various contexts to your reporter or custom Vitest handler.\n\nTo accomplish this, relying on the [test context](/guide/test-context) is not feasible since it cannot be serialized. However, with Vitest, you can utilize the `meta` property available on every task (suite or test) to share data between your tests and the Node.js process. It's important to note that this communication is one-way only, as the `meta` property can only be modified from within the test context. Any changes made within the Node.js context will not be visible in your tests.\n\nYou can populate `meta` property on test context or inside `beforeAll`/`afterAll` hooks for suite tasks.\n\n```ts\nafterAll((suite) => {\n  suite.meta.done = true\n})\n\ntest('custom', ({ task }) => {\n  task.meta.custom = 'some-custom-handler'\n})\n```\n\nOnce a test is completed, Vitest will send a task including the result and `meta` to the Node.js process using RPC, and then report it in `onTestCaseResult` and other hooks that have access to tasks. To process this test case, you can utilize the `onTestCaseResult` method available in your reporter implementation:\n\n```ts [custom-reporter.js]\nimport type { Reporter, TestCase, TestModule } from 'vitest/node'\n\nexport default {\n  onTestCaseResult(testCase: TestCase) {\n    // custom === 'some-custom-handler' ✅\n    const { custom } = testCase.meta()\n  },\n  onTestRunEnd(testModule: TestModule) {\n    testModule.meta().done === true\n    testModule.children.at(0).meta().custom === 'some-custom-handler'\n  }\n} satisfies Reporter\n```\n\n::: danger BEWARE\nVitest uses different methods to communicate with the Node.js process.\n\n- If Vitest runs tests inside worker threads, it will send data via [message port](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort)\n- If Vitest uses child process, the data will be send as a serialized Buffer via [`process.send`](https://nodejs.org/api/process.html#processsendmessage-sendhandle-options-callback) API\n- If Vitest runs tests in the browser, the data will be stringified using [flatted](https://npmx.dev/package/flatted) package\n\nThis property is also present on every test in the `json` reporter, so make sure that data can be serialized into JSON.\n\nAlso, make sure you serialize [Error properties](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#error_types) before you set them.\n:::\n\nYou can also get this information from Vitest state when tests finished running:\n\n```ts\nconst vitest = await createVitest('test')\nconst { testModules } = await vitest.start()\n\nconst testModule = testModules[0]\ntestModule.meta().done === true\ntestModule.children.at(0).meta().custom === 'some-custom-handler'\n```\n\nIt's also possible to extend type definitions when using TypeScript:\n\n```ts\ndeclare module 'vitest' {\n  interface TaskMeta {\n    done?: boolean\n    custom?: string\n  }\n}\n```\n"
  },
  {
    "path": "docs/api/advanced/plugin.md",
    "content": "---\ntitle: Plugin API\noutline: deep\n---\n\n# Plugin API <Version>3.1.0</Version> {#plugin-api}\n\n::: warning\nThis is an advanced API. If you just want to [run tests](/guide/), you probably don't need this. It is primarily used by library authors.\n\nThis guide assumes you know how to work with [Vite plugins](https://vite.dev/guide/api-plugin.html).\n:::\n\nVitest supports a `configureVitest` [plugin](https://vite.dev/guide/api-plugin.html) hook since version 3.1.\n\n::: code-group\n```ts [only vitest]\nimport type { Vite, VitestPluginContext } from 'vitest/node'\n\nexport function plugin(): Vite.Plugin {\n  return {\n    name: 'vitest:my-plugin',\n    configureVitest(context: VitestPluginContext) {\n      // ...\n    }\n  }\n}\n```\n```ts [vite and vitest]\n/// <reference types=\"vitest/config\" />\n\nimport type { Plugin } from 'vite'\n\nexport function plugin(): Plugin {\n  return {\n    name: 'vitest:my-plugin',\n    transform() {\n      // ...\n    },\n    configureVitest(context) {\n      // ...\n    }\n  }\n}\n```\n:::\n\n::: tip TypeScript\nVitest re-exports all Vite type-only imports via a `Vite` namespace, which you can use to keep your versions in sync. However, if you are writing a plugin for both Vite and Vitest, you can continue using the `Plugin` type from the `vite` entrypoint. Just make sure you have `vitest/config` referenced somewhere so that `configureVitest` is augmented correctly:\n\n```ts\n/// <reference types=\"vitest/config\" />\n```\n:::\n\nUnlike [`reporter.onInit`](/api/advanced/reporters#oninit), this hooks runs early in Vitest lifecycle allowing you to make changes to configuration like `coverage` and `reporters`. A more notable change is that you can manipulate the global config from a [test project](/guide/projects) if your plugin is defined in the project and not in the global config.\n\n## Context\n\n### project\n\nThe current [test project](./test-project) that the plugin belongs to.\n\n::: warning Browser Mode\nNote that if you are relying on a browser feature, the `project.browser` field is not set yet. Use [`reporter.onBrowserInit`](./reporters#onbrowserinit) event instead.\n:::\n\n### vitest\n\nThe global [Vitest](./vitest) instance. You can change the global configuration by directly mutating the `vitest.config` property:\n\n```ts\nvitest.config.coverage.enabled = false\nvitest.config.reporters.push([['my-reporter', {}]])\n```\n\n::: warning Config is Resolved\nNote that Vitest already resolved the config, so some types might be different from the usual user configuration. This also means that some properties will not be resolved again, like `setupFile`. If you are adding new files, make sure to resolve it first.\n\nAt this point reporters are not created yet, so modifying `vitest.reporters` will have no effect because it will be overwritten. If you need to inject your own reporter, modify the config instead.\n:::\n\n### injectTestProjects\n\n```ts\nfunction injectTestProjects(\n  config: TestProjectConfiguration | TestProjectConfiguration[]\n): Promise<TestProject[]>\n```\n\nThis methods accepts a config glob pattern, a filepath to the config or an inline configuration. It returns an array of resolved [test projects](./test-project).\n\n```ts\n// inject a single project with a custom alias\nconst newProjects = await injectTestProjects({\n  // you can inherit the current project config by referencing `extends`\n  // note that you cannot have a project with the name that already exists,\n  // so it's a good practice to define a custom name\n  extends: project.vite.config.configFile,\n  test: {\n    name: 'my-custom-alias',\n    alias: {\n      customAlias: resolve('./custom-path.js'),\n    },\n  },\n})\n```\n\n::: warning Projects are Filtered\nVitest filters projects during the config resolution, so if the user defined a filter, injected project might not be resolved unless it [matches the filter](./vitest#matchesprojectfilter). You can update the filter via the `vitest.config.project` option to always include your test project:\n\n```ts\nvitest.config.project.push('my-project-name')\n```\n\nNote that this will only affect projects injected with [`injectTestProjects`](#injecttestprojects) method.\n:::\n\n::: tip Referencing the Current Config\nIf you want to keep the user configuration, you can specify the `extends` property. All other properties will be merged with the user defined config.\n\nThe project's `configFile` can be accessed in Vite's config: `project.vite.config.configFile`.\n\nNote that this will also inherit the `name` - Vitest doesn't allow multiple projects with the same name, so this will throw an error. Make sure you specified a different name. You can access the current name via the `project.name` property and all used names are available in the `vitest.projects` array.\n:::\n\n### experimental_defineCacheKeyGenerator <Version type=\"experimental\">4.0.11</Version> <Experimental /> {#definecachekeygenerator}\n\n```ts\ninterface CacheKeyIdGeneratorContext {\n  environment: DevEnvironment\n  id: string\n  sourceCode: string\n}\n\nfunction experimental_defineCacheKeyGenerator(\n  callback: (context: CacheKeyIdGeneratorContext) => string | undefined | null | false\n): void\n```\n\nDefine a generator that will be applied before hashing the cache key.\n\nUse this to make sure Vitest generates correct hash. It is a good idea to define this function if your plugin can be registered with different options.\n\nThis is called only if [`experimental.fsModuleCache`](/config/experimental#experimental-fsmodulecache) is defined.\n\n```ts\ninterface PluginOptions {\n  replacePropertyKey: string\n  replacePropertyValue: string\n}\n\nexport function plugin(options: PluginOptions) {\n  return {\n    name: 'plugin-that-replaces-property',\n    transform(code) {\n      return code.replace(\n        options.replacePropertyKey,\n        options.replacePropertyValue\n      )\n    },\n    configureVitest({ experimental_defineCacheKeyGenerator }) {\n      experimental_defineCacheKeyGenerator(() => {\n        // since these options affect the transform result,\n        // return them together as a unique string\n        return options.replacePropertyKey + options.replacePropertyValue\n      })\n    }\n  }\n}\n```\n\nIf `false` is returned, the module will not be cached on the file system.\n"
  },
  {
    "path": "docs/api/advanced/reporters.md",
    "content": "# Reporters\n\n::: warning\nThis is an advanced API. If you just want to configure built-in reporters, read the [\"Reporters\"](/guide/reporters) guide.\n:::\n\nVitest has its own test run lifecycle. These are represented by reporter's methods:\n\n- [`onInit`](#oninit)\n- [`onTestRunStart`](#ontestrunstart)\n  - [`onTestModuleQueued`](#ontestmodulequeued)\n  - [`onTestModuleCollected`](#ontestmodulecollected)\n  - [`onTestModuleStart`](#ontestmodulestart)\n    - [`onTestSuiteReady`](#ontestsuiteready)\n      - [`onHookStart(beforeAll)`](#onhookstart)\n      - [`onHookEnd(beforeAll)`](#onhookend)\n        - [`onTestCaseReady`](#ontestcaseready)\n          - [`onTestCaseAnnotate`](#ontestcaseannotate) <Version>3.2.0</Version>\n          - [`onTestCaseArtifactRecord`](#ontestcaseartifactrecord) <Version type=\"experimental\">4.0.11</Version>\n          - [`onHookStart(beforeEach)`](#onhookstart)\n          - [`onHookEnd(beforeEach)`](#onhookend)\n          - [`onHookStart(afterEach)`](#onhookstart)\n          - [`onHookEnd(afterEach)`](#onhookend)\n        - [`onTestCaseResult`](#ontestcaseresult)\n      - [`onHookStart(afterAll)`](#onhookstart)\n      - [`onHookEnd(afterAll)`](#onhookend)\n    - [`onTestSuiteResult`](#ontestsuiteresult)\n  - [`onTestModuleEnd`](#ontestmoduleend)\n  - [`onCoverage`](#oncoverage)\n- [`onTestRunEnd`](#ontestrunend)\n\nTests and suites within a single module will be reported in order unless they were skipped. All skipped tests are reported at the end of suite/module.\n\nNote that since test modules can run in parallel, Vitest will report them in parallel.\n\nThis guide lists all supported reporter methods. However, don't forget that instead of creating your own reporter, you can [extend existing one](/guide/advanced/reporters) instead:\n\n```ts [custom-reporter.js]\nimport { BaseReporter } from 'vitest/node'\n\nexport default class CustomReporter extends BaseReporter {\n  onTestRunEnd(testModules, errors) {\n    console.log(testModule.length, 'tests finished running')\n    super.onTestRunEnd(testModules, errors)\n  }\n}\n```\n\n## onInit\n\n```ts\nfunction onInit(vitest: Vitest): Awaitable<void>\n```\n\nThis method is called when [Vitest](/api/advanced/vitest) was initiated or started, but before the tests were filtered.\n\n::: info\nInternally this method is called inside [`vitest.start`](/api/advanced/vitest#start), [`vitest.init`](/api/advanced/vitest#init) or [`vitest.mergeReports`](/api/advanced/vitest#mergereports). If you are using programmatic API, make sure to call either one depending on your needs before calling [`vitest.runTestSpecifications`](/api/advanced/vitest#runtestspecifications), for example. Built-in CLI will always run methods in correct order.\n:::\n\nNote that you can also get access to `vitest` instance from test cases, suites and test modules via a [`project`](/api/advanced/test-project) property, but it might also be useful to store a reference to `vitest` in this method.\n\n::: details Example\n```ts\nimport type { Reporter, TestSpecification, Vitest } from 'vitest/node'\n\nclass MyReporter implements Reporter {\n  private vitest!: Vitest\n\n  onInit(vitest: Vitest) {\n    this.vitest = vitest\n  }\n\n  onTestRunStart(specifications: TestSpecification[]) {\n    console.log(\n      specifications.length,\n      'test files will run in',\n      this.vitest.config.root,\n    )\n  }\n}\n\nexport default new MyReporter()\n```\n:::\n\n## onBrowserInit {#onbrowserinit}\n\n```ts\nfunction onBrowserInit(project: TestProject): Awaitable<void>\n```\n\nThis method is called when the browser instance is initiated. It receives an instance of the project for which the browser is initiated. `project.browser` will always be defined when this method is called.\n\n## onTestRunStart\n\n```ts\nfunction onTestRunStart(\n  specifications: TestSpecification[]\n): Awaitable<void>\n```\n\nThis method is called when a new test run has started. It receives an array of [test specifications](/api/advanced/test-specification) scheduled to run. This array is readonly and available only for information purposes.\n\nIf Vitest didn't find any test files to run, this event will be invoked with an empty array, and then [`onTestRunEnd`](#ontestrunend) will be called immediately after.\n\n::: details Example\n```ts\nimport type { Reporter, TestSpecification } from 'vitest/node'\n\nclass MyReporter implements Reporter {\n  onTestRunStart(specifications: TestSpecification[]) {\n    console.log(specifications.length, 'test files will run')\n  }\n}\n\nexport default new MyReporter()\n```\n:::\n\n## onTestRunEnd\n\n```ts\nfunction onTestRunEnd(\n  testModules: ReadonlyArray<TestModule>,\n  unhandledErrors: ReadonlyArray<SerializedError>,\n  reason: TestRunEndReason\n): Awaitable<void>\n```\n\nThis method is called after all tests have finished running and the coverage merged all reports, if it's enabled. Note that you can get the coverage information in [`onCoverage`](#oncoverage) hook.\n\nIt receives a readonly list of test modules. You can iterate over it via a [`testModule.children`](/api/advanced/test-collection) property to report the state and errors, if any.\n\nThe second argument is a readonly list of unhandled errors that Vitest wasn't able to attribute to any test. These can happen outside of the test run because of an error in a plugin, or inside the test run as a side-effect of a non-awaited function (for example, a timeout that threw an error after the test has finished running).\n\nThe third argument indicated why the test run was finished:\n\n- `passed`: test run was finished normally and there are no errors\n- `failed`: test run has at least one error (due to a syntax error during collection or an actual error during test execution)\n- `interrupted`: test was interrupted by [`vitest.cancelCurrentRun`](/api/advanced/vitest#cancelcurrentrun) call or `Ctrl+C` was pressed in the terminal (note that it's still possible to have failed tests in this case)\n\nIf Vitest didn't find any test files to run, this event will be invoked with empty arrays of modules and errors, and the state will depend on the value of [`config.passWithNoTests`](/config/passwithnotests).\n\n::: details Example\n```ts\nimport type {\n  Reporter,\n  SerializedError,\n  TestModule,\n  TestRunEndReason,\n  TestSpecification\n} from 'vitest/node'\n\nclass MyReporter implements Reporter {\n  onTestRunEnd(\n    testModules: ReadonlyArray<TestModule>,\n    unhandledErrors: ReadonlyArray<SerializedError>,\n    reason: TestRunEndReason,\n  ) {\n    if (reason === 'passed') {\n      testModules.forEach(module => console.log(module.moduleId, 'succeeded'))\n    }\n    else if (reason === 'failed') {\n      // note that this will skip possible errors in suites\n      // you can get them from testSuite.errors()\n      for (const testCase of testModules.children.allTests()) {\n        if (testCase.result().state === 'failed') {\n          console.log(testCase.fullName, 'in', testCase.module.moduleId, 'failed')\n          console.log(testCase.result().errors)\n        }\n      }\n    }\n    else {\n      console.log('test run was interrupted, skipping report')\n    }\n  }\n}\n\nexport default new MyReporter()\n```\n:::\n\n## onCoverage\n\n```ts\nfunction onCoverage(coverage: unknown): Awaitable<void>\n```\n\nThis hook is called after coverage results have been processed. Coverage provider's reporters are called after this hook. The typings of `coverage` depends on the `coverage.provider`. For Vitest's default built-in providers you can import the types from `istanbul-lib-coverage` package:\n\n```ts\nimport type { CoverageMap } from 'istanbul-lib-coverage'\n\ndeclare function onCoverage(coverage: CoverageMap): Awaitable<void>\n```\n\nIf Vitest didn't perform any coverage, this hook is not called.\n\n## onTestModuleQueued\n\n```ts\nfunction onTestModuleQueued(testModule: TestModule): Awaitable<void>\n```\n\nThis method is called right before Vitest imports the setup file and the test module itself. This means that `testModule` will have no [`children`](/api/advanced/test-suite#children) yet, but you can start reporting it as the next test to run.\n\n## onTestModuleCollected\n\n```ts\nfunction onTestModuleCollected(testModule: TestModule): Awaitable<void>\n```\n\nThis method is called when all tests inside the file were collected, meaning [`testModule.children`](/api/advanced/test-suite#children) collection is populated, but tests don't have any results yet.\n\n## onTestModuleStart\n\n```ts\nfunction onTestModuleStart(testModule: TestModule): Awaitable<void>\n```\n\nThis method is called right after [`onTestModuleCollected`](#ontestmodulecollected) unless Vitest runs in collection mode ([`vitest.collect()`](/api/advanced/vitest#collect) or `vitest collect` in the CLI), in this case it will not be called at all because there are no tests to run.\n\n## onTestModuleEnd\n\n```ts\nfunction onTestModuleEnd(testModule: TestModule): Awaitable<void>\n```\n\nThis method is called when every test in the module finished running. This means, every test inside [`testModule.children`](/api/advanced/test-suite#children) will have a `test.result()` that is not equal to `pending`.\n\n## onHookStart\n\n```ts\nfunction onHookStart(context: ReportedHookContext): Awaitable<void>\n```\n\nThis method is called when any of these hooks have started running:\n\n- `beforeAll`\n- `afterAll`\n- `beforeEach`\n- `afterEach`\n\nIf `beforeAll` or `afterAll` are started, the `entity` will be either [`TestSuite`](/api/advanced/test-suite) or [`TestModule`](/api/advanced/test-module).\n\nIf `beforeEach` or `afterEach` are started, the `entity` will always be [`TestCase`](/api/advanced/test-case).\n\n::: warning\n`onHookStart` method will not be called if the hook did not run during the test run.\n:::\n\n## onHookEnd\n\n```ts\nfunction onHookEnd(context: ReportedHookContext): Awaitable<void>\n```\n\nThis method is called when any of these hooks have finished running:\n\n- `beforeAll`\n- `afterAll`\n- `beforeEach`\n- `afterEach`\n\nIf `beforeAll` or `afterAll` have finished, the `entity` will be either [`TestSuite`](/api/advanced/test-suite) or [`TestModule`](/api/advanced/test-module).\n\nIf `beforeEach` or `afterEach` have finished, the `entity` will always be [`TestCase`](/api/advanced/test-case).\n\n::: warning\n`onHookEnd` method will not be called if the hook did not run during the test run.\n:::\n\n## onTestSuiteReady\n\n```ts\nfunction onTestSuiteReady(testSuite: TestSuite): Awaitable<void>\n```\n\nThis method is called before the suite starts to run its tests. This method is also called if the suite was skipped.\n\nIf the file doesn't have any suites, this method will not be called. Consider using `onTestModuleStart` to cover this use case.\n\n## onTestSuiteResult\n\n```ts\nfunction onTestSuiteResult(testSuite: TestSuite): Awaitable<void>\n```\n\nThis method is called after the suite has finished running tests. This method is also called if the suite was skipped.\n\nIf the file doesn't have any suites, this method will not be called. Consider using `onTestModuleEnd` to cover this use case.\n\n## onTestCaseReady\n\n```ts\nfunction onTestCaseReady(testCase: TestCase): Awaitable<void>\n```\n\nThis method is called before the test starts to run or it was skipped. Note that `beforeEach` and `afterEach` hooks are considered part of the test because they can influence the result.\n\n::: warning\nNotice that it's possible to have [`testCase.result()`](/api/advanced/test-case#result) with `passed` or `failed` state already when `onTestCaseReady` is called. This can happen if test was running too fast and both `onTestCaseReady` and `onTestCaseResult` were scheduled to run in the same microtask.\n:::\n\n## onTestCaseResult\n\n```ts\nfunction onTestCaseResult(testCase: TestCase): Awaitable<void>\n```\n\nThis method is called when the test has finished running or was just skipped. Note that this will be called after the `afterEach` hook is finished, if there are any.\n\nAt this point, [`testCase.result()`](/api/advanced/test-case#result) will have non-pending state.\n\n## onTestCaseAnnotate <Version>3.2.0</Version> {#ontestcaseannotate}\n\n```ts\nfunction onTestCaseAnnotate(\n  testCase: TestCase,\n  annotation: TestAnnotation,\n): Awaitable<void>\n```\n\nThe `onTestCaseAnnotate` hook is associated with the [`context.annotate`](/guide/test-context#annotate) method. When `annotate` is invoked, Vitest serialises it and sends the same attachment to the main thread where reporter can interact with it.\n\nIf the path is specified, Vitest stores it in a separate directory (configured by [`attachmentsDir`](/config/attachmentsdir)) and modifies the `path` property to reference it.\n\n## onTestCaseArtifactRecord <Version type=\"experimental\">4.0.11</Version> {#ontestcaseartifactrecord}\n\n```ts\nfunction onTestCaseArtifactRecord(\n  testCase: TestCase,\n  artifact: TestArtifact,\n): Awaitable<void>\n```\n\nThe `onTestCaseArtifactRecord` hook is associated with the [`recordArtifact`](/api/advanced/artifacts#recordartifact) utility. When `recordArtifact` is invoked, Vitest serialises it and sends the same attachment to the main thread where reporter can interact with it.\n\nIf the path is specified, Vitest stores it in a separate directory (configured by [`attachmentsDir`](/config/attachmentsdir)) and modifies the `path` property to reference it.\n\nNote: annotations, [even though they're built on top of this feature](/api/advanced/artifacts#relationship-with-annotations), won't hit this hook and won't appear in the `task.artifacts` array for backwards compatibility reasons until the next major version.\n"
  },
  {
    "path": "docs/api/advanced/runner.md",
    "content": "# Runner API <Badge type=\"danger\">advanced</Badge>\n\n::: warning\nThis is advanced API. If you just want to [run tests](/guide/), you probably don't need this. It is primarily used by library authors.\n:::\n\nYou can specify a path to your test runner with the `runner` option in your configuration file. This file should have a default export with a class constructor implementing these methods:\n\n```ts\nexport interface VitestRunner {\n  /**\n   * First thing that's getting called before actually collecting and running tests.\n   */\n  onBeforeCollect?: (paths: string[]) => unknown\n  /**\n   * Called after collecting tests and before \"onBeforeRun\".\n   */\n  onCollected?: (files: File[]) => unknown\n\n  /**\n   * Called when test runner should cancel next test runs.\n   * Runner should listen for this method and mark tests and suites as skipped in\n   * \"onBeforeRunSuite\" and \"onBeforeRunTask\" when called.\n   */\n  onCancel?: (reason: CancelReason) => unknown\n\n  /**\n   * Called before running a single test. Doesn't have \"result\" yet.\n   */\n  onBeforeRunTask?: (test: Test) => unknown\n  /**\n   * Called before actually running the test function. Already has \"result\" with \"state\" and \"startTime\".\n   */\n  onBeforeTryTask?: (test: Test, options: { retry: number; repeats: number }) => unknown\n  /**\n   * Called after result and state are set.\n   */\n  onAfterRunTask?: (test: Test) => unknown\n  /**\n   * Called right after running the test function. Doesn't have new state yet. Will not be called, if the test function throws.\n   */\n  onAfterTryTask?: (test: Test, options: { retry: number; repeats: number }) => unknown\n  /**\n   * Called after the retry resolution happened. Unlike `onAfterTryTask`, the test now has a new state.\n   * All `after` hooks were also called by this point.\n   */\n  onAfterRetryTask?: (test: Test, options: { retry: number; repeats: number }) => unknown\n\n  /**\n   * Called before running a single suite. Doesn't have \"result\" yet.\n   */\n  onBeforeRunSuite?: (suite: Suite) => unknown\n  /**\n   * Called after running a single suite. Has state and result.\n   */\n  onAfterRunSuite?: (suite: Suite) => unknown\n\n  /**\n   * If defined, will be called instead of usual Vitest suite partition and handling.\n   * \"before\" and \"after\" hooks will not be ignored.\n   */\n  runSuite?: (suite: Suite) => Promise<void>\n  /**\n   * If defined, will be called instead of usual Vitest handling. Useful, if you have your custom test function.\n   * \"before\" and \"after\" hooks will not be ignored.\n   */\n  runTask?: (test: TaskPopulated) => Promise<void>\n\n  /**\n   * Called, when a task is updated. The same as \"onTaskUpdate\" in a reporter, but this is running in the same thread as tests.\n   */\n  onTaskUpdate?: (task: [string, TaskResult | undefined, TaskMeta | undefined][]) => Promise<void>\n\n  /**\n   * Called before running all tests in collected paths.\n   */\n  onBeforeRunFiles?: (files: File[]) => unknown\n  /**\n   * Called right after running all tests in collected paths.\n   */\n  onAfterRunFiles?: (files: File[]) => unknown\n  /**\n   * Called when new context for a test is defined. Useful, if you want to add custom properties to the context.\n   * If you only want to define custom context with a runner, consider using \"beforeAll\" in \"setupFiles\" instead.\n   */\n  extendTaskContext?: (context: TestContext) => TestContext\n  /**\n   * Called when certain files are imported. Can be called in two situations: to collect tests and to import setup files.\n   */\n  importFile: (filepath: string, source: VitestRunnerImportSource) => unknown\n  /**\n   * Function that is called when the runner attempts to get the value when `test.extend` is used with `{ injected: true }`\n   */\n  injectValue?: (key: string) => unknown\n  /**\n   * Publicly available configuration.\n   */\n  config: VitestRunnerConfig\n  /**\n   * The name of the current pool. Can affect how stack trace is inferred on the server side.\n   */\n  pool?: string\n}\n```\n\nWhen initiating this class, Vitest passes down Vitest config, - you should expose it as a `config` property:\n\n```ts [runner.ts]\nimport type { RunnerTestFile, SerializedConfig, TestRunner, VitestTestRunner } from 'vitest'\n\nclass CustomRunner extends TestRunner implements VitestTestRunner {\n  public config: SerializedConfig\n\n  constructor(config: SerializedConfig) {\n    this.config = config\n  }\n\n  onAfterRunFiles(files: RunnerTestFile[]) {\n    console.log('finished running', files)\n  }\n}\n\nexport default CustomRunner\n```\n\n::: warning\nVitest also injects an instance of `ModuleRunner` from `vite/module-runner` as `moduleRunner` property. You can use it to process files in `importFile` method (this is default behavior of `TestRunner` and `BenchmarkRunner`).\n\n`ModuleRunner` exposes `import` method, which is used to import test files in a Vite-friendly environment. Meaning, it will resolve imports and transform file content at runtime so that Node can understand it:\n\n```ts\nexport default class Runner {\n  async importFile(filepath: string) {\n    await this.moduleRunner.import(filepath)\n  }\n}\n```\n:::\n\n::: warning\nIf you don't have a custom runner or didn't define `runTest` method, Vitest will try to retrieve a task automatically. If you didn't add a function with `setFn`, it will fail.\n:::\n\n::: tip\nSnapshot support and some other features depend on the runner. If you don't want to lose it, you can extend your runner from `VitestTestRunner` imported from `vitest/runners`. It also exposes `NodeBenchmarkRunner`, if you want to extend benchmark functionality.\n:::\n\n## Tasks\n\n::: warning\nThe \"Runner Tasks API\" is experimental and should primarily be used only in the test runtime. Vitest also exposes the [\"Reported Tasks API\"](/api/advanced/test-module), which should be preferred when working in the main thread (inside the reporter, for example).\n\nThe team is currently discussing if \"Runner Tasks\" should be replaced by \"Reported Tasks\" in the future.\n:::\n\nSuites and tests are called `tasks` internally. Vitest runner initiates a `File` task before collecting any tests - this is a superset of `Suite` with a few additional properties. It is available on every task (including `File`) as a `file` property.\n\n```ts\ninterface File extends Suite {\n  /**\n   * The name of the pool that the file belongs to.\n   * @default 'forks'\n   */\n  pool?: string\n  /**\n   * The path to the file in UNIX format.\n   */\n  filepath: string\n  /**\n   * The name of the test project the file belongs to.\n   */\n  projectName: string | undefined\n  /**\n   * The time it took to collect all tests in the file.\n   * This time also includes importing all the file dependencies.\n   */\n  collectDuration?: number\n  /**\n   * The time it took to import the setup file.\n   */\n  setupDuration?: number\n}\n```\n\nEvery suite has a `tasks` property that is populated during collection phase. It is useful to traverse the task tree from the top down.\n\n```ts\ninterface Suite extends TaskBase {\n  type: 'suite'\n  /**\n   * File task. It's the root task of the file.\n   */\n  file: File\n  /**\n   * An array of tasks that are part of the suite.\n   */\n  tasks: Task[]\n}\n```\n\nEvery task has a `suite` property that references a suite it is located in. If `test` or `describe` are initiated at the top level, they will not have a `suite` property (it will **not** be equal to `file`!). `File` also never has a `suite` property. It is useful to travers the tasks from the bottom up.\n\n```ts\ninterface Test<ExtraContext = object> extends TaskBase {\n  type: 'test'\n  /**\n   * Test context that will be passed to the test function.\n   */\n  context: TestContext & ExtraContext\n  /**\n   * File task. It's the root task of the file.\n   */\n  file: File\n  /**\n   * Whether the task was skipped by calling `context.skip()`.\n   */\n  pending?: boolean\n  /**\n   * Whether the task should succeed if it fails. If the task fails, it will be marked as passed.\n   */\n  fails?: boolean\n  /**\n   * Store promises (from async expects) to wait for them before finishing the test\n   */\n  promises?: Promise<any>[]\n}\n```\n\nEvery task can have a `result` field. Suites can only have this field if an error thrown within a suite callback or `beforeAll`/`afterAll` callbacks prevents them from collecting tests. Tests always have this field after their callbacks are called - the `state` and `errors` fields are present depending on the outcome. If an error was thrown in `beforeEach` or `afterEach` callbacks, the thrown error will be present in `task.result.errors`.\n\n```ts\nexport interface TaskResult {\n  /**\n   * State of the task. Inherits the `task.mode` during collection.\n   * When the task has finished, it will be changed to `pass` or `fail`.\n   * - **pass**: task ran successfully\n   * - **fail**: task failed\n   */\n  state: TaskState\n  /**\n   * Errors that occurred during the task execution. It is possible to have several errors\n   * if `expect.soft()` failed multiple times.\n   */\n  errors?: TestError[]\n  /**\n   * How long in milliseconds the task took to run.\n   */\n  duration?: number\n  /**\n   * Time in milliseconds when the task started running.\n   */\n  startTime?: number\n  /**\n   * Heap size in bytes after the task finished.\n   * Only available if `logHeapUsage` option is set and `process.memoryUsage` is defined.\n   */\n  heap?: number\n  /**\n   * State of related to this task hooks. Useful during reporting.\n   */\n  hooks?: Partial<Record<'afterAll' | 'beforeAll' | 'beforeEach' | 'afterEach', TaskState>>\n  /**\n   * The amount of times the task was retried. The task is retried only if it\n   * failed and `retry` option is set.\n   */\n  retryCount?: number\n  /**\n   * The amount of times the task was repeated. The task is repeated only if\n   * `repeats` option is set. This number also contains `retryCount`.\n   */\n  repeatCount?: number\n}\n```\n\n## Your Task Function\n\nVitest exposes `createTaskCollector` utility to create your own `test` method. It behaves the same way as a test, but calls a custom method during collection.\n\nA task is an object that is part of a suite. It is automatically added to the current suite with a `suite.task` method:\n\n```js [custom.js]\nexport { afterAll, beforeAll, describe, TestRunner } from 'vitest'\n\n// this function will be called during collection phase:\n// don't call function handler here, add it to suite tasks\n// with \"getCurrentSuite().task()\" method\n// note: createTaskCollector provides support for \"todo\"/\"each\"/...\nexport const myCustomTask = TestRunner.createTaskCollector(\n  function (name, fn, timeout) {\n    TestRunner.getCurrentSuite().task(name, {\n      ...this, // so \"todo\"/\"skip\"/... is tracked correctly\n      meta: {\n        customPropertyToDifferentiateTask: true\n      },\n      handler: fn,\n      timeout,\n    })\n  }\n)\n```\n\n```js [tasks.test.js]\nimport {\n  afterAll,\n  beforeAll,\n  describe,\n  myCustomTask\n} from './custom.js'\nimport { gardener } from './gardener.js'\n\ndescribe('take care of the garden', () => {\n  beforeAll(() => {\n    gardener.putWorkingClothes()\n  })\n\n  myCustomTask('weed the grass', () => {\n    gardener.weedTheGrass()\n  })\n  myCustomTask.todo('mow the lawn', () => {\n    gardener.mowerTheLawn()\n  })\n  myCustomTask('water flowers', () => {\n    gardener.waterFlowers()\n  })\n\n  afterAll(() => {\n    gardener.goHome()\n  })\n})\n```\n\n```bash\nvitest ./garden/tasks.test.js\n```\n"
  },
  {
    "path": "docs/api/advanced/test-case.md",
    "content": "# TestCase\n\nThe `TestCase` class represents a single test. This class is only available in the main thread. Refer to the [\"Runner API\"](/api/advanced/runner#tasks) if you are working with runtime tasks.\n\nThe `TestCase` instance always has a `type` property with the value of `test`. You can use it to distinguish between different task types:\n\n```ts\nif (task.type === 'test') {\n  task // TestCase\n}\n```\n\n## project\n\nThis references the [`TestProject`](/api/advanced/test-project) that the test belongs to.\n\n## module\n\nThis is a direct reference to the [`TestModule`](/api/advanced/test-module) where the test is defined.\n\n## name\n\nThis is a test name that was passed to the `test` function.\n\n```ts\nimport { test } from 'vitest'\n\n// [!code word:'the validation works correctly']\ntest('the validation works correctly', () => {\n  // ...\n})\n```\n\n## fullName\n\nThe name of the test including all parent suites separated with `>` symbol. This test has a full name \"the validation logic > the validation works correctly\":\n\n```ts\nimport { describe, test } from 'vitest'\n\n// [!code word:'the validation works correctly']\n// [!code word:'the validation logic']\ndescribe('the validation logic', () => {\n  test('the validation works correctly', () => {\n    // ...\n  })\n})\n```\n\n## id\n\nThis is test's unique identifier. This ID is deterministic and will be the same for the same test across multiple runs. The ID is based on the [project](/api/advanced/test-project) name, module ID and test order.\n\nThe ID looks like this:\n\n```\n1223128da3_0_0\n^^^^^^^^^^ the file hash\n           ^ suite index\n             ^ test index\n```\n\n::: tip\nYou can generate file hash with `generateFileHash` function from `vitest/node` which is available since Vitest 3:\n\n```ts\nimport { generateFileHash } from 'vitest/node'\n\nconst hash = generateFileHash(\n  '/file/path.js', // relative path\n  undefined, // the project name or `undefined` is not set\n)\n```\n:::\n\n::: danger\nDon't try to parse the ID. It can have a minus at the start: `-1223128da3_0_0_0`.\n:::\n\n## location\n\nThe location in the module where the test was defined. Locations are collected only if [`includeTaskLocation`](/config/includetasklocation) is enabled in the config. Note that this option is automatically enabled if `--reporter=html`, `--ui` or `--browser` flags are used.\n\nThe location of this test will be equal to `{ line: 3, column: 1 }`:\n\n```ts:line-numbers {3}\nimport { test } from 'vitest'\n\ntest('the validation works correctly', () => {\n  // ...\n})\n```\n\n## parent\n\nParent [suite](/api/advanced/test-suite). If the test was called directly inside the [module](/api/advanced/test-module), the parent will be the module itself.\n\n## options\n\n```ts\ninterface TaskOptions {\n  readonly each: boolean | undefined\n  readonly fails: boolean | undefined\n  readonly concurrent: boolean | undefined\n  readonly shuffle: boolean | undefined\n  readonly retry: number | undefined\n  readonly repeats: number | undefined\n  readonly tags: string[] | undefined\n  readonly timeout: number | undefined\n  readonly mode: 'run' | 'only' | 'skip' | 'todo'\n}\n```\n\nThe options that test was collected with.\n\n## tags <Version>4.1.0</Version> {#tags}\n\n[Tags](/guide/test-tags) that were implicitly or explicitly assigned to the test.\n\n## ok\n\n```ts\nfunction ok(): boolean\n```\n\nChecks if the test did not fail the suite. If the test is not finished yet or was skipped, it will return `true`.\n\n## meta\n\n```ts\nfunction meta(): TaskMeta\n```\n\nCustom [metadata](/api/advanced/metadata) that was attached to the test during its execution. The meta can be attached by assigning a property to the `ctx.task.meta` object during a test run:\n\n```ts {3,6}\nimport { test } from 'vitest'\n\ntest('the validation works correctly', ({ task }) => {\n  // ...\n\n  task.meta.decorated = false\n})\n```\n\nIf the test did not finish running yet, the meta will be an empty object, unless it has static meta:\n\n```ts\ntest('the validation works correctly', { meta: { decorated: true } })\n```\n\nSince Vitest 4.1, Vitest inherits [`meta`](/api/advanced/test-suite#meta) property defined on the [suite](/api/advanced/test-suite).\n\n## result\n\n```ts\nfunction result(): TestResult\n```\n\nTest results. If test is not finished yet or was just collected, it will be equal to `TestResultPending`:\n\n```ts\nexport interface TestResultPending {\n  /**\n   * The test was collected, but didn't finish running yet.\n   */\n  readonly state: 'pending'\n  /**\n   * Pending tests have no errors.\n   */\n  readonly errors: undefined\n}\n```\n\nIf the test was skipped, the return value will be `TestResultSkipped`:\n\n```ts\ninterface TestResultSkipped {\n  /**\n   * The test was skipped with `skip` or `todo` flag.\n   * You can see which one was used in the `options.mode` option.\n   */\n  readonly state: 'skipped'\n  /**\n   * Skipped tests have no errors.\n   */\n  readonly errors: undefined\n  /**\n   * A custom note passed down to `ctx.skip(note)`.\n   */\n  readonly note: string | undefined\n}\n```\n\n::: tip\nIf the test was skipped because another test has `only` flag, the `options.mode` will be equal to `skip`.\n:::\n\nIf the test failed, the return value will be `TestResultFailed`:\n\n```ts\ninterface TestResultFailed {\n  /**\n   * The test failed to execute.\n   */\n  readonly state: 'failed'\n  /**\n   * Errors that were thrown during the test execution.\n   */\n  readonly errors: ReadonlyArray<TestError>\n}\n```\n\nIf the test passed, the return value will be `TestResultPassed`:\n\n```ts\ninterface TestResultPassed {\n  /**\n   * The test passed successfully.\n   */\n  readonly state: 'passed'\n  /**\n   * Errors that were thrown during the test execution.\n   */\n  readonly errors: ReadonlyArray<TestError> | undefined\n}\n```\n\n::: warning\nNote that the test with `passed` state can still have errors attached - this can happen if `retry` was triggered at least once.\n:::\n\n## diagnostic\n\n```ts\nfunction diagnostic(): TestDiagnostic | undefined\n```\n\nUseful information about the test like duration, memory usage, etc:\n\n```ts\ninterface TestDiagnostic {\n  /**\n   * If the duration of the test is above `slowTestThreshold`.\n   */\n  readonly slow: boolean\n  /**\n   * The amount of memory used by the test in bytes.\n   * This value is only available if the test was executed with `logHeapUsage` flag.\n   */\n  readonly heap: number | undefined\n  /**\n   * The time it takes to execute the test in ms.\n   */\n  readonly duration: number\n  /**\n   * The time in ms when the test started.\n   */\n  readonly startTime: number\n  /**\n   * The amount of times the test was retried.\n   */\n  readonly retryCount: number\n  /**\n   * The amount of times the test was repeated as configured by `repeats` option.\n   * This value can be lower if the test failed during the repeat and no `retry` is configured.\n   */\n  readonly repeatCount: number\n  /**\n   * If test passed on a second retry.\n   */\n  readonly flaky: boolean\n}\n```\n\n::: info\n`diagnostic()` will return `undefined` if the test was not scheduled to run yet.\n:::\n\n## annotations\n\n```ts\nfunction annotations(): ReadonlyArray<TestAnnotation>\n```\n\n[Test annotations](/guide/test-annotations) added via the [`task.annotate`](/guide/test-context#annotate) API during the test execution.\n\n## artifacts <Version type=\"experimental\">4.0.11</Version> <Experimental /> {#artifacts}\n\n```ts\nfunction artifacts(): ReadonlyArray<TestArtifact>\n```\n\n[Test artifacts](/api/advanced/artifacts) recorded via the `recordArtifact` API during the test execution.\n\n## toTestSpecification <Version>4.1.0</Version> {#totestspecification}\n\n```ts\nfunction toTestSpecification(): TestSpecification\n```\n\nReturns a new [test specification](/api/advanced/test-specification) that can be used to filter or run this specific test case.\n"
  },
  {
    "path": "docs/api/advanced/test-collection.md",
    "content": "# TestCollection\n\n`TestCollection` represents a collection of top-level [suites](/api/advanced/test-suite) and [tests](/api/advanced/test-case) in a suite or a module. It also provides useful methods to iterate over itself.\n\n::: info\nMost methods return an iterator instead of an array for better performance in case you don't need every item in the collection. If you prefer working with array, you can spread the iterator: `[...children.allSuites()]`.\n\nAlso note that the collection itself is an iterator:\n\n```ts\nfor (const child of module.children) {\n  console.log(child.type, child.name)\n}\n```\n:::\n\n## size\n\nThe number of tests and suites in the collection.\n\n::: warning\nThis number includes only tests and suites at the top-level, it doesn't include nested suites and tests.\n:::\n\n## at\n\n```ts\nfunction at(index: number): TestCase | TestSuite | undefined\n```\n\nReturns the test or suite at a specific index. This method accepts negative indexes.\n\n## array\n\n```ts\nfunction array(): (TestCase | TestSuite)[]\n```\n\nThe same collection but as an array. This is useful if you want to use `Array` methods like `map` and `filter` that are not supported by the `TaskCollection` implementation.\n\n## allSuites\n\n```ts\nfunction allSuites(): Generator<TestSuite, undefined, void>\n```\n\nFilters all suites that are part of this collection and its children.\n\n```ts\nfor (const suite of module.children.allSuites()) {\n  if (suite.errors().length) {\n    console.log('failed to collect', suite.errors())\n  }\n}\n```\n\n## allTests\n\n```ts\nfunction allTests(state?: TestState): Generator<TestCase, undefined, void>\n```\n\nFilters all tests that are part of this collection and its children.\n\n```ts\nfor (const test of module.children.allTests()) {\n  if (test.result().state === 'pending') {\n    console.log('test', test.fullName, 'did not finish')\n  }\n}\n```\n\nYou can pass down a `state` value to filter tests by the state.\n\n## tests\n\n```ts\nfunction tests(state?: TestState): Generator<TestCase, undefined, void>\n```\n\nFilters only the tests that are part of this collection. You can pass down a `state` value to filter tests by the state.\n\n## suites\n\n```ts\nfunction suites(): Generator<TestSuite, undefined, void>\n```\n\nFilters only the suites that are part of this collection.\n"
  },
  {
    "path": "docs/api/advanced/test-module.md",
    "content": "# TestModule\n\nThe `TestModule` class represents a single module in a single project. This class is only available in the main thread. Refer to the [\"Runner API\"](/api/advanced/runner#tasks) if you are working with runtime tasks.\n\nThe `TestModule` instance always has a `type` property with the value of `module`. You can use it to distinguish between different task types:\n\n```ts\nif (task.type === 'module') {\n  task // TestModule\n}\n```\n\n::: warning Extending Suite Methods\nThe `TestModule` class inherits all methods and properties from the [`TestSuite`](/api/advanced/test-suite). This guide will only list methods and properties unique to the `TestModule`.\n:::\n\n## moduleId\n\nThis is usually an absolute unix file path (even on Windows). It can be a virtual id if the file is not on the disk. This value corresponds to Vite's `ModuleGraph` id.\n\n```ts\n'C:/Users/Documents/project/example.test.ts' // ✅\n'/Users/mac/project/example.test.ts' // ✅\n'C:\\\\Users\\\\Documents\\\\project\\\\example.test.ts' // ❌\n```\n\n## relativeModuleId\n\nModule id relative to the project. This is the same as `task.name` in the deprecated API.\n\n```ts\n'project/example.test.ts' // ✅\n'example.test.ts' // ✅\n'project\\\\example.test.ts' // ❌\n```\n\n## state\n\n```ts\nfunction state(): TestModuleState\n```\n\nWorks the same way as [`testSuite.state()`](/api/advanced/test-suite#state), but can also return `queued` if module wasn't executed yet.\n\n## meta <Version>3.1.0</Version> {#meta}\n\n```ts\nfunction meta(): TaskMeta\n```\n\nCustom [metadata](/api/advanced/metadata) that was attached to the module during its execution or collection. The meta can be attached by assigning a property to the `task.meta` object during a test run:\n\n```ts {5,10}\nimport { test } from 'vitest'\n\ndescribe('the validation works correctly', (task) => {\n  // assign \"decorated\" during collection\n  task.file.meta.decorated = false\n\n  test('some test', ({ task }) => {\n    // assign \"decorated\" during test run, it will be available\n    // only in onTestCaseReady hook\n    task.file.meta.decorated = false\n  })\n})\n```\n\n:::tip\nIf metadata was attached during collection (outside of the `test` function), then it will be available in [`onTestModuleCollected`](./reporters#ontestmodulecollected) hook in the custom reporter.\n:::\n\n## diagnostic\n\n```ts\nfunction diagnostic(): ModuleDiagnostic\n```\n\nUseful information about the module like duration, memory usage, etc. If the module was not executed yet, all diagnostic values will return `0`.\n\n```ts\ninterface ModuleDiagnostic {\n  /**\n   * The time it takes to import and initiate an environment.\n   */\n  readonly environmentSetupDuration: number\n  /**\n   * The time it takes Vitest to setup test harness (runner, mocks, etc.).\n   */\n  readonly prepareDuration: number\n  /**\n   * The time it takes to import the test module.\n   * This includes importing everything in the module and executing suite callbacks.\n   */\n  readonly collectDuration: number\n  /**\n   * The time it takes to import the setup module.\n   */\n  readonly setupDuration: number\n  /**\n   * Accumulated duration of all tests and hooks in the module.\n   */\n  readonly duration: number\n  /**\n   * The amount of memory used by the module in bytes.\n   * This value is only available if the test was executed with `logHeapUsage` flag.\n   */\n  readonly heap: number | undefined\n  /**\n   * The time spent importing every non-externalized dependency that Vitest has processed.\n   */\n  readonly importDurations: Record<string, ImportDuration>\n}\n\n/** The time spent importing & executing a non-externalized file. */\ninterface ImportDuration {\n  /** The time spent importing & executing the file itself, not counting all non-externalized imports that the file does. */\n  selfTime: number\n\n  /** The time spent importing & executing the file and all its imports. */\n  totalTime: number\n}\n```\n\n## viteEnvironment <Version>4.1.0</Version> {#viteenvironment}\n\nThis is a Vite's [`DevEnvironment`](https://vite.dev/guide/api-environment) that transforms all files inside of the test module.\n\n::: details History\n- `v4.0.15`: added as experimental\n:::\n\n## toTestSpecification <Version>4.1.0</Version> {#totestspecification}\n\n```ts\nfunction toTestSpecification(testCases?: TestCase[]): TestSpecification\n```\n\nReturns a new [test specification](/api/advanced/test-specification) that can be used to filter or run this specific test module.\n\nIt accepts an optional array of test cases that should be filtered.\n"
  },
  {
    "path": "docs/api/advanced/test-project.md",
    "content": "---\ntitle: TestProject\n---\n\n# TestProject <Version>3.0.0</Version> {#testproject}\n\n::: warning\nThis guide describes the advanced Node.js API. If you just want to define projects, follow the [\"Test Projects\"](/guide/projects) guide.\n:::\n\n## name\n\nThe name is a unique string assigned by the user or interpreted by Vitest. If user did not provide a name, Vitest tries to load a `package.json` in the root of the project and takes the `name` property from there. If there is no `package.json`, Vitest uses the name of the folder by default. Inline projects use numbers as the name (converted to string).\n\n::: code-group\n```ts [node.js]\nimport { createVitest } from 'vitest/node'\n\nconst vitest = await createVitest('test')\nvitest.projects.map(p => p.name) === [\n  '@pkg/server',\n  'utils',\n  '2',\n  'custom'\n]\n```\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      './packages/server', // has package.json with \"@pkg/server\"\n      './utils', // doesn't have a package.json file\n      {\n        // doesn't customize the name\n        test: {\n          pool: 'threads',\n        },\n      },\n      {\n        // customized the name\n        test: {\n          name: 'custom',\n        },\n      },\n    ],\n  },\n})\n```\n:::\n\n::: info\nIf the [root project](/api/advanced/vitest#getrootproject) is not part of user projects, its `name` will not be resolved.\n:::\n\n## vitest\n\n`vitest` references the global [`Vitest`](/api/advanced/vitest) process.\n\n## serializedConfig\n\nThis is the config that test processes receive. Vitest [serializes config](https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/node/config/serializeConfig.ts) manually by removing all functions and properties that are not possible to serialize. Since this value is available in both tests and node, its type is exported from the main entry point.\n\n```ts\nimport type { SerializedConfig } from 'vitest'\n\nconst config: SerializedConfig = vitest.projects[0].serializedConfig\n```\n\n::: warning\nThe `serializedConfig` property is a getter. Every time it's accessed Vitest serializes the config again in case it was changed. This also means that it always returns a different reference:\n\n```ts\nproject.serializedConfig === project.serializedConfig // ❌\n```\n:::\n\n## globalConfig\n\nThe test config that [`Vitest`](/api/advanced/vitest) was initialized with. If this is the [root project](/api/advanced/vitest#getrootproject), `globalConfig` and `config` will reference the same object. This config is useful for values that cannot be set on the project level, like `coverage` or `reporters`.\n\n```ts\nimport type { ResolvedConfig } from 'vitest/node'\n\nvitest.config === vitest.projects[0].globalConfig\n```\n\n## config\n\nThis is the project's resolved test config.\n\n## hash <Version>3.2.0</Version> {#hash}\n\nThe unique hash of this project. This value is consistent between the reruns.\n\nIt is based on the root of the project and its name. Note that the root path is not consistent between different OS, so the hash will also be different.\n\n## vite\n\nThis is project's [`ViteDevServer`](https://vite.dev/guide/api-javascript#vitedevserver). All projects have their own Vite servers.\n\n## browser\n\nThis value will be set only if tests are running in the browser. If `browser` is enabled, but tests didn't run yet, this will be `undefined`. If you need to check if the project supports browser tests, use `project.isBrowserEnabled()` method.\n\n::: warning\nThe browser API is even more experimental and doesn't follow SemVer. The browser API will be standardized separately from the rest of the APIs.\n:::\n\n## provide\n\n```ts\nfunction provide<T extends keyof ProvidedContext & string>(\n  key: T,\n  value: ProvidedContext[T],\n): void\n```\n\nA way to provide custom values to tests in addition to [`config.provide`](/config/provide) field. All values are validated with [`structuredClone`](https://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone) before they are stored, but the values on `providedContext` themselves are not cloned.\n\n::: code-group\n```ts [node.js]\nimport { createVitest } from 'vitest/node'\n\nconst vitest = await createVitest('test')\nconst project = vitest.projects.find(p => p.name === 'custom')\nproject.provide('key', 'value')\nawait vitest.start()\n```\n```ts [test.spec.js]\nimport { inject } from 'vitest'\nconst value = inject('key')\n```\n:::\n\nThe values can be provided dynamically. Provided value in tests will be updated on their next run.\n\n::: tip\nThis method is also available to [global setup files](/config/globalsetup) for cases where you cannot use the public API:\n\n```js\nexport default function setup({ provide }) {\n  provide('wsPort', 3000)\n}\n```\n:::\n\n## getProvidedContext\n\n```ts\nfunction getProvidedContext(): ProvidedContext\n```\n\nThis returns the context object. Every project also inherits the global context set by `vitest.provide`.\n\n```ts\nimport { createVitest } from 'vitest/node'\n\nconst vitest = await createVitest('test')\nvitest.provide('global', true)\nconst project = vitest.projects.find(p => p.name === 'custom')\nproject.provide('key', 'value')\n\n// { global: true, key: 'value' }\nconst context = project.getProvidedContext()\n```\n\n::: tip\nProject context values will always override root project's context.\n:::\n\n## createSpecification\n\n```ts\nfunction createSpecification(\n  moduleId: string,\n  locations?: number[],\n): TestSpecification\n```\n\nCreate a [test specification](/api/advanced/test-specification) that can be used in [`vitest.runTestSpecifications`](/api/advanced/vitest#runtestspecifications). Specification scopes the test file to a specific `project` and test `locations` (optional). Test [locations](/api/advanced/test-case#location) are code lines where the test is defined in the source code. If locations are provided, Vitest will only run tests defined on those lines. Note that if [`testNamePattern`](/config/testnamepattern) is defined, then it will also be applied.\n\n```ts\nimport { createVitest } from 'vitest/node'\nimport { resolve } from 'node:path/posix'\n\nconst vitest = await createVitest('test')\nconst project = vitest.projects[0]\nconst specification = project.createSpecification(\n  resolve('./example.test.ts'),\n  [20, 40], // optional test lines\n)\nawait vitest.runTestSpecifications([specification])\n```\n\n::: warning\n`createSpecification` expects resolved [module ID](/api/advanced/test-specification#moduleid). It doesn't auto-resolve the file or check that it exists on the file system.\n\nAlso note that `project.createSpecification` always returns a new instance.\n:::\n\n## isRootProject\n\n```ts\nfunction isRootProject(): boolean\n```\n\nChecks if the current project is the root project. You can also get the root project by calling [`vitest.getRootProject()`](/api/advanced/vitest#getrootproject).\n\n## globTestFiles\n\n```ts\nfunction globTestFiles(filters?: string[]): {\n  /**\n   * Test files that match the filters.\n   */\n  testFiles: string[]\n  /**\n   * Typecheck test files that match the filters. This will be empty unless `typecheck.enabled` is `true`.\n   */\n  typecheckTestFiles: string[]\n}\n```\n\nGlobs all test files. This function returns an object with regular tests and typecheck tests.\n\nThis method accepts `filters`. Filters can only a part of the file path, unlike in other methods on the [`Vitest`](/api/advanced/vitest) instance:\n\n```js\nproject.globTestFiles(['foo']) // ✅\nproject.globTestFiles(['basic/foo.js:10']) // ❌\n```\n\n::: tip\nVitest uses [fast-glob](https://npmx.dev/package/fast-glob) to find test files. `test.dir`, `test.root`, `root` or `process.cwd()` define the `cwd` option.\n\nThis method looks at several config options:\n\n- `test.include`, `test.exclude` to find regular test files\n- `test.includeSource`, `test.exclude` to find in-source tests\n- `test.typecheck.include`, `test.typecheck.exclude` to find typecheck tests\n:::\n\n## matchesTestGlob\n\n```ts\nfunction matchesTestGlob(\n  moduleId: string,\n  source?: () => string\n): boolean\n```\n\nThis method checks if the file is a regular test file. It uses the same config properties that `globTestFiles` uses for validation.\n\nThis method also accepts a second parameter, which is the source code. This is used to validate if the file is an in-source test. If you are calling this method several times for several projects it is recommended to read the file once and pass it down directly. If the file is not a test file, but matches the `includeSource` glob, Vitest will synchronously read the file unless the `source` is provided.\n\n```ts\nimport { createVitest } from 'vitest/node'\nimport { resolve } from 'node:path/posix'\n\nconst vitest = await createVitest('test')\nconst project = vitest.projects[0]\n\nproject.matchesTestGlob(resolve('./basic.test.ts')) // true\nproject.matchesTestGlob(resolve('./basic.ts')) // false\nproject.matchesTestGlob(resolve('./basic.ts'), () => `\nif (import.meta.vitest) {\n  // ...\n}\n`) // true if `includeSource` is set\n```\n\n## import\n\n<!--@include: ./import-example.md-->\n\nImport a file using Vite module runner. The file will be transformed by Vite with provided project's config and executed in a separate context. Note that `moduleId` will be relative to the `config.root`.\n\n::: danger\n`project.import` reuses Vite's module graph, so importing the same module using a regular import will return a different module:\n\n```ts\nimport * as staticExample from './example.js'\nconst dynamicExample = await project.import('./example.js')\n\ndynamicExample !== staticExample // ✅\n```\n:::\n\n::: info\nInternally, Vitest uses this method to import global setups, custom coverage providers and custom reporters, meaning all of them share the same module graph as long as they belong to the same Vite server.\n:::\n\n## onTestsRerun\n\n```ts\nfunction onTestsRerun(cb: OnTestsRerunHandler): void\n```\n\nThis is a shorthand for [`project.vitest.onTestsRerun`](/api/advanced/vitest#ontestsrerun). It accepts a callback that will be awaited when the tests have been scheduled to rerun (usually, due to a file change).\n\n```ts\nproject.onTestsRerun((specs) => {\n  console.log(specs)\n})\n```\n\n## isBrowserEnabled\n\n```ts\nfunction isBrowserEnabled(): boolean\n```\n\nReturns `true` if this project runs tests in the browser.\n\n## close\n\n```ts\nfunction close(): Promise<void>\n```\n\nCloses the project and all associated resources. This can only be called once; the closing promise is cached until the server restarts. If the resources are needed again, create a new project.\n\nIn detail, this method closes the Vite server, stops the typechecker service, closes the browser if it's running, deletes the temporary directory that holds the source code, and resets the provided context.\n"
  },
  {
    "path": "docs/api/advanced/test-specification.md",
    "content": "# TestSpecification\n\nThe `TestSpecification` class describes what module to run as a test and its parameters.\n\nYou can only create a specification by calling [`createSpecification`](/api/advanced/test-project#createspecification) method on a test project:\n\n```ts\nconst specification = project.createSpecification(\n  resolve('./example.test.ts'),\n  {\n    testLines: [20, 40],\n    testNamePattern: /hello world/,\n    testIds: ['1223128da3_0_0_0', '1223128da3_0_0'],\n    testTagsFilter: ['frontend and backend'],\n  } // optional test filters\n)\n```\n\n`createSpecification` expects resolved module identifier. It doesn't auto-resolve the file or check that it exists on the file system.\n\n## taskId\n\n[Test module's](/api/advanced/test-suite#id) identifier.\n\n## project\n\nThis references the [`TestProject`](/api/advanced/test-project) that the test module belongs to.\n\n## moduleId\n\nThe ID of the module in Vite's module graph. Usually, it's an absolute file path using posix separator:\n\n```ts\n'C:/Users/Documents/project/example.test.ts' // ✅\n'/Users/mac/project/example.test.ts' // ✅\n'C:\\\\Users\\\\Documents\\\\project\\\\example.test.ts' // ❌\n```\n\n## testModule\n\nInstance of [`TestModule`](/api/advanced/test-module) associated with the specification. If test wasn't queued yet, this will be `undefined`.\n\n## pool {#pool}\n\nThe [`pool`](/config/pool) in which the test module will run.\n\n::: danger\nIt's possible to have multiple pools in a single test project with [`typecheck.enabled`](/config/typecheck#typecheck-enabled). This means it's possible to have several specifications with the same `moduleId` but different `pool`. In later versions, the project will only support a single pool.\n:::\n\n## testLines\n\nThis is an array of lines in the source code where the test files are defined. This field is defined only if the `createSpecification` method received an array.\n\nNote that if there is no test on at least one of the lines, the whole suite will fail. An example of a correct `testLines` configuration:\n\n::: code-group\n```ts [script.js]\nconst specification = project.createSpecification(\n  resolve('./example.test.ts'),\n  [3, 8, 9],\n)\n```\n```ts:line-numbers{3,8,9} [example.test.js]\nimport { test, describe } from 'vitest'\n\ntest('verification works')\n\ndescribe('a group of tests', () => { // [!code error]\n  // ...\n\n  test('nested test')\n  test.skip('skipped test')\n})\n```\n:::\n\n## testNamePattern <Version>4.1.0</Version> {#testnamepattern}\n\nA regexp that matches the name of the test in this module. This value will override the global [`testNamePattern`](/config/testnamepattern) option if it's set.\n\n## testIds <Version>4.1.0</Version> {#testids}\n\nThe ids of tasks inside of this specification to run.\n\n## testTagsFilter <Version>4.1.0</Version> {#testtagsfilter}\n\nThe [tags filter](/guide/test-tags#syntax) that a test must pass in order to be included in the run. Multiple filters are treated as `AND`.\n\n## toJSON\n\n```ts\nfunction toJSON(): SerializedTestSpecification\n```\n\n`toJSON` generates a JSON-friendly object that can be consumed by the [Browser Mode](/guide/browser/) or [Vitest UI](/guide/ui).\n"
  },
  {
    "path": "docs/api/advanced/test-suite.md",
    "content": "# TestSuite\n\nThe `TestSuite` class represents a single suite. This class is only available in the main thread. Refer to the [\"Runner API\"](/api/advanced/runner#tasks) if you are working with runtime tasks.\n\nThe `TestSuite` instance always has a `type` property with the value of `suite`. You can use it to distinguish between different task types:\n\n```ts\nif (task.type === 'suite') {\n  task // TestSuite\n}\n```\n\n## project\n\nThis references the [`TestProject`](/api/advanced/test-project) that the test belongs to.\n\n## module\n\nThis is a direct reference to the [`TestModule`](/api/advanced/test-module) where the test is defined.\n\n## name\n\nThis is a suite name that was passed to the `describe` function.\n\n```ts\nimport { describe } from 'vitest'\n\n// [!code word:'the validation logic']\ndescribe('the validation logic', () => {\n  // ...\n})\n```\n\n## fullName\n\nThe name of the suite including all parent suites separated with `>` symbol. This suite has a full name \"the validation logic > validating cities\":\n\n```ts\nimport { describe, test } from 'vitest'\n\n// [!code word:'the validation logic']\n// [!code word:'validating cities']\ndescribe('the validation logic', () => {\n  describe('validating cities', () => {\n    // ...\n  })\n})\n```\n\n## id\n\nThis is suite's unique identifier. This ID is deterministic and will be the same for the same suite across multiple runs. The ID is based on the [project](/api/advanced/test-project) name, module ID and suite order.\n\nThe ID looks like this:\n\n```\n1223128da3_0_0_0\n^^^^^^^^^^ the file hash\n           ^ suite index\n             ^ nested suite index\n               ^ test index\n```\n\n::: tip\nYou can generate file hash with `generateFileHash` function from `vitest/node` which is available since Vitest 3:\n\n```ts\nimport { generateFileHash } from 'vitest/node'\n\nconst hash = generateFileHash(\n  '/file/path.js', // relative path\n  undefined, // the project name or `undefined` is not set\n)\n```\n:::\n\n::: danger\nDon't try to parse the ID. It can have a minus at the start: `-1223128da3_0_0_0`.\n:::\n\n## location\n\nThe location in the module where the suite was defined. Locations are collected only if [`includeTaskLocation`](/config/includetasklocation) is enabled in the config. Note that this option is automatically enabled if `--reporter=html`, `--ui` or `--browser` flags are used.\n\nThe location of this suite will be equal to `{ line: 3, column: 1 }`:\n\n```ts:line-numbers {3}\nimport { describe } from 'vitest'\n\ndescribe('the validation works correctly', () => {\n  // ...\n})\n```\n\n## parent\n\nParent suite. If the suite was called directly inside the [module](/api/advanced/test-module), the parent will be the module itself.\n\n## options\n\n```ts\ninterface TaskOptions {\n  readonly each: boolean | undefined\n  readonly fails: boolean | undefined\n  readonly concurrent: boolean | undefined\n  readonly shuffle: boolean | undefined\n  readonly retry: number | undefined\n  readonly repeats: number | undefined\n  readonly tags: string[] | undefined\n  readonly mode: 'run' | 'only' | 'skip' | 'todo'\n}\n```\n\nThe options that suite was collected with.\n\n## children\n\nThis is a [collection](/api/advanced/test-collection) of all suites and tests inside the current suite.\n\n```ts\nfor (const task of suite.children) {\n  if (task.type === 'test') {\n    console.log('test', task.fullName)\n  }\n  else {\n    // task is TaskSuite\n    console.log('suite', task.name)\n  }\n}\n```\n\n::: warning\nNote that `suite.children` will only iterate the first level of nesting, it won't go deeper. If you need to iterate over all tests or suites, use [`children.allTests()`](/api/advanced/test-collection#alltests) or [`children.allSuites()`](/api/advanced/test-collection#allsuites). If you need to iterate over everything, use recursive function:\n\n```ts\nfunction visit(collection: TestCollection) {\n  for (const task of collection) {\n    if (task.type === 'suite') {\n      // report a suite\n      visit(task.children)\n    }\n    else {\n      // report a test\n    }\n  }\n}\n```\n:::\n\n## ok\n\n```ts\nfunction ok(): boolean\n```\n\nChecks if the suite has any failed tests. This will also return `false` if suite failed during collection. In that case, check the [`errors()`](#errors) for thrown errors.\n\n## state\n\n```ts\nfunction state(): TestSuiteState\n```\n\nChecks the running state of the suite. Possible return values:\n\n- **pending**: the tests in this suite did not finish running yet.\n- **failed**: this suite has failed tests or they couldn't be collected. If [`errors()`](#errors) is not empty, it means the suite failed to collect tests.\n- **passed**: every test inside this suite has passed.\n- **skipped**: this suite was skipped during collection.\n\n::: warning\nNote that [test module](/api/advanced/test-module) also has a `state` method that returns the same values, but it can also return an additional `queued` state if the module wasn't executed yet.\n:::\n\n## errors\n\n```ts\nfunction errors(): TestError[]\n```\n\nErrors that happened outside of the test run during collection, like syntax errors.\n\n```ts {4}\nimport { describe } from 'vitest'\n\ndescribe('collection failed', () => {\n  throw new Error('a custom error')\n})\n```\n\n::: warning\nNote that errors are serialized into simple objects: `instanceof Error` will always return `false`.\n:::\n\n## meta <Version>3.1.0</Version> {#meta}\n\n```ts\nfunction meta(): TaskMeta\n```\n\nCustom [metadata](/api/advanced/metadata) that was attached to the suite during its execution or collection. Since Vitest 4.1, the meta can be attached by providing a `meta` object during test collection:\n\n```ts {7,10}\nimport { describe, test, TestRunner } from 'vitest'\n\ndescribe('the validation works correctly', { meta: { decorated: true } }, () => {\n  test('some test', ({ task }) => {\n    // assign \"decorated\" during test run, it will be available\n    // only in onTestCaseReady hook\n    task.suite.meta.decorated = false\n\n    // tests inherit suite's metadata\n    task.meta.decorated === true\n  })\n})\n```\n\nNote that suite metadata will be inherited by tests since Vitest 4.1.\n\n:::tip\nIf metadata was attached during collection (outside of the `test` function), then it will be available in [`onTestModuleCollected`](./reporters#ontestmodulecollected) hook in the custom reporter.\n:::\n\n## toTestSpecification <Version>4.1.0</Version> {#totestspecification}\n\n```ts\nfunction toTestSpecification(): TestSpecification\n```\n\nReturns a new [test specification](/api/advanced/test-specification) that can be used to filter or run this specific test suite.\n"
  },
  {
    "path": "docs/api/advanced/vitest.md",
    "content": "---\noutline: deep\ntitle: Vitest API\n---\n\n# Vitest\n\nVitest instance requires the current test mode. It can be either:\n\n- `test` when running runtime tests\n- `benchmark` when running benchmarks <Badge type=\"warning\">experimental</Badge>\n\n::: details New in Vitest 4\nVitest 4 added several new APIs (they are marked with a \"4.0.0+\" badge) and removed deprecated APIs:\n\n- `invalidates`\n- `changedTests` (use [`onFilterWatchedSpecification`](#onfilterwatchedspecification) instead)\n- `server` (use [`vite`](#vite) instead)\n- `getProjectsByTestFile` (use [`getModuleSpecifications`](#getmodulespecifications) instead)\n- `getFileWorkspaceSpecs` (use [`getModuleSpecifications`](#getmodulespecifications) instead)\n- `getModuleProjects` (filter by [`this.projects`](#projects) yourself)\n- `updateLastChanged` (renamed to [`invalidateFile`](#invalidatefile))\n- `globTestSpecs` (use [`globTestSpecifications`](#globtestspecifications) instead)\n- `globTestFiles` (use [`globTestSpecifications`](#globtestspecifications) instead)\n- `listFile` (use [`getRelevantTestSpecifications`](#getrelevanttestspecifications) instead)\n:::\n\n## mode\n\n### test\n\nTest mode will only call functions inside `test` or `it`, and throws an error when `bench` is encountered. This mode uses `include` and `exclude` options in the config to find test files.\n\n### benchmark <Badge type=\"warning\">experimental</Badge>\n\nBenchmark mode calls `bench` functions and throws an error, when it encounters `test` or `it`. This mode uses `benchmark.include` and `benchmark.exclude` options in the config to find benchmark files.\n\n## config\n\nThe root (or global) config. If projects are defined, they will reference this as `globalConfig`.\n\n::: warning\nThis is Vitest config, it doesn't extend _Vite_ config. It only has resolved values from the `test` property.\n:::\n\n## vite\n\nThis is a global [`ViteDevServer`](https://vite.dev/guide/api-javascript#vitedevserver).\n\n## state <Badge type=\"warning\">experimental</Badge>\n\n::: warning\nPublic `state` is an experimental API (except `vitest.state.getReportedEntity`). Breaking changes might not follow SemVer, please pin Vitest's version when using it.\n:::\n\nGlobal state stores information about the current tests. It uses the same API from `@vitest/runner` by default, but we recommend using the [Reported Tasks API](/api/advanced/reporters#reported-tasks) instead by calling `state.getReportedEntity()` on the `@vitest/runner` API:\n\n```ts\nconst task = vitest.state.idMap.get(taskId) // old API\nconst testCase = vitest.state.getReportedEntity(task) // new API\n```\n\nIn the future, the old API won't be exposed anymore.\n\n## snapshot\n\nThe global snapshot manager. Vitest keeps track of all snapshots using the `snapshot.add` method.\n\nYou can get the latest summary of snapshots via the `vitest.snapshot.summary` property.\n\n## cache\n\nCache manager that stores information about latest test results and test file stats. In Vitest itself this is only used by the default sequencer to sort tests.\n\n## watcher <Version>4.0.0</Version> {#watcher}\n\nThe instance of a Vitest watcher with useful methods to track file changes and rerun tests. You can use `onFileChange`, `onFileDelete` or `onFileCreate` with your own watcher, if the built-in watcher is disabled.\n\n## projects\n\nAn array of [test projects](/api/advanced/test-project) that belong to user's projects. If the user did not specify a them, this array will only contain a [root project](#getrootproject).\n\nVitest will ensure that there is always at least one project in this array. If the user specifies a non-existent `--project` name, Vitest will throw an error before this array is defined.\n\n## getRootProject\n\n```ts\nfunction getRootProject(): TestProject\n```\n\nThis returns the root test project. The root project generally doesn't run any tests and is not included in `vitest.projects` unless the user explicitly includes the root config in their configuration, or projects are not defined at all.\n\nThe primary goal of the root project is to setup the global config. In fact, `rootProject.config` references `rootProject.globalConfig` and `vitest.config` directly:\n\n```ts\nrootProject.config === rootProject.globalConfig === rootProject.vitest.config\n```\n\n## provide\n\n```ts\nfunction provide<T extends keyof ProvidedContext & string>(\n  key: T,\n  value: ProvidedContext[T],\n): void\n```\n\nVitest exposes `provide` method which is a shorthand for `vitest.getRootProject().provide`. With this method you can pass down values from the main thread to tests. All values are checked with `structuredClone` before they are stored, but the values themselves are not cloned.\n\nTo receive the values in the test, you need to import `inject` method from `vitest` entrypoint:\n\n```ts\nimport { inject } from 'vitest'\nconst port = inject('wsPort') // 3000\n```\n\nFor better type safety, we encourage you to augment the type of `ProvidedContext`:\n\n```ts\nimport { createVitest } from 'vitest/node'\n\nconst vitest = await createVitest('test', {\n  watch: false,\n})\nvitest.provide('wsPort', 3000)\n\ndeclare module 'vitest' {\n  export interface ProvidedContext {\n    wsPort: number\n  }\n}\n```\n\n::: warning\nTechnically, `provide` is a method of [`TestProject`](/api/advanced/test-project), so it is limited to the specific project. However, all projects inherit the values from the root project which makes `vitest.provide` universal way of passing down values to tests.\n:::\n\n## getProvidedContext\n\n```ts\nfunction getProvidedContext(): ProvidedContext\n```\n\nThis returns the root context object. This is a shorthand for `vitest.getRootProject().getProvidedContext`.\n\n## getProjectByName\n\n```ts\nfunction getProjectByName(name: string): TestProject\n```\n\nThis method returns the project by its name. Similar to calling `vitest.projects.find`.\n\n::: warning\nIn case the project doesn't exist, this method will return the root project - make sure to check the names again if the project you are looking for is the one returned.\n\nIf user didn't customize a name, the Vitest will assign an empty string as a name.\n:::\n\n## globTestSpecifications\n\n```ts\nfunction globTestSpecifications(\n  filters?: string[],\n): Promise<TestSpecification[]>\n```\n\nThis method constructs new [test specifications](/api/advanced/test-specification) by collecting every test in all projects with [`project.globTestFiles`](/api/advanced/test-project#globtestfiles). It accepts string filters to match the test files - these are the same filters that [CLI supports](/guide/filtering#cli).\n\nThis method automatically caches all test specifications. When you call [`getModuleSpecifications`](#getmodulespecifications) next time, it will return the same specifications unless [`clearSpecificationsCache`](#clearspecificationscache) was called before that.\n\n::: warning\nAs of Vitest 3, it's possible to have multiple test specifications with the same module ID (file path) if `poolMatchGlob` has several pools or if `typecheck` is enabled. This possibility will be removed in Vitest 4.\n:::\n\n```ts\nconst specifications = await vitest.globTestSpecifications(['my-filter'])\n// [TestSpecification{ moduleId: '/tests/my-filter.test.ts' }]\nconsole.log(specifications)\n```\n\n## getRelevantTestSpecifications\n\n```ts\nfunction getRelevantTestSpecifications(\n  filters?: string[]\n): Promise<TestSpecification[]>\n```\n\nThis method resolves every test specification by calling [`project.globTestFiles`](/api/advanced/test-project#globtestfiles). It accepts string filters to match the test files - these are the same filters that [CLI supports](/guide/filtering#cli). If `--changed` flag was specified, the list will be filtered to include only files that changed. `getRelevantTestSpecifications` doesn't run any test files.\n\n::: warning\nThis method can be slow because it needs to filter `--changed` flags. Do not use it if you just need a list of test files.\n\n- If you need to get the list of specifications for known test files, use [`getModuleSpecifications`](#getmodulespecifications) instead.\n- If you need to get the list of all possible test files, use [`globTestSpecifications`](#globtestspecifications).\n:::\n\n## mergeReports\n\n```ts\nfunction mergeReports(directory?: string): Promise<TestRunResult>\n```\n\nMerge reports from multiple runs located in the specified directory (value from `--merge-reports` if not specified). This value can also be set on `config.mergeReports` (by default, it will read `.vitest-reports` folder).\n\nNote that the `directory` will always be resolved relative to the working directory.\n\nThis method is called automatically by [`startVitest`](/guide/advanced/tests) if `config.mergeReports` is set.\n\n## collect\n\n```ts\nfunction collect(filters?: string[]): Promise<TestRunResult>\n```\n\nExecute test files without running test callbacks. `collect` returns unhandled errors and an array of [test modules](/api/advanced/test-module). It accepts string filters to match the test files - these are the same filters that [CLI supports](/guide/filtering#cli).\n\nThis method resolves tests specifications based on the config `include`, `exclude`, and `includeSource` values. Read more at [`project.globTestFiles`](/api/advanced/test-project#globtestfiles). If `--changed` flag was specified, the list will be filtered to include only files that changed.\n\n::: warning\nNote that Vitest doesn't use static analysis to collect tests. Vitest will run every test file in isolation, just like it runs regular tests.\n\nThis makes this method very slow, unless you disable isolation before collecting tests.\n:::\n\n## start\n\n```ts\nfunction start(filters?: string[]): Promise<TestRunResult>\n```\n\nInitialize reporters, the coverage provider, and run tests. This method accepts string filters to match the test files - these are the same filters that [CLI supports](/guide/filtering#cli).\n\n::: warning\nThis method should not be called if [`vitest.init()`](#init) is also invoked. Use [`runTestSpecifications`](#runtestspecifications) or [`rerunTestSpecifications`](#reruntestspecifications) instead if you need to run tests after Vitest was initialised.\n:::\n\nThis method is called automatically by [`startVitest`](/guide/advanced/tests) if `config.mergeReports` and `config.standalone` are not set.\n\n## init\n\n```ts\nfunction init(): Promise<void>\n```\n\nInitialize reporters and the coverage provider. This method doesn't run any tests. If the `--watch` flag is provided, Vitest will still run changed tests even if this method was not called.\n\nInternally, this method is called only if [`--standalone`](/guide/cli#standalone) flag is enabled.\n\n::: warning\nThis method should not be called if [`vitest.start()`](#start) is also invoked.\n:::\n\nThis method is called automatically by [`startVitest`](/guide/advanced/tests) if `config.standalone` is set.\n\n## getModuleSpecifications\n\n```ts\nfunction getModuleSpecifications(moduleId: string): TestSpecification[]\n```\n\nReturns a list of test specifications related to the module ID. The ID should already be resolved to an absolute file path. If ID doesn't match `include` or `includeSource` patterns, the returned array will be empty.\n\nThis method can return already cached specifications based on the `moduleId` and `pool`. But note that [`project.createSpecification`](/api/advanced/test-project#createspecification) always returns a new instance and it's not cached automatically. However, specifications are automatically cached when [`runTestSpecifications`](#runtestspecifications) is called.\n\n::: warning\nAs of Vitest 3, this method uses a cache to check if the file is a test. To make sure that the cache is not empty, call [`globTestSpecifications`](#globtestspecifications) at least once.\n:::\n\n## clearSpecificationsCache\n\n```ts\nfunction clearSpecificationsCache(moduleId?: string): void\n```\n\nVitest automatically caches test specifications for each file when [`globTestSpecifications`](#globtestspecifications) or [`runTestSpecifications`](#runtestspecifications) is called. This method clears the cache for the given file or the whole cache altogether depending on the first argument.\n\n## runTestSpecifications\n\n```ts\nfunction runTestSpecifications(\n  specifications: TestSpecification[],\n  allTestsRun = false\n): Promise<TestRunResult>\n```\n\nThis method runs every test based on the received [specifications](/api/advanced/test-specification). The second argument, `allTestsRun`, is used by the coverage provider to determine if it needs to include uncovered files in report.\n\n::: warning\nThis method doesn't trigger `onWatcherRerun`, `onWatcherStart` and `onTestsRerun` callbacks. If you are rerunning tests based on the file change, consider using [`rerunTestSpecifications`](#reruntestspecifications) instead.\n:::\n\n## rerunTestSpecifications\n\n```ts\nfunction rerunTestSpecifications(\n  specifications: TestSpecification[],\n  allTestsRun = false\n): Promise<TestRunResult>\n```\n\nThis method emits `reporter.onWatcherRerun` and `onTestsRerun` events, then it runs tests with [`runTestSpecifications`](#runtestspecifications). If there were no errors in the main process, it will emit `reporter.onWatcherStart` event.\n\n## runTestFiles <Version>4.1.0</Version> {#runtestfiles}\n\n```ts\nfunction runTestFiles(\n  filepaths: string[],\n  allTestsRun = false\n): Promise<TestRunResult>\n```\n\nThis automatically creates specifications to run based on filepaths filters.\n\nThis is different from [`start`](#start) because it does not create a coverage provider, trigger `onInit` and `onWatcherStart` events, or throw an error if there are no files to run (in this case, the function will return empty arrays without triggering a test run).\n\nThis function accepts the same filters as [`start`](#start) and the CLI.\n\n## updateSnapshot\n\n```ts\nfunction updateSnapshot(files?: string[]): Promise<TestRunResult>\n```\n\nUpdate snapshots in specified files. If no files are provided, it will update files with failed tests and obsolete snapshots.\n\n## collectTests\n\n```ts\nfunction collectTests(\n  specifications: TestSpecification[]\n): Promise<TestRunResult>\n```\n\nExecute test files without running test callbacks. `collectTests` returns unhandled errors and an array of [test modules](/api/advanced/test-module).\n\nThis method works exactly the same as [`collect`](#collect), but you need to provide test specifications yourself.\n\n::: warning\nNote that Vitest doesn't use static analysis to collect tests. Vitest will run every test file in isolation, just like it runs regular tests.\n\nThis makes this method very slow, unless you disable isolation before collecting tests.\n:::\n\n## cancelCurrentRun\n\n```ts\nfunction cancelCurrentRun(reason: CancelReason): Promise<void>\n```\n\nThis method will gracefully cancel all ongoing tests. It will stop the on-going tests and will not run tests that were scheduled to run but haven't started yet.\n\n## setGlobalTestNamePattern\n\n```ts\nfunction setGlobalTestNamePattern(pattern: string | RegExp): void\n```\n\nThis methods overrides the global [test name pattern](/config/testnamepattern).\n\n::: warning\nThis method doesn't start running any tests. To run tests with updated pattern, call [`runTestSpecifications`](#runtestspecifications).\n:::\n\n## getGlobalTestNamePattern <Version>4.0.0</Version> {#getglobaltestnamepattern}\n\n```ts\nfunction getGlobalTestNamePattern(): RegExp | undefined\n```\n\nReturns the regexp used for the global test name pattern.\n\n## resetGlobalTestNamePattern\n\n```ts\nfunction resetGlobalTestNamePattern(): void\n```\n\nThis methods resets the [test name pattern](/config/testnamepattern). It means Vitest won't skip any tests now.\n\n::: warning\nThis method doesn't start running any tests. To run tests without a pattern, call [`runTestSpecifications`](#runtestspecifications).\n:::\n\n## enableSnapshotUpdate\n\n```ts\nfunction enableSnapshotUpdate(): void\n```\n\nEnable the mode that allows updating snapshots when running tests. Every test that runs after this method is called will update snapshots. To disable the mode, call [`resetSnapshotUpdate`](#resetsnapshotupdate).\n\n::: warning\nThis method doesn't start running any tests. To update snapshots, run tests with [`runTestSpecifications`](#runtestspecifications).\n:::\n\n## resetSnapshotUpdate\n\n```ts\nfunction resetSnapshotUpdate(): void\n```\n\nDisable the mode that allows updating snapshots when running tests. This method doesn't start running any tests.\n\n## invalidateFile\n\n```ts\nfunction invalidateFile(filepath: string): void\n```\n\nThis method invalidates the file in the cache of every project. It is mostly useful if you rely on your own watcher because Vite's cache persist in memory.\n\n::: danger\nIf you disable Vitest's watcher but keep Vitest running, it is important to manually clear the cache with this method because there is no way to disable the cache. This method will also invalidate file's importers.\n:::\n\n## import\n\n<!--@include: ./import-example.md-->\n\nImport a file using Vite module runner. The file will be transformed by Vite with the global config and executed in a separate context. Note that `moduleId` will be relative to the `config.root`.\n\n::: danger\n`project.import` reuses Vite's module graph, so importing the same module using a regular import will return a different module:\n\n```ts\nimport * as staticExample from './example.js'\nconst dynamicExample = await vitest.import('./example.js')\n\ndynamicExample !== staticExample // ✅\n```\n:::\n\n::: info\nInternally, Vitest uses this method to import global setups, custom coverage providers, and custom reporters, meaning all of them share the same module graph as long as they belong to the same Vite server.\n:::\n\n## close\n\n```ts\nfunction close(): Promise<void>\n```\n\nCloses all projects and their associated resources. This can only be called once; the closing promise is cached until the server restarts.\n\n## exit\n\n```ts\nfunction exit(force = false): Promise<void>\n```\n\nCloses all projects and exit the process. If `force` is set to `true`, the process will exit immediately after closing the projects.\n\nThis method will also forcefully call `process.exit()` if the process is still active after [`config.teardownTimeout`](/config/teardowntimeout) milliseconds.\n\n## shouldKeepServer\n\n```ts\nfunction shouldKeepServer(): boolean\n```\n\nThis method will return `true` if the server should be kept running after the tests are done. This usually means that the `watch` mode was enabled.\n\n## onServerRestart\n\n```ts\nfunction onServerRestart(fn: OnServerRestartHandler): void\n```\n\nRegister a handler that will be called when the server is restarted due to a config change.\n\n## onCancel\n\n```ts\nfunction onCancel(fn: (reason: CancelReason) => Awaitable<void>): () => void\n```\n\nRegister a handler that will be called when the test run is cancelled with [`vitest.cancelCurrentRun`](#cancelcurrentrun).\n\nSince 4.0.10, `onCancel` experimentally returns a teardown function that will remove the listener. Since 4.1.0 this behaviour is considered stable.\n\n## onClose\n\n```ts\nfunction onClose(fn: () => Awaitable<void>): void\n```\n\nRegister a handler that will be called when the server is closed.\n\n## onTestsRerun\n\n```ts\nfunction onTestsRerun(fn: OnTestsRerunHandler): void\n```\n\nRegister a handler that will be called when the tests are rerunning. The tests can rerun when [`rerunTestSpecifications`](#reruntestspecifications) is called manually or when a file is changed and the built-in watcher schedules a rerun.\n\n## onFilterWatchedSpecification\n\n```ts\nfunction onFilterWatchedSpecification(\n  fn: (specification: TestSpecification) => boolean\n): void\n```\nRegister a handler that will be called when a file is changed. This callback should return `true` or `false`, indicating whether the test file needs to be rerun.\n\nWith this method, you can hook into the default watcher logic to delay or discard tests that the user doesn't want to keep track of at the moment:\n\n```ts\nconst continuesTests: string[] = []\n\nmyCustomWrapper.onContinuesRunEnabled(testItem =>\n  continuesTests.push(item.fsPath)\n)\n\nvitest.onFilterWatchedSpecification(specification =>\n  continuesTests.includes(specification.moduleId)\n)\n```\n\nVitest can create different specifications for the same file depending on the `pool` or `locations` options, so do not rely on the reference. Vitest can also return cached specification from [`vitest.getModuleSpecifications`](#getmodulespecifications) - the cache is based on the `moduleId` and `pool`. Note that [`project.createSpecification`](/api/advanced/test-project#createspecification) always returns a new instance.\n\n## matchesProjectFilter <Version>3.1.0</Version> {#matchesprojectfilter}\n\n```ts\nfunction matchesProjectFilter(name: string): boolean\n```\n\nCheck if the name matches the current [project filter](/guide/cli#project). If there is no project filter, this will always return `true`.\n\nIt is not possible to programmatically change the `--project` CLI option.\n\n## waitForTestRunEnd <Version>4.0.0</Version> {#waitfortestrunend}\n\n```ts\nfunction waitForTestRunEnd(): Promise<void>\n```\n\nIf there is a test run happening, returns a promise that will resolve when the test run is finished.\n\n## createCoverageProvider <Version>4.0.0</Version> {#createcoverageprovider}\n\n```ts\nfunction createCoverageProvider(): Promise<CoverageProvider | null>\n```\n\nCreates a coverage provider if `coverage` is enabled in the config. This is done automatically if you are running tests with [`start`](#start) or [`init`](#init) methods.\n\n::: warning\nThis method will also clean all previous reports if [`coverage.clean`](/config/coverage#coverage-clean) is not set to `false`.\n:::\n\n## enableCoverage <Version>4.0.0</Version> {#enablecoverage}\n\n```ts\nfunction enableCoverage(): Promise<void>\n```\n\nThis method enables coverage for tests that run after this call. `enableCoverage` doesn't run any tests; it only sets up Vitest to collect coverage.\n\nIt creates a new coverage provider if one doesn't already exist.\n\n## disableCoverage <Version>4.0.0</Version> {#disablecoverage}\n\n```ts\nfunction disableCoverage(): void\n```\n\nThis method disables coverage collection for tests that run afterwards.\n\n## getSeed <Version>4.0.0</Version> {#getseed}\n\n```ts\nfunction getSeed(): number | null\n```\n\nReturns the seed, if tests are running in a random order.\n\n## experimental_parseSpecification <Version type=\"experimental\">4.0.0</Version> <Experimental /> {#parsespecification}\n\n```ts\nfunction experimental_parseSpecification(\n  specification: TestSpecification\n): Promise<TestModule>\n```\n\nThis function will collect all tests inside the file without running it. It uses rollup's `parseAst` function on top of Vite's `ssrTransform` to statically analyse the file and collect all tests that it can.\n\n::: warning\nIf Vitest could not analyse the name of the test, it will inject a `dynamic: true` property to the test or a suite. The `id` will also have a postfix with `-dynamic` to not break tests that were collected properly.\n\nVitest always injects this property in tests with `for` or `each` modifier or tests with a dynamic name (like, `hello ${property}` or `'hello' + ${property}`). Vitest will still assign a name to the test, but it cannot be used to filter tests.\n\nThere is nothing Vitest can do to make it possible to filter dynamic tests, but you can turn a test with `for` or `each` modifier into a name pattern with `escapeTestName` function:\n\n```ts\nimport { escapeTestName } from 'vitest/node'\n\n// turns into /hello, .+?/\nconst escapedPattern = new RegExp(escapeTestName('hello, %s', true))\n```\n:::\n\n::: warning\nVitest will only collect tests defined in the file. It will never follow imports to other files.\n\nVitest collects all `it`, `test`, `suite` and `describe` definitions even if they were not imported from the `vitest` entry point.\n:::\n\n## experimental_parseSpecifications <Version type=\"experimental\">4.0.0</Version> <Experimental /> {#parsespecifications}\n\n```ts\nfunction experimental_parseSpecifications(\n  specifications: TestSpecification[],\n  options?: {\n    concurrency?: number\n  }\n): Promise<TestModule[]>\n```\n\nThis method will [collect tests](#parsespecification) from an array of specifications. By default, Vitest will run only `os.availableParallelism()` number of specifications at a time to reduce the potential performance degradation. You can specify a different number in a second argument.\n\n## experimental_clearCache <Version type=\"experimental\">4.0.11</Version> <Experimental /> {#clearcache}\n\n```ts\nfunction experimental_clearCache(): Promise<void>\n```\n\nDeletes all Vitest caches, including [`experimental.fsModuleCache`](/config/experimental#experimental-fsmodulecache).\n\n## experimental_getSourceModuleDiagnostic <Version type=\"experimental\">4.0.15</Version> <Experimental /> {#getsourcemodulediagnostic}\n\n```ts\nexport function experimental_getSourceModuleDiagnostic(\n  moduleId: string,\n  testModule?: TestModule,\n): Promise<SourceModuleDiagnostic>\n```\n\n::: details Types\n```ts\nexport interface ModuleDefinitionLocation {\n  line: number\n  column: number\n}\n\nexport interface SourceModuleLocations {\n  modules: ModuleDefinitionDiagnostic[]\n  untracked: ModuleDefinitionDiagnostic[]\n}\n\nexport interface ModuleDefinitionDiagnostic {\n  start: ModuleDefinitionLocation\n  end: ModuleDefinitionLocation\n  startIndex: number\n  endIndex: number\n  url: string\n  resolvedId: string\n}\n\nexport interface ModuleDefinitionDurationsDiagnostic extends ModuleDefinitionDiagnostic {\n  selfTime: number\n  totalTime: number\n  external?: boolean\n}\n\nexport interface UntrackedModuleDefinitionDiagnostic {\n  url: string\n  resolvedId: string\n  selfTime: number\n  totalTime: number\n  external?: boolean\n}\n\nexport interface SourceModuleDiagnostic {\n  modules: ModuleDefinitionDurationsDiagnostic[]\n  untrackedModules: UntrackedModuleDefinitionDiagnostic[]\n}\n```\n:::\n\nReturns module's diagnostic. If [`testModule`](/api/advanced/test-module) is not provided, `selfTime` and `totalTime` will be aggregated across all tests that were running the last time. If the module was not transformed or executed, the diagnostic will be empty.\n\n::: warning\nAt the moment, the [browser](/guide/browser/) modules are not supported.\n:::\n"
  },
  {
    "path": "docs/api/assert-type.md",
    "content": "# assertType\n\n::: warning\nDuring runtime this function doesn't do anything. To [enable typechecking](/guide/testing-types#run-typechecking), don't forget to pass down `--typecheck` flag.\n:::\n\n- **Type:** `<T>(value: T): void`\n\nYou can use this function as an alternative for [`expectTypeOf`](/api/expect-typeof) to easily assert that the argument type is equal to the generic provided.\n\n```ts\nimport { assertType } from 'vitest'\n\nfunction concat(a: string, b: string): string\nfunction concat(a: number, b: number): number\nfunction concat(a: string | number, b: string | number): string | number\n\nassertType<string>(concat('a', 'b'))\nassertType<number>(concat(1, 2))\n// @ts-expect-error wrong types\nassertType(concat('a', 2))\n```\n"
  },
  {
    "path": "docs/api/assert.md",
    "content": "# assert\n\nVitest reexports the `assert` method from [`chai`](https://www.chaijs.com/api/assert/) for verifying invariants.\n\n## assert\n\n- **Type:** `(expression: any, message?: string) => asserts expression`\n\nAssert that the given `expression` is truthy, otherwise the assertion fails.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert', () => {\n  assert('foo' !== 'bar', 'foo should not be equal to bar')\n})\n```\n\n## fail\n\n- **Type:**\n  - `(message?: string) => never`\n  - `<T>(actual: T, expected: T, message?: string, operator?: string) => never`\n\nForce an assertion failure.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.fail', () => {\n  assert.fail('error message on failure')\n  assert.fail('foo', 'bar', 'foo is not bar', '===')\n})\n```\n\n## isOk\n\n- **Type:** `<T>(value: T, message?: string) => asserts value`\n- **Alias** `ok`\n\nAssert that the given `value` is truthy.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isOk', () => {\n  assert.isOk('foo', 'every truthy is ok')\n  assert.isOk(false, 'this will fail since false is not truthy')\n})\n```\n\n## isNotOk\n\n- **Type:** `<T>(value: T, message?: string) => void`\n- **Alias** `notOk`\n\nAssert that the given `value` is falsy.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isNotOk', () => {\n  assert.isNotOk('foo', 'this will fail, every truthy is not ok')\n  assert.isNotOk(false, 'this will pass since false is falsy')\n})\n```\n\n## equal\n\n- **Type:** `<T>(actual: T, expected: T, message?: string) => void`\n\nAsserts non-strict equality (==) of `actual` and `expected`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.equal', () => {\n  assert.equal(Math.sqrt(4), '2')\n})\n```\n\n## notEqual\n\n- **Type:** `<T>(actual: T, expected: T, message?: string) => void`\n\nAsserts non-strict inequality (!=) of `actual` and `expected`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.equal', () => {\n  assert.notEqual(Math.sqrt(4), 3)\n})\n```\n\n## strictEqual\n\n- **Type:** `<T>(actual: T, expected: T, message?: string) => void`\n\nAsserts strict equality (===) of `actual` and `expected`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.strictEqual', () => {\n  assert.strictEqual(Math.sqrt(4), 2)\n})\n```\n\n## deepEqual\n\n- **Type:** `<T>(actual: T, expected: T, message?: string) => void`\n\nAsserts that `actual` is deeply equal to `expected`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.deepEqual', () => {\n  assert.deepEqual({ color: 'green' }, { color: 'green' })\n})\n```\n\n## notDeepEqual\n\n- **Type:** `<T>(actual: T, expected: T, message?: string) => void`\n\nAssert that `actual` is not deeply equal to `expected`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notDeepEqual', () => {\n  assert.notDeepEqual({ color: 'green' }, { color: 'red' })\n})\n```\n\n## isAbove\n\n- **Type:** `(valueToCheck: number, valueToBeAbove: number, message?: string) => void`\n\nAssert that `valueToCheck` is strictly greater than (>) `valueToBeAbove`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isAbove', () => {\n  assert.isAbove(5, 2, '5 is strictly greater than 2')\n})\n```\n\n## isAtLeast\n\n- **Type:** `(valueToCheck: number, valueToBeAtLeast: number, message?: string) => void`\n\nAssert that `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isAtLeast', () => {\n  assert.isAtLeast(5, 2, '5 is greater or equal to 2')\n  assert.isAtLeast(3, 3, '3 is greater or equal to 3')\n})\n```\n\n## isBelow\n\n- **Type:** `(valueToCheck: number, valueToBeBelow: number, message?: string) => void`\n\nAsserts `valueToCheck` is strictly less than (<) `valueToBeBelow`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isBelow', () => {\n  assert.isBelow(3, 6, '3 is strictly less than 6')\n})\n```\n\n## isAtMost\n\n- **Type:** `(valueToCheck: number, valueToBeAtMost: number, message?: string) => void`\n\nAsserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isAtMost', () => {\n  assert.isAtMost(3, 6, '3 is less than or equal to 6')\n  assert.isAtMost(4, 4, '4 is less than or equal to 4')\n})\n```\n\n## isTrue\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is true`\n\nAsserts that `value` is true.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst testPassed = true\n\ntest('assert.isTrue', () => {\n  assert.isTrue(testPassed)\n})\n```\n\n## isNotTrue\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is Exclude<T, true>`\n\nAsserts that `value` is not true.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst testPassed = 'ok'\n\ntest('assert.isNotTrue', () => {\n  assert.isNotTrue(testPassed)\n})\n```\n\n## isFalse\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is false`\n\nAsserts that `value` is false.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst testPassed = false\n\ntest('assert.isFalse', () => {\n  assert.isFalse(testPassed)\n})\n```\n\n## isNotFalse\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is Exclude<T, false>`\n\nAsserts that `value` is not false.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst testPassed = 'no'\n\ntest('assert.isNotFalse', () => {\n  assert.isNotFalse(testPassed)\n})\n```\n\n## isNull\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is null`\n\nAsserts that `value` is null.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst error = null\n\ntest('assert.isNull', () => {\n  assert.isNull(error, 'error is null')\n})\n```\n\n## isNotNull\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is Exclude<T, null>`\n\nAsserts that `value` is not null.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst error = { message: 'error was occurred' }\n\ntest('assert.isNotNull', () => {\n  assert.isNotNull(error, 'error is not null but object')\n})\n```\n\n## isNaN\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is NaN.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst calculation = 1 * 'vitest'\n\ntest('assert.isNaN', () => {\n  assert.isNaN(calculation, '1 * \"vitest\" is NaN')\n})\n```\n\n## isNotNaN\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is not NaN.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst calculation = 1 * 2\n\ntest('assert.isNotNaN', () => {\n  assert.isNotNaN(calculation, '1 * 2 is Not NaN but 2')\n})\n```\n\n## exists\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is NonNullable<T>`\n\nAsserts that `value` is neither null nor undefined.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst name = 'foo'\n\ntest('assert.exists', () => {\n  assert.exists(name, 'foo is neither null nor undefined')\n})\n```\n\n## notExists\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is null | undefined`\n\nAsserts that `value` is either null nor undefined.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst foo = null\nconst bar = undefined\n\ntest('assert.notExists', () => {\n  assert.notExists(foo, 'foo is null so not exist')\n  assert.notExists(bar, 'bar is undefined so not exist')\n})\n```\n\n## isUndefined\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is undefined`\n\nAsserts that `value` is undefined.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst name = undefined\n\ntest('assert.isUndefined', () => {\n  assert.isUndefined(name, 'name is undefined')\n})\n```\n\n## isDefined\n\n- **Type:** `<T>(value: T, message?: string) => asserts value is Exclude<T, undefined>`\n\nAsserts that `value` is not undefined.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst name = 'foo'\n\ntest('assert.isDefined', () => {\n  assert.isDefined(name, 'name is not undefined')\n})\n```\n\n## isFunction\n\n- **Type:** `<T>(value: T, message?: string) => void`\n- **Alias:** `isCallable`\nAsserts that `value` is a function.\n\n```ts\nimport { assert, test } from 'vitest'\n\nfunction name() { return 'foo' };\n\ntest('assert.isFunction', () => {\n  assert.isFunction(name, 'name is function')\n})\n```\n\n## isNotFunction\n\n- **Type:** `<T>(value: T, message?: string) => void`\n- **Alias:** `isNotCallable`\n\nAsserts that `value` is not a function.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst name = 'foo'\n\ntest('assert.isNotFunction', () => {\n  assert.isNotFunction(name, 'name is not function but string')\n})\n```\n\n## isObject\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is an object of type Object (as revealed by Object.prototype.toString). The assertion does not match subclassed objects.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst someThing = { color: 'red', shape: 'circle' }\n\ntest('assert.isObject', () => {\n  assert.isObject(someThing, 'someThing is object')\n})\n```\n\n## isNotObject\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is not an object of type Object (as revealed by Object.prototype.toString). The assertion does not match subclassed objects.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst someThing = 'redCircle'\n\ntest('assert.isNotObject', () => {\n  assert.isNotObject(someThing, 'someThing is not object but string')\n})\n```\n\n## isArray\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is an array.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst color = ['red', 'green', 'yellow']\n\ntest('assert.isArray', () => {\n  assert.isArray(color, 'color is array')\n})\n```\n\n## isNotArray\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is not an array.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst color = 'red'\n\ntest('assert.isNotArray', () => {\n  assert.isNotArray(color, 'color is not array but string')\n})\n```\n\n## isString\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is a string.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst color = 'red'\n\ntest('assert.isString', () => {\n  assert.isString(color, 'color is string')\n})\n```\n\n## isNotString\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is not a string.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst color = ['red', 'green', 'yellow']\n\ntest('assert.isNotString', () => {\n  assert.isNotString(color, 'color is not string but array')\n})\n```\n\n## isNumber\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is a number.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst colors = 3\n\ntest('assert.isNumber', () => {\n  assert.isNumber(colors, 'colors is number')\n})\n```\n\n## isNotNumber\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is not a number.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst colors = '3 colors'\n\ntest('assert.isNotNumber', () => {\n  assert.isNotNumber(colors, 'colors is not number but strings')\n})\n```\n\n## isFinite\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is a finite number (not NaN, Infinity).\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst colors = 3\n\ntest('assert.isFinite', () => {\n  assert.isFinite(colors, 'colors is number not NaN or Infinity')\n})\n```\n\n## isBoolean\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is a boolean.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst isReady = true\n\ntest('assert.isBoolean', () => {\n  assert.isBoolean(isReady, 'isReady is a boolean')\n})\n```\n\n## isNotBoolean\n\n- **Type:** `<T>(value: T, message?: string) => void`\n\nAsserts that `value` is not a boolean.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst isReady = 'sure'\n\ntest('assert.isBoolean', () => {\n  assert.isBoolean(isReady, 'isReady is not a boolean but string')\n})\n```\n\n## typeOf\n\n- **Type:** `<T>(value: T, name: string, message?: string) => void`\n\nAsserts that `value`’s type is `name`, as determined by Object.prototype.toString.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.typeOf', () => {\n  assert.typeOf({ color: 'red' }, 'object', 'we have an object')\n  assert.typeOf(['red', 'green'], 'array', 'we have an array')\n  assert.typeOf('red', 'string', 'we have a string')\n  assert.typeOf(/red/, 'regexp', 'we have a regular expression')\n  assert.typeOf(null, 'null', 'we have a null')\n  assert.typeOf(undefined, 'undefined', 'we have an undefined')\n})\n```\n\n## notTypeOf\n\n- **Type:** `<T>(value: T, name: string, message?: string) => void`\n\nAsserts that `value`’s type is not `name`, as determined by Object.prototype.toString.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notTypeOf', () => {\n  assert.notTypeOf('red', 'number', '\"red\" is not a number')\n})\n```\n\n## instanceOf\n\n- **Type:** `<T>(value: T, constructor: Function, message?: string) => asserts value is T`\n\nAsserts that `value` is an instance of `constructor`.\n\n```ts\nimport { assert, test } from 'vitest'\n\nfunction Person(name) { this.name = name }\nconst foo = new Person('foo')\n\nclass Tea {\n  constructor(name) {\n    this.name = name\n  }\n}\nconst coffee = new Tea('coffee')\n\ntest('assert.instanceOf', () => {\n  assert.instanceOf(foo, Person, 'foo is an instance of Person')\n  assert.instanceOf(coffee, Tea, 'coffee is an instance of Tea')\n})\n```\n\n## notInstanceOf\n\n- **Type:** `<T>(value: T, constructor: Function, message?: string) => asserts value is Exclude<T, U>`\n\nAsserts that `value` is not an instance of `constructor`.\n\n```ts\nimport { assert, test } from 'vitest'\n\nfunction Person(name) { this.name = name }\nconst foo = new Person('foo')\n\nclass Tea {\n  constructor(name) {\n    this.name = name\n  }\n}\nconst coffee = new Tea('coffee')\n\ntest('assert.instanceOf', () => {\n  assert.instanceOf(foo, Tea, 'foo is not an instance of Tea')\n})\n```\n\n## include\n\n- **Type:**\n  - `(haystack: string, needle: string, message?: string) => void`\n  - `<T>(haystack: readonly T[] | ReadonlySet<T> | ReadonlyMap<any, T>, needle: T, message?: string) => void`\n  - `<T extends object>(haystack: WeakSet<T>, needle: T, message?: string) => void`\n  - `<T>(haystack: T, needle: Partial<T>, message?: string) => void`\n\nAsserts that `haystack` includes `needle`. Can be used to assert the inclusion of a value in an array, a substring in a string, or a subset of properties in an object.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.include', () => {\n  assert.include([1, 2, 3], 2, 'array contains value')\n  assert.include('foobar', 'foo', 'string contains substring')\n  assert.include({ foo: 'bar', hello: 'universe' }, { foo: 'bar' }, 'object contains property')\n})\n```\n\n## notInclude\n\n- **Type:**\n  - `(haystack: string, needle: string, message?: string) => void`\n  - `<T>(haystack: readonly T[] | ReadonlySet<T> | ReadonlyMap<any, T>, needle: T, message?: string) => void`\n  - `<T extends object>(haystack: WeakSet<T>, needle: T, message?: string) => void`\n  - `<T>(haystack: T, needle: Partial<T>, message?: string) => void`\n\nAsserts that `haystack` does not include `needle`. It can be used to assert the absence of a value in an array, a substring in a string, or a subset of properties in an object.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notInclude', () => {\n  assert.notInclude([1, 2, 3], 4, 'array doesn\\'t contain 4')\n  assert.notInclude('foobar', 'baz', 'foobar doesn\\'t contain baz')\n  assert.notInclude({ foo: 'bar', hello: 'universe' }, { foo: 'baz' }, 'object doesn\\'t contain property')\n})\n```\n\n## deepInclude\n\n- **Type:**\n- `(haystack: string, needle: string, message?: string) => void`\n- `<T>(haystack: readonly T[] | ReadonlySet<T> | ReadonlyMap<any, T>, needle: T, message?: string) => void`\n- `<T>(haystack: T, needle: T extends WeakSet<any> ? never : Partial<T>, message?: string) => void`\n\nAsserts that `haystack` includes `needle`. Can be used to assert the inclusion of a value in an array or a subset of properties in an object. Deep equality is used.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst obj1 = { a: 1 }\nconst obj2 = { b: 2 }\n\ntest('assert.deepInclude', () => {\n  assert.deepInclude([obj1, obj2], { a: 1 })\n  assert.deepInclude({ foo: obj1, bar: obj2 }, { foo: { a: 1 } })\n})\n```\n\n## notDeepInclude\n\n- **Type:**\n  - `(haystack: string, needle: string, message?: string) => void`\n  - `<T>(haystack: readonly T[] | ReadonlySet<T> | ReadonlyMap<any, T>, needle: T, message?: string) => void`\n  - `<T>(haystack: T, needle: T extends WeakSet<any> ? never : Partial<T>, message?: string) => void`\n\nAsserts that `haystack` does not include `needle`. It can be used to assert the absence of a value in an array or a subset of properties in an object. Deep equality is used.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst obj1 = { a: 1 }\nconst obj2 = { b: 2 }\n\ntest('assert.notDeepInclude', () => {\n  assert.notDeepInclude([obj1, obj2], { a: 10 })\n  assert.notDeepInclude({ foo: obj1, bar: obj2 }, { foo: { a: 10 } })\n})\n```\n\n## nestedInclude\n\n- **Type:** `(haystack: any, needle: any, message?: string) => void`\n\nAsserts that `haystack` includes `needle`. Can be used to assert the inclusion of a subset of properties in an object. Enables the use of dot- and bracket-notation for referencing nested properties. ‘[]’ and ‘.’ in property names can be escaped using double backslashes.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.nestedInclude', () => {\n  assert.nestedInclude({ '.a': { b: 'x' } }, { '\\\\.a.[b]': 'x' })\n  assert.nestedInclude({ a: { '[b]': 'x' } }, { 'a.\\\\[b\\\\]': 'x' })\n})\n```\n\n## notNestedInclude\n\n- **Type:** `(haystack: any, needle: any, message?: string) => void`\n\nAsserts that `haystack` does not include `needle`. Can be used to assert the inclusion of a subset of properties in an object. Enables the use of dot- and bracket-notation for referencing nested properties. ‘[]’ and ‘.’ in property names can be escaped using double backslashes.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.nestedInclude', () => {\n  assert.notNestedInclude({ '.a': { b: 'x' } }, { '\\\\.a.b': 'y' })\n  assert.notNestedInclude({ a: { '[b]': 'x' } }, { 'a.\\\\[b\\\\]': 'y' })\n})\n```\n\n## deepNestedInclude\n\n- **Type:** `(haystack: any, needle: any, message?: string) => void`\n\nAsserts that `haystack` includes `needle`. Can be used to assert the inclusion of a subset of properties in an object while checking for deep equality. Enables the use of dot- and bracket-notation for referencing nested properties. ‘[]’ and ‘.’ in property names can be escaped using double backslashes.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.deepNestedInclude', () => {\n  assert.deepNestedInclude({ a: { b: [{ x: 1 }] } }, { 'a.b[0]': { x: 1 } })\n  assert.deepNestedInclude({ '.a': { '[b]': { x: 1 } } }, { '\\\\.a.\\\\[b\\\\]': { x: 1 } })\n})\n```\n\n## notDeepNestedInclude\n\n- **Type:** `(haystack: any, needle: any, message?: string) => void`\n\nAsserts that `haystack` not includes `needle`. Can be used to assert the absence of a subset of properties in an object while checking for deep equality. Enables the use of dot- and bracket-notation for referencing nested properties. ‘[]’ and ‘.’ in property names can be escaped using double backslashes.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notDeepNestedInclude', () => {\n  assert.notDeepNestedInclude({ a: { b: [{ x: 1 }] } }, { 'a.b[0]': { y: 1 } })\n  assert.notDeepNestedInclude({ '.a': { '[b]': { x: 1 } } }, { '\\\\.a.\\\\[b\\\\]': { y: 2 } })\n})\n```\n\n## ownInclude\n\n- **Type:** `(haystack: any, needle: any, message?: string) => void`\n\nAsserts that `haystack` includes `needle`. Can be used to assert the inclusion of a subset of properties in an object while ignoring inherited properties.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.ownInclude', () => {\n  assert.ownInclude({ a: 1 }, { a: 1 })\n})\n```\n\n## notOwnInclude\n\n- **Type:** `(haystack: any, needle: any, message?: string) => void`\n\nAsserts that `haystack` includes `needle`. Can be used to assert the absence of a subset of properties in an object while ignoring inherited properties.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst obj1 = {\n  b: 2\n}\n\nconst obj2 = object.create(obj1)\nobj2.a = 1\n\ntest('assert.notOwnInclude', () => {\n  assert.notOwnInclude(obj2, { b: 2 })\n})\n```\n\n## deepOwnInclude\n\n- **Type:** `(haystack: any, needle: any, message?: string) => void`\n\nAsserts that `haystack` includes `needle`. Can be used to assert the inclusion of a subset of properties in an object while ignoring inherited properties and checking for deep equality.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.deepOwnInclude', () => {\n  assert.deepOwnInclude({ a: { b: 2 } }, { a: { b: 2 } })\n})\n```\n\n## notDeepOwnInclude\n\n- **Type:** `(haystack: any, needle: any, message?: string) => void`\n\nAsserts that `haystack` not includes `needle`. Can be used to assert the absence of a subset of properties in an object while ignoring inherited properties and checking for deep equality.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notDeepOwnInclude', () => {\n  assert.notDeepOwnInclude({ a: { b: 2 } }, { a: { c: 3 } })\n})\n```\n\n## match\n\n- **Type:** `(value: string, regexp: RegExp, message?: string) => void`\n\nAsserts that `value` matches the regular expression `regexp`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.match', () => {\n  assert.match('foobar', /^foo/, 'regexp matches')\n})\n```\n\n## notMatch\n\n- **Type:** `(value: string, regexp: RegExp, message?: string) => void`\n\nAsserts that `value` does not matches the regular expression `regexp`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notMatch', () => {\n  assert.notMatch('foobar', /^foo/, 'regexp does not match')\n})\n```\n\n## property\n\n- **Type:** `<T>(object: T, property: string, message?: string) => void`\n\nAsserts that `object` has a direct or inherited property named by `property`\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.property', () => {\n  assert.property({ tea: { green: 'matcha' } }, 'tea')\n  assert.property({ tea: { green: 'matcha' } }, 'toString')\n})\n```\n\n## notProperty\n\n- **Type:** `<T>(object: T, property: string, message?: string) => void`\n\nAsserts that `object` does not have a direct or inherited property named by `property`\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notProperty', () => {\n  assert.notProperty({ tea: { green: 'matcha' } }, 'coffee')\n})\n```\n\n## propertyVal\n\n- **Type:** `<T, V>(object: T, property: string, value: V, message?: string) => void`\n\nAsserts that `object` has a direct or inherited property named by `property` with a value given by `value`. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notPropertyVal', () => {\n  assert.propertyVal({ tea: 'is good' }, 'tea', 'is good')\n})\n```\n\n## notPropertyVal\n\n- **Type:** `<T, V>(object: T, property: string, value: V, message?: string) => void`\n\nAsserts that `object` does not have a direct or inherited property named by `property` with a value given by `value`. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notPropertyVal', () => {\n  assert.notPropertyVal({ tea: 'is good' }, 'tea', 'is bad')\n  assert.notPropertyVal({ tea: 'is good' }, 'coffee', 'is good')\n})\n```\n\n## deepPropertyVal\n\n- **Type:** `<T, V>(object: T, property: string, value: V, message?: string) => void`\n\nAsserts that `object` has a direct or inherited property named by `property` with a value given by `value`. Uses a deep equality check.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.deepPropertyVal', () => {\n  assert.deepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'matcha' })\n})\n```\n\n## notDeepPropertyVal\n\n- **Type:** `<T, V>(object: T, property: string, value: V, message?: string) => void`\n\nAsserts that `object` does not have a direct or inherited property named by `property` with a value given by `value`. Uses a deep equality check.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.deepPropertyVal', () => {\n  assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { black: 'matcha' })\n  assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'oolong' })\n  assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'coffee', { green: 'matcha' })\n})\n```\n\n## nestedProperty\n\n- **Type:** `<T>(object: T, property: string, message?: string) => void`\n\nAsserts that `object` has a direct or inherited property named by `property`, which can be a string using dot- and bracket-notation for nested reference.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.deepPropertyVal', () => {\n  assert.nestedProperty({ tea: { green: 'matcha' } }, 'tea.green')\n})\n```\n\n## notNestedProperty\n\n- **Type:** `<T>(object: T, property: string, message?: string) => void`\n\nAsserts that `object` does not have a direct or inherited property named by `property`, which can be a string using dot- and bracket-notation for nested reference.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.deepPropertyVal', () => {\n  assert.notNestedProperty({ tea: { green: 'matcha' } }, 'tea.oolong')\n})\n```\n\n## nestedPropertyVal\n\n- **Type:** `<T>(object: T, property: string, value: any, message?: string) => void`\n\nAsserts that `object` has a property named by `property` with value given by `value`. `property` can use dot- and bracket-notation for nested reference. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.nestedPropertyVal', () => {\n  assert.nestedPropertyVal({ tea: { green: 'matcha' } }, 'tea.green', 'matcha')\n})\n```\n\n## notNestedPropertyVal\n\n- **Type:** `<T>(object: T, property: string, value: any, message?: string) => void`\n\nAsserts that `object` does not have a property named by `property` with value given by `value`. `property` can use dot- and bracket-notation for nested reference. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notNestedPropertyVal', () => {\n  assert.notNestedPropertyVal({ tea: { green: 'matcha' } }, 'tea.green', 'konacha')\n  assert.notNestedPropertyVal({ tea: { green: 'matcha' } }, 'coffee.green', 'matcha')\n})\n```\n\n## deepNestedPropertyVal\n\n- **Type:** `<T>(object: T, property: string, value: any, message?: string) => void`\n\nAsserts that `object` has a property named by `property` with a value given by `value`. `property` can use dot- and bracket-notation for nested reference. Uses a deep equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notNestedPropertyVal', () => {\n  assert.notNestedPropertyVal({ tea: { green: 'matcha' } }, 'tea.green', 'konacha')\n  assert.notNestedPropertyVal({ tea: { green: 'matcha' } }, 'coffee.green', 'matcha')\n})\n```\n\n## notDeepNestedPropertyVal\n\n- **Type:** `<T>(object: T, property: string, value: any, message?: string) => void`\n\nAsserts that `object` does not have a property named by `property` with value given by `value`. `property` can use dot- and bracket-notation for nested reference. Uses a deep equality check.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notDeepNestedPropertyVal', () => {\n  assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { oolong: 'yum' })\n  assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { matcha: 'yuck' })\n  assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.black', { matcha: 'yum' })\n})\n```\n\n## lengthOf\n\n- **Type:** `<T extends { readonly length?: number | undefined } | { readonly size?: number | undefined }>(object: T, length: number, message?: string) => void`\n\nAsserts that `object` has a `length` or `size` with the expected value.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.lengthOf', () => {\n  assert.lengthOf([1, 2, 3], 3, 'array has length of 3')\n  assert.lengthOf('foobar', 6, 'string has length of 6')\n  assert.lengthOf(new Set([1, 2, 3]), 3, 'set has size of 3')\n  assert.lengthOf(new Map([['a', 1], ['b', 2], ['c', 3]]), 3, 'map has size of 3')\n})\n```\n\n## hasAnyKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` has at least one of the `keys` provided. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.hasAnyKeys', () => {\n  assert.hasAnyKeys({ foo: 1, bar: 2, baz: 3 }, ['foo', 'iDontExist', 'baz'])\n  assert.hasAnyKeys({ foo: 1, bar: 2, baz: 3 }, { foo: 30, iDontExist: 99, baz: 1337 })\n  assert.hasAnyKeys(new Map([[{ foo: 1 }, 'bar'], ['key', 'value']]), [{ foo: 1 }, 'key'])\n  assert.hasAnyKeys(new Set([{ foo: 'bar' }, 'anotherKey']), [{ foo: 'bar' }, 'anotherKey'])\n})\n```\n\n## hasAllKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` has all and only all of the `keys` provided. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.hasAllKeys', () => {\n  assert.hasAllKeys({ foo: 1, bar: 2, baz: 3 }, ['foo', 'bar', 'baz'])\n  assert.hasAllKeys({ foo: 1, bar: 2, baz: 3 }, { foo: 30, bar: 99, baz: 1337 })\n  assert.hasAllKeys(new Map([[{ foo: 1 }, 'bar'], ['key', 'value']]), [{ foo: 1 }, 'key'])\n  assert.hasAllKeys(new Set([{ foo: 'bar' }, 'anotherKey'], [{ foo: 'bar' }, 'anotherKey']))\n})\n```\n\n## containsAllKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` has all of the `keys` provided but may have more keys not listed. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.containsAllKeys', () => {\n  assert.containsAllKeys({ foo: 1, bar: 2, baz: 3 }, ['foo', 'baz'])\n  assert.containsAllKeys({ foo: 1, bar: 2, baz: 3 }, ['foo', 'bar', 'baz'])\n  assert.containsAllKeys({ foo: 1, bar: 2, baz: 3 }, { foo: 30, baz: 1337 })\n  assert.containsAllKeys({ foo: 1, bar: 2, baz: 3 }, { foo: 30, bar: 99, baz: 1337 })\n  assert.containsAllKeys(new Map([[{ foo: 1 }, 'bar'], ['key', 'value']]), [{ foo: 1 }])\n  assert.containsAllKeys(new Map([[{ foo: 1 }, 'bar'], ['key', 'value']]), [{ foo: 1 }, 'key'])\n  assert.containsAllKeys(new Set([{ foo: 'bar' }, 'anotherKey'], [{ foo: 'bar' }]))\n  assert.containsAllKeys(new Set([{ foo: 'bar' }, 'anotherKey'], [{ foo: 'bar' }, 'anotherKey']))\n})\n```\n\n## doesNotHaveAnyKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` has none of the `keys` provided. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.doesNotHaveAnyKeys', () => {\n  assert.doesNotHaveAnyKeys({ foo: 1, bar: 2, baz: 3 }, ['one', 'two', 'example'])\n  assert.doesNotHaveAnyKeys({ foo: 1, bar: 2, baz: 3 }, { one: 1, two: 2, example: 'foo' })\n  assert.doesNotHaveAnyKeys(new Map([[{ foo: 1 }, 'bar'], ['key', 'value']]), [{ one: 'two' }, 'example'])\n  assert.doesNotHaveAnyKeys(new Set([{ foo: 'bar' }, 'anotherKey'], [{ one: 'two' }, 'example']))\n})\n```\n\n## doesNotHaveAllKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` does not have at least one of the `keys` provided. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.hasAnyKeys', () => {\n  assert.doesNotHaveAnyKeys({ foo: 1, bar: 2, baz: 3 }, ['one', 'two', 'example'])\n  assert.doesNotHaveAnyKeys({ foo: 1, bar: 2, baz: 3 }, { one: 1, two: 2, example: 'foo' })\n  assert.doesNotHaveAnyKeys(new Map([[{ foo: 1 }, 'bar'], ['key', 'value']]), [{ one: 'two' }, 'example'])\n  assert.doesNotHaveAnyKeys(new Set([{ foo: 'bar' }, 'anotherKey']), [{ one: 'two' }, 'example'])\n})\n```\n\n## hasAnyDeepKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` has at least one of the `keys` provided. Since Sets and Maps can have objects as keys you can use this assertion to perform a deep comparison. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.hasAnyDeepKeys', () => {\n  assert.hasAnyDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [1, 2]]), { one: 'one' })\n  assert.hasAnyDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [1, 2]]), [{ one: 'one' }, { two: 'two' }])\n  assert.hasAnyDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [{ two: 'two' }, 'valueTwo']]), [{ one: 'one' }, { two: 'two' }])\n  assert.hasAnyDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), { one: 'one' })\n  assert.hasAnyDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), [{ one: 'one' }, { three: 'three' }])\n  assert.hasAnyDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), [{ one: 'one' }, { two: 'two' }])\n})\n```\n\n## hasAllDeepKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` has all and only all of the `keys` provided. Since Sets and Maps can have objects as keys you can use this assertion to perform a deep comparison. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.hasAnyDeepKeys', () => {\n  assert.hasAllDeepKeys(new Map([[{ one: 'one' }, 'valueOne']]), { one: 'one' })\n  assert.hasAllDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [{ two: 'two' }, 'valueTwo']]), [{ one: 'one' }, { two: 'two' }])\n  assert.hasAllDeepKeys(new Set([{ one: 'one' }]), { one: 'one' })\n  assert.hasAllDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), [{ one: 'one' }, { two: 'two' }])\n})\n```\n\n## containsAllDeepKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` contains all of the `keys` provided. Since Sets and Maps can have objects as keys you can use this assertion to perform a deep comparison. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.containsAllDeepKeys', () => {\n  assert.containsAllDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [1, 2]]), { one: 'one' })\n  assert.containsAllDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [{ two: 'two' }, 'valueTwo']]), [{ one: 'one' }, { two: 'two' }])\n  assert.containsAllDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), { one: 'one' })\n  assert.containsAllDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), [{ one: 'one' }, { two: 'two' }])\n})\n```\n\n## doesNotHaveAnyDeepKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` has none of the `keys` provided. Since Sets and Maps can have objects as keys you can use this assertion to perform a deep comparison. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.doesNotHaveAnyDeepKeys', () => {\n  assert.doesNotHaveAnyDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [1, 2]]), { thisDoesNot: 'exist' })\n  assert.doesNotHaveAnyDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [{ two: 'two' }, 'valueTwo']]), [{ twenty: 'twenty' }, { fifty: 'fifty' }])\n  assert.doesNotHaveAnyDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), { twenty: 'twenty' })\n  assert.doesNotHaveAnyDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), [{ twenty: 'twenty' }, { fifty: 'fifty' }])\n})\n```\n\n## doesNotHaveAllDeepKeys\n\n- **Type:** `<T>(object: T, keys: Array<Object | string> | { [key: string]: any }, message?: string) => void`\n\nAsserts that `object` does not have at least one of the `keys` provided. Since Sets and Maps can have objects as keys you can use this assertion to perform a deep comparison. You can also provide a single object instead of a keys array and its keys will be used as the expected set of keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.doesNotHaveAllDeepKeys', () => {\n  assert.doesNotHaveAllDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [1, 2]]), { thisDoesNot: 'exist' })\n  assert.doesNotHaveAllDeepKeys(new Map([[{ one: 'one' }, 'valueOne'], [{ two: 'two' }, 'valueTwo']]), [{ twenty: 'twenty' }, { one: 'one' }])\n  assert.doesNotHaveAllDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), { twenty: 'twenty' })\n  assert.doesNotHaveAllDeepKeys(new Set([{ one: 'one' }, { two: 'two' }]), [{ one: 'one' }, { fifty: 'fifty' }])\n})\n```\n\n## throws\n\n- **Type:**\n  - `(fn: () => void, errMsgMatcher?: RegExp | string, ignored?: any, message?: string) => void`\n  - `(fn: () => void, errorLike?: ErrorConstructor | Error | null, errMsgMatcher?: RegExp | string | null, message?: string) => void`\n- **Alias:**\n  - `throw`\n  - `Throw`\n\nIf `errorLike` is an Error constructor, asserts that `fn` will throw an error that is an instance of `errorLike`. If errorLike is an Error instance, asserts that the error thrown is the same instance as `errorLike`. If `errMsgMatcher` is provided, it also asserts that the error thrown will have a message matching `errMsgMatcher`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.throws', () => {\n  assert.throws(fn, 'Error thrown must have this msg')\n  assert.throws(fn, /Error thrown must have a msg that matches this/)\n  assert.throws(fn, ReferenceError)\n  assert.throws(fn, errorInstance)\n  assert.throws(fn, ReferenceError, 'Error thrown must be a ReferenceError and have this msg')\n  assert.throws(fn, errorInstance, 'Error thrown must be the same errorInstance and have this msg')\n  assert.throws(fn, ReferenceError, /Error thrown must be a ReferenceError and match this/)\n  assert.throws(fn, errorInstance, /Error thrown must be the same errorInstance and match this/)\n})\n```\n\n## doesNotThrow\n\n- **Type:** `(fn: () => void, errMsgMatcher?: RegExp | string, ignored?: any, message?: string) => void`\n- **Type:** `(fn: () => void, errorLike?: ErrorConstructor | Error | null, errMsgMatcher?: RegExp | string | null, message?: string) => void`\n\nIf `errorLike` is an Error constructor, asserts that `fn` will not throw an error that is an instance of `errorLike`. If errorLike is an Error instance, asserts that the error thrown is not the same instance as `errorLike`. If `errMsgMatcher` is provided, it also asserts that the error thrown will not have a message matching `errMsgMatcher`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.doesNotThrow', () => {\n  assert.doesNotThrow(fn, 'Any Error thrown must not have this message')\n  assert.doesNotThrow(fn, /Any Error thrown must not match this/)\n  assert.doesNotThrow(fn, Error)\n  assert.doesNotThrow(fn, errorInstance)\n  assert.doesNotThrow(fn, Error, 'Error must not have this message')\n  assert.doesNotThrow(fn, errorInstance, 'Error must not have this message')\n  assert.doesNotThrow(fn, Error, /Error must not match this/)\n  assert.doesNotThrow(fn, errorInstance, /Error must not match this/)\n})\n```\n\n## operator\n\n- **Type:** `(val1: OperatorComparable, operator: Operator, val2: OperatorComparable, message?: string) => void`\n\nCompare `val1` and `val2` using `operator`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.operator', () => {\n  assert.operator(1, '<', 2, 'everything is ok')\n})\n```\n\n## closeTo\n\n- **Type:** `(actual: number, expected: number, delta: number, message?: string) => void`\n- **Alias:** `approximately`\n\nAsserts that the `actual` is equal `expected`, to within a +/- `delta` range.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.closeTo', () => {\n  assert.closeTo(1.5, 1, 0.5, 'numbers are close')\n})\n```\n\n## sameMembers\n\n- **Type:** `<T>(set1: T[], set2: T[], message?: string) => void`\n\nAsserts that `set1` and `set2` have the same members in any order. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.sameMembers', () => {\n  assert.sameMembers([1, 2, 3], [2, 1, 3], 'same members')\n})\n```\n\n## notSameMembers\n\n- **Type:** `<T>(set1: T[], set2: T[], message?: string) => void`\n\nAsserts that `set1` and `set2` don't have the same members in any order. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.sameMembers', () => {\n  assert.notSameMembers([1, 2, 3], [5, 1, 3], 'not same members')\n})\n```\n\n## sameDeepMembers\n\n- **Type:** `<T>(set1: T[], set2: T[], message?: string) => void`\n\nAsserts that `set1` and `set2` have the same members in any order. Uses a deep equality check.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.sameDeepMembers', () => {\n  assert.sameDeepMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ b: 2 }, { a: 1 }, { c: 3 }], 'same deep members')\n})\n```\n\n## notSameDeepMembers\n\n- **Type:** `<T>(set1: T[], set2: T[], message?: string) => void`\n\nAsserts that `set1` and `set2` don’t have the same members in any order. Uses a deep equality check.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.sameDeepMembers', () => {\n  assert.sameDeepMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ b: 2 }, { a: 1 }, { c: 3 }], 'same deep members')\n})\n```\n\n## sameOrderedMembers\n\n- **Type:** `<T>(set1: T[], set2: T[], message?: string) => void`\n\nAsserts that `set1` and `set2` have the same members in the same order. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.sameOrderedMembers', () => {\n  assert.sameOrderedMembers([1, 2, 3], [1, 2, 3], 'same ordered members')\n})\n```\n\n## notSameOrderedMembers\n\n- **Type:** `<T>(set1: T[], set2: T[], message?: string) => void`\n\nAsserts that `set1` and `set2` have the same members in the same order. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notSameOrderedMembers', () => {\n  assert.notSameOrderedMembers([1, 2, 3], [2, 1, 3], 'not same ordered members')\n})\n```\n\n## sameDeepOrderedMembers\n\n- **Type:** `<T>(set1: T[], set2: T[], message?: string) => void`\n\nAsserts that `set1` and `set2` have the same members in the same order. Uses a deep equality check.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.sameDeepOrderedMembers', () => {\n  assert.sameDeepOrderedMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ a: 1 }, { b: 2 }, { c: 3 }], 'same deep ordered members')\n})\n```\n\n## notSameDeepOrderedMembers\n\n- **Type:** `<T>(set1: T[], set2: T[], message?: string) => void`\n\nAsserts that `set1` and `set2` don’t have the same members in the same order. Uses a deep equality check.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notSameDeepOrderedMembers', () => {\n  assert.notSameDeepOrderedMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ a: 1 }, { b: 2 }, { z: 5 }], 'not same deep ordered members')\n  assert.notSameDeepOrderedMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ b: 2 }, { a: 1 }, { c: 3 }], 'not same deep ordered members')\n})\n```\n\n## includeMembers\n\n- **Type:** `<T>(superset: T[], subset: T[], message?: string) => void`\n\nAsserts that `subset` is included in `superset` in any order. Uses a strict equality check (===). Duplicates are ignored.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.includeMembers', () => {\n  assert.includeMembers([1, 2, 3], [2, 1, 2], 'include members')\n})\n```\n\n## notIncludeMembers\n\n- **Type:** `<T>(superset: T[], subset: T[], message?: string) => void`\n\nAsserts that `subset` isn't included in `superset` in any order. Uses a strict equality check (===). Duplicates are ignored.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notIncludeMembers', () => {\n  assert.notIncludeMembers([1, 2, 3], [5, 1], 'not include members')\n})\n```\n\n## includeDeepMembers\n\n- **Type:** `<T>(superset: T[], subset: T[], message?: string) => void`\n\nAsserts that `subset` is included in `superset` in any order. Uses a deep equality check. Duplicates are ignored.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.includeDeepMembers', () => {\n  assert.includeDeepMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ b: 2 }, { a: 1 }, { b: 2 }], 'include deep members')\n})\n```\n\n## notIncludeDeepMembers\n\n- **Type:** `<T>(superset: T[], subset: T[], message?: string) => void`\n\nAsserts that `subset` isn’t included in `superset` in any order. Uses a deep equality check. Duplicates are ignored.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notIncludeDeepMembers', () => {\n  assert.notIncludeDeepMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ b: 2 }, { f: 5 }], 'not include deep members')\n})\n```\n\n## includeOrderedMembers\n\n- **Type:** `<T>(superset: T[], subset: T[], message?: string) => void`\n\nAsserts that `subset` is included in `superset` in the same order beginning with the first element in `superset`. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.includeOrderedMembers', () => {\n  assert.includeOrderedMembers([1, 2, 3], [1, 2], 'include ordered members')\n})\n```\n\n## notIncludeOrderedMembers\n\n- **Type:** `<T>(superset: T[], subset: T[], message?: string) => void`\n\nAsserts that `subset` isn't included in `superset` in the same order beginning with the first element in `superset`. Uses a strict equality check (===).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.notIncludeOrderedMembers', () => {\n  assert.notIncludeOrderedMembers([1, 2, 3], [2, 1], 'not include ordered members')\n  assert.notIncludeOrderedMembers([1, 2, 3], [2, 3], 'not include ordered members')\n})\n```\n\n## includeDeepOrderedMembers\n\n- **Type:** `<T>(superset: T[], subset: T[], message?: string) => void`\n\nAsserts that `subset` is included in `superset` in the same order beginning with the first element in `superset`. Uses a deep equality check.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.includeDeepOrderedMembers', () => {\n  assert.includeDeepOrderedMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ a: 1 }, { b: 2 }], 'include deep ordered members')\n})\n```\n\n## notIncludeDeepOrderedMembers\n\n- **Type:** `<T>(superset: T[], subset: T[], message?: string) => void`\n\nAsserts that `subset` isn’t included in `superset` in the same order beginning with the first element in superset. Uses a deep equality check.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.includeDeepOrderedMembers', () => {\n  assert.notIncludeDeepOrderedMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ a: 1 }, { f: 5 }], 'not include deep ordered members')\n  assert.notIncludeDeepOrderedMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ b: 2 }, { a: 1 }], 'not include deep ordered members')\n  assert.notIncludeDeepOrderedMembers([{ a: 1 }, { b: 2 }, { c: 3 }], [{ b: 2 }, { c: 3 }], 'not include deep ordered members')\n})\n```\n\n## oneOf\n\n- **Type:** `<T>(inList: T, list: T[], message?: string) => void`\n\nAsserts that non-object, non-array value `inList` appears in the flat array `list`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.oneOf', () => {\n  assert.oneOf(1, [2, 1], 'Not found in list')\n})\n```\n\n## changes\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, message?: string) => void`\n\nAsserts that a `modifier` changes the `object` of a `property`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.changes', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val = 22 };\n  assert.changes(fn, obj, 'val')\n})\n```\n\n## changesBy\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, change: number, message?: string) => void`\n\nAsserts that a `modifier` changes the `object` of a `property` by a `change`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.changesBy', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val += 2 };\n  assert.changesBy(fn, obj, 'val', 2)\n})\n```\n\n## doesNotChange\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, message?: string) => void`\n\nAsserts that a `modifier` does not changes the `object` of a `property`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.doesNotChange', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val += 2 };\n  assert.doesNotChange(fn, obj, 'val', 2)\n})\n```\n\n## changesButNotBy\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, change:number, message?: string) => void`\n\nAsserts that a `modifier` does not change the `object` of a `property` or of a `modifier` return value by a `change`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.changesButNotBy', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val += 10 };\n  assert.changesButNotBy(fn, obj, 'val', 5)\n})\n```\n\n## increases\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, message?: string) => void`\n\nAsserts that a `modifier` increases a numeric `object`'s `property`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.increases', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val = 13 };\n  assert.increases(fn, obj, 'val')\n})\n```\n\n## increasesBy\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, change: number, message?: string) => void`\n\nAsserts that a `modifier` increases a numeric `object`'s `property` or a `modifier` return value by an `change`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.increasesBy', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val += 10 };\n  assert.increasesBy(fn, obj, 'val', 10)\n})\n```\n\n## doesNotIncrease\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, message?: string) => void`\n\nAsserts that a `modifier` does not increases a numeric `object`'s `property`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.doesNotIncrease', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val = 8 }\n  assert.doesNotIncrease(fn, obj, 'val')\n})\n```\n\n## increasesButNotBy\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, change: number, message?: string) => void`\n\nAsserts that a `modifier` does not increases a numeric `object`'s `property` or a `modifier` return value by an `change`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.increasesButNotBy', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val += 15 };\n  assert.increasesButNotBy(fn, obj, 'val', 10)\n})\n```\n\n## decreases\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, message?: string) => void`\n\nAsserts that a `modifier` decreases a numeric `object`'s `property`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.decreases', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val = 5 };\n  assert.decreases(fn, obj, 'val')\n})\n```\n\n## decreasesBy\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, change: number, message?: string) => void`\n\nAsserts that a `modifier` decreases a numeric `object`'s `property` or a `modifier` return value by a `change`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.decreasesBy', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val -= 5 };\n  assert.decreasesBy(fn, obj, 'val', 5)\n})\n```\n\n## doesNotDecrease\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, message?: string) => void`\n\nAsserts that a `modifier` dose not decrease a numeric `object`'s `property`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.doesNotDecrease', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val = 15 }\n  assert.doesNotDecrease(fn, obj, 'val')\n})\n```\n\n## doesNotDecreaseBy\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, change: number, message?: string) => void`\n\nAsserts that a `modifier` does not decrease a numeric `object`'s `property` or a `modifier` return value by a `change`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.doesNotDecreaseBy', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val = 5 };\n  assert.doesNotDecreaseBy(fn, obj, 'val', 1)\n})\n```\n\n## decreasesButNotBy\n\n- **Type:** `<T>(modifier: Function, object: T, property: string, change: number, message?: string) => void`\n\nAsserts that a `modifier` does not decrease a numeric `object`'s `property` or a `modifier` return value by a `change`.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.decreasesButNotBy', () => {\n  const obj = { val: 10 }\n  function fn() { obj.val = 5 };\n  assert.decreasesButNotBy(fn, obj, 'val', 1)\n})\n```\n\n## ifError\n\n- **Type:** `<T>(object: T, message?: string) => void`\n\nAsserts if `object` is not a false value, and throws if it is a true value. This is added to allow for chai to be a drop-in replacement for Node’s assert class.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.ifError', () => {\n  const err = new Error('I am a custom error')\n  assert.ifError(err) // Rethrows err!\n})\n```\n\n## isExtensible\n\n- **Type:** `<T>(object: T, message?: string) => void`\n- **Alias:** `extensible`\n\nAsserts that `object` is extensible (can have new properties added to it).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isExtensible', () => {\n  assert.isExtensible({})\n})\n```\n\n## isNotExtensible\n\n- **Type:** `<T>(object: T, message?: string) => void`\n- **Alias:** `notExtensible`\n\nAsserts that `object` is not extensible (can not have new properties added to it).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isNotExtensible', () => {\n  const nonExtensibleObject = Object.preventExtensions({})\n  const sealedObject = Object.seal({})\n  const frozenObject = Object.freeze({})\n\n  assert.isNotExtensible(nonExtensibleObject)\n  assert.isNotExtensible(sealedObject)\n  assert.isNotExtensible(frozenObject)\n})\n```\n\n## isSealed\n\n- **Type:** `<T>(object: T, message?: string) => void`\n- **Alias:** `sealed`\n\nAsserts that `object` is sealed (cannot have new properties added to it and its existing properties cannot be removed).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isSealed', () => {\n  const sealedObject = Object.seal({})\n  const frozenObject = Object.seal({})\n\n  assert.isSealed(sealedObject)\n  assert.isSealed(frozenObject)\n})\n```\n\n## isNotSealed\n\n- **Type:** `<T>(object: T, message?: string) => void`\n- **Alias:** `notSealed`\n\nAsserts that `object` is not sealed (can have new properties added to it and its existing properties can be removed).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isNotSealed', () => {\n  assert.isNotSealed({})\n})\n```\n\n## isFrozen\n\n- **Type:** `<T>(object: T, message?: string) => void`\n- **Alias:** `frozen`\n\nAsserts that object is frozen (cannot have new properties added to it and its existing properties cannot be modified).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isFrozen', () => {\n  const frozenObject = Object.freeze({})\n  assert.frozen(frozenObject)\n})\n```\n\n## isNotFrozen\n\n- **Type:** `<T>(object: T, message?: string) => void`\n- **Alias:** `notFrozen`\n\nAsserts that `object` is not frozen (can have new properties added to it and its existing properties can be modified).\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isNotFrozen', () => {\n  assert.isNotFrozen({})\n})\n```\n\n## isEmpty\n\n- **Type:** `<T>(target: T, message?: string) => void`\n- **Alias:** `empty`\n\nAsserts that the `target` does not contain any values. For arrays and strings, it checks the length property. For Map and Set instances, it checks the size property. For non-function objects, it gets the count of its own enumerable string keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isEmpty', () => {\n  assert.isEmpty([])\n  assert.isEmpty('')\n  assert.isEmpty(new Map())\n  assert.isEmpty({})\n})\n```\n\n## isNotEmpty\n\n- **Type:** `<T>(object: T, message?: string) => void`\n- **Alias:** `notEmpty`\n\nAsserts that the `target` contains values. For arrays and strings, it checks the length property. For Map and Set instances, it checks the size property. For non-function objects, it gets the count of its own enumerable string keys.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('assert.isNotEmpty', () => {\n  assert.isNotEmpty([1, 2])\n  assert.isNotEmpty('34')\n  assert.isNotEmpty(new Set([5, 6]))\n  assert.isNotEmpty({ key: 7 })\n})\n```\n"
  },
  {
    "path": "docs/api/browser/assertions.md",
    "content": "---\ntitle: Assertion API | Browser Mode\n---\n\n# Assertion API\n\nVitest provides a wide range of DOM assertions out of the box forked from [`@testing-library/jest-dom`](https://github.com/testing-library/jest-dom) library with the added support for locators and built-in retry-ability.\n\n::: tip TypeScript Support\nIf you are using [TypeScript](/guide/browser/#typescript) or want to have correct type hints in `expect`, make sure you have `vitest/browser` referenced somewhere. If you never imported from there, you can add a `reference` comment in any file that's covered by your `tsconfig.json`:\n\n```ts\n/// <reference types=\"vitest/browser\" />\n```\n:::\n\nTests in the browser might fail inconsistently due to their asynchronous nature. Because of this, it is important to have a way to guarantee that assertions succeed even if the condition is delayed (by a timeout, network request, or animation, for example). For this purpose, Vitest provides retriable assertions out of the box via the [`expect.poll`](/api/expect#poll) and `expect.element` APIs:\n\n```ts\nimport { expect, test } from 'vitest'\nimport { page } from 'vitest/browser'\n\ntest('error banner is rendered', async () => {\n  triggerError()\n\n  // This creates a locator that will try to find the element\n  // when any of its methods are called.\n  // This call by itself doesn't check the existence of the element.\n  const banner = page.getByRole('alert', {\n    name: /error/i,\n  })\n\n  // Vitest provides `expect.element` with built-in retry-ability\n  // It will repeatedly check that the element exists in the DOM and that\n  // the content of `element.textContent` is equal to \"Error!\"\n  // until all the conditions are met\n  await expect.element(banner).toHaveTextContent('Error!')\n})\n```\n\nWe recommend to always use `expect.element` when working with `page.getBy*` locators to reduce test flakiness. Note that `expect.element` accepts a second option:\n\n```ts\ninterface ExpectPollOptions {\n  // The interval to retry the assertion for in milliseconds\n  // Defaults to \"expect.poll.interval\" config option\n  interval?: number\n  // Time to retry the assertion for in milliseconds\n  // Defaults to \"expect.poll.timeout\" config option\n  timeout?: number\n  // The message printed when the assertion fails\n  message?: string\n}\n```\n\n::: tip\n`expect.element` is a shorthand for `expect.poll(() => element)` and works in exactly the same way.\n\n`toHaveTextContent` and all other assertions are still available on a regular `expect` without a built-in retry-ability mechanism:\n\n```ts\n// will fail immediately if .textContent is not `'Error!'`\nexpect(banner).toHaveTextContent('Error!')\n```\n:::\n\n## toBeDisabled\n\n```ts\nfunction toBeDisabled(): Promise<void>\n```\n\nAllows you to check whether an element is disabled from the user's perspective.\n\nMatches if the element is a form control and the `disabled` attribute is specified on this element or the\nelement is a descendant of a form element with a `disabled` attribute.\n\nNote that only native control elements such as HTML `button`, `input`, `select`, `textarea`, `option`, `optgroup`\ncan be disabled by setting \"disabled\" attribute. \"disabled\" attribute on other elements is ignored, unless it's a custom element.\n\n```html\n<button\n  data-testid=\"button\"\n  type=\"submit\"\n  disabled\n>\n  submit\n</button>\n```\n\n```ts\nawait expect.element(getByTestId('button')).toBeDisabled() // ✅\nawait expect.element(getByTestId('button')).not.toBeDisabled() // ❌\n```\n\n## toBeEnabled\n\n```ts\nfunction toBeEnabled(): Promise<void>\n```\n\nAllows you to check whether an element is not disabled from the user's perspective.\n\nWorks like [`not.toBeDisabled()`](#tobedisabled). Use this matcher to avoid double negation in your tests.\n\n```html\n<button\n  data-testid=\"button\"\n  type=\"submit\"\n  disabled\n>\n  submit\n</button>\n```\n\n```ts\nawait expect.element(getByTestId('button')).toBeEnabled() // ✅\nawait expect.element(getByTestId('button')).not.toBeEnabled() // ❌\n```\n\n## toBeEmptyDOMElement\n\n```ts\nfunction toBeEmptyDOMElement(): Promise<void>\n```\n\nThis allows you to assert whether an element has no visible content for the user. It ignores comments but will fail if the element contains white-space.\n\n```html\n<span data-testid=\"not-empty\"><span data-testid=\"empty\"></span></span>\n<span data-testid=\"with-whitespace\"> </span>\n<span data-testid=\"with-comment\"><!-- comment --></span>\n```\n\n```ts\nawait expect.element(getByTestId('empty')).toBeEmptyDOMElement()\nawait expect.element(getByTestId('not-empty')).not.toBeEmptyDOMElement()\nawait expect.element(\n  getByTestId('with-whitespace')\n).not.toBeEmptyDOMElement()\n```\n\n## toBeInTheDocument\n\n```ts\nfunction toBeInTheDocument(): Promise<void>\n```\n\nAssert whether an element is present in the document or not.\n\n```html\n<svg data-testid=\"svg-element\"></svg>\n```\n\n```ts\nawait expect.element(getByTestId('svg-element')).toBeInTheDocument()\nawait expect.element(getByTestId('does-not-exist')).not.toBeInTheDocument()\n```\n\n::: warning\nThis matcher does not find detached elements. The element must be added to the document to be found by `toBeInTheDocument`. If you desire to search in a detached element, please use: [`toContainElement`](#tocontainelement).\n:::\n\n## toBeInvalid\n\n```ts\nfunction toBeInvalid(): Promise<void>\n```\n\nThis allows you to check if an element, is currently invalid.\n\nAn element is invalid if it has an [`aria-invalid` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-invalid) with no value or a value of `\"true\"`, or if the result of [`checkValidity()`](https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation) is `false`.\n\n```html\n<input data-testid=\"no-aria-invalid\" />\n<input data-testid=\"aria-invalid\" aria-invalid />\n<input data-testid=\"aria-invalid-value\" aria-invalid=\"true\" />\n<input data-testid=\"aria-invalid-false\" aria-invalid=\"false\" />\n\n<form data-testid=\"valid-form\">\n  <input />\n</form>\n\n<form data-testid=\"invalid-form\">\n  <input required />\n</form>\n```\n\n```ts\nawait expect.element(getByTestId('no-aria-invalid')).not.toBeInvalid()\nawait expect.element(getByTestId('aria-invalid')).toBeInvalid()\nawait expect.element(getByTestId('aria-invalid-value')).toBeInvalid()\nawait expect.element(getByTestId('aria-invalid-false')).not.toBeInvalid()\n\nawait expect.element(getByTestId('valid-form')).not.toBeInvalid()\nawait expect.element(getByTestId('invalid-form')).toBeInvalid()\n```\n\n## toBeRequired\n\n```ts\nfunction toBeRequired(): Promise<void>\n```\n\nThis allows you to check if a form element is currently required.\n\nAn element is required if it is having a `required` or `aria-required=\"true\"` attribute.\n\n```html\n<input data-testid=\"required-input\" required />\n<input data-testid=\"aria-required-input\" aria-required=\"true\" />\n<input data-testid=\"conflicted-input\" required aria-required=\"false\" />\n<input data-testid=\"aria-not-required-input\" aria-required=\"false\" />\n<input data-testid=\"optional-input\" />\n<input data-testid=\"unsupported-type\" type=\"image\" required />\n<select data-testid=\"select\" required></select>\n<textarea data-testid=\"textarea\" required></textarea>\n<div data-testid=\"supported-role\" role=\"tree\" required></div>\n<div data-testid=\"supported-role-aria\" role=\"tree\" aria-required=\"true\"></div>\n```\n\n```ts\nawait expect.element(getByTestId('required-input')).toBeRequired()\nawait expect.element(getByTestId('aria-required-input')).toBeRequired()\nawait expect.element(getByTestId('conflicted-input')).toBeRequired()\nawait expect.element(getByTestId('aria-not-required-input')).not.toBeRequired()\nawait expect.element(getByTestId('optional-input')).not.toBeRequired()\nawait expect.element(getByTestId('unsupported-type')).not.toBeRequired()\nawait expect.element(getByTestId('select')).toBeRequired()\nawait expect.element(getByTestId('textarea')).toBeRequired()\nawait expect.element(getByTestId('supported-role')).not.toBeRequired()\nawait expect.element(getByTestId('supported-role-aria')).toBeRequired()\n```\n\n## toBeValid\n\n```ts\nfunction toBeValid(): Promise<void>\n```\n\nThis allows you to check if the value of an element, is currently valid.\n\nAn element is valid if it has no [`aria-invalid` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-invalid) or an attribute value of \"false\". The result of [`checkValidity()`](https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation) must also be `true` if it's a form element.\n\n```html\n<input data-testid=\"no-aria-invalid\" />\n<input data-testid=\"aria-invalid\" aria-invalid />\n<input data-testid=\"aria-invalid-value\" aria-invalid=\"true\" />\n<input data-testid=\"aria-invalid-false\" aria-invalid=\"false\" />\n\n<form data-testid=\"valid-form\">\n  <input />\n</form>\n\n<form data-testid=\"invalid-form\">\n  <input required />\n</form>\n```\n\n```ts\nawait expect.element(getByTestId('no-aria-invalid')).toBeValid()\nawait expect.element(getByTestId('aria-invalid')).not.toBeValid()\nawait expect.element(getByTestId('aria-invalid-value')).not.toBeValid()\nawait expect.element(getByTestId('aria-invalid-false')).toBeValid()\n\nawait expect.element(getByTestId('valid-form')).toBeValid()\nawait expect.element(getByTestId('invalid-form')).not.toBeValid()\n```\n\n## toBeVisible\n\n```ts\nfunction toBeVisible(): Promise<void>\n```\n\nThis allows you to check if an element is currently visible to the user.\n\nElement is considered visible when it has non-empty bounding box and does not have `visibility:hidden` computed style.\n\nNote that according to this definition:\n\n- Elements of zero size **are not** considered visible.\n- Elements with `display:none` **are not** considered visible.\n- Elements with `opacity:0` **are** considered visible.\n\nTo check that at least one element from the list is visible, use `locator.first()`.\n\n```ts\n// A specific element is visible.\nawait expect.element(page.getByText('Welcome')).toBeVisible()\n\n// At least one item in the list is visible.\nawait expect.element(page.getByTestId('todo-item').first()).toBeVisible()\n\n// At least one of the two elements is visible, possibly both.\nawait expect.element(\n  page.getByRole('button', { name: 'Sign in' })\n    .or(page.getByRole('button', { name: 'Sign up' }))\n    .first()\n).toBeVisible()\n```\n\n## toBeInViewport <Version>4.0.0</Version> {#tobeinviewport}\n\n```ts\nfunction toBeInViewport(options: { ratio?: number }): Promise<void>\n```\n\nThis allows you to check if an element is currently in viewport with [IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).\n\nYou can pass `ratio` argument as option, which means the minimal ratio of the element should be in viewport. `ratio` should be in 0~1.\n\n```ts\n// A specific element is in viewport.\nawait expect.element(page.getByText('Welcome')).toBeInViewport()\n\n// 50% of a specific element should be in viewport\nawait expect.element(page.getByText('To')).toBeInViewport({ ratio: 0.5 })\n\n// Full of a specific element should be in viewport\nawait expect.element(page.getByText('Vitest')).toBeInViewport({ ratio: 1 })\n```\n\n## toContainElement\n\n```ts\nfunction toContainElement(element: HTMLElement | SVGElement | Locator | null): Promise<void>\n```\n\nThis allows you to assert whether an element contains another element as a descendant or not.\n\n```html\n<span data-testid=\"ancestor\"><span data-testid=\"descendant\"></span></span>\n```\n\n```ts\nconst ancestor = getByTestId('ancestor')\nconst descendant = getByTestId('descendant')\nconst nonExistantElement = getByTestId('does-not-exist')\n\nawait expect.element(ancestor).toContainElement(descendant)\nawait expect.element(descendant).not.toContainElement(ancestor)\nawait expect.element(ancestor).not.toContainElement(nonExistantElement)\n```\n\n## toContainHTML\n\n```ts\nfunction toContainHTML(htmlText: string): Promise<void>\n```\n\nAssert whether a string representing a HTML element is contained in another element. The string should contain valid html, and not any incomplete html.\n\n```html\n<span data-testid=\"parent\"><span data-testid=\"child\"></span></span>\n```\n\n```ts\n// These are valid usages\nawait expect.element(getByTestId('parent')).toContainHTML('<span data-testid=\"child\"></span>')\nawait expect.element(getByTestId('parent')).toContainHTML('<span data-testid=\"child\" />')\nawait expect.element(getByTestId('parent')).not.toContainHTML('<br />')\n\n// These won't work\nawait expect.element(getByTestId('parent')).toContainHTML('data-testid=\"child\"')\nawait expect.element(getByTestId('parent')).toContainHTML('data-testid')\nawait expect.element(getByTestId('parent')).toContainHTML('</span>')\n```\n\n::: warning\nChances are you probably do not need to use this matcher. We encourage testing from the perspective of how the user perceives the app in a browser. That's why testing against a specific DOM structure is not advised.\n\nIt could be useful in situations where the code being tested renders html that was obtained from an external source, and you want to validate that html code was used as intended.\n\nIt should not be used to check DOM structure that you control. Please, use [`toContainElement`](#tocontainelement) instead.\n:::\n\n## toHaveAccessibleDescription\n\n```ts\nfunction toHaveAccessibleDescription(description?: string | RegExp): Promise<void>\n```\n\nThis allows you to assert that an element has the expected\n[accessible description](https://w3c.github.io/accname/).\n\nYou can pass the exact string of the expected accessible description, or you can\nmake a partial match passing a regular expression, or by using\n[`expect.stringContaining`](/api/expect#expect-stringcontaining) or [`expect.stringMatching`](/api/expect#expect-stringmatching).\n\n```html\n<a\n  data-testid=\"link\"\n  href=\"/\"\n  aria-label=\"Home page\"\n  title=\"A link to start over\"\n  >Start</a\n>\n<a data-testid=\"extra-link\" href=\"/about\" aria-label=\"About page\">About</a>\n<img src=\"avatar.jpg\" data-testid=\"avatar\" alt=\"User profile pic\" />\n<img\n  src=\"logo.jpg\"\n  data-testid=\"logo\"\n  alt=\"Company logo\"\n  aria-describedby=\"t1\"\n/>\n<span id=\"t1\" role=\"presentation\">The logo of Our Company</span>\n<img\n  src=\"logo.jpg\"\n  data-testid=\"logo2\"\n  alt=\"Company logo\"\n  aria-description=\"The logo of Our Company\"\n/>\n```\n\n```ts\nawait expect.element(getByTestId('link')).toHaveAccessibleDescription()\nawait expect.element(getByTestId('link')).toHaveAccessibleDescription('A link to start over')\nawait expect.element(getByTestId('link')).not.toHaveAccessibleDescription('Home page')\nawait expect.element(getByTestId('extra-link')).not.toHaveAccessibleDescription()\nawait expect.element(getByTestId('avatar')).not.toHaveAccessibleDescription()\nawait expect.element(getByTestId('logo')).not.toHaveAccessibleDescription('Company logo')\nawait expect.element(getByTestId('logo')).toHaveAccessibleDescription(\n  'The logo of Our Company',\n)\nawait expect.element(getByTestId('logo2')).toHaveAccessibleDescription(\n  'The logo of Our Company',\n)\n```\n\n## toHaveAccessibleErrorMessage\n\n```ts\nfunction toHaveAccessibleErrorMessage(message?: string | RegExp): Promise<void>\n```\n\nThis allows you to assert that an element has the expected\n[accessible error message](https://w3c.github.io/aria/#aria-errormessage).\n\nYou can pass the exact string of the expected accessible error message.\nAlternatively, you can perform a partial match by passing a regular expression\nor by using\n[`expect.stringContaining`](/api/expect#expect-stringcontaining) or [`expect.stringMatching`](/api/expect#expect-stringmatching).\n\n```html\n<input\n  aria-label=\"Has Error\"\n  aria-invalid=\"true\"\n  aria-errormessage=\"error-message\"\n/>\n<div id=\"error-message\" role=\"alert\">This field is invalid</div>\n\n<input aria-label=\"No Error Attributes\" />\n<input\n  aria-label=\"Not Invalid\"\n  aria-invalid=\"false\"\n  aria-errormessage=\"error-message\"\n/>\n```\n\n```ts\n// Inputs with Valid Error Messages\nawait expect.element(getByRole('textbox', { name: 'Has Error' })).toHaveAccessibleErrorMessage()\nawait expect.element(getByRole('textbox', { name: 'Has Error' })).toHaveAccessibleErrorMessage(\n  'This field is invalid',\n)\nawait expect.element(getByRole('textbox', { name: 'Has Error' })).toHaveAccessibleErrorMessage(\n  /invalid/i,\n)\nawait expect.element(\n  getByRole('textbox', { name: 'Has Error' }),\n).not.toHaveAccessibleErrorMessage('This field is absolutely correct!')\n\n// Inputs without Valid Error Messages\nawait expect.element(\n  getByRole('textbox', { name: 'No Error Attributes' }),\n).not.toHaveAccessibleErrorMessage()\n\nawait expect.element(\n  getByRole('textbox', { name: 'Not Invalid' }),\n).not.toHaveAccessibleErrorMessage()\n```\n\n## toHaveAccessibleName\n\n```ts\nfunction toHaveAccessibleName(name?: string | RegExp): Promise<void>\n```\n\nThis allows you to assert that an element has the expected\n[accessible name](https://w3c.github.io/accname/). It is useful, for instance,\nto assert that form elements and buttons are properly labelled.\n\nYou can pass the exact string of the expected accessible name, or you can make a\npartial match passing a regular expression, or by using\n[`expect.stringContaining`](/api/expect#expect-stringcontaining) or [`expect.stringMatching`](/api/expect#expect-stringmatching).\n\n```html\n<img data-testid=\"img-alt\" src=\"\" alt=\"Test alt\" />\n<img data-testid=\"img-empty-alt\" src=\"\" alt=\"\" />\n<svg data-testid=\"svg-title\"><title>Test title</title></svg>\n<button data-testid=\"button-img-alt\"><img src=\"\" alt=\"Test\" /></button>\n<p><img data-testid=\"img-paragraph\" src=\"\" alt=\"\" /> Test content</p>\n<button data-testid=\"svg-button\"><svg><title>Test</title></svg></p>\n<div><svg data-testid=\"svg-without-title\"></svg></div>\n<input data-testid=\"input-title\" title=\"test\" />\n```\n\n```javascript\nawait expect.element(getByTestId('img-alt')).toHaveAccessibleName('Test alt')\nawait expect.element(getByTestId('img-empty-alt')).not.toHaveAccessibleName()\nawait expect.element(getByTestId('svg-title')).toHaveAccessibleName('Test title')\nawait expect.element(getByTestId('button-img-alt')).toHaveAccessibleName()\nawait expect.element(getByTestId('img-paragraph')).not.toHaveAccessibleName()\nawait expect.element(getByTestId('svg-button')).toHaveAccessibleName()\nawait expect.element(getByTestId('svg-without-title')).not.toHaveAccessibleName()\nawait expect.element(getByTestId('input-title')).toHaveAccessibleName()\n```\n\n## toHaveAttribute\n\n```ts\nfunction toHaveAttribute(attribute: string, value?: unknown): Promise<void>\n```\n\nThis allows you to check whether the given element has an attribute or not. You\ncan also optionally check that the attribute has a specific expected value or\npartial match using [`expect.stringContaining`](/api/expect#expect-stringcontaining) or [`expect.stringMatching`](/api/expect#expect-stringmatching).\n\n```html\n<button data-testid=\"ok-button\" type=\"submit\" disabled>ok</button>\n```\n\n```ts\nconst button = getByTestId('ok-button')\n\nawait expect.element(button).toHaveAttribute('disabled')\nawait expect.element(button).toHaveAttribute('type', 'submit')\nawait expect.element(button).not.toHaveAttribute('type', 'button')\n\nawait expect.element(button).toHaveAttribute(\n  'type',\n  expect.stringContaining('sub')\n)\nawait expect.element(button).toHaveAttribute(\n  'type',\n  expect.not.stringContaining('but')\n)\n```\n\n## toHaveClass\n\n```ts\nfunction toHaveClass(...classNames: string[], options?: { exact: boolean }): Promise<void>\nfunction toHaveClass(...classNames: (string | RegExp)[]): Promise<void>\n```\n\nThis allows you to check whether the given element has certain classes within\nits `class` attribute. You must provide at least one class, unless you are\nasserting that an element does not have any classes.\n\nThe list of class names may include strings and regular expressions. Regular\nexpressions are matched against each individual class in the target element, and\nit is NOT matched against its full `class` attribute value as whole.\n\n::: warning\nNote that you cannot use `exact: true` option when only regular expressions are provided.\n:::\n\n```html\n<button data-testid=\"delete-button\" class=\"btn extra btn-danger\">\n  Delete item\n</button>\n<button data-testid=\"no-classes\">No Classes</button>\n```\n\n```ts\nconst deleteButton = getByTestId('delete-button')\nconst noClasses = getByTestId('no-classes')\n\nawait expect.element(deleteButton).toHaveClass('extra')\nawait expect.element(deleteButton).toHaveClass('btn-danger btn')\nawait expect.element(deleteButton).toHaveClass(/danger/, 'btn')\nawait expect.element(deleteButton).toHaveClass('btn-danger', 'btn')\nawait expect.element(deleteButton).not.toHaveClass('btn-link')\nawait expect.element(deleteButton).not.toHaveClass(/link/)\n\n// ⚠️ regexp matches against individual classes, not the whole classList\nawait expect.element(deleteButton).not.toHaveClass(/btn extra/)\n\n// the element has EXACTLY a set of classes (in any order)\nawait expect.element(deleteButton).toHaveClass('btn-danger extra btn', {\n  exact: true\n})\n// if it has more than expected it is going to fail\nawait expect.element(deleteButton).not.toHaveClass('btn-danger extra', {\n  exact: true\n})\n\nawait expect.element(noClasses).not.toHaveClass()\n```\n\n## toHaveFocus\n\n```ts\nfunction toHaveFocus(): Promise<void>\n```\n\nThis allows you to assert whether an element has focus or not.\n\n```html\n<div><input type=\"text\" data-testid=\"element-to-focus\" /></div>\n```\n\n```ts\nconst input = page.getByTestId('element-to-focus')\ninput.element().focus()\nawait expect.element(input).toHaveFocus()\ninput.element().blur()\nawait expect.element(input).not.toHaveFocus()\n```\n\n## toHaveFormValues\n\n```ts\nfunction toHaveFormValues(expectedValues: Record<string, unknown>): Promise<void>\n```\n\nThis allows you to check if a form or fieldset contains form controls for each given name, and having the specified value.\n\n::: tip\nIt is important to stress that this matcher can only be invoked on a [form](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement) or a [fieldset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFieldSetElement) element.\n\nThis allows it to take advantage of the [`.elements`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements) property in `form` and `fieldset` to reliably fetch all form controls within them.\n\nThis also avoids the possibility that users provide a container that contains more than one `form`, thereby intermixing form controls that are not related, and could even conflict with one another.\n:::\n\nThis matcher abstracts away the particularities with which a form control value\nis obtained depending on the type of form control. For instance, `<input>`\nelements have a `value` attribute, but `<select>` elements do not. Here's a list\nof all cases covered:\n\n- `<input type=\"number\">` elements return the value as a **number**, instead of\n  a string.\n- `<input type=\"checkbox\">` elements:\n  - if there's a single one with the given `name` attribute, it is treated as a\n    **boolean**, returning `true` if the checkbox is checked, `false` if\n    unchecked.\n  - if there's more than one checkbox with the same `name` attribute, they are\n    all treated collectively as a single form control, which returns the value\n    as an **array** containing all the values of the selected checkboxes in the\n    collection.\n- `<input type=\"radio\">` elements are all grouped by the `name` attribute, and\n  such a group treated as a single form control. This form control returns the\n  value as a **string** corresponding to the `value` attribute of the selected\n  radio button within the group.\n- `<input type=\"text\">` elements return the value as a **string**. This also\n  applies to `<input>` elements having any other possible `type` attribute\n  that's not explicitly covered in different rules above (e.g. `search`,\n  `email`, `date`, `password`, `hidden`, etc.)\n- `<select>` elements without the `multiple` attribute return the value as a\n  **string** corresponding to the `value` attribute of the selected `option`, or\n  `undefined` if there's no selected option.\n- `<select multiple>` elements return the value as an **array** containing all\n  the values of the [selected options](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/selectedOptions).\n- `<textarea>` elements return their value as a **string**. The value\n  corresponds to their node content.\n\nThe above rules make it easy, for instance, to switch from using a single select\ncontrol to using a group of radio buttons. Or to switch from a multi select\ncontrol, to using a group of checkboxes. The resulting set of form values used\nby this matcher to compare against would be the same.\n\n```html\n<form data-testid=\"login-form\">\n  <input type=\"text\" name=\"username\" value=\"jane.doe\" />\n  <input type=\"password\" name=\"password\" value=\"12345678\" />\n  <input type=\"checkbox\" name=\"rememberMe\" checked />\n  <button type=\"submit\">Sign in</button>\n</form>\n```\n\n```ts\nawait expect.element(getByTestId('login-form')).toHaveFormValues({\n  username: 'jane.doe',\n  rememberMe: true,\n})\n```\n\n## toHaveStyle\n\n```ts\nfunction toHaveStyle(css: string | Partial<CSSStyleDeclaration>): Promise<void>\n```\n\nThis allows you to check if a certain element has some specific css properties\nwith specific values applied. It matches only if the element has _all_ the\nexpected properties applied, not just some of them.\n\n```html\n<button\n  data-testid=\"delete-button\"\n  style=\"display: none; background-color: red\"\n>\n  Delete item\n</button>\n```\n\n```ts\nconst button = getByTestId('delete-button')\n\nawait expect.element(button).toHaveStyle('display: none')\nawait expect.element(button).toHaveStyle({ display: 'none' })\nawait expect.element(button).toHaveStyle(`\n  background-color: red;\n  display: none;\n`)\nawait expect.element(button).toHaveStyle({\n  backgroundColor: 'red',\n  display: 'none',\n})\nawait expect.element(button).not.toHaveStyle(`\n  background-color: blue;\n  display: none;\n`)\nawait expect.element(button).not.toHaveStyle({\n  backgroundColor: 'blue',\n  display: 'none',\n})\n```\n\nThis also works with rules that are applied to the element via a class name for\nwhich some rules are defined in a stylesheet currently active in the document.\nThe usual rules of css precedence apply.\n\n## toHaveTextContent\n\n```ts\nfunction toHaveTextContent(\n  text: string | RegExp,\n  options?: { normalizeWhitespace: boolean }\n): Promise<void>\n```\n\nThis allows you to check whether the given node has a text content or not. This\nsupports elements, but also text nodes and fragments.\n\nWhen a `string` argument is passed through, it will perform a partial\ncase-sensitive match to the node content.\n\nTo perform a case-insensitive match, you can use a `RegExp` with the `/i`\nmodifier.\n\nIf you want to match the whole content, you can use a `RegExp` to do it.\n\n```html\n<span data-testid=\"text-content\">Text Content</span>\n```\n\n```ts\nconst element = getByTestId('text-content')\n\nawait expect.element(element).toHaveTextContent('Content')\n// to match the whole content\nawait expect.element(element).toHaveTextContent(/^Text Content$/)\n// to use case-insensitive match\nawait expect.element(element).toHaveTextContent(/content$/i)\nawait expect.element(element).not.toHaveTextContent('content')\n```\n\n## toHaveValue\n\n```ts\nfunction toHaveValue(value: string | string[] | number | null): Promise<void>\n```\n\nThis allows you to check whether the given form element has the specified value.\nIt accepts `<input>`, `<select>` and `<textarea>` elements with the exception of\n`<input type=\"checkbox\">` and `<input type=\"radio\">`, which can be meaningfully\nmatched only using [`toBeChecked`](#tobechecked) or\n[`toHaveFormValues`](#tohaveformvalues).\n\nIt also accepts elements with roles `meter`, `progressbar`, `slider` or\n`spinbutton` and checks their `aria-valuenow` attribute (as a number).\n\nFor all other form elements, the value is matched using the same algorithm as in\n[`toHaveFormValues`](#tohaveformvalues) does.\n\n```html\n<input type=\"text\" value=\"text\" data-testid=\"input-text\" />\n<input type=\"number\" value=\"5\" data-testid=\"input-number\" />\n<input type=\"text\" data-testid=\"input-empty\" />\n<select multiple data-testid=\"select-number\">\n  <option value=\"first\">First Value</option>\n  <option value=\"second\" selected>Second Value</option>\n  <option value=\"third\" selected>Third Value</option>\n</select>\n```\n\n```ts\nconst textInput = getByTestId('input-text')\nconst numberInput = getByTestId('input-number')\nconst emptyInput = getByTestId('input-empty')\nconst selectInput = getByTestId('select-number')\n\nawait expect.element(textInput).toHaveValue('text')\nawait expect.element(numberInput).toHaveValue(5)\nawait expect.element(emptyInput).not.toHaveValue()\nawait expect.element(selectInput).toHaveValue(['second', 'third'])\n```\n\n## toHaveDisplayValue\n\n```typescript\nfunction toHaveDisplayValue(\n  value: string | RegExp | (string | RegExp)[]\n): Promise<void>\n```\n\nThis allows you to check whether the given form element has the specified\ndisplayed value (the one the end user will see). It accepts `<input>`,\n`<select>` and `<textarea>` elements with the exception of\n`<input type=\"checkbox\">` and `<input type=\"radio\">`, which can be meaningfully\nmatched only using [`toBeChecked`](#tobechecked) or\n[`toHaveFormValues`](#tohaveformvalues).\n\n```html\n<label for=\"input-example\">First name</label>\n<input type=\"text\" id=\"input-example\" value=\"Luca\" />\n\n<label for=\"textarea-example\">Description</label>\n<textarea id=\"textarea-example\">An example description here.</textarea>\n\n<label for=\"single-select-example\">Fruit</label>\n<select id=\"single-select-example\">\n  <option value=\"\">Select a fruit...</option>\n  <option value=\"banana\">Banana</option>\n  <option value=\"ananas\">Ananas</option>\n  <option value=\"avocado\">Avocado</option>\n</select>\n\n<label for=\"multiple-select-example\">Fruits</label>\n<select id=\"multiple-select-example\" multiple>\n  <option value=\"\">Select a fruit...</option>\n  <option value=\"banana\" selected>Banana</option>\n  <option value=\"ananas\">Ananas</option>\n  <option value=\"avocado\" selected>Avocado</option>\n</select>\n```\n\n```ts\nconst input = page.getByLabelText('First name')\nconst textarea = page.getByLabelText('Description')\nconst selectSingle = page.getByLabelText('Fruit')\nconst selectMultiple = page.getByLabelText('Fruits')\n\nawait expect.element(input).toHaveDisplayValue('Luca')\nawait expect.element(input).toHaveDisplayValue(/Luc/)\nawait expect.element(textarea).toHaveDisplayValue('An example description here.')\nawait expect.element(textarea).toHaveDisplayValue(/example/)\nawait expect.element(selectSingle).toHaveDisplayValue('Select a fruit...')\nawait expect.element(selectSingle).toHaveDisplayValue(/Select/)\nawait expect.element(selectMultiple).toHaveDisplayValue([/Avocado/, 'Banana'])\n```\n\n## toBeChecked\n\n```ts\nfunction toBeChecked(): Promise<void>\n```\n\nThis allows you to check whether the given element is checked. It accepts an\n`input` of type `checkbox` or `radio` and elements with a `role` of `checkbox`,\n`radio` or `switch` with a valid `aria-checked` attribute of `\"true\"` or\n`\"false\"`.\n\n```html\n<input type=\"checkbox\" checked data-testid=\"input-checkbox-checked\" />\n<input type=\"checkbox\" data-testid=\"input-checkbox-unchecked\" />\n<div role=\"checkbox\" aria-checked=\"true\" data-testid=\"aria-checkbox-checked\" />\n<div\n  role=\"checkbox\"\n  aria-checked=\"false\"\n  data-testid=\"aria-checkbox-unchecked\"\n/>\n\n<input type=\"radio\" checked value=\"foo\" data-testid=\"input-radio-checked\" />\n<input type=\"radio\" value=\"foo\" data-testid=\"input-radio-unchecked\" />\n<div role=\"radio\" aria-checked=\"true\" data-testid=\"aria-radio-checked\" />\n<div role=\"radio\" aria-checked=\"false\" data-testid=\"aria-radio-unchecked\" />\n<div role=\"switch\" aria-checked=\"true\" data-testid=\"aria-switch-checked\" />\n<div role=\"switch\" aria-checked=\"false\" data-testid=\"aria-switch-unchecked\" />\n```\n\n```ts\nconst inputCheckboxChecked = getByTestId('input-checkbox-checked')\nconst inputCheckboxUnchecked = getByTestId('input-checkbox-unchecked')\nconst ariaCheckboxChecked = getByTestId('aria-checkbox-checked')\nconst ariaCheckboxUnchecked = getByTestId('aria-checkbox-unchecked')\nawait expect.element(inputCheckboxChecked).toBeChecked()\nawait expect.element(inputCheckboxUnchecked).not.toBeChecked()\nawait expect.element(ariaCheckboxChecked).toBeChecked()\nawait expect.element(ariaCheckboxUnchecked).not.toBeChecked()\n\nconst inputRadioChecked = getByTestId('input-radio-checked')\nconst inputRadioUnchecked = getByTestId('input-radio-unchecked')\nconst ariaRadioChecked = getByTestId('aria-radio-checked')\nconst ariaRadioUnchecked = getByTestId('aria-radio-unchecked')\nawait expect.element(inputRadioChecked).toBeChecked()\nawait expect.element(inputRadioUnchecked).not.toBeChecked()\nawait expect.element(ariaRadioChecked).toBeChecked()\nawait expect.element(ariaRadioUnchecked).not.toBeChecked()\n\nconst ariaSwitchChecked = getByTestId('aria-switch-checked')\nconst ariaSwitchUnchecked = getByTestId('aria-switch-unchecked')\nawait expect.element(ariaSwitchChecked).toBeChecked()\nawait expect.element(ariaSwitchUnchecked).not.toBeChecked()\n```\n\n## toBePartiallyChecked\n\n```typescript\nfunction toBePartiallyChecked(): Promise<void>\n```\n\nThis allows you to check whether the given element is partially checked. It\naccepts an `input` of type `checkbox` and elements with a `role` of `checkbox`\nwith a `aria-checked=\"mixed\"`, or `input` of type `checkbox` with\n`indeterminate` set to `true`\n\n```html\n<input type=\"checkbox\" aria-checked=\"mixed\" data-testid=\"aria-checkbox-mixed\" />\n<input type=\"checkbox\" checked data-testid=\"input-checkbox-checked\" />\n<input type=\"checkbox\" data-testid=\"input-checkbox-unchecked\" />\n<div role=\"checkbox\" aria-checked=\"true\" data-testid=\"aria-checkbox-checked\" />\n<div\n  role=\"checkbox\"\n  aria-checked=\"false\"\n  data-testid=\"aria-checkbox-unchecked\"\n/>\n<input type=\"checkbox\" data-testid=\"input-checkbox-indeterminate\" />\n```\n\n```ts\nconst ariaCheckboxMixed = getByTestId('aria-checkbox-mixed')\nconst inputCheckboxChecked = getByTestId('input-checkbox-checked')\nconst inputCheckboxUnchecked = getByTestId('input-checkbox-unchecked')\nconst ariaCheckboxChecked = getByTestId('aria-checkbox-checked')\nconst ariaCheckboxUnchecked = getByTestId('aria-checkbox-unchecked')\nconst inputCheckboxIndeterminate = getByTestId('input-checkbox-indeterminate')\n\nawait expect.element(ariaCheckboxMixed).toBePartiallyChecked()\nawait expect.element(inputCheckboxChecked).not.toBePartiallyChecked()\nawait expect.element(inputCheckboxUnchecked).not.toBePartiallyChecked()\nawait expect.element(ariaCheckboxChecked).not.toBePartiallyChecked()\nawait expect.element(ariaCheckboxUnchecked).not.toBePartiallyChecked()\n\ninputCheckboxIndeterminate.element().indeterminate = true\nawait expect.element(inputCheckboxIndeterminate).toBePartiallyChecked()\n```\n\n## toHaveRole\n\n```ts\nfunction toHaveRole(role: ARIARole): Promise<void>\n```\n\nThis allows you to assert that an element has the expected [role](https://www.w3.org/TR/html-aria/#docconformance).\n\nThis is useful in cases where you already have access to an element via some query other than the role itself, and want to make additional assertions regarding its accessibility.\n\nThe role can match either an explicit role (via the `role` attribute), or an implicit one via the [implicit ARIA semantics](https://www.w3.org/TR/html-aria/#docconformance).\n\n```html\n<button data-testid=\"button\">Continue</button>\n<div role=\"button\" data-testid=\"button-explicit\">Continue</button>\n<button role=\"switch button\" data-testid=\"button-explicit-multiple\">Continue</button>\n<a href=\"/about\" data-testid=\"link\">About</a>\n<a data-testid=\"link-invalid\">Invalid link<a/>\n```\n\n```ts\nawait expect.element(getByTestId('button')).toHaveRole('button')\nawait expect.element(getByTestId('button-explicit')).toHaveRole('button')\nawait expect.element(getByTestId('button-explicit-multiple')).toHaveRole('button')\nawait expect.element(getByTestId('button-explicit-multiple')).toHaveRole('switch')\nawait expect.element(getByTestId('link')).toHaveRole('link')\nawait expect.element(getByTestId('link-invalid')).not.toHaveRole('link')\nawait expect.element(getByTestId('link-invalid')).toHaveRole('generic')\n```\n\n::: warning\nRoles are matched literally by string equality, without inheriting from the ARIA role hierarchy. As a result, querying a superclass role like `checkbox` will not include elements with a subclass role like `switch`.\n\nAlso note that unlike `testing-library`, Vitest ignores all custom roles except the first valid one, following Playwright's behaviour:\n\n```jsx\n<div data-testid=\"switch\" role=\"switch alert\"></div>\n\nawait expect.element(getByTestId('switch')).toHaveRole('switch') // ✅\nawait expect.element(getByTestId('switch')).toHaveRole('alert') // ❌\n```\n:::\n\n## toHaveSelection\n\n```ts\nfunction toHaveSelection(selection?: string): Promise<void>\n```\n\nThis allows to assert that an element has a\n[text selection](https://developer.mozilla.org/en-US/docs/Web/API/Selection).\n\nThis is useful to check if text or part of the text is selected within an\nelement. The element can be either an input of type text, a textarea, or any\nother element that contains text, such as a paragraph, span, div etc.\n\n::: warning\nThe expected selection is a string, it does not allow to check for\nselection range indices.\n:::\n\n```html\n<div>\n  <input type=\"text\" value=\"text selected text\" data-testid=\"text\" />\n  <textarea data-testid=\"textarea\">text selected text</textarea>\n  <p data-testid=\"prev\">prev</p>\n  <p data-testid=\"parent\">\n    text <span data-testid=\"child\">selected</span> text\n  </p>\n  <p data-testid=\"next\">next</p>\n</div>\n```\n\n```ts\ngetByTestId('text').element().setSelectionRange(5, 13)\nawait expect.element(getByTestId('text')).toHaveSelection('selected')\n\ngetByTestId('textarea').element().setSelectionRange(0, 5)\nawait expect.element('textarea').toHaveSelection('text ')\n\nconst selection = document.getSelection()\nconst range = document.createRange()\nselection.removeAllRanges()\nselection.empty()\nselection.addRange(range)\n\n// selection of child applies to the parent as well\nrange.selectNodeContents(getByTestId('child').element())\nawait expect.element(getByTestId('child')).toHaveSelection('selected')\nawait expect.element(getByTestId('parent')).toHaveSelection('selected')\n\n// selection that applies from prev all, parent text before child, and part child.\nrange.setStart(getByTestId('prev').element(), 0)\nrange.setEnd(getByTestId('child').element().childNodes[0], 3)\nawait expect.element(queryByTestId('prev')).toHaveSelection('prev')\nawait expect.element(queryByTestId('child')).toHaveSelection('sel')\nawait expect.element(queryByTestId('parent')).toHaveSelection('text sel')\nawait expect.element(queryByTestId('next')).not.toHaveSelection()\n\n// selection that applies from part child, parent text after child and part next.\nrange.setStart(getByTestId('child').element().childNodes[0], 3)\nrange.setEnd(getByTestId('next').element().childNodes[0], 2)\nawait expect.element(queryByTestId('child')).toHaveSelection('ected')\nawait expect.element(queryByTestId('parent')).toHaveSelection('ected text')\nawait expect.element(queryByTestId('prev')).not.toHaveSelection()\nawait expect.element(queryByTestId('next')).toHaveSelection('ne')\n```\n\n## toMatchScreenshot <Badge type=\"warning\">experimental</Badge> {#tomatchscreenshot}\n\n```ts\nfunction toMatchScreenshot(\n  options?: ScreenshotMatcherOptions,\n): Promise<void>\nfunction toMatchScreenshot(\n  name?: string,\n  options?: ScreenshotMatcherOptions,\n): Promise<void>\n```\n\n::: tip\nThe `toMatchScreenshot` assertion can be configured globally in your\n[Vitest config](/config/browser/expect#tomatchscreenshot).\n:::\n\nThis assertion allows you to perform visual regression testing by comparing\nscreenshots of elements or pages against stored reference images.\n\nWhen differences are detected beyond the configured threshold, the test fails.\nTo help identify the changes, the assertion generates:\n\n- The actual screenshot captured during the test\n- The expected reference screenshot\n- A diff image highlighting the differences (when possible)\n\n::: warning Screenshots Stability\nThe assertion automatically retries taking screenshots until two consecutive\ncaptures yield the same result. This helps reduce flakiness caused by\nanimations, loading states, or other dynamic content. You can control this\nbehavior with the `timeout` option.\n\nHowever, browser rendering can vary across:\n\n- Different browsers and browser versions\n- Operating systems (Windows, macOS, Linux)\n- Screen resolutions and pixel densities\n- GPU drivers and hardware acceleration\n- Font rendering and system fonts\n\nIt is recommended to read the\n[Visual Regression Testing guide](/guide/browser/visual-regression-testing) to\nimplement this testing strategy efficiently.\n:::\n\n::: tip\nWhen a screenshot comparison fails due to **intentional changes**, you can\nupdate the reference screenshot by pressing the `u` key in watch mode, or by\nrunning tests with the `-u` or `--update` flags.\n:::\n\n```html\n<button data-testid=\"button\">Fancy Button</button>\n```\n\n```ts\n// basic usage, auto-generates screenshot name\nawait expect.element(getByTestId('button')).toMatchScreenshot()\n\n// with custom name\nawait expect.element(getByTestId('button')).toMatchScreenshot('fancy-button')\n\n// with options\nawait expect.element(getByTestId('button')).toMatchScreenshot({\n  comparatorName: 'pixelmatch',\n  comparatorOptions: {\n    allowedMismatchedPixelRatio: 0.01,\n  },\n})\n\n// with both name and options\nawait expect.element(getByTestId('button')).toMatchScreenshot('fancy-button', {\n  comparatorName: 'pixelmatch',\n  comparatorOptions: {\n    allowedMismatchedPixelRatio: 0.01,\n  },\n})\n```\n\n### Options\n\n- `comparatorName: \"pixelmatch\" = \"pixelmatch\"`\n\n  The algorithm/library used for comparing images.\n\n  `\"pixelmatch\"` is the only built-in comparator, but you can use custom ones by [registering them in the config file](/config/browser/expect#browser-expect-tomatchscreenshot-comparators).\n\n- `comparatorOptions: object`\n\n  These options allow changing the behavior of the comparator. What properties\n  can be set depends on the chosen comparator algorithm.\n\n  Vitest has set default values out of the box, but they can be overridden.\n\n  - [`\"pixelmatch\"` options](#pixelmatch-comparator-options)\n\n  ::: warning\n  **Always explicitly set `comparatorName` to get proper type inference for\n  `comparatorOptions`**.\n\n  Without it, TypeScript won't know which options are valid:\n\n  ```ts\n  // ❌ TypeScript can't infer the correct options\n  await expect.element(button).toMatchScreenshot({\n    comparatorOptions: {\n      // might error when new comparators are added\n      allowedMismatchedPixelRatio: 0.01,\n    },\n  })\n\n  // ✅ TypeScript knows these are pixelmatch options\n  await expect.element(button).toMatchScreenshot({\n    comparatorName: 'pixelmatch',\n    comparatorOptions: {\n      allowedMismatchedPixelRatio: 0.01,\n    },\n  })\n  ```\n  :::\n\n- `screenshotOptions: object`\n\n  The same options allowed by\n  [`locator.screenshot()`](/api/browser/locators.html#screenshot), except for:\n\n  - `'base64'`\n  - `'path'`\n  - `'save'`\n  - `'type'`\n\n- `timeout: number = 5_000`\n\n  Time to wait until a stable screenshot is found.\n\n  Setting this value to `0` disables the timeout, but if a stable screenshot\n  can't be determined the process will not end.\n\n#### `\"pixelmatch\"` comparator options\n\nThe `\"pixelmatch\"` comparator uses [`@blazediff/core`](https://blazediff.dev/docs/core) under the hood. The following options are available when using it:\n\n- `allowedMismatchedPixelRatio: number | undefined = undefined`\n\n  The maximum allowed ratio of differing pixels between the captured screenshot\n  and the reference image.\n\n  Must be a value between `0` and `1`.\n\n  For example, `allowedMismatchedPixelRatio: 0.02` means the test will pass\n  if up to 2% of pixels differ, but fail if more than 2% differ.\n\n- `allowedMismatchedPixels: number | undefined = undefined`\n\n  The maximum number of pixels that are allowed to differ between the captured\n  screenshot and the stored reference image.\n\n  If set to `undefined`, any non-zero difference will cause the test to fail.\n\n  For example, `allowedMismatchedPixels: 10` means the test will pass if 10 or\n  fewer pixels differ, but fail if 11 or more differ.\n\n- `threshold: number = 0.1`\n\n  Acceptable perceived color difference between the same pixel in two images.\n\n  Value ranges from `0` (strict) to `1` (very lenient). Lower values mean small\n  differences will be detected.\n\n  The comparison uses the [YIQ color space](https://en.wikipedia.org/wiki/YIQ).\n\n- `includeAA: boolean = false`\n\n  If `true`, disables detection and ignoring of anti-aliased pixels.\n\n- `alpha: number = 0.1`\n\n  Blending level of unchanged pixels in the diff image.\n\n  Ranges from `0` (white) to `1` (original brightness).\n\n- `aaColor: [r: number, g: number, b: number] = [255, 255, 0]`\n\n  Color used for anti-aliased pixels in the diff image.\n\n- `diffColor: [r: number, g: number, b: number] = [255, 0, 0]`\n\n  Color used for differing pixels in the diff image.\n\n- `diffColorAlt: [r: number, g: number, b: number] | undefined = undefined`\n\n  Optional alternative color for dark-on-light differences, to help show what's\n  added vs. removed.\n\n  If not set, `diffColor` is used for all differences.\n\n- `diffMask: boolean = false`\n\n  If `true`, shows only the diff as a mask on a transparent background, instead\n  of overlaying it on the original image.\n\n  Anti-aliased pixels won't be shown (if detected).\n\n::: warning\nWhen both `allowedMismatchedPixels` and `allowedMismatchedPixelRatio` are set,\nthe more restrictive value is used.\n\nFor example, if you allow 100 pixels or 2% ratio, and your image has 10,000\npixels, the effective limit would be 100 pixels instead of 200.\n:::\n"
  },
  {
    "path": "docs/api/browser/commands.md",
    "content": "---\ntitle: Commands | Browser Mode\noutline: deep\n---\n\n# Commands\n\nCommand is a function that invokes another function on the server and passes down the result back to the browser. Vitest exposes several built-in commands you can use in your browser tests.\n\n## Built-in Commands\n\n### Files Handling\n\nYou can use the `readFile`, `writeFile`, and `removeFile` APIs to handle files in your browser tests. Since Vitest 3.2, all paths are resolved relative to the [project](/guide/projects) root (which is `process.cwd()`, unless overridden manually). Previously, paths were resolved relative to the test file.\n\nBy default, Vitest uses `utf-8` encoding but you can override it with options.\n\n::: tip\nThis API follows [`server.fs`](https://vitejs.dev/config/server-options.html#server-fs-allow) limitations for security reasons.\n\nIf [`browser.api.allowWrite`](/config/browser/api) or [`api.allowWrite`](/config/api#api-allowwrite) are disabled, `writeFile` and `removeFile` functions won't do anything.\n:::\n\n```ts\nimport { server } from 'vitest/browser'\n\nconst { readFile, writeFile, removeFile } = server.commands\n\nit('handles files', async () => {\n  const file = './test.txt'\n\n  await writeFile(file, 'hello world')\n  const content = await readFile(file)\n\n  expect(content).toBe('hello world')\n\n  await removeFile(file)\n})\n```\n\n## CDP Session\n\nVitest exposes access to raw Chrome DevTools Protocol via the `cdp` method exported from `vitest/browser`. It is mostly useful to library authors to build tools on top of it.\n\n```ts\nimport { cdp } from 'vitest/browser'\n\nconst input = document.createElement('input')\ndocument.body.appendChild(input)\ninput.focus()\n\nawait cdp().send('Input.dispatchKeyEvent', {\n  type: 'keyDown',\n  text: 'a',\n})\n\nexpect(input).toHaveValue('a')\n```\n\n::: warning\nCDP session works only with `playwright` provider and only when using `chromium` browser. You can read more about it in playwright's [`CDPSession`](https://playwright.dev/docs/api/class-cdpsession) documentation.\n:::\n\n## Custom Commands\n\nYou can also add your own commands via [`browser.commands`](/config/browser/commands) config option. If you develop a library, you can provide them via a `config` hook inside a plugin:\n\n```ts\nimport type { Plugin } from 'vitest/config'\nimport type { BrowserCommand } from 'vitest/node'\n\nconst myCustomCommand: BrowserCommand<[arg1: string, arg2: string]> = ({\n  testPath,\n  provider\n}, arg1, arg2) => {\n  if (provider.name === 'playwright') {\n    console.log(testPath, arg1, arg2)\n    return { someValue: true }\n  }\n\n  throw new Error(`provider ${provider.name} is not supported`)\n}\n\nexport default function BrowserCommands(): Plugin {\n  return {\n    name: 'vitest:custom-commands',\n    config() {\n      return {\n        test: {\n          browser: {\n            commands: {\n              myCustomCommand,\n            }\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nThen you can call it inside your test by importing it from `vitest/browser`:\n\n```ts\nimport { commands } from 'vitest/browser'\nimport { expect, test } from 'vitest'\n\ntest('custom command works correctly', async () => {\n  const result = await commands.myCustomCommand('test1', 'test2')\n  expect(result).toEqual({ someValue: true })\n})\n\n// if you are using TypeScript, you can augment the module\ndeclare module 'vitest/browser' {\n  interface BrowserCommands {\n    myCustomCommand: (arg1: string, arg2: string) => Promise<{\n      someValue: true\n    }>\n  }\n}\n```\n\n::: warning\nCustom functions will override built-in ones if they have the same name.\n:::\n\n### Custom `playwright` commands\n\nVitest exposes several `playwright` specific properties on the command context.\n\n- `page` references the full page that contains the test iframe. This is the orchestrator HTML and you most likely shouldn't touch it to not break things.\n- `frame` is an async method that will resolve tester [`Frame`](https://playwright.dev/docs/api/class-frame). It has a similar API to the `page`, but it doesn't support certain methods. If you need to query an element, you should prefer using `context.iframe` instead because it is more stable and faster.\n- `iframe` is a [`FrameLocator`](https://playwright.dev/docs/api/class-framelocator) that should be used to query other elements on the page.\n- `context` refers to the unique [BrowserContext](https://playwright.dev/docs/api/class-browsercontext).\n\n```ts\nimport { BrowserCommand } from 'vitest/node'\n\nexport const myCommand: BrowserCommand<[string, number]> = async (\n  ctx,\n  arg1: string,\n  arg2: number\n) => {\n  if (ctx.provider.name === 'playwright') {\n    const element = await ctx.iframe.findByRole('alert')\n    const screenshot = await element.screenshot()\n    // do something with the screenshot\n    return difference\n  }\n}\n```\n\n### Custom `webdriverio` commands\n\nVitest exposes some `webdriverio` specific properties on the context object.\n\n- `browser` is the `WebdriverIO.Browser` API.\n\nVitest automatically switches the `webdriver` context to the test iframe by calling `browser.switchFrame` before the command is called, so `$` and `$$` methods refer to the elements inside the iframe, not in the orchestrator, but non-webdriver APIs will still refer to the parent frame context.\n"
  },
  {
    "path": "docs/api/browser/context.md",
    "content": "---\ntitle: Context API | Browser Mode\n---\n\n# Context API\n\nVitest exposes a context module via `vitest/browser` entry point. As of 2.0, it exposes a small set of utilities that might be useful to you in tests.\n\n## `userEvent`\n\n::: tip\nThe `userEvent` API is explained in detail at [Interactivity API](/api/browser/interactivity).\n:::\n\n```ts\n/**\n * Handler for user interactions. The support is implemented by the browser provider (`playwright` or `webdriverio`).\n * If used with `preview` provider, fallbacks to simulated events via `@testing-library/user-event`.\n * @experimental\n */\nexport const userEvent: {\n  setup: () => UserEvent\n  cleanup: () => Promise<void>\n  click: (element: Element, options?: UserEventClickOptions) => Promise<void>\n  dblClick: (element: Element, options?: UserEventDoubleClickOptions) => Promise<void>\n  tripleClick: (element: Element, options?: UserEventTripleClickOptions) => Promise<void>\n  selectOptions: (\n    element: Element,\n    values: HTMLElement | HTMLElement[] | string | string[],\n    options?: UserEventSelectOptions,\n  ) => Promise<void>\n  keyboard: (text: string) => Promise<void>\n  type: (element: Element, text: string, options?: UserEventTypeOptions) => Promise<void>\n  clear: (element: Element) => Promise<void>\n  tab: (options?: UserEventTabOptions) => Promise<void>\n  hover: (element: Element, options?: UserEventHoverOptions) => Promise<void>\n  unhover: (element: Element, options?: UserEventHoverOptions) => Promise<void>\n  fill: (element: Element, text: string, options?: UserEventFillOptions) => Promise<void>\n  dragAndDrop: (source: Element, target: Element, options?: UserEventDragAndDropOptions) => Promise<void>\n}\n```\n\n## `commands`\n\n::: tip\nThis API is explained in detail at [Commands API](/api/browser/commands).\n:::\n\n```ts\n/**\n * Available commands for the browser.\n * A shortcut to `server.commands`.\n */\nexport const commands: BrowserCommands\n```\n\n## `page`\n\nThe `page` export provides utilities to interact with the current `page`.\n\n::: warning\nWhile it exposes some utilities from Playwright's `page`, it is not the same object. Since the browser context is evaluated in the browser, your tests don't have access to Playwright's `page` because it runs on the server.\n\nUse [Commands API](/api/browser/commands) if you need to have access to Playwright's `page` object.\n:::\n\n```ts\nexport const page: {\n  /**\n   * Change the size of iframe's viewport.\n   */\n  viewport(width: number, height: number): Promise<void>\n  /**\n   * Make a screenshot of the test iframe or a specific element.\n   * @returns Path to the screenshot file or path and base64.\n   */\n  screenshot(options: Omit<ScreenshotOptions, 'base64'> & { base64: true }): Promise<{\n    path: string\n    base64: string\n  }>\n  screenshot(options?: ScreenshotOptions): Promise<string>\n  /**\n   * Add a trace marker when browser tracing is enabled.\n   */\n  mark(name: string, options?: { stack?: string }): Promise<void>\n  /**\n   * Group multiple operations under a trace marker when browser tracing is enabled.\n   */\n  mark<T>(name: string, body: () => T | Promise<T>, options?: { stack?: string }): Promise<T>\n  /**\n   * Extend default `page` object with custom methods.\n   */\n  extend(methods: Partial<BrowserPage>): BrowserPage\n  /**\n   * Wrap an HTML element in a `Locator`. When querying for elements, the search will always return this element.\n   */\n  elementLocator(element: Element): Locator\n  /**\n   * The iframe locator. This is a document locator that enters the iframe body\n   * and works similarly to the `page` object.\n   * **Warning:** At the moment, this is supported only by the `playwright` provider.\n   */\n  frameLocator(iframeElement: Locator): FrameLocator\n\n  /**\n   * Locator APIs. See its documentation for more details.\n   */\n  getByRole(role: ARIARole | string, options?: LocatorByRoleOptions): Locator\n  getByLabelText(text: string | RegExp, options?: LocatorOptions): Locator\n  getByTestId(text: string | RegExp): Locator\n  getByAltText(text: string | RegExp, options?: LocatorOptions): Locator\n  getByPlaceholder(text: string | RegExp, options?: LocatorOptions): Locator\n  getByText(text: string | RegExp, options?: LocatorOptions): Locator\n  getByTitle(text: string | RegExp, options?: LocatorOptions): Locator\n}\n```\n\n::: tip\nThe `getBy*` API is explained at [Locators API](/api/browser/locators).\n:::\n\n::: warning WARNING <Version>3.2.0</Version>\nNote that `screenshot` will always return a base64 string if `save` is set to `false`.\nThe `path` is also ignored in that case.\n:::\n\n### mark\n\n```ts\nfunction mark(name: string, options?: { stack?: string }): Promise<void>\nfunction mark<T>(\n  name: string,\n  body: () => T | Promise<T>,\n  options?: { stack?: string },\n): Promise<T>\n```\n\nAdds a named marker to the trace timeline for the current test.\n\nPass `options.stack` to override the callsite location in trace metadata. This is useful for wrapper libraries that need to preserve the end-user source location.\n\nIf you pass a callback, Vitest creates a trace group with this name, runs the callback, and closes the group automatically.\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.mark('before submit')\nawait page.getByRole('button', { name: 'Submit' }).click()\nawait page.mark('after submit')\n\nawait page.mark('submit flow', async () => {\n  await page.getByRole('textbox', { name: 'Email' }).fill('john@example.com')\n  await page.getByRole('button', { name: 'Submit' }).click()\n})\n```\n\n::: tip\nThis method is useful only when [`browser.trace`](/config/browser/trace) is enabled.\n:::\n\n### frameLocator\n\n```ts\nfunction frameLocator(iframeElement: Locator): FrameLocator\n```\n\nThe `frameLocator` method returns a `FrameLocator` instance that can be used to find elements inside the iframe.\n\nThe frame locator is similar to `page`. It does not refer to the Iframe HTML element, but to the iframe's document.\n\n```ts\nconst frame = page.frameLocator(\n  page.getByTestId('iframe')\n)\n\nawait frame.getByText('Hello World').click() // ✅\nawait frame.click() // ❌ Not available\n```\n\n::: danger IMPORTANT\nAt the moment, the `frameLocator` method is only supported by the `playwright` provider.\n\nThe interactive methods (like `click` or `fill`) are always available on elements within the iframe, but assertions with `expect.element` require the iframe to have the [same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy).\n:::\n\n## `cdp`\n\n```ts\nfunction cdp(): CDPSession\n```\n\nThe `cdp` export returns the current Chrome DevTools Protocol session. It is mostly useful to library authors to build tools on top of it.\n\n::: warning\nCDP session works only with `playwright` provider and only when using `chromium` browser. You can read more about it in playwright's [`CDPSession`](https://playwright.dev/docs/api/class-cdpsession) documentation.\n:::\n\n```ts\nexport const cdp: () => CDPSession\n```\n\n## `server`\n\nThe `server` export represents the Node.js environment where the Vitest server is running. It is mostly useful for debugging or limiting your tests based on the environment.\n\n```ts\nexport const server: {\n  /**\n   * Platform the Vitest server is running on.\n   * The same as calling `process.platform` on the server.\n   */\n  platform: Platform\n  /**\n   * Runtime version of the Vitest server.\n   * The same as calling `process.version` on the server.\n   */\n  version: string\n  /**\n   * Name of the browser provider.\n   */\n  provider: string\n  /**\n   * Name of the current browser.\n   */\n  browser: string\n  /**\n   * Available commands for the browser.\n   */\n  commands: BrowserCommands\n  /**\n   * Serialized test config.\n   */\n  config: SerializedConfig\n}\n```\n\n## `utils`\n\nUtility functions useful for custom render libraries.\n\n```ts\nexport const utils: {\n  /**\n   * This is simillar to calling `page.elementLocator`, but it returns only\n   * locator selectors.\n   */\n  getElementLocatorSelectors(element: Element): LocatorSelectors\n  /**\n   * Prints prettified HTML of an element.\n   */\n  debug(\n    el?: Element | Locator | null | (Element | Locator)[],\n    maxLength?: number,\n    options?: PrettyDOMOptions,\n  ): void\n  /**\n   * Returns prettified HTML of an element.\n   */\n  prettyDOM(\n    dom?: Element | Locator | undefined | null,\n    maxLength?: number,\n    prettyFormatOptions?: PrettyDOMOptions,\n  ): string\n  /**\n   * Configures default options of `prettyDOM` and `debug` functions.\n   * This will also affect `vitest-browser-{framework}` package.\n   */\n  configurePrettyDOM(options: StringifyOptions): void\n  /**\n   * Creates \"Cannot find element\" error. Useful for custom locators.\n   */\n  getElementError(selector: string, container?: Element): Error\n}\n```\n\n### configurePrettyDOM <Version>4.0.0</Version> {#configureprettydom}\n\nThe `configurePrettyDOM` function allows you to configure default options for the `prettyDOM` and `debug` functions. This is useful for customizing how HTML is formatted in test failure messages.\n\n```ts\nimport { utils } from 'vitest/browser'\n\nutils.configurePrettyDOM({\n  maxDepth: 3,\n  filterNode: 'script, style, [data-test-hide]'\n})\n```\n\n#### Options\n\n- **`maxDepth`** - Maximum depth to print nested elements (default: `Infinity`)\n- **`maxLength`** - Maximum length of the output string (default: `7000`)\n- **`filterNode`** - A CSS selector string or function to filter out nodes from the output. When a string is provided, elements matching the selector will be excluded. When a function is provided, it should return `false` to exclude a node.\n- **`highlight`** - Enable syntax highlighting (default: `true`)\n- And other options from [`pretty-format`](https://npmx.dev/package/@vitest/pretty-format)\n\n#### Filtering with CSS Selectors <Version>4.1.0</Version> {#filtering-with-css-selectors}\n\nThe `filterNode` option allows you to hide irrelevant markup (like scripts, styles, or hidden elements) from test failure messages, making it easier to identify the actual cause of failures.\n\n```ts\nimport { utils } from 'vitest/browser'\n\n// Filter out common noise elements\nutils.configurePrettyDOM({\n  filterNode: 'script, style, [data-test-hide]'\n})\n\n// Or use directly with prettyDOM\nconst html = utils.prettyDOM(element, undefined, {\n  filterNode: 'script, style'\n})\n```\n\n**Common Patterns:**\n\nFilter out scripts and styles:\n```ts\nutils.configurePrettyDOM({ filterNode: 'script, style' })\n```\n\nHide specific elements with data attributes:\n```ts\nutils.configurePrettyDOM({ filterNode: '[data-test-hide]' })\n```\n\nHide nested content within an element:\n```ts\n// Hides all children of elements with data-test-hide-content\nutils.configurePrettyDOM({ filterNode: '[data-test-hide-content] *' })\n```\n\nCombine multiple selectors:\n```ts\nutils.configurePrettyDOM({\n  filterNode: 'script, style, [data-test-hide], svg'\n})\n```\n\n::: tip\nThis feature is inspired by Testing Library's [`defaultIgnore`](https://testing-library.com/docs/dom-testing-library/api-configuration/#defaultignore) configuration.\n:::\n"
  },
  {
    "path": "docs/api/browser/interactivity.md",
    "content": "---\ntitle: Interactivity API | Browser Mode\n---\n\n# Interactivity API\n\nVitest implements a subset of [`@testing-library/user-event`](https://testing-library.com/docs/user-event/intro) APIs using [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) or [webdriver](https://www.w3.org/TR/webdriver/) instead of faking events which makes the browser behaviour more reliable and consistent with how users interact with a page.\n\n```ts\nimport { userEvent } from 'vitest/browser'\n\nawait userEvent.click(document.querySelector('.button'))\n```\n\nAlmost every `userEvent` method inherits its provider options.\n\n## userEvent.setup\n\n```ts\nfunction setup(): UserEvent\n```\n\nCreates a new user event instance. This is useful if you need to keep the state of keyboard to press and release buttons correctly.\n\n::: warning\nUnlike `@testing-library/user-event`, the default `userEvent` instance from `vitest/browser` is created once, not every time its methods are called! You can see the difference in how it works in this snippet:\n\n```ts\nimport { userEvent as vitestUserEvent } from 'vitest/browser'\nimport { userEvent as originalUserEvent } from '@testing-library/user-event'\n\nawait vitestUserEvent.keyboard('{Shift}') // press shift without releasing\nawait vitestUserEvent.keyboard('{/Shift}') // releases shift\n\nawait originalUserEvent.keyboard('{Shift}') // press shift without releasing\nawait originalUserEvent.keyboard('{/Shift}') // DID NOT release shift because the state is different\n```\n\nThis behaviour is more useful because we do not emulate the keyboard, we actually press the Shift, so keeping the original behaviour would cause unexpected issues when typing in the field.\n:::\n\n## userEvent.click\n\n```ts\nfunction click(\n  element: Element | Locator,\n  options?: UserEventClickOptions,\n): Promise<void>\n```\n\nClick on an element. Inherits provider's options. Please refer to your provider's documentation for detailed explanation about how this method works.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('clicks on an element', async () => {\n  const logo = page.getByRole('img', { name: /logo/ })\n\n  await userEvent.click(logo)\n  // or you can access it directly on the locator\n  await logo.click()\n\n  // With WebdriverIO, this uses either ElementClick (with no arguments) or\n  // actions (with arguments). Use an empty object to force the use of actions.\n  await logo.click({})\n})\n```\n\n### Clicking with a modifier\n\nWith either WebdriverIO or Playwright:\n\n```ts\nawait userEvent.keyboard('{Shift>}')\n// By using an empty object as the option, this opts in to using a chain of actions\n// instead of an ElementClick in webdriver.\n// Firefox has a bug that makes this necessary.\n// Follow https://bugzilla.mozilla.org/show_bug.cgi?id=1456642 to know when this\n// will be fixed.\nawait userEvent.click(element, {})\nawait userEvent.keyboard('{/Shift}')\n```\n\nWith Playwright:\n```ts\nawait userEvent.click(element, { modifiers: ['Shift'] })\n```\n\nReferences:\n\n- [Playwright `locator.click` API](https://playwright.dev/docs/api/class-locator#locator-click)\n- [WebdriverIO `element.click` API](https://webdriver.io/docs/api/element/click/)\n- [testing-library `click` API](https://testing-library.com/docs/user-event/convenience/#click)\n\n## userEvent.dblClick\n\n```ts\nfunction dblClick(\n  element: Element | Locator,\n  options?: UserEventDoubleClickOptions,\n): Promise<void>\n```\n\nTriggers a double click event on an element.\n\nPlease refer to your provider's documentation for detailed explanation about how this method works.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('triggers a double click on an element', async () => {\n  const logo = page.getByRole('img', { name: /logo/ })\n\n  await userEvent.dblClick(logo)\n  // or you can access it directly on the locator\n  await logo.dblClick()\n})\n```\n\nReferences:\n\n- [Playwright `locator.dblclick` API](https://playwright.dev/docs/api/class-locator#locator-dblclick)\n- [WebdriverIO `element.doubleClick` API](https://webdriver.io/docs/api/element/doubleClick/)\n- [testing-library `dblClick` API](https://testing-library.com/docs/user-event/convenience/#dblClick)\n\n## userEvent.tripleClick\n\n```ts\nfunction tripleClick(\n  element: Element | Locator,\n  options?: UserEventTripleClickOptions,\n): Promise<void>\n```\n\nTriggers a triple click event on an element. Since there is no `tripleclick` in browser api, this method will fire three click events in a row, and so you must check [click event detail](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event#usage_notes) to filter the event: `evt.detail === 3`.\n\nPlease refer to your provider's documentation for detailed explanation about how this method works.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('triggers a triple click on an element', async () => {\n  const logo = page.getByRole('img', { name: /logo/ })\n  let tripleClickFired = false\n  logo.addEventListener('click', (evt) => {\n    if (evt.detail === 3) {\n      tripleClickFired = true\n    }\n  })\n\n  await userEvent.tripleClick(logo)\n  // or you can access it directly on the locator\n  await logo.tripleClick()\n\n  expect(tripleClickFired).toBe(true)\n})\n```\n\nReferences:\n\n- [Playwright `locator.click` API](https://playwright.dev/docs/api/class-locator#locator-click): implemented via `click` with `clickCount: 3` .\n- [WebdriverIO `browser.action` API](https://webdriver.io/docs/api/browser/action/): implemented via actions api with `move` plus three `down + up + pause` events in a row\n- [testing-library `tripleClick` API](https://testing-library.com/docs/user-event/convenience/#tripleClick)\n\n## userEvent.wheel <Version>4.1.0</Version> {#userevent-wheel}\n\n```ts\nfunction wheel(\n  element: Element | Locator,\n  options: UserEventWheelOptions,\n): Promise<void>\n```\n\nTriggers a [`wheel` event](https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event) on an element.\n\nYou can specify the scroll amount using either `delta` for precise pixel-based control, or `direction` for simpler directional scrolling (`up`, `down`, `left`, `right`). When you need to trigger multiple wheel events, use the `times` option rather than calling the method multiple times for better performance.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('scroll using delta values', async () => {\n  const tablist = page.getByRole('tablist')\n\n  // Scroll right by 100 pixels\n  await userEvent.wheel(tablist, { delta: { x: 100 } })\n\n  // Scroll down by 50 pixels\n  await userEvent.wheel(tablist, { delta: { y: 50 } })\n\n  // Scroll diagonally 2 times\n  await userEvent.wheel(tablist, { delta: { x: 50, y: 100 }, times: 2 })\n})\n\ntest('scroll using direction', async () => {\n  const tablist = page.getByRole('tablist')\n\n  // Scroll right 5 times\n  await userEvent.wheel(tablist, { direction: 'right', times: 5 })\n\n  // Scroll left once\n  await userEvent.wheel(tablist, { direction: 'left' })\n})\n```\n\nWheel events can also be triggered directly from [locators](/api/browser/locators#wheel):\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.getByRole('tablist').wheel({ direction: 'right' })\n```\n\n::: warning\nThis method is intended for testing UI that explicitly listens to `wheel` events (e.g., custom zoom controls, horizontal tab scrolling, canvas interactions). If you need to scroll the page to bring an element into view, rely on the built-in automatic scrolling functionality provided by other `userEvent` methods or [locator actions](/api/browser/locators#methods) instead.\n:::\n\n## userEvent.fill\n\n```ts\nfunction fill(\n  element: Element | Locator,\n  text: string,\n): Promise<void>\n```\n\nSet a value to the `input`/`textarea`/`contenteditable` field. This will remove any existing text in the input before setting the new value.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('update input', async () => {\n  const input = page.getByRole('input')\n\n  await userEvent.fill(input, 'foo') // input.value == foo\n  await userEvent.fill(input, '{{a[[') // input.value == {{a[[\n  await userEvent.fill(input, '{Shift}') // input.value == {Shift}\n\n  // or you can access it directly on the locator\n  await input.fill('foo') // input.value == foo\n})\n```\n\nThis methods focuses the element, fills it and triggers an `input` event after filling. You can use an empty string to clear the field.\n\n::: tip\nThis API is faster than using [`userEvent.type`](#userevent-type) or [`userEvent.keyboard`](#userevent-keyboard), but it **doesn't support** [user-event `keyboard` syntax](https://testing-library.com/docs/user-event/keyboard) (e.g., `{Shift}{selectall}`).\n\nWe recommend using this API over [`userEvent.type`](#userevent-type) in situations when you don't need to enter special characters or have granular control over keypress events.\n:::\n\nReferences:\n\n- [Playwright `locator.fill` API](https://playwright.dev/docs/api/class-locator#locator-fill)\n- [WebdriverIO `element.setValue` API](https://webdriver.io/docs/api/element/setValue)\n- [testing-library `type` API](https://testing-library.com/docs/user-event/utility/#type)\n\n## userEvent.keyboard\n\n```ts\nfunction keyboard(text: string): Promise<void>\n```\n\nThe `userEvent.keyboard` allows you to trigger keyboard strokes. If any input has a focus, it will type characters into that input. Otherwise, it will trigger keyboard events on the currently focused element (`document.body` if there are no focused elements).\n\nThis API supports [user-event `keyboard` syntax](https://testing-library.com/docs/user-event/keyboard).\n\n```ts\nimport { userEvent } from 'vitest/browser'\n\ntest('trigger keystrokes', async () => {\n  await userEvent.keyboard('foo') // translates to: f, o, o\n  await userEvent.keyboard('{{a[[') // translates to: {, a, [\n  await userEvent.keyboard('{Shift}{f}{o}{o}') // translates to: Shift, f, o, o\n  await userEvent.keyboard('{a>5}') // press a without releasing it and trigger 5 keydown\n  await userEvent.keyboard('{a>5/}') // press a for 5 keydown and then release it\n})\n```\n\nReferences:\n\n- [Playwright `Keyboard` API](https://playwright.dev/docs/api/class-keyboard)\n- [WebdriverIO `action('key')` API](https://webdriver.io/docs/api/browser/action#key-input-source)\n- [testing-library `type` API](https://testing-library.com/docs/user-event/utility/#type)\n\n## userEvent.tab\n\n```ts\nfunction tab(options?: UserEventTabOptions): Promise<void>\n```\n\nSends a `Tab` key event. This is a shorthand for `userEvent.keyboard('{tab}')`.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('tab works', async () => {\n  const [input1, input2] = page.getByRole('input').elements()\n\n  expect(input1).toHaveFocus()\n\n  await userEvent.tab()\n\n  expect(input2).toHaveFocus()\n\n  await userEvent.tab({ shift: true })\n\n  expect(input1).toHaveFocus()\n})\n```\n\nReferences:\n\n- [Playwright `Keyboard` API](https://playwright.dev/docs/api/class-keyboard)\n- [WebdriverIO `action('key')` API](https://webdriver.io/docs/api/browser/action#key-input-source)\n- [testing-library `tab` API](https://testing-library.com/docs/user-event/convenience/#tab)\n\n## userEvent.type\n\n```ts\nfunction type(\n  element: Element | Locator,\n  text: string,\n  options?: UserEventTypeOptions,\n): Promise<void>\n```\n\n::: warning\nIf you don't rely on [special characters](https://testing-library.com/docs/user-event/keyboard) (e.g., `{shift}` or `{selectall}`), it is recommended to use [`userEvent.fill`](#userevent-fill) instead for better performance.\n:::\n\nThe `type` method implements `@testing-library/user-event`'s [`type`](https://testing-library.com/docs/user-event/utility/#type) utility built on top of [`keyboard`](https://testing-library.com/docs/user-event/keyboard) API.\n\nThis function allows you to type characters into an `input`/`textarea`/`contenteditable` element. It supports [user-event `keyboard` syntax](https://testing-library.com/docs/user-event/keyboard).\n\nIf you just need to press characters without an input, use [`userEvent.keyboard`](#userevent-keyboard) API.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('update input', async () => {\n  const input = page.getByRole('input')\n\n  await userEvent.type(input, 'foo') // input.value == foo\n  await userEvent.type(input, '{{a[[') // input.value == foo{a[\n  await userEvent.type(input, '{Shift}') // input.value == foo{a[\n})\n```\n\n::: info\nVitest doesn't expose `.type` method on the locator like `input.type` because it exists only for compatibility with the `userEvent` library. Consider using `.fill` instead as it is faster.\n:::\n\nReferences:\n\n- [Playwright `locator.press` API](https://playwright.dev/docs/api/class-locator#locator-press)\n- [WebdriverIO `action('key')` API](https://webdriver.io/docs/api/browser/action#key-input-source)\n- [testing-library `type` API](https://testing-library.com/docs/user-event/utility/#type)\n\n## userEvent.clear\n\n```ts\nfunction clear(element: Element | Locator, options?: UserEventClearOptions): Promise<void>\n```\n\nThis method clears the input element content.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('clears input', async () => {\n  const input = page.getByRole('input')\n\n  await userEvent.fill(input, 'foo')\n  expect(input).toHaveValue('foo')\n\n  await userEvent.clear(input)\n  // or you can access it directly on the locator\n  await input.clear()\n\n  expect(input).toHaveValue('')\n})\n```\n\nReferences:\n\n- [Playwright `locator.clear` API](https://playwright.dev/docs/api/class-locator#locator-clear)\n- [WebdriverIO `element.clearValue` API](https://webdriver.io/docs/api/element/clearValue)\n- [testing-library `clear` API](https://testing-library.com/docs/user-event/utility/#clear)\n\n## userEvent.selectOptions\n\n```ts\nfunction selectOptions(\n  element: Element | Locator,\n  values:\n    | HTMLElement\n    | HTMLElement[]\n    | Locator\n    | Locator[]\n    | string\n    | string[],\n  options?: UserEventSelectOptions,\n): Promise<void>\n```\n\nThe `userEvent.selectOptions` allows selecting a value in a `<select>` element.\n\n::: warning\nIf select element doesn't have [`multiple`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#attr-multiple) attribute, Vitest will select only the first element in the array.\n\nUnlike `@testing-library`, Vitest doesn't support [listbox](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role) at the moment, but we plan to add support for it in the future.\n:::\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('clears input', async () => {\n  const select = page.getByRole('select')\n\n  await userEvent.selectOptions(select, 'Option 1')\n  // or you can access it directly on the locator\n  await select.selectOptions('Option 1')\n\n  expect(select).toHaveValue('option-1')\n\n  await userEvent.selectOptions(select, 'option-1')\n  expect(select).toHaveValue('option-1')\n\n  await userEvent.selectOptions(select, [\n    page.getByRole('option', { name: 'Option 1' }),\n    page.getByRole('option', { name: 'Option 2' }),\n  ])\n  expect(select).toHaveValue(['option-1', 'option-2'])\n})\n```\n\n::: warning\n`webdriverio` provider doesn't support selecting multiple elements because it doesn't provide API to do so.\n:::\n\nReferences:\n\n- [Playwright `locator.selectOption` API](https://playwright.dev/docs/api/class-locator#locator-select-option)\n- [WebdriverIO `element.selectByIndex` API](https://webdriver.io/docs/api/element/selectByIndex)\n- [testing-library `selectOptions` API](https://testing-library.com/docs/user-event/utility/#-selectoptions-deselectoptions)\n\n## userEvent.hover\n\n```ts\nfunction hover(\n  element: Element | Locator,\n  options?: UserEventHoverOptions,\n): Promise<void>\n```\n\nThis method moves the cursor position to the selected element. Please refer to your provider's documentation for detailed explanation about how this method works.\n\n::: warning\nIf you are using `webdriverio` provider, the cursor will move to the center of the element by default.\n\nIf you are using `playwright` provider, the cursor moves to \"some\" visible point of the element.\n:::\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('hovers logo element', async () => {\n  const logo = page.getByRole('img', { name: /logo/ })\n\n  await userEvent.hover(logo)\n  // or you can access it directly on the locator\n  await logo.hover()\n})\n```\n\nReferences:\n\n- [Playwright `locator.hover` API](https://playwright.dev/docs/api/class-locator#locator-hover)\n- [WebdriverIO `element.moveTo` API](https://webdriver.io/docs/api/element/moveTo/)\n- [testing-library `hover` API](https://testing-library.com/docs/user-event/convenience/#hover)\n\n## userEvent.unhover\n\n```ts\nfunction unhover(\n  element: Element | Locator,\n  options?: UserEventHoverOptions,\n): Promise<void>\n```\n\nThis works the same as [`userEvent.hover`](#userevent-hover), but moves the cursor to the `document.body` element instead.\n\n::: warning\nBy default, the cursor position is in \"some\" visible place (in `playwright` provider) or in the center (in `webdriverio` provider) of the body element, so if the currently hovered element is already in the same position, this method will have no effect.\n:::\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('unhover logo element', async () => {\n  const logo = page.getByRole('img', { name: /logo/ })\n\n  await userEvent.unhover(logo)\n  // or you can access it directly on the locator\n  await logo.unhover()\n})\n```\n\nReferences:\n\n- [Playwright `locator.hover` API](https://playwright.dev/docs/api/class-locator#locator-hover)\n- [WebdriverIO `element.moveTo` API](https://webdriver.io/docs/api/element/moveTo/)\n- [testing-library `hover` API](https://testing-library.com/docs/user-event/convenience/#hover)\n\n## userEvent.upload\n\n```ts\nfunction upload(\n  element: Element | Locator,\n  files: string[] | string | File[] | File,\n  options?: UserEventUploadOptions,\n): Promise<void>\n```\n\nChange a file input element to have the specified files.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('can upload a file', async () => {\n  const input = page.getByRole('button', { name: /Upload files/ })\n\n  const file = new File(['file'], 'file.png', { type: 'image/png' })\n\n  await userEvent.upload(input, file)\n  // or you can access it directly on the locator\n  await input.upload(file)\n\n  // you can also use file paths relative to the root of the project\n  await userEvent.upload(input, './fixtures/file.png')\n})\n```\n\n::: warning\n`webdriverio` provider supports this command only in `chrome` and `edge` browsers. It also only supports string types at the moment.\n:::\n\nReferences:\n\n- [Playwright `locator.setInputFiles` API](https://playwright.dev/docs/api/class-locator#locator-set-input-files)\n- [WebdriverIO `browser.uploadFile` API](https://webdriver.io/docs/api/browser/uploadFile)\n- [testing-library `upload` API](https://testing-library.com/docs/user-event/utility/#upload)\n\n## userEvent.dragAndDrop\n\n```ts\nfunction dragAndDrop(\n  source: Element | Locator,\n  target: Element | Locator,\n  options?: UserEventDragAndDropOptions,\n): Promise<void>\n```\n\nDrags the source element on top of the target element. Don't forget that the `source` element has to have the `draggable` attribute set to `true`.\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\ntest('drag and drop works', async () => {\n  const source = page.getByRole('img', { name: /logo/ })\n  const target = page.getByTestId('logo-target')\n\n  await userEvent.dragAndDrop(source, target)\n  // or you can access it directly on the locator\n  await source.dropTo(target)\n\n  await expect.element(target).toHaveTextContent('Logo is processed')\n})\n```\n\n::: warning\nThis API is not supported by the default `preview` provider.\n:::\n\nReferences:\n\n- [Playwright `frame.dragAndDrop` API](https://playwright.dev/docs/api/class-frame#frame-drag-and-drop)\n- [WebdriverIO `element.dragAndDrop` API](https://webdriver.io/docs/api/element/dragAndDrop/)\n\n## userEvent.copy\n\n```ts\nfunction copy(): Promise<void>\n```\n\nCopy the selected text to the clipboard.\n\n```js\nimport { page, userEvent } from 'vitest/browser'\n\ntest('copy and paste', async () => {\n  // write to 'source'\n  await userEvent.click(page.getByPlaceholder('source'))\n  await userEvent.keyboard('hello')\n\n  // select and copy 'source'\n  await userEvent.dblClick(page.getByPlaceholder('source'))\n  await userEvent.copy()\n\n  // paste to 'target'\n  await userEvent.click(page.getByPlaceholder('target'))\n  await userEvent.paste()\n\n  await expect.element(page.getByPlaceholder('source')).toHaveTextContent('hello')\n  await expect.element(page.getByPlaceholder('target')).toHaveTextContent('hello')\n})\n```\n\nReferences:\n\n- [testing-library `copy` API](https://testing-library.com/docs/user-event/convenience/#copy)\n\n## userEvent.cut\n\n```ts\nfunction cut(): Promise<void>\n```\n\nCut the selected text to the clipboard.\n\n```js\nimport { page, userEvent } from 'vitest/browser'\n\ntest('copy and paste', async () => {\n  // write to 'source'\n  await userEvent.click(page.getByPlaceholder('source'))\n  await userEvent.keyboard('hello')\n\n  // select and cut 'source'\n  await userEvent.dblClick(page.getByPlaceholder('source'))\n  await userEvent.cut()\n\n  // paste to 'target'\n  await userEvent.click(page.getByPlaceholder('target'))\n  await userEvent.paste()\n\n  await expect.element(page.getByPlaceholder('source')).toHaveTextContent('')\n  await expect.element(page.getByPlaceholder('target')).toHaveTextContent('hello')\n})\n```\n\nReferences:\n\n- [testing-library `cut` API](https://testing-library.com/docs/user-event/clipboard#cut)\n\n## userEvent.paste\n\n```ts\nfunction paste(): Promise<void>\n```\n\nPaste the text from the clipboard. See [`userEvent.copy`](#userevent-copy) and [`userEvent.cut`](#userevent-cut) for usage examples.\n\nReferences:\n\n- [testing-library `paste` API](https://testing-library.com/docs/user-event/clipboard#paste)\n"
  },
  {
    "path": "docs/api/browser/locators.md",
    "content": "---\ntitle: Locators | Browser Mode\noutline: [2, 3]\n---\n\n# Locators\n\nA locator is a representation of an element or a number of elements. Every locator is defined by a string called a selector. Vitest abstracts this selector by providing convenient methods that generate them behind the scenes.\n\nThe locator API uses a fork of [Playwright's locators](https://playwright.dev/docs/api/class-locator) called [Ivya](https://npmx.dev/ivya). However, Vitest provides this API to every [provider](/config/browser/provider), not just playwright.\n\n::: tip\nThis page covers API usage. To better understand locators and their usage, read [Playwright's \"Locators\" documentation](https://playwright.dev/docs/locators).\n:::\n\n::: tip Difference from `testing-library`\nVitest's `page.getBy*` methods return a locator object, not a DOM element. This makes locator queries composable and allows Vitest to retry interactions and assertions when needed.\n\nCompared to testing-library queries:\n\n- Use locator chaining (`.getBy*`, `.filter`, `.nth`) instead of `within(...)`.\n- Keep locators around and interact with them later (`await locator.click()`), instead of resolving elements up front.\n- Single-element escape hatches like `.element()` and `.query()` are strict and throw if multiple elements match.\n\n```ts\nimport { expect } from 'vitest'\nimport { page } from 'vitest/browser'\n\nconst deleteButton = page\n  .getByRole('row')\n  .filter({ hasText: 'Vitest' })\n  .getByRole('button', { name: /delete/i })\n\nawait deleteButton.click()\nawait expect.element(deleteButton).toBeEnabled()\n```\n:::\n\n## getByRole\n\n```ts\nfunction getByRole(\n  role: ARIARole | string,\n  options?: LocatorByRoleOptions,\n): Locator\n```\n\nCreates a way to locate an element by its [ARIA role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles), [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes) and [accessible name](https://developer.mozilla.org/en-US/docs/Glossary/Accessible_name).\n\n::: tip\nIf you only query for a single element with `getByText('The name')` it's oftentimes better to use `getByRole(expectedRole, { name: 'The name' })`. The accessible name query does not replace other queries such as `*ByAltText` or `*ByTitle`. While the accessible name can be equal to these attributes, it does not replace the functionality of these attributes.\n:::\n\nConsider the following DOM structure.\n\n```html\n<h3>Sign up</h3>\n<label>\n  Login\n  <input type=\"text\" />\n</label>\n<label>\n  Password\n  <input type=\"password\" />\n</label>\n<br/>\n<button>Submit</button>\n```\n\nYou can locate each element by its implicit role:\n\n```ts\nawait expect.element(\n  page.getByRole('heading', { name: 'Sign up' })\n).toBeVisible()\n\nawait page.getByRole('textbox', { name: 'Login' }).fill('admin')\nawait page.getByRole('textbox', { name: 'Password' }).fill('admin')\n\nawait page.getByRole('button', { name: /submit/i }).click()\n```\n\n::: warning\nRoles are matched by string equality, without inheriting from the ARIA role hierarchy. As a result, querying a superclass role like `checkbox` will not include elements with a subclass role like `switch`.\n\nBy default, many semantic elements in HTML have a role; for example, `<input type=\"radio\">` has the \"radio\" role. Non-semantic elements in HTML do not have a role; `<div>` and `<span>` without added semantics return `null`. The `role` attribute can provide semantics.\n\nProviding roles via `role` or `aria-*` attributes to built-in elements that already have an implicit role is **highly discouraged** by ARIA guidelines.\n:::\n\n**Options**\n\n- `exact: boolean`\n\n  Whether the `name` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `name` is a regular expression. Note that exact match still trims whitespace.\n\n  ```tsx\n  <button>Hello World</button>\n\n  page.getByRole('button', { name: 'hello world' }) // ✅\n  page.getByRole('button', { name: 'hello world', exact: true }) // ❌\n  page.getByRole('button', { name: 'Hello World', exact: true }) // ✅\n  ```\n\n- `checked: boolean`\n\n  Should checked elements (set by `aria-checked` or `<input type=\"checkbox\"/>`) be included or not. By default, the filter is not applied.\n\n  See [`aria-checked`](https://www.w3.org/TR/wai-aria-1.2/#aria-checked) for more information\n\n  ```tsx\n  <>\n    <button role=\"checkbox\" aria-checked=\"true\" />\n    <input type=\"checkbox\" checked />\n  </>\n\n  page.getByRole('checkbox', { checked: true }) // ✅\n  page.getByRole('checkbox', { checked: false }) // ❌\n  ```\n\n- `disabled: boolean`\n\n  Should disabled elements be included or not. By default, the filter is not applied. Note that unlike other attributes, `disable` state is inherited.\n\n  See [`aria-disabled`](https://www.w3.org/TR/wai-aria-1.2/#aria-disabled) for more information\n\n  ```tsx\n  <input type=\"text\" disabled />\n\n  page.getByRole('textbox', { disabled: true }) // ✅\n  page.getByRole('textbox', { disabled: false }) // ❌\n  ```\n\n- `expanded: boolean`\n\n  Should expanded elements be included or not. By default, the filter is not applied.\n\n  See [`aria-expanded`](https://www.w3.org/TR/wai-aria-1.2/#aria-expanded) for more information\n\n  ```tsx\n  <a aria-expanded=\"true\" href=\"example.com\">Link</a>\n\n  page.getByRole('link', { expanded: true }) // ✅\n  page.getByRole('link', { expanded: false }) // ❌\n  ```\n\n- `includeHidden: boolean`\n\n  Should elements that are [normally excluded](https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion) from the accessibility tree be queried. By default, only non-hidden elements are matched by role selector.\n\n  Note that roles `none` and `presentation` are always included.\n\n  ```tsx\n  <button style=\"display: none\" />\n\n  page.getByRole('button') // ❌\n  page.getByRole('button', { includeHidden: false }) // ❌\n  page.getByRole('button', { includeHidden: true }) // ✅\n  ```\n\n- `level: number`\n\n  A number attribute that is usually present for `heading`, `listitem`, `row`, `treeitem` roles with default values for `<h1>-<h6>` elements. By default, the filter is not applied.\n\n  See [`aria-level`](https://www.w3.org/TR/wai-aria-1.2/#aria-level) for more information\n\n  ```tsx\n  <>\n    <h1>Heading Level One</h1>\n    <div role=\"heading\" aria-level=\"1\">Second Heading Level One</div>\n  </>\n\n  page.getByRole('heading', { level: 1 }) // ✅\n  page.getByRole('heading', { level: 2 }) // ❌\n  ```\n\n- `name: string | RegExp`\n\n  [An accessible name](https://developer.mozilla.org/en-US/docs/Glossary/Accessible_name). By default, matching is case-insensitive and searches for a substring. Use `exact` option to control this behavior.\n\n  ```tsx\n  <button>Click Me!</button>\n\n  page.getByRole('button', { name: 'Click Me!' }) // ✅\n  page.getByRole('button', { name: 'click me!' }) // ✅\n  page.getByRole('button', { name: 'Click Me?' }) // ❌\n  ```\n\n- `pressed: boolean`\n\n  Should pressed elements be included or not. By default, the filter is not applied.\n\n  See [`aria-pressed`](https://www.w3.org/TR/wai-aria-1.2/#aria-pressed) for more information\n\n  ```tsx\n  <button aria-pressed=\"true\">👍</button>\n\n  page.getByRole('button', { pressed: true }) // ✅\n  page.getByRole('button', { pressed: false }) // ❌\n  ```\n\n- `selected: boolean`\n\n  Should selected elements be included or not. By default, the filter is not applied.\n\n  See [`aria-selected`](https://www.w3.org/TR/wai-aria-1.2/#aria-selected) for more information\n\n  ```tsx\n  <button role=\"tab\" aria-selected=\"true\">Vue</button>\n\n  page.getByRole('button', { selected: true }) // ✅\n  page.getByRole('button', { selected: false }) // ❌\n  ```\n\n**See also**\n\n- [List of ARIA roles at MDN](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles)\n- [List of ARIA roles at w3.org](https://www.w3.org/TR/wai-aria-1.2/#role_definitions)\n- [testing-library's `ByRole`](https://testing-library.com/docs/queries/byrole/)\n\n## getByAltText\n\n```ts\nfunction getByAltText(\n  text: string | RegExp,\n  options?: LocatorOptions,\n): Locator\n```\n\nCreates a locator capable of finding an element with an `alt` attribute that matches the text. Unlike testing-library's implementation, Vitest will match any element that has a matching `alt` attribute.\n\n```tsx\n<img alt=\"Incredibles 2 Poster\" src=\"/incredibles-2.png\" />\n\npage.getByAltText(/incredibles.*? poster/i) // ✅\npage.getByAltText('non existing alt text') // ❌\n```\n\n**Options**\n\n- `exact: boolean`\n\n  Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.\n\n**See also**\n\n- [testing-library's `ByAltText`](https://testing-library.com/docs/queries/byalttext/)\n\n## getByLabelText\n\n```ts\nfunction getByLabelText(\n  text: string | RegExp,\n  options?: LocatorOptions,\n): Locator\n```\n\nCreates a locator capable of finding an element that has an associated label.\n\nThe `page.getByLabelText('Username')` locator will find every input in the example below:\n\n```html\n// for/htmlFor relationship between label and form element id\n<label for=\"username-input\">Username</label>\n<input id=\"username-input\" />\n\n// The aria-labelledby attribute with form elements\n<label id=\"username-label\">Username</label>\n<input aria-labelledby=\"username-label\" />\n\n// Wrapper labels\n<label>Username <input /></label>\n\n// Wrapper labels where the label text is in another child element\n<label>\n  <span>Username</span>\n  <input />\n</label>\n\n// aria-label attributes\n// Take care because this is not a label that users can see on the page,\n// so the purpose of your input must be obvious to visual users.\n<input aria-label=\"Username\" />\n```\n\n**Options**\n\n- `exact: boolean`\n\n  Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.\n\n**See also**\n\n- [testing-library's `ByLabelText`](https://testing-library.com/docs/queries/bylabeltext/)\n\n## getByPlaceholder\n\n```ts\nfunction getByPlaceholder(\n  text: string | RegExp,\n  options?: LocatorOptions,\n): Locator\n```\n\nCreates a locator capable of finding an element that has the specified `placeholder` attribute. Vitest will match any element that has a matching `placeholder` attribute, not just `input`.\n\n```tsx\n<input placeholder=\"Username\" />\n\npage.getByPlaceholder('Username') // ✅\npage.getByPlaceholder('not found') // ❌\n```\n\n::: warning\nIt is generally better to rely on a label using [`getByLabelText`](#getbylabeltext) than a placeholder.\n:::\n\n**Options**\n\n- `exact: boolean`\n\n  Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.\n\n**See also**\n\n- [testing-library's `ByPlaceholderText`](https://testing-library.com/docs/queries/byplaceholdertext/)\n\n## getByText\n\n```ts\nfunction getByText(\n  text: string | RegExp,\n  options?: LocatorOptions,\n): Locator\n```\n\nCreates a locator capable of finding an element that contains the specified text. The text will be matched against TextNode's [`nodeValue`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeValue) or input's value if the type is `button` or `reset`. Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one, turns line breaks into spaces and ignores leading and trailing whitespace.\n\n```tsx\n<a href=\"/about\">About ℹ️</a>\n\npage.getByText(/about/i) // ✅\npage.getByText('about', { exact: true }) // ❌\n```\n\n::: tip\nThis locator is useful for locating non-interactive elements. If you need to locate an interactive element, like a button or an input, prefer [`getByRole`](#getbyrole).\n:::\n\n**Options**\n\n- `exact: boolean`\n\n  Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.\n\n**See also**\n\n- [testing-library's `ByText`](https://testing-library.com/docs/queries/bytext/)\n\n## getByTitle\n\n```ts\nfunction getByTitle(\n  text: string | RegExp,\n  options?: LocatorOptions,\n): Locator\n```\n\nCreates a locator capable of finding an element that has the specified `title` attribute. Unlike testing-library's `getByTitle`, Vitest cannot find `title` elements within an SVG.\n\n```tsx\n<span title=\"Delete\" id=\"2\"></span>\n\npage.getByTitle('Delete') // ✅\npage.getByTitle('Create') // ❌\n```\n\n**Options**\n\n- `exact: boolean`\n\n  Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.\n\n**See also**\n\n- [testing-library's `ByTitle`](https://testing-library.com/docs/queries/bytitle/)\n\n## getByTestId\n\n```ts\nfunction getByTestId(text: string | RegExp): Locator\n```\n\nCreates a locator capable of finding an element that matches the specified test id attribute. You can configure the attribute name with [`browser.locators.testIdAttribute`](/config/browser/locators#testidattribute).\n\n```tsx\n<div data-testid=\"custom-element\" />\n\npage.getByTestId('custom-element') // ✅\npage.getByTestId('non-existing-element') // ❌\n```\n\n::: warning\nIt is recommended to use this only after the other locators don't work for your use case. Using `data-testid` attributes does not resemble how your software is used and should be avoided if possible.\n:::\n\n**Options**\n\n- `exact: boolean`\n\n  Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.\n\n**See also**\n\n- [testing-library's `ByTestId`](https://testing-library.com/docs/queries/bytestid/)\n\n## nth\n\n```ts\nfunction nth(index: number): Locator\n```\n\nThis method returns a new locator that matches only a specific index within a multi-element query result. It's zero based, `nth(0)` selects the first element. Unlike `elements()[n]`, the `nth` locator will be retried until the element is present.\n\n```html\n<div aria-label=\"one\"><input/><input/><input/></div>\n<div aria-label=\"two\"><input/></div>\n```\n\n```tsx\npage.getByRole('textbox').nth(0) // ✅\npage.getByRole('textbox').nth(4) // ❌\n```\n\n::: tip\nBefore resorting to `nth`, you may find it useful to use chained locators to narrow down your search.\nSometimes there is no better way to distinguish than by element position; although this can lead to flake, it's better than nothing.\n:::\n\n```tsx\npage.getByLabel('two').getByRole('input') // ✅ better alternative to page.getByRole('textbox').nth(3)\npage.getByLabel('one').getByRole('input') // ❌ too ambiguous\npage.getByLabel('one').getByRole('input').nth(1) // ✅ pragmatic compromise\n```\n\n## first\n\n```ts\nfunction first(): Locator\n```\n\nThis method returns a new locator that matches only the first index of a multi-element query result.\nIt is sugar for `nth(0)`.\n\n```html\n<input/> <input/> <input/>\n```\n\n```tsx\npage.getByRole('textbox').first() // ✅\n```\n\n## last\n\n```ts\nfunction last(): Locator\n```\n\nThis method returns a new locator that matches only the last index of a multi-element query result.\nIt is sugar for `nth(-1)`.\n\n```html\n<input/> <input/> <input/>\n```\n\n```tsx\npage.getByRole('textbox').last() // ✅\n```\n\n## and\n\n```ts\nfunction and(locator: Locator): Locator\n```\n\nThis method creates a new locator that matches both the parent and provided locator. The following example finds a button with a specific title:\n\n```ts\npage.getByRole('button').and(page.getByTitle('Subscribe'))\n```\n\n## or\n\n```ts\nfunction or(locator: Locator): Locator\n```\n\nThis method creates a new locator that matches either one or both locators.\n\n::: warning\nNote that if locator matches more than a single element, calling another method might throw an error if it expects a single element:\n\n```tsx\n<>\n  <button>Click me</button>\n  <a href=\"https://vitest.dev\">Error happened!</a>\n</>\n\npage.getByRole('button')\n  .or(page.getByRole('link'))\n  .click() // ❌ matches multiple elements\n```\n:::\n\n## filter\n\n```ts\nfunction filter(options: LocatorOptions): Locator\n```\n\nThis methods narrows down the locator according to the options, such as filtering by text. It can be chained to apply multiple filters.\n\n### has\n\n- **Type:** `Locator`\n\nThis options narrows down the selector to match elements that contain other elements matching provided locator. For example, with this HTML:\n\n```html{1,3}\n<article>\n  <div>Vitest</div>\n</article>\n<article>\n  <div>Rolldown</div>\n</article>\n```\n\nWe can narrow down the locator to only find the `article` with `Vitest` text inside:\n\n```ts\npage.getByRole('article').filter({ has: page.getByText('Vitest') }) // ✅\n```\n\n::: warning\nProvided locator (`page.getByText('Vitest')` in the example) must be relative to the parent locator (`page.getByRole('article')` in the example). It will be queried starting with the parent locator, not the document root.\n\nMeaning, you cannot pass down a locator that queries the element outside of the parent locator:\n\n```ts\npage.getByText('Vitest').filter({ has: page.getByRole('article') }) // ❌\n```\n\nThis example will fail because the `article` element is outside the element with `Vitest` text.\n:::\n\n::: tip\nThis method can be chained to narrow down the element even further:\n\n```ts\npage.getByRole('article')\n  .filter({ has: page.getByRole('button', { name: 'delete row' }) })\n  .filter({ has: page.getByText('Vitest') })\n```\n:::\n\n### hasNot\n\n- **Type:** `Locator`\n\nThis option narrows down the selector to match elements that do not contain other elements matching provided locator. For example, with this HTML:\n\n```html{1,3}\n<article>\n  <div>Vitest</div>\n</article>\n<article>\n  <div>Rolldown</div>\n</article>\n```\n\nWe can narrow down the locator to only find the `article` that doesn't have `Rolldown` inside.\n\n```ts\npage.getByRole('article')\n  .filter({ hasNot: page.getByText('Rolldown') }) // ✅\npage.getByRole('article')\n  .filter({ hasNot: page.getByText('Vitest') }) // ❌\n```\n\n::: warning\nNote that provided locator is queried against the parent, not the document root, just like [`has`](#has) option.\n:::\n\n### hasText\n\n- **Type:** `string | RegExp`\n\nThis options narrows down the selector to only match elements that contain provided text somewhere inside. When the `string` is passed, matching is case-insensitive and searches for a substring.\n\n```html{1,3}\n<article>\n  <div>Vitest</div>\n</article>\n<article>\n  <div>Rolldown</div>\n</article>\n```\n\nBoth locators will find the same element because the search is case-insensitive:\n\n```ts\npage.getByRole('article').filter({ hasText: 'Vitest' }) // ✅\npage.getByRole('article').filter({ hasText: 'Vite' }) // ✅\n```\n\n### hasNotText\n\n- **Type:** `string | RegExp`\n\nThis options narrows down the selector to only match elements that do not contain provided text somewhere inside. When the `string` is passed, matching is case-insensitive and searches for a substring.\n\n## Methods\n\nAll methods are asynchronous and must be awaited. Since Vitest 3, tests will fail if a method is not awaited.\n\n### click\n\n```ts\nfunction click(options?: UserEventClickOptions): Promise<void>\n```\n\nClick on an element. You can use the options to set the cursor position.\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.getByRole('img', { name: 'Rose' }).click()\n```\n\n- [See more at `userEvent.click`](/api/browser/interactivity#userevent-click)\n\n### dblClick\n\n```ts\nfunction dblClick(options?: UserEventDoubleClickOptions): Promise<void>\n```\n\nTriggers a double click event on an element. You can use the options to set the cursor position.\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.getByRole('img', { name: 'Rose' }).dblClick()\n```\n\n- [See more at `userEvent.dblClick`](/api/browser/interactivity#userevent-dblclick)\n\n### tripleClick\n\n```ts\nfunction tripleClick(options?: UserEventTripleClickOptions): Promise<void>\n```\n\nTriggers a triple click event on an element. Since there is no `tripleclick` in browser api, this method will fire three click events in a row.\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.getByRole('img', { name: 'Rose' }).tripleClick()\n```\n\n- [See more at `userEvent.tripleClick`](/api/browser/interactivity#userevent-tripleclick)\n\n### wheel <Version>4.1.0</Version> {#wheel}\n\n```ts\nfunction wheel(options: UserEventWheelOptions): Promise<void>\n```\n\nTriggers a [`wheel` event](https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event) on an element. You can use the options to choose a general scroll `direction` or a precise `delta` value.\n\n```ts\nimport { page } from 'vitest/browser'\n\n// Scroll right\nawait page.getByRole('tablist').wheel({ direction: 'right' })\n```\n\n- [See more at `userEvent.wheel`](/api/browser/interactivity#userevent-wheel)\n\n### clear\n\n```ts\nfunction clear(options?: UserEventClearOptions): Promise<void>\n```\n\nClears the input element content.\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.getByRole('textbox', { name: 'Full Name' }).clear()\n```\n\n- [See more at `userEvent.clear`](/api/browser/interactivity#userevent-clear)\n\n### hover\n\n```ts\nfunction hover(options?: UserEventHoverOptions): Promise<void>\n```\n\nMoves the cursor position to the selected element.\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.getByRole('img', { name: 'Rose' }).hover()\n```\n\n- [See more at `userEvent.hover`](/api/browser/interactivity#userevent-hover)\n\n### unhover\n\n```ts\nfunction unhover(options?: UserEventHoverOptions): Promise<void>\n```\n\nThis works the same as [`locator.hover`](#hover), but moves the cursor to the `document.body` element instead.\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.getByRole('img', { name: 'Rose' }).unhover()\n```\n\n- [See more at `userEvent.unhover`](/api/browser/interactivity#userevent-unhover)\n\n### fill\n\n```ts\nfunction fill(text: string, options?: UserEventFillOptions): Promise<void>\n```\n\nSets the value of the current `input`, `textarea` or `contenteditable` element.\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.getByRole('input', { name: 'Full Name' }).fill('Mr. Bean')\n```\n\n- [See more at `userEvent.fill`](/api/browser/interactivity#userevent-fill)\n\n### dropTo\n\n```ts\nfunction dropTo(\n  target: Locator,\n  options?: UserEventDragAndDropOptions,\n): Promise<void>\n```\n\nDrags the current element to the target location.\n\n```ts\nimport { page } from 'vitest/browser'\n\nconst paris = page.getByText('Paris')\nconst france = page.getByText('France')\n\nawait paris.dropTo(france)\n```\n\n- [See more at `userEvent.dragAndDrop`](/api/browser/interactivity#userevent-draganddrop)\n\n### selectOptions\n\n```ts\nfunction selectOptions(\n  values:\n    | HTMLElement\n    | HTMLElement[]\n    | Locator\n    | Locator[]\n    | string\n    | string[],\n  options?: UserEventSelectOptions,\n): Promise<void>\n```\n\nChoose one or more values from a `<select>` element.\n\n```ts\nimport { page } from 'vitest/browser'\n\nconst languages = page.getByRole('select', { name: 'Languages' })\n\nawait languages.selectOptions('EN')\nawait languages.selectOptions(['ES', 'FR'])\nawait languages.selectOptions([\n  languages.getByRole('option', { name: 'Spanish' }),\n  languages.getByRole('option', { name: 'French' }),\n])\n```\n\n- [See more at `userEvent.selectOptions`](/api/browser/interactivity#userevent-selectoptions)\n\n### screenshot\n\n```ts\nfunction screenshot(options: LocatorScreenshotOptions & { save: false }): Promise<string>\nfunction screenshot(options: LocatorScreenshotOptions & { base64: true }): Promise<{\n  path: string\n  base64: string\n}>\nfunction screenshot(options?: LocatorScreenshotOptions & { base64?: false }): Promise<string>\n```\n\nCreates a screenshot of the element matching the locator's selector.\n\nYou can specify the save location for the screenshot using the `path` option, which is relative to the current test file. If the `path` option is not set, Vitest will default to using [`browser.screenshotDirectory`](/config/browser/screenshotdirectory) (`__screenshot__` by default), along with the names of the file and the test to determine the screenshot's filepath.\n\nIf you also need the content of the screenshot, you can specify `base64: true` to return it alongside the filepath where the screenshot is saved.\n\n```ts\nimport { page } from 'vitest/browser'\n\nconst button = page.getByRole('button', { name: 'Click Me!' })\n\nconst path = await button.screenshot()\n\nconst { path, base64 } = await button.screenshot({\n  path: './button-click-me.png',\n  base64: true, // also return base64 string\n})\n// path - fullpath to the screenshot\n// bas64 - base64 encoded string of the screenshot\n```\n\n::: warning WARNING <Version>3.2.0</Version>\nNote that `screenshot` will always return a base64 string if `save` is set to `false`.\nThe `path` is also ignored in that case.\n:::\n\n### mark\n\n```ts\nfunction mark(name: string, options?: { stack?: string }): Promise<void>\n```\n\nAdds a named marker to the trace timeline and uses the current locator as marker context.\n\nPass `options.stack` to override the callsite location in trace metadata. This is useful for wrapper libraries that need to preserve the end-user source location.\n\n```ts\nimport { page } from 'vitest/browser'\n\nconst submitButton = page.getByRole('button', { name: 'Submit' })\n\nawait submitButton.mark('before submit')\nawait submitButton.click()\nawait submitButton.mark('after submit')\n```\n\n::: tip\nThis method is useful only when [`browser.trace`](/config/browser/trace) is enabled.\n:::\n\n### query\n\n```ts\nfunction query(): Element | null\n```\n\nThis method returns a single element matching the locator's selector or `null` if no element is found.\n\nIf multiple elements match the selector, this method will throw an error.  Use [`.elements()`](#elements) when you need all matching DOM Elements or [`.all()`](#all) if you need an array of locators matching the selector.\n\n::: danger\nThis is an escape hatch for external APIs that do not support locators. Prefer using locator methods instead.\n:::\n\nConsider the following DOM structure:\n\n```html\n<div>Hello <span>World</span></div>\n<div>Hello</div>\n```\n\nThese locators will not throw an error:\n\n```ts\npage.getByText('Hello World').query() // ✅ HTMLDivElement\npage.getByText('Hello Germany').query() // ✅ null\npage.getByText('World').query() // ✅ HTMLSpanElement\npage.getByText('Hello', { exact: true }).query() // ✅ HTMLSpanElement\n```\n\nThese locators will throw an error:\n\n```ts\n// returns multiple elements\npage.getByText('Hello').query() // ❌\npage.getByText(/^Hello/).query() // ❌\n```\n\n### element\n\n```ts\nfunction element(): Element\n```\n\nThis method returns a single element matching the locator's selector.\n\nIf _no element_ matches the selector, an error is thrown. Consider using [`.query()`](#query) when you just need to check if the element exists.\n\nIf _multiple elements_ match the selector, an error is thrown. Use [`.elements()`](#elements) when you need all matching DOM Elements or [`.all()`](#all) if you need an array of locators matching the selector.\n\n::: danger\nThis is an escape hatch for external APIs that do not support locators. Prefer using locator methods instead.\n\nIt is called automatically when locator is used with `expect.element` every time the assertion is [retried](/api/browser/assertions):\n\n```ts\nawait expect.element(page.getByRole('button')).toBeDisabled()\n```\n:::\n\nConsider the following DOM structure:\n\n```html\n<div>Hello <span>World</span></div>\n<div>Hello Germany</div>\n<div>Hello</div>\n```\n\nThese locators will not throw an error:\n\n```ts\npage.getByText('Hello World').element() // ✅\npage.getByText('Hello Germany').element() // ✅\npage.getByText('World').element() // ✅\npage.getByText('Hello', { exact: true }).element() // ✅\n```\n\nThese locators will throw an error:\n\n```ts\n// returns multiple elements\npage.getByText('Hello').element() // ❌\npage.getByText(/^Hello/).element() // ❌\n\n// returns no elements\npage.getByText('Hello USA').element() // ❌\n```\n\n### elements\n\n```ts\nfunction elements(): Element[]\n```\n\nThis method returns an array of elements matching the locator's selector.\n\nThis function never throws an error. If there are no elements matching the selector, this method will return an empty array.\n\nConsider the following DOM structure:\n\n```html\n<div>Hello <span>World</span></div>\n<div>Hello</div>\n```\n\nThese locators will always succeed:\n\n```ts\npage.getByText('Hello World').elements() // ✅ [HTMLElement]\npage.getByText('World').elements() // ✅ [HTMLElement]\npage.getByText('Hello', { exact: true }).elements() // ✅ [HTMLElement]\npage.getByText('Hello').elements() // ✅ [HTMLElement, HTMLElement]\npage.getByText('Hello USA').elements() // ✅ []\n```\n\n### findElement <Version>4.1.0</Version> {#findelement}\n\n```ts\nfunction findElement(\n  options?: SelectorOptions\n): Promise<HTMLElement | SVGElement>\n```\n\n::: danger WARNING\nThis is an escape hatch for cases where you need the raw DOM element — for example, to pass it to a third-party library like FormKit that doesn't accept Vitest locators. If you are interacting with the element yourself, use other [builtin methods](#methods) instead.\n:::\n\nThis method returns an element matching the locator. Unlike [`.element()`](#element), this method will wait and retry until a matching element appears in the DOM, using increasing intervals (0, 20, 50, 100, 100, 500ms).\n\nIf _no element_ is found before the timeout, an error is thrown. By default, the timeout matches the test timeout.\n\nIf _multiple elements_ match the selector and `strict` is `true` (the default), an error is thrown immediately without retrying. Set `strict` to `false` to return the first matching element instead.\n\nIt accepts options:\n\n- `timeout: number` - How long to wait in milliseconds until at least one element is found. By default, this shares timeout with the test.\n- `strict: boolean` - When `true` (default), throws an error if multiple elements match the locator. When `false`, returns the first matching element.\n\nConsider the following DOM structure:\n\n```html\n<div>Hello <span>World</span></div>\n<div>Hello Germany</div>\n<div>Hello</div>\n```\n\nThese locators will resolve successfully:\n\n```ts\nawait page.getByText('Hello World').findElement() // ✅ HTMLDivElement\nawait page.getByText('World').findElement() // ✅ HTMLSpanElement\nawait page.getByText('Hello Germany').findElement() // ✅ HTMLDivElement\n```\n\nThese locators will throw an error:\n\n```ts\n// multiple elements match, strict mode rejects\nawait page.getByText('Hello').findElement() // ❌\nawait page.getByText(/^Hello/).findElement() // ❌\n\n// no matching element before timeout\nawait page.getByText('Hello USA').findElement() // ❌\n```\n\nUsing `strict: false` to allow multiple matches:\n\n```ts\n// returns the first matching element instead of throwing\nawait page.getByText('Hello').findElement({ strict: false }) // ✅ HTMLDivElement\n```\n\n### all\n\n```ts\nfunction all(): Locator[]\n```\n\nThis method returns an array of new locators that match the selector.\n\nInternally, this method calls `.elements` and wraps every element using [`page.elementLocator`](/api/browser/context#page).\n\n- [See `locator.elements()`](#elements)\n\n## Properties\n\n### selector\n\nThe `selector` is a string that will be used to locate the element by the browser provider. Playwright will use a `playwright` locator syntax while `preview` and `webdriverio` will use CSS.\n\n::: danger\nYou should not use this string in your test code. The `selector` string should only be used when working with the Commands API:\n\n```ts [commands.ts]\nimport type { BrowserCommand } from 'vitest/node'\n\nconst test: BrowserCommand<string> = function test(context, selector) {\n  // playwright\n  await context.iframe.locator(selector).click()\n  // webdriverio\n  await context.browser.$(selector).click()\n}\n```\n\n```ts [example.test.ts]\nimport { test } from 'vitest'\nimport { commands, page } from 'vitest/browser'\n\ntest('works correctly', async () => {\n  await commands.test(page.getByText('Hello').selector) // ✅\n  // vitest will automatically unwrap it to a string\n  await commands.test(page.getByText('Hello')) // ✅\n})\n```\n:::\n\n### length\n\nThis getter returns a number of elements that this locator is matching. It is equivalent to calling `locator.elements().length`.\n\nConsider the following DOM structure:\n\n```html\n<button>Click Me!</button>\n<button>Don't click me!</button>\n```\n\nThis property will always succeed:\n\n```ts\npage.getByRole('button').length // ✅ 2\npage.getByRole('button', { title: 'Click Me!' }).length // ✅ 1\npage.getByRole('alert').length // ✅ 0\n```\n\n## Custom Locators <Version>3.2.0</Version> <Badge type=\"danger\">advanced</Badge> {#custom-locators}\n\nYou can extend built-in locators API by defining an object of locator factories. These methods will exist as methods on the `page` object and any created locator.\n\nThese locators can be useful if built-in locators are not enough. For example, when you use a custom framework for your UI.\n\nThe locator factory needs to return a selector string or a locator itself.\n\n::: tip\nThe selector syntax is identical to Playwright locators. Please, read [their guide](https://playwright.dev/docs/other-locators) to better understand how to work with them.\n:::\n\n```ts\nimport { locators } from 'vitest/browser'\n\nlocators.extend({\n  getByArticleTitle(title) {\n    return `[data-title=\"${title}\"]`\n  },\n  getByArticleCommentsCount(count) {\n    return `.comments :text(\"${count} comments\")`\n  },\n  async previewComments() {\n    // you have access to the current locator via \"this\"\n    // beware that if the method was called on `page`, `this` will be `page`,\n    // not the locator!\n    if (this !== page) {\n      await this.click()\n    }\n    // ...\n  }\n})\n\n// if you are using typescript, you can extend LocatorSelectors interface\n// to have the autocompletion in locators.extend, page.* and locator.* methods\ndeclare module 'vitest/browser' {\n  interface LocatorSelectors {\n    // if the custom method returns a string, it will be converted into a locator\n    // if it returns anything else, then it will be returned as usual\n    getByArticleTitle(title: string): Locator\n    getByArticleCommentsCount(count: number): Locator\n\n    // Vitest will return a promise and won't try to convert it into a locator\n    previewComments(this: Locator): Promise<void>\n  }\n}\n```\n\nIf the method is called on the global `page` object, then selector will be applied to the whole page. In the example below, `getByArticleTitle` will find all elements with an attribute `data-title` with the value of `title`. However, if the method is called on the locator, then it will be scoped to that locator.\n\n```html\n<article data-title=\"Hello, World!\">\n  Hello, World!\n  <button id=\"comments\">2 comments</button>\n</article>\n\n<article data-title=\"Hello, Vitest!\">\n  Hello, Vitest!\n  <button id=\"comments\">0 comments</button>\n</article>\n```\n\n```ts\nconst articles = page.getByRole('article')\nconst worldArticle = page.getByArticleTitle('Hello, World!') // ✅\nconst commentsElement = worldArticle.getByArticleCommentsCount(2) // ✅\nconst wrongCommentsElement = worldArticle.getByArticleCommentsCount(0) // ❌\nconst wrongElement = page.getByArticleTitle('No Article!') // ❌\n\nawait commentsElement.previewComments() // ✅\nawait wrongCommentsElement.previewComments() // ❌\n```\n"
  },
  {
    "path": "docs/api/browser/react.md",
    "content": "---\noutline: deep\n---\n\n# vitest-browser-react\n\nThe community [`vitest-browser-react`](https://npmx.dev/package/vitest-browser-react) package renders [React](https://react.dev/) components in [Browser Mode](/guide/browser/).\n\n```jsx\nimport { render } from 'vitest-browser-react'\nimport { expect, test } from 'vitest'\nimport Component from './Component.jsx'\n\ntest('counter button increments the count', async () => {\n  const screen = await render(<Component count={1} />)\n\n  await screen.getByRole('button', { name: 'Increment' }).click()\n\n  await expect.element(screen.getByText('Count is 2')).toBeVisible()\n})\n```\n\n::: warning\nThis library takes inspiration from [`@testing-library/react`](https://github.com/testing-library/react-testing-library).\n\nIf you have used `@testing-library/react` in your tests before, you can keep using it, however the `vitest-browser-react` package provides certain benefits unique to the Browser Mode that `@testing-library/react` lacks:\n\n`vitest-browser-react` returns APIs that interact well with built-in [locators](/api/browser/locators), [user events](/api/browser/interactivity) and [assertions](/api/browser/assertions): for example, Vitest will automatically retry the element until the assertion is successful, even if it was rerendered between the assertions.\n:::\n\nThe package exposes two entry points: `vitest-browser-react` and `vitest-browser-react/pure`. They expose almost identical API (`pure` also exposes `configure`), but the `pure` entry point doesn't add a handler to remove the component before the next test has started.\n\n## render\n\n```ts\nexport function render(\n  ui: React.ReactNode,\n  options?: ComponentRenderOptions,\n): Promise<RenderResult>\n```\n\nThe `render` function records a `react.render` trace mark, visible in the [Trace View](/guide/browser/trace-view).\n\n:::warning\nNote that `render` is asynchronous, unlike in other packages. This is to support [`Suspense`](https://react.dev/reference/react/Suspense) correctly.\n\n```tsx\nimport { render } from 'vitest-browser-react'\nconst screen = render(<Component />) // [!code --]\nconst screen = await render(<Component />) // [!code ++]\n```\n:::\n\n### Options\n\n#### container\n\nBy default, Vitest will create a `div`, append it to `document.body`, and render your component there. If you provide your own `HTMLElement` container, it will not be appended automatically — you'll need to call `document.body.appendChild(container)` before `render`.\n\nFor example, if you are unit testing a `tbody` element, it cannot be a child of a `div`. In this case, you can specify a `table` as the render container.\n\n```jsx\nconst table = document.createElement('table')\n\nconst { container } = await render(<TableBody {...props} />, {\n  // ⚠️ appending the element to `body` manually before rendering\n  container: document.body.appendChild(table),\n})\n```\n\n#### baseElement\n\nIf the `container` is specified, then this defaults to that, otherwise this defaults to `document.body`. This is used as the base element for the queries as well as what is printed when you use `debug()`.\n\n#### wrapper\n\nPass a React Component as the `wrapper` option to have it rendered around the inner element. This is most useful for creating reusable custom render functions for common data providers. For example:\n\n```jsx\nimport React from 'react'\nimport { render } from 'vitest-browser-react'\nimport { ThemeProvider } from 'my-ui-lib'\nimport { TranslationProvider } from 'my-i18n-lib'\n\nfunction AllTheProviders({ children }) {\n  return (\n    <ThemeProvider theme=\"light\">\n      <TranslationProvider>\n        {children}\n      </TranslationProvider>\n    </ThemeProvider>\n  )\n}\n\nexport function customRender(ui, options) {\n  return render(ui, { wrapper: AllTheProviders, ...options })\n}\n```\n\n### Render Result\n\nIn addition to documented return value, the `render` function also returns all available [locators](/api/browser/locators) relative to the [`baseElement`](#baseelement), including [custom ones](/api/browser/locators#custom-locators).\n\n```tsx\nconst screen = await render(<TableBody {...props} />)\n\nawait screen.getByRole('link', { name: 'Expand' }).click()\n```\n\n#### container\n\nThe containing `div` DOM node of your rendered React Element (rendered using `ReactDOM.render`). This is a regular DOM node, so you technically could call `container.querySelector` etc. to inspect the children.\n\n:::danger\nIf you find yourself using `container` to query for rendered elements then you should reconsider! The [locators](/api/browser/locators) are designed to be more resilient to changes that will be made to the component you're testing. Avoid using `container` to query for elements!\n:::\n\n#### baseElement\n\nThe containing DOM node where your React Element is rendered in the `container`. If you don't specify the `baseElement` in the options of render, it will default to `document.body`.\n\nThis is useful when the component you want to test renders something outside the container `div`, e.g. when you want to snapshot test your portal component which renders its HTML directly in the body.\n\n:::tip\nThe queries returned by the `render` looks into `baseElement`, so you can use queries to test your portal component without the `baseElement`.\n:::\n\n#### locator\n\nThe [locator](/api/browser/locators) of your `container`. It is useful to use queries scoped only to your component, or pass it down to other assertions:\n\n```jsx\nimport { render } from 'vitest-browser-react'\n\nconst { locator } = await render(<NumberDisplay number={1} />)\n\nawait locator.getByRole('button').click()\nawait expect.element(locator).toHaveTextContent('Hello World')\n```\n\n#### debug\n\n```ts\nfunction debug(\n  el?: HTMLElement | HTMLElement[] | Locator | Locator[],\n  maxLength?: number,\n  options?: PrettyDOMOptions,\n): void\n```\n\nThis method is a shortcut for `console.log(prettyDOM(baseElement))`. It will print the DOM content of the container or specified elements to the console.\n\n#### rerender\n\n```ts\nfunction rerender(ui: React.ReactNode): Promise<void>\n```\n\nAlso records a `react.rerender` trace mark in the [Trace View](/guide/browser/trace-view).\n\nIt is better if you test the component that's doing the prop updating to ensure that the props are being updated correctly to avoid relying on implementation details in your tests. That said, if you'd prefer to update the props of a rendered component in your test, this function can be used to update props of the rendered component.\n\n```jsx\nimport { render } from 'vitest-browser-react'\n\nconst { rerender } = await render(<NumberDisplay number={1} />)\n\n// re-render the same component with different props\nawait rerender(<NumberDisplay number={2} />)\n```\n\n#### unmount\n\n```ts\nfunction unmount(): Promise<void>\n```\n\nAlso records a `react.unmount` trace mark in the [Trace View](/guide/browser/trace-view).\n\nThis will cause the rendered component to be unmounted. This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks).\n\n```jsx\nimport { render } from 'vitest-browser-react'\n\nconst { container, unmount } = await render(<Login />)\nawait unmount()\n// your component has been unmounted and now: container.innerHTML === ''\n```\n\n#### asFragment\n\n```ts\nfunction asFragment(): DocumentFragment\n```\n\nReturns a `DocumentFragment` of your rendered component. This can be useful if you need to avoid live bindings and see how your component reacts to events.\n\n## cleanup\n\n```ts\nexport function cleanup(): Promise<void>\n```\n\nRemove all components rendered with [`render`](#render).\n\n## renderHook\n\n```ts\nexport function renderHook<Props, Result>(\n  renderCallback: (initialProps?: Props) => Result,\n  options: RenderHookOptions<Props>,\n): Promise<RenderHookResult<Result, Props>>\n```\n\nThis is a convenience wrapper around `render` with a custom test component. The API emerged from a popular testing pattern and is mostly interesting for libraries publishing hooks. You should prefer `render` since a custom test component results in more readable and robust tests since the thing you want to test is not hidden behind an abstraction.\n\n```jsx\nimport { renderHook } from 'vitest-browser-react'\n\ntest('returns logged in user', async () => {\n  const { result } = await renderHook(() => useLoggedInUser())\n  expect(result.current).toEqual({ name: 'Alice' })\n})\n```\n\n### Options\n\n`renderHook` accepts the same options as [`render`](#render) with an addition to `initialProps`:\n\nIt declares the props that are passed to the render-callback when first invoked. These will not be passed if you call `rerender` without props.\n\n```jsx\nimport { renderHook } from 'vitest-browser-react'\n\ntest('returns logged in user', async () => {\n  const { result, rerender } = await renderHook((props = {}) => props, {\n    initialProps: { name: 'Alice' },\n  })\n  expect(result.current).toEqual({ name: 'Alice' })\n  await rerender()\n  expect(result.current).toEqual({ name: undefined })\n})\n```\n\n:::warning\nWhen using `renderHook` in conjunction with the `wrapper` and `initialProps` options, the `initialProps` are not passed to the `wrapper` component. To provide props to the `wrapper` component, consider a solution like this:\n\n```jsx\nfunction createWrapper(Wrapper, props) {\n  return function CreatedWrapper({ children }) {\n    return <Wrapper {...props}>{children}</Wrapper>\n  }\n}\n\n// ...\n\nawait renderHook(() => {}, {\n  wrapper: createWrapper(Wrapper, { value: 'foo' }),\n})\n```\n:::\n\n`renderHook` returns a few useful methods and properties:\n\n### Render Hook Result\n\n#### result\n\nHolds the value of the most recently committed return value of the render-callback:\n\n```jsx\nimport { useState } from 'react'\nimport { renderHook } from 'vitest-browser-react'\nimport { expect } from 'vitest'\n\nconst { result } = await renderHook(() => {\n  const [name, setName] = useState('')\n  React.useEffect(() => {\n    setName('Alice')\n  }, [])\n\n  return name\n})\n\nexpect(result.current).toBe('Alice')\n```\n\nNote that the value is held in `result.current`. Think of result as a [ref](https://react.dev/learn/referencing-values-with-refs) for the most recently committed value.\n\n#### rerender {#renderhooks-rerender}\n\nRenders the previously rendered render-callback with the new props:\n\n```jsx\nimport { renderHook } from 'vitest-browser-react'\n\nconst { rerender } = await renderHook(({ name = 'Alice' } = {}) => name)\n\n// re-render the same hook with different props\nawait rerender({ name: 'Bob' })\n```\n\n#### unmount {#renderhooks-unmount}\n\nUnmounts the test hook.\n\n```jsx\nimport { renderHook } from 'vitest-browser-react'\n\nconst { unmount } = await renderHook(({ name = 'Alice' } = {}) => name)\n\nawait unmount()\n```\n\n## Extend Queries\n\nTo extend locator queries, see [`\"Custom Locators\"`](/api/browser/locators#custom-locators). For example, to make `render` return a new custom locator, define it using the `locators.extend` API:\n\n```jsx {5-7,12}\nimport { locators } from 'vitest/browser'\nimport { render } from 'vitest-browser-react'\n\nlocators.extend({\n  getByArticleTitle(title) {\n    return `[data-title=\"${title}\"]`\n  },\n})\n\nconst screen = await render(<Component />)\nawait expect.element(\n  screen.getByArticleTitle('Hello World')\n).toBeVisible()\n```\n\n## Configuration\n\nYou can configure if the component should be rendered in Strict Mode with configure method from `vitest-browser-react/pure`:\n\n```js\nimport { configure } from 'vitest-browser-react/pure'\n\nconfigure({\n  // disabled by default\n  reactStrictMode: true,\n})\n```\n\n## See also\n\n- [React Testing Library documentation](https://testing-library.com/docs/react-testing-library/intro)\n"
  },
  {
    "path": "docs/api/browser/svelte.md",
    "content": "---\noutline: deep\n---\n\n# vitest-browser-svelte\n\nThe community [`vitest-browser-svelte`](https://npmx.dev/package/vitest-browser-svelte) package renders [Svelte](https://svelte.dev/) components in [Browser Mode](/guide/browser/).\n\n```ts\nimport { render } from 'vitest-browser-svelte'\nimport { expect, test } from 'vitest'\nimport Component from './Component.svelte'\n\ntest('counter button increments the count', async () => {\n  const screen = await render(Component, {\n    initialCount: 1,\n  })\n\n  await screen.getByRole('button', { name: 'Increment' }).click()\n\n  await expect.element(screen.getByText('Count is 2')).toBeVisible()\n})\n```\n\n::: warning\nThis library takes inspiration from [`@testing-library/svelte`](https://github.com/testing-library/svelte-testing-library).\n\nIf you have used `@testing-library/svelte` in your tests before, you can keep using it, however the `vitest-browser-svelte` package provides certain benefits unique to the Browser Mode that `@testing-library/svelte` lacks:\n\n`vitest-browser-svelte` returns APIs that interact well with built-in [locators](/api/browser/locators), [user events](/api/browser/interactivity) and [assertions](/api/browser/assertions): for example, Vitest will automatically retry the element until the assertion is successful, even if it was rerendered between the assertions.\n:::\n\nThe package exposes two entry points: `vitest-browser-svelte` and `vitest-browser-svelte/pure`. They expose identical API, but the `pure` entry point doesn't add a handler to remove the component before the next test has started.\n\n## render\n\n```ts\nexport function render<C extends Component>(\n  Component: ComponentImport<C>,\n  options?: ComponentOptions<C>,\n  renderOptions?: SetupOptions\n): RenderResult<C> & PromiseLike<RenderResult<C>>\n```\n\nThe `render` function records a `svelte.render` trace mark, visible in the [Trace View](/guide/browser/trace-view).\n\n::: warning\nSynchronous usage of `render` is deprecated and will be removed in the next major version. Please always `await` the result:\n\n```ts\nconst screen = render(Component) // [!code --]\nconst screen = await render(Component) // [!code ++]\n```\n:::\n\n### Options\n\nThe `render` function supports either options that you can pass down to [`mount`](https://svelte.dev/docs/svelte/imperative-component-api#mount) or props directly:\n\n```ts\nconst screen = await render(Component, {\n  props: { // [!code --]\n    initialCount: 1, // [!code --]\n  }, // [!code --]\n  initialCount: 1, // [!code ++]\n})\n```\n\n#### props\n\nComponent props.\n\n#### target\n\nBy default, Vitest will create a `div`, append it to `document.body`, and render your component there. If you provide your own `HTMLElement` container, it will not be appended automatically — you'll need to call `document.body.appendChild(container)` before `render`.\n\nFor example, if you are unit testing a `tbody` element, it cannot be a child of a `div`. In this case, you can specify a `table` as the render container.\n\n```ts\nconst table = document.createElement('table')\n\nconst screen = await render(TableBody, {\n  props,\n  // ⚠️ appending the element to `body` manually before rendering\n  target: document.body.appendChild(table),\n})\n```\n\n#### baseElement\n\nThis can be passed down in a third argument. You should rarely, if ever, need to use this option.\n\nIf the `target` is specified, then this defaults to that, otherwise this defaults to `document.body`. This is used as the base element for the queries as well as what is printed when you use `debug()`.\n\n### Render Result\n\nIn addition to documented return value, the `render` function also returns all available [locators](/api/browser/locators) relative to the [`baseElement`](#baseelement), including [custom ones](/api/browser/locators#custom-locators).\n\n```ts\nconst screen = await render(TableBody, props)\n\nawait screen.getByRole('link', { name: 'Expand' }).click()\n```\n\n#### container\n\nThe containing DOM node where your Svelte component is rendered. This is a regular DOM node, so you technically could call `container.querySelector` etc. to inspect the children.\n\n:::danger\nIf you find yourself using `container` to query for rendered elements then you should reconsider! The [locators](/api/browser/locators) are designed to be more resilient to changes that will be made to the component you're testing. Avoid using `container` to query for elements!\n:::\n\n#### component\n\nThe mounted Svelte component instance. You can use this to access component methods and properties if needed.\n\n```ts\nconst { component } = await render(Counter, {\n  initialCount: 0,\n})\n\n// Access component exports if needed\n```\n\n#### locator\n\nThe [locator](/api/browser/locators) of your `container`. It is useful to use queries scoped only to your component, or pass it down to other assertions:\n\n```ts\nimport { render } from 'vitest-browser-svelte'\n\nconst { locator } = await render(NumberDisplay, {\n  number: 2,\n})\n\nawait locator.getByRole('button').click()\nawait expect.element(locator).toHaveTextContent('Hello World')\n```\n\n#### debug\n\n```ts\nfunction debug(\n  el?: HTMLElement | HTMLElement[] | Locator | Locator[],\n): void\n```\n\nThis method is a shortcut for `console.log(prettyDOM(baseElement))`. It will print the DOM content of the container or specified elements to the console.\n\n#### rerender\n\n```ts\nfunction rerender(props: Partial<ComponentProps<T>>): Promise<void>\n```\n\nUpdates the component's props and waits for Svelte to apply the changes. Use this to test how your component responds to prop changes. Also records a `svelte.rerender` trace mark in the [Trace View](/guide/browser/trace-view).\n\n```ts\nimport { render } from 'vitest-browser-svelte'\n\nconst { rerender } = await render(NumberDisplay, {\n  number: 1,\n})\n\n// re-render the same component with different props\nawait rerender({ number: 2 })\n```\n\n#### unmount\n\n```ts\nfunction unmount(): Promise<void>\n```\n\nUnmount and destroy the Svelte component. Also records a `svelte.unmount` trace mark in the [Trace View](/guide/browser/trace-view). This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks).\n\n::: warning\nSynchronous usage of `unmount` is deprecated and will be removed in the next major version. Please always `await` the result.\n:::\n\n```ts\nimport { render } from 'vitest-browser-svelte'\n\nconst { container, unmount } = await render(Component)\nawait unmount()\n// your component has been unmounted and now: container.innerHTML === ''\n```\n\n## cleanup\n\n```ts\nexport function cleanup(): void\n```\n\nRemove all components rendered with [`render`](#render).\n\n## Extend Queries\n\nTo extend locator queries, see [`\"Custom Locators\"`](/api/browser/locators#custom-locators). For example, to make `render` return a new custom locator, define it using the `locators.extend` API:\n\n```ts {5-7,12}\nimport { locators } from 'vitest/browser'\nimport { render } from 'vitest-browser-svelte'\n\nlocators.extend({\n  getByArticleTitle(title) {\n    return `[data-title=\"${title}\"]`\n  },\n})\n\nconst screen = await render(Component)\nawait expect.element(\n  screen.getByArticleTitle('Hello World')\n).toBeVisible()\n```\n\n## Snippets\n\nFor simple snippets, you can use a wrapper component and \"dummy\" children to test them. Setting `data-testid` attributes can be helpful when testing slots in this manner.\n\n::: code-group\n```ts [basic.test.js]\nimport { render } from 'vitest-browser-svelte'\nimport { expect, test } from 'vitest'\n\nimport SubjectTest from './basic-snippet.test.svelte'\n\ntest('basic snippet', async () => {\n  const screen = await render(SubjectTest)\n\n  const heading = screen.getByRole('heading')\n  const child = heading.getByTestId('child')\n\n  await expect.element(child).toBeInTheDocument()\n})\n```\n```svelte [basic-snippet.svelte]\n<script>\n  let { children } = $props()\n</script>\n\n<h1>\n  {@render children?.()}\n</h1>\n```\n```svelte [basic-snippet.test.svelte]\n<script>\n  import Subject from './basic-snippet.svelte'\n</script>\n\n<Subject>\n  <span data-testid=\"child\"></span>\n</Subject>\n```\n:::\n\nFor more complex snippets, e.g. where you want to check arguments, you can use Svelte's [`createRawSnippet`](https://svelte.dev/docs/svelte/svelte#createRawSnippet) API.\n\n::: code-group\n```js [complex-snippet.test.js]\nimport { render } from 'vitest-browser-svelte'\nimport { createRawSnippet } from 'svelte'\nimport { expect, test } from 'vitest'\n\nimport Subject from './complex-snippet.svelte'\n\ntest('renders greeting in message snippet', async () => {\n  const screen = await render(Subject, {\n    name: 'Alice',\n    message: createRawSnippet(greeting => ({\n      render: () => `<span data-testid=\"message\">${greeting()}</span>`,\n    })),\n  })\n\n  const message = screen.getByTestId('message')\n\n  await expect.element(message).toHaveTextContent('Hello, Alice!')\n})\n```\n```svelte [complex-snippet.svelte]\n<script>\n  let { name, message } = $props()\n\n  const greeting = $derived(`Hello, ${name}!`)\n</script>\n\n<p>\n  {@render message?.(greeting)}\n</p>\n```\n:::\n\n## See also\n\n- [Svelte Testing Library documentation](https://testing-library.com/docs/svelte-testing-library/intro)\n- [Svelte Testing Library examples](https://github.com/testing-library/svelte-testing-library/tree/main/examples)\n"
  },
  {
    "path": "docs/api/browser/vue.md",
    "content": "---\noutline: deep\n---\n\n# vitest-browser-vue\n\nThe community [`vitest-browser-vue`](https://npmx.dev/package/vitest-browser-vue) package renders [Vue](https://vuejs.org/) components in [Browser Mode](/guide/browser/).\n\n```ts\nimport { render } from 'vitest-browser-vue'\nimport { expect, test } from 'vitest'\nimport Component from './Component.vue'\n\ntest('counter button increments the count', async () => {\n  const screen = await render(Component, {\n    props: {\n      initialCount: 1,\n    }\n  })\n\n  await screen.getByRole('button', { name: 'Increment' }).click()\n\n  await expect.element(screen.getByText('Count is 2')).toBeVisible()\n})\n```\n\n::: warning\nThis library takes inspiration from [`@testing-library/vue`](https://github.com/testing-library/vue-testing-library).\n\nIf you have used `@testing-library/vue` in your tests before, you can keep using it, however the `vitest-browser-vue` package provides certain benefits unique to the Browser Mode that `@testing-library/vue` lacks:\n\n`vitest-browser-vue` returns APIs that interact well with built-in [locators](/api/browser/locators), [user events](/api/browser/interactivity) and [assertions](/api/browser/assertions): for example, Vitest will automatically retry the element until the assertion is successful, even if it was rerendered between the assertions.\n:::\n\nThe package exposes two entry points: `vitest-browser-vue` and `vitest-browser-vue/pure`. They expose identical API, but the `pure` entry point doesn't add a handler to remove the component before the next test has started.\n\n## render\n\n```ts\nexport function render(\n  component: Component,\n  options?: ComponentRenderOptions,\n): RenderResult & PromiseLike<RenderResult>\n```\n\nThe `render` function records a `vue.render` trace mark, visible in the [Trace View](/guide/browser/trace-view).\n\n::: warning\nSynchronous usage of `render` is deprecated and will be removed in the next major version. Please always `await` the result:\n\n```ts\nconst screen = render(Component) // [!code --]\nconst screen = await render(Component) // [!code ++]\n```\n:::\n\n### Options\n\nThe `render` function supports all [`mount` options](https://test-utils.vuejs.org/api/#mount) from `@vue/test-utils` (except `attachTo` - use `container` instead). In addition to them, there are also `container` and `baseElement`.\n\n#### container\n\nBy default, Vitest will create a `div`, append it to `document.body`, and render your component there. If you provide your own `HTMLElement` container, it will not be appended automatically — you'll need to call `document.body.appendChild(container)` before `render`.\n\nFor example, if you are unit testing a `tbody` element, it cannot be a child of a `div`. In this case, you can specify a `table` as the render container.\n\n```js\nconst table = document.createElement('table')\n\nconst { container } = await render(TableBody, {\n  props,\n  // ⚠️ appending the element to `body` manually before rendering\n  container: document.body.appendChild(table),\n})\n```\n\n#### baseElement\n\nIf the `container` is specified, then this defaults to that, otherwise this defaults to `document.body`. This is used as the base element for the queries as well as what is printed when you use `debug()`.\n\n### Render Result\n\nIn addition to documented return value, the `render` function also returns all available [locators](/api/browser/locators) relative to the [`baseElement`](#baseelement), including [custom ones](/api/browser/locators#custom-locators).\n\n```ts\nconst screen = await render(TableBody, { props })\n\nawait screen.getByRole('link', { name: 'Expand' }).click()\n```\n\n#### container\n\nThe containing DOM node where your Vue component is rendered. This is a regular DOM node, so you technically could call `container.querySelector` etc. to inspect the children.\n\n:::danger\nIf you find yourself using `container` to query for rendered elements then you should reconsider! The [locators](/api/browser/locators) are designed to be more resilient to changes that will be made to the component you're testing. Avoid using `container` to query for elements!\n:::\n\n#### baseElement\n\nThe containing DOM node where your Vue component is rendered in the `container`. If you don't specify the `baseElement` in the options of render, it will default to `document.body`.\n\nThis is useful when the component you want to test renders something outside the container `div`, e.g. when you want to snapshot test your portal component which renders its HTML directly in the body.\n\n:::tip\nThe queries returned by the `render` looks into `baseElement`, so you can use queries to test your portal component without the `baseElement`.\n:::\n\n#### locator\n\nThe [locator](/api/browser/locators) of your `container`. It is useful to use queries scoped only to your component, or pass it down to other assertions:\n\n```js\nimport { render } from 'vitest-browser-vue'\n\nconst { locator } = await render(NumberDisplay, {\n  props: { number: 2 }\n})\n\nawait locator.getByRole('button').click()\nawait expect.element(locator).toHaveTextContent('Hello World')\n```\n\n#### debug\n\n```ts\nfunction debug(\n  el?: HTMLElement | HTMLElement[] | Locator | Locator[],\n  maxLength?: number,\n  options?: PrettyDOMOptions,\n): void\n```\n\nThis method is a shortcut for `console.log(prettyDOM(baseElement))`. It will print the DOM content of the container or specified elements to the console.\n\n#### rerender\n\n```ts\nfunction rerender(props: Partial<Props>): void & PromiseLike<void>\n```\n\nAlso records a `vue.rerender` trace mark in the [Trace View](/guide/browser/trace-view).\n\nIt is better if you test the component that's doing the prop updating to ensure that the props are being updated correctly to avoid relying on implementation details in your tests. That said, if you'd prefer to update the props of a rendered component in your test, this function can be used to update props of the rendered component.\n\n::: warning\nSynchronous usage of `rerender` is deprecated and will be removed in the next major version. Please always `await` the result.\n:::\n\n```js\nimport { render } from 'vitest-browser-vue'\n\nconst { rerender } = await render(NumberDisplay, { props: { number: 1 } })\n\n// re-render the same component with different props\nawait rerender({ number: 2 })\n```\n\n#### unmount\n\n```ts\nfunction unmount(): void & PromiseLike<void>\n```\n\nThis will cause the rendered component to be unmounted. Also records a `vue.unmount` trace mark in the [Trace View](/guide/browser/trace-view). This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks).\n\n::: warning\nSynchronous usage of `unmount` is deprecated and will be removed in the next major version. Please always `await` the result.\n:::\n\n#### emitted\n\n```ts\nfunction emitted<T = unknown>(): Record<string, T[]>\nfunction emitted<T = unknown[]>(eventName: string): undefined | T[]\n```\n\nReturns the emitted events from the Component.\n\n::: warning\nEmitted values are an implementation detail not exposed directly to the user, so it is better to test how your emitted values are changing the displayed content by using [locators](/api/browser/locators) instead.\n:::\n\n## cleanup\n\n```ts\nexport function cleanup(): void\n```\n\nRemove all components rendered with [`render`](#render).\n\n## Extend Queries\n\nTo extend locator queries, see [`\"Custom Locators\"`](/api/browser/locators#custom-locators). For example, to make `render` return a new custom locator, define it using the `locators.extend` API:\n\n```js {5-7,12}\nimport { locators } from 'vitest/browser'\nimport { render } from 'vitest-browser-vue'\n\nlocators.extend({\n  getByArticleTitle(title) {\n    return `[data-title=\"${title}\"]`\n  },\n})\n\nconst screen = await render(Component)\nawait expect.element(\n  screen.getByArticleTitle('Hello World')\n).toBeVisible()\n```\n\n## Configuration\n\nYou can configure [Vue Test Utils](https://test-utils.vuejs.org/api/#config) options by assigning properties to the `config` export (available in both `vitest-browser-vue` and `vitest-browser-vue/pure`):\n\n```js\nimport { config } from 'vitest-browser-vue/pure'\n\nconfig.global.stubs.CustomComponent = {\n  template: '<div></div>',\n}\n```\n\n## See also\n\n- [Vue Testing Library documentation](https://testing-library.com/docs/vue-testing-library/intro)\n"
  },
  {
    "path": "docs/api/describe.md",
    "content": "---\noutline: deep\n---\n\n# describe\n\n- **Alias:** `suite`\n\n```ts\nfunction describe(\n  name: string | Function,\n  body?: () => unknown,\n  timeout?: number\n): void\nfunction describe(\n  name: string | Function,\n  options: SuiteOptions,\n  body?: () => unknown,\n): void\n```\n\n`describe` is used to group related tests and benchmarks into a suite. Suites help organize your test files by creating logical blocks, making test output easier to read and enabling shared setup/teardown through [lifecycle hooks](/api/hooks).\n\nWhen you use `test` in the top level of file, they are collected as part of the implicit suite for it. Using `describe` you can define a new suite in the current context, as a set of related tests or benchmarks and other nested suites.\n\n```ts [basic.spec.ts]\nimport { describe, expect, test } from 'vitest'\n\nconst person = {\n  isActive: true,\n  age: 32,\n}\n\ndescribe('person', () => {\n  test('person is defined', () => {\n    expect(person).toBeDefined()\n  })\n\n  test('is active', () => {\n    expect(person.isActive).toBeTruthy()\n  })\n\n  test('age limit', () => {\n    expect(person.age).toBeLessThanOrEqual(32)\n  })\n})\n```\n\nYou can also nest `describe` blocks if you have a hierarchy of tests:\n\n```ts\nimport { describe, expect, test } from 'vitest'\n\nfunction numberToCurrency(value: number | string) {\n  if (typeof value !== 'number') {\n    throw new TypeError('Value must be a number')\n  }\n\n  return value.toFixed(2).toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')\n}\n\ndescribe('numberToCurrency', () => {\n  describe('given an invalid number', () => {\n    test('composed of non-numbers to throw error', () => {\n      expect(() => numberToCurrency('abc')).toThrow()\n    })\n  })\n\n  describe('given a valid number', () => {\n    test('returns the correct currency format', () => {\n      expect(numberToCurrency(10000)).toBe('10,000.00')\n    })\n  })\n})\n```\n\n## Test Options\n\nYou can use [test options](/api/test#test-options) to apply configuration to every test inside a suite, including nested suites. This is useful when you want to set timeouts, retries, or other options for a group of related tests.\n\n```ts\nimport { describe, test } from 'vitest'\n\ndescribe('slow tests', { timeout: 10_000 }, () => {\n  test('test 1', () => { /* ... */ })\n  test('test 2', () => { /* ... */ })\n\n  // nested suites also inherit the timeout\n  describe('nested', () => {\n    test('test 3', () => { /* ... */ })\n  })\n})\n```\n\n### `shuffle`\n\n- **Type:** `boolean`\n- **Default:** `false` (configured by [`sequence.shuffle`](/config/sequence#sequence-shuffle))\n- **Alias:** [`describe.shuffle`](#describe-shuffle)\n\nRun tests within the suite in random order. This option is inherited by nested suites.\n\n```ts\nimport { describe, test } from 'vitest'\n\ndescribe('randomized tests', { shuffle: true }, () => {\n  test('test 1', () => { /* ... */ })\n  test('test 2', () => { /* ... */ })\n  test('test 3', () => { /* ... */ })\n})\n```\n\n## describe.skip\n\n- **Alias:** `suite.skip`\n\nUse `describe.skip` in a suite to avoid running a particular describe block.\n\n```ts\nimport { assert, describe, test } from 'vitest'\n\ndescribe.skip('skipped suite', () => {\n  test('sqrt', () => {\n    // Suite skipped, no error\n    assert.equal(Math.sqrt(4), 3)\n  })\n})\n```\n\n## describe.skipIf\n\n- **Alias:** `suite.skipIf`\n\nIn some cases, you might run suites multiple times with different environments, and some of the suites might be environment-specific. Instead of wrapping the suite with `if`, you can use `describe.skipIf` to skip the suite whenever the condition is truthy.\n\n```ts\nimport { describe, test } from 'vitest'\n\nconst isDev = process.env.NODE_ENV === 'development'\n\ndescribe.skipIf(isDev)('prod only test suite', () => {\n  // this test suite only runs in production\n})\n```\n\n## describe.runIf\n\n- **Alias:** `suite.runIf`\n\nOpposite of [describe.skipIf](#describe-skipif).\n\n```ts\nimport { assert, describe, test } from 'vitest'\n\nconst isDev = process.env.NODE_ENV === 'development'\n\ndescribe.runIf(isDev)('dev only test suite', () => {\n  // this test suite only runs in development\n})\n```\n\n## describe.only\n\n- **Alias:** `suite.only`\n\nUse `describe.only` to only run certain suites\n\n```ts\nimport { assert, describe, test } from 'vitest'\n\n// Only this suite (and others marked with only) are run\ndescribe.only('suite', () => {\n  test('sqrt', () => {\n    assert.equal(Math.sqrt(4), 3)\n  })\n})\n\ndescribe('other suite', () => {\n  // ... will be skipped\n})\n```\n\nSometimes it is very useful to run `only` tests in a certain file, ignoring all other tests from the whole test suite, which pollute the output.\n\nIn order to do that, run `vitest` with specific file containing the tests in question:\n\n```shell\nvitest interesting.test.ts\n```\n\n## describe.concurrent\n\n- **Alias:** `suite.concurrent`\n\n`describe.concurrent` runs all inner suites and tests in parallel\n\n```ts\nimport { describe, test } from 'vitest'\n\n// All suites and tests within this suite will be run in parallel\ndescribe.concurrent('suite', () => {\n  test('concurrent test 1', async () => { /* ... */ })\n  describe('concurrent suite 2', async () => {\n    test('concurrent test inner 1', async () => { /* ... */ })\n    test('concurrent test inner 2', async () => { /* ... */ })\n  })\n  test.concurrent('concurrent test 3', async () => { /* ... */ })\n})\n```\n\n`.skip`, `.only`, and `.todo` works with concurrent suites. All the following combinations are valid:\n\n```ts\ndescribe.concurrent(/* ... */)\ndescribe.skip.concurrent(/* ... */) // or describe.concurrent.skip(/* ... */)\ndescribe.only.concurrent(/* ... */) // or describe.concurrent.only(/* ... */)\ndescribe.todo.concurrent(/* ... */) // or describe.concurrent.todo(/* ... */)\n```\n\nWhen running concurrent tests, Snapshots and Assertions must use `expect` from the local [Test Context](/guide/test-context) to ensure the right test is detected.\n\n```ts\ndescribe.concurrent('suite', () => {\n  test('concurrent test 1', async ({ expect }) => {\n    expect(foo).toMatchSnapshot()\n  })\n  test('concurrent test 2', async ({ expect }) => {\n    expect(foo).toMatchSnapshot()\n  })\n})\n```\n\n## describe.sequential\n\n- **Alias:** `suite.sequential`\n\n`describe.sequential` in a suite marks every test as sequential. This is useful if you want to run tests in sequence within `describe.concurrent` or with the `--sequence.concurrent` command option.\n\n```ts\nimport { describe, test } from 'vitest'\n\ndescribe.concurrent('suite', () => {\n  test('concurrent test 1', async () => { /* ... */ })\n  test('concurrent test 2', async () => { /* ... */ })\n\n  describe.sequential('', () => {\n    test('sequential test 1', async () => { /* ... */ })\n    test('sequential test 2', async () => { /* ... */ })\n  })\n})\n```\n\n## describe.shuffle\n\n- **Alias:** `suite.shuffle`\n\nVitest provides a way to run all tests in random order via CLI flag [`--sequence.shuffle`](/guide/cli) or config option [`sequence.shuffle`](/config/sequence#sequence-shuffle), but if you want to have only part of your test suite to run tests in random order, you can mark it with this flag.\n\n```ts\nimport { describe, test } from 'vitest'\n\n// or describe('suite', { shuffle: true }, ...)\ndescribe.shuffle('suite', () => {\n  test('random test 1', async () => { /* ... */ })\n  test('random test 2', async () => { /* ... */ })\n  test('random test 3', async () => { /* ... */ })\n\n  // `shuffle` is inherited\n  describe('still random', () => {\n    test('random 4.1', async () => { /* ... */ })\n    test('random 4.2', async () => { /* ... */ })\n  })\n\n  // disable shuffle inside\n  describe('not random', { shuffle: false }, () => {\n    test('in order 5.1', async () => { /* ... */ })\n    test('in order 5.2', async () => { /* ... */ })\n  })\n})\n// order depends on sequence.seed option in config (Date.now() by default)\n```\n\n`.skip`, `.only`, and `.todo` works with random suites.\n\n## describe.todo\n\n- **Alias:** `suite.todo`\n\nUse `describe.todo` to stub suites to be implemented later. An entry will be shown in the report for the tests so you know how many tests you still need to implement.\n\n```ts\n// An entry will be shown in the report for this suite\ndescribe.todo('unimplemented suite')\n```\n\n## describe.each\n\n- **Alias:** `suite.each`\n\n::: tip\nWhile `describe.each` is provided for Jest compatibility,\nVitest also has [`describe.for`](#describe-for) which simplifies argument types and aligns with [`test.for`](/api/test#test-for).\n:::\n\nUse `describe.each` if you have more than one test that depends on the same data.\n\n```ts\nimport { describe, expect, test } from 'vitest'\n\ndescribe.each([\n  { a: 1, b: 1, expected: 2 },\n  { a: 1, b: 2, expected: 3 },\n  { a: 2, b: 1, expected: 3 },\n])('describe object add($a, $b)', ({ a, b, expected }) => {\n  test(`returns ${expected}`, () => {\n    expect(a + b).toBe(expected)\n  })\n\n  test(`returned value not be greater than ${expected}`, () => {\n    expect(a + b).not.toBeGreaterThan(expected)\n  })\n\n  test(`returned value not be less than ${expected}`, () => {\n    expect(a + b).not.toBeLessThan(expected)\n  })\n})\n```\n\n* First row should be column names, separated by `|`;\n* One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.\n\n```ts\nimport { describe, expect, test } from 'vitest'\n\ndescribe.each`\n  a               | b      | expected\n  ${1}            | ${1}   | ${2}\n  ${'a'}          | ${'b'} | ${'ab'}\n  ${[]}           | ${'b'} | ${'b'}\n  ${{}}           | ${'b'} | ${'[object Object]b'}\n  ${{ asd: 1 }}   | ${'b'} | ${'[object Object]b'}\n`('describe template string add($a, $b)', ({ a, b, expected }) => {\n  test(`returns ${expected}`, () => {\n    expect(a + b).toBe(expected)\n  })\n})\n```\n\n## describe.for\n\n- **Alias:** `suite.for`\n\nThe difference from `describe.each` is how array case is provided in the arguments.\nOther non array case (including template string usage) works exactly same.\n\n```ts\n// `each` spreads array case\ndescribe.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('add(%i, %i) -> %i', (a, b, expected) => { // [!code --]\n  test('test', () => {\n    expect(a + b).toBe(expected)\n  })\n})\n\n// `for` doesn't spread array case\ndescribe.for([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('add(%i, %i) -> %i', ([a, b, expected]) => { // [!code ++]\n  test('test', () => {\n    expect(a + b).toBe(expected)\n  })\n})\n```\n"
  },
  {
    "path": "docs/api/expect-typeof.md",
    "content": "# expectTypeOf\n\n::: warning\nDuring runtime this function doesn't do anything. To [enable typechecking](/guide/testing-types#run-typechecking), don't forget to pass down `--typecheck` flag.\n:::\n\n- **Type:** `<T>(a: unknown) => ExpectTypeOf`\n\n## not\n\n- **Type:** `ExpectTypeOf`\n\nYou can negate all assertions, using `.not` property.\n\n## toEqualTypeOf\n\n- **Type:** `<T>(expected: T) => void`\n\nThis matcher will check if the types are fully equal to each other. This matcher will not fail if two objects have different values, but the same type. It will fail however if an object is missing a property.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf({ a: 1 }).toEqualTypeOf<{ a: number }>()\nexpectTypeOf({ a: 1 }).toEqualTypeOf({ a: 1 })\nexpectTypeOf({ a: 1 }).toEqualTypeOf({ a: 2 })\nexpectTypeOf({ a: 1, b: 1 }).not.toEqualTypeOf<{ a: number }>()\n```\n\n## toMatchTypeOf\n\n- **Type:** `<T>(expected: T) => void`\n\n::: warning DEPRECATED\nThis matcher has been deprecated since expect-type v1.2.0. Use [`toExtend`](#toextend) instead.\n:::\nThis matcher checks if expect type extends provided type. It is different from `toEqual` and is more similar to [expect's](/api/expect) `toMatchObject()`. With this matcher, you can check if an object “matches” a type.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf({ a: 1, b: 1 }).toMatchTypeOf({ a: 1 })\nexpectTypeOf<number>().toMatchTypeOf<string | number>()\nexpectTypeOf<string | number>().not.toMatchTypeOf<number>()\n```\n\n## toExtend\n\n- **Type:** `<T>(expected: T) => void`\n\nThis matcher checks if expect type extends provided type. It is different from `toEqual` and is more similar to [expect's](/api/expect) `toMatchObject()`. With this matcher, you can check if an object \"matches\" a type.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf({ a: 1, b: 1 }).toExtend({ a: 1 })\nexpectTypeOf<number>().toExtend<string | number>()\nexpectTypeOf<string | number>().not.toExtend<number>()\n```\n\n## toMatchObjectType\n\n- **Type:** `() => void`\n\nThis matcher performs a strict check on object types, ensuring that the expected type matches the provided object type. It's stricter than [`toExtend`](#toextend) and is the recommended choice when working with object types as it's more likely to catch issues like readonly properties.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf({ a: 1, b: 2 }).toMatchObjectType<{ a: number }>() // preferred\nexpectTypeOf({ a: 1, b: 2 }).toExtend<{ a: number }>() // works but less strict\n\n// Supports nested object checking\nconst user = {\n  name: 'John',\n  address: { city: 'New York', zip: '10001' }\n}\nexpectTypeOf(user).toMatchObjectType<{ name: string; address: { city: string } }>()\n```\n\n::: warning\nThis matcher only works with plain object types. It will fail for union types and other complex types. For those cases, use [`toExtend`](#toextend) instead.\n:::\n\n## extract\n\n- **Type:** `ExpectTypeOf<ExtractedUnion>`\n\nYou can use `.extract` to narrow down types for further testing.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\ntype ResponsiveProp<T> = T | T[] | { xs?: T; sm?: T; md?: T }\n\ninterface CSSProperties { margin?: string; padding?: string }\n\nfunction getResponsiveProp<T>(_props: T): ResponsiveProp<T> {\n  return {}\n}\n\nconst cssProperties: CSSProperties = { margin: '1px', padding: '2px' }\n\nexpectTypeOf(getResponsiveProp(cssProperties))\n  .extract<{ xs?: any }>() // extracts the last type from a union\n  .toEqualTypeOf<{ xs?: CSSProperties; sm?: CSSProperties; md?: CSSProperties }>()\n\nexpectTypeOf(getResponsiveProp(cssProperties))\n  .extract<unknown[]>() // extracts an array from a union\n  .toEqualTypeOf<CSSProperties[]>()\n```\n\n::: warning\nIf no type is found in the union, `.extract` will return `never`.\n:::\n\n## exclude\n\n- **Type:** `ExpectTypeOf<NonExcludedUnion>`\n\nYou can use `.exclude` to remove types from a union for further testing.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\ntype ResponsiveProp<T> = T | T[] | { xs?: T; sm?: T; md?: T }\n\ninterface CSSProperties { margin?: string; padding?: string }\n\nfunction getResponsiveProp<T>(_props: T): ResponsiveProp<T> {\n  return {}\n}\n\nconst cssProperties: CSSProperties = { margin: '1px', padding: '2px' }\n\nexpectTypeOf(getResponsiveProp(cssProperties))\n  .exclude<unknown[]>()\n  .exclude<{ xs?: unknown }>() // or just .exclude<unknown[] | { xs?: unknown }>()\n  .toEqualTypeOf<CSSProperties>()\n```\n\n::: warning\nIf no type is found in the union, `.exclude` will return `never`.\n:::\n\n## returns\n\n- **Type:** `ExpectTypeOf<ReturnValue>`\n\nYou can use `.returns` to extract return value of a function type.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(() => {}).returns.toBeVoid()\nexpectTypeOf((a: number) => [a, a]).returns.toEqualTypeOf([1, 2])\n```\n\n::: warning\nIf used on a non-function type, it will return `never`, so you won't be able to chain it with other matchers.\n:::\n\n## parameters\n\n- **Type:** `ExpectTypeOf<Parameters>`\n\nYou can extract function arguments with `.parameters` to perform assertions on its value. Parameters are returned as an array.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\ntype NoParam = () => void\ntype HasParam = (s: string) => void\n\nexpectTypeOf<NoParam>().parameters.toEqualTypeOf<[]>()\nexpectTypeOf<HasParam>().parameters.toEqualTypeOf<[string]>()\n```\n\n::: warning\nIf used on a non-function type, it will return `never`, so you won't be able to chain it with other matchers.\n:::\n\n::: tip\nYou can also use [`.toBeCallableWith`](#tobecallablewith) matcher as a more expressive assertion.\n:::\n\n## parameter\n\n- **Type:** `(nth: number) => ExpectTypeOf`\n\nYou can extract a certain function argument with `.parameter(number)` call to perform other assertions on it.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nfunction foo(a: number, b: string) {\n  return [a, b]\n}\n\nexpectTypeOf(foo).parameter(0).toBeNumber()\nexpectTypeOf(foo).parameter(1).toBeString()\n```\n\n::: warning\nIf used on a non-function type, it will return `never`, so you won't be able to chain it with other matchers.\n:::\n\n## constructorParameters\n\n- **Type:** `ExpectTypeOf<ConstructorParameters>`\n\nYou can extract constructor parameters as an array of values and perform assertions on them with this method.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(Date).constructorParameters.toEqualTypeOf<[] | [string | number | Date]>()\n```\n\n::: warning\nIf used on a non-function type, it will return `never`, so you won't be able to chain it with other matchers.\n:::\n\n::: tip\nYou can also use [`.toBeConstructibleWith`](#tobeconstructiblewith) matcher as a more expressive assertion.\n:::\n\n## instance\n\n- **Type:** `ExpectTypeOf<ConstructableInstance>`\n\nThis property gives access to matchers that can be performed on an instance of the provided class.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(Date).instance.toHaveProperty('toISOString')\n```\n\n::: warning\nIf used on a non-function type, it will return `never`, so you won't be able to chain it with other matchers.\n:::\n\n## items\n\n- **Type:** `ExpectTypeOf<T>`\n\nYou can get array item type with `.items` to perform further assertions.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf([1, 2, 3]).items.toEqualTypeOf<number>()\nexpectTypeOf([1, 2, 3]).items.not.toEqualTypeOf<string>()\n```\n\n## resolves\n\n- **Type:** `ExpectTypeOf<ResolvedPromise>`\n\nThis matcher extracts resolved value of a `Promise`, so you can perform other assertions on it.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nasync function asyncFunc() {\n  return 123\n}\n\nexpectTypeOf(asyncFunc).returns.resolves.toBeNumber()\nexpectTypeOf(Promise.resolve('string')).resolves.toBeString()\n```\n\n::: warning\nIf used on a non-promise type, it will return `never`, so you won't be able to chain it with other matchers.\n:::\n\n## guards\n\n- **Type:** `ExpectTypeOf<Guard>`\n\nThis matcher extracts guard value (e.g., `v is number`), so you can perform assertions on it.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nfunction isString(v: any): v is string {\n  return typeof v === 'string'\n}\nexpectTypeOf(isString).guards.toBeString()\n```\n\n::: warning\nReturns `never`, if the value is not a guard function, so you won't be able to chain it with other matchers.\n:::\n\n## asserts\n\n- **Type:** `ExpectTypeOf<Assert>`\n\nThis matcher extracts assert value (e.g., `assert v is number`), so you can perform assertions on it.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nfunction assertNumber(v: any): asserts v is number {\n  if (typeof v !== 'number') {\n    throw new TypeError('Nope !')\n  }\n}\n\nexpectTypeOf(assertNumber).asserts.toBeNumber()\n```\n\n::: warning\nReturns `never`, if the value is not an assert function, so you won't be able to chain it with other matchers.\n:::\n\n## toBeAny\n\n- **Type:** `() => void`\n\nWith this matcher you can check, if provided type is `any` type. If the type is too specific, the test will fail.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf<any>().toBeAny()\nexpectTypeOf({} as any).toBeAny()\nexpectTypeOf('string').not.toBeAny()\n```\n\n## toBeUnknown\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is `unknown` type.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf().toBeUnknown()\nexpectTypeOf({} as unknown).toBeUnknown()\nexpectTypeOf('string').not.toBeUnknown()\n```\n\n## toBeNever\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is a `never` type.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf<never>().toBeNever()\nexpectTypeOf((): never => {}).returns.toBeNever()\n```\n\n## toBeFunction\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is a `function`.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(42).not.toBeFunction()\nexpectTypeOf((): never => {}).toBeFunction()\n```\n\n## toBeObject\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is an `object`.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(42).not.toBeObject()\nexpectTypeOf({}).toBeObject()\n```\n\n## toBeArray\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is `Array<T>`.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(42).not.toBeArray()\nexpectTypeOf([]).toBeArray()\nexpectTypeOf([1, 2]).toBeArray()\nexpectTypeOf([{}, 42]).toBeArray()\n```\n\n## toBeString\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is a `string`.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(42).not.toBeString()\nexpectTypeOf('').toBeString()\nexpectTypeOf('a').toBeString()\n```\n\n## toBeBoolean\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is `boolean`.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(42).not.toBeBoolean()\nexpectTypeOf(true).toBeBoolean()\nexpectTypeOf<boolean>().toBeBoolean()\n```\n\n## toBeVoid\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is `void`.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(() => {}).returns.toBeVoid()\nexpectTypeOf<void>().toBeVoid()\n```\n\n## toBeSymbol\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is a `symbol`.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(Symbol(1)).toBeSymbol()\nexpectTypeOf<symbol>().toBeSymbol()\n```\n\n## toBeNull\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is `null`.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(null).toBeNull()\nexpectTypeOf<null>().toBeNull()\nexpectTypeOf(undefined).not.toBeNull()\n```\n\n## toBeUndefined\n\n- **Type:** `() => void`\n\nThis matcher checks, if provided type is `undefined`.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(undefined).toBeUndefined()\nexpectTypeOf<undefined>().toBeUndefined()\nexpectTypeOf(null).not.toBeUndefined()\n```\n\n## toBeNullable\n\n- **Type:** `() => void`\n\nThis matcher checks, if you can use `null` or `undefined` with provided type.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf<undefined | 1>().toBeNullable()\nexpectTypeOf<null | 1>().toBeNullable()\nexpectTypeOf<undefined | null | 1>().toBeNullable()\n```\n\n## toBeCallableWith\n\n- **Type:** `() => void`\n\nThis matcher ensures you can call provided function with a set of parameters.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\ntype NoParam = () => void\ntype HasParam = (s: string) => void\n\nexpectTypeOf<NoParam>().toBeCallableWith()\nexpectTypeOf<HasParam>().toBeCallableWith('some string')\n```\n\n::: warning\nIf used on a non-function type, it will return `never`, so you won't be able to chain it with other matchers.\n:::\n\n## toBeConstructibleWith\n\n- **Type:** `() => void`\n\nThis matcher ensures you can create a new instance with a set of constructor parameters.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nexpectTypeOf(Date).toBeConstructibleWith(new Date())\nexpectTypeOf(Date).toBeConstructibleWith('01-01-2000')\n```\n\n::: warning\nIf used on a non-function type, it will return `never`, so you won't be able to chain it with other matchers.\n:::\n\n## toHaveProperty\n\n- **Type:** `<K extends keyof T>(property: K) => ExpectTypeOf<T[K>`\n\nThis matcher checks if a property exists on the provided object. If it exists, it also returns the same set of matchers for the type of this property, so you can chain assertions one after another.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\nconst obj = { a: 1, b: '' }\n\nexpectTypeOf(obj).toHaveProperty('a')\nexpectTypeOf(obj).not.toHaveProperty('c')\n\nexpectTypeOf(obj).toHaveProperty('a').toBeNumber()\nexpectTypeOf(obj).toHaveProperty('b').toBeString()\nexpectTypeOf(obj).toHaveProperty('a').not.toBeString()\n```\n\n## branded\n\n- **Type:** `ExpectTypeOf<BrandedType>`\n\nYou can use `.branded` to allow type assertions to succeed for types that are semantically equivalent but differ in representation.\n\n```ts\nimport { expectTypeOf } from 'vitest'\n\n// Without .branded, this fails even though the types are effectively the same\nexpectTypeOf<{ a: { b: 1 } & { c: 1 } }>().toEqualTypeOf<{ a: { b: 1; c: 1 } }>()\n\n// With .branded, the assertion succeeds\nexpectTypeOf<{ a: { b: 1 } & { c: 1 } }>().branded.toEqualTypeOf<{ a: { b: 1; c: 1 } }>()\n```\n\n::: warning\nThis helper comes at a performance cost and can cause the TypeScript compiler to 'give up' if used with excessively deep types. Use it sparingly and only when necessary.\n:::\n"
  },
  {
    "path": "docs/api/expect.md",
    "content": "# expect\n\nThe following types are used in the type signatures below\n\n```ts\ntype Awaitable<T> = T | PromiseLike<T>\n```\n\n`expect` is used to create assertions. In this context `assertions` are functions that can be called to assert a statement. Vitest provides `chai` assertions by default and also `Jest` compatible assertions built on top of `chai`. Since Vitest 4.1, for spy/mock testing, Vitest also provides Chai-style assertions (e.g., [`expect(spy).to.have.been.called()`](#called)) alongside Jest-style assertions (e.g., `expect(spy).toHaveBeenCalled()`). Unlike `Jest`, Vitest supports a message as the second argument - if the assertion fails, the error message will be equal to it.\n\n```ts\nexport interface ExpectStatic extends Chai.ExpectStatic, AsymmetricMatchersContaining {\n  <T>(actual: T, message?: string): Assertion<T>\n  extend: (expects: MatchersObject) => void\n  anything: () => any\n  any: (constructor: unknown) => any\n  getState: () => MatcherState\n  setState: (state: Partial<MatcherState>) => void\n  not: AsymmetricMatchersContaining\n}\n```\n\nFor example, this code asserts that an `input` value is equal to `2`. If it's not, the assertion will throw an error, and the test will fail.\n\n```ts twoslash\nimport { expect } from 'vitest'\n\nconst input = Math.sqrt(4)\n\nexpect(input).to.equal(2) // chai API\nexpect(input).toBe(2) // jest API\n```\n\nTechnically this example doesn't use [`test`](/api/test) function, so in the console you will see Node.js error instead of Vitest output. To learn more about `test`, please read [Test API Reference](/api/test).\n\nAlso, `expect` can be used statically to access matcher functions, described later, and more.\n\n::: warning\n`expect` has no effect on testing types, if the expression doesn't have a type error. If you want to use Vitest as [type checker](/guide/testing-types), use [`expectTypeOf`](/api/expect-typeof) or [`assertType`](/api/assert-type).\n:::\n\n## assert\n\n- **Type:** `Chai.AssertStatic`\n\nVitest reexports chai's [`assert` API](https://www.chaijs.com/api/assert/) as `expect.assert` for convenience. You can see the supported methods on the [Assert API page](/api/assert).\n\nThis is especially useful if you need to narrow down the type, since `expect.to*` methods do not support that:\n\n```ts\ninterface Cat {\n  __type: 'Cat'\n  mew(): void\n}\ninterface Dog {\n  __type: 'Dog'\n  bark(): void\n}\ntype Animal = Cat | Dog\n\nconst animal: Animal = { __type: 'Dog', bark: () => {} }\n\nexpect.assert(animal.__type === 'Dog')\n// does not show a type error!\nexpect(animal.bark()).toBeUndefined()\n```\n\n::: tip\nNote that `expect.assert` also supports other type-narrowing methods (like `assert.isDefined`, `assert.exists` and so on).\n:::\n\n## soft\n\n- **Type:** `ExpectStatic & (actual: any) => Assertions`\n\n`expect.soft` functions similarly to `expect`, but instead of terminating the test execution upon a failed assertion, it continues running and marks the failure as a test failure. All errors encountered during the test will be displayed until the test is completed.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('expect.soft test', () => {\n  expect.soft(1 + 1).toBe(3) // mark the test as fail and continue\n  expect.soft(1 + 2).toBe(4) // mark the test as fail and continue\n})\n// reporter will report both errors at the end of the run\n```\n\nIt can also be used with `expect`. if `expect` assertion fails, the test will be terminated and all errors will be displayed.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('expect.soft test', () => {\n  expect.soft(1 + 1).toBe(3) // mark the test as fail and continue\n  expect(1 + 2).toBe(4) // failed and terminate the test, all previous errors will be output\n  expect.soft(1 + 3).toBe(5) // do not run\n})\n```\n\n::: warning\n`expect.soft` can only be used inside the [`test`](/api/test) function.\n:::\n\n## poll\n\n```ts\ninterface ExpectPoll extends ExpectStatic {\n  (actual: () => T, options?: { interval?: number; timeout?: number; message?: string }): Promise<Assertions<T>>\n}\n```\n\n`expect.poll` reruns the _assertion_ until it is succeeded. You can configure how many times Vitest should rerun the `expect.poll` callback by setting `interval` and `timeout` options.\n\nIf an error is thrown inside the `expect.poll` callback, Vitest will retry again until the timeout runs out.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('element exists', async () => {\n  asyncInjectElement()\n\n  await expect.poll(() => document.querySelector('.element')).toBeTruthy()\n})\n```\n\n::: warning\n`expect.poll` makes every assertion asynchronous, so you need to await it. Since Vitest 3, if you forget to await it, the test will fail with a warning to do so.\n\n`expect.poll` doesn't work with several matchers:\n\n- Snapshot matchers are not supported because they will always succeed. If your condition is flaky, consider using [`vi.waitFor`](/api/vi#vi-waitfor) instead to resolve it first:\n\n```ts\nimport { expect, vi } from 'vitest'\n\nconst flakyValue = await vi.waitFor(() => getFlakyValue())\nexpect(flakyValue).toMatchSnapshot()\n```\n\n- `.resolves` and `.rejects` are not supported. `expect.poll` already awaits the condition if it's asynchronous.\n- `toThrow` and its aliases are not supported because the `expect.poll` condition is always resolved before the matcher gets the value\n:::\n\n## not\n\nUsing `not` will negate the assertion. For example, this code asserts that an `input` value is not equal to `2`. If it's equal, the assertion will throw an error, and the test will fail.\n\n```ts\nimport { expect, test } from 'vitest'\n\nconst input = Math.sqrt(16)\n\nexpect(input).not.to.equal(2) // chai API\nexpect(input).not.toBe(2) // jest API\n```\n\n## toBe\n\n- **Type:** `(value: any) => Awaitable<void>`\n\n`toBe` can be used to assert if primitives are equal or that objects share the same reference. It is equivalent of calling `expect(Object.is(3, 3)).toBe(true)`. If the objects are not the same, but you want to check if their structures are identical, you can use [`toEqual`](#toequal).\n\nFor example, the code below checks if the trader has 13 apples.\n\n```ts\nimport { expect, test } from 'vitest'\n\nconst stock = {\n  type: 'apples',\n  count: 13,\n}\n\ntest('stock has 13 apples', () => {\n  expect(stock.type).toBe('apples')\n  expect(stock.count).toBe(13)\n})\n\ntest('stocks are the same', () => {\n  const refStock = stock // same reference\n\n  expect(stock).toBe(refStock)\n})\n```\n\nTry not to use `toBe` with floating-point numbers. Since JavaScript rounds them, `0.1 + 0.2` is not strictly `0.3`. To reliably assert floating-point numbers, use [`toBeCloseTo`](#tobecloseto) assertion.\n\n## toBeCloseTo\n\n- **Type:** `(value: number, numDigits?: number) => Awaitable<void>`\n\nUse `toBeCloseTo` to compare floating-point numbers. The optional `numDigits` argument limits the number of digits to check _after_ the decimal point. The default for `numDigits` is 2. For example:\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest.fails('decimals are not equal in javascript', () => {\n  expect(0.2 + 0.1).toBe(0.3) // 0.2 + 0.1 is 0.30000000000000004\n})\n\ntest('decimals are rounded to 5 after the point', () => {\n  // 0.2 + 0.1 is 0.30000 | \"000000000004\" removed\n  expect(0.2 + 0.1).toBeCloseTo(0.3, 5)\n  // nothing from 0.30000000000000004 is removed\n  expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50)\n})\n```\n\n## toBeDefined\n\n- **Type:** `() => Awaitable<void>`\n\n`toBeDefined` asserts that the value is not equal to `undefined`. Useful use case would be to check if function _returned_ anything.\n\n```ts\nimport { expect, test } from 'vitest'\n\nfunction getApples() {\n  return 3\n}\n\ntest('function returned something', () => {\n  expect(getApples()).toBeDefined()\n})\n```\n\n## toBeUndefined\n\n- **Type:** `() => Awaitable<void>`\n\nOpposite of `toBeDefined`, `toBeUndefined` asserts that the value _is_ equal to `undefined`. Useful use case would be to check if function hasn't _returned_ anything.\n\n```ts\nimport { expect, test } from 'vitest'\n\nfunction getApplesFromStock(stock: string) {\n  if (stock === 'Bill') {\n    return 13\n  }\n}\n\ntest('mary doesn\\'t have a stock', () => {\n  expect(getApplesFromStock('Mary')).toBeUndefined()\n})\n```\n\n## toBeTruthy\n\n- **Type:** `() => Awaitable<void>`\n\n`toBeTruthy` asserts that the value is true when converted to boolean. Useful if you don't care for the value, but just want to know it can be converted to `true`.\n\nFor example, having this code you don't care for the return value of `stocks.getInfo` - it maybe a complex object, a string, or anything else. The code will still work.\n\n```ts\nimport { Stocks } from './stocks.js'\n\nconst stocks = new Stocks()\nstocks.sync('Bill')\nif (stocks.getInfo('Bill')) {\n  stocks.sell('apples', 'Bill')\n}\n```\n\nSo if you want to test that `stocks.getInfo` will be truthy, you could write:\n\n```ts\nimport { expect, test } from 'vitest'\nimport { Stocks } from './stocks.js'\n\nconst stocks = new Stocks()\n\ntest('if we know Bill stock, sell apples to him', () => {\n  stocks.sync('Bill')\n  expect(stocks.getInfo('Bill')).toBeTruthy()\n})\n```\n\nEverything in JavaScript is truthy, except `false`, `null`, `undefined`, `NaN`, `0`, `-0`, `0n`, `\"\"` and `document.all`.\n\n## toBeFalsy\n\n- **Type:** `() => Awaitable<void>`\n\n`toBeFalsy` asserts that the value is false when converted to boolean. Useful if you don't care for the value, but just want to know if it can be converted to `false`.\n\nFor example, having this code you don't care for the return value of `stocks.stockFailed` - it may return any falsy value, but the code will still work.\n\n```ts\nimport { Stocks } from './stocks.js'\n\nconst stocks = new Stocks()\nstocks.sync('Bill')\nif (!stocks.stockFailed('Bill')) {\n  stocks.sell('apples', 'Bill')\n}\n```\n\nSo if you want to test that `stocks.stockFailed` will be falsy, you could write:\n\n```ts\nimport { expect, test } from 'vitest'\nimport { Stocks } from './stocks.js'\n\nconst stocks = new Stocks()\n\ntest('if Bill stock hasn\\'t failed, sell apples to him', () => {\n  stocks.syncStocks('Bill')\n  expect(stocks.stockFailed('Bill')).toBeFalsy()\n})\n```\n\nEverything in JavaScript is truthy, except `false`, `null`, `undefined`, `NaN`, `0`, `-0`, `0n`, `\"\"` and `document.all`.\n\n## toBeNull\n\n- **Type:** `() => Awaitable<void>`\n\n`toBeNull` simply asserts if something is `null`. Alias for `.toBe(null)`.\n\n```ts\nimport { expect, test } from 'vitest'\n\nfunction apples() {\n  return null\n}\n\ntest('we don\\'t have apples', () => {\n  expect(apples()).toBeNull()\n})\n```\n\n## toBeNullable\n\n- **Type:** `() => Awaitable<void>`\n\n`toBeNullable` simply asserts if something is nullable (`null` or `undefined`).\n\n```ts\nimport { expect, test } from 'vitest'\n\nfunction apples() {\n  return null\n}\n\nfunction bananas() {\n  return undefined\n}\n\ntest('we don\\'t have apples', () => {\n  expect(apples()).toBeNullable()\n})\n\ntest('we don\\'t have bananas', () => {\n  expect(bananas()).toBeNullable()\n})\n```\n\n## toBeNaN\n\n- **Type:** `() => Awaitable<void>`\n\n`toBeNaN` simply asserts if something is `NaN`. Alias for `.toBe(NaN)`.\n\n```ts\nimport { expect, test } from 'vitest'\n\nlet i = 0\n\nfunction getApplesCount() {\n  i++\n  return i > 1 ? Number.NaN : i\n}\n\ntest('getApplesCount has some unusual side effects...', () => {\n  expect(getApplesCount()).not.toBeNaN()\n  expect(getApplesCount()).toBeNaN()\n})\n```\n\n## toBeOneOf\n\n- **Type:** `(sample: Array<any> | Set<any>) => any`\n\n`toBeOneOf` asserts if a value matches any of the values in the provided array or set.\n\n::: warning EXPERIMENTAL\nProviding a `Set` is an experimental feature and may change in a future release.\n:::\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('fruit is one of the allowed values', () => {\n  expect(fruit).toBeOneOf(['apple', 'banana', 'orange'])\n})\n```\n\nThe asymmetric matcher is particularly useful when testing optional properties that could be either `null` or `undefined`:\n\n```ts\ntest('optional properties can be null or undefined', () => {\n  const user = {\n    firstName: 'John',\n    middleName: undefined,\n    lastName: 'Doe'\n  }\n\n  expect(user).toEqual({\n    firstName: expect.any(String),\n    middleName: expect.toBeOneOf([expect.any(String), undefined]),\n    lastName: expect.any(String),\n  })\n})\n```\n\n:::tip\nYou can use `expect.not` with this matcher to ensure a value does NOT match any of the provided options.\n:::\n\n## toBeTypeOf\n\n- **Type:** `(c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable<void>`\n\n`toBeTypeOf` asserts if an actual value is of type of received type.\n\n```ts\nimport { expect, test } from 'vitest'\n\nconst actual = 'stock'\n\ntest('stock is type of string', () => {\n  expect(actual).toBeTypeOf('string')\n})\n```\n\n:::warning\n`toBeTypeOf` uses the native `typeof` operator under the hood with all its quirks, most notably that the value `null` has type `object`.\n\n```ts\ntest('toBeTypeOf cannot check for null or array', () => {\n  expect(null).toBeTypeOf('object')\n  expect([]).toBeTypeOf('object')\n})\n```\n:::\n\n## toBeInstanceOf\n\n- **Type:** `(c: any) => Awaitable<void>`\n\n`toBeInstanceOf` asserts if an actual value is instance of received class.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { Stocks } from './stocks.js'\n\nconst stocks = new Stocks()\n\ntest('stocks are instance of Stocks', () => {\n  expect(stocks).toBeInstanceOf(Stocks)\n})\n```\n\n## toBeGreaterThan\n\n- **Type:** `(n: number | bigint) => Awaitable<void>`\n\n`toBeGreaterThan` asserts if actual value is greater than received one. Equal values will fail the test.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { getApples } from './stocks.js'\n\ntest('have more then 10 apples', () => {\n  expect(getApples()).toBeGreaterThan(10)\n})\n```\n\n## toBeGreaterThanOrEqual\n\n- **Type:** `(n: number | bigint) => Awaitable<void>`\n\n`toBeGreaterThanOrEqual` asserts if actual value is greater than received one or equal to it.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { getApples } from './stocks.js'\n\ntest('have 11 apples or more', () => {\n  expect(getApples()).toBeGreaterThanOrEqual(11)\n})\n```\n\n## toBeLessThan\n\n- **Type:** `(n: number | bigint) => Awaitable<void>`\n\n`toBeLessThan` asserts if actual value is less than received one. Equal values will fail the test.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { getApples } from './stocks.js'\n\ntest('have less then 20 apples', () => {\n  expect(getApples()).toBeLessThan(20)\n})\n```\n\n## toBeLessThanOrEqual\n\n- **Type:** `(n: number | bigint) => Awaitable<void>`\n\n`toBeLessThanOrEqual` asserts if actual value is less than received one or equal to it.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { getApples } from './stocks.js'\n\ntest('have 11 apples or less', () => {\n  expect(getApples()).toBeLessThanOrEqual(11)\n})\n```\n\n## toEqual\n\n- **Type:** `(received: any) => Awaitable<void>`\n\n`toEqual` asserts if actual value is equal to received one or has the same structure, if it is an object (compares them recursively). You can see the difference between `toEqual` and [`toBe`](#tobe) in this example:\n\n```ts\nimport { expect, test } from 'vitest'\n\nconst stockBill = {\n  type: 'apples',\n  count: 13,\n}\n\nconst stockMary = {\n  type: 'apples',\n  count: 13,\n}\n\ntest('stocks have the same properties', () => {\n  expect(stockBill).toEqual(stockMary)\n})\n\ntest('stocks are not the same', () => {\n  expect(stockBill).not.toBe(stockMary)\n})\n```\n\n:::warning\nFor `Error` objects, non-enumerable properties such as `name`, `message`, `cause` and `AggregateError.errors` are also compared. For `Error.cause`, the comparison is done asymmetrically:\n\n```ts\n// success\nexpect(new Error('hi', { cause: 'x' })).toEqual(new Error('hi'))\n\n// fail\nexpect(new Error('hi')).toEqual(new Error('hi', { cause: 'x' }))\n```\n\nTo test if something was thrown, use [`toThrow`](#tothrow) assertion.\n:::\n\n## toStrictEqual\n\n- **Type:** `(received: any) => Awaitable<void>`\n\n`toStrictEqual` asserts if the actual value is equal to the received one or has the same structure if it is an object (compares them recursively), and of the same type.\n\nDifferences from [`.toEqual`](#toequal):\n\n-  Keys with `undefined` properties are checked. e.g. `{a: undefined, b: 2}` does not match `{b: 2}` when using `.toStrictEqual`.\n-  Array sparseness is checked. e.g. `[, 1]` does not match `[undefined, 1]` when using `.toStrictEqual`.\n-  Object types are checked to be equal. e.g. A class instance with fields `a` and `b` will not equal a literal object with fields `a` and `b`.\n\n```ts\nimport { expect, test } from 'vitest'\n\nclass Stock {\n  constructor(type) {\n    this.type = type\n  }\n}\n\ntest('structurally the same, but semantically different', () => {\n  expect(new Stock('apples')).toEqual({ type: 'apples' })\n  expect(new Stock('apples')).not.toStrictEqual({ type: 'apples' })\n})\n```\n\n## toContain\n\n- **Type:** `(received: string) => Awaitable<void>`\n\n`toContain` asserts if the actual value is in an array. `toContain` can also check whether a string is a substring of another string. If you are running tests in a browser-like environment, this assertion can also check if class is contained in a `classList`, or an element is inside another one.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { getAllFruits } from './stocks.js'\n\ntest('the fruit list contains orange', () => {\n  expect(getAllFruits()).toContain('orange')\n})\n\ntest('pineapple contains apple', () => {\n  expect('pineapple').toContain('apple')\n})\n\ntest('the element contains a class and is contained', () => {\n  const element = document.querySelector('#el')\n  // element has a class\n  expect(element.classList).toContain('flex')\n  // element is inside another one\n  expect(document.querySelector('#wrapper')).toContain(element)\n})\n```\n\n## toContainEqual\n\n- **Type:** `(received: any) => Awaitable<void>`\n\n`toContainEqual` asserts if an item with a specific structure and values is contained in an array.\nIt works like [`toEqual`](#toequal) inside for each element.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { getFruitStock } from './stocks.js'\n\ntest('apple available', () => {\n  expect(getFruitStock()).toContainEqual({ fruit: 'apple', count: 5 })\n})\n```\n\n## toHaveLength\n\n- **Type:** `(received: number) => Awaitable<void>`\n\n`toHaveLength` asserts if an object has a `.length` property and it is set to a certain numeric value.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('toHaveLength', () => {\n  expect('abc').toHaveLength(3)\n  expect([1, 2, 3]).toHaveLength(3)\n\n  expect('').not.toHaveLength(3) // doesn't have .length of 3\n  expect({ length: 3 }).toHaveLength(3)\n})\n```\n\n## toHaveProperty\n\n- **Type:** `(key: any, received?: any) => Awaitable<void>`\n\n`toHaveProperty` asserts if a property at provided reference `key` exists for an object.\n\nYou can provide an optional value argument also known as deep equality, like the `toEqual` matcher to compare the received property value.\n\n```ts\nimport { expect, test } from 'vitest'\n\nconst invoice = {\n  'isActive': true,\n  'P.O': '12345',\n  'customer': {\n    first_name: 'John',\n    last_name: 'Doe',\n    location: 'China',\n  },\n  'total_amount': 5000,\n  'items': [\n    {\n      type: 'apples',\n      quantity: 10,\n    },\n    {\n      type: 'oranges',\n      quantity: 5,\n    },\n  ],\n}\n\ntest('John Doe Invoice', () => {\n  expect(invoice).toHaveProperty('isActive') // assert that the key exists\n  expect(invoice).toHaveProperty('total_amount', 5000) // assert that the key exists and the value is equal\n\n  expect(invoice).not.toHaveProperty('account') // assert that this key does not exist\n\n  // Deep referencing using dot notation\n  expect(invoice).toHaveProperty('customer.first_name')\n  expect(invoice).toHaveProperty('customer.last_name', 'Doe')\n  expect(invoice).not.toHaveProperty('customer.location', 'India')\n\n  // Deep referencing using an array containing the key\n  expect(invoice).toHaveProperty('items[0].type', 'apples')\n  expect(invoice).toHaveProperty('items.0.type', 'apples') // dot notation also works\n\n  // Deep referencing using an array containing the keyPath\n  expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples')\n  expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples') // string notation also works\n\n  // Wrap your key in an array to avoid the key from being parsed as a deep reference\n  expect(invoice).toHaveProperty(['P.O'], '12345')\n\n  // Deep equality of object property\n  expect(invoice).toHaveProperty('items[0]', { type: 'apples', quantity: 10 })\n})\n```\n\n## toMatch\n\n- **Type:** `(received: string | regexp) => Awaitable<void>`\n\n`toMatch` asserts if a string matches a regular expression or a string.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('top fruits', () => {\n  expect('top fruits include apple, orange and grape').toMatch(/apple/)\n  expect('applefruits').toMatch('fruit') // toMatch also accepts a string\n})\n```\n\n## toMatchObject\n\n- **Type:** `(received: object | array) => Awaitable<void>`\n\n`toMatchObject` asserts if an object matches a subset of the properties of an object.\n\nYou can also pass an array of objects. This is useful if you want to check that two arrays match in their number and order of elements, as opposed to `arrayContaining`, which allows for extra elements in the received array.\n\n```ts\nimport { expect, test } from 'vitest'\n\nconst johnInvoice = {\n  isActive: true,\n  customer: {\n    first_name: 'John',\n    last_name: 'Doe',\n    location: 'China',\n  },\n  total_amount: 5000,\n  items: [\n    {\n      type: 'apples',\n      quantity: 10,\n    },\n    {\n      type: 'oranges',\n      quantity: 5,\n    },\n  ],\n}\n\nconst johnDetails = {\n  customer: {\n    first_name: 'John',\n    last_name: 'Doe',\n    location: 'China',\n  },\n}\n\ntest('invoice has john personal details', () => {\n  expect(johnInvoice).toMatchObject(johnDetails)\n})\n\ntest('the number of elements must match exactly', () => {\n  // Assert that an array of object matches\n  expect([{ foo: 'bar' }, { baz: 1 }]).toMatchObject([\n    { foo: 'bar' },\n    { baz: 1 },\n  ])\n})\n```\n\n## toThrow\n\n- **Type:** `(expected?: any) => Awaitable<void>`\n\n- **Alias:** `toThrowError` <Deprecated />\n\n`toThrow` asserts if a function throws an error when it is called.\n\nYou can provide an optional argument to test that a specific error is thrown:\n\n- `RegExp`: error message matches the pattern\n- `string`: error message includes the substring\n- any other value: compare with thrown value using deep equality (similar to `toEqual`)\n\n:::tip\nYou must wrap the code in a function, otherwise the error will not be caught, and test will fail.\n\nThis does not apply for async calls as [rejects](#rejects) correctly unwraps the promise:\n```ts\ntest('expect rejects toThrow', async ({ expect }) => {\n  const promise = Promise.reject(new Error('Test'))\n  await expect(promise).rejects.toThrow()\n})\n```\n:::\n\nFor example, if we want to test that `getFruitStock('pineapples')` throws, we could write:\n\n```ts\nimport { expect, test } from 'vitest'\n\nfunction getFruitStock(type: string) {\n  if (type === 'pineapples') {\n    throw new Error('Pineapples are not in stock')\n  }\n\n  // Do some other stuff\n}\n\ntest('throws on pineapples', () => {\n  // Test that the error message says \"stock\" somewhere: these are equivalent\n  expect(() => getFruitStock('pineapples')).toThrow(/stock/)\n  expect(() => getFruitStock('pineapples')).toThrow('stock')\n\n  // Test the exact error message\n  expect(() => getFruitStock('pineapples')).toThrow(\n    /^Pineapples are not in stock$/,\n  )\n\n  expect(() => getFruitStock('pineapples')).toThrow(\n    new Error('Pineapples are not in stock'),\n  )\n  expect(() => getFruitStock('pineapples')).toThrow(expect.objectContaining({\n    message: 'Pineapples are not in stock',\n  }))\n})\n```\n\n:::tip\nTo test async functions, use in combination with [rejects](#rejects).\n\n```js\nfunction getAsyncFruitStock() {\n  return Promise.reject(new Error('empty'))\n}\n\ntest('throws on pineapples', async () => {\n  await expect(() => getAsyncFruitStock()).rejects.toThrow('empty')\n})\n```\n:::\n\n:::tip\nYou can also test non-Error values that are thrown:\n\n```ts\ntest('throws non-Error values', () => {\n  expect(() => { throw 42 }).toThrow(42)\n  expect(() => { throw { message: 'error' } }).toThrow({ message: 'error' })\n})\n```\n:::\n\n## toMatchSnapshot\n\n- **Type:** `<T>(shape?: Partial<T> | string, hint?: string) => void`\n\nThis ensures that a value matches the most recent snapshot.\n\nYou can provide an optional `hint` string argument that is appended to the test name. Although Vitest always appends a number at the end of a snapshot name, short descriptive hints might be more useful than numbers to differentiate multiple snapshots in a single it or test block. Vitest sorts snapshots by name in the corresponding `.snap` file.\n\n:::tip\n  When a snapshot mismatches and causes the test to fail, if the mismatch is expected, you can press `u` key to update the snapshot once. Or you can pass `-u` or `--update` CLI options to make Vitest always update the tests.\n:::\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('matches snapshot', () => {\n  const data = { foo: new Set(['bar', 'snapshot']) }\n  expect(data).toMatchSnapshot()\n})\n```\n\nYou can also provide a shape of an object, if you are testing just a shape of an object, and don't need it to be 100% compatible:\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('matches snapshot', () => {\n  const data = { foo: new Set(['bar', 'snapshot']) }\n  expect(data).toMatchSnapshot({ foo: expect.any(Set) })\n})\n```\n\n## toMatchInlineSnapshot\n\n- **Type:** `<T>(shape?: Partial<T> | string, snapshot?: string, hint?: string) => void`\n\nThis ensures that a value matches the most recent snapshot.\n\nVitest adds and updates the inlineSnapshot string argument to the matcher in the test file (instead of an external `.snap` file).\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('matches inline snapshot', () => {\n  const data = { foo: new Set(['bar', 'snapshot']) }\n  // Vitest will update following content when updating the snapshot\n  expect(data).toMatchInlineSnapshot(`\n    {\n      \"foo\": Set {\n        \"bar\",\n        \"snapshot\",\n      },\n    }\n  `)\n})\n```\n\nYou can also provide a shape of an object, if you are testing just a shape of an object, and don't need it to be 100% compatible:\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('matches snapshot', () => {\n  const data = { foo: new Set(['bar', 'snapshot']) }\n  expect(data).toMatchInlineSnapshot(\n    { foo: expect.any(Set) },\n    `\n    {\n      \"foo\": Any<Set>,\n    }\n  `\n  )\n})\n```\n\n## toMatchFileSnapshot {#tomatchfilesnapshot}\n\n- **Type:** `<T>(filepath: string, hint?: string) => Promise<void>`\n\nCompare or update the snapshot with the content of a file explicitly specified (instead of the `.snap` file).\n\n```ts\nimport { expect, it } from 'vitest'\n\nit('render basic', async () => {\n  const result = renderHTML(h('div', { class: 'foo' }))\n  await expect(result).toMatchFileSnapshot('./test/basic.output.html')\n})\n```\n\nNote that since file system operation is async, you need to use `await` with `toMatchFileSnapshot()`. If `await` is not used, Vitest treats it like `expect.soft`, meaning the code after the statement will continue to run even if the snapshot mismatches. After the test finishes, Vitest will check the snapshot and fail if there is a mismatch.\n\n## toThrowErrorMatchingSnapshot\n\n- **Type:** `(hint?: string) => void`\n\nThe same as [`toMatchSnapshot`](#tomatchsnapshot), but expects the same value as [`toThrow`](#tothrow).\n\n## toThrowErrorMatchingInlineSnapshot\n\n- **Type:** `(snapshot?: string, hint?: string) => void`\n\nThe same as [`toMatchInlineSnapshot`](#tomatchinlinesnapshot), but expects the same value as [`toThrow`](#tothrow).\n\n## toHaveBeenCalled\n\n- **Type:** `() => Awaitable<void>`\n\nThis assertion is useful for testing that a function has been called. Requires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\nconst market = {\n  buy(subject: string, amount: number) {\n    // ...\n  },\n}\n\ntest('spy function', () => {\n  const buySpy = vi.spyOn(market, 'buy')\n\n  expect(buySpy).not.toHaveBeenCalled()\n\n  market.buy('apples', 10)\n\n  expect(buySpy).toHaveBeenCalled()\n})\n```\n\n## toHaveBeenCalledTimes\n\n- **Type**: `(amount: number) => Awaitable<void>`\n\nThis assertion checks if a function was called a certain amount of times. Requires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\nconst market = {\n  buy(subject: string, amount: number) {\n    // ...\n  },\n}\n\ntest('spy function called two times', () => {\n  const buySpy = vi.spyOn(market, 'buy')\n\n  market.buy('apples', 10)\n  market.buy('apples', 20)\n\n  expect(buySpy).toHaveBeenCalledTimes(2)\n})\n```\n\n## toHaveBeenCalledWith\n\n- **Type**: `(...args: any[]) => Awaitable<void>`\n\nThis assertion checks if a function was called at least once with certain parameters. Requires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\nconst market = {\n  buy(subject: string, amount: number) {\n    // ...\n  },\n}\n\ntest('spy function', () => {\n  const buySpy = vi.spyOn(market, 'buy')\n\n  market.buy('apples', 10)\n  market.buy('apples', 20)\n\n  expect(buySpy).toHaveBeenCalledWith('apples', 10)\n  expect(buySpy).toHaveBeenCalledWith('apples', 20)\n})\n```\n\n## toHaveBeenCalledBefore\n\n- **Type**: `(mock: MockInstance, failIfNoFirstInvocation?: boolean) => Awaitable<void>`\n\nThis assertion checks if a `Mock` was called before another `Mock`.\n\n```ts\ntest('calls mock1 before mock2', () => {\n  const mock1 = vi.fn()\n  const mock2 = vi.fn()\n\n  mock1()\n  mock2()\n  mock1()\n\n  expect(mock1).toHaveBeenCalledBefore(mock2)\n})\n```\n\n## toHaveBeenCalledAfter\n\n- **Type**: `(mock: MockInstance, failIfNoFirstInvocation?: boolean) => Awaitable<void>`\n\nThis assertion checks if a `Mock` was called after another `Mock`.\n\n```ts\ntest('calls mock1 after mock2', () => {\n  const mock1 = vi.fn()\n  const mock2 = vi.fn()\n\n  mock2()\n  mock1()\n  mock2()\n\n  expect(mock1).toHaveBeenCalledAfter(mock2)\n})\n```\n\n## toHaveBeenCalledExactlyOnceWit\n\n- **Type**: `(...args: any[]) => Awaitable<void>`\n\nThis assertion checks if a function was called exactly once and with certain parameters. Requires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\nconst market = {\n  buy(subject: string, amount: number) {\n    // ...\n  },\n}\n\ntest('spy function', () => {\n  const buySpy = vi.spyOn(market, 'buy')\n\n  market.buy('apples', 10)\n\n  expect(buySpy).toHaveBeenCalledExactlyOnceWith('apples', 10)\n})\n```\n\n## toHaveBeenLastCalledWith\n\n- **Type**: `(...args: any[]) => Awaitable<void>`\n\nThis assertion checks if a function was called with certain parameters at its last invocation. Requires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\nconst market = {\n  buy(subject: string, amount: number) {\n    // ...\n  },\n}\n\ntest('spy function', () => {\n  const buySpy = vi.spyOn(market, 'buy')\n\n  market.buy('apples', 10)\n  market.buy('apples', 20)\n\n  expect(buySpy).not.toHaveBeenLastCalledWith('apples', 10)\n  expect(buySpy).toHaveBeenLastCalledWith('apples', 20)\n})\n```\n\n## toHaveBeenNthCalledWith\n\n- **Type**: `(time: number, ...args: any[]) => Awaitable<void>`\n\nThis assertion checks if a function was called with certain parameters at the certain time. The count starts at 1. So, to check the second entry, you would write `.toHaveBeenNthCalledWith(2, ...)`.\n\nRequires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\nconst market = {\n  buy(subject: string, amount: number) {\n    // ...\n  },\n}\n\ntest('first call of spy function called with right params', () => {\n  const buySpy = vi.spyOn(market, 'buy')\n\n  market.buy('apples', 10)\n  market.buy('apples', 20)\n\n  expect(buySpy).toHaveBeenNthCalledWith(1, 'apples', 10)\n})\n```\n\n## toHaveReturned\n\n- **Type**: `() => Awaitable<void>`\n\nThis assertion checks if a function has successfully returned a value at least once (i.e., did not throw an error). Requires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\nfunction getApplesPrice(amount: number) {\n  const PRICE = 10\n  return amount * PRICE\n}\n\ntest('spy function returned a value', () => {\n  const getPriceSpy = vi.fn(getApplesPrice)\n\n  const price = getPriceSpy(10)\n\n  expect(price).toBe(100)\n  expect(getPriceSpy).toHaveReturned()\n})\n```\n\n## toHaveReturnedTimes\n\n- **Type**: `(amount: number) => Awaitable<void>`\n\nThis assertion checks if a function has successfully returned a value an exact amount of times (i.e., did not throw an error). Requires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy function returns a value two times', () => {\n  const sell = vi.fn((product: string) => ({ product }))\n\n  sell('apples')\n  sell('bananas')\n\n  expect(sell).toHaveReturnedTimes(2)\n})\n```\n\n## toHaveReturnedWith\n\n- **Type**: `(returnValue: any) => Awaitable<void>`\n\nYou can call this assertion to check if a function has successfully returned a value with certain parameters at least once. Requires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy function returns a product', () => {\n  const sell = vi.fn((product: string) => ({ product }))\n\n  sell('apples')\n\n  expect(sell).toHaveReturnedWith({ product: 'apples' })\n})\n```\n\n## toHaveLastReturnedWith\n\n- **Type**: `(returnValue: any) => Awaitable<void>`\n\nYou can call this assertion to check if a function has successfully returned a certain value when it was last invoked. Requires a spy function to be passed to `expect`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy function returns bananas on a last call', () => {\n  const sell = vi.fn((product: string) => ({ product }))\n\n  sell('apples')\n  sell('bananas')\n\n  expect(sell).toHaveLastReturnedWith({ product: 'bananas' })\n})\n```\n\n## toHaveNthReturnedWith\n\n- **Type**: `(time: number, returnValue: any) => Awaitable<void>`\n\nYou can call this assertion to check if a function has successfully returned a value with certain parameters on a certain call. Requires a spy function to be passed to `expect`.\n\nThe count starts at 1. So, to check the second entry, you would write `.toHaveNthReturnedWith(2, ...)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy function returns bananas on second call', () => {\n  const sell = vi.fn((product: string) => ({ product }))\n\n  sell('apples')\n  sell('bananas')\n\n  expect(sell).toHaveNthReturnedWith(2, { product: 'bananas' })\n})\n```\n\n## toHaveResolved\n\n- **Type**: `() => Awaitable<void>`\n\nThis assertion checks if a function has successfully resolved a value at least once (i.e., did not reject). Requires a spy function to be passed to `expect`.\n\nIf the function returned a promise, but it was not resolved yet, this will fail.\n\n```ts\nimport { expect, test, vi } from 'vitest'\nimport db from './db/apples.js'\n\nasync function getApplesPrice(amount: number) {\n  return amount * await db.get('price')\n}\n\ntest('spy function resolved a value', async () => {\n  const getPriceSpy = vi.fn(getApplesPrice)\n\n  const price = await getPriceSpy(10)\n\n  expect(price).toBe(100)\n  expect(getPriceSpy).toHaveResolved()\n})\n```\n\n## toHaveResolvedTimes\n\n- **Type**: `(amount: number) => Awaitable<void>`\n\nThis assertion checks if a function has successfully resolved a value an exact amount of times (i.e., did not reject). Requires a spy function to be passed to `expect`.\n\nThis will only count resolved promises. If the function returned a promise, but it was not resolved yet, it will not be counted.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy function resolved a value two times', async () => {\n  const sell = vi.fn((product: string) => Promise.resolve({ product }))\n\n  await sell('apples')\n  await sell('bananas')\n\n  expect(sell).toHaveResolvedTimes(2)\n})\n```\n\n## toHaveResolvedWith\n\n- **Type**: `(returnValue: any) => Awaitable<void>`\n\nYou can call this assertion to check if a function has successfully resolved a certain value at least once. Requires a spy function to be passed to `expect`.\n\nIf the function returned a promise, but it was not resolved yet, this will fail.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy function resolved a product', async () => {\n  const sell = vi.fn((product: string) => Promise.resolve({ product }))\n\n  await sell('apples')\n\n  expect(sell).toHaveResolvedWith({ product: 'apples' })\n})\n```\n\n## toHaveLastResolvedWith\n\n- **Type**: `(returnValue: any) => Awaitable<void>`\n\nYou can call this assertion to check if a function has successfully resolved a certain value when it was last invoked. Requires a spy function to be passed to `expect`.\n\nIf the function returned a promise, but it was not resolved yet, this will fail.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy function resolves bananas on a last call', async () => {\n  const sell = vi.fn((product: string) => Promise.resolve({ product }))\n\n  await sell('apples')\n  await sell('bananas')\n\n  expect(sell).toHaveLastResolvedWith({ product: 'bananas' })\n})\n```\n\n## toHaveNthResolvedWith\n\n- **Type**: `(time: number, returnValue: any) => Awaitable<void>`\n\nYou can call this assertion to check if a function has successfully resolved a certain value on a specific invocation. Requires a spy function to be passed to `expect`.\n\nIf the function returned a promise, but it was not resolved yet, this will fail.\n\nThe count starts at 1. So, to check the second entry, you would write `.toHaveNthResolvedWith(2, ...)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy function returns bananas on second call', async () => {\n  const sell = vi.fn((product: string) => Promise.resolve({ product }))\n\n  await sell('apples')\n  await sell('bananas')\n\n  expect(sell).toHaveNthResolvedWith(2, { product: 'bananas' })\n})\n```\n\n## called <Version>4.1.0</Version> {#called}\n\n- **Type:** `Assertion` (property, not a method)\n\nChai-style assertion that checks if a spy was called at least once. This is equivalent to `toHaveBeenCalled()`.\n\n::: tip\nThis is a property assertion following sinon-chai conventions. Access it without parentheses: `expect(spy).to.have.been.called`\n:::\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy was called', () => {\n  const spy = vi.fn()\n\n  spy()\n\n  expect(spy).to.have.been.called\n  expect(spy).to.not.have.been.called // negation\n})\n```\n\n## callCount <Version>4.1.0</Version> {#callcount}\n\n- **Type:** `(count: number) => void`\n\nChai-style assertion that checks if a spy was called a specific number of times. This is equivalent to `toHaveBeenCalledTimes(count)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy call count', () => {\n  const spy = vi.fn()\n\n  spy()\n  spy()\n  spy()\n\n  expect(spy).to.have.callCount(3)\n})\n```\n\n## calledWith <Version>4.1.0</Version> {#calledwith}\n\n- **Type:** `(...args: any[]) => void`\n\nChai-style assertion that checks if a spy was called with specific arguments at least once. This is equivalent to `toHaveBeenCalledWith(...args)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy called with arguments', () => {\n  const spy = vi.fn()\n\n  spy('apple', 10)\n  spy('banana', 20)\n\n  expect(spy).to.have.been.calledWith('apple', 10)\n  expect(spy).to.have.been.calledWith('banana', 20)\n})\n```\n\n## calledOnce <Version>4.1.0</Version> {#calledonce}\n\n- **Type:** `Assertion` (property, not a method)\n\nChai-style assertion that checks if a spy was called exactly once. This is equivalent to `toHaveBeenCalledOnce()`.\n\n::: tip\nThis is a property assertion following sinon-chai conventions. Access it without parentheses: `expect(spy).to.have.been.calledOnce`\n:::\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy called once', () => {\n  const spy = vi.fn()\n\n  spy()\n\n  expect(spy).to.have.been.calledOnce\n})\n```\n\n## calledOnceWith <Version>4.1.0</Version> {#calledoncewith}\n\n- **Type:** `(...args: any[]) => void`\n\nChai-style assertion that checks if a spy was called exactly once with specific arguments. This is equivalent to `toHaveBeenCalledExactlyOnceWith(...args)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy called once with arguments', () => {\n  const spy = vi.fn()\n\n  spy('apple', 10)\n\n  expect(spy).to.have.been.calledOnceWith('apple', 10)\n})\n```\n\n## calledTwice <Version>4.1.0</Version> {#calledtwice}\n\n- **Type:** `Assertion` (property, not a method)\n\nChai-style assertion that checks if a spy was called exactly twice. This is equivalent to `toHaveBeenCalledTimes(2)`.\n\n::: tip\nThis is a property assertion following sinon-chai conventions. Access it without parentheses: `expect(spy).to.have.been.calledTwice`\n:::\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy called twice', () => {\n  const spy = vi.fn()\n\n  spy()\n  spy()\n\n  expect(spy).to.have.been.calledTwice\n})\n```\n\n## calledThrice <Version>4.1.0</Version> {#calledthrice}\n\n- **Type:** `Assertion` (property, not a method)\n\nChai-style assertion that checks if a spy was called exactly three times. This is equivalent to `toHaveBeenCalledTimes(3)`.\n\n::: tip\nThis is a property assertion following sinon-chai conventions. Access it without parentheses: `expect(spy).to.have.been.calledThrice`\n:::\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy called thrice', () => {\n  const spy = vi.fn()\n\n  spy()\n  spy()\n  spy()\n\n  expect(spy).to.have.been.calledThrice\n})\n```\n\n## lastCalledWith\n\n- **Type:** `(...args: any[]) => void`\n\nChai-style assertion that checks if the last call to a spy was made with specific arguments. This is equivalent to `toHaveBeenLastCalledWith(...args)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy last called with', () => {\n  const spy = vi.fn()\n\n  spy('apple', 10)\n  spy('banana', 20)\n\n  expect(spy).to.have.been.lastCalledWith('banana', 20)\n})\n```\n\n## nthCalledWith\n\n- **Type:** `(n: number, ...args: any[]) => void`\n\nChai-style assertion that checks if the nth call to a spy was made with specific arguments. This is equivalent to `toHaveBeenNthCalledWith(n, ...args)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy nth called with', () => {\n  const spy = vi.fn()\n\n  spy('apple', 10)\n  spy('banana', 20)\n  spy('cherry', 30)\n\n  expect(spy).to.have.been.nthCalledWith(2, 'banana', 20)\n})\n```\n\n## returned <Version>4.1.0</Version> {#returned}\n\n- **Type:** `Assertion` (property, not a method)\n\nChai-style assertion that checks if a spy returned successfully at least once. This is equivalent to `toHaveReturned()`.\n\n::: tip\nThis is a property assertion following sinon-chai conventions. Access it without parentheses: `expect(spy).to.have.returned`\n:::\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy returned', () => {\n  const spy = vi.fn(() => 'result')\n\n  spy()\n\n  expect(spy).to.have.returned\n})\n```\n\n## returnedWith <Version>4.1.0</Version> {#returnedwith}\n\n- **Type:** `(value: any) => void`\n\nChai-style assertion that checks if a spy returned a specific value at least once. This is equivalent to `toHaveReturnedWith(value)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy returned with value', () => {\n  const spy = vi.fn()\n    .mockReturnValueOnce('apple')\n    .mockReturnValueOnce('banana')\n\n  spy()\n  spy()\n\n  expect(spy).to.have.returnedWith('apple')\n  expect(spy).to.have.returnedWith('banana')\n})\n```\n\n## returnedTimes <Version>4.1.0</Version> {#returnedtimes}\n\n- **Type:** `(count: number) => void`\n\nChai-style assertion that checks if a spy returned successfully a specific number of times. This is equivalent to `toHaveReturnedTimes(count)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy returned times', () => {\n  const spy = vi.fn(() => 'result')\n\n  spy()\n  spy()\n  spy()\n\n  expect(spy).to.have.returnedTimes(3)\n})\n```\n\n## lastReturnedWith\n\n- **Type:** `(value: any) => void`\n\nChai-style assertion that checks if the last return value of a spy matches the expected value. This is equivalent to `toHaveLastReturnedWith(value)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy last returned with', () => {\n  const spy = vi.fn()\n    .mockReturnValueOnce('apple')\n    .mockReturnValueOnce('banana')\n\n  spy()\n  spy()\n\n  expect(spy).to.have.lastReturnedWith('banana')\n})\n```\n\n## nthReturnedWith\n\n- **Type:** `(n: number, value: any) => void`\n\nChai-style assertion that checks if the nth return value of a spy matches the expected value. This is equivalent to `toHaveNthReturnedWith(n, value)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy nth returned with', () => {\n  const spy = vi.fn()\n    .mockReturnValueOnce('apple')\n    .mockReturnValueOnce('banana')\n    .mockReturnValueOnce('cherry')\n\n  spy()\n  spy()\n  spy()\n\n  expect(spy).to.have.nthReturnedWith(2, 'banana')\n})\n```\n\n## calledBefore <Version>4.1.0</Version> {#calledbefore}\n\n- **Type:** `(mock: MockInstance, failIfNoFirstInvocation?: boolean) => void`\n\nChai-style assertion that checks if a spy was called before another spy. This is equivalent to `toHaveBeenCalledBefore(mock, failIfNoFirstInvocation)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy called before another', () => {\n  const spy1 = vi.fn()\n  const spy2 = vi.fn()\n\n  spy1()\n  spy2()\n\n  expect(spy1).to.have.been.calledBefore(spy2)\n})\n```\n\n## calledAfter <Version>4.1.0</Version> {#calledafter}\n\n- **Type:** `(mock: MockInstance, failIfNoFirstInvocation?: boolean) => void`\n\nChai-style assertion that checks if a spy was called after another spy. This is equivalent to `toHaveBeenCalledAfter(mock, failIfNoFirstInvocation)`.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('spy called after another', () => {\n  const spy1 = vi.fn()\n  const spy2 = vi.fn()\n\n  spy1()\n  spy2()\n\n  expect(spy2).to.have.been.calledAfter(spy1)\n})\n```\n\n::: tip Migration Guide\nFor a complete guide on migrating from Mocha+Chai+Sinon to Vitest, see the [Migration Guide](/guide/migration#mocha-chai-sinon).\n:::\n\n## toSatisfy\n\n- **Type:** `(predicate: (value: any) => boolean) => Awaitable<void>`\n\nThis assertion checks if a value satisfies a certain predicate.\n\n```ts\nimport { describe, expect, it } from 'vitest'\n\nconst isOdd = (value: number) => value % 2 !== 0\n\ndescribe('toSatisfy()', () => {\n  it('pass with 0', () => {\n    expect(1).toSatisfy(isOdd)\n  })\n\n  it('pass with negation', () => {\n    expect(2).not.toSatisfy(isOdd)\n  })\n})\n```\n\n## resolves\n\n- **Type:** `Promisify<Assertions>`\n\n`resolves` is intended to remove boilerplate when asserting asynchronous code. Use it to unwrap value from the pending promise and assert its value with usual assertions. If the promise rejects, the assertion will fail.\n\nIt returns the same `Assertions` object, but all matchers now return `Promise`, so you would need to `await` it. Also works with `chai` assertions.\n\nFor example, if you have a function, that makes an API call and returns some data, you may use this code to assert its return value:\n\n```ts\nimport { expect, test } from 'vitest'\n\nasync function buyApples() {\n  return fetch('/buy/apples').then(r => r.json())\n}\n\ntest('buyApples returns new stock id', async () => {\n  // toEqual returns a promise now, so you HAVE to await it\n  await expect(buyApples()).resolves.toEqual({ id: 1 }) // jest API\n  await expect(buyApples()).resolves.to.equal({ id: 1 }) // chai API\n})\n```\n\n:::warning\nIf the assertion is not awaited, then you will have a false-positive test that will pass every time. To make sure that assertions are actually called, you may use [`expect.assertions(number)`](#expect-assertions).\n\nSince Vitest 3, if a method is not awaited, Vitest will show a warning at the end of the test. In Vitest 4, the test will be marked as \"failed\" if the assertion is not awaited.\n:::\n\n## rejects\n\n- **Type:** `Promisify<Assertions>`\n\n`rejects` is intended to remove boilerplate when asserting asynchronous code. Use it to unwrap reason why the promise was rejected, and assert its value with usual assertions. If the promise successfully resolves, the assertion will fail.\n\nIt returns the same `Assertions` object, but all matchers now return `Promise`, so you would need to `await` it. Also works with `chai` assertions.\n\nFor example, if you have a function that fails when you call it, you may use this code to assert the reason:\n\n```ts\nimport { expect, test } from 'vitest'\n\nasync function buyApples(id) {\n  if (!id) {\n    throw new Error('no id')\n  }\n}\n\ntest('buyApples throws an error when no id provided', async () => {\n  // toThrow returns a promise now, so you HAVE to await it\n  await expect(buyApples()).rejects.toThrow('no id')\n})\n```\n\n:::warning\nIf the assertion is not awaited, then you will have a false-positive test that will pass every time. To make sure that assertions were actually called, you can use [`expect.assertions(number)`](#expect-assertions).\n\nSince Vitest 3, if a method is not awaited, Vitest will show a warning at the end of the test. In Vitest 4, the test will be marked as \"failed\" if the assertion is not awaited.\n:::\n\n## expect.assertions\n\n- **Type:** `(count: number) => void`\n\nAfter the test has passed or failed verify that a certain number of assertions was called during a test. A useful case would be to check if an asynchronous code was called.\n\nFor example, if we have a function that asynchronously calls two matchers, we can assert that they were actually called.\n\n```ts\nimport { expect, test } from 'vitest'\n\nasync function doAsync(...cbs) {\n  await Promise.all(\n    cbs.map((cb, index) => cb({ index })),\n  )\n}\n\ntest('all assertions are called', async () => {\n  expect.assertions(2)\n  function callback1(data) {\n    expect(data).toBeTruthy()\n  }\n  function callback2(data) {\n    expect(data).toBeTruthy()\n  }\n\n  await doAsync(callback1, callback2)\n})\n```\n::: warning\nWhen using `assertions` with async concurrent tests, `expect` from the local [Test Context](/guide/test-context) must be used to ensure the right test is detected.\n:::\n\n## expect.hasAssertions\n\n- **Type:** `() => void`\n\nAfter the test has passed or failed verify that at least one assertion was called during a test. A useful case would be to check if an asynchronous code was called.\n\nFor example, if you have a code that calls a callback, we can make an assertion inside a callback, but the test will always pass if we don't check if an assertion was called.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { db } from './db.js'\n\nconst cbs = []\n\nfunction onSelect(cb) {\n  cbs.push(cb)\n}\n\n// after selecting from db, we call all callbacks\nfunction select(id) {\n  return db.select({ id }).then((data) => {\n    return Promise.all(\n      cbs.map(cb => cb(data)),\n    )\n  })\n}\n\ntest('callback was called', async () => {\n  expect.hasAssertions()\n  onSelect((data) => {\n    // should be called on select\n    expect(data).toBeTruthy()\n  })\n  // if not awaited, test will fail\n  // if you don't have expect.hasAssertions(), test will pass\n  await select(3)\n})\n```\n\n## expect.unreachable\n\n- **Type:** `(message?: string) => never`\n\nThis method is used to assert that a line should never be reached.\n\nFor example, if we want to test that `build()` throws due to receiving directories having no `src` folder, and also handle each error separately, we could do this:\n\n```ts\nimport { expect, test } from 'vitest'\n\nasync function build(dir) {\n  if (dir.includes('no-src')) {\n    throw new Error(`${dir}/src does not exist`)\n  }\n}\n\nconst errorDirs = [\n  'no-src-folder',\n  // ...\n]\n\ntest.each(errorDirs)('build fails with \"%s\"', async (dir) => {\n  try {\n    await build(dir)\n    expect.unreachable('Should not pass build')\n  }\n  catch (err: any) {\n    expect(err).toBeInstanceOf(Error)\n    expect(err.stack).toContain('build')\n\n    switch (dir) {\n      case 'no-src-folder':\n        expect(err.message).toBe(`${dir}/src does not exist`)\n        break\n      default:\n        // to exhaust all error tests\n        expect.unreachable('All error test must be handled')\n        break\n    }\n  }\n})\n```\n\n## expect.anything\n\n- **Type:** `() => any`\n\nThis asymmetric matcher matches anything except `null` or `undefined`. Useful if you just want to be sure that a property exists with any value that's not either `null` or `undefined`.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('object has \"apples\" key', () => {\n  expect({ apples: 22 }).toEqual({ apples: expect.anything() })\n})\n```\n\n## expect.any\n\n- **Type:** `(constructor: unknown) => any`\n\nThis asymmetric matcher, when used with an equality check, will return `true` only if the value is an instance of a specified constructor. Useful, if you have a value that is generated each time, and you only want to know that it exists with a proper type.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { generateId } from './generators.js'\n\ntest('\"id\" is a number', () => {\n  expect({ id: generateId() }).toEqual({ id: expect.any(Number) })\n})\n```\n\n## expect.closeTo {#expect-closeto}\n\n- **Type:** `(expected: any, precision?: number) => any`\n\n`expect.closeTo` is useful when comparing floating point numbers in object properties or array item. If you need to compare a number, please use `.toBeCloseTo` instead.\n\nThe optional `precision` argument limits the number of digits to check **after** the decimal point. For the default value `2`, the test criterion is `Math.abs(expected - received) < 0.005 (that is, 10 ** -2 / 2)`.\n\nFor example, this test passes with a precision of 5 digits:\n\n```js\ntest('compare float in object properties', () => {\n  expect({\n    title: '0.1 + 0.2',\n    sum: 0.1 + 0.2,\n  }).toEqual({\n    title: '0.1 + 0.2',\n    sum: expect.closeTo(0.3, 5),\n  })\n})\n```\n\n## expect.arrayContaining\n\n- **Type:** `<T>(expected: T[]) => any`\n\nWhen used with an equality check, this asymmetric matcher will return `true` if the value is an array and contains specified items.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('basket includes fuji', () => {\n  const basket = {\n    varieties: [\n      'Empire',\n      'Fuji',\n      'Gala',\n    ],\n    count: 3\n  }\n  expect(basket).toEqual({\n    count: 3,\n    varieties: expect.arrayContaining(['Fuji'])\n  })\n})\n```\n\n:::tip\nYou can use `expect.not` with this matcher to negate the expected value.\n:::\n\n## expect.objectContaining\n\n- **Type:** `(expected: any) => any`\n\nWhen used with an equality check, this asymmetric matcher will return `true` if the value has a similar shape.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('basket has empire apples', () => {\n  const basket = {\n    varieties: [\n      {\n        name: 'Empire',\n        count: 1,\n      }\n    ],\n  }\n  expect(basket).toEqual({\n    varieties: [\n      expect.objectContaining({ name: 'Empire' }),\n    ]\n  })\n})\n```\n\n:::tip\nYou can use `expect.not` with this matcher to negate the expected value.\n:::\n\n## expect.stringContaining\n\n- **Type:** `(expected: any) => any`\n\nWhen used with an equality check, this asymmetric matcher will return `true` if the value is a string and contains a specified substring.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('variety has \"Emp\" in its name', () => {\n  const variety = {\n    name: 'Empire',\n    count: 1,\n  }\n  expect(variety).toEqual({\n    name: expect.stringContaining('Emp'),\n    count: 1,\n  })\n})\n```\n\n:::tip\nYou can use `expect.not` with this matcher to negate the expected value.\n:::\n\n## expect.stringMatching\n\n- **Type:** `(expected: any) => any`\n\nWhen used with an equality check, this asymmetric matcher will return `true` if the value is a string and contains a specified substring or if the string matches a regular expression.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('variety ends with \"re\"', () => {\n  const variety = {\n    name: 'Empire',\n    count: 1,\n  }\n  expect(variety).toEqual({\n    name: expect.stringMatching(/re$/),\n    count: 1,\n  })\n})\n```\n\n:::tip\nYou can use `expect.not` with this matcher to negate the expected value.\n:::\n\n## expect.schemaMatching\n\n- **Type:** `(expected: StandardSchemaV1) => any`\n\nWhen used with an equality check, this asymmetric matcher will return `true` if the value matches the provided schema. The schema must implement the [Standard Schema v1](https://standardschema.dev/) specification.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { z } from 'zod'\nimport * as v from 'valibot'\nimport { type } from 'arktype'\n\ntest('email validation', () => {\n  const user = { email: 'john@example.com' }\n\n  // using Zod\n  expect(user).toEqual({\n    email: expect.schemaMatching(z.string().email()),\n  })\n\n  // using Valibot\n  expect(user).toEqual({\n    email: expect.schemaMatching(v.pipe(v.string(), v.email()))\n  })\n\n  // using ArkType\n  expect(user).toEqual({\n    email: expect.schemaMatching(type('string.email')),\n  })\n})\n```\n\n:::tip\nYou can use `expect.not` with this matcher to negate the expected value.\n:::\n\n## expect.addSnapshotSerializer\n\n- **Type:** `(plugin: PrettyFormatPlugin) => void`\n\nThis method adds custom serializers that are called when creating a snapshot. This is an advanced feature - if you want to know more, please read a [guide on custom serializers](/guide/snapshot#custom-serializer).\n\nIf you are adding custom serializers, you should call this method inside [`setupFiles`](/config/setupfiles). This will affect every snapshot.\n\n:::tip\nIf you previously used Vue CLI with Jest, you might want to install [jest-serializer-vue](https://npmx.dev/package/jest-serializer-vue). Otherwise, your snapshots will be wrapped in a string, which cases `\"` to be escaped.\n:::\n\n## expect.extend\n\n- **Type:** `(matchers: MatchersObject) => void`\n\nYou can extend default matchers with your own. This function is used to extend the matchers object with custom matchers.\n\nWhen you define matchers that way, you also create asymmetric matchers that can be used like `expect.stringContaining`.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('custom matchers', () => {\n  expect.extend({\n    toBeFoo: (received, expected) => {\n      if (received !== 'foo') {\n        return {\n          message: () => `expected ${received} to be foo`,\n          pass: false,\n        }\n      }\n    },\n  })\n\n  expect('foo').toBeFoo()\n  expect({ foo: 'foo' }).toEqual({ foo: expect.toBeFoo() })\n})\n```\n\n::: tip\nIf you want your matchers to appear in every test, you should call this method inside [`setupFiles`](/config/setupfiles).\n:::\n\nThis function is compatible with Jest's `expect.extend`, so any library that uses it to create custom matchers will work with Vitest.\n\nIf you are using TypeScript, since Vitest 0.31.0 you can extend default `Assertion` interface in an ambient declaration file (e.g: `vitest.d.ts`) with the code below:\n\n```ts\ninterface CustomMatchers<R = unknown> {\n  toBeFoo: () => R\n}\n\ndeclare module 'vitest' {\n  interface Assertion<T = any> extends CustomMatchers<T> {}\n  interface AsymmetricMatchersContaining extends CustomMatchers {}\n}\n```\n\n::: warning\nDon't forget to include the ambient declaration file in your `tsconfig.json`.\n:::\n\n:::tip\nIf you want to know more, checkout [guide on extending matchers](/guide/extending-matchers).\n:::\n\n## expect.addEqualityTesters {#expect-addequalitytesters}\n\n- **Type:** `(tester: Array<Tester>) => void`\n\nYou can use this method to define custom testers, which are methods used by matchers, to test if two objects are equal. It is compatible with Jest's `expect.addEqualityTesters`.\n\n```ts\nimport { expect, test } from 'vitest'\n\nclass AnagramComparator {\n  public word: string\n\n  constructor(word: string) {\n    this.word = word\n  }\n\n  equals(other: AnagramComparator): boolean {\n    const cleanStr1 = this.word.replace(/ /g, '').toLowerCase()\n    const cleanStr2 = other.word.replace(/ /g, '').toLowerCase()\n\n    const sortedStr1 = cleanStr1.split('').sort().join('')\n    const sortedStr2 = cleanStr2.split('').sort().join('')\n\n    return sortedStr1 === sortedStr2\n  }\n}\n\nfunction isAnagramComparator(a: unknown): a is AnagramComparator {\n  return a instanceof AnagramComparator\n}\n\nfunction areAnagramsEqual(a: unknown, b: unknown): boolean | undefined {\n  const isAAnagramComparator = isAnagramComparator(a)\n  const isBAnagramComparator = isAnagramComparator(b)\n\n  if (isAAnagramComparator && isBAnagramComparator) {\n    return a.equals(b)\n  }\n  else if (isAAnagramComparator === isBAnagramComparator) {\n    return undefined\n  }\n  else {\n    return false\n  }\n}\n\nexpect.addEqualityTesters([areAnagramsEqual])\n\ntest('custom equality tester', () => {\n  expect(new AnagramComparator('listen')).toEqual(new AnagramComparator('silent'))\n})\n```\n"
  },
  {
    "path": "docs/api/hooks.md",
    "content": "---\noutline: deep\n---\n\n# Hooks\n\nThese functions allow you to hook into the life cycle of tests to avoid repeating setup and teardown code. They apply to the current context: the file if they are used at the top-level or the current suite if they are inside a `describe` block. These hooks are not called, when you are running Vitest as a [type checker](/guide/testing-types).\n\nTest hooks are called in a stack order (\"after\" hooks are reversed) by default, but you can configure it via [`sequence.hooks`](/config/sequence#sequence-hooks) option.\n\n## beforeEach\n\n```ts\nfunction beforeEach(\n  body: (context: TestContext) => unknown,\n  timeout?: number,\n): void\n```\n\nRegister a callback to be called before each of the tests in the current suite runs.\nIf the function returns a promise, Vitest waits until the promise resolve before running the test.\n\nOptionally, you can pass a timeout (in milliseconds) defining how long to wait before terminating. The default is 10 seconds, and can be configured globally with [`hookTimeout`](/config/hooktimeout).\n\n```ts\nimport { beforeEach } from 'vitest'\n\nbeforeEach(async () => {\n  // Clear mocks and add some testing data before each test run\n  await stopMocking()\n  await addUser({ name: 'John' })\n})\n```\n\nHere, the `beforeEach` ensures that user is added for each test.\n\n`beforeEach` can also return an optional cleanup function (equivalent to [`afterEach`](#aftereach)):\n\n```ts\nimport { beforeEach } from 'vitest'\n\nbeforeEach(async () => {\n  // called once before each test run\n  await prepareSomething()\n\n  // clean up function, called once after each test run\n  return async () => {\n    await resetSomething()\n  }\n})\n```\n\n## afterEach\n\n```ts\nfunction afterEach(\n  body: (context: TestContext) => unknown,\n  timeout?: number,\n): void\n```\n\nRegister a callback to be called after each one of the tests in the current suite completes.\nIf the function returns a promise, Vitest waits until the promise resolve before continuing.\n\nOptionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The default is 10 seconds, and can be configured globally with [`hookTimeout`](/config/hooktimeout).\n\n```ts\nimport { afterEach } from 'vitest'\n\nafterEach(async () => {\n  await clearTestingData() // clear testing data after each test run\n})\n```\n\nHere, the `afterEach` ensures that testing data is cleared after each test runs.\n\n::: tip\nYou can also use [`onTestFinished`](#ontestfinished) during the test execution to cleanup any state after the test has finished running.\n:::\n\n## beforeAll\n\n```ts\nfunction beforeAll(\n  body: (context: ModuleContext) => unknown,\n  timeout?: number,\n): void\n```\n\nRegister a callback to be called once before starting to run all tests in the current suite.\nIf the function returns a promise, Vitest waits until the promise resolve before running tests.\n\nOptionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The default is 10 seconds, and can be configured globally with [`hookTimeout`](/config/hooktimeout).\n\n```ts\nimport { beforeAll } from 'vitest'\n\nbeforeAll(async () => {\n  await startMocking() // called once before all tests run\n})\n```\n\nHere the `beforeAll` ensures that the mock data is set up before tests run.\n\n`beforeAll` can also return an optional cleanup function (equivalent to [`afterAll`](#afterall)):\n\n```ts\nimport { beforeAll } from 'vitest'\n\nbeforeAll(async () => {\n  // called once before all tests run\n  await startMocking()\n\n  // clean up function, called once after all tests run\n  return async () => {\n    await stopMocking()\n  }\n})\n```\n\n## afterAll\n\n```ts\nfunction afterAll(\n  body: (context: ModuleContext) => unknown,\n  timeout?: number,\n): void\n```\n\nRegister a callback to be called once after all tests have run in the current suite.\nIf the function returns a promise, Vitest waits until the promise resolve before continuing.\n\nOptionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The default is 10 seconds, and can be configured globally with [`hookTimeout`](/config/hooktimeout).\n\n```ts\nimport { afterAll } from 'vitest'\n\nafterAll(async () => {\n  await stopMocking() // this method is called after all tests run\n})\n```\n\nHere the `afterAll` ensures that `stopMocking` method is called after all tests run.\n\n## aroundEach\n\n```ts\nfunction aroundEach(\n  body: (\n    runTest: () => Promise<void>,\n    context: TestContext,\n  ) => Promise<void>,\n  timeout?: number,\n): void\n```\n\nRegister a callback function that wraps around each test within the current suite. The callback receives a `runTest` function that **must** be called to run the test.\n\nThe `runTest()` function runs `beforeEach` hooks, the test itself, fixtures accessed in the test, and `afterEach` hooks. Fixtures that are accessed in the `aroundEach` callback are initialized before `runTest()` is called and are torn down after the aroundEach teardown code completes, allowing you to safely use them in both setup and teardown phases.\n\n::: warning\nYou **must** call `runTest()` within your callback. If `runTest()` is not called, the test will fail with an error.\n:::\n\nOptionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The timeout applies independently to the setup phase (before `runTest()`) and teardown phase (after `runTest()`). The default is 10 seconds, and can be configured globally with [`hookTimeout`](/config/hooktimeout).\n\n```ts\nimport { aroundEach, test } from 'vitest'\n\naroundEach(async (runTest) => {\n  await db.transaction(runTest)\n})\n\ntest('insert user', async () => {\n  await db.insert({ name: 'Alice' })\n  // transaction is automatically rolled back after the test\n})\n```\n\n::: tip When to use `aroundEach`\nUse `aroundEach` when your test needs to run **inside a context** that wraps around it, such as:\n- Wrapping tests in [AsyncLocalStorage](https://nodejs.org/api/async_context.html#class-asynclocalstorage) context\n- Wrapping tests with tracing spans\n- Database transactions\n\nIf you just need to run code before and after tests, prefer using [`beforeEach`](#beforeeach) with a cleanup return function:\n```ts\nbeforeEach(async () => {\n  await database.connect()\n  return async () => {\n    await database.disconnect()\n  }\n})\n```\n:::\n\n### Multiple Hooks\n\nWhen multiple `aroundEach` hooks are registered, they are nested inside each other. The first registered hook is the outermost wrapper:\n\n```ts\naroundEach(async (runTest) => {\n  console.log('outer before')\n  await runTest()\n  console.log('outer after')\n})\n\naroundEach(async (runTest) => {\n  console.log('inner before')\n  await runTest()\n  console.log('inner after')\n})\n\n// Output order:\n//  outer before\n//    inner before\n//      test\n//    inner after\n//  outer after\n```\n\n### Context and Fixtures\n\nThe callback receives the test context as the second argument which means that you can use fixtures with `aroundEach`:\n\n```ts\nimport { aroundEach, test as base } from 'vitest'\n\nconst test = base.extend<{ db: Database; user: User }>({\n  db: async ({}, use) => {\n    // db is created before `aroundEach` hook\n    const db = await createTestDatabase()\n    await use(db)\n    await db.close()\n  },\n  user: async ({ db }, use) => {\n    // `user` runs as part of the transaction\n    // because it's accessed inside the `test`\n    const user = await db.createUser()\n    await use(user)\n  },\n})\n\n// note that `aroundEach` is available on test\n// for a better TypeScript support of fixtures\ntest.aroundEach(async (runTest, { db }) => {\n  await db.transaction(runTest)\n})\n\ntest('insert user', async ({ db, user }) => {\n  await db.insert(user)\n})\n```\n\n## aroundAll\n\n```ts\nfunction aroundAll(\n  body: (\n    runSuite: () => Promise<void>,\n    context: ModuleContext,\n  ) => Promise<void>,\n  timeout?: number,\n): void\n```\n\nRegister a callback function that wraps around all tests within the current suite. The callback receives a `runSuite` function that **must** be called to run the suite's tests.\n\nThe `runSuite()` function runs all tests in the suite, including `beforeAll`/`afterAll`/`beforeEach`/`afterEach` hooks, `aroundEach` hooks, and fixtures.\n\n::: warning\nYou **must** call `runSuite()` within your callback. If `runSuite()` is not called, the hook will fail with an error and all tests in the suite will be skipped.\n:::\n\nOptionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating. The timeout applies independently to the setup phase (before `runSuite()`) and teardown phase (after `runSuite()`). The default is 10 seconds, and can be configured globally with [`hookTimeout`](/config/hooktimeout).\n\n```ts\nimport { aroundAll, test } from 'vitest'\n\naroundAll(async (runSuite) => {\n  await tracer.trace('test-suite', runSuite)\n})\n\ntest('test 1', () => {\n  // Runs within the tracing span\n})\n\ntest('test 2', () => {\n  // Also runs within the same tracing span\n})\n```\n\n::: tip When to use `aroundAll`\nUse `aroundAll` when your suite needs to run **inside a context** that wraps around all tests, such as:\n- Wrapping an entire suite in [AsyncLocalStorage](https://nodejs.org/api/async_context.html#class-asynclocalstorage) context\n- Wrapping a suite with tracing spans\n- Database transactions\n\nIf you just need to run code once before and after all tests, prefer using [`beforeAll`](#beforeall) with a cleanup return function:\n```ts\nbeforeAll(async () => {\n  await server.start()\n  return async () => {\n    await server.stop()\n  }\n})\n```\n:::\n\n### Multiple Hooks\n\nWhen multiple `aroundAll` hooks are registered, they are nested inside each other. The first registered hook is the outermost wrapper:\n\n```ts\naroundAll(async (runSuite) => {\n  console.log('outer before')\n  await runSuite()\n  console.log('outer after')\n})\n\naroundAll(async (runSuite) => {\n  console.log('inner before')\n  await runSuite()\n  console.log('inner after')\n})\n\n// Output order: outer before → inner before → tests → inner after → outer after\n```\n\nEach suite has its own independent `aroundAll` hooks. Parent suite's `aroundAll` wraps around child suite's execution:\n\n```ts\nimport { AsyncLocalStorage } from 'node:async_hooks'\nimport { aroundAll, describe, test } from 'vitest'\n\nconst context = new AsyncLocalStorage<{ suiteId: string }>()\n\naroundAll(async (runSuite) => {\n  await context.run({ suiteId: 'root' }, runSuite)\n})\n\ntest('root test', () => {\n  // context.getStore() returns { suiteId: 'root' }\n})\n\ndescribe('nested', () => {\n  aroundAll(async (runSuite) => {\n    // Parent's context is available here\n    await context.run({ suiteId: 'nested' }, runSuite)\n  })\n\n  test('nested test', () => {\n    // context.getStore() returns { suiteId: 'nested' }\n  })\n})\n```\n\n## Test Hooks\n\nVitest provides a few hooks that you can call _during_ the test execution to cleanup the state when the test has finished running.\n\n::: warning\nThese hooks will throw an error if they are called outside of the test body.\n:::\n\n### onTestFinished {#ontestfinished}\n\nThis hook is always called after the test has finished running. It is called after `afterEach` hooks since they can influence the test result. It receives an `TestContext` object like `beforeEach` and `afterEach`.\n\n```ts {1,5}\nimport { onTestFinished, test } from 'vitest'\n\ntest('performs a query', () => {\n  const db = connectDb()\n  onTestFinished(() => db.close())\n  db.query('SELECT * FROM users')\n})\n```\n\n::: warning\nIf you are running tests concurrently, you should always use `onTestFinished` hook from the test context since Vitest doesn't track concurrent tests in global hooks:\n\n```ts {3,5}\nimport { test } from 'vitest'\n\ntest.concurrent('performs a query', ({ onTestFinished }) => {\n  const db = connectDb()\n  onTestFinished(() => db.close())\n  db.query('SELECT * FROM users')\n})\n```\n:::\n\nThis hook is particularly useful when creating reusable logic:\n\n```ts\n// this can be in a separate file\nfunction getTestDb() {\n  const db = connectMockedDb()\n  onTestFinished(() => db.close())\n  return db\n}\n\ntest('performs a user query', async () => {\n  const db = getTestDb()\n  expect(\n    await db.query('SELECT * from users').perform()\n  ).toEqual([])\n})\n\ntest('performs an organization query', async () => {\n  const db = getTestDb()\n  expect(\n    await db.query('SELECT * from organizations').perform()\n  ).toEqual([])\n})\n```\n\nIt is also a good practice to cleanup your spies after each test, so they don't leak into other tests. You can do so by enabling [`restoreMocks`](/config/restoremocks) config globally, or restoring the spy inside `onTestFinished` (if you try to restore the mock at the end of the test, it won't be restored if one of the assertions fails - using `onTestFinished` ensures the code always runs):\n\n```ts\nimport { onTestFinished, test } from 'vitest'\n\ntest('performs a query', () => {\n  const spy = vi.spyOn(db, 'query')\n  onTestFinished(() => spy.mockClear())\n\n  db.query('SELECT * FROM users')\n  expect(spy).toHaveBeenCalled()\n})\n```\n\n::: tip\nThis hook is always called in reverse order and is not affected by [`sequence.hooks`](/config/sequence#sequence-hooks) option.\n:::\n\n### onTestFailed\n\nThis hook is called only after the test has failed. It is called after `afterEach` hooks since they can influence the test result. It receives a `TestContext` object like `beforeEach` and `afterEach`. This hook is useful for debugging.\n\n```ts {1,5-7}\nimport { onTestFailed, test } from 'vitest'\n\ntest('performs a query', () => {\n  const db = connectDb()\n  onTestFailed(({ task }) => {\n    console.log(task.result.errors)\n  })\n  db.query('SELECT * FROM users')\n})\n```\n\n::: warning\nIf you are running tests concurrently, you should always use `onTestFailed` hook from the test context since Vitest doesn't track concurrent tests in global hooks:\n\n```ts {3,5-7}\nimport { test } from 'vitest'\n\ntest.concurrent('performs a query', ({ onTestFailed }) => {\n  const db = connectDb()\n  onTestFailed(({ task }) => {\n    console.log(task.result.errors)\n  })\n  db.query('SELECT * FROM users')\n})\n```\n:::\n"
  },
  {
    "path": "docs/api/mock.md",
    "content": "# Mocks\n\nYou can create a mock function or a class to track its execution with the `vi.fn` method. If you want to track a property on an already created object, you can use the `vi.spyOn` method:\n\n```js\nimport { vi } from 'vitest'\n\nconst fn = vi.fn()\nfn('hello world')\nfn.mock.calls[0] === ['hello world']\n\nconst market = {\n  getApples: () => 100\n}\n\nconst getApplesSpy = vi.spyOn(market, 'getApples')\nmarket.getApples()\ngetApplesSpy.mock.calls.length === 1\n```\n\nYou should use mock assertions (e.g., [`toHaveBeenCalled`](/api/expect#tohavebeencalled)) on [`expect`](/api/expect) to assert mock results. This API reference describes available properties and methods to manipulate mock behavior.\n\n::: warning IMPORTANT\nVitest spies inherit implementation's [`length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length) property when initialized, but it doesn't override it if the implementation was changed later:\n\n::: code-group\n```ts [vi.fn]\nconst fn = vi.fn((arg1) => {})\nfn.length // == 1\n\nfn.mockImplementation(() => {})\nfn.length // == 1\n```\n```ts [vi.spyOn]\nconst example = {\n  fn(arg1, arg2) {\n    // ...\n  }\n}\n\nconst fn = vi.spyOn(example, 'fn')\nfn.length // == 2\n\nfn.mockImplementation(() => {})\nfn.length // == 2\n```\n:::\n\n::: tip\nThe custom function implementation in the types below is marked with a generic `<T>`.\n:::\n\n::: warning Class Support {#class-support}\nShorthand methods like `mockReturnValue`, `mockReturnValueOnce`, `mockResolvedValue` and others cannot be used on a mocked class. Class constructors have [unintuitive behaviour](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/constructor) regarding the return value:\n\n```ts {2,7}\nconst CorrectDogClass = vi.fn(class {\n  constructor(public name: string) {}\n})\n\nconst IncorrectDogClass = vi.fn(class {\n  constructor(public name: string) {\n    return { name }\n  }\n})\n\nconst Marti = new CorrectDogClass('Marti')\nconst Newt = new IncorrectDogClass('Newt')\n\nMarti instanceof CorrectDogClass // ✅ true\nNewt instanceof IncorrectDogClass // ❌ false!\n```\n\nEven though the shapes are the same, the _return value_ from the constructor is assigned to `Newt`, which is a plain object, not an instance of a mock. Vitest guards you against this behaviour in shorthand methods (but not in `mockImplementation`!) and throws an error instead.\n\nIf you need to mock constructed instance of a class, consider using the `class` syntax with `mockImplementation` instead:\n\n```ts\nmock.mockReturnValue({ hello: () => 'world' }) // [!code --]\nmock.mockImplementation(class { hello = () => 'world' }) // [!code ++]\n```\n\nIf you need to test the behaviour where this is a valid use case, you can use `mockImplementation` with a `constructor`:\n\n```ts\nmock.mockImplementation(class {\n  constructor(name: string) {\n    return { name }\n  }\n})\n```\n:::\n\n## getMockImplementation\n\n```ts\nfunction getMockImplementation(): T | undefined\n```\n\nReturns the current mock implementation if there is one.\n\nIf the mock was created with [`vi.fn`](/api/vi#vi-fn), it will use the provided method as the mock implementation.\n\nIf the mock was created with [`vi.spyOn`](/api/vi#vi-spyon), it will return `undefined` unless a custom implementation is provided.\n\n## getMockName\n\n```ts\nfunction getMockName(): string\n```\n\nUse it to return the name assigned to the mock with the `.mockName(name)` method. By default, `vi.fn()` mocks will return `'vi.fn()'`, while spies created with `vi.spyOn` will keep the original name.\n\n## mockClear\n\n```ts\nfunction mockClear(): Mock<T>\n```\n\nClears all information about every call. After calling it, all properties on `.mock` will return to their initial state. This method does not reset implementations. It is useful for cleaning up mocks between different assertions.\n\n```ts\nconst person = {\n  greet: (name: string) => `Hello ${name}`,\n}\nconst spy = vi.spyOn(person, 'greet').mockImplementation(() => 'mocked')\nexpect(person.greet('Alice')).toBe('mocked')\nexpect(spy.mock.calls).toEqual([['Alice']])\n\n// clear call history but keep mock implementation\nspy.mockClear()\nexpect(spy.mock.calls).toEqual([])\nexpect(person.greet('Bob')).toBe('mocked')\nexpect(spy.mock.calls).toEqual([['Bob']])\n```\n\nTo automatically call this method before each test, enable the [`clearMocks`](/config/clearmocks) setting in the configuration.\n\n## mockName\n\n```ts\nfunction mockName(name: string): Mock<T>\n```\n\nSets the internal mock name. This is useful for identifying the mock when an assertion fails.\n\n## mockImplementation\n\n```ts\nfunction mockImplementation(fn: T): Mock<T>\n```\n\nAccepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function.\n\n```ts\nconst mockFn = vi.fn().mockImplementation((apples: number) => apples + 1)\n// or: vi.fn(apples => apples + 1);\n\nconst NelliesBucket = mockFn(0)\nconst BobsBucket = mockFn(1)\n\nNelliesBucket === 1 // true\nBobsBucket === 2 // true\n\nmockFn.mock.calls[0][0] === 0 // true\nmockFn.mock.calls[1][0] === 1 // true\n```\n\n## mockImplementationOnce\n\n```ts\nfunction mockImplementationOnce(fn: T): Mock<T>\n```\n\nAccepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function. This method can be chained to produce different results for multiple function calls.\n\n```ts\nconst myMockFn = vi\n  .fn()\n  .mockImplementationOnce(() => true) // 1st call\n  .mockImplementationOnce(() => false) // 2nd call\n\nmyMockFn() // 1st call: true\nmyMockFn() // 2nd call: false\n```\n\nWhen the mocked function runs out of implementations, it will invoke the default implementation set with `vi.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called:\n\n```ts\nconst myMockFn = vi\n  .fn(() => 'default')\n  .mockImplementationOnce(() => 'first call')\n  .mockImplementationOnce(() => 'second call')\n\n// 'first call', 'second call', 'default', 'default'\nconsole.log(myMockFn(), myMockFn(), myMockFn(), myMockFn())\n```\n\n## withImplementation\n\n```ts\nfunction withImplementation(\n  fn: T,\n  cb: () => void\n): Mock<T>\nfunction withImplementation(\n  fn: T,\n  cb: () => Promise<void>\n): Promise<Mock<T>>\n```\n\nOverrides the original mock implementation temporarily while the callback is being executed.\n\n```js\nconst myMockFn = vi.fn(() => 'original')\n\nmyMockFn.withImplementation(() => 'temp', () => {\n  myMockFn() // 'temp'\n})\n\nmyMockFn() // 'original'\n```\n\nCan be used with an asynchronous callback. The method has to be awaited to use the original implementation afterward.\n\n```ts\ntest('async callback', () => {\n  const myMockFn = vi.fn(() => 'original')\n\n  // We await this call since the callback is async\n  await myMockFn.withImplementation(\n    () => 'temp',\n    async () => {\n      myMockFn() // 'temp'\n    },\n  )\n\n  myMockFn() // 'original'\n})\n```\n\nNote that this method takes precedence over the [`mockImplementationOnce`](#mockimplementationonce).\n\n## mockRejectedValue\n\n```ts\nfunction mockRejectedValue(value: unknown): Mock<T>\n```\n\nAccepts an error that will be rejected when an async function is called.\n\n```ts\nconst asyncMock = vi.fn().mockRejectedValue(new Error('Async error'))\n\nawait asyncMock() // throws Error<'Async error'>\n```\n\n## mockRejectedValueOnce\n\n```ts\nfunction mockRejectedValueOnce(value: unknown): Mock<T>\n```\n\nAccepts a value that will be rejected during the next function call. If chained, each consecutive call will reject the specified value.\n\n```ts\nconst asyncMock = vi\n  .fn()\n  .mockResolvedValueOnce('first call')\n  .mockRejectedValueOnce(new Error('Async error'))\n\nawait asyncMock() // 'first call'\nawait asyncMock() // throws Error<'Async error'>\n```\n\n## mockReset\n\n```ts\nfunction mockReset(): Mock<T>\n```\n\nDoes what [`mockClear`](#mockClear) does and resets the mock implementation. This also resets all \"once\" implementations.\n\nNote that resetting a mock from `vi.fn()` will set the implementation to an empty function that returns `undefined`.\nResetting a mock from `vi.fn(impl)` will reset the implementation to `impl`.\n\nThis is useful when you want to reset a mock to its original state.\n\n```ts\nconst person = {\n  greet: (name: string) => `Hello ${name}`,\n}\nconst spy = vi.spyOn(person, 'greet').mockImplementation(() => 'mocked')\nexpect(person.greet('Alice')).toBe('mocked')\nexpect(spy.mock.calls).toEqual([['Alice']])\n\n// clear call history and reset implementation, but method is still spied\nspy.mockReset()\nexpect(spy.mock.calls).toEqual([])\nexpect(person.greet).toBe(spy)\nexpect(person.greet('Bob')).toBe('Hello Bob')\nexpect(spy.mock.calls).toEqual([['Bob']])\n```\n\nTo automatically call this method before each test, enable the [`mockReset`](/config/mockreset) setting in the configuration.\n\n## mockRestore\n\n```ts\nfunction mockRestore(): Mock<T>\n```\n\nDoes what [`mockReset`](#mockreset) does and restores the original descriptors of spied-on objects, if the mock was created with [`vi.spyOn`](/api/vi#vi-spyon).\n\n`mockRestore` on a `vi.fn()` mock is identical to [`mockReset`](#mockreset).\n\n```ts\nconst person = {\n  greet: (name: string) => `Hello ${name}`,\n}\nconst spy = vi.spyOn(person, 'greet').mockImplementation(() => 'mocked')\nexpect(person.greet('Alice')).toBe('mocked')\nexpect(spy.mock.calls).toEqual([['Alice']])\n\n// clear call history and restore spied object method\nspy.mockRestore()\nexpect(spy.mock.calls).toEqual([])\nexpect(person.greet).not.toBe(spy)\nexpect(person.greet('Bob')).toBe('Hello Bob')\nexpect(spy.mock.calls).toEqual([])\n```\n\nTo automatically call this method before each test, enable the [`restoreMocks`](/config/restoremocks) setting in the configuration.\n\n## mockResolvedValue\n\n```ts\nfunction mockResolvedValue(value: Awaited<ReturnType<T>>): Mock<T>\n```\n\nAccepts a value that will be resolved when the async function is called. TypeScript will only accept values that match the return type of the original function.\n\n```ts\nconst asyncMock = vi.fn().mockResolvedValue(42)\n\nawait asyncMock() // 42\n```\n\n## mockResolvedValueOnce\n\n```ts\nfunction mockResolvedValueOnce(value: Awaited<ReturnType<T>>): Mock<T>\n```\n\nAccepts a value that will be resolved during the next function call. TypeScript will only accept values that match the return type of the original function. If chained, each consecutive call will resolve the specified value.\n\n```ts\nconst asyncMock = vi\n  .fn()\n  .mockResolvedValue('default')\n  .mockResolvedValueOnce('first call')\n  .mockResolvedValueOnce('second call')\n\nawait asyncMock() // first call\nawait asyncMock() // second call\nawait asyncMock() // default\nawait asyncMock() // default\n```\n\n## mockReturnThis\n\n```ts\nfunction mockReturnThis(): Mock<T>\n```\n\nUse this if you need to return the `this` context from the method without invoking the actual implementation. This is a shorthand for:\n\n```ts\nspy.mockImplementation(function () {\n  return this\n})\n```\n\n## mockReturnValue\n\n```ts\nfunction mockReturnValue(value: ReturnType<T>): Mock<T>\n```\n\nAccepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function.\n\n```ts\nconst mock = vi.fn()\nmock.mockReturnValue(42)\nmock() // 42\nmock.mockReturnValue(43)\nmock() // 43\n```\n\n## mockReturnValueOnce\n\n```ts\nfunction mockReturnValueOnce(value: ReturnType<T>): Mock<T>\n```\n\nAccepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function.\n\nWhen the mocked function runs out of implementations, it will invoke the default implementation set with `vi.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called:\n\n```ts\nconst myMockFn = vi\n  .fn()\n  .mockReturnValue('default')\n  .mockReturnValueOnce('first call')\n  .mockReturnValueOnce('second call')\n\n// 'first call', 'second call', 'default', 'default'\nconsole.log(myMockFn(), myMockFn(), myMockFn(), myMockFn())\n```\n\n## mockThrow <Version>4.1.0</Version> {#mockthrow}\n\n```ts\nfunction mockThrow(value: unknown): Mock<T>\n```\n\nAccepts a value that will be thrown whenever the mock function is called.\n\n```ts\nconst myMockFn = vi.fn()\nmyMockFn.mockThrow(new Error('error message'))\nmyMockFn() // throws Error<'error message'>\n```\n\n## mockThrowOnce <Version>4.1.0</Version> {#mockthrowonce}\n\n```ts\nfunction mockThrowOnce(value: unknown): Mock<T>\n```\n\nAccepts a value that will be thrown during the next function call. If chained, every consecutive call will throw the specified value.\n\n```ts\nconst myMockFn = vi\n  .fn()\n  .mockReturnValue('default')\n  .mockThrowOnce(new Error('first call error'))\n  .mockThrowOnce('second call error')\n\nexpect(() => myMockFn()).toThrow('first call error')\nexpect(() => myMockFn()).toThrow('second call error')\nexpect(myMockFn()).toEqual('default')\n```\n\n## mock.calls\n\n```ts\nconst calls: Parameters<T>[]\n```\n\nThis is an array containing all arguments for each call. One item of the array is the arguments of that call.\n\n```js\nconst fn = vi.fn()\n\nfn('arg1', 'arg2')\nfn('arg3')\n\nfn.mock.calls === [\n  ['arg1', 'arg2'], // first call\n  ['arg3'], // second call\n]\n```\n\n:::warning Objects are Stored by Reference\nNote that Vitest always stores objects by reference in all properies of the `mock` state. This means that if the properties were changed by your code, then some assertions like [`.toHaveBeenCalledWith`](/api/expect#tohavebeencalledwith) will not pass:\n\n```ts\nconst argument = {\n  value: 0,\n}\nconst fn = vi.fn()\nfn(argument) // { value: 0 }\n\nargument.value = 10\n\nexpect(fn).toHaveBeenCalledWith({ value: 0 }) // [!code --]\n\n// The equality check is done against the original argument,\n// but its property was changed between the call and assertion\nexpect(fn).toHaveBeenCalledWith({ value: 10 }) // [!code ++]\n```\n\nIn this case you can clone the argument yourself:\n\n```ts{6}\nconst calledArguments = []\nconst fn = vi.fn((arg) => {\n  calledArguments.push(structuredClone(arg))\n})\n\nexpect(calledArguments[0]).toEqual({ value: 0 })\n```\n:::\n\n## mock.lastCall\n\n```ts\nconst lastCall: Parameters<T> | undefined\n```\n\nThis contains the arguments of the last call. If the mock wasn't called, it will return `undefined`.\n\n## mock.results\n\n```ts\ninterface MockResultReturn<T> {\n  type: 'return'\n  /**\n   * The value that was returned from the function.\n   * If the function returned a Promise, then this will be a resolved value.\n   */\n  value: T\n}\n\ninterface MockResultIncomplete {\n  type: 'incomplete'\n  value: undefined\n}\n\ninterface MockResultThrow {\n  type: 'throw'\n  /**\n   * An error that was thrown during function execution.\n   */\n  value: any\n}\n\ntype MockResult<T>\n  = | MockResultReturn<T>\n    | MockResultThrow\n    | MockResultIncomplete\n\nconst results: MockResult<ReturnType<T>>[]\n```\n\nThis is an array containing all values that were `returned` from the function. One item of the array is an object with properties `type` and `value`. Available types are:\n\n- `'return'` - function returned without throwing.\n- `'throw'` - function threw a value.\n- `'incomplete'` - the function did not finish running yet.\n\nThe `value` property contains the returned value or thrown error. If the function returned a `Promise`, then `result` will always be `'return'` even if the promise was rejected.\n\n```js\nconst fn = vi.fn()\n  .mockReturnValueOnce('result')\n  .mockImplementationOnce(() => { throw new Error('thrown error') })\n\nconst result = fn() // returned 'result'\n\ntry {\n  fn() // threw Error\n}\ncatch {}\n\nfn.mock.results === [\n  // first result\n  {\n    type: 'return',\n    value: 'result',\n  },\n  // last result\n  {\n    type: 'throw',\n    value: Error,\n  },\n]\n```\n\n## mock.settledResults\n\n```ts\ninterface MockSettledResultIncomplete {\n  type: 'incomplete'\n  value: undefined\n}\n\ninterface MockSettledResultFulfilled<T> {\n  type: 'fulfilled'\n  value: T\n}\n\ninterface MockSettledResultRejected {\n  type: 'rejected'\n  value: any\n}\n\nexport type MockSettledResult<T>\n  = | MockSettledResultFulfilled<T>\n    | MockSettledResultRejected\n    | MockSettledResultIncomplete\n\nconst settledResults: MockSettledResult<Awaited<ReturnType<T>>>[]\n```\n\nAn array containing all values that were resolved or rejected by the function.\n\nIf the function returned non-promise values, the `value` will be kept as is, but the `type` will still says `fulfilled` or `rejected`.\n\nUntil the value is resolved or rejected, the `settledResult` type will be `incomplete`.\n\n```js\nconst fn = vi.fn().mockResolvedValueOnce('result')\n\nconst result = fn()\n\nfn.mock.settledResults === [\n  {\n    type: 'incomplete',\n    value: undefined,\n  },\n]\n\nawait result\n\nfn.mock.settledResults === [\n  {\n    type: 'fulfilled',\n    value: 'result',\n  },\n]\n```\n\n## mock.invocationCallOrder\n\n```ts\nconst invocationCallOrder: number[]\n```\n\nThis property returns the order of the mock function's execution. It is an array of numbers that are shared between all defined mocks.\n\n```js\nconst fn1 = vi.fn()\nconst fn2 = vi.fn()\n\nfn1()\nfn2()\nfn1()\n\nfn1.mock.invocationCallOrder === [1, 3]\nfn2.mock.invocationCallOrder === [2]\n```\n\n## mock.contexts\n\n```ts\nconst contexts: ThisParameterType<T>[]\n```\n\nThis property is an array of `this` values used during each call to the mock function.\n\n```js\nconst fn = vi.fn()\nconst context = {}\n\nfn.apply(context)\nfn.call(context)\n\nfn.mock.contexts[0] === context\nfn.mock.contexts[1] === context\n```\n\n## mock.instances\n\n```ts\nconst instances: ReturnType<T>[]\n```\n\nThis property is an array containing all instances that were created when the mock was called with the `new` keyword. Note that this is the actual context (`this`) of the function, not a return value.\n\n::: warning\nIf the mock was instantiated with `new MyClass()`, then `mock.instances` will be an array with one value:\n\n```js\nconst MyClass = vi.fn()\nconst a = new MyClass()\n\nMyClass.mock.instances[0] === a\n```\n\nIf you return a value from the constructor, it will not be in the `instances` array, but instead inside `results`:\n\n```js\nconst Spy = vi.fn(() => ({ method: vi.fn() }))\nconst a = new Spy()\n\nSpy.mock.instances[0] !== a\nSpy.mock.results[0] === a\n```\n:::\n"
  },
  {
    "path": "docs/api/test.md",
    "content": "---\noutline: deep\n---\n\n# Test\n\n- **Alias:** `it`\n\n```ts\nfunction test(\n  name: string | Function,\n  body?: () => unknown,\n  timeout?: number\n): void\nfunction test(\n  name: string | Function,\n  options: TestOptions,\n  body?: () => unknown,\n): void\n```\n\n`test` or `it` defines a set of related expectations. It receives the test name and a function that holds the expectations to test.\n\nOptionally, you can provide a timeout (in milliseconds) for specifying how long to wait before terminating, or a set of [additional options](#test-options). The default timeout is 5 seconds, and can be configured globally with [`testTimeout`](/config/testtimeout).\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('should work as expected', () => {\n  expect(Math.sqrt(4)).toBe(2)\n})\n```\n\n::: warning\nIf the first argument is a function, its `name` property will be used as the name of the test. The function itself will not be called.\n\nIf test body is not provided, the test is marked as `todo`.\n:::\n\nWhen a test function returns a promise, the runner will wait until it is resolved to collect async expectations. If the promise is rejected, the test will fail.\n\n::: tip\nIn Jest, `TestFunction` can also be of type `(done: DoneCallback) => void`. If this form is used, the test will not be concluded until `done` is called. You can achieve the same using an `async` function, see the [Migration guide Done Callback section](/guide/migration#done-callback).\n:::\n\n## Test Options\n\nYou can define boolean options by chaining properties on a function:\n\n```ts\nimport { test } from 'vitest'\n\ntest.skip('skipped test', () => {\n  // some logic that fails right now\n})\n\ntest.concurrent.skip('skipped concurrent test', () => {\n  // some logic that fails right now\n})\n```\n\nBut you can also provide an object as a second argument instead:\n\n```ts\nimport { test } from 'vitest'\n\ntest('skipped test', { skip: true }, () => {\n  // some logic that fails right now\n})\n\ntest('skipped concurrent test', { skip: true, concurrent: true }, () => {\n  // some logic that fails right now\n})\n```\n\nThey both work in exactly the same way. To use either one is purely a stylistic choice.\n\n### timeout\n\n- **Type:** `number`\n- **Default:** `5_000` (configured by [`testTimeout`](/config/testtimeout))\n\nTest timeout in milliseconds.\n\n::: warning\nNote that if you are providing timeout as the last argument, you cannot use options anymore:\n\n```ts\nimport { test } from 'vitest'\n\n// ✅ this works\ntest.skip('heavy test', () => {\n  // ...\n}, 10_000)\n\n// ❌ this doesn't work\ntest('heavy test', { skip: true }, () => {\n  // ...\n}, 10_000)\n```\n\nHowever, you can provide a timeout inside the object:\n\n```ts\nimport { test } from 'vitest'\n\n// ✅ this works\ntest('heavy test', { skip: true, timeout: 10_000 }, () => {\n  // ...\n})\n```\n:::\n\n### retry\n\n- **Default:** `0` (configured by [`retry`](/config/retry))\n- **Type:**\n\n```ts\ntype Retry = number | {\n  /**\n   * The number of times to retry the test if it fails.\n   * @default 0\n   */\n  count?: number\n  /**\n   * Delay in milliseconds between retry attempts.\n   * @default 0\n   */\n  delay?: number\n  /**\n   * Condition to determine if a test should be retried based on the error.\n   * - If a RegExp, it is tested against the error message\n   * - If a function, called with the TestError object; return true to retry\n   *\n   * NOTE: Functions can only be used in test files, not in vitest.config.ts,\n   * because the configuration is serialized when passed to worker threads.\n   *\n   * @default undefined (retry on all errors)\n   */\n  condition?: RegExp | ((error: TestError) => boolean)\n}\n```\n\nRetry configuration for the test. If a number, specifies how many times to retry. If an object, allows fine-grained retry control.\n\nNote that the object configuration is available only since Vitest 4.1.\n\n### repeats\n\n- **Type:** `number`\n- **Default:** `0`\n\nHow many times the test will run again. If set to `0` (the default), the test will run only one time.\n\nThis can be useful for debugging flaky tests.\n\n### tags <Version>4.1.0</Version> {#tags}\n\n- **Type:** `string[]`\n- **Default:** `[]`\n\nCustom user [tags](/guide/test-tags). If the tag is not specified in the [configuration](/config/tags), the test will fail before it starts, unless [`strictTags`](/config/stricttags) is disabled manually.\n\n```ts\nimport { it } from 'vitest'\n\nit('user returns data from db', { tags: ['db', 'flaky'] }, () => {\n  // ...\n})\n```\n\n### meta <Version>4.1.0</Version> {#meta}\n\n- **Type:** `TaskMeta`\n\nAttaches custom [metadata](/api/advanced/metadata) available in reporters.\n\n::: warning\nVitest merges top-level properties inherited from suites or tags. However, it does not perform a deep merge of nested objects.\n\n```ts\nimport { describe, test } from 'vitest'\n\ndescribe(\n  'nested meta',\n  {\n    meta: {\n      nested: { object: true, array: false },\n    },\n  },\n  () => {\n    test(\n      'overrides part of meta',\n      {\n        meta: {\n          nested: { object: false }\n        },\n      },\n      ({ task }) => {\n        // task.meta === { nested: { object: false } }\n        // notice array got lost because \"nested\" object was overridden\n      }\n    )\n  }\n)\n```\n\nPrefer using non-nested meta, if possible.\n:::\n\n### concurrent\n\n- **Type:** `boolean`\n- **Default:** `false` (configured by [`sequence.concurrent`](/config/sequence#sequence-concurrent))\n- **Alias:** [`test.concurrent`](#test-concurrent)\n\nWhether this test run concurrently with other concurrent tests in the suite.\n\n### sequential\n\n- **Type:** `boolean`\n- **Default:** `true`\n- **Alias:** [`test.sequential`](#test-sequential)\n\nWhether tests run sequentially. When both `concurrent` and `sequential` are specified, `concurrent` takes precendence.\n\n### skip\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Alias:** [`test.skip`](#test-skip)\n\nWhether the test should be skipped.\n\n### only\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Alias:** [`test.only`](#test-only)\n\nShould this test be the only one running in a suite.\n\n### todo\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Alias:** [`test.todo`](#test-todo)\n\nWhether the test should be skipped and marked as a todo.\n\n### fails\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Alias:** [`test.fails`](#test-fails)\n\nWhether the test is expected to fail. If it does, the test will pass, otherwise it will fail.\n\n## test.extend\n\n- **Alias:** `it.extend`\n\nUse `test.extend` to extend the test context with custom fixtures. This will return a new `test` and it's also extendable, so you can compose more fixtures or override existing ones by extending it as you need. See [Extend Test Context](/guide/test-context#extend-test-context) for more information.\n\n```ts\nimport { test as baseTest, expect } from 'vitest'\n\nexport const test = baseTest\n  // Simple value - type is inferred as { port: number; host: string }\n  .extend('config', { port: 3000, host: 'localhost' })\n  // Function fixture - type is inferred from return value\n  .extend('server', async ({ config }) => {\n    // TypeScript knows config is { port: number; host: string }\n    return `http://${config.host}:${config.port}`\n  })\n\ntest('server uses correct port', ({ config, server }) => {\n  // TypeScript knows the types:\n  // - config is { port: number; host: string }\n  // - server is string\n  expect(server).toBe('http://localhost:3000')\n  expect(config.port).toBe(3000)\n})\n```\n\n## test.override <Version>4.1.0</Version> {#test-override}\n\nUse `test.override` to override fixture values for all tests within the current suite and its nested suites. This must be called at the top level of a `describe` block. See [Overriding Fixture Values](/guide/test-context.html#overriding-fixture-values) for more information.\n\n```ts\nimport { test as baseTest, describe, expect } from 'vitest'\n\nconst test = baseTest\n  .extend('dependency', 'default')\n  .extend('dependant', ({ dependency }) => dependency)\n\ndescribe('use scoped values', () => {\n  test.override({ dependency: 'new' })\n\n  test('uses scoped value', ({ dependant }) => {\n    // `dependant` uses the new overridden value that is scoped\n    // to all tests in this suite\n    expect(dependant).toEqual({ dependency: 'new' })\n  })\n})\n```\n\n## test.scoped <Version>3.1.0</Version> <Deprecated /> {#test-scoped}\n\n- **Alias:** `it.scoped`\n\n::: danger DEPRECATED\n`test.scoped` is deprecated in favor of [`test.override`](#test-override) and will be removed in a future major version.\n:::\n\nAlias of [`test.override`](#test-override)\n\n## test.skip\n\n- **Alias:** `it.skip`\n\nIf you want to skip running certain tests, but you don't want to delete the code due to any reason, you can use `test.skip` to avoid running them.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest.skip('skipped test', () => {\n  // Test skipped, no error\n  assert.equal(Math.sqrt(4), 3)\n})\n```\n\nYou can also skip test by calling `skip` on its [context](/guide/test-context) dynamically:\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('skipped test', (context) => {\n  context.skip()\n  // Test skipped, no error\n  assert.equal(Math.sqrt(4), 3)\n})\n```\n\nIf the condition is unknown, you can provide it to the `skip` method as the first arguments:\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest('skipped test', (context) => {\n  context.skip(Math.random() < 0.5, 'optional message')\n  // Test skipped, no error\n  assert.equal(Math.sqrt(4), 3)\n})\n```\n\n## test.skipIf\n\n- **Alias:** `it.skipIf`\n\nIn some cases you might run tests multiple times with different environments, and some of the tests might be environment-specific. Instead of wrapping the test code with `if`, you can use `test.skipIf` to skip the test whenever the condition is truthy.\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst isDev = process.env.NODE_ENV === 'development'\n\ntest.skipIf(isDev)('prod only test', () => {\n  // this test only runs in production\n})\n```\n\n## test.runIf\n\n- **Alias:** `it.runIf`\n\nOpposite of [test.skipIf](#test-skipif).\n\n```ts\nimport { assert, test } from 'vitest'\n\nconst isDev = process.env.NODE_ENV === 'development'\n\ntest.runIf(isDev)('dev only test', () => {\n  // this test only runs in development\n})\n```\n\n## test.only\n\n- **Alias:** `it.only`\n\nUse `test.only` to only run certain tests in a given suite. This is useful when debugging.\n\n```ts\nimport { assert, test } from 'vitest'\n\ntest.only('test', () => {\n  // Only this test (and others marked with only) are run\n  assert.equal(Math.sqrt(4), 2)\n})\n```\n\nSometimes it is very useful to run `only` tests in a certain file, ignoring all other tests from the whole test suite, which pollute the output.\n\nIn order to do that, run `vitest` with specific file containing the tests in question:\n\n```shell\nvitest interesting.test.ts\n```\n\n::: warning\nVitest detects when tests are running in CI and will throw an error if any test has `only` flag. You can configure this behaviour via [`allowOnly`](/config/allowonly) option.\n:::\n\n## test.concurrent\n\n- **Alias:** `it.concurrent`\n\n`test.concurrent` marks consecutive tests to be run in parallel. It receives the test name, an async function with the tests to collect, and an optional timeout (in milliseconds).\n\n```ts\nimport { describe, test } from 'vitest'\n\n// The two tests marked with concurrent will be run in parallel\ndescribe('suite', () => {\n  test('serial test', async () => { /* ... */ })\n  test.concurrent('concurrent test 1', async () => { /* ... */ })\n  test.concurrent('concurrent test 2', async () => { /* ... */ })\n})\n```\n\n`test.skip`, `test.only`, and `test.todo` works with concurrent tests. All the following combinations are valid:\n\n```ts\ntest.concurrent(/* ... */)\ntest.skip.concurrent(/* ... */) // or test.concurrent.skip(/* ... */)\ntest.only.concurrent(/* ... */) // or test.concurrent.only(/* ... */)\ntest.todo.concurrent(/* ... */) // or test.concurrent.todo(/* ... */)\n```\n\nWhen running concurrent tests, Snapshots and Assertions must use `expect` from the local [Test Context](/guide/test-context.md) to ensure the right test is detected.\n\n```ts\ntest.concurrent('test 1', async ({ expect }) => {\n  expect(foo).toMatchSnapshot()\n})\ntest.concurrent('test 2', async ({ expect }) => {\n  expect(foo).toMatchSnapshot()\n})\n```\n\nNote that if tests are synchronous, Vitest will still run them sequentially.\n\n## test.sequential\n\n- **Alias:** `it.sequential`\n\n`test.sequential` marks a test as sequential. This is useful if you want to run tests in sequence within `describe.concurrent` or with the `--sequence.concurrent` command option.\n\n```ts\nimport { describe, test } from 'vitest'\n\n// with config option { sequence: { concurrent: true } }\ntest('concurrent test 1', async () => { /* ... */ })\ntest('concurrent test 2', async () => { /* ... */ })\n\ntest.sequential('sequential test 1', async () => { /* ... */ })\ntest.sequential('sequential test 2', async () => { /* ... */ })\n\n// within concurrent suite\ndescribe.concurrent('suite', () => {\n  test('concurrent test 1', async () => { /* ... */ })\n  test('concurrent test 2', async () => { /* ... */ })\n\n  test.sequential('sequential test 1', async () => { /* ... */ })\n  test.sequential('sequential test 2', async () => { /* ... */ })\n})\n```\n\n## test.todo\n\n- **Alias:** `it.todo`\n\nUse `test.todo` to stub tests to be implemented later. An entry will be shown in the report for the tests so you know how many tests you still need to implement.\n\n```ts\n// An entry will be shown in the report for this test\ntest.todo('unimplemented test', () => {\n  // failing implementation...\n})\n```\n\n::: tip\nVitest will automatically mark test as `todo` if test has no body.\n:::\n\n## test.fails\n\n- **Alias:** `it.fails`\n\nUse `test.fails` to indicate that an assertion will fail explicitly.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest.fails('repro #1234', () => {\n  expect(add(1, 2)).toBe(4)\n})\n```\n\nThis flag is useful to track difference in behaviour of your library over time. For example, you can define a failing test without fixing the issue yet due to time constraints. Tests marked with `fails` are tracked in the test summary since Vitest 4.1.\n\n## test.each\n\n- **Alias:** `it.each`\n\n::: tip\nWhile `test.each` is provided for Jest compatibility,\nVitest also has [`test.for`](#test-for) with an additional feature to integrate [`TestContext`](/guide/test-context).\n:::\n\nUse `test.each` when you need to run the same test with different variables.\nYou can inject parameters with [printf formatting](https://nodejs.org/api/util.html#util_util_format_format_args) in the test name in the order of the test function parameters.\n\n- `%s`: string\n- `%d`: number\n- `%i`: integer\n- `%f`: floating point value\n- `%j`: json\n- `%o`: object\n- `%#`: 0-based index of the test case\n- `%$`: 1-based index of the test case\n- `%%`: single percent sign ('%')\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('add(%i, %i) -> %i', (a, b, expected) => {\n  expect(a + b).toBe(expected)\n})\n\n// this will return\n// ✓ add(1, 1) -> 2\n// ✓ add(1, 2) -> 3\n// ✓ add(2, 1) -> 3\n```\n\nYou can also access object properties and array elements with `$` prefix:\n\n```ts\ntest.each([\n  { a: 1, b: 1, expected: 2 },\n  { a: 1, b: 2, expected: 3 },\n  { a: 2, b: 1, expected: 3 },\n])('add($a, $b) -> $expected', ({ a, b, expected }) => {\n  expect(a + b).toBe(expected)\n})\n\n// this will return\n// ✓ add(1, 1) -> 2\n// ✓ add(1, 2) -> 3\n// ✓ add(2, 1) -> 3\n\ntest.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('add($0, $1) -> $2', (a, b, expected) => {\n  expect(a + b).toBe(expected)\n})\n\n// this will return\n// ✓ add(1, 1) -> 2\n// ✓ add(1, 2) -> 3\n// ✓ add(2, 1) -> 3\n```\n\nYou can also access Object attributes with `.`, if you are using objects as arguments:\n\n  ```ts\n  test.each`\n  a               | b      | expected\n  ${{ val: 1 }}   | ${'b'} | ${'1b'}\n  ${{ val: 2 }}   | ${'b'} | ${'2b'}\n  ${{ val: 3 }}   | ${'b'} | ${'3b'}\n  `('add($a.val, $b) -> $expected', ({ a, b, expected }) => {\n    expect(a.val + b).toBe(expected)\n  })\n\n  // this will return\n  // ✓ add(1, b) -> 1b\n  // ✓ add(2, b) -> 2b\n  // ✓ add(3, b) -> 3b\n  ```\n\n* First row should be column names, separated by `|`;\n* One or more subsequent rows of data supplied as template literal expressions using `${value}` syntax.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest.each`\n  a               | b      | expected\n  ${1}            | ${1}   | ${2}\n  ${'a'}          | ${'b'} | ${'ab'}\n  ${[]}           | ${'b'} | ${'b'}\n  ${{}}           | ${'b'} | ${'[object Object]b'}\n  ${{ asd: 1 }}   | ${'b'} | ${'[object Object]b'}\n`('returns $expected when $a is added $b', ({ a, b, expected }) => {\n  expect(a + b).toBe(expected)\n})\n```\n\n::: tip\nVitest processes `$values` with Chai `format` method. If the value is too truncated, you can increase [chaiConfig.truncateThreshold](/config/chaiconfig#chaiconfig-truncatethreshold) in your config file.\n:::\n\n## test.for\n\n- **Alias:** `it.for`\n\nAlternative to `test.each` to provide [`TestContext`](/guide/test-context).\n\nThe difference from `test.each` lies in how arrays are provided in the arguments.\nNon-array arguments to `test.for` (including template string usage) work exactly the same as for `test.each`.\n\n```ts\n// `each` spreads arrays\ntest.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('add(%i, %i) -> %i', (a, b, expected) => { // [!code --]\n  expect(a + b).toBe(expected)\n})\n\n// `for` doesn't spread arrays (notice the square brackets around the arguments)\ntest.for([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('add(%i, %i) -> %i', ([a, b, expected]) => { // [!code ++]\n  expect(a + b).toBe(expected)\n})\n```\n\nThe 2nd argument is [`TestContext`](/guide/test-context) and can be used for concurrent snapshots, for example:\n\n```ts\ntest.concurrent.for([\n  [1, 1],\n  [1, 2],\n  [2, 1],\n])('add(%i, %i)', ([a, b], { expect }) => {\n  expect(a + b).toMatchSnapshot()\n})\n```\n\n## test.describe <Version>4.1.0</Version> {#test-describe}\n\nScoped `describe`. See [describe](/api/describe) for more information.\n\n## test.suite <Version>4.1.0</Version> {#test-suite}\n\nAlias for `suite`. See [describe](/api/describe) for more information.\n\n## test.beforeEach\n\nScoped `beforeEach` hook that inherits types from [`test.extend`](#test-extend). See [beforeEach](/api/hooks#beforeeach) for more information.\n\n## test.afterEach\n\nScoped `afterEach` hook that inherits types from [`test.extend`](#test-extend). See [afterEach](/api/hooks#aftereach) for more information.\n\n## test.beforeAll\n\nScoped `beforeAll` hook that inherits types from [`test.extend`](#test-extend). See [beforeAll](/api/hooks#beforeall) for more information.\n\n## test.afterAll\n\nScoped `afterAll` hook that inherits types from [`test.extend`](#test-extend). See [afterAll](/api/hooks#afterall) for more information.\n\n## test.aroundEach <Version>4.1.0</Version> {#test-aroundeach}\n\nScoped `aroundEach` hook that inherits types from [`test.extend`](#test-extend). See [aroundEach](/api/hooks#aroundeach) for more information.\n\n## test.aroundAll <Version>4.1.0</Version> {#test-aroundall}\n\nScoped `aroundAll` hook that inherits types from [`test.extend`](#test-extend). See [aroundAll](/api/hooks#aroundall) for more information.\n\n## bench <Experimental /> {#bench}\n\n- **Type:** `(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void`\n\n::: danger\nBenchmarking is experimental and does not follow SemVer.\n:::\n\n`bench` defines a benchmark. In Vitest terms, benchmark is a function that defines a series of operations. Vitest runs this function multiple times to display different performance results.\n\nVitest uses the [`tinybench`](https://github.com/tinylibs/tinybench) library under the hood, inheriting all its options that can be used as a third argument.\n\n```ts\nimport { bench } from 'vitest'\n\nbench('normal sorting', () => {\n  const x = [1, 5, 4, 2, 3]\n  x.sort((a, b) => {\n    return a - b\n  })\n}, { time: 1000 })\n```\n\n```ts\nexport interface Options {\n  /**\n   * time needed for running a benchmark task (milliseconds)\n   * @default 500\n   */\n  time?: number\n\n  /**\n   * number of times that a task should run if even the time option is finished\n   * @default 10\n   */\n  iterations?: number\n\n  /**\n   * function to get the current timestamp in milliseconds\n   */\n  now?: () => number\n\n  /**\n   * An AbortSignal for aborting the benchmark\n   */\n  signal?: AbortSignal\n\n  /**\n   * Throw if a task fails (events will not work if true)\n   */\n  throws?: boolean\n\n  /**\n   * warmup time (milliseconds)\n   * @default 100ms\n   */\n  warmupTime?: number\n\n  /**\n   * warmup iterations\n   * @default 5\n   */\n  warmupIterations?: number\n\n  /**\n   * setup function to run before each benchmark task (cycle)\n   */\n  setup?: Hook\n\n  /**\n   * teardown function to run after each benchmark task (cycle)\n   */\n  teardown?: Hook\n}\n```\nAfter the test case is run, the output structure information is as follows:\n\n```\n  name                      hz     min     max    mean     p75     p99    p995    p999     rme  samples\n· normal sorting  6,526,368.12  0.0001  0.3638  0.0002  0.0002  0.0002  0.0002  0.0004  ±1.41%   652638\n```\n```ts\nexport interface TaskResult {\n  /*\n   * the last error that was thrown while running the task\n   */\n  error?: unknown\n\n  /**\n   * The amount of time in milliseconds to run the benchmark task (cycle).\n   */\n  totalTime: number\n\n  /**\n   * the minimum value in the samples\n   */\n  min: number\n  /**\n   * the maximum value in the samples\n   */\n  max: number\n\n  /**\n   * the number of operations per second\n   */\n  hz: number\n\n  /**\n   * how long each operation takes (ms)\n   */\n  period: number\n\n  /**\n   * task samples of each task iteration time (ms)\n   */\n  samples: number[]\n\n  /**\n   * samples mean/average (estimate of the population mean)\n   */\n  mean: number\n\n  /**\n   * samples variance (estimate of the population variance)\n   */\n  variance: number\n\n  /**\n   * samples standard deviation (estimate of the population standard deviation)\n   */\n  sd: number\n\n  /**\n   * standard error of the mean (a.k.a. the standard deviation of the sampling distribution of the sample mean)\n   */\n  sem: number\n\n  /**\n   * degrees of freedom\n   */\n  df: number\n\n  /**\n   * critical value of the samples\n   */\n  critical: number\n\n  /**\n   * margin of error\n   */\n  moe: number\n\n  /**\n   * relative margin of error\n   */\n  rme: number\n\n  /**\n   * median absolute deviation\n   */\n  mad: number\n\n  /**\n   * p50/median percentile\n   */\n  p50: number\n\n  /**\n   * p75 percentile\n   */\n  p75: number\n\n  /**\n   * p99 percentile\n   */\n  p99: number\n\n  /**\n   * p995 percentile\n   */\n  p995: number\n\n  /**\n   * p999 percentile\n   */\n  p999: number\n}\n```\n\n### bench.skip\n\n- **Type:** `(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void`\n\nYou can use `bench.skip` syntax to skip running certain benchmarks.\n\n```ts\nimport { bench } from 'vitest'\n\nbench.skip('normal sorting', () => {\n  const x = [1, 5, 4, 2, 3]\n  x.sort((a, b) => {\n    return a - b\n  })\n})\n```\n\n### bench.only\n\n- **Type:** `(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void`\n\nUse `bench.only` to only run certain benchmarks in a given suite. This is useful when debugging.\n\n```ts\nimport { bench } from 'vitest'\n\nbench.only('normal sorting', () => {\n  const x = [1, 5, 4, 2, 3]\n  x.sort((a, b) => {\n    return a - b\n  })\n})\n```\n\n### bench.todo\n\n- **Type:** `(name: string | Function) => void`\n\nUse `bench.todo` to stub benchmarks to be implemented later.\n\n```ts\nimport { bench } from 'vitest'\n\nbench.todo('unimplemented test')\n```\n"
  },
  {
    "path": "docs/api/vi.md",
    "content": "---\noutline: deep\n---\n\n# Vi\n\nVitest provides utility functions to help you out through its `vi` helper. You can access it globally (when [globals configuration](/config/globals) is enabled), or import it from `vitest` directly:\n\n```js\nimport { vi } from 'vitest'\n```\n\n## Mock Modules\n\nThis section describes the API that you can use when [mocking a module](/guide/mocking/modules). Beware that Vitest doesn't support mocking modules imported using `require()`.\n\n### vi.mock\n\n```ts\ninterface MockOptions {\n  spy?: boolean\n}\n\ninterface MockFactory<T> {\n  (importOriginal: () => T): unknown\n}\n\nfunction mock(\n  path: string,\n  factory?: MockOptions | MockFactory<unknown>\n): void\nfunction mock<T>(\n  module: Promise<T>,\n  factory?: MockOptions | MockFactory<T>\n): void\n```\n\nSubstitutes all imported modules from provided `path` with another module. You can use configured Vite aliases inside a path. The call to `vi.mock` is hoisted, so it doesn't matter where you call it. It will always be executed before all imports. If you need to reference some variables outside of its scope, you can define them inside [`vi.hoisted`](#vi-hoisted) and reference them inside `vi.mock`.\n\nIt is recommended to use `vi.mock` or `vi.hoisted` only inside test files. If Vite's [module runner](/config/experimental#experimental-vitemodulerunner) is disabled, they will not be hoisted. This is a performance optimisation to avoid ready unnecessary files.\n\n::: warning\n`vi.mock` works only for modules that were imported with the `import` keyword. It doesn't work with `require`.\n\nIn order to hoist `vi.mock`, Vitest statically analyzes your files. It indicates that `vi` that was not directly imported from the `vitest` package (for example, from some utility file) cannot be used. Use `vi.mock` with `vi` imported from `vitest`, or enable [`globals`](/config/globals) config option.\n\nVitest will not mock modules that were imported inside a [setup file](/config/setupfiles) because they are cached by the time a test file is running. You can call [`vi.resetModules()`](#vi-resetmodules) inside [`vi.hoisted`](#vi-hoisted) to clear all module caches before running a test file.\n:::\n\nIf the `factory` function is defined, all imports will return its result. Vitest calls factory only once and caches results for all subsequent imports until [`vi.unmock`](#vi-unmock) or [`vi.doUnmock`](#vi-dounmock) is called.\n\nUnlike in `jest`, the factory can be asynchronous. You can use [`vi.importActual`](#vi-importactual) or a helper with the factory passed in as the first argument, and get the original module inside.\n\nYou can also provide an object with a `spy` property instead of a factory function. If `spy` is `true`, then Vitest will automock the module as usual, but it won't override the implementation of exports. This is useful if you just want to assert that the exported method was called correctly by another method.\n\n```ts\nimport { calculator } from './src/calculator.ts'\n\nvi.mock('./src/calculator.ts', { spy: true })\n\n// calls the original implementation,\n// but allows asserting the behaviour later\nconst result = calculator(1, 2)\n\nexpect(result).toBe(3)\nexpect(calculator).toHaveBeenCalledWith(1, 2)\nexpect(calculator).toHaveReturnedWith(3)\n```\n\nVitest also supports a module promise instead of a string in the `vi.mock` and `vi.doMock` methods for better IDE support. When the file is moved, the path will be updated, and `importOriginal` inherits the type automatically. Using this signature will also enforce factory return type to be compatible with the original module (keeping exports optional).\n\n```ts twoslash\n// @filename: ./path/to/module.js\nexport declare function total(...numbers: number[]): number\n// @filename: test.js\nimport { vi } from 'vitest'\n// ---cut---\nvi.mock(import('./path/to/module.js'), async (importOriginal) => {\n  const mod = await importOriginal() // type is inferred\n  //    ^?\n  return {\n    ...mod,\n    // replace some exports\n    total: vi.fn(),\n  }\n})\n```\n\nUnder the hood, Vitest still operates on a string and not a module object.\n\nIf you are using TypeScript with `paths` aliases configured in `tsconfig.json` however, the compiler won't be able to correctly resolve import types.\nIn order to make it work, make sure to replace all aliased imports, with their corresponding relative paths.\nEg. use `import('./path/to/module.js')` instead of `import('@/module')`.\n\n::: warning\n`vi.mock` is hoisted (in other words, _moved_) to **top of the file**. It means that whenever you write it (be it inside `beforeEach` or `test`), it will actually be called before that.\n\nThis also means that you cannot use any variables inside the factory that are defined outside the factory.\n\nIf you need to use variables inside the factory, try [`vi.doMock`](#vi-domock). It works the same way but isn't hoisted. Beware that it only mocks subsequent imports.\n\nYou can also reference variables defined by `vi.hoisted` method if it was declared before `vi.mock`:\n\n```ts\nimport { namedExport } from './path/to/module.js'\n\nconst mocks = vi.hoisted(() => {\n  return {\n    namedExport: vi.fn(),\n  }\n})\n\nvi.mock('./path/to/module.js', () => {\n  return {\n    namedExport: mocks.namedExport,\n  }\n})\n\nvi.mocked(namedExport).mockReturnValue(100)\n\nexpect(namedExport()).toBe(100)\nexpect(namedExport).toBe(mocks.namedExport)\n```\n:::\n\n::: warning\nIf you are mocking a module with default export, you will need to provide a `default` key within the returned factory function object. This is an ES module-specific caveat; therefore, `jest` documentation may differ as `jest` uses CommonJS modules. For example,\n\n```ts\nvi.mock('./path/to/module.js', () => {\n  return {\n    default: { myDefaultKey: vi.fn() },\n    namedExport: vi.fn(),\n    // etc...\n  }\n})\n```\n:::\n\nIf there is a `__mocks__` folder alongside a file that you are mocking, and the factory is not provided, Vitest will try to find a file with the same name in the `__mocks__` subfolder and use it as an actual module. If you are mocking a dependency, Vitest will try to find a `__mocks__` folder in the [root](/config/root) of the project (default is `process.cwd()`). You can tell Vitest where the dependencies are located through the [`deps.moduleDirectories`](/config/deps#deps-moduledirectories) config option.\n\nFor example, you have this file structure:\n\n```\n- __mocks__\n  - axios.js\n- src\n  __mocks__\n    - increment.js\n  - increment.js\n- tests\n  - increment.test.js\n```\n\nIf you call `vi.mock` in a test file without a factory or options provided, it will find a file in the `__mocks__` folder to use as a module:\n\n```ts [increment.test.js]\nimport { vi } from 'vitest'\n\n// axios is a default export from `__mocks__/axios.js`\nimport axios from 'axios'\n\n// increment is a named export from `src/__mocks__/increment.js`\nimport { increment } from '../increment.js'\n\nvi.mock('axios')\nvi.mock('../increment.js')\n\naxios.get(`/apples/${increment(1)}`)\n```\n\n::: warning\nBeware that if you don't call `vi.mock`, modules **are not** mocked automatically. To replicate Jest's automocking behaviour, you can call `vi.mock` for each required module inside [`setupFiles`](/config/setupfiles).\n:::\n\nIf there is no `__mocks__` folder or a factory provided, Vitest will import the original module and auto-mock all its exports. For the rules applied, see [algorithm](/guide/mocking/modules#automocking-algorithm).\n\n### vi.doMock\n\n```ts\nfunction doMock(\n  path: string,\n  factory?: MockOptions | MockFactory<unknown>\n): Disposable\nfunction doMock<T>(\n  module: Promise<T>,\n  factory?: MockOptions | MockFactory<T>\n): Disposable\n```\n\nThe same as [`vi.mock`](#vi-mock), but it's not hoisted to the top of the file, so you can reference variables in the global file scope. The next [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) of the module will be mocked.\n\n::: warning\nThis will not mock modules that were imported before this was called. Don't forget that all static imports in ESM are always [hoisted](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#hoisting), so putting this before static import will not force it to be called before the import:\n\n```ts\nvi.doMock('./increment.js') // this will be called _after_ the import statement\n\nimport { increment } from './increment.js'\n```\n:::\n\n```ts [increment.js]\nexport function increment(number) {\n  return number + 1\n}\n```\n\n```ts [increment.test.js]\nimport { beforeEach, test } from 'vitest'\nimport { increment } from './increment.js'\n\n// the module is not mocked, because vi.doMock is not called yet\nincrement(1) === 2\n\nlet mockedIncrement = 100\n\nbeforeEach(() => {\n  // you can access variables inside a factory\n  vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }))\n})\n\ntest('importing the next module imports mocked one', async () => {\n  // original import WAS NOT MOCKED, because vi.doMock is evaluated AFTER imports\n  expect(increment(1)).toBe(2)\n  const { increment: mockedIncrement } = await import('./increment.js')\n  // new dynamic import returns mocked module\n  expect(mockedIncrement(1)).toBe(101)\n  expect(mockedIncrement(1)).toBe(102)\n  expect(mockedIncrement(1)).toBe(103)\n})\n```\n\n::: tip\nIn environments that support [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management), you can use `using` on the value returned from `vi.doMock()` to automatically call [`vi.doUnmock()`](#vi-dounmock) on the mocked module when the containing block is exited. This is especially useful when mocking a dynamically imported module for a single test case.\n\n```ts\nit('uses a mocked version of my-module', () => {\n  using _mockDisposable = vi.doMock('my-module')\n\n  const myModule = await import('my-module') // mocked\n\n  // my-module is restored here\n})\n\nit('uses the normal version of my-module again', () => {\n  const myModule = await import('my-module') // not mocked\n})\n```\n:::\n\n### vi.mocked\n\n```ts\nfunction mocked<T>(\n  object: T,\n  deep?: boolean\n): MaybeMockedDeep<T>\nfunction mocked<T>(\n  object: T,\n  options?: { partial?: boolean; deep?: boolean }\n): MaybePartiallyMockedDeep<T>\n```\n\nType helper for TypeScript. Just returns the object that was passed.\n\nWhen `partial` is `true` it will expect a `Partial<T>` as a return value. By default, this will only make TypeScript believe that the first level values are mocked. You can pass down `{ deep: true }` as a second argument to tell TypeScript that the whole object is mocked, if it actually is. You can pass down `{ partial: true, deep: true }` to make nested objects also partial recursively.\n\n```ts [example.ts]\nexport function add(x: number, y: number): number {\n  return x + y\n}\n\nexport function fetchSomething(): Promise<Response> {\n  return fetch('https://vitest.dev/')\n}\n\nexport function getUser(): { name: string; address: { city: string; zip: string } } {\n  return { name: 'John', address: { city: 'New York', zip: '10001' } }\n}\n```\n\n```ts [example.test.ts]\nimport * as example from './example'\n\nvi.mock('./example')\n\ntest('1 + 1 equals 10', async () => {\n  vi.mocked(example.add).mockReturnValue(10)\n  expect(example.add(1, 1)).toBe(10)\n})\n\ntest('mock return value with only partially correct typing', async () => {\n  vi.mocked(example.fetchSomething).mockResolvedValue(new Response('hello'))\n  vi.mocked(example.fetchSomething, { partial: true }).mockResolvedValue({ ok: false })\n  // vi.mocked(example.someFn).mockResolvedValue({ ok: false }) // this is a type error\n})\n\ntest('mock return value with deep partial typing', async () => {\n  vi.mocked(example.getUser, { partial: true, deep: true }).mockReturnValue({\n    address: { city: 'Los Angeles' },\n  })\n  expect(example.getUser().address.city).toBe('Los Angeles')\n})\n```\n\n### vi.importActual\n\n```ts\nfunction importActual<T>(path: string): Promise<T>\n```\n\nImports module, bypassing all checks if it should be mocked. Can be useful if you want to mock module partially.\n\n```ts\nvi.mock('./example.js', async () => {\n  const originalModule = await vi.importActual('./example.js')\n\n  return { ...originalModule, get: vi.fn() }\n})\n```\n\n### vi.importMock\n\n```ts\nfunction importMock<T>(path: string): Promise<MaybeMockedDeep<T>>\n```\n\nImports a module with all of its properties (including nested properties) mocked. Follows the same rules that [`vi.mock`](#vi-mock) does. For the rules applied, see [algorithm](/guide/mocking/modules#automocking-algorithm).\n\n### vi.unmock\n\n```ts\nfunction unmock(path: string | Promise<Module>): void\n```\n\nRemoves module from the mocked registry. All calls to import will return the original module even if it was mocked before. This call is hoisted to the top of the file, so it will only unmock modules that were defined in `setupFiles`, for example.\n\n### vi.doUnmock\n\n```ts\nfunction doUnmock(path: string | Promise<Module>): void\n```\n\nThe same as [`vi.unmock`](#vi-unmock), but is not hoisted to the top of the file. The next import of the module will import the original module instead of the mock. This will not unmock previously imported modules.\n\n```ts [increment.js]\nexport function increment(number) {\n  return number + 1\n}\n```\n\n```ts [increment.test.js]\nimport { increment } from './increment.js'\n\n// increment is already mocked, because vi.mock is hoisted\nincrement(1) === 100\n\n// this is hoisted, and factory is called before the import on line 1\nvi.mock('./increment.js', () => ({ increment: () => 100 }))\n\n// all calls are mocked, and `increment` always returns 100\nincrement(1) === 100\nincrement(30) === 100\n\n// this is not hoisted, so other import will return unmocked module\nvi.doUnmock('./increment.js')\n\n// this STILL returns 100, because `vi.doUnmock` doesn't reevaluate a module\nincrement(1) === 100\nincrement(30) === 100\n\n// the next import is unmocked, now `increment` is the original function that returns count + 1\nconst { increment: unmockedIncrement } = await import('./increment.js')\n\nunmockedIncrement(1) === 2\nunmockedIncrement(30) === 31\n```\n\n### vi.resetModules\n\n```ts\nfunction resetModules(): Vitest\n```\n\nResets modules registry by clearing the cache of all modules. This allows modules to be reevaluated when reimported. Top-level imports cannot be re-evaluated. Might be useful to isolate modules where local state conflicts between tests.\n\n```ts\nimport { vi } from 'vitest'\n\nimport { data } from './data.js' // Will not get reevaluated beforeEach test\n\nbeforeEach(() => {\n  vi.resetModules()\n})\n\ntest('change state', async () => {\n  const mod = await import('./some/path.js') // Will get reevaluated\n  mod.changeLocalState('new value')\n  expect(mod.getLocalState()).toBe('new value')\n})\n\ntest('module has old state', async () => {\n  const mod = await import('./some/path.js') // Will get reevaluated\n  expect(mod.getLocalState()).toBe('old value')\n})\n```\n\n::: warning\nDoes not reset mocks registry. To clear mocks registry, use [`vi.unmock`](#vi-unmock) or [`vi.doUnmock`](#vi-dounmock).\n:::\n\n### vi.dynamicImportSettled\n\n```ts\nfunction dynamicImportSettled(): Promise<void>\n```\n\nWait for all imports to load. Useful, if you have a synchronous call that starts importing a module that you cannot wait otherwise.\n\n```ts\nimport { expect, test } from 'vitest'\n\n// cannot track import because Promise is not returned\nfunction renderComponent() {\n  import('./component.js').then(({ render }) => {\n    render()\n  })\n}\n\ntest('operations are resolved', async () => {\n  renderComponent()\n  await vi.dynamicImportSettled()\n  expect(document.querySelector('.component')).not.toBeNull()\n})\n```\n\n::: tip\nIf during a dynamic import another dynamic import is initiated, this method will wait until all of them are resolved.\n\nThis method will also wait for the next `setTimeout` tick after the import is resolved so all synchronous operations should be completed by the time it's resolved.\n:::\n\n## Mocking Functions and Objects\n\nThis section describes how to work with [method mocks](/api/mock) and replace environmental and global variables.\n\n### vi.fn\n\n```ts\nfunction fn(fn?: Procedure | Constructable): Mock\n```\n\nCreates a spy on a function, but can also be initiated without one. Every time a function is invoked, it stores its call arguments, returns, and instances. Additionally, you can manipulate its behavior with [methods](/api/mock).\nIf no function is given, mock will return `undefined` when invoked.\n\n```ts\nconst getApples = vi.fn(() => 0)\n\ngetApples()\n\nexpect(getApples).toHaveBeenCalled()\nexpect(getApples).toHaveReturnedWith(0)\n\ngetApples.mockReturnValueOnce(5)\n\nconst res = getApples()\nexpect(res).toBe(5)\nexpect(getApples).toHaveNthReturnedWith(2, 5)\n```\n\nYou can also pass down a class to `vi.fn`:\n\n```ts\nconst Cart = vi.fn(class {\n  get = () => 0\n})\n\nconst cart = new Cart()\nexpect(Cart).toHaveBeenCalled()\n```\n\n### vi.mockObject <Version>3.2.0</Version>\n\n```ts\nfunction mockObject<T>(value: T, options?: MockOptions): MaybeMockedDeep<T>\n```\n\nDeeply mocks properties and methods of a given object in the same way as `vi.mock()` mocks module exports. See [automocking](/guide/mocking.html#automocking-algorithm) for the detail.\n\n```ts\nconst original = {\n  simple: () => 'value',\n  nested: {\n    method: () => 'real'\n  },\n  prop: 'foo',\n}\n\nconst mocked = vi.mockObject(original)\nexpect(mocked.simple()).toBe(undefined)\nexpect(mocked.nested.method()).toBe(undefined)\nexpect(mocked.prop).toBe('foo')\n\nmocked.simple.mockReturnValue('mocked')\nmocked.nested.method.mockReturnValue('mocked nested')\n\nexpect(mocked.simple()).toBe('mocked')\nexpect(mocked.nested.method()).toBe('mocked nested')\n```\n\nJust like `vi.mock()`, you can pass `{ spy: true }` as a second argument to keep function implementations:\n\n```ts\nconst spied = vi.mockObject(original, { spy: true })\nexpect(spied.simple()).toBe('value')\nexpect(spied.simple).toHaveBeenCalled()\nexpect(spied.simple.mock.results[0]).toEqual({ type: 'return', value: 'value' })\n```\n\n### vi.isMockFunction\n\n```ts\nfunction isMockFunction(fn: unknown): asserts fn is Mock\n```\n\nChecks that a given parameter is a mock function. If you are using TypeScript, it will also narrow down its type.\n\n### vi.clearAllMocks\n\n```ts\nfunction clearAllMocks(): Vitest\n```\n\nCalls [`.mockClear()`](/api/mock#mockclear) on all spies.\nThis will clear mock history without affecting mock implementations.\n\n### vi.resetAllMocks\n\n```ts\nfunction resetAllMocks(): Vitest\n```\n\nCalls [`.mockReset()`](/api/mock#mockreset) on all spies.\nThis will clear mock history and reset each mock's implementation.\n\n### vi.restoreAllMocks\n\n```ts\nfunction restoreAllMocks(): Vitest\n```\n\nThis restores all original implementations on spies created with [`vi.spyOn`](#vi-spyon).\n\nAfter the mock was restored, you can spy on it again.\n\n::: warning\nThis method also does not affect mocks created during [automocking](/guide/mocking/modules#mocking-a-module).\n\nNote that unlike [`mock.mockRestore`](/api/mock#mockrestore), `vi.restoreAllMocks` will not clear mock history or reset the mock implementation\n:::\n\n### vi.spyOn\n\n```ts\nfunction spyOn<T, K extends keyof T>(\n  object: T,\n  key: K,\n  accessor?: 'get' | 'set'\n): Mock<T[K]>\n```\n\nCreates a spy on a method or getter/setter of an object similar to [`vi.fn()`](#vi-fn). It returns a [mock function](/api/mock).\n\n```ts\nlet apples = 0\nconst cart = {\n  getApples: () => 42,\n}\n\nconst spy = vi.spyOn(cart, 'getApples').mockImplementation(() => apples)\napples = 1\n\nexpect(cart.getApples()).toBe(1)\n\nexpect(spy).toHaveBeenCalled()\nexpect(spy).toHaveReturnedWith(1)\n```\n\nIf the spying method is a class definition, the mock implementations have to use the `function` or the `class` keyword:\n\n```ts {12-14,16-20}\nconst cart = {\n  Apples: class Apples {\n    getApples() {\n      return 42\n    }\n  }\n}\n\nconst spy = vi.spyOn(cart, 'Apples')\n  .mockImplementation(() => ({ getApples: () => 0 })) // [!code --]\n  // with a function keyword\n  .mockImplementation(function () {\n    this.getApples = () => 0\n  })\n  // with a custom class\n  .mockImplementation(class MockApples {\n    getApples() {\n      return 0\n    }\n  })\n```\n\nIf you provide an arrow function, you will get [`<anonymous> is not a constructor` error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_a_constructor) when the mock is called.\n\n::: tip\nIn environments that support [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management), you can use `using` instead of `const` to automatically call `mockRestore` on any mocked function when the containing block is exited. This is especially useful for spied methods:\n\n```ts\nit('calls console.log', () => {\n  using spy = vi.spyOn(console, 'log').mockImplementation(() => {})\n  debug('message')\n  expect(spy).toHaveBeenCalled()\n})\n// console.log is restored here\n```\n:::\n\n::: tip\nYou can call [`vi.restoreAllMocks`](#vi-restoreallmocks) inside [`afterEach`](/api/hooks#aftereach) (or enable [`test.restoreMocks`](/config/restoremocks)) to restore all methods to their original implementations after every test. This will restore the original [object descriptor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty), so you won't be able to change method's implementation anymore, unless you spy again:\n\n```ts\nconst cart = {\n  getApples: () => 42,\n}\n\nconst spy = vi.spyOn(cart, 'getApples').mockReturnValue(10)\n\nconsole.log(cart.getApples()) // 10\nvi.restoreAllMocks()\nconsole.log(cart.getApples()) // 42\nspy.mockReturnValue(10)\nconsole.log(cart.getApples()) // still 42!\n```\n:::\n\n::: tip\nIt is not possible to spy on exported methods in [Browser Mode](/guide/browser/). Instead, you can spy on every exported method by calling `vi.mock(\"./file-path.js\", { spy: true })`. This will mock every export but keep its implementation intact, allowing you to assert if the method was called correctly.\n\n```ts\nimport { calculator } from './src/calculator.ts'\n\nvi.mock('./src/calculator.ts', { spy: true })\n\ncalculator(1, 2)\n\nexpect(calculator).toHaveBeenCalledWith(1, 2)\nexpect(calculator).toHaveReturned(3)\n```\n\nAnd while it is possible to spy on exports in `jsdom` or other Node.js environments, this might change in the future.\n:::\n\n### vi.stubEnv {#vi-stubenv}\n\n```ts\nfunction stubEnv<T extends string>(\n  name: T,\n  value: T extends 'PROD' | 'DEV' | 'SSR' ? boolean : string | undefined\n): Vitest\n```\n\nChanges the value of environmental variable on `process.env` and `import.meta.env`. You can restore its value by calling `vi.unstubAllEnvs`.\n\n```ts\nimport { vi } from 'vitest'\n\n// `process.env.NODE_ENV` and `import.meta.env.NODE_ENV`\n// are \"development\" before calling \"vi.stubEnv\"\n\nvi.stubEnv('NODE_ENV', 'production')\n\nprocess.env.NODE_ENV === 'production'\nimport.meta.env.NODE_ENV === 'production'\n\nvi.stubEnv('NODE_ENV', undefined)\n\nprocess.env.NODE_ENV === undefined\nimport.meta.env.NODE_ENV === undefined\n\n// doesn't change other envs\nimport.meta.env.MODE === 'development'\n```\n\n:::tip\nYou can also change the value by simply assigning it, but you won't be able to use `vi.unstubAllEnvs` to restore previous value:\n\n```ts\nimport.meta.env.MODE = 'test'\n```\n:::\n\n### vi.unstubAllEnvs {#vi-unstuballenvs}\n\n```ts\nfunction unstubAllEnvs(): Vitest\n```\n\nRestores all `import.meta.env` and `process.env` values that were changed with `vi.stubEnv`. When it's called for the first time, Vitest remembers the original value and will store it, until `unstubAllEnvs` is called again.\n\n```ts\nimport { vi } from 'vitest'\n\n// `process.env.NODE_ENV` and `import.meta.env.NODE_ENV`\n// are \"development\" before calling stubEnv\n\nvi.stubEnv('NODE_ENV', 'production')\n\nprocess.env.NODE_ENV === 'production'\nimport.meta.env.NODE_ENV === 'production'\n\nvi.stubEnv('NODE_ENV', 'staging')\n\nprocess.env.NODE_ENV === 'staging'\nimport.meta.env.NODE_ENV === 'staging'\n\nvi.unstubAllEnvs()\n\n// restores to the value that were stored before the first \"stubEnv\" call\nprocess.env.NODE_ENV === 'development'\nimport.meta.env.NODE_ENV === 'development'\n```\n\n### vi.stubGlobal\n\n```ts\nfunction stubGlobal(\n  name: string | number | symbol,\n  value: unknown\n): Vitest\n```\n\nChanges the value of global variable. You can restore its original value by calling `vi.unstubAllGlobals`.\n\n```ts\nimport { vi } from 'vitest'\n\n// `innerWidth` is \"0\" before calling stubGlobal\n\nvi.stubGlobal('innerWidth', 100)\n\ninnerWidth === 100\nglobalThis.innerWidth === 100\n// if you are using jsdom or happy-dom\nwindow.innerWidth === 100\n```\n\n:::tip\nYou can also change the value by simply assigning it to `globalThis` or `window` (if you are using `jsdom` or `happy-dom` environment), but you won't be able to use `vi.unstubAllGlobals` to restore original value:\n\n```ts\nglobalThis.innerWidth = 100\n// if you are using jsdom or happy-dom\nwindow.innerWidth = 100\n```\n:::\n\n### vi.unstubAllGlobals {#vi-unstuballglobals}\n\n```ts\nfunction unstubAllGlobals(): Vitest\n```\n\nRestores all global values on `globalThis`/`global` (and `window`/`top`/`self`/`parent`, if you are using `jsdom` or `happy-dom` environment) that were changed with `vi.stubGlobal`. When it's called for the first time, Vitest remembers the original value and will store it, until `unstubAllGlobals` is called again.\n\n```ts\nimport { vi } from 'vitest'\n\nconst Mock = vi.fn()\n\n// IntersectionObserver is \"undefined\" before calling \"stubGlobal\"\n\nvi.stubGlobal('IntersectionObserver', Mock)\n\nIntersectionObserver === Mock\nglobal.IntersectionObserver === Mock\nglobalThis.IntersectionObserver === Mock\n// if you are using jsdom or happy-dom\nwindow.IntersectionObserver === Mock\n\nvi.unstubAllGlobals()\n\nglobalThis.IntersectionObserver === undefined\n'IntersectionObserver' in globalThis === false\n// throws ReferenceError, because it's not defined\nIntersectionObserver === undefined\n```\n\n## Fake Timers\n\nThis sections describes how to work with [fake timers](/guide/mocking/timers).\n\n### vi.advanceTimersByTime\n\n```ts\nfunction advanceTimersByTime(ms: number): Vitest\n```\n\nThis method will invoke every initiated timer until the specified number of milliseconds is passed or the queue is empty - whatever comes first.\n\n```ts\nlet i = 0\nsetInterval(() => console.log(++i), 50)\n\nvi.advanceTimersByTime(150)\n\n// log: 1\n// log: 2\n// log: 3\n```\n\n### vi.advanceTimersByTimeAsync\n\n```ts\nfunction advanceTimersByTimeAsync(ms: number): Promise<Vitest>\n```\n\nThis method will invoke every initiated timer until the specified number of milliseconds is passed or the queue is empty - whatever comes first. This will include asynchronously set timers.\n\n```ts\nlet i = 0\nsetInterval(() => Promise.resolve().then(() => console.log(++i)), 50)\n\nawait vi.advanceTimersByTimeAsync(150)\n\n// log: 1\n// log: 2\n// log: 3\n```\n\n### vi.advanceTimersToNextTimer\n\n```ts\nfunction advanceTimersToNextTimer(): Vitest\n```\n\nWill call next available timer. Useful to make assertions between each timer call. You can chain call it to manage timers by yourself.\n\n```ts\nlet i = 0\nsetInterval(() => console.log(++i), 50)\n\nvi.advanceTimersToNextTimer() // log: 1\n  .advanceTimersToNextTimer() // log: 2\n  .advanceTimersToNextTimer() // log: 3\n```\n\n### vi.advanceTimersToNextTimerAsync\n\n```ts\nfunction advanceTimersToNextTimerAsync(): Promise<Vitest>\n```\n\nWill call next available timer and wait until it's resolved if it was set asynchronously. Useful to make assertions between each timer call.\n\n```ts\nlet i = 0\nsetInterval(() => Promise.resolve().then(() => console.log(++i)), 50)\n\nawait vi.advanceTimersToNextTimerAsync() // log: 1\nexpect(console.log).toHaveBeenCalledWith(1)\n\nawait vi.advanceTimersToNextTimerAsync() // log: 2\nawait vi.advanceTimersToNextTimerAsync() // log: 3\n```\n\n### vi.advanceTimersToNextFrame {#vi-advancetimerstonextframe}\n\n```ts\nfunction advanceTimersToNextFrame(): Vitest\n```\n\nSimilar to [`vi.advanceTimersByTime`](/api/vi#vi-advancetimersbytime), but will advance timers by the milliseconds needed to execute callbacks currently scheduled with `requestAnimationFrame`.\n\n```ts\nlet frameRendered = false\n\nrequestAnimationFrame(() => {\n  frameRendered = true\n})\n\nvi.advanceTimersToNextFrame()\n\nexpect(frameRendered).toBe(true)\n```\n\n### vi.getTimerCount\n\n```ts\nfunction getTimerCount(): number\n```\n\nGet the number of waiting timers.\n\n### vi.clearAllTimers\n\n```ts\nfunction clearAllTimers(): void\n```\n\nRemoves all timers that are scheduled to run. These timers will never run in the future.\n\n### vi.getMockedSystemTime\n\n```ts\nfunction getMockedSystemTime(): Date | null\n```\n\nReturns mocked current date. If date is not mocked the method will return `null`.\n\n### vi.getRealSystemTime\n\n```ts\nfunction getRealSystemTime(): number\n```\n\nWhen using `vi.useFakeTimers`, `Date.now` calls are mocked. If you need to get real time in milliseconds, you can call this function.\n\n### vi.runAllTicks\n\n```ts\nfunction runAllTicks(): Vitest\n```\n\nCalls every microtask that was queued by `process.nextTick`. This will also run all microtasks scheduled by themselves.\n\n### vi.runAllTimers\n\n```ts\nfunction runAllTimers(): Vitest\n```\n\nThis method will invoke every initiated timer until the timer queue is empty. It means that every timer called during `runAllTimers` will be fired. If you have an infinite interval, it will throw after 10 000 tries (can be configured with [`fakeTimers.loopLimit`](/config/faketimers#faketimers-looplimit)).\n\n```ts\nlet i = 0\nsetTimeout(() => console.log(++i))\nconst interval = setInterval(() => {\n  console.log(++i)\n  if (i === 3) {\n    clearInterval(interval)\n  }\n}, 50)\n\nvi.runAllTimers()\n\n// log: 1\n// log: 2\n// log: 3\n```\n\n### vi.runAllTimersAsync\n\n```ts\nfunction runAllTimersAsync(): Promise<Vitest>\n```\n\nThis method will asynchronously invoke every initiated timer until the timer queue is empty. It means that every timer called during `runAllTimersAsync` will be fired even asynchronous timers. If you have an infinite interval,\nit will throw after 10 000 tries (can be configured with [`fakeTimers.loopLimit`](/config/faketimers#faketimers-looplimit)).\n\n```ts\nsetTimeout(async () => {\n  console.log(await Promise.resolve('result'))\n}, 100)\n\nawait vi.runAllTimersAsync()\n\n// log: result\n```\n\n### vi.runOnlyPendingTimers\n\n```ts\nfunction runOnlyPendingTimers(): Vitest\n```\n\nThis method will call every timer that was initiated after [`vi.useFakeTimers`](#vi-usefaketimers) call. It will not fire any timer that was initiated during its call.\n\n```ts\nlet i = 0\nsetInterval(() => console.log(++i), 50)\n\nvi.runOnlyPendingTimers()\n\n// log: 1\n```\n\n### vi.runOnlyPendingTimersAsync\n\n```ts\nfunction runOnlyPendingTimersAsync(): Promise<Vitest>\n```\n\nThis method will asynchronously call every timer that was initiated after [`vi.useFakeTimers`](#vi-usefaketimers) call, even asynchronous ones. It will not fire any timer that was initiated during its call.\n\n```ts\nsetTimeout(() => {\n  console.log(1)\n}, 100)\nsetTimeout(() => {\n  Promise.resolve().then(() => {\n    console.log(2)\n    setInterval(() => {\n      console.log(3)\n    }, 40)\n  })\n}, 10)\n\nawait vi.runOnlyPendingTimersAsync()\n\n// log: 2\n// log: 3\n// log: 3\n// log: 1\n```\n\n### vi.setSystemTime\n\n```ts\nfunction setSystemTime(date: string | number | Date): Vitest\n```\n\nIf fake timers are enabled, this method simulates a user changing the system clock (will affect date related API like `hrtime`, `performance.now` or `new Date()`) - however, it will not fire any timers. If fake timers are not enabled, this method will only mock `Date.*` calls.\n\nUseful if you need to test anything that depends on the current date - for example [Luxon](https://github.com/moment/luxon/) calls inside your code.\n\nAccepts the same string and number arguments as the `Date`.\n\n```ts\nconst date = new Date(1998, 11, 19)\n\nvi.useFakeTimers()\nvi.setSystemTime(date)\n\nexpect(Date.now()).toBe(date.valueOf())\n\nvi.useRealTimers()\n```\n\n### vi.useFakeTimers\n\n```ts\nfunction useFakeTimers(config?: FakeTimerInstallOpts): Vitest\n```\n\nTo enable mocking timers, you need to call this method. It will wrap all further calls to timers (such as `setTimeout`, `setInterval`, `clearTimeout`, `clearInterval`, `setImmediate`, `clearImmediate`, and `Date`) until [`vi.useRealTimers()`](#vi-userealtimers) is called.\n\nMocking `nextTick` is not supported when running Vitest inside `node:child_process` by using `--pool=forks`. NodeJS uses `process.nextTick` internally in `node:child_process` and hangs when it is mocked. Mocking `nextTick` is supported when running Vitest with `--pool=threads`.\n\nThe implementation is based internally on [`@sinonjs/fake-timers`](https://github.com/sinonjs/fake-timers).\n\n::: tip\n`vi.useFakeTimers()` does not automatically mock `process.nextTick` and `queueMicrotask`.\nBut you can enable it by specifying the option in `toFake` argument: `vi.useFakeTimers({ toFake: ['nextTick', 'queueMicrotask'] })`.\n:::\n\n### vi.setTimerTickMode <Version>4.1.0</Version> {#vi-settimertickmode}\n\n- **Type:** `(mode: 'manual' | 'nextTimerAsync') => Vitest | (mode: 'interval', interval?: number) => Vitest`\n\nControls how fake timers are advanced.\n\n- `manual`: The default behavior. Timers will only advance when you call one of `vi.advanceTimers...()` methods.\n- `nextTimerAsync`: Timers will be advanced automatically to the next available timer after each macrotask.\n- `interval`: Timers are advanced automatically by a specified interval.\n\nWhen `mode` is `'interval'`, you can also provide an `interval` in milliseconds.\n\n**Example:**\n\n```ts\nimport { vi } from 'vitest'\n\nvi.useFakeTimers()\n\n// Manual mode (default)\nvi.setTimerTickMode('manual')\n\nlet i = 0\nsetInterval(() => console.log(++i), 50)\n\nvi.advanceTimersByTime(150) // logs 1, 2, 3\n\n// nextTimerAsync mode\nvi.setTimerTickMode('nextTimerAsync')\n\n// Timers will advance automatically after each macrotask\nawait new Promise(resolve => setTimeout(resolve, 150)) // logs 4, 5, 6\n\n// interval mode (default when 'fakeTimers.shouldAdvanceTime' is `true`)\nvi.setTimerTickMode('interval', 50)\n\n// Timers will advance automatically every 50ms\nawait new Promise(resolve => setTimeout(resolve, 150)) // logs 7, 8, 9\n```\n\n### vi.isFakeTimers {#vi-isfaketimers}\n\n```ts\nfunction isFakeTimers(): boolean\n```\n\nReturns `true` if fake timers are enabled.\n\n### vi.useRealTimers\n\n```ts\nfunction useRealTimers(): Vitest\n```\n\nWhen timers have run out, you may call this method to return mocked timers to its original implementations. All timers that were scheduled before will be discarded.\n\n## Miscellaneous\n\nA set of useful helper functions that Vitest provides.\n\n### vi.waitFor {#vi-waitfor}\n\n```ts\nfunction waitFor<T>(\n  callback: WaitForCallback<T>,\n  options?: number | WaitForOptions\n): Promise<T>\n```\n\nWait for the callback to execute successfully. If the callback throws an error or returns a rejected promise it will continue to wait until it succeeds or times out.\n\nIf options is set to a number, the effect is equivalent to setting `{ timeout: options }`.\n\nThis is very useful when you need to wait for some asynchronous action to complete, for example, when you start a server and need to wait for it to start.\n\n```ts\nimport { expect, test, vi } from 'vitest'\nimport { createServer } from './server.js'\n\ntest('Server started successfully', async () => {\n  const server = createServer()\n\n  await vi.waitFor(\n    () => {\n      if (!server.isReady) {\n        throw new Error('Server not started')\n      }\n\n      console.log('Server started')\n    },\n    {\n      timeout: 500, // default is 1000\n      interval: 20, // default is 50\n    }\n  )\n  expect(server.isReady).toBe(true)\n})\n```\n\nIt also works for asynchronous callbacks\n\n```ts\n// @vitest-environment jsdom\n\nimport { expect, test, vi } from 'vitest'\nimport { getDOMElementAsync, populateDOMAsync } from './dom.js'\n\ntest('Element exists in a DOM', async () => {\n  // start populating DOM\n  populateDOMAsync()\n\n  const element = await vi.waitFor(async () => {\n    // try to get the element until it exists\n    const element = await getDOMElementAsync() as HTMLElement | null\n    expect(element).toBeTruthy()\n    expect(element.dataset.initialized).toBeTruthy()\n    return element\n  }, {\n    timeout: 500, // default is 1000\n    interval: 20, // default is 50\n  })\n  expect(element).toBeInstanceOf(HTMLElement)\n})\n```\n\nIf `vi.useFakeTimers` is used, `vi.waitFor` automatically calls `vi.advanceTimersByTime(interval)` in every check callback.\n\n### vi.waitUntil {#vi-waituntil}\n\n```ts\nfunction waitUntil<T>(\n  callback: WaitUntilCallback<T>,\n  options?: number | WaitUntilOptions\n): Promise<T>\n```\n\nThis is similar to `vi.waitFor`, but if the callback throws any errors, execution is immediately interrupted and an error message is received. If the callback returns falsy value, the next check will continue until truthy value is returned. This is useful when you need to wait for something to exist before taking the next step.\n\nLook at the example below. We can use `vi.waitUntil` to wait for the element to appear on the page, and then we can do something with the element.\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\ntest('Element render correctly', async () => {\n  const element = await vi.waitUntil(\n    () => document.querySelector('.element'),\n    {\n      timeout: 500, // default is 1000\n      interval: 20, // default is 50\n    }\n  )\n\n  // do something with the element\n  expect(element.querySelector('.element-child')).toBeTruthy()\n})\n```\n\n### vi.hoisted {#vi-hoisted}\n\n```ts\nfunction hoisted<T>(factory: () => T): T\n```\n\nAll static `import` statements in ES modules are hoisted to the top of the file, so any code that is defined before the imports will actually be executed after imports are evaluated.\n\nHowever, it can be useful to invoke some side effects like mocking dates before importing a module.\n\nTo bypass this limitation, you can rewrite static imports into dynamic ones like this:\n\n```diff\ncallFunctionWithSideEffect()\n- import { value } from './some/module.js'\n+ const { value } = await import('./some/module.js')\n```\n\nWhen running `vitest`, you can do this automatically by using `vi.hoisted` method. Under the hood, Vitest will convert static imports into dynamic ones with preserved live-bindings.\n\n```diff\n- callFunctionWithSideEffect()\nimport { value } from './some/module.js'\n+ vi.hoisted(() => callFunctionWithSideEffect())\n```\n\n::: warning IMPORTS ARE NOT AVAILABLE\nRunning code before the imports means that you cannot access imported variables because they are not defined yet:\n\n```ts\nimport { value } from './some/module.js'\n\nvi.hoisted(() => { value }) // throws an error // [!code warning]\n```\n\nThis code will produce an error:\n\n```\nCannot access '__vi_import_0__' before initialization\n```\n\nIf you need to access a variable from another module inside of `vi.hoisted`, use dynamic import:\n\n```ts\nawait vi.hoisted(async () => {\n  const { value } = await import('./some/module.js')\n})\n```\n\nHowever, it is discourage to import anything inside of `vi.hoisted` because imports are already hoisted - if you need to execute something before the tests are running, just execute it in the imported module itself.\n:::\n\nThis method returns the value that was returned from the factory. You can use that value in your `vi.mock` factories if you need easy access to locally defined variables:\n\n```ts\nimport { expect, vi } from 'vitest'\nimport { originalMethod } from './path/to/module.js'\n\nconst { mockedMethod } = vi.hoisted(() => {\n  return { mockedMethod: vi.fn() }\n})\n\nvi.mock('./path/to/module.js', () => {\n  return { originalMethod: mockedMethod }\n})\n\nmockedMethod.mockReturnValue(100)\nexpect(originalMethod()).toBe(100)\n```\n\nNote that this method can also be called asynchronously even if your environment doesn't support top-level await:\n\n```ts\nconst json = await vi.hoisted(async () => {\n  const response = await fetch('https://jsonplaceholder.typicode.com/posts')\n  return response.json()\n})\n```\n\n### vi.setConfig\n\n```ts\nfunction setConfig(config: RuntimeOptions): void\n```\n\nUpdates config for the current test file. This method supports only config options that will affect the current test file:\n\n```ts\nvi.setConfig({\n  allowOnly: true,\n  testTimeout: 10_000,\n  hookTimeout: 10_000,\n  clearMocks: true,\n  restoreMocks: true,\n  fakeTimers: {\n    now: new Date(2021, 11, 19),\n    // supports the whole object\n  },\n  maxConcurrency: 10,\n  sequence: {\n    hooks: 'stack'\n    // supports only \"sequence.hooks\"\n  }\n})\n```\n\n### vi.resetConfig\n\n```ts\nfunction resetConfig(): void\n```\n\nIf [`vi.setConfig`](#vi-setconfig) was called before, this will reset config to the original state.\n\n### vi.defineHelper <Version>4.1.0</Version> {#vi-defineHelper}\n\n```ts\nfunction defineHelper<F extends (...args: any) => any>(fn: F): F\n```\n\nWraps a function to create an assertion helper. When an assertion fails inside the helper, the error stack trace will point to where the helper was called, not inside the helper itself. This makes it easier to identify the source of test failures when using custom assertion functions.\n\nWorks with both synchronous and asynchronous functions, and supports `expect.soft()`.\n\n```ts\nimport { expect, vi } from 'vitest'\n\nconst assertPair = vi.defineHelper((a, b) => {\n  expect(a).toEqual(b)\n})\n\ntest('example', () => {\n  assertPair('left', 'right') // Error points to this line\n})\n```\n\nExample output:\n\n<!-- eslint-skip -->\n```js\nFAIL  example.test.ts > example\nAssertionError: expected 'left' to deeply equal 'right'\n\nExpected: \"right\"\nReceived: \"left\"\n\n ❯ example.test.ts:8:3\n      7| test('example', () => {\n      8|   assertPair('left', 'right')\n       |   ^\n      9| })\n```\n"
  },
  {
    "path": "docs/blog/vitest-3-2.md",
    "content": "---\ntitle: Vitest 3.2 is out!\nauthor:\n  name: The Vitest Team\ndate: 2025-06-02\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vitest 3.2\n  - - meta\n    - property: og:image\n      content: https://vitest.dev/og-vitest-3-2.png\n  - - meta\n    - property: og:url\n      content: https://vitest.dev/blog/vitest-3-2\n  - - meta\n    - property: og:description\n      content: Vitest 3.2 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vitest 3.2 is out!\n\n_June 2, 2025_\n\n![Vitest 3.2 Announcement Cover Image](/og-vitest-3-2.png)\n\nVitest 3.2 focuses on improvements to Browser Mode and TypeScript support. This release also includes some new useful methods, config options and deprecates the `workspace` config in favour of `projects`.\n\n## `workspace` is Deprecated\n\nIn an effort to simplify the configuration, the team decided to deprecate the separate `vitest.workspace` file and recommend using only the `projects` option in the root config. This also simplifies how the global options are configured (because you don't need to guess how to add reporters when you have no root config).\n\nWe also decided to deprecate the `workspace` name because it clashes with other tools like PNPM that provide monorepo support via this option. Vitest doesn't run these projects with separate `CWD` and treats them more like sub-Vitests. It also gives us more space to come up with a better solution for monorepos without breaking others.\n\nThis option will be removed completely in a future major, replaced by `projects`. Until then, Vitest will print a warning if workspace feature is used.\n\n<!--@include: ../guide/examples/projects-workspace.md-->\n\n## Annotation API\n\nThe new [annotation API](/guide/test-annotations) allows you to annotate any test with a custom message and attachment. These annotations are visible in the UI, HTML, junit, tap and GitHub Actions reporters. Vitest will also print related annotation in the CLI if the test fails.\n\n<img src=\"/annotation-api-cute-puppy-example.png\" alt=\"an example of annotation with a cute puppy\" />\n\n## Scoped Fixtures\n\nThe `test.extend` fixtures can now specify the `scope` option: either `file` or `worker`.\n\n```ts\nconst test = baseTest.extend({\n  db: [\n    async ({}, use) => {\n      // ...setup\n      await use(db)\n      await db.close()\n    },\n    { scope: 'worker' },\n  ],\n})\n```\n\nThe file fixture is similar to using `beforeAll` and `afterAll` at the top level of the file, but it won't be called if the fixture is not used in any test.\n\nThe `worker` fixture is initiated once per worker, but note that by default Vitest creates one worker for every test, so you need to disable [isolation](/config/isolate) to benefit from it.\n\n## Custom Project Name Colors\n\nYou can now set a custom [color](/config/name) when using `projects`:\n\n::: details Config Example\n```ts{6-9,14-17}\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: {\n            label: 'unit',\n            color: 'red',\n          },\n        },\n      },\n      {\n        test: {\n          name: {\n            label: 'browser',\n            color: 'green',\n          },\n          browser: {\n            enabled: true,\n            provider: 'playwright',\n            instances: [{ browser: 'chromium' }],\n          },\n        },\n      },\n    ],\n  },\n})\n```\n:::\n\n<img src=\"/v3-2-custom-colors.png\" alt=\"an example of project names with custom backgrounds\" />\n\n## Custom Browser Locators API\n\nBuilt-in locators might not be enough to express your application’s needs. Instead of falling back to CSS and losing the retry-ability protection that Vitest provides through its locator API, we now recommend extending locators using the new [`locators.extend` API](/api/browser/locators#custom-locators).\n\n```ts\nimport { locators } from '@vitest/browser/context'\n\nlocators.extend({\n  getByCommentsCount(count: number) {\n    return `.comments :text(\"${count} comments\")`\n  },\n})\n```\n\nReturn a Playwright [locator string](https://playwright.dev/docs/other-locators) to construct a new locator. Note that string returned from this method will be scoped to the parent locator, if there is one.\n\nNow you can call `getByCommentsCount` on the `page` or any other locator directly:\n\n```ts\nawait expect.element(page.getByCommentsCount(1)).toBeVisible()\nawait expect.element(\n  page.getByRole('article', { name: 'Hello World' })\n    .getByCommentsCount(1)\n).toBeVisible()\n```\n\nIf this method returns a string, then the return value will be converted into a locator, so you can keep chaining it:\n\n```ts\npage.getByRole('article', { name: 'Hello World' })\n  .getByCommentsCount(1)\n  .getByText('comments')\n```\n\nThis method has access to the current locator context, if there is one (if method is called on the `page`, then context will refer to `page`), so you can chain all locator methods inside:\n\n```ts\nimport { locators } from '@vitest/browser/context'\nimport type { Locator } from '@vitest/browser/context'\n\nlocators.extend({\n  getByCommentsCount(this: Locator, count: number) {\n    return this.getByRole('comment')\n      .and(this.getByText(`${count} comments`))\n  },\n})\n```\n\nHaving access to context also allows you to call regular methods of the locator to define a custom user event:\n\n```ts\nimport { locators, page } from '@vitest/browser/context'\nimport type { Locator } from '@vitest/browser/context'\n\nlocators.extend({\n  clickAndFill(this: Locator, text: string) {\n    await this.click()\n    await this.fill(text)\n  },\n})\n\nawait page.getByRole('textbox').clickAndFill('Hello World')\n```\n\nPlease, refer to the [`locators.extend` API](/api/browser/locators#custom-locators) for more information.\n\n## Explicit Resource Management in `vi.spyOn` and `vi.fn`\n\nIn environments that support [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management), you can use `using` instead of `const` to automatically call `mockRestore` on any mocked function when the containing block is exited. This is especially useful for spied methods:\n\n```ts\nit('calls console.log', () => {\n  using spy = vi.spyOn(console, 'log').mockImplementation(() => {})\n  debug('message')\n  expect(spy).toHaveBeenCalled()\n})\n\n// console.log is restored here\n```\n\n## Test `signal` API\n\nVitest now provides an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) object to the test body. You can use it to stop any resource that supports this Web API.\n\nThe signal is aborted when test times out, another test fails and [`--bail` flag](/config/bail) is set to a non-zero value, or the user presses Ctrl+C in the terminal.\n\nFor example, you can stop a `fetch` request when tests are interrupted:\n\n```ts\nit('stop request when test times out', async ({ signal }) => {\n  await fetch('/heavy-resource', { signal })\n}, 2000)\n```\n\n## Coverage V8 AST-aware remapping\n\nVitest now uses `ast-v8-to-istanbul` package developed by one of the Vitest maintainers, [AriPerkkio](https://github.com/AriPerkkio). This brings v8 coverage report in line with istanbul, but has a better performance! Enable this feature by setting [`coverage.experimentalAstAwareRemapping`](/config/coverage#coverage-experimentalastawareremapping) to `true`.\n\nWe are planning to make this the default remapping mode in the next major. The old `v8-to-istanbul` will be removed completely. Feel free to join discussion at https://github.com/vitest-dev/vitest/issues/7928.\n\n## `watchTriggerPatterns` Option\n\nWhen you edit a file, Vitest is smart enough to rerun only tests that import this file. Unfortunately, Vitest static analysis respects only static and dynamic `import` statement. If you are reading a file or starting a separate process, Vitest will ignore changes to related files.\n\nWith `watchTriggerPatterns` option you can configure which tests to rerun depending on the file that was changed. For example, to always rerun `mailers` tests when a template is changed, add a trigger pattern:\n\n```ts\nexport default defineConfig({\n  test: {\n    watchTriggerPatterns: [\n      {\n        pattern: /^src\\/templates\\/(.*)\\.(ts|html|txt)$/,\n        testsToRun: (file, match) => {\n          return `api/tests/mailers/${match[2]}.test.ts`\n        },\n      },\n    ],\n  },\n})\n```\n\n## The New Multi-Purpose `Matchers` Type\n\nVitest now has a `Matchers` type that you can extend to add type support for all your custom matchers in one place. This type affects all these use cases:\n\n- `expect().to*`\n- `expect.to*`\n- `expect.extend({ to* })`\n\nFor example, to have a type-safe `toBeFoo` matcher, you can write something like this:\n\n```ts twoslash\nimport { expect } from 'vitest'\n\ninterface CustomMatchers<R = unknown> {\n  toBeFoo: (arg: string) => R\n}\n\ndeclare module 'vitest' {\n  interface Matchers<T = any> extends CustomMatchers<T> {}\n}\n\nexpect.extend({\n  toBeFoo(actual, arg) {\n    //            ^?\n    // ... implementation\n    return {\n      pass: true,\n      message: () => '',\n    }\n  }\n})\n\nexpect('foo').toBeFoo('foo')\nexpect.toBeFoo('foo')\n```\n\n## `sequence.groupOrder`\n\nThe new [`sequence.groupOrder`](/config/sequence#sequence-grouporder) option controls the order in which the project runs its tests when using multiple [projects](/guide/projects).\n\n- Projects with the same group order number will run together, and groups are run from lowest to highest.\n- If you don’t set this option, all projects run in parallel.\n- If several projects use the same group order, they will run at the same time.\n\n::: details Example\nConsider this example:\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: 'slow',\n          sequence: {\n            groupOrder: 0,\n          },\n        },\n      },\n      {\n        test: {\n          name: 'fast',\n          sequence: {\n            groupOrder: 0,\n          },\n        },\n      },\n      {\n        test: {\n          name: 'flaky',\n          sequence: {\n            groupOrder: 1,\n          },\n        },\n      },\n    ],\n  },\n})\n```\n\nTests in these projects will run in this order:\n\n```\n 0. slow  |\n          |> running together\n 0. fast  |\n\n 1. flaky |> runs after slow and fast alone\n```\n:::\n\n----\n\nThe complete list of changes is at the [Vitest 3.2 Changelog](https://github.com/vitest-dev/vitest/releases/tag/v3.2.0).\n"
  },
  {
    "path": "docs/blog/vitest-3.md",
    "content": "---\ntitle: Vitest 3.0 is out!\nauthor:\n  name: The Vitest Team\ndate: 2025-01-17\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vitest 3.0\n  - - meta\n    - property: og:image\n      content: https://vitest.dev/og-vitest-3.jpg\n  - - meta\n    - property: og:url\n      content: https://vitest.dev/blog/vitest-3\n  - - meta\n    - property: og:description\n      content: Vitest 3.0 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vitest 3.0 is out!\n\n_January 17, 2025_\n\n![Vitest 3 Announcement Cover Image](/og-vitest-3.jpg)\n\nWe released Vitest 2 half a year ago. We have seen huge adoption, from 4,8M to 7,7M weekly npm downloads. Our ecosystem is growing rapidly too. Among others, [Storybook new testing capabilities powered by our vscode extension and browser mode](https://storybook.js.org/docs/writing-tests/test-addon) and Matt Pocock is building [Evalite](https://www.evalite.dev/), a tool for evaluating AI-powered apps, on top of Vitest.\n\n## The next Vitest major is here\n\nToday, we are thrilled to announce Vitest 3! This is a big one!\n\nQuick links:\n\n- [Docs](/)\n- Translations: [简体中文](https://cn.vitest.dev/)\n- [Migration Guide](/guide/migration)\n- [GitHub Changelog](https://github.com/vitest-dev/vitest/releases/tag/v3.0.0)\n\nIf you've not used Vitest before, we suggest reading the [Getting Started](/guide/) and [Features](/guide/features) guides first.\n\nWe extend our gratitude to the over [550 contributors to Vitest Core](https://github.com/vitest-dev/vitest/graphs/contributors) and to the maintainers and contributors of Vitest integrations, tools, and translations who have helped us develop this new major release. We encourage you to get involved and help us improve Vitest for the entire ecosystem. Learn more at our [Contributing Guide](https://github.com/vitest-dev/vitest/blob/main/CONTRIBUTING.md).\n\nTo get started, we suggest helping [triage issues](https://github.com/vitest-dev/vitest/issues), [review PRs](https://github.com/vitest-dev/vitest/pulls), send failing tests PRs based on open issues, and support others in [Discussions](https://github.com/vitest-dev/vitest/discussions) and Vitest Land's [help forum](https://discord.com/channels/917386801235247114/1057959614160851024). If you'd like to talk to us, join our [Discord community](http://chat.vitest.dev/) and say hi on the [#contributing channel](https://discord.com/channels/917386801235247114/1057959614160851024).\n\nFor the latest news about the Vitest ecosystem and Vitest core, follow us on [Bluesky](https://bsky.app/profile/vitest.dev) or [Mastodon](https://webtoo.ls/@vitest).\n\n## Reporter Updates\n\n[@AriPerkkio](https://github.com/ariperkkio) rewrote how Vitest reports the test run. You should see less flicker and more stable output!\n\n<div class=\"flex align-center justify-center\">\n  <video controls>\n    <source src=\"/new-reporter.webm\" type=\"video/webm\">\n  </video>\n</div>\n\nAlongside this change, we also redesign the public reporter API (the `reporters` field) making the [lifecycle](/api/advanced/reporters) easier to understand.\n\nYou can follow the design process in [#7069](https://github.com/vitest-dev/vitest/pull/7069) PR. It was a hard fight trying to reverse-engineer the previous `onTaskUpdate` API to make this new elegant lifecycle possible.\n\n<div class=\"flex align-center justify-center\">\n  <img src=\"/on-task-update.gif\" alt=\"a gif from it's always sunny with a drawing board\" />\n</div>\n\n## Inline Workspace\n\nRejoice! No more separate files to define your [workspace](/guide/projects) - specify an array of projects using the `workspace` field in your `vitest.config` file:\n\n```jsx\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    workspace: ['packages/*'],\n  },\n})\n```\n\n## Multi-Browser Configuration\n\nVitest 3 introduces a more performant way to run your browser tests in different browsers or setups. Instead of using the workspace, you can define an array of [`instances`](/guide/browser/multiple-setups) to run your browser tests in different setups:\n\n```jsx\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: 'playwright',\n      instances: [\n        {\n          browser: 'chromium',\n          launch: { devtools: true },\n        },\n        {\n          browser: 'firefox',\n          setupFiles: ['./setup.firefox.ts'],\n          provide: {\n            secret: 'my-secret',\n          },\n        },\n      ],\n    }\n  }\n})\n```\n\nThe main advantage of `instances` over `workspace` is a better caching strategy - Vitest creates only a single Vite server to serve files, which are processed only once, independent of how many browsers you test.\n\nThis release also improves the documentation of Browser Mode features and introduces separate guides for [Playwright](/config/browser/playwright) and [WebdriverIO](/config/browser/webdriverio) hopefully making it easier to configure.\n\n## Filtering by Location\n\nIn Vitest 3 you can now filter tests by line number.\n\n```\n$ vitest basic/foo.js:10\n$ vitest ./basic/foo.js:10\n```\n\nA big shutout to [@mzhubail](https://github.com/mzhubail) for implementing this feature.\n\n## Public API\n\nWe have redesigned the public API available from `vitest/node` and are planning to remove the experimental tag in the next minor version. This release also includes brand new documentation covering all exposed methods.\n\n<img alt=\"Vitest API documentation\" img-light src=\"/docs-api-light.png\">\n<img alt=\"Vitest API documentation\" img-dark src=\"/docs-api-dark.png\">\n\n## Breaking changes\n\nVitest 3 has a few small breaking changes that should not affect most users, but we advise reviewing the detailed [Migration Guide](/guide/migration.html#vitest-3) before upgrading.\n\nThe complete list of changes is at the [Vitest 3 Changelog](https://github.com/vitest-dev/vitest/releases/tag/v3.0.0).\n\n## Acknowledgments\n\nVitest 3 is the result of countless hours by the [Vitest team](/team) and our contributors. We appreciate the individuals and companies sponsoring Vitest development. [Vladimir](https://github.com/sheremet-va) and [Hiroshi](https://github.com/hi-ogawa) joined [VoidZero](https://voidzero.dev) to work on Vite and Vitest full-time, and [StackBlitz](https://stackblitz.com/) hired [Ari](https://github.com/ariperkkio) to invest more time in Vitest development. A shout-out to [NuxtLabs](https://nuxtlabs.com), [Zammad](https://zammad.com), and sponsors on [Vitest's GitHub Sponsors](https://github.com/sponsors/vitest-dev) and [Vitest's Open Collective](https://opencollective.com/vitest).\n"
  },
  {
    "path": "docs/blog/vitest-4-1.md",
    "content": "---\ntitle: Vitest 4.1 is out!\nauthor:\n  name: The Vitest Team\ndate: 2026-03-12\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vitest 4.1\n  - - meta\n    - property: og:image\n      content: https://vitest.dev/og-vitest-4-1.jpg\n  - - meta\n    - property: og:url\n      content: https://vitest.dev/blog/vitest-4-1\n  - - meta\n    - property: og:description\n      content: Vitest 4.1 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vitest 4.1 is out!\n\n_March 12, 2026_\n\n![Vitest 4.1 Announcement Cover Image](/og-vitest-4-1.jpg)\n\n## The next Vitest minor is here\n\nToday, we are thrilled to announce Vitest 4.1 packed with new exciting features!\n\nQuick links:\n\n- [Docs](/)\n- Translations: [简体中文](https://cn.vitest.dev/)\n- [GitHub Changelog](https://github.com/vitest-dev/vitest/releases/tag/v4.1.0)\n\nIf you've not used Vitest before, we suggest reading the [Getting Started](/guide/) and [Features](/guide/features) guides first.\n\nWe extend our gratitude to the over [713 contributors to Vitest Core](https://github.com/vitest-dev/vitest/graphs/contributors) and to the maintainers and contributors of Vitest integrations, tools, and translations who have helped us develop this new release. We encourage you to get involved and help us improve Vitest for the entire ecosystem. Learn more at our [Contributing Guide](https://github.com/vitest-dev/vitest/blob/main/CONTRIBUTING.md).\n\nTo get started, we suggest helping [triage issues](https://github.com/vitest-dev/vitest/issues), [review PRs](https://github.com/vitest-dev/vitest/pulls), send failing tests PRs based on open issues, and support others in [Discussions](https://github.com/vitest-dev/vitest/discussions) and Vitest Land's [help forum](https://discord.com/channels/917386801235247114/1057959614160851024). If you'd like to talk to us, join our [Discord community](http://chat.vitest.dev/) and say hi on the [#contributing channel](https://discord.com/channels/917386801235247114/1057959614160851024).\n\nFor the latest news about the Vitest ecosystem and Vitest core, follow us on [Bluesky](https://bsky.app/profile/vitest.dev) or [Mastodon](https://webtoo.ls/@vitest).\n\nTo stay updated, keep an eye on the [VoidZero blog](https://voidzero.dev/blog) and subscribe to the [newsletter](https://voidzero.dev/newsletter).\n\n## Vite 8 Support\n\nThis release adds support for the new Vite 8 version. Additionally, Vitest now uses the installed `vite` version instead of downloading a separate dependency, if possible. This makes issues like type inconsistencies in your config file obsolete.\n\n## Test Tags\n\n[Tags](/guide/test-tags) let you label tests to organize them into groups. Once tagged, you can filter tests by tag or apply shared options — like a longer timeout or automatic retries — to every test with a given tag.\n\nTo use tags, define them in your configuration file. Each tag requires a `name` and can optionally include test options that apply to every test marked with that tag. For the full list of available options, see [`tags`](/config/tags).\n\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    tags: [\n      {\n        name: 'db',\n        description: 'Tests for database queries.',\n        timeout: 60_000,\n      },\n      {\n        name: 'flaky',\n        description: 'Flaky CI tests.',\n        retry: process.env.CI ? 3 : 0,\n      },\n    ],\n  },\n})\n```\n\nWith this configuration, you can apply `flaky` and `db` tags to your tests:\n\n```ts\ntest('flaky database test', { tags: ['flaky', 'db'] }, () => {\n  // ...\n})\n```\n\nThe test has a timeout of 60 seconds and will be retried 3 times on CI because these options were specified in the configuration file for `db` and `flaky` tags.\n\nInspired by [pytest](https://docs.pytest.org/en/stable/reference/reference.html#cmdoption-m), Vitest supports a custom syntax for filtering tags:\n\n- `and` or `&&` to include both expressions\n- `or` or `||` to include at least one expression\n- `not` or `!` to exclude the expression\n- `*` to match any number of characters (0 or more)\n- `()` to group expressions and override precedence\n\nHere are some common filtering patterns:\n\n```shell\n# Run only unit tests\nvitest --tags-filter=\"unit\"\n\n# Run tests that are both frontend AND fast\nvitest --tags-filter=\"frontend and fast\"\n\n# Run frontend tests that are not flaky\nvitest --tags-filter=\"frontend && !flaky\"\n\n# Run tests matching a wildcard pattern\nvitest --tags-filter=\"api/*\"\n```\n\n## Experimental `viteModuleRunner: false`\n\nBy default, Vitest runs all code inside Vite's [module runner](https://vite.dev/guide/api-environment-runtimes#modulerunner) — a permissive sandbox that provides `import.meta.env`, `require`, `__dirname`, `__filename`, and applies Vite plugins and aliases. While this makes getting started easy, it can hide real issues: your tests may pass in the sandbox but fail in production because the runtime behavior differs from native Node.js.\n\nVitest 4.1 introduces [`experimental.viteModuleRunner`](/config/experimental#experimental-vitemodulerunner), which lets you disable the module runner entirely and run tests with native `import` instead:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    experimental: {\n      viteModuleRunner: false,\n    },\n  },\n})\n```\n\nWith this flag, **no file transforms are applied** — your test files, source code, and setup files are executed by Node.js directly. This means faster startup, closer-to-production behavior, and issues like incorrect `__dirname` injection or silently passing imports of nonexistent exports are caught early.\n\nIf you are using Node.js 22.18+ or 23.6+, TypeScript is [stripped natively](https://nodejs.org/en/learn/typescript/run-natively) — no extra configuration needed.\n\nMocking with `vi.mock` and `vi.hoisted` is supported via the Node.js [Module Loader API](https://nodejs.org/api/module.html#customization-hooks) (requires Node.js 22.15+). Note that `import.meta.env`, Vite plugins, aliases, and the `istanbul` coverage provider are not available in this mode.\n\nConsider this option if you run server-side or script-like tests that don't need Vite transforms. For `jsdom`/`happy-dom` tests, we still recommend the default module runner or [browser mode](/guide/browser/).\n\nRead more in the [`experimental.viteModuleRunner` docs](/config/experimental#experimental-vitemodulerunner).\n\n## Configure UI Browser Window\n\nVitest 4.1 introduces [`browser.detailsPanelPosition`](/config/browser/detailspanelposition), letting you choose where the details panel appears in Browser UI.\n\n<center>\n  <img alt=\"Vitest UI with details at the bottom\" img-light src=\"/ui/light-ui-details-bottom.png\">\n  <img alt=\"Vitest UI with details at the bottom\" img-dark src=\"/ui/dark-ui-details-bottom.png\">\n\n  <sup>An example of UI with the details panel at the bottom.</sup>\n</center>\n\nThis is especially useful on smaller screens, where switching to a bottom panel leaves more horizontal space for your app:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      detailsPanelPosition: 'bottom', // or 'right'\n    },\n  },\n})\n```\n\nYou can also switch this directly from the UI via the new layout toggle button.\n\n## Enhanced Browser Trace View\n\nVitest 4.1 brings major improvements to the [Playwright Trace Viewer](/guide/browser/trace-view) integration in browser mode. Browser interactions like `click`, `fill`, and `expect.element` are now automatically grouped in the trace timeline and linked back to the exact line in your test file.\n\n<center>\n  <img alt=\"Trace Viewer showing the trace timeline and rendered component\" img-light src=\"/trace-viewer-light.png\">\n  <img alt=\"Trace Viewer showing the trace timeline and rendered component\" img-dark src=\"/trace-viewer-dark.png\">\n\n  <sup>An example of trace view with `expect.element` assertion failure highlighted.</sup>\n</center>\n\nFramework libraries are also integrating with the trace. For example, [`vitest-browser-react`](https://github.com/vitest-community/vitest-browser-react)'s `render()` utility now automatically appears in the trace with rendered element highlighted.\n\nFor custom annotations, the new [`page.mark`](/api/browser/context#mark) and [`locator.mark`](/api/browser/locators#mark) APIs let you add your own markers to the trace:\n\n```ts\nimport { page } from 'vitest/browser'\n\nawait page.mark('before sign in')\nawait page.getByRole('button', { name: 'Sign in' }).click()\nawait page.mark('after sign in')\n```\n\nYou can also group a whole flow under one named entry:\n\n```ts\nawait page.mark('sign in flow', async () => {\n  await page.getByRole('textbox', { name: 'Email' }).fill('john@example.com')\n  await page.getByRole('textbox', { name: 'Password' }).fill('secret')\n  await page.getByRole('button', { name: 'Sign in' }).click()\n})\n```\n\nRead more in the [Trace View guide](/guide/browser/trace-view).\n\n## Type-Inference in `test.extend` - New Builder Pattern\n\nVitest 4.1 introduces a new [`test.extend`](/guide/test-context) pattern that supports type inference. You can return a value from the factory instead of calling the `use` function — TypeScript infers the type of each fixture from its return value, so you don't need to declare types manually.\n\n```ts\nimport { test as baseTest } from 'vitest'\n\nexport const test = baseTest\n  // Simple value - type is inferred as { port: number; host: string }\n  .extend('config', { port: 3000, host: 'localhost' })\n  // Function fixture - type is inferred from return value\n  .extend('server', async ({ config }) => {\n    // TypeScript knows config is { port: number; host: string }\n    return `http://${config.host}:${config.port}`\n  })\n```\n\nFor fixtures that need setup or cleanup logic, use a function. The `onCleanup` callback registers teardown logic that runs after the fixture's scope ends:\n\n```ts\nimport { test as baseTest } from 'vitest'\n\nexport const test = baseTest\n  .extend('tempFile', async ({}, { onCleanup }) => {\n    const filePath = `/tmp/test-${Date.now()}.txt`\n    await fs.writeFile(filePath, 'test data')\n\n    // Register cleanup - runs after test completes\n    onCleanup(() => fs.unlink(filePath))\n\n    return filePath\n  })\n```\n\nIn addition to this, Vitest now passes down `file` and `worker` contexts to `beforeAll`, `afterAll` and `aroundAll` hooks:\n\n```ts\nimport { test as baseTest } from 'vitest'\n\nconst test = baseTest\n  .extend('config', { scope: 'file' }, () => loadConfig())\n  .extend('db', { scope: 'file' }, ({ config }) => createDatabase(config.port))\n\ntest.beforeAll(async ({ db }) => {\n  await db.migrateUsers()\n})\n\ntest.afterAll(async ({ db }) => {\n  await db.deleteUsers()\n})\n```\n\n::: warning\nThis change could be considered breaking. Previously Vitest passed down undocumented `Suite` as the first argument. The team decided that the usage was small enough to not disrupt the ecosystem.\n:::\n\n## New `aroundAll` and `aroundEach` Hooks\n\nThe new `aroundEach` hook registers a callback function that wraps around each test within the current suite. The callback receives a `runTest` function that **must** be called to run the test. The `aroundAll` hook works similarly, but is called for every suite, not every test.\n\nYou should use `aroundEach` when your test needs to run **inside a context** that wraps around it, such as:\n- Wrapping tests in [AsyncLocalStorage](https://nodejs.org/api/async_context.html#class-asynclocalstorage) context\n- Wrapping tests with tracing spans\n- Database transactions\n\n```ts\nimport { test as baseTest } from 'vitest'\n\nconst test = baseTest\n  .extend('db', async ({}, { onCleanup }) => {\n    // db is created before `aroundEach` hook\n    const db = await createTestDatabase()\n    onCleanup(() => db.close())\n    return db\n  })\n\ntest.aroundEach(async (runTest, { db }) => {\n  await db.transaction(runTest)\n})\n\ntest('insert user', async ({ db }) => {\n  // called inside a transaction\n  await db.insert({ name: 'Alice' })\n})\n```\n\n## Helper for Better Stack Traces\n\nWhen a test fails inside a shared utility function, the stack trace usually points to the line inside that helper — not where it was called. This makes it harder to find which test actually failed, especially when the same helper is used across many tests.\n\n[`vi.defineHelper`](/api/vi#vi-definehelper) wraps a function so that Vitest removes its internals from the stack trace and points the error back to the call site instead:\n\n```ts\nimport { expect, test, vi } from 'vitest'\n\nconst assertPair = vi.defineHelper((a, b) => {\n  expect(a).toEqual(b) // 🙅‍♂️ error code block will NOT point to here\n})\n\ntest('example', () => {\n  assertPair('left', 'right') // 🙆 but point to here\n})\n```\n\nThis is especially useful for custom assertion libraries and reusable test utilities where the call site is more meaningful than the implementation.\n\n## `--detect-async-leaks` to Catch Leaks\n\nLeaked timers, handles, and unresolved async resources can make test suites flaky and hard to debug. Vitest 4.1 adds [`detectAsyncLeaks`](/config/detectasyncleaks) to help track these issues.\n\nYou can enable it via CLI:\n\n```sh\nvitest --detect-async-leaks\n```\n\nOr in config:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    detectAsyncLeaks: true,\n  },\n})\n```\n\nWhen enabled, Vitest uses `node:async_hooks` to report leaked async resources with source locations. Since this adds runtime overhead, it is best used while debugging.\n\n## `vscode` Improvements\n\nThe official [vscode extension](https://vitest.dev/vscode) received a large number of fixes and new features:\n\n- The extension no longer keeps a running process in the background unless you explicitly enable continuous run manually or via a new config option `watchOnStartup`. This reduces memory usage and eliminates the `maximumConfigs` config option.\n- The new \"Run Related Tests\" command runs tests that import the currently open file.\n- The new \"Toggle Continuous Run\" action is now available when clicking on the gutter icon.\n- The extension now supports [Deno runtime](https://deno.com/).\n- The extension cancels the test run sooner after clicking \"Stop\", when possible.\n- The extension displays the module load time inline next to each import statement, if you are using Vitest 4.1.\n\n<center>\n  <img src=\"/vscode-import-breakdown.png\" alt=\"An example of import breakdown in vscode\">\n  <sup>An example of import breakdown in vscode.</sup>\n</center>\n\n## GitHub Actions Job Summary\n\nThe built-in [`github-actions` reporter](/guide/reporters#github-actions-reporter) now automatically generates a [Job Summary](https://github.blog/news-insights/product-news/supercharging-github-actions-with-job-summaries/) with an overview of your test results. The summary includes test file and test case statistics, and highlights flaky tests that required retries — with permalink URLs linking test names directly to the relevant source lines on GitHub.\n\n<center>\n  <img alt=\"GitHub Actions Job Summary\" img-dark src=\"/github-actions-job-summary-dark.png\">\n  <img alt=\"GitHub Actions Job Summary\" img-light src=\"/github-actions-job-summary-light.png\">\n\n  <sup>An example of the job summary with flaky test details.</sup>\n</center>\n\nThe summary is enabled by default when running in GitHub Actions and writes to the path specified by `$GITHUB_STEP_SUMMARY`. No configuration is needed in most cases. To disable it or customize the output path:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['github-actions', {\n        jobSummary: {\n          enabled: false, // or set `outputPath` to customize where the summary is written\n        },\n      }],\n    ],\n  },\n})\n```\n\n## New `agent` Reporter to Reduce Token Usage\n\nAs AI coding agents become a common way to run tests, Vitest 4.1 introduces the [`agent` reporter](/guide/reporters#agent-reporter) — a minimal output mode designed to reduce token usage. It only displays failed tests and their errors, suppressing passed test output and console logs from passing tests.\n\nVitest automatically enables this reporter when it detects it's running inside an AI coding agent. The detection is powered by [`std-env`](https://github.com/unjs/std-env), which recognizes popular agent environments out of the box. You can also set the `AI_AGENT=copilot` (or any name) environment variable explicitly. No configuration needed — just run Vitest as usual:\n\n```sh\nAI_AGENT=copilot vitest\n```\n\nIf you configure custom reporters, the automatic detection is skipped, so add `'agent'` to the list manually if you want both.\n\n## New `mockThrow` API\n\nPreviously, making a mock throw required wrapping the error in a function: `mockImplementation(() => { throw new Error(...) })`. The new [`mockThrow`](/api/mock#mockthrow) and [`mockThrowOnce`](/api/mock#mockthrowonce) methods make this more concise and readable:\n\n```ts\nconst myMockFn = vi.fn()\nmyMockFn.mockThrow(new Error('error message'))\nmyMockFn() // throws Error<'error message'>\n```\n\n## Strict Mode in WebdriverIO and Preview\n\nLocating elements is now strict by default in `webdriverio` and `preview`, matching Playwright behavior.\n\nIf a locator resolves to multiple elements, Vitest throws a \"strict mode violation\" instead of silently picking one. This helps catch ambiguous queries early:\n\n```ts\nconst button = page.getByRole('button')\n\nawait button.click() // throws if multiple buttons match\nawait button.click({ strict: false }) // opt out and return first match\n```\n\n## Chai-style Mocking Assertions\n\nVitest already supports chai-style assertions like `eql`, `throw`, and `be`. This release extends that support to mock assertions, making it easier to migrate from Sinon-based test suites without rewriting every expectation:\n\n```ts\nimport { expect, vi } from 'vitest'\n\nconst fn = vi.fn()\n\nfn('example')\n\nexpect(fn).to.have.been.called // expect(fn).toHaveBeenCalled()\nexpect(fn).to.have.been.calledWith('example') // expect(fn).toHaveBeenCalledWith('example')\nexpect(fn).to.have.returned // expect(fn).toHaveReturned()\nexpect(fn).to.have.callCount(1) // expect(fn).toHaveBeenCalledTimes(1)\n```\n\n## Coverage `ignore start/stop` Ignore Hints\n\nYou can now completely ignore specific lines from code coverage using `ignore start/stop` comments.\nIn Vitest v3, this was supported by the `v8` provider, but not in v4.0 due to underlying dependency changes.\n\nDue to the community's request, we've now implemented it back ourselves and extended the support to both `v8` and `istanbul` providers.\n\n```ts\n/* istanbul ignore start -- @preserve */\nif (parameter) { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\nelse { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\n/* istanbul ignore stop -- @preserve */\n\nconsole.log('Included')\n\n/* v8 ignore start -- @preserve */\nif (parameter) { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\nelse { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\n/* v8 ignore stop -- @preserve */\n\nconsole.log('Included')\n```\n\nSee [Coverage | Ignoring Code](/guide/coverage.html#ignoring-code) for more examples.\n\n## Coverage For Changed Files Only\n\nIf you want to get code coverage only for the modified files, you can use [`coverage.changed`](/config/coverage.html#coverage-changed) to limit the file inclusion.\n\nCompared to the regular [`--changed`](/guide/cli.html#changed) flag, `--coverage.changed` allows you to still run all test files, but limit the coverage reporting only to the changed files.\nThis allows you to exclude unchanged files from coverage that `--changed` would otherwise include.\n\n## Coverage in HTML Reporter and Subpath Deployments\n\nCoverage HTML viewing now works reliably across UI mode, HTML reporter, and browser mode — including when deployed under a subpath. For custom coverage reporters, the new [`coverage.htmlDir`](/config/coverage#coverage-htmldir) option can be used to integrate their HTML output.\n\n## Acknowledgments\n\nVitest 4.1 is the result of countless hours by the [Vitest team](/team) and our contributors. We appreciate the individuals and companies sponsoring Vitest development. [Vladimir](https://github.com/sheremet-va) and [Hiroshi](https://github.com/hi-ogawa) are part of the [VoidZero](https://voidzero.dev) Team and are able to work on Vite and Vitest full-time, and [Ari](https://github.com/ariperkkio) can invest more time in Vitest thanks to support from [Chromatic](https://www.chromatic.com/). A big shout-out to [Zammad](https://zammad.com), and sponsors on [Vitest's GitHub Sponsors](https://github.com/sponsors/vitest-dev) and [Vitest's Open Collective](https://opencollective.com/vitest).\n"
  },
  {
    "path": "docs/blog/vitest-4.md",
    "content": "---\ntitle: Vitest 4.0 is out!\nauthor:\n  name: The Vitest Team\ndate: 2025-10-22\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vitest 4.0\n  - - meta\n    - property: og:image\n      content: https://vitest.dev/og-vitest-4.jpg\n  - - meta\n    - property: og:url\n      content: https://vitest.dev/blog/vitest-4\n  - - meta\n    - property: og:description\n      content: Vitest 4.0 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vitest 4.0 is out!\n\n_October 22, 2025_\n\n![Vitest 4 Announcement Cover Image](/og-vitest-4.jpg)\n\n## The next Vitest major is here\n\nToday, we are thrilled to announce Vitest 4!\n\nQuick links:\n\n- [Docs](/)\n- Translations: [简体中文](https://cn.vitest.dev/)\n- [Migration Guide](/guide/migration#vitest-4)\n- [GitHub Changelog](https://github.com/vitest-dev/vitest/releases/tag/v4.0.0)\n\nIf you've not used Vitest before, we suggest reading the [Getting Started](/guide/) and [Features](/guide/features) guides first.\n\nWe extend our gratitude to the over [640 contributors to Vitest Core](https://github.com/vitest-dev/vitest/graphs/contributors) and to the maintainers and contributors of Vitest integrations, tools, and translations who have helped us develop this new major release. We encourage you to get involved and help us improve Vitest for the entire ecosystem. Learn more at our [Contributing Guide](https://github.com/vitest-dev/vitest/blob/main/CONTRIBUTING.md).\n\nTo get started, we suggest helping [triage issues](https://github.com/vitest-dev/vitest/issues), [review PRs](https://github.com/vitest-dev/vitest/pulls), send failing tests PRs based on open issues, and support others in [Discussions](https://github.com/vitest-dev/vitest/discussions) and Vitest Land's [help forum](https://discord.com/channels/917386801235247114/1057959614160851024). If you'd like to talk to us, join our [Discord community](http://chat.vitest.dev/) and say hi on the [#contributing channel](https://discord.com/channels/917386801235247114/1057959614160851024).\n\nFor the latest news about the Vitest ecosystem and Vitest core, follow us on [Bluesky](https://bsky.app/profile/vitest.dev) or [Mastodon](https://webtoo.ls/@vitest).\n\nTo stay updated, keep an eye on the [VoidZero blog](https://voidzero.dev/blog) and subscribe to the [newsletter](https://voidzero.dev/newsletter).\n\n## Browser Mode is Stable\n\nWith this release we are removing the `experimental` tag from [Browser Mode](/guide/browser/). To make it possible, we had to introduce some changes to the public API.\n\nTo define a provider, you now need to install a separate package: [`@vitest/browser-playwright`](https://npmx.dev/package/@vitest/browser-playwright), [`@vitest/browser-webdriverio`](https://npmx.dev/package/@vitest/browser-webdriverio), or [`@vitest/browser-preview`](https://npmx.dev/package/@vitest/browser-preview). This makes it simpler to work with custom options and doesn't require adding `/// <reference` comments anymore.\n\n::: code-group\n```ts [playwright]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright' // [!code ++]\n/// <reference path=\"@vitest/browser/providers/playwright\" /> // [!code --]\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: 'playwright', // [!code --]\n      provider: playwright({ // [!code ++]\n        launchOptions: { // [!code ++]\n          slowMo: 100, // [!code ++]\n        }, // [!code ++]\n      }), // [!code ++]\n      instances: [\n        {\n          browser: 'chromium',\n          launch: { // [!code --]\n            slowMo: 100, // [!code --]\n          }, // [!code --]\n        },\n      ],\n    },\n  },\n})\n```\n```ts [webdriverio]\nimport { defineConfig } from 'vitest/config'\nimport { webdriverio } from '@vitest/browser-webdriverio' // [!code ++]\n/// <reference path=\"@vitest/browser/providers/webdriverio\" /> // [!code --]\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: 'webdriverio', // [!code --]\n      provider: webdriverio({ // [!code ++]\n        capabilities: { // [!code ++]\n          browserVersion: '82', // [!code ++]\n        }, // [!code ++]\n      }),\n      instances: [\n        {\n          browser: 'chrome',\n          capabilities: { // [!code --]\n            browserVersion: '82', // [!code --]\n          }, // [!code --]\n        },\n      ],\n    },\n  },\n})\n```\n```ts [preview]\nimport { defineConfig } from 'vitest/config'\nimport { preview } from '@vitest/browser-preview' // [!code ++]\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: 'preview', // [!code --]\n      provider: preview(), // [!code ++]\n      instances: [\n        { browser: 'chrome' },\n      ],\n    },\n  },\n})\n```\n:::\n\nThe context is no longer imported from `@vitest/browser/context` (but it will keep working until the next major version for better compatibility with tools that did not update yet), now just import from `vitest/browser`:\n\n```ts\nimport { page } from '@vitest/browser/context' // [!code --]\nimport { page } from 'vitest/browser' // [!code ++]\n\ntest('example', async () => {\n  await page.getByRole('button').click()\n})\n```\n\nWith these changes, the `@vitest/browser` package can be removed from your dependencies. It is now included in every provider package automatically.\n\n## Visual Regression Testing\n\nVitest 4 adds support for [Visual Regression testing](/guide/browser/visual-regression-testing.md) in Browser Mode. We will continue to iterate on this feature to improve the experience.\n\nVisual regression testing in Vitest can be done through the\n[`toMatchScreenshot` assertion](/api/browser/assertions.html#tomatchscreenshot):\n\n```ts\nimport { expect, test } from 'vitest'\nimport { page } from 'vitest/browser'\n\ntest('hero section looks correct', async () => {\n  // ...the rest of the test\n\n  // capture and compare screenshot\n  await expect(page.getByTestId('hero')).toMatchScreenshot('hero-section')\n})\n```\n\nVitest captures screenshots of your UI components and pages, then compares them against reference images to detect unintended visual changes.\n\nAlongside this feature, Vitest also introduces a `toBeInViewport` matcher. It allows you to check if an element is currently in viewport with [IntersectionObserver API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).\n\n```ts\n// A specific element is in viewport.\nawait expect.element(page.getByText('Welcome')).toBeInViewport()\n\n// 50% of a specific element should be in viewport\nawait expect.element(page.getByText('To')).toBeInViewport({ ratio: 0.5 })\n```\n\n## Playwright Traces Support\n\nVitest 4 supports generating [Playwright Traces](/guide/browser/trace-view). To enable tracing, you need to set the [`trace`](/config/browser/trace) option in the `test.browser` configuration or pass down `--browser.trace=on` option (`off`, `on-first-retry`, `on-all-retries`, `retain-on-failure` are also available).\n\n![Playwright Traces interface](/traces.png)\n\nThe traces are available in reporters as [annotations](/guide/test-annotations). For example, in the HTML reporter, you can find the link to the trace file in the test details. To open the trace file, you can use the [Playwright Trace Viewer](https://playwright.dev/docs/trace-viewer).\n\n## Locator Improvements\n\nThe `frameLocator` method returns a `FrameLocator` instance that can be used to find elements inside the iframe.\nVitest now supports a new [`page.frameLocator`](/api/browser/context#framelocator) API (only with `playwright` provider).\n\n```ts\nconst frame = page.frameLocator(\n  page.getByTestId('iframe')\n)\n\nawait frame.getByText('Hello World').click() // ✅\nawait frame.click() // ❌ Not available\n```\n\nEvery locator now exposes a `length` property, allowing them to be used with `toHaveLength` matcher automatically:\n\n```ts\nawait expect.element(page.getByText('Item')).toHaveLength(3)\n```\n\n## Improved Debugging\n\nThe [vscode extension](https://vitest.dev/vscode) now supports \"Debug Test\" button when running browser tests.\n\nIf you prefer configuring the debug options yourself, you can start Vitest with the `--inspect` flag (available with `playwright` and `webdriverio`) and connect to [DevTools](chrome://inspect/) manually. In this case Vitest will also disable the new [`trackUnhandledErrors`](/config/browser/trackunhandlederrors) option automatically.\n\n## Type-Aware Hooks\n\nWhen using `test.extend` with lifecycle hooks like `beforeEach` and `afterEach`, you can now reference them directly on the returned `test` object:\n\n```ts\nimport { test as baseTest } from 'vitest'\n\nconst test = baseTest.extend<{\n  todos: number[]\n}>({\n  todos: async ({}, use) => {\n    await use([])\n  },\n})\n\n// Unlike global hooks, these hooks are aware of the extended context\ntest.beforeEach(({ todos }) => {\n  todos.push(1)\n})\n\ntest.afterEach(({ todos }) => {\n  console.log(todos)\n})\n```\n\n## `expect.assert`\n\nVitest has always exported [Chai's `assert`](https://www.chaijs.com/api/assert/), but sometimes using it was inconvenient because many modules have the same export.\n\nNow Vitest exposes the same method on `expect` for an easy access. This is especially useful if you need to narrow down the type, since `expect.to*` methods do not support that:\n\n```ts\ninterface Cat {\n  __type: 'Cat'\n  mew(): void\n}\ninterface Dog {\n  __type: 'Dog'\n  bark(): void\n}\ntype Animal = Cat | Dog\n\nconst animal: Animal = { __type: 'Dog', bark: () => {} }\n\nexpect.assert(animal.__type === 'Dog')\n// does not show a type error!\nexpect(animal.bark()).toBeUndefined()\n```\n\n## `expect.schemaMatching`\n\nVitest 4 introduces a new asymmetric matcher called `expect.schemaMatching`. It accepts a [Standard Schema v1](https://standardschema.dev/) object and validates values against it, passing the assertion when the value conforms to the schema.\n\nAs a reminder, asymmetric matchers can be used in all `expect` matchers that check equality, including `toEqual`, `toStrictEqual`, `toMatchObject`, `toContainEqual`, `toThrow`, `toHaveBeenCalledWith`, `toHaveReturnedWith` and `toHaveBeenResolvedWith`.\n\n```ts\nimport { expect, test } from 'vitest'\nimport { z } from 'zod'\nimport * as v from 'valibot'\nimport { type } from 'arktype'\n\ntest('email validation', () => {\n  const user = { email: 'john@example.com' }\n\n  // using Zod\n  expect(user).toEqual({\n    email: expect.schemaMatching(z.string().email()),\n  })\n\n  // using Valibot\n  expect(user).toEqual({\n    email: expect.schemaMatching(v.pipe(v.string(), v.email()))\n  })\n\n  // using ArkType\n  expect(user).toEqual({\n    email: expect.schemaMatching(type('string.email')),\n  })\n})\n```\n\n## Reporter Updates\n\nThe `basic` reporter was removed. You can use the `default` reporter with `summary: false` instead:\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['default', { summary: false }],\n    ],\n  },\n})\n```\n\nThe [`default`](/guide/reporters#default-reporter) reporter now only prints tests in a tree if there is only one test file running. If you want to always see tests printed as a tree, you can use a new [`tree`](/guide/reporters#tree-reporter) reporter.\n\nThe [`verbose`](/guide/reporters#verbose-reporter) reporter now always prints tests one by one when they are finished. Previously, this was done only in CI, and locally `verbose` would behave mostly like a `default` reporter. If you prefer to keep the old behaviour, you can conditionally use the `verbose` reporter only in CI by updating the config:\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    reporter: process.env.CI ? 'verbose' : 'default',\n  },\n})\n```\n\n## New API Methods\n\nVitest 4 comes with new advanced public [API methods](/api/advanced/vitest):\n\n- [`experimental_parseSpecifications`](/api/advanced/vitest#parsespecification) allows you to parse a test file without running it.\n- [`watcher`](/api/advanced/vitest#watcher) exposes methods that can be used when you disable the default Vitest watcher.\n- [`enableCoverage`](/api/advanced/vitest#enablecoverage) and [`disableCoverage`](/api/advanced/vitest#disablecoverage) allow you to enable and disable coverage dynamically.\n- [`getSeed`](/api/advanced/vitest#enablecoverage) returns the seed value, if tests run at random.\n- [`getGlobalTestNamePattern`](/api/advanced/vitest#getglobaltestnamepattern) returns the current test name pattern.\n- [`waitForTestRunEnd`](/api/advanced/vitest#waitfortestrunend) returns a promise that resolves when all tests have finished running.\n\n## Breaking changes\n\nVitest 4 has a few breaking changes that could affect you, so we advise reviewing the detailed [Migration Guide](/guide/migration#vitest-4) before upgrading.\n\nThe complete list of changes is at the [Vitest 4 Changelog](https://github.com/vitest-dev/vitest/releases/tag/v4.0.0).\n\n## Acknowledgments\n\nVitest 4 is the result of countless hours by the [Vitest team](/team) and our contributors. We appreciate the individuals and companies sponsoring Vitest development. [Vladimir](https://github.com/sheremet-va) and [Hiroshi](https://github.com/hi-ogawa) are part of the [VoidZero](https://voidzero.dev) Team and are able to work on Vite and Vitest full-time, and [Ari](https://github.com/ariperkkio) can invest more time in Vitest thanks to [StackBlitz](https://stackblitz.com/). A shout-out to [NuxtLabs](https://nuxtlabs.com), [Zammad](https://zammad.com), and sponsors on [Vitest's GitHub Sponsors](https://github.com/sponsors/vitest-dev) and [Vitest's Open Collective](https://opencollective.com/vitest).\n"
  },
  {
    "path": "docs/blog.md",
    "content": "---\nsidebar: false\neditLink: false\noutline: false\n---\n\n<script setup>\nimport BlogIndex from './.vitepress/components/BlogIndex.vue'\n</script>\n\n# Latest From the Vitest Blog\n\n<BlogIndex />\n"
  },
  {
    "path": "docs/config/alias.md",
    "content": "---\ntitle: alias | Config\noutline: deep\n---\n\n# alias\n\n- **Type:** `Record<string, string> | Array<{ find: string | RegExp, replacement: string, customResolver?: ResolverFunction | ResolverObject }>`\n\nDefine custom aliases when running inside tests. They will be merged with aliases from `resolve.alias`.\n\n::: warning\nVitest uses Vite SSR primitives to run tests which has [certain pitfalls](https://vitejs.dev/guide/ssr.html#ssr-externals).\n\n1. Aliases affect only modules imported directly with an `import` keyword by an [inlined](/config/server#server-deps-inline) module (all source code is inlined by default).\n2. Vitest does not support aliasing `require` calls.\n3. If you are aliasing an external dependency (e.g., `react` -> `preact`), you may want to alias the actual `node_modules` packages instead to make it work for externalized dependencies. Both [Yarn](https://classic.yarnpkg.com/en/docs/cli/add/#toc-yarn-add-alias) and [pnpm](https://pnpm.io/aliases/) support aliasing via the `npm:` prefix.\n:::\n"
  },
  {
    "path": "docs/config/allowonly.md",
    "content": "---\ntitle: allowOnly | Config\noutline: deep\n---\n\n# allowOnly\n\n- **Type**: `boolean`\n- **Default**: `!process.env.CI`\n- **CLI:** `--allowOnly`, `--allowOnly=false`\n\nBy default, Vitest does not permit tests marked with the [`only`](/api/test#test-only) flag in Continuous Integration (CI) environments. Conversely, in local development environments, Vitest allows these tests to run.\n\n::: info\nVitest uses [`std-env`](https://npmx.dev/package/std-env) package to detect the environment.\n:::\n\nYou can customize this behavior by explicitly setting the `allowOnly` option to either `true` or `false`.\n\n::: code-group\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    allowOnly: true,\n  },\n})\n```\n```bash [CLI]\nvitest --allowOnly\n```\n:::\n\nWhen enabled, Vitest will not fail the test suite if tests marked with [`only`](/api/test#test-only) are detected, including in CI environments.\n\nWhen disabled, Vitest will fail the test suite if tests marked with [`only`](/api/test#test-only) are detected, including in local development environments.\n"
  },
  {
    "path": "docs/config/api.md",
    "content": "---\ntitle: api | Config\noutline: deep\n---\n\n# api\n\n- **Type:** `boolean | number | object`\n- **Default:** `false`\n- **CLI:** `--api`, `--api.port`, `--api.host`, `--api.strictPort`\n\nListen to port and serve API for [the UI](/guide/ui) or [browser server](/guide/browser/). When set to `true`, the default port is `51204`.\n\n## api.allowWrite <Version>4.1.0</Version> {#api-allowwrite}\n\n- **Type:** `boolean`\n- **Default:** `true` if not exposed to the network, `false` otherwise\n\nVitest server can save test files or snapshot files via the API. This allows anyone who can connect to the API the ability to run any arbitrary code on your machine.\n\n::: danger SECURITY ADVICE\nVitest does not expose the API to the internet by default and only listens on `localhost`. However if `host` is manually exposed to the network, anyone who connects to it can run arbitrary code on your machine, unless `api.allowWrite` and `api.allowExec` are set to `false`.\n\nIf the host is set to anything other than `localhost` or `127.0.0.1`, Vitest will set `api.allowWrite` and `api.allowExec` to `false` by default. This means that any write operations (like changing the code in the UI) will not work. However, if you understand the security implications, you can override them.\n:::\n\n## api.allowExec <Version>4.1.0</Version> {#api-allowexec}\n\n- **Type:** `boolean`\n- **Default:** `true` if not exposed to the network, `false` otherwise\n\nAllows running any test file via the API. See the security advice in [`api.allowWrite`](#api-allowwrite).\n"
  },
  {
    "path": "docs/config/attachmentsdir.md",
    "content": "---\ntitle: attachmentsDir | Config\noutline: deep\n---\n\n# attachmentsDir\n\n- **Type:** `string`\n- **Default:** `'.vitest-attachments'`\n\nDirectory path for storing attachments created by [`context.annotate`](/guide/test-context#annotate) relative to the project root.\n"
  },
  {
    "path": "docs/config/bail.md",
    "content": "---\ntitle: bail | Config\noutline: deep\n---\n\n# bail\n\n- **Type:** `number`\n- **Default:** `0`\n- **CLI**: `--bail=<value>`\n\nStop test execution when given number of tests have failed.\n\nBy default Vitest will run all of your test cases even if some of them fail. This may not be desired for CI builds where you are only interested in 100% successful builds and would like to stop test execution as early as possible when test failures occur. The `bail` option can be used to speed up CI runs by preventing it from running more tests when failures have occurred.\n"
  },
  {
    "path": "docs/config/benchmark.md",
    "content": "---\ntitle: benchmark | Config\noutline: deep\n---\n\n# benchmark <Experimental /> {#benchmark}\n\n- **Type:** `{ include?, exclude?, ... }`\n\nOptions used when running `vitest bench`.\n\n## benchmark.include\n\n- **Type:** `string[]`\n- **Default:** `['**/*.{bench,benchmark}.?(c|m)[jt]s?(x)']`\n\nInclude globs for benchmark test files\n\n## benchmark.exclude\n\n- **Type:** `string[]`\n- **Default:** `['node_modules', 'dist', '.idea', '.git', '.cache']`\n\nExclude globs for benchmark test files\n\n## benchmark.includeSource\n\n- **Type:** `string[]`\n- **Default:** `[]`\n\nInclude globs for in-source benchmark test files. This option is similar to [`includeSource`](/config/include-source).\n\nWhen defined, Vitest will run all matched files with `import.meta.vitest` inside.\n\n## benchmark.reporters\n\n- **Type:** `Arrayable<BenchmarkBuiltinReporters | Reporter>`\n- **Default:** `'default'`\n\nCustom reporter for output. Can contain one or more built-in report names, reporter instances, and/or paths to custom reporters.\n\n## benchmark.outputFile\n\nDeprecated in favor of `benchmark.outputJson`.\n\n## benchmark.outputJson {#benchmark-outputJson}\n\n- **Type:** `string | undefined`\n- **Default:** `undefined`\n\nA file path to store the benchmark result, which can be used for `--compare` option later.\n\nFor example:\n\n```sh\n# save main branch's result\ngit checkout main\nvitest bench --outputJson main.json\n\n# change a branch and compare against main\ngit checkout feature\nvitest bench --compare main.json\n```\n\n## benchmark.compare {#benchmark-compare}\n\n- **Type:** `string | undefined`\n- **Default:** `undefined`\n\nA file path to a previous benchmark result to compare against current runs.\n"
  },
  {
    "path": "docs/config/browser/api.md",
    "content": "---\ntitle: browser.api | Config\noutline: deep\n---\n\n# browser.api\n\n- **Type:** `number | object`\n- **Default:** `63315`\n- **CLI:** `--browser.api=63315`, `--browser.api.port=1234, --browser.api.host=example.com`\n\nConfigure options for Vite server that serves code in the browser. Does not affect [`test.api`](/config/api) option. By default, Vitest assigns port `63315` to avoid conflicts with the development server, allowing you to run both in parallel.\n\n## api.allowWrite <Version>4.1.0</Version> {#api-allowwrite}\n\n- **Type:** `boolean`\n- **Default:** `true` if not exposed to the network, `false` otherwise\n\nVitest saves [annotation attachments](/guide/test-annotations), [artifacts](/api/advanced/artifacts) and [snapshots](/guide/snapshot) by receiving a WebSocket connection from the browser. This allows anyone who can connect to the API write any arbitrary code on your machine within the root of your project (configured by [`fs.allow`](https://vite.dev/config/server-options#server-fs-allow)).\n\nIf browser server is not exposed to the internet (the host is `localhost`), this should not be a problem, so the default value in that case is `true`. If you override the host, Vitest will set `allowWrite` to `false` by default to prevent potentially harmful writes.\n\n## api.allowExec <Version>4.1.0</Version> {#api-allowexec}\n\n- **Type:** `boolean`\n- **Default:** `true` if not exposed to the network, `false` otherwise\n\nAllows running any test file via the UI. This only applies to the interactive elements (and the server code behind them) in the [UI](/guide/ui) that can run the code. If UI is disabled, this has no effect. See [`api.allowExec`](/config/api#api-allowexec) for more information.\n"
  },
  {
    "path": "docs/config/browser/commands.md",
    "content": "---\ntitle: browser.commands | Config\noutline: deep\n---\n\n# browser.commands\n\n- **Type:** `Record<string, BrowserCommand>`\n- **Default:** `{ readFile, writeFile, ... }`\n\nCustom [commands](/api/browser/commands) that can be imported during browser tests from `vitest/browser`.\n"
  },
  {
    "path": "docs/config/browser/connecttimeout.md",
    "content": "---\ntitle: browser.connectTimeout | Config\noutline: deep\n---\n\n# browser.connectTimeout\n\n- **Type:** `number`\n- **Default:** `60_000`\n\nThe timeout in milliseconds. If connection to the browser takes longer, the test suite will fail.\n\n::: info\nThis is the time it should take for the browser to establish the WebSocket connection with the Vitest server. In normal circumstances, this timeout should never be reached.\n:::\n"
  },
  {
    "path": "docs/config/browser/detailspanelposition.md",
    "content": "---\ntitle: browser.detailsPanelPosition | Config\noutline: deep\n---\n\n# browser.detailsPanelPosition\n\n- **Type:** `'right' | 'bottom'`\n- **Default:** `'right'`\n- **CLI:** `--browser.detailsPanelPosition=bottom`, `--browser.detailsPanelPosition=right`\n\nControls the default position of the details panel in the Vitest UI when running browser tests.\n\n- `'right'` - Shows the details panel on the right side with a horizontal split between the browser viewport and the details panel.\n- `'bottom'` - Shows the details panel at the bottom with a vertical split between the browser viewport and the details panel.\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      detailsPanelPosition: 'bottom', // or 'right'\n    },\n  },\n})\n```\n\n## Example\n\n::: tabs\n== bottom\n<center>\n  <img alt=\"Vitest UI with details at the bottom\" img-light src=\"/ui/light-ui-details-bottom.png\">\n  <img alt=\"Vitest UI with details at the bottom\" img-dark src=\"/ui/dark-ui-details-bottom.png\">\n</center>\n== right\n<center>\n  <img alt=\"Vitest UI with details at the right side\" img-light src=\"/ui/light-ui-details-right.png\">\n  <img alt=\"Vitest UI with details at the right side\" img-dark src=\"/ui/dark-ui-details-right.png\">\n</center>\n:::\n"
  },
  {
    "path": "docs/config/browser/enabled.md",
    "content": "---\ntitle: browser.enabled | Config\n---\n\n# browser.enabled\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **CLI:** `--browser`, `--browser.enabled=false`\n\nEnabling this flag makes Vitest run all tests in a [browser](/guide/browser/) by default. If you are configuring other browser options via the CLI, you can use `--browser.enabled` alongside them instead of `--browser`:\n\n```sh\nvitest --browser.enabled --browser.headless\n```\n\n::: warning\nTo enable [Browser Mode](/guide/browser/), you must also specify the [`provider`](/config/browser/provider) and at least one [`instance`](/config/browser/instances). Available providers:\n\n- [playwright](/config/browser/playwright)\n- [webdriverio](/config/browser/webdriverio)\n- [preview](/config/browser/preview)\n:::\n\n## Example\n\n```js{7} [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  },\n})\n```\n\nIf you use TypeScript, the `browser` field in `instances` provides autocompletion based on your provider.\n"
  },
  {
    "path": "docs/config/browser/expect.md",
    "content": "---\ntitle: browser.expect | Config\noutline: deep\n---\n\n# browser.expect\n\n- **Type:** `ExpectOptions`\n\n## browser.expect.toMatchScreenshot\n\nDefault options for the\n[`toMatchScreenshot` assertion](/api/browser/assertions.html#tomatchscreenshot).\nThese options will be applied to all screenshot assertions.\n\n::: tip\nSetting global defaults for screenshot assertions helps maintain consistency\nacross your test suite and reduces repetition in individual tests. You can still\noverride these defaults at the assertion level when needed for specific test cases.\n:::\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      expect: {\n        toMatchScreenshot: {\n          comparatorName: 'pixelmatch',\n          comparatorOptions: {\n            threshold: 0.2,\n            allowedMismatchedPixels: 100,\n          },\n          resolveScreenshotPath: ({ arg, browserName, ext, testFileName }) =>\n            `custom-screenshots/${testFileName}/${arg}-${browserName}${ext}`,\n        },\n      },\n    },\n  },\n})\n```\n\n[All options available in the `toMatchScreenshot` assertion](/api/browser/assertions#options)\ncan be configured here. Additionally, two path resolution functions are\navailable: `resolveScreenshotPath` and `resolveDiffPath`.\n\n## browser.expect.toMatchScreenshot.resolveScreenshotPath\n\n- **Type:** `(data: PathResolveData) => string`\n- **Default output:** `` `${root}/${testFileDirectory}/${screenshotDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}` ``\n\nA function to customize where reference screenshots are stored. The function\nreceives an object with the following properties:\n\n- `arg: string`\n\n  Path **without** extension, sanitized and relative to the test file.\n\n  This comes from the arguments passed to `toMatchScreenshot`; if called\n  without arguments this will be the auto-generated name.\n\n  ```ts\n  test('calls `onClick`', () => {\n    expect(locator).toMatchScreenshot()\n    // arg = \"calls-onclick-1\"\n  })\n\n  expect(locator).toMatchScreenshot('foo/bar/baz.png')\n  // arg = \"foo/bar/baz\"\n\n  expect(locator).toMatchScreenshot('../foo/bar/baz.png')\n  // arg = \"foo/bar/baz\"\n  ```\n\n- `ext: string`\n\n  Screenshot extension, with leading dot.\n\n  This can be set through the arguments passed to `toMatchScreenshot`, but\n  the value will fall back to `'.png'` if an unsupported extension is used.\n\n- `browserName: string`\n\n  The instance's browser name.\n\n- `platform: NodeJS.Platform`\n\n  The value of\n  [`process.platform`](https://nodejs.org/docs/v22.16.0/api/process.html#processplatform).\n\n- `screenshotDirectory: string`\n\n  The value provided to\n  [`browser.screenshotDirectory`](/config/browser/screenshotdirectory),\n  if none is provided, its default value.\n\n- `root: string`\n\n  Absolute path to the project's [`root`](/config/root).\n\n- `testFileDirectory: string`\n\n  Path to the test file, relative to the project's [`root`](/config/root).\n\n- `testFileName: string`\n\n  The test's filename.\n\n- `testName: string`\n\n  The [`test`](/api/test)'s name, including parent\n  [`describe`](/api/describe), sanitized.\n\n- `attachmentsDir: string`\n\n  The value provided to [`attachmentsDir`](/config/attachmentsdir), if none is\n  provided, its default value.\n\nFor example, to group screenshots by browser:\n\n```ts\nresolveScreenshotPath: ({ arg, browserName, ext, root, testFileName }) =>\n  `${root}/screenshots/${browserName}/${testFileName}/${arg}${ext}`\n```\n\n## browser.expect.toMatchScreenshot.resolveDiffPath\n\n- **Type:** `(data: PathResolveData) => string`\n- **Default output:** `` `${root}/${attachmentsDir}/${testFileDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}` ``\n\nA function to customize where diff images are stored when screenshot comparisons\nfail. Receives the same data object as\n[`resolveScreenshotPath`](#browser-expect-tomatchscreenshot-resolvescreenshotpath).\n\nFor example, to store diffs in a subdirectory of attachments:\n\n```ts\nresolveDiffPath: ({ arg, attachmentsDir, browserName, ext, root, testFileName }) =>\n  `${root}/${attachmentsDir}/screenshot-diffs/${testFileName}/${arg}-${browserName}${ext}`\n```\n\n## browser.expect.toMatchScreenshot.comparators\n\n- **Type:** `Record<string, Comparator>`\n\nRegister custom screenshot comparison algorithms, like [SSIM](https://en.wikipedia.org/wiki/Structural_similarity_index_measure) or other perceptual similarity metrics.\n\nTo create a custom comparator, you need to register it in your config. If using TypeScript, declare its options in the `ScreenshotComparatorRegistry` interface.\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\n// 1. Declare the comparator's options type\ndeclare module 'vitest/browser' {\n  interface ScreenshotComparatorRegistry {\n    myCustomComparator: {\n      sensitivity?: number\n      ignoreColors?: boolean\n    }\n  }\n}\n\n// 2. Implement the comparator\nexport default defineConfig({\n  test: {\n    browser: {\n      expect: {\n        toMatchScreenshot: {\n          comparators: {\n            myCustomComparator: async (\n              reference,\n              actual,\n              {\n                createDiff, // always provided by Vitest\n                sensitivity = 0.01,\n                ignoreColors = false,\n              }\n            ) => {\n              // ...algorithm implementation\n              return { pass, diff, message }\n            },\n          },\n        },\n      },\n    },\n  },\n})\n```\n\nThen use it in your tests:\n\n```ts\nawait expect(locator).toMatchScreenshot({\n  comparatorName: 'myCustomComparator',\n  comparatorOptions: {\n    sensitivity: 0.08,\n    ignoreColors: true,\n  },\n})\n```\n\n**Comparator Function Signature:**\n\n```ts\ntype Comparator<Options> = (\n  reference: {\n    metadata: { height: number; width: number }\n    data: TypedArray\n  },\n  actual: {\n    metadata: { height: number; width: number }\n    data: TypedArray\n  },\n  options: {\n    createDiff: boolean\n  } & Options\n) => Promise<{\n  pass: boolean\n  diff: TypedArray | null\n  message: string | null\n}> | {\n  pass: boolean\n  diff: TypedArray | null\n  message: string | null\n}\n```\n\nThe `reference` and `actual` images are decoded using the appropriate codec (currently only PNG). The `data` property is a flat `TypedArray` (`Buffer`, `Uint8Array`, or `Uint8ClampedArray`) containing pixel data in RGBA format:\n\n- **4 bytes per pixel**: red, green, blue, alpha (from `0` to `255` each)\n- **Row-major order**: pixels are stored left-to-right, top-to-bottom\n- **Total length**: `width × height × 4` bytes\n- **Alpha channel**: always present. Images without transparency have alpha values set to `255` (fully opaque)\n\n::: tip Performance Considerations\nThe `createDiff` option indicates whether a diff image is needed. During [stable screenshot detection](/guide/browser/visual-regression-testing#how-visual-tests-work), Vitest calls comparators with `createDiff: false` to avoid unnecessary work.\n\n**Respect this flag to keep your tests fast**.\n:::\n\n::: warning Handle Missing Options\nThe `options` parameter in `toMatchScreenshot()` is optional, so users might not provide all your comparator options. Always make them optional with default values:\n\n```ts\nmyCustomComparator: (\n  reference,\n  actual,\n  { createDiff, threshold = 0.1, maxDiff = 100 },\n) => {\n  // ...comparison logic\n}\n```\n:::\n"
  },
  {
    "path": "docs/config/browser/headless.md",
    "content": "---\ntitle: browser.headless | Config\noutline: deep\n---\n\n# browser.headless\n\n- **Type:** `boolean`\n- **Default:** `process.env.CI`\n- **CLI:** `--browser.headless`, `--browser.headless=false`\n\nRun the browser in a `headless` mode. If you are running Vitest in CI, it will be enabled by default.\n"
  },
  {
    "path": "docs/config/browser/instances.md",
    "content": "---\ntitle: browser.instances | Config\noutline: deep\n---\n\n# browser.instances\n\n- **Type:** `BrowserConfig`\n- **Default:** `[]`\n\nDefines multiple browser setups. Every config has to have at least a `browser` field.\n\nYou can specify most of the [project options](/config/) (not marked with a <CRoot /> icon) and some of the `browser` options like `browser.testerHtmlPath`.\n\n::: warning\nEvery browser config inherits options from the root config:\n\n```ts{3,9} [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    setupFile: ['./root-setup-file.js'],\n    browser: {\n      enabled: true,\n      testerHtmlPath: './custom-path.html',\n      instances: [\n        {\n          // will have both setup files: \"root\" and \"browser\"\n          setupFile: ['./browser-setup-file.js'],\n          // implicitly has \"testerHtmlPath\" from the root config // [!code warning]\n          // testerHtmlPath: './custom-path.html', // [!code warning]\n        },\n      ],\n    },\n  },\n})\n```\n\nFor more examples, refer to the [\"Multiple Setups\" guide](/guide/browser/multiple-setups).\n:::\n\nList of available `browser` options:\n\n- `browser` (the name of the browser)\n- [`headless`](/config/browser/headless)\n- [`locators`](/config/browser/locators)\n- [`viewport`](/config/browser/viewport)\n- [`testerHtmlPath`](/config/browser/testerhtmlpath)\n- [`screenshotDirectory`](/config/browser/screenshotdirectory)\n- [`screenshotFailures`](/config/browser/screenshotfailures)\n- [`provider`](/config/browser/provider)\n\nUnder the hood, Vitest transforms these instances into separate [test projects](/api/advanced/test-project) sharing a single Vite server for better caching performance.\n"
  },
  {
    "path": "docs/config/browser/isolate.md",
    "content": "---\ntitle: browser.isolate | Config\noutline: deep\n---\n\n# browser.isolate <Deprecated />\n\n- **Type:** `boolean`\n- **Default:** the same as [`--isolate`](/config/isolate)\n- **CLI:** `--browser.isolate`, `--browser.isolate=false`\n\nRun every test in a separate iframe.\n\n::: danger DEPRECATED\nThis option is deprecated. Use [`isolate`](/config/isolate) instead.\n:::\n"
  },
  {
    "path": "docs/config/browser/locators.md",
    "content": "---\ntitle: browser.locators | Config\noutline: deep\n---\n\n# browser.locators\n\nOptions for built-in [browser locators](/api/browser/locators).\n\n## browser.locators.testIdAttribute\n\n- **Type:** `string`\n- **Default:** `data-testid`\n\nAttribute used to find elements with `getByTestId` locator.\n"
  },
  {
    "path": "docs/config/browser/orchestratorscripts.md",
    "content": "---\ntitle: browser.orchestratorScripts | Config\noutline: deep\n---\n\n# browser.orchestratorScripts\n\n- **Type:** `BrowserScript[]`\n- **Default:** `[]`\n\nCustom scripts that should be injected into the orchestrator HTML before test iframes are initiated. This HTML document only sets up iframes and doesn't actually import your code.\n\nThe script `src` and `content` will be processed by Vite plugins. Script should be provided in the following shape:\n\n```ts\nexport interface BrowserScript {\n  /**\n   * If \"content\" is provided and type is \"module\", this will be its identifier.\n   *\n   * If you are using TypeScript, you can add `.ts` extension here for example.\n   * @default `injected-${index}.js`\n   */\n  id?: string\n  /**\n   * JavaScript content to be injected. This string is processed by Vite plugins if type is \"module\".\n   *\n   * You can use `id` to give Vite a hint about the file extension.\n   */\n  content?: string\n  /**\n   * Path to the script. This value is resolved by Vite so it can be a node module or a file path.\n   */\n  src?: string\n  /**\n   * If the script should be loaded asynchronously.\n   */\n  async?: boolean\n  /**\n   * Script type.\n   * @default 'module'\n   */\n  type?: string\n}\n```\n"
  },
  {
    "path": "docs/config/browser/playwright.md",
    "content": "# Configuring Playwright\n\nTo run tests using playwright, you need to install the [`@vitest/browser-playwright`](https://npmx.dev/package/@vitest/browser-playwright) npm package and specify its `playwright` export in the `test.browser.provider` property of your config:\n\n```ts [vitest.config.js]\nimport { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright(),\n      instances: [{ browser: 'chromium' }]\n    },\n  },\n})\n```\n\nYou can configure the [`launchOptions`](https://playwright.dev/docs/api/class-browsertype#browser-type-launch), [`connectOptions`](https://playwright.dev/docs/api/class-browsertype#browser-type-connect) and [`contextOptions`](https://playwright.dev/docs/api/class-browser#browser-new-context) when calling `playwright` at the top level or inside instances:\n\n```ts{7-14,21-26} [vitest.config.js]\nimport { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      // shared provider options between all instances\n      provider: playwright({\n        launchOptions: {\n          slowMo: 50,\n          channel: 'chrome-beta',\n        },\n        actionTimeout: 5_000,\n      }),\n      instances: [\n        { browser: 'chromium' },\n        {\n          browser: 'firefox',\n          // overriding options only for a single instance\n          // this will NOT merge options with the parent one\n          provider: playwright({\n            launchOptions: {\n              firefoxUserPrefs: {\n                'browser.startup.homepage': 'https://example.com',\n              },\n            },\n          })\n        }\n      ],\n    },\n  },\n})\n```\n\n::: warning\nUnlike Playwright test runner, Vitest opens a _single_ page to run all tests that are defined in the same file. This means that isolation is restricted to a single test file, not to every individual test.\n:::\n\n## launchOptions\n\nThese options are directly passed down to `playwright[browser].launch` command. You can read more about the command and available arguments in the [Playwright documentation](https://playwright.dev/docs/api/class-browsertype#browser-type-launch).\n\n::: warning\nVitest will ignore `launch.headless` option. Instead, use [`test.browser.headless`](/config/browser/headless).\n\nNote that Vitest will push debugging flags to `launch.args` if [`--inspect`](/guide/cli#inspect) is enabled.\n:::\n\n## connectOptions\n\nThese options are directly passed down to `playwright[browser].connect` command. You can read more about the command and available arguments in the [Playwright documentation](https://playwright.dev/docs/api/class-browsertype#browser-type-connect).\n\nUse `connectOptions.wsEndpoint` to connect to an existing Playwright server instead of launching browsers locally. This is useful for running browsers in Docker, in CI, or on a remote machine.\n\n::: warning\n\nVitest forwards `launchOptions` to Playwright server via the `x-playwright-launch-options` header. This works only if the remote Playwright server supports this header, for example when using the `playwright run-server` CLI.\n\n:::\n\n::: details Example: Running a Playwright Server in Docker\nTo run browsers in a Docker container (see [Playwright Docker guide](https://playwright.dev/docs/docker#remote-connection)):\n\nStart a Playwright server using Docker Compose:\n\n```yaml [docker-compose.yml]\nservices:\n  playwright:\n    image: mcr.microsoft.com/playwright:v1.58.1-noble\n    command: /bin/sh -c \"npx -y playwright@1.58.1 run-server --port 6677 --host 0.0.0.0\"\n    init: true\n    ipc: host\n    user: pwuser\n    ports:\n      - '6677:6677'\n```\n\n```sh\ndocker compose up -d\n```\n\nThen configure Vitest to connect to it. The [`exposeNetwork`](https://playwright.dev/docs/api/class-browsertype#browser-type-connect-option-expose-network) option lets the containerized browser reach Vitest's dev server on the host:\n\n```ts [vitest.config.ts]\nimport { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright({\n        connectOptions: {\n          wsEndpoint: 'ws://127.0.0.1:6677/',\n          exposeNetwork: '<loopback>',\n        },\n      }),\n      instances: [\n        { browser: 'chromium' },\n        { browser: 'firefox' },\n        { browser: 'webkit' },\n      ],\n    },\n  },\n})\n```\n:::\n\n## contextOptions\n\nVitest creates a new context for every test file by calling [`browser.newContext()`](https://playwright.dev/docs/api/class-browsercontext). You can configure this behaviour by specifying [custom arguments](https://playwright.dev/docs/api/class-browser#browser-new-context).\n\n::: tip\nNote that the context is created for every _test file_, not every _test_ like in playwright test runner.\n:::\n\n::: warning\nVitest always sets `ignoreHTTPSErrors` to `true` in case your server is served via HTTPS and `serviceWorkers` to `'allow'` to support module mocking via [MSW](https://mswjs.io).\n\nIt is also recommended to use [`test.browser.viewport`](/config/browser/headless) instead of specifying it here as it will be lost when tests are running in headless mode.\n:::\n\n## `actionTimeout`\n\n- **Default:** no timeout\n\nThis value configures the default timeout it takes for Playwright to wait until all accessibility checks pass and [the action](/api/browser/interactivity) is actually done.\n\nYou can also configure the action timeout per-action:\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\n\nawait userEvent.click(page.getByRole('button'), {\n  timeout: 1_000,\n})\n```\n\n## `persistentContext` <Version>4.1.0</Version> {#persistentcontext}\n\n- **Type:** `boolean | string`\n- **Default:** `false`\n\nWhen enabled, Vitest uses Playwright's [persistent context](https://playwright.dev/docs/api/class-browsertype#browser-type-launch-persistent-context) instead of a regular browser context. This allows browser state (cookies, localStorage, DevTools settings, etc.) to persist between test runs.\n\n::: warning\nThis option is ignored when running tests in parallel (e.g. when headless with [`fileParallelism`](/config/fileparallelism) enalbed) since persistent context cannot be shared across parallel sessions.\n:::\n\n- When set to `true`, the user data is stored in `./node_modules/.cache/vitest-playwright-user-data`\n- When set to a string, the value is used as the path to the user data directory\n\n```ts [vitest.config.js]\nimport { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright({\n        persistentContext: true,\n        // or specify a custom directory:\n        // persistentContext: './my-browser-data',\n      }),\n      instances: [{ browser: 'chromium' }],\n    },\n  },\n})\n```\n"
  },
  {
    "path": "docs/config/browser/preview.md",
    "content": "# Configuring Preview\n\n::: warning\nThe `preview` provider's main functionality is to show tests in a real browser environment. However, it does not support advanced browser automation features like multiple browser instances or headless mode. For more complex scenarios, consider using [Playwright](/config/browser/playwright) or [WebdriverIO](/config/browser/webdriverio).\n:::\n\nTo see your tests running in a real browser, you need to install the [`@vitest/browser-preview`](https://npmx.dev/package/@vitest/browser-preview) npm package and specify its `preview` export in the `test.browser.provider` property of your config:\n\n```ts [vitest.config.js]\nimport { preview } from '@vitest/browser-preview'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: preview(),\n      instances: [{ browser: 'chromium' }]\n    },\n  },\n})\n```\n\nThis will open a new browser window using your default browser to run the tests. You can configure which browser to use by setting the `browser` property in the `instances` array. Vitest will try to open that browser automatically, but it might not work in some environments. In that case, you can manually open the provided URL in your desired browser.\n\n## Differences with Other Providers\n\nThe preview provider has some limitations compared to other providers like [Playwright](/config/browser/playwright) or [WebdriverIO](/config/browser/webdriverio):\n\n- It does not support headless mode; the browser window will always be visible.\n- It does not support multiple instances of the same browser; each instance must use a different browser.\n- It does not support advanced browser capabilities or options; you can only specify the browser name.\n- It does not support CDP (Chrome DevTools Protocol) commands or other low-level browser interactions. Unlike Playwright or WebdriverIO, the [`userEvent`](/api/browser/interactivity) API is just re-exported from [`@testing-library/user-event`](https://npmx.dev/package/@testing-library/user-event) and does not have any special integration with the browser.\n"
  },
  {
    "path": "docs/config/browser/provider.md",
    "content": "---\ntitle: browser.provider | Config\noutline: deep\n---\n\n# browser.provider {#browser-provider}\n\n- **Type:** `BrowserProviderOption`\n\nThe return value of the provider factory. You can import the factory from `@vitest/browser-<provider-name>` or make your own provider:\n\n```ts{8-10}\nimport { playwright } from '@vitest/browser-playwright'\nimport { webdriverio } from '@vitest/browser-webdriverio'\nimport { preview } from '@vitest/browser-preview'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright(),\n      provider: webdriverio(),\n      provider: preview(),\n    },\n  },\n})\n```\n\nTo configure how provider initializes the browser, you can pass down options to the factory function:\n\n```ts{7-13,20-26}\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      // shared provider options between all instances\n      provider: playwright({\n        launchOptions: {\n          slowMo: 50,\n          channel: 'chrome-beta',\n        },\n        actionTimeout: 5_000,\n      }),\n      instances: [\n        { browser: 'chromium' },\n        {\n          browser: 'firefox',\n          // overriding options only for a single instance\n          // this will NOT merge options with the parent one\n          provider: playwright({\n            launchOptions: {\n              firefoxUserPrefs: {\n                'browser.startup.homepage': 'https://example.com',\n              },\n            },\n          })\n        }\n      ],\n    },\n  },\n})\n```\n\n## Custom Provider <Badge type=\"danger\">advanced</Badge>\n\n::: danger ADVANCED API\nThe custom provider API is highly experimental and can change between patches. If you just need to run tests in a browser, use the [`browser.instances`](/config/browser/instances) option instead.\n:::\n\n```ts\nexport interface BrowserProvider {\n  name: string\n  mocker?: BrowserModuleMocker\n  readonly initScripts?: string[]\n  /**\n   * @experimental opt-in into file parallelisation\n   */\n  supportsParallelism: boolean\n  getCommandsContext: (sessionId: string) => Record<string, unknown>\n  openPage: (sessionId: string, url: string) => Promise<void>\n  getCDPSession?: (sessionId: string) => Promise<CDPSession>\n  close: () => Awaitable<void>\n}\n```\n"
  },
  {
    "path": "docs/config/browser/screenshotdirectory.md",
    "content": "---\ntitle: browser.screenshotDirectory | Config\noutline: deep\n---\n\n# browser.screenshotDirectory\n\n- **Type:** `string`\n- **Default:** `__screenshots__` in the test file directory\n\nPath to the screenshots directory relative to the `root`.\n"
  },
  {
    "path": "docs/config/browser/screenshotfailures.md",
    "content": "---\ntitle: browser.screenshotFailures | Config\noutline: deep\n---\n\n# browser.screenshotFailures\n\n- **Type:** `boolean`\n- **Default:** `!browser.ui`\n\nShould Vitest take screenshots if the test fails.\n"
  },
  {
    "path": "docs/config/browser/testerhtmlpath.md",
    "content": "---\ntitle: browser.testerHtmlPath | Config\noutline: deep\n---\n\n# browser.testerHtmlPath\n\n- **Type:** `string`\n\nA path to the HTML entry point. Can be relative to the root of the project. This file will be processed with [`transformIndexHtml`](https://vite.dev/guide/api-plugin#transformindexhtml) hook.\n"
  },
  {
    "path": "docs/config/browser/trace.md",
    "content": "---\ntitle: browser.trace | Config\noutline: deep\n---\n\n# browser.trace\n\n- **Type:** `'on' | 'off' | 'on-first-retry' | 'on-all-retries' | 'retain-on-failure' | object`\n- **CLI:** `--browser.trace=on`, `--browser.trace=retain-on-failure`\n- **Default:** `'off'`\n\nCapture a trace of your browser test runs. You can preview traces with [Playwright Trace Viewer](https://trace.playwright.dev/).\n\nThis options supports the following values:\n\n- `'on'` - capture trace for all tests. (not recommended as it's performance heavy)\n- `'off'` - do not capture traces.\n- `'on-first-retry'` - capture trace only when retrying the test for the first time.\n- `'on-all-retries'` - capture trace on every retry of the test.\n- `'retain-on-failure'` - capture trace only for tests that fail. This will automatically delete traces for tests that pass.\n- `object` - an object with the following shape:\n\n```ts\ninterface TraceOptions {\n  mode: 'on' | 'off' | 'on-first-retry' | 'on-all-retries' | 'retain-on-failure'\n  /**\n   * The directory where all traces will be stored. By default, Vitest\n   * stores all traces in `__traces__` folder close to the test file.\n   */\n  tracesDir?: string\n  /**\n   * Whether to capture screenshots during tracing. Screenshots are used to build a timeline preview.\n   * @default true\n   */\n  screenshots?: boolean\n  /**\n   * If this option is true tracing will\n   * - capture DOM snapshot on every action\n   * - record network activity\n   * @default true\n   */\n  snapshots?: boolean\n}\n```\n\n::: danger WARNING\nThis option is supported only by the [**playwright**](/config/browser/playwright) provider.\n:::\n"
  },
  {
    "path": "docs/config/browser/trackunhandlederrors.md",
    "content": "---\ntitle: browser.trackUnhandledErrors | Config\noutline: deep\n---\n\n# browser.trackUnhandledErrors\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nEnables tracking uncaught errors and exceptions so they can be reported by Vitest.\n\nIf you need to hide certain errors, it is recommended to use [`onUnhandledError`](/config/onunhandlederror) option instead.\n\nDisabling this will completely remove all Vitest error handlers, which can help debugging with the \"Pause on exceptions\" checkbox turned on.\n"
  },
  {
    "path": "docs/config/browser/ui.md",
    "content": "---\ntitle: browser.ui | Config\noutline: deep\n---\n\n# browser.ui\n\n- **Type:** `boolean`\n- **Default:** `!isCI`\n- **CLI:** `--browser.ui=false`\n\nShould Vitest UI be injected into the page. By default, injects UI iframe during development.\n"
  },
  {
    "path": "docs/config/browser/viewport.md",
    "content": "---\ntitle: browser.viewport | Config\noutline: deep\n---\n\n# browser.viewport\n\n- **Type:** `{ width, height }`\n- **Default:** `414x896`\n\nDefault iframe's viewport.\n"
  },
  {
    "path": "docs/config/browser/webdriverio.md",
    "content": "# Configuring WebdriverIO\n\n::: info Playwright vs WebdriverIO\nIf you do not already use WebdriverIO in your project, we recommend starting with [Playwright](/config/browser/playwright) as it is easier to configure and has more flexible API.\n:::\n\nTo run tests using WebdriverIO, you need to install the [`@vitest/browser-webdriverio`](https://npmx.dev/package/@vitest/browser-webdriverio) npm package and specify its `webdriverio` export in the `test.browser.provider` property of your config:\n\n```ts [vitest.config.js]\nimport { webdriverio } from '@vitest/browser-webdriverio'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: webdriverio(),\n      instances: [{ browser: 'chrome' }]\n    },\n  },\n})\n```\n\nYou can configure all the parameters that [`remote`](https://webdriver.io/docs/api/modules/#remoteoptions-modifier) function accepts:\n\n```ts{8-12,19-25} [vitest.config.js]\nimport { webdriverio } from '@vitest/browser-webdriverio'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      // shared provider options between all instances\n      provider: webdriverio({\n        capabilities: {\n          browserVersion: '82',\n        },\n      }),\n      instances: [\n        { browser: 'chrome' },\n        {\n          browser: 'firefox',\n          // overriding options only for a single instance\n          // this will NOT merge options with the parent one\n          provider: webdriverio({\n            capabilities: {\n              'moz:firefoxOptions': {\n                args: ['--disable-gpu'],\n              },\n            },\n          })\n        },\n      ],\n    },\n  },\n})\n```\n\nYou can find most available options in the [WebdriverIO documentation](https://webdriver.io/docs/configuration/). Note that Vitest will ignore all test runner options because we only use `webdriverio`'s browser capabilities.\n\n::: tip\nMost useful options are located on `capabilities` object. WebdriverIO allows nested capabilities, but Vitest will ignore those options because we rely on a different mechanism to spawn several browsers.\n\nNote that Vitest will ignore `capabilities.browserName` — use [`test.browser.instances.browser`](/config/browser/instances#browser) instead.\n:::\n"
  },
  {
    "path": "docs/config/cache.md",
    "content": "---\ntitle: cache | Config\noutline: deep\n---\n\n# cache <CRoot />\n\n- **Type**: `false`\n- **CLI**: `--no-cache`, `--cache=false`\n\nUse this option if you want to disable the cache feature. At the moment Vitest stores cache for test results to run the longer and failed tests first.\n\nThe cache directory is controlled by the Vite's [`cacheDir`](https://vitejs.dev/config/shared-options.html#cachedir) option:\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  cacheDir: 'custom-folder/.vitest'\n})\n```\n\nYou can limit the directory only for Vitest by using `process.env.VITEST`:\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  cacheDir: process.env.VITEST ? 'custom-folder/.vitest' : undefined\n})\n```\n"
  },
  {
    "path": "docs/config/chaiconfig.md",
    "content": "---\ntitle: chaiConfig | Config\noutline: deep\n---\n\n# chaiConfig\n\n- **Type:** `{ includeStack?, showDiff?, truncateThreshold? }`\n- **Default:** `{ includeStack: false, showDiff: true, truncateThreshold: 40 }`\n\nEquivalent to [Chai config](https://github.com/chaijs/chai/blob/4.x.x/lib/chai/config.js).\n\n## chaiConfig.includeStack\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nInfluences whether stack trace is included in Assertion error message. Default of false suppresses stack trace in the error message.\n\n## chaiConfig.showDiff\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nInfluences whether or not the `showDiff` flag should be included in the thrown AssertionErrors. `false` will always be `false`; `true` will be true when the assertion has requested a diff to be shown.\n\n## chaiConfig.truncateThreshold\n\n- **Type:** `number`\n- **Default:** `40`\n\nSets length threshold for actual and expected values in assertion errors. If this threshold is exceeded, for example for large data structures, the value is replaced with something like `[ Array(3) ]` or `{ Object (prop1, prop2) }`. Set it to `0` if you want to disable truncating altogether.\n\nThis config option affects truncating values in `test.each` titles and inside the assertion error message.\n"
  },
  {
    "path": "docs/config/clearmocks.md",
    "content": "---\ntitle: clearMocks | Config\noutline: deep\n---\n\n# clearMocks\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nShould Vitest automatically call [`vi.clearAllMocks()`](/api/vi#vi-clearallmocks) before each test.\n\nThis will clear mock history without affecting mock implementations.\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    clearMocks: true,\n  },\n})\n```\n\n::: warning\nBe aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will clear the mock history for all mocks, including those currently being used by other tests in progress.\n:::\n"
  },
  {
    "path": "docs/config/coverage.md",
    "content": "---\ntitle: coverage | Config\noutline: deep\n---\n\n# coverage <CRoot /> {#coverage}\n\nYou can use [`v8`](/guide/coverage.html#v8-provider), [`istanbul`](/guide/coverage.html#istanbul-provider) or [a custom coverage solution](/guide/coverage#custom-coverage-provider) for coverage collection.\n\nYou can provide coverage options to CLI with dot notation:\n\n```sh\nnpx vitest --coverage.enabled --coverage.provider=istanbul\n```\n\n::: warning\nIf you are using coverage options with dot notation, don't forget to specify `--coverage.enabled`. Do not provide a single `--coverage` option in that case.\n:::\n\n## coverage.provider\n\n- **Type:** `'v8' | 'istanbul' | 'custom'`\n- **Default:** `'v8'`\n- **CLI:** `--coverage.provider=<provider>`\n\nUse `provider` to select the tool for coverage collection.\n\n## coverage.enabled\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.enabled`, `--coverage.enabled=false`\n\nEnables coverage collection. Can be overridden using `--coverage` CLI option.\n\n## coverage.include\n\n- **Type:** `string[]`\n- **Default:** Files that were imported during test run\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.include=<pattern>`, `--coverage.include=<pattern1> --coverage.include=<pattern2>`\n\nList of files included in coverage as glob patterns. By default only files covered by tests are included.\n\nIt is recommended to pass file extensions in the pattern.\n\nSee [Including and excluding files from coverage report](/guide/coverage.html#including-and-excluding-files-from-coverage-report) for examples.\n\n## coverage.exclude\n\n- **Type:** `string[]`\n- **Default:** : `[]`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.exclude=<path>`, `--coverage.exclude=<path1> --coverage.exclude=<path2>`\n\nList of files excluded from coverage as glob patterns.\n\nSee [Including and excluding files from coverage report](/guide/coverage.html#including-and-excluding-files-from-coverage-report) for examples.\n\n## coverage.clean\n\n- **Type:** `boolean`\n- **Default:** `true`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.clean`, `--coverage.clean=false`\n\nClean coverage results before running tests\n\n## coverage.cleanOnRerun\n\n- **Type:** `boolean`\n- **Default:** `true`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.cleanOnRerun`, `--coverage.cleanOnRerun=false`\n\nClean coverage report on watch rerun. Set to `false` to preserve coverage results from previous run in watch mode.\n\n## coverage.reportsDirectory\n\n- **Type:** `string`\n- **Default:** `'./coverage'`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.reportsDirectory=<path>`\n\n::: warning\nVitest will delete this directory before running tests if `coverage.clean` is enabled (default value).\n:::\n\nDirectory to write coverage report to.\n\n## coverage.reporter\n\n- **Type:** `string | string[] | [string, {}][]`\n- **Default:** `['text', 'html', 'clover', 'json']`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.reporter=<reporter>`, `--coverage.reporter=<reporter1> --coverage.reporter=<reporter2>`\n\nCoverage reporters to use. See [istanbul documentation](https://istanbul.js.org/docs/advanced/alternative-reporters/) for detailed list of all reporters. See [`@types/istanbul-reports`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/276d95e4304b3670eaf6e8e5a7ea9e265a14e338/types/istanbul-reports/index.d.ts) for details about reporter specific options.\n\nThe reporter has three different types:\n\n- A single reporter: `{ reporter: 'html' }`\n- Multiple reporters without options: `{ reporter: ['html', 'json'] }`\n- A single or multiple reporters with reporter options:\n  <!-- eslint-skip -->\n  ```ts\n  {\n    reporter: [\n      ['lcov', { 'projectRoot': './src' }],\n      ['json', { 'file': 'coverage.json' }],\n      ['text']\n    ]\n  }\n  ```\n\nYou can also pass custom coverage reporters. See [Guide - Custom Coverage Reporter](/guide/coverage#custom-coverage-reporter) for more information.\n\n<!-- eslint-skip -->\n```ts\n  {\n    reporter: [\n      // Specify reporter using name of the NPM package\n      '@vitest/custom-coverage-reporter',\n      ['@vitest/custom-coverage-reporter', { someOption: true }],\n\n      // Specify reporter using local path\n      '/absolute/path/to/custom-reporter.cjs',\n      ['/absolute/path/to/custom-reporter.cjs', { someOption: true }],\n    ]\n  }\n```\n\nYou can check your coverage report in Vitest UI: check [Vitest UI Coverage](/guide/coverage#vitest-ui) for more details.\n\n## coverage.reportOnFailure {#coverage-reportonfailure}\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.reportOnFailure`, `--coverage.reportOnFailure=false`\n\nGenerate coverage report even when tests fail.\n\n## coverage.allowExternal\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.allowExternal`, `--coverage.allowExternal=false`\n\nCollect coverage of files outside the [project `root`](/config/root).\n\n## coverage.excludeAfterRemap\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.excludeAfterRemap`, `--coverage.excludeAfterRemap=false`\n\nApply exclusions again after coverage has been remapped to original sources.\nThis is useful when your source files are transpiled and may contain source maps of non-source files.\n\nUse this option when you are seeing files that show up in report even if they match your `coverage.exclude` patterns.\n\n## coverage.skipFull\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.skipFull`, `--coverage.skipFull=false`\n\nDo not show files with 100% statement, branch, and function coverage.\n\n## coverage.thresholds\n\nOptions for coverage thresholds.\n\nIf a threshold is set to a positive number, it will be interpreted as the minimum percentage of coverage required. For example, setting the lines threshold to `90` means that 90% of lines must be covered.\n\nIf a threshold is set to a negative number, it will be treated as the maximum number of uncovered items allowed. For example, setting the lines threshold to `-10` means that no more than 10 lines may be uncovered.\n\n<!-- eslint-skip -->\n```ts\n{\n  coverage: {\n    thresholds: {\n      // Requires 90% function coverage\n      functions: 90,\n\n      // Require that no more than 10 lines are uncovered\n      lines: -10,\n    }\n  }\n}\n```\n\n### coverage.thresholds.lines\n\n- **Type:** `number`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.thresholds.lines=<number>`\n\nGlobal threshold for lines.\n\n### coverage.thresholds.functions\n\n- **Type:** `number`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.thresholds.functions=<number>`\n\nGlobal threshold for functions.\n\n### coverage.thresholds.branches\n\n- **Type:** `number`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.thresholds.branches=<number>`\n\nGlobal threshold for branches.\n\n### coverage.thresholds.statements\n\n- **Type:** `number`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.thresholds.statements=<number>`\n\nGlobal threshold for statements.\n\n### coverage.thresholds.perFile\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.thresholds.perFile`, `--coverage.thresholds.perFile=false`\n\nCheck thresholds per file.\n\n### coverage.thresholds.autoUpdate\n\n- **Type:** `boolean | function`\n- **Default:** `false`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.thresholds.autoUpdate=<boolean>`\n\nUpdate all threshold values `lines`, `functions`, `branches` and `statements` to configuration file when current coverage is better than the configured thresholds.\nThis option helps to maintain thresholds when coverage is improved.\n\nYou can also pass a function for formatting the updated threshold values:\n\n<!-- eslint-skip -->\n```ts\n{\n  coverage: {\n    thresholds: {\n      // Update thresholds without decimals\n      autoUpdate: (newThreshold) => Math.floor(newThreshold),\n\n      // 95.85 -> 95\n      functions: 95,\n    }\n  }\n}\n```\n\n### coverage.thresholds.100\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.thresholds.100`, `--coverage.thresholds.100=false`\n\nSets global thresholds to 100.\nShortcut for `--coverage.thresholds.lines 100 --coverage.thresholds.functions 100 --coverage.thresholds.branches 100 --coverage.thresholds.statements 100`.\n\n### coverage.thresholds[glob-pattern]\n\n- **Type:** `{ statements?: number functions?: number branches?: number lines?: number }`\n- **Default:** `undefined`\n- **Available for providers:** `'v8' | 'istanbul'`\n\nSets thresholds for files matching the glob pattern.\n\n::: tip NOTE\nVitest counts all files, including those covered by glob-patterns, into the global coverage thresholds.\nThis is different from Jest behavior.\n:::\n\n<!-- eslint-skip -->\n```ts\n{\n  coverage: {\n    thresholds: {\n      // Thresholds for all files\n      functions: 95,\n      branches: 70,\n\n      // Thresholds for matching glob pattern\n      'src/utils/**.ts': {\n        statements: 95,\n        functions: 90,\n        branches: 85,\n        lines: 80,\n      },\n\n      // Files matching this pattern will only have lines thresholds set.\n      // Global thresholds are not inherited.\n      '**/math.ts': {\n        lines: 100,\n      }\n    }\n  }\n}\n```\n\n### coverage.thresholds[glob-pattern].100\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **Available for providers:** `'v8' | 'istanbul'`\n\nSets thresholds to 100 for files matching the glob pattern.\n\n<!-- eslint-skip -->\n```ts\n{\n  coverage: {\n    thresholds: {\n      // Thresholds for all files\n      functions: 95,\n      branches: 70,\n\n      // Thresholds for matching glob pattern\n      'src/utils/**.ts': { 100: true },\n      '**/math.ts': { 100: true }\n    }\n  }\n}\n```\n\n## coverage.ignoreClassMethods\n\n- **Type:** `string[]`\n- **Default:** `[]`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.ignoreClassMethods=<method>`\n\nSet to array of class method names to ignore for coverage.\nSee [istanbul documentation](https://github.com/istanbuljs/nyc#ignoring-methods) for more information.\n\n## coverage.watermarks\n\n- **Type:**\n<!-- eslint-skip -->\n```ts\n{\n  statements?: [number, number],\n  functions?: [number, number],\n  branches?: [number, number],\n  lines?: [number, number]\n}\n```\n\n- **Default:**\n<!-- eslint-skip -->\n```ts\n{\n  statements: [50, 80],\n  functions: [50, 80],\n  branches: [50, 80],\n  lines: [50, 80]\n}\n```\n\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.watermarks.statements=50,80`, `--coverage.watermarks.branches=50,80`\n\nWatermarks for statements, lines, branches and functions. See [istanbul documentation](https://github.com/istanbuljs/nyc#high-and-low-watermarks) for more information.\n\n## coverage.processingConcurrency\n\n- **Type:** `boolean`\n- **Default:** `Math.min(20, os.availableParallelism?.() ?? os.cpus().length)`\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.processingConcurrency=<number>`\n\nConcurrency limit used when processing the coverage results.\n\n## coverage.customProviderModule\n\n- **Type:** `string`\n- **Available for providers:** `'custom'`\n- **CLI:** `--coverage.customProviderModule=<path or module name>`\n\nSpecifies the module name or path for the custom coverage provider module. See [Guide - Custom Coverage Provider](/guide/coverage#custom-coverage-provider) for more information.\n\n## coverage.htmlDir\n\n- **Type:** `string`\n- **Default:** Automatically inferred from `html`, `html-spa`, or `lcov` coverage reporters\n- **CLI:** `--coverage.htmlDir=<path>`\n\nDirectory of HTML coverage output to be served in [Vitest UI](/guide/ui) and [HTML reporter](/guide/reporters.html#html-reporter).\n\nThis is automatically configured when using builtin coverage reporters that produce HTML output (`html`, `html-spa`, and `lcov`). Use this option to override with a custom coverage reporting location when using custom coverage reporters.\n\nNote that setting this option does not change where coverage HTML report is generated. Configure the `coverage.reporter` option to change the directory instead.\n\n## coverage.changed\n\n- **Type:** `boolean | string`\n- **Default:** `false` (inherits from `test.changed`)\n- **Available for providers:** `'v8' | 'istanbul'`\n- **CLI:** `--coverage.changed`, `--coverage.changed=<commit/branch>`\n\nCollect coverage only for files changed since a specified commit or branch. When set to `true`, it uses staged and unstaged changes.\n"
  },
  {
    "path": "docs/config/css.md",
    "content": "---\ntitle: css | Config\noutline: deep\n---\n\n# css\n\n- **Type**: `boolean | { include?, exclude?, modules? }`\n\nConfigure if CSS should be processed. When excluded, CSS files will be replaced with empty strings to bypass the subsequent processing. CSS Modules will return a proxy to not affect runtime.\n\n::: warning\nThis option is not applied to [browser tests](/guide/browser/).\n:::\n\n## css.include\n\n- **Type**: `RegExp | RegExp[]`\n- **Default**: `[]`\n\nRegExp pattern for files that should return actual CSS and will be processed by Vite pipeline.\n\n:::tip\nTo process all CSS files, use `/.+/`.\n:::\n\n## css.exclude\n\n- **Type**: `RegExp | RegExp[]`\n- **Default**: `[]`\n\nRegExp pattern for files that will return an empty CSS file.\n\n## css.modules\n\n- **Type**: `{ classNameStrategy? }`\n- **Default**: `{}`\n\n### css.modules.classNameStrategy\n\n- **Type**: `'stable' | 'scoped' | 'non-scoped'`\n- **Default**: `'stable'`\n\nIf you decide to process CSS files, you can configure if class names inside CSS modules should be scoped. You can choose one of the options:\n\n- `stable`: class names will be generated as `_${name}_${hashedFilename}`, which means that generated class will stay the same, if CSS content is changed, but will change, if the name of the file is modified, or file is moved to another folder. This setting is useful, if you use snapshot feature.\n- `scoped`: class names will be generated as usual, respecting `css.modules.generateScopedName` method, if you have one and CSS processing is enabled. By default, filename will be generated as `_${name}_${hash}`, where hash includes filename and content of the file.\n- `non-scoped`: class names will not be hashed.\n\n::: warning\nBy default, Vitest exports a proxy, bypassing CSS Modules processing. If you rely on CSS properties on your classes, you have to enable CSS processing using `include` option.\n:::\n"
  },
  {
    "path": "docs/config/dangerouslyignoreunhandlederrors.md",
    "content": "---\ntitle: dangerouslyIgnoreUnhandledErrors | Config\noutline: deep\n---\n\n# dangerouslyIgnoreUnhandledErrors <CRoot />\n\n- **Type**: `boolean`\n- **Default**: `false`\n- **CLI:**\n  - `--dangerouslyIgnoreUnhandledErrors`\n  - `--dangerouslyIgnoreUnhandledErrors=false`\n\nIf this option is set to `true`, Vitest will not fail the test run if there are unhandled errors. Note that built-in reporters will still report them.\n\nIf you want to filter out certain errors conditionally, use [`onUnhandledError`](/config/onunhandlederror) callback instead.\n\n## Example\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    dangerouslyIgnoreUnhandledErrors: true,\n  },\n})\n```\n"
  },
  {
    "path": "docs/config/deps.md",
    "content": "---\ntitle: deps | Config\noutline: deep\n---\n\n# deps\n\n- **Type:** `{ optimizer?, ... }`\n\nHandling for dependencies resolution.\n\n## deps.optimizer {#deps-optimizer}\n\n- **Type:** `{ ssr?, client? }`\n- **See also:** [Dep Optimization Options](https://vitejs.dev/config/dep-optimization-options.html)\n\nEnable dependency optimization. If you have a lot of tests, this might improve their performance.\n\nWhen Vitest encounters the external library listed in `include`, it will be bundled into a single file using esbuild and imported as a whole module. This is good for several reasons:\n\n- Importing packages with a lot of imports is expensive. By bundling them into one file we can save a lot of time\n- Importing UI libraries is expensive because they are not meant to run inside Node.js\n- Your `alias` configuration is now respected inside bundled packages\n- Code in your tests is running closer to how it's running in the browser\n\nBe aware that only packages in `deps.optimizer?.[mode].include` option are bundled (some plugins populate this automatically, like Svelte). You can read more about available options in [Vite](https://vitejs.dev/config/dep-optimization-options.html) docs (Vitest doesn't support `disable` and `noDiscovery` options). By default, Vitest uses `optimizer.client` for `jsdom` and `happy-dom` environments, and `optimizer.ssr` for `node` and `edge` environments.\n\nThis options also inherits your `optimizeDeps` configuration (for web Vitest will extend `optimizeDeps`, for ssr - `ssr.optimizeDeps`). If you redefine `include`/`exclude` option in `deps.optimizer` it will extend your `optimizeDeps` when running tests. Vitest automatically removes the same options from `include`, if they are listed in `exclude`.\n\n::: tip\nYou will not be able to edit your `node_modules` code for debugging, since the code is actually located in your `cacheDir` or `test.cache.dir` directory. If you want to debug with `console.log` statements, edit it directly or force rebundling with `deps.optimizer?.[mode].force` option.\n:::\n\n### deps.optimizer.{mode}.enabled\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nEnable dependency optimization.\n\n## deps.client  {#deps-client}\n\n- **Type:** `{ transformAssets?, ... }`\n\nOptions that are applied to external files when the environment is set to `client`. By default, `jsdom` and `happy-dom` use `client` environment, while `node` and `edge` environments use `ssr`, so these options will have no affect on files inside those environments.\n\nUsually, files inside `node_modules` are externalized, but these options also affect files in [`server.deps.external`](/config/server#server-deps-external).\n\n### deps.client.transformAssets\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nShould Vitest process assets (.png, .svg, .jpg, etc) files and resolve them like Vite does in the browser.\n\nThis module will have a default export equal to the path to the asset, if no query is specified.\n\n::: warning\nAt the moment, this option only works with [`vmThreads`](/config/pool#vmthreads) and [`vmForks`](/config/pool#vmforks) pools.\n:::\n\n### deps.client.transformCss\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nShould Vitest process CSS (.css, .scss, .sass, etc) files and resolve them like Vite does in the browser.\n\nIf CSS files are disabled with [`css`](/config/css) options, this option will just silence `ERR_UNKNOWN_FILE_EXTENSION` errors.\n\n::: warning\nAt the moment, this option only works with [`vmThreads`](/config/pool#vmthreads) and [`vmForks`](/config/pool#vmforks) pools.\n:::\n\n### deps.client.transformGlobPattern\n\n- **Type:** `RegExp | RegExp[]`\n- **Default:** `[]`\n\nRegexp pattern to match external files that should be transformed.\n\nBy default, files inside `node_modules` are externalized and not transformed, unless it's CSS or an asset, and corresponding option is not disabled.\n\n::: warning\nAt the moment, this option only works with [`vmThreads`](/config/pool#vmthreads) and [`vmForks`](/config/pool#vmforks) pools.\n:::\n\n## deps.interopDefault\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nInterpret CJS module's default as named exports. Some dependencies only bundle CJS modules and don't use named exports that Node.js can statically analyze when a package is imported using `import` syntax instead of `require`. When importing such dependencies in Node environment using named exports, you will see this error:\n\n```\nimport { read } from 'fs-jetpack';\n         ^^^^\nSyntaxError: Named export 'read' not found. The requested module 'fs-jetpack' is a CommonJS module, which may not support all module.exports as named exports.\nCommonJS modules can always be imported via the default export.\n```\n\nVitest doesn't do static analysis, and cannot fail before your running code, so you will most likely see this error when running tests, if this feature is disabled:\n\n```\nTypeError: createAsyncThunk is not a function\nTypeError: default is not a function\n```\n\nBy default, Vitest assumes you are using a bundler to bypass this and will not fail, but you can disable this behaviour manually, if your code is not processed.\n\n## deps.moduleDirectories\n\n- **Type:** `string[]`\n- **Default**: `['node_modules']`\n\nA list of directories that should be treated as module directories. This config option affects the behavior of [`vi.mock`](/api/vi#vi-mock): when no factory is provided and the path of what you are mocking matches one of the `moduleDirectories` values, Vitest will try to resolve the mock by looking for a `__mocks__` folder in the [root](/config/root) of the project.\n\nThis option will also affect if a file should be treated as a module when externalizing dependencies. By default, Vitest imports external modules with native Node.js bypassing Vite transformation step.\n\nSetting this option will _override_ the default, if you wish to still search `node_modules` for packages include it along with any other options:\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    deps: {\n      moduleDirectories: ['node_modules', path.resolve('../../packages')],\n    }\n  },\n})\n```\n"
  },
  {
    "path": "docs/config/detectasyncleaks.md",
    "content": "---\ntitle: detectAsyncLeaks | Config\noutline: deep\n---\n\n# detectAsyncLeaks\n\n- **Type:** `boolean`\n- **CLI:** `--detectAsyncLeaks`, `--detect-async-leaks`\n- **Default:** `false`\n\n::: warning\nEnabling this option will make your tests run much slower. Use only when debugging or developing tests.\n:::\n\nDetect asynchronous resources leaking from the test file.\nUses [`node:async_hooks`](https://nodejs.org/api/async_hooks.html) to track creation of async resources. If a resource is not cleaned up, it will be logged after tests have finished.\n\nFor example if your code has `setTimeout` calls that execute the callback after tests have finished, you will see following error:\n\n```sh\n⎯⎯⎯⎯⎯⎯⎯⎯ Async Leaks 1 ⎯⎯⎯⎯⎯⎯⎯⎯\n\nTimeout leaking in test/checkout-screen.test.tsx\n 26|\n 27|   useEffect(() => {\n 28|     setTimeout(() => setWindowWidth(window.innerWidth), 150)\n   |     ^\n 29|   })\n 30|\n```\n\nTo fix this, you'll need to make sure your code cleans the timeout properly:\n\n```js\nuseEffect(() => {\n  setTimeout(() => setWindowWidth(window.innerWidth), 150) // [!code --]\n  const timeout = setTimeout(() => setWindowWidth(window.innerWidth), 150) // [!code ++]\n\n  return function cleanup() { // [!code ++]\n    clearTimeout(timeout) // [!code ++]\n  } // [!code ++]\n})\n```\n"
  },
  {
    "path": "docs/config/diff.md",
    "content": "---\ntitle: diff | Config\noutline: deep\n---\n\n# diff\n\n- **Type:** `string`\n- **CLI:** `--diff=<path>`\n\n`DiffOptions` object or a path to a module which exports `DiffOptions`. Useful if you want to customize diff display.\n\nFor example, as a config object:\n\n```ts\nimport { defineConfig } from 'vitest/config'\nimport c from 'picocolors'\n\nexport default defineConfig({\n  test: {\n    diff: {\n      aIndicator: c.bold('--'),\n      bIndicator: c.bold('++'),\n      omitAnnotationLines: true,\n    },\n  },\n})\n```\n\nOr as a module:\n\n:::code-group\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    diff: './vitest.diff.ts',\n  },\n})\n```\n\n```ts [vitest.diff.ts]\nimport type { DiffOptions } from 'vitest'\nimport c from 'picocolors'\n\nexport default {\n  aIndicator: c.bold('--'),\n  bIndicator: c.bold('++'),\n  omitAnnotationLines: true,\n} satisfies DiffOptions\n```\n:::\n\n## diff.expand\n\n- **Type**: `boolean`\n- **Default**: `true`\n- **CLI:** `--diff.expand=false`\n\nExpand all common lines.\n\n## diff.truncateThreshold\n\n- **Type**: `number`\n- **Default**: `0`\n- **CLI:** `--diff.truncateThreshold=<path>`\n\nThe maximum length of diff result to be displayed. Diffs above this threshold will be truncated.\nTruncation won't take effect with default value 0.\n\n## diff.truncateAnnotation\n\n- **Type**: `string`\n- **Default**: `'... Diff result is truncated'`\n- **CLI:** `--diff.truncateAnnotation=<annotation>`\n\nAnnotation that is output at the end of diff result if it's truncated.\n\n## diff.truncateAnnotationColor\n\n- **Type**: `DiffOptionsColor = (arg: string) => string`\n- **Default**: `noColor = (string: string): string => string`\n\nColor of truncate annotation, default is output with no color.\n\n## diff.printBasicPrototype\n\n- **Type**: `boolean`\n- **Default**: `false`\n\nPrint basic prototype `Object` and `Array` in diff output\n\n## diff.maxDepth\n\n- **Type**: `number`\n- **Default**: `20` (or `8` when comparing different types)\n\nLimit the depth to recurse when printing nested objects\n"
  },
  {
    "path": "docs/config/dir.md",
    "content": "---\ntitle: dir | Config\noutline: deep\n---\n\n# dir\n\n- **Type:** `string`\n- **CLI:** `--dir=<path>`\n- **Default:** same as `root`\n\nBase directory to scan for the test files. You can specify this option to speed up test discovery if your root covers the whole project\n"
  },
  {
    "path": "docs/config/disableconsoleintercept.md",
    "content": "---\ntitle: disableConsoleIntercept | Config\noutline: deep\n---\n\n# disableConsoleIntercept\n\n- **Type:** `boolean`\n- **CLI:** `--disableConsoleIntercept`\n- **Default:** `false`\n\nBy default, Vitest automatically intercepts console logging during tests for extra formatting of test file, test title, etc.\n\nThis is also required for console log preview on Vitest UI.\n\nHowever, disabling such interception might help when you want to debug a code with normal synchronous terminal console logging.\n\n::: warning\nThis option has no effect on [browser tests](/guide/browser/) since Vitest preserves original logging in browser devtools.\n:::\n"
  },
  {
    "path": "docs/config/env.md",
    "content": "---\ntitle: env | Config\noutline: deep\n---\n\n# env\n\n- **Type:** `Partial<NodeJS.ProcessEnv>`\n\nEnvironment variables available on `process.env` and `import.meta.env` during tests. These variables will not be available in the main process (in `globalSetup`, for example).\n"
  },
  {
    "path": "docs/config/environment.md",
    "content": "---\ntitle: environment | Config\n---\n\n# environment\n\n- **Type:** `'node' | 'jsdom' | 'happy-dom' | 'edge-runtime' | string`\n- **Default:** `'node'`\n- **CLI:** `--environment=<env>`\n\nThe environment that will be used for testing. The default environment in Vitest\nis a Node.js environment. If you are building a web application, you can use\nbrowser-like environment through either [`jsdom`](https://github.com/jsdom/jsdom)\nor [`happy-dom`](https://github.com/capricorn86/happy-dom) instead.\nIf you are building edge functions, you can use [`edge-runtime`](https://edge-runtime.vercel.app/packages/vm) environment\n\n::: tip\nYou can also use [Browser Mode](/guide/browser/) to run integration or unit tests in the browser without mocking the environment.\n:::\n\nTo define custom options for your environment, use [`environmentOptions`](/config/environmentoptions).\n\nBy adding a `@vitest-environment` docblock or comment at the top of the file,\nyou can specify another environment to be used for all tests in that file:\n\nDocblock style:\n\n```js\n/**\n * @vitest-environment jsdom\n */\n\ntest('use jsdom in this test file', () => {\n  const element = document.createElement('div')\n  expect(element).not.toBeNull()\n})\n```\n\nComment style:\n\n```js\n// @vitest-environment happy-dom\n\ntest('use happy-dom in this test file', () => {\n  const element = document.createElement('div')\n  expect(element).not.toBeNull()\n})\n```\n\nFor compatibility with Jest, there is also a `@jest-environment`:\n\n```js\n/**\n * @jest-environment jsdom\n */\n\ntest('use jsdom in this test file', () => {\n  const element = document.createElement('div')\n  expect(element).not.toBeNull()\n})\n```\n\nYou can also define a custom environment. When non-builtin environment is used, Vitest will try to load the file if it's relative or absolute, or a package `vitest-environment-${name}`, if the name is a bare specifier.\n\nThe custom environment file should export an object with the shape of `Environment`:\n\n```ts [environment.js]\nimport type { Environment } from 'vitest'\n\nexport default <Environment>{\n  name: 'custom',\n  viteEnvironment: 'ssr',\n  setup() {\n    // custom setup\n    return {\n      teardown() {\n        // called after all tests with this env have been run\n      }\n    }\n  }\n}\n```\n\n::: tip\nThe `viteEnvironment` field corresponde to the environment defined by the [Vite Environment API](https://vite.dev/guide/api-environment#environment-api). By default, Vite exposes `client` (for the browser) and `ssr` (for the server) environments.\n:::\n\nVitest also exposes `builtinEnvironments` through `vitest/environments` entry, in case you just want to extend it. You can read more about extending environments in [our guide](/guide/environment).\n\n::: tip\njsdom environment exposes `jsdom` global variable equal to the current [JSDOM](https://github.com/jsdom/jsdom) instance. If you want TypeScript to recognize it, you can add `vitest/jsdom` to your `tsconfig.json` when you use this environment:\n\n```json [tsconfig.json]\n{\n  \"compilerOptions\": {\n    \"types\": [\"vitest/jsdom\"]\n  }\n}\n```\n:::\n"
  },
  {
    "path": "docs/config/environmentoptions.md",
    "content": "---\ntitle: environmentOptions | Config\n---\n\n# environmentOptions\n\n- **Type:** `Record<'jsdom' | 'happyDOM' | string, unknown>`\n- **Default:** `{}`\n\nThese options are passed to the setup method of the current [environment](/config/environment). By default, you can configure options only for `jsdom` and `happyDOM` when you use them as your test environment.\n\n## Example\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    environmentOptions: {\n      jsdom: {\n        url: 'http://localhost:3000',\n      },\n      happyDOM: {\n        width: 300,\n        height: 400,\n      },\n    },\n  },\n})\n```\n\n::: warning\nOptions are scoped to their environment. For example, put jsdom options under the `jsdom` key and happy-dom options under the `happyDOM` key. This lets you mix multiple environments within the same project.\n:::\n"
  },
  {
    "path": "docs/config/exclude.md",
    "content": "---\ntitle: exclude | Config\n---\n\n# exclude\n\n- **Type:** `string[]`\n- **Default:** `['**/node_modules/**', '**/.git/**']`\n- **CLI:** `vitest --exclude \"**/excluded-file\" --exclude \"*/other-files/*.js\"`\n\nA list of [glob patterns](https://superchupu.dev/tinyglobby/comparison) that should be excluded from your test files. These patterns are resolved relative to the [`root`](/config/root) ([`process.cwd()`](https://nodejs.org/api/process.html#processcwd) by default).\n\nVitest uses the [`tinyglobby`](https://npmx.dev/package/tinyglobby) package to resolve the globs.\n\n::: warning\nThis option does not affect coverage. If you need to remove certain files from the coverage report, use [`coverage.exclude`](/config/coverage#exclude).\n\nThis is the only option that doesn't override your configuration if you provide it with a CLI flag. All glob patterns added via `--exclude` flag will be added to the config's `exclude`.\n:::\n\n## Example\n\n```js\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    exclude: [\n      '**/node_modules/**',\n      '**/dist/**',\n      './temp/**',\n    ],\n  },\n})\n```\n\n::: tip\nAlthough the CLI `exclude` option is additive, manually setting `exclude` in your config will replace the default value. To extend the default `exclude` patterns, use `configDefaults` from `vitest/config`:\n\n```js{6}\nimport { configDefaults, defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    exclude: [\n      ...configDefaults.exclude,\n      'packages/template/*',\n      './temp/**',\n    ],\n  },\n})\n```\n:::\n"
  },
  {
    "path": "docs/config/execargv.md",
    "content": "---\ntitle: execArgv | Config\noutline: deep\n---\n\n# execArgv\n\n- **Type:** `string[]`\n- **Default:** `[]`\n\nPass additional arguments to `node` in the runner worker. See [Command-line API | Node.js](https://nodejs.org/docs/latest/api/cli.html) for more information.\n\n:::warning\nBe careful when using, it as some options may crash worker, e.g. `--prof`, `--title`. See https://github.com/nodejs/node/issues/41103.\n:::\n"
  },
  {
    "path": "docs/config/expandsnapshotdiff.md",
    "content": "---\ntitle: expandSnapshotDiff | Config\noutline: deep\n---\n\n# expandSnapshotDiff\n\n- **Type:** `boolean`\n- **CLI:** `--expandSnapshotDiff`, `--expand-snapshot-diff`\n- **Default:** `false`\n\nShow full diff when snapshot fails instead of a patch.\n"
  },
  {
    "path": "docs/config/expect.md",
    "content": "---\ntitle: expect | Config\noutline: deep\n---\n\n# expect\n\n- **Type:** `ExpectOptions`\n\n## expect.requireAssertions\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nThe same as calling [`expect.hasAssertions()`](/api/expect#expect-hasassertions) at the start of every test. This makes sure that no test will pass accidentally.\n\n::: tip\nThis only works with Vitest's `expect`. If you use `assert` or `.should` assertions, they will not count, and your test will fail due to the lack of expect assertions.\n\nYou can change the value of this by calling `vi.setConfig({ expect: { requireAssertions: false } })`. The config will be applied to every subsequent `expect` call until the `vi.resetConfig` is called manually.\n:::\n\n::: warning\nWhen you run tests with `sequence.concurrent` and `expect.requireAssertions` set to `true`, you should use [local expect](/guide/test-context.html#expect) instead of the global one. Otherwise, this may cause false negatives in [some situations (#8469)](https://github.com/vitest-dev/vitest/issues/8469).\n:::\n\n## expect.poll\n\nGlobal configuration options for [`expect.poll`](/api/expect#poll). These are the same options you can pass down to `expect.poll(condition, options)`.\n\n### expect.poll.interval\n\n- **Type:** `number`\n- **Default:** `50`\n\nPolling interval in milliseconds\n\n### expect.poll.timeout\n\n- **Type:** `number`\n- **Default:** `1000`\n\nPolling timeout in milliseconds\n"
  },
  {
    "path": "docs/config/experimental.md",
    "content": "---\ntitle: experimental | Config\noutline: deep\n---\n\n# experimental\n\n## experimental.fsModuleCache <Version type=\"experimental\">4.0.11</Version> {#experimental-fsmodulecache}\n\n::: tip FEEDBACK\nPlease leave feedback regarding this feature in a [GitHub Discussion](https://github.com/vitest-dev/vitest/discussions/9221).\n:::\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nEnabling this option allows Vitest to keep cached modules on the file system, making tests run faster between reruns.\n\nYou can delete the old cache by running [`vitest --clearCache`](/guide/cli#clearcache).\n\n::: warning BROWSER SUPPORT\nAt the moment, this option does not affect [the browser](/guide/browser/).\n:::\n\nYou can debug if your modules are cached by running vitest with a `DEBUG=vitest:cache:fs` environment variable:\n\n```shell\nDEBUG=vitest:cache:fs vitest --experimental.fsModuleCache\n```\n\n### Known Issues\n\nVitest creates a persistent file hash based on file content, its id, Vite's environment configuration and coverage status. Vitest tries to use as much information as it has about the configuration, but it is still incomplete. At the moment, it is not possible to track your plugin options because there is no standard interface for it.\n\nIf you have a plugin that relies on things outside the file content or the public configuration (like reading another file or a folder), it's possible that the cache will get stale. To work around that, you can define a [cache key generator](/api/advanced/plugin#definecachekeygenerator) to specify a dynamic option or to opt out of caching for that module:\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'vitest-cache',\n      configureVitest({ experimental_defineCacheKeyGenerator }) {\n        experimental_defineCacheKeyGenerator(({ id, sourceCode }) => {\n          // never cache this id\n          if (id.includes('do-not-cache')) {\n            return false\n          }\n\n          // cache this file based on the value of a dynamic variable\n          if (sourceCode.includes('myDynamicVar')) {\n            return process.env.DYNAMIC_VAR_VALUE\n          }\n        })\n      }\n    }\n  ],\n  test: {\n    experimental: {\n      fsModuleCache: true,\n    },\n  },\n})\n```\n\nIf you are a plugin author, consider defining a [cache key generator](/api/advanced/plugin#definecachekeygenerator) in your plugin if it can be registered with different options that affect the transform result.\n\nOn the other hand, if your plugin should not affect the cache key, you can opt out by setting `api.vitest.experimental.ignoreFsModuleCache` to `true`:\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'vitest-cache',\n      api: {\n        vitest: {\n          experimental: {\n            ignoreFsModuleCache: true,\n          },\n        },\n      },\n    },\n  ],\n  test: {\n    experimental: {\n      fsModuleCache: true,\n    },\n  },\n})\n```\n\nNote that you can still define the cache key generator even if the plugin opts out of module caching.\n\n## experimental.fsModuleCachePath <Version type=\"experimental\">4.0.11</Version> {#experimental-fsmodulecachepath}\n\n- **Type:** `string`\n- **Default:** `'node_modules/.experimental-vitest-cache'`\n\nDirectory where the file system cache is located.\n\nBy default, Vitest will try to find the workspace root and store the cache inside the `node_modules` folder. The root is based on your package manager's lockfile (for example, `.package-lock.json`, `.yarn-state.yml`, `.pnpm/lock.yaml` and so on).\n\nAt the moment, Vitest ignores the [test.cache.dir](/config/cache) or [cacheDir](https://vite.dev/config/shared-options#cachedir) options completely and creates a separate folder.\n\n## experimental.openTelemetry <Version type=\"experimental\">4.0.11</Version> {#experimental-opentelemetry}\n\n::: tip FEEDBACK\nPlease leave feedback regarding this feature in a [GitHub Discussion](https://github.com/vitest-dev/vitest/discussions/9222).\n:::\n\n- **Type:**\n\n```ts\ninterface OpenTelemetryOptions {\n  enabled: boolean\n  /**\n   * A path to a file that exposes an OpenTelemetry SDK for Node.js.\n   */\n  sdkPath?: string\n  /**\n   * A path to a file that exposes an OpenTelemetry SDK for the browser.\n   */\n  browserSdkPath?: string\n}\n```\n\n- **Default:** `{ enabled: false }`\n\nThis option controls [OpenTelemetry](https://opentelemetry.io/) support. Vitest imports the SDK file in the main thread and before every test file, if `enabled` is set to `true`.\n\n::: danger PERFORMANCE CONCERNS\nOpenTelemetry may significantly impact Vitest performance; enable it only for local debugging.\n:::\n\nYou can use a [custom service](/guide/open-telemetry) together with Vitest to pinpoint which tests or files are slowing down your test suite.\n\nFor browser mode, see the [Browser Mode](/guide/open-telemetry#browser-mode) section of the OpenTelemetry guide.\n\nAn `sdkPath` is resolved relative to the [`root`](/config/root) of the project and should point to a module that exposes a started SDK instance as a default export. For example:\n\n::: code-group\n```js [otel.js]\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'\nimport { NodeSDK } from '@opentelemetry/sdk-node'\n\nconst sdk = new NodeSDK({\n  serviceName: 'vitest',\n  traceExporter: new OTLPTraceExporter(),\n  instrumentations: [getNodeAutoInstrumentations()],\n})\n\nsdk.start()\nexport default sdk\n```\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    experimental: {\n      openTelemetry: {\n        enabled: true,\n        sdkPath: './otel.js',\n      },\n    },\n  },\n})\n```\n:::\n\n::: warning\nIt's important that Node can process `sdkPath` content because it is not transformed by Vitest. See [the guide](/guide/open-telemetry) on how to work with OpenTelemetry inside of Vitest.\n:::\n\n## experimental.importDurations <Version type=\"experimental\">4.1.0</Version> {#experimental-importdurations}\n\n::: tip FEEDBACK\nPlease leave feedback regarding this feature in a [GitHub Discussion](https://github.com/vitest-dev/vitest/discussions/9224).\n:::\n\n- **Type:**\n\n```ts\ninterface ImportDurationsOptions {\n  /**\n   * When to print import breakdown to CLI terminal.\n   * - false: Never print (default)\n   * - true: Always print\n   * - 'on-warn': Print only when any import exceeds warn threshold\n   */\n  print?: boolean | 'on-warn'\n  /**\n   * Fail the test run if any import exceeds the danger threshold.\n   * When enabled and threshold exceeded, breakdown is always printed.\n   * @default false\n   */\n  failOnDanger?: boolean\n  /**\n   * Maximum number of imports to collect and display.\n   */\n  limit?: number\n  /**\n   * Duration thresholds in milliseconds for coloring and warnings.\n   */\n  thresholds?: {\n    /** Threshold for yellow/warning color. @default 100 */\n    warn?: number\n    /** Threshold for red/danger color and failOnDanger. @default 500 */\n    danger?: number\n  }\n}\n```\n\n- **Default:** `{ print: false, failOnDanger: false, limit: 0, thresholds: { warn: 100, danger: 500 } }` (`limit` is 10 if `print` or UI is enabled)\n\nConfigure import duration collection and display.\n\nThe `print` option controls CLI terminal output. The `limit` option controls how many imports to collect and display. [Vitest UI](/guide/ui#import-breakdown) can always toggle the breakdown display regardless of the `print` setting.\n\n- Self: the time it took to import the module, excluding static imports;\n- Total: the time it took to import the module, including static imports. Note that this does not include `transform` time of the current module.\n\n<img alt=\"An example of import breakdown in the terminal\" src=\"/reporter-import-breakdown.png\" img-dark />\n<img alt=\"An example of import breakdown in the terminal\" src=\"/reporter-import-breakdown-light.png\" img-light />\n\nNote that if the file path is too long, Vitest will truncate it at the start until it fits 45 character limit.\n\n### experimental.importDurations.print {#experimental-importdurationsprint}\n\n- **Type:** `boolean | 'on-warn'`\n- **Default:** `false`\n\nControls when to print import breakdown to CLI terminal after tests finish. This only works with [`default`](/guide/reporters#default), [`verbose`](/guide/reporters#verbose), or [`tree`](/guide/reporters#tree) reporters.\n\n- `false`: Never print breakdown\n- `true`: Always print breakdown\n- `'on-warn'`: Print only when any import exceeds the `thresholds.warn` value\n\n### experimental.importDurations.failOnDanger {#experimental-importdurationsfailondanger}\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nFail the test run if any import exceeds the `thresholds.danger` value. When enabled and the threshold is exceeded, the breakdown is always printed regardless of the `print` setting.\n\nThis is useful for enforcing import performance budgets in CI:\n\n```bash\nvitest --experimental.importDurations.failOnDanger\n```\n\n### experimental.importDurations.limit {#experimental-importdurationslimit}\n\n- **Type:** `number`\n- **Default:** `0` (or `10` if `print`, `failOnDanger`, or UI is enabled)\n\nMaximum number of imports to collect and display in CLI output, [Vitest UI](/guide/ui#import-breakdown), and third-party reporters.\n\n### experimental.importDurations.thresholds {#experimental-importdurationsthresholds}\n\n- **Type:** `{ warn?: number; danger?: number }`\n- **Default:** `{ warn: 100, danger: 500 }`\n\nDuration thresholds in milliseconds for coloring and warnings:\n\n- `warn`: Threshold for yellow/warning color (default: 100ms)\n- `danger`: Threshold for red/danger color and `failOnDanger` (default: 500ms)\n\n::: info\n[Vitest UI](/guide/ui#import-breakdown) shows a breakdown of imports automatically if at least one file took longer than the `danger` threshold to load.\n:::\n\n## experimental.viteModuleRunner <Version type=\"experimental\">4.1.0</Version> {#experimental-vitemodulerunner}\n\n::: tip FEEDBACK\nPlease leave feedback regarding this feature in a [GitHub Discussion](https://github.com/vitest-dev/vitest/discussions/9501).\n:::\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nControls whether Vitest uses Vite's [module runner](https://vite.dev/guide/api-environment-runtimes#modulerunner) to run the code or fallback to the native `import`.\n\nIf this option is defined in the root config, all [projects](/guide/projects) will inherit it automatically.\n\nConsider disabling the module runner if you are running tests in the same environment as your code (server backend or simple scripts, for example). However, we still recommend running `jsdom`/`happy-dom` tests with Vite's module runner or in [the browser](/guide/browser/) since it doesn't require any additional configuration.\n\nDisabling this flag will disable _all_ file transforms:\n\n- test files and your source code are not processed by Vite\n- your global setup files are not processed\n- your custom runner/pool/environment files are not processed\n- your config file is still processed by Vite (this happens before Vitest knows the `viteModuleRunner` flag)\n\n::: warning\nAt the moment, Vitest still requires Vite for certain functionality like the module graph or watch mode.\n\nAlso note that this option only works with `forks` or `threads` [pools](/config/pool).\n:::\n\n### Module Runner\n\nBy default, Vitest runs tests in a very permissive module runner sandbox powered by Vite's [Environment API](https://vite.dev/guide/api-environment.html#environment-api). Every file is categorized as either an \"inline\" module or an \"external\" module.\n\nModule runner runs all \"inlined\" modules. It provides `import.meta.env`, `require`, `__dirname`, `__filename`, static `import`, and has its own module resolution mechanism. This makes it very easy to run code when you don't want to configure the environment and just need to test that the bare JavaScript logic you wrote works as intended.\n\nAll \"external\" modules run in native mode, meaning they are executed outside of the module runner sandbox. If you are running tests in Node.js, these files are imported with the native `import` keyword and processed by Node.js directly.\n\nWhile running JSDOM/happy-dom tests in a permissive fake environment might be justified, running Node.js tests in a non-Node.js environment can hide and silence potential errors you may encounter in production, especially if your code doesn't require any additional transformations provided by Vite plugins.\n\n### Known Limitations\n\nSome Vitest features rely on files being transformed. Vitest uses synchronous [Node.js Loaders API](https://nodejs.org/api/module.html#customization-hooks) to transform test files and setup files to support these features:\n\n- [`import.meta.vitest`](/guide/in-source)\n- [`vi.mock`](/api/vi#vi-mock)\n- [`vi.hoisted`](/api/vi#vi-hoisted)\n\n::: warning\nThis means that Vitest requires at least Node 22.15 for those features to work. At the moment, they also do not work in Deno or Bun.\n\nVitest will only detect `vi.mock` and `vi.hoisted` inside of test files, they will not be hoisted inside imported modules.\n:::\n\nThis could affect performance because Vitest needs to read the file and process it. If you do not use these features, you can disable the transforms by setting `experimental.nodeLoader` to `false`. Vitest only reads test files and setup files while looking for `vi.mock` or `vi.hoisted`. Using these in other files won't hoist them to the top of the file and can lead to unexpected behavior.\n\nSome features will not work due to the nature of `viteModuleRunner`, including:\n\n- no `import.meta.env`: `import.meta.env` is a Vite feature, use `process.env` instead\n- no `plugins`: plugins are not applied because there is no transformation phase, use [customization hooks](https://nodejs.org/api/module.html#customization-hooks) via [`execArgv`](/config/execargv) instead\n- no `alias`: aliases are not applied because there is no transformation phase\n- `istanbul` coverage provider doesn't work because there is no transformation phase, use `v8` instead\n\n::: warning Coverage Support\nAt the momemnt Vitest supports coverage via `v8` provider as long as files can be transformed into JavaScript. To transform TypeScript, Vitest uses [`module.stripTypeScriptTypes`](https://nodejs.org/api/module.html#modulestriptypescripttypescode-options) which is available in Node.js since v22.13. If you are using a custom [module loader](https://nodejs.org/api/module.html#customization-hooks), Vitest is not able to reuse it to transform files for analysis.\n:::\n\nWith regards to mocking, it is also important to point out that ES modules do not support property override. This means that code like this won't work anymore:\n\n```ts\nimport * as fs from 'node:fs'\nimport { vi } from 'vitest'\n\nvi.spyOn(fs, 'readFileSync').mockImplementation(() => '42') // ❌\n```\n\nHowever, Vitest supports auto-spying on modules without overriding their implementation. When `vi.mock` is called with a `spy: true` argument, the module is mocked in a way that preserves original implementations, but all exported functions are wrapped in a `vi.fn()` spy:\n\n```ts\nimport * as fs from 'node:fs'\nimport { vi } from 'vitest'\n\nvi.mock('node:fs', { spy: true })\n\nfs.readFileSync.mockImplementation(() => '42') // ✅\n```\n\nFactory mocking is implemented using a top-level await. This means that mocked modules cannot be loaded with `require()` in your source code:\n\n```ts\nvi.mock('node:fs', async (importOriginal) => {\n  return {\n    ...await importOriginal(),\n    readFileSync: vi.fn(),\n  }\n})\n\nconst fs = require('node:fs') // throws an error\n```\n\nThis limitation exists because factories can be asynchronous. This should not be a problem because Vitest doesn't mock builtin modules inside `node_modules`, which is simillar to how Vitest works by default.\n\n### TypeScript\n\nIf you are using Node.js 22.18/23.6 or higher, TypeScript will be [transformed natively](https://nodejs.org/en/learn/typescript/run-natively) by Node.js.\n\n::: warning TypeScript with Node.js 22.6-22.18\nIf you are using Node.js version between 22.6 and 22.18, you can also enable native TypeScript support via `--experimental-strip-types` flag:\n\n```shell\nNODE_OPTIONS=\"--experimental-strip-types\" vitest\n```\n\nIf you are using TypeScript and Node.js version lower than 22.6, then you will need to either:\n\n- build your test files and source code and run those files directly\n- import a [custom loader](https://nodejs.org/api/module.html#customization-hooks) via `execArgv` flag\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nconst tsxApi = import.meta.resolve('tsx/esm/api')\n\nexport default defineConfig({\n  test: {\n    execArgv: [\n      `--import=data:text/javascript,import * as tsx from \"${tsxApi}\";tsx.register()`,\n    ],\n    experimental: {\n      viteModuleRunner: false,\n    },\n  },\n})\n```\n\nIf you are running tests in Deno, TypeScript files are processed by the runtime without any additional configurations.\n:::\n\n## experimental.nodeLoader <Version type=\"experimental\">4.1.0</Version> {#experimental-nodeloader}\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nIf module runner is disabled, Vitest uses a native [Node.js module loader](https://nodejs.org/api/module.html#customization-hooks) to transform files to support `import.meta.vitest`, `vi.mock` and `vi.hoisted`.\n\nIf you don't use these features, you can disable this to improve performance.\n"
  },
  {
    "path": "docs/config/faketimers.md",
    "content": "---\ntitle: fakeTimers | Config\noutline: deep\n---\n\n# fakeTimers\n\n- **Type:** `FakeTimerInstallOpts`\n\nOptions that Vitest will pass down to [`@sinon/fake-timers`](https://npmx.dev/package/@sinonjs/fake-timers) when using [`vi.useFakeTimers()`](/api/vi#vi-usefaketimers).\n\n## fakeTimers.now\n\n- **Type:** `number | Date`\n- **Default:** `Date.now()`\n\nInstalls fake timers with the specified Unix epoch.\n\n## fakeTimers.toFake\n\n- **Type:** `('setTimeout' | 'clearTimeout' | 'setImmediate' | 'clearImmediate' | 'setInterval' | 'clearInterval' | 'Date' | 'nextTick' | 'hrtime' | 'requestAnimationFrame' | 'cancelAnimationFrame' | 'requestIdleCallback' | 'cancelIdleCallback' | 'performance' | 'queueMicrotask')[]`\n- **Default:** everything available globally except `nextTick` and `queueMicrotask`\n\nAn array with names of global methods and APIs to fake.\n\nTo only mock `setTimeout()` and `nextTick()`, specify this property as `['setTimeout', 'nextTick']`.\n\nMocking `nextTick` is not supported when running Vitest inside `node:child_process` by using `--pool=forks`. NodeJS uses `process.nextTick` internally in `node:child_process` and hangs when it is mocked. Mocking `nextTick` is supported when running Vitest with `--pool=threads`.\n\n## fakeTimers.loopLimit\n\n- **Type:** `number`\n- **Default:** `10_000`\n\nThe maximum number of timers that will be run when calling [`vi.runAllTimers()`](/api/vi#vi-runalltimers).\n\n## fakeTimers.shouldAdvanceTime\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nTells @sinonjs/fake-timers to increment mocked time automatically based on the real system time shift (e.g. the mocked time will be incremented by 20ms for every 20ms change in the real system time).\n\n## fakeTimers.advanceTimeDelta\n\n- **Type:** `number`\n- **Default:** `20`\n\nRelevant only when using with `shouldAdvanceTime: true`. increment mocked time by advanceTimeDelta ms every advanceTimeDelta ms change in the real system time.\n\n## fakeTimers.shouldClearNativeTimers\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nTells fake timers to clear \"native\" (i.e. not fake) timers by delegating to their respective handlers. When disabled, it can lead to potentially unexpected behavior if timers existed prior to starting fake timers session.\n"
  },
  {
    "path": "docs/config/fileparallelism.md",
    "content": "---\ntitle: fileParallelism | Config\noutline: deep\n---\n\n# fileParallelism\n\n- **Type:** `boolean`\n- **Default:** `true`\n- **CLI:** `--no-file-parallelism`, `--fileParallelism=false`\n\nShould all test files run in parallel. Setting this to `false` will override `maxWorkers` option to `1`.\n\n::: tip\nThis option doesn't affect tests running in the same file. If you want to run those in parallel, use `concurrent` option on [describe](/api/describe#describe-concurrent) or via [a config](/config/sequence#sequence-concurrent).\n:::\n"
  },
  {
    "path": "docs/config/forcereruntriggers.md",
    "content": "---\ntitle: forceRerunTriggers | Config\noutline: deep\n---\n\n# forceRerunTriggers <CRoot />\n\n- **Type**: `string[]`\n- **Default:** `['**/package.json/**', '**/vitest.config.*/**', '**/vite.config.*/**']`\n\nGlob pattern of file paths that will trigger the whole suite rerun. When paired with the `--changed` argument will run the whole test suite if the trigger is found in the git diff.\n\nUseful if you are testing calling CLI commands, because Vite cannot construct a module graph:\n\n```ts\ntest('execute a script', async () => {\n  // Vitest cannot rerun this test, if content of `dist/index.js` changes\n  await execa('node', ['dist/index.js'])\n})\n```\n\n::: tip\nMake sure that your files are not excluded by [`server.watch.ignored`](https://vitejs.dev/config/server-options.html#server-watch).\n:::\n"
  },
  {
    "path": "docs/config/globals.md",
    "content": "---\ntitle: globals | Config\n---\n\n# globals\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **CLI:** `--globals`, `--no-globals`, `--globals=false`\n\nBy default, `vitest` does not provide global APIs for explicitness. If you prefer to use the APIs globally like Jest, you can pass the `--globals` option to CLI or add `globals: true` in the config.\n\n```js\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    globals: true,\n  },\n})\n```\n\n::: tip\nNote that some libraries, e.g., `@testing-library/react`, rely on globals being present to perform auto cleanup.\n:::\n\nTo get TypeScript working with the global APIs, add `vitest/globals` to the `types` field in your `tsconfig.json`:\n\n```json [tsconfig.json]\n{\n  \"compilerOptions\": {\n    \"types\": [\"vitest/globals\"]\n  }\n}\n```\n\nIf you have redefined your [`typeRoots`](https://www.typescriptlang.org/tsconfig/#typeRoots) to include additional types in your compilation, you will need to add back the `node_modules` to make `vitest/globals` discoverable:\n\n```json [tsconfig.json]\n{\n  \"compilerOptions\": {\n    \"typeRoots\": [\"./types\", \"./node_modules/@types\", \"./node_modules\"],\n    \"types\": [\"vitest/globals\"]\n  }\n}\n```\n"
  },
  {
    "path": "docs/config/globalsetup.md",
    "content": "---\ntitle: globalSetup | Config\noutline: deep\n---\n\n# globalSetup\n\n- **Type:** `string | string[]`\n\nPath to global setup files relative to project [root](/config/root).\n\nA global setup file can either export named functions `setup` and `teardown` or a `default` function that returns a teardown function:\n\n::: code-group\n```js [exports]\nexport function setup(project) {\n  console.log('setup')\n}\n\nexport function teardown() {\n  console.log('teardown')\n}\n```\n```js [default]\nexport default function setup(project) {\n  console.log('setup')\n\n  return function teardown() {\n    console.log('teardown')\n  }\n}\n```\n:::\n\nNote that the `setup` method and a `default` function receive a [test project](/api/advanced/test-project) as the first argument. The global setup is called before the test workers are created and only if there is at least one test queued, and teardown is called after all test files have finished running. In [watch mode](/config/watch), the teardown is called before the process is exited instead. If you need to reconfigure your setup before the test rerun, you can use [`onTestsRerun`](#handling-test-reruns) hook instead.\n\nMultiple global setup files are possible. `setup` and `teardown` are executed sequentially with teardown in reverse order.\n\n::: danger\nBeware that the global setup is running in a different global scope before test workers are even created, so your tests don't have access to global variables defined here. However, you can pass down serializable data to tests via [`provide`](/config/provide) method and read them in your tests via `inject` imported from `vitest`:\n\n:::code-group\n```ts [example.test.ts]\nimport { inject } from 'vitest'\n\ninject('wsPort') === 3000\n```\n```ts [globalSetup.ts]\nimport type { TestProject } from 'vitest/node'\n\nexport default function setup(project: TestProject) {\n  project.provide('wsPort', 3000)\n}\n\ndeclare module 'vitest' {\n  export interface ProvidedContext {\n    wsPort: number\n  }\n}\n```\n\nIf you need to execute code in the same process as tests, use [`setupFiles`](/config/setupfiles) instead, but note that it runs before every test file.\n:::\n\n## Handling Test Reruns\n\nYou can define a custom callback function to be called when Vitest reruns tests. The test runner will wait for it to complete before executing tests. Note that you cannot destruct the `project` like `{ onTestsRerun }` because it relies on the context.\n\n```ts [globalSetup.ts]\nimport type { TestProject } from 'vitest/node'\n\nexport default function setup(project: TestProject) {\n  project.onTestsRerun(async () => {\n    await restartDb()\n  })\n}\n```\n"
  },
  {
    "path": "docs/config/hideskippedtests.md",
    "content": "---\ntitle: hideSkippedTests | Config\noutline: deep\n---\n\n# hideSkippedTests\n\n- **Type:** `boolean`\n- **CLI:** `--hideSkippedTests`, `--hide-skipped-tests`\n- **Default:** `false`\n\nHide logs for skipped tests\n"
  },
  {
    "path": "docs/config/hooktimeout.md",
    "content": "---\ntitle: hookTimeout | Config\noutline: deep\n---\n\n# hookTimeout\n\n- **Type:** `number`\n- **Default:** `10_000` in Node.js, `30_000` if `browser.enabled` is `true`\n- **CLI:** `--hook-timeout=10000`, `--hookTimeout=10000`\n\nDefault timeout of a hook in milliseconds. Use `0` to disable timeout completely.\n"
  },
  {
    "path": "docs/config/include-source.md",
    "content": "---\ntitle: includeSource | Config\n---\n\n# includeSource\n\n- **Type:** `string[]`\n- **Default:** `[]`\n\nA list of [glob patterns](https://superchupu.dev/tinyglobby/comparison) that match your [in-source test files](/guide/in-source). These patterns are resolved relative to the [`root`](/config/root) ([`process.cwd()`](https://nodejs.org/api/process.html#processcwd) by default).\n\nWhen defined, Vitest will run all matched files that have `import.meta.vitest` inside.\n\n::: warning\nVitest performs a simple text-based inclusion check on source files. If a file contains `import.meta.vitest`, even in a comment, it will be matched as an in-source test file.\n:::\n\nVitest uses the [`tinyglobby`](https://npmx.dev/package/tinyglobby) package to resolve the globs.\n\n## Example\n\n```js\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    includeSource: ['src/**/*.{js,ts}'],\n  },\n})\n```\n\nThen you can write tests inside your source files:\n\n```ts [src/index.ts]\nexport function add(...args: number[]) {\n  return args.reduce((a, b) => a + b, 0)\n}\n\n// #region in-source test suites\nif (import.meta.vitest) {\n  const { it, expect } = import.meta.vitest\n  it('add', () => {\n    expect(add()).toBe(0)\n    expect(add(1)).toBe(1)\n    expect(add(1, 2, 3)).toBe(6)\n  })\n}\n// #endregion\n```\n\nFor your production build, you need to replace the `import.meta.vitest` with `undefined`, letting the bundler do the dead code elimination.\n\n::: code-group\n```js [vite.config.ts]\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  define: { // [!code ++]\n    'import.meta.vitest': 'undefined', // [!code ++]\n  }, // [!code ++]\n})\n```\n```js [rolldown.config.js]\nimport { defineConfig } from 'rolldown/config'\n\nexport default defineConfig({\n  transform: {\n    define: { // [!code ++]\n      'import.meta.vitest': 'undefined', // [!code ++]\n    }, // [!code ++]\n  },\n})\n```\n```js [rollup.config.js]\nimport replace from '@rollup/plugin-replace' // [!code ++]\n\nexport default {\n  plugins: [\n    replace({ // [!code ++]\n      'import.meta.vitest': 'undefined', // [!code ++]\n    }) // [!code ++]\n  ],\n  // other options\n}\n```\n```js [build.config.js]\nimport { defineBuildConfig } from 'unbuild'\n\nexport default defineBuildConfig({\n  replace: { // [!code ++]\n    'import.meta.vitest': 'undefined', // [!code ++]\n  }, // [!code ++]\n  // other options\n})\n```\n```js [webpack.config.js]\nconst webpack = require('webpack')\n\nmodule.exports = {\n  plugins: [\n    new webpack.DefinePlugin({ // [!code ++]\n      'import.meta.vitest': 'undefined', // [!code ++]\n    })// [!code ++]\n  ],\n}\n```\n:::\n\n::: tip\nTo get TypeScript support for `import.meta.vitest`, add `vitest/importMeta` to your `tsconfig.json`:\n\n```json [tsconfig.json]\n{\n  \"compilerOptions\": {\n    \"types\": [\"vitest/importMeta\"]\n  }\n}\n```\n:::\n"
  },
  {
    "path": "docs/config/include.md",
    "content": "---\ntitle: include | Config\n---\n\n# include\n\n- **Type:** `string[]`\n- **Default:** `['**/*.{test,spec}.?(c|m)[jt]s?(x)']`\n- **CLI:** `vitest [...include]`, `vitest **/*.test.js`\n\nA list of [glob patterns](https://superchupu.dev/tinyglobby/comparison) that match your test files. These patterns are resolved relative to the [`root`](/config/root) ([`process.cwd()`](https://nodejs.org/api/process.html#processcwd) by default).\n\nVitest uses the [`tinyglobby`](https://npmx.dev/package/tinyglobby) package to resolve the globs.\n\n::: tip NOTE\nWhen using coverage, Vitest automatically adds test files `include` patterns to coverage's default `exclude` patterns. See [`coverage.exclude`](/config/coverage#exclude).\n:::\n\n## Example\n\n```js\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: [\n      './test',\n      './**/*.{test,spec}.tsx?',\n    ],\n  },\n})\n```\n\nVitest provides reasonable defaults, so normally you wouldn't override them. A good example of defining `include` is for [test projects](/guide/projects):\n\n```js{8,12} [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: 'unit',\n          include: ['./test/unit/*.test.js'],\n        },\n      },\n      {\n        test: {\n          name: 'e2e',\n          include: ['./test/e2e/*.test.js'],\n        },\n      },\n    ],\n  },\n})\n```\n\n::: warning\nThis option will override Vitest defaults. If you just want to extend them, use `configDefaults` from `vitest/config`:\n\n```js{6}\nimport { configDefaults, defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: [\n      ...configDefaults.include,\n      './test',\n      './**/*.{test,spec}.tsx?',\n    ],\n  },\n})\n```\n:::\n"
  },
  {
    "path": "docs/config/includetasklocation.md",
    "content": "---\ntitle: includeTaskLocation | Config\noutline: deep\n---\n\n# includeTaskLocation\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nShould `location` property be included when Vitest API receives tasks in [reporters](/config/reporters). If you have a lot of tests, this might cause a small performance regression.\n\nThe `location` property has `column` and `line` values that correspond to the `test` or `describe` position in the original file.\n\nThis option will be auto-enabled if you don't disable it explicitly, and you are running Vitest with:\n- [Vitest UI](/guide/ui)\n- or using the [Browser Mode](/guide/browser/) without [headless](/guide/browser/#headless) mode\n- or using [HTML Reporter](/guide/reporters#html-reporter)\n\n::: tip\nThis option has no effect if you do not use custom code that relies on this.\n:::\n"
  },
  {
    "path": "docs/config/index.md",
    "content": "---\noutline: deep\n---\n\n# Configuring Vitest\n\nIf you are using Vite and have a `vite.config` file, Vitest will read it to match with the plugins and setup as your Vite app. If you want to have a different configuration for testing or your main app doesn't rely on Vite specifically, you could either:\n\n- Create `vitest.config.ts`, which will have the higher priority and will **override** the configuration from `vite.config.ts` (Vitest supports all conventional JS and TS extensions, but doesn't support `json`) - it means all options in your `vite.config` will be **ignored**\n- Pass `--config` option to CLI, e.g. `vitest --config ./path/to/vitest.config.ts`\n- Use `process.env.VITEST` or `mode` property on `defineConfig` (will be set to `test`/`benchmark` if not overridden with `--mode`) to conditionally apply different configuration in `vite.config.ts`. Note that like any other environment variable, `VITEST` is also exposed on `import.meta.env` in your tests\n\nTo configure `vitest` itself, add `test` property in your Vite config. You'll also need to add a reference to Vitest types using a [triple slash command](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-) at the top of your config file, if you are importing `defineConfig` from `vite` itself.\n\nIf you are not using `vite`, add `defineConfig` imported from `vitest/config` to your config file:\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    // ... Specify options here.\n  },\n})\n```\n\nIf you have a `vite` config already, you can add `/// <reference types=\"vitest/config\" />` to include the `test` types:\n\n```js [vite.config.js]\n/// <reference types=\"vitest/config\" />\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    // ... Specify options here.\n  },\n})\n```\n\nYou can retrieve Vitest's default options to expand them if needed:\n\n```js [vitest.config.js]\nimport { configDefaults, defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    exclude: [...configDefaults.exclude, 'packages/template/*'],\n  },\n})\n```\n\nWhen using a separate `vitest.config.js`, you can also extend Vite's options from another config file if needed:\n\n```js [vitest.config.js]\nimport { defineConfig, mergeConfig } from 'vitest/config'\nimport viteConfig from './vite.config'\n\nexport default mergeConfig(viteConfig, defineConfig({\n  test: {\n    exclude: ['packages/template/*'],\n  },\n}))\n```\n\nIf your Vite config is defined as a function, you can define the config like this:\n\n```js [vitest.config.js]\nimport { defineConfig, mergeConfig } from 'vitest/config'\nimport viteConfig from './vite.config'\n\nexport default defineConfig(configEnv => mergeConfig(\n  viteConfig(configEnv),\n  defineConfig({\n    test: {\n      exclude: ['packages/template/*'],\n    },\n  })\n))\n```\n\nSince Vitest uses Vite config, you can also use any configuration option from [Vite](https://vitejs.dev/config/). For example, `define` to define global variables, or `resolve.alias` to define aliases - these options should be defined on the top level, _not_ within a `test` property.\n\nConfiguration options that are not supported inside a [project](/guide/projects) config have <CRoot /> icon next to them. This means they can only be set in the root Vitest config.\n"
  },
  {
    "path": "docs/config/isolate.md",
    "content": "---\ntitle: isolate | Config\noutline: deep\n---\n\n# isolate\n\n- **Type:** `boolean`\n- **Default:** `true`\n- **CLI:** `--no-isolate`, `--isolate=false`\n\nRun tests in an isolated environment. This option has no effect on `vmThreads` and `vmForks` pools.\n\nDisabling this option might [improve performance](/guide/improving-performance) if your code doesn't rely on side effects (which is usually true for projects with `node` environment).\n\n::: tip\nYou can disable isolation for specific test files by using Vitest workspaces and disabling isolation per project.\n:::\n"
  },
  {
    "path": "docs/config/logheapusage.md",
    "content": "---\ntitle: logHeapUsage | Config\noutline: deep\n---\n\n# logHeapUsage\n\n- **Type**: `boolean`\n- **Default**: `false`\n- **CLI:** `--logHeapUsage`, `--logHeapUsage=false`\n\nShow heap usage after each test. Useful for debugging memory leaks.\n"
  },
  {
    "path": "docs/config/maxconcurrency.md",
    "content": "---\ntitle: maxConcurrency | Config\noutline: deep\n---\n\n# maxConcurrency\n\n- **Type**: `number`\n- **Default**: `5`\n- **CLI**: `--max-concurrency=10`, `--maxConcurrency=10`\n\nThe maximum number of tests and hooks that can run at the same time when using `test.concurrent` or `describe.concurrent`.\n\nThe hook execution order within a single group is also controlled by [`sequence.hooks`](/config/sequence#sequence-hooks). With `sequence.hooks: 'parallel'`, the execution is bounded by the same limit of [`maxConcurrency`](/config/maxconcurrency).\n"
  },
  {
    "path": "docs/config/maxworkers.md",
    "content": "---\ntitle: maxWorkers | Config\noutline: deep\n---\n\n# maxWorkers\n\n- **Type:** `number | string`\n- **Default:**\n  - if [`watch`](/config/watch) is disabled, uses all available parallelism\n  - if [`watch`](/config/watch) is enabled, uses half of all available parallelism\n\nDefines the maximum concurrency for test workers. Accepts either a number or a percentage string.\n\n- Number: spawns up to the specified number of workers.\n- Percentage string (e.g., \"50%\"): computes the worker count as the given percentage of the machine’s available parallelism.\n\n## Example\n\n### Number\n\n::: code-group\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    maxWorkers: 4,\n  },\n})\n```\n```bash [CLI]\nvitest --maxWorkers=4\n```\n:::\n\n### Percent\n\n::: code-group\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    maxWorkers: '50%',\n  },\n})\n```\n```bash [CLI]\nvitest --maxWorkers=50%\n```\n:::\n\nVitest uses [`os.availableParallelism`](https://nodejs.org/api/os.html#osavailableparallelism) to know the maximum amount of parallelism available.\n"
  },
  {
    "path": "docs/config/mockreset.md",
    "content": "---\ntitle: mockReset | Config\noutline: deep\n---\n\n# mockReset\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nShould Vitest automatically call [`vi.resetAllMocks()`](/api/vi#vi-resetallmocks) before each test.\n\nThis will clear mock history and reset each implementation.\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    mockReset: true,\n  },\n})\n```\n\n::: warning\nBe aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will clear the mock history and implementation for all mocks, including those currently being used by other tests in progress.\n:::\n"
  },
  {
    "path": "docs/config/mode.md",
    "content": "---\ntitle: mode | Config\noutline: deep\n---\n\n# mode\n\n- **Type:** `string`\n- **CLI:** `--mode=staging`\n- **Default:** `'test'`\n\nOverrides Vite mode\n"
  },
  {
    "path": "docs/config/name.md",
    "content": "---\ntitle: name | Config\n---\n\n# name\n\n- **Type:**\n\n```ts\ninterface UserConfig {\n  name?: string | { label: string; color?: LabelColor }\n}\n```\n\nAssign a custom name to the test project or Vitest process. The name will be visible in the CLI and UI, and available in the Node.js API via [`project.name`](/api/advanced/test-project#name).\n\nThe color used by the CLI and UI can be changed by providing an object with a `color` property.\n\n## Colors\n\nThe displayed colors depend on your terminal’s color scheme. In the UI, colors match their CSS equivalents.\n\n- black\n- red\n- green\n- yellow\n- blue\n- magenta\n- cyan\n- white\n\n## Example\n\n::: code-group\n```js [string]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    name: 'unit',\n  },\n})\n```\n```js [object]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    name: {\n      label: 'unit',\n      color: 'blue',\n    },\n  },\n})\n```\n:::\n\nThis property is mostly useful if you have several projects as it helps distinguish them in your terminal:\n\n```js{7,11} [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        name: 'unit',\n        include: ['./test/*.unit.test.js'],\n      },\n      {\n        name: 'e2e',\n        include: ['./test/*.e2e.test.js'],\n      },\n    ],\n  },\n})\n```\n\n::: tip\nVitest automatically assigns a name when none is provided. Resolution order:\n\n- If the project is specified by a config file or directory, Vitest uses the package.json's `name` field.\n- If there is no `package.json`, Vitest falls back to the project folder's basename.\n- If the project is defined inline in the `projects` array (an object), Vitest assigns a numeric name equal to that project's array index (0-based).\n:::\n\n::: warning\nNote that projects cannot have the same name. Vitest will throw an error during the config resolution.\n:::\n\nYou can also assign different names to different browser [instances](/config/browser/instances):\n\n```js{10,11} [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium', name: 'Chrome' },\n        { browser: 'firefox', name: 'Firefox' },\n      ],\n    },\n  },\n})\n```\n\n::: tip\nBrowser instances inherit their parent project's name with the browser name appended in parentheses. For example, a project named `browser` with a chromium instance will be shown as `browser (chromium)`.\n\nIf the parent project has no name, or instances are defined at the root level (not inside a named project), the instance name defaults to the browser value (e.g. `chromium`). To override this behavior, set an explicit `name` on the instance.\n:::\n"
  },
  {
    "path": "docs/config/onconsolelog.md",
    "content": "---\ntitle: onConsoleLog | Config\noutline: deep\n---\n\n# onConsoleLog <CRoot />\n\n```ts\nfunction onConsoleLog(\n  log: string,\n  type: 'stdout' | 'stderr',\n  entity: TestModule | TestSuite | TestCase | undefined,\n): boolean | void\n```\n\nCustom handler for `console` methods in tests. If you return `false`, Vitest will not print the log to the console. Note that Vitest ignores all other falsy values.\n\nCan be useful for filtering out logs from third-party libraries.\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    onConsoleLog(log: string, type: 'stdout' | 'stderr'): boolean | void {\n      return !(log === 'message from third party library' && type === 'stdout')\n    },\n  },\n})\n```\n"
  },
  {
    "path": "docs/config/onstacktrace.md",
    "content": "---\ntitle: onStackTrace | Config\noutline: deep\n---\n\n# onStackTrace <CRoot />\n\n- **Type**: `(error: Error, frame: ParsedStack) => boolean | void`\n\nApply a filtering function to each frame of each stack trace when handling errors. This does not apply to stack traces printed by [`printConsoleTrace`](/config/printconsoletrace#printconsoletrace). The first argument, `error`, is a `TestError`.\n\nCan be useful for filtering out stack trace frames from third-party libraries.\n\n::: tip\nThe stack trace's total size is also typically limited by V8's [`Error.stackTraceLimit`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stackTraceLimit) number. You could set this to a high value in your test setup function to prevent stacks from being truncated.\n:::\n\n```ts\nimport type { ParsedStack, TestError } from 'vitest'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    onStackTrace(error: TestError, { file }: ParsedStack): boolean | void {\n      // If we've encountered a ReferenceError, show the whole stack.\n      if (error.name === 'ReferenceError') {\n        return\n      }\n\n      // Reject all frames from third party libraries.\n      if (file.includes('node_modules')) {\n        return false\n      }\n    },\n  },\n})\n```\n"
  },
  {
    "path": "docs/config/onunhandlederror.md",
    "content": "---\ntitle: onUnhandledError | Config\noutline: deep\n---\n\n# onUnhandledError <CRoot /> <Version>4.0.0</Version>\n\n- **Type:**\n\n```ts\nfunction onUnhandledError(\n  error: (TestError | Error) & { type: string }\n): boolean | void\n```\n\nA custom callback for filtering unhandled errors that should not be reported. When an error is filtered out, it no longer affects the result of the test run.\n\nTo report unhandled errors without affecting the test outcome, use the [`dangerouslyIgnoreUnhandledErrors`](/config/dangerouslyignoreunhandlederrors) option instead.\n\n::: tip\nThis callback is called on the main thread, it doesn't have access to your test context.\n:::\n\n## Example\n\n```ts\nimport type { ParsedStack } from 'vitest'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    onUnhandledError(error): boolean | void {\n      // Ignore all errors with the name \"MySpecialError\".\n      if (error.name === 'MySpecialError') {\n        return false\n      }\n    },\n  },\n})\n```\n"
  },
  {
    "path": "docs/config/open.md",
    "content": "---\ntitle: open | Config\noutline: deep\n---\n\n# open <CRoot />\n\n- **Type:** `boolean`\n- **Default:** `!process.env.CI`\n- **CLI:** `--open`, `--open=false`\n\nOpen Vitest UI automatically if it's [enabled](/config/ui).\n"
  },
  {
    "path": "docs/config/outputfile.md",
    "content": "---\ntitle: outputFile | Config\noutline: deep\n---\n\n# outputFile <CRoot /> {#outputfile}\n\n- **Type:** `string | Record<string, string>`\n- **CLI:** `--outputFile=<path>`, `--outputFile.json=./path`\n\nWrite test results to a file when the `--reporter=json`, `--reporter=html` or `--reporter=junit` option is also specified.\nBy providing an object instead of a string you can define individual outputs when using multiple reporters.\n"
  },
  {
    "path": "docs/config/passwithnotests.md",
    "content": "---\ntitle: passWithNoTests | Config\noutline: deep\n---\n\n# passWithNoTests <CRoot />\n\n- **Type**: `boolean`\n- **Default**: `false`\n- **CLI:** `--passWithNoTests`, `--passWithNoTests=false`\n\nVitest will not fail, if no tests will be found.\n"
  },
  {
    "path": "docs/config/pool.md",
    "content": "---\ntitle: pool | Config\noutline: deep\n---\n\n# pool\n\n- **Type:** `'threads' | 'forks' | 'vmThreads' | 'vmForks'`\n- **Default:** `'forks'`\n- **CLI:** `--pool=threads`\n\nPool used to run tests in.\n\n## threads\n\nEnable multi-threading. When using threads you are unable to use process related APIs such as `process.chdir()`. Some libraries written in native languages, such as Prisma, `bcrypt` and `canvas`, have problems when running in multiple threads and run into segfaults. In these cases it is advised to use `forks` pool instead.\n\n## forks\n\nSimilar as `threads` pool but uses `child_process` instead of `worker_threads`. Communication between tests and main process is not as fast as with `threads` pool. Process related APIs such as `process.chdir()` are available in `forks` pool.\n\n## vmThreads\n\nRun tests using [VM context](https://nodejs.org/api/vm.html) (inside a sandboxed environment) in a `threads` pool.\n\nThis makes tests run faster, but the VM module is unstable when running [ESM code](https://github.com/nodejs/node/issues/37648). Your tests will [leak memory](https://github.com/nodejs/node/issues/33439) - to battle that, consider manually editing [`vmMemoryLimit`](/config/vmmemorylimit) value.\n\n::: warning\nRunning code in a sandbox has some advantages (faster tests), but also comes with a number of disadvantages.\n\n- The globals within native modules, such as (`fs`, `path`, etc), differ from the globals present in your test environment. As a result, any error thrown by these native modules will reference a different Error constructor compared to the one used in your code:\n\n```ts\ntry {\n  fs.writeFileSync('/doesnt exist')\n}\ncatch (err) {\n  console.log(err instanceof Error) // false\n}\n```\n\n- Importing ES modules caches them indefinitely which introduces memory leaks if you have a lot of contexts (test files). There is no API in Node.js that clears that cache.\n- Accessing globals [takes longer](https://github.com/nodejs/node/issues/31658) in a sandbox environment.\n\nPlease, be aware of these issues when using this option. Vitest team cannot fix any of the issues on our side.\n:::\n\n## vmForks\n\nSimilar as `vmThreads` pool but uses `child_process` instead of `worker_threads`. Communication between tests and the main process is not as fast as with `vmThreads` pool. Process related APIs such as `process.chdir()` are available in `vmForks` pool. Please be aware that this pool has the same pitfalls listed in `vmThreads`.\n"
  },
  {
    "path": "docs/config/printconsoletrace.md",
    "content": "---\ntitle: printConsoleTrace | Config\noutline: deep\n---\n\n# printConsoleTrace\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nAlways print console traces when calling any `console` method. This is useful for debugging.\n"
  },
  {
    "path": "docs/config/projects.md",
    "content": "---\ntitle: projects | Config\noutline: deep\n---\n\n# projects <CRoot />\n\n- **Type:** `TestProjectConfiguration[]`\n- **Default:** `[]`\n\nAn array of [projects](/guide/projects).\n"
  },
  {
    "path": "docs/config/provide.md",
    "content": "---\ntitle: provide | Config\noutline: deep\n---\n\n# provide\n\n- **Type:** `Partial<ProvidedContext>`\n\nDefine values that can be accessed inside your tests using `inject` method.\n\n:::code-group\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    provide: {\n      API_KEY: '123',\n    },\n  },\n})\n```\n```ts [api.test.js]\nimport { expect, inject, test } from 'vitest'\n\ntest('api key is defined', () => {\n  expect(inject('API_KEY')).toBe('123')\n})\n```\n:::\n\n::: warning\nProperties have to be strings and values need to be [serializable](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#supported_types) because this object will be transferred between different processes.\n:::\n\n::: tip\nIf you are using TypeScript, you will need to augment `ProvidedContext` type for type safe access:\n\n```ts [vitest.shims.d.ts]\ndeclare module 'vitest' {\n  export interface ProvidedContext {\n    API_KEY: string\n  }\n}\n\n// mark this file as a module so augmentation works correctly\nexport {}\n```\n:::\n"
  },
  {
    "path": "docs/config/reporters.md",
    "content": "---\ntitle: reporters | Config\n---\n\n# reporters <CRoot />\n\n- **Type:**\n\n```ts\ninterface UserConfig {\n  reporters?: ConfigReporter | Array<ConfigReporter>\n}\n\ntype ConfigReporter = string | Reporter | [string, object?]\n```\n\n- **Default:** [`'default'`](/guide/reporters#default-reporter) (or <code>[['default'](/guide/reporters#default-reporter), ['github-actions'](/guide/reporters#github-actions-reporter)]</code> when `process.env.GITHUB_ACTIONS === 'true'`)\n- **CLI:**\n  - `--reporter=tap` for a single reporter\n  - `--reporter=verbose --reporter=github-actions` for multiple reporters\n\nThis option defines a single reporter or a list of reporters available to Vitest during the test run.\n\nAlongside built-in reporters, you can also pass down a custom implementation of a [`Reporter` interface](/api/advanced/reporters), or a path to a module that exports it as a default export (e.g. `'./path/to/reporter.ts'`, `'@scope/reporter'`).\n\nYou can configure a reporter by providing a tuple: `[string, object]`, where the string is a reporter name, and the object is the reporter's options.\n\n::: warning\nNote that the [coverage](/guide/coverage) feature uses a different [`coverage.reporter`](/config/coverage#reporter) option instead of this one.\n:::\n\n## Built-in Reporters\n\n- [`default`](/guide/reporters#default-reporter)\n- [`verbose`](/guide/reporters#verbose-reporter)\n- [`tree`](/guide/reporters#tree-reporter)\n- [`dot`](/guide/reporters#dot-reporter)\n- [`junit`](/guide/reporters#junit-reporter)\n- [`json`](/guide/reporters#json-reporter)\n- [`html`](/guide/reporters#html-reporter)\n- [`tap`](/guide/reporters#tap-reporter)\n- [`tap-flat`](/guide/reporters#tap-flat-reporter)\n- [`hanging-process`](/guide/reporters#hanging-process-reporter)\n- [`github-actions`](/guide/reporters#github-actions-reporter)\n- [`agent`](/guide/reporters#agent-reporter)\n- [`blob`](/guide/reporters#blob-reporter)\n\n## Example\n\n::: code-group\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    reporters: [\n      'default',\n      // conditional reporter\n      process.env.CI ? 'github-actions' : {},\n      // custom reporter from npm package\n      // options are passed down as a tuple\n      [\n        'vitest-sonar-reporter',\n        { outputFile: 'sonar-report.xml' }\n      ],\n    ]\n  }\n})\n```\n```bash [CLI]\nvitest --reporter=github-actions --reporter=junit\n```\n:::\n"
  },
  {
    "path": "docs/config/resolvesnapshotpath.md",
    "content": "---\ntitle: resolveSnapshotPath | Config\noutline: deep\n---\n\n# resolveSnapshotPath <CRoot />\n\n- **Type**: `(testPath: string, snapExtension: string, context: { config: SerializedConfig }) => string`\n- **Default**: stores snapshot files in `__snapshots__` directory\n\nOverrides default snapshot path. For example, to store snapshots next to test files:\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    resolveSnapshotPath: (testPath, snapExtension) => testPath + snapExtension,\n  },\n})\n```\n\nYou can also use the `context` parameter to access the project's serialized config. This is useful when you have multiple [projects](/guide/projects) and want to store snapshots in different locations based on the project name:\n\n```ts\nimport { basename, dirname, join } from 'node:path'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    resolveSnapshotPath(testPath, snapExtension, context) {\n      return join(\n        dirname(testPath),\n        '__snapshots__',\n        context.config.name ?? 'default',\n        basename(testPath) + snapExtension,\n      )\n    },\n  },\n})\n```\n"
  },
  {
    "path": "docs/config/restoremocks.md",
    "content": "---\ntitle: restoreMocks | Config\noutline: deep\n---\n\n# restoreMocks\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nShould Vitest automatically call [`vi.restoreAllMocks()`](/api/vi#vi-restoreallmocks) before each test.\n\nThis restores all original implementations on spies created manually with [`vi.spyOn`](/api/vi#vi-spyon).\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    restoreMocks: true,\n  },\n})\n```\n\n::: warning\nBe aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will restore the implementation for all spies, including those currently being used by other tests in progress.\n:::\n"
  },
  {
    "path": "docs/config/retry.md",
    "content": "---\ntitle: retry | Config\noutline: deep\n---\n\n# retry\n\nRetry the test specific number of times if it fails.\n\n- **Type:** `number | { count?: number, delay?: number, condition?: RegExp }`\n- **Default:** `0`\n- **CLI:** `--retry <times>`, `--retry.count <times>`, `--retry.delay <ms>`, `--retry.condition <pattern>`\n\n## Basic Usage\n\nSpecify a number to retry failed tests:\n\n```ts\nexport default defineConfig({\n  test: {\n    retry: 3,\n  },\n})\n```\n\n## CLI Usage\n\nYou can also configure retry options from the command line:\n\n```bash\n# Simple retry count\nvitest --retry 3\n\n# Advanced options using dot notation\nvitest --retry.count 3 --retry.delay 500 --retry.condition 'ECONNREFUSED|timeout'\n```\n\n## Advanced Options <Version>4.1.0</Version> {#advanced-options}\n\nUse an object to configure retry behavior:\n\n```ts\nexport default defineConfig({\n  test: {\n    retry: {\n      count: 3, // Number of times to retry\n      delay: 1000, // Delay in milliseconds between retries\n      condition: /ECONNREFUSED|timeout/i, // RegExp to match errors that should trigger retry\n    },\n  },\n})\n```\n\n### count\n\nNumber of times to retry a test if it fails. Default is `0`.\n\n```ts\nexport default defineConfig({\n  test: {\n    retry: {\n      count: 2,\n    },\n  },\n})\n```\n\n### delay\n\nDelay in milliseconds between retry attempts. Useful for tests that interact with rate-limited APIs or need time to recover. Default is `0`.\n\n```ts\nexport default defineConfig({\n  test: {\n    retry: {\n      count: 3,\n      delay: 500, // Wait 500ms between retries\n    },\n  },\n})\n```\n\n### condition\n\nA RegExp pattern or a function to determine if a test should be retried based on the error.\n\n- When a **RegExp**, it's tested against the error message\n- When a **function**, it receives the error and returns a boolean\n\n::: warning\nWhen defining `condition` as a function, it must be done in a test file directly, not in a configuration file (configurations are serialized for worker threads).\n:::\n\n#### RegExp condition (in config file):\n\n```ts\nexport default defineConfig({\n  test: {\n    retry: {\n      count: 2,\n      condition: /ECONNREFUSED|ETIMEDOUT/i, // Retry on connection/timeout errors\n    },\n  },\n})\n```\n\n#### Function condition (in test file):\n\n```ts\nimport { describe, test } from 'vitest'\n\ndescribe('tests with advanced retry condition', () => {\n  test('with function condition', { retry: { count: 2, condition: error => error.message.includes('Network') } }, () => {\n    // test code\n  })\n})\n```\n\n## Test File Override\n\nYou can also define retry options per test or suite in test files:\n\n```ts\nimport { describe, test } from 'vitest'\n\ndescribe('flaky tests', {\n  retry: {\n    count: 2,\n    delay: 100,\n  },\n}, () => {\n  test('network request', () => {\n    // test code\n  })\n})\n\ntest('another test', {\n  retry: {\n    count: 3,\n    condition: error => error.message.includes('timeout'),\n  },\n}, () => {\n  // test code\n})\n```\n"
  },
  {
    "path": "docs/config/root.md",
    "content": "---\ntitle: root | Config\noutline: deep\n---\n\n# root\n\n- **Type:** `string`\n- **CLI:** `-r <path>`, `--root=<path>`\n\nProject root\n"
  },
  {
    "path": "docs/config/runner.md",
    "content": "---\ntitle: runner | Config\noutline: deep\n---\n\n# runner\n\n- **Type**: `VitestRunnerConstructor`\n- **Default**: `node`, when running tests, or `benchmark`, when running benchmarks\n\nPath to a custom test runner. This is an advanced feature and should be used with custom library runners. You can read more about it in [the documentation](/api/advanced/runner).\n"
  },
  {
    "path": "docs/config/sequence.md",
    "content": "---\ntitle: sequence | Config\noutline: deep\n---\n\n# sequence\n\n- **Type**: `{ sequencer?, shuffle?, seed?, hooks?, setupFiles?, groupOrder }`\n\nOptions for how tests should be sorted.\n\nYou can provide sequence options to CLI with dot notation:\n\n```sh\nnpx vitest --sequence.shuffle --sequence.seed=1000\n```\n\n## sequence.sequencer <CRoot />\n\n- **Type**: `TestSequencerConstructor`\n- **Default**: `BaseSequencer`\n\nA custom class that defines methods for sharding and sorting. You can extend `BaseSequencer` from `vitest/node`, if you only need to redefine one of the `sort` and `shard` methods, but both should exist.\n\nSharding is happening before sorting, and only if `--shard` option is provided.\n\nIf [`sequence.groupOrder`](#sequence-grouporder) is specified, the sequencer will be called once for each group and pool.\n\n## sequence.groupOrder\n\n- **Type:** `number`\n- **Default:** `0`\n\nControls the order in which this project runs its tests when using multiple [projects](/guide/projects).\n\n- Projects with the same group order number will run together, and groups are run from lowest to highest.\n- If you don't set this option, all projects run in parallel.\n- If several projects use the same group order, they will run at the same time.\n\nThis setting only affects the order in which projects run, not the order of tests within a project.\nTo control test isolation or the order of tests inside a project, use the [`isolate`](/config/isolate) and [`sequence.sequencer`](/config/sequence#sequence-sequencer) options.\n\n::: details Example\nConsider this example:\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: 'slow',\n          sequence: {\n            groupOrder: 0,\n          },\n        },\n      },\n      {\n        test: {\n          name: 'fast',\n          sequence: {\n            groupOrder: 0,\n          },\n        },\n      },\n      {\n        test: {\n          name: 'flaky',\n          sequence: {\n            groupOrder: 1,\n          },\n        },\n      },\n    ],\n  },\n})\n```\n\nTests in these projects will run in this order:\n\n```\n 0. slow  |\n          |> running together\n 0. fast  |\n\n 1. flaky |> runs after slow and fast alone\n```\n:::\n\n## sequence.shuffle\n\n- **Type**: `boolean | { files?, tests? }`\n- **Default**: `false`\n- **CLI**: `--sequence.shuffle`, `--sequence.shuffle=false`\n\nIf you want files and tests to run randomly, you can enable it with this option, or CLI argument [`--sequence.shuffle`](/guide/cli).\n\nVitest usually uses cache to sort tests, so long-running tests start earlier, which makes tests run faster. If your files and tests run in random order, you will lose this performance improvement, but it may be useful to track tests that accidentally depend on another test run previously.\n\n### sequence.shuffle.files {#sequence-shuffle-files}\n\n- **Type**: `boolean`\n- **Default**: `false`\n- **CLI**: `--sequence.shuffle.files`, `--sequence.shuffle.files=false`\n\nWhether to randomize files, be aware that long running tests will not start earlier if you enable this option.\n\n### sequence.shuffle.tests {#sequence-shuffle-tests}\n\n- **Type**: `boolean`\n- **Default**: `false`\n- **CLI**: `--sequence.shuffle.tests`, `--sequence.shuffle.tests=false`\n\nWhether to randomize tests.\n\n## sequence.concurrent {#sequence-concurrent}\n\n- **Type**: `boolean`\n- **Default**: `false`\n- **CLI**: `--sequence.concurrent`, `--sequence.concurrent=false`\n\nIf you want tests to run in parallel, you can enable it with this option, or CLI argument [`--sequence.concurrent`](/guide/cli).\n\n::: warning\nWhen you run tests with `sequence.concurrent` and `expect.requireAssertions` set to `true`, you should use [local expect](/guide/test-context.html#expect) instead of the global one. Otherwise, this may cause false negatives in [some situations (#8469)](https://github.com/vitest-dev/vitest/issues/8469).\n:::\n\n## sequence.seed <CRoot />\n\n- **Type**: `number`\n- **Default**: `Date.now()`\n- **CLI**: `--sequence.seed=1000`\n\nSets the randomization seed, if tests are running in random order.\n\n## sequence.hooks\n\n- **Type**: `'stack' | 'list' | 'parallel'`\n- **Default**: `'stack'`\n- **CLI**: `--sequence.hooks=<value>`\n\nChanges the order in which hooks are executed.\n\n- `stack` will order \"after\" hooks in reverse order, \"before\" hooks will run in the order they were defined\n- `list` will order all hooks in the order they are defined\n- `parallel` runs hooks in a single group in parallel (hooks in parent suites still run before the current suite's hooks). The actual number of simultaneously running hooks is limited by [`maxConcurrency`](/config/maxconcurrency).\n\n::: tip\nThis option doesn't affect [`onTestFinished`](/api/hooks#ontestfinished). It is always called in reverse order.\n:::\n\n## sequence.setupFiles {#sequence-setupfiles}\n\n- **Type**: `'list' | 'parallel'`\n- **Default**: `'parallel'`\n- **CLI**: `--sequence.setupFiles=<value>`\n\nChanges the order in which setup files are executed.\n\n- `list` will run setup files in the order they are defined\n- `parallel` will run setup files in parallel\n"
  },
  {
    "path": "docs/config/server.md",
    "content": "---\ntitle: server | Config\noutline: deep\n---\n\n# server <Deprecated />\n\nBefore Vitest 4, this option was used to define the configuration for the `vite-node` server.\n\nAt the moment, this option allows you to configure the inlining and externalization mechanisms, along with the module runner debugging configuration.\n\n::: warning\nThese options should be used only as the last resort to improve performance by externalizing auto-inlined dependencies or to fix issues by inlining invalid external dependencies.\n\nNormally, Vitest should do this automatically.\n:::\n\n## server.deps\n\n### server.deps.external\n\n- **Type:** `(string | RegExp)[]`\n- **Default:** files inside [`moduleDirectories`](/config/deps#moduledirectories)\n\nSpecifies modules that should not be transformed by Vite and should instead be processed directly by the engine. These modules are imported via native dynamic `import` and bypass both transformation and resolution phases.\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    server: {\n      deps: {\n        external: ['react'],\n      },\n    },\n  },\n})\n```\n\nExternal modules and their dependencies are not present in the module graph and will not trigger test restarts when they change.\n\nTypically, packages under `node_modules` are externalized.\n\n::: tip\nIf a string is provided, it is first normalized by prefixing the `/node_modules/` or other [`moduleDirectories`](/config/deps#moduledirectories) segments (for example, `'react'` becomes `/node_modules/react/`), and the resulting string is then matched against the full file path. For example, package `@company/some-name` located inside `packages/some-name` should be specified as `some-name`, and `packages` should be included in `deps.moduleDirectories`.\n\nIf a `RegExp` is provided, it is matched against the full file path.\n:::\n\n### server.deps.inline\n\n- **Type:** `(string | RegExp)[] | true`\n- **Default:** everything that is not externalized\n\nSpecifies modules that should be transformed and resolved by Vite. These modules are run by Vite's [module runner](https://vite.dev/guide/api-environment-runtimes#modulerunner).\n\nTypically, your source files are inlined.\n\n::: tip\nIf a string is provided, it is first normalized by prefixing the `/node_modules/` or other [`moduleDirectories`](/config/deps#moduledirectories) segments (for example, `'react'` becomes `/node_modules/react/`), and the resulting string is then matched against the full file path. For example, package `@company/some-name` located inside `packages/some-name` should be specified as `some-name`, and `packages` should be included in `deps.moduleDirectories`.\n\nIf a `RegExp` is provided, it is matched against the full file path.\n:::\n\n### server.deps.fallbackCJS\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nWhen enabled, Vitest will try to guess a CommonJS build for an ESM entry by checking a few common CJS/UMD file name and folder patterns (like `.mjs`, `.umd.js`, `.cjs.js`, `umd/`, `cjs/`, `lib/`).\n\nThis is a best-effort heuristic to work around confusing or incorrect ESM/CJS packaging and may not work for all dependencies.\n"
  },
  {
    "path": "docs/config/setupfiles.md",
    "content": "---\ntitle: setupFiles | Config\noutline: deep\n---\n\n# setupFiles\n\n- **Type:** `string | string[]`\n\nPaths to setup files resolved relative to the [`root`](/config/root). They will run before each _test file_ in the same process. By default, all test files run in parallel, but you can configure it with [`sequence.setupFiles`](/config/sequence#sequence-setupfiles) option.\n\nVitest will ignore any exports from these files.\n\n:::warning\nNote that setup files are executed in the same process as tests, unlike [`globalSetup`](/config/globalsetup) that runs once in the main thread before any test worker is created.\n:::\n\n:::info\nEditing a setup file will automatically trigger a rerun of all tests.\n:::\n\nIf you have a heavy process running in the background, you can use `process.env.VITEST_POOL_ID` (integer-like string) inside to distinguish between workers and spread the workload.\n\n:::warning\nIf [isolation](/config/isolate) is disabled, imported modules are cached, but the setup file itself is executed again before each test file, meaning that you are accessing the same global object before each test file. Make sure you are not doing the same thing more than necessary.\n\nFor example, you may rely on a global variable:\n\n```ts\nimport { config } from '@some-testing-lib'\n\nif (!globalThis.setupInitialized) {\n  config.plugins = [myCoolPlugin]\n  computeHeavyThing()\n  globalThis.setupInitialized = true\n}\n\n// hooks reset before each test file\nafterEach(() => {\n  cleanup()\n})\n\nglobalThis.resetBeforeEachTest = true\n```\n:::\n"
  },
  {
    "path": "docs/config/silent.md",
    "content": "---\ntitle: silent | Config\noutline: deep\n---\n\n# silent <CRoot /> {#silent}\n\n- **Type:** `boolean | 'passed-only'`\n- **Default:** `false`\n- **CLI:** `--silent`, `--silent=false`\n\nSilent console output from tests.\n\nUse `'passed-only'` to see logs from failing tests only. Logs from failing tests are printed after a test has finished.\n"
  },
  {
    "path": "docs/config/slowtestthreshold.md",
    "content": "---\ntitle: slowTestThreshold | Config\noutline: deep\n---\n\n# slowTestThreshold <CRoot />\n\n- **Type**: `number`\n- **Default**: `300`\n- **CLI**: `--slow-test-threshold=<number>`, `--slowTestThreshold=<number>`\n\nThe number of milliseconds after which a test or suite is considered slow and reported as such in the results.\n"
  },
  {
    "path": "docs/config/snapshotenvironment.md",
    "content": "---\ntitle: snapshotEnvironment | Config\noutline: deep\n---\n\n# snapshotEnvironment\n\n- **Type:** `string`\n\nPath to a custom snapshot environment implementation. This is useful if you are running your tests in an environment that doesn't support Node.js APIs. This option doesn't have any effect on a browser runner.\n\nThis object should have the shape of `SnapshotEnvironment` and is used to resolve and read/write snapshot files:\n\n```ts\nexport interface SnapshotEnvironment {\n  getVersion: () => string\n  getHeader: () => string\n  resolvePath: (filepath: string) => Promise<string>\n  resolveRawPath: (testPath: string, rawPath: string) => Promise<string>\n  saveSnapshotFile: (filepath: string, snapshot: string) => Promise<void>\n  readSnapshotFile: (filepath: string) => Promise<string | null>\n  removeSnapshotFile: (filepath: string) => Promise<void>\n}\n```\n\nYou can extend default `VitestSnapshotEnvironment` from `vitest/snapshot` entry point if you need to overwrite only a part of the API.\n\n::: warning\nThis is a low-level option and should be used only for advanced cases where you don't have access to default Node.js APIs.\n\nIf you just need to configure snapshots feature, use [`snapshotFormat`](/config/snapshotformat) or [`resolveSnapshotPath`](/config/resolvesnapshotpath) options.\n:::\n"
  },
  {
    "path": "docs/config/snapshotformat.md",
    "content": "---\ntitle: snapshotFormat | Config\noutline: deep\n---\n\n# snapshotFormat <CRoot />\n\n- **Type:** `PrettyFormatOptions`\n\nFormat options for snapshot testing. These options are passed down to our fork of [`pretty-format`](https://npmx.dev/package/pretty-format). In addition to the `pretty-format` options we support `printShadowRoot: boolean`.\n\n::: tip\nBeware that `plugins` field on this object will be ignored.\n\nIf you need to extend snapshot serializer via pretty-format plugins, please, use [`expect.addSnapshotSerializer`](/api/expect#expect-addsnapshotserializer) API or [snapshotSerializers](/config/snapshotserializers) option.\n:::\n"
  },
  {
    "path": "docs/config/snapshotserializers.md",
    "content": "---\ntitle: snapshotSerializers | Config\noutline: deep\n---\n\n# snapshotSerializers <CRoot />\n\n- **Type:** `string[]`\n- **Default:** `[]`\n\nA list of paths to snapshot serializer modules for snapshot testing, useful if you want add custom snapshot serializers. See [Custom Serializer](/guide/snapshot#custom-serializer) for more information.\n"
  },
  {
    "path": "docs/config/stricttags.md",
    "content": "---\ntitle: strictTags | Config\noutline: deep\n---\n\n# strictTags <Version>4.1.0</Version> {#stricttags}\n\n- **Type:** `boolean`\n- **Default:** `true`\n- **CLI:** `--strict-tags`, `--no-strict-tags`\n\nShould Vitest throw an error if test has a [`tag`](/config/tags) that is not defined in the config to avoid silently doing something surprising due to mistyped names (applying the wrong configuration or skipping the test due to a `--tags-filter` flag).\n\nNote that Vitest will always throw an error if `--tags-filter` flag defines a tag not present in the config.\n\nFor example, this test will throw an error because the tag `fortnend` has a typo (it should be `frontend`):\n\n::: code-group\n```js [form.test.js]\ntest('renders a form', { tags: ['fortnend'] }, () => {\n  // ...\n})\n```\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    tags: [\n      { name: 'frontend' },\n    ],\n  },\n})\n```\n:::\n"
  },
  {
    "path": "docs/config/tags.md",
    "content": "---\ntitle: tags | Config\noutline: deep\n---\n\n# tags <Version>4.1.0</Version> {#tags}\n\n- **Type:** `TestTagDefinition[]`\n- **Default:** `[]`\n\nDefines all [available tags](/guide/test-tags) in your test project. By default, if test defines a name not listed here, Vitest will throw an error, but this can be configured via a [`strictTags`](/config/stricttags) option.\n\nIf you are using [`projects`](/config/projects), they will inherit all global tags definitions automatically.\n\nUse [`--tags-filter`](/guide/test-tags#syntax) to filter tests by their tags. Use [`--list-tags`](/guide/cli#listtags) to print every tag in your Vitest workspace.\n\n## name\n\n- **Type:** `string`\n- **Required:** `true`\n\nThe name of the tag. This is what you use in the `tags` option in tests.\n\n```ts\nexport default defineConfig({\n  test: {\n    tags: [\n      { name: 'unit' },\n      { name: 'e2e' },\n    ],\n  },\n})\n```\n\n::: tip\nIf you are using TypeScript, you can enforce what tags are available by augmenting the `TestTags` type with a property that contains a union of strings (make sure this file is included by your `tsconfig`):\n\n```ts [vitest.shims.ts]\nimport 'vitest'\n\ndeclare module 'vitest' {\n  interface TestTags {\n    tags:\n      | 'frontend'\n      | 'backend'\n      | 'db'\n      | 'flaky'\n  }\n}\n```\n:::\n\n## description\n\n- **Type:** `string`\n\nA human-readable description for the tag. This will be shown in UI and inside error messages when a tag is not found.\n\n```ts\nexport default defineConfig({\n  test: {\n    tags: [\n      {\n        name: 'slow',\n        description: 'Tests that take a long time to run.',\n      },\n    ],\n  },\n})\n```\n\n## priority\n\n- **Type:** `number`\n- **Default:** `Infinity`\n\nPriority for merging options when multiple tags with the same options are applied to a test. Lower number means higher priority (e.g., priority `1` takes precedence over priority `3`).\n\n```ts\nexport default defineConfig({\n  test: {\n    tags: [\n      {\n        name: 'flaky',\n        timeout: 30_000,\n        priority: 1, // higher priority\n      },\n      {\n        name: 'db',\n        timeout: 60_000,\n        priority: 2, // lower priority\n      },\n    ],\n  },\n})\n```\n\nWhen a test has both tags, the `timeout` will be `30_000` because `flaky` has a higher priority.\n\n## Test Options\n\nTags can define [test options](/api/test#test-options) that will be applied to every test marked with the tag. These options are merged with the test's own options, with the test's options taking precedence.\n\n::: warning\nThe [`retry.condition`](/api/test#retry) can onle be a regexp because the config values need to be serialised.\n\nTags also cannot apply other [tags](/api/test#tags) via these options.\n:::\n\n## Example\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    tags: [\n      {\n        name: 'unit',\n        description: 'Unit tests.',\n      },\n      {\n        name: 'e2e',\n        description: 'End-to-end tests.',\n        timeout: 60_000,\n      },\n      {\n        name: 'flaky',\n        description: 'Flaky tests that need retries.',\n        retry: process.env.CI ? 3 : 0,\n        priority: 1,\n      },\n      {\n        name: 'slow',\n        description: 'Slow tests.',\n        timeout: 120_000,\n      },\n      {\n        name: 'skip-ci',\n        description: 'Tests to skip in CI.',\n        skip: !!process.env.CI,\n      },\n    ],\n  },\n})\n```\n"
  },
  {
    "path": "docs/config/teardowntimeout.md",
    "content": "---\ntitle: teardownTimeout | Config\noutline: deep\n---\n\n# teardownTimeout <CRoot /> {#teardowntimeout}\n\n- **Type:** `number`\n- **Default:** `10000`\n- **CLI:** `--teardown-timeout=5000`, `--teardownTimeout=5000`\n\nDefault timeout to wait for close when Vitest shuts down, in milliseconds\n"
  },
  {
    "path": "docs/config/testnamepattern.md",
    "content": "---\ntitle: testNamePattern | Config\noutline: deep\n---\n\n# testNamePattern <CRoot /> {#testnamepattern}\n\n- **Type** `string | RegExp`\n- **CLI:** `-t <pattern>`, `--testNamePattern=<pattern>`, `--test-name-pattern=<pattern>`\n\nRun tests with full names matching the pattern.\nIf you add `OnlyRunThis` to this property, tests not containing the word `OnlyRunThis` in the test name will be skipped.\n\n```js\nimport { expect, test } from 'vitest'\n\n// run\ntest('OnlyRunThis', () => {\n  expect(true).toBe(true)\n})\n\n// skipped\ntest('doNotRun', () => {\n  expect(true).toBe(true)\n})\n```\n"
  },
  {
    "path": "docs/config/testtimeout.md",
    "content": "---\ntitle: testTimeout | Config\noutline: deep\n---\n\n# testTimeout\n\n- **Type:** `number`\n- **Default:** `5_000` in Node.js, `15_000` if `browser.enabled` is `true`\n- **CLI:** `--test-timeout=5000`, `--testTimeout=5000`\n\nDefault timeout of a test in milliseconds. Use `0` to disable timeout completely.\n"
  },
  {
    "path": "docs/config/typecheck.md",
    "content": "---\ntitle: typecheck | Config\noutline: deep\n---\n\n# typecheck <Experimental /> {#typecheck}\n\nOptions for configuring [typechecking](/guide/testing-types) test environment.\n\n## typecheck.enabled {#typecheck-enabled}\n\n- **Type**: `boolean`\n- **Default**: `false`\n- **CLI**: `--typecheck`, `--typecheck.enabled`\n\nEnable typechecking alongside your regular tests.\n\n## typecheck.only {#typecheck-only}\n\n- **Type**: `boolean`\n- **Default**: `false`\n- **CLI**: `--typecheck.only`\n\nRun only typecheck tests, when typechecking is enabled. When using CLI, this option will automatically enable typechecking.\n\n## typecheck.checker\n\n- **Type**: `'tsc' | 'vue-tsc' | string`\n- **Default**: `tsc`\n\nWhat tools to use for type checking. Vitest will spawn a process with certain parameters for easier parsing, depending on the type. Checker should implement the same output format as `tsc`.\n\nYou need to have a package installed to use typechecker:\n\n- `tsc` requires `typescript` package\n- `vue-tsc` requires `vue-tsc` package\n\nYou can also pass down a path to custom binary or command name that produces the same output as `tsc --noEmit --pretty false`.\n\n## typecheck.include\n\n- **Type**: `string[]`\n- **Default**: `['**/*.{test,spec}-d.?(c|m)[jt]s?(x)']`\n\nGlob pattern for files that should be treated as test files\n\n## typecheck.exclude\n\n- **Type**: `string[]`\n- **Default**: `['**/node_modules/**', '**/dist/**', '**/cypress/**', '**/.{idea,git,cache,output,temp}/**']`\n\nGlob pattern for files that should not be treated as test files\n\n## typecheck.allowJs\n\n- **Type**: `boolean`\n- **Default**: `false`\n\nCheck JS files that have `@ts-check` comment. If you have it enabled in tsconfig, this will not overwrite it.\n\n## typecheck.ignoreSourceErrors\n\n- **Type**: `boolean`\n- **Default**: `false`\n\nDo not fail, if Vitest found errors outside the test files. This will not show you non-test errors at all.\n\nBy default, if Vitest finds source error, it will fail test suite.\n\n## typecheck.tsconfig\n\n- **Type**: `string`\n- **Default**: _tries to find closest tsconfig.json_\n\nPath to custom tsconfig, relative to the project root.\n\n## typecheck.spawnTimeout\n\n- **Type**: `number`\n- **Default**: `10_000`\n\nMinimum time in milliseconds it takes to spawn the typechecker.\n"
  },
  {
    "path": "docs/config/ui.md",
    "content": "---\ntitle: ui | Config\noutline: deep\n---\n\n# ui <CRoot />\n\n- **Type:** `boolean`\n- **Default:** `false`\n- **CLI:** `--ui`, `--ui=false`\n\nEnable [Vitest UI](/guide/ui).\n\n::: warning\nThis features requires a [`@vitest/ui`](https://npmx.dev/package/@vitest/ui) package to be installed. If you do not have it already, Vitest will install it when you run the test command for the first time.\n:::\n\n::: danger SECURITY ADVICE\nMake sure that your UI server is not exposed to the network. Since Vitest 4.1 setting [`api.host`](/config/api) to anything other than `localhost` will disable the buttons to save the code or run any tests for security reasons, effectively making UI a readonly reporter.\n:::\n"
  },
  {
    "path": "docs/config/unstubenvs.md",
    "content": "---\ntitle: unstubEnvs | Config\noutline: deep\n---\n\n# unstubEnvs\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nShould Vitest automatically call [`vi.unstubAllEnvs()`](/api/vi#vi-unstuballenvs) before each test.\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    unstubEnvs: true,\n  },\n})\n```\n\n::: warning\nBe aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will restore all the values changed with [`vi.stubEnv`](/api/vi#vi-stubenv), including those currently being used by other tests in progress.\n:::\n"
  },
  {
    "path": "docs/config/unstubglobals.md",
    "content": "---\ntitle: unstubGlobals | Config\noutline: deep\n---\n\n# unstubGlobals\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nShould Vitest automatically call [`vi.unstubAllGlobals()`](/api/vi#vi-unstuballglobals) before each test.\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    unstubGlobals: true,\n  },\n})\n```\n\n::: warning\nBe aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will restore all global values that were changed with [`vi.stubGlobal`](/api/vi#vi-stubglobal), including those currently being used by other tests in progress.\n:::\n"
  },
  {
    "path": "docs/config/update.md",
    "content": "---\ntitle: update | Config\noutline: deep\n---\n\n# update <CRoot /> {#update}\n\n- **Type:** `boolean | 'new' | 'all' | 'none'`\n- **Default:** `false`\n- **CLI:** `-u`, `--update`, `--update=false`, `--update=new`, `--update=none`\n\nDefine snapshot update behavior.\n\n- `true` or `'all'`: updates all changed snapshots and deletes obsolete ones\n- `new`: generates new snapshots without changing or deleting obsolete ones\n- `none`: does not write snapshots and fails on snapshot mismatches, missing snapshots, and obsolete snapshots\n\nWhen `update` is `false` (the default), Vitest resolves snapshot update mode by environment:\n\n- Local runs (non-CI): works same as `new`\n- CI runs (`process.env.CI` is truthy): works same as `none`\n"
  },
  {
    "path": "docs/config/vmmemorylimit.md",
    "content": "---\ntitle: vmMemoryLimit | Config\noutline: deep\n---\n\n# vmMemoryLimit\n\n- **Type:** `string | number`\n- **Default:** `1 / CPU Cores`\n\nThis option affects only `vmForks` and `vmThreads` pools.\n\nSpecifies the memory limit for workers before they are recycled. This value heavily depends on your environment, so it's better to specify it manually instead of relying on the default.\n\n::: tip\nThe implementation is based on Jest's [`workerIdleMemoryLimit`](https://jestjs.io/docs/configuration#workeridlememorylimit-numberstring).\n\nThe limit can be specified in a number of different ways and whatever the result is `Math.floor` is used to turn it into an integer value:\n\n- `<= 1` - The value is assumed to be a percentage of system memory. So 0.5 sets the memory limit of the worker to half of the total system memory\n- `\\> 1` - Assumed to be a fixed byte value. Because of the previous rule if you wanted a value of 1 byte (I don't know why) you could use 1.1.\n- With units\n  - `50%` - As above, a percentage of total system memory\n  - `100KB`, `65MB`, etc - With units to denote a fixed memory limit.\n    - `K` / `KB` - Kilobytes (x1000)\n    - `KiB` - Kibibytes (x1024)\n    - `M` / `MB` - Megabytes\n    - `MiB` - Mebibytes\n    - `G` / `GB` - Gigabytes\n    - `GiB` - Gibibytes\n:::\n\n::: warning\nPercentage based memory limit [does not work on Linux CircleCI](https://github.com/jestjs/jest/issues/11956#issuecomment-1212925677) workers due to incorrect system memory being reported.\n:::\n"
  },
  {
    "path": "docs/config/watch.md",
    "content": "---\ntitle: watch | Config\noutline: deep\n---\n\n# watch <CRoot /> {#watch}\n\n- **Type:** `boolean`\n- **Default:** `!process.env.CI && process.stdin.isTTY`\n- **CLI:** `-w`, `--watch`, `--watch=false`\n\nEnable watch mode\n\nIn interactive environments, this is the default, unless `--run` is specified explicitly.\n\nIn CI, or when run from a non-interactive shell, \"watch\" mode is not the default, but can be enabled explicitly with this flag.\n"
  },
  {
    "path": "docs/config/watchtriggerpatterns.md",
    "content": "---\ntitle: watchTriggerPatterns | Config\noutline: deep\n---\n\n# watchTriggerPatterns <CRoot /> <Version>3.2.0</Version>\n\n- **Type:** `WatcherTriggerPattern[]`\n\nVitest reruns tests based on the module graph which is populated by static and dynamic `import` statements. However, if you are reading from the file system or fetching from a proxy, then Vitest cannot detect those dependencies.\n\nTo correctly rerun those tests, you can define a regex pattern and a function that returns a list of test files to run.\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    watchTriggerPatterns: [\n      {\n        pattern: /^src\\/(mailers|templates)\\/(.*)\\.(ts|html|txt)$/,\n        testsToRun: (id, match) => {\n          // relative to the root value\n          return `./api/tests/mailers/${match[2]}.test.ts`\n        },\n      },\n    ],\n  },\n})\n```\n\n::: warning\nReturned files should be either absolute or relative to the root. Note that this is a global option, and it cannot be used inside of [project](/guide/projects) configs.\n:::\n"
  },
  {
    "path": "docs/guide/advanced/index.md",
    "content": "---\ntitle: Advanced API\n---\n\n# Getting Started <Badge type=\"danger\">advanced</Badge> {#getting-started}\n\n::: warning\nThis guide lists advanced APIs to run tests via a Node.js script. If you just want to [run tests](/guide/), you probably don't need this. It is primarily used by library authors.\n:::\n\nYou can import any method from the `vitest/node` entry-point.\n\n## startVitest\n\n```ts\nfunction startVitest(\n  mode: VitestRunMode,\n  cliFilters: string[] = [],\n  options: CliOptions = {},\n  viteOverrides?: ViteUserConfig,\n  vitestOptions?: VitestOptions,\n): Promise<Vitest>\n```\n\nYou can start running Vitest tests using its Node API:\n\n```js\nimport { startVitest } from 'vitest/node'\n\nconst vitest = await startVitest('test')\n\nawait vitest.close()\n```\n\n`startVitest` function returns [`Vitest`](/api/advanced/vitest) instance if tests can be started.\n\nIf watch mode is not enabled, Vitest will call `close` method automatically.\n\nIf watch mode is enabled and the terminal supports TTY, Vitest will register console shortcuts.\n\nYou can pass down a list of filters as a second argument. Vitest will run only tests that contain at least one of the passed-down strings in their file path.\n\nAdditionally, you can use the third argument to pass in CLI arguments, which will override any test config options. Alternatively, you can pass in the complete Vite config as the fourth argument, which will take precedence over any other user-defined options.\n\nAfter running the tests, you can get the results from the [`state.getTestModules`](/api/advanced/test-module) API:\n\n```ts\nimport type { TestModule } from 'vitest/node'\n\nconst vitest = await startVitest('test')\n\nconsole.log(vitest.state.getTestModules()) // [TestModule]\n```\n\n::: tip\nThe [\"Running Tests\"](/guide/advanced/tests#startvitest) guide has a usage example.\n:::\n\n## createVitest\n\n```ts\nfunction createVitest(\n  mode: VitestRunMode,\n  options: CliOptions,\n  viteOverrides: ViteUserConfig = {},\n  vitestOptions: VitestOptions = {},\n): Promise<Vitest>\n```\n\nYou can create Vitest instance by using `createVitest` function. It returns the same [`Vitest`](/api/advanced/vitest) instance as `startVitest`, but it doesn't start tests and doesn't validate installed packages.\n\n```js\nimport { createVitest } from 'vitest/node'\n\nconst vitest = await createVitest('test', {\n  watch: false,\n})\n```\n\n::: tip\nThe [\"Running Tests\"](/guide/advanced/tests#createvitest) guide has a usage example.\n:::\n\n## resolveConfig\n\n```ts\nfunction resolveConfig(\n  options: UserConfig = {},\n  viteOverrides: ViteUserConfig = {},\n): Promise<{\n  vitestConfig: ResolvedConfig\n  viteConfig: ResolvedViteConfig\n}>\n```\n\nThis method resolves the config with custom parameters. If no parameters are given, the `root` will be `process.cwd()`.\n\n```ts\nimport { resolveConfig } from 'vitest/node'\n\n// vitestConfig only has resolved \"test\" properties\nconst { vitestConfig, viteConfig } = await resolveConfig({\n  mode: 'custom',\n  configFile: false,\n  resolve: {\n    conditions: ['custom']\n  },\n  test: {\n    setupFiles: ['/my-setup-file.js'],\n    pool: 'threads',\n  },\n})\n```\n\n::: info\nDue to how Vite's `createServer` works, Vitest has to resolve the config during the plugin's `configResolve` hook. Therefore, this method is not actually used internally and is exposed exclusively as a public API.\n\nIf you pass down the config to the `startVitest` or `createVitest` APIs, Vitest will still resolve the config again.\n:::\n\n::: warning\nThe `resolveConfig` doesn't resolve `projects`. To resolve projects configs, Vitest needs an established Vite server.\n\nAlso note that `viteConfig.test` will not be fully resolved. If you need Vitest config, use `vitestConfig` instead.\n:::\n\n## parseCLI\n\n```ts\nfunction parseCLI(argv: string | string[], config: CliParseOptions = {}): {\n  filter: string[]\n  options: CliOptions\n}\n```\n\nYou can use this method to parse CLI arguments. It accepts a string (where arguments are split by a single space) or a strings array of CLI arguments in the same format that Vitest CLI uses. It returns a filter and `options` that you can later pass down to `createVitest` or `startVitest` methods.\n\n```ts\nimport { parseCLI } from 'vitest/node'\n\nconst result = parseCLI('vitest ./files.ts --coverage --browser=chrome')\n\nresult.options\n// {\n//   coverage: { enabled: true },\n//   browser: { name: 'chrome', enabled: true }\n// }\n\nresult.filter\n// ['./files.ts']\n```\n"
  },
  {
    "path": "docs/guide/advanced/pool.md",
    "content": "# Custom Pool <Badge type=\"danger\">advanced</Badge> {#custom-pool}\n\n::: warning\nThis is an advanced, experimental and very low-level API. If you just want to [run tests](/guide/), you probably don't need this. It is primarily used by library authors.\n:::\n\nVitest runs tests in a pool. By default, there are several pool runners:\n\n- `threads` to run tests using `node:worker_threads` (isolation is provided with a new worker context)\n- `forks` to run tests using `node:child_process` (isolation is provided with a new `child_process.fork` process)\n- `vmThreads` to run tests using `node:worker_threads` (but isolation is provided with `vm` module instead of a new worker context)\n- `browser` to run tests using browser providers\n- `typescript` to run typechecking on tests\n\n::: tip\nSee [`vitest-pool-example`](https://npmx.dev/package/vitest-pool-example) for example of a custom pool runner implementation.\n:::\n\n## Usage\n\nYou can provide your own pool runner by a function that returns `PoolRunnerInitializer`.\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport customPool from './my-custom-pool.ts'\n\nexport default defineConfig({\n  test: {\n    // will run every file with a custom pool by default\n    pool: customPool({\n      customProperty: true,\n    })\n  },\n})\n```\n\nIf you need to run tests in different pools, use the [`projects`](/guide/projects) feature:\n\n```ts [vitest.config.ts]\nimport customPool from './my-custom-pool.ts'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        extends: true,\n        test: {\n          pool: 'threads',\n        },\n      },\n      {\n        extends: true,\n        test: {\n          pool: customPool({\n            customProperty: true,\n          })\n        }\n      }\n    ],\n  },\n})\n```\n\n## API\n\nThe `pool` option accepts a `PoolRunnerInitializer` that can be used for custom pool runners. The `name` property should indicate name of the custom pool runner. It should be identical with your worker's `name` property.\n\n```ts [my-custom-pool.ts]\nimport type { PoolRunnerInitializer } from 'vitest/node'\n\nexport function customPool(customOptions: CustomOptions): PoolRunnerInitializer {\n  return {\n    name: 'custom-pool',\n    createPoolWorker: options => new CustomPoolWorker(options, customOptions),\n  }\n}\n```\n\nIn your `CustomPoolWorker` you need to define all required methods:\n\n```ts [my-custom-pool.ts]\nimport type { PoolOptions, PoolWorker, WorkerRequest } from 'vitest/node'\n\nclass CustomPoolWorker implements PoolWorker {\n  name = 'custom-pool'\n  private customOptions: CustomOptions\n\n  constructor(options: PoolOptions, customOptions: CustomOptions) {\n    this.customOptions = customOptions\n  }\n\n  send(message: WorkerRequest): void {\n    // Provide way to send your worker a message\n  }\n\n  on(event: string, callback: (arg: any) => void): void {\n    // Provide way to listen to your workers events, e.g. message, error, exit\n  }\n\n  off(event: string, callback: (arg: any) => void): void {\n    // Provide way to unsubscribe `on` listeners\n  }\n\n  async start() {\n    // do something when the worker is started\n  }\n\n  async stop() {\n    // cleanup the state\n  }\n\n  deserialize(data) {\n    return data\n  }\n}\n```\n\nYour `CustomPoolRunner` will be controlling how your custom test runner worker life cycles and communication channel works. For example, your `CustomPoolRunner` could launch a `node:worker_threads` `Worker`, and provide communication via `Worker.postMessage` and `parentPort`.\n\nIn your worker file, you can import helper utilities from `vitest/worker`:\n\n```ts [my-worker.ts]\nimport { init, runBaseTests, setupEnvironment } from 'vitest/worker'\n\ninit({\n  post: (response) => {\n    // Provide way to send this message to CustomPoolRunner's onWorker as message event\n  },\n  on: (callback) => {\n    // Provide a way to listen CustomPoolRunner's \"postMessage\" calls\n  },\n  off: (callback) => {\n    // Optional, provide a way to remove listeners added by \"on\" calls\n  },\n  teardown: () => {\n    // Optional, provide a way to teardown worker, e.g. unsubscribe all the `on` listeners\n  },\n  serialize: (value) => {\n    // Optional, provide custom serializer for `post` calls\n  },\n  deserialize: (value) => {\n    // Optional, provide custom deserializer for `on` callbacks\n  },\n  runTests: (state, traces) => runBaseTests('run', state, traces),\n  collectTests: (state, traces) => runBaseTests('collect', state, traces),\n  setup: setupEnvironment,\n})\n```\n"
  },
  {
    "path": "docs/guide/advanced/reporters.md",
    "content": "# Extending Reporters <Badge type=\"danger\">advanced</Badge> {#extending-reporters}\n\n::: warning\nThis is an advanced API. If you just want to configure built-in reporters, read the [\"Reporters\"](/guide/reporters) guide.\n:::\n\nYou can import reporters from `vitest/node` and extend them to create your custom reporters.\n\n## Extending Built-in Reporters\n\nIn general, you don't need to create your reporter from scratch. `vitest` comes with several default reporting programs that you can extend.\n\n```ts\nimport { DefaultReporter } from 'vitest/node'\n\nexport default class MyDefaultReporter extends DefaultReporter {\n  // do something\n}\n```\n\n::: warning\nHowever, note that exposed reports are not considered stable and can change the shape of their API within a minor version.\n:::\n\nOf course, you can create your reporter from scratch. Just implement the [`Reporter`](/api/advanced/reporters) interface:\n\nAnd here is an example of a custom reporter:\n\n```ts [custom-reporter.js]\nimport type { Reporter } from 'vitest/node'\n\nexport default class CustomReporter implements Reporter {\n  onTestModuleCollected(testModule) {\n    console.log(testModule.moduleId, 'is finished')\n\n    for (const test of testModule.children.allTests()) {\n      console.log(test.name, test.result().state)\n    }\n  }\n}\n```\n\nThen you can use your custom reporter in the `vitest.config.ts` file:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport CustomReporter from './custom-reporter.js'\n\nexport default defineConfig({\n  test: {\n    reporters: [new CustomReporter()],\n  },\n})\n```\n\n## Reported Tasks\n\nReported [events](/api/advanced/reporters) receive tasks for [tests](/api/advanced/test-case), [suites](/api/advanced/test-suite) and [modules](/api/advanced/test-module):\n\n```ts twoslash\nimport type { Reporter, TestModule } from 'vitest/node'\n\nclass MyReporter implements Reporter {\n  onTestRunEnd(testModules: ReadonlyArray<TestModule>) {\n    for (const testModule of testModules) {\n      for (const task of testModule.children) {\n        //                          ^?\n        console.log('test run end', task.type, task.fullName)\n      }\n    }\n  }\n}\n```\n\n## Exported Reporters\n\n`vitest` comes with a few [built-in reporters](/guide/reporters) that you can use out of the box.\n\n### Built-in reporters:\n\n1. `DefaultReporter`\n2. `DotReporter`\n3. `JsonReporter`\n4. `VerboseReporter`\n5. `TapReporter`\n6. `JUnitReporter`\n7. `TapFlatReporter`\n8. `HangingProcessReporter`\n9. `TreeReporter`\n\n### Interface reporters:\n\n1. `Reporter`\n"
  },
  {
    "path": "docs/guide/advanced/tests.md",
    "content": "# Running Tests <Badge type=\"danger\">advanced</Badge> {#running-tests}\n\n::: warning\nThis guide explains how to use the advanced API to run tests via a Node.js script. If you just want to [run tests](/guide/), you probably don't need this. It is primarily used by library authors.\n:::\n\nVitest exposes two methods to initiate Vitest:\n\n- `startVitest` initiates Vitest, validates the packages are installed and runs tests immediately\n- `createVitest` only initiates Vitest and doesn't run any tests\n\n## `startVitest`\n\n```ts\nimport { startVitest } from 'vitest/node'\n\nconst vitest = await startVitest(\n  'test',\n  [], // CLI filters\n  {}, // override test config\n  {}, // override Vite config\n  {}, // custom Vitest options\n)\nconst testModules = vitest.state.getTestModules()\nfor (const testModule of testModules) {\n  console.log(testModule.moduleId, testModule.ok() ? 'passed' : 'failed')\n}\n```\n\n## `createVitest`\n\nCreates a [Vitest](/api/advanced/vitest) instances without running tests.\n\n`createVitest` method doesn't validate that required packages are installed. It also doesn't respect `config.standalone` or `config.mergeReports`. Vitest won't be closed automatically even if `watch` is disabled.\n\n```ts\nimport { createVitest } from 'vitest/node'\n\nconst vitest = await createVitest(\n  'test',\n  {}, // override test config\n  {}, // override Vite config\n  {}, // custom Vitest options\n)\n\n// called when `vitest.cancelCurrentRun()` is invoked\nvitest.onCancel(() => {})\n// called during `vitest.close()` call\nvitest.onClose(() => {})\n// called when Vitest reruns test files\nvitest.onTestsRerun((files) => {})\n\ntry {\n  // this will set process.exitCode to 1 if tests failed,\n  // and won't close the process automatically\n  await vitest.start(['my-filter'])\n}\ncatch (err) {\n  // this can throw\n  // \"FilesNotFoundError\" if no files were found\n  // \"GitNotFoundError\" with `--changed` and repository is not initialized\n}\nfinally {\n  await vitest.close()\n}\n```\n\nIf you intend to keep the `Vitest` instance, make sure to at least call [`init`](/api/advanced/vitest#init). This will initialise reporters and the coverage provider, but won't run any tests. It is also recommended to enable the `watch` mode even if you don't intend to use the Vitest watcher, but want to keep the instance running. Vitest relies on this flag for some of its features to work correctly in a continuous process.\n\nAfter reporters are initialised, use [`runTestSpecifications`](/api/advanced/vitest#runtestspecifications) or [`rerunTestSpecifications`](/api/advanced/vitest#reruntestspecifications) to run tests if manual run is required:\n\n```ts\nwatcher.on('change', async (file) => {\n  const specifications = vitest.getModuleSpecifications(file)\n  if (specifications.length) {\n    vitest.invalidateFile(file)\n    // you can use runTestSpecifications if \"reporter.onWatcher*\" hooks\n    // should not be invoked\n    await vitest.rerunTestSpecifications(specifications)\n  }\n})\n```\n\n::: warning\nThe example above shows a potential use-case if you disable the default watcher behaviour. By default, Vitest already reruns tests if files change.\n\nAlso note that `getModuleSpecifications` will not resolve test files unless they were already processed by `globTestSpecifications`. If the file was just created, use `project.matchesGlobPattern` instead:\n\n```ts\nwatcher.on('add', async (file) => {\n  const specifications = []\n  for (const project of vitest.projects) {\n    if (project.matchesGlobPattern(file)) {\n      specifications.push(project.createSpecification(file))\n    }\n  }\n\n  if (specifications.length) {\n    await vitest.rerunTestSpecifications(specifications)\n  }\n})\n```\n:::\n\nIn cases where you need to disable the watcher, you can pass down `server.watch: null` since Vite 5.3 or `server.watch: { ignored: ['*/*'] }` to a Vite config:\n\n```ts\nawait createVitest(\n  'test',\n  {},\n  {\n    plugins: [\n      {\n        name: 'stop-watcher',\n        async configureServer(server) {\n          await server.watcher.close()\n        }\n      }\n    ],\n    server: {\n      watch: null,\n    },\n  }\n)\n```\n"
  },
  {
    "path": "docs/guide/browser/component-testing.md",
    "content": "---\ntitle: Component Testing | Guide\noutline: deep\n---\n\n# Component Testing\n\nComponent testing is a testing strategy that focuses on testing individual UI components in isolation. Unlike end-to-end tests that test entire user flows, component tests verify that each component works correctly on its own, making them faster to run and easier to debug.\n\nVitest provides comprehensive support for component testing across multiple frameworks including Vue, React, Svelte, Lit, Preact, Qwik, Solid, Marko, and more. This guide covers the specific patterns, tools, and best practices for testing components effectively with Vitest.\n\n## Why Component Testing?\n\nComponent testing sits between unit tests and end-to-end tests, offering several advantages:\n\n- **Faster feedback** - Test individual components without loading entire applications\n- **Isolated testing** - Focus on component behavior without external dependencies\n- **Better debugging** - Easier to pinpoint issues in specific components\n- **Comprehensive coverage** - Test edge cases and error states more easily\n\n## Browser Mode for Component Testing\n\nComponent testing in Vitest uses **Browser Mode** to run tests in real browser environments using Playwright, WebdriverIO, or preview mode. This provides the most accurate testing environment as your components run in real browsers with actual DOM implementations, CSS rendering, and browser APIs.\n\n### Why Browser Mode?\n\nBrowser Mode is the recommended approach for component testing because it provides the most accurate testing environment. Unlike DOM simulation libraries, Browser Mode catches real-world issues that can affect your users.\n\n::: tip\nBrowser Mode catches issues that DOM simulation libraries might miss, including:\n- CSS layout and styling problems\n- Real browser API behavior\n- Accurate event handling and propagation\n- Proper focus management and accessibility features\n\n:::\n\n### Purpose of This Guide\n\nThis guide focuses specifically on **component testing patterns and best practices** using Vitest's capabilities. While many examples use Browser Mode (as it's the recommended approach), the focus here is on component-specific testing strategies rather than browser configuration details.\n\nFor detailed browser setup, configuration options, and advanced browser features, refer to the [Browser Mode documentation](/guide/browser/).\n\n## What Makes a Good Component Test\n\nGood component tests focus on **behavior and user experience** rather than implementation details:\n\n- **Test the contract** - How components receive inputs (props) and produce outputs (events, renders)\n- **Test user interactions** - Clicks, form submissions, keyboard navigation\n- **Test edge cases** - Error states, loading states, empty states\n- **Avoid testing internals** - State variables, private methods, CSS classes\n\n### Component Testing Hierarchy\n\n```\n1. Critical User Paths → Always test these\n2. Error Handling      → Test failure scenarios\n3. Edge Cases          → Empty data, extreme values\n4. Accessibility       → Screen readers, keyboard nav\n5. Performance         → Large datasets, animations\n```\n\n## Component Testing Strategies\n\n### Isolation Strategy\n\nTest components in isolation by mocking dependencies:\n\n```tsx\n// For API requests, we recommend MSW (Mock Service Worker)\n// See: https://vitest.dev/guide/mocking/requests\n//\n// vi.mock(import('../api/userService'), () => ({\n//   fetchUser: vi.fn().mockResolvedValue({ name: 'John' })\n// }))\n\n// Mock child components to focus on parent logic\nvi.mock(import('../components/UserCard'), () => ({\n  default: vi.fn(({ user }) => `<div>User: ${user.name}</div>`)\n}))\n\ntest('UserProfile handles loading and data states', async () => {\n  const { getByText } = render(<UserProfile userId=\"123\" />)\n\n  // Test loading state\n  await expect.element(getByText('Loading...')).toBeInTheDocument()\n\n  // Test for data to load (expect.element auto-retries)\n  await expect.element(getByText('User: John')).toBeInTheDocument()\n})\n```\n\n### Integration Strategy\n\nTest component collaboration and data flow:\n\n```tsx\ntest('ProductList filters and displays products correctly', async () => {\n  const mockProducts = [\n    { id: 1, name: 'Laptop', category: 'Electronics', price: 999 },\n    { id: 2, name: 'Book', category: 'Education', price: 29 }\n  ]\n\n  const { getByLabelText, getByText } = render(\n    <ProductList products={mockProducts} />\n  )\n\n  // Initially shows all products\n  await expect.element(getByText('Laptop')).toBeInTheDocument()\n  await expect.element(getByText('Book')).toBeInTheDocument()\n\n  // Filter by category\n  await userEvent.selectOptions(\n    getByLabelText(/category/i),\n    'Electronics'\n  )\n\n  // Only electronics should remain\n  await expect.element(getByText('Laptop')).toBeInTheDocument()\n  await expect.element(queryByText('Book')).not.toBeInTheDocument()\n})\n```\n\n## Testing Library Integration\n\nWhile Vitest provides official packages for popular frameworks ([`vitest-browser-vue`](https://npmx.dev/package/vitest-browser-vue), [`vitest-browser-react`](https://npmx.dev/package/vitest-browser-react), [`vitest-browser-svelte`](https://npmx.dev/package/vitest-browser-svelte)), you can integrate with [Testing Library](https://testing-library.com/) for frameworks not yet officially supported.\n\n### When to Use Testing Library\n\n- Your framework doesn't have an official Vitest browser package yet\n- You're migrating existing tests that use Testing Library\n- You prefer Testing Library's API for specific testing scenarios\n\n### Integration Pattern\n\nThe key is using `page.elementLocator()` to bridge Testing Library's DOM output with Vitest's browser mode APIs:\n\n```jsx\n// For Solid.js components\nimport { render } from '@testing-library/solid'\nimport { page } from 'vitest/browser'\n\ntest('Solid component handles user interaction', async () => {\n  // Use Testing Library to render the component\n  const { baseElement, getByRole } = render(() =>\n    <Counter initialValue={0} />\n  )\n\n  // Bridge to Vitest's browser mode for interactions and assertions\n  const screen = page.elementLocator(baseElement)\n\n  // Use Vitest's page queries for finding elements\n  const incrementButton = screen.getByRole('button', { name: /increment/i })\n\n  // Use Vitest's assertions and interactions\n  await expect.element(screen.getByText('Count: 0')).toBeInTheDocument()\n\n  // Trigger user interaction using Vitest's page API\n  await incrementButton.click()\n\n  await expect.element(screen.getByText('Count: 1')).toBeInTheDocument()\n})\n```\n\n### Available Testing Library Packages\n\nPopular Testing Library packages that work well with Vitest:\n\n- [`@testing-library/solid`](https://github.com/solidjs/solid-testing-library) - For Solid.js\n- [`@marko/testing-library`](https://testing-library.com/docs/marko-testing-library/intro) - For Marko\n- [`@testing-library/svelte`](https://testing-library.com/docs/svelte-testing-library/intro) - Alternative to [`vitest-browser-svelte`](https://npmx.dev/package/vitest-browser-svelte)\n- [`@testing-library/vue`](https://testing-library.com/docs/vue-testing-library/intro) - Alternative to [`vitest-browser-vue`](https://npmx.dev/package/vitest-browser-vue)\n\n::: tip Migration Path\nIf your framework gets official Vitest support later, you can gradually migrate by replacing Testing Library's `render` function while keeping most of your test logic intact.\n:::\n\n## Best Practices\n\n### 1. Use Browser Mode for CI/CD\nEnsure tests run in real browser environments for the most accurate testing. Browser Mode provides accurate CSS rendering, real browser APIs, and proper event handling.\n\n### 2. Test User Interactions\nSimulate real user behavior using Vitest's [Interactivity API](/api/browser/interactivity). Use `page.getByRole()` and `userEvent` methods as shown in our [Advanced Testing Patterns](#advanced-testing-patterns):\n\n```tsx\n// Good: Test actual user interactions\nawait page.getByRole('button', { name: /submit/i }).click()\nawait page.getByLabelText(/email/i).fill('user@example.com')\n\n// Avoid: Testing implementation details\n// component.setState({ email: 'user@example.com' })\n```\n\n### 3. Test Accessibility\nEnsure components work for all users by testing keyboard navigation, focus management, and ARIA attributes. See our [Testing Accessibility](#testing-accessibility) example for practical patterns:\n\n```tsx\n// Test keyboard navigation\nawait userEvent.keyboard('{Tab}')\nawait expect.element(document.activeElement).toHaveFocus()\n\n// Test ARIA attributes\nawait expect.element(modal).toHaveAttribute('aria-modal', 'true')\n```\n\n### 4. Mock External Dependencies\nFocus tests on component logic by mocking APIs and external services. This makes tests faster and more reliable. See our [Isolation Strategy](#isolation-strategy) for examples:\n\n```tsx\n// For API requests, we recommend using MSW (Mock Service Worker)\n// See: https://vitest.dev/guide/mocking/requests\n// This provides more realistic request/response mocking\n\n// For module mocking, use the import() syntax\nvi.mock(import('../components/UserCard'), () => ({\n  default: vi.fn(() => <div>Mocked UserCard</div>)\n}))\n```\n\n### 5. Use Meaningful Test Descriptions\nWrite test descriptions that explain the expected behavior, not implementation details:\n\n```tsx\n// Good: Describes user-facing behavior\ntest('shows error message when email format is invalid')\ntest('disables submit button while form is submitting')\n\n// Avoid: Implementation-focused descriptions\ntest('calls validateEmail function')\ntest('sets isSubmitting state to true')\n```\n\n## Advanced Testing Patterns\n\n### Testing Component State Management\n\n```tsx\n// Testing stateful components and state transitions\ntest('ShoppingCart manages items correctly', async () => {\n  const { getByText, getByTestId } = render(<ShoppingCart />)\n\n  // Initially empty\n  await expect.element(getByText('Your cart is empty')).toBeInTheDocument()\n\n  // Add item\n  await page.getByRole('button', { name: /add laptop/i }).click()\n\n  // Verify state change\n  await expect.element(getByText('1 item')).toBeInTheDocument()\n  await expect.element(getByText('Laptop - $999')).toBeInTheDocument()\n\n  // Test quantity updates\n  await page.getByRole('button', { name: /increase quantity/i }).click()\n  await expect.element(getByText('2 items')).toBeInTheDocument()\n})\n```\n\n### Testing Async Components with Data Fetching\n\n```tsx\n// Option 1: Recommended - Use MSW (Mock Service Worker) for API mocking\nimport { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\n// Set up MSW worker with API handlers\nconst worker = setupWorker(\n  http.get('/api/users/:id', ({ params }) => {\n    // Describe the happy path\n    return HttpResponse.json({ id: params.id, name: 'John Doe', email: 'john@example.com' })\n  })\n)\n\n// Start the worker before all tests\nbeforeAll(() => worker.start())\nafterEach(() => worker.resetHandlers())\nafterAll(() => worker.stop())\n\ntest('UserProfile handles loading, success, and error states', async () => {\n  // Test success state\n  const { getByText } = render(<UserProfile userId=\"123\" />)\n  // expect.element auto-retries until elements are found\n  await expect.element(getByText('John Doe')).toBeInTheDocument()\n  await expect.element(getByText('john@example.com')).toBeInTheDocument()\n\n  // Test error state by overriding the handler for this test\n  worker.use(\n    http.get('/api/users/:id', () => {\n      return HttpResponse.json({ error: 'User not found' }, { status: 404 })\n    })\n  )\n\n  const { getByText: getErrorText } = render(<UserProfile userId=\"999\" />)\n  await expect.element(getErrorText('Error: User not found')).toBeInTheDocument()\n})\n```\n\n::: tip\nSee more details on [using MSW in the browser](https://mswjs.io/docs/integrations/browser).\n:::\n\n### Testing Component Communication\n\n```tsx\n// Test parent-child component interaction\ntest('parent and child components communicate correctly', async () => {\n  const mockOnSelectionChange = vi.fn()\n\n  const { getByText } = render(\n    <ProductCatalog onSelectionChange={mockOnSelectionChange}>\n      <ProductFilter />\n      <ProductGrid />\n    </ProductCatalog>\n  )\n\n  // Interact with child component\n  await page.getByRole('checkbox', { name: /electronics/i }).click()\n\n  // Verify parent receives the communication\n  expect(mockOnSelectionChange).toHaveBeenCalledWith({\n    category: 'electronics',\n    filters: ['electronics']\n  })\n\n  // Verify other child component updates (expect.element auto-retries)\n  await expect.element(getByText('Showing Electronics products')).toBeInTheDocument()\n})\n```\n\n### Testing Complex Forms with Validation\n\n```tsx\ntest('ContactForm handles complex validation scenarios', async () => {\n  const mockSubmit = vi.fn()\n  const { getByLabelText, getByText } = render(\n    <ContactForm onSubmit={mockSubmit} />\n  )\n\n  const nameInput = page.getByLabelText(/full name/i)\n  const emailInput = page.getByLabelText(/email/i)\n  const messageInput = page.getByLabelText(/message/i)\n  const submitButton = page.getByRole('button', { name: /send message/i })\n\n  // Test validation triggers\n  await submitButton.click()\n\n  await expect.element(getByText('Name is required')).toBeInTheDocument()\n  await expect.element(getByText('Email is required')).toBeInTheDocument()\n  await expect.element(getByText('Message is required')).toBeInTheDocument()\n\n  // Test partial validation\n  await nameInput.fill('John Doe')\n  await submitButton.click()\n\n  await expect.element(getByText('Name is required')).not.toBeInTheDocument()\n  await expect.element(getByText('Email is required')).toBeInTheDocument()\n\n  // Test email format validation\n  await emailInput.fill('invalid-email')\n  await submitButton.click()\n\n  await expect.element(getByText('Please enter a valid email')).toBeInTheDocument()\n\n  // Test successful submission\n  await emailInput.fill('john@example.com')\n  await messageInput.fill('Hello, this is a test message.')\n  await submitButton.click()\n\n  expect(mockSubmit).toHaveBeenCalledWith({\n    name: 'John Doe',\n    email: 'john@example.com',\n    message: 'Hello, this is a test message.'\n  })\n})\n```\n\n### Testing Error Boundaries\n\n```tsx\n// Test how components handle and recover from errors\nfunction ThrowError({ shouldThrow }: { shouldThrow: boolean }) {\n  if (shouldThrow) {\n    throw new Error('Component error!')\n  }\n  return <div>Component working fine</div>\n}\n\ntest('ErrorBoundary catches and displays errors gracefully', async () => {\n  const { getByText, rerender } = render(\n    <ErrorBoundary fallback={<div>Something went wrong</div>}>\n      <ThrowError shouldThrow={false} />\n    </ErrorBoundary>\n  )\n\n  // Initially working\n  await expect.element(getByText('Component working fine')).toBeInTheDocument()\n\n  // Trigger error\n  rerender(\n    <ErrorBoundary fallback={<div>Something went wrong</div>}>\n      <ThrowError shouldThrow={true} />\n    </ErrorBoundary>\n  )\n\n  // Error boundary should catch it\n  await expect.element(getByText('Something went wrong')).toBeInTheDocument()\n})\n```\n\n### Testing Accessibility\n\n```tsx\ntest('Modal component is accessible', async () => {\n  const { getByRole, getByLabelText } = render(\n    <Modal isOpen={true} title=\"Settings\">\n      <SettingsForm />\n    </Modal>\n  )\n\n  // Test focus management - modal should receive focus when opened\n  // This is crucial for screen reader users to know a modal opened\n  const modal = getByRole('dialog')\n  await expect.element(modal).toHaveFocus()\n\n  // Test ARIA attributes - these provide semantic information to screen readers\n  await expect.element(modal).toHaveAttribute('aria-labelledby') // Links to title element\n  await expect.element(modal).toHaveAttribute('aria-modal', 'true') // Indicates modal behavior\n\n  // Test keyboard navigation - Escape key should close modal\n  // This is required by ARIA authoring practices\n  await userEvent.keyboard('{Escape}')\n  // expect.element auto-retries until modal is removed\n  await expect.element(modal).not.toBeInTheDocument()\n\n  // Test focus trap - tab navigation should cycle within modal\n  // This prevents users from tabbing to content behind the modal\n  const firstInput = getByLabelText(/username/i)\n  const lastButton = getByRole('button', { name: /save/i })\n\n  // Use click to focus on the first input, then test tab navigation\n  await firstInput.click()\n  await userEvent.keyboard('{Shift>}{Tab}{/Shift}') // Shift+Tab goes backwards\n  await expect.element(lastButton).toHaveFocus() // Should wrap to last element\n})\n```\n\n## Debugging Component Tests\n\n### 1. Use Browser Dev Tools\n\nBrowser Mode runs tests in real browsers, giving you access to full developer tools. When tests fail, you can:\n\n- **Open browser dev tools** during test execution (F12 or right-click → Inspect)\n- **Set breakpoints** in your test code or component code\n- **Inspect the DOM** to see the actual rendered output\n- **Check console errors** for JavaScript errors or warnings\n- **Monitor network requests** to debug API calls\n\nFor headful mode debugging, add `headless: false` to your browser config temporarily.\n\n### 2. Add Debug Statements\n\nUse strategic logging to understand test failures:\n\n```tsx\ntest('debug form validation', async () => {\n  render(<ContactForm />)\n\n  const submitButton = page.getByRole('button', { name: /submit/i })\n  await submitButton.click()\n\n  // Debug: Check if element exists with different query\n  const errorElement = page.getByText('Email is required')\n  console.log('Error element found:', errorElement.length)\n\n  await expect.element(errorElement).toBeInTheDocument()\n})\n```\n\n### 3. Inspect Rendered Output\n\nWhen components don't render as expected, investigate systematically:\n\n**Use Vitest's browser UI:**\n- Run tests with browser mode enabled\n- Open the browser URL shown in the terminal to see tests running\n- Visual inspection helps identify CSS issues, layout problems, or missing elements\n\n**Test element queries:**\n```tsx\n// Debug why elements can't be found\nconst button = page.getByRole('button', { name: /submit/i })\nconsole.log('Button count:', button.length) // Should be 1\n\n// Try alternative queries if the first one fails\nif (button.length === 0) {\n  console.log('All buttons:', page.getByRole('button').length)\n  console.log('By test ID:', page.getByTestId('submit-btn').length)\n}\n```\n\n### 4. Verify Selectors\n\nSelector issues are common causes of test failures. Debug them systematically:\n\n**Check accessible names:**\n```tsx\n// If getByRole fails, check what roles/names are available\nconst buttons = page.getByRole('button').all()\nfor (const button of buttons) {\n  // Use element() to get the DOM element and access native properties\n  const element = button.element()\n  const accessibleName = element.getAttribute('aria-label') || element.textContent\n  console.log(`Button: \"${accessibleName}\"`)\n}\n```\n\n**Test different query strategies:**\n```tsx\n// Multiple ways to find the same element using .or for auto-retrying\nconst submitButton = page.getByRole('button', { name: /submit/i }) // By accessible name\n  .or(page.getByTestId('submit-button')) // By test ID\n  .or(page.getByText('Submit')) // By exact text\n// Note: Vitest doesn't have page.locator(), use specific getBy* methods instead\n```\n\n**Common selector debugging patterns:**\n```tsx\ntest('debug element queries', async () => {\n  render(<LoginForm />)\n\n  // Check if element is visible and enabled\n  const emailInput = page.getByLabelText(/email/i)\n  await expect.element(emailInput).toBeVisible() // Will show if element is visible and print DOM if not\n})\n```\n\n### 5. Debugging Async Issues\n\nComponent tests often involve timing issues:\n\n```tsx\ntest('debug async component behavior', async () => {\n  render(<AsyncUserProfile userId=\"123\" />)\n\n  // expect.element will automatically retry and show helpful error messages\n  await expect.element(page.getByText('John Doe')).toBeInTheDocument()\n})\n```\n\n## Migration from Other Testing Frameworks\n\n### From Jest + Testing Library\n\nMost Jest + Testing Library tests work with minimal changes:\n\n```ts\n// Before (Jest)\nimport { render, screen } from '@testing-library/react' // [!code --]\n\n// After (Vitest)\nimport { render } from 'vitest-browser-react' // [!code ++]\n```\n\n### Key Differences\n\n- Use `await expect.element()` instead of `expect()` for DOM assertions\n- Use `vitest/browser` for user interactions instead of `@testing-library/user-event`\n- Browser Mode provides real browser environment for accurate testing\n\n## Learn More\n\n- [Browser Mode Documentation](/guide/browser/)\n- [Assertion API](/api/browser/assertions)\n- [Interactivity API](/api/browser/interactivity)\n- [Example Repository](https://github.com/vitest-tests/browser-examples)\n"
  },
  {
    "path": "docs/guide/browser/index.md",
    "content": "---\ntitle: Browser Mode | Guide\noutline: deep\n---\n\n# Browser Mode {#browser-mode}\n\nThis page provides information about the browser mode feature in the Vitest API, which allows you to run your tests in the browser natively, providing access to browser globals like window and document.\n\n::: tip\nIf you are looking for documentation for `expect`, `vi` or any general API like test projects or type testing, refer to the [\"Getting Started\" guide](/guide/).\n:::\n\n<img alt=\"Vitest UI\" img-light src=\"/ui-browser-1-light.png\">\n<img alt=\"Vitest UI\" img-dark src=\"/ui-browser-1-dark.png\">\n\n## Installation\n\nFor easier setup, you can use `vitest init browser` command to install required dependencies and create browser configuration.\n\n::: code-group\n```bash [npm]\nnpx vitest init browser\n```\n```bash [yarn]\nyarn exec vitest init browser\n```\n```bash [pnpm]\npnpx vitest init browser\n```\n```bash [bun]\nbunx vitest init browser\n```\n:::\n\n### Manual Installation\n\nYou can also install packages manually. Vitest always requires a provider to be defined. You can chose either [`preview`](/config/browser/preview), [`playwright`](/config/browser/playwright) or [`webdriverio`](/config/browser/webdriverio).\n\nIf you want to just preview how your tests look, you can use the `preview` provider:\n\n::: code-group\n```bash [npm]\nnpm install -D vitest @vitest/browser-preview\n```\n```bash [yarn]\nyarn add -D vitest @vitest/browser-preview\n```\n```bash [pnpm]\npnpm add -D vitest @vitest/browser-preview\n```\n```bash [bun]\nbun add -D vitest @vitest/browser-preview\n```\n:::\n\n::: warning\nHowever, to run tests in CI you need to install either [`playwright`](https://npmx.dev/package/playwright) or [`webdriverio`](https://npmx.dev/package/webdriverio). We also recommend switching to either one of them for testing locally instead of using the default `preview` provider since it relies on simulating events instead of using Chrome DevTools Protocol.\n\nIf you don't already use one of these tools, we recommend starting with Playwright because it supports parallel execution, which makes your tests run faster.\n\n::: tabs key:provider\n== Playwright\n[Playwright](https://npmx.dev/package/playwright) is a framework for Web Testing and Automation.\n\n::: code-group\n```bash [npm]\nnpm install -D vitest @vitest/browser-playwright\n```\n```bash [yarn]\nyarn add -D vitest @vitest/browser-playwright\n```\n```bash [pnpm]\npnpm add -D vitest @vitest/browser-playwright\n```\n```bash [bun]\nbun add -D vitest @vitest/browser-playwright\n```\n== WebdriverIO\n\n[WebdriverIO](https://npmx.dev/package/webdriverio) allows you to run tests locally using the WebDriver protocol.\n\n::: code-group\n```bash [npm]\nnpm install -D vitest @vitest/browser-webdriverio\n```\n```bash [yarn]\nyarn add -D vitest @vitest/browser-webdriverio\n```\n```bash [pnpm]\npnpm add -D vitest @vitest/browser-webdriverio\n```\n```bash [bun]\nbun add -D vitest @vitest/browser-webdriverio\n```\n:::\n\n## Configuration\n\nTo activate browser mode in your Vitest configuration, set the `browser.enabled` field to `true` in your Vitest configuration file. Here is an example configuration using the browser field:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright(),\n      enabled: true,\n      // at least one instance is required\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  }\n})\n```\n\n::: info\nVitest assigns port `63315` to avoid conflicts with the development server, allowing you to run both in parallel. You can change that with the [`browser.api`](/config/browser/api) option.\n\nThe CLI does not print the Vite server URL automatically. You can press \"b\" to print the URL when running in watch mode.\n:::\n\nIf you have not used Vite before, make sure you have your framework's plugin installed and specified in the config. Some frameworks might require extra configuration to work - check their Vite related documentation to be sure.\n\n::: code-group\n```ts [react]\nimport { defineConfig } from 'vitest/config'\nimport react from '@vitejs/plugin-react'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  plugins: [react()],\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    }\n  }\n})\n```\n```ts [vue]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\nimport vue from '@vitejs/plugin-vue'\n\nexport default defineConfig({\n  plugins: [vue()],\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    }\n  }\n})\n```\n```ts [svelte]\nimport { defineConfig } from 'vitest/config'\nimport { svelte } from '@sveltejs/vite-plugin-svelte'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  plugins: [svelte()],\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    }\n  }\n})\n```\n```ts [solid]\nimport { defineConfig } from 'vitest/config'\nimport solidPlugin from 'vite-plugin-solid'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  plugins: [solidPlugin()],\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    }\n  }\n})\n```\n```ts [marko]\nimport { defineConfig } from 'vitest/config'\nimport marko from '@marko/vite'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  plugins: [marko()],\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    }\n  }\n})\n```\n```ts [qwik]\nimport { defineConfig } from 'vitest/config'\nimport { qwikVite } from '@builder.io/qwik/optimizer'\nimport { playwright } from '@vitest/browser-playwright'\n\n// optional, run the tests in SSR mode\nimport { testSSR } from 'vitest-browser-qwik/ssr-plugin'\n\nexport default defineConfig({\n  plugins: [testSSR(), qwikVite()],\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [{ browser: 'chromium' }]\n    },\n  },\n})\n```\n:::\n\nIf you need to run some tests using Node-based runner, you can define a [`projects`](/guide/projects) option with separate configurations for different testing strategies:\n\n{#projects-config}\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          // an example of file based convention,\n          // you don't have to follow it\n          include: [\n            'tests/unit/**/*.{test,spec}.ts',\n            'tests/**/*.unit.{test,spec}.ts',\n          ],\n          name: 'unit',\n          environment: 'node',\n        },\n      },\n      {\n        test: {\n          // an example of file based convention,\n          // you don't have to follow it\n          include: [\n            'tests/browser/**/*.{test,spec}.ts',\n            'tests/**/*.browser.{test,spec}.ts',\n          ],\n          name: 'browser',\n          browser: {\n            enabled: true,\n            provider: playwright(),\n            instances: [\n              { browser: 'chromium' },\n            ],\n          },\n        },\n      },\n    ],\n  },\n})\n```\n\n## Browser Option Types\n\nThe browser option in Vitest depends on the provider. Vitest will fail, if you pass `--browser` and don't specify its name in the config file. Available options:\n\n- `webdriverio` supports these browsers:\n  - `firefox`\n  - `chrome`\n  - `edge`\n  - `safari`\n- `playwright` supports these browsers:\n  - `firefox`\n  - `webkit`\n  - `chromium`\n\n## Browser Compatibility\n\nVitest uses [Vite dev server](https://vitejs.dev/guide/#browser-support) to run your tests, so we only support features specified in the [`esbuild.target`](https://vitejs.dev/config/shared-options.html#esbuild) option (`esnext` by default).\n\nBy default, Vite targets browsers which support the native [ES Modules](https://caniuse.com/es6-module), native [ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta). On top of that, we utilize [`BroadcastChannel`](https://caniuse.com/?search=BroadcastChannel) to communicate between iframes:\n\n- Chrome >=87\n- Firefox >=78\n- Safari >=15.4\n- Edge >=88\n\n## Running Tests\n\nWhen you specify a browser name in the browser option, Vitest will try to run the specified browser using `preview` by default, and then run the tests there. If you don't want to use `preview`, you can configure the custom browser provider by using `browser.provider` option.\n\nTo specify a browser using the CLI, use the `--browser` flag followed by the browser name, like this:\n\n```sh\nnpx vitest --browser=chromium\n```\n\nOr you can provide browser options to CLI with dot notation:\n\n```sh\nnpx vitest --browser.headless\n```\n\n::: warning\nSince Vitest 3.2, if you don't have the `browser` option in your config but specify the `--browser` flag, Vitest will fail because it can't assume that config is meant for the browser and not Node.js tests.\n:::\n\nBy default, Vitest will automatically open the browser UI for development. Your tests will run inside an iframe in the center. You can configure the viewport by selecting the preferred dimensions, calling `page.viewport` inside the test, or setting default values in [the config](/config/browser/viewport).\n\n## Headless\n\nHeadless mode is another option available in the browser mode. In headless mode, the browser runs in the background without a user interface, which makes it useful for running automated tests. The headless option in Vitest can be set to a boolean value to enable or disable headless mode.\n\nWhen using headless mode, Vitest won't open the UI automatically. If you want to continue using the UI but have tests run headlessly, you can install the [`@vitest/ui`](/guide/ui) package and pass the `--ui` flag when running Vitest.\n\nHere's an example configuration enabling headless mode:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright(),\n      enabled: true,\n      headless: true,\n    },\n  }\n})\n```\n\nYou can also set headless mode using the `--browser.headless` flag in the CLI, like this:\n\n```sh\nnpx vitest --browser.headless\n```\n\nIn this case, Vitest will run in headless mode using the Chrome browser.\n\n::: warning\nHeadless mode is not available by default. You need to use either [`playwright`](https://npmx.dev/package/playwright) or [`webdriverio`](https://npmx.dev/package/webdriverio) providers to enable this feature.\n:::\n\n## Examples\n\nBy default, you don't need any external packages to work with the Browser Mode:\n\n```js [example.test.js]\nimport { expect, test } from 'vitest'\nimport { page } from 'vitest/browser'\nimport { render } from './my-render-function.js'\n\ntest('properly handles form inputs', async () => {\n  render() // mount DOM elements\n\n  // Asserts initial state.\n  await expect.element(page.getByText('Hi, my name is Alice')).toBeInTheDocument()\n\n  // Get the input DOM node by querying the associated label.\n  const usernameInput = page.getByLabelText(/username/i)\n\n  // Type the name into the input. This already validates that the input\n  // is filled correctly, no need to check the value manually.\n  await usernameInput.fill('Bob')\n\n  await expect.element(page.getByText('Hi, my name is Bob')).toBeInTheDocument()\n})\n```\n\nHowever, Vitest also provides packages to render components for several popular frameworks out of the box:\n\n- [`vitest-browser-vue`](https://github.com/vitest-dev/vitest-browser-vue) to render [vue](https://vuejs.org) components\n- [`vitest-browser-svelte`](https://github.com/vitest-dev/vitest-browser-svelte) to render [svelte](https://svelte.dev) components\n- [`vitest-browser-react`](https://github.com/vitest-dev/vitest-browser-react) to render [react](https://react.dev) components\n- [`vitest-browser-angular`](https://github.com/vitest-community/vitest-browser-angular) to render [Angular](https://angular.dev) components\n\nCommunity packages are available for other frameworks:\n\n- [`vitest-browser-lit`](https://github.com/EskiMojo14/vitest-browser-lit) to render [lit](https://lit.dev) components\n- [`vitest-browser-preact`](https://github.com/JoviDeCroock/vitest-browser-preact) to render [preact](https://preactjs.com) components\n- [`vitest-browser-qwik`](https://github.com/QwikDev/vitest-browser-qwik) to render [qwik](https://qwik.dev) components\n\nIf your framework is not represented, feel free to create your own package - it is a simple wrapper around the framework renderer and `page.elementLocator` API. We will add a link to it on this page. Make sure it has a name starting with `vitest-browser-`.\n\nBesides rendering components and locating elements, you will also need to make assertions. Vitest forks the [`@testing-library/jest-dom`](https://github.com/testing-library/jest-dom) library to provide a wide range of DOM assertions out of the box. Read more at the [Assertions API](/api/browser/assertions).\n\n```ts\nimport { expect } from 'vitest'\nimport { page } from 'vitest/browser'\n// element is rendered correctly\nawait expect.element(page.getByText('Hello World')).toBeInTheDocument()\n```\n\nVitest exposes a [Context API](/api/browser/context) with a small set of utilities that might be useful to you in tests. For example, if you need to make an interaction, like clicking an element or typing text into an input, you can use `userEvent` from `vitest/browser`. Read more at the [Interactivity API](/api/browser/interactivity).\n\n```ts\nimport { page, userEvent } from 'vitest/browser'\nawait userEvent.fill(page.getByLabelText(/username/i), 'Alice')\n// or just locator.fill\nawait page.getByLabelText(/username/i).fill('Alice')\n```\n\n::: code-group\n```ts [vue]\nimport { render } from 'vitest-browser-vue'\nimport Component from './Component.vue'\n\ntest('properly handles v-model', async () => {\n  const screen = render(Component)\n\n  // Asserts initial state.\n  await expect.element(screen.getByText('Hi, my name is Alice')).toBeInTheDocument()\n\n  // Get the input DOM node by querying the associated label.\n  const usernameInput = screen.getByLabelText(/username/i)\n\n  // Type the name into the input. This already validates that the input\n  // is filled correctly, no need to check the value manually.\n  await usernameInput.fill('Bob')\n\n  await expect.element(screen.getByText('Hi, my name is Bob')).toBeInTheDocument()\n})\n```\n```ts [svelte]\nimport { render } from 'vitest-browser-svelte'\nimport { expect, test } from 'vitest'\n\nimport Greeter from './greeter.svelte'\n\ntest('greeting appears on click', async () => {\n  const screen = render(Greeter, { name: 'World' })\n\n  const button = screen.getByRole('button')\n  await button.click()\n  const greeting = screen.getByText(/hello world/iu)\n\n  await expect.element(greeting).toBeInTheDocument()\n})\n```\n```tsx [react]\nimport { render } from 'vitest-browser-react'\nimport Fetch from './fetch'\n\ntest('loads and displays greeting', async () => {\n  // Render a React element into the DOM\n  const screen = render(<Fetch url=\"/greeting\" />)\n\n  await screen.getByText('Load Greeting').click()\n  // wait before throwing an error if it cannot find an element\n  const heading = screen.getByRole('heading')\n\n  // assert that the alert message is correct\n  await expect.element(heading).toHaveTextContent('hello there')\n  await expect.element(screen.getByRole('button')).toBeDisabled()\n})\n```\n```ts [lit]\nimport { render } from 'vitest-browser-lit'\nimport { html } from 'lit'\nimport './greeter-button'\n\ntest('greeting appears on click', async () => {\n  const screen = render(html`<greeter-button name=\"World\"></greeter-button>`)\n\n  const button = screen.getByRole('button')\n  await button.click()\n  const greeting = screen.getByText(/hello world/iu)\n\n  await expect.element(greeting).toBeInTheDocument()\n})\n```\n```tsx [preact]\nimport { render } from 'vitest-browser-preact'\nimport { createElement } from 'preact'\nimport Greeting from '.Greeting'\n\ntest('greeting appears on click', async () => {\n  const screen = render(<Greeting />)\n\n  const button = screen.getByRole('button')\n  await button.click()\n  const greeting = screen.getByText(/hello world/iu)\n\n  await expect.element(greeting).toBeInTheDocument()\n})\n```\n```tsx [qwik]\nimport { render } from 'vitest-browser-qwik'\nimport Greeting from './greeting'\n\ntest('greeting appears on click', async () => {\n  // renderSSR and renderHook are also available\n  const screen = render(<Greeting />)\n\n  const button = screen.getByRole('button')\n  await button.click()\n  const greeting = screen.getByText(/hello world/iu)\n\n  await expect.element(greeting).toBeInTheDocument()\n})\n```\n:::\n\nVitest doesn't support all frameworks out of the box, but you can use external tools to run tests with these frameworks. We also encourage the community to create their own `vitest-browser` wrappers - if you have one, feel free to add it to the examples above.\n\nFor unsupported frameworks, we recommend using `testing-library` packages:\n\n- [`@solidjs/testing-library`](https://testing-library.com/docs/solid-testing-library/intro) to render [solid](https://www.solidjs.com) components\n- [`@marko/testing-library`](https://testing-library.com/docs/marko-testing-library/intro) to render [marko](https://markojs.com) components\n\nYou can also see more examples in [`browser-examples`](https://github.com/vitest-tests/browser-examples) repository.\n\n::: warning\n`testing-library` provides a package `@testing-library/user-event`. We do not recommend using it directly because it simulates events instead of actually triggering them - instead, use [`userEvent`](/api/browser/interactivity) imported from `vitest/browser` that uses Chrome DevTools Protocol or Webdriver (depending on the provider) under the hood.\n:::\n\n::: code-group\n```tsx [solid]\n// based on @testing-library/solid API\n// https://testing-library.com/docs/solid-testing-library/api\n\nimport { render } from '@testing-library/solid'\n\nit('uses params', async () => {\n  const App = () => (\n    <>\n      <Route\n        path=\"/ids/:id\"\n        component={() => (\n          <p>\n            Id:\n            {useParams()?.id}\n          </p>\n        )}\n      />\n      <Route path=\"/\" component={() => <p>Start</p>} />\n    </>\n  )\n  const { baseElement } = render(() => <App />, { location: 'ids/1234' })\n  const screen = page.elementLocator(baseElement)\n\n  await expect.screen(screen.getByText('Id: 1234')).toBeInTheDocument()\n})\n```\n```ts [marko]\n// based on @testing-library/marko API\n// https://testing-library.com/docs/marko-testing-library/api\n\nimport { render, screen } from '@marko/testing-library'\nimport Greeting from './greeting.marko'\n\ntest('renders a message', async () => {\n  const { baseElement } = await render(Greeting, { name: 'Marko' })\n  const screen = page.elementLocator(baseElement)\n  await expect.element(screen.getByText(/Marko/)).toBeInTheDocument()\n  expect(container.firstChild).toMatchInlineSnapshot(`\n    <h1>Hello, Marko!</h1>\n  `)\n})\n```\n:::\n\n## Limitations\n\n### Thread Blocking Dialogs\n\nWhen using Vitest Browser, it's important to note that thread blocking dialogs like `alert` or `confirm` cannot be used natively. This is because they block the web page, which means Vitest cannot continue communicating with the page, causing the execution to hang.\n\nIn such situations, Vitest provides default mocks with default returned values for these APIs. This ensures that if the user accidentally uses synchronous popup web APIs, the execution would not hang. However, it's still recommended for the user to mock these web APIs for a better experience. Read more in [Mocking](/guide/mocking).\n\n### Spying on Module Exports\n\nBrowser Mode uses the browser's native ESM support to serve modules. The module namespace object is sealed and can't be reconfigured, unlike in Node.js tests where Vitest can patch the Module Runner. This means you can't call `vi.spyOn` on an imported object:\n\n```ts\nimport { vi } from 'vitest'\nimport * as module from './module.js'\n\nvi.spyOn(module, 'method') // ❌ throws an error\n```\n\nTo bypass this limitation, Vitest supports `{ spy: true }` option in `vi.mock('./module.js')`. This will automatically spy on every export in the module without replacing them with fake ones.\n\n```ts\nimport { vi } from 'vitest'\nimport * as module from './module.js'\n\nvi.mock('./module.js', { spy: true })\n\nvi.mocked(module.method).mockImplementation(() => {\n  // ...\n})\n```\n\nHowever, the only way to mock exported _variables_ is to export a method that will change the internal value:\n\n::: code-group\n```js [module.js]\nexport let MODE = 'test'\nexport function changeMode(newMode) {\n  MODE = newMode\n}\n```\n```js [module.test.ts]\nimport { expect } from 'vitest'\nimport { changeMode, MODE } from './module.js'\n\nchangeMode('production')\nexpect(MODE).toBe('production')\n```\n:::\n"
  },
  {
    "path": "docs/guide/browser/multiple-setups.md",
    "content": "# Multiple Setups\n\nYou can specify several different browser setups using the [`browser.instances`](/config/browser/instances) option.\n\nThe main advantage of using the `browser.instances` over the [test projects](/guide/projects) is improved caching. Every project will use the same Vite server meaning the file transform and [dependency pre-bundling](https://vite.dev/guide/dep-pre-bundling.html) has to happen only once.\n\n## Several Browsers\n\nYou can use the `browser.instances` field to specify options for different browsers. For example, if you want to run the same tests in different browsers, the minimal configuration will look like this:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      headless: true,\n      instances: [\n        { browser: 'chromium' },\n        { browser: 'firefox' },\n        { browser: 'webkit' },\n      ],\n    },\n  },\n})\n```\n\n## Different Setups\n\nYou can also specify different config options independently from the browser (although, the instances _can_ also have `browser` fields):\n\n::: code-group\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      headless: true,\n      instances: [\n        {\n          browser: 'chromium',\n          name: 'chromium-1',\n          setupFiles: ['./ratio-setup.ts'],\n          provide: {\n            ratio: 1,\n          },\n        },\n        {\n          browser: 'chromium',\n          name: 'chromium-2',\n          provide: {\n            ratio: 2,\n          },\n        },\n      ],\n    },\n  },\n})\n```\n```ts [example.test.ts]\nimport { expect, inject, test } from 'vitest'\nimport { globalSetupModifier } from './example.js'\n\ntest('ratio works', () => {\n  expect(inject('ratio') * globalSetupModifier).toBe(14)\n})\n```\n:::\n\nIn this example Vitest will run all tests in `chromium` browser, but execute a `'./ratio-setup.ts'` file only in the first configuration and inject a different `ratio` value depending on the [`provide` field](/config/provide).\n\n::: warning\nNote that you need to define the custom `name` value if you are using the same browser name because Vitest will assign the `browser` as the project name otherwise.\n:::\n\n## Filtering\n\nYou can filter what projects to run with the [`--project` flag](/guide/cli#project). Vitest will automatically assign the browser name as a project name if it is not assigned manually. If the root config already has a name, Vitest will merge them: `custom` -> `custom (browser)`.\n\n```shell\n$ vitest --project=chromium\n```\n\n::: code-group\n```ts{6,8} [default]\nexport default defineConfig({\n  test: {\n    browser: {\n      instances: [\n        // name: chromium\n        { browser: 'chromium' },\n        // name: custom\n        { browser: 'firefox', name: 'custom' },\n      ]\n    }\n  }\n})\n```\n```ts{3,7,9} [custom]\nexport default defineConfig({\n  test: {\n    name: 'custom',\n    browser: {\n      instances: [\n        // name: custom (chromium)\n        { browser: 'chromium' },\n        // name: manual\n        { browser: 'firefox', name: 'manual' },\n      ]\n    }\n  }\n})\n```\n:::\n"
  },
  {
    "path": "docs/guide/browser/trace-view.md",
    "content": "# Trace View\n\nVitest Browser Mode supports generating Playwright's [trace files](https://playwright.dev/docs/trace-viewer#viewing-remote-traces). To enable tracing, you need to set the [`trace`](/config/browser/trace) option in the `test.browser` configuration.\n\n::: warning\nGenerating trace files is only available when using the [Playwright provider](/config/browser/playwright).\n:::\n\n::: code-group\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright(),\n      trace: 'on',\n    },\n  },\n})\n```\n```bash [CLI]\nvitest --browser.trace=on\n```\n:::\n\nBy default, Vitest will generate a trace file for each test. You can also configure it to only generate traces on test failures by setting `trace` to `'on-first-retry'`, `'on-all-retries'` or `'retain-on-failure'`. The files will be saved in `__traces__` folder next to your test files. The name of the trace includes the project name, the test name, the [`repeats`](/api/test#repeats) count and [`retry`](/api/test#retry) count:\n\n```\nchromium-my-test-0-0.trace.zip\n^^^^^^^^ project name\n         ^^^^^^ test name\n                ^ repeat count\n                  ^ retry count\n```\n\nTo change the output directory, you can set the `tracesDir` option in the `test.browser.trace` configuration. This way all traces will be stored in the same directory, grouped by the test file.\n\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright(),\n      trace: {\n        mode: 'on',\n        // the path is relative to the root of the project\n        tracesDir: './playwright-traces',\n      },\n    },\n  },\n})\n```\n\nThe traces are available in reporters as [annotations](/guide/test-annotations). For example, in the HTML reporter, you can find the link to the trace file in the test details.\n\n## Trace markers\n\nYou can add explicit named markers to make the trace timeline easier to read:\n\n```ts\nimport { page } from 'vitest/browser'\n\ndocument.body.innerHTML = `\n  <button type=\"button\">Sign in</button>\n`\n\nawait page.getByRole('button', { name: 'Sign in' }).mark('sign in button rendered')\n```\n\nBoth `page.mark(name)` and `locator.mark(name)` are available.\n\nYou can also group multiple operations under one marker with `page.mark(name, callback)`:\n\n```ts\nawait page.mark('sign in flow', async () => {\n  await page.getByRole('textbox', { name: 'Email' }).fill('john@example.com')\n  await page.getByRole('textbox', { name: 'Password' }).fill('secret')\n  await page.getByRole('button', { name: 'Sign in' }).click()\n})\n```\n\nYou can also wrap reusable helpers with [`vi.defineHelper()`](/api/vi#vi-defineHelper) so trace entries point to where the helper is called, not its internals:\n\n```ts\nimport { vi } from 'vitest'\nimport { page } from 'vitest/browser'\n\nconst myRender = vi.defineHelper(async (content: string) => {\n  document.body.innerHTML = content\n  await page.elementLocator(document.body).mark('render helper')\n})\n\ntest('renders content', async () => {\n  await myRender('<button>Hello</button>') // trace points to this line\n})\n```\n\n## Preview\n\nTo open the trace file, you can use the Playwright Trace Viewer. Run the following command in your terminal:\n\n```bash\nnpx playwright show-trace \"path-to-trace-file\"\n```\n\nThis will start the Trace Viewer and load the specified trace file.\n\nAlternatively, you can open the Trace Viewer in your browser at https://trace.playwright.dev and upload the trace file there.\n\n<img alt=\"Trace Viewer showing the trace timeline and rendered component\" img-light src=\"/trace-viewer-light.png\">\n<img alt=\"Trace Viewer showing the trace timeline and rendered component\" img-dark src=\"/trace-viewer-dark.png\">\n\n## Source Location\n\nWhen you open a trace, you'll notice that Vitest groups browser interactions and links them back to the exact line in your test that triggered them. This happens automatically for:\n\n- `expect.element(...)` assertions\n- Interactive actions like `click`, `fill`, `type`, `hover`, `selectOptions`, `upload`, `dragAndDrop`, `tab`, `keyboard`, `wheel`, and screenshots\n\nUnder the hood, Playwright still records its own low-level action events as usual. Vitest wraps them with source-location groups so you can jump straight from the trace timeline to the relevant line in your test.\n\nKeep in mind that plain assertions like `expect(value).toBe(...)` run in Node, not the browser, so they won't show up in the trace.\n\nFor anything not covered automatically, you can use `page.mark()` or `locator.mark()` to add your own trace groups — see [Trace markers](#trace-markers) above.\n\n::: warning\n\nCurrently a source view of a trace can be only displayed properly when viewing it on the machine generated a trace with `playwright show-trace` CLI. This is expected to be fixed soon (see https://github.com/microsoft/playwright/pull/39307).\n\n:::\n"
  },
  {
    "path": "docs/guide/browser/visual-regression-testing.md",
    "content": "---\ntitle: Visual Regression Testing\noutline: [2, 3]\n---\n\n# Visual Regression Testing\n\nVitest can run visual regression tests out of the box. It captures screenshots\nof your UI components and pages, then compares them against reference images to\ndetect unintended visual changes.\n\nUnlike functional tests that verify behavior, visual tests catch styling issues,\nlayout shifts, and rendering problems that might otherwise go unnoticed without\nthorough manual testing.\n\n## Why Visual Regression Testing?\n\nVisual bugs don’t throw errors, they just look wrong. That’s where visual\ntesting comes in.\n\n- That button still submits the form... but why is it hot pink now?\n- The text fits perfectly... until someone views it on mobile\n- Everything works great... except those two containers are out of viewport\n- That careful CSS refactor works... but broke the layout on a page no one tests\n\nVisual regression testing acts as a safety net for your UI, automatically\ncatching these visual changes before they reach production.\n\n## Getting Started\n\n::: warning Browser Rendering Differences\nVisual regression tests are **inherently unstable across different\nenvironments**. Screenshots will look different on different machines because\nof:\n\n- Font rendering (the big one. Windows, macOS, Linux, they all render text\ndifferently)\n- GPU drivers and hardware acceleration\n- Whether you're running headless or not\n- Browser settings and versions\n- ...and honestly, sometimes just the phase of the moon\n\nThat's why Vitest includes the browser and platform in screenshot names (like\n`button-chromium-darwin.png`).\n\nFor stable tests, use the same environment everywhere. We **strongly recommend**\ncloud services like\n[Azure App Testing](https://azure.microsoft.com/en-us/products/app-testing/)\nor [Docker containers](https://playwright.dev/docs/docker).\n:::\n\nVisual regression testing in Vitest can be done through the\n[`toMatchScreenshot` assertion](/api/browser/assertions.html#tomatchscreenshot):\n\n```ts\nimport { expect, test } from 'vitest'\nimport { page } from 'vitest/browser'\n\ntest('hero section looks correct', async () => {\n  // ...the rest of the test\n\n  // capture and compare screenshot\n  await expect(page.getByTestId('hero')).toMatchScreenshot('hero-section')\n})\n```\n\n### Creating References\n\nWhen you run a visual test for the first time, Vitest creates a reference (also\ncalled baseline) screenshot and fails the test with the following error message:\n\n```\nexpect(element).toMatchScreenshot()\n\nNo existing reference screenshot found; a new one was created. Review it before running tests again.\n\nReference screenshot:\n  tests/__screenshots__/hero.test.ts/hero-section-chromium-darwin.png\n```\n\nThis is normal. Check that the screenshot looks right, then run the test again.\nVitest will now compare future runs against this baseline.\n\n::: tip\nReference screenshots live in `__screenshots__` folders next to your tests.\n**Don't forget to commit them!**\n:::\n\n### Screenshot Organization\n\nBy default, screenshots are organized as:\n\n```\n.\n├── __screenshots__\n│   └── test-file.test.ts\n│       ├── test-name-chromium-darwin.png\n│       ├── test-name-firefox-linux.png\n│       └── test-name-webkit-win32.png\n└── test-file.test.ts\n```\n\nThe naming convention includes:\n- **Test name**: either the first argument of the `toMatchScreenshot()` call,\nor automatically generated from the test's name.\n- **Browser name**: `chrome`, `chromium`, `firefox` or `webkit`.\n- **Platform**: `aix`, `darwin`, `freebsd`, `linux`, `openbsd`, `sunos`, or\n`win32`.\n\nThis ensures screenshots from different environments don't overwrite each other.\n\n### Updating References\n\nWhen you intentionally change your UI, you'll need to update the reference\nscreenshots:\n\n```bash\n$ vitest --update\n```\n\nReview updated screenshots before committing to make sure changes are\nintentional.\n\n## How Visual Tests Work\n\nVisual regression tests need stable screenshots to compare against. But pages aren't instantly stable as images load, animations finish, fonts render, and layouts settle.\n\nVitest handles this automatically through \"Stable Screenshot Detection\":\n\n1. Vitest takes a first screenshot (or uses the reference screenshot if available) as baseline\n1. It takes another screenshot and compares it with the baseline\n    - If the screenshots match, the page is stable and testing continues\n    - If they differ, Vitest uses the newest screenshot as the baseline and repeats\n1. This continues until stability is achieved or the timeout is reached\n\nThis ensures that transient visual changes (like loading spinners or animations) don't cause false failures. If something never stops animating though, you'll hit the timeout, so consider [disabling animations during testing](#disable-animations).\n\nIf a stable screenshot is captured after retries (one or more) and a reference screenshot exists, Vitest performs a final comparison with the reference using `createDiff: true`. This will generate a diff image if they don't match.\n\nDuring stability detection, Vitest calls comparators with `createDiff: false` since it only needs to know if screenshots match. This keeps the detection process fast.\n\n## Configuring Visual Tests\n\n### Global Configuration\n\nConfigure visual regression testing defaults in your\n[Vitest config](/config/browser/expect#tomatchscreenshot):\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      expect: {\n        toMatchScreenshot: {\n          comparatorName: 'pixelmatch',\n          comparatorOptions: {\n            // 0-1, how different can colors be?\n            threshold: 0.2,\n            // 1% of pixels can differ\n            allowedMismatchedPixelRatio: 0.01,\n          },\n        },\n      },\n    },\n  },\n})\n```\n\n### Per-Test Configuration\n\nOverride global settings for specific tests:\n\n```ts\nawait expect(element).toMatchScreenshot('button-hover', {\n  comparatorName: 'pixelmatch',\n  comparatorOptions: {\n    // more lax comparison for text-heavy elements\n    allowedMismatchedPixelRatio: 0.1,\n  },\n})\n```\n\n## Best Practices\n\n### Test Specific Elements\n\nUnless you explicitly want to test the whole page, prefer capturing specific\ncomponents to reduce false positives:\n\n```ts\n// ❌ Captures entire page; prone to unrelated changes\nawait expect(page).toMatchScreenshot()\n\n// ✅ Captures only the component under test\nawait expect(page.getByTestId('product-card')).toMatchScreenshot()\n```\n\n### Handle Dynamic Content\n\nDynamic content like timestamps, user data, or random values will cause tests\nto fail. You can either mock the sources of dynamic content or mask them when\nusing the Playwright provider by using the\n[`mask` option](https://playwright.dev/docs/api/class-page#page-screenshot-option-mask)\nin `screenshotOptions`.\n\n```ts\nawait expect(page.getByTestId('profile')).toMatchScreenshot({\n  screenshotOptions: {\n    mask: [page.getByTestId('last-seen')],\n  },\n})\n```\n\n### Disable Animations\n\nAnimations can cause flaky tests. Disable them during testing by injecting\na custom CSS snippet:\n\n```css\n*, *::before, *::after {\n  animation-duration: 0s !important;\n  animation-delay: 0s !important;\n  transition-duration: 0s !important;\n  transition-delay: 0s !important;\n}\n```\n\n::: tip\nWhen using the Playwright provider, animations are automatically disabled\nwhen using the assertion: the `animations` option's value in `screenshotOptions`\nis set to `\"disabled\"` by default.\n:::\n\n### Set Appropriate Thresholds\n\nTuning thresholds is tricky. It depends on the content, test environment,\nwhat's acceptable for your app, and might also change based on the test.\n\nVitest does not set a default for the mismatching pixels, that's up for the\nuser to decide based on their needs. The recommendation is to use\n`allowedMismatchedPixelRatio`, so that the threshold is computed on the size\nof the screenshot and not a fixed number.\n\nWhen setting both `allowedMismatchedPixelRatio` and\n`allowedMismatchedPixels`, Vitest uses whichever limit is stricter.\n\n### Set consistent viewport sizes\n\nAs the browser instance might have a different default size, it's best to\nset a specific viewport size, either on the test or the instance\nconfiguration:\n\n```ts\nawait page.viewport(1280, 720)\n```\n\n```ts [vitest.config.ts]\nimport { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        {\n          browser: 'chromium',\n          viewport: { width: 1280, height: 720 },\n        },\n      ],\n    },\n  },\n})\n```\n\n### Use Git LFS\n\nStore reference screenshots in\n[Git LFS](https://github.com/git-lfs/git-lfs?tab=readme-ov-file) if you plan to\nhave a large test suite.\n\n## Debugging Failed Tests\n\nWhen a visual test fails, Vitest provides three images to help debug:\n\n1. **Reference screenshot**: the expected baseline image\n1. **Actual screenshot**: what was captured during the test\n1. **Diff image**: highlights the differences, but this might not get generated\n\nYou'll see something like:\n\n```\nexpect(element).toMatchScreenshot()\n\nScreenshot does not match the stored reference.\n245 pixels (ratio 0.03) differ.\n\nReference screenshot:\n  tests/__screenshots__/button.test.ts/button-chromium-darwin.png\n\nActual screenshot:\n  tests/.vitest-attachments/button.test.ts/button-chromium-darwin-actual.png\n\nDiff image:\n  tests/.vitest-attachments/button.test.ts/button-chromium-darwin-diff.png\n```\n\n### Understanding the diff image\n\n- **Red pixels** are areas that differ between reference and actual\n- **Yellow pixels** are anti-aliasing differences (when anti-alias is not ignored)\n- **Transparent/original** are unchanged areas\n\n:::tip\nIf the diff is mostly red, something's really wrong. If it's speckled with a\nfew red pixels around text, you probably just need to bump your threshold.\n:::\n\n## Common Issues and Solutions\n\n### False Positives from Font Rendering\n\nFont availability and rendering varies significantly between systems. Some\npossible solutions might be to:\n\n- Use web fonts and wait for them to load:\n\n  ```ts\n  // wait for fonts to load\n  await document.fonts.ready\n\n  // continue with your tests\n  ```\n\n- Increase comparison threshold for text-heavy areas:\n\n  ```ts\n  await expect(page.getByTestId('article-summary')).toMatchScreenshot({\n    comparatorName: 'pixelmatch',\n    comparatorOptions: {\n      // 10% of the pixels are allowed to change\n      allowedMismatchedPixelRatio: 0.1,\n    },\n  })\n  ```\n\n- Use a cloud service or containerized environment for consistent font rendering.\n\n### Flaky Tests or Different Screenshot Sizes\n\nIf tests pass and fail randomly, or if screenshots have different dimensions\nbetween runs:\n\n- Wait for everything to load, including loading indicators\n- Set explicit viewport sizes: `await page.viewport(1920, 1080)`\n- Check for responsive behavior at viewport boundaries\n- Check for unintended animations or transitions\n- Increase test timeout for large screenshots\n- Use a cloud service or containerized environment\n\n## Visual Regression Testing for Teams\n\nRemember when we mentioned visual tests need a stable environment? Well, here's\nthe thing: your local machine isn't it.\n\nFor teams, you've basically got three options:\n\n1. **Self-hosted runners**, complex to set up, painful to maintain\n1. **GitHub Actions**, free (for open source), works with any provider\n1. **Cloud services**, like\n[Azure App Testing](https://azure.microsoft.com/en-us/products/app-testing/),\nbuilt for this exact problem\n\nWe'll focus on options 2 and 3 since they're the quickest to get running.\n\nTo be upfront, the main trade-offs for each are:\n\n- **GitHub Actions**: visual tests only run in CI (developers can't run them\nlocally)\n- **Microsoft's service**: works everywhere but costs money and only works\nwith Playwright\n\n:::: tabs key:vrt-for-teams\n=== GitHub Actions\n\nThe trick here is keeping visual tests separate from your regular tests,\notherwise, you'll waste hours checking failing logs of screenshot mismatches.\n\n### Organizing Your Tests\n\nFirst, isolate your visual tests. Stick them in a `visual` folder (or whatever\nmakes sense for your project):\n\n```json [package.json]\n{\n  \"scripts\": {\n    \"test:unit\": \"vitest --exclude tests/visual/*.test.ts\",\n    \"test:visual\": \"vitest tests/visual/*.test.ts\"\n  }\n}\n```\n\nNow developers can run `npm run test:unit` locally without visual tests getting\nin the way. Visual tests stay in CI where the environment is consistent.\n\n::: tip Alternative\nNot a fan of glob patterns? You could also use separate\n[Test Projects](/guide/projects) instead and run them using:\n\n- `vitest --project unit`\n- `vitest --project visual`\n:::\n\n### CI Setup\n\nYour CI needs browsers installed. How you do this depends on your provider:\n\n::: tabs key:provider\n== Playwright\n\n[Playwright](https://npmx.dev/package/playwright) makes this easy. Just pin\nyour version and add this before running tests:\n\n```yaml [.github/workflows/ci.yml]\n# ...the rest of the workflow\n- name: Install Playwright Browsers\n  run: npx --no playwright install --with-deps --only-shell\n```\n\n== WebdriverIO\n\n[WebdriverIO](https://npmx.dev/package/webdriverio) expects you to bring\nyour own browsers. The folks at\n[@browser-actions](https://github.com/browser-actions) have your back:\n\n```yaml [.github/workflows/ci.yml]\n# ...the rest of the workflow\n- uses: browser-actions/setup-chrome@v1\n  with:\n    chrome-version: 120\n```\n\n:::\n\nThen run your visual tests:\n\n```yaml [.github/workflows/ci.yml]\n# ...the rest of the workflow\n# ...browser setup\n- name: Visual Regression Testing\n  run: npm run test:visual\n```\n\n### The Update Workflow\n\nHere's where it gets interesting. You don't want to update screenshots on every\nPR automatically <small>*(chaos!)*</small>. Instead, create a\nmanually-triggered workflow that developers can run when they intentionally\nchange the UI.\n\nThe workflow below:\n- Only runs on feature branches (never on main)\n- Credits the person who triggered it as co-author\n- Prevents concurrent runs on the same branch\n- Shows a nice summary:\n  - **When screenshots changed**, it lists what changed\n\n    <img alt=\"Action summary after updates\" img-light src=\"/vrt-gha-summary-update-light.png\">\n    <img alt=\"Action summary after updates\" img-dark src=\"/vrt-gha-summary-update-dark.png\">\n\n  - **When nothing changed**, well, it tells you that too\n\n    <img alt=\"Action summary after no updates\" img-light src=\"/vrt-gha-summary-no-update-light.png\">\n    <img alt=\"Action summary after no updates\" img-dark src=\"/vrt-gha-summary-no-update-dark.png\">\n\n::: tip\nThis is just one approach. Some teams prefer PR comments (`/update-screenshots`),\nothers use labels. Adjust it to fit your workflow!\n\nThe important part is having a controlled way to update baselines.\n:::\n\n```yaml [.github/workflows/update-screenshots.yml]\nname: Update Visual Regression Screenshots\n\non:\n  workflow_dispatch: # manual trigger only\n\nenv:\n  AUTHOR_NAME: 'github-actions[bot]'\n  AUTHOR_EMAIL: '41898282+github-actions[bot]@users.noreply.github.com'\n  COMMIT_MESSAGE: |\n    test: update visual regression screenshots\n\n    Co-authored-by: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>\n\njobs:\n  update-screenshots:\n    runs-on: ubuntu-24.04\n\n    # safety first: don't run on main\n    if: github.ref_name != github.event.repository.default_branch\n\n    # one at a time per branch\n    concurrency:\n      group: visual-regression-screenshots@${{ github.ref_name }}\n      cancel-in-progress: true\n\n    permissions:\n      contents: write # needs to push changes\n\n    steps:\n      - name: Checkout selected branch\n        uses: actions/checkout@v4\n        with:\n          ref: ${{ github.ref_name }}\n          # use PAT if triggering other workflows\n          # token: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Configure Git\n        run: |\n          git config --global user.name \"${{ env.AUTHOR_NAME }}\"\n          git config --global user.email \"${{ env.AUTHOR_EMAIL }}\"\n\n      # your setup steps here (node, pnpm, whatever)\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 24\n\n      - name: Install dependencies\n        run: npm ci\n\n      - name: Install Playwright Browsers\n        run: npx --no playwright install --with-deps --only-shell\n\n      # the magic happens below 🪄\n      - name: Update Visual Regression Screenshots\n        run: npm run test:visual --update\n\n      # check what changed\n      - name: Check for changes\n        id: check_changes\n        run: |\n          CHANGED_FILES=$(git status --porcelain | awk '{print $2}')\n          if [ \"${CHANGED_FILES:+x}\" ]; then\n            echo \"changes=true\" >> $GITHUB_OUTPUT\n            echo \"Changes detected\"\n\n            # save the list for the summary\n            echo \"changed_files<<EOF\" >> $GITHUB_OUTPUT\n            echo \"$CHANGED_FILES\" >> $GITHUB_OUTPUT\n            echo \"EOF\" >> $GITHUB_OUTPUT\n            echo \"changed_count=$(echo \"$CHANGED_FILES\" | wc -l)\" >> $GITHUB_OUTPUT\n          else\n            echo \"changes=false\" >> $GITHUB_OUTPUT\n            echo \"No changes detected\"\n          fi\n\n      # commit if there are changes\n      - name: Commit changes\n        if: steps.check_changes.outputs.changes == 'true'\n        run: |\n          git add -A\n          git commit -m \"${{ env.COMMIT_MESSAGE }}\"\n\n      - name: Push changes\n        if: steps.check_changes.outputs.changes == 'true'\n        run: git push origin ${{ github.ref_name }}\n\n      # pretty summary for humans\n      - name: Summary\n        run: |\n          if [[ \"${{ steps.check_changes.outputs.changes }}\" == \"true\" ]]; then\n            echo \"### 📸 Visual Regression Screenshots Updated\" >> $GITHUB_STEP_SUMMARY\n            echo \"\" >> $GITHUB_STEP_SUMMARY\n            echo \"Successfully updated **${{ steps.check_changes.outputs.changed_count }}** screenshot(s) on \\`${{ github.ref_name }}\\`\" >> $GITHUB_STEP_SUMMARY\n            echo \"\" >> $GITHUB_STEP_SUMMARY\n            echo \"#### Changed Files:\" >> $GITHUB_STEP_SUMMARY\n            echo \"\\`\\`\\`\" >> $GITHUB_STEP_SUMMARY\n            echo \"${{ steps.check_changes.outputs.changed_files }}\" >> $GITHUB_STEP_SUMMARY\n            echo \"\\`\\`\\`\" >> $GITHUB_STEP_SUMMARY\n            echo \"\" >> $GITHUB_STEP_SUMMARY\n            echo \"✅ The updated screenshots have been committed and pushed. Your visual regression baseline is now up to date!\" >> $GITHUB_STEP_SUMMARY\n          else\n            echo \"### ℹ️ No Screenshot Updates Required\" >> $GITHUB_STEP_SUMMARY\n            echo \"\" >> $GITHUB_STEP_SUMMARY\n            echo \"The visual regression test command ran successfully but no screenshots needed updating.\" >> $GITHUB_STEP_SUMMARY\n            echo \"\" >> $GITHUB_STEP_SUMMARY\n            echo \"All screenshots are already up to date! 🎉\" >> $GITHUB_STEP_SUMMARY\n          fi\n```\n\n=== Azure App Testing\n\nYour tests stay local, only the browsers run in the cloud. It's Playwright's\nremote browser feature, but Microsoft handles all the infrastructure.\n\n### Organizing Your Tests\n\nKeep visual tests separate to control costs. Only tests that actually take\nscreenshots should use the service.\n\nThe cleanest approach is using [Test Projects](/guide/projects):\n\n```ts [vitest.config.ts]\nimport { env } from 'node:process'\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  // ...global Vite config\n  tests: {\n    // ...global Vitest config\n    projects: [\n      {\n        extends: true,\n        test: {\n          name: 'unit',\n          include: ['tests/**/*.test.ts'],\n          // regular config, can use local browsers\n        },\n      },\n      {\n        extends: true,\n        test: {\n          name: 'visual',\n          // or you could use a different suffix, e.g.,: `tests/**/*.visual.ts?(x)`\n          include: ['visual-regression-tests/**/*.test.ts?(x)'],\n          browser: {\n            enabled: true,\n            provider: playwright({\n              connectOptions: {\n                wsEndpoint: `${env.PLAYWRIGHT_SERVICE_URL}?${new URLSearchParams({\n                  'api-version': '2025-09-01',\n                  'os': 'linux', // always use Linux for consistency\n                  // helps identifying runs in the service's dashboard\n                  'runName': `Vitest ${env.CI ? 'CI' : 'local'} run @${new Date().toISOString()}`,\n                })}`,\n                exposeNetwork: '<loopback>',\n                headers: {\n                  Authorization: `Bearer ${env.PLAYWRIGHT_SERVICE_ACCESS_TOKEN}`,\n                },\n                timeout: 30_000,\n              }\n            }),\n            headless: true,\n            instances: [\n              {\n                browser: 'chromium',\n                viewport: { width: 2560, height: 1440 },\n              },\n            ],\n          },\n        },\n      },\n    ],\n  },\n})\n```\n\nFollow the [official guide to create a Playwright Workspace](https://learn.microsoft.com/en-us/azure/app-testing/playwright-workspaces/quickstart-run-end-to-end-tests?tabs=playwrightcli&pivots=playwright-test-runner#create-a-workspace).\n\nOnce your workspace is created, configure Vitest to use it:\n\n1. **Set the endpoint URL**: following the [official guide](https://learn.microsoft.com/en-us/azure/app-testing/playwright-workspaces/quickstart-run-end-to-end-tests?tabs=playwrightcli&pivots=playwright-test-runner#configure-the-browser-endpoint), retrieve the URL and set it as the `PLAYWRIGHT_SERVICE_URL` environment variable.\n1. **Enable token authentication**: [enable access tokens](https://learn.microsoft.com/en-us/azure/app-testing/playwright-workspaces/how-to-manage-authentication?pivots=playwright-test-runner#enable-authentication-using-access-tokens) for your workspace, then [generate a token](https://learn.microsoft.com/en-us/azure/app-testing/playwright-workspaces/how-to-manage-access-tokens#generate-a-workspace-access-token) and set it as the `PLAYWRIGHT_SERVICE_ACCESS_TOKEN` environment variable.\n\n::: danger Keep that Token Secret!\nNever commit `PLAYWRIGHT_SERVICE_ACCESS_TOKEN` to your repository. Anyone with\nthe token can rack up your bill. Use environment variables locally and secrets\nin CI.\n:::\n\nThen split your `test` script like this:\n\n```json [package.json]\n{\n  \"scripts\": {\n    \"test:visual\": \"vitest --project visual\",\n    \"test:unit\": \"vitest --project unit\"\n  }\n}\n```\n\n### Running Tests\n\n```bash\n# Local development\nnpm run test:unit    # free, runs locally\nnpm run test:visual  # uses cloud browsers\n\n# Update screenshots\nnpm run test:visual -- --update\n```\n\nThe best part of this approach is that it just works:\n\n- **Consistent screenshots**, everyone uses the same cloud browsers\n- **Works locally**, developers can run and update visual tests on their machines\n- **Pay for what you use**, only visual tests consume service minutes\n- **No Docker or workflow setups needed**, nothing to manage or maintain\n\n### CI Setup\n\nIn your CI, add the secrets:\n\n```yaml\nenv:\n  PLAYWRIGHT_SERVICE_URL: ${{ vars.PLAYWRIGHT_SERVICE_URL }}\n  PLAYWRIGHT_SERVICE_ACCESS_TOKEN: ${{ secrets.PLAYWRIGHT_SERVICE_ACCESS_TOKEN }}\n```\n\nThen run your tests like normal. The service handles the rest.\n\n::::\n\n### So Which One?\n\nBoth approaches work. The real question is what pain points matter most to your\nteam.\n\nIf you're already deep in the GitHub ecosystem, GitHub Actions is hard to beat.\nFree for open source, works with any browser provider, and you control\neverything.\n\nThe downside? That \"works on my machine\" conversation when someone generates\nscreenshots locally and they don't match CI expectations anymore.\n\nA cloud service makes sense if developers need to run visual tests locally.\n\nSome teams have designers checking their work or developers who prefer catching\nissues before pushing. It allows skipping the push-wait-check-fix-push cycle.\n\nStill on the fence? Start with GitHub Actions. You can always add a cloud\nservice later if local testing becomes a pain point.\n"
  },
  {
    "path": "docs/guide/browser/why.md",
    "content": "---\ntitle: Why Browser Mode | Browser Mode\noutline: deep\n---\n\n# Why Browser Mode\n\n## Motivation\n\nWe developed the Vitest browser mode feature to help improve testing workflows and achieve more accurate and reliable test results. This addition to our testing API allows developers to run tests in a native browser environment. In this section, we'll explore the motivations behind this feature and its benefits for testing.\n\n### Different Ways of Testing\n\nThere are different ways to test JavaScript code. Some testing frameworks simulate browser environments in Node.js, while others run tests in real browsers. In this context, [jsdom](https://npmx.dev/package/jsdom) is an example of a spec implementation that simulates a browser environment by being used with a test runner like Jest or Vitest, while other testing tools such as [WebdriverIO](https://webdriver.io/) or [Cypress](https://www.cypress.io/) allow developers to test their applications in a real browser or in case of [Playwright](https://playwright.dev/) provide you a browser engine.\n\n### The Simulation Caveat\n\nTesting JavaScript programs in simulated environments such as jsdom or happy-dom has simplified the test setup and provided an easy-to-use API, making them suitable for many projects and increasing confidence in test results. However, it is crucial to keep in mind that these tools only simulate a browser environment and not an actual browser, which may result in some discrepancies between the simulated environment and the real environment. Therefore, false positives or negatives in test results may occur.\n\nTo achieve the highest level of confidence in our tests, it's crucial to test in a real browser environment. This is why we developed the browser mode feature in Vitest, allowing developers to run tests natively in a browser and gain more accurate and reliable test results. With browser-level testing, developers can be more confident that their application will work as intended in a real-world scenario.\n\n## Drawbacks\n\nWhen using Vitest browser, it is important to consider the following drawbacks:\n\n### Early Development\n\nThe browser mode feature of Vitest is still in its early stages of development. As such, it may not yet be fully optimized, and there may be some bugs or issues that have not yet been ironed out. It is recommended that users augment their Vitest browser experience with a standalone browser-side test runner like WebdriverIO, Cypress or Playwright.\n\n### Longer Initialization\n\nVitest browser requires spinning up the provider and the browser during the initialization process, which can take some time. This can result in longer initialization times compared to other testing patterns.\n"
  },
  {
    "path": "docs/guide/cli-generated.md",
    "content": "### root\n\n- **CLI:** `-r, --root <path>`\n- **Config:** [root](/config/root)\n\nRoot path\n\n### config\n\n- **CLI:** `-c, --config <path>`\n\nPath to config file\n\n### update\n\n- **CLI:** `-u, --update [type]`\n- **Config:** [update](/config/update)\n\nUpdate snapshot (accepts boolean, \"new\", \"all\" or \"none\")\n\n### watch\n\n- **CLI:** `-w, --watch`\n- **Config:** [watch](/config/watch)\n\nEnable watch mode\n\n### testNamePattern\n\n- **CLI:** `-t, --testNamePattern <pattern>`\n- **Config:** [testNamePattern](/config/testnamepattern)\n\nRun tests with full names matching the specified regexp pattern\n\n### dir\n\n- **CLI:** `--dir <path>`\n- **Config:** [dir](/config/dir)\n\nBase directory to scan for the test files\n\n### ui\n\n- **CLI:** `--ui`\n\nEnable UI\n\n### open\n\n- **CLI:** `--open`\n- **Config:** [open](/config/open)\n\nOpen UI automatically (default: `!process.env.CI`)\n\n### api.port\n\n- **CLI:** `--api.port [port]`\n\nSpecify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to `51204`\n\n### api.host\n\n- **CLI:** `--api.host [host]`\n\nSpecify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses\n\n### api.strictPort\n\n- **CLI:** `--api.strictPort`\n\nSet to true to exit if port is already in use, instead of automatically trying the next available port\n\n### api.allowExec\n\n- **CLI:** `--api.allowExec`\n- **Config:** [api.allowExec](/config/api#api-allowexec)\n\nAllow API to execute code. (Be careful when enabling this option in untrusted environments)\n\n### api.allowWrite\n\n- **CLI:** `--api.allowWrite`\n- **Config:** [api.allowWrite](/config/api#api-allowwrite)\n\nAllow API to edit files. (Be careful when enabling this option in untrusted environments)\n\n### silent\n\n- **CLI:** `--silent [value]`\n- **Config:** [silent](/config/silent)\n\nSilent console output from tests. Use `'passed-only'` to see logs from failing tests only.\n\n### hideSkippedTests\n\n- **CLI:** `--hideSkippedTests`\n\nHide logs for skipped tests\n\n### reporters\n\n- **CLI:** `--reporter <name>`\n- **Config:** [reporters](/config/reporters)\n\nSpecify reporters (default, agent, blob, verbose, dot, json, tap, tap-flat, junit, tree, hanging-process, github-actions)\n\n### outputFile\n\n- **CLI:** `--outputFile <filename/-s>`\n- **Config:** [outputFile](/config/outputfile)\n\nWrite test results to a file when supporter reporter is also specified, use cac's dot notation for individual outputs of multiple reporters (example: `--outputFile.tap=./tap.txt`)\n\n### coverage.provider\n\n- **CLI:** `--coverage.provider <name>`\n- **Config:** [coverage.provider](/config/coverage#coverage-provider)\n\nSelect the tool for coverage collection, available values are: \"v8\", \"istanbul\" and \"custom\"\n\n### coverage.enabled\n\n- **CLI:** `--coverage.enabled`\n- **Config:** [coverage.enabled](/config/coverage#coverage-enabled)\n\nEnables coverage collection. Can be overridden using the `--coverage` CLI option (default: `false`)\n\n### coverage.include\n\n- **CLI:** `--coverage.include <pattern>`\n- **Config:** [coverage.include](/config/coverage#coverage-include)\n\nFiles included in coverage as glob patterns. May be specified more than once when using multiple patterns. By default only files covered by tests are included.\n\n### coverage.exclude\n\n- **CLI:** `--coverage.exclude <pattern>`\n- **Config:** [coverage.exclude](/config/coverage#coverage-exclude)\n\nFiles to be excluded in coverage. May be specified more than once when using multiple extensions.\n\n### coverage.clean\n\n- **CLI:** `--coverage.clean`\n- **Config:** [coverage.clean](/config/coverage#coverage-clean)\n\nClean coverage results before running tests (default: true)\n\n### coverage.cleanOnRerun\n\n- **CLI:** `--coverage.cleanOnRerun`\n- **Config:** [coverage.cleanOnRerun](/config/coverage#coverage-cleanonrerun)\n\nClean coverage report on watch rerun (default: true)\n\n### coverage.reportsDirectory\n\n- **CLI:** `--coverage.reportsDirectory <path>`\n- **Config:** [coverage.reportsDirectory](/config/coverage#coverage-reportsdirectory)\n\nDirectory to write coverage report to (default: ./coverage)\n\n### coverage.reporter\n\n- **CLI:** `--coverage.reporter <name>`\n- **Config:** [coverage.reporter](/config/coverage#coverage-reporter)\n\nCoverage reporters to use. Visit [`coverage.reporter`](/config/coverage#coverage-reporter) for more information (default: `[\"text\", \"html\", \"clover\", \"json\"]`)\n\n### coverage.reportOnFailure\n\n- **CLI:** `--coverage.reportOnFailure`\n- **Config:** [coverage.reportOnFailure](/config/coverage#coverage-reportonfailure)\n\nGenerate coverage report even when tests fail (default: `false`)\n\n### coverage.allowExternal\n\n- **CLI:** `--coverage.allowExternal`\n- **Config:** [coverage.allowExternal](/config/coverage#coverage-allowexternal)\n\nCollect coverage of files outside the project root (default: `false`)\n\n### coverage.skipFull\n\n- **CLI:** `--coverage.skipFull`\n- **Config:** [coverage.skipFull](/config/coverage#coverage-skipfull)\n\nDo not show files with 100% statement, branch, and function coverage (default: `false`)\n\n### coverage.thresholds.100\n\n- **CLI:** `--coverage.thresholds.100`\n- **Config:** [coverage.thresholds.100](/config/coverage#coverage-thresholds-100)\n\nShortcut to set all coverage thresholds to 100 (default: `false`)\n\n### coverage.thresholds.perFile\n\n- **CLI:** `--coverage.thresholds.perFile`\n- **Config:** [coverage.thresholds.perFile](/config/coverage#coverage-thresholds-perfile)\n\nCheck thresholds per file. See `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches` and `--coverage.thresholds.statements` for the actual thresholds (default: `false`)\n\n### coverage.thresholds.autoUpdate\n\n- **CLI:** `--coverage.thresholds.autoUpdate <boolean|function>`\n- **Config:** [coverage.thresholds.autoUpdate](/config/coverage#coverage-thresholds-autoupdate)\n\nUpdate threshold values: \"lines\", \"functions\", \"branches\" and \"statements\" to configuration file when current coverage is above the configured thresholds (default: `false`)\n\n### coverage.thresholds.lines\n\n- **CLI:** `--coverage.thresholds.lines <number>`\n\nThreshold for lines. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers\n\n### coverage.thresholds.functions\n\n- **CLI:** `--coverage.thresholds.functions <number>`\n\nThreshold for functions. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers\n\n### coverage.thresholds.branches\n\n- **CLI:** `--coverage.thresholds.branches <number>`\n\nThreshold for branches. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers\n\n### coverage.thresholds.statements\n\n- **CLI:** `--coverage.thresholds.statements <number>`\n\nThreshold for statements. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers\n\n### coverage.ignoreClassMethods\n\n- **CLI:** `--coverage.ignoreClassMethods <name>`\n- **Config:** [coverage.ignoreClassMethods](/config/coverage#coverage-ignoreclassmethods)\n\nArray of class method names to ignore for coverage. Visit [istanbuljs](https://github.com/istanbuljs/nyc#ignoring-methods) for more information. This option is only available for the istanbul providers (default: `[]`)\n\n### coverage.processingConcurrency\n\n- **CLI:** `--coverage.processingConcurrency <number>`\n- **Config:** [coverage.processingConcurrency](/config/coverage#coverage-processingconcurrency)\n\nConcurrency limit used when processing the coverage results. (default min between 20 and the number of CPUs)\n\n### coverage.customProviderModule\n\n- **CLI:** `--coverage.customProviderModule <path>`\n- **Config:** [coverage.customProviderModule](/config/coverage#coverage-customprovidermodule)\n\nSpecifies the module name or path for the custom coverage provider module. Visit [Custom Coverage Provider](/guide/coverage#custom-coverage-provider) for more information. This option is only available for custom providers\n\n### coverage.watermarks.statements\n\n- **CLI:** `--coverage.watermarks.statements <watermarks>`\n\nHigh and low watermarks for statements in the format of `<high>,<low>`\n\n### coverage.watermarks.lines\n\n- **CLI:** `--coverage.watermarks.lines <watermarks>`\n\nHigh and low watermarks for lines in the format of `<high>,<low>`\n\n### coverage.watermarks.branches\n\n- **CLI:** `--coverage.watermarks.branches <watermarks>`\n\nHigh and low watermarks for branches in the format of `<high>,<low>`\n\n### coverage.watermarks.functions\n\n- **CLI:** `--coverage.watermarks.functions <watermarks>`\n\nHigh and low watermarks for functions in the format of `<high>,<low>`\n\n### coverage.changed\n\n- **CLI:** `--coverage.changed <commit/branch>`\n- **Config:** [coverage.changed](/config/coverage#coverage-changed)\n\nCollect coverage only for files changed since a specified commit or branch (e.g., `origin/main` or `HEAD~1`). Inherits value from `--changed` by default.\n\n### mode\n\n- **CLI:** `--mode <name>`\n- **Config:** [mode](/config/mode)\n\nOverride Vite mode (default: `test` or `benchmark`)\n\n### isolate\n\n- **CLI:** `--isolate`\n- **Config:** [isolate](/config/isolate)\n\nRun every test file in isolation. To disable isolation, use `--no-isolate` (default: `true`)\n\n### globals\n\n- **CLI:** `--globals`\n- **Config:** [globals](/config/globals)\n\nInject apis globally\n\n### dom\n\n- **CLI:** `--dom`\n\nMock browser API with happy-dom\n\n### browser.enabled\n\n- **CLI:** `--browser.enabled`\n- **Config:** [browser.enabled](/config/browser/enabled)\n\nRun tests in the browser. Equivalent to `--browser.enabled` (default: `false`)\n\n### browser.name\n\n- **CLI:** `--browser.name <name>`\n\nRun all tests in a specific browser. Some browsers are only available for specific providers (see `--browser.provider`).\n\n### browser.headless\n\n- **CLI:** `--browser.headless`\n- **Config:** [browser.headless](/config/browser/headless)\n\nRun the browser in headless mode (i.e. without opening the GUI (Graphical User Interface)). If you are running Vitest in CI, it will be enabled by default (default: `process.env.CI`)\n\n### browser.api.port\n\n- **CLI:** `--browser.api.port [port]`\n- **Config:** [browser.api.port](/config/browser/api#api-port)\n\nSpecify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to `63315`\n\n### browser.api.host\n\n- **CLI:** `--browser.api.host [host]`\n- **Config:** [browser.api.host](/config/browser/api#api-host)\n\nSpecify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses\n\n### browser.api.strictPort\n\n- **CLI:** `--browser.api.strictPort`\n- **Config:** [browser.api.strictPort](/config/browser/api#api-strictport)\n\nSet to true to exit if port is already in use, instead of automatically trying the next available port\n\n### browser.api.allowExec\n\n- **CLI:** `--browser.api.allowExec`\n- **Config:** [browser.api.allowExec](/config/browser/api#api-allowexec)\n\nAllow API to execute code. (Be careful when enabling this option in untrusted environments)\n\n### browser.api.allowWrite\n\n- **CLI:** `--browser.api.allowWrite`\n- **Config:** [browser.api.allowWrite](/config/browser/api#api-allowwrite)\n\nAllow API to edit files. (Be careful when enabling this option in untrusted environments)\n\n### browser.isolate\n\n- **CLI:** `--browser.isolate`\n- **Config:** [browser.isolate](/config/browser/isolate)\n\nRun every browser test file in isolation. To disable isolation, use `--browser.isolate=false` (default: `true`)\n\n### browser.ui\n\n- **CLI:** `--browser.ui`\n- **Config:** [browser.ui](/config/browser/ui)\n\nShow Vitest UI when running tests (default: `!process.env.CI`)\n\n### browser.detailsPanelPosition\n\n- **CLI:** `--browser.detailsPanelPosition <position>`\n- **Config:** [browser.detailsPanelPosition](/config/browser/detailspanelposition)\n\nDefault position for the details panel in browser mode. Either `right` (horizontal split) or `bottom` (vertical split) (default: `right`)\n\n### browser.fileParallelism\n\n- **CLI:** `--browser.fileParallelism`\n\nShould browser test files run in parallel. Use `--browser.fileParallelism=false` to disable (default: `true`)\n\n### browser.connectTimeout\n\n- **CLI:** `--browser.connectTimeout <timeout>`\n- **Config:** [browser.connectTimeout](/config/browser/connecttimeout)\n\nIf connection to the browser takes longer, the test suite will fail (default: `60_000`)\n\n### browser.trackUnhandledErrors\n\n- **CLI:** `--browser.trackUnhandledErrors`\n- **Config:** [browser.trackUnhandledErrors](/config/browser/trackunhandlederrors)\n\nControl if Vitest catches uncaught exceptions so they can be reported (default: `true`)\n\n### browser.trace\n\n- **CLI:** `--browser.trace <mode>`\n- **Config:** [browser.trace](/config/browser/trace)\n\nEnable trace view mode. Supported: \"on\", \"off\", \"on-first-retry\", \"on-all-retries\", \"retain-on-failure\".\n\n### pool\n\n- **CLI:** `--pool <pool>`\n- **Config:** [pool](/config/pool)\n\nSpecify pool, if not running in the browser (default: `forks`)\n\n### execArgv\n\n- **CLI:** `--execArgv <option>`\n- **Config:** [execArgv](/config/execargv)\n\nPass additional arguments to `node` process when spawning `worker_threads` or `child_process`.\n\n### vmMemoryLimit\n\n- **CLI:** `--vmMemoryLimit <limit>`\n- **Config:** [vmMemoryLimit](/config/vmmemorylimit)\n\nMemory limit for VM pools. If you see memory leaks, try to tinker this value.\n\n### fileParallelism\n\n- **CLI:** `--fileParallelism`\n- **Config:** [fileParallelism](/config/fileparallelism)\n\nShould all test files run in parallel. Use `--no-file-parallelism` to disable (default: `true`)\n\n### maxWorkers\n\n- **CLI:** `--maxWorkers <workers>`\n- **Config:** [maxWorkers](/config/maxworkers)\n\nMaximum number or percentage of workers to run tests in\n\n### environment\n\n- **CLI:** `--environment <name>`\n- **Config:** [environment](/config/environment)\n\nSpecify runner environment, if not running in the browser (default: `node`)\n\n### passWithNoTests\n\n- **CLI:** `--passWithNoTests`\n- **Config:** [passWithNoTests](/config/passwithnotests)\n\nPass when no tests are found\n\n### logHeapUsage\n\n- **CLI:** `--logHeapUsage`\n- **Config:** [logHeapUsage](/config/logheapusage)\n\nShow the size of heap for each test when running in node\n\n### detectAsyncLeaks\n\n- **CLI:** `--detectAsyncLeaks`\n- **Config:** [detectAsyncLeaks](/config/detectasyncleaks)\n\nDetect asynchronous resources leaking from the test file (default: `false`)\n\n### allowOnly\n\n- **CLI:** `--allowOnly`\n- **Config:** [allowOnly](/config/allowonly)\n\nAllow tests and suites that are marked as only (default: `!process.env.CI`)\n\n### dangerouslyIgnoreUnhandledErrors\n\n- **CLI:** `--dangerouslyIgnoreUnhandledErrors`\n- **Config:** [dangerouslyIgnoreUnhandledErrors](/config/dangerouslyignoreunhandlederrors)\n\nIgnore any unhandled errors that occur\n\n### sequence.shuffle.files\n\n- **CLI:** `--sequence.shuffle.files`\n- **Config:** [sequence.shuffle.files](/config/sequence#sequence-shuffle-files)\n\nRun files in a random order. Long running tests will not start earlier if you enable this option. (default: `false`)\n\n### sequence.shuffle.tests\n\n- **CLI:** `--sequence.shuffle.tests`\n- **Config:** [sequence.shuffle.tests](/config/sequence#sequence-shuffle-tests)\n\nRun tests in a random order (default: `false`)\n\n### sequence.concurrent\n\n- **CLI:** `--sequence.concurrent`\n- **Config:** [sequence.concurrent](/config/sequence#sequence-concurrent)\n\nMake tests run in parallel (default: `false`)\n\n### sequence.seed\n\n- **CLI:** `--sequence.seed <seed>`\n- **Config:** [sequence.seed](/config/sequence#sequence-seed)\n\nSet the randomization seed. This option will have no effect if `--sequence.shuffle` is falsy. Visit [\"Random Seed\" page](https://en.wikipedia.org/wiki/Random_seed) for more information\n\n### sequence.hooks\n\n- **CLI:** `--sequence.hooks <order>`\n- **Config:** [sequence.hooks](/config/sequence#sequence-hooks)\n\nChanges the order in which hooks are executed. Accepted values are: \"stack\", \"list\" and \"parallel\". Visit [`sequence.hooks`](/config/sequence#sequence-hooks) for more information (default: `\"parallel\"`)\n\n### sequence.setupFiles\n\n- **CLI:** `--sequence.setupFiles <order>`\n- **Config:** [sequence.setupFiles](/config/sequence#sequence-setupfiles)\n\nChanges the order in which setup files are executed. Accepted values are: \"list\" and \"parallel\". If set to \"list\", will run setup files in the order they are defined. If set to \"parallel\", will run setup files in parallel (default: `\"parallel\"`)\n\n### inspect\n\n- **CLI:** `--inspect [[host:]port]`\n\nEnable Node.js inspector (default: `127.0.0.1:9229`)\n\n### inspectBrk\n\n- **CLI:** `--inspectBrk [[host:]port]`\n\nEnable Node.js inspector and break before the test starts\n\n### testTimeout\n\n- **CLI:** `--testTimeout <timeout>`\n- **Config:** [testTimeout](/config/testtimeout)\n\nDefault timeout of a test in milliseconds (default: `5000`). Use `0` to disable timeout completely.\n\n### hookTimeout\n\n- **CLI:** `--hookTimeout <timeout>`\n- **Config:** [hookTimeout](/config/hooktimeout)\n\nDefault hook timeout in milliseconds (default: `10000`). Use `0` to disable timeout completely.\n\n### bail\n\n- **CLI:** `--bail <number>`\n- **Config:** [bail](/config/bail)\n\nStop test execution when given number of tests have failed (default: `0`)\n\n### retry.count\n\n- **CLI:** `--retry.count <times>`\n- **Config:** [retry.count](/config/retry#retry-count)\n\nNumber of times to retry a test if it fails (default: `0`)\n\n### retry.delay\n\n- **CLI:** `--retry.delay <ms>`\n- **Config:** [retry.delay](/config/retry#retry-delay)\n\nDelay in milliseconds between retry attempts (default: `0`)\n\n### retry.condition\n\n- **CLI:** `--retry.condition <pattern>`\n- **Config:** [retry.condition](/config/retry#retry-condition)\n\nRegex pattern to match error messages that should trigger a retry. Only errors matching this pattern will cause a retry (default: retry on all errors)\n\n### diff.aAnnotation\n\n- **CLI:** `--diff.aAnnotation <annotation>`\n- **Config:** [diff.aAnnotation](/config/diff#diff-aannotation)\n\nAnnotation for expected lines (default: `Expected`)\n\n### diff.aIndicator\n\n- **CLI:** `--diff.aIndicator <indicator>`\n- **Config:** [diff.aIndicator](/config/diff#diff-aindicator)\n\nIndicator for expected lines (default: `-`)\n\n### diff.bAnnotation\n\n- **CLI:** `--diff.bAnnotation <annotation>`\n- **Config:** [diff.bAnnotation](/config/diff#diff-bannotation)\n\nAnnotation for received lines (default: `Received`)\n\n### diff.bIndicator\n\n- **CLI:** `--diff.bIndicator <indicator>`\n- **Config:** [diff.bIndicator](/config/diff#diff-bindicator)\n\nIndicator for received lines (default: `+`)\n\n### diff.commonIndicator\n\n- **CLI:** `--diff.commonIndicator <indicator>`\n- **Config:** [diff.commonIndicator](/config/diff#diff-commonindicator)\n\nIndicator for common lines (default: ` `)\n\n### diff.contextLines\n\n- **CLI:** `--diff.contextLines <lines>`\n- **Config:** [diff.contextLines](/config/diff#diff-contextlines)\n\nNumber of lines of context to show around each change (default: `5`)\n\n### diff.emptyFirstOrLastLinePlaceholder\n\n- **CLI:** `--diff.emptyFirstOrLastLinePlaceholder <placeholder>`\n- **Config:** [diff.emptyFirstOrLastLinePlaceholder](/config/diff#diff-emptyfirstorlastlineplaceholder)\n\nPlaceholder for an empty first or last line (default: `\"\"`)\n\n### diff.expand\n\n- **CLI:** `--diff.expand`\n- **Config:** [diff.expand](/config/diff#diff-expand)\n\nExpand all common lines (default: `true`)\n\n### diff.includeChangeCounts\n\n- **CLI:** `--diff.includeChangeCounts`\n- **Config:** [diff.includeChangeCounts](/config/diff#diff-includechangecounts)\n\nInclude comparison counts in diff output (default: `false`)\n\n### diff.omitAnnotationLines\n\n- **CLI:** `--diff.omitAnnotationLines`\n- **Config:** [diff.omitAnnotationLines](/config/diff#diff-omitannotationlines)\n\nOmit annotation lines from the output (default: `false`)\n\n### diff.printBasicPrototype\n\n- **CLI:** `--diff.printBasicPrototype`\n- **Config:** [diff.printBasicPrototype](/config/diff#diff-printbasicprototype)\n\nPrint basic prototype Object and Array (default: `true`)\n\n### diff.maxDepth\n\n- **CLI:** `--diff.maxDepth <maxDepth>`\n- **Config:** [diff.maxDepth](/config/diff#diff-maxdepth)\n\nLimit the depth to recurse when printing nested objects (default: `20`)\n\n### diff.truncateThreshold\n\n- **CLI:** `--diff.truncateThreshold <threshold>`\n- **Config:** [diff.truncateThreshold](/config/diff#diff-truncatethreshold)\n\nNumber of lines to show before and after each change (default: `0`)\n\n### diff.truncateAnnotation\n\n- **CLI:** `--diff.truncateAnnotation <annotation>`\n- **Config:** [diff.truncateAnnotation](/config/diff#diff-truncateannotation)\n\nAnnotation for truncated lines (default: `... Diff result is truncated`)\n\n### exclude\n\n- **CLI:** `--exclude <glob>`\n- **Config:** [exclude](/config/exclude)\n\nAdditional file globs to be excluded from test\n\n### expandSnapshotDiff\n\n- **CLI:** `--expandSnapshotDiff`\n- **Config:** [expandSnapshotDiff](/config/expandsnapshotdiff)\n\nShow full diff when snapshot fails\n\n### disableConsoleIntercept\n\n- **CLI:** `--disableConsoleIntercept`\n- **Config:** [disableConsoleIntercept](/config/disableconsoleintercept)\n\nDisable automatic interception of console logging (default: `false`)\n\n### typecheck.enabled\n\n- **CLI:** `--typecheck.enabled`\n- **Config:** [typecheck.enabled](/config/typecheck#typecheck-enabled)\n\nEnable typechecking alongside tests (default: `false`)\n\n### typecheck.only\n\n- **CLI:** `--typecheck.only`\n- **Config:** [typecheck.only](/config/typecheck#typecheck-only)\n\nRun only typecheck tests. This automatically enables typecheck (default: `false`)\n\n### typecheck.checker\n\n- **CLI:** `--typecheck.checker <name>`\n- **Config:** [typecheck.checker](/config/typecheck#typecheck-checker)\n\nSpecify the typechecker to use. Available values are: \"tsc\" and \"vue-tsc\" and a path to an executable (default: `\"tsc\"`)\n\n### typecheck.allowJs\n\n- **CLI:** `--typecheck.allowJs`\n- **Config:** [typecheck.allowJs](/config/typecheck#typecheck-allowjs)\n\nAllow JavaScript files to be typechecked. By default takes the value from tsconfig.json\n\n### typecheck.ignoreSourceErrors\n\n- **CLI:** `--typecheck.ignoreSourceErrors`\n- **Config:** [typecheck.ignoreSourceErrors](/config/typecheck#typecheck-ignoresourceerrors)\n\nIgnore type errors from source files\n\n### typecheck.tsconfig\n\n- **CLI:** `--typecheck.tsconfig <path>`\n- **Config:** [typecheck.tsconfig](/config/typecheck#typecheck-tsconfig)\n\nPath to a custom tsconfig file\n\n### typecheck.spawnTimeout\n\n- **CLI:** `--typecheck.spawnTimeout <time>`\n- **Config:** [typecheck.spawnTimeout](/config/typecheck#typecheck-spawntimeout)\n\nMinimum time in milliseconds it takes to spawn the typechecker\n\n### project\n\n- **CLI:** `--project <name>`\n\nThe name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: `--project=1 --project=2`. You can also filter projects using wildcards like `--project=packages*`, and exclude projects with `--project=!pattern`.\n\n### slowTestThreshold\n\n- **CLI:** `--slowTestThreshold <threshold>`\n- **Config:** [slowTestThreshold](/config/slowtestthreshold)\n\nThreshold in milliseconds for a test or suite to be considered slow (default: `300`)\n\n### teardownTimeout\n\n- **CLI:** `--teardownTimeout <timeout>`\n- **Config:** [teardownTimeout](/config/teardowntimeout)\n\nDefault timeout of a teardown function in milliseconds (default: `10000`)\n\n### maxConcurrency\n\n- **CLI:** `--maxConcurrency <number>`\n- **Config:** [maxConcurrency](/config/maxconcurrency)\n\nMaximum number of concurrent tests and suites during test file execution (default: `5`)\n\n### expect.requireAssertions\n\n- **CLI:** `--expect.requireAssertions`\n- **Config:** [expect.requireAssertions](/config/expect#expect-requireassertions)\n\nRequire that all tests have at least one assertion\n\n### expect.poll.interval\n\n- **CLI:** `--expect.poll.interval <interval>`\n- **Config:** [expect.poll.interval](/config/expect#expect-poll-interval)\n\nPoll interval in milliseconds for `expect.poll()` assertions (default: `50`)\n\n### expect.poll.timeout\n\n- **CLI:** `--expect.poll.timeout <timeout>`\n- **Config:** [expect.poll.timeout](/config/expect#expect-poll-timeout)\n\nPoll timeout in milliseconds for `expect.poll()` assertions (default: `1000`)\n\n### printConsoleTrace\n\n- **CLI:** `--printConsoleTrace`\n- **Config:** [printConsoleTrace](/config/printconsoletrace)\n\nAlways print console stack traces\n\n### includeTaskLocation\n\n- **CLI:** `--includeTaskLocation`\n- **Config:** [includeTaskLocation](/config/includetasklocation)\n\nCollect test and suite locations in the `location` property\n\n### attachmentsDir\n\n- **CLI:** `--attachmentsDir <dir>`\n- **Config:** [attachmentsDir](/config/attachmentsdir)\n\nThe directory where attachments from `context.annotate` are stored in (default: `.vitest-attachments`)\n\n### run\n\n- **CLI:** `--run`\n\nDisable watch mode\n\n### color\n\n- **CLI:** `--no-color`\n\nRemoves colors from the console output\n\n### clearScreen\n\n- **CLI:** `--clearScreen`\n\nClear terminal screen when re-running tests during watch mode (default: `true`)\n\n### configLoader\n\n- **CLI:** `--configLoader <loader>`\n\nUse `bundle` to bundle the config with esbuild or `runner` (experimental) to process it on the fly. This is only available in vite version 6.1.0 and above. (default: `bundle`)\n\n### standalone\n\n- **CLI:** `--standalone`\n\nStart Vitest without running tests. Tests will be running only on change. This option is ignored when CLI file filters are passed. (default: `false`)\n\n### listTags\n\n- **CLI:** `--listTags [type]`\n\nList all available tags instead of running tests. `--list-tags=json` will output tags in JSON format, unless there are no tags.\n\n### clearCache\n\n- **CLI:** `--clearCache`\n\nDelete all Vitest caches, including `experimental.fsModuleCache`, without running any tests. This will reduce the performance in the subsequent test run.\n\n### tagsFilter\n\n- **CLI:** `--tagsFilter <expression>`\n\nRun only tests with the specified tags. You can use logical operators `&&` (and), `||` (or) and `!` (not) to create complex expressions, see [Test Tags](/guide/test-tags#syntax) for more information.\n\n### strictTags\n\n- **CLI:** `--strictTags`\n- **Config:** [strictTags](/config/stricttags)\n\nShould Vitest throw an error if test has a tag that is not defined in the config. (default: `true`)\n\n### experimental.fsModuleCache\n\n- **CLI:** `--experimental.fsModuleCache`\n- **Config:** [experimental.fsModuleCache](/config/experimental#experimental-fsmodulecache)\n\nEnable caching of modules on the file system between reruns.\n\n### experimental.importDurations.print\n\n- **CLI:** `--experimental.importDurations.print <boolean|on-warn>`\n- **Config:** [experimental.importDurations.print](/config/experimental#experimental-importdurations-print)\n\nWhen to print import breakdown to CLI terminal. Use `true` to always print, `false` to never print, or `on-warn` to print only when imports exceed the warn threshold (default: false).\n\n### experimental.importDurations.limit\n\n- **CLI:** `--experimental.importDurations.limit <number>`\n- **Config:** [experimental.importDurations.limit](/config/experimental#experimental-importdurations-limit)\n\nMaximum number of imports to collect and display (default: 0, or 10 if print or UI is enabled).\n\n### experimental.importDurations.failOnDanger\n\n- **CLI:** `--experimental.importDurations.failOnDanger`\n- **Config:** [experimental.importDurations.failOnDanger](/config/experimental#experimental-importdurations-failondanger)\n\nFail the test run if any import exceeds the danger threshold (default: false).\n\n### experimental.importDurations.thresholds.warn\n\n- **CLI:** `--experimental.importDurations.thresholds.warn <number>`\n- **Config:** [experimental.importDurations.thresholds.warn](/config/experimental#experimental-importdurations-thresholds-warn)\n\nWarning threshold - imports exceeding this are shown in yellow/orange (default: 100).\n\n### experimental.importDurations.thresholds.danger\n\n- **CLI:** `--experimental.importDurations.thresholds.danger <number>`\n- **Config:** [experimental.importDurations.thresholds.danger](/config/experimental#experimental-importdurations-thresholds-danger)\n\nDanger threshold - imports exceeding this are shown in red (default: 500).\n\n### experimental.viteModuleRunner\n\n- **CLI:** `--experimental.viteModuleRunner`\n- **Config:** [experimental.viteModuleRunner](/config/experimental#experimental-vitemodulerunner)\n\nControl whether Vitest uses Vite's module runner to run the code or fallback to the native `import`. (default: `true`)\n\n### experimental.nodeLoader\n\n- **CLI:** `--experimental.nodeLoader`\n- **Config:** [experimental.nodeLoader](/config/experimental#experimental-nodeloader)\n\nControls whether Vitest will use Node.js Loader API to process in-source or mocked files. This has no effect if `viteModuleRunner` is enabled. Disabling this can increase performance. (default: `true`)\n"
  },
  {
    "path": "docs/guide/cli.md",
    "content": "---\ntitle: Command Line Interface | Guide\noutline: deep\n---\n\n# Command Line Interface\n\n## Commands\n\n### `vitest`\n\nStart Vitest in the current directory. Will enter the watch mode in development environment and run mode in CI (or non-interactive terminal) automatically.\n\nYou can pass an additional argument as the filter of the test files to run. For example:\n\n```bash\nvitest foobar\n```\n\nWill run only the test file that contains `foobar` in their paths. This filter only checks inclusion and doesn't support regexp or glob patterns (unless your terminal processes it before Vitest receives the filter).\n\nSince Vitest 3, you can also specify the test by filename and line number:\n\n```bash\n$ vitest basic/foo.test.ts:10\n```\n\n::: warning\nNote that Vitest requires the full filename for this feature to work. It can be relative to the current working directory or an absolute file path.\n\n```bash\n$ vitest basic/foo.js:10 # ✅\n$ vitest ./basic/foo.js:10 # ✅\n$ vitest /users/project/basic/foo.js:10 # ✅\n$ vitest foo:10 # ❌\n$ vitest ./basic/foo:10 # ❌\n```\n\nAt the moment Vitest also doesn't support ranges:\n\n```bash\n$ vitest basic/foo.test.ts:10, basic/foo.test.ts:25 # ✅\n$ vitest basic/foo.test.ts:10-25 # ❌\n```\n:::\n\n### `vitest run`\n\nPerform a single run without watch mode.\n\n### `vitest watch`\n\nRun all test suites but watch for changes and rerun tests when they change. Same as calling `vitest` without an argument. Will fallback to `vitest run` in CI or when stdin is not a TTY (non-interactive environment).\n\n### `vitest dev`\n\nAlias to `vitest watch`.\n\n### `vitest related`\n\nRun only tests that cover a list of source files. Works with static imports (e.g., `import('./index.js')` or `import index from './index.js`), but not the dynamic ones (e.g., `import(filepath)`). All files should be relative to root folder.\n\nUseful to run with [`lint-staged`](https://github.com/okonet/lint-staged) or with your CI setup.\n\n```bash\nvitest related /src/index.ts /src/hello-world.js\n```\n\n::: tip\nDon't forget that Vitest runs with enabled watch mode by default. If you are using tools like `lint-staged`, you  should also pass `--run` option, so that command can exit normally.\n\n```js [.lintstagedrc.js]\nexport default {\n  '*.{js,ts}': 'vitest related --run',\n}\n```\n:::\n\n### `vitest bench`\n\nRun only [benchmark](/guide/features.html#benchmarking) tests, which compare performance results.\n\n### `vitest init`\n\n`vitest init <name>` can be used to setup project configuration. At the moment, it only supports [`browser`](/guide/browser/) value:\n\n```bash\nvitest init browser\n```\n\n### `vitest list`\n\n`vitest list` command inherits all `vitest` options to print the list of all matching tests. This command ignores `reporters` option. By default, it will print the names of all tests that matched the file filter and name pattern:\n\n```shell\nvitest list filename.spec.ts -t=\"some-test\"\n```\n\n```txt\ndescribe > some-test\ndescribe > some-test > test 1\ndescribe > some-test > test 2\n```\n\nYou can pass down `--json` flag to print tests in JSON format or save it in a separate file:\n\n```bash\nvitest list filename.spec.ts -t=\"some-test\" --json=./file.json\n```\n\nIf `--json` flag doesn't receive a value, it will output the JSON into stdout.\n\nYou also can pass down `--filesOnly` flag to print the test files only:\n\n```bash\nvitest list --filesOnly\n```\n\n```txt\ntests/test1.test.ts\ntests/test2.test.ts\n```\n\nSince Vitest 4.1, you may pass `--static-parse` to [parse test files](/api/advanced/vitest#parsespecifications) instead of running them to collect tests. Vitest parses test files with limited concurrency, defaulting to `os.availableParallelism()`. You can change it via the `--static-parse-concurrency` option.\n\n## Shell Autocompletions\n\nVitest provides shell autocompletions for commands, options, and option values powered by [`@bomb.sh/tab`](https://github.com/bombshell-dev/tab).\n\n### Setup\n\nFor permanent setup in zsh, add this to your `~/.zshrc`:\n\n```bash\n# Add to ~/.zshrc for permanent autocompletions (same can be done for other shells)\nsource <(vitest complete zsh)\n```\n\n### Package Manager Integration\n\n`@bomb.sh/tab` integrates with [package managers](https://github.com/bombshell-dev/tab?tab=readme-ov-file#package-manager-completions). Autocompletions work when running vitest directly:\n\n::: code-group\n\n```bash [npm]\nnpm vitest <Tab>\n```\n\n```bash [npm]\nnpm exec vitest <Tab>\n```\n\n```bash [pnpm]\npnpm vitest <Tab>\n```\n\n```bash [yarn]\nyarn vitest <Tab>\n```\n\n```bash [bun]\nbun vitest <Tab>\n```\n\n:::\n\nFor package manager autocompletions, you should install [tab's package manager completions](https://github.com/bombshell-dev/tab?tab=readme-ov-file#package-manager-completions) separately.\n\n## Options\n\n::: tip\nVitest supports both camel case and kebab case for [CLI arguments](https://github.com/cacjs/cac#dot-nested-options). For example, `--passWithNoTests` and `--pass-with-no-tests` will both work (`--no-color` and `--inspect-brk` are the exceptions).\n\nVitest also supports different ways of specifying the value: `--reporter dot` and `--reporter=dot` are both valid.\n\nIf option supports an array of values, you need to pass the option multiple times:\n\n```\nvitest --reporter=dot --reporter=default\n```\n\nBoolean options can be negated with `no-` prefix. Specifying the value as `false` also works:\n\n```\nvitest --no-api\nvitest --api=false\n```\n:::\n\n<!--@include: ./cli-generated.md-->\n\n### changed\n\n- **Type**: `boolean | string`\n- **Default**: false\n\nRun tests only against changed files. If no value is provided, it will run tests against uncommitted changes (including staged and unstaged).\n\nTo run tests against changes made in the last commit, you can use `--changed HEAD~1`. You can also pass commit hash (e.g. `--changed 09a9920`) or branch name (e.g. `--changed origin/develop`).\n\nWhen used with code coverage the report will contain only the files that were related to the changes.\n\nIf paired with the [`forceRerunTriggers`](/config/forcereruntriggers) config option it will run the whole test suite if at least one of the files listed in the `forceRerunTriggers` list changes. By default, changes to the Vitest config file and `package.json` will always rerun the whole suite.\n\n### shard\n\n- **Type**: `string`\n- **Default**: disabled\n\nTest suite shard to execute in a format of `<index>`/`<count>`, where\n\n- `count` is a positive integer, count of divided parts\n- `index` is a positive integer, index of divided part\n\nThis command will divide all tests into `count` equal parts, and will run only those that happen to be in an `index` part. For example, to split your tests suite into three parts, use this:\n\n```sh\nvitest run --shard=1/3\nvitest run --shard=2/3\nvitest run --shard=3/3\n```\n\n:::warning\nYou cannot use this option with `--watch` enabled (enabled in dev by default).\n:::\n\n::: tip\nIf `--reporter=blob` is used without an output file, the default path will include the current shard config to avoid collisions with other Vitest processes.\n:::\n\n### merge-reports\n\n- **Type:** `boolean | string`\n\nMerges every blob report located in the specified folder (`.vitest-reports` by default). You can use any reporters with this command (except [`blob`](/guide/reporters#blob-reporter)):\n\n```sh\nvitest --merge-reports --reporter=junit\n```\n"
  },
  {
    "path": "docs/guide/common-errors.md",
    "content": "---\ntitle: Common Errors | Guide\n---\n\n# Common Errors\n\n## Cannot find module './relative-path'\n\nIf you receive an error that module cannot be found, it might mean several different things:\n\n1. You misspelled the path. Make sure the path is correct.\n\n2. It's possible that you rely on `baseUrl` in your `tsconfig.json`. Vite doesn't take into account `tsconfig.json` by default, so you might need to install [`vite-tsconfig-paths`](https://npmx.dev/package/vite-tsconfig-paths) yourself, if you rely on this behavior.\n\n```ts\nimport { defineConfig } from 'vitest/config'\nimport tsconfigPaths from 'vite-tsconfig-paths'\n\nexport default defineConfig({\n  plugins: [tsconfigPaths()]\n})\n```\n\nOr rewrite your path to not be relative to root:\n\n```diff\n- import helpers from 'src/helpers'\n+ import helpers from '../src/helpers'\n```\n\n3. Make sure you don't have relative [aliases](/config/alias). Vite treats them as relative to the file where the import is instead of the root.\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    alias: {\n      '@/': './src/', // [!code --]\n      '@/': new URL('./src/', import.meta.url).pathname, // [!code ++]\n    }\n  }\n})\n```\n\n## Failed to Terminate Worker\n\nThis error can happen when NodeJS's `fetch` is used with [`pool: 'threads'`](/config/pool#threads). See [#3077](https://github.com/vitest-dev/vitest/issues/3077) for details.\n\nThe default [`pool: 'forks'`](/config/pool#forks) does not have this issue. If you've explicitly set `pool: 'threads'`, switching back to `'forks'` or using [`'vmForks'`](/config/pool#vmforks) will resolve it.\n\n## Custom package conditions are not resolved\n\nIf you are using custom conditions in your `package.json` [exports](https://nodejs.org/api/packages.html#package-entry-points) or [subpath imports](https://nodejs.org/api/packages.html#subpath-imports), you may find that Vitest does not respect these conditions by default.\n\nFor example, if you have the following in your `package.json`:\n\n```json\n{\n  \"exports\": {\n    \".\": {\n      \"custom\": \"./lib/custom.js\",\n      \"import\": \"./lib/index.js\"\n    }\n  },\n  \"imports\": {\n    \"#internal\": {\n      \"custom\": \"./src/internal.js\",\n      \"default\": \"./lib/internal.js\"\n    }\n  }\n}\n```\n\nBy default, Vitest will only use the `import` and `default` conditions. To make Vitest respect custom conditions, you need to configure [`ssr.resolve.conditions`](https://vite.dev/config/ssr-options#ssr-resolve-conditions) in your Vitest config:\n\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  ssr: {\n    resolve: {\n      conditions: ['custom', 'import', 'default'],\n    },\n  },\n})\n```\n\n::: tip Why `ssr.resolve.conditions` and not `resolve.conditions`?\nVitest follows Vite's configuration convention:\n- [`resolve.conditions`](https://vite.dev/config/shared-options#resolve-conditions) applies to Vite's `client` environment, which corresponds to Vitest's browser mode, jsdom, happy-dom, or custom environments with `viteEnvironment: 'client'`.\n- [`ssr.resolve.conditions`](https://vite.dev/config/ssr-options#ssr-resolve-conditions) applies to Vite's `ssr` environment, which corresponds to Vitest's node environment or custom environments with `viteEnvironment: 'ssr'`.\n\nSince Vitest defaults to the `node` environment (which uses `viteEnvironment: 'ssr'`), module resolution uses `ssr.resolve.conditions`. This applies to both package exports and subpath imports.\n\nYou can learn more about Vite environments and Vitest environments in [`environment`](/config/environment).\n:::\n\n## Segfaults and Native Code Errors\n\nRunning [native NodeJS modules](https://nodejs.org/api/addons.html) in `pool: 'threads'` can run into cryptic errors coming from the native code.\n\n- `Segmentation fault (core dumped)`\n- `thread '<unnamed>' panicked at 'assertion failed`\n- `Abort trap: 6`\n- `internal error: entered unreachable code`\n\nIn these cases the native module is likely not built to be multi-thread safe. As a workaround, you can switch to `pool: 'forks'` which runs the test cases in multiple `node:child_process` instead of multiple `node:worker_threads`.\n\n::: code-group\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    pool: 'forks',\n  },\n})\n```\n```bash [CLI]\nvitest --pool=forks\n```\n:::\n\n## Unhandled Promise Rejection\n\nThis error happens when a Promise rejects but no `.catch()` handler or `await` is attached to it before the microtask queue flushes. This behavior comes from JavaScript itself and is not specific to Vitest. Learn more in the [Node.js documentation](https://nodejs.org/api/process.html#event-unhandledrejection).\n\nA common cause is calling an async function without `await`ing it:\n\n```ts\nasync function fetchUser(id) {\n  const res = await fetch(`/api/users/${id}`)\n  if (!res.ok) {\n    throw new Error(`User ${id} not found`) // [!code highlight]\n  }\n  return res.json()\n}\n\ntest('fetches user', async () => {\n  fetchUser(123) // [!code error]\n})\n```\n\nBecause `fetchUser()` is not `await`ed, its rejection has no handler and Vitest reports:\n\n```\nUnhandled Rejection: Error: User 123 not found\n```\n\n### Fix\n\n`await` the promise so Vitest can catch the error:\n\n```ts\ntest('fetches user', async () => {\n  await fetchUser(123) // [!code ++]\n})\n```\n\nIf you expect the call to throw, use [`expect().rejects`](/api/expect#rejects):\n\n```ts\ntest('rejects for missing user', async () => {\n  await expect(fetchUser(123)).rejects.toThrow('User 123 not found')\n})\n```\n"
  },
  {
    "path": "docs/guide/comparisons.md",
    "content": "---\ntitle: Comparisons with Other Test Runners | Guide\n---\n\n# Comparisons with Other Test Runners\n\n## Jest\n\n[Jest](https://jestjs.io/) took over the Testing Framework space by providing out-of-the-box support for most JavaScript projects, a comfortable API (`it` and `expect`), and the full pack of testing features that most setups would require (snapshots, mocks, coverage). We are thankful to the Jest team and community for creating a delightful testing API and pushing forward a lot of the testing patterns that are now a standard in the web ecosystem.\n\nIt is possible to use Jest in Vite setups. [@sodatea](https://bsky.app/profile/haoqun.dev) built [vite-jest](https://github.com/sodatea/vite-jest#readme), which aims to provide first-class Vite integration for [Jest](https://jestjs.io/). The last [blockers in Jest](https://github.com/sodatea/vite-jest/blob/main/packages/vite-jest/README.md#vite-jest) have been solved, so this is a valid option for your unit tests.\n\nHowever, in a world where we have [Vite](https://vitejs.dev) providing support for the most common web tooling (TypeScript, JSX, most popular UI Frameworks), Jest represents a duplication of complexity. If your app is powered by Vite, having two different pipelines to configure and maintain is not justifiable. With Vitest you get to define the configuration for your dev, build and test environments as a single pipeline, sharing the same plugins and the same vite.config.js.\n\nEven if your library is not using Vite (for example, if it is built with esbuild or Rollup), Vitest is an interesting option as it gives you a faster run for your unit tests and a jump in DX thanks to the default watch mode using Vite instant Hot Module Reload (HMR). Vitest offers compatibility with most of the Jest API and ecosystem libraries, so in most projects, it should be a drop-in replacement for Jest.\n\n## Cypress\n\n[Cypress](https://www.cypress.io/) is a browser-based test runner and a complementary tool to Vitest. If you'd like to use Cypress, we suggest using Vitest for all headless logic in your application and Cypress for all browser-based logic.\n\nCypress is known as an end-to-end testing tool, but their [new component test runner](https://on.cypress.io/component) has great support for testing Vite components and is an ideal choice to test anything that renders in a browser.\n\nBrowser-based runners, like Cypress, WebdriverIO and Web Test Runner, will catch issues that Vitest cannot because they use the real browser and real browser APIs.\n\nCypress's test driver is focused on determining if elements are visible, accessible, and interactive. Cypress is purpose-built for UI development and testing and its DX is centered around test driving your visual components. You see your component rendered alongside the test reporter. Once the test is complete, the component remains interactive and you can debug any failures that occur using your browser devtools.\n\nIn contrast, Vitest is focused on delivering the best DX possible for lightning fast, *headless* testing. Node-based runners like Vitest support various partially-implemented browser environments, like `jsdom`, which implement enough for you to quickly unit test any code that references browser APIs. The tradeoff is that these browser environments have limitations in what they can implement. For example, [jsdom is missing a number of features](https://github.com/jsdom/jsdom/issues?q=is%3Aissue+is%3Aopen+sort%3Acomments-desc) like `window.navigation` or a layout engine (`offsetTop`, etc).\n\nLastly, in contrast to the Web Test Runner, the Cypress test runner is more like an IDE than a test runner because you also see the real rendered component in the browser, along with its test results and logs.\n\nCypress has also been [integrating Vite in their products](https://www.youtube.com/watch?v=7S5cbY8iYLk): re-building their App's UI using [Vitesse](https://github.com/antfu/vitesse) and using Vite to test drive their project's development.\n\nWe believe that Cypress isn't a good option for unit testing headless code, but that using Cypress (for E2E and Component Testing) and Vitest (for unit tests) would cover your app's testing needs.\n\n## WebdriverIO\n\n[WebdriverIO](https://webdriver.io/) is, similar to Cypress, a browser-based alternative test runner and a complementary tool to Vitest. It can be used as an end-to-end testing tool as well as for testing [web components](https://webdriver.io/docs/component-testing). It even uses components of Vitest under the hood, e.g. for [mocking and stubbing](https://webdriver.io/docs/mocksandspies/) within component tests.\n\nWebdriverIO comes with the same advantages as Cypress allowing you to test your logic in real browser. However, it uses actual [web standards](https://w3c.github.io/webdriver/) for automation, which overcomes some of the tradeoffs and limitation when running tests in Cypress. Furthermore, it allows you to run tests on mobile as well, giving you access to test your application in even more environments.\n\n## Web Test Runner\n\n[@web/test-runner](https://modern-web.dev/docs/test-runner/overview/) runs tests inside a headless browser, providing the same execution environment as your web application without the need for mocking out browser APIs or the DOM. This also makes it possible to debug inside a real browser using the devtools, although there is no UI shown for stepping through the test, as there is in Cypress tests.\n\nTo use @web/test-runner with a Vite project, use [@remcovaes/web-test-runner-vite-plugin](https://github.com/remcovaes/web-test-runner-vite-plugin). @web/test-runner does not include assertion or mocking libraries, so it is up to you to add them.\n\n## uvu\n\n[uvu](https://github.com/lukeed/uvu) is a test runner for Node.js and the browser. It runs tests in a single thread, so tests are not isolated and can leak across files. Vitest, however, uses worker threads to isolate tests and run them in parallel.\n\nFor transforming your code, uvu relies on require and loader hooks. Vitest uses [Vite](https://vitejs.dev), so files are transformed with the full power of Vite's plugin system. In a world where we have Vite providing support for the most common web tooling (TypeScript, JSX, most popular UI Frameworks), uvu represents a duplication of complexity. If your app is powered by Vite, having two different pipelines to configure and maintain is not justifiable. With Vitest you get to define the configuration for your dev, build and test environments as a single pipeline, sharing the same plugins and the same configuration.\n\nuvu does not provide an intelligent watch mode to rerun the changed tests, while Vitest gives you amazing DX thanks to the default watch mode using Vite instant Hot Module Reload (HMR).\n\nuvu is a fast option for running simple tests, but Vitest can be faster and more reliable for more complex tests and projects.\n\n## Mocha\n\n[Mocha](https://mochajs.org) is a test framework running on Node.js and in the browser. Mocha is a popular choice for server-side testing. Mocha is highly configurable and does not include certain features by default. For example, it does not come with an assertion library, with the idea being that Node's built-in assertion runner is good enough for most use cases. Another popular choice for assertions with Mocha is [Chai](https://www.chaijs.com).\n\nVitest also provides out-of-the-box setup for a few other features, which take additional configuration or the addition of other libraries in Mocha, for example:\n\n- Snapshot testing\n- TypeScript\n- JSX support\n- Code Coverage\n- Mocking\n- Smart watch mode (only re-runs affected tests)\n\nWhile Mocha supports Native ESM, it has limitations and configuration constraints. Watch mode does not work with ES Module files, for example.\n\nPerformance-wise, Mocha runs tests serially by default but supports parallel execution with the `--parallel` flag (though some reporters and features don't work in parallel mode).\n\nIf you're already using Vite in your build pipeline, Vitest allows you to reuse the same configuration and plugins for testing, whereas Mocha would require a separate test setup. Vitest provides a Jest-compatible API while also supporting Mocha's familiar `describe`, `it`, and hook syntax, making migration straightforward for most test suites.\n\nMocha remains a solid choice for projects that need a minimal, flexible test runner with complete control over their testing stack. However, if you want a modern testing experience with everything included out of the box - especially for Vite-powered applications - Vitest has you covered.\n\n## Playwright\n\n[Playwright](https://playwright.dev) is a testing framework from Microsoft that excels at end-to-end testing across multiple browsers (Chromium, Firefox, and WebKit). It controls real browsers to test complete user workflows—from logging in and navigating your app to submitting forms and verifying results. Vitest, on the other hand, is optimised for fast, isolated unit and component tests in a headless environment. These differences make it an ideal complement to Vitest.\n\nA standard setup is to use Vitest for all unit and component tests (business logic, utilities, hooks, and UI component tests), and Playwright for end-to-end tests that verify critical user paths and cross-browser compatibility. This combination gives you fast feedback during development with Vitest while ensuring your complete application works correctly in real browsers with Playwright.\n\nVitest recently introduced [browser mode](https://vitest.dev/guide/browser), which runs tests in real browsers. However, there are key architectural differences: Playwright component tests run in a Node.js process and control the browser remotely. Vitest's browser mode runs tests natively in the browser, maintaining consistency with Vitest's test runner and developer experience, but it does have some [limitations](https://vitest.dev/guide/browser/#limitations).\n"
  },
  {
    "path": "docs/guide/coverage.md",
    "content": "---\ntitle: Coverage | Guide\n---\n\n# Coverage\n\nVitest supports Native code coverage via [`v8`](https://v8.dev/blog/javascript-code-coverage) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/).\n\n## Coverage Providers\n\nBoth `v8` and `istanbul` support are optional. By default, `v8` will be used.\n\nYou can select the coverage tool by setting `test.coverage.provider` to `v8` or `istanbul`:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      provider: 'v8' // or 'istanbul'\n    },\n  },\n})\n```\n\nWhen you start the Vitest process, it will prompt you to install the corresponding support package automatically.\n\nOr if you prefer to install them manually:\n\n::: code-group\n```bash [v8]\nnpm i -D @vitest/coverage-v8\n```\n```bash [istanbul]\nnpm i -D @vitest/coverage-istanbul\n```\n:::\n\n## V8 Provider\n\n::: info\nThe description of V8 coverage below is Vitest specific and does not apply to other test runners.\nSince `v3.2.0` Vitest has used [AST based coverage remapping](/blog/vitest-3-2#coverage-v8-ast-aware-remapping) for V8 coverage, which produces identical coverage reports to Istanbul.\n\nThis allows users to have the speed of V8 coverage with accuracy of Istanbul coverage.\n:::\n\nBy default Vitest uses `'v8'` coverage provider.\nThis provider requires Javascript runtime that's implemented on top of [V8 engine](https://v8.dev/), such as NodeJS, Deno or any Chromium based browsers such as Google Chrome.\n\nCoverage collection is performed during runtime by instructing V8 using [`node:inspector`](https://nodejs.org/api/inspector.html) and [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/) in browsers. User's source files can be executed as-is without any pre-instrumentation steps.\n\n- ✅ Recommended option to use\n- ✅ No pre-transpile step. Test files can be executed as-is.\n- ✅ Faster execute times than Istanbul.\n- ✅ Lower memory usage than Istanbul.\n- ✅ Coverage report accuracy is as good as with Istanbul ([since Vitest `v3.2.0`](/blog/vitest-3-2#coverage-v8-ast-aware-remapping)).\n- ⚠️ In some cases can be slower than Istanbul, e.g. when loading lots of different modules. V8 does not support limiting coverage collection to specific modules.\n- ⚠️ There are some minor limitations set by V8 engine. See [`ast-v8-to-istanbul` | Limitations](https://github.com/AriPerkkio/ast-v8-to-istanbul?tab=readme-ov-file#limitations).\n- ❌ Does not work on environments that don't use V8, such as Firefox or Bun. Or on environments that don't expose V8 coverage via profiler, such as Cloudflare Workers.\n\n<script setup>\nimport ArrowDown from '../.vitepress/components/ArrowDown.vue'\nimport Box from '../.vitepress/components/Box.vue'\n</script>\n\n<div style=\"display: flex; flex-direction: column; align-items: center; padding: 2rem 0; max-width: 20rem;\">\n  <Box>Test file</Box>\n  <ArrowDown />\n  <Box>Enable V8 runtime coverage collection</Box>\n  <ArrowDown />\n  <Box>Run file</Box>\n  <ArrowDown />\n  <Box>Collect coverage results from V8</Box>\n  <ArrowDown />\n  <Box>Remap coverage results to source files</Box>\n  <ArrowDown />\n  <Box>Coverage report</Box>\n</div>\n\n## Istanbul Provider\n\n[Istanbul code coverage tooling](https://istanbul.js.org/) has existed since 2012 and is very well battle-tested.\nThis provider works on any Javascript runtime as coverage tracking is done by instrumenting user's source files.\n\nIn practice, instrumenting source files means adding additional Javascript in user's files:\n\n```js\n// Simplified example of branch and function coverage counters\nconst coverage = { // [!code ++]\n  branches: { 1: [0, 0] }, // [!code ++]\n  functions: { 1: 0 }, // [!code ++]\n} // [!code ++]\n\nexport function getUsername(id) {\n  // Function coverage increased when this is invoked  // [!code ++]\n  coverage.functions['1']++ // [!code ++]\n\n  if (id == null) {\n    // Branch coverage increased when this is invoked  // [!code ++]\n    coverage.branches['1'][0]++ // [!code ++]\n\n    throw new Error('User ID is required')\n  }\n  // Implicit else coverage increased when if-statement condition not met  // [!code ++]\n  coverage.branches['1'][1]++ // [!code ++]\n\n  return database.getUser(id)\n}\n\nglobalThis.__VITEST_COVERAGE__ ||= {} // [!code ++]\nglobalThis.__VITEST_COVERAGE__[filename] = coverage // [!code ++]\n```\n\n- ✅ Works on any Javascript runtime\n- ✅ Widely used and battle-tested for over 13 years.\n- ✅ In some cases faster than V8. Coverage instrumentation can be limited to specific files, as opposed to V8 where all modules are instrumented.\n- ❌ Requires pre-instrumentation step\n- ❌ Execution speed is slower than V8 due to instrumentation overhead\n- ❌ Instrumentation increases file sizes\n- ❌ Memory usage is higher than V8\n\n<div style=\"display: flex; flex-direction: column; align-items: center; padding: 2rem 0; max-width: 20rem;\">\n  <Box>Test file</Box>\n  <ArrowDown />\n  <Box>Pre‑instrumentation with Babel</Box>\n  <ArrowDown />\n  <Box>Run file</Box>\n  <ArrowDown />\n  <Box>Collect coverage results from Javascript scope</Box>\n  <ArrowDown />\n  <Box>Remap coverage results to source files</Box>\n  <ArrowDown />\n  <Box>Coverage report</Box>\n</div>\n\n## Coverage Setup\n\n::: tip\nAll coverage options are listed in [Coverage Config Reference](/config/coverage).\n:::\n\nTo test with coverage enabled, you can pass the `--coverage` flag in CLI or set `coverage.enabled` in `vitest.config.ts`:\n\n::: code-group\n```json [package.json]\n{\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"coverage\": \"vitest run --coverage\"\n  }\n}\n```\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      enabled: true\n    },\n  },\n})\n```\n:::\n\n## Including and Excluding Files from Coverage Report\n\nYou can define what files are shown in coverage report by configuring [`coverage.include`](/config/coverage#coverage-include) and [`coverage.exclude`](/config/coverage#coverage-exclude).\n\nBy default Vitest will show only files that were imported during test run.\nTo include uncovered files in the report, you'll need to configure [`coverage.include`](/config/coverage#coverage-include) with a pattern that will pick your source files:\n\n::: code-group\n```ts [vitest.config.ts] {6}\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      include: ['src/**/*.{ts,tsx}']\n    },\n  },\n})\n```\n```sh [Covered Files]\n├── src\n│   ├── components\n│   │   └── counter.tsx   # [!code ++]\n│   ├── mock-data\n│   │   ├── products.json # [!code error]\n│   │   └── users.json    # [!code error]\n│   └── utils\n│       ├── formatters.ts # [!code ++]\n│       ├── time.ts       # [!code ++]\n│       └── users.ts      # [!code ++]\n├── test\n│   └── utils.test.ts     # [!code error]\n│\n├── package.json          # [!code error]\n├── tsup.config.ts        # [!code error]\n└── vitest.config.ts      # [!code error]\n```\n:::\n\nTo exclude files that are matching `coverage.include`, you can define an additional [`coverage.exclude`](/config/coverage#coverage-exclude):\n\n::: code-group\n```ts [vitest.config.ts] {7}\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      include: ['src/**/*.{ts,tsx}'],\n      exclude: ['**/utils/users.ts']\n    },\n  },\n})\n```\n```sh [Covered Files]\n├── src\n│   ├── components\n│   │   └── counter.tsx   # [!code ++]\n│   ├── mock-data\n│   │   ├── products.json # [!code error]\n│   │   └── users.json    # [!code error]\n│   └── utils\n│       ├── formatters.ts # [!code ++]\n│       ├── time.ts       # [!code ++]\n│       └── users.ts      # [!code error]\n├── test\n│   └── utils.test.ts     # [!code error]\n│\n├── package.json          # [!code error]\n├── tsup.config.ts        # [!code error]\n└── vitest.config.ts      # [!code error]\n```\n:::\n\n## Custom Coverage Reporter\n\nYou can use custom coverage reporters by passing either the name of the package or absolute path in `test.coverage.reporter`:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      reporter: [\n        // Specify reporter using name of the NPM package\n        ['@vitest/custom-coverage-reporter', { someOption: true }],\n\n        // Specify reporter using local path\n        '/absolute/path/to/custom-reporter.cjs',\n      ],\n    },\n  },\n})\n```\n\nCustom reporters are loaded by Istanbul and must match its reporter interface. See [built-in reporters' implementation](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib) for reference.\n\n```js [custom-reporter.cjs]\nconst { ReportBase } = require('istanbul-lib-report')\n\nmodule.exports = class CustomReporter extends ReportBase {\n  constructor(opts) {\n    super()\n\n    // Options passed from configuration are available here\n    this.file = opts.file\n  }\n\n  onStart(root, context) {\n    this.contentWriter = context.writer.writeFile(this.file)\n    this.contentWriter.println('Start of custom coverage report')\n  }\n\n  onEnd() {\n    this.contentWriter.println('End of custom coverage report')\n    this.contentWriter.close()\n  }\n}\n```\n\n## Custom Coverage Provider\n\nIt's also possible to provide your custom coverage provider by passing `'custom'` in `test.coverage.provider`:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      provider: 'custom',\n      customProviderModule: 'my-custom-coverage-provider'\n    },\n  },\n})\n```\n\nThe custom providers require a `customProviderModule` option which is a module name or path where to load the `CoverageProviderModule` from. It must export an object that implements `CoverageProviderModule` as default export:\n\n```ts [my-custom-coverage-provider.ts]\nimport type {\n  CoverageProvider,\n  CoverageProviderModule,\n  ResolvedCoverageOptions,\n  Vitest\n} from 'vitest'\n\nconst CustomCoverageProviderModule: CoverageProviderModule = {\n  getProvider(): CoverageProvider {\n    return new CustomCoverageProvider()\n  },\n\n  // Implements rest of the CoverageProviderModule ...\n}\n\nclass CustomCoverageProvider implements CoverageProvider {\n  name = 'custom-coverage-provider'\n  options!: ResolvedCoverageOptions\n\n  initialize(ctx: Vitest) {\n    this.options = ctx.config.coverage\n  }\n\n  // Implements rest of the CoverageProvider ...\n}\n\nexport default CustomCoverageProviderModule\n```\n\nPlease refer to the type definition for more details.\n\n## Ignoring Code\n\nBoth coverage providers have their own ways how to ignore code from coverage reports:\n\n- [`v8`](https://github.com/AriPerkkio/ast-v8-to-istanbul?tab=readme-ov-file#ignoring-code)\n- [`istanbul`](https://github.com/istanbuljs/nyc#parsing-hints-ignoring-lines)\n\nWhen using TypeScript the source codes are transpiled using `esbuild`, which strips all comments from the source codes ([esbuild#516](https://github.com/evanw/esbuild/issues/516)).\nComments which are considered as [legal comments](https://esbuild.github.io/api/#legal-comments) are preserved.\n\nYou can include a `@preserve` keyword in the ignore hint.\nBeware that these ignore hints may now be included in final production build as well.\n\n::: tip\nFollow https://github.com/vitest-dev/vitest/issues/2021 for updates about `@preserve` usage.\n:::\n\n```diff\n-/* istanbul ignore if */\n+/* istanbul ignore if -- @preserve */\nif (condition) {\n\n-/* v8 ignore if */\n+/* v8 ignore if -- @preserve */\nif (condition) {\n```\n\n### Examples\n\n::: code-group\n\n```ts [lines: start/stop]\n/* istanbul ignore start -- @preserve */\nif (parameter) { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\nelse { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\n/* istanbul ignore stop -- @preserve */\n\nconsole.log('Included')\n\n/* v8 ignore start -- @preserve */\nif (parameter) { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\nelse { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\n/* v8 ignore stop -- @preserve */\n\nconsole.log('Included')\n```\n\n```ts [if else]\n/* v8 ignore if -- @preserve */\nif (parameter) { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\nelse {\n  console.log('Included')\n}\n\n/* v8 ignore else -- @preserve */\nif (parameter) {\n  console.log('Included')\n}\nelse { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\n```\n\n```ts [next node]\n/* v8 ignore next -- @preserve */\nconsole.log('Ignored') // [!code error]\nconsole.log('Included')\n\n/* v8 ignore next -- @preserve */\nfunction ignored() { // [!code error]\n  console.log('all') // [!code error]\n  // [!code error]\n  console.log('lines') // [!code error]\n  // [!code error]\n  console.log('are') // [!code error]\n  // [!code error]\n  console.log('ignored') // [!code error]\n} // [!code error]\n\n/* v8 ignore next -- @preserve */\nclass Ignored { // [!code error]\n  ignored() {} // [!code error]\n  alsoIgnored() {} // [!code error]\n} // [!code error]\n\n/* v8 ignore next -- @preserve */\ncondition // [!code error]\n  ? console.log('ignored') // [!code error]\n  : console.log('also ignored') // [!code error]\n```\n\n```ts [try catch]\n/* v8 ignore next -- @preserve */\ntry { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\ncatch (error) { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\n\ntry {\n  console.log('Included')\n}\ncatch (error) {\n  /* v8 ignore next -- @preserve */\n  console.log('Ignored') // [!code error]\n  /* v8 ignore next -- @preserve */\n  console.log('Ignored') // [!code error]\n}\n\n// Requires rolldown-vite due to esbuild's lack of support.\n// See https://vite.dev/guide/rolldown.html#how-to-try-rolldown\ntry {\n  console.log('Included')\n}\ncatch (error) /* v8 ignore next */ { // [!code error]\n  console.log('Ignored') // [!code error]\n} // [!code error]\n```\n\n```ts [switch case]\nswitch (type) {\n  case 1:\n    return 'Included'\n\n  /* v8 ignore next -- @preserve */\n  case 2: // [!code error]\n    return 'Ignored' // [!code error]\n\n  case 3:\n    return 'Included'\n\n  /* v8 ignore next -- @preserve */\n  default: // [!code error]\n    return 'Ignored' // [!code error]\n}\n```\n\n```ts [whole file]\n/* v8 ignore file -- @preserve */\nexport function ignored() { // [!code error]\n  return 'Whole file is ignored'// [!code error]\n}// [!code error]\n```\n:::\n\n## Coverage Performance\n\nIf code coverage generation is slow on your project, see [Profiling Test Performance | Code coverage](/guide/profiling-test-performance.html#code-coverage).\n\n## Vitest UI\n\nYou can check your coverage report in [Vitest UI](/guide/ui) and [HTML reporter](/guide/reporters.html#html-reporter).\n\nThis is integrated with builtin coverage reporters with HTML output (`html`, `html-spa`, and `lcov` reporters). `html` reporter is enabled by default and this works out of the box. To integrate with custom reporters, you can configure [`coverage.htmlDir`](/config/coverage#coverage-htmldir).\n\n<img alt=\"html coverage activation in Vitest UI\" img-light src=\"/vitest-ui-show-coverage-light.png\">\n<img alt=\"html coverage activation in Vitest UI\" img-dark src=\"/vitest-ui-show-coverage-dark.png\">\n\n<img alt=\"html coverage in Vitest UI\" img-light src=\"/ui-coverage-1-light.png\">\n<img alt=\"html coverage in Vitest UI\" img-dark src=\"/ui-coverage-1-dark.png\">\n"
  },
  {
    "path": "docs/guide/debugging.md",
    "content": "---\ntitle: Debugging | Guide\n---\n\n# Debugging\n\n:::tip\nWhen debugging tests you might want to use following options:\n\n- [`--test-timeout=0`](/guide/cli#testtimeout) to prevent tests from timing out when stopping at breakpoints\n- [`--no-file-parallelism`](/guide/cli#fileparallelism) to prevent test files from running parallel\n\n:::\n\n## VS Code\n\nQuick way to debug tests in VS Code is via `JavaScript Debug Terminal`. Open a new `JavaScript Debug Terminal` and run `npm run test` or `vitest` directly. *this works with any code run in Node, so will work with most JS testing frameworks*\n\n![image](https://user-images.githubusercontent.com/5594348/212169143-72bf39ce-f763-48f5-822a-0c8b2e6a8484.png)\n\nYou can also add a dedicated launch configuration to debug a test file in VS Code:\n\n```json\n{\n  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Debug Current Test File\",\n      \"autoAttachChildProcesses\": true,\n      \"skipFiles\": [\"<node_internals>/**\", \"**/node_modules/**\"],\n      \"program\": \"${workspaceRoot}/node_modules/vitest/vitest.mjs\",\n      \"args\": [\"run\", \"${relativeFile}\"],\n      \"smartStep\": true,\n      \"console\": \"integratedTerminal\"\n    }\n  ]\n}\n```\n\nThen in the debug tab, ensure 'Debug Current Test File' is selected. You can then open the test file you want to debug and press F5 to start debugging.\n\n### Browser mode\n\nTo debug [Vitest Browser Mode](/guide/browser/index.md), pass `--inspect` or `--inspect-brk` in CLI or define it in your Vitest configuration:\n\n::: code-group\n```bash [CLI]\nvitest --inspect-brk --browser --no-file-parallelism\n```\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    inspectBrk: true,\n    fileParallelism: false,\n    browser: {\n      provider: playwright(),\n      instances: [{ browser: 'chromium' }]\n    },\n  },\n})\n```\n:::\n\nBy default Vitest will use port `9229` as debugging port. You can overwrite it with by passing value in `--inspect-brk`:\n\n```bash\nvitest --inspect-brk=127.0.0.1:3000 --browser --no-file-parallelism\n```\n\nUse following [VSCode Compound configuration](https://code.visualstudio.com/docs/editor/debugging#_compound-launch-configurations) for launching Vitest and attaching debugger in the browser:\n\n```json\n{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Run Vitest Browser\",\n      \"program\": \"${workspaceRoot}/node_modules/vitest/vitest.mjs\",\n      \"console\": \"integratedTerminal\",\n      \"args\": [\"--inspect-brk\", \"--browser\", \"--no-file-parallelism\"]\n    },\n    {\n      \"type\": \"chrome\",\n      \"request\": \"attach\",\n      \"name\": \"Attach to Vitest Browser\",\n      \"port\": 9229\n    }\n  ],\n  \"compounds\": [\n    {\n      \"name\": \"Debug Vitest Browser\",\n      \"configurations\": [\"Attach to Vitest Browser\", \"Run Vitest Browser\"],\n      \"stopAll\": true\n    }\n  ]\n}\n```\n\n## IntelliJ IDEA\n\nCreate a [vitest](https://www.jetbrains.com/help/idea/vitest.html#createRunConfigVitest) run configuration. Use the following settings to run all tests in debug mode:\n\nSetting | Value\n --- | ---\nWorking directory | `/path/to/your-project-root`\n\nThen run this configuration in debug mode. The IDE will stop at JS/TS breakpoints set in the editor.\n\n## Node Inspector, e.g. Chrome DevTools\n\nVitest also supports debugging tests without IDEs. However this requires that tests are not run parallel. Use one of the following commands to launch Vitest.\n\n```sh\n# To run in a single worker\nvitest --inspect-brk --no-file-parallelism\n\n# To run in browser mode\nvitest --inspect-brk --browser --no-file-parallelism\n```\n\nOnce Vitest starts it will stop execution and wait for you to open developer tools that can connect to [Node.js inspector](https://nodejs.org/en/docs/guides/debugging-getting-started/). You can use Chrome DevTools for this by opening `chrome://inspect` on browser.\n\nIn watch mode you can keep the debugger open during test re-runs by using the `--isolate false` options.\n"
  },
  {
    "path": "docs/guide/environment.md",
    "content": "---\ntitle: Test Environment | Guide\n---\n\n# Test Environment\n\nVitest provides [`environment`](/config/environment) option to run code inside a specific environment. You can modify how environment behaves with [`environmentOptions`](/config/environmentoptions) option.\n\nBy default, you can use these environments:\n\n- `node` is default environment\n- `jsdom` emulates browser environment by providing Browser API, uses [`jsdom`](https://github.com/jsdom/jsdom) package\n- `happy-dom` emulates browser environment by providing Browser API, and considered to be faster than jsdom, but lacks some API, uses [`happy-dom`](https://github.com/capricorn86/happy-dom) package\n- `edge-runtime` emulates Vercel's [edge-runtime](https://edge-runtime.vercel.app/), uses [`@edge-runtime/vm`](https://npmx.dev/package/@edge-runtime/vm) package\n\n::: info\nWhen using `jsdom` or `happy-dom` environments, Vitest follows the same rules that Vite does when importing [CSS](https://vitejs.dev/guide/features.html#css) and [assets](https://vitejs.dev/guide/features.html#static-assets). If importing external dependency fails with `unknown extension .css` error, you need to inline the whole import chain manually by adding all packages to [`server.deps.inline`](/config/server#inline). For example, if the error happens in `package-3` in this import chain: `source code -> package-1 -> package-2 -> package-3`, you need to add all three packages to `server.deps.inline`.\n\nThe `require` of CSS and assets inside the external dependencies are resolved automatically.\n:::\n\n::: warning\n\"Environments\" exist only when running tests in Node.js.\n\n`browser` is not considered an environment in Vitest. If you wish to run part of your tests using [Browser Mode](/guide/browser/), you can create a [test project](/guide/browser/#projects-config).\n:::\n\n## Environments for Specific Files\n\nWhen setting `environment` option in your config, it will apply to all the test files in your project. To have more fine-grained control, you can use control comments to specify environment for specific files. Control comments are comments that start with `@vitest-environment` and are followed by the environment name:\n\n```ts\n// @vitest-environment jsdom\n\nimport { expect, test } from 'vitest'\n\ntest('test', () => {\n  expect(typeof window).not.toBe('undefined')\n})\n```\n\n## Custom Environment\n\nYou can create your own package to extend Vitest environment. To do so, create package with the name `vitest-environment-${name}` or specify a path to a valid JS/TS file. That package should export an object with the shape of `Environment`:\n\n```ts\nimport type { Environment } from 'vitest/runtime'\n\nexport default <Environment>{\n  name: 'custom',\n  viteEnvironment: 'ssr',\n  // optional - only if you support \"vmForks\" or \"vmThreads\" pools\n  async setupVM() {\n    const vm = await import('node:vm')\n    const context = vm.createContext()\n    return {\n      getVmContext() {\n        return context\n      },\n      teardown() {\n        // called after all tests with this env have been run\n      }\n    }\n  },\n  setup() {\n    // custom setup\n    return {\n      teardown() {\n        // called after all tests with this env have been run\n      }\n    }\n  }\n}\n```\n\n::: warning\nVitest requires `viteEnvironment` option on environment object (fallbacks to the Vitest environment name by default). It should be equal to `ssr`, `client` or any custom [Vite environment](https://vite.dev/guide/api-environment) name. This value determines which environment is used to process file.\n:::\n\nYou also have access to default Vitest environments through `vitest/runtime` entry:\n\n```ts\nimport { builtinEnvironments, populateGlobal } from 'vitest/runtime'\n\nconsole.log(builtinEnvironments) // { jsdom, happy-dom, node, edge-runtime }\n```\n\nVitest also provides `populateGlobal` utility function, which can be used to move properties from object into the global namespace:\n\n```ts\ninterface PopulateOptions {\n  // should non-class functions be bind to the global namespace\n  bindFunctions?: boolean\n}\n\ninterface PopulateResult {\n  // a list of all keys that were copied, even if value doesn't exist on original object\n  keys: Set<string>\n  // a map of original object that might have been overridden with keys\n  // you can return these values inside `teardown` function\n  originals: Map<string | symbol, any>\n}\n\nexport function populateGlobal(global: any, original: any, options: PopulateOptions): PopulateResult\n```\n"
  },
  {
    "path": "docs/guide/examples/projects-workspace.md",
    "content": "```ts\nimport { defineConfig } from \"vitest/config\";\nexport default defineConfig({\n  test: {\n    // \"test.workspace\" is now \"test.projects\"\n    workspace: [ // [!code --]\n    projects: [ // [!code ++]\n      { test: { name: \"Unit\" } },\n      { test: { name: \"Integration\" } },\n    ],\n  },\n});\n```\n"
  },
  {
    "path": "docs/guide/examples/promise-done.md",
    "content": "```js\nit('should work', (done) => {  // [!code --]\nit('should work', () => new Promise(done => { // [!code ++]\n  // ...\n  done()\n}) // [!code --]\n})) // [!code ++]\n```\n"
  },
  {
    "path": "docs/guide/extending-matchers.md",
    "content": "---\ntitle: Extending Matchers | Guide\n---\n\n# Extending Matchers\n\nSince Vitest is compatible with both Chai and Jest, you can use either the [`chai.use`](https://www.chaijs.com/guide/plugins/) API or `expect.extend`, whichever you prefer.\n\nThis guide will explore extending matchers with `expect.extend`. If you are interested in Chai's API, check [their guide](https://www.chaijs.com/guide/plugins/).\n\nTo extend default matchers, call `expect.extend` with an object containing your matchers.\n\n```ts\nexpect.extend({\n  toBeFoo(received, expected) {\n    const { isNot } = this\n    return {\n      // do not alter your \"pass\" based on isNot. Vitest does it for you\n      pass: received === 'foo',\n      message: () => `${received} is${isNot ? ' not' : ''} foo`\n    }\n  }\n})\n```\n\nIf you are using TypeScript, you can extend default `Matchers` interface in an ambient declaration file (e.g: `vitest.d.ts`) with the code below:\n\n```ts\nimport 'vitest'\n\ndeclare module 'vitest' {\n  interface Matchers<T = any> {\n    toBeFoo: () => R\n  }\n}\n```\n\n::: tip\nImporting `vitest` makes TypeScript think this is an ES module file, type declaration won't work without it.\n:::\n\nExtending the `Matchers` interface will add a type to `expect.extend`, `expect().*`, and `expect.*` methods at the same time.\n\n::: warning\nDon't forget to include the ambient declaration file in your `tsconfig.json`.\n:::\n\nThe return value of a matcher should be compatible with the following interface:\n\n```ts\ninterface MatcherResult {\n  pass: boolean\n  message: () => string\n  // If you pass these, they will automatically appear inside a diff when\n  // the matcher does not pass, so you don't need to print the diff yourself\n  actual?: unknown\n  expected?: unknown\n}\n```\n\n::: warning\nIf you create an asynchronous matcher, don't forget to `await` the result (`await expect('foo').toBeFoo()`) in the test itself:\n\n```ts\nexpect.extend({\n  async toBeAsyncAssertion() {\n    // ...\n  }\n})\n\nawait expect().toBeAsyncAssertion()\n```\n:::\n\nThe first argument inside a matcher's function is the received value (the one inside `expect(received)`). The rest are arguments passed directly to the matcher. Since version 4.1, Vitest exposes several types that can be used by your custom matcher:\n\n```ts\nimport type {\n  // the function type\n  Matcher,\n  // the return value\n  MatcherResult,\n  // state available as `this`\n  MatcherState,\n} from 'vitest'\nimport { expect } from 'vitest'\n\n// a simple matcher, using \"function\" to have access to \"this\"\nconst customMatcher: Matcher = function (received) {\n  // ...\n}\n\n// a matcher with arguments\nconst customMatcher: Matcher<MatcherState, [arg1: unknown, arg2: unknown]> = function (received, arg1, arg2) {\n  // ...\n}\n\n// a matcher with custom annotations\nfunction customMatcher(this: MatcherState, received: unknown, arg1: unknown, arg2: unknown): MatcherResult {\n  // ...\n  return {\n    pass: false,\n    message: () => 'something went wrong!',\n  }\n}\n\nexpect.extend({ customMatcher })\n```\n\nMatcher function has access to `this` context with the following properties:\n\n## `isNot`\n\nReturns true, if matcher was called on `not` (`expect(received).not.toBeFoo()`). You do not need to respect it, Vitest will reverse the value of `pass` automatically.\n\n## `promise`\n\nIf matcher was called on `resolved/rejected`, this value will contain the name of modifier. Otherwise, it will be an empty string.\n\n## `equals`\n\nThis is a utility function that allows you to compare two values. It will return `true` if values are equal, `false` otherwise. This function is used internally for almost every matcher. It supports objects with asymmetric matchers by default.\n\n## `utils`\n\nThis contains a set of utility functions that you can use to display messages.\n\n`this` context also contains information about the current test. You can also get it by calling `expect.getState()`. The most useful properties are:\n\n## `currentTestName`\n\nFull name of the current test (including describe block).\n\n## `task` <Advanced /> <Version>4.1.0</Version> {#task}\n\nContains a reference to [the `Test` runner task](/api/advanced/runner#tasks) when available.\n\n::: warning\nWhen using the global `expect` with concurrent tests, `this.task` is `undefined`. Use `context.expect` instead to ensure `task` is available in custom matchers.\n:::\n\n## `testPath`\n\nFile path to the current test.\n\n## `environment`\n\nThe name of the current [`environment`](/config/environment) (for example, `jsdom`).\n\n## `soft`\n\nWas assertion called as a [`soft`](/api/expect#soft) one. You don't need to respect it, Vitest will always catch the error.\n\n::: tip\nThese are not all of the available properties, only the most useful ones. The other state values are used by Vitest internally.\n:::\n"
  },
  {
    "path": "docs/guide/features.md",
    "content": "---\ntitle: Features | Guide\noutline: deep\n---\n\n# Features\n\n<script setup>\nimport FeaturesList from '../.vitepress/components/FeaturesList.vue'\n</script>\n\n<FeaturesList class=\"!gap-1 text-lg\" />\n\n<div h-2 />\n<CourseLink href=\"https://vueschool.io/lessons/your-first-test?friend=vueuse\">Learn how to write your first test by Video</CourseLink>\n\n## Shared Config between Test, Dev and Build\n\nVite's config, transformers, resolvers, and plugins. Use the same setup from your app to run the tests.\n\nLearn more at [Configuring Vitest](/guide/#configuring-vitest).\n\n## Watch Mode\n\n```bash\n$ vitest\n```\n\nWhen you modify your source code or the test files, Vitest smartly searches the module graph and only reruns the related tests, just like how HMR works in Vite!\n\n`vitest` starts in `watch mode` **by default in development environment** and `run mode` in CI environment (when `process.env.CI` presents) smartly. You can use `vitest watch` or `vitest run` to explicitly specify the desired mode.\n\nStart Vitest with the `--standalone` flag to keep it running in the background. It won't run any tests until they change. Vitest will not run tests if the source code is changed until the test that imports the source has been run\n\n## Common Web Idioms Out-Of-The-Box\n\nOut-of-the-box ES Module / TypeScript / JSX support / PostCSS\n\n## Threads\n\nBy default Vitest runs test files in [multiple processes](/guide/parallelism) using [`node:child_process`](https://nodejs.org/api/child_process.html), allowing tests to run simultaneously. If you want to speed up your test suite even further, consider enabling `--pool=threads` to run tests using [`node:worker_threads`](https://nodejs.org/api/worker_threads.html) (beware that some packages might not work with this setup).\nTo run tests in a single thread or process, see [`fileParallelism`](/config/fileparallelism).\n\nVitest also isolates each file's environment so env mutations in one file don't affect others. Isolation can be disabled by passing `--no-isolate` to the CLI (trading correctness for run performance).\n\n## Test Filtering\n\nVitest provides many ways to narrow down the tests to run in order to speed up testing so you can focus on development.\n\nLearn more about [Test Filtering](/guide/filtering).\n\n## Running Tests Concurrently\n\nUse `.concurrent` in consecutive tests to start them in parallel.\n\n```ts\nimport { describe, it } from 'vitest'\n\n// The two tests marked with concurrent will be started in parallel\ndescribe('suite', () => {\n  it('serial test', async () => { /* ... */ })\n  it.concurrent('concurrent test 1', async ({ expect }) => { /* ... */ })\n  it.concurrent('concurrent test 2', async ({ expect }) => { /* ... */ })\n})\n```\n\nIf you use `.concurrent` on a suite, every test in it will be started in parallel.\n\n```ts\nimport { describe, it } from 'vitest'\n\n// All tests within this suite will be started in parallel\ndescribe.concurrent('suite', () => {\n  it('concurrent test 1', async ({ expect }) => { /* ... */ })\n  it('concurrent test 2', async ({ expect }) => { /* ... */ })\n  it.concurrent('concurrent test 3', async ({ expect }) => { /* ... */ })\n})\n```\n\nYou can also use `.skip`, `.only`, and `.todo` with concurrent suites and tests. Read more in the [API Reference](/api/test#test-concurrent).\n\n::: warning\nWhen running concurrent tests, Snapshots and Assertions must use `expect` from the local [Test Context](/guide/test-context) to ensure the right test is detected.\n:::\n\n## Snapshot\n\n[Jest-compatible](https://jestjs.io/docs/snapshot-testing) snapshot support.\n\n```ts\nimport { expect, it } from 'vitest'\n\nit('renders correctly', () => {\n  const result = render()\n  expect(result).toMatchSnapshot()\n})\n```\n\nLearn more at [Snapshot](/guide/snapshot).\n\n## Chai and Jest `expect` Compatibility\n\n[Chai](https://www.chaijs.com/) is built-in for assertions with [Jest `expect`](https://jestjs.io/docs/expect)-compatible APIs.\n\nNotice that if you are using third-party libraries that add matchers, setting [`test.globals`](/config/globals) to `true` will provide better compatibility.\n\n## Mocking\n\n[Tinyspy](https://github.com/tinylibs/tinyspy) is built-in for mocking with `jest`-compatible APIs on `vi` object.\n\n```ts\nimport { expect, vi } from 'vitest'\n\nconst fn = vi.fn()\n\nfn('hello', 1)\n\nexpect(vi.isMockFunction(fn)).toBe(true)\nexpect(fn.mock.calls[0]).toEqual(['hello', 1])\n\nfn.mockImplementation((arg: string) => arg)\n\nfn('world', 2)\n\nexpect(fn.mock.results[1].value).toBe('world')\n```\n\nVitest supports both [happy-dom](https://github.com/capricorn86/happy-dom) or [jsdom](https://github.com/jsdom/jsdom) for mocking DOM and browser APIs. They don't come with Vitest, you will need to install them separately:\n\n::: code-group\n```bash [happy-dom]\n$ npm i -D happy-dom\n```\n```bash [jsdom]\n$ npm i -D jsdom\n```\n:::\n\nAfter that, change the `environment` option in your config file:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    environment: 'happy-dom', // or 'jsdom', 'node'\n  },\n})\n```\n\nLearn more at [Mocking](/guide/mocking).\n\n## Coverage\n\nVitest supports Native code coverage via [`v8`](https://v8.dev/blog/javascript-code-coverage) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/).\n\n```json [package.json]\n{\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"coverage\": \"vitest run --coverage\"\n  }\n}\n```\n\nLearn more at [Coverage](/guide/coverage).\n\n## In-Source Testing\n\nVitest also provides a way to run tests within your source code along with the implementation, similar to [Rust's module tests](https://doc.rust-lang.org/book/ch11-03-test-organization.html#the-tests-module-and-cfgtest).\n\nThis makes the tests share the same closure as the implementations and able to test against private states without exporting. Meanwhile, it also brings the feedback loop closer for development.\n\n```ts [src/index.ts]\n// the implementation\nexport function add(...args: number[]): number {\n  return args.reduce((a, b) => a + b, 0)\n}\n\n// in-source test suites\nif (import.meta.vitest) {\n  const { it, expect } = import.meta.vitest\n  it('add', () => {\n    expect(add()).toBe(0)\n    expect(add(1)).toBe(1)\n    expect(add(1, 2, 3)).toBe(6)\n  })\n}\n```\n\nLearn more at [In-source testing](/guide/in-source).\n\n## Benchmarking <Badge type=\"warning\">Experimental</Badge> {#benchmarking}\n\nYou can run benchmark tests with [`bench`](/api/test#bench) function via [Tinybench](https://github.com/tinylibs/tinybench) to compare performance results.\n\n```ts [sort.bench.ts]\nimport { bench, describe } from 'vitest'\n\ndescribe('sort', () => {\n  bench('normal', () => {\n    const x = [1, 5, 4, 2, 3]\n    x.sort((a, b) => {\n      return a - b\n    })\n  })\n\n  bench('reverse', () => {\n    const x = [1, 5, 4, 2, 3]\n    x.reverse().sort((a, b) => {\n      return a - b\n    })\n  })\n})\n```\n\n<img alt=\"Benchmark report\" img-dark src=\"https://github.com/vitest-dev/vitest/assets/4232207/6f0383ea-38ba-4f14-8a05-ab243afea01d\">\n<img alt=\"Benchmark report\" img-light src=\"https://github.com/vitest-dev/vitest/assets/4232207/efbcb427-ecf1-4882-88de-210cd73415f6\">\n\n## Type Testing <Badge type=\"warning\">Experimental</Badge> {#type-testing}\n\nYou can [write tests](/guide/testing-types) to catch type regressions. Vitest comes with [`expect-type`](https://github.com/mmkal/expect-type) package to provide you with a similar and easy to understand API.\n\n```ts [types.test-d.ts]\nimport { assertType, expectTypeOf, test } from 'vitest'\nimport { mount } from './mount.js'\n\ntest('my types work properly', () => {\n  expectTypeOf(mount).toBeFunction()\n  expectTypeOf(mount).parameter(0).toExtend<{ name: string }>()\n\n  // @ts-expect-error name is a string\n  assertType(mount({ name: 42 }))\n})\n```\n\n## Sharding\n\nRun tests on different machines using [`--shard`](/guide/cli#shard) and [`--reporter=blob`](/guide/reporters#blob-reporter) flags.\nAll test and coverage results can be merged at the end of your CI pipeline using `--merge-reports` command:\n\n```bash\nvitest --shard=1/2 --reporter=blob --coverage\nvitest --shard=2/2 --reporter=blob --coverage\nvitest --merge-reports --reporter=junit --coverage\n```\n\nSee [`Improving Performance | Sharding`](/guide/improving-performance#sharding) for more information.\n\n## Environment Variables\n\nVitest exclusively autoloads environment variables prefixed with `VITE_` from `.env` files to maintain compatibility with frontend-related tests, adhering to [Vite's established convention](https://vitejs.dev/guide/env-and-mode.html#env-files). To load every environmental variable from `.env` files anyway, you can use `loadEnv` method imported from `vite`:\n\n```ts [vitest.config.ts]\nimport { loadEnv } from 'vite'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig(({ mode }) => ({\n  test: {\n    // mode defines what \".env.{mode}\" file to choose if exists\n    env: loadEnv(mode, process.cwd(), ''),\n  },\n}))\n```\n\n## Unhandled Errors\n\nBy default, Vitest catches and reports all [unhandled rejections](https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event), [uncaught exceptions](https://nodejs.org/api/process.html#event-uncaughtexception) (in Node.js) and [error](https://developer.mozilla.org/en-US/docs/Web/API/Window/error_event) events (in the [browser](/guide/browser/)).\n\nYou can disable this behaviour by catching them manually. Vitest assumes the callback is handled by you and won't report the error.\n\n::: code-group\n```ts [setup.node.js]\n// in Node.js\nprocess.on('unhandledRejection', () => {\n  // your own handler\n})\n\nprocess.on('uncaughtException', () => {\n  // your own handler\n})\n```\n```ts [setup.browser.js]\n// in the browser\nwindow.addEventListener('error', () => {\n  // your own handler\n})\n\nwindow.addEventListener('unhandledrejection', () => {\n  // your own handler\n})\n```\n:::\n\nAlternatively, you can also ignore reported errors with a [`dangerouslyIgnoreUnhandledErrors`](/config/dangerouslyignoreunhandlederrors) option. Vitest will still report them, but they won't affect the test result (exit code won't be changed).\n\nIf you need to test that error was not caught, you can create a test that looks like this:\n\n```ts\ntest('my function throws uncaught error', async ({ onTestFinished }) => {\n  const unhandledRejectionListener = vi.fn()\n  process.on('unhandledRejection', unhandledRejectionListener)\n  onTestFinished(() => {\n    process.off('unhandledRejection', unhandledRejectionListener)\n  })\n\n  callMyFunctionThatRejectsError()\n\n  await expect.poll(unhandledRejectionListener).toHaveBeenCalled()\n})\n```\n"
  },
  {
    "path": "docs/guide/filtering.md",
    "content": "---\ntitle: Test Filtering | Guide\n---\n\n# Test Filtering\n\nFiltering, timeouts, concurrent for suite and tests\n\n## CLI\n\nYou can use CLI to filter test files by name:\n\n```bash\n$ vitest basic\n```\n\nWill only execute test files that contain `basic`, e.g.\n\n```\nbasic.test.ts\nbasic-foo.test.ts\nbasic/foo.test.ts\n```\n\nYou can also use the `-t, --testNamePattern <pattern>` option to filter tests by full name. This can be helpful when you want to filter by the name defined within a file rather than the filename itself.\n\nSince Vitest 3, you can also specify the test by filename and line number:\n\n```bash\n$ vitest basic/foo.test.ts:10\n```\n\n::: warning\nNote that Vitest requires the full filename for this feature to work. It can be relative to the current working directory or an absolute file path.\n\n```bash\n$ vitest basic/foo.js:10 # ✅\n$ vitest ./basic/foo.js:10 # ✅\n$ vitest /users/project/basic/foo.js:10 # ✅\n$ vitest foo:10 # ❌\n$ vitest ./basic/foo:10 # ❌\n```\n\nAt the moment Vitest also doesn't support ranges:\n\n```bash\n$ vitest basic/foo.test.ts:10, basic/foo.test.ts:25 # ✅\n$ vitest basic/foo.test.ts:10-25 # ❌\n```\n:::\n\n## Specifying a Timeout\n\nYou can optionally pass a timeout in milliseconds as a third argument to tests. The default is [5 seconds](/config/testtimeout).\n\n```ts\nimport { test } from 'vitest'\n\ntest('name', async () => { /* ... */ }, 1000)\n```\n\nHooks also can receive a timeout, with the same 5 seconds default.\n\n```ts\nimport { beforeAll } from 'vitest'\n\nbeforeAll(async () => { /* ... */ }, 1000)\n```\n\n## Skipping Suites and Tests\n\nUse `.skip` to avoid running certain suites or tests\n\n```ts\nimport { assert, describe, it } from 'vitest'\n\ndescribe.skip('skipped suite', () => {\n  it('test', () => {\n    // Suite skipped, no error\n    assert.equal(Math.sqrt(4), 3)\n  })\n})\n\ndescribe('suite', () => {\n  it.skip('skipped test', () => {\n    // Test skipped, no error\n    assert.equal(Math.sqrt(4), 3)\n  })\n})\n```\n\n## Filtering Tags\n\nIf your test defines a [tag](/guide/test-tags), you can filter your tests with a `--tags-filter` option:\n\n```ts\ntest('renders a form', { tags: ['frontend'] }, () => {\n  // ...\n})\n\ntest('calls an external API', { tags: ['backend'] }, () => {\n  // ...\n})\n```\n\n```shell\nvitest --tags-filter=frontend\n```\n\n## Selecting Suites and Tests to Run\n\nUse `.only` to only run certain suites or tests\n\n```ts\nimport { assert, describe, it } from 'vitest'\n\n// Only this suite (and others marked with only) are run\ndescribe.only('suite', () => {\n  it('test', () => {\n    assert.equal(Math.sqrt(4), 3)\n  })\n})\n\ndescribe('another suite', () => {\n  it('skipped test', () => {\n    // Test skipped, as tests are running in Only mode\n    assert.equal(Math.sqrt(4), 3)\n  })\n\n  it.only('test', () => {\n    // Only this test (and others marked with only) are run\n    assert.equal(Math.sqrt(4), 2)\n  })\n})\n```\n\nRun Vitest with a file filter and a line number:\n\n```shell\nvitest ./test/example.test.ts:5\n```\n\n```ts:line-numbers\nimport { assert, describe, it } from 'vitest'\n\ndescribe('suite', () => {\n  // Run only this test\n  it('test', () => {\n    assert.equal(Math.sqrt(4), 3)\n  })\n})\n```\n\n## Unimplemented Suites and Tests\n\nUse `.todo` to stub suites and tests that should be implemented\n\n```ts\nimport { describe, it } from 'vitest'\n\n// An entry will be shown in the report for this suite\ndescribe.todo('unimplemented suite')\n\n// An entry will be shown in the report for this test\ndescribe('suite', () => {\n  it.todo('unimplemented test')\n})\n```\n"
  },
  {
    "path": "docs/guide/ide.md",
    "content": "---\ntitle: IDE Integrations | Guide\n---\n\n<script setup>\nimport { useData } from 'vitepress'\nconst { isDark } = useData()\n</script>\n\n# IDE Integrations\n\n## VS Code <Badge>Official</Badge> {#vs-code}\n\n<p text-center>\n<img :src=\"`https://raw.githubusercontent.com/vitest-dev/vscode/main/img/cover-${isDark ? 'light' : 'dark' }.png`\" w-60 alt=\"vscode logo\">\n</p>\n\n[GitHub](https://github.com/vitest-dev/vscode) | [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=vitest.explorer)\n\n![A gif of vscode extension in vscode](https://i.ibb.co/bJCbCf2/202203292020.gif)\n\n## JetBrains IDE\n\nWebStorm, PhpStorm, IntelliJ IDEA Ultimate, and other JetBrains IDEs come with built-in support for Vitest.\n\n<p text-center>\n<img :src=\"`/ide/vitest-jb-${isDark ? 'light' : 'dark'}.png`\" w-60 alt=\"webstorm logo\">\n</p>\n\n[WebStorm Help](https://www.jetbrains.com/help/webstorm/vitest.html) | [IntelliJ IDEA Ultimate Help](https://www.jetbrains.com/help/idea/vitest.html) | [PhpStorm Help](https://www.jetbrains.com/help/phpstorm/vitest.html)\n\n![Vitest WebStorm Demo](https://raw.githubusercontent.com/kricact/WS-info/main/gifs/vitest-run-all.gif)\n\n## Wallaby.js <Badge>Paid (free for OSS)</Badge>\n\nCreated by [The Wallaby Team](https://wallabyjs.com)\n\n[Wallaby.js](https://wallabyjs.com) runs your Vitest tests immediately as you type, highlighting results in your IDE right next to your code.\n\n<p text-left>\n  <img :src=\"`/ide/vitest-wallaby-${isDark ? 'light' : 'dark'}.png`\" alt=\"Vitest + Wallaby logos\" w-142>\n</p>\n\n[VS Code](https://marketplace.visualstudio.com/items?itemName=WallabyJs.wallaby-vscode) | [JetBrains](https://plugins.jetbrains.com/plugin/15742-wallaby) |\n[Visual Studio](https://marketplace.visualstudio.com/items?itemName=vs-publisher-999439.WallabyjsforVisualStudio2022) | [Sublime Text](https://packagecontrol.io/packages/Wallaby)\n\n![Wallaby VS Code Demo](https://wallabyjs.com/assets/img/vitest_demo.gif)\n"
  },
  {
    "path": "docs/guide/improving-performance.md",
    "content": "# Improving Performance\n\n## Test Isolation\n\nBy default Vitest runs every test file in an isolated environment based on the [pool](/config/pool):\n\n- `threads` pool runs every test file in a separate [`Worker`](https://nodejs.org/api/worker_threads.html#class-worker)\n- `forks` pool runs every test file in a separate [forked child process](https://nodejs.org/api/child_process.html#child_processforkmodulepath-args-options)\n- `vmThreads` pool runs every test file in a separate [VM context](https://nodejs.org/api/vm.html#vmcreatecontextcontextobject-options), but it uses workers for parallelism\n\nThis greatly increases test times, which might not be desirable for projects that don't rely on side effects and properly cleanup their state (which is usually true for projects with `node` environment). In this case disabling isolation will improve the speed of your tests. To do that, you can provide `--no-isolate` flag to the CLI or set [`test.isolate`](/config/isolate) property in the config to `false`.\n\n::: code-group\n```bash [CLI]\nvitest --no-isolate\n```\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    isolate: false,\n  },\n})\n```\n:::\n\nYou can also disable isolation for specific files only by using `projects`:\n\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: 'Isolated',\n          isolate: true, // (default value)\n          exclude: ['**.non-isolated.test.ts'],\n        },\n      },\n      {\n        test: {\n          name: 'Non-isolated',\n          isolate: false,\n          include: ['**.non-isolated.test.ts'],\n        },\n      },\n    ],\n  },\n})\n```\n\n:::tip\nIf you are using `vmThreads` pool, you cannot disable isolation. Use `threads` pool instead to improve your tests performance.\n:::\n\nFor some projects, it might also be desirable to disable parallelism to improve startup time. To do that, provide `--no-file-parallelism` flag to the CLI or set [`test.fileParallelism`](/config/fileparallelism) property in the config to `false`.\n\n::: code-group\n```bash [CLI]\nvitest --no-file-parallelism\n```\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    fileParallelism: false,\n  },\n})\n```\n:::\n\n## Limiting Directory Search\n\nYou can limit the working directory when Vitest searches for files using [`test.dir`](/config/dir) option. This should make the search faster if you have unrelated folders and files in the root directory.\n\n## Caching Between Reruns\n\nIn watch mode, Vitest caches all transformed files in memory, which makes reruns fast. However, this cache is discarded once the test run finishes. By enabling [`experimental.fsModuleCache`](/config/experimental#experimental-fsmodulecache), Vitest persists this cache to the file system so it can be reused across reruns.\n\nThis improvement is most noticeable when rerunning a small number of tests that depend on a large module graph. For full test suites, parallelization already mitigates the cost because other tests populate the in-memory cache while earlier tests are still running. For example, running one test file with a huge module graph (>900 modules):\n\n```shell\n# the first run\nDuration  8.75s (transform 4.02s, setup 629ms, import 5.52s, tests 2.52s, environment 0ms, prepare 3ms)\n\n# the second run\nDuration  5.90s (transform 842ms, setup 543ms, import 2.35s, tests 2.94s, environment 0ms, prepare 3ms)\n```\n\n## Pool\n\nBy default Vitest runs tests in `pool: 'forks'`. While `'forks'` pool is better for compatibility issues ([hanging process](/guide/common-errors.html#failed-to-terminate-worker) and [segfaults](/guide/common-errors.html#segfaults-and-native-code-errors)), it may be slightly slower than `pool: 'threads'` in larger projects.\n\nYou can try to improve test run time by switching `pool` option in configuration:\n\n::: code-group\n```bash [CLI]\nvitest --pool=threads\n```\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    pool: 'threads',\n  },\n})\n```\n:::\n\n## Sharding\n\nTest sharding is a process of splitting your test suite into groups, or shards. This can be useful when you have a large test suite and multiple machines that could run subsets of that suite simultaneously.\n\nTo split Vitest tests on multiple different runs, use [`--shard`](/guide/cli#shard) option with [`--reporter=blob`](/guide/reporters#blob-reporter) option:\n\n```sh\nvitest run --reporter=blob --shard=1/3 # 1st machine\nvitest run --reporter=blob --shard=2/3 # 2nd machine\nvitest run --reporter=blob --shard=3/3 # 3rd machine\n```\n\n> Vitest splits your _test files_, not your test cases, into shards. If you've got 1000 test files, the `--shard=1/4` option will run 250 test files, no matter how many test cases individual files have.\n\nCollect the results stored in `.vitest-reports` directory from each machine and merge them with [`--merge-reports`](/guide/cli#merge-reports) option:\n\n```sh\nvitest run --merge-reports\n```\n\n::: details GitHub Actions example\nThis setup is also used at https://github.com/vitest-tests/test-sharding.\n\n```yaml\n# Inspired from https://playwright.dev/docs/test-sharding\nname: Tests\non:\n  push:\n    branches:\n      - main\njobs:\n  tests:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        shardIndex: [1, 2, 3, 4]\n        shardTotal: [4]\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0\n\n      - name: Install dependencies\n        run: pnpm i\n\n      - name: Run tests\n        run: pnpm run test --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}\n\n      - name: Upload blob report to GitHub Actions Artifacts\n        if: ${{ !cancelled() }}\n        uses: actions/upload-artifact@v4\n        with:\n          name: blob-report-${{ matrix.shardIndex }}\n          path: .vitest-reports/*\n          include-hidden-files: true\n          retention-days: 1\n\n      - name: Upload attachments to GitHub Actions Artifacts\n        if: ${{ !cancelled() }}\n        uses: actions/upload-artifact@v4\n        with:\n          name: blob-attachments-${{ matrix.shardIndex }}\n          path: .vitest-attachments/**\n          include-hidden-files: true\n          retention-days: 1\n\n  merge-reports:\n    if: ${{ !cancelled() }}\n    needs: [tests]\n\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0\n\n      - name: Install dependencies\n        run: pnpm i\n\n      - name: Download blob reports from GitHub Actions Artifacts\n        uses: actions/download-artifact@v4\n        with:\n          path: .vitest-reports\n          pattern: blob-report-*\n          merge-multiple: true\n\n      - name: Download attachments from GitHub Actions Artifacts\n        uses: actions/download-artifact@v4\n        with:\n          path: .vitest-attachments\n          pattern: blob-attachments-*\n          merge-multiple: true\n\n      - name: Merge reports\n        run: npx vitest --merge-reports\n```\n\nIf your tests create file-based attachments (for example via `context.annotate` or custom artifacts), upload and restore [`attachmentsDir`](/config/attachmentsdir) in the merge job as shown above.\n\n:::\n\n:::tip\nTest sharding can also become useful on high CPU-count machines.\n\nVitest will run only a single Vite server in its main thread. Rest of the threads are used to run test files.\nIn a high CPU-count machine the main thread can become a bottleneck as it cannot handle all the requests coming from the threads. For example in 32 CPU machine the main thread is responsible to handle load coming from 31 test threads.\n\nTo reduce the load from main thread's Vite server you can use test sharding. The load can be balanced on multiple Vite server.\n\n```sh\n# Example for splitting tests on 32 CPU to 4 shards.\n# As each process needs 1 main thread, there's 7 threads for test runners (1+7)*4 = 32\n# Use VITEST_MAX_WORKERS:\nVITEST_MAX_WORKERS=7 vitest run --reporter=blob --shard=1/4 & \\\nVITEST_MAX_WORKERS=7 vitest run --reporter=blob --shard=2/4 & \\\nVITEST_MAX_WORKERS=7 vitest run --reporter=blob --shard=3/4 & \\\nVITEST_MAX_WORKERS=7 vitest run --reporter=blob --shard=4/4 & \\\nwait # https://man7.org/linux/man-pages/man2/waitpid.2.html\n\nvitest run --merge-reports\n```\n\n:::\n"
  },
  {
    "path": "docs/guide/in-source.md",
    "content": "---\ntitle: In-Source Testing | Guide\n---\n\n# In-Source Testing\n\nVitest provides a way to run tests within your source code along side the implementation, similar to [Rust's module tests](https://doc.rust-lang.org/book/ch11-03-test-organization.html#the-tests-module-and-cfgtest).\n\nThis makes the tests share the same closure as the implementations and able to test against private states without exporting. Meanwhile, it also brings a closer feedback loop for development.\n\n::: warning\nThis guide explains how to write tests inside your source code. If you need to write tests in separate test files, follow the [\"Writing Tests\" guide](/guide/#writing-tests).\n:::\n\n## Setup\n\nTo get started, put a `if (import.meta.vitest)` block at the end of your source file and write some tests inside it. For example:\n\n```ts [src/index.ts]\n// the implementation\nexport function add(...args: number[]) {\n  return args.reduce((a, b) => a + b, 0)\n}\n\n// in-source test suites\nif (import.meta.vitest) {\n  const { it, expect } = import.meta.vitest\n  it('add', () => {\n    expect(add()).toBe(0)\n    expect(add(1)).toBe(1)\n    expect(add(1, 2, 3)).toBe(6)\n  })\n}\n```\n\nUpdate the `includeSource` config for Vitest to grab the files under `src/`:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    includeSource: ['src/**/*.{js,ts}'], // [!code ++]\n  },\n})\n```\n\nThen you can start to test!\n\n```bash\n$ npx vitest\n```\n\n## Production Build\n\nFor the production build, you will need to set the `define` options in your config file, letting the bundler do the dead code elimination. For example, in Vite\n\n```ts [vite.config.ts]\n/// <reference types=\"vitest/config\" />\n\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    includeSource: ['src/**/*.{js,ts}'],\n  },\n  define: { // [!code ++]\n    'import.meta.vitest': 'undefined', // [!code ++]\n  }, // [!code ++]\n})\n```\n\n### Other Bundlers\n\n::: details Rolldown\n```js [rolldown.config.js]\nimport { defineConfig } from 'rolldown/config'\n\nexport default defineConfig({\n  transform: {\n    define: { // [!code ++]\n      'import.meta.vitest': 'undefined', // [!code ++]\n    }, // [!code ++]\n  },\n})\n```\n\nLearn more: [Rolldown](https://rolldown.rs/)\n:::\n\n::: details Rollup\n```js [rollup.config.js]\nimport replace from '@rollup/plugin-replace' // [!code ++]\n\nexport default {\n  plugins: [\n    replace({ // [!code ++]\n      'import.meta.vitest': 'undefined', // [!code ++]\n    }) // [!code ++]\n  ],\n  // other options\n}\n```\n\nLearn more: [Rollup](https://rollupjs.org/)\n:::\n\n::: details unbuild\n```js [build.config.js]\nimport { defineBuildConfig } from 'unbuild'\n\nexport default defineBuildConfig({\n  replace: { // [!code ++]\n    'import.meta.vitest': 'undefined', // [!code ++]\n  }, // [!code ++]\n  // other options\n})\n```\n\nLearn more: [unbuild](https://github.com/unjs/unbuild)\n:::\n\n::: details webpack\n```js [webpack.config.js]\nconst webpack = require('webpack')\n\nmodule.exports = {\n  plugins: [\n    new webpack.DefinePlugin({ // [!code ++]\n      'import.meta.vitest': 'undefined', // [!code ++]\n    })// [!code ++]\n  ],\n}\n```\n\nLearn more: [webpack](https://webpack.js.org/plugins/define-plugin/)\n:::\n\n## TypeScript\n\nTo get TypeScript support for `import.meta.vitest`, add `vitest/importMeta` to your `tsconfig.json`:\n\n```json [tsconfig.json]\n{\n  \"compilerOptions\": {\n    \"types\": [\n      \"vitest/importMeta\" // [!code ++]\n    ]\n  }\n}\n```\n\nReference to [`examples/in-source-test`](https://github.com/vitest-dev/vitest/tree/main/examples/in-source-test) for the full example.\n\n## Notes\n\nThis feature could be useful for:\n\n- Unit testing for small-scoped functions or utilities\n- Prototyping\n- Inline Assertion\n\nIt's recommended to **use separate test files instead** for more complex tests like components or E2E testing.\n"
  },
  {
    "path": "docs/guide/index.md",
    "content": "---\ntitle: Getting Started | Guide\n---\n\n# Getting Started\n\n## Overview\n\nVitest (pronounced as _\"veetest\"_) is a next generation testing framework\npowered by\nVite.\n\nYou can learn more about the rationale behind the project in the [Why Vitest](/guide/why) section.\n\n## Trying Vitest Online\n\nYou can try Vitest online on [StackBlitz](https://vitest.new). It runs Vitest directly in the browser, and it is almost identical to the local setup but doesn't require installing anything on your machine.\n\n## Adding Vitest to Your Project\n\n<CourseLink href=\"https://vueschool.io/lessons/how-to-install-vitest?friend=vueuse\">Learn how to install by Video</CourseLink>\n\n::: code-group\n```bash [npm]\nnpm install -D vitest\n```\n```bash [yarn]\nyarn add -D vitest\n```\n```bash [pnpm]\npnpm add -D vitest\n```\n```bash [bun]\nbun add -D vitest\n```\n:::\n\n:::tip\nVitest requires Vite >=v6.0.0 and Node >=v20.0.0\n:::\n\nIt is recommended that you install a copy of `vitest` in your `package.json`, using one of the methods listed above. However, if you would prefer to run `vitest` directly, you can use `npx vitest` (the `npx` tool comes with npm and Node.js).\n\nThe `npx` tool will execute the specified command. By default, `npx` will first check if the command exists in the local project's binaries. If it is not found there, `npx` will look in the system's `$PATH` and execute it if found. If the command is not found in either location, `npx` will install it in a temporary location prior to execution.\n\n## Writing Tests\n\nAs an example, we will write a simple test that verifies the output of a function that adds two numbers.\n\n``` js [sum.js]\nexport function sum(a, b) {\n  return a + b\n}\n```\n\n``` js [sum.test.js]\nimport { expect, test } from 'vitest'\nimport { sum } from './sum.js'\n\ntest('adds 1 + 2 to equal 3', () => {\n  expect(sum(1, 2)).toBe(3)\n})\n```\n\n::: tip\nBy default, tests must contain `.test.` or `.spec.` in their file name.\n:::\n\nNext, in order to execute the test, add the following section to your `package.json`:\n\n```json [package.json]\n{\n  \"scripts\": {\n    \"test\": \"vitest\"\n  }\n}\n```\n\nFinally, run `npm run test`, `yarn test` or `pnpm test`, depending on your package manager, and Vitest will print this message:\n\n```txt\n✓ sum.test.js (1)\n  ✓ adds 1 + 2 to equal 3\n\nTest Files  1 passed (1)\n     Tests  1 passed (1)\n  Start at  02:15:44\n  Duration  311ms\n```\n\n::: warning\nIf you are using Bun as your package manager, make sure to use `bun run test` command instead of `bun test`, otherwise Bun will run its own test runner.\n:::\n\nLearn more about the usage of Vitest, see the [API](/api/test) section.\n\n## Configuring Vitest\n\nOne of the main advantages of Vitest is its unified configuration with Vite. If present, `vitest` will read your root `vite.config.ts` to match with the plugins and setup as your Vite app. For example, your Vite [resolve.alias](https://vitejs.dev/config/shared-options.html#resolve-alias) and [plugins](https://vitejs.dev/guide/using-plugins.html) configuration will work out-of-the-box. If you want a different configuration during testing, you can:\n\n- Create `vitest.config.ts`, which will have the higher priority\n- Pass `--config` option to CLI, e.g. `vitest --config ./path/to/vitest.config.ts`\n- Use `process.env.VITEST` or `mode` property on `defineConfig` (will be set to `test` if not overridden) to conditionally apply different configuration in `vite.config.ts`. Note that like any other environment variable, `VITEST` is also exposed on `import.meta.env` in your tests\n\nVitest supports the same extensions for your configuration file as Vite does: `.js`, `.mjs`, `.cjs`, `.ts`, `.cts`, `.mts`. Vitest does not support `.json` extension.\n\nIf you are not using Vite as your build tool, you can configure Vitest using the `test` property in your config file:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    // ...\n  },\n})\n```\n\n::: tip\nEven if you do not use Vite yourself, Vitest relies heavily on it for its transformation pipeline. For that reason, you can also configure any property described in [Vite documentation](https://vitejs.dev/config/).\n:::\n\nIf you are already using Vite, add `test` property in your Vite config. You'll also need to add a reference to Vitest types using a [triple slash directive](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-) at the top of your config file.\n\n```ts [vite.config.ts]\n/// <reference types=\"vitest/config\" />\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    // ...\n  },\n})\n```\n\nSee the list of config options in the [Config Reference](../config/)\n\n::: warning\nIf you decide to have two separate config files for Vite and Vitest, make sure to define the same Vite options in your Vitest config file since it will override your Vite file, not extend it. You can also use `mergeConfig` method from `vite` or `vitest/config` entries to merge Vite config with Vitest config:\n\n:::code-group\n```ts [vitest.config.mjs]\nimport { defineConfig, mergeConfig } from 'vitest/config'\nimport viteConfig from './vite.config.mjs'\n\nexport default mergeConfig(viteConfig, defineConfig({\n  test: {\n    // ...\n  },\n}))\n```\n\n```ts [vite.config.mjs]\nimport { defineConfig } from 'vite'\nimport Vue from '@vitejs/plugin-vue'\n\nexport default defineConfig({\n  plugins: [Vue()],\n})\n```\n\nHowever, we recommend using the same file for both Vite and Vitest, instead of creating two separate files.\n:::\n\n## Projects Support\n\nRun different project configurations inside the same project with [Test Projects](/guide/projects). You can define a list of files and folders that define your projects in `vitest.config` file.\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      // you can use a list of glob patterns to define your projects\n      // Vitest expects a list of config files\n      // or directories where there is a config file\n      'packages/*',\n      'tests/*/vitest.config.{e2e,unit}.ts',\n      // you can even run the same tests,\n      // but with different configs in the same \"vitest\" process\n      {\n        test: {\n          name: 'happy-dom',\n          root: './shared_tests',\n          environment: 'happy-dom',\n          setupFiles: ['./setup.happy-dom.ts'],\n        },\n      },\n      {\n        test: {\n          name: 'node',\n          root: './shared_tests',\n          environment: 'node',\n          setupFiles: ['./setup.node.ts'],\n        },\n      },\n    ],\n  },\n})\n```\n\n## Command Line Interface\n\nIn a project where Vitest is installed, you can use the `vitest` binary in your npm scripts, or run it directly with `npx vitest`. Here are the default npm scripts in a scaffolded Vitest project:\n\n<!-- prettier-ignore -->\n```json [package.json]\n{\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"coverage\": \"vitest run --coverage\"\n  }\n}\n```\n\nTo run tests once without watching for file changes, use `vitest run`.\nYou can specify additional CLI options like `--port` or `--https`. For a full list of CLI options, run `npx vitest --help` in your project.\n\nLearn more about the [Command Line Interface](/guide/cli)\n\n## Automatic Dependency Installation\n\nVitest will prompt you to install certain dependencies if they are not already installed. You can disable this behavior by setting the `VITEST_SKIP_INSTALL_CHECKS=1` environment variable.\n\n## IDE Integrations\n\nWe also provided an official extension for Visual Studio Code to enhance your testing experience with Vitest.\n\n[Install from VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=vitest.explorer)\n\nLearn more about [IDE Integrations](/guide/ide)\n\n## Examples\n\n| Example | Source | Playground |\n|---|---|---|\n| `basic` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/basic) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/basic?initialPath=__vitest__/) |\n| `fastify` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/fastify) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/fastify?initialPath=__vitest__/) |\n| `in-source-test` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/in-source-test) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/in-source-test?initialPath=__vitest__/) |\n| `lit` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/lit) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/lit?initialPath=__vitest__/) |\n| `vue` | [GitHub](https://github.com/vitest-tests/browser-examples/tree/main/examples/vue) | [Play Online](https://stackblitz.com/fork/github/vitest-tests/browser-examples/tree/main/examples/vue?initialPath=__vitest__/) |\n| `marko` | [GitHub](https://github.com/vitest-tests/browser-examples/tree/main/examples/marko) | [Play Online](https://stackblitz.com/fork/github/vitest-tests/browser-examples/tree/main/examples/marko?initialPath=__vitest__/) |\n| `preact` | [GitHub](https://github.com/vitest-tests/browser-examples/tree/main/examples/preact) | [Play Online](https://stackblitz.com/fork/github/vitest-tests/browser-examples/tree/main/examples/preact?initialPath=__vitest__/) |\n| `qwik`| [Github](https://github.com/vitest-tests/browser-examples/tree/main/examples/qwik) | [Play Online](https://stackblitz.com/fork/github/vitest-tests/browser-examples/tree/main/examples/qwik?initialPath=__vitest__/) |\n| `react` | [GitHub](https://github.com/vitest-tests/browser-examples/tree/main/examples/react) | [Play Online](https://stackblitz.com/fork/github/vitest-tests/browser-examples/tree/main/examples/react?initialPath=__vitest__/) |\n| `solid` | [GitHub](https://github.com/vitest-tests/browser-examples/tree/main/examples/solid) | [Play Online](https://stackblitz.com/fork/github/vitest-tests/browser-examples/tree/main/examples/solid?initialPath=__vitest__/) |\n| `svelte` | [GitHub](https://github.com/vitest-tests/browser-examples/tree/main/examples/svelte) | [Play Online](https://stackblitz.com/fork/github/vitest-tests/browser-examples/tree/main/examples/svelte?initialPath=__vitest__/) |\n| `profiling` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/profiling) | Not Available |\n| `typecheck` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/typecheck) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/typecheck?initialPath=__vitest__/) |\n| `projects` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/projects) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/projects?initialPath=__vitest__/) |\n\n## Projects using Vitest\n\n- [unocss](https://github.com/unocss/unocss)\n- [unplugin-auto-import](https://github.com/antfu/unplugin-auto-import)\n- [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)\n- [vue](https://github.com/vuejs/core)\n- [vite](https://github.com/vitejs/vite)\n- [vitesse](https://github.com/antfu/vitesse)\n- [vitesse-lite](https://github.com/antfu/vitesse-lite)\n- [fluent-vue](https://github.com/demivan/fluent-vue)\n- [vueuse](https://github.com/vueuse/vueuse)\n- [milkdown](https://github.com/Saul-Mirone/milkdown)\n- [gridjs-svelte](https://github.com/iamyuu/gridjs-svelte)\n- [spring-easing](https://github.com/okikio/spring-easing)\n- [bytemd](https://github.com/bytedance/bytemd)\n- [faker](https://github.com/faker-js/faker)\n- [million](https://github.com/aidenybai/million)\n- [Vitamin](https://github.com/wtchnm/Vitamin)\n- [neodrag](https://github.com/PuruVJ/neodrag)\n- [svelte-multiselect](https://github.com/janosh/svelte-multiselect)\n- [iconify](https://github.com/iconify/iconify)\n- [tdesign-vue-next](https://github.com/Tencent/tdesign-vue-next)\n- [cz-git](https://github.com/Zhengqbbb/cz-git)\n\n<!--\nFor contributors:\nWe no longer accept new entries to this list a this moment.\nThanks for choosing Vitest!\n-->\n\n## Using Unreleased Commits\n\nEach commit on main branch and a PR with a `cr-tracked` label are published to [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new). You can install it by `npm i https://pkg.pr.new/vitest@{commit}`.\n\nIf you want to test your own modification locally, you can build and link it yourself ([pnpm](https://pnpm.io/) is required):\n\n```bash\ngit clone https://github.com/vitest-dev/vitest.git\ncd vitest\npnpm install\ncd packages/vitest\npnpm run build\npnpm link --global # you can use your preferred package manager for this step\n```\n\nThen go to the project where you are using Vitest and run `pnpm link --global vitest` (or the package manager that you used to link `vitest` globally).\n\n## Community\n\nIf you have questions or need help, reach out to the community at [Discord](https://chat.vitest.dev) and [GitHub Discussions](https://github.com/vitest-dev/vitest/discussions).\n"
  },
  {
    "path": "docs/guide/lifecycle.md",
    "content": "---\ntitle: Test Run Lifecycle | Guide\noutline: deep\n---\n\n# Test Run Lifecycle\n\nUnderstanding the test run lifecycle is essential for writing effective tests, debugging issues, and optimizing your test suite. This guide explains when and in what order different lifecycle phases occur in Vitest, from initialization to teardown.\n\n## Overview\n\nA typical Vitest test run goes through these main phases:\n\n1. **Initialization:** Configuration loading and project setup\n2. **Global Setup:** One-time setup before any tests run\n3. **Worker Creation:** Test workers are spawned based on the [pool](/config/pool) configuration\n4. **Test File Collection:** Test files are discovered and organized\n5. **Test Execution:** Tests run with their hooks and assertions\n6. **Reporting:** Results are collected and reported\n7. **Global Teardown:** Final cleanup after all tests complete\n\nPhases 4–6 run once for each test file, so across your test suite they will execute multiple times and may also run in parallel across different files when you use more than [1 worker](/config/maxworkers).\n\n## Detailed Lifecycle Phases\n\n### 1. Initialization Phase\n\nWhen you run `vitest`, the framework first loads your configuration and prepares the test environment.\n\n**What happens:**\n- [Command-line](/guide/cli) arguments are parsed\n- [Configuration file](/config/) is loaded\n- Project structure is validated\n\nThis phase can run again if the config file or one of its imports changes.\n\n**Scope:** Main process (before any test workers are created)\n\n### 2. Global Setup Phase\n\nIf you have configured [`globalSetup`](/config/globalsetup) files, they run once before any test workers are created.\n\n**What happens:**\n- `setup()` functions (or exported `default` function) from global setup files execute sequentially\n- Multiple global setup files run in the order they are defined\n\n**Scope:** Main process (separate from test workers)\n\n**Important notes:**\n- Global setup runs in a **different global scope** from your tests\n- Tests cannot access variables defined in global setup (use [`provide`/`inject`](/config/provide) instead)\n- Global setup only runs if there is at least one test queued\n\n```ts [globalSetup.ts]\nexport function setup(project) {\n  // Runs once before all tests\n  console.log('Global setup')\n\n  // Share data with tests\n  project.provide('apiUrl', 'http://localhost:3000')\n}\n\nexport function teardown() {\n  // Runs once after all tests\n  console.log('Global teardown')\n}\n```\n\n### 3. Worker Creation Phase\n\nAfter global setup completes, Vitest creates test workers based on your [pool configuration](/config/pool).\n\n**What happens:**\n- Workers are spawned according to the `browser.enabled` or `pool` setting (`threads`, `forks`, `vmThreads`, or `vmForks`)\n- Each worker gets its own isolated environment (unless [isolation](/config/isolate) is disabled)\n- By default, workers are not reused to provide isolation. Workers are reused only if:\n  - [isolation](/config/isolate) is disabled\n  - OR pool is `vmThreads` or `vmForks` because [VM](https://nodejs.org/api/vm.html) provides enough isolation\n\n**Scope:** Worker processes/threads\n\n### 4. Test File Setup Phase\n\nBefore each test file runs, [setup files](/config/setupfiles) are executed.\n\n**What happens:**\n- Setup files run in the same process as your tests\n- By default, setup files run in **parallel** (configurable via [`sequence.setupFiles`](/config/sequence#sequence-setupfiles))\n- Setup files execute before **each test file**\n- Any global _state_ or configuration can be initialized here\n\n**Scope:** Worker process (same as your tests)\n\n**Important notes:**\n- If [isolation](/config/isolate) is disabled, setup files still rerun before each test file to trigger side effects, but imported modules are cached\n- Editing a setup file triggers a rerun of all tests in watch mode\n\n```ts [setupFile.ts]\nimport { afterEach } from 'vitest'\n\n// Runs before each test file\nconsole.log('Setup file executing')\n\n// Register hooks that apply to all tests\nafterEach(() => {\n  cleanup()\n})\n```\n\n### 5. Test Collection and Execution Phase\n\nThis is the main phase where your tests actually run.\n\n#### Test File Execution Order\n\nTest files are executed based on your configuration:\n\n- **Sequential by default** within a worker\n- Files will run in **parallel** across different workers, configured by [`maxWorkers`](/config/maxworkers)\n- Order can be randomized with [`sequence.shuffle`](/config/sequence#sequence-shuffle) or fine-tuned with [`sequence.sequencer`](/config/sequence#sequence-sequencer)\n- Long-running tests typically start earlier (based on cache) unless shuffle is enabled\n\n#### Within Each Test File\n\nThe execution follows this order:\n\n1. **File-level code:** All code outside `describe` blocks runs immediately\n2. **Test collection:** `describe` blocks are processed, and tests are registered as side effects of importing the test file\n3. **[`aroundAll`](/api/hooks#aroundall) hooks:** Wrap around all tests in the suite (must call `runSuite()`)\n4. **[`beforeAll`](/api/hooks#beforeall) hooks:** Run once before any tests in the suite\n5. **For each test:**\n   - [`aroundEach`](/api/hooks#aroundeach) hooks wrap around the test (must call `runTest()`)\n   - `beforeEach` hooks execute (in order defined, or based on [`sequence.hooks`](/config/sequence#sequence-hooks))\n   - Test function executes\n   - `afterEach` hooks execute (reverse order by default with `sequence.hooks: 'stack'`)\n   - [`onTestFinished`](/api/hooks#ontestfinished) callbacks run (always in reverse order)\n   - If test failed: [`onTestFailed`](/api/hooks#ontestfailed) callbacks run\n   - Note: if `repeats` or `retry` are set, all of these steps are executed again\n6. **[`afterAll`](/api/hooks#afterall) hooks:** Run once after all tests in the suite complete\n\n**Example execution flow:**\n\n```ts\n// This runs immediately (collection phase)\nconsole.log('File loaded')\n\ndescribe('User API', () => {\n  // This runs immediately (collection phase)\n  console.log('Suite defined')\n\n  aroundAll(async (runSuite) => {\n    // Wraps around all tests in this suite\n    console.log('aroundAll before')\n    await runSuite()\n    console.log('aroundAll after')\n  })\n\n  beforeAll(() => {\n    // Runs once before all tests in this suite\n    console.log('beforeAll')\n  })\n\n  aroundEach(async (runTest) => {\n    // Wraps around each test\n    console.log('aroundEach before')\n    await runTest()\n    console.log('aroundEach after')\n  })\n\n  beforeEach(() => {\n    // Runs before each test\n    console.log('beforeEach')\n  })\n\n  test('creates user', () => {\n    // Test executes\n    console.log('test 1')\n  })\n\n  test('updates user', () => {\n    // Test executes\n    console.log('test 2')\n  })\n\n  afterEach(() => {\n    // Runs after each test\n    console.log('afterEach')\n  })\n\n  afterAll(() => {\n    // Runs once after all tests in this suite\n    console.log('afterAll')\n  })\n})\n\n// Output:\n// File loaded\n// Suite defined\n// aroundAll before\n//   beforeAll\n//   aroundEach before\n//     beforeEach\n//       test 1\n//     afterEach\n//   aroundEach after\n//   aroundEach before\n//     beforeEach\n//       test 2\n//     afterEach\n//   aroundEach after\n//   afterAll\n// aroundAll after\n```\n\n#### Nested Suites\n\nWhen using nested `describe` blocks, hooks follow a hierarchical pattern. The `aroundAll` and `aroundEach` hooks wrap around their respective scopes, with parent hooks wrapping child hooks:\n\n```ts\ndescribe('outer', () => {\n  aroundAll(async (runSuite) => {\n    console.log('outer aroundAll before')\n    await runSuite()\n    console.log('outer aroundAll after')\n  })\n\n  beforeAll(() => console.log('outer beforeAll'))\n\n  aroundEach(async (runTest) => {\n    console.log('outer aroundEach before')\n    await runTest()\n    console.log('outer aroundEach after')\n  })\n\n  beforeEach(() => console.log('outer beforeEach'))\n\n  test('outer test', () => console.log('outer test'))\n\n  describe('inner', () => {\n    aroundAll(async (runSuite) => {\n      console.log('inner aroundAll before')\n      await runSuite()\n      console.log('inner aroundAll after')\n    })\n\n    beforeAll(() => console.log('inner beforeAll'))\n\n    aroundEach(async (runTest) => {\n      console.log('inner aroundEach before')\n      await runTest()\n      console.log('inner aroundEach after')\n    })\n\n    beforeEach(() => console.log('inner beforeEach'))\n\n    test('inner test', () => console.log('inner test'))\n\n    afterEach(() => console.log('inner afterEach'))\n    afterAll(() => console.log('inner afterAll'))\n  })\n\n  afterEach(() => console.log('outer afterEach'))\n  afterAll(() => console.log('outer afterAll'))\n})\n\n// Output:\n// outer aroundAll before\n//   outer beforeAll\n//   outer aroundEach before\n//     outer beforeEach\n//       outer test\n//     outer afterEach\n//   outer aroundEach after\n//   inner aroundAll before\n//     inner beforeAll\n//     outer aroundEach before\n//       inner aroundEach before\n//         outer beforeEach\n//           inner beforeEach\n//             inner test\n//           inner afterEach\n//         outer afterEach\n//       inner aroundEach after\n//     outer aroundEach after\n//     inner afterAll\n//   inner aroundAll after\n//   outer afterAll\n// outer aroundAll after\n```\n\n#### Concurrent Tests\n\nWhen using `test.concurrent` or [`sequence.concurrent`](/config/sequence#sequence-concurrent):\n\n- Tests within the same file can run in parallel\n- Each concurrent test still runs its own `beforeEach` and `afterEach` hooks\n- Use [test context](/guide/test-context) for concurrent snapshots: `test.concurrent('name', async ({ expect }) => {})`\n\n### 6. Reporting Phase\n\nThroughout the test run, reporters receive lifecycle events and display results.\n\n**What happens:**\n- Reporters receive events as tests progress\n- Results are collected and formatted\n- Test summaries are generated\n- Coverage reports are generated (if enabled)\n\nFor detailed information about the reporter lifecycle, see the [Reporters](/api/advanced/reporters) guide.\n\n### 7. Global Teardown Phase\n\nAfter all tests complete, global teardown functions execute.\n\n**What happens:**\n- `teardown()` functions from [`globalSetup`](/config/globalsetup) files run\n- Multiple teardown functions run in **reverse order** of their setup\n- In watch mode, teardown runs before process exit, not between test reruns\n\n**Scope:** Main process\n\n```ts [globalSetup.ts]\nexport function teardown() {\n  // Clean up global resources\n  console.log('Global teardown complete')\n}\n```\n\n## Lifecycle in Different Scopes\n\nUnderstanding where code executes is crucial for avoiding common pitfalls:\n\n| Phase | Scope | Access to Test Context | Runs |\n|-------|-------|----------------------|------|\n| Config File | Main process | ❌ No | Once per Vitest run |\n| Global Setup | Main process | ❌ No (use `provide`/`inject`) | Once per Vitest run |\n| Setup Files | Worker (same as tests) | ✅ Yes | Before each test file |\n| File-level code | Worker | ✅ Yes | Once per test file |\n| `aroundAll` | Worker | ✅ Yes | Once per suite (wraps all tests) |\n| `beforeAll` / `afterAll` | Worker | ✅ Yes | Once per suite |\n| `aroundEach` | Worker | ✅ Yes | Per test (wraps each test) |\n| `beforeEach` / `afterEach` | Worker | ✅ Yes | Per test |\n| Test function | Worker | ✅ Yes | Once (or more with retries/repeats) |\n| Global Teardown | Main process | ❌ No | Once per Vitest run |\n\n## Watch Mode Lifecycle\n\nIn watch mode, the lifecycle repeats with some differences:\n\n1. **Initial run:** Full lifecycle as described above\n2. **On file change:**\n   - New [test run](/api/advanced/reporters#ontestrunstart) starts\n   - Only affected test files are re-run\n   - [Setup files](/config/setupfiles) run again for those test files\n   - [Global setup](/config/globalsetup) does **not** re-run (use [`project.onTestsRerun`](/config/globalsetup#handling-test-reruns) for rerun-specific logic)\n3. **On exit:**\n   - Global teardown executes\n   - Process terminates\n\n## Performance Considerations\n\nUnderstanding the lifecycle helps optimize test performance:\n\n- **Global setup** is ideal for expensive one-time operations (database seeding, server startup)\n- **Setup files** run before each test file - avoid heavy operations here if you have many test files\n- **`beforeAll`** is better than `beforeEach` for expensive setup that doesn't need isolation\n- **Disabling [isolation](/config/isolate)** improves performance, but setup files still execute before each file\n- **[Pool configuration](/config/pool)** affects parallelization and available APIs\n\nFor tips on how to improve performance, read the [Improving Performance](/guide/improving-performance) guide.\n\n## Related Documentation\n\n- [Global Setup Configuration](/config/globalsetup)\n- [Setup Files Configuration](/config/setupfiles)\n- [Test Sequencing Options](/config/sequence)\n- [Isolation Configuration](/config/isolate)\n- [Pool Configuration](/config/pool)\n- [Extending Reporters](/guide/advanced/reporters) - for reporter lifecycle events\n- [Test API Reference](/api/hooks) - for hook APIs\n"
  },
  {
    "path": "docs/guide/migration.md",
    "content": "---\ntitle: Migration Guide | Guide\noutline: deep\n---\n\n# Migration Guide\n\n[Migrating to Vitest 3.0](https://v3.vitest.dev/guide/migration) | [Migrating to Vitest 2.0](https://v2.vitest.dev/guide/migration)\n\n## Migrating to Vitest 4.0 {#vitest-4}\n\n::: warning Prerequisites\nVitest 4.0 requires **Vite >= 6.0.0** and **Node.js >= 20.0.0**. Before proceeding\nwith any other migration steps, ensure your environment meets these requirements.\nRunning Vitest 4.0 on older versions of Vite or Node.js is not supported and may\nresult in unexpected errors.\n:::\n\n### V8 Code Coverage Major Changes\n\nVitest's V8 code coverage provider is now using more accurate coverage result remapping logic.\nIt is expected for users to see changes in their coverage reports when updating from Vitest v3.\n\nIn the past Vitest used [`v8-to-istanbul`](https://github.com/istanbuljs/v8-to-istanbul) for remapping V8 coverage results into your source files.\nThis method wasn't very accurate and provided plenty of false positives in the coverage reports.\nWe've now developed a new package that utilizes AST based analysis for the V8 coverage.\nThis allows V8 reports to be as accurate as `@vitest/coverage-istanbul` reports.\n\n- Coverage ignore hints have updated. See [Coverage | Ignoring Code](/guide/coverage.html#ignoring-code).\n- `coverage.ignoreEmptyLines` is removed. Lines without runtime code are no longer included in reports.\n- `coverage.experimentalAstAwareRemapping` is removed. This option is now enabled by default, and is the only supported remapping method.\n- `coverage.ignoreClassMethods` is now supported by V8 provider too.\n\n### Removed Options `coverage.all` and `coverage.extensions`\n\nIn previous versions Vitest included all uncovered files in coverage report by default.\nThis was due to `coverage.all` defaulting to `true`, and `coverage.include` defaulting to `**`.\nThese default values were chosen for a good reason - it is impossible for testing tools to guess where users are storing their source files.\n\nThis ended up having Vitest's coverage providers processing unexpected files, like minified Javascript, leading to slow/stuck coverage report generations.\nIn Vitest v4 we have removed `coverage.all` completely and <ins>**defaulted to include only covered files in the report**</ins>.\n\nWhen upgrading to v4 it is recommended to define `coverage.include` in your configuration, and then start applying simple `coverage.exclude` patterns if needed.\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    coverage: {\n      // Include covered and uncovered files matching this pattern:\n      include: ['packages/**/src/**.{js,jsx,ts,tsx}'], // [!code ++]\n\n      // Exclusion is applied for the files that match include pattern above\n      // No need to define root level *.config.ts files or node_modules, as we didn't add those in include\n      exclude: ['**/some-pattern/**'], // [!code ++]\n\n      // These options are removed now\n      all: true, // [!code --]\n      extensions: ['js', 'ts'], // [!code --]\n    }\n  }\n})\n```\n\nIf `coverage.include` is not defined, coverage report will include only files that were loaded during test run:\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    coverage: {\n      // Include not set, include only files that are loaded during test run\n      include: undefined, // [!code ++]\n\n      // Loaded files that match this pattern will be excluded:\n      exclude: ['**/some-pattern/**'], // [!code ++]\n    }\n  }\n})\n```\n\nSee also new guides:\n- [Including and excluding files from coverage report](/guide/coverage.html#including-and-excluding-files-from-coverage-report) for examples\n- [Profiling Test Performance | Code coverage](/guide/profiling-test-performance.html#code-coverage) for tips about debugging coverage generation\n\n### Simplified `exclude`\n\nBy default, Vitest now only excludes tests from `node_modules` and `.git` folders. This means that Vitest no longer excludes:\n\n- `dist` and `cypress` folders\n- `.idea`, `.cache`, `.output`, `.temp` folders\n- config files like `rollup.config.js`, `prettier.config.js`, `ava.config.js` and so on\n\nIf you need to limit the directory where your tests files are located, use the [`test.dir`](/config/dir) option instead because it is more performant than excluding files:\n\n```ts\nimport { configDefaults, defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    dir: './frontend/tests', // [!code ++]\n  },\n})\n```\n\nTo restore the previous behaviour, specify old `excludes` manually:\n\n```ts\nimport { configDefaults, defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    exclude: [\n      ...configDefaults.exclude,\n      '**/dist/**', // [!code ++]\n      '**/cypress/**', // [!code ++]\n      '**/.{idea,git,cache,output,temp}/**', // [!code ++]\n      '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*' // [!code ++]\n    ],\n  },\n})\n```\n\n### `spyOn` and `fn` Support Constructors\n\nPreviously, if you tried to spy on a constructor with `vi.spyOn`, you would get an error like `Constructor <name> requires 'new'`. Since Vitest 4, all mocks called with a `new` keyword construct the instance instead of calling `mock.apply`. This means that the mock implementation has to use either the `function` or the `class` keyword in these cases:\n\n```ts {12-14,16-20}\nconst cart = {\n  Apples: class Apples {\n    getApples() {\n      return 42\n    }\n  }\n}\n\nconst Spy = vi.spyOn(cart, 'Apples')\n  .mockImplementation(() => ({ getApples: () => 0 })) // [!code --]\n  // with a function keyword\n  .mockImplementation(function () {\n    this.getApples = () => 0\n  })\n  // with a custom class\n  .mockImplementation(class MockApples {\n    getApples() {\n      return 0\n    }\n  })\n\nconst mock = new Spy()\n```\n\nNote that now if you provide an arrow function, you will get [`<anonymous> is not a constructor` error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_a_constructor) when the mock is called.\n\n### Changes to Mocking\n\nAlongside new features like supporting constructors, Vitest 4 creates mocks differently to address several module mocking issues that we received over the years. This release attempts to make module spies less confusing, especially when working with classes.\n\n- `vi.fn().getMockName()` now returns `vi.fn()` by default instead of `spy`. This can affect snapshots with mocks - the name will be changed from `[MockFunction spy]` to `[MockFunction]`. Spies created with `vi.spyOn` will keep using the original name by default for better debugging experience\n- `vi.restoreAllMocks` no longer resets the state of spies and only restores spies created manually with `vi.spyOn`, automocks are no longer affected by this function (this also affects the config option [`restoreMocks`](/config/restoremocks)). Note that `.mockRestore` will still reset the mock implementation and clear the state\n- Calling `vi.spyOn` on a mock now returns the same mock\n- `mock.settledResults` are now populated immediately on function invocation with an `'incomplete'` result. When the promise is finished, the type is changed according to the result.\n- Automocked instance methods are now properly isolated, but share a state with the prototype. Overriding the prototype implementation will always affect instance methods unless the methods have a custom mock implementation of their own. Calling `.mockReset` on the mock also no longer breaks that inheritance.\n```ts\nimport { AutoMockedClass } from './example.js'\nconst instance1 = new AutoMockedClass()\nconst instance2 = new AutoMockedClass()\n\ninstance1.method.mockReturnValue(42)\n\nexpect(instance1.method()).toBe(42)\nexpect(instance2.method()).toBe(undefined)\n\nexpect(AutoMockedClass.prototype.method).toHaveBeenCalledTimes(2)\n\ninstance1.method.mockReset()\nAutoMockedClass.prototype.method.mockReturnValue(100)\n\nexpect(instance1.method()).toBe(100)\nexpect(instance2.method()).toBe(100)\n\nexpect(AutoMockedClass.prototype.method).toHaveBeenCalledTimes(4)\n```\n- Automocked methods can no longer be restored, even with a manual `.mockRestore`. Automocked modules with `spy: true` will keep working as before\n- Automocked getters no longer call the original getter. By default, automocked getters now return `undefined`. You can keep using `vi.spyOn(object, name, 'get')` to spy on a getter and change its implementation\n- The mock `vi.fn(implementation).mockReset()` now correctly returns the mock implementation in `.getMockImplementation()`\n- `vi.fn().mock.invocationCallOrder` now starts with `1`, like Jest does, instead of `0`\n\n### Standalone Mode with Filename Filter\n\nTo improve user experience, Vitest will now start running the matched files when [`--standalone`](/guide/cli#standalone) is used with filename filter.\n\n```sh\n# In Vitest v3 and below this command would ignore \"math.test.ts\" filename filter.\n# In Vitest v4 the math.test.ts will run automatically.\n$ vitest --standalone math.test.ts\n```\n\nThis allows users to create re-usable `package.json` scripts for standalone mode.\n\n::: code-group\n```json [package.json]\n{\n  \"scripts\": {\n    \"test:dev\": \"vitest --standalone\"\n  }\n}\n```\n```bash [CLI]\n# Start Vitest in standalone mode, without running any files on start\n$ pnpm run test:dev\n\n# Run math.test.ts immediately\n$ pnpm run test:dev math.test.ts\n```\n:::\n\n### Replacing `vite-node` with [Module Runner](https://vite.dev/guide/api-environment-runtimes.html#modulerunner)\n\nModule Runner is a successor to `vite-node` implemented directly in Vite. Vitest now uses it directly instead of having a wrapper around Vite SSR handler. This means that certain features are no longer available:\n\n- `VITE_NODE_DEPS_MODULE_DIRECTORIES` environment variable was replaced with `VITEST_MODULE_DIRECTORIES`\n- Vitest no longer injects `__vitest_executor` into every [test runner](/api/advanced/runner). Instead, it injects `moduleRunner` which is an instance of [`ModuleRunner`](https://vite.dev/guide/api-environment-runtimes.html#modulerunner)\n- `vitest/execute` entry point was removed. It was always meant to be internal\n- [Custom environments](/guide/environment) no longer need to provide a `transformMode` property. Instead, provide `viteEnvironment`. If it is not provided, Vitest will use the environment name to transform files on the server (see [`server.environments`](https://vite.dev/guide/api-environment-instances.html))\n- `vite-node` is no longer a dependency of Vitest\n- `deps.optimizer.web` was renamed to [`deps.optimizer.client`](/config/deps#deps-client). You can also use any custom names to apply optimizer configs when using other server environments\n\nVite has its own externalization mechanism, but we decided to keep using the old one to reduce the amount of breaking changes. You can keep using [`server.deps`](/config/server#deps) to inline or externalize packages.\n\nThis update should not be noticeable unless you rely on advanced features mentioned above.\n\n### `workspace` is Replaced with `projects`\n\nThe `workspace` configuration option was renamed to [`projects`](/guide/projects) in Vitest 3.2. They are functionally the same, except you cannot specify another file as the source of your workspace (previously you could specify a file that would export an array of projects). Migrating to `projects` is easy, just move the code from `vitest.workspace.js` to `vitest.config.ts`:\n\n::: code-group\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    workspace: './vitest.workspace.js', // [!code --]\n    projects: [ // [!code ++]\n      './packages/*', // [!code ++]\n      { // [!code ++]\n        test: { // [!code ++]\n          name: 'unit', // [!code ++]\n        }, // [!code ++]\n      }, // [!code ++]\n    ] // [!code ++]\n  }\n})\n```\n```ts [vitest.workspace.js]\nimport { defineWorkspace } from 'vitest/config' // [!code --]\n\nexport default defineWorkspace([ // [!code --]\n  './packages/*', // [!code --]\n  { // [!code --]\n    test: { // [!code --]\n      name: 'unit', // [!code --]\n    }, // [!code --]\n  } // [!code --]\n]) // [!code --]\n```\n:::\n\n### Browser Provider Rework\n\nIn Vitest 4.0, the browser provider now accepts an object instead of a string (`'playwright'`, `'webdriverio'`). The `preview` is no longer a default. This makes it simpler to work with custom options and doesn't require adding `/// <reference` comments anymore.\n\n```ts\nimport { playwright } from '@vitest/browser-playwright' // [!code ++]\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: 'playwright', // [!code --]\n      provider: playwright({ // [!code ++]\n        launchOptions: { // [!code ++]\n          slowMo: 100, // [!code ++]\n        }, // [!code ++]\n      }), // [!code ++]\n      instances: [\n        {\n          browser: 'chromium',\n          launch: { // [!code --]\n            slowMo: 100, // [!code --]\n          }, // [!code --]\n        },\n      ],\n    },\n  },\n})\n```\n\nThe naming of properties in `playwright` factory now also aligns with [Playwright documentation](https://playwright.dev/docs/api/class-testoptions#test-options-launch-options) making it easier to find.\n\nWith this change, the `@vitest/browser` package is no longer needed, and you can remove it from your dependencies. To support the context import, you should update the `@vitest/browser/context` to `vitest/browser`:\n\n```ts\nimport { page } from '@vitest/browser/context' // [!code --]\nimport { page } from 'vitest/browser' // [!code ++]\n\ntest('example', async () => {\n  await page.getByRole('button').click()\n})\n```\n\nThe modules are identical, so doing a simple \"Find and Replace\" should be sufficient.\n\nIf you were using the `@vitest/browser/utils` module, you can now import those utilities from `vitest/browser` as well:\n\n```ts\nimport { getElementError } from '@vitest/browser/utils' // [!code --]\nimport { utils } from 'vitest/browser' // [!code ++]\nconst { getElementError } = utils // [!code ++]\n```\n\n::: warning\nBoth `@vitest/browser/context` and `@vitest/browser/utils` work at runtime during the transition period, but they will be removed in a future release.\n:::\n\n### Pool Rework\n\nVitest has used [`tinypool`](https://github.com/tinylibs/tinypool) for orchestrating how test files are run in the test runner workers. Tinypool has controlled how complex tasks like parallelism, isolation and IPC communication works internally. However we've found that Tinypool has some flaws that are slowing down development of Vitest. In Vitest v4 we've completely removed Tinypool and rewritten how pools work without new dependencies. Read more about reasoning from [feat!: rewrite pools without tinypool #8705\n](https://github.com/vitest-dev/vitest/pull/8705).\n\nNew pool architecture allows Vitest to simplify many previously complex configuration options:\n\n- `maxThreads` and `maxForks` are now `maxWorkers`.\n- Environment variables `VITEST_MAX_THREADS` and `VITEST_MAX_FORKS` are now `VITEST_MAX_WORKERS`.\n- `singleThread` and `singleFork` are now `maxWorkers: 1, isolate: false`. If your tests were relying on module reset between tests, you'll need to add [setupFile](/config/setupfiles) that calls [`vi.resetModules()`](/api/vi.html#vi-resetmodules) in [`beforeAll` test hook](/api/hooks#beforeall).\n- `poolOptions` is removed. All previous `poolOptions` are now top-level options. The `memoryLimit` of VM pools is renamed to `vmMemoryLimit`.\n- `threads.useAtomics` is removed. If you have a use case for this, feel free to open a new feature request.\n- Custom pool interface has been rewritten, see [Custom Pool](/guide/advanced/pool#custom-pool)\n\n```ts\nexport default defineConfig({\n  test: {\n    poolOptions: { // [!code --]\n      forks: { // [!code --]\n        execArgv: ['--expose-gc'], // [!code --]\n        isolate: false, // [!code --]\n        singleFork: true, // [!code --]\n      }, // [!code --]\n      vmThreads: { // [!code --]\n        memoryLimit: '300Mb' // [!code --]\n      }, // [!code --]\n    }, // [!code --]\n    execArgv: ['--expose-gc'], // [!code ++]\n    isolate: false, // [!code ++]\n    maxWorkers: 1, // [!code ++]\n    vmMemoryLimit: '300Mb', // [!code ++]\n  }\n})\n```\n\nPreviously it was not possible to specify some pool related options per project when using [Vitest Projects](/guide/projects). With the new architecture this is no longer a blocker.\n\n::: code-group\n```ts [Isolation per project]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        // Non-isolated unit tests\n        name: 'Unit tests',\n        isolate: false,\n        exclude: ['**.integration.test.ts'],\n      },\n      {\n        // Isolated integration tests\n        name: 'Integration tests',\n        include: ['**.integration.test.ts'],\n      },\n    ],\n  },\n})\n```\n```ts [Parallel & Sequential projects]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        name: 'Parallel',\n        exclude: ['**.sequential.test.ts'],\n      },\n      {\n        name: 'Sequential',\n        include: ['**.sequential.test.ts'],\n        fileParallelism: false,\n      },\n    ],\n  },\n})\n```\n```ts [Node CLI options per project]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        name: 'Production env',\n        execArgv: ['--env-file=.env.prod']\n      },\n      {\n        name: 'Staging env',\n        execArgv: ['--env-file=.env.staging']\n      },\n    ],\n  },\n})\n```\n:::\n\nSee [Recipes](/guide/recipes) for more examples.\n\n### Reporter Updates\n\nReporter APIs `onCollected`, `onSpecsCollected`, `onPathsCollected`, `onTaskUpdate` and `onFinished` were removed. See [`Reporters API`](/api/advanced/reporters) for new alternatives. The new APIs were introduced in Vitest `v3.0.0`.\n\nThe `basic` reporter was removed as it is equal to:\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['default', { summary: false }]\n    ]\n  }\n})\n```\n\nThe [`verbose`](/guide/reporters#verbose-reporter) reporter now prints test cases as a flat list. To revert to the previous behaviour, use `--reporter=tree`:\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: ['verbose'], // [!code --]\n    reporters: ['tree'], // [!code ++]\n  }\n})\n```\n\n### Snapshots using Custom Elements Print the Shadow Root\n\nIn Vitest 4.0 snapshots that include custom elements will print the shadow root contents. To restore the previous behavior, set the [`printShadowRoot` option](/config/snapshotformat) to `false`.\n\n```js{15-22}\n// before Vitest 4.0\nexports[`custom element with shadow root 1`] = `\n\"<body>\n  <div>\n    <custom-element />\n  </div>\n</body>\"\n`\n\n// after Vitest 4.0\nexports[`custom element with shadow root 1`] = `\n\"<body>\n  <div>\n    <custom-element>\n      #shadow-root\n        <span\n          class=\"some-name\"\n          data-test-id=\"33\"\n          id=\"5\"\n        >\n          hello\n        </span>\n    </custom-element>\n  </div>\n</body>\"\n`\n```\n\n### Deprecated APIs are Removed\n\nVitest 4.0 removes some deprecated APIs, including:\n\n- `poolMatchGlobs` config option. Use [`projects`](/guide/projects) instead.\n- `environmentMatchGlobs` config option. Use [`projects`](/guide/projects) instead.\n- `deps.external`, `deps.inline`, `deps.fallbackCJS` config options. Use `server.deps.external`, `server.deps.inline`, or `server.deps.fallbackCJS` instead.\n- `browser.testerScripts` config option. Use [`browser.testerHtmlPath`](/config/browser/testerhtmlpath) instead.\n- `minWorkers` config option. Only `maxWorkers` has any effect on how tests are running, so we are removing this public option.\n- Vitest no longer supports providing test options object as a third argument to `test` and `describe`. Use the second argument instead:\n\n```ts\ntest('example', () => { /* ... */ }, { retry: 2 }) // [!code --]\ntest('example', { retry: 2 }, () => { /* ... */ }) // [!code ++]\n```\n\nNote that providing a timeout number as the last argument is still supported:\n\n```ts\ntest('example', () => { /* ... */ }, 1000) // ✅\n```\n\nThis release also removes all deprecated types. This finally fixes an issue where Vitest accidentally pulled in `@types/node` (see [#5481](https://github.com/vitest-dev/vitest/issues/5481) and [#6141](https://github.com/vitest-dev/vitest/issues/6141)).\n\n## Migrating from Jest {#jest}\n\nVitest has been designed with a Jest compatible API, in order to make the migration from Jest as simple as possible. Despite those efforts, you may still run into the following differences:\n\n### Globals as a Default\n\nJest has their [globals API](https://jestjs.io/docs/api) enabled by default. Vitest does not. You can either enable globals via [the `globals` configuration setting](/config/globals) or update your code to use imports from the `vitest` module instead.\n\nIf you decide to keep globals disabled, be aware that common libraries like [`testing-library`](https://testing-library.com/) will not run auto DOM [cleanup](https://testing-library.com/docs/svelte-testing-library/api/#cleanup).\n\n### `mock.mockReset`\n\nJest's [`mockReset`](https://jestjs.io/docs/mock-function-api#mockfnmockreset) replaces the mock implementation with an\nempty function that returns `undefined`.\n\nVitest's [`mockReset`](/api/mock#mockreset) resets the mock implementation to its original.\nThat is, resetting a mock created by `vi.fn(impl)` will reset the mock implementation to `impl`.\n\n### `mock.mock` is Persistent\n\nJest will recreate the mock state when `.mockClear` is called, meaning you always need to access it as a getter. Vitest, on the other hand, holds a persistent reference to the state, meaning you can reuse it:\n\n```ts\nconst mock = vi.fn()\nconst state = mock.mock\nmock.mockClear()\n\nexpect(state).toBe(mock.mock) // fails in Jest\n```\n\n### Module Mocks\n\nWhen mocking a module in Jest, the factory argument's return value is the default export. In Vitest, the factory argument has to return an object with each export explicitly defined. For example, the following `jest.mock` would have to be updated as follows:\n\n```ts\njest.mock('./some-path', () => 'hello') // [!code --]\nvi.mock('./some-path', () => ({ // [!code ++]\n  default: 'hello', // [!code ++]\n})) // [!code ++]\n```\n\nFor more details please refer to the [`vi.mock` api section](/api/vi#vi-mock).\n\n### Auto-Mocking Behaviour\n\nUnlike Jest, mocked modules in `<root>/__mocks__` are not loaded unless `vi.mock()` is called. If you need them to be mocked in every test, like in Jest, you can mock them inside [`setupFiles`](/config/setupfiles).\n\n### Importing the Original of a Mocked Package\n\nIf you are only partially mocking a package, you might have previously used Jest's function `requireActual`. In Vitest, you should replace these calls with `vi.importActual`.\n\n```ts\nconst { cloneDeep } = jest.requireActual('lodash/cloneDeep') // [!code --]\nconst { cloneDeep } = await vi.importActual('lodash/cloneDeep') // [!code ++]\n```\n\n### Extends mocking to external libraries\n\nWhere Jest does it by default, when mocking a module and wanting this mocking to be extended to other external libraries that use the same module, you should explicitly tell which 3rd-party library you want to be mocked, so the external library would be part of your source code, by using [server.deps.inline](/config/server#inline).\n\n```\nserver.deps.inline: [\"lib-name\"]\n```\n\n### expect.getState().currentTestName\n\nVitest's `test` names are joined with a `>` symbol to make it easier to distinguish tests from suites, while Jest uses an empty space (` `).\n\n```diff\n- `${describeTitle} ${testTitle}`\n+ `${describeTitle} > ${testTitle}`\n```\n\n### Envs\n\nJust like Jest, Vitest sets `NODE_ENV` to `test`, if it wasn't set before. Vitest also has a counterpart for `JEST_WORKER_ID` called `VITEST_POOL_ID` (always less than or equal to `maxWorkers`), so if you rely on it, don't forget to rename it. Vitest also exposes `VITEST_WORKER_ID` which is a unique ID of a running worker - this number is not affected by `maxWorkers`, and will increase with each created worker.\n\n### Replace property\n\nIf you want to modify the object, you will use [replaceProperty API](https://jestjs.io/docs/jest-object#jestreplacepropertyobject-propertykey-value) in Jest, you can use [`vi.stubEnv`](/api/vi#vi-stubenv) or [`vi.spyOn`](/api/vi#vi-spyon) to do the same also in Vitest.\n\n### Done Callback\n\nVitest does not support the callback style of declaring tests. You can rewrite them to use `async`/`await` functions, or use Promise to mimic the callback style.\n\n<!--@include: ./examples/promise-done.md-->\n\n### Hooks\n\n`beforeAll`/`beforeEach` hooks may return [teardown function](/api/hooks#beforeach) in Vitest. Because of that you may need to rewrite your hooks declarations, if they return something other than `undefined` or `null`:\n\n```ts\nbeforeEach(() => setActivePinia(createTestingPinia())) // [!code --]\nbeforeEach(() => { setActivePinia(createTestingPinia()) }) // [!code ++]\n```\n\nIn Jest hooks are called sequentially (one after another). By default, Vitest runs hooks in a stack. To use Jest's behavior, update [`sequence.hooks`](/config/sequence#sequence-hooks) option:\n\n```ts\nexport default defineConfig({\n  test: {\n    sequence: { // [!code ++]\n      hooks: 'list', // [!code ++]\n    } // [!code ++]\n  }\n})\n```\n\n### Types\n\nVitest doesn't have an equivalent to `jest` namespace, so you will need to import types directly from `vitest`:\n\n```ts\nlet fn: jest.Mock<(name: string) => number> // [!code --]\nimport type { Mock } from 'vitest' // [!code ++]\nlet fn: Mock<(name: string) => number> // [!code ++]\n```\n\n### Timers\n\nVitest doesn't support Jest's legacy timers.\n\n### Timeout\n\nIf you used `jest.setTimeout`, you would need to migrate to `vi.setConfig`:\n\n```ts\njest.setTimeout(5_000) // [!code --]\nvi.setConfig({ testTimeout: 5_000 }) // [!code ++]\n```\n\n### Vue Snapshots\n\nThis is not a Jest-specific feature, but if you previously were using Jest with vue-cli preset, you will need to install [`jest-serializer-vue`](https://github.com/eddyerburgh/jest-serializer-vue) package, and specify it in [`snapshotSerializers`](/config/snapshotserializers):\n\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    snapshotSerializers: ['jest-serializer-vue']\n  }\n})\n```\n\nOtherwise your snapshots will have a lot of escaped `\"` characters.\n\n## Migrating from Mocha + Chai + Sinon {#mocha-chai-sinon}\n\nVitest provides excellent support for migrating from Mocha+Chai+Sinon test suites. While Vitest uses a Jest-compatible API by default, it also provides Chai-style assertions for spy/mock testing, making migration easier.\n\n### Test Structure\n\nMocha and Vitest have similar test structures, but with some differences:\n\n```ts\n// Mocha\ndescribe('suite', () => {\n  before(() => { /* setup */ })\n  after(() => { /* teardown */ })\n  beforeEach(() => { /* setup */ })\n  afterEach(() => { /* teardown */ })\n\n  it('test', () => {\n    // test code\n  })\n})\n\n// Vitest - same structure works!\nimport { afterAll, afterEach, beforeAll, beforeEach, describe, it } from 'vitest'\n\ndescribe('suite', () => {\n  beforeAll(() => { /* setup */ })\n  afterAll(() => { /* teardown */ })\n  beforeEach(() => { /* setup */ })\n  afterEach(() => { /* teardown */ })\n\n  it('test', () => {\n    // test code\n  })\n})\n```\n\n### Assertions\n\nVitest includes Chai assertions by default, so Chai assertions work without changes:\n\n```ts\n// Both Mocha+Chai and Vitest\nimport { expect } from 'vitest' // or 'chai' in Mocha\n\nexpect(value).to.equal(42)\nexpect(value).to.be.true\nexpect(array).to.have.lengthOf(3)\nexpect(obj).to.have.property('key')\n```\n\n### Spy/Mock Assertions\n\nVitest provides **Chai-style assertions** for spies and mocks, allowing you to migrate from Sinon without rewriting assertions:\n\n```ts\n// Before (Mocha + Chai + Sinon)\nconst sinon = require('sinon')\nconst chai = require('chai')\nconst sinonChai = require('sinon-chai')\nchai.use(sinonChai)\n\nconst spy = sinon.spy(obj, 'method')\nobj.method('arg1', 'arg2')\n\nexpect(spy).to.have.been.called\nexpect(spy).to.have.been.calledOnce\nexpect(spy).to.have.been.calledWith('arg1', 'arg2')\n\n// After (Vitest) - same assertion syntax!\nimport { expect, vi } from 'vitest'\n\nconst spy = vi.spyOn(obj, 'method')\nobj.method('arg1', 'arg2')\n\nexpect(spy).to.have.been.called\nexpect(spy).to.have.been.calledOnce\nexpect(spy).to.have.been.calledWith('arg1', 'arg2')\n```\n\n#### Complete Chai-Style Assertion Support\n\nVitest supports all common sinon-chai assertions:\n\n| Sinon-Chai | Vitest | Description |\n|------------|--------|-------------|\n| `spy.called` | `called` | Spy was called at least once |\n| `spy.calledOnce` | `calledOnce` | Spy was called exactly once |\n| `spy.calledTwice` | `calledTwice` | Spy was called exactly twice |\n| `spy.calledThrice` | `calledThrice` | Spy was called exactly three times |\n| `spy.callCount(n)` | `callCount(n)` | Spy was called n times |\n| `spy.calledWith(...)` | `calledWith(...)` | Spy was called with specific args |\n| `spy.calledOnceWith(...)` | `calledOnceWith(...)` | Spy was called once with specific args |\n| `spy.returned` | `returned` | Spy returned successfully |\n| `spy.returnedWith(value)` | `returnedWith(value)` | Spy returned specific value |\n\nSee the [Chai-Style Spy Assertions](/api/expect#chai-style-spy-assertions) documentation for the complete list.\n\n### Creating Spies and Mocks\n\nReplace Sinon's spy/stub/mock creation with Vitest's `vi` utilities:\n\n```ts\n// Sinon\nconst sinon = require('sinon')\nconst spy = sinon.spy()\nconst stub = sinon.stub(obj, 'method')\nconst mock = sinon.mock(obj)\n\n// Vitest\nimport { vi } from 'vitest'\nconst spy = vi.fn()\nconst stub = vi.spyOn(obj, 'method')\n// Vitest doesn't have \"mocks\" - use spies instead\n```\n\n### Stubbing Return Values\n\n```ts\n// Sinon\nstub.returns(42)\nstub.onFirstCall().returns(1)\nstub.onSecondCall().returns(2)\n\n// Vitest\nstub.mockReturnValue(42)\nstub.mockReturnValueOnce(1)\nstub.mockReturnValueOnce(2)\n```\n\n### Stubbing Implementations\n\n```ts\n// Sinon\nstub.callsFake(arg => arg * 2)\n\n// Vitest\nstub.mockImplementation(arg => arg * 2)\n```\n\n### Restoring Spies\n\n```ts\n// Sinon\nspy.restore()\nsinon.restore() // restore all\n\n// Vitest\nspy.mockRestore()\nvi.restoreAllMocks() // restore all\n```\n\n### Timers\n\nBoth Sinon and Vitest use `@sinonjs/fake-timers` internally:\n\n```ts\n// Sinon\nconst clock = sinon.useFakeTimers()\nclock.tick(1000)\nclock.restore()\n\n// Vitest\nimport { vi } from 'vitest'\nvi.useFakeTimers()\nvi.advanceTimersByTime(1000)\nvi.useRealTimers()\n```\n\n### Key Differences\n\n1. **Globals**: Mocha provides globals by default. In Vitest, either import from `vitest` or enable [`globals`](/config/globals) config\n2. **Assertion style**: You can use both Chai-style (`expect(spy).to.have.been.called`) and Jest-style (`expect(spy).toHaveBeenCalled()`)\n3. **Parallel execution**: Vitest runs tests in parallel by default, Mocha runs sequentially\n\nFor more information, see:\n- [Chai-Style Spy Assertions](/api/expect#chai-style-spy-assertions)\n- [Mocking Guide](/guide/mocking)\n- [Vi API](/api/vi)\n"
  },
  {
    "path": "docs/guide/mocking/classes.md",
    "content": "# Mocking Classes\n\nYou can mock an entire class with a single [`vi.fn`](/api/vi#fn) call.\n\n```ts\nclass Dog {\n  name: string\n\n  constructor(name: string) {\n    this.name = name\n  }\n\n  static getType(): string {\n    return 'animal'\n  }\n\n  greet = (): string => {\n    return `Hi! My name is ${this.name}!`\n  }\n\n  speak(): string {\n    return 'bark!'\n  }\n\n  isHungry() {}\n  feed() {}\n}\n```\n\nWe can re-create this class with `vi.fn` (or `vi.spyOn().mockImplementation()`):\n\n```ts\nconst Dog = vi.fn(class {\n  static getType = vi.fn(() => 'mocked animal')\n\n  constructor(name) {\n    this.name = name\n  }\n\n  greet = vi.fn(() => `Hi! My name is ${this.name}!`)\n  speak = vi.fn(() => 'loud bark!')\n  feed = vi.fn()\n})\n```\n\n::: warning\nIf a non-primitive is returned from the constructor function, that value will become the result of the new expression. In this case the `[[Prototype]]` may not be correctly bound:\n\n```ts\nconst CorrectDogClass = vi.fn(function (name) {\n  this.name = name\n})\n\nconst IncorrectDogClass = vi.fn(name => ({\n  name\n}))\n\nconst Marti = new CorrectDogClass('Marti')\nconst Newt = new IncorrectDogClass('Newt')\n\nMarti instanceof CorrectDogClass // ✅ true\nNewt instanceof IncorrectDogClass // ❌ false!\n```\n\nIf you are mocking classes, prefer the class syntax over the function.\n:::\n\n::: tip WHEN TO USE?\nGenerally speaking, you would re-create a class like this inside the module factory if the class is re-exported from another module:\n\n```ts\nimport { Dog } from './dog.js'\n\nvi.mock(import('./dog.js'), () => {\n  const Dog = vi.fn(class {\n    feed = vi.fn()\n    // ... other mocks\n  })\n  return { Dog }\n})\n```\n\nThis method can also be used to pass an instance of a class to a function that accepts the same interface:\n\n```ts [src/feed.ts]\nfunction feed(dog: Dog) {\n  // ...\n}\n```\n```ts [tests/dog.test.ts]\nimport { expect, test, vi } from 'vitest'\nimport { feed } from '../src/feed.js'\n\nconst Dog = vi.fn(class {\n  feed = vi.fn()\n})\n\ntest('can feed dogs', () => {\n  const dogMax = new Dog('Max')\n\n  feed(dogMax)\n\n  expect(dogMax.feed).toHaveBeenCalled()\n  expect(dogMax.isHungry()).toBe(false)\n})\n```\n:::\n\nNow, when we create a new instance of the `Dog` class its `speak` method (alongside `feed` and `greet`) is already mocked:\n\n```ts\nconst Cooper = new Dog('Cooper')\nCooper.speak() // loud bark!\nCooper.greet() // Hi! My name is Cooper!\n\n// you can use built-in assertions to check the validity of the call\nexpect(Cooper.speak).toHaveBeenCalled()\nexpect(Cooper.greet).toHaveBeenCalled()\n\nconst Max = new Dog('Max')\n\n// methods are not shared between instances if you assigned them directly\nexpect(Max.speak).not.toHaveBeenCalled()\nexpect(Max.greet).not.toHaveBeenCalled()\n```\n\nWe can reassign the return value for a specific instance:\n\n```ts\nconst dog = new Dog('Cooper')\n\n// \"vi.mocked\" is a type helper, since\n// TypeScript doesn't know that Dog is a mocked class,\n// it wraps any function in a Mock<T> type\n// without validating if the function is a mock\nvi.mocked(dog.speak).mockReturnValue('woof woof')\n\ndog.speak() // woof woof\n```\n\nTo mock the property, we can use the `vi.spyOn(dog, 'name', 'get')` method. This makes it possible to use spy assertions on the mocked property:\n\n```ts\nconst dog = new Dog('Cooper')\n\nconst nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max')\n\nexpect(dog.name).toBe('Max')\nexpect(nameSpy).toHaveBeenCalledTimes(1)\n```\n\n::: tip\nYou can also spy on getters and setters using the same method.\n:::\n\n::: danger\nUsing classes with `vi.fn()` was introduced in Vitest 4. Previously, you had to use `function` and `prototype` inheritence directly. See [v3 guide](https://v3.vitest.dev/guide/mocking.html#classes).\n:::\n"
  },
  {
    "path": "docs/guide/mocking/dates.md",
    "content": "# Mocking Dates\n\nSometimes you need to be in control of the date to ensure consistency when testing. Vitest uses [`@sinonjs/fake-timers`](https://github.com/sinonjs/fake-timers) package for manipulating timers, as well as system date. You can find more about the specific API in detail [here](/api/vi#vi-setsystemtime).\n\n## Example\n\n```js\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nconst businessHours = [9, 17]\n\nfunction purchase() {\n  const currentHour = new Date().getHours()\n  const [open, close] = businessHours\n\n  if (currentHour > open && currentHour < close) {\n    return { message: 'Success' }\n  }\n\n  return { message: 'Error' }\n}\n\ndescribe('purchasing flow', () => {\n  beforeEach(() => {\n    // tell vitest we use mocked time\n    vi.useFakeTimers()\n  })\n\n  afterEach(() => {\n    // restoring date after each test run\n    vi.useRealTimers()\n  })\n\n  it('allows purchases within business hours', () => {\n    // set hour within business hours\n    const date = new Date(2000, 1, 1, 13)\n    vi.setSystemTime(date)\n\n    // access Date.now() will result in the date set above\n    expect(purchase()).toEqual({ message: 'Success' })\n  })\n\n  it('disallows purchases outside of business hours', () => {\n    // set hour outside business hours\n    const date = new Date(2000, 1, 1, 19)\n    vi.setSystemTime(date)\n\n    // access Date.now() will result in the date set above\n    expect(purchase()).toEqual({ message: 'Error' })\n  })\n})\n```\n"
  },
  {
    "path": "docs/guide/mocking/file-system.md",
    "content": "# Mocking the File System\n\nMocking the file system ensures that the tests do not depend on the actual file system, making the tests more reliable and predictable. This isolation helps in avoiding side effects from previous tests. It allows for testing error conditions and edge cases that might be difficult or impossible to replicate with an actual file system, such as permission issues, disk full scenarios, or read/write errors.\n\nVitest doesn't provide any file system mocking API out of the box. You can use `vi.mock` to mock the `fs` module manually, but it's hard to maintain. Instead, we recommend using [`memfs`](https://npmx.dev/package/memfs) to do that for you. `memfs` creates an in-memory file system, which simulates file system operations without touching the actual disk. This approach is fast and safe, avoiding any potential side effects on the real file system.\n\n## Example\n\nTo automatically redirect every `fs` call to `memfs`, you can create `__mocks__/fs.cjs` and `__mocks__/fs/promises.cjs` files at the root of your project:\n\n::: code-group\n```ts [__mocks__/fs.cjs]\n// we can also use `import`, but then\n// every export should be explicitly defined\n\nconst { fs } = require('memfs')\nmodule.exports = fs\n```\n\n```ts [__mocks__/fs/promises.cjs]\n// we can also use `import`, but then\n// every export should be explicitly defined\n\nconst { fs } = require('memfs')\nmodule.exports = fs.promises\n```\n:::\n\n```ts [read-hello-world.js]\nimport { readFileSync } from 'node:fs'\n\nexport function readHelloWorld(path) {\n  return readFileSync(path, 'utf-8')\n}\n```\n\n```ts [hello-world.test.js]\nimport { beforeEach, expect, it, vi } from 'vitest'\nimport { fs, vol } from 'memfs'\nimport { readHelloWorld } from './read-hello-world.js'\n\n// tell vitest to use fs mock from __mocks__ folder\n// this can be done in a setup file if fs should always be mocked\nvi.mock('node:fs')\nvi.mock('node:fs/promises')\n\nbeforeEach(() => {\n  // reset the state of in-memory fs\n  vol.reset()\n})\n\nit('should return correct text', () => {\n  const path = '/hello-world.txt'\n  fs.writeFileSync(path, 'hello world')\n\n  const text = readHelloWorld(path)\n  expect(text).toBe('hello world')\n})\n\nit('can return a value multiple times', () => {\n  // you can use vol.fromJSON to define several files\n  vol.fromJSON(\n    {\n      './dir1/hw.txt': 'hello dir1',\n      './dir2/hw.txt': 'hello dir2',\n    },\n    // default cwd\n    '/tmp',\n  )\n\n  expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1')\n  expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2')\n})\n```\n"
  },
  {
    "path": "docs/guide/mocking/functions.md",
    "content": "# Mocking Functions\n\nMocking functions can be split up into two different categories: spying and mocking.\n\nIf you need to observe the behaviour of a method on an object, you can use [`vi.spyOn()`](/api/vi#vi-spyon) to create a spy that tracks calls to that method.\n\nIf you need to pass down a custom function implementation as an argument or create a new mocked entity, you can use [`vi.fn()`](/api/vi#vi-fn) to create a mock function.\n\nBoth `vi.spyOn` and `vi.fn` share the same methods.\n\n## Example\n\n```js\nimport { afterEach, describe, expect, it, vi } from 'vitest'\n\nconst messages = {\n  items: [\n    { message: 'Simple test message', from: 'Testman' },\n    // ...\n  ],\n  addItem(item) {\n    messages.items.push(item)\n    messages.callbacks.forEach(callback => callback(item))\n  },\n  onItem(callback) {\n    messages.callbacks.push(callback)\n  },\n  getLatest, // can also be a `getter or setter if supported`\n}\n\nfunction getLatest(index = messages.items.length - 1) {\n  return messages.items[index]\n}\n\nit('should get the latest message with a spy', () => {\n  const spy = vi.spyOn(messages, 'getLatest')\n  expect(spy.getMockName()).toEqual('getLatest')\n\n  expect(messages.getLatest()).toEqual(\n    messages.items[messages.items.length - 1],\n  )\n\n  expect(spy).toHaveBeenCalledTimes(1)\n\n  spy.mockImplementationOnce(() => 'access-restricted')\n  expect(messages.getLatest()).toEqual('access-restricted')\n\n  expect(spy).toHaveBeenCalledTimes(2)\n})\n\nit('passing down the mock', () => {\n  const callback = vi.fn()\n  messages.onItem(callback)\n\n  messages.addItem({ message: 'Another test message', from: 'Testman' })\n  expect(callback).toHaveBeenCalledWith({\n    message: 'Another test message',\n    from: 'Testman',\n  })\n})\n```\n"
  },
  {
    "path": "docs/guide/mocking/globals.md",
    "content": "# Mocking Globals\n\nYou can mock global variables that are not present with `jsdom` or `node` by using [`vi.stubGlobal`](/api/vi#vi-stubglobal) helper. It will put the value of the global variable into a `globalThis` object.\n\nBy default, Vitest does not reset these globals, but you can turn on the [`unstubGlobals`](/config/unstubglobals) option in your config to restore the original values after each test or call [`vi.unstubAllGlobals()`](/api/vi#vi-unstuballglobals) manually.\n\n```ts\nimport { vi } from 'vitest'\n\nconst IntersectionObserverMock = vi.fn(class {\n  disconnect = vi.fn()\n  observe = vi.fn()\n  takeRecords = vi.fn()\n  unobserve = vi.fn()\n})\n\nvi.stubGlobal('IntersectionObserver', IntersectionObserverMock)\n\n// now you can access it as `IntersectionObserver` or `window.IntersectionObserver`\n```\n"
  },
  {
    "path": "docs/guide/mocking/modules.md",
    "content": "# Mocking Modules\n\n## Defining a Module\n\nBefore mocking a \"module\", we should define what it is. In Vitest context, the \"module\" is a file that exports something. Using [plugins](https://vite.dev/guide/api-plugin.html), any file can be turned into a JavaScript module. The \"module object\" is a namespace object that holds dynamic references to exported identifiers. Simply put, it's an object with exported methods and properties. In this example, `example.js` is a module that exports `answer` and `variable`:\n\n```js [example.js]\nexport function answer() {\n  // ...\n  return 42\n}\n\nexport const variable = 'example'\n```\n\nThe `exampleObject` here is a module object:\n\n```js [example.test.js]\nimport * as exampleObject from './example.js'\n```\n\nThe `exampleObject` will always exist even if you imported the example using named imports:\n\n```js [example.test.js]\nimport { answer, variable } from './example.js'\n```\n\nYou can only reference `exampleObject` outside the example module itself. For example, in a test.\n\n## Mocking a Module\n\nFor the purpose of this guide, let's introduce some definitions.\n\n- **Mocked module** is a module that was completely replaced with another one.\n- **Spied module** is a mocked module, but its exported methods keep the original implementation. They can also be tracked.\n- **Mocked export** is a module export, which invocations can be tracked.\n- **Spied export** is a mocked export.\n\nTo mock a module completely, you can use the [`vi.mock` API](/api/vi#vi-mock). You can define a new module dynamically by providing a factory that returns a new module as a second argument:\n\n```ts\nimport { vi } from 'vitest'\n\n// The ./example.js module will be replaced with\n// the result of a factory function, and the\n// original ./example.js module will never be called\nvi.mock(import('./example.js'), () => {\n  return {\n    answer() {\n      // ...\n      return 42\n    },\n    variable: 'mock',\n  }\n})\n```\n\n::: tip\nRemember that you can call `vi.mock` in a [setup file](/config/setupfiles) to apply the module mock in every test file automatically.\n:::\n\n::: tip\nNote the usage of dynamic import: `import('./example.ts')`. Vitest will strip it before the code is executed, but it allows TypeScript to properly validate the string and type the `importOriginal` method in your IDE or CLI.\n:::\n\nIf your code is trying to access a method that was not returned from this factory, Vitest will throw an error with a helpful message. Note that `answer` is not mocked, i.e. it cannot be tracked. To make it trackable, use `vi.fn()` instead:\n\n```ts\nimport { vi } from 'vitest'\n\nvi.mock(import('./example.js'), () => {\n  return {\n    answer: vi.fn(),\n    variable: 'mock',\n  }\n})\n```\n\nThe factory method accepts an `importOriginal` function that will execute the original module and return its module object:\n\n```ts\nimport { expect, vi } from 'vitest'\nimport { answer } from './example.js'\n\nvi.mock(import('./example.js'), async (importOriginal) => {\n  const originalModule = await importOriginal()\n  return {\n    answer: vi.fn(originalModule.answer),\n    variable: 'mock',\n  }\n})\n\nexpect(answer()).toBe(42)\n\nexpect(answer).toHaveBeenCalled()\nexpect(answer).toHaveReturned(42)\n```\n\n::: warning\nNote that `importOriginal` is asynchronous and needs to be awaited.\n:::\n\nIn the above example, we provided the original `answer` to the `vi.fn()` call so it can keep calling it while being tracked at the same time.\n\nIf you require the use of `importOriginal`, consider spying on the export directly via another API: `vi.spyOn`. Instead of replacing the whole module, you can spy only on a single exported method. To do that, you need to import the module as a namespace object:\n\n```ts\nimport { expect, vi } from 'vitest'\nimport * as exampleObject from './example.js'\n\nconst spy = vi.spyOn(exampleObject, 'answer').mockReturnValue(0)\n\nexpect(exampleObject.answer()).toBe(0)\nexpect(exampleObject.answer).toHaveBeenCalled()\n```\n\n::: danger Browser Mode Support\nThis will not work in the [Browser Mode](/guide/browser/) because it uses the browser's native ESM support to serve modules. The module namespace object is sealed and can't be reconfigured. To bypass this limitation, Vitest supports `{ spy: true }` option in `vi.mock('./example.js')`. This will automatically spy on every export in the module without replacing them with fake ones.\n\n```ts\nimport { vi } from 'vitest'\nimport * as exampleObject from './example.js'\n\nvi.mock('./example.js', { spy: true })\n\nvi.mocked(exampleObject.answer).mockReturnValue(0)\n```\n:::\n\n::: warning\nYou only need to import the module as a namespace object in the file where you are using the `vi.spyOn` utility. If the `answer` is called in another file and is imported there as a named export, Vitest will be able to properly track it as long as the function that called it is called after `vi.spyOn`:\n\n```ts [source.js]\nimport { answer } from './example.js'\n\nexport function question() {\n  if (answer() === 42) {\n    return 'Ultimate Question of Life, the Universe, and Everything'\n  }\n\n  return 'Unknown Question'\n}\n```\n:::\n\nNote that `vi.spyOn` will only spy on calls that were done after it spied on the method. So, if the function is executed at the top level during an import or it was called before the spying, `vi.spyOn` will not be able to report on it.\n\nTo automatically mock any module before it is imported, you can call `vi.mock` with a path:\n\n```ts\nimport { vi } from 'vitest'\n\nvi.mock(import('./example.js'))\n```\n\nIf the file `./__mocks__/example.js` exists, then Vitest will load it instead. Otherwise, Vitest will load the original module and replace everything recursively:\n\n{#automocking-algorithm}\n\n- All arrays will be empty\n- All primitives will stay untouched\n- All getters will return `undefined`\n- All methods will return `undefined`\n- All objects will be deeply cloned\n- All instances of classes and their prototypes will be cloned\n\nTo disable this behavior, you can pass down `spy: true` as the second argument:\n\n```ts\nimport { vi } from 'vitest'\n\nvi.mock(import('./example.js'), { spy: true })\n```\n\nInstead of returning `undefined`, all methods will call the original implementation, but you can still keep track of these calls:\n\n```ts\nimport { expect, vi } from 'vitest'\nimport { answer } from './example.js'\n\nvi.mock(import('./example.js'), { spy: true })\n\n// calls the original implementation\nexpect(answer()).toBe(42)\n// vitest can still track the invocations\nexpect(answer).toHaveBeenCalled()\n```\n\nOne nice thing that mocked modules support is sharing the state between the instance and its prototype. Consider this module:\n\n```ts [answer.js]\nexport class Answer {\n  constructor(value) {\n    this._value = value\n  }\n\n  value() {\n    return this._value\n  }\n}\n```\n\nBy mocking it, we can keep track of every invocation of `.value()` even without having access to the instance itself:\n\n```ts [answer.test.js]\nimport { expect, test, vi } from 'vitest'\nimport { Answer } from './answer.js'\n\nvi.mock(import('./answer.js'), { spy: true })\n\ntest('instance inherits the state', () => {\n  // these invocations could be private inside another function\n  // that you don't have access to in your test\n  const answer1 = new Answer(42)\n  const answer2 = new Answer(0)\n\n  expect(answer1.value()).toBe(42)\n  expect(answer1.value).toHaveBeenCalled()\n  // note that different instances have their own states\n  expect(answer2.value).not.toHaveBeenCalled()\n\n  expect(answer2.value()).toBe(0)\n\n  // but the prototype state accumulates all calls\n  expect(Answer.prototype.value).toHaveBeenCalledTimes(2)\n  expect(Answer.prototype.value).toHaveReturned(42)\n  expect(Answer.prototype.value).toHaveReturned(0)\n})\n```\n\nThis can be very useful to track calls to instances that are never exposed.\n\n## Mocking Non-existing Module\n\nVitest supports mocking virtual modules. These modules don't exist on the file system, but your code imports them. For example, this can happen when your development environment is different from production. One common example is mocking `vscode` APIs in your unit tests.\n\nBy default, Vitest will fail transforming files if it cannot find the source of the import. To bypass this, you need to specify it in your config. You can either always redirect the import to a file, or just signal Vite to ignore it and use the `vi.mock` factory to define its exports.\n\nTo redirect the import, use [`test.alias`](/config/alias) config option:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport { resolve } from 'node:path'\n\nexport default defineConfig({\n  test: {\n    alias: {\n      vscode: resolve(import.meta.dirname, './mock/vscode.js'),\n    },\n  },\n})\n```\n\nTo mark the module as always resolved, return the same string from `resolveId` hook of a plugin:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport { resolve } from 'node:path'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'virtual-vscode',\n      resolveId(id) {\n        if (id === 'vscode') {\n          return 'vscode'\n        }\n      }\n    }\n  ]\n})\n```\n\nNow you can use `vi.mock` as usual in your tests:\n\n```ts\nimport { vi } from 'vitest'\n\nvi.mock(import('vscode'), () => {\n  return {\n    window: {\n      createOutputChannel: vi.fn(),\n    }\n  }\n})\n```\n\n## How it Works\n\nVitest implements different module mocking mechanisms depending on the environment. The only feature they share is the plugin transformer. When Vitest sees that a file has `vi.mock` inside, it will transform every static import into a dynamic one and move the `vi.mock` call to the top of the file. This allows Vitest to register the mock before the import happens without breaking the ESM rule of hoisted imports.\n\n::: code-group\n```ts [example.js]\nimport { answer } from './answer.js'\n\nvi.mock(import('./answer.js'))\n\nconsole.log(answer)\n```\n```ts [example.transformed.js]\nvi.mock('./answer.js')\n\nconst __vitest_module_0__ = await __handle_mock__(\n  () => import('./answer.js')\n)\n// to keep the live binding, we have to access\n// the export on the module namespace\nconsole.log(__vitest_module_0__.answer())\n```\n:::\n\nThe `__handle_mock__` wrapper just makes sure the mock is resolved before the import is initiated, it doesn't modify the module in any way.\n\nThe module mocking plugins are available in the [`@vitest/mocker` package](https://github.com/vitest-dev/vitest/tree/main/packages/mocker).\n\n### JSDOM, happy-dom, Node\n\nWhen you run your tests in an emulated environment, Vitest creates a [module runner](https://vite.dev/guide/api-environment-runtimes.html#modulerunner) that can consume Vite code. The module runner is designed in such a way that Vitest can hook into the module evaluation and replace it with the mock, if it was registered. This means that Vitest runs your code in an ESM-like environment, but it doesn't use native ESM mechanism directly. This allows the test runner to bend the rules around ES Modules immutability, allowing users to call `vi.spyOn` on a seemingly ES Module.\n\nIf module runner is [disabled](/config/experimental#experimental-vitemodulerunner) and [node loader](/config/experimental#experimental-nodeloader) is not explicitly disabled, Vitest will [register a loader hook](https://nodejs.org/api/module.html#customization-hooks) that transforms original modules into mocked ones. In this mode users cannot call `vi.spyOn` on an ES Module because Vitest uses a native loader mechanism with all its guard rails. In addition to that, Vitest also has to inject a `mock` query into every mocked module which is visible in the stack trace.\n\n### Browser Mode\n\nVitest uses native ESM in the Browser Mode. This means that we cannot replace the module so easily. Instead, Vitest intercepts the fetch request (via playwright's `page.route` or a Vite plugin API if using `preview` or `webdriverio`) and serves transformed code, if the module was mocked.\n\nFor example, if the module is automocked, Vitest can parse static exports and create a placeholder module:\n\n::: code-group\n```ts [answer.js]\nexport function answer() {\n  return 42\n}\n```\n```ts [answer.transformed.js]\nfunction answer() {\n  return 42\n}\n\nconst __private_module__ = {\n  [Symbol.toStringTag]: 'Module',\n  answer: vi.fn(answer),\n}\n\nexport const answer = __private_module__.answer\n```\n:::\n\nThe example is simplified for brevity, but the concept is unchanged. We can inject a `__private_module__` variable into the module to hold the mocked values. If the user called `vi.mock` with `spy: true`, we pass down the original value; otherwise, we create a simple `vi.fn()` mock.\n\nIf user defined a custom factory, this makes it harder to inject the code, but not impossible. When the mocked file is served, we first resolve the factory in the browser, then pass down the keys back to the server, and use them to create a placeholder module:\n\n```ts\nconst resolvedFactoryKeys = await resolveBrowserFactory(url)\nconst mockedModule = `\nconst __private_module__ = getFactoryReturnValue(${url})\n${resolvedFactoryKeys.map(key => `export const ${key} = __private_module__[\"${key}\"]`).join('\\n')}\n`\n```\n\nThis module can now be served back to the browser. You can inspect the code in the devtools when you run the tests.\n\n## Mocking Modules Pitfalls\n\nBeware that it is not possible to mock calls to methods that are called inside other methods of the same file. For example, in this code:\n\n```ts [foobar.js]\nexport function foo() {\n  return 'foo'\n}\n\nexport function foobar() {\n  return `${foo()}bar`\n}\n```\n\nIt is not possible to mock the `foo` method from the outside because it is referenced directly. So this code will have no effect on the `foo` call inside `foobar` (but it will affect the `foo` call in other modules):\n\n```ts [foobar.test.ts]\nimport { vi } from 'vitest'\nimport * as mod from './foobar.js'\n\n// this will only affect \"foo\" outside of the original module\nvi.spyOn(mod, 'foo')\nvi.mock(import('./foobar.js'), async (importOriginal) => {\n  return {\n    ...await importOriginal(),\n    // this will only affect \"foo\" outside of the original module\n    foo: () => 'mocked'\n  }\n})\n```\n\nYou can confirm this behavior by providing the implementation to the `foobar` method directly:\n\n```ts [foobar.test.js]\nimport * as mod from './foobar.js'\n\nvi.spyOn(mod, 'foo')\n\n// exported foo references mocked method\nmod.foobar(mod.foo)\n```\n\n```ts [foobar.js]\nexport function foo() {\n  return 'foo'\n}\n\nexport function foobar(injectedFoo) {\n  return injectedFoo === foo // false\n}\n```\n\nThis is the intended behavior, and we do not plan to implement a workaround. Consider refactoring your code into multiple files or use techniques such as [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection). We believe that making the application testable is not the responsibility of the test runner, but of the application architecture.\n"
  },
  {
    "path": "docs/guide/mocking/requests.md",
    "content": "# Mocking Requests\n\nBecause Vitest runs in Node, mocking network requests is tricky; web APIs are not available, so we need something that will mimic network behavior for us. We recommend [Mock Service Worker](https://mswjs.io/) to accomplish this. It allows you to mock `http`, `WebSocket` and `GraphQL` network requests, and is framework agnostic.\n\nMock Service Worker (MSW) works by intercepting the requests your tests make, allowing you to use it without changing any of your application code. In-browser, this uses the [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). In Node.js, and for Vitest, it uses the [`@mswjs/interceptors`](https://github.com/mswjs/interceptors) library. To learn more about MSW, read their [introduction](https://mswjs.io/docs/)\n\n## Configuration\n\nYou can use it like below in your [setup file](/config/setupfiles)\n\n::: code-group\n\n```js [HTTP Setup]\nimport { afterAll, afterEach, beforeAll } from 'vitest'\nimport { setupServer } from 'msw/node'\nimport { http, HttpResponse } from 'msw'\n\nconst posts = [\n  {\n    userId: 1,\n    id: 1,\n    title: 'first post title',\n    body: 'first post body',\n  },\n  // ...\n]\n\nexport const restHandlers = [\n  http.get('https://rest-endpoint.example/path/to/posts', () => {\n    return HttpResponse.json(posts)\n  }),\n]\n\nconst server = setupServer(...restHandlers)\n\n// Start server before all tests\nbeforeAll(() => server.listen({ onUnhandledRequest: 'error' }))\n\n// Close server after all tests\nafterAll(() => server.close())\n\n// Reset handlers after each test for test isolation\nafterEach(() => server.resetHandlers())\n```\n\n```js [GraphQL Setup]\nimport { afterAll, afterEach, beforeAll } from 'vitest'\nimport { setupServer } from 'msw/node'\nimport { graphql, HttpResponse } from 'msw'\n\nconst posts = [\n  {\n    userId: 1,\n    id: 1,\n    title: 'first post title',\n    body: 'first post body',\n  },\n  // ...\n]\n\nconst graphqlHandlers = [\n  graphql.query('ListPosts', () => {\n    return HttpResponse.json({\n      data: { posts },\n    })\n  }),\n]\n\nconst server = setupServer(...graphqlHandlers)\n\n// Start server before all tests\nbeforeAll(() => server.listen({ onUnhandledRequest: 'error' }))\n\n// Close server after all tests\nafterAll(() => server.close())\n\n// Reset handlers after each test for test isolation\nafterEach(() => server.resetHandlers())\n```\n\n```js [WebSocket Setup]\nimport { afterAll, afterEach, beforeAll } from 'vitest'\nimport { setupServer } from 'msw/node'\nimport { ws } from 'msw'\n\nconst chat = ws.link('wss://chat.example.com')\n\nconst wsHandlers = [\n  chat.addEventListener('connection', ({ client }) => {\n    client.addEventListener('message', (event) => {\n      console.log('Received message from client:', event.data)\n      // Echo the received message back to the client\n      client.send(`Server received: ${event.data}`)\n    })\n  }),\n]\n\nconst server = setupServer(...wsHandlers)\n\n// Start server before all tests\nbeforeAll(() => server.listen({ onUnhandledRequest: 'error' }))\n\n// Close server after all tests\nafterAll(() => server.close())\n\n// Reset handlers after each test for test isolation\nafterEach(() => server.resetHandlers())\n```\n:::\n\n> Configuring the server with `onUnhandledRequest: 'error'` ensures that an error is thrown whenever there is a request that does not have a corresponding request handler.\n\n## More\nThere is much more to MSW. You can access cookies and query parameters, define mock error responses, and much more! To see all you can do with MSW, read [their documentation](https://mswjs.io/docs).\n"
  },
  {
    "path": "docs/guide/mocking/timers.md",
    "content": "# Timers\n\nWhen we test code that involves timeouts or intervals, instead of having our tests wait it out or timeout, we can speed up our tests by using \"fake\" timers that mock calls to `setTimeout` and `setInterval`.\n\nSee the [`vi.useFakeTimers` API section](/api/vi#vi-usefaketimers) for a more in depth detailed API description.\n\n## Example\n\n```js\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nfunction executeAfterTwoHours(func) {\n  setTimeout(func, 1000 * 60 * 60 * 2) // 2 hours\n}\n\nfunction executeEveryMinute(func) {\n  setInterval(func, 1000 * 60) // 1 minute\n}\n\nconst mock = vi.fn(() => console.log('executed'))\n\ndescribe('delayed execution', () => {\n  beforeEach(() => {\n    vi.useFakeTimers()\n  })\n  afterEach(() => {\n    vi.restoreAllMocks()\n  })\n  it('should execute the function', () => {\n    executeAfterTwoHours(mock)\n    vi.runAllTimers()\n    expect(mock).toHaveBeenCalledTimes(1)\n  })\n  it('should not execute the function', () => {\n    executeAfterTwoHours(mock)\n    // advancing by 2ms won't trigger the func\n    vi.advanceTimersByTime(2)\n    expect(mock).not.toHaveBeenCalled()\n  })\n  it('should execute every minute', () => {\n    executeEveryMinute(mock)\n    vi.advanceTimersToNextTimer()\n    expect(mock).toHaveBeenCalledTimes(1)\n    vi.advanceTimersToNextTimer()\n    expect(mock).toHaveBeenCalledTimes(2)\n  })\n})\n```\n"
  },
  {
    "path": "docs/guide/mocking.md",
    "content": "---\ntitle: Mocking | Guide\noutline: false\n---\n\n# Mocking\n\nWhen writing tests it's only a matter of time before you need to create a \"fake\" version of an internal — or external — service. This is commonly referred to as **mocking**. Vitest provides utility functions to help you out through its `vi` helper. You can import it from `vitest` or access it globally if [`global` configuration](/config/globals) is enabled.\n\n::: warning\nAlways remember to clear or restore mocks before or after each test run to undo mock state changes between runs! See [`mockReset`](/api/mock#mockreset) docs for more info.\n:::\n\nIf you are not familiar with `vi.fn`, `vi.mock` or `vi.spyOn` methods, check the [API section](/api/vi) first.\n\nVitest has a comprehensive list of guides regarding mocking:\n\n- [Mocking Classes](/guide/mocking/classes.md)\n- [Mocking Dates](/guide/mocking/dates.md)\n- [Mocking the File System](/guide/mocking/file-system.md)\n- [Mocking Functions](/guide/mocking/functions.md)\n- [Mocking Globals](/guide/mocking/globals.md)\n- [Mocking Modules](/guide/mocking/modules.md)\n- [Mocking Requests](/guide/mocking/requests.md)\n- [Mocking Timers](/guide/mocking/timers.md)\n\nFor a simpler and quicker way to get started with mocking, you can check the Cheat Sheet below.\n\n## Cheat Sheet\n\nI want to…\n\n### Mock exported variables\n```js [example.js]\nexport const getter = 'variable'\n```\n```ts [example.test.ts]\nimport * as exports from './example.js'\n\nvi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked')\n```\n\n::: warning\nThis will not work in the Browser Mode. For a workaround, see [Limitations](/guide/browser/#spying-on-module-exports).\n:::\n\n### Mock an exported function\n\n1. Example with `vi.mock`:\n\n::: warning\nDon't forget that a `vi.mock` call is hoisted to top of the file. It will always be executed before all imports.\n:::\n\n```ts [example.js]\nexport function method() {}\n```\n```ts\nimport { method } from './example.js'\n\nvi.mock('./example.js', () => ({\n  method: vi.fn()\n}))\n```\n\n2. Example with `vi.spyOn`:\n```ts\nimport * as exports from './example.js'\n\nvi.spyOn(exports, 'method').mockImplementation(() => {})\n```\n\n::: warning\n`vi.spyOn` example will not work in the Browser Mode. For a workaround, see [Limitations](/guide/browser/#spying-on-module-exports).\n:::\n\n### Mock an exported class implementation\n\n1. Example with a fake `class`:\n```ts [example.js]\nexport class SomeClass {}\n```\n```ts\nimport { SomeClass } from './example.js'\n\nvi.mock(import('./example.js'), () => {\n  const SomeClass = vi.fn(class FakeClass {\n    someMethod = vi.fn()\n  })\n  return { SomeClass }\n})\n```\n\n2. Example with `vi.spyOn`:\n\n```ts\nimport * as mod from './example.js'\n\nvi.spyOn(mod, 'SomeClass').mockImplementation(class FakeClass {\n  someMethod = vi.fn()\n})\n```\n\n::: warning\n`vi.spyOn` example will not work in the Browser Mode. For a workaround, see [Limitations](/guide/browser/#spying-on-module-exports).\n:::\n\n### Spy on an object returned from a function\n\n1. Example using cache:\n\n```ts [example.js]\nexport function useObject() {\n  return { method: () => true }\n}\n```\n\n```ts [useObject.js]\nimport { useObject } from './example.js'\n\nconst obj = useObject()\nobj.method()\n```\n\n```ts [useObject.test.js]\nimport { useObject } from './example.js'\n\nvi.mock(import('./example.js'), () => {\n  let _cache\n  const useObject = () => {\n    if (!_cache) {\n      _cache = {\n        method: vi.fn(),\n      }\n    }\n    // now every time that useObject() is called it will\n    // return the same object reference\n    return _cache\n  }\n  return { useObject }\n})\n\nconst obj = useObject()\n// obj.method was called inside some-path\nexpect(obj.method).toHaveBeenCalled()\n```\n\n### Mock part of a module\n\n```ts\nimport { mocked, original } from './some-path.js'\n\nvi.mock(import('./some-path.js'), async (importOriginal) => {\n  const mod = await importOriginal()\n  return {\n    ...mod,\n    mocked: vi.fn()\n  }\n})\noriginal() // has original behaviour\nmocked() // is a spy function\n```\n\n::: warning\nDon't forget that this only [mocks _external_ access](/guide/mocking/modules#mocking-modules-pitfalls). In this example, if `original` calls `mocked` internally, it will always call the function defined in the module, not in the mock factory.\n:::\n\n### Mock the current date\n\nTo mock `Date`'s time, you can use `vi.setSystemTime` helper function. This value will **not** automatically reset between different tests.\n\nBeware that using `vi.useFakeTimers` also changes the `Date`'s time.\n\n```ts\nconst mockDate = new Date(2022, 0, 1)\nvi.setSystemTime(mockDate)\nconst now = new Date()\nexpect(now.valueOf()).toBe(mockDate.valueOf())\n// reset mocked time\nvi.useRealTimers()\n```\n\n### Mock a global variable\n\nYou can set global variable by assigning a value to `globalThis` or using [`vi.stubGlobal`](/api/vi#vi-stubglobal) helper. When using `vi.stubGlobal`, it will **not** automatically reset between different tests, unless you enable [`unstubGlobals`](/config/unstubglobals) config option or call [`vi.unstubAllGlobals`](/api/vi#vi-unstuballglobals).\n\n```ts\nvi.stubGlobal('__VERSION__', '1.0.0')\nexpect(__VERSION__).toBe('1.0.0')\n```\n\n### Mock `import.meta.env`\n\n1. To change environmental variable, you can just assign a new value to it.\n\n::: warning\nThe environmental variable value will **_not_** automatically reset between different tests.\n:::\n\n```ts\nimport { beforeEach, expect, it } from 'vitest'\n\n// you can reset it in beforeEach hook manually\nconst originalViteEnv = import.meta.env.VITE_ENV\n\nbeforeEach(() => {\n  import.meta.env.VITE_ENV = originalViteEnv\n})\n\nit('changes value', () => {\n  import.meta.env.VITE_ENV = 'staging'\n  expect(import.meta.env.VITE_ENV).toBe('staging')\n})\n```\n\n2. If you want to automatically reset the value(s), you can use the `vi.stubEnv` helper with the [`unstubEnvs`](/config/unstubenvs) config option enabled (or call [`vi.unstubAllEnvs`](/api/vi#vi-unstuballenvs) manually in a `beforeEach` hook):\n\n```ts\nimport { expect, it, vi } from 'vitest'\n\n// before running tests \"VITE_ENV\" is \"test\"\nimport.meta.env.VITE_ENV === 'test'\n\nit('changes value', () => {\n  vi.stubEnv('VITE_ENV', 'staging')\n  expect(import.meta.env.VITE_ENV).toBe('staging')\n})\n\nit('the value is restored before running an other test', () => {\n  expect(import.meta.env.VITE_ENV).toBe('test')\n})\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    unstubEnvs: true,\n  },\n})\n```\n"
  },
  {
    "path": "docs/guide/open-telemetry.md",
    "content": "# Open Telemetry Support <Experimental /> {#open-telemetry-support}\n\n::: tip FEEDBACK\nPlease, leave feedback regarding this feature in a [GitHub Discussion](https://github.com/vitest-dev/vitest/discussions/9222).\n:::\n\n::: tip Example Project\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/opentelemetry)\n:::\n\n[OpenTelemetry](https://opentelemetry.io/) traces can be a useful tool to debug the performance and behavior of your application inside tests.\n\nIf enabled, Vitest integration generates spans that are scoped to your test's worker.\n\n::: warning\nOpenTelemetry initialization increases the startup time of every test unless Vitest runs without [isolation](/config/isolate). You can see it as the `vitest.runtime.traces` span inside `vitest.worker.start`.\n:::\n\nTo start using OpenTelemetry in Vitest, specify an SDK module path via [`experimental.openTelemetry.sdkPath`](/config/experimental#experimental-opentelemetry) and set `experimental.openTelemetry.enabled` to `true`. Vitest will automatically instrument the whole process and each individual test worker.\n\nMake sure to export the SDK as a default export, so that Vitest can flush the network requests before the process is closed. Note that Vitest doesn't automatically call `start`.\n\n## Quickstart\n\nBefore previewing your application traces, install required packages and specify the path to your instrumentation file in the config.\n\n```shell\nnpm i @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-proto\n```\n\n::: code-group\n```js{12} [otel.js]\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'\nimport { NodeSDK } from '@opentelemetry/sdk-node'\n\nconst sdk = new NodeSDK({\n  serviceName: 'vitest',\n  traceExporter: new OTLPTraceExporter(),\n  instrumentations: [getNodeAutoInstrumentations()],\n})\n\nsdk.start()\nexport default sdk\n```\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    experimental: {\n      openTelemetry: {\n        enabled: true,\n        sdkPath: './otel.js',\n      },\n    },\n  },\n})\n```\n:::\n\n::: danger FAKE TIMERS\nIf you are using fake timers, it is important to reset them before the test ends, otherwise traces might not be tracked properly.\n:::\n\nVitest doesn't process the `sdkPath` module, so it is important that the SDK can be imported within your Node.js environment. It is ideal to use the `.js` extension for this file. Using another extension will slow down your tests and may require providing additional Node.js arguments.\n\nIf you want to provide a TypeScript file, make sure to familiarize yourself with [TypeScript](https://nodejs.org/api/typescript.html#type-stripping) page in the Node.js documentation.\n\n## Custom Traces\n\nYou can use the OpenTelemetry API yourself to track certain operations in your code. Custom traces automatically inherit the Vitest OpenTelemetry context:\n\n```ts\nimport { trace } from '@opentelemetry/api'\nimport { test } from 'vitest'\nimport { db } from './src/db'\n\nconst tracer = trace.getTracer('vitest')\n\ntest('db connects properly', async () => {\n  // this is shown inside `vitest.test.runner.test.callback` span\n  await tracer.startActiveSpan('db.connect', () => db.connect())\n})\n```\n\n## Browser Mode\n\nWhen running tests in [browser mode](/guide/browser/), Vitest propagates trace context between Node.js and the browser. Node.js side traces (test orchestration, browser driver communication) are available without additional configuration.\n\nTo capture traces from the browser runtime, provide a browser-compatible SDK via `browserSdkPath`:\n\n```shell\nnpm i @opentelemetry/sdk-trace-web @opentelemetry/exporter-trace-otlp-proto\n```\n\n::: code-group\n```js [otel-browser.js]\nimport {\n  BatchSpanProcessor,\n  WebTracerProvider,\n} from '@opentelemetry/sdk-trace-web'\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'\n\nconst provider = new WebTracerProvider({\n  spanProcessors: [\n    new BatchSpanProcessor(new OTLPTraceExporter()),\n  ],\n})\n\nprovider.register()\nexport default provider\n```\n```js [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider: 'playwright',\n      instances: [{ browser: 'chromium' }],\n    },\n    experimental: {\n      openTelemetry: {\n        enabled: true,\n        sdkPath: './otel.js',\n        browserSdkPath: './otel-browser.js',\n      },\n    },\n  },\n})\n```\n:::\n\n::: warning ASYNC CONTEXT\nUnlike Node.js, browsers do not have automatic async context propagation. Vitest handles this internally for test execution, but custom spans in deeply nested async code may not propagate context automatically.\n:::\n\n## View Traces\n\nTo generate traces, run Vitest as usual. You can run Vitest in either watch mode or run mode. Vitest will call `sdk.shutdown()` manually after everything is finished to make sure traces are handled properly.\n\nYou can view traces using any of the open source or commercial products that support OpenTelemetry API. If you did not use OpenTelemetry before, we recommend starting with [Jaeger](https://www.jaegertracing.io/docs/2.11/getting-started/#all-in-one) because it is really easy to setup.\n\n<img src=\"/otel-jaeger.png\" alt=\"an example of open telemetry result in jaeger\" />\n\n## `@opentelemetry/api`\n\nVitest declares `@opentelemetry/api` as an optional peer dependency, which it uses internally to generate spans. When trace collection is not enabled, Vitest will not attempt to use this dependency.\n\nWhen configuring Vitest to use OpenTelemetry, you will typically install `@opentelemetry/sdk-node`, which includes `@opentelemetry/api` as a transitive dependency, thereby satisfying Vitest's peer dependency requirement. If you encounter an error indicating that `@opentelemetry/api` cannot be found, this typically means trace collection has not been enabled. If the error persists after proper configuration, you may need to install `@opentelemetry/api` explicitly.\n\n## Inter-Process Context Propagation\n\nVitest supports automatic context propagation from parent processes via the `TRACEPARENT` and `TRACESTATE` environment variables as defined in the [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/env-carriers.md). This is particularly useful when running Vitest as part of a larger distributed tracing system (e.g., CI/CD pipelines with OpenTelemetry instrumentation).\n"
  },
  {
    "path": "docs/guide/parallelism.md",
    "content": "---\ntitle: Parallelism | Guide\noutline: deep\n---\n\n# Parallelism\n\n## File Parallelism\n\nBy default, Vitest runs _test files_ in parallel. Depending on the specified `pool`, Vitest uses a different mechanism to parallelize test files:\n\n- `forks` (the default) and `vmForks` run tests in different [child processes](https://nodejs.org/api/child_process.html)\n- `threads` and `vmThreads` run tests in different [worker threads](https://nodejs.org/api/worker_threads.html)\n\nBoth \"child processes\" and \"worker threads\" are referred to as \"workers\". You can configure the number of running workers with [`maxWorkers`](/config/maxworkers) option.\n\nIf you have a lot of tests, it is usually faster to run them in parallel, but it also depends on the project, the environment and [isolation](/config/isolate) state. To disable file parallelisation, you can set [`fileParallelism`](/config/fileparallelism) to `false`. To learn more about possible performance improvements, read the [Performance Guide](/guide/improving-performance).\n\n## Test Parallelism\n\nUnlike _test files_, Vitest runs _tests_ in sequence. This means that tests inside a single test file will run in the order they are defined.\n\nVitest supports the [`concurrent`](/api/test#test-concurrent) option to run tests together. If this option is set, Vitest will group concurrent tests in the same _file_ (the number of simultaneously running tests depends on the [`maxConcurrency`](/config/maxconcurrency) option) and run them with [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all).\n\nThe hook execution order within a single group is also controlled by [`sequence.hooks`](/config/sequence#sequence-hooks). With `sequence.hooks: 'parallel'`, the execution is bounded by the same limit of [`maxConcurrency`](/config/maxconcurrency).\n\nVitest doesn't perform any smart analysis and doesn't create additional workers to run these tests. This means that the performance of your tests will improve only if you rely heavily on asynchronous operations. For example, these tests will still run one after another even though the `concurrent` option is specified. This is because they are synchronous:\n\n```ts\ntest.concurrent('the first test', () => {\n  expect(1).toBe(1)\n})\n\ntest.concurrent('the second test', () => {\n  expect(2).toBe(2)\n})\n```\n\nIf you wish to run all tests concurrently, you can set the [`sequence.concurrent`](/config/sequence#sequence-concurrent) option to `true`.\n"
  },
  {
    "path": "docs/guide/profiling-test-performance.md",
    "content": "# Profiling Test Performance\n\nWhen you run Vitest it reports multiple time metrics of your tests:\n\n> ```bash\n> RUN  v2.1.1 /x/vitest/examples/profiling\n>\n> ✓ test/prime-number.test.ts (1) 4517ms\n>   ✓ generate prime number 4517ms\n>\n> Test Files  1 passed (1)\n>      Tests  1 passed (1)\n>   Start at  09:32:53\n>   Duration  4.80s (transform 44ms, setup 0ms, import 35ms, tests 4.52s, environment 0ms)\n>   # Time metrics ^^\n> ```\n\n- Transform: How much time was spent transforming the files. See [File Transform](#file-transform).\n- Setup: Time spent for running the [`setupFiles`](/config/setupfiles) files.\n- Import: Time it took to import your test files and their dependencies. This also includes the time spent collecting all tests. Note that this doesn't include dynamic imports inside of tests.\n- Tests: Time spent for actually running the test cases.\n- Environment: Time spent for setting up the test [`environment`](/config/environment), for example JSDOM.\n\n## Test Runner\n\nIn cases where your test execution time is high, you can generate a profile of the test runner. See NodeJS documentation for following options:\n\n- [`--cpu-prof`](https://nodejs.org/api/cli.html#--cpu-prof)\n- [`--heap-prof`](https://nodejs.org/api/cli.html#--heap-prof)\n- [`--prof`](https://nodejs.org/api/cli.html#--prof)\n\n:::warning\nThe `--prof` option does not work with `pool: 'threads'` due to `node:worker_threads` limitations.\n:::\n\nTo pass these options to Vitest's test runner, define `execArgv` in your Vitest configuration:\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    fileParallelism: false,\n    execArgv: [\n      '--cpu-prof',\n      '--cpu-prof-dir=test-runner-profile',\n      '--heap-prof',\n      '--heap-prof-dir=test-runner-profile'\n    ],\n  },\n})\n```\n\nAfter the tests have run there should be a `test-runner-profile/*.cpuprofile` and `test-runner-profile/*.heapprofile` files generated. See [Inspecting profiling records](#inspecting-profiling-records) for instructions how to analyze these files.\n\nSee [Profiling | Examples](https://github.com/vitest-dev/vitest/tree/main/examples/profiling) for example.\n\n## Main Thread\n\nProfiling main thread is useful for debugging Vitest's Vite usage and [`globalSetup`](/config/globalsetup) files.\nThis is also where your Vite plugins are running.\n\n:::tip\nSee [Performance | Vite](https://vitejs.dev/guide/performance.html) for more tips about Vite specific profiling.\n\nWe recommend [`vite-plugin-inspect`](https://github.com/antfu-collective/vite-plugin-inspect) for profiling your Vite plugin performance.\n:::\n\nTo do this you'll need to pass arguments to the Node process that runs Vitest.\n\n```bash\n$ node --cpu-prof --cpu-prof-dir=main-profile ./node_modules/vitest/vitest.mjs --run\n#      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                  ^^^^^\n#               NodeJS arguments                                           Vitest arguments\n```\n\nAfter the tests have run there should be a `main-profile/*.cpuprofile` file generated. See [Inspecting profiling records](#inspecting-profiling-records) for instructions how to analyze these files.\n\n## File Transform\n\nThis profiling strategy is a good way to identify unnecessary transforms caused by [barrel files](https://vitejs.dev/guide/performance.html#avoid-barrel-files).\nIf these logs contain files that should not be loaded when your test is run, you might have barrel files that are importing files unnecessarily.\n\nYou can also use [Vitest UI](/guide/ui) to debug slowness caused by barrel file.\nThe example below shows how importing files without barrel file reduces amount of transformed files by ~85%.\n\n::: code-group\n``` [File tree]\n├── src\n│   └── utils\n│       ├── currency.ts\n│       ├── formatters.ts  <-- File to test\n│       ├── index.ts\n│       ├── location.ts\n│       ├── math.ts\n│       ├── time.ts\n│       └── users.ts\n├── test\n│   └── formatters.test.ts\n└── vitest.config.ts\n```\n```ts [example.test.ts]\nimport { expect, test } from 'vitest'\nimport { formatter } from '../src/utils' // [!code --]\nimport { formatter } from '../src/utils/formatters' // [!code ++]\n\ntest('formatter works', () => {\n  expect(formatter).not.toThrow()\n})\n```\n:::\n\n<img src=\"/module-graph-barrel-file.png\" alt=\"Vitest UI demonstrating barrel file issues\" />\n\nTo see how files are transformed, you can open the \"Module Info\" view in the UI:\n\n<img alt=\"The module info view for an inlined module\" img-light src=\"/ui/light-module-info.png\">\n<img alt=\"The module info view for an inlined module\" img-dark src=\"/ui/dark-module-info.png\">\n\n## File Import\n\nSome modules just take a long time to load. To identify which modules are the slowest, enable [`experimental.importDurations`](/config/experimental#experimental-importdurations) in your configuration:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    experimental: {\n      importDurations: {\n        print: true,\n      },\n    },\n  },\n})\n```\n\nThis will print a breakdown of the slowest imports after your tests finish:\n\n```bash\nImport Duration Breakdown (Top 10)\n\nModule                      Self     Total\nmy-test.test.ts              5ms    620ms [████████████████████]\ndate-fns/index.js          500ms    500ms [████████████████░░░░] # [!code error]\nsrc/utils/helpers.ts        10ms    120ms [████████░░░░░░░░░░░░]\n```\n\nYou can also use `--experimental.importDurations.print` from the CLI without changing your configuration:\n\n```bash\nvitest --experimental.importDurations.print\n```\n\nOnce you've identified the slow modules, there are several strategies to speed up imports:\n\n### Use Specific Entry Points\n\nMany libraries ship multiple entry points. Importing the main entry point (which is often a [barrel file](https://vitejs.dev/guide/performance.html#avoid-barrel-files)) can pull in far more code than you need.\n\nFor example, `date-fns` re-exports hundreds of functions from its main entry point. Instead of importing from the top-level module, import directly from the specific function:\n\n```ts\nimport { format } from 'date-fns' // [!code --]\nimport { format } from 'date-fns/format' // [!code ++]\n```\n\n### Use `resolve.alias` to Redirect Imports\n\nIf a dependency doesn't provide granular entry points, or if third-party code imports the heavy entry point, you can use [`resolve.alias`](https://vite.dev/config/shared-options#resolve-alias) to redirect imports to a lighter alternative:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  resolve: {\n    alias: [\n      {\n        find: /^date-fns$/,\n        replacement: join(dirname(require.resolve('date-fns/package.json')), 'index.cjs'),\n      },\n    ]\n  },\n})\n```\n\n### Use the Dependency Optimizer\n\nVitest can bundle external libraries into a single file using [`deps.optimizer`](/config/deps#deps-optimizer), which reduces the overhead of importing packages with many internal modules:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    deps: {\n      optimizer: {\n        ssr: {\n          enabled: true,\n          include: ['date-fns'],\n        },\n      },\n    },\n  },\n})\n```\n\nThis is especially effective for UI libraries and packages with deep import trees. Use `optimizer.ssr` for `node`/`edge` environments and `optimizer.client` for `jsdom`/`happy-dom` environments.\n\n## Code Coverage\n\nIf code coverage generation is slow on your project you can use `DEBUG=vitest:coverage` environment variable to enable performance logging.\n\n```bash\n$ DEBUG=vitest:coverage vitest --run --coverage\n\n RUN  v3.1.1 /x/vitest-example\n\n  vitest:coverage Reading coverage results 2/2\n  vitest:coverage Converting 1/2\n  vitest:coverage 4 ms /x/src/multiply.ts\n  vitest:coverage Converting 2/2\n  vitest:coverage 552 ms /x/src/add.ts\n  vitest:coverage Uncovered files 1/2\n  vitest:coverage File \"/x/src/large-file.ts\" is taking longer than 3s # [!code error]\n  vitest:coverage 3027 ms /x/src/large-file.ts\n  vitest:coverage Uncovered files 2/2\n  vitest:coverage 4 ms /x/src/untested-file.ts\n  vitest:coverage Generate coverage total time 3521 ms\n```\n\nThis profiling approach is great for detecting large files that are accidentally picked by coverage providers.\nFor example if your configuration is accidentally including large built minified Javascript files in code coverage, they should appear in logs.\nIn these cases you might want to adjust your [`coverage.include`](/config/coverage#coverage-include) and [`coverage.exclude`](/config/coverage#coverage-exclude) options.\n\n## Inspecting Profiling Records\n\nYou can inspect the contents of `*.cpuprofile` and `*.heapprofile` with various tools. See list below for examples.\n\n- [Speedscope](https://www.speedscope.app/)\n- [Performance Profiling JavaScript in Visual Studio Code](https://code.visualstudio.com/docs/nodejs/profiling#_analyzing-a-profile)\n- [Profile Node.js performance with the Performance panel | developer.chrome.com](https://developer.chrome.com/docs/devtools/performance/nodejs#analyze)\n- [Memory panel overview | developer.chrome.com](https://developer.chrome.com/docs/devtools/memory-problems/heap-snapshots#view_snapshots)\n"
  },
  {
    "path": "docs/guide/projects.md",
    "content": "---\ntitle: Test Projects | Guide\n---\n\n# Test Projects\n\n::: tip Sample Project\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/projects) - [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/projects?initialPath=__vitest__/)\n\n:::\n\n::: warning\nThis feature is also known as a `workspace`. The `workspace` is deprecated since 3.2 and replaced with the `projects` configuration. They are functionally the same.\n:::\n\nVitest provides a way to define multiple project configurations within a single Vitest process. This feature is particularly useful for monorepo setups but can also be used to run tests with different configurations, such as `resolve.alias`, `plugins`, or `test.browser` and more.\n\n## Defining Projects\n\nYou can define projects in your root [config](/config/):\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: ['packages/*'],\n  },\n})\n```\n\nProject configurations are inlined configs, files, or glob patterns referencing your projects. For example, if you have a folder named `packages` that contains your projects, you can define an array in your root Vitest config:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: ['packages/*'],\n  },\n})\n```\n\nVitest will treat every folder in `packages` as a separate project even if it doesn't have a config file inside. If a project entry resolves to a file (either from a glob pattern or a direct file path), Vitest will validate that the name either:\n\n- starts with `vitest.config` or `vite.config` (for example, `vitest.config.unit.ts`)\n- or matches `vitest.<name>.config.*` / `vite.<name>.config.*`, where `<name>` can contain letters, numbers, `_`, and `-`\n\nFor example, these config files are valid:\n\n- `vitest.config.ts`\n- `vite.config.js`\n- `vitest.unit.config.ts`\n- `vitest.e2e-node.config.ts`\n- `vite.e2e.config.js`\n- `vitest.config.unit.js`\n- `vite.config.e2e.js`\n\nTo exclude folders and files, you can use the negation pattern:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    // include all folders inside \"packages\" except \"excluded\"\n    projects: [\n      'packages/*',\n      '!packages/excluded'\n    ],\n  },\n})\n```\n\nIf you have a nested structure where some folders need to be projects, but other folders have their own subfolders, you have to use brackets to avoid matching the parent folder:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\n// For example, this will create projects:\n// packages/a\n// packages/b\n// packages/business/c\n// packages/business/d\n// Notice that \"packages/business\" is not a project itself\n\nexport default defineConfig({\n  test: {\n    projects: [\n      // matches every folder inside \"packages\" except \"business\"\n      'packages/!(business)',\n      // matches every folder inside \"packages/business\"\n      'packages/business/*',\n    ],\n  },\n})\n```\n\n::: warning\nVitest does not treat the root `vitest.config` file as a project unless it is explicitly specified in the configuration. Consequently, the root configuration will only influence global options such as `reporters` and `coverage`. Note that Vitest will always run certain plugin hooks, like `apply`, `config`, `configResolved` or `configureServer`, specified in the root config file. Vitest also uses the same plugins to execute global setups and custom coverage provider.\n:::\n\nYou can also reference projects with their config files:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: ['packages/*/vitest.config.{e2e,unit}.ts'],\n  },\n})\n```\n\nThis pattern will only include projects with a `vitest.config` file that contains `e2e` or `unit` before the extension.\n\nYou can also define projects using inline configuration. The configuration supports both syntaxes simultaneously.\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      // matches every folder and file inside the `packages` folder\n      'packages/*',\n      {\n        // add \"extends: true\" to inherit the options from the root config\n        extends: true,\n        test: {\n          include: ['tests/**/*.{browser}.test.{ts,js}'],\n          // it is recommended to define a name when using inline configs\n          name: 'happy-dom',\n          environment: 'happy-dom',\n        }\n      },\n      {\n        test: {\n          include: ['tests/**/*.{node}.test.{ts,js}'],\n          // color of the name label can be changed\n          name: { label: 'node', color: 'green' },\n          environment: 'node',\n        }\n      }\n    ]\n  }\n})\n```\n\n::: warning\nAll projects must have unique names; otherwise, Vitest will throw an error. If a name is not provided in the inline configuration, Vitest will assign a number. For project configurations defined with glob syntax, Vitest will default to using the \"name\" property in the nearest `package.json` file or, if none exists, the folder name.\n:::\n\nProjects do not support all configuration properties. For better type safety, use the `defineProject` method instead of `defineConfig` within project configuration files:\n\n```ts twoslash [packages/a/vitest.config.ts]\n// @errors: 2769\nimport { defineProject } from 'vitest/config'\n\nexport default defineProject({\n  test: {\n    environment: 'jsdom',\n    // \"reporters\" is not supported in a project config,\n    // so it will show an error\n    reporters: ['json']\n  }\n})\n```\n\n## Running Tests\n\nTo run tests, define a script in your root `package.json`:\n\n```json [package.json]\n{\n  \"scripts\": {\n    \"test\": \"vitest\"\n  }\n}\n```\n\nNow tests can be run using your package manager:\n\n::: code-group\n```bash [npm]\nnpm run test\n```\n```bash [yarn]\nyarn test\n```\n```bash [pnpm]\npnpm run test\n```\n```bash [bun]\nbun run test\n```\n:::\n\nIf you need to run tests only inside a single project, use the `--project` CLI option:\n\n::: code-group\n```bash [npm]\nnpm run test --project e2e\n```\n```bash [yarn]\nyarn test --project e2e\n```\n```bash [pnpm]\npnpm run test --project e2e\n```\n```bash [bun]\nbun run test --project e2e\n```\n:::\n\n::: tip\nCLI option `--project` can be used multiple times to filter out several projects:\n\n::: code-group\n```bash [npm]\nnpm run test --project e2e --project unit\n```\n```bash [yarn]\nyarn test --project e2e --project unit\n```\n```bash [pnpm]\npnpm run test --project e2e --project unit\n```\n```bash [bun]\nbun run test --project e2e --project unit\n```\n:::\n\n## Configuration\n\nNone of the configuration options are inherited from the root-level config file. You can create a shared config file and merge it with the project config yourself:\n\n```ts [packages/a/vitest.config.ts]\nimport { defineProject, mergeConfig } from 'vitest/config'\nimport configShared from '../vitest.shared.js'\n\nexport default mergeConfig(\n  configShared,\n  defineProject({\n    test: {\n      environment: 'jsdom',\n    }\n  })\n)\n```\n\nAdditionally, you can use the `extends` option to inherit from your root-level configuration. All options will be merged.\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n  test: {\n    pool: 'threads',\n    projects: [\n      {\n        // will inherit options from this config like plugins and pool\n        extends: true,\n        test: {\n          name: 'unit',\n          include: ['**/*.unit.test.ts'],\n        },\n      },\n      {\n        // won't inherit any options from this config\n        // this is the default behaviour\n        extends: false,\n        test: {\n          name: 'integration',\n          include: ['**/*.integration.test.ts'],\n        },\n      },\n    ],\n  },\n})\n```\n\n::: danger Unsupported Options\nSome of the configuration options are not allowed in a project config. Most notably:\n\n- `coverage`: coverage is done for the whole process\n- `reporters`: only root-level reporters can be supported\n- `resolveSnapshotPath`: only root-level resolver is respected\n- all other options that don't affect test runners\n\nAll configuration options that are not supported inside a project configuration are marked with a <CRoot /> icon next to their name. They can only be defined once in the root config file.\n:::\n"
  },
  {
    "path": "docs/guide/recipes.md",
    "content": "---\ntitle: Recipes | Guide\n---\n\n# Recipes\n\n## Disabling Isolation for Specific Test Files Only\n\nYou can speed up your test run by disabling isolation for specific set of files by specifying `isolate` per `projects` entries:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          // Non-isolated unit tests\n          name: 'Unit tests',\n          isolate: false,\n          exclude: ['**.integration.test.ts'],\n        },\n      },\n      {\n        test: {\n          // Isolated integration tests\n          name: 'Integration tests',\n          include: ['**.integration.test.ts'],\n        },\n      },\n    ],\n  },\n})\n```\n\n## Parallel and Sequential Test Files\n\nYou can split test files into parallel and sequential groups by using `projects` option:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: 'Parallel',\n          exclude: ['**.sequential.test.ts'],\n        },\n      },\n      {\n        test: {\n          name: 'Sequential',\n          include: ['**.sequential.test.ts'],\n          fileParallelism: false,\n        },\n      },\n    ],\n  },\n})\n```\n"
  },
  {
    "path": "docs/guide/reporters.md",
    "content": "---\ntitle: Reporters | Guide\noutline: deep\n---\n\n# Reporters\n\nVitest provides several built-in reporters to display test output in different formats, as well as the ability to use custom reporters. You can select different reporters either by using the `--reporter` command line option, or by including a `reporters` property in your [configuration file](/config/reporters). If no reporter is specified, Vitest will use the `default` reporter as described below.\n\nUsing reporters via command line:\n\n```bash\nnpx vitest --reporter=verbose\n```\n\nUsing reporters via [`vitest.config.ts`](/config/):\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    reporters: ['verbose']\n  },\n})\n```\n\nSome reporters can be customized by passing additional options to them. Reporter specific options are described in sections below.\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: [\n      'default',\n      ['junit', { suiteName: 'UI tests' }]\n    ],\n  },\n})\n```\n\n## Reporter Output\n\nBy default, Vitest's reporters will print their output to the terminal. When using the `json`, `html` or `junit` reporters, you can instead write your tests' output to a file by including an `outputFile` [configuration option](/config/outputfile) either in your Vite configuration file or via CLI.\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=json --outputFile=./test-output.json\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['json'],\n    outputFile: './test-output.json'\n  },\n})\n```\n:::\n\n## Combining Reporters\n\nYou can use multiple reporters simultaneously to print your test results in different formats. For example:\n\n```bash\nnpx vitest --reporter=json --reporter=default\n```\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: ['json', 'default'],\n    outputFile: './test-output.json'\n  },\n})\n```\n\nThe above example will both print the test results to the terminal in the default style and write them as JSON to the designated output file.\n\nWhen using multiple reporters, it's also possible to designate multiple output files, as follows:\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: ['junit', 'json', 'verbose'],\n    outputFile: {\n      junit: './junit-report.xml',\n      json: './json-report.json',\n    },\n  },\n})\n```\n\nThis example will write separate JSON and XML reports as well as printing a verbose report to the terminal.\n\n## Built-in Reporters\n\n### Default Reporter\n\nBy default (i.e. if no reporter is specified), Vitest will display summary of running tests and their status at the bottom. Once a suite passes, its status will be reported on top of the summary.\n\n::: tip\nWhen Vitest detects it is running inside an AI coding agent, the [`agent`](#agent-reporter) reporter is used instead to reduce output and minimize token usage. You can override this by explicitly configuring the [`reporters`](/config/reporters) option.\n:::\n\nYou can disable the summary by configuring the reporter:\n\n:::code-group\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['default', { summary: false }]\n    ]\n  },\n})\n```\n:::\n\nExample output for tests in progress:\n\n```bash\n ✓ test/example-1.test.ts (5 tests | 1 skipped) 306ms\n ✓ test/example-2.test.ts (5 tests | 1 skipped) 307ms\n\n ❯ test/example-3.test.ts 3/5\n ❯ test/example-4.test.ts 1/5\n\n Test Files 2 passed (4)\n      Tests 10 passed | 3 skipped (65)\n   Start at 11:01:36\n   Duration 2.00s\n```\n\nFinal output after tests have finished:\n\n```bash\n ✓ test/example-1.test.ts (5 tests | 1 skipped) 306ms\n ✓ test/example-2.test.ts (5 tests | 1 skipped) 307ms\n ✓ test/example-3.test.ts (5 tests | 1 skipped) 307ms\n ✓ test/example-4.test.ts (5 tests | 1 skipped) 307ms\n\n Test Files  4 passed (4)\n      Tests  16 passed | 4 skipped (20)\n   Start at  12:34:32\n   Duration  1.26s (transform 35ms, setup 1ms, collect 90ms, tests 1.47s, environment 0ms, prepare 267ms)\n```\n\nIf there is only one test file running, Vitest will output the full test tree of that file, similar to the [`tree`](#tree-reporter) reporter. The default reporter will also print the test tree if there is at least one failed test in the file.\n\n```bash\n✓ __tests__/file1.test.ts (2) 725ms\n   ✓ first test file (2) 725ms\n     ✓ 2 + 2 should equal 4\n     ✓ 4 - 2 should equal 2\n\n Test Files  1 passed (1)\n      Tests  2 passed (2)\n   Start at  12:34:32\n   Duration  1.26s (transform 35ms, setup 1ms, collect 90ms, tests 1.47s, environment 0ms, prepare 267ms)\n```\n\n### Verbose Reporter\n\nThe verbose reporter prints every test case once it is finished. It does not report suites or files separately. If `--includeTaskLocation` is enabled, it will also include the location of each test in the output. Similar to `default` reporter, you can disable the summary by configuring the reporter.\n\nIn addition to this, the `verbose` reporter prints test error messages right away. The full test error is reported when the test run is finished.\n\nThis is the only terminal reporter that reports [annotations](/guide/test-annotations) when the test doesn't fail.\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=verbose\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['verbose', { summary: false }]\n    ]\n  },\n})\n```\n:::\n\nExample output:\n\n```bash\n✓ __tests__/file1.test.ts > first test file > 2 + 2 should equal 4 1ms\n✓ __tests__/file1.test.ts > first test file > 4 - 2 should equal 2 1ms\n✓ __tests__/file2.test.ts > second test file > 1 + 1 should equal 2 1ms\n✓ __tests__/file2.test.ts > second test file > 2 - 1 should equal 1 1ms\n\n Test Files  2 passed (2)\n      Tests  4 passed (4)\n   Start at  12:34:32\n   Duration  1.26s (transform 35ms, setup 1ms, collect 90ms, tests 1.47s, environment 0ms, prepare 267ms)\n```\n\nAn example with `--includeTaskLocation`:\n\n```bash\n✓ __tests__/file1.test.ts:2:1 > first test file > 2 + 2 should equal 4 1ms\n✓ __tests__/file1.test.ts:3:1 > first test file > 4 - 2 should equal 2 1ms\n✓ __tests__/file2.test.ts:2:1 > second test file > 1 + 1 should equal 2 1ms\n✓ __tests__/file2.test.ts:3:1 > second test file > 2 - 1 should equal 1 1ms\n\n Test Files  2 passed (2)\n      Tests  4 passed (4)\n   Start at  12:34:32\n   Duration  1.26s (transform 35ms, setup 1ms, collect 90ms, tests 1.47s, environment 0ms, prepare 267ms)\n```\n\n### Tree Reporter\n\nThe tree reporter is same as `default` reporter, but it also displays each individual test after the suite has finished. Similar to `default` reporter, you can disable the summary by configuring the reporter.\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=tree\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['tree', { summary: false }]\n    ]\n  },\n})\n```\n:::\n\nExample output for tests in progress with default `slowTestThreshold: 300`:\n\n```bash\n ✓ __tests__/example-1.test.ts (2) 725ms\n   ✓ first test file (2) 725ms\n     ✓ 2 + 2 should equal 4\n     ✓ 4 - 2 should equal 2\n\n ❯ test/example-2.test.ts 3/5\n   ↳ should run longer than three seconds 1.57s\n ❯ test/example-3.test.ts 1/5\n\n Test Files 2 passed (4)\n      Tests 10 passed | 3 skipped (65)\n   Start at 11:01:36\n   Duration 2.00s\n```\n\nExample of final terminal output for a passing test suite:\n\n```bash\n✓ __tests__/file1.test.ts (2) 725ms\n   ✓ first test file (2) 725ms\n     ✓ 2 + 2 should equal 4\n     ✓ 4 - 2 should equal 2\n✓ __tests__/file2.test.ts (2) 746ms\n  ✓ second test file (2) 746ms\n    ✓ 1 + 1 should equal 2\n    ✓ 2 - 1 should equal 1\n\n Test Files  2 passed (2)\n      Tests  4 passed (4)\n   Start at  12:34:32\n   Duration  1.26s (transform 35ms, setup 1ms, collect 90ms, tests 1.47s, environment 0ms, prepare 267ms)\n```\n\n### Dot Reporter\n\nPrints a single dot for each completed test to provide minimal output while still showing all tests that have run. Details are only provided for failed tests, along with the summary for the suite.\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=dot\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['dot']\n  },\n})\n```\n:::\n\nExample terminal output for a passing test suite:\n\n```bash\n....\n\n Test Files  2 passed (2)\n      Tests  4 passed (4)\n   Start at  12:34:32\n   Duration  1.26s (transform 35ms, setup 1ms, collect 90ms, tests 1.47s, environment 0ms, prepare 267ms)\n```\n\n### JUnit Reporter\n\nOutputs a report of the test results in JUnit XML format. Can either be printed to the terminal or written to an XML file using the [`outputFile`](/config/outputfile) configuration option.\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=junit\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['junit']\n  },\n})\n```\n:::\n\nExample of a JUnit XML report:\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"2\" failures=\"1\" errors=\"0\" time=\"0.503\">\n    <testsuite name=\"__tests__/test-file-1.test.ts\" timestamp=\"2023-10-19T17:41:58.580Z\" hostname=\"My-Computer.local\" tests=\"2\" failures=\"1\" errors=\"0\" skipped=\"0\" time=\"0.013\">\n        <testcase classname=\"__tests__/test-file-1.test.ts\" name=\"first test file &gt; 2 + 2 should equal 4\" time=\"0.01\">\n            <failure message=\"expected 5 to be 4 // Object.is equality\" type=\"AssertionError\">\nAssertionError: expected 5 to be 4 // Object.is equality\n ❯ __tests__/test-file-1.test.ts:20:28\n            </failure>\n        </testcase>\n        <testcase classname=\"__tests__/test-file-1.test.ts\" name=\"first test file &gt; 4 - 2 should equal 2\" time=\"0\">\n        </testcase>\n    </testsuite>\n</testsuites>\n```\n\nThe outputted XML contains nested `testsuites` and `testcase` tags. These can also be customized via reporter options `suiteName` and `classnameTemplate`. `classnameTemplate` can either be a template string or a function.\n\nThe supported placeholders for the `classnameTemplate` option are:\n- filename\n- filepath\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['junit', { suiteName: 'custom suite name', classnameTemplate: 'filename:{filename} - filepath:{filepath}' }]\n    ]\n  },\n})\n```\n\n### JSON Reporter\n\nGenerates a report of the test results in a JSON format compatible with Jest's `--json` option. Can either be printed to the terminal or written to a file using the [`outputFile`](/config/outputfile) configuration option.\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=json\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['json']\n  },\n})\n```\n:::\n\nExample of a JSON report:\n\n```json\n{\n  \"numTotalTestSuites\": 4,\n  \"numPassedTestSuites\": 2,\n  \"numFailedTestSuites\": 1,\n  \"numPendingTestSuites\": 1,\n  \"numTotalTests\": 4,\n  \"numPassedTests\": 1,\n  \"numFailedTests\": 1,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"startTime\": 1697737019307,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"\",\n            \"first test file\"\n          ],\n          \"fullName\": \" first test file 2 + 2 should equal 4\",\n          \"status\": \"failed\",\n          \"title\": \"2 + 2 should equal 4\",\n          \"duration\": 9,\n          \"failureMessages\": [\n            \"expected 5 to be 4 // Object.is equality\"\n          ],\n          \"location\": {\n            \"line\": 20,\n            \"column\": 28\n          },\n          \"meta\": {}\n        }\n      ],\n      \"startTime\": 1697737019787,\n      \"endTime\": 1697737019797,\n      \"status\": \"failed\",\n      \"message\": \"\",\n      \"name\": \"/root-directory/__tests__/test-file-1.test.ts\"\n    }\n  ],\n  \"coverageMap\": {}\n}\n```\n\n::: info\nSince Vitest 3, the JSON reporter includes coverage information in `coverageMap` if coverage is enabled.\n:::\n\n### HTML Reporter\n\nGenerates an HTML file to view test results through an interactive [GUI](/guide/ui). After the file has been generated, Vitest will keep a local development server running and provide a link to view the report in a browser.\n\nOutput file can be specified using the [`outputFile`](/config/outputfile) configuration option. If no `outputFile` option is provided, a new HTML file will be created.\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=html\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['html']\n  },\n})\n```\n:::\n\n::: tip\nThis reporter requires installed [`@vitest/ui`](/guide/ui) package.\n:::\n\n### TAP Reporter\n\nOutputs a report following [Test Anything Protocol](https://testanything.org/) (TAP).\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=tap\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['tap']\n  },\n})\n```\n:::\n\nExample of a TAP report:\n```bash\nTAP version 13\n1..1\nnot ok 1 - __tests__/test-file-1.test.ts # time=14.00ms {\n    1..1\n    not ok 1 - first test file # time=13.00ms {\n        1..2\n        not ok 1 - 2 + 2 should equal 4 # time=11.00ms\n            ---\n            error:\n                name: \"AssertionError\"\n                message: \"expected 5 to be 4 // Object.is equality\"\n            at: \"/root-directory/__tests__/test-file-1.test.ts:20:28\"\n            actual: \"5\"\n            expected: \"4\"\n            ...\n        ok 2 - 4 - 2 should equal 2 # time=1.00ms\n    }\n}\n```\n\n### TAP Flat Reporter\n\nOutputs a TAP flat report. Like the `tap` reporter, test results are formatted to follow TAP standards, but test suites are formatted as a flat list rather than a nested hierarchy.\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=tap-flat\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['tap-flat']\n  },\n})\n```\n:::\n\nExample of a TAP flat report:\n```bash\nTAP version 13\n1..2\nnot ok 1 - __tests__/test-file-1.test.ts > first test file > 2 + 2 should equal 4 # time=11.00ms\n    ---\n    error:\n        name: \"AssertionError\"\n        message: \"expected 5 to be 4 // Object.is equality\"\n    at: \"/root-directory/__tests__/test-file-1.test.ts:20:28\"\n    actual: \"5\"\n    expected: \"4\"\n    ...\nok 2 - __tests__/test-file-1.test.ts > first test file > 4 - 2 should equal 2 # time=0.00ms\n```\n\n### Hanging Process Reporter\n\nDisplays a list of hanging processes, if any are preventing Vitest from exiting safely. The `hanging-process` reporter does not itself display test results, but can be used in conjunction with another reporter to monitor processes while tests run. Using this reporter can be resource-intensive, so should generally be reserved for debugging purposes in situations where Vitest consistently cannot exit the process.\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=hanging-process\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['hanging-process']\n  },\n})\n```\n:::\n\n### GitHub Actions Reporter {#github-actions-reporter}\n\nOutput [workflow commands](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message)\nto provide annotations for test failures. This reporter is automatically enabled when the `reporters` option is not configured and `process.env.GITHUB_ACTIONS === 'true'` (on GitHub Actions environment).\n\n<img alt=\"GitHub Actions\" img-dark src=\"https://github.com/vitest-dev/vitest/assets/4232207/336cddc2-df6b-4b8a-8e72-4d00010e37f5\">\n<img alt=\"GitHub Actions\" img-light src=\"https://github.com/vitest-dev/vitest/assets/4232207/ce8447c1-0eab-4fe1-abef-d0d322290dca\">\n\nIf you configure reporters, you need to explicitly add `github-actions`.\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: process.env.GITHUB_ACTIONS === 'true' ? ['dot', 'github-actions'] : ['dot'],\n  },\n})\n```\n\nYou can customize the file paths that are printed in [GitHub's annotation command format](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions) by using the `onWritePath` option. This is useful when running Vitest in a containerized environment, such as Docker, where the file paths may not match the paths in the GitHub Actions environment.\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: process.env.GITHUB_ACTIONS === 'true'\n      ? [\n          'default',\n          ['github-actions', { onWritePath(path) {\n            return path.replace(/^\\/app\\//, `${process.env.GITHUB_WORKSPACE}/`)\n          } }],\n        ]\n      : ['default'],\n  },\n})\n```\n\nIf you are using [Annotations API](/guide/test-annotations), the reporter will automatically inline them in the GitHub UI. You can disable this by setting `displayAnnotations` option to `false`:\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['github-actions', { displayAnnotations: false }],\n    ],\n  },\n})\n```\n\nThe GitHub Actions reporter automatically generates a [Job Summary](https://github.blog/news-insights/product-news/supercharging-github-actions-with-job-summaries/) with an overview of your test results. The summary includes test file and test case statistics, and highlights flaky tests that required retries.\n\n<img alt=\"GitHub Actions Job Summary\" img-dark src=\"/github-actions-job-summary-dark.png\">\n<img alt=\"GitHub Actions Job Summary\" img-light src=\"/github-actions-job-summary-light.png\">\n\nThe job summary is enabled by default and writes to the path specified by `$GITHUB_STEP_SUMMARY`. You can override it by using the `jobSummary.outputPath` option:\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['github-actions', {\n        jobSummary: {\n          outputPath: '/home/runner/jobs/summary/step',\n        },\n      }],\n    ],\n  },\n})\n```\n\nTo disable the job summary:\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['github-actions', { jobSummary: { enabled: false } }],\n    ],\n  },\n})\n```\n\nThe flaky tests section of the summary includes permalink URLs that link test names directly to the relevant source lines on GitHub. These links are generated automatically using environment variables that GitHub Actions provides (`$GITHUB_REPOSITORY`, `$GITHUB_SHA`, and `$GITHUB_WORKSPACE`), so no configuration is needed in most cases.\n\nIf you need to override these values — for example, when running in a container or a custom environment — you can customize them via the `fileLinks` option:\n\n- `repository`: the GitHub repository in `owner/repo` format. Defaults to `process.env.GITHUB_REPOSITORY`.\n- `commitHash`: the commit SHA to use in permalink URLs. Defaults to `process.env.GITHUB_SHA`.\n- `workspacePath`: the absolute path to the root of the repository on disk. Used to compute relative file paths for the permalink URLs. Defaults to `process.env.GITHUB_WORKSPACE`.\n\nAll three values must be available for the links to be generated.\n\n```ts\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['github-actions', {\n        jobSummary: {\n          fileLinks: {\n            repository: 'owner/repo',\n            commitHash: 'abcdefg',\n            workspacePath: '/home/runner/work/repo/',\n          },\n        },\n      }],\n    ],\n  },\n})\n```\n\n### Agent Reporter\n\nOutputs a minimal report optimized for AI coding assistants and LLM-based workflows. Only failed tests and their error messages are displayed. Console logs from passing tests and the summary section are suppressed to reduce token usage.\n\nThis reporter is automatically enabled when no `reporters` option is configured and Vitest detects it is running inside an AI coding agent. If you configure custom reporters, you can explicitly add `agent`:\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=agent\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['agent']\n  },\n})\n```\n:::\n\n### Blob Reporter\n\nStores test results on the machine so they can be later merged using [`--merge-reports`](/guide/cli#merge-reports) command.\nBy default, stores all results in `.vitest-reports` folder, but can be overridden with `--outputFile` or `--outputFile.blob` flags.\n\n```bash\nnpx vitest --reporter=blob --outputFile=reports/blob-1.json\n```\n\nWe recommend using this reporter if you are running Vitest on different machines with the [`--shard`](/guide/cli#shard) flag.\nAll blob reports can be merged into any report by using `--merge-reports` command at the end of your CI pipeline:\n\n```bash\nnpx vitest --merge-reports=reports --reporter=json --reporter=default\n```\n\nBlob reporter output doesn't include file-based [attachments](/api/advanced/artifacts.html#testattachment).\nMake sure to merge [`attachmentsDir`](/config/attachmentsdir) separately alongside blob reports on CI when using this feature.\n\n::: tip\nBoth `--reporter=blob` and `--merge-reports` do not work in watch mode.\n:::\n\n## Custom Reporters\n\nYou can use third-party custom reporters installed from NPM by specifying their package name in the reporters' option:\n\n:::code-group\n```bash [CLI]\nnpx vitest --reporter=some-published-vitest-reporter\n```\n\n```ts [vitest.config.ts]\nexport default defineConfig({\n  test: {\n    reporters: ['some-published-vitest-reporter']\n  },\n})\n```\n:::\n\nAdditionally, you can define your own [custom reporters](/guide/advanced/reporters) and use them by specifying their file path:\n\n```bash\nnpx vitest --reporter=./path/to/reporter.ts\n```\n\nCustom reporters should implement the [Reporter interface](https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/node/types/reporter.ts).\n"
  },
  {
    "path": "docs/guide/snapshot.md",
    "content": "---\ntitle: Snapshot | Guide\n---\n\n# Snapshot\n\n<CourseLink href=\"https://vueschool.io/lessons/snapshots-in-vitest?friend=vueuse\">Learn Snapshot by video from Vue School</CourseLink>\n\nSnapshot tests are a very useful tool whenever you want to make sure the output of your functions does not change unexpectedly.\n\nWhen using snapshot, Vitest will take a snapshot of the given value, then compare it to a reference snapshot file stored alongside the test. The test will fail if the two snapshots do not match: either the change is unexpected, or the reference snapshot needs to be updated to the new version of the result.\n\n## Use Snapshots\n\nTo snapshot a value, you can use the [`toMatchSnapshot()`](/api/expect#tomatchsnapshot) from `expect()` API:\n\n```ts\nimport { expect, it } from 'vitest'\n\nit('toUpperCase', () => {\n  const result = toUpperCase('foobar')\n  expect(result).toMatchSnapshot()\n})\n```\n\nThe first time this test is run, Vitest creates a snapshot file that looks like this:\n\n```js\n// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports['toUpperCase 1'] = '\"FOOBAR\"'\n```\n\nThe snapshot artifact should be committed alongside code changes, and reviewed as part of your code review process. On subsequent test runs, Vitest will compare the rendered output with the previous snapshot. If they match, the test will pass. If they don't match, either the test runner found a bug in your code that should be fixed, or the implementation has changed and the snapshot needs to be updated.\n\n::: warning\nWhen using Snapshots with async concurrent tests, `expect` from the local [Test Context](/guide/test-context) must be used to ensure the right test is detected.\n:::\n\n## Inline Snapshots\n\nSimilarly, you can use the [`toMatchInlineSnapshot()`](/api/expect#tomatchinlinesnapshot) to store the snapshot inline within the test file.\n\n```ts\nimport { expect, it } from 'vitest'\n\nit('toUpperCase', () => {\n  const result = toUpperCase('foobar')\n  expect(result).toMatchInlineSnapshot()\n})\n```\n\nInstead of creating a snapshot file, Vitest will modify the test file directly to update the snapshot as a string:\n\n```ts\nimport { expect, it } from 'vitest'\n\nit('toUpperCase', () => {\n  const result = toUpperCase('foobar')\n  expect(result).toMatchInlineSnapshot('\"FOOBAR\"')\n})\n```\n\nThis allows you to see the expected output directly without jumping across different files.\n\n::: warning\nWhen using Snapshots with async concurrent tests, `expect` from the local [Test Context](/guide/test-context) must be used to ensure the right test is detected.\n:::\n\n## Updating Snapshots\n\nWhen the received value doesn't match the snapshot, the test fails and shows you the difference between them. When the snapshot change is expected, you may want to update the snapshot from the current state.\n\nIn watch mode, you can press the `u` key in the terminal to update the failed snapshot directly.\n\nOr you can use the `--update` or `-u` flag in the CLI to make Vitest update snapshots.\n\n```bash\nvitest -u\n```\n\n### CI behavior\n\nBy default, Vitest does not write snapshots in CI (`process.env.CI` is truthy) and any snapshot mismatches, missing snapshots, and obsolete snapshots fail the run. See [`update`](/config/update) for the details.\n\nAn **obsolete snapshot** is a snapshot entry (or snapshot file) that no longer matches any collected test. This usually happens after removing or renaming tests.\n\n## File Snapshots\n\nWhen calling `toMatchSnapshot()`, we store all snapshots in a formatted snap file. That means we need to escape some characters (namely the double-quote `\"` and backtick `` ` ``) in the snapshot string. Meanwhile, you might lose the syntax highlighting for the snapshot content (if they are in some language).\n\nIn light of this, we introduced [`toMatchFileSnapshot()`](/api/expect#tomatchfilesnapshot) to explicitly match against a file. This allows you to assign any file extension to the snapshot file, and makes them more readable.\n\n```ts\nimport { expect, it } from 'vitest'\n\nit('render basic', async () => {\n  const result = renderHTML(h('div', { class: 'foo' }))\n  await expect(result).toMatchFileSnapshot('./test/basic.output.html')\n})\n```\n\nIt will compare with the content of `./test/basic.output.html`. And can be written back with the `--update` flag.\n\n## Visual Snapshots\n\nFor visual regression testing of UI components and pages, Vitest provides built-in support through [browser mode](/guide/browser/) with the [`toMatchScreenshot()`](/api/browser/assertions#tomatchscreenshot) assertion:\n\n```ts\nimport { expect, test } from 'vitest'\nimport { page } from 'vitest/browser'\n\ntest('button looks correct', async () => {\n  const button = page.getByRole('button')\n  await expect(button).toMatchScreenshot('primary-button')\n})\n```\n\nThis captures screenshots and compares them against reference images to detect unintended visual changes. Learn more in the [Visual Regression Testing guide](/guide/browser/visual-regression-testing).\n\n## Custom Serializer\n\nYou can add your own logic to alter how your snapshots are serialized. Like Jest, Vitest has default serializers for built-in JavaScript types, HTML elements, ImmutableJS and for React elements.\n\nYou can explicitly add custom serializer by using [`expect.addSnapshotSerializer`](/api/expect#expect-addsnapshotserializer) API.\n\n```ts\nexpect.addSnapshotSerializer({\n  serialize(val, config, indentation, depth, refs, printer) {\n    // `printer` is a function that serializes a value using existing plugins.\n    return `Pretty foo: ${printer(\n      val.foo,\n      config,\n      indentation,\n      depth,\n      refs,\n    )}`\n  },\n  test(val) {\n    return val && Object.prototype.hasOwnProperty.call(val, 'foo')\n  },\n})\n```\n\nWe also support [snapshotSerializers](/config/snapshotserializers) option to implicitly add custom serializers.\n\n```ts [path/to/custom-serializer.ts]\nimport { SnapshotSerializer } from 'vitest'\n\nexport default {\n  serialize(val, config, indentation, depth, refs, printer) {\n    // `printer` is a function that serializes a value using existing plugins.\n    return `Pretty foo: ${printer(\n      val.foo,\n      config,\n      indentation,\n      depth,\n      refs,\n    )}`\n  },\n  test(val) {\n    return val && Object.prototype.hasOwnProperty.call(val, 'foo')\n  },\n} satisfies SnapshotSerializer\n```\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    snapshotSerializers: ['path/to/custom-serializer.ts'],\n  },\n})\n```\n\nAfter adding a test like this:\n\n```ts\ntest('foo snapshot test', () => {\n  const bar = {\n    foo: {\n      x: 1,\n      y: 2,\n    },\n  }\n\n  expect(bar).toMatchSnapshot()\n})\n```\n\nYou will get the following snapshot:\n\n```\nPretty foo: Object {\n  \"x\": 1,\n  \"y\": 2,\n}\n```\n\nWe are using Jest's `pretty-format` for serializing snapshots. You can read more about it here: [pretty-format](https://github.com/facebook/jest/blob/main/packages/pretty-format/README.md#serialize).\n\n## Difference from Jest\n\nVitest provides an almost compatible Snapshot feature with [Jest's](https://jestjs.io/docs/snapshot-testing) with a few exceptions:\n\n#### 1. Comment header in the snapshot file is different\n\n```diff\n- // Jest Snapshot v1, https://goo.gl/fbAQLP\n+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n```\n\nThis does not really affect the functionality but might affect your commit diff when migrating from Jest.\n\n#### 2. `printBasicPrototype` is default to `false`\n\nBoth Jest and Vitest's snapshots are powered by [`pretty-format`](https://github.com/facebook/jest/blob/main/packages/pretty-format). In Vitest we set `printBasicPrototype` default to `false` to provide a cleaner snapshot output, while in Jest <29.0.0 it's `true` by default.\n\n```ts\nimport { expect, test } from 'vitest'\n\ntest('snapshot', () => {\n  const bar = [\n    {\n      foo: 'bar',\n    },\n  ]\n\n  // in Jest\n  expect(bar).toMatchInlineSnapshot(`\n    Array [\n      Object {\n        \"foo\": \"bar\",\n      },\n    ]\n  `)\n\n  // in Vitest\n  expect(bar).toMatchInlineSnapshot(`\n    [\n      {\n        \"foo\": \"bar\",\n      },\n    ]\n  `)\n})\n```\n\nWe believe this is a more reasonable default for readability and overall DX. If you still prefer Jest's behavior, you can change your config:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    snapshotFormat: {\n      printBasicPrototype: true,\n    },\n  },\n})\n```\n\n#### 3. Chevron `>` is used as a separator instead of colon `:` for custom messages\n\nVitest uses chevron `>` as a separator instead of colon `:` for readability, when a custom message is passed during creation of a snapshot file.\n\nFor the following example test code:\n```js\ntest('toThrowErrorMatchingSnapshot', () => {\n  expect(() => {\n    throw new Error('error')\n  }).toThrowErrorMatchingSnapshot('hint')\n})\n```\n\nIn Jest, the snapshot will be:\n```console\nexports[`toThrowErrorMatchingSnapshot: hint 1`] = `\"error\"`;\n```\n\nIn Vitest, the equivalent snapshot will be:\n```console\nexports[`toThrowErrorMatchingSnapshot > hint 1`] = `[Error: error]`;\n```\n\n#### 4. default `Error` snapshot is different for `toThrowErrorMatchingSnapshot` and `toThrowErrorMatchingInlineSnapshot`\n\n```js\nimport { expect, test } from 'vitest'\n\ntest('snapshot', () => {\n  // in Jest and Vitest\n  expect(new Error('error')).toMatchInlineSnapshot(`[Error: error]`)\n\n  // Jest snapshots `Error.message` for `Error` instance\n  // Vitest prints the same value as toMatchInlineSnapshot\n  expect(() => {\n    throw new Error('error')\n  }).toThrowErrorMatchingInlineSnapshot(`\"error\"`) // [!code --]\n  }).toThrowErrorMatchingInlineSnapshot(`[Error: error]`) // [!code ++]\n})\n```\n"
  },
  {
    "path": "docs/guide/test-annotations.md",
    "content": "---\ntitle: Test Annotations | Guide\noutline: deep\n---\n\n# Test Annotations\n\nVitest supports annotating your tests with custom messages and files via the [`context.annotate`](/guide/test-context#annotate) API. These annotations will be attached to the test case and passed down to reporters in the [`onTestAnnotate`](/api/advanced/reporters#ontestannotate) hook.\n\n```ts\ntest('hello world', async ({ annotate }) => {\n  await annotate('this is my test')\n\n  if (condition) {\n    await annotate('this should\\'ve errored', 'error')\n  }\n\n  const file = createTestSpecificFile()\n  await annotate('creates a file', { body: file })\n})\n```\n\n::: warning\nThe `annotate` function returns a Promise, so it needs to be awaited if you rely on it somehow. However, Vitest will also automatically await any non-awaited annotation before the test finishes.\n:::\n\nDepending on your reporter, you will see these annotations differently.\n\n## Built-in Reporters\n### default\n\nThe `default` reporter prints annotations only if the test has failed:\n\n```\n  ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n  FAIL  example.test.js > an example of a test with annotation\nError: thrown error\n  ❯ example.test.js:11:21\n      9 |    await annotate('annotation 1')\n      10|    await annotate('annotation 2', 'warning')\n      11|    throw new Error('thrown error')\n        |          ^\n      12|  })\n\n  ❯ example.test.js:9:15 notice\n    ↳ annotation 1\n  ❯ example.test.js:10:15 warning\n    ↳ annotation 2\n\n  ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n```\n\n### verbose\n\nThe `verbose` reporter is the only terminal reporter that reports annotations when the test doesn't fail.\n\n```\n✓ example.test.js > an example of a test with annotation\n\n  ❯ example.test.js:9:15 notice\n    ↳ annotation 1\n  ❯ example.test.js:10:15 warning\n    ↳ annotation 2\n\n```\n\n### html\n\nThe HTML reporter shows annotations the same way the UI does. You can see the annotation on the line where it was called. At the moment, if the annotation wasn't called in a test file, you cannot see it in the UI. We are planning to support a separate test summary view where it will be visible.\n\n<img alt=\"Vitest UI\" img-light src=\"/annotations-html-light.png\">\n<img alt=\"Vitest UI\" img-dark src=\"/annotations-html-dark.png\">\n\n### junit\n\nThe `junit` reporter lists annotations inside the testcase's `properties` tag. The JUnit reporter will ignore all attachments and will print only the type and the message.\n\n```xml\n<testcase classname=\"basic/example.test.js\" name=\"an example of a test with annotation\" time=\"0.14315\">\n    <properties>\n        <property name=\"notice\" value=\"the message of the annotation\">\n        </property>\n    </properties>\n</testcase>\n```\n\n### github-actions\n\nThe `github-actions` reporter will print the annotation as a [notice message](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-a-notice-message) by default. You can configure the `type` by passing down the second argument as `notice`, `warning` or `error`. If type is none of these, Vitest will show the message as a notice.\n\n<img alt=\"GitHub Actions\" img-light src=\"/annotations-gha-light.png\">\n<img alt=\"GitHub Actions\" img-dark src=\"/annotations-gha-dark.png\">\n\n### tap\n\nThe `tap` and `tap-flat` reporters print annotations as diagnostic messages on a new line starting with a `#` symbol. They will ignore all attachments and will print only the type and message:\n\n```\nok 1 - an example of a test with annotation # time=143.15ms\n    # notice: the message of the annotation\n```\n"
  },
  {
    "path": "docs/guide/test-context.md",
    "content": "---\ntitle: Test Context | Guide\noutline: deep\n---\n\n# Test Context\n\nInspired by [Playwright Fixtures](https://playwright.dev/docs/test-fixtures), Vitest's test context allows you to define utils, states, and fixtures that can be used in your tests.\n\n## Usage\n\nThe first argument for each test callback is a test context.\n\n```ts\nimport { it } from 'vitest'\n\nit('should work', ({ task }) => {\n  // prints name of the test\n  console.log(task.name)\n})\n```\n\n## Built-in Test Context\n\n### `task`\n\nA readonly object containing metadata about the test.\n\n### `expect`\n\nThe `expect` API bound to the current test:\n\n```ts\nimport { it } from 'vitest'\n\nit('math is easy', ({ expect }) => {\n  expect(2 + 2).toBe(4)\n})\n```\n\nThis API is useful for running snapshot tests concurrently because global expect cannot track them:\n\n```ts\nimport { it } from 'vitest'\n\nit.concurrent('math is easy', ({ expect }) => {\n  expect(2 + 2).toMatchInlineSnapshot()\n})\n\nit.concurrent('math is hard', ({ expect }) => {\n  expect(2 * 2).toMatchInlineSnapshot()\n})\n```\n\n### `skip`\n\n```ts\nfunction skip(note?: string): never\nfunction skip(condition: boolean, note?: string): void\n```\n\nSkips subsequent test execution and marks test as skipped:\n\n```ts\nimport { expect, it } from 'vitest'\n\nit('math is hard', ({ skip }) => {\n  skip()\n  expect(2 + 2).toBe(5)\n})\n```\n\nSince Vitest 3.1, it accepts a boolean parameter to skip the test conditionally:\n\n```ts\nit('math is hard', ({ skip, mind }) => {\n  skip(mind === 'foggy')\n  expect(2 + 2).toBe(5)\n})\n```\n\n### `annotate` <Version>3.2.0</Version> {#annotate}\n\n```ts\nfunction annotate(\n  message: string,\n  attachment?: TestAttachment,\n): Promise<TestAnnotation>\n\nfunction annotate(\n  message: string,\n  type?: string,\n  attachment?: TestAttachment,\n): Promise<TestAnnotation>\n```\n\nAdd a [test annotation](/guide/test-annotations) that will be displayed by your [reporter](/config/reporters).\n\n```ts\ntest('annotations API', async ({ annotate }) => {\n  await annotate('https://github.com/vitest-dev/vitest/pull/7953', 'issues')\n})\n```\n\n### `signal` <Version>3.2.0</Version> {#signal}\n\nAn [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that can be aborted by Vitest. The signal is aborted in these situations:\n\n- Test times out\n- User manually cancelled the test run with Ctrl+C\n- [`vitest.cancelCurrentRun`](/api/advanced/vitest#cancelcurrentrun) was called programmatically\n- Another test failed in parallel and the [`bail`](/config/bail) flag is set\n\n```ts\nit('stop request when test times out', async ({ signal }) => {\n  await fetch('/resource', { signal })\n}, 2000)\n```\n\n### `onTestFailed`\n\nThe [`onTestFailed`](/api/hooks#ontestfailed) hook bound to the current test. This API is useful if you are running tests concurrently and need to have a special handling only for this specific test.\n\n### `onTestFinished`\n\nThe [`onTestFinished`](/api/hooks#ontestfailed) hook bound to the current test. This API is useful if you are running tests concurrently and need to have a special handling only for this specific test.\n\n## Extend Test Context\n\nVitest allows you to extend the test context with custom fixtures using `test.extend`.\n\nThe `test.extend` method lets you create a custom test API with fixtures - reusable values that are automatically set up and torn down for your tests. Vitest supports two syntaxes: the builder pattern (recommended) and the object syntax (Playwright-compatible).\n\n### Builder Pattern <Version>4.1.0</Version> {#builder-pattern}\n\nThe builder pattern is the recommended way to define fixtures because it provides automatic type inference. TypeScript infers the type of each fixture from its return value, so you don't need to declare types manually.\n\n```ts [my-test.ts]\nimport { test as baseTest } from 'vitest'\n\nexport const test = baseTest\n  // Simple value - type is inferred as { port: number; host: string }\n  .extend('config', { port: 3000, host: 'localhost' })\n  // Function fixture - type is inferred from return value\n  .extend('server', async ({ config }) => {\n    // TypeScript knows config is { port: number; host: string }\n    return `http://${config.host}:${config.port}`\n  })\n```\n\nThen use it in your tests:\n\n```ts [my-test.test.ts]\nimport { expect } from 'vitest'\nimport { test } from './my-test.js'\n\ntest('server uses correct port', ({ config, server }) => {\n  // TypeScript knows the types:\n  // - config is { port: number; host: string }\n  // - server is string\n  expect(server).toBe('http://localhost:3000')\n  expect(config.port).toBe(3000)\n})\n```\n\n#### Setup and Cleanup with `onCleanup`\n\nFor fixtures that need setup or cleanup logic, use a function. The `onCleanup` callback registers teardown logic that runs after the fixture's scope ends:\n\n```ts\nimport { test as baseTest } from 'vitest'\n\nexport const test = baseTest\n  .extend('tempFile', async ({}, { onCleanup }) => {\n    const filePath = `/tmp/test-${Date.now()}.txt`\n    await fs.writeFile(filePath, 'test data')\n\n    // Register cleanup - runs after test completes\n    onCleanup(async () => {\n      await fs.unlink(filePath)\n    })\n\n    return filePath\n  })\n```\n\nFor more complex examples:\n\n```ts\nconst test = baseTest\n  .extend('database', { scope: 'file' }, async ({}, { onCleanup }) => {\n    const db = await createDatabase()\n    await db.connect()\n\n    onCleanup(async () => {\n      await db.disconnect()\n    })\n\n    return db\n  })\n  .extend('user', async ({ database }, { onCleanup }) => {\n    const user = await database.createTestUser()\n\n    onCleanup(async () => {\n      await database.deleteUser(user.id)\n    })\n\n    return user\n  })\n```\n\n::: warning\nThe `onCleanup` function can only be called **once per fixture**. If you need multiple cleanup operations, either combine them into a single cleanup function, or split your fixture into multiple smaller fixtures:\n\n```ts\n// ❌ This will throw an error\nconst test = baseTest\n  .extend('resources', async ({}, { onCleanup }) => {\n    const a = await acquireA()\n    onCleanup(() => releaseA(a))\n\n    const b = await acquireB()\n    onCleanup(() => releaseB(b)) // Error: onCleanup can only be called once\n\n    return { a, b }\n  })\n\n// ✅ Split into separate fixtures (recommended)\nconst test = baseTest\n  .extend('resourceA', async ({}, { onCleanup }) => {\n    const a = await acquireA()\n    onCleanup(() => releaseA(a))\n    return a\n  })\n  .extend('resourceB', async ({}, { onCleanup }) => {\n    const b = await acquireB()\n    onCleanup(() => releaseB(b))\n    return b\n  })\n```\n\nSplitting into separate fixtures is the recommended approach as it provides better isolation and makes dependencies explicit.\n:::\n\n#### Fixture Options\n\nThe second argument to `.extend()` accepts options:\n\n```ts\nconst test = baseTest\n  // Automatic fixture - runs for every test even if not used\n  .extend('metrics', { auto: true }, ({}, { onCleanup }) => {\n    const metrics = new MetricsCollector()\n    metrics.start()\n    onCleanup(() => metrics.stop())\n    return metrics\n  })\n  // Worker-scoped fixture - initialized once per worker\n  .extend('config', { scope: 'worker' }, () => {\n    return loadConfig()\n  })\n  // File-scoped fixture - initialized once per file\n  .extend('database', { scope: 'file' }, async ({ config }, { onCleanup }) => {\n    const db = await createDatabase(config)\n    onCleanup(() => db.close())\n    return db\n  })\n  // Injected fixture - can be overridden via config\n  .extend('baseUrl', { injected: true }, () => {\n    return 'http://localhost:3000'\n  })\n```\n\nFor test-scoped fixtures (the default), you can omit the options:\n\n```ts\nconst test = baseTest\n  .extend('simple', () => 'value')\n```\n\n#### Accessing Other Fixtures\n\nEach fixture can access previously defined fixtures via its first parameter. This works for both function and non-function fixtures:\n\n```ts\nconst test = baseTest\n  .extend('config', { apiUrl: 'https://api.example.com', port: 3000 })\n  .extend('client', ({ config }) => {\n    // TypeScript knows config is { apiUrl: string; port: number }\n    return new ApiClient(config.apiUrl)\n  })\n  .extend('user', async ({ client }) => {\n    // TypeScript knows client is ApiClient\n    return await client.getCurrentUser()\n  })\n```\n\n#### Object Syntax (Playwright-Compatible)\n\nVitest also supports a Playwright-compatible object syntax. This is useful if you're migrating from Playwright or prefer defining all fixtures at once:\n\n```ts [my-test.ts]\nimport { test as baseTest } from 'vitest'\n\nexport const test = baseTest.extend({\n  page: async ({}, use) => {\n    // setup the fixture before each test function\n    const page = await browser.newPage()\n\n    // use the fixture value\n    await use(page)\n\n    // cleanup the fixture after each test function\n    await page.close()\n  },\n  baseUrl: 'http://localhost:3000'\n})\n```\n\nThe key difference from the builder pattern is the `use()` callback pattern for cleanup:\n\n```ts\n// Object syntax: cleanup code goes AFTER use()\nconst test = baseTest.extend({\n  database: async ({}, use) => {\n    const db = await createDatabase()\n    await db.connect()\n\n    await use(db) // Test runs here\n\n    // Cleanup after the test\n    await db.disconnect()\n  }\n})\n\n// Builder pattern: cleanup is registered with onCleanup()\nconst test = baseTest\n  .extend('database', async ({}, { onCleanup }) => {\n    const db = await createDatabase()\n    await db.connect()\n\n    onCleanup(() => db.disconnect())\n\n    return db // Test runs after this returns\n  })\n```\n\n::: info\nWith the object syntax, you need to provide types manually as a generic parameter since TypeScript cannot infer them from the `use()` callback:\n\n```ts\nconst test = baseTest.extend<{\n  page: Page\n  baseUrl: string\n}>({\n  page: async ({}, use) => {\n    const page = await browser.newPage()\n    await use(page)\n    await page.close()\n  },\n  baseUrl: 'http://localhost:3000'\n})\n```\n:::\n\n#### Tuple Syntax for Options\n\nWith the object syntax, use a tuple to specify fixture options:\n\n```ts\nconst test = baseTest.extend({\n  // Auto fixture\n  fixture: [\n    async ({}, use) => {\n      setup()\n      await use()\n      teardown()\n    },\n    { auto: true }\n  ],\n  // Scoped fixture\n  database: [\n    async ({}, use) => {\n      const db = await createDatabase()\n      await use(db)\n      await db.close()\n    },\n    { scope: 'file' }\n  ],\n  // Injected fixture\n  url: [\n    '/default',\n    { injected: true }\n  ],\n})\n```\n\n### Fixture Initialization\n\nVitest runner will smartly initialize your fixtures and inject them into the test context based on usage.\n\n```ts\nimport { test as baseTest } from 'vitest'\n\nconst test = baseTest\n  .extend('database', async () => {\n    console.log('database initializing')\n    return createDatabase()\n  })\n  .extend('cache', async () => {\n    return createCache()\n  })\n\n// database will not run\ntest('no fixtures needed', () => {})\ntest('only cache', ({ cache }) => {})\n\n// database will run\ntest('needs database', ({ database }) => {})\n```\n\n::: warning\nWhen using `test.extend()` with fixtures, you should always use the object destructuring pattern `{ database }` to access context both in fixture function and test function.\n\n```ts\ntest('context must be destructured', (context) => { // [!code --]\n  expect(context.database).toBeDefined()\n})\n\ntest('context must be destructured', ({ database }) => { // [!code ++]\n  expect(database).toBeDefined()\n})\n```\n:::\n\n### Extending Extended Tests\n\nYou can extend an already extended test to add more fixtures:\n\n```ts\nimport { test as dbTest } from './my-test.js'\n\nexport const test = dbTest\n  .extend('user', ({ database }) => {\n    return database.createUser()\n  })\n```\n\nWith the object syntax:\n\n```ts\nimport { test as dbTest } from './my-test.js'\n\nexport const test = dbTest.extend({\n  admin: async ({ database }, use) => {\n    const admin = await database.createAdmin()\n    await use(admin)\n    await database.deleteUser(admin.id)\n  }\n})\n```\n\n### Mixing Both Syntaxes\n\nYou can combine both approaches. The builder pattern can be chained after object-based extensions:\n\n```ts\nconst test = baseTest\n  // Object syntax for simple fixtures\n  .extend<{ apiKey: string }>({\n    apiKey: 'test-key-123',\n  })\n  // Builder pattern for complex fixtures with inference\n  .extend('client', ({ apiKey }) => {\n    // TypeScript knows apiKey is string\n    return new ApiClient(apiKey)\n  })\n```\n\n### Fixture Scopes <Version>3.2.0</Version> {#fixture-scopes}\n\nBy default, fixtures are initialized for each test. You can change this with the `scope` option to share fixtures across tests.\n\n::: warning\nBy default any fixture without a scope is treated as a `test` fixture. This means that you cannot use it inside `worker` and `file` scopes. If you wish to access it there, consider specifying a scope manually:\n\n```ts\ntest\n  .extend('port', { scope: 'worker' }, 5000)\n  .extend('db', { scope: 'worker' }, async ({ port }) => {\n    return createDb(port)\n  })\n```\n\nNote that you cannot override non-test fixtures inside `describe` blocks:\n\n```ts\ntest.describe('a nested suite', () => {\n  test.override('port', { scope: 'worker' }, 3000) // throws an error\n})\n```\n\nConsider overriding it on the top level of the module, or by using [`injected`](#default-fixture-injected) option and providing the value in the project config.\n\nAlso note that in [non-isolate](/config/isolate) mode overriding a `worker` fixture will affect the fixture value in all test files running after it was overridden.\n:::\n\n#### Test Scope (Default)\n\nTest-scoped fixtures are created fresh for each test:\n\n```ts\nconst test = baseTest\n  .extend('counter', () => {\n    return { value: 0 }\n  })\n\ntest('first test', ({ counter }) => {\n  counter.value++\n  expect(counter.value).toBe(1)\n})\n\ntest('second test', ({ counter }) => {\n  // Fresh instance, value is 0 again\n  expect(counter.value).toBe(0)\n})\n```\n\nTest-scoped fixtures have access to the [built-in test context](#built-in-test-context) (`task`, `expect`, `skip`, etc.):\n\n```ts\nconst test = baseTest\n  .extend('testInfo', ({ task }) => {\n    return { name: task.name }\n  })\n```\n\n#### File Scope\n\nFile-scoped fixtures are initialized once per test file:\n\n```ts\nconst test = baseTest\n  .extend('database', { scope: 'file' }, async ({}, { onCleanup }) => {\n    const db = await createDatabase()\n    onCleanup(() => db.close())\n    return db\n  })\n\ntest('first test', ({ database }) => {\n  // Uses the same database instance\n})\n\ntest('second test', ({ database }) => {\n  // Same database instance as first test\n})\n```\n\n#### Worker Scope\n\nWorker-scoped fixtures are initialized once per worker process:\n\n```ts\nconst test = baseTest\n  .extend('config', { scope: 'worker' }, () => {\n    return await loadExpensiveConfig()\n  })\n```\n\n::: info\nBy default, every file runs in a separate worker, so `file` and `worker` scopes work the same way. However, if you disable [isolation](/config/isolate), then the number of workers is limited by [`maxWorkers`](/config/maxworkers), and worker-scoped fixtures will be shared across files running in the same worker.\n\nWhen running tests in `vmThreads` or `vmForks`, `scope: 'worker'` works the same way as `scope: 'file'` because each file has its own VM context.\n:::\n\n#### Scope Hierarchy\n\nFixtures can only access other fixtures from the same or higher (longer-lived) scopes:\n\n| Fixture Scope | Can Access |\n|---------------|------------|\n| `worker` | Only other worker fixtures |\n| `file` | Worker + file fixtures |\n| `test` | Worker + file + test fixtures + [test context](#built-in-test-context) |\n\n```ts\nconst test = baseTest\n  .extend('config', { scope: 'worker' }, () => {\n    return { apiUrl: 'https://api.example.com' }\n  })\n  .extend('database', { scope: 'file' }, async ({ config }, { onCleanup }) => {\n    // ✅ File fixture can access worker fixture\n    const db = await createDatabase(config.apiUrl)\n    onCleanup(() => db.close())\n    return db\n  })\n  .extend('user', async ({ database, task }) => {\n    // ✅ Test fixture can access file fixture AND test context\n    return await database.createUser(task.name)\n  })\n```\n\n::: tip\nOnly test-scoped fixtures have access to the [built-in test context](#built-in-test-context) (`task`, `expect`, `skip`, etc.). Worker and file fixtures run outside of any specific test, so test-specific properties are not available to them.\n\nIf you need the file path in a file-scoped fixture, use `expect.getState().testPath` instead.\n:::\n\n#### Type-Safe Scope Access <Version>3.2.0</Version> {#type-safe-scope-access}\n\nWith the builder pattern, TypeScript automatically enforces scope-based access rules. If you try to access a test-scoped fixture from a file-scoped fixture, you'll get a compile-time error.\n\nIf you're using the object syntax and want the same type safety, you can use the `$worker`, `$file`, and `$test` keys to explicitly declare which fixtures belong to which scope:\n\n```ts\nconst test = baseTest.extend<{\n  $worker: { config: Config }\n  $file: { database: Database }\n  $test: { user: User }\n}>({\n  config: [async ({}, use) => {\n    await use(loadConfig())\n  }, { scope: 'worker' }],\n\n  database: [async ({ config }, use) => {\n    const db = await createDatabase(config)\n    await use(db)\n    await db.close()\n  }, { scope: 'file' }],\n\n  user: async ({ database }, use) => {\n    const user = await database.createUser()\n    await use(user)\n    await database.deleteUser(user.id)\n  },\n})\n```\n\nThis provides the same compile-time safety as the builder pattern, catching scope violations at build time rather than runtime.\n\n### Default Fixture (Injected)\n\nSince Vitest 3, you can provide different values in different [projects](/guide/projects). To enable this, pass `{ injected: true }` in the options. If the key is not specified in the [project configuration](/config/provide), the default value will be used.\n\n:::code-group\n```ts [fixtures.test.ts]\nimport { test as baseTest } from 'vitest'\n\nconst test = baseTest\n  .extend('url', { injected: true }, '/default')\n\ntest('works correctly', ({ url }) => {\n  // url is \"/default\" in \"project-new\"\n  // url is \"/full\" in \"project-full\"\n  // url is \"/empty\" in \"project-empty\"\n})\n```\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: 'project-new',\n        },\n      },\n      {\n        test: {\n          name: 'project-full',\n          provide: {\n            url: '/full',\n          },\n        },\n      },\n      {\n        test: {\n          name: 'project-empty',\n          provide: {\n            url: '/empty',\n          },\n        },\n      },\n    ],\n  },\n})\n```\n:::\n\n### Overriding Fixture Values <Version>4.1.0</Version> {#overriding-fixture-values}\n\nYou can override fixture values for a specific suite and its children using `test.override`. This is useful when you need different fixture values for different test scenarios.\n\n::: tip\nVitest will automatically inherit the options, if they are not provided when overriding. Note that you cannot override fixture's `scope` or `auto` options.\n:::\n\n#### Builder Pattern (Recommended)\n\n```ts\nimport { test as baseTest, describe, expect } from 'vitest'\n\nconst test = baseTest\n  .extend('config', { port: 3000, host: 'localhost' })\n  .extend('server', ({ config }) => `http://${config.host}:${config.port}`)\n\ndescribe('production environment', () => {\n  // Override with a new static value (chainable)\n  test\n    .override('config', { port: 8080, host: 'api.example.com' })\n\n  test('uses production config', ({ server }) => {\n    expect(server).toBe('http://api.example.com:8080')\n  })\n})\n\ndescribe('with custom server', () => {\n  // Override with a function that can access other fixtures\n  test.override('server', ({ config }) => {\n    return `https://${config.host}:${config.port}/v2`\n  })\n\n  test('uses custom server', ({ server }) => {\n    expect(server).toBe('https://localhost:3000/v2')\n  })\n})\n\ntest('uses default values', ({ server }) => {\n  expect(server).toBe('http://localhost:3000')\n})\n```\n\n#### Chaining Multiple Overrides\n\n`test.override` returns the test API, so you can chain multiple calls:\n\n```ts\ndescribe('production environment', () => {\n  test\n    .override('environment', 'production')\n    .override('port', 8080)\n    .override('debug', false)\n\n  test('uses production settings', ({ environment, port, debug }) => {\n    expect(environment).toBe('production')\n    expect(port).toBe(8080)\n    expect(debug).toBe(false)\n  })\n})\n```\n\n#### Object Syntax\n\nYou can also use object syntax to override multiple fixtures at once:\n\n```ts\ndescribe('different configuration', () => {\n  test.override({\n    config: { port: 4000, host: 'test.local' },\n  })\n\n  test('uses overwritten config', ({ config }) => {\n    expect(config.port).toBe(4000)\n  })\n})\n```\n\n#### With Cleanup\n\nWhen overwriting with a function, you can use `onCleanup` just like in `test.extend`:\n\n```ts\ndescribe('with custom database', () => {\n  test.override('database', async ({ config }, { onCleanup }) => {\n    const db = await createTestDatabase(config)\n    onCleanup(() => db.drop())\n    return db\n  })\n\n  test('uses custom database', ({ database }) => {\n    // Uses the overwritten database\n  })\n})\n```\n\n#### Nested Scopes\n\nOverrides are inherited by nested suites and can be overwritten again:\n\n```ts\ndescribe('level 1', () => {\n  test.override('value', 'one')\n\n  test('uses level 1 value', ({ value }) => {\n    expect(value).toBe('one')\n  })\n\n  describe('level 2', () => {\n    test.override('value', 'two')\n\n    test('uses level 2 value', ({ value }) => {\n      expect(value).toBe('two')\n    })\n  })\n\n  test('still uses level 1 value', ({ value }) => {\n    expect(value).toBe('one')\n  })\n})\n```\n\n::: warning\nNote that you cannot introduce new fixtures inside `test.override`. Extend the test context with `test.extend` instead.\n:::\n\n::: info\n`test.scoped` is deprecated in favor of `test.override`. The `test.scoped` API still works but will be removed in a future version.\n:::\n\n### Type-Safe Hooks\n\nWhen using `test.extend`, the extended `test` object provides type-safe hooks that are aware of the extended context:\n\n```ts\nconst test = baseTest\n  .extend('counter', { value: 0, increment() { this.value++ } })\n\n// Unlike global hooks, these hooks are aware of the extended context\ntest.beforeEach(({ counter }) => {\n  counter.increment()\n})\n\ntest.afterEach(({ counter }) => {\n  console.log('Final count:', counter.value)\n})\n```\n\n#### Suite-Level Hooks with Fixtures <Version>4.1.0</Version> {#suite-level-hooks}\n\nThe extended `test` object also provides [`beforeAll`](/api/hooks#beforeall), [`afterAll`](/api/hooks#afterall), and [`aroundAll`](/api/hooks#aroundall) hooks that can access file-scoped and worker-scoped fixtures:\n\n```ts\nconst test = baseTest\n  .extend('config', { scope: 'file' }, () => loadConfig())\n  .extend('database', { scope: 'file' }, async ({ config }, { onCleanup }) => {\n    const db = await createDatabase(config)\n    onCleanup(() => db.close())\n    return db\n  })\n\n// Access file-scoped fixtures in suite-level hooks\ntest.aroundAll(async (runSuite, { database }) => {\n  await database.transaction(runSuite)\n})\n\ntest.beforeAll(async ({ database }) => {\n  await database.createUsers()\n})\n\ntest.afterAll(async ({ database }) => {\n  await database.removeUsers()\n})\n```\n\n::: warning IMPORTANT\nSuite-level hooks (`beforeAll`, `afterAll`, `aroundAll`) **must be called on the `test` object returned from `test.extend()`** to have access to the extended fixtures. Using the global `beforeAll`/`afterAll`/`aroundAll` functions will not have access to your custom fixtures:\n\n```ts\nimport { test as baseTest, beforeAll } from 'vitest'\n\nconst test = baseTest\n  .extend('database', { scope: 'file' }, async ({}, { onCleanup }) => {\n    const db = await createDatabase()\n    onCleanup(() => db.close())\n    return db\n  })\n\n// ❌ WRONG: Global beforeAll doesn't have access to 'database'\nbeforeAll(({ database }) => {\n  // Error: 'database' is undefined\n})\n\n// ✅ CORRECT: Use test.beforeAll to access fixtures\ntest.beforeAll(({ database }) => {\n  // 'database' is available\n})\n```\n\nThis applies to all suite-level hooks: `beforeAll`, `afterAll`, and `aroundAll`.\n:::\n\n::: tip\nSuite-level hooks can only access [**file-scoped** and **worker-scoped** fixtures](#fixture-scopes). Test-scoped fixtures are not available in these hooks because they run outside the context of individual tests. If you try to access a test-scoped fixture in a suite-level hook, Vitest will throw an error.\n\n```ts\nconst test = baseTest\n  .extend('testFixture', () => 'test-scoped')\n  .extend('fileFixture', { scope: 'file' }, () => 'file-scoped')\n\n// ❌ Error: test-scoped fixtures not available in beforeAll\ntest.beforeAll(({ testFixture }) => {})\n\n// ✅ Works: file-scoped fixtures are available\ntest.beforeAll(({ fileFixture }) => {})\n```\n:::\n"
  },
  {
    "path": "docs/guide/test-tags.md",
    "content": "---\ntitle: Test Tags | Guide\noutline: deep\n---\n\n# Test Tags <Version>4.1.0</Version> {#test-tags}\n\n[`Tags`](/config/tags) let you label tests so you can filter what runs and override their options when needed.\n\n## Defining Tags\n\nTags must be defined in your configuration file — Vitest does not provide any built-in tags. If a test uses a tag that isn't defined in the config, the test runner will throw an error. This prevents unexpected behavior from mistyped tag names. You can disable this check with the [`strictTags`](/config/stricttags) option.\n\nYou must define a `name` of the tag, and you may define additional options that will be applied to every test marked with the tag, e.g., a `timeout`, or `retry`. For the full list of available options, see [`tags`](/config/tags).\n\n```ts [vitest.config.js]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    tags: [\n      {\n        name: 'frontend',\n        description: 'Tests written for frontend.',\n      },\n      {\n        name: 'backend',\n        description: 'Tests written for backend.',\n      },\n      {\n        name: 'db',\n        description: 'Tests for database queries.',\n        timeout: 60_000,\n      },\n      {\n        name: 'flaky',\n        description: 'Flaky CI tests.',\n        retry: process.env.CI ? 3 : 0,\n        timeout: 30_000,\n        priority: 1,\n      },\n    ],\n  },\n})\n```\n\n::: warning\nIf several tags have the same options and are used on the same test, they will be resolved in the order they were specified, or sorted by priority first (the lower the number, the higher the priority). Tags without a defined priority are merged first and will be overridden by higher priority ones:\n\n```ts\ntest('flaky database test', { tags: ['flaky', 'db'] })\n// { timeout: 30_000, retry: 3 }\n```\n\nNote that the `timeout` is 30 seconds (and not 60) because `flaky` tag has a priority of `1` while `db` (that defines 60 second timeout) has no priority.\n\nIf test defines its own options, they will have the highest priority:\n\n```ts\ntest('flaky database test', { tags: ['flaky', 'db'], timeout: 120_000 })\n// { timeout: 120_000, retry: 3 }\n```\n:::\n\nIf you are using TypeScript, you can enforce what tags are available by augmenting the `TestTags` type with a property that contains a union of strings (make sure this file is included by your `tsconfig`):\n\n```ts [vitest.shims.ts]\nimport 'vitest'\n\ndeclare module 'vitest' {\n  interface TestTags {\n    tags:\n      | 'frontend'\n      | 'backend'\n      | 'db'\n      | 'flaky'\n  }\n}\n```\n\nTo see all your tags, you can use [`--list-tags`](/guide/cli#listtags) command:\n\n```shell\nvitest --list-tags\n\nfrontend: Tests written for frontend.\nbackend: Tests written for backend.\ndb: Tests for database queries.\nflaky: Flaky CI tests.\n```\n\nTo print it in JSON, pass down `--list-tags=json`:\n\n```json\n{\n  \"tags\": [\n    {\n      \"name\": \"frontend\",\n      \"description\": \"Tests written for frontend.\"\n    },\n    {\n      \"name\": \"backend\",\n      \"description\": \"Tests written for backend.\"\n    },\n    {\n      \"name\": \"db\",\n      \"description\": \"Tests for database queries.\",\n      \"timeout\": 60000\n    },\n    {\n      \"name\": \"flaky\",\n      \"description\": \"Flaky CI tests.\",\n      \"retry\": 0,\n      \"timeout\": 30000,\n      \"priority\": 1\n    }\n  ],\n  \"projects\": []\n}\n```\n\n## Using Tags in Tests\n\nYou can apply tags to individual tests or entire suites using the `tags` option:\n\n```ts\nimport { describe, test } from 'vitest'\n\ntest('renders homepage', { tags: ['frontend'] }, () => {\n  // ...\n})\n\ndescribe('API endpoints', { tags: ['backend'] }, () => {\n  test('returns user data', () => {\n    // This test inherits the \"backend\" tag from the parent suite\n  })\n\n  test('validates input', { tags: ['validation'] }, () => {\n    // This test has both \"backend\" (inherited) and \"validation\" tags\n  })\n})\n```\n\nTags are inherited from parent suites, so all tests inside a tagged `describe` block will automatically have that tag.\n\nIt's also possible to define `tags` for every test in the file by using JSDoc's `@module-tag` at the top of the file:\n\n```ts\n/**\n * Auth tests\n * @module-tag admin/pages/dashboard\n * @module-tag acceptance\n */\n\ntest('dashboard renders items', () => {\n  // ...\n})\n```\n\n::: danger\nA `@module-tag` in a JSDoc comment applies to all tests in that file, not just the test it precedes.\n\nConsider this example:\n\n```js{3,10}\ndescribe('forms', () => {\n  /**\n   * @module-tag frontend\n   */\n  test('renders a form', () => {\n    // ...\n  })\n\n  /**\n   * @module-tag db\n   */\n  test('db returns users', () => {\n    // ...\n  })\n})\n```\n\nIn this example, every test in the file will have both the `frontend` and `db` tags. To tag individual tests, use the options argument instead:\n\n```js{2,6}\ndescribe('forms', () => {\n  test('renders a form', { tags: 'frontend' }, () => {\n    // ...\n  })\n\n  test('db returns users', { tags: 'db' }, () => {\n    // ...\n  })\n})\n```\n:::\n\n## Filtering Tests by Tag\n\nTo run only tests with specific tags, use the [`--tags-filter`](/guide/cli#tagsfilter) CLI option:\n\n```shell\nvitest --tags-filter=frontend\nvitest --tags-filter=\"frontend and backend\"\n```\n\nIf you are running Vitest UI, you can start a filter with a `tag:` prefix to filter out tests by tags using the same tags expression syntax:\n\n<img alt=\"The tags filter in Vitest UI\" img-light src=\"/ui/light-ui-tags.png\">\n<img alt=\"The tags filter in Vitest UI\" img-dark src=\"/ui/dark-ui-tags.png\">\n\nIf you are using a programmatic API, you can pass down a `tagsFilter` option to [`startVitest`](/guide/advanced/#startvitest) or [`createVitest`](/guide/advanced/#createvitest):\n\n```ts\nimport { startVitest } from 'vitest/node'\n\nawait startVitest('test', [], {\n  tagsFilter: ['frontend and backend'],\n})\n```\n\nOr you can create a [test specification](/api/advanced/test-specification) with your custom filters:\n\n```ts\nconst specification = vitest.getRootProject().createSpecification(\n  '/path-to-file.js',\n  {\n    testTagsFilter: ['frontend and backend'],\n  },\n)\n```\n\n### Syntax\n\nYou can combine tags in different ways. Vitest supports these keywords:\n\n- `and` or `&&` to include both expressions\n- `or` or `||` to include at least one expression\n- `not` or `!` to exclude the expression\n- `*` to match any number of characters (0 or more)\n- `()` to group expressions and override precedence\n\nThe parser follows standard [operator precedence](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence): `not`/`!` has the highest priority, then `and`/`&&`, then `or`/`||`. Use parentheses to override default precedence.\n\n::: warning Reserved Names\nTag names cannot be `and`, `or`, or `not` (case-insensitive) as these are reserved keywords. Tag names also cannot contain special characters (`(`, `)`, `&`, `|`, `!`, `*`, spaces) as these are used by the expression parser.\n:::\n\n### Wildcards\n\nYou can use a wildcard (`*`) to match any number of characters:\n\n```shell\nvitest --tags-filter=\"unit/*\"\n```\n\nThis will match tags like `unit/components`, `unit/utils`, etc.\n\n### Excluding Tags\n\nTo exclude tests with a specific tag, add an exclamation mark (`!`) at the start or a \"not\" keyword:\n\n```shell\nvitest --tags-filter=\"!slow and not flaky\"\n```\n\n### Examples\n\nHere are some common filtering patterns:\n\n```shell\n# Run only unit tests\nvitest --tags-filter=\"unit\"\n\n# Run tests that are both frontend AND fast\nvitest --tags-filter=\"frontend and fast\"\n\n# Run tests that are either unit OR e2e\nvitest --tags-filter=\"unit or e2e\"\n\n# Run all tests except slow ones\nvitest --tags-filter=\"!slow\"\n\n# Run frontend tests that are not flaky\nvitest --tags-filter=\"frontend && !flaky\"\n\n# Run tests matching a wildcard pattern\nvitest --tags-filter=\"api/*\"\n\n# Complex expression with parentheses\nvitest --tags-filter=\"(unit || e2e) && !slow\"\n\n# Run database tests that are either postgres or mysql, but not slow\nvitest --tags-filter=\"db && (postgres || mysql) && !slow\"\n```\n\nYou can also pass multiple `--tags-filter` flags. They are combined with AND logic:\n\n```shell\n# Run tests that match (unit OR e2e) AND are NOT slow\nvitest --tags-filter=\"unit || e2e\" --tags-filter=\"!slow\"\n```\n"
  },
  {
    "path": "docs/guide/testing-types.md",
    "content": "---\ntitle: Testing Types | Guide\n---\n\n# Testing Types\n\n::: tip Sample Project\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/typecheck) - [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/typecheck?initialPath=__vitest__/)\n\n:::\n\nVitest allows you to write tests for your types, using `expectTypeOf` or `assertType` syntaxes. By default all tests inside `*.test-d.ts` files are considered type tests, but you can change it with [`typecheck.include`](/config/typecheck#typecheck-include) config option.\n\nUnder the hood Vitest calls `tsc` or `vue-tsc`, depending on your config, and parses results. Vitest will also print out type errors in your source code, if it finds any. You can disable it with [`typecheck.ignoreSourceErrors`](/config/typecheck#typecheck-ignoresourceerrors) config option.\n\nKeep in mind that Vitest doesn't run these files, they are only statically analyzed by the compiler. Meaning, that if you use a dynamic name or `test.each` or `test.for`, the test name will not be evaluated - it will be displayed as is.\n\n::: warning\nBefore Vitest 2.1, your `typecheck.include` overrode the `include` pattern, so your runtime tests did not actually run; they were only type-checked.\n\nSince Vitest 2.1, if your `include` and `typecheck.include` overlap, Vitest will report type tests and runtime tests as separate entries.\n:::\n\nUsing CLI flags, like `--allowOnly` and `-t` are also supported for type checking.\n\n```ts [mount.test-d.ts]\nimport { assertType, expectTypeOf } from 'vitest'\nimport { mount } from './mount.js'\n\ntest('my types work properly', () => {\n  expectTypeOf(mount).toBeFunction()\n  expectTypeOf(mount).parameter(0).toExtend<{ name: string }>()\n\n  // @ts-expect-error name is a string\n  assertType(mount({ name: 42 }))\n})\n```\n\nAny type error triggered inside a test file will be treated as a test error, so you can use any type trick you want to test types of your project.\n\nYou can see a list of possible matchers in [API section](/api/expect-typeof).\n\n## Reading Errors\n\nIf you are using `expectTypeOf` API, refer to the [expect-type documentation on its error messages](https://github.com/mmkal/expect-type#error-messages).\n\nWhen types don't match, `.toEqualTypeOf` and `.toExtend` use a special helper type to produce error messages that are as actionable as possible. But there's a bit of an nuance to understanding them. Since the assertions are written \"fluently\", the failure should be on the \"expected\" type, not the \"actual\" type (`expect<Actual>().toEqualTypeOf<Expected>()`). This means that type errors can be a little confusing - so this library produces a `MismatchInfo` type to try to make explicit what the expectation is. For example:\n\n```ts\nexpectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>()\n```\n\nIs an assertion that will fail, since `{a: 1}` has type `{a: number}` and not `{a: string}`.  The error message in this case will read something like this:\n\n```\ntest/test.ts:999:999 - error TS2344: Type '{ a: string; }' does not satisfy the constraint '{ a: \\\\\"Expected: string, Actual: number\\\\\"; }'.\n  Types of property 'a' are incompatible.\n    Type 'string' is not assignable to type '\\\\\"Expected: string, Actual: number\\\\\"'.\n\n999 expectTypeOf({a: 1}).toEqualTypeOf<{a: string}>()\n```\n\nNote that the type constraint reported is a human-readable messaging specifying both the \"expected\" and \"actual\" types. Rather than taking the sentence `Types of property 'a' are incompatible // Type 'string' is not assignable to type \"Expected: string, Actual: number\"` literally - just look at the property name (`'a'`) and the message: `Expected: string, Actual: number`. This will tell you what's wrong, in most cases. Extremely complex types will of course be more effort to debug, and may require some experimentation. Please [raise an issue](https://github.com/mmkal/expect-type) if the error messages are actually misleading.\n\nThe `toBe...` methods (like `toBeString`, `toBeNumber`, `toBeVoid` etc.) fail by resolving to a non-callable type when the `Actual` type under test doesn't match up. For example, the failure for an assertion like `expectTypeOf(1).toBeString()` will look something like this:\n\n```\ntest/test.ts:999:999 - error TS2349: This expression is not callable.\n  Type 'ExpectString<number>' has no call signatures.\n\n999 expectTypeOf(1).toBeString()\n                    ~~~~~~~~~~\n```\n\nThe `This expression is not callable` part isn't all that helpful - the meaningful error is the next line, `Type 'ExpectString<number> has no call signatures`. This essentially means you passed a number but asserted it should be a string.\n\nIf TypeScript added support for [\"throw\" types](https://github.com/microsoft/TypeScript/pull/40468) these error messages could be improved significantly. Until then they will take a certain amount of squinting.\n\n### Concrete \"expected\" objects vs typeargs\n\nError messages for an assertion like this:\n\n```ts\nexpectTypeOf({ a: 1 }).toEqualTypeOf({ a: '' })\n```\n\nWill be less helpful than for an assertion like this:\n\n```ts\nexpectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>()\n```\n\nThis is because the TypeScript compiler needs to infer the typearg for the `.toEqualTypeOf({a: ''})` style, and this library can only mark it as a failure by comparing it against a generic `Mismatch` type. So, where possible, use a typearg rather than a concrete type for `.toEqualTypeOf` and `.toExtend`. If it's much more convenient to compare two concrete types, you can use `typeof`:\n\n```ts\nconst one = valueFromFunctionOne({ some: { complex: inputs } })\nconst two = valueFromFunctionTwo({ some: { other: inputs } })\n\nexpectTypeOf(one).toEqualTypeOf<typeof two>()\n```\n\nIf you find it hard working with `expectTypeOf` API and figuring out errors, you can always use more simple `assertType` API:\n\n```ts\nconst answer = 42\n\nassertType<number>(answer)\n// @ts-expect-error answer is not a string\nassertType<string>(answer)\n```\n\n::: tip\nWhen using `@ts-expect-error` syntax, you might want to make sure that you didn't make a typo. You can do that by including your type files in [`test.include`](/config/include) config option, so Vitest will also actually *run* these tests and fail with `ReferenceError`.\n\nThis will pass, because it expects an error, but the word “answer” has a typo, so it's a false positive error:\n\n```ts\n// @ts-expect-error answer is not a string\nassertType<string>(answr)\n```\n:::\n\n## Run Typechecking\n\nTo enable typechecking, just add [`--typecheck`](/config/typecheck) flag to your Vitest command in `package.json`:\n\n```json [package.json]\n{\n  \"scripts\": {\n    \"test\": \"vitest --typecheck\"\n  }\n}\n```\n\nNow you can run typecheck:\n\n::: code-group\n```bash [npm]\nnpm run test\n```\n```bash [yarn]\nyarn test\n```\n```bash [pnpm]\npnpm run test\n```\n```bash [bun]\nbun test\n```\n:::\n\nVitest uses `tsc --noEmit` or `vue-tsc --noEmit`, depending on your configuration, so you can remove these scripts from your pipeline.\n"
  },
  {
    "path": "docs/guide/ui.md",
    "content": "---\ntitle: Vitest UI | Guide\n---\n\n# Vitest UI\n\nPowered by Vite, Vitest also has a dev server under the hood when running the tests. This allows Vitest to provide a beautiful UI to view and interact with your tests. The Vitest UI is optional, so you'll need to install it with:\n\n```bash\nnpm i -D @vitest/ui\n```\n\nThen you can start the tests with UI by passing the `--ui` flag:\n\n```bash\nvitest --ui\n```\n\nThen you can visit the Vitest UI at <a href=\"http://localhost:51204/__vitest__/\">`http://localhost:51204/__vitest__/`</a>\n\n::: warning\nThe UI is interactive and requires a running Vite server, so make sure to run Vitest in `watch` mode (the default). Alternatively, you can generate a static HTML report that looks identical to the Vitest UI by specifying `html` in config's `reporters` option.\n:::\n\n<img alt=\"Vitest UI\" img-light src=\"/ui-1-light.png\">\n<img alt=\"Vitest UI\" img-dark src=\"/ui-1-dark.png\">\n\nUI can also be used as a reporter. Use `'html'` reporter in your Vitest configuration to generate HTML output and preview the results of your tests:\n\n```ts [vitest.config.ts]\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    reporters: ['html'],\n  },\n})\n```\n\nYou can check your coverage report in Vitest UI: see [Vitest UI Coverage](/guide/coverage#vitest-ui) for more details.\n\n::: warning\nIf you still want to see how your tests are running in real time in the terminal, don't forget to add `default` reporter to `reporters` option: `['default', 'html']`.\n:::\n\n::: tip\nTo preview your HTML report, you can use the [vite preview](https://vitejs.dev/guide/cli.html#vite-preview) command:\n\n```sh\nnpx vite preview --outDir ./html\n```\n\nYou can configure output with [`outputFile`](/config/outputfile) config option. You need to specify `.html` path there. For example, `./html/index.html` is the default value.\n:::\n\n## Module Graph\n\nModule Graph's tab displays the module graph of the selected test file.\n\n::: info\nAll of the provided images use [Zammad](https://github.com/zammad/zammad) repository as an example.\n:::\n\n<img alt=\"The module graph view\" img-light src=\"/ui/light-module-graph.png\">\n<img alt=\"The module graph view\" img-dark src=\"/ui/dark-module-graph.png\">\n\nIf there are more than 50 modules, the module graph displays only the first two levels of the graph to reduce the visual clutter. You can always click on \"Show Full Graph\" icon to preview the full graph.\n\n<center>\n  <img alt=\"The 'Show Full Graph' button located close to the legend\" img-light src=\"/ui/light-ui-show-graph.png\">\n  <img alt=\"The 'Show Full Graph' button located close to the legend\" img-dark src=\"/ui/dark-ui-show-graph.png\">\n</center>\n\n::: warning\nNote that if your graph is too big, it may take some time before the node positions are stabilized.\n:::\n\nYou can always restore the entry module graph by clicking on \"Reset\". To expand the module graph, right-click or hold <kbd>Shift</kbd> while clicking the node that interests you. It will display all nodes related to the selected one.\n\nBy default, Vitest doesn't show the modules from `node_modules`. Usually, these modules are externalized. You can enable them by deselecting \"Hide node_modules\".\n\n### Module Info\n\nBy left-clicking on the module node, you open the Module Info view.\n\n<img alt=\"The module info view for an inlined module\" img-light src=\"/ui/light-module-info.png\">\n<img alt=\"The module info view for an inlined module\" img-dark src=\"/ui/dark-module-info.png\">\n\nThis view is separated into two parts. The top part shows the full module ID and some diagnostics about the module. If [`experimental.fsModuleCache`](/config/experimental#experimental-fsmodulecache) is enabled, there will be a \"cached\" or \"not cached\" badge. On the right you can see time diagnostics:\n\n- Self Time: the time it took to import the module, excluding static imports.\n- Total Time: the time it took to import the module, including static imports. Note that this does not include `transform` time of the current module.\n- Transform: the time it took to transform the module.\n\nIf you opened this view by clicking on an import, you will also see a \"Back\" button at the start that will take you to the previous module.\n\nThe bottom part depends on the module type. If the module is external, you will only see the source code of that file. You will not be able to traverse the module graph any further, and you won't see how long it took to import static imports.\n\n<img alt=\"The module info view for an external module\" img-light src=\"/ui/light-module-info-external.png\">\n<img alt=\"The module info view for an external module\" img-dark src=\"/ui/dark-module-info-external.png\">\n\nIf the module was inlined, you will see three more windows:\n\n- Source: unchanged source code of the module\n- Transformed: the transformed code that Vitest executes using Vite's [module runner](https://vite.dev/guide/api-environment-runtimes#modulerunner)\n- Source Map (v3): source map mappings\n\nAll static imports in the \"Source\" window show a total time it took to evaluate them by the current module. If the import was already evaluated in the module graph, it will show `0ms` because it is cached by that point.\n\nIf the module took longer than the [`danger` threshold](/config/experimental#experimental-importdurations-thresholds) (default: 500ms) to load, the time will be displayed in red. If the module took longer than the [`warn` threshold](/config/experimental#experimental-importdurations-thresholds) (default: 100ms), the time will be displayed in orange.\n\nYou can click on an import source to jump into that module and traverse the graph further (note `./support/assertions/index.ts` below).\n\n<img alt=\"The module info view for an internal module\" img-light src=\"/ui/light-module-info-traverse.png\">\n<img alt=\"The module info view for an internal module\" img-dark src=\"/ui/dark-module-info-traverse.png\">\n\n::: warning\nNote that type-only imports are not executed at runtime and do not display a total duration. They also cannot be opened.\n:::\n\nIf another plugin injects a module import during transformation, those imports will be displayed at the start of the module in gray colour (for example, modules injected by `import.meta.glob`). They also show the total time and can be traversed further.\n\n<img alt=\"The module info view for an internal module\" img-light src=\"/ui/light-module-info-shadow.png\">\n<img alt=\"The module info view for an internal module\" img-dark src=\"/ui/dark-module-info-shadow.png\">\n\n::: tip\nIf you are developing a custom integration on top of Vitest, you can use [`vitest.experimental_getSourceModuleDiagnostic`](/api/advanced/vitest#getsourcemodulediagnostic) to retrieve this information.\n:::\n\n### Import Breakdown\n\n::: tip FEEDBACK\nPlease, leave feedback regarding this feature in a [GitHub Discussion](https://github.com/vitest-dev/vitest/discussions/9224).\n:::\n\nThe Module Graph tab also provides an Import Breakdown with a list of modules that take the longest time to load (top 10 by default), sorted by Total Time.\n\n<img alt=\"Import breakdown with a list of top 10 modules that take the longest time to load\" img-light src=\"/ui/light-import-breakdown.png\">\n<img alt=\"Import breakdown with a list of top 10 modules that take the longest time to load\" img-dark src=\"/ui/dark-import-breakdown.png\">\n\nYou can click on the module to see the Module Info. If the module is external, it will have the yellow color (the same color in the module graph).\n\nThe breakdown shows a list of modules with self time, total time, and a percentage relative to the time it took to load the whole test file.\n\nThe \"Show Import Breakdown\" icon will have a red color if there is at least one file that took longer than the [`danger` threshold](/config/experimental#experimental-importdurations-thresholds) (default: 500ms) to load, and it will be orange if there is at least one file that took longer than the [`warn` threshold](/config/experimental#experimental-importdurations-thresholds) (default: 100ms).\n\nYou can use [`experimental.importDurations.limit`](/config/experimental#experimental-importdurationslimit) to control the number of imports displayed.\n"
  },
  {
    "path": "docs/guide/using-plugins.md",
    "content": "---\ntitle: Using Plugins | Guide\n---\n\n# Using Plugins\n\nVitest can be extended using plugins, similar to how Vite plugins work. This allows you to enhance and customize Vitest's functionality by using the same API and concepts of Vite plugins.\n\nFor detailed guidance on how to write plugins, you can refer to the [Vite plugin documentation](https://vitejs.dev/guide/api-plugin).\n"
  },
  {
    "path": "docs/guide/why.md",
    "content": "---\ntitle: Why Vitest | Guide\n---\n\n# Why Vitest\n\n:::tip NOTE\nThis guide assumes that you are familiar with Vite. A good way to start learning more is to read the [Why Vite Guide](https://vitejs.dev/guide/why.html), and [Next generation frontend tooling with ViteJS](https://www.youtube.com/watch?v=UJypSr8IhKY), a stream where [Evan You](https://bsky.app/profile/evanyou.me) did a demo explaining the main concepts.\n:::\n\n## The Need for a Vite Native Test Runner\n\nVite's out-of-the-box support for common web patterns, features like glob imports and SSR primitives, and its many plugins and integrations are fostering a vibrant ecosystem. Its dev and build story are key to its success. For docs, there are several SSG-based alternatives powered by Vite. Vite's Unit Testing story hasn't been clear though. Existing options like [Jest](https://jestjs.io/) were created in a different context. There is a lot of duplication between Jest and Vite, forcing users to configure two different pipelines.\n\nUsing Vite dev server to transform your files during testing, enables the creation of a simple runner that doesn't need to deal with the complexity of transforming source files and can solely focus on providing the best DX during testing. A test runner that uses the same configuration of your App (through `vite.config.js`), sharing a common transformation pipeline during dev, build, and test time. That is extensible with the same plugin API that lets you and the maintainers of your tools provide first-class integration with Vite. A tool that is built with Vite in mind from the start, taking advantage of its improvements in DX, like its instant Hot Module Reload (HMR). This is Vitest, a next generation testing framework powered by Vite.\n\nGiven Jest's massive adoption, Vitest provides a compatible API that allows you to use it as a drop-in replacement in most projects. It also includes the most common features required when setting up your unit tests (mocking, snapshots, coverage). Vitest cares a lot about performance and uses Worker threads to run as much as possible in parallel. Some ports have seen test running an order of magnitude faster. Watch mode is enabled by default, aligning itself with the way Vite pushes for a dev first experience. Even with all these improvements in DX, Vitest stays lightweight by carefully choosing its dependencies (or directly inlining needed pieces).\n\n**Vitest aims to position itself as the Test Runner of choice for Vite projects, and as a solid alternative even for projects not using Vite.**\n\nContinue reading in the [Getting Started Guide](./index)\n\n## How is Vitest Different from X?\n\nYou can check out the [Comparisons](./comparisons) section for more details on how Vitest differs from other similar tools.\n"
  },
  {
    "path": "docs/index.md",
    "content": "---\ntitle: Vitest\ntitleTemplate: Next Generation testing framework\nlayout: home\ntheme: dark\n---\n\n<script setup>\nimport Home from './.vitepress/theme/Home.vue'\n</script>\n\n<Home />\n"
  },
  {
    "path": "docs/package.json",
    "content": "{\n  \"name\": \"docs\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"vitepress --port 3333 --open\",\n    \"build\": \"nr cli-table && nr prefetch && vitepress build\",\n    \"cli-table\": \"tsx .vitepress/scripts/cli-generator.ts\",\n    \"build-no-prefetch\": \"vitepress build\",\n    \"serve\": \"vitepress serve\",\n    \"preview-https\": \"pnpm run build && serve .vitepress/dist\",\n    \"preview-https-no-prefetch\": \"pnpm run build-no-prefetch && serve .vitepress/dist\",\n    \"prefetch\": \"tsx .vitepress/scripts/fetch-avatars.ts\",\n    \"generate-pwa-icons\": \"pwa-assets-generator\"\n  },\n  \"dependencies\": {\n    \"@vueuse/core\": \"catalog:\",\n    \"vue\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@iconify-json/carbon\": \"catalog:\",\n    \"@iconify-json/logos\": \"catalog:\",\n    \"@iconify/vue\": \"catalog:\",\n    \"@shikijs/transformers\": \"^3.23.0\",\n    \"@shikijs/vitepress-twoslash\": \"^3.23.0\",\n    \"@unocss/reset\": \"catalog:\",\n    \"@vite-pwa/assets-generator\": \"^1.0.2\",\n    \"@vite-pwa/vitepress\": \"^1.1.0\",\n    \"@vitejs/plugin-vue\": \"catalog:\",\n    \"@voidzero-dev/vitepress-theme\": \"^4.8.3\",\n    \"https-localhost\": \"^4.7.1\",\n    \"tinyglobby\": \"catalog:\",\n    \"unocss\": \"catalog:\",\n    \"vite\": \"^6.3.5\",\n    \"vite-plugin-pwa\": \"^1.2.0\",\n    \"vitepress\": \"2.0.0-alpha.16\",\n    \"vitepress-plugin-group-icons\": \"^1.7.1\",\n    \"vitepress-plugin-llms\": \"^1.11.0\",\n    \"vitepress-plugin-tabs\": \"^0.8.0\",\n    \"workbox-window\": \"^7.4.0\"\n  }\n}\n"
  },
  {
    "path": "docs/public/_headers",
    "content": "/\n  X-Frame-Options: DENY\n  X-XSS-Protection: 1; mode=block\n\n/api/\n  X-Frame-Options: DENY\n  X-XSS-Protection: 1; mode=block\n\n/config/\n  X-Frame-Options: DENY\n  X-XSS-Protection: 1; mode=block\n\n/guide/\n  X-Frame-Options: DENY\n  X-XSS-Protection: 1; mode=block\n\n/*.html\n  X-Frame-Options: DENY\n  X-XSS-Protection: 1; mode=block\n\n/*\n  X-Content-Type-Options: nosniff\n  Referrer-Policy: no-referrer\n  Strict-Transport-Security: max-age=31536000; includeSubDomains\n\n/assets/*\n  cache-control: max-age=31536000\n  cache-control: immutable\n"
  },
  {
    "path": "docs/public/robots.txt",
    "content": "User-agent: *\nAllow: /\n"
  },
  {
    "path": "docs/pwa-assets.config.ts",
    "content": "import {\n  defineConfig,\n  minimalPreset as preset,\n} from '@vite-pwa/assets-generator/config'\n\nexport default defineConfig({\n  preset: {\n    ...preset,\n    assetName(type, size) {\n      switch (type) {\n        case 'transparent':\n          return `pwa-${size.width}x${size.height}.png`\n        case 'maskable':\n          return 'maskable-icon.png'\n        case 'apple':\n          return 'apple-touch-icon.png'\n      }\n    },\n  },\n  images: ['public/logo.svg'],\n})\n"
  },
  {
    "path": "docs/team.md",
    "content": "---\nlayout: page\ntitle: Meet the Team\ndescription: The development of Vitest is guided by an international team.\n---\n\n<script setup>\nimport {\n  VPTeamPage,\n  VPTeamPageTitle,\n  VPTeamPageSection,\n  VPTeamMembers\n} from '@voidzero-dev/vitepress-theme'\nimport { teamMembers, teamEmeritiMembers } from './.vitepress/contributors'\n</script>\n\n<VPTeamPage>\n  <VPTeamPageTitle>\n    <template #title>Meet the Team</template>\n    <template #lead>\n      The development of Vitest is guided by an international team, some of whom\n      have chosen to be featured below.\n    </template>\n  </VPTeamPageTitle>\n  <VPTeamMembers :members=\"teamMembers\" />\n  <VPTeamPageSection>\n    <template #title>Team Emeriti</template>\n    <template #lead>\n      Here we honor some no-longer-active team members who have made valuable\n      contributions in the past.\n    </template>\n    <template #members>\n      <VPTeamMembers size=\"small\" :members=\"teamEmeritiMembers\" />\n    </template>\n  </VPTeamPageSection>\n</VPTeamPage>\n"
  },
  {
    "path": "docs/todo.md",
    "content": "# Remove UnoCSS - Migration Complete\n\nUnoCSS was causing OOM in CI. Removed entirely and replaced with `@iconify/vue` + plain CSS.\n\n## Summary\n\n- Removed UnoCSS plugin from `vite.config.ts`\n- Removed `uno.css` import from `theme/index.ts`\n- Added `@iconify/vue` for icons\n- Converted all UnoCSS utilities to scoped CSS\n\n## Completed\n\n- [x] `vite.config.ts` - removed UnoCSS plugin\n- [x] `theme/index.ts` - removed `import 'uno.css'`\n- [x] `CRoot.vue` - @iconify/vue + CSS\n- [x] `ListItem.vue` - @iconify/vue + CSS (spinner, checkmark, close icons)\n- [x] `CourseLink.vue` - @iconify/vue + CSS\n- [x] `FeaturesList.vue` - plain CSS\n- [x] `Advanced.vue` - plain CSS\n- [x] `Experimental.vue` - plain CSS\n\n## Test pages\n\n- `/guide/features` - FeaturesList, ListItem, CourseLink\n- `/config/projects` - CRoot\n- `/api/advanced/vitest` - Experimental\n\n## Not used (skipped)\n\n- `HomePage.vue` - not used in new theme\n"
  },
  {
    "path": "docs/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"jsx\": \"preserve\",\n    \"lib\": [\"DOM\", \"ESNext\"],\n    \"baseUrl\": \".\",\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"Bundler\",\n    \"paths\": {\n      \"~/*\": [\"src/*\"]\n    },\n    \"resolveJsonModule\": true,\n    \"types\": [\n      \"vite/client\",\n      \"vite-plugin-pwa/client\",\n      \"vitepress\"\n    ],\n    \"strict\": true,\n    \"strictNullChecks\": true,\n    \"noUnusedLocals\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\n    \"./*.ts\",\n    \"./.vitepress/**/*.ts\",\n    \"./.vitepress/**/*.vue\"\n  ],\n  \"exclude\": [\"dist\", \"node_modules\"]\n}\n"
  },
  {
    "path": "docs/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  optimizeDeps: {\n    // vitepress is aliased with replacement `join(DIST_CLIENT_PATH, '/index')`\n    // This needs to be excluded from optimization\n    exclude: ['@vueuse/core', 'vitepress', '@docsearch/css'],\n  },\n})\n"
  },
  {
    "path": "eslint.config.js",
    "content": "import antfu, { GLOB_SRC } from '@antfu/eslint-config'\n\nexport default antfu(\n  {\n    vue: true,\n    // Disable tests rules because we need to test with various setup\n    test: false,\n    // This replaces the old `.gitignore`\n    ignores: [\n      '**/coverage',\n      '**/*.snap',\n      '**/bench.json',\n      '**/fixtures',\n      '**/assets/**',\n      '**/*.d.ts',\n      '**/*.timestamp-*',\n      'test/core/src/self',\n      'test/core/test/mocking/already-hoisted.test.ts',\n      'test/cache/cache/.vitest-base/results.json',\n      'test/core/src/wasm/wasm-bindgen-no-cyclic',\n      'test/workspaces/results.json',\n      'test/workspaces-browser/results.json',\n      'test/reporters/fixtures/with-syntax-error.test.js',\n      'test/network-imports/public/slash@3.0.0.js',\n      'test/coverage-test/src/transpiled.js',\n      'test/coverage-test/src/original.ts',\n      'test/cli/deps/error/*',\n      'examples/**/mockServiceWorker.js',\n      'examples/sveltekit/.svelte-kit',\n      'packages/browser/**/esm-client-injector.js',\n      // contains technically invalid code to display pretty diff\n      'docs/guide/snapshot.md',\n      // uses invalid js example\n      'docs/api/advanced/import-example.md',\n      'docs/guide/examples/*.md',\n    ],\n  },\n  {\n    rules: {\n      // prefer global Buffer to not initialize the whole module\n      'node/prefer-global/buffer': 'off',\n      'node/prefer-global/process': 'off',\n      'no-empty-pattern': 'off',\n      'antfu/indent-binary-ops': 'off',\n      'unused-imports/no-unused-imports': 'error',\n      'pnpm/json-enforce-catalog': 'off',\n      'style/member-delimiter-style': [\n        'error',\n        {\n          multiline: { delimiter: 'none' },\n          singleline: { delimiter: 'semi' },\n        },\n      ],\n      // let TypeScript handle this\n      'no-undef': 'off',\n      'ts/no-invalid-this': 'off',\n      'eslint-comments/no-unlimited-disable': 'off',\n      'curly': ['error', 'all'],\n\n      // TODO: migrate and turn it back on\n      'ts/ban-types': 'off',\n      'ts/no-unsafe-function-type': 'off',\n\n      'markdown/fenced-code-language': 'off',\n      // it uses parser which is not compatible with vitepress\n      'markdown/no-missing-link-fragments': 'off',\n\n      'no-restricted-imports': [\n        'error',\n        {\n          paths: ['path'],\n        },\n      ],\n\n      'import/no-named-as-default': 'off',\n    },\n  },\n  {\n    files: [`packages/*/*.{js,mjs,d.ts}`],\n    rules: {\n      'antfu/no-import-dist': 'off',\n    },\n  },\n  {\n    files: [`packages/${GLOB_SRC}`],\n    rules: {\n      'no-restricted-imports': [\n        'error',\n        {\n          paths: ['vitest', 'path', 'vitest/node'],\n        },\n      ],\n    },\n  },\n  {\n    // these files define vitest as peer dependency\n    files: [`packages/{coverage-*,ui,browser,web-worker,browser-*}/${GLOB_SRC}`],\n    rules: {\n      'no-restricted-imports': [\n        'error',\n        {\n          paths: ['path'],\n        },\n      ],\n    },\n  },\n  {\n    files: [\n      `docs/${GLOB_SRC}`,\n      `**/*.md`,\n      `**/*.md/${GLOB_SRC}`,\n    ],\n    rules: {\n      'prefer-arrow-callback': 'off',\n      'perfectionist/sort-imports': 'off',\n      'style/max-statements-per-line': 'off',\n      'import/newline-after-import': 'off',\n      'import/first': 'off',\n      'unused-imports/no-unused-imports': 'off',\n      'ts/method-signature-style': 'off',\n      'no-self-compare': 'off',\n      'import/no-mutable-exports': 'off',\n      'no-throw-literal': 'off',\n    },\n  },\n  {\n    files: [\n      `docs/${GLOB_SRC}`,\n      `packages/web-worker/${GLOB_SRC}`,\n      `test/core/${GLOB_SRC}`,\n    ],\n    rules: {\n      'no-restricted-globals': 'off',\n    },\n  },\n  {\n    files: [\n      `test/${GLOB_SRC}`,\n    ],\n    rules: {\n      'antfu/no-top-level-await': 'off',\n      'unicorn/consistent-function-scoping': 'off',\n    },\n  },\n)\n"
  },
  {
    "path": "examples/basic/README.md",
    "content": "# Vitest Demo\n\nRun `npm test` and change a test or source code to see HMR in action!\n\nLearn more at https://vitest.dev\n"
  },
  {
    "path": "examples/basic/package.json",
    "content": "{\n  \"name\": \"@vitest/example-test\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"license\": \"MIT\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"test:ui\": \"vitest --ui\",\n    \"test:run\": \"vitest run\"\n  },\n  \"devDependencies\": {\n    \"@vitest/ui\": \"latest\",\n    \"vite\": \"latest\",\n    \"vitest\": \"latest\"\n  },\n  \"stackblitz\": {\n    \"startCommand\": \"npm run test:ui\"\n  }\n}\n"
  },
  {
    "path": "examples/basic/src/basic.ts",
    "content": "export const squared = (n: number) => n * n\n"
  },
  {
    "path": "examples/basic/test/__snapshots__/suite.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`suite name > snapshot 1`] = `\n{\n  \"foo\": \"bar\",\n}\n`;\n"
  },
  {
    "path": "examples/basic/test/basic.test.ts",
    "content": "import { assert, expect, test } from 'vitest'\nimport { squared } from '../src/basic.js'\n\n// Edit an assertion and save to see HMR in action\n\ntest('Math.sqrt()', () => {\n  expect(Math.sqrt(4)).toBe(2)\n  expect(Math.sqrt(144)).toBe(12)\n  expect(Math.sqrt(2)).toBe(Math.SQRT2)\n})\n\ntest('Squared', () => {\n  expect(squared(2)).toBe(4)\n  expect(squared(12)).toBe(144)\n})\n\ntest('JSON', () => {\n  const input = {\n    foo: 'hello',\n    bar: 'world',\n  }\n\n  const output = JSON.stringify(input)\n\n  expect(output).eq('{\"foo\":\"hello\",\"bar\":\"world\"}')\n  assert.deepEqual(JSON.parse(output), input, 'matches original')\n})\n"
  },
  {
    "path": "examples/basic/test/suite.test.ts",
    "content": "import { assert, describe, expect, it } from 'vitest'\n\ndescribe('suite name', () => {\n  it('foo', () => {\n    assert.equal(Math.sqrt(4), 2)\n  })\n\n  it('bar', () => {\n    expect(1 + 1).eq(2)\n  })\n\n  it('snapshot', () => {\n    expect({ foo: 'bar' }).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "examples/basic/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"module\": \"node16\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"sourceMap\": true,\n    \"verbatimModuleSyntax\": true\n  },\n  \"include\": [\"src\", \"test\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/basic/vite.config.ts",
    "content": "/// <reference types=\"vitest/config\" />\n\n// Configure Vitest (https://vitest.dev/config/)\n\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    /* for example, use global to avoid globals imports (describe, test, expect): */\n    // globals: true,\n  },\n})\n"
  },
  {
    "path": "examples/fastify/mockData.ts",
    "content": "const usersData = [{\n  id: 1,\n  name: 'John Snow',\n  email: 'john@got.com',\n}, {\n  id: 2,\n  name: 'Daenerys Targaryen',\n  email: 'daenerys@got.com',\n}, {\n  id: 3,\n  name: 'Arya Stark',\n  email: 'arya@got.com',\n}, {\n  id: 4,\n  name: 'Rhaenyra Targaryen',\n  email: 'rhaenyra@hod.com',\n}]\nexport { usersData }\n"
  },
  {
    "path": "examples/fastify/package.json",
    "content": "{\n  \"name\": \"@vitest/example-fastify\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"license\": \"MIT\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"dev\": \"NODE_ENV=development tsx watch src\",\n    \"test\": \"vitest\",\n    \"test:ui\": \"vitest --ui\",\n    \"test:run\": \"vitest run\"\n  },\n  \"devDependencies\": {\n    \"@vitest/ui\": \"latest\",\n    \"fastify\": \"^5.7.2\",\n    \"supertest\": \"^7.2.2\",\n    \"tsx\": \"^4.21.0\",\n    \"vite\": \"latest\",\n    \"vitest\": \"latest\"\n  },\n  \"stackblitz\": {\n    \"startCommand\": \"npm run test:ui\"\n  }\n}\n"
  },
  {
    "path": "examples/fastify/src/app.ts",
    "content": "import type { FastifyInstance } from 'fastify'\nimport Fastify from 'fastify'\nimport { usersData } from '../mockData'\n\nconst app: FastifyInstance = Fastify({\n  logger: process.env.NODE_ENV === 'development',\n})\n\napp.get('/users', async () => {\n  return usersData\n})\n\nexport default app\n"
  },
  {
    "path": "examples/fastify/src/index.ts",
    "content": "import app from './app'\n\nasync function start() {\n  try {\n    await app.listen({ port: 3000 })\n  }\n  catch (err) {\n    app.log.error(err)\n    process.exit(1)\n  }\n}\n\nstart()\n"
  },
  {
    "path": "examples/fastify/test/app.test.ts",
    "content": "import supertest from 'supertest'\nimport { afterAll, expect, test } from 'vitest'\n\nimport { usersData } from '../mockData'\nimport app from '../src/app'\n\ntest('with HTTP injection', async () => {\n  const response = await app.inject({\n    method: 'GET',\n    url: '/users',\n  })\n\n  expect(response.statusCode).toBe(200)\n  expect(JSON.parse(response.payload)).toHaveLength(4)\n  expect(JSON.parse(response.payload)).toStrictEqual(usersData)\n})\n\ntest('with a running server', async () => {\n  await app.ready()\n\n  const response = await supertest(app.server)\n    .get('/users')\n    .expect(200)\n\n  expect(response.body).toHaveLength(4)\n  expect(response.body).toStrictEqual(usersData)\n})\n\ntest('with axios', async () => {\n  await app.listen()\n  await app.ready()\n\n  const address = app.server.address()\n  const port = typeof address === 'string' ? address : address?.port\n\n  const response = await fetch(`http://localhost:${port}/users`).then(r => r.json())\n\n  expect(response).toHaveLength(4)\n  expect(response).toStrictEqual(usersData)\n})\n\nafterAll(async () => {\n  await app.close()\n})\n"
  },
  {
    "path": "examples/in-source-test/package.json",
    "content": "{\n  \"name\": \"@vitest/example-in-source-test\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"test:run\": \"vitest run\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5.9.3\",\n    \"vitest\": \"latest\"\n  }\n}\n"
  },
  {
    "path": "examples/in-source-test/src/index.ts",
    "content": "// the implementation\nexport function add(...args: number[]) {\n  return args.reduce((a, b) => a + b, 0)\n}\n\n// in-source test suites\nif (import.meta.vitest) {\n  const { it, expect } = import.meta.vitest\n  it('add', () => {\n    expect(add()).toBe(0)\n    expect(add(1)).toBe(1)\n    expect(add(1, 2, 3)).toBe(6)\n  })\n}\n"
  },
  {
    "path": "examples/in-source-test/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"types\": [\n      \"vitest/importMeta\"\n    ],\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/in-source-test/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    includeSource: ['src/**/*.{js,ts}'],\n  },\n})\n"
  },
  {
    "path": "examples/lit/.gitignore",
    "content": "__traces__\n__screenshots__\n"
  },
  {
    "path": "examples/lit/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Lit App</title>\n    <script type=\"module\" src=\"/src/my-button.ts\"></script>\n  </head>\n  <body>\n    <my-button name=\"World\">\n      <p>This is child content</p>\n    </my-button>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/lit/package.json",
    "content": "{\n  \"name\": \"@vitest/example-lit\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"files\": [\n    \"dist\",\n    \"types\"\n  ],\n  \"scripts\": {\n    \"coverage\": \"vitest run --coverage\",\n    \"dev\": \"vite\",\n    \"test\": \"vitest\",\n    \"list\": \"vitest list\",\n    \"test:ui\": \"vitest --ui\"\n  },\n  \"dependencies\": {\n    \"lit\": \"^3.3.2\"\n  },\n  \"devDependencies\": {\n    \"@vitest/browser-playwright\": \"latest\",\n    \"jsdom\": \"latest\",\n    \"playwright\": \"^1.58.2\",\n    \"vite\": \"latest\",\n    \"vitest\": \"latest\"\n  },\n  \"stackblitz\": {\n    \"startCommand\": \"npm run test:ui\"\n  }\n}\n"
  },
  {
    "path": "examples/lit/src/my-button.ts",
    "content": "import { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n/**\n * An example button.\n *\n * @slot - This button has a slot\n */\n@customElement('my-button')\nexport class MyButton extends LitElement {\n  static styles = css`\n    :host {\n      display: block;\n      border: solid 1px gray;\n      padding: 16px;\n      max-width: 800px;\n    }\n  `\n\n  /**\n   * The name to say \"Hello\" to.\n   */\n  @property()\n  name = 'World'\n\n  /**\n   * The number of times the button has been clicked.\n   */\n  @property({ type: Number })\n  count = 1\n\n  render() {\n    return html`\n      <h1>Hello, ${this.name}!</h1>\n      <button @click=${this._onClick} role=\"button\">\n        Click Count: ${this.count}\n      </button>\n      <slot></slot>\n    `\n  }\n\n  private _onClick() {\n    this.count++\n    this.dispatchEvent(new CustomEvent('count', { detail: this.count }))\n  }\n\n  foo(): string {\n    return 'foo'\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'my-button': MyButton\n  }\n}\n"
  },
  {
    "path": "examples/lit/test/basic.test.ts",
    "content": "import { beforeEach, describe, expect, it } from 'vitest'\nimport { page } from 'vitest/browser'\n\nimport '../src/my-button.js'\n\ndescribe('Button with increment', async () => {\n  beforeEach(async () => {\n    await page.mark('render', async () => {\n      document.body.innerHTML = '<my-button name=\"World\"></my-button>'\n      await page.getByRole('button').mark('render button')\n    })\n  })\n\n  it('should increment the count on each click', async () => {\n    await page.getByRole('button').click()\n\n    await expect.element(page.getByRole('button')).toHaveTextContent('2')\n    if (import.meta.env.VITE_FAIL_TEST) {\n      await expect.element(page.getByRole('button'), { timeout: 3000 }).toHaveTextContent('3')\n    }\n  })\n\n  it('should show name props', async () => {\n    await expect.element(page.getByRole('heading')).toHaveTextContent('World')\n  })\n})\n"
  },
  {
    "path": "examples/lit/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"useDefineForClassFields\": false,\n    \"experimentalDecorators\": true,\n    \"module\": \"node16\",\n    \"moduleResolution\": \"Node16\",\n    \"types\": [\"vite/client\"],\n    \"verbatimModuleSyntax\": true\n  }\n}\n"
  },
  {
    "path": "examples/lit/vite.config.ts",
    "content": "/// <reference types=\"vitest/config\" />\n\nimport { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vite'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  test: {\n    // Lit recommends using browser environment for testing\n    // https://lit.dev/docs/tools/testing/#testing-in-the-browser\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  },\n})\n"
  },
  {
    "path": "examples/opentelemetry/README.md",
    "content": "# Vitest Opentelemtry Example\n\n- **Documentation**: https://vitest.dev/guide/open-telemetry.html\n\n## Usage\n\n```sh\n# Start Jaeger service to receive otlp traces over http\n# and serve Web UI at http://localhost:16686\ndocker compose up -d\n\n# Run tests (exports with OTLP HTTP by deafult)\npnpm test --experimental.openTelemetry.enabled\n\n# Use console exporter for quick debugging\nOTEL_TRACES_EXPORTER=console pnpm test --experimental.openTelemetry.enabled\n\n# Run browser mode\npnpm test --experimental.openTelemetry.enabled --browser.enabled\n```\n"
  },
  {
    "path": "examples/opentelemetry/docker-compose.yaml",
    "content": "services:\n  # for testing open-telemetry integration locally\n  # https://www.jaegertracing.io/docs/2.12/getting-started/\n  jaeger:\n    image: cr.jaegertracing.io/jaegertracing/jaeger:2.16.0\n    # Assign ports for Jaeger UI and OTLP receiver\n    ports:\n      # UI http://localhost:16686\n      - 16686:16686\n      # OTLP over HTTP (default for NodeSDK)\n      - 4318:4318\n      # Optional: uncomment if needed\n      # - 4317:4317  # OTLP over gRPC\n      # - 5778:5778  # Jaeger sampling strategies\n      # - 9411:9411  # Zipkin compatibility\n\n    # Use volume to persist data across container restarts.\n    # This can be commented out if persistence is not needed.\n    # https://www.jaegertracing.io/docs/2.12/storage/badger/\n    user: '0:0'\n    command: --config /etc/jaeger/config.yml\n    volumes:\n      - ./jaeger-config.yml:/etc/jaeger/config.yml:ro\n      - jaeger-data:/tmp/badger\n\nvolumes:\n  jaeger-data:\n"
  },
  {
    "path": "examples/opentelemetry/jaeger-config.yml",
    "content": "# https://www.jaegertracing.io/docs/2.12/deployment/configuration/\nextensions:\n  jaeger_storage:\n    backends:\n      main_storage:\n        badger:\n          directories:\n            keys: /tmp/badger/keys\n            values: /tmp/badger/data\n          ephemeral: false\n          consistency: true\n          maintenance_interval: 5m\n  jaeger_query:\n    storage:\n      traces: main_storage\n\n# https://opentelemetry.io/docs/languages/js/exporters/#configure-cors-headers\nreceivers:\n  otlp:\n    protocols:\n      http:\n        endpoint: 0.0.0.0:4318\n        cors:\n          allowed_origins:\n            - http://localhost:*\n\nprocessors:\n  batch:\n\nexporters:\n  jaeger_storage_exporter:\n    trace_storage: main_storage\n\nservice:\n  extensions: [jaeger_storage, jaeger_query]\n  pipelines:\n    traces:\n      receivers: [otlp]\n      processors: [batch]\n      exporters: [jaeger_storage_exporter]\n"
  },
  {
    "path": "examples/opentelemetry/otel-browser.js",
    "content": "import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'\nimport { resourceFromAttributes } from '@opentelemetry/resources'\nimport { BatchSpanProcessor, WebTracerProvider } from '@opentelemetry/sdk-trace-web'\n\nconst provider = new WebTracerProvider({\n  resource: resourceFromAttributes({\n    'service.name': 'vitest-browser',\n  }),\n  spanProcessors: [\n    new BatchSpanProcessor(new OTLPTraceExporter()),\n    // you can add a ConsoleSpanExporter for debugging purposes\n    // (available in @opentelemetry/sdk-trace-web)\n    // new SimpleSpanProcessor(new ConsoleSpanExporter()),\n  ],\n})\n\nprovider.register({\n  // you can customize contextManager but browser support has limitation\n  // cf. https://github.com/open-telemetry/opentelemetry-js/discussions/2060\n  // contextManager: new StackContextManager(), // this is the default (avialable in sdk-trace-web)\n  // contextManager: new ZoneContextManager(), // doesn't seem to help (avialable in @opentelemetry/context-zone)\n})\n\nexport default provider\n"
  },
  {
    "path": "examples/opentelemetry/otel.js",
    "content": "// @ts-check\nimport { NodeSDK } from '@opentelemetry/sdk-node'\n\nconst sdk = new NodeSDK({\n  serviceName: 'vitest',\n\n  // NodeSDK uses \"@opentelemetry/exporter-trace-otlp-proto\" by default.\n  // you can override it via `traceExporter` options.\n  // traceExporter: ...,\n\n  // you can configure additional instrumentations such as `@opentelemetry/auto-instrumentations-node`\n  // via `instrumentations` options.\n  // instrumentations: ...\n})\nsdk.start()\nexport default sdk\n"
  },
  {
    "path": "examples/opentelemetry/package.json",
    "content": "{\n  \"name\": \"@vitest/example-opentelemetry\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"compose\": \"docker compose\",\n    \"test\": \"vitest\"\n  },\n  \"devDependencies\": {\n    \"@opentelemetry/api\": \"^1.9.0\",\n    \"@opentelemetry/context-zone\": \"^2.6.0\",\n    \"@opentelemetry/exporter-trace-otlp-proto\": \"^0.213.0\",\n    \"@opentelemetry/resources\": \"^2.6.0\",\n    \"@opentelemetry/sdk-node\": \"^0.213.0\",\n    \"@opentelemetry/sdk-trace-web\": \"^2.6.0\",\n    \"@vitest/browser-playwright\": \"latest\",\n    \"vite\": \"latest\",\n    \"vitest\": \"latest\"\n  }\n}\n"
  },
  {
    "path": "examples/opentelemetry/src/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { sleep } from './basic'\n\ntest('one plus one', async () => {\n  await sleep(100)\n  expect(1 + 1).toBe(2)\n})\n\ntest('one plus two', async () => {\n  expect(1 + 2).toBe(3)\n})\n"
  },
  {
    "path": "examples/opentelemetry/src/basic.ts",
    "content": "export function sleep(ms: number): Promise<void> {\n  return new Promise(resolve => setTimeout(resolve, ms))\n}\n"
  },
  {
    "path": "examples/opentelemetry/src/other.test.ts",
    "content": "import { trace } from '@opentelemetry/api'\nimport { test } from 'vitest'\n\ntest('other', async () => {\n  await new Promise(r => setTimeout(r, 150))\n})\n\ntest('custom', async () => {\n  // this starts span synchronously inside test function,\n  // so trace parent works without async context manager (e.g. on browser mode).\n\n  // console.log(context.active())\n  // > vitest.test.runner.test.callback\n  //   > custom-span\n\n  const tracer = trace.getTracer('custom-scope')\n  await tracer.startActiveSpan('custom-span', async (span) => {\n    span.setAttribute('custom-attribute', 'hello world')\n    await new Promise(resolve => setTimeout(resolve, 50))\n    span.end()\n  })\n\n  // however the context is dropped on browser mode.\n  // console.log(context.active())\n})\n\ntest.runIf(typeof document !== 'undefined')('browser test', async () => {\n  const { page } = await import('vitest/browser')\n  document.body.innerHTML = `<button>Hello Vitest</button>`\n  await page.getByRole('button', { name: 'Hello Vitest' }).click()\n})\n"
  },
  {
    "path": "examples/opentelemetry/vite.config.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    experimental: {\n      openTelemetry: {\n        // enable via CLI flag --experimental.openTelemetry.enabled=true\n        enabled: false,\n        sdkPath: './otel.js',\n        browserSdkPath: './otel-browser.js',\n      },\n    },\n    browser: {\n      // enable via CLI flag --browser.enabled=true\n      enabled: false,\n      provider: playwright(),\n      instances: [{ browser: 'chromium' }],\n    },\n  },\n})\n"
  },
  {
    "path": "examples/profiling/global-setup.ts",
    "content": "import { rmSync } from 'node:fs'\n\nexport function setup() {\n  rmSync('./threads-profile', { force: true, recursive: true })\n  rmSync('./forks-profile', { force: true, recursive: true })\n}\n"
  },
  {
    "path": "examples/profiling/package.json",
    "content": "{\n  \"name\": \"@vitest/example-profiling\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"test\": \"vitest\"\n  },\n  \"devDependencies\": {\n    \"vite\": \"latest\",\n    \"vitest\": \"latest\"\n  }\n}\n"
  },
  {
    "path": "examples/profiling/src/prime-number.ts",
    "content": "/* eslint-disable unicorn/no-new-array */\n\nconst store: bigint[] = []\n\nexport default function getPrimeNumber(bitLength: number): bigint {\n  if (!bitLength) {\n    throw new Error('bitLength is required')\n  }\n\n  const number = randomBigInt(bitLength)\n\n  if (isPrimeNumber(number) && !store.includes(number)) {\n    store.push(number)\n\n    return number\n  }\n\n  return getPrimeNumber(bitLength)\n}\n\n/**\n * Generate random `BigInt` with given bit length\n * e.g. randomBigInt(8) -> 153n (1001 1001)\n */\nfunction randomBigInt(bitLength: number): bigint {\n  const binaryString: string = new Array(bitLength)\n    // MSB should be one to guarantee bit length\n    .fill('1')\n    // Fill string with 0s and 1s\n    .reduce(bin => bin + Math.round(Math.random()).toString())\n\n  return BigInt(`0b${binaryString}`)\n}\n\nfunction isPrimeNumber(number: bigint): boolean {\n  if (number <= 2n) {\n    return false\n  }\n\n  if (number % 2n === 0n) {\n    return false\n  }\n\n  if (number === 3n) {\n    return true\n  }\n\n  const squareRoot = bigIntSquareRoot(number)\n\n  // Intentionally inefficient to highlight performance issues\n  for (let i = 3n; i < squareRoot; i += 2n) {\n    if (number % i === 0n) {\n      return false\n    }\n  }\n\n  return true\n}\n\nfunction bigIntSquareRoot(number: bigint): bigint {\n  if (number < 0n) {\n    throw new Error('Negative numbers are not supported')\n  }\n  if (number < 2n) {\n    return number\n  }\n\n  function iterate(value: bigint, guess: bigint): bigint {\n    const nextGuess = (value / guess + guess) >> 1n\n\n    if (guess === nextGuess) {\n      return guess\n    }\n    if (guess === nextGuess - 1n) {\n      return guess\n    }\n\n    return iterate(value, nextGuess)\n  }\n\n  return iterate(number, 1n)\n}\n"
  },
  {
    "path": "examples/profiling/test/prime-number.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport getPrimeNumber from '../src/prime-number'\n\nconst BITS = process.env.CI ? 8 : 62\n\ntest('generate prime number', () => {\n  const prime = getPrimeNumber(BITS)\n\n  expect(prime).toBeGreaterThanOrEqual(0)\n  expect(prime).toBeLessThanOrEqual(2 ** BITS)\n})\n"
  },
  {
    "path": "examples/profiling/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    watch: false,\n    globalSetup: './global-setup.ts',\n\n    // Generate a single profile\n    fileParallelism: false,\n\n    execArgv: [\n      // https://nodejs.org/api/cli.html#--cpu-prof\n      '--cpu-prof',\n      '--cpu-prof-dir=vitest-profile',\n\n      // https://nodejs.org/api/cli.html#--heap-prof\n      '--heap-prof',\n      '--heap-prof-dir=vitest-profile',\n    ],\n  },\n})\n"
  },
  {
    "path": "examples/projects/package.json",
    "content": "{\n  \"name\": \"@vitest/example-projects\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"test:ui\": \"vitest --ui\",\n    \"test:run\": \"vitest run\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/jest-dom\": \"^6.9.1\",\n    \"@testing-library/react\": \"^16.3.2\",\n    \"@testing-library/user-event\": \"^14.6.1\",\n    \"@types/react\": \"^19.2.14\",\n    \"@vitejs/plugin-react\": \"^5.1.4\",\n    \"@vitest/ui\": \"latest\",\n    \"fastify\": \"^5.7.2\",\n    \"jsdom\": \"^27.4.0\",\n    \"react\": \"^19.2.4\",\n    \"supertest\": \"^7.2.2\",\n    \"tsx\": \"^4.21.0\",\n    \"vite\": \"latest\",\n    \"vitest\": \"latest\"\n  },\n  \"workspaces\": [\n    \"packages/*\"\n  ],\n  \"stackblitz\": {\n    \"startCommand\": \"npm run test:ui\"\n  }\n}\n"
  },
  {
    "path": "examples/projects/packages/client/components/Link.tsx",
    "content": "import React, { useState } from 'react'\n\nconst STATUS = {\n  HOVERED: 'hovered',\n  NORMAL: 'normal',\n}\n\nfunction Link({ page, children }: React.PropsWithChildren<{ page: string }>) {\n  const [status, setStatus] = useState(STATUS.NORMAL)\n\n  const onMouseEnter = () => {\n    setStatus(STATUS.HOVERED)\n  }\n\n  const onMouseLeave = () => {\n    setStatus(STATUS.NORMAL)\n  }\n\n  return (\n    <a\n      className={status}\n      href={page || '#'}\n      aria-label={`Link is ${status}`}\n      onMouseEnter={onMouseEnter}\n      onMouseLeave={onMouseLeave}\n    >\n      {children}\n    </a>\n  )\n}\n\nexport default Link\n"
  },
  {
    "path": "examples/projects/packages/client/test/basic.test.tsx",
    "content": "import { render, screen } from '@testing-library/react'\nimport { userEvent } from '@testing-library/user-event'\nimport React from 'react'\nimport { expect, test } from 'vitest'\nimport Link from '../components/Link.js'\n\ntest('Link changes the state when hovered', async () => {\n  render(\n    <Link page=\"http://antfu.me\">Anthony Fu</Link>,\n  )\n\n  const link = screen.getByText('Anthony Fu')\n\n  expect(link).toHaveAccessibleName('Link is normal')\n\n  await userEvent.hover(link)\n\n  await expect.poll(() => link).toHaveAccessibleName('Link is hovered')\n\n  await userEvent.unhover(link)\n\n  await expect.poll(() => link).toHaveAccessibleName('Link is normal')\n})\n"
  },
  {
    "path": "examples/projects/packages/client/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"jsx\": \"react\",\n    \"lib\": [\"esnext\", \"dom\"],\n    \"module\": \"node16\",\n    \"moduleResolution\": \"node16\",\n    \"types\": [\"@testing-library/jest-dom\"],\n    \"strict\": true,\n    \"declaration\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \"./vitest.setup.ts\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/projects/packages/client/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    environment: 'jsdom',\n    setupFiles: './vitest.setup.ts',\n  },\n})\n"
  },
  {
    "path": "examples/projects/packages/client/vitest.setup.ts",
    "content": "import '@testing-library/jest-dom/vitest'\n"
  },
  {
    "path": "examples/projects/packages/server/mockData.ts",
    "content": "const usersData = [{\n  id: 1,\n  name: 'John Snow',\n  email: 'john@got.com',\n}, {\n  id: 2,\n  name: 'Daenerys Targaryen',\n  email: 'daenerys@got.com',\n}, {\n  id: 3,\n  name: 'Arya Stark',\n  email: 'arya@got.com',\n}, {\n  id: 4,\n  name: 'Rhaenyra Targaryen',\n  email: 'rhaenyra@hod.com',\n}]\nexport { usersData }\n"
  },
  {
    "path": "examples/projects/packages/server/src/app.ts",
    "content": "import type { FastifyInstance } from 'fastify'\nimport Fastify from 'fastify'\nimport { usersData } from '../mockData.js'\n\nconst app: FastifyInstance = Fastify({\n  logger: process.env.NODE_ENV === 'development',\n})\n\napp.get('/users', async () => {\n  return usersData\n})\n\nexport default app\n"
  },
  {
    "path": "examples/projects/packages/server/src/index.ts",
    "content": "import app from './app.js'\n\nasync function start() {\n  try {\n    await app.listen({ port: 3000 })\n  }\n  catch (err) {\n    app.log.error(err)\n    process.exit(1)\n  }\n}\n\nstart()\n"
  },
  {
    "path": "examples/projects/packages/server/test/app.test.ts",
    "content": "import supertest from 'supertest'\nimport { afterAll, expect, test } from 'vitest'\n\nimport { usersData } from '../mockData.js'\nimport app from '../src/app.js'\n\ntest('with HTTP injection', async () => {\n  const response = await app.inject({\n    method: 'GET',\n    url: '/users',\n  })\n\n  expect(response.statusCode).toBe(200)\n  expect(JSON.parse(response.payload)).toHaveLength(4)\n  expect(JSON.parse(response.payload)).toStrictEqual(usersData)\n})\n\ntest('with a running server', async () => {\n  await app.ready()\n\n  const response = await supertest(app.server)\n    .get('/users')\n    .expect(200)\n\n  expect(response.body).toHaveLength(4)\n  expect(response.body).toStrictEqual(usersData)\n})\n\ntest('with axios', async () => {\n  await app.listen()\n  await app.ready()\n\n  const address = app.server.address()\n  const port = typeof address === 'string' ? address : address?.port\n\n  const response = await fetch(`http://localhost:${port}/users`).then(r => r.json())\n\n  expect(response).toHaveLength(4)\n  expect(response).toStrictEqual(usersData)\n})\n\nafterAll(async () => {\n  await app.close()\n})\n"
  },
  {
    "path": "examples/projects/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"module\": \"node16\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"sourceMap\": true,\n    \"verbatimModuleSyntax\": true\n  },\n  \"include\": [\"packages\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/projects/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: ['packages/*'],\n  },\n})\n"
  },
  {
    "path": "examples/typecheck/package.json",
    "content": "{\n  \"name\": \"@vitest/example-typecheck\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"license\": \"MIT\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"test:ui\": \"vitest --ui\",\n    \"test:run\": \"vitest run\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^24.12.0\",\n    \"@vitest/ui\": \"latest\",\n    \"typescript\": \"^5.9.3\",\n    \"vite\": \"latest\",\n    \"vitest\": \"latest\"\n  },\n  \"stackblitz\": {\n    \"startCommand\": \"npm run test:ui\"\n  }\n}\n"
  },
  {
    "path": "examples/typecheck/test/normal.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('normal', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "examples/typecheck/test/type.test-d.ts",
    "content": "import { expect, expectTypeOf, test } from 'vitest'\n\ntest('type', () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n  expect(1).toBe(2) // not executed\n})\n"
  },
  {
    "path": "examples/typecheck/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"sourceMap\": true,\n    \"verbatimModuleSyntax\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"src\", \"test\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "examples/typecheck/vite.config.ts",
    "content": "/// <reference types=\"vitest/config\" />\n\n// Configure Vitest (https://vitest.dev/config/)\n\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    /* for example, use global to avoid globals imports (describe, test, expect): */\n    // globals: true,\n    typecheck: {\n      enabled: true,\n    },\n  },\n})\n"
  },
  {
    "path": "netlify.toml",
    "content": "[build]\npublish = \"docs/.vitepress/dist\"\ncommand = \"pnpm ci:docs\"\nignore = \"git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF docs/ package.json pnpm-lock.yaml\"\n\n[build.environment]\nNODE_VERSION = \"24\"\n# don't need playwright for docs build\nPLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = \"1\"\n# https://github.com/nodejs/corepack/issues/612#issuecomment-2631462297\nCOREPACK_INTEGRITY_KEYS = '{\"npm\":[{\"expires\":\"2025-01-29T00:00:00.000Z\",\"keyid\":\"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA\",\"keytype\":\"ecdsa-sha2-nistp256\",\"scheme\":\"ecdsa-sha2-nistp256\",\"key\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg==\"},{\"expires\":null,\"keyid\":\"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U\",\"keytype\":\"ecdsa-sha2-nistp256\",\"scheme\":\"ecdsa-sha2-nistp256\",\"key\":\"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEY6Ya7W++7aUPzvMTrezH6Ycx3c+HOKYCcNGybJZSCJq/fd7Qa8uuAKtdIkUQtQiEKERhAmE5lMMJhP8OkDOa2g==\"}]}'\n\n[[redirects]]\nfrom = \"/new\"\nto = \"https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/basic?initialPath=__vitest__/\"\nstatus = 302\n\n[[redirects]]\nfrom = \"/vscode\"\nto = \"https://marketplace.visualstudio.com/items?itemName=vitest.explorer\"\nstatus = 302\n\n[[redirects]]\nfrom = \"/config/file\"\nto = \"/config/\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/config/browser\"\nto = \"/config/browser/enabled\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/guide/workspace\"\nto = \"/guide/projects\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/advanced/api\"\nto = \"/guide/advanced\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/advanced/api/*\"\nto = \"/api/advanced/:splat\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/advanced/*\"\nto = \"/guide/advanced/:splat\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/guide/workspace.html\"\nto = \"/guide/projects\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/guide/browser/context\"\nto = \"/api/browser/context\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/guide/browser/interactivity-api\"\nto = \"/api/browser/interactivity\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/guide/browser/locators\"\nto = \"/api/browser/locators\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/guide/browser/assertion-api\"\nto = \"/api/browser/assertions\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/guide/browser/commands\"\nto = \"/api/browser/commands\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/guide/browser/playwright\"\nto = \"/config/browser/playwright\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/guide/browser/webdriverio\"\nto = \"/config/browser/webdriverio\"\nstatus = 301\n\n[[redirects]]\nfrom = \"/api/\"\nto = \"/api/test\"\nstatus = 301\n\n[[headers]]\nfor = \"/manifest.webmanifest\"\n\n[headers.values]\nContent-Type = \"application/manifest+json\"\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@vitest/monorepo\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"private\": true,\n  \"packageManager\": \"pnpm@10.31.0\",\n  \"description\": \"Next generation testing framework powered by Vite\",\n  \"engines\": {\n    \"node\": \"^20.0.0 || ^22.0.0 || >=24.0.0\"\n  },\n  \"scripts\": {\n    \"ci\": \"ni && nr typecheck && nr lint && nr build && nr test:ci\",\n    \"ci:docs\": \"pnpm run build && pnpm run docs:build\",\n    \"build\": \"pnpm -r --filter @vitest/ui --filter='./packages/**' run build\",\n    \"dev\": \"NODE_OPTIONS=\\\"--max-old-space-size=8192\\\" pnpm -r --parallel --filter='./packages/**' run dev\",\n    \"docs\": \"pnpm -C docs run dev\",\n    \"docs:build\": \"ROLLDOWN_OPTIONS_VALIDATION=loose pnpm -C docs run build\",\n    \"docs:serve\": \"pnpm -C docs run serve\",\n    \"docs:https\": \"pnpm -C docs run preview-https\",\n    \"docs:https-no-prefetch\": \"pnpm -C docs run preview-https-no-prefetch\",\n    \"docs:contributors\": \"tsx scripts/update-contributors.ts\",\n    \"lint\": \"eslint --cache .\",\n    \"lint:fix\": \"nr lint --fix\",\n    \"publish-ci\": \"tsx scripts/publish-ci.ts\",\n    \"release\": \"tsx scripts/release.ts\",\n    \"test\": \"pnpm --filter test-core test:threads\",\n    \"test:ci\": \"CI=true pnpm -r --reporter-hide-prefix --stream --sequential --filter '@vitest/test-*' --filter !test-browser run test\",\n    \"test:ci:no-bail\": \"CI=true pnpm -r --no-bail --reporter-hide-prefix --stream --sequential --filter '@vitest/test-*' --filter !test-browser run test\",\n    \"test:ci:cache\": \"CI=true pnpm -r --reporter-hide-prefix --stream --sequential --filter '@vitest/test-*' --filter !test-browser --filter '!@vitest/test-integration-dts-*' --filter !test-ui --filter !test-cache run test --experimental.fsModuleCache\",\n    \"test:examples\": \"CI=true pnpm -r --reporter-hide-prefix --stream --filter '@vitest/example-*' run test\",\n    \"test:ecosystem-ci\": \"ECOSYSTEM_CI=true pnpm test:ci\",\n    \"typebuild\": \"tsx ./scripts/explain-types.ts\",\n    \"typecheck\": \"tsc -p tsconfig.check.json --noEmit\",\n    \"typecheck:why\": \"tsc -p tsconfig.check.json --noEmit --explainFiles > explainTypes.txt\",\n    \"ui:build\": \"vite build packages/ui\",\n    \"ui:dev\": \"npm -C packages/ui run dev:client\",\n    \"ui:test\": \"npm -C packages/ui run test:run\",\n    \"override-rolldown\": \"yq -i '.overrides.vite = \\\"npm:vite@8\\\"' pnpm-workspace.yaml\",\n    \"test:browser:webdriverio\": \"pnpm -C test/browser run test:webdriverio\",\n    \"test:browser:playwright\": \"pnpm -C test/browser run test:playwright\"\n  },\n  \"devDependencies\": {\n    \"@antfu/eslint-config\": \"^7.6.1\",\n    \"@antfu/ni\": \"^28.3.0\",\n    \"@playwright/test\": \"^1.58.2\",\n    \"@rollup/plugin-commonjs\": \"^29.0.2\",\n    \"@rollup/plugin-json\": \"^6.1.0\",\n    \"@rollup/plugin-node-resolve\": \"^16.0.3\",\n    \"@types/node\": \"24.12.0\",\n    \"@types/ws\": \"catalog:\",\n    \"@vitest/browser\": \"workspace:*\",\n    \"@vitest/coverage-istanbul\": \"workspace:*\",\n    \"@vitest/coverage-v8\": \"workspace:*\",\n    \"@vitest/ui\": \"workspace:*\",\n    \"bumpp\": \"^10.4.1\",\n    \"changelogithub\": \"^14.0.0\",\n    \"esbuild\": \"^0.27.3\",\n    \"eslint\": \"^10.0.3\",\n    \"magic-string\": \"^0.30.21\",\n    \"pathe\": \"^2.0.3\",\n    \"premove\": \"^4.0.0\",\n    \"rollup\": \"^4.59.0\",\n    \"rollup-plugin-dts\": \"^6.3.0\",\n    \"rollup-plugin-license\": \"^3.7.0\",\n    \"tinyglobby\": \"catalog:\",\n    \"tsx\": \"^4.21.0\",\n    \"typescript\": \"^5.9.3\",\n    \"unplugin-isolated-decl\": \"^0.15.7\",\n    \"unplugin-oxc\": \"^0.6.0\",\n    \"vite\": \"7.1.5\",\n    \"vitest\": \"workspace:*\",\n    \"zx\": \"^8.8.5\"\n  }\n}\n"
  },
  {
    "path": "packages/browser/README.md",
    "content": "# @vitest/browser\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/browser?color=a1b858&label=)](https://npmx.dev/package/@vitest/browser)\n\nThis package exposes utilities to make your own browser provider. If you just need to run tests in the browser, consider installing one of these packages instead:\n\n- [@vitest/browser-playwright](https://npmx.dev/package/@vitest/browser-playwright) - run tests using [playwright](https://playwright.dev/)\n- [@vitest/browser-webdriverio](https://npmx.dev/package/@vitest/browser-webdriverio) - run tests using [webdriverio](https://webdriver.io/)\n- [@vitest/browser-preview](https://npmx.dev/package/@vitest/browser-preview) to see how your tests look like in a real browser.\n\n[GitHub](https://github.com/vitest-dev/vitest) | [Documentation](https://vitest.dev/guide/browser/)\n"
  },
  {
    "path": "packages/browser/aria-role.d.ts",
    "content": "type ARIAWidgetRole =\n    | \"button\"\n    | \"checkbox\"\n    | \"gridcell\"\n    | \"link\"\n    | \"menuitem\"\n    | \"menuitemcheckbox\"\n    | \"menuitemradio\"\n    | \"option\"\n    | \"progressbar\"\n    | \"radio\"\n    | \"scrollbar\"\n    | \"searchbox\"\n    | \"slider\"\n    | \"spinbutton\"\n    | \"switch\"\n    | \"tab\"\n    | \"tabpanel\"\n    | \"textbox\"\n    | \"treeitem\";\n\ntype ARIACompositeWidgetRole =\n    | \"combobox\"\n    | \"grid\"\n    | \"listbox\"\n    | \"menu\"\n    | \"menubar\"\n    | \"radiogroup\"\n    | \"tablist\"\n    | \"tree\"\n    | \"treegrid\";\n\ntype ARIADocumentStructureRole =\n    | \"application\"\n    | \"article\"\n    | \"blockquote\"\n    | \"caption\"\n    | \"cell\"\n    | \"columnheader\"\n    | \"definition\"\n    | \"deletion\"\n    | \"directory\"\n    | \"document\"\n    | \"emphasis\"\n    | \"feed\"\n    | \"figure\"\n    | \"generic\"\n    | \"group\"\n    | \"heading\"\n    | \"img\"\n    | \"insertion\"\n    | \"list\"\n    | \"listitem\"\n    | \"math\"\n    | \"meter\"\n    | \"none\"\n    | \"note\"\n    | \"paragraph\"\n    | \"presentation\"\n    | \"row\"\n    | \"rowgroup\"\n    | \"rowheader\"\n    | \"separator\"\n    | \"strong\"\n    | \"subscript\"\n    | \"superscript\"\n    | \"table\"\n    | \"term\"\n    | \"time\"\n    | \"toolbar\"\n    | \"tooltip\";\n\ntype ARIALandmarkRole =\n    | \"banner\"\n    | \"complementary\"\n    | \"contentinfo\"\n    | \"form\"\n    | \"main\"\n    | \"navigation\"\n    | \"region\"\n    | \"search\";\n\ntype ARIALiveRegionRole = \"alert\" | \"log\" | \"marquee\" | \"status\" | \"timer\";\n\ntype ARIAWindowRole = \"alertdialog\" | \"dialog\";\n\ntype ARIAUncategorizedRole = \"code\";\n\nexport type ARIARole =\n    | ARIAWidgetRole\n    | ARIACompositeWidgetRole\n    | ARIADocumentStructureRole\n    | ARIALandmarkRole\n    | ARIALiveRegionRole\n    | ARIAWindowRole\n    | ARIAUncategorizedRole;\n"
  },
  {
    "path": "packages/browser/context.d.ts",
    "content": "import { SerializedConfig } from 'vitest'\nimport { StringifyOptions, CDPSession, BrowserCommands } from 'vitest/internal/browser'\nimport { ARIARole } from './aria-role.js'\nimport {} from './matchers.js'\n\nexport type BufferEncoding =\n  | 'ascii'\n  | 'utf8'\n  | 'utf-8'\n  | 'utf16le'\n  | 'utf-16le'\n  | 'ucs2'\n  | 'ucs-2'\n  | 'base64'\n  | 'base64url'\n  | 'latin1'\n  | 'binary'\n  | 'hex'\n\nexport { CDPSession };\n\nexport interface ScreenshotOptions extends SelectorOptions {\n  /**\n   * The HTML element to screeshot.\n   */\n  element?: Element | Locator\n  /**\n   * Path relative to the current test file.\n   * @default `__screenshots__/${testFileName}/${testName}.png`\n   */\n  path?: string\n  /**\n   * Will also return the base64 encoded screenshot alongside the path.\n   */\n  base64?: boolean\n  /**\n   * Keep the screenshot on the file system. If file is not saved,\n   * `page.screenshot` always returns `base64` screenshot.\n   * @default true\n   */\n  save?: boolean\n}\n\nexport interface MarkOptions {\n  /**\n   * Optional stack string used to resolve marker location.\n   * Useful for wrapper libraries that need to forward the end-user callsite.\n   */\n  stack?: string\n}\n\ninterface StandardScreenshotComparators {\n  pixelmatch: {\n    /**\n     * The maximum number of pixels that are allowed to differ between the captured\n     * screenshot and the stored reference image.\n     *\n     * If set to `undefined`, any non-zero difference will cause the test to fail.\n     *\n     * For example, `allowedMismatchedPixels: 10` means the test will pass if 10\n     * or fewer pixels differ, but fail if 11 or more differ.\n     *\n     * If both this and `allowedMismatchedPixelRatio` are set, the more restrictive\n     * value (i.e., fewer allowed mismatches) will be used.\n     *\n     * @default undefined\n     */\n    allowedMismatchedPixels?: number | undefined\n    /**\n     * The maximum allowed ratio of differing pixels between the captured screenshot\n     * and the reference image.\n     *\n     * Must be a value between `0` and `1`.\n     *\n     * For example, `allowedMismatchedPixelRatio: 0.02` means the test will pass\n     * if up to 2% of pixels differ, but fail if more than 2% differ.\n     *\n     * If both this and `allowedMismatchedPixels` are set, the more restrictive\n     * value (i.e., fewer allowed mismatches) will be used.\n     *\n     * @default undefined\n     */\n    allowedMismatchedPixelRatio?: number | undefined\n    /**\n     * Acceptable perceived color difference between the same pixel in two images.\n     *\n     * Value ranges from `0` (strict) to `1` (very lenient). Lower values mean\n     * small differences will be detected.\n     *\n     * The comparison uses the {@link https://en.wikipedia.org/wiki/YIQ | YIQ color space}.\n     *\n     * @default 0.1\n     */\n    threshold?: number | undefined\n    /**\n     * If `true`, disables detection and ignoring of anti-aliased pixels.\n     *\n     * @default false\n     */\n    includeAA?: boolean | undefined\n    /**\n     * Blending level of unchanged pixels in the diff image.\n     *\n     * Ranges from `0` (white) to `1` (original brightness).\n     *\n     * @default 0.1\n     */\n    alpha?: number | undefined\n    /**\n     * Color used for anti-aliased pixels in the diff image.\n     *\n     * Format: `[R, G, B]`\n     *\n     * @default [255, 255, 0]\n     */\n    aaColor?: [r: number, g: number, b: number] | undefined\n    /**\n     * Color used for differing pixels in the diff image.\n     *\n     * Format: `[R, G, B]`\n     *\n     * @default [255, 0, 0]\n     */\n    diffColor?: [r: number, g: number, b: number] | undefined\n    /**\n     * Optional alternative color for dark-on-light differences, to help show\n     * what's added vs. removed.\n     *\n     * If not set, `diffColor` is used for all differences.\n     *\n     * Format: `[R, G, B]`\n     *\n     * @default undefined\n     */\n    diffColorAlt?: [r: number, g: number, b: number] | undefined\n    /**\n     * If `true`, shows only the diff as a mask on a transparent background,\n     * instead of overlaying it on the original image.\n     *\n     * Anti-aliased pixels won't be shown (if detected).\n     *\n     * @default false\n     */\n    diffMask?: boolean | undefined\n  }\n}\n\nexport interface ScreenshotComparatorRegistry extends StandardScreenshotComparators {}\n\nexport type NonStandardScreenshotComparators = Omit<\n  ScreenshotComparatorRegistry,\n  keyof StandardScreenshotComparators\n>\n\nexport interface ScreenshotMatcherOptions<\n  ComparatorName extends keyof ScreenshotComparatorRegistry = keyof ScreenshotComparatorRegistry\n> {\n  /**\n   * The name of the comparator to use for visual diffing.\n   *\n   * Must be one of the keys from {@linkcode ScreenshotComparatorRegistry}.\n   *\n   * @defaultValue `'pixelmatch'`\n   */\n  comparatorName?: ComparatorName\n  comparatorOptions?: ScreenshotComparatorRegistry[ComparatorName]\n  screenshotOptions?: Omit<\n    ScreenshotOptions,\n    'element' | 'base64' | 'path' | 'save' | 'type' | 'strict' | 'timeout'\n  >\n  /**\n   * Time to wait until a stable screenshot is found.\n   *\n   * Setting this value to `0` disables the timeout, but if a stable screenshot\n   * can't be determined the process will not end.\n   *\n   * @default 5000\n   */\n  timeout?: number\n  /**\n   * Allow only a single element with the same locator.\n   *\n   * If Vitest finds multiple elements, it will throw an error immediately without retrying.\n   * @default true\n   */\n  strict?: boolean\n}\n\nexport interface UserEvent {\n  /**\n   * Creates a new user event instance. This is useful if you need to keep the\n   * state of keyboard to press and release buttons correctly.\n   *\n   * **Note:** Unlike `@testing-library/user-event`, the default `userEvent` instance\n   * from `vitest/browser` is created once, not every time its methods are called!\n   * @see {@link https://vitest.dev/api/browser/interactivity.html#userevent-setup}\n   */\n  setup: () => UserEvent\n  /**\n   * Cleans up the user event instance, releasing any resources or state it holds,\n   * such as keyboard press state. For the default `userEvent` instance, this method\n   * is automatically called after each test case.\n   */\n  cleanup: () => Promise<void>\n  /**\n   * Click on an element. Uses provider's API under the hood and supports all its options.\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-click} Playwright API\n   * @see {@link https://webdriver.io/docs/api/element/click/} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/convenience/#click} testing-library API\n   */\n  click: (element: Element | Locator, options?: UserEventClickOptions) => Promise<void>\n  /**\n   * Triggers a double click event on an element. Uses provider's API under the hood.\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-dblclick} Playwright API\n   * @see {@link https://webdriver.io/docs/api/element/doubleClick/} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/convenience/#dblClick} testing-library API\n   */\n  dblClick: (element: Element | Locator, options?: UserEventDoubleClickOptions) => Promise<void>\n  /**\n   * Triggers a triple click event on an element. Uses provider's API under the hood.\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-click} Playwright API: using `click` with `clickCount: 3`\n   * @see {@link https://webdriver.io/docs/api/browser/actions/} WebdriverIO API: using actions api with `move` plus three `down + up + pause` events in a row\n   * @see {@link https://testing-library.com/docs/user-event/convenience/#tripleclick} testing-library API\n   */\n  tripleClick: (element: Element | Locator, options?: UserEventTripleClickOptions) => Promise<void>\n  /**\n   * Triggers a {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event|`wheel` event} on an element.\n   *\n   * @param element - The target element to receive wheel events.\n   * @param options - Scroll configuration using `delta` or `direction`.\n   * @returns A promise that resolves when all wheel events have been dispatched.\n   *\n   * @since 4.1.0\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-wheel}\n   *\n   * @example\n   * // Scroll down by 100 pixels\n   * await userEvent.wheel(container, { delta: { y: 100 } })\n   *\n   * @example\n   * // Scroll up 5 times\n   * await userEvent.wheel(container, { direction: 'up', times: 5 })\n   */\n  wheel(element: Element | Locator, options: UserEventWheelOptions): Promise<void>\n  /**\n   * Choose one or more values from a select element. Uses provider's API under the hood.\n   * If select doesn't have `multiple` attribute, only the first value will be selected.\n   * @example\n   * await userEvent.selectOptions(select, 'Option 1')\n   * expect(select).toHaveValue('option-1')\n   *\n   * await userEvent.selectOptions(select, 'option-1')\n   * expect(select).toHaveValue('option-1')\n   *\n   * await userEvent.selectOptions(select, [\n   *  screen.getByRole('option', { name: 'Option 1' }),\n   *  screen.getByRole('option', { name: 'Option 2' }),\n   * ])\n   * expect(select).toHaveValue(['option-1', 'option-2'])\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-select-option} Playwright API\n   * @see {@link https://webdriver.io/docs/api/element/doubleClick/} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/utility/#-selectoptions-deselectoptions} testing-library API\n   */\n  selectOptions: (\n    element: HTMLElement | SVGElement | Locator,\n    values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],\n    options?: UserEventSelectOptions,\n  ) => Promise<void>\n  /**\n   * Type text on the keyboard. If any input is focused, it will receive the text,\n   * otherwise it will be typed on the document. Uses provider's API under the hood.\n   * **Supports** [user-event `keyboard` syntax](https://testing-library.com/docs/user-event/keyboard) (e.g., `{Shift}`) even with `playwright` and `webdriverio` providers.\n   * @example\n   * await userEvent.keyboard('foo') // translates to: f, o, o\n   * await userEvent.keyboard('{{a[[') // translates to: {, a, [\n   * await userEvent.keyboard('{Shift}{f}{o}{o}') // translates to: Shift, f, o, o\n   * @see {@link https://playwright.dev/docs/api/class-keyboard} Playwright API\n   * @see {@link https://webdriver.io/docs/api/browser/keys} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/keyboard} testing-library API\n   */\n  keyboard: (text: string) => Promise<void>\n  /**\n   * Types text into an element. Uses provider's API under the hood.\n   * **Supports** [user-event `keyboard` syntax](https://testing-library.com/docs/user-event/keyboard) (e.g., `{Shift}`) even with `playwright` and `webdriverio` providers.\n   * This method can be significantly slower than `userEvent.fill`, so it should be used only when necessary.\n   * @example\n   * await userEvent.type(input, 'foo') // translates to: f, o, o\n   * await userEvent.type(input, '{{a[[') // translates to: {, a, [\n   * await userEvent.type(input, '{Shift}{f}{o}{o}') // translates to: Shift, f, o, o\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-press} Playwright API\n   * @see {@link https://webdriver.io/docs/api/browser/action#key-input-source} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/utility/#type} testing-library API\n   */\n  type: (element: Element | Locator, text: string, options?: UserEventTypeOptions) => Promise<void>\n  /**\n   * Removes all text from an element. Uses provider's API under the hood.\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-clear} Playwright API\n   * @see {@link https://webdriver.io/docs/api/element/clearValue} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/utility/#clear} testing-library API\n   */\n  clear: (element: Element | Locator, options?: UserEventClearOptions) => Promise<void>\n  /**\n   * Sends a `Tab` key event. Uses provider's API under the hood.\n   * @see {@link https://playwright.dev/docs/api/class-keyboard} Playwright API\n   * @see {@link https://webdriver.io/docs/api/element/keys} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/convenience/#tab} testing-library API\n   */\n  tab: (options?: UserEventTabOptions) => Promise<void>\n  /**\n   * Hovers over an element. Uses provider's API under the hood.\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-hover} Playwright API\n   * @see {@link https://webdriver.io/docs/api/element/moveTo/} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/convenience/#hover} testing-library API\n   */\n  hover: (element: Element | Locator, options?: UserEventHoverOptions) => Promise<void>\n  /**\n   * Moves cursor position to the body element. Uses provider's API under the hood.\n   * By default, the cursor position is in the center (in webdriverio) or in some visible place (in playwright)\n   * of the body element, so if the current element is already there, this will have no effect.\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-hover} Playwright API\n   * @see {@link https://webdriver.io/docs/api/element/moveTo/} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/convenience/#hover} testing-library API\n   */\n  unhover: (element: Element | Locator, options?: UserEventHoverOptions) => Promise<void>\n  /**\n   * Change a file input element to have the specified files. Uses provider's API under the hood.\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-set-input-files} Playwright API\n   * @see {@link https://testing-library.com/docs/user-event/utility#upload} testing-library API\n   */\n  upload: (element: Element | Locator, files: File | File[] | string | string[], options?: UserEventUploadOptions) => Promise<void>\n  /**\n   * Copies the selected content.\n   * @see {@link https://playwright.dev/docs/api/class-keyboard} Playwright API\n   * @see {@link https://webdriver.io/docs/api/browser/keys//} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/clipboard#copy} testing-library API\n   */\n  copy: () => Promise<void>\n  /**\n   * Cuts the selected content.\n   * @see {@link https://playwright.dev/docs/api/class-keyboard} Playwright API\n   * @see {@link https://webdriver.io/docs/api/browser/keys//} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/clipboard#cut} testing-library API\n   */\n  cut: () => Promise<void>\n  /**\n   * Pastes the copied or cut content.\n   * @see {@link https://playwright.dev/docs/api/class-keyboard} Playwright API\n   * @see {@link https://webdriver.io/docs/api/browser/keys//} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/clipboard#paste} testing-library API\n   */\n  paste: () => Promise<void>\n  /**\n   * Fills an input element with text. This will remove any existing text in the input before typing the new text.\n   * Uses provider's API under the hood.\n   * This API is faster than using `userEvent.type` or `userEvent.keyboard`, but it **doesn't support** [user-event `keyboard` syntax](https://testing-library.com/docs/user-event/keyboard) (e.g., `{Shift}`).\n   * @example\n   * await userEvent.fill(input, 'foo') // translates to: f, o, o\n   * await userEvent.fill(input, '{{a[[') // translates to: {, {, a, [, [\n   * await userEvent.fill(input, '{Shift}') // translates to: {, S, h, i, f, t, }\n   * @see {@link https://playwright.dev/docs/api/class-locator#locator-fill} Playwright API\n   * @see {@link https://webdriver.io/docs/api/element/setValue} WebdriverIO API\n   * @see {@link https://testing-library.com/docs/user-event/utility/#type} testing-library API\n   */\n  fill: (element: Element | Locator, text: string, options?: UserEventFillOptions) => Promise<void>\n  /**\n   * Drags a source element on top of the target element. This API is not supported by \"preview\" provider.\n   * @see {@link https://playwright.dev/docs/api/class-frame#frame-drag-and-drop} Playwright API\n   * @see {@link https://webdriver.io/docs/api/element/dragAndDrop/} WebdriverIO API\n   */\n  dragAndDrop: (source: Element | Locator, target: Element | Locator, options?: UserEventDragAndDropOptions) => Promise<void>\n}\n\nexport interface UserEventFillOptions {}\nexport interface UserEventHoverOptions {}\nexport interface UserEventSelectOptions {}\nexport interface UserEventClickOptions {}\nexport interface UserEventClearOptions {}\nexport interface UserEventDoubleClickOptions {}\nexport interface UserEventTripleClickOptions {}\nexport interface UserEventDragAndDropOptions {}\nexport interface UserEventUploadOptions {}\n\n/**\n * Base options shared by all wheel event configurations.\n *\n * @since 4.1.0\n */\nexport interface UserEventWheelBaseOptions {\n  /**\n   * Number of wheel events to fire. Defaults to `1`.\n   *\n   * Useful for triggering multiple scroll steps in a single call.\n   */\n  times?: number\n}\n\n/**\n * Wheel options using pixel-based `delta` values for precise scroll control.\n *\n * @since 4.1.0\n */\nexport interface UserEventWheelDeltaOptions extends UserEventWheelBaseOptions {\n  /**\n   * Precise scroll delta values in pixels. At least one axis must be specified.\n   *\n   * - Positive `y` scrolls down, negative `y` scrolls up.\n   * - Positive `x` scrolls right, negative `x` scrolls left.\n   */\n  delta: { x: number; y?: number } | { x?: number; y: number }\n  direction?: undefined\n}\n\n/**\n * Wheel options using semantic `direction` values for simpler scroll control.\n *\n * @since 4.1.0\n */\nexport interface UserEventWheelDirectionOptions extends UserEventWheelBaseOptions {\n  /**\n   * Semantic scroll direction. Use this for readable tests when exact pixel values don't matter.\n   */\n  direction: 'up' | 'down' | 'left' | 'right'\n  delta?: undefined\n}\n\n/**\n * Options for triggering wheel events.\n *\n * Specify scrolling using either `delta` for precise pixel values, or `direction` for semantic scrolling. These are mutually exclusive.\n *\n * @since 4.1.0\n */\nexport type UserEventWheelOptions = UserEventWheelDeltaOptions | UserEventWheelDirectionOptions\n\nexport interface LocatorOptions {\n  /**\n   * Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a\n   * regular expression. Note that exact match still trims whitespace.\n   */\n  exact?: boolean\n  hasText?: string | RegExp\n  hasNotText?: string | RegExp\n  has?: Locator\n  hasNot?: Locator\n}\n\nexport interface LocatorByRoleOptions extends LocatorOptions {\n  /**\n   * Should checked elements (set by `aria-checked` or `<input type=\"checkbox\"/>`) be included or not. By default, the filter is not applied.\n   *\n   * See [`aria-checked`](https://www.w3.org/TR/wai-aria-1.2/#aria-checked) for more information\n   */\n  checked?: boolean\n  /**\n   * Should disabled elements be included or not. By default, the filter is not applied. Note that unlike other attributes, `disable` state is inherited.\n   *\n   * See [`aria-disabled`](https://www.w3.org/TR/wai-aria-1.2/#aria-disabled) for more information\n   */\n  disabled?: boolean\n  /**\n   * Should expanded elements be included or not. By default, the filter is not applied.\n   *\n   * See [`aria-expanded`](https://www.w3.org/TR/wai-aria-1.2/#aria-expanded) for more information\n   */\n  expanded?: boolean\n  /**\n   * Should elements that are [normally excluded](https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion) from the accessibility tree be queried. By default, only non-hidden elements are matched by role selector.\n   *\n   * Note that roles `none` and `presentation` are always included.\n   * @default false\n   */\n  includeHidden?: boolean\n  /**\n   * A number attribute that is usually present for `heading`, `listitem`, `row`, `treeitem` roles with default values for `<h1>-<h6>` elements. By default, the filter is not applied.\n   *\n   * See [`aria-level`](https://www.w3.org/TR/wai-aria-1.2/#aria-level) for more information\n   */\n  level?: number\n  /**\n   * Option to match the [accessible name](https://w3c.github.io/accname/#dfn-accessible-name). By default, matching is\n   * case-insensitive and searches for a substring, use `exact` to control this behavior.\n   */\n  name?: string | RegExp\n  /**\n   * Should pressed elements be included or not. By default, the filter is not applied.\n   *\n   * See [`aria-pressed`](https://www.w3.org/TR/wai-aria-1.2/#aria-pressed) for more information\n   */\n  pressed?: boolean\n  /**\n   * Should selected elements be included or not. By default, the filter is not applied.\n   *\n   * See [`aria-selected`](https://www.w3.org/TR/wai-aria-1.2/#aria-selected) for more information\n   */\n  selected?: boolean\n}\n\nexport interface LocatorScreenshotOptions extends Omit<ScreenshotOptions, 'element'> {}\n\nexport interface LocatorSelectors {\n  /**\n   * Creates a way to locate an element by its [ARIA role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles), [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes) and [accessible name](https://developer.mozilla.org/en-US/docs/Glossary/Accessible_name).\n   * @see {@link https://vitest.dev/api/browser/locators#getbyrole}\n   */\n  getByRole: (role: ARIARole | ({} & string), options?: LocatorByRoleOptions) => Locator\n  /**\n   * @see {@link https://vitest.dev/api/browser/locators#getbylabeltext}\n   */\n  getByLabelText: (text: string | RegExp, options?: LocatorOptions) => Locator\n  /**\n   * Creates a locator capable of finding an element with an `alt` attribute that matches the text. Unlike testing-library's implementation, Vitest will match any element that has an `alt` attribute.\n   * @see {@link https://vitest.dev/api/browser/locators#getbyalttext}\n   */\n  getByAltText: (text: string | RegExp, options?: LocatorOptions) => Locator\n  /**\n   * Creates a locator capable of finding an element that has the specified placeholder text. Vitest will match any element that has a matching `placeholder` attribute, not just `input`.\n   * @see {@link https://vitest.dev/api/browser/locators#getbyplaceholder}\n   */\n  getByPlaceholder: (text: string | RegExp, options?: LocatorOptions) => Locator\n  /**\n   * Creates a locator capable of finding an element that contains the specified text. The text will be matched against TextNode's [`nodeValue`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeValue) or input's value if the type is `button` or `reset`.\n   * Matching by text always normalizes whitespace, even with exact match.\n   * For example, it turns multiple spaces into one, turns line breaks into spaces and ignores leading and trailing whitespace.\n   * @see {@link https://vitest.dev/api/browser/locators#getbytext}\n   */\n  getByText: (text: string | RegExp, options?: LocatorOptions) => Locator\n  /**\n   * Creates a locator capable of finding an element that has the specified `title` attribute. Unlike testing-library's `getByTitle`, Vitest cannot find `title` elements within an SVG.\n   * @see {@link https://vitest.dev/api/browser/locators#getbytitle}\n   */\n  getByTitle: (text: string | RegExp, options?: LocatorOptions) => Locator\n  /**\n   * Creates a locator capable of finding an element that matches the specified test id attribute. You can configure the attribute name with [`browser.locators.testIdAttribute`](https://vitest.dev/config/browser/locators#browser-locators-testidattribute).\n   * @see {@link https://vitest.dev/api/browser/locators#getbytestid}\n   */\n  getByTestId: (text: string | RegExp) => Locator\n}\n\nexport interface FrameLocator extends LocatorSelectors {}\n\nexport interface SelectorOptions {\n  /**\n   * How long to wait until a single element is found. By default, this has the same timeout as the test.\n   *\n   * Vitest will try to find the element in ever increasing intervals: 0, 20, 50, 100, 100, 500.\n   */\n  timeout?: number\n  /**\n   * Allow only a single element with the same locator.\n   *\n   * If Vitest finds multiple elements, it will throw an error immediately without retrying.\n   * @default true\n   */\n  strict?: boolean\n}\n\nexport interface Locator extends LocatorSelectors {\n  /**\n   * Selector string that will be used to locate the element by the browser provider.\n   * You can use this string in the commands API:\n   * ```ts\n   * // playwright\n   * function test({ selector, iframe }) {\n   *   await iframe.locator(selector).click()\n   * }\n   * // webdriverio\n   * function test({ selector, browser }) {\n   *   await browser.$(selector).click()\n   * }\n   * ```\n   * @see {@link https://vitest.dev/api/browser/locators#selector}\n   */\n  readonly selector: string\n\n  /**\n   * The number of elements that this locator is matching.\n   * @see {@link https://vitest.dev/api/browser/locators#length}\n   */\n  readonly length: number\n\n  /**\n   * Click on an element. You can use the options to set the cursor position.\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-click}\n   */\n  click(options?: UserEventClickOptions): Promise<void>\n  /**\n   * Triggers a double click event on an element. You can use the options to set the cursor position.\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-dblclick}\n   */\n  dblClick(options?: UserEventDoubleClickOptions): Promise<void>\n  /**\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-tripleclick}\n   */\n  tripleClick(options?: UserEventTripleClickOptions): Promise<void>\n  /**\n   * Triggers a {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event|`wheel` event} on an element.\n   *\n   * @param options - Scroll configuration using `delta` or `direction`.\n   * @returns A promise that resolves when all wheel events have been dispatched.\n   *\n   * @since 4.1.0\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-wheel}\n   *\n   * @example\n   * // Scroll down by 100 pixels\n   * await container.wheel({ delta: { y: 100 } })\n   *\n   * @example\n   * // Scroll up 5 times\n   * await container.wheel({ direction: 'up', times: 5 })\n   */\n  wheel(options: UserEventWheelOptions): Promise<void>\n  /**\n   * Clears the input element content\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-clear}\n   */\n  clear(options?: UserEventClearOptions): Promise<void>\n  /**\n   * Moves the cursor position to the selected element\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-hover}\n   */\n  hover(options?: UserEventHoverOptions): Promise<void>\n  /**\n   * This works the same as `locator.hover`, but moves the cursor to the `document.body` element instead.\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-unhover}\n   */\n  unhover(options?: UserEventHoverOptions): Promise<void>\n  /**\n   * Sets the value of the current `input`, `textarea` or `contenteditable` element.\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-fill}\n   */\n  fill(text: string, options?: UserEventFillOptions): Promise<void>\n  /**\n   * Drags the current element to the target location.\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-dropto}\n   */\n  dropTo(target: Locator, options?: UserEventDragAndDropOptions): Promise<void>\n  /**\n   * Choose one or more values from a `<select>` element.\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-selectoptions}\n   */\n  selectOptions(\n    values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],\n    options?: UserEventSelectOptions,\n  ): Promise<void>\n  /**\n   * Change a file input element to have the specified files. Uses provider's API under the hood.\n   * @see {@link https://vitest.dev/api/browser/interactivity#userevent-upload}\n   */\n  upload(files: File | File[] | string | string[], options?: UserEventUploadOptions): Promise<void>\n\n  /**\n   * Make a screenshot of an element matching the locator.\n   * @see {@link https://vitest.dev/api/browser/locators#screenshot}\n   */\n  screenshot(options: Omit<LocatorScreenshotOptions, 'base64'> & { base64: true }): Promise<{\n    path: string\n    base64: string\n  }>\n  screenshot(options?: LocatorScreenshotOptions): Promise<string>\n\n  /**\n   * Add a trace marker for this locator when browser tracing is enabled.\n   * @see {@link https://vitest.dev/api/browser/locators#mark}\n   */\n  mark(name: string, options?: MarkOptions): Promise<void>\n\n  /**\n   * Returns an element matching the selector.\n   *\n   * - If multiple elements match the selector, an error is thrown.\n   * - If no elements match the selector, an error is thrown.\n   *\n   * @see {@link https://vitest.dev/api/browser/locators#element}\n   */\n  element(): HTMLElement | SVGElement\n  /**\n   * Returns an array of elements matching the selector.\n   *\n   * If no elements match the selector, an empty array is returned.\n   *\n   * @see {@link https://vitest.dev/api/browser/locators#elements}\n   */\n  elements(): (HTMLElement | SVGElement)[]\n  /**\n   * Returns an element matching the selector.\n   *\n   * - If multiple elements match the selector, an error is thrown.\n   * - If no elements match the selector, returns `null`.\n   *\n   * @see {@link https://vitest.dev/api/browser/locators#query}\n   */\n  query(): HTMLElement | SVGElement | null\n  /**\n   * Wraps an array of `.elements()` matching the selector in a new `Locator`.\n   *\n   * @see {@link https://vitest.dev/api/browser/locators#all}\n   */\n  all(): Locator[]\n  /**\n   * Returns a locator for the nth element matching the selector.\n   * @see {@link https://vitest.dev/api/browser/locators#nth}\n   */\n  nth(index: number): Locator\n  /**\n   * Returns a locator for the first element matching the selector.\n   * @see {@link https://vitest.dev/api/browser/locators#first}\n   */\n  first(): Locator\n  /**\n   * Returns a locator for the last element matching the selector.\n   * @see {@link https://vitest.dev/api/browser/locators#last}\n   */\n  last(): Locator\n  /**\n   * Returns a locator that matches both the current locator and the provided locator.\n   * @see {@link https://vitest.dev/api/browser/locators#and}\n   */\n  and(locator: Locator): Locator\n  /**\n   * Returns a locator that matches either the current locator or the provided locator.\n   * @see {@link https://vitest.dev/api/browser/locators#or}\n   */\n  or(locator: Locator): Locator\n  /**\n   * Narrows existing locator according to the options.\n   * @see {@link https://vitest.dev/api/browser/locators#filter}\n   */\n  filter(options: LocatorOptions): Locator\n  /**\n   * This method returns an element matching the locator.\n   * Unlike [`.element()`](https://vitest.dev/api/browser/locators#element),\n   * this method will wait and retry until a matching element appears in the DOM,\n   * using increasing intervals (0, 20, 50, 100, 100, 500ms).\n   *\n   * **WARNING:**\n   *\n   * This is an escape hatch for library authors and 3d-party APIs that do not support locators directly.\n   * If you are interacting with the element, use builtin methods instead.\n   * @since 4.1.0\n   * @see {@link https://vitest.dev/api/browser/locators#findelement}\n   */\n  findElement(options?: SelectorOptions): Promise<HTMLElement | SVGElement>\n}\n\nexport interface UserEventTabOptions {\n  shift?: boolean\n}\n\nexport interface UserEventTypeOptions extends SelectorOptions {\n  skipClick?: boolean\n  skipAutoClose?: boolean\n}\n\ntype Platform =\n  | 'aix'\n  | 'android'\n  | 'darwin'\n  | 'freebsd'\n  | 'haiku'\n  | 'linux'\n  | 'openbsd'\n  | 'sunos'\n  | 'win32'\n  | 'cygwin'\n  | 'netbsd'\n\nexport const server: {\n  /**\n   * Platform the Vitest server is running on.\n   * The same as calling `process.platform` on the server.\n   */\n  platform: Platform\n  /**\n   * Runtime version of the Vitest server.\n   * The same as calling `process.version` on the server.\n   */\n  version: string\n  /**\n   * Name of the browser provider.\n   */\n  provider: string\n  /**\n   * Name of the current browser.\n   */\n  browser: string\n  /**\n   * Available commands for the browser.\n   * @see {@link https://vitest.dev/api/browser/commands}\n   */\n  commands: BrowserCommands\n  /**\n   * Serialized test config.\n   */\n  config: SerializedConfig\n}\n\n/**\n * Handler for user interactions. The support is provided by the browser provider (`playwright` or `webdriverio`).\n * If used with `preview` provider, fallbacks to simulated events via `@testing-library/user-event`.\n * @experimental\n */\nexport const userEvent: UserEvent\n\n/**\n * Available commands for the browser.\n * A shortcut to `server.commands`.\n * @see {@link https://vitest.dev/api/browser/commands}\n */\nexport const commands: BrowserCommands\n\nexport interface BrowserPage extends LocatorSelectors {\n  /**\n   * Change the size of iframe's viewport.\n   */\n  viewport(width: number, height: number): Promise<void>\n  /**\n   * Make a screenshot of the test iframe or a specific element.\n   * @returns Path to the screenshot file or path and base64.\n   */\n  screenshot(options: Omit<ScreenshotOptions, 'save'> & { save: false }): Promise<string>\n  screenshot(options: Omit<ScreenshotOptions, 'base64'> & { base64: true }): Promise<{\n    path: string\n    base64: string\n  }>\n  screenshot(options?: Omit<ScreenshotOptions, 'base64'>): Promise<string>\n  screenshot(options?: ScreenshotOptions): Promise<string | {\n    path: string\n    base64: string\n  }>\n  /**\n   * Add a trace marker when browser tracing is enabled.\n   * @see {@link https://vitest.dev/api/browser/context#mark}\n   */\n  mark(name: string, options?: MarkOptions): Promise<void>\n  /**\n   * Group multiple operations under a trace marker when browser tracing is enabled.\n   * @see {@link https://vitest.dev/api/browser/context#mark}\n   */\n  mark<T>(name: string, body: () => T | Promise<T>, options?: MarkOptions): Promise<T>\n  /**\n   * Extend default `page` object with custom methods.\n   */\n  extend(methods: Partial<BrowserPage>): BrowserPage\n  /**\n   * Wrap an HTML element in a `Locator`. When querying for elements, the search will always return this element.\n   * @see {@link https://vitest.dev/api/browser/locators}\n   */\n  elementLocator(element: Element): Locator\n  /**\n   * The iframe locator. This is a document locator that enters the iframe body\n   * and works similarly to the `page` object.\n   *\n   * As the first argument, pass down the locator to the `<iframe>` element itself.\n   *\n   * **Warning:** At the moment, this is supported only by the `playwright` provider.\n   * @example\n   * ```ts\n   * const frame = page.frameLocator(\n   *   page.getByTestId('iframe')\n   * )\n   *\n   * await frame.getByText('Hello World').click()\n   * ```\n   * @param locator The locator object.\n   * @see {@link https://vitest.dev/api/browser/locators}\n   */\n  frameLocator(locator: Locator): FrameLocator\n}\n\nexport interface BrowserLocators {\n  createElementLocators(element: Element): LocatorSelectors\n  // TODO: enhance docs\n  /**\n   * Extends `page.*` and `locator.*` interfaces.\n   * @see {@link}\n   *\n   * @example\n   * ```ts\n   * import { locators } from 'vitest/browser'\n   *\n   * declare module 'vitest/browser' {\n   *   interface LocatorSelectors {\n   *     getByCSS(css: string): Locator\n   *   }\n   * }\n   *\n   * locators.extend({\n   *   getByCSS(css: string) {\n   *     return `css=${css}`\n   *   }\n   * })\n   * ```\n   */\n  extend(methods: {\n    [K in keyof LocatorSelectors]?: (\n      this: BrowserPage | Locator,\n      ...args: Parameters<LocatorSelectors[K]>\n    ) => ReturnType<LocatorSelectors[K]> | string\n  }): void\n}\n\n\nexport type PrettyDOMOptions = Omit<StringifyOptions, 'maxLength'>\n\nexport const utils: {\n  /**\n   * This is simillar to calling `page.elementLocator`, but it returns only\n   * locator selectors.\n   */\n  getElementLocatorSelectors(element: Element): LocatorSelectors\n  /**\n   * Prints prettified HTML of an element.\n   */\n  debug(\n    el?: Element | Locator | null | (Element | Locator)[],\n    maxLength?: number,\n    options?: PrettyDOMOptions,\n  ): void\n  /**\n   * Returns prettified HTML of an element.\n   */\n  prettyDOM(\n    dom?: Element | Locator | undefined | null,\n    maxLength?: number,\n    prettyFormatOptions?: PrettyDOMOptions,\n  ): string\n  /**\n   * Configures default options of `prettyDOM` and `debug` functions.\n   * This will also affect `vitest-browser-{framework}` package.\n   */\n  configurePrettyDOM(options: StringifyOptions): void\n  /**\n   * Creates \"Cannot find element\" error. Useful for custom locators.\n   */\n  getElementError(selector: string, container?: Element): Error\n}\n\nexport const locators: BrowserLocators\n\nexport const page: BrowserPage\nexport const cdp: () => CDPSession\n"
  },
  {
    "path": "packages/browser/context.js",
    "content": "// Vitest resolves \"vitest/browser\" as a virtual module instead\n\n// fake exports for static analysis\nexport const page = null\nexport const server = null\nexport const userEvent = null\nexport const cdp = null\nexport const commands = null\nexport const locators = null\nexport const utils = null\n\nconst pool = globalThis.__vitest_worker__?.ctx?.pool\n\nthrow new Error(\n  // eslint-disable-next-line prefer-template\n  'vitest/browser can be imported only inside the Browser Mode. '\n  + (pool\n    ? `Your test is running in ${pool} pool. Make sure your regular tests are excluded from the \"test.include\" glob pattern.`\n    : 'Instead, it was imported outside of Vitest.'),\n)\n"
  },
  {
    "path": "packages/browser/dummy.js",
    "content": ""
  },
  {
    "path": "packages/browser/jest-dom.d.ts",
    "content": "// Disable automatic exports.\n\nimport { ARIARole } from './aria-role.ts'\nimport { Locator, ScreenshotComparatorRegistry, ScreenshotMatcherOptions } from './context.js'\n\nexport interface TestingLibraryMatchers<E, R> {\n  /**\n   * @description\n   * Assert whether an element is present in the document or not.\n   * @example\n   * <svg data-testid=\"svg-element\"></svg>\n   *\n   * await expect.element(page.getByTestId('svg-element')).toBeInTheDocument()\n   * await expect.element(page.getByTestId('does-not-exist')).not.toBeInTheDocument()\n   * @see https://vitest.dev/api/browser/assertions#tobeinthedocument\n   */\n  toBeInTheDocument(): R\n  /**\n   * @description\n   * Assert whether an element is within the viewport or not.\n   *\n   * An element is considered to be in the viewport if any part of it intersects with the current viewport bounds.\n   * This matcher calculates the intersection ratio between the element and the viewport, similar to the\n   * IntersectionObserver API.\n   *\n   * The element must be in the document and have visible dimensions. Elements with display: none or\n   * visibility: hidden are considered not in viewport.\n   * @example\n   * <div\n   *   data-testid=\"visible-element\"\n   *   style=\"position: absolute; top: 10px; left: 10px; width: 50px; height: 50px;\"\n   * >\n   *   Visible Element\n   * </div>\n   *\n   * <div\n   *   data-testid=\"hidden-element\"\n   *   style=\"position: fixed; top: -100px; left: 10px; width: 50px; height: 50px;\"\n   * >\n   *   Hidden Element\n   * </div>\n   *\n   * <div\n   *   data-testid=\"large-element\"\n   *   style=\"height: 400vh;\"\n   * >\n   *   Large Element\n   * </div>\n   *\n   * // Check if any part of element is in viewport\n   * await expect.element(page.getByTestId('visible-element')).toBeInViewport()\n   *\n   * // Check if element is outside viewport\n   * await expect.element(page.getByTestId('hidden-element')).not.toBeInViewport()\n   *\n   * // Check if at least 50% of element is visible\n   * await expect.element(page.getByTestId('large-element')).toBeInViewport({ ratio: 0.5 })\n   *\n   * // Check if element is completely visible\n   * await expect.element(page.getByTestId('visible-element')).toBeInViewport({ ratio: 1 })\n   * @see https://vitest.dev/api/browser/assertions#tobeinviewport\n   */\n  toBeInViewport(options?: { ratio?: number }): R\n  /**\n   * @description\n   * This allows you to check if an element is currently visible to the user.\n   *\n   * An element is visible if **all** the following conditions are met:\n   * * it does not have its css property display set to none\n   * * it does not have its css property visibility set to either hidden or collapse\n   * * it does not have its css property opacity set to 0\n   * * its parent element is also visible (and so on up to the top of the DOM tree)\n   * * it does not have the hidden attribute\n   * * if `<details />` it has the open attribute\n   * @example\n   * <div\n   *   data-testid=\"zero-opacity\"\n   *   style=\"opacity: 0\"\n   * >\n   *   Zero Opacity\n   * </div>\n   *\n   * <div data-testid=\"visible\">Visible Example</div>\n   *\n   * await expect.element(page.getByTestId('zero-opacity')).not.toBeVisible()\n   * await expect.element(page.getByTestId('visible')).toBeVisible()\n   * @see https://vitest.dev/api/browser/assertions#tobevisible\n   */\n  toBeVisible(): R\n  /**\n   * @description\n   * Assert whether an element has content or not.\n   * @example\n   * <span data-testid=\"not-empty\">\n   *   <span data-testid=\"empty\"></span>\n   * </span>\n   *\n   * await expect.element(page.getByTestId('empty')).toBeEmptyDOMElement()\n   * await expect.element(page.getByTestId('not-empty')).not.toBeEmptyDOMElement()\n   * @see https://vitest.dev/api/browser/assertions#tobeemptydomelement\n   */\n  toBeEmptyDOMElement(): R\n  /**\n   * @description\n   * Allows you to check whether an element is disabled from the user's perspective.\n   *\n   * Matches if the element is a form control and the `disabled` attribute is specified on this element or the\n   * element is a descendant of a form element with a `disabled` attribute.\n   * @example\n   * <button\n   *   data-testid=\"button\"\n   *   type=\"submit\"\n   *   disabled\n   * >\n   *   submit\n   * </button>\n   *\n   * await expect.element(page.getByTestId('button')).toBeDisabled()\n   * @see https://vitest.dev/api/browser/assertions#tobedisabled\n   */\n  toBeDisabled(): R\n  /**\n   * @description\n   * Allows you to check whether an element is not disabled from the user's perspective.\n   *\n   * Works like `not.toBeDisabled()`.\n   *\n   * Use this matcher to avoid double negation in your tests.\n   * @example\n   * <button\n   *   data-testid=\"button\"\n   *   type=\"submit\"\n   * >\n   *   submit\n   * </button>\n   *\n   * await expect.element(page.getByTestId('button')).toBeEnabled()\n   * @see https://vitest.dev/api/browser/assertions#tobeenabled\n   */\n  toBeEnabled(): R\n  /**\n   * @description\n   * Check if a form element, or the entire `form`, is currently invalid.\n   *\n   * An `input`, `select`, `textarea`, or `form` element is invalid if it has an `aria-invalid` attribute with no\n   * value or a value of \"true\", or if the result of `checkValidity()` is false.\n   * @example\n   * <input data-testid=\"no-aria-invalid\" />\n   *\n   * <form data-testid=\"invalid-form\">\n   *   <input required />\n   * </form>\n   *\n   * await expect(page.getByTestId('no-aria-invalid')).not.toBeInvalid()\n   * await expect(page.getByTestId('invalid-form')).toBeInvalid()\n   * @see https://vitest.dev/api/browser/assertions#tobeinvalid\n   */\n  toBeInvalid(): R\n  /**\n   * @description\n   * This allows you to check if a form element is currently required.\n   *\n   * An element is required if it is having a `required` or `aria-required=\"true\"` attribute.\n   * @example\n   * <input data-testid=\"required-input\" required />\n   * <div\n   *   data-testid=\"supported-role\"\n   *   role=\"tree\"\n   *   required />\n   *\n   * await expect.element(page.getByTestId('required-input')).toBeRequired()\n   * await expect.element(page.getByTestId('supported-role')).not.toBeRequired()\n   * @see https://vitest.dev/api/browser/assertions#toberequired\n   */\n  toBeRequired(): R\n  /**\n   * @description\n   * Allows you to check if a form element is currently required.\n   *\n   * An `input`, `select`, `textarea`, or `form` element is invalid if it has an `aria-invalid` attribute with no\n   * value or a value of \"false\", or if the result of `checkValidity()` is true.\n   * @example\n   * <input data-testid=\"aria-invalid\" aria-invalid />\n   *\n   * <form data-testid=\"valid-form\">\n   *   <input />\n   * </form>\n   *\n   * await expect.element(page.getByTestId('no-aria-invalid')).not.toBeValid()\n   * await expect.element(page.getByTestId('invalid-form')).toBeInvalid()\n   * @see https://vitest.dev/api/browser/assertions#tobevalid\n   */\n  toBeValid(): R\n  /**\n   * @description\n   * Allows you to assert whether an element contains another element as a descendant or not.\n   * @example\n   * <span data-testid=\"ancestor\">\n   *   <span data-testid=\"descendant\"></span>\n   * </span>\n   *\n   * const ancestor = page.getByTestId('ancestor')\n   * const descendant = page.getByTestId('descendant')\n   * const nonExistentElement = page.getByTestId('does-not-exist')\n   * await expect.element(ancestor).toContainElement(descendant)\n   * await expect.element(descendant).not.toContainElement(ancestor)\n   * await expect.element(ancestor).not.toContainElement(nonExistentElement)\n   * @see https://vitest.dev/api/browser/assertions#tocontainelement\n   */\n  toContainElement(element: HTMLElement | SVGElement | Locator | null): R\n  /**\n   * @description\n   * Assert whether a string representing a HTML element is contained in another element.\n   * @example\n   * <span data-testid=\"parent\"><span data-testid=\"child\"></span></span>\n   *\n   * const parent = page.getByTestId('parent')\n   * await expect.element(parent).toContainHTML('<span data-testid=\"child\"></span>')\n   * @see https://vitest.dev/api/browser/assertions#tocontainhtml\n   */\n  toContainHTML(htmlText: string): R\n  /**\n   * @description\n   * Allows you to check if a given element has an attribute or not.\n   *\n   * You can also optionally check that the attribute has a specific expected value or partial match using\n   * [expect.stringContaining](https://jestjs.io/docs/en/expect.html#expectnotstringcontainingstring) or\n   * [expect.stringMatching](https://jestjs.io/docs/en/expect.html#expectstringmatchingstring-regexp).\n   * @example\n   * <button\n   *   data-testid=\"ok-button\"\n   *   type=\"submit\"\n   *   disabled\n   * >\n   *   ok\n   * </button>\n   *\n   * await expect.element(button).toHaveAttribute('disabled')\n   * await expect.element(button).toHaveAttribute('type', 'submit')\n   * await expect.element(button).not.toHaveAttribute('type', 'button')\n   * @see https://vitest.dev/api/browser/assertions#tohaveattribute\n   */\n  toHaveAttribute(attr: string, value?: unknown): R\n  /**\n   * @description\n   * Check whether the given element has certain classes within its `class` attribute.\n   *\n   * You must provide at least one class, unless you are asserting that an element does not have any classes.\n   * @example\n   * <button\n   *   data-testid=\"delete-button\"\n   *   class=\"btn xs btn-danger\"\n   * >\n   *   delete item\n   * </button>\n   *\n   * <div data-testid=\"no-classes\">no classes</div>\n   *\n   * const deleteButton = page.getByTestId('delete-button')\n   * const noClasses = page.getByTestId('no-classes')\n   * await expect.element(deleteButton).toHaveClass('btn')\n   * await expect.element(deleteButton).toHaveClass('btn-danger xs')\n   * await expect.element(deleteButton).toHaveClass(/danger/, 'xs')\n   * await expect.element(deleteButton).toHaveClass('btn xs btn-danger', {exact: true})\n   * await expect.element(deleteButton).not.toHaveClass('btn xs btn-danger', {exact: true})\n   * await expect.element(noClasses).not.toHaveClass()\n   * @see https://vitest.dev/api/browser/assertions#tohaveclass\n   */\n  toHaveClass(...classNames:\n   | (string | RegExp)[]\n   | [string, options?: {exact: boolean}]\n   | [string, string, options?: {exact: boolean}]\n   | [string, string, string, options?: {exact: boolean}]\n   | [string, string, string, string, options?: {exact: boolean}]\n   | [string, string, string, string, string, options?: {exact: boolean}]\n   | [string, string, string, string, string, string, options?: {exact: boolean}]\n   | [string, string, string, string, string, string, string, options?: {exact: boolean}]\n   | [string, string, string, string, string, string, string, string, options?: {exact: boolean}]\n   | [string, string, string, string, string, string, string, string, string, options?: {exact: boolean}]\n  ): R\n  /**\n   * @description\n   * This allows you to check whether the given form element has the specified displayed value (the one the\n   * end user will see). It accepts <input>, <select> and <textarea> elements with the exception of <input type=\"checkbox\">\n   * and <input type=\"radio\">, which can be meaningfully matched only using toBeChecked or toHaveFormValues.\n   * @example\n   * <label for=\"input-example\">First name</label>\n   * <input type=\"text\" id=\"input-example\" value=\"Luca\" />\n   *\n   * <label for=\"textarea-example\">Description</label>\n   * <textarea id=\"textarea-example\">An example description here.</textarea>\n   *\n   * <label for=\"single-select-example\">Fruit</label>\n   * <select id=\"single-select-example\">\n   *   <option value=\"\">Select a fruit...</option>\n   *   <option value=\"banana\">Banana</option>\n   *   <option value=\"ananas\">Ananas</option>\n   *   <option value=\"avocado\">Avocado</option>\n   * </select>\n   *\n   * <label for=\"multiple-select-example\">Fruits</label>\n   * <select id=\"multiple-select-example\" multiple>\n   *   <option value=\"\">Select a fruit...</option>\n   *   <option value=\"banana\" selected>Banana</option>\n   *   <option value=\"ananas\">Ananas</option>\n   *   <option value=\"avocado\" selected>Avocado</option>\n   * </select>\n   *\n   * const input = page.getByLabelText('First name')\n   * const textarea = page.getByLabelText('Description')\n   * const selectSingle = page.getByLabelText('Fruit')\n   * const selectMultiple = page.getByLabelText('Fruits')\n   *\n   * await expect.element(input).toHaveDisplayValue('Luca')\n   * await expect.element(textarea).toHaveDisplayValue('An example description here.')\n   * await expect.element(selectSingle).toHaveDisplayValue('Select a fruit...')\n   * await expect.element(selectMultiple).toHaveDisplayValue(['Banana', 'Avocado'])\n   *\n   * @see https://vitest.dev/api/browser/assertions#tohavedisplayvalue\n   */\n  toHaveDisplayValue(value: string | number | RegExp | Array<string | RegExp | number>): R\n  /**\n   * @description\n   * Assert whether an element has focus or not.\n   * @example\n   * <div>\n   *   <input type=\"text\" data-testid=\"element-to-focus\" />\n   * </div>\n   *\n   * const input = page.getByTestId('element-to-focus')\n   * input.element().focus()\n   * await expect.element(input).toHaveFocus()\n   * input.element().blur()\n   * await expect.element(input).not.toHaveFocus()\n   * @see https://vitest.dev/api/browser/assertions#tohavefocus\n   */\n  toHaveFocus(): R\n  /**\n   * @description\n   * Check if a form or fieldset contains form controls for each given name, and having the specified value.\n   *\n   * Can only be invoked on a form or fieldset element.\n   * @example\n   * <form data-testid=\"login-form\">\n   *   <input type=\"text\" name=\"username\" value=\"jane.doe\" />\n   *   <input type=\"password\" name=\"password\" value=\"123\" />\n   *   <input type=\"checkbox\" name=\"rememberMe\" checked />\n   *   <button type=\"submit\">Sign in</button>\n   * </form>\n   *\n   * await expect.element(page.getByTestId('login-form')).toHaveFormValues({\n   *   username: 'jane.doe',\n   *   rememberMe: true,\n   * })\n   * @see https://vitest.dev/api/browser/assertions#tohaveformvalues\n   */\n  toHaveFormValues(expectedValues: Record<string, unknown>): R\n  /**\n   * @description\n   * Check if an element has specific css properties with specific values applied.\n   *\n   * Only matches if the element has *all* the expected properties applied, not just some of them.\n   * @example\n   * <button\n   *   data-testid=\"submit-button\"\n   *   style=\"background-color: green; display: none\"\n   * >\n   *   submit\n   * </button>\n   *\n   * const button = page.getByTestId('submit-button')\n   * await expect.element(button).toHaveStyle('background-color: green')\n   * await expect.element(button).toHaveStyle({\n   *   'background-color': 'green',\n   *   display: 'none'\n   * })\n   * @see https://vitest.dev/api/browser/assertions#tohavestyle\n   */\n  toHaveStyle(css: string | Partial<CSSStyleDeclaration>): R\n  /**\n   * @description\n   * Check whether the given element has a text content or not.\n   *\n   * When a string argument is passed through, it will perform a partial case-sensitive match to the element\n   * content.\n   *\n   * To perform a case-insensitive match, you can use a RegExp with the `/i` modifier.\n   *\n   * If you want to match the whole content, you can use a RegExp to do it.\n   * @example\n   * <span data-testid=\"text-content\">Text Content</span>\n   *\n   * const element = page.getByTestId('text-content')\n   * await expect.element(element).toHaveTextContent('Content')\n   * // to match the whole content\n   * await expect.element(element).toHaveTextContent(/^Text Content$/)\n   * // to use case-insensitive match\n   * await expect.element(element).toHaveTextContent(/content$/i)\n   * await expect.element(element).not.toHaveTextContent('content')\n   * @see https://vitest.dev/api/browser/assertions#tohavetextcontent\n   */\n  toHaveTextContent(\n    text: string | number | RegExp,\n    options?: {normalizeWhitespace: boolean},\n  ): R\n  /**\n   * @description\n   * Check whether the given form element has the specified value.\n   *\n   * Accepts `<input>`, `<select>`, and `<textarea>` elements with the exception of `<input type=\"checkbox\">` and\n   * `<input type=\"radiobox\">`, which can be matched only using\n   * [toBeChecked](https://vitest.dev/api/browser/assertions#tobechecked) or\n   * [toHaveFormValues](https://vitest.dev/api/browser/assertions#tohaveformvalues).\n   * @example\n   * <input\n   *   type=\"number\"\n   *   value=\"5\"\n   *   data-testid=\"input-number\" />\n   *\n   * const numberInput = page.getByTestId('input-number')\n   * await expect.element(numberInput).toHaveValue(5)\n   * @see https://vitest.dev/api/browser/assertions#tohavevalue\n   */\n  toHaveValue(value?: string | string[] | number | null): R\n  /**\n   * @description\n   * Assert whether the given element is checked.\n   *\n   * It accepts an `input` of type `checkbox` or `radio` and elements with a `role` of `radio` with a valid\n   * `aria-checked` attribute of \"true\" or \"false\".\n   * @example\n   * <input\n   *   type=\"checkbox\"\n   *   checked\n   *   data-testid=\"input-checkbox\" />\n   * <input\n   *   type=\"radio\"\n   *   value=\"foo\"\n   *   data-testid=\"input-radio\" />\n   *\n   * const inputCheckbox = page.getByTestId('input-checkbox')\n   * const inputRadio = page.getByTestId('input-radio')\n   * await expect.element(inputCheckbox).toBeChecked()\n   * await expect.element(inputRadio).not.toBeChecked()\n   * @see https://vitest.dev/api/browser/assertions#tobechecked\n   */\n  toBeChecked(): R\n  /**\n   * @description\n   * This allows to assert that an element has the expected [accessible description](https://w3c.github.io/accname/).\n   *\n   * You can pass the exact string of the expected accessible description, or you can make a\n   * partial match passing a regular expression, or by using either\n   * [expect.stringContaining](https://jestjs.io/docs/en/expect.html#expectnotstringcontainingstring)\n   * or [expect.stringMatching](https://jestjs.io/docs/en/expect.html#expectstringmatchingstring-regexp).\n   * @example\n   * <a data-testid=\"link\" href=\"/\" aria-label=\"Home page\" title=\"A link to start over\">Start</a>\n   * <a data-testid=\"extra-link\" href=\"/about\" aria-label=\"About page\">About</a>\n   * <img src=\"avatar.jpg\" data-testid=\"avatar\" alt=\"User profile pic\" />\n   * <img src=\"logo.jpg\" data-testid=\"logo\" alt=\"Company logo\" aria-describedby=\"t1\" />\n   * <span id=\"t1\" role=\"presentation\">The logo of Our Company</span>\n   *\n   * await expect.element(page.getByTestId('link')).toHaveAccessibleDescription()\n   * await expect.element(page.getByTestId('link')).toHaveAccessibleDescription('A link to start over')\n   * await expect.element(page.getByTestId('link')).not.toHaveAccessibleDescription('Home page')\n   * await expect.element(page.getByTestId('extra-link')).not.toHaveAccessibleDescription()\n   * await expect.element(page.getByTestId('avatar')).not.toHaveAccessibleDescription()\n   * await expect.element(page.getByTestId('logo')).not.toHaveAccessibleDescription('Company logo')\n   * await expect.element(page.getByTestId('logo')).toHaveAccessibleDescription('The logo of Our Company')\n   * @see https://vitest.dev/api/browser/assertions#tohaveaccessibledescription\n   */\n  toHaveAccessibleDescription(text?: string | RegExp | E): R\n\n  /**\n   * @description\n   * This allows you to assert that an element has the expected\n   * [accessible error message](https://w3c.github.io/aria/#aria-errormessage).\n   *\n   * You can pass the exact string of the expected accessible error message.\n   * Alternatively, you can perform a partial match by passing a regular expression\n   * or by using either\n   * [expect.stringContaining](https://jestjs.io/docs/en/expect.html#expectnotstringcontainingstring)\n   * or [expect.stringMatching](https://jestjs.io/docs/en/expect.html#expectstringmatchingstring-regexp).\n   *\n   * @example\n   * <input aria-label=\"Has Error\" aria-invalid=\"true\" aria-errormessage=\"error-message\" />\n   * <div id=\"error-message\" role=\"alert\">This field is invalid</div>\n   *\n   * <input aria-label=\"No Error Attributes\" />\n   * <input aria-label=\"Not Invalid\" aria-invalid=\"false\" aria-errormessage=\"error-message\" />\n   *\n   * // Inputs with Valid Error Messages\n   * await expect.element(page.getByRole('textbox', {name: 'Has Error'})).toHaveAccessibleErrorMessage()\n   * await expect.element(page.getByRole('textbox', {name: 'Has Error'})).toHaveAccessibleErrorMessage('This field is invalid')\n   * await expect.element(page.getByRole('textbox', {name: 'Has Error'})).toHaveAccessibleErrorMessage(/invalid/i)\n   * await expect.element(\n   *   page.getByRole('textbox', {name: 'Has Error'}),\n   * ).not.toHaveAccessibleErrorMessage('This field is absolutely correct!')\n   *\n   * // Inputs without Valid Error Messages\n   * await expect.element(\n   *   page.getByRole('textbox', {name: 'No Error Attributes'}),\n   * ).not.toHaveAccessibleErrorMessage()\n   *\n   * await expect.element(\n   *   page.getByRole('textbox', {name: 'Not Invalid'}),\n   * ).not.toHaveAccessibleErrorMessage()\n   *\n   * @see https://vitest.dev/api/browser/assertions#tohaveaccessibleerrormessage\n   */\n  toHaveAccessibleErrorMessage(text?: string | RegExp | E): R\n\n  /**\n   * @description\n   * This allows to assert that an element has the expected [accessible name](https://w3c.github.io/accname/).\n   * It is useful, for instance, to assert that form elements and buttons are properly labelled.\n   *\n   * You can pass the exact string of the expected accessible name, or you can make a\n   * partial match passing a regular expression, or by using either\n   * [expect.stringContaining](https://jestjs.io/docs/en/expect.html#expectnotstringcontainingstring)\n   * or [expect.stringMatching](https://jestjs.io/docs/en/expect.html#expectstringmatchingstring-regexp).\n   * @example\n   * <img data-testid=\"img-alt\" src=\"\" alt=\"Test alt\" />\n   * <img data-testid=\"img-empty-alt\" src=\"\" alt=\"\" />\n   * <svg data-testid=\"svg-title\"><title>Test title</title></svg>\n   * <button data-testid=\"button-img-alt\"><img src=\"\" alt=\"Test\" /></button>\n   * <p><img data-testid=\"img-paragraph\" src=\"\" alt=\"\" /> Test content</p>\n   * <button data-testid=\"svg-button\"><svg><title>Test</title></svg></p>\n   * <div><svg data-testid=\"svg-without-title\"></svg></div>\n   * <input data-testid=\"input-title\" title=\"test\" />\n   *\n   * await expect.element(page.getByTestId('img-alt')).toHaveAccessibleName('Test alt')\n   * await expect.element(page.getByTestId('img-empty-alt')).not.toHaveAccessibleName()\n   * await expect.element(page.getByTestId('svg-title')).toHaveAccessibleName('Test title')\n   * await expect.element(page.getByTestId('button-img-alt')).toHaveAccessibleName()\n   * await expect.element(page.getByTestId('img-paragraph')).not.toHaveAccessibleName()\n   * await expect.element(page.getByTestId('svg-button')).toHaveAccessibleName()\n   * await expect.element(page.getByTestId('svg-without-title')).not.toHaveAccessibleName()\n   * await expect.element(page.getByTestId('input-title')).toHaveAccessibleName()\n   * @see https://vitest.dev/api/browser/assertions#tohaveaccessiblename\n   */\n  toHaveAccessibleName(text?: string | RegExp | E): R\n  /**\n   * @description\n   * This allows you to assert that an element has the expected\n   * [role](https://www.w3.org/TR/html-aria/#docconformance).\n   *\n   * This is useful in cases where you already have access to an element via\n   * some query other than the role itself, and want to make additional\n   * assertions regarding its accessibility.\n   *\n   * The role can match either an explicit role (via the `role` attribute), or\n   * an implicit one via the [implicit ARIA\n   * semantics](https://www.w3.org/TR/html-aria/).\n   *\n   * Note: roles are matched literally by string equality, without inheriting\n   * from the ARIA role hierarchy. As a result, querying a superclass role\n   * like 'checkbox' will not include elements with a subclass role like\n   * 'switch'.\n   *\n   * @example\n   * <button data-testid=\"button\">Continue</button>\n   * <div role=\"button\" data-testid=\"button-explicit\">Continue</button>\n   * <button role=\"switch button\" data-testid=\"button-explicit-multiple\">Continue</button>\n   * <a href=\"/about\" data-testid=\"link\">About</a>\n   * <a data-testid=\"link-invalid\">Invalid link<a/>\n   *\n   * await expect.element(page.getByTestId('button')).toHaveRole('button')\n   * await expect.element(page.getByTestId('button-explicit')).toHaveRole('button')\n   * await expect.element(page.getByTestId('button-explicit-multiple')).toHaveRole('button')\n   * await expect.element(page.getByTestId('button-explicit-multiple')).toHaveRole('switch')\n   * await expect.element(page.getByTestId('link')).toHaveRole('link')\n   * await expect.element(page.getByTestId('link-invalid')).not.toHaveRole('link')\n   * await expect.element(page.getByTestId('link-invalid')).toHaveRole('generic')\n   *\n   * @see https://vitest.dev/api/browser/assertions#tohaverole\n   */\n  toHaveRole(\n    // Get autocomplete for ARIARole union types, while still supporting another string\n    // Ref: https://github.com/microsoft/TypeScript/issues/29729#issuecomment-567871939\n    role: ARIARole | (string & {}),\n  ): R\n  /**\n   * @description\n   * This allows you to check whether the given element is partially checked.\n   * It accepts an input of type checkbox and elements with a role of checkbox\n   * with a aria-checked=\"mixed\", or input of type checkbox with indeterminate\n   * set to true\n   *\n   * @example\n   * <input type=\"checkbox\" aria-checked=\"mixed\" data-testid=\"aria-checkbox-mixed\" />\n   * <input type=\"checkbox\" checked data-testid=\"input-checkbox-checked\" />\n   * <input type=\"checkbox\" data-testid=\"input-checkbox-unchecked\" />\n   * <div role=\"checkbox\" aria-checked=\"true\" data-testid=\"aria-checkbox-checked\" />\n   * <div\n   *   role=\"checkbox\"\n   *   aria-checked=\"false\"\n   *   data-testid=\"aria-checkbox-unchecked\"\n   * />\n   * <input type=\"checkbox\" data-testid=\"input-checkbox-indeterminate\" />\n   *\n   * const ariaCheckboxMixed = getByTestId('aria-checkbox-mixed')\n   * const inputCheckboxChecked = getByTestId('input-checkbox-checked')\n   * const inputCheckboxUnchecked = getByTestId('input-checkbox-unchecked')\n   * const ariaCheckboxChecked = getByTestId('aria-checkbox-checked')\n   * const ariaCheckboxUnchecked = getByTestId('aria-checkbox-unchecked')\n   * const inputCheckboxIndeterminate = getByTestId('input-checkbox-indeterminate')\n   *\n   * await expect.element(ariaCheckboxMixed).toBePartiallyChecked()\n   * await expect.element(inputCheckboxChecked).not.toBePartiallyChecked()\n   * await expect.element(inputCheckboxUnchecked).not.toBePartiallyChecked()\n   * await expect.element(ariaCheckboxChecked).not.toBePartiallyChecked()\n   * await expect.element(ariaCheckboxUnchecked).not.toBePartiallyChecked()\n   *\n   * inputCheckboxIndeterminate.indeterminate = true\n   * await expect.element(inputCheckboxIndeterminate).toBePartiallyChecked()\n   * @see https://vitest.dev/api/browser/assertions#tobepartiallychecked\n   */\n  toBePartiallyChecked(): R\n  /**\n   * @description\n   * This allows to assert that an element has a\n   * [text selection](https://developer.mozilla.org/en-US/docs/Web/API/Selection).\n   *\n   * This is useful to check if text or part of the text is selected within an\n   * element. The element can be either an input of type text, a textarea, or any\n   * other element that contains text, such as a paragraph, span, div etc.\n   *\n   * NOTE: the expected selection is a string, it does not allow to check for\n   * selection range indices.\n   *\n   * @example\n   * <div>\n   * <input type=\"text\" value=\"text selected text\" data-testid=\"text\" />\n   * <textarea data-testid=\"textarea\">text selected text</textarea>\n   * <p data-testid=\"prev\">prev</p>\n   * <p data-testid=\"parent\">text <span data-testid=\"child\">selected</span> text</p>\n   * <p data-testid=\"next\">next</p>\n   * </div>\n   *\n   * page.getByTestId('text').element().setSelectionRange(5, 13)\n   * await expect.element(page.getByTestId('text')).toHaveSelection('selected')\n   *\n   * page.getByTestId('textarea').element().setSelectionRange(0, 5)\n   * await expect.element('textarea').toHaveSelection('text ')\n   *\n   * const selection = document.getSelection()\n   * const range = document.createRange()\n   * selection.removeAllRanges()\n   * selection.empty()\n   * selection.addRange(range)\n   *\n   * // selection of child applies to the parent as well\n   * range.selectNodeContents(page.getByTestId('child').element())\n   * await expect.element(page.getByTestId('child')).toHaveSelection('selected')\n   * await expect.element(page.getByTestId('parent')).toHaveSelection('selected')\n   *\n   * // selection that applies from prev all, parent text before child, and part child.\n   * range.setStart(page.getByTestId('prev').element(), 0)\n   * range.setEnd(page.getByTestId('child').element().childNodes[0], 3)\n   * await expect.element(page.queryByTestId('prev')).toHaveSelection('prev')\n   * await expect.element(page.queryByTestId('child')).toHaveSelection('sel')\n   * await expect.element(page.queryByTestId('parent')).toHaveSelection('text sel')\n   * await expect.element(page.queryByTestId('next')).not.toHaveSelection()\n   *\n   * // selection that applies from part child, parent text after child and part next.\n   * range.setStart(page.getByTestId('child').element().childNodes[0], 3)\n   * range.setEnd(page.getByTestId('next').element().childNodes[0], 2)\n   * await expect.element(page.queryByTestId('child')).toHaveSelection('ected')\n   * await expect.element(page.queryByTestId('parent')).toHaveSelection('ected text')\n   * await expect.element(page.queryByTestId('prev')).not.toHaveSelection()\n   * await expect.element(page.queryByTestId('next')).toHaveSelection('ne')\n   *\n   * @see https://vitest.dev/api/browser/assertions#tohaveselection\n   */\n  toHaveSelection(selection?: string): R\n\n  /**\n   * @description\n   * This assertion allows you to perform visual regression testing by comparing\n   * screenshots of elements or pages against stored reference images.\n   *\n   * When differences are detected beyond the configured threshold, the test fails.\n   * To help identify the changes, the assertion generates:\n   *\n   * - The actual screenshot captured during the test\n   * - The expected reference screenshot\n   * - A diff image highlighting the differences (when possible)\n   *\n   * @example\n   * <button data-testid=\"button\">Fancy Button</button>\n   *\n   * // basic usage, auto-generates screenshot name\n   * await expect.element(getByTestId('button')).toMatchScreenshot()\n   *\n   * // with custom name\n   * await expect.element(getByTestId('button')).toMatchScreenshot('fancy-button')\n   *\n   * // with options\n   * await expect.element(getByTestId('button')).toMatchScreenshot({\n   *   comparatorName: 'pixelmatch',\n   *   comparatorOptions: {\n   *     allowedMismatchedPixelRatio: 0.01,\n   *   },\n   * })\n   *\n   * // with both name and options\n   * await expect.element(getByTestId('button')).toMatchScreenshot('fancy-button', {\n   *   comparatorName: 'pixelmatch',\n   *   comparatorOptions: {\n   *     allowedMismatchedPixelRatio: 0.01,\n   *   },\n   * })\n   *\n   * @see https://vitest.dev/api/browser/assertions#tomatchscreenshot\n   */\n  toMatchScreenshot<ComparatorName extends keyof ScreenshotComparatorRegistry>(\n    options?: ScreenshotMatcherOptions<ComparatorName>,\n  ): Promise<R>\n  toMatchScreenshot<ComparatorName extends keyof ScreenshotComparatorRegistry>(\n    name?: string,\n    options?: ScreenshotMatcherOptions<ComparatorName>,\n  ): Promise<R>\n}\n"
  },
  {
    "path": "packages/browser/matchers.d.ts",
    "content": "import type { Locator } from './context.js'\nimport type { TestingLibraryMatchers } from './jest-dom.js'\nimport type { Assertion, ExpectPollOptions } from 'vitest'\n\ndeclare module 'vitest' {\n  interface JestAssertion<T = any> extends TestingLibraryMatchers<void, T> {}\n  interface AsymmetricMatchersContaining extends TestingLibraryMatchers<void, void> {}\n\n  type Promisify<O> = {\n    [K in keyof O]: O[K] extends (...args: infer A) => infer R\n      ? O extends R\n        ? Promisify<O[K]>\n        : (...args: A) => Promise<R>\n      : O[K];\n  }\n\n  type PromisifyDomAssertion<T> = Promisify<Assertion<T>>\n\n  interface ExpectStatic {\n    /**\n     * `expect.element(locator)` is a shorthand for `expect.poll(() => locator.element())`.\n     * You can set default timeout via `expect.poll.timeout` option in the config.\n     * @see {@link https://vitest.dev/api/expect#poll}\n     */\n    element: <T extends HTMLElement | SVGElement | null | Locator>(element: T, options?: ExpectPollOptions) => PromisifyDomAssertion<Awaited<HTMLElement | SVGElement | null>>\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "packages/browser/package.json",
    "content": "{\n  \"name\": \"@vitest/browser\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Browser running for Vitest\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/guide/browser/\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/browser\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vitest\",\n    \"test\",\n    \"browser\",\n    \"component\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./context\": {\n      \"types\": \"./context.d.ts\",\n      \"default\": \"./context.js\"\n    },\n    \"./client\": {\n      \"default\": \"./dist/client.js\"\n    },\n    \"./matchers\": {\n      \"types\": \"./matchers.d.ts\",\n      \"default\": \"./dummy.js\"\n    },\n    \"./locators\": {\n      \"types\": \"./dist/locators.d.ts\",\n      \"default\": \"./dist/locators.js\"\n    },\n    \"./utils\": {\n      \"default\": \"./dummy.js\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"*.d.ts\",\n    \"context.js\",\n    \"dist\",\n    \"dummy.js\",\n    \"providers\"\n  ],\n  \"scripts\": {\n    \"typecheck\": \"tsc -p ./src/client/tsconfig.json --noEmit\",\n    \"typecheck:why\": \"tsc -p ./src/client/tsconfig.json --noEmit --explainFiles > explainTypes.txt\",\n    \"build\": \"premove dist && pnpm build:node && pnpm build:client\",\n    \"build:client\": \"vite build src/client\",\n    \"build:node\": \"rollup -c\",\n    \"dev:client\": \"node --watch-preserve-output --watch-path src/client scripts/build-client.js\",\n    \"dev:node\": \"rollup -c --watch --watch.include 'src/**'\",\n    \"dev\": \"premove dist && pnpm run --stream '/^dev:/'\"\n  },\n  \"peerDependencies\": {\n    \"vitest\": \"workspace:*\"\n  },\n  \"dependencies\": {\n    \"@blazediff/core\": \"1.9.1\",\n    \"@vitest/mocker\": \"workspace:*\",\n    \"@vitest/utils\": \"workspace:*\",\n    \"magic-string\": \"catalog:\",\n    \"pngjs\": \"^7.0.0\",\n    \"sirv\": \"catalog:\",\n    \"tinyrainbow\": \"catalog:\",\n    \"ws\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@opentelemetry/api\": \"^1.9.0\",\n    \"@testing-library/user-event\": \"^14.6.1\",\n    \"@types/pngjs\": \"^6.0.5\",\n    \"@types/ws\": \"catalog:\",\n    \"@vitest/runner\": \"workspace:*\",\n    \"birpc\": \"catalog:\",\n    \"flatted\": \"catalog:\",\n    \"ivya\": \"^1.7.1\",\n    \"mime\": \"^4.1.0\",\n    \"pathe\": \"catalog:\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/browser/rollup.config.js",
    "content": "import { createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst external = [\n  ...Object.keys(pkg.dependencies),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^@?vitest(\\/|$)/,\n  '@vitest/browser/utils',\n  '@vitest/browser/context',\n  '@vitest/browser/client',\n  'vitest/browser',\n  'worker_threads',\n  'node:worker_threads',\n  'vite',\n  'vitest/internal/browser',\n]\n\nconst dtsUtils = createDtsUtils()\nconst dtsUtilsClient = createDtsUtils({\n  // need extra depth to avoid output conflict\n  isolatedDeclDir: '.types-client/tester',\n  cleanupDir: '.types-client',\n})\n\nconst plugins = [\n  resolve({\n    preferBuiltins: true,\n  }),\n  json(),\n  commonjs(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nconst input = {\n  index: './src/node/index.ts',\n}\n\nexport default () =>\n  defineConfig([\n    {\n      input,\n      output: {\n        dir: 'dist',\n        format: 'esm',\n      },\n      external,\n      context: 'null',\n      plugins: [\n        {\n          name: 'no-side-effects',\n          async resolveId(id, importer) {\n            // Clipboard injects \"afterEach\" callbacks\n            // We mark it as having no side effects to prevent it from being included in the bundle\n            if (id.includes('dataTransfer/Clipboard')) {\n              return {\n                ...await this.resolve(id, importer),\n                moduleSideEffects: false,\n              }\n            }\n          },\n        },\n        ...dtsUtils.isolatedDecl(),\n        ...plugins,\n      ],\n    },\n    {\n      input: {\n        'locators': './src/client/tester/locators/index.ts',\n        'expect-element': './src/client/tester/expect-element.ts',\n      },\n      output: {\n        dir: 'dist',\n        format: 'esm',\n      },\n      external,\n      plugins: [\n        ...dtsUtilsClient.isolatedDecl(),\n        ...plugins.filter(p => p.name !== 'unplugin-oxc'),\n        oxc({\n          transform: { target: 'node18' },\n          minify: true,\n        }),\n      ],\n    },\n    {\n      input: './src/client/tester/context.ts',\n      output: {\n        file: 'dist/context.js',\n        format: 'esm',\n      },\n      external: ['vitest/internal/browser'],\n      plugins: [\n        oxc({\n          transform: { target: 'node18' },\n        }),\n      ],\n    },\n    {\n      input: './src/client/client.ts',\n      output: {\n        file: 'dist/client.js',\n        format: 'esm',\n      },\n      plugins: [\n        resolve({\n          preferBuiltins: true,\n        }),\n        oxc({\n          transform: { target: 'node18' },\n        }),\n      ],\n    },\n    {\n      input: './src/client/tester/state.ts',\n      output: {\n        file: 'dist/state.js',\n        format: 'iife',\n      },\n      plugins: [\n        oxc({\n          transform: { target: 'node18' },\n        }),\n        resolve(),\n      ],\n    },\n    {\n      input: dtsUtils.dtsInput(input),\n      output: {\n        dir: 'dist',\n        entryFileNames: '[name].d.ts',\n        format: 'esm',\n      },\n      watch: false,\n      external,\n      plugins: dtsUtils.dts(),\n    },\n    {\n      input: dtsUtilsClient.dtsInput({\n        locators: './src/client/tester/locators/index.ts',\n      }),\n      output: {\n        dir: 'dist',\n        entryFileNames: '[name].d.ts',\n        format: 'esm',\n      },\n      watch: false,\n      external,\n      plugins: dtsUtilsClient.dts(),\n    },\n  ])\n"
  },
  {
    "path": "packages/browser/scripts/build-client.js",
    "content": "// wrapper script for `node --watch`.\n// this works around some issues with `vite build --watch`.\nimport { spawn } from 'node:child_process'\n\nspawn('node', ['--run', 'build:client'], {\n  stdio: 'inherit',\n})\n"
  },
  {
    "path": "packages/browser/src/client/channel.ts",
    "content": "import type { CancelReason, FileSpecification } from '@vitest/runner'\nimport type { OTELCarrier } from 'vitest/internal/browser'\nimport { getBrowserState } from './utils'\n\nexport interface IframeViewportEvent {\n  event: 'viewport'\n  width: number\n  height: number\n  iframeId: string\n}\n\nexport interface IframeViewportFailEvent {\n  event: 'viewport:fail'\n  iframeId: string\n  error: string\n}\n\nexport interface IframeViewportDoneEvent {\n  event: 'viewport:done'\n  iframeId: string\n}\n\nexport interface GlobalChannelTestRunCanceledEvent {\n  type: 'cancel'\n  reason: CancelReason\n}\n\nexport interface IframeExecuteEvent {\n  event: 'execute'\n  method: 'run' | 'collect'\n  files: FileSpecification[]\n  iframeId: string\n  context: string\n}\n\nexport interface IframeCleanupEvent {\n  event: 'cleanup'\n  iframeId: string\n}\n\nexport interface IframePrepareEvent {\n  event: 'prepare'\n  iframeId: string\n  startTime: number\n  otelCarrier?: OTELCarrier\n}\n\nexport type GlobalChannelIncomingEvent = GlobalChannelTestRunCanceledEvent\n\nexport type IframeChannelIncomingEvent\n  = | IframeViewportEvent\n\nexport type IframeChannelOutgoingEvent\n  = | IframeExecuteEvent\n    | IframeCleanupEvent\n    | IframePrepareEvent\n    | IframeViewportFailEvent\n    | IframeViewportDoneEvent\n\nexport type IframeChannelEvent\n  = | IframeChannelIncomingEvent\n    | IframeChannelOutgoingEvent\n\nexport const channel: BroadcastChannel = new BroadcastChannel(\n  `vitest:${getBrowserState().sessionId}`,\n)\nexport const globalChannel: BroadcastChannel = new BroadcastChannel('vitest:global')\n"
  },
  {
    "path": "packages/browser/src/client/client.ts",
    "content": "import type { ModuleMocker } from '@vitest/mocker/browser'\nimport type { CancelReason } from '@vitest/runner'\nimport type { BirpcReturn } from 'birpc'\nimport type { WebSocketBrowserEvents, WebSocketBrowserHandlers } from '../types'\nimport type { IframeOrchestrator } from './orchestrator'\nimport { createBirpc } from 'birpc'\nimport { parse, stringify } from 'flatted'\nimport { getBrowserState } from './utils'\n\nconst PAGE_TYPE = getBrowserState().type\n\nexport const PORT: string = location.port\nexport const HOST: string = [location.hostname, PORT].filter(Boolean).join(':')\nexport const RPC_ID: string\n  = PAGE_TYPE === 'orchestrator'\n    ? getBrowserState().sessionId\n    : getBrowserState().testerId\nconst METHOD = getBrowserState().method\nexport const ENTRY_URL: string = `${\n  location.protocol === 'https:' ? 'wss:' : 'ws:'\n}//${HOST}/__vitest_browser_api__?type=${PAGE_TYPE}&rpcId=${RPC_ID}&sessionId=${getBrowserState().sessionId}&projectName=${encodeURIComponent(getBrowserState().config.name || '')}&method=${METHOD}&token=${(window as any).VITEST_API_TOKEN || '0'}`\n\nconst onCancelCallbacks: ((reason: CancelReason) => void)[] = []\n\nexport function onCancel(callback: (reason: CancelReason) => void): void {\n  onCancelCallbacks.push(callback)\n}\n\nexport interface VitestBrowserClient {\n  rpc: BrowserRPC\n  ws: WebSocket\n  waitForConnection: () => Promise<void>\n}\n\nexport type BrowserRPC = BirpcReturn<\n  WebSocketBrowserHandlers,\n  WebSocketBrowserEvents\n>\n\n// ws connection can be established before the orchestrator is fully loaded\n// in very rare cases in the preview provider\nfunction waitForOrchestrator() {\n  return new Promise<IframeOrchestrator>((resolve, reject) => {\n    const type = getBrowserState().type\n    if (type !== 'orchestrator') {\n      reject(new TypeError('Only orchestrator can create testers.'))\n      return\n    }\n\n    function check() {\n      const orchestrator = getBrowserState().orchestrator\n      if (orchestrator) {\n        return resolve(orchestrator)\n      }\n      setTimeout(check)\n    }\n    check()\n  })\n}\n\nfunction createClient() {\n  const autoReconnect = true\n  const reconnectInterval = 2000\n  const reconnectTries = 10\n  const connectTimeout = 60000\n\n  let tries = reconnectTries\n\n  const ctx: VitestBrowserClient = {\n    ws: new WebSocket(ENTRY_URL),\n    waitForConnection,\n  } as VitestBrowserClient\n\n  let onMessage: Function\n\n  ctx.rpc = createBirpc<WebSocketBrowserHandlers, WebSocketBrowserEvents>(\n    {\n      async onCancel(reason) {\n        await Promise.all(onCancelCallbacks.map(fn => fn(reason)))\n      },\n      async createTesters(options) {\n        const orchestrator = await waitForOrchestrator()\n        return orchestrator.createTesters(options)\n      },\n      async cleanupTesters() {\n        const orchestrator = await waitForOrchestrator()\n        return orchestrator.cleanupTesters()\n      },\n      cdpEvent(event: string, payload: unknown) {\n        const cdp = getBrowserState().cdp\n        if (!cdp) {\n          return\n        }\n        cdp.emit(event, payload)\n      },\n      async resolveManualMock(url: string) {\n        // @ts-expect-error not typed global API\n        const mocker = globalThis.__vitest_mocker__ as ModuleMocker | undefined\n        const responseId = getBrowserState().sessionId\n        if (!mocker) {\n          return { url, keys: [], responseId }\n        }\n        const exports = await mocker.resolveFactoryModule(url)\n        const keys = Object.keys(exports)\n        return {\n          url,\n          keys,\n          responseId,\n        }\n      },\n    },\n    {\n      post: msg => ctx.ws.send(msg),\n      on: fn => (onMessage = fn),\n      serialize: e =>\n        stringify(e, (_, v) => {\n          if (v instanceof Error) {\n            return {\n              name: v.name,\n              message: v.message,\n              stack: v.stack,\n            }\n          }\n          return v\n        }),\n      deserialize: parse,\n      timeout: -1, // createTesters can take a while\n    },\n  )\n\n  let openPromise: Promise<void>\n\n  function reconnect(reset = false) {\n    if (reset) {\n      tries = reconnectTries\n    }\n    ctx.ws = new WebSocket(ENTRY_URL)\n    registerWS()\n  }\n\n  function registerWS() {\n    openPromise = new Promise((resolve, reject) => {\n      const timeout = setTimeout(() => {\n        reject(\n          new Error(\n            `Cannot connect to the server in ${connectTimeout / 1000} seconds`,\n          ),\n        )\n      }, connectTimeout)\n      if (ctx.ws.OPEN === ctx.ws.readyState) {\n        resolve()\n      }\n      // still have a listener even if it's already open to update tries\n      ctx.ws.addEventListener('open', () => {\n        tries = reconnectTries\n        resolve()\n        clearTimeout(timeout)\n      })\n    })\n    ctx.ws.addEventListener('message', (v) => {\n      onMessage(v.data)\n    })\n    ctx.ws.addEventListener('close', () => {\n      tries -= 1\n      if (autoReconnect && tries > 0) {\n        setTimeout(reconnect, reconnectInterval)\n      }\n    })\n  }\n\n  registerWS()\n\n  function waitForConnection() {\n    return openPromise\n  }\n\n  return ctx\n}\n\nexport const client: VitestBrowserClient = createClient()\n\nexport * from './channel'\n"
  },
  {
    "path": "packages/browser/src/client/orchestrator.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"{__VITEST_FAVICON__}\" type=\"image/svg+xml\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vitest Browser Runner</title>\n    <style>\n      html {\n        overflow: hidden;\n        padding: 0;\n        margin: 0;\n      }\n      body {\n        padding: 0;\n        margin: 0;\n      }\n      html,\n      body,\n      iframe[data-vitest],\n      #vitest-tester {\n        width: 100%;\n        height: 100%;\n      }\n    </style>\n    {__VITEST_INJECTOR__}\n    {__VITEST_ERROR_CATCHER__}\n    {__VITEST_SCRIPTS__}\n  </head>\n  <body>\n    <script type=\"module\" src=\"/orchestrator.ts\"></script>\n    <div id=\"vitest-tester\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/browser/src/client/orchestrator.ts",
    "content": "import type { Context as OTELContext } from '@opentelemetry/api'\nimport type { GlobalChannelIncomingEvent, IframeChannelIncomingEvent, IframeChannelOutgoingEvent, IframeViewportDoneEvent, IframeViewportFailEvent } from '@vitest/browser/client'\nimport type { FileSpecification } from '@vitest/runner'\nimport type { BrowserTesterOptions, SerializedConfig } from 'vitest'\nimport { channel, client, globalChannel } from '@vitest/browser/client'\nimport { generateFileHash } from '@vitest/runner/utils'\nimport { relative } from 'pathe'\nimport { Traces } from 'vitest/internal/browser'\nimport { getUiAPI } from './ui'\nimport { getBrowserState, getConfig } from './utils'\n\nconst ID_ALL = '__vitest_all__'\n\nexport class IframeOrchestrator {\n  private cancelled = false\n  private recreateNonIsolatedIframe = false\n  private iframes = new Map<string, HTMLIFrameElement>()\n\n  public eventTarget: EventTarget = new EventTarget()\n\n  private traces: Traces\n\n  constructor() {\n    debug('init orchestrator', getBrowserState().sessionId)\n\n    const otelConfig = getBrowserState().config.experimental.openTelemetry\n    this.traces = new Traces({\n      enabled: !!(otelConfig?.enabled && otelConfig.browserSdkPath),\n      sdkPath: `/@fs/${otelConfig?.browserSdkPath}`,\n    })\n\n    channel.addEventListener(\n      'message',\n      e => this.onIframeEvent(e),\n    )\n    globalChannel.addEventListener(\n      'message',\n      e => this.onGlobalChannelEvent(e),\n    )\n  }\n\n  public async createTesters(options: BrowserTesterOptions): Promise<void> {\n    await this.traces.waitInit()\n    this.traces.recordInitSpan(\n      this.traces.getContextFromCarrier(getBrowserState().otelCarrier),\n    )\n    const orchestratorSpan = this.traces.startContextSpan(\n      'vitest.browser.orchestrator.run',\n      this.traces.getContextFromCarrier(options.otelCarrier),\n    )\n    orchestratorSpan.span.setAttributes({\n      'vitest.browser.files': options.files.map(f => f.filepath),\n    })\n    const endSpan = async () => {\n      orchestratorSpan.span.end()\n      // orchestrator doesn't know specific timing when it gets torn down,\n      // so we ensure flushing traces here after each run\n      await this.traces.flush()\n    }\n\n    const startTime = performance.now()\n\n    this.cancelled = false\n\n    const config = getConfig()\n    debug('create testers', ...options.files.join(', '))\n    const container = await getContainer(config)\n\n    if (config.browser.ui) {\n      container.className = 'absolute origin-top mt-[8px]'\n      container.parentElement!.setAttribute('data-ready', 'true')\n      // in non-isolated mode this will also remove the iframe,\n      // so we only do this once\n      if (container.textContent) {\n        container.textContent = ''\n      }\n    }\n\n    if (config.browser.isolate === false) {\n      await this.runNonIsolatedTests(container, options, startTime, orchestratorSpan.context)\n      await endSpan()\n      return\n    }\n\n    this.iframes.forEach(iframe => iframe.remove())\n    this.iframes.clear()\n\n    for (let i = 0; i < options.files.length; i++) {\n      if (this.cancelled) {\n        await endSpan()\n        return\n      }\n\n      const file = options.files[i]\n      debug('create iframe', file.filepath)\n\n      await this.runIsolatedTestInIframe(\n        container,\n        file,\n        options,\n        startTime,\n        orchestratorSpan.context,\n      )\n    }\n    await endSpan()\n  }\n\n  public async cleanupTesters(): Promise<void> {\n    const config = getConfig()\n    if (config.browser.isolate) {\n      // isolated mode assigns filepaths as ids\n      const files = Array.from(this.iframes.keys())\n      // when the run is completed, show the last file in the UI\n      const ui = getUiAPI()\n      if (ui && files[0]) {\n        const id = generateFileId(files[0])\n        ui.setCurrentFileId(id)\n      }\n      return\n    }\n    // we only cleanup non-isolated iframe because\n    // in isolated mode every iframe is cleaned up after the test\n    const iframe = this.iframes.get(ID_ALL)\n    if (!iframe) {\n      return\n    }\n    await this.sendEventToIframe({\n      event: 'cleanup',\n      iframeId: ID_ALL,\n    })\n    this.recreateNonIsolatedIframe = true\n  }\n\n  private async runNonIsolatedTests(\n    container: HTMLDivElement,\n    options: BrowserTesterOptions,\n    startTime: number,\n    otelContext: OTELContext,\n  ) {\n    if (this.recreateNonIsolatedIframe) {\n      // recreate a new non-isolated iframe during watcher reruns\n      // because we called \"cleanup\" in the previous run\n      // the iframe is not removed immediately to let the user see the last test\n      this.recreateNonIsolatedIframe = false\n      this.iframes.get(ID_ALL)!.remove()\n      this.iframes.delete(ID_ALL)\n      debug('recreate non-isolated iframe')\n    }\n\n    if (!this.iframes.has(ID_ALL)) {\n      debug('preparing non-isolated iframe')\n      await this.prepareIframe(container, ID_ALL, startTime, otelContext)\n    }\n\n    const config = getConfig()\n    const { width, height } = config.browser.viewport\n    const iframe = this.iframes.get(ID_ALL)!\n\n    await setIframeViewport(iframe, width, height)\n    debug('run non-isolated tests', options.files.join(', '))\n    await this.sendEventToIframe({\n      event: 'execute',\n      iframeId: ID_ALL,\n      files: options.files,\n      method: options.method,\n      context: options.providedContext,\n    })\n    debug('finished running tests', options.files.join(', '))\n    // we don't cleanup here because in non-isolated mode\n    // it is done after all tests finished running\n  }\n\n  private async runIsolatedTestInIframe(\n    container: HTMLDivElement,\n    spec: FileSpecification,\n    options: BrowserTesterOptions,\n    startTime: number,\n    otelContext: OTELContext,\n  ) {\n    const config = getConfig()\n    const { width, height } = config.browser.viewport\n\n    const file = spec.filepath\n\n    if (this.iframes.has(file)) {\n      this.iframes.get(file)!.remove()\n      this.iframes.delete(file)\n    }\n\n    const iframe = await this.prepareIframe(\n      container,\n      file,\n      startTime,\n      otelContext,\n    )\n    await setIframeViewport(iframe, width, height)\n    // running tests after the \"prepare\" event\n    await this.sendEventToIframe({\n      event: 'execute',\n      files: [spec],\n      method: options.method,\n      iframeId: file,\n      context: options.providedContext,\n    })\n    // perform \"cleanup\" to cleanup resources and calculate the coverage\n    await this.sendEventToIframe({\n      event: 'cleanup',\n      iframeId: file,\n    })\n  }\n\n  private dispatchIframeError(error: Error) {\n    const event = new CustomEvent('iframeerror', { detail: error })\n    this.eventTarget.dispatchEvent(event)\n    return error\n  }\n\n  private async prepareIframe(\n    container: HTMLDivElement,\n    iframeId: string,\n    startTime: number,\n    otelContext: OTELContext,\n  ) {\n    const iframe = this.createTestIframe(iframeId)\n    container.appendChild(iframe)\n\n    await new Promise<void>((resolve, reject) => {\n      iframe.onload = () => {\n        const href = this.getIframeHref(iframe)\n        debug('iframe loaded with href', href)\n        if (href !== iframe.src) {\n          reject(this.dispatchIframeError(new Error(\n            `Cannot connect to the iframe. `\n            + `Did you change the location or submitted a form? `\n            + 'If so, don\\'t forget to call `event.preventDefault()` to avoid reloading the page.\\n\\n'\n            + `Received URL: ${href || 'unknown due to CORS'}\\nExpected: ${iframe.src}`,\n          )))\n        }\n        else if (this.iframes.has(iframeId)) {\n          const events = this.iframeEvents.get(iframe)\n          if (events?.size) {\n            this.dispatchIframeError(new Error(this.createWarningMessage(iframeId, 'during a test')))\n          }\n          else {\n            this.warnReload(iframe, iframeId)\n          }\n        }\n        else {\n          this.iframes.set(iframeId, iframe)\n          this.sendEventToIframe({\n            event: 'prepare',\n            iframeId,\n            startTime,\n            otelCarrier: this.traces.getContextCarrier(otelContext),\n          }).then(resolve, error => reject(this.dispatchIframeError(error)))\n        }\n      }\n      iframe.onerror = (e) => {\n        if (typeof e === 'string') {\n          reject(this.dispatchIframeError(new Error(e)))\n        }\n        else if (e instanceof ErrorEvent) {\n          reject(this.dispatchIframeError(e.error))\n        }\n        else {\n          reject(this.dispatchIframeError(new Error(`Cannot load the iframe ${iframeId}.`)))\n        }\n      }\n    })\n    return iframe\n  }\n\n  private loggedIframe = new WeakSet<HTMLIFrameElement>()\n\n  private createWarningMessage(iframeId: string, location: string) {\n    return `The iframe${iframeId === ID_ALL ? '' : ` for \"${iframeId}\"`} was reloaded ${location}. `\n      + `This can lead to unexpected behavior during tests, duplicated test results or tests hanging.\\n\\n`\n      + `Make sure that your test code does not change window's location, submit forms without preventing default behavior, or imports unoptimized dependencies.\\n`\n      + `If you are using a framework that manipulates browser history (like React Router), consider using memory-based routing for tests. `\n      + `If you think this is a false positive, open an issue with a reproduction: https://github.com/vitest-dev/vitest/issues/new`\n  }\n\n  private warnReload(iframe: HTMLIFrameElement, iframeId: string) {\n    if (this.loggedIframe.has(iframe)) {\n      return\n    }\n    this.loggedIframe.add(iframe)\n    const message = `\\x1B[41m WARNING \\x1B[49m ${this.createWarningMessage(iframeId, 'multiple times')}`\n\n    client.rpc.sendLog('run', {\n      type: 'stderr',\n      time: Date.now(),\n      content: message,\n      size: message.length,\n      taskId: iframeId === ID_ALL ? undefined : generateFileId(iframeId),\n    }).catch(() => { /* ignore */ })\n  }\n\n  private getIframeHref(iframe: HTMLIFrameElement) {\n    try {\n      // same origin iframe has contentWindow\n      // same origin trusted iframe (where tests can run)\n      // also allows accessing \"location\"\n      return iframe.contentWindow?.location.href\n    }\n    catch {\n      // looks like this iframe is not a tester.html\n      return undefined\n    }\n  }\n\n  private createTestIframe(iframeId: string) {\n    const iframe = document.createElement('iframe')\n    const src = `/?sessionId=${getBrowserState().sessionId}&iframeId=${iframeId}`\n    iframe.setAttribute('loading', 'eager')\n    iframe.setAttribute('src', src)\n    iframe.setAttribute('data-vitest', 'true')\n\n    iframe.style.border = 'none'\n    iframe.style.width = '100%'\n    iframe.style.height = '100%'\n    iframe.setAttribute('allowfullscreen', 'true')\n    iframe.setAttribute('allow', 'clipboard-write;')\n    iframe.setAttribute('name', 'vitest-iframe')\n    return iframe\n  }\n\n  private async onGlobalChannelEvent(e: MessageEvent<GlobalChannelIncomingEvent>) {\n    debug('global channel event', JSON.stringify(e.data))\n    switch (e.data.type) {\n      case 'cancel': {\n        this.cancelled = true\n        break\n      }\n    }\n  }\n\n  private async onIframeEvent(e: MessageEvent<IframeChannelIncomingEvent>) {\n    debug('iframe event', JSON.stringify(e.data))\n    switch (e.data.event) {\n      case 'viewport': {\n        const { width, height, iframeId: id } = e.data\n        const iframe = this.iframes.get(id)\n        if (!iframe) {\n          const error = `Cannot find iframe with id ${id}`\n          channel.postMessage({\n            event: 'viewport:fail',\n            iframeId: id,\n            error,\n          } satisfies IframeViewportFailEvent)\n          await client.rpc.onUnhandledError(\n            {\n              name: 'Teardown Error',\n              message: error,\n            },\n            'Teardown Error',\n          )\n          break\n        }\n        await setIframeViewport(iframe, width, height)\n        channel.postMessage({ event: 'viewport:done', iframeId: id } satisfies IframeViewportDoneEvent)\n        break\n      }\n      default: {\n        // ignore responses\n        if (\n          typeof e.data.event === 'string'\n          && (e.data.event as string).startsWith('response:')\n        ) {\n          break\n        }\n\n        await client.rpc.onUnhandledError(\n          {\n            name: 'Unexpected Event',\n            message: `Unexpected event: ${(e.data as any).event}`,\n          },\n          'Unexpected Event',\n        )\n      }\n    }\n  }\n\n  private iframeEvents = new WeakMap<HTMLIFrameElement, Set<string>>()\n\n  private async sendEventToIframe(event: IframeChannelOutgoingEvent): Promise<void> {\n    const iframe = this.iframes.get(event.iframeId)\n    if (!iframe) {\n      throw new Error(`Cannot find iframe with id ${event.iframeId}`)\n    }\n    let events = this.iframeEvents.get(iframe)\n    if (!events) {\n      events = new Set()\n      this.iframeEvents.set(iframe, events)\n    }\n    events.add(event.event)\n\n    channel.postMessage(event)\n    return new Promise<void>((resolve, reject) => {\n      const cleanupEvents = () => {\n        channel.removeEventListener('message', onReceived)\n        this.eventTarget.removeEventListener('iframeerror', onError)\n      }\n\n      function onReceived(e: MessageEvent) {\n        if (e.data.iframeId === event.iframeId && e.data.event === `response:${event.event}`) {\n          resolve()\n          cleanupEvents()\n          events!.delete(event.event)\n        }\n      }\n\n      function onError(e: Event) {\n        reject((e as CustomEvent).detail)\n        cleanupEvents()\n        events!.delete(event.event)\n      }\n\n      this.eventTarget.addEventListener('iframeerror', onError)\n      channel.addEventListener('message', onReceived)\n    })\n  }\n}\n\nconst orchestrator = new IframeOrchestrator()\ngetBrowserState().orchestrator = orchestrator\n\nasync function getContainer(config: SerializedConfig): Promise<HTMLDivElement> {\n  if (config.browser.ui) {\n    const element = document.querySelector('#tester-ui')\n    if (!element) {\n      return new Promise<HTMLDivElement>((resolve) => {\n        queueMicrotask(() => {\n          resolve(getContainer(config))\n        })\n      })\n    }\n    return element as HTMLDivElement\n  }\n  return document.querySelector('#vitest-tester') as HTMLDivElement\n}\n\nfunction generateFileId(file: string) {\n  const config = getConfig()\n  const path = relative(config.root, file)\n  return generateFileHash(path, config.name)\n}\n\nasync function setIframeViewport(\n  iframe: HTMLIFrameElement,\n  width: number,\n  height: number,\n) {\n  const ui = getUiAPI()\n  if (ui) {\n    await ui.setIframeViewport(width, height)\n  }\n  else if (getBrowserState().provider === 'webdriverio') {\n    iframe.parentElement?.setAttribute('data-scale', '1')\n    await client.rpc.triggerCommand(\n      getBrowserState().sessionId,\n      '__vitest_viewport',\n      undefined,\n      [{ width, height }],\n    )\n  }\n  else {\n    const scale = Math.min(\n      1,\n      iframe.parentElement!.parentElement!.clientWidth / width,\n      iframe.parentElement!.parentElement!.clientHeight / height,\n    )\n    iframe.parentElement!.style.cssText = `\n      width: ${width}px;\n      height: ${height}px;\n      transform: scale(${scale});\n      transform-origin: left top;\n    `\n    iframe.parentElement?.setAttribute('data-scale', String(scale))\n    await new Promise(r => requestAnimationFrame(r))\n  }\n}\n\nfunction debug(...args: unknown[]) {\n  const debug = getConfig().env.VITEST_BROWSER_DEBUG\n  if (debug && debug !== 'false') {\n    client.rpc.debug(...args.map(String))\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/public/error-catcher.js",
    "content": "import { client } from '@vitest/browser/client'\n\nfunction serializeError(unhandledError) {\n  const state = globalThis.__vitest_worker__\n  const VITEST_TEST_NAME = state && state.current && state.current.type === 'test'\n    ? state.current.name\n    : undefined\n  const VITEST_TEST_PATH = state && state.filepath ? state.filepath : undefined\n\n  if (typeof unhandledError !== 'object' || !unhandledError) {\n    return {\n      message: String(unhandledError),\n      VITEST_TEST_NAME,\n      VITEST_TEST_PATH,\n    }\n  }\n\n  return {\n    name: unhandledError.name,\n    message: unhandledError.message,\n    stack: String(unhandledError.stack),\n    VITEST_TEST_NAME,\n    VITEST_TEST_PATH,\n  }\n}\n\nfunction catchWindowErrors(errorEvent, prop, cb) {\n  let userErrorListenerCount = 0\n  function throwUnhandlerError(e) {\n    if (userErrorListenerCount === 0 && e[prop] != null) {\n      cb(e)\n    }\n    else {\n      // `ErrorEvent` doesn't necessary have `ErrotEvent.error` defined\n      // but some has `ErrorEvent.message` defined, e.g. ResizeObserver error.\n      // https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent/error\n      // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors\n      console.error(e.message ? new Error(e.message) : e)\n    }\n  }\n  const addEventListener = window.addEventListener.bind(window)\n  const removeEventListener = window.removeEventListener.bind(window)\n  window.addEventListener(errorEvent, throwUnhandlerError)\n  window.addEventListener = function (...args) {\n    if (args[0] === errorEvent) {\n      userErrorListenerCount++\n    }\n    return addEventListener.apply(this, args)\n  }\n  window.removeEventListener = function (...args) {\n    if (args[0] === errorEvent && userErrorListenerCount) {\n      userErrorListenerCount--\n    }\n    return removeEventListener.apply(this, args)\n  }\n  return function clearErrorHandlers() {\n    window.removeEventListener(errorEvent, throwUnhandlerError)\n  }\n}\n\nfunction registerUnexpectedErrors() {\n  const offError = catchWindowErrors('error', 'error', event =>\n    reportUnexpectedError('Error', event.error))\n  const offRejection = catchWindowErrors('unhandledrejection', 'reason', event =>\n    reportUnexpectedError('Unhandled Rejection', event.reason))\n  return () => {\n    offError()\n    offRejection()\n  }\n}\n\nasync function reportUnexpectedError(\n  type,\n  error,\n) {\n  const processedError = serializeError(error)\n  await client.waitForConnection().then(() => {\n    return client.rpc.onUnhandledError(processedError, type)\n  }).catch(console.error)\n}\n\nglobalThis.__vitest_browser_runner__.disposeExceptionTracker = registerUnexpectedErrors()\n"
  },
  {
    "path": "packages/browser/src/client/public/esm-client-injector.js",
    "content": "(() => {\n  function wrapModule(moduleCallback) {\n    if (typeof moduleCallback !== \"function\") {\n      return moduleCallback\n    }\n\n    if (typeof __vitest_mocker__ === \"undefined\" || typeof __vitest_worker__ === 'undefined') {\n      return moduleCallback()\n    }\n\n    const { evaluatedModules } = __vitest_worker__\n    const moduleId = `${Math.random()}`\n    const viteModule = evaluatedModules.ensureModule(moduleId, moduleId)\n\n    viteModule.evaluated = false\n    viteModule.promise = new Promise((resolve, reject) => {\n      __vitest_mocker__.prepare().finally(() => {\n        moduleCallback().then(resolve, reject)\n      });\n    });\n    return viteModule.promise.finally(() => {\n      viteModule.evaluated = true\n      viteModule.promise = undefined\n\n      evaluatedModules.idToModuleMap.delete(viteModule.id)\n      evaluatedModules.fileToModulesMap.delete(viteModule.file)\n      evaluatedModules.urlToIdModuleMap.delete(viteModule.url)\n    });\n  }\n\n  window.__vitest_browser_runner__ = {\n    wrapModule,\n    wrapDynamicImport: wrapModule,\n    disposeExceptionTracker: () => {},\n    cleanups: [],\n    config: { __VITEST_CONFIG__ },\n    viteConfig: { __VITEST_VITE_CONFIG__ },\n    type: { __VITEST_TYPE__ },\n    sessionId: { __VITEST_SESSION_ID__ },\n    testerId: { __VITEST_TESTER_ID__ },\n    otelCarrier: { __VITEST_OTEL_CARRIER__ },\n    provider: { __VITEST_PROVIDER__ },\n    method: { __VITEST_METHOD__ },\n    providedContext: { __VITEST_PROVIDED_CONTEXT__ },\n  };\n  window.VITEST_API_TOKEN = { __VITEST_API_TOKEN__ };\n\n  const config = __vitest_browser_runner__.config;\n\n  if (config.testNamePattern)\n    config.testNamePattern = parseRegexp(config.testNamePattern);\n\n  function parseRegexp(input) {\n    // Parse input\n    const m = input.match(/(\\/?)(.+)\\1([a-z]*)/i);\n\n    // match nothing\n    if (!m) return /$^/;\n\n    // Invalid flags\n    if (m[3] && !/^(?!.*?(.).*?\\1)[gmixXsuUAJ]+$/.test(m[3]))\n      return RegExp(input);\n\n    // Create the regular expression\n    return new RegExp(m[2], m[3]);\n  }\n})();\n"
  },
  {
    "path": "packages/browser/src/client/tester/context.ts",
    "content": "import type {\n  Options as TestingLibraryOptions,\n  UserEvent as TestingLibraryUserEvent,\n} from '@testing-library/user-event'\nimport type { RunnerTask } from 'vitest'\nimport type {\n  BrowserLocators,\n  BrowserPage,\n  Locator,\n  LocatorSelectors,\n  MarkOptions,\n  UserEvent,\n  UserEventWheelOptions,\n} from 'vitest/browser'\nimport type { StringifyOptions } from 'vitest/internal/browser'\nimport type { IframeViewportEvent } from '../client'\nimport type { BrowserRunnerState } from '../utils'\nimport type { Locator as LocatorAPI } from './locators/index'\nimport { vi } from 'vitest'\nimport { __INTERNAL, stringify } from 'vitest/internal/browser'\nimport { ensureAwaited, getBrowserState, getWorkerState } from '../utils'\nimport { convertToSelector, isLocator, processTimeoutOptions, resolveUserEventWheelOptions } from './tester-utils'\n\n// this file should not import anything directly, only types and utils\n\n// @ts-expect-error not typed global\nconst provider = __vitest_browser_runner__.provider\nconst sessionId = getBrowserState().sessionId\nconst channel = new BroadcastChannel(`vitest:${sessionId}`)\n\nfunction triggerCommand<T>(command: string, args: any[], error?: Error) {\n  return getBrowserState().commands.triggerCommand<T>(command, args, error)\n}\n\nexport function createUserEvent(__tl_user_event_base__?: TestingLibraryUserEvent, options?: TestingLibraryOptions): UserEvent {\n  if (__tl_user_event_base__) {\n    return createPreviewUserEvent(__tl_user_event_base__, options ?? {})\n  }\n\n  const keyboard = {\n    unreleased: [] as string[],\n  }\n\n  // https://playwright.dev/docs/api/class-keyboard\n  // https://webdriver.io/docs/api/browser/keys/\n  const modifier = provider === 'playwright'\n    ? 'ControlOrMeta'\n    : provider === 'webdriverio'\n      ? 'Ctrl'\n      : 'Control'\n\n  const userEvent: UserEvent = {\n    setup() {\n      return createUserEvent()\n    },\n    cleanup() {\n      // avoid cleanup rpc call if there is nothing to cleanup\n      if (!keyboard.unreleased.length) {\n        return Promise.resolve()\n      }\n      return ensureAwaited(async (error) => {\n        await triggerCommand('__vitest_cleanup', [keyboard], error)\n        keyboard.unreleased = []\n      })\n    },\n    click(element, options) {\n      return convertToLocator(element).click(options)\n    },\n    dblClick(element, options) {\n      return convertToLocator(element).dblClick(options)\n    },\n    tripleClick(element, options) {\n      return convertToLocator(element).tripleClick(options)\n    },\n    wheel(elementOrOptions: Element | Locator, options: UserEventWheelOptions) {\n      return convertToLocator(elementOrOptions).wheel(options)\n    },\n    selectOptions(element, value, options) {\n      return convertToLocator(element).selectOptions(value, options)\n    },\n    clear(element, options) {\n      return convertToLocator(element).clear(options)\n    },\n    hover(element, options) {\n      return convertToLocator(element).hover(options)\n    },\n    unhover(element, options) {\n      return convertToLocator(element).unhover(options)\n    },\n    upload(element, files: string | string[] | File | File[], options) {\n      return convertToLocator(element).upload(files, options)\n    },\n\n    // non userEvent events, but still useful\n    fill(element, text, options) {\n      return convertToLocator(element).fill(text, options)\n    },\n    dragAndDrop(source, target, options) {\n      const sourceLocator = convertToLocator(source)\n      const targetLocator = convertToLocator(target)\n      return sourceLocator.dropTo(targetLocator, options)\n    },\n\n    // testing-library user-event\n    type(element, text, options) {\n      return ensureAwaited(async (error) => {\n        const selector = await convertToSelector(element, options)\n        const { unreleased } = await triggerCommand<{ unreleased: string[] }>(\n          '__vitest_type',\n          [\n            selector,\n            text,\n            { ...options, unreleased: keyboard.unreleased },\n          ],\n          error,\n        )\n        keyboard.unreleased = unreleased\n      })\n    },\n    tab(options = {}) {\n      return ensureAwaited(error => triggerCommand('__vitest_tab', [options], error))\n    },\n    keyboard(text) {\n      return ensureAwaited(async (error) => {\n        const { unreleased } = await triggerCommand<{ unreleased: string[] }>(\n          '__vitest_keyboard',\n          [text, keyboard],\n          error,\n        )\n        keyboard.unreleased = unreleased\n      })\n    },\n    copy() {\n      return userEvent.keyboard(`{${modifier}>}{c}{/${modifier}}`)\n    },\n    cut() {\n      return userEvent.keyboard(`{${modifier}>}{x}{/${modifier}}`)\n    },\n    paste() {\n      return userEvent.keyboard(`{${modifier}>}{v}{/${modifier}}`)\n    },\n  }\n  return userEvent\n}\n\nfunction createPreviewUserEvent(userEventBase: TestingLibraryUserEvent, options?: TestingLibraryOptions): UserEvent {\n  let userEvent = userEventBase.setup({\n    advanceTimers: delay => vi.advanceTimersByTimeAsync(delay),\n    ...options,\n  })\n  let clipboardData: DataTransfer | undefined\n\n  function toElement(element: Element | Locator) {\n    return element instanceof Element ? element : element.element()\n  }\n\n  const vitestUserEvent: UserEvent = {\n    setup(options?: any) {\n      return createPreviewUserEvent(userEventBase, options)\n    },\n    async cleanup() {\n      userEvent = userEventBase.setup({\n        advanceTimers: delay => vi.advanceTimersByTimeAsync(delay),\n        ...options,\n      })\n    },\n    async click(element) {\n      await userEvent.click(toElement(element))\n    },\n    async dblClick(element) {\n      await userEvent.dblClick(toElement(element))\n    },\n    async tripleClick(element) {\n      await userEvent.tripleClick(toElement(element))\n    },\n    async selectOptions(element, value) {\n      const options = (Array.isArray(value) ? value : [value]).map((option) => {\n        if (typeof option !== 'string') {\n          return toElement(option)\n        }\n        return option\n      })\n      await userEvent.selectOptions(\n        toElement(element),\n        options as string[] | HTMLElement[],\n      )\n    },\n    async clear(element) {\n      await userEvent.clear(toElement(element))\n    },\n    async hover(element: Element | Locator) {\n      await userEvent.hover(toElement(element))\n    },\n    async unhover(element: Element | Locator) {\n      await userEvent.unhover(toElement(element))\n    },\n    async upload(element, files: string | string[] | File | File[]) {\n      const uploadPromise = (Array.isArray(files) ? files : [files]).map(async (file) => {\n        if (typeof file !== 'string') {\n          return file\n        }\n\n        const { content: base64, basename, mime } = await triggerCommand<{\n          content: string\n          basename: string\n          mime: string\n        }>('__vitest_fileInfo', [file, 'base64'])\n\n        const fileInstance = fetch(`data:${mime};base64,${base64}`)\n          .then(r => r.blob())\n          .then(blob => new File([blob], basename, { type: mime }))\n        return fileInstance\n      })\n      const uploadFiles = await Promise.all(uploadPromise)\n      return userEvent.upload(toElement(element) as HTMLElement, uploadFiles)\n    },\n\n    async fill(element, text) {\n      await userEvent.clear(toElement(element))\n      return userEvent.type(toElement(element), text)\n    },\n    async dragAndDrop() {\n      throw new Error(`The \"preview\" provider doesn't support 'userEvent.dragAndDrop'`)\n    },\n\n    async type(element, text, options) {\n      await userEvent.type(toElement(element), text, options)\n    },\n    async tab(options) {\n      await userEvent.tab(options)\n    },\n    async keyboard(text: string) {\n      await userEvent.keyboard(text)\n    },\n\n    async copy() {\n      clipboardData = await userEvent.copy()\n    },\n    async cut() {\n      clipboardData = await userEvent.cut()\n    },\n    async paste() {\n      await userEvent.paste(clipboardData)\n    },\n    async wheel(element: Element | Locator, options: UserEventWheelOptions) {\n      const resolvedElement = isLocator(element) ? element.element() : element\n      const resolvedOptions = resolveUserEventWheelOptions(options)\n\n      const rect = resolvedElement.getBoundingClientRect()\n\n      const centerX = rect.left + rect.width / 2\n      const centerY = rect.top + rect.height / 2\n\n      const wheelEvent = new WheelEvent('wheel', {\n        clientX: centerX,\n        clientY: centerY,\n        deltaY: resolvedOptions.delta.y ?? 0,\n        deltaX: resolvedOptions.delta.x ?? 0,\n        deltaMode: 0,\n        bubbles: true,\n        cancelable: true,\n      })\n\n      const times = options.times ?? 1\n\n      for (let count = 0; count < times; count += 1) {\n        resolvedElement.dispatchEvent(wheelEvent)\n      }\n    },\n  }\n\n  for (const [name, fn] of Object.entries(vitestUserEvent)) {\n    if (name !== 'setup') {\n      (vitestUserEvent as any)[name] = function (this: any, ...args: any[]) {\n        return ensureAwaited(() => fn.apply(this, args))\n      }\n    }\n  }\n\n  return vitestUserEvent\n}\n\nexport function cdp(): BrowserRunnerState['cdp'] {\n  return getBrowserState().cdp!\n}\n\nconst screenshotIds: Record<string, Record<string, string>> = {}\nexport const page: BrowserPage = {\n  viewport(width, height) {\n    const id = getBrowserState().iframeId!\n    channel.postMessage({\n      event: 'viewport',\n      width,\n      height,\n      iframeId: id,\n    } satisfies IframeViewportEvent)\n    return new Promise((resolve, reject) => {\n      channel.addEventListener('message', function handler(e) {\n        if (e.data.event === 'viewport:done' && e.data.iframeId === id) {\n          channel.removeEventListener('message', handler)\n          resolve()\n        }\n        if (e.data.event === 'viewport:fail' && e.data.iframeId === id) {\n          channel.removeEventListener('message', handler)\n          reject(new Error(e.data.error))\n        }\n      })\n    })\n  },\n  async screenshot(options = {}) {\n    const currentTest = getWorkerState().current\n    if (!currentTest) {\n      throw new Error('Cannot take a screenshot outside of a test.')\n    }\n\n    if (currentTest.concurrent) {\n      throw new Error(\n        'Cannot take a screenshot in a concurrent test because '\n        + 'concurrent tests run at the same time in the same iframe and affect each other\\'s environment. '\n        + 'Use a non-concurrent test to take a screenshot.',\n      )\n    }\n\n    const repeatCount = currentTest.result?.repeatCount ?? 0\n    const taskName = getTaskFullName(currentTest)\n    const number = screenshotIds[repeatCount]?.[taskName] ?? 1\n\n    screenshotIds[repeatCount] ??= {}\n    screenshotIds[repeatCount][taskName] = number + 1\n\n    const name\n      = options.path || `${taskName.replace(/[^a-z0-9]/gi, '-')}-${number}.png`\n\n    const [element, ...mask] = await Promise.all([\n      options.element ? convertToSelector(options.element, options) : undefined,\n      ...('mask' in options\n        ? (options.mask as Array<Element | Locator>).map(el => convertToSelector(el, options))\n        : []),\n    ])\n\n    const normalizedOptions = 'mask' in options\n      ? { ...options, mask }\n      : options\n\n    return ensureAwaited(error => triggerCommand(\n      '__vitest_screenshot',\n      [\n        name,\n        processTimeoutOptions({\n          ...normalizedOptions,\n          element,\n        } as any /** TODO */),\n      ],\n      error,\n    ))\n  },\n  mark<T>(\n    name: string,\n    bodyOrOptions?: MarkOptions | (() => T | Promise<T>),\n    options?: MarkOptions,\n  ): any {\n    const currentTest = getWorkerState().current\n    const hasActiveTrace = !!currentTest && getBrowserState().activeTraceTaskIds.has(currentTest.id)\n\n    if (typeof bodyOrOptions === 'function') {\n      return ensureAwaited(async (error) => {\n        if (hasActiveTrace) {\n          await triggerCommand(\n            '__vitest_groupTraceStart',\n            [{\n              name,\n              stack: options?.stack ?? error?.stack,\n            }],\n            error,\n          )\n        }\n        try {\n          return await bodyOrOptions()\n        }\n        finally {\n          if (hasActiveTrace) {\n            await triggerCommand('__vitest_groupTraceEnd', [], error)\n          }\n        }\n      })\n    }\n\n    if (!hasActiveTrace) {\n      return Promise.resolve()\n    }\n\n    return ensureAwaited(error => triggerCommand(\n      '__vitest_markTrace',\n      [{\n        name,\n        stack: bodyOrOptions?.stack ?? error?.stack,\n      }],\n      error,\n    ))\n  },\n  getByRole() {\n    throw new Error(`Method \"getByRole\" is not supported by the \"${provider}\" provider.`)\n  },\n  getByLabelText() {\n    throw new Error(`Method \"getByLabelText\" is not supported by the \"${provider}\" provider.`)\n  },\n  getByTestId() {\n    throw new Error(`Method \"getByTestId\" is not supported by the \"${provider}\" provider.`)\n  },\n  getByAltText() {\n    throw new Error(`Method \"getByAltText\" is not supported by the \"${provider}\" provider.`)\n  },\n  getByPlaceholder() {\n    throw new Error(`Method \"getByPlaceholder\" is not supported by the \"${provider}\" provider.`)\n  },\n  getByText() {\n    throw new Error(`Method \"getByText\" is not supported by the \"${provider}\" provider.`)\n  },\n  getByTitle() {\n    throw new Error(`Method \"getByTitle\" is not supported by the \"${provider}\" provider.`)\n  },\n  elementLocator() {\n    throw new Error(`Method \"elementLocator\" is not supported by the \"${provider}\" provider.`)\n  },\n  frameLocator() {\n    throw new Error(`Method \"frameLocator\" is not supported by the \"${provider}\" provider.`)\n  },\n  extend(methods) {\n    for (const key in methods) {\n      (page as any)[key] = (methods as any)[key].bind(page)\n    }\n    return page\n  },\n}\n\nfunction convertToLocator(element: Element | Locator): Locator {\n  if (element instanceof Element) {\n    return page.elementLocator(element)\n  }\n  return element\n}\n\nfunction getTaskFullName(task: RunnerTask): string {\n  return task.suite ? `${getTaskFullName(task.suite)} ${task.name}` : task.name\n}\n\nexport const locators: BrowserLocators = {\n  createElementLocators: getElementLocatorSelectors,\n  extend(methods) {\n    const Locator = __INTERNAL._createLocator('css=body').constructor as typeof LocatorAPI\n    for (const method in methods) {\n      __INTERNAL._extendedMethods.add(method)\n      const cb = (methods as any)[method] as (...args: any[]) => string | Locator\n      // @ts-expect-error types are hard to make work\n      Locator.prototype[method] = function (...args: any[]) {\n        const selectorOrLocator = cb.call(this, ...args)\n        if (typeof selectorOrLocator === 'string') {\n          return this.locator(selectorOrLocator)\n        }\n        return selectorOrLocator\n      }\n      page[method as 'getByRole'] = function (...args: any[]) {\n        const selectorOrLocator = cb.call(this, ...args)\n        if (typeof selectorOrLocator === 'string') {\n          return __INTERNAL._createLocator(selectorOrLocator)\n        }\n        return selectorOrLocator\n      }\n    }\n  },\n}\n\nfunction getElementLocatorSelectors(element: Element): LocatorSelectors {\n  const locator = page.elementLocator(element)\n  return {\n    getByAltText: (altText, options) => locator.getByAltText(altText, options),\n    getByLabelText: (labelText, options) => locator.getByLabelText(labelText, options),\n    getByPlaceholder: (placeholderText, options) => locator.getByPlaceholder(placeholderText, options),\n    getByRole: (role, options) => locator.getByRole(role, options),\n    getByTestId: testId => locator.getByTestId(testId),\n    getByText: (text, options) => locator.getByText(text, options),\n    getByTitle: (title, options) => locator.getByTitle(title, options),\n    ...Array.from(__INTERNAL._extendedMethods).reduce((methods, method) => {\n      methods[method] = (...args: any[]) => (locator as any)[method](...args)\n      return methods\n    }, {} as any),\n  }\n}\n\ntype PrettyDOMOptions = Omit<StringifyOptions, 'maxLength'>\n\nlet defaultOptions: StringifyOptions | undefined\n\nfunction debug(\n  el?: Element | Locator | null | (Element | Locator)[],\n  maxLength?: number,\n  options?: PrettyDOMOptions,\n): void {\n  if (Array.isArray(el)) {\n    // eslint-disable-next-line no-console\n    el.forEach(e => console.log(prettyDOM(e, maxLength, options)))\n  }\n  else {\n    // eslint-disable-next-line no-console\n    console.log(prettyDOM(el, maxLength, options))\n  }\n}\n\nfunction prettyDOM(\n  dom?: Element | Locator | undefined | null,\n  maxLength: number = Number(defaultOptions?.maxLength ?? import.meta.env.DEBUG_PRINT_LIMIT ?? 7000),\n  prettyFormatOptions: PrettyDOMOptions = {},\n): string {\n  if (maxLength === 0) {\n    return ''\n  }\n\n  if (!dom) {\n    dom = document.body\n  }\n\n  if ('element' in dom && 'all' in dom) {\n    dom = dom.element()\n  }\n\n  const type = typeof dom\n  if (type !== 'object' || !dom.outerHTML) {\n    const typeName = type === 'object' ? dom.constructor.name : type\n    throw new TypeError(`Expecting a valid DOM element, but got ${typeName}.`)\n  }\n\n  const pretty = stringify(dom, Number.POSITIVE_INFINITY, {\n    maxLength,\n    highlight: true,\n    ...defaultOptions,\n    ...prettyFormatOptions,\n  })\n  return dom.outerHTML.length > maxLength\n    ? `${pretty.slice(0, maxLength)}...`\n    : pretty\n}\n\nfunction getElementError(selector: string, container: Element): Error {\n  const error = new Error(`Cannot find element with locator: ${__INTERNAL._asLocator('javascript', selector)}\\n\\n${prettyDOM(container)}`)\n  error.name = 'VitestBrowserElementError'\n  return error\n}\n\nfunction configurePrettyDOM(options: StringifyOptions) {\n  defaultOptions = options\n}\n\nexport const utils = {\n  getElementError,\n  prettyDOM,\n  debug,\n  getElementLocatorSelectors,\n  configurePrettyDOM,\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/dialog.ts",
    "content": "function showPopupWarning<T>(name: string, value: T, defaultValue?: T) {\n  return (...params: any[]) => {\n    const formattedParams = params.map(p => JSON.stringify(p)).join(', ')\n\n    console.warn(`Vitest encountered a \\`${name}(${formattedParams})\\` call that it cannot handle by default, so it returned \\`${value}\\`. Read more in https://vitest.dev/guide/browser/#thread-blocking-dialogs.\nIf needed, mock the \\`${name}\\` call manually like:\n\n\\`\\`\\`\nimport { expect, vi } from \"vitest\"\n\nvi.spyOn(window, \"${name}\")${\n  defaultValue ? `.mockReturnValue(${JSON.stringify(defaultValue)})` : ''\n}\n${name}(${formattedParams})\nexpect(${name}).toHaveBeenCalledWith(${formattedParams})\n\\`\\`\\``)\n    return value\n  }\n}\n\nexport function setupDialogsSpy(): void {\n  globalThis.alert = showPopupWarning('alert', undefined)\n  globalThis.confirm = showPopupWarning('confirm', false, true)\n  globalThis.prompt = showPopupWarning('prompt', null, 'your value')\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/index.ts",
    "content": "import type { MatchersObject } from '@vitest/expect'\nimport toBeChecked from './toBeChecked'\nimport toBeEmptyDOMElement from './toBeEmptyDOMElement'\nimport { toBeDisabled, toBeEnabled } from './toBeEnabled'\nimport toBeInTheDocument from './toBeInTheDocument'\nimport { toBeInvalid, toBeValid } from './toBeInvalid'\nimport toBeInViewport from './toBeInViewport'\nimport toBePartiallyChecked from './toBePartiallyChecked'\nimport toBeRequired from './toBeRequired'\nimport toBeVisible from './toBeVisible'\nimport toContainElement from './toContainElement'\nimport toContainHTML from './toContainHTML'\nimport toHaveAccessibleDescription from './toHaveAccessibleDescription'\nimport toHaveAccessibleErrorMessage from './toHaveAccessibleErrorMessage'\nimport toHaveAccessibleName from './toHaveAccessibleName'\nimport toHaveAttribute from './toHaveAttribute'\nimport toHaveClass from './toHaveClass'\nimport toHaveDisplayValue from './toHaveDisplayValue'\nimport toHaveFocus from './toHaveFocus'\nimport toHaveFormValues from './toHaveFormValues'\nimport toHaveRole from './toHaveRole'\nimport toHaveSelection from './toHaveSelection'\nimport toHaveStyle from './toHaveStyle'\nimport toHaveTextContent from './toHaveTextContent'\nimport toHaveValue from './toHaveValue'\nimport toMatchScreenshot from './toMatchScreenshot'\n\nexport const matchers: MatchersObject = {\n  toBeDisabled,\n  toBeEnabled,\n  toBeEmptyDOMElement,\n  toBeInTheDocument,\n  toBeInViewport,\n  toBeInvalid,\n  toBeRequired,\n  toBeValid,\n  toBeVisible,\n  toContainElement,\n  toContainHTML,\n  toHaveAccessibleDescription,\n  toHaveAccessibleErrorMessage,\n  toHaveAccessibleName,\n  toHaveAttribute,\n  toHaveClass,\n  toHaveFocus,\n  toHaveFormValues,\n  toHaveStyle,\n  toHaveTextContent,\n  toHaveValue,\n  toHaveDisplayValue,\n  toBeChecked,\n  toBePartiallyChecked,\n  toHaveRole,\n  toHaveSelection,\n  toMatchScreenshot,\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toBeChecked.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getAriaChecked, getAriaCheckedRoles, getAriaRole } from 'ivya/utils'\nimport { getElementFromUserInput, isInputElement, toSentence } from './utils'\n\nconst supportedRoles = getAriaCheckedRoles()\n\nexport default function toBeChecked(\n  this: MatcherState,\n  actual: Element | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toBeChecked, this)\n\n  const isValidInput = () => {\n    return (\n      isInputElement(htmlElement)\n      && ['checkbox', 'radio'].includes(htmlElement.type)\n    )\n  }\n\n  const isValidAriaElement = () => {\n    return (\n      supportedRoles.includes(getAriaRole(htmlElement) || '')\n      && ['true', 'false'].includes(htmlElement.getAttribute('aria-checked') || '')\n    )\n  }\n\n  if (!isValidInput() && !isValidAriaElement()) {\n    return {\n      pass: false,\n      message: () =>\n        `only inputs with type=\"checkbox\" or type=\"radio\" or elements with ${supportedRolesSentence()} and a valid aria-checked attribute can be used with .toBeChecked(). Use .toHaveValue() instead`,\n    }\n  }\n\n  const checkedValue = getAriaChecked(htmlElement)\n  const isChecked = checkedValue === true // don't tolerate \"mixed\", see toBePartiallyChecked\n\n  return {\n    pass: isChecked,\n    message: () => {\n      const is = isChecked ? 'is' : 'is not'\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBeChecked`,\n          'element',\n          '',\n        ),\n        '',\n        `Received element ${is} checked:`,\n        `  ${this.utils.printReceived(htmlElement.cloneNode(false))}`,\n      ].join('\\n')\n    },\n  }\n}\n\nfunction supportedRolesSentence() {\n  return toSentence(\n    supportedRoles.map(role => `role=\"${role}\"`),\n    { lastWordConnector: ' or ' },\n  )\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toBeEmptyDOMElement.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput } from './utils'\n\nexport default function toBeEmptyDOMElement(\n  this: MatcherState,\n  actual: Element | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toBeEmptyDOMElement, this)\n\n  return {\n    pass: isEmptyElement(htmlElement),\n    message: () => {\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBeEmptyDOMElement`,\n          'element',\n          '',\n        ),\n        '',\n        'Received:',\n        `  ${this.utils.printReceived(htmlElement.innerHTML)}`,\n      ].join('\\n')\n    },\n  }\n}\n\n/**\n * Identifies if an element doesn't contain child nodes (excluding comments)\n */\nfunction isEmptyElement(element: HTMLElement | SVGElement): boolean {\n  const nonCommentChildNodes = [...element.childNodes].filter(node => node.nodeType !== Node.COMMENT_NODE)\n  return nonCommentChildNodes.length === 0\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toBeEnabled.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getAriaDisabled } from 'ivya/utils'\nimport { getElementFromUserInput, getTag } from './utils'\n\nexport function toBeDisabled(\n  this: MatcherState,\n  actual: Element | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toBeDisabled, this)\n  const isDisabled = isElementDisabled(htmlElement)\n  return {\n    pass: isDisabled,\n    message: () => {\n      const is = isDisabled ? 'is' : 'is not'\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBeDisabled`,\n          'element',\n          '',\n        ),\n        '',\n        `Received element ${is} disabled:`,\n        `  ${this.utils.printReceived(htmlElement.cloneNode(false))}`,\n      ].join('\\n')\n    },\n  }\n}\n\nexport function toBeEnabled(\n  this: MatcherState,\n  actual: Element | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toBeEnabled, this)\n  const isDisabled = isElementDisabled(htmlElement)\n  return {\n    pass: !isDisabled,\n    message: () => {\n      const is = !isDisabled ? 'is' : 'is not'\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBeEnabled`,\n          'element',\n          '',\n        ),\n        '',\n        `Received element ${is} enabled:`,\n        `  ${this.utils.printReceived(htmlElement.cloneNode(false))}`,\n      ].join('\\n')\n    },\n  }\n}\n\nfunction isElementDisabled(element: HTMLElement | SVGElement) {\n  // ivya doesn't support custom elements check\n  if (getTag(element).includes('-')) {\n    return element.hasAttribute('disabled')\n  }\n  return getAriaDisabled(element)\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toBeInTheDocument.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { queryElementFromUserInput } from './utils'\n\nexport default function toBeInTheDocument(\n  this: MatcherState,\n  actual: Element | Locator | null,\n): ExpectationResult {\n  let htmlElement: null | HTMLElement | SVGElement = null\n\n  if (actual !== null || !this.isNot) {\n    htmlElement = queryElementFromUserInput(actual, toBeInTheDocument, this)\n  }\n\n  const pass\n    = htmlElement === null\n      ? false\n      : htmlElement.ownerDocument === htmlElement.getRootNode({ composed: true })\n\n  const errorFound = () => {\n    return `expected document not to contain element, found ${this.utils.stringify(\n      htmlElement?.cloneNode(true),\n    )} instead`\n  }\n  const errorNotFound = () => {\n    return `element could not be found in the document`\n  }\n\n  return {\n    pass,\n    message: () => {\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBeInTheDocument`,\n          'element',\n          '',\n        ),\n        '',\n\n        this.utils.RECEIVED_COLOR(this.isNot ? errorFound() : errorNotFound()),\n      ].join('\\n')\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toBeInViewport.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput } from './utils'\n\nexport default function toBeInViewport(\n  this: MatcherState,\n  actual: Element | Locator,\n  options?: { ratio?: number },\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toBeInViewport, this)\n\n  const expectedRatio = options?.ratio ?? 0\n  return getViewportIntersection(htmlElement, expectedRatio).then(({ pass, ratio }) => {\n    return {\n      pass,\n      message: () => {\n        const is = pass ? 'is' : 'is not'\n        const ratioText = expectedRatio > 0 ? ` with ratio ${expectedRatio}` : ''\n        const actualRatioText = ratio !== undefined ? ` (actual ratio: ${ratio.toFixed(3)})` : ''\n        return [\n          this.utils.matcherHint(\n            `${this.isNot ? '.not' : ''}.toBeInViewport`,\n            'element',\n            '',\n          ),\n          '',\n          `Received element ${is} in viewport${ratioText}${actualRatioText}:`,\n          `  ${this.utils.printReceived(htmlElement.cloneNode(false))}`,\n        ].join('\\n')\n      },\n    }\n  })\n}\n\n/**\n * Get viewport intersection ratio using IntersectionObserver API\n * This implementation follows Playwright's approach using IntersectionObserver as the primary mechanism\n */\nasync function getViewportIntersection(element: HTMLElement | SVGElement, expectedRatio: number): Promise<{ pass: boolean; ratio?: number }> {\n  // Use IntersectionObserver API to get the intersection ratio\n  // Following Playwright's exact pattern from viewportRatio function\n  const intersectionRatio = await new Promise<number>((resolve) => {\n    // This mimics Playwright's Promise-based implementation in a synchronous context\n    const observer = new IntersectionObserver((entries) => {\n      if (entries.length > 0) {\n        resolve(entries[0].intersectionRatio)\n      }\n      else {\n        resolve(0)\n      }\n      observer.disconnect()\n    })\n\n    observer.observe(element)\n\n    // Firefox workaround: requestAnimationFrame to ensure observer callback fires\n    // This is exactly how Playwright handles it\n    requestAnimationFrame(() => {})\n  })\n\n  // Apply the same logic as Playwright:\n  // ratio > 0 && ratio > (expectedRatio - 1e-9)\n  const pass = intersectionRatio > 0 && intersectionRatio > (expectedRatio - 1e-9)\n\n  return { pass, ratio: intersectionRatio }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toBeInvalid.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput, getTag } from './utils'\n\nconst FORM_TAGS = ['FORM', 'INPUT', 'SELECT', 'TEXTAREA']\n\nfunction isElementHavingAriaInvalid(element: HTMLElement | SVGElement) {\n  return (\n    element.hasAttribute('aria-invalid')\n    && element.getAttribute('aria-invalid') !== 'false'\n  )\n}\n\nfunction isSupportsValidityMethod(element: HTMLElement | SVGElement): element is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLFormElement {\n  return FORM_TAGS.includes(getTag(element))\n}\n\nfunction isElementInvalid(element: HTMLElement | SVGElement) {\n  const isHaveAriaInvalid = isElementHavingAriaInvalid(element)\n  if (isSupportsValidityMethod(element)) {\n    return isHaveAriaInvalid || !element.checkValidity()\n  }\n  else {\n    return isHaveAriaInvalid\n  }\n}\n\nexport function toBeInvalid(\n  this: MatcherState,\n  element: HTMLElement | SVGElement | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(element, toBeInvalid, this)\n\n  const isInvalid = isElementInvalid(htmlElement)\n\n  return {\n    pass: isInvalid,\n    message: () => {\n      const is = isInvalid ? 'is' : 'is not'\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBeInvalid`,\n          'element',\n          '',\n        ),\n        '',\n        `Received element ${is} currently invalid:`,\n        `  ${this.utils.printReceived(htmlElement.cloneNode(false))}`,\n      ].join('\\n')\n    },\n  }\n}\n\nexport function toBeValid(\n  this: MatcherState,\n  element: HTMLElement | SVGElement | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(element, toBeInvalid, this)\n\n  const isValid = !isElementInvalid(htmlElement)\n\n  return {\n    pass: isValid,\n    message: () => {\n      const is = isValid ? 'is' : 'is not'\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBeValid`,\n          'element',\n          '',\n        ),\n        '',\n        `Received element ${is} currently valid:`,\n        `  ${this.utils.printReceived(htmlElement.cloneNode(false))}`,\n      ].join('\\n')\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toBePartiallyChecked.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getAriaChecked as ivyaGetAriaChecked } from 'ivya/utils'\nimport { getElementFromUserInput, isInputElement } from './utils'\n\nexport default function toBePartiallyChecked(\n  this: MatcherState,\n  actual: Element | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toBePartiallyChecked, this)\n\n  const isValidInput = () => {\n    return (\n      isInputElement(htmlElement) && htmlElement.type === 'checkbox'\n    )\n  }\n\n  const isValidAriaElement = () => {\n    return htmlElement.getAttribute('role') === 'checkbox'\n  }\n\n  if (!isValidInput() && !isValidAriaElement()) {\n    return {\n      pass: false,\n      message: () =>\n        'only inputs with type=\"checkbox\" or elements with role=\"checkbox\" and a valid aria-checked attribute can be used with .toBePartiallyChecked(). Use .toHaveValue() instead',\n    }\n  }\n\n  const isPartiallyChecked = isAriaMixed(htmlElement)\n\n  return {\n    pass: isPartiallyChecked,\n    message: () => {\n      const is = isPartiallyChecked ? 'is' : 'is not'\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBePartiallyChecked`,\n          'element',\n          '',\n        ),\n        '',\n        `Received element ${is} partially checked:`,\n        `  ${this.utils.printReceived(htmlElement.cloneNode(false))}`,\n      ].join('\\n')\n    },\n  }\n}\n\nfunction isAriaMixed(element: HTMLElement | SVGElement): boolean {\n  const isMixed = ivyaGetAriaChecked(element) === 'mixed'\n  if (!isMixed) {\n    // playwright only looks at aria-checked if element is not a checkbox/radio\n    if (\n      isInputElement(element)\n      && ['checkbox', 'radio'].includes((element as HTMLInputElement).type)\n    ) {\n      const ariaValue = element.getAttribute('aria-checked')\n      if (ariaValue === 'mixed') {\n        return true\n      }\n    }\n  }\n  return isMixed\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toBeRequired.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput, getTag } from './utils'\n\n// form elements that support 'required'\nconst FORM_TAGS = ['SELECT', 'TEXTAREA']\n\nconst ARIA_FORM_TAGS = ['INPUT', 'SELECT', 'TEXTAREA']\n\nconst UNSUPPORTED_INPUT_TYPES = [\n  'color',\n  'hidden',\n  'range',\n  'submit',\n  'image',\n  'reset',\n]\n\nconst SUPPORTED_ARIA_ROLES = [\n  'checkbox',\n  'combobox',\n  'gridcell',\n  'listbox',\n  'radiogroup',\n  'spinbutton',\n  'textbox',\n  'tree',\n]\n\nfunction isRequiredOnFormTagsExceptInput(element: HTMLElement | SVGElement) {\n  return FORM_TAGS.includes(getTag(element)) && element.hasAttribute('required')\n}\n\nfunction isRequiredOnSupportedInput(element: HTMLElement | SVGElement) {\n  return (\n    getTag(element) === 'INPUT'\n    && element.hasAttribute('required')\n    && ((element.hasAttribute('type')\n      && !UNSUPPORTED_INPUT_TYPES.includes(element.getAttribute('type') || ''))\n    || !element.hasAttribute('type'))\n  )\n}\n\nfunction isElementRequiredByARIA(element: HTMLElement | SVGElement) {\n  return (\n    element.hasAttribute('aria-required')\n    && element.getAttribute('aria-required') === 'true'\n    && (ARIA_FORM_TAGS.includes(getTag(element))\n      || (element.hasAttribute('role')\n        && SUPPORTED_ARIA_ROLES.includes(element.getAttribute('role') || '')))\n  )\n}\n\nexport default function toBeRequired(\n  this: MatcherState,\n  element: HTMLElement | SVGElement | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(element, toBeRequired, this)\n\n  const isRequired\n    = isRequiredOnFormTagsExceptInput(htmlElement)\n      || isRequiredOnSupportedInput(htmlElement)\n      || isElementRequiredByARIA(htmlElement)\n\n  return {\n    pass: isRequired,\n    message: () => {\n      const is = isRequired ? 'is' : 'is not'\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBeRequired`,\n          'element',\n          '',\n        ),\n        '',\n        `Received element ${is} required:`,\n        `  ${this.utils.printReceived(htmlElement.cloneNode(false))}`,\n      ].join('\\n')\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toBeVisible.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { beginAriaCaches, endAriaCaches, isElementVisible as ivyaIsVisible } from 'ivya/utils'\nimport { server } from 'vitest/browser'\nimport { getElementFromUserInput } from './utils'\n\nexport default function toBeVisible(\n  this: MatcherState,\n  actual: Element | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toBeVisible, this)\n  const isInDocument\n    = htmlElement.ownerDocument === htmlElement.getRootNode({ composed: true })\n  beginAriaCaches()\n  const isVisible = isInDocument && isElementVisible(htmlElement)\n  endAriaCaches()\n  return {\n    pass: isVisible,\n    message: () => {\n      const is = isVisible ? 'is' : 'is not'\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toBeVisible`,\n          'element',\n          '',\n        ),\n        '',\n        `Received element ${is} visible${\n          isInDocument ? '' : ' (element is not in the document)'\n        }:`,\n        `  ${this.utils.printReceived(htmlElement.cloneNode(false))}`,\n      ].join('\\n')\n    },\n  }\n}\n\nfunction isElementVisible(element: HTMLElement | SVGElement): boolean {\n  const isIvyaVisible = ivyaIsVisible(element)\n  // if it's visible or not, but we are not in webkit, respect the result\n  if (server.browser !== 'webkit') {\n    return isIvyaVisible\n  }\n  // if we are in webkit and it's not visible, fallback to jest-dom check\n  // because ivya doesn't use .checkVisibility here\n  const detailsElement = element.closest('details')\n  if (!detailsElement || element === detailsElement) {\n    return isIvyaVisible\n  }\n  return isElementVisibleInDetails(element as HTMLElement)\n}\n\nfunction isElementVisibleInDetails(targetElement: HTMLElement) {\n  let currentElement: HTMLElement | null = targetElement\n\n  while (currentElement) {\n    if (currentElement.tagName === 'DETAILS') {\n      const isSummary = currentElement.querySelector('summary') === targetElement\n      if (!(currentElement as HTMLDetailsElement).open && !isSummary) {\n        return false\n      }\n    }\n    currentElement = currentElement.parentElement\n  }\n\n  return targetElement.offsetParent !== null\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toContainElement.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput } from './utils'\n\nexport default function toContainElement(\n  this: MatcherState,\n  actual: Element | Locator,\n  expectedElement: Element | Locator | null,\n): ExpectationResult {\n  const containerElement = getElementFromUserInput(actual, toContainElement, this)\n  const childElement = expectedElement !== null\n    ? getElementFromUserInput(expectedElement, toContainElement, this)\n    : null\n\n  return {\n    pass: containerElement.contains(childElement),\n    message: () => {\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toContainElement`,\n          'element',\n          'element',\n        ),\n        '',\n\n        this.utils.RECEIVED_COLOR(`${this.utils.stringify(\n          containerElement.cloneNode(false),\n        )} ${\n          this.isNot ? 'contains:' : 'does not contain:'\n        } ${this.utils.stringify(childElement ? childElement.cloneNode(false) : null)}\n        `),\n      ].join('\\n')\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toContainHTML.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput } from './utils'\n\nfunction getNormalizedHtml(container: HTMLElement | SVGElement, htmlText: string) {\n  const div = container.ownerDocument.createElement('div')\n  div.innerHTML = htmlText\n  return div.innerHTML\n}\n\nexport default function toContainHTML(\n  this: MatcherState,\n  actual: Element | Locator,\n  htmlText: string,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toContainHTML, this)\n\n  if (typeof htmlText !== 'string') {\n    throw new TypeError(`.toContainHTML() expects a string value, got ${htmlText}`)\n  }\n\n  return {\n    pass: htmlElement.outerHTML.includes(getNormalizedHtml(htmlElement, htmlText)),\n    message: () => {\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toContainHTML`,\n          'element',\n          '',\n        ),\n        'Expected:',\n        `  ${this.utils.EXPECTED_COLOR(htmlText)}`,\n        'Received:',\n        `  ${this.utils.printReceived(htmlElement.cloneNode(true))}`,\n      ].join('\\n')\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveAccessibleDescription.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementAccessibleDescription } from 'ivya/utils'\nimport { getElementFromUserInput, getMessage } from './utils'\n\nexport default function toHaveAccessibleDescription(\n  this: MatcherState,\n  actual: Element | Locator,\n  expectedAccessibleDescription?: string | RegExp,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveAccessibleDescription, this)\n  const actualAccessibleDescription = getElementAccessibleDescription(htmlElement, false)\n  const defaultView = htmlElement.ownerDocument.defaultView || window\n\n  const missingExpectedValue = arguments.length === 1\n\n  let pass = false\n  if (missingExpectedValue) {\n    // When called without an expected value we only want to validate that the element has an\n    // accessible description, whatever it may be.\n    pass = actualAccessibleDescription !== ''\n  }\n  else {\n    pass\n      = expectedAccessibleDescription instanceof defaultView.RegExp\n        ? expectedAccessibleDescription.test(actualAccessibleDescription)\n        : this.equals(\n            actualAccessibleDescription,\n            expectedAccessibleDescription,\n            this.customTesters,\n          )\n  }\n\n  return {\n    pass,\n\n    message: () => {\n      const to = this.isNot ? 'not to' : 'to'\n      return getMessage(\n        this,\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toHaveAccessibleDescription`,\n          'element',\n          '',\n        ),\n        `Expected element ${to} have accessible description`,\n        expectedAccessibleDescription,\n        'Received',\n        actualAccessibleDescription,\n      )\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveAccessibleErrorMessage.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementAccessibleErrorMessage } from 'ivya/utils'\nimport { getElementFromUserInput, getMessage, redent } from './utils'\n\nexport default function toHaveAccessibleErrorMessage(\n  this: MatcherState,\n  actual: Element | Locator,\n  expectedAccessibleErrorMessage?: string | RegExp,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveAccessibleErrorMessage, this)\n  const actualAccessibleErrorMessage = getElementAccessibleErrorMessage(htmlElement) ?? ''\n  const defaultView = htmlElement.ownerDocument.defaultView || window\n\n  const missingExpectedValue = arguments.length === 1\n\n  let pass = false\n  if (missingExpectedValue) {\n    // When called without an expected value we only want to validate that the element has an\n    // accessible description, whatever it may be.\n    pass = actualAccessibleErrorMessage !== ''\n  }\n  else {\n    pass\n      = expectedAccessibleErrorMessage instanceof defaultView.RegExp\n        ? expectedAccessibleErrorMessage.test(actualAccessibleErrorMessage)\n        : this.equals(\n            actualAccessibleErrorMessage,\n            expectedAccessibleErrorMessage,\n            this.customTesters,\n          )\n  }\n\n  return {\n    pass,\n\n    message: () => {\n      const to = this.isNot ? 'not to' : 'to'\n      if (expectedAccessibleErrorMessage == null) {\n        return [\n          this.utils.matcherHint(\n            `${this.isNot ? '.not' : ''}.toHaveAccessibleErrorMessage`,\n            'element',\n            '',\n          ),\n          `Expected element ${to} have accessible error message, but got${!this.isNot ? ' nothing' : ''}`,\n          this.isNot ? this.utils.RECEIVED_COLOR(redent(actualAccessibleErrorMessage, 2)) : '',\n        ].filter(Boolean).join('\\n\\n')\n      }\n      return getMessage(\n        this,\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toHaveAccessibleErrorMessage`,\n          'element',\n          '',\n        ),\n        `Expected element ${to} have accessible error message`,\n        expectedAccessibleErrorMessage,\n        'Received',\n        actualAccessibleErrorMessage,\n      )\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveAccessibleName.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementAccessibleName } from 'ivya/utils'\nimport { getElementFromUserInput, getMessage } from './utils'\n\nexport default function toHaveAccessibleName(\n  this: MatcherState,\n  actual: Element | Locator,\n  expectedAccessibleName?: string | RegExp,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveAccessibleName, this)\n  const actualAccessibleName = getElementAccessibleName(htmlElement, false)\n  const missingExpectedValue = arguments.length === 1\n  const defaultView = htmlElement.ownerDocument.defaultView || window\n\n  let pass = false\n  if (missingExpectedValue) {\n    // When called without an expected value we only want to validate that the element has an\n    // accessible name, whatever it may be.\n    pass = actualAccessibleName !== ''\n  }\n  else {\n    pass\n      = expectedAccessibleName instanceof defaultView.RegExp\n        ? expectedAccessibleName.test(actualAccessibleName)\n        : this.equals(actualAccessibleName, expectedAccessibleName, this.customTesters)\n  }\n\n  return {\n    pass,\n\n    message: () => {\n      const to = this.isNot ? 'not to' : 'to'\n      return getMessage(\n        this,\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.${toHaveAccessibleName.name}`,\n          'element',\n          '',\n        ),\n        `Expected element ${to} have accessible name`,\n        expectedAccessibleName,\n        'Received',\n        actualAccessibleName,\n      )\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveAttribute.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput, getMessage } from './utils'\n\nexport default function toHaveAttribute(\n  this: MatcherState,\n  actual: Element | Locator,\n  attribute: string,\n  expectedValue?: string,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveAttribute, this)\n  const isExpectedValuePresent = expectedValue !== undefined\n  const hasAttribute = htmlElement.hasAttribute(attribute)\n  const receivedValue = htmlElement.getAttribute(attribute)\n  return {\n    pass: isExpectedValuePresent\n      ? hasAttribute && this.equals(receivedValue, expectedValue, this.customTesters)\n      : hasAttribute,\n    message: () => {\n      const to = this.isNot ? 'not to' : 'to'\n      const receivedAttribute = hasAttribute\n        ? printAttribute(this.utils.stringify, attribute, receivedValue)\n        : null\n      const matcher = this.utils.matcherHint(\n        `${this.isNot ? '.not' : ''}.toHaveAttribute`,\n        'element',\n        this.utils.printExpected(attribute),\n        {\n          secondArgument: isExpectedValuePresent\n            ? this.utils.printExpected(expectedValue)\n            : undefined,\n          comment: getAttributeComment(\n            this.utils.stringify,\n            attribute,\n            expectedValue,\n          ),\n        },\n      )\n      return getMessage(\n        this,\n        matcher,\n        `Expected the element ${to} have attribute`,\n        printAttribute(this.utils.stringify, attribute, expectedValue),\n        'Received',\n        receivedAttribute,\n      )\n    },\n  }\n}\n\nfunction printAttribute(stringify: (obj: unknown) => string, name: string, value: unknown) {\n  return value === undefined ? name : `${name}=${stringify(value)}`\n}\n\nfunction getAttributeComment(stringify: (obj: unknown) => string, name: string, value: unknown) {\n  return value === undefined\n    ? `element.hasAttribute(${stringify(name)})`\n    : `element.getAttribute(${stringify(name)}) === ${stringify(value)}`\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveClass.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput, getMessage } from './utils'\n\nexport default function toHaveClass(\n  this: MatcherState,\n  actual: Element | Locator,\n  ...params: (string | RegExp)[] | [string, options?: { exact: boolean }]\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveClass, this)\n  const { expectedClassNames, options } = getExpectedClassNamesAndOptions(params)\n\n  const received = splitClassNames(htmlElement.getAttribute('class'))\n  const expected = expectedClassNames.reduce(\n    (acc, className) => {\n      return acc.concat(\n        typeof className === 'string' || !className\n          ? splitClassNames(className)\n          : className,\n      )\n    },\n    [] as (string | RegExp)[],\n  )\n\n  const hasRegExp = expected.some(className => className instanceof RegExp)\n  if (options.exact && hasRegExp) {\n    throw new Error('Exact option does not support RegExp expected class names')\n  }\n\n  if (options.exact) {\n    return {\n      pass: isSubset(expected, received) && expected.length === received.length,\n      message: () => {\n        const to = this.isNot ? 'not to' : 'to'\n        return getMessage(\n          this,\n          this.utils.matcherHint(\n            `${this.isNot ? '.not' : ''}.toHaveClass`,\n            'element',\n            this.utils.printExpected(expected.join(' ')),\n          ),\n          `Expected the element ${to} have EXACTLY defined classes`,\n          expected.join(' '),\n          'Received',\n          received.join(' '),\n        )\n      },\n    }\n  }\n\n  return expected.length > 0\n    ? {\n        pass: isSubset(expected, received),\n        message: () => {\n          const to = this.isNot ? 'not to' : 'to'\n          return getMessage(\n            this,\n            this.utils.matcherHint(\n              `${this.isNot ? '.not' : ''}.toHaveClass`,\n              'element',\n              this.utils.printExpected(expected.join(' ')),\n            ),\n            `Expected the element ${to} have class`,\n            expected.join(' '),\n            'Received',\n            received.join(' '),\n          )\n        },\n      }\n    : {\n        pass: this.isNot ? received.length > 0 : false,\n        message: () =>\n          this.isNot\n            ? getMessage(\n                this,\n                this.utils.matcherHint('.not.toHaveClass', 'element', ''),\n                'Expected the element to have classes',\n                '(none)',\n                'Received',\n                received.join(' '),\n              )\n            : [\n                this.utils.matcherHint(`.toHaveClass`, 'element'),\n                'At least one expected class must be provided.',\n              ].join('\\n'),\n      }\n}\n\nfunction getExpectedClassNamesAndOptions(\n  params: (string | RegExp)[] | [string, options?: { exact: boolean }],\n): {\n  expectedClassNames: (string | RegExp)[]\n  options: { exact: boolean }\n} {\n  const lastParam = params.pop()\n  let expectedClassNames, options\n\n  if (typeof lastParam === 'object' && !(lastParam instanceof RegExp)) {\n    expectedClassNames = params\n    options = lastParam\n  }\n  else {\n    expectedClassNames = params.concat(lastParam)\n    options = { exact: false }\n  }\n  return { expectedClassNames: expectedClassNames as string[], options }\n}\n\nfunction splitClassNames(str: string | undefined | null): string[] {\n  if (!str) {\n    return []\n  }\n  return str.split(/\\s+/).filter(s => s.length > 0)\n}\n\nfunction isSubset(subset: (string | RegExp)[], superset: string[]) {\n  return subset.every(strOrRegexp =>\n    typeof strOrRegexp === 'string'\n      ? superset.includes(strOrRegexp)\n      : superset.some(className => strOrRegexp.test(className)),\n  )\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveDisplayValue.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput, getMessage, getTag, isInputElement } from './utils'\n\nexport default function toHaveDisplayValue(\n  this: MatcherState,\n  actual: Element | Locator,\n  expectedValue: string | RegExp | Array<string | RegExp>,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveDisplayValue, this)\n  const tagName = getTag(htmlElement)\n\n  if (!['SELECT', 'INPUT', 'TEXTAREA'].includes(tagName)) {\n    throw new Error(\n      '.toHaveDisplayValue() currently supports only input, textarea or select elements, try with another matcher instead.',\n    )\n  }\n\n  if (isInputElement(htmlElement) && ['radio', 'checkbox'].includes(htmlElement.type)) {\n    throw new Error(\n      `.toHaveDisplayValue() currently does not support input[type=\"${htmlElement.type}\"], try with another matcher instead.`,\n    )\n  }\n\n  const values = getValues(tagName, htmlElement)\n  const expectedValues = getExpectedValues(expectedValue)\n  const numberOfMatchesWithValues = expectedValues.filter(expected =>\n    values.some(value =>\n      expected instanceof RegExp\n        ? expected.test(value)\n        : this.equals(value, String(expected), this.customTesters),\n    ),\n  ).length\n\n  const matchedWithAllValues = numberOfMatchesWithValues === values.length\n  const matchedWithAllExpectedValues\n    = numberOfMatchesWithValues === expectedValues.length\n\n  return {\n    pass: matchedWithAllValues && matchedWithAllExpectedValues,\n    message: () =>\n      getMessage(\n        this,\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toHaveDisplayValue`,\n          'element',\n          '',\n        ),\n        `Expected element ${this.isNot ? 'not ' : ''}to have display value`,\n        expectedValue,\n        'Received',\n        values,\n      ),\n  }\n}\n\nfunction getValues(tagName: string, htmlElement: HTMLElement | SVGElement) {\n  return tagName === 'SELECT'\n    ? Array.from(htmlElement as HTMLSelectElement)\n        .filter(option => (option as HTMLOptionElement).selected)\n        .map(option => option.textContent || '')\n    : [(htmlElement as HTMLInputElement).value]\n}\n\nfunction getExpectedValues(expectedValue: string | RegExp | Array<string | RegExp>): Array<string | RegExp> {\n  return Array.isArray(expectedValue) ? expectedValue : [expectedValue]\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveFocus.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getElementFromUserInput } from './utils'\n\nexport default function toHaveFocus(\n  this: MatcherState,\n  actual: Element | Locator,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveFocus, this)\n\n  return {\n    pass: htmlElement.ownerDocument.activeElement === htmlElement,\n    message: () => {\n      return [\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toHaveFocus`,\n          'element',\n          '',\n        ),\n        '',\n        ...(this.isNot\n          ? [\n              'Received element is focused:',\n              `  ${this.utils.printReceived(htmlElement)}`,\n            ]\n          : [\n              'Expected element with focus:',\n              `  ${this.utils.printExpected(htmlElement)}`,\n              'Received element with focus:',\n              `  ${this.utils.printReceived(\n                htmlElement.ownerDocument.activeElement,\n              )}`,\n            ]),\n      ].join('\\n')\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveFormValues.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { cssEscape } from 'ivya/utils'\nimport { arrayAsSetComparison, getElementFromUserInput, getSingleElementValue, getTag } from './utils'\n\nexport default function toHaveFormValues(\n  this: MatcherState,\n  actual: Element | Locator,\n  expectedValues: Record<string, unknown>,\n): ExpectationResult {\n  const formElement = getElementFromUserInput(actual, toHaveFormValues, this)\n\n  const defaultView = formElement.ownerDocument.defaultView || window\n\n  if (!(formElement instanceof defaultView.HTMLFieldSetElement) && !(formElement instanceof defaultView.HTMLFormElement)) {\n    throw new TypeError(`toHaveFormValues must be called on a form or a fieldset, instead got ${getTag(formElement)}`)\n  }\n\n  if (!expectedValues || typeof expectedValues !== 'object') {\n    throw new TypeError(\n      `toHaveFormValues must be called with an object of expected form values. Got ${expectedValues}`,\n    )\n  }\n\n  const formValues = getAllFormValues(formElement)\n  return {\n    pass: Object.entries(expectedValues).every(([name, expectedValue]) =>\n      this.equals(formValues[name], expectedValue, [arrayAsSetComparison, ...this.customTesters]),\n    ),\n    message: () => {\n      const to = this.isNot ? 'not to' : 'to'\n      const matcher = `${this.isNot ? '.not' : ''}.toHaveFormValues`\n\n      const commonKeyValues: Record<string, unknown> = {}\n      for (const key in formValues) {\n        if (!Object.hasOwn(expectedValues, key)) {\n          continue\n        }\n        commonKeyValues[key] = formValues[key]\n      }\n\n      return [\n        this.utils.matcherHint(matcher, 'element', ''),\n        `Expected the element ${to} have form values`,\n        this.utils.diff(expectedValues, commonKeyValues),\n      ].join('\\n\\n')\n    },\n  }\n}\n\n// Returns the combined value of several elements that have the same name\n// e.g. radio buttons or groups of checkboxes\nfunction getMultiElementValue(elements: HTMLInputElement[]) {\n  let type = ''\n  for (const element of elements) {\n    if (type && type !== element.type) {\n      throw new Error(\n        'Multiple form elements with the same name must be of the same type',\n      )\n    }\n    type = element.type\n  }\n  switch (type) {\n    case 'radio': {\n      const selected = elements.find(radio => radio.checked)\n      return selected ? selected.value : undefined\n    }\n    case 'checkbox':\n      return elements\n        .filter(checkbox => checkbox.checked)\n        .map(checkbox => checkbox.value)\n    default:\n      // NOTE: Not even sure this is a valid use case, but just in case...\n      return elements.map(element => element.value)\n  }\n}\n\nfunction getFormValue(container: HTMLFormElement | HTMLFieldSetElement, name: string) {\n  const elements = [...container.querySelectorAll(`[name=\"${cssEscape(name)}\"]`)]\n  /* istanbul ignore if */\n  if (elements.length === 0) {\n    return undefined // shouldn't happen, but just in case\n  }\n  switch (elements.length) {\n    case 1:\n      return getSingleElementValue(elements[0])\n    default:\n      return getMultiElementValue(elements as HTMLInputElement[])\n  }\n}\n\n// Strips the `[]` suffix off a form value name\nfunction getPureName(name: string) {\n  return /\\[\\]$/.test(name) ? name.slice(0, -2) : name\n}\n\nfunction getAllFormValues(container: HTMLFormElement | HTMLFieldSetElement) {\n  const values: Record<string, unknown> = {}\n\n  for (const element of container.elements) {\n    if (!('name' in element)) {\n      continue\n    }\n    const name = element.name as string\n    values[getPureName(name)] = getFormValue(container, name)\n  }\n\n  return values\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveRole.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { beginAriaCaches, endAriaCaches, getAriaRole } from 'ivya/utils'\nimport { getElementFromUserInput, getMessage } from './utils'\n\nexport default function toHaveRole(\n  this: MatcherState,\n  actual: Element | Locator,\n  expectedRole: string,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveRole, this)\n  beginAriaCaches()\n  const actualRole = getAriaRole(htmlElement)\n  endAriaCaches()\n  return {\n    pass: actualRole === expectedRole,\n    message: () => {\n      const to = this.isNot ? 'not to' : 'to'\n      return getMessage(\n        this,\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toHaveRole`,\n          'element',\n          '',\n        ),\n        `Expected element ${to} have role`,\n        expectedRole,\n        'Received',\n        actualRole,\n      )\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveSelection.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { arrayAsSetComparison, getElementFromUserInput, getMessage, getTag } from './utils'\n\nexport default function toHaveSelection(\n  this: MatcherState,\n  element: HTMLElement | SVGElement | Locator,\n  expectedSelection: string,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(element, toHaveSelection, this)\n\n  const expectsSelection = expectedSelection !== undefined\n\n  if (expectsSelection && typeof expectedSelection !== 'string') {\n    throw new Error(`expected selection must be a string or undefined`)\n  }\n\n  const receivedSelection = getSelection(htmlElement)\n\n  return {\n    pass: expectsSelection\n      ? this.equals(receivedSelection, expectedSelection, [arrayAsSetComparison, ...this.customTesters])\n      : Boolean(receivedSelection),\n    message: () => {\n      const to = this.isNot ? 'not to' : 'to'\n      const matcher = this.utils.matcherHint(\n        `${this.isNot ? '.not' : ''}.toHaveSelection`,\n        'element',\n        expectedSelection,\n      )\n      return getMessage(\n        this,\n        matcher,\n        `Expected the element ${to} have selection`,\n        expectsSelection ? expectedSelection : '(any)',\n        'Received',\n        receivedSelection,\n      )\n    },\n  }\n}\n\nfunction getSelection(element: HTMLElement | SVGElement): string {\n  const selection = element.ownerDocument.getSelection()\n\n  if (!selection) {\n    return ''\n  }\n\n  if (['INPUT', 'TEXTAREA'].includes(getTag(element))) {\n    const input = element as HTMLInputElement | HTMLTextAreaElement\n    if (['radio', 'checkbox'].includes(input.type)) {\n      return ''\n    }\n    if (input.selectionStart == null || input.selectionEnd == null) {\n      return ''\n    }\n    return input.value\n      .toString()\n      .substring(input.selectionStart, input.selectionEnd)\n  }\n\n  if (selection.anchorNode === null || selection.focusNode === null) {\n    // No selection\n    return ''\n  }\n\n  const originalRange = selection.getRangeAt(0)\n  const temporaryRange = element.ownerDocument.createRange()\n\n  if (selection.containsNode(element, false)) {\n    // Whole element is inside selection\n    temporaryRange.selectNodeContents(element)\n    selection.removeAllRanges()\n    selection.addRange(temporaryRange)\n  }\n  else if (\n    element.contains(selection.anchorNode)\n    && element.contains(selection.focusNode)\n  ) {\n    // Element contains selection, nothing to do\n  }\n  else {\n    // Element is partially selected\n    const selectionStartsWithinElement\n      = element === originalRange.startContainer\n        || element.contains(originalRange.startContainer)\n    const selectionEndsWithinElement\n      = element === originalRange.endContainer\n        || element.contains(originalRange.endContainer)\n    selection.removeAllRanges()\n\n    if (selectionStartsWithinElement || selectionEndsWithinElement) {\n      temporaryRange.selectNodeContents(element)\n\n      if (selectionStartsWithinElement) {\n        temporaryRange.setStart(\n          originalRange.startContainer,\n          originalRange.startOffset,\n        )\n      }\n      if (selectionEndsWithinElement) {\n        temporaryRange.setEnd(\n          originalRange.endContainer,\n          originalRange.endOffset,\n        )\n      }\n\n      selection.addRange(temporaryRange)\n    }\n  }\n\n  const result = selection.toString()\n\n  selection.removeAllRanges()\n  selection.addRange(originalRange)\n\n  return result\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveStyle.ts",
    "content": "import type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { server } from 'vitest/browser'\nimport { getElementFromUserInput } from './utils'\n\nconst browser = server.config.browser.name\n\n// these values should keep the `style` attribute instead of computing px to be consistent with jsdom\n// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/used_value#difference_from_computed_value\nconst usedValuesProps = new Set([\n  'backgroundPosition',\n  'background-position',\n  'bottom',\n  'left',\n  'right',\n  'top',\n  'height',\n  'width',\n  'margin-bottom',\n  'marginBottom',\n  'margin-left',\n  'marginLeft',\n  'margin-right',\n  'marginRight',\n  'margin-top',\n  'marginTop',\n  'min-height',\n  'minHeight',\n  'min-width',\n  'minWidth',\n  'padding-bottom',\n  'padding-left',\n  'padding-right',\n  'padding-top',\n  'text-indent',\n  'paddingBottom',\n  'paddingLeft',\n  'paddingRight',\n  'paddingTop',\n  'textIndent',\n])\n\nexport default function toHaveStyle(\n  this: MatcherState,\n  actual: Element | Locator,\n  css: string | Record<string, unknown>,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveStyle, this)\n  const { getComputedStyle } = htmlElement.ownerDocument.defaultView!\n\n  const expected = typeof css === 'object'\n    ? getStyleFromObjectCSS(css)\n    : computeCSSStyleDeclaration(css)\n  const received = getComputedStyle(htmlElement)\n  const receivedCustomKeys = new Set(Array.from(htmlElement.style))\n\n  return {\n    pass: isSubset(expected, htmlElement, received, receivedCustomKeys),\n    message: () => {\n      const matcher = `${this.isNot ? '.not' : ''}.toHaveStyle`\n      const expectedKeys = new Set(Object.keys(expected))\n      const receivedObject = Array.from(received)\n        .filter(prop => expectedKeys.has(prop))\n        .reduce(\n          (obj, prop) => {\n            const styleSheet = receivedCustomKeys.has(prop) && usedValuesProps.has(prop)\n              ? htmlElement.style\n              : received\n            obj[prop] = styleSheet[prop as 'color']\n            return obj\n          },\n          {} as Record<string, unknown>,\n        )\n      const receivedString = printoutObjectStyles(receivedObject)\n      const diff = receivedString === ''\n        ? 'Expected styles could not be parsed by the browser. Did you make a typo?'\n        : this.utils.diff(\n            printoutObjectStyles(expected),\n            receivedString,\n          )\n      return [\n        this.utils.matcherHint(matcher, 'element', ''),\n        diff,\n      ].join('\\n\\n')\n    },\n  }\n}\n\nfunction getStyleFromObjectCSS(css: Record<string, unknown>): Record<string, unknown> {\n  const doc = browser === 'chrome' || browser === 'chromium'\n    ? document\n    : document.implementation.createHTMLDocument('')\n\n  const copy = doc.createElement('div')\n  doc.body.appendChild(copy)\n  const keys = Object.keys(css)\n\n  keys.forEach((property) => {\n    copy.style[property as 'color'] = css[property] as string\n  })\n\n  const styles: Record<string, unknown> = {}\n  // to get normalized colors (blue -> rgb(0, 0, 255))\n  const computedStyles = window.getComputedStyle(copy)\n  keys.forEach((property) => {\n    const styleSheet = usedValuesProps.has(property) ? copy.style : computedStyles\n    const value = styleSheet[property as 'color']\n    // ignore invalid keys\n    if (value != null) {\n      styles[property] = value\n    }\n  })\n  copy.remove()\n\n  return styles\n}\n\nfunction computeCSSStyleDeclaration(css: string): Record<string, unknown> {\n  // on chromium for styles to be computed, they need to be inserted into the actual document\n  // webkit will also not compute _some_ style like transform if it's not in the document\n  const doc = browser === 'chrome' || browser === 'chromium' || browser === 'webkit'\n    ? document\n    : document.implementation.createHTMLDocument('')\n\n  const rootElement = doc.createElement('div')\n  rootElement.setAttribute('style', css.replace(/\\n/g, ''))\n  doc.body.appendChild(rootElement)\n\n  const computedStyle = window.getComputedStyle(rootElement)\n\n  const styleDeclaration = Array.from(rootElement.style).reduce((acc, prop) => {\n    acc[prop] = usedValuesProps.has(prop)\n      ? rootElement.style.getPropertyValue(prop)\n      : computedStyle.getPropertyValue(prop)\n    return acc\n  }, {} as Record<string, unknown>)\n  rootElement.remove()\n  return styleDeclaration\n}\n\nfunction printoutObjectStyles(styles: Record<string, unknown>): string {\n  return Object.keys(styles)\n    .sort()\n    .map(prop => `${prop}: ${styles[prop]};`)\n    .join('\\n')\n}\n\nfunction isSubset(\n  styles: Record<string, unknown>,\n  element: HTMLElement | SVGElement,\n  computedStyle: CSSStyleDeclaration,\n  receivedCustomKeys: Set<string>,\n): boolean {\n  const keys = Object.keys(styles)\n  if (!keys.length) {\n    return false\n  }\n  return keys.every((prop) => {\n    const value = styles[prop as 'color']\n    const isCustomProperty = prop.startsWith('--')\n    const spellingVariants = [prop]\n    if (!isCustomProperty) {\n      spellingVariants.push(prop.toLowerCase())\n    }\n\n    const pass = spellingVariants.some(\n      (name) => {\n        const styleSheet = receivedCustomKeys.has(prop) && usedValuesProps.has(prop)\n          ? element.style\n          : computedStyle\n        return styleSheet[name as 'color'] === value\n          || styleSheet.getPropertyValue(name) === value\n      },\n    )\n    return pass\n  },\n  )\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveTextContent.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { getMessage, getNodeFromUserInput, matches, normalize } from './utils'\n\nexport default function toHaveTextContent(\n  this: MatcherState,\n  actual: Element | Locator,\n  matcher: string | RegExp,\n  options: { normalizeWhitespace?: boolean } = { normalizeWhitespace: true },\n): ExpectationResult {\n  const node = getNodeFromUserInput(actual, toHaveTextContent, this)\n\n  const textContent = options.normalizeWhitespace\n    ? normalize(node.textContent || '')\n    : (node.textContent || '').replace(/\\u00A0/g, ' ') // Replace &nbsp; with normal spaces\n\n  const checkingWithEmptyString = textContent !== '' && matcher === ''\n\n  return {\n    pass: !checkingWithEmptyString && matches(textContent, matcher),\n    message: () => {\n      const to = this.isNot ? 'not to' : 'to'\n      return getMessage(\n        this,\n        this.utils.matcherHint(\n          `${this.isNot ? '.not' : ''}.toHaveTextContent`,\n          'element',\n          '',\n        ),\n        checkingWithEmptyString\n          ? `Checking with empty string will always match, use .toBeEmptyDOMElement() instead`\n          : `Expected element ${to} have text content`,\n        matcher,\n        'Received',\n        textContent,\n      )\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toHaveValue.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { ExpectationResult, MatcherState } from '@vitest/expect'\nimport type { Locator } from '../locators'\nimport { arrayAsSetComparison, getElementFromUserInput, getMessage, getSingleElementValue, isInputElement } from './utils'\n\nexport default function toHaveValue(\n  this: MatcherState,\n  actual: Element | Locator,\n  expectedValue?: string,\n): ExpectationResult {\n  const htmlElement = getElementFromUserInput(actual, toHaveValue, this)\n\n  if (\n    isInputElement(htmlElement)\n    && ['checkbox', 'radio'].includes(htmlElement.type)\n  ) {\n    throw new Error(\n      'input with type=checkbox or type=radio cannot be used with .toHaveValue(). Use .toBeChecked() for type=checkbox or .toHaveFormValues() instead',\n    )\n  }\n\n  const receivedValue = getSingleElementValue(htmlElement)\n  const expectsValue = expectedValue !== undefined\n\n  let expectedTypedValue = expectedValue\n  let receivedTypedValue = receivedValue\n  // eslint-disable-next-line eqeqeq\n  if (expectedValue == receivedValue && expectedValue !== receivedValue) {\n    expectedTypedValue = `${expectedValue} (${typeof expectedValue})`\n    receivedTypedValue = `${receivedValue} (${typeof receivedValue})`\n  }\n\n  return {\n    pass: expectsValue\n      ? this.equals(receivedValue, expectedValue, [arrayAsSetComparison, ...this.customTesters])\n      : Boolean(receivedValue),\n    message: () => {\n      const to = this.isNot ? 'not to' : 'to'\n      const matcher = this.utils.matcherHint(\n        `${this.isNot ? '.not' : ''}.toHaveValue`,\n        'element',\n        expectedValue,\n      )\n      return getMessage(\n        this,\n        matcher,\n        `Expected the element ${to} have value`,\n        expectsValue ? expectedTypedValue : '(any)',\n        'Received',\n        receivedTypedValue,\n      )\n    },\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/toMatchScreenshot.ts",
    "content": "import type { AsyncExpectationResult, MatcherState } from '@vitest/expect'\nimport type { VisualRegressionArtifact } from '@vitest/runner'\nimport type { ScreenshotMatcherOptions } from '../../../../context'\nimport type { ScreenshotMatcherArguments, ScreenshotMatcherOutput } from '../../../shared/screenshotMatcher/types'\nimport type { Locator } from '../locators'\nimport { recordArtifact } from 'vitest'\nimport { getBrowserState } from '../../utils'\nimport { convertToSelector } from '../tester-utils'\n\nconst counters = new Map<string, { current: number }>([])\n\nexport default async function toMatchScreenshot(\n  this: MatcherState,\n  actual: Element | Locator,\n  nameOrOptions?: ScreenshotMatcherOptions | string,\n  options: ScreenshotMatcherOptions = typeof nameOrOptions === 'object'\n    ? nameOrOptions\n    : {},\n): AsyncExpectationResult {\n  if (this.isNot) {\n    throw new Error('\\'toMatchScreenshot\\' cannot be used with \"not\"')\n  }\n\n  if (this.task === undefined || this.currentTestName === undefined) {\n    throw new Error('\\'toMatchScreenshot\\' cannot be used without test context')\n  }\n\n  const counterName = `${this.task.result?.repeatCount ?? 0}${this.testPath}${this.currentTestName}`\n  let counter = counters.get(counterName)\n\n  if (counter === undefined) {\n    counter = { current: 0 }\n\n    counters.set(counterName, counter)\n  }\n\n  counter.current += 1\n\n  const name = typeof nameOrOptions === 'string'\n    ? nameOrOptions\n    : `${this.currentTestName} ${counter.current}`\n\n  const [element, ...mask] = await Promise.all([\n    convertToSelector(actual, options),\n    ...options.screenshotOptions && 'mask' in options.screenshotOptions\n      ? (options.screenshotOptions.mask as Array<Element | Locator>)\n          .map(m => convertToSelector(m, options))\n      : [],\n  ])\n\n  const normalizedOptions: Omit<ScreenshotMatcherArguments[2], 'element'> = (\n    options.screenshotOptions && 'mask' in options.screenshotOptions\n      ? {\n          ...options,\n          screenshotOptions: {\n            ...options.screenshotOptions,\n            mask,\n          },\n        }\n      // TS believes `mask` to still be defined as `ReadonlyArray<Element | Locator>`\n      : options as any\n  )\n\n  const result = await getBrowserState().commands.triggerCommand<ScreenshotMatcherOutput>(\n    '__vitest_screenshotMatcher',\n    [\n      name,\n      this.currentTestName,\n      {\n        element,\n        ...normalizedOptions,\n      },\n    ] satisfies ScreenshotMatcherArguments,\n  )\n\n  if (result.pass === false) {\n    const attachments: VisualRegressionArtifact['attachments'] = []\n\n    if (result.reference) {\n      attachments.push({ name: 'reference', ...result.reference })\n    }\n\n    if (result.actual) {\n      attachments.push({ name: 'actual', ...result.actual })\n    }\n\n    if (result.diff) {\n      attachments.push({ name: 'diff', ...result.diff })\n    }\n\n    if (attachments.length > 0) {\n      await recordArtifact(this.task, {\n        type: 'internal:toMatchScreenshot',\n        kind: 'visual-regression',\n        message: result.message,\n        attachments,\n      })\n    }\n  }\n\n  return {\n    pass: result.pass,\n    message: () =>\n      result.pass\n        ? ''\n        : [\n            this.utils.matcherHint('toMatchScreenshot', 'element', ''),\n            '',\n            result.message,\n            result.reference\n              ? `\\nReference screenshot:\\n  ${this.utils.EXPECTED_COLOR(result.reference.path)}`\n              : null,\n            result.actual\n              ? `\\nActual screenshot:\\n  ${this.utils.RECEIVED_COLOR(result.actual.path)}`\n              : null,\n            result.diff\n              ? this.utils.DIM_COLOR(`\\nDiff image:\\n  ${result.diff.path}`)\n              : null,\n            '',\n          ]\n            .filter(element => element !== null)\n            .join('\\n'),\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect/utils.ts",
    "content": "/**\n * The MIT License (MIT)\n * Copyright (c) 2017 Kent C. Dodds\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n */\n\nimport type { MatcherState } from '@vitest/expect'\nimport { Locator } from '../locators'\n\nexport function queryElementFromUserInput(\n  elementOrLocator: Element | Locator | null,\n  // TODO: minifier doesn't keep names, so we need to update this\n  matcherFn: (...args: any) => any,\n  context: MatcherState,\n): HTMLElement | SVGElement | null {\n  if (elementOrLocator instanceof Locator) {\n    elementOrLocator = elementOrLocator.query()\n  }\n\n  if (elementOrLocator == null) {\n    return null\n  }\n\n  return getElementFromUserInput(elementOrLocator, matcherFn, context)\n}\n\nexport function getElementFromUserInput(\n  elementOrLocator: Element | Locator | null,\n  // TODO: minifier doesn't keep names, so we need to update this\n  matcherFn: (...args: any) => any,\n  context: MatcherState,\n): HTMLElement | SVGElement {\n  if (elementOrLocator instanceof Locator) {\n    elementOrLocator = elementOrLocator.element()\n  }\n\n  const defaultView = elementOrLocator?.ownerDocument?.defaultView || window\n\n  if (\n    elementOrLocator instanceof defaultView.HTMLElement\n    || elementOrLocator instanceof defaultView.SVGElement\n  ) {\n    return elementOrLocator\n  }\n\n  throw new UserInputElementTypeError(\n    elementOrLocator,\n    matcherFn,\n    context,\n  )\n}\n\nexport function getNodeFromUserInput(\n  elementOrLocator: Element | Locator,\n  matcherFn: (...args: any) => any,\n  context: MatcherState,\n): Node {\n  if (elementOrLocator instanceof Locator) {\n    elementOrLocator = elementOrLocator.element()\n  }\n\n  const defaultView = elementOrLocator.ownerDocument?.defaultView || window\n\n  if (\n    elementOrLocator instanceof defaultView.Node\n  ) {\n    return elementOrLocator\n  }\n\n  throw new UserInputNodeTypeError(\n    elementOrLocator,\n    matcherFn,\n    context,\n  )\n}\n\nexport function getMessage(\n  context: MatcherState,\n  matcher: string,\n  expectedLabel: string,\n  expectedValue: unknown,\n  receivedLabel: string,\n  receivedValue: unknown,\n): string {\n  return [\n    `${matcher}\\n`,\n\n    `${expectedLabel}:\\n${context.utils.EXPECTED_COLOR(\n      redent(display(context, expectedValue), 2),\n    )}`,\n\n    `${receivedLabel}:\\n${context.utils.RECEIVED_COLOR(\n      redent(display(context, receivedValue), 2),\n    )}`,\n  ].join('\\n')\n}\n\nexport function redent(string: string, count: number): string {\n  return indentString(stripIndent(string), count)\n}\n\nfunction indentString(string: string, count: number) {\n  const regex = /^(?!\\s*$)/gm\n\n  return string.replace(regex, ' '.repeat(count))\n}\n\nfunction minIndent(string: string) {\n  const match = string.match(/^[ \\t]*(?=\\S)/gm)\n\n  if (!match) {\n    return 0\n  }\n\n  return match.reduce((r, a) => Math.min(r, a.length), Infinity)\n}\n\nfunction stripIndent(string: string) {\n  const indent = minIndent(string)\n\n  if (indent === 0) {\n    return string\n  }\n\n  const regex = new RegExp(`^[ \\\\t]{${indent}}`, 'gm')\n\n  return string.replace(regex, '')\n}\n\nfunction display(context: MatcherState, value: unknown) {\n  return typeof value === 'string' ? value : context.utils.stringify(value)\n}\n\ninterface ToSentenceOptions {\n  wordConnector?: string\n  lastWordConnector?: string\n}\n\nexport function toSentence(\n  array: string[],\n  { wordConnector = ', ', lastWordConnector = ' and ' }: ToSentenceOptions = {},\n): string {\n  return [array.slice(0, -1).join(wordConnector), array.at(-1)].join(\n    array.length > 1 ? lastWordConnector : '',\n  )\n}\n\nclass GenericTypeError extends Error {\n  constructor(expectedString: string, received: unknown, matcherFn: (...args: any) => any, context: MatcherState) {\n    super()\n\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, matcherFn)\n    }\n    let withType = ''\n    try {\n      withType = context.utils.printWithType(\n        'Received',\n        received,\n        context.utils.printReceived,\n      )\n    }\n    catch {\n      // Can throw for Document:\n      // https://github.com/jsdom/jsdom/issues/2304\n    }\n    this.message = [\n      context.utils.matcherHint(\n        `${context.isNot ? '.not' : ''}.${matcherFn.name}`,\n        'received',\n        '',\n      ),\n      '',\n\n      `${context.utils.RECEIVED_COLOR(\n        'received',\n      )} value must ${expectedString} or a Locator that returns ${expectedString}.`,\n      withType,\n    ].join('\\n')\n  }\n}\n\nclass UserInputElementTypeError extends GenericTypeError {\n  constructor(\n    element: unknown,\n    matcherFn: (...args: any) => any,\n    context: MatcherState,\n  ) {\n    super('an HTMLElement or an SVGElement', element, matcherFn, context)\n  }\n}\n\nclass UserInputNodeTypeError extends GenericTypeError {\n  constructor(\n    element: unknown,\n    matcherFn: (...args: any) => any,\n    context: MatcherState,\n  ) {\n    super('a Node', element, matcherFn, context)\n  }\n}\n\nexport function getTag(element: Element): string {\n  // Named inputs, e.g. <input name=tagName>, will be exposed as fields on the parent <form>\n  // and override its properties.\n  if (element instanceof HTMLFormElement) {\n    return 'FORM'\n  }\n  // Elements from the svg namespace do not have uppercase tagName right away.\n  return element.tagName.toUpperCase()\n}\n\nexport function isInputElement(element: HTMLElement | SVGElement): element is HTMLInputElement {\n  return getTag(element) === 'INPUT'\n}\n\ntype SimpleInputValue = string | number | boolean | null\n\nexport function getSingleElementValue(\n  element: Element | undefined,\n): SimpleInputValue | string[] | undefined {\n  if (!element) {\n    return undefined\n  }\n\n  switch (getTag(element)) {\n    case 'INPUT':\n      return getInputValue(element as HTMLInputElement)\n    case 'SELECT':\n      return getSelectValue(element as HTMLSelectElement)\n    default: {\n      return (element as any).value ?? getAccessibleValue(element)\n    }\n  }\n}\n\nfunction getSelectValue({ multiple, options }: HTMLSelectElement) {\n  const selectedOptions = [...options].filter(option => option.selected)\n\n  if (multiple) {\n    return [...selectedOptions].map(opt => opt.value)\n  }\n  /* istanbul ignore if */\n  if (selectedOptions.length === 0) {\n    return undefined // Couldn't make this happen, but just in case\n  }\n  return selectedOptions[0].value\n}\n\nfunction getInputValue(inputElement: HTMLInputElement) {\n  switch (inputElement.type) {\n    case 'number':\n      return inputElement.value === '' ? null : Number(inputElement.value)\n    case 'checkbox':\n      return inputElement.checked\n    default:\n      return inputElement.value\n  }\n}\n\nconst rolesSupportingValues = ['meter', 'progressbar', 'slider', 'spinbutton']\nfunction getAccessibleValue(element: Element) {\n  if (!rolesSupportingValues.includes(element.getAttribute('role') || '')) {\n    return undefined\n  }\n  return Number(element.getAttribute('aria-valuenow'))\n}\n\nexport function normalize(text: string): string {\n  return text.replace(/\\s+/g, ' ').trim()\n}\n\nexport function matches(textToMatch: string, matcher: string | RegExp): boolean {\n  if (matcher instanceof RegExp) {\n    return matcher.test(textToMatch)\n  }\n  else {\n    return textToMatch.includes(String(matcher))\n  }\n}\n\nexport function arrayAsSetComparison(a: unknown, b: unknown): boolean | undefined {\n  if (Array.isArray(a) && Array.isArray(b)) {\n    const setB = new Set(b)\n    for (const item of new Set(a)) {\n      if (!setB.has(item)) {\n        return false\n      }\n    }\n    return true\n  }\n  return undefined\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/expect-element.ts",
    "content": "import type { Assertion, ExpectPollOptions, PromisifyDomAssertion } from 'vitest'\nimport type { Locator } from 'vitest/browser'\nimport { chai, expect } from 'vitest'\nimport { getType } from 'vitest/internal/browser'\nimport { getBrowserState, getWorkerState } from '../utils'\nimport { matchers } from './expect'\nimport { processTimeoutOptions } from './tester-utils'\n\nconst kLocator = Symbol.for('$$vitest:locator')\n\nfunction element<T extends HTMLElement | SVGElement | null | Locator>(elementOrLocator: T, options?: ExpectPollOptions): PromisifyDomAssertion<HTMLElement | SVGElement | null> {\n  if (elementOrLocator != null && !(elementOrLocator instanceof HTMLElement) && !(elementOrLocator instanceof SVGElement) && !(kLocator in elementOrLocator)) {\n    throw new Error(`Invalid element or locator: ${elementOrLocator}. Expected an instance of HTMLElement, SVGElement or Locator, received ${getType(elementOrLocator)}`)\n  }\n\n  const expectElement = expect.poll<HTMLElement | SVGElement | null>(function element(this: object) {\n    if (elementOrLocator instanceof Element || elementOrLocator == null) {\n      return elementOrLocator\n    }\n\n    const isNot = chai.util.flag(this, 'negate') as boolean\n    const name = chai.util.flag(this, '_name') as string\n    // special case for `toBeInTheDocument` matcher\n    if (isNot && name === 'toBeInTheDocument') {\n      return elementOrLocator.query()\n    }\n    if (name === 'toHaveLength') {\n      // we know that `toHaveLength` requires multiple elements,\n      // but types generally expect a single one\n      return elementOrLocator.elements() as unknown as HTMLElement\n    }\n\n    if (name === 'toMatchScreenshot' && !chai.util.flag(this, '_poll.assert_once')) {\n      // `toMatchScreenshot` should only run once after the element resolves\n      chai.util.flag(this, '_poll.assert_once', true)\n    }\n\n    // element selector uses prettyDOM under the hood, which is an expensive call\n    // that should not be called on each failed locator attempt to avoid memory leak:\n    // https://github.com/vitest-dev/vitest/issues/7139\n    const isLastPollAttempt = chai.util.flag(this, '_isLastPollAttempt')\n\n    if (isLastPollAttempt) {\n      return elementOrLocator.element()\n    }\n\n    const result = elementOrLocator.query()\n\n    if (!result) {\n      throw new Error(`Cannot find element with locator: ${JSON.stringify(elementOrLocator)}`)\n    }\n\n    return result\n  }, processTimeoutOptions(options))\n\n  chai.util.flag(expectElement, '_poll.element', true)\n\n  // ask `expect.poll` to invoke trace after the assertion\n  const currentTest = getWorkerState().current\n  if (currentTest && getBrowserState().activeTraceTaskIds.has(currentTest.id)) {\n    const sourceError = new Error('__vitest_mark_trace__')\n    chai.util.flag(expectElement, '_poll.onSettled', async (meta: { assertion: Assertion; status: 'pass' | 'fail' }) => {\n      const isNot = chai.util.flag(meta.assertion, 'negate')\n      const name = chai.util.flag(meta.assertion, '_name') || '<unknown>'\n      const baseName = `expect.element().${isNot ? 'not.' : ''}${name}`\n      const traceName = meta.status === 'fail' ? `${baseName} [ERROR]` : baseName\n      const selector = !elementOrLocator || elementOrLocator instanceof Element\n        ? undefined\n        : elementOrLocator.selector\n      await getBrowserState().commands.triggerCommand(\n        '__vitest_markTrace',\n        [{\n          name: traceName,\n          selector,\n          stack: sourceError.stack,\n        }],\n        sourceError,\n      )\n    })\n  }\n\n  return expectElement\n}\n\nexpect.extend(matchers)\nexpect.element = element\n"
  },
  {
    "path": "packages/browser/src/client/tester/locators/index.ts",
    "content": "import type { ParsedSelector } from 'ivya'\nimport type {\n  LocatorByRoleOptions,\n  LocatorOptions,\n  LocatorScreenshotOptions,\n  MarkOptions,\n  SelectorOptions,\n  UserEventClearOptions,\n  UserEventClickOptions,\n  UserEventDragAndDropOptions,\n  UserEventFillOptions,\n  UserEventHoverOptions,\n  UserEventSelectOptions,\n  UserEventUploadOptions,\n  UserEventWheelOptions,\n} from 'vitest/browser'\nimport {\n  asLocator,\n  getByAltTextSelector,\n  getByLabelSelector,\n  getByPlaceholderSelector,\n  getByRoleSelector,\n  getByTestIdSelector,\n  getByTextSelector,\n  getByTitleSelector,\n  Ivya,\n} from 'ivya'\nimport { page, server, utils } from 'vitest/browser'\nimport { __INTERNAL, getSafeTimers } from 'vitest/internal/browser'\nimport { ensureAwaited, getBrowserState, getWorkerState } from '../../utils'\nimport { escapeForTextSelector, isLocator, processTimeoutOptions, resolveUserEventWheelOptions } from '../tester-utils'\n\nexport { ensureAwaited } from '../../utils'\nexport { convertElementToCssSelector, getIframeScale, processTimeoutOptions } from '../tester-utils'\nexport {\n  getByAltTextSelector,\n  getByLabelSelector,\n  getByPlaceholderSelector,\n  getByRoleSelector,\n  getByTestIdSelector,\n  getByTextSelector,\n  getByTitleSelector,\n} from 'ivya'\n\n__INTERNAL._asLocator = asLocator\n\nconst now = Date.now\nconst waitForIntervals = [0, 20, 50, 100, 100, 500]\n\nfunction sleep(ms: number): Promise<void> {\n  const { setTimeout } = getSafeTimers()\n  return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n// we prefer using playwright locators because they are more powerful and support Shadow DOM\nexport const selectorEngine: Ivya = Ivya.create({\n  browser: ((name: string) => {\n    switch (name) {\n      case 'edge':\n      case 'chrome':\n        return 'chromium'\n      case 'safari':\n        return 'webkit'\n      default:\n        return name as 'webkit' | 'firefox' | 'chromium'\n    }\n  })(server.config.browser.name),\n  testIdAttribute: server.config.browser.locators.testIdAttribute,\n})\n\nconst kLocator = Symbol.for('$$vitest:locator')\n\nexport abstract class Locator {\n  public abstract selector: string\n\n  private _parsedSelector: ParsedSelector | undefined\n  protected _container?: Element | undefined\n  protected _pwSelector?: string | undefined\n  protected _errorSource?: Error\n\n  constructor() {\n    Object.defineProperty(this, kLocator, {\n      enumerable: false,\n      writable: false,\n      configurable: false,\n      value: kLocator,\n    })\n  }\n\n  public click(options?: UserEventClickOptions): Promise<void> {\n    return this.triggerCommand<void>('__vitest_click', this.selector, options)\n  }\n\n  public dblClick(options?: UserEventClickOptions): Promise<void> {\n    return this.triggerCommand<void>('__vitest_dblClick', this.selector, options)\n  }\n\n  public tripleClick(options?: UserEventClickOptions): Promise<void> {\n    return this.triggerCommand<void>('__vitest_tripleClick', this.selector, options)\n  }\n\n  public wheel(options: UserEventWheelOptions): Promise<void> {\n    return ensureAwaited<void>(async (error) => {\n      await getBrowserState().commands.triggerCommand<void>(\n        '__vitest_wheel',\n        [this.selector, resolveUserEventWheelOptions(options)],\n        error,\n      )\n\n      const browser = getBrowserState().config.browser.name\n\n      // looks like on Chromium the scroll event gets dispatched a frame later\n      if (browser === 'chromium' || browser === 'chrome') {\n        return new Promise((resolve) => {\n          requestAnimationFrame(() => {\n            resolve()\n          })\n        })\n      }\n    })\n  }\n\n  public clear(options?: UserEventClearOptions): Promise<void> {\n    return this.triggerCommand<void>('__vitest_clear', this.selector, options)\n  }\n\n  public hover(options?: UserEventHoverOptions): Promise<void> {\n    return this.triggerCommand<void>('__vitest_hover', this.selector, options)\n  }\n\n  public unhover(options?: UserEventHoverOptions): Promise<void> {\n    return this.triggerCommand<void>('__vitest_hover', 'html > body', options)\n  }\n\n  public fill(text: string, options?: UserEventFillOptions): Promise<void> {\n    return this.triggerCommand<void>('__vitest_fill', this.selector, text, options)\n  }\n\n  public upload(files: string | string[] | File | File[], options?: UserEventUploadOptions): Promise<void> {\n    return ensureAwaited(async (error) => {\n      const filesPromise = (Array.isArray(files) ? files : [files]).map(async (file) => {\n        if (typeof file === 'string') {\n          return file\n        }\n        const bas64String = await new Promise<string>((resolve, reject) => {\n          const reader = new FileReader()\n          reader.onload = () => resolve(reader.result as string)\n          reader.onerror = () => reject(new Error(`Failed to read file: ${file.name}`))\n          reader.readAsDataURL(file)\n        })\n\n        return {\n          name: file.name,\n          mimeType: file.type,\n          // strip prefix `data:[<media-type>][;base64],`\n          base64: bas64String.slice(bas64String.indexOf(',') + 1),\n        }\n      })\n      return getBrowserState().commands.triggerCommand<void>(\n        '__vitest_upload',\n        [this.selector, await Promise.all(filesPromise), options],\n        error,\n      )\n    })\n  }\n\n  public dropTo(target: Locator, options: UserEventDragAndDropOptions = {}): Promise<void> {\n    return this.triggerCommand<void>(\n      '__vitest_dragAndDrop',\n      this.selector,\n      target.selector,\n      options,\n    )\n  }\n\n  public selectOptions(\n    value: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],\n    options?: UserEventSelectOptions,\n  ): Promise<void> {\n    const values = (Array.isArray(value) ? value : [value]).map((v) => {\n      if (typeof v !== 'string') {\n        const selector = isLocator(v) ? v.selector : selectorEngine.generateSelectorSimple(v)\n        return { element: selector }\n      }\n      return v\n    })\n    return this.triggerCommand('__vitest_selectOptions', this.selector, values, options)\n  }\n\n  public screenshot(options: Omit<LocatorScreenshotOptions, 'base64'> & { base64: true }): Promise<{\n    path: string\n    base64: string\n  }>\n  public screenshot(options?: LocatorScreenshotOptions): Promise<string>\n  public screenshot(options?: LocatorScreenshotOptions): Promise<string | {\n    path: string\n    base64: string\n  }> {\n    return page.screenshot({\n      ...options,\n      element: this,\n    })\n  }\n\n  public mark(name: string, options?: MarkOptions): Promise<void> {\n    const currentTest = getWorkerState().current\n    if (!currentTest || !getBrowserState().activeTraceTaskIds.has(currentTest.id)) {\n      return Promise.resolve()\n    }\n    return ensureAwaited(error => getBrowserState().commands.triggerCommand<void>(\n      '__vitest_markTrace',\n      [{\n        name,\n        selector: this.selector,\n        stack: options?.stack ?? error?.stack,\n      }],\n      error,\n    ))\n  }\n\n  protected abstract locator(selector: string): Locator\n  protected abstract elementLocator(element: Element): Locator\n\n  public getByRole(role: string, options?: LocatorByRoleOptions): Locator {\n    return this.locator(getByRoleSelector(role, options))\n  }\n\n  public getByAltText(text: string | RegExp, options?: LocatorOptions): Locator {\n    return this.locator(getByAltTextSelector(text, options))\n  }\n\n  public getByLabelText(text: string | RegExp, options?: LocatorOptions): Locator {\n    return this.locator(getByLabelSelector(text, options))\n  }\n\n  public getByPlaceholder(text: string | RegExp, options?: LocatorOptions): Locator {\n    return this.locator(getByPlaceholderSelector(text, options))\n  }\n\n  public getByTestId(testId: string | RegExp): Locator {\n    return this.locator(getByTestIdSelector(server.config.browser.locators.testIdAttribute, testId))\n  }\n\n  public getByText(text: string | RegExp, options?: LocatorOptions): Locator {\n    return this.locator(getByTextSelector(text, options))\n  }\n\n  public getByTitle(title: string | RegExp, options?: LocatorOptions): Locator {\n    return this.locator(getByTitleSelector(title, options))\n  }\n\n  public filter(filter: LocatorOptions): Locator {\n    const selectors = []\n\n    if (filter?.hasText) {\n      selectors.push(`internal:has-text=${escapeForTextSelector(filter.hasText, false)}`)\n    }\n\n    if (filter?.hasNotText) {\n      selectors.push(`internal:has-not-text=${escapeForTextSelector(filter.hasNotText, false)}`)\n    }\n\n    if (filter?.has) {\n      const locator = filter.has as Locator\n      selectors.push(`internal:has=${JSON.stringify(locator._pwSelector || locator.selector)}`)\n    }\n\n    if (filter?.hasNot) {\n      const locator = filter.hasNot as Locator\n      selectors.push(`internal:has-not=${JSON.stringify(locator._pwSelector || locator.selector)}`)\n    }\n\n    if (!selectors.length) {\n      throw new Error(`Locator.filter expects at least one filter. None provided.`)\n    }\n\n    return this.locator(selectors.join(' >> '))\n  }\n\n  public and(locator: Locator): Locator {\n    return this.locator(`internal:and=${JSON.stringify(locator._pwSelector || locator.selector)}`)\n  }\n\n  public or(locator: Locator): Locator {\n    return this.locator(`internal:or=${JSON.stringify(locator._pwSelector || locator.selector)}`)\n  }\n\n  public query(): HTMLElement | SVGElement | null {\n    const parsedSelector = this._parsedSelector || (this._parsedSelector = selectorEngine.parseSelector(this._pwSelector || this.selector))\n    return selectorEngine.querySelector(parsedSelector, document.documentElement, true) as HTMLElement | SVGElement\n  }\n\n  public element(): HTMLElement | SVGElement {\n    const element = this.query()\n    if (!element) {\n      throw utils.getElementError(this._pwSelector || this.selector, this._container || document.body)\n    }\n    return element\n  }\n\n  public elements(): (HTMLElement | SVGElement)[] {\n    const parsedSelector = this._parsedSelector || (this._parsedSelector = selectorEngine.parseSelector(this._pwSelector || this.selector))\n    return selectorEngine.querySelectorAll(parsedSelector, document.documentElement) as (HTMLElement | SVGElement)[]\n  }\n\n  public get length(): number {\n    return this.elements().length\n  }\n\n  public all(): Locator[] {\n    return this.elements().map(element => this.elementLocator(element))\n  }\n\n  public nth(index: number): Locator {\n    return this.locator(`nth=${index}`)\n  }\n\n  public first(): Locator {\n    return this.nth(0)\n  }\n\n  public last(): Locator {\n    return this.nth(-1)\n  }\n\n  public toString(): string {\n    return this.selector\n  }\n\n  public toJSON(): string {\n    return this.selector\n  }\n\n  public async findElement(options_: SelectorOptions = {}): Promise<HTMLElement | SVGElement> {\n    const options = processTimeoutOptions(options_)\n    const timeout = options?.timeout\n    const strict = options?.strict ?? true\n    const startTime = now()\n    let intervalIndex = 0\n    while (true) {\n      const elements = this.elements()\n      if (elements.length === 1) {\n        return elements[0]\n      }\n      if (elements.length > 1) {\n        if (strict) {\n          throw createStrictModeViolationError(this._pwSelector || this.selector, elements)\n        }\n        return elements[0]\n      }\n      const elapsed = now() - startTime\n      const isLastCall = timeout != null && elapsed >= timeout\n      if (isLastCall) {\n        throw utils.getElementError(this._pwSelector || this.selector, this._container || document.body)\n      }\n      const interval = waitForIntervals[Math.min(intervalIndex++, waitForIntervals.length - 1)]\n      const nextInterval = timeout != null\n        ? Math.min(interval, timeout - elapsed)\n        : interval\n      await sleep(nextInterval)\n    }\n  }\n\n  protected triggerCommand<T>(command: string, ...args: any[]): Promise<T> {\n    if (this._errorSource) {\n      return triggerCommandWithTrace<T>({\n        name: command,\n        arguments: args,\n        errorSource: this._errorSource,\n      })\n    }\n    return ensureAwaited(error => triggerCommandWithTrace<T>({\n      name: command,\n      arguments: args,\n      errorSource: error,\n    }))\n  }\n}\n\nexport function triggerCommandWithTrace<T>(\n  options: {\n    name: string\n    arguments: unknown[]\n    errorSource?: Error | undefined\n  },\n): Promise<T> {\n  return getBrowserState().commands.triggerCommand<T>(\n    options.name,\n    options.arguments,\n    options.errorSource,\n  )\n}\n\nfunction createStrictModeViolationError(\n  selector: string,\n  matches: Element[],\n) {\n  const infos = matches.slice(0, 10).map(m => ({\n    preview: selectorEngine.previewNode(m),\n    selector: selectorEngine.generateSelectorSimple(m),\n  }))\n  const lines = infos.map(\n    (info, i) =>\n      `\\n    ${i + 1}) ${info.preview} aka ${asLocator('javascript', info.selector)}`,\n  )\n  if (infos.length < matches.length) {\n    lines.push('\\n    ...')\n  }\n  return new Error(\n    `strict mode violation: ${asLocator('javascript', selector)} resolved to ${matches.length} elements:${lines.join('')}\\n`,\n  )\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/logger.ts",
    "content": "import { browserFormat } from 'vitest/internal/browser'\nimport { getConfig } from '../utils'\nimport { rpc } from './rpc'\nimport { getBrowserRunner } from './runner'\n\nconst { Date, console, performance } = globalThis\n\nexport function setupConsoleLogSpy(): void {\n  const {\n    log,\n    info,\n    error,\n    dir,\n    dirxml,\n    trace,\n    time,\n    timeEnd,\n    timeLog,\n    warn,\n    debug,\n    count,\n    countReset,\n  } = console\n  console.log = stdout(log)\n  console.debug = stdout(debug)\n  console.info = stdout(info)\n\n  console.error = stderr(error)\n  console.warn = stderr(warn)\n\n  console.dir = (item, options) => {\n    dir(item, options)\n    sendLog('stdout', browserFormat(item))\n  }\n\n  console.dirxml = (...args) => {\n    dirxml(...args)\n    sendLog('stdout', processLog(args))\n  }\n\n  console.trace = (...args: unknown[]) => {\n    trace(...args)\n    const content = processLog(args)\n    const error = new Error('$$Trace')\n    const processor = (globalThis as any).__vitest_worker__?.onFilterStackTrace || ((s: string) => s || '')\n    const stack = processor(error.stack || '')\n    sendLog('stderr', `${content}\\n${stack}`, true)\n  }\n\n  const timeLabels: Record<string, number> = {}\n\n  console.time = (label = 'default') => {\n    time(label)\n    const now = performance.now()\n    timeLabels[label] = now\n  }\n\n  console.timeLog = (label = 'default') => {\n    timeLog(label)\n    if (!(label in timeLabels)) {\n      sendLog('stderr', `Timer \"${label}\" does not exist`)\n    }\n    else {\n      sendLog('stdout', `${label}: ${timeLabels[label]} ms`)\n    }\n  }\n\n  console.timeEnd = (label = 'default') => {\n    timeEnd(label)\n    const end = performance.now()\n    const start = timeLabels[label]\n    if (!(label in timeLabels)) {\n      sendLog('stderr', `Timer \"${label}\" does not exist`)\n    }\n    else if (typeof start !== 'undefined') {\n      const duration = end - start\n      sendLog('stdout', `${label}: ${duration} ms`)\n    }\n  }\n\n  const countLabels: Record<string, number> = {}\n\n  console.count = (label = 'default') => {\n    count(label)\n    const counter = (countLabels[label] ?? 0) + 1\n    countLabels[label] = counter\n    sendLog('stdout', `${label}: ${counter}`)\n  }\n\n  console.countReset = (label = 'default') => {\n    countReset(label)\n    countLabels[label] = 0\n  }\n}\n\nfunction stdout(base: (...args: unknown[]) => void) {\n  return (...args: unknown[]) => {\n    base(...args)\n    // ignore shadow root logs from wdio\n    // https://github.com/webdriverio/webdriverio/discussions/14221\n    if (args[0] === '[WDIO]') {\n      if (args[1] === 'newShadowRoot' || args[1] === 'removeShadowRoot') {\n        return\n      }\n    }\n    sendLog('stdout', processLog(args))\n  }\n}\nfunction stderr(base: (...args: unknown[]) => void) {\n  return (...args: unknown[]) => {\n    base(...args)\n    sendLog('stderr', processLog(args))\n  }\n}\n\nfunction processLog(args: unknown[]) {\n  return browserFormat(...args)\n}\n\nfunction sendLog(\n  type: 'stdout' | 'stderr',\n  content: string,\n  disableStack?: boolean,\n) {\n  if (content.startsWith('[vite]')) {\n    return\n  }\n  const unknownTestId = '__vitest__unknown_test__'\n  // @ts-expect-error untyped global\n  const taskId = globalThis.__vitest_worker__?.current?.id ?? unknownTestId\n  const origin\n    = getConfig().printConsoleTrace && !disableStack\n      ? new Error('STACK_TRACE').stack?.split('\\n').slice(1).join('\\n')\n      : undefined\n  const runner = getBrowserRunner()\n  rpc().sendLog(runner?.method || 'run', {\n    origin,\n    content,\n    browser: true,\n    time: Date.now(),\n    taskId,\n    type,\n    size: content.length,\n  })\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/mocker-interceptor.ts",
    "content": "import type { ModuleMockerInterceptor } from '@vitest/mocker/browser'\nimport type { BrowserRPC } from '../client'\nimport { getBrowserState, getWorkerState } from '../utils'\n\nexport function createModuleMockerInterceptor(): ModuleMockerInterceptor {\n  return {\n    async register(module) {\n      const state = getBrowserState()\n      await rpc().registerMock(state.sessionId, module.toJSON())\n    },\n    async delete(id) {\n      const state = getBrowserState()\n      await rpc().unregisterMock(state.sessionId, id)\n    },\n    async invalidate() {\n      const state = getBrowserState()\n      await rpc().clearMocks(state.sessionId)\n    },\n  }\n}\n\nexport function rpc(): BrowserRPC {\n  return getWorkerState().rpc as any as BrowserRPC\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/mocker.ts",
    "content": "import { ModuleMocker } from '@vitest/mocker/browser'\nimport { getBrowserState } from '../utils'\n\nexport class VitestBrowserClientMocker extends ModuleMocker {\n  // default \"vi\" utility tries to access mock context to avoid circular dependencies\n  public getMockContext() {\n    return { callstack: null }\n  }\n\n  public override wrapDynamicImport<T>(moduleFactory: () => Promise<T>): Promise<T> {\n    return getBrowserState().wrapModule(moduleFactory)\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/rpc.ts",
    "content": "import type { VitestBrowserClient } from '@vitest/browser/client'\nimport { getSafeTimers } from 'vitest/internal/browser'\n\nconst { get } = Reflect\n\nfunction withSafeTimers(getTimers: typeof getSafeTimers, fn: () => void) {\n  const { setTimeout, clearTimeout } = getTimers()\n\n  const currentSetTimeout = globalThis.setTimeout\n  const currentClearTimeout = globalThis.clearTimeout\n\n  try {\n    globalThis.setTimeout = setTimeout\n    globalThis.clearTimeout = clearTimeout\n\n    const result = fn()\n    return result\n  }\n  finally {\n    globalThis.setTimeout = currentSetTimeout\n    globalThis.clearTimeout = currentClearTimeout\n  }\n}\n\nconst promises = new Set<Promise<unknown>>()\n\nexport async function rpcDone(): Promise<unknown[] | undefined> {\n  if (!promises.size) {\n    return\n  }\n  const awaitable = Array.from(promises)\n  return Promise.all(awaitable)\n}\n\nexport function createSafeRpc(\n  client: VitestBrowserClient,\n): VitestBrowserClient['rpc'] {\n  return new Proxy(client.rpc, {\n    get(target, p, handler) {\n      if (p === 'then') {\n        return\n      }\n      const sendCall = get(target, p, handler)\n      const safeSendCall = (...args: any[]) =>\n        withSafeTimers(getSafeTimers, async () => {\n          const result = sendCall(...args)\n          promises.add(result)\n          try {\n            return await result\n          }\n          finally {\n            promises.delete(result)\n          }\n        })\n      safeSendCall.asEvent = sendCall.asEvent\n      return safeSendCall\n    },\n  })\n}\n\nexport function rpc(): VitestBrowserClient['rpc'] {\n  // @ts-expect-error not typed global\n  return globalThis.__vitest_worker__.rpc\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/runner.ts",
    "content": "import type {\n  CancelReason,\n  File,\n  Suite,\n  Task,\n  TaskEventPack,\n  TaskResultPack,\n  Test,\n  TestAnnotation,\n  TestArtifact,\n  VitestRunner,\n} from '@vitest/runner'\nimport type { SerializedConfig, TestExecutionMethod, WorkerGlobalState } from 'vitest'\nimport type {\n  Traces,\n} from 'vitest/internal/browser'\nimport type { VitestBrowserClientMocker } from './mocker'\nimport type { CommandsManager } from './tester-utils'\nimport { globalChannel, onCancel } from '@vitest/browser/client'\nimport { getTestName } from '@vitest/runner/utils'\nimport { BenchmarkRunner, recordArtifact, TestRunner } from 'vitest'\nimport { page, userEvent } from 'vitest/browser'\nimport {\n  DecodedMap,\n  getOriginalPosition,\n  loadDiffConfig,\n  loadSnapshotSerializers,\n  takeCoverageInsideWorker,\n} from 'vitest/internal/browser'\nimport { createStackString, parseStacktrace } from '../../../../utils/src/source-map'\nimport { getBrowserState, getWorkerState, moduleRunner } from '../utils'\nimport { rpc } from './rpc'\nimport { VitestBrowserSnapshotEnvironment } from './snapshot'\n\ninterface BrowserRunnerOptions {\n  config: SerializedConfig\n}\n\nexport const browserHashMap: Map<string, string> = new Map()\n\ninterface CoverageHandler {\n  takeCoverage: () => Promise<unknown>\n}\n\ninterface BrowserVitestRunner extends VitestRunner {\n  sourceMapCache: Map<string, any>\n  method: TestExecutionMethod\n  setMethod: (method: TestExecutionMethod) => void\n}\n\nexport function createBrowserRunner(\n  runnerClass: { new (config: SerializedConfig): VitestRunner },\n  mocker: VitestBrowserClientMocker,\n  state: WorkerGlobalState,\n  coverageModule: CoverageHandler | null,\n): { new (options: BrowserRunnerOptions): BrowserVitestRunner } {\n  return class BrowserTestRunner extends runnerClass implements VitestRunner {\n    public config: SerializedConfig\n    hashMap = browserHashMap\n    public sourceMapCache = new Map<string, any>()\n    public method = 'run' as TestExecutionMethod\n    private commands: CommandsManager\n    private _otel!: Traces\n\n    constructor(options: BrowserRunnerOptions) {\n      super(options.config)\n      this.config = options.config\n      this.commands = getBrowserState().commands\n      this.viteEnvironment = '__browser__'\n      this._otel = getBrowserState().traces\n    }\n\n    setMethod(method: TestExecutionMethod) {\n      this.method = method\n    }\n\n    private traces = new Map<string, string[]>()\n\n    onBeforeTryTask: VitestRunner['onBeforeTryTask'] = async (...args) => {\n      await userEvent.cleanup()\n      await super.onBeforeTryTask?.(...args)\n      const trace = this.config.browser.trace\n      const test = args[0]\n      const { retry, repeats } = args[1]\n      const shouldTrace = trace !== 'off'\n        && !(trace === 'on-all-retries' && retry === 0)\n        && !(trace === 'on-first-retry' && retry !== 1)\n      if (!shouldTrace) {\n        getBrowserState().activeTraceTaskIds.delete(test.id)\n        return\n      }\n      getBrowserState().activeTraceTaskIds.add(test.id)\n      let title = getTestName(test)\n      if (retry) {\n        title += ` (retry x${retry})`\n      }\n      if (repeats) {\n        title += ` (repeat x${repeats})`\n      }\n\n      const name = getTraceName(test, retry, repeats)\n      await this.commands.triggerCommand(\n        '__vitest_startChunkTrace',\n        [{ name, title }],\n      )\n    }\n\n    onAfterRetryTask = async (test: Test, { retry, repeats }: { retry: number; repeats: number }) => {\n      if (!getBrowserState().activeTraceTaskIds.has(test.id)) {\n        return\n      }\n      await this.commands.triggerCommand('__vitest_markTrace', [{\n        name: `onAfterRetryTask [${test.result?.state}]`,\n        stack: test.result?.errors?.[0].stack,\n      }])\n      const name = getTraceName(test, retry, repeats)\n      if (!this.traces.has(test.id)) {\n        this.traces.set(test.id, [])\n      }\n      const traces = this.traces.get(test.id)!\n      const { tracePath } = await this.commands.triggerCommand(\n        '__vitest_stopChunkTrace',\n        [{ name }],\n      ) as { tracePath: string }\n      traces.push(tracePath)\n    }\n\n    onAfterRunTask = async (task: Test) => {\n      await super.onAfterRunTask?.(task)\n      const trace = this.config.browser.trace\n      const traces = this.traces.get(task.id) || []\n      if (traces.length) {\n        if (trace === 'retain-on-failure' && task.result?.state === 'pass') {\n          await this.commands.triggerCommand(\n            '__vitest_deleteTracing',\n            [{ traces }],\n          )\n        }\n        else {\n          await this.commands.triggerCommand(\n            '__vitest_annotateTraces',\n            [{ testId: task.id, traces }],\n          )\n        }\n      }\n\n      if (this.config.bail && task.result?.state === 'fail') {\n        const previousFailures = await rpc().getCountOfFailedTests()\n        const currentFailures = 1 + previousFailures\n\n        if (currentFailures >= this.config.bail) {\n          rpc().cancelCurrentRun('test-failure')\n          this.cancel('test-failure')\n        }\n      }\n    }\n\n    onTaskFinished = async (task: Task) => {\n      if (\n        this.config.browser.screenshotFailures\n        && document.body.clientHeight > 0\n        && task.result?.state === 'fail'\n        && task.type === 'test'\n        && task.artifacts.every(\n          artifact => artifact.type !== 'internal:toMatchScreenshot',\n        )\n      ) {\n        const screenshot = await page.screenshot({\n          timeout: this.config.browser.providerOptions?.actionTimeout ?? 5_000,\n        } as any /** TODO */).catch((err) => {\n          console.error('[vitest] Failed to take a screenshot', err)\n        })\n        if (screenshot) {\n          await recordArtifact(task, {\n            type: 'internal:failureScreenshot',\n            attachments: [{ contentType: 'image/png', path: screenshot, originalPath: screenshot }],\n          } as const)\n        }\n      }\n    }\n\n    cancel = (reason: CancelReason) => {\n      super.cancel?.(reason)\n      globalChannel.postMessage({ type: 'cancel', reason })\n    }\n\n    onBeforeRunSuite = async (suite: Suite | File) => {\n      await Promise.all([\n        super.onBeforeRunSuite?.(suite),\n        (async () => {\n          if (!('filepath' in suite)) {\n            return\n          }\n          const map = await rpc().getBrowserFileSourceMap(suite.filepath)\n          this.sourceMapCache.set(suite.filepath, map)\n          const snapshotEnvironment = this.config.snapshotOptions.snapshotEnvironment\n          if (snapshotEnvironment instanceof VitestBrowserSnapshotEnvironment) {\n            snapshotEnvironment.addSourceMap(suite.filepath, map)\n          }\n        })(),\n      ])\n    }\n\n    onAfterRunFiles = async (files: File[]) => {\n      const [coverage] = await Promise.all([\n        coverageModule?.takeCoverage?.(),\n        mocker.invalidate(),\n        super.onAfterRunFiles?.(files),\n      ])\n\n      if (coverage) {\n        await rpc().onAfterSuiteRun({\n          coverage,\n          testFiles: files.map(file => file.name),\n          environment: '__browser__',\n          projectName: this.config.name,\n        })\n      }\n    }\n\n    onCollectStart = (file: File) => {\n      return rpc().onQueued(this.method, file)\n    }\n\n    onCollected = async (files: File[]): Promise<unknown> => {\n      files.forEach((file) => {\n        file.prepareDuration = state.durations.prepare\n        file.environmentLoad = state.durations.environment\n        // should be collected only for a single test file in a batch\n        state.durations.prepare = 0\n        state.durations.environment = 0\n      })\n\n      if (this.config.includeTaskLocation) {\n        try {\n          await updateTestFilesLocations(files, this.sourceMapCache)\n        }\n        catch {}\n      }\n      return rpc().onCollected(this.method, files)\n    }\n\n    onTestAnnotate = (test: Test, annotation: TestAnnotation): Promise<TestAnnotation> => {\n      const artifact: TestArtifact = { type: 'internal:annotation', annotation, location: annotation.location }\n\n      return this.onTestArtifactRecord(test, artifact).then(({ annotation }) => annotation)\n    }\n\n    onTestArtifactRecord = <Artifact extends TestArtifact>(test: Test, artifact: Artifact): Promise<Artifact> => {\n      if (artifact.location) {\n        // the file should be the test file\n        // tests from other files are not supported\n        const map = this.sourceMapCache.get(artifact.location.file)\n\n        if (!map) {\n          return rpc().onTaskArtifactRecord(test.id, artifact)\n        }\n\n        const traceMap = new DecodedMap(map as any, artifact.location.file)\n        const position = getOriginalPosition(traceMap, artifact.location)\n\n        if (position) {\n          const { source, column, line } = position\n          const file = source || artifact.location.file\n          artifact.location = {\n            line,\n            column: column + 1,\n            // if the file path is on windows, we need to remove the starting slash\n            file: file.match(/\\/\\w:\\//) ? file.slice(1) : file,\n          }\n\n          if (artifact.type === 'internal:annotation') {\n            artifact.annotation.location = artifact.location\n          }\n        }\n      }\n\n      return rpc().onTaskArtifactRecord(test.id, artifact)\n    }\n\n    onTaskUpdate = (task: TaskResultPack[], events: TaskEventPack[]): Promise<void> => {\n      return rpc().onTaskUpdate(this.method, task, events)\n    }\n\n    importFile = async (filepath: string, mode: 'collect' | 'setup') => {\n      let hash = this.hashMap.get(filepath)\n\n      // if the mode is setup, we need to re-evaluate the setup file on each test run\n      if (mode === 'setup' || !hash) {\n        hash = Date.now().toString()\n        this.hashMap.set(filepath, hash)\n      }\n\n      // on Windows we need the unit to resolve the test file\n      const prefix = `/${/^\\w:/.test(filepath) ? '@fs/' : ''}`\n      const query = `browserv=${hash}`\n      const importpath = `${prefix}${filepath}?${query}`.replace(/\\/+/g, '/')\n      // start tracing before the test file is imported\n      const trace = this.config.browser.trace\n      if (mode === 'collect' && trace !== 'off') {\n        await this.commands.triggerCommand('__vitest_startTracing', [])\n      }\n      try {\n        await import(/* @vite-ignore */ importpath)\n      }\n      catch (err) {\n        throw new Error(`Failed to import test file ${filepath}`, { cause: err })\n      }\n    }\n\n    trace = <T>(name: string, attributes: Record<string, any> | (() => T), cb?: () => T): T => {\n      const options: import('@opentelemetry/api').SpanOptions = typeof attributes === 'object' ? { attributes } : {}\n      return this._otel.$(`vitest.test.runner.${name}`, options, cb || attributes as () => T)\n    }\n  }\n}\n\nlet cachedRunner: BrowserVitestRunner | null = null\n\nexport function getBrowserRunner(): BrowserVitestRunner | null {\n  return cachedRunner\n}\n\nexport async function initiateRunner(\n  state: WorkerGlobalState,\n  mocker: VitestBrowserClientMocker,\n  config: SerializedConfig,\n): Promise<BrowserVitestRunner> {\n  if (cachedRunner) {\n    return cachedRunner\n  }\n  const runnerClass\n    = config.mode === 'test' ? TestRunner : BenchmarkRunner\n\n  const BrowserRunner = createBrowserRunner(runnerClass, mocker, state, {\n    takeCoverage: () =>\n      takeCoverageInsideWorker(config.coverage, moduleRunner),\n  })\n  if (!config.snapshotOptions.snapshotEnvironment) {\n    config.snapshotOptions.snapshotEnvironment = new VitestBrowserSnapshotEnvironment()\n  }\n  const runner = new BrowserRunner({\n    config,\n  })\n  cachedRunner = runner\n\n  onCancel((reason) => {\n    runner.cancel?.(reason)\n  })\n\n  const [diffOptions] = await Promise.all([\n    loadDiffConfig(config, moduleRunner as any),\n    loadSnapshotSerializers(config, moduleRunner as any),\n  ])\n  runner.config.diffOptions = diffOptions\n  getWorkerState().onFilterStackTrace = (stack: string) => {\n    const stacks = parseStacktrace(stack, {\n      getSourceMap(file) {\n        return runner.sourceMapCache.get(file)\n      },\n    })\n    return createStackString(stacks)\n  }\n  return runner\n}\n\nasync function getTraceMap(file: string, sourceMaps: Map<string, any>) {\n  const result = sourceMaps.get(file) || await rpc().getBrowserFileSourceMap(file).then((map) => {\n    sourceMaps.set(file, map)\n    return map\n  })\n  if (!result) {\n    return null\n  }\n  return new DecodedMap(result as any, file)\n}\n\nasync function updateTestFilesLocations(files: File[], sourceMaps: Map<string, any>) {\n  const promises = files.map(async (file) => {\n    const traceMap = await getTraceMap(file.filepath, sourceMaps)\n    if (!traceMap) {\n      return null\n    }\n    const updateLocation = (task: Task) => {\n      if (task.location) {\n        const position = getOriginalPosition(traceMap, task.location)\n        if (position) {\n          const { line, column } = position\n          task.location = { line, column: task.each ? column : column + 1 }\n        }\n      }\n      if ('tasks' in task) {\n        task.tasks.forEach(updateLocation)\n      }\n    }\n    file.tasks.forEach(updateLocation)\n    return null\n  })\n\n  await Promise.all(promises)\n}\n\nfunction getTraceName(task: Task, retryCount: number, repeatsCount: number) {\n  const name = getTestName(task, '-').replace(/[^a-z0-9]/gi, '-')\n  return `${name}-${repeatsCount}-${retryCount}`\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/snapshot.ts",
    "content": "import type { VitestBrowserClient } from '@vitest/browser/client'\nimport type { ParsedStack } from 'vitest/internal/browser'\nimport type { SnapshotEnvironment } from 'vitest/runtime'\nimport { DecodedMap, getOriginalPosition } from 'vitest/internal/browser'\n\nexport class VitestBrowserSnapshotEnvironment implements SnapshotEnvironment {\n  private sourceMaps = new Map<string, any>()\n  private traceMaps = new Map<string, DecodedMap>()\n\n  public addSourceMap(filepath: string, map: any): void {\n    this.sourceMaps.set(filepath, map)\n  }\n\n  getVersion(): string {\n    return '1'\n  }\n\n  getHeader(): string {\n    return `// Vitest Snapshot v${this.getVersion()}, https://vitest.dev/guide/snapshot.html`\n  }\n\n  readSnapshotFile(filepath: string): Promise<string | null> {\n    return rpc().readSnapshotFile(filepath)\n  }\n\n  saveSnapshotFile(filepath: string, snapshot: string): Promise<void> {\n    return rpc().saveSnapshotFile(filepath, snapshot)\n  }\n\n  resolvePath(filepath: string): Promise<string> {\n    return rpc().resolveSnapshotPath(filepath)\n  }\n\n  resolveRawPath(testPath: string, rawPath: string): Promise<string> {\n    return rpc().resolveSnapshotRawPath(testPath, rawPath)\n  }\n\n  removeSnapshotFile(filepath: string): Promise<void> {\n    return rpc().removeSnapshotFile(filepath)\n  }\n\n  processStackTrace(stack: ParsedStack): ParsedStack {\n    const map = this.sourceMaps.get(stack.file)\n    if (!map) {\n      return stack\n    }\n    let traceMap = this.traceMaps.get(stack.file)\n    if (!traceMap) {\n      traceMap = new DecodedMap(map, stack.file)\n      this.traceMaps.set(stack.file, traceMap)\n    }\n    const position = getOriginalPosition(traceMap, stack)\n    if (position) {\n      return { ...stack, line: position.line, column: position.column }\n    }\n    return stack\n  }\n}\n\nfunction rpc(): VitestBrowserClient['rpc'] {\n  // @ts-expect-error not typed global\n  return globalThis.__vitest_worker__.rpc\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/state.ts",
    "content": "import type { BrowserRPC } from '@vitest/browser/client'\nimport type { WorkerGlobalState } from 'vitest'\nimport { EvaluatedModules } from 'vite/module-runner'\nimport { getBrowserState } from '../utils'\n\nconst config = getBrowserState().config\nconst sessionId = getBrowserState().sessionId\n\nconst state: WorkerGlobalState = {\n  ctx: {\n    rpc: null as any,\n    pool: 'browser',\n    workerId: 1,\n    config,\n    projectName: config.name || '',\n    files: [],\n    environment: {\n      name: 'browser',\n      options: null,\n    },\n    // this is populated before tests run\n    providedContext: {},\n    invalidates: [],\n  },\n  onCancel: null as any,\n  config,\n  environment: {\n    name: 'browser',\n    viteEnvironment: 'client',\n    setup() {\n      throw new Error('Not called in the browser')\n    },\n  },\n  onCleanup: fn => getBrowserState().cleanups.push(fn),\n  evaluatedModules: new EvaluatedModules(),\n  resolvingModules: new Set(),\n  moduleExecutionInfo: new Map(),\n  metaEnv: null as any,\n  rpc: null as any,\n  durations: {\n    environment: 0,\n    prepare: performance.now(),\n  },\n  providedContext: {},\n}\n\n// @ts-expect-error not typed global\nglobalThis.__vitest_browser__ = true\n// @ts-expect-error not typed global\nglobalThis.__vitest_worker__ = state\n\ngetBrowserState().cdp = createCdp()\n\nfunction rpc() {\n  return state.rpc as any as BrowserRPC\n}\n\nfunction createCdp() {\n  const listenersMap = new WeakMap<Function, string>()\n\n  function getId(listener: Function) {\n    const id = listenersMap.get(listener) || crypto.randomUUID()\n    listenersMap.set(listener, id)\n    return id\n  }\n\n  const listeners: Record<string, Function[]> = {}\n\n  const cdp = {\n    send(method: string, params?: Record<string, any>) {\n      return rpc().sendCdpEvent(sessionId, method, params)\n    },\n    on(event: string, listener: (payload: any) => void) {\n      const listenerId = getId(listener)\n      listeners[event] = listeners[event] || []\n      listeners[event].push(listener)\n      rpc().trackCdpEvent(sessionId, 'on', event, listenerId).catch(error)\n      return cdp\n    },\n    once(event: string, listener: (payload: any) => void) {\n      const listenerId = getId(listener)\n      const handler = (data: any) => {\n        listener(data)\n        cdp.off(event, listener)\n      }\n      listeners[event] = listeners[event] || []\n      listeners[event].push(handler)\n      rpc().trackCdpEvent(sessionId, 'once', event, listenerId).catch(error)\n      return cdp\n    },\n    off(event: string, listener: (payload: any) => void) {\n      const listenerId = getId(listener)\n      if (listeners[event]) {\n        listeners[event] = listeners[event].filter(l => l !== listener)\n      }\n      rpc().trackCdpEvent(sessionId, 'off', event, listenerId).catch(error)\n      return cdp\n    },\n    emit(event: string, payload: unknown) {\n      if (listeners[event]) {\n        listeners[event].forEach((l) => {\n          try {\n            l(payload)\n          }\n          catch (err) {\n            error(err)\n          }\n        })\n      }\n    },\n  }\n\n  return cdp\n}\n\nfunction error(err: unknown) {\n  window.dispatchEvent(new ErrorEvent('error', { error: err }))\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/tester-utils.ts",
    "content": "import type { Locator, SelectorOptions, UserEventWheelDeltaOptions, UserEventWheelOptions } from 'vitest/browser'\nimport type { BrowserRPC } from '../client'\nimport { getBrowserState, getWorkerState } from '../utils'\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function convertElementToCssSelector(element: Element): string {\n  if (!element || !(element instanceof Element)) {\n    throw new Error(\n      `Expected DOM element to be an instance of Element, received ${typeof element}`,\n    )\n  }\n\n  return getUniqueCssSelector(element)\n}\n\nfunction escapeIdForCSSSelector(id: string) {\n  return id\n    .split('')\n    .map((char) => {\n      const code = char.charCodeAt(0)\n\n      if (char === ' ' || char === '#' || char === '.' || char === ':' || char === '[' || char === ']' || char === '>' || char === '+' || char === '~' || char === '\\\\') {\n        // Escape common special characters with backslashes\n        return `\\\\${char}`\n      }\n      else if (code >= 0x10000) {\n        // Unicode escape for characters outside the BMP\n        return `\\\\${code.toString(16).toUpperCase().padStart(6, '0')} `\n      }\n      else if (code < 0x20 || code === 0x7F) {\n        // Non-printable ASCII characters (0x00-0x1F and 0x7F) are escaped\n        return `\\\\${code.toString(16).toUpperCase().padStart(2, '0')} `\n      }\n      else if (code >= 0x80) {\n        // Non-ASCII characters (0x80 and above) are escaped\n        return `\\\\${code.toString(16).toUpperCase().padStart(2, '0')} `\n      }\n      else {\n        // Allowable characters are used directly\n        return char\n      }\n    })\n    .join('')\n}\n\nfunction getUniqueCssSelector(el: Element) {\n  const path = []\n  let parent: null | ParentNode\n  let hasShadowRoot = false\n  // eslint-disable-next-line no-cond-assign\n  while (parent = getParent(el)) {\n    if ((parent as Element).shadowRoot) {\n      hasShadowRoot = true\n    }\n\n    const tag = el.tagName\n    if (el.id) {\n      path.push(`#${escapeIdForCSSSelector(el.id)}`)\n    }\n    else if (!el.nextElementSibling && !el.previousElementSibling) {\n      path.push(tag.toLowerCase())\n    }\n    else {\n      let index = 0\n      let sameTagSiblings = 0\n      let elementIndex = 0\n\n      for (const sibling of parent.children) {\n        index++\n        if (sibling.tagName === tag) {\n          sameTagSiblings++\n        }\n        if (sibling === el) {\n          elementIndex = index\n        }\n      }\n\n      if (sameTagSiblings > 1) {\n        path.push(`${tag.toLowerCase()}:nth-child(${elementIndex})`)\n      }\n      else {\n        path.push(tag.toLowerCase())\n      }\n    }\n    el = parent as Element\n  };\n  return `${getBrowserState().provider === 'webdriverio' && hasShadowRoot ? '>>>' : ''}${path.reverse().join(' > ')}`\n}\n\nfunction getParent(el: Element) {\n  const parent = el.parentNode\n  if (parent instanceof ShadowRoot) {\n    return parent.host\n  }\n  return parent\n}\n\nconst ACTION_TRACE_COMMANDS = new Set([\n  '__vitest_click',\n  '__vitest_dblClick',\n  '__vitest_tripleClick',\n  '__vitest_wheel',\n  '__vitest_type',\n  '__vitest_clear',\n  '__vitest_fill',\n  '__vitest_selectOptions',\n  '__vitest_dragAndDrop',\n  '__vitest_hover',\n  '__vitest_upload',\n  '__vitest_tab',\n  '__vitest_keyboard',\n  '__vitest_takeScreenshot',\n])\n\nexport class CommandsManager {\n  private _listeners: ((command: string, args: any[]) => void)[] = []\n\n  public onCommand(listener: (command: string, args: any[]) => void): void {\n    this._listeners.push(listener)\n  }\n\n  public async triggerCommand<T>(\n    command: string,\n    args: any[],\n    // error makes sure the stack trace is correct on webkit,\n    // if we make the error here, it looses the context\n    clientError: Error = new Error('empty'),\n  ): Promise<T> {\n    const state = getWorkerState()\n    const rpc = state.rpc as any as BrowserRPC\n    const { sessionId, traces } = getBrowserState()\n    const filepath = state.filepath || state.current?.file?.filepath\n    args = args.filter(arg => arg !== undefined) // remove optional fields\n\n    const actionTraceGroupName = ACTION_TRACE_COMMANDS.has(command) ? command : undefined\n    const currentTest = getWorkerState().current\n    const shouldMarkTrace = actionTraceGroupName\n      && !!currentTest\n      && getBrowserState().activeTraceTaskIds.has(currentTest.id)\n\n    if (this._listeners.length) {\n      await Promise.all(this._listeners.map(listener => listener(command, args)))\n    }\n    return traces.$(\n      'vitest.browser.tester.command',\n      {\n        attributes: {\n          'vitest.browser.command': command,\n          'code.file.path': filepath,\n        },\n      },\n      async () => {\n        if (shouldMarkTrace) {\n          await rpc.triggerCommand<void>(\n            sessionId,\n            '__vitest_groupTraceStart',\n            filepath,\n            [{\n              name: actionTraceGroupName,\n              stack: clientError.stack,\n            }],\n          )\n        }\n        try {\n          return await rpc.triggerCommand<T>(sessionId, command, filepath, args)\n        }\n        catch (err: any) {\n          // rethrow an error to keep the stack trace in browser\n          clientError.message = err.message\n          clientError.name = err.name\n          clientError.stack = clientError.stack?.replace(clientError.message, err.message)\n          throw clientError\n        }\n        finally {\n          if (shouldMarkTrace) {\n            await rpc.triggerCommand<void>(\n              sessionId,\n              '__vitest_groupTraceEnd',\n              filepath,\n              [],\n            )\n          }\n        }\n      },\n    )\n  }\n}\n\nconst now = globalThis.performance\n  ? globalThis.performance.now.bind(globalThis.performance)\n  : Date.now\n\nexport function processTimeoutOptions<T extends { timeout?: number }>(options_: T | undefined): T | undefined {\n  if (\n    // if timeout is set, keep it\n    (options_ && options_.timeout != null)\n  ) {\n    return options_\n  }\n  // if there is a default action timeout, use it\n  if (getWorkerState().config.browser.providerOptions.actionTimeout != null) {\n    return options_\n  }\n  const runner = getBrowserState().runner\n  const startTime = runner._currentTaskStartTime\n  // ignore timeout if this is called outside of a test\n  if (!startTime) {\n    return options_\n  }\n  const timeout = runner._currentTaskTimeout\n  if (timeout === 0 || timeout == null || timeout === Number.POSITIVE_INFINITY) {\n    return options_\n  }\n  options_ = options_ || {} as T\n  const currentTime = now()\n  const endTime = startTime + timeout\n  const remainingTime = Math.floor(endTime - currentTime)\n  if (remainingTime <= 0) {\n    return options_\n  }\n  // give us some time to process the timeout\n  options_.timeout = remainingTime - 100\n  return options_\n}\n\nexport function getIframeScale(): number {\n  const testerUi = window.parent.document.querySelector(`iframe[data-vitest]`)?.parentElement\n  if (!testerUi) {\n    throw new Error(`Cannot find Tester element. This is a bug in Vitest. Please, open a new issue with reproduction.`)\n  }\n  const scaleAttribute = testerUi.getAttribute('data-scale')\n  const scale = Number(scaleAttribute)\n  if (Number.isNaN(scale)) {\n    throw new TypeError(`Cannot parse scale value from Tester element (${scaleAttribute}). This is a bug in Vitest. Please, open a new issue with reproduction.`)\n  }\n  return scale\n}\n\nfunction escapeRegexForSelector(re: RegExp): string {\n  // Unicode mode does not allow \"identity character escapes\", so we do not escape and\n  // hope that it does not contain quotes and/or >> signs.\n  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Character_escape\n  // TODO: rework RE usages in internal selectors away from literal representation to json, e.g. {source,flags}.\n  if (re.unicode || (re as any).unicodeSets) {\n    return String(re)\n  }\n  // Even number of backslashes followed by the quote -> insert a backslash.\n  return String(re).replace(/(^|[^\\\\])(\\\\\\\\)*([\"'`])/g, '$1$2\\\\$3').replace(/>>/g, '\\\\>\\\\>')\n}\n\nexport function escapeForTextSelector(text: string | RegExp, exact: boolean): string {\n  if (typeof text !== 'string') {\n    return escapeRegexForSelector(text)\n  }\n  return `${JSON.stringify(text)}${exact ? 's' : 'i'}`\n}\n\nconst provider = getBrowserState().provider\nconst kElementLocator = Symbol.for('$$vitest:locator-resolved')\n\nexport async function convertToSelector(elementOrLocator: Element | Locator, options?: SelectorOptions): Promise<string> {\n  if (!elementOrLocator) {\n    throw new Error('Expected element or locator to be defined.')\n  }\n  if (elementOrLocator instanceof Element) {\n    return convertElementToCssSelector(elementOrLocator)\n  }\n  if (isLocator(elementOrLocator)) {\n    if (provider === 'playwright' || kElementLocator in elementOrLocator) {\n      return elementOrLocator.selector\n    }\n    const element = await elementOrLocator.findElement(options)\n    return convertElementToCssSelector(element)\n  }\n  throw new Error('Expected element or locator to be an instance of Element or Locator.')\n}\n\nconst kLocator = Symbol.for('$$vitest:locator')\n\nexport function isLocator(element: unknown): element is Locator {\n  return (!!element && typeof element === 'object' && kLocator in element)\n}\n\nconst DEFAULT_WHEEL_DELTA = 100\n\nexport function resolveUserEventWheelOptions(options: UserEventWheelOptions): UserEventWheelDeltaOptions {\n  let delta: UserEventWheelDeltaOptions['delta']\n\n  if (options.delta) {\n    delta = options.delta\n  }\n  else {\n    switch (options.direction) {\n      case 'up': {\n        delta = { y: -DEFAULT_WHEEL_DELTA }\n        break\n      }\n\n      case 'down': {\n        delta = { y: DEFAULT_WHEEL_DELTA }\n        break\n      }\n\n      case 'left': {\n        delta = { x: -DEFAULT_WHEEL_DELTA }\n        break\n      }\n\n      case 'right': {\n        delta = { x: DEFAULT_WHEEL_DELTA }\n        break\n      }\n    }\n  }\n\n  return {\n    delta,\n    times: options.times,\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/client/tester/tester.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"{__VITEST_FAVICON__}\" type=\"image/svg+xml\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vitest Browser Tester</title>\n  </head>\n  <body>\n    <script type=\"module\" src=\"./tester.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/browser/src/client/tester/tester.ts",
    "content": "import type { BrowserRPC, IframeChannelEvent } from '@vitest/browser/client'\nimport type { FileSpecification } from '@vitest/runner'\nimport { channel, client, onCancel } from '@vitest/browser/client'\nimport { parse } from 'flatted'\nimport { page, server, userEvent } from 'vitest/browser'\nimport {\n  collectTests,\n  setupCommonEnv,\n  SpyModule,\n  startCoverageInsideWorker,\n  startTests,\n  stopCoverageInsideWorker,\n  Traces,\n} from 'vitest/internal/browser'\nimport { getBrowserState, getConfig, getWorkerState, moduleRunner } from '../utils'\nimport { setupDialogsSpy } from './dialog'\nimport { setupConsoleLogSpy } from './logger'\nimport { VitestBrowserClientMocker } from './mocker'\nimport { createModuleMockerInterceptor } from './mocker-interceptor'\nimport { createSafeRpc } from './rpc'\nimport { browserHashMap, initiateRunner } from './runner'\nimport { CommandsManager } from './tester-utils'\n\nconst debugVar = getConfig().env.VITEST_BROWSER_DEBUG\nconst debug = debugVar && debugVar !== 'false'\n  ? (...args: unknown[]) => client.rpc.debug?.(...args.map(String))\n  : undefined\n\nconst otelConfig = getConfig().experimental.openTelemetry\nconst traces = new Traces({\n  enabled: !!(otelConfig?.enabled && otelConfig?.browserSdkPath),\n  sdkPath: `/@fs/${otelConfig?.browserSdkPath}`,\n})\nlet rootTesterSpan: ReturnType<Traces['startContextSpan']> | undefined\ngetBrowserState().traces = traces\n\nchannel.addEventListener('message', async (e) => {\n  await client.waitForConnection()\n\n  const data = e.data\n  debug?.('event from orchestrator', JSON.stringify(e.data))\n\n  if (!isEvent(data)) {\n    const error = new Error(`Unknown message: ${JSON.stringify(e.data)}`)\n    unhandledError(error, 'Unknown Iframe Message')\n    return\n  }\n\n  // ignore events to other iframes\n  if (!('iframeId' in data) || data.iframeId !== getBrowserState().iframeId) {\n    return\n  }\n\n  switch (data.event) {\n    case 'execute': {\n      const { method, files, context } = data\n      const state = getWorkerState()\n      const parsedContext = parse(context)\n\n      state.ctx.providedContext = parsedContext\n      state.providedContext = parsedContext\n\n      if (method === 'collect') {\n        await executeTests('collect', files).catch(err => unhandledError(err, 'Collect Error'))\n      }\n      else {\n        await executeTests('run', files).catch(err => unhandledError(err, 'Run Error'))\n      }\n      break\n    }\n    case 'cleanup': {\n      await cleanup().catch(err => unhandledError(err, 'Cleanup Error'))\n      rootTesterSpan?.span.end()\n      await traces.finish()\n      break\n    }\n    case 'prepare': {\n      await traces.waitInit()\n      const tracesContext = traces.getContextFromCarrier(data.otelCarrier)\n      traces.recordInitSpan(tracesContext)\n      rootTesterSpan = traces.startContextSpan(\n        `vitest.browser.tester.run`,\n        tracesContext,\n      )\n      traces.bind(rootTesterSpan.context)\n      await prepare(data).catch(err => unhandledError(err, 'Prepare Error'))\n      break\n    }\n    case 'viewport:done':\n    case 'viewport:fail':\n    case 'viewport': {\n      break\n    }\n    default: {\n      const error = new Error(`Unknown event: ${(data as any).event}`)\n      unhandledError(error, 'Unknown Event')\n    }\n  }\n\n  channel.postMessage({\n    event: `response:${data.event}`,\n    iframeId: getBrowserState().iframeId!,\n  })\n})\n\nconst url = new URL(location.href)\nconst iframeId = url.searchParams.get('iframeId')!\n\nconst commands = new CommandsManager()\ngetBrowserState().commands = commands\ngetBrowserState().activeTraceTaskIds = new Set()\ngetBrowserState().iframeId = iframeId\n\nlet contextSwitched = false\n\nasync function prepareTestEnvironment(options: PrepareOptions) {\n  debug?.('trying to resolve the runner')\n  const config = getConfig()\n\n  const rpc = createSafeRpc(client)\n\n  const state = getWorkerState()\n\n  // @ts-expect-error replaced with `import.meta.env` by transform\n  state.metaEnv = __vitest_browser_import_meta_env_init__\n  state.onCancel = onCancel\n  state.ctx.rpc = rpc as any\n  state.rpc = rpc as any\n\n  const interceptor = createModuleMockerInterceptor()\n  const mocker = new VitestBrowserClientMocker(\n    interceptor,\n    rpc,\n    SpyModule.createMockInstance,\n    {\n      root: getBrowserState().viteConfig.root,\n    },\n  )\n  // @ts-expect-error mocking vitest apis\n  globalThis.__vitest_mocker__ = mocker\n\n  setupConsoleLogSpy()\n  setupDialogsSpy()\n\n  const runner = await initiateRunner(state, mocker, config)\n  getBrowserState().runner = runner\n\n  // webdiverio context depends on the iframe state, so we need to switch the context,\n  // we delay this in case the user doesn't use any userEvent commands to avoid the overhead\n  if (server.provider === 'webdriverio') {\n    let switchPromise: Promise<void> | null = null\n\n    commands.onCommand(async () => {\n      if (switchPromise) {\n        await switchPromise\n      }\n      // if this is the first command, make sure we switched the command context to an iframe\n      if (!contextSwitched) {\n        switchPromise = rpc.wdioSwitchContext('iframe').finally(() => {\n          switchPromise = null\n          contextSwitched = true\n        })\n        await switchPromise\n      }\n    })\n  }\n\n  state.durations.prepare = performance.now() - options.startTime\n\n  return {\n    runner,\n    config,\n    state,\n  }\n}\n\nlet preparedData:\n  | Awaited<ReturnType<typeof prepareTestEnvironment>>\n  | undefined\n\nasync function executeTests(method: 'run' | 'collect', specifications: FileSpecification[]) {\n  if (!preparedData) {\n    throw new Error(`Data was not properly initialized. This is a bug in Vitest. Please, open a new issue with reproduction.`)\n  }\n\n  debug?.('runner resolved successfully')\n\n  const { runner, state } = preparedData\n\n  state.ctx.files = specifications\n  runner.setMethod(method)\n\n  const version = url.searchParams.get('browserv') || ''\n  specifications.forEach(({ filepath }) => {\n    const currentVersion = browserHashMap.get(filepath)\n    if (!currentVersion || currentVersion[1] !== version) {\n      browserHashMap.set(filepath, version)\n    }\n  })\n\n  for (const file of specifications) {\n    state.filepath = file.filepath\n    debug?.('running test file', file.filepath)\n\n    await traces.$(\n      `vitest.test.runner.${method}.module`,\n      { attributes: { 'code.file.path': file.filepath },\n      },\n      async () => {\n        if (method === 'run') {\n          await startTests([file], runner)\n        }\n        else {\n          await collectTests([file], runner)\n        }\n      },\n    )\n  }\n}\n\ninterface PrepareOptions {\n  startTime: number\n}\n\nasync function prepare(options: PrepareOptions) {\n  preparedData = await prepareTestEnvironment(options)\n\n  // page is reloading\n  debug?.('runner resolved successfully')\n\n  const { config, state } = preparedData\n\n  state.durations.prepare = performance.now() - state.durations.prepare\n\n  debug?.('prepare time', state.durations.prepare, 'ms')\n\n  await Promise.all([\n    setupCommonEnv(config),\n    startCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.browser.isolate }),\n    (async () => {\n      const VitestIndex = await import('vitest')\n      Object.defineProperty(window, '__vitest_index__', {\n        value: VitestIndex,\n        enumerable: false,\n      })\n    })(),\n  ])\n\n  if (!config.browser.trackUnhandledErrors) {\n    getBrowserState().disposeExceptionTracker()\n  }\n}\n\nasync function cleanup() {\n  const state = getWorkerState()\n  const config = getConfig()\n  const rpc = state.rpc as any as BrowserRPC\n\n  const cleanupSymbol = Symbol.for('vitest:component-cleanup')\n\n  if (cleanupSymbol in page) {\n    try {\n      await (page[cleanupSymbol] as any)()\n    }\n    catch (error: any) {\n      await unhandledError(error, 'Cleanup Error')\n    }\n  }\n  // need to cleanup for each tester\n  // since playwright keyboard API is stateful on page instance level\n  await userEvent.cleanup()\n    .catch(error => unhandledError(error, 'Cleanup Error'))\n\n  await Promise.all(\n    getBrowserState().cleanups.map(fn => fn()),\n  ).catch(error => unhandledError(error, 'Cleanup Error'))\n\n  // if isolation is disabled, Vitest reuses the same iframe and we\n  // don't need to switch the context back at all\n  if (contextSwitched) {\n    await rpc.wdioSwitchContext('parent')\n      .catch(error => unhandledError(error, 'Cleanup Error'))\n  }\n  await stopCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.browser.isolate }).catch((error) => {\n    return unhandledError(error, 'Coverage Error')\n  })\n}\n\nfunction unhandledError(e: Error, type: string) {\n  return client.rpc.onUnhandledError({\n    name: e.name,\n    message: e.message,\n    stack: e.stack,\n  }, type).catch(() => {})\n}\nfunction isEvent(data: unknown): data is IframeChannelEvent {\n  return typeof data === 'object' && !!data && 'event' in data\n}\n"
  },
  {
    "path": "packages/browser/src/client/tsconfig.json",
    "content": "{\n  \"extends\": \"../../../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"lib\": [\n      \"dom\",\n      \"esnext\",\n      \"DOM.Iterable\"\n    ],\n    \"types\": [\"vite/client\"],\n    \"noEmit\": true\n  },\n  \"include\": [\n    \"./**/*.ts\",\n    \"../types.ts\",\n    \"../../matchers.d.ts\"\n  ],\n  \"exclude\": [\n    \"./vite.config.ts\"\n  ]\n}\n"
  },
  {
    "path": "packages/browser/src/client/ui.ts",
    "content": "import type { BrowserUI } from 'vitest'\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function getUiAPI(): BrowserUI | undefined {\n  // @ts-expect-error not typed global\n  return window.__vitest_ui_api__\n}\n"
  },
  {
    "path": "packages/browser/src/client/utils.ts",
    "content": "import type { VitestRunner } from '@vitest/runner'\nimport type { SerializedConfig, WorkerGlobalState } from 'vitest'\nimport type { OTELCarrier, Traces } from 'vitest/internal/browser'\nimport type { IframeOrchestrator } from './orchestrator'\nimport type { CommandsManager } from './tester/tester-utils'\n\nexport async function importId(id: string): Promise<any> {\n  const name = `/@id/${id}`.replace(/\\\\/g, '/')\n  return getBrowserState().wrapModule(() => import(/* @vite-ignore */ name))\n}\n\nexport async function importFs(id: string): Promise<any> {\n  const name = `/@fs/${id}`.replace(/\\\\/g, '/')\n  return getBrowserState().wrapModule(() => import(/* @vite-ignore */ name))\n}\n\nexport const moduleRunner = {\n  isBrowser: true,\n\n  import: (id: string): Promise<any> => {\n    if (id[0] === '/' || id[1] === ':') {\n      return importFs(id)\n    }\n    return importId(id)\n  },\n}\n\nexport function getConfig(): SerializedConfig {\n  return getBrowserState().config\n}\n\nexport function ensureAwaited<T>(promise: (error?: Error) => Promise<T>): Promise<T> {\n  const test = getWorkerState().current\n  if (!test || test.type !== 'test') {\n    return promise()\n  }\n  let awaited = false\n  const sourceError = new Error('STACK_TRACE_ERROR')\n  test.onFinished ??= []\n  test.onFinished.push(() => {\n    if (!awaited) {\n      const error = new Error(\n        `The call was not awaited. This method is asynchronous and must be awaited; otherwise, the call will not start to avoid unhandled rejections.`,\n      )\n      error.stack = sourceError.stack?.replace(sourceError.message, error.message)\n      throw error\n    }\n  })\n  // don't even start the promise if it's not awaited to not cause any unhanded promise rejections\n  let promiseResult: Promise<T> | undefined\n  return {\n    then(onFulfilled, onRejected) {\n      awaited = true\n      return (promiseResult ||= promise(sourceError)).then(onFulfilled, onRejected)\n    },\n    catch(onRejected) {\n      awaited = true\n      return (promiseResult ||= promise(sourceError)).catch(onRejected)\n    },\n    finally(onFinally) {\n      awaited = true\n      return (promiseResult ||= promise(sourceError)).finally(onFinally)\n    },\n    [Symbol.toStringTag]: 'Promise',\n  } satisfies Promise<T>\n}\n\nexport interface BrowserRunnerState {\n  files: string[]\n  runningFiles: string[]\n  config: SerializedConfig\n  provider: string\n  runner: VitestRunner\n  viteConfig: {\n    root: string\n  }\n  providedContext: string\n  type: 'tester' | 'orchestrator'\n  disposeExceptionTracker: () => void\n  wrapModule: <T>(module: () => T) => T\n  iframeId?: string\n  sessionId: string\n  testerId: string\n  otelCarrier?: OTELCarrier\n  method: 'run' | 'collect'\n  orchestrator?: IframeOrchestrator\n  commands: CommandsManager\n  activeTraceTaskIds: Set<string>\n  traces: Traces\n  cleanups: Array<() => unknown>\n  cdp?: {\n    on: (event: string, listener: (payload: any) => void) => void\n    once: (event: string, listener: (payload: any) => void) => void\n    off: (event: string, listener: (payload: any) => void) => void\n    send: (method: string, params?: Record<string, unknown>) => Promise<unknown>\n    emit: (event: string, payload: unknown) => void\n  }\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function getBrowserState(): BrowserRunnerState {\n  // @ts-expect-error not typed global\n  return window.__vitest_browser_runner__\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function getWorkerState(): WorkerGlobalState {\n  // @ts-expect-error not typed global\n  const state = window.__vitest_worker__\n  if (!state) {\n    throw new Error('Worker state is not found. This is an issue with Vitest. Please, open an issue.')\n  }\n  return state\n}\n"
  },
  {
    "path": "packages/browser/src/client/vite.config.ts",
    "content": "import fs from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { resolve } from 'pathe'\nimport { globSync } from 'tinyglobby'\nimport * as vite from 'vite'\n\nconst browserTargets = ['chrome87', 'firefox78', 'safari15.4', 'edge88']\n\nexport default vite.defineConfig({\n  server: {\n    watch: { ignored: ['**/**'] },\n  },\n  esbuild: {\n    target: browserTargets,\n    legalComments: 'inline',\n  },\n  build: {\n    target: browserTargets,\n    minify: false,\n    outDir: '../../dist/client',\n    emptyOutDir: false,\n    assetsDir: '__vitest_browser__',\n    manifest: true,\n    rollupOptions: {\n      output: 'rolldownVersion' in vite\n        ? {\n            minify: false,\n          } as any\n        : {},\n      input: {\n        orchestrator: resolve(import.meta.dirname, './orchestrator.html'),\n        tester: resolve(import.meta.dirname, './tester/tester.html'),\n      },\n      external: [\n        /^vitest\\//,\n        'vitest',\n        /^msw/,\n        'vitest/browser',\n        '@vitest/browser/client',\n      ],\n    },\n  },\n  plugins: [\n    {\n      name: 'copy-ui-plugin',\n\n      closeBundle: async () => {\n        const root = resolve(\n          fileURLToPath(import.meta.url),\n          '../../../../../packages',\n        )\n\n        const ui = resolve(root, 'ui/dist/client')\n        const uiEntryPoint = resolve(ui, 'index.html')\n        const browser = resolve(root, 'browser/dist/client/__vitest__/')\n\n        const timeout = setTimeout(\n          () => console.log('[copy-ui-plugin] Waiting for UI to be built...'),\n          1000,\n        )\n        await waitFor(() => fs.existsSync(ui) && fs.existsSync(uiEntryPoint))\n        clearTimeout(timeout)\n\n        const files = globSync(['**/*'], { cwd: ui, expandDirectories: false })\n\n        if (fs.existsSync(browser)) {\n          fs.rmSync(browser, { recursive: true })\n        }\n\n        fs.mkdirSync(browser, { recursive: true })\n        fs.mkdirSync(resolve(browser, 'assets'))\n\n        files.forEach((f) => {\n          fs.copyFileSync(resolve(ui, f), resolve(browser, f))\n        })\n\n        console.log('[copy-ui-plugin] UI copied')\n      },\n    },\n  ],\n})\n\nasync function waitFor(method: () => boolean, retries = 100): Promise<void> {\n  if (method()) {\n    return\n  }\n\n  if (retries === 0) {\n    throw new Error('Timeout in waitFor')\n  }\n\n  await new Promise(resolve => setTimeout(resolve, 500))\n\n  return waitFor(method, retries - 1)\n}\n"
  },
  {
    "path": "packages/browser/src/node/cdp.ts",
    "content": "import type { CDPSession } from 'vitest/node'\nimport type { WebSocketBrowserRPC } from '../types'\n\nexport class BrowserServerCDPHandler {\n  private listenerIds: Record<string, string[]> = {}\n\n  private listeners: Record<string, (payload: unknown) => void> = {}\n\n  constructor(\n    private session: CDPSession,\n    private tester: WebSocketBrowserRPC,\n  ) {}\n\n  send(method: string, params?: Record<string, unknown>): Promise<unknown> {\n    return this.session.send(method as any, params)\n  }\n\n  on(event: string, id: string, once = false): void {\n    if (!this.listenerIds[event]) {\n      this.listenerIds[event] = []\n    }\n    this.listenerIds[event].push(id)\n\n    if (!this.listeners[event]) {\n      this.listeners[event] = (payload) => {\n        this.tester.cdpEvent(\n          event,\n          payload,\n        )\n        if (once) {\n          this.off(event, id)\n        }\n      }\n\n      this.session.on(event as any, this.listeners[event])\n    }\n  }\n\n  off(event: string, id: string): void {\n    if (!this.listenerIds[event]) {\n      this.listenerIds[event] = []\n    }\n    this.listenerIds[event] = this.listenerIds[event].filter(l => l !== id)\n\n    if (!this.listenerIds[event].length) {\n      this.session.off(event as any, this.listeners[event])\n      delete this.listeners[event]\n    }\n  }\n\n  once(event: string, listener: string): void {\n    this.on(event, listener, true)\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/commands/fs.ts",
    "content": "import type { BrowserCommands } from 'vitest/browser'\nimport type { BrowserCommand, TestProject } from 'vitest/node'\nimport fs, { promises as fsp } from 'node:fs'\nimport { basename, dirname, resolve } from 'node:path'\nimport mime from 'mime/lite'\nimport { isFileLoadingAllowed } from 'vitest/node'\nimport { slash } from '../utils'\n\nfunction assertFileAccess(path: string, project: TestProject) {\n  if (\n    !isFileLoadingAllowed(project.vite.config, path)\n    && !isFileLoadingAllowed(project.vitest.vite.config, path)\n  ) {\n    throw new Error(\n      `Access denied to \"${path}\". See Vite config documentation for \"server.fs\": https://vitejs.dev/config/server-options.html#server-fs-strict.`,\n    )\n  }\n}\n\nfunction assertWrite(path: string, project: TestProject) {\n  if (!project.config.browser.api.allowWrite || !project.vitest.config.api.allowWrite) {\n    throw new Error(`Cannot modify file \"${path}\". File writing is disabled because server is exposed to the internet, see https://vitest.dev/config/browser/api.`)\n  }\n}\n\nexport const readFile: BrowserCommand<\n  Parameters<BrowserCommands['readFile']>\n> = async ({ project }, path, options = {}) => {\n  const filepath = resolve(project.config.root, path)\n  assertFileAccess(slash(filepath), project)\n  // never return a Buffer\n  if (typeof options === 'object' && !options.encoding) {\n    options.encoding = 'utf-8'\n  }\n  return fsp.readFile(filepath, options)\n}\n\nexport const writeFile: BrowserCommand<\n  Parameters<BrowserCommands['writeFile']>\n> = async ({ project }, path, data, options) => {\n  assertWrite(path, project)\n  const filepath = resolve(project.config.root, path)\n  assertFileAccess(slash(filepath), project)\n  const dir = dirname(filepath)\n  if (!fs.existsSync(dir)) {\n    await fsp.mkdir(dir, { recursive: true })\n  }\n  await fsp.writeFile(filepath, data, options)\n}\n\nexport const removeFile: BrowserCommand<\n  Parameters<BrowserCommands['removeFile']>\n> = async ({ project }, path) => {\n  assertWrite(path, project)\n  const filepath = resolve(project.config.root, path)\n  assertFileAccess(slash(filepath), project)\n  await fsp.rm(filepath)\n}\n\nexport const _fileInfo: BrowserCommand<[path: string, encoding: BufferEncoding]> = async ({ project }, path, encoding) => {\n  const filepath = resolve(project.config.root, path)\n  assertFileAccess(slash(filepath), project)\n  const content = await fsp.readFile(filepath, encoding || 'base64')\n  return {\n    content,\n    basename: basename(filepath),\n    mime: mime.getType(filepath),\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/commands/index.ts",
    "content": "import {\n  _fileInfo,\n  readFile,\n  removeFile,\n  writeFile,\n} from './fs'\nimport { screenshot } from './screenshot'\nimport { screenshotMatcher } from './screenshotMatcher'\nimport { _groupTraceEnd, _groupTraceStart, _markTrace } from './trace'\n\nexport default {\n  readFile: readFile as typeof readFile,\n  removeFile: removeFile as typeof removeFile,\n  writeFile: writeFile as typeof writeFile,\n  // private commands\n  __vitest_markTrace: _markTrace as typeof _markTrace,\n  __vitest_groupTraceStart: _groupTraceStart as typeof _groupTraceStart,\n  __vitest_groupTraceEnd: _groupTraceEnd as typeof _groupTraceEnd,\n  __vitest_fileInfo: _fileInfo as typeof _fileInfo,\n  __vitest_screenshot: screenshot as typeof screenshot,\n  __vitest_screenshotMatcher: screenshotMatcher as typeof screenshotMatcher,\n}\n"
  },
  {
    "path": "packages/browser/src/node/commands/screenshot.ts",
    "content": "import type { BrowserCommand } from 'vitest/node'\nimport type { ScreenshotOptions } from '../../../context'\n\ninterface ScreenshotCommandOptions extends Omit<ScreenshotOptions, 'element' | 'mask'> {\n  element?: string\n  mask?: readonly string[]\n}\n\ndeclare module 'vitest/browser' {\n  interface BrowserCommands {\n    /**\n     * @internal\n     */\n    __vitest_takeScreenshot: (name: string, options: ScreenshotCommandOptions) => Promise<{\n      buffer: Buffer\n      path: string\n    }>\n  }\n}\n\nexport const screenshot: BrowserCommand<[string, ScreenshotCommandOptions]> = async (\n  context,\n  name: string,\n  options = {},\n) => {\n  options.save ??= true\n\n  if (!options.save) {\n    options.base64 = true\n  }\n\n  const { buffer, path } = await context.triggerCommand('__vitest_takeScreenshot', name, options)\n\n  return returnResult(options, path, buffer)\n}\n\nfunction returnResult(\n  options: ScreenshotCommandOptions,\n  path: string,\n  buffer: Buffer,\n) {\n  if (!options.save) {\n    return buffer.toString('base64')\n  }\n  if (options.base64) {\n    return { path, base64: buffer.toString('base64') }\n  }\n  return path\n}\n"
  },
  {
    "path": "packages/browser/src/node/commands/screenshotMatcher/codecs/index.ts",
    "content": "import png from './png'\n\nexport function getCodec(type: 'png'): typeof png\n\nexport function getCodec(type: string) {\n  switch (type) {\n    case 'png':\n      return png\n\n    default:\n      throw new Error(`No codec found for type ${type}`)\n  }\n}\n\nexport type AnyCodec = typeof png\n"
  },
  {
    "path": "packages/browser/src/node/commands/screenshotMatcher/codecs/png.ts",
    "content": "import type { Metadata, PackerOptions, ParserOptions } from 'pngjs'\nimport type { Codec } from '../types'\nimport { PNG } from 'pngjs'\n\nconst codec: Codec<ParserOptions, Metadata, PackerOptions> = {\n  decode: (buffer, options) => {\n    const {\n      data,\n      alpha,\n      bpp,\n      color,\n      colorType,\n      depth,\n      height,\n      interlace,\n      palette,\n      width,\n    } = PNG.sync.read(\n      Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer),\n      options,\n    )\n\n    return {\n      metadata: {\n        alpha,\n        bpp,\n        color,\n        colorType,\n        depth,\n        height,\n        interlace,\n        palette,\n        width,\n      },\n      data,\n    }\n  },\n  encode: ({ data, metadata: { height, width } }, options) => {\n    const png = new PNG({\n      height,\n      width,\n    })\n\n    png.data = Buffer.isBuffer(data) ? data : Buffer.from(data)\n\n    return PNG.sync.write(png, options)\n  },\n}\n\nexport default codec\n"
  },
  {
    "path": "packages/browser/src/node/commands/screenshotMatcher/comparators/index.ts",
    "content": "import type { BrowserCommandContext } from 'vitest/node'\nimport type { ScreenshotComparatorRegistry } from '../../../../../context'\nimport type { Comparator } from '../types'\nimport { pixelmatch } from './pixelmatch'\n\nconst comparators: {\n  [ComparatorName in keyof ScreenshotComparatorRegistry]: Comparator<\n    ScreenshotComparatorRegistry[ComparatorName]\n  >\n} = {\n  pixelmatch,\n}\n\nexport function getComparator<ComparatorName extends keyof ScreenshotComparatorRegistry>(\n  comparator: ComparatorName,\n  context: BrowserCommandContext,\n): Comparator<ScreenshotComparatorRegistry[ComparatorName]> {\n  if (comparator in comparators) {\n    return comparators[comparator]\n  }\n\n  const customComparators = context\n    .project\n    .config\n    .browser\n    .expect\n    ?.toMatchScreenshot\n    ?.comparators\n\n  if (customComparators && comparator in customComparators) {\n    return customComparators[comparator]\n  }\n\n  throw new Error(`Unrecognized comparator ${comparator}`)\n}\n\nexport type AnyComparator = Comparator<ScreenshotComparatorRegistry[keyof ScreenshotComparatorRegistry]>\n"
  },
  {
    "path": "packages/browser/src/node/commands/screenshotMatcher/comparators/pixelmatch.ts",
    "content": "import type { ScreenshotComparatorRegistry } from '../../../../../context'\nimport type { Comparator } from '../types'\nimport { diff } from '@blazediff/core'\n\nconst defaultOptions = {\n  allowedMismatchedPixelRatio: undefined,\n  allowedMismatchedPixels: undefined,\n  threshold: 0.1,\n  includeAA: false,\n  alpha: 0.1,\n  aaColor: [255, 255, 0],\n  diffColor: [255, 0, 0],\n  diffColorAlt: undefined,\n  diffMask: false,\n} satisfies ScreenshotComparatorRegistry['pixelmatch']\n\nexport const pixelmatch: Comparator<ScreenshotComparatorRegistry['pixelmatch']> = (\n  reference,\n  actual,\n  { createDiff, ...options },\n) => {\n  if (reference.metadata.height !== actual.metadata.height || reference.metadata.width !== actual.metadata.width) {\n    return {\n      pass: false,\n      diff: null,\n      message: `Expected image dimensions to be ${reference.metadata.width}×${\n        reference.metadata.height\n      }px, but received ${actual.metadata.width}×${\n        actual.metadata.height\n      }px.`,\n    }\n  }\n\n  const optionsWithDefaults = { ...defaultOptions, ...options }\n  const diffBuffer = createDiff\n    ? new Uint8Array(reference.data.length)\n    : undefined\n\n  const mismatchedPixels = diff(\n    reference.data,\n    actual.data,\n    diffBuffer,\n    reference.metadata.width,\n    reference.metadata.height,\n    optionsWithDefaults,\n  )\n\n  const imageArea = reference.metadata.width * reference.metadata.height\n\n  let allowedMismatchedPixels = Math.min(\n    optionsWithDefaults.allowedMismatchedPixels ?? Number.POSITIVE_INFINITY,\n    (optionsWithDefaults.allowedMismatchedPixelRatio\n      ?? Number.POSITIVE_INFINITY)\n    * imageArea,\n  )\n\n  if (allowedMismatchedPixels === Number.POSITIVE_INFINITY) {\n    allowedMismatchedPixels = 0\n  }\n\n  const pass = mismatchedPixels <= allowedMismatchedPixels\n\n  return {\n    pass,\n    diff: diffBuffer ?? null,\n    message: pass\n      ? null\n      : `${mismatchedPixels} pixels (ratio ${(\n        // as we compare using `<=`, use `Math.ceil` to ensure the reported ratio\n        // doesn't appear equal to the allowed limit when it's a bit over\n        Math.ceil((mismatchedPixels / imageArea) * 100) / 100\n      ).toFixed(2)}) differ.`,\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/commands/screenshotMatcher/index.ts",
    "content": "import type { SnapshotUpdateState } from 'vitest'\nimport type { ScreenshotMatcherOptions } from 'vitest/browser'\nimport type { BrowserCommand, BrowserCommandContext } from 'vitest/node'\nimport type { ScreenshotMatcherArguments, ScreenshotMatcherOutput } from '../../../shared/screenshotMatcher/types'\nimport type { AnyCodec } from './codecs'\nimport type { AnyComparator } from './comparators'\nimport type { TypedArray } from './types'\nimport type { ResolvedOptions } from './utils'\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { basename, dirname } from 'pathe'\nimport { asyncTimeout, resolveOptions, takeDecodedScreenshot } from './utils'\n\n/** Decoded image data with dimensions metadata. */\ntype DecodedImage = Awaited<ReturnType<AnyCodec['decode']>>\n\n/** Bundle of an image with its filesystem path. */\ninterface ScreenshotData {\n  image: DecodedImage\n  path: string\n}\n\n/**\n * Discriminated union representing all possible outcomes of a screenshot comparison.\n *\n * Each variant is self-contained with the data needed for side effects and output building.\n *\n * - `unstable-screenshot`: page never stabilized within timeout\n * - `missing-reference`: no baseline exists to compare against\n * - `update-reference`: snapshot update was requested (run with `--update`)\n * - `matched-immediately`: screenshot matched reference on first capture (no retries)\n * - `matched-after-comparison`: screenshot matched after another comparison\n * - `mismatch`: screenshot differs from reference\n */\ntype MatchOutcome\n  = | {\n    type: 'unstable-screenshot'\n    reference: ScreenshotData | null\n  }\n  | {\n    type: 'missing-reference'\n    location: 'reference' | 'diffs'\n    reference: ScreenshotData\n  }\n  | {\n    type: 'update-reference'\n    reference: ScreenshotData\n  }\n  | { type: 'matched-immediately' }\n  | { type: 'matched-after-comparison' }\n  | {\n    type: 'mismatch'\n    reference: ScreenshotData\n    actual: ScreenshotData\n    diff: ScreenshotData | null\n    message: string | null\n  }\n\n/**\n * Browser command that compares a screenshot against a stored reference.\n *\n * The comparison workflow is organized as follows:\n *\n * 1. Load existing reference (if any)\n * 2. Capture a stable screenshot (retrying until the page stops changing)\n * 3. Determine the outcome based on capture results and update settings\n * 4. Write any necessary files (new references, diffs)\n * 5. Return result for the test runner\n */\nexport const screenshotMatcher: BrowserCommand<ScreenshotMatcherArguments> = async (\n  context,\n  name,\n  testName,\n  options,\n): ScreenshotMatcherOutput => {\n  if (!context.testPath) {\n    throw new Error('Cannot compare screenshots without a test path')\n  }\n\n  const { element } = options\n  const {\n    codec,\n    comparator,\n    paths,\n    resolvedOptions: { comparatorOptions, screenshotOptions, timeout },\n  } = resolveOptions({ context, name, testName, options })\n\n  const referenceFile = await readFile(paths.reference).catch(() => null)\n  const reference = referenceFile && await codec.decode(referenceFile, {})\n\n  const screenshotResult = await waitForStableScreenshot({\n    codec,\n    comparator,\n    comparatorOptions,\n    context,\n    element,\n    name: `${Date.now()}-${basename(paths.reference)}`,\n    reference,\n    screenshotOptions,\n  }, timeout)\n\n  const outcome = await determineOutcome({\n    reference,\n    screenshot: screenshotResult && screenshotResult.actual,\n    retries: screenshotResult?.retries ?? 0,\n    updateSnapshot: context.project.serializedConfig.snapshotOptions.updateSnapshot,\n    paths,\n    comparator,\n    comparatorOptions,\n  })\n\n  await performSideEffects(outcome, codec)\n\n  return buildOutput(outcome, timeout)\n}\n\n/**\n * Core comparison logic that produces a {@linkcode MatchOutcome}.\n *\n * All branching logic lives here. This is the single source of truth for \"what happened\".\n *\n * The outcome carries all data needed by {@linkcode performSideEffects} and {@linkcode buildOutput}.\n */\nasync function determineOutcome(\n  {\n    comparator,\n    comparatorOptions,\n    paths,\n    reference,\n    retries,\n    screenshot,\n    updateSnapshot,\n  }: Pick<ResolvedOptions, 'comparator' | 'paths'> & {\n    comparatorOptions: ResolvedOptions['resolvedOptions']['comparatorOptions']\n    reference: DecodedImage | null\n    retries: number\n    screenshot: DecodedImage | null\n    updateSnapshot: SnapshotUpdateState\n  },\n): Promise<MatchOutcome> {\n  if (screenshot === null) {\n    return {\n      type: 'unstable-screenshot',\n      reference: reference && {\n        image: reference,\n        path: paths.reference,\n      },\n    }\n  }\n\n  // no reference to compare against - create one based on update settings\n  if (reference === null) {\n    if (updateSnapshot === 'all') {\n      return {\n        type: 'update-reference',\n        reference: {\n          image: screenshot,\n          path: paths.reference,\n        },\n      }\n    }\n\n    const location = updateSnapshot === 'none'\n      ? 'diffs'\n      : 'reference'\n\n    return {\n      type: 'missing-reference',\n      location,\n      reference: {\n        image: screenshot,\n        path: location === 'reference'\n          ? paths.reference\n          : paths.diffs.reference,\n      },\n    }\n  }\n\n  // first capture matched reference (used as baseline) - no further comparison needed\n  if (retries === 0) {\n    return { type: 'matched-immediately' }\n  }\n\n  const comparisonResult = await comparator(\n    reference,\n    screenshot,\n    { createDiff: true, ...comparatorOptions },\n  )\n\n  if (comparisonResult.pass) {\n    return { type: 'matched-after-comparison' }\n  }\n\n  if (updateSnapshot === 'all') {\n    return {\n      type: 'update-reference',\n      reference: {\n        image: screenshot,\n        path: paths.reference,\n      },\n    }\n  }\n\n  return {\n    type: 'mismatch',\n    reference: {\n      image: reference,\n      path: paths.reference,\n    },\n    actual: {\n      image: screenshot,\n      path: paths.diffs.actual,\n    },\n    diff: comparisonResult.diff && {\n      image: {\n        data: comparisonResult.diff,\n        // `comparator` only returns pixel data; diff dimensions always match reference\n        metadata: reference.metadata,\n      },\n      path: paths.diffs.diff,\n    },\n    message: comparisonResult.message,\n  }\n}\n\n/**\n * Writes files to disk based on the outcome.\n *\n * Only `missing-reference`, `update-reference`, and `mismatch` write files. Successful matches produce no side effects.\n */\nasync function performSideEffects(\n  outcome: MatchOutcome,\n  codec: AnyCodec,\n): Promise<void> {\n  switch (outcome.type) {\n    case 'missing-reference':\n    case 'update-reference': {\n      await writeScreenshot(\n        outcome.reference.path,\n        await codec.encode(outcome.reference.image, {}),\n      )\n\n      break\n    }\n\n    case 'mismatch': {\n      await writeScreenshot(\n        outcome.actual.path,\n        await codec.encode(outcome.actual.image, {}),\n      )\n\n      if (outcome.diff) {\n        await writeScreenshot(\n          outcome.diff.path,\n          await codec.encode(outcome.diff.image, {}),\n        )\n      }\n\n      break\n    }\n  }\n}\n\n/**\n * Transforms a {@linkcode MatchOutcome} into the output format expected by the test runner.\n *\n * Maps each outcome to a pass/fail result with metadata and error messages.\n */\nfunction buildOutput(\n  outcome: MatchOutcome,\n  timeout: number,\n): Awaited<ScreenshotMatcherOutput> {\n  switch (outcome.type) {\n    case 'unstable-screenshot':\n      return {\n        pass: false,\n        reference: outcome.reference && {\n          path: outcome.reference.path,\n          width: outcome.reference.image.metadata.width,\n          height: outcome.reference.image.metadata.height,\n        },\n        actual: null,\n        diff: null,\n        message: `Could not capture a stable screenshot within ${timeout}ms.`,\n      }\n\n    case 'missing-reference': {\n      return {\n        pass: false,\n        reference: {\n          path: outcome.reference.path,\n          width: outcome.reference.image.metadata.width,\n          height: outcome.reference.image.metadata.height,\n        },\n        actual: null,\n        diff: null,\n        message: outcome.location === 'reference'\n          ? 'No existing reference screenshot found; a new one was created. Review it before running tests again.'\n          : 'No existing reference screenshot found.',\n      }\n    }\n\n    case 'update-reference':\n    case 'matched-immediately':\n    case 'matched-after-comparison':\n      return { pass: true }\n\n    case 'mismatch':\n      return {\n        pass: false,\n        reference: {\n          path: outcome.reference.path,\n          width: outcome.reference.image.metadata.width,\n          height: outcome.reference.image.metadata.height,\n        },\n        actual: {\n          path: outcome.actual.path,\n          width: outcome.actual.image.metadata.width,\n          height: outcome.actual.image.metadata.height,\n        },\n        diff: outcome.diff && {\n          path: outcome.diff.path,\n          width: outcome.diff.image.metadata.width,\n          height: outcome.diff.image.metadata.height,\n        },\n        message: `Screenshot does not match the stored reference.${\n          outcome.message ? `\\n${outcome.message}` : ''\n        }`,\n      }\n\n    default: {\n      // exhaustiveness check - TypeScript will error if a case is unhandled\n      outcome satisfies never\n\n      return {\n        pass: false,\n        actual: null,\n        reference: null,\n        diff: null,\n        message: `Outcome (${(outcome as MatchOutcome).type}) not handled. This is a bug in Vitest. Please, open an issue with reproduction.`,\n      }\n    }\n  }\n}\n\n/** Configuration for stable screenshot capture. */\ninterface StableScreenshotOptions {\n  codec: AnyCodec\n  comparator: AnyComparator\n  comparatorOptions: ScreenshotMatcherOptions['comparatorOptions']\n  context: BrowserCommandContext\n  element: string\n  name: string\n  reference: ReturnType<AnyCodec['decode']> | null\n  screenshotOptions: ScreenshotMatcherArguments[2]['screenshotOptions']\n}\n\n/**\n * Captures a stable screenshot with timeout handling.\n *\n * Wraps {@linkcode getStableScreenshot} with an abort controller that triggers when the timeout expires. Returns `null` if the page never stabilizes.\n */\nasync function waitForStableScreenshot(options: StableScreenshotOptions, timeout: number,\n): Promise<{ actual: DecodedImage; retries: number } | null> {\n  const abortController = new AbortController()\n\n  const stableScreenshot = getStableScreenshot(\n    options,\n    abortController.signal,\n  )\n\n  const result = await (\n    timeout === 0\n      ? stableScreenshot\n      : Promise.race([\n          stableScreenshot,\n          asyncTimeout(timeout).finally(() => abortController.abort()),\n        ])\n  )\n\n  return result\n}\n\n/**\n * Takes screenshots repeatedly until the page reaches a visually stable state.\n *\n * This function compares consecutive screenshots and continues taking new ones until two consecutive screenshots match according to the provided comparator.\n *\n * The process works as follows:\n *\n * 1. Uses as baseline an optional reference screenshot or takes a new screenshot\n * 2. Takes a screenshot and compares with baseline\n * 3. If they match, the page is considered stable and the function returns\n * 4. If they don't match, it continues with the newer screenshot as the baseline\n * 5. Repeats until stability is achieved or the operation is aborted\n *\n * @returns `Promise` resolving to an object containing the retry count and final screenshot\n */\nasync function getStableScreenshot({\n  codec,\n  context,\n  comparator,\n  comparatorOptions,\n  element,\n  name,\n  reference,\n  screenshotOptions,\n}: StableScreenshotOptions, signal: AbortSignal): Promise<{\n  retries: number\n  actual: DecodedImage\n}> {\n  const screenshotArgument = {\n    codec,\n    context,\n    element,\n    name,\n    screenshotOptions,\n  } satisfies Parameters<typeof takeDecodedScreenshot>[0]\n\n  let retries = 0\n\n  let decodedBaseline = reference\n\n  while (signal.aborted === false) {\n    if (decodedBaseline === null) {\n      decodedBaseline = takeDecodedScreenshot(screenshotArgument)\n    }\n\n    const [image1, image2] = await Promise.all([\n      decodedBaseline,\n      takeDecodedScreenshot(screenshotArgument),\n    ])\n\n    const isStable = (await comparator(\n      image1,\n      image2,\n      { ...comparatorOptions, createDiff: false },\n    )).pass\n\n    decodedBaseline = image2\n\n    if (isStable) {\n      break\n    }\n\n    retries += 1\n  }\n\n  return {\n    retries,\n    actual: await decodedBaseline!,\n  }\n}\n\n/** Writes encoded images to disk, creating parent directories as needed. */\nasync function writeScreenshot(path: string, image: TypedArray) {\n  try {\n    await mkdir(dirname(path), { recursive: true })\n    await writeFile(path, image)\n  }\n  catch (cause) {\n    throw new Error('Couldn\\'t write file to fs', { cause })\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/commands/screenshotMatcher/types.ts",
    "content": "import type {\n  NonStandardScreenshotComparators,\n  ScreenshotComparatorRegistry,\n  ScreenshotMatcherOptions,\n} from '@vitest/browser/context'\n\ninterface BaseMetadata { height: number; width: number }\nexport type TypedArray\n  = | Buffer<ArrayBufferLike>\n    | Uint8Array<ArrayBufferLike>\n    | Uint8ClampedArray<ArrayBufferLike>\nexport type Promisable<T> = T | Promise<T>\n\nexport interface Codec<\n  DecoderOptions extends object,\n  DecoderMetadata extends object,\n  EncoderOptions extends object,\n> {\n  decode: (\n    buffer: TypedArray,\n    options: DecoderOptions,\n  ) => Promisable<{\n    data: TypedArray\n    metadata: DecoderMetadata & BaseMetadata\n  }>\n  encode: (\n    image: { data: TypedArray; metadata: BaseMetadata },\n    options: EncoderOptions,\n  ) => Promisable<TypedArray>\n}\n\nexport type Comparator<Options extends Record<string, unknown>> = (\n  reference: {\n    metadata: BaseMetadata\n    data: TypedArray\n  },\n  actual: {\n    metadata: BaseMetadata\n    data: TypedArray\n  },\n  options: {\n    /**\n     * Allows the comparator to create a diff image.\n     *\n     * Note that the comparator might choose to ignore the flag, so a diff image is not guaranteed.\n     */\n    createDiff: boolean\n  } & Options,\n) => Promisable<{ pass: boolean; diff: TypedArray | null; message: string | null }>\n\ntype CustomComparatorsToRegister = {\n  [Key in keyof NonStandardScreenshotComparators]: Comparator<NonStandardScreenshotComparators[Key]>\n}\n\nexport type CustomComparatorsRegistry\n  = keyof CustomComparatorsToRegister extends never\n    ? { comparators?: Record<string, Comparator<Record<string, unknown>>> }\n    : { comparators: CustomComparatorsToRegister }\n\ndeclare module 'vitest/node' {\n  export interface ToMatchScreenshotOptions\n    extends Omit<\n      ScreenshotMatcherOptions,\n      'comparatorName' | 'comparatorOptions'\n    >, CustomComparatorsRegistry {}\n\n  export interface ToMatchScreenshotComparators\n    extends ScreenshotComparatorRegistry {}\n}\n"
  },
  {
    "path": "packages/browser/src/node/commands/screenshotMatcher/utils.ts",
    "content": "// Note: this augments `screenshotOptions` types\nimport type {} from '@vitest/browser-playwright'\n\nimport type { BrowserCommandContext, BrowserConfigOptions } from 'vitest/node'\nimport type { ScreenshotMatcherOptions } from '../../../../context'\nimport type { ScreenshotMatcherArguments } from '../../../shared/screenshotMatcher/types'\nimport type { AnyCodec } from './codecs'\nimport { platform } from 'node:os'\nimport { deepMerge } from '@vitest/utils/helpers'\nimport { basename, dirname, extname, join, relative, resolve } from 'pathe'\nimport { getCodec } from './codecs'\nimport { getComparator } from './comparators'\n\ntype GlobalOptions = Required<Omit<\n  NonNullable<\n    NonNullable<BrowserConfigOptions['expect']>['toMatchScreenshot']\n    & NonNullable<Pick<ScreenshotMatcherArguments[2], 'screenshotOptions'>>\n  >,\n  'comparators'\n>>\n\nconst defaultOptions = {\n  comparatorName: 'pixelmatch',\n  // these are handled by each comparator on its own\n  comparatorOptions: {},\n  screenshotOptions: {\n    animations: 'disabled',\n    caret: 'hide',\n    fullPage: false,\n    maskColor: '#ff00ff',\n    omitBackground: false,\n    scale: 'device',\n  },\n  timeout: 5_000,\n  strict: true,\n  resolveDiffPath: ({\n    arg,\n    ext,\n    root,\n    attachmentsDir,\n    browserName,\n    platform,\n    testFileDirectory,\n    testFileName,\n  }) => resolve(\n    root,\n    attachmentsDir,\n    testFileDirectory,\n    testFileName,\n    `${arg}-${browserName}-${platform}${ext}`,\n  ),\n  resolveScreenshotPath: ({\n    arg,\n    ext,\n    root,\n    screenshotDirectory,\n    testFileDirectory,\n    testFileName,\n    browserName,\n  }) => resolve(\n    root,\n    testFileDirectory,\n    screenshotDirectory,\n    testFileName,\n    `${arg}-${browserName}-${platform}${ext}`,\n  ),\n} satisfies GlobalOptions\n\ntype SupportedCodecs = Parameters<typeof getCodec>[0]\n\nconst supportedExtensions = ['png'] satisfies SupportedCodecs[]\n\nexport interface ResolvedOptions {\n  codec: ReturnType<typeof getCodec>\n  comparator: ReturnType<typeof getComparator>\n  resolvedOptions: GlobalOptions\n  paths: {\n    reference: string\n    diffs: {\n      reference: string\n      actual: string\n      diff: string\n    }\n  }\n}\n\nexport function resolveOptions(\n  {\n    context,\n    name,\n    options,\n    testName,\n  }: {\n    context: BrowserCommandContext\n    name: string\n    testName: string\n    options: ScreenshotMatcherOptions\n  },\n): ResolvedOptions {\n  if (context.testPath === undefined) {\n    throw new Error('`resolveOptions` has to be used in a test file')\n  }\n\n  const resolvedOptions = deepMerge<GlobalOptions>(\n    Object.create(null),\n    defaultOptions,\n    context.project.config.browser.expect?.toMatchScreenshot ?? {},\n    options,\n  )\n\n  const extensionFromName = extname(name)\n\n  // technically the type is a lie, but we check beneath and reassign otherwise\n  let extension = extensionFromName.replace(/^\\./, '') as SupportedCodecs\n\n  // when `type` will be supported in `screenshotOptions`:\n  // - `'png'` should end up in `defaultOptions.screenshotOptions.type`\n  // - this condition should be switched around\n  // - the assignment should be `resolvedOptions.screenshotOptions.type = extension`\n  // - everything using `extension` should use `resolvedOptions.screenshotOptions.type`\n  if (supportedExtensions.includes(extension) === false) {\n    extension = 'png'\n  }\n\n  const { root } = context.project.serializedConfig\n\n  const resolvePathData = {\n    arg: sanitizeArg(\n      // remove the extension only if it ends up being used\n      extensionFromName.endsWith(extension)\n        ? basename(name, extensionFromName)\n        : name,\n    ),\n    ext: `.${extension}`,\n    platform: platform(),\n    root,\n    screenshotDirectory: relative(\n      root,\n      join(root, context.project.config.browser.screenshotDirectory ?? '__screenshots__'),\n    ),\n    attachmentsDir: relative(root, context.project.config.attachmentsDir),\n    testFileDirectory: relative(root, dirname(context.testPath)),\n    testFileName: basename(context.testPath),\n    testName: sanitize(testName, false),\n    browserName: context.project.config.browser.name,\n  } satisfies Parameters<GlobalOptions['resolveDiffPath']>[0]\n\n  return {\n    codec: getCodec(extension),\n    comparator: getComparator(resolvedOptions.comparatorName, context),\n    resolvedOptions,\n    paths: {\n      reference: resolvedOptions.resolveScreenshotPath(resolvePathData),\n      // lazily initialize this, as it might not be needed at all\n      get diffs() {\n        const diffs = {\n          reference: resolvedOptions.resolveDiffPath({\n            ...resolvePathData,\n            arg: `${resolvePathData.arg}-reference`,\n          }),\n          actual: resolvedOptions.resolveDiffPath({\n            ...resolvePathData,\n            arg: `${resolvePathData.arg}-actual`,\n          }),\n          diff: resolvedOptions.resolveDiffPath({\n            ...resolvePathData,\n            arg: `${resolvePathData.arg}-diff`,\n          }),\n        }\n\n        Object.defineProperty(this, 'diffs', { value: diffs })\n\n        return diffs\n      },\n    },\n  }\n}\n\n/**\n * Sanitizes a string by removing or transforming characters to ensure it is\n * safe for use as a filename or path segment. It supports two modes:\n *\n * 1. Non-path mode (`keepPaths === false`):\n *    - Replaces one or more whitespace characters (`\\s+`) with a single hyphen (`-`).\n *    - Removes any character that is not a word character (`\\w`) or a hyphen (`-`).\n *    - Collapses multiple consecutive hyphens (`-{2,}`) into a single hyphen.\n *\n * 2. Path-preserving mode (`keepPaths === true`):\n *    - Splits the input string on the path separator.\n *    - Sanitizes each path segment individually in non-path mode.\n *    - Joins the sanitized segments back together.\n *\n * @param input - The raw string to sanitize.\n * @param keepPaths - If `false`, performs a flat sanitization (drops path segments).\n * If `true`, treats `input` as a path: each segment is sanitized independently,\n * preserving separators.\n */\nfunction sanitize(input: string, keepPaths: boolean): string {\n  if (keepPaths === false) {\n    return input\n      .replace(/\\s+/g, '-')\n      .replace(/[^\\w-]+/g, '')\n      .replace(/-{2,}/g, '-')\n  }\n\n  return input.split('/').map(path => sanitize(path, false)).join('/')\n}\n\n/**\n * Takes a string, treats it as a potential path or filename, and ensures it cannot\n * escape the root directory or contain invalid characters. Internally, it:\n *\n * 1. Prepends the path separator to the raw input to form a path-like string.\n * 2. Uses {@linkcode relative|relative('/', <that-path>)} to compute a relative\n * path from the root, which effectively strips any leading separators and prevents\n * traversal above the root.\n * 3. Passes the resulting relative path into {@linkcode sanitize|sanitize(..., true)},\n * preserving any path separators but sanitizing each segment.\n *\n * @param input - The raw string to clean.\n */\nfunction sanitizeArg(input: string): string {\n  return sanitize(relative('/', join('/', input)), true)\n}\n\n/**\n * Takes a screenshot and decodes it using the provided codec.\n *\n * The screenshot is taken as a base64 string and then decoded into the format\n * expected by the comparator.\n *\n * @returns `Promise` resolving to the decoded screenshot data\n */\nexport function takeDecodedScreenshot({\n  codec,\n  context,\n  element,\n  name,\n  screenshotOptions,\n}: {\n  codec: AnyCodec\n  context: BrowserCommandContext\n  element: string\n  name: string\n  screenshotOptions: ScreenshotMatcherArguments[2]['screenshotOptions']\n}): ReturnType<AnyCodec['decode']> {\n  return context.triggerCommand(\n    '__vitest_takeScreenshot',\n    name,\n    { ...screenshotOptions, save: false, element },\n  ).then(\n    ({ buffer }) => codec.decode(buffer, {}),\n  )\n}\n\n/**\n * Creates a promise that resolves to `null` after the specified timeout.\n * If the timeout is `0`, the promise resolves immediately.\n *\n * @param timeout - The delay in milliseconds before the promise resolves\n * @returns `Promise` that resolves to `null` after the timeout\n */\nexport function asyncTimeout(timeout: number): Promise<null> {\n  return new Promise((resolve) => {\n    if (timeout === 0) {\n      resolve(null)\n    }\n    else {\n      setTimeout(() => resolve(null), timeout)\n    }\n  })\n}\n"
  },
  {
    "path": "packages/browser/src/node/commands/trace.ts",
    "content": "import type { BrowserCommand } from 'vitest/node'\n\ninterface MarkTracePayload {\n  name: string\n  stack?: string\n  selector?: string\n}\n\ninterface GroupTracePayload {\n  name: string\n  stack?: string\n}\n\ndeclare module 'vitest/browser' {\n  interface BrowserCommands {\n    /**\n     * @internal\n     */\n    __vitest_markTrace: (payload: MarkTracePayload) => Promise<void>\n    /**\n     * @internal\n     */\n    __vitest_groupTraceStart: (payload: GroupTracePayload) => Promise<void>\n    /**\n     * @internal\n     */\n    __vitest_groupTraceEnd: () => Promise<void>\n  }\n}\n\nexport const _markTrace: BrowserCommand<[payload: MarkTracePayload]> = async (\n  context,\n  payload,\n) => {\n  if (context.provider.name === 'playwright') {\n    await context.triggerCommand('__vitest_markTrace', payload)\n  }\n}\n\nexport const _groupTraceStart: BrowserCommand<[payload: GroupTracePayload]> = async (\n  context,\n  payload,\n) => {\n  if (context.provider.name === 'playwright') {\n    await context.triggerCommand('__vitest_groupTraceStart', payload)\n  }\n}\n\nexport const _groupTraceEnd: BrowserCommand<[]> = async (\n  context,\n) => {\n  if (context.provider.name === 'playwright') {\n    await context.triggerCommand('__vitest_groupTraceEnd')\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/constants.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { resolve } from 'pathe'\n\nconst pkgRoot = resolve(fileURLToPath(import.meta.url), '../..')\nexport const distRoot: string = resolve(pkgRoot, 'dist')\n"
  },
  {
    "path": "packages/browser/src/node/index.ts",
    "content": "import type { BrowserCommand, BrowserProviderOption, BrowserServerFactory } from 'vitest/node'\nimport { MockerRegistry } from '@vitest/mocker'\nimport { interceptorPlugin } from '@vitest/mocker/node'\nimport c from 'tinyrainbow'\nimport { createViteLogger, createViteServer } from 'vitest/node'\nimport { version } from '../../package.json'\nimport { distRoot } from './constants'\nimport BrowserPlugin from './plugin'\nimport { ParentBrowserProject } from './projectParent'\nimport { setupBrowserRpc } from './rpc'\n\nexport type { CustomComparatorsRegistry } from './commands/screenshotMatcher/types'\n\nexport function defineBrowserCommand<T extends unknown[]>(\n  fn: BrowserCommand<T>,\n): BrowserCommand<T> {\n  return fn\n}\n\n// export type { ProjectBrowser } from './project'\nexport { parseKeyDef, resolveScreenshotPath } from './utils'\n\nexport { asLocator } from 'ivya'\n\nexport const createBrowserServer: BrowserServerFactory = async (options) => {\n  const project = options.project\n  const configFile = project.vite.config.configFile\n\n  if (project.vitest.version !== version) {\n    project.vitest.logger.warn(\n      c.yellow(\n        `Loaded ${c.inverse(c.yellow(` vitest@${project.vitest.version} `))} and ${c.inverse(c.yellow(` @vitest/browser@${version} `))}.`\n        + '\\nRunning mixed versions is not supported and may lead into bugs'\n        + '\\nUpdate your dependencies and make sure the versions match.',\n      ),\n    )\n  }\n\n  const server = new ParentBrowserProject(project, '/')\n\n  const configPath = typeof configFile === 'string' ? configFile : false\n\n  const logLevel = (process.env.VITEST_BROWSER_DEBUG as 'info') ?? 'info'\n\n  const logger = createViteLogger(project.vitest.logger, logLevel, {\n    allowClearScreen: false,\n  })\n\n  const mockerRegistry = new MockerRegistry()\n\n  let cacheDir: string\n  const vite = await createViteServer({\n    ...project.options, // spread project config inlined in root workspace config\n    define: project.config.viteDefine,\n    base: '/',\n    root: project.config.root,\n    logLevel,\n    customLogger: {\n      ...logger,\n      info(msg, options) {\n        logger.info(msg, options)\n        if (msg.includes('optimized dependencies changed. reloading')) {\n          logger.warn(\n            [\n              c.yellow(`\\n${c.bold('[vitest]')} Vite unexpectedly reloaded a test. This may cause tests to fail, lead to flaky behaviour or duplicated test runs.\\n`),\n              c.yellow(`For a stable experience, please add mentioned dependencies to your config\\'s ${c.bold('\\`optimizeDeps.include\\`')} field manually.\\n\\n`),\n            ].join(''),\n          )\n        }\n      },\n    },\n    mode: project.config.mode,\n    configFile: configPath,\n    configLoader: project.vite.config.inlineConfig.configLoader,\n    // watch is handled by Vitest\n    server: {\n      hmr: false,\n      watch: null,\n    },\n    cacheDir: project.vite.config.cacheDir,\n    plugins: [\n      {\n        name: 'vitest-internal:browser-cacheDir',\n        configResolved(config) {\n          cacheDir = config.cacheDir\n        },\n      },\n      ...options.mocksPlugins({\n        filter(id) {\n          if (id.includes(distRoot) || id.includes(cacheDir)) {\n            return false\n          }\n          return true\n        },\n      }),\n      options.metaEnvReplacer(),\n      ...(project.options?.plugins || []),\n      BrowserPlugin(server),\n      interceptorPlugin({ registry: mockerRegistry }),\n      options.coveragePlugin(),\n    ],\n  })\n\n  await vite.listen()\n\n  setupBrowserRpc(server, mockerRegistry)\n\n  return server\n}\n\nexport function defineBrowserProvider<T extends object = object>(options: Omit<\n  BrowserProviderOption<T>,\n  'serverFactory' | 'options'\n> & { options?: T }): BrowserProviderOption {\n  return {\n    ...options,\n    options: options.options || {},\n    serverFactory: createBrowserServer,\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/middlewares/orchestratorMiddleware.ts",
    "content": "import type { Connect } from 'vite'\nimport type { ParentBrowserProject } from '../projectParent'\nimport { resolveOrchestrator } from '../serverOrchestrator'\nimport { allowIframes, disableCache } from './utils'\n\nexport function createOrchestratorMiddleware(parentServer: ParentBrowserProject): Connect.NextHandleFunction {\n  return async function vitestOrchestratorMiddleware(req, res, next) {\n    if (!req.url) {\n      return next()\n    }\n    const url = new URL(req.url, 'http://localhost')\n    if (url.pathname !== parentServer.prefixOrchestratorUrl) {\n      return next()\n    }\n\n    const html = await resolveOrchestrator(parentServer, url, res)\n    if (html) {\n      disableCache(res)\n      allowIframes(res)\n\n      res.write(html, 'utf-8')\n      res.end()\n    }\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/middlewares/testerMiddleware.ts",
    "content": "import type { Connect } from 'vite'\nimport type { ParentBrowserProject } from '../projectParent'\nimport { resolveTester } from '../serverTester'\nimport { allowIframes, disableCache } from './utils'\n\nexport function createTesterMiddleware(browserServer: ParentBrowserProject): Connect.NextHandleFunction {\n  return async function vitestTesterMiddleware(req, res, next) {\n    if (!req.url) {\n      return next()\n    }\n    const url = new URL(req.url, 'http://localhost')\n    if (url.pathname !== browserServer.prefixTesterUrl || !url.searchParams.has('sessionId')) {\n      return next()\n    }\n\n    const html = await resolveTester(browserServer, url, res, next)\n    if (html) {\n      disableCache(res)\n      allowIframes(res)\n      res.write(html, 'utf-8')\n      res.end()\n    }\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/middlewares/utils.ts",
    "content": "import type { ServerResponse } from 'node:http'\n\nexport function disableCache(res: ServerResponse): void {\n  res.setHeader(\n    'Cache-Control',\n    'no-cache, max-age=0, must-revalidate',\n  )\n  res.setHeader('Content-Type', 'text/html; charset=utf-8')\n}\n\nexport function allowIframes(res: ServerResponse): void {\n  // remove custom iframe related headers to allow the iframe to load\n  res.removeHeader('X-Frame-Options')\n}\n"
  },
  {
    "path": "packages/browser/src/node/plugin.ts",
    "content": "import type { HtmlTagDescriptor } from 'vite'\nimport type { Plugin } from 'vitest/config'\nimport type { ParentBrowserProject } from './projectParent'\nimport { createReadStream, readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { dynamicImportPlugin } from '@vitest/mocker/node'\nimport { toArray } from '@vitest/utils/helpers'\nimport MagicString from 'magic-string'\nimport { dirname, join, resolve } from 'pathe'\nimport sirv from 'sirv'\nimport {\n  isFileServingAllowed,\n  isValidApiRequest,\n  resolveApiServerConfig,\n  resolveFsAllow,\n  rolldownVersion,\n  distDir as vitestDist,\n} from 'vitest/node'\nimport { distRoot } from './constants'\nimport { createOrchestratorMiddleware } from './middlewares/orchestratorMiddleware'\nimport { createTesterMiddleware } from './middlewares/testerMiddleware'\nimport BrowserContext from './plugins/pluginContext'\n\nexport type { BrowserCommand } from 'vitest/node'\n\nconst versionRegexp = /(?:\\?|&)v=\\w{8}/\n\nexport default (parentServer: ParentBrowserProject, base = '/'): Plugin[] => {\n  function isPackageExists(pkg: string, root: string) {\n    return parentServer.vitest.packageInstaller.isPackageExists?.(pkg, {\n      paths: [root],\n    })\n  }\n\n  return [\n    {\n      enforce: 'pre',\n      name: 'vitest:browser',\n      async configureServer(server) {\n        parentServer.setServer(server)\n\n        // eslint-disable-next-line prefer-arrow-callback\n        server.middlewares.use(function vitestHeaders(_req, res, next) {\n          const headers = server.config.server.headers\n          if (headers) {\n            for (const name in headers) {\n              res.setHeader(name, headers[name]!)\n            }\n          }\n          next()\n        })\n        // strip _vitest_original query added by importActual so that\n        // the plugin pipeline sees the original import id (e.g. virtual modules's load hook).\n        server.middlewares.use((req, _res, next) => {\n          if (\n            req.url?.includes('_vitest_original')\n            && parentServer.project.config.browser.provider?.name === 'playwright'\n          ) {\n            req.url = req.url\n              .replace(/[?&]_vitest_original(?=[&#]|$)/, '')\n              .replace(/[?&]ext\\b[^&#]*/, '')\n              .replace(/\\?$/, '')\n          }\n          next()\n        })\n        server.middlewares.use(createOrchestratorMiddleware(parentServer))\n        server.middlewares.use(createTesterMiddleware(parentServer))\n\n        server.middlewares.use(\n          `${base}favicon.svg`,\n          (_, res) => {\n            const content = readFileSync(resolve(distRoot, 'client/favicon.svg'))\n            res.write(content, 'utf-8')\n            res.end()\n          },\n        )\n\n        // Serve coverage HTML at ./coverage if configured\n        const coverageHtmlDir = parentServer.vitest.config.coverage?.htmlDir\n        if (coverageHtmlDir) {\n          server.middlewares.use(\n            '/__vitest_test__/coverage',\n            sirv(coverageHtmlDir, {\n              single: true,\n              dev: true,\n              setHeaders: (res) => {\n                const csp = res.getHeader('Content-Security-Policy')\n                if (typeof csp === 'string') {\n                  // add frame-ancestors to allow the iframe to be loaded by Vitest,\n                  // but keep the rest of the CSP\n                  res.setHeader(\n                    'Content-Security-Policy',\n                    csp.replace(/frame-ancestors [^;]+/, 'frame-ancestors *'),\n                  )\n                }\n                res.setHeader(\n                  'Cache-Control',\n                  'public,max-age=0,must-revalidate',\n                )\n              },\n            }),\n          )\n        }\n\n        server.middlewares.use((req, res, next) => {\n          // 9000 mega head move\n          // Vite always caches optimized dependencies, but users might mock\n          // them in _some_ tests, while keeping original modules in others\n          // there is no way to configure that in Vite, so we patch it here\n          // to always ignore the cache-control set by Vite in the next middleware\n          if (req.url && versionRegexp.test(req.url) && !req.url.includes('chunk-')) {\n            res.setHeader('Cache-Control', 'no-cache')\n            const setHeader = res.setHeader.bind(res)\n            res.setHeader = function (name, value) {\n              if (name === 'Cache-Control') {\n                return res\n              }\n              return setHeader(name, value)\n            }\n          }\n          next()\n        })\n        // handle attachments the same way as in packages/ui/node/index.ts\n        server.middlewares.use((req, res, next) => {\n          if (!req.url) {\n            return next()\n          }\n\n          const url = new URL(req.url, 'http://localhost')\n\n          if (url.pathname !== '/__vitest_attachment__') {\n            return next()\n          }\n\n          const path = url.searchParams.get('path')\n          const contentType = url.searchParams.get('contentType')\n\n          if (!isValidApiRequest(parentServer.config, req) || !contentType || !path) {\n            return next()\n          }\n\n          const fsPath = decodeURIComponent(path)\n\n          if (!isFileServingAllowed(parentServer.vite.config, fsPath)) {\n            return next()\n          }\n\n          try {\n            res.setHeader(\n              'content-type',\n              contentType,\n            )\n\n            return createReadStream(fsPath)\n              .pipe(res)\n              .on('close', () => res.end())\n          }\n          catch (err) {\n            return next(err)\n          }\n        })\n      },\n    },\n    {\n      name: 'vitest:browser:tests',\n      enforce: 'pre',\n      async config() {\n        // this plugin can be used in different projects, but all of them\n        // have the same `include` pattern, so it doesn't matter which project we use\n        const project = parentServer.project\n        const { testFiles: browserTestFiles } = await project.globTestFiles()\n        const setupFiles = toArray(project.config.setupFiles)\n\n        // replace env values - cannot be reassign at runtime\n        const define: Record<string, string> = {}\n        for (const env in (project.config.env || {})) {\n          const stringValue = JSON.stringify(project.config.env[env])\n          define[`import.meta.env.${env}`] = stringValue\n        }\n\n        const entries: string[] = [\n          ...browserTestFiles,\n          ...setupFiles,\n          resolve(vitestDist, 'index.js'),\n          resolve(vitestDist, 'browser.js'),\n          resolve(vitestDist, 'runners.js'),\n          resolve(vitestDist, 'utils.js'),\n          ...(project.config.snapshotSerializers || []),\n        ]\n\n        const exclude = [\n          'vitest',\n          'vitest/browser',\n          'vitest/internal/browser',\n          'vite/module-runner',\n          '@vitest/browser/utils',\n          '@vitest/browser/context',\n          '@vitest/browser/client',\n          '@vitest/utils',\n          '@vitest/utils/source-map',\n          '@vitest/runner',\n          '@vitest/spy',\n          '@vitest/utils/error',\n          '@vitest/snapshot',\n          '@vitest/expect',\n          'std-env',\n          'tinybench',\n          'tinyspy',\n          'tinyrainbow',\n          'pathe',\n          'msw',\n          'msw/browser',\n        ]\n\n        if (typeof project.config.diff === 'string') {\n          entries.push(project.config.diff)\n        }\n\n        if (parentServer.vitest.coverageProvider) {\n          const coverage = parentServer.vitest._coverageOptions\n          const provider = coverage.provider\n          if (provider === 'v8') {\n            const path = tryResolve('@vitest/coverage-v8', [parentServer.config.root])\n            if (path) {\n              entries.push(path)\n              exclude.push('@vitest/coverage-v8/browser')\n            }\n          }\n          else if (provider === 'istanbul') {\n            const path = tryResolve('@vitest/coverage-istanbul', [parentServer.config.root])\n            if (path) {\n              entries.push(path)\n              exclude.push('@vitest/coverage-istanbul')\n            }\n          }\n          else if (provider === 'custom' && coverage.customProviderModule) {\n            entries.push(coverage.customProviderModule)\n          }\n        }\n\n        const include = [\n          'vitest > expect-type',\n          'vitest > @vitest/snapshot > magic-string',\n          'vitest > @vitest/expect > chai',\n        ]\n\n        const provider = parentServer.config.browser.provider || [...parentServer.children][0]?.provider\n        if (provider?.name === 'preview') {\n          include.push(\n            '@vitest/browser-preview > @testing-library/user-event',\n            '@vitest/browser-preview > @testing-library/dom',\n          )\n        }\n\n        const fileRoot = browserTestFiles[0] ? dirname(browserTestFiles[0]) : project.config.root\n\n        const svelte = isPackageExists('vitest-browser-svelte', fileRoot)\n        if (svelte) {\n          exclude.push('vitest-browser-svelte')\n        }\n\n        // since we override the resolution in the esbuild plugin, Vite can no longer optimizer it\n        const vue = isPackageExists('vitest-browser-vue', fileRoot)\n        if (vue) {\n          // we override them in the esbuild plugin so optimizer can no longer intercept it\n          include.push(\n            'vitest-browser-vue',\n            'vitest-browser-vue > @vue/test-utils',\n            'vitest-browser-vue > @vue/test-utils > @vue/compiler-core',\n          )\n        }\n        const vueTestUtils = isPackageExists('@vue/test-utils', fileRoot)\n        if (vueTestUtils) {\n          include.push('@vue/test-utils')\n        }\n\n        const otelConfig = project.config.experimental.openTelemetry\n        if (otelConfig?.enabled && otelConfig.browserSdkPath) {\n          entries.push(otelConfig.browserSdkPath)\n          include.push('@opentelemetry/api')\n        }\n\n        return {\n          define,\n          resolve: {\n            dedupe: ['vitest'],\n          },\n          optimizeDeps: {\n            entries,\n            exclude,\n            include,\n          },\n        }\n      },\n      async resolveId(id) {\n        if (!/\\?browserv=\\w+$/.test(id)) {\n          return\n        }\n\n        let useId = id.slice(0, id.lastIndexOf('?'))\n        if (useId.startsWith('/@fs/')) {\n          useId = useId.slice(5)\n        }\n\n        if (/^\\w:/.test(useId)) {\n          useId = useId.replace(/\\\\/g, '/')\n        }\n\n        return useId\n      },\n    },\n    {\n      name: 'vitest:browser:resolve-virtual',\n      async resolveId(rawId) {\n        if (rawId === '/mockServiceWorker.js') {\n          return this.resolve('msw/mockServiceWorker.js', distRoot, {\n            skipSelf: true,\n          })\n        }\n      },\n    },\n    {\n      name: 'vitest:browser:assets',\n      configureServer(server) {\n        server.middlewares.use(\n          '/__vitest__',\n          sirv(resolve(distRoot, 'client/__vitest__')),\n        )\n      },\n      resolveId(id) {\n        if (id.startsWith('/__vitest_browser__/')) {\n          return resolve(distRoot, 'client', id.slice(1))\n        }\n      },\n      transform(code, id) {\n        if (id.includes(parentServer.vite.config.cacheDir) && id.includes('loupe.js')) {\n          // loupe bundle has a nastry require('util') call that leaves a warning in the console\n          const utilRequire = 'nodeUtil = require_util();'\n          return code.replace(utilRequire, ' '.repeat(utilRequire.length))\n        }\n      },\n    },\n    BrowserContext(parentServer),\n    dynamicImportPlugin({\n      globalThisAccessor: '\"__vitest_browser_runner__\"',\n      filter(id) {\n        if (id.includes(distRoot)) {\n          return false\n        }\n        return true\n      },\n    }),\n    {\n      name: 'vitest:browser:config',\n      enforce: 'post',\n      async config(viteConfig) {\n        // Enables using ignore hint for coverage providers with @preserve keyword\n        // Only set esbuild options when not using rolldown-vite (Vite 8+),\n        // which uses oxc for transformation instead of esbuild\n        if (!rolldownVersion && viteConfig.esbuild !== false) {\n          viteConfig.esbuild ||= {}\n          viteConfig.esbuild.legalComments = 'inline'\n        }\n\n        const defaultPort = parentServer.vitest.state._data.browserLastPort++\n\n        const api = resolveApiServerConfig(\n          viteConfig.test?.browser || {},\n          defaultPort,\n        )\n\n        viteConfig.server = {\n          ...viteConfig.server,\n          port: defaultPort,\n          ...api,\n          middlewareMode: false,\n          open: false,\n        }\n        viteConfig.server.fs ??= {}\n        viteConfig.server.fs.allow = viteConfig.server.fs.allow || []\n        viteConfig.server.fs.allow.push(\n          ...resolveFsAllow(\n            parentServer.vitest.config.root,\n            parentServer.vitest.vite.config.configFile,\n          ),\n          distRoot,\n        )\n\n        return {\n          resolve: {\n            alias: viteConfig.test?.alias,\n          },\n        }\n      },\n    },\n    {\n      name: 'vitest:browser:in-source-tests',\n      transform: {\n        filter: {\n          code: /import\\.meta\\.vitest/,\n        },\n        handler(code, id) {\n          const filename = cleanUrl(id)\n\n          if (!code.includes('import.meta.vitest')) {\n            return\n          }\n          const s = new MagicString(code, { filename })\n          s.prepend(\n            `Object.defineProperty(import.meta, 'vitest', { get() { return typeof __vitest_worker__ !== 'undefined' && __vitest_worker__.filepath === \"${filename.replace(/\"/g, '\\\\\"')}\" ? __vitest_index__ : undefined } });\\n`,\n          )\n          return {\n            code: s.toString(),\n            map: s.generateMap({ hires: true }),\n          }\n        },\n      },\n    },\n    {\n      name: 'vitest:browser:worker',\n      transform(code, id, _options) {\n        // https://github.com/vitejs/vite/blob/ba56cf43b5480f8519349f7d7fe60718e9af5f1a/packages/vite/src/node/plugins/worker.ts#L46\n        if (/(?:\\?|&)worker_file&type=\\w+(?:&|$)/.test(id)) {\n          const s = new MagicString(code)\n          s.prepend('globalThis.__vitest_browser_runner__ = { wrapDynamicImport: f => f() };\\n')\n          return {\n            code: s.toString(),\n            map: s.generateMap({ hires: 'boundary' }),\n          }\n        }\n      },\n    },\n    {\n      name: 'vitest:browser:transform-tester-html',\n      enforce: 'pre',\n      async transformIndexHtml(html, ctx) {\n        const projectBrowser = [...parentServer.children].find((server) => {\n          return ctx.filename === server.testerFilepath\n        })\n        if (!projectBrowser) {\n          return\n        }\n\n        const stateJs = typeof parentServer.stateJs === 'string'\n          ? parentServer.stateJs\n          : await parentServer.stateJs\n\n        const testerTags: HtmlTagDescriptor[] = []\n\n        const isDefaultTemplate = resolve(distRoot, 'client/tester/tester.html') === projectBrowser.testerFilepath\n        if (!isDefaultTemplate) {\n          const manifestContent = parentServer.manifest instanceof Promise\n            ? await parentServer.manifest\n            : parentServer.manifest\n          const testerEntry = manifestContent['tester/tester.html']\n\n          testerTags.push({\n            tag: 'script',\n            attrs: {\n              type: 'module',\n              crossorigin: '',\n              src: `${parentServer.base}${testerEntry.file}`,\n            },\n            injectTo: 'head',\n          })\n\n          for (const importName of testerEntry.imports || []) {\n            const entryManifest = manifestContent[importName]\n            if (entryManifest) {\n              testerTags.push(\n                {\n                  tag: 'link',\n                  attrs: {\n                    href: `${parentServer.base}${entryManifest.file}`,\n                    rel: 'modulepreload',\n                    crossorigin: '',\n                  },\n                  injectTo: 'head',\n                },\n              )\n            }\n          }\n        }\n        else {\n          // inject the reset style only in the default template,\n          // allowing users to customize the style in their own template\n          testerTags.push({\n            tag: 'style',\n            children: `\nhtml {\n  padding: 0;\n  margin: 0;\n}\nbody {\n  padding: 0;\n  margin: 0;\n  min-height: 100vh;\n}`,\n            injectTo: 'head',\n          })\n        }\n\n        return [\n          {\n            tag: 'script',\n            children: '{__VITEST_INJECTOR__}',\n            injectTo: 'head-prepend' as const,\n          },\n          {\n            tag: 'script',\n            children: stateJs,\n            injectTo: 'head-prepend',\n          } as const,\n          {\n            tag: 'script',\n            attrs: {\n              type: 'module',\n              src: parentServer.errorCatcherUrl,\n            },\n            injectTo: 'head' as const,\n          },\n          {\n            tag: 'script',\n            attrs: {\n              type: 'module',\n              src: parentServer.matchersUrl,\n            },\n            injectTo: 'head' as const,\n          },\n          ...parentServer.initScripts.map(script => ({\n            tag: 'script',\n            attrs: {\n              type: 'module',\n              src: join('/@fs/', script),\n            },\n            injectTo: 'head',\n          } as const)),\n          ...testerTags,\n        ].filter(s => s != null)\n      },\n    },\n    {\n      name: 'vitest:browser:support-testing-library',\n      enforce: 'pre',\n      config() {\n        const rolldownPlugin = {\n          name: 'vue-test-utils-rewrite',\n          resolveId: {\n            // test-utils: resolve to CJS instead of the browser because the browser version expects a global Vue object\n            // compiler-core: only CJS version allows slots as strings\n            filter: { id: /^@vue\\/(test-utils|compiler-core)$/ },\n            handler(source: string, importer: string) {\n              const resolved = getRequire().resolve(source, {\n                paths: [importer!],\n              })\n              return resolved\n            },\n          },\n        }\n        const esbuildPlugin = {\n          name: 'test-utils-rewrite',\n          // \"any\" because vite doesn't expose any types for this\n          setup(build: any) {\n            // test-utils: resolve to CJS instead of the browser because the browser version expects a global Vue object\n            // compiler-core: only CJS version allows slots as strings\n            build.onResolve({ filter: /^@vue\\/(test-utils|compiler-core)$/ }, (args: any) => {\n              const resolved = getRequire().resolve(args.path, {\n                paths: [args.importer],\n              })\n              return { path: resolved }\n            })\n          },\n        }\n\n        return {\n          optimizeDeps: rolldownVersion\n            ? { rolldownOptions: { plugins: [rolldownPlugin] } }\n            : { esbuildOptions: { plugins: [esbuildPlugin] } },\n        }\n      },\n    },\n    {\n      name: 'vitest:browser:__vitest_browser_import_meta_env_init__',\n      transform: {\n        handler(code) {\n          // this transform runs after `vitest:meta-env-replacer` so that\n          // `import.meta.env` will be handled by Vite import analysis to match behavior.\n          if (code.includes('__vitest_browser_import_meta_env_init__')) {\n            return code.replace('__vitest_browser_import_meta_env_init__', 'import.meta.env')\n          }\n        },\n      },\n    },\n  ]\n}\n\nfunction tryResolve(path: string, paths: string[]) {\n  try {\n    const _require = getRequire()\n    return _require.resolve(path, { paths })\n  }\n  catch {\n    return undefined\n  }\n}\n\nlet _require: NodeRequire\nfunction getRequire() {\n  if (!_require) {\n    _require = createRequire(import.meta.url)\n  }\n  return _require\n}\n\nconst postfixRE = /[?#].*$/\nfunction cleanUrl(url: string): string {\n  return url.replace(postfixRE, '')\n}\n"
  },
  {
    "path": "packages/browser/src/node/plugins/pluginContext.ts",
    "content": "import type { Rollup } from 'vite'\nimport type { Plugin } from 'vitest/config'\nimport type { BrowserProvider } from 'vitest/node'\nimport type { ParentBrowserProject } from '../projectParent'\nimport { fileURLToPath } from 'node:url'\nimport { slash } from '@vitest/utils/helpers'\nimport { dirname, resolve } from 'pathe'\n\nconst VIRTUAL_ID_CONTEXT = '\\0vitest/browser'\nconst ID_CONTEXT = 'vitest/browser'\n// for libraries that use an older import but are not type checked\nconst DEPRECATED_ID_CONTEXT = '@vitest/browser/context'\n\nconst DEPRECATED_VIRTUAL_ID_UTILS = '\\0@vitest/browser/utils'\nconst DEPRECATED_ID_UTILS = '@vitest/browser/utils'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nexport default function BrowserContext(globalServer: ParentBrowserProject): Plugin {\n  return {\n    name: 'vitest:browser:virtual-module:context',\n    enforce: 'pre',\n    resolveId(id, importer) {\n      if (id === ID_CONTEXT) {\n        return VIRTUAL_ID_CONTEXT\n      }\n      if (id === DEPRECATED_ID_CONTEXT) {\n        if (importer && !importer.includes('/node_modules/')) {\n          globalServer.vitest.logger.deprecate(\n            `${importer} tries to load a deprecated \"${id}\" module. `\n            + `This import will stop working in the next major version. `\n            + `Please, use \"vitest/browser\" instead.`,\n          )\n        }\n        return VIRTUAL_ID_CONTEXT\n      }\n      if (id === DEPRECATED_ID_UTILS) {\n        return DEPRECATED_VIRTUAL_ID_UTILS\n      }\n    },\n    load(id) {\n      if (id === VIRTUAL_ID_CONTEXT) {\n        return generateContextFile.call(this, globalServer)\n      }\n      if (id === DEPRECATED_VIRTUAL_ID_UTILS) {\n        return `\nimport { utils } from 'vitest/browser'\nexport const getElementLocatorSelectors = utils.getElementLocatorSelectors\nexport const debug = utils.debug\nexport const prettyDOM = utils.prettyDOM\nexport const getElementError = utils.getElementError\n        `\n      }\n    },\n  }\n}\n\nasync function generateContextFile(\n  this: Rollup.PluginContext,\n  globalServer: ParentBrowserProject,\n) {\n  const commands = Object.keys(globalServer.commands)\n  const provider = [...globalServer.children][0].provider\n  const providerName = provider?.name || 'preview'\n\n  const commandsCode = commands\n    .filter(command => !command.startsWith('__vitest'))\n    .map((command) => {\n      return `    [\"${command}\"]: (...args) => __vitest_browser_runner__.commands.triggerCommand(\"${command}\", args),`\n    })\n    .join('\\n')\n\n  const userEventNonProviderImport = await getUserEventImport(\n    provider,\n    this.resolve.bind(this),\n  )\n  const distContextPath = slash(`/@fs/${resolve(__dirname, 'context.js')}`)\n\n  return `\nimport { page, createUserEvent, cdp, locators, utils } from '${distContextPath}'\n${userEventNonProviderImport}\n\nexport const server = {\n  platform: ${JSON.stringify(process.platform)},\n  version: ${JSON.stringify(process.version)},\n  provider: ${JSON.stringify(providerName)},\n  browser: __vitest_browser_runner__.config.browser.name,\n  commands: {\n    ${commandsCode}\n  },\n  config: __vitest_browser_runner__.config,\n}\nexport const commands = server.commands\nexport const userEvent = createUserEvent(_userEventSetup)\nexport { page, cdp, locators, utils }\n`\n}\n\nasync function getUserEventImport(provider: BrowserProvider | undefined, resolve: (id: string, importer: string) => Promise<null | { id: string }>) {\n  if (!provider || provider.name !== 'preview') {\n    return 'const _userEventSetup = undefined'\n  }\n  const previewDistRoot = (provider as any).distRoot\n  const resolved = await resolve('@testing-library/user-event', previewDistRoot)\n  if (!resolved) {\n    throw new Error(`Failed to resolve user-event package from ${previewDistRoot}`)\n  }\n  return `\\\nimport { userEvent as __vitest_user_event__ } from '${slash(`/@fs/${resolved.id}`)}'\nconst _userEventSetup = __vitest_user_event__\n`\n}\n"
  },
  {
    "path": "packages/browser/src/node/project.ts",
    "content": "import type { StackTraceParserOptions } from '@vitest/utils/source-map'\nimport type { ViteDevServer } from 'vite'\nimport type { ParsedStack, SerializedConfig, TestError } from 'vitest'\nimport type { BrowserCommands } from 'vitest/browser'\nimport type {\n  BrowserCommand,\n  BrowserCommandContext,\n  BrowserProvider,\n  ProjectBrowser as IProjectBrowser,\n  ResolvedConfig,\n  TestProject,\n  Vitest,\n} from 'vitest/node'\nimport type { ParentBrowserProject } from './projectParent'\nimport { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { resolve } from 'pathe'\nimport { distRoot } from './constants'\nimport { BrowserServerState } from './state'\nimport { getBrowserProvider } from './utils'\n\nexport class ProjectBrowser implements IProjectBrowser {\n  public testerHtml: Promise<string> | string\n  public testerFilepath: string\n\n  public provider!: BrowserProvider\n  public vitest: Vitest\n  public vite: ViteDevServer\n  public config: ResolvedConfig\n\n  public state: BrowserServerState = new BrowserServerState()\n\n  constructor(\n    public parent: ParentBrowserProject,\n    public project: TestProject,\n    public base: string,\n  ) {\n    this.vitest = project.vitest\n    this.config = project.config\n    this.vite = parent.vite\n\n    // instances can override testerHtmlPath\n    const testerHtmlPath = project.config.browser.testerHtmlPath\n      ? resolve(project.config.root, project.config.browser.testerHtmlPath)\n      : resolve(distRoot, 'client/tester/tester.html')\n    // TODO: when config resolution is rewritten, project and parentProject should be created before the vite server is started\n    if (!existsSync(testerHtmlPath)) {\n      throw new Error(`Tester HTML file \"${testerHtmlPath}\" doesn't exist.`)\n    }\n    this.testerFilepath = testerHtmlPath\n    this.testerHtml = readFile(\n      this.testerFilepath,\n      'utf8',\n    ).then(html => (this.testerHtml = html))\n  }\n\n  private commands = {} as Record<string, BrowserCommand<any, any>>\n\n  public registerCommand<K extends keyof BrowserCommands>(\n    name: K,\n    cb: BrowserCommand<\n      Parameters<BrowserCommands[K]>,\n      ReturnType<BrowserCommands[K]>\n    >,\n  ): void {\n    if (!/^[a-z_$][\\w$]*$/i.test(name)) {\n      throw new Error(\n        `Invalid command name \"${name}\". Only alphanumeric characters, $ and _ are allowed.`,\n      )\n    }\n    this.commands[name] = cb\n  }\n\n  public triggerCommand = (<K extends keyof BrowserCommand>(\n    name: K,\n    context: BrowserCommandContext,\n    ...args: Parameters<BrowserCommands[K]>\n  ): ReturnType<BrowserCommands[K]> => {\n    if (name in this.commands) {\n      return this.commands[name](context, ...args)\n    }\n    if (name in this.parent.commands) {\n      return this.parent.commands[name](context, ...args)\n    }\n    throw new Error(`Provider ${this.provider.name} does not support command \"${name}\".`)\n  }) as any\n\n  wrapSerializedConfig(): SerializedConfig {\n    const config = wrapConfig(this.project.serializedConfig)\n    config.env ??= {}\n    config.env.VITEST_BROWSER_DEBUG = process.env.VITEST_BROWSER_DEBUG || ''\n    return config\n  }\n\n  async initBrowserProvider(project: TestProject): Promise<void> {\n    if (this.provider) {\n      return\n    }\n    this.provider = await getBrowserProvider(project.config.browser, project)\n    if (this.provider.initScripts) {\n      this.parent.initScripts = this.provider.initScripts\n      // make sure the script can be imported\n      const allow = this.parent.vite.config.server.fs.allow\n      this.provider.initScripts.forEach((script) => {\n        if (!allow.includes(script)) {\n          allow.push(script)\n        }\n      })\n    }\n  }\n\n  public parseErrorStacktrace(\n    e: TestError,\n    options: StackTraceParserOptions = {},\n  ): ParsedStack[] {\n    return this.parent.parseErrorStacktrace(e, options)\n  }\n\n  public parseStacktrace(\n    trace: string,\n    options: StackTraceParserOptions = {},\n  ): ParsedStack[] {\n    return this.parent.parseStacktrace(trace, options)\n  }\n\n  async close(): Promise<void> {\n    await this.vite.close()\n  }\n}\n\nfunction wrapConfig(config: SerializedConfig): SerializedConfig {\n  return {\n    ...config,\n    // workaround RegExp serialization\n    testNamePattern: config.testNamePattern\n      ? (config.testNamePattern.toString() as any as RegExp)\n      : undefined,\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/projectParent.ts",
    "content": "import type { StackTraceParserOptions } from '@vitest/utils/source-map'\nimport type { HtmlTagDescriptor } from 'vite'\nimport type { ParsedStack, TestError } from 'vitest'\nimport type {\n  BrowserCommand,\n  BrowserScript,\n  CDPSession,\n  ResolvedConfig,\n  TestProject,\n  Vite,\n  Vitest,\n} from 'vitest/node'\nimport type { BrowserServerState } from './state'\nimport { readFile } from 'node:fs/promises'\nimport { parseErrorStacktrace, parseStacktrace } from '@vitest/utils/source-map'\nimport { extractSourcemapFromFile } from '@vitest/utils/source-map/node'\nimport { join, resolve } from 'pathe'\nimport { BrowserServerCDPHandler } from './cdp'\nimport builtinCommands from './commands/index'\nimport { distRoot } from './constants'\nimport { ProjectBrowser } from './project'\nimport { slash } from './utils'\n\nexport class ParentBrowserProject {\n  public orchestratorScripts: string | undefined\n\n  public faviconUrl: string\n  public prefixOrchestratorUrl: string\n  public prefixTesterUrl: string\n  public manifest: Promise<Vite.Manifest> | Vite.Manifest\n\n  public vite!: Vite.ViteDevServer\n  private stackTraceOptions: StackTraceParserOptions\n  public orchestratorHtml: Promise<string> | string\n  public injectorJs: Promise<string> | string\n  public errorCatcherUrl: string\n  public locatorsUrl: string | undefined\n  public matchersUrl: string\n  public stateJs: Promise<string> | string\n\n  public initScripts: string[] = []\n\n  public commands: Record<string, BrowserCommand<any>> = {}\n  public children: Set<ProjectBrowser> = new Set()\n  public vitest: Vitest\n\n  public config: ResolvedConfig\n\n  // cache for non-vite source maps\n  private sourceMapCache = new Map<string, any>()\n\n  constructor(\n    public project: TestProject,\n    public base: string,\n  ) {\n    this.vitest = project.vitest\n    this.config = project.config\n    this.stackTraceOptions = {\n      frameFilter: project.config.onStackTrace,\n      getSourceMap: (id) => {\n        if (this.sourceMapCache.has(id)) {\n          return this.sourceMapCache.get(id)\n        }\n\n        const result = this.vite.moduleGraph.getModuleById(id)?.transformResult\n        // handle non-inline source map such as pre-bundled deps in node_modules/.vite\n        if (result && !result.map) {\n          const filePath = id.split('?')[0]\n          const extracted = extractSourcemapFromFile(result.code, filePath)\n          this.sourceMapCache.set(id, extracted?.map)\n          return extracted?.map\n        }\n\n        this.sourceMapCache.set(id, result?.map)\n        return result?.map\n      },\n      getUrlId: (id) => {\n        const moduleGraph = this.vite.environments.client.moduleGraph\n        const mod = moduleGraph.getModuleById(id)\n        if (mod) {\n          return id\n        }\n        const resolvedPath = resolve(this.vite.config.root, id.slice(1))\n        const modUrl = moduleGraph.getModuleById(resolvedPath)\n        if (modUrl) {\n          return resolvedPath\n        }\n        // some browsers (looking at you, safari) don't report queries in stack traces\n        // the next best thing is to try the first id that this file resolves to\n        const files = moduleGraph.getModulesByFile(resolvedPath)\n        if (files && files.size) {\n          return files.values().next().value!.id!\n        }\n        return id\n      },\n    }\n\n    for (const [name, command] of Object.entries(builtinCommands)) {\n      this.commands[name] ??= command\n    }\n\n    // validate names because they can't be used as identifiers\n    for (const command in project.config.browser.commands) {\n      if (!/^[a-z_$][\\w$]*$/i.test(command)) {\n        throw new Error(\n          `Invalid command name \"${command}\". Only alphanumeric characters, $ and _ are allowed.`,\n        )\n      }\n      this.commands[command] = project.config.browser.commands[command]\n    }\n\n    this.prefixTesterUrl = `${base || '/'}`\n    this.prefixOrchestratorUrl = `${base}__vitest_test__/`\n    this.faviconUrl = `${base}__vitest__/favicon.svg`\n\n    this.manifest = (async () => {\n      return JSON.parse(\n        await readFile(`${distRoot}/client/.vite/manifest.json`, 'utf8'),\n      )\n    })().then(manifest => (this.manifest = manifest))\n\n    this.orchestratorHtml = (project.config.browser.ui\n      ? readFile(resolve(distRoot, 'client/__vitest__/index.html'), 'utf8')\n      : readFile(resolve(distRoot, 'client/orchestrator.html'), 'utf8'))\n      .then(html => (this.orchestratorHtml = html))\n    this.injectorJs = readFile(\n      resolve(distRoot, 'client/esm-client-injector.js'),\n      'utf8',\n    ).then(js => (this.injectorJs = js))\n    this.errorCatcherUrl = join('/@fs/', resolve(distRoot, 'client/error-catcher.js'))\n\n    this.matchersUrl = join('/@fs/', distRoot, 'expect-element.js')\n    this.stateJs = readFile(\n      resolve(distRoot, 'state.js'),\n      'utf-8',\n    ).then(js => (this.stateJs = js))\n  }\n\n  public setServer(vite: Vite.ViteDevServer): void {\n    this.vite = vite\n  }\n\n  public spawn(project: TestProject): ProjectBrowser {\n    if (!this.vite) {\n      throw new Error(`Cannot spawn child server without a parent dev server.`)\n    }\n    const clone = new ProjectBrowser(\n      this,\n      project,\n      '/',\n    )\n    this.children.add(clone)\n    return clone\n  }\n\n  public parseErrorStacktrace(\n    e: TestError,\n    options: StackTraceParserOptions = {},\n  ): ParsedStack[] {\n    return parseErrorStacktrace(e, {\n      ...this.stackTraceOptions,\n      ...options,\n    })\n  }\n\n  public parseStacktrace(\n    trace: string,\n    options: StackTraceParserOptions = {},\n  ): ParsedStack[] {\n    return parseStacktrace(trace, {\n      ...this.stackTraceOptions,\n      ...options,\n    })\n  }\n\n  public readonly cdps: Map<string, BrowserServerCDPHandler> = new Map()\n  private cdpSessionsPromises = new Map<string, Promise<CDPSession>>()\n\n  async ensureCDPHandler(sessionId: string, rpcId: string): Promise<BrowserServerCDPHandler> {\n    const cachedHandler = this.cdps.get(rpcId)\n    if (cachedHandler) {\n      return cachedHandler\n    }\n    const browserSession = this.vitest._browserSessions.getSession(sessionId)\n    if (!browserSession) {\n      throw new Error(`Session \"${sessionId}\" not found.`)\n    }\n\n    const browser = browserSession.project.browser!\n    const provider = browser.provider\n    if (!provider) {\n      throw new Error(`Browser provider is not defined for the project \"${browserSession.project.name}\".`)\n    }\n    if (!provider.getCDPSession) {\n      throw new Error(`CDP is not supported by the provider \"${provider.name}\".`)\n    }\n\n    const session = await this.cdpSessionsPromises.get(rpcId) ?? await (async () => {\n      const promise = provider.getCDPSession!(sessionId).finally(() => {\n        this.cdpSessionsPromises.delete(rpcId)\n      })\n      this.cdpSessionsPromises.set(rpcId, promise)\n      return promise\n    })()\n\n    const rpc = (browser.state as BrowserServerState).testers.get(rpcId)\n    if (!rpc) {\n      throw new Error(`Tester RPC \"${rpcId}\" was not established.`)\n    }\n\n    const handler = new BrowserServerCDPHandler(session, rpc)\n    this.cdps.set(\n      rpcId,\n      handler,\n    )\n    return handler\n  }\n\n  removeCDPHandler(sessionId: string): void {\n    this.cdps.delete(sessionId)\n  }\n\n  async formatScripts(scripts: BrowserScript[] | undefined): Promise<HtmlTagDescriptor[]> {\n    if (!scripts?.length) {\n      return []\n    }\n    const server = this.vite\n    const promises = scripts.map(\n      async ({ content, src, async, id, type = 'module' }, index): Promise<HtmlTagDescriptor> => {\n        const srcLink = (src ? (await server.pluginContainer.resolveId(src))?.id : undefined) || src\n        const transformId = srcLink || join(server.config.root, `virtual__${id || `injected-${index}.js`}`)\n        await server.moduleGraph.ensureEntryFromUrl(transformId)\n        const contentProcessed\n          = content && type === 'module'\n            ? (await server.pluginContainer.transform(content, transformId)).code\n            : content\n        return {\n          tag: 'script',\n          attrs: {\n            type,\n            ...(async ? { async: '' } : {}),\n            ...(srcLink\n              ? {\n                  src: srcLink.startsWith('http') ? srcLink : slash(`/@fs/${srcLink}`),\n                }\n              : {}),\n          },\n          injectTo: 'head',\n          children: contentProcessed || '',\n        }\n      },\n    )\n    return (await Promise.all(promises))\n  }\n\n  resolveTesterUrl(pathname: string): { sessionId: string; testFile: string } {\n    const [sessionId, testFile] = pathname\n      .slice(this.prefixTesterUrl.length)\n      .split('/')\n    const decodedTestFile = decodeURIComponent(testFile)\n    return { sessionId, testFile: decodedTestFile }\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/rpc.ts",
    "content": "import type { MockerRegistry } from '@vitest/mocker'\nimport type { Duplex } from 'node:stream'\nimport type { TestError } from 'vitest'\nimport type { BrowserCommandContext, ResolveSnapshotPathHandlerContext, TestProject } from 'vitest/node'\nimport type { WebSocket } from 'ws'\nimport type { WebSocketBrowserEvents, WebSocketBrowserHandlers } from '../types'\nimport type { ParentBrowserProject } from './projectParent'\nimport type { BrowserServerState } from './state'\nimport { existsSync, promises as fs } from 'node:fs'\nimport { AutomockedModule, AutospiedModule, ManualMockedModule, RedirectedModule } from '@vitest/mocker'\nimport { ServerMockResolver } from '@vitest/mocker/node'\nimport { extractSourcemapFromFile } from '@vitest/utils/source-map/node'\nimport { createBirpc } from 'birpc'\nimport { parse, stringify } from 'flatted'\nimport { dirname, join } from 'pathe'\nimport { createDebugger, isFileLoadingAllowed, isValidApiRequest } from 'vitest/node'\nimport { WebSocketServer } from 'ws'\n\nconst debug = createDebugger('vitest:browser:api')\n\nconst BROWSER_API_PATH = '/__vitest_browser_api__'\n\nexport function setupBrowserRpc(globalServer: ParentBrowserProject, defaultMockerRegistry: MockerRegistry): void {\n  const vite = globalServer.vite\n  const vitest = globalServer.vitest\n\n  const wss = new WebSocketServer({ noServer: true })\n\n  vite.httpServer?.on('upgrade', (request, socket: Duplex, head: Buffer) => {\n    if (!request.url) {\n      return\n    }\n\n    const { pathname, searchParams } = new URL(request.url, 'http://localhost')\n    if (pathname !== BROWSER_API_PATH) {\n      return\n    }\n\n    if (!isValidApiRequest(vitest.config, request)) {\n      socket.destroy()\n      return\n    }\n\n    const type = searchParams.get('type')\n    const rpcId = searchParams.get('rpcId')\n    const sessionId = searchParams.get('sessionId')\n    const projectName = searchParams.get('projectName')\n\n    if (type !== 'tester' && type !== 'orchestrator') {\n      return error(\n        new Error(`[vitest] Type query in ${request.url} is invalid. Type should be either \"tester\" or \"orchestrator\".`),\n      )\n    }\n\n    if (!sessionId || !rpcId || projectName == null) {\n      return error(\n        new Error(`[vitest] Invalid URL ${request.url}. \"projectName\", \"sessionId\" and \"rpcId\" queries are required.`),\n      )\n    }\n\n    const sessions = vitest._browserSessions\n\n    if (!sessions.sessionIds.has(sessionId)) {\n      const ids = [...sessions.sessionIds].join(', ')\n      return error(\n        new Error(`[vitest] Unknown session id \"${sessionId}\". Expected one of ${ids}.`),\n      )\n    }\n\n    if (type === 'orchestrator') {\n      const session = sessions.getSession(sessionId)\n      // it's possible the session was already resolved by the preview provider\n      session?.connected()\n    }\n\n    const project = vitest.getProjectByName(projectName)\n\n    if (!project) {\n      return error(\n        new Error(`[vitest] Project \"${projectName}\" not found.`),\n      )\n    }\n\n    wss.handleUpgrade(request, socket, head, (ws) => {\n      wss.emit('connection', ws, request)\n\n      const { rpc, offCancel } = setupClient(project, rpcId, ws)\n      const state = project.browser!.state as BrowserServerState\n      const clients = type === 'tester' ? state.testers : state.orchestrators\n      clients.set(rpcId, rpc)\n\n      debug?.('[%s] Browser API connected to %s', rpcId, type)\n\n      ws.on('close', () => {\n        debug?.('[%s] Browser API disconnected from %s', rpcId, type)\n        offCancel()\n        clients.delete(rpcId)\n        globalServer.removeCDPHandler(rpcId)\n        if (type === 'orchestrator') {\n          sessions.destroySession(sessionId)\n        }\n        // this will reject any hanging methods if there are any\n        rpc.$close(\n          new Error(`[vitest] Browser connection was closed while running tests. Was the page closed unexpectedly?`),\n        )\n      })\n    })\n  })\n\n  // we don't throw an error inside a stream because this can segfault the process\n  function error(err: Error) {\n    console.error(err)\n    vitest.state.catchError(err, 'RPC Error')\n  }\n\n  function checkFileAccess(path: string) {\n    if (!isFileLoadingAllowed(vite.config, path)) {\n      throw new Error(\n        `Access denied to \"${path}\". See Vite config documentation for \"server.fs\": https://vitejs.dev/config/server-options.html#server-fs-strict.`,\n      )\n    }\n  }\n\n  function canWrite(project: TestProject) {\n    return (\n      project.config.browser.api.allowWrite\n      && project.vitest.config.browser.api.allowWrite\n      && project.config.api.allowWrite\n      && project.vitest.config.api.allowWrite\n    )\n  }\n\n  function setupClient(project: TestProject, rpcId: string, ws: WebSocket) {\n    const mockResolver = new ServerMockResolver(globalServer.vite, {\n      moduleDirectories: project.config?.deps?.moduleDirectories,\n    })\n    const mocker = project.browser?.provider.mocker\n\n    const rpc = createBirpc<WebSocketBrowserEvents, WebSocketBrowserHandlers>(\n      {\n        async onUnhandledError(error, type) {\n          if (error && typeof error === 'object') {\n            const _error = error as TestError\n            _error.stacks = globalServer.parseErrorStacktrace(_error)\n          }\n          vitest.state.catchError(error, type)\n        },\n        async onQueued(method, file) {\n          if (method === 'collect') {\n            vitest.state.collectFiles(project, [file])\n          }\n          else {\n            await vitest._testRun.enqueued(project, file)\n          }\n        },\n        async onCollected(method, files) {\n          if (method === 'collect') {\n            vitest.state.collectFiles(project, files)\n          }\n          else {\n            await vitest._testRun.collected(project, files)\n          }\n        },\n        async onTaskArtifactRecord(id, artifact) {\n          if (!canWrite(project)) {\n            if (artifact.type === 'internal:annotation' && artifact.annotation.attachment) {\n              artifact.annotation.attachment = undefined\n              vitest.logger.error(\n                `[vitest] Cannot record annotation attachment because file writing is disabled. See https://vitest.dev/config/browser/api.`,\n              )\n            }\n            // remove attachments if cannot write\n            if (artifact.attachments?.length) {\n              const attachments = artifact.attachments.map(n => n.path).filter(r => !!r).join('\", \"')\n              artifact.attachments = []\n              vitest.logger.error(\n                `[vitest] Cannot record attachments (\"${attachments}\") because file writing is disabled, removing attachments from artifact \"${artifact.type}\". See https://vitest.dev/config/browser/api.`,\n              )\n            }\n          }\n\n          return vitest._testRun.recordArtifact(id, artifact)\n        },\n        async onTaskUpdate(method, packs, events) {\n          if (method === 'collect') {\n            vitest.state.updateTasks(packs)\n          }\n          else {\n            await vitest._testRun.updated(packs, events)\n          }\n        },\n        onAfterSuiteRun(meta) {\n          vitest.coverageProvider?.onAfterSuiteRun(meta)\n        },\n        async sendLog(method, log) {\n          if (method === 'collect') {\n            vitest.state.updateUserLog(log)\n          }\n          else {\n            await vitest._testRun.log(log)\n          }\n        },\n        resolveSnapshotPath(testPath) {\n          return vitest.snapshot.resolvePath<ResolveSnapshotPathHandlerContext>(testPath, {\n            config: project.serializedConfig,\n          })\n        },\n        resolveSnapshotRawPath(testPath, rawPath) {\n          return vitest.snapshot.resolveRawPath(testPath, rawPath)\n        },\n        snapshotSaved(snapshot) {\n          vitest.snapshot.add(snapshot)\n        },\n        async readSnapshotFile(snapshotPath) {\n          checkFileAccess(snapshotPath)\n          if (!existsSync(snapshotPath)) {\n            return null\n          }\n          return fs.readFile(snapshotPath, 'utf-8')\n        },\n        async saveSnapshotFile(id, content) {\n          checkFileAccess(id)\n          if (!canWrite(project)) {\n            vitest.logger.error(\n              `[vitest] Cannot save snapshot file \"${id}\". File writing is disabled because server is exposed to the internet, see https://vitest.dev/config/browser/api.`,\n            )\n            return\n          }\n          await fs.mkdir(dirname(id), { recursive: true })\n          await fs.writeFile(id, content, 'utf-8')\n        },\n        async removeSnapshotFile(id) {\n          checkFileAccess(id)\n          if (!canWrite(project)) {\n            vitest.logger.error(\n              `[vitest] Cannot remove snapshot file \"${id}\". File writing is disabled because server is exposed to the internet, see https://vitest.dev/config/browser/api.`,\n            )\n            return\n          }\n          if (!existsSync(id)) {\n            throw new Error(`Snapshot file \"${id}\" does not exist.`)\n          }\n          await fs.unlink(id)\n        },\n        getBrowserFileSourceMap(id) {\n          const mod = globalServer.vite.moduleGraph.getModuleById(id)\n          const result = mod?.transformResult\n          // handle non-inline source map such as pre-bundled deps in node_modules/.vite\n          if (result && !result.map) {\n            const filePath = id.split('?')[0]\n            const extracted = extractSourcemapFromFile(result.code, filePath)\n            return extracted?.map\n          }\n          return result?.map\n        },\n        cancelCurrentRun(reason) {\n          vitest.cancelCurrentRun(reason)\n        },\n        async resolveId(id, importer) {\n          return mockResolver.resolveId(id, importer)\n        },\n        debug(...args) {\n          vitest.logger.console.debug(...args)\n        },\n        getCountOfFailedTests() {\n          return vitest.state.getCountOfFailedTests()\n        },\n        async wdioSwitchContext(direction) {\n          const provider = project.browser!.provider\n          if (!provider) {\n            throw new Error('Commands are only available for browser tests.')\n          }\n          if (provider.name !== 'webdriverio') {\n            throw new Error('Switch context is only available for WebDriverIO provider.')\n          }\n          if (direction === 'iframe') {\n            await (provider as any).switchToTestFrame()\n          }\n          else {\n            await (provider as any).switchToMainFrame()\n          }\n        },\n        async triggerCommand(sessionId, command, testPath, payload) {\n          debug?.('[%s] Triggering command \"%s\"', sessionId, command)\n          const provider = project.browser!.provider\n          if (!provider) {\n            throw new Error('Commands are only available for browser tests.')\n          }\n          const context = Object.assign(\n            {\n              testPath,\n              project,\n              provider,\n              contextId: sessionId,\n              sessionId,\n              triggerCommand: (name: string, ...args: any[]) => {\n                return project.browser!.triggerCommand(\n                  name as any,\n                  context,\n                  ...args,\n                )\n              },\n            },\n            provider.getCommandsContext(sessionId),\n          ) as any as BrowserCommandContext\n          return await project.browser!.triggerCommand(\n            command as any,\n            context,\n            ...payload,\n          )\n        },\n        resolveMock(rawId, importer, options) {\n          return mockResolver.resolveMock(rawId, importer, options)\n        },\n        invalidate(ids) {\n          return mockResolver.invalidate(ids)\n        },\n\n        async registerMock(sessionId, module) {\n          if (!mocker) {\n            // make sure modules are not processed yet in case they were imported before\n            // and were not mocked\n            mockResolver.invalidate([module.id])\n\n            if (module.type === 'manual') {\n              const mock = ManualMockedModule.fromJSON(module, async () => {\n                try {\n                  const { keys } = await rpc.resolveManualMock(module.url)\n                  return Object.fromEntries(keys.map(key => [key, null]))\n                }\n                catch (err) {\n                  vitest.state.catchError(err, 'Manual Mock Resolver Error')\n                  return {}\n                }\n              })\n              defaultMockerRegistry.add(mock)\n            }\n            else {\n              if (module.type === 'redirect') {\n                const redirectUrl = new URL(module.redirect)\n                module.redirect = join(vite.config.root, redirectUrl.pathname)\n              }\n              defaultMockerRegistry.register(module)\n            }\n            return\n          }\n\n          if (module.type === 'manual') {\n            const manualModule = ManualMockedModule.fromJSON(module, async () => {\n              const { keys } = await rpc.resolveManualMock(module.url)\n              return Object.fromEntries(keys.map(key => [key, null]))\n            })\n            await mocker.register(sessionId, manualModule)\n          }\n          else if (module.type === 'redirect') {\n            await mocker.register(sessionId, RedirectedModule.fromJSON(module))\n          }\n          else if (module.type === 'automock') {\n            await mocker.register(sessionId, AutomockedModule.fromJSON(module))\n          }\n          else if (module.type === 'autospy') {\n            await mocker.register(sessionId, AutospiedModule.fromJSON(module))\n          }\n        },\n        clearMocks(sessionId) {\n          if (!mocker) {\n            return defaultMockerRegistry.clear()\n          }\n          return mocker.clear(sessionId)\n        },\n        unregisterMock(sessionId, id) {\n          if (!mocker) {\n            return defaultMockerRegistry.delete(id)\n          }\n          return mocker.delete(sessionId, id)\n        },\n\n        // CDP\n        async sendCdpEvent(sessionId: string, event: string, payload?: Record<string, unknown>) {\n          const cdp = await globalServer.ensureCDPHandler(sessionId, rpcId)\n          return cdp.send(event, payload)\n        },\n        async trackCdpEvent(sessionId: string, type: 'on' | 'once' | 'off', event: string, listenerId: string) {\n          const cdp = await globalServer.ensureCDPHandler(sessionId, rpcId)\n          cdp[type](event, listenerId)\n        },\n      },\n      {\n        post: msg => ws.send(msg),\n        on: fn => ws.on('message', fn),\n        eventNames: ['onCancel', 'cdpEvent'],\n        serialize: (data: any) => stringify(data, stringifyReplace),\n        deserialize: parse,\n        timeout: -1, // createTesters can take a long time\n      },\n    )\n\n    const offCancel = vitest.onCancel(reason => rpc.onCancel(reason))\n\n    return { rpc, offCancel }\n  }\n}\n\n// Serialization support utils.\nfunction cloneByOwnProperties(value: any) {\n  // Clones the value's properties into a new Object. The simpler approach of\n  // Object.assign() won't work in the case that properties are not enumerable.\n  return Object.getOwnPropertyNames(value).reduce(\n    (clone, prop) => ({\n      ...clone,\n      [prop]: value[prop],\n    }),\n    {},\n  )\n}\n\n/**\n * Replacer function for serialization methods such as JS.stringify() or\n * flatted.stringify().\n */\nexport function stringifyReplace(key: string, value: any): any {\n  if (value instanceof Error) {\n    const cloned = cloneByOwnProperties(value)\n    return {\n      name: value.name,\n      message: value.message,\n      stack: value.stack,\n      ...cloned,\n    }\n  }\n  else {\n    return value\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/serverOrchestrator.ts",
    "content": "import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { ProjectBrowser } from './project'\nimport type { ParentBrowserProject } from './projectParent'\nimport { stringify } from 'flatted'\nimport { replacer } from './utils'\n\nexport async function resolveOrchestrator(\n  globalServer: ParentBrowserProject,\n  url: URL,\n  res: ServerResponse<IncomingMessage>,\n): Promise<string | undefined> {\n  let sessionId = url.searchParams.get('sessionId')\n  // it's possible to open the page without a context\n  if (!sessionId) {\n    const contexts = [...globalServer.children].flatMap(p => [...p.state.orchestrators.keys()])\n    sessionId = contexts.at(-1) ?? 'none'\n  }\n\n  // it's ok to not have a session here, especially in the preview provider\n  // because the user could refresh the page which would remove the session id from the url\n\n  const session = globalServer.vitest._browserSessions.getSession(sessionId!)\n  const browserProject = (session?.project.browser as ProjectBrowser | undefined) || [...globalServer.children][0]\n\n  if (!browserProject) {\n    return\n  }\n\n  // ignore unknown pages\n  if (sessionId && sessionId !== 'none' && !globalServer.vitest._browserSessions.sessionIds.has(sessionId)) {\n    return\n  }\n\n  const injectorJs = typeof globalServer.injectorJs === 'string'\n    ? globalServer.injectorJs\n    : await globalServer.injectorJs\n\n  const injector = replacer(injectorJs, {\n    __VITEST_PROVIDER__: JSON.stringify(browserProject.config.browser.provider?.name || 'preview'),\n    __VITEST_CONFIG__: JSON.stringify(browserProject.wrapSerializedConfig()),\n    __VITEST_VITE_CONFIG__: JSON.stringify({\n      root: browserProject.vite.config.root,\n    }),\n    __VITEST_METHOD__: JSON.stringify('orchestrate'),\n    __VITEST_TYPE__: '\"orchestrator\"',\n    __VITEST_SESSION_ID__: JSON.stringify(sessionId),\n    __VITEST_TESTER_ID__: '\"none\"',\n    __VITEST_OTEL_CARRIER__: url.searchParams.get('otelCarrier') ?? 'null',\n    __VITEST_PROVIDED_CONTEXT__: JSON.stringify(stringify(browserProject.project.getProvidedContext())),\n    __VITEST_API_TOKEN__: JSON.stringify(globalServer.vitest.config.api.token),\n  })\n\n  // disable CSP for the orchestrator as we are the ones controlling it\n  res.removeHeader('Content-Security-Policy')\n\n  if (!globalServer.orchestratorScripts) {\n    globalServer.orchestratorScripts = (await globalServer.formatScripts(\n      globalServer.config.browser.orchestratorScripts,\n    )).map((script) => {\n      let html = '<script '\n      for (const attr in script.attrs || {}) {\n        html += `${attr}=\"${script.attrs![attr]}\" `\n      }\n      html += `>${script.children}</script>`\n      return html\n    }).join('\\n')\n  }\n\n  let baseHtml = typeof globalServer.orchestratorHtml === 'string'\n    ? globalServer.orchestratorHtml\n    : await globalServer.orchestratorHtml\n\n  // if UI is enabled, use UI HTML and inject the orchestrator script\n  if (globalServer.config.browser.ui) {\n    const manifestContent = globalServer.manifest instanceof Promise\n      ? await globalServer.manifest\n      : globalServer.manifest\n    const jsEntry = manifestContent['orchestrator.html'].file\n    const base = browserProject.parent.vite.config.base || '/'\n    baseHtml = baseHtml\n      .replace('href=\"./favicon.ico\"', `href=\"${base}__vitest__/favicon.ico\"`)\n      .replace('href=\"./favicon.svg\"', `href=\"${base}__vitest__/favicon.svg\"`)\n      .replaceAll('./assets/', `${base}__vitest__/assets/`)\n      .replace(\n        '<!-- !LOAD_METADATA! -->',\n        [\n          '{__VITEST_INJECTOR__}',\n          '{__VITEST_ERROR_CATCHER__}',\n          '{__VITEST_SCRIPTS__}',\n          `<script type=\"module\" crossorigin src=\"${base}${jsEntry}\"></script>`,\n        ].join('\\n'),\n      )\n  }\n\n  return replacer(baseHtml, {\n    __VITEST_FAVICON__: globalServer.faviconUrl,\n    __VITEST_TITLE__: 'Vitest Browser Runner',\n    __VITEST_SCRIPTS__: globalServer.orchestratorScripts,\n    __VITEST_INJECTOR__: `<script type=\"module\">${injector}</script>`,\n    __VITEST_ERROR_CATCHER__: `<script type=\"module\" src=\"${globalServer.errorCatcherUrl}\"></script>`,\n    __VITEST_SESSION_ID__: JSON.stringify(sessionId),\n  })\n}\n"
  },
  {
    "path": "packages/browser/src/node/serverTester.ts",
    "content": "import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { Connect } from 'vite'\nimport type { ProjectBrowser } from './project'\nimport type { ParentBrowserProject } from './projectParent'\nimport crypto from 'node:crypto'\nimport { join } from 'pathe'\nimport { replacer } from './utils'\n\nexport async function resolveTester(\n  globalServer: ParentBrowserProject,\n  url: URL,\n  res: ServerResponse<IncomingMessage>,\n  next: Connect.NextFunction,\n): Promise<string | undefined> {\n  const csp = res.getHeader('Content-Security-Policy')\n  if (typeof csp === 'string') {\n    // add frame-ancestors to allow the iframe to be loaded by Vitest,\n    // but keep the rest of the CSP\n    res.setHeader(\n      'Content-Security-Policy',\n      csp.replace(/frame-ancestors [^;]+/, 'frame-ancestors *'),\n    )\n  }\n\n  const sessionId = url.searchParams.get('sessionId') || 'none'\n  const session = globalServer.vitest._browserSessions.getSession(sessionId)\n\n  if (!session) {\n    res.statusCode = 400\n    res.end('Invalid session ID')\n    return\n  }\n\n  const project = globalServer.vitest.getProjectByName(session.project.name || '')\n  const browserProject = (project.browser as ProjectBrowser | undefined) || [...globalServer.children][0]\n\n  if (!browserProject) {\n    res.statusCode = 400\n    res.end('Invalid session ID')\n    return\n  }\n\n  const injectorJs: string = typeof globalServer.injectorJs === 'string'\n    ? globalServer.injectorJs\n    : await globalServer.injectorJs\n\n  const injector = replacer(injectorJs, {\n    __VITEST_PROVIDER__: JSON.stringify(project.browser!.provider.name),\n    __VITEST_CONFIG__: JSON.stringify(browserProject.wrapSerializedConfig()),\n    __VITEST_VITE_CONFIG__: JSON.stringify({\n      root: browserProject.vite.config.root,\n    }),\n    __VITEST_TYPE__: '\"tester\"',\n    __VITEST_METHOD__: JSON.stringify('none'),\n    __VITEST_SESSION_ID__: JSON.stringify(sessionId),\n    __VITEST_OTEL_CARRIER__: JSON.stringify(null),\n    __VITEST_TESTER_ID__: JSON.stringify(crypto.randomUUID()),\n    __VITEST_PROVIDED_CONTEXT__: '{}',\n    __VITEST_API_TOKEN__: JSON.stringify(globalServer.vitest.config.api.token),\n  })\n\n  const testerHtml = typeof browserProject.testerHtml === 'string'\n    ? browserProject.testerHtml\n    : await browserProject.testerHtml\n\n  try {\n    const url = join('/@fs/', browserProject.testerFilepath)\n    const indexhtml = await browserProject.vite.transformIndexHtml(url, testerHtml)\n    const html = replacer(indexhtml, {\n      __VITEST_FAVICON__: globalServer.faviconUrl,\n      __VITEST_INJECTOR__: injector,\n    })\n    return html\n  }\n  catch (err: any) {\n    session.fail(err)\n    next(err)\n  }\n}\n"
  },
  {
    "path": "packages/browser/src/node/state.ts",
    "content": "import type { BrowserServerState as IBrowserServerState } from 'vitest/node'\nimport type { WebSocketBrowserRPC } from '../types'\n\nexport class BrowserServerState implements IBrowserServerState {\n  public readonly orchestrators: Map<string, WebSocketBrowserRPC> = new Map()\n  public readonly testers: Map<string, WebSocketBrowserRPC> = new Map()\n}\n"
  },
  {
    "path": "packages/browser/src/node/utils.ts",
    "content": "import type {\n  BrowserProvider,\n  ResolvedBrowserOptions,\n  ResolvedConfig,\n  TestProject,\n} from 'vitest/node'\n\nimport { defaultKeyMap } from '@testing-library/user-event/dist/esm/keyboard/keyMap.js'\nimport { parseKeyDef as tlParse } from '@testing-library/user-event/dist/esm/keyboard/parseKeyDef.js'\nimport { basename, dirname, relative, resolve } from 'pathe'\n\ndeclare enum DOM_KEY_LOCATION {\n  STANDARD = 0,\n  LEFT = 1,\n  RIGHT = 2,\n  NUMPAD = 3,\n}\n\ninterface keyboardKey {\n  /** Physical location on a keyboard */\n  code?: string\n  /** Character or functional key descriptor */\n  key?: string\n  /** Location on the keyboard for keys with multiple representation */\n  location?: DOM_KEY_LOCATION\n  /** Does the character in `key` require/imply AltRight to be pressed? */\n  altGr?: boolean\n  /** Does the character in `key` require/imply a shiftKey to be pressed? */\n  shift?: boolean\n}\n\nexport function parseKeyDef(text: string): {\n  keyDef: keyboardKey\n  releasePrevious: boolean\n  releaseSelf: boolean\n  repeat: number\n}[] {\n  return tlParse(defaultKeyMap, text)\n}\n\nexport function replacer(code: string, values: Record<string, string>): string {\n  return code.replace(/\\{\\s*(\\w+)\\s*\\}/g, (_, key) => values[key] ?? _)\n}\n\nexport function resolveScreenshotPath(\n  testPath: string,\n  name: string,\n  config: ResolvedConfig,\n  customPath: string | undefined,\n): string {\n  if (customPath) {\n    return resolve(dirname(testPath), customPath)\n  }\n  const dir = dirname(testPath)\n  const base = basename(testPath)\n  if (config.browser.screenshotDirectory) {\n    return resolve(\n      config.browser.screenshotDirectory,\n      relative(config.root, dir),\n      base,\n      name,\n    )\n  }\n  return resolve(dir, '__screenshots__', base, name)\n}\n\nexport async function getBrowserProvider(\n  options: ResolvedBrowserOptions,\n  project: TestProject,\n): Promise<BrowserProvider> {\n  const browser = project.config.browser.name\n  const name = project.name ? `[${project.name}] ` : ''\n  if (!browser) {\n    throw new Error(\n      `${name}Browser name is required. Please, set \\`test.browser.instances[].browser\\` option manually.`,\n    )\n  }\n  if (options.provider == null) {\n    throw new Error(`Browser Mode requires the \"provider\" to always be specified.`)\n  }\n  const supportedBrowsers = options.provider.supportedBrowser || []\n  if (supportedBrowsers.length && !supportedBrowsers.includes(browser)) {\n    throw new Error(\n      `${name}Browser \"${browser}\" is not supported by the browser provider \"${\n        options.provider.name\n      }\". Supported browsers: ${supportedBrowsers.join(', ')}.`,\n    )\n  }\n  if (typeof options.provider.providerFactory !== 'function') {\n    throw new TypeError(`The \"${name}\" browser provider does not provide a \"providerFactory\" function. Received ${typeof options.provider.providerFactory}.`)\n  }\n  return options.provider.providerFactory(project)\n}\n\nexport function slash(path: string): string {\n  return path.replace(/\\\\/g, '/').replace(/\\/+/g, '/')\n}\n"
  },
  {
    "path": "packages/browser/src/shared/screenshotMatcher/types.ts",
    "content": "import type { ScreenshotComparatorRegistry, ScreenshotMatcherOptions } from '../../../context'\n\nexport type ScreenshotMatcherArguments<\n  ComparatorName extends keyof ScreenshotComparatorRegistry = keyof ScreenshotComparatorRegistry,\n> = [\n  name: string,\n  testName: string,\n  options: ScreenshotMatcherOptions<ComparatorName>\n    & {\n      element: string\n      screenshotOptions?: ScreenshotMatcherOptions<ComparatorName>['screenshotOptions'] & { mask?: readonly string[] }\n    },\n]\n\ninterface ScreenshotData { path: string; width: number; height: number }\n\nexport type ScreenshotMatcherOutput = Promise<\n  {\n    pass: false\n    reference: ScreenshotData | null\n    actual: ScreenshotData | null\n    diff: ScreenshotData | null\n    message: string\n  }\n  | {\n    pass: true\n  }\n>\n"
  },
  {
    "path": "packages/browser/src/types.ts",
    "content": "import type { MockedModuleSerialized, ServerIdResolution, ServerMockResolution } from '@vitest/mocker'\nimport type { TaskEventPack, TaskResultPack, TestArtifact } from '@vitest/runner'\nimport type { BirpcReturn } from 'birpc'\nimport type {\n  AfterSuiteRunMeta,\n  BrowserTesterOptions,\n  CancelReason,\n  RunnerTestFile,\n  SerializedTestSpecification,\n  SnapshotResult,\n  TestExecutionMethod,\n  UserConsoleLog,\n} from 'vitest'\n\nexport interface WebSocketBrowserHandlers {\n  resolveSnapshotPath: (testPath: string) => string\n  resolveSnapshotRawPath: (testPath: string, rawPath: string) => string\n  onUnhandledError: (error: unknown, type: string) => Promise<void>\n  onQueued: (method: TestExecutionMethod, file: RunnerTestFile) => void\n  onCollected: (method: TestExecutionMethod, files: RunnerTestFile[]) => Promise<void>\n  onTaskArtifactRecord: <Artifact extends TestArtifact>(testId: string, artifact: Artifact) => Promise<Artifact>\n  onTaskUpdate: (method: TestExecutionMethod, packs: TaskResultPack[], events: TaskEventPack[]) => void\n  onAfterSuiteRun: (meta: AfterSuiteRunMeta) => void\n  cancelCurrentRun: (reason: CancelReason) => void\n  getCountOfFailedTests: () => number\n  readSnapshotFile: (id: string) => Promise<string | null>\n  saveSnapshotFile: (id: string, content: string) => Promise<void>\n  removeSnapshotFile: (id: string) => Promise<void>\n  sendLog: (method: TestExecutionMethod, log: UserConsoleLog) => void\n  snapshotSaved: (snapshot: SnapshotResult) => void\n  debug: (...args: string[]) => void\n  resolveId: (\n    id: string,\n    importer?: string,\n  ) => Promise<ServerIdResolution | null>\n  triggerCommand: <T>(\n    sessionId: string,\n    command: string,\n    testPath: string | undefined,\n    payload: unknown[],\n  ) => Promise<T>\n  resolveMock: (\n    id: string,\n    importer: string,\n    options: { mock: 'spy' | 'factory' | 'auto' },\n  ) => Promise<ServerMockResolution>\n  invalidate: (ids: string[]) => void\n  getBrowserFileSourceMap: (\n    id: string,\n  ) => SourceMap | null | { mappings: '' } | undefined\n  wdioSwitchContext: (direction: 'iframe' | 'parent') => void\n\n  registerMock: (sessionId: string, mock: MockedModuleSerialized) => void\n  unregisterMock: (sessionId: string, id: string) => void\n  clearMocks: (sessionId: string) => void\n\n  // cdp\n  sendCdpEvent: (sessionId: string, event: string, payload?: Record<string, unknown>) => unknown\n  trackCdpEvent: (sessionId: string, type: 'on' | 'once' | 'off', event: string, listenerId: string) => void\n}\n\nexport type Awaitable<T> = T | PromiseLike<T>\n\nexport interface WebSocketEvents {\n  onCollected?: (files: RunnerTestFile[]) => Awaitable<void>\n  onTaskUpdate?: (packs: TaskResultPack[]) => Awaitable<void>\n  onUserConsoleLog?: (log: UserConsoleLog) => Awaitable<void>\n  onPathsCollected?: (paths?: string[]) => Awaitable<void>\n  onSpecsCollected?: (specs?: SerializedTestSpecification[]) => Awaitable<void>\n  onFinishedReportCoverage: () => void\n}\n\nexport interface WebSocketBrowserEvents {\n  onCancel: (reason: CancelReason) => void\n  createTesters: (options: BrowserTesterOptions) => Promise<void>\n  cleanupTesters: () => Promise<void>\n  cdpEvent: (event: string, payload: unknown) => void\n  resolveManualMock: (url: string) => Promise<{\n    url: string\n    keys: string[]\n    responseId: string\n  }>\n}\n\nexport type WebSocketBrowserRPC = BirpcReturn<\n  WebSocketBrowserEvents,\n  WebSocketBrowserHandlers\n>\n\ninterface SourceMap {\n  file: string\n  mappings: string\n  names: string[]\n  sources: string[]\n  sourcesContent?: string[]\n  version: number\n  toString: () => string\n  toUrl: () => string\n}\n"
  },
  {
    "path": "packages/browser/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"types\": [\"node\", \"vite/client\"],\n    \"isolatedDeclarations\": true\n  },\n  \"exclude\": [\n    \"dist\",\n    \"node_modules\",\n    \"**/vite.config.ts\",\n    \"src/client/**/*.ts\"\n  ]\n}\n"
  },
  {
    "path": "packages/browser/utils.d.ts",
    "content": "import { LocatorSelectors, Locator } from './context'\nimport { StringifyOptions } from 'vitest/internal/browser'\n\nexport type PrettyDOMOptions = Omit<StringifyOptions, 'maxLength'>\n\n/** @deprecated use `import('vitest/browser').utils.getElementLocatorSelectors` instead */\nexport declare function getElementLocatorSelectors(element: Element): LocatorSelectors\n/** @deprecated use `import('vitest/browser').utils.debug` instead */\nexport declare function debug(\n  el?: Element | Locator | null | (Element | Locator)[],\n  maxLength?: number,\n  options?: PrettyDOMOptions,\n): void\n/** @deprecated use `import('vitest/browser').utils.prettyDOM` instead */\nexport declare function prettyDOM(\n  dom?: Element | Locator | undefined | null,\n  maxLength?: number,\n  prettyFormatOptions?: PrettyDOMOptions,\n): string\n/** @deprecated use `import('vitest/browser').utils.getElementError` instead */\nexport declare function getElementError(selector: string, container?: Element): Error\n"
  },
  {
    "path": "packages/browser-playwright/README.md",
    "content": "# @vitest/browser-playwright\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/browser-playwright?color=a1b858&label=)](https://npmx.dev/package/@vitest/browser-playwright)\n\nRun your Vitest [browser tests](https://vitest.dev/guide/browser/) using [playwright](https://playwright.dev/docs/api/class-playwright) API. Note that Vitest does not use playwright as a test runner, but only as a browser provider.\n\nWe recommend using this package if you are already using playwright in your project or if you do not have any E2E tests yet.\n\n## Installation\n\nInstall the package with your favorite package manager:\n\n```sh\nnpm install -D @vitest/browser-playwright\n# or\nyarn add -D @vitest/browser-playwright\n# or\npnpm add -D @vitest/browser-playwright\n```\n\nThen specify it in the `browser.provider` field of your Vitest configuration:\n\n```ts\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config'\nimport { playwright } from '@vitest/browser-playwright'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright({\n        // ...custom playwright options\n      }),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  },\n})\n```\n\nThen run Vitest in the browser mode:\n\n```sh\nnpx vitest --browser\n```\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/browser-playwright) | [Documentation](https://vitest.dev/config/browser/playwright)\n"
  },
  {
    "path": "packages/browser-playwright/context.d.ts",
    "content": "export * from '@vitest/browser/context'\n"
  },
  {
    "path": "packages/browser-playwright/package.json",
    "content": "{\n  \"name\": \"@vitest/browser-playwright\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Browser running for Vitest using playwright\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/config/browser/playwright\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/browser-playwright\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"browser\",\n    \"playwright\",\n    \"component\",\n    \"mocks\",\n    \"test\",\n    \"testing\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./context\": {\n      \"types\": \"./context.d.ts\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"context.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && pnpm rollup -c\",\n    \"dev\": \"rollup -c --watch --watch.include 'src/**'\"\n  },\n  \"peerDependencies\": {\n    \"playwright\": \"*\",\n    \"vitest\": \"workspace:*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"playwright\": {\n      \"optional\": false\n    }\n  },\n  \"dependencies\": {\n    \"@vitest/browser\": \"workspace:*\",\n    \"@vitest/mocker\": \"workspace:*\",\n    \"tinyrainbow\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"playwright\": \"^1.58.2\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/browser-playwright/rollup.config.js",
    "content": "import { createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst external = [\n  ...Object.keys(pkg.dependencies),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^@?vitest(\\/|$)/,\n  'vite',\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  resolve({\n    preferBuiltins: true,\n  }),\n  json(),\n  commonjs(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nexport default () =>\n  defineConfig([\n    {\n      input: {\n        index: './src/index.ts',\n        locators: './src/locators.ts',\n      },\n      output: {\n        dir: 'dist',\n        format: 'esm',\n      },\n      external,\n      context: 'null',\n      plugins: [\n        ...dtsUtils.isolatedDecl(),\n        ...plugins,\n      ],\n    },\n    {\n      input: dtsUtils.dtsInput('src/index.ts'),\n      output: {\n        dir: 'dist',\n        entryFileNames: '[name].d.ts',\n        format: 'esm',\n      },\n      watch: false,\n      external,\n      plugins: dtsUtils.dts(),\n    },\n  ])\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/clear.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { getDescribedLocator } from './utils'\n\nexport const clear: UserEventCommand<UserEvent['clear']> = async (\n  context,\n  selector,\n) => {\n  const element = getDescribedLocator(context, selector)\n  await element.clear()\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/click.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { getDescribedLocator } from './utils'\n\nexport const click: UserEventCommand<UserEvent['click']> = async (\n  context,\n  selector,\n  options = {},\n) => {\n  await getDescribedLocator(context, selector).click(options)\n}\n\nexport const dblClick: UserEventCommand<UserEvent['dblClick']> = async (\n  context,\n  selector,\n  options = {},\n) => {\n  await getDescribedLocator(context, selector).dblclick(options)\n}\n\nexport const tripleClick: UserEventCommand<UserEvent['tripleClick']> = async (\n  context,\n  selector,\n  options = {},\n) => {\n  await getDescribedLocator(context, selector).click({\n    ...options,\n    clickCount: 3,\n  })\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/dragAndDrop.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\n\nexport const dragAndDrop: UserEventCommand<UserEvent['dragAndDrop']> = async (\n  context,\n  source,\n  target,\n  options_,\n) => {\n  const frame = await context.frame()\n  await frame.dragAndDrop(\n    source,\n    target,\n    options_,\n  )\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/fill.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { getDescribedLocator } from './utils'\n\nexport const fill: UserEventCommand<UserEvent['fill']> = async (\n  context,\n  selector,\n  text,\n  options = {},\n) => {\n  const element = getDescribedLocator(context, selector)\n  await element.fill(text, options)\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/hover.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { getDescribedLocator } from './utils'\n\nexport const hover: UserEventCommand<UserEvent['hover']> = async (\n  context,\n  selector,\n  options = {},\n) => {\n  await getDescribedLocator(context, selector).hover(options)\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/index.ts",
    "content": "import { clear } from './clear'\nimport { click, dblClick, tripleClick } from './click'\nimport { dragAndDrop } from './dragAndDrop'\nimport { fill } from './fill'\nimport { hover } from './hover'\nimport { keyboard, keyboardCleanup } from './keyboard'\nimport { takeScreenshot } from './screenshot'\nimport { selectOptions } from './select'\nimport { tab } from './tab'\nimport {\n  annotateTraces,\n  deleteTracing,\n  groupTraceEnd,\n  groupTraceStart,\n  markTrace,\n  startChunkTrace,\n  startTracing,\n  stopChunkTrace,\n} from './trace'\nimport { type } from './type'\nimport { upload } from './upload'\nimport { wheel } from './wheel'\n\nexport default {\n  __vitest_upload: upload as typeof upload,\n  __vitest_click: click as typeof click,\n  __vitest_dblClick: dblClick as typeof dblClick,\n  __vitest_tripleClick: tripleClick as typeof tripleClick,\n  __vitest_wheel: wheel as typeof wheel,\n  __vitest_takeScreenshot: takeScreenshot as typeof takeScreenshot,\n  __vitest_type: type as typeof type,\n  __vitest_clear: clear as typeof clear,\n  __vitest_fill: fill as typeof fill,\n  __vitest_tab: tab as typeof tab,\n  __vitest_keyboard: keyboard as typeof keyboard,\n  __vitest_selectOptions: selectOptions as typeof selectOptions,\n  __vitest_dragAndDrop: dragAndDrop as typeof dragAndDrop,\n  __vitest_hover: hover as typeof hover,\n  __vitest_cleanup: keyboardCleanup as typeof keyboardCleanup,\n  __vitest_deleteTracing: deleteTracing as typeof deleteTracing,\n  __vitest_startChunkTrace: startChunkTrace as typeof startChunkTrace,\n  __vitest_startTracing: startTracing as typeof startTracing,\n  __vitest_stopChunkTrace: stopChunkTrace as typeof stopChunkTrace,\n  __vitest_annotateTraces: annotateTraces as typeof annotateTraces,\n  __vitest_markTrace: markTrace as typeof markTrace,\n  __vitest_groupTraceStart: groupTraceStart as typeof groupTraceStart,\n  __vitest_groupTraceEnd: groupTraceEnd as typeof groupTraceEnd,\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/keyboard.ts",
    "content": "import type { BrowserProvider } from 'vitest/node'\nimport type { PlaywrightBrowserProvider } from '../playwright'\nimport type { UserEventCommand } from './utils'\nimport { parseKeyDef } from '@vitest/browser'\n\nexport interface KeyboardState {\n  unreleased: string[]\n}\n\nexport const keyboard: UserEventCommand<(text: string, state: KeyboardState) => Promise<{ unreleased: string[] }>> = async (\n  context,\n  text,\n  state,\n) => {\n  const frame = await context.frame()\n  await frame.evaluate(focusIframe)\n\n  const pressed = new Set<string>(state.unreleased)\n\n  await keyboardImplementation(\n    pressed,\n    context.provider,\n    context.sessionId,\n    text,\n    async () => {\n      const frame = await context.frame()\n      await frame.evaluate(selectAll)\n    },\n    true,\n  )\n\n  return {\n    unreleased: Array.from(pressed),\n  }\n}\n\nexport const keyboardCleanup: UserEventCommand<(state: KeyboardState) => Promise<void>> = async (\n  context,\n  state,\n) => {\n  const { provider, sessionId } = context\n  if (!state.unreleased) {\n    return\n  }\n  const page = (provider as PlaywrightBrowserProvider).getPage(sessionId)\n  for (const key of state.unreleased) {\n    await page.keyboard.up(key)\n  }\n}\n\n// fallback to insertText for non US key\n// https://github.com/microsoft/playwright/blob/50775698ae13642742f2a1e8983d1d686d7f192d/packages/playwright-core/src/server/input.ts#L95\nconst VALID_KEYS = new Set(['Escape', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'Backquote', '`', '~', 'Digit1', '1', '!', 'Digit2', '2', '@', 'Digit3', '3', '#', 'Digit4', '4', '$', 'Digit5', '5', '%', 'Digit6', '6', '^', 'Digit7', '7', '&', 'Digit8', '8', '*', 'Digit9', '9', '(', 'Digit0', '0', ')', 'Minus', '-', '_', 'Equal', '=', '+', 'Backslash', '\\\\', '|', 'Backspace', 'Tab', 'KeyQ', 'q', 'Q', 'KeyW', 'w', 'W', 'KeyE', 'e', 'E', 'KeyR', 'r', 'R', 'KeyT', 't', 'T', 'KeyY', 'y', 'Y', 'KeyU', 'u', 'U', 'KeyI', 'i', 'I', 'KeyO', 'o', 'O', 'KeyP', 'p', 'P', 'BracketLeft', '[', '{', 'BracketRight', ']', '}', 'CapsLock', 'KeyA', 'a', 'A', 'KeyS', 's', 'S', 'KeyD', 'd', 'D', 'KeyF', 'f', 'F', 'KeyG', 'g', 'G', 'KeyH', 'h', 'H', 'KeyJ', 'j', 'J', 'KeyK', 'k', 'K', 'KeyL', 'l', 'L', 'Semicolon', ';', ':', 'Quote', '\\'', '\"', 'Enter', '\\n', '\\r', 'ShiftLeft', 'Shift', 'KeyZ', 'z', 'Z', 'KeyX', 'x', 'X', 'KeyC', 'c', 'C', 'KeyV', 'v', 'V', 'KeyB', 'b', 'B', 'KeyN', 'n', 'N', 'KeyM', 'm', 'M', 'Comma', ',', '<', 'Period', '.', '>', 'Slash', '/', '?', 'ShiftRight', 'ControlLeft', 'Control', 'MetaLeft', 'Meta', 'AltLeft', 'Alt', 'Space', ' ', 'AltRight', 'AltGraph', 'MetaRight', 'ContextMenu', 'ControlRight', 'PrintScreen', 'ScrollLock', 'Pause', 'PageUp', 'PageDown', 'Insert', 'Delete', 'Home', 'End', 'ArrowLeft', 'ArrowUp', 'ArrowRight', 'ArrowDown', 'NumLock', 'NumpadDivide', 'NumpadMultiply', 'NumpadSubtract', 'Numpad7', 'Numpad8', 'Numpad9', 'Numpad4', 'Numpad5', 'Numpad6', 'NumpadAdd', 'Numpad1', 'Numpad2', 'Numpad3', 'Numpad0', 'NumpadDecimal', 'NumpadEnter', 'ControlOrMeta'])\n\nexport async function keyboardImplementation(\n  pressed: Set<string>,\n  provider: BrowserProvider,\n  sessionId: string,\n  text: string,\n  selectAll: () => Promise<void>,\n  skipRelease: boolean,\n): Promise<{ pressed: Set<string> }> {\n  const page = (provider as PlaywrightBrowserProvider).getPage(sessionId)\n  const actions = parseKeyDef(text)\n\n  for (const { releasePrevious, releaseSelf, repeat, keyDef } of actions) {\n    const key = keyDef.key!\n\n    // TODO: instead of calling down/up for each key, join non special\n    // together, and call `type` once for all non special keys,\n    // and then `press` for special keys\n    if (pressed.has(key)) {\n      if (VALID_KEYS.has(key)) {\n        await page.keyboard.up(key)\n      }\n      pressed.delete(key)\n    }\n\n    if (!releasePrevious) {\n      if (key === 'selectall') {\n        await selectAll()\n        continue\n      }\n\n      for (let i = 1; i <= repeat; i++) {\n        if (VALID_KEYS.has(key)) {\n          await page.keyboard.down(key)\n        }\n        else {\n          await page.keyboard.insertText(key)\n        }\n      }\n\n      if (releaseSelf) {\n        if (VALID_KEYS.has(key)) {\n          await page.keyboard.up(key)\n        }\n      }\n      else {\n        pressed.add(key)\n      }\n    }\n  }\n\n  if (!skipRelease && pressed.size) {\n    for (const key of pressed) {\n      if (VALID_KEYS.has(key)) {\n        await page.keyboard.up(key)\n      }\n    }\n  }\n\n  return {\n    pressed,\n  }\n}\n\nfunction focusIframe() {\n  if (\n    !document.activeElement\n    || document.activeElement.ownerDocument !== document\n    || document.activeElement === document.body\n  ) {\n    window.focus()\n  }\n}\n\nfunction selectAll() {\n  const element = document.activeElement as HTMLInputElement\n  if (element && typeof element.select === 'function') {\n    element.select()\n  }\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/screenshot.ts",
    "content": "import type { ScreenshotOptions } from 'vitest/browser'\nimport type { BrowserCommandContext } from 'vitest/node'\nimport { mkdir } from 'node:fs/promises'\nimport { resolveScreenshotPath } from '@vitest/browser'\nimport { dirname, normalize } from 'pathe'\nimport { getDescribedLocator } from './utils'\n\ninterface ScreenshotCommandOptions extends Omit<ScreenshotOptions, 'element' | 'mask'> {\n  element?: string\n  mask?: readonly string[]\n}\n/**\n * Takes a screenshot using the provided browser context and returns a buffer and the expected screenshot path.\n *\n * **Note**: the returned `path` indicates where the screenshot *might* be found.\n * It is not guaranteed to exist, especially if `options.save` is `false`.\n *\n * @throws {Error} If the function is not called within a test or if the browser provider does not support screenshots.\n */\nexport async function takeScreenshot(\n  context: BrowserCommandContext,\n  name: string,\n  options: Omit<ScreenshotCommandOptions, 'base64'>,\n): Promise<{ buffer: Buffer<ArrayBufferLike>; path: string }> {\n  if (!context.testPath) {\n    throw new Error(`Cannot take a screenshot without a test path`)\n  }\n\n  const path = resolveScreenshotPath(\n    context.testPath,\n    name,\n    context.project.config,\n    options.path,\n  )\n\n  // playwright does not need a screenshot path if we don't intend to save it\n  let savePath: string | undefined\n\n  if (options.save) {\n    savePath = normalize(path)\n\n    await mkdir(dirname(savePath), { recursive: true })\n  }\n\n  const mask = options.mask?.map(selector => getDescribedLocator(context, selector))\n\n  if (options.element) {\n    const { element: selector, ...config } = options\n    const element = getDescribedLocator(context, selector)\n    const buffer = await element.screenshot({\n      ...config,\n      mask,\n      path: savePath,\n    })\n    return { buffer, path }\n  }\n\n  const buffer = await getDescribedLocator(context, 'body').screenshot({\n    ...options,\n    mask,\n    path: savePath,\n  })\n  return { buffer, path }\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/select.ts",
    "content": "import type { ElementHandle } from 'playwright'\nimport type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { getDescribedLocator } from './utils'\n\nexport const selectOptions: UserEventCommand<UserEvent['selectOptions']> = async (\n  context,\n  selector,\n  userValues,\n  options = {},\n) => {\n  const value = userValues as any as (string | { element: string })[]\n  const selectElement = getDescribedLocator(context, selector)\n\n  const values = await Promise.all(value.map(async (v) => {\n    if (typeof v === 'string') {\n      return v\n    }\n    const elementHandler = await getDescribedLocator(context, v.element).elementHandle()\n    if (!elementHandler) {\n      throw new Error(`Element not found: ${v.element}`)\n    }\n    return elementHandler\n  })) as (readonly string[]) | (readonly ElementHandle[])\n\n  await selectElement.selectOption(values, options)\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/tab.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\n\nexport const tab: UserEventCommand<UserEvent['tab']> = async (\n  context,\n  options = {},\n) => {\n  const page = context.page\n  await page.keyboard.press(options.shift === true ? 'Shift+Tab' : 'Tab')\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/trace.ts",
    "content": "import type { ParsedStack } from 'vitest'\nimport type { BrowserCommand, BrowserCommandContext, BrowserProvider } from 'vitest/node'\nimport type { PlaywrightBrowserProvider } from '../playwright'\nimport { unlink } from 'node:fs/promises'\nimport { basename, dirname, relative, resolve } from 'pathe'\nimport { getDescribedLocator } from './utils'\n\nexport const startTracing: BrowserCommand<[]> = async ({ context, project, provider, sessionId }) => {\n  if (isPlaywrightProvider(provider)) {\n    if (provider.tracingContexts.has(sessionId)) {\n      return\n    }\n\n    provider.tracingContexts.add(sessionId)\n    const options = project.config.browser!.trace\n    await context.tracing.start({\n      screenshots: options.screenshots ?? true,\n      snapshots: options.snapshots ?? true,\n      sources: options.sources ?? true,\n    }).catch(() => {\n      provider.tracingContexts.delete(sessionId)\n    })\n    return\n  }\n  throw new TypeError(`The ${provider.name} provider does not support tracing.`)\n}\n\nexport const startChunkTrace: BrowserCommand<[{ name: string; title: string }]> = async (\n  command,\n  { name, title },\n) => {\n  const { provider, sessionId, testPath, context } = command\n  if (!testPath) {\n    throw new Error(`stopChunkTrace cannot be called outside of the test file.`)\n  }\n  if (isPlaywrightProvider(provider)) {\n    if (!provider.tracingContexts.has(sessionId)) {\n      await startTracing(command)\n    }\n    const path = resolveTracesPath(command, name)\n    provider.pendingTraces.set(path, sessionId)\n    await context.tracing.startChunk({ name, title })\n    return\n  }\n  throw new TypeError(`The ${provider.name} provider does not support tracing.`)\n}\n\nexport const stopChunkTrace: BrowserCommand<[{ name: string }]> = async (\n  context,\n  { name },\n) => {\n  if (isPlaywrightProvider(context.provider)) {\n    const path = resolveTracesPath(context, name)\n    context.provider.pendingTraces.delete(path)\n    await context.context.tracing.stopChunk({ path })\n    return { tracePath: path }\n  }\n  throw new TypeError(`The ${context.provider.name} provider does not support tracing.`)\n}\n\nexport const markTrace: BrowserCommand<[payload: { name: string; selector?: string; stack?: string }]> = async (\n  context,\n  payload,\n) => {\n  if (isPlaywrightProvider(context.provider)) {\n    // skip if tracing is not active\n    // this is only safe guard and this isn't expected to happen since\n    // runner already checks if tracing is active before sending this command\n    if (!context.provider.tracingContexts.has(context.sessionId)) {\n      return\n    }\n    const { name, selector, stack } = payload\n    const location = parseLocation(context, stack)\n    // mark trace via group/groupEnd with dummy calls to force snapshot.\n    // https://github.com/microsoft/playwright/issues/39308\n    await context.context.tracing.group(name, { location })\n    try {\n      if (selector) {\n        const locator = getDescribedLocator(context, selector) as any\n        if (typeof locator._expect === 'function') {\n          await locator._expect('to.be.attached', {\n            isNot: false,\n            timeout: 1, // don't wait when element doesn't exist\n          })\n        }\n        else {\n          await context.page.evaluate(() => 0)\n        }\n      }\n      else {\n        await context.page.evaluate(() => 0)\n      }\n    }\n    catch {}\n    await context.context.tracing.groupEnd()\n    return\n  }\n  throw new TypeError(`The ${context.provider.name} provider does not support tracing.`)\n}\n\nexport const groupTraceStart: BrowserCommand<[payload: { name: string; stack?: string }]> = async (\n  context,\n  payload,\n) => {\n  if (isPlaywrightProvider(context.provider)) {\n    if (!context.provider.tracingContexts.has(context.sessionId)) {\n      return\n    }\n    const { name, stack } = payload\n    const location = parseLocation(context, stack)\n    await context.context.tracing.group(name, { location })\n    return\n  }\n  throw new TypeError(`The ${context.provider.name} provider does not support tracing.`)\n}\n\nexport const groupTraceEnd: BrowserCommand<[]> = async (\n  context,\n) => {\n  if (isPlaywrightProvider(context.provider)) {\n    if (!context.provider.tracingContexts.has(context.sessionId)) {\n      return\n    }\n    await context.context.tracing.groupEnd()\n    return\n  }\n  throw new TypeError(`The ${context.provider.name} provider does not support tracing.`)\n}\n\nfunction parseLocation(context: BrowserCommandContext, stack?: string): ParsedStack | undefined {\n  if (!stack) {\n    return\n  }\n  const parsedStacks = context.project.browser!.parseStacktrace(stack)\n  return parsedStacks[0]\n}\n\nfunction resolveTracesPath({ testPath, project }: BrowserCommandContext, name: string) {\n  if (!testPath) {\n    throw new Error(`This command can only be called inside a test file.`)\n  }\n  const options = project.config.browser!.trace\n  const sanitizedName = `${project.name.replace(/[^a-z0-9]/gi, '-')}-${name}.trace.zip`\n  if (options.tracesDir) {\n    return resolve(options.tracesDir, sanitizedName)\n  }\n  const dir = dirname(testPath)\n  const base = basename(testPath)\n  return resolve(\n    dir,\n    '__traces__',\n    base,\n    `${project.name.replace(/[^a-z0-9]/gi, '-')}-${name}.trace.zip`,\n  )\n}\n\nexport const deleteTracing: BrowserCommand<[{ traces: string[] }]> = async (\n  context,\n  { traces },\n) => {\n  if (!context.testPath) {\n    throw new Error(`stopChunkTrace cannot be called outside of the test file.`)\n  }\n  if (isPlaywrightProvider(context.provider)) {\n    return Promise.all(\n      traces.map(trace => unlink(trace).catch((err) => {\n        if (err.code === 'ENOENT') {\n        // Ignore the error if the file doesn't exist\n          return\n        }\n        // Re-throw other errors\n        throw err\n      })),\n    )\n  }\n\n  throw new Error(`provider ${context.provider.name} is not supported`)\n}\n\nexport const annotateTraces: BrowserCommand<[{ traces: string[]; testId: string }]> = async (\n  { project },\n  { testId, traces },\n) => {\n  const vitest = project.vitest\n  await Promise.all(traces.map((trace) => {\n    const entity = vitest.state.getReportedEntityById(testId)\n    const location = entity?.location\n      ? {\n          file: entity.module.moduleId,\n          line: entity.location.line,\n          column: entity.location.column,\n        }\n      : undefined\n    return vitest._testRun.recordArtifact(testId, {\n      type: 'internal:annotation',\n      annotation: {\n        message: relative(project.config.root, trace),\n        type: 'traces',\n        attachment: {\n          path: trace,\n          contentType: 'application/octet-stream',\n        },\n        location,\n      },\n      location,\n    })\n  }))\n}\n\nfunction isPlaywrightProvider(provider: BrowserProvider): provider is PlaywrightBrowserProvider {\n  return provider.name === 'playwright'\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/type.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { keyboardImplementation } from './keyboard'\nimport { getDescribedLocator } from './utils'\n\nexport const type: UserEventCommand<UserEvent['type']> = async (\n  context,\n  selector,\n  text,\n  options = {},\n) => {\n  const { skipClick = false, skipAutoClose = false } = options\n  const unreleased = new Set(Reflect.get(options, 'unreleased') as string[] ?? [])\n\n  const element = getDescribedLocator(context, selector)\n\n  if (!skipClick) {\n    await element.focus()\n  }\n\n  await keyboardImplementation(\n    unreleased,\n    context.provider,\n    context.sessionId,\n    text,\n    () => element.selectText(),\n    skipAutoClose,\n  )\n\n  return {\n    unreleased: Array.from(unreleased),\n  }\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/upload.ts",
    "content": "import type { UserEventUploadOptions } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { resolve } from 'pathe'\nimport { getDescribedLocator } from './utils'\n\nexport const upload: UserEventCommand<(element: string, files: Array<string | {\n  name: string\n  mimeType: string\n  base64: string\n}>, options: UserEventUploadOptions) => void> = async (\n  context,\n  selector,\n  files,\n  options,\n) => {\n  const testPath = context.testPath\n  if (!testPath) {\n    throw new Error(`Cannot upload files outside of a test`)\n  }\n  const root = context.project.config.root\n\n  const playwrightFiles = files.map((file) => {\n    if (typeof file === 'string') {\n      return resolve(root, file)\n    }\n    return {\n      name: file.name,\n      mimeType: file.mimeType,\n      buffer: Buffer.from(file.base64, 'base64'),\n    }\n  })\n  await getDescribedLocator(context, selector).setInputFiles(playwrightFiles as string[], options)\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/utils.ts",
    "content": "import type { Locator } from 'vitest/browser'\nimport type { BrowserCommand, BrowserCommandContext } from 'vitest/node'\nimport { asLocator } from '@vitest/browser'\n\nexport type UserEventCommand<T extends (...args: any) => any> = BrowserCommand<\n  ConvertUserEventParameters<Parameters<T>>\n>\n\ntype ConvertElementToLocator<T> = T extends Element | Locator ? string : T\ntype ConvertUserEventParameters<T extends unknown[]> = {\n  [K in keyof T]: ConvertElementToLocator<T[K]>;\n}\n\nexport function defineBrowserCommand<T extends unknown[]>(\n  fn: BrowserCommand<T>,\n): BrowserCommand<T> {\n  return fn\n}\n\n// strip iframe locator part from the trace description e.g.\n// - locator('[data-vitest=\"true\"]').contentFrame().getByRole('button')\n//     ⇓\n// - getByRole('button')\nexport function getDescribedLocator(\n  context: BrowserCommandContext,\n  selector: string,\n): ReturnType<BrowserCommandContext['iframe']['locator']> {\n  const locator = context.iframe.locator(selector)\n  return typeof locator.describe === 'function'\n    ? locator.describe(asLocator('javascript', selector))\n    : locator\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/commands/wheel.ts",
    "content": "import type { Locator, UserEventWheelDeltaOptions } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { hover } from './hover'\n\ntype WheelCommand = (element: Locator | Element, options: UserEventWheelDeltaOptions) => Promise<void>\n\nexport const wheel: UserEventCommand<WheelCommand> = async (\n  context,\n  selector,\n  options,\n) => {\n  await hover(context, selector)\n\n  const times = options.times ?? 1\n  const deltaX = options.delta.x ?? 0\n  const deltaY = options.delta.y ?? 0\n\n  for (let count = 0; count < times; count += 1) {\n    await context.page.mouse.wheel(deltaX, deltaY)\n  }\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/constants.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { resolve } from 'pathe'\n\nconst pkgRoot = resolve(fileURLToPath(import.meta.url), '../..')\nexport const distRoot: string = resolve(pkgRoot, 'dist')\n"
  },
  {
    "path": "packages/browser-playwright/src/index.ts",
    "content": "export {\n  type CDPSession,\n  playwright,\n  PlaywrightBrowserProvider,\n  type PlaywrightProviderOptions,\n} from './playwright'\nexport { defineBrowserCommand } from '@vitest/browser'\n"
  },
  {
    "path": "packages/browser-playwright/src/locators.ts",
    "content": "import type {\n  UserEventClearOptions,\n  UserEventClickOptions,\n  UserEventDragAndDropOptions,\n  UserEventFillOptions,\n  UserEventHoverOptions,\n  UserEventSelectOptions,\n  UserEventUploadOptions,\n} from 'vitest/browser'\nimport {\n  getByAltTextSelector,\n  getByLabelSelector,\n  getByPlaceholderSelector,\n  getByRoleSelector,\n  getByTestIdSelector,\n  getByTextSelector,\n  getByTitleSelector,\n  getIframeScale,\n  Locator,\n  processTimeoutOptions,\n  selectorEngine,\n} from '@vitest/browser/locators'\nimport { page, server } from 'vitest/browser'\nimport { __INTERNAL } from 'vitest/internal/browser'\n\nclass PlaywrightLocator extends Locator {\n  constructor(public selector: string, protected _container?: Element) {\n    super()\n  }\n\n  public override click(options?: UserEventClickOptions) {\n    return super.click(processTimeoutOptions(processClickOptions(options)))\n  }\n\n  public override dblClick(options?: UserEventClickOptions): Promise<void> {\n    return super.dblClick(processTimeoutOptions(processClickOptions(options)))\n  }\n\n  public override tripleClick(options?: UserEventClickOptions): Promise<void> {\n    return super.tripleClick(processTimeoutOptions(processClickOptions(options)))\n  }\n\n  public override selectOptions(\n    value: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],\n    options?: UserEventSelectOptions,\n  ): Promise<void> {\n    return super.selectOptions(value, processTimeoutOptions(options))\n  }\n\n  public override clear(options?: UserEventClearOptions): Promise<void> {\n    return super.clear(processTimeoutOptions(options))\n  }\n\n  public override hover(options?: UserEventHoverOptions): Promise<void> {\n    return super.hover(processTimeoutOptions(processHoverOptions(options)))\n  }\n\n  public override upload(\n    files: string | string[] | File | File[],\n    options?: UserEventUploadOptions,\n  ): Promise<void> {\n    return super.upload(files, processTimeoutOptions(options))\n  }\n\n  public override fill(text: string, options?: UserEventFillOptions): Promise<void> {\n    return super.fill(text, processTimeoutOptions(options))\n  }\n\n  public override dropTo(target: Locator, options?: UserEventDragAndDropOptions): Promise<void> {\n    return super.dropTo(target, processTimeoutOptions(\n      processDragAndDropOptions(options),\n    ))\n  }\n\n  protected locator(selector: string) {\n    return new PlaywrightLocator(`${this.selector} >> ${selector}`, this._container)\n  }\n\n  protected elementLocator(element: Element) {\n    return new PlaywrightLocator(\n      selectorEngine.generateSelectorSimple(element),\n      element,\n    )\n  }\n}\n\npage.extend({\n  getByLabelText(text, options) {\n    return new PlaywrightLocator(getByLabelSelector(text, options))\n  },\n  getByRole(role, options) {\n    return new PlaywrightLocator(getByRoleSelector(role, options))\n  },\n  getByTestId(testId) {\n    return new PlaywrightLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute, testId))\n  },\n  getByAltText(text, options) {\n    return new PlaywrightLocator(getByAltTextSelector(text, options))\n  },\n  getByPlaceholder(text, options) {\n    return new PlaywrightLocator(getByPlaceholderSelector(text, options))\n  },\n  getByText(text, options) {\n    return new PlaywrightLocator(getByTextSelector(text, options))\n  },\n  getByTitle(title, options) {\n    return new PlaywrightLocator(getByTitleSelector(title, options))\n  },\n\n  elementLocator(element: Element) {\n    return new PlaywrightLocator(\n      selectorEngine.generateSelectorSimple(element),\n      element,\n    )\n  },\n  frameLocator(locator: Locator) {\n    return new PlaywrightLocator(\n      `${locator.selector} >> internal:control=enter-frame`,\n    )\n  },\n})\n\n__INTERNAL._createLocator = selector => new PlaywrightLocator(selector)\n\nfunction processDragAndDropOptions(options?: UserEventDragAndDropOptions) {\n  if (!options) {\n    return options\n  }\n  if (options.sourcePosition) {\n    options.sourcePosition = processPlaywrightPosition(options.sourcePosition)\n  }\n  if (options.targetPosition) {\n    options.targetPosition = processPlaywrightPosition(options.targetPosition)\n  }\n  return options\n}\n\nfunction processHoverOptions(options?: UserEventHoverOptions) {\n  if (!options) {\n    return options\n  }\n  if (options.position) {\n    options.position = processPlaywrightPosition(options.position)\n  }\n  return options\n}\n\nfunction processClickOptions(options?: UserEventClickOptions) {\n  if (!options) {\n    return options\n  }\n  if (options.position) {\n    options.position = processPlaywrightPosition(options.position)\n  }\n  return options\n}\n\nfunction processPlaywrightPosition(position: { x: number; y: number }) {\n  const scale = getIframeScale()\n  if (position.x != null) {\n    position.x *= scale\n  }\n  if (position.y != null) {\n    position.y *= scale\n  }\n  return position\n}\n"
  },
  {
    "path": "packages/browser-playwright/src/playwright.ts",
    "content": "/* eslint-disable ts/method-signature-style */\n\nimport type { CustomComparatorsRegistry } from '@vitest/browser'\nimport type { MockedModule } from '@vitest/mocker'\nimport type {\n  Browser,\n  BrowserContext,\n  BrowserContextOptions,\n  ConnectOptions,\n  Frame,\n  FrameLocator,\n  LaunchOptions,\n  Page,\n  CDPSession as PlaywrightCDPSession,\n} from 'playwright'\nimport type { SourceMap } from 'rollup'\nimport type { ResolvedConfig } from 'vite'\nimport type {\n  Locator,\n  ScreenshotComparatorRegistry,\n  ScreenshotMatcherOptions,\n} from 'vitest/browser'\nimport type {\n  BrowserCommand,\n  BrowserModuleMocker,\n  BrowserProvider,\n  BrowserProviderOption,\n  CDPSession,\n  TestProject,\n} from 'vitest/node'\nimport { defineBrowserProvider } from '@vitest/browser'\nimport { createManualModuleSource } from '@vitest/mocker/node'\nimport { resolve } from 'pathe'\nimport c from 'tinyrainbow'\nimport { createDebugger, isCSSRequest } from 'vitest/node'\nimport commands from './commands'\nimport { distRoot } from './constants'\n\nconst debug = createDebugger('vitest:browser:playwright')\n\nconst playwrightBrowsers = ['firefox', 'webkit', 'chromium'] as const\ntype PlaywrightBrowser = (typeof playwrightBrowsers)[number]\n\n// Enable intercepting of requests made by service workers - experimental API is only available in Chromium based browsers\n// Requests from service workers are only available on context.route() https://playwright.dev/docs/service-workers-experimental\nprocess.env.PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS ??= '1'\n\nexport interface PlaywrightProviderOptions {\n  /**\n   * The options passed down to [`playwright.connect`](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) method.\n   * @see {@link https://playwright.dev/docs/api/class-browsertype#browser-type-launch}\n   */\n  launchOptions?: Omit<\n    LaunchOptions,\n    'tracesDir'\n  >\n  /**\n   * The options passed down to [`playwright.connect`](https://playwright.dev/docs/api/class-browsertype#browser-type-connect) method.\n   *\n   * This is used only if you connect remotely to the playwright instance via a WebSocket connection.\n   * @see {@link https://playwright.dev/docs/api/class-browsertype#browser-type-connect}\n   */\n  connectOptions?: ConnectOptions & {\n    wsEndpoint: string\n  }\n  /**\n   * The options passed down to [`browser.newContext`](https://playwright.dev/docs/api/class-browser#browser-new-context) method.\n   * @see {@link https://playwright.dev/docs/api/class-browser#browser-new-context}\n   */\n  contextOptions?: Omit<\n    BrowserContextOptions,\n    'ignoreHTTPSErrors' | 'serviceWorkers'\n  >\n  /**\n   * The maximum time in milliseconds to wait for `userEvent` action to complete.\n   * @default 0 (no timeout)\n   */\n  actionTimeout?: number\n\n  /**\n   * Use a persistent context instead of a regular browser context.\n   * This allows browser state (cookies, localStorage, DevTools settings, etc.) to persist between test runs.\n   * When set to `true`, the user data is stored in `./node_modules/.cache/vitest-playwright-user-data`.\n   * When set to a string, the value is used as the path to the user data directory.\n   *\n   * Note: This option is ignored when running tests in parallel (e.g. headless with fileParallelism enabled)\n   * because persistent context cannot be shared across parallel sessions.\n   * @default false\n   * @see {@link https://playwright.dev/docs/api/class-browsertype#browser-type-launch-persistent-context}\n   */\n  persistentContext?: boolean | string\n}\n\nexport function playwright(options: PlaywrightProviderOptions = {}): BrowserProviderOption<PlaywrightProviderOptions> {\n  return defineBrowserProvider({\n    name: 'playwright',\n    supportedBrowser: playwrightBrowsers,\n    options,\n    providerFactory(project) {\n      return new PlaywrightBrowserProvider(project, options)\n    },\n  })\n}\n\nexport class PlaywrightBrowserProvider implements BrowserProvider {\n  public name = 'playwright' as const\n  public supportsParallelism = true\n\n  public browser: Browser | null = null\n  public persistentContext: BrowserContext | null = null\n\n  public contexts: Map<string, BrowserContext> = new Map()\n  public pages: Map<string, Page> = new Map()\n  public mocker: BrowserModuleMocker\n  public browserName: PlaywrightBrowser\n\n  private browserPromise: Promise<Browser> | null = null\n  private closing = false\n\n  public tracingContexts: Set<string> = new Set()\n  public pendingTraces: Map<string, string> = new Map()\n\n  public initScripts: string[] = [\n    resolve(distRoot, 'locators.js'),\n  ]\n\n  constructor(\n    private project: TestProject,\n    private options: PlaywrightProviderOptions,\n  ) {\n    this.browserName = project.config.browser.name as PlaywrightBrowser\n    this.mocker = this.createMocker()\n\n    for (const [name, command] of Object.entries(commands)) {\n      project.browser!.registerCommand(name as any, command as BrowserCommand)\n    }\n\n    // make sure the traces are finished if the test hangs\n    process.on('SIGTERM', this.onSIGTERM)\n  }\n\n  private onSIGTERM = () => {\n    if (!this.browser) {\n      return\n    }\n    const promises = []\n    for (const [trace, contextId] of this.pendingTraces.entries()) {\n      promises.push((() => {\n        const context = this.contexts.get(contextId)\n        return context?.tracing.stopChunk({ path: trace })\n      })())\n    }\n    return Promise.allSettled(promises)\n  }\n\n  private async openBrowser(openBrowserOptions: { parallel: boolean }) {\n    await this._throwIfClosing()\n\n    if (this.browserPromise) {\n      debug?.('[%s] the browser is resolving, reusing the promise', this.browserName)\n      return this.browserPromise\n    }\n\n    if (this.browser) {\n      debug?.('[%s] the browser is resolved, reusing it', this.browserName)\n      return this.browser\n    }\n\n    this.browserPromise = (async () => {\n      const options = this.project.config.browser\n\n      const playwright = await import('playwright')\n\n      const launchOptions: LaunchOptions = {\n        ...this.options.launchOptions,\n        headless: options.headless,\n      }\n\n      if (typeof options.trace === 'object' && options.trace.tracesDir) {\n        launchOptions.tracesDir = options.trace?.tracesDir\n      }\n\n      const inspector = this.project.vitest.config.inspector\n      if (inspector.enabled) {\n        // NodeJS equivalent defaults: https://nodejs.org/en/learn/getting-started/debugging#enable-inspector\n        const port = inspector.port || 9229\n        const host = inspector.host || '127.0.0.1'\n\n        launchOptions.args ||= []\n        launchOptions.args.push(`--remote-debugging-port=${port}`)\n\n        if (host !== 'localhost' && host !== '127.0.0.1' && host !== '::1') {\n          this.project.vitest.logger.warn(`Custom inspector host \"${host}\" will be ignored. Chromium only allows remote debugging on localhost.`)\n        }\n        this.project.vitest.logger.log(`Debugger listening on ws://127.0.0.1:${port}`)\n      }\n\n      // start Vitest UI maximized only on supported browsers\n      if (this.project.config.browser.ui && this.browserName === 'chromium') {\n        if (!launchOptions.args) {\n          launchOptions.args = []\n        }\n        if (!launchOptions.args.includes('--start-maximized') && !launchOptions.args.includes('--start-fullscreen')) {\n          launchOptions.args.push('--start-maximized')\n        }\n      }\n\n      debug?.('[%s] initializing the browser with launch options: %O', this.browserName, launchOptions)\n\n      if (this.options.connectOptions) {\n        let { wsEndpoint, headers = {}, ...connectOptions } = this.options.connectOptions\n        if ('x-playwright-launch-options' in headers) {\n          this.project.vitest.logger.warn(\n            c.yellow(\n              'Detected \"x-playwright-launch-options\" in connectOptions.headers. Provider config launchOptions is ignored.',\n            ),\n          )\n        }\n        else {\n          headers = { ...headers, 'x-playwright-launch-options': JSON.stringify(launchOptions) }\n        }\n        this.browser = await playwright[this.browserName].connect(wsEndpoint, {\n          ...connectOptions,\n          headers,\n        })\n        this.browserPromise = null\n        return this.browser\n      }\n\n      let persistentContextOption = this.options.persistentContext\n      if (persistentContextOption && openBrowserOptions.parallel) {\n        persistentContextOption = false\n        this.project.vitest.logger.warn(\n          c.yellow(`The persistentContext option is ignored because tests are running in parallel.`),\n        )\n      }\n      if (persistentContextOption) {\n        const userDataDir\n          = typeof this.options.persistentContext === 'string'\n            ? this.options.persistentContext\n            : './node_modules/.cache/vitest-playwright-user-data'\n        // TODO: how to avoid default \"about\" page?\n        this.persistentContext = await playwright[this.browserName].launchPersistentContext(\n          userDataDir,\n          {\n            ...launchOptions,\n            ...this.getContextOptions(),\n          },\n        )\n        this.browser = this.persistentContext.browser()!\n      }\n      else {\n        this.browser = await playwright[this.browserName].launch(launchOptions)\n      }\n      this.browserPromise = null\n      return this.browser\n    })()\n\n    return this.browserPromise\n  }\n\n  private createMocker(): BrowserModuleMocker {\n    const idPreficates = new Map<string, (url: URL) => boolean>()\n    const sessionIds = new Map<string, string[]>()\n\n    function createPredicate(sessionId: string, url: string) {\n      const moduleUrl = new URL(url, 'http://localhost')\n      const predicate = (url: URL) => {\n        if (url.searchParams.has('_vitest_original')) {\n          return false\n        }\n\n        // different modules, ignore request\n        if (url.pathname !== moduleUrl.pathname) {\n          return false\n        }\n\n        url.searchParams.delete('t')\n        url.searchParams.delete('v')\n        url.searchParams.delete('import')\n\n        // different search params, ignore request\n        if (url.searchParams.size !== moduleUrl.searchParams.size) {\n          return false\n        }\n\n        // check that all search params are the same\n        for (const [param, value] of url.searchParams.entries()) {\n          if (moduleUrl.searchParams.get(param) !== value) {\n            return false\n          }\n        }\n\n        return true\n      }\n      const ids = sessionIds.get(sessionId) || []\n      ids.push(moduleUrl.href)\n      sessionIds.set(sessionId, ids)\n      idPreficates.set(predicateKey(sessionId, moduleUrl.href), predicate)\n      return predicate\n    }\n\n    function predicateKey(sessionId: string, url: string) {\n      return `${sessionId}:${url}`\n    }\n\n    return {\n      register: async (sessionId: string, module: MockedModule): Promise<void> => {\n        const page = this.getPage(sessionId)\n        await page.context().route(createPredicate(sessionId, module.url), async (route) => {\n          if (module.type === 'manual') {\n            const exports = Object.keys(await module.resolve())\n            const body = createManualModuleSource(module.url, exports)\n            return route.fulfill({\n              body,\n              headers: getHeaders(this.project.browser!.vite.config),\n            })\n          }\n\n          // webkit doesn't support redirect responses\n          // https://github.com/microsoft/playwright/issues/18318\n          const isWebkit = this.browserName === 'webkit'\n          if (isWebkit) {\n            let url: string\n            if (module.type === 'redirect') {\n              const redirect = new URL(module.redirect)\n              url = redirect.href.slice(redirect.origin.length)\n            }\n            else {\n              const request = new URL(route.request().url())\n              request.searchParams.set('mock', module.type)\n              url = request.href.slice(request.origin.length)\n            }\n\n            const result = await this.project.browser!.vite.transformRequest(url).catch(() => null)\n            if (!result) {\n              return route.continue()\n            }\n            let content = result.code\n            if (result.map && 'version' in result.map && result.map.mappings) {\n              const type = isDirectCSSRequest(url) ? 'css' : 'js'\n              content = getCodeWithSourcemap(type, content.toString(), result.map)\n            }\n            return route.fulfill({\n              body: content,\n              headers: getHeaders(this.project.browser!.vite.config),\n            })\n          }\n\n          if (module.type === 'redirect') {\n            return route.fulfill({\n              status: 302,\n              headers: {\n                Location: module.redirect,\n              },\n            })\n          }\n          else if (module.type === 'automock' || module.type === 'autospy') {\n            const url = new URL(route.request().url())\n            url.searchParams.set('mock', module.type)\n            return route.fulfill({\n              status: 302,\n              headers: {\n                Location: url.href,\n              },\n            })\n          }\n          else {\n            // all types are exhausted\n            const _module: never = module\n          }\n        })\n      },\n      delete: async (sessionId: string, id: string): Promise<void> => {\n        const page = this.getPage(sessionId)\n        const key = predicateKey(sessionId, id)\n        const predicate = idPreficates.get(key)\n        if (predicate) {\n          await page.context().unroute(predicate).finally(() => idPreficates.delete(key))\n        }\n      },\n      clear: async (sessionId: string): Promise<void> => {\n        const page = this.getPage(sessionId)\n        const ids = sessionIds.get(sessionId) || []\n        const promises = ids.map((id) => {\n          const key = predicateKey(sessionId, id)\n          const predicate = idPreficates.get(key)\n          if (predicate) {\n            return page.context().unroute(predicate).finally(() => idPreficates.delete(key))\n          }\n          return null\n        })\n        await Promise.all(promises).finally(() => sessionIds.delete(sessionId))\n      },\n    }\n  }\n\n  private async createContext(sessionId: string, openBrowserOptions: { parallel: boolean }) {\n    await this._throwIfClosing()\n\n    if (this.contexts.has(sessionId)) {\n      debug?.('[%s][%s] the context already exists, reusing it', sessionId, this.browserName)\n      return this.contexts.get(sessionId)!\n    }\n\n    const browser = await this.openBrowser(openBrowserOptions)\n    await this._throwIfClosing(browser)\n    const actionTimeout = this.options.actionTimeout\n    const options = this.getContextOptions()\n    // TODO: investigate the consequences for Vitest 5\n    // else {\n    // if UI is disabled, keep the iframe scale to 1\n    // options.viewport ??= this.project.config.browser.viewport\n    // }\n    const context = this.persistentContext ?? await browser.newContext(options)\n    await this._throwIfClosing(context)\n    if (actionTimeout != null) {\n      context.setDefaultTimeout(actionTimeout)\n    }\n    debug?.('[%s][%s] the context is ready', sessionId, this.browserName)\n    this.contexts.set(sessionId, context)\n    return context\n  }\n\n  private getContextOptions(): BrowserContextOptions {\n    const contextOptions = this.options.contextOptions ?? {}\n    const options = {\n      ...contextOptions,\n      ignoreHTTPSErrors: true,\n    } satisfies BrowserContextOptions\n    if (this.project.config.browser.ui) {\n      options.viewport = null\n    }\n    return options\n  }\n\n  public getPage(sessionId: string): Page {\n    const page = this.pages.get(sessionId)\n    if (!page) {\n      throw new Error(`Page \"${sessionId}\" not found in ${this.browserName} browser.`)\n    }\n    return page\n  }\n\n  public getCommandsContext(sessionId: string): {\n    page: Page\n    context: BrowserContext\n    frame: () => Promise<Frame>\n    readonly iframe: FrameLocator\n  } {\n    const page = this.getPage(sessionId)\n    return {\n      page,\n      context: this.contexts.get(sessionId)!,\n      frame(): Promise<Frame> {\n        return new Promise<Frame>((resolve, reject) => {\n          const frame = page.frame('vitest-iframe')\n          if (frame) {\n            return resolve(frame)\n          }\n\n          const timeout = setTimeout(() => {\n            const err = new Error(`Cannot find \"vitest-iframe\" on the page. This is a bug in Vitest, please report it.`)\n            reject(err)\n          }, 1000).unref()\n          page.on('frameattached', (frame) => {\n            clearTimeout(timeout)\n            resolve(frame)\n          })\n        })\n      },\n      get iframe(): FrameLocator {\n        return page.frameLocator('[data-vitest=\"true\"]')!\n      },\n    }\n  }\n\n  private async openBrowserPage(sessionId: string, options: { parallel: boolean }) {\n    await this._throwIfClosing()\n\n    if (this.pages.has(sessionId)) {\n      debug?.('[%s][%s] the page already exists, closing the old one', sessionId, this.browserName)\n      const page = this.pages.get(sessionId)!\n      await page.close()\n      this.pages.delete(sessionId)\n    }\n\n    const context = await this.createContext(sessionId, options)\n    const page = await context.newPage()\n    debug?.('[%s][%s] the page is ready', sessionId, this.browserName)\n    await this._throwIfClosing(page)\n    this.pages.set(sessionId, page)\n\n    if (process.env.VITEST_PW_DEBUG) {\n      page.on('requestfailed', (request) => {\n        console.error(\n          '[PW Error]',\n          request.resourceType(),\n          'request failed for',\n          request.url(),\n          'url:',\n          request.failure()?.errorText,\n        )\n      })\n    }\n\n    return page\n  }\n\n  async openPage(sessionId: string, url: string, options: { parallel: boolean }): Promise<void> {\n    debug?.('[%s][%s] creating the browser page for %s', sessionId, this.browserName, url)\n    const browserPage = await this.openBrowserPage(sessionId, options)\n    debug?.('[%s][%s] browser page is created, opening %s', sessionId, this.browserName, url)\n    await browserPage.goto(url, { timeout: 0 })\n    await this._throwIfClosing(browserPage)\n  }\n\n  private async _throwIfClosing(disposable?: { close: () => Promise<void> }) {\n    if (this.closing) {\n      debug?.('[%s] provider was closed, cannot perform the action on %s', this.browserName, String(disposable))\n      await disposable?.close()\n      this.pages.clear()\n      this.contexts.clear()\n      this.browser = null\n      this.browserPromise = null\n      throw new Error(`[vitest] The provider was closed.`)\n    }\n  }\n\n  async getCDPSession(sessionid: string): Promise<CDPSession> {\n    const page = this.getPage(sessionid)\n    const cdp = await page.context().newCDPSession(page)\n    return {\n      send(method, params) {\n        return cdp.send(method as any, params)\n      },\n      on(event, listener) {\n        return cdp.on(event as any, listener)\n      },\n      off(event, listener) {\n        return cdp.off(event as any, listener)\n      },\n      once(event, listener) {\n        return cdp.once(event as any, listener)\n      },\n    }\n  }\n\n  async close(): Promise<void> {\n    process.off('SIGTERM', this.onSIGTERM)\n\n    debug?.('[%s] closing provider', this.browserName)\n    this.closing = true\n    if (this.browserPromise) {\n      await this.browserPromise\n      this.browserPromise = null\n    }\n    const browser = this.browser\n    this.browser = null\n    await Promise.all([...this.pages.values()].map(p => p.close()))\n    this.pages.clear()\n    if (this.persistentContext) {\n      await this.persistentContext.close()\n    }\n    else {\n      await Promise.all([...this.contexts.values()].map(c => c.close()))\n    }\n    this.contexts.clear()\n    await browser?.close()\n    debug?.('[%s] provider is closed', this.browserName)\n  }\n}\n\nfunction getHeaders(config: ResolvedConfig) {\n  const headers: Record<string, string> = {\n    'Content-Type': 'application/javascript',\n  }\n\n  for (const name in config.server.headers) {\n    headers[name] = String(config.server.headers[name]!)\n  }\n  return headers\n}\n\nfunction getCodeWithSourcemap(\n  type: 'js' | 'css',\n  code: string,\n  map: SourceMap,\n): string {\n  if (type === 'js') {\n    code += `\\n//# sourceMappingURL=${genSourceMapUrl(map)}`\n  }\n  else if (type === 'css') {\n    code += `\\n/*# sourceMappingURL=${genSourceMapUrl(map)} */`\n  }\n\n  return code\n}\n\nfunction genSourceMapUrl(map: SourceMap | string): string {\n  if (typeof map !== 'string') {\n    map = JSON.stringify(map)\n  }\n  return `data:application/json;base64,${Buffer.from(map).toString('base64')}`\n}\n\nconst directRequestRE = /[?&]direct\\b/\n\nfunction isDirectCSSRequest(request: string): boolean {\n  return isCSSRequest(request) && directRequestRE.test(request)\n}\n\ndeclare module 'vitest/node' {\n  export interface BrowserCommandContext {\n    page: Page\n    frame(): Promise<Frame>\n    iframe: FrameLocator\n    context: BrowserContext\n  }\n\n  export interface _BrowserNames {\n    playwright: PlaywrightBrowser\n  }\n\n  export interface ToMatchScreenshotOptions\n    extends Omit<\n      ScreenshotMatcherOptions,\n      'comparatorName' | 'comparatorOptions'\n    >, CustomComparatorsRegistry {}\n\n  export interface ToMatchScreenshotComparators\n    extends ScreenshotComparatorRegistry {}\n}\n\ntype PWHoverOptions = NonNullable<Parameters<Page['hover']>[1]>\ntype PWClickOptions = NonNullable<Parameters<Page['click']>[1]>\ntype PWDoubleClickOptions = NonNullable<Parameters<Page['dblclick']>[1]>\ntype PWFillOptions = NonNullable<Parameters<Page['fill']>[2]>\ntype PWScreenshotOptions = NonNullable<Parameters<Page['screenshot']>[0]>\ntype PWSelectOptions = NonNullable<Parameters<Page['selectOption']>[2]>\ntype PWDragAndDropOptions = NonNullable<Parameters<Page['dragAndDrop']>[2]>\ntype PWSetInputFiles = NonNullable<Parameters<Page['setInputFiles']>[2]>\n// Must be re-aliased here or rollup-plugin-dts removes the import alias and you end up with a circular reference\ntype PWCDPSession = Pick<PlaywrightCDPSession, 'send' | 'on' | 'off' | 'once'>\n\nexport { type PWCDPSession as CDPSession }\n\ndeclare module 'vitest/browser' {\n  export interface UserEventHoverOptions extends PWHoverOptions {}\n  export interface UserEventClickOptions extends PWClickOptions {}\n  export interface UserEventDoubleClickOptions extends PWDoubleClickOptions {}\n  export interface UserEventTripleClickOptions extends PWClickOptions {}\n  export interface UserEventFillOptions extends PWFillOptions {}\n  export interface UserEventSelectOptions extends PWSelectOptions {}\n  export interface UserEventDragAndDropOptions extends PWDragAndDropOptions {}\n  export interface UserEventUploadOptions extends PWSetInputFiles {}\n\n  export interface ScreenshotOptions extends Omit<PWScreenshotOptions, 'mask'> {\n    mask?: ReadonlyArray<Element | Locator> | undefined\n  }\n\n  export interface CDPSession extends PWCDPSession {}\n}\n"
  },
  {
    "path": "packages/browser-playwright/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"types\": [\"node\", \"vite/client\"],\n    \"isolatedDeclarations\": true\n  },\n  \"exclude\": [\n    \"dist\",\n    \"node_modules\",\n    \"**/vite.config.ts\",\n    \"src/client/**/*.ts\"\n  ]\n}\n"
  },
  {
    "path": "packages/browser-preview/README.md",
    "content": "# @vitest/browser-preview\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/browser-preview?color=a1b858&label=)](https://npmx.dev/package/@vitest/browser-preview)\n\nSee how your tests look like in a real browser. For proper and stable browser testing, we recommend running tests in a headless browser in your CI instead. For this, you should use either:\n\n- [@vitest/browser-playwright](https://npmx.dev/package/@vitest/browser-playwright) - run tests using [playwright](https://playwright.dev/)\n- [@vitest/browser-webdriverio](https://npmx.dev/package/@vitest/browser-webdriverio) - run tests using [webdriverio](https://webdriver.io/)\n\n## Installation\n\nInstall the package with your favorite package manager:\n\n```sh\nnpm install -D @vitest/browser-preview\n# or\nyarn add -D @vitest/browser-preview\n# or\npnpm add -D @vitest/browser-preview\n```\n\nThen specify it in the `browser.provider` field of your Vitest configuration:\n\n```ts\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config'\nimport { preview } from '@vitest/browser-preview'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: preview(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  },\n})\n```\n\nThen run Vitest in the browser mode:\n\n```sh\nnpx vitest --browser\n```\n\nIf browser didn't open automatically, follow the link in the terminal to open the browser preview.\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/browser-preview) | [Documentation](https://vitest.dev/guide/browser/)\n"
  },
  {
    "path": "packages/browser-preview/context.d.ts",
    "content": "export * from '@vitest/browser/context'\n"
  },
  {
    "path": "packages/browser-preview/package.json",
    "content": "{\n  \"name\": \"@vitest/browser-preview\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Browser running for Vitest using your browser of choice\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/guide/browser\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/browser-preview\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"browser\",\n    \"component\",\n    \"mocks\",\n    \"test\",\n    \"testing\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./context\": {\n      \"types\": \"./context.d.ts\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"context.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && pnpm rollup -c\",\n    \"dev\": \"rollup -c --watch --watch.include 'src/**'\"\n  },\n  \"peerDependencies\": {\n    \"vitest\": \"workspace:*\"\n  },\n  \"dependencies\": {\n    \"@testing-library/dom\": \"^10.4.1\",\n    \"@testing-library/user-event\": \"^14.6.1\",\n    \"@vitest/browser\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/browser-preview/rollup.config.js",
    "content": "import { createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst external = [\n  ...Object.keys(pkg.dependencies),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^@?vitest(\\/|$)/,\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  resolve({\n    preferBuiltins: true,\n  }),\n  json(),\n  commonjs(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nexport default () =>\n  defineConfig([\n    {\n      input: {\n        index: './src/index.ts',\n        locators: './src/locators.ts',\n      },\n      output: {\n        dir: 'dist',\n        format: 'esm',\n      },\n      external,\n      context: 'null',\n      plugins: [\n        ...dtsUtils.isolatedDecl(),\n        ...plugins,\n      ],\n    },\n    {\n      input: dtsUtils.dtsInput('src/index.ts'),\n      output: {\n        dir: 'dist',\n        entryFileNames: '[name].d.ts',\n        format: 'esm',\n      },\n      watch: false,\n      external,\n      plugins: dtsUtils.dts(),\n    },\n  ])\n"
  },
  {
    "path": "packages/browser-preview/src/constants.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { resolve } from 'pathe'\n\nconst pkgRoot = resolve(fileURLToPath(import.meta.url), '../..')\nexport const distRoot: string = resolve(pkgRoot, 'dist')\n"
  },
  {
    "path": "packages/browser-preview/src/index.ts",
    "content": "export {\n  preview,\n  PreviewBrowserProvider,\n} from './preview'\nexport { defineBrowserCommand } from '@vitest/browser'\n"
  },
  {
    "path": "packages/browser-preview/src/locators.ts",
    "content": "import type {\n  UserEventClearOptions,\n  UserEventClickOptions,\n  UserEventFillOptions,\n  UserEventHoverOptions,\n  UserEventSelectOptions,\n  UserEventUploadOptions,\n  UserEventWheelOptions,\n} from 'vitest/browser'\nimport {\n  convertElementToCssSelector,\n  getByAltTextSelector,\n  getByLabelSelector,\n  getByPlaceholderSelector,\n  getByRoleSelector,\n  getByTestIdSelector,\n  getByTextSelector,\n  getByTitleSelector,\n  Locator,\n  selectorEngine,\n} from '@vitest/browser/locators'\nimport { page, server, userEvent, utils } from 'vitest/browser'\nimport { __INTERNAL } from 'vitest/internal/browser'\n\nclass PreviewLocator extends Locator {\n  constructor(protected _pwSelector: string, protected _container?: Element) {\n    super()\n  }\n\n  override get selector() {\n    const selectors = this.elements().map(element => convertElementToCssSelector(element))\n    if (!selectors.length) {\n      throw utils.getElementError(this._pwSelector, this._container || document.body)\n    }\n    return selectors.join(', ')\n  }\n\n  async click(options?: UserEventClickOptions): Promise<void> {\n    const element = await this.findElement(options)\n    return userEvent.click(element)\n  }\n\n  async dblClick(options?: UserEventClickOptions): Promise<void> {\n    const element = await this.findElement(options)\n    return userEvent.dblClick(element)\n  }\n\n  async tripleClick(options?: UserEventClickOptions): Promise<void> {\n    const element = await this.findElement(options)\n    return userEvent.tripleClick(element)\n  }\n\n  async hover(options?: UserEventHoverOptions): Promise<void> {\n    const element = await this.findElement(options)\n    return userEvent.hover(element)\n  }\n\n  async unhover(options?: UserEventHoverOptions): Promise<void> {\n    const element = await this.findElement(options)\n    return userEvent.unhover(element)\n  }\n\n  async fill(text: string, options?: UserEventFillOptions): Promise<void> {\n    const element = await this.findElement(options)\n    return userEvent.fill(element, text)\n  }\n\n  async upload(file: string | string[] | File | File[], options?: UserEventUploadOptions): Promise<void> {\n    const element = await this.findElement(options)\n    return userEvent.upload(element, file)\n  }\n\n  async wheel(options: UserEventWheelOptions): Promise<void> {\n    const element = await this.findElement(options)\n    return userEvent.wheel(element, options)\n  }\n\n  async selectOptions(\n    options: string | string[] | HTMLElement | HTMLElement[] | Locator | Locator[],\n    settings?: UserEventSelectOptions,\n  ): Promise<void> {\n    const element = await this.findElement(settings)\n    return userEvent.selectOptions(element, options)\n  }\n\n  async clear(options?: UserEventClearOptions): Promise<void> {\n    const element = await this.findElement(options)\n    return userEvent.clear(element)\n  }\n\n  protected locator(selector: string) {\n    return new PreviewLocator(`${this._pwSelector} >> ${selector}`, this._container)\n  }\n\n  protected elementLocator(element: Element) {\n    return new PreviewLocator(\n      selectorEngine.generateSelectorSimple(element),\n      element,\n    )\n  }\n}\n\npage.extend({\n  getByLabelText(text, options) {\n    return new PreviewLocator(getByLabelSelector(text, options))\n  },\n  getByRole(role, options) {\n    return new PreviewLocator(getByRoleSelector(role, options))\n  },\n  getByTestId(testId) {\n    return new PreviewLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute, testId))\n  },\n  getByAltText(text, options) {\n    return new PreviewLocator(getByAltTextSelector(text, options))\n  },\n  getByPlaceholder(text, options) {\n    return new PreviewLocator(getByPlaceholderSelector(text, options))\n  },\n  getByText(text, options) {\n    return new PreviewLocator(getByTextSelector(text, options))\n  },\n  getByTitle(title, options) {\n    return new PreviewLocator(getByTitleSelector(title, options))\n  },\n\n  elementLocator(element: Element) {\n    return new PreviewLocator(\n      selectorEngine.generateSelectorSimple(element),\n      element,\n    )\n  },\n})\n\n__INTERNAL._createLocator = selector => new PreviewLocator(selector)\n"
  },
  {
    "path": "packages/browser-preview/src/preview.ts",
    "content": "import type { SelectorOptions } from 'vitest/browser'\nimport type { BrowserProvider, BrowserProviderOption, TestProject } from 'vitest/node'\nimport { nextTick } from 'node:process'\nimport { defineBrowserProvider } from '@vitest/browser'\nimport { resolve } from 'pathe'\nimport { distRoot } from './constants'\n\nexport function preview(): BrowserProviderOption {\n  return defineBrowserProvider({\n    name: 'preview',\n    providerFactory(project) {\n      return new PreviewBrowserProvider(project)\n    },\n  })\n}\n\nexport class PreviewBrowserProvider implements BrowserProvider {\n  public name = 'preview' as const\n  public supportsParallelism: boolean = false\n  private project!: TestProject\n  private open = false\n\n  public distRoot: string = distRoot\n\n  public initScripts: string[] = [\n    resolve(distRoot, 'locators.js'),\n  ]\n\n  constructor(project: TestProject) {\n    this.project = project\n    this.open = false\n    if (project.config.browser.headless) {\n      throw new Error(\n        'You\\'ve enabled headless mode for \"preview\" provider but it doesn\\'t support it. Use \"playwright\" or \"webdriverio\" instead: https://vitest.dev/guide/browser/#configuration',\n      )\n    }\n    nextTick(() => {\n      project.vitest.logger.printBrowserBanner(project)\n    })\n  }\n\n  isOpen(): boolean {\n    return this.open\n  }\n\n  getCommandsContext() {\n    return {}\n  }\n\n  async openPage(_sessionId: string, url: string): Promise<void> {\n    this.open = true\n    if (!this.project.browser) {\n      throw new Error('Browser is not initialized')\n    }\n    const options = this.project.browser.vite.config.server\n    const _open = options.open\n    options.open = url\n    this.project.browser.vite.openBrowser()\n    options.open = _open\n  }\n\n  async close(): Promise<void> {}\n}\n\ndeclare module 'vitest/browser' {\n  export interface UserEventClickOptions extends SelectorOptions {}\n  export interface UserEventHoverOptions extends SelectorOptions {}\n  export interface UserEventFillOptions extends SelectorOptions {}\n  export interface UserEventSelectOptions extends SelectorOptions {}\n  export interface UserEventClearOptions extends SelectorOptions {}\n  export interface UserEventDoubleClickOptions extends SelectorOptions {}\n  export interface UserEventTripleClickOptions extends SelectorOptions {}\n  export interface UserEventUploadOptions extends SelectorOptions {}\n  export interface UserEventWheelBaseOptions extends SelectorOptions {}\n  export interface LocatorScreenshotOptions extends SelectorOptions {}\n}\n"
  },
  {
    "path": "packages/browser-preview/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"types\": [\"node\", \"vite/client\"],\n    \"isolatedDeclarations\": true\n  },\n  \"exclude\": [\n    \"dist\",\n    \"node_modules\",\n    \"**/vite.config.ts\",\n    \"src/client/**/*.ts\"\n  ]\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/README.md",
    "content": "# @vitest/browser-webdriverio\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/browser-webdriverio?color=a1b858&label=)](https://npmx.dev/package/@vitest/browser-webdriverio)\n\nRun your Vitest [browser tests](https://vitest.dev/guide/browser/) using [webdriverio](https://webdriver.io/docs/api/browser) API. Note that Vitest does not use webdriverio as a test runner, but only as a browser provider.\n\nWe recommend using this package if you are already using webdriverio in your project.\n\n## Installation\n\nInstall the package with your favorite package manager:\n\n```sh\nnpm install -D @vitest/browser-webdriverio\n# or\nyarn add -D @vitest/browser-webdriverio\n# or\npnpm add -D @vitest/browser-webdriverio\n```\n\nThen specify it in the `browser.provider` field of your Vitest configuration:\n\n```ts\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config'\nimport { webdriverio } from '@vitest/browser-webdriverio'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: webdriverio({\n        // ...custom webdriverio options\n      }),\n      instances: [\n        { browser: 'chrome' },\n      ],\n    },\n  },\n})\n```\n\nThen run Vitest in the browser mode:\n\n```sh\nnpx vitest --browser\n```\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/browser-webdriverio) | [Documentation](https://vitest.dev/config/browser/webdriverio)\n"
  },
  {
    "path": "packages/browser-webdriverio/context.d.ts",
    "content": "export * from '@vitest/browser/context'\n"
  },
  {
    "path": "packages/browser-webdriverio/package.json",
    "content": "{\n  \"name\": \"@vitest/browser-webdriverio\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Browser running for Vitest using webdriverio\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/config/browser/webdriverio\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/browser-webdriverio\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"browser\",\n    \"webdriverio\",\n    \"wdio\",\n    \"component\",\n    \"mocks\",\n    \"test\",\n    \"testing\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./context\": {\n      \"types\": \"./context.d.ts\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"context.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && pnpm rollup -c\",\n    \"dev\": \"rollup -c --watch --watch.include 'src/**'\"\n  },\n  \"peerDependencies\": {\n    \"vitest\": \"workspace:*\",\n    \"webdriverio\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"webdriverio\": {\n      \"optional\": false\n    }\n  },\n  \"dependencies\": {\n    \"@vitest/browser\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@wdio/types\": \"^9.24.0\",\n    \"vitest\": \"workspace:*\",\n    \"webdriverio\": \"^9.20.0\"\n  }\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/rollup.config.js",
    "content": "import { createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst external = [\n  ...Object.keys(pkg.dependencies),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^@?vitest(\\/|$)/,\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  resolve({\n    preferBuiltins: true,\n  }),\n  json(),\n  commonjs(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nexport default () =>\n  defineConfig([\n    {\n      input: {\n        index: './src/index.ts',\n        locators: './src/locators.ts',\n      },\n      output: {\n        dir: 'dist',\n        format: 'esm',\n      },\n      external,\n      context: 'null',\n      plugins: [\n        ...dtsUtils.isolatedDecl(),\n        ...plugins,\n      ],\n    },\n    {\n      input: dtsUtils.dtsInput('src/index.ts'),\n      output: {\n        dir: 'dist',\n        entryFileNames: '[name].d.ts',\n        format: 'esm',\n      },\n      watch: false,\n      external,\n      plugins: dtsUtils.dts(),\n    },\n  ])\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/clear.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\n\nexport const clear: UserEventCommand<UserEvent['clear']> = async (\n  context,\n  selector,\n) => {\n  const browser = context.browser\n  await browser.$(selector).clearValue()\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/click.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\n\nexport const click: UserEventCommand<UserEvent['click']> = async (\n  context,\n  selector,\n  options,\n) => {\n  const browser = context.browser\n  await browser.$(selector).click(options)\n}\n\nexport const dblClick: UserEventCommand<UserEvent['dblClick']> = async (\n  context,\n  selector,\n  _options,\n) => {\n  const browser = context.browser\n  await browser.$(selector).doubleClick()\n}\n\nexport const tripleClick: UserEventCommand<UserEvent['tripleClick']> = async (\n  context,\n  selector,\n  _options,\n) => {\n  const browser = context.browser\n  await browser\n    .action('pointer', { parameters: { pointerType: 'mouse' } })\n  // move the pointer over the button\n    .move({ origin: browser.$(selector) })\n  // simulate 3 clicks\n    .down()\n    .up()\n    .pause(50)\n    .down()\n    .up()\n    .pause(50)\n    .down()\n    .up()\n    .pause(50)\n  // run the sequence\n    .perform()\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/dragAndDrop.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\n\nexport const dragAndDrop: UserEventCommand<UserEvent['dragAndDrop']> = async (\n  context,\n  source,\n  target,\n  options_,\n) => {\n  const $source = context.browser.$(source)\n  const $target = context.browser.$(target)\n  const options = (options_ || {}) as any\n  const duration = options.duration ?? 10\n\n  // https://github.com/webdriverio/webdriverio/issues/8022#issuecomment-1700919670\n  await context.browser\n    .action('pointer')\n    .move({ duration: 0, origin: $source, x: options.sourceX ?? 0, y: options.sourceY ?? 0 })\n    .down({ button: 0 })\n    .move({ duration: 0, origin: 'pointer', x: 0, y: 0 })\n    .pause(duration)\n    .move({ duration: 0, origin: $target, x: options.targetX ?? 0, y: options.targetY ?? 0 })\n    .move({ duration: 0, origin: 'pointer', x: 1, y: 0 })\n    .move({ duration: 0, origin: 'pointer', x: -1, y: 0 })\n    .up({ button: 0 })\n    .perform()\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/fill.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\n\nexport const fill: UserEventCommand<UserEvent['fill']> = async (\n  context,\n  selector,\n  text,\n  _options = {},\n) => {\n  const browser = context.browser\n  await browser.$(selector).setValue(text)\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/hover.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\n\nexport const hover: UserEventCommand<UserEvent['hover']> = async (\n  context,\n  selector,\n  options = {},\n) => {\n  const browser = context.browser\n  await browser.$(selector).moveTo(options as any)\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/index.ts",
    "content": "import { clear } from './clear'\nimport { click, dblClick, tripleClick } from './click'\nimport { dragAndDrop } from './dragAndDrop'\nimport { fill } from './fill'\nimport { hover } from './hover'\nimport { keyboard, keyboardCleanup } from './keyboard'\nimport { takeScreenshot } from './screenshot'\nimport { selectOptions } from './select'\nimport { tab } from './tab'\nimport { type } from './type'\nimport { upload } from './upload'\nimport { viewport } from './viewport'\nimport { wheel } from './wheel'\n\nexport default {\n  __vitest_upload: upload as typeof upload,\n  __vitest_click: click as typeof click,\n  __vitest_dblClick: dblClick as typeof dblClick,\n  __vitest_tripleClick: tripleClick as typeof tripleClick,\n  __vitest_wheel: wheel as typeof wheel,\n  __vitest_takeScreenshot: takeScreenshot as typeof takeScreenshot,\n  __vitest_type: type as typeof type,\n  __vitest_clear: clear as typeof clear,\n  __vitest_fill: fill as typeof fill,\n  __vitest_tab: tab as typeof tab,\n  __vitest_keyboard: keyboard as typeof keyboard,\n  __vitest_selectOptions: selectOptions as typeof selectOptions,\n  __vitest_dragAndDrop: dragAndDrop as typeof dragAndDrop,\n  __vitest_hover: hover as typeof hover,\n  __vitest_cleanup: keyboardCleanup as typeof keyboardCleanup,\n  __vitest_viewport: viewport as typeof viewport,\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/keyboard.ts",
    "content": "import type { BrowserProvider } from 'vitest/node'\nimport type { WebdriverBrowserProvider } from '../webdriverio'\nimport type { UserEventCommand } from './utils'\nimport { parseKeyDef } from '@vitest/browser'\nimport { Key } from 'webdriverio'\n\nexport interface KeyboardState {\n  unreleased: string[]\n}\n\nexport const keyboard: UserEventCommand<(\n  text: string,\n  state: KeyboardState,\n) => Promise<{ unreleased: string[] }>> = async (\n  context,\n  text,\n  state,\n) => {\n  await context.browser.execute(focusIframe)\n\n  const pressed = new Set<string>(state.unreleased)\n\n  await keyboardImplementation(\n    pressed,\n    context.provider,\n    context.sessionId,\n    text,\n    async () => {\n      await context.browser.execute(selectAll)\n    },\n    true,\n  )\n\n  return {\n    unreleased: Array.from(pressed),\n  }\n}\n\nexport const keyboardCleanup: UserEventCommand<(state: KeyboardState) => Promise<void>> = async (\n  context,\n  state,\n) => {\n  if (!state.unreleased) {\n    return\n  }\n  const keyboard = context.browser.action('key')\n  for (const key of state.unreleased) {\n    keyboard.up(key)\n  }\n  await keyboard.perform()\n}\n\nexport async function keyboardImplementation(\n  pressed: Set<string>,\n  provider: BrowserProvider,\n  _sessionId: string,\n  text: string,\n  selectAll: () => Promise<void>,\n  skipRelease: boolean,\n): Promise<{ pressed: Set<string> }> {\n  const browser = (provider as WebdriverBrowserProvider).browser!\n  const actions = parseKeyDef(text)\n\n  let keyboard = browser.action('key')\n\n  for (const { releasePrevious, releaseSelf, repeat, keyDef } of actions) {\n    let key = keyDef.key!\n    const special = Key[key as 'Shift']\n\n    if (special) {\n      key = special\n    }\n\n    if (pressed.has(key)) {\n      keyboard.up(key)\n      pressed.delete(key)\n    }\n\n    if (!releasePrevious) {\n      if (key === 'selectall') {\n        await keyboard.perform()\n        keyboard = browser.action('key')\n        await selectAll()\n        continue\n      }\n\n      for (let i = 1; i <= repeat; i++) {\n        keyboard.down(key)\n      }\n\n      if (releaseSelf) {\n        keyboard.up(key)\n      }\n      else {\n        pressed.add(key)\n      }\n    }\n  }\n\n  // seems like webdriverio doesn't release keys automatically if skipRelease is true and all events are keyUp\n  const allRelease = keyboard.toJSON().actions.every(action => action.type === 'keyUp')\n\n  await keyboard.perform(allRelease ? false : skipRelease)\n\n  return {\n    pressed,\n  }\n}\n\nfunction focusIframe() {\n  if (\n    !document.activeElement\n    || document.activeElement.ownerDocument !== document\n    || document.activeElement === document.body\n  ) {\n    window.focus()\n  }\n}\n\nfunction selectAll() {\n  const element = document.activeElement as HTMLInputElement\n  if (element && typeof element.select === 'function') {\n    element.select()\n  }\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/screenshot.ts",
    "content": "import type { ScreenshotOptions } from 'vitest/browser'\nimport type { BrowserCommandContext } from 'vitest/node'\nimport crypto from 'node:crypto'\nimport { mkdir, rm } from 'node:fs/promises'\nimport { normalize as platformNormalize } from 'node:path'\nimport { resolveScreenshotPath } from '@vitest/browser'\nimport { dirname, normalize, resolve } from 'pathe'\n\ninterface ScreenshotCommandOptions extends Omit<ScreenshotOptions, 'element' | 'mask'> {\n  element?: string\n  mask?: readonly string[]\n}\n\n/**\n * Takes a screenshot using the provided browser context and returns a buffer and the expected screenshot path.\n *\n * **Note**: the returned `path` indicates where the screenshot *might* be found.\n * It is not guaranteed to exist, especially if `options.save` is `false`.\n *\n * @throws {Error} If the function is not called within a test or if the browser provider does not support screenshots.\n */\nexport async function takeScreenshot(\n  context: BrowserCommandContext,\n  name: string,\n  options: Omit<ScreenshotCommandOptions, 'base64'>,\n): Promise<{ buffer: Buffer<ArrayBufferLike>; path: string }> {\n  if (!context.testPath) {\n    throw new Error(`Cannot take a screenshot without a test path`)\n  }\n\n  const path = resolveScreenshotPath(\n    context.testPath,\n    name,\n    context.project.config,\n    options.path,\n  )\n\n  // playwright does not need a screenshot path if we don't intend to save it\n  let savePath: string | undefined\n\n  if (options.save) {\n    savePath = normalize(path)\n\n    await mkdir(dirname(savePath), { recursive: true })\n  }\n\n  // webdriverio needs a path, so if one is not already set we create a temporary one\n  if (savePath === undefined) {\n    savePath = resolve(context.project.tmpDir, crypto.randomUUID())\n\n    await mkdir(context.project.tmpDir, { recursive: true })\n  }\n\n  const page = context.browser\n  const element = !options.element\n    ? await page.$('body')\n    : await page.$(`${options.element}`)\n\n  // webdriverio expects the path to contain the extension and only works with PNG files\n  const savePathWithExtension = savePath.endsWith('.png') ? savePath : `${savePath}.png`\n\n  // there seems to be a bug in webdriverio, `X:/` gets appended to cwd, so we convert to `X:\\`\n  const buffer = await element.saveScreenshot(\n    platformNormalize(savePathWithExtension),\n  )\n  if (!options.save) {\n    await rm(savePathWithExtension, { force: true })\n  }\n  return { buffer, path }\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/select.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\n\nexport const selectOptions: UserEventCommand<UserEvent['selectOptions']> = async (\n  context,\n  selector,\n  userValues,\n  _options = {},\n) => {\n  const values = userValues as any as [({ index: number })]\n\n  if (!values.length) {\n    return\n  }\n\n  const browser = context.browser\n\n  if (values.length === 1 && 'index' in values[0]) {\n    const selectElement = browser.$(selector)\n    await selectElement.selectByIndex(values[0].index)\n  }\n  else {\n    throw new Error('Provider \"webdriverio\" doesn\\'t support selecting multiple values at once')\n  }\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/tab.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { Key } from 'webdriverio'\n\nexport const tab: UserEventCommand<UserEvent['tab']> = async (\n  context,\n  options = {},\n) => {\n  const browser = context.browser\n  await browser.keys(options.shift === true ? [Key.Shift, Key.Tab] : [Key.Tab])\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/type.ts",
    "content": "import type { UserEvent } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { keyboardImplementation } from './keyboard'\n\nexport const type: UserEventCommand<UserEvent['type']> = async (\n  context,\n  selector,\n  text,\n  options = {},\n) => {\n  const { skipClick = false, skipAutoClose = false } = options\n  const unreleased = new Set(Reflect.get(options, 'unreleased') as string[] ?? [])\n\n  const browser = context.browser\n  const element = browser.$(selector)\n\n  if (!skipClick && !await element.isFocused()) {\n    await element.click()\n  }\n\n  await keyboardImplementation(\n    unreleased,\n    context.provider,\n    context.sessionId,\n    text,\n    () => browser.execute(() => {\n      const element = document.activeElement as HTMLInputElement\n      if (element && typeof element.select === 'function') {\n        element.select()\n      }\n    }),\n    skipAutoClose,\n  )\n\n  return {\n    unreleased: Array.from(unreleased),\n  }\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/upload.ts",
    "content": "import type { UserEventUploadOptions } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\nimport { resolve } from 'pathe'\n\nexport const upload: UserEventCommand<(element: string, files: Array<string | {\n  name: string\n  mimeType: string\n  base64: string\n}>, options: UserEventUploadOptions) => void> = async (\n  context,\n  selector,\n  files,\n  _options,\n) => {\n  const testPath = context.testPath\n  if (!testPath) {\n    throw new Error(`Cannot upload files outside of a test`)\n  }\n  const root = context.project.config.root\n\n  for (const file of files) {\n    if (typeof file !== 'string') {\n      throw new TypeError(`The \"${context.provider.name}\" provider doesn't support uploading files objects. Provide a file path instead.`)\n    }\n  }\n\n  const element = context.browser.$(selector)\n\n  for (const file of files) {\n    const filepath = resolve(root, file as string)\n    const remoteFilePath = await context.browser.uploadFile(filepath)\n    await element.addValue(remoteFilePath)\n  }\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/utils.ts",
    "content": "import type { Locator } from 'vitest/browser'\nimport type { BrowserCommand } from 'vitest/node'\n\nexport type UserEventCommand<T extends (...args: any) => any> = BrowserCommand<\n  ConvertUserEventParameters<Parameters<T>>\n>\n\ntype ConvertElementToLocator<T> = T extends Element | Locator ? string : T\ntype ConvertUserEventParameters<T extends unknown[]> = {\n  [K in keyof T]: ConvertElementToLocator<T[K]>;\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/viewport.ts",
    "content": "import type { WebdriverBrowserProvider } from '../webdriverio'\nimport type { UserEventCommand } from './utils'\n\nexport const viewport: UserEventCommand<(options: {\n  width: number\n  height: number\n}) => void> = async (context, options) => {\n  await (context.provider as WebdriverBrowserProvider).setViewport(options)\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/commands/wheel.ts",
    "content": "import type { Locator, UserEventWheelDeltaOptions } from 'vitest/browser'\nimport type { UserEventCommand } from './utils'\n\ntype WheelCommand = (element: Locator | Element, options: UserEventWheelDeltaOptions) => Promise<void>\n\nexport const wheel: UserEventCommand<WheelCommand> = async (\n  context,\n  selector,\n  options,\n) => {\n  const browser = context.browser\n  const times = options.times ?? 1\n  const deltaX = options.delta.x ?? 0\n  const deltaY = options.delta.y ?? 0\n\n  let action = browser.action('wheel')\n  const wheelOptions: Parameters<typeof action['scroll']>[0] = {\n    deltaX,\n    deltaY,\n    origin: browser.$(selector),\n  }\n\n  for (let count = 0; count < times; count += 1) {\n    action = action.scroll(wheelOptions)\n  }\n\n  await action.perform()\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/constants.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { resolve } from 'pathe'\n\nconst pkgRoot = resolve(fileURLToPath(import.meta.url), '../..')\nexport const distRoot: string = resolve(pkgRoot, 'dist')\n"
  },
  {
    "path": "packages/browser-webdriverio/src/index.ts",
    "content": "export {\n  WebdriverBrowserProvider,\n  webdriverio,\n  type WebdriverProviderOptions,\n} from './webdriverio'\nexport { defineBrowserCommand } from '@vitest/browser'\n"
  },
  {
    "path": "packages/browser-webdriverio/src/locators.ts",
    "content": "import type {\n  LocatorScreenshotOptions,\n  UserEventClearOptions,\n  UserEventClickOptions,\n  UserEventDragAndDropOptions,\n  UserEventFillOptions,\n  UserEventHoverOptions,\n  UserEventSelectOptions,\n  UserEventWheelOptions,\n} from 'vitest/browser'\nimport {\n  convertElementToCssSelector,\n  ensureAwaited,\n  getByAltTextSelector,\n  getByLabelSelector,\n  getByPlaceholderSelector,\n  getByRoleSelector,\n  getByTestIdSelector,\n  getByTextSelector,\n  getByTitleSelector,\n  getIframeScale,\n  Locator,\n  selectorEngine,\n  triggerCommandWithTrace,\n} from '@vitest/browser/locators'\nimport { page, server, utils } from 'vitest/browser'\nimport { __INTERNAL } from 'vitest/internal/browser'\n\nclass WebdriverIOLocator extends Locator {\n  constructor(protected _pwSelector: string, protected _container?: Element) {\n    super()\n  }\n\n  // This exists to avoid calling `this.elements` in `this.selector`'s getter in interactive actions\n  private withElement(element: Element, error: Error | undefined) {\n    const pwSelector = selectorEngine.generateSelectorSimple(element)\n    const cssSelector = convertElementToCssSelector(element)\n    return new ElementWebdriverIOLocator(cssSelector, error, pwSelector, element)\n  }\n\n  override get selector(): string {\n    const selectors = this.elements().map(element => convertElementToCssSelector(element))\n    if (!selectors.length) {\n      throw utils.getElementError(this._pwSelector, this._container || document.body)\n    }\n    let hasShadowRoot = false\n    const newSelectors = selectors.map((selector) => {\n      if (selector.startsWith('>>>')) {\n        hasShadowRoot = true\n        return selector.slice(3)\n      }\n      return selector\n    })\n    return (hasShadowRoot ? '>>>' : '') + newSelectors.join(', ')\n  }\n\n  public override click(options?: UserEventClickOptions): Promise<void> {\n    return ensureAwaited(async (error) => {\n      const element = await this.findElement(options)\n      return this.withElement(element, error).click(processClickOptions(options))\n    })\n  }\n\n  public override dblClick(options?: UserEventClickOptions): Promise<void> {\n    return ensureAwaited(async (error) => {\n      const element = await this.findElement(options)\n      return this.withElement(element, error).dblClick(processClickOptions(options))\n    })\n  }\n\n  public override tripleClick(options?: UserEventClickOptions): Promise<void> {\n    return ensureAwaited(async (error) => {\n      const element = await this.findElement(options)\n      return this.withElement(element, error).tripleClick(processClickOptions(options))\n    })\n  }\n\n  public selectOptions(\n    value: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],\n    options?: UserEventSelectOptions,\n  ): Promise<void> {\n    return ensureAwaited(async (error) => {\n      const element = await this.findElement(options)\n      const values = getWebdriverioSelectOptions(element, value)\n      return triggerCommandWithTrace<void>({\n        name: '__vitest_selectOptions',\n        arguments: [convertElementToCssSelector(element), values, options],\n        errorSource: error,\n      })\n    })\n  }\n\n  public override hover(options?: UserEventHoverOptions): Promise<void> {\n    return ensureAwaited(async (error) => {\n      const element = await this.findElement(options)\n      return this.withElement(element, error).hover(processHoverOptions(options))\n    })\n  }\n\n  public override dropTo(target: Locator, options?: UserEventDragAndDropOptions): Promise<void> {\n    // playwright doesn't enforce a single element, it selects the first one,\n    // so we just follow the behavior\n    return super.dropTo(target, processDragAndDropOptions(options))\n  }\n\n  public override wheel(options: UserEventWheelOptions): Promise<void> {\n    return ensureAwaited(async (error) => {\n      const element = await this.findElement(options)\n      return this.withElement(element, error).wheel(options)\n    })\n  }\n\n  public override clear(options?: UserEventClearOptions): Promise<void> {\n    return ensureAwaited(async (error) => {\n      const element = await this.findElement(options)\n      return this.withElement(element, error).clear(options)\n    })\n  }\n\n  public override fill(text: string, options?: UserEventFillOptions): Promise<void> {\n    return ensureAwaited(async (error) => {\n      const element = await this.findElement(options)\n      return this.withElement(element, error).fill(text, options)\n    })\n  }\n\n  public override screenshot(options?: LocatorScreenshotOptions): Promise<any> {\n    return ensureAwaited(async (error) => {\n      const element = await this.findElement(options)\n      return this.withElement(element, error).screenshot(options)\n    })\n  }\n\n  // playwright doesn't enforce a single element in upload\n  // public override async upload(): Promise<void>\n\n  protected locator(selector: string) {\n    return new WebdriverIOLocator(`${this._pwSelector} >> ${selector}`, this._container)\n  }\n\n  protected elementLocator(element: Element) {\n    return new WebdriverIOLocator(selectorEngine.generateSelectorSimple(element), element)\n  }\n}\n\nconst kElementLocator = Symbol.for('$$vitest:locator-resolved')\n\nclass ElementWebdriverIOLocator extends Locator {\n  public [kElementLocator] = true\n\n  constructor(\n    private _cssSelector: string,\n    protected _errorSource: Error | undefined,\n    protected _pwSelector: string,\n    protected _container: Element,\n  ) {\n    super()\n  }\n\n  override get selector() {\n    return this._cssSelector\n  }\n\n  protected locator(_selector: string): Locator {\n    throw new Error(`should not be called`)\n  }\n\n  protected elementLocator(_element: Element): Locator {\n    throw new Error(`should not be called`)\n  }\n}\n\npage.extend({\n  getByLabelText(text, options) {\n    return new WebdriverIOLocator(getByLabelSelector(text, options))\n  },\n  getByRole(role, options) {\n    return new WebdriverIOLocator(getByRoleSelector(role, options))\n  },\n  getByTestId(testId) {\n    return new WebdriverIOLocator(getByTestIdSelector(server.config.browser.locators.testIdAttribute, testId))\n  },\n  getByAltText(text, options) {\n    return new WebdriverIOLocator(getByAltTextSelector(text, options))\n  },\n  getByPlaceholder(text, options) {\n    return new WebdriverIOLocator(getByPlaceholderSelector(text, options))\n  },\n  getByText(text, options) {\n    return new WebdriverIOLocator(getByTextSelector(text, options))\n  },\n  getByTitle(title, options) {\n    return new WebdriverIOLocator(getByTitleSelector(title, options))\n  },\n\n  elementLocator(element: Element) {\n    return new WebdriverIOLocator(selectorEngine.generateSelectorSimple(element))\n  },\n})\n\n__INTERNAL._createLocator = selector => new WebdriverIOLocator(selector)\n\nfunction getWebdriverioSelectOptions(element: Element, value: string | string[] | HTMLElement[] | HTMLElement | Locator | Locator[]) {\n  const options = [...element.querySelectorAll('option')] as HTMLOptionElement[]\n\n  const arrayValues = Array.isArray(value) ? value : [value]\n\n  if (!arrayValues.length) {\n    return []\n  }\n\n  if (arrayValues.length > 1) {\n    throw new Error('Provider \"webdriverio\" doesn\\'t support selecting multiple values at once')\n  }\n\n  const optionValue = arrayValues[0]\n\n  if (typeof optionValue !== 'string') {\n    const element = ('element' in optionValue ? optionValue.element() : optionValue) as HTMLOptionElement\n    const index = options.indexOf(element)\n    if (index === -1) {\n      throw new Error(`The element ${selectorEngine.previewNode(element)} was not found in the \"select\" options.`)\n    }\n\n    return [{ index }]\n  }\n\n  const valueIndex = options.findIndex(option => option.value === optionValue)\n  if (valueIndex !== -1) {\n    return [{ index: valueIndex }]\n  }\n\n  const labelIndex = options.findIndex(option =>\n    option.textContent?.trim() === optionValue || option.ariaLabel === optionValue,\n  )\n\n  if (labelIndex === -1) {\n    throw new Error(`The option \"${optionValue}\" was not found in the \"select\" options.`)\n  }\n\n  return [{ index: labelIndex }]\n}\n\nfunction processClickOptions(options?: UserEventClickOptions) {\n  // only ui scales the iframe, so we need to adjust the position\n  if (!options || !server.config.browser.ui) {\n    return options\n  }\n  if (options.x != null || options.y != null) {\n    const cache = {}\n    if (options.x != null) {\n      options.x = scaleCoordinate(options.x, cache)\n    }\n    if (options.y != null) {\n      options.y = scaleCoordinate(options.y, cache)\n    }\n  }\n  return options\n}\n\nfunction processHoverOptions(options?: UserEventHoverOptions) {\n  // only ui scales the iframe, so we need to adjust the position\n  if (!options || !server.config.browser.ui) {\n    return options\n  }\n  const cache = {}\n  if (options.xOffset != null) {\n    options.xOffset = scaleCoordinate(options.xOffset, cache)\n  }\n  if (options.yOffset != null) {\n    options.yOffset = scaleCoordinate(options.yOffset, cache)\n  }\n  return options\n}\n\nfunction processDragAndDropOptions(options?: UserEventDragAndDropOptions) {\n  // only ui scales the iframe, so we need to adjust the position\n  if (!options || !server.config.browser.ui) {\n    return options\n  }\n  const cache = {}\n  if (options.sourceX != null) {\n    options.sourceX = scaleCoordinate(options.sourceX, cache)\n  }\n  if (options.sourceY != null) {\n    options.sourceY = scaleCoordinate(options.sourceY, cache)\n  }\n  if (options.targetX != null) {\n    options.targetX = scaleCoordinate(options.targetX, cache)\n  }\n  if (options.targetY != null) {\n    options.targetY = scaleCoordinate(options.targetY, cache)\n  }\n  return options\n}\n\nfunction scaleCoordinate(coordinate: number, cache: any) {\n  return Math.round(coordinate * getCachedScale(cache))\n}\n\nfunction getCachedScale(cache: { scale: number | undefined }) {\n  return cache.scale ??= getIframeScale()\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/src/webdriverio.ts",
    "content": "import type { CustomComparatorsRegistry } from '@vitest/browser'\nimport type { Capabilities } from '@wdio/types'\nimport type {\n  ScreenshotComparatorRegistry,\n  ScreenshotMatcherOptions,\n  SelectorOptions,\n} from 'vitest/browser'\nimport type {\n  BrowserCommand,\n  BrowserProvider,\n  BrowserProviderOption,\n  CDPSession,\n  TestProject,\n} from 'vitest/node'\nimport type { ClickOptions, DragAndDropOptions, MoveToOptions, remote } from 'webdriverio'\nimport { defineBrowserProvider } from '@vitest/browser'\n\nimport { resolve } from 'pathe'\nimport { createDebugger } from 'vitest/node'\nimport commands from './commands'\nimport { distRoot } from './constants'\n\nconst debug = createDebugger('vitest:browser:wdio')\n\nconst webdriverBrowsers = ['firefox', 'chrome', 'edge', 'safari'] as const\ntype WebdriverBrowser = (typeof webdriverBrowsers)[number]\n\nexport interface WebdriverProviderOptions extends Partial<\n  Parameters<typeof remote>[0]\n> {}\n\nexport function webdriverio(options: WebdriverProviderOptions = {}): BrowserProviderOption<WebdriverProviderOptions> {\n  return defineBrowserProvider({\n    name: 'webdriverio',\n    supportedBrowser: webdriverBrowsers,\n    options,\n    providerFactory(project) {\n      return new WebdriverBrowserProvider(project, options)\n    },\n  })\n}\n\nexport class WebdriverBrowserProvider implements BrowserProvider {\n  public name = 'webdriverio' as const\n  public supportsParallelism: boolean = false\n\n  public browser: WebdriverIO.Browser | null = null\n\n  private browserName!: WebdriverBrowser\n  private project!: TestProject\n\n  private options?: WebdriverProviderOptions\n\n  private closing = false\n  private iframeSwitched = false\n  private topLevelContext: string | undefined\n\n  public initScripts: string[] = [\n    resolve(distRoot, 'locators.js'),\n  ]\n\n  getSupportedBrowsers(): readonly string[] {\n    return webdriverBrowsers\n  }\n\n  constructor(\n    project: TestProject,\n    options: WebdriverProviderOptions,\n  ) {\n    // increase shutdown timeout because WDIO takes some extra time to kill the driver\n    if (!project.vitest.state._data.timeoutIncreased) {\n      project.vitest.state._data.timeoutIncreased = true\n      project.vitest.config.teardownTimeout += 10_000\n    }\n\n    this.closing = false\n    this.project = project\n    this.browserName = project.config.browser.name as WebdriverBrowser\n    this.options = options\n\n    for (const [name, command] of Object.entries(commands)) {\n      project.browser!.registerCommand(name as any, command as BrowserCommand)\n    }\n  }\n\n  isIframeSwitched(): boolean {\n    return this.iframeSwitched\n  }\n\n  async switchToTestFrame(): Promise<void> {\n    const browser = this.browser!\n    // support wdio@9\n    if (browser.switchFrame) {\n      await browser.switchFrame(browser.$('iframe[data-vitest]'))\n    }\n    else {\n      const iframe = await browser.findElement(\n        'css selector',\n        'iframe[data-vitest]',\n      )\n      await browser.switchToFrame(iframe)\n    }\n    this.iframeSwitched = true\n  }\n\n  async switchToMainFrame(): Promise<void> {\n    const page = this.browser!\n    if (page.switchFrame) {\n      await page.switchFrame(null)\n    }\n    else {\n      await page.switchToParentFrame()\n    }\n    this.iframeSwitched = false\n  }\n\n  async setViewport(options: { width: number; height: number }): Promise<void> {\n    if (this.topLevelContext == null || !this.browser) {\n      throw new Error(`The browser has no open pages.`)\n    }\n    if (this.browser.isBidi) {\n      await this.browser.send({\n        method: 'browsingContext.setViewport',\n        params: {\n          context: this.topLevelContext,\n          devicePixelRatio: 1,\n          viewport: options,\n        },\n      })\n    }\n    else {\n      await this.browser.setWindowSize(options.width, options.height)\n    }\n  }\n\n  getCommandsContext(): {\n    browser: WebdriverIO.Browser | null\n  } {\n    return {\n      browser: this.browser,\n    }\n  }\n\n  async openBrowser(): Promise<WebdriverIO.Browser> {\n    await this._throwIfClosing('opening the browser')\n\n    if (this.browser) {\n      debug?.('[%s] the browser is already opened, reusing it', this.browserName)\n      return this.browser\n    }\n\n    const options = this.project.config.browser\n\n    if (this.browserName === 'safari') {\n      if (options.headless) {\n        throw new Error(\n          'You\\'ve enabled headless mode for Safari but it doesn\\'t currently support it.',\n        )\n      }\n    }\n\n    const { remote } = await import('webdriverio')\n\n    const remoteOptions: Capabilities.WebdriverIOConfig = {\n      logLevel: 'silent',\n      ...this.options,\n      capabilities: this.buildCapabilities(),\n    }\n\n    debug?.('[%s] opening the browser with options: %O', this.browserName, remoteOptions)\n    // TODO: close everything, if browser is closed from the outside\n    this.browser = await remote(remoteOptions)\n    await this._throwIfClosing()\n\n    return this.browser\n  }\n\n  private buildCapabilities() {\n    const capabilities: Capabilities.WebdriverIOConfig['capabilities'] = {\n      ...this.options?.capabilities,\n      browserName: this.browserName,\n    }\n\n    const headlessMap = {\n      chrome: ['goog:chromeOptions', ['headless', 'disable-gpu']],\n      firefox: ['moz:firefoxOptions', ['-headless']],\n      edge: ['ms:edgeOptions', ['--headless']],\n    } as const\n\n    const options = this.project.config.browser\n    const browser = this.browserName\n    if (browser !== 'safari' && options.headless) {\n      const [key, args] = headlessMap[browser]\n      const currentValues = (this.options?.capabilities as any)?.[key] || {}\n      const newArgs = [...(currentValues.args || []), ...args]\n      capabilities[key] = { ...currentValues, args: newArgs as any }\n    }\n\n    // start Vitest UI maximized only on supported browsers\n    if (options.ui && (browser === 'chrome' || browser === 'edge')) {\n      const key = browser === 'chrome'\n        ? 'goog:chromeOptions'\n        : 'ms:edgeOptions'\n      const args = capabilities[key]?.args || []\n      if (!args.includes('--start-maximized') && !args.includes('--start-fullscreen')) {\n        args.push('--start-maximized')\n      }\n      capabilities[key] ??= {}\n      capabilities[key]!.args = args\n    }\n\n    const inspector = this.project.vitest.config.inspector\n    if (inspector.enabled && (browser === 'chrome' || browser === 'edge')) {\n      const key = browser === 'chrome'\n        ? 'goog:chromeOptions'\n        : 'ms:edgeOptions'\n      const args = capabilities[key]?.args || []\n\n      // NodeJS equivalent defaults: https://nodejs.org/en/learn/getting-started/debugging#enable-inspector\n      const port = inspector.port || 9229\n      const host = inspector.host || '127.0.0.1'\n\n      args.push(`--remote-debugging-port=${port}`)\n\n      if (host !== 'localhost' && host !== '127.0.0.1' && host !== '::1') {\n        this.project.vitest.logger.warn(`Custom inspector host \"${host}\" will be ignored. Chrome only allows remote debugging on localhost.`)\n      }\n      this.project.vitest.logger.log(`Debugger listening on ws://127.0.0.1:${port}`)\n\n      capabilities[key] ??= {}\n      capabilities[key]!.args = args\n    }\n\n    return capabilities\n  }\n\n  async openPage(sessionId: string, url: string): Promise<void> {\n    await this._throwIfClosing('creating the browser')\n    debug?.('[%s][%s] creating the browser page for %s', sessionId, this.browserName, url)\n    const browserInstance = await this.openBrowser()\n    debug?.('[%s][%s] browser page is created, opening %s', sessionId, this.browserName, url)\n    await browserInstance.url(url)\n    this.topLevelContext = await browserInstance.getWindowHandle()\n    await this._throwIfClosing('opening the url')\n  }\n\n  private async _throwIfClosing(action?: string) {\n    if (this.closing) {\n      debug?.(`[%s] provider was closed, cannot perform the action${action ? ` ${action}` : ''}`, this.browserName)\n      await (this.browser?.sessionId ? this.browser?.deleteSession?.() : null)\n      throw new Error(`[vitest] The provider was closed.`)\n    }\n  }\n\n  async close(): Promise<void> {\n    debug?.('[%s] closing provider', this.browserName)\n    this.closing = true\n    const browser = this.browser\n    const sessionId = browser?.sessionId\n    if (!browser || !sessionId) {\n      return\n    }\n\n    // https://github.com/webdriverio/webdriverio/blob/ab1a2e82b13a9c7d0e275ae87e7357e1b047d8d3/packages/wdio-runner/src/index.ts#L486\n    await browser.deleteSession()\n    browser.sessionId = undefined as unknown as string\n    this.browser = null\n  }\n\n  async getCDPSession(_sessionId: string): Promise<CDPSession> {\n    return {\n      send: (method, params) => {\n        if (!this.browser) {\n          throw new Error(`The environment was torn down.`)\n        }\n        return this.browser.sendCommandAndGetResult(method, params ?? {}).catch((error) => {\n          return Promise.reject(new Error(`Failed to execute \"${method}\" command.`, { cause: error }))\n        })\n      },\n      on: () => {\n        throw new Error(`webdriverio provider doesn't support cdp.on()`)\n      },\n      once: () => {\n        throw new Error(`webdriverio provider doesn't support cdp.once()`)\n      },\n      off: () => {\n        throw new Error(`webdriverio provider doesn't support cdp.off()`)\n      },\n    }\n  }\n}\n\ndeclare module 'vitest/browser' {\n  export interface UserEventClickOptions extends Partial<ClickOptions>, SelectorOptions {}\n  export interface UserEventHoverOptions extends MoveToOptions, SelectorOptions {}\n  export interface UserEventDragAndDropOptions extends DragAndDropOptions {\n    sourceX?: number\n    sourceY?: number\n    targetX?: number\n    targetY?: number\n  }\n  export interface UserEventFillOptions extends SelectorOptions {}\n  export interface UserEventSelectOptions extends SelectorOptions {}\n  export interface UserEventClearOptions extends SelectorOptions {}\n  export interface UserEventDoubleClickOptions extends SelectorOptions {}\n  export interface UserEventTripleClickOptions extends SelectorOptions {}\n  export interface UserEventWheelBaseOptions extends SelectorOptions {}\n  export interface LocatorScreenshotOptions extends SelectorOptions {}\n}\n\ninterface WebdriverCDPSession {\n  send: (method: string, params?: Record<string, unknown>) => Promise<unknown>\n  on: (event: string, listener: (...args: unknown[]) => void) => void\n  once: (event: string, listener: (...args: unknown[]) => void) => void\n  off: (event: string, listener: (...args: unknown[]) => void) => void\n}\n\ndeclare module 'vitest/node' {\n  export interface BrowserCommandContext {\n    browser: WebdriverIO.Browser\n  }\n\n  export interface _BrowserNames {\n    webdriverio: WebdriverBrowser\n  }\n\n  export interface ToMatchScreenshotOptions\n    extends Omit<\n      ScreenshotMatcherOptions,\n      'comparatorName' | 'comparatorOptions'\n    >, CustomComparatorsRegistry {}\n\n  export interface ToMatchScreenshotComparators\n    extends ScreenshotComparatorRegistry {}\n\n  export interface CDPSession extends WebdriverCDPSession {}\n}\n"
  },
  {
    "path": "packages/browser-webdriverio/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"types\": [\"node\", \"vite/client\"],\n    \"isolatedDeclarations\": true\n  },\n  \"exclude\": [\n    \"dist\",\n    \"node_modules\",\n    \"**/vite.config.ts\",\n    \"src/client/**/*.ts\"\n  ]\n}\n"
  },
  {
    "path": "packages/coverage-istanbul/README.md",
    "content": "# @vitest/coverage-istanbul\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/coverage-istanbul?color=a1b858&label=)](https://npmx.dev/package/@vitest/coverage-istanbul)\n\nVitest coverage provider that instruments code coverage via [istanbul](https://istanbul.js.org/).\n\n## Installation\n\nAfter installing the package, specify `istanbul` in the `coverage.provider` field of your Vitest configuration:\n\n```ts\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      provider: 'istanbul',\n    },\n  },\n})\n```\n\nThen run Vitest with coverage:\n\n```sh\nnpx vitest --coverage\n```\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/coverage-istanbul) | [Documentation](https://vitest.dev/guide/coverage)\n"
  },
  {
    "path": "packages/coverage-istanbul/package.json",
    "content": "{\n  \"name\": \"@vitest/coverage-istanbul\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Istanbul coverage provider for Vitest\",\n  \"author\": \"Anthony Fu <anthonyfu117@hotmail.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/guide/coverage\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/coverage-istanbul\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vite\",\n    \"vitest\",\n    \"test\",\n    \"coverage\",\n    \"istanbul\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch --watch.include 'src/**'\"\n  },\n  \"peerDependencies\": {\n    \"vitest\": \"workspace:*\"\n  },\n  \"dependencies\": {\n    \"@babel/core\": \"^7.29.0\",\n    \"@istanbuljs/schema\": \"^0.1.3\",\n    \"@jridgewell/gen-mapping\": \"^0.3.13\",\n    \"@jridgewell/trace-mapping\": \"catalog:\",\n    \"istanbul-lib-coverage\": \"catalog:\",\n    \"istanbul-lib-report\": \"catalog:\",\n    \"istanbul-reports\": \"catalog:\",\n    \"magicast\": \"catalog:\",\n    \"obug\": \"catalog:\",\n    \"tinyrainbow\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@types/istanbul-lib-coverage\": \"catalog:\",\n    \"@types/istanbul-lib-instrument\": \"^1.7.8\",\n    \"@types/istanbul-lib-report\": \"catalog:\",\n    \"@types/istanbul-lib-source-maps\": \"catalog:\",\n    \"@types/istanbul-reports\": \"catalog:\",\n    \"istanbul-lib-instrument\": \"^6.0.3\",\n    \"istanbul-lib-source-maps\": \"catalog:\",\n    \"pathe\": \"catalog:\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/coverage-istanbul/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport nodeResolve from '@rollup/plugin-node-resolve'\nimport { join } from 'pathe'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst entries = {\n  index: 'src/index.ts',\n  provider: 'src/provider.ts',\n}\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^@?vitest(\\/|$)/,\n\n  // We bundle istanbul-lib-instrument but don't want to bundle its babel dependency\n  '@babel/core',\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  nodeResolve(),\n  json(),\n  commonjs({\n    // \"istanbul-lib-source-maps > @jridgewell/trace-mapping\" is not CJS\n    // \"istanbul-lib-instrument > @jridgewell/trace-mapping\" is not CJS\n    esmExternals: ['@jridgewell/trace-mapping'],\n  }),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nexport default defineConfig(() => [\n  {\n    input: entries,\n    output: {\n      dir: 'dist',\n      format: 'esm',\n    },\n    external,\n    plugins,\n  },\n  {\n    input: dtsUtils.dtsInput(entries),\n    output: {\n      dir: join(process.cwd(), 'dist'),\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n    onLog(level, log, handler) {\n      // we don't control the source of \"istanbul-lib-coverage\"\n      if (\n        level === 'warn'\n        && log.exporter === 'istanbul-lib-coverage'\n        && log.message.includes('\"Range\" is imported')\n      ) {\n        return\n      }\n      handler(level, log)\n    },\n  },\n])\n"
  },
  {
    "path": "packages/coverage-istanbul/src/constants.ts",
    "content": "export const COVERAGE_STORE_KEY: string = '__VITEST_COVERAGE__'\n"
  },
  {
    "path": "packages/coverage-istanbul/src/index.ts",
    "content": "import type { CoverageMapData } from 'istanbul-lib-coverage'\nimport type { CoverageProviderModule } from 'vitest/node'\nimport type { IstanbulCoverageProvider } from './provider'\nimport { COVERAGE_STORE_KEY } from './constants'\n\nconst mod: CoverageProviderModule = {\n  takeCoverage() {\n    // @ts-expect-error -- untyped global\n    return globalThis[COVERAGE_STORE_KEY]\n  },\n\n  // Reset coverage map to prevent duplicate results if this is called twice in row\n  startCoverage() {\n    // @ts-expect-error -- untyped global\n    const coverageMap = globalThis[COVERAGE_STORE_KEY] as CoverageMapData\n\n    // When isolated, there are no previous results\n    if (!coverageMap) {\n      return\n    }\n\n    for (const filename in coverageMap) {\n      const branches = coverageMap[filename].b\n\n      for (const key in branches) {\n        branches[key] = branches[key].map(() => 0)\n      }\n\n      for (const metric of ['f', 's'] as const) {\n        const entry = coverageMap[filename][metric]\n\n        for (const key in entry) {\n          entry[key] = 0\n        }\n      }\n    }\n  },\n\n  async getProvider(): Promise<IstanbulCoverageProvider> {\n    // to not bundle the provider\n    const providerPath = './provider.js'\n    const { IstanbulCoverageProvider } = (await import(\n      /* @vite-ignore */\n      providerPath,\n    )) as typeof import('./provider')\n\n    return new IstanbulCoverageProvider()\n  },\n}\nexport default mod\n"
  },
  {
    "path": "packages/coverage-istanbul/src/provider.ts",
    "content": "import type { CoverageMap } from 'istanbul-lib-coverage'\nimport type { Instrumenter } from 'istanbul-lib-instrument'\nimport type { ProxifiedModule } from 'magicast'\nimport type { CoverageProvider, ReportContext, ResolvedCoverageOptions, Vite, Vitest } from 'vitest/node'\nimport { existsSync, promises as fs } from 'node:fs'\n// @ts-expect-error missing types\nimport { defaults as istanbulDefaults } from '@istanbuljs/schema'\nimport { addMapping, GenMapping, toEncodedMap } from '@jridgewell/gen-mapping'\nimport { eachMapping, TraceMap } from '@jridgewell/trace-mapping'\nimport libCoverage from 'istanbul-lib-coverage'\nimport { createInstrumenter } from 'istanbul-lib-instrument'\nimport libReport from 'istanbul-lib-report'\nimport libSourceMaps from 'istanbul-lib-source-maps'\nimport reports from 'istanbul-reports'\nimport { parseModule } from 'magicast'\nimport { createDebug } from 'obug'\nimport c from 'tinyrainbow'\nimport { BaseCoverageProvider, isCSSRequest } from 'vitest/node'\nimport { version } from '../package.json' with { type: 'json' }\nimport { COVERAGE_STORE_KEY } from './constants'\n\nconst debug = createDebug('vitest:coverage')\n\nexport class IstanbulCoverageProvider extends BaseCoverageProvider<ResolvedCoverageOptions<'istanbul'>> implements CoverageProvider {\n  name = 'istanbul' as const\n  version: string = version\n  instrumenter!: Instrumenter\n\n  private transformedModuleIds = new Set<string>()\n\n  initialize(ctx: Vitest): void {\n    this._initialize(ctx)\n\n    this.instrumenter = createInstrumenter({\n      produceSourceMap: true,\n      autoWrap: false,\n      esModules: true,\n      compact: false,\n      coverageVariable: COVERAGE_STORE_KEY,\n      coverageGlobalScope: 'globalThis',\n      coverageGlobalScopeFunc: false,\n      ignoreClassMethods: this.options.ignoreClassMethods,\n      parserPlugins: [\n        ...istanbulDefaults.instrumenter.parserPlugins,\n        ['importAttributes', { deprecatedAssertSyntax: true }],\n      ],\n      generatorOpts: {\n        // @ts-expect-error missing type\n        importAttributesKeyword: 'with',\n      },\n\n      // Custom option from the patched istanbul-lib-instrument: https://github.com/istanbuljs/istanbuljs/pull/835\n      ignoreLines: true,\n    })\n  }\n\n  requiresTransform(id: string): boolean {\n    // Istanbul/babel cannot instrument CSS - e.g. Vue imports end up here.\n    // File extension itself is .vue, but it contains CSS.\n    // e.g. \"Example.vue?vue&type=style&index=0&scoped=f7f04e08&lang.css\"\n    if (isCSSRequest(id)) {\n      return false\n    }\n\n    if (!this.isIncluded(removeQueryParameters(id))) {\n      return false\n    }\n\n    return true\n  }\n\n  onFileTransform(sourceCode: string, id: string, pluginCtx: Vite.Rollup.TransformPluginContext): { code: string; map: any } | undefined {\n    if (!this.requiresTransform(id)) {\n      return\n    }\n\n    const sourceMap = pluginCtx.getCombinedSourcemap()\n    sourceMap.sources = sourceMap.sources.map(removeQueryParameters)\n\n    sourceCode = sourceCode\n      // Exclude SWC's decorators that are left in source maps\n      .replaceAll('_ts_decorate', '/* istanbul ignore next */_ts_decorate')\n\n      // Exclude in-source test's test cases\n      .replaceAll(/(if +\\(import\\.meta\\.vitest\\))/g, '/* istanbul ignore next */ $1')\n\n    const code = this.instrumenter.instrumentSync(\n      sourceCode,\n      id,\n      sourceMap as any,\n    )\n\n    if (!id.includes('vitest-uncovered-coverage=true')) {\n      const transformMap = new GenMapping(sourceMap)\n\n      eachMapping(new TraceMap(sourceMap as any), (mapping) => {\n        addMapping(transformMap, {\n          generated: { line: mapping.generatedLine, column: mapping.generatedColumn },\n          original: { line: mapping.generatedLine, column: mapping.generatedColumn },\n          content: sourceCode,\n          name: mapping.name || '',\n          source: mapping.source || '',\n        })\n      })\n\n      const encodedMap = toEncodedMap(transformMap)\n      delete encodedMap.file\n      delete encodedMap.ignoreList\n      delete encodedMap.sourceRoot\n\n      this.instrumenter.instrumentSync(\n        sourceCode,\n        id,\n        encodedMap as any,\n      )\n    }\n\n    const map = this.instrumenter.lastSourceMap() as any\n    this.transformedModuleIds.add(id)\n\n    return { code, map }\n  }\n\n  createCoverageMap(): libCoverage.CoverageMap {\n    return libCoverage.createCoverageMap({})\n  }\n\n  async generateCoverage({ allTestsRun }: ReportContext): Promise<CoverageMap> {\n    const start = debug.enabled ? performance.now() : 0\n\n    const coverageMap = this.createCoverageMap()\n    let coverageMapByEnvironment = this.createCoverageMap()\n\n    await this.readCoverageFiles<CoverageMap>({\n      onFileRead(coverage) {\n        coverageMapByEnvironment.merge(coverage)\n      },\n      onFinished: async () => {\n        // Source maps can change based on projectName and transform mode.\n        // Coverage transform re-uses source maps so we need to separate transforms from each other.\n        const transformedCoverage = await transformCoverage(coverageMapByEnvironment)\n        coverageMap.merge(transformedCoverage)\n\n        coverageMapByEnvironment = this.createCoverageMap()\n      },\n      onDebug: debug,\n    })\n\n    // Include untested files when all tests were run (not a single file re-run)\n    // or if previous results are preserved by \"cleanOnRerun: false\"\n    if (this.options.include != null && (allTestsRun || !this.options.cleanOnRerun)) {\n      const coveredFiles = coverageMap.files()\n      const uncoveredCoverage = await this.getCoverageMapForUncoveredFiles(coveredFiles)\n\n      coverageMap.merge(await transformCoverage(uncoveredCoverage))\n    }\n\n    coverageMap.filter((filename) => {\n      const exists = existsSync(filename)\n\n      if (this.options.excludeAfterRemap) {\n        return exists && this.isIncluded(filename)\n      }\n\n      return exists\n    })\n\n    if (debug.enabled) {\n      debug('Generate coverage total time %d ms', (performance.now() - start!).toFixed())\n    }\n\n    return coverageMap\n  }\n\n  async generateReports(coverageMap: CoverageMap, allTestsRun: boolean | undefined): Promise<void> {\n    const context = libReport.createContext({\n      dir: this.options.reportsDirectory,\n      coverageMap,\n      watermarks: this.options.watermarks,\n    })\n\n    if (this.hasTerminalReporter(this.options.reporter)) {\n      this.ctx.logger.log(\n        c.blue(' % ') + c.dim('Coverage report from ') + c.yellow(this.name),\n      )\n    }\n\n    for (const reporter of this.options.reporter) {\n      // Type assertion required for custom reporters\n      reports\n        .create(reporter[0] as Parameters<typeof reports.create>[0], {\n          skipFull: this.options.skipFull,\n          projectRoot: this.ctx.config.root,\n          ...reporter[1],\n        })\n        .execute(context)\n    }\n\n    if (this.options.thresholds) {\n      await this.reportThresholds(coverageMap, allTestsRun)\n    }\n  }\n\n  async parseConfigModule(configFilePath: string): Promise<ProxifiedModule<any>> {\n    const contents = await fs.readFile(configFilePath, 'utf8')\n\n    return parseModule(`${contents}${this.autoUpdateMarker}`)\n  }\n\n  private async getCoverageMapForUncoveredFiles(coveredFiles: string[]) {\n    const uncoveredFiles = await this.getUntestedFiles(coveredFiles)\n\n    const cacheKey = new Date().getTime()\n    const coverageMap = this.createCoverageMap()\n\n    const transform = this.createUncoveredFileTransformer(this.ctx)\n\n    // Note that these cannot be run parallel as synchronous instrumenter.lastFileCoverage\n    // returns the coverage of the last transformed file\n    for (const [index, filename] of uncoveredFiles.entries()) {\n      let timeout: ReturnType<typeof setTimeout> | undefined\n      let start: number | undefined\n\n      if (debug.enabled) {\n        start = performance.now()\n        timeout = setTimeout(() => debug(c.bgRed(`File \"${filename}\" is taking longer than 3s`)), 3_000)\n\n        debug('Uncovered file %d/%d', index, uncoveredFiles.length)\n      }\n\n      // Make sure file is not served from cache so that instrumenter loads up requested file coverage\n      await transform(`${filename}?cache=${cacheKey}&vitest-uncovered-coverage=true`)\n      const lastCoverage = this.instrumenter.lastFileCoverage()\n      coverageMap.addFileCoverage(lastCoverage)\n\n      if (debug.enabled) {\n        clearTimeout(timeout)\n\n        const diff = performance.now() - start!\n        const color = diff > 500 ? c.bgRed : c.bgGreen\n        debug(`${color(` ${diff.toFixed()} ms `)} ${filename}`)\n      }\n    }\n\n    return coverageMap\n  }\n\n  // the coverage can be enabled after the tests are run\n  // this means the coverage will not be injected because the modules are cached,\n  // so we are invalidating all modules that don't have the istanbul coverage injected\n  onEnabled(): void {\n    const environments = this.ctx.projects.flatMap(project => [\n      ...Object.values(project.vite.environments),\n      ...Object.values(project.browser?.vite.environments || {}),\n    ])\n\n    const seen = new Set<Vite.EnvironmentModuleNode>()\n    environments.forEach((environment) => {\n      environment.moduleGraph.idToModuleMap.forEach((node) => {\n        this.invalidateTree(node, environment.moduleGraph, seen)\n      })\n    })\n  }\n\n  private invalidateTree(node: Vite.EnvironmentModuleNode, moduleGraph: Vite.EnvironmentModuleGraph, seen: Set<Vite.EnvironmentModuleNode>) {\n    if (seen.has(node)) {\n      return\n    }\n    if (node.id && !this.transformedModuleIds.has(node.id)) {\n      moduleGraph.invalidateModule(node, seen)\n    }\n    seen.add(node) // to avoid infinite loops in circular dependencies\n    node.importedModules.forEach((mod) => {\n      this.invalidateTree(mod, moduleGraph, seen)\n    })\n  }\n}\n\nasync function transformCoverage(coverageMap: CoverageMap) {\n  const sourceMapStore = libSourceMaps.createSourceMapStore()\n  return await sourceMapStore.transformCoverage(coverageMap)\n}\n\n/**\n * Remove possible query parameters from filenames\n * - From `/src/components/Header.component.ts?vue&type=script&src=true&lang.ts`\n * - To `/src/components/Header.component.ts`\n */\nfunction removeQueryParameters(filename: string) {\n  return filename.split('?')[0]\n}\n"
  },
  {
    "path": "packages/coverage-istanbul/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"moduleResolution\": \"Bundler\",\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"./dist\"]\n}\n"
  },
  {
    "path": "packages/coverage-v8/README.md",
    "content": "# @vitest/coverage-v8\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/coverage-v8?color=a1b858&label=)](https://npmx.dev/package/@vitest/coverage-v8)\n\nVitest coverage provider that supports native code coverage via [v8](https://v8.dev/blog/javascript-code-coverage).\n\n## Installation\n\nAfter installing the package, specify `v8` in the `coverage.provider` field of your Vitest configuration (or leave it empty as it is the default provider):\n\n```ts\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      provider: 'v8',\n    },\n  },\n})\n```\n\nThen run Vitest with coverage:\n\n```sh\nnpx vitest --coverage\n```\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/coverage-v8) | [Documentation](https://vitest.dev/guide/coverage)\n"
  },
  {
    "path": "packages/coverage-v8/package.json",
    "content": "{\n  \"name\": \"@vitest/coverage-v8\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"V8 coverage provider for Vitest\",\n  \"author\": \"Anthony Fu <anthonyfu117@hotmail.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/guide/coverage\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/coverage-v8\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vite\",\n    \"vitest\",\n    \"test\",\n    \"coverage\",\n    \"v8\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./browser\": {\n      \"types\": \"./dist/browser.d.ts\",\n      \"default\": \"./dist/browser.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch --watch.include 'src/**'\"\n  },\n  \"peerDependencies\": {\n    \"@vitest/browser\": \"workspace:*\",\n    \"vitest\": \"workspace:*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@vitest/browser\": {\n      \"optional\": true\n    }\n  },\n  \"dependencies\": {\n    \"@bcoe/v8-coverage\": \"^1.0.2\",\n    \"@vitest/utils\": \"workspace:*\",\n    \"ast-v8-to-istanbul\": \"^1.0.0\",\n    \"istanbul-lib-coverage\": \"catalog:\",\n    \"istanbul-lib-report\": \"catalog:\",\n    \"istanbul-reports\": \"catalog:\",\n    \"magicast\": \"catalog:\",\n    \"obug\": \"catalog:\",\n    \"std-env\": \"catalog:\",\n    \"tinyrainbow\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@types/istanbul-lib-coverage\": \"catalog:\",\n    \"@types/istanbul-lib-report\": \"catalog:\",\n    \"@types/istanbul-reports\": \"catalog:\",\n    \"@vitest/browser\": \"workspace:*\",\n    \"@vitest/browser-playwright\": \"workspace:*\",\n    \"pathe\": \"catalog:\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/coverage-v8/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport nodeResolve from '@rollup/plugin-node-resolve'\nimport { join } from 'pathe'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst entries = {\n  index: 'src/index.ts',\n  browser: 'src/browser.ts',\n  provider: 'src/provider.ts',\n}\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n  'node:inspector',\n  /^@?vitest(\\/|$)/,\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  nodeResolve(),\n  json(),\n  commonjs(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nexport default () => [\n  {\n    input: entries,\n    output: {\n      dir: 'dist',\n      format: 'esm',\n    },\n    external,\n    plugins,\n  },\n  {\n    input: dtsUtils.dtsInput(entries),\n    output: {\n      dir: join(process.cwd(), 'dist'),\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n  },\n]\n"
  },
  {
    "path": "packages/coverage-v8/src/browser.ts",
    "content": "import type { CDPSession } from '@vitest/browser-playwright'\nimport type { CoverageProviderModule } from 'vitest/node'\nimport type { V8CoverageProvider } from './provider'\nimport { cdp } from 'vitest/browser'\nimport { loadProvider } from './load-provider'\n\nconst session = cdp() as CDPSession\nlet enabled = false\n\ntype ScriptCoverage = Awaited<ReturnType<typeof session.send<'Profiler.takePreciseCoverage'>>>\n\nconst mod: CoverageProviderModule = {\n  async startCoverage() {\n    if (enabled) {\n      return\n    }\n\n    enabled = true\n\n    await session.send('Profiler.enable')\n    await session.send('Profiler.startPreciseCoverage', {\n      callCount: true,\n      detailed: true,\n    })\n  },\n\n  async takeCoverage(): Promise<{ result: any[] }> {\n    const coverage = await session.send('Profiler.takePreciseCoverage')\n    const result: typeof coverage.result = []\n\n    // Reduce amount of data sent over rpc by doing some early result filtering\n    for (const entry of coverage.result) {\n      if (filterResult(entry)) {\n        result.push({\n          ...entry,\n          url: decodeURIComponent(entry.url.replace(window.location.origin, '')),\n        })\n      }\n    }\n\n    return { result }\n  },\n\n  stopCoverage() {\n    // Browser mode should not stop coverage as same V8 instance is shared between tests\n  },\n\n  async getProvider(): Promise<V8CoverageProvider> {\n    return loadProvider()\n  },\n}\nexport default mod\n\nfunction filterResult(coverage: ScriptCoverage['result'][number]): boolean {\n  if (!coverage.url.startsWith(window.location.origin)) {\n    return false\n  }\n\n  if (coverage.url.includes('/node_modules/')) {\n    return false\n  }\n\n  if (coverage.url.includes('__vitest_browser__')) {\n    return false\n  }\n\n  if (coverage.url.includes('__vitest__/assets')) {\n    return false\n  }\n\n  if (coverage.url === window.location.href) {\n    return false\n  }\n\n  if (coverage.url.includes('/@id/@vitest/')) {\n    return false\n  }\n\n  if (coverage.url.includes('/@vite/client')) {\n    return false\n  }\n\n  return true\n}\n"
  },
  {
    "path": "packages/coverage-v8/src/index.ts",
    "content": "import type { Profiler } from 'node:inspector'\nimport type { CoverageProviderModule } from 'vitest/node'\nimport type { ScriptCoverageWithOffset, V8CoverageProvider } from './provider'\nimport inspector from 'node:inspector/promises'\nimport { fileURLToPath } from 'node:url'\nimport { normalize } from 'pathe'\nimport { provider } from 'std-env'\nimport { loadProvider } from './load-provider'\n\nconst session = new inspector.Session()\nlet enabled = false\n\nconst mod: CoverageProviderModule = {\n  async startCoverage({ isolate }) {\n    if (isolate === false && enabled) {\n      return\n    }\n\n    enabled = true\n\n    session.connect()\n    await session.post('Profiler.enable')\n    await session.post('Profiler.startPreciseCoverage', { callCount: true, detailed: true })\n  },\n\n  async takeCoverage(options): Promise<{ result: ScriptCoverageWithOffset[] }> {\n    if (provider === 'stackblitz') {\n      return { result: [] }\n    }\n\n    const coverage = await session.post('Profiler.takePreciseCoverage')\n    const result: ScriptCoverageWithOffset[] = []\n\n    // Reduce amount of data sent over rpc by doing some early result filtering\n    for (const entry of coverage.result) {\n      if (filterResult(entry)) {\n        result.push({\n          ...entry,\n          startOffset: options?.moduleExecutionInfo?.get(normalize(fileURLToPath(entry.url)))?.startOffset || 0,\n        })\n      }\n    }\n\n    return { result }\n  },\n\n  async stopCoverage({ isolate }) {\n    if (isolate === false) {\n      return\n    }\n\n    await session.post('Profiler.stopPreciseCoverage')\n    await session.post('Profiler.disable')\n    session.disconnect()\n  },\n\n  async getProvider(): Promise<V8CoverageProvider> {\n    return loadProvider()\n  },\n}\nexport default mod\n\nfunction filterResult(coverage: Profiler.ScriptCoverage): boolean {\n  if (!coverage.url.startsWith('file://')) {\n    return false\n  }\n\n  if (coverage.url.includes('/node_modules/')) {\n    return false\n  }\n\n  if (coverage.url.includes('/@id/@vitest/')) {\n    return false\n  }\n\n  if (coverage.url.includes('/@vite/client')) {\n    return false\n  }\n\n  return true\n}\n"
  },
  {
    "path": "packages/coverage-v8/src/load-provider.ts",
    "content": "import type { V8CoverageProvider } from './provider'\n\n// to not bundle the provider\nconst name = './provider.js'\n\nexport async function loadProvider(): Promise<V8CoverageProvider> {\n  const { V8CoverageProvider } = (await import(/* @vite-ignore */ name)) as typeof import('./provider')\n\n  return new V8CoverageProvider()\n}\n"
  },
  {
    "path": "packages/coverage-v8/src/provider.ts",
    "content": "import type { CoverageMap } from 'istanbul-lib-coverage'\nimport type { ProxifiedModule } from 'magicast'\nimport type { Profiler } from 'node:inspector'\nimport type { CoverageProvider, ReportContext, ResolvedCoverageOptions, TestProject, Vite, Vitest } from 'vitest/node'\nimport { existsSync, promises as fs } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\n// @ts-expect-error -- untyped\nimport { mergeProcessCovs } from '@bcoe/v8-coverage'\nimport astV8ToIstanbul from 'ast-v8-to-istanbul'\nimport libCoverage from 'istanbul-lib-coverage'\nimport libReport from 'istanbul-lib-report'\nimport reports from 'istanbul-reports'\nimport { parseModule } from 'magicast'\nimport { createDebug } from 'obug'\nimport { normalize } from 'pathe'\nimport { provider } from 'std-env'\nimport c from 'tinyrainbow'\nimport { BaseCoverageProvider, parseAstAsync } from 'vitest/node'\nimport { version } from '../package.json' with { type: 'json' }\n\nexport interface ScriptCoverageWithOffset extends Profiler.ScriptCoverage {\n  startOffset: number\n}\n\ninterface RawCoverage { result: ScriptCoverageWithOffset[] }\n\nconst FILE_PROTOCOL = 'file://'\n\nconst debug = createDebug('vitest:coverage')\n\nexport class V8CoverageProvider extends BaseCoverageProvider<ResolvedCoverageOptions<'v8'>> implements CoverageProvider {\n  name = 'v8' as const\n  version: string = version\n\n  initialize(ctx: Vitest): void {\n    this._initialize(ctx)\n  }\n\n  createCoverageMap(): CoverageMap {\n    return libCoverage.createCoverageMap({})\n  }\n\n  async generateCoverage({ allTestsRun }: ReportContext): Promise<CoverageMap> {\n    const start = debug.enabled ? performance.now() : 0\n\n    const coverageMap = this.createCoverageMap()\n    let merged: RawCoverage = { result: [] }\n\n    await this.readCoverageFiles<RawCoverage>({\n      onFileRead(coverage) {\n        merged = mergeProcessCovs([merged, coverage])\n\n        // mergeProcessCovs sometimes loses startOffset, e.g. in vue\n        merged.result.forEach((result) => {\n          if (!result.startOffset) {\n            const original = coverage.result.find(r => r.url === result.url)\n            result.startOffset = original?.startOffset || 0\n          }\n        })\n      },\n      onFinished: async (project, environment) => {\n        // Source maps can change based on projectName and transform mode.\n        // Coverage transform re-uses source maps so we need to separate transforms from each other.\n        const converted = await this.convertCoverage(\n          merged,\n          project,\n          environment,\n        )\n\n        coverageMap.merge(converted)\n\n        merged = { result: [] }\n      },\n      onDebug: debug,\n    })\n\n    // Include untested files when all tests were run (not a single file re-run)\n    // or if previous results are preserved by \"cleanOnRerun: false\"\n    if (this.options.include != null && (allTestsRun || !this.options.cleanOnRerun)) {\n      const coveredFiles = coverageMap.files()\n      const untestedCoverage = await this.getCoverageMapForUncoveredFiles(coveredFiles)\n\n      coverageMap.merge(untestedCoverage)\n    }\n\n    coverageMap.filter((filename) => {\n      const exists = existsSync(filename)\n\n      if (this.options.excludeAfterRemap) {\n        return exists && this.isIncluded(filename)\n      }\n\n      return exists\n    })\n\n    if (debug.enabled) {\n      debug(`Generate coverage total time ${(performance.now() - start!).toFixed()} ms`)\n    }\n\n    return coverageMap\n  }\n\n  async generateReports(coverageMap: CoverageMap, allTestsRun?: boolean): Promise<void> {\n    if (provider === 'stackblitz') {\n      this.ctx.logger.log(\n        c.blue(' % ')\n        + c.yellow(\n          '@vitest/coverage-v8 does not work on Stackblitz. Report will be empty.',\n        ),\n      )\n    }\n\n    const context = libReport.createContext({\n      dir: this.options.reportsDirectory,\n      coverageMap,\n      watermarks: this.options.watermarks,\n    })\n\n    if (this.hasTerminalReporter(this.options.reporter)) {\n      this.ctx.logger.log(\n        c.blue(' % ') + c.dim('Coverage report from ') + c.yellow(this.name),\n      )\n    }\n\n    for (const reporter of this.options.reporter) {\n      // Type assertion required for custom reporters\n      reports\n        .create(reporter[0] as Parameters<typeof reports.create>[0], {\n          skipFull: this.options.skipFull,\n          projectRoot: this.ctx.config.root,\n          ...reporter[1],\n        })\n        .execute(context)\n    }\n\n    if (this.options.thresholds) {\n      await this.reportThresholds(coverageMap, allTestsRun)\n    }\n  }\n\n  async parseConfigModule(configFilePath: string): Promise<ProxifiedModule<any>> {\n    const contents = await fs.readFile(configFilePath, 'utf8')\n\n    return parseModule(`${contents}${this.autoUpdateMarker}`)\n  }\n\n  private async getCoverageMapForUncoveredFiles(testedFiles: string[]): Promise<CoverageMap> {\n    const transform = this.createUncoveredFileTransformer(this.ctx)\n\n    const uncoveredFiles = await this.getUntestedFiles(testedFiles)\n\n    let index = 0\n\n    const coverageMap = this.createCoverageMap()\n\n    for (const chunk of this.toSlices(uncoveredFiles, this.options.processingConcurrency)) {\n      if (debug.enabled) {\n        index += chunk.length\n        debug('Uncovered files %d/%d', index, uncoveredFiles.length)\n      }\n\n      await Promise.all(chunk.map(async (filename) => {\n        let timeout: ReturnType<typeof setTimeout> | undefined\n        let start: number | undefined\n\n        if (debug.enabled) {\n          start = performance.now()\n          timeout = setTimeout(() => debug(c.bgRed(`File \"${filename}\" is taking longer than 3s`)), 3_000)\n        }\n\n        // Do not use pathToFileURL to avoid encoding filename parts\n        const url = `file://${filename[0] === '/' ? '' : '/'}${filename}`\n\n        const sources = await this.getSources(\n          url,\n          transform,\n        )\n\n        coverageMap.merge(await this.remapCoverage(\n          url,\n          0,\n          sources,\n          [],\n        ))\n\n        if (debug.enabled) {\n          clearTimeout(timeout)\n\n          const diff = performance.now() - start!\n          const color = diff > 500 ? c.bgRed : c.bgGreen\n          debug(`${color(` ${diff.toFixed()} ms `)} ${filename}`)\n        }\n      }))\n    }\n\n    return coverageMap\n  }\n\n  private async remapCoverage(filename: string, wrapperLength: number, result: Awaited<ReturnType<typeof this.getSources>>, functions: Profiler.FunctionCoverage[]) {\n    let ast\n\n    try {\n      ast = await parseAstAsync(result.code)\n    }\n    catch (error) {\n      this.ctx.logger.error(`Failed to parse ${filename}. Excluding it from coverage.\\n`, error)\n      return {}\n    }\n\n    return await astV8ToIstanbul({\n      code: result.code,\n      sourceMap: result.map,\n      ast,\n      coverage: { functions, url: filename },\n      ignoreClassMethods: this.options.ignoreClassMethods,\n      wrapperLength,\n      ignoreNode: (node, type) => {\n        // SSR transformed imports\n        if (\n          type === 'statement'\n          && node.type === 'VariableDeclarator'\n          && node.id.type === 'Identifier'\n          && node.id.name.startsWith('__vite_ssr_import_')\n        ) {\n          return true\n        }\n\n        // SSR transformed exports vite@>6.3.5\n        if (\n          type === 'statement'\n          && node.type === 'ExpressionStatement'\n          && node.expression.type === 'AssignmentExpression'\n          && node.expression.left.type === 'MemberExpression'\n          && node.expression.left.object.type === 'Identifier'\n          && node.expression.left.object.name === '__vite_ssr_exports__'\n        ) {\n          return true\n        }\n\n        // SSR transformed exports vite@^6.3.5\n        if (\n          type === 'statement'\n          && node.type === 'VariableDeclarator'\n          && node.id.type === 'Identifier'\n          && node.id.name === '__vite_ssr_export_default__'\n        ) {\n          return true\n        }\n\n        // CJS imports as ternaries - e.g.\n        // const React = __vite__cjsImport0_react.__esModule ? __vite__cjsImport0_react.default : __vite__cjsImport0_react;\n        if (\n          type === 'branch'\n          && node.type === 'ConditionalExpression'\n          && node.test.type === 'MemberExpression'\n          && node.test.object.type === 'Identifier'\n          && node.test.object.name.startsWith('__vite__cjsImport')\n          && node.test.property.type === 'Identifier'\n          && node.test.property.name === '__esModule'\n        ) {\n          return true\n        }\n\n        // in-source test with \"if (import.meta.vitest)\"\n        if (\n          (type === 'branch' || type === 'statement')\n          && node.type === 'IfStatement'\n          && node.test.type === 'MemberExpression'\n          && node.test.property.type === 'Identifier'\n          && node.test.property.name === 'vitest'\n        ) {\n          // SSR\n          if (\n            node.test.object.type === 'Identifier'\n            && node.test.object.name === '__vite_ssr_import_meta__'\n          ) {\n            return 'ignore-this-and-nested-nodes'\n          }\n\n          // Web\n          if (\n            node.test.object.type === 'MetaProperty'\n            && node.test.object.meta.name === 'import'\n            && node.test.object.property.name === 'meta'\n          ) {\n            return 'ignore-this-and-nested-nodes'\n          }\n        }\n\n        // Browser mode's \"import.meta.env =\"\n        if (\n          type === 'statement'\n          && node.type === 'ExpressionStatement'\n          && node.expression.type === 'AssignmentExpression'\n          && node.expression.left.type === 'MemberExpression'\n          && node.expression.left.object.type === 'MetaProperty'\n          && node.expression.left.object.meta.name === 'import'\n          && node.expression.left.object.property.name === 'meta'\n          && node.expression.left.property.type === 'Identifier'\n          && node.expression.left.property.name === 'env'\n        ) {\n          return true\n        }\n\n        // SSR mode's \"import.meta.env =\"\n        if (\n          type === 'statement'\n          && node.type === 'ExpressionStatement'\n          && node.expression.type === 'AssignmentExpression'\n          && node.expression.left.type === 'MemberExpression'\n          && node.expression.left.object.type === 'Identifier'\n          && node.expression.left.object.name === '__vite_ssr_import_meta__'\n        ) {\n          return true\n        }\n\n        // SWC's decorators\n        if (\n          type === 'statement'\n          && node.type === 'ExpressionStatement'\n          && node.expression.type === 'CallExpression'\n          && node.expression.callee.type === 'Identifier'\n          && node.expression.callee.name === '_ts_decorate'\n        ) {\n          return 'ignore-this-and-nested-nodes'\n        }\n      },\n    },\n    )\n  }\n\n  private async getSources(\n    url: string,\n    onTransform: (filepath: string) => Promise<Vite.TransformResult | undefined | null>,\n    functions: Profiler.FunctionCoverage[] = [],\n  ): Promise<{\n    code: string\n    map?: Vite.Rollup.SourceMap\n  }> {\n    // TODO: need to standardize file urls before this call somehow, this is messy\n    const filepath = url.match(/^file:\\/\\/\\/\\w:\\//)\n      ? url.slice(8)\n      : removeStartsWith(url, FILE_PROTOCOL)\n    // TODO: do we still need to \"catch\" here? why would it fail?\n    const transformResult = await onTransform(filepath).catch(() => null)\n\n    const map = transformResult?.map as Vite.Rollup.SourceMap | undefined\n    const code = transformResult?.code\n\n    if (code == null) {\n      const filePath = normalize(fileURLToPath(url))\n\n      const original = await fs.readFile(filePath, 'utf-8').catch(() => {\n        // If file does not exist construct a dummy source for it.\n        // These can be files that were generated dynamically during the test run and were removed after it.\n        const length = findLongestFunctionLength(functions)\n        return '/'.repeat(length)\n      })\n\n      return { code: original }\n    }\n\n    // Vue needs special handling for \"map.sources\"\n    if (map) {\n      map.sources ||= []\n\n      map.sources = map.sources\n        .filter(source => source != null)\n        .map(source => new URL(source, url).href)\n\n      if (map.sources.length === 0) {\n        map.sources.push(url)\n      }\n    }\n\n    return { code, map }\n  }\n\n  private async convertCoverage(\n    coverage: RawCoverage,\n    project: TestProject = this.ctx.getRootProject(),\n    environment: string,\n  ): Promise<CoverageMap> {\n    if (environment === '__browser__' && !project.browser) {\n      throw new Error(`Cannot access browser module graph because it was torn down.`)\n    }\n\n    const onTransform = async (filepath: string) => {\n      const result = await this.transformFile(filepath, project, environment)\n      if (result && environment === '__browser__' && project.browser) {\n        return { ...result, code: `${result.code}// <inline-source-map>` }\n      }\n      return result\n    }\n\n    const scriptCoverages = []\n\n    for (const result of coverage.result) {\n      if (environment === '__browser__') {\n        if (result.url.startsWith('/@fs')) {\n          result.url = `${FILE_PROTOCOL}${removeStartsWith(result.url, '/@fs')}`\n        }\n        else if (result.url.startsWith(project.config.root)) {\n          result.url = `${FILE_PROTOCOL}${result.url}`\n        }\n        else {\n          result.url = `${FILE_PROTOCOL}${project.config.root}${result.url}`\n        }\n      }\n\n      if (this.isIncluded(fileURLToPath(result.url))) {\n        scriptCoverages.push({ ...result, url: decodeURIComponent(result.url) })\n      }\n    }\n\n    const coverageMap = this.createCoverageMap()\n    let index = 0\n\n    for (const chunk of this.toSlices(scriptCoverages, this.options.processingConcurrency)) {\n      if (debug.enabled) {\n        index += chunk.length\n        debug('Converting %d/%d', index, scriptCoverages.length)\n      }\n\n      await Promise.all(\n        chunk.map(async ({ url, functions, startOffset }) => {\n          let timeout: ReturnType<typeof setTimeout> | undefined\n          let start: number | undefined\n\n          if (debug.enabled) {\n            start = performance.now()\n            timeout = setTimeout(() => debug(c.bgRed(`File \"${fileURLToPath(url)}\" is taking longer than 3s`)), 3_000)\n          }\n\n          const sources = await this.getSources(\n            url,\n            onTransform,\n            functions,\n          )\n\n          coverageMap.merge(await this.remapCoverage(\n            url,\n            startOffset,\n            sources,\n            functions,\n          ))\n\n          if (debug.enabled) {\n            clearTimeout(timeout)\n\n            const diff = performance.now() - start!\n            const color = diff > 500 ? c.bgRed : c.bgGreen\n            debug(`${color(` ${diff.toFixed()} ms `)} ${fileURLToPath(url)}`)\n          }\n        }),\n      )\n    }\n\n    return coverageMap\n  }\n}\n\n/**\n * Find the function with highest `endOffset` to determine the length of the file\n */\nfunction findLongestFunctionLength(functions: Profiler.FunctionCoverage[]) {\n  return functions.reduce((previous, current) => {\n    const maxEndOffset = current.ranges.reduce(\n      (endOffset, range) => Math.max(endOffset, range.endOffset),\n      0,\n    )\n\n    return Math.max(previous, maxEndOffset)\n  }, 0)\n}\n\nfunction removeStartsWith(filepath: string, start: string) {\n  if (filepath.startsWith(start)) {\n    return filepath.slice(start.length)\n  }\n\n  return filepath\n}\n"
  },
  {
    "path": "packages/coverage-v8/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"moduleResolution\": \"Bundler\",\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"./dist\"]\n}\n"
  },
  {
    "path": "packages/expect/README.md",
    "content": "# @vitest/expect\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/runner?color=a1b858&label=)](https://npmx.dev/package/@vitest/runner)\n\nJest's expect matchers as a Chai plugin.\n\n## Usage\n\n```js\nimport {\n  JestAsymmetricMatchers,\n  JestChaiExpect,\n  JestExtend,\n} from '@vitest/expect'\nimport * as chai from 'chai'\n\n// allows using expect.extend instead of chai.use to extend plugins\nchai.use(JestExtend)\n// adds all jest matchers to expect\nchai.use(JestChaiExpect)\n// adds asymmetric matchers like stringContaining, objectContaining\nchai.use(JestAsymmetricMatchers)\n```\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/expect) | [Documentation](https://vitest.dev/api/expect)\n"
  },
  {
    "path": "packages/expect/package.json",
    "content": "{\n  \"name\": \"@vitest/expect\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Jest's expect matchers as a Chai plugin\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/api/expect\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/expect\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vitest\",\n    \"test\",\n    \"chai\",\n    \"assertion\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch\"\n  },\n  \"dependencies\": {\n    \"@standard-schema/spec\": \"^1.1.0\",\n    \"@types/chai\": \"catalog:\",\n    \"@vitest/spy\": \"workspace:*\",\n    \"@vitest/utils\": \"workspace:*\",\n    \"chai\": \"catalog:\",\n    \"tinyrainbow\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@vitest/runner\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/expect/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^@?vitest(\\/|$)/,\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nexport default defineConfig([\n  {\n    input: 'src/index.ts',\n    output: {\n      dir: 'dist',\n      format: 'esm',\n      entryFileNames: '[name].js',\n      chunkFileNames: 'chunk-[name].js',\n    },\n    external,\n    plugins,\n    onwarn,\n  },\n  {\n    input: dtsUtils.dtsInput('src/index.ts'),\n    output: {\n      dir: 'dist',\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n    onwarn,\n  },\n])\n\nfunction onwarn(message) {\n  if (['EMPTY_BUNDLE', 'CIRCULAR_DEPENDENCY'].includes(message.code)) {\n    return\n  }\n  console.error(message)\n}\n"
  },
  {
    "path": "packages/expect/src/chai-style-assertions.ts",
    "content": "import type { Assertion, ChaiPlugin } from './types'\n\nexport const ChaiStyleAssertions: ChaiPlugin = (chai, utils) => {\n  function defProperty(\n    name: keyof Assertion,\n    delegateTo: keyof Assertion,\n  ) {\n    utils.addProperty(\n      chai.Assertion.prototype,\n      name,\n      function (this: Chai.AssertionStatic & Assertion) {\n        const jestMethod = (chai.Assertion.prototype as any)[delegateTo]\n        if (!jestMethod) {\n          throw new Error(\n            `Cannot delegate to ${String(delegateTo)}: method not found. Ensure JestChaiExpect plugin is loaded first.`,\n          )\n        }\n        return jestMethod.call(this)\n      },\n    )\n  }\n\n  function defPropertyWithArgs(\n    name: keyof Assertion,\n    delegateTo: keyof Assertion,\n    ...args: any[]\n  ) {\n    utils.addProperty(\n      chai.Assertion.prototype,\n      name,\n      function (this: Chai.AssertionStatic & Assertion) {\n        const jestMethod = (chai.Assertion.prototype as any)[delegateTo]\n        if (!jestMethod) {\n          throw new Error(\n            `Cannot delegate to ${String(delegateTo)}: method not found. Ensure JestChaiExpect plugin is loaded first.`,\n          )\n        }\n        return jestMethod.call(this, ...args)\n      },\n    )\n  }\n\n  function defMethod(\n    name: keyof Assertion,\n    delegateTo: keyof Assertion,\n  ) {\n    utils.addChainableMethod(\n      chai.Assertion.prototype,\n      name,\n      function (this: Chai.AssertionStatic & Assertion, ...args: any[]) {\n        const jestMethod = (chai.Assertion.prototype as any)[delegateTo]\n        if (!jestMethod) {\n          throw new Error(\n            `Cannot delegate to ${String(delegateTo)}: method not found. Ensure JestChaiExpect plugin is loaded first.`,\n          )\n        }\n        return jestMethod.call(this, ...args)\n      },\n      () => {},\n    )\n  }\n\n  defProperty('called', 'toHaveBeenCalled')\n  defProperty('calledOnce', 'toHaveBeenCalledOnce')\n  defProperty('returned', 'toHaveReturned')\n  defPropertyWithArgs('calledTwice', 'toHaveBeenCalledTimes', 2)\n  defPropertyWithArgs('calledThrice', 'toHaveBeenCalledTimes', 3)\n\n  defMethod('callCount', 'toHaveBeenCalledTimes')\n  defMethod('calledWith', 'toHaveBeenCalledWith')\n  defMethod('calledOnceWith', 'toHaveBeenCalledExactlyOnceWith')\n  defMethod('lastCalledWith', 'toHaveBeenLastCalledWith')\n  defMethod('nthCalledWith', 'toHaveBeenNthCalledWith')\n  defMethod('returnedWith', 'toHaveReturnedWith')\n  defMethod('returnedTimes', 'toHaveReturnedTimes')\n  defMethod('lastReturnedWith', 'toHaveLastReturnedWith')\n  defMethod('nthReturnedWith', 'toHaveNthReturnedWith')\n  defMethod('calledBefore', 'toHaveBeenCalledBefore')\n  defMethod('calledAfter', 'toHaveBeenCalledAfter')\n}\n"
  },
  {
    "path": "packages/expect/src/constants.ts",
    "content": "export const MATCHERS_OBJECT: unique symbol = Symbol.for('matchers-object')\nexport const JEST_MATCHERS_OBJECT: unique symbol = Symbol.for('$$jest-matchers-object')\nexport const GLOBAL_EXPECT: unique symbol = Symbol.for('expect-global')\nexport const ASYMMETRIC_MATCHERS_OBJECT: unique symbol = Symbol.for(\n  'asymmetric-matchers-object',\n)\n"
  },
  {
    "path": "packages/expect/src/custom-matchers.ts",
    "content": "import type { MatchersObject } from './types'\n\n// selectively ported from https://github.com/jest-community/jest-extended\nexport const customMatchers: MatchersObject = {\n  toSatisfy(actual: unknown, expected: (actual: unknown) => boolean, message?: string) {\n    const { printReceived, printExpected, matcherHint } = this.utils\n    const pass = expected(actual)\n    return {\n      pass,\n      message: () =>\n        pass\n          ? `\\\n${matcherHint('.not.toSatisfy', 'received', '')}\n\nExpected value to not satisfy:\n${message || printExpected(expected)}\nReceived:\n${printReceived(actual)}`\n          : `\\\n${matcherHint('.toSatisfy', 'received', '')}\n\nExpected value to satisfy:\n${message || printExpected(expected)}\n\nReceived:\n${printReceived(actual)}`,\n    }\n  },\n\n  toBeOneOf(actual: unknown, expected: Array<unknown> | Set<unknown>) {\n    const { equals, customTesters } = this\n    const { printReceived, printExpected, matcherHint } = this.utils\n\n    let pass: boolean\n\n    if (Array.isArray(expected)) {\n      pass = expected.length === 0\n        || expected.some(item =>\n          equals(item, actual, customTesters),\n        )\n    }\n    else if (expected instanceof Set) {\n      pass = expected.size === 0 || expected.has(actual) || [...expected].some(item => equals(item, actual, customTesters))\n    }\n    else {\n      throw new TypeError(\n        `You must provide an array or set to ${matcherHint('.toBeOneOf')}, not '${typeof expected}'.`,\n      )\n    }\n\n    return {\n      pass,\n      message: () =>\n        pass\n          ? `\\\n${matcherHint('.not.toBeOneOf', 'received', '')}\n\nExpected value to not be one of:\n${printExpected(expected)}\nReceived:\n${printReceived(actual)}`\n          : `\\\n${matcherHint('.toBeOneOf', 'received', '')}\n\nExpected value to be one of:\n${printExpected(expected)}\n\nReceived:\n${printReceived(actual)}`,\n    }\n  },\n}\n"
  },
  {
    "path": "packages/expect/src/index.ts",
    "content": "export { ChaiStyleAssertions } from './chai-style-assertions'\nexport {\n  ASYMMETRIC_MATCHERS_OBJECT,\n  GLOBAL_EXPECT,\n  JEST_MATCHERS_OBJECT,\n  MATCHERS_OBJECT,\n} from './constants'\nexport { customMatchers } from './custom-matchers'\nexport type { AsymmetricMatcherInterface } from './jest-asymmetric-matchers'\nexport {\n  Any,\n  Anything,\n  ArrayContaining,\n  AsymmetricMatcher,\n  JestAsymmetricMatchers,\n  ObjectContaining,\n  SchemaMatching,\n  StringContaining,\n  StringMatching,\n} from './jest-asymmetric-matchers'\nexport { JestChaiExpect } from './jest-expect'\nexport { JestExtend } from './jest-extend'\nexport { addCustomEqualityTesters } from './jest-matcher-utils'\nexport * from './jest-utils'\nexport { getState, setState } from './state'\nexport * from './types'\nexport * from './utils'\nexport * as chai from 'chai'\n"
  },
  {
    "path": "packages/expect/src/jest-asymmetric-matchers.ts",
    "content": "/* eslint-disable unicorn/no-instanceof-builtins -- we check both */\n\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type { ChaiPlugin, MatcherState, Tester } from './types'\nimport { GLOBAL_EXPECT } from './constants'\nimport {\n  diff,\n  getCustomEqualityTesters,\n  getMatcherUtils,\n  stringify,\n} from './jest-matcher-utils'\n\nimport {\n  equals,\n  isA,\n  isStandardSchema,\n  iterableEquality,\n  pluralize,\n  subsetEquality,\n} from './jest-utils'\nimport { getState } from './state'\n\nexport interface AsymmetricMatcherInterface {\n  asymmetricMatch: (other: unknown, customTesters?: Array<Tester>) => boolean\n  toString: () => string\n  getExpectedType?: () => string\n  toAsymmetricMatcher?: () => string\n}\n\nexport abstract class AsymmetricMatcher<\n  T,\n  State extends MatcherState = MatcherState,\n> implements AsymmetricMatcherInterface {\n  // should have \"jest\" to be compatible with its ecosystem\n  $$typeof: symbol = Symbol.for('jest.asymmetricMatcher')\n\n  constructor(protected sample: T, protected inverse = false) {}\n\n  protected getMatcherContext(expect?: Chai.ExpectStatic): State {\n    return {\n      ...getState(expect || (globalThis as any)[GLOBAL_EXPECT]),\n      equals,\n      isNot: this.inverse,\n      customTesters: getCustomEqualityTesters(),\n      utils: {\n        ...getMatcherUtils(),\n        diff,\n        stringify,\n        iterableEquality,\n        subsetEquality,\n      },\n    }\n  }\n\n  abstract asymmetricMatch(other: unknown, customTesters?: Array<Tester>): boolean\n  abstract toString(): string\n  getExpectedType?(): string\n  toAsymmetricMatcher?(): string\n}\n\n// implement custom chai/loupe inspect for better AssertionError.message formatting\n// https://github.com/chaijs/loupe/blob/9b8a6deabcd50adc056a64fb705896194710c5c6/src/index.ts#L29\n// @ts-expect-error computed properties is not supported when isolatedDeclarations is enabled\n// FIXME: https://github.com/microsoft/TypeScript/issues/61068\nAsymmetricMatcher.prototype[Symbol.for('chai/inspect')] = function (options: { depth: number; truncate: number }): string {\n  // minimal pretty-format with simple manual truncation\n  const result = stringify(this, options.depth, { min: true })\n  if (result.length <= options.truncate) {\n    return result\n  }\n  return `${this.toString()}{…}`\n}\n\nexport class StringContaining extends AsymmetricMatcher<string> {\n  constructor(sample: string, inverse = false) {\n    if (!isA('String', sample)) {\n      throw new Error('Expected is not a string')\n    }\n\n    super(sample, inverse)\n  }\n\n  asymmetricMatch(other: string): boolean {\n    const result = isA('String', other) && other.includes(this.sample)\n\n    return this.inverse ? !result : result\n  }\n\n  toString() {\n    return `String${this.inverse ? 'Not' : ''}Containing`\n  }\n\n  getExpectedType() {\n    return 'string'\n  }\n}\n\nexport class Anything extends AsymmetricMatcher<void> {\n  asymmetricMatch(other: unknown): boolean {\n    return other != null\n  }\n\n  toString() {\n    return 'Anything'\n  }\n\n  toAsymmetricMatcher() {\n    return 'Anything'\n  }\n}\n\nexport class ObjectContaining extends AsymmetricMatcher<\n  Record<string | symbol | number, unknown>\n> {\n  constructor(sample: Record<string, unknown>, inverse = false) {\n    super(sample, inverse)\n  }\n\n  getPrototype(obj: object): any {\n    if (Object.getPrototypeOf) {\n      return Object.getPrototypeOf(obj)\n    }\n\n    if (obj.constructor.prototype === obj) {\n      return null\n    }\n\n    return obj.constructor.prototype\n  }\n\n  hasProperty(obj: object | null, property: string | symbol): boolean {\n    if (!obj) {\n      return false\n    }\n\n    if (Object.hasOwn(obj, property)) {\n      return true\n    }\n\n    return this.hasProperty(this.getPrototype(obj), property)\n  }\n\n  getProperties(obj: object): (string | symbol)[] {\n    return [\n      ...Object.keys(obj),\n      ...Object.getOwnPropertySymbols(obj).filter(\n        s => Object.getOwnPropertyDescriptor(obj, s)?.enumerable,\n      ),\n    ]\n  }\n\n  asymmetricMatch(other: any, customTesters?: Array<Tester>): boolean {\n    if (typeof this.sample !== 'object') {\n      throw new TypeError(\n        `You must provide an object to ${this.toString()}, not '${typeof this\n          .sample}'.`,\n      )\n    }\n\n    let result = true\n\n    const properties = this.getProperties(this.sample)\n    for (const property of properties) {\n      if (\n        !this.hasProperty(other, property)\n      ) {\n        result = false\n        break\n      }\n      const value = this.sample[property]\n      const otherValue = other[property]\n      if (!equals(\n        value,\n        otherValue,\n        customTesters,\n      )) {\n        result = false\n        break\n      }\n    }\n\n    return this.inverse ? !result : result\n  }\n\n  toString() {\n    return `Object${this.inverse ? 'Not' : ''}Containing`\n  }\n\n  getExpectedType() {\n    return 'object'\n  }\n}\n\nexport class ArrayContaining<T = unknown> extends AsymmetricMatcher<Array<T>> {\n  constructor(sample: Array<T>, inverse = false) {\n    super(sample, inverse)\n  }\n\n  asymmetricMatch(other: Array<T>, customTesters?: Array<Tester>): boolean {\n    if (!Array.isArray(this.sample)) {\n      throw new TypeError(\n        `You must provide an array to ${this.toString()}, not '${typeof this\n          .sample}'.`,\n      )\n    }\n\n    const result\n      = this.sample.length === 0\n        || (Array.isArray(other)\n          && this.sample.every(item =>\n            other.some(another =>\n              equals(item, another, customTesters),\n            ),\n          ))\n\n    return this.inverse ? !result : result\n  }\n\n  toString() {\n    return `Array${this.inverse ? 'Not' : ''}Containing`\n  }\n\n  getExpectedType() {\n    return 'array'\n  }\n}\n\nexport class Any extends AsymmetricMatcher<any> {\n  constructor(sample: unknown) {\n    if (typeof sample === 'undefined') {\n      throw new TypeError(\n        'any() expects to be passed a constructor function. '\n        + 'Please pass one or use anything() to match any object.',\n      )\n    }\n    super(sample)\n  }\n\n  fnNameFor(func: Function): string {\n    if (func.name) {\n      return func.name\n    }\n\n    const functionToString = Function.prototype.toString\n\n    const matches = functionToString\n      .call(func)\n      .match(/^(?:async)?\\s*function\\s*(?:\\*\\s*)?([\\w$]+)\\s*\\(/)\n    return matches ? matches[1] : '<anonymous>'\n  }\n\n  asymmetricMatch(other: unknown): boolean {\n    if (this.sample === String) {\n      return typeof other == 'string' || other instanceof String\n    }\n\n    if (this.sample === Number) {\n      return typeof other == 'number' || other instanceof Number\n    }\n\n    if (this.sample === Function) {\n      return typeof other == 'function' || typeof other === 'function'\n    }\n\n    if (this.sample === Boolean) {\n      return typeof other == 'boolean' || other instanceof Boolean\n    }\n\n    if (this.sample === BigInt) {\n      return typeof other == 'bigint' || other instanceof BigInt\n    }\n\n    if (this.sample === Symbol) {\n      return typeof other == 'symbol' || other instanceof Symbol\n    }\n\n    if (this.sample === Object) {\n      return typeof other == 'object'\n    }\n\n    return other instanceof this.sample\n  }\n\n  toString() {\n    return 'Any'\n  }\n\n  getExpectedType(): string {\n    if (this.sample === String) {\n      return 'string'\n    }\n\n    if (this.sample === Number) {\n      return 'number'\n    }\n\n    if (this.sample === Function) {\n      return 'function'\n    }\n\n    if (this.sample === Object) {\n      return 'object'\n    }\n\n    if (this.sample === Boolean) {\n      return 'boolean'\n    }\n\n    return this.fnNameFor(this.sample)\n  }\n\n  toAsymmetricMatcher() {\n    return `Any<${this.fnNameFor(this.sample)}>`\n  }\n}\n\nexport class StringMatching extends AsymmetricMatcher<RegExp> {\n  constructor(sample: string | RegExp, inverse = false) {\n    if (!isA('String', sample) && !isA('RegExp', sample)) {\n      throw new Error('Expected is not a String or a RegExp')\n    }\n\n    super(new RegExp(sample), inverse)\n  }\n\n  asymmetricMatch(other: string): boolean {\n    const result = isA('String', other) && this.sample.test(other)\n\n    return this.inverse ? !result : result\n  }\n\n  toString() {\n    return `String${this.inverse ? 'Not' : ''}Matching`\n  }\n\n  getExpectedType() {\n    return 'string'\n  }\n}\n\nclass CloseTo extends AsymmetricMatcher<number> {\n  private readonly precision: number\n\n  constructor(sample: number, precision = 2, inverse = false) {\n    if (!isA('Number', sample)) {\n      throw new Error('Expected is not a Number')\n    }\n\n    if (!isA('Number', precision)) {\n      throw new Error('Precision is not a Number')\n    }\n\n    super(sample)\n    this.inverse = inverse\n    this.precision = precision\n  }\n\n  asymmetricMatch(other: number) {\n    if (!isA('Number', other)) {\n      return false\n    }\n\n    let result = false\n    if (\n      other === Number.POSITIVE_INFINITY\n      && this.sample === Number.POSITIVE_INFINITY\n    ) {\n      result = true // Infinity - Infinity is NaN\n    }\n    else if (\n      other === Number.NEGATIVE_INFINITY\n      && this.sample === Number.NEGATIVE_INFINITY\n    ) {\n      result = true // -Infinity - -Infinity is NaN\n    }\n    else {\n      result = Math.abs(this.sample - other) < 10 ** -this.precision / 2\n    }\n    return this.inverse ? !result : result\n  }\n\n  toString() {\n    return `Number${this.inverse ? 'Not' : ''}CloseTo`\n  }\n\n  override getExpectedType() {\n    return 'number'\n  }\n\n  override toAsymmetricMatcher(): string {\n    return [\n      this.toString(),\n      this.sample,\n      `(${pluralize('digit', this.precision)})`,\n    ].join(' ')\n  }\n}\n\nexport class SchemaMatching extends AsymmetricMatcher<StandardSchemaV1<unknown, unknown>> {\n  private result: StandardSchemaV1.Result<unknown> | undefined\n\n  constructor(sample: StandardSchemaV1<unknown, unknown>, inverse = false) {\n    if (!isStandardSchema(sample)) {\n      throw new TypeError(\n        'SchemaMatching expected to receive a Standard Schema.',\n      )\n    }\n    super(sample, inverse)\n  }\n\n  asymmetricMatch(other: unknown): boolean {\n    const result = this.sample['~standard'].validate(other)\n\n    // Check if the result is a Promise (async validation)\n    if (result instanceof Promise) {\n      throw new TypeError('Async schema validation is not supported in asymmetric matchers.')\n    }\n\n    this.result = result\n    const pass = !this.result.issues || this.result.issues.length === 0\n\n    return this.inverse ? !pass : pass\n  }\n\n  toString() {\n    return `Schema${this.inverse ? 'Not' : ''}Matching`\n  }\n\n  getExpectedType() {\n    return 'object'\n  }\n\n  toAsymmetricMatcher(): string {\n    const { utils } = this.getMatcherContext()\n    const issues = this.result?.issues || []\n    if (issues.length > 0) {\n      return `${this.toString()} ${utils.stringify(this.result, undefined, { printBasicPrototype: false })}`\n    }\n    return this.toString()\n  }\n}\n\nexport const JestAsymmetricMatchers: ChaiPlugin = (chai, utils) => {\n  utils.addMethod(chai.expect, 'anything', () => new Anything())\n\n  utils.addMethod(chai.expect, 'any', (expected: unknown) => new Any(expected))\n\n  utils.addMethod(\n    chai.expect,\n    'stringContaining',\n    (expected: string) => new StringContaining(expected),\n  )\n\n  utils.addMethod(\n    chai.expect,\n    'objectContaining',\n    (expected: any) => new ObjectContaining(expected),\n  )\n\n  utils.addMethod(\n    chai.expect,\n    'arrayContaining',\n    <T = any>(expected: Array<T>) => new ArrayContaining<T>(expected),\n  )\n\n  utils.addMethod(\n    chai.expect,\n    'stringMatching',\n    (expected: any) => new StringMatching(expected),\n  )\n\n  utils.addMethod(\n    chai.expect,\n    'closeTo',\n    (expected: any, precision?: number) => new CloseTo(expected, precision),\n  )\n\n  utils.addMethod(\n    chai.expect,\n    'schemaMatching',\n    (expected: any) => new SchemaMatching(expected),\n  );\n\n  // defineProperty does not work\n  (chai.expect as any).not = {\n    stringContaining: (expected: string) =>\n      new StringContaining(expected, true),\n    objectContaining: (expected: any) => new ObjectContaining(expected, true),\n    arrayContaining: <T = unknown>(expected: Array<T>) =>\n      new ArrayContaining<T>(expected, true),\n    stringMatching: (expected: string | RegExp) =>\n      new StringMatching(expected, true),\n    closeTo: (expected: any, precision?: number) =>\n      new CloseTo(expected, precision, true),\n    schemaMatching: (expected: any) => new SchemaMatching(expected, true),\n  }\n}\n"
  },
  {
    "path": "packages/expect/src/jest-expect.ts",
    "content": "import type { Test } from '@vitest/runner'\nimport type { MockInstance, MockResult, MockSettledResult } from '@vitest/spy'\nimport type { Constructable } from '@vitest/utils'\nimport type { AsymmetricMatcher } from './jest-asymmetric-matchers'\nimport type { Assertion, ChaiPlugin } from './types'\nimport { isMockFunction } from '@vitest/spy'\nimport { assertTypes, ordinal } from '@vitest/utils/helpers'\nimport c from 'tinyrainbow'\nimport { JEST_MATCHERS_OBJECT } from './constants'\nimport {\n  diff,\n  getCustomEqualityTesters,\n  stringify,\n} from './jest-matcher-utils'\nimport {\n  arrayBufferEquality,\n  generateToBeMessage,\n  getObjectSubset,\n  isError,\n  iterableEquality,\n  equals as jestEquals,\n  sparseArrayEquality,\n  subsetEquality,\n  typeEquality,\n} from './jest-utils'\nimport { createAssertionMessage, recordAsyncExpect, wrapAssertion } from './utils'\n\n// polyfill globals because expect can be used in node environment\ndeclare class Node {\n  contains(item: unknown): boolean\n}\ndeclare class DOMTokenList {\n  value: string\n  contains(item: unknown): boolean\n}\n\n// Jest Expect Compact\nexport const JestChaiExpect: ChaiPlugin = (chai, utils) => {\n  const { AssertionError } = chai\n  const customTesters = getCustomEqualityTesters()\n\n  function def(\n    name: keyof Assertion | (keyof Assertion)[],\n    fn: (this: Chai.AssertionStatic & Assertion, ...args: any[]) => any,\n  ) {\n    const addMethod = (n: keyof Assertion) => {\n      const softWrapper = wrapAssertion(utils, n, fn)\n      utils.addMethod(chai.Assertion.prototype, n, softWrapper)\n      utils.addMethod(\n        (globalThis as any)[JEST_MATCHERS_OBJECT].matchers,\n        n,\n        softWrapper,\n      )\n    }\n\n    if (Array.isArray(name)) {\n      name.forEach(n => addMethod(n))\n    }\n    else {\n      addMethod(name)\n    }\n  }\n\n  (['throw', 'throws', 'Throw'] as const).forEach((m) => {\n    utils.overwriteMethod(chai.Assertion.prototype, m, (_super: any) => {\n      return function (\n        this: Chai.Assertion & Chai.AssertionStatic,\n        ...args: any[]\n      ) {\n        const promise = utils.flag(this, 'promise')\n        const object = utils.flag(this, 'object')\n        const isNot = utils.flag(this, 'negate') as boolean\n        if (promise === 'rejects') {\n          utils.flag(this, 'object', () => {\n            throw object\n          })\n        }\n        // if it got here, it's already resolved\n        // unless it tries to resolve to a function that should throw\n        // called as '.resolves[.not].toThrow()`\n        else if (promise === 'resolves' && typeof object !== 'function') {\n          if (!isNot) {\n            const message\n              = utils.flag(this, 'message')\n                || 'expected promise to throw an error, but it didn\\'t'\n            const error = {\n              showDiff: false,\n            }\n            throw new AssertionError(message, error, utils.flag(this, 'ssfi'))\n          }\n          else {\n            return\n          }\n        }\n        _super.apply(this, args)\n      }\n    })\n  })\n\n  // @ts-expect-error @internal\n  def('withTest', function (test: Test) {\n    utils.flag(this, 'vitest-test', test)\n    return this\n  })\n\n  def('toEqual', function (expected) {\n    const actual = utils.flag(this, 'object')\n    const equal = jestEquals(actual, expected, [\n      ...customTesters,\n      iterableEquality,\n    ])\n\n    return this.assert(\n      equal,\n      'expected #{this} to deeply equal #{exp}',\n      'expected #{this} to not deeply equal #{exp}',\n      expected,\n      actual,\n    )\n  })\n\n  def('toStrictEqual', function (expected) {\n    const obj = utils.flag(this, 'object')\n    const equal = jestEquals(\n      obj,\n      expected,\n      [\n        ...customTesters,\n        iterableEquality,\n        typeEquality,\n        sparseArrayEquality,\n        arrayBufferEquality,\n      ],\n      true,\n    )\n\n    return this.assert(\n      equal,\n      'expected #{this} to strictly equal #{exp}',\n      'expected #{this} to not strictly equal #{exp}',\n      expected,\n      obj,\n    )\n  })\n  def('toBe', function (expected) {\n    const actual = this._obj\n    const pass = Object.is(actual, expected)\n\n    let deepEqualityName = ''\n\n    if (!pass) {\n      const toStrictEqualPass = jestEquals(\n        actual,\n        expected,\n        [\n          ...customTesters,\n          iterableEquality,\n          typeEquality,\n          sparseArrayEquality,\n          arrayBufferEquality,\n        ],\n        true,\n      )\n\n      if (toStrictEqualPass) {\n        deepEqualityName = 'toStrictEqual'\n      }\n      else {\n        const toEqualPass = jestEquals(actual, expected, [\n          ...customTesters,\n          iterableEquality,\n        ])\n\n        if (toEqualPass) {\n          deepEqualityName = 'toEqual'\n        }\n      }\n    }\n\n    return this.assert(\n      pass,\n      generateToBeMessage(deepEqualityName),\n      'expected #{this} not to be #{exp} // Object.is equality',\n      expected,\n      actual,\n    )\n  })\n  def('toMatchObject', function (expected) {\n    const actual = this._obj\n    const pass = jestEquals(actual, expected, [\n      ...customTesters,\n      iterableEquality,\n      subsetEquality,\n    ])\n    const isNot = utils.flag(this, 'negate') as boolean\n    const { subset: actualSubset, stripped } = getObjectSubset(\n      actual,\n      expected,\n      customTesters,\n    )\n    if ((pass && isNot) || (!pass && !isNot)) {\n      const msg = utils.getMessage(this, [\n        pass,\n        'expected #{this} to match object #{exp}',\n        'expected #{this} to not match object #{exp}',\n        expected,\n        actualSubset,\n        false,\n      ])\n      const message\n        = stripped === 0\n          ? msg\n          : `${msg}\\n(${stripped} matching ${\n            stripped === 1 ? 'property' : 'properties'\n          } omitted from actual)`\n      throw new AssertionError(message, {\n        showDiff: true,\n        expected,\n        actual: actualSubset,\n      })\n    }\n  })\n  def('toMatch', function (expected: string | RegExp) {\n    const actual = this._obj as string\n    if (typeof actual !== 'string') {\n      throw new TypeError(\n        `.toMatch() expects to receive a string, but got ${typeof actual}`,\n      )\n    }\n\n    return this.assert(\n      typeof expected === 'string'\n        ? actual.includes(expected)\n        : actual.match(expected),\n      `expected #{this} to match #{exp}`,\n      `expected #{this} not to match #{exp}`,\n      expected,\n      actual,\n    )\n  })\n  def('toContain', function (item) {\n    const actual = this._obj as\n      | Iterable<unknown>\n      | string\n      | Node\n      | DOMTokenList\n\n    if (typeof Node !== 'undefined' && actual instanceof Node) {\n      if (!(item instanceof Node)) {\n        throw new TypeError(\n          `toContain() expected a DOM node as the argument, but got ${typeof item}`,\n        )\n      }\n\n      return this.assert(\n        actual.contains(item),\n        'expected #{this} to contain element #{exp}',\n        'expected #{this} not to contain element #{exp}',\n        item,\n        actual,\n      )\n    }\n\n    if (typeof DOMTokenList !== 'undefined' && actual instanceof DOMTokenList) {\n      assertTypes(item, 'class name', ['string'])\n      const isNot = utils.flag(this, 'negate') as boolean\n      const expectedClassList = isNot\n        ? actual.value.replace(item, '').trim()\n        : `${actual.value} ${item}`\n      return this.assert(\n        actual.contains(item),\n        `expected \"${actual.value}\" to contain \"${item}\"`,\n        `expected \"${actual.value}\" not to contain \"${item}\"`,\n        expectedClassList,\n        actual.value,\n      )\n    }\n    // handle simple case on our own using `this.assert` to include diff in error message\n    if (typeof actual === 'string' && typeof item === 'string') {\n      return this.assert(\n        actual.includes(item),\n        `expected #{this} to contain #{exp}`,\n        `expected #{this} not to contain #{exp}`,\n        item,\n        actual,\n      )\n    }\n    // make \"actual\" indexable to have compatibility with jest\n    if (actual != null && typeof actual !== 'string') {\n      utils.flag(this, 'object', Array.from(actual as Iterable<unknown>))\n    }\n    return this.contain(item)\n  })\n  def('toContainEqual', function (expected) {\n    const obj = utils.flag(this, 'object')\n    const index = Array.from(obj).findIndex((item) => {\n      return jestEquals(item, expected, customTesters)\n    })\n\n    this.assert(\n      index !== -1,\n      'expected #{this} to deep equally contain #{exp}',\n      'expected #{this} to not deep equally contain #{exp}',\n      expected,\n    )\n  })\n  def('toBeTruthy', function () {\n    const obj = utils.flag(this, 'object')\n    this.assert(\n      Boolean(obj),\n      'expected #{this} to be truthy',\n      'expected #{this} to not be truthy',\n      true,\n      obj,\n    )\n  })\n  def('toBeFalsy', function () {\n    const obj = utils.flag(this, 'object')\n    this.assert(\n      !obj,\n      'expected #{this} to be falsy',\n      'expected #{this} to not be falsy',\n      false,\n      obj,\n    )\n  })\n  def('toBeGreaterThan', function (expected: number | bigint) {\n    const actual = this._obj as number | bigint\n    assertTypes(actual, 'actual', ['number', 'bigint'])\n    assertTypes(expected, 'expected', ['number', 'bigint'])\n    return this.assert(\n      actual > expected,\n      `expected ${actual} to be greater than ${expected}`,\n      `expected ${actual} to be not greater than ${expected}`,\n      expected,\n      actual,\n      false,\n    )\n  })\n  def('toBeGreaterThanOrEqual', function (expected: number | bigint) {\n    const actual = this._obj as number | bigint\n    assertTypes(actual, 'actual', ['number', 'bigint'])\n    assertTypes(expected, 'expected', ['number', 'bigint'])\n    return this.assert(\n      actual >= expected,\n      `expected ${actual} to be greater than or equal to ${expected}`,\n      `expected ${actual} to be not greater than or equal to ${expected}`,\n      expected,\n      actual,\n      false,\n    )\n  })\n  def('toBeLessThan', function (expected: number | bigint) {\n    const actual = this._obj as number | bigint\n    assertTypes(actual, 'actual', ['number', 'bigint'])\n    assertTypes(expected, 'expected', ['number', 'bigint'])\n    return this.assert(\n      actual < expected,\n      `expected ${actual} to be less than ${expected}`,\n      `expected ${actual} to be not less than ${expected}`,\n      expected,\n      actual,\n      false,\n    )\n  })\n  def('toBeLessThanOrEqual', function (expected: number | bigint) {\n    const actual = this._obj as number | bigint\n    assertTypes(actual, 'actual', ['number', 'bigint'])\n    assertTypes(expected, 'expected', ['number', 'bigint'])\n    return this.assert(\n      actual <= expected,\n      `expected ${actual} to be less than or equal to ${expected}`,\n      `expected ${actual} to be not less than or equal to ${expected}`,\n      expected,\n      actual,\n      false,\n    )\n  })\n  def('toBeNaN', function () {\n    const obj = utils.flag(this, 'object')\n    this.assert(\n      Number.isNaN(obj),\n      'expected #{this} to be NaN',\n      'expected #{this} not to be NaN',\n      Number.NaN,\n      obj,\n    )\n  })\n  def('toBeUndefined', function () {\n    const obj = utils.flag(this, 'object')\n    this.assert(\n      undefined === obj,\n      'expected #{this} to be undefined',\n      'expected #{this} not to be undefined',\n      undefined,\n      obj,\n    )\n  })\n  def('toBeNull', function () {\n    const obj = utils.flag(this, 'object')\n    this.assert(\n      obj === null,\n      'expected #{this} to be null',\n      'expected #{this} not to be null',\n      null,\n      obj,\n    )\n  })\n  def('toBeNullable', function () {\n    const obj = utils.flag(this, 'object')\n    this.assert(\n      obj == null,\n      'expected #{this} to be nullish',\n      'expected #{this} not to be nullish',\n      null,\n      obj,\n    )\n  })\n  def('toBeDefined', function () {\n    const obj = utils.flag(this, 'object')\n    this.assert(\n      typeof obj !== 'undefined',\n      'expected #{this} to be defined',\n      'expected #{this} to be undefined',\n      obj,\n    )\n  })\n  def(\n    'toBeTypeOf',\n    function (\n      expected:\n        | 'bigint'\n        | 'boolean'\n        | 'function'\n        | 'number'\n        | 'object'\n        | 'string'\n        | 'symbol'\n        | 'undefined',\n    ) {\n      const actual = typeof this._obj\n      const equal = expected === actual\n      return this.assert(\n        equal,\n        'expected #{this} to be type of #{exp}',\n        'expected #{this} not to be type of #{exp}',\n        expected,\n        actual,\n      )\n    },\n  )\n  def('toBeInstanceOf', function (obj: any) {\n    return this.instanceOf(obj)\n  })\n  def('toHaveLength', function (length: number) {\n    return this.have.length(length)\n  })\n  // destructuring, because it checks `arguments` inside, and value is passing as `undefined`\n  def(\n    'toHaveProperty',\n    function (...args: [property: string | (string | number)[], value?: any]) {\n      if (Array.isArray(args[0])) {\n        args[0] = args[0]\n          .map(key => String(key).replace(/([.[\\]])/g, '\\\\$1'))\n          .join('.')\n      }\n\n      const actual = this._obj as any\n      const [propertyName, expected] = args\n      const getValue = () => {\n        const hasOwn = Object.hasOwn(\n          actual,\n          propertyName,\n        )\n        if (hasOwn) {\n          return { value: actual[propertyName], exists: true }\n        }\n        return utils.getPathInfo(actual, propertyName)\n      }\n      const { value, exists } = getValue()\n      const pass\n        = exists\n          && (args.length === 1 || jestEquals(expected, value, customTesters))\n\n      const valueString\n        = args.length === 1 ? '' : ` with value ${utils.objDisplay(expected)}`\n\n      return this.assert(\n        pass,\n        `expected #{this} to have property \"${propertyName}\"${valueString}`,\n        `expected #{this} to not have property \"${propertyName}\"${valueString}`,\n        expected,\n        exists ? value : undefined,\n      )\n    },\n  )\n  def('toBeCloseTo', function (received: number, precision = 2) {\n    const expected = this._obj\n    let pass = false\n    let expectedDiff = 0\n    let receivedDiff = 0\n\n    if (\n      received === Number.POSITIVE_INFINITY\n      && expected === Number.POSITIVE_INFINITY\n    ) {\n      pass = true\n    }\n    else if (\n      received === Number.NEGATIVE_INFINITY\n      && expected === Number.NEGATIVE_INFINITY\n    ) {\n      pass = true\n    }\n    else {\n      expectedDiff = 10 ** -precision / 2\n      receivedDiff = Math.abs(expected - received)\n      pass = receivedDiff < expectedDiff\n    }\n    return this.assert(\n      pass,\n      `expected #{this} to be close to #{exp}, received difference is ${receivedDiff}, but expected ${expectedDiff}`,\n      `expected #{this} to not be close to #{exp}, received difference is ${receivedDiff}, but expected ${expectedDiff}`,\n      received,\n      expected,\n      false,\n    )\n  })\n\n  function assertIsMock(assertion: any) {\n    if (!isMockFunction(assertion._obj)) {\n      throw new TypeError(\n        `${utils.inspect(assertion._obj)} is not a spy or a call to a spy!`,\n      )\n    }\n  }\n\n  function getSpy(assertion: any) {\n    assertIsMock(assertion)\n    return assertion._obj as MockInstance\n  }\n\n  def(['toHaveBeenCalledTimes', 'toBeCalledTimes'], function (number: number) {\n    const spy = getSpy(this)\n    const spyName = spy.getMockName()\n    const callCount = spy.mock.calls.length\n    return this.assert(\n      callCount === number,\n      `expected \"${spyName}\" to be called #{exp} times, but got ${callCount} times`,\n      `expected \"${spyName}\" to not be called #{exp} times`,\n      number,\n      callCount,\n      false,\n    )\n  })\n  def('toHaveBeenCalledOnce', function () {\n    const spy = getSpy(this)\n    const spyName = spy.getMockName()\n    const callCount = spy.mock.calls.length\n    return this.assert(\n      callCount === 1,\n      `expected \"${spyName}\" to be called once, but got ${callCount} times`,\n      `expected \"${spyName}\" to not be called once`,\n      1,\n      callCount,\n      false,\n    )\n  })\n  def(['toHaveBeenCalled', 'toBeCalled'], function () {\n    const spy = getSpy(this)\n    const spyName = spy.getMockName()\n    const callCount = spy.mock.calls.length\n    const called = callCount > 0\n    const isNot = utils.flag(this, 'negate') as boolean\n    let msg = utils.getMessage(this, [\n      called,\n      `expected \"${spyName}\" to be called at least once`,\n      `expected \"${spyName}\" to not be called at all, but actually been called ${callCount} times`,\n      true,\n      called,\n    ])\n    if (called && isNot) {\n      msg = formatCalls(spy, msg)\n    }\n\n    if ((called && isNot) || (!called && !isNot)) {\n      throw new AssertionError(msg)\n    }\n  })\n\n  // manually compare array elements since `jestEquals` cannot\n  // apply asymmetric matcher to `undefined` array element.\n  function equalsArgumentArray(a: unknown[], b: unknown[]) {\n    return a.length === b.length && a.every((aItem, i) =>\n      jestEquals(aItem, b[i], [...customTesters, iterableEquality]),\n    )\n  }\n\n  def(['toHaveBeenCalledWith', 'toBeCalledWith'], function (...args) {\n    const spy = getSpy(this)\n    const spyName = spy.getMockName()\n    const pass = spy.mock.calls.some(callArg => equalsArgumentArray(callArg, args))\n    const isNot = utils.flag(this, 'negate') as boolean\n\n    const msg = utils.getMessage(this, [\n      pass,\n      `expected \"${spyName}\" to be called with arguments: #{exp}`,\n      `expected \"${spyName}\" to not be called with arguments: #{exp}`,\n      args,\n    ])\n\n    if ((pass && isNot) || (!pass && !isNot)) {\n      throw new AssertionError(formatCalls(spy, msg, args))\n    }\n  })\n  def('toHaveBeenCalledExactlyOnceWith', function (...args) {\n    const spy = getSpy(this)\n    const spyName = spy.getMockName()\n    const callCount = spy.mock.calls.length\n    const hasCallWithArgs = spy.mock.calls.some(callArg => equalsArgumentArray(callArg, args))\n    const pass = hasCallWithArgs && callCount === 1\n    const isNot = utils.flag(this, 'negate') as boolean\n\n    const msg = utils.getMessage(this, [\n      pass,\n      `expected \"${spyName}\" to be called once with arguments: #{exp}`,\n      `expected \"${spyName}\" to not be called once with arguments: #{exp}`,\n      args,\n    ])\n\n    if ((pass && isNot) || (!pass && !isNot)) {\n      throw new AssertionError(formatCalls(spy, msg, args))\n    }\n  })\n  def(\n    'toHaveBeenNthCalledWith',\n    function (times: number, ...args: any[]) {\n      const spy = getSpy(this)\n      const spyName = spy.getMockName()\n      const nthCall = spy.mock.calls[times - 1]\n      const callCount = spy.mock.calls.length\n      const isCalled = times <= callCount\n      this.assert(\n        nthCall && equalsArgumentArray(nthCall, args),\n        `expected ${ordinal(\n          times,\n        )} \"${spyName}\" call to have been called with #{exp}${\n          isCalled ? `` : `, but called only ${callCount} times`\n        }`,\n        `expected ${ordinal(\n          times,\n        )} \"${spyName}\" call to not have been called with #{exp}`,\n        args,\n        nthCall,\n        isCalled,\n      )\n    },\n  )\n  def(\n    'toHaveBeenLastCalledWith',\n    function (...args: any[]) {\n      const spy = getSpy(this)\n      const spyName = spy.getMockName()\n      const lastCall = spy.mock.calls.at(-1)\n\n      this.assert(\n        lastCall && equalsArgumentArray(lastCall, args),\n        `expected last \"${spyName}\" call to have been called with #{exp}`,\n        `expected last \"${spyName}\" call to not have been called with #{exp}`,\n        args,\n        lastCall,\n      )\n    },\n  )\n\n  /**\n   * Used for `toHaveBeenCalledBefore` and `toHaveBeenCalledAfter` to determine if the expected spy was called before the result spy.\n   */\n  function isSpyCalledBeforeAnotherSpy(beforeSpy: MockInstance, afterSpy: MockInstance, failIfNoFirstInvocation: number): boolean {\n    const beforeInvocationCallOrder = beforeSpy.mock.invocationCallOrder\n\n    const afterInvocationCallOrder = afterSpy.mock.invocationCallOrder\n\n    if (beforeInvocationCallOrder.length === 0) {\n      return !failIfNoFirstInvocation\n    }\n\n    if (afterInvocationCallOrder.length === 0) {\n      return false\n    }\n\n    return beforeInvocationCallOrder[0] < afterInvocationCallOrder[0]\n  }\n\n  def(\n    ['toHaveBeenCalledBefore'],\n    function (resultSpy: MockInstance, failIfNoFirstInvocation = true) {\n      const expectSpy = getSpy(this)\n\n      if (!isMockFunction(resultSpy)) {\n        throw new TypeError(\n          `${utils.inspect(resultSpy)} is not a spy or a call to a spy`,\n        )\n      }\n\n      this.assert(\n        isSpyCalledBeforeAnotherSpy(\n          expectSpy,\n          resultSpy,\n          failIfNoFirstInvocation,\n        ),\n        `expected \"${expectSpy.getMockName()}\" to have been called before \"${resultSpy.getMockName()}\"`,\n        `expected \"${expectSpy.getMockName()}\" to not have been called before \"${resultSpy.getMockName()}\"`,\n        resultSpy,\n        expectSpy,\n      )\n    },\n  )\n  def(\n    ['toHaveBeenCalledAfter'],\n    function (resultSpy: MockInstance, failIfNoFirstInvocation = true) {\n      const expectSpy = getSpy(this)\n\n      if (!isMockFunction(resultSpy)) {\n        throw new TypeError(\n          `${utils.inspect(resultSpy)} is not a spy or a call to a spy`,\n        )\n      }\n\n      this.assert(\n        isSpyCalledBeforeAnotherSpy(\n          resultSpy,\n          expectSpy,\n          failIfNoFirstInvocation,\n        ),\n        `expected \"${expectSpy.getMockName()}\" to have been called after \"${resultSpy.getMockName()}\"`,\n        `expected \"${expectSpy.getMockName()}\" to not have been called after \"${resultSpy.getMockName()}\"`,\n        resultSpy,\n        expectSpy,\n      )\n    },\n  )\n  def(\n    ['toThrow', 'toThrowError'],\n    function (expected?: string | Constructable | RegExp | Error) {\n      if (\n        typeof expected === 'string'\n        || typeof expected === 'undefined'\n        || expected instanceof RegExp\n      ) {\n        // Fixes the issue related to `chai` <https://github.com/vitest-dev/vitest/issues/6618>\n        return this.throws(expected === '' ? /^$/ : expected)\n      }\n\n      const obj = this._obj\n      const promise = utils.flag(this, 'promise')\n      const isNot = utils.flag(this, 'negate') as boolean\n      let thrown: any = null\n\n      if (promise === 'rejects') {\n        thrown = obj\n      }\n      // if it got here, it's already resolved\n      // unless it tries to resolve to a function that should throw\n      // called as .resolves.toThrow(Error)\n      else if (promise === 'resolves' && typeof obj !== 'function') {\n        if (!isNot) {\n          const message\n            = utils.flag(this, 'message')\n              || 'expected promise to throw an error, but it didn\\'t'\n          const error = {\n            showDiff: false,\n          }\n          throw new AssertionError(message, error, utils.flag(this, 'ssfi'))\n        }\n        else {\n          return\n        }\n      }\n      else {\n        let isThrow = false\n        try {\n          obj()\n        }\n        catch (err) {\n          isThrow = true\n          thrown = err\n        }\n\n        if (!isThrow && !isNot) {\n          const message\n            = utils.flag(this, 'message')\n              || 'expected function to throw an error, but it didn\\'t'\n          const error = {\n            showDiff: false,\n          }\n          throw new AssertionError(message, error, utils.flag(this, 'ssfi'))\n        }\n      }\n\n      if (typeof expected === 'function') {\n        const name = expected.name || expected.prototype.constructor.name\n        return this.assert(\n          thrown && thrown instanceof expected,\n          `expected error to be instance of ${name}`,\n          `expected error not to be instance of ${name}`,\n          expected,\n          thrown,\n        )\n      }\n\n      if (isError(expected)) {\n        const equal = jestEquals(thrown, expected, [\n          ...customTesters,\n          iterableEquality,\n        ])\n        return this.assert(\n          equal,\n          'expected a thrown error to be #{exp}',\n          'expected a thrown error not to be #{exp}',\n          expected,\n          thrown,\n        )\n      }\n\n      if (\n        typeof expected === 'object'\n        && 'asymmetricMatch' in expected\n        && typeof (expected as any).asymmetricMatch === 'function'\n      ) {\n        const matcher = expected as any as AsymmetricMatcher<any>\n        return this.assert(\n          thrown && matcher.asymmetricMatch(thrown),\n          'expected error to match asymmetric matcher',\n          'expected error not to match asymmetric matcher',\n          matcher,\n          thrown,\n        )\n      }\n\n      const equal = jestEquals(thrown, expected, [\n        ...customTesters,\n        iterableEquality,\n      ])\n      return this.assert(\n        equal,\n        'expected a thrown value to equal #{exp}',\n        'expected a thrown value not to equal #{exp}',\n        expected,\n        thrown,\n      )\n    },\n  )\n\n  interface ReturnMatcher<T extends any[] = []> {\n    name: keyof Assertion | (keyof Assertion)[]\n    condition: (spy: MockInstance, ...args: T) => boolean\n    action: string\n  }\n\n  (\n    [\n      {\n        name: 'toHaveResolved',\n        condition: spy =>\n          spy.mock.settledResults.length > 0\n          && spy.mock.settledResults.some(({ type }) => type === 'fulfilled'),\n        action: 'resolved',\n      },\n      {\n        name: ['toHaveReturned', 'toReturn'],\n        condition: spy =>\n          spy.mock.calls.length > 0\n          && spy.mock.results.some(({ type }) => type !== 'throw'),\n        action: 'called',\n      },\n    ] satisfies ReturnMatcher[]\n  ).forEach(({ name, condition, action }) => {\n    def(name, function () {\n      const spy = getSpy(this)\n      const spyName = spy.getMockName()\n      const pass = condition(spy)\n      this.assert(\n        pass,\n        `expected \"${spyName}\" to be successfully ${action} at least once`,\n        `expected \"${spyName}\" to not be successfully ${action}`,\n        pass,\n        !pass,\n        false,\n      )\n    })\n  });\n  (\n    [\n      {\n        name: 'toHaveResolvedTimes',\n        condition: (spy, times) =>\n          spy.mock.settledResults.reduce(\n            (s, { type }) => (type === 'fulfilled' ? ++s : s),\n            0,\n          ) === times,\n        action: 'resolved',\n      },\n      {\n        name: ['toHaveReturnedTimes', 'toReturnTimes'],\n        condition: (spy, times) =>\n          spy.mock.results.reduce(\n            (s, { type }) => (type === 'throw' ? s : ++s),\n            0,\n          ) === times,\n        action: 'called',\n      },\n    ] satisfies ReturnMatcher<[number]>[]\n  ).forEach(({ name, condition, action }) => {\n    def(name, function (times: number) {\n      const spy = getSpy(this)\n      const spyName = spy.getMockName()\n      const pass = condition(spy, times)\n      this.assert(\n        pass,\n        `expected \"${spyName}\" to be successfully ${action} ${times} times`,\n        `expected \"${spyName}\" to not be successfully ${action} ${times} times`,\n        `expected resolved times: ${times}`,\n        `received resolved times: ${pass}`,\n        false,\n      )\n    })\n  });\n  (\n    [\n      {\n        name: 'toHaveResolvedWith',\n        condition: (spy, value) =>\n          spy.mock.settledResults.some(\n            ({ type, value: result }) =>\n              type === 'fulfilled' && jestEquals(value, result),\n          ),\n        action: 'resolve',\n      },\n      {\n        name: ['toHaveReturnedWith', 'toReturnWith'],\n        condition: (spy, value) =>\n          spy.mock.results.some(\n            ({ type, value: result }) =>\n              type === 'return' && jestEquals(value, result),\n          ),\n        action: 'return',\n      },\n    ] satisfies ReturnMatcher<[any]>[]\n  ).forEach(({ name, condition, action }) => {\n    def(name, function (value: any) {\n      const spy = getSpy(this)\n      const pass = condition(spy, value)\n      const isNot = utils.flag(this, 'negate') as boolean\n\n      if ((pass && isNot) || (!pass && !isNot)) {\n        const spyName = spy.getMockName()\n        const msg = utils.getMessage(this, [\n          pass,\n          `expected \"${spyName}\" to ${action} with: #{exp} at least once`,\n          `expected \"${spyName}\" to not ${action} with: #{exp}`,\n          value,\n        ])\n\n        const results\n          = action === 'return' ? spy.mock.results : spy.mock.settledResults\n        throw new AssertionError(formatReturns(spy, results, msg, value))\n      }\n    })\n  });\n  (\n    [\n      {\n        name: 'toHaveLastResolvedWith',\n        condition: (spy, value) => {\n          const result\n            = spy.mock.settledResults.at(-1)\n          return Boolean(\n            result\n            && result.type === 'fulfilled'\n            && jestEquals(result.value, value),\n          )\n        },\n        action: 'resolve',\n      },\n      {\n        name: 'toHaveLastReturnedWith',\n        condition: (spy, value) => {\n          const result = spy.mock.results.at(-1)\n          return Boolean(\n            result\n            && result.type === 'return'\n            && jestEquals(result.value, value),\n          )\n        },\n        action: 'return',\n      },\n    ] satisfies ReturnMatcher<[any]>[]\n  ).forEach(({ name, condition, action }) => {\n    def(name, function (value: any) {\n      const spy = getSpy(this)\n      const results\n        = action === 'return' ? spy.mock.results : spy.mock.settledResults\n      const result = results.at(-1)\n      const spyName = spy.getMockName()\n      this.assert(\n        condition(spy, value),\n        `expected last \"${spyName}\" call to ${action} #{exp}`,\n        `expected last \"${spyName}\" call to not ${action} #{exp}`,\n        value,\n        result?.value,\n      )\n    })\n  });\n  (\n    [\n      {\n        name: 'toHaveNthResolvedWith',\n        condition: (spy, index, value) => {\n          const result = spy.mock.settledResults[index - 1]\n          return (\n            result\n            && result.type === 'fulfilled'\n            && jestEquals(result.value, value)\n          )\n        },\n        action: 'resolve',\n      },\n      {\n        name: 'toHaveNthReturnedWith',\n        condition: (spy, index, value) => {\n          const result = spy.mock.results[index - 1]\n          return (\n            result\n            && result.type === 'return'\n            && jestEquals(result.value, value)\n          )\n        },\n        action: 'return',\n      },\n    ] satisfies ReturnMatcher<[number, any]>[]\n  ).forEach(({ name, condition, action }) => {\n    def(name, function (nthCall: number, value: any) {\n      const spy = getSpy(this)\n      const spyName = spy.getMockName()\n      const results\n        = action === 'return' ? spy.mock.results : spy.mock.settledResults\n      const result = results[nthCall - 1]\n      const ordinalCall = `${ordinal(nthCall)} call`\n\n      this.assert(\n        condition(spy, nthCall, value),\n        `expected ${ordinalCall} \"${spyName}\" call to ${action} #{exp}`,\n        `expected ${ordinalCall} \"${spyName}\" call to not ${action} #{exp}`,\n        value,\n        result?.value,\n      )\n    })\n  })\n\n  // @ts-expect-error @internal\n  def('withContext', function (this: any, context: Record<string, any>) {\n    for (const key in context) {\n      utils.flag(this, key, context[key])\n    }\n    return this\n  })\n\n  utils.addProperty(\n    chai.Assertion.prototype,\n    'resolves',\n    function __VITEST_RESOLVES__(this: any) {\n      const error = new Error('resolves')\n      utils.flag(this, 'promise', 'resolves')\n      utils.flag(this, 'error', error)\n      const test: Test = utils.flag(this, 'vitest-test')\n      const obj = utils.flag(this, 'object')\n\n      if (utils.flag(this, 'poll')) {\n        throw new SyntaxError(\n          `expect.poll() is not supported in combination with .resolves`,\n        )\n      }\n\n      if (typeof obj?.then !== 'function') {\n        throw new TypeError(\n          `You must provide a Promise to expect() when using .resolves, not '${typeof obj}'.`,\n        )\n      }\n\n      const proxy: any = new Proxy(this, {\n        get: (target, key, receiver) => {\n          const result = Reflect.get(target, key, receiver)\n\n          if (typeof result !== 'function') {\n            return result instanceof chai.Assertion ? proxy : result\n          }\n\n          return (...args: any[]) => {\n            utils.flag(this, '_name', key)\n            const promise = Promise.resolve(obj).then(\n              (value: any) => {\n                utils.flag(this, 'object', value)\n                return result.call(this, ...args)\n              },\n              (err: any) => {\n                const _error = new AssertionError(\n                  `promise rejected \"${utils.inspect(\n                    err,\n                  )}\" instead of resolving`,\n                  { showDiff: false },\n                ) as Error\n                _error.cause = err\n                throw _error\n              },\n            ).catch((err: any) => {\n              if (isError(err) && error.stack) {\n                err.stack = error.stack.replace(\n                  error.message,\n                  err.message,\n                )\n              }\n              throw err\n            })\n\n            return recordAsyncExpect(\n              test,\n              promise,\n              createAssertionMessage(utils, this, !!args.length),\n              error,\n              utils.flag(this, 'soft'),\n            )\n          }\n        },\n      })\n\n      return proxy\n    },\n  )\n\n  utils.addProperty(\n    chai.Assertion.prototype,\n    'rejects',\n    function __VITEST_REJECTS__(this: any) {\n      const error = new Error('rejects')\n      utils.flag(this, 'promise', 'rejects')\n      utils.flag(this, 'error', error)\n      const test: Test = utils.flag(this, 'vitest-test')\n      const obj = utils.flag(this, 'object')\n      const wrapper = typeof obj === 'function' ? obj() : obj // for jest compat\n\n      if (utils.flag(this, 'poll')) {\n        throw new SyntaxError(\n          `expect.poll() is not supported in combination with .rejects`,\n        )\n      }\n\n      if (typeof wrapper?.then !== 'function') {\n        throw new TypeError(\n          `You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.`,\n        )\n      }\n\n      const proxy: any = new Proxy(this, {\n        get: (target, key, receiver) => {\n          const result = Reflect.get(target, key, receiver)\n\n          if (typeof result !== 'function') {\n            return result instanceof chai.Assertion ? proxy : result\n          }\n\n          return (...args: any[]) => {\n            utils.flag(this, '_name', key)\n            const promise = Promise.resolve(wrapper).then(\n              (value: any) => {\n                const _error = new AssertionError(\n                  `promise resolved \"${utils.inspect(\n                    value,\n                  )}\" instead of rejecting`,\n                  {\n                    showDiff: true,\n                    expected: new Error('rejected promise'),\n                    actual: value,\n                  },\n                ) as any\n                throw _error\n              },\n              (err: any) => {\n                utils.flag(this, 'object', err)\n                return result.call(this, ...args)\n              },\n            ).catch((err: any) => {\n              if (isError(err) && error.stack) {\n                err.stack = error.stack.replace(\n                  error.message,\n                  err.message,\n                )\n              }\n              throw err\n            })\n\n            return recordAsyncExpect(\n              test,\n              promise,\n              createAssertionMessage(utils, this, !!args.length),\n              error,\n              utils.flag(this, 'soft'),\n            )\n          }\n        },\n      })\n\n      return proxy\n    },\n  )\n}\n\nfunction formatCalls(spy: MockInstance, msg: string, showActualCall?: any) {\n  if (spy.mock.calls.length) {\n    msg += c.gray(\n      `\\n\\nReceived:\\n\\n${spy.mock.calls\n        .map((callArg, i) => {\n          let methodCall = c.bold(\n            `  ${ordinal(i + 1)} ${spy.getMockName()} call:\\n\\n`,\n          )\n          if (showActualCall) {\n            methodCall += diff(showActualCall, callArg, {\n              omitAnnotationLines: true,\n            })\n          }\n          else {\n            methodCall += stringify(callArg)\n              .split('\\n')\n              .map(line => `    ${line}`)\n              .join('\\n')\n          }\n\n          methodCall += '\\n'\n          return methodCall\n        })\n        .join('\\n')}`,\n    )\n  }\n  msg += c.gray(\n    `\\n\\nNumber of calls: ${c.bold(spy.mock.calls.length)}\\n`,\n  )\n  return msg\n}\n\nfunction formatReturns(\n  spy: MockInstance,\n  results: MockResult<any>[] | MockSettledResult<any>[],\n  msg: string,\n  showActualReturn?: any,\n) {\n  if (results.length) {\n    msg += c.gray(\n      `\\n\\nReceived:\\n\\n${results\n        .map((callReturn, i) => {\n          let methodCall = c.bold(\n            `  ${ordinal(i + 1)} ${spy.getMockName()} call return:\\n\\n`,\n          )\n          if (showActualReturn) {\n            methodCall += diff(showActualReturn, callReturn.value, {\n              omitAnnotationLines: true,\n            })\n          }\n          else {\n            methodCall += stringify(callReturn)\n              .split('\\n')\n              .map(line => `    ${line}`)\n              .join('\\n')\n          }\n\n          methodCall += '\\n'\n          return methodCall\n        })\n        .join('\\n')}`,\n    )\n  }\n  msg += c.gray(\n    `\\n\\nNumber of calls: ${c.bold(spy.mock.calls.length)}\\n`,\n  )\n  return msg\n}\n"
  },
  {
    "path": "packages/expect/src/jest-extend.ts",
    "content": "import type { Test } from '@vitest/runner'\nimport type {\n  ChaiPlugin,\n  ExpectStatic,\n  MatchersObject,\n  MatcherState,\n  SyncExpectationResult,\n} from './types'\nimport { use, util } from 'chai'\nimport { ASYMMETRIC_MATCHERS_OBJECT, JEST_MATCHERS_OBJECT } from './constants'\nimport { AsymmetricMatcher } from './jest-asymmetric-matchers'\nimport {\n  diff,\n  getCustomEqualityTesters,\n  getMatcherUtils,\n  stringify,\n} from './jest-matcher-utils'\nimport { equals, iterableEquality, subsetEquality } from './jest-utils'\nimport { getState } from './state'\nimport { wrapAssertion } from './utils'\n\nfunction getMatcherState(\n  assertion: Chai.AssertionStatic & Chai.Assertion,\n  expect: ExpectStatic,\n) {\n  const obj = assertion._obj\n  const isNot = util.flag(assertion, 'negate') as boolean\n  const promise = util.flag(assertion, 'promise') || ''\n  const customMessage = util.flag(assertion, 'message') as string | undefined\n  const jestUtils = {\n    ...getMatcherUtils(),\n    diff,\n    stringify,\n    iterableEquality,\n    subsetEquality,\n  }\n  let task: Test | undefined = util.flag(assertion, 'vitest-test')\n  const currentTestName = task?.fullTestName ?? ''\n\n  if (task?.type !== 'test') {\n    task = undefined\n  }\n\n  const matcherState: MatcherState = {\n    ...getState(expect),\n    task,\n    currentTestName,\n    customTesters: getCustomEqualityTesters(),\n    isNot,\n    utils: jestUtils,\n    promise,\n    equals,\n    // needed for built-in jest-snapshots, but we don't use it\n    suppressedErrors: [],\n    soft: util.flag(assertion, 'soft') as boolean | undefined,\n    poll: util.flag(assertion, 'poll') as boolean | undefined,\n  }\n\n  return {\n    state: matcherState,\n    isNot,\n    obj,\n    customMessage,\n  }\n}\n\nclass JestExtendError extends Error {\n  constructor(message: string, public actual?: any, public expected?: any) {\n    super(message)\n  }\n}\n\nfunction JestExtendPlugin(\n  c: Chai.ChaiStatic,\n  expect: ExpectStatic,\n  matchers: MatchersObject,\n): ChaiPlugin {\n  return (_, utils) => {\n    Object.entries(matchers).forEach(\n      ([expectAssertionName, expectAssertion]) => {\n        function expectWrapper(\n          this: Chai.AssertionStatic & Chai.Assertion,\n          ...args: any[]\n        ) {\n          const { state, isNot, obj, customMessage } = getMatcherState(this, expect)\n\n          const result = expectAssertion.call(state, obj, ...args)\n\n          if (\n            result\n            && typeof result === 'object'\n            && typeof (result as any).then === 'function'\n          ) {\n            const thenable = result as PromiseLike<SyncExpectationResult>\n            return thenable.then(({ pass, message, actual, expected }) => {\n              if ((pass && isNot) || (!pass && !isNot)) {\n                const errorMessage = customMessage != null\n                  ? customMessage\n                  : message()\n                throw new JestExtendError(errorMessage, actual, expected)\n              }\n            })\n          }\n\n          const { pass, message, actual, expected } = result as SyncExpectationResult\n\n          if ((pass && isNot) || (!pass && !isNot)) {\n            const errorMessage = customMessage != null\n              ? customMessage\n              : message()\n            throw new JestExtendError(errorMessage, actual, expected)\n          }\n        }\n\n        const softWrapper = wrapAssertion(utils, expectAssertionName, expectWrapper)\n        utils.addMethod(\n          (globalThis as any)[JEST_MATCHERS_OBJECT].matchers,\n          expectAssertionName,\n          softWrapper,\n        )\n        utils.addMethod(\n          c.Assertion.prototype,\n          expectAssertionName,\n          softWrapper,\n        )\n\n        class CustomMatcher extends AsymmetricMatcher<[unknown, ...unknown[]]> {\n          constructor(inverse = false, ...sample: [unknown, ...unknown[]]) {\n            super(sample, inverse)\n          }\n\n          asymmetricMatch(other: unknown) {\n            const { pass } = expectAssertion.call(\n              this.getMatcherContext(expect),\n              other,\n              ...this.sample,\n            ) as SyncExpectationResult\n\n            return this.inverse ? !pass : pass\n          }\n\n          toString() {\n            return `${this.inverse ? 'not.' : ''}${expectAssertionName}`\n          }\n\n          getExpectedType() {\n            return 'any'\n          }\n\n          toAsymmetricMatcher() {\n            return `${this.toString()}<${this.sample.map(item => stringify(item)).join(', ')}>`\n          }\n        }\n\n        const customMatcher = (...sample: [unknown, ...unknown[]]) =>\n          new CustomMatcher(false, ...sample)\n\n        Object.defineProperty(expect, expectAssertionName, {\n          configurable: true,\n          enumerable: true,\n          value: customMatcher,\n          writable: true,\n        })\n\n        Object.defineProperty(expect.not, expectAssertionName, {\n          configurable: true,\n          enumerable: true,\n          value: (...sample: [unknown, ...unknown[]]) =>\n            new CustomMatcher(true, ...sample),\n          writable: true,\n        })\n\n        // keep track of asymmetric matchers on global so that it can be copied over to local context's `expect`.\n        // note that the negated variant is automatically shared since it's assigned on the single `expect.not` object.\n        Object.defineProperty(\n          (globalThis as any)[ASYMMETRIC_MATCHERS_OBJECT],\n          expectAssertionName,\n          {\n            configurable: true,\n            enumerable: true,\n            value: customMatcher,\n            writable: true,\n          },\n        )\n      },\n    )\n  }\n}\n\nexport const JestExtend: ChaiPlugin = (chai, utils) => {\n  utils.addMethod(\n    chai.expect,\n    'extend',\n    (expect: ExpectStatic, expects: MatchersObject) => {\n      use(JestExtendPlugin(chai, expect, expects))\n    },\n  )\n}\n"
  },
  {
    "path": "packages/expect/src/jest-matcher-utils.ts",
    "content": "import type { Formatter } from 'tinyrainbow'\nimport type { MatcherHintOptions, Tester } from './types'\nimport { diff, printDiffOrStringify } from '@vitest/utils/diff'\nimport { stringify } from '@vitest/utils/display'\nimport { getType } from '@vitest/utils/helpers'\nimport c from 'tinyrainbow'\nimport { JEST_MATCHERS_OBJECT } from './constants'\n\nexport { diff } from '@vitest/utils/diff'\nexport { stringify }\n\nconst EXPECTED_COLOR = c.green\nconst RECEIVED_COLOR = c.red\nconst INVERTED_COLOR = c.inverse\nconst BOLD_WEIGHT = c.bold\nconst DIM_COLOR = c.dim\n\nfunction matcherHint(\n  matcherName: string,\n  received = 'received',\n  expected = 'expected',\n  options: MatcherHintOptions = {},\n): string {\n  const {\n    comment = '',\n    isDirectExpectCall = false, // seems redundant with received === ''\n    isNot = false,\n    promise = '',\n    secondArgument = '',\n    expectedColor = EXPECTED_COLOR,\n    receivedColor = RECEIVED_COLOR,\n    secondArgumentColor = EXPECTED_COLOR,\n  } = options\n  let hint = ''\n  let dimString = 'expect' // concatenate adjacent dim substrings\n\n  if (!isDirectExpectCall && received !== '') {\n    hint += DIM_COLOR(`${dimString}(`) + receivedColor(received)\n    dimString = ')'\n  }\n\n  if (promise !== '') {\n    hint += DIM_COLOR(`${dimString}.`) + promise\n    dimString = ''\n  }\n\n  if (isNot) {\n    hint += `${DIM_COLOR(`${dimString}.`)}not`\n    dimString = ''\n  }\n\n  if (matcherName.includes('.')) {\n    // Old format: for backward compatibility,\n    // especially without promise or isNot options\n    dimString += matcherName\n  }\n  else {\n    // New format: omit period from matcherName arg\n    hint += DIM_COLOR(`${dimString}.`) + matcherName\n    dimString = ''\n  }\n\n  if (expected === '') {\n    dimString += '()'\n  }\n  else {\n    hint += DIM_COLOR(`${dimString}(`) + expectedColor(expected)\n    if (secondArgument) {\n      hint += DIM_COLOR(', ') + secondArgumentColor(secondArgument)\n    }\n    dimString = ')'\n  }\n\n  if (comment !== '') {\n    dimString += ` // ${comment}`\n  }\n\n  if (dimString !== '') {\n    hint += DIM_COLOR(dimString)\n  }\n\n  return hint\n}\n\nconst SPACE_SYMBOL = '\\u{00B7}' // middle dot\n\n// Instead of inverse highlight which now implies a change,\n// replace common spaces with middle dot at the end of any line.\nfunction replaceTrailingSpaces(text: string): string {\n  return text.replace(/\\s+$/gm, spaces => SPACE_SYMBOL.repeat(spaces.length))\n}\n\nfunction printReceived(object: unknown): string {\n  return RECEIVED_COLOR(replaceTrailingSpaces(stringify(object)))\n}\nfunction printExpected(value: unknown): string {\n  return EXPECTED_COLOR(replaceTrailingSpaces(stringify(value)))\n}\n\nexport function getMatcherUtils(): {\n  EXPECTED_COLOR: Formatter\n  RECEIVED_COLOR: Formatter\n  INVERTED_COLOR: Formatter\n  BOLD_WEIGHT: Formatter\n  DIM_COLOR: Formatter\n  diff: typeof diff\n  matcherHint: typeof matcherHint\n  printReceived: typeof printReceived\n  printExpected: typeof printExpected\n  printDiffOrStringify: typeof printDiffOrStringify\n  printWithType: typeof printWithType\n} {\n  return {\n    EXPECTED_COLOR,\n    RECEIVED_COLOR,\n    INVERTED_COLOR,\n    BOLD_WEIGHT,\n    DIM_COLOR,\n\n    diff,\n    matcherHint,\n    printReceived,\n    printExpected,\n    printDiffOrStringify,\n    printWithType,\n  }\n}\n\nexport function printWithType<T>(\n  name: string,\n  value: T,\n  print: (value: T) => string,\n): string {\n  const type = getType(value)\n  const hasType\n    = type !== 'null' && type !== 'undefined'\n      ? `${name} has type:  ${type}\\n`\n      : ''\n  const hasValue = `${name} has value: ${print(value)}`\n  return hasType + hasValue\n}\n\nexport function addCustomEqualityTesters(newTesters: Array<Tester>): void {\n  if (!Array.isArray(newTesters)) {\n    throw new TypeError(\n      `expect.customEqualityTesters: Must be set to an array of Testers. Was given \"${getType(\n        newTesters,\n      )}\"`,\n    )\n  }\n\n  (globalThis as any)[JEST_MATCHERS_OBJECT].customEqualityTesters.push(\n    ...newTesters,\n  )\n}\n\nexport function getCustomEqualityTesters(): Array<Tester> {\n  return (globalThis as any)[JEST_MATCHERS_OBJECT].customEqualityTesters\n}\n"
  },
  {
    "path": "packages/expect/src/jest-utils.ts",
    "content": "/*\nCopyright (c) 2008-2016 Pivotal Labs\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n*/\n\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type { AsymmetricMatcher } from './jest-asymmetric-matchers'\nimport type { Tester, TesterContext } from './types'\nimport { isObject } from '@vitest/utils/helpers'\n\n// Extracted out of jasmine 2.5.2\nexport function equals(\n  a: unknown,\n  b: unknown,\n  customTesters?: Array<Tester>,\n  strictCheck?: boolean,\n): boolean {\n  customTesters = customTesters || []\n  return eq(a, b, [], [], customTesters, strictCheck ? hasKey : hasDefinedKey)\n}\n\nconst functionToString = Function.prototype.toString\n\nexport function isAsymmetric(obj: any): obj is AsymmetricMatcher<any> {\n  return (\n    !!obj\n    && typeof obj === 'object'\n    && 'asymmetricMatch' in obj\n    && isA('Function', obj.asymmetricMatch)\n  )\n}\n\nexport function hasAsymmetric(obj: any, seen: Set<any> = new Set()): boolean {\n  if (seen.has(obj)) {\n    return false\n  }\n  seen.add(obj)\n  if (isAsymmetric(obj)) {\n    return true\n  }\n  if (Array.isArray(obj)) {\n    return obj.some(i => hasAsymmetric(i, seen))\n  }\n  if (obj instanceof Set) {\n    return Array.from(obj).some(i => hasAsymmetric(i, seen))\n  }\n  if (isObject(obj)) {\n    return Object.values(obj).some(v => hasAsymmetric(v, seen))\n  }\n  return false\n}\n\nfunction asymmetricMatch(a: any, b: any, customTesters: Array<Tester>) {\n  const asymmetricA = isAsymmetric(a)\n  const asymmetricB = isAsymmetric(b)\n\n  if (asymmetricA && asymmetricB) {\n    return undefined\n  }\n\n  if (asymmetricA) {\n    return a.asymmetricMatch(b, customTesters)\n  }\n\n  if (asymmetricB) {\n    return b.asymmetricMatch(a, customTesters)\n  }\n}\n\n// https://github.com/jestjs/jest/blob/905bcbced3d40cdf7aadc4cdf6fb731c4bb3dbe3/packages/expect-utils/src/utils.ts#L509\nexport function isError(value: unknown): value is Error {\n  if (typeof Error.isError === 'function') {\n    return Error.isError(value)\n  }\n  switch (Object.prototype.toString.call(value)) {\n    case '[object Error]':\n    case '[object Exception]':\n    case '[object DOMException]':\n      return true\n    default:\n      return value instanceof Error\n  }\n};\n\n// Equality function lovingly adapted from isEqual in\n//   [Underscore](http://underscorejs.org)\nfunction eq(\n  a: any,\n  b: any,\n  aStack: Array<unknown>,\n  bStack: Array<unknown>,\n  customTesters: Array<Tester>,\n  hasKey: any,\n): boolean {\n  let result = true\n\n  const asymmetricResult = asymmetricMatch(a, b, customTesters)\n  if (asymmetricResult !== undefined) {\n    return asymmetricResult\n  }\n\n  const testerContext: TesterContext = { equals }\n  for (let i = 0; i < customTesters.length; i++) {\n    const customTesterResult = customTesters[i].call(\n      testerContext,\n      a,\n      b,\n      customTesters,\n    )\n    if (customTesterResult !== undefined) {\n      return customTesterResult\n    }\n  }\n\n  if (typeof URL === 'function' && a instanceof URL && b instanceof URL) {\n    return a.href === b.href\n  }\n\n  if (Object.is(a, b)) {\n    return true\n  }\n\n  // A strict comparison is necessary because `null == undefined`.\n  if (a === null || b === null) {\n    return a === b\n  }\n\n  const className = Object.prototype.toString.call(a)\n  if (className !== Object.prototype.toString.call(b)) {\n    return false\n  }\n\n  switch (className) {\n    case '[object Boolean]':\n    case '[object String]':\n    case '[object Number]':\n      if (typeof a !== typeof b) {\n        // One is a primitive, one a `new Primitive()`\n        return false\n      }\n      else if (typeof a !== 'object' && typeof b !== 'object') {\n        // both are proper primitives\n        return Object.is(a, b)\n      }\n      else {\n        // both are `new Primitive()`s\n        return Object.is(a.valueOf(), b.valueOf())\n      }\n    case '[object Date]': {\n      const numA = +a\n      const numB = +b\n      // Coerce dates to numeric primitive values. Dates are compared by their\n      // millisecond representations. Note that invalid dates with millisecond representations\n      // of `NaN` are equivalent.\n      return numA === numB || (Number.isNaN(numA) && Number.isNaN(numB))\n    }\n    // RegExps are compared by their source patterns and flags.\n    case '[object RegExp]':\n      return a.source === b.source && a.flags === b.flags\n    case '[object Temporal.Instant]':\n    case '[object Temporal.ZonedDateTime]':\n    case '[object Temporal.PlainDateTime]':\n    case '[object Temporal.PlainDate]':\n    case '[object Temporal.PlainTime]':\n    case '[object Temporal.PlainYearMonth]':\n    case '[object Temporal.PlainMonthDay]':\n      return a.equals(b)\n    case '[object Temporal.Duration]':\n      return a.toString() === b.toString()\n  }\n  if (typeof a !== 'object' || typeof b !== 'object') {\n    return false\n  }\n\n  // Use DOM3 method isEqualNode (IE>=9)\n  if (isDomNode(a) && isDomNode(b)) {\n    return a.isEqualNode(b)\n  }\n\n  // Used to detect circular references.\n  let length = aStack.length\n  while (length--) {\n    // Linear search. Performance is inversely proportional to the number of\n    // unique nested structures.\n    // circular references at same depth are equal\n    // circular reference is not equal to non-circular one\n    if (aStack[length] === a) {\n      return bStack[length] === b\n    }\n    else if (bStack[length] === b) {\n      return false\n    }\n  }\n  // Add the first object to the stack of traversed objects.\n  aStack.push(a)\n  bStack.push(b)\n  // Recursively compare objects and arrays.\n  // Compare array lengths to determine if a deep comparison is necessary.\n  if (className === '[object Array]' && a.length !== b.length) {\n    return false\n  }\n\n  if (isError(a) && isError(b)) {\n    try {\n      return isErrorEqual(a, b, aStack, bStack, customTesters, hasKey)\n    }\n    finally {\n      aStack.pop()\n      bStack.pop()\n    }\n  }\n\n  // Deep compare objects.\n  const aKeys = keys(a, hasKey)\n  let key\n  let size = aKeys.length\n\n  // Ensure that both objects contain the same number of properties before comparing deep equality.\n  if (keys(b, hasKey).length !== size) {\n    return false\n  }\n\n  while (size--) {\n    key = aKeys[size]\n\n    // Deep compare each member\n    result\n      = hasKey(b, key)\n        && eq(a[key], b[key], aStack, bStack, customTesters, hasKey)\n\n    if (!result) {\n      return false\n    }\n  }\n  // Remove the first object from the stack of traversed objects.\n  aStack.pop()\n  bStack.pop()\n\n  return result\n}\n\nfunction isErrorEqual(\n  a: Error,\n  b: Error,\n  aStack: Array<unknown>,\n  bStack: Array<unknown>,\n  customTesters: Array<Tester>,\n  hasKey: any,\n) {\n  // https://nodejs.org/docs/latest-v22.x/api/assert.html#comparison-details\n  // - [[Prototype]] of objects are compared using the === operator.\n  // - Only enumerable \"own\" properties are considered.\n  // - Error names, messages, causes, and errors are always compared, even if these are not enumerable properties. errors is also compared.\n\n  let result = (\n    Object.prototype.toString.call(a) === Object.prototype.toString.call(b)\n    && a.name === b.name\n    && a.message === b.message\n  )\n  // check Error.cause asymmetrically\n  if (typeof b.cause !== 'undefined') {\n    result &&= eq(a.cause, b.cause, aStack, bStack, customTesters, hasKey)\n  }\n  // AggregateError.errors\n  if (a instanceof AggregateError && b instanceof AggregateError) {\n    result &&= eq(a.errors, b.errors, aStack, bStack, customTesters, hasKey)\n  }\n  // spread to compare enumerable properties\n  result &&= eq({ ...a }, { ...b }, aStack, bStack, customTesters, hasKey)\n  return result\n}\n\nfunction keys(obj: object, hasKey: (obj: object, key: string) => boolean) {\n  const keys = []\n\n  for (const key in obj) {\n    if (hasKey(obj, key)) {\n      keys.push(key)\n    }\n  }\n  return keys.concat(\n    (Object.getOwnPropertySymbols(obj) as Array<any>).filter(\n      symbol =>\n        (Object.getOwnPropertyDescriptor(obj, symbol) as PropertyDescriptor)\n          .enumerable,\n    ),\n  )\n}\n\nfunction hasDefinedKey(obj: any, key: string) {\n  return hasKey(obj, key) && obj[key] !== undefined\n}\n\nfunction hasKey(obj: any, key: string) {\n  return Object.hasOwn(obj, key)\n}\n\nexport function isA(typeName: string, value: unknown): boolean {\n  return Object.prototype.toString.apply(value) === `[object ${typeName}]`\n}\n\nfunction isDomNode(obj: any): boolean {\n  return (\n    obj !== null\n    && typeof obj === 'object'\n    && 'nodeType' in obj\n    && typeof obj.nodeType === 'number'\n    && 'nodeName' in obj\n    && typeof obj.nodeName === 'string'\n    && 'isEqualNode' in obj\n    && typeof obj.isEqualNode === 'function'\n  )\n}\n\nexport function fnNameFor(func: Function): string {\n  if (func.name) {\n    return func.name\n  }\n\n  const matches = functionToString\n    .call(func)\n    .match(/^(?:async)?\\s*function\\s*(?:\\*\\s*)?([\\w$]+)\\s*\\(/)\n  return matches ? matches[1] : '<anonymous>'\n}\n\nfunction getPrototype(obj: object) {\n  if (Object.getPrototypeOf) {\n    return Object.getPrototypeOf(obj)\n  }\n\n  if (obj.constructor.prototype === obj) {\n    return null\n  }\n\n  return obj.constructor.prototype\n}\n\nexport function hasProperty(obj: object | null, property: string): boolean {\n  if (!obj) {\n    return false\n  }\n\n  if (Object.hasOwn(obj, property)) {\n    return true\n  }\n\n  return hasProperty(getPrototype(obj), property)\n}\n\n// SENTINEL constants are from https://github.com/facebook/immutable-js\nconst IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@'\nconst IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@'\nconst IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@'\nconst IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@'\nconst IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@'\n\nexport function isImmutableUnorderedKeyed(maybeKeyed: any): boolean {\n  return !!(\n    maybeKeyed\n    && maybeKeyed[IS_KEYED_SENTINEL]\n    && !maybeKeyed[IS_ORDERED_SENTINEL]\n  )\n}\n\nexport function isImmutableUnorderedSet(maybeSet: any): boolean {\n  return !!(\n    maybeSet\n    && maybeSet[IS_SET_SENTINEL]\n    && !maybeSet[IS_ORDERED_SENTINEL]\n  )\n}\n\nfunction isObjectLiteral(source: unknown): source is Record<string, unknown> {\n  return source != null && typeof source === 'object' && !Array.isArray(source)\n}\n\nfunction isImmutableList(source: unknown): boolean {\n  return Boolean(source && isObjectLiteral(source) && source[IS_LIST_SENTINEL])\n}\n\nfunction isImmutableOrderedKeyed(source: unknown): boolean {\n  return Boolean(\n    source\n    && isObjectLiteral(source)\n    && source[IS_KEYED_SENTINEL]\n    && source[IS_ORDERED_SENTINEL],\n  )\n}\n\nfunction isImmutableOrderedSet(source: unknown): boolean {\n  return Boolean(\n    source\n    && isObjectLiteral(source)\n    && source[IS_SET_SENTINEL]\n    && source[IS_ORDERED_SENTINEL],\n  )\n}\n\nfunction isImmutableRecord(source: unknown): boolean {\n  return Boolean(source && isObjectLiteral(source) && source[IS_RECORD_SYMBOL])\n}\n\n/**\n * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\nconst IteratorSymbol = Symbol.iterator\n\nfunction hasIterator(object: any) {\n  return !!(object != null && object[IteratorSymbol])\n}\n\nexport function iterableEquality(\n  a: any,\n  b: any,\n  customTesters: Array<Tester> = [],\n  aStack: Array<any> = [],\n  bStack: Array<any> = [],\n): boolean | undefined {\n  if (\n    typeof a !== 'object'\n    || typeof b !== 'object'\n    || Array.isArray(a)\n    || Array.isArray(b)\n    || !hasIterator(a)\n    || !hasIterator(b)\n  ) {\n    return undefined\n  }\n\n  if (a.constructor !== b.constructor) {\n    return false\n  }\n\n  let length = aStack.length\n  while (length--) {\n    // Linear search. Performance is inversely proportional to the number of\n    // unique nested structures.\n    // circular references at same depth are equal\n    // circular reference is not equal to non-circular one\n    if (aStack[length] === a) {\n      return bStack[length] === b\n    }\n  }\n  aStack.push(a)\n  bStack.push(b)\n\n  const filteredCustomTesters: Array<Tester> = [\n    ...customTesters.filter(t => t !== iterableEquality),\n    iterableEqualityWithStack,\n  ]\n\n  function iterableEqualityWithStack(a: any, b: any) {\n    return iterableEquality(a, b, [...customTesters], [...aStack], [...bStack])\n  }\n\n  if (a.size !== undefined) {\n    if (a.size !== b.size) {\n      return false\n    }\n    else if (isA('Set', a) || isImmutableUnorderedSet(a)) {\n      let allFound = true\n      for (const aValue of a) {\n        if (!b.has(aValue)) {\n          let has = false\n          for (const bValue of b) {\n            const isEqual = equals(aValue, bValue, filteredCustomTesters)\n            if (isEqual === true) {\n              has = true\n            }\n          }\n\n          if (has === false) {\n            allFound = false\n            break\n          }\n        }\n      }\n      // Remove the first value from the stack of traversed values.\n      aStack.pop()\n      bStack.pop()\n      return allFound\n    }\n    else if (isA('Map', a) || isImmutableUnorderedKeyed(a)) {\n      let allFound = true\n      for (const aEntry of a) {\n        if (\n          !b.has(aEntry[0])\n          || !equals(aEntry[1], b.get(aEntry[0]), filteredCustomTesters)\n        ) {\n          let has = false\n          for (const bEntry of b) {\n            const matchedKey = equals(\n              aEntry[0],\n              bEntry[0],\n              filteredCustomTesters,\n            )\n\n            let matchedValue = false\n            if (matchedKey === true) {\n              matchedValue = equals(\n                aEntry[1],\n                bEntry[1],\n                filteredCustomTesters,\n              )\n            }\n\n            if (matchedValue === true) {\n              has = true\n            }\n          }\n\n          if (has === false) {\n            allFound = false\n            break\n          }\n        }\n      }\n      // Remove the first value from the stack of traversed values.\n      aStack.pop()\n      bStack.pop()\n      return allFound\n    }\n  }\n\n  const bIterator = b[IteratorSymbol]()\n\n  for (const aValue of a) {\n    const nextB = bIterator.next()\n    if (nextB.done || !equals(aValue, nextB.value, filteredCustomTesters)) {\n      return false\n    }\n  }\n  if (!bIterator.next().done) {\n    return false\n  }\n\n  if (\n    !isImmutableList(a)\n    && !isImmutableOrderedKeyed(a)\n    && !isImmutableOrderedSet(a)\n    && !isImmutableRecord(a)\n  ) {\n    const aEntries = Object.entries(a)\n    const bEntries = Object.entries(b)\n    if (!equals(aEntries, bEntries, filteredCustomTesters)) {\n      return false\n    }\n  }\n\n  // Remove the first value from the stack of traversed values.\n  aStack.pop()\n  bStack.pop()\n  return true\n}\n\n/**\n * Checks if `hasOwnProperty(object, key)` up the prototype chain, stopping at `Object.prototype`.\n */\nfunction hasPropertyInObject(object: object, key: string | symbol): boolean {\n  const shouldTerminate\n    = !object || typeof object !== 'object' || object === Object.prototype\n\n  if (shouldTerminate) {\n    return false\n  }\n\n  return (\n    Object.hasOwn(object, key)\n    || hasPropertyInObject(Object.getPrototypeOf(object), key)\n  )\n}\n\nfunction isObjectWithKeys(a: any) {\n  return (\n    isObject(a)\n    && !isError(a)\n    && !Array.isArray(a)\n    && !(a instanceof Date)\n    && !(a instanceof Set)\n    && !(a instanceof Map)\n  )\n}\n\nexport function subsetEquality(\n  object: unknown,\n  subset: unknown,\n  customTesters: Array<Tester> = [],\n): boolean | undefined {\n  const filteredCustomTesters = customTesters.filter(\n    t => t !== subsetEquality,\n  )\n  // subsetEquality needs to keep track of the references\n  // it has already visited to avoid infinite loops in case\n  // there are circular references in the subset passed to it.\n  const subsetEqualityWithContext\n    = (seenReferences: WeakMap<object, boolean> = new WeakMap()) =>\n      (object: any, subset: any): boolean | undefined => {\n        if (!isObjectWithKeys(subset)) {\n          return undefined\n        }\n\n        return Object.keys(subset).every((key) => {\n          if (subset[key] != null && typeof subset[key] === 'object') {\n            if (seenReferences.has(subset[key])) {\n              return equals(object[key], subset[key], filteredCustomTesters)\n            }\n\n            seenReferences.set(subset[key], true)\n          }\n          const result\n            = object != null\n              && hasPropertyInObject(object, key)\n              && equals(object[key], subset[key], [\n                ...filteredCustomTesters,\n                subsetEqualityWithContext(seenReferences),\n              ])\n          // The main goal of using seenReference is to avoid circular node on tree.\n          // It will only happen within a parent and its child, not a node and nodes next to it (same level)\n          // We should keep the reference for a parent and its child only\n          // Thus we should delete the reference immediately so that it doesn't interfere\n          // other nodes within the same level on tree.\n          seenReferences.delete(subset[key])\n          return result\n        })\n      }\n\n  return subsetEqualityWithContext()(object, subset)\n}\n\nexport function typeEquality(a: any, b: any): boolean | undefined {\n  if (a == null || b == null || a.constructor === b.constructor) {\n    return undefined\n  }\n\n  return false\n}\n\nexport function arrayBufferEquality(\n  a: unknown,\n  b: unknown,\n): boolean | undefined {\n  let dataViewA = a as DataView\n  let dataViewB = b as DataView\n\n  if (!(a instanceof DataView && b instanceof DataView)) {\n    if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer)) {\n      return undefined\n    }\n\n    try {\n      dataViewA = new DataView(a)\n      dataViewB = new DataView(b)\n    }\n    catch {\n      return undefined\n    }\n  }\n\n  // Buffers are not equal when they do not have the same byte length\n  if (dataViewA.byteLength !== dataViewB.byteLength) {\n    return false\n  }\n\n  // Check if every byte value is equal to each other\n  for (let i = 0; i < dataViewA.byteLength; i++) {\n    if (dataViewA.getUint8(i) !== dataViewB.getUint8(i)) {\n      return false\n    }\n  }\n\n  return true\n}\n\nexport function sparseArrayEquality(\n  a: unknown,\n  b: unknown,\n  customTesters: Array<Tester> = [],\n): boolean | undefined {\n  if (!Array.isArray(a) || !Array.isArray(b)) {\n    return undefined\n  }\n\n  // A sparse array [, , 1] will have keys [\"2\"] whereas [undefined, undefined, 1] will have keys [\"0\", \"1\", \"2\"]\n  const aKeys = Object.keys(a)\n  const bKeys = Object.keys(b)\n  const filteredCustomTesters = customTesters.filter(\n    t => t !== sparseArrayEquality,\n  )\n  return equals(a, b, filteredCustomTesters, true) && equals(aKeys, bKeys)\n}\n\nexport function generateToBeMessage(\n  deepEqualityName: string,\n  expected = '#{this}',\n  actual = '#{exp}',\n): string {\n  const toBeMessage = `expected ${expected} to be ${actual} // Object.is equality`\n\n  if (['toStrictEqual', 'toEqual'].includes(deepEqualityName)) {\n    return `${toBeMessage}\\n\\nIf it should pass with deep equality, replace \"toBe\" with \"${deepEqualityName}\"\\n\\nExpected: ${expected}\\nReceived: serializes to the same string\\n`\n  }\n\n  return toBeMessage\n}\n\nexport function pluralize(word: string, count: number): string {\n  return `${count} ${word}${count === 1 ? '' : 's'}`\n}\n\nexport function getObjectKeys(object: object): Array<string | symbol> {\n  return [\n    ...Object.keys(object),\n    ...Object.getOwnPropertySymbols(object).filter(\n      s => Object.getOwnPropertyDescriptor(object, s)?.enumerable,\n    ),\n  ]\n}\n\nexport function getObjectSubset(\n  object: any,\n  subset: any,\n  customTesters: Array<Tester>,\n): { subset: any; stripped: number } {\n  let stripped = 0\n\n  const getObjectSubsetWithContext\n    = (seenReferences: WeakMap<object, boolean> = new WeakMap()) =>\n      (object: any, subset: any): any => {\n        if (Array.isArray(object)) {\n          if (Array.isArray(subset) && subset.length === object.length) {\n          // The map method returns correct subclass of subset.\n            return subset.map((sub: any, i: number) =>\n              getObjectSubsetWithContext(seenReferences)(object[i], sub),\n            )\n          }\n        }\n        else if (object instanceof Date) {\n          return object\n        }\n        else if (isObject(object) && isObject(subset)) {\n          if (\n            equals(object, subset, [\n              ...customTesters,\n              iterableEquality,\n              subsetEquality,\n            ])\n          ) {\n            // return \"expected\" subset to avoid showing irrelevant toMatchObject diff\n            return subset\n          }\n\n          const trimmed: any = {}\n          seenReferences.set(object, trimmed)\n\n          // preserve constructor for toMatchObject diff\n          if (typeof object.constructor === 'function' && typeof object.constructor.name === 'string') {\n            Object.defineProperty(trimmed, 'constructor', {\n              enumerable: false,\n              value: object.constructor,\n            })\n          }\n\n          for (const key of getObjectKeys(object)) {\n            if (hasPropertyInObject(subset, key)) {\n              trimmed[key] = seenReferences.has(object[key])\n                ? seenReferences.get(object[key])\n                : getObjectSubsetWithContext(seenReferences)(\n                    object[key],\n                    subset[key],\n                  )\n            }\n            else {\n              if (!seenReferences.has(object[key])) {\n                stripped += 1\n                if (isObject(object[key])) {\n                  stripped += getObjectKeys(object[key]).length\n                }\n\n                getObjectSubsetWithContext(seenReferences)(\n                  object[key],\n                  subset[key],\n                )\n              }\n            }\n          }\n\n          if (getObjectKeys(trimmed).length > 0) {\n            return trimmed\n          }\n        }\n\n        return object\n      }\n\n  return { subset: getObjectSubsetWithContext()(object, subset), stripped }\n}\n\n/**\n * Detects if an object is a Standard Schema V1 compatible schema\n */\nexport function isStandardSchema(obj: any): obj is StandardSchemaV1 {\n  return (\n    !!obj\n    && (typeof obj === 'object' || typeof obj === 'function')\n    && obj['~standard']\n    && typeof obj['~standard'].validate === 'function'\n  )\n}\n"
  },
  {
    "path": "packages/expect/src/state.ts",
    "content": "import type { ExpectStatic, MatcherState, Tester } from './types'\nimport {\n  ASYMMETRIC_MATCHERS_OBJECT,\n  GLOBAL_EXPECT,\n  JEST_MATCHERS_OBJECT,\n  MATCHERS_OBJECT,\n} from './constants'\n\nif (!Object.hasOwn(globalThis, MATCHERS_OBJECT)) {\n  const globalState = new WeakMap<ExpectStatic, MatcherState>()\n  const matchers = Object.create(null)\n  const customEqualityTesters: Array<Tester> = []\n  const asymmetricMatchers = Object.create(null)\n  Object.defineProperty(globalThis, MATCHERS_OBJECT, {\n    get: () => globalState,\n  })\n  Object.defineProperty(globalThis, JEST_MATCHERS_OBJECT, {\n    configurable: true,\n    get: () => ({\n      state: globalState.get((globalThis as any)[GLOBAL_EXPECT]),\n      matchers,\n      customEqualityTesters,\n    }),\n  })\n  Object.defineProperty(globalThis, ASYMMETRIC_MATCHERS_OBJECT, {\n    get: () => asymmetricMatchers,\n  })\n}\n\nexport function getState<State extends MatcherState = MatcherState>(\n  expect: ExpectStatic,\n): State {\n  return (globalThis as any)[MATCHERS_OBJECT].get(expect)\n}\n\nexport function setState<State extends MatcherState = MatcherState>(\n  state: Partial<State>,\n  expect: ExpectStatic,\n): void {\n  const map = (globalThis as any)[MATCHERS_OBJECT]\n  const current = map.get(expect) || {}\n  // so it keeps getters from `testPath`\n  const results = Object.defineProperties(current, {\n    ...Object.getOwnPropertyDescriptors(current),\n    ...Object.getOwnPropertyDescriptors(state),\n  })\n  map.set(expect, results)\n}\n"
  },
  {
    "path": "packages/expect/src/types.ts",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { Test } from '@vitest/runner'\nimport type { MockInstance } from '@vitest/spy'\nimport type { Formatter } from 'tinyrainbow'\nimport type { AsymmetricMatcher } from './jest-asymmetric-matchers'\nimport type { diff, getMatcherUtils, stringify } from './jest-matcher-utils'\n\nexport type ChaiPlugin = Chai.ChaiPlugin\n\nexport type Tester = (\n  this: TesterContext,\n  a: any,\n  b: any,\n  customTesters: Array<Tester>,\n) => boolean | undefined\n\nexport interface TesterContext {\n  equals: (\n    a: unknown,\n    b: unknown,\n    customTesters?: Array<Tester>,\n    strictCheck?: boolean,\n  ) => boolean\n}\nexport type { DiffOptions } from '@vitest/utils/diff'\n\nexport interface MatcherHintOptions {\n  comment?: string\n  expectedColor?: Formatter\n  isDirectExpectCall?: boolean\n  isNot?: boolean\n  promise?: string\n  receivedColor?: Formatter\n  secondArgument?: string\n  secondArgumentColor?: Formatter\n}\n\nexport interface MatcherState {\n  customTesters: Array<Tester>\n  assertionCalls: number\n  currentTestName?: string\n  /**\n   * @deprecated exists only in types\n   */\n  dontThrow?: () => void\n  /**\n   * @deprecated exists only in types\n   */\n  error?: Error\n  equals: (\n    a: unknown,\n    b: unknown,\n    customTesters?: Array<Tester>,\n    strictCheck?: boolean,\n  ) => boolean\n  /**\n   * @deprecated exists only in types\n   */\n  expand?: boolean\n  expectedAssertionsNumber?: number | null\n  expectedAssertionsNumberErrorGen?: (() => Error) | null\n  isExpectingAssertions?: boolean\n  isExpectingAssertionsError?: Error | null\n  isNot: boolean\n  promise: string\n  /**\n   * @deprecated exists only in types\n   */\n  suppressedErrors: Array<Error>\n  testPath?: string\n  utils: ReturnType<typeof getMatcherUtils> & {\n    diff: typeof diff\n    stringify: typeof stringify\n    iterableEquality: Tester\n    subsetEquality: Tester\n  }\n  soft?: boolean\n  poll?: boolean\n  task?: Readonly<Test>\n}\n\nexport interface SyncExpectationResult {\n  pass: boolean\n  message: () => string\n  actual?: any\n  expected?: any\n}\n\nexport type AsyncExpectationResult = Promise<SyncExpectationResult>\n\nexport type ExpectationResult = SyncExpectationResult | AsyncExpectationResult\n\nexport interface RawMatcherFn<T extends MatcherState = MatcherState, E extends Array<any> = Array<any>> {\n  (this: T, received: any, ...expected: E): ExpectationResult\n}\n\n// Allow unused `T` to preserve its name for extensions.\n// Type parameter names must be identical when extending those types.\n// eslint-disable-next-line\nexport interface Matchers<T = any> {}\n\nexport type MatchersObject<T extends MatcherState = MatcherState> = Record<\n  string,\n  RawMatcherFn<T>\n> & ThisType<T> & {\n  [K in keyof Matchers<T>]?: RawMatcherFn<T, Parameters<Matchers<T>[K]>>\n}\n\nexport interface ExpectStatic\n  extends Chai.ExpectStatic,\n  Matchers,\n  AsymmetricMatchersContaining {\n  <T>(actual: T, message?: string): Assertion<T>\n  extend: (expects: MatchersObject) => void\n  anything: () => any\n  any: (constructor: unknown) => any\n  getState: () => MatcherState\n  setState: (state: Partial<MatcherState>) => void\n  not: AsymmetricMatchersContaining\n}\n\ninterface CustomMatcher {\n  /**\n   * Checks that a value satisfies a custom matcher function.\n   *\n   * @param matcher - A function returning a boolean based on the custom condition\n   * @param message - Optional custom error message on failure\n   *\n   * @example\n   * expect(age).toSatisfy(val => val >= 18, 'Age must be at least 18');\n   * expect(age).toEqual(expect.toSatisfy(val => val >= 18, 'Age must be at least 18'));\n   */\n  toSatisfy: (matcher: (value: any) => boolean, message?: string) => any\n\n  /**\n   * Matches if the received value is one of the values in the expected array or set.\n   *\n   * @example\n   * expect(1).toBeOneOf([1, 2, 3])\n   * expect('foo').toBeOneOf([expect.any(String)])\n   * expect({ a: 1 }).toEqual({ a: expect.toBeOneOf(['1', '2', '3']) })\n   */\n  toBeOneOf: <T>(sample: Array<T> | Set<T>) => any\n}\n\nexport interface AsymmetricMatchersContaining extends CustomMatcher {\n  /**\n   * Matches if the received string contains the expected substring.\n   *\n   * @example\n   * expect('I have an apple').toEqual(expect.stringContaining('apple'));\n   * expect({ a: 'test string' }).toEqual({ a: expect.stringContaining('test') });\n   */\n  stringContaining: (expected: string) => any\n\n  /**\n   * Matches if the received object contains all properties of the expected object.\n   *\n   * @example\n   * expect({ a: '1', b: 2 }).toEqual(expect.objectContaining({ a: '1' }))\n   */\n  objectContaining: <T = any>(expected: DeeplyAllowMatchers<T>) => any\n\n  /**\n   * Matches if the received array contains all elements in the expected array.\n   *\n   * @example\n   * expect(['a', 'b', 'c']).toEqual(expect.arrayContaining(['b', 'a']));\n   */\n  arrayContaining: <T = unknown>(expected: Array<DeeplyAllowMatchers<T>>) => any\n\n  /**\n   * Matches if the received string or regex matches the expected pattern.\n   *\n   * @example\n   * expect('hello world').toEqual(expect.stringMatching(/^hello/));\n   * expect('hello world').toEqual(expect.stringMatching('hello'));\n   */\n  stringMatching: (expected: string | RegExp) => any\n\n  /**\n   * Matches if the received number is within a certain precision of the expected number.\n   *\n   * @example\n   * expect(10.45).toEqual(expect.closeTo(10.5, 1));\n   * expect(5.11).toEqual(expect.closeTo(5.12)); // with default precision\n   */\n  closeTo: (expected: number, precision?: number) => any\n\n  /**\n   * Matches if the received value validates against a Standard Schema.\n   *\n   * @param schema - A Standard Schema V1 compatible schema object\n   *\n   * @example\n   * expect(user).toEqual(expect.schemaMatching(z.object({ name: z.string() })))\n   * expect(['hello', 'world']).toEqual([expect.schemaMatching(z.string()), expect.schemaMatching(z.string())])\n   */\n  schemaMatching: (schema: unknown) => any\n}\n\ntype WithAsymmetricMatcher<T> = T | AsymmetricMatcher<unknown>\n\nexport type DeeplyAllowMatchers<T> = T extends Array<infer Element>\n  ? WithAsymmetricMatcher<T> | DeeplyAllowMatchers<Element>[]\n  : T extends object\n    ? WithAsymmetricMatcher<T> | { [K in keyof T]: DeeplyAllowMatchers<T[K]> }\n    : WithAsymmetricMatcher<T>\n\nexport interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {\n  /**\n   * Used when you want to check that two objects have the same value.\n   * This matcher recursively checks the equality of all fields, rather than checking for object identity.\n   *\n   * @example\n   * expect(user).toEqual({ name: 'Alice', age: 30 });\n   */\n  toEqual: <E>(expected: E) => void\n\n  /**\n   * Use to test that objects have the same types as well as structure.\n   *\n   * @example\n   * expect(user).toStrictEqual({ name: 'Alice', age: 30 });\n   */\n  toStrictEqual: <E>(expected: E) => void\n\n  /**\n   * Checks that a value is what you expect. It calls `Object.is` to compare values.\n   * Don't use `toBe` with floating-point numbers.\n   *\n   * @example\n   * expect(result).toBe(42);\n   * expect(status).toBe(true);\n   */\n  toBe: <E>(expected: E) => void\n\n  /**\n   * Check that a string matches a regular expression.\n   *\n   * @example\n   * expect(message).toMatch(/hello/);\n   * expect(greeting).toMatch('world');\n   */\n  toMatch: (expected: string | RegExp) => void\n\n  /**\n   * Used to check that a JavaScript object matches a subset of the properties of an object\n   *\n   * @example\n   * expect(user).toMatchObject({\n   *   name: 'Alice',\n   *   address: { city: 'Wonderland' }\n   * });\n   */\n  toMatchObject: <E extends object | any[]>(expected: E) => void\n\n  /**\n   * Used when you want to check that an item is in a list.\n   * For testing the items in the list, this uses `===`, a strict equality check.\n   *\n   * @example\n   * expect(items).toContain('apple');\n   * expect(numbers).toContain(5);\n   */\n  toContain: <E>(item: E) => void\n\n  /**\n   * Used when you want to check that an item is in a list.\n   * For testing the items in the list, this matcher recursively checks the\n   * equality of all fields, rather than checking for object identity.\n   *\n   * @example\n   * expect(items).toContainEqual({ name: 'apple', quantity: 1 });\n   */\n  toContainEqual: <E>(item: E) => void\n\n  /**\n   * Use when you don't care what a value is, you just want to ensure a value\n   * is true in a boolean context. In JavaScript, there are six falsy values:\n   * `false`, `0`, `''`, `null`, `undefined`, and `NaN`. Everything else is truthy.\n   *\n   * @example\n   * expect(user.isActive).toBeTruthy();\n   */\n  toBeTruthy: () => void\n\n  /**\n   * When you don't care what a value is, you just want to\n   * ensure a value is false in a boolean context.\n   *\n   * @example\n   * expect(user.isActive).toBeFalsy();\n   */\n  toBeFalsy: () => void\n\n  /**\n   * For comparing floating point numbers.\n   *\n   * @example\n   * expect(score).toBeGreaterThan(10);\n   */\n  toBeGreaterThan: (num: number | bigint) => void\n\n  /**\n   * For comparing floating point numbers.\n   *\n   * @example\n   * expect(score).toBeGreaterThanOrEqual(10);\n   */\n  toBeGreaterThanOrEqual: (num: number | bigint) => void\n\n  /**\n   * For comparing floating point numbers.\n   *\n   * @example\n   * expect(score).toBeLessThan(10);\n   */\n  toBeLessThan: (num: number | bigint) => void\n\n  /**\n   * For comparing floating point numbers.\n   *\n   * @example\n   * expect(score).toBeLessThanOrEqual(10);\n   */\n  toBeLessThanOrEqual: (num: number | bigint) => void\n\n  /**\n   * Used to check that a variable is NaN.\n   *\n   * @example\n   * expect(value).toBeNaN();\n   */\n  toBeNaN: () => void\n\n  /**\n   * Used to check that a variable is undefined.\n   *\n   * @example\n   * expect(value).toBeUndefined();\n   */\n  toBeUndefined: () => void\n\n  /**\n   * This is the same as `.toBe(null)` but the error messages are a bit nicer.\n   * So use `.toBeNull()` when you want to check that something is null.\n   *\n   * @example\n   * expect(value).toBeNull();\n   */\n  toBeNull: () => void\n\n  /**\n   * Used to check that a variable is nullable (null or undefined).\n   *\n   * @example\n   * expect(value).toBeNullable();\n   */\n  toBeNullable: () => void\n\n  /**\n   * Ensure that a variable is not undefined.\n   *\n   * @example\n   * expect(value).toBeDefined();\n   */\n  toBeDefined: () => void\n\n  /**\n   * Ensure that an object is an instance of a class.\n   * This matcher uses `instanceof` underneath.\n   *\n   * @example\n   * expect(new Date()).toBeInstanceOf(Date);\n   */\n  toBeInstanceOf: <E>(expected: E) => void\n\n  /**\n   * Used to check that an object has a `.length` property\n   * and it is set to a certain numeric value.\n   *\n   * @example\n   * expect([1, 2, 3]).toHaveLength(3);\n   * expect('hello').toHaveLength(5);\n   */\n  toHaveLength: (length: number) => void\n\n  /**\n   * Use to check if a property at the specified path exists on an object.\n   * For checking deeply nested properties, you may use dot notation or an array containing\n   * the path segments for deep references.\n   *\n   * Optionally, you can provide a value to check if it matches the value present at the path\n   * on the target object. This matcher uses 'deep equality' (like `toEqual()`) and recursively checks\n   * the equality of all fields.\n   *\n   * @example\n   * expect(user).toHaveProperty('address.city', 'New York');\n   * expect(config).toHaveProperty(['settings', 'theme'], 'dark');\n   */\n  toHaveProperty: <E>(\n    property: string | (string | number)[],\n    value?: E,\n  ) => void\n\n  /**\n   * Using exact equality with floating point numbers is a bad idea.\n   * Rounding means that intuitive things fail.\n   * The default for `numDigits` is 2.\n   *\n   * @example\n   * expect(price).toBeCloseTo(9.99, 2);\n   */\n  toBeCloseTo: (number: number, numDigits?: number) => void\n\n  /**\n   * Ensures that a mock function is called an exact number of times.\n   *\n   * Also under the alias `expect.toBeCalledTimes`.\n   *\n   * @example\n   * expect(mockFunc).toHaveBeenCalledTimes(2);\n   */\n  toHaveBeenCalledTimes: (times: number) => void\n\n  /**\n   * Ensures that a mock function is called an exact number of times.\n   *\n   * Alias for `expect.toHaveBeenCalledTimes`.\n   *\n   * @example\n   * expect(mockFunc).toBeCalledTimes(2);\n   * @deprecated Use `toHaveBeenCalledTimes` instead\n   */\n  toBeCalledTimes: (times: number) => void\n\n  /**\n   * Ensures that a mock function is called.\n   *\n   * Also under the alias `expect.toBeCalled`.\n   *\n   * @example\n   * expect(mockFunc).toHaveBeenCalled();\n   */\n\n  toHaveBeenCalled: () => void\n\n  /**\n   * Ensures that a mock function is called.\n   *\n   * Alias for `expect.toHaveBeenCalled`.\n   *\n   * @example\n   * expect(mockFunc).toBeCalled();\n   * @deprecated Use `toHaveBeenCalled` instead\n   */\n  toBeCalled: () => void\n\n  /**\n   * Ensure that a mock function is called with specific arguments.\n   *\n   * Also under the alias `expect.toBeCalledWith`.\n   *\n   * @example\n   * expect(mockFunc).toHaveBeenCalledWith('arg1', 42);\n   */\n  toHaveBeenCalledWith: <E extends any[]>(...args: E) => void\n\n  /**\n   * Ensure that a mock function is called with specific arguments.\n   *\n   * Alias for `expect.toHaveBeenCalledWith`.\n   *\n   * @example\n   * expect(mockFunc).toBeCalledWith('arg1', 42);\n   * @deprecated Use `toHaveBeenCalledWith` instead\n   */\n  toBeCalledWith: <E extends any[]>(...args: E) => void\n\n  /**\n   * Ensure that a mock function is called with specific arguments on an Nth call.\n   *\n   * Also under the alias `expect.nthCalledWith`.\n   *\n   * @example\n   * expect(mockFunc).toHaveBeenNthCalledWith(2, 'secondArg');\n   */\n  toHaveBeenNthCalledWith: <E extends any[]>(n: number, ...args: E) => void\n\n  /**\n   * If you have a mock function, you can use `.toHaveBeenLastCalledWith`\n   * to test what arguments it was last called with.\n   *\n   * Also under the alias `expect.lastCalledWith`.\n   *\n   * @example\n   * expect(mockFunc).toHaveBeenLastCalledWith('lastArg');\n   */\n  toHaveBeenLastCalledWith: <E extends any[]>(...args: E) => void\n\n  /**\n   * Used to test that a function throws when it is called.\n   *\n   * Also under the alias `expect.toThrowError`.\n   *\n   * @example\n   * expect(() => functionWithError()).toThrow('Error message');\n   * expect(() => parseJSON('invalid')).toThrow(SyntaxError);\n   * expect(() => { throw 42 }).toThrow(42);\n   */\n  toThrow: (expected?: any) => void\n\n  /**\n   * Used to test that a function throws when it is called.\n   *\n   * Alias for `expect.toThrow`.\n   *\n   * @example\n   * expect(() => functionWithError()).toThrowError('Error message');\n   * expect(() => parseJSON('invalid')).toThrowError(SyntaxError);\n   * expect(() => { throw 42 }).toThrowError(42);\n   * @deprecated Use `toThrow` instead\n   */\n  toThrowError: (expected?: any) => void\n\n  /**\n   * Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time\n   *\n   * Alias for `expect.toHaveReturned`.\n   *\n   * @example\n   * expect(mockFunc).toReturn();\n   * @deprecated Use `toHaveReturned` instead\n   */\n  toReturn: () => void\n\n  /**\n   * Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time\n   *\n   * Also under the alias `expect.toReturn`.\n   *\n   * @example\n   * expect(mockFunc).toHaveReturned();\n   */\n  toHaveReturned: () => void\n\n  /**\n   * Use to ensure that a mock function returned successfully (i.e., did not throw an error) an exact number of times.\n   * Any calls to the mock function that throw an error are not counted toward the number of times the function returned.\n   *\n   * Alias for `expect.toHaveReturnedTimes`.\n   *\n   * @example\n   * expect(mockFunc).toReturnTimes(3);\n   * @deprecated Use `toHaveReturnedTimes` instead\n   */\n  toReturnTimes: (times: number) => void\n\n  /**\n   * Use to ensure that a mock function returned successfully (i.e., did not throw an error) an exact number of times.\n   * Any calls to the mock function that throw an error are not counted toward the number of times the function returned.\n   *\n   * Also under the alias `expect.toReturnTimes`.\n   *\n   * @example\n   * expect(mockFunc).toHaveReturnedTimes(3);\n   */\n  toHaveReturnedTimes: (times: number) => void\n\n  /**\n   * Use to ensure that a mock function returned a specific value.\n   *\n   * Alias for `expect.toHaveReturnedWith`.\n   *\n   * @example\n   * expect(mockFunc).toReturnWith('returnValue');\n   * @deprecated Use `toHaveReturnedWith` instead\n   */\n  toReturnWith: <E>(value: E) => void\n\n  /**\n   * Use to ensure that a mock function returned a specific value.\n   *\n   * Also under the alias `expect.toReturnWith`.\n   *\n   * @example\n   * expect(mockFunc).toHaveReturnedWith('returnValue');\n   */\n  toHaveReturnedWith: <E>(value: E) => void\n\n  /**\n   * Use to test the specific value that a mock function last returned.\n   * If the last call to the mock function threw an error, then this matcher will fail\n   * no matter what value you provided as the expected return value.\n   *\n   * Also under the alias `expect.lastReturnedWith`.\n   *\n   * @example\n   * expect(mockFunc).toHaveLastReturnedWith('lastValue');\n   */\n  toHaveLastReturnedWith: <E>(value: E) => void\n\n  /**\n   * Use to test the specific value that a mock function returned for the nth call.\n   * If the nth call to the mock function threw an error, then this matcher will fail\n   * no matter what value you provided as the expected return value.\n   *\n   * Also under the alias `expect.nthReturnedWith`.\n   *\n   * @example\n   * expect(mockFunc).toHaveNthReturnedWith(2, 'nthValue');\n   */\n  toHaveNthReturnedWith: <E>(nthCall: number, value: E) => void\n}\n\ntype VitestAssertion<A, T> = {\n  [K in keyof A]: A[K] extends Chai.Assertion\n    ? Assertion<T>\n    : A[K] extends (...args: any[]) => any\n      ? A[K] // not converting function since they may contain overload\n      : VitestAssertion<A[K], T>;\n} & ((type: string, message?: string) => Assertion)\n\ntype Promisify<O> = {\n  [K in keyof O]: O[K] extends (...args: infer A) => infer R\n    ? Promisify<O[K]> & ((...args: A) => Promise<R>)\n    : O[K];\n}\n\nexport type PromisifyAssertion<T> = Promisify<Assertion<T>>\n\nexport interface Assertion<T = any>\n  extends VitestAssertion<Chai.Assertion, T>,\n  JestAssertion<T>,\n  ChaiMockAssertion,\n  Matchers<T> {\n  /**\n   * Ensures a value is of a specific type.\n   *\n   * @example\n   * expect(value).toBeTypeOf('string');\n   * expect(number).toBeTypeOf('number');\n   */\n  toBeTypeOf: (\n    expected:\n      | 'bigint'\n      | 'boolean'\n      | 'function'\n      | 'number'\n      | 'object'\n      | 'string'\n      | 'symbol'\n      | 'undefined',\n  ) => void\n\n  /**\n   * Asserts that a mock function was called exactly once.\n   *\n   * @example\n   * expect(mockFunc).toHaveBeenCalledOnce();\n   */\n  toHaveBeenCalledOnce: () => void\n\n  /**\n   * Ensure that a mock function is called with specific arguments and called\n   * exactly once.\n   *\n   * @example\n   * expect(mockFunc).toHaveBeenCalledExactlyOnceWith('arg1', 42);\n   */\n  toHaveBeenCalledExactlyOnceWith: <E extends any[]>(...args: E) => void\n\n  /**\n   * This assertion checks if a `Mock` was called before another `Mock`.\n   * @param mock - A mock function created by `vi.spyOn` or `vi.fn`\n   * @param failIfNoFirstInvocation - Fail if the first mock was never called\n   * @example\n   * const mock1 = vi.fn()\n   * const mock2 = vi.fn()\n   *\n   * mock1()\n   * mock2()\n   * mock1()\n   *\n   * expect(mock1).toHaveBeenCalledBefore(mock2)\n   */\n  toHaveBeenCalledBefore: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => void\n\n  /**\n   * This assertion checks if a `Mock` was called after another `Mock`.\n   * @param mock - A mock function created by `vi.spyOn` or `vi.fn`\n   * @param failIfNoFirstInvocation - Fail if the first mock was never called\n   * @example\n   * const mock1 = vi.fn()\n   * const mock2 = vi.fn()\n   *\n   * mock2()\n   * mock1()\n   * mock2()\n   *\n   * expect(mock1).toHaveBeenCalledAfter(mock2)\n   */\n  toHaveBeenCalledAfter: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => void\n\n  /**\n   * Checks that a promise resolves successfully at least once.\n   *\n   * @example\n   * await expect(promise).toHaveResolved();\n   */\n  toHaveResolved: () => void\n\n  /**\n   * Checks that a promise resolves to a specific value.\n   *\n   * @example\n   * await expect(promise).toHaveResolvedWith('success');\n   */\n  toHaveResolvedWith: <E>(value: E) => void\n\n  /**\n   * Ensures a promise resolves a specific number of times.\n   *\n   * @example\n   * expect(mockAsyncFunc).toHaveResolvedTimes(3);\n   */\n  toHaveResolvedTimes: (times: number) => void\n\n  /**\n   * Asserts that the last resolved value of a promise matches an expected value.\n   *\n   * @example\n   * await expect(mockAsyncFunc).toHaveLastResolvedWith('finalResult');\n   */\n  toHaveLastResolvedWith: <E>(value: E) => void\n\n  /**\n   * Ensures a specific value was returned by a promise on the nth resolution.\n   *\n   * @example\n   * await expect(mockAsyncFunc).toHaveNthResolvedWith(2, 'secondResult');\n   */\n  toHaveNthResolvedWith: <E>(nthCall: number, value: E) => void\n\n  /**\n   * Verifies that a promise resolves.\n   *\n   * @example\n   * await expect(someAsyncFunc).resolves.toBe(42);\n   */\n  resolves: PromisifyAssertion<T>\n\n  /**\n   * Verifies that a promise rejects.\n   *\n   * @example\n   * await expect(someAsyncFunc).rejects.toThrow('error');\n   */\n  rejects: PromisifyAssertion<T>\n}\n\n/**\n * Chai-style assertions for spy/mock testing.\n * These provide sinon-chai compatible assertion names that delegate to Jest-style implementations.\n */\nexport interface ChaiMockAssertion {\n  /**\n   * Checks that a spy was called at least once.\n   * Chai-style equivalent of `toHaveBeenCalled`.\n   *\n   * @example\n   * expect(spy).to.have.been.called\n   */\n  readonly called: Assertion\n\n  /**\n   * Checks that a spy was called a specific number of times.\n   * Chai-style equivalent of `toHaveBeenCalledTimes`.\n   *\n   * @example\n   * expect(spy).to.have.callCount(3)\n   */\n  callCount: (count: number) => void\n\n  /**\n   * Checks that a spy was called with specific arguments at least once.\n   * Chai-style equivalent of `toHaveBeenCalledWith`.\n   *\n   * @example\n   * expect(spy).to.have.been.calledWith('arg1', 'arg2')\n   */\n  calledWith: <E extends any[]>(...args: E) => void\n\n  /**\n   * Checks that a spy was called exactly once.\n   * Chai-style equivalent of `toHaveBeenCalledOnce`.\n   *\n   * @example\n   * expect(spy).to.have.been.calledOnce\n   */\n  readonly calledOnce: Assertion\n\n  /**\n   * Checks that a spy was called exactly once with specific arguments.\n   * Chai-style equivalent of `toHaveBeenCalledExactlyOnceWith`.\n   *\n   * @example\n   * expect(spy).to.have.been.calledOnceWith('arg1', 'arg2')\n   */\n  calledOnceWith: <E extends any[]>(...args: E) => void\n\n  /**\n   * Checks that the last call to a spy was made with specific arguments.\n   * Chai-style equivalent of `toHaveBeenLastCalledWith`.\n   *\n   * @example\n   * expect(spy).to.have.been.lastCalledWith('arg1', 'arg2')\n   */\n  lastCalledWith: <E extends any[]>(...args: E) => void\n\n  /**\n   * Checks that the nth call to a spy was made with specific arguments.\n   * Chai-style equivalent of `toHaveBeenNthCalledWith`.\n   *\n   * @example\n   * expect(spy).to.have.been.nthCalledWith(2, 'arg1', 'arg2')\n   */\n  nthCalledWith: <E extends any[]>(n: number, ...args: E) => void\n\n  /**\n   * Checks that a spy returned successfully at least once.\n   * Chai-style equivalent of `toHaveReturned`.\n   *\n   * @example\n   * expect(spy).to.have.returned\n   */\n  readonly returned: Assertion\n\n  /**\n   * Checks that a spy returned a specific value at least once.\n   * Chai-style equivalent of `toHaveReturnedWith`.\n   *\n   * @example\n   * expect(spy).to.have.returnedWith('value')\n   */\n  returnedWith: <E>(value: E) => void\n\n  /**\n   * Checks that a spy returned successfully a specific number of times.\n   * Chai-style equivalent of `toHaveReturnedTimes`.\n   *\n   * @example\n   * expect(spy).to.have.returnedTimes(3)\n   */\n  returnedTimes: (count: number) => void\n\n  /**\n   * Checks that the last return value of a spy matches the expected value.\n   * Chai-style equivalent of `toHaveLastReturnedWith`.\n   *\n   * @example\n   * expect(spy).to.have.lastReturnedWith('value')\n   */\n  lastReturnedWith: <E>(value: E) => void\n\n  /**\n   * Checks that the nth return value of a spy matches the expected value.\n   * Chai-style equivalent of `toHaveNthReturnedWith`.\n   *\n   * @example\n   * expect(spy).to.have.nthReturnedWith(2, 'value')\n   */\n  nthReturnedWith: <E>(n: number, value: E) => void\n\n  /**\n   * Checks that a spy was called before another spy.\n   * Chai-style equivalent of `toHaveBeenCalledBefore`.\n   *\n   * @example\n   * expect(spy1).to.have.been.calledBefore(spy2)\n   */\n  calledBefore: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => void\n\n  /**\n   * Checks that a spy was called after another spy.\n   * Chai-style equivalent of `toHaveBeenCalledAfter`.\n   *\n   * @example\n   * expect(spy1).to.have.been.calledAfter(spy2)\n   */\n  calledAfter: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => void\n\n  /**\n   * Checks that a spy was called exactly twice.\n   * Chai-style equivalent of `toHaveBeenCalledTimes(2)`.\n   *\n   * @example\n   * expect(spy).to.have.been.calledTwice\n   */\n  readonly calledTwice: Assertion\n\n  /**\n   * Checks that a spy was called exactly three times.\n   * Chai-style equivalent of `toHaveBeenCalledTimes(3)`.\n   *\n   * @example\n   * expect(spy).to.have.been.calledThrice\n   */\n  readonly calledThrice: Assertion\n}\n\ndeclare global {\n  // support augmenting jest.Matchers by other libraries\n  // eslint-disable-next-line ts/no-namespace\n  namespace jest {\n    // eslint-disable-next-line unused-imports/no-unused-vars, ts/no-empty-object-type\n    interface Matchers<R, T = {}> {}\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "packages/expect/src/utils.ts",
    "content": "import type { Test } from '@vitest/runner/types'\nimport type { Assertion } from './types'\nimport { processError } from '@vitest/utils/error'\nimport { noop } from '@vitest/utils/helpers'\n\nexport function createAssertionMessage(\n  util: Chai.ChaiUtils,\n  assertion: Assertion,\n  hasArgs: boolean,\n) {\n  const soft = util.flag(assertion, 'soft') ? '.soft' : ''\n  const not = util.flag(assertion, 'negate') ? 'not.' : ''\n  const name = `${util.flag(assertion, '_name')}(${hasArgs ? 'expected' : ''})`\n  const promiseName = util.flag(assertion, 'promise')\n  const promise = promiseName ? `.${promiseName}` : ''\n  return `expect${soft}(actual)${promise}.${not}${name}`\n}\n\nexport function recordAsyncExpect(\n  _test: any,\n  promise: Promise<any>,\n  assertion: string,\n  error: Error,\n  isSoft?: boolean,\n): Promise<any> {\n  const test = _test as Test | undefined\n  // record promise for test, that resolves before test ends\n  if (test && promise instanceof Promise) {\n    // if promise is explicitly awaited, remove it from the list\n    promise = promise.finally(() => {\n      if (!test.promises) {\n        return\n      }\n      const index = test.promises.indexOf(promise)\n      if (index !== -1) {\n        test.promises.splice(index, 1)\n      }\n    })\n\n    // record promise\n    if (!test.promises) {\n      test.promises = []\n    }\n    // setup `expect.soft` handler here instead of `wrapAssertion`\n    // to avoid double error tracking while keeping non-await promise detection.\n    if (isSoft) {\n      promise = promise.then(noop, (err) => {\n        handleTestError(test, err)\n      })\n    }\n    test.promises.push(promise)\n\n    let resolved = false\n    test.onFinished ??= []\n    test.onFinished.push(() => {\n      if (!resolved) {\n        const processor = (globalThis as any).__vitest_worker__?.onFilterStackTrace || ((s: string) => s || '')\n        const stack = processor(error.stack)\n        console.warn([\n          `Promise returned by \\`${assertion}\\` was not awaited. `,\n          'Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in the next Vitest major. ',\n          'Please remember to await the assertion.\\n',\n          stack,\n        ].join(''))\n      }\n    })\n\n    return {\n      then(onFulfilled, onRejected) {\n        resolved = true\n        return promise.then(onFulfilled, onRejected)\n      },\n      catch(onRejected) {\n        resolved = true\n        return promise.catch(onRejected)\n      },\n      finally(onFinally) {\n        resolved = true\n        return promise.finally(onFinally)\n      },\n      [Symbol.toStringTag]: 'Promise',\n    } satisfies Promise<any>\n  }\n\n  return promise\n}\n\nfunction handleTestError(test: Test, err: unknown) {\n  test.result ||= { state: 'fail' }\n  test.result.state = 'fail'\n  test.result.errors ||= []\n  test.result.errors.push(processError(err))\n}\n\nexport function wrapAssertion(\n  utils: Chai.ChaiUtils,\n  name: string,\n  fn: (this: Chai.AssertionStatic & Assertion, ...args: any[]) => void | PromiseLike<void>,\n) {\n  return function (this: Chai.AssertionStatic & Assertion, ...args: any[]): void | PromiseLike<void> {\n    // private\n    if (name !== 'withTest') {\n      utils.flag(this, '_name', name)\n    }\n\n    if (!utils.flag(this, 'soft')) {\n      // avoid WebKit's proper tail call to preserve stacktrace offset for inline snapshot\n      // https://webkit.org/blog/6240/ecmascript-6-proper-tail-calls-in-webkit\n      try {\n        return fn.apply(this, args)\n      }\n      finally {\n        // no lint\n      }\n    }\n\n    const test: Test = utils.flag(this, 'vitest-test')\n\n    if (!test) {\n      throw new Error('expect.soft() can only be used inside a test')\n    }\n\n    try {\n      const result = fn.apply(this, args)\n\n      if (result && typeof result === 'object' && typeof result.then === 'function') {\n        return result.then(noop, (err) => {\n          handleTestError(test, err)\n        })\n      }\n\n      return result\n    }\n    catch (err) {\n      handleTestError(test, err)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/expect/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"./dist\"]\n}\n"
  },
  {
    "path": "packages/mocker/EXPORTS.md",
    "content": "## Using as a Vite plugin\n\nMake sure you have `vite` and `@vitest/spy` installed (and `msw` if you are planning to use `ModuleMockerMSWInterceptor`).\n\n```ts\nimport { mockerPlugin } from '@vitest/mocker/node'\n\nexport default defineConfig({\n  plugins: [mockerPlugin()],\n})\n```\n\nTo use it in your code, register the runtime mocker. The naming of `vi` matters - it is used by the compiler. You can configure the name by changing the `hoistMocks.utilsObjectName` and `hoistMocks.regexpHoistable` options.\n\n```ts\nimport {\n  ModuleMockerMSWInterceptor,\n  ModuleMockerServerInterceptor,\n  registerModuleMocker\n} from '@vitest/mocker/register'\n\n// you can use either a server interceptor (relies on Vite's websocket connection)\nconst vi = registerModuleMocker(() => new ModuleMockerServerInterceptor())\n// or you can use MSW to intercept requests directly in the browser\nconst vi = registerModuleMocker(globalThisAccessor => new ModuleMockerMSWInterceptor({ globalThisAccessor }))\n```\n\n```ts\n// you can also just import \"auto-register\" at the top of your entry point,\n// this will use the server interceptor by default\nimport '@vitest/mocker/auto-register'\n// if you do this, you can create compiler hints with \"createCompilerHints\"\n// utility to use in your own code\nimport { createCompilerHints } from '@vitest/mocker/browser'\nconst vi = createCompilerHints()\n```\n\n`registerModuleMocker` returns compiler hints that Vite plugin will look for.\n\nBy default, Vitest looks for `vi.mock`/`vi.doMock`/`vi.unmock`/`vi.doUnmock`/`vi.hoisted`. You can configure this with the `hoistMocks` option when initiating a plugin:\n\n```ts\nimport { mockerPlugin } from '@vitest/mocker/node'\n\nexport default defineConfig({\n  plugins: [\n    mockerPlugin({\n      hoistMocks: {\n        regexpHoistable: /myObj.mock/,\n        // you will also need to update other options accordingly\n        utilsObjectName: ['myObj'],\n      },\n    }),\n  ],\n})\n```\n\nNow you can call `vi.mock` in your code and the mocker should kick in automatically:\n\n```ts\nimport { mocked } from './some-module.js'\n\nvi.mock('./some-module.js', () => {\n  return { mocked: true }\n})\n\nmocked === true\n```\n\n# Public Exports\n\n## MockerRegistry\n\nJust a cache that holds mocked modules to be used by the actual mocker.\n\n```ts\nimport { ManualMockedModule, MockerRegistry } from '@vitest/mocker'\nconst registry = new MockerRegistry()\n\n// Vitest requites the original ID for better error messages,\n// You can pass down anything related to the module there\nregistry.register('manual', './id.js', '/users/custom/id.js', factory)\nregistry.get('/users/custom/id.js') instanceof ManualMockedModule\n```\n\n## mockObject\n\nDeeply mock an object. This is the function that automocks modules in Vitest.\n\n```ts\nimport { mockObject } from '@vitest/mocker'\nimport { spyOn } from '@vitest/spy'\n\nmockObject(\n  {\n    // this is needed because it can be used in vm context\n    globalConstructors: {\n      Object,\n      // ...\n    },\n    // you can provide your own spyOn implementation\n    spyOn,\n    mockType: 'automock' // or 'autospy'\n  },\n  {\n    myDeep: {\n      object() {\n        return {\n          willAlso: {\n            beMocked() {\n              return true\n            },\n          },\n        }\n      },\n    },\n  }\n)\n```\n\n## automockPlugin\n\nThe Vite plugin that can mock any module in the browser.\n\n```ts\nimport { automockPlugin } from '@vitest/mocker/node'\nimport { createServer } from 'vite'\n\nawait createServer({\n  plugins: [\n    automockPlugin(),\n  ],\n})\n```\n\nAny module that has `mock=automock` or `mock=autospy` query will be mocked:\n\n```ts\nimport { calculator } from './src/calculator.js?mock=automock'\n\ncalculator(1, 2)\ncalculator.mock.calls[0] === [1, 2]\n```\n\nIdeally, you would inject those queries somehow, not write them manually. In the future, this package will support `with { mock: 'auto' }` syntax.\n\n> [!WARNING]\n> The plugin expects a global `__vitest_mocker__` variable with a `mockObject` method. Make sure it is injected _before_ the mocked file is imported. You can also configure the accessor by changing the `globalThisAccessor` option.\n\n> [!NOTE]\n> This plugin is included in `mockerPlugin`.\n\n## automockModule\n\nReplace every export with a mock in the code.\n\n```ts\nimport { automockModule } from '@vitest/mocker/node'\nimport { parseAst } from 'vite'\n\nconst ms = await automockModule(\n  `export function test() {}`,\n  'automock',\n  parseAst,\n)\nconsole.log(\n  ms.toString(),\n  ms.generateMap({ hires: 'boundary' })\n)\n```\n\nProduces this:\n\n```ts\nfunction test() {}\n\nconst __vitest_es_current_module__ = {\n  __esModule: true,\n  test,\n}\nconst __vitest_mocked_module__ = __vitest_mocker__.mockObject(__vitest_es_current_module__, 'automock')\nconst __vitest_mocked_0__ = __vitest_mocked_module__.test\nexport {\n  __vitest_mocked_0__ as test,\n}\n```\n\n## hoistMocksPlugin\n\nThe plugin that hoists every compiler hint, replaces every static import with dynamic one and updates exports access to make sure live-binding is not broken.\n\n```ts\nimport { hoistMocksPlugin } from '@vitest/mocker/node'\nimport { createServer } from 'vite'\n\nawait createServer({\n  plugins: [\n    hoistMocksPlugin({\n      hoistedModules: ['virtual:my-module'],\n      regexpHoistable: /myObj.(mock|hoist)/,\n      utilsObjectName: ['myObj'],\n      hoistableMockMethodNames: ['mock'],\n      // disable support for vi.mock(import('./path'))\n      dynamicImportMockMethodNames: [],\n      hoistedMethodNames: ['hoist'],\n    }),\n  ],\n})\n```\n\n> [!NOTE]\n> This plugin is included in `mockerPlugin`.\n\n## hoistMocks\n\nHoist compiler hints, replace static imports with dynamic ones and update exports access to make sure live-binding is not broken.\n\nThis is required to ensure mocks are resolved before we import the user module.\n\n```ts\nimport { parseAst } from 'vite'\n\nhoistMocks(\n  `\nimport { mocked } from './some-module.js'\n\nvi.mock('./some-module.js', () => {\n  return { mocked: true }\n})\n\nmocked === true\n  `,\n  '/my-module.js',\n  parseAst\n)\n```\n\nProduces this code:\n\n```js\nvi.mock('./some-module.js', () => {\n  return { mocked: true }\n})\n\nconst __vi_import_0__ = await import('./some-module.js')\n__vi_import_0__.mocked === true\n```\n\n## dynamicImportPlugin\n\nWrap every dynamic import with `mocker.wrapDynamicImport`. This is required to ensure mocks are resolved before we import the user module. You can configure the `globalThis` accessor with `globalThisAccessor` option.\n\nIt doesn't make sense to use this plugin in isolation from other plugins.\n\n```ts\nimport { dynamicImportPlugin } from '@vitest/mocker/node'\nimport { createServer } from 'vite'\n\nawait createServer({\n  plugins: [\n    dynamicImportPlugin({\n      globalThisAccessor: 'Symbol.for(\"my-mocker\")'\n    }),\n  ],\n})\n```\n\n```ts\nawait import('./my-module.js')\n\n// produces this:\nawait globalThis[`Symbol.for('my-mocker')`].wrapDynamicImport(() => import('./my-module.js'))\n```\n\n## findMockRedirect\n\nThis method will try to find a file inside `__mocks__` folder that corresponds to the current file.\n\n```ts\nimport { findMockRedirect } from '@vitest/mocker/node'\n\n// uses sync fs APIs\nconst mockRedirect = findMockRedirect(\n  root,\n  'vscode',\n  'vscode', // if defined, will assume the file is a library name\n)\n// mockRedirect == ${root}/__mocks__/vscode.js\n```\n"
  },
  {
    "path": "packages/mocker/README.md",
    "content": "# @vitest/mocker\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/mocker?color=a1b858&label=)](https://npmx.dev/package/@vitest/mocker)\n\nVitest's module mocker implementation.\n\n[GitHub](https://github.com/vitest-dev/vitest/blob/main/packages/mocker/) | [Documentation](https://github.com/vitest-dev/vitest/blob/main/packages/mocker/EXPORTS.md)\n"
  },
  {
    "path": "packages/mocker/package.json",
    "content": "{\n  \"name\": \"@vitest/mocker\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Vitest module mocker implementation\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://github.com/vitest-dev/vitest/tree/main/packages/mocker\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/mocker\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vitest\",\n    \"test\",\n    \"mock\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./node\": {\n      \"types\": \"./dist/node.d.ts\",\n      \"default\": \"./dist/node.js\"\n    },\n    \"./browser\": {\n      \"types\": \"./dist/browser.d.ts\",\n      \"default\": \"./dist/browser.js\"\n    },\n    \"./redirect\": {\n      \"types\": \"./dist/redirect.d.ts\",\n      \"default\": \"./dist/redirect.js\"\n    },\n    \"./automock\": {\n      \"types\": \"./dist/automock.d.ts\",\n      \"default\": \"./dist/automock.js\"\n    },\n    \"./register\": {\n      \"types\": \"./dist/register.d.ts\",\n      \"default\": \"./dist/register.js\"\n    },\n    \"./auto-register\": {\n      \"types\": \"./dist/register.d.ts\",\n      \"default\": \"./dist/register.js\"\n    },\n    \"./transforms\": {\n      \"types\": \"./dist/transforms.d.ts\",\n      \"default\": \"./dist/transforms.js\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"*.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch\"\n  },\n  \"peerDependencies\": {\n    \"msw\": \"^2.4.9\",\n    \"vite\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"msw\": {\n      \"optional\": true\n    },\n    \"vite\": {\n      \"optional\": true\n    }\n  },\n  \"dependencies\": {\n    \"@vitest/spy\": \"workspace:*\",\n    \"estree-walker\": \"^3.0.3\",\n    \"magic-string\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@types/estree\": \"catalog:\",\n    \"@vitest/spy\": \"workspace:*\",\n    \"@vitest/utils\": \"workspace:*\",\n    \"acorn-walk\": \"catalog:\",\n    \"cjs-module-lexer\": \"^2.2.0\",\n    \"es-module-lexer\": \"^2.0.0\",\n    \"msw\": \"catalog:\",\n    \"pathe\": \"catalog:\",\n    \"vite\": \"^6.3.5\"\n  }\n}\n"
  },
  {
    "path": "packages/mocker/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst entries = {\n  'index': 'src/index.ts',\n  'node': 'src/node/index.ts',\n  'redirect': 'src/node/redirect.ts',\n  'automock': 'src/node/automock.ts',\n  'browser': 'src/browser/index.ts',\n  'register': 'src/browser/register.ts',\n  'auto-register': 'src/browser/auto-register.ts',\n  'transforms': 'src/node/transforms.ts',\n}\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^msw/,\n]\n\nconst dtsUtils = createDtsUtils()\n\n/** @type {import('rollup').Plugin[]} */\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  resolve({\n    preferBuiltins: true,\n  }),\n  json(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n  commonjs(),\n]\n\nexport default defineConfig([\n  {\n    input: entries,\n    output: {\n      dir: 'dist',\n      format: 'esm',\n      entryFileNames: '[name].js',\n      chunkFileNames: 'chunk-[name].js',\n    },\n    external,\n    plugins,\n    onwarn,\n  },\n  {\n    input: dtsUtils.dtsInput(entries),\n    output: {\n      dir: 'dist',\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n    onwarn,\n  },\n])\n\nfunction onwarn(message) {\n  if (['EMPTY_BUNDLE', 'CIRCULAR_DEPENDENCY'].includes(message.code)) {\n    return\n  }\n  console.error(message)\n}\n"
  },
  {
    "path": "packages/mocker/src/automocker.ts",
    "content": "type Key = string | symbol\n\nexport type CreateMockInstanceProcedure = (options?: {\n  prototypeMembers?: (string | symbol)[]\n  name?: string | symbol\n  originalImplementation?: (...args: any[]) => any\n  keepMembersImplementation?: boolean\n}) => any\n\nexport interface MockObjectOptions {\n  type: 'automock' | 'autospy'\n  globalConstructors: GlobalConstructors\n  createMockInstance: CreateMockInstanceProcedure\n}\n\nexport function mockObject(\n  options: MockObjectOptions,\n  object: Record<Key, any>,\n  mockExports: Record<Key, any> = {},\n): Record<Key, any> {\n  const finalizers = new Array<() => void>()\n  const refs = new RefTracker()\n\n  const define = (container: Record<Key, any>, key: Key, value: any) => {\n    try {\n      container[key] = value\n      return true\n    }\n    catch {\n      return false\n    }\n  }\n\n  const createMock = (currentValue: (...args: any[]) => any) => {\n    if (!options.createMockInstance) {\n      throw new Error(\n        '[@vitest/mocker] `createMockInstance` is not defined. This is a Vitest error. Please open a new issue with reproduction.',\n      )\n    }\n    const createMockInstance = options.createMockInstance\n    const prototypeMembers = currentValue.prototype\n      ? collectFunctionProperties(currentValue.prototype)\n      : []\n    return createMockInstance({\n      name: currentValue.name,\n      prototypeMembers,\n      originalImplementation: options.type === 'autospy' ? currentValue : undefined,\n      keepMembersImplementation: options.type === 'autospy',\n    })\n  }\n\n  const mockPropertiesOf = (\n    container: Record<Key, any>,\n    newContainer: Record<Key, any>,\n  ) => {\n    const containerType = getType(container)\n    const isModule = containerType === 'Module' || !!container.__esModule\n    for (const { key: property, descriptor } of getAllMockableProperties(\n      container,\n      isModule,\n      options.globalConstructors,\n    )) {\n      // Modules define their exports as getters. We want to process those.\n      if (!isModule && descriptor.get) {\n        try {\n          if (options.type === 'autospy') {\n            Object.defineProperty(newContainer, property, descriptor)\n          }\n          else {\n            Object.defineProperty(newContainer, property, {\n              configurable: descriptor.configurable,\n              enumerable: descriptor.enumerable,\n              // automatically mock getters and setters\n              // https://github.com/vitest-dev/vitest/issues/8345\n              get: () => {},\n              set: descriptor.set ? () => {} : undefined,\n            })\n          }\n        }\n        catch {\n          // Ignore errors, just move on to the next prop.\n        }\n        continue\n      }\n\n      // Skip special read-only props, we don't want to mess with those.\n      if (isReadonlyProp(container[property], property)) {\n        continue\n      }\n\n      const value = container[property]\n\n      // Special handling of references we've seen before to prevent infinite\n      // recursion in circular objects.\n      const refId = refs.getId(value)\n      if (refId !== undefined) {\n        finalizers.push(() =>\n          define(newContainer, property, refs.getMockedValue(refId)),\n        )\n        continue\n      }\n\n      const type = getType(value)\n\n      if (Array.isArray(value)) {\n        if (options.type === 'automock') {\n          define(newContainer, property, [])\n        }\n        else {\n          const array = value.map((value) => {\n            if (value && typeof value === 'object') {\n              const newObject = {}\n              mockPropertiesOf(value, newObject)\n              return newObject\n            }\n            if (typeof value === 'function') {\n              return createMock(value)\n            }\n            return value\n          })\n          define(newContainer, property, array)\n        }\n        continue\n      }\n\n      const isFunction\n        = type.includes('Function') && typeof value === 'function'\n      if (\n        (!isFunction || value._isMockFunction)\n        && type !== 'Object'\n        && type !== 'Module'\n      ) {\n        define(newContainer, property, value)\n        continue\n      }\n\n      if (options.type === 'autospy' && type === 'Module') {\n        // Replace with clean object to recursively autospy exported module objects:\n        //   export * as ns from \"./ns\"\n        // or\n        //   import * as ns from \"./ns\"\n        //   export { ns }\n        const exports = Object.create(null)\n        Object.defineProperty(exports, Symbol.toStringTag, {\n          value: 'Module',\n          configurable: true,\n          writable: true,\n        })\n        try {\n          newContainer[property] = exports\n        }\n        catch {\n          continue\n        }\n      }\n      // Sometimes this assignment fails for some unknown reason. If it does,\n      // just move along.\n      else if (!define(newContainer, property, isFunction || options.type === 'autospy' ? value : {})) {\n        continue\n      }\n\n      if (isFunction) {\n        const mock = createMock(newContainer[property])\n        newContainer[property] = mock\n      }\n\n      refs.track(value, newContainer[property])\n      mockPropertiesOf(value, newContainer[property])\n    }\n  }\n\n  const mockedObject: Record<Key, any> = mockExports\n  mockPropertiesOf(object, mockedObject)\n\n  // Plug together refs\n  for (const finalizer of finalizers) {\n    finalizer()\n  }\n\n  return mockedObject\n}\n\nclass RefTracker {\n  private idMap = new Map<any, number>()\n  private mockedValueMap = new Map<number, any>()\n\n  public getId(value: any) {\n    return this.idMap.get(value)\n  }\n\n  public getMockedValue(id: number) {\n    return this.mockedValueMap.get(id)\n  }\n\n  public track(originalValue: any, mockedValue: any): number {\n    const newId = this.idMap.size\n    this.idMap.set(originalValue, newId)\n    this.mockedValueMap.set(newId, mockedValue)\n    return newId\n  }\n}\n\nfunction getType(value: unknown): string {\n  return Object.prototype.toString.apply(value).slice(8, -1)\n}\n\nfunction isReadonlyProp(object: unknown, prop: string | symbol) {\n  if (\n    prop === 'arguments'\n    || prop === 'caller'\n    || prop === 'callee'\n    || prop === 'name'\n    || prop === 'length'\n  ) {\n    const typeName = getType(object)\n    return (\n      typeName === 'Function'\n      || typeName === 'AsyncFunction'\n      || typeName === 'GeneratorFunction'\n      || typeName === 'AsyncGeneratorFunction'\n    )\n  }\n\n  if (\n    prop === 'source'\n    || prop === 'global'\n    || prop === 'ignoreCase'\n    || prop === 'multiline'\n  ) {\n    return getType(object) === 'RegExp'\n  }\n\n  return false\n}\n\nexport interface GlobalConstructors {\n  Object: ObjectConstructor\n  Function: FunctionConstructor\n  RegExp: RegExpConstructor\n  Array: ArrayConstructor\n  Map: MapConstructor\n}\n\nfunction getAllMockableProperties(\n  obj: any,\n  isModule: boolean,\n  constructors: GlobalConstructors,\n) {\n  const { Map, Object, Function, RegExp, Array } = constructors\n\n  const allProps = new Map<\n    string | symbol,\n    { key: string | symbol; descriptor: PropertyDescriptor }\n  >()\n  let curr = obj\n  do {\n    // we don't need properties from these\n    if (\n      curr === Object.prototype\n      || curr === Function.prototype\n      || curr === RegExp.prototype\n    ) {\n      break\n    }\n\n    collectOwnProperties(curr, (key) => {\n      const descriptor = Object.getOwnPropertyDescriptor(curr, key)\n      if (descriptor) {\n        allProps.set(key, { key, descriptor })\n      }\n    })\n    // eslint-disable-next-line no-cond-assign\n  } while ((curr = Object.getPrototypeOf(curr)))\n  // default is not specified in ownKeys, if module is interoped\n  if (isModule && !allProps.has('default') && 'default' in obj) {\n    const descriptor = Object.getOwnPropertyDescriptor(obj, 'default')\n    if (descriptor) {\n      allProps.set('default', { key: 'default', descriptor })\n    }\n  }\n  return Array.from(allProps.values())\n}\n\nfunction collectOwnProperties(\n  obj: any,\n  collector: Set<string | symbol> | ((key: string | symbol) => void),\n) {\n  const collect\n    = typeof collector === 'function'\n      ? collector\n      : (key: string | symbol) => collector.add(key)\n  Object.getOwnPropertyNames(obj).forEach(collect)\n  Object.getOwnPropertySymbols(obj).forEach(collect)\n}\n\nfunction collectFunctionProperties(prototype: any) {\n  const properties = new Set<string | symbol>()\n  collectOwnProperties(prototype, (prop) => {\n    const descriptor = Object.getOwnPropertyDescriptor(prototype, prop)\n    if (!descriptor || descriptor.get) {\n      return\n    }\n    const type = getType(descriptor.value)\n    if (type.includes('Function') && !isReadonlyProp(descriptor.value, prop)) {\n      properties.add(prop)\n    }\n  })\n  return Array.from(properties)\n}\n"
  },
  {
    "path": "packages/mocker/src/browser/auto-register.ts",
    "content": "import { ModuleMockerServerInterceptor } from './interceptor-native'\nimport { registerModuleMocker } from './register'\n\nregisterModuleMocker(\n  () => new ModuleMockerServerInterceptor(),\n)\n"
  },
  {
    "path": "packages/mocker/src/browser/hints.ts",
    "content": "import type { MaybeMockedDeep } from '@vitest/spy'\nimport type { ModuleMockFactoryWithHelper, ModuleMockOptions } from '../types'\nimport type { ModuleMocker } from './mocker'\nimport { createSimpleStackTrace } from '@vitest/utils/helpers'\nimport { parseSingleStack } from '@vitest/utils/source-map'\n\nexport interface CompilerHintsOptions {\n  /**\n   * This is the key used to access the globalThis object in the worker.\n   * Unlike `globalThisAccessor` in other APIs, this is not injected into the script.\n   * ```ts\n   * // globalThisKey: '__my_variable__' produces:\n   * globalThis['__my_variable__']\n   * // globalThisKey: '\"__my_variable__\"' produces:\n   * globalThis['\"__my_variable__\"'] // notice double quotes\n   * ```\n   * @default '__vitest_mocker__'\n   */\n  globalThisKey?: string\n}\n\nexport interface ModuleMockerCompilerHints {\n  hoisted: <T>(factory: () => T) => T\n  mock: (path: string | Promise<unknown>, factory?: ModuleMockOptions | ModuleMockFactoryWithHelper) => void\n  unmock: (path: string | Promise<unknown>) => void\n  doMock: (path: string | Promise<unknown>, factory?: ModuleMockOptions | ModuleMockFactoryWithHelper) => void\n  doUnmock: (path: string | Promise<unknown>) => void\n  importActual: <T>(path: string) => Promise<T>\n  importMock: <T>(path: string) => Promise<MaybeMockedDeep<T>>\n}\n\nexport function createCompilerHints(options?: CompilerHintsOptions): ModuleMockerCompilerHints {\n  const globalThisAccessor = options?.globalThisKey || '__vitest_mocker__'\n  function _mocker(): ModuleMocker {\n    // @ts-expect-error injected by the plugin\n    return typeof globalThis[globalThisAccessor] !== 'undefined'\n      // @ts-expect-error injected by the plugin\n      ? globalThis[globalThisAccessor]\n      : new Proxy(\n          {} as any,\n          {\n            get(_, name) {\n              throw new Error(\n                'Vitest mocker was not initialized in this environment. '\n                + `vi.${String(name)}() is forbidden.`,\n              )\n            },\n          },\n        )\n  }\n\n  return {\n    hoisted<T>(factory: () => T): T {\n      if (typeof factory !== 'function') {\n        throw new TypeError(\n          `vi.hoisted() expects a function, but received a ${typeof factory}`,\n        )\n      }\n      return factory()\n    },\n\n    mock(path: string | Promise<unknown>, factory?: ModuleMockOptions | ModuleMockFactoryWithHelper): void {\n      if (typeof path !== 'string') {\n        throw new TypeError(\n          `vi.mock() expects a string path, but received a ${typeof path}`,\n        )\n      }\n      const importer = getImporter('mock')\n      _mocker().queueMock(\n        path,\n        importer,\n        typeof factory === 'function'\n          ? () =>\n              factory(() =>\n                _mocker().importActual(\n                  path,\n                  importer,\n                ),\n              )\n          : factory,\n      )\n    },\n\n    unmock(path: string | Promise<unknown>): void {\n      if (typeof path !== 'string') {\n        throw new TypeError(\n          `vi.unmock() expects a string path, but received a ${typeof path}`,\n        )\n      }\n      _mocker().queueUnmock(path, getImporter('unmock'))\n    },\n\n    doMock(path: string | Promise<unknown>, factory?: ModuleMockOptions | ModuleMockFactoryWithHelper): void {\n      if (typeof path !== 'string') {\n        throw new TypeError(\n          `vi.doMock() expects a string path, but received a ${typeof path}`,\n        )\n      }\n      const importer = getImporter('doMock')\n      _mocker().queueMock(\n        path,\n        importer,\n        typeof factory === 'function'\n          ? () =>\n              factory(() =>\n                _mocker().importActual(\n                  path,\n                  importer,\n                ),\n              )\n          : factory,\n      )\n    },\n\n    doUnmock(path: string | Promise<unknown>): void {\n      if (typeof path !== 'string') {\n        throw new TypeError(\n          `vi.doUnmock() expects a string path, but received a ${typeof path}`,\n        )\n      }\n      _mocker().queueUnmock(path, getImporter('doUnmock'))\n    },\n\n    async importActual<T = unknown>(path: string): Promise<T> {\n      return _mocker().importActual<T>(\n        path,\n        getImporter('importActual'),\n      )\n    },\n\n    async importMock<T>(path: string): Promise<MaybeMockedDeep<T>> {\n      return _mocker().importMock(path, getImporter('importMock'))\n    },\n  }\n}\n\nfunction getImporter(name: string) {\n  const stackTrace = /* @__PURE__ */ createSimpleStackTrace({ stackTraceLimit: 5 })\n  const stackArray = stackTrace.split('\\n')\n  // if there is no message in a stack trace, use the item - 1\n  const importerStackIndex = stackArray.findIndex((stack) => {\n    return stack.includes(` at Object.${name}`) || stack.includes(`${name}@`)\n  })\n  const stack = /* @__PURE__ */ parseSingleStack(stackArray[importerStackIndex + 1])\n  return stack?.file || ''\n}\n"
  },
  {
    "path": "packages/mocker/src/browser/index.ts",
    "content": "export { createCompilerHints } from './hints'\nexport type { CompilerHintsOptions, ModuleMockerCompilerHints } from './hints'\nexport type { ModuleMockerInterceptor } from './interceptor'\nexport { ModuleMockerMSWInterceptor, type ModuleMockerMSWInterceptorOptions } from './interceptor-msw'\n\nexport { ModuleMockerServerInterceptor } from './interceptor-native'\nexport { ModuleMocker } from './mocker'\nexport type {\n  ModuleMockerConfig,\n  ModuleMockerRPC,\n  ResolveIdResult,\n  ResolveMockResult,\n} from './mocker'\n"
  },
  {
    "path": "packages/mocker/src/browser/interceptor-msw.ts",
    "content": "import type { HttpHandler } from 'msw'\nimport type { SetupWorker, StartOptions } from 'msw/browser'\nimport type { ManualMockedModule, MockedModule } from '../registry'\nimport type { ModuleMockerInterceptor } from './interceptor'\nimport { MockerRegistry } from '../registry'\nimport { cleanUrl, createManualModuleSource } from '../utils'\n\nexport interface ModuleMockerMSWInterceptorOptions {\n  /**\n   * The identifier to access the globalThis object in the worker.\n   * This will be injected into the script as is, so make sure it's a valid JS expression.\n   * @example\n   * ```js\n   * // globalThisAccessor: '__my_variable__' produces:\n   * globalThis[__my_variable__]\n   * // globalThisAccessor: 'Symbol.for('secret:mocks')' produces:\n   * globalThis[Symbol.for('secret:mocks')]\n   * // globalThisAccessor: '\"__vitest_mocker__\"' (notice quotes) produces:\n   * globalThis[\"__vitest_mocker__\"]\n   * ```\n   * @default `\"__vitest_mocker__\"`\n   */\n  globalThisAccessor?: string\n  /**\n   * Options passed down to `msw.setupWorker().start(options)`\n   */\n  mswOptions?: StartOptions\n  /**\n   * A pre-configured `msw.setupWorker` instance.\n   */\n  mswWorker?: SetupWorker\n}\n\nexport class ModuleMockerMSWInterceptor implements ModuleMockerInterceptor {\n  protected readonly mocks: MockerRegistry = new MockerRegistry()\n\n  private startPromise: undefined | Promise<SetupWorker>\n  private worker: undefined | SetupWorker\n\n  constructor(\n    private readonly options: ModuleMockerMSWInterceptorOptions = {},\n  ) {\n    if (!options.globalThisAccessor) {\n      options.globalThisAccessor = '\"__vitest_mocker__\"'\n    }\n  }\n\n  async register(module: MockedModule): Promise<void> {\n    await this.init()\n    this.mocks.add(module)\n  }\n\n  async delete(url: string): Promise<void> {\n    await this.init()\n    this.mocks.delete(url)\n  }\n\n  async invalidate(): Promise<void> {\n    this.mocks.clear()\n  }\n\n  private async resolveManualMock(mock: ManualMockedModule) {\n    const exports = Object.keys(await mock.resolve())\n    const text = createManualModuleSource(mock.url, exports, this.options.globalThisAccessor)\n    return new Response(text, {\n      headers: {\n        'Content-Type': 'application/javascript',\n      },\n    })\n  }\n\n  protected async init(): Promise<SetupWorker> {\n    if (this.worker) {\n      return this.worker\n    }\n    if (this.startPromise) {\n      return this.startPromise\n    }\n    const worker = this.options.mswWorker\n    this.startPromise = Promise.all([\n      worker\n        ? {\n            setupWorker(handler: HttpHandler) {\n              worker.use(handler)\n              return worker\n            },\n          }\n        : import('msw/browser'),\n      import('msw/core/http'),\n    ]).then(([{ setupWorker }, { http }]) => {\n      const worker = setupWorker(\n        http.get(/.+/, async ({ request }) => {\n          const path = cleanQuery(request.url.slice(location.origin.length))\n          if (!this.mocks.has(path)) {\n            return passthrough()\n          }\n\n          const mock = this.mocks.get(path)!\n\n          switch (mock.type) {\n            case 'manual':\n              return this.resolveManualMock(mock)\n            case 'automock':\n            case 'autospy':\n              return Response.redirect(injectQuery(path, `mock=${mock.type}`))\n            case 'redirect':\n              return Response.redirect(mock.redirect)\n            default:\n              throw new Error(`Unknown mock type: ${(mock as any).type}`)\n          }\n        }),\n      )\n      return worker.start(this.options.mswOptions).then(() => worker)\n    }).finally(() => {\n      this.worker = worker\n      this.startPromise = undefined\n    })\n    return await this.startPromise\n  }\n}\n\nconst trailingSeparatorRE = /[?&]$/\nconst timestampRE = /\\bt=\\d{13}&?\\b/\nconst versionRE = /\\bv=\\w{8}&?\\b/\nfunction cleanQuery(url: string) {\n  return url.replace(timestampRE, '').replace(versionRE, '').replace(trailingSeparatorRE, '')\n}\n\nfunction passthrough() {\n  return new Response(null, {\n    status: 302,\n    statusText: 'Passthrough',\n    headers: {\n      'x-msw-intention': 'passthrough',\n    },\n  })\n}\n\nconst replacePercentageRE = /%/g\nfunction injectQuery(url: string, queryToInject: string): string {\n  // encode percents for consistent behavior with pathToFileURL\n  // see #2614 for details\n  const resolvedUrl = new URL(\n    url.replace(replacePercentageRE, '%25'),\n    location.href,\n  )\n  const { search, hash } = resolvedUrl\n  const pathname = cleanUrl(url)\n  return `${pathname}?${queryToInject}${search ? `&${search.slice(1)}` : ''}${\n    hash ?? ''\n  }`\n}\n"
  },
  {
    "path": "packages/mocker/src/browser/interceptor-native.ts",
    "content": "import type { MockedModule } from '../registry'\nimport type { ModuleMockerInterceptor } from './interceptor'\nimport { rpc } from './utils'\n\nexport class ModuleMockerServerInterceptor implements ModuleMockerInterceptor {\n  async register(module: MockedModule): Promise<void> {\n    await rpc('vitest:interceptor:register', module.toJSON())\n  }\n\n  async delete(id: string): Promise<void> {\n    await rpc('vitest:interceptor:delete', id)\n  }\n\n  async invalidate(): Promise<void> {\n    await rpc('vitest:interceptor:invalidate')\n  }\n}\n"
  },
  {
    "path": "packages/mocker/src/browser/interceptor.ts",
    "content": "import type { MockedModule } from '../registry'\n\nexport interface ModuleMockerInterceptor {\n  register: (module: MockedModule) => Promise<void>\n  delete: (url: string) => Promise<void>\n  invalidate: () => Promise<void>\n}\n"
  },
  {
    "path": "packages/mocker/src/browser/mocker.ts",
    "content": "import type { CreateMockInstanceProcedure } from '../automocker'\nimport type { MockedModule, MockedModuleType } from '../registry'\nimport type { ModuleMockContext, ModuleMockOptions, TestModuleMocker } from '../types'\nimport type { ModuleMockerInterceptor } from './interceptor'\nimport { extname, join } from 'pathe'\nimport { mockObject } from '../automocker'\nimport { AutomockedModule, MockerRegistry, RedirectedModule } from '../registry'\n\nconst { now } = Date\n\nexport class ModuleMocker implements TestModuleMocker {\n  protected registry: MockerRegistry = new MockerRegistry()\n\n  private queue = new Set<Promise<void>>()\n  private mockedIds = new Set<string>()\n\n  constructor(\n    private interceptor: ModuleMockerInterceptor,\n    private rpc: ModuleMockerRPC,\n    private createMockInstance: CreateMockInstanceProcedure,\n    private config: ModuleMockerConfig,\n  ) {}\n\n  public async prepare(): Promise<void> {\n    if (!this.queue.size) {\n      return\n    }\n    await Promise.all([...this.queue.values()])\n  }\n\n  public async resolveFactoryModule(id: string): Promise<Record<string | symbol, any>> {\n    const mock = this.registry.get(id)\n    if (!mock || mock.type !== 'manual') {\n      throw new Error(`Mock ${id} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`)\n    }\n    const result = await mock.resolve()\n    return result\n  }\n\n  public getFactoryModule(id: string): any {\n    const mock = this.registry.get(id)\n    if (!mock || mock.type !== 'manual') {\n      throw new Error(`Mock ${id} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`)\n    }\n    if (!mock.cache) {\n      throw new Error(`Mock ${id} wasn't resolved. This is probably a Vitest error. Please, open a new issue with reproduction.`)\n    }\n    return mock.cache\n  }\n\n  public async invalidate(): Promise<void> {\n    const ids = Array.from(this.mockedIds)\n    if (!ids.length) {\n      return\n    }\n    await this.rpc.invalidate(ids)\n    await this.interceptor.invalidate()\n    this.registry.clear()\n  }\n\n  public async importActual<T>(id: string, importer: string): Promise<T> {\n    const resolved = await this.rpc.resolveId(id, importer)\n    if (resolved == null) {\n      throw new Error(\n        `[vitest] Cannot resolve \"${id}\" imported from \"${importer}\"`,\n      )\n    }\n    const ext = extname(resolved.id)\n    const url = new URL(resolved.url, this.getBaseUrl())\n    const query = `_vitest_original&ext${ext}`\n    const actualUrl = `${url.pathname}${\n      url.search ? `${url.search}&${query}` : `?${query}`\n    }${url.hash}`\n    return this.wrapDynamicImport(() => import(/* @vite-ignore */ actualUrl)).then((mod) => {\n      if (!resolved.optimized || typeof mod.default === 'undefined') {\n        return mod\n      }\n      // vite injects this helper for optimized modules, so we try to follow the same behavior\n      const m = mod.default\n      return m?.__esModule ? m : { ...((typeof m === 'object' && !Array.isArray(m)) || typeof m === 'function' ? m : {}), default: m }\n    })\n  }\n\n  protected getBaseUrl(): string {\n    return location.href\n  }\n\n  public async importMock<T>(rawId: string, importer: string): Promise<T> {\n    await this.prepare()\n    const { resolvedId, resolvedUrl, redirectUrl } = await this.rpc.resolveMock(\n      rawId,\n      importer,\n      { mock: 'auto' },\n    )\n\n    const mockUrl = this.resolveMockPath(cleanVersion(resolvedUrl))\n    let mock = this.registry.get(mockUrl)\n\n    if (!mock) {\n      if (redirectUrl) {\n        const resolvedRedirect = new URL(this.resolveMockPath(cleanVersion(redirectUrl)), this.getBaseUrl()).toString()\n        mock = new RedirectedModule(rawId, resolvedId, mockUrl, resolvedRedirect)\n      }\n      else {\n        mock = new AutomockedModule(rawId, resolvedId, mockUrl)\n      }\n    }\n\n    if (mock.type === 'manual') {\n      return await mock.resolve() as T\n    }\n\n    if (mock.type === 'automock' || mock.type === 'autospy') {\n      const url = new URL(`/@id/${resolvedId}`, this.getBaseUrl())\n      const query = url.search ? `${url.search}&t=${now()}` : `?t=${now()}`\n      const moduleObject = await import(/* @vite-ignore */ `${url.pathname}${query}&mock=${mock.type}${url.hash}`)\n      return this.mockObject(moduleObject, mock.type) as T\n    }\n\n    return import(/* @vite-ignore */ mock.redirect)\n  }\n\n  public mockObject(\n    object: Record<string | symbol, any>,\n    moduleType?: 'automock' | 'autospy',\n  ): Record<string | symbol, any>\n  public mockObject(\n    object: Record<string | symbol, any>,\n    mockExports: Record<string | symbol, any> | undefined,\n    moduleType?: 'automock' | 'autospy',\n  ): Record<string | symbol, any>\n  public mockObject(\n    object: Record<string | symbol, any>,\n    mockExportsOrModuleType?: Record<string | symbol, any> | 'automock' | 'autospy',\n    moduleType?: 'automock' | 'autospy',\n  ): Record<string | symbol, any> {\n    let mockExports: Record<string | symbol, any> | undefined\n    if (mockExportsOrModuleType === 'automock' || mockExportsOrModuleType === 'autospy') {\n      moduleType = mockExportsOrModuleType\n      mockExports = undefined\n    }\n    else {\n      mockExports = mockExportsOrModuleType\n    }\n    moduleType ??= 'automock'\n    const result = mockObject(\n      {\n        globalConstructors: {\n          Object,\n          Function,\n          Array,\n          Map,\n          RegExp,\n        },\n        createMockInstance: this.createMockInstance,\n        type: moduleType,\n      },\n      object,\n      mockExports,\n    )\n    return result\n  }\n\n  public getMockContext(): ModuleMockContext {\n    return {\n      callstack: null,\n    }\n  }\n\n  public queueMock(rawId: string, importer: string, factoryOrOptions?: ModuleMockOptions | (() => any)): void {\n    const promise = this.rpc\n      .resolveMock(rawId, importer, {\n        mock: typeof factoryOrOptions === 'function'\n          ? 'factory'\n          : factoryOrOptions?.spy ? 'spy' : 'auto',\n      })\n      .then(async ({ redirectUrl, resolvedId, resolvedUrl, needsInterop, mockType }) => {\n        const mockUrl = this.resolveMockPath(cleanVersion(resolvedUrl))\n        this.mockedIds.add(resolvedId)\n        const factory = typeof factoryOrOptions === 'function'\n          ? async () => {\n            const data = await factoryOrOptions()\n            // vite wraps all external modules that have \"needsInterop\" in a function that\n            // merges all exports from default into the module object\n            return needsInterop ? { default: data } : data\n          }\n          : undefined\n\n        const mockRedirect = typeof redirectUrl === 'string'\n          ? new URL(this.resolveMockPath(cleanVersion(redirectUrl)), this.getBaseUrl()).toString()\n          : null\n\n        let module: MockedModule\n        if (mockType === 'manual') {\n          module = this.registry.register('manual', rawId, resolvedId, mockUrl, factory!)\n        }\n        // autospy takes higher priority over redirect, so it needs to be checked first\n        else if (mockType === 'autospy') {\n          module = this.registry.register('autospy', rawId, resolvedId, mockUrl)\n        }\n        else if (mockType === 'redirect') {\n          module = this.registry.register('redirect', rawId, resolvedId, mockUrl, mockRedirect!)\n        }\n        else {\n          module = this.registry.register('automock', rawId, resolvedId, mockUrl)\n        }\n\n        await this.interceptor.register(module)\n      })\n      .finally(() => {\n        this.queue.delete(promise)\n      })\n    this.queue.add(promise)\n  }\n\n  public queueUnmock(id: string, importer: string): void {\n    const promise = this.rpc\n      .resolveId(id, importer)\n      .then(async (resolved) => {\n        if (!resolved) {\n          return\n        }\n        const mockUrl = this.resolveMockPath(cleanVersion(resolved.url))\n        this.mockedIds.add(resolved.id)\n        this.registry.delete(mockUrl)\n        await this.interceptor.delete(mockUrl)\n      })\n      .finally(() => {\n        this.queue.delete(promise)\n      })\n    this.queue.add(promise)\n  }\n\n  // We need to await mock registration before importing the actual module\n  // In case there is a mocked module in the import chain\n  public wrapDynamicImport<T>(moduleFactory: () => Promise<T>): Promise<T> {\n    if (typeof moduleFactory === 'function') {\n      const promise = new Promise<T>((resolve, reject) => {\n        this.prepare().finally(() => {\n          moduleFactory().then(resolve, reject)\n        })\n      })\n      return promise\n    }\n    return moduleFactory\n  }\n\n  public getMockedModuleById(id: string): MockedModule | undefined {\n    return this.registry.getById(id)\n  }\n\n  public reset(): void {\n    this.registry.clear()\n    this.mockedIds.clear()\n    this.queue.clear()\n  }\n\n  private resolveMockPath(path: string) {\n    const config = this.config\n    const fsRoot = join('/@fs/', config.root)\n\n    // URL can be /file/path.js, but path is resolved to /file/path\n    if (path.startsWith(config.root)) {\n      return path.slice(config.root.length)\n    }\n\n    if (path.startsWith(fsRoot)) {\n      return path.slice(fsRoot.length)\n    }\n\n    return path\n  }\n}\n\nconst versionRegexp = /(\\?|&)v=\\w{8}/\nfunction cleanVersion(url: string) {\n  return url.replace(versionRegexp, '')\n}\n\nexport interface ResolveIdResult {\n  id: string\n  url: string\n  optimized: boolean\n}\n\nexport interface ResolveMockResult {\n  mockType: MockedModuleType\n  resolvedId: string\n  resolvedUrl: string\n  redirectUrl?: string | null\n  needsInterop?: boolean\n}\n\nexport interface ModuleMockerRPC {\n  invalidate: (ids: string[]) => Promise<void>\n  resolveId: (id: string, importer: string) => Promise<ResolveIdResult | null>\n  resolveMock: (\n    id: string,\n    importer: string,\n    options: { mock: 'spy' | 'factory' | 'auto' },\n  ) => Promise<ResolveMockResult>\n}\n\nexport interface ModuleMockerConfig {\n  root: string\n}\n"
  },
  {
    "path": "packages/mocker/src/browser/register.ts",
    "content": "import type { ModuleMockerCompilerHints } from './hints'\nimport type { ModuleMockerInterceptor } from './index'\nimport { createMockInstance } from '@vitest/spy'\nimport { createCompilerHints } from './hints'\nimport { ModuleMocker } from './index'\nimport { hot, rpc } from './utils'\n\ndeclare const __VITEST_GLOBAL_THIS_ACCESSOR__: string\ndeclare const __VITEST_MOCKER_ROOT__: string\n\nexport function registerModuleMocker(\n  interceptor: (accessor: string) => ModuleMockerInterceptor,\n): ModuleMockerCompilerHints {\n  const mocker = new ModuleMocker(\n    interceptor(__VITEST_GLOBAL_THIS_ACCESSOR__),\n    {\n      resolveId(id, importer) {\n        return rpc('vitest:mocks:resolveId', { id, importer })\n      },\n      resolveMock(id, importer, options) {\n        return rpc('vitest:mocks:resolveMock', { id, importer, options })\n      },\n      async invalidate(ids) {\n        return rpc('vitest:mocks:invalidate', { ids })\n      },\n    },\n    createMockInstance,\n    {\n      root: __VITEST_MOCKER_ROOT__,\n    },\n  )\n\n  ;(globalThis as any)[__VITEST_GLOBAL_THIS_ACCESSOR__] = mocker\n\n  registerNativeFactoryResolver(mocker)\n\n  return createCompilerHints({\n    globalThisKey: __VITEST_GLOBAL_THIS_ACCESSOR__,\n  })\n}\n\nexport function registerNativeFactoryResolver(mocker: ModuleMocker): void {\n  hot.on('vitest:interceptor:resolve', async (url: string) => {\n    const exports = await mocker.resolveFactoryModule(url)\n    const keys = Object.keys(exports)\n    hot.send('vitest:interceptor:resolved', { url, keys })\n  })\n}\n"
  },
  {
    "path": "packages/mocker/src/browser/utils.ts",
    "content": "import type { ViteHotContext } from 'vite/types/hot.js'\n\nconst hot: ViteHotContext = import.meta.hot! || {\n  on: warn,\n  off: warn,\n  send: warn,\n}\n\nfunction warn() {\n  console.warn('Vitest mocker cannot work if Vite didn\\'t establish WS connection.')\n}\n\nexport { hot }\n\nexport function rpc<T>(event: string, data?: any): Promise<T> {\n  hot.send(event, data)\n  return new Promise<T>((resolve, reject) => {\n    const timeout = setTimeout(() => {\n      reject(new Error(`Failed to resolve ${event} in time`))\n    }, 5_000)\n    hot.on(`${event}:result`, function r(data) {\n      resolve(data)\n      clearTimeout(timeout)\n      hot.off(`${event}:result`, r)\n    })\n  })\n}\n"
  },
  {
    "path": "packages/mocker/src/index.ts",
    "content": "export { mockObject } from './automocker'\nexport type { GlobalConstructors, MockObjectOptions } from './automocker'\n\nexport {\n  AutomockedModule,\n  AutospiedModule,\n  ManualMockedModule,\n  MockerRegistry,\n  RedirectedModule,\n} from './registry'\nexport type {\n  AutomockedModuleSerialized,\n  AutospiedModuleSerialized,\n  ManualMockedModuleSerialized,\n  MockedModule,\n  MockedModuleSerialized,\n  MockedModuleType,\n  RedirectedModuleSerialized,\n} from './registry'\n\nexport type {\n  ModuleMockContext,\n  ModuleMockFactory,\n  ModuleMockFactoryWithHelper,\n  ModuleMockOptions,\n  ServerIdResolution,\n  ServerMockResolution,\n  TestModuleMocker,\n} from './types'\n"
  },
  {
    "path": "packages/mocker/src/node/automock.ts",
    "content": "import type { Declaration, ExportAllDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, Expression, Pattern, Positioned, Program } from './esmWalker'\nimport { readFileSync } from 'node:fs'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport MagicString from 'magic-string'\nimport { getArbitraryModuleIdentifier } from './esmWalker'\nimport { collectModuleExports, resolveModuleFormat, transformCode } from './parsers'\n\nexport interface AutomockOptions {\n  /**\n   * @default \"__vitest_mocker__\"\n   */\n  globalThisAccessor?: string\n  id?: string\n}\n\n// TODO: better source map replacement\nexport function automockModule(\n  code: string,\n  mockType: 'automock' | 'autospy',\n  parse: (code: string) => any,\n  options: AutomockOptions = {},\n): MagicString {\n  const globalThisAccessor = options.globalThisAccessor || '\"__vitest_mocker__\"'\n  let ast: Program\n  try {\n    ast = parse(code) as Program\n  }\n  catch (cause) {\n    if (options.id) {\n      throw new Error(`failed to parse ${options.id}`, { cause })\n    }\n    throw cause\n  }\n\n  const m = new MagicString(code)\n\n  const allSpecifiers: { name: string; alias?: string }[] = []\n  const replacers: (() => void)[] = []\n  let importIndex = 0\n  for (const _node of ast.body) {\n    if (_node.type === 'ExportAllDeclaration') {\n      const node = _node as Positioned<ExportAllDeclaration>\n      // TODO: pass it down in the browser mode\n      if (!options.id) {\n        throw new Error(\n          `automocking files with \\`export *\\` is not supported because it cannot be easily statically analysed`,\n        )\n      }\n\n      const source = node.source.value\n      if (typeof source !== 'string') {\n        throw new TypeError(`unknown source type while automocking: ${source}`)\n      }\n\n      const moduleUrl = import.meta.resolve(source, pathToFileURL(options.id).toString())\n      const modulePath = fileURLToPath(moduleUrl)\n      const moduleContent = readFileSync(modulePath, 'utf-8')\n      const transformedCode = transformCode(moduleContent, moduleUrl)\n      const moduleFormat = resolveModuleFormat(moduleUrl, transformedCode)\n      const moduleExports = collectModuleExports(modulePath, transformedCode, moduleFormat || 'module')\n      replacers.push(() => {\n        const importNames: string[] = []\n        moduleExports.forEach((exportName) => {\n          const isReexported = allSpecifiers.some(({ name, alias }) => name === exportName || alias === exportName)\n          if (!isReexported) {\n            importNames.push(exportName)\n            allSpecifiers.push({ name: exportName })\n          }\n        })\n\n        const importString = `import { ${importNames.join(', ')} } from '${source}';`\n\n        m.overwrite(node.start, node.end, importString)\n      })\n    }\n\n    if (_node.type === 'ExportNamedDeclaration') {\n      const node = _node as Positioned<ExportNamedDeclaration>\n      const declaration = node.declaration // export const name\n\n      function traversePattern(expression: Pattern) {\n        // export const test = '1'\n        if (expression.type === 'Identifier') {\n          allSpecifiers.push({ name: expression.name })\n        }\n        // export const [test, ...rest] = [1, 2, 3]\n        else if (expression.type === 'ArrayPattern') {\n          expression.elements.forEach((element) => {\n            if (!element) {\n              return\n            }\n            traversePattern(element)\n          })\n        }\n        else if (expression.type === 'ObjectPattern') {\n          expression.properties.forEach((property) => {\n            // export const { ...rest } = {}\n            if (property.type === 'RestElement') {\n              traversePattern(property)\n            }\n            // export const { test, test2: alias } = {}\n            else if (property.type === 'Property') {\n              traversePattern(property.value)\n            }\n            else {\n              property satisfies never\n            }\n          })\n        }\n        else if (expression.type === 'RestElement') {\n          traversePattern(expression.argument)\n        }\n        // const [name[1], name[2]] = []\n        // cannot be used in export\n        else if (expression.type === 'AssignmentPattern') {\n          throw new Error(\n            `AssignmentPattern is not supported. Please open a new bug report.`,\n          )\n        }\n        // const test = thing.func()\n        // cannot be used in export\n        else if (expression.type === 'MemberExpression') {\n          throw new Error(\n            `MemberExpression is not supported. Please open a new bug report.`,\n          )\n        }\n        else {\n          expression satisfies never\n        }\n      }\n\n      if (declaration) {\n        if (declaration.type === 'FunctionDeclaration') {\n          allSpecifiers.push({ name: declaration.id.name })\n        }\n        else if (declaration.type === 'VariableDeclaration') {\n          declaration.declarations.forEach((declaration) => {\n            traversePattern(declaration.id)\n          })\n        }\n        else if (declaration.type === 'ClassDeclaration') {\n          allSpecifiers.push({ name: declaration.id.name })\n        }\n        else {\n          declaration satisfies never\n        }\n        m.remove(node.start, (declaration as Positioned<Declaration>).start)\n      }\n\n      const specifiers = node.specifiers || []\n      const source = node.source\n\n      if (!source && specifiers.length) {\n        specifiers.forEach((specifier) => {\n          allSpecifiers.push({\n            alias: getArbitraryModuleIdentifier(specifier.exported),\n            name: getArbitraryModuleIdentifier(specifier.local),\n          })\n        })\n        m.remove(node.start, node.end)\n      }\n      else if (source && specifiers.length) {\n        const importNames: [string, string][] = []\n\n        specifiers.forEach((specifier) => {\n          const importedName = `__vitest_imported_${importIndex++}__`\n          importNames.push([getArbitraryModuleIdentifier(specifier.local), importedName])\n          allSpecifiers.push({\n            name: importedName,\n            alias: getArbitraryModuleIdentifier(specifier.exported),\n          })\n        })\n\n        const importString = `import { ${importNames\n          .map(([name, alias]) => `${name} as ${alias}`)\n          .join(', ')} } from '${source.value}'`\n\n        m.overwrite(node.start, node.end, importString)\n      }\n    }\n    if (_node.type === 'ExportDefaultDeclaration') {\n      const node = _node as Positioned<ExportDefaultDeclaration>\n      const declaration = node.declaration as Positioned<Expression>\n      allSpecifiers.push({ name: '__vitest_default', alias: 'default' })\n      m.overwrite(node.start, declaration.start, `const __vitest_default = `)\n    }\n  }\n  replacers.forEach(cb => cb())\n  const moduleObject = `\nconst __vitest_current_es_module__ = {\n  __esModule: true,\n  ${allSpecifiers.map(({ name }) => `[\"${name}\"]: ${name},`).join('\\n  ')}\n}\nconst __vitest_mocked_module__ = globalThis[${globalThisAccessor}].mockObject(__vitest_current_es_module__, \"${mockType}\")\n`\n  const assigning = allSpecifiers\n    .map(({ name }, index) => {\n      return `const __vitest_mocked_${index}__ = __vitest_mocked_module__[\"${name}\"]`\n    })\n    .join('\\n')\n\n  const redeclarations = allSpecifiers\n    .map(({ name, alias }, index) => {\n      return `  __vitest_mocked_${index}__ as ${alias || name},`\n    })\n    .join('\\n')\n  const specifiersExports = `\nexport {\n${redeclarations}\n}\n`\n  m.append(moduleObject + assigning + specifiersExports)\n  return m\n}\n"
  },
  {
    "path": "packages/mocker/src/node/automockPlugin.ts",
    "content": "import type { Plugin } from 'vite'\nimport type { AutomockOptions } from './automock'\nimport { cleanUrl } from '../utils'\nimport { automockModule } from './automock'\n\nexport type { AutomockOptions as AutomockPluginOptions } from './automock'\n\nexport function automockPlugin(options: AutomockOptions = {}): Plugin {\n  return {\n    name: 'vitest:automock',\n    enforce: 'post',\n    transform(code, id) {\n      if (id.includes('mock=automock') || id.includes('mock=autospy')) {\n        const mockType = id.includes('mock=automock') ? 'automock' : 'autospy'\n        const ms = automockModule(code, mockType, this.parse, options)\n        return {\n          code: ms.toString(),\n          map: ms.generateMap({ hires: 'boundary', source: cleanUrl(id) }),\n        }\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/mocker/src/node/dynamicImportPlugin.ts",
    "content": "import type { SourceMap } from 'magic-string'\nimport type { Plugin, Rollup } from 'vite'\nimport type { Expression, Positioned } from './esmWalker'\nimport MagicString from 'magic-string'\nimport { esmWalker } from './esmWalker'\n\nconst regexDynamicImport = /import\\s*\\(/\n\nexport interface DynamicImportPluginOptions {\n  /**\n   * @default `\"__vitest_mocker__\"`\n   */\n  globalThisAccessor?: string\n  filter?: (id: string) => boolean\n}\n\nexport function dynamicImportPlugin(options: DynamicImportPluginOptions = {}): Plugin {\n  return {\n    name: 'vitest:browser:esm-injector',\n    enforce: 'post',\n    transform(source, id) {\n      // TODO: test is not called for static imports\n      if (!regexDynamicImport.test(source)) {\n        return\n      }\n      if (options.filter && !options.filter(id)) {\n        return\n      }\n      return injectDynamicImport(source, id, this.parse, options)\n    },\n  }\n}\n\nexport interface DynamicImportInjectorResult {\n  code: string\n  map: SourceMap\n}\n\nexport function injectDynamicImport(\n  code: string,\n  id: string,\n  parse: Rollup.PluginContext['parse'],\n  options: DynamicImportPluginOptions = {},\n): DynamicImportInjectorResult | undefined {\n  if (code.includes('wrapDynamicImport')) {\n    return\n  }\n\n  const s = new MagicString(code)\n\n  let ast: ReturnType<Rollup.PluginContext['parse']>\n  try {\n    ast = parse(code)\n  }\n  catch (err) {\n    console.error(`Cannot parse ${id}:\\n${(err as any).message}`)\n    return\n  }\n\n  // 3. convert references to import bindings & import.meta references\n  esmWalker(ast, {\n    // TODO: make env updatable\n    onImportMeta() {\n      // s.update(node.start, node.end, viImportMetaKey)\n    },\n    onDynamicImport(node) {\n      const globalThisAccessor = options.globalThisAccessor || '\"__vitest_mocker__\"'\n      const replaceString = `globalThis[${globalThisAccessor}].wrapDynamicImport(() => import(`\n      const importSubstring = code.substring(node.start, node.end)\n      const hasIgnore = importSubstring.includes('/* @vite-ignore */')\n      s.overwrite(\n        node.start,\n        (node.source as Positioned<Expression>).start,\n        replaceString + (hasIgnore ? '/* @vite-ignore */ ' : ''),\n      )\n      s.overwrite(node.end - 1, node.end, '))')\n    },\n  })\n\n  return {\n    code: s.toString(),\n    map: s.generateMap({ hires: 'boundary', source: id }),\n  }\n}\n"
  },
  {
    "path": "packages/mocker/src/node/esmWalker.ts",
    "content": "import type {\n  Node as _Node,\n  CallExpression,\n  Function as FunctionNode,\n  Identifier,\n  ImportExpression,\n  Literal,\n  MetaProperty,\n  Pattern,\n  Property,\n  VariableDeclaration,\n} from 'estree'\nimport type { Rollup } from 'vite'\nimport { walk as eswalk } from 'estree-walker'\n\nexport type * from 'estree'\n\nexport type Positioned<T> = T & {\n  start: number\n  end: number\n}\n\nexport type Node = Positioned<_Node>\n\ninterface IdentifierInfo {\n  /**\n   * If the identifier is used in a property shorthand\n   * { foo } -> { foo: __import_x__.foo }\n   */\n  hasBindingShortcut: boolean\n  /**\n   * The identifier is used in a class declaration\n   */\n  classDeclaration: boolean\n  /**\n   * The identifier is a name for a class expression\n   */\n  classExpression: boolean\n}\n\ninterface Visitors {\n  onIdentifier?: (\n    node: Positioned<Identifier>,\n    info: IdentifierInfo,\n    parentStack: Node[],\n  ) => void\n  onImportMeta?: (node: Positioned<MetaProperty>) => void\n  onDynamicImport?: (node: Positioned<ImportExpression>) => void\n  onCallExpression?: (node: Positioned<CallExpression>) => void\n}\n\nconst isNodeInPatternWeakSet = new WeakSet<_Node>()\nexport function setIsNodeInPattern(node: Property): WeakSet<_Node> {\n  return isNodeInPatternWeakSet.add(node)\n}\nexport function isNodeInPattern(node: _Node): node is Property {\n  return isNodeInPatternWeakSet.has(node)\n}\n\n/**\n * Same logic from \\@vue/compiler-core & \\@vue/compiler-sfc\n * Except this is using acorn AST\n */\nexport function esmWalker(\n  root: ReturnType<Rollup.PluginContext['parse']>,\n  { onIdentifier, onImportMeta, onDynamicImport, onCallExpression }: Visitors,\n): void {\n  const parentStack: Node[] = []\n  const varKindStack: VariableDeclaration['kind'][] = []\n  const scopeMap = new WeakMap<_Node, Set<string>>()\n  const identifiers: [id: any, stack: Node[]][] = []\n\n  const setScope = (node: _Node, name: string) => {\n    let scopeIds = scopeMap.get(node)\n    if (scopeIds && scopeIds.has(name)) {\n      return\n    }\n\n    if (!scopeIds) {\n      scopeIds = new Set()\n      scopeMap.set(node, scopeIds)\n    }\n    scopeIds.add(name)\n  }\n\n  function isInScope(name: string, parents: Node[]) {\n    return parents.some(node => node && scopeMap.get(node)?.has(name))\n  }\n  function handlePattern(p: Pattern, parentScope: _Node) {\n    if (p.type === 'Identifier') {\n      setScope(parentScope, p.name)\n    }\n    else if (p.type === 'RestElement') {\n      handlePattern(p.argument, parentScope)\n    }\n    else if (p.type === 'ObjectPattern') {\n      p.properties.forEach((property) => {\n        if (property.type === 'RestElement') {\n          setScope(parentScope, (property.argument as Identifier).name)\n        }\n        else {\n          handlePattern(property.value, parentScope)\n        }\n      })\n    }\n    else if (p.type === 'ArrayPattern') {\n      p.elements.forEach((element) => {\n        if (element) {\n          handlePattern(element, parentScope)\n        }\n      })\n    }\n    else if (p.type === 'AssignmentPattern') {\n      handlePattern(p.left, parentScope)\n    }\n    else {\n      setScope(parentScope, (p as any).name)\n    }\n  }\n\n  eswalk(root as Node, {\n    enter(node, parent) {\n      if (node.type === 'ImportDeclaration') {\n        return this.skip()\n      }\n\n      // track parent stack, skip for \"else-if\"/\"else\" branches as acorn nests\n      // the ast within \"if\" nodes instead of flattening them\n      if (\n        parent\n        && !(parent.type === 'IfStatement' && node === parent.alternate)\n      ) {\n        parentStack.unshift(parent as Node)\n      }\n\n      // track variable declaration kind stack used by VariableDeclarator\n      if (node.type === 'VariableDeclaration') {\n        varKindStack.unshift(node.kind)\n      }\n\n      if (node.type === 'CallExpression') {\n        onCallExpression?.(node as Positioned<CallExpression>)\n      }\n\n      if (node.type === 'MetaProperty' && node.meta.name === 'import') {\n        onImportMeta?.(node as Positioned<MetaProperty>)\n      }\n      else if (node.type === 'ImportExpression') {\n        onDynamicImport?.(node as Positioned<ImportExpression>)\n      }\n\n      if (node.type === 'Identifier') {\n        if (\n          !isInScope(node.name, parentStack)\n          && isRefIdentifier(node, parent!, parentStack)\n        ) {\n          // record the identifier, for DFS -> BFS\n          identifiers.push([node, parentStack.slice(0)])\n        }\n      }\n      else if (node.type === 'ClassDeclaration' && node.id) {\n        // A class declaration name could shadow an import, so add its name to the parent scope\n        const parentScope = findParentScope(parentStack)\n        if (parentScope) {\n          setScope(parentScope, node.id.name)\n        }\n      }\n      else if (node.type === 'ClassExpression' && node.id) {\n        // A class expression name could shadow an import, so add its name to the scope\n        setScope(node, node.id.name)\n      }\n      else if (isFunctionNode(node)) {\n        // If it is a function declaration, it could be shadowing an import\n        // Add its name to the scope so it won't get replaced\n        if (node.type === 'FunctionDeclaration') {\n          const parentScope = findParentScope(parentStack)\n          if (parentScope) {\n            setScope(parentScope, node.id!.name)\n          }\n        }\n        // walk function expressions and add its arguments to known identifiers\n        // so that we don't prefix them\n        node.params.forEach((p) => {\n          if (p.type === 'ObjectPattern' || p.type === 'ArrayPattern') {\n            handlePattern(p, node)\n            return\n          }\n          (eswalk as any)(p.type === 'AssignmentPattern' ? p.left : p, {\n            enter(child: Node, parent: Node) {\n              // skip params default value of destructure\n              if (\n                parent?.type === 'AssignmentPattern'\n                && parent?.right === child\n              ) {\n                return this.skip()\n              }\n\n              if (child.type !== 'Identifier') {\n                return\n              }\n              // do not record as scope variable if is a destructuring keyword\n              if (isStaticPropertyKey(child, parent)) {\n                return\n              }\n              // do not record if this is a default value\n              // assignment of a destructuring variable\n              if (\n                (parent?.type === 'TemplateLiteral'\n                  && parent?.expressions.includes(child))\n                || (parent?.type === 'CallExpression' && parent?.callee === child)\n              ) {\n                return\n              }\n\n              setScope(node, child.name)\n            },\n          })\n        })\n      }\n      else if (node.type === 'Property' && parent!.type === 'ObjectPattern') {\n        // mark property in destructuring pattern\n        setIsNodeInPattern(node)\n      }\n      else if (node.type === 'VariableDeclarator') {\n        const parentFunction = findParentScope(\n          parentStack,\n          varKindStack[0] === 'var',\n        )\n        if (parentFunction) {\n          handlePattern(node.id, parentFunction)\n        }\n      }\n      else if (node.type === 'CatchClause' && node.param) {\n        handlePattern(node.param, node)\n      }\n    },\n\n    leave(node, parent) {\n      // untrack parent stack from above\n      if (\n        parent\n        && !(parent.type === 'IfStatement' && node === parent.alternate)\n      ) {\n        parentStack.shift()\n      }\n\n      if (node.type === 'VariableDeclaration') {\n        varKindStack.shift()\n      }\n    },\n  })\n\n  // emit the identifier events in BFS so the hoisted declarations\n  // can be captured correctly\n  identifiers.forEach(([node, stack]) => {\n    if (!isInScope(node.name, stack)) {\n      const parent = stack[0]\n      const grandparent = stack[1]\n      const hasBindingShortcut\n        = isStaticProperty(parent)\n          && parent.shorthand\n          && (!isNodeInPattern(parent)\n            || isInDestructuringAssignment(parent, parentStack))\n\n      const classDeclaration\n        = (parent.type === 'PropertyDefinition'\n          && grandparent?.type === 'ClassBody')\n        || (parent.type === 'ClassDeclaration' && node === parent.superClass)\n\n      const classExpression\n        = parent.type === 'ClassExpression' && node === parent.id\n\n      onIdentifier?.(\n        node,\n        {\n          hasBindingShortcut,\n          classDeclaration,\n          classExpression,\n        },\n        stack,\n      )\n    }\n  })\n}\n\nfunction isRefIdentifier(id: Identifier, parent: _Node, parentStack: _Node[]) {\n  // declaration id\n  if (\n    parent.type === 'CatchClause'\n    || ((parent.type === 'VariableDeclarator'\n      || parent.type === 'ClassDeclaration')\n    && parent.id === id)\n  ) {\n    return false\n  }\n\n  if (isFunctionNode(parent)) {\n    // function declaration/expression id\n    if ((parent as any).id === id) {\n      return false\n    }\n\n    // params list\n    if (parent.params.includes(id)) {\n      return false\n    }\n  }\n\n  // class method name\n  if (parent.type === 'MethodDefinition' && !parent.computed) {\n    return false\n  }\n\n  // property key\n  if (isStaticPropertyKey(id, parent)) {\n    return false\n  }\n\n  // object destructuring pattern\n  if (isNodeInPattern(parent) && parent.value === id) {\n    return false\n  }\n\n  // non-assignment array destructuring pattern\n  if (\n    parent.type === 'ArrayPattern'\n    && !isInDestructuringAssignment(parent, parentStack)\n  ) {\n    return false\n  }\n\n  // member expression property\n  if (\n    parent.type === 'MemberExpression'\n    && parent.property === id\n    && !parent.computed\n  ) {\n    return false\n  }\n\n  if (parent.type === 'ExportSpecifier') {\n    return false\n  }\n\n  // is a special keyword but parsed as identifier\n  if (id.name === 'arguments') {\n    return false\n  }\n\n  return true\n}\n\nexport function isStaticProperty(node: _Node): node is Property {\n  return node && node.type === 'Property' && !node.computed\n}\n\nexport function isStaticPropertyKey(node: _Node, parent: _Node): boolean {\n  return isStaticProperty(parent) && parent.key === node\n}\n\nconst functionNodeTypeRE = /Function(?:Expression|Declaration)$|Method$/\nexport function isFunctionNode(node: _Node): node is FunctionNode {\n  return functionNodeTypeRE.test(node.type)\n}\n\nconst blockNodeTypeRE = /^BlockStatement$|^For(?:In|Of)?Statement$/\nfunction isBlock(node: _Node) {\n  return blockNodeTypeRE.test(node.type)\n}\n\nfunction findParentScope(\n  parentStack: _Node[],\n  isVar = false,\n): _Node | undefined {\n  return parentStack.find(isVar ? isFunctionNode : isBlock)\n}\n\nexport function isInDestructuringAssignment(\n  parent: _Node,\n  parentStack: _Node[],\n): boolean {\n  if (\n    parent\n    && (parent.type === 'Property' || parent.type === 'ArrayPattern')\n  ) {\n    return parentStack.some(i => i.type === 'AssignmentExpression')\n  }\n\n  return false\n}\n\nexport function getArbitraryModuleIdentifier(node: Identifier | Literal): string {\n  return node.type === 'Identifier' ? node.name : node.raw!\n}\n"
  },
  {
    "path": "packages/mocker/src/node/hoistMocks.ts",
    "content": "import type {\n  AwaitExpression,\n  CallExpression,\n  ExportDefaultDeclaration,\n  ExportNamedDeclaration,\n  Expression,\n  Identifier,\n  ImportDeclaration,\n  VariableDeclaration,\n} from 'estree'\nimport type { Node, Positioned } from './esmWalker'\nimport { findNodeAround } from 'acorn-walk'\nimport MagicString from 'magic-string'\nimport { esmWalker } from './esmWalker'\n\nexport interface HoistMocksOptions {\n  /**\n   * List of modules that should always be imported before compiler hints.\n   * @default 'vitest'\n   */\n  hoistedModule?: string\n  /**\n   * @default [\"vi\", \"vitest\"]\n   */\n  utilsObjectNames?: string[]\n  /**\n   * @default [\"mock\", \"unmock\"]\n   */\n  hoistableMockMethodNames?: string[]\n  /**\n   * @default [\"mock\", \"unmock\", \"doMock\", \"doUnmock\"]\n   */\n  dynamicImportMockMethodNames?: string[]\n  /**\n   * @default [\"hoisted\"]\n   */\n  hoistedMethodNames?: string[]\n  globalThisAccessor?: string\n  regexpHoistable?: RegExp\n  codeFrameGenerator?: CodeFrameGenerator\n  magicString?: () => MagicString\n}\n\nconst API_NOT_FOUND_ERROR = `There are some problems in resolving the mocks API.\nYou may encounter this issue when importing the mocks API from another module other than 'vitest'.\nTo fix this issue you can either:\n- import the mocks API directly from 'vitest'\n- enable the 'globals' option`\n\nfunction API_NOT_FOUND_CHECK(names: string[]) {\n  return `\\nif (${names.map(name => `typeof globalThis[\"${name}\"] === \"undefined\"`).join(' && ')}) `\n    + `{ throw new Error(${JSON.stringify(API_NOT_FOUND_ERROR)}) }\\n`\n}\n\nfunction isIdentifier(node: any): node is Positioned<Identifier> {\n  return node.type === 'Identifier'\n}\n\nfunction getNodeTail(code: string, node: Node) {\n  let end = node.end\n  if (code[node.end] === ';') {\n    end += 1\n  }\n  if (code[node.end] === '\\n') {\n    return end + 1\n  }\n  if (code[node.end + 1] === '\\n') {\n    end += 1\n  }\n  return end\n}\n\nconst regexpHoistable\n  = /\\b(?:vi|vitest)\\s*\\.\\s*(?:mock|unmock|hoisted|doMock|doUnmock)\\s*\\(/\nconst hashbangRE = /^#!.*\\n/\n\n// this is a fork of Vite SSR transform\nexport function hoistMocks(\n  code: string,\n  id: string,\n  parse: (code: string) => any,\n  options: HoistMocksOptions = {},\n): MagicString | undefined {\n  const needHoisting = (options.regexpHoistable || regexpHoistable).test(code)\n\n  if (!needHoisting) {\n    return\n  }\n\n  const s = options.magicString?.() || new MagicString(code)\n\n  let ast: any\n  try {\n    ast = parse(code)\n  }\n  catch (err) {\n    console.error(`Cannot parse ${id}:\\n${(err as any).message}.`)\n    return\n  }\n\n  const {\n    hoistableMockMethodNames = ['mock', 'unmock'],\n    dynamicImportMockMethodNames = ['mock', 'unmock', 'doMock', 'doUnmock'],\n    hoistedMethodNames = ['hoisted'],\n    utilsObjectNames = ['vi', 'vitest'],\n    hoistedModule = 'vitest',\n  } = options\n\n  // hoist at the start of the file, after the hashbang\n  const hashbangEnd = hashbangRE.exec(code)?.[0].length ?? 0\n  let hoistIndex = hashbangEnd\n\n  let hoistedModuleImported = false\n\n  let uid = 0\n  const idToImportMap = new Map<string, string>()\n\n  const imports: {\n    node: Positioned<ImportDeclaration>\n    id: string\n  }[] = []\n\n  // this will transform import statements into dynamic ones, if there are imports\n  // it will keep the import as is, if we don't need to mock anything\n  // in browser environment it will wrap the module value with \"vitest_wrap_module\" function\n  // that returns a proxy to the module so that named exports can be mocked\n  function defineImport(\n    importNode: ImportDeclaration & {\n      start: number\n      end: number\n    },\n  ) {\n    const source = importNode.source.value as string\n    // always hoist vitest import to top of the file, so\n    // \"vi\" helpers can access it\n    if (hoistedModule === source) {\n      hoistedModuleImported = true\n      return\n    }\n    const importId = `__vi_import_${uid++}__`\n    imports.push({ id: importId, node: importNode })\n\n    return importId\n  }\n\n  // 1. check all import statements and record id -> importName map\n  for (const node of ast.body as Node[]) {\n    // import foo from 'foo' --> foo -> __import_foo__.default\n    // import { baz } from 'foo' --> baz -> __import_foo__.baz\n    // import * as ok from 'foo' --> ok -> __import_foo__\n    if (node.type === 'ImportDeclaration') {\n      const importId = defineImport(node)\n      if (!importId) {\n        continue\n      }\n      for (const spec of node.specifiers) {\n        if (spec.type === 'ImportSpecifier') {\n          if (spec.imported.type === 'Identifier') {\n            idToImportMap.set(\n              spec.local.name,\n              `${importId}.${spec.imported.name}`,\n            )\n          }\n          else {\n            idToImportMap.set(\n              spec.local.name,\n              `${importId}[${JSON.stringify(spec.imported.value as string)}]`,\n            )\n          }\n        }\n        else if (spec.type === 'ImportDefaultSpecifier') {\n          idToImportMap.set(spec.local.name, `${importId}.default`)\n        }\n        else {\n          // namespace specifier\n          idToImportMap.set(spec.local.name, importId)\n        }\n      }\n    }\n  }\n\n  const declaredConst = new Set<string>()\n  const hoistedNodes: Set<Positioned<\n  CallExpression | VariableDeclaration | AwaitExpression\n  >> = new Set()\n\n  function createSyntaxError(node: Positioned<Node>, message: string) {\n    const _error = new SyntaxError(message)\n    Error.captureStackTrace(_error, createSyntaxError)\n    const serializedError: any = {\n      name: 'SyntaxError',\n      message: _error.message,\n      stack: _error.stack,\n    }\n    if (options.codeFrameGenerator) {\n      serializedError.frame = options.codeFrameGenerator(node, id, code)\n    }\n    return serializedError\n  }\n\n  function assertNotDefaultExport(\n    node: Positioned<CallExpression>,\n    error: string,\n  ) {\n    const defaultExport = findNodeAround(\n      ast,\n      node.start,\n      'ExportDefaultDeclaration',\n    )?.node as Positioned<ExportDefaultDeclaration> | undefined\n    if (\n      defaultExport?.declaration === node\n      || (defaultExport?.declaration.type === 'AwaitExpression'\n        && defaultExport.declaration.argument === node)\n    ) {\n      throw createSyntaxError(defaultExport, error)\n    }\n  }\n\n  function assertNotNamedExport(\n    node: Positioned<VariableDeclaration>,\n    error: string,\n  ) {\n    const nodeExported = findNodeAround(\n      ast,\n      node.start,\n      'ExportNamedDeclaration',\n    )?.node as Positioned<ExportNamedDeclaration> | undefined\n    if (nodeExported?.declaration === node) {\n      throw createSyntaxError(nodeExported, error)\n    }\n  }\n\n  function getVariableDeclaration(node: Positioned<CallExpression>) {\n    const declarationNode = findNodeAround(\n      ast,\n      node.start,\n      'VariableDeclaration',\n    )?.node as Positioned<VariableDeclaration> | undefined\n    const init = declarationNode?.declarations[0]?.init\n    if (\n      init\n      && (init === node\n        || (init.type === 'AwaitExpression' && init.argument === node))\n    ) {\n      return declarationNode\n    }\n  }\n\n  const usedUtilityExports = new Set<string>()\n  let hasImportMetaVitest = false\n\n  esmWalker(ast, {\n    onImportMeta(node) {\n      const property = code.slice(node.end, node.end + 7) // '.vitest'.length\n      if (property === '.vitest') {\n        hasImportMetaVitest = true\n      }\n    },\n    onIdentifier(id, info, parentStack) {\n      const binding = idToImportMap.get(id.name)\n      if (!binding) {\n        return\n      }\n\n      if (info.hasBindingShortcut) {\n        s.appendLeft(id.end, `: ${binding}`)\n      }\n      else if (info.classDeclaration) {\n        if (!declaredConst.has(id.name)) {\n          declaredConst.add(id.name)\n          // locate the top-most node containing the class declaration\n          const topNode = parentStack[parentStack.length - 2]\n          s.prependRight(topNode.start, `const ${id.name} = ${binding};\\n`)\n        }\n      }\n      else if (\n        // don't transform class name identifier\n        !info.classExpression\n      ) {\n        s.update(id.start, id.end, binding)\n      }\n    },\n    onDynamicImport(_node) {\n      // TODO: vi.mock(import) breaks it, and vi.mock('', () => import) also does,\n      // only move imports that are outside of vi.mock\n      // backwards compat, don't do if not passed\n      // if (!options.globalThisAccessor) {\n      //   return\n      // }\n\n      // const globalThisAccessor = options.globalThisAccessor\n      // const replaceString = `globalThis[${globalThisAccessor}].wrapDynamicImport(() => import(`\n      // const importSubstring = code.substring(node.start, node.end)\n      // const hasIgnore = importSubstring.includes('/* @vite-ignore */')\n      // s.overwrite(\n      //   node.start,\n      //   (node.source as Positioned<Expression>).start,\n      //   replaceString + (hasIgnore ? '/* @vite-ignore */ ' : ''),\n      // )\n      // s.overwrite(node.end - 1, node.end, '))')\n    },\n    onCallExpression(node) {\n      if (\n        node.callee.type === 'MemberExpression'\n        && isIdentifier(node.callee.object)\n        && utilsObjectNames.includes(node.callee.object.name)\n        && isIdentifier(node.callee.property)\n      ) {\n        const methodName = node.callee.property.name\n        usedUtilityExports.add(node.callee.object.name)\n\n        if (hoistableMockMethodNames.includes(methodName)) {\n          const method = `${node.callee.object.name}.${methodName}`\n          assertNotDefaultExport(\n            node,\n            `Cannot export the result of \"${method}\". Remove export declaration because \"${method}\" doesn\\'t return anything.`,\n          )\n          const declarationNode = getVariableDeclaration(node)\n          if (declarationNode) {\n            assertNotNamedExport(\n              declarationNode,\n              `Cannot export the result of \"${method}\". Remove export declaration because \"${method}\" doesn\\'t return anything.`,\n            )\n          }\n          // rewrite vi.mock(import('..')) into vi.mock('..')\n          if (\n            node.type === 'CallExpression'\n            && node.callee.type === 'MemberExpression'\n            && dynamicImportMockMethodNames.includes((node.callee.property as Identifier).name)\n          ) {\n            const moduleInfo = node.arguments[0] as Positioned<Expression>\n            // vi.mock(import('./path')) -> vi.mock('./path')\n            if (moduleInfo.type === 'ImportExpression') {\n              const source = moduleInfo.source as Positioned<Expression>\n              s.overwrite(\n                moduleInfo.start,\n                moduleInfo.end,\n                s.slice(source.start, source.end),\n              )\n            }\n            // vi.mock(await import('./path')) -> vi.mock('./path')\n            if (\n              moduleInfo.type === 'AwaitExpression'\n              && moduleInfo.argument.type === 'ImportExpression'\n            ) {\n              const source = moduleInfo.argument.source as Positioned<Expression>\n              s.overwrite(\n                moduleInfo.start,\n                moduleInfo.end,\n                s.slice(source.start, source.end),\n              )\n            }\n          }\n          hoistedNodes.add(node)\n        }\n        // vi.doMock(import('./path')) -> vi.doMock('./path')\n        // vi.doMock(await import('./path')) -> vi.doMock('./path')\n        else if (dynamicImportMockMethodNames.includes(methodName)) {\n          const moduleInfo = node.arguments[0] as Positioned<Expression>\n          let source: Positioned<Expression> | null = null\n          if (moduleInfo.type === 'ImportExpression') {\n            source = moduleInfo.source as Positioned<Expression>\n          }\n          if (\n            moduleInfo.type === 'AwaitExpression'\n            && moduleInfo.argument.type === 'ImportExpression'\n          ) {\n            source = moduleInfo.argument.source as Positioned<Expression>\n          }\n          if (source) {\n            s.overwrite(\n              moduleInfo.start,\n              moduleInfo.end,\n              s.slice(source.start, source.end),\n            )\n          }\n        }\n\n        if (hoistedMethodNames.includes(methodName)) {\n          assertNotDefaultExport(\n            node,\n            'Cannot export hoisted variable. You can control hoisting behavior by placing the import from this file first.',\n          )\n\n          const declarationNode = getVariableDeclaration(node)\n          if (declarationNode) {\n            assertNotNamedExport(\n              declarationNode,\n              'Cannot export hoisted variable. You can control hoisting behavior by placing the import from this file first.',\n            )\n            // hoist \"const variable = vi.hoisted(() => {})\"\n            hoistedNodes.add(declarationNode)\n          }\n          else {\n            const awaitedExpression = findNodeAround(\n              ast,\n              node.start,\n              'AwaitExpression',\n            )?.node as Positioned<AwaitExpression> | undefined\n            // hoist \"await vi.hoisted(async () => {})\" or \"vi.hoisted(() => {})\"\n            const moveNode = awaitedExpression?.argument === node ? awaitedExpression : node\n            hoistedNodes.add(moveNode)\n          }\n        }\n      }\n    },\n  })\n\n  function getNodeName(node: CallExpression) {\n    const callee = node.callee || {}\n    if (\n      callee.type === 'MemberExpression'\n      && isIdentifier(callee.property)\n      && isIdentifier(callee.object)\n    ) {\n      const argument = node.arguments[0] as Positioned<Expression>\n      const argStr = argument.type === 'Literal' || argument.type === 'ImportExpression'\n        ? code.slice(argument.start, argument.end)\n        : ''\n      return `${callee.object.name}.${callee.property.name}(${argStr})`\n    }\n    return '\"hoisted method\"'\n  }\n\n  function getNodeCall(node: Node): Positioned<CallExpression> {\n    if (node.type === 'CallExpression') {\n      return node\n    }\n    if (node.type === 'VariableDeclaration') {\n      const { declarations } = node\n      const init = declarations[0].init\n      if (init) {\n        return getNodeCall(init as Node)\n      }\n    }\n    if (node.type === 'AwaitExpression') {\n      const { argument } = node\n      if (argument.type === 'CallExpression') {\n        return getNodeCall(argument as Node)\n      }\n    }\n    return node as Positioned<CallExpression>\n  }\n\n  function createError(outsideNode: Node, insideNode: Node) {\n    const outsideCall = getNodeCall(outsideNode)\n    const insideCall = getNodeCall(insideNode)\n    throw createSyntaxError(\n      insideCall,\n      `Cannot call ${getNodeName(insideCall)} inside ${getNodeName(\n        outsideCall,\n      )}: both methods are hoisted to the top of the file and not actually called inside each other.`,\n    )\n  }\n\n  // validate hoistedNodes doesn't have nodes inside other nodes\n  const arrayNodes = Array.from(hoistedNodes)\n  for (let i = 0; i < arrayNodes.length; i++) {\n    const node = arrayNodes[i]\n    for (let j = i + 1; j < arrayNodes.length; j++) {\n      const otherNode = arrayNodes[j]\n\n      if (node.start >= otherNode.start && node.end <= otherNode.end) {\n        throw createError(otherNode, node)\n      }\n      if (otherNode.start >= node.start && otherNode.end <= node.end) {\n        throw createError(node, otherNode)\n      }\n    }\n  }\n\n  // validate that hoisted nodes are defined on the top level\n  // ignore `import.meta.vitest` because it needs to be inside an IfStatement\n  // and it can be used anywhere in the code (inside methods too)\n  if (!hasImportMetaVitest) {\n    for (const node of ast.body as Node[]) {\n      hoistedNodes.delete(node as any)\n      if (node.type === 'ExpressionStatement') {\n        hoistedNodes.delete(node.expression as any)\n      }\n    }\n\n    for (const invalidNode of hoistedNodes) {\n      console.warn(\n        `Warning: A ${getNodeName(getNodeCall(invalidNode))} call in \"${id}\" is not at the top level of the module. `\n        + `Although it appears nested, it will be hoisted and executed before any tests run. `\n        + `Move it to the top level to reflect its actual execution order. This will become an error in a future version.\\n`\n        + `See: https://vitest.dev/guide/mocking/modules#how-it-works`,\n      )\n    }\n  }\n\n  // hoist vi.mock/vi.hoisted\n  for (const node of arrayNodes) {\n    const end = getNodeTail(code, node)\n    // don't hoist into itself if it's already at the top\n    if (hoistIndex === end || hoistIndex === node.start) {\n      hoistIndex = end\n    }\n    else {\n      s.move(node.start, end, hoistIndex)\n    }\n  }\n\n  // hoist actual dynamic imports last so they are inserted after all hoisted mocks\n  for (const { node: importNode, id: importId } of imports) {\n    const source = importNode.source.value as string\n\n    const sourceString = JSON.stringify(source)\n    let importLine = `const ${importId} = await `\n    if (options.globalThisAccessor) {\n      importLine += `globalThis[${options.globalThisAccessor}].wrapDynamicImport(() => import(${sourceString}));\\n`\n    }\n    else {\n      importLine += `import(${sourceString});\\n`\n    }\n\n    s.update(\n      importNode.start,\n      importNode.end,\n      importLine,\n    )\n\n    if (importNode.start === hoistIndex) {\n      // no need to hoist, but update hoistIndex to keep the order\n      hoistIndex = importNode.end\n    }\n    else {\n      // There will be an error if the module is called before it is imported,\n      // so the module import statement is hoisted to the top\n      s.move(importNode.start, importNode.end, hoistIndex)\n    }\n  }\n\n  if (!hoistedModuleImported && arrayNodes.length > 0) {\n    const utilityImports = [...usedUtilityExports]\n    // \"vi\" or \"vitest\" is imported from a module other than \"vitest\"\n    if (utilityImports.some(name => idToImportMap.has(name))) {\n      s.appendLeft(hashbangEnd, API_NOT_FOUND_CHECK(utilityImports))\n    }\n    // if \"vi\" or \"vitest\" are not imported at all, import them\n    else if (utilityImports.length) {\n      s.appendLeft(\n        hashbangEnd,\n        `import { ${[...usedUtilityExports].join(', ')} } from ${JSON.stringify(\n          hoistedModule,\n        )}\\n`,\n      )\n    }\n  }\n\n  return s\n}\n\ninterface CodeFrameGenerator {\n  (node: Positioned<Node>, id: string, code: string): string\n}\n"
  },
  {
    "path": "packages/mocker/src/node/hoistMocksPlugin.ts",
    "content": "import type { SourceMap } from 'magic-string'\nimport type { Plugin, Rollup } from 'vite'\nimport type { HoistMocksOptions } from './hoistMocks'\nimport { createFilter } from 'vite'\nimport { cleanUrl } from '../utils'\nimport { hoistMocks } from './hoistMocks'\n\nexport interface HoistMocksPluginOptions extends Omit<HoistMocksOptions, 'regexpHoistable'> {\n  include?: string | RegExp | (string | RegExp)[]\n  exclude?: string | RegExp | (string | RegExp)[]\n  /**\n   * overrides include/exclude options\n   */\n  filter?: (id: string) => boolean\n}\n\nexport function hoistMocksPlugin(options: HoistMocksPluginOptions = {}): Plugin {\n  const filter = options.filter || createFilter(options.include, options.exclude)\n\n  const {\n    hoistableMockMethodNames = ['mock', 'unmock'],\n    dynamicImportMockMethodNames = ['mock', 'unmock', 'doMock', 'doUnmock'],\n    hoistedMethodNames = ['hoisted'],\n    utilsObjectNames = ['vi', 'vitest'],\n  } = options\n\n  const methods = new Set([\n    ...hoistableMockMethodNames,\n    ...hoistedMethodNames,\n    ...dynamicImportMockMethodNames,\n  ])\n\n  const regexpHoistable = new RegExp(\n    `\\\\b(?:${utilsObjectNames.join('|')})\\\\s*\\.\\\\s*(?:${Array.from(methods).join('|')})\\\\s*\\\\(`,\n  )\n\n  return {\n    name: 'vitest:mocks',\n    enforce: 'post',\n    transform(code, id) {\n      if (!filter(id)) {\n        return\n      }\n      const s = hoistMocks(code, id, this.parse, {\n        regexpHoistable,\n        hoistableMockMethodNames,\n        hoistedMethodNames,\n        utilsObjectNames,\n        dynamicImportMockMethodNames,\n        ...options,\n      })\n      if (s) {\n        return {\n          code: s.toString(),\n          map: s.generateMap({ hires: 'boundary', source: cleanUrl(id) }),\n        }\n      }\n    },\n  }\n}\n\n// to keeb backwards compat\nexport function hoistMockAndResolve(\n  code: string,\n  id: string,\n  parse: Rollup.PluginContext['parse'],\n  options: HoistMocksOptions = {},\n): HoistMocksResult | undefined {\n  const s = hoistMocks(code, id, parse, options)\n  if (s) {\n    return {\n      code: s.toString(),\n      map: s.generateMap({ hires: 'boundary', source: cleanUrl(id) }),\n    }\n  }\n}\n\nexport interface HoistMocksResult {\n  code: string\n  map: SourceMap\n}\n"
  },
  {
    "path": "packages/mocker/src/node/index.ts",
    "content": "export { createManualModuleSource } from '../utils'\nexport { automockModule } from './automock'\nexport type { AutomockPluginOptions } from './automockPlugin'\nexport { automockPlugin } from './automockPlugin'\nexport { dynamicImportPlugin } from './dynamicImportPlugin'\nexport { hoistMockAndResolve as hoistMocks, hoistMocksPlugin } from './hoistMocksPlugin'\nexport type { HoistMocksPluginOptions, HoistMocksResult } from './hoistMocksPlugin'\nexport { interceptorPlugin } from './interceptorPlugin'\n\nexport type { InterceptorPluginOptions } from './interceptorPlugin'\nexport { mockerPlugin } from './mockerPlugin'\nexport { findMockRedirect } from './redirect'\nexport { ServerMockResolver } from './resolver'\nexport type { ServerResolverOptions } from './resolver'\n"
  },
  {
    "path": "packages/mocker/src/node/interceptorPlugin.ts",
    "content": "import type { Plugin } from 'vite'\nimport type { MockedModuleSerialized } from '../registry'\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path/posix'\nimport { ManualMockedModule, MockerRegistry } from '../registry'\nimport { cleanUrl, createManualModuleSource } from '../utils'\nimport { automockModule } from './automock'\n\nexport interface InterceptorPluginOptions {\n  /**\n   * @default \"__vitest_mocker__\"\n   */\n  globalThisAccessor?: string\n  registry?: MockerRegistry\n}\n\nexport function interceptorPlugin(options: InterceptorPluginOptions = {}): Plugin {\n  const registry = options.registry || new MockerRegistry()\n  return {\n    name: 'vitest:mocks:interceptor',\n    enforce: 'pre',\n    load: {\n      order: 'pre',\n      async handler(id) {\n        const mock = registry.getById(id)\n        if (!mock) {\n          return\n        }\n        if (mock.type === 'manual') {\n          const exports = Object.keys(await mock.resolve())\n          const accessor = options.globalThisAccessor || '\"__vitest_mocker__\"'\n          return createManualModuleSource(mock.url, exports, accessor)\n        }\n        if (mock.type === 'redirect') {\n          return readFile(mock.redirect, 'utf-8')\n        }\n      },\n    },\n    transform: {\n      order: 'post',\n      handler(code, id) {\n        const mock = registry.getById(id)\n        if (!mock) {\n          return\n        }\n        if (mock.type === 'automock' || mock.type === 'autospy') {\n          const m = automockModule(code, mock.type, this.parse, {\n            globalThisAccessor: options.globalThisAccessor,\n          })\n\n          return {\n            code: m.toString(),\n            map: m.generateMap({ hires: 'boundary', source: cleanUrl(id) }),\n          }\n        }\n      },\n    },\n    configureServer(server) {\n      server.ws.on('vitest:interceptor:register', (event: MockedModuleSerialized) => {\n        if (event.type === 'manual') {\n          const module = ManualMockedModule.fromJSON(event, async () => {\n            const keys = await getFactoryExports(event.url)\n            return Object.fromEntries(keys.map(key => [key, null]))\n          })\n          registry.add(module)\n        }\n        else {\n          if (event.type === 'redirect') {\n            const redirectUrl = new URL(event.redirect)\n            event.redirect = join(server.config.root, redirectUrl.pathname)\n          }\n          registry.register(event)\n        }\n        server.ws.send('vitest:interceptor:register:result')\n      })\n      server.ws.on('vitest:interceptor:delete', (id: string) => {\n        registry.delete(id)\n        server.ws.send('vitest:interceptor:delete:result')\n      })\n      server.ws.on('vitest:interceptor:invalidate', () => {\n        registry.clear()\n        server.ws.send('vitest:interceptor:invalidate:result')\n      })\n\n      function getFactoryExports(url: string) {\n        server.ws.send('vitest:interceptor:resolve', url)\n        let timeout: NodeJS.Timeout\n        return new Promise<string[]>((resolve, reject) => {\n          timeout = setTimeout(() => {\n            reject(new Error(`Timeout while waiting for factory exports of ${url}`))\n          }, 10_000)\n          server.ws.on('vitest:interceptor:resolved', ({ url: resolvedUrl, keys }: { url: string; keys: string[] }) => {\n            if (resolvedUrl === url) {\n              clearTimeout(timeout)\n              resolve(keys)\n            }\n          })\n        })\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/mocker/src/node/mockerPlugin.ts",
    "content": "import type { Plugin, ViteDevServer } from 'vite'\nimport type { AutomockPluginOptions } from './automockPlugin'\nimport type { HoistMocksPluginOptions } from './hoistMocksPlugin'\n\nimport { readFile } from 'node:fs/promises'\nimport { fileURLToPath } from 'node:url'\nimport { resolve } from 'pathe'\nimport { automockPlugin } from './automockPlugin'\nimport { dynamicImportPlugin } from './dynamicImportPlugin'\nimport { hoistMocksPlugin } from './hoistMocksPlugin'\nimport { interceptorPlugin } from './interceptorPlugin'\nimport { ServerMockResolver } from './resolver'\n\ninterface MockerPluginOptions extends AutomockPluginOptions {\n  hoistMocks?: HoistMocksPluginOptions\n}\n\n// this is an implementation for public usage\n// vitest doesn't use this plugin directly\n\nexport function mockerPlugin(options: MockerPluginOptions = {}): Plugin[] {\n  let server: ViteDevServer\n  const registerPath = resolve(fileURLToPath(new URL('./register.js', import.meta.url)))\n  return [\n    {\n      name: 'vitest:mocker:ws-rpc',\n      config(_, { command }) {\n        if (command !== 'serve') {\n          return\n        }\n        return {\n          server: {\n            // don't pre-transform request because they might be mocked at runtime\n            preTransformRequests: false,\n          },\n          optimizeDeps: {\n            exclude: ['@vitest/mocker/register', '@vitest/mocker/browser'],\n          },\n        }\n      },\n      configureServer(server_) {\n        server = server_\n        const mockResolver = new ServerMockResolver(server)\n        server.ws.on('vitest:mocks:resolveId', async ({ id, importer }: { id: string; importer: string }) => {\n          const resolved = await mockResolver.resolveId(id, importer)\n          server.ws.send('vitest:mocks:resolvedId:result', resolved)\n        })\n        server.ws.on('vitest:mocks:resolveMock', async ({ id, importer, options }: { id: string; importer: string; options: any }) => {\n          const resolved = await mockResolver.resolveMock(id, importer, options)\n          server.ws.send('vitest:mocks:resolveMock:result', resolved)\n        })\n        server.ws.on('vitest:mocks:invalidate', async ({ ids }: { ids: string[] }) => {\n          mockResolver.invalidate(ids)\n          server.ws.send('vitest:mocks:invalidate:result')\n        })\n      },\n      async load(id) {\n        if (id !== registerPath) {\n          return\n        }\n\n        if (!server) {\n          // mocker doesn't work during build\n          return 'export {}'\n        }\n\n        const content = await readFile(registerPath, 'utf-8')\n        const result = content\n          .replace(\n            /__VITEST_GLOBAL_THIS_ACCESSOR__/g,\n            options.globalThisAccessor ?? '\"__vitest_mocker__\"',\n          )\n          .replace(\n            '__VITEST_MOCKER_ROOT__',\n            JSON.stringify(server.config.root),\n          )\n        return result\n      },\n    },\n    hoistMocksPlugin(options.hoistMocks),\n    interceptorPlugin(options),\n    automockPlugin(options),\n    dynamicImportPlugin(options),\n  ]\n}\n"
  },
  {
    "path": "packages/mocker/src/node/parsers.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport module, { createRequire, isBuiltin } from 'node:module'\nimport { extname } from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { filterOutComments } from '@vitest/utils/helpers'\nimport { init as initCjsLexer, parse as parseCjsSyntax } from 'cjs-module-lexer'\nimport { init as initModuleLexer, parse as parseModuleSyntax } from 'es-module-lexer'\n\nexport async function initSyntaxLexers(): Promise<void> {\n  await Promise.all([\n    initCjsLexer(),\n    initModuleLexer,\n  ])\n}\n\nconst isTransform = process.execArgv.includes('--experimental-transform-types')\n  || process.env.NODE_OPTIONS?.includes('--experimental-transform-types')\n\nexport function transformCode(code: string, filename: string): string {\n  const ext = extname(filename.split('?')[0])\n  const isTs = ext === '.ts' || ext === '.cts' || ext === '.mts'\n  if (!isTs) {\n    return code\n  }\n  if (!module.stripTypeScriptTypes) {\n    throw new Error(`Cannot parse '${filename}' because \"module.stripTypeScriptTypes\" is not supported. Module mocking requires Node.js 22.15 or higher. This is NOT a bug of Vitest.`)\n  }\n  return module.stripTypeScriptTypes(code, { mode: isTransform ? 'transform' : 'strip' })\n}\n\nconst cachedFileExports = new Map<string, string[]>()\n\nexport function collectModuleExports(\n  filename: string,\n  code: string,\n  format: 'module' | 'commonjs',\n  exports: string[] = [],\n): string[] {\n  if (format === 'module') {\n    const [imports_, exports_] = parseModuleSyntax(code, filename)\n    const fileExports = [...exports_.map(p => p.n)]\n    imports_.forEach(({ ss: start, se: end, n: name }) => {\n      const substring = code.substring(start, end).replace(/ +/g, ' ')\n      if (name && substring.startsWith('export *') && !substring.startsWith('export * as')) {\n        fileExports.push(...tryParseModule(name))\n      }\n    })\n    cachedFileExports.set(filename, fileExports)\n    exports.push(...fileExports)\n  }\n  else {\n    const { exports: exports_, reexports } = parseCjsSyntax(code, filename)\n    const fileExports = [...exports_]\n    reexports.forEach((name) => {\n      fileExports.push(...tryParseModule(name))\n    })\n    cachedFileExports.set(filename, fileExports)\n    exports.push(...fileExports)\n  }\n\n  function tryParseModule(name: string): string[] {\n    try {\n      return parseModule(name)\n    }\n    catch (error) {\n      console.warn(`[module mocking] Failed to parse '${name}' imported from ${filename}:`, error)\n      return []\n    }\n  }\n\n  let __require: NodeJS.Require | undefined\n  function getModuleRequire() {\n    return (__require ??= createRequire(filename))\n  }\n\n  function parseModule(name: string): string[] {\n    if (isBuiltin(name)) {\n      if (cachedFileExports.has(name)) {\n        const cachedExports = cachedFileExports.get(name)!\n        return cachedExports\n      }\n\n      const builtinModule = getBuiltinModule(name)\n      const builtinExports = Object.keys(builtinModule)\n      cachedFileExports.set(name, builtinExports)\n      return builtinExports\n    }\n\n    const resolvedModuleUrl = format === 'module'\n      ? import.meta.resolve(name, pathToFileURL(filename).toString())\n      : getModuleRequire().resolve(name)\n\n    const resolvedModulePath = format === 'commonjs'\n      ? resolvedModuleUrl\n      : fileURLToPath(resolvedModuleUrl)\n\n    if (cachedFileExports.has(resolvedModulePath)) {\n      return cachedFileExports.get(resolvedModulePath)!\n    }\n\n    const fileContent = readFileSync(resolvedModulePath, 'utf-8')\n    const ext = extname(resolvedModulePath)\n    const code = transformCode(fileContent, resolvedModulePath)\n    if (code == null) {\n      cachedFileExports.set(resolvedModulePath, [])\n      return []\n    }\n\n    const resolvedModuleFormat = resolveModuleFormat(resolvedModulePath, code)\n    if (ext === '.json') {\n      return ['default']\n    }\n    else {\n      // can't do wasm, for example\n      console.warn(`Cannot process '${resolvedModuleFormat}' imported from ${filename} because of unknown file extension: ${ext}.`)\n    }\n    if (resolvedModuleFormat) {\n      return collectModuleExports(resolvedModulePath, code, resolvedModuleFormat, exports)\n    }\n    return []\n  }\n\n  return Array.from(new Set(exports))\n}\n\nexport function resolveModuleFormat(url: string, code: string): 'module' | 'commonjs' | undefined {\n  const ext = extname(url)\n\n  if (ext === '.cjs' || ext === '.cts') {\n    return 'commonjs'\n  }\n  else if (ext === '.mjs' || ext === '.mts') {\n    return 'module'\n  }\n  // https://nodejs.org/api/packages.html#syntax-detection\n  else if (ext === '.js' || ext === '.ts' || ext === '') {\n    if (!module.findPackageJSON) {\n      throw new Error(`Cannot parse the module format of '${url}' because \"module.findPackageJSON\" is not available. Upgrade to Node 22.14 to use this feature. This is NOT a bug of Vitest.`)\n    }\n    const pkgJsonPath = module.findPackageJSON(url)\n    const pkgJson = pkgJsonPath ? JSON.parse(readFileSync(pkgJsonPath, 'utf-8')) : {}\n    if (pkgJson?.type === 'module') {\n      return 'module'\n    }\n    else if (pkgJson?.type === 'commonjs') {\n      return 'commonjs'\n    }\n    else {\n      // Ambiguous input! Check if it has ESM syntax. Node.js is much smarter here,\n      // but we don't need to run the code, so we can be more relaxed\n      if (hasESM(filterOutComments(code))) {\n        return 'module'\n      }\n      else {\n        return 'commonjs'\n      }\n    }\n  }\n  return undefined\n}\n\nlet __globalRequire: NodeJS.Require | undefined\nfunction getBuiltinModule(moduleId: string) {\n  __globalRequire ??= module.createRequire(import.meta.url)\n  return __globalRequire(moduleId)\n}\n\nconst ESM_RE\n  = /(?:[\\s;]|^)(?:import[\\s\\w*,{}]*from|import\\s*[\"'*{]|export\\b\\s*(?:[*{]|default|class|type|function|const|var|let|async function)|import\\.meta\\b)/m\n\nfunction hasESM(code: string) {\n  return ESM_RE.test(code)\n}\n"
  },
  {
    "path": "packages/mocker/src/node/redirect.ts",
    "content": "import fs from 'node:fs'\nimport nodeModule from 'node:module'\nimport { basename, dirname, extname, join, resolve } from 'pathe'\n\nconst { existsSync, readdirSync, statSync } = fs\n\nexport function findMockRedirect(\n  root: string,\n  mockPath: string,\n  external: string | null,\n): string | null {\n  const path = external || mockPath\n\n  // it's a node_module alias\n  // all mocks should be inside <root>/__mocks__\n  if (external || isNodeBuiltin(mockPath) || !existsSync(mockPath)) {\n    const mockDirname = dirname(path) // for nested mocks: @vueuse/integration/useJwt\n    const mockFolder = join(root, '__mocks__', mockDirname)\n\n    if (!existsSync(mockFolder)) {\n      return null\n    }\n\n    const baseOriginal = basename(path)\n\n    function findFile(mockFolder: string, baseOriginal: string): string | null {\n      const files = readdirSync(mockFolder)\n      for (const file of files) {\n        const baseFile = basename(file, extname(file))\n        if (baseFile === baseOriginal) {\n          const path = resolve(mockFolder, file)\n          // if the same name, return the file\n          if (statSync(path).isFile()) {\n            return path\n          }\n          else {\n            // find folder/index.{js,ts}\n            const indexFile = findFile(path, 'index')\n            if (indexFile) {\n              return indexFile\n            }\n          }\n        }\n      }\n      return null\n    }\n\n    return findFile(mockFolder, baseOriginal)\n  }\n\n  const dir = dirname(path)\n  const baseId = basename(path)\n  const fullPath = resolve(dir, '__mocks__', baseId)\n  return existsSync(fullPath) ? fullPath : null\n}\n\nconst builtins = new Set([\n  ...nodeModule.builtinModules,\n  'assert/strict',\n  'diagnostics_channel',\n  'dns/promises',\n  'fs/promises',\n  'path/posix',\n  'path/win32',\n  'readline/promises',\n  'stream/consumers',\n  'stream/promises',\n  'stream/web',\n  'timers/promises',\n  'util/types',\n  'wasi',\n])\n\n// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix\nconst prefixedBuiltins = new Set([\n  'node:sea',\n  'node:sqlite',\n  'node:test',\n  'node:test/reporters',\n])\nconst NODE_BUILTIN_NAMESPACE = 'node:'\nfunction isNodeBuiltin(id: string): boolean {\n  // Added in v18.6.0\n  if (nodeModule.isBuiltin) {\n    return nodeModule.isBuiltin(id)\n  }\n  if (prefixedBuiltins.has(id)) {\n    return true\n  }\n  return builtins.has(\n    id.startsWith(NODE_BUILTIN_NAMESPACE)\n      ? id.slice(NODE_BUILTIN_NAMESPACE.length)\n      : id,\n  )\n}\n"
  },
  {
    "path": "packages/mocker/src/node/resolver.ts",
    "content": "import type { Rollup, ResolvedConfig as ViteConfig, ViteDevServer } from 'vite'\nimport type { ServerIdResolution, ServerMockResolution } from '../types'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { isAbsolute, join, resolve } from 'pathe'\nimport { cleanUrl } from '../utils'\nimport { findMockRedirect } from './redirect'\n\nexport interface ServerResolverOptions {\n  /**\n   * @default ['/node_modules/']\n   */\n  moduleDirectories?: string[]\n}\n\nconst VALID_ID_PREFIX = '/@id/'\n\nexport class ServerMockResolver {\n  constructor(\n    private server: ViteDevServer,\n    private options: ServerResolverOptions = {},\n  ) {}\n\n  async resolveMock(\n    rawId: string,\n    importer: string,\n    options: { mock: 'spy' | 'factory' | 'auto' },\n  ): Promise<ServerMockResolution> {\n    const { id, fsPath, external } = await this.resolveMockId(rawId, importer)\n    const resolvedUrl = this.normalizeResolveIdToUrl({ id }).url\n\n    if (options.mock === 'factory') {\n      const manifest = getViteDepsManifest(this.server.config)\n      const needsInterop = manifest?.[fsPath]?.needsInterop ?? false\n      return { mockType: 'manual', resolvedId: id, resolvedUrl, needsInterop }\n    }\n\n    if (options.mock === 'spy') {\n      return { mockType: 'autospy', resolvedId: id, resolvedUrl }\n    }\n\n    const redirectUrl = findMockRedirect(this.server.config.root, fsPath, external)\n\n    return {\n      mockType: redirectUrl === null ? 'automock' : 'redirect',\n      redirectUrl,\n      resolvedId: id,\n      resolvedUrl,\n    }\n  }\n\n  public invalidate(ids: string[]): void {\n    ids.forEach((id) => {\n      const moduleGraph = this.server.moduleGraph\n      const module = moduleGraph.getModuleById(id)\n      if (module) {\n        module.transformResult = null\n      }\n    })\n  }\n\n  public async resolveId(id: string, importer?: string): Promise<ServerIdResolution | null> {\n    const resolved = await this.server.pluginContainer.resolveId(\n      id,\n      importer,\n      {\n        ssr: false,\n      },\n    )\n    if (!resolved) {\n      return null\n    }\n    return this.normalizeResolveIdToUrl(resolved)\n  }\n\n  private normalizeResolveIdToUrl(resolved: { id: string }) {\n    const isOptimized = resolved.id.startsWith(withTrailingSlash(this.server.config.cacheDir))\n    let url: string\n    // normalise the URL to be acceptable by the browser\n    // https://github.com/vitejs/vite/blob/14027b0f2a9b01c14815c38aab22baf5b29594bb/packages/vite/src/node/plugins/importAnalysis.ts#L103\n    const root = this.server.config.root\n    if (resolved.id.startsWith(withTrailingSlash(root))) {\n      url = resolved.id.slice(root.length)\n    }\n    else if (\n      resolved.id !== '/@react-refresh'\n      && isAbsolute(resolved.id)\n      && existsSync(cleanUrl(resolved.id))\n    ) {\n      url = join('/@fs/', resolved.id)\n    }\n    else {\n      url = resolved.id\n    }\n    if (url[0] !== '.' && url[0] !== '/') {\n      url = resolved.id.startsWith(VALID_ID_PREFIX)\n        ? resolved.id\n        : VALID_ID_PREFIX + resolved.id.replace('\\0', '__x00__')\n    }\n    return {\n      id: resolved.id,\n      url,\n      optimized: isOptimized,\n    }\n  }\n\n  private async resolveMockId(rawId: string, importer: string) {\n    if (\n      !this.server.moduleGraph.getModuleById(importer)\n      && !importer.startsWith(this.server.config.root)\n    ) {\n      importer = join(this.server.config.root, importer)\n    }\n    const resolved = await this.server.pluginContainer.resolveId(\n      rawId,\n      importer,\n      {\n        ssr: false,\n      },\n    )\n    return this.resolveModule(rawId, resolved)\n  }\n\n  private resolveModule(rawId: string, resolved: Rollup.PartialResolvedId | null) {\n    const id = resolved?.id || rawId\n    const external\n      = !isAbsolute(id) || isModuleDirectory(this.options, id) ? rawId : null\n    return {\n      id,\n      fsPath: cleanUrl(id),\n      external,\n    }\n  }\n}\n\nfunction isModuleDirectory(config: ServerResolverOptions, path: string) {\n  const moduleDirectories = config.moduleDirectories || [\n    '/node_modules/',\n  ]\n  return moduleDirectories.some((dir: string) => path.includes(dir))\n}\n\ninterface PartialManifest {\n  [name: string]: {\n    hash: string\n    needsInterop: boolean\n  }\n}\n\nconst metadata = new WeakMap<ViteConfig, PartialManifest>()\n\nfunction getViteDepsManifest(config: ViteConfig) {\n  if (metadata.has(config)) {\n    return metadata.get(config)!\n  }\n  const cacheDirPath = getDepsCacheDir(config)\n  const metadataPath = resolve(cacheDirPath, '_metadata.json')\n  if (!existsSync(metadataPath)) {\n    return null\n  }\n  const { optimized } = JSON.parse(readFileSync(metadataPath, 'utf-8'))\n  const newManifest: PartialManifest = {}\n  for (const name in optimized) {\n    const dep = optimized[name]\n    const file = resolve(cacheDirPath, dep.file)\n    newManifest[file] = {\n      hash: dep.fileHash,\n      needsInterop: dep.needsInterop,\n    }\n  }\n  metadata.set(config, newManifest)\n  return newManifest\n}\n\nfunction getDepsCacheDir(config: ViteConfig): string {\n  return resolve(config.cacheDir, 'deps')\n}\n\nfunction withTrailingSlash(path: string): string {\n  if (path.at(-1) !== '/') {\n    return `${path}/`\n  }\n\n  return path\n}\n"
  },
  {
    "path": "packages/mocker/src/node/transforms.ts",
    "content": "export { createManualModuleSource } from '../utils'\nexport { automockModule } from './automock'\nexport { hoistMocks } from './hoistMocks'\nexport { collectModuleExports, initSyntaxLexers } from './parsers'\n"
  },
  {
    "path": "packages/mocker/src/registry.ts",
    "content": "export class MockerRegistry {\n  private readonly registryByUrl: Map<string, MockedModule> = new Map()\n  private readonly registryById: Map<string, MockedModule> = new Map()\n\n  clear(): void {\n    this.registryByUrl.clear()\n    this.registryById.clear()\n  }\n\n  keys(): IterableIterator<string> {\n    return this.registryByUrl.keys()\n  }\n\n  add(mock: MockedModule): void {\n    this.registryByUrl.set(mock.url, mock)\n    this.registryById.set(mock.id, mock)\n  }\n\n  public register(\n    json: MockedModuleSerialized,\n  ): MockedModule\n  public register(\n    type: 'redirect',\n    raw: string,\n    id: string,\n    url: string,\n    redirect: string,\n  ): RedirectedModule\n  public register(\n    type: 'manual',\n    raw: string,\n    id: string,\n    url: string,\n    factory: () => any,\n  ): ManualMockedModule\n  public register(\n    type: 'automock',\n    raw: string,\n    id: string,\n    url: string,\n  ): AutomockedModule\n  public register(\n    type: 'autospy',\n    id: string,\n    raw: string,\n    url: string,\n  ): AutospiedModule\n  public register(\n    typeOrEvent: MockedModuleType | MockedModuleSerialized,\n    raw?: string,\n    id?: string,\n    url?: string,\n    factoryOrRedirect?: string | (() => any),\n  ): MockedModule {\n    const type = typeof typeOrEvent === 'object' ? typeOrEvent.type : typeOrEvent\n\n    if (typeof typeOrEvent === 'object') {\n      const event = typeOrEvent\n      if (\n        event instanceof AutomockedModule\n        || event instanceof AutospiedModule\n        || event instanceof ManualMockedModule\n        || event instanceof RedirectedModule\n      ) {\n        throw new TypeError(\n          `[vitest] Cannot register a mock that is already defined. `\n          + `Expected a JSON representation from \\`MockedModule.toJSON\\`, instead got \"${event.type}\". `\n          + `Use \"registry.add()\" to update a mock instead.`,\n        )\n      }\n      if (event.type === 'automock') {\n        const module = AutomockedModule.fromJSON(event)\n        this.add(module)\n        return module\n      }\n      else if (event.type === 'autospy') {\n        const module = AutospiedModule.fromJSON(event)\n        this.add(module)\n        return module\n      }\n      else if (event.type === 'redirect') {\n        const module = RedirectedModule.fromJSON(event)\n        this.add(module)\n        return module\n      }\n      else if (event.type === 'manual') {\n        throw new Error(`Cannot set serialized manual mock. Define a factory function manually with \\`ManualMockedModule.fromJSON()\\`.`)\n      }\n      else {\n        throw new Error(`Unknown mock type: ${(event as any).type}`)\n      }\n    }\n\n    if (typeof raw !== 'string') {\n      throw new TypeError('[vitest] Mocks require a raw string.')\n    }\n\n    if (typeof url !== 'string') {\n      throw new TypeError('[vitest] Mocks require a url string.')\n    }\n\n    if (typeof id !== 'string') {\n      throw new TypeError('[vitest] Mocks require an id string.')\n    }\n\n    if (type === 'manual') {\n      if (typeof factoryOrRedirect !== 'function') {\n        throw new TypeError('[vitest] Manual mocks require a factory function.')\n      }\n      const mock = new ManualMockedModule(raw, id, url, factoryOrRedirect)\n      this.add(mock)\n      return mock\n    }\n    else if (type === 'automock' || type === 'autospy') {\n      const mock = type === 'automock'\n        ? new AutomockedModule(raw, id, url)\n        : new AutospiedModule(raw, id, url)\n      this.add(mock)\n      return mock\n    }\n    else if (type === 'redirect') {\n      if (typeof factoryOrRedirect !== 'string') {\n        throw new TypeError('[vitest] Redirect mocks require a redirect string.')\n      }\n      const mock = new RedirectedModule(raw, id, url, factoryOrRedirect)\n      this.add(mock)\n      return mock\n    }\n    else {\n      throw new Error(`[vitest] Unknown mock type: ${type}`)\n    }\n  }\n\n  public delete(id: string): void {\n    this.registryByUrl.delete(id)\n  }\n\n  public deleteById(id: string): void {\n    this.registryById.delete(id)\n  }\n\n  public get(id: string): MockedModule | undefined {\n    return this.registryByUrl.get(id)\n  }\n\n  public getById(id: string): MockedModule | undefined {\n    return this.registryById.get(id)\n  }\n\n  public has(id: string): boolean {\n    return this.registryByUrl.has(id)\n  }\n}\n\nexport type MockedModule\n  = | AutomockedModule\n    | AutospiedModule\n    | ManualMockedModule\n    | RedirectedModule\nexport type MockedModuleType = 'automock' | 'autospy' | 'manual' | 'redirect'\n\nexport type MockedModuleSerialized\n  = | AutomockedModuleSerialized\n    | AutospiedModuleSerialized\n    | ManualMockedModuleSerialized\n    | RedirectedModuleSerialized\n\nexport class AutomockedModule {\n  public readonly type = 'automock'\n\n  constructor(\n    public raw: string,\n    public id: string,\n    public url: string,\n  ) {}\n\n  static fromJSON(data: AutomockedModuleSerialized): AutospiedModule {\n    return new AutospiedModule(data.raw, data.id, data.url)\n  }\n\n  toJSON(): AutomockedModuleSerialized {\n    return {\n      type: this.type,\n      url: this.url,\n      raw: this.raw,\n      id: this.id,\n    }\n  }\n}\n\nexport interface AutomockedModuleSerialized {\n  type: 'automock'\n  url: string\n  raw: string\n  id: string\n}\n\nexport class AutospiedModule {\n  public readonly type = 'autospy'\n\n  constructor(\n    public raw: string,\n    public id: string,\n    public url: string,\n  ) {}\n\n  static fromJSON(data: AutospiedModuleSerialized): AutospiedModule {\n    return new AutospiedModule(data.raw, data.id, data.url)\n  }\n\n  toJSON(): AutospiedModuleSerialized {\n    return {\n      type: this.type,\n      url: this.url,\n      id: this.id,\n      raw: this.raw,\n    }\n  }\n}\n\nexport interface AutospiedModuleSerialized {\n  type: 'autospy'\n  url: string\n  raw: string\n  id: string\n}\n\nexport class RedirectedModule {\n  public readonly type = 'redirect'\n\n  constructor(\n    public raw: string,\n    public id: string,\n    public url: string,\n    public redirect: string,\n  ) {}\n\n  static fromJSON(data: RedirectedModuleSerialized): RedirectedModule {\n    return new RedirectedModule(data.raw, data.id, data.url, data.redirect)\n  }\n\n  toJSON(): RedirectedModuleSerialized {\n    return {\n      type: this.type,\n      url: this.url,\n      raw: this.raw,\n      id: this.id,\n      redirect: this.redirect,\n    }\n  }\n}\n\nexport interface RedirectedModuleSerialized {\n  type: 'redirect'\n  url: string\n  id: string\n  raw: string\n  redirect: string\n}\n\nexport class ManualMockedModule<T = any> {\n  public cache: T | undefined\n  public readonly type = 'manual'\n\n  constructor(\n    public raw: string,\n    public id: string,\n    public url: string,\n    public factory: () => T,\n  ) {}\n\n  resolve(): T {\n    if (this.cache) {\n      return this.cache\n    }\n    let exports: any\n    try {\n      exports = this.factory()\n    }\n    catch (err: any) {\n      throw createHelpfulError(err)\n    }\n\n    if (typeof exports === 'object' && typeof exports?.then === 'function') {\n      return exports.then(\n        (result: T) => {\n          assertValidExports(this.raw, result)\n          return (this.cache = result)\n        },\n        (error: any) => {\n          throw createHelpfulError(error)\n        },\n      )\n    }\n\n    assertValidExports(this.raw, exports)\n\n    return (this.cache = exports)\n  }\n\n  static fromJSON(data: ManualMockedModuleSerialized, factory: () => any): ManualMockedModule {\n    return new ManualMockedModule(data.raw, data.id, data.url, factory)\n  }\n\n  toJSON(): ManualMockedModuleSerialized {\n    return {\n      type: this.type,\n      url: this.url,\n      id: this.id,\n      raw: this.raw,\n    }\n  }\n}\n\nfunction createHelpfulError(cause: Error) {\n  const error = new Error(\n    '[vitest] There was an error when mocking a module. '\n    + 'If you are using \"vi.mock\" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. '\n    + 'Read more: https://vitest.dev/api/vi.html#vi-mock',\n  )\n  error.cause = cause\n  return error\n}\n\nfunction assertValidExports(raw: string, exports: any) {\n  if (exports === null || typeof exports !== 'object' || Array.isArray(exports)) {\n    throw new TypeError(\n      `[vitest] vi.mock(\"${raw}\", factory?: () => unknown) is not returning an object. Did you mean to return an object with a \"default\" key?`,\n    )\n  }\n}\n\nexport interface ManualMockedModuleSerialized {\n  type: 'manual'\n  url: string\n  id: string\n  raw: string\n}\n"
  },
  {
    "path": "packages/mocker/src/types.ts",
    "content": "/* eslint-disable ts/method-signature-style */\n\ntype Awaitable<T> = T | PromiseLike<T>\n\nexport type ModuleMockFactoryWithHelper<M = unknown> = (\n  importOriginal: <T extends M = M>() => Promise<T>,\n) => Awaitable<Partial<M>>\nexport type ModuleMockFactory = () => any\nexport interface ModuleMockOptions {\n  spy?: boolean\n}\n\nexport interface ServerMockResolution {\n  mockType: 'manual' | 'redirect' | 'automock' | 'autospy'\n  resolvedId: string\n  resolvedUrl: string\n  needsInterop?: boolean\n  redirectUrl?: string | null\n}\n\nexport interface ServerIdResolution {\n  id: string\n  url: string\n  optimized: boolean\n}\n\nexport interface ModuleMockContext {\n  /**\n   * When mocking with a factory, this refers to the module that imported the mock.\n   */\n  callstack: null | string[]\n}\n\nexport interface TestModuleMocker {\n  queueMock(\n    id: string,\n    importer: string,\n    factoryOrOptions?: ModuleMockFactory | ModuleMockOptions,\n  ): void\n  queueUnmock(id: string, importer: string): void\n  importActual<T>(\n    rawId: string,\n    importer: string,\n    callstack?: string[] | null,\n  ): Promise<T>\n  importMock(rawId: string, importer: string): Promise<any>\n  mockObject(\n    object: Record<string | symbol, any>,\n    moduleType?: 'automock' | 'autospy',\n  ): Record<string | symbol, any>\n  mockObject(\n    object: Record<string | symbol, any>,\n    mockExports: Record<string | symbol, any> | undefined,\n    moduleType?: 'automock' | 'autospy',\n  ): Record<string | symbol, any>\n  getMockContext(): ModuleMockContext\n  reset(): void\n}\n"
  },
  {
    "path": "packages/mocker/src/utils.ts",
    "content": "const postfixRE = /[?#].*$/\nexport function cleanUrl(url: string): string {\n  return url.replace(postfixRE, '')\n}\n\nexport function createManualModuleSource(moduleUrl: string, exports: string[], globalAccessor = '\"__vitest_mocker__\"'): string {\n  const source = `\nconst __factoryModule__ = await globalThis[${globalAccessor}].getFactoryModule(\"${moduleUrl}\");\n`\n  const keys = exports\n    .map((name, index) => {\n      return `let __${index} = __factoryModule__[\"${name}\"]\nexport { __${index} as \"${name}\" }`\n    })\n    .join('\\n')\n  let code = `${source}\\n${keys}`\n  // this prevents recursion\n  code += `\nif (__factoryModule__.__factoryPromise != null) {\n  __factoryModule__.__factoryPromise.then((resolvedModule) => {\n    ${exports.map((name, index) => {\n      return `__${index} = resolvedModule[\"${name}\"];`\n    }).join('\\n')}\n  })\n}\n  `\n  return code\n}\n"
  },
  {
    "path": "packages/mocker/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"moduleResolution\": \"Bundler\",\n    \"types\": [\"vite/client\"],\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\"**/dist/**\"]\n}\n"
  },
  {
    "path": "packages/pretty-format/README.md",
    "content": "# @vitest/pretty-format\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/pretty-format?color=a1b858&label=)](https://npmx.dev/package/@vitest/pretty-format)\n\nJest's `pretty-format` implementation that only supports ESM.\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/pretty-format) | [Documentation](https://vitest.dev/)\n"
  },
  {
    "path": "packages/pretty-format/package.json",
    "content": "{\n  \"name\": \"@vitest/pretty-format\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Fork of pretty-format with support for ESM\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://github.com/vitest-dev/vitest/tree/main/packages/pretty-format\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/pretty-format\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vitest\",\n    \"test\",\n    \"pretty\",\n    \"pretty-format\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"*.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch\"\n  },\n  \"dependencies\": {\n    \"tinyrainbow\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@types/react-is\": \"^19.2.0\",\n    \"react-is\": \"^19.2.4\",\n    \"react-is-18\": \"npm:react-is@18.3.1\"\n  }\n}\n"
  },
  {
    "path": "packages/pretty-format/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst entries = {\n  index: 'src/index.ts',\n}\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  resolve({\n    preferBuiltins: true,\n  }),\n  json(),\n  {\n    name: 'process-env',\n    transform(code) {\n      // inline is-react\n      if (code.includes('process.env.NODE_ENV')) {\n        return code.replace(/process\\.env\\.NODE_ENV/g, '\"production\"')\n      }\n    },\n  },\n  commonjs(),\n  oxc({\n    transform: {\n      target: 'node20',\n    },\n  }),\n]\n\nexport default defineConfig([\n  {\n    input: entries,\n    output: {\n      dir: 'dist',\n      format: 'esm',\n      entryFileNames: '[name].js',\n      chunkFileNames: 'chunk-[name].js',\n    },\n    external,\n    plugins,\n    onwarn,\n  },\n  {\n    input: dtsUtils.dtsInput(entries),\n    output: {\n      dir: 'dist',\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n    onwarn,\n  },\n])\n\nfunction onwarn(message) {\n  if (['EMPTY_BUNDLE', 'CIRCULAR_DEPENDENCY'].includes(message.code)) {\n    return\n  }\n  console.error(message)\n}\n"
  },
  {
    "path": "packages/pretty-format/src/collections.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { CompareKeys, Config, Printer, Refs } from './types'\n\nfunction getKeysOfEnumerableProperties(object: Record<string, unknown>, compareKeys: CompareKeys) {\n  const rawKeys = Object.keys(object)\n  const keys: Array<string | symbol>\n    = compareKeys === null ? rawKeys : rawKeys.sort(compareKeys)\n\n  if (Object.getOwnPropertySymbols) {\n    for (const symbol of Object.getOwnPropertySymbols(object)) {\n      if (Object.getOwnPropertyDescriptor(object, symbol)!.enumerable) {\n        keys.push(symbol)\n      }\n    }\n  }\n\n  return keys as Array<string>\n}\n\n/**\n * Return entries (for example, of a map)\n * with spacing, indentation, and comma\n * without surrounding punctuation (for example, braces)\n */\nexport function printIteratorEntries(\n  iterator: Iterator<[unknown, unknown]>,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n  separator = ': ',\n): string {\n  let result = ''\n  let width = 0\n  let current = iterator.next()\n\n  if (!current.done) {\n    result += config.spacingOuter\n\n    const indentationNext = indentation + config.indent\n\n    while (!current.done) {\n      result += indentationNext\n\n      if (width++ === config.maxWidth) {\n        result += '…'\n        break\n      }\n\n      const name = printer(\n        current.value[0],\n        config,\n        indentationNext,\n        depth,\n        refs,\n      )\n      const value = printer(\n        current.value[1],\n        config,\n        indentationNext,\n        depth,\n        refs,\n      )\n\n      result += name + separator + value\n\n      current = iterator.next()\n\n      if (!current.done) {\n        result += `,${config.spacingInner}`\n      }\n      else if (!config.min) {\n        result += ','\n      }\n    }\n\n    result += config.spacingOuter + indentation\n  }\n\n  return result\n}\n\n/**\n * Return values (for example, of a set)\n * with spacing, indentation, and comma\n * without surrounding punctuation (braces or brackets)\n */\nexport function printIteratorValues(\n  iterator: Iterator<unknown>,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n): string {\n  let result = ''\n  let width = 0\n  let current = iterator.next()\n\n  if (!current.done) {\n    result += config.spacingOuter\n\n    const indentationNext = indentation + config.indent\n\n    while (!current.done) {\n      result += indentationNext\n\n      if (width++ === config.maxWidth) {\n        result += '…'\n        break\n      }\n\n      result += printer(current.value, config, indentationNext, depth, refs)\n\n      current = iterator.next()\n\n      if (!current.done) {\n        result += `,${config.spacingInner}`\n      }\n      else if (!config.min) {\n        result += ','\n      }\n    }\n\n    result += config.spacingOuter + indentation\n  }\n\n  return result\n}\n\n/**\n * Return items (for example, of an array)\n * with spacing, indentation, and comma\n * without surrounding punctuation (for example, brackets)\n */\nexport function printListItems(\n  list: ArrayLike<unknown> | DataView | ArrayBuffer,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n): string {\n  let result = ''\n  list = list instanceof ArrayBuffer ? new DataView(list) : list\n  const isDataView = (l: unknown): l is DataView => l instanceof DataView\n  const length = isDataView(list) ? list.byteLength : list.length\n\n  if (length > 0) {\n    result += config.spacingOuter\n\n    const indentationNext = indentation + config.indent\n\n    for (let i = 0; i < length; i++) {\n      result += indentationNext\n\n      if (i === config.maxWidth) {\n        result += '…'\n        break\n      }\n\n      if (isDataView(list) || i in list) {\n        result += printer(\n          isDataView(list) ? list.getInt8(i) : list[i],\n          config,\n          indentationNext,\n          depth,\n          refs,\n        )\n      }\n\n      if (i < length - 1) {\n        result += `,${config.spacingInner}`\n      }\n      else if (!config.min) {\n        result += ','\n      }\n    }\n\n    result += config.spacingOuter + indentation\n  }\n\n  return result\n}\n\n/**\n * Return properties of an object\n * with spacing, indentation, and comma\n * without surrounding punctuation (for example, braces)\n */\nexport function printObjectProperties(\n  val: Record<string, unknown>,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n): string {\n  let result = ''\n  const keys = getKeysOfEnumerableProperties(val, config.compareKeys)\n\n  if (keys.length > 0) {\n    result += config.spacingOuter\n\n    const indentationNext = indentation + config.indent\n\n    for (let i = 0; i < keys.length; i++) {\n      const key = keys[i]\n      const name = printer(key, config, indentationNext, depth, refs)\n      const value = printer(val[key], config, indentationNext, depth, refs)\n\n      result += `${indentationNext + name}: ${value}`\n\n      if (i < keys.length - 1) {\n        result += `,${config.spacingInner}`\n      }\n      else if (!config.min) {\n        result += ','\n      }\n    }\n\n    result += config.spacingOuter + indentation\n  }\n\n  return result\n}\n"
  },
  {
    "path": "packages/pretty-format/src/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {\n  Colors,\n  Config,\n  NewPlugin,\n  Options,\n  OptionsReceived,\n  Plugin,\n  Plugins,\n  Refs,\n  Theme,\n} from './types'\nimport styles from 'tinyrainbow'\nimport {\n  printIteratorEntries,\n  printIteratorValues,\n  printListItems,\n  printObjectProperties,\n} from './collections'\nimport AsymmetricMatcher from './plugins/AsymmetricMatcher'\nimport DOMCollection from './plugins/DOMCollection'\nimport DOMElement from './plugins/DOMElement'\nimport Immutable from './plugins/Immutable'\nimport ReactElement from './plugins/ReactElement'\nimport ReactTestComponent from './plugins/ReactTestComponent'\n\nexport { createDOMElementFilter } from './plugins/DOMElement'\n\nconst toString = Object.prototype.toString\nconst toISOString = Date.prototype.toISOString\nconst errorToString = Error.prototype.toString\nconst regExpToString = RegExp.prototype.toString\n\n/**\n * Explicitly comparing typeof constructor to function avoids undefined as name\n * when mock identity-obj-proxy returns the key as the value for any key.\n */\nfunction getConstructorName(val: new (...args: Array<any>) => unknown) {\n  return (typeof val.constructor === 'function' && val.constructor.name) || 'Object'\n}\n\n/** Is val is equal to global window object? Works even if it does not exist :) */\nfunction isWindow(val: unknown) {\n  return typeof window !== 'undefined' && val === window\n}\n\n// eslint-disable-next-line regexp/no-super-linear-backtracking\nconst SYMBOL_REGEXP = /^Symbol\\((.*)\\)(.*)$/\nconst NEWLINE_REGEXP = /\\n/g\n\nclass PrettyFormatPluginError extends Error {\n  constructor(message: string, stack: string) {\n    super(message)\n    this.stack = stack\n    this.name = this.constructor.name\n  }\n}\n\nfunction isToStringedArrayType(toStringed: string): boolean {\n  return (\n    toStringed === '[object Array]'\n    || toStringed === '[object ArrayBuffer]'\n    || toStringed === '[object DataView]'\n    || toStringed === '[object Float32Array]'\n    || toStringed === '[object Float64Array]'\n    || toStringed === '[object Int8Array]'\n    || toStringed === '[object Int16Array]'\n    || toStringed === '[object Int32Array]'\n    || toStringed === '[object Uint8Array]'\n    || toStringed === '[object Uint8ClampedArray]'\n    || toStringed === '[object Uint16Array]'\n    || toStringed === '[object Uint32Array]'\n  )\n}\n\nfunction printNumber(val: number): string {\n  return Object.is(val, -0) ? '-0' : String(val)\n}\n\nfunction printBigInt(val: bigint): string {\n  return String(`${val}n`)\n}\n\nfunction printFunction(val: Function, printFunctionName: boolean): string {\n  if (!printFunctionName) {\n    return '[Function]'\n  }\n  return `[Function ${val.name || 'anonymous'}]`\n}\n\nfunction printSymbol(val: symbol): string {\n  return String(val).replace(SYMBOL_REGEXP, 'Symbol($1)')\n}\n\nfunction printError(val: Error): string {\n  return `[${errorToString.call(val)}]`\n}\n\n/**\n * The first port of call for printing an object, handles most of the\n * data-types in JS.\n */\nfunction printBasicValue(\n  val: any,\n  printFunctionName: boolean,\n  escapeRegex: boolean,\n  escapeString: boolean,\n): string | null {\n  if (val === true || val === false) {\n    return `${val}`\n  }\n  if (val === undefined) {\n    return 'undefined'\n  }\n  if (val === null) {\n    return 'null'\n  }\n\n  const typeOf = typeof val\n\n  if (typeOf === 'number') {\n    return printNumber(val)\n  }\n  if (typeOf === 'bigint') {\n    return printBigInt(val)\n  }\n  if (typeOf === 'string') {\n    if (escapeString) {\n      return `\"${val.replaceAll(/\"|\\\\/g, '\\\\$&')}\"`\n    }\n    return `\"${val}\"`\n  }\n  if (typeOf === 'function') {\n    return printFunction(val, printFunctionName)\n  }\n  if (typeOf === 'symbol') {\n    return printSymbol(val)\n  }\n\n  const toStringed = toString.call(val)\n\n  if (toStringed === '[object WeakMap]') {\n    return 'WeakMap {}'\n  }\n  if (toStringed === '[object WeakSet]') {\n    return 'WeakSet {}'\n  }\n  if (\n    toStringed === '[object Function]'\n    || toStringed === '[object GeneratorFunction]'\n  ) {\n    return printFunction(val, printFunctionName)\n  }\n  if (toStringed === '[object Symbol]') {\n    return printSymbol(val)\n  }\n  if (toStringed === '[object Date]') {\n    return Number.isNaN(+val) ? 'Date { NaN }' : toISOString.call(val)\n  }\n  if (toStringed === '[object Error]') {\n    return printError(val)\n  }\n  if (toStringed === '[object RegExp]') {\n    if (escapeRegex) {\n      // https://github.com/benjamingr/RegExp.escape/blob/main/polyfill.js\n      return regExpToString.call(val).replaceAll(/[$()*+.?[\\\\\\]^{|}]/g, '\\\\$&')\n    }\n    return regExpToString.call(val)\n  }\n\n  if (val instanceof Error) {\n    return printError(val)\n  }\n\n  return null\n}\n\n/**\n * Handles more complex objects ( such as objects with circular references.\n * maps and sets etc )\n */\nfunction printComplexValue(\n  val: any,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  hasCalledToJSON?: boolean,\n): string {\n  if (refs.includes(val)) {\n    return '[Circular]'\n  }\n  refs = [...refs]\n  refs.push(val)\n\n  const hitMaxDepth = ++depth > config.maxDepth\n  const min = config.min\n\n  if (\n    config.callToJSON\n    && !hitMaxDepth\n    && val.toJSON\n    && typeof val.toJSON === 'function'\n    && !hasCalledToJSON\n  ) {\n    return printer(val.toJSON(), config, indentation, depth, refs, true)\n  }\n\n  const toStringed = toString.call(val)\n  if (toStringed === '[object Arguments]') {\n    return hitMaxDepth\n      ? '[Arguments]'\n      : `${min ? '' : 'Arguments '}[${printListItems(\n        val,\n        config,\n        indentation,\n        depth,\n        refs,\n        printer,\n      )}]`\n  }\n  if (isToStringedArrayType(toStringed)) {\n    return hitMaxDepth\n      ? `[${val.constructor.name}]`\n      : `${\n        min\n          ? ''\n          : !config.printBasicPrototype && val.constructor.name === 'Array'\n              ? ''\n              : `${val.constructor.name} `\n      }[${printListItems(val, config, indentation, depth, refs, printer)}]`\n  }\n  if (toStringed === '[object Map]') {\n    return hitMaxDepth\n      ? '[Map]'\n      : `Map {${printIteratorEntries(\n        val.entries(),\n        config,\n        indentation,\n        depth,\n        refs,\n        printer,\n        ' => ',\n      )}}`\n  }\n  if (toStringed === '[object Set]') {\n    return hitMaxDepth\n      ? '[Set]'\n      : `Set {${printIteratorValues(\n        val.values(),\n        config,\n        indentation,\n        depth,\n        refs,\n        printer,\n      )}}`\n  }\n\n  // Avoid failure to serialize global window object in jsdom test environment.\n  // For example, not even relevant if window is prop of React element.\n  return hitMaxDepth || isWindow(val)\n    ? `[${getConstructorName(val)}]`\n    : `${\n      min\n        ? ''\n        : !config.printBasicPrototype && getConstructorName(val) === 'Object'\n            ? ''\n            : `${getConstructorName(val)} `\n    }{${printObjectProperties(\n      val,\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n    )}}`\n}\n\nconst ErrorPlugin: NewPlugin = {\n  test: val => val && val instanceof Error,\n  serialize(val: Error, config, indentation, depth, refs, printer) {\n    if (refs.includes(val)) {\n      return '[Circular]'\n    }\n    refs = [...refs, val]\n    const hitMaxDepth = ++depth > config.maxDepth\n    const { message, cause, ...rest } = val\n    const entries = {\n      message,\n      ...typeof cause !== 'undefined' ? { cause } : {},\n      ...val instanceof AggregateError ? { errors: val.errors } : {},\n      ...rest,\n    }\n    const name = val.name !== 'Error' ? val.name : getConstructorName(val as any)\n    return hitMaxDepth\n      ? `[${name}]`\n      : `${name} {${printIteratorEntries(\n        Object.entries(entries).values(),\n        config,\n        indentation,\n        depth,\n        refs,\n        printer,\n      )}}`\n  },\n}\n\nfunction isNewPlugin(plugin: Plugin): plugin is NewPlugin {\n  return (plugin as NewPlugin).serialize != null\n}\n\nfunction printPlugin(\n  plugin: Plugin,\n  val: any,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n): string {\n  let printed\n\n  try {\n    printed = isNewPlugin(plugin)\n      ? plugin.serialize(val, config, indentation, depth, refs, printer)\n      : plugin.print(\n          val,\n          valChild => printer(valChild, config, indentation, depth, refs),\n          (str) => {\n            const indentationNext = indentation + config.indent\n            return (\n              indentationNext\n              + str.replaceAll(NEWLINE_REGEXP, `\\n${indentationNext}`)\n            )\n          },\n          {\n            edgeSpacing: config.spacingOuter,\n            min: config.min,\n            spacing: config.spacingInner,\n          },\n          config.colors,\n        )\n  }\n  catch (error: any) {\n    throw new PrettyFormatPluginError(error.message, error.stack)\n  }\n  if (typeof printed !== 'string') {\n    throw new TypeError(\n      `pretty-format: Plugin must return type \"string\" but instead returned \"${typeof printed}\".`,\n    )\n  }\n  return printed\n}\n\nfunction findPlugin(plugins: Plugins, val: unknown) {\n  for (const plugin of plugins) {\n    try {\n      if (plugin.test(val)) {\n        return plugin\n      }\n    }\n    catch (error: any) {\n      throw new PrettyFormatPluginError(error.message, error.stack)\n    }\n  }\n\n  return null\n}\n\nfunction printer(\n  val: unknown,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  hasCalledToJSON?: boolean,\n): string {\n  const plugin = findPlugin(config.plugins, val)\n  if (plugin !== null) {\n    return printPlugin(plugin, val, config, indentation, depth, refs)\n  }\n\n  const basicResult = printBasicValue(\n    val,\n    config.printFunctionName,\n    config.escapeRegex,\n    config.escapeString,\n  )\n  if (basicResult !== null) {\n    return basicResult\n  }\n\n  return printComplexValue(\n    val,\n    config,\n    indentation,\n    depth,\n    refs,\n    hasCalledToJSON,\n  )\n}\n\nconst DEFAULT_THEME: Theme = {\n  comment: 'gray',\n  content: 'reset',\n  prop: 'yellow',\n  tag: 'cyan',\n  value: 'green',\n}\n\nconst DEFAULT_THEME_KEYS = Object.keys(DEFAULT_THEME) as Array<\n  keyof typeof DEFAULT_THEME\n>\n\nexport const DEFAULT_OPTIONS: Options = {\n  callToJSON: true,\n  compareKeys: undefined,\n  escapeRegex: false,\n  escapeString: true,\n  highlight: false,\n  indent: 2,\n  maxDepth: Number.POSITIVE_INFINITY,\n  maxWidth: Number.POSITIVE_INFINITY,\n  min: false,\n  plugins: [],\n  printBasicPrototype: true,\n  printFunctionName: true,\n  printShadowRoot: true,\n  theme: DEFAULT_THEME,\n} satisfies Options\n\nfunction validateOptions(options: OptionsReceived) {\n  for (const key of Object.keys(options)) {\n    if (!Object.hasOwn(DEFAULT_OPTIONS, key)) {\n      throw new Error(`pretty-format: Unknown option \"${key}\".`)\n    }\n  }\n\n  if (options.min && options.indent !== undefined && options.indent !== 0) {\n    throw new Error(\n      'pretty-format: Options \"min\" and \"indent\" cannot be used together.',\n    )\n  }\n}\n\nfunction getColorsHighlight(): Colors {\n  return DEFAULT_THEME_KEYS.reduce((colors, key) => {\n    const value = DEFAULT_THEME[key]\n    const color = value && (styles as any)[value]\n    if (\n      color\n      && typeof color.close === 'string'\n      && typeof color.open === 'string'\n    ) {\n      colors[key] = color\n    }\n    else {\n      throw new Error(\n        `pretty-format: Option \"theme\" has a key \"${key}\" whose value \"${value}\" is undefined in ansi-styles.`,\n      )\n    }\n    return colors\n  }, Object.create(null))\n}\n\nfunction getColorsEmpty(): Colors {\n  return DEFAULT_THEME_KEYS.reduce((colors, key) => {\n    colors[key] = { close: '', open: '' }\n    return colors\n  }, Object.create(null))\n}\n\nfunction getPrintFunctionName(options?: OptionsReceived) {\n  return options?.printFunctionName ?? DEFAULT_OPTIONS.printFunctionName\n}\n\nfunction getEscapeRegex(options?: OptionsReceived) {\n  return options?.escapeRegex ?? DEFAULT_OPTIONS.escapeRegex\n}\n\nfunction getEscapeString(options?: OptionsReceived) {\n  return options?.escapeString ?? DEFAULT_OPTIONS.escapeString\n}\n\nfunction getConfig(options?: OptionsReceived): Config {\n  return {\n    callToJSON: options?.callToJSON ?? DEFAULT_OPTIONS.callToJSON,\n    colors: options?.highlight ? getColorsHighlight() : getColorsEmpty(),\n    compareKeys:\n    typeof options?.compareKeys === 'function' || options?.compareKeys === null\n      ? options.compareKeys\n      : DEFAULT_OPTIONS.compareKeys,\n    escapeRegex: getEscapeRegex(options),\n    escapeString: getEscapeString(options),\n    indent: options?.min\n      ? ''\n      : createIndent(options?.indent ?? DEFAULT_OPTIONS.indent),\n    maxDepth: options?.maxDepth ?? DEFAULT_OPTIONS.maxDepth,\n    maxWidth: options?.maxWidth ?? DEFAULT_OPTIONS.maxWidth,\n    min: options?.min ?? DEFAULT_OPTIONS.min,\n    plugins: options?.plugins ?? DEFAULT_OPTIONS.plugins,\n    printBasicPrototype: options?.printBasicPrototype ?? true,\n    printFunctionName: getPrintFunctionName(options),\n    printShadowRoot: options?.printShadowRoot ?? true,\n    spacingInner: options?.min ? ' ' : '\\n',\n    spacingOuter: options?.min ? '' : '\\n',\n  }\n}\n\nfunction createIndent(indent: number): string {\n  return Array.from({ length: indent + 1 }).join(' ')\n}\n\n/**\n * Returns a presentation string of your `val` object\n * @param val any potential JavaScript object\n * @param options Custom settings\n */\nexport function format(val: unknown, options?: OptionsReceived): string {\n  if (options) {\n    validateOptions(options)\n    if (options.plugins) {\n      const plugin = findPlugin(options.plugins, val)\n      if (plugin !== null) {\n        return printPlugin(plugin, val, getConfig(options), '', 0, [])\n      }\n    }\n  }\n\n  const basicResult = printBasicValue(\n    val,\n    getPrintFunctionName(options),\n    getEscapeRegex(options),\n    getEscapeString(options),\n  )\n  if (basicResult !== null) {\n    return basicResult\n  }\n\n  return printComplexValue(val, getConfig(options), '', 0, [])\n}\n\nexport type {\n  Colors,\n  CompareKeys,\n  Config,\n  NewPlugin,\n  OldPlugin,\n  Options,\n  OptionsReceived,\n  Plugin,\n  Plugins,\n  PrettyFormatOptions,\n  Printer,\n  Refs,\n  Theme,\n} from './types'\n\nexport const plugins: {\n  AsymmetricMatcher: NewPlugin\n  DOMCollection: NewPlugin\n  DOMElement: NewPlugin\n  Immutable: NewPlugin\n  ReactElement: NewPlugin\n  ReactTestComponent: NewPlugin\n  Error: NewPlugin\n} = {\n  AsymmetricMatcher,\n  DOMCollection,\n  DOMElement,\n  Immutable,\n  ReactElement,\n  ReactTestComponent,\n  Error: ErrorPlugin,\n}\n"
  },
  {
    "path": "packages/pretty-format/src/plugins/AsymmetricMatcher.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Config, NewPlugin, Printer, Refs } from '../types'\nimport { printListItems, printObjectProperties } from '../collections'\n\nconst asymmetricMatcher\n  = typeof Symbol === 'function' && Symbol.for\n    ? Symbol.for('jest.asymmetricMatcher')\n    : 0x13_57_A5\nconst SPACE = ' '\n\nexport const serialize: NewPlugin['serialize'] = (\n  val: any,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n) => {\n  const stringedValue = val.toString()\n\n  if (\n    stringedValue === 'ArrayContaining'\n    || stringedValue === 'ArrayNotContaining'\n  ) {\n    if (++depth > config.maxDepth) {\n      return `[${stringedValue}]`\n    }\n    return `${stringedValue + SPACE}[${printListItems(\n      val.sample,\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n    )}]`\n  }\n\n  if (\n    stringedValue === 'ObjectContaining'\n    || stringedValue === 'ObjectNotContaining'\n  ) {\n    if (++depth > config.maxDepth) {\n      return `[${stringedValue}]`\n    }\n    return `${stringedValue + SPACE}{${printObjectProperties(\n      val.sample,\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n    )}}`\n  }\n\n  if (\n    stringedValue === 'StringMatching'\n    || stringedValue === 'StringNotMatching'\n  ) {\n    return (\n      stringedValue\n      + SPACE\n      + printer(val.sample, config, indentation, depth, refs)\n    )\n  }\n\n  if (\n    stringedValue === 'StringContaining'\n    || stringedValue === 'StringNotContaining'\n  ) {\n    return (\n      stringedValue\n      + SPACE\n      + printer(val.sample, config, indentation, depth, refs)\n    )\n  }\n\n  if (typeof val.toAsymmetricMatcher !== 'function') {\n    throw new TypeError(\n      `Asymmetric matcher ${val.constructor.name} does not implement toAsymmetricMatcher()`,\n    )\n  }\n\n  return val.toAsymmetricMatcher()\n}\n\nexport const test: NewPlugin['test'] = (val: any) =>\n  val && val.$$typeof === asymmetricMatcher\n\nconst plugin: NewPlugin = { serialize, test }\n\nexport default plugin\n"
  },
  {
    "path": "packages/pretty-format/src/plugins/DOMCollection.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Config, NewPlugin, Printer, Refs } from '../types'\nimport { printListItems, printObjectProperties } from '../collections'\n\nconst SPACE = ' '\n\nconst OBJECT_NAMES = new Set(['DOMStringMap', 'NamedNodeMap'])\nconst ARRAY_REGEXP = /^(?:HTML\\w*Collection|NodeList)$/\n\nfunction testName(name: any) {\n  return OBJECT_NAMES.has(name) || ARRAY_REGEXP.test(name)\n}\n\nexport const test: NewPlugin['test'] = (val: object) =>\n  val\n  && val.constructor\n  && !!val.constructor.name\n  && testName(val.constructor.name)\n\nfunction isNamedNodeMap(collection: object): collection is NamedNodeMap {\n  return collection.constructor.name === 'NamedNodeMap'\n}\n\nexport const serialize: NewPlugin['serialize'] = (\n  collection: any | NamedNodeMap,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n) => {\n  const name = collection.constructor.name\n  if (++depth > config.maxDepth) {\n    return `[${name}]`\n  }\n\n  return (\n    (config.min ? '' : name + SPACE)\n    + (OBJECT_NAMES.has(name)\n      ? `{${printObjectProperties(\n        isNamedNodeMap(collection)\n          ? [...collection].reduce<Record<string, string>>(\n              (props, attribute) => {\n                props[attribute.name] = attribute.value\n                return props\n              },\n              {},\n            )\n          : { ...collection },\n        config,\n        indentation,\n        depth,\n        refs,\n        printer,\n      )}}`\n      : `[${printListItems(\n        [...collection],\n        config,\n        indentation,\n        depth,\n        refs,\n        printer,\n      )}]`)\n  )\n}\n\nconst plugin: NewPlugin = { serialize, test }\n\nexport default plugin\n"
  },
  {
    "path": "packages/pretty-format/src/plugins/DOMElement.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Config, NewPlugin, Printer, Refs } from '../types'\nimport {\n  printChildren,\n  printComment,\n  printElement,\n  printElementAsLeaf,\n  printProps,\n  printShadowRoot,\n  printText,\n} from './lib/markup'\n\nconst ELEMENT_NODE = 1\nconst TEXT_NODE = 3\nconst COMMENT_NODE = 8\nconst FRAGMENT_NODE = 11\n\nconst ELEMENT_REGEXP = /^(?:(?:HTML|SVG)\\w*)?Element$/\n\nfunction testHasAttribute(val: any) {\n  try {\n    return typeof val.hasAttribute === 'function' && val.hasAttribute('is')\n  }\n  catch {\n    return false\n  }\n}\n\nfunction testNode(val: any) {\n  const constructorName = val.constructor.name\n  const { nodeType, tagName } = val\n  const isCustomElement\n    = (typeof tagName === 'string' && tagName.includes('-'))\n      || testHasAttribute(val)\n\n  return (\n    (nodeType === ELEMENT_NODE\n      && (ELEMENT_REGEXP.test(constructorName) || isCustomElement))\n    || (nodeType === TEXT_NODE && constructorName === 'Text')\n    || (nodeType === COMMENT_NODE && constructorName === 'Comment')\n    || (nodeType === FRAGMENT_NODE && constructorName === 'DocumentFragment')\n  )\n}\n\nexport const test: NewPlugin['test'] = (val: any) =>\n  val?.constructor?.name && testNode(val)\n\ntype HandledType = Element | Text | Comment | DocumentFragment\n\nfunction nodeIsText(node: HandledType): node is Text {\n  return node.nodeType === TEXT_NODE\n}\n\nfunction nodeIsComment(node: HandledType): node is Comment {\n  return node.nodeType === COMMENT_NODE\n}\n\nfunction nodeIsFragment(node: HandledType): node is DocumentFragment {\n  return node.nodeType === FRAGMENT_NODE\n}\n\nexport interface FilterConfig extends Config {\n  filterNode?: (node: any) => boolean\n}\n\nfunction filterChildren(children: any[], filterNode?: (node: any) => boolean): any[] {\n  // Filter out text nodes that only contain whitespace to prevent empty lines\n  // This is done regardless of whether a filterNode is provided\n  let filtered = children.filter((node) => {\n    // Filter out text nodes that are only whitespace\n    if (node.nodeType === TEXT_NODE) {\n      const text = node.data || ''\n      // Keep text nodes that have non-whitespace content\n      return text.trim().length > 0\n    }\n    return true\n  })\n\n  // Apply additional user-provided filter if specified\n  if (filterNode) {\n    filtered = filtered.filter(filterNode)\n  }\n\n  return filtered\n}\n\nfunction serializeDOM(\n  node: HandledType,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n  filterNode?: (node: any) => boolean,\n) {\n  if (nodeIsText(node)) {\n    return printText(node.data, config)\n  }\n\n  if (nodeIsComment(node)) {\n    return printComment(node.data, config)\n  }\n\n  const type = nodeIsFragment(node)\n    ? 'DocumentFragment'\n    : node.tagName.toLowerCase()\n\n  if (++depth > config.maxDepth) {\n    return printElementAsLeaf(type, config)\n  }\n\n  const children = Array.prototype.slice.call(node.childNodes || node.children)\n  const shadowChildren = (nodeIsFragment(node) || !node.shadowRoot)\n    ? []\n    : Array.prototype.slice.call(node.shadowRoot.children)\n\n  const resolvedChildren = filterNode ? filterChildren(children, filterNode) : children\n  const resolvedShadowChildren = filterNode ? filterChildren(shadowChildren, filterNode) : shadowChildren\n\n  return printElement(\n    type,\n    printProps(\n      nodeIsFragment(node)\n        ? []\n        : Array.from(node.attributes, attr => attr.name).sort(),\n      nodeIsFragment(node)\n        ? {}\n        : [...node.attributes].reduce<Record<string, string>>(\n            (props, attribute) => {\n              props[attribute.name] = attribute.value\n              return props\n            },\n            {},\n          ),\n      config,\n      indentation + config.indent,\n      depth,\n      refs,\n      printer,\n    ),\n    (resolvedShadowChildren.length > 0\n      ? printShadowRoot(resolvedShadowChildren, config, indentation + config.indent, depth, refs, printer)\n      : '')\n    + printChildren(\n      resolvedChildren,\n      config,\n      indentation + config.indent,\n      depth,\n      refs,\n      printer,\n    ),\n    config,\n    indentation,\n  )\n}\n\nexport const serialize: NewPlugin['serialize'] = (\n  node: HandledType,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n) => serializeDOM(node, config, indentation, depth, refs, printer)\n\nexport function createDOMElementFilter(filterNode?: (node: any) => boolean): NewPlugin {\n  return {\n    test,\n    serialize: (\n      node: HandledType,\n      config: Config,\n      indentation: string,\n      depth: number,\n      refs: Refs,\n      printer: Printer,\n    ) => serializeDOM(node, config, indentation, depth, refs, printer, filterNode),\n  }\n}\n\nconst plugin: NewPlugin = { serialize, test }\n\nexport default plugin\n"
  },
  {
    "path": "packages/pretty-format/src/plugins/Immutable.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Config, NewPlugin, Printer, Refs } from '../types'\nimport { printIteratorEntries, printIteratorValues } from '../collections'\n\n// SENTINEL constants are from https://github.com/facebook/immutable-js\nconst IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@'\nconst IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@'\nconst IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@'\nconst IS_MAP_SENTINEL = '@@__IMMUTABLE_MAP__@@'\nconst IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@'\nconst IS_RECORD_SENTINEL = '@@__IMMUTABLE_RECORD__@@' // immutable v4\nconst IS_SEQ_SENTINEL = '@@__IMMUTABLE_SEQ__@@'\nconst IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@'\nconst IS_STACK_SENTINEL = '@@__IMMUTABLE_STACK__@@'\n\nconst getImmutableName = (name: string) => `Immutable.${name}`\nconst printAsLeaf = (name: string) => `[${name}]`\nconst SPACE = ' '\nconst LAZY = '…' // Seq is lazy if it calls a method like filter\n\nfunction printImmutableEntries(\n  val: any,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n  type: string,\n): string {\n  return ++depth > config.maxDepth\n    ? printAsLeaf(getImmutableName(type))\n    : `${getImmutableName(type) + SPACE}{${printIteratorEntries(\n      val.entries(),\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n    )}}`\n}\n\n// Record has an entries method because it is a collection in immutable v3.\n// Return an iterator for Immutable Record from version v3 or v4.\nfunction getRecordEntries(val: any): Iterator<any> {\n  let i = 0\n  return {\n    next() {\n      if (i < val._keys.length) {\n        const key = val._keys[i++]\n        return { done: false, value: [key, val.get(key)] }\n      }\n      return { done: true, value: undefined }\n    },\n  }\n}\n\nfunction printImmutableRecord(val: any, config: Config, indentation: string, depth: number, refs: Refs, printer: Printer): string {\n  // _name property is defined only for an Immutable Record instance\n  // which was constructed with a second optional descriptive name arg\n  const name = getImmutableName(val._name || 'Record')\n  return ++depth > config.maxDepth\n    ? printAsLeaf(name)\n    : `${name + SPACE}{${printIteratorEntries(\n      getRecordEntries(val),\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n    )}}`\n}\n\nfunction printImmutableSeq(val: any, config: Config, indentation: string, depth: number, refs: Refs, printer: Printer): string {\n  const name = getImmutableName('Seq')\n\n  if (++depth > config.maxDepth) {\n    return printAsLeaf(name)\n  }\n\n  if (val[IS_KEYED_SENTINEL]) {\n    return `${name + SPACE}{${\n      // from Immutable collection of entries or from ECMAScript object\n      val._iter || val._object\n        ? printIteratorEntries(\n            val.entries(),\n            config,\n            indentation,\n            depth,\n            refs,\n            printer,\n          )\n        : LAZY\n    }}`\n  }\n\n  return `${name + SPACE}[${\n    val._iter // from Immutable collection of values\n    || val._array // from ECMAScript array\n    || val._collection // from ECMAScript collection in immutable v4\n    || val._iterable // from ECMAScript collection in immutable v3\n      ? printIteratorValues(\n          val.values(),\n          config,\n          indentation,\n          depth,\n          refs,\n          printer,\n        )\n      : LAZY\n  }]`\n}\n\nfunction printImmutableValues(val: any, config: Config, indentation: string, depth: number, refs: Refs, printer: Printer, type: string): string {\n  return ++depth > config.maxDepth\n    ? printAsLeaf(getImmutableName(type))\n    : `${getImmutableName(type) + SPACE}[${printIteratorValues(\n      val.values(),\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n    )}]`\n}\n\nexport const serialize: NewPlugin['serialize'] = (\n  val: any,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n) => {\n  if (val[IS_MAP_SENTINEL]) {\n    return printImmutableEntries(\n      val,\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n      val[IS_ORDERED_SENTINEL] ? 'OrderedMap' : 'Map',\n    )\n  }\n\n  if (val[IS_LIST_SENTINEL]) {\n    return printImmutableValues(\n      val,\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n      'List',\n    )\n  }\n  if (val[IS_SET_SENTINEL]) {\n    return printImmutableValues(\n      val,\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n      val[IS_ORDERED_SENTINEL] ? 'OrderedSet' : 'Set',\n    )\n  }\n  if (val[IS_STACK_SENTINEL]) {\n    return printImmutableValues(\n      val,\n      config,\n      indentation,\n      depth,\n      refs,\n      printer,\n      'Stack',\n    )\n  }\n\n  if (val[IS_SEQ_SENTINEL]) {\n    return printImmutableSeq(val, config, indentation, depth, refs, printer)\n  }\n\n  // For compatibility with immutable v3 and v4, let record be the default.\n  return printImmutableRecord(val, config, indentation, depth, refs, printer)\n}\n\n// Explicitly comparing sentinel properties to true avoids false positive\n// when mock identity-obj-proxy returns the key as the value for any key.\nexport const test: NewPlugin['test'] = (val: any) =>\n  val\n  && (val[IS_ITERABLE_SENTINEL] === true || val[IS_RECORD_SENTINEL] === true)\n\nconst plugin: NewPlugin = { serialize, test }\n\nexport default plugin\n"
  },
  {
    "path": "packages/pretty-format/src/plugins/ReactElement.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Config, NewPlugin, Printer, Refs } from '../types'\nimport * as ReactIs19 from 'react-is'\n// @ts-expect-error no type\nimport * as ReactIs18 from 'react-is-18'\nimport {\n  printChildren,\n  printElement,\n  printElementAsLeaf,\n  printProps,\n} from './lib/markup'\n\nconst reactIsMethods = [\n  'isAsyncMode',\n  'isConcurrentMode',\n  'isContextConsumer',\n  'isContextProvider',\n  'isElement',\n  'isForwardRef',\n  'isFragment',\n  'isLazy',\n  'isMemo',\n  'isPortal',\n  'isProfiler',\n  'isStrictMode',\n  'isSuspense',\n  'isSuspenseList',\n  'isValidElementType',\n] as const\n\nconst ReactIs: typeof ReactIs18 = Object.fromEntries(\n  reactIsMethods.map(m => [m, (v: any) => ReactIs18[m](v) || (ReactIs19 as any)[m](v)]),\n) as any\n\n// Given element.props.children, or subtree during recursive traversal,\n// return flattened array of children.\nfunction getChildren(arg: unknown, children: Array<unknown> = []) {\n  if (Array.isArray(arg)) {\n    for (const item of arg) {\n      getChildren(item, children)\n    }\n  }\n  else if (arg != null && arg !== false && arg !== '') {\n    children.push(arg)\n  }\n  return children\n}\n\nfunction getType(element: any) {\n  const type = element.type\n  if (typeof type === 'string') {\n    return type\n  }\n  if (typeof type === 'function') {\n    return type.displayName || type.name || 'Unknown'\n  }\n\n  if (ReactIs.isFragment(element)) {\n    return 'React.Fragment'\n  }\n  if (ReactIs.isSuspense(element)) {\n    return 'React.Suspense'\n  }\n  if (typeof type === 'object' && type !== null) {\n    if (ReactIs.isContextProvider(element)) {\n      return 'Context.Provider'\n    }\n\n    if (ReactIs.isContextConsumer(element)) {\n      return 'Context.Consumer'\n    }\n\n    if (ReactIs.isForwardRef(element)) {\n      if (type.displayName) {\n        return type.displayName\n      }\n\n      const functionName = type.render.displayName || type.render.name || ''\n\n      return functionName === '' ? 'ForwardRef' : `ForwardRef(${functionName})`\n    }\n\n    if (ReactIs.isMemo(element)) {\n      const functionName\n        = type.displayName || type.type.displayName || type.type.name || ''\n\n      return functionName === '' ? 'Memo' : `Memo(${functionName})`\n    }\n  }\n  return 'UNDEFINED'\n}\n\nfunction getPropKeys(element: any) {\n  const { props } = element\n\n  return Object.keys(props)\n    .filter(key => key !== 'children' && props[key] !== undefined)\n    .sort()\n}\n\nexport const serialize: NewPlugin['serialize'] = (\n  element: any,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n) =>\n  ++depth > config.maxDepth\n    ? printElementAsLeaf(getType(element), config)\n    : printElement(\n        getType(element),\n        printProps(\n          getPropKeys(element),\n          element.props,\n          config,\n          indentation + config.indent,\n          depth,\n          refs,\n          printer,\n        ),\n        printChildren(\n          getChildren(element.props.children),\n          config,\n          indentation + config.indent,\n          depth,\n          refs,\n          printer,\n        ),\n        config,\n        indentation,\n      )\n\nexport const test: NewPlugin['test'] = (val: unknown) =>\n  val != null && ReactIs.isElement(val)\n\nconst plugin: NewPlugin = { serialize, test }\n\nexport default plugin\n"
  },
  {
    "path": "packages/pretty-format/src/plugins/ReactTestComponent.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Config, NewPlugin, Printer, Refs } from '../types'\nimport {\n  printChildren,\n  printElement,\n  printElementAsLeaf,\n  printProps,\n} from './lib/markup'\n\nexport interface ReactTestObject {\n  $$typeof: symbol\n  type: string\n  props?: Record<string, unknown>\n  children?: null | Array<ReactTestChild>\n}\n\n// Child can be `number` in Stack renderer but not in Fiber renderer.\ntype ReactTestChild = ReactTestObject | string | number\n\nconst testSymbol\n  = typeof Symbol === 'function' && Symbol.for\n    ? Symbol.for('react.test.json')\n    : 0xE_A7_13_57\n\nfunction getPropKeys(object: ReactTestObject) {\n  const { props } = object\n\n  return props\n    ? Object.keys(props)\n        .filter(key => props[key] !== undefined)\n        .sort()\n    : []\n}\n\nexport const serialize: NewPlugin['serialize'] = (\n  object: ReactTestObject,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n) =>\n  ++depth > config.maxDepth\n    ? printElementAsLeaf(object.type, config)\n    : printElement(\n        object.type,\n        object.props\n          ? printProps(\n              getPropKeys(object),\n              object.props,\n              config,\n              indentation + config.indent,\n              depth,\n              refs,\n              printer,\n            )\n          : '',\n        object.children\n          ? printChildren(\n              object.children,\n              config,\n              indentation + config.indent,\n              depth,\n              refs,\n              printer,\n            )\n          : '',\n        config,\n        indentation,\n      )\n\nexport const test: NewPlugin['test'] = val =>\n  val && val.$$typeof === testSymbol\n\nconst plugin: NewPlugin = { serialize, test }\n\nexport default plugin\n"
  },
  {
    "path": "packages/pretty-format/src/plugins/lib/escapeHTML.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport default function escapeHTML(str: string): string {\n  return str.replaceAll('<', '&lt;').replaceAll('>', '&gt;')\n}\n"
  },
  {
    "path": "packages/pretty-format/src/plugins/lib/markup.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Config, Printer, Refs } from '../../types'\nimport escapeHTML from './escapeHTML'\n\n// Return empty string if keys is empty.\nexport function printProps(\n  keys: Array<string>,\n  props: Record<string, unknown>,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  printer: Printer,\n): string {\n  const indentationNext = indentation + config.indent\n  const colors = config.colors\n  return keys\n    .map((key) => {\n      const value = props[key]\n      // hidden injected value that should not be printed\n      if (\n        typeof value === 'string'\n        && value[0] === '_'\n        && value.startsWith('__vitest_')\n        && value.match(/__vitest_\\d+__/)\n      ) {\n        return ''\n      }\n\n      let printed = printer(value, config, indentationNext, depth, refs)\n\n      if (typeof value !== 'string') {\n        if (printed.includes('\\n')) {\n          printed\n            = config.spacingOuter\n              + indentationNext\n              + printed\n              + config.spacingOuter\n              + indentation\n        }\n        printed = `{${printed}}`\n      }\n\n      return `${\n        config.spacingInner\n        + indentation\n        + colors.prop.open\n        + key\n        + colors.prop.close\n      }=${colors.value.open}${printed}${colors.value.close}`\n    })\n    .join('')\n}\n\n// Return empty string if children is empty.\nexport function printChildren(children: Array<unknown>, config: Config, indentation: string, depth: number, refs: Refs, printer: Printer): string {\n  return children\n    .map(\n      child =>\n        config.spacingOuter\n        + indentation\n        + (typeof child === 'string'\n          ? printText(child, config)\n          : printer(child, config, indentation, depth, refs)),\n    )\n    .join('')\n}\n\nexport function printShadowRoot(children: Array<unknown>, config: Config, indentation: string, depth: number, refs: Refs, printer: Printer): string {\n  if (config.printShadowRoot === false) {\n    return ''\n  }\n  return [\n    `${config.spacingOuter + indentation}#shadow-root`,\n    printChildren(\n      children,\n      config,\n      indentation + config.indent,\n      depth,\n      refs,\n      printer,\n    ),\n  ].join('')\n}\n\nexport function printText(text: string, config: Config): string {\n  const contentColor = config.colors.content\n  return contentColor.open + escapeHTML(text) + contentColor.close\n}\n\nexport function printComment(comment: string, config: Config): string {\n  const commentColor = config.colors.comment\n  return `${commentColor.open}<!--${escapeHTML(comment)}-->${\n    commentColor.close\n  }`\n}\n\n// Separate the functions to format props, children, and element,\n// so a plugin could override a particular function, if needed.\n// Too bad, so sad: the traditional (but unnecessary) space\n// in a self-closing tagColor requires a second test of printedProps.\nexport function printElement(type: string, printedProps: string, printedChildren: string, config: Config, indentation: string): string {\n  const tagColor = config.colors.tag\n  return `${tagColor.open}<${type}${\n    printedProps\n    && tagColor.close\n    + printedProps\n    + config.spacingOuter\n    + indentation\n    + tagColor.open\n  }${\n    printedChildren\n      ? `>${tagColor.close}${printedChildren}${config.spacingOuter}${indentation}${tagColor.open}</${type}`\n      : `${printedProps && !config.min ? '' : ' '}/`\n  }>${tagColor.close}`\n}\n\nexport function printElementAsLeaf(type: string, config: Config): string {\n  const tagColor = config.colors.tag\n  return `${tagColor.open}<${type}${tagColor.close} …${tagColor.open} />${tagColor.close}`\n}\n"
  },
  {
    "path": "packages/pretty-format/src/types.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport interface Colors {\n  comment: { close: string; open: string }\n  content: { close: string; open: string }\n  prop: { close: string; open: string }\n  tag: { close: string; open: string }\n  value: { close: string; open: string }\n}\ntype Indent = (arg0: string) => string\nexport type Refs = Array<unknown>\ntype Print = (arg0: unknown) => string\n\nexport type Theme = Required<{\n  comment?: string\n  content?: string\n  prop?: string\n  tag?: string\n  value?: string\n}>\n\n/**\n * compare function used when sorting object keys, `null` can be used to skip over sorting.\n */\nexport type CompareKeys = ((a: string, b: string) => number) | null | undefined\n\ntype RequiredOptions = Required<PrettyFormatOptions>\n\nexport interface Options\n  extends Omit<RequiredOptions, 'compareKeys' | 'theme'> {\n  compareKeys: CompareKeys\n  theme: Theme\n}\n\nexport interface PrettyFormatOptions {\n  callToJSON?: boolean\n  escapeRegex?: boolean\n  escapeString?: boolean\n  highlight?: boolean\n  indent?: number\n  maxDepth?: number\n  maxWidth?: number\n  min?: boolean\n  printBasicPrototype?: boolean\n  printFunctionName?: boolean\n  printShadowRoot?: boolean\n  compareKeys?: CompareKeys\n  plugins?: Plugins\n}\n\nexport type OptionsReceived = PrettyFormatOptions\n\nexport interface Config {\n  callToJSON: boolean\n  compareKeys: CompareKeys\n  colors: Colors\n  escapeRegex: boolean\n  escapeString: boolean\n  indent: string\n  maxDepth: number\n  maxWidth: number\n  min: boolean\n  plugins: Plugins\n  printBasicPrototype: boolean\n  printFunctionName: boolean\n  printShadowRoot: boolean\n  spacingInner: string\n  spacingOuter: string\n}\n\nexport type Printer = (\n  val: unknown,\n  config: Config,\n  indentation: string,\n  depth: number,\n  refs: Refs,\n  hasCalledToJSON?: boolean,\n) => string\n\ntype Test = (arg0: any) => boolean\n\nexport interface NewPlugin {\n  serialize: (\n    val: any,\n    config: Config,\n    indentation: string,\n    depth: number,\n    refs: Refs,\n    printer: Printer,\n  ) => string\n  test: Test\n}\n\ninterface PluginOptions {\n  edgeSpacing: string\n  min: boolean\n  spacing: string\n}\n\nexport interface OldPlugin {\n  print: (\n    val: unknown,\n    print: Print,\n    indent: Indent,\n    options: PluginOptions,\n    colors: Colors,\n  ) => string\n  test: Test\n}\n\nexport type Plugin = NewPlugin | OldPlugin\n\nexport type Plugins = Array<Plugin>\n"
  },
  {
    "path": "packages/pretty-format/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"lib\": [\"ESNext\", \"DOM\", \"DOM.Iterable\"],\n    \"moduleResolution\": \"Bundler\",\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\"**/dist/**\"]\n}\n"
  },
  {
    "path": "packages/runner/README.md",
    "content": "# @vitest/runner\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/runner?color=a1b858&label=)](https://npmx.dev/package/@vitest/runner)\n\nVitest mechanism to collect and run tests.\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/runner) | [Documentation](https://vitest.dev/api/advanced/runner)\n"
  },
  {
    "path": "packages/runner/package.json",
    "content": "{\n  \"name\": \"@vitest/runner\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Vitest test runner\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/api/advanced/runner\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/runner\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vitest\",\n    \"test\",\n    \"test-runner\"\n  ],\n  \"sideEffects\": true,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./utils\": {\n      \"types\": \"./dist/utils.d.ts\",\n      \"default\": \"./dist/utils.js\"\n    },\n    \"./types\": {\n      \"types\": \"./dist/types.d.ts\",\n      \"default\": \"./dist/types.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"*.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch\"\n  },\n  \"dependencies\": {\n    \"@vitest/utils\": \"workspace:*\",\n    \"pathe\": \"catalog:\"\n  }\n}\n"
  },
  {
    "path": "packages/runner/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport json from '@rollup/plugin-json'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^@?vitest(\\/|$)/,\n]\n\nconst entries = {\n  index: 'src/index.ts',\n  utils: 'src/utils/index.ts',\n  types: 'src/types.ts',\n}\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n  json(),\n]\n\nexport default defineConfig([\n  {\n    input: entries,\n    output: {\n      dir: 'dist',\n      format: 'esm',\n      entryFileNames: '[name].js',\n      chunkFileNames: 'chunk-[name].js',\n    },\n    external,\n    plugins,\n    onwarn,\n  },\n  {\n    input: dtsUtils.dtsInput(entries),\n    output: {\n      dir: 'dist',\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n    onwarn,\n  },\n])\n\nfunction onwarn(message) {\n  if (['EMPTY_BUNDLE', 'CIRCULAR_DEPENDENCY'].includes(message.code)) {\n    return\n  }\n  console.error(message)\n}\n"
  },
  {
    "path": "packages/runner/src/artifact.ts",
    "content": "import type { Test, TestArtifact, TestArtifactBase /* used in JSDoc */, TestAttachment } from './types/tasks'\nimport { finishSendTasksUpdate } from './run'\nimport { getRunner } from './suite'\nimport { findTestFileStackTrace } from './utils/collect'\n\n/**\n * @experimental\n * @advanced\n *\n * Records a custom test artifact during test execution.\n *\n * This function allows you to attach structured data, files, or metadata to a test.\n *\n * Vitest automatically injects the source location where the artifact was created and manages any attachments you include.\n *\n * **Note:** artifacts must be recorded before the task is reported. Any artifacts recorded after that will not be included in the task.\n *\n * @param task - The test task context, typically accessed via `this.task` in custom matchers or `context.task` in tests\n * @param artifact - The artifact to record. Must extend {@linkcode TestArtifactBase}\n *\n * @returns A promise that resolves to the recorded artifact with location injected\n *\n * @throws {Error} If the test runner doesn't support artifacts\n *\n * @example\n * ```ts\n * // In a custom assertion\n * async function toHaveValidSchema(this: MatcherState, actual: unknown) {\n *   const validation = validateSchema(actual)\n *\n *   await recordArtifact(this.task, {\n *     type: 'my-plugin:schema-validation',\n *     passed: validation.valid,\n *     errors: validation.errors,\n *   })\n *\n *   return { pass: validation.valid, message: () => '...' }\n * }\n * ```\n */\nexport async function recordArtifact<Artifact extends TestArtifact>(task: Test, artifact: Artifact): Promise<Artifact> {\n  const runner = getRunner()\n\n  const stack = findTestFileStackTrace(\n    task.file.filepath,\n    new Error('STACK_TRACE').stack!,\n  )\n\n  if (stack) {\n    artifact.location = {\n      file: stack.file,\n      line: stack.line,\n      column: stack.column,\n    }\n\n    if (artifact.type === 'internal:annotation') {\n      artifact.annotation.location = artifact.location\n    }\n  }\n\n  if (Array.isArray(artifact.attachments)) {\n    for (const attachment of artifact.attachments) {\n      manageArtifactAttachment(attachment)\n    }\n  }\n\n  // annotations won't resolve as artifacts for backwards compatibility until next major\n  if (artifact.type === 'internal:annotation') {\n    return artifact\n  }\n\n  if (!runner.onTestArtifactRecord) {\n    throw new Error(`Test runner doesn't support test artifacts.`)\n  }\n\n  await finishSendTasksUpdate(runner)\n\n  const resolvedArtifact = await runner.onTestArtifactRecord(task, artifact)\n\n  task.artifacts.push(resolvedArtifact)\n\n  return resolvedArtifact as typeof artifact\n}\n\nconst table: string[] = []\nfor (let i = 65; i < 91; i++) {\n  table.push(String.fromCharCode(i)) // A-Z\n}\nfor (let i = 97; i < 123; i++) {\n  table.push(String.fromCharCode(i)) // a-z\n}\nfor (let i = 0; i < 10; i++) {\n  table.push(i.toString(10)) // 0-9\n}\ntable.push('+', '/')\n\nfunction encodeUint8Array(bytes: Uint8Array): string {\n  let base64 = ''\n  const len = bytes.byteLength\n  for (let i = 0; i < len; i += 3) {\n    if (len === i + 1) { // last 1 byte\n      const a = (bytes[i] & 0xFC) >> 2\n      const b = ((bytes[i] & 0x03) << 4)\n      base64 += table[a]\n      base64 += table[b]\n      base64 += '=='\n    }\n    else if (len === i + 2) { // last 2 bytes\n      const a = (bytes[i] & 0xFC) >> 2\n      const b = ((bytes[i] & 0x03) << 4) | ((bytes[i + 1] & 0xF0) >> 4)\n      const c = ((bytes[i + 1] & 0x0F) << 2)\n      base64 += table[a]\n      base64 += table[b]\n      base64 += table[c]\n      base64 += '='\n    }\n    else {\n      const a = (bytes[i] & 0xFC) >> 2\n      const b = ((bytes[i] & 0x03) << 4) | ((bytes[i + 1] & 0xF0) >> 4)\n      const c = ((bytes[i + 1] & 0x0F) << 2) | ((bytes[i + 2] & 0xC0) >> 6)\n      const d = bytes[i + 2] & 0x3F\n      base64 += table[a]\n      base64 += table[b]\n      base64 += table[c]\n      base64 += table[d]\n    }\n  }\n  return base64\n}\n\n/**\n * Records an async operation associated with a test task.\n *\n * This function tracks promises that should be awaited before a test completes.\n * The promise is automatically removed from the test's promise list once it settles.\n */\nexport function recordAsyncOperation<T>(\n  test: Test,\n  promise: Promise<T>,\n): Promise<T> {\n  // if promise is explicitly awaited, remove it from the list\n  promise = promise.finally(() => {\n    if (!test.promises) {\n      return\n    }\n    const index = test.promises.indexOf(promise)\n    if (index !== -1) {\n      test.promises.splice(index, 1)\n    }\n  })\n\n  // record promise\n  if (!test.promises) {\n    test.promises = []\n  }\n  test.promises.push(promise)\n  return promise\n}\n\n/**\n * Validates and prepares a test attachment for serialization.\n *\n * This function ensures attachments have either `body` or `path` set (but not both), and converts `Uint8Array` bodies to base64-encoded strings for easier serialization.\n *\n * @param attachment - The attachment to validate and prepare\n *\n * @throws {TypeError} If neither `body` nor `path` is provided\n * @throws {TypeError} If both `body` and `path` are provided\n */\nexport function manageArtifactAttachment(attachment: TestAttachment): void {\n  if (attachment.body == null && !attachment.path) {\n    throw new TypeError(`Test attachment requires \"body\" or \"path\" to be set. Both are missing.`)\n  }\n  if (attachment.body && attachment.path) {\n    throw new TypeError(`Test attachment requires only one of \"body\" or \"path\" to be set. Both are specified.`)\n  }\n  // convert to a string so it's easier to serialise\n  if (attachment.body instanceof Uint8Array) {\n    attachment.body = encodeUint8Array(attachment.body)\n  }\n}\n"
  },
  {
    "path": "packages/runner/src/collect.ts",
    "content": "import type { FileSpecification, VitestRunner } from './types/runner'\nimport type { File, SuiteHooks } from './types/tasks'\nimport { processError } from '@vitest/utils/error' // TODO: load dynamically\nimport { toArray } from '@vitest/utils/helpers'\nimport { collectorContext } from './context'\nimport { getHooks, setHooks } from './map'\nimport { runSetupFiles } from './setup'\nimport {\n  clearCollectorContext,\n  createSuiteHooks,\n  getDefaultSuite,\n} from './suite'\nimport {\n  calculateSuiteHash,\n  createFileTask,\n  interpretTaskModes,\n  someTasksAreOnly,\n} from './utils/collect'\nimport { createTagsFilter, validateTags } from './utils/tags'\n\nconst now = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now\n\nexport async function collectTests(\n  specs: string[] | FileSpecification[],\n  runner: VitestRunner,\n): Promise<File[]> {\n  const files: File[] = []\n\n  const config = runner.config\n  const $ = runner.trace!\n  let defaultTagsFilter: ((testTags: string[]) => boolean) | undefined\n\n  for (const spec of specs) {\n    const filepath = typeof spec === 'string' ? spec : spec.filepath\n    await $(\n      'collect_spec',\n      { 'code.file.path': filepath },\n      async () => {\n        const testLocations = typeof spec === 'string' ? undefined : spec.testLocations\n        const testNamePattern = typeof spec === 'string' ? undefined : spec.testNamePattern\n        const testIds = typeof spec === 'string' ? undefined : spec.testIds\n        const testTagsFilter = typeof spec === 'object' && spec.testTagsFilter\n          ? createTagsFilter(spec.testTagsFilter, config.tags)\n          : undefined\n\n        const fileTags: string[] = typeof spec === 'string' ? [] : (spec.fileTags || [])\n\n        const file = createFileTask(filepath, config.root, config.name, runner.pool, runner.viteEnvironment)\n        file.tags = fileTags\n        file.shuffle = config.sequence.shuffle\n\n        try {\n          validateTags(runner.config, fileTags)\n\n          runner.onCollectStart?.(file)\n\n          clearCollectorContext(file, runner)\n\n          const setupFiles = toArray(config.setupFiles)\n          if (setupFiles.length) {\n            const setupStart = now()\n            await runSetupFiles(config, setupFiles, runner)\n            const setupEnd = now()\n            file.setupDuration = setupEnd - setupStart\n          }\n          else {\n            file.setupDuration = 0\n          }\n\n          const collectStart = now()\n\n          await runner.importFile(filepath, 'collect')\n\n          const durations = runner.getImportDurations?.()\n          if (durations) {\n            file.importDurations = durations\n          }\n\n          const defaultTasks = await getDefaultSuite().collect(file)\n\n          const fileHooks = createSuiteHooks()\n          mergeHooks(fileHooks, getHooks(defaultTasks))\n\n          for (const c of [...defaultTasks.tasks, ...collectorContext.tasks]) {\n            if (c.type === 'test' || c.type === 'suite') {\n              file.tasks.push(c)\n            }\n            else if (c.type === 'collector') {\n              const suite = await c.collect(file)\n              if (suite.name || suite.tasks.length) {\n                mergeHooks(fileHooks, getHooks(suite))\n                file.tasks.push(suite)\n              }\n            }\n            else {\n              // check that types are exhausted\n              c satisfies never\n            }\n          }\n\n          setHooks(file, fileHooks)\n          file.collectDuration = now() - collectStart\n        }\n        catch (e) {\n          const errors = e instanceof AggregateError\n            ? e.errors.map(e => processError(e, runner.config.diffOptions))\n            : [processError(e, runner.config.diffOptions)]\n          file.result = {\n            state: 'fail',\n            errors,\n          }\n\n          const durations = runner.getImportDurations?.()\n          if (durations) {\n            file.importDurations = durations\n          }\n        }\n\n        calculateSuiteHash(file)\n\n        const hasOnlyTasks = someTasksAreOnly(file)\n        if (!testTagsFilter && !defaultTagsFilter && config.tagsFilter) {\n          defaultTagsFilter = createTagsFilter(config.tagsFilter, config.tags)\n        }\n        interpretTaskModes(\n          file,\n          testNamePattern ?? config.testNamePattern,\n          testLocations,\n          testIds,\n          testTagsFilter ?? defaultTagsFilter,\n          hasOnlyTasks,\n          false,\n          config.allowOnly,\n        )\n\n        if (file.mode === 'queued') {\n          file.mode = 'run'\n        }\n\n        files.push(file)\n      },\n    )\n  }\n\n  return files\n}\n\nfunction mergeHooks(baseHooks: SuiteHooks, hooks: SuiteHooks): SuiteHooks {\n  for (const _key in hooks) {\n    const key = _key as keyof SuiteHooks\n    baseHooks[key].push(...(hooks[key] as any))\n  }\n\n  return baseHooks\n}\n"
  },
  {
    "path": "packages/runner/src/context.ts",
    "content": "import type { Awaitable } from '@vitest/utils'\nimport type { VitestRunner } from './types/runner'\nimport type {\n  RuntimeContext,\n  SuiteCollector,\n  Test,\n  TestAnnotation,\n  TestContext,\n  WriteableTestContext,\n} from './types/tasks'\nimport { getSafeTimers } from '@vitest/utils/timers'\nimport { manageArtifactAttachment, recordArtifact, recordAsyncOperation } from './artifact'\nimport { PendingError } from './errors'\nimport { finishSendTasksUpdate } from './run'\nimport { getRunner } from './suite'\n\nconst now = globalThis.performance\n  ? globalThis.performance.now.bind(globalThis.performance)\n  : Date.now\n\nexport const collectorContext: RuntimeContext = {\n  tasks: [],\n  currentSuite: null,\n}\n\nexport function collectTask(task: SuiteCollector): void {\n  collectorContext.currentSuite?.tasks.push(task)\n}\n\nexport async function runWithSuite(\n  suite: SuiteCollector,\n  fn: () => Awaitable<void>,\n): Promise<void> {\n  const prev = collectorContext.currentSuite\n  collectorContext.currentSuite = suite\n  await fn()\n  collectorContext.currentSuite = prev\n}\n\nexport function withTimeout<T extends (...args: any[]) => any>(\n  fn: T,\n  timeout: number,\n  isHook = false,\n  stackTraceError?: Error,\n  onTimeout?: (args: T extends (...args: infer A) => any ? A : never, error: Error) => void,\n): T {\n  if (timeout <= 0 || timeout === Number.POSITIVE_INFINITY) {\n    return fn\n  }\n\n  const { setTimeout, clearTimeout } = getSafeTimers()\n\n  // this function name is used to filter error in test/cli/test/fails.test.ts\n  return (function runWithTimeout(...args: T extends (...args: infer A) => any ? A : never) {\n    const startTime = now()\n    const runner = getRunner()\n    runner._currentTaskStartTime = startTime\n    runner._currentTaskTimeout = timeout\n    return new Promise((resolve_, reject_) => {\n      const timer = setTimeout(() => {\n        clearTimeout(timer)\n        rejectTimeoutError()\n      }, timeout)\n      // `unref` might not exist in browser\n      timer.unref?.()\n\n      function rejectTimeoutError() {\n        const error = makeTimeoutError(isHook, timeout, stackTraceError)\n        onTimeout?.(args, error)\n        reject_(error)\n      }\n\n      function resolve(result: unknown) {\n        runner._currentTaskStartTime = undefined\n        runner._currentTaskTimeout = undefined\n        clearTimeout(timer)\n        // if test/hook took too long in microtask, setTimeout won't be triggered,\n        // but we still need to fail the test, see\n        // https://github.com/vitest-dev/vitest/issues/2920\n        if (now() - startTime >= timeout) {\n          rejectTimeoutError()\n          return\n        }\n        resolve_(result)\n      }\n\n      function reject(error: unknown) {\n        runner._currentTaskStartTime = undefined\n        runner._currentTaskTimeout = undefined\n        clearTimeout(timer)\n        reject_(error)\n      }\n\n      // sync test/hook will be caught by try/catch\n      try {\n        const result = fn(...args) as PromiseLike<unknown>\n        // the result is a thenable, we don't wrap this in Promise.resolve\n        // to avoid creating new promises\n        if (typeof result === 'object' && result != null && typeof result.then === 'function') {\n          result.then(resolve, reject)\n        }\n        else {\n          resolve(result)\n        }\n      }\n      // user sync test/hook throws an error\n      catch (error) {\n        reject(error)\n      }\n    })\n  }) as T\n}\n\nexport function withCancel<T extends (...args: any[]) => any>(\n  fn: T,\n  signal: AbortSignal,\n): T {\n  return (function runWithCancel(...args: T extends (...args: infer A) => any ? A : never) {\n    return new Promise((resolve, reject) => {\n      signal.addEventListener('abort', () => reject(signal.reason))\n\n      try {\n        const result = fn(...args) as PromiseLike<unknown>\n\n        if (typeof result === 'object' && result != null && typeof result.then === 'function') {\n          result.then(resolve, reject)\n        }\n        else {\n          resolve(result)\n        }\n      }\n      catch (error) {\n        reject(error)\n      }\n    })\n  }) as T\n}\n\nconst abortControllers = new WeakMap<TestContext, AbortController>()\n\nexport function abortIfTimeout([context]: [TestContext?, unknown?], error: Error): void {\n  if (context) {\n    abortContextSignal(context, error)\n  }\n}\n\nexport function abortContextSignal(context: TestContext, error: Error): void {\n  const abortController = abortControllers.get(context)\n  abortController?.abort(error)\n}\n\nexport function createTestContext(\n  test: Test,\n  runner: VitestRunner,\n): TestContext {\n  const context = function () {\n    throw new Error('done() callback is deprecated, use promise instead')\n  } as unknown as WriteableTestContext\n\n  let abortController = abortControllers.get(context)\n\n  if (!abortController) {\n    abortController = new AbortController()\n    abortControllers.set(context, abortController)\n  }\n\n  context.signal = abortController.signal\n  context.task = test\n\n  context.skip = (condition?: boolean | string, note?: string): never => {\n    if (condition === false) {\n      // do nothing\n      return undefined as never\n    }\n    test.result ??= { state: 'skip' }\n    test.result.pending = true\n    throw new PendingError(\n      'test is skipped; abort execution',\n      test,\n      typeof condition === 'string' ? condition : note,\n    )\n  }\n\n  context.annotate = ((message, type, attachment) => {\n    if (test.result && test.result.state !== 'run') {\n      throw new Error(`Cannot annotate tests outside of the test run. The test \"${test.name}\" finished running with the \"${test.result.state}\" state already.`)\n    }\n\n    const annotation: TestAnnotation = {\n      message,\n      type: typeof type === 'object' || type === undefined ? 'notice' : type,\n    }\n    const annotationAttachment = typeof type === 'object' ? type : attachment\n\n    if (annotationAttachment) {\n      annotation.attachment = annotationAttachment\n\n      manageArtifactAttachment(annotation.attachment)\n    }\n\n    return recordAsyncOperation(\n      test,\n      recordArtifact(test, { type: 'internal:annotation', annotation }).then(async ({ annotation }) => {\n        if (!runner.onTestAnnotate) {\n          throw new Error(`Test runner doesn't support test annotations.`)\n        }\n\n        await finishSendTasksUpdate(runner)\n\n        const resolvedAnnotation = await runner.onTestAnnotate(test, annotation)\n        test.annotations.push(resolvedAnnotation)\n        return resolvedAnnotation\n      }),\n    )\n  }) as TestContext['annotate']\n\n  context.onTestFailed = (handler, timeout) => {\n    test.onFailed ||= []\n    test.onFailed.push(\n      withTimeout(\n        handler,\n        timeout ?? runner.config.hookTimeout,\n        true,\n        new Error('STACK_TRACE_ERROR'),\n        (_, error) => abortController.abort(error),\n      ),\n    )\n  }\n\n  context.onTestFinished = (handler, timeout) => {\n    test.onFinished ||= []\n    test.onFinished.push(\n      withTimeout(\n        handler,\n        timeout ?? runner.config.hookTimeout,\n        true,\n        new Error('STACK_TRACE_ERROR'),\n        (_, error) => abortController.abort(error),\n      ),\n    )\n  }\n\n  return runner.extendTaskContext?.(context) || context\n}\n\nfunction makeTimeoutError(isHook: boolean, timeout: number, stackTraceError?: Error) {\n  const message = `${\n    isHook ? 'Hook' : 'Test'\n  } timed out in ${timeout}ms.\\nIf this is a long-running ${\n    isHook ? 'hook' : 'test'\n  }, pass a timeout value as the last argument or configure it globally with \"${\n    isHook ? 'hookTimeout' : 'testTimeout'\n  }\".`\n  const error = new Error(message)\n  if (stackTraceError?.stack) {\n    error.stack = stackTraceError.stack.replace(error.message, stackTraceError.message)\n  }\n  return error\n}\n"
  },
  {
    "path": "packages/runner/src/errors.ts",
    "content": "import type { CancelReason } from './types/runner'\nimport type { TaskBase } from './types/tasks'\n\nexport class PendingError extends Error {\n  public code = 'VITEST_PENDING'\n  public taskId: string\n\n  constructor(public message: string, task: TaskBase, public note: string | undefined) {\n    super(message)\n    this.taskId = task.id\n  }\n}\n\nexport class TestRunAbortError extends Error {\n  public name = 'TestRunAbortError'\n  public reason: CancelReason\n  constructor(message: string, reason: CancelReason) {\n    super(message)\n    this.reason = reason\n  }\n}\n\nexport class FixtureDependencyError extends Error {\n  public name = 'FixtureDependencyError'\n}\n\nexport class FixtureAccessError extends Error {\n  public name = 'FixtureAccessError'\n}\n\nexport class FixtureParseError extends Error {\n  public name = 'FixtureParseError'\n}\n\nexport class AroundHookSetupError extends Error {\n  public name = 'AroundHookSetupError'\n}\n\nexport class AroundHookTeardownError extends Error {\n  public name = 'AroundHookTeardownError'\n}\n\nexport class AroundHookMultipleCallsError extends Error {\n  public name = 'AroundHookMultipleCallsError'\n}\n"
  },
  {
    "path": "packages/runner/src/fixture.ts",
    "content": "import type { FixtureFn, Suite, VitestRunner } from './types'\nimport type { File, FixtureOptions, TestContext } from './types/tasks'\nimport { createDefer, filterOutComments, isObject, ordinal } from '@vitest/utils/helpers'\nimport { FixtureAccessError, FixtureDependencyError, FixtureParseError } from './errors'\nimport { getTestFixtures } from './map'\nimport { getCurrentSuite } from './suite'\n\nconst FIXTURE_STACK_TRACE_KEY = Symbol.for('VITEST_FIXTURE_STACK_TRACE')\n\nexport interface TestFixtureItem extends FixtureOptions {\n  name: string\n  value: unknown\n  scope: 'test' | 'file' | 'worker'\n  deps: Set<string>\n  // so it's possible to call base fixture inside ({ a: ({ a }, use) => {} })\n  parent?: TestFixtureItem\n}\n\nexport type UserFixtures = Record<string, unknown>\nexport type FixtureRegistrations = Map<string, TestFixtureItem>\n\nexport class TestFixtures {\n  private _suiteContexts: WeakMap<Suite | { type: 'worker' }, /* context object */ Record<string, unknown>>\n  private _overrides = new WeakMap<Suite, FixtureRegistrations>()\n  private _registrations: FixtureRegistrations\n\n  private static _definitions: TestFixtures[] = []\n  private static _builtinFixtures: string[] = [\n    'task',\n    'signal',\n    'onTestFailed',\n    'onTestFinished',\n    'skip',\n    'annotate',\n  ] satisfies (keyof TestContext)[]\n\n  private static _fixtureOptionKeys: string[] = ['auto', 'injected', 'scope']\n  private static _fixtureScopes: string[] = ['test', 'file', 'worker']\n  private static _workerContextSuite = { type: 'worker' } as const\n\n  static clearDefinitions(): void {\n    TestFixtures._definitions.length = 0\n  }\n\n  static getWorkerContexts(): Record<string, any>[] {\n    return TestFixtures._definitions.map(f => f.getWorkerContext())\n  }\n\n  static getFileContexts(file: File): Record<string, any>[] {\n    return TestFixtures._definitions.map(f => f.getFileContext(file))\n  }\n\n  static isFixtureOptions(obj: unknown): boolean {\n    return isObject(obj) && Object.keys(obj as any).some(key => TestFixtures._fixtureOptionKeys.includes(key))\n  }\n\n  constructor(registrations?: FixtureRegistrations) {\n    this._registrations = registrations ?? new Map()\n    this._suiteContexts = new WeakMap()\n    TestFixtures._definitions.push(this)\n  }\n\n  extend(runner: VitestRunner, userFixtures: UserFixtures): TestFixtures {\n    const { suite } = getCurrentSuite()\n    const isTopLevel = !suite || suite.file === suite\n    const registrations = this.parseUserFixtures(runner, userFixtures, isTopLevel)\n    return new TestFixtures(registrations)\n  }\n\n  get(suite: Suite): FixtureRegistrations {\n    let currentSuite: Suite | undefined = suite\n    while (currentSuite) {\n      const overrides = this._overrides.get(currentSuite)\n      // return the closest override\n      if (overrides) {\n        return overrides\n      }\n      if (currentSuite === currentSuite.file) {\n        break\n      }\n      currentSuite = currentSuite.suite || currentSuite.file\n    }\n    return this._registrations\n  }\n\n  override(runner: VitestRunner, userFixtures: UserFixtures): void {\n    const { suite: currentSuite, file } = getCurrentSuite()\n    const suite = currentSuite || file\n    const isTopLevel = !currentSuite || currentSuite.file === currentSuite\n    // Create a copy of the closest parent's registrations to avoid modifying them\n    // For chained calls, this.get(suite) returns this suite's overrides; for first call, returns parent's\n    const suiteRegistrations = new Map(this.get(suite))\n    const registrations = this.parseUserFixtures(runner, userFixtures, isTopLevel, suiteRegistrations)\n    // If defined in top-level, just override all registrations\n    // We don't support overriding suite-level fixtures anyway (it will throw an error)\n    if (isTopLevel) {\n      this._registrations = registrations\n    }\n    else {\n      this._overrides.set(suite, registrations)\n    }\n  }\n\n  getFileContext(file: File): Record<string, any> {\n    if (!this._suiteContexts.has(file)) {\n      this._suiteContexts.set(file, Object.create(null))\n    }\n    return this._suiteContexts.get(file)!\n  }\n\n  getWorkerContext(): Record<string, any> {\n    if (!this._suiteContexts.has(TestFixtures._workerContextSuite)) {\n      this._suiteContexts.set(TestFixtures._workerContextSuite, Object.create(null))\n    }\n    return this._suiteContexts.get(TestFixtures._workerContextSuite)!\n  }\n\n  private parseUserFixtures(\n    runner: VitestRunner,\n    userFixtures: UserFixtures,\n    supportNonTest: boolean,\n    registrations = new Map<string, TestFixtureItem>(this._registrations),\n  ) {\n    const errors: Error[] = []\n\n    Object.entries(userFixtures).forEach(([name, fn]) => {\n      let options: FixtureOptions | undefined\n      let value: unknown | undefined\n      let _options: FixtureOptions | undefined\n\n      if (\n        Array.isArray(fn)\n        && fn.length >= 2\n        && TestFixtures.isFixtureOptions(fn[1])\n      ) {\n        _options = fn[1] as FixtureOptions\n        options = {\n          auto: _options.auto ?? false,\n          scope: _options.scope ?? 'test',\n          injected: _options.injected ?? false,\n        }\n        value = options.injected\n          ? (runner.injectValue?.(name) ?? fn[0])\n          : fn[0]\n      }\n      else {\n        value = fn\n      }\n\n      const parent = registrations.get(name)\n      if (parent && options) {\n        if (parent.scope !== options.scope) {\n          errors.push(new FixtureDependencyError(`The \"${name}\" fixture was already registered with a \"${options.scope}\" scope.`))\n        }\n        if (parent.auto !== options.auto) {\n          errors.push(new FixtureDependencyError(`The \"${name}\" fixture was already registered as { auto: ${options.auto} }.`))\n        }\n      }\n      else if (parent) {\n        options = {\n          auto: parent.auto,\n          scope: parent.scope,\n          injected: parent.injected,\n        }\n      }\n      else if (!options) {\n        options = {\n          auto: false,\n          injected: false,\n          scope: 'test',\n        }\n      }\n\n      if (options.scope && !TestFixtures._fixtureScopes.includes(options.scope)) {\n        errors.push(new FixtureDependencyError(`The \"${name}\" fixture has unknown scope \"${options.scope}\".`))\n      }\n\n      if (!supportNonTest && options.scope !== 'test') {\n        errors.push(new FixtureDependencyError(`The \"${name}\" fixture cannot be defined with a ${options.scope} scope${!_options?.scope && parent?.scope ? ' (inherited from the base fixture)' : ''} inside the describe block. Define it at the top level of the file instead.`))\n      }\n\n      const deps = isFixtureFunction(value)\n        ? getUsedProps(value)\n        : new Set<string>()\n      const item: TestFixtureItem = {\n        name,\n        value,\n        auto: options.auto ?? false,\n        injected: options.injected ?? false,\n        scope: options.scope ?? 'test',\n        deps,\n        parent,\n      }\n\n      if (isFixtureFunction(value)) {\n        Object.assign(value, { [FIXTURE_STACK_TRACE_KEY]: new Error('STACK_TRACE_ERROR') })\n      }\n\n      registrations.set(name, item)\n\n      if (item.scope === 'worker' && (runner.pool === 'vmThreads' || runner.pool === 'vmForks')) {\n        item.scope = 'file'\n      }\n    })\n\n    // validate fixture dependency scopes\n    for (const fixture of registrations.values()) {\n      for (const depName of fixture.deps) {\n        if (TestFixtures._builtinFixtures.includes(depName)) {\n          continue\n        }\n\n        const dep = registrations.get(depName)\n        if (!dep) {\n          errors.push(new FixtureDependencyError(`The \"${fixture.name}\" fixture depends on unknown fixture \"${depName}\".`))\n          continue\n        }\n        if (depName === fixture.name && !fixture.parent) {\n          errors.push(new FixtureDependencyError(`The \"${fixture.name}\" fixture depends on itself, but does not have a base implementation.`))\n          continue\n        }\n\n        if (TestFixtures._fixtureScopes.indexOf(fixture.scope) > TestFixtures._fixtureScopes.indexOf(dep.scope)) {\n          errors.push(new FixtureDependencyError(`The ${fixture.scope} \"${fixture.name}\" fixture cannot depend on a ${dep.scope} fixture \"${dep.name}\".`))\n          continue\n        }\n      }\n    }\n\n    if (errors.length === 1) {\n      throw errors[0]\n    }\n    else if (errors.length > 1) {\n      throw new AggregateError(errors, 'Cannot resolve user fixtures. See errors for more information.')\n    }\n    return registrations\n  }\n}\n\nconst cleanupFnArrayMap = new WeakMap<\n  object,\n  Array<() => void | Promise<void>>\n>()\n\nexport async function callFixtureCleanup(context: object): Promise<void> {\n  const cleanupFnArray = cleanupFnArrayMap.get(context) ?? []\n  for (const cleanup of cleanupFnArray.reverse()) {\n    await cleanup()\n  }\n  cleanupFnArrayMap.delete(context)\n}\n\n/**\n * Returns the current number of cleanup functions registered for the context.\n * This can be used as a checkpoint to later clean up only fixtures added after this point.\n */\nexport function getFixtureCleanupCount(context: object): number {\n  return cleanupFnArrayMap.get(context)?.length ?? 0\n}\n\n/**\n * Cleans up only fixtures that were added after the given checkpoint index.\n * This is used by aroundEach to clean up fixtures created inside runTest()\n * while preserving fixtures that were created for aroundEach itself.\n */\nexport async function callFixtureCleanupFrom(context: object, fromIndex: number): Promise<void> {\n  const cleanupFnArray = cleanupFnArrayMap.get(context)\n  if (!cleanupFnArray || cleanupFnArray.length <= fromIndex) {\n    return\n  }\n  // Get items added after the checkpoint\n  const toCleanup = cleanupFnArray.slice(fromIndex)\n  // Clean up in reverse order\n  for (const cleanup of toCleanup.reverse()) {\n    await cleanup()\n  }\n  // Remove cleaned up items from the array, keeping items before checkpoint\n  cleanupFnArray.length = fromIndex\n}\n\ntype SuiteHook = 'beforeAll' | 'afterAll' | 'aroundAll'\n\nexport interface WithFixturesOptions {\n  /**\n   * Whether this is a suite-level hook (beforeAll/afterAll/aroundAll).\n   * Suite hooks can only access file/worker scoped fixtures and static values.\n   */\n  suiteHook?: SuiteHook\n  /**\n   * The test context to use. If not provided, the hookContext passed to the\n   * returned function will be used.\n   */\n  context?: Record<string, any>\n  /**\n   * Error with stack trace captured at hook registration time.\n   * Used to provide better error messages with proper stack traces.\n   */\n  stackTraceError?: Error\n  /**\n   * Current fixtures from the context.\n   */\n  fixtures?: TestFixtures\n  /**\n   * The suite to use for fixture lookups.\n   * Used by beforeEach/afterEach/aroundEach hooks to pick up fixture overrides from the test's describe block.\n   */\n  suite?: Suite\n}\n\nconst contextHasFixturesCache = new WeakMap<TestContext, WeakSet<TestFixtureItem>>()\n\nexport function withFixtures(fn: Function, options?: WithFixturesOptions) {\n  const collector = getCurrentSuite()\n  const suite = options?.suite || collector.suite || collector.file\n  return async (hookContext?: TestContext): Promise<any> => {\n    const context: (TestContext & { [key: string]: any }) | undefined = hookContext || options?.context as TestContext\n\n    if (!context) {\n      if (options?.suiteHook) {\n        validateSuiteHook(fn, options.suiteHook, options.stackTraceError)\n      }\n\n      return fn({})\n    }\n\n    const fixtures = options?.fixtures || getTestFixtures(context)\n    if (!fixtures) {\n      return fn(context)\n    }\n\n    const registrations = fixtures.get(suite)\n    if (!registrations.size) {\n      return fn(context)\n    }\n\n    const usedFixtures: TestFixtureItem[] = []\n    const usedProps = getUsedProps(fn)\n\n    for (const fixture of registrations.values()) {\n      if (fixture.auto || usedProps.has(fixture.name)) {\n        usedFixtures.push(fixture)\n      }\n    }\n\n    if (!usedFixtures.length) {\n      return fn(context)\n    }\n\n    if (!cleanupFnArrayMap.has(context)) {\n      cleanupFnArrayMap.set(context, [])\n    }\n    const cleanupFnArray = cleanupFnArrayMap.get(context)!\n\n    const pendingFixtures = resolveDeps(usedFixtures, registrations)\n\n    if (!pendingFixtures.length) {\n      return fn(context)\n    }\n\n    // Check if suite-level hook is trying to access test-scoped fixtures\n    // Suite hooks (beforeAll/afterAll/aroundAll) can only access file/worker scoped fixtures\n    if (options?.suiteHook) {\n      const testScopedFixtures = pendingFixtures.filter(f => f.scope === 'test')\n      if (testScopedFixtures.length > 0) {\n        const fixtureNames = testScopedFixtures.map(f => `\"${f.name}\"`).join(', ')\n        const alternativeHook = {\n          aroundAll: 'aroundEach',\n          beforeAll: 'beforeEach',\n          afterAll: 'afterEach',\n        }\n        const error = new FixtureDependencyError(\n          `Test-scoped fixtures cannot be used inside ${options.suiteHook} hook. `\n          + `The following fixtures are test-scoped: ${fixtureNames}. `\n          + `Use { scope: 'file' } or { scope: 'worker' } fixtures instead, or move the logic to ${alternativeHook[options.suiteHook]} hook.`,\n        )\n        // Use stack trace from hook registration for better error location\n        if (options.stackTraceError?.stack) {\n          error.stack = error.message + options.stackTraceError.stack.replace(options.stackTraceError.message, '')\n        }\n        throw error\n      }\n    }\n\n    if (!contextHasFixturesCache.has(context)) {\n      contextHasFixturesCache.set(context, new WeakSet())\n    }\n    const cachedFixtures = contextHasFixturesCache.get(context)!\n\n    for (const fixture of pendingFixtures) {\n      if (fixture.scope === 'test') {\n        // fixture could be already initialized during \"before\" hook\n        // we can't check \"fixture.name\" in context because context may\n        // access the parent fixture ({ a: ({ a }) => {} })\n        if (cachedFixtures.has(fixture)) {\n          continue\n        }\n        cachedFixtures.add(fixture)\n\n        const resolvedValue = await resolveTestFixtureValue(\n          fixture,\n          context,\n          cleanupFnArray,\n        )\n        context[fixture.name] = resolvedValue\n\n        cleanupFnArray.push(() => {\n          cachedFixtures.delete(fixture)\n        })\n      }\n      else {\n        const resolvedValue = await resolveScopeFixtureValue(\n          fixtures,\n          suite,\n          fixture,\n        )\n        context[fixture.name] = resolvedValue\n      }\n    }\n\n    return fn(context)\n  }\n}\n\nfunction isFixtureFunction(value: unknown): value is FixtureFn<any, any, any> {\n  return typeof value === 'function'\n}\n\nfunction resolveTestFixtureValue(\n  fixture: TestFixtureItem,\n  context: TestContext & { [key: string]: any },\n  cleanupFnArray: (() => void | Promise<void>)[],\n) {\n  if (!isFixtureFunction(fixture.value)) {\n    return fixture.value\n  }\n\n  return resolveFixtureFunction(\n    fixture.value,\n    fixture.name,\n    context,\n    cleanupFnArray,\n  )\n}\n\nconst scopedFixturePromiseCache = new WeakMap<TestFixtureItem, Promise<unknown>>()\n\nasync function resolveScopeFixtureValue(\n  fixtures: TestFixtures,\n  suite: Suite,\n  fixture: TestFixtureItem,\n) {\n  const workerContext = fixtures.getWorkerContext()\n  const fileContext = fixtures.getFileContext(suite.file)\n  const fixtureContext = fixture.scope === 'worker' ? workerContext : fileContext\n\n  if (!isFixtureFunction(fixture.value)) {\n    fixtureContext[fixture.name] = fixture.value\n    return fixture.value\n  }\n\n  if (fixture.name in fixtureContext) {\n    return fixtureContext[fixture.name]\n  }\n\n  if (scopedFixturePromiseCache.has(fixture)) {\n    return scopedFixturePromiseCache.get(fixture)!\n  }\n\n  if (!cleanupFnArrayMap.has(fixtureContext)) {\n    cleanupFnArrayMap.set(fixtureContext, [])\n  }\n  const cleanupFnFileArray = cleanupFnArrayMap.get(fixtureContext)!\n\n  const promise = resolveFixtureFunction(\n    fixture.value,\n    fixture.name,\n    fixture.scope === 'file' ? { ...workerContext, ...fileContext } : fixtureContext,\n    cleanupFnFileArray,\n  ).then((value) => {\n    fixtureContext[fixture.name] = value\n    scopedFixturePromiseCache.delete(fixture)\n    return value\n  })\n  scopedFixturePromiseCache.set(fixture, promise)\n  return promise\n}\n\nasync function resolveFixtureFunction(\n  fixtureFn: (\n    context: unknown,\n    useFn: (arg: unknown) => Promise<void>,\n  ) => Promise<void>,\n  fixtureName: string,\n  context: unknown,\n  cleanupFnArray: (() => void | Promise<void>)[],\n): Promise<unknown> {\n  // wait for `use` call to extract fixture value\n  const useFnArgPromise = createDefer()\n  const stackTraceError\n    = FIXTURE_STACK_TRACE_KEY in fixtureFn && fixtureFn[FIXTURE_STACK_TRACE_KEY] instanceof Error\n      ? fixtureFn[FIXTURE_STACK_TRACE_KEY]\n      : undefined\n  let isUseFnArgResolved = false\n\n  const fixtureReturn = fixtureFn(context, async (useFnArg: unknown) => {\n    // extract `use` argument\n    isUseFnArgResolved = true\n    useFnArgPromise.resolve(useFnArg)\n\n    // suspend fixture teardown by holding off `useReturnPromise` resolution until cleanup\n    const useReturnPromise = createDefer<void>()\n    cleanupFnArray.push(async () => {\n      // start teardown by resolving `use` Promise\n      useReturnPromise.resolve()\n      // wait for finishing teardown\n      await fixtureReturn\n    })\n    await useReturnPromise\n  }).then(() => {\n    // fixture returned without calling use()\n    if (!isUseFnArgResolved) {\n      const error = new Error(\n        `Fixture \"${fixtureName}\" returned without calling \"use\". Make sure to call \"use\" in every code path of the fixture function.`,\n      )\n      if (stackTraceError?.stack) {\n        error.stack = error.message + stackTraceError.stack.replace(stackTraceError.message, '')\n      }\n      useFnArgPromise.reject(error)\n    }\n  }).catch((e: unknown) => {\n    // treat fixture setup error as test failure\n    if (!isUseFnArgResolved) {\n      useFnArgPromise.reject(e)\n      return\n    }\n    // otherwise re-throw to avoid silencing error during cleanup\n    throw e\n  })\n\n  return useFnArgPromise\n}\n\nfunction resolveDeps(\n  usedFixtures: TestFixtureItem[],\n  registrations: FixtureRegistrations,\n  depSet = new Set<TestFixtureItem>(),\n  pendingFixtures: TestFixtureItem[] = [],\n) {\n  usedFixtures.forEach((fixture) => {\n    if (pendingFixtures.includes(fixture)) {\n      return\n    }\n    if (!isFixtureFunction(fixture.value) || !fixture.deps) {\n      pendingFixtures.push(fixture)\n      return\n    }\n    if (depSet.has(fixture)) {\n      if (fixture.parent) {\n        fixture = fixture.parent\n      }\n      else {\n        throw new Error(\n          `Circular fixture dependency detected: ${fixture.name} <- ${[...depSet]\n            .reverse()\n            .map(d => d.name)\n            .join(' <- ')}`,\n        )\n      }\n    }\n\n    depSet.add(fixture)\n    resolveDeps(\n      [...fixture.deps].map(n => n === fixture.name ? fixture.parent : registrations.get(n)).filter(n => !!n),\n      registrations,\n      depSet,\n      pendingFixtures,\n    )\n    pendingFixtures.push(fixture)\n    depSet.clear()\n  })\n\n  return pendingFixtures\n}\n\nfunction validateSuiteHook(fn: Function, hook: SuiteHook, suiteError: Error | undefined) {\n  const usedProps = getUsedProps(fn, { sourceError: suiteError, suiteHook: hook })\n  if (usedProps.size) {\n    const error = new FixtureAccessError(\n      `The ${hook} hook uses fixtures \"${[...usedProps].join('\", \"')}\", but has no access to context. `\n      + `Did you forget to call it as \"test.${hook}()\" instead of \"${hook}()\"?\\n`\n      + `If you used internal \"suite\" task as the first argument previously, access it in the second argument instead. `\n      + `See https://vitest.dev/guide/test-context#suite-level-hooks`,\n    )\n    if (suiteError) {\n      error.stack = suiteError.stack?.replace(suiteError.message, error.message)\n    }\n    throw error\n  }\n}\n\nconst kPropsSymbol = Symbol('$vitest:fixture-props')\nconst kPropNamesSymbol = Symbol('$vitest:fixture-prop-names')\n\ninterface FixturePropsOptions {\n  index?: number\n  original?: Function\n}\n\nexport function configureProps(fn: Function, options: FixturePropsOptions): void {\n  Object.defineProperty(fn, kPropsSymbol, {\n    value: options,\n    enumerable: false,\n  })\n}\n\nfunction memoProps(fn: Function, props: Set<string>): Set<string> {\n  (fn as any)[kPropNamesSymbol] = props\n  return props\n}\n\ninterface PropsParserOptions {\n  sourceError?: Error | undefined\n  suiteHook?: SuiteHook\n}\n\nfunction getUsedProps(fn: Function, { sourceError, suiteHook }: PropsParserOptions = {}): Set<string> {\n  if (kPropNamesSymbol in fn) {\n    return fn[kPropNamesSymbol] as Set<string>\n  }\n\n  const {\n    index: fixturesIndex = 0,\n    original: implementation = fn,\n  } = kPropsSymbol in fn ? fn[kPropsSymbol] as FixturePropsOptions : {}\n  let fnString = filterOutComments(implementation.toString())\n\n  // match lowered async function and strip it off\n  // example code on esbuild-try https://esbuild.github.io/try/#YgAwLjI0LjAALS1zdXBwb3J0ZWQ6YXN5bmMtYXdhaXQ9ZmFsc2UAZQBlbnRyeS50cwBjb25zdCBvID0gewogIGYxOiBhc3luYyAoKSA9PiB7fSwKICBmMjogYXN5bmMgKGEpID0+IHt9LAogIGYzOiBhc3luYyAoYSwgYikgPT4ge30sCiAgZjQ6IGFzeW5jIGZ1bmN0aW9uKGEpIHt9LAogIGY1OiBhc3luYyBmdW5jdGlvbiBmZihhKSB7fSwKICBhc3luYyBmNihhKSB7fSwKCiAgZzE6IGFzeW5jICgpID0+IHt9LAogIGcyOiBhc3luYyAoeyBhIH0pID0+IHt9LAogIGczOiBhc3luYyAoeyBhIH0sIGIpID0+IHt9LAogIGc0OiBhc3luYyBmdW5jdGlvbiAoeyBhIH0pIHt9LAogIGc1OiBhc3luYyBmdW5jdGlvbiBnZyh7IGEgfSkge30sCiAgYXN5bmMgZzYoeyBhIH0pIHt9LAoKICBoMTogYXN5bmMgKCkgPT4ge30sCiAgLy8gY29tbWVudCBiZXR3ZWVuCiAgaDI6IGFzeW5jIChhKSA9PiB7fSwKfQ\n  //   __async(this, null, function*\n  //   __async(this, arguments, function*\n  //   __async(this, [_0, _1], function*\n  if (/__async\\((?:this|null), (?:null|arguments|\\[[_0-9, ]*\\]), function\\*/.test(fnString)) {\n    fnString = fnString.split(/__async\\((?:this|null),/)[1]\n  }\n  const match = fnString.match(/[^(]*\\(([^)]*)/)\n  if (!match) {\n    return memoProps(fn, new Set())\n  }\n\n  const args = splitByComma(match[1])\n  if (!args.length) {\n    return memoProps(fn, new Set())\n  }\n\n  const fixturesArgument = args[fixturesIndex]\n\n  if (!fixturesArgument) {\n    return memoProps(fn, new Set())\n  }\n\n  if (!(fixturesArgument[0] === '{' && fixturesArgument.endsWith('}'))) {\n    const ordinalArgument = ordinal(fixturesIndex + 1)\n    const error = new FixtureParseError(\n      `The ${ordinalArgument} argument inside a fixture must use object destructuring pattern, e.g. ({ task } => {}). `\n      + `Instead, received \"${fixturesArgument}\".`\n      + `${(suiteHook ? ` If you used internal \"suite\" task as the ${ordinalArgument} argument previously, access it in the ${ordinal(fixturesIndex + 2)} argument instead.` : '')}`,\n    )\n    if (sourceError) {\n      error.stack = sourceError.stack?.replace(sourceError.message, error.message)\n    }\n    throw error\n  }\n\n  const _first = fixturesArgument.slice(1, -1).replace(/\\s/g, '')\n  const props = splitByComma(_first).map((prop) => {\n    return prop.replace(/:.*|=.*/g, '')\n  })\n\n  const last = props.at(-1)\n  if (last && last.startsWith('...')) {\n    const error = new FixtureParseError(\n      `Rest parameters are not supported in fixtures, received \"${last}\".`,\n    )\n    if (sourceError) {\n      error.stack = sourceError.stack?.replace(sourceError.message, error.message)\n    }\n    throw error\n  }\n\n  return memoProps(fn, new Set(props))\n}\n\nfunction splitByComma(s: string) {\n  const result = []\n  const stack = []\n  let start = 0\n  for (let i = 0; i < s.length; i++) {\n    if (s[i] === '{' || s[i] === '[') {\n      stack.push(s[i] === '{' ? '}' : ']')\n    }\n    else if (s[i] === stack.at(-1)) {\n      stack.pop()\n    }\n    else if (!stack.length && s[i] === ',') {\n      const token = s.substring(start, i).trim()\n      if (token) {\n        result.push(token)\n      }\n      start = i + 1\n    }\n  }\n  const lastToken = s.substring(start).trim()\n  if (lastToken) {\n    result.push(lastToken)\n  }\n  return result\n}\n"
  },
  {
    "path": "packages/runner/src/hooks.ts",
    "content": "import type { WithFixturesOptions } from './fixture'\nimport type {\n  AfterAllListener,\n  AfterEachListener,\n  AroundAllListener,\n  AroundEachListener,\n  BeforeAllListener,\n  BeforeEachListener,\n  File,\n  InternalChainableContext,\n  OnTestFailedHandler,\n  OnTestFinishedHandler,\n  RegisteredAroundAllListener,\n  Suite,\n  TaskHook,\n  TaskPopulated,\n  TestContext,\n} from './types/tasks'\nimport { assertTypes } from '@vitest/utils/helpers'\nimport { abortContextSignal, abortIfTimeout, withTimeout } from './context'\nimport { configureProps, withFixtures } from './fixture'\nimport { getCurrentSuite, getRunner } from './suite'\nimport { getCurrentTest } from './test-state'\nimport { getChainableContext } from './utils/chain'\n\nfunction getDefaultHookTimeout() {\n  return getRunner().config.hookTimeout\n}\n\nconst CLEANUP_TIMEOUT_KEY = Symbol.for('VITEST_CLEANUP_TIMEOUT')\nconst CLEANUP_STACK_TRACE_KEY = Symbol.for('VITEST_CLEANUP_STACK_TRACE')\nconst AROUND_TIMEOUT_KEY = Symbol.for('VITEST_AROUND_TIMEOUT')\nconst AROUND_STACK_TRACE_KEY = Symbol.for('VITEST_AROUND_STACK_TRACE')\n\nexport function getBeforeHookCleanupCallback(hook: Function, result: any, context?: TestContext): Function | undefined {\n  if (typeof result === 'function') {\n    const timeout\n      = CLEANUP_TIMEOUT_KEY in hook && typeof hook[CLEANUP_TIMEOUT_KEY] === 'number'\n        ? hook[CLEANUP_TIMEOUT_KEY]\n        : getDefaultHookTimeout()\n    const stackTraceError\n      = CLEANUP_STACK_TRACE_KEY in hook && hook[CLEANUP_STACK_TRACE_KEY] instanceof Error\n        ? hook[CLEANUP_STACK_TRACE_KEY]\n        : undefined\n    return withTimeout(\n      result,\n      timeout,\n      true,\n      stackTraceError,\n      (_, error) => {\n        if (context) {\n          abortContextSignal(context, error)\n        }\n      },\n    )\n  }\n}\n\n/**\n * Registers a callback function to be executed once before all tests within the current suite.\n * This hook is useful for scenarios where you need to perform setup operations that are common to all tests in a suite, such as initializing a database connection or setting up a test environment.\n *\n * **Note:** The `beforeAll` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file.\n *\n * @param {Function} fn - The callback function to be executed before all tests.\n * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.\n * @returns {void}\n * @example\n * ```ts\n * // Example of using beforeAll to set up a database connection\n * beforeAll(async () => {\n *   await database.connect();\n * });\n * ```\n */\nexport function beforeAll<ExtraContext = object>(\n  this: unknown,\n  fn: BeforeAllListener<ExtraContext>,\n  timeout: number = getDefaultHookTimeout(),\n): void {\n  assertTypes(fn, '\"beforeAll\" callback', ['function'])\n  const stackTraceError = new Error('STACK_TRACE_ERROR')\n  const context = getChainableContext(this)\n  return getCurrentSuite<ExtraContext>().on(\n    'beforeAll',\n    Object.assign(\n      withTimeout(\n        withSuiteFixtures('beforeAll', fn, context, stackTraceError),\n        timeout,\n        true,\n        stackTraceError,\n      ),\n      {\n        [CLEANUP_TIMEOUT_KEY]: timeout,\n        [CLEANUP_STACK_TRACE_KEY]: stackTraceError,\n      },\n    ),\n  )\n}\n\n/**\n * Registers a callback function to be executed once after all tests within the current suite have completed.\n * This hook is useful for scenarios where you need to perform cleanup operations after all tests in a suite have run, such as closing database connections or cleaning up temporary files.\n *\n * **Note:** The `afterAll` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.\n *\n * @param {Function} fn - The callback function to be executed after all tests.\n * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.\n * @returns {void}\n * @example\n * ```ts\n * // Example of using afterAll to close a database connection\n * afterAll(async () => {\n *   await database.disconnect();\n * });\n * ```\n */\nexport function afterAll<ExtraContext = object>(\n  this: unknown,\n  fn: AfterAllListener<ExtraContext>,\n  timeout?: number,\n): void {\n  assertTypes(fn, '\"afterAll\" callback', ['function'])\n  const context = getChainableContext(this)\n  const stackTraceError = new Error('STACK_TRACE_ERROR')\n  return getCurrentSuite<ExtraContext>().on(\n    'afterAll',\n    withTimeout(\n      withSuiteFixtures('afterAll', fn, context, stackTraceError),\n      timeout ?? getDefaultHookTimeout(),\n      true,\n      stackTraceError,\n    ),\n  )\n}\n\n/**\n * Registers a callback function to be executed before each test within the current suite.\n * This hook is useful for scenarios where you need to reset or reinitialize the test environment before each test runs, such as resetting database states, clearing caches, or reinitializing variables.\n *\n * **Note:** The `beforeEach` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file.\n *\n * @param {Function} fn - The callback function to be executed before each test. This function receives an `TestContext` parameter if additional test context is needed.\n * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.\n * @returns {void}\n * @example\n * ```ts\n * // Example of using beforeEach to reset a database state\n * beforeEach(async () => {\n *   await database.reset();\n * });\n * ```\n */\nexport function beforeEach<ExtraContext = object>(\n  fn: BeforeEachListener<ExtraContext>,\n  timeout: number = getDefaultHookTimeout(),\n): void {\n  assertTypes(fn, '\"beforeEach\" callback', ['function'])\n  const stackTraceError = new Error('STACK_TRACE_ERROR')\n\n  const wrapper: BeforeEachListener<ExtraContext> = (context, suite) => {\n    const fixtureResolver = withFixtures(fn, { suite })\n    return fixtureResolver(context)\n  }\n\n  return getCurrentSuite<ExtraContext>().on(\n    'beforeEach',\n    Object.assign(\n      withTimeout(\n        wrapper,\n        timeout ?? getDefaultHookTimeout(),\n        true,\n        stackTraceError,\n        abortIfTimeout,\n      ),\n      {\n        [CLEANUP_TIMEOUT_KEY]: timeout,\n        [CLEANUP_STACK_TRACE_KEY]: stackTraceError,\n      },\n    ),\n  )\n}\n\n/**\n * Registers a callback function to be executed after each test within the current suite has completed.\n * This hook is useful for scenarios where you need to clean up or reset the test environment after each test runs, such as deleting temporary files, clearing test-specific database entries, or resetting mocked functions.\n *\n * **Note:** The `afterEach` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.\n *\n * @param {Function} fn - The callback function to be executed after each test. This function receives an `TestContext` parameter if additional test context is needed.\n * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.\n * @returns {void}\n * @example\n * ```ts\n * // Example of using afterEach to delete temporary files created during a test\n * afterEach(async () => {\n *   await fileSystem.deleteTempFiles();\n * });\n * ```\n */\nexport function afterEach<ExtraContext = object>(\n  fn: AfterEachListener<ExtraContext>,\n  timeout?: number,\n): void {\n  assertTypes(fn, '\"afterEach\" callback', ['function'])\n  const wrapper: AfterEachListener<ExtraContext> = (context, suite) => {\n    const fixtureResolver = withFixtures(fn, { suite })\n    return fixtureResolver(context)\n  }\n\n  return getCurrentSuite<ExtraContext>().on(\n    'afterEach',\n    withTimeout(\n      wrapper,\n      timeout ?? getDefaultHookTimeout(),\n      true,\n      new Error('STACK_TRACE_ERROR'),\n      abortIfTimeout,\n    ),\n  )\n}\n\n/**\n * Registers a callback function to be executed when a test fails within the current suite.\n * This function allows for custom actions to be performed in response to test failures, such as logging, cleanup, or additional diagnostics.\n *\n * **Note:** The `onTestFailed` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.\n *\n * @param {Function} fn - The callback function to be executed upon a test failure. The function receives the test result (including errors).\n * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.\n * @throws {Error} Throws an error if the function is not called within a test.\n * @returns {void}\n * @example\n * ```ts\n * // Example of using onTestFailed to log failure details\n * onTestFailed(({ errors }) => {\n *   console.log(`Test failed: ${test.name}`, errors);\n * });\n * ```\n */\nexport const onTestFailed: TaskHook<OnTestFailedHandler> = createTestHook(\n  'onTestFailed',\n  (test, handler, timeout) => {\n    test.onFailed ||= []\n    test.onFailed.push(\n      withTimeout(\n        handler,\n        timeout ?? getDefaultHookTimeout(),\n        true,\n        new Error('STACK_TRACE_ERROR'),\n        abortIfTimeout,\n      ),\n    )\n  },\n)\n\n/**\n * Registers a callback function to be executed when the current test finishes, regardless of the outcome (pass or fail).\n * This function is ideal for performing actions that should occur after every test execution, such as cleanup, logging, or resetting shared resources.\n *\n * This hook is useful if you have access to a resource in the test itself and you want to clean it up after the test finishes. It is a more compact way to clean up resources than using the combination of `beforeEach` and `afterEach`.\n *\n * **Note:** The `onTestFinished` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.\n *\n * **Note:** The `onTestFinished` hook is not called if the test is canceled with a dynamic `ctx.skip()` call.\n *\n * @param {Function} fn - The callback function to be executed after a test finishes. The function can receive parameters providing details about the completed test, including its success or failure status.\n * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.\n * @throws {Error} Throws an error if the function is not called within a test.\n * @returns {void}\n * @example\n * ```ts\n * // Example of using onTestFinished for cleanup\n * const db = await connectToDatabase();\n * onTestFinished(async () => {\n *   await db.disconnect();\n * });\n * ```\n */\nexport const onTestFinished: TaskHook<OnTestFinishedHandler> = createTestHook(\n  'onTestFinished',\n  (test, handler, timeout) => {\n    test.onFinished ||= []\n    test.onFinished.push(\n      withTimeout(\n        handler,\n        timeout ?? getDefaultHookTimeout(),\n        true,\n        new Error('STACK_TRACE_ERROR'),\n        abortIfTimeout,\n      ),\n    )\n  },\n)\n\n/**\n * Registers a callback function that wraps around all tests within the current suite.\n * The callback receives a `runSuite` function that must be called to run the suite's tests.\n * This hook is useful for scenarios where you need to wrap an entire suite in a context\n * (e.g., starting a server, opening a database connection that all tests share).\n *\n * **Note:** When multiple `aroundAll` hooks are registered, they are nested inside each other.\n * The first registered hook is the outermost wrapper.\n *\n * @param {Function} fn - The callback function that wraps the suite. Must call `runSuite()` to run the tests.\n * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.\n * @returns {void}\n * @example\n * ```ts\n * // Example of using aroundAll to wrap suite in a tracing span\n * aroundAll(async (runSuite) => {\n *   await tracer.trace('test-suite', runSuite);\n * });\n * ```\n * @example\n * ```ts\n * // Example of using aroundAll with fixtures\n * aroundAll(async (runSuite, { db }) => {\n *   await db.transaction(() => runSuite());\n * });\n * ```\n */\nexport function aroundAll<ExtraContext = object>(\n  this: unknown,\n  fn: AroundAllListener<ExtraContext>,\n  timeout?: number,\n): void {\n  assertTypes(fn, '\"aroundAll\" callback', ['function'])\n  const stackTraceError = new Error('STACK_TRACE_ERROR')\n  const resolvedTimeout = timeout ?? getDefaultHookTimeout()\n  const context = getChainableContext(this)\n\n  return getCurrentSuite().on(\n    'aroundAll',\n    Object.assign(\n      withSuiteFixtures(\n        'aroundAll',\n        fn,\n        context,\n        stackTraceError,\n        1,\n      ) as RegisteredAroundAllListener,\n      {\n        [AROUND_TIMEOUT_KEY]: resolvedTimeout,\n        [AROUND_STACK_TRACE_KEY]: stackTraceError,\n      },\n    ),\n  )\n}\n\n/**\n * Registers a callback function that wraps around each test within the current suite.\n * The callback receives a `runTest` function that must be called to run the test.\n * This hook is useful for scenarios where you need to wrap tests in a context (e.g., database transactions).\n *\n * **Note:** When multiple `aroundEach` hooks are registered, they are nested inside each other.\n * The first registered hook is the outermost wrapper.\n *\n * @param {Function} fn - The callback function that wraps the test. Must call `runTest()` to run the test.\n * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.\n * @returns {void}\n * @example\n * ```ts\n * // Example of using aroundEach to wrap tests in a database transaction\n * aroundEach(async (runTest) => {\n *   await database.transaction(() => runTest());\n * });\n * ```\n * @example\n * ```ts\n * // Example of using aroundEach with fixtures\n * aroundEach(async (runTest, { db }) => {\n *   await db.transaction(() => runTest());\n * });\n * ```\n */\nexport function aroundEach<ExtraContext = object>(\n  fn: AroundEachListener<ExtraContext>,\n  timeout?: number,\n): void {\n  assertTypes(fn, '\"aroundEach\" callback', ['function'])\n  const stackTraceError = new Error('STACK_TRACE_ERROR')\n  const resolvedTimeout = timeout ?? getDefaultHookTimeout()\n\n  const wrapper: AroundEachListener<ExtraContext> = (runTest, context, suite) => {\n    const innerFn = (ctx: any) => fn(runTest, ctx, suite)\n    configureProps(innerFn, { index: 1, original: fn })\n\n    const fixtureResolver = withFixtures(innerFn, { suite })\n    return fixtureResolver(context)\n  }\n\n  return getCurrentSuite<ExtraContext>().on(\n    'aroundEach',\n    Object.assign(\n      wrapper,\n      {\n        [AROUND_TIMEOUT_KEY]: resolvedTimeout,\n        [AROUND_STACK_TRACE_KEY]: stackTraceError,\n      },\n    ),\n  )\n}\n\nfunction withSuiteFixtures(\n  suiteHook: WithFixturesOptions['suiteHook'],\n  fn: Function,\n  context: InternalChainableContext | undefined,\n  stackTraceError: Error,\n  contextIndex = 0,\n) {\n  return (...args: any[]) => {\n    const suite = args.at(-1) as Suite | File\n    const prefix = args.slice(0, -1) // this is potential \"runSuite\"\n\n    const wrapper = (ctx: any) => fn(...prefix, ctx, suite)\n    configureProps(wrapper, { index: contextIndex, original: fn })\n\n    const fixtures = context?.getFixtures()\n    const fileContext = fixtures?.getFileContext(suite.file)\n\n    const fixtured = withFixtures(wrapper, {\n      suiteHook,\n      fixtures,\n      context: fileContext,\n      stackTraceError,\n    })\n    return fixtured()\n  }\n}\n\nexport function getAroundHookTimeout(hook: Function): number {\n  return AROUND_TIMEOUT_KEY in hook && typeof hook[AROUND_TIMEOUT_KEY] === 'number'\n    ? hook[AROUND_TIMEOUT_KEY]\n    : getDefaultHookTimeout()\n}\n\nexport function getAroundHookStackTrace(hook: Function): Error | undefined {\n  return AROUND_STACK_TRACE_KEY in hook && hook[AROUND_STACK_TRACE_KEY] instanceof Error\n    ? hook[AROUND_STACK_TRACE_KEY]\n    : undefined\n}\n\nfunction createTestHook<T>(\n  name: string,\n  handler: (test: TaskPopulated, handler: T, timeout?: number) => void,\n): TaskHook<T> {\n  return (fn: T, timeout?: number) => {\n    assertTypes(fn, `\"${name}\" callback`, ['function'])\n\n    const current = getCurrentTest()\n\n    if (!current) {\n      throw new Error(`Hook ${name}() can only be called inside a test`)\n    }\n\n    return handler(current, fn, timeout)\n  }\n}\n"
  },
  {
    "path": "packages/runner/src/index.ts",
    "content": "export { recordArtifact } from './artifact'\nexport {\n  afterAll,\n  afterEach,\n  aroundAll,\n  aroundEach,\n  beforeAll,\n  beforeEach,\n  onTestFailed,\n  onTestFinished,\n} from './hooks'\nexport { getFn, getHooks, setFn, setHooks } from './map'\nexport { collectTests, startTests, updateTask } from './run'\nexport {\n  createTaskCollector,\n  describe,\n  getCurrentSuite,\n  it,\n  suite,\n  test,\n} from './suite'\nexport { getCurrentTest } from './test-state'\nexport type * from './types'\n"
  },
  {
    "path": "packages/runner/src/map.ts",
    "content": "import type { Awaitable } from '@vitest/utils'\nimport type { TestFixtures } from './fixture'\nimport type { Suite, SuiteHooks, Test, TestContext } from './types/tasks'\n\n// use WeakMap here to make the Test and Suite object serializable\nconst fnMap = new WeakMap()\nconst testFixtureMap = new WeakMap()\nconst hooksMap = new WeakMap()\n\nexport function setFn(key: Test, fn: () => Awaitable<void>): void {\n  fnMap.set(key, fn)\n}\n\nexport function getFn<Task = Test>(key: Task): () => Awaitable<void> {\n  return fnMap.get(key as any)\n}\n\nexport function setTestFixture(\n  key: TestContext,\n  fixture: TestFixtures,\n): void {\n  testFixtureMap.set(key, fixture)\n}\n\nexport function getTestFixtures<Context = TestContext>(key: Context): TestFixtures {\n  return testFixtureMap.get(key as any)\n}\n\nexport function setHooks(key: Suite, hooks: SuiteHooks): void {\n  hooksMap.set(key, hooks)\n}\n\nexport function getHooks(key: Suite): SuiteHooks {\n  return hooksMap.get(key)\n}\n"
  },
  {
    "path": "packages/runner/src/run.ts",
    "content": "import type { Awaitable, TestError } from '@vitest/utils'\nimport type { DiffOptions } from '@vitest/utils/diff'\nimport type { FileSpecification, VitestRunner } from './types/runner'\nimport type {\n  AroundEachListener,\n  File,\n  RegisteredAroundAllListener,\n  SequenceHooks,\n  Suite,\n  SuiteHooks,\n  Task,\n  TaskMeta,\n  TaskResult,\n  TaskResultPack,\n  TaskState,\n  TaskUpdateEvent,\n  Test,\n  TestContext,\n  WriteableTestContext,\n} from './types/tasks'\nimport type { ConcurrencyLimiter } from './utils/limit-concurrency'\nimport { processError } from '@vitest/utils/error' // TODO: load dynamically\nimport { shuffle } from '@vitest/utils/helpers'\nimport { getSafeTimers } from '@vitest/utils/timers'\nimport { collectTests } from './collect'\nimport { abortContextSignal } from './context'\nimport { AroundHookMultipleCallsError, AroundHookSetupError, AroundHookTeardownError, PendingError, TestRunAbortError } from './errors'\nimport { callFixtureCleanup, callFixtureCleanupFrom, getFixtureCleanupCount, TestFixtures } from './fixture'\nimport { getAroundHookStackTrace, getAroundHookTimeout, getBeforeHookCleanupCallback } from './hooks'\nimport { getFn, getHooks } from './map'\nimport { addRunningTest, getRunningTests, setCurrentTest } from './test-state'\nimport { limitConcurrency } from './utils/limit-concurrency'\nimport { partitionSuiteChildren } from './utils/suite'\nimport { hasFailed, hasTests } from './utils/tasks'\n\nconst now = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now\nconst unixNow = Date.now\nconst { clearTimeout, setTimeout } = getSafeTimers()\nlet limitMaxConcurrency: ConcurrencyLimiter\n\n/**\n * Normalizes retry configuration to extract individual values.\n * Handles both number and object forms.\n */\nfunction getRetryCount(retry: number | { count?: number } | undefined): number {\n  if (retry === undefined) {\n    return 0\n  }\n  if (typeof retry === 'number') {\n    return retry\n  }\n  return retry.count ?? 0\n}\n\nfunction getRetryDelay(retry: number | { delay?: number } | undefined): number {\n  if (retry === undefined) {\n    return 0\n  }\n  if (typeof retry === 'number') {\n    return 0\n  }\n  return retry.delay ?? 0\n}\n\nfunction getRetryCondition(\n  retry: number | { condition?: RegExp | ((error: TestError) => boolean) } | undefined,\n): RegExp | ((error: TestError) => boolean) | undefined {\n  if (retry === undefined) {\n    return undefined\n  }\n  if (typeof retry === 'number') {\n    return undefined\n  }\n  return retry.condition\n}\n\nfunction updateSuiteHookState(\n  task: Task,\n  name: keyof SuiteHooks,\n  state: TaskState,\n  runner: VitestRunner,\n) {\n  if (!task.result) {\n    task.result = { state: 'run' }\n  }\n  if (!task.result.hooks) {\n    task.result.hooks = {}\n  }\n  const suiteHooks = task.result.hooks\n  if (suiteHooks) {\n    suiteHooks[name] = state\n\n    let event: TaskUpdateEvent = state === 'run' ? 'before-hook-start' : 'before-hook-end'\n\n    if (name === 'afterAll' || name === 'afterEach') {\n      event = state === 'run' ? 'after-hook-start' : 'after-hook-end'\n    }\n\n    updateTask(\n      event,\n      task,\n      runner,\n    )\n  }\n}\n\nfunction getSuiteHooks(\n  suite: Suite,\n  name: keyof SuiteHooks,\n  sequence: SequenceHooks,\n) {\n  const hooks = getHooks(suite)[name]\n  if (sequence === 'stack' && (name === 'afterAll' || name === 'afterEach')) {\n    return hooks.slice().reverse()\n  }\n  return hooks\n}\n\nasync function callTestHooks(\n  runner: VitestRunner,\n  test: Test,\n  hooks: ((context: TestContext) => Awaitable<void>)[],\n  sequence: SequenceHooks,\n) {\n  if (sequence === 'stack') {\n    hooks = hooks.slice().reverse()\n  }\n\n  if (!hooks.length) {\n    return\n  }\n\n  const context = test.context as WriteableTestContext\n\n  const onTestFailed = test.context.onTestFailed\n  const onTestFinished = test.context.onTestFinished\n  context.onTestFailed = () => {\n    throw new Error(`Cannot call \"onTestFailed\" inside a test hook.`)\n  }\n  context.onTestFinished = () => {\n    throw new Error(`Cannot call \"onTestFinished\" inside a test hook.`)\n  }\n\n  if (sequence === 'parallel') {\n    try {\n      await Promise.all(hooks.map(fn => limitMaxConcurrency(() => fn(test.context))))\n    }\n    catch (e) {\n      failTask(test.result!, e, runner.config.diffOptions)\n    }\n  }\n  else {\n    for (const fn of hooks) {\n      try {\n        await limitMaxConcurrency(() => fn(test.context))\n      }\n      catch (e) {\n        failTask(test.result!, e, runner.config.diffOptions)\n      }\n    }\n  }\n\n  context.onTestFailed = onTestFailed\n  context.onTestFinished = onTestFinished\n}\n\nexport async function callSuiteHook<T extends keyof SuiteHooks>(\n  suite: Suite,\n  currentTask: Task,\n  name: T,\n  runner: VitestRunner,\n  args: SuiteHooks[T][0] extends (...args: infer A) => Awaitable<any> ? A : never,\n): Promise<unknown[]> {\n  const sequence = runner.config.sequence.hooks\n\n  const callbacks: unknown[] = []\n  // stop at file level\n  const parentSuite: Suite | null = 'filepath' in suite ? null : suite.suite || suite.file\n\n  if (name === 'beforeEach' && parentSuite) {\n    callbacks.push(\n      ...(await callSuiteHook(parentSuite, currentTask, name, runner, args)),\n    )\n  }\n\n  const hooks = getSuiteHooks(suite, name, sequence)\n\n  if (hooks.length > 0) {\n    updateSuiteHookState(currentTask, name, 'run', runner)\n  }\n\n  async function runHook(hook: Function) {\n    return limitMaxConcurrency(async () => {\n      return getBeforeHookCleanupCallback(\n        hook,\n        await hook(...args),\n        name === 'beforeEach' ? args[0] as TestContext : undefined,\n      )\n    })\n  }\n\n  if (sequence === 'parallel') {\n    callbacks.push(\n      ...(await Promise.all(hooks.map(hook => runHook(hook)))),\n    )\n  }\n  else {\n    for (const hook of hooks) {\n      callbacks.push(await runHook(hook))\n    }\n  }\n\n  if (hooks.length > 0) {\n    updateSuiteHookState(currentTask, name, 'pass', runner)\n  }\n\n  if (name === 'afterEach' && parentSuite) {\n    callbacks.push(\n      ...(await callSuiteHook(parentSuite, currentTask, name, runner, args)),\n    )\n  }\n\n  return callbacks\n}\n\nfunction getAroundEachHooks(suite: Suite): AroundEachListener[] {\n  const hooks: AroundEachListener[] = []\n  const parentSuite: Suite | null = 'filepath' in suite ? null : suite.suite || suite.file\n  if (parentSuite) {\n    hooks.push(...getAroundEachHooks(parentSuite))\n  }\n  hooks.push(...getHooks(suite).aroundEach)\n  return hooks\n}\n\nfunction getAroundAllHooks(suite: Suite): RegisteredAroundAllListener[] {\n  return getHooks(suite).aroundAll\n}\n\ninterface AroundHooksOptions<THook extends Function> {\n  hooks: THook[]\n  hookName: 'aroundEach' | 'aroundAll'\n  callbackName: 'runTest()' | 'runSuite()'\n  onTimeout?: (error: Error) => void\n  invokeHook: (hook: THook, use: () => Promise<void>) => Awaitable<unknown>\n}\n\nfunction makeAroundHookTimeoutError(\n  hookName: string,\n  phase: 'setup' | 'teardown',\n  timeout: number,\n  stackTraceError?: Error,\n) {\n  const message = `The ${phase} phase of \"${hookName}\" hook timed out after ${timeout}ms.`\n  const ErrorClass = phase === 'setup' ? AroundHookSetupError : AroundHookTeardownError\n  const error = new ErrorClass(message)\n  if (stackTraceError?.stack) {\n    error.stack = stackTraceError.stack.replace(stackTraceError.message, error.message)\n  }\n  return error\n}\n\nasync function callAroundHooks<THook extends Function>(\n  runInner: () => Promise<void>,\n  options: AroundHooksOptions<THook>,\n): Promise<void> {\n  const { hooks, hookName, callbackName, onTimeout, invokeHook } = options\n\n  if (!hooks.length) {\n    await runInner()\n    return\n  }\n\n  const hookErrors: unknown[] = []\n\n  const createTimeoutPromise = (\n    timeout: number,\n    phase: 'setup' | 'teardown',\n    stackTraceError: Error | undefined,\n  ): { promise: Promise<never>; isTimedOut: () => boolean; clear: () => void } => {\n    let timer: ReturnType<typeof setTimeout> | undefined\n    let timedout = false\n\n    const promise = new Promise<never>((_, reject) => {\n      if (timeout > 0 && timeout !== Number.POSITIVE_INFINITY) {\n        timer = setTimeout(() => {\n          timedout = true\n          const error = makeAroundHookTimeoutError(hookName, phase, timeout, stackTraceError)\n          onTimeout?.(error)\n          reject(error)\n        }, timeout)\n        timer.unref?.()\n      }\n    })\n\n    const clear = () => {\n      if (timer) {\n        clearTimeout(timer)\n        timer = undefined\n      }\n    }\n\n    return { promise, clear, isTimedOut: () => timedout }\n  }\n\n  const runNextHook = async (index: number): Promise<void> => {\n    if (index >= hooks.length) {\n      return runInner()\n    }\n\n    const hook = hooks[index]\n    const timeout = getAroundHookTimeout(hook)\n    const stackTraceError = getAroundHookStackTrace(hook)\n\n    let useCalled = false\n    let setupTimeout: ReturnType<typeof createTimeoutPromise>\n    let teardownTimeout: ReturnType<typeof createTimeoutPromise> | undefined\n    let setupLimitConcurrencyRelease: (() => void) | undefined\n    let teardownLimitConcurrencyRelease: (() => void) | undefined\n\n    // Promise that resolves when use() is called (setup phase complete)\n    let resolveUseCalled!: () => void\n    const useCalledPromise = new Promise<void>((resolve) => {\n      resolveUseCalled = resolve\n    })\n\n    // Promise that resolves when use() returns (inner hooks complete, teardown phase starts)\n    let resolveUseReturned!: () => void\n    const useReturnedPromise = new Promise<void>((resolve) => {\n      resolveUseReturned = resolve\n    })\n\n    // Promise that resolves when hook completes\n    let resolveHookComplete!: () => void\n    let rejectHookComplete!: (error: Error) => void\n    const hookCompletePromise = new Promise<void>((resolve, reject) => {\n      resolveHookComplete = resolve\n      rejectHookComplete = reject\n    })\n\n    const use = async () => {\n      // shouldn't continue to next (runTest/Suite or inner aroundEach/All) when aroundEach/All setup timed out.\n      if (setupTimeout.isTimedOut()) {\n        // we can throw any error to bail out.\n        // this error is not seen by end users since `runNextHook` already rejected with timeout error\n        // and this error is caught by `rejectHookComplete`.\n        throw new Error('__VITEST_INTERNAL_AROUND_HOOK_ABORT__')\n      }\n\n      if (useCalled) {\n        throw new AroundHookMultipleCallsError(\n          `The \\`${callbackName}\\` callback was called multiple times in the \\`${hookName}\\` hook. `\n          + `The callback can only be called once per hook.`,\n        )\n      }\n      useCalled = true\n      resolveUseCalled()\n\n      // Setup phase completed - clear setup timer\n      setupTimeout.clear()\n      setupLimitConcurrencyRelease?.()\n\n      // Run inner hooks - don't time this against our teardown timeout\n      await runNextHook(index + 1).catch(e => hookErrors.push(e))\n\n      teardownLimitConcurrencyRelease = await limitMaxConcurrency.acquire()\n\n      // Start teardown timer after inner hooks complete - only times this hook's teardown code\n      teardownTimeout = createTimeoutPromise(timeout, 'teardown', stackTraceError)\n\n      // Signal that use() is returning (teardown phase starting)\n      resolveUseReturned()\n    }\n\n    setupLimitConcurrencyRelease = await limitMaxConcurrency.acquire()\n\n    // Start setup timeout\n    setupTimeout = createTimeoutPromise(timeout, 'setup', stackTraceError)\n\n    // Run the hook in the background\n    ;(async () => {\n      try {\n        await invokeHook(hook, use)\n        if (!useCalled) {\n          throw new AroundHookSetupError(\n            `The \\`${callbackName}\\` callback was not called in the \\`${hookName}\\` hook. `\n            + `Make sure to call \\`${callbackName}\\` to run the ${hookName === 'aroundEach' ? 'test' : 'suite'}.`,\n          )\n        }\n        resolveHookComplete()\n      }\n      catch (error) {\n        rejectHookComplete(error as Error)\n      }\n      finally {\n        setupLimitConcurrencyRelease?.()\n        teardownLimitConcurrencyRelease?.()\n      }\n    })()\n\n    // Wait for either: use() to be called OR hook to complete (error) OR setup timeout\n    try {\n      await Promise.race([\n        useCalledPromise,\n        hookCompletePromise,\n        setupTimeout.promise,\n      ])\n    }\n    finally {\n      setupLimitConcurrencyRelease?.()\n      setupTimeout.clear()\n    }\n\n    // Wait for use() to return (inner hooks complete) OR hook to complete (error during inner hooks)\n    await Promise.race([\n      useReturnedPromise,\n      hookCompletePromise,\n    ])\n\n    // Now teardownTimeout is guaranteed to be set\n    // Wait for hook to complete (teardown) OR teardown timeout\n    try {\n      await Promise.race([\n        hookCompletePromise,\n        teardownTimeout?.promise,\n      ])\n    }\n    finally {\n      teardownLimitConcurrencyRelease?.()\n      teardownTimeout?.clear()\n    }\n  }\n\n  await runNextHook(0).catch(e => hookErrors.push(e))\n\n  if (hookErrors.length > 0) {\n    throw hookErrors\n  }\n}\n\nasync function callAroundAllHooks(\n  suite: Suite,\n  runSuiteInner: () => Promise<void>,\n): Promise<void> {\n  await callAroundHooks(runSuiteInner, {\n    hooks: getAroundAllHooks(suite),\n    hookName: 'aroundAll',\n    callbackName: 'runSuite()',\n    invokeHook: (hook, use) => hook(use, suite),\n  })\n}\n\nasync function callAroundEachHooks(\n  suite: Suite,\n  test: Test,\n  runTest: (fixtureCheckpoint: number) => Promise<void>,\n): Promise<void> {\n  await callAroundHooks(\n    // Take checkpoint right before runTest - at this point all aroundEach fixtures\n    // have been resolved, so we can correctly identify which fixtures belong to\n    // aroundEach (before checkpoint) vs inside runTest (after checkpoint)\n    () => runTest(getFixtureCleanupCount(test.context)),\n    {\n      hooks: getAroundEachHooks(suite),\n      hookName: 'aroundEach',\n      callbackName: 'runTest()',\n      onTimeout: error => abortContextSignal(test.context, error),\n      invokeHook: (hook, use) => hook(use, test.context, suite),\n    },\n  )\n}\n\nconst packs = new Map<string, [TaskResult | undefined, TaskMeta]>()\nconst eventsPacks: [string, TaskUpdateEvent, undefined][] = []\nconst pendingTasksUpdates: Promise<void>[] = []\n\nfunction sendTasksUpdate(runner: VitestRunner): void {\n  if (packs.size) {\n    const taskPacks = Array.from(packs).map<TaskResultPack>(([id, task]) => {\n      return [id, task[0], task[1]]\n    })\n    const p = runner.onTaskUpdate?.(taskPacks, eventsPacks)\n    if (p) {\n      pendingTasksUpdates.push(p)\n      // remove successful promise to not grow array indefnitely,\n      // but keep rejections so finishSendTasksUpdate can handle them\n      p.then(\n        () => pendingTasksUpdates.splice(pendingTasksUpdates.indexOf(p), 1),\n        () => {},\n      )\n    }\n    eventsPacks.length = 0\n    packs.clear()\n  }\n}\n\nexport async function finishSendTasksUpdate(runner: VitestRunner): Promise<void> {\n  sendTasksUpdate(runner)\n  await Promise.all(pendingTasksUpdates)\n}\n\nfunction throttle<T extends (...args: any[]) => void>(fn: T, ms: number): T {\n  let last = 0\n  let pendingCall: ReturnType<typeof setTimeout> | undefined\n\n  return function call(this: any, ...args: any[]) {\n    const now = unixNow()\n    if (now - last > ms) {\n      last = now\n\n      clearTimeout(pendingCall)\n      pendingCall = undefined\n\n      return fn.apply(this, args)\n    }\n\n    // Make sure fn is still called even if there are no further calls\n    pendingCall ??= setTimeout(() => call.bind(this)(...args), ms)\n  } as any\n}\n\n// throttle based on summary reporter's DURATION_UPDATE_INTERVAL_MS\nconst sendTasksUpdateThrottled = throttle(sendTasksUpdate, 100)\n\nexport function updateTask(event: TaskUpdateEvent, task: Task, runner: VitestRunner): void {\n  eventsPacks.push([task.id, event, undefined])\n  packs.set(task.id, [task.result, task.meta])\n  sendTasksUpdateThrottled(runner)\n}\n\nasync function callCleanupHooks(runner: VitestRunner, cleanups: unknown[]) {\n  const sequence = runner.config.sequence.hooks\n\n  if (sequence === 'stack') {\n    cleanups = cleanups.slice().reverse()\n  }\n\n  if (sequence === 'parallel') {\n    await Promise.all(\n      cleanups.map(async (fn) => {\n        if (typeof fn !== 'function') {\n          return\n        }\n        await limitMaxConcurrency(() => fn())\n      }),\n    )\n  }\n  else {\n    for (const fn of cleanups) {\n      if (typeof fn !== 'function') {\n        continue\n      }\n      await limitMaxConcurrency(() => fn())\n    }\n  }\n}\n\n/**\n * Determines if a test should be retried based on its retryCondition configuration\n */\nfunction passesRetryCondition(test: Test, errors: TestError[] | undefined): boolean {\n  const condition = getRetryCondition(test.retry)\n\n  if (!errors || errors.length === 0) {\n    return false\n  }\n\n  if (!condition) {\n    return true\n  }\n\n  const error = errors[errors.length - 1]\n\n  if (condition instanceof RegExp) {\n    return condition.test(error.message || '')\n  }\n  else if (typeof condition === 'function') {\n    return condition(error)\n  }\n\n  return false\n}\n\nexport async function runTest(test: Test, runner: VitestRunner): Promise<void> {\n  await runner.onBeforeRunTask?.(test)\n\n  if (test.mode !== 'run' && test.mode !== 'queued') {\n    updateTask('test-prepare', test, runner)\n    updateTask('test-finished', test, runner)\n    return\n  }\n\n  if (test.result?.state === 'fail') {\n    // should not be possible to get here, I think this is just copy pasted from suite\n    // TODO: maybe someone fails tests in `beforeAll` hooks?\n    // https://github.com/vitest-dev/vitest/pull/7069\n    updateTask('test-failed-early', test, runner)\n    return\n  }\n\n  const start = now()\n\n  test.result = {\n    state: 'run',\n    startTime: unixNow(),\n    retryCount: 0,\n  }\n  updateTask('test-prepare', test, runner)\n\n  const cleanupRunningTest = addRunningTest(test)\n  setCurrentTest(test)\n\n  const suite = test.suite || test.file\n  const $ = runner.trace!\n\n  const repeats = test.repeats ?? 0\n  for (let repeatCount = 0; repeatCount <= repeats; repeatCount++) {\n    const retry = getRetryCount(test.retry)\n    for (let retryCount = 0; retryCount <= retry; retryCount++) {\n      let beforeEachCleanups: unknown[] = []\n      // fixtureCheckpoint is passed by callAroundEachHooks - it represents the count\n      // of fixture cleanup functions AFTER all aroundEach fixtures have been resolved\n      // but BEFORE the test runs. This allows us to clean up only fixtures created\n      // inside runTest while preserving aroundEach fixtures for teardown.\n      await callAroundEachHooks(suite, test, async (fixtureCheckpoint) => {\n        try {\n          await runner.onBeforeTryTask?.(test, {\n            retry: retryCount,\n            repeats: repeatCount,\n          })\n\n          test.result!.repeatCount = repeatCount\n\n          beforeEachCleanups = await $('test.beforeEach', () => callSuiteHook(\n            suite,\n            test,\n            'beforeEach',\n            runner,\n            [test.context, suite],\n          ))\n\n          if (runner.runTask) {\n            await $('test.callback', () => limitMaxConcurrency(() => runner.runTask!(test)))\n          }\n          else {\n            const fn = getFn(test)\n            if (!fn) {\n              throw new Error(\n                'Test function is not found. Did you add it using `setFn`?',\n              )\n            }\n            await $('test.callback', () => limitMaxConcurrency(() => fn()))\n          }\n\n          await runner.onAfterTryTask?.(test, {\n            retry: retryCount,\n            repeats: repeatCount,\n          })\n\n          if (test.result!.state !== 'fail') {\n            test.result!.state = 'pass'\n          }\n        }\n        catch (e) {\n          failTask(test.result!, e, runner.config.diffOptions)\n        }\n\n        try {\n          await runner.onTaskFinished?.(test)\n        }\n        catch (e) {\n          failTask(test.result!, e, runner.config.diffOptions)\n        }\n\n        try {\n          await $('test.afterEach', () => callSuiteHook(suite, test, 'afterEach', runner, [\n            test.context,\n            suite,\n          ]))\n          if (beforeEachCleanups.length) {\n            await $('test.cleanup', () => callCleanupHooks(runner, beforeEachCleanups))\n          }\n          // Only clean up fixtures created inside runTest (after the checkpoint)\n          // Fixtures created for aroundEach will be cleaned up after aroundEach teardown\n          await callFixtureCleanupFrom(test.context, fixtureCheckpoint)\n        }\n        catch (e) {\n          failTask(test.result!, e, runner.config.diffOptions)\n        }\n\n        if (test.onFinished?.length) {\n          await $('test.onFinished', () => callTestHooks(runner, test, test.onFinished!, 'stack'))\n        }\n\n        if (test.result!.state === 'fail' && test.onFailed?.length) {\n          await $('test.onFailed', () => callTestHooks(\n            runner,\n            test,\n            test.onFailed!,\n            runner.config.sequence.hooks,\n          ))\n        }\n\n        test.onFailed = undefined\n        test.onFinished = undefined\n\n        await runner.onAfterRetryTask?.(test, {\n          retry: retryCount,\n          repeats: repeatCount,\n        })\n      }).catch((error) => {\n        failTask(test.result!, error, runner.config.diffOptions)\n      })\n\n      // Clean up fixtures that were created for aroundEach (before the checkpoint)\n      // This runs after aroundEach teardown has completed\n      try {\n        await callFixtureCleanup(test.context)\n      }\n      catch (e) {\n        failTask(test.result!, e, runner.config.diffOptions)\n      }\n\n      // skipped with new PendingError\n      if (test.result?.pending || test.result?.state === 'skip') {\n        test.mode = 'skip'\n        test.result = {\n          state: 'skip',\n          note: test.result?.note,\n          pending: true,\n          duration: now() - start,\n        }\n        updateTask('test-finished', test, runner)\n        setCurrentTest(undefined)\n        cleanupRunningTest()\n        return\n      }\n\n      if (test.result.state === 'pass') {\n        break\n      }\n\n      if (retryCount < retry) {\n        const shouldRetry = passesRetryCondition(test, test.result.errors)\n\n        if (!shouldRetry) {\n          break\n        }\n\n        test.result.state = 'run'\n        test.result.retryCount = (test.result.retryCount ?? 0) + 1\n\n        const delay = getRetryDelay(test.retry)\n        if (delay > 0) {\n          await new Promise(resolve => setTimeout(resolve, delay))\n        }\n      }\n\n      // update retry info\n      updateTask('test-retried', test, runner)\n    }\n  }\n\n  // if test is marked to be failed, flip the result\n  if (test.fails) {\n    if (test.result.state === 'pass') {\n      const error = processError(new Error('Expect test to fail'))\n      test.result.state = 'fail'\n      test.result.errors = [error]\n    }\n    else {\n      test.result.state = 'pass'\n      test.result.errors = undefined\n    }\n  }\n\n  cleanupRunningTest()\n  setCurrentTest(undefined)\n\n  test.result.duration = now() - start\n\n  await runner.onAfterRunTask?.(test)\n\n  updateTask('test-finished', test, runner)\n}\n\nfunction failTask(result: TaskResult, err: unknown, diffOptions: DiffOptions | undefined) {\n  if (err instanceof PendingError) {\n    result.state = 'skip'\n    result.note = err.note\n    result.pending = true\n    return\n  }\n\n  if (err instanceof TestRunAbortError) {\n    result.state = 'skip'\n    result.note = err.message\n    return\n  }\n\n  result.state = 'fail'\n  const errors = Array.isArray(err) ? err : [err]\n  for (const e of errors) {\n    const errors = e instanceof AggregateError\n      ? e.errors.map(e => processError(e, diffOptions))\n      : [processError(e, diffOptions)]\n    result.errors ??= []\n    result.errors.push(...errors)\n  }\n}\n\nfunction markTasksAsSkipped(suite: Suite, runner: VitestRunner) {\n  suite.tasks.forEach((t) => {\n    t.mode = 'skip'\n    t.result = { ...t.result, state: 'skip' }\n    updateTask('test-finished', t, runner)\n    if (t.type === 'suite') {\n      markTasksAsSkipped(t, runner)\n    }\n  })\n}\n\nfunction markPendingTasksAsSkipped(suite: Suite, runner: VitestRunner, note?: string) {\n  suite.tasks.forEach((t) => {\n    if (!t.result || t.result.state === 'run') {\n      t.mode = 'skip'\n      t.result = { ...t.result, state: 'skip', note }\n      updateTask('test-cancel', t, runner)\n    }\n\n    if (t.type === 'suite') {\n      markPendingTasksAsSkipped(t, runner, note)\n    }\n  })\n}\n\nexport async function runSuite(suite: Suite, runner: VitestRunner): Promise<void> {\n  await runner.onBeforeRunSuite?.(suite)\n\n  if (suite.result?.state === 'fail') {\n    markTasksAsSkipped(suite, runner)\n    // failed during collection\n    updateTask('suite-failed-early', suite, runner)\n    return\n  }\n\n  const start = now()\n\n  const mode = suite.mode\n\n  suite.result = {\n    state: mode === 'skip' || mode === 'todo' ? mode : 'run',\n    startTime: unixNow(),\n  }\n  const $ = runner.trace!\n\n  updateTask('suite-prepare', suite, runner)\n\n  let beforeAllCleanups: unknown[] = []\n\n  if (suite.mode === 'skip') {\n    suite.result.state = 'skip'\n\n    updateTask('suite-finished', suite, runner)\n  }\n  else if (suite.mode === 'todo') {\n    suite.result.state = 'todo'\n\n    updateTask('suite-finished', suite, runner)\n  }\n  else {\n    let suiteRan = false\n\n    try {\n      await callAroundAllHooks(suite, async () => {\n        suiteRan = true\n        try {\n          // beforeAll\n          try {\n            beforeAllCleanups = await $('suite.beforeAll', () => callSuiteHook(\n              suite,\n              suite,\n              'beforeAll',\n              runner,\n              [suite],\n            ))\n          }\n          catch (e) {\n            failTask(suite.result!, e, runner.config.diffOptions)\n            markTasksAsSkipped(suite, runner)\n            return\n          }\n\n          // run suite children\n          if (runner.runSuite) {\n            await runner.runSuite(suite)\n          }\n          else {\n            for (let tasksGroup of partitionSuiteChildren(suite)) {\n              if (tasksGroup[0].concurrent === true) {\n                await Promise.all(tasksGroup.map(c => runSuiteChild(c, runner)))\n              }\n              else {\n                const { sequence } = runner.config\n                if (suite.shuffle) {\n                  // run describe block independently from tests\n                  const suites = tasksGroup.filter(\n                    group => group.type === 'suite',\n                  )\n                  const tests = tasksGroup.filter(group => group.type === 'test')\n                  const groups = shuffle<Task[]>([suites, tests], sequence.seed)\n                  tasksGroup = groups.flatMap(group =>\n                    shuffle(group, sequence.seed),\n                  )\n                }\n                for (const c of tasksGroup) {\n                  await runSuiteChild(c, runner)\n                }\n              }\n            }\n          }\n        }\n        finally {\n          // afterAll runs even if beforeAll or suite children fail\n          try {\n            await $('suite.afterAll', () => callSuiteHook(suite, suite, 'afterAll', runner, [suite]))\n            if (beforeAllCleanups.length) {\n              await $('suite.cleanup', () => callCleanupHooks(runner, beforeAllCleanups))\n            }\n            if (suite.file === suite) {\n              const contexts = TestFixtures.getFileContexts(suite.file)\n              await Promise.all(contexts.map(context => callFixtureCleanup(context)))\n            }\n          }\n          catch (e) {\n            failTask(suite.result!, e, runner.config.diffOptions)\n          }\n        }\n      })\n    }\n    catch (e) {\n      // mark tasks as skipped if aroundAll failed before the suite callback was executed\n      if (!suiteRan) {\n        markTasksAsSkipped(suite, runner)\n      }\n      failTask(suite.result!, e, runner.config.diffOptions)\n    }\n\n    if (suite.mode === 'run' || suite.mode === 'queued') {\n      if (!runner.config.passWithNoTests && !hasTests(suite)) {\n        suite.result.state = 'fail'\n        if (!suite.result.errors?.length) {\n          const error = processError(\n            new Error(`No test found in suite ${suite.name}`),\n          )\n          suite.result.errors = [error]\n        }\n      }\n      else if (hasFailed(suite)) {\n        suite.result.state = 'fail'\n      }\n      else {\n        suite.result.state = 'pass'\n      }\n    }\n\n    suite.result.duration = now() - start\n\n    await runner.onAfterRunSuite?.(suite)\n\n    updateTask('suite-finished', suite, runner)\n  }\n}\n\nasync function runSuiteChild(c: Task, runner: VitestRunner) {\n  const $ = runner.trace!\n  if (c.type === 'test') {\n    return $(\n      'run.test',\n      {\n        'vitest.test.id': c.id,\n        'vitest.test.name': c.name,\n        'vitest.test.mode': c.mode,\n        'vitest.test.timeout': c.timeout,\n        'code.file.path': c.file.filepath,\n        'code.line.number': c.location?.line,\n        'code.column.number': c.location?.column,\n      },\n      () => runTest(c, runner),\n    )\n  }\n  else if (c.type === 'suite') {\n    return $(\n      'run.suite',\n      {\n        'vitest.suite.id': c.id,\n        'vitest.suite.name': c.name,\n        'vitest.suite.mode': c.mode,\n        'code.file.path': c.file.filepath,\n        'code.line.number': c.location?.line,\n        'code.column.number': c.location?.column,\n      },\n      () => runSuite(c, runner),\n    )\n  }\n}\n\nexport async function runFiles(files: File[], runner: VitestRunner): Promise<void> {\n  limitMaxConcurrency ??= limitConcurrency(runner.config.maxConcurrency)\n\n  for (const file of files) {\n    if (!file.tasks.length && !runner.config.passWithNoTests) {\n      if (!file.result?.errors?.length) {\n        const error = processError(\n          new Error(`No test suite found in file ${file.filepath}`),\n        )\n        file.result = {\n          state: 'fail',\n          errors: [error],\n        }\n      }\n    }\n    await runner.trace!(\n      'run.spec',\n      {\n        'code.file.path': file.filepath,\n        'vitest.suite.tasks.length': file.tasks.length,\n      },\n      () => runSuite(file, runner),\n    )\n  }\n}\n\nconst workerRunners = new WeakSet<VitestRunner>()\n\nfunction defaultTrace<T>(_: string, attributes: any, cb?: () => T): T {\n  if (typeof attributes === 'function') {\n    return attributes() as T\n  }\n  return cb!()\n}\n\nexport async function startTests(specs: string[] | FileSpecification[], runner: VitestRunner): Promise<File[]> {\n  runner.trace ??= defaultTrace\n  const cancel = runner.cancel?.bind(runner)\n  // Ideally, we need to have an event listener for this, but only have a runner here.\n  // Adding another onCancel felt wrong (maybe it needs to be refactored)\n  runner.cancel = (reason) => {\n    // We intentionally create only one error since there is only one test run that can be cancelled\n    const error = new TestRunAbortError('The test run was aborted by the user.', reason)\n    getRunningTests().forEach((test) => {\n      abortContextSignal(test.context, error)\n      markPendingTasksAsSkipped(test.file, runner, error.message)\n    },\n    )\n    return cancel?.(reason)\n  }\n\n  if (!workerRunners.has(runner)) {\n    runner.onCleanupWorkerContext?.(async () => {\n      await Promise.all(\n        [...TestFixtures.getWorkerContexts()].map(context => callFixtureCleanup(context)),\n      ).finally(() => {\n        TestFixtures.clearDefinitions()\n      })\n    })\n    workerRunners.add(runner)\n  }\n\n  try {\n    const paths = specs.map(f => typeof f === 'string' ? f : f.filepath)\n    await runner.onBeforeCollect?.(paths)\n\n    const files = await collectTests(specs, runner)\n\n    await runner.onCollected?.(files)\n    await runner.onBeforeRunFiles?.(files)\n\n    await runFiles(files, runner)\n\n    await runner.onAfterRunFiles?.(files)\n\n    await finishSendTasksUpdate(runner)\n\n    return files\n  }\n  finally {\n    runner.cancel = cancel\n  }\n}\n\nasync function publicCollect(specs: string[] | FileSpecification[], runner: VitestRunner): Promise<File[]> {\n  runner.trace ??= defaultTrace\n\n  const paths = specs.map(f => typeof f === 'string' ? f : f.filepath)\n\n  await runner.onBeforeCollect?.(paths)\n\n  const files = await collectTests(specs, runner)\n\n  await runner.onCollected?.(files)\n  return files\n}\n\nexport { publicCollect as collectTests }\n"
  },
  {
    "path": "packages/runner/src/setup.ts",
    "content": "import type { VitestRunner, VitestRunnerConfig } from './types/runner'\n\nexport async function runSetupFiles(\n  config: VitestRunnerConfig,\n  files: string[],\n  runner: VitestRunner,\n): Promise<void> {\n  if (config.sequence.setupFiles === 'parallel') {\n    await Promise.all(\n      files.map(async (fsPath) => {\n        await runner.importFile(fsPath, 'setup')\n      }),\n    )\n  }\n  else {\n    for (const fsPath of files) {\n      await runner.importFile(fsPath, 'setup')\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runner/src/suite.ts",
    "content": "import type { UserFixtures } from './fixture'\nimport type { VitestRunner } from './types/runner'\nimport type {\n  File,\n  InternalTestContext,\n  RunMode,\n  Suite,\n  SuiteAPI,\n  SuiteCollector,\n  SuiteFactory,\n  SuiteHooks,\n  SuiteOptions,\n  Task,\n  TaskCustomOptions,\n  TaskPopulated,\n  Test,\n  TestAPI,\n  TestFunction,\n  TestOptions,\n} from './types/tasks'\nimport { format, formatRegExp, objDisplay } from '@vitest/utils/display'\nimport {\n  isNegativeNaN,\n  isObject,\n  objectAttr,\n  toArray,\n  unique,\n} from '@vitest/utils/helpers'\nimport {\n  abortIfTimeout,\n  collectorContext,\n  collectTask,\n  createTestContext,\n  runWithSuite,\n  withCancel,\n  withTimeout,\n} from './context'\nimport { configureProps, TestFixtures, withFixtures } from './fixture'\nimport { afterAll, afterEach, aroundAll, aroundEach, beforeAll, beforeEach } from './hooks'\nimport { getHooks, setFn, setHooks, setTestFixture } from './map'\nimport { getCurrentTest } from './test-state'\nimport { findTestFileStackTrace } from './utils'\nimport { createChainable, getChainableContext } from './utils/chain'\nimport { createNoTagsError, validateTags } from './utils/tags'\nimport { createTaskName } from './utils/tasks'\n\n/**\n * Creates a suite of tests, allowing for grouping and hierarchical organization of tests.\n * Suites can contain both tests and other suites, enabling complex test structures.\n *\n * @param {string} name - The name of the suite, used for identification and reporting.\n * @param {Function} fn - A function that defines the tests and suites within this suite.\n * @example\n * ```ts\n * // Define a suite with two tests\n * suite('Math operations', () => {\n *   test('should add two numbers', () => {\n *     expect(add(1, 2)).toBe(3);\n *   });\n *\n *   test('should subtract two numbers', () => {\n *     expect(subtract(5, 2)).toBe(3);\n *   });\n * });\n * ```\n * @example\n * ```ts\n * // Define nested suites\n * suite('String operations', () => {\n *   suite('Trimming', () => {\n *     test('should trim whitespace from start and end', () => {\n *       expect('  hello  '.trim()).toBe('hello');\n *     });\n *   });\n *\n *   suite('Concatenation', () => {\n *     test('should concatenate two strings', () => {\n *       expect('hello' + ' ' + 'world').toBe('hello world');\n *     });\n *   });\n * });\n * ```\n */\nexport const suite: SuiteAPI = createSuite()\n/**\n * Defines a test case with a given name and test function. The test function can optionally be configured with test options.\n *\n * @param {string | Function} name - The name of the test or a function that will be used as a test name.\n * @param {TestOptions | TestFunction} [optionsOrFn] - Optional. The test options or the test function if no explicit name is provided.\n * @param {number | TestOptions | TestFunction} [optionsOrTest] - Optional. The test function or options, depending on the previous parameters.\n * @throws {Error} If called inside another test function.\n * @example\n * ```ts\n * // Define a simple test\n * test('should add two numbers', () => {\n *   expect(add(1, 2)).toBe(3);\n * });\n * ```\n * @example\n * ```ts\n * // Define a test with options\n * test('should subtract two numbers', { retry: 3 }, () => {\n *   expect(subtract(5, 2)).toBe(3);\n * });\n * ```\n */\nexport const test: TestAPI = createTest(function (\n  name: string | Function,\n  optionsOrFn?: TestOptions | TestFunction,\n  optionsOrTest?: number | TestOptions | TestFunction,\n) {\n  if (getCurrentTest()) {\n    throw new Error(\n      'Calling the test function inside another test function is not allowed. Please put it inside \"describe\" or \"suite\" so it can be properly collected.',\n    )\n  }\n\n  getCurrentSuite().test.fn.call(\n    this,\n    formatName(name),\n    optionsOrFn as TestOptions,\n    optionsOrTest as TestFunction,\n  )\n})\n\n/**\n * Creates a suite of tests, allowing for grouping and hierarchical organization of tests.\n * Suites can contain both tests and other suites, enabling complex test structures.\n *\n * @param {string} name - The name of the suite, used for identification and reporting.\n * @param {Function} fn - A function that defines the tests and suites within this suite.\n * @example\n * ```ts\n * // Define a suite with two tests\n * describe('Math operations', () => {\n *   test('should add two numbers', () => {\n *     expect(add(1, 2)).toBe(3);\n *   });\n *\n *   test('should subtract two numbers', () => {\n *     expect(subtract(5, 2)).toBe(3);\n *   });\n * });\n * ```\n * @example\n * ```ts\n * // Define nested suites\n * describe('String operations', () => {\n *   describe('Trimming', () => {\n *     test('should trim whitespace from start and end', () => {\n *       expect('  hello  '.trim()).toBe('hello');\n *     });\n *   });\n *\n *   describe('Concatenation', () => {\n *     test('should concatenate two strings', () => {\n *       expect('hello' + ' ' + 'world').toBe('hello world');\n *     });\n *   });\n * });\n * ```\n */\nexport const describe: SuiteAPI = suite\n/**\n * Defines a test case with a given name and test function. The test function can optionally be configured with test options.\n *\n * @param {string | Function} name - The name of the test or a function that will be used as a test name.\n * @param {TestOptions | TestFunction} [optionsOrFn] - Optional. The test options or the test function if no explicit name is provided.\n * @param {number | TestOptions | TestFunction} [optionsOrTest] - Optional. The test function or options, depending on the previous parameters.\n * @throws {Error} If called inside another test function.\n * @example\n * ```ts\n * // Define a simple test\n * it('adds two numbers', () => {\n *   expect(add(1, 2)).toBe(3);\n * });\n * ```\n * @example\n * ```ts\n * // Define a test with options\n * it('subtracts two numbers', { retry: 3 }, () => {\n *   expect(subtract(5, 2)).toBe(3);\n * });\n * ```\n */\nexport const it: TestAPI = test\n\nlet runner: VitestRunner\nlet defaultSuite: SuiteCollector\nlet currentTestFilepath: string\n\nfunction assert(condition: any, message: string) {\n  if (!condition) {\n    throw new Error(\n      `Vitest failed to find ${message}. One of the following is possible:`\n      + '\\n- \"vitest\" is imported directly without running \"vitest\" command'\n      + '\\n- \"vitest\" is imported inside \"globalSetup\" (to fix this, use \"setupFiles\" instead, because \"globalSetup\" runs in a different context)'\n      + '\\n- \"vitest\" is imported inside Vite / Vitest config file'\n      + '\\n- Otherwise, it might be a Vitest bug. Please report it to https://github.com/vitest-dev/vitest/issues\\n',\n    )\n  }\n}\n\nexport function getDefaultSuite(): SuiteCollector<object> {\n  assert(defaultSuite, 'the default suite')\n  return defaultSuite\n}\n\nexport function getTestFilepath(): string {\n  return currentTestFilepath\n}\n\nexport function getRunner(): VitestRunner {\n  assert(runner, 'the runner')\n  return runner\n}\n\nfunction createDefaultSuite(runner: VitestRunner) {\n  const config = runner.config.sequence\n  const options: SuiteOptions = {}\n  if (config.concurrent != null) {\n    options.concurrent = config.concurrent\n  }\n  const collector = suite('', options, () => {})\n  // no parent suite for top-level tests\n  delete collector.suite\n  return collector\n}\n\nexport function clearCollectorContext(\n  file: File,\n  currentRunner: VitestRunner,\n): void {\n  currentTestFilepath = file.filepath\n  runner = currentRunner\n  if (!defaultSuite) {\n    defaultSuite = createDefaultSuite(currentRunner)\n  }\n  defaultSuite.file = file\n  collectorContext.tasks.length = 0\n  defaultSuite.clear()\n  collectorContext.currentSuite = defaultSuite\n}\n\nexport function getCurrentSuite<ExtraContext = object>(): SuiteCollector<ExtraContext> {\n  const currentSuite = (collectorContext.currentSuite\n    || defaultSuite) as unknown as SuiteCollector<ExtraContext>\n  assert(currentSuite, 'the current suite')\n  return currentSuite\n}\n\nexport function createSuiteHooks(): SuiteHooks {\n  return {\n    beforeAll: [],\n    afterAll: [],\n    beforeEach: [],\n    afterEach: [],\n    aroundEach: [],\n    aroundAll: [],\n  }\n}\n\nconst POSITIVE_INFINITY = Number.POSITIVE_INFINITY\n\nfunction parseArguments<T extends (...args: any[]) => any>(\n  optionsOrFn: T | object | undefined,\n  timeoutOrTest: T | number | undefined,\n) {\n  if (timeoutOrTest != null && typeof timeoutOrTest === 'object') {\n    throw new TypeError(`Signature \"test(name, fn, { ... })\" was deprecated in Vitest 3 and removed in Vitest 4. Please, provide options as a second argument instead.`)\n  }\n\n  let options: TestOptions = {}\n  let fn: T | undefined\n\n  // it('', () => {}, 1000)\n  if (typeof timeoutOrTest === 'number') {\n    options = { timeout: timeoutOrTest }\n  }\n  // it('', { retry: 2 }, () => {})\n  else if (typeof optionsOrFn === 'object') {\n    options = optionsOrFn\n  }\n\n  if (typeof optionsOrFn === 'function') {\n    if (typeof timeoutOrTest === 'function') {\n      throw new TypeError(\n        'Cannot use two functions as arguments. Please use the second argument for options.',\n      )\n    }\n    fn = optionsOrFn as T\n  }\n  else if (typeof timeoutOrTest === 'function') {\n    fn = timeoutOrTest as T\n  }\n\n  return {\n    options,\n    handler: fn,\n  }\n}\n\n// implementations\nfunction createSuiteCollector(\n  name: string,\n  factory: SuiteFactory = () => {},\n  mode: RunMode,\n  each?: boolean,\n  suiteOptions?: SuiteOptions,\n) {\n  const tasks: (Test | Suite | SuiteCollector)[] = []\n\n  let suite!: Suite\n  initSuite(true)\n\n  const task = function (name = '', options: TaskCustomOptions = {}) {\n    const currentSuite = collectorContext.currentSuite?.suite\n    const parentTask = currentSuite ?? collectorContext.currentSuite?.file\n    const parentTags = parentTask?.tags || []\n    const testTags = unique([...parentTags, ...toArray(options.tags)])\n    const tagsOptions = testTags\n      .map((tag) => {\n        const tagDefinition = runner.config.tags?.find(t => t.name === tag)\n        if (!tagDefinition && runner.config.strictTags) {\n          throw createNoTagsError(runner.config.tags, tag)\n        }\n        return tagDefinition\n      })\n      .filter(r => r != null)\n      // higher priority should be last, run 1, 2, 3, ... etc\n      .sort((tag1, tag2) => (tag2.priority ?? POSITIVE_INFINITY) - (tag1.priority ?? POSITIVE_INFINITY))\n      .reduce((acc, tag) => {\n        const { name, description, priority, meta, ...options } = tag\n        Object.assign(acc, options)\n        if (meta) {\n          acc.meta = Object.assign(acc.meta ?? Object.create(null), meta)\n        }\n        return acc\n      }, {} as TestOptions)\n\n    const testOwnMeta = options.meta\n    options = {\n      ...tagsOptions,\n      ...options,\n    }\n    const timeout = options.timeout ?? runner.config.testTimeout\n    const parentMeta = currentSuite?.meta\n    const tagMeta = tagsOptions.meta\n    const testMeta = Object.create(null)\n    if (tagMeta) {\n      Object.assign(testMeta, tagMeta)\n    }\n    if (parentMeta) {\n      Object.assign(testMeta, parentMeta)\n    }\n    if (testOwnMeta) {\n      Object.assign(testMeta, testOwnMeta)\n    }\n    const task: Test = {\n      id: '',\n      name,\n      fullName: createTaskName([\n        currentSuite?.fullName ?? collectorContext.currentSuite?.file?.fullName,\n        name,\n      ]),\n      fullTestName: createTaskName([currentSuite?.fullTestName, name]),\n      suite: currentSuite,\n      each: options.each,\n      fails: options.fails,\n      context: undefined!,\n      type: 'test',\n      file: (currentSuite?.file ?? collectorContext.currentSuite?.file)!,\n      timeout,\n      retry: options.retry ?? runner.config.retry,\n      repeats: options.repeats,\n      mode: options.only\n        ? 'only'\n        : options.skip\n          ? 'skip'\n          : options.todo\n            ? 'todo'\n            : 'run',\n      meta: testMeta,\n      annotations: [],\n      artifacts: [],\n      tags: testTags,\n    }\n    const handler = options.handler\n    if (task.mode === 'run' && !handler) {\n      task.mode = 'todo'\n    }\n    if (\n      options.concurrent\n      || (!options.sequential && runner.config.sequence.concurrent)\n    ) {\n      task.concurrent = true\n    }\n    task.shuffle = suiteOptions?.shuffle\n    const context = createTestContext(task, runner)\n    // create test context\n    Object.defineProperty(task, 'context', {\n      value: context,\n      enumerable: false,\n    })\n    setTestFixture(context, options.fixtures ?? new TestFixtures())\n\n    const limit = Error.stackTraceLimit\n    Error.stackTraceLimit = 10\n    const stackTraceError = new Error('STACK_TRACE_ERROR')\n    Error.stackTraceLimit = limit\n\n    if (handler) {\n      setFn(\n        task,\n        withTimeout(\n          withCancel(withAwaitAsyncAssertions(withFixtures(handler, { context }), task), task.context.signal),\n          timeout,\n          false,\n          stackTraceError,\n          (_, error) => abortIfTimeout([context], error),\n        ),\n      )\n    }\n\n    if (runner.config.includeTaskLocation) {\n      const error = stackTraceError.stack!\n      const stack = findTestFileStackTrace(currentTestFilepath, error)\n      if (stack) {\n        task.location = {\n          line: stack.line,\n          column: stack.column,\n        }\n      }\n    }\n\n    tasks.push(task)\n    return task\n  }\n\n  const test = createTest(function (\n    name: string | Function,\n    optionsOrFn?: TestOptions | TestFunction,\n    timeoutOrTest?: number | TestFunction,\n  ) {\n    let { options, handler } = parseArguments(optionsOrFn, timeoutOrTest)\n\n    // inherit repeats, retry, timeout from suite\n    if (typeof suiteOptions === 'object') {\n      options = Object.assign({}, suiteOptions, options)\n    }\n\n    // inherit concurrent / sequential from suite\n    const concurrent = this.concurrent ?? (!this.sequential && options?.concurrent)\n    if (options.concurrent != null && concurrent != null) {\n      options.concurrent = concurrent\n    }\n\n    const sequential = this.sequential ?? (!this.concurrent && options?.sequential)\n    if (options.sequential != null && sequential != null) {\n      options.sequential = sequential\n    }\n\n    const test = task(formatName(name), {\n      ...this,\n      ...options,\n      handler,\n    }) as unknown as Test\n\n    test.type = 'test'\n  })\n\n  const collector: SuiteCollector = {\n    type: 'collector',\n    name,\n    mode,\n    suite,\n    options: suiteOptions,\n    test,\n    file: suite.file,\n    tasks,\n    collect,\n    task,\n    clear,\n    on: addHook,\n  }\n\n  function addHook<T extends keyof SuiteHooks>(name: T, ...fn: SuiteHooks[T]) {\n    getHooks(suite)[name].push(...(fn as any))\n  }\n\n  function initSuite(includeLocation: boolean) {\n    if (typeof suiteOptions === 'number') {\n      suiteOptions = { timeout: suiteOptions }\n    }\n\n    const currentSuite = collectorContext.currentSuite?.suite\n    const parentTask = currentSuite ?? collectorContext.currentSuite?.file\n    const suiteTags = toArray(suiteOptions?.tags)\n    validateTags(runner.config, suiteTags)\n\n    suite = {\n      id: '',\n      type: 'suite',\n      name,\n      fullName: createTaskName([\n        currentSuite?.fullName ?? collectorContext.currentSuite?.file?.fullName,\n        name,\n      ]),\n      fullTestName: createTaskName([currentSuite?.fullTestName, name]),\n      suite: currentSuite,\n      mode,\n      each,\n      file: (currentSuite?.file ?? collectorContext.currentSuite?.file)!,\n      shuffle: suiteOptions?.shuffle,\n      tasks: [],\n      meta: suiteOptions?.meta ?? Object.create(null),\n      concurrent: suiteOptions?.concurrent,\n      tags: unique([...parentTask?.tags || [], ...suiteTags]),\n    }\n\n    if (runner && includeLocation && runner.config.includeTaskLocation) {\n      const limit = Error.stackTraceLimit\n      Error.stackTraceLimit = 15\n      const error = new Error('stacktrace').stack!\n      Error.stackTraceLimit = limit\n      const stack = findTestFileStackTrace(currentTestFilepath, error)\n      if (stack) {\n        suite.location = {\n          line: stack.line,\n          column: stack.column,\n        }\n      }\n    }\n\n    setHooks(suite, createSuiteHooks())\n  }\n\n  function clear() {\n    tasks.length = 0\n    initSuite(false)\n  }\n\n  async function collect(file: File) {\n    if (!file) {\n      throw new TypeError('File is required to collect tasks.')\n    }\n\n    if (factory) {\n      await runWithSuite(collector, () => factory(test))\n    }\n\n    const allChildren: Task[] = []\n\n    for (const i of tasks) {\n      allChildren.push(i.type === 'collector' ? await i.collect(file) : i)\n    }\n\n    suite.tasks = allChildren\n\n    return suite\n  }\n\n  collectTask(collector)\n  return collector\n}\n\nfunction withAwaitAsyncAssertions<T extends (...args: any[]) => any>(fn: T, task: TaskPopulated): T {\n  return (async (...args: any[]) => {\n    const fnResult = await fn(...args)\n    // some async expect will be added to this array, in case user forget to await them\n    if (task.promises) {\n      const result = await Promise.allSettled(task.promises)\n      const errors = result\n        .map(r => (r.status === 'rejected' ? r.reason : undefined))\n        .filter(Boolean)\n      if (errors.length) {\n        throw errors\n      }\n    }\n    return fnResult\n  }) as T\n}\n\nfunction createSuite() {\n  function suiteFn(\n    this: Record<string, boolean | undefined>,\n    name: string | Function,\n    factoryOrOptions?: SuiteFactory | SuiteOptions,\n    optionsOrFactory?: number | SuiteFactory,\n  ) {\n    if (getCurrentTest()) {\n      throw new Error(\n        'Calling the suite function inside test function is not allowed. It can be only called at the top level or inside another suite function.',\n      )\n    }\n\n    const currentSuite: SuiteCollector | undefined = collectorContext.currentSuite || defaultSuite\n\n    let { options, handler: factory } = parseArguments(\n      factoryOrOptions,\n      optionsOrFactory,\n    ) as { options: SuiteOptions; handler: SuiteFactory | undefined }\n\n    const isConcurrentSpecified = options.concurrent || this.concurrent || options.sequential === false\n    const isSequentialSpecified = options.sequential || this.sequential || options.concurrent === false\n\n    const { meta: parentMeta, ...parentOptions } = currentSuite?.options || {}\n    // inherit options from current suite\n    options = {\n      ...parentOptions,\n      ...options,\n    }\n\n    const shuffle = this.shuffle ?? options.shuffle ?? currentSuite?.options?.shuffle ?? runner?.config.sequence.shuffle\n    if (shuffle != null) {\n      options.shuffle = shuffle\n    }\n\n    let mode: RunMode = (this.only ?? options.only)\n      ? 'only'\n      : (this.skip ?? options.skip)\n          ? 'skip'\n          : (this.todo ?? options.todo)\n              ? 'todo'\n              : 'run'\n\n    // passed as test(name), assume it's a \"todo\"\n    if (mode === 'run' && !factory) {\n      mode = 'todo'\n    }\n\n    // inherit concurrent / sequential from suite\n    const isConcurrent = isConcurrentSpecified || (options.concurrent && !isSequentialSpecified)\n    const isSequential = isSequentialSpecified || (options.sequential && !isConcurrentSpecified)\n    if (isConcurrent != null) {\n      options.concurrent = isConcurrent && !isSequential\n    }\n    if (isSequential != null) {\n      options.sequential = isSequential && !isConcurrent\n    }\n\n    if (parentMeta) {\n      options.meta = Object.assign(Object.create(null), parentMeta, options.meta)\n    }\n\n    return createSuiteCollector(\n      formatName(name),\n      factory,\n      mode,\n      this.each,\n      options,\n    )\n  }\n\n  suiteFn.each = function <T>(\n    this: SuiteAPI,\n    cases: ReadonlyArray<T>,\n    ...args: any[]\n  ) {\n    const context = getChainableContext(this)\n    const suite = context.withContext()\n    context.setContext('each', true)\n\n    if (Array.isArray(cases) && args.length) {\n      cases = formatTemplateString(cases, args)\n    }\n\n    return (\n      name: string | Function,\n      optionsOrFn: ((...args: T[]) => void) | TestOptions,\n      fnOrOptions?: ((...args: T[]) => void) | number,\n    ) => {\n      const _name = formatName(name)\n      const arrayOnlyCases = cases.every(Array.isArray)\n\n      const { options, handler } = parseArguments(optionsOrFn, fnOrOptions)\n\n      const fnFirst = typeof optionsOrFn === 'function'\n\n      cases.forEach((i, idx) => {\n        const items = Array.isArray(i) ? i : [i]\n        if (fnFirst) {\n          if (arrayOnlyCases) {\n            suite(\n              formatTitle(_name, items, idx),\n              handler ? () => handler(...items) : undefined,\n              options.timeout,\n            )\n          }\n          else {\n            suite(formatTitle(_name, items, idx), handler ? () => handler(i) : undefined, options.timeout)\n          }\n        }\n        else {\n          if (arrayOnlyCases) {\n            suite(formatTitle(_name, items, idx), options, handler ? () => handler(...items) : undefined)\n          }\n          else {\n            suite(formatTitle(_name, items, idx), options, handler ? () => handler(i) : undefined)\n          }\n        }\n      })\n\n      context.setContext('each', undefined)\n    }\n  }\n\n  suiteFn.for = function <T>(\n    this: {\n      withContext: () => SuiteAPI\n      setContext: (key: string, value: boolean | undefined) => SuiteAPI\n    },\n    cases: ReadonlyArray<T>,\n    ...args: any[]\n  ) {\n    if (Array.isArray(cases) && args.length) {\n      cases = formatTemplateString(cases, args)\n    }\n\n    return (\n      name: string | Function,\n      optionsOrFn: ((...args: T[]) => void) | TestOptions,\n      fnOrOptions?: ((...args: T[]) => void) | number,\n    ) => {\n      const name_ = formatName(name)\n      const { options, handler } = parseArguments(optionsOrFn, fnOrOptions)\n      cases.forEach((item, idx) => {\n        suite(formatTitle(name_, toArray(item), idx), options, handler ? () => handler(item) : undefined)\n      })\n    }\n  }\n\n  suiteFn.skipIf = (condition: any) =>\n    (condition ? suite.skip : suite) as SuiteAPI\n  suiteFn.runIf = (condition: any) =>\n    (condition ? suite : suite.skip) as SuiteAPI\n\n  return createChainable(\n    ['concurrent', 'sequential', 'shuffle', 'skip', 'only', 'todo'],\n    suiteFn,\n  ) as unknown as SuiteAPI\n}\n\nexport function createTaskCollector(\n  fn: (...args: any[]) => any,\n): TestAPI {\n  const taskFn = fn as any\n\n  taskFn.each = function <T>(\n    this: TestAPI,\n    cases: ReadonlyArray<T>,\n    ...args: any[]\n  ) {\n    const context = getChainableContext(this)\n    const test = context.withContext()\n    context.setContext('each', true)\n\n    if (Array.isArray(cases) && args.length) {\n      cases = formatTemplateString(cases, args)\n    }\n\n    return (\n      name: string | Function,\n      optionsOrFn: ((...args: T[]) => void) | TestOptions,\n      fnOrOptions?: ((...args: T[]) => void) | number,\n    ) => {\n      const _name = formatName(name)\n      const arrayOnlyCases = cases.every(Array.isArray)\n\n      const { options, handler } = parseArguments(optionsOrFn, fnOrOptions)\n\n      const fnFirst = typeof optionsOrFn === 'function'\n\n      cases.forEach((i, idx) => {\n        const items = Array.isArray(i) ? i : [i]\n\n        if (fnFirst) {\n          if (arrayOnlyCases) {\n            test(\n              formatTitle(_name, items, idx),\n              handler ? () => handler(...items) : undefined,\n              options.timeout,\n            )\n          }\n          else {\n            test(formatTitle(_name, items, idx), handler ? () => handler(i) : undefined, options.timeout)\n          }\n        }\n        else {\n          if (arrayOnlyCases) {\n            test(formatTitle(_name, items, idx), options, handler ? () => handler(...items) : undefined)\n          }\n          else {\n            test(formatTitle(_name, items, idx), options, handler ? () => handler(i) : undefined)\n          }\n        }\n      })\n\n      context.setContext('each', undefined)\n    }\n  }\n\n  taskFn.for = function <T>(\n    this: TestAPI,\n    cases: ReadonlyArray<T>,\n    ...args: any[]\n  ) {\n    const context = getChainableContext(this)\n    const test = context.withContext()\n\n    if (Array.isArray(cases) && args.length) {\n      cases = formatTemplateString(cases, args)\n    }\n\n    return (\n      name: string | Function,\n      optionsOrFn: ((...args: T[]) => void) | TestOptions,\n      fnOrOptions?: ((...args: T[]) => void) | number,\n    ) => {\n      const _name = formatName(name)\n      const { options, handler } = parseArguments(optionsOrFn, fnOrOptions)\n      cases.forEach((item, idx) => {\n        // monkey-patch handler to allow parsing fixture\n        const handlerWrapper = handler ? (ctx: any) => handler(item, ctx) : undefined\n        if (handlerWrapper) {\n          configureProps(handlerWrapper, { index: 1, original: handler })\n        }\n        test(formatTitle(_name, toArray(item), idx), options, handlerWrapper)\n      })\n    }\n  }\n\n  taskFn.skipIf = function (this: TestAPI, condition: any) {\n    return condition ? this.skip : this\n  }\n  taskFn.runIf = function (this: TestAPI, condition: any) {\n    return condition ? this : this.skip\n  }\n\n  /**\n   * Parse builder pattern arguments into a fixtures object.\n   * Handles both builder pattern (name, options?, value) and object syntax.\n   */\n  function parseBuilderFixtures(\n    fixturesOrName: UserFixtures | string,\n    optionsOrFn?: object | ((...args: any[]) => any),\n    maybeFn?: (...args: any[]) => any,\n  ): UserFixtures {\n    // Object syntax: just return as-is\n    if (typeof fixturesOrName !== 'string') {\n      return fixturesOrName\n    }\n\n    const fixtureName = fixturesOrName\n    let fixtureOptions: object | undefined\n    let fixtureValue: any\n\n    if (maybeFn !== undefined) {\n      // (name, options, value) or (name, options, fn)\n      fixtureOptions = optionsOrFn as object\n      fixtureValue = maybeFn\n    }\n    else {\n      // (name, value) or (name, fn)\n      // Check if optionsOrFn looks like fixture options (has scope or auto)\n      if (\n        optionsOrFn !== null\n        && typeof optionsOrFn === 'object'\n        && !Array.isArray(optionsOrFn)\n        && TestFixtures.isFixtureOptions(optionsOrFn)\n      ) {\n        // (name, options) with no value - treat as empty object fixture\n        fixtureOptions = optionsOrFn as object\n        fixtureValue = {}\n      }\n      else {\n        // (name, value) or (name, fn)\n        fixtureOptions = undefined\n        fixtureValue = optionsOrFn\n      }\n    }\n\n    // Function value: wrap with onCleanup pattern\n    if (typeof fixtureValue === 'function') {\n      const builderFn = fixtureValue as (...args: any[]) => any\n\n      // Wrap builder pattern function (returns value) to use() pattern\n      const fixture = async (ctx: any, use: (value: any) => Promise<void>) => {\n        let cleanup: (() => any) | undefined\n        const onCleanup = (fn: () => any) => {\n          if (cleanup !== undefined) {\n            throw new Error(\n              `onCleanup can only be called once per fixture. `\n              + `Define separate fixtures if you need multiple cleanup functions.`,\n            )\n          }\n          cleanup = fn\n        }\n        const value = await builderFn(ctx, { onCleanup })\n        await use(value)\n        if (cleanup) {\n          await cleanup()\n        }\n      }\n      configureProps(fixture, { original: builderFn })\n\n      if (fixtureOptions) {\n        return { [fixtureName]: [fixture, fixtureOptions] } as any\n      }\n      return { [fixtureName]: fixture } as any\n    }\n\n    // Non-function value: use directly\n    if (fixtureOptions) {\n      return { [fixtureName]: [fixtureValue, fixtureOptions] } as any\n    }\n    return { [fixtureName]: fixtureValue } as any\n  }\n\n  taskFn.override = function (\n    this: TestAPI,\n    fixturesOrName: UserFixtures | string,\n    optionsOrFn?: object | ((...args: any[]) => any),\n    maybeFn?: (...args: any[]) => any,\n  ) {\n    const userFixtures = parseBuilderFixtures(fixturesOrName, optionsOrFn, maybeFn)\n    getChainableContext(this).getFixtures().override(runner, userFixtures)\n    return this\n  }\n\n  taskFn.scoped = function (fixtures: UserFixtures) {\n    console.warn(`test.scoped() is deprecated and will be removed in future versions. Please use test.override() instead.`)\n    return this.override(fixtures)\n  }\n\n  taskFn.extend = function (\n    this: TestAPI,\n    fixturesOrName: UserFixtures | string,\n    optionsOrFn?: object | ((...args: any[]) => any),\n    maybeFn?: (...args: any[]) => any,\n  ) {\n    const userFixtures = parseBuilderFixtures(fixturesOrName, optionsOrFn, maybeFn)\n    const fixtures = getChainableContext(this).getFixtures().extend(\n      runner,\n      userFixtures,\n    )\n\n    const _test = createTest(function (\n      name: string | Function,\n      optionsOrFn?: TestOptions | TestFunction,\n      optionsOrTest?: number | TestFunction,\n    ) {\n      fn.call(this, formatName(name), optionsOrFn, optionsOrTest)\n    })\n    getChainableContext(_test).mergeContext({ fixtures })\n\n    return _test\n  }\n\n  taskFn.describe = suite\n  taskFn.suite = suite\n  taskFn.beforeEach = beforeEach\n  taskFn.afterEach = afterEach\n  taskFn.beforeAll = beforeAll\n  taskFn.afterAll = afterAll\n  taskFn.aroundEach = aroundEach\n  taskFn.aroundAll = aroundAll\n\n  const _test = createChainable(\n    ['concurrent', 'sequential', 'skip', 'only', 'todo', 'fails'],\n    taskFn,\n    { fixtures: new TestFixtures() },\n  ) as TestAPI\n\n  return _test\n}\n\nfunction createTest(\n  fn: (\n    this: InternalTestContext,\n    title: string,\n    optionsOrFn?: TestOptions | TestFunction,\n    optionsOrTest?: number | TestFunction,\n  ) => void,\n) {\n  return createTaskCollector(fn) as TestAPI\n}\n\nfunction formatName(name: string | Function) {\n  return typeof name === 'string'\n    ? name\n    : typeof name === 'function'\n      ? name.name || '<anonymous>'\n      : String(name)\n}\n\nfunction formatTitle(template: string, items: any[], idx: number) {\n  if (template.includes('%#') || template.includes('%$')) {\n    // '%#' match index of the test case\n    template = template\n      .replace(/%%/g, '__vitest_escaped_%__')\n      .replace(/%#/g, `${idx}`)\n      .replace(/%\\$/g, `${idx + 1}`)\n      .replace(/__vitest_escaped_%__/g, '%%')\n  }\n  const count = template.split('%').length - 1\n\n  if (template.includes('%f')) {\n    const placeholders = template.match(/%f/g) || []\n    placeholders.forEach((_, i) => {\n      if (isNegativeNaN(items[i]) || Object.is(items[i], -0)) {\n        // Replace the i-th occurrence of '%f' with '-%f'\n        let occurrence = 0\n        template = template.replace(/%f/g, (match) => {\n          occurrence++\n          return occurrence === i + 1 ? '-%f' : match\n        })\n      }\n    })\n  }\n\n  const isObjectItem = isObject(items[0])\n  function formatAttribute(s: string) {\n    return s.replace(/\\$([$\\w.]+)/g, (_, key: string) => {\n      const isArrayKey = /^\\d+$/.test(key)\n      if (!isObjectItem && !isArrayKey) {\n        return `$${key}`\n      }\n      const arrayElement = isArrayKey ? objectAttr(items, key) : undefined\n      const value = isObjectItem ? objectAttr(items[0], key, arrayElement) : arrayElement\n      return objDisplay(value, {\n        truncate: runner?.config?.chaiConfig?.truncateThreshold,\n      })\n    })\n  }\n\n  let output = ''\n  let i = 0\n  handleRegexMatch(\n    template,\n    formatRegExp,\n    // format \"%\"\n    (match) => {\n      if (i < count) {\n        output += format(match[0], items[i++])\n      }\n      else {\n        output += match[0]\n      }\n    },\n    // format \"$\"\n    (nonMatch) => {\n      output += formatAttribute(nonMatch)\n    },\n  )\n  return output\n}\n\n// based on https://github.com/unocss/unocss/blob/2e74b31625bbe3b9c8351570749aa2d3f799d919/packages/autocomplete/src/parse.ts#L11\nfunction handleRegexMatch(\n  input: string,\n  regex: RegExp,\n  onMatch: (match: RegExpMatchArray) => void,\n  onNonMatch: (nonMatch: string) => void,\n) {\n  let lastIndex = 0\n  for (const m of input.matchAll(regex)) {\n    if (lastIndex < m.index) {\n      onNonMatch(input.slice(lastIndex, m.index))\n    }\n    onMatch(m)\n    lastIndex = m.index + m[0].length\n  }\n  if (lastIndex < input.length) {\n    onNonMatch(input.slice(lastIndex))\n  }\n}\n\nfunction formatTemplateString(cases: any[], args: any[]): any[] {\n  const header = cases\n    .join('')\n    .trim()\n    .replace(/ /g, '')\n    .split('\\n')\n    .map(i => i.split('|'))[0]\n  const res: any[] = []\n  for (let i = 0; i < Math.floor(args.length / header.length); i++) {\n    const oneCase: Record<string, any> = {}\n    for (let j = 0; j < header.length; j++) {\n      oneCase[header[j]] = args[i * header.length + j] as any\n    }\n    res.push(oneCase)\n  }\n  return res\n}\n"
  },
  {
    "path": "packages/runner/src/test-state.ts",
    "content": "import type { Test } from './types/tasks'\n\nlet _test: Test | undefined\n\nexport function setCurrentTest<T extends Test>(test: T | undefined): void {\n  _test = test\n}\n\nexport function getCurrentTest<T extends Test | undefined>(): T {\n  return _test as T\n}\n\nconst tests: Array<Test> = []\nexport function addRunningTest(test: Test): () => void {\n  tests.push(test)\n  return () => {\n    tests.splice(tests.indexOf(test))\n  }\n}\n\nexport function getRunningTests(): Array<Test> {\n  return tests\n}\n"
  },
  {
    "path": "packages/runner/src/types/runner.ts",
    "content": "import type { DiffOptions } from '@vitest/utils/diff'\nimport type {\n  File,\n  ImportDuration,\n  SequenceHooks,\n  SequenceSetupFiles,\n  SerializableRetry,\n  Suite,\n  TaskEventPack,\n  TaskResultPack,\n  Test,\n  TestAnnotation,\n  TestArtifact,\n  TestContext,\n  TestOptions,\n  TestTags,\n} from './tasks'\n\n/**\n * This is a subset of Vitest config that's required for the runner to work.\n */\nexport interface VitestRunnerConfig {\n  root: string\n  setupFiles: string[]\n  name: string | undefined\n  passWithNoTests: boolean\n  testNamePattern: RegExp | undefined\n  allowOnly: boolean\n  sequence: {\n    shuffle?: boolean\n    concurrent?: boolean\n    seed: number\n    hooks: SequenceHooks\n    setupFiles: SequenceSetupFiles\n  }\n  chaiConfig: {\n    truncateThreshold?: number\n  } | undefined\n  maxConcurrency: number\n  testTimeout: number\n  hookTimeout: number\n  retry: SerializableRetry\n  includeTaskLocation: boolean | undefined\n  diffOptions?: DiffOptions\n  tags: TestTagDefinition[]\n  tagsFilter: string[] | undefined\n  strictTags: boolean\n}\n\n/**\n * Possible options to run a single file in a test.\n */\nexport interface FileSpecification {\n  filepath: string\n  // file can be marked via a jsdoc comment to have tags,\n  // these are _not_ tags to filter tests by\n  fileTags?: string[]\n  testLocations: number[] | undefined\n  testNamePattern: RegExp | undefined\n  testTagsFilter: string[] | undefined\n  testIds: string[] | undefined\n}\n\nexport interface TestTagDefinition extends Omit<TestOptions, 'tags' | 'shuffle'> {\n  /**\n   * The name of the tag. This is what you use in the `tags` array in tests.\n   */\n  name: keyof TestTags extends never\n    ? string\n    : TestTags[keyof TestTags]\n  /**\n   * A description for the tag. This will be shown in the CLI help and UI.\n   */\n  description?: string\n  /**\n   * Priority for merging options when multiple tags with the same options are applied to a test.\n   *\n   * Lower number means higher priority. E.g., priority 1 takes precedence over priority 3.\n   */\n  priority?: number\n}\n\nexport type VitestRunnerImportSource = 'collect' | 'setup'\n\nexport interface VitestRunnerConstructor {\n  new (config: VitestRunnerConfig): VitestRunner\n}\n\nexport type CancelReason\n  = | 'keyboard-input'\n    | 'test-failure'\n    | (string & Record<string, never>)\n\nexport interface VitestRunner {\n  /**\n   * First thing that's getting called before actually collecting and running tests.\n   */\n  onBeforeCollect?: (paths: string[]) => unknown\n  /**\n   * Called after the file task was created but not collected yet.\n   */\n  onCollectStart?: (file: File) => unknown\n  /**\n   * Called after collecting tests and before \"onBeforeRun\".\n   */\n  onCollected?: (files: File[]) => unknown\n\n  /**\n   * Called when test runner should cancel next test runs.\n   * Runner should listen for this method and mark tests and suites as skipped in\n   * \"onBeforeRunSuite\" and \"onBeforeRunTask\" when called.\n   */\n  cancel?: (reason: CancelReason) => unknown\n\n  /**\n   * Called before running a single test. Doesn't have \"result\" yet.\n   */\n  onBeforeRunTask?: (test: Test) => unknown\n  /**\n   * Called before actually running the test function. Already has \"result\" with \"state\" and \"startTime\".\n   */\n  onBeforeTryTask?: (\n    test: Test,\n    options: { retry: number; repeats: number },\n  ) => unknown\n  /**\n   * When the task has finished running, but before cleanup hooks are called\n   */\n  onTaskFinished?: (test: Test) => unknown\n  /**\n   * Called after result and state are set.\n   */\n  onAfterRunTask?: (test: Test) => unknown\n  /**\n   * Called right after running the test function. Doesn't have new state yet. Will not be called, if the test function throws.\n   */\n  onAfterTryTask?: (\n    test: Test,\n    options: { retry: number; repeats: number },\n  ) => unknown\n  /**\n   * Called after the retry resolution happened. Unlike `onAfterTryTask`, the test now has a new state.\n   * All `after` hooks were also called by this point.\n   */\n  onAfterRetryTask?: (\n    test: Test,\n    options: { retry: number; repeats: number },\n  ) => unknown\n\n  /**\n   * Called before running a single suite. Doesn't have \"result\" yet.\n   */\n  onBeforeRunSuite?: (suite: Suite) => unknown\n  /**\n   * Called after running a single suite. Has state and result.\n   */\n  onAfterRunSuite?: (suite: Suite) => unknown\n\n  /**\n   * If defined, will be called instead of usual Vitest suite partition and handling.\n   * \"before\" and \"after\" hooks will not be ignored.\n   */\n  runSuite?: (suite: Suite) => Promise<void>\n  /**\n   * If defined, will be called instead of usual Vitest handling. Useful, if you have your custom test function.\n   * \"before\" and \"after\" hooks will not be ignored.\n   */\n  runTask?: (test: Test) => Promise<void>\n\n  /**\n   * Called, when a task is updated. The same as \"onTaskUpdate\" in a reporter, but this is running in the same thread as tests.\n   */\n  onTaskUpdate?: (task: TaskResultPack[], events: TaskEventPack[]) => Promise<void>\n\n  /**\n   * Called when annotation is added via the `context.annotate` method.\n   */\n  onTestAnnotate?: (test: Test, annotation: TestAnnotation) => Promise<TestAnnotation>\n\n  /**\n   * @experimental\n   *\n   * Called when artifacts are recorded on tests via the `recordArtifact` utility.\n   */\n  onTestArtifactRecord?: <Artifact extends TestArtifact>(test: Test, artifact: Artifact) => Promise<Artifact>\n\n  /**\n   * Called before running all tests in collected paths.\n   */\n  onBeforeRunFiles?: (files: File[]) => unknown\n  /**\n   * Called right after running all tests in collected paths.\n   */\n  onAfterRunFiles?: (files: File[]) => unknown\n  /**\n   * Called when new context for a test is defined. Useful if you want to add custom properties to the context.\n   * If you only want to define custom context, consider using \"beforeAll\" in \"setupFiles\" instead.\n   *\n   * @see https://vitest.dev/advanced/runner#your-task-function\n   */\n  extendTaskContext?: (context: TestContext) => TestContext\n  /**\n   * Called when test and setup files are imported. Can be called in two situations: when collecting tests and when importing setup files.\n   */\n  importFile: (filepath: string, source: VitestRunnerImportSource) => unknown\n  /**\n   * Function that is called when the runner attempts to get the value when `test.extend` is used with `{ injected: true }`\n   */\n  injectValue?: (key: string) => unknown\n  /**\n   * Gets the time spent importing each individual non-externalized file that Vitest collected.\n   */\n  getImportDurations?: () => Record<string, ImportDuration>\n  /**\n   * Publicly available configuration.\n   */\n  config: VitestRunnerConfig\n  /**\n   * The name of the current pool. Can affect how stack trace is inferred on the server side.\n   */\n  pool?: string\n  /**\n   * The current Vite environment that processes the files on the server.\n   */\n  viteEnvironment?: string\n\n  onCleanupWorkerContext?: (cleanup: () => unknown) => void\n\n  // eslint-disable-next-line ts/method-signature-style\n  trace?<T>(name: string, cb: () => T): T\n  // eslint-disable-next-line ts/method-signature-style\n  trace?<T>(name: string, attributes: Record<string, any>, cb: () => T): T\n\n  /** @private */\n  _currentTaskStartTime?: number\n  /** @private */\n  _currentTaskTimeout?: number\n}\n"
  },
  {
    "path": "packages/runner/src/types/tasks.ts",
    "content": "import type { Awaitable, TestError } from '@vitest/utils'\nimport type { TestFixtures } from '../fixture'\nimport type { afterAll, afterEach, aroundAll, aroundEach, beforeAll, beforeEach } from '../hooks'\nimport type { ChainableFunction, kChainableContext } from '../utils/chain'\n\nexport type RunMode = 'run' | 'skip' | 'only' | 'todo' | 'queued'\nexport type TaskState = RunMode | 'pass' | 'fail'\n\nexport interface TaskBase {\n  /**\n   * Unique task identifier. Based on the file id and the position of the task.\n   * The id of the file task is based on the file path relative to root and project name.\n   * It will not change between runs.\n   * @example `1201091390`, `1201091390_0`, `1201091390_0_1`\n   */\n  id: string\n  /**\n   * Task name provided by the user. If no name was provided, it will be an empty string.\n   */\n  name: string\n  /**\n   * Full name including the file path, any parent suites, and this task's name.\n   *\n   * Uses ` > ` as the separator between levels.\n   *\n   * @example\n   * // file\n   * 'test/task-names.test.ts'\n   * @example\n   * // suite\n   * 'test/task-names.test.ts > meal planning'\n   * 'test/task-names.test.ts > meal planning > grocery lists'\n   * @example\n   * // test\n   * 'test/task-names.test.ts > meal planning > grocery lists > calculates ingredients'\n   */\n  fullName: string\n  /**\n   * Full name excluding the file path, including any parent suites and this task's name. `undefined` for file tasks.\n   *\n   * Uses ` > ` as the separator between levels.\n   *\n   * @example\n   * // file\n   * undefined\n   * @example\n   * // suite\n   * 'meal planning'\n   * 'meal planning > grocery lists'\n   * @example\n   * // test\n   * 'meal planning > grocery lists > calculates ingredients'\n   */\n  fullTestName?: string\n  /**\n   * Task mode.\n   * - **skip**: task is skipped\n   * - **only**: only this task and other tasks with `only` mode will run\n   * - **todo**: task is marked as a todo, alias for `skip`\n   * - **run**: task will run or already ran\n   * - **queued**: task will start running next. It can only exist on the File\n   */\n  mode: RunMode\n  /**\n   * Custom metadata for the task. JSON reporter will save this data.\n   */\n  meta: TaskMeta\n  /**\n   * Whether the task was produced with `.each()` method.\n   */\n  each?: boolean\n  /**\n   * Whether the task should run concurrently with other tasks.\n   */\n  concurrent?: boolean\n  /**\n   * Whether the tasks of the suite run in a random order.\n   */\n  shuffle?: boolean\n  /**\n   * Suite that this task is part of. File task or the global suite will have no parent.\n   */\n  suite?: Suite\n  /**\n   * Result of the task. Suite and file tasks will only have the result if there\n   * was an error during collection or inside `afterAll`/`beforeAll`.\n   */\n  result?: TaskResult\n  /**\n   * Retry configuration for the task.\n   * - If a number, specifies how many times to retry\n   * - If an object, allows fine-grained retry control\n   * @default 0\n   */\n  retry?: Retry\n  /**\n   * The amount of times the task should be repeated after the successful run.\n   * If the task fails, it will not be retried unless `retry` is specified.\n   * @default 0\n   */\n  repeats?: number\n  /**\n   * Location of the task in the file. This field is populated only if\n   * `includeTaskLocation` option is set. It is generated by calling `new Error`\n   * and parsing the stack trace, so the location might differ depending on the runtime.\n   */\n  location?: Location\n  /**\n   * If the test was collected by parsing the file AST, and the name\n   * is not a static string, this property will be set to `true`.\n   * @experimental\n   */\n  dynamic?: boolean\n  /**\n   * Custom tags of the task. Useful for filtering tasks.\n   */\n  tags?: string[]\n}\n\nexport interface TaskPopulated extends TaskBase {\n  /**\n   * File task. It's the root task of the file.\n   */\n  file: File\n  /**\n   * Whether the task should succeed if it fails. If the task fails, it will be marked as passed.\n   */\n  fails?: boolean\n  /**\n   * Hooks that will run if the task fails. The order depends on the `sequence.hooks` option.\n   * @internal\n   */\n  onFailed?: OnTestFailedHandler[]\n  /**\n   * Hooks that will run after the task finishes. The order depends on the `sequence.hooks` option.\n   * @internal\n   */\n  onFinished?: OnTestFinishedHandler[]\n  /**\n   * Store promises (from async expects) to wait for them before finishing the test\n   */\n  promises?: Promise<any>[]\n}\n\n/**\n * Custom metadata that can be used in reporters.\n */\nexport interface TaskMeta {}\n\n/**\n * The result of calling a task.\n */\nexport interface TaskResult {\n  /**\n   * State of the task. Inherits the `task.mode` during collection.\n   * When the task has finished, it will be changed to `pass` or `fail`.\n   * - **pass**: task ran successfully\n   * - **fail**: task failed\n   */\n  state: TaskState\n  /**\n   * Errors that occurred during the task execution. It is possible to have several errors\n   * if `expect.soft()` failed multiple times or `retry` was triggered.\n   */\n  errors?: TestError[]\n  /**\n   * How long in milliseconds the task took to run.\n   */\n  duration?: number\n  /**\n   * Time in milliseconds when the task started running.\n   */\n  startTime?: number\n  /**\n   * Heap size in bytes after the task finished.\n   * Only available if `logHeapUsage` option is set and `process.memoryUsage` is defined.\n   */\n  heap?: number\n  /**\n   * State of related to this task hooks. Useful during reporting.\n   */\n  hooks?: Partial<Record<keyof SuiteHooks, TaskState>>\n  /**\n   * The amount of times the task was retried. The task is retried only if it\n   * failed and `retry` option is set.\n   */\n  retryCount?: number\n  /**\n   * The amount of times the task was repeated. The task is repeated only if\n   * `repeats` option is set. This number also contains `retryCount`.\n   */\n  repeatCount?: number\n  /** @internal */\n  note?: string\n  /**\n   * Whether the task was skipped by calling `context.skip()`.\n   * @internal\n   */\n  pending?: boolean\n}\n\n/** The time spent importing & executing a non-externalized file. */\nexport interface ImportDuration {\n  /** The time spent importing & executing the file itself, not counting all non-externalized imports that the file does. */\n  selfTime: number\n\n  /** The time spent importing & executing the file and all its imports. */\n  totalTime: number\n\n  /** Will be set to `true`, if the module was externalized. In this case totalTime and selfTime are identical. */\n  external?: boolean\n\n  /** Which module imported this module first. All subsequent imports are cached. */\n  importer?: string\n}\n\n/**\n * The tuple representing a single task update.\n * Usually reported after the task finishes.\n */\nexport type TaskResultPack = [\n  /**\n   * Unique task identifier from `task.id`.\n   */\n  id: string,\n  /**\n   * The result of running the task from `task.result`.\n   */\n  result: TaskResult | undefined,\n  /**\n   * Custom metadata from `task.meta`.\n   */\n  meta: TaskMeta,\n]\n\nexport interface TaskEventData {\n  annotation?: TestAnnotation | undefined\n  artifact?: TestArtifact | undefined\n}\n\nexport type TaskEventPack = [\n  /**\n   * Unique task identifier from `task.id`.\n   */\n  id: string,\n  /**\n   * The name of the event that triggered the update.\n   */\n  event: TaskUpdateEvent,\n  /**\n   * Data associated with the event\n   */\n  data: TaskEventData | undefined,\n]\n\nexport type TaskUpdateEvent\n  = | 'test-failed-early'\n    | 'suite-failed-early'\n    | 'test-prepare'\n    | 'test-finished'\n    | 'test-retried'\n    | 'test-cancel'\n    | 'suite-prepare'\n    | 'suite-finished'\n    | 'before-hook-start'\n    | 'before-hook-end'\n    | 'after-hook-start'\n    | 'after-hook-end'\n    | 'test-annotation'\n    | 'test-artifact'\n\nexport interface Suite extends TaskBase {\n  type: 'suite'\n  /**\n   * File task. It's the root task of the file.\n   */\n  file: File\n  /**\n   * An array of tasks that are part of the suite.\n   */\n  tasks: Task[]\n}\n\nexport interface File extends Suite {\n  /**\n   * The name of the pool that the file belongs to.\n   * @default 'forks'\n   */\n  pool?: string\n  /**\n   * The environment that processes the file on the server.\n   */\n  viteEnvironment?: string\n  /**\n   * The path to the file in UNIX format.\n   */\n  filepath: string\n  /**\n   * The name of the workspace project the file belongs to.\n   */\n  projectName: string | undefined\n  /**\n   * The time it took to collect all tests in the file.\n   * This time also includes importing all the file dependencies.\n   */\n  collectDuration?: number\n  /**\n   * The time it took to import the setup file.\n   */\n  setupDuration?: number\n  /**\n   * Whether the file is initiated without running any tests.\n   * This is done to populate state on the server side by Vitest.\n   * @internal\n   */\n  local?: boolean\n\n  /** The time spent importing every non-externalized dependency that Vitest has processed. */\n  importDurations?: Record<string, ImportDuration>\n}\n\nexport interface Test<ExtraContext = object> extends TaskPopulated {\n  type: 'test'\n  /**\n   * Test context that will be passed to the test function.\n   */\n  context: TestContext & ExtraContext\n  /**\n   * The test timeout in milliseconds.\n   */\n  timeout: number\n  /**\n   * An array of custom annotations.\n   */\n  annotations: TestAnnotation[]\n  /**\n   * An array of artifacts produced by the test.\n   *\n   * @experimental\n   */\n  artifacts: TestArtifact[]\n  fullTestName: string\n}\n\nexport type Task = Test | Suite | File\n\nexport type TestFunction<ExtraContext = object> = (\n  context: TestContext & ExtraContext,\n) => Awaitable<any> | void\n\n// jest's ExtractEachCallbackArgs\ntype ExtractEachCallbackArgs<T extends ReadonlyArray<any>> = {\n  1: [T[0]]\n  2: [T[0], T[1]]\n  3: [T[0], T[1], T[2]]\n  4: [T[0], T[1], T[2], T[3]]\n  5: [T[0], T[1], T[2], T[3], T[4]]\n  6: [T[0], T[1], T[2], T[3], T[4], T[5]]\n  7: [T[0], T[1], T[2], T[3], T[4], T[5], T[6]]\n  8: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7]]\n  9: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8]]\n  10: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]]\n  fallback: Array<T extends ReadonlyArray<infer U> ? U : any>\n}[T extends Readonly<[any]>\n  ? 1\n  : T extends Readonly<[any, any]>\n    ? 2\n    : T extends Readonly<[any, any, any]>\n      ? 3\n      : T extends Readonly<[any, any, any, any]>\n        ? 4\n        : T extends Readonly<[any, any, any, any, any]>\n          ? 5\n          : T extends Readonly<[any, any, any, any, any, any]>\n            ? 6\n            : T extends Readonly<[any, any, any, any, any, any, any]>\n              ? 7\n              : T extends Readonly<[any, any, any, any, any, any, any, any]>\n                ? 8\n                : T extends Readonly<[any, any, any, any, any, any, any, any, any]>\n                  ? 9\n                  : T extends Readonly<[any, any, any, any, any, any, any, any, any, any]>\n                    ? 10\n                    : 'fallback']\n\ninterface EachFunctionReturn<T extends any[]> {\n  (\n    name: string | Function,\n    fn: (...args: T) => Awaitable<void>,\n    options?: number\n  ): void\n  (\n    name: string | Function,\n    options: TestCollectorOptions,\n    fn: (...args: T) => Awaitable<void>\n  ): void\n}\n\ninterface TestEachFunction {\n  <T extends any[] | [any]>(cases: ReadonlyArray<T>): EachFunctionReturn<T>\n  <T extends ReadonlyArray<any>>(cases: ReadonlyArray<T>): EachFunctionReturn<\n    ExtractEachCallbackArgs<T>\n  >\n  <T>(cases: ReadonlyArray<T>): EachFunctionReturn<T[]>\n  (...args: [TemplateStringsArray, ...any]): EachFunctionReturn<any[]>\n}\n\ninterface TestForFunctionReturn<Arg, Context> {\n  (\n    name: string | Function,\n    fn: (arg: Arg, context: Context) => Awaitable<void>\n  ): void\n  (\n    name: string | Function,\n    options: TestCollectorOptions,\n    fn: (args: Arg, context: Context) => Awaitable<void>\n  ): void\n}\n\ninterface TestForFunction<ExtraContext> {\n  // test.for([1, 2, 3])\n  // test.for([[1, 2], [3, 4, 5]])\n  <T>(cases: ReadonlyArray<T>): TestForFunctionReturn<\n    T,\n    TestContext & ExtraContext\n  >\n\n  // test.for`\n  //    a  |  b\n  //   {1} | {2}\n  //   {3} | {4}\n  // `\n  (strings: TemplateStringsArray, ...values: any[]): TestForFunctionReturn<\n    any,\n    TestContext & ExtraContext\n  >\n}\n\ninterface SuiteForFunction {\n  <T>(cases: ReadonlyArray<T>): EachFunctionReturn<[T]>\n  (...args: [TemplateStringsArray, ...any]): EachFunctionReturn<any[]>\n}\n\ninterface TestCollectorCallable<C = object> {\n  <ExtraContext extends C>(\n    name: string | Function,\n    fn?: TestFunction<ExtraContext>,\n    options?: number\n  ): void\n  <ExtraContext extends C>(\n    name: string | Function,\n    options?: TestCollectorOptions,\n    fn?: TestFunction<ExtraContext>\n  ): void\n}\n\nexport interface InternalChainableContext<API = TestAPI> {\n  /** @internal */\n  mergeContext: (ctx: Partial<InternalTestContext>) => void\n  /** @internal */\n  setContext: (key: keyof InternalTestContext, value: any) => void\n  /** @internal */\n  withContext: () => API\n  /** @internal */\n  getFixtures: () => TestFixtures\n}\ntype ChainableTestAPI<ExtraContext = object> = ChainableFunction<\n  'concurrent' | 'sequential' | 'only' | 'skip' | 'todo' | 'fails',\n  TestCollectorCallable<ExtraContext>,\n  {\n    each: TestEachFunction\n    for: TestForFunction<ExtraContext>\n  }\n>\n\ntype TestCollectorOptions = Omit<TestOptions, 'shuffle'>\n\n/**\n * Retry configuration for tests.\n * Can be a number for simple retry count, or an object for advanced retry control.\n */\nexport type Retry = number | {\n  /**\n   * The number of times to retry the test if it fails.\n   * @default 0\n   */\n  count?: number\n  /**\n   * Delay in milliseconds between retry attempts.\n   * @default 0\n   */\n  delay?: number\n  /**\n   * Condition to determine if a test should be retried based on the error.\n   * - If a RegExp, it is tested against the error message\n   * - If a function, called with the TestError object; return true to retry\n   *\n   * NOTE: Functions can only be used in test files, not in vitest.config.ts,\n   * because the configuration is serialized when passed to worker threads.\n   *\n   * @default undefined (retry on all errors)\n   */\n  condition?: RegExp | ((error: TestError) => boolean)\n}\n\n/**\n * Serializable retry configuration (used in config files).\n * Functions cannot be serialized, so only string conditions are allowed.\n */\nexport type SerializableRetry = number | {\n  /**\n   * The number of times to retry the test if it fails.\n   * @default 0\n   */\n  count?: number\n  /**\n   * Delay in milliseconds between retry attempts.\n   * @default 0\n   */\n  delay?: number\n  /**\n   * Condition to determine if a test should be retried based on the error.\n   * Must be a RegExp tested against the error message.\n   *\n   * @default undefined (retry on all errors)\n   */\n  condition?: RegExp\n}\n\nexport interface TestOptions {\n  /**\n   * Test timeout.\n   */\n  timeout?: number\n  /**\n   * Retry configuration for the test.\n   * - If a number, specifies how many times to retry\n   * - If an object, allows fine-grained retry control\n   * @default 0\n   */\n  retry?: Retry\n  /**\n   * How many times the test will run again.\n   * Only inner tests will repeat if set on `describe()`, nested `describe()` will inherit parent's repeat by default.\n   *\n   * @default 0\n   */\n  repeats?: number\n  /**\n   * Whether suites and tests run concurrently.\n   * Tests inherit `concurrent` from `describe()` and nested `describe()` will inherit from parent's `concurrent`.\n   */\n  concurrent?: boolean\n  /**\n   * Whether tests run sequentially.\n   * Tests inherit `sequential` from `describe()` and nested `describe()` will inherit from parent's `sequential`.\n   */\n  sequential?: boolean\n  /**\n   * Whether the test should be skipped.\n   */\n  skip?: boolean\n  /**\n   * Should this test be the only one running in a suite.\n   */\n  only?: boolean\n  /**\n   * Whether the test should be skipped and marked as a todo.\n   */\n  todo?: boolean\n  /**\n   * Whether the test is expected to fail. If it does, the test will pass, otherwise it will fail.\n   */\n  fails?: boolean\n  /**\n   * Custom tags of the test. Useful for filtering tests.\n   */\n  tags?: keyof TestTags extends never\n    ? string[] | string\n    : TestTags[keyof TestTags] | TestTags[keyof TestTags][]\n  /**\n   * Custom test metadata available to reporters.\n   */\n  meta?: Partial<TaskMeta>\n}\n\nexport interface TestTags {}\n\nexport interface SuiteOptions extends TestOptions {\n  /**\n   * Whether the tasks of the suite run in a random order.\n   */\n  shuffle?: boolean\n}\n\ninterface ExtendedAPI<ExtraContext> {\n  skipIf: (condition: any) => ChainableTestAPI<ExtraContext>\n  runIf: (condition: any) => ChainableTestAPI<ExtraContext>\n}\n\ninterface Hooks<ExtraContext> {\n  /**\n   * Suite-level hooks only receive file/worker scoped fixtures.\n   * Test-scoped fixtures are NOT available in beforeAll/afterAll/aroundAll.\n   */\n  beforeAll: typeof beforeAll<ExtractSuiteContext<ExtraContext>>\n  afterAll: typeof afterAll<ExtractSuiteContext<ExtraContext>>\n  aroundAll: typeof aroundAll<ExtractSuiteContext<ExtraContext>>\n  /**\n   * Test-level hooks receive all fixtures including test-scoped ones.\n   */\n  beforeEach: typeof beforeEach<ExtraContext>\n  afterEach: typeof afterEach<ExtraContext>\n  aroundEach: typeof aroundEach<ExtraContext>\n}\n\nexport type TestAPI<ExtraContext = object> = ChainableTestAPI<ExtraContext>\n  & ExtendedAPI<ExtraContext> & Hooks<ExtraContext> & {\n    /** @internal */\n    [kChainableContext]: InternalChainableContext<TestAPI>\n    /**\n     * Extend the test API with custom fixtures.\n     *\n     * @example\n     * ```ts\n     * // Simple test fixtures (backward compatible)\n     * const myTest = test.extend<{ foo: string }>({\n     *   foo: 'value',\n     * })\n     *\n     * // With scoped fixtures - use $test/$file/$worker structure\n     * const myTest = test.extend<{\n     *   $test: { testData: string }\n     *   $file: { fileDb: Database }\n     *   $worker: { workerConfig: Config }\n     * }>({\n     *   testData: async ({ fileDb }, use) => {\n     *     await use(await fileDb.getData())\n     *   },\n     *   fileDb: [async ({ workerConfig }, use) => {\n     *     // File fixture can only access workerConfig, NOT testData\n     *     const db = new Database(workerConfig)\n     *     await use(db)\n     *     await db.close()\n     *   }, { scope: 'file' }],\n     *   workerConfig: [async ({}, use) => {\n     *     // Worker fixture can only access other worker fixtures\n     *     await use(loadConfig())\n     *   }, { scope: 'worker' }],\n     * })\n     *\n     * // Builder pattern with automatic type inference\n     * const myTest = test\n     *   .extend('config', { scope: 'worker' }, async ({}) => {\n     *     return { port: 3000 }  // Type inferred as { port: number }\n     *   })\n     *   .extend('db', { scope: 'file' }, async ({ config }, { onCleanup }) => {\n     *     // TypeScript knows config is { port: number }\n     *     const db = new Database(config.port)\n     *     onCleanup(() => db.close())  // Register cleanup\n     *     return db  // Type inferred as Database\n     *   })\n     *   .extend('data', async ({ db }) => {\n     *     // TypeScript knows db is Database\n     *     return await db.getData()  // Type inferred from return\n     *   })\n     * ```\n     */\n    extend: {\n      // Builder pattern overloads with automatic type inference from return value\n      // MUST come first for correct TypeScript overload resolution\n\n      // Function overloads (with cleanup support via onCleanup)\n      // When extending with same key, T must match existing type (last value wins at runtime)\n      // Overload 1: Worker scope function - can only access worker fixtures\n      <K extends string, T extends (K extends keyof ExtraContext ? ExtraContext[K] : unknown)>(\n        name: K,\n        options: WorkerScopeFixtureOptions,\n        fn: BuilderFixtureFn<T, WorkerScopeContext<ExtraContext>>,\n      ): TestAPI<AddBuilderWorker<ExtraContext, K, T>>\n      // Overload 2: File scope function - can access worker + file fixtures\n      <K extends string, T extends (K extends keyof ExtraContext ? ExtraContext[K] : unknown)>(\n        name: K,\n        options: FileScopeFixtureOptions,\n        fn: BuilderFixtureFn<T, FileScopeContext<ExtraContext>>,\n      ): TestAPI<AddBuilderFile<ExtraContext, K, T>>\n      // Overload 3: Test scope function with options - can access all fixtures\n      <K extends string, T extends (K extends keyof ExtraContext ? ExtraContext[K] : unknown)>(\n        name: K,\n        options: TestScopeFixtureOptions,\n        fn: BuilderFixtureFn<T, TestScopeContext<ExtraContext>>,\n      ): TestAPI<AddBuilderTest<ExtraContext, K, T>>\n      // Overload 4: Test scope function default (no options) - can access all fixtures\n      <K extends string, T extends (K extends keyof ExtraContext ? ExtraContext[K] : unknown)>(\n        name: K,\n        fn: BuilderFixtureFn<T, TestScopeContext<ExtraContext>>,\n      ): TestAPI<AddBuilderTest<ExtraContext, K, T>>\n\n      // Non-function value overloads (simple values without cleanup)\n      // Overload 5: Static value with worker scope options\n      <K extends string, T extends (K extends keyof ExtraContext ? ExtraContext[K] : unknown)>(\n        name: K,\n        options: WorkerScopeFixtureOptions,\n        value: T extends (...args: any[]) => any ? never : T,\n      ): TestAPI<AddBuilderWorker<ExtraContext, K, T>>\n      // Overload 6: Static value with file scope options\n      <K extends string, T extends (K extends keyof ExtraContext ? ExtraContext[K] : unknown)>(\n        name: K,\n        options: FileScopeFixtureOptions,\n        value: T extends (...args: any[]) => any ? never : T,\n      ): TestAPI<AddBuilderFile<ExtraContext, K, T>>\n      // Overload 7: Static value with test scope options\n      <K extends string, T extends (K extends keyof ExtraContext ? ExtraContext[K] : unknown)>(\n        name: K,\n        options: TestScopeFixtureOptions,\n        value: T extends (...args: any[]) => any ? never : T,\n      ): TestAPI<AddBuilderTest<ExtraContext, K, T>>\n      // Overload 8: Static value default (no options) - must exclude functions\n      <K extends string, T extends (K extends keyof ExtraContext ? ExtraContext[K] : unknown)>(\n        name: K,\n        value: T extends (...args: any[]) => any ? never : T,\n      ): TestAPI<AddBuilderTest<ExtraContext, K, T>>\n\n      // Object syntax overloads\n      // Overload 9: Scoped fixtures with { $test?, $file?, $worker? } structure\n      <T extends ScopedFixturesDef>(\n        fixtures: ScopedFixturesObject<T, ExtraContext>,\n      ): TestAPI<ExtractScopedFixtures<T> & ExtraContext>\n      // Overload 10: Legacy flat fixtures (backward compatible)\n      <T extends Record<string, any> = object>(\n        fixtures: Fixtures<T, ExtraContext>,\n      ): TestAPI<{\n        [K in keyof T | keyof ExtraContext]: K extends keyof T\n          ? T[K]\n          : K extends keyof ExtraContext\n            ? ExtraContext[K]\n            : never\n      }>\n    }\n    /**\n     * Overwrite fixture values for the current suite scope.\n     * Supports both object syntax and builder pattern.\n     *\n     * @example\n     * ```ts\n     * describe('with custom config', () => {\n     *   // Object syntax\n     *   test.override({ config: { port: 4000 } })\n     *\n     *   // Builder pattern - value\n     *   test.override('config', { port: 4000 })\n     *\n     *   // Builder pattern - function\n     *   test.override('config', () => ({ port: 4000 }))\n     *\n     *   // Builder pattern - function with cleanup\n     *   test.override('db', async ({ config }, { onCleanup }) => {\n     *     const db = await createDb(config)\n     *     onCleanup(() => db.close())\n     *     return db\n     *   })\n     * })\n     * ```\n     */\n    override: {\n      // Builder pattern overloads\n      // Overload 1: Function with options\n      <K extends keyof ExtraContext>(\n        name: K,\n        options: FixtureOptions,\n        fn: BuilderFixtureFn<ExtraContext[K], ExtraContext & TestContext>,\n      ): TestAPI<ExtraContext>\n      // Overload 2: Function without options\n      <K extends keyof ExtraContext>(\n        name: K,\n        fn: BuilderFixtureFn<ExtraContext[K], ExtraContext & TestContext>,\n      ): TestAPI<ExtraContext>\n      // Overload 3: Static value with options\n      <K extends keyof ExtraContext>(\n        name: K,\n        options: FixtureOptions,\n        value: ExtraContext[K] extends (...args: any[]) => any ? never : ExtraContext[K],\n      ): TestAPI<ExtraContext>\n      // Overload 4: Static value without options\n      <K extends keyof ExtraContext>(\n        name: K,\n        value: ExtraContext[K] extends (...args: any[]) => any ? never : ExtraContext[K],\n      ): TestAPI<ExtraContext>\n      // Overload 5: Object syntax\n      (fixtures: Partial<Fixtures<ExtraContext>>): TestAPI<ExtraContext>\n    }\n    /**\n     * @deprecated Use `test.override()` instead\n     */\n    scoped: (\n      fixtures: Partial<Fixtures<ExtraContext>>,\n    ) => TestAPI<ExtraContext>\n    describe: SuiteAPI<ExtraContext>\n    suite: SuiteAPI<ExtraContext>\n  }\n\nexport interface InternalTestContext extends Record<\n  'concurrent' | 'sequential' | 'skip' | 'only' | 'todo' | 'fails' | 'each',\n  boolean | undefined\n> {\n  fixtures: TestFixtures\n}\n\nexport interface FixtureOptions {\n  /**\n   * Whether to automatically set up current fixture, even though it's not being used in tests.\n   * @default false\n   */\n  auto?: boolean\n  /**\n   * Indicated if the injected value from the config should be preferred over the fixture value\n   */\n  injected?: boolean\n  /**\n   * When should the fixture be set up.\n   * - **test**: fixture will be set up before every test\n   * - **worker**: fixture will be set up once per worker\n   * - **file**: fixture will be set up once per file\n   *\n   * **Warning:** The `vmThreads` and `vmForks` pools initiate worker fixtures once per test file.\n   * @default 'test'\n   */\n  scope?: 'test' | 'worker' | 'file'\n}\n\n/**\n * Options for test-scoped fixtures.\n * Test fixtures are set up before each test and have access to all fixtures.\n */\nexport interface TestScopeFixtureOptions extends Omit<FixtureOptions, 'scope'> {\n  /**\n   * @default 'test'\n   */\n  scope?: 'test'\n}\n\n/**\n * Options for file-scoped fixtures.\n * File fixtures are set up once per file and can only access other file fixtures and worker fixtures.\n */\nexport interface FileScopeFixtureOptions extends Omit<FixtureOptions, 'scope'> {\n  /**\n   * Must be 'file' for file-scoped fixtures.\n   */\n  scope: 'file'\n}\n\n/**\n * Options for worker-scoped fixtures.\n * Worker fixtures are set up once per worker and can only access other worker fixtures.\n */\nexport interface WorkerScopeFixtureOptions extends Omit<FixtureOptions, 'scope'> {\n  /**\n   * Must be 'worker' for worker-scoped fixtures.\n   */\n  scope: 'worker'\n}\n\nexport type Use<T> = (value: T) => Promise<void>\n\n/**\n * Cleanup registration function for builder pattern fixtures.\n * Call this to register a cleanup function that runs after the test/file/worker completes.\n *\n * **Note:** This function can only be called once per fixture. If you need multiple\n * cleanup operations, either combine them into a single cleanup function or split\n * your fixture into multiple smaller fixtures.\n */\nexport type OnCleanup = (cleanup: () => Awaitable<void>) => void\n\n/**\n * Builder pattern fixture function with automatic type inference.\n * Returns the fixture value directly (type is inferred from return).\n * Use onCleanup to register teardown logic.\n *\n * Parameters can be omitted if not needed:\n * - `async () => value` - no dependencies, no cleanup\n * - `async ({ dep }) => value` - with dependencies, no cleanup\n * - `async ({ dep }, { onCleanup }) => value` - with dependencies and cleanup\n */\nexport type BuilderFixtureFn<T, Context> = (\n  context: Context,\n  fixture: { onCleanup: OnCleanup },\n) => T | Promise<T>\n\nexport type ExtractSuiteContext<C>\n  = C extends { $__worker?: any } | { $__file?: any } | { $__test?: any }\n    ? ExtractBuilderWorker<C> & ExtractBuilderFile<C>\n    : C\n\n/**\n * Extracts worker-scoped fixtures from a context that includes scope info.\n */\nexport type ExtractBuilderWorker<C> = C extends { $__worker?: infer W }\n  ? W extends Record<string, any> ? W : object\n  : object\n\n/**\n * Extracts file-scoped fixtures from a context that includes scope info.\n */\nexport type ExtractBuilderFile<C> = C extends { $__file?: infer F }\n  ? F extends Record<string, any> ? F : object\n  : object\n\n/**\n * Extracts test-scoped fixtures from a context that includes scope info.\n */\nexport type ExtractBuilderTest<C> = C extends { $__test?: infer T }\n  ? T extends Record<string, any> ? T : object\n  : object\n\n/**\n * Adds a worker fixture to the context with proper scope tracking.\n */\nexport type AddBuilderWorker<C, K extends string, V> = Omit<C, '$__worker'> & Record<K, V> & {\n  readonly $__worker?: ExtractBuilderWorker<C> & Record<K, V>\n  readonly $__file?: ExtractBuilderFile<C>\n  readonly $__test?: ExtractBuilderTest<C>\n}\n\n/**\n * Adds a file fixture to the context with proper scope tracking.\n */\nexport type AddBuilderFile<C, K extends string, V> = Omit<C, '$__file'> & Record<K, V> & {\n  readonly $__worker?: ExtractBuilderWorker<C>\n  readonly $__file?: ExtractBuilderFile<C> & Record<K, V>\n  readonly $__test?: ExtractBuilderTest<C>\n}\n\n/**\n * Adds a test fixture to the context with proper scope tracking.\n */\nexport type AddBuilderTest<C, K extends string, V> = Omit<C, '$__test'> & Record<K, V> & {\n  readonly $__worker?: ExtractBuilderWorker<C>\n  readonly $__file?: ExtractBuilderFile<C>\n  readonly $__test?: ExtractBuilderTest<C> & Record<K, V>\n}\n\n/**\n * Context available to worker-scoped fixtures.\n * Worker fixtures can only access other worker fixtures.\n * They do NOT have access to test context (task, expect, onTestFailed, etc.)\n * since they run once per worker, outside of any specific test.\n */\nexport type WorkerScopeContext<C> = ExtractBuilderWorker<C>\n\n/**\n * Context available to file-scoped fixtures.\n * File fixtures can access worker and other file fixtures.\n * They do NOT have access to test context (task, expect, onTestFailed, etc.)\n * since they run once per file, outside of any specific test.\n */\nexport type FileScopeContext<C> = ExtractBuilderWorker<C> & ExtractBuilderFile<C>\n\n/**\n * Context available to test-scoped fixtures (all fixtures + test context).\n */\nexport type TestScopeContext<C> = C & TestContext\nexport type FixtureFn<T, K extends keyof T, ExtraContext> = (\n  context: Omit<T, K> & ExtraContext,\n  use: Use<T[K]>,\n) => Promise<void>\nexport type Fixture<T, K extends keyof T, ExtraContext = object> = ((\n  ...args: any\n) => any) extends T[K]\n  ? T[K] extends any\n    ? FixtureFn<T, K, Omit<ExtraContext, Exclude<keyof T, K>>>\n    : never\n  : | T[K]\n    | (T[K] extends any\n      ? FixtureFn<T, K, Omit<ExtraContext, Exclude<keyof T, K>>>\n      : never)\n\n/**\n * Fixture function with explicit context type for scoped fixtures.\n */\nexport type ScopedFixtureFn<Value, Context> = (\n  context: Context,\n  use: Use<Value>,\n) => Promise<void>\n\n/**\n * Fixtures definition for backward compatibility.\n * All fixtures are in T and any scope is allowed.\n */\nexport type Fixtures<T, ExtraContext = object> = {\n  [K in keyof T]:\n    | Fixture<T, K, ExtraContext & TestContext>\n    | [Fixture<T, K, ExtraContext & TestContext>, FixtureOptions?]\n}\n\n/**\n * Scoped fixtures definition using a single generic with optional scope keys.\n * This provides better ergonomics than multiple generics.\n * Uses $ prefix to avoid conflicts with fixture names.\n *\n * @example\n * ```ts\n * test.extend<{\n *   $worker?: { config: Config }\n *   $file?: { db: Database }\n *   $test?: { data: string }\n * }>({ ... })\n * ```\n */\nexport interface ScopedFixturesDef {\n  $test?: Record<string, any>\n  $file?: Record<string, any>\n  $worker?: Record<string, any>\n}\n\n/**\n * Extracts fixture types from a ScopedFixturesDef.\n * Handles optional properties by using Exclude to remove undefined.\n */\nexport type ExtractScopedFixtures<T extends ScopedFixturesDef>\n  = ([Exclude<T['$test'], undefined>] extends [never] ? object : Exclude<T['$test'], undefined>)\n    & ([Exclude<T['$file'], undefined>] extends [never] ? object : Exclude<T['$file'], undefined>)\n    & ([Exclude<T['$worker'], undefined>] extends [never] ? object : Exclude<T['$worker'], undefined>)\n\n/**\n * Creates the fixtures object type for ScopedFixturesDef with proper scope validation.\n * - Test fixtures: can be defined as value, function, or tuple with optional scope\n * - File fixtures: MUST have { scope: 'file' }\n * - Worker fixtures: MUST have { scope: 'worker' }\n */\nexport type ScopedFixturesObject<T extends ScopedFixturesDef, ExtraContext = object> = {\n  // Test fixtures - scope is optional, have access to all fixtures + TestContext\n  [K in keyof NonNullable<T['$test']>]:\n    | NonNullable<T['$test']>[K]\n    | ScopedFixtureFn<NonNullable<T['$test']>[K], ExtractScopedFixtures<T> & ExtraContext & TestContext>\n    | [ScopedFixtureFn<NonNullable<T['$test']>[K], ExtractScopedFixtures<T> & ExtraContext & TestContext>, TestScopeFixtureOptions?]\n} & {\n  // File fixtures - scope: 'file' is REQUIRED, NO TestContext access\n  [K in keyof NonNullable<T['$file']>]:\n  [ScopedFixtureFn<NonNullable<T['$file']>[K], (NonNullable<T['$file']> & NonNullable<T['$worker']>) & ExtraContext>, FileScopeFixtureOptions]\n} & {\n  // Worker fixtures - scope: 'worker' is REQUIRED, NO TestContext access\n  [K in keyof NonNullable<T['$worker']>]:\n  [ScopedFixtureFn<NonNullable<T['$worker']>[K], NonNullable<T['$worker']> & ExtraContext>, WorkerScopeFixtureOptions]\n}\n\nexport type InferFixturesTypes<T> = T extends TestAPI<infer C> ? C : T\n\ninterface SuiteCollectorCallable<ExtraContext = object> {\n  <OverrideExtraContext extends ExtraContext = ExtraContext>(\n    name: string | Function,\n    fn?: SuiteFactory<OverrideExtraContext>,\n    options?: number\n  ): SuiteCollector<OverrideExtraContext>\n  <OverrideExtraContext extends ExtraContext = ExtraContext>(\n    name: string | Function,\n    options: SuiteOptions,\n    fn?: SuiteFactory<OverrideExtraContext>\n  ): SuiteCollector<OverrideExtraContext>\n}\n\ntype ChainableSuiteAPI<ExtraContext = object> = ChainableFunction<\n  'concurrent' | 'sequential' | 'only' | 'skip' | 'todo' | 'shuffle',\n  SuiteCollectorCallable<ExtraContext>,\n  {\n    each: TestEachFunction\n    for: SuiteForFunction\n  }\n>\n\nexport type SuiteAPI<ExtraContext = object> = ChainableSuiteAPI<ExtraContext> & {\n  /** @internal */\n  [kChainableContext]: InternalChainableContext<TestAPI>\n  skipIf: (condition: any) => ChainableSuiteAPI<ExtraContext>\n  runIf: (condition: any) => ChainableSuiteAPI<ExtraContext>\n}\n\nexport interface BeforeAllListener<ExtraContext = object> {\n  (context: ExtraContext, suite: Readonly<Suite | File>): Awaitable<unknown>\n}\n\nexport interface AfterAllListener<ExtraContext = object> {\n  (context: ExtraContext, suite: Readonly<Suite | File>): Awaitable<unknown>\n}\n\nexport interface BeforeEachListener<ExtraContext = object> {\n  (\n    context: TestContext & ExtraContext,\n    suite: Readonly<Suite>\n  ): Awaitable<unknown>\n}\n\nexport interface AfterEachListener<ExtraContext = object> {\n  (\n    context: TestContext & ExtraContext,\n    suite: Readonly<Suite>\n  ): Awaitable<unknown>\n}\n\nexport interface AroundEachListener<ExtraContext = object> {\n  (\n    runTest: () => Promise<void>,\n    context: TestContext & ExtraContext,\n    suite: Readonly<Suite>\n  ): Awaitable<unknown>\n}\n\nexport interface AroundAllListener<ExtraContext = object> {\n  (\n    runSuite: () => Promise<void>,\n    context: ExtraContext,\n    suite: Readonly<Suite | File>\n  ): Awaitable<unknown>\n}\n\n// Contexts are provided when registered, not when invoked\nexport interface RegisteredAllListener {\n  (suite: Readonly<Suite | File>): Awaitable<unknown>\n}\n\nexport interface RegisteredAroundAllListener {\n  (\n    runSuite: () => Promise<void>,\n    suite: Readonly<Suite | File>\n  ): Awaitable<unknown>\n}\n\nexport interface SuiteHooks<ExtraContext = object> {\n  beforeAll: RegisteredAllListener[]\n  afterAll: RegisteredAllListener[]\n  aroundAll: RegisteredAroundAllListener[]\n\n  beforeEach: BeforeEachListener<ExtraContext>[]\n  afterEach: AfterEachListener<ExtraContext>[]\n  aroundEach: AroundEachListener<ExtraContext>[]\n}\n\nexport interface TaskCustomOptions extends TestOptions {\n  /**\n   * Whether the task was produced with `.each()` method.\n   */\n  each?: boolean\n  /**\n   * Task fixtures.\n   */\n  fixtures?: TestFixtures\n  /**\n   * Function that will be called when the task is executed.\n   * If nothing is provided, the runner will try to get the function using `getFn(task)`.\n   * If the runner cannot find the function, the task will be marked as failed.\n   */\n  handler?: (context: TestContext) => Awaitable<void>\n}\n\nexport interface SuiteCollector<ExtraContext = object> {\n  readonly name: string\n  readonly mode: RunMode\n  options?: SuiteOptions\n  type: 'collector'\n  test: TestAPI<ExtraContext>\n  tasks: (\n    | Suite\n    | Test<ExtraContext>\n    | SuiteCollector<ExtraContext>\n  )[]\n  file: File\n  suite?: Suite\n  task: (name: string, options?: TaskCustomOptions) => Test<ExtraContext>\n  collect: (file: File) => Promise<Suite>\n  clear: () => void\n  on: <T extends keyof SuiteHooks<ExtraContext>>(\n    name: T,\n    ...fn: SuiteHooks<ExtraContext>[T]\n  ) => void\n}\n\nexport type SuiteFactory<ExtraContext = object> = (\n  test: TestAPI<ExtraContext>,\n) => Awaitable<void>\n\nexport interface RuntimeContext {\n  tasks: (SuiteCollector | Test)[]\n  currentSuite: SuiteCollector | null\n}\n\n/**\n * User's custom test context.\n */\nexport interface TestContext {\n  /**\n   * Metadata of the current test\n   */\n  readonly task: Readonly<Test>\n\n  /**\n   * An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that will be aborted if the test times out or\n   * the test run was cancelled.\n   * @see {@link https://vitest.dev/guide/test-context#signal}\n   */\n  readonly signal: AbortSignal\n\n  /**\n   * Register a callback to run when this specific test fails.\n   * Useful when tests run concurrently.\n   * @see {@link https://vitest.dev/guide/test-context#ontestfailed}\n   */\n  readonly onTestFailed: (fn: OnTestFailedHandler, timeout?: number) => void\n\n  /**\n   * Register a callback to run when this specific test finishes.\n   * Useful when tests run concurrently.\n   * @see {@link https://vitest.dev/guide/test-context#ontestfinished}\n   */\n  readonly onTestFinished: (fn: OnTestFinishedHandler, timeout?: number) => void\n\n  /**\n   * Mark tests as skipped. All execution after this call will be skipped.\n   * This function throws an error, so make sure you are not catching it accidentally.\n   * @see {@link https://vitest.dev/guide/test-context#skip}\n   */\n  readonly skip: {\n    (note?: string): never\n    (condition: boolean, note?: string): void\n  }\n\n  /**\n   * Add a test annotation that will be displayed by your reporter.\n   * @see {@link https://vitest.dev/guide/test-context#annotate}\n   */\n  readonly annotate: {\n    (message: string, type?: string, attachment?: TestAttachment): Promise<TestAnnotation>\n    (message: string, attachment?: TestAttachment): Promise<TestAnnotation>\n  }\n}\n\nexport type OnTestFailedHandler = (context: TestContext) => Awaitable<void>\nexport type OnTestFinishedHandler = (context: TestContext) => Awaitable<void>\n\nexport interface TaskHook<HookListener> {\n  (fn: HookListener, timeout?: number): void\n}\n\nexport type SequenceHooks = 'stack' | 'list' | 'parallel'\nexport type SequenceSetupFiles = 'list' | 'parallel'\n\nexport type WriteableTestContext = {\n  -readonly [P in keyof TestContext]: TestContext[P]\n}\n\n// test artifacts\n\n/**\n * Represents a file or data attachment associated with a test artifact.\n *\n * Attachments can be either file-based (via `path`) or inline content (via `body`).\n * The `contentType` helps consumers understand how to interpret the attachment data.\n */\nexport interface TestAttachment {\n  /** MIME type of the attachment (e.g., 'image/png', 'text/plain') */\n  contentType?: string\n  /** File system path to the attachment */\n  path?: string\n  /** Inline attachment content as a string or raw binary data */\n  body?: string | Uint8Array\n}\n\nexport interface Location {\n  /** Line number in the source file (1-indexed) */\n  line: number\n  /** Column number in the line (1-indexed) */\n  column: number\n}\n\nexport interface FileLocation extends Location {\n  /** Line number in the source file (1-indexed) */\n  line: number\n  /** Column number in the line (1-indexed) */\n  column: number\n  /** Path to the source file */\n  file: string\n}\n\n/**\n * Source code location information for a test artifact.\n *\n * Indicates where in the source code the artifact originated from.\n */\nexport interface TestArtifactLocation extends FileLocation {}\n\n/**\n * @experimental\n *\n * Base interface for all test artifacts.\n *\n * Extend this interface when creating custom test artifacts. Vitest automatically manages the `attachments` array and injects the `location` property to indicate where the artifact was created in your test code.\n *\n * **Important**: when running with [`api.allowWrite`](https://vitest.dev/config/api#api-allowwrite) or [`browser.api.allowWrite`](https://vitest.dev/config/browser/api#api-allowwrite) disabled, Vitest empties the `attachments` array on every artifact before reporting it.\n */\nexport interface TestArtifactBase {\n  /** File or data attachments associated with this artifact */\n  attachments?: TestAttachment[]\n  /** Source location where this artifact was created */\n  location?: TestArtifactLocation\n}\n\n/**\n * @deprecated Use {@linkcode TestArtifactLocation} instead.\n *\n * Kept for backwards compatibility.\n */\nexport type TestAnnotationLocation = TestArtifactLocation\n\nexport interface TestAnnotation {\n  message: string\n  type: string\n  location?: TestArtifactLocation\n  attachment?: TestAttachment\n}\n\n/**\n * @experimental\n *\n * Artifact type for test annotations.\n */\nexport interface TestAnnotationArtifact extends TestArtifactBase {\n  type: 'internal:annotation'\n  annotation: TestAnnotation\n}\n\ninterface VisualRegressionArtifactAttachment extends TestAttachment {\n  name: 'reference' | 'actual' | 'diff'\n  width: number\n  height: number\n}\n\n/**\n * @experimental\n *\n * Artifact type for visual regressions.\n */\nexport interface VisualRegressionArtifact extends TestArtifactBase {\n  type: 'internal:toMatchScreenshot'\n  kind: 'visual-regression'\n  message: string\n  attachments: VisualRegressionArtifactAttachment[]\n}\n\ninterface FailureScreenshotArtifactAttachment extends TestAttachment {\n  path: string\n  /** Original file system path to the screenshot, before attachment resolution */\n  originalPath: string\n  body?: undefined\n}\n\n/**\n * @experimental\n *\n * Artifact type for failure screenshots.\n */\nexport interface FailureScreenshotArtifact extends TestArtifactBase {\n  type: 'internal:failureScreenshot'\n  attachments: [FailureScreenshotArtifactAttachment] | []\n}\n\n/**\n * @experimental\n * @advanced\n *\n * Registry for custom test artifact types.\n *\n * Augment this interface to register custom artifact types that your tests can produce.\n *\n * Each custom artifact should extend {@linkcode TestArtifactBase} and include a unique `type` discriminator property.\n *\n * @remarks\n * - Use a `Symbol` as the **registry key** to guarantee uniqueness\n * - The `type` property should follow the pattern `'package-name:artifact-name'`, `'internal:'` is a reserved prefix\n * - Use `attachments` to include files or data; extend {@linkcode TestAttachment} for custom metadata\n * - `location` property is automatically injected to indicate where the artifact was created\n *\n * @example\n *  ```ts\n * // Define custom attachment type for generated PDF\n * interface PDFAttachment extends TestAttachment {\n *   contentType: 'application/pdf'\n *   body: Uint8Array\n *   pageCount: number\n *   fileSize: number\n * }\n *\n * interface PDFGenerationArtifact extends TestArtifactBase {\n *   type: 'my-plugin:pdf-generation'\n *   templateName: string\n *   isValid: boolean\n *   attachments: [PDFAttachment]\n * }\n *\n * // Use a symbol to guarantee key uniqueness\n * const pdfKey = Symbol('pdf-generation')\n *\n * declare module 'vitest' {\n *   interface TestArtifactRegistry {\n *     [pdfKey]: PDFGenerationArtifact\n *   }\n * }\n *\n * // Custom assertion for PDF generation\n * async function toGenerateValidPDF(\n *   this: MatcherState,\n *   actual: PDFTemplate,\n *   data: Record<string, unknown>\n * ): AsyncExpectationResult {\n *   const pdfBuffer = await actual.render(data)\n *   const validation = await validatePDF(pdfBuffer)\n *\n *   await recordArtifact(this.task, {\n *     type: 'my-plugin:pdf-generation',\n *     templateName: actual.name,\n *     isValid: validation.success,\n *     attachments: [{\n *       contentType: 'application/pdf',\n *       body: pdfBuffer,\n *       pageCount: validation.pageCount,\n *       fileSize: pdfBuffer.byteLength\n *     }]\n *   })\n *\n *   return {\n *     pass: validation.success,\n *     message: () => validation.success\n *       ? `Generated valid PDF with ${validation.pageCount} pages`\n *       : `Invalid PDF: ${validation.error}`\n *   }\n * }\n * ```\n */\nexport interface TestArtifactRegistry {}\n\n/**\n * @experimental\n *\n * Union type of all test artifacts, including built-in and custom registered artifacts.\n *\n * This type automatically includes all artifacts registered via {@link TestArtifactRegistry}.\n */\nexport type TestArtifact\n  = | FailureScreenshotArtifact\n    | TestAnnotationArtifact\n    | VisualRegressionArtifact\n    | TestArtifactRegistry[keyof TestArtifactRegistry]\n"
  },
  {
    "path": "packages/runner/src/types.ts",
    "content": "export type {\n  CancelReason,\n  FileSpecification,\n  TestTagDefinition,\n  VitestRunner,\n  VitestRunnerConfig,\n  VitestRunnerConstructor,\n  VitestRunnerImportSource,\n} from './types/runner'\nexport type {\n  AfterAllListener,\n  AfterEachListener,\n  AroundAllListener,\n  AroundEachListener,\n  BeforeAllListener,\n  BeforeEachListener,\n  FailureScreenshotArtifact,\n  File,\n  Fixture,\n  FixtureFn,\n  FixtureOptions,\n  Fixtures,\n  ImportDuration,\n  InferFixturesTypes,\n  OnTestFailedHandler,\n  OnTestFinishedHandler,\n  Retry,\n  RunMode,\n  RuntimeContext,\n  SequenceHooks,\n  SequenceSetupFiles,\n  SerializableRetry,\n  Suite,\n  SuiteAPI,\n  SuiteCollector,\n  SuiteFactory,\n  SuiteHooks,\n  SuiteOptions,\n  Task,\n  TaskBase,\n  TaskCustomOptions,\n  TaskEventPack,\n  TaskHook,\n  TaskMeta,\n  TaskPopulated,\n  TaskResult,\n  TaskResultPack,\n  TaskState,\n  TaskUpdateEvent,\n  Test,\n  TestAnnotation,\n  TestAnnotationArtifact,\n  TestAnnotationLocation,\n  TestAPI,\n  TestArtifact,\n  TestArtifactBase,\n  TestArtifactLocation,\n  TestArtifactRegistry,\n  TestAttachment,\n  TestContext,\n  TestFunction,\n  TestOptions,\n  TestTags,\n  Use,\n  VisualRegressionArtifact,\n} from './types/tasks'\n"
  },
  {
    "path": "packages/runner/src/utils/chain.ts",
    "content": "import type { InternalChainableContext, SuiteAPI, TestAPI } from '../types/tasks'\n\nexport type ChainableFunction<\n  T extends string,\n  F extends (...args: any) => any,\n  C = object,\n> = F & {\n  [x in T]: ChainableFunction<T, F, C>;\n} & {\n  fn: (this: Record<T, any>, ...args: Parameters<F>) => ReturnType<F>\n} & C\n\nexport const kChainableContext: unique symbol = Symbol('kChainableContext')\n\nexport function getChainableContext(chainable: SuiteAPI): InternalChainableContext\nexport function getChainableContext(chainable: TestAPI): InternalChainableContext\nexport function getChainableContext(chainable: any): InternalChainableContext | undefined\nexport function getChainableContext(chainable: any): InternalChainableContext | undefined {\n  return chainable?.[kChainableContext]\n}\n\nexport function createChainable<T extends string, Args extends any[], R = any>(\n  keys: T[],\n  fn: (this: Record<T, any>, ...args: Args) => R,\n  context?: Record<string, any>,\n): ChainableFunction<T, (...args: Args) => R> {\n  function create(context: Record<T, any>) {\n    const chain = function (this: any, ...args: Args) {\n      return fn.apply(context, args)\n    }\n    Object.assign(chain, fn)\n    Object.defineProperty(chain, kChainableContext, {\n      value: {\n        withContext: () => chain.bind(context),\n        getFixtures: () => (context as any).fixtures,\n        setContext: (key: T, value: any) => {\n          context[key] = value\n        },\n        mergeContext: (ctx: Record<T, any>) => {\n          Object.assign(context, ctx)\n        },\n      },\n      enumerable: false,\n    })\n    for (const key of keys) {\n      Object.defineProperty(chain, key, {\n        get() {\n          return create({ ...context, [key]: true })\n        },\n      })\n    }\n    return chain\n  }\n\n  const chain = create(context ?? {} as any) as any\n  Object.defineProperty(chain, 'fn', {\n    value: fn,\n    enumerable: false,\n  })\n  return chain\n}\n"
  },
  {
    "path": "packages/runner/src/utils/collect.ts",
    "content": "import type { ParsedStack } from '@vitest/utils'\nimport type { File, Suite, TaskBase } from '../types/tasks'\nimport { processError } from '@vitest/utils/error'\nimport { parseSingleStack } from '@vitest/utils/source-map'\nimport { relative } from 'pathe'\n\n/**\n * If any tasks been marked as `only`, mark all other tasks as `skip`.\n */\nexport function interpretTaskModes(\n  file: Suite,\n  namePattern?: string | RegExp,\n  testLocations?: number[] | undefined,\n  testIds?: string[] | undefined,\n  testTagsFilter?: ((testTags: string[]) => boolean) | undefined,\n  onlyMode?: boolean,\n  parentIsOnly?: boolean,\n  allowOnly?: boolean,\n): void {\n  const matchedLocations: number[] = []\n\n  const traverseSuite = (suite: Suite, parentIsOnly?: boolean, parentMatchedWithLocation?: boolean) => {\n    const suiteIsOnly = parentIsOnly || suite.mode === 'only'\n\n    // Check if any tasks in this suite have `.only` - if so, only those should run\n    const hasSomeTasksOnly = onlyMode && suite.tasks.some(\n      t => t.mode === 'only' || (t.type === 'suite' && someTasksAreOnly(t)),\n    )\n\n    suite.tasks.forEach((t) => {\n      // Check if either the parent suite or the task itself are marked as included\n      // If there are tasks with `.only` in this suite, only include those (not all tasks from describe.only)\n      const includeTask = hasSomeTasksOnly\n        ? (t.mode === 'only' || (t.type === 'suite' && someTasksAreOnly(t)))\n        : (suiteIsOnly || t.mode === 'only')\n      if (onlyMode) {\n        if (t.type === 'suite' && (includeTask || someTasksAreOnly(t))) {\n          // Don't skip this suite\n          if (t.mode === 'only') {\n            checkAllowOnly(t, allowOnly)\n            t.mode = 'run'\n          }\n        }\n        else if (t.mode === 'run' && !includeTask) {\n          t.mode = 'skip'\n        }\n        else if (t.mode === 'only') {\n          checkAllowOnly(t, allowOnly)\n          t.mode = 'run'\n        }\n      }\n\n      let hasLocationMatch = parentMatchedWithLocation\n      // Match test location against provided locations, only run if present\n      // in `testLocations`. Note: if `includeTaskLocation` is not enabled,\n      // all test will be skipped.\n      if (testLocations !== undefined && testLocations.length !== 0) {\n        if (t.location && testLocations?.includes(t.location.line)) {\n          t.mode = 'run'\n          matchedLocations.push(t.location.line)\n          hasLocationMatch = true\n        }\n        else if (parentMatchedWithLocation) {\n          t.mode = 'run'\n        }\n        else if (t.type === 'test') {\n          t.mode = 'skip'\n        }\n      }\n\n      if (t.type === 'test') {\n        if (namePattern && !getTaskFullName(t).match(namePattern)) {\n          t.mode = 'skip'\n        }\n        if (testIds && !testIds.includes(t.id)) {\n          t.mode = 'skip'\n        }\n        if (testTagsFilter && !testTagsFilter(t.tags || [])) {\n          t.mode = 'skip'\n        }\n      }\n      else if (t.type === 'suite') {\n        if (t.mode === 'skip') {\n          skipAllTasks(t)\n        }\n        else if (t.mode === 'todo') {\n          todoAllTasks(t)\n        }\n        else {\n          traverseSuite(t, includeTask, hasLocationMatch)\n        }\n      }\n    })\n\n    // if all subtasks are skipped, mark as skip\n    if (suite.mode === 'run' || suite.mode === 'queued') {\n      if (suite.tasks.length && suite.tasks.every(i => i.mode !== 'run' && i.mode !== 'queued')) {\n        suite.mode = 'skip'\n      }\n    }\n  }\n\n  traverseSuite(file, parentIsOnly, false)\n\n  const nonMatching = testLocations?.filter(loc => !matchedLocations.includes(loc))\n  if (nonMatching && nonMatching.length !== 0) {\n    const message = nonMatching.length === 1\n      ? `line ${nonMatching[0]}`\n      : `lines ${nonMatching.join(', ')}`\n\n    if (file.result === undefined) {\n      file.result = {\n        state: 'fail',\n        errors: [],\n      }\n    }\n    if (file.result.errors === undefined) {\n      file.result.errors = []\n    }\n\n    file.result.errors.push(\n      processError(new Error(`No test found in ${file.name} in ${message}`)),\n    )\n  }\n}\n\nfunction getTaskFullName(task: TaskBase): string {\n  return `${task.suite ? `${getTaskFullName(task.suite)} ` : ''}${task.name}`\n}\n\nexport function someTasksAreOnly(suite: Suite): boolean {\n  return suite.tasks.some(\n    t => t.mode === 'only' || (t.type === 'suite' && someTasksAreOnly(t)),\n  )\n}\n\nfunction skipAllTasks(suite: Suite) {\n  suite.tasks.forEach((t) => {\n    if (t.mode === 'run' || t.mode === 'queued') {\n      t.mode = 'skip'\n      if (t.type === 'suite') {\n        skipAllTasks(t)\n      }\n    }\n  })\n}\nfunction todoAllTasks(suite: Suite) {\n  suite.tasks.forEach((t) => {\n    if (t.mode === 'run' || t.mode === 'queued') {\n      t.mode = 'todo'\n      if (t.type === 'suite') {\n        todoAllTasks(t)\n      }\n    }\n  })\n}\n\nfunction checkAllowOnly(task: TaskBase, allowOnly?: boolean) {\n  if (allowOnly) {\n    return\n  }\n  const error = processError(\n    new Error(\n      '[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error',\n    ),\n  )\n  task.result = {\n    state: 'fail',\n    errors: [error],\n  }\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function generateHash(str: string): string {\n  let hash = 0\n  if (str.length === 0) {\n    return `${hash}`\n  }\n  for (let i = 0; i < str.length; i++) {\n    const char = str.charCodeAt(i)\n    hash = (hash << 5) - hash + char\n    hash = hash & hash // Convert to 32bit integer\n  }\n  return `${hash}`\n}\n\nexport function calculateSuiteHash(parent: Suite): void {\n  parent.tasks.forEach((t, idx) => {\n    t.id = `${parent.id}_${idx}`\n    if (t.type === 'suite') {\n      calculateSuiteHash(t)\n    }\n  })\n}\n\nexport function createFileTask(\n  filepath: string,\n  root: string,\n  projectName: string | undefined,\n  pool?: string,\n  viteEnvironment?: string,\n): File {\n  const path = relative(root, filepath)\n  const file: File = {\n    id: generateFileHash(path, projectName),\n    name: path,\n    fullName: path,\n    type: 'suite',\n    mode: 'queued',\n    filepath,\n    tasks: [],\n    meta: Object.create(null),\n    projectName,\n    file: undefined!,\n    pool,\n    viteEnvironment,\n  }\n  file.file = file\n  return file\n}\n\n/**\n * Generate a unique ID for a file based on its path and project name\n * @param file File relative to the root of the project to keep ID the same between different machines\n * @param projectName The name of the test project\n */\n/* @__NO_SIDE_EFFECTS__ */\nexport function generateFileHash(\n  file: string,\n  projectName: string | undefined,\n): string {\n  return /* @__PURE__ */ generateHash(`${file}${projectName || ''}`)\n}\n\nexport function findTestFileStackTrace(testFilePath: string, error: string): ParsedStack | undefined {\n  // first line is the error message\n  const lines = error.split('\\n').slice(1)\n  for (const line of lines) {\n    const stack = parseSingleStack(line)\n    if (stack && stack.file === testFilePath) {\n      return stack\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runner/src/utils/index.ts",
    "content": "export { type ChainableFunction, createChainable } from './chain'\nexport {\n  calculateSuiteHash,\n  createFileTask,\n  findTestFileStackTrace,\n  generateFileHash,\n  generateHash,\n  interpretTaskModes,\n  someTasksAreOnly,\n} from './collect'\nexport { limitConcurrency } from './limit-concurrency'\nexport { partitionSuiteChildren } from './suite'\nexport { createTagsFilter, validateTags } from './tags'\nexport {\n  createTaskName,\n  getFullName,\n  getNames,\n  getSuites,\n  getTasks,\n  getTestName,\n  getTests,\n  hasFailed,\n  hasTests,\n  isTestCase,\n} from './tasks'\n"
  },
  {
    "path": "packages/runner/src/utils/limit-concurrency.ts",
    "content": "// A compact (code-wise, probably not memory-wise) singly linked list node.\ntype QueueNode<T> = [value: T, next?: QueueNode<T>]\n\nexport interface ConcurrencyLimiter extends ConcurrencyLimiterFn {\n  acquire: () => (() => void) | Promise<() => void>\n}\n\ntype ConcurrencyLimiterFn = <Args extends unknown[], T>(func: (...args: Args) => PromiseLike<T> | T, ...args: Args) => Promise<T>\n\n/**\n * Return a function for running multiple async operations with limited concurrency.\n */\nexport function limitConcurrency(concurrency: number = Infinity): ConcurrencyLimiter {\n  // The number of currently active + pending tasks.\n  let count = 0\n\n  // The head and tail of the pending task queue, built using a singly linked list.\n  // Both head and tail are initially undefined, signifying an empty queue.\n  // They both become undefined again whenever there are no pending tasks.\n  let head: undefined | QueueNode<() => void>\n  let tail: undefined | QueueNode<() => void>\n\n  // A bookkeeping function executed whenever a task has been run to completion.\n  const finish = () => {\n    count--\n\n    // Check if there are further pending tasks in the queue.\n    if (head) {\n      // Allow the next pending task to run and pop it from the queue.\n      head[0]()\n      head = head[1]\n\n      // The head may now be undefined if there are no further pending tasks.\n      // In that case, set tail to undefined as well.\n      tail = head && tail\n    }\n  }\n\n  const acquire = () => {\n    let released = false\n    const release = () => {\n      if (!released) {\n        released = true\n        finish()\n      }\n    }\n\n    if (count++ < concurrency) {\n      return release\n    }\n\n    return new Promise<() => void>((resolve) => {\n      if (tail) {\n        // There are pending tasks, so append to the queue.\n        tail = tail[1] = [() => resolve(release)]\n      }\n      else {\n        // No other pending tasks, initialize the queue with a new tail and head.\n        head = tail = [() => resolve(release)]\n      }\n    })\n  }\n\n  const limiterFn: ConcurrencyLimiterFn = (func, ...args) => {\n    function run(release: () => void) {\n      try {\n        const result = func(...args)\n        if (result instanceof Promise) {\n          return result.finally(release)\n        }\n        release()\n        return Promise.resolve(result)\n      }\n      catch (error) {\n        release()\n        return Promise.reject(error)\n      }\n    }\n\n    const release = acquire()\n    return release instanceof Promise ? release.then(run) : run(release)\n  }\n\n  return Object.assign(limiterFn, { acquire })\n}\n"
  },
  {
    "path": "packages/runner/src/utils/suite.ts",
    "content": "import type { Suite, Task } from '../types/tasks'\n\n/**\n * Partition in tasks groups by consecutive concurrent\n */\nexport function partitionSuiteChildren(suite: Suite): Task[][] {\n  let tasksGroup: Task[] = []\n  const tasksGroups: Task[][] = []\n  for (const c of suite.tasks) {\n    if (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {\n      tasksGroup.push(c)\n    }\n    else {\n      tasksGroups.push(tasksGroup)\n      tasksGroup = [c]\n    }\n  }\n  if (tasksGroup.length > 0) {\n    tasksGroups.push(tasksGroup)\n  }\n\n  return tasksGroups\n}\n"
  },
  {
    "path": "packages/runner/src/utils/tags.ts",
    "content": "import type { TestTagDefinition, VitestRunnerConfig } from '../types/runner'\n\nexport function validateTags(config: VitestRunnerConfig, tags: string[]): void {\n  if (!config.strictTags) {\n    return\n  }\n\n  const availableTags = new Set(config.tags.map(tag => tag.name))\n  for (const tag of tags) {\n    if (!availableTags.has(tag)) {\n      throw createNoTagsError(config.tags, tag)\n    }\n  }\n}\n\nexport function createNoTagsError(availableTags: TestTagDefinition[], tag: string, prefix = 'tag'): never {\n  if (!availableTags.length) {\n    throw new Error(`The Vitest config does't define any \"tags\", cannot apply \"${tag}\" ${prefix} for this test. See: https://vitest.dev/guide/test-tags`)\n  }\n  throw new Error(`The ${prefix} \"${tag}\" is not defined in the configuration. Available tags are:\\n${availableTags\n    .map(t => `- ${t.name}${t.description ? `: ${t.description}` : ''}`)\n    .join('\\n')}`)\n}\n\nexport function createTagsFilter(tagsExpr: string[], availableTags: TestTagDefinition[]): (testTags: string[]) => boolean {\n  const matchers = tagsExpr.map(expr => parseTagsExpression(expr, availableTags))\n  return (testTags: string[]) => {\n    return matchers.every(matcher => matcher(testTags))\n  }\n}\n\ntype TagMatcher = (tags: string[]) => boolean\n\nfunction parseTagsExpression(expr: string, availableTags: TestTagDefinition[]): TagMatcher {\n  const tokens = tokenize(expr)\n  const stream = new TokenStream(tokens, expr)\n  const ast = parseOrExpression(stream, availableTags)\n  if (stream.peek().type !== 'EOF') {\n    throw new Error(`Invalid tags expression: unexpected \"${formatToken(stream.peek())}\" in \"${expr}\"`)\n  }\n  return (tags: string[]) => evaluateNode(ast, tags)\n}\n\nfunction formatToken(token: Token): string {\n  switch (token.type) {\n    case 'TAG': return token.value\n    default: return formatTokenType(token.type)\n  }\n}\n\ntype Token\n  = | { type: 'TAG'; value: string }\n    | { type: 'AND' }\n    | { type: 'OR' }\n    | { type: 'NOT' }\n    | { type: 'LPAREN' }\n    | { type: 'RPAREN' }\n    | { type: 'EOF' }\n\nfunction tokenize(expr: string): Token[] {\n  const tokens: Token[] = []\n  let i = 0\n\n  while (i < expr.length) {\n    if (expr[i] === ' ' || expr[i] === '\\t') {\n      i++\n      continue\n    }\n\n    if (expr[i] === '(') {\n      tokens.push({ type: 'LPAREN' })\n      i++\n      continue\n    }\n\n    if (expr[i] === ')') {\n      tokens.push({ type: 'RPAREN' })\n      i++\n      continue\n    }\n\n    if (expr[i] === '!') {\n      tokens.push({ type: 'NOT' })\n      i++\n      continue\n    }\n\n    if (expr.slice(i, i + 2) === '&&') {\n      tokens.push({ type: 'AND' })\n      i += 2\n      continue\n    }\n\n    if (expr.slice(i, i + 2) === '||') {\n      tokens.push({ type: 'OR' })\n      i += 2\n      continue\n    }\n\n    if (/^and(?:\\s|\\)|$)/i.test(expr.slice(i))) {\n      tokens.push({ type: 'AND' })\n      i += 3\n      continue\n    }\n\n    if (/^or(?:\\s|\\)|$)/i.test(expr.slice(i))) {\n      tokens.push({ type: 'OR' })\n      i += 2\n      continue\n    }\n\n    if (/^not\\s/i.test(expr.slice(i))) {\n      tokens.push({ type: 'NOT' })\n      i += 3\n      continue\n    }\n\n    let tag = ''\n    while (i < expr.length && expr[i] !== ' ' && expr[i] !== '\\t' && expr[i] !== '(' && expr[i] !== ')' && expr[i] !== '!' && expr[i] !== '&' && expr[i] !== '|') {\n      const remaining = expr.slice(i)\n      // Only treat and/or/not as operators if we're at the start of a tag (after whitespace)\n      // This allows tags like \"demand\", \"editor\", \"cannot\" to work correctly\n      if (tag === '' && (/^and(?:\\s|\\)|$)/i.test(remaining) || /^or(?:\\s|\\)|$)/i.test(remaining) || /^not\\s/i.test(remaining))) {\n        break\n      }\n      tag += expr[i]\n      i++\n    }\n\n    if (tag) {\n      tokens.push({ type: 'TAG', value: tag })\n    }\n  }\n\n  tokens.push({ type: 'EOF' })\n  return tokens\n}\n\ntype ASTNode\n  = | { type: 'tag'; value: string; pattern: RegExp | null }\n    | { type: 'not'; operand: ASTNode }\n    | { type: 'and'; left: ASTNode; right: ASTNode }\n    | { type: 'or'; left: ASTNode; right: ASTNode }\n\nclass TokenStream {\n  private pos = 0\n  constructor(private tokens: Token[], public expr: string) {}\n\n  peek(): Token {\n    return this.tokens[this.pos]\n  }\n\n  next(): Token {\n    return this.tokens[this.pos++]\n  }\n\n  expect(type: Token['type']): Token {\n    const token = this.next()\n    if (token.type !== type) {\n      if (type === 'RPAREN' && token.type === 'EOF') {\n        throw new Error(`Invalid tags expression: missing closing \")\" in \"${this.expr}\"`)\n      }\n      throw new Error(`Invalid tags expression: expected \"${formatTokenType(type)}\" but got \"${formatToken(token)}\" in \"${this.expr}\"`)\n    }\n    return token\n  }\n\n  unexpectedToken(): never {\n    const token = this.peek()\n    if (token.type === 'EOF') {\n      throw new Error(`Invalid tags expression: unexpected end of expression in \"${this.expr}\"`)\n    }\n    throw new Error(`Invalid tags expression: unexpected \"${formatToken(token)}\" in \"${this.expr}\"`)\n  }\n}\n\nfunction formatTokenType(type: Token['type']): string {\n  switch (type) {\n    case 'TAG': return 'tag'\n    case 'AND': return 'and'\n    case 'OR': return 'or'\n    case 'NOT': return 'not'\n    case 'LPAREN': return '('\n    case 'RPAREN': return ')'\n    case 'EOF': return 'end of expression'\n  }\n}\n\nfunction parseOrExpression(stream: TokenStream, availableTags: TestTagDefinition[]): ASTNode {\n  let left = parseAndExpression(stream, availableTags)\n\n  while (stream.peek().type === 'OR') {\n    stream.next()\n    const right = parseAndExpression(stream, availableTags)\n    left = { type: 'or', left, right }\n  }\n\n  return left\n}\n\nfunction parseAndExpression(stream: TokenStream, availableTags: TestTagDefinition[]): ASTNode {\n  let left = parseUnaryExpression(stream, availableTags)\n\n  while (stream.peek().type === 'AND') {\n    stream.next()\n    const right = parseUnaryExpression(stream, availableTags)\n    left = { type: 'and', left, right }\n  }\n\n  return left\n}\n\nfunction parseUnaryExpression(stream: TokenStream, availableTags: TestTagDefinition[]): ASTNode {\n  if (stream.peek().type === 'NOT') {\n    stream.next()\n    const operand = parseUnaryExpression(stream, availableTags)\n    return { type: 'not', operand }\n  }\n\n  return parsePrimaryExpression(stream, availableTags)\n}\n\nfunction parsePrimaryExpression(stream: TokenStream, availableTags: TestTagDefinition[]): ASTNode {\n  const token = stream.peek()\n\n  if (token.type === 'LPAREN') {\n    stream.next()\n    const expr = parseOrExpression(stream, availableTags)\n    stream.expect('RPAREN')\n    return expr\n  }\n\n  if (token.type === 'TAG') {\n    stream.next()\n    const tagValue = token.value\n    const pattern = resolveTagPattern(tagValue, availableTags)\n    return { type: 'tag', value: tagValue, pattern }\n  }\n\n  stream.unexpectedToken()\n}\n\nfunction createWildcardRegex(pattern: string): RegExp {\n  return new RegExp(`^${pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*')}$`)\n}\n\nfunction resolveTagPattern(tagPattern: string, availableTags: TestTagDefinition[]): RegExp | null {\n  if (tagPattern.includes('*')) {\n    const regex = createWildcardRegex(tagPattern)\n    const hasMatch = availableTags.some(tag => regex.test(tag.name))\n    if (!hasMatch) {\n      throw createNoTagsError(availableTags, tagPattern, 'tag pattern')\n    }\n    return regex\n  }\n\n  if (!availableTags.length || !availableTags.some(tag => tag.name === tagPattern)) {\n    throw createNoTagsError(availableTags, tagPattern, 'tag pattern')\n  }\n  return null\n}\n\nfunction evaluateNode(node: ASTNode, tags: string[]): boolean {\n  switch (node.type) {\n    case 'tag':\n      if (node.pattern) {\n        return tags.some(tag => node.pattern!.test(tag))\n      }\n      return tags.includes(node.value)\n    case 'not':\n      return !evaluateNode(node.operand, tags)\n    case 'and':\n      return evaluateNode(node.left, tags) && evaluateNode(node.right, tags)\n    case 'or':\n      return evaluateNode(node.left, tags) || evaluateNode(node.right, tags)\n  }\n}\n"
  },
  {
    "path": "packages/runner/src/utils/tasks.ts",
    "content": "import type { Arrayable } from '@vitest/utils'\nimport type { Suite, Task, Test } from '../types/tasks'\nimport { toArray } from '@vitest/utils/helpers'\n\nexport function isTestCase(s: Task): s is Test {\n  return s.type === 'test'\n}\n\nexport function getTests(suite: Arrayable<Task>): Test[] {\n  const tests: Test[] = []\n  const arraySuites = toArray(suite)\n  for (const s of arraySuites) {\n    if (isTestCase(s)) {\n      tests.push(s)\n    }\n    else {\n      for (const task of s.tasks) {\n        if (isTestCase(task)) {\n          tests.push(task)\n        }\n        else {\n          const taskTests = getTests(task)\n          for (const test of taskTests) {\n            tests.push(test)\n          }\n        }\n      }\n    }\n  }\n  return tests\n}\n\nexport function getTasks(tasks: Arrayable<Task> = []): Task[] {\n  return toArray(tasks).flatMap(s =>\n    isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)],\n  )\n}\n\nexport function getSuites(suite: Arrayable<Task>): Suite[] {\n  return toArray(suite).flatMap(s =>\n    s.type === 'suite' ? [s, ...getSuites(s.tasks)] : [],\n  )\n}\n\nexport function hasTests(suite: Arrayable<Suite>): boolean {\n  return toArray(suite).some(s =>\n    s.tasks.some(c => isTestCase(c) || hasTests(c)),\n  )\n}\n\nexport function hasFailed(suite: Arrayable<Task>): boolean {\n  return toArray(suite).some(\n    s =>\n      s.result?.state === 'fail' || (s.type === 'suite' && hasFailed(s.tasks)),\n  )\n}\n\nexport function getNames(task: Task): string[] {\n  const names = [task.name]\n  let current: Task | undefined = task\n\n  while (current?.suite) {\n    current = current.suite\n    if (current?.name) {\n      names.unshift(current.name)\n    }\n  }\n\n  if (current !== task.file) {\n    names.unshift(task.file.name)\n  }\n\n  return names\n}\n\nexport function getFullName(task: Task, separator = ' > '): string {\n  return getNames(task).join(separator)\n}\n\nexport function getTestName(task: Task, separator = ' > '): string {\n  return getNames(task).slice(1).join(separator)\n}\n\nexport function createTaskName(names: readonly (string | undefined)[], separator = ' > '): string {\n  return names.filter(name => name !== undefined).join(separator)\n}\n"
  },
  {
    "path": "packages/runner/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"./dist\"]\n}\n"
  },
  {
    "path": "packages/runner/types.d.ts",
    "content": "export * from './dist/types.js'\n"
  },
  {
    "path": "packages/runner/utils.d.ts",
    "content": "export * from './dist/utils.js'\n"
  },
  {
    "path": "packages/snapshot/README.md",
    "content": "# @vitest/snapshot\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/snapshot?color=a1b858&label=)](https://npmx.dev/package/@vitest/snapshot)\n\nLightweight implementation of Jest's snapshots.\n\n## Usage\n\n```js\nimport { SnapshotClient } from '@vitest/snapshot'\nimport { NodeSnapshotEnvironment } from '@vitest/snapshot/environment'\nimport { SnapshotManager } from '@vitest/snapshot/manager'\n\nconst client = new SnapshotClient({\n  // you need to provide your own equality check implementation if you use it\n  // this function is called when `.toMatchSnapshot({ property: 1 })` is called\n  isEqual: (received, expected) =>\n    equals(received, expected, [iterableEquality, subsetEquality]),\n})\n\n// class that implements snapshot saving and reading\n// by default uses fs module, but you can provide your own implementation depending on the environment\nconst environment = new NodeSnapshotEnvironment()\n\n// you need to implement this yourselves,\n// this depends on your runner\nfunction getCurrentFilepath() {\n  return '/file.spec.js'\n}\nfunction getCurrentTestName() {\n  return 'test1'\n}\n\n// example for inline snapshots, nothing is required to support regular snapshots,\n// just call `assert` with `isInline: false`\nfunction wrapper(received) {\n  function __INLINE_SNAPSHOT__(inlineSnapshot, message) {\n    client.assert({\n      received,\n      message,\n      isInline: true,\n      inlineSnapshot,\n      filepath: getCurrentFilepath(),\n      name: getCurrentTestName(),\n    })\n  }\n  return {\n    // the name is hard-coded, it should be inside another function, so Vitest can find the actual test file where it was called (parses call stack trace + 2)\n    // you can override this behaviour in SnapshotState's `_inferInlineSnapshotStack` method by providing your own SnapshotState to SnapshotClient constructor\n    toMatchInlineSnapshot: (...args) => __INLINE_SNAPSHOT__(...args),\n  }\n}\n\nconst options = {\n  updateSnapshot: 'new',\n  snapshotEnvironment: environment,\n}\n\nawait client.startCurrentRun(\n  getCurrentFilepath(),\n  getCurrentTestName(),\n  options\n)\n\n// this will save snapshot to a file which is returned by \"snapshotEnvironment.resolvePath\"\nclient.assert({\n  received: 'some text',\n  isInline: false,\n})\n\n// uses \"pretty-format\", so it requires quotes\n// also naming is hard-coded when parsing test files\nwrapper('text 1').toMatchInlineSnapshot()\nwrapper('text 2').toMatchInlineSnapshot('\"text 2\"')\n\nconst result = await client.finishCurrentRun() // this saves files and returns SnapshotResult\n\n// you can use manager to manage several clients\nconst manager = new SnapshotManager(options)\nmanager.add(result)\n\n// do something\n// and then read the summary\n\nconsole.log(manager.summary)\n```\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/snapshot) | [Documentation](https://vitest.dev/guide/snapshot)\n"
  },
  {
    "path": "packages/snapshot/environment.d.ts",
    "content": "export * from './dist/environment.js'\n"
  },
  {
    "path": "packages/snapshot/manager.d.ts",
    "content": "export * from './dist/manager.js'\n"
  },
  {
    "path": "packages/snapshot/package.json",
    "content": "{\n  \"name\": \"@vitest/snapshot\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Vitest snapshot manager\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/guide/snapshot\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/snapshot\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vitest\",\n    \"test\",\n    \"snapshot\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./environment\": {\n      \"types\": \"./dist/environment.d.ts\",\n      \"default\": \"./dist/environment.js\"\n    },\n    \"./manager\": {\n      \"types\": \"./dist/manager.d.ts\",\n      \"default\": \"./dist/manager.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"*.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch\"\n  },\n  \"dependencies\": {\n    \"@vitest/pretty-format\": \"workspace:*\",\n    \"@vitest/utils\": \"workspace:*\",\n    \"magic-string\": \"catalog:\",\n    \"pathe\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@types/natural-compare\": \"^1.4.3\",\n    \"natural-compare\": \"^1.4.0\"\n  }\n}\n"
  },
  {
    "path": "packages/snapshot/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport nodeResolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^@?vitest(\\/|$)/,\n]\n\nconst entries = {\n  index: 'src/index.ts',\n  environment: 'src/environment.ts',\n  manager: 'src/manager.ts',\n}\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  nodeResolve({\n    preferBuiltins: true,\n  }),\n  commonjs(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nexport default defineConfig([\n  {\n    input: entries,\n    output: {\n      dir: 'dist',\n      format: 'esm',\n      entryFileNames: '[name].js',\n      chunkFileNames: 'chunk-[name].js',\n    },\n    external,\n    plugins,\n    onwarn,\n  },\n  {\n    input: dtsUtils.dtsInput(entries),\n    output: {\n      dir: 'dist',\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n    onwarn,\n  },\n])\n\nfunction onwarn(message) {\n  if (['EMPTY_BUNDLE', 'CIRCULAR_DEPENDENCY'].includes(message.code)) {\n    return\n  }\n  console.error(message)\n}\n"
  },
  {
    "path": "packages/snapshot/src/client.ts",
    "content": "import type { RawSnapshotInfo } from './port/rawSnapshot'\nimport type { SnapshotResult, SnapshotStateOptions } from './types'\nimport SnapshotState from './port/state'\nimport { deepMergeSnapshot } from './port/utils'\n\nfunction createMismatchError(\n  message: string,\n  expand: boolean | undefined,\n  actual: unknown,\n  expected: unknown,\n) {\n  const error = new Error(message)\n  Object.defineProperty(error, 'actual', {\n    value: actual,\n    enumerable: true,\n    configurable: true,\n    writable: true,\n  })\n  Object.defineProperty(error, 'expected', {\n    value: expected,\n    enumerable: true,\n    configurable: true,\n    writable: true,\n  })\n  Object.defineProperty(error, 'diffOptions', { value: { expand } })\n  return error\n}\n\nexport interface Context {\n  file: string\n  title?: string\n  fullTitle?: string\n}\n\ninterface AssertOptions {\n  received: unknown\n  filepath: string\n  name: string\n  /**\n   * Not required but needed for `SnapshotClient.clearTest` to implement test-retry behavior.\n   * @default name\n   */\n  testId?: string\n  message?: string\n  isInline?: boolean\n  properties?: object\n  inlineSnapshot?: string\n  error?: Error\n  errorMessage?: string\n  rawSnapshot?: RawSnapshotInfo\n}\n\nexport interface SnapshotClientOptions {\n  isEqual?: (received: unknown, expected: unknown) => boolean\n}\n\nexport class SnapshotClient {\n  snapshotStateMap: Map<string, SnapshotState> = new Map()\n\n  constructor(private options: SnapshotClientOptions = {}) {}\n\n  async setup(\n    filepath: string,\n    options: SnapshotStateOptions,\n  ): Promise<void> {\n    if (this.snapshotStateMap.has(filepath)) {\n      return\n    }\n    this.snapshotStateMap.set(\n      filepath,\n      await SnapshotState.create(filepath, options),\n    )\n  }\n\n  async finish(filepath: string): Promise<SnapshotResult> {\n    const state = this.getSnapshotState(filepath)\n    const result = await state.pack()\n    this.snapshotStateMap.delete(filepath)\n    return result\n  }\n\n  skipTest(filepath: string, testName: string): void {\n    const state = this.getSnapshotState(filepath)\n    state.markSnapshotsAsCheckedForTest(testName)\n  }\n\n  clearTest(filepath: string, testId: string): void {\n    const state = this.getSnapshotState(filepath)\n    state.clearTest(testId)\n  }\n\n  getSnapshotState(filepath: string): SnapshotState {\n    const state = this.snapshotStateMap.get(filepath)\n    if (!state) {\n      throw new Error(\n        `The snapshot state for '${filepath}' is not found. Did you call 'SnapshotClient.setup()'?`,\n      )\n    }\n    return state\n  }\n\n  assert(options: AssertOptions): void {\n    const {\n      filepath,\n      name,\n      testId = name,\n      message,\n      isInline = false,\n      properties,\n      inlineSnapshot,\n      error,\n      errorMessage,\n      rawSnapshot,\n    } = options\n    let { received } = options\n\n    if (!filepath) {\n      throw new Error('Snapshot cannot be used outside of test')\n    }\n\n    const snapshotState = this.getSnapshotState(filepath)\n\n    if (typeof properties === 'object') {\n      if (typeof received !== 'object' || !received) {\n        throw new Error(\n          'Received value must be an object when the matcher has properties',\n        )\n      }\n\n      try {\n        const pass = this.options.isEqual?.(received, properties) ?? false\n        // const pass = equals(received, properties, [iterableEquality, subsetEquality])\n        if (!pass) {\n          throw createMismatchError(\n            'Snapshot properties mismatched',\n            snapshotState.expand,\n            received,\n            properties,\n          )\n        }\n        else {\n          received = deepMergeSnapshot(received, properties)\n        }\n      }\n      catch (err: any) {\n        err.message = errorMessage || 'Snapshot mismatched'\n        throw err\n      }\n    }\n\n    const testName = [name, ...(message ? [message] : [])].join(' > ')\n\n    const { actual, expected, key, pass } = snapshotState.match({\n      testId,\n      testName,\n      received,\n      isInline,\n      error,\n      inlineSnapshot,\n      rawSnapshot,\n    })\n\n    if (!pass) {\n      throw createMismatchError(\n        `Snapshot \\`${key || 'unknown'}\\` mismatched`,\n        snapshotState.expand,\n        rawSnapshot ? actual : actual?.trim(),\n        rawSnapshot ? expected : expected?.trim(),\n      )\n    }\n  }\n\n  async assertRaw(options: AssertOptions): Promise<void> {\n    if (!options.rawSnapshot) {\n      throw new Error('Raw snapshot is required')\n    }\n\n    const { filepath, rawSnapshot } = options\n\n    if (rawSnapshot.content == null) {\n      if (!filepath) {\n        throw new Error('Snapshot cannot be used outside of test')\n      }\n\n      const snapshotState = this.getSnapshotState(filepath)\n\n      // save the filepath, so it don't lose even if the await make it out-of-context\n      options.filepath ||= filepath\n      // resolve and read the raw snapshot file\n      rawSnapshot.file = await snapshotState.environment.resolveRawPath(\n        filepath,\n        rawSnapshot.file,\n      )\n      rawSnapshot.content\n        = (await snapshotState.environment.readSnapshotFile(rawSnapshot.file))\n          ?? undefined\n    }\n\n    return this.assert(options)\n  }\n\n  clear(): void {\n    this.snapshotStateMap.clear()\n  }\n}\n"
  },
  {
    "path": "packages/snapshot/src/env/node.ts",
    "content": "import type { SnapshotEnvironment, SnapshotEnvironmentOptions } from '../types'\nimport { existsSync, promises as fs } from 'node:fs'\nimport { basename, dirname, isAbsolute, join, resolve } from 'pathe'\n\nexport class NodeSnapshotEnvironment implements SnapshotEnvironment {\n  constructor(private options: SnapshotEnvironmentOptions = {}) {}\n\n  getVersion(): string {\n    return '1'\n  }\n\n  getHeader(): string {\n    return `// Snapshot v${this.getVersion()}`\n  }\n\n  async resolveRawPath(testPath: string, rawPath: string): Promise<string> {\n    return isAbsolute(rawPath) ? rawPath : resolve(dirname(testPath), rawPath)\n  }\n\n  async resolvePath(filepath: string): Promise<string> {\n    return join(\n      join(dirname(filepath), this.options.snapshotsDirName ?? '__snapshots__'),\n      `${basename(filepath)}.snap`,\n    )\n  }\n\n  async prepareDirectory(dirPath: string): Promise<void> {\n    await fs.mkdir(dirPath, { recursive: true })\n  }\n\n  async saveSnapshotFile(filepath: string, snapshot: string): Promise<void> {\n    await fs.mkdir(dirname(filepath), { recursive: true })\n    await fs.writeFile(filepath, snapshot, 'utf-8')\n  }\n\n  async readSnapshotFile(filepath: string): Promise<string | null> {\n    if (!existsSync(filepath)) {\n      return null\n    }\n    return fs.readFile(filepath, 'utf-8')\n  }\n\n  async removeSnapshotFile(filepath: string): Promise<void> {\n    if (existsSync(filepath)) {\n      await fs.unlink(filepath)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/snapshot/src/environment.ts",
    "content": "export { NodeSnapshotEnvironment } from './env/node'\nexport type { SnapshotEnvironment } from './types/environment'\n"
  },
  {
    "path": "packages/snapshot/src/index.ts",
    "content": "export { SnapshotClient } from './client'\n\nexport { stripSnapshotIndentation } from './port/inlineSnapshot'\nexport { addSerializer, getSerializers } from './port/plugins'\nexport { default as SnapshotState } from './port/state'\n\nexport type {\n  SnapshotData,\n  SnapshotEnvironment,\n  SnapshotMatchOptions,\n  SnapshotResult,\n  SnapshotSerializer,\n  SnapshotStateOptions,\n  SnapshotSummary,\n  SnapshotUpdateState,\n  UncheckedSnapshot,\n} from './types'\n"
  },
  {
    "path": "packages/snapshot/src/manager.ts",
    "content": "import type {\n  SnapshotResult,\n  SnapshotStateOptions,\n  SnapshotSummary,\n} from './types'\nimport { basename, dirname, isAbsolute, join, resolve } from 'pathe'\n\nexport class SnapshotManager {\n  public summary!: SnapshotSummary\n  public extension = '.snap'\n\n  constructor(\n    public options: Omit<SnapshotStateOptions, 'snapshotEnvironment'>,\n  ) {\n    this.clear()\n  }\n\n  clear(): void {\n    this.summary = emptySummary(this.options)\n  }\n\n  add(result: SnapshotResult): void {\n    addSnapshotResult(this.summary, result)\n  }\n\n  resolvePath<T = any>(testPath: string, context?: T): string {\n    const resolver\n      = this.options.resolveSnapshotPath || (() => {\n        return join(\n          join(dirname(testPath), '__snapshots__'),\n          `${basename(testPath)}${this.extension}`,\n        )\n      })\n\n    const path = resolver(testPath, this.extension, context)\n    return path\n  }\n\n  resolveRawPath(testPath: string, rawPath: string): string {\n    return isAbsolute(rawPath) ? rawPath : resolve(dirname(testPath), rawPath)\n  }\n}\n\nexport function emptySummary(\n  options: Omit<SnapshotStateOptions, 'snapshotEnvironment'>,\n): SnapshotSummary {\n  const summary = {\n    added: 0,\n    failure: false,\n    filesAdded: 0,\n    filesRemoved: 0,\n    filesRemovedList: [],\n    filesUnmatched: 0,\n    filesUpdated: 0,\n    matched: 0,\n    total: 0,\n    unchecked: 0,\n    uncheckedKeysByFile: [],\n    unmatched: 0,\n    updated: 0,\n    didUpdate: options.updateSnapshot === 'all',\n  }\n  return summary\n}\n\nexport function addSnapshotResult(\n  summary: SnapshotSummary,\n  result: SnapshotResult,\n): void {\n  if (result.added) {\n    summary.filesAdded++\n  }\n  if (result.fileDeleted) {\n    summary.filesRemoved++\n  }\n  if (result.unmatched) {\n    summary.filesUnmatched++\n  }\n  if (result.updated) {\n    summary.filesUpdated++\n  }\n\n  summary.added += result.added\n  summary.matched += result.matched\n  summary.unchecked += result.unchecked\n  if (result.uncheckedKeys && result.uncheckedKeys.length > 0) {\n    summary.uncheckedKeysByFile.push({\n      filePath: result.filepath,\n      keys: result.uncheckedKeys,\n    })\n  }\n\n  summary.unmatched += result.unmatched\n  summary.updated += result.updated\n  summary.total\n    += result.added + result.matched + result.unmatched + result.updated\n}\n"
  },
  {
    "path": "packages/snapshot/src/port/inlineSnapshot.ts",
    "content": "import type MagicString from 'magic-string'\nimport type { SnapshotEnvironment } from '../types'\nimport { getCallLastIndex } from '@vitest/utils/helpers'\nimport {\n  lineSplitRE,\n  offsetToLineNumber,\n  positionToOffset,\n} from '@vitest/utils/offset'\n\nexport interface InlineSnapshot {\n  snapshot: string\n  testId: string\n  file: string\n  line: number\n  column: number\n}\n\nexport async function saveInlineSnapshots(\n  environment: SnapshotEnvironment,\n  snapshots: Array<InlineSnapshot>,\n): Promise<void> {\n  const MagicString = (await import('magic-string')).default\n  const files = new Set(snapshots.map(i => i.file))\n  await Promise.all(\n    Array.from(files).map(async (file) => {\n      const snaps = snapshots.filter(i => i.file === file)\n      const code = await environment.readSnapshotFile(file)\n      if (code == null) {\n        throw new Error(`cannot read ${file} when saving inline snapshot`)\n      }\n\n      const s = new MagicString(code)\n\n      for (const snap of snaps) {\n        const index = positionToOffset(code, snap.line, snap.column)\n        replaceInlineSnap(code, s, index, snap.snapshot)\n      }\n\n      const transformed = s.toString()\n      if (transformed !== code) {\n        await environment.saveSnapshotFile(file, transformed)\n      }\n    }),\n  )\n}\n\nconst startObjectRegex\n  = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\\s*\\(\\s*(?:\\/\\*[\\s\\S]*\\*\\/\\s*|\\/\\/.*(?:[\\n\\r\\u2028\\u2029]\\s*|[\\t\\v\\f \\xA0\\u1680\\u2000-\\u200A\\u202F\\u205F\\u3000\\uFEFF]))*\\{/\n\nfunction replaceObjectSnap(\n  code: string,\n  s: MagicString,\n  index: number,\n  newSnap: string,\n) {\n  let _code = code.slice(index)\n  const startMatch = startObjectRegex.exec(_code)\n  if (!startMatch) {\n    return false\n  }\n\n  _code = _code.slice(startMatch.index)\n\n  let callEnd = getCallLastIndex(_code)\n  if (callEnd === null) {\n    return false\n  }\n  callEnd += index + startMatch.index\n\n  const shapeStart = index + startMatch.index + startMatch[0].length\n  const shapeEnd = getObjectShapeEndIndex(code, shapeStart)\n  const snap = `, ${prepareSnapString(newSnap, code, index)}`\n\n  if (shapeEnd === callEnd) {\n    // toMatchInlineSnapshot({ foo: expect.any(String) })\n    s.appendLeft(callEnd, snap)\n  }\n  else {\n    // toMatchInlineSnapshot({ foo: expect.any(String) }, ``)\n    s.overwrite(shapeEnd, callEnd, snap)\n  }\n\n  return true\n}\n\nfunction getObjectShapeEndIndex(code: string, index: number) {\n  let startBraces = 1\n  let endBraces = 0\n  while (startBraces !== endBraces && index < code.length) {\n    const s = code[index++]\n    if (s === '{') {\n      startBraces++\n    }\n    else if (s === '}') {\n      endBraces++\n    }\n  }\n  return index\n}\n\nfunction prepareSnapString(snap: string, source: string, index: number) {\n  const lineNumber = offsetToLineNumber(source, index)\n  const line = source.split(lineSplitRE)[lineNumber - 1]\n  const indent = line.match(/^\\s*/)![0] || ''\n  const indentNext = indent.includes('\\t') ? `${indent}\\t` : `${indent}  `\n\n  const lines = snap.trim().replace(/\\\\/g, '\\\\\\\\').split(/\\n/g)\n\n  const isOneline = lines.length <= 1\n  const quote = '`'\n  if (isOneline) {\n    return `${quote}${lines\n      .join('\\n')\n      .replace(/`/g, '\\\\`')\n      .replace(/\\$\\{/g, '\\\\${')}${quote}`\n  }\n  return `${quote}\\n${lines\n    .map(i => (i ? indentNext + i : ''))\n    .join('\\n')\n    .replace(/`/g, '\\\\`')\n    .replace(/\\$\\{/g, '\\\\${')}\\n${indent}${quote}`\n}\n\nconst toMatchInlineName = 'toMatchInlineSnapshot'\nconst toThrowErrorMatchingInlineName = 'toThrowErrorMatchingInlineSnapshot'\n\n// on webkit, the line number is at the end of the method, not at the start\nfunction getCodeStartingAtIndex(code: string, index: number) {\n  const indexInline = index - toMatchInlineName.length\n  if (code.slice(indexInline, index) === toMatchInlineName) {\n    return {\n      code: code.slice(indexInline),\n      index: indexInline,\n    }\n  }\n  const indexThrowInline = index - toThrowErrorMatchingInlineName.length\n  if (code.slice(index - indexThrowInline, index) === toThrowErrorMatchingInlineName) {\n    return {\n      code: code.slice(index - indexThrowInline),\n      index: index - indexThrowInline,\n    }\n  }\n  return {\n    code: code.slice(index),\n    index,\n  }\n}\n\nconst startRegex\n  = /(?:toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot)\\s*\\(\\s*(?:\\/\\*[\\s\\S]*\\*\\/\\s*|\\/\\/.*(?:[\\n\\r\\u2028\\u2029]\\s*|[\\t\\v\\f \\xA0\\u1680\\u2000-\\u200A\\u202F\\u205F\\u3000\\uFEFF]))*[\\w$]*(['\"`)])/\nexport function replaceInlineSnap(\n  code: string,\n  s: MagicString,\n  currentIndex: number,\n  newSnap: string,\n): boolean {\n  const { code: codeStartingAtIndex, index } = getCodeStartingAtIndex(code, currentIndex)\n\n  const startMatch = startRegex.exec(codeStartingAtIndex)\n\n  const firstKeywordMatch = /toMatchInlineSnapshot|toThrowErrorMatchingInlineSnapshot/.exec(\n    codeStartingAtIndex,\n  )\n\n  if (!startMatch || startMatch.index !== firstKeywordMatch?.index) {\n    return replaceObjectSnap(code, s, index, newSnap)\n  }\n\n  const quote = startMatch[1]\n  const startIndex = index + startMatch.index + startMatch[0].length\n  const snapString = prepareSnapString(newSnap, code, index)\n\n  if (quote === ')') {\n    s.appendRight(startIndex - 1, snapString)\n    return true\n  }\n\n  const quoteEndRE = new RegExp(`(?:^|[^\\\\\\\\])${quote}`)\n  const endMatch = quoteEndRE.exec(code.slice(startIndex))\n  if (!endMatch) {\n    return false\n  }\n  const endIndex = startIndex + endMatch.index! + endMatch[0].length\n  s.overwrite(startIndex - 1, endIndex, snapString)\n\n  return true\n}\n\nconst INDENTATION_REGEX = /^([^\\S\\n]*)\\S/m\nexport function stripSnapshotIndentation(inlineSnapshot: string): string {\n  // Find indentation if exists.\n  const match = inlineSnapshot.match(INDENTATION_REGEX)\n  if (!match || !match[1]) {\n    // No indentation.\n    return inlineSnapshot\n  }\n\n  const indentation = match[1]\n  const lines = inlineSnapshot.split(/\\n/g)\n  if (lines.length <= 2) {\n    // Must be at least 3 lines.\n    return inlineSnapshot\n  }\n\n  if (lines[0].trim() !== '' || lines.at(-1)?.trim() !== '') {\n    // If not blank first and last lines, abort.\n    return inlineSnapshot\n  }\n\n  for (let i = 1; i < lines.length - 1; i++) {\n    if (lines[i] !== '') {\n      if (lines[i].indexOf(indentation) !== 0) {\n        // All lines except first and last should either be blank or have the same\n        // indent as the first line (or more). If this isn't the case we don't\n        // want to touch the snapshot at all.\n        return inlineSnapshot\n      }\n\n      lines[i] = lines[i].substring(indentation.length)\n    }\n  }\n\n  // Last line is a special case because it won't have the same indent as others\n  // but may still have been given some indent to line up.\n  lines[lines.length - 1] = ''\n\n  // Return inline snapshot, now at indent 0.\n  inlineSnapshot = lines.join('\\n')\n  return inlineSnapshot\n}\n"
  },
  {
    "path": "packages/snapshot/src/port/mockSerializer.ts",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * https://github.com/facebook/jest/blob/4eb4f6a59b6eae0e05b8e51dd8cd3fdca1c7aff1/packages/jest-snapshot/src/mockSerializer.ts#L4\n */\n\nimport type { NewPlugin } from '@vitest/pretty-format'\n\nexport const serialize: NewPlugin['serialize'] = (\n  val,\n  config,\n  indentation,\n  depth,\n  refs,\n  printer,\n): string => {\n  // Serialize a non-default name, even if config.printFunctionName is false.\n  const name = val.getMockName()\n  const nameString = name === 'vi.fn()' ? '' : ` ${name}`\n\n  let callsString = ''\n  if (val.mock.calls.length !== 0) {\n    const indentationNext = indentation + config.indent\n    callsString = ` {${config.spacingOuter}${indentationNext}\"calls\": ${printer(\n      val.mock.calls,\n      config,\n      indentationNext,\n      depth,\n      refs,\n    )}${config.min ? ', ' : ','}${\n      config.spacingOuter\n    }${indentationNext}\"results\": ${printer(\n      val.mock.results,\n      config,\n      indentationNext,\n      depth,\n      refs,\n    )}${config.min ? '' : ','}${config.spacingOuter}${indentation}}`\n  }\n\n  return `[MockFunction${nameString}]${callsString}`\n}\n\nexport const test: NewPlugin['test'] = val => val && !!val._isMockFunction\n\nconst plugin: NewPlugin = { serialize, test }\n\nexport default plugin\n"
  },
  {
    "path": "packages/snapshot/src/port/plugins.ts",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type {\n  Plugin as PrettyFormatPlugin,\n  Plugins as PrettyFormatPlugins,\n} from '@vitest/pretty-format'\nimport { plugins as prettyFormatPlugins } from '@vitest/pretty-format'\n\nimport MockSerializer from './mockSerializer'\n\nconst {\n  DOMCollection,\n  DOMElement,\n  Immutable,\n  ReactElement,\n  ReactTestComponent,\n  AsymmetricMatcher,\n} = prettyFormatPlugins\n\nlet PLUGINS: PrettyFormatPlugins = [\n  ReactTestComponent,\n  ReactElement,\n  DOMElement,\n  DOMCollection,\n  Immutable,\n  AsymmetricMatcher,\n  MockSerializer,\n]\n\nexport function addSerializer(plugin: PrettyFormatPlugin): void {\n  PLUGINS = [plugin].concat(PLUGINS)\n}\n\nexport function getSerializers(): PrettyFormatPlugins {\n  return PLUGINS\n}\n"
  },
  {
    "path": "packages/snapshot/src/port/rawSnapshot.ts",
    "content": "import type { SnapshotEnvironment } from '../types'\n\nexport interface RawSnapshotInfo {\n  file: string\n  readonly?: boolean\n  content?: string\n}\n\nexport interface RawSnapshot extends RawSnapshotInfo {\n  snapshot: string\n  file: string\n}\n\nexport async function saveRawSnapshots(\n  environment: SnapshotEnvironment,\n  snapshots: Array<RawSnapshot>,\n): Promise<void> {\n  await Promise.all(\n    snapshots.map(async (snap) => {\n      if (!snap.readonly) {\n        await environment.saveSnapshotFile(snap.file, snap.snapshot)\n      }\n    }),\n  )\n}\n"
  },
  {
    "path": "packages/snapshot/src/port/state.ts",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { OptionsReceived as PrettyFormatOptions } from '@vitest/pretty-format'\nimport type { ParsedStack } from '@vitest/utils'\nimport type {\n  SnapshotData,\n  SnapshotEnvironment,\n  SnapshotMatchOptions,\n  SnapshotResult,\n  SnapshotStateOptions,\n  SnapshotUpdateState,\n} from '../types'\nimport type { InlineSnapshot } from './inlineSnapshot'\nimport type { RawSnapshot, RawSnapshotInfo } from './rawSnapshot'\nimport { parseErrorStacktrace } from '@vitest/utils/source-map'\nimport { saveInlineSnapshots } from './inlineSnapshot'\nimport { saveRawSnapshots } from './rawSnapshot'\n\nimport {\n  addExtraLineBreaks,\n  CounterMap,\n  DefaultMap,\n  getSnapshotData,\n  keyToTestName,\n  normalizeNewlines,\n  removeExtraLineBreaks,\n  saveSnapshotFile,\n  serialize,\n  testNameToKey,\n} from './utils'\n\ninterface SnapshotReturnOptions {\n  actual: string\n  count: number\n  expected?: string\n  key: string\n  pass: boolean\n}\n\ninterface SaveStatus {\n  deleted: boolean\n  saved: boolean\n}\n\ntype ParsedStackPosition = Pick<ParsedStack, 'file' | 'line' | 'column'>\n\nfunction isSameStackPosition(x: ParsedStackPosition, y: ParsedStackPosition) {\n  return x.file === y.file && x.column === y.column && x.line === y.line\n}\n\nexport default class SnapshotState {\n  private _counters = new CounterMap<string>()\n  private _dirty: boolean\n  private _updateSnapshot: SnapshotUpdateState\n  private _snapshotData: SnapshotData\n  private _initialData: SnapshotData\n  private _inlineSnapshots: Array<InlineSnapshot>\n  private _inlineSnapshotStacks: Array<ParsedStack & { testId: string; snapshot: string }>\n  private _testIdToKeys = new DefaultMap<string, string[]>(() => [])\n  private _rawSnapshots: Array<RawSnapshot>\n  private _uncheckedKeys: Set<string>\n  private _snapshotFormat: PrettyFormatOptions\n  private _environment: SnapshotEnvironment\n  private _fileExists: boolean\n  expand: boolean\n\n  // getter/setter for jest-image-snapshot compat\n  // https://github.com/vitest-dev/vitest/issues/7322\n  private _added = new CounterMap<string>()\n  private _matched = new CounterMap<string>()\n  private _unmatched = new CounterMap<string>()\n  private _updated = new CounterMap<string>()\n  get added(): CounterMap<string> { return this._added }\n  set added(value: number) { this._added._total = value }\n  get matched(): CounterMap<string> { return this._matched }\n  set matched(value: number) { this._matched._total = value }\n  get unmatched(): CounterMap<string> { return this._unmatched }\n  set unmatched(value: number) { this._unmatched._total = value }\n  get updated(): CounterMap<string> { return this._updated }\n  set updated(value: number) { this._updated._total = value }\n\n  private constructor(\n    public testFilePath: string,\n    public snapshotPath: string,\n    snapshotContent: string | null,\n    options: SnapshotStateOptions,\n  ) {\n    const { data, dirty } = getSnapshotData(snapshotContent, options)\n    this._fileExists = snapshotContent != null // TODO: update on watch?\n    this._initialData = { ...data }\n    this._snapshotData = { ...data }\n    this._dirty = dirty\n    this._inlineSnapshots = []\n    this._inlineSnapshotStacks = []\n    this._rawSnapshots = []\n    this._uncheckedKeys = new Set(Object.keys(this._snapshotData))\n    this.expand = options.expand || false\n    this._updateSnapshot = options.updateSnapshot\n    this._snapshotFormat = {\n      printBasicPrototype: false,\n      escapeString: false,\n      ...options.snapshotFormat,\n    }\n    this._environment = options.snapshotEnvironment\n  }\n\n  static async create(testFilePath: string, options: SnapshotStateOptions): Promise<SnapshotState> {\n    const snapshotPath = await options.snapshotEnvironment.resolvePath(\n      testFilePath,\n    )\n    const content = await options.snapshotEnvironment.readSnapshotFile(\n      snapshotPath,\n    )\n    return new SnapshotState(testFilePath, snapshotPath, content, options)\n  }\n\n  get environment(): SnapshotEnvironment {\n    return this._environment\n  }\n\n  markSnapshotsAsCheckedForTest(testName: string): void {\n    this._uncheckedKeys.forEach((uncheckedKey) => {\n      // skip snapshots with following keys\n      //   testName n\n      //   testName > xxx n (this is for toMatchSnapshot(\"xxx\") API)\n      if (/ \\d+$| > /.test(uncheckedKey.slice(testName.length))) {\n        this._uncheckedKeys.delete(uncheckedKey)\n      }\n    })\n  }\n\n  clearTest(testId: string): void {\n    // clear inline\n    this._inlineSnapshots = this._inlineSnapshots.filter(s => s.testId !== testId)\n    this._inlineSnapshotStacks = this._inlineSnapshotStacks.filter(s => s.testId !== testId)\n\n    // clear file\n    for (const key of this._testIdToKeys.get(testId)) {\n      const name = keyToTestName(key)\n      const count = this._counters.get(name)\n      if (count > 0) {\n        if (key in this._snapshotData || key in this._initialData) {\n          this._snapshotData[key] = this._initialData[key]\n        }\n        this._counters.set(name, count - 1)\n      }\n    }\n    this._testIdToKeys.delete(testId)\n\n    // clear stats\n    this.added.delete(testId)\n    this.updated.delete(testId)\n    this.matched.delete(testId)\n    this.unmatched.delete(testId)\n  }\n\n  protected _inferInlineSnapshotStack(stacks: ParsedStack[]): ParsedStack | null {\n    // if called inside resolves/rejects, stacktrace is different\n    const promiseIndex = stacks.findIndex(i =>\n      i.method.match(/__VITEST_(RESOLVES|REJECTS)__/),\n    )\n    if (promiseIndex !== -1) {\n      return stacks[promiseIndex + 3]\n    }\n\n    // inline snapshot function can be named __INLINE_SNAPSHOT_OFFSET_<n>__\n    // to specify a custom stack offset\n    for (let i = 0; i < stacks.length; i++) {\n      const match = stacks[i].method.match(/__INLINE_SNAPSHOT_OFFSET_(\\d+)__/)\n      if (match) {\n        return stacks[i + Number(match[1])] ?? null\n      }\n    }\n\n    // inline snapshot function is called __INLINE_SNAPSHOT__\n    // in integrations/snapshot/chai.ts\n    const stackIndex = stacks.findIndex(i =>\n      i.method.includes('__INLINE_SNAPSHOT__'),\n    )\n    return stackIndex !== -1 ? stacks[stackIndex + 2] : null\n  }\n\n  private _addSnapshot(\n    key: string,\n    receivedSerialized: string,\n    options: { rawSnapshot?: RawSnapshotInfo; stack?: ParsedStack; testId: string },\n  ): void {\n    this._dirty = true\n    if (options.stack) {\n      this._inlineSnapshots.push({\n        snapshot: receivedSerialized,\n        testId: options.testId,\n        ...options.stack,\n      })\n    }\n    else if (options.rawSnapshot) {\n      this._rawSnapshots.push({\n        ...options.rawSnapshot,\n        snapshot: receivedSerialized,\n      })\n    }\n    else {\n      this._snapshotData[key] = receivedSerialized\n    }\n  }\n\n  async save(): Promise<SaveStatus> {\n    const hasExternalSnapshots = Object.keys(this._snapshotData).length\n    const hasInlineSnapshots = this._inlineSnapshots.length\n    const hasRawSnapshots = this._rawSnapshots.length\n    const isEmpty\n      = !hasExternalSnapshots && !hasInlineSnapshots && !hasRawSnapshots\n\n    const status: SaveStatus = {\n      deleted: false,\n      saved: false,\n    }\n\n    if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {\n      if (hasExternalSnapshots) {\n        await saveSnapshotFile(\n          this._environment,\n          this._snapshotData,\n          this.snapshotPath,\n        )\n        this._fileExists = true\n      }\n      if (hasInlineSnapshots) {\n        await saveInlineSnapshots(this._environment, this._inlineSnapshots)\n      }\n      if (hasRawSnapshots) {\n        await saveRawSnapshots(this._environment, this._rawSnapshots)\n      }\n\n      status.saved = true\n    }\n    else if (!hasExternalSnapshots && this._fileExists) {\n      if (this._updateSnapshot === 'all') {\n        await this._environment.removeSnapshotFile(this.snapshotPath)\n        this._fileExists = false\n      }\n\n      status.deleted = true\n    }\n\n    return status\n  }\n\n  getUncheckedCount(): number {\n    return this._uncheckedKeys.size || 0\n  }\n\n  getUncheckedKeys(): Array<string> {\n    return Array.from(this._uncheckedKeys)\n  }\n\n  removeUncheckedKeys(): void {\n    if (this._updateSnapshot === 'all' && this._uncheckedKeys.size) {\n      this._dirty = true\n      this._uncheckedKeys.forEach(key => delete this._snapshotData[key])\n      this._uncheckedKeys.clear()\n    }\n  }\n\n  match({\n    testId,\n    testName,\n    received,\n    key,\n    inlineSnapshot,\n    isInline,\n    error,\n    rawSnapshot,\n  }: SnapshotMatchOptions): SnapshotReturnOptions {\n    // this also increments counter for inline snapshots. maybe we shouldn't?\n    this._counters.increment(testName)\n    const count = this._counters.get(testName)\n\n    if (!key) {\n      key = testNameToKey(testName, count)\n    }\n    this._testIdToKeys.get(testId).push(key)\n\n    // Do not mark the snapshot as \"checked\" if the snapshot is inline and\n    // there's an external snapshot. This way the external snapshot can be\n    // removed with `--updateSnapshot`.\n    if (!(isInline && this._snapshotData[key] !== undefined)) {\n      this._uncheckedKeys.delete(key)\n    }\n\n    let receivedSerialized\n      = rawSnapshot && typeof received === 'string'\n        ? (received as string)\n        : serialize(received, undefined, this._snapshotFormat)\n\n    if (!rawSnapshot) {\n      receivedSerialized = addExtraLineBreaks(receivedSerialized)\n    }\n\n    if (rawSnapshot) {\n      // normalize EOL when snapshot contains CRLF but received is LF\n      if (\n        rawSnapshot.content\n        && rawSnapshot.content.match(/\\r\\n/)\n        && !receivedSerialized.match(/\\r\\n/)\n      ) {\n        rawSnapshot.content = normalizeNewlines(rawSnapshot.content)\n      }\n    }\n\n    const expected = isInline\n      ? inlineSnapshot\n      : rawSnapshot\n        ? rawSnapshot.content\n        : this._snapshotData[key]\n    const expectedTrimmed = rawSnapshot ? expected : expected?.trim()\n    const pass = expectedTrimmed === (rawSnapshot ? receivedSerialized : receivedSerialized.trim())\n    const hasSnapshot = expected !== undefined\n    const snapshotIsPersisted\n      = isInline\n        || this._fileExists\n        || (rawSnapshot && rawSnapshot.content != null)\n\n    if (pass && !isInline && !rawSnapshot) {\n      // Executing a snapshot file as JavaScript and writing the strings back\n      // when other snapshots have changed loses the proper escaping for some\n      // characters. Since we check every snapshot in every test, use the newly\n      // generated formatted string.\n      // Note that this is only relevant when a snapshot is added and the dirty\n      // flag is set.\n      this._snapshotData[key] = receivedSerialized\n    }\n\n    // find call site of toMatchInlineSnapshot\n    let stack: ParsedStack | undefined\n    if (isInline) {\n      const stacks = parseErrorStacktrace(\n        error || new Error('snapshot'),\n        { ignoreStackEntries: [] },\n      )\n      const _stack = this._inferInlineSnapshotStack(stacks)\n      if (!_stack) {\n        throw new Error(\n          `@vitest/snapshot: Couldn't infer stack frame for inline snapshot.\\n${JSON.stringify(\n            stacks,\n          )}`,\n        )\n      }\n      stack = this.environment.processStackTrace?.(_stack) || _stack\n      // removing 1 column, because source map points to the wrong\n      // location for js files, but `column-1` points to the same in both js/ts\n      // https://github.com/vitejs/vite/issues/8657\n      stack.column--\n\n      // reject multiple inline snapshots at the same location if snapshot is different\n      const snapshotsWithSameStack = this._inlineSnapshotStacks.filter(s => isSameStackPosition(s, stack!))\n      if (snapshotsWithSameStack.length > 0) {\n        // ensure only one snapshot will be written at the same location\n        this._inlineSnapshots = this._inlineSnapshots.filter(s => !isSameStackPosition(s, stack!))\n\n        const differentSnapshot = snapshotsWithSameStack.find(s => s.snapshot !== receivedSerialized)\n        if (differentSnapshot) {\n          throw Object.assign(\n            new Error(\n              'toMatchInlineSnapshot with different snapshots cannot be called at the same location',\n            ),\n            {\n              actual: receivedSerialized,\n              expected: differentSnapshot.snapshot,\n            },\n          )\n        }\n      }\n      this._inlineSnapshotStacks.push({ ...stack, testId, snapshot: receivedSerialized })\n    }\n\n    // These are the conditions on when to write snapshots:\n    //  * There's no snapshot file in a non-CI environment.\n    //  * There is a snapshot file and we decided to update the snapshot.\n    //  * There is a snapshot file, but it doesn't have this snapshot.\n    // These are the conditions on when not to write snapshots:\n    //  * The update flag is set to 'none'.\n    //  * There's no snapshot file or a file without this snapshot on a CI environment.\n    if (\n      (hasSnapshot && this._updateSnapshot === 'all')\n      || ((!hasSnapshot || !snapshotIsPersisted)\n        && (this._updateSnapshot === 'new' || this._updateSnapshot === 'all'))\n    ) {\n      if (this._updateSnapshot === 'all') {\n        if (!pass) {\n          if (hasSnapshot) {\n            this.updated.increment(testId)\n          }\n          else {\n            this.added.increment(testId)\n          }\n\n          this._addSnapshot(key, receivedSerialized, {\n            stack,\n            testId,\n            rawSnapshot,\n          })\n        }\n        else {\n          this.matched.increment(testId)\n        }\n      }\n      else {\n        this._addSnapshot(key, receivedSerialized, {\n          stack,\n          testId,\n          rawSnapshot,\n        })\n        this.added.increment(testId)\n      }\n\n      return {\n        actual: '',\n        count,\n        expected: '',\n        key,\n        pass: true,\n      }\n    }\n    else {\n      if (!pass) {\n        this.unmatched.increment(testId)\n        return {\n          actual: rawSnapshot ? receivedSerialized : removeExtraLineBreaks(receivedSerialized),\n          count,\n          expected:\n            expectedTrimmed !== undefined\n              ? rawSnapshot ? expectedTrimmed : removeExtraLineBreaks(expectedTrimmed)\n              : undefined,\n          key,\n          pass: false,\n        }\n      }\n      else {\n        this.matched.increment(testId)\n        return {\n          actual: '',\n          count,\n          expected: '',\n          key,\n          pass: true,\n        }\n      }\n    }\n  }\n\n  async pack(): Promise<SnapshotResult> {\n    const snapshot: SnapshotResult = {\n      filepath: this.testFilePath,\n      added: 0,\n      fileDeleted: false,\n      matched: 0,\n      unchecked: 0,\n      uncheckedKeys: [],\n      unmatched: 0,\n      updated: 0,\n    }\n    const uncheckedCount = this.getUncheckedCount()\n    const uncheckedKeys = this.getUncheckedKeys()\n    if (uncheckedCount) {\n      this.removeUncheckedKeys()\n    }\n\n    const status = await this.save()\n    snapshot.fileDeleted = status.deleted\n    snapshot.added = this.added.total()\n    snapshot.matched = this.matched.total()\n    snapshot.unmatched = this.unmatched.total()\n    snapshot.updated = this.updated.total()\n    snapshot.unchecked = !status.deleted ? uncheckedCount : 0\n    snapshot.uncheckedKeys = Array.from(uncheckedKeys)\n\n    return snapshot\n  }\n}\n"
  },
  {
    "path": "packages/snapshot/src/port/utils.ts",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { OptionsReceived as PrettyFormatOptions } from '@vitest/pretty-format'\nimport type { SnapshotData, SnapshotStateOptions } from '../types'\nimport type { SnapshotEnvironment } from '../types/environment'\nimport { format as prettyFormat } from '@vitest/pretty-format'\nimport { isObject } from '@vitest/utils/helpers'\nimport naturalCompare from 'natural-compare'\nimport { getSerializers } from './plugins'\n\n// TODO: rewrite and clean up\n\nexport function testNameToKey(testName: string, count: number): string {\n  return `${testName} ${count}`\n}\n\nexport function keyToTestName(key: string): string {\n  if (!/ \\d+$/.test(key)) {\n    throw new Error('Snapshot keys must end with a number.')\n  }\n\n  return key.replace(/ \\d+$/, '')\n}\n\nexport function getSnapshotData(\n  content: string | null,\n  options: SnapshotStateOptions,\n): {\n  data: SnapshotData\n  dirty: boolean\n} {\n  const update = options.updateSnapshot\n  const data = Object.create(null)\n  let snapshotContents = ''\n  let dirty = false\n\n  if (content != null) {\n    try {\n      snapshotContents = content\n      // eslint-disable-next-line no-new-func\n      const populate = new Function('exports', snapshotContents)\n      populate(data)\n    }\n    catch {}\n  }\n\n  // const validationResult = validateSnapshotVersion(snapshotContents)\n  const isInvalid = snapshotContents // && validationResult\n\n  // if (update === 'none' && isInvalid)\n  //   throw validationResult\n\n  if ((update === 'all' || update === 'new') && isInvalid) {\n    dirty = true\n  }\n\n  return { data, dirty }\n}\n\n// Add extra line breaks at beginning and end of multiline snapshot\n// to make the content easier to read.\nexport function addExtraLineBreaks(string: string): string {\n  return string.includes('\\n') ? `\\n${string}\\n` : string\n}\n\n// Remove extra line breaks at beginning and end of multiline snapshot.\n// Instead of trim, which can remove additional newlines or spaces\n// at beginning or end of the content from a custom serializer.\nexport function removeExtraLineBreaks(string: string): string {\n  return string.length > 2 && string[0] === '\\n' && string.endsWith('\\n')\n    ? string.slice(1, -1)\n    : string\n}\n\n// export const removeLinesBeforeExternalMatcherTrap = (stack: string): string => {\n//   const lines = stack.split('\\n')\n\n//   for (let i = 0; i < lines.length; i += 1) {\n//     // It's a function name specified in `packages/expect/src/index.ts`\n//     // for external custom matchers.\n//     if (lines[i].includes('__EXTERNAL_MATCHER_TRAP__'))\n//       return lines.slice(i + 1).join('\\n')\n//   }\n\n//   return stack\n// }\n\nconst escapeRegex = true\nconst printFunctionName = false\n\nexport function serialize(\n  val: unknown,\n  indent = 2,\n  formatOverrides: PrettyFormatOptions = {},\n): string {\n  return normalizeNewlines(\n    prettyFormat(val, {\n      escapeRegex,\n      indent,\n      plugins: getSerializers(),\n      printFunctionName,\n      ...formatOverrides,\n    }),\n  )\n}\n\nexport function minify(val: unknown): string {\n  return prettyFormat(val, {\n    escapeRegex,\n    min: true,\n    plugins: getSerializers(),\n    printFunctionName,\n  })\n}\n\n// Remove double quote marks and unescape double quotes and backslashes.\nexport function deserializeString(stringified: string): string {\n  return stringified.slice(1, -1).replace(/\\\\(\"|\\\\)/g, '$1')\n}\n\nexport function escapeBacktickString(str: string): string {\n  return str.replace(/`|\\\\|\\$\\{/g, '\\\\$&')\n}\n\nfunction printBacktickString(str: string): string {\n  return `\\`${escapeBacktickString(str)}\\``\n}\n\nexport function normalizeNewlines(string: string): string {\n  return string.replace(/\\r\\n|\\r/g, '\\n')\n}\n\nexport async function saveSnapshotFile(\n  environment: SnapshotEnvironment,\n  snapshotData: SnapshotData,\n  snapshotPath: string,\n): Promise<void> {\n  const snapshots = Object.keys(snapshotData)\n    .sort(naturalCompare)\n    .map(\n      key =>\n        `exports[${printBacktickString(key)}] = ${printBacktickString(\n          normalizeNewlines(snapshotData[key]),\n        )};`,\n    )\n\n  const content = `${environment.getHeader()}\\n\\n${snapshots.join('\\n\\n')}\\n`\n  const oldContent = await environment.readSnapshotFile(snapshotPath)\n  const skipWriting = oldContent != null && oldContent === content\n\n  if (skipWriting) {\n    return\n  }\n\n  await environment.saveSnapshotFile(snapshotPath, content)\n}\n\nexport async function saveSnapshotFileRaw(\n  environment: SnapshotEnvironment,\n  content: string,\n  snapshotPath: string,\n): Promise<void> {\n  const oldContent = await environment.readSnapshotFile(snapshotPath)\n  const skipWriting = oldContent != null && oldContent === content\n\n  if (skipWriting) {\n    return\n  }\n\n  await environment.saveSnapshotFile(snapshotPath, content)\n}\n\nfunction deepMergeArray(target: any[] = [], source: any[] = []) {\n  const mergedOutput = Array.from(target)\n\n  source.forEach((sourceElement, index) => {\n    const targetElement = mergedOutput[index]\n\n    if (Array.isArray(target[index])) {\n      mergedOutput[index] = deepMergeArray(target[index], sourceElement)\n    }\n    else if (isObject(targetElement)) {\n      mergedOutput[index] = deepMergeSnapshot(target[index], sourceElement)\n    }\n    else {\n      // Source does not exist in target or target is primitive and cannot be deep merged\n      mergedOutput[index] = sourceElement\n    }\n  })\n\n  return mergedOutput\n}\n\n/**\n * Deep merge, but considers asymmetric matchers. Unlike base util's deep merge,\n * will merge any object-like instance.\n * Compatible with Jest's snapshot matcher. Should not be used outside of snapshot.\n *\n * @example\n * ```ts\n * toMatchSnapshot({\n *   name: expect.stringContaining('text')\n * })\n * ```\n */\nexport function deepMergeSnapshot(target: any, source: any): any {\n  if (isObject(target) && isObject(source)) {\n    const mergedOutput = { ...target }\n    Object.keys(source).forEach((key) => {\n      if (isObject(source[key]) && !source[key].$$typeof) {\n        if (!(key in target)) {\n          Object.assign(mergedOutput, { [key]: source[key] })\n        }\n        else {\n          mergedOutput[key] = deepMergeSnapshot(target[key], source[key])\n        }\n      }\n      else if (Array.isArray(source[key])) {\n        mergedOutput[key] = deepMergeArray(target[key], source[key])\n      }\n      else {\n        Object.assign(mergedOutput, { [key]: source[key] })\n      }\n    })\n\n    return mergedOutput\n  }\n  else if (Array.isArray(target) && Array.isArray(source)) {\n    return deepMergeArray(target, source)\n  }\n  return target\n}\n\nexport class DefaultMap<K, V> extends Map<K, V> {\n  constructor(\n    private defaultFn: (key: K) => V,\n    entries?: Iterable<readonly [K, V]>,\n  ) {\n    super(entries)\n  }\n\n  override get(key: K): V {\n    if (!this.has(key)) {\n      this.set(key, this.defaultFn(key))\n    }\n    return super.get(key)!\n  }\n}\n\nexport class CounterMap<K> extends DefaultMap<K, number> {\n  constructor() {\n    super(() => 0)\n  }\n\n  // compat for jest-image-snapshot https://github.com/vitest-dev/vitest/issues/7322\n  // `valueOf` and `Snapshot.added` setter allows\n  //   snapshotState.added = snapshotState.added + 1\n  // to function as\n  //   snapshotState.added.total_ = snapshotState.added.total() + 1\n  _total: number | undefined\n\n  valueOf(): number {\n    return this._total = this.total()\n  }\n\n  increment(key: K): void {\n    if (typeof this._total !== 'undefined') {\n      this._total++\n    }\n    this.set(key, this.get(key) + 1)\n  }\n\n  total(): number {\n    if (typeof this._total !== 'undefined') {\n      return this._total\n    }\n    let total = 0\n    for (const x of this.values()) {\n      total += x\n    }\n    return total\n  }\n}\n"
  },
  {
    "path": "packages/snapshot/src/types/environment.ts",
    "content": "import type { ParsedStack } from '@vitest/utils'\n\nexport interface SnapshotEnvironment {\n  getVersion: () => string\n  getHeader: () => string\n  resolvePath: (filepath: string) => Promise<string>\n  resolveRawPath: (testPath: string, rawPath: string) => Promise<string>\n  saveSnapshotFile: (filepath: string, snapshot: string) => Promise<void>\n  readSnapshotFile: (filepath: string) => Promise<string | null>\n  removeSnapshotFile: (filepath: string) => Promise<void>\n  processStackTrace?: (stack: ParsedStack) => ParsedStack\n}\n\nexport interface SnapshotEnvironmentOptions {\n  snapshotsDirName?: string\n}\n"
  },
  {
    "path": "packages/snapshot/src/types/index.ts",
    "content": "import type {\n  OptionsReceived as PrettyFormatOptions,\n  Plugin as PrettyFormatPlugin,\n} from '@vitest/pretty-format'\nimport type { RawSnapshotInfo } from '../port/rawSnapshot'\nimport type {\n  SnapshotEnvironment,\n  SnapshotEnvironmentOptions,\n} from './environment'\n\nexport type { SnapshotEnvironment, SnapshotEnvironmentOptions }\nexport type SnapshotData = Record<string, string>\n\nexport type SnapshotUpdateState = 'all' | 'new' | 'none'\n\nexport type SnapshotSerializer = PrettyFormatPlugin\n\nexport interface SnapshotStateOptions {\n  updateSnapshot: SnapshotUpdateState\n  snapshotEnvironment: SnapshotEnvironment\n  expand?: boolean\n  snapshotFormat?: PrettyFormatOptions\n  resolveSnapshotPath?: (path: string, extension: string, context?: any) => string\n}\n\nexport interface SnapshotMatchOptions {\n  testId: string\n  testName: string\n  received: unknown\n  key?: string\n  inlineSnapshot?: string\n  isInline: boolean\n  error?: Error\n  rawSnapshot?: RawSnapshotInfo\n}\n\nexport interface SnapshotResult {\n  filepath: string\n  added: number\n  fileDeleted: boolean\n  matched: number\n  unchecked: number\n  uncheckedKeys: Array<string>\n  unmatched: number\n  updated: number\n}\n\nexport interface UncheckedSnapshot {\n  filePath: string\n  keys: Array<string>\n}\n\nexport interface SnapshotSummary {\n  added: number\n  didUpdate: boolean\n  failure: boolean\n  filesAdded: number\n  filesRemoved: number\n  filesRemovedList: Array<string>\n  filesUnmatched: number\n  filesUpdated: number\n  matched: number\n  total: number\n  unchecked: number\n  uncheckedKeysByFile: Array<UncheckedSnapshot>\n  unmatched: number\n  updated: number\n}\n"
  },
  {
    "path": "packages/snapshot/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"moduleResolution\": \"Bundler\",\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"./dist\"]\n}\n"
  },
  {
    "path": "packages/spy/README.md",
    "content": "# @vitest/spy\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/spy?color=a1b858&label=)](https://npmx.dev/package/@vitest/spy)\n\nLightweight Jest-compatible mocking implementation.\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/spy) | [Documentation](https://vitest.dev/api/mock)\n"
  },
  {
    "path": "packages/spy/package.json",
    "content": "{\n  \"name\": \"@vitest/spy\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Lightweight Jest compatible spy implementation\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/api/mock\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/spy\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vitest\",\n    \"test\",\n    \"mock\",\n    \"spy\",\n    \"intercept\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch\"\n  }\n}\n"
  },
  {
    "path": "packages/spy/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nexport default defineConfig([\n  {\n    input: 'src/index.ts',\n    output: {\n      dir: 'dist',\n      format: 'esm',\n      entryFileNames: '[name].js',\n      chunkFileNames: 'chunk-[name].js',\n    },\n    external,\n    plugins,\n    onwarn,\n  },\n  {\n    input: dtsUtils.dtsInput('src/index.ts'),\n    output: {\n      dir: 'dist',\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n    onwarn,\n  },\n])\n\nfunction onwarn(message) {\n  if (['EMPTY_BUNDLE', 'CIRCULAR_DEPENDENCY'].includes(message.code)) {\n    return\n  }\n  console.error(message)\n}\n"
  },
  {
    "path": "packages/spy/src/index.ts",
    "content": "import type {\n  Classes,\n  Constructable,\n  Methods,\n  Mock,\n  MockConfig,\n  MockContext,\n  MockInstanceOption,\n  MockProcedureContext,\n  MockResult,\n  MockReturnType,\n  MockSettledResult,\n  Procedure,\n  Properties,\n} from './types'\n\nexport function isMockFunction(fn: any): fn is Mock {\n  return (\n    typeof fn === 'function' && '_isMockFunction' in fn && fn._isMockFunction === true\n  )\n}\n\nconst MOCK_RESTORE = new Set<() => void>()\n// Jest keeps the state in a separate WeakMap which is good for memory,\n// but it makes the state slower to access and return different values\n// if you stored it before calling `mockClear` where it will be recreated\nconst REGISTERED_MOCKS = new Set<Mock<Procedure | Constructable>>()\nconst MOCK_CONFIGS = new WeakMap<Mock<Procedure | Constructable>, MockConfig>()\n\nexport function createMockInstance(options: MockInstanceOption = {}): Mock<Procedure | Constructable> {\n  const {\n    originalImplementation,\n    restore,\n    mockImplementation,\n    resetToMockImplementation,\n    resetToMockName,\n  } = options\n\n  if (restore) {\n    MOCK_RESTORE.add(restore)\n  }\n\n  const config = getDefaultConfig(originalImplementation)\n  const state = getDefaultState()\n\n  const mock = createMock({\n    config,\n    state,\n    ...options,\n  })\n  const mockLength = (mockImplementation || originalImplementation)?.length ?? 0\n  Object.defineProperty(mock, 'length', {\n    writable: true,\n    enumerable: false,\n    value: mockLength,\n    configurable: true,\n  })\n  // inherit the default name so it appears in snapshots and logs\n  // this is used by `vi.spyOn()` for better debugging.\n  // when `vi.fn()` is called, we just use the default string\n  if (resetToMockName) {\n    config.mockName = mock.name || 'vi.fn()'\n  }\n  MOCK_CONFIGS.set(mock, config)\n  REGISTERED_MOCKS.add(mock)\n\n  mock._isMockFunction = true\n  mock.getMockImplementation = () => {\n    // Jest only returns `config.mockImplementation` here,\n    // but we think it makes sense to return what the next function will be called\n    return config.onceMockImplementations[0] || config.mockImplementation\n  }\n\n  Object.defineProperty(mock, 'mock', {\n    configurable: false,\n    enumerable: true,\n    writable: false,\n    value: state,\n  })\n\n  mock.mockImplementation = function mockImplementation(implementation) {\n    config.mockImplementation = implementation\n    return mock\n  }\n\n  mock.mockImplementationOnce = function mockImplementationOnce(implementation) {\n    config.onceMockImplementations.push(implementation)\n    return mock\n  }\n\n  mock.withImplementation = function withImplementation(implementation, callback) {\n    const previousImplementation = config.mockImplementation\n    const previousOnceImplementations = config.onceMockImplementations\n\n    const reset = () => {\n      config.mockImplementation = previousImplementation\n      config.onceMockImplementations = previousOnceImplementations\n    }\n\n    config.mockImplementation = implementation\n    config.onceMockImplementations = []\n\n    const returnValue = callback()\n\n    if (typeof returnValue === 'object' && typeof (returnValue as Promise<any>)?.then === 'function') {\n      return (returnValue as Promise<any>).then(() => {\n        reset()\n        return mock\n      }) as any\n    }\n    else {\n      reset()\n    }\n    return mock\n  }\n\n  mock.mockReturnThis = function mockReturnThis() {\n    return mock.mockImplementation(function (this: any) {\n      return this\n    })\n  }\n\n  mock.mockReturnValue = function mockReturnValue(value) {\n    return mock.mockImplementation(function () {\n      if (new.target) {\n        throwConstructorError('mockReturnValue')\n      }\n\n      return value\n    })\n  }\n\n  mock.mockReturnValueOnce = function mockReturnValueOnce(value) {\n    return mock.mockImplementationOnce(function () {\n      if (new.target) {\n        throwConstructorError('mockReturnValueOnce')\n      }\n\n      return value\n    })\n  }\n\n  mock.mockThrow = function mockThrow(value) {\n    // eslint-disable-next-line prefer-arrow-callback\n    return mock.mockImplementation(function () {\n      throw value\n    })\n  }\n\n  mock.mockThrowOnce = function mockThrowOnce(value) {\n    // eslint-disable-next-line prefer-arrow-callback\n    return mock.mockImplementationOnce(function () {\n      throw value\n    })\n  }\n\n  mock.mockResolvedValue = function mockResolvedValue(value) {\n    return mock.mockImplementation(function () {\n      if (new.target) {\n        throwConstructorError('mockResolvedValue')\n      }\n\n      return Promise.resolve(value)\n    })\n  }\n\n  mock.mockResolvedValueOnce = function mockResolvedValueOnce(value) {\n    return mock.mockImplementationOnce(function () {\n      if (new.target) {\n        throwConstructorError('mockResolvedValueOnce')\n      }\n\n      return Promise.resolve(value)\n    })\n  }\n\n  mock.mockRejectedValue = function mockRejectedValue(value) {\n    return mock.mockImplementation(function () {\n      if (new.target) {\n        throwConstructorError('mockRejectedValue')\n      }\n\n      return Promise.reject(value)\n    })\n  }\n\n  mock.mockRejectedValueOnce = function mockRejectedValueOnce(value) {\n    return mock.mockImplementationOnce(function () {\n      if (new.target) {\n        throwConstructorError('mockRejectedValueOnce')\n      }\n\n      return Promise.reject(value)\n    })\n  }\n\n  mock.mockClear = function mockClear() {\n    state.calls = []\n    state.contexts = []\n    state.instances = []\n    state.invocationCallOrder = []\n    state.results = []\n    state.settledResults = []\n    return mock\n  }\n\n  mock.mockReset = function mockReset() {\n    mock.mockClear()\n    config.mockImplementation = resetToMockImplementation\n      ? mockImplementation\n      : undefined\n    config.mockName = resetToMockName ? (mock.name || 'vi.fn()') : 'vi.fn()'\n    config.onceMockImplementations = []\n    return mock\n  }\n\n  mock.mockRestore = function mockRestore() {\n    mock.mockReset()\n    return restore?.()\n  }\n\n  mock.mockName = function mockName(name: string) {\n    if (typeof name === 'string') {\n      config.mockName = name\n    }\n    return mock\n  }\n\n  mock.getMockName = function getMockName() {\n    return config.mockName || 'vi.fn()'\n  }\n\n  if (Symbol.dispose) {\n    mock[Symbol.dispose] = () => mock.mockRestore()\n  }\n\n  if (mockImplementation) {\n    mock.mockImplementation(mockImplementation)\n  }\n\n  return mock\n}\n\nexport function fn<T extends Procedure | Constructable = Procedure>(\n  originalImplementation?: T,\n): Mock<T> {\n  // if the function is already a mock, just return the same function,\n  // simillarly to how vi.spyOn() works\n  if (originalImplementation != null && isMockFunction(originalImplementation)) {\n    return originalImplementation as Mock<T>\n  }\n\n  return createMockInstance({\n    // we pass this down so getMockImplementation() always returns the value\n    mockImplementation: originalImplementation,\n    // special case so that .mockReset() resets the value to\n    // the the originalImplementation instead of () => undefined\n    resetToMockImplementation: true,\n  }) as Mock<T>\n}\n\nexport function spyOn<T extends object, S extends Properties<Required<T>>>(\n  object: T,\n  key: S,\n  accessor: 'get',\n): Mock<() => T[S]>\nexport function spyOn<T extends object, G extends Properties<Required<T>>>(\n  object: T,\n  key: G,\n  accessor: 'set',\n): Mock<(arg: T[G]) => void>\nexport function spyOn<T extends object, M extends Classes<Required<T>> | Methods<Required<T>>>(\n  object: T,\n  key: M,\n): Required<T>[M] extends Constructable | Procedure\n  ? Mock<Required<T>[M]>\n  : never\nexport function spyOn<T extends object, K extends keyof T>(\n  object: T,\n  key: K,\n  accessor?: 'get' | 'set',\n): Mock<Procedure | Constructable> {\n  assert(\n    object != null,\n    'The vi.spyOn() function could not find an object to spy upon. The first argument must be defined.',\n  )\n\n  assert(\n    typeof object === 'object' || typeof object === 'function',\n    'Vitest cannot spy on a primitive value.',\n  )\n\n  const [originalDescriptorObject, originalDescriptor] = getDescriptor(object, key) || []\n  assert(\n    originalDescriptor || key in object,\n    `The property \"${String(key)}\" is not defined on the ${typeof object}.`,\n  )\n  let accessType: 'get' | 'set' | 'value' = accessor || 'value'\n  let ssr = false\n\n  // vite ssr support - actual function is stored inside a getter\n  if (\n    accessType === 'value'\n    && originalDescriptor\n    && originalDescriptor.value == null\n    && originalDescriptor.get\n  ) {\n    accessType = 'get'\n    ssr = true\n  }\n\n  let original: Procedure | undefined\n\n  if (originalDescriptor) {\n    original = originalDescriptor[accessType]\n    // weird Proxy edge case where descriptor's value is undefined,\n    // but there's still a value on the object when called\n    // https://github.com/vitest-dev/vitest/issues/9439\n    if (original == null && accessType === 'value') {\n      original = object[key] as unknown as Procedure\n    }\n  }\n  else if (accessType !== 'value') {\n    original = () => object[key]\n  }\n  else {\n    original = object[key] as unknown as Procedure\n  }\n\n  const originalImplementation = ssr && original ? original() : original\n  const originalType = typeof originalImplementation\n\n  assert(\n    // allow only functions\n    originalType === 'function'\n    // or allow getter/setter on a static value,\n    // e.g. spyOn({ value: 3 }, 'value', 'get')\n    || (accessType !== 'value' && original == null),\n    `vi.spyOn() can only spy on a function. Received ${originalType}.`,\n  )\n\n  if (isMockFunction(originalImplementation)) {\n    return originalImplementation\n  }\n\n  const reassign = (cb: any) => {\n    const { value, ...desc } = originalDescriptor || {\n      configurable: true,\n      writable: true,\n    }\n    if (accessType !== 'value') {\n      delete desc.writable // getter/setter can't have writable attribute at all\n    }\n    ;(desc as PropertyDescriptor)[accessType] = cb\n    Object.defineProperty(object, key, desc)\n  }\n\n  const restore = () => {\n    // if method is defined on the prototype, we can just remove it from\n    // the current object instead of redefining a copy of it\n    if (originalDescriptorObject !== object) {\n      Reflect.deleteProperty(object, key)\n    }\n    else if (originalDescriptor && !original) {\n      Object.defineProperty(object, key, originalDescriptor)\n    }\n    else {\n      reassign(original)\n    }\n  }\n\n  const mock = createMockInstance({\n    restore,\n    originalImplementation,\n    resetToMockName: true,\n  })\n\n  try {\n    reassign(\n      ssr\n        ? () => mock\n        : mock,\n    )\n  }\n  catch (error) {\n    if (\n      error instanceof TypeError\n      && Symbol.toStringTag\n      && (object as any)[Symbol.toStringTag] === 'Module'\n      && (error.message.includes('Cannot redefine property')\n        || error.message.includes('Cannot replace module namespace')\n        || error.message.includes('can\\'t redefine non-configurable property'))\n    ) {\n      throw new TypeError(\n        `Cannot spy on export \"${String(key)}\". Module namespace is not configurable in ESM. See: https://vitest.dev/guide/browser/#limitations`,\n        { cause: error },\n      )\n    }\n\n    throw error\n  }\n\n  return mock\n}\n\nfunction getDescriptor(obj: any, method: string | symbol | number): [any, PropertyDescriptor] | undefined {\n  const objDescriptor = Object.getOwnPropertyDescriptor(obj, method)\n  if (objDescriptor) {\n    return [obj, objDescriptor]\n  }\n  let currentProto = Object.getPrototypeOf(obj)\n  while (currentProto !== null) {\n    const descriptor = Object.getOwnPropertyDescriptor(currentProto, method)\n    if (descriptor) {\n      return [currentProto, descriptor]\n    }\n    currentProto = Object.getPrototypeOf(currentProto)\n  }\n}\n\nfunction assert(condition: any, message: string): asserts condition {\n  if (!condition) {\n    throw new Error(message)\n  }\n}\n\nlet invocationCallCounter = 1\n\nfunction createMock(\n  {\n    state,\n    config,\n    name: mockName,\n    prototypeState,\n    prototypeConfig,\n    keepMembersImplementation,\n    mockImplementation,\n    prototypeMembers = [],\n  }: MockInstanceOption & {\n    state: MockContext\n    config: MockConfig\n  },\n) {\n  const original = config.mockOriginal // init with vi.spyOn(obj, 'Klass')\n  const pseudoOriginal = mockImplementation // init with vi.fn(Klass)\n  const name = (mockName || original?.name || 'Mock') as string\n  const namedObject: Record<string, Mock<Procedure | Constructable>> = {\n    // to keep the name of the function intact\n    [name]: (function (this: any, ...args: any[]) {\n      registerCalls(args, state, prototypeState)\n      registerInvocationOrder(invocationCallCounter++, state, prototypeState)\n\n      const result = {\n        type: 'incomplete',\n        value: undefined,\n      } as MockResult<Procedure>\n\n      const settledResult = {\n        type: 'incomplete',\n        value: undefined,\n      } as MockSettledResult<Procedure>\n\n      registerResult(result, state, prototypeState)\n      registerSettledResult(settledResult, state, prototypeState)\n\n      const context = new.target ? undefined : this\n      const [instanceIndex, instancePrototypeIndex] = registerInstance(context, state, prototypeState)\n      const [contextIndex, contextPrototypeIndex] = registerContext(context, state, prototypeState)\n\n      const implementation: Procedure | Constructable\n        = config.onceMockImplementations.shift()\n          || config.mockImplementation\n          || prototypeConfig?.onceMockImplementations.shift()\n          || prototypeConfig?.mockImplementation\n          || original\n          || function () {}\n\n      let returnValue\n      let thrownValue\n      let didThrow = false\n\n      try {\n        if (new.target) {\n          returnValue = Reflect.construct(implementation, args, new.target)\n\n          // jest calls this before the implementation, but we have to resolve this _after_\n          // because we cannot do it before the `Reflect.construct` called the custom implementation.\n          // fortunetly, the constructor is always an empty functon because `prototypeMethods`\n          // are only used by the automocker, so this doesn't matter\n          for (const prop of prototypeMembers) {\n            const prototypeMock = returnValue[prop]\n            // the method was overidden because of inheritence, ignore it\n            // eslint-disable-next-line ts/no-use-before-define\n            if (prototypeMock !== mock.prototype[prop]) {\n              continue\n            }\n\n            const isMock = isMockFunction(prototypeMock)\n            const prototypeState = isMock ? prototypeMock.mock : undefined\n            const prototypeConfig = isMock ? MOCK_CONFIGS.get(prototypeMock) : undefined\n            returnValue[prop] = createMockInstance({\n              originalImplementation: keepMembersImplementation\n                ? prototypeConfig?.mockOriginal\n                : undefined,\n              prototypeState,\n              prototypeConfig,\n              keepMembersImplementation,\n            })\n          }\n        }\n        else {\n          returnValue = (implementation as Procedure).apply(this, args)\n        }\n      }\n      catch (error: any) {\n        thrownValue = error\n        didThrow = true\n        if (error instanceof TypeError && error.message.includes('is not a constructor')) {\n          console.warn(`[vitest] The ${namedObject[name].getMockName()} mock did not use 'function' or 'class' in its implementation, see https://vitest.dev/api/vi#vi-spyon for examples.`)\n        }\n        throw error\n      }\n      finally {\n        if (didThrow) {\n          result.type = 'throw'\n          result.value = thrownValue\n\n          settledResult.type = 'rejected'\n          settledResult.value = thrownValue\n        }\n        else {\n          result.type = 'return'\n          result.value = returnValue\n\n          if (new.target) {\n            state.contexts[contextIndex - 1] = returnValue\n            state.instances[instanceIndex - 1] = returnValue\n\n            if (contextPrototypeIndex != null && prototypeState) {\n              prototypeState.contexts[contextPrototypeIndex - 1] = returnValue\n            }\n            if (instancePrototypeIndex != null && prototypeState) {\n              prototypeState.instances[instancePrototypeIndex - 1] = returnValue\n            }\n          }\n\n          if (returnValue instanceof Promise) {\n            returnValue.then(\n              (settledValue) => {\n                settledResult.type = 'fulfilled'\n                settledResult.value = settledValue\n              },\n              (rejectedValue) => {\n                settledResult.type = 'rejected'\n                settledResult.value = rejectedValue\n              },\n            )\n          }\n          else {\n            settledResult.type = 'fulfilled'\n            settledResult.value = returnValue\n          }\n        }\n      }\n\n      return returnValue\n    }) as Mock,\n  }\n  const mock = namedObject[name] as Mock<Procedure | Constructable>\n  const copyPropertiesFrom = original || pseudoOriginal\n  if (copyPropertiesFrom) {\n    copyOriginalStaticProperties(mock, copyPropertiesFrom)\n  }\n  return mock\n}\n\nfunction registerCalls(args: unknown[], state: MockContext, prototypeState?: MockContext) {\n  state.calls.push(args)\n  prototypeState?.calls.push(args)\n}\n\nfunction registerInvocationOrder(order: number, state: MockContext, prototypeState?: MockContext) {\n  state.invocationCallOrder.push(order)\n  prototypeState?.invocationCallOrder.push(order)\n}\n\nfunction registerResult(result: MockResult<Procedure>, state: MockContext, prototypeState?: MockContext) {\n  state.results.push(result)\n  prototypeState?.results.push(result)\n}\n\nfunction registerSettledResult(result: MockSettledResult<Procedure>, state: MockContext, prototypeState?: MockContext) {\n  state.settledResults.push(result)\n  prototypeState?.settledResults.push(result)\n}\n\nfunction registerInstance(instance: MockReturnType<Procedure>, state: MockContext, prototypeState?: MockContext) {\n  const instanceIndex = state.instances.push(instance)\n  const instancePrototypeIndex = prototypeState?.instances.push(instance)\n  return [instanceIndex, instancePrototypeIndex] as const\n}\n\nfunction registerContext(context: MockProcedureContext<Procedure>, state: MockContext, prototypeState?: MockContext) {\n  const contextIndex = state.contexts.push(context)\n  const contextPrototypeIndex = prototypeState?.contexts.push(context)\n  return [contextIndex, contextPrototypeIndex] as const\n}\n\nfunction copyOriginalStaticProperties(mock: Mock<Procedure | Constructable>, original: Procedure | Constructable) {\n  const { properties, descriptors } = getAllProperties(original)\n\n  for (const key of properties) {\n    const descriptor = descriptors[key]!\n    const mockDescriptor = getDescriptor(mock, key)\n    if (mockDescriptor) {\n      continue\n    }\n\n    Object.defineProperty(mock, key, descriptor)\n  }\n}\n\nconst ignoreProperties = new Set<string | symbol>([\n  'length',\n  'name',\n  'prototype',\n  Symbol.for('nodejs.util.promisify.custom'),\n])\n\nfunction getAllProperties(original: Procedure | Constructable) {\n  const properties = new Set<string | symbol>()\n  const descriptors: Record<string | symbol, PropertyDescriptor | undefined>\n    = {}\n  while (\n    original\n    && original !== Object.prototype\n    && original !== Function.prototype\n  ) {\n    const ownProperties = [\n      ...Object.getOwnPropertyNames(original),\n      ...Object.getOwnPropertySymbols(original),\n    ]\n    for (const prop of ownProperties) {\n      if (descriptors[prop] || ignoreProperties.has(prop)) {\n        continue\n      }\n      properties.add(prop)\n      descriptors[prop] = Object.getOwnPropertyDescriptor(original, prop)\n    }\n    original = Object.getPrototypeOf(original)\n  }\n  return {\n    properties,\n    descriptors,\n  }\n}\n\nfunction getDefaultConfig(original?: Procedure | Constructable): MockConfig {\n  return {\n    mockImplementation: undefined,\n    mockOriginal: original,\n    mockName: 'vi.fn()',\n    onceMockImplementations: [],\n  }\n}\n\nfunction getDefaultState(): MockContext {\n  const state = {\n    calls: [],\n    contexts: [],\n    instances: [],\n    invocationCallOrder: [],\n    settledResults: [],\n    results: [],\n    get lastCall() {\n      return state.calls.at(-1)\n    },\n  }\n  return state\n}\n\nexport function restoreAllMocks(): void {\n  for (const restore of MOCK_RESTORE) {\n    restore()\n  }\n  MOCK_RESTORE.clear()\n}\n\nexport function clearAllMocks(): void {\n  REGISTERED_MOCKS.forEach(mock => mock.mockClear())\n}\n\nexport function resetAllMocks(): void {\n  REGISTERED_MOCKS.forEach(mock => mock.mockReset())\n}\n\nfunction throwConstructorError(shorthand: string): never {\n  throw new TypeError(\n    `Cannot use \\`${shorthand}\\` when called with \\`new\\`. Use \\`mockImplementation\\` with a \\`class\\` keyword instead. See https://vitest.dev/api/mock#class-support for more information.`,\n  )\n}\n\nexport type {\n  Constructable,\n  MaybeMocked,\n  MaybeMockedConstructor,\n  MaybeMockedDeep,\n  MaybePartiallyMocked,\n  MaybePartiallyMockedDeep,\n  Mock,\n  MockContext,\n  Mocked,\n  MockedClass,\n  MockedFunction,\n  MockedFunctionDeep,\n  MockedObject,\n  MockedObjectDeep,\n  MockInstance,\n  MockInstanceOption,\n  MockParameters,\n  MockProcedureContext,\n  MockResult,\n  MockResultIncomplete,\n  MockResultReturn,\n  MockResultThrow,\n  MockReturnType,\n  MockSettledResult,\n  MockSettledResultFulfilled,\n  MockSettledResultIncomplete,\n  MockSettledResultRejected,\n  PartiallyMockedFunction,\n  PartiallyMockedFunctionDeep,\n  PartialMock,\n  Procedure,\n} from './types'\n"
  },
  {
    "path": "packages/spy/src/types.ts",
    "content": "export interface MockResultReturn<T> {\n  type: 'return'\n  /**\n   * The value that was returned from the function. If function returned a Promise, then this will be a resolved value.\n   */\n  value: T\n}\nexport interface MockResultIncomplete {\n  type: 'incomplete'\n  value: undefined\n}\nexport interface MockResultThrow {\n  type: 'throw'\n  /**\n   * An error that was thrown during function execution.\n   */\n  value: any\n}\n\nexport interface MockSettledResultIncomplete {\n  type: 'incomplete'\n  value: undefined\n}\n\nexport interface MockSettledResultFulfilled<T> {\n  type: 'fulfilled'\n  value: T\n}\n\nexport interface MockSettledResultRejected {\n  type: 'rejected'\n  value: any\n}\n\nexport type MockResult<T>\n  = | MockResultReturn<T>\n    | MockResultThrow\n    | MockResultIncomplete\nexport type MockSettledResult<T>\n  = | MockSettledResultFulfilled<T>\n    | MockSettledResultRejected\n    | MockSettledResultIncomplete\n\nexport type MockParameters<T extends Procedure | Constructable> = T extends Constructable\n  ? ConstructorParameters<T>\n  : T extends Procedure\n    ? Parameters<T> : never\n\nexport type MockReturnType<T extends Procedure | Constructable> = T extends Constructable\n  ? InstanceType<T>\n  : T extends Procedure\n    ? ReturnType<T> : never\n\nexport type MockProcedureContext<T extends Procedure | Constructable> = T extends Constructable\n  ? InstanceType<T>\n  : ThisParameterType<T>\n\nexport interface MockContext<T extends Procedure | Constructable = Procedure> {\n  /**\n   * This is an array containing all arguments for each call. One item of the array is the arguments of that call.\n   *\n   * @see https://vitest.dev/api/mock#mock-calls\n   * @example\n   * const fn = vi.fn()\n   *\n   * fn('arg1', 'arg2')\n   * fn('arg3')\n   *\n   * fn.mock.calls === [\n   *   ['arg1', 'arg2'], // first call\n   *   ['arg3'], // second call\n   * ]\n   */\n  calls: MockParameters<T>[]\n  /**\n   * This is an array containing all instances that were instantiated when mock was called with a `new` keyword. Note that this is an actual context (`this`) of the function, not a return value.\n   * @see https://vitest.dev/api/mock#mock-instances\n   */\n  instances: MockProcedureContext<T>[]\n  /**\n   * An array of `this` values that were used during each call to the mock function.\n   * @see https://vitest.dev/api/mock#mock-contexts\n   */\n  contexts: MockProcedureContext<T>[]\n  /**\n   * The order of mock's execution. This returns an array of numbers which are shared between all defined mocks.\n   *\n   * @see https://vitest.dev/api/mock#mock-invocationcallorder\n   * @example\n   * const fn1 = vi.fn()\n   * const fn2 = vi.fn()\n   *\n   * fn1()\n   * fn2()\n   * fn1()\n   *\n   * fn1.mock.invocationCallOrder === [1, 3]\n   * fn2.mock.invocationCallOrder === [2]\n   */\n  invocationCallOrder: number[]\n  /**\n   * This is an array containing all values that were `returned` from the function.\n   *\n   * The `value` property contains the returned value or thrown error. If the function returned a `Promise`, then `result` will always be `'return'` even if the promise was rejected.\n   *\n   * @see https://vitest.dev/api/mock#mock-results\n   * @example\n   * const fn = vi.fn()\n   *   .mockReturnValueOnce('result')\n   *   .mockImplementationOnce(() => { throw new Error('thrown error') })\n   *\n   * const result = fn()\n   *\n   * try {\n   *   fn()\n   * }\n   * catch {}\n   *\n   * fn.mock.results === [\n   *   {\n   *     type: 'return',\n   *     value: 'result',\n   *   },\n   *   {\n   *     type: 'throw',\n   *     value: Error,\n   *   },\n   * ]\n   */\n  results: MockResult<MockReturnType<T>>[]\n  /**\n   * An array containing all values that were `resolved` or `rejected` from the function.\n   *\n   * This array will be empty if the function was never resolved or rejected.\n   *\n   * @see https://vitest.dev/api/mock#mock-settledresults\n   * @example\n   * const fn = vi.fn().mockResolvedValueOnce('result')\n   *\n   * const result = fn()\n   *\n   * fn.mock.settledResults === [\n   *   {\n   *     type: 'incomplete',\n   *     value: undefined,\n   *   }\n   * ]\n   * fn.mock.results === [\n   *   {\n   *     type: 'return',\n   *     value: Promise<'result'>,\n   *   },\n   * ]\n   *\n   * await result\n   *\n   * fn.mock.settledResults === [\n   *   {\n   *     type: 'fulfilled',\n   *     value: 'result',\n   *   },\n   * ]\n   */\n  settledResults: MockSettledResult<Awaited<MockReturnType<T>>>[]\n  /**\n   * This contains the arguments of the last call. If spy wasn't called, will return `undefined`.\n   * @see https://vitest.dev/api/mock#mock-lastcall\n   */\n  lastCall: MockParameters<T> | undefined\n}\n\nexport type Procedure = (...args: any[]) => any\n// pick a single function type from function overloads, unions, etc...\nexport type NormalizedProcedure<T extends Procedure | Constructable> = T extends Constructable\n  ? ({\n    new (...args: ConstructorParameters<T>): InstanceType<T>\n  })\n  | ({\n    (this: InstanceType<T>, ...args: ConstructorParameters<T>): void\n  })\n  : T extends Procedure\n    ? (...args: Parameters<T>) => ReturnType<T>\n    : never\n\nexport type Methods<T> = keyof {\n  [K in keyof T as T[K] extends Procedure ? K : never]: T[K];\n}\nexport type Properties<T> = {\n  [K in keyof T]: T[K] extends Procedure ? never : K;\n}[keyof T]\n& (string | symbol)\nexport type Classes<T> = {\n  [K in keyof T]: T[K] extends new (...args: any[]) => any ? K : never;\n}[keyof T]\n& (string | symbol)\n\n/*\ncf. https://typescript-eslint.io/rules/method-signature-style/\n\nTypescript assignability is different between\n  { foo: (f: T) => U } (this is \"method-signature-style\")\nand\n  { foo(f: T): U }\n\nJest uses the latter for `MockInstance.mockImplementation` etc... and it allows assignment such as:\n  const boolFn: Jest.Mock<() => boolean> = jest.fn<() => true>(() => true)\n*/\n/* eslint-disable ts/method-signature-style */\nexport interface MockInstance<T extends Procedure | Constructable = Procedure> extends Disposable {\n  /**\n   * Use it to return the name assigned to the mock with the `.mockName(name)` method. By default, it will return `vi.fn()`.\n   * @see https://vitest.dev/api/mock#getmockname\n   */\n  getMockName(): string\n  /**\n   * Sets the internal mock name. This is useful for identifying the mock when an assertion fails.\n   * @see https://vitest.dev/api/mock#mockname\n   */\n  mockName(name: string): this\n  /**\n   * Current context of the mock. It stores information about all invocation calls, instances, and results.\n   */\n  mock: MockContext<T>\n  /**\n   * Clears all information about every call. After calling it, all properties on `.mock` will return to their initial state. This method does not reset implementations. It is useful for cleaning up mocks between different assertions.\n   *\n   * To automatically call this method before each test, enable the [`clearMocks`](https://vitest.dev/config/clearmocks) setting in the configuration.\n   * @see https://vitest.dev/api/mock#mockclear\n   */\n  mockClear(): this\n  /**\n   * Does what `mockClear` does and resets inner implementation to the original function. This also resets all \"once\" implementations.\n   *\n   * Note that resetting a mock from `vi.fn()` will set implementation to an empty function that returns `undefined`.\n   * Resetting a mock from `vi.fn(impl)` will set implementation to `impl`. It is useful for completely resetting a mock to its default state.\n   *\n   * To automatically call this method before each test, enable the [`mockReset`](https://vitest.dev/config/mockreset) setting in the configuration.\n   * @see https://vitest.dev/api/mock#mockreset\n   */\n  mockReset(): this\n  /**\n   * Does what `mockReset` does and restores original descriptors of spied-on objects.\n   * @see https://vitest.dev/api/mock#mockrestore\n   */\n  mockRestore(): void\n  /**\n   * Returns current permanent mock implementation if there is one.\n   *\n   * If mock was created with `vi.fn`, it will consider passed down method as a mock implementation.\n   *\n   * If mock was created with `vi.spyOn`, it will return `undefined` unless a custom implementation was provided.\n   */\n  getMockImplementation(): NormalizedProcedure<T> | undefined\n  /**\n   * Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function.\n   * @see https://vitest.dev/api/mock#mockimplementation\n   * @example\n   * const increment = vi.fn().mockImplementation(count => count + 1);\n   * expect(increment(3)).toBe(4);\n   */\n  mockImplementation(fn: NormalizedProcedure<T>): this\n  /**\n   * Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function. This method can be chained to produce different results for multiple function calls.\n   *\n   * When the mocked function runs out of implementations, it will invoke the default implementation set with `vi.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called.\n   * @see https://vitest.dev/api/mock#mockimplementationonce\n   * @example\n   * const fn = vi.fn(count => count).mockImplementationOnce(count => count + 1);\n   * expect(fn(3)).toBe(4);\n   * expect(fn(3)).toBe(3);\n   */\n  mockImplementationOnce(fn: NormalizedProcedure<T>): this\n  /**\n   * Overrides the original mock implementation temporarily while the callback is being executed.\n   *\n   * Note that this method takes precedence over the [`mockImplementationOnce`](https://vitest.dev/api/mock#mockimplementationonce).\n   * @see https://vitest.dev/api/mock#withimplementation\n   * @example\n   * const myMockFn = vi.fn(() => 'original')\n   *\n   * myMockFn.withImplementation(() => 'temp', () => {\n   *   myMockFn() // 'temp'\n   * })\n   *\n   * myMockFn() // 'original'\n   */\n  withImplementation(fn: NormalizedProcedure<T>, cb: () => Promise<unknown>): Promise<this>\n  withImplementation(fn: NormalizedProcedure<T>, cb: () => unknown): this\n\n  /**\n   * Use this if you need to return the `this` context from the method without invoking the actual implementation.\n   * @see https://vitest.dev/api/mock#mockreturnthis\n   */\n  mockReturnThis(): this\n  /**\n   * Accepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function.\n   * @see https://vitest.dev/api/mock#mockreturnvalue\n   * @example\n   * const mock = vi.fn()\n   * mock.mockReturnValue(42)\n   * mock() // 42\n   * mock.mockReturnValue(43)\n   * mock() // 43\n   */\n  mockReturnValue(value: MockReturnType<T>): this\n  /**\n   * Accepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function.\n   *\n   * When the mocked function runs out of implementations, it will invoke the default implementation set with `vi.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called.\n   * @example\n   * const myMockFn = vi\n   *   .fn()\n   *   .mockReturnValue('default')\n   *   .mockReturnValueOnce('first call')\n   *   .mockReturnValueOnce('second call')\n   *\n   * // 'first call', 'second call', 'default'\n   * console.log(myMockFn(), myMockFn(), myMockFn())\n   */\n  mockReturnValueOnce(value: MockReturnType<T>): this\n  /**\n   * Accepts a value that will be thrown whenever the mock function is called.\n   * @see https://vitest.dev/api/mock#mockthrow\n   * @example\n   * const myMockFn = vi.fn().mockThrow(new Error('error'))\n   * myMockFn() // throws 'error'\n   */\n  mockThrow(value: unknown): this\n  /**\n   * Accepts a value that will be thrown during the next function call. If chained, every consecutive call will throw the specified value.\n   * @example\n   * const myMockFn = vi\n   *   .fn()\n   *   .mockReturnValue('default')\n   *   .mockThrowOnce(new Error('first call error'))\n   *   .mockThrowOnce('second call error')\n   *\n   * expect(() => myMockFn()).toThrowError('first call error')\n   * expect(() => myMockFn()).toThrowError('second call error')\n   * expect(myMockFn()).toEqual('default')\n   */\n  mockThrowOnce(value: unknown): this\n  /**\n   * Accepts a value that will be resolved when the async function is called. TypeScript will only accept values that match the return type of the original function.\n   * @example\n   * const asyncMock = vi.fn().mockResolvedValue(42)\n   * asyncMock() // Promise<42>\n   */\n  mockResolvedValue(value: Awaited<MockReturnType<T>>): this\n  /**\n   * Accepts a value that will be resolved during the next function call. TypeScript will only accept values that match the return type of the original function. If chained, each consecutive call will resolve the specified value.\n   * @example\n   * const myMockFn = vi\n   *   .fn()\n   *   .mockResolvedValue('default')\n   *   .mockResolvedValueOnce('first call')\n   *   .mockResolvedValueOnce('second call')\n   *\n   * // Promise<'first call'>, Promise<'second call'>, Promise<'default'>\n   * console.log(myMockFn(), myMockFn(), myMockFn())\n   */\n  mockResolvedValueOnce(value: Awaited<MockReturnType<T>>): this\n  /**\n   * Accepts an error that will be rejected when async function is called.\n   * @example\n   * const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'))\n   * await asyncMock() // throws Error<'Async error'>\n   */\n  mockRejectedValue(error: unknown): this\n  /**\n   * Accepts a value that will be rejected during the next function call. If chained, each consecutive call will reject the specified value.\n   * @example\n   * const asyncMock = vi\n   *   .fn()\n   *   .mockResolvedValueOnce('first call')\n   *   .mockRejectedValueOnce(new Error('Async error'))\n   *\n   * await asyncMock() // first call\n   * await asyncMock() // throws Error<'Async error'>\n   */\n  mockRejectedValueOnce(error: unknown): this\n  /** @internal */\n  _isMockFunction: true\n}\n/* eslint-enable ts/method-signature-style */\n\nexport type Mock<T extends Procedure | Constructable = Procedure> = MockInstance<T> & (\n  T extends Constructable\n    ? (\n        T extends Procedure\n          // supports both `new Class()` and `Class()`\n          ? {\n              new (...args: ConstructorParameters<T>): InstanceType<T>\n              (...args: Parameters<T>): ReturnType<T>\n            }\n          // supports only `new Class()`\n          : {\n              new (...args: ConstructorParameters<T>): InstanceType<T>\n            }\n      )\n    // any function can be called with the new keyword\n    : {\n        new (...args: MockParameters<T>): MockReturnType<T>\n        (...args: MockParameters<T>): MockReturnType<T>\n      }\n) & { [P in keyof T]: T[P] }\n\ntype PartialMaybePromise<T> = T extends Promise<Awaited<T>>\n  ? Promise<Partial<Awaited<T>>>\n  : Partial<T>\n\ntype PartialResultFunction<T> = T extends Constructable\n  ? ({\n    new (...args: ConstructorParameters<T>): InstanceType<T>\n  })\n  | ({\n    (this: InstanceType<T>, ...args: ConstructorParameters<T>): void\n  })\n  : T extends Procedure\n    ? (...args: Parameters<T>) => PartialMaybePromise<ReturnType<T>>\n    : T\n\nexport type PartialMock<T extends Procedure | Constructable = Procedure> = Mock<\n  PartialResultFunction<\n    T extends Mock\n      ? NonNullable<ReturnType<T['getMockImplementation']>>\n      : T\n  >\n>\n\ntype DeepPartial<T> = T extends Procedure\n  ? T\n  : T extends Array<infer U>\n    ? Array<DeepPartial<U>>\n    : T extends object\n      ? { [K in keyof T]?: DeepPartial<T[K]> }\n      : T\n\ntype DeepPartialMaybePromise<T> = T extends Promise<Awaited<T>>\n  ? Promise<DeepPartial<Awaited<T>>>\n  : DeepPartial<T>\n\ntype DeepPartialResultFunction<T> = T extends Constructable\n  ? ({\n    new (...args: ConstructorParameters<T>): InstanceType<T>\n  })\n  | ({\n    (this: InstanceType<T>, ...args: ConstructorParameters<T>): void\n  })\n  : T extends Procedure\n    ? (...args: Parameters<T>) => DeepPartialMaybePromise<ReturnType<T>>\n    : T\n\ntype DeepPartialMock<T extends Procedure | Constructable = Procedure> = Mock<\n  DeepPartialResultFunction<\n    T extends Mock\n      ? NonNullable<ReturnType<T['getMockImplementation']>>\n      : T\n  >\n>\n\nexport type MaybeMockedConstructor<T> = T extends Constructable\n  ? Mock<T>\n  : T\nexport type MockedFunction<T extends Procedure | Constructable> = Mock<T>\n  & MockedObject<T>\nexport type PartiallyMockedFunction<T extends Procedure | Constructable> = PartialMock<T>\n  & MockedObject<T>\nexport type MockedFunctionDeep<T extends Procedure | Constructable> = Mock<T>\n  & MockedObjectDeep<T>\nexport type PartiallyMockedFunctionDeep<T extends Procedure | Constructable> = DeepPartialMock<T>\n  & MockedObjectDeep<T>\nexport type MockedObject<T> = MaybeMockedConstructor<T> & {\n  [K in Methods<T>]: T[K] extends Procedure ? MockedFunction<T[K]> : T[K];\n} & { [K in Properties<T>]: T[K] }\nexport type MockedObjectDeep<T> = MaybeMockedConstructor<T> & {\n  [K in Methods<T>]: T[K] extends Procedure ? MockedFunctionDeep<T[K]> : T[K];\n} & { [K in Properties<T>]: MaybeMockedDeep<T[K]> }\n\nexport type MaybeMockedDeep<T> = T extends Procedure | Constructable\n  ? MockedFunctionDeep<T>\n  : T extends object\n    ? MockedObjectDeep<T>\n    : T\n\nexport type MaybePartiallyMockedDeep<T> = T extends Procedure | Constructable\n  ? PartiallyMockedFunctionDeep<T>\n  : T extends object\n    ? MockedObjectDeep<T>\n    : T\n\nexport type MaybeMocked<T> = T extends Procedure | Constructable\n  ? MockedFunction<T>\n  : T extends object\n    ? MockedObject<T>\n    : T\n\nexport type MaybePartiallyMocked<T> = T extends Procedure | Constructable\n  ? PartiallyMockedFunction<T>\n  : T extends object\n    ? MockedObject<T>\n    : T\n\nexport interface Constructable {\n  new (...args: any[]): any\n}\n\nexport type MockedClass<T extends Constructable> = MockInstance<T> & {\n  prototype: T extends { prototype: any } ? Mocked<T['prototype']> : never\n} & T\n\nexport type Mocked<T> = {\n  [P in keyof T]: T[P] extends Procedure\n    ? MockInstance<T[P]>\n    : T[P] extends Constructable\n      ? MockedClass<T[P]>\n      : T[P];\n} & T\n\nexport interface MockConfig {\n  mockImplementation: Procedure | Constructable | undefined\n  mockOriginal: Procedure | Constructable | undefined\n  mockName: string\n  onceMockImplementations: Array<Procedure | Constructable>\n}\n\nexport interface MockInstanceOption {\n  originalImplementation?: Procedure | Constructable\n  mockImplementation?: Procedure | Constructable\n  resetToMockImplementation?: boolean\n  restore?: () => void\n  prototypeMembers?: (string | symbol)[]\n  keepMembersImplementation?: boolean\n  prototypeState?: MockContext\n  prototypeConfig?: MockConfig\n  resetToMockName?: boolean\n  name?: string | symbol\n}\n"
  },
  {
    "path": "packages/spy/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"moduleResolution\": \"Bundler\",\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"./dist\"]\n}\n"
  },
  {
    "path": "packages/ui/CONTRIBUTING.md",
    "content": "At project root, create terminals with each of the following commands:\n\n```bash\nnr ui:dev\n```\n\n```bash\nnr test --api\n```\n\nAs the last command, you can use any of the available tests suites instead. Make sure that they run at 51204 port or specify a custom port with `VITE_PORT` environmental variable when running the first command. For example,\n\n```bash\nVITE_PORT=3200 nr ui:dev\n```\n\n```bash\nnr test --api=3200\n```\n\nOpen the browser at the URL printed by the first command. For example, `http://localhost:5173/`. If you see a connection error, it means the port is specified incorrectly.\n\nTo preview the browser tab, uncomment the \"browser-dev-preview\" plugin in `vite.config.ts`.\n\nTo configure the browser state, update the `__vitest_browser_runner__` object in `browser.dev.js`.\n"
  },
  {
    "path": "packages/ui/README.md",
    "content": "# @vitest/ui\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/ui?color=a1b858&label=)](https://npmx.dev/package/@vitest/ui)\n\nSee your test results in the browser.\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/ui) | [Documentation](https://vitest.dev/guide/ui)\n"
  },
  {
    "path": "packages/ui/browser.dev.js",
    "content": "window.__vitest_browser_runner__ = {\n  files: [],\n  config: {\n    browser: {\n      name: 'chrome',\n    },\n  },\n  type: 'orchestrator',\n  provider: 'playwright',\n  wrapModule: () => {},\n}\n"
  },
  {
    "path": "packages/ui/client/App.vue",
    "content": "<template>\n  <RouterView />\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/AnnotationAttachmentImage.vue",
    "content": "<script setup lang=\"ts\">\nimport type { TestAnnotation } from 'vitest'\nimport { computed } from 'vue'\nimport { getAttachmentUrl, isExternalAttachment } from '~/composables/attachments'\n\nconst props = defineProps<{\n  annotation: TestAnnotation\n}>()\n\nconst href = computed<string>(() => {\n  const attachment = props.annotation.attachment!\n  const potentialUrl = attachment.path || attachment.body\n  if (typeof potentialUrl === 'string' && (potentialUrl.startsWith('http://') || potentialUrl.startsWith('https://'))) {\n    return potentialUrl\n  }\n  else {\n    return getAttachmentUrl(attachment)\n  }\n})\n</script>\n\n<template>\n  <a\n    v-if=\"annotation.attachment && annotation.attachment.contentType?.startsWith('image/')\"\n    target=\"_blank\"\n    class=\"inline-block mt-2\"\n    :style=\"{ maxWidth: '600px' }\"\n    :href=\"href\"\n    :referrerPolicy=\"isExternalAttachment(annotation.attachment) ? 'no-referrer' : undefined\"\n  >\n    <img\n      :src=\"href\"\n    >\n  </a>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/Badge.vue",
    "content": "<script setup lang=\"ts\">\nconst { type = 'info' } = defineProps<{\n  type?: 'danger' | 'warning' | 'info' | 'tip' | 'custom'\n}>()\n</script>\n\n<template>\n  <span\n    class=\"rounded-full py-0.5 px-2 text-xs text-white select-none\"\n    :class=\"{\n      'bg-red': type === 'danger',\n      'bg-orange': type === 'warning',\n      'bg-gray': type === 'info',\n      'bg-indigo/60': type === 'tip',\n    }\"\n  >\n    <slot />\n  </span>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/BrowserIframe.vue",
    "content": "<script setup lang=\"ts\">\nimport type { ViewportSize } from '~/composables/browser'\nimport { useWindowSize } from '@vueuse/core'\nimport { computed } from 'vue'\nimport { viewport } from '~/composables/browser'\nimport { browserState } from '~/composables/client'\nimport {\n  detailsPanelVisible,\n  detailsPosition,\n  panels,\n  showNavigationPanel,\n  updateBrowserPanel,\n} from '~/composables/navigation'\nimport IconButton from './IconButton.vue'\n\nconst sizes: Record<ViewportSize, [width: number, height: number]> = {\n  'small-mobile': [320, 568],\n  'large-mobile': [414, 896],\n  'tablet': [834, 1112],\n}\n\nfunction isViewport(name: ViewportSize) {\n  const preset = sizes[name]\n  return viewport.value[0] === preset[0] && viewport.value[1] === preset[1]\n}\n\nconst { width: windowWidth, height: windowHeight } = useWindowSize()\n\nasync function changeViewport(name: ViewportSize) {\n  viewport.value = sizes[name]\n  if (browserState?.provider === 'webdriverio') {\n    updateBrowserPanel()\n  }\n}\n\nconst PADDING_SIDES = 20\nconst PADDING_TOP = 100\n\nconst containerSize = computed(() => {\n  if (browserState?.provider === 'webdriverio') {\n    const [width, height] = viewport.value\n    return { width, height }\n  }\n\n  const parentContainerWidth = windowWidth.value * (panels.details.size / 100)\n  const parentOffsetWidth = parentContainerWidth * (panels.details.browser / 100)\n  const containerWidth = parentOffsetWidth - PADDING_SIDES\n  const containerHeight = windowHeight.value - PADDING_TOP\n  return {\n    width: containerWidth,\n    height: containerHeight,\n  }\n})\n\nconst scale = computed(() => {\n  if (browserState?.provider === 'webdriverio') {\n    return 1\n  }\n\n  const [iframeWidth, iframeHeight] = viewport.value\n  const { width: containerWidth, height: containerHeight } = containerSize.value\n  const widthScale = containerWidth > iframeWidth ? 1 : containerWidth / iframeWidth\n  const heightScale = containerHeight > iframeHeight ? 1 : containerHeight / iframeHeight\n  return Math.min(1, widthScale, heightScale)\n})\n\nconst marginLeft = computed(() => {\n  const containerWidth = containerSize.value.width\n  const iframeWidth = viewport.value[0]\n  const offset = Math.trunc((containerWidth + PADDING_SIDES - iframeWidth) / 2)\n  return `${offset}px`\n})\n</script>\n\n<template>\n  <div h=\"full\" flex=\"~ col\">\n    <div p=\"3\" h-10 flex=\"~ gap-2\" items-center bg-header border=\"b base\">\n      <IconButton\n        v-show=\"panels.navigation <= 15\"\n        v-tooltip.bottom=\"'Show Navigation Panel'\"\n        title=\"Show Navigation Panel\"\n        rotate-180\n        icon=\"i-carbon:side-panel-close\"\n        @click=\"showNavigationPanel()\"\n      />\n      <div class=\"i-carbon-content-delivery-network\" />\n      <span pl-1 font-bold text-sm flex-auto ws-nowrap overflow-hidden truncate>Browser UI</span>\n      <IconButton\n        v-show=\"detailsPosition === 'right' && !detailsPanelVisible\"\n        v-tooltip.bottom=\"'Show Details Panel'\"\n        title=\"Show Details Panel\"\n        icon=\"i-carbon:side-panel-close\"\n        @click=\"detailsPanelVisible = true\"\n      />\n    </div>\n    <div p=\"l3 y2 r2\" flex=\"~ gap-2\" items-center bg-header border=\"b-2 base\">\n      <!-- TODO: these are only for preview (thank you Storybook!), we need to support more different and custom sizes (as a dropdown) -->\n      <IconButton\n        v-tooltip.bottom=\"'Small mobile'\"\n        title=\"Small mobile\"\n        icon=\"i-carbon:mobile\"\n        :active=\"isViewport('small-mobile')\"\n        @click=\"changeViewport('small-mobile')\"\n      />\n      <IconButton\n        v-tooltip.bottom=\"'Large mobile'\"\n        title=\"Large mobile\"\n        icon=\"i-carbon:mobile-add\"\n        :active=\"isViewport('large-mobile')\"\n        @click=\"changeViewport('large-mobile')\"\n      />\n      <IconButton\n        v-tooltip.bottom=\"'Tablet'\"\n        title=\"Tablet\"\n        icon=\"i-carbon:tablet\"\n        :active=\"isViewport('tablet')\"\n        @click=\"changeViewport('tablet')\"\n      />\n      <span class=\"pointer-events-none\" text-sm>\n        {{ viewport[0] }}x{{ viewport[1] }}px\n        <span v-if=\"scale < 1\">({{ (scale * 100).toFixed(0) }}%)</span>\n      </span>\n    </div>\n    <div id=\"tester-container\" relative>\n      <div\n        id=\"tester-ui\"\n        class=\"flex h-full justify-center items-center font-light op70\"\n        :data-scale=\"scale\"\n        :style=\"{\n          '--viewport-width': `${viewport[0]}px`,\n          '--viewport-height': `${viewport[1]}px`,\n          '--tester-transform': `scale(${scale})`,\n          '--tester-margin-left': marginLeft,\n        }\"\n      >\n        Select a test to run\n      </div>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n#tester-container:not([data-ready]) {\n  width: 100%;\n  height: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n[data-ready] #tester-ui {\n  width: var(--viewport-width);\n  height: var(--viewport-height);\n  transform: var(--tester-transform);\n  margin-left: var(--tester-margin-left);\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/ClosedDetailsHeader.vue",
    "content": "<script setup lang=\"ts\">\nimport DetailsHeaderButtons from '~/components/DetailsHeaderButtons.vue'\n</script>\n\n<template>\n  <div\n    p=\"2\"\n    flex=\"~ gap-2\"\n    items-center\n    bg-header\n    border=\"b base\"\n  >\n    <div flex-1 />\n    <DetailsHeaderButtons />\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/CodeMirrorContainer.vue",
    "content": "<script setup lang=\"ts\">\nimport type { EditorFromTextArea } from 'codemirror'\nimport type { Ref } from 'vue'\nimport { onMounted, ref, useAttrs } from 'vue'\nimport { codemirrorRef, useCodeMirror } from '~/composables/codemirror'\n\nconst { mode, readOnly } = defineProps<{\n  mode?: string\n  readOnly?: boolean\n  saving?: boolean\n}>()\n\nconst emit = defineEmits<{\n  (event: 'save', content: string): void\n  (event: 'codemirror', codemirror: EditorFromTextArea): void\n}>()\n\nconst modelValue = defineModel<string>()\n\nconst attrs = useAttrs()\n\nconst modeMap: Record<string, any> = {\n  html: 'htmlmixed',\n  vue: 'htmlmixed',\n  svelte: 'htmlmixed',\n  js: 'javascript',\n  mjs: 'javascript',\n  cjs: 'javascript',\n  ts: { name: 'javascript', typescript: true },\n  mts: { name: 'javascript', typescript: true },\n  cts: { name: 'javascript', typescript: true },\n  jsx: { name: 'javascript', jsx: true },\n  tsx: { name: 'javascript', typescript: true, jsx: true },\n}\n\nconst el = ref<HTMLTextAreaElement>()\n\nonMounted(async () => {\n  // useCodeMirror will remove the codemirrorRef.value on onUnmounted callback\n  const codemirror = useCodeMirror(el, modelValue as unknown as Ref<string>, {\n    ...attrs,\n    mode: modeMap[mode || ''] || mode,\n    readOnly: readOnly ? true : undefined,\n    extraKeys: {\n      'Cmd-S': function (cm) {\n        const isReadonly = cm.getOption('readOnly')\n        if (!isReadonly) {\n          emit('save', cm.getValue())\n        }\n      },\n      'Ctrl-S': function (cm) {\n        const isReadonly = cm.getOption('readOnly')\n        if (!isReadonly) {\n          emit('save', cm.getValue())\n        }\n      },\n    },\n  })\n\n  codemirror.on('refresh', () => {\n    emit('codemirror', codemirror)\n  })\n  codemirror.on('change', () => {\n    emit('codemirror', codemirror)\n  })\n  codemirror.setSize('100%', '100%')\n  codemirror.clearHistory()\n  codemirrorRef.value = codemirror\n  setTimeout(() => codemirrorRef.value?.refresh(), 100)\n})\n</script>\n\n<template>\n  <div relative font-mono text-sm class=\"codemirror-scrolls\" :class=\"saving ? 'codemirror-busy' : undefined\">\n    <textarea ref=\"el\" />\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/ConnectionOverlay.vue",
    "content": "<script setup lang=\"ts\">\nimport {\n  browserState,\n  client,\n  isConnected,\n  isConnecting,\n} from '~/composables/client'\n</script>\n\n<template>\n  <template v-if=\"!isConnected\">\n    <div\n      fixed\n      inset-0\n      p2\n      z-10\n      select-none\n      text=\"center sm\"\n      bg=\"overlay\"\n      backdrop-blur-sm\n      backdrop-saturate-0\n      @click=\"client.reconnect\"\n    >\n      <div\n        h-full\n        flex=\"~ col gap-2\"\n        items-center\n        justify-center\n        :class=\"isConnecting ? 'animate-pulse' : ''\"\n      >\n        <div\n          text=\"5xl\"\n          :class=\"\n            isConnecting\n              ? 'i-carbon:renew animate-spin animate-reverse'\n              : 'i-carbon-wifi-off'\n          \"\n        />\n        <div text-2xl>\n          {{ isConnecting ? \"Connecting...\" : \"Disconnected\" }}\n        </div>\n        <div text-lg op50>\n          Check your terminal or start a new server with `{{\n            browserState\n              ? `vitest --browser=${browserState.config.browser.name}`\n              : \"vitest --ui\"\n          }}`\n        </div>\n      </div>\n    </div>\n  </template>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/Coverage.vue",
    "content": "<script setup lang=\"ts\">\nimport DetailsHeaderButtons from '~/components/DetailsHeaderButtons.vue'\nimport { browserState } from '~/composables/client'\n</script>\n\n<template>\n  <div h=\"full\" flex=\"~ col\">\n    <div p=\"3\" h-10 flex=\"~ gap-2\" items-center bg-header border=\"b base\">\n      <div class=\"i-carbon:folder-details-reference\" />\n      <span pl-1 font-bold text-sm flex-auto ws-nowrap overflow-hidden truncate>Coverage</span>\n      <DetailsHeaderButtons v-if=\"browserState\" />\n    </div>\n    <div flex-auto py-1 bg-white>\n      <iframe id=\"vitest-ui-coverage\" src=\"./coverage/index.html\" />\n    </div>\n  </div>\n</template>\n\n<style>\n#vitest-ui-coverage {\n  width: 100%;\n  height: calc(100vh - 42px);\n  border: none;\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/Dashboard.vue",
    "content": "<script setup lang=\"ts\">\nimport DetailsHeaderButtons from '~/components/DetailsHeaderButtons.vue'\nimport { browserState } from '~/composables/client'\nimport TestsFilesContainer from './dashboard/TestsFilesContainer.vue'\n</script>\n\n<template>\n  <div h=\"full\" flex=\"~ col\">\n    <div p=\"3\" h-10 flex=\"~ gap-2\" items-center bg-header border=\"b base\">\n      <div class=\"i-carbon-dashboard\" />\n      <span pl-1 font-bold text-sm flex-auto ws-nowrap overflow-hidden truncate>Dashboard</span>\n      <DetailsHeaderButtons v-if=\"browserState\" />\n    </div>\n    <div class=\"scrolls\" flex-auto py-1>\n      <TestsFilesContainer />\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/DetailsHeaderButtons.vue",
    "content": "<script setup lang=\"ts\">\nimport IconButton from '~/components/IconButton.vue'\nimport {\n  detailsPanelVisible,\n  detailsPosition,\n  hideDetailsPanel,\n  showDetailsPanel,\n  toggleDetailsPosition,\n} from '~/composables/navigation'\n\nfunction getDetailsPanelToggleRotation(action: 'show' | 'hide') {\n  // `i-carbon:side-panel-close` is treated as \"pointing right\" by default.\n  // We rotate it based on where the details panel is positioned.\n  if (detailsPosition.value === 'right') {\n    return action === 'hide' ? 'rotate-180' : ''\n  }\n  // detailsPosition === 'bottom'\n  return action === 'hide' ? '-rotate-90' : 'rotate-90'\n}\n</script>\n\n<template>\n  <IconButton\n    v-tooltip.bottom=\"`Switch panel position (${detailsPosition === 'bottom' ? 'right' : 'bottom'})`\"\n    :title=\"`Switch panel position (${detailsPosition === 'bottom' ? 'right' : 'bottom'})`\"\n    icon=\"i-carbon-split-screen\"\n    :class=\"{ 'rotate-90': detailsPosition === 'right' }\"\n    @click=\"toggleDetailsPosition\"\n  />\n  <IconButton\n    v-if=\"detailsPanelVisible\"\n    v-tooltip.bottom=\"detailsPosition === 'right' ? 'Hide Right Panel' : 'Hide Bottom Panel'\"\n    :title=\"detailsPosition === 'right' ? 'Hide Right Panel' : 'Hide Bottom Panel'\"\n    icon=\"i-carbon:side-panel-close\"\n    :class=\"getDetailsPanelToggleRotation('hide')\"\n    @click=\"hideDetailsPanel\"\n  />\n  <IconButton\n    v-show=\"!detailsPanelVisible\"\n    v-tooltip.bottom=\"detailsPosition === 'right' ? 'Show Right Panel' : 'Show Bottom Panel'\"\n    :title=\"detailsPosition === 'right' ? 'Show Right Panel' : 'Show Bottom Panel'\"\n    icon=\"i-carbon:side-panel-close\"\n    :class=\"getDetailsPanelToggleRotation('show')\"\n    @click=\"showDetailsPanel\"\n  />\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/FailureScreenshot.vue",
    "content": "<script setup lang=\"ts\">\nimport type { RunnerTask } from 'vitest'\nimport { computed, ref } from 'vue'\nimport { getAttachmentUrl } from '~/composables/attachments'\nimport { isReport } from '~/constants'\nimport IconButton from './IconButton.vue'\nimport Modal from './Modal.vue'\nimport ScreenshotError from './views/ScreenshotError.vue'\n\nconst { task } = defineProps<{\n  task: RunnerTask\n}>()\n\nconst showScreenshot = ref(false)\nconst artifact = computed(() => {\n  if (task.type === 'test') {\n    const artifact = task.artifacts.find(artifact => artifact.type === 'internal:failureScreenshot')\n\n    if (artifact !== undefined) {\n      return artifact\n    }\n  }\n\n  return null\n})\nconst screenshotUrl = computed(() =>\n  artifact.value && artifact.value.attachments.length && getAttachmentUrl(artifact.value.attachments[0]),\n)\n\nfunction openScreenshot() {\n  if (artifact.value === null || artifact.value.attachments.length === 0) {\n    return\n  }\n\n  const filePath = artifact.value.attachments[0].originalPath\n\n  fetch(`/__open-in-editor?file=${encodeURIComponent(filePath)}`)\n}\n</script>\n\n<template>\n  <template v-if=\"screenshotUrl\">\n    <div flex=\"~ gap-2 items-center\">\n      <IconButton\n        v-tooltip.bottom=\"'View screenshot error'\"\n        class=\"!op-100\"\n        icon=\"i-carbon:image\"\n        title=\"View screenshot error\"\n        @click=\"showScreenshot = true\"\n      />\n      <!-- in a report there is no dev server to handle the action -->\n      <IconButton\n        v-if=\"!isReport\"\n        v-tooltip.bottom=\"'Open screenshot error in editor'\"\n        class=\"!op-100\"\n        icon=\"i-carbon:image-reference\"\n        title=\"Open screenshot error in editor\"\n        @click=\"openScreenshot\"\n      />\n    </div>\n    <Modal :key=\"screenshotUrl\" v-model=\"showScreenshot\" direction=\"right\">\n      <ScreenshotError\n        :file=\"task.file.filepath\"\n        :name=\"task.name\"\n        :url=\"screenshotUrl\"\n        @close=\"showScreenshot = false\"\n      />\n    </Modal>\n  </template>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/FileDetails.vue",
    "content": "<script setup lang=\"ts\">\nimport type { RunnerTask, RunnerTestCase } from 'vitest'\nimport type { ModuleGraph } from '~/composables/module-graph'\nimport type { Params } from '~/composables/params'\nimport { debouncedWatch } from '@vueuse/core'\nimport { toJSON } from 'flatted'\nimport { computed, nextTick, ref } from 'vue'\nimport DetailsHeaderButtons from '~/components/DetailsHeaderButtons.vue'\nimport {\n  browserState,\n  client,\n  current,\n  currentLogs,\n  isReport,\n} from '~/composables/client'\nimport { tagsDefinitions } from '~/composables/client/state'\nimport { explorerTree } from '~/composables/explorer'\nimport { hasFailedSnapshot } from '~/composables/explorer/collector'\nimport { getModuleGraph } from '~/composables/module-graph'\nimport { selectedTest, viewMode } from '~/composables/params'\nimport { getBadgeNameColor, getBadgeTextColor } from '~/utils/task'\nimport IconButton from './IconButton.vue'\nimport StatusIcon from './StatusIcon.vue'\nimport ViewConsoleOutput from './views/ViewConsoleOutput.vue'\nimport ViewEditor from './views/ViewEditor.vue'\nimport ViewModuleGraph from './views/ViewModuleGraph.vue'\nimport ViewReport from './views/ViewReport.vue'\nimport ViewTestReport from './views/ViewTestReport.vue'\n\nconst graph = ref<ModuleGraph>({ nodes: [], links: [] })\nconst draft = ref(false)\nconst hasGraphBeenDisplayed = ref(false)\nconst loadingModuleGraph = ref(false)\nconst currentFilepath = ref<string | undefined>(undefined)\nconst hideNodeModules = ref(true)\n\nconst test = computed(() => {\n  return selectedTest.value\n    ? client.state.idMap.get(selectedTest.value) as RunnerTestCase\n    : undefined\n})\n\nconst graphData = computed(() => {\n  const c = current.value\n  if (!c || !c.filepath) {\n    return\n  }\n\n  return {\n    filepath: c.filepath,\n    projectName: c.file.projectName || '',\n  }\n})\n\nconst failedSnapshot = computed(() => {\n  return current.value && hasFailedSnapshot(current.value)\n})\n\nconst isTypecheck = computed(() => {\n  return !!current.value?.meta?.typecheck\n})\n\nfunction open() {\n  const filePath = current.value?.filepath\n  if (filePath) {\n    fetch(`/__open-in-editor?file=${encodeURIComponent(filePath)}`)\n  }\n}\n\nfunction changeViewMode(view: Params['view']) {\n  if (view === 'graph') {\n    hasGraphBeenDisplayed.value = true\n  }\n\n  viewMode.value = view\n}\nconst consoleCount = computed(() => {\n  return currentLogs.value?.reduce((s, { size }) => s + size, 0) ?? 0\n})\n\nfunction onDraft(value: boolean) {\n  draft.value = value\n}\n\nconst nodeModuleRegex = /[/\\\\]node_modules[/\\\\]/\n\nasync function loadModuleGraph(force = false) {\n  if (\n    loadingModuleGraph.value\n    || (graphData.value?.filepath === currentFilepath.value && !force)\n  ) {\n    return\n  }\n\n  loadingModuleGraph.value = true\n\n  await nextTick()\n\n  try {\n    const gd = graphData.value\n    if (!gd) {\n      loadingModuleGraph.value = false\n      return\n    }\n\n    if (\n      force\n      || !currentFilepath.value\n      || gd.filepath !== currentFilepath.value\n      || (!graph.value.nodes.length && !graph.value.links.length)\n    ) {\n      let moduleGraph = await client.rpc.getModuleGraph(\n        gd.projectName,\n        gd.filepath,\n        !!browserState,\n      )\n      // remove node_modules from the graph when enabled\n      if (hideNodeModules.value) {\n        // when using static html reporter, we've the meta as global, we need to clone it\n        if (isReport) {\n          moduleGraph\n            = typeof window.structuredClone !== 'undefined'\n              ? window.structuredClone(moduleGraph)\n              : toJSON(moduleGraph)\n        }\n        moduleGraph.inlined = moduleGraph.inlined.filter(\n          n => !nodeModuleRegex.test(n),\n        )\n        moduleGraph.externalized = moduleGraph.externalized.filter(\n          n => !nodeModuleRegex.test(n),\n        )\n      }\n      graph.value = getModuleGraph(\n        moduleGraph,\n        gd.filepath,\n      )\n      currentFilepath.value = gd.filepath\n    }\n    changeViewMode('graph')\n  }\n  finally {\n    await new Promise(resolve => setTimeout(resolve, 100))\n    loadingModuleGraph.value = false\n  }\n}\n\ndebouncedWatch(\n  () => [graphData.value, viewMode.value, hideNodeModules.value] as const,\n  ([, vm, hide], old) => {\n    if (vm === 'graph') {\n      // only force reload when hide is changed\n      loadModuleGraph(old && hide !== old[2])\n    }\n  },\n  { debounce: 100, immediate: true },\n)\n\nconst projectNameColor = computed(() => {\n  const projectName = current.value?.file.projectName || ''\n  return explorerTree.colors.get(projectName) || getBadgeNameColor(current.value?.file.projectName)\n})\n\nconst projectNameTextColor = computed(() => getBadgeTextColor(projectNameColor.value))\n\nconst testTitle = computed(() => {\n  const testId = selectedTest.value\n  if (!testId) {\n    return current.value?.name\n  }\n  const names: string[] = []\n  let node: RunnerTask | undefined = client.state.idMap.get(testId)\n  while (node) {\n    names.push(node.name)\n    node = node.suite\n  }\n  return names.reverse().join(' > ')\n})\n\nconst tags = computed(() => {\n  const testId = selectedTest.value\n  if (!testId) {\n    return []\n  }\n  const node = client.state.idMap.get(testId)\n  return (node?.tags || []).map(tag => ({\n    name: tag,\n    description: tagsDefinitions.value[tag]?.description,\n    bg: getBadgeNameColor(tag, true),\n    border: getBadgeNameColor(tag),\n    text: 'white',\n  }))\n})\n</script>\n\n<template>\n  <div\n    v-if=\"current\"\n    flex\n    flex-col\n    h-full\n    max-h-full\n    overflow-hidden\n    data-testid=\"file-detail\"\n  >\n    <div>\n      <div p=\"2\" h-10 flex=\"~ gap-2\" items-center bg-header border=\"b base\">\n        <StatusIcon :state=\"current.result?.state\" :mode=\"current.mode\" :failed-snapshot=\"failedSnapshot\" />\n        <div v-if=\"isTypecheck\" v-tooltip.bottom=\"'This is a typecheck test. It won\\'t report results of the runtime tests'\" class=\"i-logos:typescript-icon\" flex-shrink-0 />\n        <span\n          v-if=\"current?.file.projectName\"\n          class=\"rounded-full py-0.5 px-2 text-xs font-light\"\n          :style=\"{ backgroundColor: projectNameColor, color: projectNameTextColor }\"\n          cursor-default\n        >\n          {{ current.file.projectName }}\n        </span>\n        <div flex-1 font-light overflow-hidden text-sm flex>\n          <span op-50 truncate>\n            {{ testTitle }}\n          </span>\n\n          <span\n            v-for=\"tag of tags\"\n            :key=\"tag.name\"\n            v-tooltip.bottom=\"tag.description\"\n            class=\"rounded-full ml-2 px-2 text-xs font-light\"\n            :style=\"{ backgroundColor: tag.bg, color: tag.text, border: `1px solid ${tag.border}` }\"\n            :title=\"tag.description\"\n            cursor-default\n            flex\n            items-center\n          >\n            {{ tag.name }}\n          </span>\n        </div>\n        <div class=\"flex text-lg\">\n          <IconButton\n            v-if=\"!isReport\"\n            v-tooltip.bottom=\"'Open in editor'\"\n            title=\"Open in editor\"\n            icon=\"i-carbon-launch\"\n            :disabled=\"!current?.filepath\"\n            @click=\"open\"\n          />\n          <DetailsHeaderButtons v-if=\"browserState\" />\n        </div>\n      </div>\n      <div flex=\"~\" items-center bg-header border=\"b-2 base\" text-sm h-41px>\n        <button\n          tab-button\n          class=\"flex items-center gap-2\"\n          :class=\"{ 'tab-button-active': viewMode == null }\"\n          data-testid=\"btn-report\"\n          @click=\"changeViewMode(null)\"\n        >\n          <span class=\"block w-1.4em h-1.4em i-carbon:report\" />\n          Report\n        </button>\n        <button\n          tab-button\n          data-testid=\"btn-graph\"\n          class=\"flex items-center gap-2\"\n          :class=\"{ 'tab-button-active': viewMode === 'graph' }\"\n          @click=\"changeViewMode('graph')\"\n        >\n          <span\n            v-if=\"loadingModuleGraph\"\n            class=\"block w-1.4em h-1.4em i-carbon:circle-dash animate-spin animate-2s\"\n          />\n          <span\n            v-else\n            class=\"block w-1.4em h-1.4em i-carbon:chart-relationship\"\n          />\n          Module Graph\n        </button>\n        <button\n          tab-button\n          data-testid=\"btn-code\"\n          class=\"flex items-center gap-2\"\n          :class=\"{ 'tab-button-active': viewMode === 'editor' }\"\n          @click=\"changeViewMode('editor')\"\n        >\n          <span class=\"block w-1.4em h-1.4em i-carbon:code\" />\n          {{ draft ? \"*&#160;\" : \"\" }}Code\n        </button>\n        <button\n          tab-button\n          data-testid=\"btn-console\"\n          class=\"flex items-center gap-2\"\n          :class=\"{\n            'tab-button-active': viewMode === 'console',\n            'op20': viewMode !== 'console' && consoleCount === 0,\n          }\"\n          @click=\"changeViewMode('console')\"\n        >\n          <span class=\"block w-1.4em h-1.4em i-carbon:terminal-3270\" />\n          Console ({{ consoleCount }})\n        </button>\n      </div>\n    </div>\n\n    <div flex flex-col flex-1 overflow=\"hidden\">\n      <div v-if=\"hasGraphBeenDisplayed\" :flex-1=\"viewMode === 'graph' && ''\">\n        <ViewModuleGraph\n          v-show=\"viewMode === 'graph' && !loadingModuleGraph\"\n          v-model=\"hideNodeModules\"\n          :graph=\"graph\"\n          data-testid=\"graph\"\n          :project-name=\"current.file.projectName || ''\"\n        />\n      </div>\n      <ViewEditor\n        v-if=\"viewMode === 'editor'\"\n        :key=\"current.id\"\n        :file=\"current\"\n        data-testid=\"editor\"\n        @draft=\"onDraft\"\n      />\n      <ViewConsoleOutput\n        v-else-if=\"viewMode === 'console'\"\n        :file=\"current\"\n        data-testid=\"console\"\n      />\n      <ViewReport v-else-if=\"!viewMode && !test && current\" :file=\"current\" data-testid=\"report\" />\n      <ViewTestReport v-else-if=\"!viewMode && test\" :test=\"test\" data-testid=\"report\" />\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/FilterStatus.vue",
    "content": "<script setup lang=\"ts\">\nconst { disabled = false } = defineProps<{\n  label: string\n  disabled?: boolean\n}>()\nconst modelValue = defineModel<boolean | null>()\n\nfunction toggle() {\n  if (disabled) {\n    return\n  }\n\n  modelValue.value = !modelValue.value\n}\n</script>\n\n<template>\n  <label\n    class=\"font-light text-sm checkbox w-fit flex items-center py-1 gap-y-1 mb-1px overflow-hidden\"\n    :class=\"disabled ? 'cursor-not-allowed op50' : 'cursor-pointer'\"\n    v-bind=\"$attrs\"\n    @click.prevent=\"toggle\"\n  >\n    <span\n      :class=\"[\n        modelValue ? 'i-carbon:checkbox-checked-filled' : 'i-carbon:checkbox',\n      ]\"\n      text-lg\n      flex-shrink-0\n      aria-hidden=\"true\"\n    />\n    <input\n      v-model=\"modelValue\"\n      type=\"checkbox\"\n      :disabled=\"disabled\"\n      sr-only\n    >\n    <span flex-1 ms-2 select-none whitespace-nowrap truncate>{{ label }}</span>\n  </label>\n</template>\n\n<style>\n.checkbox:focus-within {\n  outline: none;\n  border-color: initial;\n  /* don't add outline-none here => uno will add 2px to the outline */\n  @apply focus-base border-b-1 !mb-none;\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/IconAction.vue",
    "content": "<script setup lang=\"ts\">\ndefineProps<{\n  icon?: string\n}>()\n</script>\n\n<template>\n  <button\n    type=\"button\"\n    dark=\"op75\"\n    bg=\"gray-200 dark:#111\"\n    hover=\"op100\"\n    rounded-1\n    p-0.5\n  >\n    <span block :class=\"icon\" op65 class=\"dark:op85 hover:op100\" />\n  </button>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/IconButton.vue",
    "content": "<script setup lang=\"ts\">\ndefineProps<{\n  icon?: `i-${string}` | `dark:i-${string}`\n  title?: string\n  disabled?: boolean\n  active?: boolean\n}>()\n</script>\n\n<template>\n  <button\n    :aria-label=\"title\"\n    role=\"button\"\n    :opacity=\"disabled ? 10 : 70\"\n    rounded\n    :disabled=\"disabled\"\n    :hover=\"disabled || active ? '' : 'bg-active op100'\"\n    class=\"w-1.4em h-1.4em flex\" :class=\"[{ 'bg-gray-500:35 op100': active }]\"\n  >\n    <slot>\n      <span :class=\"icon\" ma block />\n    </slot>\n  </button>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/Modal.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nconst { direction = 'bottom' } = defineProps<{\n  direction?: string\n}>()\n\nconst modelValue = defineModel<boolean>({ default: false })\n\nconst positionClass = computed(() => {\n  switch (direction) {\n    case 'bottom':\n      return 'bottom-0 left-0 right-0 border-t'\n    case 'top':\n      return 'top-0 left-0 right-0 border-b'\n    case 'left':\n      return 'bottom-0 left-0 top-0 border-r'\n    case 'right':\n      return 'bottom-0 top-0 right-0 border-l'\n    default:\n      return ''\n  }\n})\n\nconst transform = computed(() => {\n  switch (direction) {\n    case 'bottom':\n      return 'translateY(100%)'\n    case 'top':\n      return 'translateY(-100%)'\n    case 'left':\n      return 'translateX(-100%)'\n    case 'right':\n      return 'translateX(100%)'\n    default:\n      return ''\n  }\n})\n\nconst closeModal = () => (modelValue.value = false)\n</script>\n\n<template>\n  <div\n    class=\"fixed inset-0 z-40\"\n    :class=\"modelValue ? '' : 'pointer-events-none'\"\n  >\n    <div\n      class=\"bg-base inset-0 absolute transition-opacity duration-500 ease-out\"\n      :class=\"modelValue ? 'opacity-50' : 'opacity-0'\"\n      @click=\"closeModal\"\n    />\n    <div\n      class=\"bg-base border-base absolute transition-all duration-200 ease-out scrolls\"\n      :class=\"[positionClass]\"\n      :style=\"modelValue ? {} : { transform }\"\n    >\n      <slot />\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/ModuleGraphImportBreakdown.vue",
    "content": "<script setup lang=\"ts\">\nimport type { ModuleType } from '~/composables/module-graph'\nimport { relative } from 'pathe'\nimport { computed } from 'vue'\nimport { config } from '~/composables/client'\nimport { currentModule } from '~/composables/navigation'\nimport { formatTime, getDurationClass, getExternalModuleName } from '~/utils/task'\n\ninterface ImportEntry {\n  importedFile: string\n  relativeFile: string\n  selfTime: number\n  totalTime: number\n  formattedSelfTime: string\n  formattedTotalTime: string\n  selfTimeClass: string | undefined\n  totalTimeClass: string | undefined\n  external?: boolean\n}\n\nconst emit = defineEmits<{\n  select: [moduleId: string, type: ModuleType]\n}>()\n\nconst imports = computed(() => {\n  const file = currentModule.value\n  const importDurations = file?.importDurations\n  const root = config.value.root\n  if (!importDurations || !root) {\n    return []\n  }\n\n  const allImports: ImportEntry[] = []\n  for (const filePath in importDurations) {\n    const duration = importDurations[filePath]\n    const raltiveModule = duration.external\n      ? getExternalModuleName(filePath)\n      : relative(root, filePath)\n    allImports.push({\n      importedFile: filePath,\n      relativeFile: ellipsisFile(raltiveModule),\n      selfTime: duration.selfTime,\n      totalTime: duration.totalTime,\n      formattedSelfTime: formatTime(duration.selfTime),\n      formattedTotalTime: formatTime(duration.totalTime),\n      selfTimeClass: getDurationClass(duration.selfTime),\n      totalTimeClass: getDurationClass(duration.totalTime),\n      external: duration.external,\n    })\n  }\n  return allImports.sort((a, b) => b.totalTime - a.totalTime)\n})\n\nfunction ellipsisFile(moduleId: string) {\n  if (moduleId.length <= 45) {\n    return moduleId\n  }\n  return `...${moduleId.slice(-45)}`\n}\n</script>\n\n<template>\n  <div class=\"overflow-auto max-h-120\">\n    <h1 my-2 mx-4>\n      Import Duration Breakdown <span op-70>(ordered by Total Time)</span>\n    </h1>\n    <table my-2 mx-4 text-sm font-light op-90>\n      <thead>\n        <tr>\n          <th>\n            Module\n          </th>\n          <th>\n            Self\n          </th>\n          <th>\n            Total\n          </th>\n          <th>\n            %\n          </th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr v-for=\"row of imports\" :key=\"row.importedFile\">\n          <td\n            class=\"cursor-pointer pr-2\"\n            :style=\"{ color: row.external ? 'var(--color-node-external)' : undefined }\"\n            @click=\"emit('select', row.importedFile, row.external ? 'external' : 'inline')\"\n          >\n            {{ row.relativeFile }}\n          </td>\n          <td pr-2 :class=\"row.selfTimeClass\">\n            {{ row.formattedSelfTime }}\n          </td>\n          <td pr-2 :class=\"row.totalTimeClass\">\n            {{ row.formattedTotalTime }}\n          </td>\n          <td pr-2 :class=\"row.totalTimeClass\">\n            {{ Math.round((row.totalTime / imports[0].totalTime) * 100) }}%\n          </td>\n        </tr>\n      </tbody>\n    </table>\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/ModuleTransformResultView.vue",
    "content": "<script setup lang=\"ts\">\nimport type { Editor, EditorFromTextArea, LineWidget, TextMarker } from 'codemirror'\nimport type { Experimental, ExternalResult, TransformResultWithSource } from 'vitest'\nimport type { ModuleType } from '~/composables/module-graph'\nimport { asyncComputed, onKeyStroke } from '@vueuse/core'\nimport { Tooltip as VueTooltip } from 'floating-vue'\nimport { join, relative } from 'pathe'\nimport { computed } from 'vue'\nimport { browserState, client, config } from '~/composables/client'\nimport { currentModule } from '~/composables/navigation'\nimport { formatPreciseTime, formatTime, getDurationClass, getImportDurationType } from '~/utils/task'\nimport Badge from './Badge.vue'\nimport CodeMirrorContainer from './CodeMirrorContainer.vue'\nimport IconButton from './IconButton.vue'\n\nconst props = defineProps<{\n  id: string\n  projectName: string\n  type: ModuleType\n  canUndo: boolean\n}>()\n\nconst emit = defineEmits<{\n  (e: 'close'): void\n  (e: 'select', id: string, type: ModuleType): void\n  (e: 'back'): void\n}>()\n\nconst result = asyncComputed<TransformResultWithSource | ExternalResult | undefined>(() => {\n  if (!currentModule.value?.id) {\n    return undefined\n  }\n  if (props.type === 'inline') {\n    return client.rpc.getTransformResult(props.projectName, props.id, currentModule.value.id, !!browserState)\n  }\n  if (props.type === 'external') {\n    return client.rpc.getExternalResult(props.id, currentModule.value.id)\n  }\n})\nconst durations = computed(() => {\n  const importDurations = currentModule.value?.importDurations || {}\n  return importDurations[props.id] || importDurations[join('/@fs/', props.id)] || {}\n})\nconst ext = computed(() => props.id?.split(/\\./g).pop() || 'js')\n\nconst source = computed(() => result.value?.source?.trim() || '')\nconst isCached = computed(() => {\n  if (!result.value || !('code' in result.value) || !config.value.experimental?.fsModuleCache) {\n    return undefined\n  }\n  const index = result.value.code.lastIndexOf('vitestCache=')\n  return index !== -1\n})\n\nconst code = computed(\n  () => {\n    if (!result.value || !('code' in result.value)) {\n      return null\n    }\n    return result.value.code\n      .replace(/\\/\\/# sourceMappingURL=.*\\n/, '')\n      .replace(/\\/\\/# sourceMappingSource=.*\\n/, '')\n      .replace(/\\/\\/# vitestCache=.*\\n?/, '')\n      .trim() || ''\n  },\n)\nconst sourceMap = computed(() => {\n  if (!result.value || !('map' in result.value)) {\n    return {\n      mappings: '',\n    }\n  }\n  return {\n    mappings: result.value?.map?.mappings ?? '',\n    version: (result.value?.map as any)?.version,\n  }\n})\n\nconst widgetElements: HTMLDivElement[] = []\nconst markers: TextMarker[] = []\nconst lineWidgets: LineWidget[] = []\n\nfunction onMousedown(editor: Editor, e: MouseEvent) {\n  const lineCh = editor.coordsChar({ left: e.clientX, top: e.clientY })\n  const markers = editor.findMarksAt(lineCh)\n  if (markers.length !== 1) {\n    return\n  }\n  const resolvedUrl = markers[0].title\n  if (resolvedUrl) {\n    const type = markers[0].attributes?.['data-external'] === 'true' ? 'external' : 'inline'\n    emit('select', resolvedUrl, type)\n  }\n}\n\nfunction buildShadowImportsHtml(imports: Experimental.UntrackedModuleDefinitionDiagnostic[]) {\n  const shadowImportsDiv = document.createElement('div')\n  shadowImportsDiv.classList.add('mb-5')\n  const root = config.value.root\n  if (!root) {\n    return\n  }\n\n  imports.forEach(({ resolvedId, totalTime, external }) => {\n    const importDiv = document.createElement('div')\n    importDiv.append(document.createTextNode('import '))\n\n    const sourceDiv = document.createElement('span')\n    const url = relative(root, resolvedId)\n    sourceDiv.textContent = `\"/${url}\"`\n    sourceDiv.className = 'hover:underline decoration-gray cursor-pointer select-none'\n    importDiv.append(sourceDiv)\n    sourceDiv.addEventListener('click', () => {\n      emit('select', resolvedId, external ? 'external' : 'inline')\n    })\n\n    const timeElement = document.createElement('span')\n    timeElement.textContent = ` ${formatTime(totalTime)}`\n    const durationClass = getDurationClass(totalTime)\n    if (durationClass) {\n      timeElement.classList.add(durationClass)\n    }\n    importDiv.append(timeElement)\n\n    shadowImportsDiv.append(importDiv)\n  })\n  return shadowImportsDiv\n}\n\nfunction createDurationDiv(duration: number) {\n  const timeElement = document.createElement('div')\n  timeElement.className = 'flex ml-2'\n  timeElement.textContent = formatTime(duration)\n  const durationClass = getDurationClass(duration)\n  if (durationClass) {\n    timeElement.classList.add(durationClass)\n  }\n  return timeElement\n}\n\nfunction markImportDurations(codemirror: EditorFromTextArea) {\n  lineWidgets.forEach(lw => lw.clear())\n  lineWidgets.length = 0\n\n  widgetElements.forEach(el => el.remove())\n  widgetElements.length = 0\n\n  markers.forEach(m => m.clear())\n  markers.length = 0\n\n  if (result.value && 'modules' in result.value) {\n    codemirror.off('mousedown', onMousedown)\n    codemirror.on('mousedown', onMousedown)\n\n    const untrackedModules = result.value.untrackedModules\n\n    if (untrackedModules?.length) {\n      const importDiv = buildShadowImportsHtml(untrackedModules)\n      if (!importDiv) {\n        return\n      }\n      widgetElements.push(importDiv)\n      lineWidgets.push(codemirror.addLineWidget(0, importDiv, { above: true }))\n    }\n\n    result.value.modules?.forEach((diagnostic) => {\n      const start = {\n        line: diagnostic.start.line - 1,\n        ch: diagnostic.start.column,\n      }\n      const end = {\n        line: diagnostic.end.line - 1,\n        ch: diagnostic.end.column,\n      }\n      const marker = codemirror.markText(start, end, {\n        title: diagnostic.resolvedId,\n        attributes: {\n          'data-external': String(diagnostic.external === true),\n        },\n        className: 'hover:underline decoration-red cursor-pointer select-none',\n      })\n      markers.push(marker)\n      const timeElement = createDurationDiv(diagnostic.totalTime + (diagnostic.transformTime || 0))\n      if (!untrackedModules?.length) {\n        timeElement.classList.add('-mt-5')\n      }\n      widgetElements.push(timeElement)\n      codemirror.addWidget(\n        {\n          line: diagnostic.end.line - 1,\n          ch: diagnostic.end.column + 1,\n        },\n        timeElement,\n        false,\n      )\n    })\n  }\n}\n\nfunction goBack() {\n  emit('back')\n}\n\nonKeyStroke('Escape', () => {\n  emit('close')\n})\n// TODO: sourcemap https://evanw.github.io/source-map-visualization/\n</script>\n\n<template>\n  <div w-350 max-w-screen h-full flex flex-col>\n    <div p-4 relative>\n      <div flex justify-between>\n        <p>\n          <IconButton\n            v-if=\"canUndo\"\n            v-tooltip.bottom=\"'Go Back'\"\n            icon=\"i-carbon-arrow-left\"\n            class=\"flex-inline\"\n            @click=\"goBack()\"\n          />\n          Module Info\n          <VueTooltip class=\"inline\" cursor-help>\n            <Badge type=\"custom\" ml-1 :style=\"{ backgroundColor: `var(--color-node-${type})` }\">\n              {{ type }}\n            </Badge>\n            <template #popper>\n              This is module is {{ type === 'external' ? 'externalized' : 'inlined' }}.\n              <template v-if=\"type === 'external'\">\n                It means that the module was not processed by Vite plugins, but instead was directly imported by the environment.\n              </template>\n              <template v-else>\n                It means that the module was processed by Vite plugins.\n              </template>\n            </template>\n          </VueTooltip>\n          <VueTooltip v-if=\"isCached === true\" class=\"inline\" cursor-help>\n            <Badge type=\"tip\" ml-2>\n              cached\n            </Badge>\n            <template #popper>\n              This module is cached on the file system under `experimental.fsModuleCachePath` (\"node_modules/.exprtimental-vitest-cache\" by default).\n            </template>\n          </VueTooltip>\n          <VueTooltip v-if=\"isCached === false\" class=\"inline\" cursor-help>\n            <Badge type=\"warning\" ml-2>\n              not cached\n            </Badge>\n            <template #popper>\n              <p>This module is not cached on the file system. It might be the first test run after cache invalidation or</p>\n              <p>it was excluded manually via `experimental_defineCacheKeyGenerator`, or it cannot be cached (modules with `import.meta.glob`, for example).</p>\n            </template>\n          </VueTooltip>\n        </p>\n        <div mr-8 flex gap-2 items-center>\n          <VueTooltip v-if=\"durations.selfTime != null && durations.external !== true\" class=\"inline\" cursor-help>\n            <Badge :type=\"getImportDurationType(durations.selfTime)\">\n              self: {{ formatTime(durations.selfTime) }}\n            </Badge>\n            <template #popper>\n              It took {{ formatPreciseTime(durations.selfTime) }} to import this module, excluding static imports.\n            </template>\n          </VueTooltip>\n          <VueTooltip v-if=\"durations.totalTime != null\" class=\"inline\" cursor-help>\n            <Badge :type=\"getImportDurationType(durations.totalTime)\">\n              total: {{ formatTime(durations.totalTime) }}\n            </Badge>\n            <template #popper>\n              It took {{ formatPreciseTime(durations.totalTime) }} to import the whole module, including static imports.\n            </template>\n          </VueTooltip>\n          <VueTooltip v-if=\"result && 'transformTime' in result && result.transformTime\" class=\"inline\" cursor-help>\n            <Badge :type=\"getImportDurationType(result.transformTime)\">\n              transform: {{ formatTime(result.transformTime) }}\n            </Badge>\n            <template #popper>\n              It took {{ formatPreciseTime(result.transformTime) }} to transform this module by Vite plugins.\n            </template>\n          </VueTooltip>\n        </div>\n      </div>\n      <p op50 font-mono text-sm>\n        {{ id }}\n      </p>\n      <IconButton\n        icon=\"i-carbon-close\"\n        absolute\n        top-5px\n        right-5px\n        text-2xl\n        @click=\"emit('close')\"\n      />\n    </div>\n    <div v-if=\"!result\" p-5>\n      No transform result found for this module.\n    </div>\n    <template v-else>\n      <div grid=\"~ rows-[min-content_auto]\" overflow-hidden flex-auto :class=\"{ 'cols-2': code != null }\">\n        <div p=\"x3 y-1\" bg-overlay border=\"base b t r\">\n          Source\n        </div>\n        <div v-if=\"code != null\" p=\"x3 y-1\" bg-overlay border=\"base b t\">\n          Transformed\n        </div>\n        <CodeMirrorContainer\n          :key=\"id\"\n          h-full\n          :model-value=\"source\"\n          read-only\n          v-bind=\"{ lineNumbers: true }\"\n          :mode=\"ext\"\n          @codemirror=\"markImportDurations($event)\"\n        />\n        <CodeMirrorContainer\n          v-if=\"code != null\"\n          h-full\n          :model-value=\"code\"\n          read-only\n          v-bind=\"{ lineNumbers: true }\"\n          mode=\"js\"\n        />\n      </div>\n      <div v-if=\"sourceMap.mappings !== ''\">\n        <div p=\"x3 y-1\" bg-overlay border=\"base b t\">\n          Source map (v{{ sourceMap.version }})\n        </div>\n        <CodeMirrorContainer\n          :model-value=\"sourceMap.mappings\"\n          read-only\n          v-bind=\"{ lineNumbers: true }\"\n        />\n      </div>\n    </template>\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/Navigation.vue",
    "content": "<script setup lang=\"ts\">\nimport type { RunnerTestFile } from 'vitest'\nimport { Tooltip as VueTooltip } from 'floating-vue'\nimport { computed, nextTick } from 'vue'\nimport { isDark, toggleDark } from '~/composables'\nimport { client, config, isReport, runAll, runFiles } from '~/composables/client'\nimport { explorerTree } from '~/composables/explorer'\nimport { initialized, shouldShowExpandAll } from '~/composables/explorer/state'\nimport {\n  clickOnTask,\n  coverageConfigured,\n  coverageEnabled,\n  coverageVisible,\n  dashboardVisible,\n  disableCoverage,\n  showCoverage,\n  showDashboard,\n} from '~/composables/navigation'\nimport Explorer from './explorer/Explorer.vue'\nimport IconButton from './IconButton.vue'\n\nfunction updateSnapshot() {\n  return client.rpc.updateSnapshot()\n}\n\nconst toggleMode = computed(() => isDark.value ? 'light' : 'dark')\n\nasync function onRunAll(files?: RunnerTestFile[]) {\n  if (config.value.api?.allowExec === false) {\n    return\n  }\n\n  if (coverageEnabled.value) {\n    disableCoverage.value = true\n    await nextTick()\n    if (coverageVisible.value) {\n      showDashboard(true)\n      await nextTick()\n    }\n  }\n  if (files?.length) {\n    await runFiles(files)\n  }\n  else {\n    await runAll()\n  }\n}\n\nfunction collapseTests() {\n  explorerTree.collapseAllNodes()\n}\n\nfunction expandTests() {\n  explorerTree.expandAllNodes()\n}\n\nfunction getRerunTooltip(filteredFiles: RunnerTestFile[] | undefined) {\n  if (config.value.api?.allowExec === false) {\n    return 'Cannot run tests when `api.allowExec` is `false`. Did you expose UI to the internet?'\n  }\n  return filteredFiles ? (filteredFiles.length === 0 ? 'No test to run (clear filter)' : 'Rerun filtered') : 'Rerun all'\n}\n</script>\n\n<template>\n  <!-- TODO: have test tree so the folders are also nested: test -> filename -> suite -> test -->\n  <Explorer border=\"r base\" :on-item-click=\"clickOnTask\" :nested=\"true\" @run=\"onRunAll\">\n    <template #header=\"{ filteredFiles }\">\n      <img w-6 h-6 src=\"/favicon.svg\" alt=\"Vitest logo\">\n      <span font-light text-sm flex-1>Vitest</span>\n      <div class=\"flex text-lg\">\n        <IconButton\n          v-show=\"!shouldShowExpandAll\"\n          v-tooltip.bottom=\"'Collapse tests'\"\n          title=\"Collapse tests\"\n          :disabled=\"!initialized\"\n          data-testid=\"collapse-all\"\n          icon=\"i-carbon:collapse-all\"\n          @click=\"collapseTests()\"\n        />\n        <IconButton\n          v-show=\"shouldShowExpandAll\"\n          v-tooltip.bottom=\"'Expand tests'\"\n          :disabled=\"!initialized\"\n          title=\"Expand tests\"\n          data-testid=\"expand-all\"\n          icon=\"i-carbon:expand-all\"\n          @click=\"expandTests()\"\n        />\n        <IconButton\n          v-show=\"(coverageConfigured && !coverageEnabled) || !dashboardVisible\"\n          v-tooltip.bottom=\"'Dashboard'\"\n          title=\"Show dashboard\"\n          class=\"!animate-100ms\"\n          animate-count-1\n          icon=\"i-carbon:dashboard\"\n          @click=\"showDashboard(true)\"\n        />\n        <VueTooltip\n          v-if=\"coverageConfigured && !coverageEnabled\"\n          title=\"Coverage enabled but missing html reporter\"\n          class=\"w-1.4em h-1.4em op100 rounded flex color-red5 dark:color-#f43f5e cursor-help\"\n        >\n          <div class=\"i-carbon:folder-off ma\" />\n          <template #popper>\n            <div class=\"op100 gap-1 p-y-1\" grid=\"~ items-center cols-[1.5em_1fr]\">\n              <div class=\"i-carbon:information-square w-1.5em h-1.5em\" />\n              <div>Coverage enabled but missing html reporter.</div>\n              <div style=\"grid-column: 2\">\n                Add html reporter to your configuration to see coverage here.\n              </div>\n            </div>\n          </template>\n        </VueTooltip>\n        <IconButton\n          v-if=\"coverageEnabled\"\n          v-show=\"!coverageVisible\"\n          v-tooltip.bottom=\"'Coverage'\"\n          :disabled=\"disableCoverage\"\n          title=\"Show coverage\"\n          class=\"!animate-100ms\"\n          animate-count-1\n          icon=\"i-carbon:folder-details-reference\"\n          @click=\"showCoverage()\"\n        />\n        <IconButton\n          v-if=\"(explorerTree.summary.failedSnapshot && !isReport && config.api?.allowExec && config.api?.allowWrite)\"\n          v-tooltip.bottom=\"'Update all failed snapshot(s)'\"\n          icon=\"i-carbon:result-old\"\n          :disabled=\"!explorerTree.summary.failedSnapshotEnabled\"\n          @click=\"explorerTree.summary.failedSnapshotEnabled && updateSnapshot()\"\n        />\n        <IconButton\n          v-if=\"!isReport\"\n          v-tooltip.bottom=\"getRerunTooltip(filteredFiles)\"\n          :disabled=\"filteredFiles?.length === 0 || !config.api?.allowExec\"\n          icon=\"i-carbon:play\"\n          data-testid=\"btn-run-all\"\n          @click=\"onRunAll(filteredFiles)\"\n        />\n        <IconButton\n          v-tooltip.bottom=\"`Toggle to ${toggleMode} mode`\"\n          icon=\"dark:i-carbon-moon i-carbon:sun\"\n          @click=\"toggleDark()\"\n        />\n      </div>\n    </template>\n  </Explorer>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/ProgressBar.vue",
    "content": "<script setup lang=\"ts\">\nimport { useWindowSize } from '@vueuse/core'\nimport { computed } from 'vue'\nimport { finished } from '~/composables/client/state'\nimport { explorerTree } from '~/composables/explorer'\n\nconst { width } = useWindowSize()\nconst classes = computed(() => {\n  return [\n    explorerTree.summary.files === 0 && '!bg-gray-4 !dark:bg-gray-7',\n    !finished.value && 'in-progress',\n  ].filter(Boolean).join(' ')\n})\n\nconst widthPass = computed(() => {\n  const t = explorerTree.summary.files\n  return t > 0 ? (width.value * explorerTree.summary.filesSuccess / t) : 0\n})\nconst widthFailed = computed(() => {\n  const t = explorerTree.summary.files\n  return t > 0 ? (width.value * explorerTree.summary.filesFailed / t) : 0\n})\nconst pending = computed(() => {\n  const t = explorerTree.summary.files\n  return t - explorerTree.summary.filesFailed - explorerTree.summary.filesSuccess\n})\nconst widthPending = computed(() => {\n  const t = explorerTree.summary.files\n  return t > 0 ? (width.value * pending.value / t) : 0\n})\n</script>\n\n<template>\n  <div\n    absolute\n    t-0\n    l-0\n    r-0\n    z-index-1031\n    pointer-events-none\n    p-0\n    h-3px\n    grid=\"~ auto-cols-max\"\n    justify-items-center\n    w-screen\n    :class=\"classes\"\n  >\n    <div h-3px relative overflow-hidden class=\"px-0\" w-screen>\n      <div\n        absolute\n        l-0\n        t-0\n        bg-red-700 dark:bg-red-500\n        h-3px\n        :class=\"classes\"\n        :style=\"`width: ${widthFailed}px;`\"\n      >\n        &#160;\n      </div>\n      <div\n        absolute\n        l-0\n        t-0\n        bg-green-700 dark:bg-green-500\n        h-3px\n        :class=\"classes\"\n        :style=\"`left: ${widthFailed}px; width: ${widthPass}px;`\"\n      >\n        &#160;\n      </div>\n      <div\n        absolute\n        l-0\n        t-0\n        bg-yellow-700 dark:bg-yellow-500\n        h-3px\n        :class=\"classes\"\n        :style=\"`left: ${widthPass + widthFailed}px; width: ${widthPending}px;`\"\n      >\n        &#160;\n      </div>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.in-progress {\n  background-image: linear-gradient(\n    45deg,\n    rgba(255, 255, 255, 0.15) 25%,\n    transparent 25%,\n    transparent 50%,\n    rgba(255, 255, 255, 0.15) 50%,\n    rgba(255, 255, 255, 0.15) 75%,\n    transparent 75%,\n    transparent\n  );\n  background-size: 40px 40px;\n  animation: in-progress-stripes 2s linear infinite;\n}\n@keyframes in-progress-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/ResultsPanel.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\ndefineProps<{\n  color?: string\n}>()\n\nconst open = ref(true)\n</script>\n\n<template>\n  <div\n    :open=\"open\"\n    class=\"results-panel\"\n    data-testid=\"results-panel\"\n    @toggle=\"open = ($event.target as any).open\"\n  >\n    <div\n      p=\"y1\"\n      text-sm\n      bg-base\n      items-center\n      z-5\n      gap-2\n      :class=\"color\"\n      w-full\n      flex\n      select-none\n      sticky\n      top=\"-1\"\n    >\n      <div flex-1 h-1px border=\"base b\" op80 />\n      <slot name=\"summary\" :open=\"open\" />\n      <div flex-1 h-1px border=\"base b\" op80 />\n    </div>\n    <slot />\n  </div>\n</template>\n\n<style>\n.results-panel {\n  user-select: none;\n  width: 100%;\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/StatusIcon.vue",
    "content": "<script setup lang=\"ts\">\nimport type { RunMode, TaskState } from 'vitest'\n\ndefineProps<{\n  state?: TaskState\n  mode?: RunMode\n  failedSnapshot?: boolean\n}>()\n</script>\n\n<template>\n  <div\n    v-if=\"state === 'pass'\"\n    text-green-700 dark:text-green-500\n    flex-shrink-0\n    i-carbon:checkmark\n  />\n  <div\n    v-else-if=\"failedSnapshot\"\n    v-tooltip.right=\"'Contains failed snapshot'\"\n    text-red-700 dark:text-red-500\n    flex-shrink-0\n    i-carbon:compare\n  />\n  <div\n    v-else-if=\"state === 'fail'\"\n    text-red-700 dark:text-red-500\n    flex-shrink-0\n    i-carbon:close\n  />\n  <div\n    v-else-if=\"mode === 'todo'\"\n    v-tooltip.right=\"'Todo'\"\n    text-gray-500\n    flex-shrink-0\n    i-carbon:document-blank\n  />\n  <div\n    v-else-if=\"mode === 'skip' || state === 'skip'\"\n    v-tooltip.right=\"'Skipped'\"\n    text-gray-500\n    flex-shrink-0\n    i-carbon:redo\n    rotate-90\n  />\n  <div v-else text-yellow-700 dark:text-yellow-500 flex-shrink-0 i-carbon:circle-dash animate-spin />\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/ArtifactTemplate.vue",
    "content": "<script setup lang=\"ts\">\nimport { useSlots } from 'vue'\n\nconst slots = useSlots()\n</script>\n\n<template>\n  <article class=\"flex flex-col gap-4\">\n    <h1>\n      <slot name=\"title\" />\n    </h1>\n    <p v-if=\"slots.message\">\n      <slot name=\"message\" />\n    </p>\n    <slot />\n  </article>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/Artifacts.vue",
    "content": "<script setup lang=\"ts\">\nimport type { RunnerTestCase, TestArtifact } from 'vitest'\nimport type { Component } from 'vue'\nimport { computed } from 'vue'\nimport { getLocationString, openLocation } from '~/composables/location'\nimport VisualRegression from './visual-regression/VisualRegression.vue'\n\nconst { test } = defineProps<{ test: RunnerTestCase }>()\n\ninterface HandledArtifact { artifact: TestArtifact; component: Component; props: object }\n\ntype ComponentProps<T> = T extends new(...args: any) => { $props: infer P } ? NonNullable<P>\n  : T extends (props: infer P, ...args: any) => any ? P\n    : object\n\nconst handledArtifacts = computed<readonly HandledArtifact[]>(() => {\n  const handledArtifacts: HandledArtifact[] = []\n\n  for (const artifact of test.artifacts) {\n    switch (artifact.type) {\n      case 'internal:toMatchScreenshot': {\n        if (artifact.kind === 'visual-regression') {\n          handledArtifacts.push({\n            artifact,\n            component: VisualRegression,\n            props: { regression: artifact } satisfies ComponentProps<typeof VisualRegression>,\n          })\n        }\n\n        continue\n      }\n    }\n  }\n\n  return handledArtifacts\n})\n</script>\n\n<template>\n  <template v-if=\"handledArtifacts.length\">\n    <h1 m-2>\n      Test Artifacts\n    </h1>\n    <div\n      v-for=\"{ artifact, component, props }, index of handledArtifacts\"\n      :key=\"artifact.type + index\"\n      bg=\"yellow-500/10\"\n      text=\"yellow-500 sm\"\n      p=\"x3 y2\"\n      m-2\n      rounded\n      role=\"note\"\n    >\n      <div flex=\"~ gap-2 items-center justify-between\" overflow-hidden>\n        <div>\n          <span\n            v-if=\"artifact.location && artifact.location.file === test.file.filepath\"\n            v-tooltip.bottom=\"'Open in Editor'\"\n            title=\"Open in Editor\"\n            class=\"flex gap-1 text-yellow-500/80 cursor-pointer\"\n            ws-nowrap\n            @click=\"openLocation(test, artifact.location)\"\n          >\n            {{ getLocationString(artifact.location) }}\n          </span>\n          <span\n            v-else-if=\"artifact.location && artifact.location.file !== test.file.filepath\"\n            class=\"flex gap-1 text-yellow-500/80\"\n            ws-nowrap\n          >\n            {{ getLocationString(artifact.location) }}\n          </span>\n        </div>\n      </div>\n      <component :is=\"component\" v-bind=\"props\" />\n    </div>\n  </template>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/visual-regression/SmallTabs.spec.ts",
    "content": "import { faker } from '@faker-js/faker'\nimport { describe, expect, it } from 'vitest'\nimport { userEvent } from 'vitest/browser'\nimport { defineComponent, h } from 'vue'\nimport { page, render } from '~/test'\nimport SmallTabs from './SmallTabs.vue'\nimport SmallTabsPane from './SmallTabsPane.vue'\n\nfunction createSmallTabs(children: number) {\n  return defineComponent({\n    setup: () =>\n      () =>\n        h(\n          SmallTabs,\n          null,\n          {\n            default: () => Array.from({ length: children }, () => h(\n              SmallTabsPane,\n              { title: faker.lorem.word() },\n              () => faker.lorem.words(2),\n            )),\n          },\n        ),\n  })\n}\n\ndescribe('SmallTabs', () => {\n  it('has accessible elements', async () => {\n    render(createSmallTabs(2))\n\n    // a tablist with two elements inside\n    const tablist = page.getByRole('tablist')\n    const tabs = tablist.getByRole('tab')\n    const firstTab = tabs.first()\n    const secondTab = tabs.last()\n\n    await expect.element(tablist).toBeInTheDocument()\n    expect(tabs.all()).toHaveLength(2)\n\n    await expect.element(firstTab).toHaveAttribute('aria-selected', 'true')\n    await expect.element(secondTab).toHaveAttribute('aria-selected', 'false')\n\n    // two tab panels, with one hidden\n    const panels = page.getByRole('tabpanel', { includeHidden: true })\n    const firstPanel = panels.first()\n    const secondPanel = panels.last()\n\n    expect(panels.all()).toHaveLength(2)\n\n    await expect.element(firstPanel).not.toHaveAttribute('hidden')\n    await expect.element(secondPanel).toHaveAttribute('hidden')\n\n    // panels should be labelled by their tab button\n    await expect.element(firstPanel).toHaveAttribute(\n      'aria-labelledby',\n      firstTab.element().getAttribute('id'),\n    )\n    await expect.element(secondPanel).toHaveAttribute(\n      'aria-labelledby',\n      secondTab.element().getAttribute('id'),\n    )\n\n    await expect.element(firstTab).toHaveAttribute(\n      'aria-controls',\n      firstPanel.element().getAttribute('id'),\n    )\n    await expect.element(secondTab).toHaveAttribute(\n      'aria-controls',\n      secondPanel.element().getAttribute('id'),\n    )\n  })\n\n  it('opens one panel at a time', async () => {\n    const tabsLimit = 5\n\n    render(createSmallTabs(tabsLimit))\n\n    const tabs = page.getByRole('tablist').getByRole('tab')\n    const panels = page.getByRole('tabpanel', { includeHidden: true })\n\n    for (let tabIndex = 0; tabIndex < tabsLimit; tabIndex += 1) {\n      const activeTab = tabs.nth(tabIndex)\n      const activePanel = panels.nth(tabIndex)\n\n      await userEvent.click(activeTab)\n      await expect.element(\n        tabs.and(page.getByRole('tab', { selected: true })),\n      ).toBe(activeTab.element())\n      await expect.element(\n        page.getByRole('tabpanel'),\n      ).toBe(activePanel.element())\n    }\n  })\n})\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/visual-regression/SmallTabs.vue",
    "content": "<script setup lang=\"ts\">\nimport type { SmallTabsConfig } from '~/composables/small-tabs'\nimport { provide, ref, useId } from 'vue'\nimport { idFor, SMALL_TABS_CONTEXT } from '~/composables/small-tabs'\n\nconst activeTab = ref<string | null>(null)\nconst tabs = ref<SmallTabsConfig[]>([])\n\nconst id = useId()\n\nprovide(SMALL_TABS_CONTEXT, {\n  id,\n  activeTab,\n  registerTab: (tab) => {\n    if (!tabs.value.some(({ id }) => id === tab.id)) {\n      tabs.value.push(tab)\n    }\n\n    if (tabs.value.length === 1) {\n      activeTab.value = tab.id\n    }\n  },\n  unregisterTab: (tab) => {\n    const index = tabs.value.findIndex(({ id }) => id === tab.id)\n\n    if (index > -1) {\n      tabs.value.splice(index, 1)\n    }\n\n    if (activeTab.value === tab.id) {\n      activeTab.value = tabs.value[0]?.id ?? null\n    }\n  },\n})\n</script>\n\n<template>\n  <div\n    class=\"flex flex-col items-center gap-6\"\n  >\n    <div\n      role=\"tablist\"\n      aria-orientation=\"horizontal\"\n      class=\"flex gap-4\"\n    >\n      <button\n        v-for=\"tab in tabs\"\n        :id=\"idFor.tab(tab.id, id)\"\n        :key=\"tab.id\"\n        role=\"tab\"\n        :aria-selected=\"activeTab === tab.id\"\n        :aria-controls=\"idFor.tabpanel(tab.id, id)\"\n        type=\"button\"\n        class=\"aria-[selected=true]:underline underline-offset-4\"\n        @click=\"activeTab = tab.id\"\n      >\n        {{ tab.title }}\n      </button>\n    </div>\n    <slot />\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/visual-regression/SmallTabsPane.vue",
    "content": "<script setup lang=\"ts\">\nimport type { SmallTabsConfig } from '~/composables/small-tabs'\nimport { computed, inject, onMounted, onUnmounted, useId } from 'vue'\nimport { idFor, SMALL_TABS_CONTEXT } from '~/composables/small-tabs'\n\ninterface TabPaneProps extends Omit<SmallTabsConfig, 'id'> {}\n\nconst props = defineProps<TabPaneProps>()\n\nconst context = inject(SMALL_TABS_CONTEXT)\n\nif (!context) {\n  throw new Error('TabPane must be used within Tabs')\n}\n\nconst id = useId()\n\nconst isActive = computed(() => context.activeTab.value === id)\n\nonMounted(() => {\n  context.registerTab({ ...props, id })\n})\n\nonUnmounted(() => {\n  context.unregisterTab({ ...props, id })\n})\n</script>\n\n<template>\n  <div\n    :id=\"idFor.tabpanel(id, context.id)\"\n    role=\"tabpanel\"\n    :aria-labelledby=\"idFor.tab(id, context.id)\"\n    :hidden=\"!isActive\"\n    class=\"max-w-full\"\n  >\n    <slot />\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/visual-regression/VisualRegression.spec.ts",
    "content": "import type { VisualRegressionArtifact } from '@vitest/runner'\nimport { faker } from '@faker-js/faker'\nimport { describe, expect, it } from 'vitest'\nimport { userEvent } from 'vitest/browser'\nimport { page, render } from '~/test'\nimport VisualRegression from './VisualRegression.vue'\n\nconst diff = {\n  name: 'diff',\n  path: '/__diff.png',\n  width: 500,\n  height: 200,\n} as const\n\nconst reference = {\n  name: 'reference',\n  path: '/__reference.png',\n  width: 500,\n  height: 200,\n} as const\n\nconst actual = {\n  name: 'actual',\n  path: '/__actual.png',\n  width: 500,\n  height: 200,\n} as const\n\ndescribe('VisualRegression', () => {\n  it('renders content with no attachments', async () => {\n    const messageContent = faker.lorem.words(5)\n\n    render(VisualRegression, {\n      props: {\n        regression: {\n          type: 'internal:toMatchScreenshot',\n          kind: 'visual-regression',\n          message: messageContent,\n          attachments: [],\n        } satisfies VisualRegressionArtifact,\n      },\n    })\n\n    const article = page.getByRole('article')\n\n    await expect.element(article).toBeInTheDocument()\n    await expect.element(article.getByRole('heading'))\n      .toHaveTextContent('Visual Regression')\n    await expect.element(article.getByRole('paragraph'))\n      .toHaveTextContent(messageContent)\n    await expect.element(article.getByRole('tablist')).toHaveTextContent('')\n  })\n\n  it('renders diff tab', async () => {\n    render(VisualRegression, {\n      props: {\n        regression: {\n          type: 'internal:toMatchScreenshot',\n          kind: 'visual-regression',\n          message: faker.lorem.words(5),\n          attachments: [diff],\n        } satisfies VisualRegressionArtifact,\n      },\n    })\n\n    await expect.element(page.getByRole('tablist').getByRole('tab'))\n      .toHaveTextContent('Diff')\n    await expect.element(page.getByRole('tabpanel').getByRole('img'))\n      .toBeInTheDocument()\n  })\n\n  it('renders reference tab', async () => {\n    render(VisualRegression, {\n      props: {\n        regression: {\n          type: 'internal:toMatchScreenshot',\n          kind: 'visual-regression',\n          message: faker.lorem.words(5),\n          attachments: [reference],\n        } satisfies VisualRegressionArtifact,\n      },\n    })\n\n    await expect.element(page.getByRole('tablist').getByRole('tab'))\n      .toHaveTextContent('Reference')\n    await expect.element(page.getByRole('tabpanel').getByRole('img'))\n      .toBeInTheDocument()\n  })\n\n  it('renders actual tab', async () => {\n    render(VisualRegression, {\n      props: {\n        regression: {\n          type: 'internal:toMatchScreenshot',\n          kind: 'visual-regression',\n          message: faker.lorem.words(5),\n          attachments: [actual],\n        } satisfies VisualRegressionArtifact,\n      },\n    })\n\n    await expect.element(page.getByRole('tablist').getByRole('tab'))\n      .toHaveTextContent('Actual')\n    await expect.element(page.getByRole('tabpanel').getByRole('img'))\n      .toBeInTheDocument()\n  })\n\n  it('renders reference, actual, and slider tabs', async () => {\n    render(VisualRegression, {\n      props: {\n        regression: {\n          type: 'internal:toMatchScreenshot',\n          kind: 'visual-regression',\n          message: faker.lorem.words(5),\n          attachments: [reference, actual],\n        } satisfies VisualRegressionArtifact,\n      },\n    })\n\n    const tablist = page.getByRole('tablist')\n    const tabs = tablist.getByRole('tab')\n\n    await expect.element(tablist).toBeInTheDocument()\n\n    expect(tabs.all()).toHaveLength(3)\n    await expect.element(tabs.nth(0)).toHaveTextContent('Reference')\n    await expect.element(tabs.nth(1)).toHaveTextContent('Actual')\n    await expect.element(tabs.nth(2)).toHaveTextContent('Slider')\n\n    await userEvent.click(tabs.nth(2))\n\n    await expect.element(\n      page.getByLabelText(\n        'Image comparison slider showing reference and actual screenshots',\n      ),\n    ).toBeInTheDocument()\n  })\n\n  it('renders diff, reference, actual, and slider tabs', async () => {\n    render(VisualRegression, {\n      props: {\n        regression: {\n          type: 'internal:toMatchScreenshot',\n          kind: 'visual-regression',\n          message: faker.lorem.words(5),\n          attachments: [diff, reference, actual],\n        } satisfies VisualRegressionArtifact,\n      },\n    })\n\n    const tablist = page.getByRole('tablist')\n    const tabs = tablist.getByRole('tab')\n\n    await expect.element(tablist).toBeInTheDocument()\n\n    expect(tabs.all()).toHaveLength(4)\n    await expect.element(tabs.nth(0)).toHaveTextContent('Diff')\n    await expect.element(tabs.nth(1)).toHaveTextContent('Reference')\n    await expect.element(tabs.nth(2)).toHaveTextContent('Actual')\n    await expect.element(tabs.nth(3)).toHaveTextContent('Slider')\n  })\n})\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/visual-regression/VisualRegression.vue",
    "content": "<script setup lang=\"ts\">\nimport type { VisualRegressionArtifact } from '@vitest/runner'\nimport { computed } from 'vue'\nimport ArtifactTemplate from '../ArtifactTemplate.vue'\nimport SmallTabs from './SmallTabs.vue'\nimport SmallTabsPane from './SmallTabsPane.vue'\nimport VisualRegressionImage from './VisualRegressionImage.vue'\nimport VisualRegressionSlider from './VisualRegressionSlider.vue'\n\nconst { regression } = defineProps<{\n  regression: VisualRegressionArtifact\n}>()\n\ntype AttachmentWithMeta = Exclude<VisualRegressionArtifact['attachments'][number], { name: 'diff' }>\n\nconst groups = computed(() => ({\n  diff: regression.attachments.find(artifact => artifact.name === 'diff'),\n  reference: regression.attachments.find((artifact): artifact is AttachmentWithMeta => artifact.name === 'reference'),\n  actual: regression.attachments.find((artifact): artifact is AttachmentWithMeta => artifact.name === 'actual'),\n}))\n</script>\n\n<template>\n  <ArtifactTemplate>\n    <template #title>\n      Visual Regression\n    </template>\n    <template #message>\n      {{ regression.message }}\n    </template>\n    <SmallTabs>\n      <SmallTabsPane\n        v-if=\"groups.diff\"\n        :key=\"groups.diff.path\"\n        title=\"Diff\"\n      >\n        <VisualRegressionImage :attachment=\"groups.diff\" />\n      </SmallTabsPane>\n      <SmallTabsPane\n        v-if=\"groups.reference\"\n        :key=\"groups.reference.path\"\n        title=\"Reference\"\n      >\n        <VisualRegressionImage :attachment=\"groups.reference\" />\n      </SmallTabsPane>\n      <SmallTabsPane\n        v-if=\"groups.actual\"\n        :key=\"groups.actual.path\"\n        title=\"Actual\"\n      >\n        <VisualRegressionImage :attachment=\"groups.actual\" />\n      </SmallTabsPane>\n      <SmallTabsPane\n        v-if=\"groups.reference && groups.actual\"\n        :key=\"(groups.reference.path ?? '') + (groups.actual.path ?? '')\"\n        title=\"Slider\"\n      >\n        <VisualRegressionSlider :actual=\"groups.actual\" :reference=\"groups.reference\" />\n      </SmallTabsPane>\n    </SmallTabs>\n  </ArtifactTemplate>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/visual-regression/VisualRegressionImage.vue",
    "content": "<script setup lang=\"ts\">\nimport type { TestAttachment } from '@vitest/runner'\nimport { computed } from 'vue'\nimport { internalOrExternalUrl, isExternalAttachment } from '~/composables/attachments'\nimport VisualRegressionImageContainer from './VisualRegressionImageContainer.vue'\n\nconst { attachment } = defineProps<{\n  attachment: TestAttachment\n}>()\n\nconst href = computed<string>(() => internalOrExternalUrl(attachment))\n</script>\n\n<template>\n  <VisualRegressionImageContainer>\n    <a\n      target=\"_blank\"\n      :href=\"href\"\n      :referrerPolicy=\"isExternalAttachment(attachment) ? 'no-referrer' : undefined\"\n    >\n      <img\n        :src=\"href\"\n      >\n    </a>\n  </VisualRegressionImageContainer>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/visual-regression/VisualRegressionImageContainer.vue",
    "content": "<script setup lang=\"ts\">\nconst checkeredBackground = `url(\"${\n  CSS.escape('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 2 2\"><path d=\"M1 2V0h1v1H0v1z\" fill-opacity=\".05\"/></svg>')\n}\")`\n</script>\n\n<template>\n  <div\n    class=\"max-w-full w-fit mx-auto bg-[size:16px_16px] bg-[#fafafa] dark:bg-[#3a3a3a] bg-center p-4 rounded user-select-none outline-0 outline-black dark:outline-white outline-offset-4 outline-solid focus-within:has-focus-visible:outline-2\"\n    :style=\"{ backgroundImage: checkeredBackground }\"\n  >\n    <slot />\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/visual-regression/VisualRegressionSlider.spec.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { locators, userEvent } from 'vitest/browser'\nimport { page, render } from '~/test'\nimport VisualRegressionSlider from './VisualRegressionSlider.vue'\n\nlocators.extend({\n  // @ts-expect-error this gets used only in the first block which tests elements removed from the accessibility tree\n  getByCSS(selector: string) {\n    return selector\n  },\n})\n\nconst reference = {\n  path: '/__reference.png',\n  width: 500,\n  height: 200,\n}\n\nconst actual = {\n  path: '/__actual.png',\n  width: 500,\n  height: 200,\n}\n\nconst containerLabel = 'Image comparison slider showing reference and actual screenshots'\nconst inputLabel = 'Adjust slider to compare reference and actual images'\n\ndescribe('VisualRegressionSlider', () => {\n  it('renders both images with correct URLs', async () => {\n    render(VisualRegressionSlider, {\n      props: {\n        reference,\n        actual,\n      },\n    })\n\n    // !!! images are hidden/removed from the accessibility tree, so we fall back to CSS selectors\n\n    // both image tags should be rendered and contain the path\n    // @ts-expect-error extended only for this block\n    const images = page.getByCSS('img')\n    const referenceImage = images.first()\n    const actualImage = images.last()\n\n    expect(images.all()).toHaveLength(2)\n\n    await expect.element(referenceImage).toHaveProperty(\n      'src',\n      expect.stringContaining(encodeURIComponent(reference.path)),\n    )\n    await expect.element(actualImage).toHaveProperty(\n      'src',\n      expect.stringContaining(encodeURIComponent(actual.path)),\n    )\n\n    // images should be wrapped in (hidden) containers with role presentation\n    // @ts-expect-error extended only for this block\n    const referenceContainer = page.getByCSS('div:has(> img)').first()\n    // @ts-expect-error extended only for this block\n    const actualContainer = page.getByCSS('div:has(> img)').last()\n\n    await expect.element(referenceContainer).toHaveAttribute('aria-hidden', 'true')\n    await expect.element(referenceContainer).toHaveAttribute('role', 'presentation')\n\n    await expect.element(actualContainer).toHaveAttribute('aria-hidden', 'true')\n    await expect.element(actualContainer).toHaveAttribute('role', 'presentation')\n  })\n\n  it('has accessible descriptions', async () => {\n    render(VisualRegressionSlider, {\n      props: {\n        reference,\n        actual,\n      },\n    })\n\n    const container = page.getByLabelText(containerLabel)\n    const input = page.getByLabelText(inputLabel)\n    const status = page.getByRole(\n      'status',\n      { hasText: 'Showing 50% reference, 50% actual' },\n    )\n\n    // container with accessible label should exist and contain input and status\n    await expect.element(container).toBeInTheDocument()\n    await expect.element(container).toContainElement(input)\n    await expect.element(container).toContainElement(status)\n    // split is an implementation detail, but in absence of VRT it's a best-effort approach to check it's working\n    await expect.element(container).toHaveStyle('--split: 50%')\n\n    // input with label should be an input and have an id\n    await expect.element(input).toBeInstanceOf(HTMLInputElement)\n    await expect.element(input).toHaveAttribute('id')\n\n    // status element should exist and be connected to the input\n    await expect.element(status).toBeInTheDocument()\n    await expect.element(status).toHaveAttribute(\n      'for',\n      input.element().getAttribute('id'),\n    )\n  })\n\n  it('has slider boundaries', async () => {\n    render(VisualRegressionSlider, {\n      props: {\n        reference,\n        actual,\n      },\n    })\n\n    const input = page.getByLabelText(inputLabel)\n\n    await expect.element(input).toHaveAttribute('min', '0')\n    await expect.element(input).toHaveAttribute('max', '100')\n    await expect.element(input).toHaveAttribute('step', '0.1')\n  })\n\n  it('updates split percentage on slider movement', async () => {\n    render(VisualRegressionSlider, {\n      props: {\n        reference,\n        actual,\n      },\n    })\n\n    const container = page.getByLabelText(containerLabel)\n    const input = page.getByLabelText(inputLabel)\n    const status = page.getByRole('status')\n\n    // initial state should be 50\n    await expect.element(input).toHaveValue('50')\n    await expect.element(container).toHaveStyle('--split: 50%')\n\n    // keyboard interaction\n    await userEvent.click(status)\n    await userEvent.tab()\n    await userEvent.keyboard('{ArrowRight>10/}')\n    await userEvent.click(status)\n\n    await expect.element(input).toHaveValue('51')\n    await expect.element(container).toHaveStyle('--split: 51%')\n    await expect.element(status).toHaveTextContent('Showing 51% reference, 49% actual')\n\n    // mouse interaction\n    await userEvent.click(\n      input,\n      {\n        position: {\n          x: 1,\n          y: input.element().getBoundingClientRect().height / 2,\n        },\n      },\n    )\n    await userEvent.click(status)\n\n    await expect.element(input).toHaveValue('0')\n    await expect.element(status).toHaveTextContent('Showing 0% reference, 100% actual')\n    await expect.element(container).toHaveStyle('--split: 0%')\n  })\n})\n"
  },
  {
    "path": "packages/ui/client/components/artifacts/visual-regression/VisualRegressionSlider.vue",
    "content": "<script setup lang=\"ts\">\nimport type { VisualRegressionArtifact } from '@vitest/runner'\nimport { computed, ref, useId } from 'vue'\nimport { internalOrExternalUrl } from '~/composables/attachments'\nimport VisualRegressionImageContainer from './VisualRegressionImageContainer.vue'\n\ntype AttachmentWithMeta = Exclude<VisualRegressionArtifact['attachments'][number], { name: 'diff' }>\n\nconst { actual, reference } = defineProps<{\n  reference: AttachmentWithMeta\n  actual: AttachmentWithMeta\n}>()\n\nconst referenceUrl = computed(() => internalOrExternalUrl(reference))\nconst actualUrl = computed(() => internalOrExternalUrl(actual))\n\nconst maxWidth = computed(() =>\n  Math.max(reference.width, actual.width),\n)\nconst maxHeight = computed(() =>\n  Math.max(reference.height, actual.height),\n)\n\nconst splitPercentage = ref(50)\n\nconst inputId = useId()\n</script>\n\n<template>\n  <VisualRegressionImageContainer>\n    <div\n      aria-label=\"Image comparison slider showing reference and actual screenshots\"\n      class=\"relative max-w-full h-full overflow-hidden\"\n      :style=\"{\n        '--split': `${splitPercentage}%`,\n        'aspectRatio': `${maxWidth} / ${maxHeight}`,\n        'width': `${maxWidth}px`,\n      }\"\n    >\n      <div\n        class=\"absolute w-full h-full place-content-center place-items-center [clip-path:polygon(0%_0%,var(--split)_0%,var(--split)_100%,0%_100%)]\"\n        aria-hidden=\"true\"\n        role=\"presentation\"\n      >\n        <img :src=\"referenceUrl\">\n      </div>\n      <div\n        class=\"absolute w-full h-full place-content-center place-items-center [clip-path:polygon(var(--split)_0%,100%_0%,100%_100%,var(--split)_100%)]\"\n        aria-hidden=\"true\"\n        role=\"presentation\"\n      >\n        <img :src=\"actualUrl\">\n      </div>\n      <div\n        class=\"absolute left-[--split] h-full w-[2px] -translate-x-1/2 bg-white shadow-[0_0_3px_rgb(0_0_0/.2),0_0_10px_rgb(0_0_0/.5)] before:content-[''] before:absolute before:top-1/2 before:size-[16px] before:bg-white before:border-[2px] before:border-black before:rounded-full before:-translate-y-1/2 before:translate-x-[calc(-50%+1px)]\"\n        aria-hidden=\"true\"\n        role=\"presentation\"\n      />\n      <input\n        :id=\"inputId\"\n        v-model=\"splitPercentage\"\n        type=\"range\"\n        min=\"0\"\n        max=\"100\"\n        step=\"0.1\"\n        aria-label=\"Adjust slider to compare reference and actual images\"\n        class=\"absolute inset-0 opacity-0 cursor-col-resize\"\n      >\n      <output :for=\"inputId\" class=\"sr-only\">\n        Showing {{ splitPercentage }}% reference, {{ 100 - splitPercentage }}% actual\n      </output>\n    </div>\n  </VisualRegressionImageContainer>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/dashboard/DashboardEntry.spec.ts",
    "content": "import { faker } from '@faker-js/faker'\nimport { describe, expect, it } from 'vitest'\nimport { h } from 'vue'\nimport { page, render } from '~/test'\nimport DashboardEntry from './DashboardEntry.vue'\n\nconst bodyTestId = 'body-content'\nconst headerTestId = 'header-content'\n\nfunction div(o: { testId: string; body: string }) {\n  return h('div', { 'data-testid': o.testId }, o.body)\n}\n\ndescribe('DashboardEntry', () => {\n  it('renders the body and header slots', async () => {\n    render(DashboardEntry, {\n      slots: {\n        body: div({ testId: bodyTestId, body: faker.lorem.words(2) }),\n        header: div({ testId: headerTestId, body: faker.hacker.phrase() }),\n      },\n    })\n\n    await expect.element(page.getByTestId(bodyTestId)).toBeInTheDocument()\n    await expect.element(page.getByTestId(headerTestId)).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/ui/client/components/dashboard/DashboardEntry.vue",
    "content": "<script setup lang=\"ts\">\n// const { tail = false } = defineProps<{ tail?: boolean }>()\n</script>\n\n<template>\n  <div p-2 text-center flex>\n    <div>\n      <div text-4xl min-w-2em>\n        <slot name=\"body\" />\n      </div>\n      <div text-md>\n        <slot name=\"header\" />\n      </div>\n    </div>\n    <!--\n    <div v-if=\"!tail\" data-testid=\"tail\" my-0 op50 w-2px bg-current origin-center rotate-0 translate-x-3 />\n-->\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/dashboard/ErrorEntry.vue",
    "content": "<script setup lang=\"ts\">\nimport type { TestError } from '@vitest/utils'\n\ndefineProps<{\n  error: TestError\n}>()\n</script>\n\n<template>\n  <h4 bg=\"red500/10\" p-1 mb-1 mt-2 rounded>\n    <span font-bold>\n      {{ error.name || error.nameStr || 'Unknown Error' }}<template v-if=\"error.message\">:</template>\n    </span>\n    {{ error.message }}\n  </h4>\n  <p v-if=\"error.stacks?.length\" class=\"scrolls\" text=\"xs\" font-mono mx-1 my-2 pb-2 overflow-auto>\n    <span v-for=\"(frame, i) in error.stacks\" :key=\"i\" whitespace-pre :font-bold=\"i === 0 ? '' : null\">❯ {{ frame.method }} {{ frame.file }}:<span text=\"red500/70\">{{ frame.line }}:{{ frame.column }}</span><br></span>\n  </p>\n  <p v-if=\"error.VITEST_TEST_PATH\" text=\"sm\" mb-2>\n    This error originated in <span font-bold>{{ error.VITEST_TEST_PATH }}</span> test file. It doesn't mean the error was thrown inside the file itself, but while it was running.\n  </p>\n  <div v-if=\"error.VITEST_TEST_NAME\" text=\"sm\" mb-2>\n    The latest test that might've caused the error is <span font-bold>{{ error.VITEST_TEST_NAME }}</span>. It might mean one of the following:<br>\n    <ul>\n      <li>\n        The error was thrown, while Vitest was running this test.\n      </li>\n      <li>\n        If the error occurred after the test had been completed, this was the last documented test before it was thrown.\n      </li>\n    </ul>\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/dashboard/TestFilesEntry.vue",
    "content": "<script setup lang=\"ts\">\nimport { unhandledErrors } from '~/composables/client/state'\nimport { explorerTree } from '~/composables/explorer'\nimport ErrorEntry from './ErrorEntry.vue'\n</script>\n\n<template>\n  <div\n    data-testid=\"test-files-entry\"\n    grid=\"~ cols-[min-content_1fr_min-content]\"\n    items-center\n    gap=\"x-2 y-3\"\n    p=\"x4\"\n    relative\n    font-light\n    w-80\n    op80\n  >\n    <div i-carbon-document />\n    <div>Files</div>\n    <div class=\"number\" data-testid=\"num-files\">\n      {{ explorerTree.summary.files }}\n    </div>\n\n    <template v-if=\"explorerTree.summary.filesSuccess\">\n      <div i-carbon-checkmark />\n      <div>Pass</div>\n      <div class=\"number\">\n        {{ explorerTree.summary.filesSuccess }}\n      </div>\n    </template>\n\n    <template v-if=\"explorerTree.summary.filesSkipped\">\n      <div i-carbon:redo rotate-90 />\n      <div>\n        Skip\n      </div>\n      <div class=\"number\" text-purple-700 dark:text-purple-400>\n        {{ explorerTree.summary.filesSkipped }}\n      </div>\n    </template>\n\n    <template v-if=\"explorerTree.summary.filesFailed\">\n      <div i-carbon-close />\n      <div>\n        Fail\n      </div>\n      <div class=\"number\" text-red-700 dark:text-red-500>\n        {{ explorerTree.summary.filesFailed }}\n      </div>\n    </template>\n\n    <template v-if=\"explorerTree.summary.filesSnapshotFailed\">\n      <div i-carbon-compare />\n      <div>\n        Snapshot Fail\n      </div>\n      <div class=\"number\" text-red-700 dark:text-red-500>\n        {{ explorerTree.summary.filesSnapshotFailed }}\n      </div>\n    </template>\n\n    <template v-if=\"unhandledErrors.length\">\n      <div i-carbon-checkmark-outline-error />\n      <div>\n        Errors\n      </div>\n      <div class=\"number\" text-red-700 dark:text-red-500>\n        {{ unhandledErrors.length }}\n      </div>\n    </template>\n\n    <div i-carbon-timer />\n    <div>Time</div>\n    <div class=\"number\" data-testid=\"run-time\">\n      {{ explorerTree.summary.time }}\n    </div>\n  </div>\n  <template v-if=\"unhandledErrors.length\">\n    <div bg=\"red500/10\" text=\"red500\" p=\"x3 y2\" max-w-xl m-2 rounded>\n      <h3 text-center mb-2>\n        Unhandled Errors\n      </h3>\n      <p text=\"sm\" font-thin mb-2 data-testid=\"unhandled-errors\">\n        Vitest caught {{ unhandledErrors.length }} error{{ unhandledErrors.length > 1 ? 's' : '' }} during the test run.<br>\n        This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.\n      </p>\n      <details\n        data-testid=\"unhandled-errors-details\"\n        class=\"scrolls unhandled-errors\"\n        text=\"sm\"\n        font-thin\n        pe-2.5\n        open:max-h-52\n        overflow-auto\n      >\n        <summary font-bold cursor-pointer>\n          Errors\n        </summary>\n        <ErrorEntry v-for=\"(e, idx) in unhandledErrors\" :key=\"idx\" :error=\"e\" />\n      </details>\n    </div>\n  </template>\n</template>\n\n<style scoped>\n.number {\n  font-weight: 400;\n  text-align: right;\n}\n\n.unhandled-errors {\n  --cm-ttc-c-thumb: #ccc;\n}\n\nhtml.dark .unhandled-errors {\n  --cm-ttc-c-thumb: #444;\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/dashboard/TestsEntry.vue",
    "content": "<script setup lang=\"ts\">\nimport { explorerTree } from '~/composables/explorer'\nimport { filter } from '~/composables/explorer/state'\nimport DashboardEntry from './DashboardEntry.vue'\n\nfunction toggleFilter(type: 'success' | 'failed' | 'skipped' | 'slow' | 'total') {\n  // Reset all filters first\n  filter.success = false\n  filter.failed = false\n  filter.skipped = false\n  filter.slow = false\n\n  if (type === 'total') {\n    return\n  }\n  // Then set the selected one\n  filter[type] = true\n}\n</script>\n\n<template>\n  <div flex=\"~ wrap\" justify-evenly gap-2 p=\"x-4\" relative>\n    <DashboardEntry\n      text-green-700 dark:text-green-500\n      data-testid=\"pass-entry\"\n      cursor-pointer\n      hover=\"op80\"\n      @click=\"toggleFilter('success')\"\n    >\n      <template #header>\n        Pass\n      </template>\n      <template #body>\n        {{ explorerTree.summary.testsSuccess }}\n      </template>\n    </DashboardEntry>\n    <DashboardEntry\n      :class=\"{ 'text-red-700 dark:text-red-500': explorerTree.summary.testsFailed, 'op50': !explorerTree.summary.testsFailed }\"\n      data-testid=\"fail-entry\"\n      cursor-pointer\n      hover=\"op80\"\n      @click=\"toggleFilter('failed')\"\n    >\n      <template #header>\n        Fail\n      </template>\n      <template #body>\n        {{ explorerTree.summary.testsFailed }}\n      </template>\n    </DashboardEntry>\n    <DashboardEntry\n      v-if=\"explorerTree.summary.testsExpectedFail\"\n      text-cyan-700 dark:text-cyan-500\n      data-testid=\"expected-fail-entry\"\n    >\n      <template #header>\n        Expected Fail\n      </template>\n      <template #body>\n        {{ explorerTree.summary.testsExpectedFail }}\n      </template>\n    </DashboardEntry>\n    <DashboardEntry\n      v-if=\"explorerTree.summary.testsSkipped\"\n      text-purple-700 dark:text-purple-400\n      data-testid=\"skipped-entry\"\n      cursor-pointer\n      hover=\"op80\"\n      @click=\"toggleFilter('skipped')\"\n    >\n      <template #header>\n        Skip\n      </template>\n      <template #body>\n        {{ explorerTree.summary.testsSkipped }}\n      </template>\n    </DashboardEntry>\n    <DashboardEntry\n      v-if=\"explorerTree.summary.testsTodo\"\n      op50\n      data-testid=\"todo-entry\"\n    >\n      <template #header>\n        Todo\n      </template>\n      <template #body>\n        {{ explorerTree.summary.testsTodo }}\n      </template>\n    </DashboardEntry>\n    <DashboardEntry\n      :tail=\"true\"\n      data-testid=\"total-entry\"\n      cursor-pointer\n      hover=\"op80\"\n      @click=\"toggleFilter('total')\"\n    >\n      <template #header>\n        Total\n      </template>\n      <template #body>\n        {{ explorerTree.summary.totalTests }}\n      </template>\n    </DashboardEntry>\n    <DashboardEntry\n      v-if=\"explorerTree.summary.testsSlow\"\n      text-yellow-700 dark:text-yellow-500\n      data-testid=\"slow-entry\"\n      cursor-pointer\n      hover=\"op80\"\n      @click=\"toggleFilter('slow')\"\n    >\n      <template #header>\n        Slow\n      </template>\n      <template #body>\n        {{ explorerTree.summary.testsSlow }}\n      </template>\n    </DashboardEntry>\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/dashboard/TestsFilesContainer.vue",
    "content": "<script setup lang=\"ts\">\nimport { finished } from '~/composables/client/state'\nimport { explorerTree } from '~/composables/explorer'\nimport TestFilesEntry from './TestFilesEntry.vue'\nimport TestsEntry from './TestsEntry.vue'\n</script>\n\n<template>\n  <div gap-0 flex=\"~ col gap-4\" h-full justify-center items-center>\n    <template v-if=\"explorerTree.summary.files === 0 && finished\">\n      <div class=\"text-gray-5\">\n        No tests found\n      </div>\n    </template>\n    <section aria-labelledby=\"tests\" m=\"y-4 x-2\">\n      <TestsEntry />\n    </section>\n    <TestFilesEntry />\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/explorer/Explorer.vue",
    "content": "<script setup lang=\"ts\">\nimport type { File, Task } from '@vitest/runner'\nimport { hideAllPoppers } from 'floating-vue'\nimport { computed, ref } from 'vue'\n\n// @ts-expect-error missing types\nimport { RecycleScroller } from 'vue-virtual-scroller'\nimport { availableProjects, config } from '~/composables/client'\nimport { useSearch } from '~/composables/explorer/search'\nimport { ALL_PROJECTS, projectSort } from '~/composables/explorer/state'\nimport { activeFileId, selectedTest } from '~/composables/params'\nimport FilterStatus from '../FilterStatus.vue'\nimport IconButton from '../IconButton.vue'\nimport ResultsPanel from '../ResultsPanel.vue'\nimport ExplorerItem from './ExplorerItem.vue'\nimport 'vue-virtual-scroller/dist/vue-virtual-scroller.css'\n\ndefineOptions({ inheritAttrs: false })\n\nconst { onItemClick } = defineProps<{\n  onItemClick?: (task: Task) => void\n}>()\n\nconst emit = defineEmits<{\n  (event: 'item-click', files?: File[]): void\n  (event: 'run', files?: File[]): void\n}>()\n\nconst includeTaskLocation = computed(() => config.value.includeTaskLocation)\nconst slowTime = computed(() => {\n  const threshold = config.value.slowTestThreshold\n  if (typeof threshold === 'number') {\n    return ` (>${threshold}ms)`\n  }\n\n  return ''\n})\n\nconst searchBox = ref<HTMLInputElement | undefined>()\nconst selectProjectRef = ref<HTMLSelectElement | undefined>()\nconst sortProjectRef = ref<HTMLSelectElement | undefined>()\n\nconst {\n  initialized,\n  filter,\n  search,\n  disableFilter,\n  isFiltered,\n  isFilteredByStatus,\n  disableClearSearch,\n  clearAll,\n  clearSearch,\n  clearFilter,\n  filteredFiles,\n  testsTotal,\n  uiEntries,\n  enableProjects,\n  disableClearProjects,\n  currentProject,\n  currentProjectName,\n  clearProject,\n  clearProjectSort,\n  disableClearProjectSort,\n  searchMatcher,\n} = useSearch(searchBox, selectProjectRef, sortProjectRef)\n</script>\n\n<template>\n  <div h=\"full\" flex=\"~ col\">\n    <div>\n      <div p=\"2\" h-10 flex=\"~ gap-2\" items-center bg-header border=\"b base\">\n        <slot name=\"header\" :filtered-files=\"isFiltered || isFilteredByStatus ? filteredFiles : undefined\" />\n      </div>\n      <div\n        v-if=\"enableProjects\"\n        p=\"l3 y2 r2\"\n        bg-header\n        border=\"b-2 base\"\n        grid=\"~ cols-[auto_auto_minmax(0,1fr)_auto] gap-x-2 gap-y-1\"\n        items-center\n      >\n        <div class=\"i-carbon:workspace\" flex-shrink-0 />\n        <label for=\"project-select\" text-sm>\n          Projects\n        </label>\n        <div class=\"relative flex-1\">\n          <select\n            id=\"project-select\"\n            ref=\"selectProjectRef\"\n            v-model=\"currentProject\"\n            w-full\n            appearance-none\n            bg-base\n            text-base\n            border=\"~ base rounded\"\n            pl-2\n            pr-8\n            py-1\n            text-sm\n            cursor-pointer\n            hover:bg-active\n            class=\"outline-none\"\n          >\n            <option :value=\"ALL_PROJECTS\" class=\"text-base bg-base\">\n              All Projects\n            </option>\n            <option\n              v-for=\"project in availableProjects\"\n              :key=\"project\"\n              :value=\"project\"\n              class=\"text-base bg-base\"\n            >\n              {{ project }}\n            </option>\n          </select>\n          <div class=\"i-carbon:chevron-down absolute right-2 top-1/2 op50 -translate-y-1/2 pointer-events-none\" />\n        </div>\n\n        <IconButton\n          v-tooltip.bottom=\"'Clear project filter'\"\n          :disabled=\"disableClearProjects\"\n          title=\"Clear project filter\"\n          icon=\"i-carbon:filter-remove\"\n          @click.passive=\"clearProject(true)\"\n        />\n      </div>\n      <div\n        p=\"l3 y2 r2\"\n        bg-header\n        border=\"b-2 base\"\n        grid=\"~ cols-[auto_auto_minmax(0,1fr)_auto] gap-x-2\"\n        items-center\n      >\n        <div class=\"i-carbon:arrows-vertical\" flex-shrink-0 />\n        <label for=\"project-sort\" text-sm>\n          Sort by\n        </label>\n        <div class=\"relative flex-1\">\n          <select\n            id=\"project-sort\"\n            ref=\"sortProjectRef\"\n            v-model=\"projectSort\"\n            w-full\n            appearance-none\n            bg-base\n            text-base\n            border=\"~ base rounded\"\n            pl-2\n            pr-8\n            py-1\n            text-sm\n            cursor-pointer\n            hover:bg-active\n            class=\"outline-none\"\n          >\n            <option value=\"default\" class=\"text-base bg-base\">\n              Default\n            </option>\n            <option value=\"duration-desc\" class=\"text-base bg-base\">\n              Slowest first\n            </option>\n            <option value=\"duration-asc\" class=\"text-base bg-base\">\n              Fastest first\n            </option>\n            <option v-if=\"enableProjects\" value=\"asc\" class=\"text-base bg-base\">\n              Project A-Z\n            </option>\n            <option v-if=\"enableProjects\" value=\"desc\" class=\"text-base bg-base\">\n              Project Z-A\n            </option>\n          </select>\n          <div class=\"i-carbon:chevron-down absolute right-2 top-1/2 op50 -translate-y-1/2 pointer-events-none\" />\n        </div>\n        <IconButton\n          v-tooltip.bottom=\"'Reset sort'\"\n          :disabled=\"disableClearProjectSort\"\n          title=\"Reset sort\"\n          icon=\"i-carbon:filter-reset\"\n          @click.passive=\"clearProjectSort(true)\"\n        />\n      </div>\n      <div\n        p=\"l3 y2 r2\"\n        flex=\"~ gap-2\"\n        items-center\n        bg-header\n        border=\"b-2 base\"\n      >\n        <div class=\"i-carbon:search\" flex-shrink-0 />\n        <input\n          ref=\"searchBox\"\n          v-model=\"search\"\n          placeholder=\"Search... (e.g. test name, tag:expression)\"\n          outline=\"none\"\n          bg=\"transparent\"\n          font=\"light\"\n          text=\"sm\"\n          flex-1\n          pl-1\n          :op=\"search.length ? '100' : '50'\"\n          @keydown.esc=\"clearSearch(false)\"\n          @keydown.enter=\"emit('run', isFiltered || isFilteredByStatus ? filteredFiles : undefined)\"\n        >\n        <IconButton\n          v-tooltip.bottom=\"'Clear search'\"\n          :disabled=\"disableClearSearch\"\n          title=\"Clear search\"\n          icon=\"i-carbon:filter-remove\"\n          @click.passive=\"clearSearch(true)\"\n        />\n      </div>\n      <div\n        p=\"l3 y2 r2\"\n        items-center\n        bg-header\n        border=\"b-2 base\"\n        flex=\"~ wrap gap-x-4 justify-between\"\n      >\n        <div min-w-full flex=\"~ gap-2 items-center\">\n          <div aria-hidden=\"true\" class=\"i-carbon:filter\" flex-shrink-0 />\n          <div flex-grow-1 text-sm>\n            Filter\n          </div>\n          <IconButton\n            v-tooltip.bottom=\"'Clear Filter'\"\n            :disabled=\"disableFilter\"\n            title=\"Clear filter\"\n            icon=\"i-carbon:filter-remove\"\n            @click.passive=\"clearFilter(false)\"\n          />\n        </div>\n        <FilterStatus v-model=\"filter.failed\" label=\"Fail\" />\n        <FilterStatus v-model=\"filter.success\" label=\"Pass\" />\n        <FilterStatus v-model=\"filter.skipped\" label=\"Skip\" />\n        <FilterStatus v-model=\"filter.onlyTests\" label=\"Only Tests\" />\n        <FilterStatus v-model=\"filter.slow\" :label=\"`Slow${slowTime}`\" />\n      </div>\n    </div>\n    <div class=\"scrolls\" flex-auto py-1 @scroll.passive=\"hideAllPoppers\">\n      <ResultsPanel>\n        <template v-if=\"initialized\" #summary>\n          <div grid=\"~ items-center gap-x-1 cols-[auto_min-content_auto] rows-[min-content_min-content]\">\n            <span text-red-700 dark:text-red-500>\n              FAIL ({{ testsTotal.failed }})\n            </span>\n            <span>/</span>\n            <span text-yellow-700 dark:text-yellow-500>\n              RUNNING ({{ testsTotal.running }})\n            </span>\n            <span text-green-700 dark:text-green-500>\n              PASS ({{ testsTotal.success }})\n            </span>\n            <span>/</span>\n            <span class=\"text-purple-700 dark:text-purple-400\">\n              SKIP ({{ filter.onlyTests ? testsTotal.skipped : '--' }})\n            </span>\n          </div>\n        </template>\n        <!-- empty-state -->\n        <template v-if=\"(isFiltered || isFilteredByStatus || !!currentProjectName) && uiEntries.length === 0\">\n          <div v-if=\"initialized\" flex=\"~ col\" items-center p=\"x4 y4\" font-light>\n            <div v-if=\"searchMatcher.error\" text-red text-center>\n              {{ searchMatcher.error }}\n            </div>\n            <div v-else op30>\n              No matched test\n            </div>\n            <button\n              type=\"button\"\n              font-light\n              text-sm\n              border=\"~ gray-400/50 rounded\"\n              p=\"x2 y0.5\"\n              m=\"t2\"\n              op=\"50\"\n              :class=\"disableClearSearch ? null : 'hover:op100'\"\n              :disabled=\"disableClearSearch\"\n              @click.passive=\"clearSearch(true)\"\n            >\n              Clear Search\n            </button>\n            <button\n              type=\"button\"\n              font-light\n              text-sm\n              border=\"~ gray-400/50 rounded\"\n              p=\"x2 y0.5\"\n              m=\"t2\"\n              op=\"50\"\n              :class=\"disableFilter ? null : 'hover:op100'\"\n              :disabled=\"disableFilter\"\n              @click.passive=\"clearFilter(true)\"\n            >\n              Clear Filter\n            </button>\n            <button\n              type=\"button\"\n              font-light\n              op=\"50 hover:100\"\n              text-sm\n              border=\"~ gray-400/50 rounded\"\n              p=\"x2 y0.5\"\n              m=\"t2\"\n              @click.passive=\"clearAll\"\n            >\n              Clear All\n            </button>\n          </div>\n          <div v-else flex=\"~ col\" items-center p=\"x4 y4\" font-light>\n            <div class=\"i-carbon:circle-dash animate-spin\" />\n            <div op30>\n              Loading...\n            </div>\n          </div>\n        </template>\n        <template v-else>\n          <RecycleScroller\n            page-mode\n            key-field=\"id\"\n            :item-size=\"28\"\n            :items=\"uiEntries\"\n            :buffer=\"100\"\n          >\n            <template #default=\"{ item }\">\n              <ExplorerItem\n                class=\"h-28px m-0 p-0\"\n                :task-id=\"item.id\"\n                :expandable=\"item.expandable\"\n                :type=\"item.type\"\n                :current=\"activeFileId === item.id\"\n                :indent=\"item.indent\"\n                :name=\"item.name\"\n                :typecheck=\"item.typecheck === true\"\n                :project-name=\"item.projectName ?? ''\"\n                :project-name-color=\"item.projectNameColor ?? ''\"\n                :state=\"item.state\"\n                :duration=\"item.duration\"\n                :slow=\"item.slow === true\"\n                :opened=\"item.expanded\"\n                :disable-task-location=\"!includeTaskLocation\"\n                :class=\"selectedTest === item.id || (!selectedTest && activeFileId === item.id) ? 'bg-active' : ''\"\n                :on-item-click=\"onItemClick\"\n              />\n            </template>\n          </RecycleScroller>\n        </template>\n      </ResultsPanel>\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/explorer/ExplorerItem.vue",
    "content": "<script setup lang=\"ts\">\nimport type { Task, TaskState } from '@vitest/runner'\nimport type { TaskTreeNodeType } from '~/composables/explorer/types'\nimport { Tooltip as VueTooltip } from 'floating-vue'\nimport { computed, nextTick } from 'vue'\nimport { client, config, isReport, runFiles, runTask } from '~/composables/client'\nimport { showTaskSource } from '~/composables/codemirror'\nimport { explorerTree } from '~/composables/explorer'\nimport { hasFailedSnapshot } from '~/composables/explorer/collector'\nimport { escapeHtml, highlightRegex } from '~/composables/explorer/state'\nimport { coverageEnabled, disableCoverage } from '~/composables/navigation'\nimport { getBadgeTextColor } from '~/utils/task'\nimport IconAction from '../IconAction.vue'\nimport IconButton from '../IconButton.vue'\nimport StatusIcon from '../StatusIcon.vue'\n\n// TODO: better handling of \"opened\" - it means to forcefully open the tree item and set in TasksList right now\nconst {\n  taskId,\n  indent,\n  name,\n  duration,\n  slow,\n  current,\n  opened,\n  expandable,\n  typecheck,\n  type,\n  disableTaskLocation,\n  onItemClick,\n  projectNameColor,\n  state,\n} = defineProps<{\n  taskId: string\n  name: string\n  indent: number\n  typecheck?: boolean\n  duration?: number\n  slow?: boolean\n  state?: TaskState\n  current: boolean\n  type: TaskTreeNodeType\n  opened: boolean\n  expandable: boolean\n  search?: string\n  projectName?: string\n  projectNameColor: string\n  disableTaskLocation?: boolean\n  onItemClick?: (task: Task) => void\n}>()\n\nconst task = computed(() => client.state.idMap.get(taskId))\n\nconst failedSnapshot = computed(() => {\n  // don't traverse the tree if it's a report\n  if (isReport) {\n    return false\n  }\n\n  const t = task.value\n  return t && hasFailedSnapshot(t)\n})\n\nfunction toggleOpen() {\n  if (!expandable) {\n    onItemClick?.(task.value!)\n    return\n  }\n\n  if (opened) {\n    explorerTree.collapseNode(taskId)\n  }\n  else {\n    explorerTree.expandNode(taskId)\n  }\n}\n\nasync function onRun(task: Task) {\n  onItemClick?.(task)\n  if (coverageEnabled.value) {\n    disableCoverage.value = true\n    await nextTick()\n  }\n\n  if (type === 'file') {\n    await runFiles([task.file])\n  }\n  else {\n    await runTask(task)\n  }\n}\n\nfunction updateSnapshot(task: Task) {\n  return client.rpc.updateSnapshot(task.file)\n}\n\nconst data = computed(() => {\n  return indent <= 0 ? [] : Array.from({ length: indent }, (_, i) => `${taskId}-${i}`)\n})\nconst gridStyles = computed(() => {\n  const entries = data.value\n  const gridColumns: string[] = []\n  // folder icon\n  if (type === 'file' || type === 'suite') {\n    gridColumns.push('min-content')\n  }\n\n  // status icon\n  gridColumns.push('min-content')\n  // typecheck icon\n  if (type === 'suite' && typecheck) {\n    gridColumns.push('min-content')\n  }\n  // text content\n  gridColumns.push('minmax(0, 1fr)')\n  // action buttons\n  gridColumns.push('min-content')\n\n  // all the vertical lines with width 1rem and mx-2: always centered\n  return `grid-template-columns: ${\n    entries.map(() => '1rem').join(' ')\n  } ${gridColumns.join(' ')};`\n})\n\nconst runButtonTitle = computed(() => {\n  if (config.value.api?.allowExec === false) {\n    return 'Cannot run tests when `api.allowExec` is `false`. Did you expose UI to the internet?'\n  }\n  return type === 'file'\n    ? 'Run current file'\n    : type === 'suite'\n      ? 'Run all tests in this suite'\n      : 'Run current test'\n})\n\nconst escapedName = computed(() => escapeHtml(name))\nconst highlighted = computed(() => {\n  const regex = highlightRegex.value\n  const useName = escapedName.value\n  return regex\n    ? useName.replace(regex, match => `<span class=\"highlight\">${match}</span>`)\n    : useName\n})\n\nconst disableShowDetails = computed(() => type !== 'file' && disableTaskLocation)\nconst showDetailsTooltip = computed(() => {\n  return type === 'file'\n    ? 'Open test details'\n    : type === 'suite'\n      ? 'View Suite Source Code'\n      : 'View Test Source Code'\n})\nconst showDetailsClasses = computed(() => disableShowDetails.value ? 'color-red5 dark:color-#f43f5e' : null)\n\nfunction showDetails() {\n  const t = task.value!\n  if (type === 'file') {\n    onItemClick?.(t)\n  }\n  else {\n    showTaskSource(t)\n  }\n}\n\nconst projectNameTextColor = computed(() => getBadgeTextColor(projectNameColor))\n\n/**\nexperiments trying to show tags compactly\nconst tagsBorderGradient = computed(() => {\n  const t = task.value!\n  if (!t || t.type !== 'test' || !t.tags?.length) {\n    return null\n  }\n  const colors = t.tags.map(t => getBadgeNameColor(t)).reverse()\n  const percent = 100 / colors.length\n  const res = `linear-gradient(to bottom left, ${colors.map(c => `${c} ${percent}%`).join(', ')})`\n  return res\n})\nconst tagsBgGradient = computed(() => {\n  const t = task.value!\n  if (!t || t.type !== 'test' || !t.tags?.length) {\n    return null\n  }\n  const colors = t.tags.map(t => getBadgeNameColor(t, true)).reverse()\n  const percent = 100 / colors.length\n  const res = `linear-gradient(to bottom left, ${colors.map(c => `${c} ${percent}%`).join(', ')})`\n  return res\n})\n */\n</script>\n\n<template>\n  <div\n    v-if=\"task\"\n    items-center\n    p=\"x-2 y-1\"\n    grid=\"~ rows-1 items-center gap-x-2\"\n    w-full\n    h-28px\n    border-rounded\n    hover=\"bg-active\"\n    cursor-pointer\n    class=\"item-wrapper\"\n    :style=\"gridStyles\"\n    :aria-label=\"name\"\n    :data-current=\"current\"\n    data-testid=\"explorer-item\"\n    @click=\"toggleOpen()\"\n  >\n    <template v-if=\"indent > 0\">\n      <div v-for=\"i in data\" :key=\"i\" border=\"solid gray-500 dark:gray-400\" class=\"vertical-line\" h-28px inline-flex mx-2 op20 />\n    </template>\n    <div v-if=\"type === 'file' || type === 'suite'\" w-4>\n      <div :class=\"opened ? 'i-carbon:chevron-down' : 'i-carbon:chevron-right op20'\" op20 />\n    </div>\n    <StatusIcon :state=\"state\" :mode=\"task.mode\" :failed-snapshot=\"failedSnapshot\" w-4 />\n    <div flex items-baseline gap-2 overflow-hidden>\n      <div v-if=\"type === 'file' && typecheck\" v-tooltip.bottom=\"'This is a typecheck test. It won\\'t report results of the runtime tests'\" class=\"i-logos:typescript-icon\" flex-shrink-0 />\n      <span text-sm truncate font-light>\n        <span v-if=\"type === 'file' && projectName\" class=\"rounded-full py-0.5 px-2 mr-1 text-xs\" :style=\"{ backgroundColor: projectNameColor, color: projectNameTextColor }\">\n          {{ projectName }}\n        </span>\n        <span :class=\"state === 'fail' ? 'text-red-700 dark:text-red-500' : undefined\" v-html=\"highlighted\" />\n      </span>\n      <span\n        v-if=\"typeof duration === 'number'\"\n        text=\"xs\"\n        :class=\"slow ? 'text-yellow-700 dark:text-yellow-500' : 'op20'\"\n        style=\"white-space: nowrap\"\n      >\n        {{ duration > 0 ? duration : '< 1' }}ms\n      </span>\n    </div>\n    <div gap-1 justify-end items-center flex-grow-1 pl-1 class=\"test-actions\">\n      <!-- <div\n        v-if=\"tagsBorderGradient\"\n        text-xs\n        rounded-full\n        flex\n        justify-center\n        items-center\n        class=\"w-[1.1rem] h-[1.1rem]\"\n        :style=\"{\n          background: tagsBorderGradient,\n        }\"\n      >\n        <div :style=\"{ background: tagsBgGradient }\" class=\"w-[0.9rem] h-[0.9rem]\" rounded-full />\n      </div> -->\n      <IconAction\n        v-if=\"!isReport && failedSnapshot && config.api?.allowExec && config.api?.allowWrite\"\n        v-tooltip.bottom=\"'Fix failed snapshot(s)'\"\n        data-testid=\"btn-fix-snapshot\"\n        title=\"Fix failed snapshot(s)\"\n        icon=\"i-carbon:result-old\"\n        @click.prevent.stop=\"updateSnapshot(task)\"\n      />\n      <VueTooltip\n        placement=\"bottom\"\n        class=\"w-1.4em h-1.4em op100 rounded flex\"\n        :class=\"showDetailsClasses\"\n      >\n        <IconButton\n          data-testid=\"btn-open-details\"\n          :icon=\"type === 'file' ? 'i-carbon:intrusion-prevention' : 'i-carbon:code-reference'\"\n          @click.prevent.stop=\"showDetails\"\n        />\n        <template #popper>\n          <div v-if=\"disableShowDetails\" class=\"op100 gap-1 p-y-1\" grid=\"~ items-center cols-[1.5em_1fr]\">\n            <div class=\"i-carbon:information-square w-1.5em h-1.5em\" />\n            <div>{{ showDetailsTooltip }}: this feature is not available, you have disabled <span class=\"text-[#add467]\">includeTaskLocation</span> in your configuration file.</div>\n            <div style=\"grid-column: 2\">\n              Clicking this button the code tab will position the cursor at first line in the source code since the UI doesn't have the information available.\n            </div>\n          </div>\n          <div v-else>\n            {{ showDetailsTooltip }}\n          </div>\n        </template>\n      </VueTooltip>\n      <IconButton\n        v-if=\"!isReport\"\n        v-tooltip.bottom=\"runButtonTitle\"\n        data-testid=\"btn-run-test\"\n        :title=\"runButtonTitle\"\n        icon=\"i-carbon:play-filled-alt\"\n        text-green-700 dark:text-green-500\n        :disabled=\"config.api?.allowExec === false\"\n        @click.prevent.stop=\"onRun(task)\"\n      />\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.vertical-line:first-of-type {\n  @apply border-l-2px;\n}\n.vertical-line + .vertical-line {\n  @apply border-r-1px;\n}\n.test-actions {\n  display: none;\n}\n.item-wrapper:hover .test-actions {\n  display: flex;\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/views/ScreenshotError.vue",
    "content": "<script setup lang=\"ts\">\nimport { onKeyStroke } from '@vueuse/core'\nimport IconButton from '../IconButton.vue'\n\ndefineProps<{\n  file: string\n  name: string\n  url?: string\n}>()\nconst emit = defineEmits<{ (e: 'close'): void }>()\n\nonKeyStroke('Escape', () => {\n  emit('close')\n})\n</script>\n\n<template>\n  <div w-350 max-w-screen h-full flex flex-col>\n    <div p-4 relative border=\"base b\">\n      <p>Screenshot error</p>\n      <p op50 font-mono text-sm>\n        {{ file }}\n      </p>\n      <p op50 font-mono text-sm>\n        {{ name }}\n      </p>\n      <IconButton\n        icon=\"i-carbon:close\"\n        title=\"Close\"\n        absolute\n        top-5px\n        right-5px\n        text-2xl\n        @click=\"emit('close')\"\n      />\n    </div>\n\n    <div class=\"scrolls\" grid=\"~ cols-1 rows-[min-content]\" p-4>\n      <img\n        v-if=\"url\"\n        :src=\"url\"\n        :alt=\"`Screenshot error for '${name}' test in file '${file}'`\"\n        border=\"base t r b l dotted red-500\"\n      >\n      <div v-else>\n        Something was wrong, the image cannot be resolved.\n      </div>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.scrolls {\n  place-items: center;\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/views/ViewConsoleOutput.vue",
    "content": "<script setup lang=\"ts\">\nimport { getNames } from '@vitest/ws-client'\nimport { computed } from 'vue'\nimport { client, currentLogs as logs } from '~/composables/client'\nimport { isDark } from '~/composables/dark'\nimport { createAnsiToHtmlFilter } from '~/composables/error'\nimport { escapeHtml } from '~/utils/escape'\nimport ViewConsoleOutputEntry from './ViewConsoleOutputEntry.vue'\n\nconst formattedLogs = computed(() => {\n  const data = logs.value\n  if (data) {\n    const filter = createAnsiToHtmlFilter(isDark.value)\n    return data.map(({ taskId, type, time, content }) => ({ taskId, type, time, content: filter.toHtml(escapeHtml(content)) }))\n  }\n\n  return undefined\n})\n\nfunction getTaskName(id?: string) {\n  const task = id && client.state.idMap.get(id)\n  if (task && 'filepath' in task) {\n    return task.name\n  }\n  return (task ? getNames(task).slice(1).join(' > ') : '-') || '-'\n}\n</script>\n\n<template>\n  <div v-if=\"formattedLogs?.length\" h-full class=\"scrolls\" flex flex-col data-testid=\"logs\">\n    <div v-for=\"{ taskId, type, time, content } of formattedLogs\" :key=\"taskId\" font-mono>\n      <ViewConsoleOutputEntry\n        :task-name=\"getTaskName(taskId)\"\n        :type=\"type\"\n        :time=\"time\"\n        :content=\"content\"\n      />\n    </div>\n  </div>\n  <div v-else p6>\n    Log something in your test and it would print here. (e.g. <pre inline>console.log(foo)</pre>)\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/views/ViewConsoleOutputEntry.spec.ts",
    "content": "import Filter from 'ansi-to-html'\nimport { describe, expect, it } from 'vitest'\nimport { render } from '~/test'\nimport ViewConsoleOutputEntry from './ViewConsoleOutputEntry.vue'\n\ndescribe('ViewConsoleOutputEntry', () => {\n  it('test html entry', () => {\n    const now = new Date().toISOString()\n    const content = new Filter().toHtml(`\\x1B[33m${now}\\x1B[0m`)\n    const { container } = render(ViewConsoleOutputEntry, {\n      props: {\n        taskName: 'test/html',\n        type: 'stderr',\n        time: Date.now(),\n        content,\n      },\n    })\n\n    const spans = container.querySelectorAll('span')\n    expect(spans).toHaveLength(1)\n    const span = spans[0]\n\n    expect(span.textContent, 'the message has the correct message').toBe(now)\n    expect(\n      span.getAttribute('style'),\n      'the message has the correct text color',\n    ).toBe('color:#A50')\n  })\n})\n"
  },
  {
    "path": "packages/ui/client/components/views/ViewConsoleOutputEntry.vue",
    "content": "<script setup lang=\"ts\">\nimport type { UserConsoleLog } from 'vitest'\n\ndefineProps<{\n  taskName: string\n  type: UserConsoleLog['type']\n  time: UserConsoleLog['time']\n  content: UserConsoleLog['content']\n}>()\n\nfunction formatTime(t: number) {\n  return new Date(t).toLocaleTimeString()\n}\n</script>\n\n<template>\n  <div border=\"b base\" p-4>\n    <div\n      text-xs\n      mb-1\n      :class=\"type === 'stderr' ? 'text-red-600 dark:text-red-300' : 'op30'\"\n    >\n      {{ formatTime(time) }} | {{ taskName }} | {{ type }}\n    </div>\n    <pre data-type=\"html\" v-html=\"content\" />\n  </div>\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/views/ViewEditor.vue",
    "content": "<script setup lang=\"ts\">\nimport type { Task } from '@vitest/runner'\nimport type CodeMirror from 'codemirror'\nimport type { RunnerTestFile, TestAnnotation, TestError } from 'vitest'\nimport { until, useResizeObserver, watchDebounced } from '@vueuse/core'\nimport { createTooltip, destroyTooltip } from 'floating-vue'\nimport { computed, nextTick, onBeforeUnmount, ref, shallowRef, watch } from 'vue'\nimport { getAttachmentUrl, sanitizeFilePath } from '~/composables/attachments'\nimport { client, config, isReport } from '~/composables/client'\nimport { finished } from '~/composables/client/state'\nimport { codemirrorRef } from '~/composables/codemirror'\nimport { openInEditor } from '~/composables/error'\nimport { columnNumber, lineNumber } from '~/composables/params'\nimport CodeMirrorContainer from '../CodeMirrorContainer.vue'\n\nconst props = defineProps<{\n  file?: RunnerTestFile\n}>()\n\nconst emit = defineEmits<{ (event: 'draft', value: boolean): void }>()\n\nconst code = ref('')\nconst serverCode = shallowRef<string | undefined>(undefined)\nconst draft = ref(false)\nconst loading = ref(true)\nconst saving = ref(false)\nconst currentPosition = ref<CodeMirror.Position | undefined>()\n\nwatch(\n  () => props.file,\n  async () => {\n    // this watcher will be called multiple times when saving the file in the view editor\n    // since we are saving the file and changing the content inside onSave we just return here\n    if (saving.value) {\n      return\n    }\n    loading.value = true\n    try {\n      if (!props.file || !props.file?.filepath) {\n        code.value = ''\n        serverCode.value = code.value\n        draft.value = false\n        loading.value = false\n        return\n      }\n\n      code.value = (await client.rpc.readTestFile(props.file.filepath)) || ''\n      serverCode.value = code.value\n      draft.value = false\n    }\n    catch (e) {\n      console.error('cannot fetch file', e)\n    }\n\n    await nextTick()\n\n    // fire focusing editor after loading\n    loading.value = false\n  },\n  { immediate: true },\n)\n\nwatch(() => [loading.value, saving.value, props.file, lineNumber.value, columnNumber.value] as const, ([loadingFile, s, _, l, c]) => {\n  if (!loadingFile && !s) {\n    if (l != null) {\n      nextTick(() => {\n        const cp = currentPosition.value\n        const line = cp ?? { line: (l ?? 1) - 1, ch: c ?? 0 }\n        // restore caret position: the watchDebounced below will use old value\n        if (cp) {\n          currentPosition.value = undefined\n        }\n        else {\n          codemirrorRef.value?.scrollIntoView(line, 100)\n          nextTick(() => {\n            codemirrorRef.value?.focus()\n            codemirrorRef.value?.setCursor(line)\n          })\n        }\n      })\n    }\n    else {\n      nextTick(() => {\n        codemirrorRef.value?.focus()\n      })\n    }\n  }\n}, { flush: 'post' })\n\nconst ext = computed(() => props.file?.filepath?.split(/\\./g).pop() || 'js')\nconst editor = ref<any>()\n\nconst errors = computed(() => {\n  const errors: TestError[] = []\n  function addFailed(task: Task) {\n    if (task.result?.errors) {\n      errors.push(...task.result.errors as TestError[])\n    }\n    if (task.type === 'suite') {\n      task.tasks.forEach(addFailed)\n    }\n  }\n  props.file?.tasks.forEach(addFailed)\n  return errors\n})\n\nconst annotations = computed(() => {\n  const annotations: TestAnnotation[] = []\n  function addAnnotations(task: Task) {\n    if (task.type === 'test') {\n      annotations.push(...task.annotations)\n    }\n    if (task.type === 'suite') {\n      task.tasks.forEach(addAnnotations)\n    }\n  }\n  props.file?.tasks.forEach(addAnnotations)\n  return annotations\n})\nconst widgets: CodeMirror.LineWidget[] = []\nconst handles: CodeMirror.LineHandle[] = []\nconst listeners: [el: HTMLSpanElement, l: EventListener, t: () => void][] = []\n\nconst hasBeenEdited = ref(false)\n\nfunction clearListeners() {\n  listeners.forEach(([el, l, t]) => {\n    el.removeEventListener('click', l)\n    t()\n  })\n  listeners.length = 0\n}\n\nuseResizeObserver(editor, () => {\n  codemirrorRef.value?.refresh()\n})\n\nfunction codemirrorChanges() {\n  draft.value = serverCode.value !== codemirrorRef.value!.getValue()\n}\n\nwatch(\n  draft,\n  (d) => {\n    emit('draft', d)\n  },\n  { immediate: true },\n)\n\nfunction createErrorElement(e: TestError) {\n  const stacks = (e?.stacks || []).filter(\n    i => i.file && i.file === props.file?.filepath,\n  )\n  const stack = stacks?.[0]\n  if (!stack) {\n    return\n  }\n  const div = document.createElement('div')\n  div.className = 'op80 flex gap-x-2 items-center'\n  const pre = document.createElement('pre')\n  pre.className = 'c-red-700 dark:c-red-400'\n  pre.textContent = `${' '.repeat(stack.column)}^ ${e.name}: ${\n    e?.message || ''\n  }`\n  div.appendChild(pre)\n  const span = document.createElement('span')\n  span.className\n    = 'i-carbon-launch c-red-700 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em'\n  span.tabIndex = 0\n  span.ariaLabel = 'Open in Editor'\n  createTooltip(\n    span,\n    {\n      content: 'Open in Editor',\n      placement: 'bottom',\n    },\n    false,\n  )\n  const el: EventListener = async () => {\n    await openInEditor(stack.file, stack.line, stack.column)\n  }\n  span.addEventListener('click', el)\n  div.appendChild(span)\n  listeners.push([span, el, () => destroyTooltip(span)])\n  handles.push(codemirrorRef.value!.addLineClass(stack.line - 1, 'wrap', 'bg-red-500/10'))\n  widgets.push(codemirrorRef.value!.addLineWidget(stack.line - 1, div))\n}\n\nfunction createAnnotationElement(annotation: TestAnnotation) {\n  if (!annotation.location) {\n    return\n  }\n\n  // TODO(v4): design\n  const { line, file } = annotation.location\n  if (file !== props.file?.filepath) {\n    return\n  }\n\n  const notice = document.createElement('div')\n  notice.classList.add(\n    'wrap',\n    'bg-active',\n    'py-3',\n    'px-6',\n    'my-1',\n  )\n  notice.role = 'note'\n\n  const messageWrapper = document.createElement('div')\n  messageWrapper.classList.add('block', 'text-black', 'dark:text-white')\n\n  const type = document.createElement('span')\n  type.textContent = `${annotation.type}: `\n  type.classList.add('font-bold')\n\n  const message = document.createElement('span')\n  message.classList.add('whitespace-pre')\n  message.textContent = annotation.message.replace(/[^\\r]\\n/, '\\r\\n')\n\n  messageWrapper.append(type, message)\n  notice.append(messageWrapper)\n  const attachment = annotation.attachment\n  if (attachment?.path || attachment?.body) {\n    if (attachment.contentType?.startsWith('image/')) {\n      const link = document.createElement('a')\n      const img = document.createElement('img')\n      link.classList.add('inline-block', 'mt-3')\n      link.style.maxWidth = '50vw'\n      const potentialUrl = attachment.path || attachment.body\n      if (typeof potentialUrl === 'string' && (potentialUrl.startsWith('http://') || potentialUrl.startsWith('https://'))) {\n        img.setAttribute('src', potentialUrl)\n        link.referrerPolicy = 'no-referrer'\n      }\n      else {\n        img.setAttribute('src', getAttachmentUrl(attachment))\n      }\n      link.target = '_blank'\n      link.href = img.src\n      link.append(img)\n      notice.append(link)\n    }\n    else {\n      const download = document.createElement('a')\n      download.href = getAttachmentUrl(attachment)\n      download.download = sanitizeFilePath(annotation.message, attachment.contentType)\n      download.classList.add('flex', 'w-min', 'gap-2', 'items-center', 'font-sans', 'underline', 'cursor-pointer')\n      const icon = document.createElement('div')\n      icon.classList.add('i-carbon:download', 'block')\n      const text = document.createElement('span')\n      text.textContent = 'Download'\n      download.append(icon, text)\n      notice.append(download)\n    }\n  }\n  widgets.push(codemirrorRef.value!.addLineWidget(line - 1, notice))\n}\n\nconst { pause, resume } = watch(\n  [codemirrorRef, errors, annotations, finished] as const,\n  ([cmValue, errors, annotations, end]) => {\n    if (!cmValue) {\n      widgets.length = 0\n      handles.length = 0\n      clearListeners()\n      return\n    }\n\n    // if still running\n    if (!end) {\n      return\n    }\n\n    // cleanup previous data when not saving just reloading\n    cmValue.off('changes', codemirrorChanges)\n\n    // cleanup previous data\n    clearListeners()\n    widgets.forEach(widget => widget.clear())\n    handles.forEach(h => cmValue?.removeLineClass(h, 'wrap'))\n    widgets.length = 0\n    handles.length = 0\n\n    setTimeout(() => {\n      // add new data\n      errors.forEach(createErrorElement)\n\n      annotations.forEach(createAnnotationElement)\n\n      // Prevent getting access to initial state\n      if (!hasBeenEdited.value) {\n        cmValue.clearHistory()\n      }\n\n      cmValue.on('changes', codemirrorChanges)\n    }, 100)\n  },\n  { flush: 'post' },\n)\n\nwatchDebounced(() => [finished.value, saving.value, currentPosition.value] as const, ([f, s], old) => {\n  if (f && !s && old && old[2]) {\n    codemirrorRef.value?.setCursor(old[2])\n  }\n}, { debounce: 100, flush: 'post' })\n\nasync function onSave(content: string) {\n  if (saving.value) {\n    return\n  }\n  pause()\n  saving.value = true\n  await nextTick()\n\n  // clear previous state\n  const cmValue = codemirrorRef.value\n  if (cmValue) {\n    cmValue.setOption('readOnly', true)\n    await nextTick()\n    cmValue.refresh()\n  }\n  // save cursor position\n  currentPosition.value = cmValue?.getCursor()\n  cmValue?.off('changes', codemirrorChanges)\n\n  // cleanup previous data\n  clearListeners()\n  widgets.forEach(widget => widget.clear())\n  handles.forEach(h => cmValue?.removeLineClass(h, 'wrap'))\n  widgets.length = 0\n  handles.length = 0\n\n  try {\n    hasBeenEdited.value = true\n    // save the file changes\n    await client.rpc.saveTestFile(props.file!.filepath, content)\n    // update original server code\n    serverCode.value = content\n    // update draft indicator in the tab title (</> * Code)\n    draft.value = false\n  }\n  catch (e) {\n    console.error('error saving file', e)\n  }\n\n  // Prevent getting access to initial state\n  if (!hasBeenEdited.value) {\n    cmValue?.clearHistory()\n  }\n\n  try {\n    // the server will send a few events in a row\n    // await to re-run test\n    await until(finished).toBe(false, { flush: 'sync', timeout: 1000, throwOnTimeout: true })\n    // await to finish\n    await until(finished).toBe(true, { flush: 'sync', timeout: 1000, throwOnTimeout: false })\n  }\n  catch {\n    // ignore errors\n  }\n\n  // add new data\n  errors.value.forEach(createErrorElement)\n  annotations.value.forEach(createAnnotationElement)\n\n  cmValue?.on('changes', codemirrorChanges)\n\n  saving.value = false\n  await nextTick()\n  if (cmValue) {\n    cmValue.setOption('readOnly', false)\n    await nextTick()\n    cmValue.refresh()\n  }\n  // activate watcher\n  resume()\n}\n\n// we need to remove listeners before unmounting the component: the watcher will not be called\nonBeforeUnmount(clearListeners)\n</script>\n\n<template>\n  <CodeMirrorContainer\n    ref=\"editor\"\n    v-model=\"code\"\n    h-full\n    v-bind=\"{ lineNumbers: true, readOnly: isReport || !config.api?.allowWrite, saving }\"\n    :mode=\"ext\"\n    data-testid=\"code-mirror\"\n    @save=\"onSave\"\n  />\n</template>\n"
  },
  {
    "path": "packages/ui/client/components/views/ViewModuleGraph.vue",
    "content": "<script setup lang=\"ts\">\nimport type { ResizeContext } from 'd3-graph-controller'\nimport type { Selection } from 'd3-selection'\nimport type {\n  ModuleGraph,\n  ModuleGraphController,\n  ModuleLink,\n  ModuleNode,\n  ModuleType,\n} from '~/composables/module-graph'\nimport { useRefHistory } from '@vueuse/core'\nimport {\n  defineGraphConfig,\n  defineNode,\n  GraphController,\n  Markers,\n  PositionInitializers,\n} from 'd3-graph-controller'\nimport { computed, onMounted, onUnmounted, ref, shallowRef, toRefs, watch } from 'vue'\nimport { config, isReport } from '~/composables/client'\nimport { currentModule } from '~/composables/navigation'\nimport IconButton from '../IconButton.vue'\nimport Modal from '../Modal.vue'\nimport ViewModuleGraphImportBreakdown from '../ModuleGraphImportBreakdown.vue'\nimport ModuleTransformResultView from '../ModuleTransformResultView.vue'\n\nconst props = defineProps<{\n  graph: ModuleGraph\n  projectName: string\n}>()\n\nconst hideNodeModules = defineModel<boolean>({ required: true })\n\nconst { graph } = toRefs(props)\n\nconst el = ref<HTMLDivElement>()\n\nconst modalShow = ref(false)\nconst selectedModule = ref<{ id: string; type: ModuleType } | null>()\nconst selectedModuleHistory = useRefHistory(selectedModule)\nconst controller = ref<ModuleGraphController | undefined>()\nconst focusedNode = ref<string | null>(null)\nconst filteredGraph = shallowRef<ModuleGraph>(graph.value)\nconst breakdownIconClass = computed(() => {\n  let textClass = ''\n  const importDurations = currentModule.value?.importDurations\n  const thresholds = config.value.experimental?.importDurations.thresholds\n  if (!importDurations || !thresholds) {\n    return textClass\n  }\n  for (const moduleId in importDurations) {\n    const { totalTime } = importDurations[moduleId]\n    if (totalTime >= thresholds.danger) {\n      textClass = 'text-red'\n      break\n    }\n    else if (totalTime >= thresholds.warn) {\n      textClass = 'text-orange'\n    }\n  }\n  return textClass\n})\nconst breakdownShow = ref(breakdownIconClass.value === 'text-red')\n\nonMounted(() => {\n  filteredGraph.value = filterGraphByLevels(graph.value, null, 2)\n  resetGraphController()\n})\n\nonUnmounted(() => {\n  controller.value?.shutdown()\n})\n\nwatch(graph, () => {\n  filteredGraph.value = filterGraphByLevels(graph.value, focusedNode.value, 2)\n  resetGraphController()\n})\n\nfunction showFullGraph() {\n  filteredGraph.value = graph.value\n  resetGraphController()\n}\n\nfunction toggleImportBreakdown() {\n  breakdownShow.value = !breakdownShow.value\n}\n\nfunction filterGraphByLevels(\n  sourceGraph: ModuleGraph,\n  startNodeId: string | null,\n  levels: number = 2,\n): ModuleGraph {\n  if (!sourceGraph.nodes.length || sourceGraph.nodes.length <= 50) {\n    return sourceGraph\n  }\n\n  // Build adjacency list for efficient traversal\n  const adjacencyList = new Map<string, Set<string>>()\n  sourceGraph.nodes.forEach(node => adjacencyList.set(node.id, new Set()))\n\n  sourceGraph.links.forEach((link) => {\n    const sourceId = typeof link.source === 'object' ? link.source.id : String(link.source)\n    const targetId = typeof link.target === 'object' ? link.target.id : String(link.target)\n    adjacencyList.get(sourceId)?.add(targetId)\n    adjacencyList.get(targetId)?.add(sourceId)\n  })\n\n  let startNodes: string[]\n  if (startNodeId) {\n    startNodes = [startNodeId]\n  }\n  else {\n    // Find root node (node with type 'inline' that appears as source but not target, or first inline node)\n    const targetIds = new Set(sourceGraph.links.map(link =>\n      typeof link.target === 'object' ? link.target.id : String(link.target),\n    ))\n    const rootCandidates = sourceGraph.nodes.filter(\n      node => node.type === 'inline' && !targetIds.has(node.id),\n    )\n    startNodes = rootCandidates.length > 0\n      ? [rootCandidates[0].id]\n      : [sourceGraph.nodes[0].id]\n  }\n\n  // BFS to find all nodes within N levels\n  const visitedNodes = new Set<string>()\n  const queue: Array<{ id: string; level: number }> = startNodes.map(id => ({ id, level: 0 }))\n\n  while (queue.length > 0) {\n    const { id, level } = queue.shift()!\n\n    if (visitedNodes.has(id) || level > levels) {\n      continue\n    }\n\n    visitedNodes.add(id)\n\n    if (level < levels) {\n      const neighbors = adjacencyList.get(id) || new Set()\n      neighbors.forEach((neighborId) => {\n        if (!visitedNodes.has(neighborId)) {\n          queue.push({ id: neighborId, level: level + 1 })\n        }\n      })\n    }\n  }\n\n  const nodeMap = new Map(sourceGraph.nodes.map(node => [node.id, node]))\n  const filteredNodes = Array.from(visitedNodes)\n    .map(id => nodeMap.get(id))\n    .filter(node => node !== undefined) as ModuleNode[]\n\n  const filteredNodeMap = new Map(filteredNodes.map(node => [node.id, node]))\n\n  const filteredLinks = sourceGraph.links\n    .map((link) => {\n      const sourceId = typeof link.source === 'object' ? link.source.id : String(link.source)\n      const targetId = typeof link.target === 'object' ? link.target.id : String(link.target)\n\n      // Only include links where both nodes are in the filtered set\n      if (visitedNodes.has(sourceId) && visitedNodes.has(targetId)) {\n        const sourceNode = filteredNodeMap.get(sourceId)\n        const targetNode = filteredNodeMap.get(targetId)\n\n        if (sourceNode && targetNode) {\n          return {\n            ...link,\n            source: sourceNode,\n            target: targetNode,\n          }\n        }\n      }\n      return null\n    })\n    .filter(link => link !== null) as ModuleLink[]\n\n  return {\n    nodes: filteredNodes,\n    links: filteredLinks,\n  }\n}\n\nfunction setFilter(name: ModuleType, value: boolean) {\n  controller.value?.filterNodesByType(value, name)\n}\n\nfunction setSelectedModule(id: string, type: ModuleType) {\n  selectedModule.value = { id, type }\n  modalShow.value = true\n}\n\nfunction selectPreviousModule() {\n  selectedModuleHistory.undo()\n}\n\nfunction closeResultView() {\n  modalShow.value = false\n  selectedModuleHistory.clear()\n}\n\nfunction focusOnNode(nodeId: string) {\n  focusedNode.value = nodeId\n  filteredGraph.value = filterGraphByLevels(graph.value, nodeId, 2)\n  updateNodeColors()\n  resetGraphController()\n}\n\nfunction resetToRoot() {\n  focusedNode.value = null\n  filteredGraph.value = filterGraphByLevels(graph.value, null, 2)\n  updateNodeColors()\n  resetGraphController()\n}\n\nfunction updateNodeColors() {\n  const updatedNodes = filteredGraph.value.nodes.map((node) => {\n    let color: string\n    let labelColor: string\n\n    if (node.id === focusedNode.value) {\n      color = 'var(--color-node-focused)'\n      labelColor = 'var(--color-node-focused)'\n    }\n    else if (node.type === 'inline') {\n      const originalColor = node.color\n      const isRoot = originalColor === 'var(--color-node-root)'\n      color = isRoot ? 'var(--color-node-root)' : 'var(--color-node-inline)'\n      labelColor = color\n    }\n    else {\n      color = 'var(--color-node-external)'\n      labelColor = 'var(--color-node-external)'\n    }\n\n    return defineNode<ModuleType, ModuleNode>({\n      ...node,\n      color,\n      label: node.label\n        ? {\n            ...node.label,\n            color: labelColor,\n          }\n        : node.label,\n    })\n  })\n\n  const nodeMap = new Map(updatedNodes.map(node => [node.id, node]))\n\n  const updatedLinks = filteredGraph.value.links.map((link) => {\n    const sourceId = typeof link.source === 'object' ? link.source.id : String(link.source)\n    const targetId = typeof link.target === 'object' ? link.target.id : String(link.target)\n\n    return {\n      ...link,\n      source: nodeMap.get(sourceId)!,\n      target: nodeMap.get(targetId)!,\n    }\n  })\n\n  filteredGraph.value = {\n    nodes: updatedNodes,\n    links: updatedLinks,\n  }\n}\n\nfunction resetGraphController(reset = false) {\n  controller.value?.shutdown()\n\n  // Force reload the module graph only when node_modules are shown.\n  // The module graph doesn't contain node_modules entries.\n  if (reset && !hideNodeModules.value) {\n    hideNodeModules.value = true\n    return\n  }\n\n  if (!filteredGraph.value || !el.value) {\n    return\n  }\n\n  const nodesLength = filteredGraph.value.nodes.length\n  let zoom = 1\n  let min = 0.5\n  if (nodesLength > 300) {\n    zoom = 0.3\n    min = 0.2\n  }\n  else if (nodesLength > 200) {\n    zoom = 0.4\n    min = 0.3\n  }\n  else if (nodesLength > 100) {\n    zoom = 0.5\n    min = 0.3\n  }\n  else if (nodesLength > 50) {\n    zoom = 0.7\n    zoom = 0.4\n  }\n\n  controller.value = new GraphController(\n    el.value!,\n    filteredGraph.value,\n    // See https://graph-controller.yeger.eu/config/ for more options\n    defineGraphConfig<ModuleType, ModuleNode, ModuleLink>({\n      nodeRadius: 10,\n      autoResize: true,\n      simulation: {\n        alphas: {\n          initialize: 1,\n          resize: ({ newHeight, newWidth }: ResizeContext) => {\n            const willBeHidden = newHeight === 0 && newWidth === 0\n            if (willBeHidden) {\n              return 0\n            }\n            return 0.05\n          },\n        },\n        forces: {\n          collision: {\n            radiusMultiplier: 10,\n          },\n          link: {\n            length: 140,\n          },\n        },\n      },\n      marker: Markers.Arrow(2),\n      modifiers: {\n        node: bindOnClick,\n      },\n      positionInitializer: graph.value.nodes.length === 1\n        ? PositionInitializers.Centered\n        : PositionInitializers.Randomized,\n      zoom: {\n        initial: zoom,\n        min,\n        max: 1.5,\n      },\n    }),\n  )\n}\n\nconst isValidClick = (event: PointerEvent) => event.button === 0\nconst isRightClick = (event: PointerEvent) => event.button === 2\n\nfunction bindOnClick(\n  selection: Selection<SVGCircleElement, ModuleNode, SVGGElement, undefined>,\n) {\n  if (isReport) {\n    return\n  }\n  // Handle both left-click (focus) and right-click (open modal)\n  let px = 0\n  let py = 0\n  let pt = 0\n  let isRightClickDown = false\n\n  selection\n    .on('pointerdown', (event: PointerEvent, node) => {\n      if (!node.x || !node.y) {\n        return\n      }\n\n      isRightClickDown = isRightClick(event)\n\n      if (!isValidClick(event) && !isRightClickDown) {\n        return\n      }\n\n      px = node.x\n      py = node.y\n      pt = Date.now()\n    })\n    .on('pointerup', (event: PointerEvent, node: ModuleNode) => {\n      if (!node.x || !node.y) {\n        return\n      }\n\n      const wasRightClick = isRightClick(event)\n\n      if (!isValidClick(event) && !wasRightClick) {\n        return\n      }\n\n      if (Date.now() - pt > 500) {\n        return\n      }\n\n      const dx = node.x - px\n      const dy = node.y - py\n      if (dx ** 2 + dy ** 2 < 100) {\n        // Left-click: show details (open modal)\n        if (!wasRightClick && !event.shiftKey) {\n          setSelectedModule(node.id, node.type)\n        }\n        // Right-click or Shift+Click: expand graph (focus on node)\n        else if (wasRightClick || event.shiftKey) {\n          event.preventDefault()\n          if (node.type === 'inline') {\n            focusOnNode(node.id)\n          }\n        }\n      }\n    })\n    .on('contextmenu', (event: PointerEvent) => {\n      // Prevent default context menu\n      event.preventDefault()\n    })\n}\n</script>\n\n<template>\n  <div h-full min-h-75 flex-1 overflow=\"hidden\">\n    <div>\n      <div flex items-center gap-2 px-3 py-2>\n        <div\n          flex=\"~ gap-1\"\n          items-center\n          select-none\n        >\n          <div class=\"pr-2\">\n            {{ filteredGraph.nodes.length }}/{{ graph.nodes.length }} {{ filteredGraph.nodes.length === 1 ? 'module' : 'modules' }}\n          </div>\n          <input\n            id=\"hide-node-modules\"\n            v-model=\"hideNodeModules\"\n            type=\"checkbox\"\n          >\n          <label\n            font-light\n            text-sm\n            ws-nowrap\n            overflow-hidden\n            select-none\n            truncate\n            for=\"hide-node-modules\"\n            border-b-2\n            border=\"$cm-namespace\"\n          >Hide node_modules</label>\n        </div>\n        <div\n          v-for=\"node of controller?.nodeTypes.sort()\"\n          :key=\"node\"\n          flex=\"~ gap-1\"\n          items-center\n          select-none\n        >\n          <input\n            :id=\"`type-${node}`\"\n            type=\"checkbox\"\n            :checked=\"controller?.nodeTypeFilter.includes(node)\"\n            @change=\"setFilter(node, ($event as any).target.checked)\"\n          >\n          <label\n            font-light\n            text-sm\n            ws-nowrap\n            overflow-hidden\n            capitalize\n            select-none\n            truncate\n            :for=\"`type-${node}`\"\n            border-b-2\n            :style=\"{ 'border-color': `var(--color-node-${node})` }\"\n          >{{ node }} Modules</label>\n        </div>\n        <div flex-auto />\n        <div\n          flex=\"~ gap-2\"\n          items-center\n          text-xs\n          opacity-60\n        >\n          <span>Click on node: details • Right-click/Shift: expand graph</span>\n        </div>\n        <div>\n          <IconButton\n            v-tooltip.bottom=\"`${breakdownShow ? 'Hide' : 'Show'} Import Breakdown`\"\n            icon=\"i-carbon-notebook\"\n            :class=\"breakdownIconClass\"\n            @click=\"toggleImportBreakdown()\"\n          />\n        </div>\n        <div>\n          <IconButton\n            v-tooltip.bottom=\"'Show Full Graph'\"\n            icon=\"i-carbon-ibm-cloud-direct-link-2-connect\"\n            @click=\"showFullGraph()\"\n          />\n        </div>\n        <div>\n          <IconButton\n            v-tooltip.bottom=\"'Reset'\"\n            icon=\"i-carbon-reset\"\n            @click=\"resetToRoot()\"\n          />\n        </div>\n      </div>\n    </div>\n    <div v-if=\"breakdownShow\" class=\"absolute bg-[#eee] dark:bg-[#222] border-base right-0 mr-2 rounded-xl mt-2\">\n      <ViewModuleGraphImportBreakdown @select=\"(id, type) => setSelectedModule(id, type)\" />\n    </div>\n    <div ref=\"el\" />\n    <Modal v-model=\"modalShow\" direction=\"right\">\n      <template v-if=\"selectedModule\">\n        <Suspense>\n          <ModuleTransformResultView\n            :id=\"selectedModule.id\"\n            :project-name=\"projectName\"\n            :type=\"selectedModule.type\"\n            :can-undo=\"selectedModuleHistory.undoStack.value.length > 1\"\n            @close=\"closeResultView()\"\n            @select=\"(id, type) => setSelectedModule(id, type)\"\n            @back=\"selectPreviousModule()\"\n          />\n        </Suspense>\n      </template>\n    </Modal>\n  </div>\n</template>\n\n<style>\n:root {\n  --color-link-label: var(--color-text);\n  --color-link: #ddd;\n  --color-node-external: #6C5C33;\n  --color-node-inline: #8bc4a0;\n  --color-node-root: #6e9aa5;\n  --color-node-focused: #e67e22;\n  --color-node-label: var(--color-text);\n  --color-node-stroke: var(--color-text);\n}\n\nhtml.dark {\n  --color-text: #fff;\n  --color-link: #333;\n  --color-node-external: #c0ad79;\n  --color-node-inline: #468b60;\n  --color-node-root: #467d8b;\n  --color-node-focused: #f39c12;\n}\n\n.graph {\n  /* The graph container is offset in its parent. Thus we can't use the default 100% height and have to subtract the offset. */\n  height: calc(100% - 39px) !important;\n}\n\n.graph .node {\n  stroke-width: 2px;\n  stroke-opacity: 0.5;\n}\n\n.graph .link {\n  stroke-width: 2px;\n}\n\n.graph .node:hover:not(.focused) {\n  filter: none !important;\n}\n\n.graph .node__label {\n  transform: translateY(20px);\n  font-weight: 100;\n  filter: brightness(0.5);\n}\n\nhtml.dark .graph .node__label {\n  filter: brightness(1.2);\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/views/ViewReport.spec.ts",
    "content": "import type { RunnerTestFile } from 'vitest'\nimport { faker } from '@faker-js/faker'\nimport { beforeEach, describe, expect, it } from 'vitest'\nimport { config } from '~/composables/client'\nimport { page, render } from '~/test'\nimport ViewReport from './ViewReport.vue'\n\nconfig.value.root = ''\n\nconst taskErrorTestId = 'task-error'\nconst viewReportTestId = 'view-report'\nconst stackRowTestId = 'stack'\n\nfunction makeTextStack() {\n  return {\n    line: faker.number.int({ min: 0, max: 120 }),\n    column: faker.number.int({ min: 0, max: 5000 }),\n    // Absolute file paths\n    file: faker.system.filePath(),\n    method: faker.hacker.verb(),\n  }\n}\n\n// 5 Stacks\nconst textStacks = Array.from({ length: 5 }, makeTextStack)\n\nconst diff = `\n  \\x1B[32m- Expected\\x1B[39m\n  \\x1B[31m+ Received\\x1B[39m\n\n  \\x1B[2m  Object {\\x1B[22m\n  \\x1B[2m    \"a\": 1,\\x1B[22m\n  \\x1B[32m-   \"b\": 2,\\x1B[39m\n  \\x1B[31m+   \"b\": 3,\\x1B[39m\n  \\x1B[2m  }\\x1B[22m\n`\n\nconst error = {\n  name: 'Do some test',\n  stacks: textStacks,\n  message: 'Error: Transform failed with 1 error:',\n  diff,\n}\n\nconst fileWithTextStacks: RunnerTestFile = {\n  id: 'f-1',\n  name: 'test/plain-stack-trace.ts',\n  type: 'suite',\n  mode: 'run',\n  filepath: 'test/plain-stack-trace.ts',\n  fullName: 'test/plain-stack-trace.ts',\n  meta: {},\n  result: {\n    state: 'fail',\n    errors: [error],\n  },\n  tasks: [],\n  projectName: '',\n  file: null!,\n}\nfileWithTextStacks.file = fileWithTextStacks\n\ndescribe('ViewReport', () => {\n  describe('RunnerTestFile where stacks are in text', () => {\n    beforeEach(() => {\n      render(ViewReport, {\n        props: {\n          file: fileWithTextStacks,\n        },\n        attrs: {\n          'data-testid': viewReportTestId,\n        },\n      })\n    })\n\n    it('renders all of the stacks', () => {\n      const stacks = error.stacks\n      const stacksElements = page.getByTestId(stackRowTestId)\n      expect(stacksElements).toHaveLength(stacks.length)\n\n      for (let idx = 0; idx < stacks.length; idx++) {\n        const { column, line, file: fileName } = stacks[idx]\n        expect(stacksElements.nth(idx)).toHaveTextContent(`${line}:${column}`)\n        expect(stacksElements.nth(idx)).toHaveTextContent(`- ${fileName}`)\n      }\n    })\n\n    it('renders the error message', () => {\n      const report = page.getByTestId(viewReportTestId)\n      expect(report).toHaveTextContent(error.message)\n      expect(report).toHaveTextContent(error.name)\n    })\n  })\n\n  it('test html stack trace without html message', () => {\n    const file: RunnerTestFile = {\n      id: 'f-1',\n      name: 'test/plain-stack-trace.ts',\n      type: 'suite',\n      mode: 'run',\n      filepath: 'test/plain-stack-trace.ts',\n      fullName: 'test/plain-stack-trace.ts',\n      meta: {},\n      result: {\n        state: 'fail',\n        errors: [\n          {\n            name: 'Do some test',\n            stacks: [],\n            stack: '\\x1B[33mtest/plain-stack-trace.ts\\x1B[0m',\n            message: 'Error: Transform failed with 1 error:',\n            diff,\n          },\n        ],\n      },\n      tasks: [],\n      projectName: '',\n      file: null!,\n    }\n    file.file = file\n    const container = render(ViewReport, {\n      props: { file },\n    })\n    const taskError = container.getByTestId(taskErrorTestId)\n    const preElements = taskError.element().querySelectorAll('pre')\n    expect(preElements).toHaveLength(1)\n\n    expect(preElements[0].textContent, 'error has the correct plain text').toBe(\n      'Do some test: Error: Transform failed with 1 error:test/plain-stack-trace.ts',\n    )\n    expect(\n      preElements[0].children,\n      'the pre container has the correct children',\n    ).toHaveLength(2)\n\n    const [bold, stack] = preElements[0].children\n    expect(bold.tagName, 'error contains <b> element').toBe('B')\n    expect(bold.textContent, 'the <b> error element is correct').toBe(\n      'Do some test',\n    )\n\n    expect(\n      stack.children,\n      'the stack children elements is correct',\n    ).toHaveLength(0)\n    expect(stack.innerHTML, 'stack has the correct message').toBe(\n      'test/plain-stack-trace.ts',\n    )\n    expect(\n      stack.getAttribute('style'),\n      'the stack has the correct text color',\n    ).toBe('color:#A50')\n  })\n\n  it('test html stack trace and message', () => {\n    const file: RunnerTestFile = {\n      id: 'f-1',\n      name: 'test/plain-stack-trace.ts',\n      type: 'suite',\n      mode: 'run',\n      filepath: 'test/plain-stack-trace.ts',\n      fullName: 'test/plain-stack-trace.ts',\n      meta: {},\n      result: {\n        state: 'fail',\n        errors: [\n          {\n            name: 'Do some test',\n            stack: '\\x1B[33mtest/plain-stack-trace.ts\\x1B[0m',\n            stacks: [],\n            message: '\\x1B[44mError: Transform failed with 1 error:\\x1B[0m',\n            diff,\n          },\n        ],\n      },\n      tasks: [],\n      projectName: '',\n      file: null!,\n    }\n    file.file = file\n    const container = render(ViewReport, {\n      props: { file },\n    })\n    const taskError = container.getByTestId(taskErrorTestId)\n    const preElements = taskError.element().querySelectorAll('pre')\n    expect(preElements).toHaveLength(1)\n\n    expect(preElements[0].textContent, 'error has the correct plain text').toBe(\n      'Do some test: Error: Transform failed with 1 error:test/plain-stack-trace.ts',\n    )\n    expect(\n      preElements[0].children,\n      'the pre container has the correct children',\n    ).toHaveLength(3)\n\n    const [bold, error, stack] = preElements[0].children\n    expect(bold.tagName, 'error contains <b> element').toBe('B')\n    expect(bold.textContent, 'the <b> error element is correct').toBe(\n      'Do some test',\n    )\n\n    expect(error.innerHTML, 'the error has the correct message').toBe(\n      'Error: Transform failed with 1 error:',\n    )\n    expect(\n      error.getAttribute('style'),\n      'the error has the correct background color',\n    ).toBe('background-color:#00A')\n\n    expect(\n      stack.children,\n      'the stack children elements is correct',\n    ).toHaveLength(0)\n    expect(stack.innerHTML, 'stack has the correct message').toBe(\n      'test/plain-stack-trace.ts',\n    )\n    expect(\n      stack.getAttribute('style'),\n      'the stack has the correct text color',\n    ).toBe('color:#A50')\n  })\n\n  it('test diff display', () => {\n    const component = render(ViewReport, {\n      props: {\n        file: fileWithTextStacks,\n      },\n    })\n\n    const diffElement = component.getByTestId('diff')\n\n    expect(diffElement.getByText(/Expected/)).toBeInTheDocument()\n    expect(diffElement.getByText(/Received/)).toBeInTheDocument()\n    expect(diffElement.getByText(/\\\\x1B/)).not.toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/ui/client/components/views/ViewReport.vue",
    "content": "<script setup lang=\"ts\">\nimport type { RunnerTask, RunnerTestFile, RunnerTestSuite } from 'vitest'\nimport { computed } from 'vue'\nimport { config } from '~/composables/client'\nimport { isDark } from '~/composables/dark'\nimport { mapLeveledTaskStacks } from '~/composables/error'\nimport FailureScreenshot from '../FailureScreenshot.vue'\nimport ViewReportError from './ViewReportError.vue'\n\nconst props = defineProps<{\n  file: RunnerTestFile\n}>()\n\ntype LeveledTask = RunnerTask & {\n  level: number\n}\n\nfunction collectFailed(task: RunnerTask, level: number): LeveledTask[] {\n  if (task.result?.state !== 'fail') {\n    return []\n  }\n\n  if (task.type === 'test') {\n    return [{ ...task, level }]\n  }\n  else {\n    return [\n      { ...task, level },\n      ...task.tasks.flatMap(t => collectFailed(t, level + 1)),\n    ]\n  }\n}\n\nconst failed = computed(() => {\n  const file = props.file\n  const failedFlatMap = file.tasks?.flatMap(t => collectFailed(t, 0)) ?? []\n  const result = file.result\n  const fileError = result?.errors?.[0]\n  // we must check also if the test cannot compile\n  if (fileError) {\n    // create a dummy one\n    const fileErrorTask: RunnerTestSuite & { level: number } = {\n      id: file!.id,\n      file: file!,\n      name: file!.name,\n      fullName: file!.name,\n      level: 0,\n      type: 'suite',\n      mode: 'run',\n      meta: {},\n      tasks: [],\n      result,\n    }\n    failedFlatMap.unshift(fileErrorTask)\n  }\n  return failedFlatMap.length > 0\n    ? mapLeveledTaskStacks(isDark.value, failedFlatMap)\n    : failedFlatMap\n})\n</script>\n\n<template>\n  <div h-full class=\"scrolls\">\n    <template v-if=\"failed.length\">\n      <div v-for=\"task of failed\" :id=\"task.id\" :key=\"task.id\">\n        <div\n          bg=\"red-500/10\"\n          text=\"red-500 sm\"\n          p=\"x3 y2\"\n          m-2\n          rounded\n          :style=\"{\n            'margin-left': `${\n              task.result?.htmlError ? 0.5 : 2 * (task as LeveledTask).level + 0.5\n            }rem`,\n          }\"\n        >\n          <div flex=\"~ gap-2 items-center\">\n            <span>{{ task.name }}</span>\n            <FailureScreenshot :task=\"task\" />\n          </div>\n          <div\n            v-if=\"task.result?.htmlError\"\n            class=\"scrolls scrolls-rounded task-error\"\n            data-testid=\"task-error\"\n          >\n            <pre v-html=\"task.result.htmlError\" />\n          </div>\n          <template v-else-if=\"task.result?.errors && config.root\">\n            <ViewReportError\n              v-for=\"(error, idx) of task.result.errors\"\n              :key=\"idx\"\n              :error=\"error\"\n              :filename=\"file.name\"\n              :root=\"config.root\"\n              :file-id=\"file.id\"\n            />\n          </template>\n        </div>\n      </div>\n    </template>\n    <template v-else>\n      <div bg=\"green-500/10\" text=\"green-500 sm\" p=\"x4 y2\" m-2 rounded>\n        All tests passed in this file\n      </div>\n    </template>\n  </div>\n</template>\n\n<style scoped>\n.task-error {\n  --cm-ttc-c-thumb: #ccc;\n}\nhtml.dark .task-error {\n  --cm-ttc-c-thumb: #444;\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/views/ViewReportError.vue",
    "content": "<script setup lang=\"ts\">\nimport type { ParsedStack, TestError } from 'vitest'\nimport { computed } from 'vue'\nimport { showLocationSource } from '~/composables/codemirror'\nimport { isDark } from '~/composables/dark'\nimport { createAnsiToHtmlFilter, isTestFile, openInEditor } from '~/composables/error'\nimport { escapeHtml } from '~/utils/escape'\n\nconst props = defineProps<{\n  fileId: string\n  root: string\n  filename?: string\n  error: TestError\n}>()\n\nfunction relative(p: string) {\n  if (p.startsWith(props.root)) {\n    return p.slice(props.root.length)\n  }\n  return p\n}\n\nconst filter = computed(() => createAnsiToHtmlFilter(isDark.value))\n\nconst isDiffShowable = computed(() => {\n  return !!props.error?.diff\n})\n\nconst diff = computed(() =>\n  props.error.diff\n    ? filter.value.toHtml(escapeHtml(props.error.diff))\n    : undefined,\n)\n\nfunction showCode(stack: ParsedStack) {\n  if (isTestFile(stack.file, props.filename)) {\n    return showLocationSource(props.fileId, stack)\n  }\n  return openInEditor(stack.file, stack.line, stack.column)\n}\n</script>\n\n<template>\n  <div class=\"scrolls scrolls-rounded task-error\">\n    <pre><b>{{ error.name }}</b>: {{ error.message }}</pre>\n    <div\n      v-for=\"(stack, i) of error.stacks\"\n      :key=\"i\"\n      class=\"op80 flex gap-x-2 items-center\"\n      data-testid=\"stack\"\n    >\n      <pre>\n - {{ relative(stack.file) }}:{{ stack.line }}:{{ stack.column }}</pre>\n      <div\n        v-tooltip.bottom=\"'Open in Editor'\"\n        class=\"i-carbon-launch c-red-700 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em\"\n        tabindex=\"0\"\n        aria-label=\"Open in Editor\"\n        @click.passive=\"showCode(stack)\"\n      />\n    </div>\n    <template v-if=\"isDiffShowable\">\n      <pre data-testid=\"diff\" v-html=\"diff\" />\n    </template>\n  </div>\n</template>\n\n<style scoped>\n.task-error {\n  --cm-ttc-c-thumb: #ccc;\n}\nhtml.dark .task-error {\n  --cm-ttc-c-thumb: #444;\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/components/views/ViewTestReport.vue",
    "content": "<script setup lang=\"ts\">\nimport type { RunnerTestCase } from 'vitest'\nimport { computed } from 'vue'\nimport { getAttachmentUrl, sanitizeFilePath } from '~/composables/attachments'\nimport { config } from '~/composables/client'\nimport { isDark } from '~/composables/dark'\nimport { mapLeveledTaskStacks } from '~/composables/error'\nimport { getLocationString, openLocation } from '~/composables/location'\nimport AnnotationAttachmentImage from '../AnnotationAttachmentImage.vue'\nimport Artifacts from '../artifacts/Artifacts.vue'\nimport FailureScreenshot from '../FailureScreenshot.vue'\nimport ViewReportError from './ViewReportError.vue'\n\nconst props = defineProps<{\n  test: RunnerTestCase\n}>()\n\nconst failed = computed(() => {\n  if (!props.test.result || !props.test.result.errors?.length) {\n    return null\n  }\n  return mapLeveledTaskStacks(isDark.value, [props.test])[0] as RunnerTestCase | null\n})\n\nconst kWellKnownMeta = new Set([\n  'benchmark',\n  'typecheck',\n])\nconst meta = computed(() => {\n  return Object.entries(props.test.meta).filter(([name]) => {\n    return !kWellKnownMeta.has(name)\n  })\n})\n</script>\n\n<template>\n  <div h-full class=\"scrolls\">\n    <div v-if=\"failed\">\n      <div\n        bg=\"red-500/10\"\n        text=\"red-500 sm\"\n        p=\"x3 y2\"\n        m-2\n        rounded\n      >\n        <FailureScreenshot :task=\"test\" />\n        <div\n          v-if=\"test.result?.htmlError\"\n          class=\"scrolls scrolls-rounded task-error\"\n          data-testid=\"task-error\"\n        >\n          <pre v-html=\"test.result.htmlError\" />\n        </div>\n        <template v-else-if=\"test.result?.errors && config.root\">\n          <ViewReportError\n            v-for=\"(error, idx) of test.result.errors\"\n            :key=\"idx\"\n            :file-id=\"test.file.id\"\n            :error=\"error\"\n            :filename=\"test.file.name\"\n            :root=\"config.root\"\n          />\n        </template>\n      </div>\n    </div>\n    <template v-else>\n      <div bg=\"green-500/10\" text=\"green-500 sm\" p=\"x4 y2\" m-2 rounded>\n        The test has passed without any errors\n      </div>\n    </template>\n    <template v-if=\"test.annotations.length\">\n      <h1 m-2>\n        Test Annotations\n      </h1>\n      <div\n        v-for=\"annotation of test.annotations\"\n        :key=\"annotation.type + annotation.message\"\n        bg=\"yellow-500/10\"\n        text=\"yellow-500 sm\"\n        p=\"x3 y2\"\n        m-2\n        rounded\n        role=\"note\"\n      >\n        <div flex=\"~ gap-2 items-center justify-between\" overflow-hidden>\n          <div class=\"flex gap-2\" overflow-hidden>\n            <span class=\"font-bold\" ws-nowrap truncate>{{ annotation.type }}</span>\n            <a\n              v-if=\"annotation.attachment && !annotation.attachment.contentType?.startsWith('image/')\"\n              class=\"flex gap-1 items-center text-yellow-500/80 cursor-pointer\"\n              :href=\"getAttachmentUrl(annotation.attachment)\"\n              :download=\"sanitizeFilePath(annotation.message, annotation.attachment.contentType)\"\n            >\n              <span class=\"i-carbon:download block\" />\n              Download\n            </a>\n          </div>\n          <div>\n            <span\n              v-if=\"annotation.location && annotation.location.file === test.file.filepath\"\n              v-tooltip.bottom=\"'Open in Editor'\"\n              title=\"Open in Editor\"\n              class=\"flex gap-1 text-yellow-500/80 cursor-pointer\"\n              ws-nowrap\n              @click=\"openLocation(test, annotation.location)\"\n            >\n              {{ getLocationString(annotation.location) }}\n            </span>\n            <span\n              v-else-if=\"annotation.location && annotation.location.file !== test.file.filepath\"\n              class=\"flex gap-1 text-yellow-500/80\"\n              ws-nowrap\n            >\n              {{ getLocationString(annotation.location) }}\n            </span>\n          </div>\n        </div>\n\n        <div\n          class=\"scrolls scrolls-rounded task-error\"\n          data-testid=\"task-error\"\n        >\n          {{ annotation.message }}\n        </div>\n\n        <AnnotationAttachmentImage :annotation=\"annotation\" />\n      </div>\n    </template>\n    <Artifacts :test=\"test\" />\n    <template v-if=\"meta.length\">\n      <h1 m-2>\n        Test Meta\n      </h1>\n      <div\n        bg=\"gray/10\"\n        text=\"black-100 sm\"\n        p=\"x3 y2\"\n        m-2\n        rounded\n        class=\"grid grid-cols-1 md:grid-cols-[200px_1fr] gap-2\"\n        overflow-hidden\n      >\n        <template v-for=\"([name, content]) of meta\" :key=\"name\">\n          <div font-bold ws-nowrap truncate py-2>\n            {{ name }}\n          </div>\n          <pre overflow-auto bg=\"gray/30\" rounded p-2>{{ content }}</pre>\n        </template>\n      </div>\n    </template>\n  </div>\n</template>\n\n<style scoped>\n.task-error {\n  --cm-ttc-c-thumb: #ccc;\n}\nhtml.dark .task-error {\n  --cm-ttc-c-thumb: #444;\n}\n</style>\n"
  },
  {
    "path": "packages/ui/client/composables/api.ts",
    "content": "import type { BrowserUI } from 'vitest'\nimport { viewport } from './browser'\nimport { browserState, findById } from './client'\nimport { currentModule, showDashboard, updateBrowserPanel } from './navigation'\nimport { activeFileId } from './params'\n\nexport const ui: BrowserUI = {\n  setCurrentFileId(fileId: string) {\n    activeFileId.value = fileId\n    currentModule.value = findById(fileId)\n    showDashboard(false)\n  },\n  async setIframeViewport(width: number, height: number) {\n    // reset the button before setting a custom viewport\n    viewport.value = [width, height]\n    if (browserState?.provider === 'webdriverio') {\n      updateBrowserPanel()\n    }\n    await new Promise(r => requestAnimationFrame(r))\n  },\n}\n"
  },
  {
    "path": "packages/ui/client/composables/attachments.ts",
    "content": "import type { TestAttachment } from '@vitest/runner'\nimport mime from 'mime/lite'\nimport { basename } from 'pathe'\nimport { isReport } from '~/constants'\n\nexport function getAttachmentUrl(attachment: TestAttachment): string {\n  const contentType = attachment.contentType ?? 'application/octet-stream'\n  if (attachment.path) {\n    if (isReport) {\n      // html reporter copies attachments to /data/ folder\n      return `./data/${basename(attachment.path)}`\n    }\n    return `/__vitest_attachment__?path=${encodeURIComponent(attachment.path)}&contentType=${contentType}&token=${(window as any).VITEST_API_TOKEN}`\n  }\n  // attachment.body is always a string outside of the test frame\n  return `data:${contentType};base64,${attachment.body}`\n}\n\nexport function sanitizeFilePath(s: string, contentType: string | undefined): string {\n  const extension = contentType ? mime.getExtension(contentType) : null\n  // eslint-disable-next-line no-control-regex\n  return s.replace(/[\\x00-\\x2C\\x2E\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7F]+/g, '-') + (extension ? `.${extension}` : '')\n}\n\nexport function isExternalAttachment(attachment: TestAttachment): boolean {\n  const potentialUrl = attachment.path || attachment.body\n  return typeof potentialUrl === 'string' && (potentialUrl.startsWith('http://') || potentialUrl.startsWith('https://'))\n}\n\nexport function internalOrExternalUrl(attachment: TestAttachment): string {\n  const potentialUrl = attachment.path || attachment.body\n\n  if (typeof potentialUrl === 'string' && (potentialUrl.startsWith('http://') || potentialUrl.startsWith('https://'))) {\n    return potentialUrl\n  }\n\n  return getAttachmentUrl(attachment)\n}\n"
  },
  {
    "path": "packages/ui/client/composables/browser.ts",
    "content": "import { ref } from 'vue'\n\nexport type ViewportSize\n  = | 'small-mobile'\n    | 'large-mobile'\n    | 'tablet'\nexport const viewport = ref<[number, number]>([414, 896])\n"
  },
  {
    "path": "packages/ui/client/composables/client/index.ts",
    "content": "import type { WebSocketStatus } from '@vueuse/core'\nimport type {\n  RunnerTask,\n  RunnerTaskEventPack,\n  RunnerTaskResultPack,\n  RunnerTestFile,\n  SerializedConfig,\n  TestAnnotation,\n} from 'vitest'\nimport type { BrowserRunnerState } from '../../../types'\nimport { createFileTask } from '@vitest/runner/utils'\nimport { createClient, getTasks } from '@vitest/ws-client'\nimport { computed, reactive as reactiveVue, ref, shallowRef, watch } from 'vue'\nimport { explorerTree } from '~/composables/explorer'\nimport { isFileNode } from '~/composables/explorer/utils'\nimport { isSuite as isTaskSuite } from '~/utils/task'\nimport { ui } from '../../composables/api'\nimport { ENTRY_URL, isReport } from '../../constants'\nimport { parseError } from '../error'\nimport { activeFileId } from '../params'\nimport { testRunState, unhandledErrors } from './state'\nimport { createStaticClient } from './static'\n\nexport { ENTRY_URL, HOST, isReport, PORT } from '../../constants'\n\nexport const client = (function createVitestClient() {\n  if (isReport) {\n    return createStaticClient()\n  }\n  else {\n    return createClient(ENTRY_URL, {\n      reactive: (data, ctxKey) => {\n        return ctxKey === 'state' ? reactiveVue(data as any) as any : shallowRef(data)\n      },\n      handlers: {\n        onTestAnnotate(testId: string, annotation: TestAnnotation) {\n          explorerTree.recordTestArtifact(testId, { type: 'internal:annotation', annotation, location: annotation.location })\n        },\n        onTestArtifactRecord(testId, artifact) {\n          explorerTree.recordTestArtifact(testId, artifact)\n        },\n        onTaskUpdate(packs: RunnerTaskResultPack[], events: RunnerTaskEventPack[]) {\n          explorerTree.resumeRun(packs, events)\n          testRunState.value = 'running'\n        },\n        onSpecsCollected(_specs, startTime) {\n          explorerTree.startTime = startTime || performance.now()\n        },\n        onFinished(_files, errors, _coverage, executionTime) {\n          explorerTree.endRun(executionTime)\n          // don't change the testRunState.value here:\n          // - when saving the file in the codemirror requires explorer tree endRun to finish (multiple microtasks)\n          // - if we change here the state before the tasks states are updated, the cursor position will be lost\n          // - line moved to composables/explorer/collector.ts::refreshExplorer after calling updateRunningTodoTests\n          // testRunState.value = 'idle'\n          unhandledErrors.value = (errors || []).map(parseError)\n        },\n        onFinishedReportCoverage() {\n          // reload coverage iframe\n          const iframe = document.querySelector('iframe#vitest-ui-coverage')\n          if (iframe instanceof HTMLIFrameElement && iframe.contentWindow) {\n            iframe.contentWindow.location.reload()\n          }\n        },\n      },\n    })\n  }\n})()\n\nexport const config = shallowRef<Partial<SerializedConfig>>({} as any)\nexport const status = ref<WebSocketStatus>('CONNECTING')\nexport const availableProjects = shallowRef<string[]>([])\n\nexport const current = computed(() => {\n  const currentFileId = activeFileId.value\n  return currentFileId ? findById(currentFileId) : undefined\n})\nexport const currentLogs = computed(() => getTasks(current.value).map(i => i?.logs || []).flat() || [])\n\nexport function findById(id: string) {\n  const file = client.state.idMap.get(id)\n  return file ? file as RunnerTestFile : undefined\n}\n\nexport const isConnected = computed(() => status.value === 'OPEN')\nexport const isConnecting = computed(() => status.value === 'CONNECTING')\nexport const isDisconnected = computed(() => status.value === 'CLOSED')\n\nexport function runAll() {\n  return runFiles(client.state.getFiles())\n}\n\nfunction clearTaskResult(task: RunnerTask) {\n  delete task.result\n  const node = explorerTree.nodes.get(task.id)\n  if (node) {\n    node.state = undefined\n    // update task mode to allow change icon on skipped tests\n    task.mode = 'run'\n    node.duration = undefined\n    if (isTaskSuite(task)) {\n      for (const t of task.tasks) {\n        clearTaskResult(t)\n      }\n    }\n  }\n}\n\nfunction clearResults(useFiles: RunnerTestFile[]) {\n  const map = explorerTree.nodes\n  useFiles.forEach((f) => {\n    delete f.result\n    getTasks(f).forEach((i) => {\n      delete i.result\n      if (map.has(i.id)) {\n        const task = map.get(i.id)\n        if (task) {\n          task.state = undefined\n          task.mode = 'run'\n          task.duration = undefined\n        }\n      }\n    })\n    const file = map.get(f.id)\n    if (file) {\n      file.state = undefined\n      file.mode = 'run'\n      file.duration = undefined\n      if (isFileNode(file)) {\n        file.collectDuration = undefined\n      }\n    }\n  })\n}\n\nexport function runFiles(useFiles: RunnerTestFile[]) {\n  clearResults(useFiles)\n\n  explorerTree.startRun()\n\n  return client.rpc.rerun(useFiles.map(i => i.filepath), true)\n}\n\nexport function runTask(task: RunnerTask) {\n  clearTaskResult(task)\n\n  explorerTree.startRun()\n\n  return client.rpc.rerunTask(task.id)\n}\n\nexport function runCurrent() {\n  if (current.value) {\n    return runFiles([current.value])\n  }\n}\n\n// @ts-expect-error not typed global\nexport const browserState = window.__vitest_browser_runner__ as\n  | BrowserRunnerState\n  | undefined\n\n// @ts-expect-error not typed global\nwindow.__vitest_ui_api__ = ui\n\nwatch(\n  () => client.ws,\n  (ws) => {\n    status.value = isReport ? 'OPEN' : 'CONNECTING'\n\n    ws.addEventListener('open', async () => {\n      status.value = 'OPEN'\n      client.state.filesMap.clear()\n      let [files, _config, errors, projects] = await Promise.all([\n        client.rpc.getFiles(),\n        client.rpc.getConfig(),\n        client.rpc.getUnhandledErrors(),\n        client.rpc.getResolvedProjectLabels(),\n      ])\n      if (_config.standalone) {\n        const filenames = await client.rpc.getTestFiles()\n        files = filenames.map(([{ name, root }, filepath]) => {\n          const file = createFileTask(filepath, root, name)\n          file.mode = 'skip'\n          return file\n        })\n      }\n      availableProjects.value = projects.map(p => p.name)\n      explorerTree.loadFiles(files, projects)\n      client.state.collectFiles(files)\n      explorerTree.startRun()\n      unhandledErrors.value = (errors || []).map(parseError)\n      config.value = _config\n    })\n\n    ws.addEventListener('close', () => {\n      setTimeout(() => {\n        if (status.value === 'CONNECTING') {\n          status.value = 'CLOSED'\n        }\n      }, 1000)\n    })\n  },\n  { immediate: true },\n)\n\n// display the first file on init\n// if (!activeFileId.value) {\n//   const stop = watch(\n//     () => client.state.getFiles(),\n//     (files) => {\n//       if (activeFileId.value) {\n//         stop()\n//         return\n//       }\n//\n//       if (files.length && files[0].id) {\n//         activeFileId.value = files[0].id\n//         stop()\n//       }\n//     },\n//     { immediate: true },\n//   )\n// }\n"
  },
  {
    "path": "packages/ui/client/composables/client/state.ts",
    "content": "import type { TestTagDefinition } from '@vitest/runner'\nimport type { TestError } from '@vitest/utils'\nimport type { Ref } from 'vue'\nimport type { RunState } from '../../../types'\nimport { computed, ref } from 'vue'\nimport { config } from '.'\n\nexport const testRunState: Ref<RunState> = ref('idle')\nexport const finished = computed(() => testRunState.value === 'idle')\nexport const unhandledErrors: Ref<TestError[]> = ref([])\nexport const tagsDefinitions = computed(() => {\n  const tags = config.value.tags || []\n  return tags.reduce((acc, tag) => {\n    acc[tag.name] = tag\n    return acc\n  }, {} as Record<string, TestTagDefinition>)\n})\n"
  },
  {
    "path": "packages/ui/client/composables/client/static.ts",
    "content": "import type { VitestClient } from '@vitest/ws-client'\nimport type { BirpcReturn } from 'birpc'\nimport type {\n  ModuleGraphData,\n  RunnerTestFile,\n  SerializedConfig,\n  WebSocketEvents,\n  WebSocketHandlers,\n} from 'vitest'\nimport { decompressSync, strFromU8 } from 'fflate'\nimport { parse } from 'flatted'\nimport { reactive } from 'vue'\nimport { StateManager } from '../../../../ws-client/src/state'\n\ninterface HTMLReportMetadata {\n  paths: string[]\n  files: RunnerTestFile[]\n  config: SerializedConfig\n  projects: string[]\n  moduleGraph: Record<string, Record<string, ModuleGraphData>>\n  unhandledErrors: unknown[]\n  // filename -> source\n  sources: Record<string, string>\n}\n\nconst noop: any = () => {}\nconst asyncNoop: any = () => Promise.resolve()\n\nexport function createStaticClient(): VitestClient {\n  const ctx = reactive({\n    state: new StateManager(),\n    waitForConnection,\n    reconnect,\n    ws: new EventTarget(),\n  }) as VitestClient\n\n  ctx.state.filesMap = reactive(ctx.state.filesMap)\n  ctx.state.idMap = reactive(ctx.state.idMap)\n\n  let metadata!: HTMLReportMetadata\n\n  const rpc = {\n    getFiles: () => {\n      return metadata.files\n    },\n    getPaths: () => {\n      return metadata.paths\n    },\n    getConfig: () => {\n      return metadata.config\n    },\n    getResolvedProjectNames: () => {\n      return metadata.projects\n    },\n    getResolvedProjectLabels: () => {\n      return []\n    },\n    getModuleGraph: async (projectName, id) => {\n      return metadata.moduleGraph[projectName]?.[id]\n    },\n    getUnhandledErrors: () => {\n      return metadata.unhandledErrors\n    },\n    getExternalResult: asyncNoop,\n    getTransformResult: asyncNoop,\n    onDone: noop,\n    writeFile: asyncNoop,\n    rerun: asyncNoop,\n    rerunTask: asyncNoop,\n    updateSnapshot: asyncNoop,\n    resolveSnapshotPath: asyncNoop,\n    snapshotSaved: asyncNoop,\n    onAfterSuiteRun: asyncNoop,\n    onCancel: asyncNoop,\n    getCountOfFailedTests: () => 0,\n    sendLog: asyncNoop,\n    resolveSnapshotRawPath: asyncNoop,\n    readSnapshotFile: asyncNoop,\n    saveSnapshotFile: asyncNoop,\n    readTestFile: async (id: string) => {\n      return metadata.sources[id]\n    },\n    removeSnapshotFile: asyncNoop,\n    onUnhandledError: noop,\n    saveTestFile: asyncNoop,\n    getProvidedContext: () => ({}),\n    getTestFiles: asyncNoop,\n  } as WebSocketHandlers\n\n  ctx.rpc = rpc as any as BirpcReturn<WebSocketHandlers, WebSocketEvents>\n\n  const openPromise = Promise.resolve()\n\n  function reconnect() {\n    registerMetadata()\n  }\n\n  async function registerMetadata() {\n    const res = await fetch(window.METADATA_PATH!)\n    const content = new Uint8Array(await res.arrayBuffer())\n\n    // Check for gzip magic numbers (0x1f 0x8b) to determine if content is compressed.\n    // This handles cases where a static server incorrectly sets Content-Encoding: gzip\n    // for .gz files, causing the browser to auto-decompress before we process the raw gzip data.\n    if (content.length >= 2 && content[0] === 0x1F && content[1] === 0x8B) {\n      const decompressed = strFromU8(decompressSync(content))\n      metadata = parse(decompressed) as HTMLReportMetadata\n    }\n    else {\n      metadata = parse(strFromU8(content)) as HTMLReportMetadata\n    }\n    const event = new Event('open')\n    ctx.ws.dispatchEvent(event)\n  }\n\n  registerMetadata()\n\n  function waitForConnection() {\n    return openPromise\n  }\n\n  return ctx\n}\n"
  },
  {
    "path": "packages/ui/client/composables/codemirror.ts",
    "content": "import type { Task, TestArtifactLocation } from '@vitest/runner'\nimport type { RunnerTestCase } from 'vitest'\nimport type { Ref, WritableComputedRef } from 'vue'\nimport CodeMirror from 'codemirror'\n\nimport { markRaw, onUnmounted, shallowRef, watch } from 'vue'\n\nimport { navigateTo } from '~/composables/navigation'\nimport { openInEditor } from './error'\nimport { selectedTest } from './params'\nimport 'codemirror/mode/javascript/javascript'\n// import 'codemirror/mode/css/css'\nimport 'codemirror/mode/xml/xml'\nimport 'codemirror/mode/htmlmixed/htmlmixed'\nimport 'codemirror/mode/jsx/jsx'\nimport 'codemirror/addon/display/placeholder'\nimport 'codemirror/addon/scroll/simplescrollbars'\nimport 'codemirror/addon/scroll/simplescrollbars.css'\n\nexport const codemirrorRef = shallowRef<CodeMirror.EditorFromTextArea>()\n\nexport function useCodeMirror(\n  textarea: Ref<HTMLTextAreaElement | null | undefined>,\n  input: Ref<string> | WritableComputedRef<string>,\n  options: CodeMirror.EditorConfiguration = {},\n) {\n  const cm = CodeMirror.fromTextArea(textarea.value!, {\n    theme: 'vars',\n    ...options,\n    scrollbarStyle: 'simple',\n  })\n\n  let skip = false\n\n  cm.on('change', () => {\n    if (skip) {\n      skip = false\n      return\n    }\n    input.value = cm.getValue()\n  })\n\n  watch(\n    input,\n    (v) => {\n      if (v !== cm.getValue()) {\n        skip = true\n        const selections = cm.listSelections()\n        cm.replaceRange(\n          v,\n          cm.posFromIndex(0),\n          cm.posFromIndex(Number.POSITIVE_INFINITY),\n        )\n        cm.setSelections(selections)\n      }\n    },\n    { immediate: true },\n  )\n\n  onUnmounted(() => {\n    codemirrorRef.value = undefined\n  })\n\n  return markRaw(cm)\n}\n\nexport async function showTaskSource(task: Task) {\n  navigateTo({\n    file: task.file.id,\n    line: task.location?.line ?? 1,\n    view: 'editor',\n    test: task.id,\n    column: null,\n  })\n}\n\nexport function showLocationSource(fileId: string, location: { line: number; column: number }) {\n  navigateTo({\n    file: fileId,\n    column: location.column - 1,\n    line: location.line,\n    view: 'editor',\n    test: selectedTest.value,\n  })\n}\n\nexport function showAttachmentSource(task: RunnerTestCase, location?: TestArtifactLocation) {\n  if (!location) {\n    return\n  }\n  const { line, column, file } = location\n  if (task.file.filepath !== file) {\n    return openInEditor(file, line, column)\n  }\n  navigateTo({\n    file: task.file.id,\n    column: column - 1,\n    line,\n    view: 'editor',\n    test: selectedTest.value,\n  })\n}\n"
  },
  {
    "path": "packages/ui/client/composables/dark.ts",
    "content": "import { useDark, useToggle } from '@vueuse/core'\n\nexport const isDark = useDark()\nexport const toggleDark = useToggle(isDark)\n"
  },
  {
    "path": "packages/ui/client/composables/error.ts",
    "content": "import type Convert from 'ansi-to-html'\nimport type { RunnerTask, TestError } from 'vitest'\nimport { parseStacktrace } from '@vitest/utils/source-map'\nimport Filter from 'ansi-to-html'\nimport { escapeHtml } from '~/utils/escape'\n\ndeclare module '@vitest/runner' {\n  interface TaskResult {\n    htmlError?: string\n  }\n}\n\nexport function isTestFile(name: string, fileName?: string) {\n  return fileName && name.endsWith(fileName)\n}\n\nexport async function openInEditor(name: string, line: number, column: number) {\n  const url = encodeURI(`${name}:${line}:${column}`)\n  await fetch(`/__open-in-editor?file=${url}`)\n}\n\nexport function createAnsiToHtmlFilter(dark: boolean) {\n  return new Filter({\n    fg: dark ? '#FFF' : '#000',\n    bg: dark ? '#000' : '#FFF',\n  })\n}\n\nfunction isPrimitive(value: unknown) {\n  return (\n    value === null || (typeof value !== 'function' && typeof value !== 'object')\n  )\n}\n\nexport function parseError(e: unknown) {\n  let error = e as TestError\n\n  if (isPrimitive(e)) {\n    error = {\n      message: String(error).split(/\\n/g)[0],\n      stack: String(error),\n      name: '',\n      stacks: [],\n    }\n  }\n\n  if (!e) {\n    const err = new Error('unknown error')\n    error = {\n      message: err.message,\n      stack: err.stack,\n      name: '',\n      stacks: [],\n    }\n  }\n\n  error.stacks = parseStacktrace(error.stack || '', {\n    ignoreStackEntries: [],\n  })\n\n  return error\n}\n\nfunction createHtmlError(filter: Convert, error: TestError) {\n  let htmlError = ''\n  if (error.message?.includes('\\x1B')) {\n    htmlError = `<b>${error.name}</b>: ${filter.toHtml(\n      escapeHtml(error.message),\n    )}`\n  }\n\n  const startStrWithX1B = error.stack?.includes('\\x1B')\n  if (startStrWithX1B) {\n    if (htmlError.length > 0) {\n      htmlError += filter.toHtml(\n        escapeHtml((error.stack) as string),\n      )\n    }\n    else {\n      htmlError = `<b>${error.name}</b>: ${\n        error.message\n      }${filter.toHtml(\n        escapeHtml((error.stack) as string),\n      )}`\n    }\n  }\n\n  if (htmlError.length > 0) {\n    return htmlError\n  }\n  return null\n}\n\nexport function mapLeveledTaskStacks(dark: boolean, tasks: RunnerTask[]) {\n  const filter = createAnsiToHtmlFilter(dark)\n  return tasks.map((t) => {\n    const result = t.result\n    if (!result || result.htmlError) {\n      return t\n    }\n    const errors = result.errors\n      ?.map(error => createHtmlError(filter, error))\n      .filter(error => error != null)\n      .join('<br><br>')\n    if (errors?.length) {\n      result.htmlError = errors\n    }\n    return t\n  })\n}\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/collapse.ts",
    "content": "import type { UITaskTreeNode } from '~/composables/explorer/types'\nimport { explorerTree } from '~/composables/explorer/index'\nimport { openedTreeItems, treeFilter, uiEntries } from '~/composables/explorer/state'\nimport { isFileNode, isParentNode } from '~/composables/explorer/utils'\n\n/**\n * Collapse all nodes: all children collapsed.\n *\n * This method will use current `uiEntries`, we don't need to traverse the full tree.\n * The action will be applied on the current items in the test results explorer.\n *\n * If the node is not a parent node, nothing will happen.\n *\n * Calling this method will:\n * - collapse all nodes\n * - remove opened tree items for the node and any children\n * - update uiEntries without child nodes\n *\n * @param id The node id to collapse.\n */\nexport function runCollapseNode(id: string) {\n  const node = explorerTree.nodes.get(id)\n  if (!node || !isParentNode(node)) {\n    return\n  }\n\n  const treeItems = new Set(openedTreeItems.value)\n  treeItems.delete(node.id)\n  const entries = [...collectCollapseNode(node)]\n  openedTreeItems.value = Array.from(treeItems)\n  // Keep expandAll state as it is: collapsing individual shouldn't prevent collapsing all the nodes (\"collapse all\" button)\n  // There is a watcher on composable search.ts to reset to undefined expandAll if there are no opened items\n  // treeFilter.value.expandAll = true\n  uiEntries.value = entries\n}\n\n/**\n * Collapse all nodes: any child collapsed.\n *\n * This method will use current `uiEntries`, we don't need to traverse the full tree.\n * The action will be applied on the current items in the test results explorer.\n *\n * We'll use current `uiEntries`, we don't need to traverse the full tree.\n *\n * Calling this method will:\n * - collapse all nodes\n * - clear stored opened tree items\n * - update the filtered expandAll state to true\n * - update uiEntries without child nodes\n *\n */\nexport function runCollapseAllTask() {\n  // collapse all nodes\n  collapseAllNodes(explorerTree.root.tasks)\n  const entries = [...uiEntries.value.filter(isFileNode)]\n  collapseAllNodes(entries)\n  // collapse all nodes\n  openedTreeItems.value = []\n  treeFilter.value.expandAll = true\n  uiEntries.value = entries\n}\n\nfunction collapseAllNodes(nodes: UITaskTreeNode[]) {\n  for (const node of nodes) {\n    if (isParentNode(node)) {\n      node.expanded = false\n      collapseAllNodes(node.tasks)\n    }\n  }\n}\n\nfunction* collectChildNodes(node: UITaskTreeNode, itself: boolean): Generator<string> {\n  if (itself) {\n    yield node.id\n  }\n\n  if (isParentNode(node)) {\n    for (let i = 0; i < node.tasks.length; i++) {\n      yield* collectChildNodes(node.tasks[i], true)\n    }\n  }\n}\n\nfunction* collectCollapseNode(node: UITaskTreeNode) {\n  const id = node.id\n  // collect children to remove from the list\n  const childNodes = new Set<string>(collectChildNodes(node, false))\n  for (let i = 0; i < uiEntries.value.length; i++) {\n    const child = uiEntries.value[i]\n    // collapse current node and return it\n    if (child.id === id) {\n      child.expanded = false\n      yield child\n      continue\n    }\n\n    // remove children from the list\n    if (childNodes.has(child.id)) {\n      childNodes.delete(child.id)\n      continue\n    }\n\n    // return the node\n    yield child\n  }\n}\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/collector.ts",
    "content": "import type { File, Task, TaskResultPack, Test, TestArtifact } from '@vitest/runner'\nimport type { Arrayable } from '@vitest/utils'\nimport type { CollectFilteredTests, CollectorInfo, Filter, FilteredTests, SearchMatcher } from '~/composables/explorer/types'\nimport { isTestCase } from '@vitest/runner/utils'\nimport { toArray } from '@vitest/utils/helpers'\nimport { client, findById } from '~/composables/client'\nimport { testRunState } from '~/composables/client/state'\nimport { expandNodesOnEndRun } from '~/composables/explorer/expand'\nimport { runFilter, testMatcher } from '~/composables/explorer/filter'\nimport { explorerTree } from '~/composables/explorer/index'\nimport {\n  initialized,\n  openedTreeItems,\n  treeFilter,\n  uiEntries,\n  uiFiles,\n} from '~/composables/explorer/state'\nimport {\n  createOrUpdateFileNode,\n  createOrUpdateNodeTask,\n  createOrUpdateSuiteTask,\n  isRunningTestNode,\n  isSlowTestTask,\n} from '~/composables/explorer/utils'\nimport { isSuite } from '~/utils/task'\nimport { hasFailedSnapshot } from '../../../../vitest/src/utils/tasks'\n\nexport { hasFailedSnapshot }\n\nexport function runLoadFiles(\n  remoteFiles: File[],\n  collect: boolean,\n  search: SearchMatcher,\n  filter: Filter,\n) {\n  remoteFiles.map(f => [`${f.filepath}:${f.projectName || ''}`, f] as const)\n    .sort(([a], [b]) => a.localeCompare(b))\n    .map(([, f]) => createOrUpdateFileNode(f, collect))\n\n  uiFiles.value = [...explorerTree.root.tasks]\n  runFilter(search, {\n    failed: filter.failed,\n    success: filter.success,\n    skipped: filter.skipped,\n    slow: filter.slow,\n    onlyTests: filter.onlyTests,\n  })\n}\n\nexport function preparePendingTasks(packs: TaskResultPack[]) {\n  queueMicrotask(() => {\n    const pending = explorerTree.pendingTasks\n    const idMap = client.state.idMap\n    for (const pack of packs) {\n      const result = pack[1]\n      if (result) {\n        const task = idMap.get(pack[0])\n        if (task) {\n          let file = pending.get(task.file.id)\n          if (!file) {\n            file = new Set()\n            pending.set(task.file.id, file)\n          }\n          file.add(task.id)\n        }\n      }\n    }\n  })\n}\n\nexport function recordTestArtifact(\n  id: string,\n  artifact: TestArtifact,\n) {\n  const pending = explorerTree.pendingTasks\n  const idMap = client.state.idMap\n  const test = idMap.get(id)\n  if (test?.type === 'test') {\n    let file = pending.get(test.file.id)\n    if (!file) {\n      file = new Set()\n      pending.set(test.file.id, file)\n    }\n    file.add(test.id)\n\n    if (artifact.type === 'internal:annotation') {\n      test.annotations.push(artifact.annotation)\n    }\n    else {\n      test.artifacts.push(artifact)\n    }\n  }\n}\n\nexport function runCollect(\n  start: boolean,\n  end: boolean,\n  summary: CollectorInfo,\n  search: SearchMatcher,\n  filter: Filter,\n  executionTime: number,\n) {\n  if (start) {\n    resetCollectorInfo(summary)\n  }\n\n  const collect = !start\n  queueMicrotask(() => {\n    if (end) {\n      traverseFiles(collect)\n    }\n    else {\n      traverseReceivedFiles(collect)\n    }\n  })\n\n  queueMicrotask(() => {\n    collectData(summary, executionTime)\n  })\n\n  queueMicrotask(() => {\n    if (end) {\n      summary.failedSnapshot = uiFiles.value && hasFailedSnapshot(\n        uiFiles.value.map(f => findById(f.id)!),\n      )\n      summary.failedSnapshotEnabled = true\n    }\n  })\n\n  queueMicrotask(() => {\n    doRunFilter(search, filter, end)\n  })\n}\n\nfunction* collectRunningTodoTests() {\n  yield* uiEntries.value.filter(isRunningTestNode)\n}\n\nfunction updateRunningTodoTests() {\n  const idMap = client.state.idMap\n  let task: Task | undefined\n  for (const test of collectRunningTodoTests()) {\n    // lookup the parent\n    task = idMap.get(test.parentId)\n    if (task && isSuite(task) && task.mode === 'todo') {\n      task = idMap.get(test.id)\n      if (task) {\n        task.mode = 'todo'\n      }\n    }\n  }\n}\n\nfunction traverseFiles(collect: boolean) {\n  // add missing files: now we have only files with running tests on the initial ws open event\n  const files = client.state.getFiles()\n  const currentFiles = explorerTree.nodes\n  const missingFiles = files.filter(f => !currentFiles.has(f.id))\n  for (let i = 0; i < missingFiles.length; i++) {\n    createOrUpdateFileNode(missingFiles[i], collect)\n    createOrUpdateEntry(missingFiles[i].tasks)\n  }\n\n  // update pending tasks\n  const rootTasks = explorerTree.root.tasks\n  // collect remote children\n  for (let i = 0; i < rootTasks.length; i++) {\n    const fileNode = rootTasks[i]\n    const file = findById(fileNode.id)\n    if (!file) {\n      continue\n    }\n\n    createOrUpdateFileNode(file, collect)\n    const tasks = file.tasks\n    if (!tasks?.length) {\n      continue\n    }\n\n    createOrUpdateEntry(file.tasks)\n  }\n}\n\nfunction traverseReceivedFiles(collect: boolean) {\n  const updatedFiles = new Map(explorerTree.pendingTasks.entries())\n  explorerTree.pendingTasks.clear()\n\n  // add missing files: now we have only files with running tests on the initial ws open event\n  const currentFiles = explorerTree.nodes\n  const missingFiles = Array\n    .from(updatedFiles.keys())\n    .filter(id => !currentFiles.has(id))\n    .map(id => findById(id))\n    .filter(Boolean) as File[]\n\n  let newFile: File\n  for (let i = 0; i < missingFiles.length; i++) {\n    newFile = missingFiles[i]\n    createOrUpdateFileNode(newFile, false)\n    createOrUpdateEntry(newFile.tasks)\n    // remove the file from the updated files\n    updatedFiles.delete(newFile.id)\n  }\n\n  // collect remote children\n  const idMap = client.state.idMap\n  const rootTasks = explorerTree.root.tasks\n  for (let i = 0; i < rootTasks.length; i++) {\n    const fileNode = rootTasks[i]\n    const file = findById(fileNode.id)\n    if (!file) {\n      continue\n    }\n    const entries = updatedFiles.get(file.id)\n    if (!entries) {\n      continue\n    }\n    createOrUpdateFileNode(file, collect)\n    createOrUpdateEntry(Array.from(entries, id => idMap.get(id)).filter(Boolean) as Task[])\n  }\n}\n\nfunction doRunFilter(\n  search: SearchMatcher,\n  filter: Filter,\n  end = false,\n) {\n  const expandAll = treeFilter.value.expandAll\n  const resetExpandAll = expandAll !== true\n  const ids = new Set(openedTreeItems.value)\n  const applyExpandNodes = (ids.size > 0 && expandAll === false) || resetExpandAll\n\n  // refresh explorer\n  queueMicrotask(() => {\n    refreshExplorer(search, filter, end)\n  })\n\n  // initialize the explorer\n  if (!initialized.value) {\n    queueMicrotask(() => {\n      if (uiEntries.value.length || end) {\n        initialized.value = true\n      }\n    })\n  }\n\n  if (applyExpandNodes) {\n    // expand all nodes\n    queueMicrotask(() => {\n      expandNodesOnEndRun(ids, end)\n      if (resetExpandAll) {\n        treeFilter.value.expandAll = false\n      }\n    })\n    // refresh explorer\n    queueMicrotask(() => {\n      refreshExplorer(search, filter, end)\n    })\n  }\n}\n\nfunction refreshExplorer(search: SearchMatcher, filter: Filter, end: boolean) {\n  runFilter(search, filter)\n  // update only at the end\n  if (end) {\n    updateRunningTodoTests()\n    testRunState.value = 'idle'\n  }\n}\n\nfunction createOrUpdateEntry(tasks: Task[]) {\n  let task: Task\n  for (let i = 0; i < tasks.length; i++) {\n    task = tasks[i]\n    if (isSuite(task)) {\n      createOrUpdateSuiteTask(task.id, true)\n    }\n    else {\n      createOrUpdateNodeTask(task.id)\n    }\n  }\n}\n\nexport function resetCollectorInfo(summary: CollectorInfo) {\n  summary.files = 0\n  summary.time = ''\n  summary.filesFailed = 0\n  summary.filesSuccess = 0\n  summary.filesIgnore = 0\n  summary.filesRunning = 0\n  summary.filesSkipped = 0\n  summary.filesTodo = 0\n  summary.testsFailed = 0\n  summary.testsSuccess = 0\n  summary.testsIgnore = 0\n  summary.testsSkipped = 0\n  summary.testsTodo = 0\n  summary.testsExpectedFail = 0\n  summary.testsSlow = 0\n  summary.totalTests = 0\n  summary.failedSnapshotEnabled = false\n}\n\nfunction collectData(\n  summary: CollectorInfo,\n  time: number,\n) {\n  const idMap = client.state.idMap\n  const filesMap = new Map(explorerTree.root.tasks.filter(f => idMap.has(f.id)).map(f => [f.id, f]))\n  const useFiles = Array.from(filesMap.values(), file => [file.id, findById(file.id)] as const)\n  const data = {\n    files: filesMap.size,\n    time: time > 1000 ? `${(time / 1000).toFixed(2)}s` : `${Math.round(time)}ms`,\n    filesFailed: 0,\n    filesSuccess: 0,\n    filesIgnore: 0,\n    filesRunning: 0,\n    filesSkipped: 0,\n    filesTodo: 0,\n    filesSnapshotFailed: 0,\n    testsFailed: 0,\n    testsSuccess: 0,\n    testsIgnore: 0,\n    testsSkipped: 0,\n    testsTodo: 0,\n    testsExpectedFail: 0,\n    testsSlow: 0,\n    totalTests: 0,\n    failedSnapshot: false,\n    failedSnapshotEnabled: false,\n  } satisfies CollectorInfo\n\n  for (const [_, f] of useFiles) {\n    if (!f) {\n      continue\n    }\n    if (f.result?.state === 'fail') {\n      data.filesFailed++\n    }\n    else if (f.result?.state === 'pass') {\n      data.filesSuccess++\n    }\n    else if (f.mode === 'skip') {\n      data.filesIgnore++\n      data.filesSkipped++\n    }\n    else if (f.mode === 'todo') {\n      data.filesIgnore++\n      data.filesTodo++\n    }\n    else {\n      data.filesRunning++\n    }\n\n    const {\n      failed,\n      success,\n      skipped,\n      total,\n      ignored,\n      todo,\n      expectedFail,\n      slow,\n    } = collectTests(f)\n\n    data.totalTests += total\n    data.testsFailed += failed\n    data.testsSuccess += success\n    data.testsSkipped += skipped\n    data.testsTodo += todo\n    data.testsExpectedFail += expectedFail\n    data.testsSlow += slow\n    data.testsIgnore += ignored\n  }\n\n  summary.files = data.files\n  summary.time = data.time\n  summary.filesFailed = data.filesFailed\n  summary.filesSuccess = data.filesSuccess\n  summary.filesIgnore = data.filesIgnore\n  summary.filesRunning = data.filesRunning\n  summary.filesSkipped = data.filesSkipped\n  summary.filesTodo = data.filesTodo\n  summary.testsFailed = data.testsFailed\n  summary.testsSuccess = data.testsSuccess\n  summary.testsTodo = data.testsTodo\n  summary.testsExpectedFail = data.testsExpectedFail\n  summary.testsSlow = data.testsSlow\n  summary.testsIgnore = data.testsIgnore\n  summary.testsSkipped = data.testsSkipped\n  summary.totalTests = data.totalTests\n}\n\nfunction collectTests(file: File, search: SearchMatcher = () => true, filter?: Filter) {\n  const data = {\n    failed: 0,\n    success: 0,\n    skipped: 0,\n    running: 0,\n    total: 0,\n    ignored: 0,\n    todo: 0,\n    expectedFail: 0,\n    slow: 0,\n  } satisfies CollectFilteredTests\n\n  for (const t of testsCollector(file)) {\n    if (!filter || testMatcher(t, search, filter)) {\n      data.total++\n      if (isSlowTestTask(t)) {\n        data.slow++\n      }\n      if (t.result?.state === 'fail') {\n        data.failed++\n      }\n      else if (t.result?.state === 'pass') {\n        // Check if this is an expected failure\n        if (t.fails) {\n          data.expectedFail++\n        }\n        else {\n          data.success++\n        }\n      }\n      else if (t.mode === 'skip') {\n        data.ignored++\n        data.skipped++\n      }\n      else if (t.mode === 'todo') {\n        data.ignored++\n        data.todo++\n      }\n    }\n  }\n\n  data.running = data.total - data.failed - data.success - data.ignored - data.expectedFail\n\n  return data\n}\n\nexport function collectTestsTotalData(\n  filtered: boolean,\n  onlyTests: boolean,\n  tests: File[],\n  filesSummary: FilteredTests,\n  search: SearchMatcher,\n  filter: Filter,\n) {\n  if (onlyTests) {\n    // todo: apply similar logic when filtered\n    return tests\n      .map(file => collectTests(file, search, filter))\n      .reduce((acc, {\n        failed,\n        success,\n        ignored,\n        running,\n      }) => {\n        acc.failed += failed\n        acc.success += success\n        acc.skipped += ignored\n        acc.running += running\n        return acc\n      }, { failed: 0, success: 0, skipped: 0, running: 0 })\n  }\n  else if (filtered) {\n    const data = {\n      failed: 0,\n      success: 0,\n      skipped: 0,\n      running: 0,\n    } satisfies FilteredTests\n    // will match when the filter entry is active or filter is inactive (skipped excluded)\n    // for example, we should update all when the filter is empty\n    // but shouldn't update failed if we're filtering by success\n    const empty = !filter.success && !filter.failed\n    const applyFailed = filter.failed || empty\n    const applySuccess = filter.success || empty\n    for (const f of tests) {\n      if (f.result?.state === 'fail') {\n        data.failed += applyFailed ? 1 : 0\n      }\n      else if (f.result?.state === 'pass') {\n        data.success += applySuccess ? 1 : 0\n      }\n      else if (f.mode === 'skip' || f.mode === 'todo') {\n        // just ignore\n      }\n      else {\n        data.running++\n      }\n    }\n\n    return data\n  }\n\n  return filesSummary\n}\n\nfunction* testsCollector(suite: Arrayable<Task>): Generator<Test> {\n  const arraySuites = toArray(suite)\n  let s: Task\n  for (let i = 0; i < arraySuites.length; i++) {\n    s = arraySuites[i]\n    if (isTestCase(s)) {\n      yield s\n    }\n    else {\n      yield* testsCollector(s.tasks)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/expand.ts",
    "content": "import type { Filter, SearchMatcher, UITaskTreeNode } from '~/composables/explorer/types'\nimport { findById } from '~/composables/client'\nimport { filterAll, filterNode } from '~/composables/explorer/filter'\nimport { explorerTree } from '~/composables/explorer/index'\nimport { filteredFiles, openedTreeItems, treeFilter, uiEntries } from '~/composables/explorer/state'\nimport { createOrUpdateNode, createOrUpdateSuiteTask, isFileNode, isParentNode } from '~/composables/explorer/utils'\n\n/**\n * Expand the node: only direct children will be expanded\n *\n * This method will use current `uiEntries`, we don't need to traverse the full tree.\n * The action will be applied on the current items in the test results explorer.\n *\n * **Note:** we only need to apply the filter on child nodes, when filtering, parent nodes\n * are not present in the explorer if don't match the filter, only those matching the criteria\n * will be there, we only need to filter the children of the node to expand.\n *\n * Calling this method will:\n * - remove opened tree items for the node and any children\n * - update uiEntries including child nodes\n *\n * @param id The node id to expand.\n * @param search The search applied.\n * @param filter The filter applied.\n */\nexport function runExpandNode(\n  id: string,\n  search: SearchMatcher,\n  filter: Filter,\n) {\n  const entry = createOrUpdateSuiteTask(\n    id,\n    false,\n  )\n  if (!entry) {\n    return\n  }\n\n  const [node, task] = entry\n\n  // create only direct children\n  for (const subtask of task.tasks) {\n    createOrUpdateNode(node.id, subtask, false)\n  }\n\n  // expand the node\n  node.expanded = true\n\n  const treeItems = new Set(openedTreeItems.value)\n  treeItems.add(node.id)\n  // collect children\n  // the first node is itself only when it is a file\n  const children = new Set(filterNode(\n    node,\n    search,\n    filter,\n  ))\n\n  const entries = [...collectExpandedNode(node, children)]\n  openedTreeItems.value = Array.from(treeItems)\n  // Keep expandAll state as it is: expanding individual shouldn't prevent expanding all the nodes (\"expand all\" button)\n  // There is a watcher on composable search.ts to reset to undefined expandAll if there are no opened items\n  // treeFilter.value.expandAll = false\n  uiEntries.value = entries\n}\n\n/**\n * Expand all nodes: any child expanded.\n *\n * This method will use current `uiEntries`, we don't need to traverse the full tree.\n * The action will be applied on the current items in the test results explorer.\n *\n * Any already expanded child will be shown as expanded: collapsing nodes will not collapse any child.\n *\n * **Note:** we don't need to apply the filter here, we'll use the current `uiEntries`, when filtering,\n * parent nodes are not present in the explorer, only those matching the criteria will be there.\n * The filter will be applied to the full tree.\n *\n * Calling this method will:\n * - expand all nodes\n * - add stored opened tree items\n * - update the filtered expandAll state to false\n * - update uiEntries with child nodes\n *\n * @param search The search applied.\n * @param filter The filter applied.\n */\nexport function runExpandAll(\n  search: SearchMatcher,\n  filter: Filter,\n) {\n  expandAllNodes(explorerTree.root.tasks, false)\n  const entries = [...filterAll(\n    search,\n    filter,\n  )]\n  treeFilter.value.expandAll = false\n  openedTreeItems.value = []\n  uiEntries.value = entries\n  filteredFiles.value = entries.filter(isFileNode).map(f => findById(f.id)!)\n}\n\nexport function expandNodesOnEndRun(\n  ids: Set<string>,\n  end: boolean,\n) {\n  if (ids.size) {\n    for (const node of uiEntries.value) {\n      if (ids.has(node.id)) {\n        node.expanded = true\n      }\n    }\n  }\n  else if (end) {\n    expandAllNodes(uiEntries.value.filter(isFileNode), true)\n  }\n}\n\nexport function expandAllNodes(nodes: UITaskTreeNode[], updateState: boolean) {\n  for (const node of nodes) {\n    if (isParentNode(node)) {\n      node.expanded = true\n      expandAllNodes(node.tasks, false)\n    }\n  }\n\n  if (updateState) {\n    treeFilter.value.expandAll = false\n    openedTreeItems.value = []\n  }\n}\n\nfunction* collectExpandedNode(\n  node: UITaskTreeNode,\n  children: Set<UITaskTreeNode>,\n) {\n  const id = node.id\n  const ids = new Set(Array.from(children).map(n => n.id))\n\n  for (const child of uiEntries.value) {\n    if (child.id === id) {\n      child.expanded = true\n      if (!ids.has(child.id)) {\n        yield node\n      }\n      yield* children\n    }\n    else if (!ids.has(child.id)) {\n      yield child\n    }\n  }\n}\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/filter.ts",
    "content": "import type { Task } from '@vitest/runner'\nimport type { FileTreeNode, Filter, FilterResult, ParentTreeNode, SearchMatcher, UITaskTreeNode } from '~/composables/explorer/types'\nimport { client, config, findById } from '~/composables/client'\nimport { explorerTree } from '~/composables/explorer/index'\nimport { currentProjectName, filteredFiles, projectSort, uiEntries } from '~/composables/explorer/state'\nimport {\n  getSortedRootTasks,\n  isFileNode,\n  isParentNode,\n  isTestNode,\n} from '~/composables/explorer/utils'\n\nexport function testMatcher(task: Task, search: SearchMatcher, filter: Filter) {\n  return task ? matchTask(task, search, filter) : false\n}\n/**\n * Filter child nodes using search, filter and only tests.\n *\n * @param search The search applied.\n * @param filter The filter applied.\n */\nexport function runFilter(\n  search: SearchMatcher,\n  filter: Filter,\n) {\n  const entries = [...filterAll(\n    search,\n    filter,\n  )]\n  uiEntries.value = entries\n  filteredFiles.value = entries.filter(isFileNode).map(f => findById(f.id)!)\n}\n\nexport function* filterAll(\n  search: SearchMatcher,\n  filter: Filter,\n) {\n  const project = currentProjectName.value\n  const tasks = getSortedRootTasks(projectSort.value)\n\n  for (const node of tasks) {\n    if (project && node.projectName !== project) {\n      continue\n    }\n    yield* filterNode(node, search, filter)\n  }\n}\n\nexport function* filterNode(\n  node: UITaskTreeNode,\n  search: SearchMatcher,\n  filter: Filter,\n) {\n  const treeNodes = new Set<string>()\n\n  const parentsMap = new Map<string, boolean>()\n  const list: FilterResult[] = []\n\n  let fileId: string | undefined\n\n  if (filter.onlyTests) {\n    for (const [match, child] of visitNode(\n      node,\n      treeNodes,\n      n => matcher(n, search, filter),\n    )) {\n      list.push([match, child])\n    }\n  }\n  else {\n    for (const [match, child] of visitNode(\n      node,\n      treeNodes,\n      n => matcher(n, search, filter),\n    )) {\n      if (isParentNode(child)) {\n        parentsMap.set(child.id, match)\n        if (isFileNode(child)) {\n          if (match) {\n            fileId = child.id\n          }\n          list.push([match, child])\n        }\n        else {\n          list.push([match || parentsMap.get(child.parentId) === true, child])\n        }\n      }\n      else {\n        list.push([match || parentsMap.get(child.parentId) === true, child])\n      }\n    }\n    // when expanding a non-file node\n    if (!fileId && !isFileNode(node) && 'fileId' in node) {\n      fileId = node.fileId as string\n    }\n  }\n\n  const filesToShow = new Set<string>()\n\n  const entries = [...filterParents(\n    list,\n    filter.onlyTests,\n    treeNodes,\n    filesToShow,\n    fileId,\n  )].reverse()\n\n  // We show only the files and parents whose parent is expanded.\n  // Filtering will return all the nodes matching the filter and their parents.\n  // Once we've the tree, we need to remove the children from not expanded parents.\n  // For example, if we have a suite with only one test, when collapsing the suite node,\n  // we still need to show the suite, but the test must be removed from the list to render.\n\n  const map = explorerTree.nodes\n\n  // When searching, expand parent nodes of matching tests so they are visible\n  for (const id of treeNodes) {\n    const treeNode = map.get(id)\n    if (treeNode && 'expanded' in treeNode) {\n      treeNode.expanded = true\n    }\n  }\n\n  // collect files and all suites whose parent is expanded\n  const parents = new Set(\n    entries.filter(e => isFileNode(e) || (isParentNode(e) && map.get(e.parentId)?.expanded)).map(e => e.id),\n  )\n\n  // collect files, and suites and tests whose parent is expanded\n  yield* entries.filter((node) => {\n    // all file nodes or children of expanded parents\n    return isFileNode(node) || (parents.has(node.parentId) && map.get(node.parentId)?.expanded)\n  })\n}\n\nfunction expandCollapseNode(\n  match: boolean,\n  child: FileTreeNode | ParentTreeNode,\n  treeNodes: Set<string>,\n  collapseParents: boolean,\n  filesToShow: Set<string>,\n) {\n  if (collapseParents) {\n    if (isFileNode(child)) {\n      if (filesToShow.has(child.id)) {\n        return child\n      }\n\n      return undefined\n    }\n    // show the parent if at least one child matches the filter\n    if (treeNodes.has(child.id)) {\n      const parent = explorerTree.nodes.get(child.parentId)\n      if (parent && isFileNode(parent)) {\n        filesToShow.add(parent.id)\n      }\n\n      return child\n    }\n  }\n  else {\n    // show the parent if matches the filter or at least one child matches the filter\n    if (match || treeNodes.has(child.id) || filesToShow.has(child.id)) {\n      const parent = explorerTree.nodes.get(child.parentId)\n      if (parent && isFileNode(parent)) {\n        filesToShow.add(parent.id)\n      }\n\n      return child\n    }\n  }\n}\n\nfunction* filterParents(\n  list: FilterResult[],\n  collapseParents: boolean,\n  treeNodes: Set<string>,\n  filesToShow: Set<string>,\n  nodeId?: string,\n) {\n  for (let i = list.length - 1; i >= 0; i--) {\n    const [match, child] = list[i]\n    const isParent = isParentNode(child)\n    if (!collapseParents && nodeId && treeNodes.has(nodeId) && 'fileId' in child && child.fileId === nodeId) {\n      if (isParent) {\n        treeNodes.add(child.id)\n      }\n      let parent = explorerTree.nodes.get(child.parentId)\n      while (parent) {\n        treeNodes.add(parent.id)\n        if (isFileNode(parent)) {\n          filesToShow.add(parent.id)\n        }\n        parent = explorerTree.nodes.get(parent.parentId)\n      }\n      yield child\n      continue\n    }\n\n    if (isParent) {\n      const node = expandCollapseNode(\n        match,\n        child,\n        treeNodes,\n        collapseParents,\n        filesToShow,\n      )\n      if (node) {\n        yield node\n      }\n    }\n    else if (match) {\n      const parent = explorerTree.nodes.get(child.parentId)\n      if (parent && isFileNode(parent)) {\n        filesToShow.add(parent.id)\n      }\n      yield child\n    }\n  }\n}\n\nfunction matchState(task: Task, filter: Filter) {\n  if (filter.slow) {\n    if (task.type === 'test') {\n      const threshold = config.value.slowTestThreshold\n      if (typeof threshold === 'number' && typeof task.result?.duration === 'number' && task.result.duration > threshold) {\n        return true\n      }\n    }\n  }\n\n  if (filter.success || filter.failed) {\n    if ('result' in task) {\n      if (filter.success && task.result?.state === 'pass') {\n        return true\n      }\n      if (filter.failed && task.result?.state === 'fail') {\n        return true\n      }\n    }\n  }\n\n  if (filter.skipped && 'mode' in task) {\n    return task.mode === 'skip' || task.mode === 'todo'\n  }\n\n  return false\n}\n\nfunction matchTask(\n  task: Task,\n  search: SearchMatcher,\n  filter: Filter,\n) {\n  // search and filter will apply together\n  if (search(task)) {\n    const hasStatusFilter = filter.success || filter.failed || filter.skipped || filter.slow\n    if (hasStatusFilter) {\n      if (matchState(task, filter)) {\n        return true\n      }\n    }\n    else {\n      return true\n    }\n  }\n\n  return false\n}\n\nfunction* visitNode(\n  node: UITaskTreeNode,\n  treeNodes: Set<string>,\n  matcher: (node: UITaskTreeNode) => boolean,\n): Generator<[match: boolean, node: UITaskTreeNode]> {\n  const match = matcher(node)\n\n  if (match) {\n    if (isTestNode(node)) {\n      let parent = explorerTree.nodes.get(node.parentId)\n      while (parent) {\n        treeNodes.add(parent.id)\n        parent = explorerTree.nodes.get(parent.parentId)\n      }\n    }\n    else if (isFileNode(node)) {\n      treeNodes.add(node.id)\n    }\n    else {\n      treeNodes.add(node.id)\n      let parent = explorerTree.nodes.get(node.parentId)\n      while (parent) {\n        treeNodes.add(parent.id)\n        parent = explorerTree.nodes.get(parent.parentId)\n      }\n    }\n  }\n\n  yield [match, node]\n  if (isParentNode(node)) {\n    for (let i = 0; i < node.tasks.length; i++) {\n      yield* visitNode(node.tasks[i], treeNodes, matcher)\n    }\n  }\n}\n\nfunction matcher(node: UITaskTreeNode, search: SearchMatcher, filter: Filter) {\n  const task = client.state.idMap.get(node.id)\n  return task ? matchTask(task, search, filter) : false\n}\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/index.ts",
    "content": "import { ExplorerTree } from './tree'\n\nexport const explorerTree = new ExplorerTree()\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/search.ts",
    "content": "import type { Ref } from 'vue'\nimport type { SortUIType } from '~/composables/explorer/types'\nimport { debouncedWatch } from '@vueuse/core'\nimport { computed, ref, watch } from 'vue'\nimport { explorerTree } from '~/composables/explorer'\nimport {\n  ALL_PROJECTS,\n  currentProject,\n  currentProjectName,\n  disableClearProjects,\n  enableProjects,\n  filter,\n  filteredFiles,\n  initialized,\n  isFiltered,\n  isFilteredByStatus,\n  openedTreeItems,\n  projectSort,\n  search,\n  searchMatcher,\n  testsTotal,\n  treeFilter,\n  uiEntries,\n} from './state'\n\nexport function useSearch(\n  searchBox: Ref<HTMLInputElement | undefined>,\n  selectProject: Ref<HTMLSelectElement | undefined>,\n  sortProject: Ref<HTMLSelectElement | undefined>,\n) {\n  const disableFilter = computed(() => {\n    if (isFilteredByStatus.value) {\n      return false\n    }\n\n    return !filter.onlyTests\n  })\n\n  const disableClearSearch = computed(() => search.value === '')\n  const debouncedSearch = ref(search.value)\n  const disableClearProjectSort = computed(() => projectSort.value === 'default')\n\n  // Reset project-specific sort when multiple projects are no longer available\n  watch(() => enableProjects.value, (enabled) => {\n    if (!enabled && (projectSort.value === 'asc' || projectSort.value === 'desc')) {\n      projectSort.value = 'default'\n    }\n  })\n\n  debouncedWatch(() => search.value, (value) => {\n    debouncedSearch.value = value?.trim() ?? ''\n  }, { debounce: 256 })\n\n  function clearSearch(focus: boolean) {\n    search.value = ''\n    if (focus) {\n      searchBox.value?.focus()\n    }\n  }\n\n  function clearFilter(focus: boolean) {\n    filter.failed = false\n    filter.success = false\n    filter.skipped = false\n    filter.slow = false\n    filter.onlyTests = false\n    if (focus) {\n      searchBox.value?.focus()\n    }\n  }\n\n  function clearProject(focus: boolean) {\n    currentProject.value = ALL_PROJECTS\n    if (focus) {\n      selectProject.value?.focus()\n    }\n  }\n\n  function clearProjectSort(focus: boolean) {\n    projectSort.value = 'default'\n    if (focus) {\n      sortProject.value?.focus()\n    }\n  }\n\n  function clearAll() {\n    clearFilter(false)\n    clearSearch(true)\n    clearProject(false)\n    clearProjectSort(false)\n  }\n\n  function updateFilterStorage(\n    searchValue: string,\n    failedValue: boolean,\n    successValue: boolean,\n    skippedValue: boolean,\n    slowValue: boolean,\n    onlyTestsValue: boolean,\n    projectValue: string,\n    projectSortValue: SortUIType,\n  ) {\n    if (!initialized.value) {\n      return\n    }\n\n    treeFilter.value.search = searchValue?.trim() ?? ''\n    treeFilter.value.failed = failedValue\n    treeFilter.value.success = successValue\n    treeFilter.value.skipped = skippedValue\n    treeFilter.value.slow = slowValue\n    treeFilter.value.onlyTests = onlyTestsValue\n    treeFilter.value.project = projectValue\n    treeFilter.value.projectSort = projectSortValue === 'default' ? undefined : projectSortValue\n  }\n\n  watch(\n    () => [\n      debouncedSearch.value,\n      filter.failed,\n      filter.success,\n      filter.skipped,\n      filter.slow,\n      filter.onlyTests,\n      currentProject.value,\n      projectSort.value,\n    ] as const,\n    ([search, failed, success, skipped, slow, onlyTests, project, projectSort]) => {\n      updateFilterStorage(\n        search,\n        failed,\n        success,\n        skipped,\n        slow,\n        onlyTests,\n        project,\n        projectSort,\n      )\n      explorerTree.filterNodes()\n    },\n    { flush: 'post' },\n  )\n\n  watch(() => openedTreeItems.value.length, (size) => {\n    if (size) {\n      treeFilter.value.expandAll = undefined\n    }\n  }, { flush: 'post' })\n\n  return {\n    initialized,\n    filter,\n    search,\n    disableFilter,\n    isFiltered,\n    isFilteredByStatus,\n    disableClearSearch,\n    clearAll,\n    clearSearch,\n    clearFilter,\n    filteredFiles,\n    testsTotal,\n    uiEntries,\n    searchMatcher,\n    enableProjects,\n    disableClearProjects,\n    currentProject,\n    currentProjectName,\n    clearProject,\n    projectSort,\n    clearProjectSort,\n    disableClearProjectSort,\n  }\n}\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/state.ts",
    "content": "import type { File, Task } from '@vitest/runner'\nimport type { FileTreeNode, Filter, FilteredTests, SortUIType, TreeFilterState, UITaskTreeNode } from './types'\nimport { createTagsFilter } from '@vitest/runner/utils'\nimport { useLocalStorage } from '@vueuse/core'\nimport { computed, reactive, ref, shallowRef } from 'vue'\nimport { availableProjects } from '~/composables/client'\nimport { caseInsensitiveMatch } from '~/utils/task'\nimport { config } from '../client'\nimport { explorerTree } from './index'\n\nexport const uiFiles = shallowRef<FileTreeNode[]>([])\nexport const uiEntries = shallowRef<UITaskTreeNode[]>([])\nexport const openedTreeItems = useLocalStorage<string[]>(\n  'vitest-ui_task-tree-opened',\n  [],\n  { shallow: true },\n)\nexport const ALL_PROJECTS = '__vitest_ui_all_projects__'\nexport const openedTreeItemsSet = computed(() => new Set(openedTreeItems.value))\nexport const treeFilter = useLocalStorage<TreeFilterState>(\n  'vitest-ui_task-tree-filter',\n  {\n    expandAll: undefined,\n    failed: false,\n    success: false,\n    skipped: false,\n    slow: false,\n    onlyTests: false,\n    search: '',\n    project: ALL_PROJECTS,\n    projectSort: undefined,\n  },\n)\nexport const projectSort = ref<SortUIType>(treeFilter.value.projectSort || 'default')\nexport const currentProject = shallowRef(treeFilter.value?.project || ALL_PROJECTS)\nexport const enableProjects = computed(() => availableProjects.value.length > 1)\nexport const disableClearProjects = computed(() => currentProject.value === ALL_PROJECTS)\nexport const currentProjectName = computed(() => {\n  return !enableProjects.value || currentProject.value === ALL_PROJECTS ? undefined : currentProject.value\n})\nexport const search = ref<string>(treeFilter.value.search)\nconst tagExpressionsCache = new Map<string, { error?: string; matcher: (tags: string[]) => boolean }>()\nexport const searchMatcher = computed(() => {\n  if (search.value.startsWith('tag:')) {\n    if (!config.value.tags) { // config is not loaded yet\n      return { matcher: () => true }\n    }\n    const tagQuery = search.value.slice(4).trim()\n    let filter = tagExpressionsCache.get(tagQuery)\n    if (!filter) {\n      filter = createSafeFilter(tagQuery)\n      tagExpressionsCache.set(tagQuery, filter)\n    }\n    return {\n      matcher: (task: Task) => filter.matcher(task.tags || []),\n      error: filter.error,\n    }\n  }\n  return {\n    matcher: (task: Task) => search.value === '' || caseInsensitiveMatch(task.name, search.value),\n  }\n})\n\nfunction createSafeFilter(\n  query: string,\n) {\n  if (!query) {\n    return { matcher: () => true }\n  }\n  try {\n    return { matcher: createTagsFilter([query], config.value.tags || []) }\n  }\n  catch (error: any) {\n    return { matcher: () => false, error: error.message }\n  }\n}\nconst htmlEntities: Record<string, string> = {\n  '&': '&amp;',\n  '<': '&lt;',\n  '>': '&gt;',\n  '\"': '&quot;',\n  '\\'': '&#39;',\n}\nexport function escapeHtml(str: string) {\n  return str.replace(/[&<>\"']/g, m => htmlEntities[m])\n}\nexport const highlightRegex = computed(() => {\n  const searchString = search.value.toLowerCase()\n  return searchString.length ? new RegExp(`(${escapeHtml(searchString)})`, 'gi') : null\n})\nexport const isFiltered = computed(() => search.value.trim() !== '')\nexport const filter = reactive<Filter>({\n  failed: treeFilter.value.failed,\n  success: treeFilter.value.success,\n  skipped: treeFilter.value.skipped,\n  slow: treeFilter.value.slow,\n  onlyTests: treeFilter.value.onlyTests,\n})\nexport const isFilteredByStatus = computed(() => {\n  if (filter.failed) {\n    return true\n  }\n\n  if (filter.success) {\n    return true\n  }\n\n  if (filter.skipped) {\n    return true\n  }\n\n  if (filter.slow) {\n    return true\n  }\n\n  return false\n})\nexport const filteredFiles = shallowRef<File[]>([])\nexport const initialized = ref(false)\nexport const shouldShowExpandAll = computed(() => {\n  const expandAll = treeFilter.value.expandAll\n  const opened = openedTreeItems.value\n\n  if (opened.length > 0) {\n    return expandAll !== true\n  }\n\n  return expandAll !== false\n})\nexport const testsTotal = computed<FilteredTests>(() => {\n  const filtered = isFiltered.value\n  const filteredByStatus = isFilteredByStatus.value\n  const project = currentProjectName.value\n  const onlyTests = filter.onlyTests\n  const failed = explorerTree.summary.filesFailed\n  const success = explorerTree.summary.filesSuccess\n  const skipped = explorerTree.summary.filesSkipped\n  const running = explorerTree.summary.filesRunning\n  const files = filteredFiles.value\n  return explorerTree.collectTestsTotal(\n    filtered || filteredByStatus || !!project,\n    onlyTests,\n    files,\n    {\n      failed,\n      success,\n      skipped,\n      running,\n    },\n  )\n})\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/tree.ts",
    "content": "import type { File, TaskResultPack, TestArtifact } from '@vitest/runner'\nimport type { RunnerTaskEventPack } from 'vitest'\nimport type {\n  CollectorInfo,\n  FilteredTests,\n  RootTreeNode,\n  UITaskTreeNode,\n} from '~/composables/explorer/types'\nimport { useRafFn } from '@vueuse/core'\nimport { reactive } from 'vue'\nimport { runCollapseAllTask, runCollapseNode } from '~/composables/explorer/collapse'\nimport { collectTestsTotalData, preparePendingTasks, recordTestArtifact, runCollect, runLoadFiles } from '~/composables/explorer/collector'\nimport { runExpandAll, runExpandNode } from '~/composables/explorer/expand'\nimport { runFilter } from '~/composables/explorer/filter'\nimport {\n  filter,\n  searchMatcher,\n} from '~/composables/explorer/state'\n\nexport class ExplorerTree {\n  private rafCollector: ReturnType<typeof useRafFn>\n  private resumeEndRunId: ReturnType<typeof setTimeout> | undefined\n  public startTime: number = 0\n  public executionTime: number = 0\n  constructor(\n    public projects: string[] = [],\n    public colors = new Map<string, string | undefined>(),\n    private onTaskUpdateCalled: boolean = false,\n    private resumeEndTimeout = 500,\n    public root = <RootTreeNode>{\n      id: 'vitest-root-node',\n      expandable: true,\n      expanded: true,\n      tasks: [],\n    },\n    public pendingTasks = new Map<string, Set<string>>(),\n    public nodes = new Map<string, UITaskTreeNode>(),\n    public summary = reactive<CollectorInfo>({\n      files: 0,\n      time: '',\n      filesFailed: 0,\n      filesSuccess: 0,\n      filesIgnore: 0,\n      filesRunning: 0,\n      filesSkipped: 0,\n      filesSnapshotFailed: 0,\n      filesTodo: 0,\n      testsFailed: 0,\n      testsSuccess: 0,\n      testsIgnore: 0,\n      testsSkipped: 0,\n      testsTodo: 0,\n      testsExpectedFail: 0,\n      testsSlow: 0,\n      totalTests: 0,\n      failedSnapshot: false,\n      failedSnapshotEnabled: false,\n    }),\n  ) {\n    // will run runCollect every ~100ms: 1000/10 = 100ms\n    // (beware increasing fpsLimit, it can be too much for the browser)\n    this.rafCollector = useRafFn(this.runCollect.bind(this), { fpsLimit: 10, immediate: false })\n  }\n\n  loadFiles(remoteFiles: File[], projects: { name: string; color?: string }[]) {\n    this.projects.splice(0, this.projects.length, ...projects.map(p => p.name))\n    this.colors = new Map(projects.map(p => [p.name, p.color]))\n\n    runLoadFiles(\n      remoteFiles,\n      true,\n      searchMatcher.value.matcher,\n      {\n        failed: filter.failed,\n        success: filter.success,\n        skipped: filter.skipped,\n        slow: filter.slow,\n        onlyTests: filter.onlyTests,\n      },\n    )\n  }\n\n  startRun() {\n    this.startTime = performance.now()\n    this.resumeEndRunId = setTimeout(() => this.endRun(), this.resumeEndTimeout)\n    this.collect(true, false)\n  }\n\n  recordTestArtifact(testId: string, artifact: TestArtifact) {\n    recordTestArtifact(testId, artifact)\n    if (!this.onTaskUpdateCalled) {\n      clearTimeout(this.resumeEndRunId)\n      this.onTaskUpdateCalled = true\n      this.collect(true, false, false)\n      this.rafCollector.resume()\n    }\n  }\n\n  resumeRun(packs: TaskResultPack[], _events: RunnerTaskEventPack[]) {\n    preparePendingTasks(packs)\n    if (!this.onTaskUpdateCalled) {\n      clearTimeout(this.resumeEndRunId)\n      this.onTaskUpdateCalled = true\n      this.collect(true, false, false)\n      this.rafCollector.resume()\n    }\n  }\n\n  endRun(executionTime = performance.now() - this.startTime) {\n    this.executionTime = executionTime\n    this.rafCollector.pause()\n    this.onTaskUpdateCalled = false\n    this.collect(false, true)\n  }\n\n  private runCollect() {\n    this.collect(false, false)\n  }\n\n  private collect(start: boolean, end: boolean, task = true) {\n    if (task) {\n      queueMicrotask(() => {\n        runCollect(\n          start,\n          end,\n          this.summary,\n          searchMatcher.value.matcher,\n          {\n            failed: filter.failed,\n            success: filter.success,\n            skipped: filter.skipped,\n            slow: filter.slow,\n            onlyTests: filter.onlyTests,\n          },\n          end ? this.executionTime : performance.now() - this.startTime,\n        )\n      })\n    }\n    else {\n      runCollect(\n        start,\n        end,\n        this.summary,\n        searchMatcher.value.matcher,\n        {\n          failed: filter.failed,\n          success: filter.success,\n          skipped: filter.skipped,\n          slow: filter.slow,\n          onlyTests: filter.onlyTests,\n        },\n        end ? this.executionTime : performance.now() - this.startTime,\n      )\n    }\n  }\n\n  collectTestsTotal(\n    filtered: boolean,\n    onlyTests: boolean,\n    tests: File[],\n    filesSummary: FilteredTests,\n  ) {\n    return collectTestsTotalData(filtered, onlyTests, tests, filesSummary, searchMatcher.value.matcher, {\n      failed: filter.failed,\n      success: filter.success,\n      skipped: filter.skipped,\n      slow: filter.slow,\n      onlyTests: filter.onlyTests,\n    })\n  }\n\n  collapseNode(id: string) {\n    queueMicrotask(() => {\n      runCollapseNode(id)\n    })\n  }\n\n  expandNode(id: string) {\n    queueMicrotask(() => {\n      runExpandNode(id, searchMatcher.value.matcher, {\n        failed: filter.failed,\n        success: filter.success,\n        skipped: filter.skipped,\n        slow: filter.slow,\n        onlyTests: filter.onlyTests,\n      })\n    })\n  }\n\n  collapseAllNodes() {\n    queueMicrotask(() => {\n      runCollapseAllTask()\n    })\n  }\n\n  expandAllNodes() {\n    queueMicrotask(() => {\n      runExpandAll(searchMatcher.value.matcher, {\n        failed: filter.failed,\n        success: filter.success,\n        skipped: filter.skipped,\n        slow: filter.slow,\n        onlyTests: filter.onlyTests,\n      })\n    })\n  }\n\n  filterNodes() {\n    queueMicrotask(() => {\n      runFilter(searchMatcher.value.matcher, {\n        failed: filter.failed,\n        success: filter.success,\n        skipped: filter.skipped,\n        slow: filter.slow,\n        onlyTests: filter.onlyTests,\n      })\n    })\n  }\n}\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/types.ts",
    "content": "import type { RunMode, Task, TaskState } from '@vitest/runner'\n\nexport type FilterResult = [match: boolean, node: UITaskTreeNode]\n\nexport interface FilteredTests {\n  failed: number\n  success: number\n  skipped: number\n  running: number\n}\n\nexport interface SearchMatcher {\n  (task: Task): boolean\n}\n\nexport interface CollectFilteredTests extends FilteredTests {\n  total: number\n  ignored: number\n  todo: number\n  expectedFail: number\n  slow: number\n}\n\nexport interface TaskTreeNode {\n  id: string\n  expandable: boolean\n  expanded: boolean\n}\n\nexport interface RootTreeNode extends TaskTreeNode {\n  tasks: FileTreeNode[]\n}\n\nexport type TaskTreeNodeType = 'file' | 'suite' | 'test'\n\nexport interface UITaskTreeNode extends TaskTreeNode {\n  type: TaskTreeNodeType\n  name: string\n  parentId: string\n  mode: RunMode\n  indent: number\n  state?: TaskState\n  duration?: number\n  slow?: boolean\n}\n\nexport interface TestTreeNode extends UITaskTreeNode {\n  fileId: string\n  type: 'test'\n}\n\nexport interface ParentTreeNode extends UITaskTreeNode {\n  children: Set<string>\n  tasks: UITaskTreeNode[]\n}\n\nexport interface SuiteTreeNode extends ParentTreeNode {\n  fileId: string\n  type: 'suite'\n}\n\nexport interface FileTreeNode extends ParentTreeNode {\n  type: 'file'\n  filepath: string\n  typecheck: boolean | undefined\n  projectName?: string\n  projectNameColor: string\n  collectDuration?: number\n  setupDuration?: number\n  environmentLoad?: number\n  prepareDuration?: number\n}\n\nexport interface Filter {\n  failed: boolean\n  success: boolean\n  skipped: boolean\n  slow: boolean\n  onlyTests: boolean\n}\n\nexport type ProjectSortType = 'asc' | 'desc'\nexport type DurationSortType = 'duration-asc' | 'duration-desc'\nexport type SortType = ProjectSortType | DurationSortType\nexport type SortUIType = SortType | 'default'\n\n/**\n * @deprecated Use `SortUIType` instead\n */\nexport type ProjectSortUIType = SortUIType\n\nexport interface TreeFilterState extends Filter {\n  search: string\n  expandAll?: boolean\n  project?: string\n  projectSort?: SortType\n}\n\nexport interface CollectorInfo {\n  files: number\n  time: string\n  filesFailed: number\n  filesSuccess: number\n  filesIgnore: number\n  filesRunning: number\n  filesSkipped: number\n  filesTodo: number\n  filesSnapshotFailed: number\n  testsFailed: number\n  testsSuccess: number\n  testsIgnore: number\n  testsSkipped: number\n  testsTodo: number\n  testsExpectedFail: number\n  testsSlow: number\n  totalTests: number\n  failedSnapshot: boolean\n  failedSnapshotEnabled: boolean\n}\n"
  },
  {
    "path": "packages/ui/client/composables/explorer/utils.ts",
    "content": "import type { File, Task } from '@vitest/runner'\nimport type {\n  FileTreeNode,\n  ParentTreeNode,\n  SortUIType,\n  SuiteTreeNode,\n  TestTreeNode,\n  UITaskTreeNode,\n} from '~/composables/explorer/types'\nimport { isTestCase } from '@vitest/runner/utils'\nimport { client, config } from '~/composables/client'\nimport { explorerTree } from '~/composables/explorer/index'\nimport { openedTreeItemsSet } from '~/composables/explorer/state'\nimport { getBadgeNameColor, isSuite as isTaskSuite } from '~/utils/task'\n\nexport function isTestNode(node: UITaskTreeNode): node is TestTreeNode {\n  return node.type === 'test'\n}\n\nexport function isRunningTestNode(node: UITaskTreeNode): node is TestTreeNode {\n  return node.mode === 'run' && (node.type === 'test')\n}\n\nexport function isFileNode(node: UITaskTreeNode): node is FileTreeNode {\n  return node.type === 'file'\n}\n\nexport function isSuiteNode(node: UITaskTreeNode): node is SuiteTreeNode {\n  return node.type === 'suite'\n}\n\nexport function isParentNode(node: UITaskTreeNode): node is FileTreeNode | SuiteTreeNode {\n  return node.type === 'file' || node.type === 'suite'\n}\n\nexport function isSlowTestTask(task: Task) {\n  if (task.type !== 'test') {\n    return false\n  }\n\n  const duration = task.result?.duration\n  if (typeof duration !== 'number') {\n    return false\n  }\n\n  const treshold = config.value.slowTestThreshold\n  return typeof treshold === 'number' && duration > treshold\n}\n\nexport function getSortedRootTasks(sort: SortUIType, tasks = explorerTree.root.tasks) {\n  const sorted = [...tasks]\n\n  sorted.sort((a, b) => {\n    if (sort === 'duration-desc' || sort === 'duration-asc') {\n      const durationA = a.duration ?? 0\n      const durationB = b.duration ?? 0\n      if (durationA !== durationB) {\n        return sort === 'duration-desc'\n          ? durationB - durationA\n          : durationA - durationB\n      }\n    }\n    else if (sort === 'asc' || sort === 'desc') {\n      const projectA = a.projectName || ''\n      const projectB = b.projectName || ''\n      if (projectA !== projectB) {\n        return sort === 'asc'\n          ? projectA.localeCompare(projectB)\n          : projectB.localeCompare(projectA)\n      }\n    }\n    // Default sort (by filepath, then project) is the fallback\n    return `${a.filepath}:${a.projectName}`.localeCompare(`${b.filepath}:${b.projectName}`)\n  })\n\n  return sorted\n}\n\nexport function createOrUpdateFileNode(\n  file: File,\n  collect = false,\n) {\n  let fileNode = explorerTree.nodes.get(file.id) as FileTreeNode | undefined\n\n  if (fileNode) {\n    fileNode.typecheck = !!file.meta && 'typecheck' in file.meta\n    fileNode.state = file.result?.state\n    fileNode.mode = file.mode\n    fileNode.duration = typeof file.result?.duration === 'number' ? Math.round(file.result.duration) : undefined\n    fileNode.slow = false\n    fileNode.collectDuration = file.collectDuration\n    fileNode.setupDuration = file.setupDuration\n    fileNode.environmentLoad = file.environmentLoad\n    fileNode.prepareDuration = file.prepareDuration\n  }\n  else {\n    fileNode = {\n      id: file.id,\n      parentId: 'root',\n      name: file.name,\n      mode: file.mode,\n      expandable: true,\n      // When the current run finish, we will expand all nodes when required, here we expand only the opened nodes\n      expanded: openedTreeItemsSet.value.size > 0 && openedTreeItemsSet.value.has(file.id),\n      type: 'file',\n      children: new Set(),\n      tasks: [],\n      typecheck: !!file.meta && 'typecheck' in file.meta,\n      indent: 0,\n      duration: typeof file.result?.duration === 'number' ? Math.round(file.result.duration) : undefined,\n      slow: false,\n      filepath: file.filepath,\n      projectName: file.projectName || '',\n      projectNameColor: explorerTree.colors.get(file.projectName || '') || getBadgeNameColor(file.projectName),\n      collectDuration: file.collectDuration,\n      setupDuration: file.setupDuration,\n      environmentLoad: file.environmentLoad,\n      prepareDuration: file.prepareDuration,\n      state: file.result?.state,\n    }\n    explorerTree.nodes.set(file.id, fileNode)\n    explorerTree.root.tasks.push(fileNode)\n  }\n  if (collect) {\n    for (let i = 0; i < file.tasks.length; i++) {\n      createOrUpdateNode(file.id, file.tasks[i], true)\n    }\n  }\n}\n\nexport function createOrUpdateSuiteTask(\n  id: string,\n  all: boolean,\n) {\n  const node = explorerTree.nodes.get(id)\n  if (!node || !isParentNode(node)) {\n    return\n  }\n\n  const task = client.state.idMap.get(id)\n  // if no children just return\n  if (!task || !isTaskSuite(task)) {\n    return\n  }\n\n  // update the node\n  createOrUpdateNode(node.parentId, task, all && task.tasks.length > 0)\n\n  return [node, task] as const\n}\n\nexport function createOrUpdateNodeTask(id: string) {\n  const node = explorerTree.nodes.get(id)\n  if (!node) {\n    return\n  }\n\n  const task = client.state.idMap.get(id)\n  // if it is not a test just return\n  if (!task || !isTestCase(task)) {\n    return\n  }\n\n  createOrUpdateNode(node.parentId, task, false)\n}\n\nexport function createOrUpdateNode(\n  parentId: string,\n  task: Task,\n  createAll: boolean,\n) {\n  const node = explorerTree.nodes.get(parentId) as ParentTreeNode | undefined\n  let taskNode: UITaskTreeNode | undefined\n  const duration = typeof task.result?.duration === 'number'\n    ? Math.round(task.result.duration)\n    : undefined\n  if (node) {\n    taskNode = explorerTree.nodes.get(task.id)\n    if (taskNode) {\n      if (!node.children.has(task.id)) {\n        node.tasks.push(taskNode)\n        node.children.add(task.id)\n      }\n\n      taskNode.name = task.name\n      taskNode.mode = task.mode\n      taskNode.duration = duration\n      taskNode.slow = isSlowTestTask(task)\n      taskNode.state = task.result?.state\n    }\n    else {\n      if (isTestCase(task)) {\n        taskNode = {\n          id: task.id,\n          fileId: task.file.id,\n          parentId,\n          name: task.name,\n          mode: task.mode,\n          type: task.type,\n          expandable: false,\n          expanded: false,\n          indent: node.indent + 1,\n          duration,\n          slow: isSlowTestTask(task),\n          state: task.result?.state,\n        } as TestTreeNode\n      }\n      else {\n        taskNode = {\n          id: task.id,\n          fileId: task.file.id,\n          parentId,\n          name: task.name,\n          mode: task.mode,\n          type: 'suite',\n          expandable: true,\n          // When the current run finish, we will expand all nodes when required, here we expand only the opened nodes\n          expanded: openedTreeItemsSet.value.size > 0 && openedTreeItemsSet.value.has(task.id),\n          children: new Set(),\n          tasks: [],\n          indent: node.indent + 1,\n          duration,\n          slow: false,\n          state: task.result?.state,\n        } as SuiteTreeNode\n      }\n      explorerTree.nodes.set(task.id, taskNode)\n      node.tasks.push(taskNode)\n      node.children.add(task.id)\n    }\n\n    if (taskNode && createAll && isTaskSuite(task)) {\n      for (let i = 0; i < task.tasks.length; i++) {\n        createOrUpdateNode(taskNode.id, task.tasks[i], createAll)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/ui/client/composables/index.ts",
    "content": "export * from './dark'\n"
  },
  {
    "path": "packages/ui/client/composables/location.ts",
    "content": "import type { RunnerTestCase, TestArtifactLocation } from 'vitest'\nimport { relative } from 'pathe'\nimport { config } from './client'\nimport { showAttachmentSource } from './codemirror'\n\nexport function openLocation(test: RunnerTestCase, location?: TestArtifactLocation) {\n  return showAttachmentSource(test, location)\n}\n\nexport function getLocationString(location: TestArtifactLocation) {\n  const root = config.value.root\n  const path = root ? relative(root, location.file) : location.file\n\n  return `${path}:${location.line}:${location.column}`\n}\n"
  },
  {
    "path": "packages/ui/client/composables/module-graph.ts",
    "content": "import type {\n  Graph,\n  GraphConfig,\n  GraphController,\n  GraphLink,\n  GraphNode,\n} from 'd3-graph-controller'\nimport type { ModuleGraphData } from 'vitest'\nimport { defineGraph, defineLink, defineNode } from 'd3-graph-controller'\nimport { calcExternalLabels, createModuleLabelItem } from '~/utils/task'\nimport { config } from './client'\n\nexport type ModuleType = 'external' | 'inline'\nexport type ModuleNode = GraphNode<ModuleType>\nexport type ModuleLink = GraphLink<ModuleType, ModuleNode>\nexport type ModuleGraph = Graph<ModuleType, ModuleNode, ModuleLink>\nexport type ModuleGraphController = GraphController<\n  ModuleType,\n  ModuleNode,\n  ModuleLink\n>\nexport type ModuleGraphConfig = GraphConfig<ModuleType, ModuleNode, ModuleLink>\n\nfunction defineExternalModuleNodes(modules: string[]): ModuleNode[] {\n  const labels = modules.map(module =>\n    createModuleLabelItem(module),\n  )\n  const map = calcExternalLabels(labels)\n  return labels.map(({ raw, id, splitted }) => {\n    return defineNode<ModuleType, ModuleNode>({\n      color: 'var(--color-node-external)',\n      label: {\n        color: 'var(--color-node-external)',\n        fontSize: '0.875rem',\n        text: id.includes('node_modules')\n          ? (map.get(raw) ?? raw)\n          : splitted[splitted.length - 1],\n      },\n      isFocused: false,\n      id,\n      type: 'external',\n    })\n  })\n}\n\nfunction defineInlineModuleNode(module: string, isRoot: boolean): ModuleNode {\n  return defineNode<ModuleType, ModuleNode>({\n    color: isRoot ? 'var(--color-node-root)' : 'var(--color-node-inline)',\n    label: {\n      color: isRoot ? 'var(--color-node-root)' : 'var(--color-node-inline)',\n      fontSize: '0.875rem',\n      text: module.split(/\\//g).pop()!,\n    },\n    isFocused: false,\n    id: module,\n    type: 'inline',\n  })\n}\n\nexport function getModuleGraph(\n  data: ModuleGraphData,\n  rootPath: string | undefined,\n): ModuleGraph {\n  if (!data) {\n    return defineGraph({})\n  }\n\n  const externalizedNodes = !config.value.experimental?.viteModuleRunner\n    ? defineExternalModuleNodes([...data.inlined, ...data.externalized])\n    : defineExternalModuleNodes(data.externalized)\n  const inlinedNodes\n    = !config.value.experimental?.viteModuleRunner\n      ? []\n      : data.inlined.map(module =>\n        defineInlineModuleNode(module, module === rootPath),\n      ) ?? []\n  const nodes = [...externalizedNodes, ...inlinedNodes]\n  const nodeMap = Object.fromEntries(nodes.map(node => [node.id, node]))\n  const links = Object.entries(data.graph).flatMap(\n    ([module, deps]) =>\n      deps\n        .map((dep) => {\n          const source = nodeMap[module]\n          const target = nodeMap[dep]\n          if (source === undefined || target === undefined) {\n            return undefined\n          }\n\n          return defineLink({\n            source,\n            target,\n            color: 'var(--color-link)',\n            label: false,\n          })\n        })\n        .filter(link => link !== undefined) as ModuleLink[],\n  )\n  return defineGraph({ nodes, links })\n}\n"
  },
  {
    "path": "packages/ui/client/composables/navigation.ts",
    "content": "import type { File, Task } from '@vitest/runner'\nimport type { Params } from './params'\nimport { useLocalStorage, watchOnce } from '@vueuse/core'\nimport { computed, nextTick, reactive, ref, watch } from 'vue'\nimport { viewport } from './browser'\nimport { browserState, client, config, findById } from './client'\nimport { testRunState } from './client/state'\nimport { showTaskSource } from './codemirror'\nimport { activeFileId, columnNumber, lineNumber, selectedTest, viewMode } from './params'\n\nexport const currentModule = ref<File>()\nexport const dashboardVisible = ref(true)\nexport const coverageVisible = ref(false)\nexport const disableCoverage = ref(true)\nexport const coverage = computed(() => config.value?.coverage)\nexport const coverageConfigured = computed(() => coverage.value?.enabled)\nexport const coverageEnabled = computed(() => {\n  return (\n    coverageConfigured.value\n    && !!coverage.value?.htmlDir\n  )\n})\nexport const mainSizes = useLocalStorage<[left: number, right: number]>(\n  'vitest-ui_splitpanes-mainSizes',\n  [33, 67],\n)\nexport const detailSizes = useLocalStorage<[left: number, right: number]>(\n  'vitest-ui_splitpanes-detailSizes',\n  [\n    // @ts-expect-error \"browserState\" is not initialised yet\n    window.__vitest_browser_runner__?.provider === 'webdriverio'\n      ? ((viewport.value[0] / window.outerWidth) * 100)\n      : 33,\n    67,\n  ],\n)\n\nexport const detailsPanelVisible = useLocalStorage<boolean>(\n  'vitest-ui_details-panel-visible',\n  true,\n)\n\nexport const detailsPosition = ref<'right' | 'bottom'>('right')\n\nnextTick(() => {\n  watch(config, () => {\n    if (config.value?.browser?.detailsPanelPosition) {\n      detailsPosition.value = config.value.browser.detailsPanelPosition\n    }\n  })\n})\n\nexport function hideDetailsPanel() {\n  // setTimeout is used to avoid splitpanes throwing a race condition error\n  setTimeout(() => {\n    detailsPanelVisible.value = false\n  }, 0)\n}\nexport function showDetailsPanel() {\n  detailsPanelVisible.value = true\n}\n\n// live sizes of panels in percentage\nexport const panels = reactive({\n  navigation: mainSizes.value[0],\n  details: {\n    size: mainSizes.value[1],\n    // these sizes are relative to the details panel\n    browser: detailSizes.value[0],\n    main: detailSizes.value[1],\n  },\n})\n\nwatch(\n  testRunState,\n  (state) => {\n    disableCoverage.value = state === 'running'\n  },\n  { immediate: true },\n)\n\nexport function initializeNavigation() {\n  const file = activeFileId.value\n  if (file && file.length > 0) {\n    const current = findById(file)\n    if (current) {\n      currentModule.value = current\n      dashboardVisible.value = false\n      coverageVisible.value = false\n    }\n    else {\n      watchOnce(\n        () => client.state.getFiles(),\n        () => {\n          currentModule.value = findById(file)\n          dashboardVisible.value = false\n          coverageVisible.value = false\n        },\n      )\n    }\n  }\n\n  return dashboardVisible\n}\n\nexport function showDashboard(show: boolean) {\n  dashboardVisible.value = show\n  coverageVisible.value = false\n  if (show) {\n    currentModule.value = undefined\n    activeFileId.value = ''\n  }\n}\n\nexport function navigateTo({ file, line, view, test, column }: Params) {\n  activeFileId.value = file\n  lineNumber.value = line\n  columnNumber.value = column\n  viewMode.value = view\n  selectedTest.value = test\n  currentModule.value = findById(file)\n  showDashboard(false)\n}\n\nexport function clickOnTask(task: Task) {\n  if (task.type === 'test') {\n    if (viewMode.value === 'editor') {\n      showTaskSource(task)\n    }\n    else {\n      navigateTo({\n        file: task.file.id,\n        line: null,\n        column: null,\n        view: viewMode.value,\n        test: task.id,\n      })\n    }\n  }\n  else {\n    navigateTo({\n      file: task.file.id,\n      test: null,\n      line: null,\n      view: viewMode.value,\n      column: null,\n    })\n  }\n}\n\nexport function showCoverage() {\n  coverageVisible.value = true\n  dashboardVisible.value = false\n  currentModule.value = undefined\n  activeFileId.value = ''\n}\n\nfunction calculateBrowserPanel() {\n  // we don't scale webdriverio provider because it doesn't support scaling\n  // TODO: find a way to make this universal - maybe show browser separately(?)\n  if (browserState?.provider === 'webdriverio') {\n    const parentWindow = window.outerWidth * (panels.details.size / 100)\n    // 40 is 20px padding for each sice\n    const tabWidth = ((viewport.value[0] + 20) / parentWindow) * 100\n    return tabWidth\n  }\n  return 33\n}\n\nexport function showNavigationPanel() {\n  panels.navigation = 33\n  panels.details.size = 67\n  mainSizes.value = [33, 67]\n}\n\nexport function updateBrowserPanel() {\n  // we don't need to change the size of the browser panel if the right\n  // panel is hidden\n  if (panels.details.main === 0) {\n    return\n  }\n\n  panels.details.browser = calculateBrowserPanel()\n  panels.details.main = 100 - panels.details.browser\n\n  detailSizes.value = [\n    panels.details.browser,\n    panels.details.main,\n  ]\n}\n\nexport function toggleDetailsPosition() {\n  detailsPosition.value = detailsPosition.value === 'right' ? 'bottom' : 'right'\n  // Reset to default sizes when changing orientation\n  const defaultSize = detailsPosition.value === 'bottom' ? 33 : 50\n  detailSizes.value = [defaultSize, 100 - defaultSize]\n  panels.details.browser = defaultSize\n  panels.details.main = 100 - defaultSize\n}\n"
  },
  {
    "path": "packages/ui/client/composables/params.ts",
    "content": "import { toRef, useUrlSearchParams } from '@vueuse/core'\n\nexport interface Params {\n  file: string\n  view: null | 'graph' | 'editor' | 'console'\n  line: null | number\n  test: null | string\n  column: null | number\n}\n\nexport const params = useUrlSearchParams<Params>('hash', {\n  initialValue: {\n    file: '',\n    view: null,\n    line: null,\n    test: null,\n    column: null,\n  },\n})\n\nexport const activeFileId = toRef(params, 'file')\nexport const viewMode = toRef(params, 'view')\nexport const lineNumber = toRef(params, 'line')\nexport const columnNumber = toRef(params, 'column')\nexport const selectedTest = toRef(params, 'test')\n"
  },
  {
    "path": "packages/ui/client/composables/small-tabs.ts",
    "content": "import type { InjectionKey, Ref } from 'vue'\n\nexport interface SmallTabsConfig {\n  id: string\n  title: string\n}\n\nexport interface SmallTabsContext {\n  id: string\n  activeTab: Ref<string | null>\n  registerTab: (tab: SmallTabsConfig) => void\n  unregisterTab: (tab: SmallTabsConfig) => void\n}\n\nexport const SMALL_TABS_CONTEXT: InjectionKey<SmallTabsContext> = Symbol('tabContext')\n\nexport const idFor = {\n  tab: (id: SmallTabsConfig['id'], globalContext: SmallTabsContext['id']) =>\n    `${globalContext}-${id}-tab`,\n  tabpanel: (id: SmallTabsConfig['id'], globalContext: SmallTabsContext['id']) =>\n    `${globalContext}-${id}-tabpanel`,\n}\n"
  },
  {
    "path": "packages/ui/client/constants.ts",
    "content": "export const PORT = import.meta.hot ? (import.meta.env.VITE_PORT || '51204') : location.port\nexport const HOST = [location.hostname, PORT].filter(Boolean).join(':')\nexport const ENTRY_URL = `${\n  location.protocol === 'https:' ? 'wss:' : 'ws:'\n}//${HOST}/__vitest_api__?token=${(window as any).VITEST_API_TOKEN || '0'}`\nexport const isReport = !!window.METADATA_PATH\nexport const BASE_PATH = isReport ? import.meta.env.BASE_URL : __BASE_PATH__\n"
  },
  {
    "path": "packages/ui/client/global-setup.ts",
    "content": "/// <reference types=\"vite-plugin-pages/client\" />\n\nimport type { Directive } from 'vue'\nimport FloatingVue, { vTooltip } from 'floating-vue'\nimport routes from 'virtual:generated-pages'\nimport {\n  createRouter as _createRouter,\n  createWebHashHistory,\n} from 'vue-router'\nimport 'd3-graph-controller/default.css'\nimport 'splitpanes/dist/splitpanes.css'\nimport '@unocss/reset/tailwind.css'\nimport 'codemirror/lib/codemirror.css'\nimport 'codemirror-theme-vars/base.css'\nimport './styles/main.css'\nimport 'floating-vue/dist/style.css'\nimport 'uno.css'\n\nexport const directives: Record<string, Directive> = {\n  tooltip: vTooltip,\n}\n\nFloatingVue.options.instantMove = true\nFloatingVue.options.distance = 10\n\nexport function createRouter() {\n  return _createRouter({\n    history: createWebHashHistory(),\n    routes,\n  })\n}\n\nexport const plugins = [createRouter]\n"
  },
  {
    "path": "packages/ui/client/main.ts",
    "content": "import { createApp } from 'vue'\nimport App from './App.vue'\nimport { directives, plugins } from './global-setup'\n\nconst app = createApp(App)\n\nplugins.forEach((plugin) => {\n  app.use(plugin())\n})\n\nObject.entries(directives).forEach(([name, directive]) => {\n  app.directive(name, directive)\n})\n\napp.mount('#app')\n"
  },
  {
    "path": "packages/ui/client/pages/index.vue",
    "content": "<script setup lang=\"ts\">\nimport { useDebounceFn } from '@vueuse/core'\n// @ts-expect-error missing types\nimport { Pane, Splitpanes } from 'splitpanes'\nimport BrowserIframe from '~/components/BrowserIframe.vue'\nimport ClosedDetailsHeader from '~/components/ClosedDetailsHeader.vue'\nimport ConnectionOverlay from '~/components/ConnectionOverlay.vue'\nimport Coverage from '~/components/Coverage.vue'\nimport Dashboard from '~/components/Dashboard.vue'\nimport FileDetails from '~/components/FileDetails.vue'\nimport Navigation from '~/components/Navigation.vue'\nimport ProgressBar from '~/components/ProgressBar.vue'\nimport { browserState } from '~/composables/client'\nimport {\n  coverageVisible,\n  detailSizes,\n  detailsPanelVisible,\n  detailsPosition,\n  initializeNavigation,\n  mainSizes,\n  panels,\n} from '~/composables/navigation'\n\nconst dashboardVisible = initializeNavigation()\n\nconst onBrowserPanelResizing = useDebounceFn(({ panes }: { panes: { size: number }[] }) => {\n  // don't trigger events in the iframe while resizing\n  preventBrowserEvents()\n  recordDetailsResize(panes)\n}, 0)\n\nconst onMainResized = useDebounceFn(({ panes }: { panes: { size: number }[] }) => {\n  panes.forEach((e, i) => {\n    mainSizes.value[i] = e.size\n  })\n  recordMainResize(panes)\n  allowBrowserEvents()\n}, 0)\n\nconst onModuleResized = useDebounceFn(({ panes }: { panes: { size: number }[] }) => {\n  panes.forEach((e, i) => {\n    detailSizes.value[i] = e.size\n  })\n  recordDetailsResize(panes)\n  allowBrowserEvents()\n}, 0)\n\nconst resizingMain = useDebounceFn(({ panes }: { panes: { size: number }[] }) => {\n  recordMainResize(panes)\n  preventBrowserEvents()\n}, 0)\n\nfunction recordMainResize(panes: { size: number }[]) {\n  panels.navigation = panes[0].size\n  if (panes[1]) {\n    panels.details.size = panes[1].size\n  }\n}\n\nfunction recordDetailsResize(panes: { size: number }[]) {\n  panels.details.browser = panes[0].size\n  if (panes[1]) {\n    panels.details.main = panes[1].size\n  }\n}\n\nfunction preventBrowserEvents() {\n  const tester = document.querySelector<HTMLDivElement>('#tester-ui')\n  if (tester) {\n    tester.style.pointerEvents = 'none'\n  }\n}\n\nfunction allowBrowserEvents() {\n  const tester = document.querySelector<HTMLDivElement>('#tester-ui')\n  if (tester) {\n    tester.style.pointerEvents = ''\n  }\n}\n</script>\n\n<template>\n  <ProgressBar />\n  <div h-screen w-screen overflow=\"hidden\">\n    <Splitpanes\n      class=\"pt-4px\"\n      @resized=\"onMainResized\"\n      @resize=\"resizingMain\"\n    >\n      <Pane :size=\"mainSizes[0]\">\n        <Navigation />\n      </Pane>\n      <Pane :size=\"mainSizes[1]\">\n        <transition v-if=\"!browserState\" key=\"ui-detail\">\n          <Dashboard v-if=\"dashboardVisible\" key=\"summary\" />\n          <Coverage\n            v-else-if=\"coverageVisible\"\n            key=\"coverage\"\n          />\n          <FileDetails v-else key=\"details\" />\n        </transition>\n        <template v-else>\n          <div\n            flex=\"~ col\"\n            h-full\n          >\n            <Splitpanes\n              id=\"details-splitpanes\"\n              key=\"browser-detail\"\n              :horizontal=\"detailsPosition === 'bottom'\"\n              :class=\"detailsPosition === 'bottom' && !detailsPanelVisible ? 'flex-1 min-h-0 overflow-hidden' : 'h-full'\"\n              @resize=\"onBrowserPanelResizing\"\n              @resized=\"onModuleResized\"\n            >\n              <Pane :size=\"detailSizes[0]\" min-size=\"10\">\n                <BrowserIframe v-once />\n              </Pane>\n              <Pane\n                v-if=\"detailsPanelVisible\"\n                :size=\"detailSizes[1]\"\n                min-size=\"10\"\n              >\n                <div h-full overflow-hidden>\n                  <Dashboard v-if=\"dashboardVisible\" key=\"summary\" />\n                  <Coverage\n                    v-else-if=\"coverageVisible\"\n                    key=\"coverage\"\n                  />\n                  <FileDetails v-else key=\"details\" />\n                </div>\n              </Pane>\n            </Splitpanes>\n            <ClosedDetailsHeader\n              v-if=\"detailsPosition === 'bottom' && !detailsPanelVisible\"\n            />\n          </div>\n        </template>\n      </Pane>\n    </Splitpanes>\n  </div>\n  <ConnectionOverlay />\n</template>\n"
  },
  {
    "path": "packages/ui/client/shim.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n/// <reference types=\"vite-plugin-pages/client\" />\n\nconst __BASE_PATH__: string\n\ndeclare interface Window {\n  METADATA_PATH?: string\n}\n\ndeclare interface Error {\n  VITEST_TEST_NAME?: string\n  VITEST_TEST_PATH?: string\n}\n"
  },
  {
    "path": "packages/ui/client/styles/main.css",
    "content": "html,\nbody {\n  height: 100%;\n  font-family: \"Readex Pro\", sans-serif;\n  scroll-behavior: smooth;\n}\n\n:root {\n  --color-text-light: #000;\n  --color-text-dark: #ddd;\n  --color-text: var(--color-text-light);\n  --background-color: #e4e4e4;\n}\n\nhtml.dark {\n  --color-text: var(--color-text-dark);\n  --background-color: #141414;\n  color: var(--color-text);\n  background-color: var(--background-color);\n  color-scheme: dark;\n}\n\n.CodeMirror {\n  height: 100% !important;\n  width: 100% !important;\n  font-family: inherit;\n}\n\n.cm-s-vars .cm-tag {\n  color: var(--cm-keyword);\n}\n\n:root {\n  --cm-foreground: #393a3480;\n  --cm-background: transparent;\n  --cm-comment: #a0ada0;\n  --cm-string: #b56959;\n  --cm-literal: #2f8a89;\n  --cm-number: #296aa3;\n  --cm-keyword: #1c6b48;\n  --cm-function: #6c7834;\n  --cm-boolean: #1c6b48;\n  --cm-constant: #a65e2b;\n  --cm-deleted: #a14f55;\n  --cm-class: #2993a3;\n  --cm-builtin: #ab5959;\n  --cm-property: #b58451;\n  --cm-namespace: #b05a78;\n  --cm-punctuation: #8e8f8b;\n  --cm-decorator: #bd8f8f;\n  --cm-regex: #ab5e3f;\n  --cm-json-property: #698c96;\n  --cm-line-number-gutter: #f8f8f8;\n  /* scrollbars colors */\n  --cm-ttc-c-thumb: #eee;\n  --cm-ttc-c-track: white;\n}\n\nhtml.dark {\n  --cm-scheme: dark;\n  --cm-foreground: #d4cfbf80;\n  --cm-background: transparent;\n  --cm-comment: #758575;\n  --cm-string: #d48372;\n  --cm-literal: #429988;\n  --cm-keyword: #4d9375;\n  --cm-boolean: #1c6b48;\n  --cm-number: #6394bf;\n  --cm-variable: #c2b36e;\n  --cm-function: #a1b567;\n  --cm-deleted: #a14f55;\n  --cm-class: #54b1bf;\n  --cm-builtin: #e0a569;\n  --cm-property: #dd8e6e;\n  --cm-namespace: #db889a;\n  --cm-punctuation: #858585;\n  --cm-decorator: #bd8f8f;\n  --cm-regex: #ab5e3f;\n  --cm-json-property: #6b8b9e;\n  --cm-line-number: #888888;\n  --cm-line-number-gutter: #161616;\n  --cm-line-highlight-background: #444444;\n  --cm-selection-background: #44444450;\n  /* scrollbars colors */\n  --cm-ttc-c-thumb: #222;\n  --cm-ttc-c-track: #111;\n}\n\n.splitpanes__pane {\n  background-color: unset !important;\n}\n\n.splitpanes__splitter {\n  position: relative;\n  background-color: rgba(125, 125, 125, 0.1);\n  z-index: 10;\n}\n\n.splitpanes__splitter:before {\n  content: \"\";\n  position: absolute;\n  left: 0;\n  top: 0;\n  transition: opacity 0.4s;\n  background-color: rgba(125, 125, 125, 0.1);\n  opacity: 0;\n  z-index: 1;\n}\n\n.splitpanes__splitter:hover:before {\n  opacity: 1;\n}\n\n.splitpanes--vertical > .splitpanes__splitter:before {\n  /* make vertical scroll usable */\n  left: 0;\n  right: -10px;\n  height: 100%;\n}\n\n.splitpanes--horizontal > .splitpanes__splitter:before {\n  top: 0;\n  bottom: -10px;\n  width: 100%;\n}\n\n.splitpanes.loading .splitpanes__pane {\n  transition: none !important;\n  height: 100%;\n}\n\n/* CODEMIRROR SCROLLS */\n.CodeMirror-scroll {\n  /* hide FF native scrolls */\n  scrollbar-width: none;\n}\n.CodeMirror-scroll::-webkit-scrollbar,\n.codemirror-scrolls::-webkit-scrollbar {\n  display: none;\n}\n.codemirror-scrolls {\n  overflow: auto !important;\n  scrollbar-width: thin;\n  scrollbar-color: var(--cm-ttc-c-thumb) var(--cm-ttc-c-track);\n}\n/* the horizontal/vertical background */\n.CodeMirror-simplescroll-horizontal,\n.CodeMirror-simplescroll-vertical {\n  background-color: var(--cm-ttc-c-track) !important;\n  border: none !important;\n}\n/* the horizontal/vertical bubble background */\n.CodeMirror-simplescroll-horizontal div,\n.CodeMirror-simplescroll-vertical div {\n  background-color: var(--cm-ttc-c-thumb) !important;\n  border: none !important;\n}\n/* the right bottom corner background*/\n.CodeMirror-scrollbar-filler,\n.CodeMirror-gutter-filler {\n  background-color: var(--cm-ttc-c-track) !important;\n}\n.CodeMirror {\n  overflow: unset !important;\n}\n.CodeMirror-vscrollbar,\n.CodeMirror-hscrollbar {\n  display: none !important;\n}\n.CodeMirror-scroll {\n  margin-bottom: unset !important;\n  margin-right: unset !important;\n  padding-bottom: unset !important;\n}\n/* END CODEMIRROR SCROLLS */\n\n/* SCROLLS */\n.scrolls::-webkit-scrollbar {\n  width: 8px;\n  height: 8px;\n}\n.scrolls {\n  overflow: auto !important;\n  scrollbar-width: thin;\n  scrollbar-color: var(--cm-ttc-c-thumb) var(--cm-ttc-c-track);\n}\n.scrolls::-webkit-scrollbar-track {\n  background: var(--cm-ttc-c-track);\n}\n.scrolls::-webkit-scrollbar-thumb {\n  background-color: var(--cm-ttc-c-thumb);\n  border: 2px solid var(--cm-ttc-c-thumb);\n}\n.scrolls::-webkit-scrollbar-thumb,\n.scrolls-rounded::-webkit-scrollbar-track {\n  border-radius: 3px;\n}\n.scrolls::-webkit-scrollbar-corner {\n  background-color: var(--cm-ttc-c-track);\n}\n/* END SCROLLS */\n\n.v-popper__popper .v-popper__inner {\n  font-size: 12px;\n  padding: 4px 6px;\n  border-radius: 4px;\n  background-color: var(--background-color);\n  color: var(--color-text);\n}\n\n.v-popper__popper .v-popper__arrow-outer {\n  border-color: var(--background-color);\n}\n\n.codemirror-busy > .CodeMirror > .CodeMirror-scroll > .CodeMirror-sizer .CodeMirror-lines {\n  cursor: wait !important;\n}\n"
  },
  {
    "path": "packages/ui/client/test.ts",
    "content": "import type { ComponentRenderOptions } from 'vitest-browser-vue'\nimport { vTooltip } from 'floating-vue'\nimport {\n  render as _render,\n} from 'vitest-browser-vue'\n\nexport { page } from 'vitest/browser'\n\nexport function render<C>(component: C, options?: ComponentRenderOptions<C, any>) {\n  return _render(component, {\n    ...options,\n    global: {\n      directives: {\n        tooltip: vTooltip,\n      },\n    },\n  })\n}\n"
  },
  {
    "path": "packages/ui/client/utils/escape.ts",
    "content": "export function escapeHtml(unsafe: string) {\n  return unsafe\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&#39;')\n}\n"
  },
  {
    "path": "packages/ui/client/utils/task.ts",
    "content": "import type { RunnerTask, RunnerTestSuite } from 'vitest'\nimport { isDark } from '~/composables'\n\nexport function isSuite(task: RunnerTask): task is RunnerTestSuite {\n  return Object.hasOwn(task, 'tasks')\n}\n\nexport function isTaskDone(task: RunnerTask) {\n  const state = task.result?.state\n  const mode = task.mode\n\n  return state === 'pass' || state === 'fail' || state === 'skip' || mode === 'skip' || mode === 'todo'\n}\n\nexport function caseInsensitiveMatch(target: string, str2: string) {\n  if (typeof target !== 'string' || typeof str2 !== 'string') {\n    return false\n  }\n  return target.toLowerCase().includes(str2.toLowerCase())\n}\n\nexport function formatTime(time: number): string {\n  if (time > 1000) {\n    return `${(time / 1000).toFixed(2)}s`\n  }\n  return `${Math.round(time)}ms`\n}\n\nexport function formatPreciseTime(time: number): string {\n  if (time > 1000) {\n    return `${(time / 1000).toFixed(2)}s`\n  }\n  return `${time.toFixed(2)}ms`\n}\n\nexport interface ModuleLabelItem {\n  id: string\n  raw: string\n  splits: string[]\n  readonly splitted: string[]\n  candidate: string\n  finished: boolean\n}\n\nexport function calcExternalLabels(\n  labels: ModuleLabelItem[],\n): Map<string, string> {\n  const result: Map<string, string> = new Map()\n  const splitMap: Map<string, number[]> = new Map()\n  const firsts: number[] = []\n  while (true) {\n    let finishedCount = 0\n    labels.forEach((label, i) => {\n      const { splits, finished } = label\n      // record the candidate as final label text when label is marked finished\n      if (finished) {\n        finishedCount++\n        const { raw, candidate } = label\n        result.set(raw, candidate)\n        return\n      }\n      if (splits.length === 0) {\n        label.finished = true\n        return\n      }\n      const head = splits[0]\n      if (splitMap.has(head)) {\n        label.candidate += label.candidate === '' ? head : `/${head}`\n        splitMap.get(head)?.push(i)\n        splits.shift()\n      }\n      else {\n        splitMap.set(head, [i])\n        // record the index of the label where the head first appears\n        firsts.push(i)\n      }\n    })\n    // update candidate of label which index appears in first array\n    firsts.forEach((i) => {\n      const label = labels[i]\n      const head = label.splits.shift()\n      label.candidate += label.candidate === '' ? head : `/${head}`\n    })\n    splitMap.forEach((value) => {\n      if (value.length === 1) {\n        const index = value[0]\n        labels[index].finished = true\n      }\n    })\n    splitMap.clear()\n    firsts.length = 0\n    if (finishedCount === labels.length) {\n      break\n    }\n  }\n  return result\n}\n\nexport function createModuleLabelItem(module: string): ModuleLabelItem {\n  let raw = module\n  if (raw.includes('/node_modules/')) {\n    raw = module.split(/\\/node_modules\\//g).pop()!\n  }\n  const splits = raw.split(/\\//g)\n  return {\n    raw,\n    splits,\n    splitted: [...splits],\n    candidate: '',\n    finished: false,\n    id: module,\n  }\n}\n\nexport function getExternalModuleName(module: string) {\n  const label = createModuleLabelItem(module)\n  return label.raw\n}\n\nexport function getImportDurationType(duration: number) {\n  if (duration >= 500) {\n    return 'danger'\n  }\n  if (duration >= 100) {\n    return 'warning'\n  }\n}\n\nexport function getDurationClass(duration: number) {\n  const type = getImportDurationType(duration)\n  if (type === 'danger') {\n    return 'text-red'\n  }\n  if (type === 'warning') {\n    return 'text-orange'\n  }\n}\n\nexport function getBadgeNameColor(name: string | undefined, transparent = false) {\n  if (!name) {\n    return ''\n  }\n  const index = name\n    .split('')\n    .reduce((acc, v, idx) => acc + v.charCodeAt(0) + idx, 0)\n  const colors = isDark.value\n    ? ['yellow', 'cyan', '#006800', 'magenta']\n    : ['#ff5400', '#02a4a4', 'green', 'magenta']\n  const transparentColors = isDark.value\n    ? ['#ffff0091', '#0ff6', '#5dbb5dc9', '#ff00ff80']\n    : ['#ff540091', '#00828266', '#5dbb5dc9', '#ff00ff80']\n  return (transparent ? transparentColors : colors)[index % colors.length]\n}\n\nexport function getBadgeTextColor(color: string) {\n  switch (color) {\n    case 'blue':\n    case 'green':\n    case 'magenta':\n    case 'black':\n    case 'red':\n      return 'white'\n\n    case 'yellow':\n    case 'cyan':\n    case 'white':\n    default:\n      return 'black'\n  }\n}\n"
  },
  {
    "path": "packages/ui/explorer.md",
    "content": "# Explorer Overall Behavior\n\nThis document describes the overall behavior of the new Explorer component and the logic for:\n- searching\n- expanding/collapsing nodes\n- filtering by status\n- `Test Only` filter\n\nCheck [Notes](#notes) for a brief summary about the old and the new logic.\n\n## New Logic\n\nThe explorer will not use the `idsMap` and `filesMap` directly from the `ws-client` state to render the tree. It will use new types to represent the tree in the ui, and a new logic to handle the tree list in the DOM:\n- [nodes](client/composables/explorer/tree.ts): changes in the `ws-client` state will be mapped here with tree structure.\n- [uiEntries](client/composables/explorer/state.ts): a shallow ref to represent the flat tree entries in the ui, the logic will use `nodes` to build it.\n\nAny operation in the explorer using `queueMicrotask` to avoid blocking the main thread, and any operation on list/map using `generators`.\n\nThe explorer logic splits the actions in three main parts:\n- collecting tasks while running the tests\n- searching/filtering: hereinafter searching for simplicity\n- expanding/collapsing nodes\n\nWhereas collecting and searching are complex operations, expanding/collapsing nodes is a simple operation. Why?:\n- collecting tasks: we need to traverse the full tree to update every test/suite/file in the ui tree: we're collecting `ws-client` messages from the server, and the nodes in the ui must be updated to reflect the state.\n- searching: we need to traverse the full tree to collect every test/suite/file in the tree matching applied search and/or the filter.\n- expanding/collapsing: simple operation that only requires traversing nodes present in the ui switching the `expanded` property (_expanding all nodes requires full search_).\n\n### Collecting tasks\n\nOld [ws-client](client/composables/client/index.ts) logic was traversing the full tree to update all the nodes in the ui on every `onTaskUpdate` callback (was using reactive `idsMap` in the `ws-client` state).\nThe new logic will traverse only the task files in the task result provided in the `onTaskUpdate` callback, that's a huge improvement in performance.\n\nThe main change in the new logic is about using `requestAnimationFrame` to collect ui updates every 100ms, collecting all changes received in `onTaskUpdate` callback. On every loop, the [uiEntries](client/composables/state.ts) will be recreated with collected changes, the virtual scroller will handle the updates properly.\n\nThe logic is implemented in [collect](client/composables/explorer/collector.ts) function and the `requestAnimationFrame` loop configured in the [tree class](client/composables/explorer/tree.ts), `runCollect` function.\n\n### Searching\n\nSearch and filtering are quite simple, we only need to apply some logic to the task name, mode and result state.\nThe complexity lies in filtering the nodes of the entire tree. We need to traverse the tree several times:\n- from top to bottom to collect all tasks matching the search/filter criteria (full tree): `visitNodes` function in the [filter](client/composables/explorer/filter.ts) module.\n- from bottom to top to collect tasks and parent tasks containing children matching the search/filter criteria (full tree): `filterParents` in the [filter](client/composables/explorer/filter.ts) module.\n- from top to bottom to collect parent tasks for expanded files tasks, or parent tasks whose parent tasks are expanded (filtered tree from the previous step).\n- from top to button to collect tasks that are files, or the parent task included in the previous list and expanded (filtered tree).\n\nThe main logic is the `expandNode` function in the [filter](client/composables/explorer/filter.ts) module, will apply previous logic.\n\nThe search logic can be found in [filter](client/composables/explorer/filter.ts) module.\n\n### Collapsing nodes\n\nThis is the cheapest operation in the explorer, it only requires traversing the nodes in the ui and updating the `expanded` property:\n- collapsing all nodes: traverse the full tree ([nodes](client/composables/explorer/tree.ts) in the explorer tree) and set `expanded` to `false`, then filter the `uiEntries` by `file` type.\n- collapsing a single node: traverse the full tree and set `expanded` to `false` for the node and all its children, and replace the child in the `uiEntries` with the new collapsed one, removing its children from `uiEntries`.\n\nThe actions can be found in the [tree class](client/composables/explorer/tree.ts), `collapseAllNodes` and `collapseNode` methods, and the logic in the [collapse.ts](client/composables/explorer/collapse.ts) module.\n\n### Expanding nodes\n\nThis is also an affordable operation in the explorer, it only requires traversing the nodes in the ui and updating the `expanded` property:\n- collapsing all nodes: traverse the full tree ([nodes](client/composables/explorer/tree.ts) in the explorer tree) and set `expanded` to `true`, then rebuild the `uiEntries` using `filterAll` in the `search` module.\n- expanding single node: traverse its children in the ui ([nodes](client/composables/explorer/tree.ts) in the explorer tree) and set `expanded` to `true`, then filter its children using `filterNode` in the `search` module, and rebuild `uiEntries` replacing the current node in the ui tree with the new node and its filtered children.\n\nThe actions can be found in the [tree class](client/composables/explorer/tree.ts), `expandAllNodes` and `expandNode` methods, and the logic in the [expand.ts](client/composables/explorer/expand.ts) module.\n\n## Notes\n\nThe previous tree list approach was using a nested structure to map the tree rendering the full tree in the DOM. It was using the entries from the WebSocket client state (`idsMap` and `filesMap`), using Vue reactive for both maps. Since we updated Vue dependency to latest v3.4.27, every message received from the server was updating the corresponding entries in the maps. The tree list was being updated accordingly, firing a lot of patch updates in the vue components in the recursive tree, which was causing performance issues.\n\nThe new Explorer is using a flat structure to represent the tree via virtual scroller (`vue-virtual-scroller`). This new structure is easier to handle and manipulate, and it's also a performance improvement since the virtual scroller will update only a few nodes in the ui and not the full tree in the DOM.\nIt is using a new approach to handle the tree list, now we have a separated vue shallow ref for entries in the ui ([uiEntries in composables/explorer/state.ts](client/composables/explorer/state.ts)), and the WebSocket state using vue shallow ref for both, `idsMap` and `filesMap`, while keeping the state itself with Vue reactive.\nNow we are able to update the tree list only when the entries are updated and not when the WebSocket state is updated, which is a huge performance improvement.\n\nSome numbers running `test/core` with Vitest UI (162 files with 3 workspaces: 5100+ tests) in a `i7-12700H` laptop:\n- tree list: after server finishing running the tests, Vitest UI took ~1 minute to finish rendering the full tree (~150MB of memory usage)\n- explorer: Vitest UI finishing rendering the full tree before the server reporter shows the tests summary (~10MB of memory usage)\n\nExpanding/collapsing nodes or searching with tree list approach is blocking the main thread, while with the new explorer, it's not blocking the main thread anymore, it is just instant.\n\nWhereas the new explorer will not be affected by the number of tests, the number of tests affected the tree list approach, the more tests, the slower the ui was.\nAnyway, on really huge projects, both approaches will have performance issues, but the new explorer will be much better than the tree list approach (`vue-virtual-scroller` should be fine using ~500_000 entries, check the docs).\n"
  },
  {
    "path": "packages/ui/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"/favicon.ico\" sizes=\"48x48\">\n    <link rel=\"icon\" href=\"/favicon.svg\" sizes=\"any\" type=\"image/svg+xml\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vitest</title>\n    <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n    <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n    <link\n      href=\"https://fonts.googleapis.com/css2?family=Readex+Pro:wght@300;400&display=swap\"\n      rel=\"stylesheet\"\n    />\n    <script>\n      (function () {\n        const prefersDark =\n          window.matchMedia &&\n          window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n        const setting = localStorage.getItem(\"vueuse-color-scheme\") || \"auto\";\n        if (setting === \"dark\" || (prefersDark && setting !== \"light\"))\n          document.documentElement.classList.toggle(\"dark\", true);\n      })();\n    </script>\n    <!-- !LOAD_METADATA! -->\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/client/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/ui/node/index.ts",
    "content": "import type { Plugin } from 'vite'\nimport type { Vitest } from 'vitest/node'\nimport fs from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { join, resolve } from 'pathe'\nimport sirv from 'sirv'\nimport c from 'tinyrainbow'\nimport { isFileServingAllowed, isValidApiRequest } from 'vitest/node'\nimport { version } from '../package.json'\n\nexport default (ctx: Vitest): Plugin => {\n  if (ctx.version !== version) {\n    ctx.logger.warn(\n      c.yellow(\n        `Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/ui@${version} `))}.`\n        + '\\nRunning mixed versions is not supported and may lead into bugs'\n        + '\\nUpdate your dependencies and make sure the versions match.',\n      ),\n    )\n  }\n\n  return <Plugin>{\n    name: 'vitest:ui',\n    apply: 'serve',\n    configureServer: {\n      order: 'post',\n      handler(server) {\n        const uiOptions = ctx.config\n        const base = uiOptions.uiBase\n\n        // Serve coverage HTML at ./coverage if configured\n        const coverageHtmlDir = ctx.config.coverage?.htmlDir\n        if (coverageHtmlDir) {\n          server.middlewares.use(\n            join(base, 'coverage'),\n            sirv(coverageHtmlDir, {\n              single: true,\n              dev: true,\n              setHeaders: (res) => {\n                res.setHeader(\n                  'Cache-Control',\n                  'public,max-age=0,must-revalidate',\n                )\n              },\n            }),\n          )\n        }\n\n        const clientDist = resolve(fileURLToPath(import.meta.url), '../client')\n        const clientIndexHtml = fs.readFileSync(resolve(clientDist, 'index.html'), 'utf-8')\n\n        // eslint-disable-next-line prefer-arrow-callback\n        server.middlewares.use(function vitestAttachment(req, res, next) {\n          if (!req.url) {\n            return next()\n          }\n\n          const url = new URL(req.url, 'http://localhost')\n          if (url.pathname === '/__vitest_attachment__') {\n            const path = url.searchParams.get('path')\n            const contentType = url.searchParams.get('contentType')\n\n            // ignore invalid requests\n            if (!isValidApiRequest(ctx.config, req) || !contentType || !path) {\n              return next()\n            }\n\n            const fsPath = decodeURIComponent(path)\n\n            if (!isFileServingAllowed(ctx.vite.config, fsPath)) {\n              return next()\n            }\n\n            try {\n              res.writeHead(200, {\n                'content-type': contentType,\n              })\n              fs.createReadStream(fsPath)\n                .pipe(res)\n                .on('close', () => res.end())\n            }\n            catch (err) {\n              next(err)\n            }\n          }\n          else {\n            next()\n          }\n        })\n\n        // serve index.html with api token\n        // eslint-disable-next-line prefer-arrow-callback\n        server.middlewares.use(function vitestUiHtmlMiddleware(req, res, next) {\n          if (req.url) {\n            const url = new URL(req.url, 'http://localhost')\n            if (url.pathname === base) {\n              const html = clientIndexHtml.replace(\n                '<!-- !LOAD_METADATA! -->',\n                `<script>window.VITEST_API_TOKEN = ${JSON.stringify(ctx.config.api.token)}</script>`,\n              )\n              res.setHeader('Cache-Control', 'no-cache, max-age=0, must-revalidate')\n              res.setHeader('Content-Type', 'text/html; charset=utf-8')\n              res.write(html)\n              res.end()\n              return\n            }\n          }\n          next()\n        })\n\n        server.middlewares.use(\n          base,\n          sirv(clientDist, {\n            single: true,\n            dev: true,\n          }),\n        )\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "packages/ui/node/reporter.ts",
    "content": "import type { ModuleGraphData, RunnerTestFile, SerializedConfig } from 'vitest'\nimport type { HTMLOptions, Reporter, Vitest } from 'vitest/node'\nimport { existsSync, promises as fs } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { promisify } from 'node:util'\nimport { gzip, constants as zlibConstants } from 'node:zlib'\nimport { stringify } from 'flatted'\nimport { dirname, relative, resolve } from 'pathe'\nimport { globSync } from 'tinyglobby'\nimport c from 'tinyrainbow'\nimport { getModuleGraph } from '../../vitest/src/utils/graph'\n\ninterface PotentialConfig {\n  outputFile?: string | Partial<Record<string, string>>\n}\n\nfunction getOutputFile(config: PotentialConfig | undefined) {\n  if (!config?.outputFile) {\n    return\n  }\n\n  if (typeof config.outputFile === 'string') {\n    return config.outputFile\n  }\n\n  return config.outputFile.html\n}\n\ninterface HTMLReportData {\n  paths: string[]\n  files: RunnerTestFile[]\n  config: SerializedConfig\n  projects: string[]\n  moduleGraph: Record<string, Record<string, ModuleGraphData>>\n  unhandledErrors: unknown[]\n  // filename -> source\n  sources: Record<string, string>\n}\n\nconst distDir = resolve(fileURLToPath(import.meta.url), '../../dist')\n\nexport default class HTMLReporter implements Reporter {\n  start = 0\n  ctx!: Vitest\n  options: HTMLOptions\n\n  private reporterDir!: string\n  private htmlFilePath!: string\n\n  constructor(options: HTMLOptions) {\n    this.options = options\n  }\n\n  async onInit(ctx: Vitest): Promise<void> {\n    this.ctx = ctx\n    this.start = Date.now()\n    const htmlFile\n      = this.options.outputFile\n        || getOutputFile(this.ctx.config)\n        || 'html/index.html'\n    const htmlFilePath = resolve(this.ctx.config.root, htmlFile)\n    this.reporterDir = dirname(htmlFilePath)\n    this.htmlFilePath = htmlFilePath\n\n    await fs.mkdir(resolve(this.reporterDir, 'assets'), { recursive: true })\n  }\n\n  async onTestRunEnd(): Promise<void> {\n    const result: HTMLReportData = {\n      paths: this.ctx.state.getPaths(),\n      files: this.ctx.state.getFiles(),\n      config: this.ctx.getRootProject().serializedConfig,\n      unhandledErrors: this.ctx.state.getUnhandledErrors(),\n      projects: this.ctx.projects.map(p => p.name),\n      moduleGraph: {},\n      sources: {},\n    }\n    const promises: Promise<void>[] = []\n\n    promises.push(...result.files.map(async (file) => {\n      const projectName = file.projectName || ''\n      const resolvedConfig = this.ctx.getProjectByName(projectName).config\n      const browser = resolvedConfig.browser.enabled\n      result.moduleGraph[projectName] ??= {}\n      result.moduleGraph[projectName][file.filepath] = await getModuleGraph(\n        this.ctx,\n        projectName,\n        file.filepath,\n        browser,\n      )\n      if (!result.sources[file.filepath]) {\n        try {\n          result.sources[file.filepath] = await fs.readFile(file.filepath, {\n            encoding: 'utf-8',\n          })\n        }\n        catch {\n          // just ignore\n        }\n      }\n    }))\n\n    await Promise.all(promises)\n    await this.writeReport(stringify(result))\n  }\n\n  async writeReport(report: string): Promise<void> {\n    const metaFile = resolve(this.reporterDir, 'html.meta.json.gz')\n\n    const promiseGzip = promisify(gzip)\n    const data = await promiseGzip(report, {\n      level: zlibConstants.Z_BEST_COMPRESSION,\n    })\n    await fs.writeFile(metaFile, data, 'base64')\n    const ui = resolve(distDir, 'client')\n    // copy ui\n    const files = globSync(['**/*'], { cwd: ui, expandDirectories: false })\n    await Promise.all(\n      files.map(async (f) => {\n        if (f === 'index.html') {\n          const html = await fs.readFile(resolve(ui, f), 'utf-8')\n          const filePath = relative(this.reporterDir, metaFile)\n          await fs.writeFile(\n            this.htmlFilePath,\n            html.replace(\n              '<!-- !LOAD_METADATA! -->',\n              `<script>window.METADATA_PATH=\"${filePath}\"</script>`,\n            ),\n          )\n        }\n        else {\n          await fs.copyFile(resolve(ui, f), resolve(this.reporterDir, f))\n        }\n      }),\n    )\n\n    // copy attachments\n    // TODO: unify attachmentsDir and html outputFile, so both live together without extra copy\n    if (existsSync(this.ctx.config.attachmentsDir)) {\n      const destAttachmentsDir = resolve(this.reporterDir, 'data')\n      await fs.rm(destAttachmentsDir, { recursive: true, force: true })\n      await fs.mkdir(destAttachmentsDir, { recursive: true })\n      await fs.cp(this.ctx.config.attachmentsDir, destAttachmentsDir, { recursive: true })\n    }\n\n    this.ctx.logger.log(\n      `${c.bold(c.inverse(c.magenta(' HTML ')))} ${c.magenta(\n        'Report is generated',\n      )}`,\n    )\n    this.ctx.logger.log(\n      `${c.dim('       You can run ')}${c.bold(\n        `npx vite preview --outDir ${relative(this.ctx.config.root, this.reporterDir)}`,\n      )}${c.dim(' to see the test results.')}`,\n    )\n  }\n\n  async onFinishedReportCoverage(): Promise<void> {\n    if (this.ctx.config.coverage.enabled && this.ctx.config.coverage.htmlDir) {\n      const coverageHtmlDir = this.ctx.config.coverage.htmlDir\n      const destCoverageDir = resolve(this.reporterDir, 'coverage')\n      if (coverageHtmlDir === destCoverageDir) {\n        // skip and preserve already generated coverage report.\n        // this can happen when users configures `outputFile`\n        // next to `coverage.reportsDirectory`.\n        return\n      }\n      await fs.rm(destCoverageDir, { recursive: true, force: true })\n      await fs.mkdir(destCoverageDir, { recursive: true })\n      await fs.cp(coverageHtmlDir, destCoverageDir, { recursive: true })\n    }\n  }\n}\n"
  },
  {
    "path": "packages/ui/node/tsconfig.json",
    "content": "{\n  \"extends\": \"../../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"./*.ts\"]\n}\n"
  },
  {
    "path": "packages/ui/package.json",
    "content": "{\n  \"name\": \"@vitest/ui\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"UI for Vitest\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev/guide/ui\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/ui\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vitest\",\n    \"html\",\n    \"reporter\"\n  ],\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./reporter\": {\n      \"types\": \"./reporter.d.ts\",\n      \"default\": \"./dist/reporter.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"*.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && pnpm build:node && pnpm build:client\",\n    \"build:client\": \"vite build\",\n    \"build:node\": \"rollup -c\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"typecheck:client\": \"vue-tsc --noEmit\",\n    \"dev:client\": \"vite\",\n    \"dev\": \"rollup -c --watch --watch.include 'node/**'\",\n    \"dev:ui\": \"pnpm run --stream '/^(dev|dev:client)$/'\",\n    \"test:ui\": \"vitest --browser\"\n  },\n  \"peerDependencies\": {\n    \"vitest\": \"workspace:*\"\n  },\n  \"dependencies\": {\n    \"@vitest/utils\": \"workspace:*\",\n    \"fflate\": \"^0.8.2\",\n    \"flatted\": \"catalog:\",\n    \"pathe\": \"catalog:\",\n    \"sirv\": \"catalog:\",\n    \"tinyglobby\": \"catalog:\",\n    \"tinyrainbow\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@faker-js/faker\": \"^10.3.0\",\n    \"@iconify-json/carbon\": \"catalog:\",\n    \"@iconify-json/logos\": \"catalog:\",\n    \"@types/codemirror\": \"^5.60.17\",\n    \"@types/d3-force\": \"^3.0.10\",\n    \"@types/d3-selection\": \"^3.0.11\",\n    \"@types/ws\": \"catalog:\",\n    \"@unocss/reset\": \"catalog:\",\n    \"@vitejs/plugin-vue\": \"catalog:\",\n    \"@vitest/browser-playwright\": \"workspace:*\",\n    \"@vitest/runner\": \"workspace:*\",\n    \"@vitest/ws-client\": \"workspace:*\",\n    \"@vue/test-utils\": \"^2.4.6\",\n    \"@vueuse/core\": \"catalog:\",\n    \"ansi-to-html\": \"^0.7.2\",\n    \"birpc\": \"catalog:\",\n    \"codemirror\": \"^5.65.18\",\n    \"codemirror-theme-vars\": \"^0.1.2\",\n    \"d3-graph-controller\": \"^3.1.8\",\n    \"floating-vue\": \"^5.2.2\",\n    \"mime\": \"^4.1.0\",\n    \"rollup\": \"^4.59.0\",\n    \"splitpanes\": \"^4.0.4\",\n    \"typescript\": \"^5.9.3\",\n    \"unocss\": \"catalog:\",\n    \"vite\": \"^5.0.0\",\n    \"vite-plugin-pages\": \"^0.33.3\",\n    \"vitest-browser-vue\": \"2.0.2\",\n    \"vue\": \"catalog:\",\n    \"vue-router\": \"^5.0.3\",\n    \"vue-tsc\": \"^3.2.5\",\n    \"vue-virtual-scroller\": \"2.0.0-beta.8\"\n  }\n}\n"
  },
  {
    "path": "packages/ui/reporter.d.ts",
    "content": "import type { Reporter } from 'vitest/node'\n\ndeclare const reporter: Reporter\nexport default reporter\n"
  },
  {
    "path": "packages/ui/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies),\n  ...Object.keys(pkg.peerDependencies || {}),\n  'worker_threads',\n  'node:worker_threads',\n  /^@?vitest(\\/|$)/,\n  'vite',\n]\n\nconst dtsUtils = createDtsUtils()\n\nexport default () => {\n  return defineConfig([\n    {\n      input: {\n        index: `./node/index.ts`,\n        reporter: `./node/reporter.ts`,\n      },\n      output: {\n        dir: 'dist',\n        format: 'esm',\n      },\n      moduleContext: (id) => {\n        // mime has `this.__classPrivateFieldGet` check which should be ignored in esm\n        if (id.includes('mime/dist/src') || id.includes('mime\\\\dist\\\\src')) {\n          return '{}'\n        }\n      },\n      external,\n      plugins: [\n        ...dtsUtils.isolatedDecl(),\n        resolve({\n          preferBuiltins: true,\n        }),\n        json(),\n        commonjs(),\n        oxc({\n          transform: { target: 'node20' },\n        }),\n      ],\n      onwarn,\n    },\n    {\n      input: 'dist/.types/index.d.ts',\n      output: {\n        dir: 'dist',\n        entryFileNames: '[name].ts',\n        format: 'esm',\n      },\n      watch: false,\n      external,\n      plugins: dtsUtils.dts(),\n    },\n  ])\n}\n\nfunction onwarn(message) {\n  if (['EMPTY_BUNDLE', 'CIRCULAR_DEPENDENCY'].includes(message.code)) {\n    return\n  }\n  console.error(message)\n}\n"
  },
  {
    "path": "packages/ui/shim.d.ts",
    "content": "/// <reference types=\"./client/shim\" />\n"
  },
  {
    "path": "packages/ui/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"jsx\": \"preserve\",\n    \"lib\": [\"dom\", \"esnext\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true\n  },\n  \"vueCompilerOptions\": {\n    \"checkUnknownComponents\": true\n  },\n  \"include\": [\"./client/**/*\"],\n  \"exclude\": [\"dist\", \"node_modules\"]\n}\n"
  },
  {
    "path": "packages/ui/types.ts",
    "content": "import type { SerializedConfig } from 'vitest'\n\nexport interface WSMessage {\n  /**\n   * Message type\n   */\n  type: string\n\n  /**\n   * Message Data\n   */\n  data: any\n}\n\nexport type RunState = 'idle' | 'running'\n\nexport interface BrowserRunnerState {\n  files: string[]\n  config: SerializedConfig\n  type: 'orchestrator'\n  provider: string\n  wrapModule: <T>(module: () => T) => T\n}\n"
  },
  {
    "path": "packages/ui/vite.config.ts",
    "content": "import Vue from '@vitejs/plugin-vue'\nimport { resolve } from 'pathe'\nimport { presetAttributify, presetIcons, presetUno, transformerDirectives } from 'unocss'\nimport Unocss from 'unocss/vite'\nimport { defineConfig } from 'vite'\nimport Pages from 'vite-plugin-pages'\n\n// for debug:\n// open a static file serve to share the report json\n// and ui using the link to load the report json data\n// const debugLink = 'http://127.0.0.1:4173/__vitest__'\n\nexport default defineConfig({\n  root: import.meta.dirname,\n  base: './',\n  resolve: {\n    dedupe: ['vue'],\n    alias: {\n      '~/': `${resolve(import.meta.dirname, 'client')}/`,\n      '@vitest/ws-client': `${resolve(import.meta.dirname, '../ws-client/src/index.ts')}`,\n    },\n  },\n  define: {\n    __BASE_PATH__: '\"/__vitest__/\"',\n  },\n  plugins: [\n    Vue({\n      features: {\n        propsDestructure: true,\n      },\n      script: {\n        defineModel: true,\n      },\n    }),\n    Unocss({\n      presets: [presetUno(), presetAttributify(), presetIcons()] as any,\n      shortcuts: {\n        'bg-base': 'bg-white dark:bg-[#111]',\n        'bg-overlay': 'bg-[#eee]:50 dark:bg-[#222]:50',\n        'bg-header': 'bg-gray-500:5',\n        'bg-active': 'bg-gray-500:8',\n        'bg-hover': 'bg-gray-500:20',\n        'border-base': 'border-gray-500:10',\n        'focus-base': 'border-gray-500 dark:border-gray-400',\n        'highlight': 'bg-[#eab306] text-[#323238] dark:bg-[#323238] dark:text-[#eab306]',\n\n        'tab-button': 'font-light op50 hover:op80 h-full px-4',\n        'tab-button-active': 'op100 bg-gray-500:10',\n      },\n      transformers: [\n        transformerDirectives() as any,\n      ],\n      safelist: 'absolute origin-top mt-[8px]'.split(' '),\n    }),\n    Pages({\n      dirs: ['client/pages'],\n    }),\n    // uncomment to see the HTML reporter preview\n    // {\n    //   name: 'debug-html-report',\n    //   apply: 'serve',\n    //   transformIndexHtml(html) {\n    //     return html.replace('<!-- !LOAD_METADATA! -->', `<script>window.METADATA_PATH=\"${debugLink}/html.meta.json.gz\"</script>`)\n    //   },\n    // },\n\n    // uncomment to see the browser tab\n    // {\n    //   name: 'browser-dev-preview',\n    //   apply: 'serve',\n    //   transformIndexHtml() {\n    //     return [\n    //       { tag: 'script', attrs: { src: './browser.dev.js' } },\n    //     ]\n    //   },\n    // },\n    {\n      // workaround `crossorigin` issues on some browsers\n      // https://github.com/vitejs/vite/issues/6648\n      name: 'no-crossorigin-for-same-assets',\n      apply: 'build',\n      transformIndexHtml(html) {\n        return html\n          .replace('crossorigin src=\"./assets/', 'src=\"./assets/')\n          .replace('crossorigin href=\"./assets/', 'href=\"./assets/')\n      },\n    },\n  ],\n  build: {\n    outDir: './dist/client',\n  },\n})\n"
  },
  {
    "path": "packages/ui/vitest.config.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\nimport { mergeConfig } from 'vite'\nimport { defineConfig } from 'vitest/config'\nimport viteConfig from './vite.config'\n\nexport default mergeConfig(\n  viteConfig,\n  defineConfig({\n    optimizeDeps: {\n      include: ['vue-router', 'splitpanes', 'd3-graph-controller', 'vue-virtual-scroller'],\n    },\n    test: {\n      browser: {\n        provider: playwright(),\n        instances: [{ browser: 'chromium' }],\n      },\n    },\n  }),\n)\n"
  },
  {
    "path": "packages/utils/README.md",
    "content": "# @vitest/utils\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/utils?color=a1b858&label=)](https://npmx.dev/package/@vitest/utils)\n\nInternal shared utilities used by other Vitest packages.\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/utils) | [Documentation](https://vitest.dev/)\n"
  },
  {
    "path": "packages/utils/diff.d.ts",
    "content": "export * from './dist/diff.js'\n"
  },
  {
    "path": "packages/utils/error.d.ts",
    "content": "export * from './dist/error.js'\n"
  },
  {
    "path": "packages/utils/helpers.d.ts",
    "content": "export * from './dist/helpers.js'\n"
  },
  {
    "path": "packages/utils/package.json",
    "content": "{\n  \"name\": \"@vitest/utils\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Shared Vitest utility functions\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://github.com/vitest-dev/vitest/tree/main/packages/utils\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/utils\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./diff\": {\n      \"types\": \"./dist/diff.d.ts\",\n      \"default\": \"./dist/diff.js\"\n    },\n    \"./resolver\": {\n      \"types\": \"./dist/resolver.d.ts\",\n      \"default\": \"./dist/resolver.js\"\n    },\n    \"./error\": {\n      \"types\": \"./dist/error.d.ts\",\n      \"default\": \"./dist/error.js\"\n    },\n    \"./helpers\": {\n      \"types\": \"./dist/helpers.d.ts\",\n      \"default\": \"./dist/helpers.js\"\n    },\n    \"./offset\": {\n      \"types\": \"./dist/offset.d.ts\",\n      \"default\": \"./dist/offset.js\"\n    },\n    \"./constants\": {\n      \"types\": \"./dist/constants.d.ts\",\n      \"default\": \"./dist/constants.js\"\n    },\n    \"./timers\": {\n      \"types\": \"./dist/timers.d.ts\",\n      \"default\": \"./dist/timers.js\"\n    },\n    \"./display\": {\n      \"types\": \"./dist/display.d.ts\",\n      \"default\": \"./dist/display.js\"\n    },\n    \"./source-map\": {\n      \"types\": \"./dist/source-map.d.ts\",\n      \"default\": \"./dist/source-map.js\"\n    },\n    \"./source-map/node\": {\n      \"types\": \"./dist/source-map/node.d.ts\",\n      \"default\": \"./dist/source-map/node.js\"\n    },\n    \"./serialize\": {\n      \"types\": \"./dist/serialize.d.ts\",\n      \"default\": \"./dist/serialize.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"typesVersions\": {\n    \"*\": {\n      \"source-map\": [\n        \"dist/source-map.d.ts\"\n      ],\n      \"source-map/node\": [\n        \"dist/source-map/node.d.ts\"\n      ]\n    }\n  },\n  \"files\": [\n    \"*.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch\"\n  },\n  \"dependencies\": {\n    \"@vitest/pretty-format\": \"workspace:*\",\n    \"convert-source-map\": \"^2.0.0\",\n    \"tinyrainbow\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@jridgewell/trace-mapping\": \"catalog:\",\n    \"@types/convert-source-map\": \"^2.0.3\",\n    \"@types/estree\": \"catalog:\",\n    \"diff-sequences\": \"^29.6.3\",\n    \"loupe\": \"^3.2.1\"\n  }\n}\n"
  },
  {
    "path": "packages/utils/rollup.config.js",
    "content": "import { builtinModules, createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst entries = {\n  'index': 'src/index.ts',\n  'helpers': 'src/helpers.ts',\n  'diff': 'src/diff/index.ts',\n  'error': 'src/error.ts',\n  'source-map': 'src/source-map.ts',\n  'source-map/node': 'src/source-map/node.ts',\n  'types': 'src/types.ts',\n  'constants': 'src/constants.ts',\n  'offset': 'src/offset.ts',\n  'timers': 'src/timers.ts',\n  'display': 'src/display.ts',\n  'resolver': 'src/resolver.ts',\n  'serialize': 'src/serialize.ts',\n}\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  resolve({\n    preferBuiltins: true,\n  }),\n  json(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n  commonjs(),\n]\n\nexport default defineConfig([\n  {\n    input: entries,\n    treeshake: {\n      moduleSideEffects: [\n        {\n          external: true,\n          sideEffects: false,\n        },\n      ],\n    },\n    output: {\n      dir: 'dist',\n      format: 'esm',\n      entryFileNames: '[name].js',\n      chunkFileNames: 'chunk-[name].js',\n    },\n    external,\n    plugins,\n    onwarn,\n  },\n  {\n    input: dtsUtils.dtsInput(entries),\n    output: {\n      dir: 'dist',\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n    onwarn,\n  },\n])\n\nfunction onwarn(message) {\n  if (['EMPTY_BUNDLE', 'CIRCULAR_DEPENDENCY'].includes(message.code)) {\n    return\n  }\n  console.error(message)\n}\n"
  },
  {
    "path": "packages/utils/source-map.ts",
    "content": "export * from './dist/source-map.js'\n"
  },
  {
    "path": "packages/utils/src/constants.ts",
    "content": "// TODO: this is all copy pasted from Vite - can they expose a module that exports only constants?\n\nexport const KNOWN_ASSET_TYPES: string[] = [\n  // images\n  'apng',\n  'bmp',\n  'png',\n  'jpe?g',\n  'jfif',\n  'pjpeg',\n  'pjp',\n  'gif',\n  'svg',\n  'ico',\n  'webp',\n  'avif',\n\n  // media\n  'mp4',\n  'webm',\n  'ogg',\n  'mp3',\n  'wav',\n  'flac',\n  'aac',\n\n  // fonts\n  'woff2?',\n  'eot',\n  'ttf',\n  'otf',\n\n  // other\n  'webmanifest',\n  'pdf',\n  'txt',\n]\n\nexport const KNOWN_ASSET_RE: RegExp = new RegExp(\n  `\\\\.(${KNOWN_ASSET_TYPES.join('|')})$`,\n)\nexport const CSS_LANGS_RE: RegExp\n  = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/\n/**\n * Prefix for resolved Ids that are not valid browser import specifiers\n */\nexport const VALID_ID_PREFIX = `/@id/`\n\n/**\n * Plugins that use 'virtual modules' (e.g. for helper functions), prefix the\n * module ID with `\\0`, a convention from the rollup ecosystem.\n * This prevents other plugins from trying to process the id (like node resolution),\n * and core features like sourcemaps can use this info to differentiate between\n * virtual modules and regular files.\n * `\\0` is not a permitted char in import URLs so we have to replace them during\n * import analysis. The id will be decoded back before entering the plugins pipeline.\n * These encoded virtual ids are also prefixed by the VALID_ID_PREFIX, so virtual\n * modules in the browser end up encoded as `/@id/__x00__{id}`\n */\nexport const NULL_BYTE_PLACEHOLDER = `__x00__`\n"
  },
  {
    "path": "packages/utils/src/diff/cleanupSemantic.ts",
    "content": "/**\n * Diff Match and Patch\n * Copyright 2018 The diff-match-patch Authors.\n * https://github.com/google/diff-match-patch\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Computes the difference between two texts to create a patch.\n * Applies the patch onto another text, allowing for errors.\n * @author fraser@google.com (Neil Fraser)\n */\n\n/**\n * CHANGES by pedrottimark to diff_match_patch_uncompressed.ts file:\n *\n * 1. Delete anything not needed to use diff_cleanupSemantic method\n * 2. Convert from prototype properties to var declarations\n * 3. Convert Diff to class from constructor and prototype\n * 4. Add type annotations for arguments and return values\n * 5. Add exports\n */\n\n/**\n * The data structure representing a diff is an array of tuples:\n * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]\n * which means: delete 'Hello', add 'Goodbye' and keep ' world.'\n */\nconst DIFF_DELETE = -1\nconst DIFF_INSERT = 1\nconst DIFF_EQUAL = 0\n\n/**\n * Class representing one diff tuple.\n * Attempts to look like a two-element array (which is what this used to be).\n * @param {number} op Operation, one of: DIFF_DELETE, DIFF_INSERT, DIFF_EQUAL.\n * @param {string} text Text to be deleted, inserted, or retained.\n * @constructor\n */\nclass Diff {\n  0: number\n  1: string\n\n  constructor(op: number, text: string) {\n    this[0] = op\n    this[1] = text\n  }\n}\n\n/**\n * Determine the common prefix of two strings.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the start of each\n *     string.\n */\nfunction diff_commonPrefix(text1: string, text2: string): number {\n  // Quick check for common null cases.\n  if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) {\n    return 0\n  }\n\n  // Binary search.\n  // Performance analysis: https://neil.fraser.name/news/2007/10/09/\n  let pointermin = 0\n  let pointermax = Math.min(text1.length, text2.length)\n  let pointermid = pointermax\n  let pointerstart = 0\n  while (pointermin < pointermid) {\n    if (\n      text1.substring(pointerstart, pointermid)\n      === text2.substring(pointerstart, pointermid)\n    ) {\n      pointermin = pointermid\n      pointerstart = pointermin\n    }\n    else {\n      pointermax = pointermid\n    }\n    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin)\n  }\n  return pointermid\n}\n\n/**\n * Determine the common suffix of two strings.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the end of each string.\n */\nfunction diff_commonSuffix(text1: string, text2: string): number {\n  // Quick check for common null cases.\n  if (\n    !text1\n    || !text2\n    || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)\n  ) {\n    return 0\n  }\n\n  // Binary search.\n  // Performance analysis: https://neil.fraser.name/news/2007/10/09/\n  let pointermin = 0\n  let pointermax = Math.min(text1.length, text2.length)\n  let pointermid = pointermax\n  let pointerend = 0\n  while (pointermin < pointermid) {\n    if (\n      text1.substring(text1.length - pointermid, text1.length - pointerend)\n      === text2.substring(text2.length - pointermid, text2.length - pointerend)\n    ) {\n      pointermin = pointermid\n      pointerend = pointermin\n    }\n    else {\n      pointermax = pointermid\n    }\n    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin)\n  }\n  return pointermid\n}\n\n/**\n * Determine if the suffix of one string is the prefix of another.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the end of the first\n *     string and the start of the second string.\n * @private\n */\nfunction diff_commonOverlap_(text1: string, text2: string): number {\n  // Cache the text lengths to prevent multiple calls.\n  const text1_length = text1.length\n  const text2_length = text2.length\n  // Eliminate the null case.\n  if (text1_length === 0 || text2_length === 0) {\n    return 0\n  }\n\n  // Truncate the longer string.\n  if (text1_length > text2_length) {\n    text1 = text1.substring(text1_length - text2_length)\n  }\n  else if (text1_length < text2_length) {\n    text2 = text2.substring(0, text1_length)\n  }\n\n  const text_length = Math.min(text1_length, text2_length)\n  // Quick check for the worst case.\n  if (text1 === text2) {\n    return text_length\n  }\n\n  // Start by looking for a single character match\n  // and increase length until no match is found.\n  // Performance analysis: https://neil.fraser.name/news/2010/11/04/\n  let best = 0\n  let length = 1\n  while (true) {\n    const pattern = text1.substring(text_length - length)\n    const found = text2.indexOf(pattern)\n    if (found === -1) {\n      return best\n    }\n\n    length += found\n    if (\n      found === 0\n      || text1.substring(text_length - length) === text2.substring(0, length)\n    ) {\n      best = length\n      length++\n    }\n  }\n}\n\n/**\n * Reduce the number of edits by eliminating semantically trivial equalities.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\nfunction diff_cleanupSemantic(diffs: Array<Diff>): void {\n  let changes = false\n  const equalities = [] // Stack of indices where equalities are found.\n  let equalitiesLength = 0 // Keeping our own length var is faster in JS.\n  /** @type {?string} */\n  let lastEquality = null\n  // Always equal to diffs[equalities[equalitiesLength - 1]][1]\n  let pointer = 0 // Index of current position.\n  // Number of characters that changed prior to the equality.\n  let length_insertions1 = 0\n  let length_deletions1 = 0\n  // Number of characters that changed after the equality.\n  let length_insertions2 = 0\n  let length_deletions2 = 0\n  while (pointer < diffs.length) {\n    if (diffs[pointer][0] === DIFF_EQUAL) {\n      // Equality found.\n      equalities[equalitiesLength++] = pointer\n      length_insertions1 = length_insertions2\n      length_deletions1 = length_deletions2\n      length_insertions2 = 0\n      length_deletions2 = 0\n      lastEquality = diffs[pointer][1]\n    }\n    else {\n      // An insertion or deletion.\n      if (diffs[pointer][0] === DIFF_INSERT) {\n        length_insertions2 += diffs[pointer][1].length\n      }\n      else {\n        length_deletions2 += diffs[pointer][1].length\n      }\n\n      // Eliminate an equality that is smaller or equal to the edits on both\n      // sides of it.\n      if (\n        lastEquality\n        && lastEquality.length\n        <= Math.max(length_insertions1, length_deletions1)\n        && lastEquality.length <= Math.max(length_insertions2, length_deletions2)\n      ) {\n        // Duplicate record.\n        diffs.splice(\n          equalities[equalitiesLength - 1],\n          0,\n          new Diff(DIFF_DELETE, lastEquality),\n        )\n        // Change second copy to insert.\n        diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT\n        // Throw away the equality we just deleted.\n        equalitiesLength--\n        // Throw away the previous equality (it needs to be reevaluated).\n        equalitiesLength--\n        pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1\n        length_insertions1 = 0 // Reset the counters.\n        length_deletions1 = 0\n        length_insertions2 = 0\n        length_deletions2 = 0\n        lastEquality = null\n        changes = true\n      }\n    }\n    pointer++\n  }\n\n  // Normalize the diff.\n  if (changes) {\n    diff_cleanupMerge(diffs)\n  }\n\n  diff_cleanupSemanticLossless(diffs)\n\n  // Find any overlaps between deletions and insertions.\n  // e.g: <del>abcxxx</del><ins>xxxdef</ins>\n  //   -> <del>abc</del>xxx<ins>def</ins>\n  // e.g: <del>xxxabc</del><ins>defxxx</ins>\n  //   -> <ins>def</ins>xxx<del>abc</del>\n  // Only extract an overlap if it is as big as the edit ahead or behind it.\n  pointer = 1\n  while (pointer < diffs.length) {\n    if (\n      diffs[pointer - 1][0] === DIFF_DELETE\n      && diffs[pointer][0] === DIFF_INSERT\n    ) {\n      const deletion = diffs[pointer - 1][1]\n      const insertion = diffs[pointer][1]\n      const overlap_length1 = diff_commonOverlap_(deletion, insertion)\n      const overlap_length2 = diff_commonOverlap_(insertion, deletion)\n      if (overlap_length1 >= overlap_length2) {\n        if (\n          overlap_length1 >= deletion.length / 2\n          || overlap_length1 >= insertion.length / 2\n        ) {\n          // Overlap found.  Insert an equality and trim the surrounding edits.\n          diffs.splice(\n            pointer,\n            0,\n            new Diff(DIFF_EQUAL, insertion.substring(0, overlap_length1)),\n          )\n          diffs[pointer - 1][1] = deletion.substring(\n            0,\n            deletion.length - overlap_length1,\n          )\n          diffs[pointer + 1][1] = insertion.substring(overlap_length1)\n          pointer++\n        }\n      }\n      else {\n        if (\n          overlap_length2 >= deletion.length / 2\n          || overlap_length2 >= insertion.length / 2\n        ) {\n          // Reverse overlap found.\n          // Insert an equality and swap and trim the surrounding edits.\n          diffs.splice(\n            pointer,\n            0,\n            new Diff(DIFF_EQUAL, deletion.substring(0, overlap_length2)),\n          )\n          diffs[pointer - 1][0] = DIFF_INSERT\n          diffs[pointer - 1][1] = insertion.substring(\n            0,\n            insertion.length - overlap_length2,\n          )\n          diffs[pointer + 1][0] = DIFF_DELETE\n          diffs[pointer + 1][1] = deletion.substring(overlap_length2)\n          pointer++\n        }\n      }\n      pointer++\n    }\n    pointer++\n  }\n}\n\n// Define some regex patterns for matching boundaries.\nconst nonAlphaNumericRegex_ = /[^a-z0-9]/i\nconst whitespaceRegex_ = /\\s/\nconst linebreakRegex_ = /[\\r\\n]/\nconst blanklineEndRegex_ = /\\n\\r?\\n$/\nconst blanklineStartRegex_ = /^\\r?\\n\\r?\\n/\n\n/**\n * Look for single edits surrounded on both sides by equalities\n * which can be shifted sideways to align the edit to a word boundary.\n * e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\nfunction diff_cleanupSemanticLossless(diffs: Array<Diff>) {\n  let pointer = 1\n  // Intentionally ignore the first and last element (don't need checking).\n  while (pointer < diffs.length - 1) {\n    if (\n      diffs[pointer - 1][0] === DIFF_EQUAL\n      && diffs[pointer + 1][0] === DIFF_EQUAL\n    ) {\n      // This is a single edit surrounded by equalities.\n      let equality1 = diffs[pointer - 1][1]\n      let edit = diffs[pointer][1]\n      let equality2 = diffs[pointer + 1][1]\n\n      // First, shift the edit as far left as possible.\n      const commonOffset = diff_commonSuffix(equality1, edit)\n      if (commonOffset) {\n        const commonString = edit.substring(edit.length - commonOffset)\n        equality1 = equality1.substring(0, equality1.length - commonOffset)\n        edit = commonString + edit.substring(0, edit.length - commonOffset)\n        equality2 = commonString + equality2\n      }\n\n      // Second, step character by character right, looking for the best fit.\n      let bestEquality1 = equality1\n      let bestEdit = edit\n      let bestEquality2 = equality2\n      let bestScore\n        = diff_cleanupSemanticScore_(equality1, edit)\n          + diff_cleanupSemanticScore_(edit, equality2)\n      while (edit.charAt(0) === equality2.charAt(0)) {\n        equality1 += edit.charAt(0)\n        edit = edit.substring(1) + equality2.charAt(0)\n        equality2 = equality2.substring(1)\n        const score\n          = diff_cleanupSemanticScore_(equality1, edit)\n            + diff_cleanupSemanticScore_(edit, equality2)\n        // The >= encourages trailing rather than leading whitespace on edits.\n        if (score >= bestScore) {\n          bestScore = score\n          bestEquality1 = equality1\n          bestEdit = edit\n          bestEquality2 = equality2\n        }\n      }\n\n      if (diffs[pointer - 1][1] !== bestEquality1) {\n        // We have an improvement, save it back to the diff.\n        if (bestEquality1) {\n          diffs[pointer - 1][1] = bestEquality1\n        }\n        else {\n          diffs.splice(pointer - 1, 1)\n          pointer--\n        }\n        diffs[pointer][1] = bestEdit\n        if (bestEquality2) {\n          diffs[pointer + 1][1] = bestEquality2\n        }\n        else {\n          diffs.splice(pointer + 1, 1)\n          pointer--\n        }\n      }\n    }\n    pointer++\n  }\n}\n\n/**\n * Reorder and merge like edit sections.  Merge equalities.\n * Any edit section can move as long as it doesn't cross an equality.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\nfunction diff_cleanupMerge(diffs: Array<Diff>) {\n  // Add a dummy entry at the end.\n  diffs.push(new Diff(DIFF_EQUAL, ''))\n  let pointer = 0\n  let count_delete = 0\n  let count_insert = 0\n  let text_delete = ''\n  let text_insert = ''\n  let commonlength\n  while (pointer < diffs.length) {\n    switch (diffs[pointer][0]) {\n      case DIFF_INSERT:\n        count_insert++\n        text_insert += diffs[pointer][1]\n        pointer++\n        break\n      case DIFF_DELETE:\n        count_delete++\n        text_delete += diffs[pointer][1]\n        pointer++\n        break\n      case DIFF_EQUAL:\n        // Upon reaching an equality, check for prior redundancies.\n        if (count_delete + count_insert > 1) {\n          if (count_delete !== 0 && count_insert !== 0) {\n            // Factor out any common prefixes.\n            commonlength = diff_commonPrefix(text_insert, text_delete)\n            if (commonlength !== 0) {\n              if (\n                pointer - count_delete - count_insert > 0\n                && diffs[pointer - count_delete - count_insert - 1][0]\n                === DIFF_EQUAL\n              ) {\n                diffs[pointer - count_delete - count_insert - 1][1]\n                  += text_insert.substring(0, commonlength)\n              }\n              else {\n                diffs.splice(\n                  0,\n                  0,\n                  new Diff(DIFF_EQUAL, text_insert.substring(0, commonlength)),\n                )\n                pointer++\n              }\n              text_insert = text_insert.substring(commonlength)\n              text_delete = text_delete.substring(commonlength)\n            }\n            // Factor out any common suffixes.\n            commonlength = diff_commonSuffix(text_insert, text_delete)\n            if (commonlength !== 0) {\n              diffs[pointer][1]\n                = text_insert.substring(text_insert.length - commonlength)\n                  + diffs[pointer][1]\n              text_insert = text_insert.substring(\n                0,\n                text_insert.length - commonlength,\n              )\n              text_delete = text_delete.substring(\n                0,\n                text_delete.length - commonlength,\n              )\n            }\n          }\n          // Delete the offending records and add the merged ones.\n          pointer -= count_delete + count_insert\n          diffs.splice(pointer, count_delete + count_insert)\n          if (text_delete.length) {\n            diffs.splice(pointer, 0, new Diff(DIFF_DELETE, text_delete))\n            pointer++\n          }\n          if (text_insert.length) {\n            diffs.splice(pointer, 0, new Diff(DIFF_INSERT, text_insert))\n            pointer++\n          }\n          pointer++\n        }\n        else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {\n          // Merge this equality with the previous one.\n          diffs[pointer - 1][1] += diffs[pointer][1]\n          diffs.splice(pointer, 1)\n        }\n        else {\n          pointer++\n        }\n        count_insert = 0\n        count_delete = 0\n        text_delete = ''\n        text_insert = ''\n        break\n    }\n  }\n  if (diffs.at(-1)?.[1] === '') {\n    diffs.pop()\n  } // Remove the dummy entry at the end.\n\n  // Second pass: look for single edits surrounded on both sides by equalities\n  // which can be shifted sideways to eliminate an equality.\n  // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC\n  let changes = false\n  pointer = 1\n  // Intentionally ignore the first and last element (don't need checking).\n  while (pointer < diffs.length - 1) {\n    if (\n      diffs[pointer - 1][0] === DIFF_EQUAL\n      && diffs[pointer + 1][0] === DIFF_EQUAL\n    ) {\n      // This is a single edit surrounded by equalities.\n      if (\n        diffs[pointer][1].substring(\n          diffs[pointer][1].length - diffs[pointer - 1][1].length,\n        ) === diffs[pointer - 1][1]\n      ) {\n        // Shift the edit over the previous equality.\n        diffs[pointer][1]\n          = diffs[pointer - 1][1]\n            + diffs[pointer][1].substring(\n              0,\n              diffs[pointer][1].length - diffs[pointer - 1][1].length,\n            )\n        diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]\n        diffs.splice(pointer - 1, 1)\n        changes = true\n      }\n      else if (\n        diffs[pointer][1].substring(0, diffs[pointer + 1][1].length)\n        === diffs[pointer + 1][1]\n      ) {\n        // Shift the edit over the next equality.\n        diffs[pointer - 1][1] += diffs[pointer + 1][1]\n        diffs[pointer][1]\n          = diffs[pointer][1].substring(diffs[pointer + 1][1].length)\n            + diffs[pointer + 1][1]\n        diffs.splice(pointer + 1, 1)\n        changes = true\n      }\n    }\n    pointer++\n  }\n  // If shifts were made, the diff needs reordering and another shift sweep.\n  if (changes) {\n    diff_cleanupMerge(diffs)\n  }\n}\n\n/**\n * Given two strings, compute a score representing whether the internal\n * boundary falls on logical boundaries.\n * Scores range from 6 (best) to 0 (worst).\n * Closure, but does not reference any external variables.\n * @param {string} one First string.\n * @param {string} two Second string.\n * @return {number} The score.\n * @private\n */\nfunction diff_cleanupSemanticScore_(one: string, two: string): number {\n  if (!one || !two) {\n    // Edges are the best.\n    return 6\n  }\n\n  // Each port of this function behaves slightly differently due to\n  // subtle differences in each language's definition of things like\n  // 'whitespace'.  Since this function's purpose is largely cosmetic,\n  // the choice has been made to use each language's native features\n  // rather than force total conformity.\n  const char1 = one.charAt(one.length - 1)\n  const char2 = two.charAt(0)\n  const nonAlphaNumeric1 = char1.match(nonAlphaNumericRegex_)\n  const nonAlphaNumeric2 = char2.match(nonAlphaNumericRegex_)\n  const whitespace1 = nonAlphaNumeric1 && char1.match(whitespaceRegex_)\n  const whitespace2 = nonAlphaNumeric2 && char2.match(whitespaceRegex_)\n  const lineBreak1 = whitespace1 && char1.match(linebreakRegex_)\n  const lineBreak2 = whitespace2 && char2.match(linebreakRegex_)\n  const blankLine1 = lineBreak1 && one.match(blanklineEndRegex_)\n  const blankLine2 = lineBreak2 && two.match(blanklineStartRegex_)\n\n  if (blankLine1 || blankLine2) {\n    // Five points for blank lines.\n    return 5\n  }\n  else if (lineBreak1 || lineBreak2) {\n    // Four points for line breaks.\n    return 4\n  }\n  else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {\n    // Three points for end of sentences.\n    return 3\n  }\n  else if (whitespace1 || whitespace2) {\n    // Two points for whitespace.\n    return 2\n  }\n  else if (nonAlphaNumeric1 || nonAlphaNumeric2) {\n    // One point for non-alphanumeric.\n    return 1\n  }\n  return 0\n}\n\nexport {\n  diff_cleanupSemantic as cleanupSemantic,\n  Diff,\n  DIFF_DELETE,\n  DIFF_EQUAL,\n  DIFF_INSERT,\n}\n"
  },
  {
    "path": "packages/utils/src/diff/constants.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nexport const NO_DIFF_MESSAGE: string = 'Compared values have no visual difference.'\n\nexport const SIMILAR_MESSAGE: string\n  = 'Compared values serialize to the same structure.\\n'\n    + 'Printing internal object structure without calling `toJSON` instead.'\n"
  },
  {
    "path": "packages/utils/src/diff/diffLines.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { DiffOptions, DiffOptionsNormalized } from './types'\nimport diffSequences from 'diff-sequences'\nimport { Diff, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from './cleanupSemantic'\nimport {\n  joinAlignedDiffsExpand,\n  joinAlignedDiffsNoExpand,\n} from './joinAlignedDiffs'\nimport { normalizeDiffOptions } from './normalizeDiffOptions'\n\nfunction isEmptyString(lines: Array<string>) {\n  return lines.length === 1 && lines[0].length === 0\n}\n\ninterface ChangeCounts {\n  a: number\n  b: number\n}\n\nfunction countChanges(diffs: Array<Diff>): ChangeCounts {\n  let a = 0\n  let b = 0\n\n  diffs.forEach((diff) => {\n    switch (diff[0]) {\n      case DIFF_DELETE:\n        a += 1\n        break\n\n      case DIFF_INSERT:\n        b += 1\n        break\n    }\n  })\n\n  return { a, b }\n}\n\nfunction printAnnotation(\n  {\n    aAnnotation,\n    aColor,\n    aIndicator,\n    bAnnotation,\n    bColor,\n    bIndicator,\n    includeChangeCounts,\n    omitAnnotationLines,\n  }: DiffOptionsNormalized,\n  changeCounts: ChangeCounts,\n): string {\n  if (omitAnnotationLines) {\n    return ''\n  }\n\n  let aRest = ''\n  let bRest = ''\n\n  if (includeChangeCounts) {\n    const aCount = String(changeCounts.a)\n    const bCount = String(changeCounts.b)\n\n    // Padding right aligns the ends of the annotations.\n    const baAnnotationLengthDiff = bAnnotation.length - aAnnotation.length\n    const aAnnotationPadding = ' '.repeat(Math.max(0, baAnnotationLengthDiff))\n    const bAnnotationPadding = ' '.repeat(Math.max(0, -baAnnotationLengthDiff))\n\n    // Padding left aligns the ends of the counts.\n    const baCountLengthDiff = bCount.length - aCount.length\n    const aCountPadding = ' '.repeat(Math.max(0, baCountLengthDiff))\n    const bCountPadding = ' '.repeat(Math.max(0, -baCountLengthDiff))\n\n    aRest = `${aAnnotationPadding}  ${aIndicator} ${aCountPadding}${aCount}`\n    bRest = `${bAnnotationPadding}  ${bIndicator} ${bCountPadding}${bCount}`\n  }\n\n  const a = `${aIndicator} ${aAnnotation}${aRest}`\n  const b = `${bIndicator} ${bAnnotation}${bRest}`\n  return `${aColor(a)}\\n${bColor(b)}\\n\\n`\n}\n\nexport function printDiffLines(\n  diffs: Array<Diff>,\n  truncated: boolean,\n  options: DiffOptionsNormalized,\n): string {\n  return (\n    printAnnotation(options, countChanges(diffs))\n    + (options.expand\n      ? joinAlignedDiffsExpand(diffs, options)\n      : joinAlignedDiffsNoExpand(diffs, options))\n    + (truncated\n      ? options.truncateAnnotationColor(`\\n${options.truncateAnnotation}`)\n      : '')\n  )\n}\n\n// Compare two arrays of strings line-by-line. Format as comparison lines.\nexport function diffLinesUnified(\n  aLines: Array<string>,\n  bLines: Array<string>,\n  options?: DiffOptions,\n): string {\n  const normalizedOptions = normalizeDiffOptions(options)\n  const [diffs, truncated] = diffLinesRaw(\n    isEmptyString(aLines) ? [] : aLines,\n    isEmptyString(bLines) ? [] : bLines,\n    normalizedOptions,\n  )\n  return printDiffLines(diffs, truncated, normalizedOptions)\n}\n\n// Given two pairs of arrays of strings:\n// Compare the pair of comparison arrays line-by-line.\n// Format the corresponding lines in the pair of displayable arrays.\nexport function diffLinesUnified2(\n  aLinesDisplay: Array<string>,\n  bLinesDisplay: Array<string>,\n  aLinesCompare: Array<string>,\n  bLinesCompare: Array<string>,\n  options?: DiffOptions,\n): string {\n  if (isEmptyString(aLinesDisplay) && isEmptyString(aLinesCompare)) {\n    aLinesDisplay = []\n    aLinesCompare = []\n  }\n  if (isEmptyString(bLinesDisplay) && isEmptyString(bLinesCompare)) {\n    bLinesDisplay = []\n    bLinesCompare = []\n  }\n\n  if (\n    aLinesDisplay.length !== aLinesCompare.length\n    || bLinesDisplay.length !== bLinesCompare.length\n  ) {\n    // Fall back to diff of display lines.\n    return diffLinesUnified(aLinesDisplay, bLinesDisplay, options)\n  }\n\n  const [diffs, truncated] = diffLinesRaw(\n    aLinesCompare,\n    bLinesCompare,\n    options,\n  )\n\n  // Replace comparison lines with displayable lines.\n  let aIndex = 0\n  let bIndex = 0\n  diffs.forEach((diff: Diff) => {\n    switch (diff[0]) {\n      case DIFF_DELETE:\n        diff[1] = aLinesDisplay[aIndex]\n        aIndex += 1\n        break\n\n      case DIFF_INSERT:\n        diff[1] = bLinesDisplay[bIndex]\n        bIndex += 1\n        break\n\n      default:\n        diff[1] = bLinesDisplay[bIndex]\n        aIndex += 1\n        bIndex += 1\n    }\n  })\n\n  return printDiffLines(diffs, truncated, normalizeDiffOptions(options))\n}\n\n// Compare two arrays of strings line-by-line.\nexport function diffLinesRaw(\n  aLines: Array<string>,\n  bLines: Array<string>,\n  options?: DiffOptions,\n): [Array<Diff>, boolean] {\n  const truncate = options?.truncateThreshold ?? false\n  const truncateThreshold = Math.max(\n    Math.floor(options?.truncateThreshold ?? 0),\n    0,\n  )\n  const aLength = truncate\n    ? Math.min(aLines.length, truncateThreshold)\n    : aLines.length\n  const bLength = truncate\n    ? Math.min(bLines.length, truncateThreshold)\n    : bLines.length\n  const truncated = aLength !== aLines.length || bLength !== bLines.length\n\n  const isCommon = (aIndex: number, bIndex: number) =>\n    aLines[aIndex] === bLines[bIndex]\n\n  const diffs: Array<Diff> = []\n  let aIndex = 0\n  let bIndex = 0\n\n  const foundSubsequence = (\n    nCommon: number,\n    aCommon: number,\n    bCommon: number,\n  ) => {\n    for (; aIndex !== aCommon; aIndex += 1) {\n      diffs.push(new Diff(DIFF_DELETE, aLines[aIndex]))\n    }\n\n    for (; bIndex !== bCommon; bIndex += 1) {\n      diffs.push(new Diff(DIFF_INSERT, bLines[bIndex]))\n    }\n\n    for (; nCommon !== 0; nCommon -= 1, aIndex += 1, bIndex += 1) {\n      diffs.push(new Diff(DIFF_EQUAL, bLines[bIndex]))\n    }\n  }\n\n  diffSequences(aLength, bLength, isCommon, foundSubsequence)\n\n  // After the last common subsequence, push remaining change items.\n  for (; aIndex !== aLength; aIndex += 1) {\n    diffs.push(new Diff(DIFF_DELETE, aLines[aIndex]))\n  }\n\n  for (; bIndex !== bLength; bIndex += 1) {\n    diffs.push(new Diff(DIFF_INSERT, bLines[bIndex]))\n  }\n\n  return [diffs, truncated]\n}\n"
  },
  {
    "path": "packages/utils/src/diff/diffStrings.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { DiffOptions } from './types'\nimport diffSequences from 'diff-sequences'\nimport { Diff, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from './cleanupSemantic'\n\n// platforms compatible\nfunction getNewLineSymbol(string: string) {\n  return string.includes('\\r\\n') ? '\\r\\n' : '\\n'\n}\n\nfunction diffStrings(\n  a: string,\n  b: string,\n  options?: DiffOptions,\n): [Array<Diff>, boolean] {\n  const truncate = options?.truncateThreshold ?? false\n  const truncateThreshold = Math.max(\n    Math.floor(options?.truncateThreshold ?? 0),\n    0,\n  )\n  let aLength = a.length\n  let bLength = b.length\n  if (truncate) {\n    const aMultipleLines = a.includes('\\n')\n    const bMultipleLines = b.includes('\\n')\n    const aNewLineSymbol = getNewLineSymbol(a)\n    const bNewLineSymbol = getNewLineSymbol(b)\n    // multiple-lines string expects a newline to be appended at the end\n    const _a = aMultipleLines\n      ? `${a.split(aNewLineSymbol, truncateThreshold).join(aNewLineSymbol)}\\n`\n      : a\n    const _b = bMultipleLines\n      ? `${b.split(bNewLineSymbol, truncateThreshold).join(bNewLineSymbol)}\\n`\n      : b\n    aLength = _a.length\n    bLength = _b.length\n  }\n  const truncated = aLength !== a.length || bLength !== b.length\n\n  const isCommon = (aIndex: number, bIndex: number) => a[aIndex] === b[bIndex]\n\n  let aIndex = 0\n  let bIndex = 0\n  const diffs: Array<Diff> = []\n\n  const foundSubsequence = (\n    nCommon: number,\n    aCommon: number,\n    bCommon: number,\n  ) => {\n    if (aIndex !== aCommon) {\n      diffs.push(new Diff(DIFF_DELETE, a.slice(aIndex, aCommon)))\n    }\n\n    if (bIndex !== bCommon) {\n      diffs.push(new Diff(DIFF_INSERT, b.slice(bIndex, bCommon)))\n    }\n\n    aIndex = aCommon + nCommon // number of characters compared in a\n    bIndex = bCommon + nCommon // number of characters compared in b\n    diffs.push(new Diff(DIFF_EQUAL, b.slice(bCommon, bIndex)))\n  }\n\n  diffSequences(aLength, bLength, isCommon, foundSubsequence)\n\n  // After the last common subsequence, push remaining change items.\n  if (aIndex !== aLength) {\n    diffs.push(new Diff(DIFF_DELETE, a.slice(aIndex)))\n  }\n\n  if (bIndex !== bLength) {\n    diffs.push(new Diff(DIFF_INSERT, b.slice(bIndex)))\n  }\n\n  return [diffs, truncated]\n}\n\nexport default diffStrings\n"
  },
  {
    "path": "packages/utils/src/diff/getAlignedDiffs.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { DiffOptionsColor } from './types'\nimport { Diff, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from './cleanupSemantic'\n\n// Given change op and array of diffs, return concatenated string:\n// * include common strings\n// * include change strings which have argument op with changeColor\n// * exclude change strings which have opposite op\nfunction concatenateRelevantDiffs(\n  op: number,\n  diffs: Array<Diff>,\n  changeColor: DiffOptionsColor,\n): string {\n  return diffs.reduce(\n    (reduced: string, diff: Diff): string =>\n      reduced\n      + (diff[0] === DIFF_EQUAL\n        ? diff[1]\n        : diff[0] === op && diff[1].length !== 0 // empty if change is newline\n          ? changeColor(diff[1])\n          : ''),\n    '',\n  )\n}\n\n// Encapsulate change lines until either a common newline or the end.\nclass ChangeBuffer {\n  private readonly op: number\n  private line: Array<Diff> // incomplete line\n  private lines: Array<Diff> // complete lines\n  private readonly changeColor: DiffOptionsColor\n\n  constructor(op: number, changeColor: DiffOptionsColor) {\n    this.op = op\n    this.line = []\n    this.lines = []\n    this.changeColor = changeColor\n  }\n\n  private pushSubstring(substring: string): void {\n    this.pushDiff(new Diff(this.op, substring))\n  }\n\n  private pushLine(): void {\n    // Assume call only if line has at least one diff,\n    // therefore an empty line must have a diff which has an empty string.\n\n    // If line has multiple diffs, then assume it has a common diff,\n    // therefore change diffs have change color;\n    // otherwise then it has line color only.\n    this.lines.push(\n      this.line.length !== 1\n        ? new Diff(\n            this.op,\n            concatenateRelevantDiffs(this.op, this.line, this.changeColor),\n          )\n        : this.line[0][0] === this.op\n          ? this.line[0] // can use instance\n          : new Diff(this.op, this.line[0][1]), // was common diff\n    )\n    this.line.length = 0\n  }\n\n  isLineEmpty() {\n    return this.line.length === 0\n  }\n\n  // Minor input to buffer.\n  pushDiff(diff: Diff): void {\n    this.line.push(diff)\n  }\n\n  // Main input to buffer.\n  align(diff: Diff): void {\n    const string = diff[1]\n\n    if (string.includes('\\n')) {\n      const substrings = string.split('\\n')\n      const iLast = substrings.length - 1\n      substrings.forEach((substring, i) => {\n        if (i < iLast) {\n          // The first substring completes the current change line.\n          // A middle substring is a change line.\n          this.pushSubstring(substring)\n          this.pushLine()\n        }\n        else if (substring.length !== 0) {\n          // The last substring starts a change line, if it is not empty.\n          // Important: This non-empty condition also automatically omits\n          // the newline appended to the end of expected and received strings.\n          this.pushSubstring(substring)\n        }\n      })\n    }\n    else {\n      // Append non-multiline string to current change line.\n      this.pushDiff(diff)\n    }\n  }\n\n  // Output from buffer.\n  moveLinesTo(lines: Array<Diff>): void {\n    if (!this.isLineEmpty()) {\n      this.pushLine()\n    }\n\n    lines.push(...this.lines)\n    this.lines.length = 0\n  }\n}\n\n// Encapsulate common and change lines.\nclass CommonBuffer {\n  private readonly deleteBuffer: ChangeBuffer\n  private readonly insertBuffer: ChangeBuffer\n  private readonly lines: Array<Diff>\n\n  constructor(deleteBuffer: ChangeBuffer, insertBuffer: ChangeBuffer) {\n    this.deleteBuffer = deleteBuffer\n    this.insertBuffer = insertBuffer\n    this.lines = []\n  }\n\n  private pushDiffCommonLine(diff: Diff): void {\n    this.lines.push(diff)\n  }\n\n  private pushDiffChangeLines(diff: Diff): void {\n    const isDiffEmpty = diff[1].length === 0\n\n    // An empty diff string is redundant, unless a change line is empty.\n    if (!isDiffEmpty || this.deleteBuffer.isLineEmpty()) {\n      this.deleteBuffer.pushDiff(diff)\n    }\n\n    if (!isDiffEmpty || this.insertBuffer.isLineEmpty()) {\n      this.insertBuffer.pushDiff(diff)\n    }\n  }\n\n  private flushChangeLines(): void {\n    this.deleteBuffer.moveLinesTo(this.lines)\n    this.insertBuffer.moveLinesTo(this.lines)\n  }\n\n  // Input to buffer.\n  align(diff: Diff): void {\n    const op = diff[0]\n    const string = diff[1]\n\n    if (string.includes('\\n')) {\n      const substrings = string.split('\\n')\n      const iLast = substrings.length - 1\n      substrings.forEach((substring, i) => {\n        if (i === 0) {\n          const subdiff = new Diff(op, substring)\n          if (\n            this.deleteBuffer.isLineEmpty()\n            && this.insertBuffer.isLineEmpty()\n          ) {\n            // If both current change lines are empty,\n            // then the first substring is a common line.\n            this.flushChangeLines()\n            this.pushDiffCommonLine(subdiff)\n          }\n          else {\n            // If either current change line is non-empty,\n            // then the first substring completes the change lines.\n            this.pushDiffChangeLines(subdiff)\n            this.flushChangeLines()\n          }\n        }\n        else if (i < iLast) {\n          // A middle substring is a common line.\n          this.pushDiffCommonLine(new Diff(op, substring))\n        }\n        else if (substring.length !== 0) {\n          // The last substring starts a change line, if it is not empty.\n          // Important: This non-empty condition also automatically omits\n          // the newline appended to the end of expected and received strings.\n          this.pushDiffChangeLines(new Diff(op, substring))\n        }\n      })\n    }\n    else {\n      // Append non-multiline string to current change lines.\n      // Important: It cannot be at the end following empty change lines,\n      // because newline appended to the end of expected and received strings.\n      this.pushDiffChangeLines(diff)\n    }\n  }\n\n  // Output from buffer.\n  getLines(): Array<Diff> {\n    this.flushChangeLines()\n    return this.lines\n  }\n}\n\n// Given diffs from expected and received strings,\n// return new array of diffs split or joined into lines.\n//\n// To correctly align a change line at the end, the algorithm:\n// * assumes that a newline was appended to the strings\n// * omits the last newline from the output array\n//\n// Assume the function is not called:\n// * if either expected or received is empty string\n// * if neither expected nor received is multiline string\nfunction getAlignedDiffs(\n  diffs: Array<Diff>,\n  changeColor: DiffOptionsColor,\n): Array<Diff> {\n  const deleteBuffer = new ChangeBuffer(DIFF_DELETE, changeColor)\n  const insertBuffer = new ChangeBuffer(DIFF_INSERT, changeColor)\n  const commonBuffer = new CommonBuffer(deleteBuffer, insertBuffer)\n\n  diffs.forEach((diff) => {\n    switch (diff[0]) {\n      case DIFF_DELETE:\n        deleteBuffer.align(diff)\n        break\n\n      case DIFF_INSERT:\n        insertBuffer.align(diff)\n        break\n\n      default:\n        commonBuffer.align(diff)\n    }\n  })\n\n  return commonBuffer.getLines()\n}\n\nexport default getAlignedDiffs\n"
  },
  {
    "path": "packages/utils/src/diff/getType.ts",
    "content": "type ValueType\n  = | 'array'\n    | 'bigint'\n    | 'boolean'\n    | 'function'\n    | 'null'\n    | 'number'\n    | 'object'\n    | 'regexp'\n    | 'map'\n    | 'set'\n    | 'date'\n    | 'string'\n    | 'symbol'\n    | 'undefined'\n\n// get the type of a value with handling the edge cases like `typeof []`\n// and `typeof null`\nexport function getType(value: unknown): ValueType {\n  if (value === undefined) {\n    return 'undefined'\n  }\n  else if (value === null) {\n    return 'null'\n  }\n  else if (Array.isArray(value)) {\n    return 'array'\n  }\n  else if (typeof value === 'boolean') {\n    return 'boolean'\n  }\n  else if (typeof value === 'function') {\n    return 'function'\n  }\n  else if (typeof value === 'number') {\n    return 'number'\n  }\n  else if (typeof value === 'string') {\n    return 'string'\n  }\n  else if (typeof value === 'bigint') {\n    return 'bigint'\n  }\n  else if (typeof value === 'object') {\n    if (value != null) {\n      if (value.constructor === RegExp) {\n        return 'regexp'\n      }\n      else if (value.constructor === Map) {\n        return 'map'\n      }\n      else if (value.constructor === Set) {\n        return 'set'\n      }\n      else if (value.constructor === Date) {\n        return 'date'\n      }\n    }\n    return 'object'\n  }\n  else if (typeof value === 'symbol') {\n    return 'symbol'\n  }\n\n  throw new Error(`value of unknown type: ${value}`)\n}\n\nexport const isPrimitive = (value: unknown): boolean => Object(value) !== value\n"
  },
  {
    "path": "packages/utils/src/diff/index.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// This is a fork of Jest's jest-diff package, but it doesn't depend on Node environment (like chalk).\n\nimport type { PrettyFormatOptions } from '@vitest/pretty-format'\nimport type { DiffOptions } from './types'\nimport {\n  format as prettyFormat,\n  plugins as prettyFormatPlugins,\n} from '@vitest/pretty-format'\nimport c from 'tinyrainbow'\nimport { stringify } from '../display'\nimport { deepClone, getOwnProperties, getType as getSimpleType } from '../helpers'\nimport { Diff, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from './cleanupSemantic'\nimport { NO_DIFF_MESSAGE, SIMILAR_MESSAGE } from './constants'\nimport { diffLinesRaw, diffLinesUnified, diffLinesUnified2 } from './diffLines'\nimport { getType } from './getType'\nimport { normalizeDiffOptions } from './normalizeDiffOptions'\nimport { diffStringsRaw, diffStringsUnified } from './printDiffs'\n\nexport type { DiffOptions, DiffOptionsColor, SerializedDiffOptions } from './types'\n\nexport { diffLinesRaw, diffLinesUnified, diffLinesUnified2 }\nexport { diffStringsRaw, diffStringsUnified }\nexport { Diff, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT }\n\nfunction getCommonMessage(message: string, options?: DiffOptions) {\n  const { commonColor } = normalizeDiffOptions(options)\n  return commonColor(message)\n}\n\nconst {\n  AsymmetricMatcher,\n  DOMCollection,\n  DOMElement,\n  Immutable,\n  ReactElement,\n  ReactTestComponent,\n} = prettyFormatPlugins\n\nconst PLUGINS = [\n  ReactTestComponent,\n  ReactElement,\n  DOMElement,\n  DOMCollection,\n  Immutable,\n  AsymmetricMatcher,\n  prettyFormatPlugins.Error,\n]\nconst FORMAT_OPTIONS = {\n  maxDepth: 20,\n  plugins: PLUGINS,\n} satisfies PrettyFormatOptions\nconst FALLBACK_FORMAT_OPTIONS = {\n  callToJSON: false,\n  maxDepth: 8,\n  plugins: PLUGINS,\n} satisfies PrettyFormatOptions\n\n// Generate a string that will highlight the difference between two values\n// with green and red. (similar to how github does code diffing)\n\n/**\n * @param a Expected value\n * @param b Received value\n * @param options Diff options\n * @returns {string | null} a string diff\n */\nexport function diff(a: any, b: any, options?: DiffOptions): string | undefined {\n  if (Object.is(a, b)) {\n    return ''\n  }\n\n  const aType = getType(a)\n  let expectedType = aType\n  let omitDifference = false\n  if (aType === 'object' && typeof a.asymmetricMatch === 'function') {\n    if (a.$$typeof !== Symbol.for('jest.asymmetricMatcher')) {\n      // Do not know expected type of user-defined asymmetric matcher.\n      return undefined\n    }\n    if (typeof a.getExpectedType !== 'function') {\n      // For example, expect.anything() matches either null or undefined\n      return undefined\n    }\n    expectedType = a.getExpectedType()\n    // Primitive types boolean and number omit difference below.\n    // For example, omit difference for expect.stringMatching(regexp)\n    omitDifference = expectedType === 'string'\n  }\n\n  if (expectedType !== getType(b)) {\n    const { aAnnotation, aColor, aIndicator, bAnnotation, bColor, bIndicator }\n      = normalizeDiffOptions(options)\n    const formatOptions = getFormatOptions(FALLBACK_FORMAT_OPTIONS, options)\n    let aDisplay = prettyFormat(a, formatOptions)\n    let bDisplay = prettyFormat(b, formatOptions)\n    // even if prettyFormat prints successfully big objects,\n    // large string can choke later on (concatenation? RPC?),\n    // so truncate it to a reasonable length here.\n    // (For example, playwright's ElementHandle can become about 200_000_000 length string)\n    const MAX_LENGTH = 100_000\n    function truncate(s: string) {\n      return s.length <= MAX_LENGTH ? s : (`${s.slice(0, MAX_LENGTH)}...`)\n    }\n    aDisplay = truncate(aDisplay)\n    bDisplay = truncate(bDisplay)\n    const aDiff = `${aColor(`${aIndicator} ${aAnnotation}:`)}\\n${aDisplay}`\n    const bDiff = `${bColor(`${bIndicator} ${bAnnotation}:`)}\\n${bDisplay}`\n    return `${aDiff}\\n\\n${bDiff}`\n  }\n\n  if (omitDifference) {\n    return undefined\n  }\n\n  switch (aType) {\n    case 'string':\n      return diffLinesUnified(a.split('\\n'), b.split('\\n'), options)\n    case 'boolean':\n    case 'number':\n      return comparePrimitive(a, b, options)\n    case 'map':\n      return compareObjects(sortMap(a), sortMap(b), options)\n    case 'set':\n      return compareObjects(sortSet(a), sortSet(b), options)\n    default:\n      return compareObjects(a, b, options)\n  }\n}\n\nfunction comparePrimitive(\n  a: number | boolean,\n  b: number | boolean,\n  options?: DiffOptions,\n) {\n  const aFormat = prettyFormat(a, FORMAT_OPTIONS)\n  const bFormat = prettyFormat(b, FORMAT_OPTIONS)\n  return aFormat === bFormat\n    ? ''\n    : diffLinesUnified(aFormat.split('\\n'), bFormat.split('\\n'), options)\n}\n\nfunction sortMap(map: Map<unknown, unknown>) {\n  return new Map(Array.from(map.entries()).sort())\n}\n\nfunction sortSet(set: Set<unknown>) {\n  return new Set(Array.from(set.values()).sort())\n}\n\nfunction compareObjects(\n  a: Record<string, any>,\n  b: Record<string, any>,\n  options?: DiffOptions,\n) {\n  let difference\n  let hasThrown = false\n\n  try {\n    const formatOptions = getFormatOptions(FORMAT_OPTIONS, options)\n    difference = getObjectsDifference(a, b, formatOptions, options)\n  }\n  catch {\n    hasThrown = true\n  }\n\n  const noDiffMessage = getCommonMessage(NO_DIFF_MESSAGE, options)\n  // If the comparison yields no results, compare again but this time\n  // without calling `toJSON`. It's also possible that toJSON might throw.\n  if (difference === undefined || difference === noDiffMessage) {\n    const formatOptions = getFormatOptions(FALLBACK_FORMAT_OPTIONS, options)\n    difference = getObjectsDifference(a, b, formatOptions, options)\n\n    if (difference !== noDiffMessage && !hasThrown) {\n      difference = `${getCommonMessage(\n        SIMILAR_MESSAGE,\n        options,\n      )}\\n\\n${difference}`\n    }\n  }\n\n  return difference\n}\n\nfunction getFormatOptions(\n  formatOptions: PrettyFormatOptions,\n  options?: DiffOptions,\n): PrettyFormatOptions {\n  const { compareKeys, printBasicPrototype, maxDepth } = normalizeDiffOptions(options)\n\n  return {\n    ...formatOptions,\n    compareKeys,\n    printBasicPrototype,\n    maxDepth: maxDepth ?? formatOptions.maxDepth,\n  }\n}\n\nfunction getObjectsDifference(\n  a: Record<string, any>,\n  b: Record<string, any>,\n  formatOptions: PrettyFormatOptions,\n  options?: DiffOptions,\n): string {\n  const formatOptionsZeroIndent = { ...formatOptions, indent: 0 }\n  const aCompare = prettyFormat(a, formatOptionsZeroIndent)\n  const bCompare = prettyFormat(b, formatOptionsZeroIndent)\n\n  if (aCompare === bCompare) {\n    return getCommonMessage(NO_DIFF_MESSAGE, options)\n  }\n  else {\n    const aDisplay = prettyFormat(a, formatOptions)\n    const bDisplay = prettyFormat(b, formatOptions)\n\n    return diffLinesUnified2(\n      aDisplay.split('\\n'),\n      bDisplay.split('\\n'),\n      aCompare.split('\\n'),\n      bCompare.split('\\n'),\n      options,\n    )\n  }\n}\n\nconst MAX_DIFF_STRING_LENGTH = 20_000\n\nfunction isAsymmetricMatcher(data: any) {\n  const type = getSimpleType(data)\n  return type === 'Object' && typeof data.asymmetricMatch === 'function'\n}\n\nfunction isReplaceable(obj1: any, obj2: any) {\n  const obj1Type = getSimpleType(obj1)\n  const obj2Type = getSimpleType(obj2)\n  return (\n    obj1Type === obj2Type && (obj1Type === 'Object' || obj1Type === 'Array')\n  )\n}\n\nexport function printDiffOrStringify(\n  received: unknown,\n  expected: unknown,\n  options?: DiffOptions,\n): string | undefined {\n  const { aAnnotation, bAnnotation } = normalizeDiffOptions(options)\n\n  if (\n    typeof expected === 'string'\n    && typeof received === 'string'\n    && expected.length > 0\n    && received.length > 0\n    && expected.length <= MAX_DIFF_STRING_LENGTH\n    && received.length <= MAX_DIFF_STRING_LENGTH\n    && expected !== received\n  ) {\n    if (expected.includes('\\n') || received.includes('\\n')) {\n      return diffStringsUnified(expected, received, options)\n    }\n\n    const [diffs] = diffStringsRaw(expected, received, true)\n    const hasCommonDiff = diffs.some(diff => diff[0] === DIFF_EQUAL)\n\n    const printLabel = getLabelPrinter(aAnnotation, bAnnotation)\n    const expectedLine\n      = printLabel(aAnnotation)\n        + printExpected(\n          getCommonAndChangedSubstrings(diffs, DIFF_DELETE, hasCommonDiff),\n        )\n    const receivedLine\n      = printLabel(bAnnotation)\n        + printReceived(\n          getCommonAndChangedSubstrings(diffs, DIFF_INSERT, hasCommonDiff),\n        )\n\n    return `${expectedLine}\\n${receivedLine}`\n  }\n\n  // if (isLineDiffable(expected, received)) {\n  const clonedExpected = deepClone(expected, { forceWritable: true })\n  const clonedReceived = deepClone(received, { forceWritable: true })\n  const { replacedExpected, replacedActual } = replaceAsymmetricMatcher(clonedReceived, clonedExpected)\n  const difference = diff(replacedExpected, replacedActual, options)\n\n  return difference\n  // }\n\n  // const printLabel = getLabelPrinter(aAnnotation, bAnnotation)\n  // const expectedLine = printLabel(aAnnotation) + printExpected(expected)\n  // const receivedLine\n  //   = printLabel(bAnnotation)\n  //   + (stringify(expected) === stringify(received)\n  //     ? 'serializes to the same string'\n  //     : printReceived(received))\n\n  // return `${expectedLine}\\n${receivedLine}`\n}\n\nexport function replaceAsymmetricMatcher(\n  actual: any,\n  expected: any,\n  actualReplaced: WeakSet<WeakKey> = new WeakSet(),\n  expectedReplaced: WeakSet<WeakKey> = new WeakSet(),\n): {\n  replacedActual: any\n  replacedExpected: any\n} {\n  // handle asymmetric Error.cause diff\n  if (\n    actual instanceof Error\n    && expected instanceof Error\n    && typeof actual.cause !== 'undefined'\n    && typeof expected.cause === 'undefined'\n  ) {\n    delete actual.cause\n    return {\n      replacedActual: actual,\n      replacedExpected: expected,\n    }\n  }\n  if (!isReplaceable(actual, expected)) {\n    return { replacedActual: actual, replacedExpected: expected }\n  }\n  if (actualReplaced.has(actual) || expectedReplaced.has(expected)) {\n    return { replacedActual: actual, replacedExpected: expected }\n  }\n  actualReplaced.add(actual)\n  expectedReplaced.add(expected)\n  getOwnProperties(expected).forEach((key) => {\n    const expectedValue = expected[key]\n    const actualValue = actual[key]\n    if (isAsymmetricMatcher(expectedValue)) {\n      if (expectedValue.asymmetricMatch(actualValue)) {\n        // When matcher matches, replace expected with actual value\n        // so they appear the same in the diff\n        expected[key] = actualValue\n      }\n      else if ('sample' in expectedValue && expectedValue.sample !== undefined && isReplaceable(actualValue, expectedValue.sample)) {\n        // For container matchers (ArrayContaining, ObjectContaining), unwrap and recursively process\n        // Matcher doesn't match: unwrap but keep structure to show mismatch\n        const replaced = replaceAsymmetricMatcher(\n          actualValue,\n          expectedValue.sample,\n          actualReplaced,\n          expectedReplaced,\n        )\n        actual[key] = replaced.replacedActual\n        expected[key] = replaced.replacedExpected\n      }\n    }\n    else if (isAsymmetricMatcher(actualValue)) {\n      if (actualValue.asymmetricMatch(expectedValue)) {\n        actual[key] = expectedValue\n      }\n      else if ('sample' in actualValue && actualValue.sample !== undefined && isReplaceable(actualValue.sample, expectedValue)) {\n        const replaced = replaceAsymmetricMatcher(\n          actualValue.sample,\n          expectedValue,\n          actualReplaced,\n          expectedReplaced,\n        )\n        actual[key] = replaced.replacedActual\n        expected[key] = replaced.replacedExpected\n      }\n    }\n    else if (isReplaceable(actualValue, expectedValue)) {\n      const replaced = replaceAsymmetricMatcher(\n        actualValue,\n        expectedValue,\n        actualReplaced,\n        expectedReplaced,\n      )\n      actual[key] = replaced.replacedActual\n      expected[key] = replaced.replacedExpected\n    }\n  })\n  return {\n    replacedActual: actual,\n    replacedExpected: expected,\n  }\n}\n\ntype PrintLabel = (string: string) => string\nexport function getLabelPrinter(...strings: Array<string>): PrintLabel {\n  const maxLength = strings.reduce(\n    (max, string) => (string.length > max ? string.length : max),\n    0,\n  )\n  return (string: string): string =>\n    `${string}: ${' '.repeat(maxLength - string.length)}`\n}\n\nconst SPACE_SYMBOL = '\\u{00B7}' // middle dot\nfunction replaceTrailingSpaces(text: string): string {\n  return text.replace(/\\s+$/gm, spaces => SPACE_SYMBOL.repeat(spaces.length))\n}\n\nfunction printReceived(object: unknown): string {\n  return c.red(replaceTrailingSpaces(stringify(object)))\n}\nfunction printExpected(value: unknown): string {\n  return c.green(replaceTrailingSpaces(stringify(value)))\n}\n\nfunction getCommonAndChangedSubstrings(diffs: Array<Diff>, op: number, hasCommonDiff: boolean): string {\n  return diffs.reduce(\n    (reduced: string, diff: Diff): string =>\n      reduced\n      + (diff[0] === DIFF_EQUAL\n        ? diff[1]\n        : diff[0] === op\n          ? hasCommonDiff\n            ? c.inverse(diff[1])\n            : diff[1]\n          : ''),\n    '',\n  )\n}\n"
  },
  {
    "path": "packages/utils/src/diff/joinAlignedDiffs.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Diff } from './cleanupSemantic'\nimport type { DiffOptionsColor, DiffOptionsNormalized } from './types'\nimport { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from './cleanupSemantic'\n\nfunction formatTrailingSpaces(\n  line: string,\n  trailingSpaceFormatter: DiffOptionsColor,\n): string {\n  return line.replace(/\\s+$/, match => trailingSpaceFormatter(match))\n}\n\nfunction printDiffLine(\n  line: string,\n  isFirstOrLast: boolean,\n  color: DiffOptionsColor,\n  indicator: string,\n  trailingSpaceFormatter: DiffOptionsColor,\n  emptyFirstOrLastLinePlaceholder: string,\n): string {\n  return line.length !== 0\n    ? color(\n        `${indicator} ${formatTrailingSpaces(line, trailingSpaceFormatter)}`,\n      )\n    : indicator !== ' '\n      ? color(indicator)\n      : isFirstOrLast && emptyFirstOrLastLinePlaceholder.length !== 0\n        ? color(`${indicator} ${emptyFirstOrLastLinePlaceholder}`)\n        : ''\n}\n\nfunction printDeleteLine(\n  line: string,\n  isFirstOrLast: boolean,\n  {\n    aColor,\n    aIndicator,\n    changeLineTrailingSpaceColor,\n    emptyFirstOrLastLinePlaceholder,\n  }: DiffOptionsNormalized,\n): string {\n  return printDiffLine(\n    line,\n    isFirstOrLast,\n    aColor,\n    aIndicator,\n    changeLineTrailingSpaceColor,\n    emptyFirstOrLastLinePlaceholder,\n  )\n}\n\nfunction printInsertLine(\n  line: string,\n  isFirstOrLast: boolean,\n  {\n    bColor,\n    bIndicator,\n    changeLineTrailingSpaceColor,\n    emptyFirstOrLastLinePlaceholder,\n  }: DiffOptionsNormalized,\n): string {\n  return printDiffLine(\n    line,\n    isFirstOrLast,\n    bColor,\n    bIndicator,\n    changeLineTrailingSpaceColor,\n    emptyFirstOrLastLinePlaceholder,\n  )\n}\n\nfunction printCommonLine(\n  line: string,\n  isFirstOrLast: boolean,\n  {\n    commonColor,\n    commonIndicator,\n    commonLineTrailingSpaceColor,\n    emptyFirstOrLastLinePlaceholder,\n  }: DiffOptionsNormalized,\n): string {\n  return printDiffLine(\n    line,\n    isFirstOrLast,\n    commonColor,\n    commonIndicator,\n    commonLineTrailingSpaceColor,\n    emptyFirstOrLastLinePlaceholder,\n  )\n}\n\n// In GNU diff format, indexes are one-based instead of zero-based.\nfunction createPatchMark(\n  aStart: number,\n  aEnd: number,\n  bStart: number,\n  bEnd: number,\n  { patchColor }: DiffOptionsNormalized,\n): string {\n  return patchColor(\n    `@@ -${aStart + 1},${aEnd - aStart} +${bStart + 1},${bEnd - bStart} @@`,\n  )\n}\n\n// jest --no-expand\n//\n// Given array of aligned strings with inverse highlight formatting,\n// return joined lines with diff formatting (and patch marks, if needed).\nexport function joinAlignedDiffsNoExpand(\n  diffs: Array<Diff>,\n  options: DiffOptionsNormalized,\n): string {\n  const iLength = diffs.length\n  const nContextLines = options.contextLines\n  const nContextLines2 = nContextLines + nContextLines\n\n  // First pass: count output lines and see if it has patches.\n  let jLength = iLength\n  let hasExcessAtStartOrEnd = false\n  let nExcessesBetweenChanges = 0\n  let i = 0\n  while (i !== iLength) {\n    const iStart = i\n    while (i !== iLength && diffs[i][0] === DIFF_EQUAL) {\n      i += 1\n    }\n\n    if (iStart !== i) {\n      if (iStart === 0) {\n        // at start\n        if (i > nContextLines) {\n          jLength -= i - nContextLines // subtract excess common lines\n          hasExcessAtStartOrEnd = true\n        }\n      }\n      else if (i === iLength) {\n        // at end\n        const n = i - iStart\n        if (n > nContextLines) {\n          jLength -= n - nContextLines // subtract excess common lines\n          hasExcessAtStartOrEnd = true\n        }\n      }\n      else {\n        // between changes\n        const n = i - iStart\n        if (n > nContextLines2) {\n          jLength -= n - nContextLines2 // subtract excess common lines\n          nExcessesBetweenChanges += 1\n        }\n      }\n    }\n\n    while (i !== iLength && diffs[i][0] !== DIFF_EQUAL) {\n      i += 1\n    }\n  }\n\n  const hasPatch = nExcessesBetweenChanges !== 0 || hasExcessAtStartOrEnd\n  if (nExcessesBetweenChanges !== 0) {\n    jLength += nExcessesBetweenChanges + 1\n  } // add patch lines\n  else if (hasExcessAtStartOrEnd) {\n    jLength += 1\n  } // add patch line\n\n  const jLast = jLength - 1\n\n  const lines: Array<string> = []\n\n  let jPatchMark = 0 // index of placeholder line for current patch mark\n  if (hasPatch) {\n    lines.push('')\n  } // placeholder line for first patch mark\n\n  // Indexes of expected or received lines in current patch:\n  let aStart = 0\n  let bStart = 0\n  let aEnd = 0\n  let bEnd = 0\n\n  const pushCommonLine = (line: string): void => {\n    const j = lines.length\n    lines.push(printCommonLine(line, j === 0 || j === jLast, options))\n    aEnd += 1\n    bEnd += 1\n  }\n\n  const pushDeleteLine = (line: string): void => {\n    const j = lines.length\n    lines.push(printDeleteLine(line, j === 0 || j === jLast, options))\n    aEnd += 1\n  }\n\n  const pushInsertLine = (line: string): void => {\n    const j = lines.length\n    lines.push(printInsertLine(line, j === 0 || j === jLast, options))\n    bEnd += 1\n  }\n\n  // Second pass: push lines with diff formatting (and patch marks, if needed).\n  i = 0\n  while (i !== iLength) {\n    let iStart = i\n    while (i !== iLength && diffs[i][0] === DIFF_EQUAL) {\n      i += 1\n    }\n\n    if (iStart !== i) {\n      if (iStart === 0) {\n        // at beginning\n        if (i > nContextLines) {\n          iStart = i - nContextLines\n          aStart = iStart\n          bStart = iStart\n          aEnd = aStart\n          bEnd = bStart\n        }\n\n        for (let iCommon = iStart; iCommon !== i; iCommon += 1) {\n          pushCommonLine(diffs[iCommon][1])\n        }\n      }\n      else if (i === iLength) {\n        // at end\n        const iEnd = i - iStart > nContextLines ? iStart + nContextLines : i\n\n        for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {\n          pushCommonLine(diffs[iCommon][1])\n        }\n      }\n      else {\n        // between changes\n        const nCommon = i - iStart\n\n        if (nCommon > nContextLines2) {\n          const iEnd = iStart + nContextLines\n\n          for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {\n            pushCommonLine(diffs[iCommon][1])\n          }\n\n          lines[jPatchMark] = createPatchMark(\n            aStart,\n            aEnd,\n            bStart,\n            bEnd,\n            options,\n          )\n          jPatchMark = lines.length\n          lines.push('') // placeholder line for next patch mark\n\n          const nOmit = nCommon - nContextLines2\n          aStart = aEnd + nOmit\n          bStart = bEnd + nOmit\n          aEnd = aStart\n          bEnd = bStart\n\n          for (let iCommon = i - nContextLines; iCommon !== i; iCommon += 1) {\n            pushCommonLine(diffs[iCommon][1])\n          }\n        }\n        else {\n          for (let iCommon = iStart; iCommon !== i; iCommon += 1) {\n            pushCommonLine(diffs[iCommon][1])\n          }\n        }\n      }\n    }\n\n    while (i !== iLength && diffs[i][0] === DIFF_DELETE) {\n      pushDeleteLine(diffs[i][1])\n      i += 1\n    }\n\n    while (i !== iLength && diffs[i][0] === DIFF_INSERT) {\n      pushInsertLine(diffs[i][1])\n      i += 1\n    }\n  }\n\n  if (hasPatch) {\n    lines[jPatchMark] = createPatchMark(aStart, aEnd, bStart, bEnd, options)\n  }\n\n  return lines.join('\\n')\n}\n\n// jest --expand\n//\n// Given array of aligned strings with inverse highlight formatting,\n// return joined lines with diff formatting.\nexport function joinAlignedDiffsExpand(\n  diffs: Array<Diff>,\n  options: DiffOptionsNormalized,\n): string {\n  return diffs\n    .map((diff: Diff, i: number, diffs: Array<Diff>): string => {\n      const line = diff[1]\n      const isFirstOrLast = i === 0 || i === diffs.length - 1\n\n      switch (diff[0]) {\n        case DIFF_DELETE:\n          return printDeleteLine(line, isFirstOrLast, options)\n\n        case DIFF_INSERT:\n          return printInsertLine(line, isFirstOrLast, options)\n\n        default:\n          return printCommonLine(line, isFirstOrLast, options)\n      }\n    })\n    .join('\\n')\n}\n"
  },
  {
    "path": "packages/utils/src/diff/normalizeDiffOptions.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { CompareKeys } from '@vitest/pretty-format'\nimport type { DiffOptions, DiffOptionsNormalized } from './types'\nimport c from 'tinyrainbow'\n\nexport const noColor = (string: string): string => string\n\nconst DIFF_CONTEXT_DEFAULT = 5\nconst DIFF_TRUNCATE_THRESHOLD_DEFAULT = 0 // not truncate\n\nfunction getDefaultOptions(): DiffOptionsNormalized {\n  return {\n    aAnnotation: 'Expected',\n    aColor: c.green,\n    aIndicator: '-',\n    bAnnotation: 'Received',\n    bColor: c.red,\n    bIndicator: '+',\n    changeColor: c.inverse,\n    changeLineTrailingSpaceColor: noColor,\n    commonColor: c.dim,\n    commonIndicator: ' ',\n    commonLineTrailingSpaceColor: noColor,\n    compareKeys: undefined,\n    contextLines: DIFF_CONTEXT_DEFAULT,\n    emptyFirstOrLastLinePlaceholder: '',\n    expand: false,\n    includeChangeCounts: false,\n    omitAnnotationLines: false,\n    patchColor: c.yellow,\n    printBasicPrototype: false,\n    truncateThreshold: DIFF_TRUNCATE_THRESHOLD_DEFAULT,\n    truncateAnnotation: '... Diff result is truncated',\n    truncateAnnotationColor: noColor,\n  }\n}\n\nfunction getCompareKeys(compareKeys?: CompareKeys): CompareKeys {\n  return compareKeys && typeof compareKeys === 'function'\n    ? compareKeys\n    : undefined\n}\n\nfunction getContextLines(contextLines?: number): number {\n  return typeof contextLines === 'number'\n    && Number.isSafeInteger(contextLines)\n    && contextLines >= 0\n    ? contextLines\n    : DIFF_CONTEXT_DEFAULT\n}\n\n// Pure function returns options with all properties.\nexport function normalizeDiffOptions(\n  options: DiffOptions = {},\n): DiffOptionsNormalized {\n  return {\n    ...getDefaultOptions(),\n    ...options,\n    compareKeys: getCompareKeys(options.compareKeys),\n    contextLines: getContextLines(options.contextLines),\n  }\n}\n"
  },
  {
    "path": "packages/utils/src/diff/printDiffs.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Diff } from './cleanupSemantic'\nimport type { DiffOptions } from './types'\nimport { cleanupSemantic, DIFF_EQUAL } from './cleanupSemantic'\nimport { diffLinesUnified, printDiffLines } from './diffLines'\nimport diffStrings from './diffStrings'\nimport getAlignedDiffs from './getAlignedDiffs'\nimport { normalizeDiffOptions } from './normalizeDiffOptions'\n\nfunction hasCommonDiff(diffs: Array<Diff>, isMultiline: boolean): boolean {\n  if (isMultiline) {\n    // Important: Ignore common newline that was appended to multiline strings!\n    const iLast = diffs.length - 1\n    return diffs.some(\n      (diff, i) => diff[0] === DIFF_EQUAL && (i !== iLast || diff[1] !== '\\n'),\n    )\n  }\n\n  return diffs.some(diff => diff[0] === DIFF_EQUAL)\n}\n\n// Compare two strings character-by-character.\n// Format as comparison lines in which changed substrings have inverse colors.\nexport function diffStringsUnified(\n  a: string,\n  b: string,\n  options?: DiffOptions,\n): string {\n  if (a !== b && a.length !== 0 && b.length !== 0) {\n    const isMultiline = a.includes('\\n') || b.includes('\\n')\n\n    // getAlignedDiffs assumes that a newline was appended to the strings.\n    const [diffs, truncated] = diffStringsRaw(\n      isMultiline ? `${a}\\n` : a,\n      isMultiline ? `${b}\\n` : b,\n      true, // cleanupSemantic\n      options,\n    )\n\n    if (hasCommonDiff(diffs, isMultiline)) {\n      const optionsNormalized = normalizeDiffOptions(options)\n      const lines = getAlignedDiffs(diffs, optionsNormalized.changeColor)\n      return printDiffLines(lines, truncated, optionsNormalized)\n    }\n  }\n\n  // Fall back to line-by-line diff.\n  return diffLinesUnified(a.split('\\n'), b.split('\\n'), options)\n}\n\n// Compare two strings character-by-character.\n// Optionally clean up small common substrings, also known as chaff.\nexport function diffStringsRaw(\n  a: string,\n  b: string,\n  cleanup: boolean,\n  options?: DiffOptions,\n): [Array<Diff>, boolean] {\n  const [diffs, truncated] = diffStrings(a, b, options)\n\n  if (cleanup) {\n    cleanupSemantic(diffs)\n  } // impure function\n\n  return [diffs, truncated]\n}\n"
  },
  {
    "path": "packages/utils/src/diff/types.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport type { CompareKeys } from '@vitest/pretty-format'\n\nexport type DiffOptionsColor = (arg: string) => string\n\nexport interface DiffOptions {\n  aAnnotation?: string\n  aColor?: DiffOptionsColor\n  aIndicator?: string\n  bAnnotation?: string\n  bColor?: DiffOptionsColor\n  bIndicator?: string\n  changeColor?: DiffOptionsColor\n  changeLineTrailingSpaceColor?: DiffOptionsColor\n  commonColor?: DiffOptionsColor\n  commonIndicator?: string\n  commonLineTrailingSpaceColor?: DiffOptionsColor\n  contextLines?: number\n  emptyFirstOrLastLinePlaceholder?: string\n  expand?: boolean\n  includeChangeCounts?: boolean\n  omitAnnotationLines?: boolean\n  patchColor?: DiffOptionsColor\n  printBasicPrototype?: boolean\n  maxDepth?: number\n  compareKeys?: CompareKeys\n  truncateThreshold?: number\n  truncateAnnotation?: string\n  truncateAnnotationColor?: DiffOptionsColor\n}\n\nexport interface SerializedDiffOptions {\n  aAnnotation?: string\n  aIndicator?: string\n  bAnnotation?: string\n  bIndicator?: string\n  commonIndicator?: string\n  contextLines?: number\n  emptyFirstOrLastLinePlaceholder?: string\n  expand?: boolean\n  includeChangeCounts?: boolean\n  omitAnnotationLines?: boolean\n  printBasicPrototype?: boolean\n  maxDepth?: number\n  truncateThreshold?: number\n  truncateAnnotation?: string\n}\n\nexport interface DiffOptionsNormalized {\n  aAnnotation: string\n  aColor: DiffOptionsColor\n  aIndicator: string\n  bAnnotation: string\n  bColor: DiffOptionsColor\n  bIndicator: string\n  changeColor: DiffOptionsColor\n  changeLineTrailingSpaceColor: DiffOptionsColor\n  commonColor: DiffOptionsColor\n  commonIndicator: string\n  commonLineTrailingSpaceColor: DiffOptionsColor\n  compareKeys: CompareKeys\n  contextLines: number\n  emptyFirstOrLastLinePlaceholder: string\n  expand: boolean\n  includeChangeCounts: boolean\n  omitAnnotationLines: boolean\n  patchColor: DiffOptionsColor\n  printBasicPrototype: boolean\n  maxDepth?: number\n  truncateThreshold: number\n  truncateAnnotation: string\n  truncateAnnotationColor: DiffOptionsColor\n}\n"
  },
  {
    "path": "packages/utils/src/display.ts",
    "content": "import type { PrettyFormatOptions } from '@vitest/pretty-format'\nimport {\n  createDOMElementFilter,\n  format as prettyFormat,\n  plugins as prettyFormatPlugins,\n} from '@vitest/pretty-format'\nimport * as loupe from 'loupe'\n\ntype Inspect = (value: unknown, options: Options) => string\ninterface Options {\n  showHidden: boolean\n  depth: number\n  colors: boolean\n  customInspect: boolean\n  showProxy: boolean\n  maxArrayLength: number\n  breakLength: number\n  truncate: number\n  seen: unknown[]\n  inspect: Inspect\n  stylize: (value: string, styleType: string) => string\n}\n\nexport type LoupeOptions = Partial<Options>\n\nconst {\n  AsymmetricMatcher,\n  DOMCollection,\n  DOMElement,\n  Immutable,\n  ReactElement,\n  ReactTestComponent,\n} = prettyFormatPlugins\n\nconst PLUGINS = [\n  ReactTestComponent,\n  ReactElement,\n  DOMElement,\n  DOMCollection,\n  Immutable,\n  AsymmetricMatcher,\n]\n\nexport interface StringifyOptions extends PrettyFormatOptions {\n  maxLength?: number\n  filterNode?: string | ((node: any) => boolean)\n}\n\nexport function stringify(\n  object: unknown,\n  maxDepth = 10,\n  { maxLength, filterNode, ...options }: StringifyOptions = {},\n): string {\n  const MAX_LENGTH = maxLength ?? 10000\n  let result\n\n  // Convert string selector to filter function\n  const filterFn = typeof filterNode === 'string'\n    ? createNodeFilterFromSelector(filterNode)\n    : filterNode\n\n  const plugins = filterFn\n    ? [\n        ReactTestComponent,\n        ReactElement,\n        createDOMElementFilter(filterFn),\n        DOMCollection,\n        Immutable,\n        AsymmetricMatcher,\n      ]\n    : PLUGINS\n\n  try {\n    result = prettyFormat(object, {\n      maxDepth,\n      escapeString: false,\n      // min: true,\n      plugins,\n      ...options,\n    })\n  }\n  catch {\n    result = prettyFormat(object, {\n      callToJSON: false,\n      maxDepth,\n      escapeString: false,\n      // min: true,\n      plugins,\n      ...options,\n    })\n  }\n\n  // Prevents infinite loop https://github.com/vitest-dev/vitest/issues/7249\n  return result.length >= MAX_LENGTH && maxDepth > 1\n    ? stringify(object, Math.floor(Math.min(maxDepth, Number.MAX_SAFE_INTEGER) / 2), { maxLength, filterNode, ...options })\n    : result\n}\n\nfunction createNodeFilterFromSelector(selector: string): (node: any) => boolean {\n  const ELEMENT_NODE = 1\n  const COMMENT_NODE = 8\n\n  return (node: any) => {\n    // Filter out comments\n    if (node.nodeType === COMMENT_NODE) {\n      return false\n    }\n\n    // Filter out elements matching the selector\n    if (node.nodeType === ELEMENT_NODE && node.matches) {\n      try {\n        return !node.matches(selector)\n      }\n      catch {\n        return true\n      }\n    }\n\n    return true\n  }\n}\n\nexport const formatRegExp: RegExp = /%[sdjifoOc%]/g\n\ninterface FormatOptions {\n  prettifyObject?: boolean\n}\n\nfunction baseFormat(args: unknown[], options: FormatOptions = {}): string {\n  const formatArg = (item: unknown, inspecOptions?: LoupeOptions) => {\n    if (options.prettifyObject) {\n      return stringify(item, undefined, {\n        printBasicPrototype: false,\n        escapeString: false,\n      })\n    }\n    return inspect(item, inspecOptions)\n  }\n\n  if (typeof args[0] !== 'string') {\n    const objects = []\n    for (let i = 0; i < args.length; i++) {\n      objects.push(formatArg(args[i], { depth: 0, colors: false }))\n    }\n    return objects.join(' ')\n  }\n\n  const len = args.length\n  let i = 1\n  const template = args[0]\n  let str = String(template).replace(formatRegExp, (x) => {\n    if (x === '%%') {\n      return '%'\n    }\n    if (i >= len) {\n      return x\n    }\n    switch (x) {\n      case '%s': {\n        const value = args[i++]\n        if (typeof value === 'bigint') {\n          return `${value.toString()}n`\n        }\n        if (typeof value === 'number' && value === 0 && 1 / value < 0) {\n          return '-0'\n        }\n        if (typeof value === 'object' && value !== null) {\n          if (typeof value.toString === 'function' && value.toString !== Object.prototype.toString) {\n            return value.toString()\n          }\n          return formatArg(value, { depth: 0, colors: false })\n        }\n        return String(value)\n      }\n      case '%d': {\n        const value = args[i++]\n        if (typeof value === 'bigint') {\n          return `${value.toString()}n`\n        }\n        if (typeof value === 'symbol') {\n          return 'NaN'\n        }\n        return Number(value).toString()\n      }\n      case '%i': {\n        const value = args[i++]\n        if (typeof value === 'bigint') {\n          return `${value.toString()}n`\n        }\n        return Number.parseInt(String(value)).toString()\n      }\n      case '%f':\n        return Number.parseFloat(String(args[i++])).toString()\n      case '%o':\n        return formatArg(args[i++], { showHidden: true, showProxy: true })\n      case '%O':\n        return formatArg(args[i++])\n      case '%c': {\n        i++\n        return ''\n      }\n      case '%j':\n        try {\n          return JSON.stringify(args[i++])\n        }\n        catch (err: any) {\n          const m = err.message\n          if (\n            // chromium\n            m.includes('circular structure')\n            // safari\n            || m.includes('cyclic structures')\n            // firefox\n            || m.includes('cyclic object')\n          ) {\n            return '[Circular]'\n          }\n          throw err\n        }\n      default:\n        return x\n    }\n  })\n\n  for (let x = args[i]; i < len; x = args[++i]) {\n    if (x === null || typeof x !== 'object') {\n      str += ` ${typeof x === 'symbol' ? x.toString() : x}`\n    }\n    else {\n      str += ` ${formatArg(x)}`\n    }\n  }\n  return str\n}\n\nexport function format(...args: unknown[]): string {\n  return baseFormat(args)\n}\n\nexport function browserFormat(...args: unknown[]): string {\n  return baseFormat(args, { prettifyObject: true })\n}\n\nexport function inspect(obj: unknown, options: LoupeOptions = {}): string {\n  if (options.truncate === 0) {\n    options.truncate = Number.POSITIVE_INFINITY\n  }\n  return loupe.inspect(obj, options)\n}\n\nexport function objDisplay(obj: unknown, options: LoupeOptions = {}): string {\n  if (typeof options.truncate === 'undefined') {\n    options.truncate = 40\n  }\n  const str = inspect(obj, options)\n  const type = Object.prototype.toString.call(obj)\n\n  if (options.truncate && str.length >= options.truncate) {\n    if (type === '[object Function]') {\n      const fn = obj as () => void\n      return !fn.name ? '[Function]' : `[Function: ${fn.name}]`\n    }\n    else if (type === '[object Array]') {\n      return `[ Array(${(obj as []).length}) ]`\n    }\n    else if (type === '[object Object]') {\n      const keys = Object.keys(obj as object)\n      const kstr\n        = keys.length > 2\n          ? `${keys.splice(0, 2).join(', ')}, ...`\n          : keys.join(', ')\n      return `{ Object (${kstr}) }`\n    }\n    else {\n      return str\n    }\n  }\n  return str\n}\n"
  },
  {
    "path": "packages/utils/src/error.ts",
    "content": "import type { DiffOptions } from './diff'\nimport type { TestError } from './types'\nimport { printDiffOrStringify } from './diff'\nimport { stringify } from './display'\nimport { serializeValue } from './serialize'\n\nexport { serializeValue as serializeError }\n\nexport function processError(\n  _err: any,\n  diffOptions?: DiffOptions,\n  seen: WeakSet<WeakKey> = new WeakSet(),\n): TestError {\n  if (!_err || typeof _err !== 'object') {\n    return { message: String(_err) }\n  }\n  const err = _err as TestError\n\n  if (\n    err.showDiff\n    || (err.showDiff === undefined\n      && err.expected !== undefined\n      && err.actual !== undefined)\n  ) {\n    err.diff = printDiffOrStringify(err.actual, err.expected, {\n      ...diffOptions,\n      ...err.diffOptions as DiffOptions,\n    })\n  }\n\n  if ('expected' in err && typeof err.expected !== 'string') {\n    err.expected = stringify(err.expected, 10)\n  }\n  if ('actual' in err && typeof err.actual !== 'string') {\n    err.actual = stringify(err.actual, 10)\n  }\n\n  // some Error implementations may not allow rewriting cause\n  // in most cases, the assignment will lead to \"err.cause = err.cause\"\n  try {\n    if (!seen.has(err) && typeof err.cause === 'object') {\n      seen.add(err)\n      err.cause = processError(err.cause, diffOptions, seen)\n    }\n  }\n  catch {}\n\n  try {\n    return serializeValue(err)\n  }\n  catch (e: any) {\n    return serializeValue(\n      new Error(\n        `Failed to fully serialize error: ${e?.message}\\nInner error message: ${err?.message}`,\n      ),\n    )\n  }\n}\n"
  },
  {
    "path": "packages/utils/src/helpers.ts",
    "content": "import type { Arrayable, Nullable } from './types'\nimport { NULL_BYTE_PLACEHOLDER, VALID_ID_PREFIX } from './constants'\n\ninterface CloneOptions {\n  forceWritable?: boolean\n}\n\ninterface ErrorOptions {\n  message?: string\n  stackTraceLimit?: number\n}\n\nexport { nanoid } from './nanoid'\nexport { shuffle } from './random'\n\n/**\n * Get original stacktrace without source map support the most performant way.\n * - Create only 1 stack frame.\n * - Rewrite prepareStackTrace to bypass \"support-stack-trace\" (usually takes ~250ms).\n */\nexport function createSimpleStackTrace(options?: ErrorOptions): string {\n  const { message = '$$stack trace error', stackTraceLimit = 1 }\n    = options || {}\n  const limit = Error.stackTraceLimit\n  const prepareStackTrace = Error.prepareStackTrace\n  Error.stackTraceLimit = stackTraceLimit\n  Error.prepareStackTrace = e => e.stack\n  const err = new Error(message)\n  const stackTrace = err.stack || ''\n  Error.prepareStackTrace = prepareStackTrace\n  Error.stackTraceLimit = limit\n  return stackTrace\n}\n\nexport function notNullish<T>(v: T | null | undefined): v is NonNullable<T> {\n  return v != null\n}\n\nexport function assertTypes(\n  value: unknown,\n  name: string,\n  types: string[],\n): void {\n  const receivedType = typeof value\n  const pass = types.includes(receivedType)\n  if (!pass) {\n    throw new TypeError(\n      `${name} value must be ${types.join(' or ')}, received \"${receivedType}\"`,\n    )\n  }\n}\n\nexport function isPrimitive(value: unknown): boolean {\n  return (\n    value === null || (typeof value !== 'function' && typeof value !== 'object')\n  )\n}\n\nexport function slash(path: string): string {\n  return path.replace(/\\\\/g, '/')\n}\n\nconst postfixRE = /[?#].*$/\nexport function cleanUrl(url: string): string {\n  return url.replace(postfixRE, '')\n}\n\nconst externalRE = /^(?:[a-z]+:)?\\/\\//\nexport const isExternalUrl = (url: string): boolean => externalRE.test(url)\n\n/**\n * Prepend `/@id/` and replace null byte so the id is URL-safe.\n * This is prepended to resolved ids that are not valid browser\n * import specifiers by the importAnalysis plugin.\n */\nexport function wrapId(id: string): string {\n  return id.startsWith(VALID_ID_PREFIX)\n    ? id\n    : VALID_ID_PREFIX + id.replace('\\0', NULL_BYTE_PLACEHOLDER)\n}\n\n/**\n * Undo {@link wrapId}'s `/@id/` and null byte replacements.\n */\nexport function unwrapId(id: string): string {\n  return id.startsWith(VALID_ID_PREFIX)\n    ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, '\\0')\n    : id\n}\n\nexport function withTrailingSlash(path: string): string {\n  if (path.at(-1) !== '/') {\n    return `${path}/`\n  }\n  return path\n}\n\nexport function filterOutComments(s: string): string {\n  const result: string[] = []\n  let commentState: 'none' | 'singleline' | 'multiline' = 'none'\n  for (let i = 0; i < s.length; ++i) {\n    if (commentState === 'singleline') {\n      if (s[i] === '\\n') {\n        commentState = 'none'\n      }\n    }\n    else if (commentState === 'multiline') {\n      if (s[i - 1] === '*' && s[i] === '/') {\n        commentState = 'none'\n      }\n    }\n    else if (commentState === 'none') {\n      if (s[i] === '/' && s[i + 1] === '/') {\n        commentState = 'singleline'\n      }\n      else if (s[i] === '/' && s[i + 1] === '*') {\n        commentState = 'multiline'\n        i += 2\n      }\n      else {\n        result.push(s[i])\n      }\n    }\n  }\n  return result.join('')\n}\n\nconst bareImportRE = /^(?![a-z]:)[\\w@](?!.*:\\/\\/)/i\n\nexport function isBareImport(id: string): boolean {\n  return bareImportRE.test(id)\n}\n\nexport function toArray<T>(array?: Nullable<Arrayable<T>>): Array<T> {\n  if (array === null || array === undefined) {\n    array = []\n  }\n\n  if (Array.isArray(array)) {\n    return array\n  }\n\n  return [array]\n}\n\nexport function isObject(item: unknown): boolean {\n  return item != null && typeof item === 'object' && !Array.isArray(item)\n}\n\nfunction isFinalObj(obj: any) {\n  return (\n    obj === Object.prototype\n    || obj === Function.prototype\n    || obj === RegExp.prototype\n  )\n}\n\nexport function getType(value: unknown): string {\n  return Object.prototype.toString.apply(value).slice(8, -1)\n}\n\nfunction collectOwnProperties(\n  obj: any,\n  collector: Set<string | symbol> | ((key: string | symbol) => void),\n) {\n  const collect\n    = typeof collector === 'function'\n      ? collector\n      : (key: string | symbol) => collector.add(key)\n  Object.getOwnPropertyNames(obj).forEach(collect)\n  Object.getOwnPropertySymbols(obj).forEach(collect)\n}\n\nexport function getOwnProperties(obj: any): (string | symbol)[] {\n  const ownProps = new Set<string | symbol>()\n  if (isFinalObj(obj)) {\n    return []\n  }\n  collectOwnProperties(obj, ownProps)\n  return Array.from(ownProps)\n}\n\nconst defaultCloneOptions: CloneOptions = { forceWritable: false }\n\nexport function deepClone<T>(\n  val: T,\n  options: CloneOptions = defaultCloneOptions,\n): T {\n  const seen = new WeakMap()\n  return clone(val, seen, options)\n}\n\nexport function clone<T>(\n  val: T,\n  seen: WeakMap<any, any>,\n  options: CloneOptions = defaultCloneOptions,\n): T {\n  let k: any, out: any\n  if (seen.has(val)) {\n    return seen.get(val)\n  }\n  if (Array.isArray(val)) {\n    out = Array.from({ length: (k = val.length) })\n    seen.set(val, out)\n    while (k--) {\n      out[k] = clone(val[k], seen, options)\n    }\n    return out as any\n  }\n\n  if (Object.prototype.toString.call(val) === '[object Object]') {\n    out = Object.create(Object.getPrototypeOf(val))\n    seen.set(val, out)\n    // we don't need properties from prototype\n    const props = getOwnProperties(val)\n    for (const k of props) {\n      const descriptor = Object.getOwnPropertyDescriptor(val, k)\n      if (!descriptor) {\n        continue\n      }\n      const cloned = clone((val as any)[k], seen, options)\n      if (options.forceWritable) {\n        Object.defineProperty(out, k, {\n          enumerable: descriptor.enumerable,\n          configurable: true,\n          writable: true,\n          value: cloned,\n        })\n      }\n      else if ('get' in descriptor) {\n        Object.defineProperty(out, k, {\n          ...descriptor,\n          get() {\n            return cloned\n          },\n        })\n      }\n      else {\n        Object.defineProperty(out, k, {\n          ...descriptor,\n          value: cloned,\n        })\n      }\n    }\n    return out\n  }\n\n  return val\n}\n\nexport function noop(): void {}\n\nexport function objectAttr(\n  source: any,\n  path: string,\n  defaultValue = undefined,\n): any {\n  // a[3].b -> a.3.b\n  const paths = path.replace(/\\[(\\d+)\\]/g, '.$1').split('.')\n  let result = source\n  for (const p of paths) {\n    result = (new Object(result) as any)[p]\n    if (result === undefined) {\n      return defaultValue\n    }\n  }\n  return result\n}\n\nexport type DeferPromise<T> = Promise<T> & {\n  resolve: (value: T | PromiseLike<T>) => void\n  reject: (reason?: any) => void\n}\n\nexport function createDefer<T>(): DeferPromise<T> {\n  let resolve: ((value: T | PromiseLike<T>) => void) | null = null\n  let reject: ((reason?: any) => void) | null = null\n\n  const p = new Promise<T>((_resolve, _reject) => {\n    resolve = _resolve\n    reject = _reject\n  }) as DeferPromise<T>\n\n  p.resolve = resolve!\n  p.reject = reject!\n  return p\n}\n\n/**\n * If code starts with a function call, will return its last index, respecting arguments.\n * This will return 25 - last ending character of toMatch \")\"\n * Also works with callbacks\n * ```\n * toMatch({ test: '123' });\n * toBeAliased('123')\n * ```\n */\nexport function getCallLastIndex(code: string): number | null {\n  let charIndex = -1\n  let inString: string | null = null\n  let startedBracers = 0\n  let endedBracers = 0\n  let beforeChar: string | null = null\n  while (charIndex <= code.length) {\n    beforeChar = code[charIndex]\n    charIndex++\n    const char = code[charIndex]\n\n    const isCharString = char === '\"' || char === '\\'' || char === '`'\n\n    if (isCharString && beforeChar !== '\\\\') {\n      if (inString === char) {\n        inString = null\n      }\n      else if (!inString) {\n        inString = char\n      }\n    }\n\n    if (!inString) {\n      if (char === '(') {\n        startedBracers++\n      }\n      if (char === ')') {\n        endedBracers++\n      }\n    }\n\n    if (startedBracers && endedBracers && startedBracers === endedBracers) {\n      return charIndex\n    }\n  }\n  return null\n}\n\nexport function isNegativeNaN(val: number): boolean {\n  if (!Number.isNaN(val)) {\n    return false\n  }\n  const f64 = new Float64Array(1)\n  f64[0] = val\n  const u32 = new Uint32Array(f64.buffer)\n  const isNegative = u32[1] >>> 31 === 1\n\n  return isNegative\n}\n\nfunction toString(v: any) {\n  return Object.prototype.toString.call(v)\n}\n\nfunction isPlainObject(val: any): val is object {\n  return (\n    toString(val) === '[object Object]'\n    && (!val.constructor || val.constructor.name === 'Object')\n  )\n}\n\nfunction isMergeableObject(item: any): item is object {\n  return isPlainObject(item) && !Array.isArray(item)\n}\n\nexport function ordinal(i: number): string {\n  const j = i % 10\n  const k = i % 100\n\n  if (j === 1 && k !== 11) {\n    return `${i}st`\n  }\n\n  if (j === 2 && k !== 12) {\n    return `${i}nd`\n  }\n\n  if (j === 3 && k !== 13) {\n    return `${i}rd`\n  }\n\n  return `${i}th`\n}\n\n/**\n * Deep merge :P\n *\n * Will merge objects only if they are plain\n *\n * Do not merge types - it is very expensive and usually it's better to case a type here\n */\nexport function deepMerge<T extends object = object>(\n  target: T,\n  ...sources: any[]\n): T {\n  if (!sources.length) {\n    return target as any\n  }\n\n  const source = sources.shift()\n  if (source === undefined) {\n    return target as any\n  }\n\n  if (isMergeableObject(target) && isMergeableObject(source)) {\n    (Object.keys(source) as (keyof T)[]).forEach((key) => {\n      const _source = source as T\n      if (isMergeableObject(_source[key])) {\n        if (!target[key]) {\n          target[key] = {} as any\n        }\n\n        deepMerge(target[key] as any, _source[key])\n      }\n      else {\n        target[key] = _source[key] as any\n      }\n    })\n  }\n\n  return deepMerge(target, ...sources)\n}\n\nexport function unique<T>(array: T[]): T[] {\n  return Array.from(new Set(array))\n}\n"
  },
  {
    "path": "packages/utils/src/index.ts",
    "content": "export type { LoupeOptions, StringifyOptions } from './display'\nexport type { DeferPromise } from './helpers'\nexport type { SafeTimers } from './timers'\nexport type {\n  ArgumentsType,\n  Arrayable,\n  Awaitable,\n  Constructable,\n  DeepMerge,\n  MergeInsertions,\n  Nullable,\n  ParsedStack,\n  SerializedError,\n  TestError,\n} from './types'\n"
  },
  {
    "path": "packages/utils/src/nanoid.ts",
    "content": "// port from nanoid\n// https://github.com/ai/nanoid\nconst urlAlphabet\n  = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\nexport function nanoid(size = 21): string {\n  let id = ''\n  let i = size\n  while (i--) {\n    id += urlAlphabet[(Math.random() * 64) | 0]\n  }\n  return id\n}\n"
  },
  {
    "path": "packages/utils/src/offset.ts",
    "content": "export const lineSplitRE: RegExp = /\\r?\\n/\n\nexport function positionToOffset(\n  source: string,\n  lineNumber: number,\n  columnNumber: number,\n): number {\n  const lines = source.split(lineSplitRE)\n  const nl = /\\r\\n/.test(source) ? 2 : 1\n  let start = 0\n\n  if (lineNumber > lines.length) {\n    return source.length\n  }\n\n  for (let i = 0; i < lineNumber - 1; i++) {\n    start += lines[i].length + nl\n  }\n\n  return start + columnNumber\n}\n\nexport function offsetToLineNumber(source: string, offset: number): number {\n  if (offset > source.length) {\n    throw new Error(\n      `offset is longer than source length! offset ${offset} > length ${source.length}`,\n    )\n  }\n  const lines = source.split(lineSplitRE)\n  const nl = /\\r\\n/.test(source) ? 2 : 1\n  let counted = 0\n  let line = 0\n  for (; line < lines.length; line++) {\n    const lineLength = lines[line].length + nl\n    if (counted + lineLength >= offset) {\n      break\n    }\n\n    counted += lineLength\n  }\n  return line + 1\n}\n"
  },
  {
    "path": "packages/utils/src/random.ts",
    "content": "const RealDate = Date\n\nfunction random(seed: number) {\n  const x = Math.sin(seed++) * 10000\n  return x - Math.floor(x)\n}\n\nexport function shuffle<T>(array: T[], seed: number = RealDate.now()): T[] {\n  let length = array.length\n\n  while (length) {\n    const index = Math.floor(random(seed) * length--)\n\n    const previous = array[length]\n    array[length] = array[index]\n    array[index] = previous\n    ++seed\n  }\n\n  return array\n}\n"
  },
  {
    "path": "packages/utils/src/resolver.ts",
    "content": "import fs from 'node:fs'\nimport { dirname, join } from 'pathe'\n\nconst packageCache = new Map<string, { type?: 'module' | 'commonjs' }>()\n\nexport function findNearestPackageData(\n  basedir: string,\n): { type?: 'module' | 'commonjs' } {\n  const originalBasedir = basedir\n  while (basedir) {\n    const cached = getCachedData(packageCache, basedir, originalBasedir)\n    if (cached) {\n      return cached\n    }\n\n    const pkgPath = join(basedir, 'package.json')\n    if (tryStatSync(pkgPath)?.isFile()) {\n      const pkgData = JSON.parse(stripBomTag(fs.readFileSync(pkgPath, 'utf8')))\n\n      if (packageCache) {\n        setCacheData(packageCache, pkgData, basedir, originalBasedir)\n      }\n\n      return pkgData\n    }\n\n    const nextBasedir = dirname(basedir)\n    if (nextBasedir === basedir) {\n      break\n    }\n    basedir = nextBasedir\n  }\n\n  return {}\n}\n\nfunction stripBomTag(content: string): string {\n  if (content.charCodeAt(0) === 0xFEFF) {\n    return content.slice(1)\n  }\n\n  return content\n}\n\nfunction tryStatSync(file: string): fs.Stats | undefined {\n  try {\n    // The \"throwIfNoEntry\" is a performance optimization for cases where the file does not exist\n    return fs.statSync(file, { throwIfNoEntry: false })\n  }\n  catch {\n    // Ignore errors\n  }\n}\n\nexport function getCachedData<T>(\n  cache: Map<string, T>,\n  basedir: string,\n  originalBasedir: string,\n): NonNullable<T> | undefined {\n  const pkgData = cache.get(getFnpdCacheKey(basedir))\n  if (pkgData) {\n    traverseBetweenDirs(originalBasedir, basedir, (dir) => {\n      cache.set(getFnpdCacheKey(dir), pkgData)\n    })\n    return pkgData\n  }\n}\n\nexport function setCacheData<T>(\n  cache: Map<string, T>,\n  data: T,\n  basedir: string,\n  originalBasedir: string,\n): void {\n  cache.set(getFnpdCacheKey(basedir), data)\n  traverseBetweenDirs(originalBasedir, basedir, (dir) => {\n    cache.set(getFnpdCacheKey(dir), data)\n  })\n}\n\nfunction getFnpdCacheKey(basedir: string) {\n  return `fnpd_${basedir}`\n}\n\n/**\n * Traverse between `longerDir` (inclusive) and `shorterDir` (exclusive) and call `cb` for each dir.\n * @param longerDir Longer dir path, e.g. `/User/foo/bar/baz`\n * @param shorterDir Shorter dir path, e.g. `/User/foo`\n */\nfunction traverseBetweenDirs(\n  longerDir: string,\n  shorterDir: string,\n  cb: (dir: string) => void,\n) {\n  while (longerDir !== shorterDir) {\n    cb(longerDir)\n    longerDir = dirname(longerDir)\n  }\n}\n"
  },
  {
    "path": "packages/utils/src/serialize.ts",
    "content": "// utils is bundled for any environment and might not support `Element`\ndeclare class Element {\n  tagName: string\n}\n\nconst IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@'\nconst IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@'\n\nfunction isImmutable(v: any) {\n  return v && (v[IS_COLLECTION_SYMBOL] || v[IS_RECORD_SYMBOL])\n}\n\nconst OBJECT_PROTO = Object.getPrototypeOf({})\n\nfunction getUnserializableMessage(err: unknown) {\n  if (err instanceof Error) {\n    return `<unserializable>: ${err.message}`\n  }\n  if (typeof err === 'string') {\n    return `<unserializable>: ${err}`\n  }\n  return '<unserializable>'\n}\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm\nexport function serializeValue(val: any, seen: WeakMap<WeakKey, any> = new WeakMap()): any {\n  if (!val || typeof val === 'string') {\n    return val\n  }\n  if (val instanceof Error && 'toJSON' in val && typeof val.toJSON === 'function') {\n    const jsonValue = val.toJSON()\n\n    if (jsonValue && jsonValue !== val && typeof jsonValue === 'object') {\n      if (typeof val.message === 'string') {\n        safe(() => jsonValue.message ??= normalizeErrorMessage(val.message))\n      }\n      if (typeof val.stack === 'string') {\n        safe(() => jsonValue.stack ??= val.stack)\n      }\n      if (typeof val.name === 'string') {\n        safe(() => jsonValue.name ??= val.name)\n      }\n      if (val.cause != null) {\n        safe(() => jsonValue.cause ??= serializeValue(val.cause, seen))\n      }\n    }\n    return serializeValue(jsonValue, seen)\n  }\n  if (typeof val === 'function') {\n    return `Function<${val.name || 'anonymous'}>`\n  }\n  if (typeof val === 'symbol') {\n    return val.toString()\n  }\n  if (typeof val !== 'object') {\n    return val\n  }\n  if (typeof Buffer !== 'undefined' && val instanceof Buffer) {\n    return `<Buffer(${val.length}) ...>`\n  }\n  if (typeof Uint8Array !== 'undefined' && val instanceof Uint8Array) {\n    return `<Uint8Array(${val.length}) ...>`\n  }\n  // cannot serialize immutables as immutables\n  if (isImmutable(val)) {\n    return serializeValue(val.toJSON(), seen)\n  }\n  if (\n    val instanceof Promise\n    || (val.constructor && val.constructor.prototype === 'AsyncFunction')\n  ) {\n    return 'Promise'\n  }\n  if (typeof Element !== 'undefined' && val instanceof Element) {\n    return val.tagName\n  }\n  if (typeof val.toJSON === 'function') {\n    return serializeValue(val.toJSON(), seen)\n  }\n\n  if (seen.has(val)) {\n    return seen.get(val)\n  }\n\n  if (Array.isArray(val)) {\n    // eslint-disable-next-line unicorn/no-new-array -- we need to keep sparse arrays ([1,,3])\n    const clone: any[] = new Array(val.length)\n    seen.set(val, clone)\n    val.forEach((e, i) => {\n      try {\n        clone[i] = serializeValue(e, seen)\n      }\n      catch (err) {\n        clone[i] = getUnserializableMessage(err)\n      }\n    })\n    return clone\n  }\n  else {\n    // Objects with `Error` constructors appear to cause problems during worker communication\n    // using `MessagePort`, so the serialized error object is being recreated as plain object.\n    const clone = Object.create(null)\n    seen.set(val, clone)\n\n    let obj = val\n    while (obj && obj !== OBJECT_PROTO) {\n      Object.getOwnPropertyNames(obj).forEach((key) => {\n        if (key in clone) {\n          return\n        }\n        try {\n          clone[key] = serializeValue(val[key], seen)\n        }\n        catch (err) {\n          // delete in case it has a setter from prototype that might throw\n          delete clone[key]\n          clone[key] = getUnserializableMessage(err)\n        }\n      })\n      obj = Object.getPrototypeOf(obj)\n    }\n    if (val instanceof Error) {\n      safe(() => clone.message = normalizeErrorMessage(val.message))\n    }\n    return clone\n  }\n}\n\nfunction safe(fn: () => void) {\n  try {\n    return fn()\n  }\n  catch {\n    // ignore\n  }\n}\n\nfunction normalizeErrorMessage(message: string) {\n  return message\n    // vite 7+\n    .replace(/\\(0\\s?,\\s?__vite_ssr_import_\\d+__.(\\w+)\\)/g, '$1')\n    // vite <7\n    .replace(/__(vite_ssr_import|vi_import)_\\d+__\\./g, '')\n    // vitest-browser-* errors will have __vitest_<componentId>__ in their messages\n    .replace(/getByTestId('__vitest_\\d+__')/g, 'page')\n}\n"
  },
  {
    "path": "packages/utils/src/source-map/node.ts",
    "content": "import { existsSync, readFileSync } from 'node:fs'\nimport path from 'node:path'\nimport convertSourceMap from 'convert-source-map'\n\ninterface ExtractedSourceMap {\n  map: any\n}\n\n// based on vite\n// https://github.com/vitejs/vite/blob/84079a84ad94de4c1ef4f1bdb2ab448ff2c01196/packages/vite/src/node/server/sourcemap.ts#L149\nexport function extractSourcemapFromFile(\n  code: string,\n  filePath: string,\n): ExtractedSourceMap | undefined {\n  const map = (\n    convertSourceMap.fromSource(code)\n    || convertSourceMap.fromMapFileSource(\n      code,\n      createConvertSourceMapReadMap(filePath),\n    )\n  )?.toObject()\n  return map ? { map } : undefined\n}\n\nfunction createConvertSourceMapReadMap(originalFileName: string) {\n  return (filename: string) => {\n    // convertSourceMap can detect invalid filename from comments.\n    // fallback to empty source map to avoid errors.\n    const targetPath = path.resolve(path.dirname(originalFileName), filename)\n    if (existsSync(targetPath)) {\n      return readFileSync(targetPath, 'utf-8')\n    }\n    return '{}'\n  }\n}\n"
  },
  {
    "path": "packages/utils/src/source-map.ts",
    "content": "import type { OriginalMapping } from '@jridgewell/trace-mapping'\nimport type { ParsedStack, TestError } from './types'\nimport { originalPositionFor } from '@jridgewell/trace-mapping'\nimport { resolve } from 'pathe'\nimport { isPrimitive, notNullish } from './helpers'\n\nexport interface StackTraceParserOptions {\n  ignoreStackEntries?: (RegExp | string)[]\n  getSourceMap?: (file: string) => unknown\n  getUrlId?: (id: string) => string\n  frameFilter?: (error: TestError, frame: ParsedStack) => boolean | void\n}\n\nconst CHROME_IE_STACK_REGEXP = /^\\s*at .*(?:\\S:\\d+|\\(native\\))/m\nconst SAFARI_NATIVE_CODE_REGEXP = /^(?:eval@)?(?:\\[native code\\])?$/\n\nconst stackIgnorePatterns: (string | RegExp)[] = [\n  'node:internal',\n  /\\/packages\\/\\w+\\/dist\\//,\n  /\\/@vitest\\/\\w+\\/dist\\//,\n  '/vitest/dist/',\n  '/vitest/src/',\n  '/node_modules/chai/',\n  '/node_modules/tinyspy/',\n  '/vite/dist/node/module-runner',\n  '/rolldown-vite/dist/node/module-runner',\n  // browser related deps\n  '/deps/chunk-',\n  '/deps/@vitest',\n  '/deps/loupe',\n  '/deps/chai',\n  '/browser-playwright/dist/locators.js',\n  '/browser-webdriverio/dist/locators.js',\n  '/browser-preview/dist/locators.js',\n  /node:\\w+/,\n  /__vitest_test__/,\n  /__vitest_browser__/,\n  '/@id/__x00__vitest/browser',\n  /\\/deps\\/vitest_/,\n]\n\nexport { stackIgnorePatterns as defaultStackIgnorePatterns }\n\nconst NOW_LENGTH = Date.now().toString().length\nconst REGEXP_VITEST = new RegExp(`vitest=\\\\d{${NOW_LENGTH}}`)\n\nfunction extractLocation(urlLike: string) {\n  // Fail-fast but return locations like \"(native)\"\n  if (!urlLike.includes(':')) {\n    return [urlLike]\n  }\n\n  const regExp = /(.+?)(?::(\\d+))?(?::(\\d+))?$/\n  const parts = regExp.exec(urlLike.replace(/^\\(|\\)$/g, ''))\n  if (!parts) {\n    return [urlLike]\n  }\n  let url = parts[1]\n  if (url.startsWith('async ')) {\n    url = url.slice(6)\n  }\n  if (url.startsWith('http:') || url.startsWith('https:')) {\n    const urlObj = new URL(url)\n    urlObj.searchParams.delete('import')\n    urlObj.searchParams.delete('browserv')\n    url = urlObj.pathname + urlObj.hash + urlObj.search\n  }\n  if (url.startsWith('/@fs/')) {\n    const isWindows = /^\\/@fs\\/[a-zA-Z]:\\//.test(url)\n    url = url.slice(isWindows ? 5 : 4)\n  }\n  if (url.includes('vitest=')) {\n    url = url.replace(REGEXP_VITEST, '').replace(/[?&]$/, '')\n  }\n  return [url, parts[2] || undefined, parts[3] || undefined]\n}\n\nexport function parseSingleFFOrSafariStack(raw: string): ParsedStack | null {\n  let line = raw.trim()\n\n  if (SAFARI_NATIVE_CODE_REGEXP.test(line)) {\n    return null\n  }\n\n  if (line.includes(' > eval')) {\n    line = line.replace(\n      / line (\\d+)(?: > eval line \\d+)* > eval:\\d+:\\d+/g,\n      ':$1',\n    )\n  }\n\n  // Early return for lines that don't look like Firefox/Safari stack traces\n  // Firefox/Safari stack traces must contain '@' and should have location info after it\n  if (!line.includes('@')) {\n    return null\n  }\n\n  // Find the correct @ that separates function name from location\n  // For cases like '@https://@fs/path' or 'functionName@https://@fs/path'\n  // we need to find the first @ that precedes a valid location (containing :)\n  let atIndex = -1\n  let locationPart = ''\n  let functionName: string | undefined\n\n  // Try each @ from left to right to find the one that gives us a valid location\n  for (let i = 0; i < line.length; i++) {\n    if (line[i] === '@') {\n      const candidateLocation = line.slice(i + 1)\n      // Minimum length 3 for valid location: 1 for filename + 1 for colon + 1 for line number (e.g., \"a:1\")\n      if (candidateLocation.includes(':') && candidateLocation.length >= 3) {\n        atIndex = i\n        locationPart = candidateLocation\n        functionName = i > 0 ? line.slice(0, i) : undefined\n        break\n      }\n    }\n  }\n\n  // Validate we found a valid location with minimum length (filename:line format)\n  if (atIndex === -1 || !locationPart.includes(':') || locationPart.length < 3) {\n    return null\n  }\n  const [url, lineNumber, columnNumber] = extractLocation(locationPart)\n\n  if (!url || !lineNumber || !columnNumber) {\n    return null\n  }\n\n  return {\n    file: url,\n    method: functionName || '',\n    line: Number.parseInt(lineNumber),\n    column: Number.parseInt(columnNumber),\n  }\n}\n\nexport function parseSingleStack(raw: string): ParsedStack | null {\n  const line = raw.trim()\n  if (!CHROME_IE_STACK_REGEXP.test(line)) {\n    return parseSingleFFOrSafariStack(line)\n  }\n  return parseSingleV8Stack(line)\n}\n\n// Based on https://github.com/stacktracejs/error-stack-parser\n// Credit to stacktracejs\nexport function parseSingleV8Stack(raw: string): ParsedStack | null {\n  let line = raw.trim()\n\n  if (!CHROME_IE_STACK_REGEXP.test(line)) {\n    return null\n  }\n\n  if (line.includes('(eval ')) {\n    line = line\n      .replace(/eval code/g, 'eval')\n      .replace(/(\\(eval at [^()]*)|(,.*$)/g, '')\n  }\n\n  let sanitizedLine = line\n    .replace(/^\\s+/, '')\n    .replace(/\\(eval code/g, '(')\n    .replace(/^.*?\\s+/, '')\n\n  // capture and preserve the parenthesized location \"(/foo/my bar.js:12:87)\" in\n  // case it has spaces in it, as the string is split on \\s+ later on\n  const location = sanitizedLine.match(/ (\\(.+\\)$)/)\n\n  // remove the parenthesized location from the line, if it was matched\n  sanitizedLine = location\n    ? sanitizedLine.replace(location[0], '')\n    : sanitizedLine\n\n  // if a location was matched, pass it to extractLocation() otherwise pass all sanitizedLine\n  // because this line doesn't have function name\n  const [url, lineNumber, columnNumber] = extractLocation(\n    location ? location[1] : sanitizedLine,\n  )\n  let method = (location && sanitizedLine) || ''\n  let file = url && ['eval', '<anonymous>'].includes(url) ? undefined : url\n\n  if (!file || !lineNumber || !columnNumber) {\n    return null\n  }\n\n  if (method.startsWith('async ')) {\n    method = method.slice(6)\n  }\n\n  if (file.startsWith('file://')) {\n    file = file.slice(7)\n  }\n\n  // normalize Windows path (\\ -> /)\n  file = file.startsWith('node:') || file.startsWith('internal:')\n    ? file\n    : resolve(file)\n\n  if (method) {\n    method = method\n    // vite 7+\n      .replace(/\\(0\\s?,\\s?__vite_ssr_import_\\d+__.(\\w+)\\)/g, '$1')\n    // vite <7\n      .replace(/__(vite_ssr_import|vi_import)_\\d+__\\./g, '')\n      .replace(/(Object\\.)?__vite_ssr_export_default__\\s?/g, '')\n  }\n\n  return {\n    method,\n    file,\n    line: Number.parseInt(lineNumber),\n    column: Number.parseInt(columnNumber),\n  }\n}\n\nexport function createStackString(stacks: ParsedStack[]): string {\n  return stacks.map((stack) => {\n    const line = `${stack.file}:${stack.line}:${stack.column}`\n    if (stack.method) {\n      return `    at ${stack.method}(${line})`\n    }\n    return `    at ${line}`\n  }).join('\\n')\n}\n\nexport function parseStacktrace(\n  stack: string,\n  options: StackTraceParserOptions = {},\n): ParsedStack[] {\n  const { ignoreStackEntries = stackIgnorePatterns } = options\n  let stacks = !CHROME_IE_STACK_REGEXP.test(stack)\n    ? parseFFOrSafariStackTrace(stack)\n    : parseV8Stacktrace(stack)\n\n  // remove assertion helper's internal stacks\n  const helperIndex = stacks.findLastIndex(s => s.method === '__VITEST_HELPER__' || s.method === 'async*__VITEST_HELPER__')\n  if (helperIndex >= 0) {\n    stacks = stacks.slice(helperIndex + 1)\n  }\n\n  return stacks.map((stack) => {\n    if (options.getUrlId) {\n      stack.file = options.getUrlId(stack.file)\n    }\n\n    const map = options.getSourceMap?.(stack.file) as\n      | SourceMapLike\n      | null\n      | undefined\n    if (!map || typeof map !== 'object' || !map.version) {\n      return shouldFilter(ignoreStackEntries, stack.file) ? null : stack\n    }\n\n    const traceMap = new DecodedMap(map, stack.file)\n    const position = getOriginalPosition(traceMap, stack)\n    if (!position) {\n      return stack\n    }\n\n    const { line, column, source, name } = position\n    let file = source || stack.file\n    if (file.match(/\\/\\w:\\//)) {\n      file = file.slice(1)\n    }\n\n    if (shouldFilter(ignoreStackEntries, file)) {\n      return null\n    }\n\n    if (line != null && column != null) {\n      return {\n        line,\n        column,\n        file,\n        method: name || stack.method,\n      }\n    }\n    return stack\n  }).filter(s => s != null)\n}\n\nfunction shouldFilter(ignoreStackEntries: (string | RegExp)[], file: string): boolean {\n  return ignoreStackEntries.some(p => file.match(p))\n}\n\nfunction parseFFOrSafariStackTrace(stack: string): ParsedStack[] {\n  return stack\n    .split('\\n')\n    .map(line => parseSingleFFOrSafariStack(line))\n    .filter(notNullish)\n}\n\nfunction parseV8Stacktrace(stack: string): ParsedStack[] {\n  return stack\n    .split('\\n')\n    .map(line => parseSingleV8Stack(line))\n    .filter(notNullish)\n}\n\nexport function parseErrorStacktrace(\n  e: TestError | Error,\n  options: StackTraceParserOptions = {},\n): ParsedStack[] {\n  if (!e || isPrimitive(e)) {\n    return []\n  }\n\n  if ('stacks' in e && e.stacks) {\n    return e.stacks\n  }\n\n  const stackStr = e.stack || ''\n  // if \"stack\" property was overwritten at runtime to be something else,\n  // ignore the value because we don't know how to process it\n  let stackFrames = typeof stackStr === 'string'\n    ? parseStacktrace(stackStr, options)\n    : []\n\n  if (!stackFrames.length) {\n    const e_ = e as any\n    if (e_.fileName != null && e_.lineNumber != null && e_.columnNumber != null) {\n      stackFrames = parseStacktrace(`${e_.fileName}:${e_.lineNumber}:${e_.columnNumber}`, options)\n    }\n    if (e_.sourceURL != null && e_.line != null && e_._column != null) {\n      stackFrames = parseStacktrace(`${e_.sourceURL}:${e_.line}:${e_.column}`, options)\n    }\n  }\n\n  if (options.frameFilter) {\n    stackFrames = stackFrames.filter(\n      f => options.frameFilter!(e as TestError, f) !== false,\n    )\n  }\n\n  ;(e as TestError).stacks = stackFrames\n  return stackFrames\n}\n\ninterface SourceMapLike {\n  version: number\n  mappings?: string\n  names?: string[]\n  sources?: string[]\n  sourcesContent?: string[]\n  sourceRoot?: string\n}\n\ninterface Needle {\n  line: number\n  column: number\n}\n\nexport class DecodedMap {\n  _encoded: string\n  _decoded: undefined | number[][][]\n  _decodedMemo: Stats\n  url: string\n  version: number\n  names: string[] = []\n  resolvedSources: string[]\n\n  constructor(\n    public map: SourceMapLike,\n    from: string,\n  ) {\n    const { mappings, names, sources } = map\n    this.version = map.version\n    this.names = names || []\n    this._encoded = mappings || ''\n    this._decodedMemo = memoizedState()\n    this.url = from\n    this.resolvedSources = (sources || []).map(s =>\n      resolve(from, '..', s || ''),\n    )\n  }\n}\n\ninterface Stats {\n  lastKey: number\n  lastNeedle: number\n  lastIndex: number\n}\n\nfunction memoizedState(): Stats {\n  return {\n    lastKey: -1,\n    lastNeedle: -1,\n    lastIndex: -1,\n  }\n}\n\nexport function getOriginalPosition(\n  map: DecodedMap,\n  needle: Needle,\n): OriginalMapping | null {\n  const result = originalPositionFor(map as any, needle)\n  if (result.column == null) {\n    return null\n  }\n  return result\n}\n"
  },
  {
    "path": "packages/utils/src/timers.ts",
    "content": "const SAFE_TIMERS_SYMBOL = Symbol('vitest:SAFE_TIMERS')\n\nexport interface SafeTimers {\n  // node.js timers\n  nextTick?: (cb: () => void) => void\n  setImmediate?: {\n    <TArgs extends any[]>(\n      callback: (...args: TArgs) => void,\n      ...args: TArgs\n    ): any\n    __promisify__: <T = void>(value?: T, options?: any) => Promise<T>\n  }\n  clearImmediate?: (immediateId: any) => void\n\n  // cross-platform timers\n  setTimeout: typeof setTimeout\n  setInterval: typeof setInterval\n  clearInterval: typeof clearInterval\n  clearTimeout: typeof clearTimeout\n  queueMicrotask: typeof queueMicrotask\n}\n\nexport function getSafeTimers(): SafeTimers {\n  const {\n    setTimeout: safeSetTimeout,\n    setInterval: safeSetInterval,\n    clearInterval: safeClearInterval,\n    clearTimeout: safeClearTimeout,\n    setImmediate: safeSetImmediate,\n    clearImmediate: safeClearImmediate,\n    queueMicrotask: safeQueueMicrotask,\n  } = (globalThis as any)[SAFE_TIMERS_SYMBOL] || globalThis\n\n  const { nextTick: safeNextTick } = (globalThis as any)[SAFE_TIMERS_SYMBOL]\n    || globalThis.process || {}\n\n  return {\n    nextTick: safeNextTick,\n    setTimeout: safeSetTimeout,\n    setInterval: safeSetInterval,\n    clearInterval: safeClearInterval,\n    clearTimeout: safeClearTimeout,\n    setImmediate: safeSetImmediate,\n    clearImmediate: safeClearImmediate,\n    queueMicrotask: safeQueueMicrotask,\n  }\n}\n\nexport function setSafeTimers(): void {\n  const {\n    setTimeout: safeSetTimeout,\n    setInterval: safeSetInterval,\n    clearInterval: safeClearInterval,\n    clearTimeout: safeClearTimeout,\n    setImmediate: safeSetImmediate,\n    clearImmediate: safeClearImmediate,\n    queueMicrotask: safeQueueMicrotask,\n  } = globalThis\n\n  const { nextTick: safeNextTick } = globalThis.process || {}\n\n  const timers = {\n    nextTick: safeNextTick,\n    setTimeout: safeSetTimeout,\n    setInterval: safeSetInterval,\n    clearInterval: safeClearInterval,\n    clearTimeout: safeClearTimeout,\n    setImmediate: safeSetImmediate,\n    clearImmediate: safeClearImmediate,\n    queueMicrotask: safeQueueMicrotask,\n  };\n\n  (globalThis as any)[SAFE_TIMERS_SYMBOL] = timers\n}\n\n/**\n * Returns a promise that resolves after the specified duration.\n *\n * @param timeout - Delay in milliseconds\n * @param scheduler - Timer function to use, defaults to `setTimeout`. Useful for mocked timers.\n *\n * @example\n * await delay(100)\n *\n * @example\n * // With mocked timers\n * const { setTimeout } = getSafeTimers()\n * await delay(100, setTimeout)\n */\nexport function delay(timeout: number, scheduler: typeof setTimeout = setTimeout): Promise<void> {\n  return new Promise(resolve => scheduler(resolve, timeout))\n}\n"
  },
  {
    "path": "packages/utils/src/types.ts",
    "content": "export type Awaitable<T> = T | PromiseLike<T>\nexport type Nullable<T> = T | null | undefined\nexport type Arrayable<T> = T | Array<T>\nexport type ArgumentsType<T> = T extends (...args: infer U) => any ? U : never\n\nexport type MergeInsertions<T> = T extends object\n  ? { [K in keyof T]: MergeInsertions<T[K]> }\n  : T\n\nexport type DeepMerge<F, S> = MergeInsertions<{\n  [K in keyof F | keyof S]: K extends keyof S & keyof F\n    ? DeepMerge<F[K], S[K]>\n    : K extends keyof S\n      ? S[K]\n      : K extends keyof F\n        ? F[K]\n        : never;\n}>\n\nexport interface Constructable {\n  new (...args: any[]): any\n}\n\nexport interface ParsedStack {\n  method: string\n  file: string\n  line: number\n  column: number\n}\n\nexport interface SerializedError {\n  message: string\n  stacks?: ParsedStack[]\n  stack?: string\n  name?: string\n  cause?: SerializedError\n  [key: string]: unknown\n}\n\nexport interface TestError extends SerializedError {\n  cause?: TestError\n  diff?: string\n  actual?: string\n  expected?: string\n}\n"
  },
  {
    "path": "packages/utils/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"moduleResolution\": \"Bundler\",\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\"**/dist/**\"]\n}\n"
  },
  {
    "path": "packages/vitest/LICENSE.md",
    "content": "# Vitest core license\nVitest is released under the MIT license:\n\nMIT License\n\nCopyright (c) 2021-Present VoidZero Inc. and Vitest contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n# Licenses of bundled dependencies\nThe published Vitest artifact additionally contains code with the following licenses:\nBSD-3-Clause, ISC, MIT\n\n# Bundled dependencies:\n## @antfu/install-pkg\nLicense: MIT\nBy: Anthony Fu\nRepository: git+https://github.com/antfu/install-pkg.git\n\n> MIT License\n>\n> Copyright (c) 2021 Anthony Fu <https://github.com/antfu>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## @bomb.sh/tab\nLicense: MIT\nBy: Bombshell Authors\nRepository: git+https://github.com/bombshell-dev/tab.git\n\n---------------------------------------\n\n## @jridgewell/resolve-uri\nLicense: MIT\nBy: Justin Ridgewell\nRepository: https://github.com/jridgewell/resolve-uri\n\n> Copyright 2019 Justin Ridgewell <jridgewell@google.com>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## @jridgewell/sourcemap-codec\nLicense: MIT\nBy: Justin Ridgewell\nRepository: git+https://github.com/jridgewell/sourcemaps.git\n\n> Copyright 2024 Justin Ridgewell <justin@ridgewell.name>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## @jridgewell/trace-mapping\nLicense: MIT\nBy: Justin Ridgewell\nRepository: git+https://github.com/jridgewell/sourcemaps.git\n\n> Copyright 2024 Justin Ridgewell <justin@ridgewell.name>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## @sinonjs/commons\nLicense: BSD-3-Clause\nRepository: git+https://github.com/sinonjs/commons.git\n\n> BSD 3-Clause License\n>\n> Copyright (c) 2018, Sinon.JS\n> All rights reserved.\n>\n> Redistribution and use in source and binary forms, with or without\n> modification, are permitted provided that the following conditions are met:\n>\n> * Redistributions of source code must retain the above copyright notice, this\n>   list of conditions and the following disclaimer.\n>\n> * Redistributions in binary form must reproduce the above copyright notice,\n>   this list of conditions and the following disclaimer in the documentation\n>   and/or other materials provided with the distribution.\n>\n> * Neither the name of the copyright holder nor the names of its\n>   contributors may be used to endorse or promote products derived from\n>   this software without specific prior written permission.\n>\n> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n> DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n> FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n> DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n> OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---------------------------------------\n\n## @sinonjs/fake-timers\nLicense: BSD-3-Clause\nBy: Christian Johansen\nRepository: git+https://github.com/sinonjs/fake-timers.git\n\n> Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no. All rights reserved.\n>\n> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n>\n> 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n>\n> 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n>\n> 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n>\n> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---------------------------------------\n\n## acorn\nLicense: MIT\nBy: Marijn Haverbeke, Ingvar Stepanyan, Adrian Heine\nRepository: https://github.com/acornjs/acorn.git\n\n> MIT License\n>\n> Copyright (C) 2012-2022 by various contributors (see AUTHORS)\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## acorn-walk\nLicense: MIT\nBy: Marijn Haverbeke, Ingvar Stepanyan, Adrian Heine\nRepository: https://github.com/acornjs/acorn.git\n\n> MIT License\n>\n> Copyright (C) 2012-2020 by various contributors (see AUTHORS)\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## birpc\nLicense: MIT\nBy: Anthony Fu\nRepository: git+https://github.com/antfu-collective/birpc.git\n\n> MIT License\n>\n> Copyright (c) 2021 Anthony Fu <https://github.com/antfu>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## cac\nLicense: MIT\nBy: egoist\nRepository: egoist/cac\n\n> The MIT License (MIT)\n>\n> Copyright (c) EGOIST <0x142857@gmail.com> (https://github.com/egoist)\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## empathic\nLicense: MIT\nBy: Luke Edwards\nRepository: lukeed/empathic\n\n> MIT License\n>\n> Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## flatted\nLicense: ISC\nBy: Andrea Giammarchi\nRepository: git+https://github.com/WebReflection/flatted.git\n\n> ISC License\n>\n> Copyright (c) 2018-2020, Andrea Giammarchi, @WebReflection\n>\n> Permission to use, copy, modify, and/or distribute this software for any\n> purpose with or without fee is hereby granted, provided that the above\n> copyright notice and this permission notice appear in all copies.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n> REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n> AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n> INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n> LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n> OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n> PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## js-tokens\nLicense: MIT\nBy: Simon Lydell\nRepository: lydell/js-tokens\n\n> The MIT License (MIT)\n>\n> Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Simon Lydell\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## kleur\nLicense: MIT\nBy: Luke Edwards\nRepository: lukeed/kleur\n\n> The MIT License (MIT)\n>\n> Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## local-pkg\nLicense: MIT\nBy: Anthony Fu\nRepository: git+https://github.com/antfu-collective/local-pkg.git\n\n> MIT License\n>\n> Copyright (c) 2021 Anthony Fu <https://github.com/antfu>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## mime\nLicense: MIT\nBy: Robert Kieffer\nRepository: https://github.com/broofa/mime\n\n> MIT License\n>\n> Copyright (c) 2023 Robert Kieffer\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## mlly\nLicense: MIT\nRepository: unjs/mlly\n\n> MIT License\n>\n> Copyright (c) Pooya Parsa <pooya@pi0.io>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## package-manager-detector\nLicense: MIT\nBy: Anthony Fu\nRepository: git+https://github.com/antfu-collective/package-manager-detector.git\n\n> MIT License\n>\n> Copyright (c) 2020-PRESENT Anthony Fu <https://github.com/antfu>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## prompts\nLicense: MIT\nBy: Terkel Gjervig\nRepository: terkelg/prompts\n\n> MIT License\n>\n> Copyright (c) 2018 Terkel Gjervig Nielsen\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## quansync\nLicense: MIT\nBy: Anthony Fu, 三咲智子 Kevin Deng\nRepository: git+https://github.com/quansync-dev/quansync.git\n\n> MIT License\n>\n> Copyright (c) 2025-PRESENT Anthony Fu <https://github.com/antfu> and Kevin Deng <https://github.com/sxzz>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## sisteransi\nLicense: MIT\nBy: Terkel Gjervig\nRepository: https://github.com/terkelg/sisteransi\n\n> MIT License\n>\n> Copyright (c) 2018 Terkel Gjervig Nielsen\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## strip-literal\nLicense: MIT\nBy: Anthony Fu\nRepository: git+https://github.com/antfu/strip-literal.git\n\n> MIT License\n>\n> Copyright (c) 2022 Anthony Fu <https://github.com/antfu>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## tinyhighlight\nLicense: MIT\nRepository: git+https://github.com/tinylibs/tinyhighlight.git\n\n> # Tinyhighlight core license\n>\n> MIT License\n>\n> Copyright (c) 2023 Tinylibs\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n>\n> # Additionaly Tinyhighlight modifies code with the following licenses:\n>\n> MIT\n>\n> ## @babel/highlight\n>\n> MIT License\n>\n> Copyright (c) 2014-present Sebastian McKenzie and other contributors\n>\n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n>\n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n>\n> ## @babel/helper-validator-identifier\n>\n> MIT License\n>\n> Copyright (c) 2014-present Sebastian McKenzie and other contributors\n>\n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n>\n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## type-detect\nLicense: MIT\nBy: Jake Luer, Keith Cirkel, David Losert, Aleksey Shvayka, Lucas Fernandes da Costa, Grant Snodgrass, Jeremy Tice, Edward Betts, dvlsg, Amila Welihinda, Jake Champion, Miroslav Bajtoš\nRepository: git+ssh://git@github.com/chaijs/type-detect.git\n\n> Copyright (c) 2013 Jake Luer <jake@alogicalparadox.com> (http://alogicalparadox.com)\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## ufo\nLicense: MIT\nRepository: unjs/ufo\n\n> MIT License\n>\n> Copyright (c) Pooya Parsa <pooya@pi0.io>\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## ws\nLicense: MIT\nBy: Einar Otto Stangvik\nRepository: git+https://github.com/websockets/ws.git\n\n> Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>\n> Copyright (c) 2013 Arnout Kazemier and contributors\n> Copyright (c) 2016 Luigi Pinca and contributors\n>\n> Permission is hereby granted, free of charge, to any person obtaining a copy of\n> this software and associated documentation files (the \"Software\"), to deal in\n> the Software without restriction, including without limitation the rights to\n> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n> the Software, and to permit persons to whom the Software is furnished to do so,\n> subject to the following conditions:\n>\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n> FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "packages/vitest/README.md",
    "content": "# vitest\n\n[![NPM version](https://img.shields.io/npm/v/vitest?color=a1b858&label=)](https://npmx.dev/package/vitest)\n\nNext generation testing framework powered by Vite.\n\n[GitHub](https://github.com/vitest-dev/vitest) | [Documentation](https://vitest.dev/)\n"
  },
  {
    "path": "packages/vitest/browser/context.d.ts",
    "content": "// @ts-ignore -- @vitest/browser-playwright might not be installed\nexport * from '@vitest/browser-playwright/context'\n// @ts-ignore -- @vitest/browser-webdriverio might not be installed\nexport * from '@vitest/browser-webdriverio/context'\n// @ts-ignore -- @vitest/browser-preview might not be installed\nexport * from '@vitest/browser-preview/context'\nexport { BrowserCommands, CDPSession, FsOptions } from 'vitest/internal/browser'\n"
  },
  {
    "path": "packages/vitest/browser/context.js",
    "content": "// Vitest resolves \"vitest/browser\" as a virtual module instead\n\n// fake exports for static analysis\nexport const page = null\nexport const server = null\nexport const userEvent = null\nexport const cdp = null\nexport const commands = null\nexport const locators = null\nexport const utils = null\n\nconst pool = globalThis.__vitest_worker__?.ctx?.pool\n\nthrow new Error(\n  // eslint-disable-next-line prefer-template\n  'vitest/browser can be imported only inside the Browser Mode. '\n  + (pool\n    ? `Your test is running in ${pool} pool. Make sure your regular tests are excluded from the \"test.include\" glob pattern.`\n    : 'Instead, it was imported outside of Vitest.'),\n)\n"
  },
  {
    "path": "packages/vitest/config.d.ts",
    "content": "// ensure `@vitest/expect` provides `chai` types\nimport type {} from '@vitest/expect'\nexport * from './dist/config.js'\n"
  },
  {
    "path": "packages/vitest/coverage.d.ts",
    "content": "export * from './dist/coverage.js'\n"
  },
  {
    "path": "packages/vitest/environments.d.ts",
    "content": "export * from './dist/environments'\n"
  },
  {
    "path": "packages/vitest/globals.d.ts",
    "content": "declare global {\n  let suite: typeof import('vitest')['suite']\n  let test: typeof import('vitest')['test']\n  let chai: typeof import(\"vitest\")[\"chai\"]\n  let describe: typeof import('vitest')['describe']\n  let it: typeof import('vitest')['it']\n  let expectTypeOf: typeof import('vitest')['expectTypeOf']\n  let assertType: typeof import('vitest')['assertType']\n  let expect: typeof import('vitest')['expect']\n  let assert: typeof import('vitest')['assert']\n  let vitest: typeof import('vitest')['vitest']\n  let vi: typeof import('vitest')['vitest']\n  let beforeAll: typeof import('vitest')['beforeAll']\n  let afterAll: typeof import('vitest')['afterAll']\n  let beforeEach: typeof import('vitest')['beforeEach']\n  let afterEach: typeof import('vitest')['afterEach']\n  let aroundEach: typeof import('vitest')['aroundEach']\n  let aroundAll: typeof import('vitest')['aroundAll']\n  let onTestFailed: typeof import('vitest')['onTestFailed']\n  let onTestFinished: typeof import('vitest')['onTestFinished']\n}\nexport {}\n"
  },
  {
    "path": "packages/vitest/import-meta.d.ts",
    "content": "/// <reference path=\"./importMeta.d.ts\" />\n\n// https://github.com/microsoft/TypeScript/issues/45096\n// TypeScript has a bug that makes <reference types=\"vite/types/importMeta\" />\n// not possible in userland. This file provides a workaround for now.\n"
  },
  {
    "path": "packages/vitest/importMeta.d.ts",
    "content": "interface ImportMeta {\n  url: string\n  readonly vitest?: typeof import('vitest')\n}\n"
  },
  {
    "path": "packages/vitest/index.cjs",
    "content": "throw new Error(\n  'Vitest cannot be imported in a CommonJS module using require(). Please use \"import\" instead.'\n  + '\\n\\nIf you are using \"import\" in your source code, then it\\'s possible it was bundled into require() automatically by your bundler. '\n  + 'In that case, do not bundle CommonJS output since it will never work with Vitest, or use dynamic import() which is available in all CommonJS modules.',\n)\n"
  },
  {
    "path": "packages/vitest/index.d.cts",
    "content": "export * from './dist/index.js'\n"
  },
  {
    "path": "packages/vitest/jsdom.d.ts",
    "content": "import type { JSDOM } from 'jsdom'\n\ndeclare global {\n  const jsdom: JSDOM\n}\nexport {}\n"
  },
  {
    "path": "packages/vitest/mocker.d.ts",
    "content": "export * from './dist/mocker.js'\n"
  },
  {
    "path": "packages/vitest/node.d.ts",
    "content": "export * from './dist/node.js'\n"
  },
  {
    "path": "packages/vitest/optional-types.d.ts",
    "content": "/* eslint-disable ts/ban-ts-comment */\n\n// @ts-ignore optional peer dep\nexport type * as jsdomTypes from 'jsdom'\n\n// @ts-ignore optional peer dep\nexport type * as happyDomTypes from 'happy-dom'\n"
  },
  {
    "path": "packages/vitest/package.json",
    "content": "{\n  \"name\": \"vitest\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Next generation testing framework powered by Vite\",\n  \"author\": \"Anthony Fu <anthonyfu117@hotmail.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://vitest.dev\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/vitest\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"keywords\": [\n    \"vite\",\n    \"vitest\",\n    \"test\",\n    \"jest\"\n  ],\n  \"sideEffects\": false,\n  \"imports\": {\n    \"#module-evaluator\": {\n      \"types\": \"./dist/module-evaluator.d.ts\",\n      \"default\": \"./dist/module-evaluator.js\"\n    },\n    \"#nodejs-worker-loader\": \"./dist/nodejs-worker-loader.js\"\n  },\n  \"exports\": {\n    \".\": {\n      \"import\": {\n        \"types\": \"./dist/index.d.ts\",\n        \"default\": \"./dist/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./index.d.cts\",\n        \"default\": \"./index.cjs\"\n      }\n    },\n    \"./browser\": {\n      \"types\": \"./browser/context.d.ts\",\n      \"default\": \"./browser/context.js\"\n    },\n    \"./package.json\": \"./package.json\",\n    \"./optional-types.js\": {\n      \"types\": \"./optional-types.d.ts\"\n    },\n    \"./src/*\": \"./src/*\",\n    \"./globals\": {\n      \"types\": \"./globals.d.ts\"\n    },\n    \"./jsdom\": {\n      \"types\": \"./jsdom.d.ts\"\n    },\n    \"./importMeta\": {\n      \"types\": \"./importMeta.d.ts\"\n    },\n    \"./import-meta\": {\n      \"types\": \"./import-meta.d.ts\"\n    },\n    \"./node\": {\n      \"types\": \"./dist/node.d.ts\",\n      \"default\": \"./dist/node.js\"\n    },\n    \"./internal/browser\": {\n      \"types\": \"./dist/browser.d.ts\",\n      \"default\": \"./dist/browser.js\"\n    },\n    \"./runners\": {\n      \"types\": \"./dist/runners.d.ts\",\n      \"default\": \"./dist/runners.js\"\n    },\n    \"./suite\": {\n      \"types\": \"./dist/suite.d.ts\",\n      \"default\": \"./dist/suite.js\"\n    },\n    \"./environments\": {\n      \"types\": \"./dist/environments.d.ts\",\n      \"default\": \"./dist/environments.js\"\n    },\n    \"./config\": {\n      \"types\": \"./config.d.ts\",\n      \"require\": \"./dist/config.cjs\",\n      \"default\": \"./dist/config.js\"\n    },\n    \"./coverage\": {\n      \"types\": \"./coverage.d.ts\",\n      \"default\": \"./dist/coverage.js\"\n    },\n    \"./reporters\": {\n      \"types\": \"./dist/reporters.d.ts\",\n      \"default\": \"./dist/reporters.js\"\n    },\n    \"./snapshot\": {\n      \"types\": \"./dist/snapshot.d.ts\",\n      \"default\": \"./dist/snapshot.js\"\n    },\n    \"./runtime\": {\n      \"types\": \"./dist/runtime.d.ts\",\n      \"default\": \"./dist/runtime.js\"\n    },\n    \"./worker\": {\n      \"types\": \"./worker.d.ts\",\n      \"default\": \"./dist/worker.js\"\n    }\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"bin\": {\n    \"vitest\": \"./vitest.mjs\"\n  },\n  \"files\": [\n    \"*.cjs\",\n    \"*.d.cts\",\n    \"*.d.ts\",\n    \"*.mjs\",\n    \"bin\",\n    \"browser\",\n    \"dist\"\n  ],\n  \"engines\": {\n    \"node\": \"^20.0.0 || ^22.0.0 || >=24.0.0\"\n  },\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"NODE_OPTIONS=\\\"--max-old-space-size=8192\\\" rollup -c --watch -m inline\"\n  },\n  \"peerDependencies\": {\n    \"@edge-runtime/vm\": \"*\",\n    \"@opentelemetry/api\": \"^1.9.0\",\n    \"@types/node\": \"^20.0.0 || ^22.0.0 || >=24.0.0\",\n    \"@vitest/browser-playwright\": \"workspace:*\",\n    \"@vitest/browser-preview\": \"workspace:*\",\n    \"@vitest/browser-webdriverio\": \"workspace:*\",\n    \"@vitest/ui\": \"workspace:*\",\n    \"happy-dom\": \"*\",\n    \"jsdom\": \"*\",\n    \"vite\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@edge-runtime/vm\": {\n      \"optional\": true\n    },\n    \"@opentelemetry/api\": {\n      \"optional\": true\n    },\n    \"@types/node\": {\n      \"optional\": true\n    },\n    \"@vitest/browser-playwright\": {\n      \"optional\": true\n    },\n    \"@vitest/browser-preview\": {\n      \"optional\": true\n    },\n    \"@vitest/browser-webdriverio\": {\n      \"optional\": true\n    },\n    \"@vitest/ui\": {\n      \"optional\": true\n    },\n    \"happy-dom\": {\n      \"optional\": true\n    },\n    \"jsdom\": {\n      \"optional\": true\n    },\n    \"vite\": {\n      \"optional\": false\n    }\n  },\n  \"dependencies\": {\n    \"@vitest/expect\": \"workspace:*\",\n    \"@vitest/mocker\": \"workspace:*\",\n    \"@vitest/pretty-format\": \"workspace:*\",\n    \"@vitest/runner\": \"workspace:*\",\n    \"@vitest/snapshot\": \"workspace:*\",\n    \"@vitest/spy\": \"workspace:*\",\n    \"@vitest/utils\": \"workspace:*\",\n    \"es-module-lexer\": \"^2.0.0\",\n    \"expect-type\": \"^1.3.0\",\n    \"magic-string\": \"catalog:\",\n    \"obug\": \"catalog:\",\n    \"pathe\": \"catalog:\",\n    \"picomatch\": \"^4.0.3\",\n    \"std-env\": \"catalog:\",\n    \"tinybench\": \"^2.9.0\",\n    \"tinyexec\": \"^1.0.2\",\n    \"tinyglobby\": \"catalog:\",\n    \"tinyrainbow\": \"catalog:\",\n    \"vite\": \"^6.0.0 || ^7.0.0 || ^8.0.0\",\n    \"why-is-node-running\": \"^2.3.0\"\n  },\n  \"devDependencies\": {\n    \"@antfu/install-pkg\": \"^1.1.0\",\n    \"@bomb.sh/tab\": \"^0.0.14\",\n    \"@edge-runtime/vm\": \"^5.0.0\",\n    \"@jridgewell/trace-mapping\": \"catalog:\",\n    \"@opentelemetry/api\": \"^1.9.0\",\n    \"@sinonjs/fake-timers\": \"15.0.0\",\n    \"@types/estree\": \"catalog:\",\n    \"@types/istanbul-lib-coverage\": \"catalog:\",\n    \"@types/istanbul-reports\": \"catalog:\",\n    \"@types/jsdom\": \"^27.0.0\",\n    \"@types/node\": \"^24.12.0\",\n    \"@types/picomatch\": \"^4.0.2\",\n    \"@types/prompts\": \"^2.4.9\",\n    \"@types/sinonjs__fake-timers\": \"^15.0.1\",\n    \"acorn\": \"8.11.3\",\n    \"acorn-walk\": \"catalog:\",\n    \"birpc\": \"catalog:\",\n    \"cac\": \"catalog:\",\n    \"empathic\": \"^2.0.0\",\n    \"flatted\": \"catalog:\",\n    \"happy-dom\": \"^20.8.3\",\n    \"jsdom\": \"^27.4.0\",\n    \"local-pkg\": \"^1.1.2\",\n    \"mime\": \"^4.1.0\",\n    \"prompts\": \"^2.4.2\",\n    \"strip-literal\": \"catalog:\",\n    \"tinyhighlight\": \"catalog:\",\n    \"ws\": \"catalog:\"\n  }\n}\n"
  },
  {
    "path": "packages/vitest/reporters.d.ts",
    "content": "export * from './dist/reporters.js'\n"
  },
  {
    "path": "packages/vitest/rollup.config.js",
    "content": "import fs from 'node:fs'\nimport { builtinModules, createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport nodeResolve from '@rollup/plugin-node-resolve'\nimport { dirname, join, normalize, resolve } from 'pathe'\nimport { defineConfig } from 'rollup'\nimport license from 'rollup-plugin-license'\nimport { globSync } from 'tinyglobby'\nimport c from 'tinyrainbow'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst entries = {\n  'path': 'src/paths.ts',\n  'index': 'src/public/index.ts',\n  'cli': 'src/node/cli.ts',\n  'config': 'src/public/config.ts',\n  'node': 'src/public/node.ts',\n  'suite': 'src/public/suite.ts',\n  'browser': 'src/public/browser.ts',\n  'runners': 'src/public/runners.ts',\n  'environments': 'src/public/environments.ts',\n  'spy': 'src/integrations/spy.ts',\n  'runtime': 'src/public/runtime.ts',\n  'coverage': 'src/public/coverage.ts',\n  'reporters': 'src/public/reporters.ts',\n  'worker': 'src/public/worker.ts',\n  'module-evaluator': 'src/runtime/moduleRunner/moduleEvaluator.ts',\n  'nodejs-worker-loader': 'src/runtime/nodejsWorkerLoader.ts',\n\n  // for performance reasons we bundle them separately so we don't import everything at once\n  // 'worker': 'src/runtime/worker.ts',\n  'workers/forks': 'src/runtime/workers/forks.ts',\n  'workers/threads': 'src/runtime/workers/threads.ts',\n  'workers/vmThreads': 'src/runtime/workers/vmThreads.ts',\n  'workers/vmForks': 'src/runtime/workers/vmForks.ts',\n\n  'workers/runVmTests': 'src/runtime/runVmTests.ts',\n\n  'snapshot': 'src/public/snapshot.ts',\n}\n\nconst dtsEntries = {\n  'index': 'src/public/index.ts',\n  'node': 'src/public/node.ts',\n  'environments': 'src/public/environments.ts',\n  'browser': 'src/public/browser.ts',\n  'runners': 'src/public/runners.ts',\n  'runtime': 'src/public/runtime.ts',\n  'suite': 'src/public/suite.ts',\n  'config': 'src/public/config.ts',\n  'coverage': 'src/public/coverage.ts',\n  'reporters': 'src/public/reporters.ts',\n  'snapshot': 'src/public/snapshot.ts',\n  'worker': 'src/public/worker.ts',\n  'module-evaluator': 'src/runtime/moduleRunner/moduleEvaluator.ts',\n}\n\nconst external = [\n  ...builtinModules,\n  ...Object.keys(pkg.dependencies),\n  ...Object.keys(pkg.peerDependencies),\n  'worker_threads',\n  'node:worker_threads',\n  'node:fs',\n  'node:os',\n  'node:stream',\n  'node:vm',\n  'node:http',\n  'node:console',\n  'node:events',\n  'inspector',\n  'vitest/optional-types.js',\n  'vitest/browser',\n  'vite/module-runner',\n  '@vitest/mocker',\n  /@vitest\\/mocker\\/\\w+/,\n  '@vitest/utils/diff',\n  '@vitest/utils/error',\n  '@vitest/utils/source-map',\n  '@vitest/runner/utils',\n  '@vitest/runner/types',\n  '@vitest/snapshot/environment',\n  '@vitest/snapshot/manager',\n  /@vitest\\/utils\\/\\w+/,\n\n  '#module-evaluator',\n  '@opentelemetry/api',\n]\n\nconst dir = dirname(fileURLToPath(import.meta.url))\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  nodeResolve({\n    preferBuiltins: true,\n  }),\n  json(),\n  commonjs(),\n  oxc({\n    transform: {\n      target: 'node20',\n      define: {\n        // __VITEST_GENERATE_UI_TOKEN__ is set as a global to catch accidental leaking,\n        // in the release version the \"if\" with this condition should not be present\n        // To test strict token locally, build by e.g. `VITEST_GENERATE_UI_TOKEN=true pnpm build`\n        __VITEST_GENERATE_UI_TOKEN__: process.env.VITEST_GENERATE_UI_TOKEN === 'true' ? 'true' : 'false',\n        ...(process.env.VITE_TEST_WATCHER_DEBUG === 'false'\n          ? {\n              'process.env.VITE_TEST_WATCHER_DEBUG': 'false',\n            }\n          : {}),\n      },\n    },\n    sourcemap: true,\n  }),\n]\n\nexport default ({ watch }) =>\n  defineConfig([\n    {\n      input: entries,\n      treeshake: true,\n      output: {\n        dir: 'dist',\n        format: 'esm',\n        chunkFileNames: 'chunks/[name].[hash].js',\n      },\n      external,\n      moduleContext: (id) => {\n        // mime has `this.__classPrivateFieldGet` check which should be ignored in esm\n        if (id.includes('mime/dist/src') || id.includes('mime\\\\dist\\\\src')) {\n          return '{}'\n        }\n      },\n      plugins: [\n        ...dtsUtils.isolatedDecl(),\n        ...plugins,\n        !watch && licensePlugin(),\n      ],\n      onwarn,\n    },\n    {\n      input: 'src/public/config.ts',\n      output: [\n        {\n          file: 'dist/config.cjs',\n          format: 'cjs',\n        },\n      ],\n      external,\n      plugins,\n    },\n    {\n      input: dtsUtils.dtsInput(dtsEntries),\n      output: {\n        dir: 'dist',\n        entryFileNames: chunk =>\n          `${normalize(chunk.name).replace('src/', '')}.d.ts`,\n        format: 'esm',\n        chunkFileNames: 'chunks/[name].[hash].d.ts',\n      },\n      watch: false,\n      external,\n      plugins: dtsUtils.dts(),\n    },\n  ])\n\nfunction licensePlugin() {\n  return license({\n    thirdParty(dependencies) {\n      // https://github.com/rollup/rollup/blob/master/build-plugins/generate-license-file.js\n      // MIT Licensed https://github.com/rollup/rollup/blob/master/LICENSE-CORE.md\n      const coreLicense = fs.readFileSync(resolve(dir, '../../LICENSE'))\n      const licenses = new Set()\n      const dependencyLicenseTexts = dependencies\n        .filter(({ name }) => !name?.startsWith('@vitest/'))\n        .sort(({ name: nameA }, { name: nameB }) =>\n          nameA > nameB ? 1 : nameB > nameA ? -1 : 0,\n        )\n        .map(\n          ({\n            name,\n            license,\n            licenseText,\n            author,\n            maintainers,\n            contributors,\n            repository,\n          }) => {\n            let text = `## ${name}\\n`\n            if (license) {\n              text += `License: ${license}\\n`\n            }\n\n            const names = new Set()\n            if (author && author.name) {\n              names.add(author.name)\n            }\n\n            for (const person of maintainers.concat(contributors)) {\n              if (person && person.name) {\n                names.add(person.name)\n              }\n            }\n            if (names.size > 0) {\n              text += `By: ${Array.from(names).join(', ')}\\n`\n            }\n\n            if (repository) {\n              text += `Repository: ${repository.url || repository}\\n`\n            }\n\n            if (!licenseText) {\n              try {\n                const pkgDir = dirname(\n                  resolve(join(name, 'package.json'), {\n                    preserveSymlinks: false,\n                  }),\n                )\n                const [licenseFile] = globSync(`${pkgDir}/LICENSE*`, {\n                  caseSensitiveMatch: false,\n                  expandDirectories: false,\n                })\n                if (licenseFile) {\n                  licenseText = fs.readFileSync(licenseFile, 'utf-8')\n                }\n              }\n              catch {}\n            }\n            if (licenseText) {\n              text += `\\n${licenseText\n                .trim()\n                .replace(/(\\r\\n|\\r)/g, '\\n')\n                .split('\\n')\n                .map(line => (line ? `> ${line}` : '>'))\n                .join('\\n')}\\n`\n            }\n            licenses.add(license)\n            return text\n          },\n        )\n        .join('\\n---------------------------------------\\n\\n')\n      const licenseText\n        = '# Vitest core license\\n'\n          + `Vitest is released under the MIT license:\\n\\n${coreLicense}\\n# Licenses of bundled dependencies\\n`\n          + 'The published Vitest artifact additionally contains code with the following licenses:\\n'\n          + `${sortLicenses(licenses).join(', ')}\\n\\n`\n          + `# Bundled dependencies:\\n${dependencyLicenseTexts}`\n      const existingLicenseText = fs.readFileSync('LICENSE.md', 'utf8')\n      if (existingLicenseText !== licenseText) {\n        fs.writeFileSync('LICENSE.md', licenseText)\n        console.warn(\n          c.yellow(\n            '\\nLICENSE.md updated. You should commit the updated file.\\n',\n          ),\n        )\n      }\n    },\n  })\n}\n\nfunction onwarn(message) {\n  if (['EMPTY_BUNDLE', 'CIRCULAR_DEPENDENCY'].includes(message.code)) {\n    return\n  }\n  console.error(message)\n}\n\nfunction sortLicenses(licenses) {\n  let withParenthesis = []\n  let noParenthesis = []\n  licenses.forEach((license) => {\n    if (/^\\(/.test(license)) {\n      withParenthesis.push(license)\n    }\n    else {\n      noParenthesis.push(license)\n    }\n  })\n  withParenthesis = withParenthesis.sort()\n  noParenthesis = noParenthesis.sort()\n  return [...noParenthesis, ...withParenthesis]\n}\n"
  },
  {
    "path": "packages/vitest/runners.d.ts",
    "content": "export * from './dist/runners.js'\n"
  },
  {
    "path": "packages/vitest/snapshot.d.ts",
    "content": "export * from './dist/snapshot.js'\n"
  },
  {
    "path": "packages/vitest/src/api/check.ts",
    "content": "import type { IncomingMessage } from 'node:http'\nimport type { ResolvedConfig } from '../node/types/config'\nimport crypto from 'node:crypto'\n\nexport function isValidApiRequest(config: ResolvedConfig, req: IncomingMessage): boolean {\n  const url = new URL(req.url ?? '', 'http://localhost')\n\n  // validate token. token is injected in ui/tester/orchestrator html, which is cross origin protected.\n  try {\n    const token = url.searchParams.get('token')\n    if (token && crypto.timingSafeEqual(\n      Buffer.from(token),\n      Buffer.from(config.api.token),\n    )) {\n      return true\n    }\n  }\n  // an error is thrown when the length is incorrect\n  catch {}\n\n  return false\n}\n"
  },
  {
    "path": "packages/vitest/src/api/setup.ts",
    "content": "import type { File, TaskEventPack, TaskResultPack, TestAnnotation, TestArtifact } from '@vitest/runner'\nimport type { SerializedError } from '@vitest/utils'\nimport type { IncomingMessage } from 'node:http'\nimport type { ViteDevServer } from 'vite'\nimport type { WebSocket } from 'ws'\nimport type { Vitest } from '../node/core'\nimport type { TestCase, TestModule } from '../node/reporters/reported-tasks'\nimport type { TestSpecification } from '../node/test-specification'\nimport type { Reporter } from '../node/types/reporter'\nimport type { LabelColor, ModuleGraphData, UserConsoleLog } from '../types/general'\nimport type {\n  ExternalResult,\n  TransformResultWithSource,\n  WebSocketEvents,\n  WebSocketHandlers,\n  WebSocketRPC,\n} from './types'\nimport { existsSync, promises as fs } from 'node:fs'\nimport { performance } from 'node:perf_hooks'\nimport { noop } from '@vitest/utils/helpers'\nimport { createBirpc } from 'birpc'\nimport { parse, stringify } from 'flatted'\nimport { WebSocketServer } from 'ws'\nimport { API_PATH } from '../constants'\nimport { isFileServingAllowed } from '../node/vite'\nimport { getTestFileEnvironment } from '../utils/environments'\nimport { getModuleGraph } from '../utils/graph'\nimport { stringifyReplace } from '../utils/serialization'\nimport { isValidApiRequest } from './check'\n\nexport function setup(ctx: Vitest, _server?: ViteDevServer): void {\n  const wss = new WebSocketServer({ noServer: true })\n\n  const clients = new Map<WebSocket, WebSocketRPC>()\n\n  const server = _server || ctx.vite\n\n  server.httpServer?.on('upgrade', (request: IncomingMessage, socket, head) => {\n    if (!request.url) {\n      return\n    }\n\n    const { pathname } = new URL(request.url, 'http://localhost')\n    if (pathname !== API_PATH) {\n      return\n    }\n\n    if (!isValidApiRequest(ctx.config, request)) {\n      socket.destroy()\n      return\n    }\n\n    wss.handleUpgrade(request, socket, head, (ws) => {\n      wss.emit('connection', ws, request)\n      setupClient(ws)\n    })\n  })\n\n  function setupClient(ws: WebSocket) {\n    const rpc = createBirpc<WebSocketEvents, WebSocketHandlers>(\n      {\n        getFiles() {\n          return ctx.state.getFiles()\n        },\n        getPaths() {\n          return ctx.state.getPaths()\n        },\n        async readTestFile(id) {\n          if (!ctx.state.filesMap.has(id) || !existsSync(id)) {\n            return null\n          }\n          return fs.readFile(id, 'utf-8')\n        },\n        async saveTestFile(id, content) {\n          if (!ctx.state.filesMap.has(id) || !existsSync(id)) {\n            throw new Error(\n              `Test file \"${id}\" was not registered, so it cannot be updated using the API.`,\n            )\n          }\n          // silently ignore write attempts if not allowed\n          if (!ctx.config.api.allowWrite) {\n            return\n          }\n          return fs.writeFile(id, content, 'utf-8')\n        },\n        async rerun(files, resetTestNamePattern) {\n          // silently ignore exec attempts if not allowed\n          if (!ctx.config.api.allowExec) {\n            return\n          }\n          await ctx.rerunFiles(files, undefined, true, resetTestNamePattern)\n        },\n        async rerunTask(id) {\n          // silently ignore exec attempts if not allowed\n          if (!ctx.config.api.allowExec) {\n            return\n          }\n          await ctx.rerunTask(id)\n        },\n        getConfig() {\n          return ctx.getRootProject().serializedConfig\n        },\n        getResolvedProjectLabels(): { name: string; color?: LabelColor }[] {\n          return ctx.projects.map(p => ({ name: p.name, color: p.color }))\n        },\n        async getExternalResult(moduleId: string, testFileTaskId: string) {\n          const testModule = ctx.state.getReportedEntityById(testFileTaskId) as TestModule | undefined\n          if (!testModule) {\n            return undefined\n          }\n\n          if (!isFileServingAllowed(testModule.project.vite.config, moduleId)) {\n            return undefined\n          }\n\n          const result: ExternalResult = {}\n\n          try {\n            result.source = await fs.readFile(moduleId, 'utf-8')\n          }\n          catch {}\n\n          return result\n        },\n        async getTransformResult(projectName: string, moduleId, testFileTaskId, browser = false) {\n          const project = ctx.getProjectByName(projectName)\n          const testModule = ctx.state.getReportedEntityById(testFileTaskId) as TestModule | undefined\n          if (!testModule || !isFileServingAllowed(project.vite.config, moduleId)) {\n            return\n          }\n\n          const environment = getTestFileEnvironment(project, testModule.moduleId, browser)\n\n          const moduleNode = environment?.moduleGraph.getModuleById(moduleId)\n          if (!environment || !moduleNode?.transformResult) {\n            return\n          }\n\n          const result: TransformResultWithSource = moduleNode.transformResult\n          try {\n            result.source = result.source || (moduleNode.file ? await fs.readFile(moduleNode.file, 'utf-8') : undefined)\n          }\n          catch {}\n\n          // TODO: store this in HTML reporter separetly\n          const transformDuration = ctx.state.metadata[projectName]?.duration[moduleNode.url]?.[0]\n          if (transformDuration != null) {\n            result.transformTime = transformDuration\n          }\n          try {\n            const diagnostic = await ctx.experimental_getSourceModuleDiagnostic(moduleId, testModule)\n            result.modules = diagnostic.modules\n            result.untrackedModules = diagnostic.untrackedModules\n          }\n          catch {}\n          return result\n        },\n        async getModuleGraph(project, id, browser): Promise<ModuleGraphData> {\n          return getModuleGraph(ctx, project, id, browser)\n        },\n        async updateSnapshot(file?: File) {\n          // silently ignore exec/write attempts if not allowed\n          // this function both executes the code and write snapshots\n          if (!ctx.config.api.allowExec || !ctx.config.api.allowWrite) {\n            return\n          }\n          if (!file) {\n            await ctx.updateSnapshot()\n          }\n          else {\n            await ctx.updateSnapshot([file.filepath])\n          }\n        },\n        getUnhandledErrors() {\n          return ctx.state.getUnhandledErrors()\n        },\n        async getTestFiles() {\n          const spec = await ctx.globTestSpecifications()\n          return spec.map(spec => [\n            {\n              name: spec.project.config.name,\n              root: spec.project.config.root,\n            },\n            spec.moduleId,\n            { pool: spec.pool },\n          ])\n        },\n      },\n      {\n        post: msg => ws.send(msg),\n        on: fn => ws.on('message', fn),\n        eventNames: [\n          'onUserConsoleLog',\n          'onFinished',\n          'onFinishedReportCoverage',\n          'onCollected',\n          'onTaskUpdate',\n        ],\n        serialize: (data: any) => stringify(data, stringifyReplace),\n        deserialize: parse,\n        timeout: -1,\n      },\n    )\n\n    clients.set(ws, rpc)\n\n    ws.on('close', () => {\n      clients.delete(ws)\n      rpc.$close(new Error('[vitest-api]: Pending methods while closing rpc'))\n    })\n  }\n\n  ctx.reporters.push(new WebSocketReporter(ctx, wss, clients))\n}\n\nexport class WebSocketReporter implements Reporter {\n  private start = 0\n  private end = 0\n  constructor(\n    public ctx: Vitest,\n    public wss: WebSocketServer,\n    public clients: Map<WebSocket, WebSocketRPC>,\n  ) {}\n\n  onTestModuleCollected(testModule: TestModule): void {\n    if (this.clients.size === 0) {\n      return\n    }\n\n    this.clients.forEach((client) => {\n      client.onCollected?.([testModule.task])?.catch?.(noop)\n    })\n  }\n\n  onTestRunStart(specifications: ReadonlyArray<TestSpecification>): void {\n    if (this.clients.size === 0) {\n      return\n    }\n\n    this.start = performance.now()\n    const serializedSpecs = specifications.map(spec => spec.toJSON())\n    this.clients.forEach((client) => {\n      client.onSpecsCollected?.(serializedSpecs)?.catch?.(noop)\n    })\n  }\n\n  async onTestCaseAnnotate(testCase: TestCase, annotation: TestAnnotation): Promise<void> {\n    if (this.clients.size === 0) {\n      return\n    }\n\n    this.clients.forEach((client) => {\n      client.onTestAnnotate?.(testCase.id, annotation)?.catch?.(noop)\n    })\n  }\n\n  async onTestCaseArtifactRecord(testCase: TestCase, artifact: TestArtifact): Promise<void> {\n    if (this.clients.size === 0) {\n      return\n    }\n\n    this.clients.forEach((client) => {\n      client.onTestArtifactRecord?.(testCase.id, artifact)?.catch?.(noop)\n    })\n  }\n\n  async onTaskUpdate(packs: TaskResultPack[], events: TaskEventPack[]): Promise<void> {\n    if (this.clients.size === 0) {\n      return\n    }\n\n    this.clients.forEach((client) => {\n      client.onTaskUpdate?.(packs, events)?.catch?.(noop)\n    })\n  }\n\n  private sum<T>(items: T[], cb: (_next: T) => number | undefined) {\n    return items.reduce((total, next) => {\n      return total + Math.max(cb(next) || 0, 0)\n    }, 0)\n  }\n\n  onTestRunEnd(testModules: ReadonlyArray<TestModule>, unhandledErrors: ReadonlyArray<SerializedError>): void {\n    if (!this.clients.size) {\n      return\n    }\n\n    const files = testModules.map(testModule => testModule.task)\n    const errors = [...unhandledErrors]\n\n    this.end = performance.now()\n    const blobs = this.ctx.state.blobs\n    // Execution time is either sum of all runs of `--merge-reports` or the current run's time\n    const executionTime = blobs?.executionTimes ? this.sum(blobs.executionTimes, time => time) : this.end - this.start\n\n    this.clients.forEach((client) => {\n      client.onFinished?.(files, errors, undefined, executionTime)?.catch?.(noop)\n    })\n  }\n\n  onFinishedReportCoverage(): void {\n    this.clients.forEach((client) => {\n      client.onFinishedReportCoverage?.()?.catch?.(noop)\n    })\n  }\n\n  onUserConsoleLog(log: UserConsoleLog): void {\n    this.clients.forEach((client) => {\n      client.onUserConsoleLog?.(log)?.catch?.(noop)\n    })\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/api/types.ts",
    "content": "import type { File, TaskEventPack, TaskResultPack, TestAnnotation, TestArtifact } from '@vitest/runner'\nimport type { Awaitable } from '@vitest/utils'\nimport type { BirpcReturn } from 'birpc'\nimport type { SerializedConfig } from '../runtime/config'\nimport type { SerializedTestSpecification } from '../runtime/types/utils'\nimport type { LabelColor, ModuleGraphData, UserConsoleLog } from '../types/general'\nimport type { ModuleDefinitionDurationsDiagnostic, UntrackedModuleDefinitionDiagnostic } from '../types/module-locations'\n\ninterface SourceMap {\n  file: string\n  mappings: string\n  names: string[]\n  sources: string[]\n  sourcesContent?: string[]\n  version: number\n  toString: () => string\n  toUrl: () => string\n}\n\nexport interface ExternalResult {\n  source?: string\n}\n\nexport interface TransformResultWithSource {\n  code: string\n  map: SourceMap | {\n    mappings: ''\n  } | null\n  etag?: string\n  deps?: string[]\n  dynamicDeps?: string[]\n  source?: string\n  transformTime?: number\n  modules?: ModuleDefinitionDurationsDiagnostic[]\n  untrackedModules?: UntrackedModuleDefinitionDiagnostic[]\n}\n\nexport interface WebSocketHandlers {\n  getFiles: () => File[]\n  getTestFiles: () => Promise<SerializedTestSpecification[]>\n  getPaths: () => string[]\n  getConfig: () => SerializedConfig\n  getResolvedProjectLabels: () => { name: string; color?: LabelColor }[]\n  getModuleGraph: (\n    projectName: string,\n    id: string,\n    browser?: boolean,\n  ) => Promise<ModuleGraphData>\n  getTransformResult: (\n    projectName: string,\n    id: string,\n    testFileId: string,\n    browser?: boolean,\n  ) => Promise<TransformResultWithSource | undefined>\n  getExternalResult: (\n    id: string,\n    testFileId: string,\n  ) => Promise<ExternalResult | undefined>\n  readTestFile: (id: string) => Promise<string | null>\n  saveTestFile: (id: string, content: string) => Promise<void>\n  rerun: (files: string[], resetTestNamePattern?: boolean) => Promise<void>\n  rerunTask: (id: string) => Promise<void>\n  updateSnapshot: (file?: File) => Promise<void>\n  getUnhandledErrors: () => unknown[]\n}\n\nexport interface WebSocketEvents {\n  onCollected?: (files?: File[]) => Awaitable<void>\n  onFinished?: (\n    files: File[],\n    errors: unknown[],\n    coverage?: unknown,\n    executionTime?: number,\n  ) => Awaitable<void>\n  onTestAnnotate?: (testId: string, annotation: TestAnnotation) => Awaitable<void>\n  onTestArtifactRecord?: (testId: string, artifact: TestArtifact) => Awaitable<void>\n  onTaskUpdate?: (packs: TaskResultPack[], events: TaskEventPack[]) => Awaitable<void>\n  onUserConsoleLog?: (log: UserConsoleLog) => Awaitable<void>\n  onPathsCollected?: (paths?: string[]) => Awaitable<void>\n  onSpecsCollected?: (specs?: SerializedTestSpecification[], startTime?: number) => Awaitable<void>\n  onFinishedReportCoverage: () => void\n}\n\nexport type WebSocketRPC = BirpcReturn<WebSocketEvents, WebSocketHandlers>\n"
  },
  {
    "path": "packages/vitest/src/constants.ts",
    "content": "// if changed, update also jsdocs and docs\nexport const defaultPort = 51204\nexport const defaultBrowserPort = 63315\nexport const defaultInspectPort = 9229\n\nexport const API_PATH = '/__vitest_api__'\n\nexport const CONFIG_NAMES: string[] = ['vitest.config', 'vite.config']\n\nexport const CONFIG_EXTENSIONS: string[] = ['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs']\n\nexport const configFiles: string[] = CONFIG_NAMES.flatMap(name =>\n  CONFIG_EXTENSIONS.map(ext => name + ext),\n)\n\nexport const globalApis: string[] = [\n  // suite\n  'suite',\n  'test',\n  'describe',\n  'it',\n  // chai\n  'chai',\n  'expect',\n  'assert',\n  // typecheck\n  'expectTypeOf',\n  'assertType',\n  // utils\n  'vitest',\n  'vi',\n  // hooks\n  'beforeAll',\n  'afterAll',\n  'beforeEach',\n  'afterEach',\n  'onTestFinished',\n  'onTestFailed',\n  'aroundEach',\n  'aroundAll',\n]\n"
  },
  {
    "path": "packages/vitest/src/create/browser/creator.ts",
    "content": "import type { Agent } from '@antfu/install-pkg'\nimport type { BrowserBuiltinProvider } from '../../node/types/browser'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { writeFile } from 'node:fs/promises'\nimport { dirname, relative, resolve } from 'node:path'\nimport { detectPackageManager, installPackage } from '@antfu/install-pkg'\nimport * as find from 'empathic/find'\nimport prompt from 'prompts'\nimport { x } from 'tinyexec'\nimport c from 'tinyrainbow'\nimport { configFiles } from '../../constants'\nimport { generateExampleFiles } from './examples'\n\n// eslint-disable-next-line no-console\nconst log = console.log\n\nfunction getProviderOptions(): prompt.Choice[] {\n  const providers: Record<BrowserBuiltinProvider, string> = {\n    playwright: 'Playwright relies on Chrome DevTools protocol. Read more: https://playwright.dev',\n    webdriverio: 'WebdriverIO uses WebDriver protocol. Read more: https://webdriver.io',\n    preview: 'Preview is useful to quickly run your tests in the browser, but not suitable for CI.',\n  }\n\n  return Object.entries(providers).map<prompt.Choice>(([provider, description]) => {\n    return {\n      title: provider,\n      description,\n      value: provider,\n    }\n  })\n}\n\nfunction getBrowserNames(provider: BrowserBuiltinProvider) {\n  switch (provider) {\n    case 'webdriverio':\n      return ['chrome', 'firefox', 'edge', 'safari']\n    case 'playwright':\n      return ['chromium', 'firefox', 'webkit']\n    case 'preview':\n      return ['chrome', 'firefox', 'safari']\n  }\n}\n\nfunction getFramework(): prompt.Choice[] {\n  return [\n    {\n      title: 'vanilla',\n      value: 'vanilla',\n      description: 'No framework, just plain JavaScript or TypeScript.',\n    },\n    {\n      title: 'vue',\n      value: 'vue',\n      description: '\"The Progressive JavaScript Framework\"',\n    },\n    {\n      title: 'svelte',\n      value: 'svelte',\n      description: '\"Svelte: cybernetically enhanced web apps\"',\n    },\n    {\n      title: 'react',\n      value: 'react',\n      description: '\"The library for web and native user interfaces\"',\n    },\n    {\n      title: 'lit',\n      value: 'lit',\n      description: '\"A simple library for building fast, lightweight web components.\"',\n    },\n    {\n      title: 'preact',\n      value: 'preact',\n      description: '\"Fast 3kB alternative to React with the same modern API\"',\n    },\n    {\n      title: 'solid',\n      value: 'solid',\n      description: '\"Simple and performant reactivity for building user interfaces\"',\n    },\n    {\n      title: 'marko',\n      value: 'marko',\n      description: '\"A declarative, HTML-based language that makes building web apps fun\"',\n    },\n    {\n      title: 'qwik',\n      value: 'qwik',\n      description: '\"Instantly interactive web apps at scale\"',\n    },\n  ]\n}\n\nfunction getFrameworkTestPackage(framework: string) {\n  switch (framework) {\n    case 'vanilla':\n      return null\n    case 'vue':\n      return 'vitest-browser-vue'\n    case 'svelte':\n      return 'vitest-browser-svelte'\n    case 'react':\n      return 'vitest-browser-react'\n    case 'lit':\n      return 'vitest-browser-lit'\n    case 'preact':\n      return 'vitest-browser-preact'\n    case 'solid':\n      return '@solidjs/testing-library'\n    case 'marko':\n      return '@marko/testing-library'\n    case 'qwik':\n      return 'vitest-browser-qwik'\n  }\n  throw new Error(`Unsupported framework: ${framework}`)\n}\n\nfunction getFrameworkPluginPackage(framework: string) {\n  switch (framework) {\n    case 'vue':\n      return '@vitejs/plugin-vue'\n    case 'svelte':\n      return '@sveltejs/vite-plugin-svelte'\n    case 'react':\n      return '@vitejs/plugin-react'\n    case 'preact':\n      return '@preact/preset-vite'\n    case 'solid':\n      return 'vite-plugin-solid'\n    case 'marko':\n      return '@marko/vite'\n    case 'qwik':\n      return '@builder.io/qwik/optimizer'\n  }\n  return null\n}\n\nfunction getLanguageOptions(): prompt.Choice[] {\n  return [\n    {\n      title: 'TypeScript',\n      description: 'Use TypeScript.',\n      value: 'ts',\n    },\n    {\n      title: 'JavaScript',\n      description: 'Use plain JavaScript.',\n      value: 'js',\n    },\n  ]\n}\n\nasync function installPackages(pkgManager: string | null, packages: string[]) {\n  if (!packages.length) {\n    log(c.green('✔'), c.bold('All packages are already installed.'))\n    return\n  }\n\n  log(c.cyan('◼'), c.bold('Installing packages...'))\n  log(c.cyan('◼'), packages.join(', '))\n\n  log()\n  await installPackage(packages, { dev: true, packageManager: pkgManager ?? undefined })\n}\n\nfunction readPkgJson(path: string) {\n  if (!existsSync(path)) {\n    return null\n  }\n  const content = readFileSync(path, 'utf-8')\n  return JSON.parse(content)\n}\n\nfunction getPossibleDefaults(dependencies: any) {\n  const provider = getPossibleProvider(dependencies)\n  const framework = getPossibleFramework(dependencies)\n  return {\n    lang: 'ts',\n    provider,\n    framework,\n  }\n}\n\nfunction getPossibleFramework(dependencies: Record<string, string>) {\n  if (dependencies.vue || dependencies['vue-tsc'] || dependencies['@vue/reactivity']) {\n    return 'vue'\n  }\n  if (dependencies.react || dependencies['react-dom']) {\n    return 'react'\n  }\n  if (dependencies.svelte || dependencies['@sveltejs/kit']) {\n    return 'svelte'\n  }\n  if (dependencies.lit || dependencies['lit-html']) {\n    return 'lit'\n  }\n  if (dependencies.preact) {\n    return 'preact'\n  }\n  if (dependencies['solid-js'] || dependencies['@solidjs/start']) {\n    return 'solid'\n  }\n  if (dependencies.marko) {\n    return 'marko'\n  }\n  if (dependencies['@builder.io/qwik'] || dependencies['@qwik.dev/core']) {\n    return 'qwik'\n  }\n  return 'vanilla'\n}\n\nfunction getPossibleProvider(dependencies: Record<string, string>) {\n  if (dependencies.webdriverio || dependencies['@wdio/cli'] || dependencies['@wdio/config']) {\n    return 'webdriverio'\n  }\n  // playwright is the default recommendation\n  return 'playwright'\n}\n\nfunction getProviderDocsLink(provider: string) {\n  switch (provider) {\n    case 'playwright':\n      return 'https://vitest.dev/config/browser/playwright'\n    case 'webdriverio':\n      return 'https://vitest.dev/config/browser/webdriverio'\n  }\n}\n\nfunction sort(choices: prompt.Choice[], value: string | undefined) {\n  const index = choices.findIndex(i => i.value === value)\n  if (index === -1) {\n    return choices\n  }\n  const item = choices.splice(index, 1)[0]\n  return [item, ...choices]\n}\n\nfunction fail() {\n  process.exitCode = 1\n}\n\nfunction getFrameworkImportInfo(framework: string) {\n  switch (framework) {\n    case 'svelte':\n      return { importName: 'svelte', isNamedExport: true }\n    case 'qwik':\n      return { importName: 'qwikVite', isNamedExport: true }\n    default:\n      return { importName: framework, isNamedExport: false }\n  }\n}\n\nasync function generateFrameworkConfigFile(options: {\n  configPath: string\n  framework: string\n  frameworkPlugin: string | null\n  provider: string\n  browsers: string[]\n}) {\n  const { importName, isNamedExport } = getFrameworkImportInfo(options.framework)\n\n  const frameworkImport = isNamedExport\n    ? `import { ${importName} } from '${options.frameworkPlugin}'`\n    : `import ${importName} from '${options.frameworkPlugin}'`\n\n  const configContent = [\n    `import { defineConfig } from 'vitest/config'`,\n    `import { ${options.provider} } from '@vitest/browser-${options.provider}'`,\n    options.frameworkPlugin ? frameworkImport : null,\n    ``,\n    'export default defineConfig({',\n    options.frameworkPlugin ? `  plugins: [${importName}()],` : null,\n    `  test: {`,\n    `    browser: {`,\n    `      enabled: true,`,\n    `      provider: ${options.provider}(),`,\n    options.provider !== 'preview' && `      // ${getProviderDocsLink(options.provider)}`,\n    `      instances: [`,\n    ...options.browsers.map(browser => `        { browser: '${browser}' },`),\n    `      ],`,\n    `    },`,\n    `  },`,\n    `})`,\n    '',\n  ].filter(t => typeof t === 'string').join('\\n')\n  await writeFile(options.configPath, configContent)\n}\n\nasync function updatePkgJsonScripts(pkgJsonPath: string, vitestScript: string) {\n  if (!existsSync(pkgJsonPath)) {\n    const pkg = {\n      scripts: {\n        'test:browser': vitestScript,\n      },\n    }\n    await writeFile(pkgJsonPath, `${JSON.stringify(pkg, null, 2)}\\n`, 'utf-8')\n  }\n  else {\n    const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n    pkg.scripts = pkg.scripts || {}\n    pkg.scripts['test:browser'] = vitestScript\n    await writeFile(pkgJsonPath, `${JSON.stringify(pkg, null, 2)}\\n`, 'utf-8')\n  }\n  log(c.green('✔'), 'Added \"test:browser\" script to your package.json.')\n}\n\nfunction getRunScript(pkgManager: Agent | null) {\n  switch (pkgManager) {\n    case 'yarn@berry':\n    case 'yarn':\n      return 'yarn test:browser'\n    case 'pnpm@6':\n    case 'pnpm':\n      return 'pnpm test:browser'\n    case 'bun':\n      return 'bun test:browser'\n    default:\n      return 'npm run test:browser'\n  }\n}\n\nfunction getPlaywrightRunArgs(pkgManager: Agent | null) {\n  switch (pkgManager) {\n    case 'yarn@berry':\n    case 'yarn':\n      return ['yarn', 'exec']\n    case 'pnpm@6':\n    case 'pnpm':\n      return ['pnpx']\n    case 'bun':\n      return ['bunx']\n    default:\n      return ['npx']\n  }\n}\n\nexport async function create(): Promise<void> {\n  log(c.cyan('◼'), 'This utility will help you set up a browser testing environment.\\n')\n\n  const pkgJsonPath = resolve(process.cwd(), 'package.json')\n  const pkg = readPkgJson(pkgJsonPath) || {}\n  const dependencies = {\n    ...pkg.dependencies,\n    ...pkg.devDependencies,\n  }\n\n  const defaults = getPossibleDefaults(dependencies)\n\n  const { lang } = await prompt({\n    type: 'select',\n    name: 'lang',\n    message: 'Choose a language for your tests',\n    choices: sort(getLanguageOptions(), defaults?.lang),\n  })\n\n  if (!lang) {\n    return fail()\n  }\n\n  const { provider } = await prompt({\n    type: 'select',\n    name: 'provider',\n    message: 'Choose a browser provider. Vitest will use its API to control the testing environment',\n    choices: sort(getProviderOptions(), defaults?.provider),\n  })\n  if (!provider) {\n    return fail()\n  }\n\n  const { browsers } = await prompt({\n    type: 'multiselect',\n    name: 'browsers',\n    message: 'Choose a browser',\n    choices: getBrowserNames(provider).map(browser => ({\n      title: browser,\n      value: browser,\n    })),\n  })\n  if (!provider) {\n    return fail()\n  }\n\n  const { framework } = await prompt({\n    type: 'select',\n    name: 'framework',\n    message: 'Choose your framework',\n    choices: sort(getFramework(), defaults?.framework),\n  })\n  if (!framework) {\n    return fail()\n  }\n\n  let installPlaywright = false\n  if (provider === 'playwright') {\n    ;({ installPlaywright } = await prompt({\n      type: 'confirm',\n      name: 'installPlaywright',\n      message: `Install Playwright browsers (can be done manually via 'pnpm exec playwright install')?`,\n    }))\n  }\n  if (installPlaywright == null) {\n    return fail()\n  }\n\n  const dependenciesToInstall = [\n    `@vitest/browser-${provider}`,\n  ]\n\n  const frameworkPackage = getFrameworkTestPackage(framework)\n  if (frameworkPackage) {\n    dependenciesToInstall.push(frameworkPackage)\n  }\n\n  const frameworkPlugin = getFrameworkPluginPackage(framework)\n  if (frameworkPlugin) {\n    dependenciesToInstall.push(frameworkPlugin)\n  }\n\n  const pkgManager = await detectPackageManager()\n\n  log()\n  await installPackages(\n    pkgManager,\n    dependenciesToInstall.filter(pkg => !dependencies[pkg]),\n  )\n\n  const rootConfig = find.any(configFiles, {\n    cwd: process.cwd(),\n  })\n\n  let scriptCommand = 'vitest'\n\n  log()\n\n  if (rootConfig) {\n    const configPath = resolve(dirname(rootConfig), `vitest.browser.config.${lang}`)\n    scriptCommand = `vitest --config=${relative(process.cwd(), configPath)}`\n    await generateFrameworkConfigFile({\n      configPath,\n      framework,\n      frameworkPlugin,\n      provider,\n      browsers,\n    })\n    log(\n      c.green('✔'),\n      'Created a new config file for browser tests:',\n      c.bold(relative(process.cwd(), configPath)),\n      // TODO: Can we modify the config ourselves?\n      '\\nSince you already have a Vitest config file, it is recommended to copy the contents of the new file ',\n      'into your existing config located at ',\n      c.bold(relative(process.cwd(), rootConfig)),\n    )\n  }\n  else {\n    const configPath = resolve(process.cwd(), `vitest.config.${lang}`)\n    await generateFrameworkConfigFile({\n      configPath,\n      framework,\n      frameworkPlugin,\n      provider,\n      browsers,\n    })\n    log(c.green('✔'), 'Created a config file for browser tests:', c.bold(relative(process.cwd(), configPath)))\n  }\n\n  log()\n  await updatePkgJsonScripts(pkgJsonPath, scriptCommand)\n\n  if (installPlaywright) {\n    log()\n    const [command, ...args] = getPlaywrightRunArgs(pkgManager)\n    const allArgs = [...args, 'playwright', 'install', '--with-deps']\n    log(c.cyan('◼'), `Installing Playwright dependencies with \\`${c.bold(command)} ${c.bold(allArgs.join(' '))}\\`...`)\n    log()\n    await x(command, allArgs, {\n      nodeOptions: {\n        stdio: ['pipe', 'inherit', 'inherit'],\n      },\n    })\n  }\n\n  log()\n  const exampleTestFile = await generateExampleFiles(framework, lang)\n  log(c.green('✔'), 'Created example test file in', c.bold(relative(process.cwd(), exampleTestFile)))\n  log(c.dim('  You can safely delete this file once you have written your own tests.'))\n\n  log()\n  log(c.cyan('◼'), 'All done! Run your tests with', c.bold(getRunScript(pkgManager)))\n}\n"
  },
  {
    "path": "packages/vitest/src/create/browser/examples.ts",
    "content": "import { existsSync, writeFileSync } from 'node:fs'\nimport { mkdir } from 'node:fs/promises'\nimport { resolve } from 'node:path'\n\nconst jsxExample = {\n  name: 'HelloWorld.jsx',\n  js: `\nexport default function HelloWorld({ name }) {\n  return (\n    <div>\n      <h1>Hello {name}!</h1>\n    </div>\n  )\n}\n`,\n  ts: `\nexport default function HelloWorld({ name }: { name: string }) {\n  return (\n    <div>\n      <h1>Hello {name}!</h1>\n    </div>\n  )\n}\n`,\n  test: `\nimport { expect, test } from 'vitest'\nimport { render } from '@testing-library/jsx'\nimport HelloWorld from './HelloWorld.<EXT>x'\n\ntest('renders name', async () => {\n  const { getByText } = await render(<HelloWorld name=\"Vitest\" />)\n  await expect.element(getByText('Hello Vitest!')).toBeInTheDocument()\n})\n`,\n}\n\nconst vueExample = {\n  name: 'HelloWorld.vue',\n  js: `\n<script setup>\ndefineProps({\n  name: String\n})\n</script>\n\n<template>\n  <div>\n    <h1>Hello {{ name }}!</h1>\n  </div>\n</template>\n`,\n  ts: `\n<script setup lang=\"ts\">\ndefineProps<{\n  name: string\n}>()\n</script>\n\n<template>\n  <div>\n    <h1>Hello {{ name }}!</h1>\n  </div>\n</template>\n`,\n  test: `\nimport { expect, test } from 'vitest'\nimport { render } from 'vitest-browser-vue'\nimport HelloWorld from './HelloWorld.vue'\n\ntest('renders name', async () => {\n  const { getByText } = render(HelloWorld, {\n    props: { name: 'Vitest' },\n  })\n  await expect.element(getByText('Hello Vitest!')).toBeInTheDocument()\n})\n`,\n}\n\nconst svelteExample = {\n  name: 'HelloWorld.svelte',\n  js: `\n<script>\n  export let name\n</script>\n\n<h1>Hello {name}!</h1>\n`,\n  ts: `\n<script lang=\"ts\">\n  export let name: string\n</script>\n\n<h1>Hello {name}!</h1>\n`,\n  test: `\nimport { expect, test } from 'vitest'\nimport { render } from 'vitest-browser-svelte'\nimport HelloWorld from './HelloWorld.svelte'\n\ntest('renders name', async () => {\n  const { getByText } = render(HelloWorld, { name: 'Vitest' })\n  await expect.element(getByText('Hello Vitest!')).toBeInTheDocument()\n})\n`,\n}\n\nconst markoExample = {\n  name: 'HelloWorld.marko',\n  js: `\nclass {\n  onCreate() {\n    this.state = { name: null }\n  }\n}\n\n<h1>Hello \\${state.name}!</h1>\n`,\n  ts: `\nexport interface Input {\n  name: string\n}\n\n<h1>Hello \\${input.name}!</h1>\n`,\n  test: `\nimport { expect, test } from 'vitest'\nimport { render } from '@marko/testing-library'\nimport HelloWorld from './HelloWorld.svelte'\n\ntest('renders name', async () => {\n  const { getByText } = await render(HelloWorld, { name: 'Vitest' })\n  const element = getByText('Hello Vitest!')\n  expect(element).toBeInTheDocument()\n})\n`,\n}\n\nconst litExample = {\n  name: 'HelloWorld.js',\n  js: `\nimport { html, LitElement } from 'lit'\n\nexport class HelloWorld extends LitElement {\n  static properties = {\n    name: { type: String },\n  }\n\n  constructor() {\n    super()\n    this.name = 'World'\n  }\n\n  render() {\n    return html\\`<h1>Hello \\${this.name}!</h1>\\`\n  }\n}\n\ncustomElements.define('hello-world', HelloWorld)\n`,\n  ts: `\nimport { html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n@customElement('hello-world')\nexport class HelloWorld extends LitElement {\n  @property({ type: String })\n  name = 'World'\n\n  render() {\n    return html\\`<h1>Hello \\${this.name}!</h1>\\`\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'hello-world': HelloWorld\n  }\n}\n`,\n  test: `\nimport { expect, test } from 'vitest'\nimport { render } from 'vitest-browser-lit'\nimport { html } from 'lit'\nimport './HelloWorld.js'\n\ntest('renders name', async () => {\n  const screen = render(html\\`<hello-world name=\"Vitest\"></hello-world>\\`)\n  const element = screen.getByText('Hello Vitest!')\n  await expect.element(element).toBeInTheDocument()\n})\n`,\n}\n\nconst qwikExample = {\n  name: 'HelloWorld.jsx',\n  js: `\nimport { component$ } from '@builder.io/qwik'\n\nexport default component$(({ name }) => {\n  return (\n    <div>\n      <h1>Hello {name}!</h1>\n    </div>\n  )\n})\n`,\n  ts: `\nimport { component$ } from '@builder.io/qwik'\n\nexport default component$(({ name }: { name: string }) => {\n  return (\n    <div>\n      <h1>Hello {name}!</h1>\n    </div>\n  )\n})\n`,\n  test: `\nimport { expect, test } from 'vitest'\nimport { render } from 'vitest-browser-qwik'\nimport HelloWorld from './HelloWorld.tsx'\n\ntest('renders name', async () => {\n  const { getByText } = render(<HelloWorld name=\"Vitest\" />)\n  await expect.element(getByText('Hello Vitest!')).toBeInTheDocument()\n})\n`,\n}\n\nconst preactExample = {\n  name: 'HelloWorld.jsx',\n  js: `\nexport default function HelloWorld({ name }) {\n  return (\n    <div>\n      <h1>Hello {name}!</h1>\n    </div>\n  )\n}\n`,\n  ts: `\nexport default function HelloWorld({ name }: { name: string }) {\n  return (\n    <div>\n      <h1>Hello {name}!</h1>\n    </div>\n  )\n}\n`,\n  test: `\nimport { expect, test } from 'vitest'\nimport { render } from 'vitest-browser-preact'\nimport HelloWorld from './HelloWorld.<EXT>x'\n\ntest('renders name', async () => {\n  const { getByText } = render(<HelloWorld name=\"Vitest\" />)\n  await expect.element(getByText('Hello Vitest!')).toBeInTheDocument()\n})\n`,\n}\n\nconst vanillaExample = {\n  name: 'HelloWorld.js',\n  js: `\nexport default function HelloWorld({ name }) {\n  const parent = document.createElement('div')\n\n  const h1 = document.createElement('h1')\n  h1.textContent = 'Hello ' + name + '!'\n  parent.appendChild(h1)\n\n  return parent\n}\n`,\n  ts: `\nexport default function HelloWorld({ name }: { name: string }): HTMLDivElement {\n  const parent = document.createElement('div')\n\n  const h1 = document.createElement('h1')\n  h1.textContent = 'Hello ' + name + '!'\n  parent.appendChild(h1)\n\n  return parent\n}\n`,\n  test: `\nimport { expect, test } from 'vitest'\nimport { getByText } from '@testing-library/dom'\nimport HelloWorld from './HelloWorld.js'\n\ntest('renders name', () => {\n  const parent = HelloWorld({ name: 'Vitest' })\n  document.body.appendChild(parent)\n\n  const element = getByText(parent, 'Hello Vitest!')\n  expect(element).toBeInTheDocument()\n})\n`,\n}\n\nfunction getExampleTest(framework: string) {\n  switch (framework) {\n    case 'solid':\n      return {\n        ...jsxExample,\n        test: jsxExample.test.replace('@testing-library/jsx', `@testing-library/${framework}`),\n      }\n    case 'preact':\n      return preactExample\n    case 'react':\n      return {\n        ...jsxExample,\n        test: jsxExample.test.replace('@testing-library/jsx', `vitest-browser-${framework}`),\n      }\n    case 'vue':\n      return vueExample\n    case 'svelte':\n      return svelteExample\n    case 'lit':\n      return litExample\n    case 'marko':\n      return markoExample\n    case 'qwik':\n      return qwikExample\n    default:\n      return vanillaExample\n  }\n}\n\nexport async function generateExampleFiles(framework: string, lang: 'ts' | 'js'): Promise<string> {\n  const example = getExampleTest(framework)\n  let fileName = example.name\n  const folder = resolve(process.cwd(), 'vitest-example')\n  const fileContent = example[lang]\n\n  if (!existsSync(folder)) {\n    await mkdir(folder, { recursive: true })\n  }\n  const isJSX = fileName.endsWith('.jsx')\n\n  if (isJSX && lang === 'ts') {\n    fileName = fileName.replace('.jsx', '.tsx')\n  }\n  else if (fileName.endsWith('.js') && lang === 'ts') {\n    fileName = fileName.replace('.js', '.ts')\n  }\n\n  example.test = example.test.replace('<EXT>', lang)\n\n  const filePath = resolve(folder, fileName)\n  const testPath = resolve(folder, `HelloWorld.test.${isJSX ? `${lang}x` : lang}`)\n  writeFileSync(filePath, fileContent.trimStart(), 'utf-8')\n  writeFileSync(testPath, example.test.trimStart(), 'utf-8')\n  return testPath\n}\n"
  },
  {
    "path": "packages/vitest/src/defaults.ts",
    "content": "import type {\n  BenchmarkUserOptions,\n  CoverageV8Options,\n  ResolvedCoverageOptions,\n  UserConfig,\n} from './node/types/config'\nimport os from 'node:os'\nimport { isAgent, isCI } from './utils/env'\n\nexport { defaultBrowserPort } from './constants'\n\nexport const defaultInclude: string[] = ['**/*.{test,spec}.?(c|m)[jt]s?(x)']\nexport const defaultExclude: string[] = [\n  '**/node_modules/**',\n  '**/.git/**',\n]\nexport const benchmarkConfigDefaults: Required<\n  Omit<BenchmarkUserOptions, 'outputFile' | 'compare' | 'outputJson'>\n> = {\n  include: ['**/*.{bench,benchmark}.?(c|m)[jt]s?(x)'],\n  exclude: defaultExclude,\n  includeSource: [],\n  reporters: ['default'],\n  includeSamples: false,\n}\n\n// These are the generic defaults for coverage. Providers may also set some provider specific defaults.\nexport const coverageConfigDefaults: ResolvedCoverageOptions = {\n  provider: 'v8',\n  enabled: false,\n  clean: true,\n  cleanOnRerun: true,\n  reportsDirectory: './coverage',\n  exclude: [],\n  reportOnFailure: false,\n  reporter: [\n    ['text', {}],\n    ['html', {}],\n    ['clover', {}],\n    ['json', {}],\n  ],\n  allowExternal: false,\n  excludeAfterRemap: false,\n  processingConcurrency: Math.min(\n    20,\n    os.availableParallelism?.() ?? os.cpus().length,\n  ),\n}\n\nexport const fakeTimersDefaults: NonNullable<UserConfig['fakeTimers']> = {\n  loopLimit: 10_000,\n  shouldClearNativeTimers: true,\n}\n\nexport const configDefaults: Readonly<{\n  allowOnly: boolean\n  isolate: boolean\n  watch: boolean\n  globals: boolean\n  environment: 'node'\n  clearMocks: boolean\n  restoreMocks: boolean\n  mockReset: boolean\n  unstubGlobals: boolean\n  unstubEnvs: boolean\n  include: string[]\n  exclude: string[]\n  teardownTimeout: number\n  forceRerunTriggers: string[]\n  update: boolean\n  reporters: never[]\n  silent: boolean\n  hideSkippedTests: boolean\n  api: boolean\n  ui: boolean\n  uiBase: string\n  open: boolean\n  css: {\n    include: never[]\n  }\n  coverage: CoverageV8Options\n  fakeTimers: import('@sinonjs/fake-timers').FakeTimerInstallOpts\n  maxConcurrency: number\n  dangerouslyIgnoreUnhandledErrors: boolean\n  typecheck: {\n    checker: 'tsc'\n    include: string[]\n    exclude: string[]\n  }\n  slowTestThreshold: number\n  disableConsoleIntercept: boolean\n  detectAsyncLeaks: boolean\n}> = Object.freeze({\n  allowOnly: !isCI,\n  isolate: true,\n  watch: !isCI && process.stdin.isTTY && !isAgent,\n  globals: false,\n  environment: 'node' as const,\n  clearMocks: false,\n  restoreMocks: false,\n  mockReset: false,\n  unstubGlobals: false,\n  unstubEnvs: false,\n  include: defaultInclude,\n  exclude: defaultExclude,\n  teardownTimeout: 10000,\n  forceRerunTriggers: ['**/package.json/**', '**/{vitest,vite}.config.*/**'],\n  update: false,\n  reporters: [],\n  silent: false,\n  hideSkippedTests: false,\n  api: false,\n  ui: false,\n  uiBase: '/__vitest__/',\n  open: !isCI,\n  css: {\n    include: [],\n  },\n  coverage: coverageConfigDefaults as CoverageV8Options,\n  fakeTimers: fakeTimersDefaults,\n  maxConcurrency: 5,\n  dangerouslyIgnoreUnhandledErrors: false,\n  typecheck: {\n    checker: 'tsc' as const,\n    include: ['**/*.{test,spec}-d.?(c|m)[jt]s?(x)'],\n    exclude: defaultExclude,\n  },\n  slowTestThreshold: 300,\n  disableConsoleIntercept: false,\n  detectAsyncLeaks: false,\n})\n"
  },
  {
    "path": "packages/vitest/src/integrations/chai/config.ts",
    "content": "import { chai } from '@vitest/expect'\n\nexport function setupChaiConfig(config: ChaiConfig): void {\n  Object.assign(chai.config, config)\n}\n\nexport type ChaiConfig = Omit<\n  Partial<typeof chai.config>,\n  'useProxy' | 'proxyExcludedKeys' | 'deepEqual'\n>\n"
  },
  {
    "path": "packages/vitest/src/integrations/chai/index.ts",
    "content": "import type { Assertion, ExpectStatic, MatcherState } from '@vitest/expect'\nimport type { TaskPopulated, Test } from '@vitest/runner'\nimport {\n  addCustomEqualityTesters,\n  ASYMMETRIC_MATCHERS_OBJECT,\n  chai,\n  customMatchers,\n  getState,\n  GLOBAL_EXPECT,\n  setState,\n} from '@vitest/expect'\nimport { getCurrentTest } from '@vitest/runner'\nimport { getWorkerState } from '../../runtime/utils'\nimport { createExpectPoll } from './poll'\nimport './setup'\n\nexport function createExpect(test?: Test | TaskPopulated): ExpectStatic {\n  const expect = ((value: any, message?: string): Assertion => {\n    const { assertionCalls } = getState(expect)\n    setState({ assertionCalls: assertionCalls + 1 }, expect)\n    const assert = chai.expect(value, message) as unknown as Assertion\n    const _test = test || getCurrentTest()\n    if (_test) {\n      // @ts-expect-error internal\n      return assert.withTest(_test) as Assertion\n    }\n    else {\n      return assert\n    }\n  }) as ExpectStatic\n  Object.assign(expect, chai.expect)\n  Object.assign(expect, (globalThis as any)[ASYMMETRIC_MATCHERS_OBJECT])\n\n  expect.getState = () => getState<MatcherState>(expect)\n  expect.setState = state => setState(state as Partial<MatcherState>, expect)\n\n  // @ts-expect-error global is not typed\n  const globalState = getState(globalThis[GLOBAL_EXPECT]) || {}\n\n  setState<MatcherState>(\n    {\n      // this should also add \"snapshotState\" that is added conditionally\n      ...globalState,\n      assertionCalls: 0,\n      isExpectingAssertions: false,\n      isExpectingAssertionsError: null,\n      expectedAssertionsNumber: null,\n      expectedAssertionsNumberErrorGen: null,\n      get testPath() {\n        return getWorkerState().filepath\n      },\n      currentTestName: test\n        ? test.fullTestName ?? ''\n        : globalState.currentTestName,\n    },\n    expect,\n  )\n\n  expect.assert = chai.assert\n  // @ts-expect-error untyped\n  expect.extend = matchers => chai.expect.extend(expect, matchers)\n  expect.addEqualityTesters = customTesters =>\n    addCustomEqualityTesters(customTesters)\n\n  expect.soft = (...args) => {\n    // @ts-expect-error private soft access\n    return expect(...args).withContext({ soft: true }) as Assertion\n  }\n\n  expect.poll = createExpectPoll(expect)\n\n  expect.unreachable = (message?: string) => {\n    chai.assert.fail(\n      `expected${message ? ` \"${message}\" ` : ' '}not to be reached`,\n    )\n  }\n\n  function assertions(expected: number) {\n    const errorGen = () =>\n      new Error(\n        `expected number of assertions to be ${expected}, but got ${\n          expect.getState().assertionCalls\n        }`,\n      )\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(errorGen(), assertions)\n    }\n\n    expect.setState({\n      expectedAssertionsNumber: expected,\n      expectedAssertionsNumberErrorGen: errorGen,\n    })\n  }\n\n  function hasAssertions() {\n    const error = new Error('expected any number of assertion, but got none')\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(error, hasAssertions)\n    }\n\n    expect.setState({\n      isExpectingAssertions: true,\n      isExpectingAssertionsError: error,\n    })\n  }\n\n  chai.util.addMethod(expect, 'assertions', assertions)\n  chai.util.addMethod(expect, 'hasAssertions', hasAssertions)\n\n  expect.extend(customMatchers)\n\n  return expect\n}\n\nconst globalExpect: ExpectStatic = createExpect()\n\nObject.defineProperty(globalThis, GLOBAL_EXPECT, {\n  value: globalExpect,\n  writable: true,\n  configurable: true,\n})\n\nexport const assert: Chai.Assert = chai.assert\nexport const should: () => Chai.Should = chai.should\nexport { chai, globalExpect as expect }\n"
  },
  {
    "path": "packages/vitest/src/integrations/chai/poll.ts",
    "content": "import type { Assertion, ExpectStatic } from '@vitest/expect'\nimport type { Test } from '@vitest/runner'\nimport { chai } from '@vitest/expect'\nimport { delay, getSafeTimers } from '@vitest/utils/timers'\nimport { getWorkerState } from '../../runtime/utils'\n\n// these matchers are not supported because they don't make sense with poll\nconst unsupported = [\n  // .poll is meant to retry matchers until they succeed, and\n  // snapshots will always succeed as long as the poll method doesn't throw an error\n  // in this case using the `vi.waitFor` method is more appropriate\n  'matchSnapshot',\n  'toMatchSnapshot',\n  'toMatchInlineSnapshot',\n  'toThrowErrorMatchingSnapshot',\n  'toThrowErrorMatchingInlineSnapshot',\n  // toThrow will never succeed because we call the poll callback until it doesn't throw\n  'throws',\n  'Throw',\n  'throw',\n  'toThrow',\n  'toThrowError',\n  // these are not supported because you can call them without `.poll`,\n  // we throw an error inside the rejects/resolves methods to prevent this\n  // rejects,\n  // resolves\n]\n\n/**\n * Attaches a `cause` property to the error if missing, copies the stack trace from the source, and throws.\n *\n * @param error - The error to throw\n * @param source - Error to copy the stack trace from\n *\n * @throws Always throws the provided error with an amended stack trace\n */\nfunction throwWithCause(error: any, source: Error) {\n  if (error.cause == null) {\n    error.cause = new Error('Matcher did not succeed in time.')\n  }\n\n  throw copyStackTrace(\n    error,\n    source,\n  )\n}\n\nexport function createExpectPoll(expect: ExpectStatic): ExpectStatic['poll'] {\n  return function poll(fn, options = {}) {\n    const state = getWorkerState()\n    const defaults = state.config.expect?.poll ?? {}\n    const {\n      interval = defaults.interval ?? 50,\n      timeout = defaults.timeout ?? 1000,\n      message,\n    } = options\n    // @ts-expect-error private poll access\n    const assertion = expect(null, message).withContext({\n      poll: true,\n    }) as Assertion\n    fn = fn.bind(assertion)\n    const test = chai.util.flag(assertion, 'vitest-test') as Test | undefined\n    if (!test) {\n      throw new Error('expect.poll() must be called inside a test')\n    }\n    const proxy: any = new Proxy(assertion, {\n      get(target, key, receiver) {\n        const assertionFunction = Reflect.get(target, key, receiver)\n\n        if (typeof assertionFunction !== 'function') {\n          return assertionFunction instanceof chai.Assertion ? proxy : assertionFunction\n        }\n\n        if (key === 'assert') {\n          return assertionFunction\n        }\n\n        if (typeof key === 'string' && unsupported.includes(key)) {\n          throw new SyntaxError(\n            `expect.poll() is not supported in combination with .${key}(). Use vi.waitFor() if your assertion condition is unstable.`,\n          )\n        }\n\n        return function (this: any, ...args: any[]) {\n          const STACK_TRACE_ERROR = new Error('STACK_TRACE_ERROR')\n          const promise = async () => {\n            const { setTimeout, clearTimeout } = getSafeTimers()\n\n            let executionPhase: 'fn' | 'assertion' = 'fn'\n            let hasTimedOut = false\n\n            const timerId = setTimeout(() => {\n              hasTimedOut = true\n            }, timeout)\n\n            chai.util.flag(assertion, '_name', key)\n\n            const onSettled = chai.util.flag(assertion, '_poll.onSettled') as Function | undefined\n\n            try {\n              while (true) {\n                const isLastAttempt = hasTimedOut\n\n                if (isLastAttempt) {\n                  chai.util.flag(assertion, '_isLastPollAttempt', true)\n                }\n\n                try {\n                  executionPhase = 'fn'\n                  const obj = await fn()\n                  chai.util.flag(assertion, 'object', obj)\n\n                  executionPhase = 'assertion'\n                  const output = await assertionFunction.call(assertion, ...args)\n                  await onSettled?.({ assertion, status: 'pass' })\n\n                  return output\n                }\n                catch (err) {\n                  if (isLastAttempt || (executionPhase === 'assertion' && chai.util.flag(assertion, '_poll.assert_once'))) {\n                    await onSettled?.({ assertion, status: 'fail' })\n                    throwWithCause(err, STACK_TRACE_ERROR)\n                  }\n\n                  await delay(interval, setTimeout)\n                }\n              }\n            }\n            finally {\n              clearTimeout(timerId)\n            }\n          }\n          let awaited = false\n          test.onFinished ??= []\n          test.onFinished.push(() => {\n            if (!awaited) {\n              const negated = chai.util.flag(assertion, 'negate') ? 'not.' : ''\n              const name = chai.util.flag(assertion, '_poll.element') ? 'element(locator)' : 'poll(assertion)'\n              const assertionString = `expect.${name}.${negated}${String(key)}()`\n              const error = new Error(\n                `${assertionString} was not awaited. This assertion is asynchronous and must be awaited; otherwise, it is not executed to avoid unhandled rejections:\\n\\nawait ${assertionString}\\n`,\n              )\n              throw copyStackTrace(error, STACK_TRACE_ERROR)\n            }\n          })\n          let resultPromise: Promise<void> | undefined\n          // only .then is enough to check awaited, but we type this as `Promise<void>` in global types\n          // so let's follow it\n          return {\n            then(onFulfilled, onRejected) {\n              awaited = true\n              return (resultPromise ||= promise()).then(onFulfilled, onRejected)\n            },\n            catch(onRejected) {\n              awaited = true\n              return (resultPromise ||= promise()).catch(onRejected)\n            },\n            finally(onFinally) {\n              awaited = true\n              return (resultPromise ||= promise()).finally(onFinally)\n            },\n            [Symbol.toStringTag]: 'Promise',\n          } satisfies Promise<void>\n        }\n      },\n    })\n    return proxy\n  }\n}\n\nfunction copyStackTrace(target: Error, source: Error) {\n  if (source.stack !== undefined) {\n    target.stack = source.stack.replace(source.message, target.message)\n  }\n  return target\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/chai/setup.ts",
    "content": "import {\n  chai,\n  ChaiStyleAssertions,\n  JestAsymmetricMatchers,\n  JestChaiExpect,\n  JestExtend,\n} from '@vitest/expect'\nimport { SnapshotPlugin } from '../snapshot/chai'\n\nchai.use(JestExtend)\nchai.use(JestChaiExpect)\nchai.use(ChaiStyleAssertions)\nchai.use(SnapshotPlugin)\nchai.use(JestAsymmetricMatchers)\n"
  },
  {
    "path": "packages/vitest/src/integrations/coverage.ts",
    "content": "import type { SerializedCoverageConfig } from '../runtime/config'\nimport type { RuntimeCoverageModuleLoader } from '../utils/coverage'\nimport { resolveCoverageProviderModule } from '../utils/coverage'\n\nexport async function startCoverageInsideWorker(\n  options: SerializedCoverageConfig | undefined,\n  loader: RuntimeCoverageModuleLoader,\n  runtimeOptions: { isolate: boolean },\n): Promise<unknown> {\n  const coverageModule = await resolveCoverageProviderModule(options, loader)\n\n  if (coverageModule) {\n    return coverageModule.startCoverage?.(runtimeOptions)\n  }\n\n  return null\n}\n\nexport async function takeCoverageInsideWorker(\n  options: SerializedCoverageConfig | undefined,\n  loader: RuntimeCoverageModuleLoader,\n): Promise<unknown> {\n  const coverageModule = await resolveCoverageProviderModule(options, loader)\n\n  if (coverageModule) {\n    return coverageModule.takeCoverage?.({ moduleExecutionInfo: loader.moduleExecutionInfo })\n  }\n\n  return null\n}\n\nexport async function stopCoverageInsideWorker(\n  options: SerializedCoverageConfig | undefined,\n  loader: RuntimeCoverageModuleLoader,\n  runtimeOptions: { isolate: boolean },\n): Promise<unknown> {\n  const coverageModule = await resolveCoverageProviderModule(options, loader)\n\n  if (coverageModule) {\n    return coverageModule.stopCoverage?.(runtimeOptions)\n  }\n\n  return null\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/css/css-modules.ts",
    "content": "import type { CSSModuleScopeStrategy } from '../../node/types/config'\nimport { hash } from '../../node/hash'\n\nexport function generateCssFilenameHash(filepath: string): string {\n  return hash('sha1', filepath, 'hex').slice(0, 6)\n}\n\nexport function generateScopedClassName(\n  strategy: CSSModuleScopeStrategy,\n  name: string,\n  filename: string,\n): string | null {\n  // should be configured by Vite defaults\n  if (strategy === 'scoped') {\n    return null\n  }\n  if (strategy === 'non-scoped') {\n    return name\n  }\n  const hash = generateCssFilenameHash(filename)\n  return `_${name}_${hash}`\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/env/edge-runtime.ts",
    "content": "import type { Environment } from '../../types/environment'\nimport { KEYS } from './jsdom-keys'\nimport { populateGlobal } from './utils'\n\nexport default <Environment>{\n  name: 'edge-runtime',\n  viteEnvironment: 'ssr',\n  async setupVM() {\n    const { EdgeVM } = await import('@edge-runtime/vm')\n    const vm = new EdgeVM({\n      extend: (context) => {\n        context.global = context\n        context.Buffer = Buffer\n        return context\n      },\n    })\n    return {\n      getVmContext() {\n        return vm.context\n      },\n      teardown() {\n        // nothing to teardown\n      },\n    }\n  },\n  async setup(global) {\n    const { EdgeVM } = await import('@edge-runtime/vm')\n    const vm = new EdgeVM({\n      extend: (context) => {\n        context.global = context\n        context.Buffer = Buffer\n        KEYS.forEach((key) => {\n          if (key in global) {\n            context[key] = global[key]\n          }\n        })\n        return context\n      },\n    })\n    const { keys, originals } = populateGlobal(global, vm.context, {\n      bindFunctions: true,\n    })\n    return {\n      teardown(global) {\n        keys.forEach(key => delete global[key])\n        originals.forEach((v, k) => (global[k] = v))\n      },\n    }\n  },\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/env/happy-dom.ts",
    "content": "import type { Environment } from '../../types/environment'\nimport { populateGlobal } from './utils'\n\nasync function teardownWindow(win: {\n  happyDOM: { abort?: () => Promise<void>; cancelAsync: () => void }\n  close?: () => void\n}) {\n  if (win.close && win.happyDOM.abort) {\n    await win.happyDOM.abort()\n    win.close()\n  }\n  else {\n    win.happyDOM.cancelAsync()\n  }\n}\n\nexport default <Environment>{\n  name: 'happy-dom',\n  viteEnvironment: 'client',\n  async setupVM({ happyDOM = {} }) {\n    const { Window } = await import('happy-dom')\n    let win = new Window({\n      ...happyDOM,\n      console: console && globalThis.console ? globalThis.console : undefined,\n      url: happyDOM.url || 'http://localhost:3000',\n      settings: {\n        ...happyDOM.settings,\n        disableErrorCapturing: true,\n      },\n    }) as any\n\n    // TODO: browser doesn't expose Buffer, but a lot of dependencies use it\n    win.Buffer = Buffer\n\n    // inject structuredClone if it exists\n    if (typeof structuredClone !== 'undefined' && !win.structuredClone) {\n      win.structuredClone = structuredClone\n    }\n\n    return {\n      getVmContext() {\n        return win\n      },\n      async teardown() {\n        await teardownWindow(win)\n        win = undefined\n      },\n    }\n  },\n  async setup(global, { happyDOM = {} }) {\n    // happy-dom v3 introduced a breaking change to Window, but\n    // provides GlobalWindow as a way to use previous behaviour\n    const { Window, GlobalWindow } = await import('happy-dom')\n    const win = new (GlobalWindow || Window)({\n      ...happyDOM,\n      console: console && global.console ? global.console : undefined,\n      url: happyDOM.url || 'http://localhost:3000',\n      settings: {\n        ...happyDOM.settings,\n        disableErrorCapturing: true,\n      },\n    })\n\n    const { keys, originals } = populateGlobal(global, win, {\n      bindFunctions: true,\n      // jsdom doesn't support fetch API, but happy-dom does\n      additionalKeys: [\n        'Request',\n        'Response',\n        'MessagePort',\n        'fetch',\n        'Headers',\n        'AbortController',\n        'AbortSignal',\n        'URL',\n        'URLSearchParams',\n        'FormData',\n      ],\n    })\n\n    return {\n      async teardown(global) {\n        await teardownWindow(win)\n        keys.forEach(key => delete global[key])\n        originals.forEach((v, k) => (global[k] = v))\n      },\n    }\n  },\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/env/index.ts",
    "content": "import type { Environment } from '../../types/environment'\nimport edge from './edge-runtime'\nimport happy from './happy-dom'\nimport jsdom from './jsdom'\nimport node from './node'\n\nexport const environments: {\n  'node': Environment\n  'jsdom': Environment\n  'happy-dom': Environment\n  'edge-runtime': Environment\n} = {\n  node,\n  jsdom,\n  'happy-dom': happy,\n  'edge-runtime': edge,\n}\n\nexport const envs: string[] = Object.keys(environments)\n"
  },
  {
    "path": "packages/vitest/src/integrations/env/jsdom-keys.ts",
    "content": "// SEE https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/interfaces.js\n\nconst LIVING_KEYS = [\n  'DOMException',\n  'EventTarget',\n  'NamedNodeMap',\n  'Node',\n  'Attr',\n  'Element',\n  'DocumentFragment',\n  'DOMImplementation',\n  'Document',\n  'XMLDocument',\n  'CharacterData',\n  'Text',\n  'CDATASection',\n  'ProcessingInstruction',\n  'Comment',\n  'DocumentType',\n  'NodeList',\n  'RadioNodeList',\n  'HTMLCollection',\n  'HTMLOptionsCollection',\n  'DOMStringMap',\n  'DOMTokenList',\n  'StyleSheetList',\n  'HTMLElement',\n  'HTMLHeadElement',\n  'HTMLTitleElement',\n  'HTMLBaseElement',\n  'HTMLLinkElement',\n  'HTMLMetaElement',\n  'HTMLStyleElement',\n  'HTMLBodyElement',\n  'HTMLHeadingElement',\n  'HTMLParagraphElement',\n  'HTMLHRElement',\n  'HTMLPreElement',\n  'HTMLUListElement',\n  'HTMLOListElement',\n  'HTMLLIElement',\n  'HTMLMenuElement',\n  'HTMLDListElement',\n  'HTMLDivElement',\n  'HTMLAnchorElement',\n  'HTMLAreaElement',\n  'HTMLBRElement',\n  'HTMLButtonElement',\n  'HTMLCanvasElement',\n  'HTMLDataElement',\n  'HTMLDataListElement',\n  'HTMLDetailsElement',\n  'HTMLDialogElement',\n  'HTMLDirectoryElement',\n  'HTMLFieldSetElement',\n  'HTMLFontElement',\n  'HTMLFormElement',\n  'HTMLHtmlElement',\n  'HTMLImageElement',\n  'HTMLInputElement',\n  'HTMLLabelElement',\n  'HTMLLegendElement',\n  'HTMLMapElement',\n  'HTMLMarqueeElement',\n  'HTMLMediaElement',\n  'HTMLMeterElement',\n  'HTMLModElement',\n  'HTMLOptGroupElement',\n  'HTMLOptionElement',\n  'HTMLOutputElement',\n  'HTMLPictureElement',\n  'HTMLProgressElement',\n  'HTMLQuoteElement',\n  'HTMLScriptElement',\n  'HTMLSelectElement',\n  'HTMLSlotElement',\n  'HTMLSourceElement',\n  'HTMLSpanElement',\n  'HTMLTableCaptionElement',\n  'HTMLTableCellElement',\n  'HTMLTableColElement',\n  'HTMLTableElement',\n  'HTMLTimeElement',\n  'HTMLTableRowElement',\n  'HTMLTableSectionElement',\n  'HTMLTemplateElement',\n  'HTMLTextAreaElement',\n  'HTMLUnknownElement',\n  'HTMLFrameElement',\n  'HTMLFrameSetElement',\n  'HTMLIFrameElement',\n  'HTMLEmbedElement',\n  'HTMLObjectElement',\n  'HTMLParamElement',\n  'HTMLVideoElement',\n  'HTMLAudioElement',\n  'HTMLTrackElement',\n  'HTMLFormControlsCollection',\n  'SVGElement',\n  'SVGGraphicsElement',\n  'SVGSVGElement',\n  'SVGTitleElement',\n  'SVGAnimatedString',\n  'SVGNumber',\n  'SVGStringList',\n  'Event',\n  'CloseEvent',\n  'CustomEvent',\n  'MessageEvent',\n  'ErrorEvent',\n  'HashChangeEvent',\n  'PopStateEvent',\n  'StorageEvent',\n  'ProgressEvent',\n  'PageTransitionEvent',\n  'SubmitEvent',\n  'UIEvent',\n  'FocusEvent',\n  'InputEvent',\n  'MouseEvent',\n  'KeyboardEvent',\n  'TouchEvent',\n  'CompositionEvent',\n  'WheelEvent',\n  'BarProp',\n  'External',\n  'Location',\n  'History',\n  'Screen',\n  'Crypto',\n  'Performance',\n  'Navigator',\n  'PluginArray',\n  'MimeTypeArray',\n  'Plugin',\n  'MimeType',\n  'FileReader',\n  'FormData',\n  'Blob',\n  'File',\n  'FileList',\n  'ValidityState',\n  'DOMParser',\n  'XMLSerializer',\n  'XMLHttpRequestEventTarget',\n  'XMLHttpRequestUpload',\n  'XMLHttpRequest',\n  'WebSocket',\n  'NodeFilter',\n  'NodeIterator',\n  'TreeWalker',\n  'AbstractRange',\n  'Range',\n  'StaticRange',\n  'Selection',\n  'Storage',\n  'CustomElementRegistry',\n  'ShadowRoot',\n  'MutationObserver',\n  'MutationRecord',\n\n  'Uint8Array',\n  'Uint16Array',\n  'Uint32Array',\n  'Uint8ClampedArray',\n  'Int8Array',\n  'Int16Array',\n  'Int32Array',\n  'Float32Array',\n  'Float64Array',\n  'ArrayBuffer',\n  'DOMRectReadOnly',\n  'DOMRect',\n\n  // not specified in docs, but is available\n  'Image',\n  'Audio',\n  'Option',\n\n  'CSS',\n\n  // Conflict with Node.js values\n  // 'Headers',\n  // 'AbortController',\n  // 'AbortSignal',\n  // 'URL',\n  // 'URLSearchParams',\n]\n\nconst OTHER_KEYS = [\n  'addEventListener',\n  'alert',\n  // 'atob',\n  'blur',\n  // 'btoa',\n  'cancelAnimationFrame',\n  /* 'clearInterval', */\n  /* 'clearTimeout', */\n  'close',\n  'confirm',\n  /* 'console', */\n  'createPopup',\n  'dispatchEvent',\n  'document',\n  'focus',\n  'frames',\n  'getComputedStyle',\n  'history',\n  'innerHeight',\n  'innerWidth',\n  'length',\n  'location',\n  'matchMedia',\n  'moveBy',\n  'moveTo',\n  'name',\n  'navigator',\n  'open',\n  'outerHeight',\n  'outerWidth',\n  'pageXOffset',\n  'pageYOffset',\n  'parent',\n  'postMessage',\n  'print',\n  'prompt',\n  'removeEventListener',\n  'requestAnimationFrame',\n  'resizeBy',\n  'resizeTo',\n  'screen',\n  'screenLeft',\n  'screenTop',\n  'screenX',\n  'screenY',\n  'scroll',\n  'scrollBy',\n  'scrollLeft',\n  'scrollTo',\n  'scrollTop',\n  'scrollX',\n  'scrollY',\n  'self',\n  /* 'setInterval', */\n  /* 'setTimeout', */\n  'stop',\n  /* 'toString', */\n  'top',\n  'Window',\n  'window',\n]\n\nexport const KEYS: string[] = LIVING_KEYS.concat(OTHER_KEYS)\n"
  },
  {
    "path": "packages/vitest/src/integrations/env/jsdom.ts",
    "content": "import type { DOMWindow, VirtualConsole as IVirtualConsole } from 'jsdom'\nimport type { Environment } from '../../types/environment'\nimport type { JSDOMOptions } from '../../types/jsdom-options'\nimport { URL as NodeURL } from 'node:url'\nimport { populateGlobal } from './utils'\n\nfunction catchWindowErrors(window: DOMWindow) {\n  let userErrorListenerCount = 0\n  function throwUnhandlerError(e: ErrorEvent) {\n    if (userErrorListenerCount === 0 && e.error != null) {\n      e.preventDefault()\n      process.emit('uncaughtException', e.error)\n    }\n  }\n  const addEventListener = window.addEventListener.bind(window)\n  const removeEventListener = window.removeEventListener.bind(window)\n  window.addEventListener('error', throwUnhandlerError)\n  window.addEventListener = function (\n    ...args: [any, any, any]\n  ) {\n    if (args[0] === 'error') {\n      userErrorListenerCount++\n    }\n    return addEventListener.apply(this, args)\n  }\n  window.removeEventListener = function (\n    ...args: [any, any, any]\n  ) {\n    if (args[0] === 'error' && userErrorListenerCount) {\n      userErrorListenerCount--\n    }\n    return removeEventListener.apply(this, args)\n  }\n  return function clearErrorHandlers() {\n    window.removeEventListener('error', throwUnhandlerError)\n  }\n}\n\nlet NodeFormData_!: typeof FormData\nlet NodeBlob_!: typeof Blob\nlet NodeRequest_!: typeof Request\n\nexport default <Environment>{\n  name: 'jsdom',\n  viteEnvironment: 'client',\n  async setupVM({ jsdom = {} }) {\n    // delay initialization because it takes ~1s\n    NodeFormData_ = globalThis.FormData\n    NodeBlob_ = globalThis.Blob\n    NodeRequest_ = globalThis.Request\n\n    const { CookieJar, JSDOM, ResourceLoader, VirtualConsole } = await import(\n      'jsdom',\n    )\n    const {\n      html = '<!DOCTYPE html>',\n      userAgent,\n      url = 'http://localhost:3000',\n      contentType = 'text/html',\n      pretendToBeVisual = true,\n      includeNodeLocations = false,\n      runScripts = 'dangerously',\n      resources,\n      console = false,\n      cookieJar = false,\n      ...restOptions\n    } = jsdom as JSDOMOptions\n    let virtualConsole: IVirtualConsole | undefined\n    if (console && globalThis.console) {\n      virtualConsole = new VirtualConsole()\n      // jsdom <27\n      if ('sendTo' in virtualConsole) {\n        (virtualConsole.sendTo as any)(globalThis.console)\n      }\n      // jsdom >=27\n      else {\n        virtualConsole.forwardTo(globalThis.console)\n      }\n    }\n    let dom = new JSDOM(html, {\n      pretendToBeVisual,\n      resources:\n        resources\n        ?? (userAgent ? new ResourceLoader({ userAgent }) : undefined),\n      runScripts,\n      url,\n      virtualConsole,\n      cookieJar: cookieJar ? new CookieJar() : undefined,\n      includeNodeLocations,\n      contentType,\n      userAgent,\n      ...restOptions,\n    })\n\n    const clearAddEventListenerPatch = patchAddEventListener(dom.window)\n\n    const clearWindowErrors = catchWindowErrors(dom.window)\n\n    const utils = createCompatUtils(dom.window)\n\n    // TODO: browser doesn't expose Buffer, but a lot of dependencies use it\n    dom.window.Buffer = Buffer\n    dom.window.jsdom = dom\n    dom.window.Request = createCompatRequest(utils)\n    dom.window.URL = createJSDOMCompatURL(utils)\n\n    // inject web globals if they are missing in JSDOM but otherwise available in Nodejs\n    // https://nodejs.org/dist/latest/docs/api/globals.html\n    const globalNames = [\n      'structuredClone',\n      'BroadcastChannel',\n      'MessageChannel',\n      'MessagePort',\n      'TextEncoder',\n      'TextDecoder',\n    ] as const\n    for (const name of globalNames) {\n      const value = globalThis[name]\n      if (\n        typeof value !== 'undefined'\n        && typeof dom.window[name] === 'undefined'\n      ) {\n        dom.window[name] = value\n      }\n    }\n\n    // since we are providing Node.js's Fetch API,\n    // we also should override other APIs they use\n    const overrideGlobals = [\n      'fetch',\n      'Response',\n      'Headers',\n      'AbortController',\n      'AbortSignal',\n      'URLSearchParams',\n      // URL and Request is overriden with a compat one\n      // 'URL',\n      // 'Request',\n    ] as const\n    for (const name of overrideGlobals) {\n      const value = globalThis[name]\n      if (typeof value !== 'undefined') {\n        dom.window[name] = value as any\n      }\n    }\n\n    return {\n      getVmContext() {\n        return dom.getInternalVMContext()\n      },\n      teardown() {\n        clearAddEventListenerPatch()\n        clearWindowErrors()\n        dom.window.close()\n        dom = undefined as any\n      },\n    }\n  },\n  async setup(global, { jsdom = {} }) {\n    // delay initialization because it takes ~1s\n    NodeFormData_ = globalThis.FormData\n    NodeBlob_ = globalThis.Blob\n    NodeRequest_ = globalThis.Request\n\n    const { CookieJar, JSDOM, ResourceLoader, VirtualConsole } = await import(\n      'jsdom',\n    )\n    const {\n      html = '<!DOCTYPE html>',\n      userAgent,\n      url = 'http://localhost:3000',\n      contentType = 'text/html',\n      pretendToBeVisual = true,\n      includeNodeLocations = false,\n      runScripts = 'dangerously',\n      resources,\n      console = false,\n      cookieJar = false,\n      ...restOptions\n    } = jsdom as any\n    let virtualConsole: IVirtualConsole | undefined\n    if (console && globalThis.console) {\n      virtualConsole = new VirtualConsole()\n      // jsdom <27\n      if ('sendTo' in virtualConsole) {\n        (virtualConsole.sendTo as any)(globalThis.console)\n      }\n      // jsdom >=27\n      else {\n        virtualConsole.forwardTo(globalThis.console)\n      }\n    }\n    const dom = new JSDOM(html, {\n      pretendToBeVisual,\n      resources:\n        resources\n        ?? (userAgent ? new ResourceLoader({ userAgent }) : undefined),\n      runScripts,\n      url,\n      virtualConsole,\n      cookieJar: cookieJar ? new CookieJar() : undefined,\n      includeNodeLocations,\n      contentType,\n      userAgent,\n      ...restOptions,\n    })\n\n    const clearAddEventListenerPatch = patchAddEventListener(dom.window)\n\n    const { keys, originals } = populateGlobal(global, dom.window, {\n      bindFunctions: true,\n    })\n\n    const clearWindowErrors = catchWindowErrors(global)\n    const utils = createCompatUtils(dom.window)\n\n    global.jsdom = dom\n    global.Request = createCompatRequest(utils)\n    global.URL = createJSDOMCompatURL(utils)\n\n    return {\n      teardown(global) {\n        clearAddEventListenerPatch()\n        clearWindowErrors()\n        dom.window.close()\n        delete global.jsdom\n        keys.forEach(key => delete global[key])\n        originals.forEach((v, k) => (global[k] = v))\n      },\n    }\n  },\n}\n\nfunction createCompatRequest(utils: CompatUtils) {\n  class Request extends NodeRequest_ {\n    constructor(...args: [input: RequestInfo, init?: RequestInit]) {\n      const [input, init] = args\n      if (init?.body != null) {\n        const compatInit = { ...init }\n        if (init.body instanceof utils.window.Blob) {\n          compatInit.body = utils.makeCompatBlob(init.body as any) as any\n        }\n        if (init.body instanceof utils.window.FormData) {\n          compatInit.body = utils.makeCompatFormData(init.body)\n        }\n        super(input, compatInit)\n      }\n      else {\n        super(...args)\n      }\n    }\n\n    static [Symbol.hasInstance](instance: unknown): boolean {\n      return instance instanceof NodeRequest_\n    }\n  }\n  return Request\n}\n\nfunction createJSDOMCompatURL(utils: CompatUtils): typeof URL {\n  class URL extends NodeURL {\n    static createObjectURL(blob: any): string {\n      if (blob instanceof utils.window.Blob) {\n        const compatBlob = utils.makeCompatBlob(blob)\n        return NodeURL.createObjectURL(compatBlob as any)\n      }\n      return NodeURL.createObjectURL(blob)\n    }\n\n    static [Symbol.hasInstance](instance: unknown): boolean {\n      return instance instanceof NodeURL\n    }\n  }\n  return URL\n}\n\ninterface CompatUtils {\n  window: DOMWindow\n  makeCompatBlob: (blob: Blob) => Blob\n  makeCompatFormData: (formData: FormData) => FormData\n}\n\nfunction createCompatUtils(window: DOMWindow): CompatUtils {\n  // this returns a hidden Symbol(impl)\n  // this is cursed, and jsdom should just implement fetch API itself\n  const implSymbol = Object.getOwnPropertySymbols(\n    Object.getOwnPropertyDescriptors(new window.Blob()),\n  )[0]\n  const utils = {\n    window,\n    makeCompatFormData(formData: FormData) {\n      const nodeFormData = new NodeFormData_()\n      formData.forEach((value, key) => {\n        if (value instanceof window.Blob) {\n          nodeFormData.append(key, utils.makeCompatBlob(value as any) as any)\n        }\n        else {\n          nodeFormData.append(key, value)\n        }\n      })\n      return nodeFormData\n    },\n    makeCompatBlob(blob: Blob) {\n      const buffer = (blob as any)[implSymbol]._buffer\n      return new NodeBlob_([buffer], { type: blob.type })\n    },\n  }\n  return utils\n}\n\nfunction patchAddEventListener(window: DOMWindow) {\n  const abortControllers = new WeakMap<AbortSignal, AbortController>()\n  const JSDOMAbortSignal = window.AbortSignal\n  const JSDOMAbortController = window.AbortController\n  const originalAddEventListener = window.EventTarget.prototype.addEventListener\n\n  function getJsdomAbortController(signal: AbortSignal) {\n    if (!abortControllers.has(signal)) {\n      const jsdomAbortController = new JSDOMAbortController()\n      signal.addEventListener('abort', () => {\n        jsdomAbortController.abort(signal.reason)\n      })\n      abortControllers.set(signal, jsdomAbortController)\n    }\n    return abortControllers.get(signal)!\n  }\n\n  window.EventTarget.prototype.addEventListener = function addEventListener(\n    type: string,\n    callback: EventListenerOrEventListenerObject | null,\n    options?: AddEventListenerOptions | boolean,\n  ) {\n    if (typeof options === 'object' && options?.signal != null) {\n      const { signal, ...otherOptions } = options\n      // - this happens because AbortSignal is provided by Node.js,\n      // but jsdom APIs require jsdom's AbortSignal, while Node APIs\n      // (like fetch and Request) require a Node.js AbortSignal\n      // - disable narrow typing with \"as any\" because we need it later\n      if (!((signal as any) instanceof JSDOMAbortSignal)) {\n        const jsdomCompatOptions = Object.create(null)\n        Object.assign(jsdomCompatOptions, otherOptions)\n\n        // use jsdom-native abort controller instead and forward the\n        // previous one with `addEventListener`\n        const jsdomAbortController = getJsdomAbortController(signal)\n\n        jsdomCompatOptions.signal = jsdomAbortController.signal\n        return originalAddEventListener.call(this, type, callback, jsdomCompatOptions)\n      }\n    }\n\n    return originalAddEventListener.call(this, type, callback, options)\n  }\n\n  return () => {\n    window.EventTarget.prototype.addEventListener = originalAddEventListener\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/env/loader.ts",
    "content": "import type { BuiltinEnvironment, VitestEnvironment } from '../../node/types/config'\nimport type { Environment } from '../../types/environment'\nimport type { WorkerRPC } from '../../types/worker'\nimport type { Traces } from '../../utils/traces'\nimport { readFileSync } from 'node:fs'\nimport { isBuiltin } from 'node:module'\nimport { pathToFileURL } from 'node:url'\nimport { resolve } from 'pathe'\nimport { EvaluatedModules, ModuleRunner } from 'vite/module-runner'\nimport { VitestTransport } from '../../runtime/moduleRunner/moduleTransport'\nimport { environments } from './index'\n\nfunction isBuiltinEnvironment(\n  env: VitestEnvironment,\n): env is BuiltinEnvironment {\n  return env in environments\n}\n\nconst isWindows = process.platform === 'win32'\nconst _loaders = new Map<string, ModuleRunner>()\n\nexport function createEnvironmentLoader(root: string, rpc: WorkerRPC): ModuleRunner {\n  const cachedLoader = _loaders.get(root)\n  if (!cachedLoader || cachedLoader.isClosed()) {\n    _loaders.delete(root)\n\n    const evaluatedModules = new EvaluatedModules()\n    const moduleRunner = new ModuleRunner({\n      hmr: false,\n      sourcemapInterceptor: 'prepareStackTrace',\n      transport: new VitestTransport({\n        async fetchModule(id, importer, options) {\n          const result = await rpc.fetch(id, importer, '__vitest__', options)\n          if ('cached' in result) {\n            const code = readFileSync(result.tmp, 'utf-8')\n            return { code, ...result }\n          }\n          if (isWindows && 'externalize' in result) {\n            // TODO: vitest returns paths for external modules, but Vite returns file://\n            // https://github.com/vitejs/vite/pull/20449\n            result.externalize = isBuiltin(id) || /^(?:node:|data:|http:|https:|file:)/.test(id)\n              ? result.externalize\n              : pathToFileURL(result.externalize).toString()\n          }\n          return result\n        },\n        async resolveId(id, importer) {\n          return rpc.resolve(id, importer, '__vitest__')\n        },\n      }, evaluatedModules, new WeakMap()),\n    })\n    _loaders.set(root, moduleRunner)\n  }\n  return _loaders.get(root)!\n}\n\nexport async function loadNativeEnvironment(\n  name: string,\n  root: string,\n  traces: Traces,\n): Promise<Environment> {\n  const packageId = name[0] === '.' || name[0] === '/'\n    ? pathToFileURL(resolve(root, name)).toString()\n    : import.meta.resolve(`vitest-environment-${name}`, pathToFileURL(root).toString())\n  const pkg = await traces.$(\n    'vitest.runtime.environment.import',\n    () => import(packageId) as Promise<{ default: Environment }>,\n  )\n  return resolveEnvironmentFromModule(name, packageId, pkg)\n}\n\nfunction resolveEnvironmentFromModule(name: string, packageId: string, pkg: { default: Environment }) {\n  if (!pkg || !pkg.default || typeof pkg.default !== 'object') {\n    throw new TypeError(\n      `Environment \"${name}\" is not a valid environment. `\n      + `Path \"${packageId}\" should export default object with a \"setup\" or/and \"setupVM\" method.`,\n    )\n  }\n  const environment = pkg.default\n  if (\n    environment.transformMode != null\n    && environment.transformMode !== 'web'\n    && environment.transformMode !== 'ssr'\n  ) {\n    throw new TypeError(\n      `Environment \"${name}\" is not a valid environment. `\n      + `Path \"${packageId}\" should export default object with a \"transformMode\" method equal to \"ssr\" or \"web\", received \"${environment.transformMode}\".`,\n    )\n  }\n  if (environment.transformMode) {\n    console.warn(`The Vitest environment ${environment.name} defines the \"transformMode\". This options was deprecated in Vitest 4 and will be removed in the next major version. Please, use \"viteEnvironment\" instead.`)\n    // keep for backwards compat\n    environment.viteEnvironment ??= environment.transformMode === 'ssr'\n      ? 'ssr'\n      : 'client'\n  }\n  return environment\n}\n\nexport async function loadEnvironment(\n  name: string,\n  root: string,\n  rpc: WorkerRPC,\n  traces: Traces,\n  viteModuleRunner: boolean,\n): Promise<{ environment: Environment; loader?: ModuleRunner }> {\n  if (isBuiltinEnvironment(name)) {\n    return { environment: environments[name] }\n  }\n  if (!viteModuleRunner) {\n    return { environment: await loadNativeEnvironment(name, root, traces) }\n  }\n  const loader = createEnvironmentLoader(root, rpc)\n  const packageId\n    = name[0] === '.' || name[0] === '/'\n      ? resolve(root, name)\n      : (await traces.$(\n          'vitest.runtime.environment.resolve',\n          () => rpc.resolve(`vitest-environment-${name}`, undefined, '__vitest__'),\n        ))\n          ?.id ?? resolve(root, name)\n  const pkg = await traces.$(\n    'vitest.runtime.environment.import',\n    () => loader.import(packageId) as Promise<{ default: Environment }>,\n  )\n  const environment = resolveEnvironmentFromModule(name, packageId, pkg)\n  return {\n    environment,\n    loader,\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/env/node.ts",
    "content": "import type { Environment } from '../../types/environment'\nimport { Console } from 'node:console'\n\n// some globals we do not want, either because deprecated or we set it ourselves\nconst denyList = new Set([\n  'GLOBAL',\n  'root',\n  'global',\n  'Buffer',\n  'ArrayBuffer',\n  'Uint8Array',\n])\n\nconst nodeGlobals = new Map<string, PropertyDescriptor>()\n\nfunction populateNodeGlobals() {\n  if (nodeGlobals.size !== 0) {\n    return\n  }\n\n  const names = Object.getOwnPropertyNames(globalThis)\n  const length = names.length\n  for (let i = 0; i < length; i++) {\n    const globalName = names[i]\n    if (!denyList.has(globalName)) {\n      const descriptor = Object.getOwnPropertyDescriptor(\n        globalThis,\n        globalName,\n      )\n\n      if (!descriptor) {\n        throw new Error(\n          `No property descriptor for ${globalName}, this is a bug in Vitest.`,\n        )\n      }\n      nodeGlobals.set(globalName, descriptor)\n    }\n  }\n}\n\nexport default <Environment>{\n  name: 'node',\n  viteEnvironment: 'ssr',\n  // this is largely copied from jest's node environment\n  async setupVM() {\n    populateNodeGlobals()\n\n    const vm = await import('node:vm')\n    let context = vm.createContext()\n    let global = vm.runInContext('this', context)\n\n    const contextGlobals = new Set(Object.getOwnPropertyNames(global))\n    for (const [nodeGlobalsKey, descriptor] of nodeGlobals) {\n      if (!contextGlobals.has(nodeGlobalsKey)) {\n        if (descriptor.configurable) {\n          Object.defineProperty(global, nodeGlobalsKey, {\n            configurable: true,\n            enumerable: descriptor.enumerable,\n            get() {\n              // @ts-expect-error: no index signature\n              const val = globalThis[nodeGlobalsKey] as unknown\n\n              // override lazy getter\n              Object.defineProperty(global, nodeGlobalsKey, {\n                configurable: true,\n                enumerable: descriptor.enumerable,\n                value: val,\n                writable:\n                  descriptor.writable === true\n                  // Node 19 makes performance non-readable. This is probably not the correct solution.\n                  || nodeGlobalsKey === 'performance',\n              })\n              return val\n            },\n            set(val: unknown) {\n              // override lazy getter\n              Object.defineProperty(global, nodeGlobalsKey, {\n                configurable: true,\n                enumerable: descriptor.enumerable,\n                value: val,\n                writable: true,\n              })\n            },\n          })\n        }\n        else if ('value' in descriptor) {\n          Object.defineProperty(global, nodeGlobalsKey, {\n            configurable: false,\n            enumerable: descriptor.enumerable,\n            value: descriptor.value,\n            writable: descriptor.writable,\n          })\n        }\n        else {\n          Object.defineProperty(global, nodeGlobalsKey, {\n            configurable: false,\n            enumerable: descriptor.enumerable,\n            get: descriptor.get,\n            set: descriptor.set,\n          })\n        }\n      }\n    }\n\n    global.global = global\n    global.Buffer = Buffer\n    global.ArrayBuffer = ArrayBuffer\n    // TextEncoder (global or via 'util') references a Uint8Array constructor\n    // different than the global one used by users in tests. This makes sure the\n    // same constructor is referenced by both.\n    global.Uint8Array = Uint8Array\n\n    return {\n      getVmContext() {\n        return context\n      },\n      teardown() {\n        context = undefined as any\n        global = undefined\n      },\n    }\n  },\n  async setup(global) {\n    global.console.Console = Console\n    return {\n      teardown(global) {\n        delete global.console.Console\n      },\n    }\n  },\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/env/utils.ts",
    "content": "import { KEYS } from './jsdom-keys'\n\nconst skipKeys = ['window', 'self', 'top', 'parent']\n\nexport function getWindowKeys(\n  global: any,\n  win: any,\n  additionalKeys: string[] = [],\n): Set<string> {\n  const keysArray = [...additionalKeys, ...KEYS]\n  const keys = new Set(\n    keysArray.concat(Object.getOwnPropertyNames(win)).filter((k) => {\n      if (skipKeys.includes(k)) {\n        return false\n      }\n      if (k in global) {\n        return keysArray.includes(k)\n      }\n\n      return true\n    }),\n  )\n\n  return keys\n}\n\nfunction isClassLikeName(name: string) {\n  return name[0] === name[0].toUpperCase()\n}\n\ninterface PopulateOptions {\n  // we bind functions such as addEventListener and others\n  // because they rely on `this` in happy-dom, and in jsdom it\n  // has a priority for getting implementation from symbols\n  // (global doesn't have these symbols, but window - does)\n  bindFunctions?: boolean\n\n  additionalKeys?: string[]\n}\n\nexport function populateGlobal(\n  global: any,\n  win: any,\n  options: PopulateOptions = {},\n): {\n  keys: Set<string>\n  skipKeys: string[]\n  originals: Map<string | symbol, any>\n} {\n  const { bindFunctions = false } = options\n  const keys = getWindowKeys(global, win, options.additionalKeys)\n\n  const originals = new Map<string | symbol, any>()\n\n  const overridenKeys = new Set([...KEYS, ...options.additionalKeys || []])\n\n  const overrideObject = new Map<string | symbol, any>()\n  for (const key of keys) {\n    const boundFunction\n      = bindFunctions\n        && typeof win[key] === 'function'\n        && !isClassLikeName(key)\n        && win[key].bind(win)\n\n    if (overridenKeys.has(key) && key in global) {\n      originals.set(key, global[key])\n    }\n\n    Object.defineProperty(global, key, {\n      get() {\n        if (overrideObject.has(key)) {\n          return overrideObject.get(key)\n        }\n        if (boundFunction) {\n          return boundFunction\n        }\n        return win[key]\n      },\n      set(v) {\n        overrideObject.set(key, v)\n      },\n      configurable: true,\n    })\n  }\n\n  global.window = global\n  global.self = global\n  global.top = global\n  global.parent = global\n\n  if (global.global) {\n    global.global = global\n  }\n\n  // rewrite defaultView to reference the same global context\n  if (global.document && global.document.defaultView) {\n    Object.defineProperty(global.document, 'defaultView', {\n      get: () => global,\n      enumerable: true,\n      configurable: true,\n    })\n  }\n\n  skipKeys.forEach(k => keys.add(k))\n\n  return {\n    keys,\n    skipKeys,\n    originals,\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/globals.ts",
    "content": "import { globalApis } from '../constants'\nimport * as index from '../public/index'\n\nexport function registerApiGlobally(): void {\n  globalApis.forEach((api) => {\n    // @ts-expect-error I know what I am doing :P\n    globalThis[api] = index[api]\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/inject.ts",
    "content": "import type { ProvidedContext } from '../types/general'\nimport { getWorkerState } from '../runtime/utils'\n\n/**\n * Gives access to injected context provided from the main thread.\n * This usually returns a value provided by `globalSetup` or an external library.\n */\nexport function inject<T extends keyof ProvidedContext & string>(\n  key: T,\n): ProvidedContext[T] {\n  const workerState = getWorkerState()\n  return workerState.providedContext[key] as ProvidedContext[T]\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/mock/date.ts",
    "content": "/* Ported from https://github.com/boblauer/MockDate/blob/master/src/mockdate.ts */\n/*\nThe MIT License (MIT)\n\nCopyright (c) 2014 Bob Lauer\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\nexport const RealDate: DateConstructor = Date\n\nlet now: null | number = null\n\nclass MockDate extends RealDate {\n  constructor()\n  constructor(value: number | string)\n  constructor(\n    year: number,\n    month: number,\n    date?: number,\n    hours?: number,\n    minutes?: number,\n    seconds?: number,\n    ms?: number\n  )\n  constructor(\n    y?: number | string,\n    m?: number,\n    d?: number,\n    h?: number,\n    M?: number,\n    s?: number,\n    ms?: number,\n  ) {\n    super()\n\n    let date: any\n    switch (arguments.length) {\n      case 0:\n        if (now !== null) {\n          date = new RealDate(now.valueOf())\n        }\n        else {\n          date = new RealDate()\n        }\n        break\n      case 1:\n        date = new RealDate(y!)\n        break\n      default:\n        d = typeof d === 'undefined' ? 1 : d\n        h = h || 0\n        M = M || 0\n        s = s || 0\n        ms = ms || 0\n        date = new RealDate(y as number, m!, d, h, M, s, ms)\n        break\n    }\n\n    Object.setPrototypeOf(date, MockDate.prototype)\n\n    return date\n  }\n}\n\nMockDate.UTC = RealDate.UTC\n\nMockDate.now = function () {\n  return new MockDate().valueOf()\n}\n\nMockDate.parse = function (dateString) {\n  return RealDate.parse(dateString)\n}\n\nMockDate.toString = function () {\n  return RealDate.toString()\n}\n\nexport function mockDate(date: string | number | Date): void {\n  const dateObj = new RealDate(date.valueOf())\n  if (Number.isNaN(dateObj.getTime())) {\n    throw new TypeError(`mockdate: The time set is an invalid date: ${date}`)\n  }\n\n  // @ts-expect-error global\n  globalThis.Date = MockDate\n\n  now = dateObj.valueOf()\n}\n\nexport function resetDate(): void {\n  globalThis.Date = RealDate\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/mock/timers.ts",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of https://github.com/facebook/jest.\n */\n\nimport type {\n  FakeTimerInstallOpts,\n  FakeTimerWithContext,\n  InstalledClock,\n} from '@sinonjs/fake-timers'\nimport { withGlobal } from '@sinonjs/fake-timers'\nimport { isChildProcess } from '../../runtime/utils'\nimport { mockDate, RealDate, resetDate } from './date'\n\nexport class FakeTimers {\n  private _global: typeof globalThis\n  private _clock!: InstalledClock\n  // | _fakingTime | _fakingDate |\n  // +-------------+-------------+\n  // | false       | falsy       | initial\n  // | false       | truthy      | vi.setSystemTime called first (for mocking only Date without fake timers)\n  // | true        | falsy       | vi.useFakeTimers called first\n  // | true        | truthy      | unreachable\n  private _fakingTime: boolean\n  private _fakingDate: Date | null\n  private _fakeTimers: FakeTimerWithContext\n  private _userConfig?: FakeTimerInstallOpts\n  private _now = RealDate.now\n\n  constructor({\n    global,\n    config,\n  }: {\n    global: typeof globalThis\n    config: FakeTimerInstallOpts\n  }) {\n    this._userConfig = config\n\n    this._fakingDate = null\n\n    this._fakingTime = false\n    this._fakeTimers = withGlobal(global)\n    this._global = global\n  }\n\n  clearAllTimers(): void {\n    if (this._fakingTime) {\n      this._clock.reset()\n    }\n  }\n\n  dispose(): void {\n    this.useRealTimers()\n  }\n\n  runAllTimers(): void {\n    if (this._checkFakeTimers()) {\n      this._clock.runAll()\n    }\n  }\n\n  async runAllTimersAsync(): Promise<void> {\n    if (this._checkFakeTimers()) {\n      await this._clock.runAllAsync()\n    }\n  }\n\n  runOnlyPendingTimers(): void {\n    if (this._checkFakeTimers()) {\n      this._clock.runToLast()\n    }\n  }\n\n  async runOnlyPendingTimersAsync(): Promise<void> {\n    if (this._checkFakeTimers()) {\n      await this._clock.runToLastAsync()\n    }\n  }\n\n  advanceTimersToNextTimer(steps = 1): void {\n    if (this._checkFakeTimers()) {\n      for (let i = steps; i > 0; i--) {\n        this._clock.next()\n        // Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250\n        this._clock.tick(0)\n\n        if (this._clock.countTimers() === 0) {\n          break\n        }\n      }\n    }\n  }\n\n  async advanceTimersToNextTimerAsync(steps = 1): Promise<void> {\n    if (this._checkFakeTimers()) {\n      for (let i = steps; i > 0; i--) {\n        await this._clock.nextAsync()\n        // Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250\n        this._clock.tick(0)\n\n        if (this._clock.countTimers() === 0) {\n          break\n        }\n      }\n    }\n  }\n\n  advanceTimersByTime(msToRun: number): void {\n    if (this._checkFakeTimers()) {\n      this._clock.tick(msToRun)\n    }\n  }\n\n  async advanceTimersByTimeAsync(msToRun: number): Promise<void> {\n    if (this._checkFakeTimers()) {\n      await this._clock.tickAsync(msToRun)\n    }\n  }\n\n  advanceTimersToNextFrame(): void {\n    if (this._checkFakeTimers()) {\n      this._clock.runToFrame()\n    }\n  }\n\n  runAllTicks(): void {\n    if (this._checkFakeTimers()) {\n      this._clock.runMicrotasks()\n    }\n  }\n\n  useRealTimers(): void {\n    if (this._fakingDate) {\n      resetDate()\n      this._fakingDate = null\n    }\n\n    if (this._fakingTime) {\n      this._clock.uninstall()\n      this._fakingTime = false\n    }\n  }\n\n  useFakeTimers(): void {\n    const fakeDate = this._fakingDate || Date.now()\n    if (this._fakingDate) {\n      resetDate()\n      this._fakingDate = null\n    }\n\n    if (this._fakingTime) {\n      this._clock.uninstall()\n    }\n\n    const toFake = Object.keys(this._fakeTimers.timers)\n    // Do not mock timers internally used by node by default. It can still be mocked through userConfig.\n      .filter(\n        timer => timer !== 'nextTick' && timer !== 'queueMicrotask',\n      ) as (keyof FakeTimerWithContext['timers'])[]\n\n    if (this._userConfig?.toFake?.includes('nextTick') && isChildProcess()) {\n      throw new Error(\n        'process.nextTick cannot be mocked inside child_process',\n      )\n    }\n\n    this._clock = this._fakeTimers.install({\n      now: fakeDate,\n      ...this._userConfig,\n      toFake: this._userConfig?.toFake || toFake,\n      ignoreMissingTimers: true,\n    })\n\n    this._fakingTime = true\n  }\n\n  reset(): void {\n    if (this._checkFakeTimers()) {\n      const { now } = this._clock\n      this._clock.reset()\n      this._clock.setSystemTime(now)\n    }\n  }\n\n  setSystemTime(now?: string | number | Date): void {\n    const date = (typeof now === 'undefined' || now instanceof Date) ? now : new Date(now)\n    if (this._fakingTime) {\n      this._clock.setSystemTime(date)\n    }\n    else {\n      this._fakingDate = date ?? new Date(this.getRealSystemTime())\n      mockDate(this._fakingDate)\n    }\n  }\n\n  getMockedSystemTime(): Date | null {\n    return this._fakingTime ? new Date(this._clock.now) : this._fakingDate\n  }\n\n  getRealSystemTime(): number {\n    return this._now()\n  }\n\n  getTimerCount(): number {\n    if (this._checkFakeTimers()) {\n      return this._clock.countTimers()\n    }\n\n    return 0\n  }\n\n  setTimerTickMode(mode: 'manual' | 'nextTimerAsync' | 'interval', interval?: number): void {\n    if (this._checkFakeTimers()) {\n      if (mode === 'manual') {\n        this._clock.setTickMode({ mode: 'manual' })\n      }\n      else if (mode === 'nextTimerAsync') {\n        this._clock.setTickMode({ mode: 'nextAsync' })\n      }\n      else if (mode === 'interval') {\n        this._clock.setTickMode({ mode: 'interval', delta: interval })\n      }\n      else {\n        throw new Error(`Invalid tick mode: ${mode}`)\n      }\n    }\n  }\n\n  configure(config: FakeTimerInstallOpts): void {\n    this._userConfig = config\n  }\n\n  isFakeTimers(): boolean {\n    return this._fakingTime\n  }\n\n  private _checkFakeTimers() {\n    if (!this._fakingTime) {\n      throw new Error(\n        'A function to advance timers was called but the timers APIs are not mocked. '\n        + 'Call `vi.useFakeTimers()` in the test file first.',\n      )\n    }\n\n    return this._fakingTime\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/snapshot/chai.ts",
    "content": "import type { Assertion, ChaiPlugin } from '@vitest/expect'\nimport type { Test } from '@vitest/runner'\nimport { createAssertionMessage, equals, iterableEquality, recordAsyncExpect, subsetEquality, wrapAssertion } from '@vitest/expect'\nimport { getNames } from '@vitest/runner/utils'\nimport {\n  addSerializer,\n  SnapshotClient,\n  stripSnapshotIndentation,\n} from '@vitest/snapshot'\n\nlet _client: SnapshotClient\n\nexport function getSnapshotClient(): SnapshotClient {\n  if (!_client) {\n    _client = new SnapshotClient({\n      isEqual: (received, expected) => {\n        return equals(received, expected, [iterableEquality, subsetEquality])\n      },\n    })\n  }\n  return _client\n}\n\nfunction getError(expected: () => void | Error, promise: string | undefined) {\n  if (typeof expected !== 'function') {\n    if (!promise) {\n      throw new Error(\n        `expected must be a function, received ${typeof expected}`,\n      )\n    }\n\n    // when \"promised\", it receives thrown error\n    return expected\n  }\n\n  try {\n    expected()\n  }\n  catch (e) {\n    return e\n  }\n\n  throw new Error('snapshot function didn\\'t throw')\n}\n\nfunction getTestNames(test: Test) {\n  return {\n    filepath: test.file.filepath,\n    name: getNames(test).slice(1).join(' > '),\n    testId: test.id,\n  }\n}\n\nexport const SnapshotPlugin: ChaiPlugin = (chai, utils) => {\n  function getTest(assertionName: string, obj: object) {\n    const test = utils.flag(obj, 'vitest-test')\n    if (!test) {\n      throw new Error(`'${assertionName}' cannot be used without test context`)\n    }\n    return test as Test\n  }\n\n  for (const key of ['matchSnapshot', 'toMatchSnapshot']) {\n    utils.addMethod(\n      chai.Assertion.prototype,\n      key,\n      wrapAssertion(utils, key, function (\n        this,\n        properties?: object,\n        message?: string,\n      ) {\n        utils.flag(this, '_name', key)\n        const isNot = utils.flag(this, 'negate')\n        if (isNot) {\n          throw new Error(`${key} cannot be used with \"not\"`)\n        }\n        const expected = utils.flag(this, 'object')\n        const test = getTest(key, this)\n        if (typeof properties === 'string' && typeof message === 'undefined') {\n          message = properties\n          properties = undefined\n        }\n        const errorMessage = utils.flag(this, 'message')\n        getSnapshotClient().assert({\n          received: expected,\n          message,\n          isInline: false,\n          properties,\n          errorMessage,\n          ...getTestNames(test),\n        })\n      }),\n    )\n  }\n\n  utils.addMethod(\n    chai.Assertion.prototype,\n    'toMatchFileSnapshot',\n    function (this: Assertion, file: string, message?: string) {\n      utils.flag(this, '_name', 'toMatchFileSnapshot')\n      const isNot = utils.flag(this, 'negate')\n      if (isNot) {\n        throw new Error('toMatchFileSnapshot cannot be used with \"not\"')\n      }\n      const error = new Error('resolves')\n      const expected = utils.flag(this, 'object')\n      const test = getTest('toMatchFileSnapshot', this)\n      const errorMessage = utils.flag(this, 'message')\n\n      const promise = getSnapshotClient().assertRaw({\n        received: expected,\n        message,\n        isInline: false,\n        rawSnapshot: {\n          file,\n        },\n        errorMessage,\n        ...getTestNames(test),\n      })\n\n      return recordAsyncExpect(\n        test,\n        promise,\n        createAssertionMessage(utils, this, true),\n        error,\n        utils.flag(this, 'soft'),\n      )\n    },\n  )\n\n  utils.addMethod(\n    chai.Assertion.prototype,\n    'toMatchInlineSnapshot',\n    wrapAssertion(utils, 'toMatchInlineSnapshot', function __INLINE_SNAPSHOT_OFFSET_3__(\n      this,\n      properties?: object,\n      inlineSnapshot?: string,\n      message?: string,\n    ) {\n      utils.flag(this, '_name', 'toMatchInlineSnapshot')\n      const isNot = utils.flag(this, 'negate')\n      if (isNot) {\n        throw new Error('toMatchInlineSnapshot cannot be used with \"not\"')\n      }\n      const test = getTest('toMatchInlineSnapshot', this)\n      const expected = utils.flag(this, 'object')\n      const error = utils.flag(this, 'error')\n      if (typeof properties === 'string') {\n        message = inlineSnapshot\n        inlineSnapshot = properties\n        properties = undefined\n      }\n      if (inlineSnapshot) {\n        inlineSnapshot = stripSnapshotIndentation(inlineSnapshot)\n      }\n      const errorMessage = utils.flag(this, 'message')\n\n      getSnapshotClient().assert({\n        received: expected,\n        message,\n        isInline: true,\n        properties,\n        inlineSnapshot,\n        error,\n        errorMessage,\n        ...getTestNames(test),\n      })\n    }),\n  )\n  utils.addMethod(\n    chai.Assertion.prototype,\n    'toThrowErrorMatchingSnapshot',\n    wrapAssertion(utils, 'toThrowErrorMatchingSnapshot', function (this, properties?: object, message?: string) {\n      utils.flag(this, '_name', 'toThrowErrorMatchingSnapshot')\n      const isNot = utils.flag(this, 'negate')\n      if (isNot) {\n        throw new Error(\n          'toThrowErrorMatchingSnapshot cannot be used with \"not\"',\n        )\n      }\n      const expected = utils.flag(this, 'object')\n      const test = getTest('toThrowErrorMatchingSnapshot', this)\n      const promise = utils.flag(this, 'promise') as string | undefined\n      const errorMessage = utils.flag(this, 'message')\n      getSnapshotClient().assert({\n        received: getError(expected, promise),\n        message,\n        errorMessage,\n        ...getTestNames(test),\n      })\n    }),\n  )\n  utils.addMethod(\n    chai.Assertion.prototype,\n    'toThrowErrorMatchingInlineSnapshot',\n    wrapAssertion(utils, 'toThrowErrorMatchingInlineSnapshot', function __INLINE_SNAPSHOT_OFFSET_3__(\n      this,\n      inlineSnapshot: string,\n      message: string,\n    ) {\n      const isNot = utils.flag(this, 'negate')\n      if (isNot) {\n        throw new Error(\n          'toThrowErrorMatchingInlineSnapshot cannot be used with \"not\"',\n        )\n      }\n      const test = getTest('toThrowErrorMatchingInlineSnapshot', this)\n      const expected = utils.flag(this, 'object')\n      const error = utils.flag(this, 'error')\n      const promise = utils.flag(this, 'promise') as string | undefined\n      const errorMessage = utils.flag(this, 'message')\n\n      if (inlineSnapshot) {\n        inlineSnapshot = stripSnapshotIndentation(inlineSnapshot)\n      }\n\n      getSnapshotClient().assert({\n        received: getError(expected, promise),\n        message,\n        inlineSnapshot,\n        isInline: true,\n        error,\n        errorMessage,\n        ...getTestNames(test),\n      })\n    }),\n  )\n  utils.addMethod(chai.expect, 'addSnapshotSerializer', addSerializer)\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/snapshot/environments/node.ts",
    "content": "import { NodeSnapshotEnvironment } from '@vitest/snapshot/environment'\nimport { getWorkerState } from '../../../runtime/utils'\n\nexport class VitestNodeSnapshotEnvironment extends NodeSnapshotEnvironment {\n  getHeader(): string {\n    return `// Vitest Snapshot v${this.getVersion()}, https://vitest.dev/guide/snapshot.html`\n  }\n\n  resolvePath(filepath: string): Promise<string> {\n    const rpc = getWorkerState().rpc\n    return rpc.resolveSnapshotPath(filepath)\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/snapshot/environments/resolveSnapshotEnvironment.ts",
    "content": "import type { SnapshotEnvironment } from '@vitest/snapshot/environment'\nimport type { SerializedConfig } from '../../../runtime/config'\nimport type { TestModuleRunner } from '../../../runtime/moduleRunner/testModuleRunner'\n\nexport async function resolveSnapshotEnvironment(\n  config: SerializedConfig,\n  moduleRunner: TestModuleRunner,\n): Promise<SnapshotEnvironment> {\n  if (!config.snapshotEnvironment) {\n    const { VitestNodeSnapshotEnvironment } = await import('./node')\n    return new VitestNodeSnapshotEnvironment()\n  }\n\n  const mod = await moduleRunner.import(config.snapshotEnvironment)\n  if (typeof mod.default !== 'object' || !mod.default) {\n    throw new Error(\n      'Snapshot environment module must have a default export object with a shape of `SnapshotEnvironment`',\n    )\n  }\n  return mod.default\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/spy.ts",
    "content": "export * from '@vitest/spy'\n"
  },
  {
    "path": "packages/vitest/src/integrations/vi.ts",
    "content": "import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers'\nimport type {\n  MaybeMocked,\n  MaybeMockedDeep,\n  MaybePartiallyMocked,\n  MaybePartiallyMockedDeep,\n  MockInstance,\n} from '@vitest/spy'\nimport type { RuntimeOptions, SerializedConfig } from '../runtime/config'\nimport type { VitestMocker } from '../runtime/moduleRunner/moduleMocker'\nimport type { MockFactoryWithHelper, MockOptions } from '../types/mocker'\nimport { clearAllMocks, fn, isMockFunction, resetAllMocks, restoreAllMocks, spyOn } from '@vitest/spy'\nimport { assertTypes, createSimpleStackTrace } from '@vitest/utils/helpers'\nimport { getWorkerState, isChildProcess, resetModules, waitForImportsToResolve } from '../runtime/utils'\nimport { parseSingleStack } from '../utils/source-map'\nimport { FakeTimers } from './mock/timers'\nimport { waitFor, waitUntil } from './wait'\n\ntype ESModuleExports = Record<string, unknown>\n\nexport interface VitestUtils {\n  /**\n   * Checks if fake timers are enabled.\n   */\n  isFakeTimers: () => boolean\n  /**\n   * This method wraps all further calls to timers until [`vi.useRealTimers()`](https://vitest.dev/api/vi#vi-userealtimers) is called.\n   */\n  useFakeTimers: (config?: FakeTimerInstallOpts) => VitestUtils\n  /**\n   * Restores mocked timers to their original implementations. All timers that were scheduled before will be discarded.\n   */\n  useRealTimers: () => VitestUtils\n  /**\n   * This method will call every timer that was initiated after [`vi.useFakeTimers`](https://vitest.dev/api/vi#vi-usefaketimers) call.\n   * It will not fire any timer that was initiated during its call.\n   */\n  runOnlyPendingTimers: () => VitestUtils\n  /**\n   * This method will asynchronously call every timer that was initiated after [`vi.useFakeTimers`](https://vitest.dev/api/vi#vi-usefaketimers) call, even asynchronous ones.\n   * It will not fire any timer that was initiated during its call.\n   */\n  runOnlyPendingTimersAsync: () => Promise<VitestUtils>\n  /**\n   * This method will invoke every initiated timer until the timer queue is empty. It means that every timer called during `runAllTimers` will be fired.\n   * If you have an infinite interval, it will throw after 10,000 tries (can be configured with [`fakeTimers.loopLimit`](https://vitest.dev/config/faketimers#faketimers-looplimit)).\n   */\n  runAllTimers: () => VitestUtils\n  /**\n   * This method will asynchronously invoke every initiated timer until the timer queue is empty. It means that every timer called during `runAllTimersAsync` will be fired even asynchronous timers.\n   * If you have an infinite interval, it will throw after 10 000 tries (can be configured with [`fakeTimers.loopLimit`](https://vitest.dev/config/faketimers#faketimers-looplimit)).\n   */\n  runAllTimersAsync: () => Promise<VitestUtils>\n  /**\n   * Calls every microtask that was queued by `process.nextTick`. This will also run all microtasks scheduled by themselves.\n   */\n  runAllTicks: () => VitestUtils\n  /**\n   * This method will invoke every initiated timer until the specified number of milliseconds is passed or the queue is empty - whatever comes first.\n   */\n  advanceTimersByTime: (ms: number) => VitestUtils\n  /**\n   * This method will invoke every initiated timer until the specified number of milliseconds is passed or the queue is empty - whatever comes first. This will include and await asynchronously set timers.\n   */\n  advanceTimersByTimeAsync: (ms: number) => Promise<VitestUtils>\n  /**\n   * Will call next available timer. Useful to make assertions between each timer call. You can chain call it to manage timers by yourself.\n   */\n  advanceTimersToNextTimer: () => VitestUtils\n  /**\n   * Will call next available timer and wait until it's resolved if it was set asynchronously. Useful to make assertions between each timer call.\n   */\n  advanceTimersToNextTimerAsync: () => Promise<VitestUtils>\n  /**\n   * Similar to [`vi.advanceTimersByTime`](https://vitest.dev/api/vi#vi-advancetimersbytime), but will advance timers by the milliseconds needed to execute callbacks currently scheduled with `requestAnimationFrame`.\n   */\n  advanceTimersToNextFrame: () => VitestUtils\n  /**\n   * Get the number of waiting timers.\n   */\n  getTimerCount: () => number\n  /**\n   * If fake timers are enabled, this method simulates a user changing the system clock (will affect date related API like `hrtime`, `performance.now` or `new Date()`) - however, it will not fire any timers.\n   * If fake timers are not enabled, this method will only mock `Date.*` and `new Date()` calls.\n   */\n  setSystemTime: (time: number | string | Date) => VitestUtils\n  /**\n   * Returns mocked current date. If date is not mocked the method will return `null`.\n   */\n  getMockedSystemTime: () => Date | null\n  /**\n   * When using `vi.useFakeTimers`, `Date.now` calls are mocked. If you need to get real time in milliseconds, you can call this function.\n   */\n  getRealSystemTime: () => number\n  /**\n   * Removes all timers that are scheduled to run. These timers will never run in the future.\n   */\n  clearAllTimers: () => VitestUtils\n\n  /**\n   * Controls how fake timers are advanced.\n   * @param mode The mode to use for advancing timers.\n   * - `manual`: The default behavior. Timers will only advance when you call one of `vi.advanceTimers...()` methods.\n   * - `nextTimerAsync`: Timers will be advanced automatically to the next available timer after each macrotask.\n   * - `interval`: Timers are advanced automatically by a specified interval.\n   * @param interval The interval in milliseconds to use when `mode` is `'interval'`.\n   */\n  setTimerTickMode: ((mode: 'manual' | 'nextTimerAsync') => VitestUtils) & ((mode: 'interval', interval?: number) => VitestUtils)\n\n  /**\n   * Creates a spy on a method or getter/setter of an object similar to [`vi.fn()`](https://vitest.dev/api/vi#vi-fn). It returns a [mock function](https://vitest.dev/api/mock).\n   * @example\n   * ```ts\n   * const cart = {\n   *   getApples: () => 42\n   * }\n   *\n   * const spy = vi.spyOn(cart, 'getApples').mockReturnValue(10)\n   *\n   * expect(cart.getApples()).toBe(10)\n   * expect(spy).toHaveBeenCalled()\n   * expect(spy).toHaveReturnedWith(10)\n   * ```\n   */\n  spyOn: typeof spyOn\n\n  /**\n   * Creates a spy on a function, though can be initiated without one. Every time a function is invoked, it stores its call arguments, returns, and instances. Also, you can manipulate its behavior with [methods](https://vitest.dev/api/mock).\n   *\n   * If no function is given, mock will return `undefined`, when invoked.\n   * @example\n   * ```ts\n   * const getApples = vi.fn(() => 0)\n   *\n   * getApples()\n   *\n   * expect(getApples).toHaveBeenCalled()\n   * expect(getApples).toHaveReturnedWith(0)\n   *\n   * getApples.mockReturnValueOnce(5)\n   *\n   * expect(getApples()).toBe(5)\n   * expect(getApples).toHaveNthReturnedWith(2, 5)\n   * ```\n   */\n  fn: typeof fn\n\n  /**\n   * Wait for the callback to execute successfully. If the callback throws an error or returns a rejected promise it will continue to wait until it succeeds or times out.\n   *\n   * This is very useful when you need to wait for some asynchronous action to complete, for example, when you start a server and need to wait for it to start.\n   * @example\n   * ```ts\n   * const server = createServer()\n   *\n   * await vi.waitFor(\n   *   () => {\n   *     if (!server.isReady)\n   *       throw new Error('Server not started')\n   *\n   *     console.log('Server started')\n   *   }, {\n   *     timeout: 500, // default is 1000\n   *     interval: 20, // default is 50\n   *   }\n   * )\n   * ```\n   */\n  waitFor: typeof waitFor\n\n  /**\n   * Wraps a function to create an assertion helper. When an assertion fails inside the helper,\n   * the error stack trace will point to where the helper was called, not inside the helper itself.\n   * Works with both synchronous and asynchronous functions, and supports `expect.soft()`.\n   *\n   * @example\n   * ```ts\n   * const myEqual = vi.defineHelper((x, y) => {\n   *   expect(x).toEqual(y)\n   * })\n   *\n   * test('example', () => {\n   *   myEqual('left', 'right') // Error points to this line\n   * })\n   * ```\n   * Example output:\n   * ```\n   * FAIL  example.test.ts > example\n   * AssertionError: expected 'left' to deeply equal 'right'\n   *\n   * Expected: \"right\"\n   * Received: \"left\"\n   *\n   *  ❯ example.test.ts:6:3\n   *       4| test('example', () => {\n   *       5|   myEqual('left', 'right')\n   *        |   ^\n   *       6| })\n   * ```\n   * @param fn The assertion function to wrap\n   * @returns A wrapped function with the same signature\n   */\n  defineHelper: <F extends (...args: any) => any>(fn: F) => F\n\n  /**\n   * This is similar to [`vi.waitFor`](https://vitest.dev/api/vi#vi-waitfor), but if the callback throws any errors, execution is immediately interrupted and an error message is received.\n   *\n   * If the callback returns a falsy value, the next check will continue until a truthy value is returned. This is useful when you need to wait for something to exist before taking the next step.\n   * @example\n   * ```ts\n   * const element = await vi.waitUntil(\n   *   () => document.querySelector('.element'),\n   *   {\n   *     timeout: 500, // default is 1000\n   *     interval: 20, // default is 50\n   *   }\n   * )\n   *\n   * // do something with the element\n   * expect(element.querySelector('.element-child')).toBeTruthy()\n   * ```\n   */\n  waitUntil: typeof waitUntil\n\n  /**\n   * Run the factory before imports are evaluated. You can return a value from the factory\n   * to reuse it inside your [`vi.mock`](https://vitest.dev/api/vi#vi-mock) factory and tests.\n   *\n   * If used with [`vi.mock`](https://vitest.dev/api/vi#vi-mock), both will be hoisted in the order they are defined in.\n   */\n  hoisted: <T>(factory: () => T) => T\n\n  /**\n   * Mocks every import call to the module even if it was already statically imported.\n   *\n   * The call to `vi.mock` is hoisted to the top of the file, so you don't have access to variables declared in the global file scope\n   * unless they are defined with [`vi.hoisted`](https://vitest.dev/api/vi#vi-hoisted) before this call.\n   *\n   * Mocking algorithm is described in [documentation](https://vitest.dev/guide/mocking/modules).\n   * @param path Path to the module. Can be aliased, if your Vitest config supports it\n   * @param factory Mocked module factory. The result of this function will be an exports object\n   */\n  // eslint-disable-next-line ts/method-signature-style\n  mock(path: string, factory?: MockFactoryWithHelper | MockOptions): void\n  // eslint-disable-next-line ts/method-signature-style\n  mock<T>(module: Promise<T>, factory?: MockFactoryWithHelper<T> | MockOptions): void\n\n  /**\n   * Removes module from mocked registry. All calls to import will return the original module even if it was mocked before.\n   *\n   * This call is hoisted to the top of the file, so it will only unmock modules that were defined in `setupFiles`, for example.\n   * @param path Path to the module. Can be aliased, if your Vitest config supports it\n   */\n  // eslint-disable-next-line ts/method-signature-style\n  unmock(path: string): void\n  // eslint-disable-next-line ts/method-signature-style\n  unmock(module: Promise<unknown>): void\n\n  /**\n   * Mocks every subsequent [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) call.\n   *\n   * Unlike [`vi.mock`](https://vitest.dev/api/vi#vi-mock), this method will not mock statically imported modules because it is not hoisted to the top of the file.\n   *\n   * Mocking algorithm is described in [documentation](https://vitest.dev/guide/mocking/modules).\n   * @param path Path to the module. Can be aliased, if your Vitest config supports it\n   * @param factory Mocked module factory. The result of this function will be an exports object\n   *\n   * @returns A disposable object that calls {@link doUnmock()} when disposed\n   */\n  // eslint-disable-next-line ts/method-signature-style\n  doMock(path: string, factory?: MockFactoryWithHelper | MockOptions): Disposable\n  // eslint-disable-next-line ts/method-signature-style\n  doMock<T>(module: Promise<T>, factory?: MockFactoryWithHelper<T> | MockOptions): Disposable\n  /**\n   * Removes module from mocked registry. All subsequent calls to import will return original module.\n   *\n   * Unlike [`vi.unmock`](https://vitest.dev/api/vi#vi-unmock), this method is not hoisted to the top of the file.\n   * @param path Path to the module. Can be aliased, if your Vitest config supports it\n   */\n  // eslint-disable-next-line ts/method-signature-style\n  doUnmock(path: string): void\n  // eslint-disable-next-line ts/method-signature-style\n  doUnmock(module: Promise<unknown>): void\n\n  /**\n   * Imports module, bypassing all checks if it should be mocked.\n   * Can be useful if you want to mock module partially.\n   * @example\n   * ```ts\n   * vi.mock('./example.js', async () => {\n   *  const axios = await vi.importActual<typeof import('./example.js')>('./example.js')\n   *\n   *  return { ...axios, get: vi.fn() }\n   * })\n   * ```\n   * @param path Path to the module. Can be aliased, if your config supports it\n   */\n  importActual: <T = ESModuleExports>(path: string) => Promise<T>\n\n  /**\n   * Imports a module with all of its properties and nested properties mocked.\n   *\n   * Mocking algorithm is described in [documentation](https://vitest.dev/guide/mocking/modules).\n   * @example\n   * ```ts\n   * const example = await vi.importMock<typeof import('./example.js')>('./example.js')\n   * example.calc.mockReturnValue(10)\n   * expect(example.calc()).toBe(10)\n   * ```\n   * @param path Path to the module. Can be aliased, if your config supports it\n   * @returns Fully mocked module\n   */\n  importMock: <T = ESModuleExports>(\n    path: string,\n  ) => Promise<MaybeMockedDeep<T>>\n\n  /**\n   * Deeply mocks properties and methods of a given object\n   * in the same way as `vi.mock()` mocks module exports.\n   *\n   * @example\n   * ```ts\n   * const original = {\n   *   simple: () => 'value',\n   *   nested: {\n   *     method: () => 'real'\n   *   },\n   *   prop: 'foo',\n   * }\n   *\n   * const mocked = vi.mockObject(original)\n   * expect(mocked.simple()).toBe(undefined)\n   * expect(mocked.nested.method()).toBe(undefined)\n   * expect(mocked.prop).toBe('foo')\n   *\n   * mocked.simple.mockReturnValue('mocked')\n   * mocked.nested.method.mockReturnValue('mocked nested')\n   *\n   * expect(mocked.simple()).toBe('mocked')\n   * expect(mocked.nested.method()).toBe('mocked nested')\n   *\n   * const spied = vi.mockObject(original, { spy: true })\n   * expect(spied.simple()).toBe('value')\n   * expect(spied.simple).toHaveBeenCalled()\n   * expect(spied.simple.mock.results[0]).toEqual({ type: 'return', value: 'value' })\n   * ```\n   *\n   * @param value - The object to be mocked\n   * @returns A deeply mocked version of the input object\n   */\n  mockObject: <T>(value: T, options?: MockOptions) => MaybeMockedDeep<T>\n\n  /**\n   * Type helper for TypeScript. Just returns the object that was passed.\n   *\n   * When `partial` is `true` it will expect a `Partial<T>` as a return value. By default, this will only make TypeScript believe that\n   * the first level values are mocked. You can pass down `{ partial: true, deep: true }` to make nested objects also partial recursively.\n   * @example\n   * ```ts\n   * import example from './example.js'\n   * vi.mock('./example.js')\n   *\n   * test('1 + 1 equals 10' async () => {\n   *  vi.mocked(example.calc).mockReturnValue(10)\n   *  expect(example.calc(1, '+', 1)).toBe(10)\n   * })\n   * ```\n   * @param item Anything that can be mocked\n   * @param deep If the object is deeply mocked\n   * @param options If the object is partially or deeply mocked\n   */\n  mocked: (<T>(item: T, deep?: false) => MaybeMocked<T>)\n    & (<T>(item: T, deep: true) => MaybeMockedDeep<T>)\n    & (<T>(\n      item: T,\n      options: { partial?: false; deep?: false },\n    ) => MaybeMocked<T>)\n    & (<T>(\n      item: T,\n      options: { partial?: false; deep: true },\n    ) => MaybeMockedDeep<T>)\n    & (<T>(\n      item: T,\n      options: { partial: true; deep?: false },\n    ) => MaybePartiallyMocked<T>)\n    & (<T>(\n      item: T,\n      options: { partial: true; deep: true },\n    ) => MaybePartiallyMockedDeep<T>)\n    & (<T>(item: T) => MaybeMocked<T>)\n\n  /**\n   * Checks that a given parameter is a mock function. If you are using TypeScript, it will also narrow down its type.\n   */\n  isMockFunction: (fn: any) => fn is MockInstance\n\n  /**\n   * Calls [`.mockClear()`](https://vitest.dev/api/mock#mockclear) on every mocked function.\n   *\n   * This will only empty `.mock` state, it will not affect mock implementations.\n   *\n   * This is useful if you need to clean up mocks between different assertions within a test.\n   */\n  clearAllMocks: () => VitestUtils\n\n  /**\n   * Calls [`.mockReset()`](https://vitest.dev/api/mock#mockreset) on every mocked function.\n   *\n   * This will empty `.mock` state, reset \"once\" implementations, and reset each mock's base implementation to its original.\n   *\n   * This is useful when you want to reset all mocks to their original states.\n   */\n  resetAllMocks: () => VitestUtils\n\n  /**\n   * Calls [`.mockRestore()`](https://vitest.dev/api/mock#mockrestore) on every mocked function.\n   *\n   * This will empty `.mock` state, restore all original mock implementations, and restore original descriptors of spied-on objects.\n   *\n   * This is useful for inter-test cleanup and/or removing mocks created by [`vi.spyOn(...)`](https://vitest.dev/api/vi#vi-spyon).\n   */\n  restoreAllMocks: () => VitestUtils\n\n  /**\n   * Makes value available on global namespace.\n   * Useful, if you want to have global variables available, like `IntersectionObserver`.\n   * You can return it back to original value with `vi.unstubAllGlobals`, or by enabling `unstubGlobals` config option.\n   */\n  stubGlobal: (name: string | symbol | number, value: unknown) => VitestUtils\n\n  /**\n   * Changes the value of `import.meta.env` and `process.env`.\n   * You can return it back to original value with `vi.unstubAllEnvs`, or by enabling `unstubEnvs` config option.\n   */\n  stubEnv: <T extends string>(\n    name: T,\n    value: T extends 'PROD' | 'DEV' | 'SSR' ? boolean : string | undefined,\n  ) => VitestUtils\n\n  /**\n   * Reset the value to original value that was available before first `vi.stubGlobal` was called.\n   */\n  unstubAllGlobals: () => VitestUtils\n\n  /**\n   * Reset environmental variables to the ones that were available before first `vi.stubEnv` was called.\n   */\n  unstubAllEnvs: () => VitestUtils\n\n  /**\n   * Resets modules registry by clearing the cache of all modules. This allows modules to be reevaluated when reimported.\n   * Top-level imports cannot be re-evaluated. Might be useful to isolate modules where local state conflicts between tests.\n   *\n   * This method does not reset mocks registry. To clear mocks registry, use [`vi.unmock`](https://vitest.dev/api/vi#vi-unmock) or [`vi.doUnmock`](https://vitest.dev/api/vi#vi-dounmock).\n   */\n  resetModules: () => VitestUtils\n\n  /**\n   * Wait for all imports to load. Useful, if you have a synchronous call that starts\n   * importing a module that you cannot await otherwise.\n   * Will also wait for new imports, started during the wait.\n   */\n  dynamicImportSettled: () => Promise<void>\n\n  /**\n   * Updates runtime config. You can only change values that are used when executing tests.\n   */\n  setConfig: (config: RuntimeOptions) => void\n\n  /**\n   * If config was changed with `vi.setConfig`, this will reset it to the original state().\n   */\n  resetConfig: () => void\n}\n\nfunction createVitest(): VitestUtils {\n  let _config: null | SerializedConfig = null\n\n  const state = () => getWorkerState()\n\n  let _timers: FakeTimers\n\n  const timers = () =>\n    (_timers ||= new FakeTimers({\n      global: globalThis,\n      config: state().config.fakeTimers,\n    }))\n\n  const _stubsGlobal = new Map<\n    string | symbol | number,\n    PropertyDescriptor | undefined\n  >()\n  const _stubsEnv = new Map()\n\n  const _envBooleans = ['PROD', 'DEV', 'SSR']\n\n  const utils: VitestUtils = {\n    useFakeTimers(config?: FakeTimerInstallOpts) {\n      if (isChildProcess()) {\n        if (\n          config?.toFake?.includes('nextTick')\n          || state().config?.fakeTimers?.toFake?.includes('nextTick')\n        ) {\n          throw new Error(\n            'vi.useFakeTimers({ toFake: [\"nextTick\"] }) is not supported in node:child_process. Use --pool=threads if mocking nextTick is required.',\n          )\n        }\n      }\n\n      if (config) {\n        timers().configure({ ...state().config.fakeTimers, ...config })\n      }\n      else {\n        timers().configure(state().config.fakeTimers)\n      }\n\n      timers().useFakeTimers()\n      return utils\n    },\n\n    isFakeTimers() {\n      return timers().isFakeTimers()\n    },\n\n    useRealTimers() {\n      timers().useRealTimers()\n      return utils\n    },\n\n    runOnlyPendingTimers() {\n      timers().runOnlyPendingTimers()\n      return utils\n    },\n\n    async runOnlyPendingTimersAsync() {\n      await timers().runOnlyPendingTimersAsync()\n      return utils\n    },\n\n    runAllTimers() {\n      timers().runAllTimers()\n      return utils\n    },\n\n    async runAllTimersAsync() {\n      await timers().runAllTimersAsync()\n      return utils\n    },\n\n    runAllTicks() {\n      timers().runAllTicks()\n      return utils\n    },\n\n    advanceTimersByTime(ms: number) {\n      timers().advanceTimersByTime(ms)\n      return utils\n    },\n\n    async advanceTimersByTimeAsync(ms: number) {\n      await timers().advanceTimersByTimeAsync(ms)\n      return utils\n    },\n\n    advanceTimersToNextTimer() {\n      timers().advanceTimersToNextTimer()\n      return utils\n    },\n\n    async advanceTimersToNextTimerAsync() {\n      await timers().advanceTimersToNextTimerAsync()\n      return utils\n    },\n\n    advanceTimersToNextFrame() {\n      timers().advanceTimersToNextFrame()\n      return utils\n    },\n\n    getTimerCount() {\n      return timers().getTimerCount()\n    },\n\n    setSystemTime(time: number | string | Date) {\n      timers().setSystemTime(time)\n      return utils\n    },\n\n    getMockedSystemTime() {\n      return timers().getMockedSystemTime()\n    },\n\n    getRealSystemTime() {\n      return timers().getRealSystemTime()\n    },\n\n    clearAllTimers() {\n      timers().clearAllTimers()\n      return utils\n    },\n\n    setTimerTickMode(mode: 'manual' | 'nextTimerAsync' | 'interval', interval?: number) {\n      timers().setTimerTickMode(mode, interval)\n      return utils\n    },\n\n    // mocks\n\n    spyOn,\n    fn,\n    waitFor,\n    waitUntil,\n    defineHelper: (fn) => {\n      return function __VITEST_HELPER__(...args: any[]): any {\n        const result = fn(...args)\n        if (result && typeof result === 'object' && typeof result.then === 'function') {\n          return (async function __VITEST_HELPER__() {\n            return await result\n          })()\n        }\n        return result\n      } as any\n    },\n    hoisted<T>(factory: () => T): T {\n      assertTypes(factory, '\"vi.hoisted\" factory', ['function'])\n      return factory()\n    },\n\n    mock(path: string | Promise<unknown>, factory?: MockOptions | MockFactoryWithHelper) {\n      if (typeof path !== 'string') {\n        throw new TypeError(\n          `vi.mock() expects a string path, but received a ${typeof path}`,\n        )\n      }\n      const importer = getImporter('mock')\n      _mocker().queueMock(\n        path,\n        importer,\n        typeof factory === 'function'\n          ? () =>\n              factory(() =>\n                _mocker().importActual(\n                  path,\n                  importer,\n                  _mocker().getMockContext().callstack,\n                ),\n              )\n          : factory,\n      )\n    },\n\n    unmock(path: string | Promise<unknown>) {\n      if (typeof path !== 'string') {\n        throw new TypeError(\n          `vi.unmock() expects a string path, but received a ${typeof path}`,\n        )\n      }\n      _mocker().queueUnmock(path, getImporter('unmock'))\n    },\n\n    doMock(path: string | Promise<unknown>, factory?: MockOptions | MockFactoryWithHelper) {\n      if (typeof path !== 'string') {\n        throw new TypeError(\n          `vi.doMock() expects a string path, but received a ${typeof path}`,\n        )\n      }\n      const importer = getImporter('doMock')\n      _mocker().queueMock(\n        path,\n        importer,\n        typeof factory === 'function'\n          ? () =>\n              factory(() =>\n                _mocker().importActual(\n                  path,\n                  importer,\n                  _mocker().getMockContext().callstack,\n                ),\n              )\n          : factory,\n      )\n\n      const rv = {} as Disposable\n      if (Symbol.dispose) {\n        rv[Symbol.dispose] = () => {\n          _mocker().queueUnmock(path, importer)\n        }\n      }\n      return rv\n    },\n\n    doUnmock(path: string | Promise<unknown>) {\n      if (typeof path !== 'string') {\n        throw new TypeError(\n          `vi.doUnmock() expects a string path, but received a ${typeof path}`,\n        )\n      }\n      const importer = getImporter('doUnmock')\n      _mocker().queueUnmock(path, importer)\n    },\n\n    async importActual<T = unknown>(path: string): Promise<T> {\n      const importer = getImporter('importActual')\n      return _mocker().importActual<T>(\n        path,\n        importer,\n        _mocker().getMockContext().callstack,\n      )\n    },\n\n    async importMock<T>(path: string): Promise<MaybeMockedDeep<T>> {\n      const importer = getImporter('importMock')\n      return _mocker().importMock(path, importer)\n    },\n\n    mockObject<T>(value: T, options?: MockOptions) {\n      return _mocker().mockObject({ value }, undefined, options?.spy ? 'autospy' : 'automock').value\n    },\n\n    // this is typed in the interface so it's not necessary to type it here\n    mocked<T>(item: T, _options = {}): any {\n      return item\n    },\n\n    isMockFunction(fn: any): fn is MockInstance {\n      return isMockFunction(fn)\n    },\n\n    clearAllMocks() {\n      clearAllMocks()\n      return utils\n    },\n\n    resetAllMocks() {\n      resetAllMocks()\n      return utils\n    },\n\n    restoreAllMocks() {\n      restoreAllMocks()\n      return utils\n    },\n\n    stubGlobal(name: string | symbol | number, value: any) {\n      if (!_stubsGlobal.has(name)) {\n        _stubsGlobal.set(\n          name,\n          Object.getOwnPropertyDescriptor(globalThis, name),\n        )\n      }\n      Object.defineProperty(globalThis, name, {\n        value,\n        writable: true,\n        configurable: true,\n        enumerable: true,\n      })\n      return utils\n    },\n\n    stubEnv(name: string, value: string | boolean | undefined) {\n      const env = state().metaEnv\n      if (!_stubsEnv.has(name)) {\n        _stubsEnv.set(name, env[name])\n      }\n      if (_envBooleans.includes(name)) {\n        env[name] = value ? '1' : ''\n      }\n      else if (value === undefined) {\n        delete env[name]\n      }\n      else {\n        env[name] = String(value)\n      }\n      return utils\n    },\n\n    unstubAllGlobals() {\n      _stubsGlobal.forEach((original, name) => {\n        if (!original) {\n          Reflect.deleteProperty(globalThis, name)\n        }\n        else {\n          Object.defineProperty(globalThis, name, original)\n        }\n      })\n      _stubsGlobal.clear()\n      return utils\n    },\n\n    unstubAllEnvs() {\n      const env = state().metaEnv\n      _stubsEnv.forEach((original, name) => {\n        if (original === undefined) {\n          delete env[name]\n        }\n        else {\n          env[name] = original\n        }\n      })\n      _stubsEnv.clear()\n      return utils\n    },\n\n    resetModules() {\n      resetModules(state().evaluatedModules)\n      return utils\n    },\n\n    async dynamicImportSettled() {\n      return waitForImportsToResolve()\n    },\n\n    setConfig(config: RuntimeOptions) {\n      if (!_config) {\n        _config = { ...state().config }\n      }\n      Object.assign(state().config, config)\n    },\n\n    resetConfig() {\n      if (_config) {\n        Object.assign(state().config, _config)\n      }\n    },\n  }\n\n  return utils\n}\n\nexport const vitest: VitestUtils = createVitest()\nexport const vi: VitestUtils = vitest\n\nfunction _mocker(): VitestMocker {\n  // @ts-expect-error injected by vite-nide\n  return typeof __vitest_mocker__ !== 'undefined'\n  // @ts-expect-error injected by vite-nide\n    ? __vitest_mocker__\n    : new Proxy(\n        {} as any,\n        {\n          get(_, name) {\n            throw new Error(\n              'Vitest mocker was not initialized in this environment. '\n              + `vi.${String(name)}() is forbidden.`,\n            )\n          },\n        },\n      )\n}\n\nfunction getImporter(name: string) {\n  const stackTrace = createSimpleStackTrace({ stackTraceLimit: 5 })\n  const stackArray = stackTrace.split('\\n')\n  // if there is no message in a stack trace, use the item - 1\n  const importerStackIndex = stackArray.findLastIndex((stack) => {\n    return stack.includes(` at Object.${name}`) || stack.includes(`${name}@`) || stack.includes(` at ${name} (`)\n  })\n  const stack = parseSingleStack(stackArray[importerStackIndex + 1])\n  return stack?.file || ''\n}\n"
  },
  {
    "path": "packages/vitest/src/integrations/wait.ts",
    "content": "import { getSafeTimers } from '@vitest/utils/timers'\nimport { vi } from './vi'\n\n// The waitFor function was inspired by https://github.com/testing-library/web-testing-library/pull/2\n\nexport type WaitForCallback<T> = () => T | Promise<T>\n\nexport interface WaitForOptions {\n  /**\n   * @description Time in ms between each check callback\n   * @default 50ms\n   */\n  interval?: number\n  /**\n   * @description Time in ms after which the throw a timeout error\n   * @default 1000ms\n   */\n  timeout?: number\n}\n\nfunction copyStackTrace(target: Error, source: Error) {\n  if (source.stack !== undefined) {\n    target.stack = source.stack.replace(source.message, target.message)\n  }\n  return target\n}\n\nexport function waitFor<T>(\n  callback: WaitForCallback<T>,\n  options: number | WaitForOptions = {},\n): Promise<T> {\n  const { setTimeout, setInterval, clearTimeout, clearInterval }\n    = getSafeTimers()\n  const { interval = 50, timeout = 1000 }\n    = typeof options === 'number' ? { timeout: options } : options\n  const STACK_TRACE_ERROR = new Error('STACK_TRACE_ERROR')\n\n  return new Promise<T>((resolve, reject) => {\n    let lastError: unknown\n    let promiseStatus: 'idle' | 'pending' | 'resolved' | 'rejected' = 'idle'\n    let timeoutId: ReturnType<typeof setTimeout>\n    let intervalId: ReturnType<typeof setInterval>\n\n    const onResolve = (result: T) => {\n      if (timeoutId) {\n        clearTimeout(timeoutId)\n      }\n      if (intervalId) {\n        clearInterval(intervalId)\n      }\n\n      resolve(result)\n    }\n\n    const handleTimeout = () => {\n      if (intervalId) {\n        clearInterval(intervalId)\n      }\n      let error = lastError\n      if (!error) {\n        error = copyStackTrace(\n          new Error('Timed out in waitFor!'),\n          STACK_TRACE_ERROR,\n        )\n      }\n\n      reject(error)\n    }\n\n    const checkCallback = () => {\n      if (vi.isFakeTimers()) {\n        vi.advanceTimersByTime(interval)\n      }\n\n      if (promiseStatus === 'pending') {\n        return\n      }\n      try {\n        const result = callback()\n        if (\n          result !== null\n          && typeof result === 'object'\n          && typeof (result as any).then === 'function'\n        ) {\n          const thenable = result as PromiseLike<T>\n          promiseStatus = 'pending'\n          thenable.then(\n            (resolvedValue) => {\n              promiseStatus = 'resolved'\n              onResolve(resolvedValue)\n            },\n            (rejectedValue) => {\n              promiseStatus = 'rejected'\n              lastError = rejectedValue\n            },\n          )\n        }\n        else {\n          onResolve(result as T)\n          return true\n        }\n      }\n      catch (error) {\n        lastError = error\n      }\n    }\n\n    if (checkCallback() === true) {\n      return\n    }\n\n    timeoutId = setTimeout(handleTimeout, timeout)\n    intervalId = setInterval(checkCallback, interval)\n  })\n}\n\nexport type WaitUntilCallback<T> = () => T | Promise<T>\n\nexport interface WaitUntilOptions\n  extends Pick<WaitForOptions, 'interval' | 'timeout'> {}\n\ntype Truthy<T> = T extends false | '' | 0 | null | undefined ? never : T\n\nexport function waitUntil<T>(\n  callback: WaitUntilCallback<T>,\n  options: number | WaitUntilOptions = {},\n): Promise<Truthy<T>> {\n  const { setTimeout, setInterval, clearTimeout, clearInterval }\n    = getSafeTimers()\n  const { interval = 50, timeout = 1000 }\n    = typeof options === 'number' ? { timeout: options } : options\n  const STACK_TRACE_ERROR = new Error('STACK_TRACE_ERROR')\n\n  return new Promise<Truthy<T>>((resolve, reject) => {\n    let promiseStatus: 'idle' | 'pending' | 'resolved' | 'rejected' = 'idle'\n    let timeoutId: ReturnType<typeof setTimeout>\n    let intervalId: ReturnType<typeof setInterval>\n\n    const onReject = (error?: Error) => {\n      if (intervalId) {\n        clearInterval(intervalId)\n      }\n      if (!error) {\n        error = copyStackTrace(\n          new Error('Timed out in waitUntil!'),\n          STACK_TRACE_ERROR,\n        )\n      }\n      reject(error)\n    }\n\n    const onResolve = (result: T) => {\n      if (!result) {\n        return\n      }\n\n      if (timeoutId) {\n        clearTimeout(timeoutId)\n      }\n      if (intervalId) {\n        clearInterval(intervalId)\n      }\n\n      resolve(result as Truthy<T>)\n      return true\n    }\n\n    const checkCallback = () => {\n      if (vi.isFakeTimers()) {\n        vi.advanceTimersByTime(interval)\n      }\n\n      if (promiseStatus === 'pending') {\n        return\n      }\n      try {\n        const result = callback()\n        if (\n          result !== null\n          && typeof result === 'object'\n          && typeof (result as any).then === 'function'\n        ) {\n          const thenable = result as PromiseLike<T>\n          promiseStatus = 'pending'\n          thenable.then(\n            (resolvedValue) => {\n              promiseStatus = 'resolved'\n              onResolve(resolvedValue)\n            },\n            (rejectedValue) => {\n              promiseStatus = 'rejected'\n              onReject(rejectedValue)\n            },\n          )\n        }\n        else {\n          return onResolve(result as T)\n        }\n      }\n      catch (error) {\n        onReject(error as Error)\n      }\n    }\n\n    if (checkCallback() === true) {\n      return\n    }\n\n    timeoutId = setTimeout(onReject, timeout)\n    intervalId = setInterval(checkCallback, interval)\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/node/ast-collect.ts",
    "content": "import type { File, Suite, Task, Test } from '@vitest/runner'\nimport type { SerializedConfig } from '../runtime/config'\nimport type { TestError } from '../types/general'\nimport type { TestProject } from './project'\nimport { promises as fs } from 'node:fs'\nimport { originalPositionFor, TraceMap } from '@jridgewell/trace-mapping'\nimport {\n  calculateSuiteHash,\n  createTaskName,\n  generateHash,\n  interpretTaskModes,\n  someTasksAreOnly,\n  validateTags,\n} from '@vitest/runner/utils'\nimport { unique } from '@vitest/utils/helpers'\nimport { ancestor as walkAst } from 'acorn-walk'\nimport { relative } from 'pathe'\nimport { parseAst } from 'vite'\nimport { createIndexLocationsMap } from '../utils/base'\nimport { createDebugger } from '../utils/debugger'\nimport { detectCodeBlock } from '../utils/test-helpers'\n\ninterface ParsedFile extends File {\n  start: number\n  end: number\n}\n\ninterface ParsedTest extends Test {\n  start: number\n  end: number\n  dynamic: boolean\n}\n\ninterface ParsedSuite extends Suite {\n  start: number\n  end: number\n  dynamic: boolean\n}\n\ninterface LocalCallDefinition {\n  start: number\n  end: number\n  name: string\n  type: 'suite' | 'test'\n  mode: 'run' | 'skip' | 'only' | 'todo' | 'queued'\n  task: ParsedSuite | ParsedFile | ParsedTest\n  dynamic: boolean\n  concurrent: boolean\n  sequential: boolean\n  tags: string[]\n}\n\nconst debug = createDebugger('vitest:ast-collect-info')\nconst verbose = createDebugger('vitest:ast-collect-verbose')\n\nfunction isTestFunctionName(name: string) {\n  return name === 'it' || name === 'test' || name.startsWith('test') || name.endsWith('Test')\n}\n\nfunction isVitestFunctionName(name: string) {\n  return name === 'describe' || name === 'suite' || isTestFunctionName(name)\n}\n\nfunction astParseFile(filepath: string, code: string) {\n  const ast = parseAst(code)\n\n  if (verbose) {\n    verbose(\n      'Collecting',\n      filepath,\n      code,\n    )\n  }\n  else {\n    debug?.('Collecting', filepath)\n  }\n  const definitions: LocalCallDefinition[] = []\n  const getName = (callee: any): string | null => {\n    if (!callee) {\n      return null\n    }\n    if (callee.type === 'Identifier') {\n      return callee.name\n    }\n    if (callee.type === 'CallExpression') {\n      return getName(callee.callee)\n    }\n    if (callee.type === 'TaggedTemplateExpression') {\n      return getName(callee.tag)\n    }\n    if (callee.type === 'MemberExpression') {\n      if (\n        callee.object?.type === 'Identifier'\n        && isVitestFunctionName(callee.object.name)\n      ) {\n        return callee.object?.name\n      }\n      if (\n        // direct call as `__vite_ssr_exports_0__.test()`\n        callee.object?.name?.startsWith('__vite_ssr_')\n        // call as `__vite_ssr_exports_0__.Vitest.test`,\n        // this is a special case for using Vitest namespaces popular in Effect\n        || (callee.object?.object?.name?.startsWith('__vite_ssr_') && callee.object?.property?.name === 'Vitest')\n      ) {\n        return getName(callee.property)\n      }\n      // call as `__vite_ssr__.test.skip()` or `describe.concurrent.each()`\n      return getName(callee.object)\n    }\n    // unwrap (0, ...)\n    if (callee.type === 'SequenceExpression' && callee.expressions.length === 2) {\n      const [e0, e1] = callee.expressions\n      if (e0.type === 'Literal' && e0.value === 0) {\n        return getName(e1)\n      }\n    }\n    return null\n  }\n\n  const getProperties = (callee: any): string[] => {\n    if (!callee) {\n      return []\n    }\n    if (callee.type === 'Identifier') {\n      return []\n    }\n    if (callee.type === 'CallExpression') {\n      return getProperties(callee.callee)\n    }\n    if (callee.type === 'TaggedTemplateExpression') {\n      return getProperties(callee.tag)\n    }\n    if (callee.type === 'MemberExpression') {\n      const props = getProperties(callee.object)\n      if (callee.property?.name) {\n        props.push(callee.property.name)\n      }\n      return props\n    }\n    return []\n  }\n\n  walkAst(ast as any, {\n    CallExpression(node) {\n      const { callee } = node as any\n      const name = getName(callee)\n      if (!name) {\n        return\n      }\n      if (!isVitestFunctionName(name)) {\n        verbose?.(`Skipping ${name} (unknown call)`)\n        return\n      }\n      const properties = getProperties(callee)\n      const property = callee?.property?.name\n      // intermediate calls like .each(), .for() will be picked up in the next iteration\n      if (property && ['each', 'for', 'skipIf', 'runIf', 'extend', 'scoped', 'override'].includes(property)) {\n        return\n      }\n      // skip properties on return values of calls - e.g., test('name', fn).skip()\n      if (callee.type === 'MemberExpression' && callee.object?.type === 'CallExpression') {\n        return\n      }\n      // derive mode from the full chain (handles any order like .skip.concurrent or .concurrent.skip)\n      let mode: 'run' | 'skip' | 'only' | 'todo' = 'run'\n      for (const prop of properties) {\n        if (prop === 'skip' || prop === 'only' || prop === 'todo') {\n          mode = prop\n        }\n        else if (prop === 'skipIf' || prop === 'runIf') {\n          mode = 'skip'\n        }\n      }\n      let isConcurrent = properties.includes('concurrent')\n      let isSequential = properties.includes('sequential')\n\n      let start: number\n      const end = node.end\n      // .each or (0, __vite_ssr_exports_0__.test)()\n      if (\n        callee.type === 'CallExpression'\n        || callee.type === 'SequenceExpression'\n        || callee.type === 'TaggedTemplateExpression'\n      ) {\n        start = callee.end\n      }\n      else {\n        start = node.start\n      }\n\n      const messageNode = node.arguments?.[0]\n\n      if (messageNode == null) {\n        verbose?.(`Skipping node at ${node.start} because it doesn't have a name`)\n        return\n      }\n\n      let message: string\n      if (messageNode?.type === 'Literal' || messageNode?.type === 'TemplateLiteral') {\n        message = code.slice(messageNode.start + 1, messageNode.end - 1)\n      }\n      else {\n        message = code.slice(messageNode.start, messageNode.end)\n\n        if (message.endsWith('.name')) {\n          message = message.slice(0, -5)\n        }\n      }\n\n      if (message.startsWith('0,')) {\n        message = message.slice(2)\n      }\n\n      message = message\n        // vite 7+\n        .replace(/\\(0\\s?,\\s?__vite_ssr_import_\\d+__.(\\w+)\\)/g, '$1')\n        // vite <7\n        .replace(/__(vite_ssr_import|vi_import)_\\d+__\\./g, '')\n        // Vitest module mocker injects these\n        .replace(/__vi_import_\\d+__\\./g, '')\n\n      const parentCalleeName = typeof callee?.callee === 'object' && callee?.callee.type === 'MemberExpression' && callee?.callee.property?.name\n      let isDynamicEach = parentCalleeName === 'each' || parentCalleeName === 'for'\n      if (!isDynamicEach && callee.type === 'TaggedTemplateExpression') {\n        const property = callee.tag?.property?.name\n        isDynamicEach = property === 'each' || property === 'for'\n      }\n\n      // Extract options from the second argument if it's an options object\n      const tags: string[] = []\n      const secondArg = node.arguments?.[1]\n      if (secondArg?.type === 'ObjectExpression') {\n        for (const prop of (secondArg.properties || []) as any[]) {\n          if (prop.type !== 'Property' || prop.key?.type !== 'Identifier') {\n            continue\n          }\n          const keyName = prop.key.name\n          if (keyName === 'tags') {\n            const tagsValue = prop.value\n            if (tagsValue?.type === 'Literal' && typeof tagsValue.value === 'string') {\n              tags.push(tagsValue.value)\n            }\n            else if (tagsValue?.type === 'ArrayExpression') {\n              for (const element of tagsValue.elements || []) {\n                if (element?.type === 'Literal' && typeof element.value === 'string') {\n                  tags.push(element.value)\n                }\n              }\n            }\n          }\n          else if (prop.value?.type === 'Literal' && prop.value.value === true) {\n            if (keyName === 'skip' || keyName === 'only' || keyName === 'todo') {\n              mode = keyName\n            }\n            else if (keyName === 'concurrent') {\n              isConcurrent = true\n            }\n            else if (keyName === 'sequential') {\n              isSequential = true\n            }\n          }\n        }\n      }\n\n      debug?.('Found', name, message, `(${mode})`, tags.length ? `[${tags.join(', ')}]` : '')\n      definitions.push({\n        start,\n        end,\n        name: message,\n        type: isTestFunctionName(name) ? 'test' : 'suite',\n        mode,\n        task: null as any,\n        dynamic: isDynamicEach,\n        concurrent: isConcurrent,\n        sequential: isSequential,\n        tags,\n      } satisfies LocalCallDefinition)\n    },\n  })\n  return {\n    ast,\n    definitions,\n  }\n}\n\nexport function createFailedFileTask(project: TestProject, filepath: string, error: Error): File {\n  const testFilepath = relative(project.config.root, filepath)\n  const file: ParsedFile = {\n    filepath,\n    type: 'suite',\n    id: /* @__PURE__ */ generateHash(`${testFilepath}${project.config.name || ''}`),\n    name: testFilepath,\n    fullName: testFilepath,\n    mode: 'run',\n    tasks: [],\n    start: 0,\n    end: 0,\n    projectName: project.name,\n    meta: {},\n    pool: project.browser ? 'browser' : project.config.pool,\n    file: null!,\n    result: {\n      state: 'fail',\n      errors: serializeError(project, error),\n    },\n  }\n  file.file = file\n  return file\n}\n\nfunction serializeError(ctx: TestProject, error: any): TestError[] {\n  if ('errors' in error && 'pluginCode' in error) {\n    const errors = error.errors.map((e: any) => {\n      return {\n        name: error.name,\n        message: e.text,\n        stack: e.location\n          ? `${error.name}: ${e.text}\\n  at ${relative(ctx.config.root, e.location.file)}:${e.location.line}:${e.location.column}`\n          : '',\n      }\n    })\n    return errors\n  }\n  return [\n    {\n      name: error.name,\n      stack: error.stack,\n      message: error.message,\n    },\n  ]\n}\n\nfunction createFileTask(\n  testFilepath: string,\n  code: string,\n  requestMap: any,\n  config: SerializedConfig,\n  filepath: string,\n  fileTags: string[] | undefined,\n) {\n  const { definitions, ast } = astParseFile(testFilepath, code)\n  const file: ParsedFile = {\n    filepath,\n    type: 'suite',\n    id: /* @__PURE__ */ generateHash(`${testFilepath}${config.name || ''}`),\n    name: testFilepath,\n    fullName: testFilepath,\n    mode: 'run',\n    tasks: [],\n    start: ast.start,\n    end: ast.end,\n    projectName: config.name,\n    meta: {},\n    pool: 'browser',\n    file: null!,\n    tags: fileTags || [],\n  }\n  file.file = file\n  const indexMap = createIndexLocationsMap(code)\n  const map = requestMap && new TraceMap(requestMap)\n  let lastSuite: ParsedSuite = file as any\n  const updateLatestSuite = (index: number) => {\n    while (lastSuite.suite && lastSuite.end < index) {\n      lastSuite = lastSuite.suite as ParsedSuite\n    }\n    return lastSuite\n  }\n  definitions\n    .sort((a, b) => a.start - b.start)\n    .forEach((definition) => {\n      const latestSuite = updateLatestSuite(definition.start)\n      let mode = definition.mode\n      if (latestSuite.mode !== 'run') {\n        // inherit suite mode, if it's set\n        mode = latestSuite.mode\n      }\n      const processedLocation = indexMap.get(definition.start)\n      let location: { line: number; column: number } | undefined\n      if (map && processedLocation) {\n        const originalLocation = originalPositionFor(map, {\n          line: processedLocation.line,\n          column: processedLocation.column,\n        })\n        if (originalLocation.column != null) {\n          verbose?.(\n            `Found location for`,\n            definition.type,\n            definition.name,\n            `${processedLocation.line}:${processedLocation.column}`,\n            '->',\n            `${originalLocation.line}:${originalLocation.column}`,\n          )\n          location = {\n            line: originalLocation.line,\n            column: originalLocation.column,\n          }\n        }\n        else {\n          debug?.(\n            'Cannot find original location for',\n            definition.type,\n            definition.name,\n            `${processedLocation.column}:${processedLocation.line}`,\n          )\n        }\n      }\n      else {\n        debug?.(\n          'Cannot find original location for',\n          definition.type,\n          definition.name,\n          `${definition.start}`,\n        )\n      }\n      // Inherit tags from parent suite and merge with own tags\n      const parentTags = latestSuite.tags || []\n      const taskTags = unique([...parentTags, ...definition.tags])\n      // resolve concurrent/sequential: sequential cancels inherited concurrent\n      const concurrent = definition.sequential\n        ? undefined\n        : (definition.concurrent || latestSuite.concurrent || undefined)\n\n      if (definition.type === 'suite') {\n        const task: ParsedSuite = {\n          type: definition.type,\n          id: '',\n          suite: latestSuite,\n          file,\n          tasks: [],\n          mode,\n          each: definition.dynamic,\n          concurrent,\n          name: definition.name,\n          fullName: createTaskName([latestSuite.fullName, definition.name]),\n          fullTestName: createTaskName([latestSuite.fullTestName, definition.name]),\n          end: definition.end,\n          start: definition.start,\n          location,\n          dynamic: definition.dynamic,\n          meta: {},\n          tags: taskTags,\n        }\n        definition.task = task\n        latestSuite.tasks.push(task)\n        lastSuite = task\n        return\n      }\n      validateTags(config, taskTags)\n      const task: ParsedTest = {\n        type: definition.type,\n        id: '',\n        suite: latestSuite,\n        file,\n        each: definition.dynamic,\n        concurrent,\n        mode,\n        context: {} as any, // not used on the server\n        name: definition.name,\n        fullName: createTaskName([latestSuite.fullName, definition.name]),\n        fullTestName: createTaskName([latestSuite.fullTestName, definition.name]),\n        end: definition.end,\n        start: definition.start,\n        location,\n        dynamic: definition.dynamic,\n        meta: {},\n        timeout: 0,\n        annotations: [],\n        artifacts: [],\n        tags: taskTags,\n      }\n      definition.task = task\n      latestSuite.tasks.push(task)\n    })\n  calculateSuiteHash(file)\n  const hasOnly = someTasksAreOnly(file)\n  interpretTaskModes(\n    file,\n    config.testNamePattern,\n    undefined,\n    undefined,\n    undefined,\n    hasOnly,\n    false,\n    config.allowOnly,\n  )\n  markDynamicTests(file.tasks)\n  if (!file.tasks.length) {\n    file.result = {\n      state: 'fail',\n      errors: [\n        {\n          name: 'Error',\n          message: `No test suite found in file ${filepath}`,\n        },\n      ],\n    }\n  }\n  return file\n}\n\nexport async function astCollectTests(\n  project: TestProject,\n  filepath: string,\n): Promise<File> {\n  const request = await transformSSR(project, filepath)\n  const testFilepath = relative(project.config.root, filepath)\n  if (!request) {\n    debug?.('Cannot parse', testFilepath, '(vite didn\\'t return anything)')\n    return createFailedFileTask(\n      project,\n      filepath,\n      new Error(`Failed to parse ${testFilepath}. Vite didn't return anything.`),\n    )\n  }\n  return createFileTask(\n    testFilepath,\n    request.code,\n    request.map,\n    project.serializedConfig,\n    filepath,\n    request.fileTags,\n  )\n}\n\nasync function transformSSR(project: TestProject, filepath: string) {\n  // Read original file content to extract pragmas (environment, tags)\n  const originalCode = await fs.readFile(filepath, 'utf-8').catch(() => '')\n  const { env: pragmaEnv, tags: fileTags } = detectCodeBlock(originalCode)\n\n  // Use environment from pragma if defined, otherwise fall back to config\n  const environment = pragmaEnv || project.config.environment\n  const env = environment === 'jsdom' || environment === 'happy-dom'\n    ? project.vite.environments.client\n    : project.vite.environments.ssr\n\n  const transformResult = await env.transformRequest(filepath)\n\n  return transformResult ? { ...transformResult, fileTags } : null\n}\n\nfunction markDynamicTests(tasks: Task[]) {\n  for (const task of tasks) {\n    if (task.dynamic) {\n      task.id += '-dynamic'\n    }\n    if ('tasks' in task) {\n      markDynamicTests(task.tasks)\n    }\n  }\n}\n\nfunction escapeRegex(str: string) {\n  return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nconst kReplacers = new Map<string, string>([\n  ['%i', '\\\\d+?'],\n  ['%#', '\\\\d+?'],\n  ['%d', '[\\\\d.eE+-]+?'],\n  ['%f', '[\\\\d.eE+-]+?'],\n  ['%s', '.+?'],\n  ['%j', '.+?'],\n  ['%o', '.+?'],\n  ['%%', '%'],\n])\n\nexport function escapeTestName(label: string, dynamic: boolean): string {\n  if (!dynamic) {\n    return escapeRegex(label)\n  }\n\n  // Replace object access patterns ($value, $obj.a) with %s first\n  let pattern = label.replace(/\\$[a-z_.]+/gi, '%s')\n  pattern = escapeRegex(pattern)\n  // Replace percent placeholders with their respective regex\n  pattern = pattern.replace(/%[i#dfsjo%]/g, m => kReplacers.get(m) || m)\n  return pattern\n}\n"
  },
  {
    "path": "packages/vitest/src/node/browser/sessions.ts",
    "content": "import type { TestProject } from '../project'\nimport type { BrowserServerStateSession } from '../types/browser'\nimport { createDefer } from '@vitest/utils/helpers'\n\nexport class BrowserSessions {\n  private sessions = new Map<string, BrowserServerStateSession>()\n\n  public sessionIds: Set<string> = new Set()\n\n  getSession(sessionId: string): BrowserServerStateSession | undefined {\n    return this.sessions.get(sessionId)\n  }\n\n  destroySession(sessionId: string): void {\n    this.sessions.delete(sessionId)\n  }\n\n  createSession(sessionId: string, project: TestProject, pool: { reject: (error: Error) => void }): Promise<void> {\n    // this promise only waits for the WS connection with the orhcestrator to be established\n    const defer = createDefer<void>()\n\n    const timeout = setTimeout(() => {\n      defer.reject(new Error(`Failed to connect to the browser session \"${sessionId}\" [${project.name}] within the timeout.`))\n    }, project.vitest.config.browser.connectTimeout ?? 60_000).unref()\n\n    this.sessions.set(sessionId, {\n      project,\n      connected: () => {\n        defer.resolve()\n        clearTimeout(timeout)\n      },\n      // this fails the whole test run and cancels the pool\n      fail: (error: Error) => {\n        defer.resolve()\n        clearTimeout(timeout)\n        pool.reject(error)\n      },\n    })\n    return defer\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cache/files.ts",
    "content": "import type { Stats } from 'node:fs'\nimport type { TestSpecification } from '../test-specification'\nimport fs from 'node:fs'\nimport { relative } from 'pathe'\n\ntype FileStatsCache = Pick<Stats, 'size'>\n\nexport class FilesStatsCache {\n  public cache: Map<string, FileStatsCache> = new Map()\n\n  public getStats(key: string): FileStatsCache | undefined {\n    return this.cache.get(key)\n  }\n\n  public async populateStats(root: string, specs: TestSpecification[]): Promise<void> {\n    const promises = specs.map((spec) => {\n      const key = `${spec.project.name}:${relative(root, spec.moduleId)}`\n      return this.updateStats(spec.moduleId, key)\n    })\n    await Promise.all(promises)\n  }\n\n  public async updateStats(fsPath: string, key: string): Promise<void> {\n    if (!fs.existsSync(fsPath)) {\n      return\n    }\n    const stats = await fs.promises.stat(fsPath)\n    this.cache.set(key, { size: stats.size })\n  }\n\n  public removeStats(fsPath: string): void {\n    this.cache.forEach((_, key) => {\n      if (key.endsWith(fsPath)) {\n        this.cache.delete(key)\n      }\n    })\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cache/fsModuleCache.ts",
    "content": "import type { DevEnvironment, FetchResult } from 'vite'\nimport type { Vitest } from '../core'\nimport type { ResolvedConfig } from '../types/config'\nimport fs, { existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { readFile, rename, rm, stat, unlink, writeFile } from 'node:fs/promises'\nimport { parse, stringify } from 'flatted'\nimport { dirname, join } from 'pathe'\nimport c from 'tinyrainbow'\nimport { searchForWorkspaceRoot } from 'vite'\nimport { createDebugger } from '../../utils/debugger'\nimport { hash } from '../hash'\n\nconst debugFs = createDebugger('vitest:cache:fs')\nconst debugMemory = createDebugger('vitest:cache:memory')\n\nconst cacheComment = '\\n//# vitestCache='\nconst cacheCommentLength = cacheComment.length\n\nconst METADATA_FILE = '_metadata.json'\n\nconst parallelFsCacheRead = new Map<string, Promise<{ code: string; meta: CachedInlineModuleMeta } | undefined>>()\n\n/**\n * @experimental\n */\nexport class FileSystemModuleCache {\n  /**\n   * Even though it's possible to override the folder of project's caches\n   * We still keep a single metadata file for all projects because\n   * - they can reference files between each other\n   * - lockfile changes are reflected for the whole workspace, not just for a single project\n   */\n  private rootCache: string\n  private metadataFilePath: string\n\n  private version = '1.0.0-beta.4'\n  private fsCacheRoots = new WeakMap<ResolvedConfig, string>()\n  private fsEnvironmentHashMap = new WeakMap<DevEnvironment, string>()\n  private fsCacheKeyGenerators = new Set<CacheKeyIdGenerator>()\n  // this exists only to avoid the perf. cost of reading a file and generating a hash again\n  // surprisingly, on some machines this has negligible effect\n  private fsCacheKeys = new WeakMap<\n    DevEnvironment,\n    // Map<id, tmp | null>\n    Map<string, string | null>\n  >()\n\n  constructor(private vitest: Vitest) {\n    const workspaceRoot = searchForWorkspaceRoot(vitest.vite.config.root)\n    this.rootCache = vitest.config.experimental.fsModuleCachePath\n      || join(workspaceRoot, 'node_modules', '.experimental-vitest-cache')\n    this.metadataFilePath = join(this.rootCache, METADATA_FILE)\n  }\n\n  public defineCacheKeyGenerator(callback: CacheKeyIdGenerator): void {\n    this.fsCacheKeyGenerators.add(callback)\n  }\n\n  async clearCache(log = true): Promise<void> {\n    const fsCachePaths = this.vitest.projects.map((r) => {\n      return r.config.experimental.fsModuleCachePath || this.rootCache\n    })\n    const uniquePaths = Array.from(new Set(fsCachePaths))\n    await Promise.all(\n      uniquePaths.map(directory => rm(directory, { force: true, recursive: true })),\n    )\n    if (log) {\n      this.vitest.logger.log(`[cache] cleared fs module cache at ${uniquePaths.join(', ')}`)\n    }\n  }\n\n  private readCachedFileConcurrently(cachedFilePath: string) {\n    if (!parallelFsCacheRead.has(cachedFilePath)) {\n      parallelFsCacheRead.set(cachedFilePath, readFile(cachedFilePath, 'utf-8').then((code) => {\n        const matchIndex = code.lastIndexOf(cacheComment)\n        if (matchIndex === -1) {\n          debugFs?.(`${c.red('[empty]')} ${cachedFilePath} exists, but doesn't have a ${cacheComment} comment, transforming by vite instead`)\n          return\n        }\n\n        return { code, meta: this.fromBase64(code.slice(matchIndex + cacheCommentLength)) }\n      }).finally(() => {\n        parallelFsCacheRead.delete(cachedFilePath)\n      }))\n    }\n    return parallelFsCacheRead.get(cachedFilePath)!\n  }\n\n  async getCachedModule(cachedFilePath: string): Promise<\n    CachedInlineModuleMeta\n    | undefined\n  > {\n    if (!existsSync(cachedFilePath)) {\n      debugFs?.(`${c.red('[empty]')} ${cachedFilePath} doesn't exist, transforming by vite first`)\n      return\n    }\n\n    const fileResult = await this.readCachedFileConcurrently(cachedFilePath)\n    if (!fileResult) {\n      return\n    }\n    const { code, meta } = fileResult\n\n    debugFs?.(`${c.green('[read]')} ${meta.id} is cached in ${cachedFilePath}`)\n\n    return {\n      id: meta.id,\n      url: meta.url,\n      file: meta.file,\n      code,\n      importedUrls: meta.importedUrls,\n      mappings: meta.mappings,\n    }\n  }\n\n  async saveCachedModule<T extends FetchResult>(\n    cachedFilePath: string,\n    fetchResult: T,\n    importedUrls: string[] = [],\n    mappings: boolean = false,\n  ): Promise<void> {\n    if ('code' in fetchResult) {\n      const result = {\n        file: fetchResult.file,\n        id: fetchResult.id,\n        url: fetchResult.url,\n        importedUrls,\n        mappings,\n      } satisfies Omit<CachedInlineModuleMeta, 'code'>\n      debugFs?.(`${c.yellow('[write]')} ${fetchResult.id} is cached in ${cachedFilePath}`)\n      await atomicWriteFile(cachedFilePath, `${fetchResult.code}${cacheComment}${this.toBase64(result)}`)\n    }\n  }\n\n  private toBase64(obj: unknown) {\n    const json = stringify(obj)\n    return Buffer.from(json).toString('base64')\n  }\n\n  private fromBase64(obj: string) {\n    const json = Buffer.from(obj, 'base64').toString('utf-8')\n    return parse(json)\n  }\n\n  invalidateCachePath(\n    environment: DevEnvironment,\n    id: string,\n  ): void {\n    debugFs?.(`cache for ${id} in ${environment.name} environment is invalidated`)\n    this.fsCacheKeys.get(environment)?.delete(id)\n  }\n\n  invalidateAllCachePaths(environment: DevEnvironment): void {\n    debugFs?.(`the ${environment.name} environment cache is invalidated`)\n    this.fsCacheKeys.get(environment)?.clear()\n  }\n\n  getMemoryCachePath(\n    environment: DevEnvironment,\n    id: string,\n  ): string | null | undefined {\n    const result = this.fsCacheKeys.get(environment)?.get(id)\n    if (result != null) {\n      debugMemory?.(`${c.green('[read]')} ${id} was cached in ${result}`)\n    }\n    else if (result === null) {\n      debugMemory?.(`${c.green('[read]')} ${id} was bailed out`)\n    }\n    return result\n  }\n\n  generateCachePath(\n    vitestConfig: ResolvedConfig,\n    environment: DevEnvironment,\n    id: string,\n    fileContent: string,\n  ): string | null {\n    // bail out if file has import.meta.glob because it depends on other files\n    // TODO: figure out a way to still support it\n    if (fileContent.includes('import.meta.glob(')) {\n      this.saveMemoryCache(environment, id, null)\n      debugMemory?.(`${c.yellow('[write]')} ${id} was bailed out because it has \"import.meta.glob\"`)\n      return null\n    }\n\n    let hashString = ''\n\n    for (const generator of this.fsCacheKeyGenerators) {\n      const result = generator({ environment, id, sourceCode: fileContent })\n      if (typeof result === 'string') {\n        hashString += result\n      }\n      if (result === false) {\n        this.saveMemoryCache(environment, id, null)\n        debugMemory?.(`${c.yellow('[write]')} ${id} was bailed out by a custom generator`)\n        return null\n      }\n    }\n\n    const config = environment.config\n    // coverage provider is dynamic, so we also clear the whole cache if\n    // vitest.enableCoverage/vitest.disableCoverage is called\n    const coverageAffectsCache = String(this.vitest.config.coverage.enabled && this.vitest.coverageProvider?.requiresTransform?.(id))\n    let cacheConfig = this.fsEnvironmentHashMap.get(environment)\n    if (!cacheConfig) {\n      cacheConfig = JSON.stringify(\n        {\n          root: config.root,\n          // at the moment, Vitest always forces base to be /\n          base: config.base,\n          mode: config.mode,\n          consumer: config.consumer,\n          resolve: config.resolve,\n          // plugins can have different options, so this is not the best key,\n          // but we canot access the options because there is no standard API for it\n          plugins: config.plugins\n            .filter(p => p.api?.vitest?.experimental?.ignoreFsModuleCache !== true)\n            .map(p => p.name),\n          // in case local plugins change\n          // configFileDependencies also includes configFile\n          configFileDependencies: config.configFileDependencies.map(file => tryReadFileSync(file)),\n          environment: environment.name,\n          // this affects Vitest CSS plugin\n          css: vitestConfig.css,\n        },\n        (_, value) => {\n          if (typeof value === 'function' || value instanceof RegExp) {\n            return value.toString()\n          }\n          return value\n        },\n      )\n      this.fsEnvironmentHashMap.set(environment, cacheConfig)\n    }\n\n    hashString += id\n      + fileContent\n      + (process.env.NODE_ENV ?? '')\n      + this.version\n      + cacheConfig\n      + coverageAffectsCache\n\n    const cacheKey = hash('sha1', hashString, 'hex')\n\n    let cacheRoot = this.fsCacheRoots.get(vitestConfig)\n    if (cacheRoot == null) {\n      cacheRoot = vitestConfig.experimental.fsModuleCachePath || this.rootCache\n      this.fsCacheRoots.set(vitestConfig, cacheRoot)\n      if (!existsSync(cacheRoot)) {\n        mkdirSync(cacheRoot, { recursive: true })\n      }\n    }\n\n    const fsResultPath = join(cacheRoot, cacheKey)\n    debugMemory?.(`${c.yellow('[write]')} ${id} generated a cache in ${fsResultPath}`)\n    this.saveMemoryCache(environment, id, fsResultPath)\n    return fsResultPath\n  }\n\n  private saveMemoryCache(environment: DevEnvironment, id: string, cache: string | null) {\n    let environmentKeys = this.fsCacheKeys.get(environment)\n    if (!environmentKeys) {\n      environmentKeys = new Map()\n      this.fsCacheKeys.set(environment, environmentKeys)\n    }\n    environmentKeys.set(id, cache)\n  }\n\n  private async readMetadata(): Promise<{ lockfileHash: string } | undefined> {\n    // metadata is shared between every projects in the workspace, so we ignore project's fsModuleCachePath\n    if (!existsSync(this.metadataFilePath)) {\n      return undefined\n    }\n    try {\n      const content = await readFile(this.metadataFilePath, 'utf-8')\n      return JSON.parse(content)\n    }\n    catch {}\n  }\n\n  // before vitest starts running tests, we check that the lockfile wasn't updated\n  // if it was, we nuke the previous cache in case a custom plugin was updated\n  // or a new version of vite/vitest is installed\n  // for the same reason we also cache config file content, but that won't catch changes made in external plugins\n  public async ensureCacheIntegrity(): Promise<void> {\n    const enabled = [\n      this.vitest.getRootProject(),\n      ...this.vitest.projects,\n    ].some(p => p.config.experimental.fsModuleCache)\n    if (!enabled) {\n      return\n    }\n\n    const metadata = await this.readMetadata()\n    const currentLockfileHash = getLockfileHash(this.vitest.vite.config.root)\n\n    // no metadata found, just store a new one, don't reset the cache\n    if (!metadata) {\n      if (!existsSync(this.rootCache)) {\n        mkdirSync(this.rootCache, { recursive: true })\n      }\n      debugFs?.(`fs metadata file was created with hash ${currentLockfileHash}`)\n\n      await writeFile(\n        this.metadataFilePath,\n        JSON.stringify({ lockfileHash: currentLockfileHash }, null, 2),\n        'utf-8',\n      )\n      return\n    }\n\n    // if lockfile didn't change, don't do anything\n    if (metadata.lockfileHash === currentLockfileHash) {\n      return\n    }\n\n    // lockfile changed, let's clear all caches\n    await this.clearCache(false)\n    this.vitest.vite.config.logger.info(\n      `fs cache was cleared because lockfile has changed`,\n      {\n        timestamp: true,\n        environment: c.yellow('[vitest]'),\n      },\n    )\n    debugFs?.(`fs cache was cleared because lockfile has changed`)\n  }\n}\n\n/**\n * Performs an atomic write operation using the write-then-rename pattern.\n *\n * Why we need this:\n * - Ensures file integrity by never leaving partially written files on disk\n * - Prevents other processes from reading incomplete data during writes\n * - Particularly important for test files where incomplete writes could cause test failures\n *\n * The implementation writes to a temporary file first, then renames it to the target path.\n * This rename operation is atomic on most filesystems (including POSIX-compliant ones),\n * guaranteeing that other processes will only ever see the complete file.\n *\n * Added in https://github.com/vitest-dev/vitest/pull/7531\n */\nasync function atomicWriteFile(realFilePath: string, data: string): Promise<void> {\n  const dir = dirname(realFilePath)\n  const tmpFilePath = join(dir, `.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`)\n\n  try {\n    await writeFile(tmpFilePath, data, 'utf-8')\n    await rename(tmpFilePath, realFilePath)\n  }\n  finally {\n    try {\n      if (await stat(tmpFilePath)) {\n        await unlink(tmpFilePath)\n      }\n    }\n    catch {}\n  }\n}\n\nexport interface CachedInlineModuleMeta {\n  url: string\n  id: string\n  file: string | null\n  code: string\n  mappings: boolean\n  importedUrls: string[]\n}\n\n/**\n * Generate a unique cache identifier.\n *\n * Return `false` to disable caching of the file.\n * @experimental\n */\nexport interface CacheKeyIdGenerator {\n  (context: CacheKeyIdGeneratorContext): string | undefined | null | false\n}\n\n/**\n * @experimental\n */\nexport interface CacheKeyIdGeneratorContext {\n  environment: DevEnvironment\n  id: string\n  sourceCode: string\n}\n\n// lockfile hash resolution taken from vite\n// since this is experimental, we don't ask to expose it\nconst lockfileFormats = [\n  {\n    path: 'node_modules/.package-lock.json',\n    checkPatchesDir: 'patches',\n    manager: 'npm',\n  },\n  {\n    // Yarn non-PnP\n    path: 'node_modules/.yarn-state.yml',\n    checkPatchesDir: false,\n    manager: 'yarn',\n  },\n  {\n    // Yarn v3+ PnP\n    path: '.pnp.cjs',\n    checkPatchesDir: '.yarn/patches',\n    manager: 'yarn',\n  },\n  {\n    // Yarn v2 PnP\n    path: '.pnp.js',\n    checkPatchesDir: '.yarn/patches',\n    manager: 'yarn',\n  },\n  {\n    // yarn 1\n    path: 'node_modules/.yarn-integrity',\n    checkPatchesDir: 'patches',\n    manager: 'yarn',\n  },\n  {\n    path: 'node_modules/.pnpm/lock.yaml',\n    // Included in lockfile\n    checkPatchesDir: false,\n    manager: 'pnpm',\n  },\n  {\n    path: '.rush/temp/shrinkwrap-deps.json',\n    // Included in lockfile\n    checkPatchesDir: false,\n    manager: 'pnpm',\n  },\n  {\n    path: 'bun.lock',\n    checkPatchesDir: 'patches',\n    manager: 'bun',\n  },\n  {\n    path: 'bun.lockb',\n    checkPatchesDir: 'patches',\n    manager: 'bun',\n  },\n].sort((_, { manager }) => {\n  return process.env.npm_config_user_agent?.startsWith(manager) ? 1 : -1\n})\nconst lockfilePaths = lockfileFormats.map(l => l.path)\n\nfunction getLockfileHash(root: string): string {\n  const lockfilePath = lookupFile(root, lockfilePaths)\n  let content = lockfilePath ? fs.readFileSync(lockfilePath, 'utf-8') : ''\n  if (lockfilePath) {\n    const normalizedLockfilePath = lockfilePath.replaceAll('\\\\', '/')\n    const lockfileFormat = lockfileFormats.find(f =>\n      normalizedLockfilePath.endsWith(f.path),\n    )!\n    if (lockfileFormat.checkPatchesDir) {\n      // Default of https://github.com/ds300/patch-package\n      const baseDir = lockfilePath.slice(0, -lockfileFormat.path.length)\n      const fullPath = join(\n        baseDir,\n        lockfileFormat.checkPatchesDir as string,\n      )\n      const stat = tryStatSync(fullPath)\n      if (stat?.isDirectory()) {\n        content += stat.mtimeMs.toString()\n      }\n    }\n  }\n  return hash('sha256', content, 'hex').substring(0, 8).padEnd(8, '_')\n}\n\nfunction lookupFile(\n  dir: string,\n  fileNames: string[],\n): string | undefined {\n  while (dir) {\n    for (const fileName of fileNames) {\n      const fullPath = join(dir, fileName)\n      if (tryStatSync(fullPath)?.isFile()) {\n        return fullPath\n      }\n    }\n    const parentDir = dirname(dir)\n    if (parentDir === dir) {\n      return\n    }\n\n    dir = parentDir\n  }\n}\n\nfunction tryReadFileSync(file: string): string {\n  try {\n    return readFileSync(file, 'utf-8')\n  }\n  catch {\n    return ''\n  }\n}\n\nfunction tryStatSync(file: string): fs.Stats | undefined {\n  try {\n    // The \"throwIfNoEntry\" is a performance optimization for cases where the file does not exist\n    return fs.statSync(file, { throwIfNoEntry: false })\n  }\n  catch {\n    // Ignore errors\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cache/index.ts",
    "content": "import type { Logger } from '../logger'\nimport type { SuiteResultCache } from './results'\nimport { slash } from '@vitest/utils/helpers'\nimport { resolve } from 'pathe'\nimport { hash } from '../hash'\nimport { FilesStatsCache } from './files'\nimport { ResultsCache } from './results'\n\nexport class VitestCache {\n  results: ResultsCache\n  stats: FilesStatsCache = new FilesStatsCache()\n\n  constructor(logger: Logger) {\n    this.results = new ResultsCache(logger)\n  }\n\n  getFileTestResults(key: string): SuiteResultCache | undefined {\n    return this.results.getResults(key)\n  }\n\n  getFileStats(key: string): {\n    size: number\n  } | undefined {\n    return this.stats.getStats(key)\n  }\n\n  static resolveCacheDir(root: string, dir?: string, projectName?: string): string {\n    const baseDir = slash(dir || 'node_modules/.vite')\n    return resolve(\n      root,\n      baseDir,\n      'vitest',\n      hash('sha1', projectName || '', 'hex'),\n    )\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cache/results.ts",
    "content": "import type { File } from '@vitest/runner'\nimport type { Logger } from '../logger'\nimport type { ResolvedConfig } from '../types/config'\nimport fs, { existsSync } from 'node:fs'\nimport { rm } from 'node:fs/promises'\nimport { dirname, relative, resolve } from 'pathe'\nimport { Vitest } from '../core'\n\nexport interface SuiteResultCache {\n  failed: boolean\n  duration: number\n}\n\nexport class ResultsCache {\n  private cache = new Map<string, SuiteResultCache>()\n  private workspacesKeyMap = new Map<string, string[]>()\n  private cachePath: string | null = null\n  private version: string\n  private root = '/'\n\n  constructor(private logger: Logger) {\n    this.version = Vitest.version\n  }\n\n  public getCachePath(): string | null {\n    return this.cachePath\n  }\n\n  setConfig(root: string, config: ResolvedConfig['cache']): void {\n    this.root = root\n    if (config) {\n      this.cachePath = resolve(config.dir, 'results.json')\n    }\n  }\n\n  getResults(key: string): SuiteResultCache | undefined {\n    return this.cache.get(key)\n  }\n\n  async clearCache(): Promise<void> {\n    if (this.cachePath && existsSync(this.cachePath)) {\n      await rm(this.cachePath, { force: true, recursive: true })\n      this.logger.log('[cache] cleared results cache at', this.cachePath)\n    }\n  }\n\n  async readFromCache(): Promise<void> {\n    if (!this.cachePath) {\n      return\n    }\n\n    if (!fs.existsSync(this.cachePath)) {\n      return\n    }\n\n    const resultsCache = await fs.promises.readFile(this.cachePath, 'utf8')\n    const { results, version } = JSON.parse(resultsCache || '[]')\n    const [major, minor] = version.split('.')\n    // handling changed in 0.30.0\n    if (major > 0 || Number(minor) >= 30) {\n      this.cache = new Map(results)\n      this.version = version\n      results.forEach(([spec]: [string]) => {\n        const [projectName, relativePath] = spec.split(':')\n        const keyMap = this.workspacesKeyMap.get(relativePath) || []\n        keyMap.push(projectName)\n        this.workspacesKeyMap.set(relativePath, keyMap)\n      })\n    }\n  }\n\n  updateResults(files: File[]): void {\n    files.forEach((file) => {\n      const result = file.result\n      if (!result) {\n        return\n      }\n      const duration = result.duration || 0\n      // store as relative, so cache would be the same in CI and locally\n      const relativePath = relative(this.root, file.filepath)\n      this.cache.set(`${file.projectName || ''}:${relativePath}`, {\n        duration: duration >= 0 ? duration : 0,\n        failed: result.state === 'fail',\n      })\n    })\n  }\n\n  removeFromCache(filepath: string): void {\n    this.cache.forEach((_, key) => {\n      if (key.endsWith(filepath)) {\n        this.cache.delete(key)\n      }\n    })\n  }\n\n  async writeToCache(): Promise<void> {\n    if (!this.cachePath) {\n      return\n    }\n\n    const results = Array.from(this.cache.entries())\n\n    const cacheDirname = dirname(this.cachePath)\n\n    if (!fs.existsSync(cacheDirname)) {\n      await fs.promises.mkdir(cacheDirname, { recursive: true })\n    }\n\n    const cache = JSON.stringify({\n      version: this.version,\n      results,\n    })\n\n    await fs.promises.writeFile(this.cachePath, cache)\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cli/cac.ts",
    "content": "import type { CAC, Command } from 'cac'\nimport type { VitestRunMode } from '../types/config'\nimport type { CliOptions } from './cli-api'\nimport type { CLIOption, CLIOptions as CLIOptionsConfig } from './cli-config'\nimport { toArray } from '@vitest/utils/helpers'\nimport cac from 'cac'\nimport { normalize } from 'pathe'\nimport c from 'tinyrainbow'\nimport { version } from '../../../package.json' with { type: 'json' }\nimport { benchCliOptionsConfig, cliOptionsConfig, collectCliOptionsConfig } from './cli-config'\nimport { setupTabCompletions } from './completions'\n\nfunction addCommand(cli: CAC | Command, name: string, option: CLIOption<any>) {\n  const commandName = option.alias || name\n  let command = option.shorthand ? `-${option.shorthand}, --${commandName}` : `--${commandName}`\n  if ('argument' in option) {\n    command += ` ${option.argument}`\n  }\n\n  function transform(value: unknown) {\n    if (!option.array && Array.isArray(value)) {\n      const received = value.map(s => typeof s === 'string' ? `\"${s}\"` : s).join(', ')\n      throw new Error(\n        `Expected a single value for option \"${command}\", received [${received}]`,\n      )\n    }\n    value = removeQuotes(value)\n    if (option.transform) {\n      return option.transform(value)\n    }\n    if (option.array) {\n      return toArray(value)\n    }\n    if (option.normalize) {\n      return normalize(String(value))\n    }\n    return value\n  }\n\n  const hasSubcommands = 'subcommands' in option && option.subcommands\n\n  if (option.description) {\n    let description = option.description.replace(/\\[.*\\]\\((.*)\\)/, '$1').replace(/`/g, '')\n\n    if (hasSubcommands) {\n      description += `. Use '--help --${commandName}' for more info.`\n    }\n\n    cli.option(command, description, {\n      type: transform,\n    })\n  }\n\n  if (hasSubcommands) {\n    for (const commandName in option.subcommands) {\n      const subcommand = option.subcommands[commandName]\n      if (subcommand) {\n        addCommand(cli, `${name}.${commandName}`, subcommand)\n      }\n    }\n  }\n}\n\nexport interface CliParseOptions {\n  allowUnknownOptions?: boolean\n}\n\nfunction addCliOptions(cli: CAC | Command, options: CLIOptionsConfig<any>) {\n  for (const [optionName, option] of Object.entries(options)) {\n    if (option) {\n      addCommand(cli, optionName, option)\n    }\n  }\n}\n\nexport function createCLI(options: CliParseOptions = {}): CAC {\n  const cli = cac('vitest')\n\n  cli.version(version)\n\n  addCliOptions(cli, cliOptionsConfig)\n\n  cli.help((info) => {\n    const helpSection = info.find(current => current.title?.startsWith('For more info, run any command'))\n\n    if (helpSection) {\n      helpSection.body += '\\n  $ vitest --help --expand-help'\n    }\n\n    const options = info.find(current => current.title === 'Options')\n\n    if (typeof options !== 'object') {\n      return info\n    }\n\n    const helpIndex = process.argv.findIndex(arg => arg === '--help')\n    const subcommands = process.argv.slice(helpIndex + 1)\n\n    const defaultOutput = options.body\n      .split('\\n')\n      .filter(line => /^\\s+--\\S+\\./.test(line) === false)\n      .join('\\n')\n\n    // Filter out options with dot-notation if --help is not called with a subcommand (default behavior)\n    if (subcommands.length === 0) {\n      options.body = defaultOutput\n      return info\n    }\n\n    if (subcommands.length === 1 && (subcommands[0] === '--expand-help' || subcommands[0] === '--expandHelp')) {\n      return info\n    }\n\n    const subcommandMarker = '$SUB_COMMAND_MARKER$'\n\n    const banner = info.find(current => /^vitest\\/\\d+\\.\\d+\\.\\d+$/.test(current.body))\n    function addBannerWarning(warning: string) {\n      if (typeof banner?.body === 'string') {\n        if (banner?.body.includes(warning)) {\n          return\n        }\n\n        banner.body = `${banner.body}\\n WARN: ${warning}`\n      }\n    }\n\n    // If other subcommand combinations are used, only show options for the subcommand\n    for (let i = 0; i < subcommands.length; i++) {\n      const subcommand = subcommands[i]\n\n      // --help --expand-help can't be called with multiple subcommands and is handled above\n      if (subcommand === '--expand-help' || subcommand === '--expandHelp') {\n        addBannerWarning('--expand-help subcommand ignored because, when used with --help, it must be the only subcommand')\n        continue\n      }\n\n      // Mark the help section for the subcommands\n      if (subcommand.startsWith('--')) {\n        options.body = options.body\n          .split('\\n')\n          .map(line => (line.trim().startsWith(subcommand)) ? `${subcommandMarker}${line}` : line)\n          .join('\\n')\n      }\n    }\n\n    // Filter based on the marked options to preserve the original sort order\n    options.body = options.body\n      .split('\\n')\n      .map(line => line.startsWith(subcommandMarker) ? line.split(subcommandMarker)[1] : '')\n      .filter(line => line.length !== 0)\n      .join('\\n')\n\n    if (!options.body) {\n      addBannerWarning('no options were found for your subcommands so we printed the whole output')\n      options.body = defaultOutput\n    }\n\n    return info\n  })\n\n  cli\n    .command('run [...filters]', undefined, options)\n    .action(run)\n\n  cli\n    .command('related [...filters]', undefined, options)\n    .action(runRelated)\n\n  cli\n    .command('watch [...filters]', undefined, options)\n    .action(watch)\n\n  cli\n    .command('dev [...filters]', undefined, options)\n    .action(watch)\n\n  addCliOptions(\n    cli\n      .command('bench [...filters]', undefined, options)\n      .action(benchmark),\n    benchCliOptionsConfig,\n  )\n\n  cli\n    .command('init <project>', undefined, options)\n    .action(init)\n\n  addCliOptions(\n    cli\n      .command('list [...filters]', undefined, options)\n      .action((filters, options) => collect('test', filters, options)),\n    collectCliOptionsConfig,\n  )\n\n  cli\n    .command('[...filters]', undefined, options)\n    .action((filters, options) => start('test', filters, options))\n\n  setupTabCompletions(cli)\n  return cli\n}\n\nfunction removeQuotes<T>(str: T): T {\n  if (typeof str !== 'string') {\n    if (Array.isArray(str)) {\n      return str.map(removeQuotes) as unknown as T\n    }\n    return str\n  }\n  if (str[0] === '\"' && str.endsWith('\"')) {\n    return str.slice(1, -1) as unknown as T\n  }\n  if (str.startsWith(`'`) && str.endsWith(`'`)) {\n    return str.slice(1, -1) as unknown as T\n  }\n  return str\n}\n\nfunction splitArgv(argv: string): string[] {\n  const reg = /(['\"])(?:(?!\\1).)+\\1/g\n  argv = argv.replace(reg, match => match.replace(/\\s/g, '\\x00'))\n  return argv.split(' ').map((arg: string) => {\n    arg = arg.replace(/\\0/g, ' ')\n    return removeQuotes(arg)\n  })\n}\n\nexport function parseCLI(argv: string | string[], config: CliParseOptions = {}): {\n  filter: string[]\n  options: CliOptions\n} {\n  const arrayArgs = typeof argv === 'string' ? splitArgv(argv) : argv\n  if (arrayArgs[0] !== 'vitest') {\n    throw new Error(`Expected \"vitest\" as the first argument, received \"${arrayArgs[0]}\"`)\n  }\n  arrayArgs[0] = '/index.js'\n  arrayArgs.unshift('node')\n  let { args, options } = createCLI(config).parse(arrayArgs, {\n    run: false,\n  })\n  if (arrayArgs[2] === 'watch' || arrayArgs[2] === 'dev') {\n    options.watch = true\n  }\n  if (arrayArgs[2] === 'run' && !options.watch) {\n    options.run = true\n  }\n  if (arrayArgs[2] === 'related') {\n    options.related = args\n    options.passWithNoTests ??= true\n    args = []\n  }\n  return {\n    filter: args as string[],\n    options,\n  }\n}\n\nasync function runRelated(relatedFiles: string[] | string, argv: CliOptions): Promise<void> {\n  argv.related = relatedFiles\n  argv.passWithNoTests ??= true\n  await start('test', [], argv)\n}\n\nasync function watch(cliFilters: string[], options: CliOptions): Promise<void> {\n  options.watch = true\n  await start('test', cliFilters, options)\n}\n\nasync function run(cliFilters: string[], options: CliOptions): Promise<void> {\n  // \"vitest run --watch\" should still be watch mode\n  options.run = !options.watch\n\n  await start('test', cliFilters, options)\n}\n\nasync function benchmark(cliFilters: string[], options: CliOptions): Promise<void> {\n  console.warn(c.yellow('Benchmarking is an experimental feature.\\nBreaking changes might not follow SemVer, please pin Vitest\\'s version when using it.'))\n  await start('benchmark', cliFilters, options)\n}\n\nfunction normalizeCliOptions(cliFilters: string[], argv: CliOptions): CliOptions {\n  if (argv.exclude) {\n    argv.cliExclude = toArray(argv.exclude)\n    delete argv.exclude\n  }\n  if (cliFilters.some(filter => filter.includes(':'))) {\n    argv.includeTaskLocation ??= true\n  }\n\n  if (typeof argv.typecheck?.only === 'boolean') {\n    argv.typecheck.enabled ??= true\n  }\n  if (argv.clearCache || argv.listTags) {\n    argv.watch = false\n    argv.run = true\n  }\n\n  return argv\n}\n\nasync function start(mode: VitestRunMode, cliFilters: string[], options: CliOptions): Promise<void> {\n  try {\n    const { startVitest } = await import('./cli-api')\n    const ctx = await startVitest(mode, cliFilters.map(normalize), normalizeCliOptions(cliFilters, options))\n    if (!ctx.shouldKeepServer()) {\n      await ctx.exit()\n    }\n  }\n  catch (e) {\n    const { errorBanner } = await import('../reporters/renderers/utils')\n    console.error(`\\n${errorBanner('Startup Error')}`)\n    console.error(e)\n    console.error('\\n\\n')\n\n    if (process.exitCode == null) {\n      process.exitCode = 1\n    }\n\n    process.exit()\n  }\n}\n\nasync function init(project: string) {\n  if (project !== 'browser') {\n    console.error(new Error('Only the \"browser\" project is supported. Use \"vitest init browser\" to create a new project.'))\n    process.exit(1)\n  }\n\n  const { create } = await import('../../create/browser/creator')\n  await create()\n}\n\nasync function collect(mode: VitestRunMode, cliFilters: string[], options: CliOptions): Promise<void> {\n  try {\n    const { prepareVitest, processCollected, outputFileList } = await import('./cli-api')\n    const ctx = await prepareVitest(mode, {\n      ...normalizeCliOptions(cliFilters, options),\n      watch: false,\n      run: true,\n    }, undefined, undefined, cliFilters)\n    if (!options.filesOnly) {\n      const { testModules: tests, unhandledErrors: errors } = await ctx.collect(\n        cliFilters.map(normalize),\n        {\n          staticParse: options.staticParse,\n          staticParseConcurrency: options.staticParseConcurrency,\n        },\n      )\n\n      if (errors.length) {\n        console.error('\\nThere were unhandled errors during test collection')\n        errors.forEach(e => console.error(e))\n        console.error('\\n\\n')\n        await ctx.close()\n        return\n      }\n\n      processCollected(ctx, tests, options)\n    }\n    else {\n      const files = await ctx.getRelevantTestSpecifications(cliFilters.map(normalize))\n      outputFileList(files, options)\n    }\n\n    await ctx.close()\n  }\n  catch (e) {\n    const { errorBanner } = await import('../reporters/renderers/utils')\n    console.error(`\\n${errorBanner('Collect Error')}`)\n    console.error(e)\n    console.error('\\n\\n')\n\n    if (process.exitCode == null) {\n      process.exitCode = 1\n    }\n\n    process.exit()\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cli/cli-api.ts",
    "content": "import type { InlineConfig as ViteInlineConfig, UserConfig as ViteUserConfig } from 'vite'\nimport type { environments } from '../../integrations/env'\nimport type { Vitest, VitestOptions } from '../core'\nimport type { TestModule, TestSuite } from '../reporters/reported-tasks'\nimport type { TestSpecification } from '../test-specification'\nimport type { UserConfig, VitestEnvironment, VitestRunMode } from '../types/config'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname, isAbsolute, relative, resolve } from 'pathe'\nimport { CoverageProviderMap } from '../../utils/coverage'\nimport { createVitest } from '../create'\nimport { FilesNotFoundError, GitNotFoundError, IncludeTaskLocationDisabledError, LocationFilterFileNotFoundError, RangeLocationFilterProvidedError } from '../errors'\nimport { registerConsoleShortcuts } from '../stdin'\n\nexport interface CliOptions extends UserConfig {\n  /**\n   * Override the watch mode\n   */\n  run?: boolean\n  /**\n   * Removes colors from the console output\n   */\n  color?: boolean\n  /**\n   * Output collected tests as JSON or to a file\n   */\n  json?: string | boolean\n  /**\n   * Output collected test files only\n   */\n  filesOnly?: boolean\n  /**\n   * Parse files statically instead of running them to collect tests\n   * @experimental\n   */\n  staticParse?: boolean\n  /**\n   * How many tests to process at the same time\n   * @experimental\n   */\n  staticParseConcurrency?: number\n\n  /**\n   * Override vite config's configLoader from CLI.\n   * Use `bundle` to bundle the config with esbuild or `runner` (experimental) to process it on the fly (default: `bundle`).\n   * This is only available with **vite version 6.1.0** and above.\n   * @experimental\n   */\n  configLoader?: ViteInlineConfig extends { configLoader?: infer T } ? T : never\n}\n\n/**\n * Start Vitest programmatically\n *\n * Returns a Vitest instance if initialized successfully.\n */\nexport async function startVitest(\n  mode: VitestRunMode,\n  cliFilters: string[] = [],\n  options: CliOptions = {},\n  viteOverrides?: ViteUserConfig,\n  vitestOptions?: VitestOptions,\n): Promise<Vitest> {\n  const root = resolve(options.root || process.cwd())\n\n  const ctx = await prepareVitest(\n    mode,\n    options,\n    viteOverrides,\n    vitestOptions,\n    cliFilters,\n  )\n\n  if (mode === 'test' && ctx._coverageOptions.enabled) {\n    const provider = ctx._coverageOptions.provider || 'v8'\n    const requiredPackages = CoverageProviderMap[provider]\n\n    if (requiredPackages) {\n      if (\n        !(await ctx.packageInstaller.ensureInstalled(requiredPackages, root, ctx.version))\n      ) {\n        process.exitCode = 1\n        return ctx\n      }\n    }\n  }\n\n  const stdin = vitestOptions?.stdin || process.stdin\n  const stdout = vitestOptions?.stdout || process.stdout\n  let stdinCleanup\n  if (stdin.isTTY && ctx.config.watch) {\n    stdinCleanup = registerConsoleShortcuts(ctx, stdin, stdout)\n  }\n\n  ctx.onAfterSetServer(() => {\n    if (ctx.config.standalone) {\n      ctx.init()\n    }\n    else {\n      ctx.start(cliFilters)\n    }\n  })\n\n  try {\n    if (ctx.config.listTags) {\n      await ctx.listTags()\n    }\n    else if (ctx.config.clearCache) {\n      await ctx.experimental_clearCache()\n    }\n    else if (ctx.config.mergeReports) {\n      await ctx.mergeReports()\n    }\n    else if (ctx.config.standalone) {\n      await ctx.init()\n    }\n    else {\n      await ctx.start(cliFilters)\n    }\n    return ctx\n  }\n  catch (e) {\n    if (e instanceof FilesNotFoundError) {\n      return ctx\n    }\n\n    if (e instanceof GitNotFoundError) {\n      ctx.logger.error(e.message)\n      return ctx\n    }\n\n    if (\n      e instanceof IncludeTaskLocationDisabledError\n      || e instanceof RangeLocationFilterProvidedError\n      || e instanceof LocationFilterFileNotFoundError\n    ) {\n      ctx.logger.printError(e, { verbose: false })\n      return ctx\n    }\n\n    process.exitCode = 1\n    ctx.logger.printError(e, { fullStack: true, type: 'Unhandled Error' })\n    ctx.logger.error('\\n\\n')\n    return ctx\n  }\n  finally {\n    if (!ctx?.shouldKeepServer()) {\n      stdinCleanup?.()\n      await ctx.close()\n    }\n  }\n}\n\nexport async function prepareVitest(\n  mode: VitestRunMode,\n  options: CliOptions = {},\n  viteOverrides?: ViteUserConfig,\n  vitestOptions?: VitestOptions,\n  cliFilters?: string[],\n): Promise<Vitest> {\n  process.env.TEST = 'true'\n  process.env.VITEST = 'true'\n  process.env.NODE_ENV ??= 'test'\n\n  if (options.run) {\n    options.watch = false\n  }\n\n  if (options.standalone && (cliFilters?.length || 0) > 0) {\n    options.standalone = false\n  }\n\n  // this shouldn't affect _application root_ that can be changed inside config\n  const root = resolve(options.root || process.cwd())\n\n  const ctx = await createVitest(mode, options, viteOverrides, vitestOptions)\n\n  const environmentPackage = getEnvPackageName(ctx.config.environment)\n\n  if (\n    environmentPackage\n    && !(await ctx.packageInstaller.ensureInstalled(environmentPackage, root))\n  ) {\n    process.exitCode = 1\n    return ctx\n  }\n\n  return ctx\n}\n\nexport function processCollected(ctx: Vitest, files: TestModule[], options: CliOptions): void {\n  let errorsPrinted = false\n\n  forEachSuite(files, (suite) => {\n    suite.errors().forEach((error) => {\n      errorsPrinted = true\n      ctx.logger.printError(error, {\n        project: suite.project,\n      })\n    })\n  })\n\n  if (errorsPrinted) {\n    return\n  }\n\n  if (typeof options.json !== 'undefined') {\n    return processJsonOutput(files, options)\n  }\n\n  return formatCollectedAsString(files).forEach(test => console.log(test))\n}\n\nexport function outputFileList(files: TestSpecification[], options: CliOptions): void {\n  if (typeof options.json !== 'undefined') {\n    return outputJsonFileList(files, options)\n  }\n\n  formatFilesAsString(files, options).map(file => console.log(file))\n}\n\nfunction outputJsonFileList(files: TestSpecification[], options: CliOptions) {\n  if (typeof options.json === 'boolean') {\n    return console.log(JSON.stringify(formatFilesAsJSON(files), null, 2))\n  }\n  if (typeof options.json === 'string') {\n    const jsonPath = resolve(options.root || process.cwd(), options.json)\n    mkdirSync(dirname(jsonPath), { recursive: true })\n    writeFileSync(jsonPath, JSON.stringify(formatFilesAsJSON(files), null, 2))\n  }\n}\n\nfunction formatFilesAsJSON(files: TestSpecification[]) {\n  return files.map((file) => {\n    const result: any = {\n      file: file.moduleId,\n    }\n\n    if (file.project.name) {\n      result.projectName = file.project.name\n    }\n    return result\n  })\n}\n\nfunction formatFilesAsString(files: TestSpecification[], options: CliOptions) {\n  return files.map((file) => {\n    let name = relative(options.root || process.cwd(), file.moduleId)\n    if (file.project.name) {\n      name = `[${file.project.name}] ${name}`\n    }\n    return name\n  })\n}\n\nfunction processJsonOutput(files: TestModule[], options: CliOptions) {\n  if (typeof options.json === 'boolean') {\n    return console.log(JSON.stringify(formatCollectedAsJSON(files), null, 2))\n  }\n\n  if (typeof options.json === 'string') {\n    const jsonPath = resolve(options.root || process.cwd(), options.json)\n    mkdirSync(dirname(jsonPath), { recursive: true })\n    writeFileSync(jsonPath, JSON.stringify(formatCollectedAsJSON(files), null, 2))\n  }\n}\n\nfunction forEachSuite(modules: TestModule[], callback: (suite: TestSuite | TestModule) => void) {\n  modules.forEach((testModule) => {\n    callback(testModule)\n    for (const suite of testModule.children.allSuites()) {\n      callback(suite)\n    }\n  })\n}\n\nexport interface TestCollectJSONResult {\n  name: string\n  file: string\n  projectName?: string\n  location?: { line: number; column: number }\n}\n\nexport function formatCollectedAsJSON(files: TestModule[]): TestCollectJSONResult[] {\n  const results: TestCollectJSONResult[] = []\n\n  files.forEach((file) => {\n    for (const test of file.children.allTests()) {\n      if (test.result().state === 'skipped') {\n        continue\n      }\n      const result: TestCollectJSONResult = {\n        name: test.fullName,\n        file: test.module.moduleId,\n      }\n      if (test.project.name) {\n        result.projectName = test.project.name\n      }\n      if (test.location) {\n        result.location = test.location\n      }\n      results.push(result)\n    }\n  })\n  return results\n}\n\nexport function formatCollectedAsString(testModules: TestModule[]): string[] {\n  const results: string[] = []\n\n  testModules.forEach((testModule) => {\n    for (const test of testModule.children.allTests()) {\n      if (test.result().state === 'skipped') {\n        continue\n      }\n      const fullName = `${test.module.task.name} > ${test.fullName}`\n      results.push(\n        (test.project.name ? `[${test.project.name}] ` : '') + fullName,\n      )\n    }\n  })\n\n  return results\n}\n\nconst envPackageNames: Record<\n  Exclude<keyof typeof environments, 'node'>,\n  string\n> = {\n  'jsdom': 'jsdom',\n  'happy-dom': 'happy-dom',\n  'edge-runtime': '@edge-runtime/vm',\n}\n\nfunction getEnvPackageName(env: VitestEnvironment) {\n  if (env === 'node') {\n    return null\n  }\n  if (env in envPackageNames) {\n    return (envPackageNames as any)[env]\n  }\n  if (env[0] === '.' || isAbsolute(env)) {\n    return null\n  }\n  return `vitest-environment-${env}`\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cli/cli-config.ts",
    "content": "import type { ApiConfig } from '../types/config'\nimport type { CliOptions } from './cli-api'\nimport { defaultBrowserPort, defaultPort } from '../../constants'\nimport { ReportersMap } from '../reporters'\n\ntype NestedOption<T, V = Extract<T, Record<string, any>>> = V extends\n  | never\n  | RegExp\n  | unknown[]\n  ? never\n  : V\n\nexport type CLIOption<Value> = {\n  description: string | null\n  alias?: string\n  shorthand?: string\n  default?: unknown\n  transform?: (value: unknown) => unknown\n  array?: boolean\n  normalize?: boolean\n} & (NestedOption<Value> extends never // require subcommands for nested options\n  ? object\n  : { subcommands: CLIOptions<NestedOption<Value>> | null })\n  // require argument for non-boolean options\n& (NonNullable<Value> extends boolean ? object : { argument: string })\n\nexport type CLIOptions<Config extends object> = {\n  [Key in keyof Config as NonNullable<Config[Key]> extends Function\n    ? never\n    : Key]-?: CLIOption<Config[Key]> | null;\n}\n\ntype VitestCLIOptions = CLIOptions<CliOptions>\n\nconst apiConfig: (port: number) => CLIOptions<ApiConfig> = (port: number) => ({\n  port: {\n    description: `Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to \\`${port}\\``,\n    argument: '[port]',\n  },\n  host: {\n    description:\n      'Specify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses',\n    argument: '[host]',\n  },\n  strictPort: {\n    description:\n      'Set to true to exit if port is already in use, instead of automatically trying the next available port',\n  },\n  allowExec: {\n    description: 'Allow API to execute code. (Be careful when enabling this option in untrusted environments)',\n  },\n  allowWrite: {\n    description: 'Allow API to edit files. (Be careful when enabling this option in untrusted environments)',\n  },\n  middlewareMode: null,\n})\n\nfunction watermarkTransform(value: unknown) {\n  if (typeof value === 'string') {\n    return value.split(',').map(Number)\n  }\n  return value\n}\n\nfunction transformNestedBoolean(value: unknown) {\n  if (typeof value === 'boolean') {\n    return { enabled: value }\n  }\n  return value\n}\n\nexport const cliOptionsConfig: VitestCLIOptions = {\n  root: {\n    description: 'Root path',\n    shorthand: 'r',\n    argument: '<path>',\n    normalize: true,\n  },\n  config: {\n    shorthand: 'c',\n    description: 'Path to config file',\n    argument: '<path>',\n    normalize: true,\n  },\n  update: {\n    shorthand: 'u',\n    description: 'Update snapshot (accepts boolean, \"new\", \"all\" or \"none\")',\n    argument: '[type]',\n  },\n  watch: {\n    shorthand: 'w',\n    description: 'Enable watch mode',\n  },\n  testNamePattern: {\n    description:\n      'Run tests with full names matching the specified regexp pattern',\n    argument: '<pattern>',\n    shorthand: 't',\n  },\n  dir: {\n    description: 'Base directory to scan for the test files',\n    argument: '<path>',\n    normalize: true,\n  },\n  ui: {\n    description: 'Enable UI',\n  },\n  open: {\n    description: 'Open UI automatically (default: `!process.env.CI`)',\n  },\n  api: {\n    argument: '[port]',\n    description: `Specify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on. If true will be set to ${defaultPort}`,\n    subcommands: apiConfig(defaultPort),\n    transform(portOrOptions) {\n      if (typeof portOrOptions === 'number') {\n        return { port: portOrOptions }\n      }\n      return portOrOptions\n    },\n  },\n  silent: {\n    description: 'Silent console output from tests. Use `\\'passed-only\\'` to see logs from failing tests only.',\n    argument: '[value]',\n    transform(value) {\n      if (value === 'true' || value === 'yes' || value === true) {\n        return true\n      }\n      if (value === 'false' || value === 'no' || value === false) {\n        return false\n      }\n      if (value === 'passed-only') {\n        return value\n      }\n\n      throw new TypeError(`Unexpected value \"--silent=${value}\". Use \"--silent=true ${value}\" instead.`)\n    },\n  },\n  hideSkippedTests: {\n    description: 'Hide logs for skipped tests',\n  },\n  reporters: {\n    alias: 'reporter',\n    description: `Specify reporters (${Object.keys(ReportersMap).join(', ')})`,\n    argument: '<name>',\n    subcommands: null, // don't support custom objects\n    array: true,\n  },\n  outputFile: {\n    argument: '<filename/-s>',\n    description:\n      'Write test results to a file when supporter reporter is also specified, use cac\\'s dot notation for individual outputs of multiple reporters (example: `--outputFile.tap=./tap.txt`)',\n    subcommands: null,\n  },\n  coverage: {\n    description: 'Enable coverage report',\n    argument: '', // empty string means boolean\n    transform: transformNestedBoolean,\n    subcommands: {\n      provider: {\n        description:\n          'Select the tool for coverage collection, available values are: \"v8\", \"istanbul\" and \"custom\"',\n        argument: '<name>',\n      },\n      enabled: {\n        description:\n          'Enables coverage collection. Can be overridden using the `--coverage` CLI option (default: `false`)',\n      },\n      include: {\n        description:\n          'Files included in coverage as glob patterns. May be specified more than once when using multiple patterns. By default only files covered by tests are included.',\n        argument: '<pattern>',\n        array: true,\n      },\n      exclude: {\n        description:\n          'Files to be excluded in coverage. May be specified more than once when using multiple extensions.',\n        argument: '<pattern>',\n        array: true,\n      },\n      clean: {\n        description:\n          'Clean coverage results before running tests (default: true)',\n      },\n      cleanOnRerun: {\n        description: 'Clean coverage report on watch rerun (default: true)',\n      },\n      reportsDirectory: {\n        description:\n          'Directory to write coverage report to (default: ./coverage)',\n        argument: '<path>',\n        normalize: true,\n      },\n      reporter: {\n        description:\n          'Coverage reporters to use. Visit [`coverage.reporter`](https://vitest.dev/config/coverage#coverage-reporter) for more information (default: `[\"text\", \"html\", \"clover\", \"json\"]`)',\n        argument: '<name>',\n        subcommands: null, // don't support custom objects\n        array: true,\n      },\n      reportOnFailure: {\n        description:\n          'Generate coverage report even when tests fail (default: `false`)',\n      },\n      allowExternal: {\n        description:\n          'Collect coverage of files outside the project root (default: `false`)',\n      },\n      skipFull: {\n        description:\n          'Do not show files with 100% statement, branch, and function coverage (default: `false`)',\n      },\n      thresholds: {\n        description: null,\n        argument: '', // no displayed\n        subcommands: {\n          perFile: {\n            description:\n              'Check thresholds per file. See `--coverage.thresholds.lines`, `--coverage.thresholds.functions`, `--coverage.thresholds.branches` and `--coverage.thresholds.statements` for the actual thresholds (default: `false`)',\n          },\n          autoUpdate: {\n            description:\n              'Update threshold values: \"lines\", \"functions\", \"branches\" and \"statements\" to configuration file when current coverage is above the configured thresholds (default: `false`)',\n            argument: '<boolean|function>',\n            subcommands: null,\n            transform(value) {\n              if (value === 'true' || value === 'yes' || value === true) {\n                return true\n              }\n              if (value === 'false' || value === 'no' || value === false) {\n                return false\n              }\n              return value\n            },\n          },\n          lines: {\n            description:\n              'Threshold for lines. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers',\n            argument: '<number>',\n          },\n          functions: {\n            description:\n              'Threshold for functions. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers',\n            argument: '<number>',\n          },\n          branches: {\n            description:\n              'Threshold for branches. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers',\n            argument: '<number>',\n          },\n          statements: {\n            description:\n              'Threshold for statements. Visit [istanbuljs](https://github.com/istanbuljs/nyc#coverage-thresholds) for more information. This option is not available for custom providers',\n            argument: '<number>',\n          },\n          100: {\n            description:\n              'Shortcut to set all coverage thresholds to 100 (default: `false`)',\n          },\n        },\n      },\n      ignoreClassMethods: {\n        description:\n          'Array of class method names to ignore for coverage. Visit [istanbuljs](https://github.com/istanbuljs/nyc#ignoring-methods) for more information. This option is only available for the istanbul providers (default: `[]`)',\n        argument: '<name>',\n        array: true,\n      },\n      processingConcurrency: {\n        description:\n          'Concurrency limit used when processing the coverage results. (default min between 20 and the number of CPUs)',\n        argument: '<number>',\n      },\n      customProviderModule: {\n        description:\n          'Specifies the module name or path for the custom coverage provider module. Visit [Custom Coverage Provider](https://vitest.dev/guide/coverage#custom-coverage-provider) for more information. This option is only available for custom providers',\n        argument: '<path>',\n        normalize: true,\n      },\n      watermarks: {\n        description: null,\n        argument: '', // no displayed\n        subcommands: {\n          statements: {\n            description:\n              'High and low watermarks for statements in the format of `<high>,<low>`',\n            argument: '<watermarks>',\n            transform: watermarkTransform,\n          },\n          lines: {\n            description:\n              'High and low watermarks for lines in the format of `<high>,<low>`',\n            argument: '<watermarks>',\n            transform: watermarkTransform,\n          },\n          branches: {\n            description:\n              'High and low watermarks for branches in the format of `<high>,<low>`',\n            argument: '<watermarks>',\n            transform: watermarkTransform,\n          },\n          functions: {\n            description:\n              'High and low watermarks for functions in the format of `<high>,<low>`',\n            argument: '<watermarks>',\n            transform: watermarkTransform,\n          },\n        },\n      },\n      changed: {\n        description:\n          'Collect coverage only for files changed since a specified commit or branch (e.g., `origin/main` or `HEAD~1`). Inherits value from `--changed` by default.',\n        argument: '<commit/branch>',\n        transform(value) {\n          if (value === 'true' || value === 'yes' || value === true) {\n            return true\n          }\n          if (value === 'false' || value === 'no' || value === false) {\n            return false\n          }\n          return value\n        },\n      },\n    },\n  },\n  mode: {\n    description: 'Override Vite mode (default: `test` or `benchmark`)',\n    argument: '<name>',\n  },\n  isolate: {\n    description:\n      'Run every test file in isolation. To disable isolation, use `--no-isolate` (default: `true`)',\n  },\n  globals: {\n    description: 'Inject apis globally',\n  },\n  dom: {\n    description: 'Mock browser API with happy-dom',\n  },\n  browser: {\n    description:\n      'Run tests in the browser. Equivalent to `--browser.enabled` (default: `false`)',\n    argument: '<name>',\n    transform(browser) {\n      if (typeof browser === 'boolean') {\n        return { enabled: browser }\n      }\n      if (browser === 'true' || browser === 'false') {\n        return { enabled: browser === 'true' }\n      }\n      if (browser === 'yes' || browser === 'no') {\n        return { enabled: browser === 'yes' }\n      }\n      if (typeof browser === 'string') {\n        return { name: browser }\n      }\n      return browser\n    },\n    subcommands: {\n      enabled: {\n        description:\n          'Run tests in the browser. Equivalent to `--browser.enabled` (default: `false`)',\n      },\n      name: {\n        description:\n          'Run all tests in a specific browser. Some browsers are only available for specific providers (see `--browser.provider`).',\n        argument: '<name>',\n      },\n      headless: {\n        description:\n          'Run the browser in headless mode (i.e. without opening the GUI (Graphical User Interface)). If you are running Vitest in CI, it will be enabled by default (default: `process.env.CI`)',\n      },\n      api: {\n        description:\n          'Specify options for the browser API server. Does not affect the --api option',\n        argument: '[port]',\n        subcommands: apiConfig(defaultBrowserPort),\n      },\n      isolate: {\n        description:\n          'Run every browser test file in isolation. To disable isolation, use `--browser.isolate=false` (default: `true`)',\n      },\n      ui: {\n        description:\n          'Show Vitest UI when running tests (default: `!process.env.CI`)',\n      },\n      detailsPanelPosition: {\n        description:\n          'Default position for the details panel in browser mode. Either `right` (horizontal split) or `bottom` (vertical split) (default: `right`)',\n        argument: '<position>',\n      },\n      fileParallelism: {\n        description:\n          'Should browser test files run in parallel. Use `--browser.fileParallelism=false` to disable (default: `true`)',\n      },\n      connectTimeout: {\n        description: 'If connection to the browser takes longer, the test suite will fail (default: `60_000`)',\n        argument: '<timeout>',\n      },\n      trackUnhandledErrors: {\n        description: 'Control if Vitest catches uncaught exceptions so they can be reported (default: `true`)',\n      },\n      trace: {\n        description: 'Enable trace view mode. Supported: \"on\", \"off\", \"on-first-retry\", \"on-all-retries\", \"retain-on-failure\".',\n        argument: '<mode>',\n        subcommands: null, // don't support subcommands\n        transform(value) {\n          return { mode: value }\n        },\n      },\n      orchestratorScripts: null,\n      commands: null,\n      viewport: null,\n      screenshotDirectory: null,\n      screenshotFailures: null,\n      locators: null,\n      testerHtmlPath: null,\n      instances: null,\n      expect: null,\n      provider: null,\n    },\n  },\n  pool: {\n    description:\n      'Specify pool, if not running in the browser (default: `forks`)',\n    argument: '<pool>',\n    subcommands: null, // don't support custom objects\n  },\n  execArgv: {\n    description: 'Pass additional arguments to `node` process when spawning `worker_threads` or `child_process`.',\n    argument: '<option>',\n    array: true,\n  },\n  vmMemoryLimit: {\n    description:\n      'Memory limit for VM pools. If you see memory leaks, try to tinker this value.',\n    argument: '<limit>',\n  },\n  fileParallelism: {\n    description:\n      'Should all test files run in parallel. Use `--no-file-parallelism` to disable (default: `true`)',\n  },\n  maxWorkers: {\n    description: 'Maximum number or percentage of workers to run tests in',\n    argument: '<workers>',\n  },\n  environment: {\n    description:\n      'Specify runner environment, if not running in the browser (default: `node`)',\n    argument: '<name>',\n    subcommands: null, // don't support custom objects\n  },\n  passWithNoTests: {\n    description: 'Pass when no tests are found',\n  },\n  logHeapUsage: {\n    description: 'Show the size of heap for each test when running in node',\n  },\n  detectAsyncLeaks: {\n    description: 'Detect asynchronous resources leaking from the test file (default: `false`)',\n  },\n  allowOnly: {\n    description:\n      'Allow tests and suites that are marked as only (default: `!process.env.CI`)',\n  },\n  dangerouslyIgnoreUnhandledErrors: {\n    description: 'Ignore any unhandled errors that occur',\n  },\n  shard: {\n    description: 'Test suite shard to execute in a format of `<index>/<count>`',\n    argument: '<shards>',\n  },\n  changed: {\n    description:\n      'Run tests that are affected by the changed files (default: `false`)',\n    argument: '[since]',\n  },\n  sequence: {\n    description: 'Options for how tests should be sorted',\n    argument: '<options>',\n    subcommands: {\n      shuffle: {\n        description:\n          'Run files and tests in a random order. Enabling this option will impact Vitest\\'s cache and have a performance impact. May be useful to find tests that accidentally depend on another run previously (default: `false`)',\n        argument: '',\n        subcommands: {\n          files: {\n            description:\n              'Run files in a random order. Long running tests will not start earlier if you enable this option. (default: `false`)',\n          },\n          tests: {\n            description: 'Run tests in a random order (default: `false`)',\n          },\n        },\n      },\n      concurrent: {\n        description: 'Make tests run in parallel (default: `false`)',\n      },\n      seed: {\n        description:\n          'Set the randomization seed. This option will have no effect if `--sequence.shuffle` is falsy. Visit [\"Random Seed\" page](https://en.wikipedia.org/wiki/Random_seed) for more information',\n        argument: '<seed>',\n      },\n      hooks: {\n        description:\n          'Changes the order in which hooks are executed. Accepted values are: \"stack\", \"list\" and \"parallel\". Visit [`sequence.hooks`](https://vitest.dev/config/sequence#sequence-hooks) for more information (default: `\"parallel\"`)',\n        argument: '<order>',\n      },\n      setupFiles: {\n        description:\n          'Changes the order in which setup files are executed. Accepted values are: \"list\" and \"parallel\". If set to \"list\", will run setup files in the order they are defined. If set to \"parallel\", will run setup files in parallel (default: `\"parallel\"`)',\n        argument: '<order>',\n      },\n      groupOrder: null,\n    },\n  },\n  inspect: {\n    description: 'Enable Node.js inspector (default: `127.0.0.1:9229`)',\n    argument: '[[host:]port]',\n    transform(portOrEnabled) {\n      if (\n        portOrEnabled === 0\n        || portOrEnabled === 'true'\n        || portOrEnabled === 'yes'\n      ) {\n        return true\n      }\n      if (portOrEnabled === 'false' || portOrEnabled === 'no') {\n        return false\n      }\n      return portOrEnabled\n    },\n  },\n  inspectBrk: {\n    description: 'Enable Node.js inspector and break before the test starts',\n    argument: '[[host:]port]',\n    transform(portOrEnabled) {\n      if (\n        portOrEnabled === 0\n        || portOrEnabled === 'true'\n        || portOrEnabled === 'yes'\n      ) {\n        return true\n      }\n      if (portOrEnabled === 'false' || portOrEnabled === 'no') {\n        return false\n      }\n      return portOrEnabled\n    },\n  },\n  inspector: null,\n  testTimeout: {\n    description: 'Default timeout of a test in milliseconds (default: `5000`). Use `0` to disable timeout completely.',\n    argument: '<timeout>',\n  },\n  hookTimeout: {\n    description: 'Default hook timeout in milliseconds (default: `10000`). Use `0` to disable timeout completely.',\n    argument: '<timeout>',\n  },\n  bail: {\n    description:\n      'Stop test execution when given number of tests have failed (default: `0`)',\n    argument: '<number>',\n  },\n  retry: {\n    description:\n      'Retry the test specific number of times if it fails (default: `0`)',\n    argument: '<times>',\n    subcommands: {\n      count: {\n        description:\n          'Number of times to retry a test if it fails (default: `0`)',\n        argument: '<times>',\n      },\n      delay: {\n        description:\n          'Delay in milliseconds between retry attempts (default: `0`)',\n        argument: '<ms>',\n      },\n      condition: {\n        description:\n          'Regex pattern to match error messages that should trigger a retry. Only errors matching this pattern will cause a retry (default: retry on all errors)',\n        argument: '<pattern>',\n        transform: (value) => {\n          if (typeof value === 'string') {\n            return new RegExp(value, 'i')\n          }\n          return value\n        },\n      },\n    },\n  },\n  diff: {\n    description:\n      'DiffOptions object or a path to a module which exports DiffOptions object',\n    argument: '<path>',\n    subcommands: {\n      aAnnotation: {\n        description: 'Annotation for expected lines (default: `Expected`)',\n        argument: '<annotation>',\n      },\n      aIndicator: {\n        description: 'Indicator for expected lines (default: `-`)',\n        argument: '<indicator>',\n      },\n      bAnnotation: {\n        description: 'Annotation for received lines (default: `Received`)',\n        argument: '<annotation>',\n      },\n      bIndicator: {\n        description: 'Indicator for received lines (default: `+`)',\n        argument: '<indicator>',\n      },\n      commonIndicator: {\n        description: 'Indicator for common lines (default: ` `)',\n        argument: '<indicator>',\n      },\n      contextLines: {\n        description: 'Number of lines of context to show around each change (default: `5`)',\n        argument: '<lines>',\n      },\n      emptyFirstOrLastLinePlaceholder: {\n        description: 'Placeholder for an empty first or last line (default: `\"\"`)',\n        argument: '<placeholder>',\n      },\n      expand: {\n        description: 'Expand all common lines (default: `true`)',\n      },\n      includeChangeCounts: {\n        description: 'Include comparison counts in diff output (default: `false`)',\n      },\n      omitAnnotationLines: {\n        description: 'Omit annotation lines from the output (default: `false`)',\n      },\n      printBasicPrototype: {\n        description: 'Print basic prototype Object and Array (default: `true`)',\n      },\n      maxDepth: {\n        description: 'Limit the depth to recurse when printing nested objects (default: `20`)',\n        argument: '<maxDepth>',\n      },\n      truncateThreshold: {\n        description: 'Number of lines to show before and after each change (default: `0`)',\n        argument: '<threshold>',\n      },\n      truncateAnnotation: {\n        description: 'Annotation for truncated lines (default: `... Diff result is truncated`)',\n        argument: '<annotation>',\n      },\n    },\n  },\n  exclude: {\n    description: 'Additional file globs to be excluded from test',\n    argument: '<glob>',\n    array: true,\n  },\n  expandSnapshotDiff: {\n    description: 'Show full diff when snapshot fails',\n  },\n  disableConsoleIntercept: {\n    description:\n      'Disable automatic interception of console logging (default: `false`)',\n  },\n  typecheck: {\n    description: 'Enable typechecking alongside tests (default: `false`)',\n    argument: '', // allow boolean\n    transform: transformNestedBoolean,\n    subcommands: {\n      enabled: {\n        description: 'Enable typechecking alongside tests (default: `false`)',\n      },\n      only: {\n        description:\n          'Run only typecheck tests. This automatically enables typecheck (default: `false`)',\n      },\n      checker: {\n        description:\n          'Specify the typechecker to use. Available values are: \"tsc\" and \"vue-tsc\" and a path to an executable (default: `\"tsc\"`)',\n        argument: '<name>',\n        subcommands: null,\n      },\n      allowJs: {\n        description:\n          'Allow JavaScript files to be typechecked. By default takes the value from tsconfig.json',\n      },\n      ignoreSourceErrors: {\n        description: 'Ignore type errors from source files',\n      },\n      tsconfig: {\n        description: 'Path to a custom tsconfig file',\n        argument: '<path>',\n        normalize: true,\n      },\n      spawnTimeout: {\n        description: 'Minimum time in milliseconds it takes to spawn the typechecker',\n        argument: '<time>',\n      },\n      include: null,\n      exclude: null,\n    },\n  },\n  project: {\n    description:\n      'The name of the project to run if you are using Vitest workspace feature. This can be repeated for multiple projects: `--project=1 --project=2`. You can also filter projects using wildcards like `--project=packages*`, and exclude projects with `--project=!pattern`.',\n    argument: '<name>',\n    array: true,\n  },\n  slowTestThreshold: {\n    description:\n      'Threshold in milliseconds for a test or suite to be considered slow (default: `300`)',\n    argument: '<threshold>',\n  },\n  teardownTimeout: {\n    description:\n      'Default timeout of a teardown function in milliseconds (default: `10000`)',\n    argument: '<timeout>',\n  },\n  cache: {\n    description: 'Enable cache',\n    argument: '', // allow only boolean\n    subcommands: {\n      dir: null,\n    },\n    default: true,\n    // cache can only be \"false\" or an object\n    transform(cache) {\n      if (typeof cache !== 'boolean' && cache) {\n        throw new Error('--cache.dir is deprecated')\n      }\n      if (cache) {\n        return {}\n      }\n      return cache\n    },\n  },\n  maxConcurrency: {\n    description: 'Maximum number of concurrent tests and suites during test file execution (default: `5`)',\n    argument: '<number>',\n  },\n  expect: {\n    description: 'Configuration options for `expect()` matches',\n    argument: '', // no displayed\n    subcommands: {\n      requireAssertions: {\n        description: 'Require that all tests have at least one assertion',\n      },\n      poll: {\n        description: 'Default options for `expect.poll()`',\n        argument: '',\n        subcommands: {\n          interval: {\n            description:\n              'Poll interval in milliseconds for `expect.poll()` assertions (default: `50`)',\n            argument: '<interval>',\n          },\n          timeout: {\n            description:\n              'Poll timeout in milliseconds for `expect.poll()` assertions (default: `1000`)',\n            argument: '<timeout>',\n          },\n        },\n        transform(value) {\n          if (typeof value !== 'object') {\n            throw new TypeError(\n              `Unexpected value for --expect.poll: ${value}. If you need to configure timeout, use --expect.poll.timeout=<timeout>`,\n            )\n          }\n          return value\n        },\n      },\n    },\n    transform(value) {\n      if (typeof value !== 'object') {\n        throw new TypeError(\n          `Unexpected value for --expect: ${value}. If you need to configure expect options, use --expect.{name}=<value> syntax`,\n        )\n      }\n      return value\n    },\n  },\n  printConsoleTrace: {\n    description: 'Always print console stack traces',\n  },\n  includeTaskLocation: {\n    description: 'Collect test and suite locations in the `location` property',\n  },\n  attachmentsDir: {\n    description: 'The directory where attachments from `context.annotate` are stored in (default: `.vitest-attachments`)',\n    argument: '<dir>',\n  },\n\n  // CLI only options\n  run: {\n    description: 'Disable watch mode',\n  },\n  color: {\n    description: 'Removes colors from the console output',\n    alias: 'no-color',\n  },\n  clearScreen: {\n    description:\n      'Clear terminal screen when re-running tests during watch mode (default: `true`)',\n  },\n  configLoader: {\n    description:\n      'Use `bundle` to bundle the config with esbuild or `runner` (experimental) to process it on the fly. This is only available in vite version 6.1.0 and above. (default: `bundle`)',\n    argument: '<loader>',\n  },\n  standalone: {\n    description:\n      'Start Vitest without running tests. Tests will be running only on change. This option is ignored when CLI file filters are passed. (default: `false`)',\n  },\n  mergeReports: {\n    description:\n      'Path to a blob reports directory. If this options is used, Vitest won\\'t run any tests, it will only report previously recorded tests',\n    argument: '[path]',\n    transform(value) {\n      if (!value || typeof value === 'boolean') {\n        return '.vitest-reports'\n      }\n      return value\n    },\n  },\n  listTags: {\n    description: 'List all available tags instead of running tests. `--list-tags=json` will output tags in JSON format, unless there are no tags.',\n    argument: '[type]',\n  },\n  clearCache: {\n    description: 'Delete all Vitest caches, including `experimental.fsModuleCache`, without running any tests. This will reduce the performance in the subsequent test run.',\n  },\n  tagsFilter: {\n    description: 'Run only tests with the specified tags. You can use logical operators `&&` (and), `||` (or) and `!` (not) to create complex expressions, see [Test Tags](https://vitest.dev/guide/test-tags#syntax) for more information.',\n    argument: '<expression>',\n    array: true,\n  },\n  strictTags: {\n    description: 'Should Vitest throw an error if test has a tag that is not defined in the config. (default: `true`)',\n  },\n\n  experimental: {\n    description: 'Experimental features.',\n    argument: '<features>',\n    subcommands: {\n      fsModuleCache: {\n        description: 'Enable caching of modules on the file system between reruns.',\n      },\n      fsModuleCachePath: null,\n      openTelemetry: null,\n      importDurations: {\n        description: 'Configure import duration collection and CLI display. Note that UI\\'s \"Module Graph\" tab can always show import breakdown regardless of the `print` setting.',\n        argument: '',\n        transform(value) {\n          if (typeof value === 'boolean') {\n            return { print: value }\n          }\n          return value\n        },\n        subcommands: {\n          print: {\n            description: 'When to print import breakdown to CLI terminal. Use `true` to always print, `false` to never print, or `on-warn` to print only when imports exceed the warn threshold (default: false).',\n            argument: '<boolean|on-warn>',\n            transform(value) {\n              if (value === 'on-warn') {\n                return 'on-warn'\n              }\n              return value\n            },\n          },\n          limit: {\n            description: 'Maximum number of imports to collect and display (default: 0, or 10 if print or UI is enabled).',\n            argument: '<number>',\n          },\n          failOnDanger: {\n            description: 'Fail the test run if any import exceeds the danger threshold (default: false).',\n          },\n          thresholds: {\n            description: 'Duration thresholds in milliseconds for coloring and warnings.',\n            argument: '',\n            subcommands: {\n              warn: {\n                description: 'Warning threshold - imports exceeding this are shown in yellow/orange (default: 100).',\n                argument: '<number>',\n              },\n              danger: {\n                description: 'Danger threshold - imports exceeding this are shown in red (default: 500).',\n                argument: '<number>',\n              },\n            },\n          },\n        },\n      },\n      viteModuleRunner: {\n        description: 'Control whether Vitest uses Vite\\'s module runner to run the code or fallback to the native `import`. (default: `true`)',\n      },\n      nodeLoader: {\n        description: 'Controls whether Vitest will use Node.js Loader API to process in-source or mocked files. This has no effect if `viteModuleRunner` is enabled. Disabling this can increase performance. (default: `true`)',\n      },\n    },\n  },\n  // disable CLI options\n  cliExclude: null,\n  server: null,\n  setupFiles: null,\n  globalSetup: null,\n  snapshotFormat: null,\n  snapshotSerializers: null,\n  includeSource: null,\n  alias: null,\n  env: null,\n  environmentOptions: null,\n  unstubEnvs: null,\n  related: null,\n  restoreMocks: null,\n  runner: null,\n  mockReset: null,\n  forceRerunTriggers: null,\n  unstubGlobals: null,\n  uiBase: null,\n  benchmark: null,\n  include: null,\n  fakeTimers: null,\n  chaiConfig: null,\n  clearMocks: null,\n  css: null,\n  deps: null,\n  name: null,\n  snapshotEnvironment: null,\n  compare: null,\n  outputJson: null,\n  json: null,\n  provide: null,\n  filesOnly: null,\n  staticParse: null,\n  staticParseConcurrency: null,\n  projects: null,\n  watchTriggerPatterns: null,\n  tags: null,\n}\n\nexport const benchCliOptionsConfig: Pick<\n  VitestCLIOptions,\n  'compare' | 'outputJson'\n> = {\n  compare: {\n    description: 'Benchmark output file to compare against',\n    argument: '<filename>',\n  },\n  outputJson: {\n    description: 'Benchmark output file',\n    argument: '<filename>',\n  },\n}\n\nexport const collectCliOptionsConfig: VitestCLIOptions = {\n  ...cliOptionsConfig,\n  json: {\n    description: 'Print collected tests as JSON or write to a file (Default: false)',\n    argument: '[true/path]',\n  },\n  filesOnly: {\n    description: 'Print only test files with out the test cases',\n  },\n  staticParse: {\n    description: 'Parse files statically instead of running them to collect tests (default: false)',\n  },\n  staticParseConcurrency: {\n    description: 'How many tests to process at the same time (default: os.availableParallelism())',\n    argument: '<limit>',\n  },\n  changed: {\n    description: 'Print only tests that are affected by the changed files (default: `false`)',\n    argument: '[since]',\n  },\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cli/completions.ts",
    "content": "import type { CAC } from 'cac'\nimport tab from '@bomb.sh/tab/cac'\n\nexport async function setupTabCompletions(cli: CAC): Promise<void> {\n  await tab(cli, {\n    subCommands: {},\n    options: {\n      environment(complete) {\n        complete('node', 'Node.js environment')\n        complete('jsdom', 'JSDOM environment')\n        complete('happy-dom', 'Happy DOM environment')\n        complete('edge-runtime', 'Edge runtime environment')\n      },\n      pool(complete) {\n        complete('threads', 'Threads pool')\n        complete('forks', 'Forks pool')\n        complete('vmThreads', 'VM threads pool')\n        complete('vmForks', 'VM forks pool')\n      },\n      reporter(complete) {\n        complete('default', 'Default reporter')\n        complete('verbose', 'Verbose reporter')\n        complete('dot', 'Dot reporter')\n        complete('json', 'JSON reporter')\n        complete('junit', 'JUnit reporter')\n        complete('html', 'HTML reporter')\n        complete('tap', 'TAP reporter')\n        complete('tap-flat', 'TAP flat reporter')\n        complete('hanging-process', 'Hanging process reporter')\n      },\n      'coverage.reporter': function (complete) {\n        complete('text', 'Text coverage reporter')\n        complete('html', 'HTML coverage reporter')\n        complete('clover', 'Clover coverage reporter')\n        complete('json', 'JSON coverage reporter')\n        complete('json-summary', 'JSON summary coverage reporter')\n        complete('lcov', 'LCOV coverage reporter')\n        complete('lcovonly', 'LCOV only coverage reporter')\n        complete('teamcity', 'TeamCity coverage reporter')\n        complete('cobertura', 'Cobertura coverage reporter')\n      },\n      'browser.name': function (complete) {\n        complete('chromium', 'Chromium')\n        complete('firefox', 'Mozilla Firefox')\n        complete('safari', 'Safari')\n        complete('chrome', 'Google Chrome')\n        complete('edge', 'Microsoft Edge')\n      },\n      silent(complete) {\n        complete('true', 'Enable silent mode')\n        complete('false', 'Disable silent mode')\n        complete('passed-only', 'Show logs from failing tests only')\n      },\n    },\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cli/filter.ts",
    "content": "import { groupBy } from '../../utils/base'\nimport { RangeLocationFilterProvidedError } from '../errors'\n\nexport function parseFilter(filter: string): FileFilter {\n  const colonIndex = filter.lastIndexOf(':')\n  if (colonIndex === -1) {\n    return { filename: filter }\n  }\n\n  const [parsedFilename, lineNumber] = [\n    filter.substring(0, colonIndex),\n    filter.substring(colonIndex + 1),\n  ]\n\n  if (lineNumber.match(/^\\d+$/)) {\n    return {\n      filename: parsedFilename,\n      lineNumber: Number.parseInt(lineNumber),\n    }\n  }\n  else if (lineNumber.match(/^\\d+-\\d+$/)) {\n    throw new RangeLocationFilterProvidedError(filter)\n  }\n  else {\n    return { filename: filter }\n  }\n}\n\nexport interface FileFilter {\n  filename: string\n  lineNumber?: undefined | number\n}\n\nexport function groupFilters(filters: FileFilter[]): Record<string, number[]> {\n  const groupedFilters_ = groupBy(filters, f => f.filename)\n  const groupedFilters = Object.fromEntries(Object.entries(groupedFilters_)\n    .map((entry) => {\n      const [filename, filters] = entry\n      const testLocations = filters.map(f => f.lineNumber)\n\n      return [\n        filename,\n        testLocations.filter(l => l !== undefined) as number[],\n      ]\n    }),\n  )\n\n  return groupedFilters\n}\n"
  },
  {
    "path": "packages/vitest/src/node/cli.ts",
    "content": "import { createCLI } from './cli/cac'\n\ncreateCLI().parse()\n"
  },
  {
    "path": "packages/vitest/src/node/config/resolveConfig.ts",
    "content": "import type { ResolvedConfig as ResolvedViteConfig } from 'vite'\nimport type { Vitest } from '../core'\nimport type { Logger } from '../logger'\nimport type { BenchmarkBuiltinReporters } from '../reporters'\nimport type { ResolvedBrowserOptions } from '../types/browser'\nimport type {\n  ApiConfig,\n  ResolvedConfig,\n  UserConfig,\n} from '../types/config'\nimport type { BaseCoverageOptions, CoverageReporterWithOptions } from '../types/coverage'\nimport crypto from 'node:crypto'\nimport { pathToFileURL } from 'node:url'\nimport { slash, toArray } from '@vitest/utils/helpers'\nimport { resolveModule } from 'local-pkg'\nimport { normalize, relative, resolve } from 'pathe'\nimport c from 'tinyrainbow'\nimport { mergeConfig } from 'vite'\nimport {\n  configFiles,\n  defaultBrowserPort,\n  defaultInspectPort,\n  defaultPort,\n} from '../../constants'\nimport { benchmarkConfigDefaults, configDefaults } from '../../defaults'\nimport { isAgent, isCI, stdProvider } from '../../utils/env'\nimport { getWorkersCountByPercentage } from '../../utils/workers'\nimport { BaseSequencer } from '../sequencers/BaseSequencer'\nimport { RandomSequencer } from '../sequencers/RandomSequencer'\n\nfunction resolvePath(path: string, root: string) {\n  return normalize(\n    /* @__PURE__ */ resolveModule(path, { paths: [root] })\n    ?? resolve(root, path),\n  )\n}\n\nfunction parseInspector(inspect: string | undefined | boolean | number) {\n  if (typeof inspect === 'boolean' || inspect === undefined) {\n    return {}\n  }\n  if (typeof inspect === 'number') {\n    return { port: inspect }\n  }\n\n  if (inspect.match(/https?:\\//)) {\n    throw new Error(\n      `Inspector host cannot be a URL. Use \"host:port\" instead of \"${inspect}\"`,\n    )\n  }\n\n  const [host, port] = inspect.split(':')\n  if (!port) {\n    return { host }\n  }\n  return { host, port: Number(port) || defaultInspectPort }\n}\n\n/**\n * @deprecated Internal function\n */\nexport function resolveApiServerConfig<Options extends ApiConfig & Omit<UserConfig, 'expect'>>(\n  options: Options,\n  defaultPort: number,\n  parentApi?: ApiConfig,\n  logger?: Logger,\n): ApiConfig | undefined {\n  let api: ApiConfig | undefined\n\n  if (options.ui && !options.api) {\n    api = { port: defaultPort }\n  }\n  else if (options.api === true) {\n    api = { port: defaultPort }\n  }\n  else if (typeof options.api === 'number') {\n    api = { port: options.api }\n  }\n\n  if (typeof options.api === 'object') {\n    if (api) {\n      if (options.api.port) {\n        api.port = options.api.port\n      }\n      if (options.api.strictPort) {\n        api.strictPort = options.api.strictPort\n      }\n      if (options.api.host) {\n        api.host = options.api.host\n      }\n    }\n    else {\n      api = { ...options.api }\n    }\n  }\n\n  if (api) {\n    if (!api.port && !api.middlewareMode) {\n      api.port = defaultPort\n    }\n  }\n  else {\n    api = { middlewareMode: true }\n  }\n\n  // if the API server is exposed to network, disable write operations by default\n  if (!api.middlewareMode && api.host && api.host !== 'localhost' && api.host !== '127.0.0.1') {\n    // assigned to browser\n    if (parentApi) {\n      if (api.allowWrite == null && api.allowExec == null) {\n        logger?.error(\n          c.yellow(\n            `${c.yellowBright(' WARNING ')} API server is exposed to network, disabling write and exec operations by default for security reasons. This can cause some APIs to not work as expected. Set \\`browser.api.allowExec\\` manually to hide this warning. See https://vitest.dev/config/browser/api for more details.`,\n          ),\n        )\n      }\n    }\n    api.allowWrite ??= parentApi?.allowWrite ?? false\n    api.allowExec ??= parentApi?.allowExec ?? false\n  }\n  else {\n    api.allowWrite ??= parentApi?.allowWrite ?? true\n    api.allowExec ??= parentApi?.allowExec ?? true\n  }\n\n  return api\n}\n\nfunction resolveInlineWorkerOption(value: string | number): number {\n  if (typeof value === 'string' && value.trim().endsWith('%')) {\n    return getWorkersCountByPercentage(value)\n  }\n  else {\n    return Number(value)\n  }\n}\n\nexport function resolveConfig(\n  vitest: Vitest,\n  options: UserConfig,\n  viteConfig: ResolvedViteConfig,\n): ResolvedConfig {\n  const mode = vitest.mode\n  const logger = vitest.logger\n  if (options.dom) {\n    if (\n      viteConfig.test?.environment != null\n      && viteConfig.test!.environment !== 'happy-dom'\n    ) {\n      logger.console.warn(\n        c.yellow(\n          `${c.inverse(c.yellow(' Vitest '))} Your config.test.environment (\"${\n            viteConfig.test.environment\n          }\") conflicts with --dom flag (\"happy-dom\"), ignoring \"${\n            viteConfig.test.environment\n          }\"`,\n        ),\n      )\n    }\n\n    options.environment = 'happy-dom'\n  }\n\n  const resolved = {\n    ...configDefaults,\n    ...options,\n    root: viteConfig.root,\n    mode,\n  } as any as ResolvedConfig\n\n  if (resolved.retry && typeof resolved.retry === 'object' && typeof resolved.retry.condition === 'function') {\n    logger.console.warn(\n      c.yellow('Warning: retry.condition function cannot be used inside a config file. '\n        + 'Use a RegExp pattern instead, or define the function in your test file.'),\n    )\n\n    resolved.retry = {\n      ...resolved.retry,\n      condition: undefined,\n    }\n  }\n\n  if (options.pool && typeof options.pool !== 'string') {\n    resolved.pool = options.pool.name\n    resolved.poolRunner = options.pool\n  }\n\n  if ('poolOptions' in resolved) {\n    logger.deprecate('`test.poolOptions` was removed in Vitest 4. All previous `poolOptions` are now top-level options. Please, refer to the migration guide: https://vitest.dev/guide/migration#pool-rework')\n  }\n\n  resolved.pool ??= 'forks'\n\n  resolved.project = toArray(resolved.project)\n  resolved.provide ??= {}\n\n  // shallow copy tags array to avoid mutating user config\n  resolved.tags = [...resolved.tags || []]\n  const definedTags = new Set<string>()\n  resolved.tags.forEach((tag) => {\n    if (!tag.name || typeof tag.name !== 'string') {\n      throw new Error(`Each tag defined in \"test.tags\" must have a \"name\" property, received: ${JSON.stringify(tag)}`)\n    }\n    if (definedTags.has(tag.name)) {\n      throw new Error(`Tag name \"${tag.name}\" is already defined in \"test.tags\". Tag names must be unique.`)\n    }\n    if (tag.name.match(/\\s/)) {\n      throw new Error(`Tag name \"${tag.name}\" is invalid. Tag names cannot contain spaces.`)\n    }\n    if (tag.name.match(/([!()*|&])/)) {\n      throw new Error(`Tag name \"${tag.name}\" is invalid. Tag names cannot contain \"!\", \"*\", \"&\", \"|\", \"(\", or \")\".`)\n    }\n    if (tag.name.match(/^\\s*(and|or|not)\\s*$/i)) {\n      throw new Error(`Tag name \"${tag.name}\" is invalid. Tag names cannot be a logical operator like \"and\", \"or\", \"not\".`)\n    }\n    if (typeof tag.retry === 'object' && typeof tag.retry.condition === 'function') {\n      throw new TypeError(`Tag \"${tag.name}\": retry.condition function cannot be used inside a config file. Use a RegExp pattern instead, or define the function in your test file.`)\n    }\n    if (tag.priority != null && (typeof tag.priority !== 'number' || tag.priority < 0)) {\n      throw new TypeError(`Tag \"${tag.name}\": priority must be a non-negative number.`)\n    }\n    definedTags.add(tag.name)\n  })\n\n  resolved.name = typeof options.name === 'string'\n    ? options.name\n    : (options.name?.label || '')\n\n  resolved.color = typeof options.name !== 'string' ? options.name?.color : undefined\n\n  if (resolved.environment === 'browser') {\n    throw new Error(`Looks like you set \"test.environment\" to \"browser\". To enable Browser Mode, use \"test.browser.enabled\" instead.`)\n  }\n\n  const inspector = resolved.inspect || resolved.inspectBrk\n\n  resolved.inspector = {\n    ...resolved.inspector,\n    ...parseInspector(inspector),\n    enabled: !!inspector,\n    waitForDebugger:\n      options.inspector?.waitForDebugger ?? !!resolved.inspectBrk,\n  }\n\n  if (viteConfig.base !== '/') {\n    resolved.base = viteConfig.base\n  }\n\n  resolved.clearScreen = resolved.clearScreen ?? viteConfig.clearScreen ?? true\n\n  if (options.shard) {\n    if (resolved.watch) {\n      throw new Error('You cannot use --shard option with enabled watch')\n    }\n\n    const [indexString, countString] = options.shard.split('/')\n    const index = Math.abs(Number.parseInt(indexString, 10))\n    const count = Math.abs(Number.parseInt(countString, 10))\n\n    if (Number.isNaN(count) || count <= 0) {\n      throw new Error('--shard <count> must be a positive number')\n    }\n\n    if (Number.isNaN(index) || index <= 0 || index > count) {\n      throw new Error(\n        '--shard <index> must be a positive number less then <count>',\n      )\n    }\n\n    resolved.shard = { index, count }\n  }\n\n  if (resolved.standalone && !resolved.watch) {\n    throw new Error(`Vitest standalone mode requires --watch`)\n  }\n\n  if (resolved.mergeReports && resolved.watch) {\n    throw new Error(`Cannot merge reports with --watch enabled`)\n  }\n\n  if (resolved.maxWorkers) {\n    resolved.maxWorkers = resolveInlineWorkerOption(resolved.maxWorkers)\n  }\n\n  // run benchmark sequentially by default\n  const fileParallelism = options.fileParallelism ?? mode !== 'benchmark'\n\n  if (!fileParallelism) {\n    // ignore user config, parallelism cannot be implemented without limiting workers\n    resolved.maxWorkers = 1\n  }\n\n  if (resolved.maxConcurrency === 0) {\n    logger.console.warn(\n      c.yellow(`The option \"maxConcurrency\" cannot be set to 0. Using default value ${configDefaults.maxConcurrency} instead.`),\n    )\n    resolved.maxConcurrency = configDefaults.maxConcurrency\n  }\n\n  if (resolved.inspect || resolved.inspectBrk) {\n    if (resolved.maxWorkers !== 1) {\n      const inspectOption = `--inspect${resolved.inspectBrk ? '-brk' : ''}`\n      throw new Error(\n        `You cannot use ${inspectOption} without \"--no-file-parallelism\"`,\n      )\n    }\n  }\n\n  // apply browser CLI options only if the config already has the browser config and not disabled manually\n  if (\n    vitest._cliOptions.browser\n    && resolved.browser\n    // if enabled is set to `false`, but CLI overrides it, then always override it\n    && (resolved.browser.enabled !== false || vitest._cliOptions.browser.enabled)\n  ) {\n    resolved.browser = mergeConfig(\n      resolved.browser,\n      vitest._cliOptions.browser,\n    ) as ResolvedBrowserOptions\n  }\n\n  resolved.browser ??= {} as any\n  const browser = resolved.browser\n\n  if (browser.enabled) {\n    const instances = browser.instances\n    if (!browser.instances) {\n      browser.instances = []\n    }\n\n    // use `chromium` by default when the preview provider is specified\n    // for a smoother experience. if chromium is not available, it will\n    // open the default browser anyway\n    if (!browser.instances.length && browser.provider?.name === 'preview') {\n      browser.instances = [{ browser: 'chromium' }]\n    }\n\n    if (browser.name && instances?.length) {\n      // --browser=chromium filters configs to a single one\n      browser.instances = browser.instances.filter(instance => instance.browser === browser.name)\n\n      // if `instances` were defined, but now they are empty,\n      // let's throw an error because the filter is invalid\n      if (!browser.instances.length) {\n        throw new Error([\n          `\"browser.instances\" was set in the config, but the array is empty. Define at least one browser config.`,\n          ` The \"browser.name\" was set to \"${browser.name}\" which filtered all configs (${instances.map(c => c.browser).join(', ')}). Did you mean to use another name?`,\n        ].join(''))\n      }\n    }\n  }\n\n  if (resolved.coverage.enabled && resolved.coverage.provider === 'istanbul' && resolved.experimental?.viteModuleRunner === false) {\n    throw new Error(`\"Istanbul\" coverage provider is not compatible with \"experimental.viteModuleRunner: false\". Please, enable \"viteModuleRunner\" or switch to \"v8\" coverage provider.`)\n  }\n\n  if (browser.enabled && resolved.detectAsyncLeaks) {\n    logger.console.warn(c.yellow('The option \"detectAsyncLeaks\" is not supported in browser mode and will be ignored.'))\n  }\n\n  const containsChromium = hasBrowserChromium(vitest, resolved)\n  const hasOnlyChromium = hasOnlyBrowserChromium(vitest, resolved)\n\n  // Browser-mode \"Chromium\" only features:\n  if (browser.enabled && (!containsChromium || !hasOnlyChromium)) {\n    const browserConfig = `\n{\n  browser: {\n    provider: ${browser.provider?.name || 'preview'}(),\n    instances: [\n      ${(browser.instances || []).map(i => `{ browser: '${i.browser}' }`).join(',\\n      ')}\n    ],\n  },\n}\n    `.trim()\n\n    const preferredProvider = (!browser.provider?.name || browser.provider.name === 'preview')\n      ? 'playwright'\n      : browser.provider.name\n    const preferredBrowser = preferredProvider === 'playwright' ? 'chromium' : 'chrome'\n    const correctExample = `\n{\n  browser: {\n    provider: ${preferredProvider}(),\n    instances: [\n      { browser: '${preferredBrowser}' }\n    ],\n  },\n}\n    `.trim()\n\n    // requires all projects to be chromium\n    if (!hasOnlyChromium && resolved.coverage.enabled && resolved.coverage.provider === 'v8') {\n      const coverageExample = `\n{\n  coverage: {\n    provider: 'istanbul',\n  },\n}\n      `.trim()\n\n      throw new Error(\n        `@vitest/coverage-v8 does not work with\\n${browserConfig}\\n`\n        + `\\nUse either:\\n${correctExample}`\n        + `\\n\\n...or change your coverage provider to:\\n${coverageExample}\\n`,\n      )\n    }\n\n    // ignores non-chromium browsers when there is at least one chromium project\n    if (!containsChromium && (resolved.inspect || resolved.inspectBrk)) {\n      const inspectOption = `--inspect${resolved.inspectBrk ? '-brk' : ''}`\n\n      throw new Error(\n        `${inspectOption} does not work with\\n${browserConfig}\\n`\n        + `\\nUse either:\\n${correctExample}`\n        + `\\n\\n...or disable ${inspectOption}\\n`,\n      )\n    }\n  }\n\n  resolved.coverage.reporter = resolveCoverageReporters(resolved.coverage.reporter)\n  if (resolved.coverage.changed === undefined && resolved.changed !== undefined) {\n    resolved.coverage.changed = resolved.changed\n  }\n\n  if (resolved.coverage.enabled && resolved.coverage.reportsDirectory) {\n    const reportsDirectory = resolve(\n      resolved.root,\n      resolved.coverage.reportsDirectory,\n    )\n\n    if (\n      reportsDirectory === resolved.root\n      || reportsDirectory === process.cwd()\n    ) {\n      throw new Error(\n        `You cannot set \"coverage.reportsDirectory\" as ${reportsDirectory}. Vitest needs to be able to remove this directory before test run`,\n      )\n    }\n\n    if (resolved.coverage.htmlDir) {\n      resolved.coverage.htmlDir = resolve(\n        resolved.root,\n        resolved.coverage.htmlDir,\n      )\n    }\n\n    // infer default htmlDir based on builtin reporter's html output location\n    if (!resolved.coverage.htmlDir) {\n      const htmlReporter = resolved.coverage.reporter.find(([name]) => name === 'html' || name === 'html-spa')\n      if (htmlReporter) {\n        const [, options] = htmlReporter\n        const subdir = options && typeof options === 'object' && 'subdir' in options && typeof options.subdir === 'string'\n          ? options.subdir\n          : undefined\n        resolved.coverage.htmlDir = resolve(reportsDirectory, subdir || '.')\n      }\n      else {\n        const lcovReporter = resolved.coverage.reporter.find(([name]) => name === 'lcov')\n        if (lcovReporter) {\n          resolved.coverage.htmlDir = resolve(reportsDirectory, 'lcov-report')\n        }\n      }\n    }\n  }\n\n  if (resolved.coverage.enabled && resolved.coverage.provider === 'custom' && resolved.coverage.customProviderModule) {\n    resolved.coverage.customProviderModule = resolvePath(\n      resolved.coverage.customProviderModule,\n      resolved.root,\n    )\n  }\n\n  resolved.expect ??= {}\n\n  resolved.deps ??= {}\n  resolved.deps.moduleDirectories ??= []\n\n  resolved.deps.optimizer ??= {}\n  resolved.deps.optimizer.ssr ??= {}\n  resolved.deps.optimizer.ssr.enabled ??= false\n  resolved.deps.optimizer.client ??= {}\n  resolved.deps.optimizer.client.enabled ??= false\n\n  resolved.deps.web ??= {}\n  resolved.deps.web.transformAssets ??= true\n  resolved.deps.web.transformCss ??= true\n  resolved.deps.web.transformGlobPattern ??= []\n\n  resolved.setupFiles = toArray(resolved.setupFiles || []).map(file =>\n    resolvePath(file, resolved.root),\n  )\n  resolved.globalSetup = toArray(resolved.globalSetup || []).map(file =>\n    resolvePath(file, resolved.root),\n  )\n\n  // Add hard-coded default coverage exclusions. These cannot be overidden by user config.\n  // Override original exclude array for cases where user re-uses same object in test.exclude.\n  resolved.coverage.exclude = [\n    ...resolved.coverage.exclude,\n\n    // Exclude setup files\n    ...resolved.setupFiles.map(\n      file =>\n        `${resolved.coverage.allowExternal ? '**/' : ''}${relative(\n          resolved.root,\n          file,\n        )}`,\n    ),\n\n    // Exclude test files\n    ...resolved.include,\n\n    // Configs\n    resolved.config && slash(resolved.config),\n    ...configFiles,\n\n    // Vite internal\n    '**\\/virtual:*',\n    '**\\/__x00__*',\n\n    '**/node_modules/**',\n  ].filter(pattern => typeof pattern === 'string')\n\n  resolved.forceRerunTriggers = [\n    ...resolved.forceRerunTriggers,\n    ...resolved.setupFiles,\n  ]\n\n  if (resolved.cliExclude) {\n    resolved.exclude.push(...resolved.cliExclude)\n  }\n\n  if (resolved.runner) {\n    resolved.runner = resolvePath(resolved.runner, resolved.root)\n  }\n\n  resolved.attachmentsDir = resolve(\n    resolved.root,\n    resolved.attachmentsDir ?? '.vitest-attachments',\n  )\n\n  if (resolved.snapshotEnvironment) {\n    resolved.snapshotEnvironment = resolvePath(\n      resolved.snapshotEnvironment,\n      resolved.root,\n    )\n  }\n\n  resolved.testNamePattern = resolved.testNamePattern\n    ? resolved.testNamePattern instanceof RegExp\n      ? resolved.testNamePattern\n      : new RegExp(resolved.testNamePattern)\n    : undefined\n\n  if (resolved.snapshotFormat && 'plugins' in resolved.snapshotFormat) {\n    (resolved.snapshotFormat as any).plugins = []\n    // TODO: support it via separate config (like DiffOptions) or via `Function.toString()`\n    if (typeof resolved.snapshotFormat.compareKeys === 'function') {\n      throw new TypeError(`\"snapshotFormat.compareKeys\" function is not supported.`)\n    }\n  }\n\n  const UPDATE_SNAPSHOT = resolved.update || process.env.UPDATE_SNAPSHOT\n  resolved.snapshotOptions = {\n    expand: resolved.expandSnapshotDiff ?? false,\n    snapshotFormat: resolved.snapshotFormat || {},\n    updateSnapshot:\n      UPDATE_SNAPSHOT === 'all' || UPDATE_SNAPSHOT === 'new' || UPDATE_SNAPSHOT === 'none'\n        ? UPDATE_SNAPSHOT\n        : isCI && !UPDATE_SNAPSHOT ? 'none' : UPDATE_SNAPSHOT ? 'all' : 'new',\n    resolveSnapshotPath: options.resolveSnapshotPath,\n    // resolved inside the worker\n    snapshotEnvironment: null as any,\n  }\n\n  resolved.snapshotSerializers ??= []\n  resolved.snapshotSerializers = resolved.snapshotSerializers.map(file =>\n    resolvePath(file, resolved.root),\n  )\n  resolved.forceRerunTriggers.push(...resolved.snapshotSerializers)\n\n  if (options.resolveSnapshotPath) {\n    delete (resolved as any).resolveSnapshotPath\n  }\n\n  resolved.execArgv ??= []\n  resolved.pool ??= 'threads'\n\n  if (\n    resolved.pool === 'vmForks'\n    || resolved.pool === 'vmThreads'\n    || resolved.pool === 'typescript'\n  ) {\n    resolved.isolate = false\n  }\n\n  if (process.env.VITEST_MAX_WORKERS) {\n    resolved.maxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS)\n  }\n\n  if (mode === 'benchmark') {\n    resolved.benchmark = {\n      ...benchmarkConfigDefaults,\n      ...resolved.benchmark,\n    }\n    // override test config\n    resolved.coverage.enabled = false\n    resolved.typecheck.enabled = false\n    resolved.include = resolved.benchmark.include\n    resolved.exclude = resolved.benchmark.exclude\n    resolved.includeSource = resolved.benchmark.includeSource\n    const reporters = Array.from(\n      new Set<BenchmarkBuiltinReporters>([\n        ...toArray(resolved.benchmark.reporters),\n        // @ts-expect-error reporter is CLI flag\n        ...toArray(options.reporter),\n      ]),\n    ).filter(Boolean)\n    if (reporters.length) {\n      resolved.benchmark.reporters = reporters\n    }\n    else {\n      resolved.benchmark.reporters = ['default']\n    }\n\n    if (options.outputFile) {\n      resolved.benchmark.outputFile = options.outputFile\n    }\n\n    // --compare from cli\n    if (options.compare) {\n      resolved.benchmark.compare = options.compare\n    }\n    if (options.outputJson) {\n      resolved.benchmark.outputJson = options.outputJson\n    }\n  }\n\n  if (typeof resolved.diff === 'string') {\n    resolved.diff = resolvePath(resolved.diff, resolved.root)\n    resolved.forceRerunTriggers.push(resolved.diff)\n  }\n\n  // the server has been created, we don't need to override vite.server options\n  const api = resolveApiServerConfig(options, defaultPort)\n  resolved.api = { ...api, token: __VITEST_GENERATE_UI_TOKEN__ ? crypto.randomUUID() : '0' }\n\n  if (options.related) {\n    resolved.related = toArray(options.related).map(file =>\n      resolve(resolved.root, file),\n    )\n  }\n\n  /*\n   * Reporters can be defined in many different ways:\n   * { reporter: 'json' }\n   * { reporter: { onFinish() { method() } } }\n   * { reporter: ['json', { onFinish() { method() } }] }\n   * { reporter: [[ 'json' ]] }\n   * { reporter: [[ 'json' ], 'html'] }\n   * { reporter: [[ 'json', { outputFile: 'test.json' } ], 'html'] }\n   */\n  if (options.reporters) {\n    if (!Array.isArray(options.reporters)) {\n      // Reporter name, e.g. { reporters: 'json' }\n      if (typeof options.reporters === 'string') {\n        resolved.reporters = [[options.reporters, {}]]\n      }\n      // Inline reporter e.g. { reporters: { onFinish() { method() } } }\n      else {\n        resolved.reporters = [options.reporters]\n      }\n    }\n    // It's an array of reporters\n    else {\n      resolved.reporters = []\n\n      for (const reporter of options.reporters) {\n        if (Array.isArray(reporter)) {\n          // Reporter with options, e.g. { reporters: [ [ 'json', { outputFile: 'test.json' } ] ] }\n          resolved.reporters.push([reporter[0], reporter[1] as Record<string, unknown> || {}])\n        }\n        else if (typeof reporter === 'string') {\n          // Reporter name in array, e.g. { reporters: [\"html\", \"json\"]}\n          resolved.reporters.push([reporter, {}])\n        }\n        else {\n          // Inline reporter, e.g. { reporter: [{ onFinish() { method() } }] }\n          resolved.reporters.push(reporter)\n        }\n      }\n    }\n  }\n\n  if (mode !== 'benchmark') {\n    // @ts-expect-error \"reporter\" is from CLI, should be absolute to the running directory\n    // it is passed down as \"vitest --reporter ../reporter.js\"\n    const reportersFromCLI = resolved.reporter\n\n    const cliReporters = toArray(reportersFromCLI || []).map(\n      (reporter: string) => {\n        // ./reporter.js || ../reporter.js, but not .reporters/reporter.js\n        if (/^\\.\\.?\\//.test(reporter)) {\n          return resolve(process.cwd(), reporter)\n        }\n        return reporter\n      },\n    )\n\n    if (cliReporters.length) {\n      // When CLI reporters are specified, preserve options from config file\n      const configReportersMap = new Map<string, Record<string, unknown>>()\n\n      // Build a map of reporter names to their options from the config\n      for (const reporter of resolved.reporters) {\n        if (Array.isArray(reporter)) {\n          const [reporterName, reporterOptions] = reporter\n          if (typeof reporterName === 'string') {\n            configReportersMap.set(reporterName, reporterOptions as Record<string, unknown>)\n          }\n        }\n      }\n\n      resolved.reporters = Array.from(new Set(toArray(cliReporters)))\n        .filter(Boolean)\n        .map(reporter => [reporter, configReportersMap.get(reporter) || {}])\n    }\n  }\n\n  if (!resolved.reporters.length) {\n    resolved.reporters.push([isAgent ? 'agent' : 'default', {}])\n\n    // also enable github-actions reporter as a default\n    if (process.env.GITHUB_ACTIONS === 'true') {\n      resolved.reporters.push(['github-actions', {}])\n    }\n  }\n\n  if (resolved.changed) {\n    resolved.passWithNoTests ??= true\n  }\n\n  resolved.css ??= {}\n  if (typeof resolved.css === 'object') {\n    resolved.css.modules ??= {}\n    resolved.css.modules.classNameStrategy ??= 'stable'\n  }\n\n  if (resolved.cache !== false) {\n    if (resolved.cache && typeof resolved.cache.dir === 'string') {\n      vitest.logger.deprecate(\n        `\"cache.dir\" is deprecated, use Vite's \"cacheDir\" instead if you want to change the cache director. Note caches will be written to \"cacheDir\\/vitest\"`,\n      )\n    }\n\n    resolved.cache = { dir: viteConfig.cacheDir }\n  }\n\n  resolved.sequence ??= {} as any\n  if (\n    resolved.sequence.shuffle\n    && typeof resolved.sequence.shuffle === 'object'\n  ) {\n    const { files, tests } = resolved.sequence.shuffle\n    resolved.sequence.sequencer ??= files ? RandomSequencer : BaseSequencer\n    resolved.sequence.shuffle = tests\n  }\n  if (!resolved.sequence?.sequencer) {\n    // CLI flag has higher priority\n    resolved.sequence.sequencer = resolved.sequence.shuffle\n      ? RandomSequencer\n      : BaseSequencer\n  }\n  resolved.sequence.groupOrder ??= 0\n  resolved.sequence.hooks ??= 'stack'\n  // Set seed if either files or tests are shuffled\n  if (resolved.sequence.sequencer === RandomSequencer || resolved.sequence.shuffle) {\n    resolved.sequence.seed ??= Date.now()\n  }\n\n  resolved.typecheck = {\n    ...configDefaults.typecheck,\n    ...resolved.typecheck,\n  }\n\n  resolved.typecheck ??= {} as any\n  resolved.typecheck.enabled ??= false\n\n  if (resolved.typecheck.enabled) {\n    logger.console.warn(\n      c.yellow(\n        'Testing types with tsc and vue-tsc is an experimental feature.\\nBreaking changes might not follow SemVer, please pin Vitest\\'s version when using it.',\n      ),\n    )\n  }\n\n  resolved.browser.enabled ??= false\n  resolved.browser.headless ??= isCI\n  if (resolved.browser.isolate) {\n    logger.console.warn(\n      c.yellow('`browser.isolate` is deprecated. Use top-level `isolate` instead.'),\n    )\n  }\n  resolved.browser.isolate ??= resolved.isolate ?? true\n  resolved.browser.fileParallelism\n    ??= options.fileParallelism ?? mode !== 'benchmark'\n  // disable in headless mode by default, and if CI is detected\n  resolved.browser.ui ??= resolved.browser.headless === true ? false : !isCI\n  resolved.browser.commands ??= {}\n  resolved.browser.detailsPanelPosition ??= 'right'\n  if (resolved.browser.screenshotDirectory) {\n    resolved.browser.screenshotDirectory = resolve(\n      resolved.root,\n      resolved.browser.screenshotDirectory,\n    )\n  }\n\n  if (resolved.inspector.enabled) {\n    resolved.browser.trackUnhandledErrors ??= false\n  }\n\n  resolved.browser.viewport ??= {} as any\n  resolved.browser.viewport.width ??= 414\n  resolved.browser.viewport.height ??= 896\n\n  resolved.browser.locators ??= {} as any\n  resolved.browser.locators.testIdAttribute ??= 'data-testid'\n\n  if (typeof resolved.browser.provider === 'string') {\n    const source = `@vitest/browser-${resolved.browser.provider}`\n    throw new TypeError(\n      'The `browser.provider` configuration was changed to accept a factory instead of a string. '\n      + `Add an import of \"${resolved.browser.provider}\" from \"${source}\" instead. See: https://vitest.dev/config/browser/provider`,\n    )\n  }\n\n  const isPreview = resolved.browser.provider?.name === 'preview'\n\n  if (!isPreview && resolved.browser.enabled && stdProvider === 'stackblitz') {\n    throw new Error(`stackblitz environment does not support the ${resolved.browser.provider?.name} provider. Please, use \"@vitest/browser-preview\" instead.`)\n  }\n  if (isPreview && resolved.browser.screenshotFailures === true) {\n    console.warn(c.yellow(\n      [\n        `Browser provider \"preview\" doesn't support screenshots, `,\n        `so \"browser.screenshotFailures\" option is forcefully disabled. `,\n        `Set \"browser.screenshotFailures\" to false or remove it from the config to suppress this warning.`,\n      ].join(''),\n    ))\n    resolved.browser.screenshotFailures = false\n  }\n  else {\n    resolved.browser.screenshotFailures ??= !isPreview && !resolved.browser.ui\n  }\n  if (resolved.browser.provider && resolved.browser.provider.options == null) {\n    resolved.browser.provider.options = {}\n  }\n\n  resolved.browser.api = resolveApiServerConfig(\n    resolved.browser,\n    defaultBrowserPort,\n    resolved.api,\n    logger,\n  ) || {\n    port: defaultBrowserPort,\n  }\n\n  // enable includeTaskLocation by default in UI mode\n  if (resolved.browser.enabled) {\n    if (resolved.browser.ui) {\n      resolved.includeTaskLocation ??= true\n    }\n  }\n  else if (resolved.ui) {\n    resolved.includeTaskLocation ??= true\n  }\n\n  if (typeof resolved.browser.trace === 'string' || !resolved.browser.trace) {\n    resolved.browser.trace = { mode: resolved.browser.trace || 'off' }\n  }\n  if (resolved.browser.trace.tracesDir != null) {\n    resolved.browser.trace.tracesDir = resolvePath(\n      resolved.browser.trace.tracesDir,\n      resolved.root,\n    )\n  }\n\n  const htmlReporter = toArray(resolved.reporters).some((reporter) => {\n    if (Array.isArray(reporter)) {\n      return reporter[0] === 'html'\n    }\n\n    return false\n  })\n\n  if (htmlReporter) {\n    resolved.includeTaskLocation ??= true\n  }\n\n  resolved.server ??= {}\n  resolved.server.deps ??= {}\n\n  if (resolved.server.debug?.dump || process.env.VITEST_DEBUG_DUMP) {\n    const userFolder = resolved.server.debug?.dump || process.env.VITEST_DEBUG_DUMP\n    resolved.dumpDir = resolve(\n      resolved.root,\n      typeof userFolder === 'string' && userFolder !== 'true'\n        ? userFolder\n        : '.vitest-dump',\n      resolved.name || 'root',\n    )\n  }\n\n  resolved.testTimeout ??= resolved.browser.enabled ? 15_000 : 5_000\n  resolved.hookTimeout ??= resolved.browser.enabled ? 30_000 : 10_000\n\n  resolved.experimental ??= {} as any\n  if (resolved.experimental.openTelemetry?.sdkPath) {\n    const sdkPath = resolve(\n      resolved.root,\n      resolved.experimental.openTelemetry.sdkPath,\n    )\n    resolved.experimental.openTelemetry.sdkPath = pathToFileURL(sdkPath).toString()\n  }\n  if (resolved.experimental.openTelemetry?.browserSdkPath) {\n    const browserSdkPath = resolve(\n      resolved.root,\n      resolved.experimental.openTelemetry.browserSdkPath,\n    )\n    resolved.experimental.openTelemetry.browserSdkPath = browserSdkPath\n  }\n  if (resolved.experimental.fsModuleCachePath) {\n    resolved.experimental.fsModuleCachePath = resolve(\n      resolved.root,\n      resolved.experimental.fsModuleCachePath,\n    )\n  }\n  resolved.experimental.importDurations ??= {} as any\n  resolved.experimental.importDurations.print ??= false\n  resolved.experimental.importDurations.failOnDanger ??= false\n  if (resolved.experimental.importDurations.limit == null) {\n    const shouldCollect\n      = resolved.experimental.importDurations.print\n        || resolved.experimental.importDurations.failOnDanger\n        || resolved.ui\n    resolved.experimental.importDurations.limit = shouldCollect ? 10 : 0\n  }\n  resolved.experimental.importDurations.thresholds ??= {} as any\n  resolved.experimental.importDurations.thresholds.warn ??= 100\n  resolved.experimental.importDurations.thresholds.danger ??= 500\n\n  return resolved\n}\n\nexport function isBrowserEnabled(config: ResolvedConfig): boolean {\n  return Boolean(config.browser?.enabled)\n}\n\nexport function resolveCoverageReporters(configReporters: NonNullable<BaseCoverageOptions['reporter']>): CoverageReporterWithOptions[] {\n  // E.g. { reporter: \"html\" }\n  if (!Array.isArray(configReporters)) {\n    return [[configReporters, {}]]\n  }\n\n  const resolvedReporters: CoverageReporterWithOptions[] = []\n\n  for (const reporter of configReporters) {\n    if (Array.isArray(reporter)) {\n      // E.g. { reporter: [ [\"html\", { skipEmpty: true }], [\"lcov\"], [\"json\", { file: \"map.json\" }] ]}\n      resolvedReporters.push([reporter[0], reporter[1] as Record<string, unknown> || {}])\n    }\n    else {\n      // E.g. { reporter: [\"html\", \"json\"]}\n      resolvedReporters.push([reporter, {}])\n    }\n  }\n\n  return resolvedReporters\n}\n\nfunction isChromiumName(provider: string, name: string) {\n  if (provider === 'playwright') {\n    return name === 'chromium'\n  }\n  return name === 'chrome' || name === 'edge'\n}\n\nfunction hasBrowserChromium(vitest: Vitest, config: ResolvedConfig) {\n  const browser = config.browser\n  if (!browser || !browser.provider || browser.provider.name === 'preview' || !browser.enabled) {\n    return false\n  }\n  if (browser.name) {\n    return isChromiumName(browser.provider.name, browser.name)\n  }\n  if (!browser.instances) {\n    return false\n  }\n  return browser.instances.some((instance) => {\n    const name = instance.name || (config.name ? `${config.name} (${instance.browser})` : instance.browser)\n    // browser config is filtered out\n    if (!vitest.matchesProjectFilter(name)) {\n      return false\n    }\n    return isChromiumName(browser.provider!.name, instance.browser)\n  })\n}\n\nfunction hasOnlyBrowserChromium(vitest: Vitest, config: ResolvedConfig) {\n  const browser = config.browser\n  if (!browser || !browser.provider || browser.provider.name === 'preview' || !browser.enabled) {\n    return false\n  }\n  if (browser.name) {\n    return isChromiumName(browser.provider.name, browser.name)\n  }\n  if (!browser.instances) {\n    return false\n  }\n  return browser.instances.every((instance) => {\n    const name = instance.name || (config.name ? `${config.name} (${instance.browser})` : instance.browser)\n    // browser config is filtered out\n    if (!vitest.matchesProjectFilter(name)) {\n      return true // ignore this project\n    }\n    return isChromiumName(browser.provider!.name, instance.browser)\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/node/config/serializeConfig.ts",
    "content": "import type { TestProject } from '../project'\nimport type { ApiConfig, SerializedConfig } from '../types/config'\nimport { configDefaults } from '../../defaults'\n\nexport function serializeConfig(project: TestProject): SerializedConfig {\n  const { config, globalConfig } = project\n  const viteConfig = project._vite?.config\n  const optimizer = config.deps?.optimizer || {}\n\n  return {\n    // TODO: remove functions from environmentOptions\n    environmentOptions: config.environmentOptions,\n    mode: config.mode,\n    isolate: config.isolate,\n    maxWorkers: config.maxWorkers,\n    base: config.base,\n    logHeapUsage: config.logHeapUsage,\n    runner: config.runner,\n    bail: config.bail,\n    defines: config.defines,\n    chaiConfig: config.chaiConfig,\n    setupFiles: config.setupFiles,\n    allowOnly: config.allowOnly,\n    testTimeout: config.testTimeout,\n    testNamePattern: config.testNamePattern,\n    hookTimeout: config.hookTimeout,\n    clearMocks: config.clearMocks,\n    mockReset: config.mockReset,\n    restoreMocks: config.restoreMocks,\n    unstubEnvs: config.unstubEnvs,\n    unstubGlobals: config.unstubGlobals,\n    maxConcurrency: config.maxConcurrency,\n    pool: config.pool,\n    expect: config.expect,\n    snapshotSerializers: config.snapshotSerializers,\n    api: ((api: ApiConfig | undefined) => {\n      return {\n        allowExec: api?.allowExec,\n        allowWrite: api?.allowWrite,\n      }\n    })(project.isBrowserEnabled() ? config.browser.api : config.api),\n    // TODO: non serializable function?\n    diff: config.diff,\n    retry: config.retry,\n    disableConsoleIntercept: config.disableConsoleIntercept,\n    root: config.root,\n    name: config.name,\n    globals: config.globals,\n    snapshotEnvironment: config.snapshotEnvironment,\n    passWithNoTests: config.passWithNoTests,\n    coverage: ((coverage) => {\n      return {\n        reportsDirectory: coverage.reportsDirectory,\n        provider: coverage.provider,\n        enabled: coverage.enabled,\n        customProviderModule: 'customProviderModule' in coverage\n          ? coverage.customProviderModule\n          : undefined,\n        htmlDir: coverage.htmlDir,\n      }\n    })(config.coverage),\n    fakeTimers: config.fakeTimers,\n    deps: {\n      web: config.deps.web || {},\n      optimizer: Object.entries(optimizer).reduce((acc, [name, option]) => {\n        acc[name] = { enabled: option?.enabled ?? false }\n        return acc\n      }, {} as Record<string, { enabled: boolean }>),\n      interopDefault: config.deps.interopDefault,\n      moduleDirectories: config.deps.moduleDirectories,\n    },\n    snapshotOptions: {\n      // TODO: store it differently, not on the config\n      snapshotEnvironment: undefined!,\n      updateSnapshot: globalConfig.snapshotOptions.updateSnapshot,\n      snapshotFormat: {\n        ...globalConfig.snapshotOptions.snapshotFormat,\n      },\n      expand:\n        config.snapshotOptions.expand\n        ?? globalConfig.snapshotOptions.expand,\n    },\n    sequence: {\n      shuffle: globalConfig.sequence.shuffle,\n      concurrent: globalConfig.sequence.concurrent,\n      seed: globalConfig.sequence.seed,\n      hooks: globalConfig.sequence.hooks,\n      setupFiles: globalConfig.sequence.setupFiles,\n    },\n    inspect: globalConfig.inspect,\n    inspectBrk: globalConfig.inspectBrk,\n    inspector: globalConfig.inspector,\n    detectAsyncLeaks: globalConfig.detectAsyncLeaks,\n    watch: config.watch,\n    includeTaskLocation:\n      config.includeTaskLocation\n      ?? globalConfig.includeTaskLocation,\n    env: {\n      ...viteConfig?.env,\n      ...config.env,\n    },\n    browser: ((browser) => {\n      const provider = project.browser?.provider\n      return {\n        name: browser.name,\n        headless: browser.headless,\n        isolate: browser.isolate,\n        fileParallelism: browser.fileParallelism,\n        ui: browser.ui,\n        detailsPanelPosition: browser.detailsPanelPosition ?? 'right',\n        viewport: browser.viewport,\n        screenshotFailures: browser.screenshotFailures,\n        locators: {\n          testIdAttribute: browser.locators.testIdAttribute,\n        },\n        providerOptions: provider?.name === 'playwright'\n          ? {\n              actionTimeout: (provider as any)?.options?.actionTimeout,\n            }\n          : {},\n        trackUnhandledErrors: browser.trackUnhandledErrors ?? true,\n        trace: browser.trace.mode,\n      }\n    })(config.browser),\n    standalone: config.standalone,\n    printConsoleTrace:\n      config.printConsoleTrace ?? globalConfig.printConsoleTrace,\n    benchmark: config.benchmark && {\n      includeSamples: config.benchmark.includeSamples,\n    },\n    // the browser initialized them via `@vite/env` import\n    serializedDefines: config.browser.enabled\n      ? ''\n      : project._serializedDefines || '',\n    experimental: {\n      fsModuleCache: config.experimental.fsModuleCache ?? false,\n      importDurations: config.experimental.importDurations,\n      viteModuleRunner: config.experimental.viteModuleRunner ?? true,\n      nodeLoader: config.experimental.nodeLoader ?? true,\n      openTelemetry: config.experimental.openTelemetry,\n    },\n    tags: config.tags || [],\n    tagsFilter: config.tagsFilter,\n    strictTags: config.strictTags ?? true,\n    slowTestThreshold:\n      config.slowTestThreshold\n      ?? globalConfig.slowTestThreshold\n      ?? configDefaults.slowTestThreshold,\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/core.ts",
    "content": "import type { CancelReason, File } from '@vitest/runner'\nimport type { Awaitable } from '@vitest/utils'\nimport type { Writable } from 'node:stream'\nimport type { ViteDevServer } from 'vite'\nimport type { ModuleRunner } from 'vite/module-runner'\nimport type { SerializedCoverageConfig } from '../runtime/config'\nimport type { ArgumentsType, ProvidedContext, UserConsoleLog } from '../types/general'\nimport type { SourceModuleDiagnostic, SourceModuleLocations } from '../types/module-locations'\nimport type { CliOptions } from './cli/cli-api'\nimport type { VitestFetchFunction } from './environments/fetchModule'\nimport type { ProcessPool } from './pool'\nimport type { TestModule } from './reporters/reported-tasks'\nimport type { TestSpecification } from './test-specification'\nimport type { ResolvedConfig, TestProjectConfiguration, UserConfig, VitestRunMode } from './types/config'\nimport type { CoverageProvider, ResolvedCoverageOptions } from './types/coverage'\nimport type { Reporter } from './types/reporter'\nimport type { TestRunResult } from './types/tests'\nimport os, { tmpdir } from 'node:os'\nimport { getTasks, hasFailed, limitConcurrency } from '@vitest/runner/utils'\nimport { SnapshotManager } from '@vitest/snapshot/manager'\nimport { deepClone, deepMerge, nanoid, toArray } from '@vitest/utils/helpers'\nimport { serializeValue } from '@vitest/utils/serialize'\nimport { join, normalize, relative } from 'pathe'\nimport { isRunnableDevEnvironment } from 'vite'\nimport { version } from '../../package.json' with { type: 'json' }\nimport { distDir } from '../paths'\nimport { wildcardPatternToRegExp } from '../utils/base'\nimport { NativeModuleRunner } from '../utils/nativeModuleRunner'\nimport { convertTasksToEvents } from '../utils/tasks'\nimport { Traces } from '../utils/traces'\nimport { astCollectTests, createFailedFileTask } from './ast-collect'\nimport { BrowserSessions } from './browser/sessions'\nimport { VitestCache } from './cache'\nimport { FileSystemModuleCache } from './cache/fsModuleCache'\nimport { resolveConfig } from './config/resolveConfig'\nimport { getCoverageProvider } from './coverage'\nimport { createFetchModuleFunction } from './environments/fetchModule'\nimport { ServerModuleRunner } from './environments/serverRunner'\nimport { FilesNotFoundError } from './errors'\nimport { Logger } from './logger'\nimport { collectModuleDurationsDiagnostic, collectSourceModulesLocations } from './module-diagnostic'\nimport { VitestPackageInstaller } from './packageInstaller'\nimport { createPool } from './pool'\nimport { TestProject } from './project'\nimport { getDefaultTestProject, resolveBrowserProjects, resolveProjects } from './projects/resolveProjects'\nimport { BlobReporter, readBlobs } from './reporters/blob'\nimport { HangingProcessReporter } from './reporters/hanging-process'\nimport { createBenchmarkReporters, createReporters } from './reporters/utils'\nimport { VitestResolver } from './resolver'\nimport { VitestSpecifications } from './specifications'\nimport { StateManager } from './state'\nimport { populateProjectsTags } from './tags'\nimport { TestRun } from './test-run'\nimport { VitestWatcher } from './watcher'\n\nconst WATCHER_DEBOUNCE = 100\n\nexport interface VitestOptions {\n  packageInstaller?: VitestPackageInstaller\n  stdin?: NodeJS.ReadStream\n  stdout?: NodeJS.WriteStream | Writable\n  stderr?: NodeJS.WriteStream | Writable\n}\n\nexport class Vitest {\n  /**\n   * Current Vitest version.\n   * @example '2.0.0'\n   */\n  public readonly version: string = version\n  static readonly version: string = version\n  /**\n   * The logger instance used to log messages. It's recommended to use this logger instead of `console`.\n   * It's possible to override stdout and stderr streams when initiating Vitest.\n   * @example\n   * new Vitest('test', {\n   *   stdout: new Writable(),\n   * })\n   */\n  public readonly logger: Logger\n  /**\n   * The package installer instance used to install Vitest packages.\n   * @example\n   * await vitest.packageInstaller.ensureInstalled('@vitest/browser', process.cwd())\n   */\n  public readonly packageInstaller: VitestPackageInstaller\n  /**\n   * A path to the built Vitest directory. This is usually a folder in `node_modules`.\n   */\n  public readonly distPath: string = distDir\n  /**\n   * A list of projects that are currently running.\n   * If projects were filtered with `--project` flag, they won't appear here.\n   */\n  public projects: TestProject[] = []\n  /**\n   * A watcher handler. This is not the file system watcher. The handler only\n   * exposes methods to handle changed files.\n   *\n   * If you have your own watcher, you can use these methods to replicate\n   * Vitest behaviour.\n   */\n  public readonly watcher: VitestWatcher\n\n  /** @internal */ configOverride: Partial<ResolvedConfig> = {}\n  /** @internal */ filenamePattern?: string[]\n  /** @internal */ runningPromise?: Promise<TestRunResult>\n  /** @internal */ closingPromise?: Promise<void>\n  /** @internal */ cancelPromise?: Promise<void | void[]>\n  /** @internal */ isCancelling = false\n  /** @internal */ coreWorkspaceProject: TestProject | undefined\n  /** @internal */ _browserSessions = new BrowserSessions()\n  /** @internal */ _cliOptions: CliOptions = {}\n  /** @internal */ reporters: Reporter[] = []\n  /** @internal */ runner!: ModuleRunner\n  /** @internal */ _testRun: TestRun = undefined!\n  /** @internal */ _config?: ResolvedConfig\n  /** @internal */ _resolver!: VitestResolver\n  /** @internal */ _fetcher!: VitestFetchFunction\n  /** @internal */ _fsCache!: FileSystemModuleCache\n  /** @internal */ _tmpDir = join(tmpdir(), nanoid())\n  /** @internal */ _traces!: Traces\n\n  private isFirstRun = true\n  private restartsCount = 0\n\n  private readonly specifications: VitestSpecifications\n  private pool: ProcessPool | undefined\n  private _vite?: ViteDevServer\n  private _state?: StateManager\n  private _cache?: VitestCache\n  private _snapshot?: SnapshotManager\n  private _coverageProvider?: CoverageProvider | null | undefined\n\n  constructor(\n    public readonly mode: VitestRunMode,\n    cliOptions: UserConfig,\n    options: VitestOptions = {},\n  ) {\n    this._cliOptions = cliOptions\n    this.logger = new Logger(this, options.stdout, options.stderr)\n    this.packageInstaller = options.packageInstaller || new VitestPackageInstaller()\n    this.specifications = new VitestSpecifications(this)\n    this.watcher = new VitestWatcher(this).onWatcherRerun(file =>\n      this.scheduleRerun(file), // TODO: error handling\n    )\n  }\n\n  private _onRestartListeners: OnServerRestartHandler[] = []\n  private _onClose: (() => Awaitable<void>)[] = []\n  private _onSetServer: OnServerRestartHandler[] = []\n  private _onCancelListeners = new Set<(reason: CancelReason) => Awaitable<void>>()\n  private _onUserTestsRerun: OnTestsRerunHandler[] = []\n  private _onFilterWatchedSpecification: ((spec: TestSpecification) => boolean)[] = []\n\n  /**\n   * The global config.\n   */\n  get config(): ResolvedConfig {\n    assert(this._config, 'config')\n    return this._config\n  }\n\n  /**\n   * Global Vite's dev server instance.\n   */\n  get vite(): ViteDevServer {\n    assert(this._vite, 'vite', 'server')\n    return this._vite\n  }\n\n  /**\n   * The global test state manager.\n   * @experimental The State API is experimental and not subject to semver.\n   */\n  get state(): StateManager {\n    assert(this._state, 'state')\n    return this._state\n  }\n\n  /**\n   * The global snapshot manager. You can access the current state on `snapshot.summary`.\n   */\n  get snapshot(): SnapshotManager {\n    assert(this._snapshot, 'snapshot', 'snapshot manager')\n    return this._snapshot\n  }\n\n  /**\n   * Test results and test file stats cache. Primarily used by the sequencer to sort tests.\n   */\n  get cache(): VitestCache {\n    assert(this._cache, 'cache')\n    return this._cache\n  }\n\n  /** @internal */\n  async _setServer(options: UserConfig, server: ViteDevServer) {\n    this.watcher.unregisterWatcher()\n    clearTimeout(this._rerunTimer)\n    this.restartsCount += 1\n    this.pool?.close?.()\n    this.pool = undefined\n    this.closingPromise = undefined\n    this.projects = []\n    this.runningPromise = undefined\n    this.coreWorkspaceProject = undefined\n    this.specifications.clearCache()\n    this._coverageProvider = undefined\n    this._onUserTestsRerun = []\n\n    this._vite = server\n\n    const resolved = resolveConfig(this, options, server.config)\n\n    this._config = resolved\n    this._state = new StateManager({\n      onUnhandledError: resolved.onUnhandledError,\n    })\n    this._cache = new VitestCache(this.logger)\n    this._snapshot = new SnapshotManager({ ...resolved.snapshotOptions })\n    this._testRun = new TestRun(this)\n    const otelSdkPath = resolved.experimental.openTelemetry?.sdkPath\n    this._traces = new Traces({\n      enabled: !!resolved.experimental.openTelemetry?.enabled,\n      sdkPath: otelSdkPath,\n      watchMode: resolved.watch,\n    })\n\n    if (this.config.watch) {\n      this.watcher.registerWatcher()\n    }\n\n    this._resolver = new VitestResolver(server.config.cacheDir, resolved)\n    this._fsCache = new FileSystemModuleCache(this)\n    this._fetcher = createFetchModuleFunction(\n      this._resolver,\n      this._config,\n      this._fsCache,\n      this._traces,\n      this._tmpDir,\n    )\n    const environment = server.environments.__vitest__\n    this.runner = resolved.experimental.viteModuleRunner === false\n      ? new NativeModuleRunner(resolved.root)\n      : new ServerModuleRunner(\n          environment,\n          this._fetcher,\n          resolved,\n        )\n    // patch default ssr runnable environment so third-party usage of `runner.import`\n    // still works with Vite's external/noExternal configuration.\n    const ssrEnvironment = server.environments.ssr\n    if (isRunnableDevEnvironment(ssrEnvironment)) {\n      const ssrRunner = new ServerModuleRunner(\n        ssrEnvironment,\n        this._fetcher,\n        resolved,\n      )\n      Object.defineProperty(ssrEnvironment, 'runner', {\n        value: ssrRunner,\n        writable: true,\n        configurable: true,\n      })\n    }\n\n    if (this.config.watch) {\n      // hijack server restart\n      const serverRestart = server.restart\n      server.restart = async (...args) => {\n        await Promise.all(this._onRestartListeners.map(fn => fn()))\n        this.report('onServerRestart')\n        await this.close()\n        await serverRestart(...args)\n      }\n\n      // since we set `server.hmr: false`, Vite does not auto restart itself\n      server.watcher.on('change', async (file) => {\n        file = normalize(file)\n        const isConfig = file === server.config.configFile\n          || this.projects.some(p => p.vite.config.configFile === file)\n        if (isConfig) {\n          await Promise.all(this._onRestartListeners.map(fn => fn('config')))\n          this.report('onServerRestart', 'config')\n          await this.close()\n          await serverRestart()\n        }\n      })\n    }\n\n    this.cache.results.setConfig(resolved.root, resolved.cache)\n    try {\n      await this.cache.results.readFromCache()\n    }\n    catch { }\n\n    const projects = await this.resolveProjects(this._cliOptions)\n    this.projects = projects\n\n    await Promise.all(projects.flatMap((project) => {\n      const hooks = project.vite.config.getSortedPluginHooks('configureVitest')\n      return hooks.map(hook => hook({\n        project,\n        vitest: this,\n        injectTestProjects: this.injectTestProject,\n        /**\n         * @experimental\n         */\n        experimental_defineCacheKeyGenerator: callback => this._fsCache.defineCacheKeyGenerator(callback),\n      }))\n    }))\n\n    if (this._cliOptions.browser?.enabled) {\n      const browserProjects = this.projects.filter(p => p.config.browser.enabled)\n      if (!browserProjects.length) {\n        throw new Error(`Vitest received --browser flag, but no project had a browser configuration.`)\n      }\n    }\n    if (!this.projects.length) {\n      const filter = toArray(resolved.project).join('\", \"')\n      if (filter) {\n        throw new Error(`No projects matched the filter \"${filter}\".`)\n      }\n      else {\n        let error = `Vitest wasn't able to resolve any project.`\n        if (this.config.browser.enabled && !this.config.browser.instances?.length) {\n          error += ` Please, check that you specified the \"browser.instances\" option.`\n        }\n        throw new Error(error)\n      }\n    }\n\n    if (!this.coreWorkspaceProject) {\n      this.coreWorkspaceProject = TestProject._createBasicProject(this)\n    }\n\n    if (this.config.testNamePattern) {\n      this.configOverride.testNamePattern = this.config.testNamePattern\n    }\n\n    // populate will merge all configs into every project,\n    // we don't want that when just listing tags\n    if (!this.config.listTags) {\n      populateProjectsTags(this.coreWorkspaceProject, this.projects)\n    }\n\n    this.reporters = resolved.mode === 'benchmark'\n      ? await createBenchmarkReporters(toArray(resolved.benchmark?.reporters), this.runner)\n      : await createReporters(resolved.reporters, this)\n\n    await this._fsCache.ensureCacheIntegrity()\n\n    await Promise.all([\n      ...this._onSetServer.map(fn => fn()),\n      this._traces.waitInit(),\n    ])\n  }\n\n  /** @internal */\n  get coverageProvider(): CoverageProvider | null | undefined {\n    if (this.configOverride.coverage?.enabled === false) {\n      return null\n    }\n    return this._coverageProvider\n  }\n\n  public async listTags(): Promise<void> {\n    const listTags = this.config.listTags\n    if (typeof listTags === 'boolean') {\n      this.logger.printTags()\n    }\n    else if (listTags === 'json') {\n      const hasTags = [this.getRootProject(), ...this.projects].some(p => p.config.tags && p.config.tags.length > 0)\n      if (!hasTags) {\n        process.exitCode = 1\n        this.logger.printNoTestTagsFound()\n      }\n      else {\n        const manifest = {\n          tags: this.config.tags,\n          projects: this.projects.filter(p => p !== this.coreWorkspaceProject).map(p => ({\n            name: p.name,\n            tags: p.config.tags,\n          })),\n        }\n        this.logger.log(JSON.stringify(manifest, null, 2))\n      }\n    }\n    else {\n      throw new Error(`Unknown value for \"test.listTags\": ${listTags}`)\n    }\n  }\n\n  public async enableCoverage(): Promise<void> {\n    this.configOverride.coverage = {} as any\n    this.configOverride.coverage!.enabled = true\n    await this.createCoverageProvider()\n    await this.coverageProvider?.onEnabled?.()\n\n    // onFileTransform is the only thing that affects hash\n    if (this.coverageProvider?.onFileTransform) {\n      this.clearAllCachePaths()\n    }\n  }\n\n  public disableCoverage(): void {\n    this.configOverride.coverage ??= {} as any\n    this.configOverride.coverage!.enabled = false\n    // onFileTransform is the only thing that affects hash\n    if (this.coverageProvider?.onFileTransform) {\n      this.clearAllCachePaths()\n    }\n  }\n\n  private clearAllCachePaths() {\n    this.projects.forEach(({ vite, browser }) => {\n      const environments = [\n        ...Object.values(vite.environments),\n        ...Object.values(browser?.vite.environments || {}),\n      ]\n      environments.forEach(environment =>\n        this._fsCache.invalidateAllCachePaths(environment),\n      )\n    })\n  }\n\n  private _coverageOverrideCache = new WeakMap<ResolvedCoverageOptions, ResolvedCoverageOptions>()\n\n  /** @internal */\n  get _coverageOptions(): ResolvedCoverageOptions {\n    if (!this.configOverride.coverage) {\n      return this.config.coverage\n    }\n    if (!this._coverageOverrideCache.has(this.configOverride.coverage)) {\n      const coverage = deepClone(this.config.coverage)\n      const options = deepMerge(coverage, this.configOverride.coverage)\n      this._coverageOverrideCache.set(\n        this.configOverride.coverage,\n        options,\n      )\n    }\n    return this._coverageOverrideCache.get(this.configOverride.coverage)!\n  }\n\n  /**\n   * Inject new test projects into the workspace.\n   * @param config Glob, config path or a custom config options.\n   * @returns An array of new test projects. Can be empty if the name was filtered out.\n   */\n  private injectTestProject = async (config: TestProjectConfiguration | TestProjectConfiguration[]): Promise<TestProject[]> => {\n    const currentNames = new Set(this.projects.map(p => p.name))\n    const projects = await resolveProjects(\n      this,\n      this._cliOptions,\n      undefined,\n      Array.isArray(config) ? config : [config],\n      currentNames,\n    )\n    this.projects.push(...projects)\n    return projects\n  }\n\n  /**\n   * Provide a value to the test context. This value will be available to all tests with `inject`.\n   */\n  public provide = <T extends keyof ProvidedContext & string>(key: T, value: ProvidedContext[T]): void => {\n    this.getRootProject().provide(key, value)\n  }\n\n  /**\n   * Get global provided context.\n   */\n  public getProvidedContext(): ProvidedContext {\n    return this.getRootProject().getProvidedContext()\n  }\n\n  /** @internal */\n  _ensureRootProject(): TestProject {\n    if (this.coreWorkspaceProject) {\n      return this.coreWorkspaceProject\n    }\n    this.coreWorkspaceProject = TestProject._createBasicProject(this)\n    return this.coreWorkspaceProject\n  }\n\n  /**\n   * Return project that has the root (or \"global\") config.\n   */\n  public getRootProject(): TestProject {\n    if (!this.coreWorkspaceProject) {\n      throw new Error(`Root project is not initialized. This means that the Vite server was not established yet and the the workspace config is not resolved.`)\n    }\n    return this.coreWorkspaceProject\n  }\n\n  public getProjectByName(name: string): TestProject {\n    const project = this.projects.find(p => p.name === name)\n      || this.coreWorkspaceProject\n      || this.projects[0]\n    if (!project) {\n      throw new Error(`Project \"${name}\" was not found.`)\n    }\n    return project\n  }\n\n  /**\n   * Import a file using Vite module runner. The file will be transformed by Vite and executed in a separate context.\n   * @param moduleId The ID of the module in Vite module graph\n   */\n  public import<T>(moduleId: string): Promise<T> {\n    return this.runner.import(moduleId)\n  }\n\n  /**\n   * Creates a coverage provider if `coverage` is enabled in the config.\n   */\n  public async createCoverageProvider(): Promise<CoverageProvider | null> {\n    if (this._coverageProvider) {\n      return this._coverageProvider\n    }\n    const coverageProvider = await this.initCoverageProvider()\n    if (coverageProvider) {\n      await coverageProvider.clean(this._coverageOptions.clean)\n    }\n    return coverageProvider || null\n  }\n\n  private async resolveProjects(cliOptions: UserConfig): Promise<TestProject[]> {\n    const names = new Set<string>()\n\n    if (this.config.projects) {\n      return resolveProjects(\n        this,\n        cliOptions,\n        undefined,\n        this.config.projects,\n        names,\n      )\n    }\n\n    if ('workspace' in this.config) {\n      throw new Error('The `test.workspace` option was removed in Vitest 4. Please, migrate to `test.projects` instead. See https://vitest.dev/guide/projects for examples.')\n    }\n\n    // user can filter projects with --project flag, `getDefaultTestProject`\n    // returns the project only if it matches the filter\n    const project = getDefaultTestProject(this)\n    if (!project) {\n      return []\n    }\n    return resolveBrowserProjects(this, new Set([project.name]), [project])\n  }\n\n  /**\n   * Glob test files in every project and create a TestSpecification for each file and pool.\n   * @param filters String filters to match the test files.\n   */\n  public async globTestSpecifications(filters: string[] = []): Promise<TestSpecification[]> {\n    return this.specifications.globTestSpecifications(filters)\n  }\n\n  private async initCoverageProvider(): Promise<CoverageProvider | null | undefined> {\n    if (this._coverageProvider != null) {\n      return\n    }\n    const coverageConfig = (this.configOverride.coverage\n      ? this.getRootProject().serializedConfig.coverage\n      : this.config.coverage) as unknown as SerializedCoverageConfig\n    this._coverageProvider = await getCoverageProvider(\n      coverageConfig,\n      this.runner,\n    )\n    if (this._coverageProvider) {\n      await this._coverageProvider.initialize(this)\n      this.config.coverage = this._coverageProvider.resolveOptions()\n    }\n    return this._coverageProvider\n  }\n\n  /**\n   * Deletes all Vitest caches, including `experimental.fsModuleCache`.\n   * @experimental\n   */\n  public async experimental_clearCache(): Promise<void> {\n    await this.cache.results.clearCache()\n    await this._fsCache.clearCache()\n  }\n\n  /**\n   * Merge reports from multiple runs located in the specified directory (value from `--merge-reports` if not specified).\n   */\n  public async mergeReports(directory?: string): Promise<TestRunResult> {\n    return this._traces.$('vitest.merge_reports', async () => {\n      if (this.reporters.some(r => r instanceof BlobReporter)) {\n        throw new Error('Cannot merge reports when `--reporter=blob` is used. Remove blob reporter from the config first.')\n      }\n\n      const { files, errors, coverages, executionTimes } = await readBlobs(this.version, directory || this.config.mergeReports, this.projects)\n      this.state.blobs = { files, errors, coverages, executionTimes }\n\n      await this.report('onInit', this)\n\n      const specifications: TestSpecification[] = []\n      for (const file of files) {\n        const project = this.getProjectByName(file.projectName || '')\n        const specification = project.createSpecification(file.filepath, undefined, file.pool)\n        specifications.push(specification)\n      }\n\n      await this._testRun.start(specifications)\n      await this.coverageProvider?.onTestRunStart?.()\n\n      for (const file of files) {\n        await this._reportFileTask(file)\n      }\n\n      // append errors thrown during reporter event replay during merge reports\n      const unhandledErrors = [...errors, ...this.state.getUnhandledErrors()]\n      this._checkUnhandledErrors(unhandledErrors)\n      await this._testRun.end(specifications, unhandledErrors)\n      await this.initCoverageProvider()\n      await this.coverageProvider?.mergeReports?.(coverages)\n\n      return {\n        testModules: this.state.getTestModules(),\n        unhandledErrors: this.state.getUnhandledErrors(),\n      }\n    })\n  }\n\n  /**\n   * Returns the seed, if tests are running in a random order.\n   */\n  public getSeed(): number | null {\n    return this.config.sequence.seed ?? null\n  }\n\n  /** @internal */\n  public async _reportFileTask(file: File): Promise<void> {\n    const project = this.getProjectByName(file.projectName || '')\n    await this._testRun.enqueued(project, file).catch((error) => {\n      this.state.catchError(serializeValue(error), 'Unhandled Reporter Error')\n    })\n    await this._testRun.collected(project, [file]).catch((error) => {\n      this.state.catchError(serializeValue(error), 'Unhandled Reporter Error')\n    })\n\n    const logs: UserConsoleLog[] = []\n\n    const { packs, events } = convertTasksToEvents(file, (task) => {\n      if (task.logs) {\n        logs.push(...task.logs)\n      }\n    })\n\n    logs.sort((log1, log2) => log1.time - log2.time)\n\n    for (const log of logs) {\n      await this._testRun.log(log).catch((error) => {\n        this.state.catchError(serializeValue(error), 'Unhandled Reporter Error')\n      })\n    }\n\n    await this._testRun.updated(packs, events).catch((error) => {\n      this.state.catchError(serializeValue(error), 'Unhandled Reporter Error')\n    })\n  }\n\n  async collect(filters?: string[], options?: { staticParse?: boolean; staticParseConcurrency?: number }): Promise<TestRunResult> {\n    return this._traces.$('vitest.collect', async (collectSpan) => {\n      const filenamePattern = filters && filters?.length > 0 ? filters : []\n      collectSpan.setAttribute('vitest.collect.filters', filenamePattern)\n\n      const files = await this._traces.$(\n        'vitest.config.resolve_include_glob',\n        async () => {\n          const specifications = await this.specifications.getRelevantTestSpecifications(filters)\n          collectSpan.setAttribute(\n            'vitest.collect.specifications',\n            specifications.map((s) => {\n              const relativeModuleId = relative(s.project.config.root, s.moduleId)\n              if (s.project.name) {\n                return `|${s.project.name}| ${relativeModuleId}`\n              }\n              return relativeModuleId\n            }),\n          )\n          return specifications\n        },\n      )\n\n      // if run with --changed, don't exit if no tests are found\n      if (!files.length) {\n        return { testModules: [], unhandledErrors: [] }\n      }\n\n      if (options?.staticParse) {\n        const testModules = await this.experimental_parseSpecifications(files, {\n          concurrency: options.staticParseConcurrency,\n        })\n        return { testModules, unhandledErrors: [] }\n      }\n\n      return this.collectTests(files)\n    })\n  }\n\n  /**\n   * Returns the list of test files that match the config and filters.\n   * @param filters String filters to match the test files\n   */\n  getRelevantTestSpecifications(filters?: string[]): Promise<TestSpecification[]> {\n    return this.specifications.getRelevantTestSpecifications(filters)\n  }\n\n  /**\n   * Initialize reporters, the coverage provider, and run tests.\n   * This method can throw an error:\n   *   - `FilesNotFoundError` if no tests are found\n   *   - `GitNotFoundError` if `--related` flag is used, but git repository is not initialized\n   *   - `Error` from the user reporters\n   * @param filters String filters to match the test files\n   */\n  async start(filters?: string[]): Promise<TestRunResult> {\n    return this._traces.$('vitest.start', { context: this._traces.getContextFromEnv(process.env) }, async (startSpan) => {\n      startSpan.setAttributes({\n        config: this.vite.config.configFile,\n      })\n\n      try {\n        await this._traces.$('vitest.coverage.init', async () => {\n          await this.initCoverageProvider()\n          await this.coverageProvider?.clean(this._coverageOptions.clean)\n        })\n      }\n      finally {\n        await this.report('onInit', this)\n      }\n\n      this.filenamePattern = filters && filters?.length > 0 ? filters : undefined\n      startSpan.setAttribute('vitest.start.filters', this.filenamePattern || [])\n      const specifications = await this._traces.$(\n        'vitest.config.resolve_include_glob',\n        async () => {\n          const specifications = await this.specifications.getRelevantTestSpecifications(filters)\n          startSpan.setAttribute(\n            'vitest.start.specifications',\n            specifications.map((s) => {\n              const relativeModuleId = relative(s.project.config.root, s.moduleId)\n              if (s.project.name) {\n                return `|${s.project.name}| ${relativeModuleId}`\n              }\n              return relativeModuleId\n            }),\n          )\n          return specifications\n        },\n      )\n\n      // if run with --changed, don't exit if no tests are found\n      if (!specifications.length) {\n        await this._traces.$('vitest.test_run', async () => {\n          await this._testRun.start([])\n          await this.coverageProvider?.onTestRunStart?.()\n          const coverage = await this.coverageProvider?.generateCoverage?.({ allTestsRun: true })\n\n          await this._testRun.end([], [], coverage)\n          // Report coverage for uncovered files\n          await this.reportCoverage(coverage, true)\n        })\n\n        if (!this.config.watch || !(this.config.changed || this.config.related?.length)) {\n          throw new FilesNotFoundError(this.mode)\n        }\n      }\n\n      let testModules: TestRunResult = {\n        testModules: [],\n        unhandledErrors: [],\n      }\n\n      if (specifications.length) {\n        // populate once, update cache on watch\n        await this.cache.stats.populateStats(this.config.root, specifications)\n\n        testModules = await this.runFiles(specifications, true)\n      }\n\n      if (this.config.watch) {\n        await this.report('onWatcherStart')\n      }\n\n      return testModules\n    })\n  }\n\n  /**\n   * Initialize reporters and the coverage provider. This method doesn't run any tests.\n   * If the `--watch` flag is provided, Vitest will still run changed tests even if this method was not called.\n   */\n  async init(): Promise<void> {\n    await this._traces.$('vitest.init', async () => {\n      try {\n        await this.initCoverageProvider()\n        await this.coverageProvider?.clean(this._coverageOptions.clean)\n      }\n      finally {\n        await this.report('onInit', this)\n      }\n\n      // populate test files cache so watch mode can trigger a file rerun\n      await this.globTestSpecifications()\n\n      if (this.config.watch) {\n        await this.report('onWatcherStart')\n      }\n    })\n  }\n\n  /**\n   * If there is a test run happening, returns a promise that will\n   * resolve when the test run is finished.\n   */\n  public async waitForTestRunEnd(): Promise<void> {\n    if (!this.runningPromise) {\n      return\n    }\n    await this.runningPromise\n  }\n\n  /**\n   * Get test specifications associated with the given module. If module is not a test file, an empty array is returned.\n   *\n   * **Note:** this method relies on a cache generated by `globTestSpecifications`. If the file was not processed yet, use `project.matchesGlobPattern` instead.\n   * @param moduleId The module ID to get test specifications for.\n   */\n  public getModuleSpecifications(moduleId: string): TestSpecification[] {\n    return this.specifications.getModuleSpecifications(moduleId)\n  }\n\n  /**\n   * Vitest automatically caches test specifications for each file. This method clears the cache for the given file or the whole cache altogether.\n   */\n  public clearSpecificationsCache(moduleId?: string): void {\n    this.specifications.clearCache(moduleId)\n    if (!moduleId) {\n      this.projects.forEach((project) => {\n        project.testFilesList = null\n      })\n    }\n  }\n\n  /**\n   * Run tests for the given test specifications. This does not trigger `onWatcher*` events.\n   * @param specifications A list of specifications to run.\n   * @param allTestsRun Indicates whether all tests were run. This only matters for coverage.\n   */\n  public runTestSpecifications(specifications: TestSpecification[], allTestsRun = false): Promise<TestRunResult> {\n    specifications.forEach(spec => this.specifications.ensureSpecificationCached(spec))\n    return this.runFiles(specifications, allTestsRun)\n  }\n\n  /**\n   * Runs tests for the given file paths. This does not trigger `onWatcher*` events.\n   * @param filepaths A list of file paths to run tests for.\n   * @param allTestsRun Indicates whether all tests were run. This only matters for coverage.\n   */\n  public async runTestFiles(filepaths: string[], allTestsRun = false): Promise<TestRunResult> {\n    const specifications = await this.specifications.getRelevantTestSpecifications(filepaths)\n    if (!specifications.length) {\n      return { testModules: [], unhandledErrors: [] }\n    }\n    return this.runFiles(specifications, allTestsRun)\n  }\n\n  /**\n   * Rerun files and trigger `onWatcherRerun`, `onWatcherStart` and `onTestsRerun` events.\n   * @param specifications A list of specifications to run.\n   * @param allTestsRun Indicates whether all tests were run. This only matters for coverage.\n   */\n  public async rerunTestSpecifications(specifications: TestSpecification[], allTestsRun = false): Promise<TestRunResult> {\n    const files = specifications.map(spec => spec.moduleId)\n    await Promise.all([\n      this.report('onWatcherRerun', files, 'rerun test'),\n      ...this._onUserTestsRerun.map(fn => fn(specifications)),\n    ])\n    const result = await this.runTestSpecifications(specifications, allTestsRun)\n\n    await this.report('onWatcherStart', this.state.getFiles(files))\n    return result\n  }\n\n  private async runFiles(specs: TestSpecification[], allTestsRun: boolean): Promise<TestRunResult> {\n    return this._traces.$('vitest.test_run', async () => {\n      await this._testRun.start(specs)\n      await this.coverageProvider?.onTestRunStart?.()\n\n      // previous run\n      await this.cancelPromise\n      await this.runningPromise\n      this._onCancelListeners.clear()\n      this.isCancelling = false\n\n      // schedule the new run\n      this.runningPromise = (async () => {\n        try {\n          if (!this.pool) {\n            this.pool = createPool(this)\n          }\n\n          const invalidates = Array.from(this.watcher.invalidates)\n          this.watcher.invalidates.clear()\n          this.snapshot.clear()\n          this.state.clearErrors()\n\n          if (!this.isFirstRun && this._coverageOptions.cleanOnRerun) {\n            await this.coverageProvider?.clean()\n          }\n\n          await this.initializeGlobalSetup(specs)\n\n          try {\n            await this.pool.runTests(specs, invalidates)\n          }\n          catch (err) {\n            this.state.catchError(err, 'Unhandled Error')\n          }\n\n          const files = this.state.getFiles()\n\n          this.cache.results.updateResults(files)\n          try {\n            await this.cache.results.writeToCache()\n          }\n          catch {}\n\n          return {\n            testModules: this.state.getTestModules(),\n            unhandledErrors: this.state.getUnhandledErrors(),\n          }\n        }\n        finally {\n          const coverage = await this.coverageProvider?.generateCoverage({ allTestsRun })\n\n          const errors = this.state.getUnhandledErrors()\n          this._checkUnhandledErrors(errors)\n          await this._testRun.end(specs, errors, coverage)\n          await this.reportCoverage(coverage, allTestsRun)\n        }\n      })()\n        .finally(() => {\n          this.runningPromise = undefined\n          this.isFirstRun = false\n\n          // all subsequent runs will treat this as a fresh run\n          this.config.changed = false\n          this.config.related = undefined\n        })\n\n      return await this.runningPromise\n    })\n  }\n\n  /**\n   * Returns module's diagnostic. If `testModule` is not provided, `selfTime` and `totalTime` will be aggregated across all tests.\n   *\n   * If the module was not transformed or executed, the diagnostic will be empty.\n   * @experimental\n   * @see {@link https://vitest.dev/api/advanced/vitest#getsourcemodulediagnostic}\n   */\n  public async experimental_getSourceModuleDiagnostic(moduleId: string, testModule?: TestModule): Promise<SourceModuleDiagnostic> {\n    if (testModule) {\n      const viteEnvironment = testModule.viteEnvironment\n      // if there is no viteEnvironment, it means the file did not run yet\n      if (!viteEnvironment) {\n        return { modules: [], untrackedModules: [] }\n      }\n      const moduleLocations = await collectSourceModulesLocations(moduleId, viteEnvironment.moduleGraph)\n      return collectModuleDurationsDiagnostic(moduleId, this.state, moduleLocations, testModule)\n    }\n\n    const environments = this.projects.flatMap((p) => {\n      return Object.values(p.vite.environments)\n    })\n    const aggregatedLocationsResult = await Promise.all(\n      environments.map(environment =>\n        collectSourceModulesLocations(moduleId, environment.moduleGraph),\n      ),\n    )\n\n    return collectModuleDurationsDiagnostic(\n      moduleId,\n      this.state,\n      aggregatedLocationsResult.reduce<SourceModuleLocations>((acc, locations) => {\n        if (locations) {\n          acc.modules.push(...locations.modules)\n          acc.untracked.push(...locations.untracked)\n        }\n        return acc\n      }, { modules: [], untracked: [] }),\n    )\n  }\n\n  public async experimental_parseSpecifications(specifications: TestSpecification[], options?: {\n    /** @default os.availableParallelism() */\n    concurrency?: number\n  }): Promise<TestModule[]> {\n    if (this.mode !== 'test') {\n      throw new Error(`The \\`experimental_parseSpecifications\\` does not support \"${this.mode}\" mode.`)\n    }\n    const concurrency = options?.concurrency ?? (typeof os.availableParallelism === 'function'\n      ? os.availableParallelism()\n      : os.cpus().length)\n    const limit = limitConcurrency(concurrency)\n    const promises = specifications.map(specification =>\n      limit(() => this.experimental_parseSpecification(specification)),\n    )\n    return Promise.all(promises)\n  }\n\n  public async experimental_parseSpecification(specification: TestSpecification): Promise<TestModule> {\n    if (this.mode !== 'test') {\n      throw new Error(`The \\`experimental_parseSpecification\\` does not support \"${this.mode}\" mode.`)\n    }\n    const file = await astCollectTests(specification.project, specification.moduleId).catch((error) => {\n      return createFailedFileTask(specification.project, specification.moduleId, error)\n    })\n    // register in state, so it can be retrieved by \"getReportedEntity\"\n    this.state.collectFiles(specification.project, [file])\n    return this.state.getReportedEntity(file) as TestModule\n  }\n\n  /**\n   * Collect tests in specified modules. Vitest will run the files to collect tests.\n   * @param specifications A list of specifications to run.\n   */\n  public async collectTests(specifications: TestSpecification[]): Promise<TestRunResult> {\n    const filepaths = specifications.map(spec => spec.moduleId)\n    this.state.collectPaths(filepaths)\n\n    // previous run\n    await this.cancelPromise\n    await this.runningPromise\n    this._onCancelListeners.clear()\n    this.isCancelling = false\n\n    // schedule the new run\n    this.runningPromise = (async () => {\n      if (!this.pool) {\n        this.pool = createPool(this)\n      }\n\n      const invalidates = Array.from(this.watcher.invalidates)\n      this.watcher.invalidates.clear()\n      this.snapshot.clear()\n      this.state.clearErrors()\n\n      await this.initializeGlobalSetup(specifications)\n\n      try {\n        await this.pool.collectTests(specifications, invalidates)\n      }\n      catch (err) {\n        this.state.catchError(err, 'Unhandled Error')\n      }\n\n      const files = this.state.getFiles()\n\n      // can only happen if there was a syntax error in describe block\n      // or there was an error importing a file\n      if (hasFailed(files)) {\n        process.exitCode = 1\n      }\n\n      return {\n        testModules: this.state.getTestModules(),\n        unhandledErrors: this.state.getUnhandledErrors(),\n      }\n    })()\n      .finally(() => {\n        this.runningPromise = undefined\n\n        // all subsequent runs will treat this as a fresh run\n        this.config.changed = false\n        this.config.related = undefined\n      })\n\n    return await this.runningPromise\n  }\n\n  /**\n   * Gracefully cancel the current test run. Vitest will wait until all running tests are finished before cancelling.\n   */\n  async cancelCurrentRun(reason: CancelReason): Promise<void> {\n    this.isCancelling = true\n    this.cancelPromise = Promise.all([...this._onCancelListeners].map(listener => listener(reason)))\n\n    await this.cancelPromise.finally(() => (this.cancelPromise = undefined))\n    await this.runningPromise\n  }\n\n  /** @internal */\n  async _initBrowserServers(): Promise<void> {\n    await Promise.all(this.projects.map(p => p._initBrowserServer()))\n  }\n\n  private async initializeGlobalSetup(paths: TestSpecification[]): Promise<void> {\n    const projects = new Set(paths.map(spec => spec.project))\n    const coreProject = this.getRootProject()\n    if (!projects.has(coreProject)) {\n      projects.add(coreProject)\n    }\n    for (const project of projects) {\n      await project._initializeGlobalSetup()\n    }\n  }\n\n  /** @internal */\n  async rerunFiles(files: string[] = this.state.getFilepaths(), trigger?: string, allTestsRun = true, resetTestNamePattern = false): Promise<TestRunResult> {\n    if (resetTestNamePattern) {\n      this.configOverride.testNamePattern = undefined\n    }\n\n    if (this.filenamePattern) {\n      const filteredFiles = await this.globTestSpecifications(this.filenamePattern)\n      files = files.filter(file => filteredFiles.some(f => f.moduleId === file))\n    }\n\n    const specifications = files.flatMap(file => this.getModuleSpecifications(file))\n    await Promise.all([\n      this.report('onWatcherRerun', files, trigger),\n      ...this._onUserTestsRerun.map(fn => fn(specifications)),\n    ])\n    const testResult = await this.runFiles(specifications, allTestsRun)\n\n    await this.report('onWatcherStart', this.state.getFiles(files))\n    return testResult\n  }\n\n  /** @internal */\n  async rerunTask(id: string): Promise<void> {\n    const task = this.state.idMap.get(id)\n    if (!task) {\n      throw new Error(`Task ${id} was not found`)\n    }\n\n    const reportedTask = this.state.getReportedEntityById(id)\n    if (!reportedTask) {\n      throw new Error(`Test specification for task ${id} was not found`)\n    }\n\n    const specifications = [reportedTask.toTestSpecification()]\n    await Promise.all([\n      this.report(\n        'onWatcherRerun',\n        [task.file.filepath],\n        'tasks' in task ? 'rerun suite' : 'rerun test',\n      ),\n      ...this._onUserTestsRerun.map(fn => fn(specifications)),\n    ])\n    await this.runFiles(specifications, false)\n    await this.report(\n      'onWatcherStart',\n      ['module' in reportedTask ? reportedTask.module.task : reportedTask.task],\n    )\n  }\n\n  /** @internal */\n  async changeProjectName(pattern: string): Promise<void> {\n    if (pattern === '') {\n      this.configOverride.project = undefined\n    }\n    else {\n      this.configOverride.project = [pattern]\n    }\n\n    await this.vite.restart()\n  }\n\n  /** @internal */\n  async changeNamePattern(pattern: string, files: string[] = this.state.getFilepaths(), trigger?: string): Promise<void> {\n    // Empty test name pattern should reset filename pattern as well\n    if (pattern === '') {\n      this.filenamePattern = undefined\n    }\n\n    const testNamePattern = pattern ? new RegExp(pattern) : undefined\n    this.configOverride.testNamePattern = testNamePattern\n    // filter only test files that have tests matching the pattern\n    if (testNamePattern) {\n      files = files.filter((filepath) => {\n        const files = this.state.getFiles([filepath])\n        return !files.length || files.some((file) => {\n          const tasks = getTasks(file)\n          return !tasks.length || tasks.some(task => testNamePattern.test(task.name))\n        })\n      })\n    }\n\n    await this.rerunFiles(files, trigger, pattern === '')\n  }\n\n  /** @internal */\n  async changeFilenamePattern(pattern: string, files: string[] = this.state.getFilepaths()): Promise<void> {\n    this.filenamePattern = pattern ? [pattern] : []\n\n    const trigger = this.filenamePattern.length ? 'change filename pattern' : 'reset filename pattern'\n\n    await this.rerunFiles(files, trigger, pattern === '')\n  }\n\n  /** @internal */\n  async rerunFailed(): Promise<void> {\n    await this.rerunFiles(this.state.getFailedFilepaths(), 'rerun failed', false)\n  }\n\n  /**\n   * Update snapshots in specified files. If no files are provided, it will update files with failed tests and obsolete snapshots.\n   * @param files The list of files on the file system\n   */\n  async updateSnapshot(files?: string[]): Promise<TestRunResult> {\n    // default to failed files\n    files = files || [\n      ...this.state.getFailedFilepaths(),\n      ...this.snapshot.summary.uncheckedKeysByFile.map(s => s.filePath),\n    ]\n\n    this.enableSnapshotUpdate()\n\n    try {\n      return await this.rerunFiles(files, 'update snapshot', false)\n    }\n    finally {\n      this.resetSnapshotUpdate()\n    }\n  }\n\n  /**\n   * Enable the mode that allows updating snapshots when running tests.\n   * This method doesn't run any tests.\n   *\n   * Every test that runs after this method is called will update snapshots.\n   * To disable the mode, call `resetSnapshotUpdate`.\n   */\n  public enableSnapshotUpdate(): void {\n    this.configOverride.snapshotOptions = {\n      updateSnapshot: 'all',\n      // environment is resolved inside a worker thread\n      snapshotEnvironment: null as any,\n    }\n    this.snapshot.options.updateSnapshot = 'all'\n  }\n\n  /**\n   * Disable the mode that allows updating snapshots when running tests.\n   */\n  public resetSnapshotUpdate(): void {\n    delete this.configOverride.snapshotOptions\n    this.snapshot.options.updateSnapshot = this.config.snapshotOptions.updateSnapshot\n  }\n\n  /**\n   * Set the global test name pattern to a regexp.\n   * This method doesn't run any tests.\n   */\n  public setGlobalTestNamePattern(pattern: string | RegExp): void {\n    if (pattern instanceof RegExp) {\n      this.configOverride.testNamePattern = pattern\n    }\n    else {\n      this.configOverride.testNamePattern = pattern ? new RegExp(pattern) : undefined\n    }\n  }\n\n  /**\n   * Returns the regexp used for the global test name pattern.\n   */\n  public getGlobalTestNamePattern(): RegExp | undefined {\n    if (this.configOverride.testNamePattern != null) {\n      return this.configOverride.testNamePattern\n    }\n    return this.config.testNamePattern\n  }\n\n  /**\n   * Resets the global test name pattern. This method doesn't run any tests.\n   */\n  public resetGlobalTestNamePattern(): void {\n    this.configOverride.testNamePattern = undefined\n  }\n\n  private _rerunTimer: any\n  private async scheduleRerun(triggerId: string): Promise<void> {\n    const currentCount = this.restartsCount\n    clearTimeout(this._rerunTimer)\n    await this.cancelPromise\n    await this.runningPromise\n    clearTimeout(this._rerunTimer)\n\n    // server restarted\n    if (this.restartsCount !== currentCount) {\n      return\n    }\n\n    this._rerunTimer = setTimeout(async () => {\n      if (this.watcher.changedTests.size === 0) {\n        this.watcher.invalidates.clear()\n        return\n      }\n\n      // server restarted\n      if (this.restartsCount !== currentCount) {\n        return\n      }\n\n      this.isFirstRun = false\n\n      this.snapshot.clear()\n      let files = Array.from(this.watcher.changedTests)\n\n      if (this.filenamePattern) {\n        const filteredFiles = await this.globTestSpecifications(this.filenamePattern)\n        files = files.filter(file => filteredFiles.some(f => f.moduleId === file))\n\n        // A file that does not match the current filename pattern was changed\n        if (files.length === 0) {\n          return\n        }\n      }\n\n      this.watcher.changedTests.clear()\n\n      const triggerLabel = relative(this.config.root, triggerId)\n      // get file specifications and filter them if needed\n      const specifications = files.flatMap(file => this.getModuleSpecifications(file)).filter((specification) => {\n        if (this._onFilterWatchedSpecification.length === 0) {\n          return true\n        }\n        return this._onFilterWatchedSpecification.every(fn => fn(specification))\n      })\n      await Promise.all([\n        this.report('onWatcherRerun', files, triggerLabel),\n        ...this._onUserTestsRerun.map(fn => fn(specifications)),\n      ])\n\n      await this.runFiles(specifications, false)\n\n      await this.report('onWatcherStart', this.state.getFiles(files))\n    }, WATCHER_DEBOUNCE)\n  }\n\n  /**\n   * Invalidate a file in all projects.\n   */\n  public invalidateFile(filepath: string): void {\n    this.projects.forEach(({ vite, browser }) => {\n      const environments = [\n        ...Object.values(vite.environments),\n        ...Object.values(browser?.vite.environments || {}),\n      ]\n\n      environments.forEach((environment) => {\n        const { moduleGraph } = environment\n        const modules = moduleGraph.getModulesByFile(filepath)\n        if (!modules) {\n          return\n        }\n\n        modules.forEach((module) => {\n          moduleGraph.invalidateModule(module)\n          this._fsCache.invalidateCachePath(environment, module.id!)\n        })\n      })\n    })\n  }\n\n  /** @internal */\n  public _checkUnhandledErrors(errors: unknown[]): void {\n    if (errors.length && !this.config.dangerouslyIgnoreUnhandledErrors) {\n      process.exitCode = 1\n    }\n  }\n\n  private async reportCoverage(coverage: unknown, allTestsRun: boolean): Promise<void> {\n    if (this.state.getCountOfFailedTests() > 0) {\n      await this.coverageProvider?.onTestFailure?.()\n\n      if (!this._coverageOptions.reportOnFailure) {\n        return\n      }\n    }\n\n    if (this.coverageProvider) {\n      await this.coverageProvider.reportCoverage(coverage, { allTestsRun })\n      // notify builtin ui and html reporter after coverage html is generated\n      for (const reporter of this.reporters) {\n        if (\n          'onFinishedReportCoverage' in reporter\n          && typeof reporter.onFinishedReportCoverage === 'function'\n        ) {\n          await reporter.onFinishedReportCoverage()\n        }\n      }\n    }\n  }\n\n  /**\n   * Closes all projects and their associated resources.\n   * This can only be called once; the closing promise is cached until the server restarts.\n   */\n  public async close(): Promise<void> {\n    if (!this.closingPromise) {\n      this.closingPromise = (async () => {\n        const teardownProjects = [...this.projects]\n        if (this.coreWorkspaceProject && !teardownProjects.includes(this.coreWorkspaceProject)) {\n          teardownProjects.push(this.coreWorkspaceProject)\n        }\n        const teardownErrors: unknown[] = []\n        // do teardown before closing the server\n        for (const project of teardownProjects.reverse()) {\n          await project._teardownGlobalSetup().catch((error) => {\n            teardownErrors.push(error)\n          })\n        }\n\n        const closePromises: unknown[] = this.projects.map(w => w.close())\n        // close the core workspace server only once\n        // it's possible that it's not initialized at all because it's not running any tests\n        if (this.coreWorkspaceProject && !this.projects.includes(this.coreWorkspaceProject)) {\n          closePromises.push(this.coreWorkspaceProject.close().then(() => this._vite = undefined as any))\n        }\n\n        if (this.pool) {\n          closePromises.push((async () => {\n            await this.pool?.close?.()\n\n            this.pool = undefined\n          })())\n        }\n\n        closePromises.push(...this._onClose.map(fn => fn()))\n\n        await Promise.allSettled(closePromises).then((results) => {\n          [...results, ...teardownErrors.map(r => ({ status: 'rejected', reason: r }))].forEach((r) => {\n            if (r.status === 'rejected') {\n              this.logger.error('error during close', r.reason)\n            }\n          })\n        })\n        await this._traces?.finish()\n      })()\n    }\n    return this.closingPromise\n  }\n\n  /**\n   * Closes all projects and exit the process\n   * @param force If true, the process will exit immediately after closing the projects.\n   */\n  public async exit(force = false): Promise<void> {\n    setTimeout(() => {\n      this.report('onProcessTimeout').then(() => {\n        console.warn(`close timed out after ${this.config.teardownTimeout}ms`)\n\n        if (!this.pool) {\n          const runningServers = [this._vite, ...this.projects.map(p => p._vite)].filter(Boolean).length\n\n          if (runningServers === 1) {\n            console.warn('Tests closed successfully but something prevents Vite server from exiting')\n          }\n          else if (runningServers > 1) {\n            console.warn(`Tests closed successfully but something prevents ${runningServers} Vite servers from exiting`)\n          }\n          else {\n            console.warn('Tests closed successfully but something prevents the main process from exiting')\n          }\n\n          if (!this.reporters.some(r => r instanceof HangingProcessReporter)) {\n            console.warn('You can try to identify the cause by enabling \"hanging-process\" reporter. See https://vitest.dev/guide/reporters.html#hanging-process-reporter')\n          }\n        }\n\n        process.exit()\n      })\n    }, this.config.teardownTimeout).unref()\n\n    await this.close()\n    if (force) {\n      process.exit()\n    }\n  }\n\n  /** @internal */\n  async report<T extends keyof Reporter>(name: T, ...args: ArgumentsType<Reporter[T]>) {\n    await Promise.all(this.reporters.map(r => r[name]?.(\n      // @ts-expect-error let me go\n      ...args,\n    )))\n  }\n\n  /** @internal */\n  public async _globTestFilepaths() {\n    const specifications = await this.globTestSpecifications()\n    return Array.from(new Set(specifications.map(spec => spec.moduleId)))\n  }\n\n  /**\n   * Should the server be kept running after the tests are done.\n   */\n  shouldKeepServer(): boolean {\n    return !!this.config?.watch\n  }\n\n  /**\n   * Register a handler that will be called when the server is restarted due to a config change.\n   */\n  onServerRestart(fn: OnServerRestartHandler): void {\n    this._onRestartListeners.push(fn)\n  }\n\n  /**\n   * Register a handler that will be called when the test run is cancelled with `vitest.cancelCurrentRun`.\n   */\n  onCancel(fn: (reason: CancelReason) => Awaitable<void>): () => void {\n    this._onCancelListeners.add(fn)\n    return () => {\n      this._onCancelListeners.delete(fn)\n    }\n  }\n\n  /**\n   * Register a handler that will be called when the server is closed.\n   */\n  onClose(fn: () => Awaitable<void>): void {\n    this._onClose.push(fn)\n  }\n\n  /**\n   * Register a handler that will be called when the tests are rerunning.\n   */\n  onTestsRerun(fn: OnTestsRerunHandler): void {\n    this._onUserTestsRerun.push(fn)\n  }\n\n  /**\n   * Register a handler that will be called when a file is changed.\n   * This callback should return `true` of `false` indicating whether the test file needs to be rerun.\n   * @example\n   * const testsToRun = [resolve('./test.spec.ts')]\n   * vitest.onFilterWatchedSpecification(specification => testsToRun.includes(specification.moduleId))\n   */\n  onFilterWatchedSpecification(fn: (specification: TestSpecification) => boolean): void {\n    this._onFilterWatchedSpecification.push(fn)\n  }\n\n  /** @internal */\n  onAfterSetServer(fn: OnServerRestartHandler): void {\n    this._onSetServer.push(fn)\n  }\n\n  /**\n   * Check if the project with a given name should be included.\n   */\n  matchesProjectFilter(name: string): boolean {\n    const projects = this._config?.project || this._cliOptions?.project\n    // no filters applied, any project can be included\n    if (!projects || !projects.length) {\n      return true\n    }\n    return toArray(projects).some((project) => {\n      const regexp = wildcardPatternToRegExp(project)\n      return regexp.test(name)\n    })\n  }\n}\n\nfunction assert(condition: unknown, property: string, name: string = property): asserts condition {\n  if (!condition) {\n    throw new Error(`The ${name} was not set. It means that \\`vitest.${property}\\` was called before the Vite server was established. Await the Vitest promise before accessing \\`vitest.${property}\\`.`)\n  }\n}\n\nexport type OnServerRestartHandler = (reason?: string) => Promise<void> | void\nexport type OnTestsRerunHandler = (testFiles: TestSpecification[]) => Promise<void> | void\n"
  },
  {
    "path": "packages/vitest/src/node/coverage.ts",
    "content": "import type { CoverageMap } from 'istanbul-lib-coverage'\nimport type { TransformResult } from 'vite'\nimport type { Vitest } from '../node/core'\nimport type { BaseCoverageOptions, CoverageModuleLoader, CoverageProvider, ReportContext, ResolvedCoverageOptions } from '../node/types/coverage'\nimport type { SerializedCoverageConfig } from '../runtime/config'\nimport type { AfterSuiteRunMeta } from '../types/general'\nimport type { TestProject } from './project'\nimport { existsSync, promises as fs, readdirSync, writeFileSync } from 'node:fs'\nimport module from 'node:module'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { cleanUrl, slash } from '@vitest/utils/helpers'\nimport { relative, resolve } from 'pathe'\nimport pm from 'picomatch'\nimport { glob } from 'tinyglobby'\nimport c from 'tinyrainbow'\nimport { coverageConfigDefaults } from '../defaults'\nimport { resolveCoverageReporters } from '../node/config/resolveConfig'\nimport { resolveCoverageProviderModule } from '../utils/coverage'\n\ntype Threshold = 'lines' | 'functions' | 'statements' | 'branches'\n\ninterface ResolvedThreshold {\n  coverageMap: CoverageMap\n  name: string\n  thresholds: Partial<Record<Threshold, number | undefined>>\n}\n\n/**\n * Holds info about raw coverage results that are stored on file system:\n *\n * ```json\n * \"project-a\": {\n *   \"web\": {\n *     \"tests/math.test.ts\": \"coverage-1.json\",\n *     \"tests/utils.test.ts\": \"coverage-2.json\",\n * //                          ^^^^^^^^^^^^^^^ Raw coverage on file system\n *   },\n *   \"ssr\": { ... },\n *   \"browser\": { ... },\n * },\n * \"project-b\": ...\n * ```\n */\ntype CoverageFiles = Map<\n  NonNullable<AfterSuiteRunMeta['projectName']> | symbol,\n  Record<\n    AfterSuiteRunMeta['environment'],\n    { [TestFilenames: string]: string }\n  >\n>\ntype Entries<T> = [keyof T, T[keyof T]][]\n\nconst THRESHOLD_KEYS: Readonly<Threshold[]> = [\n  'lines',\n  'functions',\n  'statements',\n  'branches',\n]\nconst GLOBAL_THRESHOLDS_KEY = 'global'\nconst DEFAULT_PROJECT: unique symbol = Symbol.for('default-project')\nlet uniqueId = 0\n\nexport async function getCoverageProvider(\n  options: SerializedCoverageConfig | undefined,\n  loader: CoverageModuleLoader,\n): Promise<CoverageProvider | null> {\n  const coverageModule = await resolveCoverageProviderModule(options, loader)\n\n  if (coverageModule) {\n    return coverageModule.getProvider()\n  }\n\n  return null\n}\n\nexport class BaseCoverageProvider<Options extends ResolvedCoverageOptions<'istanbul' | 'v8'>> {\n  ctx!: Vitest\n  readonly name!: 'v8' | 'istanbul'\n  version!: string\n  options!: Options\n  globCache: Map<string, boolean> = new Map()\n  autoUpdateMarker = '\\n// __VITEST_COVERAGE_MARKER__'\n\n  coverageFiles: CoverageFiles = new Map()\n  pendingPromises: Promise<void>[] = []\n  coverageFilesDirectory!: string\n  roots: string[] = []\n  changedFiles?: string[]\n\n  _initialize(ctx: Vitest): void {\n    this.ctx = ctx\n\n    if (ctx.version !== this.version) {\n      ctx.logger.warn(\n        c.yellow(\n          `Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-${this.name}@${this.version} `))}.`\n          + '\\nRunning mixed versions is not supported and may lead into bugs'\n          + '\\nUpdate your dependencies and make sure the versions match.',\n        ),\n      )\n    }\n\n    const config = ctx._coverageOptions as Options\n\n    this.options = {\n      ...coverageConfigDefaults,\n\n      // User's options\n      ...config,\n\n      // Resolved fields\n      provider: this.name,\n      reportsDirectory: resolve(\n        ctx.config.root,\n        config.reportsDirectory || coverageConfigDefaults.reportsDirectory,\n      ),\n      reporter: resolveCoverageReporters(\n        config.reporter || coverageConfigDefaults.reporter,\n      ),\n      thresholds: config.thresholds && {\n        ...config.thresholds,\n        lines: config.thresholds['100'] ? 100 : config.thresholds.lines,\n        branches: config.thresholds['100'] ? 100 : config.thresholds.branches,\n        functions: config.thresholds['100'] ? 100 : config.thresholds.functions,\n        statements: config.thresholds['100'] ? 100 : config.thresholds.statements,\n      },\n    }\n\n    const shard = this.ctx.config.shard\n    const tempDirectory = `.tmp${\n      shard ? `-${shard.index}-${shard.count}` : ''\n    }`\n\n    this.coverageFilesDirectory = resolve(\n      this.options.reportsDirectory,\n      tempDirectory,\n    )\n\n    // If --project filter is set pick only roots of resolved projects\n    this.roots = ctx.config.project?.length\n      ? [...new Set(ctx.projects.map(project => project.config.root))]\n      : [ctx.config.root]\n  }\n\n  /**\n   * Check if file matches `coverage.include` but not `coverage.exclude`\n   */\n  isIncluded(_filename: string, root?: string): boolean {\n    const roots = root ? [root] : this.roots\n\n    const filename = slash(cleanUrl(_filename))\n    const cacheHit = this.globCache.get(filename)\n\n    if (cacheHit !== undefined) {\n      return cacheHit\n    }\n\n    // File outside project root with default allowExternal\n    if (this.options.allowExternal === false && roots.every(root => !filename.startsWith(root))) {\n      this.globCache.set(filename, false)\n\n      return false\n    }\n\n    // By default `coverage.include` matches all files, except \"coverage.exclude\"\n    const glob = this.options.include || '**'\n\n    let included = pm.isMatch(filename, glob, {\n      contains: true,\n      dot: true,\n      ignore: this.options.exclude,\n    })\n\n    if (included && this.changedFiles) {\n      included = this.changedFiles.includes(filename)\n    }\n\n    this.globCache.set(filename, included)\n\n    return included\n  }\n\n  private async getUntestedFilesByRoot(\n    testedFiles: string[],\n    include: string[],\n    root: string,\n  ): Promise<string[]> {\n    let includedFiles = await glob(include, {\n      cwd: root,\n      ignore: [...this.options.exclude, ...testedFiles.map(file => slash(file))],\n      absolute: true,\n      dot: true,\n      onlyFiles: true,\n    })\n\n    // Run again through picomatch as tinyglobby's exclude pattern is different ({ \"exclude\": [\"math\"] } should ignore \"src/math.ts\")\n    includedFiles = includedFiles.filter(file => this.isIncluded(file, root))\n\n    if (this.changedFiles) {\n      includedFiles = this.changedFiles.filter(file => includedFiles.includes(file))\n    }\n\n    return includedFiles.map(file => slash(path.resolve(root, file)))\n  }\n\n  async getUntestedFiles(testedFiles: string[]): Promise<string[]> {\n    if (this.options.include == null) {\n      return []\n    }\n\n    const rootMapper = this.getUntestedFilesByRoot.bind(this, testedFiles, this.options.include)\n\n    const matrix = await Promise.all(this.roots.map(rootMapper))\n\n    return matrix.flatMap(files => files)\n  }\n\n  createCoverageMap(): CoverageMap {\n    throw new Error('BaseReporter\\'s createCoverageMap was not overwritten')\n  }\n\n  async generateReports(_: CoverageMap, __: boolean | undefined): Promise<void> {\n    throw new Error('BaseReporter\\'s generateReports was not overwritten')\n  }\n\n  async parseConfigModule(_: string): Promise<{ generate: () => { code: string } }> {\n    throw new Error('BaseReporter\\'s parseConfigModule was not overwritten')\n  }\n\n  resolveOptions(): Options {\n    return this.options\n  }\n\n  async clean(clean = true): Promise<void> {\n    if (clean && existsSync(this.options.reportsDirectory)) {\n      await fs.rm(this.options.reportsDirectory, {\n        recursive: true,\n        force: true,\n        maxRetries: 10,\n      })\n    }\n\n    if (existsSync(this.coverageFilesDirectory)) {\n      await fs.rm(this.coverageFilesDirectory, {\n        recursive: true,\n        force: true,\n        maxRetries: 10,\n      })\n    }\n\n    await fs.mkdir(this.coverageFilesDirectory, { recursive: true })\n\n    this.coverageFiles = new Map()\n    this.pendingPromises = []\n  }\n\n  onAfterSuiteRun({ coverage, environment, projectName, testFiles }: AfterSuiteRunMeta): void {\n    if (!coverage) {\n      return\n    }\n\n    let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT)\n\n    if (!entry) {\n      entry = {}\n      this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry)\n    }\n\n    const testFilenames = testFiles.join()\n    const filename = resolve(\n      this.coverageFilesDirectory,\n      `coverage-${uniqueId++}.json`,\n    )\n\n    entry[environment] ??= {}\n    // If there's a result from previous run, overwrite it\n    entry[environment][testFilenames] = filename\n\n    const promise = fs.writeFile(filename, JSON.stringify(coverage), 'utf-8')\n    this.pendingPromises.push(promise)\n  }\n\n  async readCoverageFiles<CoverageType>({ onFileRead, onFinished, onDebug }: {\n    /** Callback invoked with a single coverage result */\n    onFileRead: (data: CoverageType) => void\n    /** Callback invoked once all results of a project for specific transform mode are read */\n    onFinished: (project: Vitest['projects'][number], environment: string) => Promise<void>\n    onDebug: ((...logs: any[]) => void) & { enabled: boolean }\n  }): Promise<void> {\n    let index = 0\n    const total = this.pendingPromises.length\n\n    await Promise.all(this.pendingPromises)\n    this.pendingPromises = []\n\n    for (const [projectName, coveragePerProject] of this.coverageFiles.entries()) {\n      for (const [environment, coverageByTestfiles] of Object.entries(coveragePerProject) as Entries<typeof coveragePerProject>) {\n        const filenames = Object.values(coverageByTestfiles)\n        const project = this.ctx.getProjectByName(projectName as string)\n\n        for (const chunk of this.toSlices(filenames, this.options.processingConcurrency)) {\n          if (onDebug.enabled) {\n            index += chunk.length\n            onDebug(`Reading coverage results ${index}/${total}`)\n          }\n\n          await Promise.all(chunk.map(async (filename) => {\n            const contents = await fs.readFile(filename, 'utf-8')\n            const coverage = JSON.parse(contents)\n\n            onFileRead(coverage)\n          }),\n          )\n        }\n\n        await onFinished(project, environment)\n      }\n    }\n  }\n\n  async cleanAfterRun(): Promise<void> {\n    this.coverageFiles = new Map()\n    await fs.rm(this.coverageFilesDirectory, { recursive: true })\n\n    // Remove empty reports directory, e.g. when only text-reporter is used\n    if (readdirSync(this.options.reportsDirectory).length === 0) {\n      await fs.rm(this.options.reportsDirectory, { recursive: true })\n    }\n  }\n\n  async onTestRunStart(): Promise<void> {\n    if (this.options.changed) {\n      const { VitestGit } = await import('./git')\n      const vitestGit = new VitestGit(this.ctx.config.root)\n      const changedFiles = await vitestGit.findChangedFiles({ changedSince: this.options.changed })\n\n      this.changedFiles = changedFiles ?? undefined\n    }\n    else if (this.ctx.config.changed) {\n      this.changedFiles = this.ctx.config.related\n    }\n\n    if (this.changedFiles) {\n      this.globCache.clear()\n    }\n  }\n\n  async onTestFailure(): Promise<void> {\n    if (!this.options.reportOnFailure) {\n      await this.cleanAfterRun()\n    }\n  }\n\n  async reportCoverage(coverageMap: unknown, { allTestsRun }: ReportContext): Promise<void> {\n    await this.generateReports(\n      (coverageMap as CoverageMap) || this.createCoverageMap(),\n      allTestsRun,\n    )\n\n    // In watch mode we need to preserve the previous results if cleanOnRerun is disabled\n    const keepResults = !this.options.cleanOnRerun && this.ctx.config.watch\n\n    if (!keepResults) {\n      await this.cleanAfterRun()\n    }\n  }\n\n  async reportThresholds(coverageMap: CoverageMap, allTestsRun: boolean | undefined): Promise<void> {\n    const resolvedThresholds = this.resolveThresholds(coverageMap)\n    this.checkThresholds(resolvedThresholds)\n\n    if (this.options.thresholds?.autoUpdate && allTestsRun) {\n      if (!this.ctx.vite.config.configFile) {\n        throw new Error(\n          'Missing configurationFile. The \"coverage.thresholds.autoUpdate\" can only be enabled when configuration file is used.',\n        )\n      }\n\n      const configFilePath = this.ctx.vite.config.configFile\n      const configModule = await this.parseConfigModule(configFilePath)\n\n      await this.updateThresholds({\n        thresholds: resolvedThresholds,\n        configurationFile: configModule,\n        onUpdate: () =>\n          writeFileSync(\n            configFilePath,\n            configModule.generate().code.replace(this.autoUpdateMarker, ''),\n            'utf-8',\n          ),\n\n      })\n    }\n  }\n\n  /**\n   * Constructs collected coverage and users' threshold options into separate sets\n   * where each threshold set holds their own coverage maps. Threshold set is either\n   * for specific files defined by glob pattern or global for all other files.\n   */\n  private resolveThresholds(coverageMap: CoverageMap): ResolvedThreshold[] {\n    const resolvedThresholds: ResolvedThreshold[] = []\n    const files = coverageMap.files()\n    const globalCoverageMap = this.createCoverageMap()\n\n    for (const key of Object.keys(this.options.thresholds!) as `${keyof NonNullable<typeof this.options.thresholds>}`[]) {\n      if (\n        key === 'perFile'\n        || key === 'autoUpdate'\n        || key === '100'\n        || THRESHOLD_KEYS.includes(key)\n      ) {\n        continue\n      }\n\n      const glob = key\n      const globThresholds = resolveGlobThresholds(this.options.thresholds![glob])\n      const globCoverageMap = this.createCoverageMap()\n\n      const matcher = pm(glob)\n      const matchingFiles = files.filter(file =>\n        matcher(relative(this.ctx.config.root, file)),\n      )\n\n      for (const file of matchingFiles) {\n        const fileCoverage = coverageMap.fileCoverageFor(file)\n        globCoverageMap.addFileCoverage(fileCoverage)\n      }\n\n      resolvedThresholds.push({\n        name: glob,\n        coverageMap: globCoverageMap,\n        thresholds: globThresholds,\n      })\n    }\n\n    // Global threshold is for all files, even if they are included by glob patterns\n    for (const file of files) {\n      const fileCoverage = coverageMap.fileCoverageFor(file)\n      globalCoverageMap.addFileCoverage(fileCoverage)\n    }\n\n    resolvedThresholds.unshift({\n      name: GLOBAL_THRESHOLDS_KEY,\n      coverageMap: globalCoverageMap,\n      thresholds: {\n        branches: this.options.thresholds?.branches,\n        functions: this.options.thresholds?.functions,\n        lines: this.options.thresholds?.lines,\n        statements: this.options.thresholds?.statements,\n      },\n    })\n\n    return resolvedThresholds\n  }\n\n  /**\n   * Check collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached.\n   */\n  private checkThresholds(allThresholds: ResolvedThreshold[]) {\n    for (const { coverageMap, thresholds, name } of allThresholds) {\n      if (\n        thresholds.branches === undefined\n        && thresholds.functions === undefined\n        && thresholds.lines === undefined\n        && thresholds.statements === undefined\n      ) {\n        continue\n      }\n\n      // Construct list of coverage summaries where thresholds are compared against\n      const summaries = this.options.thresholds?.perFile\n        ? coverageMap.files().map((file: string) => ({\n            file,\n            summary: coverageMap.fileCoverageFor(file).toSummary(),\n          }))\n        : [{ file: null, summary: coverageMap.getCoverageSummary() }]\n\n      // Check thresholds of each summary\n      for (const { summary, file } of summaries) {\n        for (const thresholdKey of THRESHOLD_KEYS) {\n          const threshold = thresholds[thresholdKey]\n\n          if (threshold === undefined) {\n            continue\n          }\n\n          /**\n           * Positive thresholds are treated as minimum coverage percentages (X means: X% of lines must be covered),\n           * while negative thresholds are treated as maximum uncovered counts (-X means: X lines may be uncovered).\n           */\n          if (threshold >= 0) {\n            const coverage = summary.data[thresholdKey].pct\n\n            if (coverage < threshold) {\n              process.exitCode = 1\n\n              /**\n               * Generate error message based on perFile flag:\n               * - ERROR: Coverage for statements (33.33%) does not meet threshold (85%) for src/math.ts\n               * - ERROR: Coverage for statements (50%) does not meet global threshold (85%)\n               */\n              let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet ${name === GLOBAL_THRESHOLDS_KEY ? name : `\"${name}\"`\n              } threshold (${threshold}%)`\n\n              if (this.options.thresholds?.perFile && file) {\n                errorMessage += ` for ${relative('./', file).replace(/\\\\/g, '/')}`\n              }\n\n              this.ctx.logger.error(errorMessage)\n            }\n          }\n          else {\n            const uncovered = summary.data[thresholdKey].total - summary.data[thresholdKey].covered\n            const absoluteThreshold = threshold * -1\n\n            if (uncovered > absoluteThreshold) {\n              process.exitCode = 1\n\n              /**\n               * Generate error message based on perFile flag:\n               * - ERROR: Uncovered statements (33) exceed threshold (30) for src/math.ts\n               * - ERROR: Uncovered statements (33) exceed global threshold (30)\n               */\n              let errorMessage = `ERROR: Uncovered ${thresholdKey} (${uncovered}) exceed ${name === GLOBAL_THRESHOLDS_KEY ? name : `\"${name}\"`\n              } threshold (${absoluteThreshold})`\n\n              if (this.options.thresholds?.perFile && file) {\n                errorMessage += ` for ${relative('./', file).replace(/\\\\/g, '/')}`\n              }\n\n              this.ctx.logger.error(errorMessage)\n            }\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Check if current coverage is above configured thresholds and bump the thresholds if needed\n   */\n  async updateThresholds({ thresholds: allThresholds, onUpdate, configurationFile }: {\n    thresholds: ResolvedThreshold[]\n    configurationFile: unknown // ProxifiedModule from magicast\n    onUpdate: () => void\n  }): Promise<void> {\n    let updatedThresholds = false\n\n    const config = resolveConfig(configurationFile)\n    assertConfigurationModule(config)\n\n    for (const { coverageMap, thresholds, name } of allThresholds) {\n      const summaries = this.options.thresholds?.perFile\n        ? coverageMap\n            .files()\n            .map((file: string) =>\n              coverageMap.fileCoverageFor(file).toSummary(),\n            )\n        : [coverageMap.getCoverageSummary()]\n\n      const thresholdsToUpdate: [Threshold, number][] = []\n\n      for (const key of THRESHOLD_KEYS) {\n        const threshold = thresholds[key] ?? 100\n        /**\n         * Positive thresholds are treated as minimum coverage percentages (X means: X% of lines must be covered),\n         * while negative thresholds are treated as maximum uncovered counts (-X means: X lines may be uncovered).\n         */\n        if (threshold >= 0) {\n          const actual = Math.min(\n            ...summaries.map(summary => summary[key].pct),\n          )\n\n          if (actual > threshold) {\n            thresholdsToUpdate.push([key, actual])\n          }\n        }\n        else {\n          const absoluteThreshold = threshold * -1\n          const actual = Math.max(\n            ...summaries.map(summary => summary[key].total - summary[key].covered),\n          )\n\n          if (actual < absoluteThreshold) {\n            // If everything was covered, set new threshold to 100% (since a threshold of 0 would be considered as 0%)\n            const updatedThreshold = actual === 0 ? 100 : actual * -1\n            thresholdsToUpdate.push([key, updatedThreshold])\n          }\n        }\n      }\n\n      if (thresholdsToUpdate.length === 0) {\n        continue\n      }\n\n      updatedThresholds = true\n\n      const thresholdFormatter = typeof this.options.thresholds?.autoUpdate === 'function' ? this.options.thresholds?.autoUpdate : (value: number) => value\n\n      for (const [threshold, newValue] of thresholdsToUpdate) {\n        const formattedValue = thresholdFormatter(newValue)\n        if (name === GLOBAL_THRESHOLDS_KEY) {\n          config.test.coverage.thresholds[threshold] = formattedValue\n        }\n        else {\n          const glob = config.test.coverage.thresholds[name as Threshold] as ResolvedThreshold['thresholds']\n          glob[threshold] = formattedValue\n        }\n      }\n    }\n\n    if (updatedThresholds) {\n      this.ctx.logger.log('Updating thresholds to configuration file. You may want to push with updated coverage thresholds.')\n      onUpdate()\n    }\n  }\n\n  async mergeReports(coverageMaps: unknown[]): Promise<void> {\n    const coverageMap = this.createCoverageMap()\n\n    for (const coverage of coverageMaps) {\n      coverageMap.merge(coverage as CoverageMap)\n    }\n\n    await this.generateReports(coverageMap, true)\n  }\n\n  hasTerminalReporter(reporters: ResolvedCoverageOptions['reporter']): boolean {\n    return reporters.some(\n      ([reporter]) =>\n        reporter === 'text'\n        || reporter === 'text-summary'\n        || reporter === 'text-lcov'\n        || reporter === 'teamcity',\n    )\n  }\n\n  toSlices<T>(array: T[], size: number): T[][] {\n    return array.reduce<T[][]>((chunks, item) => {\n      const index = Math.max(0, chunks.length - 1)\n      const lastChunk = chunks[index] || []\n      chunks[index] = lastChunk\n\n      if (lastChunk.length >= size) {\n        chunks.push([item])\n      }\n      else {\n        lastChunk.push(item)\n      }\n\n      return chunks\n    }, [])\n  }\n\n  // TODO: should this be abstracted in `project`/`vitest` instead?\n  // if we decide to keep `viteModuleRunner: false`, we will need to abstract transformation in both main thread and tests\n  // custom --import=module.registerHooks need to be transformed as well somehow\n  async transformFile(url: string, project: TestProject, viteEnvironment: string): Promise<TransformResult | null | undefined> {\n    const config = project.config\n\n    // vite is disabled, should transform manually if possible\n    if (config.experimental.viteModuleRunner === false) {\n      const pathname = url.split('?')[0]\n      const filename = pathname.startsWith('file://') ? fileURLToPath(pathname) : pathname\n      const extension = path.extname(filename)\n      const isTypeScript = extension === '.ts' || extension === '.mts' || extension === '.cts'\n      if (!isTypeScript) {\n        const code = await fs.readFile(filename, 'utf-8')\n        return { code, map: null }\n      }\n      if (!module.stripTypeScriptTypes) {\n        throw new Error(`Cannot parse '${url}' because \"module.stripTypeScriptTypes\" is not supported. TypeScript coverage requires Node.js 22.15 or higher. This is NOT a bug of Vitest.`)\n      }\n      const isTransform = process.execArgv.includes('--experimental-transform-types')\n        || config.execArgv.includes('--experimental-transform-types')\n        || process.env.NODE_OPTIONS?.includes('--experimental-transform-types')\n        || config.env?.NODE_OPTIONS?.includes('--experimental-transform-types')\n      const code = await fs.readFile(filename, 'utf-8')\n      return {\n        // `transform` mode will inject source maps comment at the end\n        code: module.stripTypeScriptTypes(code, { mode: isTransform ? 'transform' : 'strip' }),\n        map: null,\n      }\n    }\n\n    if (project.isBrowserEnabled() || viteEnvironment === '__browser__') {\n      const client = project.browser?.vite.environments.client || project.vite.environments.client\n      const result = await client.transformRequest(url)\n\n      if (result) {\n        return result\n      }\n    }\n\n    return project.vite.environments[viteEnvironment].transformRequest(url)\n  }\n\n  createUncoveredFileTransformer(ctx: Vitest) {\n    const projects = new Set([\n      ...ctx.projects,\n      // Check core last as it will match all files anyway\n      ctx.getRootProject(),\n    ])\n\n    return async (filename: string): Promise<TransformResult | null | undefined> => {\n      let lastError\n\n      for (const project of projects) {\n        const root = project.config.root\n\n        // On Windows root doesn't start with \"/\" while filenames do\n        if (!filename.startsWith(root) && !filename.startsWith(`/${root}`)) {\n          continue\n        }\n\n        try {\n          const environment = project.config.environment\n          const viteEnvironment = environment === 'jsdom' || environment === 'happy-dom' ? 'client' : 'ssr'\n          return await this.transformFile(filename, project, viteEnvironment)\n        }\n        catch (err) {\n          lastError = err\n        }\n      }\n\n      // All vite servers failed to transform the file\n      throw lastError\n    }\n  }\n}\n\n/**\n * Narrow down `unknown` glob thresholds to resolved ones\n */\nfunction resolveGlobThresholds(\n  thresholds: unknown,\n): ResolvedThreshold['thresholds'] {\n  if (!thresholds || typeof thresholds !== 'object') {\n    return {}\n  }\n\n  if (100 in thresholds && thresholds[100] === true) {\n    return {\n      lines: 100,\n      branches: 100,\n      functions: 100,\n      statements: 100,\n    }\n  }\n\n  return {\n    lines:\n      'lines' in thresholds && typeof thresholds.lines === 'number'\n        ? thresholds.lines\n        : undefined,\n    branches:\n      'branches' in thresholds && typeof thresholds.branches === 'number'\n        ? thresholds.branches\n        : undefined,\n    functions:\n      'functions' in thresholds && typeof thresholds.functions === 'number'\n        ? thresholds.functions\n        : undefined,\n    statements:\n      'statements' in thresholds && typeof thresholds.statements === 'number'\n        ? thresholds.statements\n        : undefined,\n  }\n}\n\nfunction assertConfigurationModule(config: unknown): asserts config is {\n  test: {\n    coverage: { thresholds: NonNullable<BaseCoverageOptions['thresholds']> }\n  }\n} {\n  try {\n    // @ts-expect-error -- Intentional unsafe null pointer check as wrapped in try-catch\n    if (typeof config.test.coverage.thresholds !== 'object') {\n      throw new TypeError(\n        'Expected config.test.coverage.thresholds to be an object',\n      )\n    }\n  }\n  catch (error) {\n    const message = error instanceof Error ? error.message : String(error)\n    throw new Error(\n      `Unable to parse thresholds from configuration file: ${message}`,\n    )\n  }\n}\n\nfunction resolveConfig(configModule: any) {\n  const mod = configModule.exports.default\n\n  try {\n    // Check for \"export default { test: {...} }\"\n    if (mod.$type === 'object') {\n      return mod\n    }\n\n    // \"export default defineConfig(...)\"\n    let config = resolveDefineConfig(mod)\n    if (config) {\n      return config\n    }\n\n    // \"export default mergeConfig(..., defineConfig(...))\"\n    if (mod.$type === 'function-call' && mod.$callee === 'mergeConfig') {\n      config = resolveMergeConfig(mod)\n      if (config) {\n        return config\n      }\n    }\n  }\n  catch (error) {\n    // Reduce magicast's verbose errors to readable ones\n    throw new Error(error instanceof Error ? error.message : String(error))\n  }\n\n  throw new Error(\n    'Failed to update coverage thresholds. Configuration file is too complex.',\n  )\n}\n\nfunction resolveDefineConfig(mod: any) {\n  if (mod.$type === 'function-call' && mod.$callee === 'defineConfig') {\n    // \"export default defineConfig({ test: {...} })\"\n    if (mod.$args[0].$type === 'object') {\n      return mod.$args[0]\n    }\n\n    if (mod.$args[0].$type === 'arrow-function-expression') {\n      if (mod.$args[0].$body.$type === 'object') {\n        // \"export default defineConfig(() => ({ test: {...} }))\"\n        return mod.$args[0].$body\n      }\n\n      // \"export default defineConfig(() => mergeConfig({...}, ...))\"\n      const config = resolveMergeConfig(mod.$args[0].$body)\n      if (config) {\n        return config\n      }\n    }\n  }\n}\n\nfunction resolveMergeConfig(mod: any): any {\n  if (mod.$type === 'function-call' && mod.$callee === 'mergeConfig') {\n    for (const arg of mod.$args) {\n      const config = resolveDefineConfig(arg)\n      if (config) {\n        return config\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/create.ts",
    "content": "import type {\n  InlineConfig as ViteInlineConfig,\n  UserConfig as ViteUserConfig,\n} from 'vite'\nimport type { CliOptions } from './cli/cli-api'\nimport type { VitestOptions } from './core'\nimport type { VitestRunMode } from './types/config'\nimport { resolve } from 'node:path'\nimport { deepClone, slash } from '@vitest/utils/helpers'\nimport * as find from 'empathic/find'\nimport { resolveModule } from 'local-pkg'\nimport { mergeConfig } from 'vite'\nimport { configFiles } from '../constants'\nimport { Vitest } from './core'\nimport { VitestPlugin } from './plugins'\nimport { createViteServer } from './vite'\n\nexport async function createVitest(\n  mode: VitestRunMode,\n  options: CliOptions,\n  viteOverrides: ViteUserConfig = {},\n  vitestOptions: VitestOptions = {},\n): Promise<Vitest> {\n  const ctx = new Vitest(mode, deepClone(options), vitestOptions)\n  const root = slash(resolve(options.root || process.cwd()))\n\n  const configPath\n    = options.config === false\n      ? false\n      : options.config\n        ? (resolveModule(options.config, { paths: [root] }) ?? resolve(root, options.config))\n        : find.any(configFiles, { cwd: root })\n\n  options.config = configPath\n\n  const { browser: _removeBrowser, ...restOptions } = options\n\n  const config: ViteInlineConfig = {\n    configFile: configPath,\n    configLoader: options.configLoader,\n    // this will make \"mode\": \"test\" | \"benchmark\" inside defineConfig\n    mode: options.mode || mode,\n    plugins: await VitestPlugin(restOptions, ctx),\n  }\n\n  try {\n    const server = await createViteServer(\n      mergeConfig(config, mergeConfig(viteOverrides, { root: options.root })),\n    )\n\n    if (ctx.config.api?.port) {\n      await server.listen()\n    }\n\n    return ctx\n  }\n  // Vitest can fail at any point inside \"setServer\" or inside a custom plugin\n  // Then we need to make sure everything was properly closed (like the logger)\n  catch (error) {\n    await ctx.close()\n    throw error\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/environments/fetchModule.ts",
    "content": "import type { Span } from '@opentelemetry/api'\nimport type { DevEnvironment, EnvironmentModuleNode, FetchResult, Rollup, TransformResult } from 'vite'\nimport type { FetchFunctionOptions } from 'vite/module-runner'\nimport type { FetchCachedFileSystemResult } from '../../types/general'\nimport type { OTELCarrier, Traces } from '../../utils/traces'\nimport type { FileSystemModuleCache } from '../cache/fsModuleCache'\nimport type { VitestResolver } from '../resolver'\nimport type { ResolvedConfig } from '../types/config'\nimport { existsSync, mkdirSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { isExternalUrl, unwrapId } from '@vitest/utils/helpers'\nimport { join } from 'pathe'\nimport { fetchModule } from 'vite'\nimport { hash } from '../hash'\nimport { normalizeResolvedIdToUrl } from './normalizeUrl'\n\nconst saveCachePromises = new Map<string, Promise<FetchResult>>()\nconst readFilePromises = new Map<string, Promise<string | null>>()\n\nclass ModuleFetcher {\n  private tmpDirectories = new Set<string>()\n  private fsCacheEnabled: boolean\n\n  constructor(\n    private resolver: VitestResolver,\n    private config: ResolvedConfig,\n    private fsCache: FileSystemModuleCache,\n    private tmpProjectDir: string,\n  ) {\n    this.fsCacheEnabled = config.experimental?.fsModuleCache === true\n  }\n\n  async fetch(\n    trace: Span,\n    url: string,\n    importer: string | undefined,\n    environment: DevEnvironment,\n    makeTmpCopies?: boolean,\n    options?: FetchFunctionOptions,\n  ): Promise<FetchResult | FetchCachedFileSystemResult> {\n    if (url.startsWith('data:')) {\n      trace.setAttribute('vitest.module.external', url)\n      return { externalize: url, type: 'builtin' }\n    }\n\n    if (url === '/@vite/client' || url === '@vite/client') {\n      trace.setAttribute('vitest.module.external', url)\n      return { externalize: '/@vite/client', type: 'module' }\n    }\n\n    const isFileUrl = url.startsWith('file://')\n\n    if (isExternalUrl(url) && !isFileUrl) {\n      trace.setAttribute('vitest.module.external', url)\n      return { externalize: url, type: 'network' }\n    }\n\n    // handle unresolved id of dynamic import skipped by Vite import analysis\n    if (url[0] !== '/') {\n      const resolved = await environment.pluginContainer.resolveId(url, importer)\n      if (resolved) {\n        url = normalizeResolvedIdToUrl(environment, resolved.id)\n      }\n    }\n\n    const moduleGraphModule = await environment.moduleGraph.ensureEntryFromUrl(unwrapId(url))\n    const cached = !!moduleGraphModule.transformResult\n\n    if (moduleGraphModule.file) {\n      trace.setAttribute('code.file.path', moduleGraphModule.file)\n    }\n\n    if (options?.cached && cached) {\n      return { cache: true }\n    }\n\n    const externalize = await this.resolver.shouldExternalize(moduleGraphModule.id!)\n    if (externalize) {\n      return { externalize, type: 'module' }\n    }\n\n    const cachePath = await this.getCachePath(\n      environment,\n      moduleGraphModule,\n    )\n\n    // full fs caching is disabled, but we still want to keep tmp files if makeTmpCopies is enabled\n    // this is primarily used by the forks pool to avoid using process.send(bigBuffer)\n    if (cachePath == null) {\n      const result = await this.fetchAndProcess(environment, url, importer, moduleGraphModule, options)\n\n      this.recordResult(trace, result)\n\n      if (!makeTmpCopies || !('code' in result)) {\n        return result\n      }\n\n      const transformResult = moduleGraphModule.transformResult\n      const tmpPath = transformResult && Reflect.get(transformResult, '_vitest_tmp')\n      if (typeof tmpPath === 'string') {\n        return getCachedResult(result, tmpPath)\n      }\n\n      const tmpDir = join(this.tmpProjectDir, environment.name)\n      if (!this.tmpDirectories.has(tmpDir)) {\n        if (!existsSync(tmpDir)) {\n          mkdirSync(tmpDir, { recursive: true })\n        }\n        this.tmpDirectories.add(tmpDir)\n      }\n\n      const tmpFile = join(tmpDir, hash('sha1', result.id, 'hex'))\n      return this.cacheResult(result, tmpFile).then((result) => {\n        if (transformResult) {\n          Reflect.set(transformResult, '_vitest_tmp', tmpFile)\n        }\n        return result\n      })\n    }\n\n    if (saveCachePromises.has(cachePath)) {\n      return saveCachePromises.get(cachePath)!.then((result) => {\n        this.recordResult(trace, result)\n        return result\n      })\n    }\n\n    const cachedModule = await this.getCachedModule(cachePath, environment, moduleGraphModule, importer)\n    if (cachedModule) {\n      this.recordResult(trace, cachedModule)\n      return cachedModule\n    }\n\n    const result = await this.fetchAndProcess(environment, url, importer, moduleGraphModule, options)\n    const importedUrls = this.getSerializedImports(moduleGraphModule)\n    const map = moduleGraphModule.transformResult?.map\n    const mappings = map && !('version' in map) && map.mappings === ''\n\n    return this.cacheResult(result, cachePath, importedUrls, !!mappings)\n  }\n\n  // we need this for UI to be able to show a module graph\n  private getSerializedImports(node: EnvironmentModuleNode): string[] {\n    const imports: string[] = []\n    node.importedModules.forEach((importer) => {\n      imports.push(importer.url)\n    })\n    return imports\n  }\n\n  private recordResult(trace: Span, result: FetchResult | FetchCachedFileSystemResult): void {\n    if ('externalize' in result) {\n      trace.setAttributes({\n        'vitest.fetched_module.external': result.externalize,\n        'vitest.fetched_module.type': result.type,\n      })\n    }\n    if ('id' in result) {\n      trace.setAttributes({\n        'vitest.fetched_module.invalidate': result.invalidate,\n        'vitest.fetched_module.id': result.id,\n        'vitest.fetched_module.url': result.url,\n        'vitest.fetched_module.cache': false,\n      })\n      if (result.file) {\n        trace.setAttribute('code.file.path', result.file)\n      }\n    }\n    if ('code' in result) {\n      trace.setAttribute('vitest.fetched_module.code_length', result.code.length)\n    }\n  }\n\n  private async getCachePath(environment: DevEnvironment, moduleGraphModule: EnvironmentModuleNode): Promise<null | string> {\n    if (!this.fsCacheEnabled) {\n      return null\n    }\n    const moduleId = moduleGraphModule.id!\n\n    const memoryCacheKey = this.fsCache.getMemoryCachePath(environment, moduleId)\n    // undefined means there is no key in memory\n    // null means the file should not be cached\n    if (memoryCacheKey !== undefined) {\n      return memoryCacheKey\n    }\n\n    const fileContent = await this.readFileContentToCache(environment, moduleGraphModule)\n    return this.fsCache.generateCachePath(\n      this.config,\n      environment,\n      moduleGraphModule.id!,\n      fileContent,\n    )\n  }\n\n  private async readFileContentToCache(\n    environment: DevEnvironment,\n    moduleGraphModule: EnvironmentModuleNode,\n  ): Promise<string> {\n    if (\n      moduleGraphModule.file\n      // \\x00 is a virtual file convention\n      && !moduleGraphModule.file.startsWith('\\x00')\n      && !moduleGraphModule.file.startsWith('virtual:')\n    ) {\n      const result = await this.readFileConcurrently(moduleGraphModule.file)\n      if (result != null) {\n        return result\n      }\n    }\n\n    const loadResult = await environment.pluginContainer.load(moduleGraphModule.id!)\n    if (typeof loadResult === 'string') {\n      return loadResult\n    }\n    if (loadResult != null) {\n      return loadResult.code\n    }\n    return ''\n  }\n\n  private async getCachedModule(\n    cachePath: string,\n    environment: DevEnvironment,\n    moduleGraphModule: EnvironmentModuleNode,\n    importer: string | undefined,\n  ): Promise<FetchResult | FetchCachedFileSystemResult | undefined> {\n    if (moduleGraphModule.transformResult?.__vitestTmp) {\n      return {\n        cached: true as const,\n        file: moduleGraphModule.file,\n        id: moduleGraphModule.id!,\n        tmp: moduleGraphModule.transformResult.__vitestTmp,\n        url: moduleGraphModule.url,\n        invalidate: false,\n      }\n    }\n\n    const cachedModule = await this.fsCache.getCachedModule(cachePath)\n\n    if (!cachedModule) {\n      return\n    }\n\n    // keep the module graph in sync\n    let map: Rollup.SourceMap | null | { mappings: '' } = extractSourceMap(cachedModule.code)\n    if (map && cachedModule.file) {\n      map.file = cachedModule.file\n    }\n    // mappings is a special source map identifier in rollup\n    if (!map && cachedModule.mappings) {\n      map = { mappings: '' }\n    }\n    moduleGraphModule.transformResult = {\n      code: cachedModule.code,\n      map,\n      ssr: true,\n      __vitestTmp: cachePath,\n    }\n\n    // we populate the module graph to make the watch mode work because it relies on importers\n    if (importer) {\n      const environmentNode = environment.moduleGraph.getModuleById(importer)\n      if (environmentNode) {\n        moduleGraphModule.importers.add(environmentNode)\n      }\n    }\n\n    await Promise.all(cachedModule.importedUrls.map(async (url) => {\n      const moduleNode = await environment.moduleGraph.ensureEntryFromUrl(url).catch(() => null)\n      if (moduleNode) {\n        moduleNode.importers.add(moduleGraphModule)\n        moduleGraphModule.importedModules.add(moduleNode)\n      }\n    }))\n\n    return {\n      cached: true as const,\n      file: cachedModule.file,\n      id: cachedModule.id,\n      tmp: cachePath,\n      url: cachedModule.url,\n      invalidate: false,\n    }\n  }\n\n  private async fetchAndProcess(\n    environment: DevEnvironment,\n    url: string,\n    importer: string | undefined,\n    moduleGraphModule: EnvironmentModuleNode,\n    options?: FetchFunctionOptions,\n  ): Promise<FetchResult> {\n    const moduleRunnerModule = await fetchModule(\n      environment,\n      url,\n      importer,\n      {\n        ...options,\n        inlineSourceMap: false,\n      },\n    ).catch(handleRollupError)\n\n    return processResultSource(environment, moduleRunnerModule)\n  }\n\n  private async cacheResult(\n    result: FetchResult,\n    cachePath: string,\n    importedUrls: string[] = [],\n    mappings = false,\n  ): Promise<FetchResult | FetchCachedFileSystemResult> {\n    const returnResult = 'code' in result\n      ? getCachedResult(result, cachePath)\n      : result\n\n    if (saveCachePromises.has(cachePath)) {\n      await saveCachePromises.get(cachePath)\n      return returnResult\n    }\n\n    const savePromise = this.fsCache\n      .saveCachedModule(cachePath, result, importedUrls, mappings)\n      .then(() => result)\n      .finally(() => {\n        saveCachePromises.delete(cachePath)\n      })\n\n    saveCachePromises.set(cachePath, savePromise)\n    await savePromise\n\n    return returnResult\n  }\n\n  private readFileConcurrently(file: string): Promise<string | null> {\n    if (!readFilePromises.has(file)) {\n      readFilePromises.set(\n        file,\n        // virtual file can have a \"file\" property\n        readFile(file, 'utf-8').catch(() => null).finally(() => {\n          readFilePromises.delete(file)\n        }),\n      )\n    }\n    return readFilePromises.get(file)!\n  }\n}\n\nexport interface VitestFetchFunction {\n  (\n    url: string,\n    importer: string | undefined,\n    environment: DevEnvironment,\n    cacheFs?: boolean,\n    options?: FetchFunctionOptions,\n    otelCarrier?: OTELCarrier\n  ): Promise<FetchResult | FetchCachedFileSystemResult>\n}\n\nexport function createFetchModuleFunction(\n  resolver: VitestResolver,\n  config: ResolvedConfig,\n  fsCache: FileSystemModuleCache,\n  traces: Traces,\n  tmpProjectDir: string,\n): VitestFetchFunction {\n  const fetcher = new ModuleFetcher(resolver, config, fsCache, tmpProjectDir)\n  return async (url, importer, environment, cacheFs, options, otelCarrier) => {\n    await traces.waitInit()\n    const context = otelCarrier\n      ? traces.getContextFromCarrier(otelCarrier)\n      : undefined\n    return traces.$(\n      'vitest.module.transform',\n      context\n        ? { context }\n        : {},\n      span => fetcher.fetch(span, url, importer, environment, cacheFs, options),\n    )\n  }\n}\n\nlet SOURCEMAPPING_URL = 'sourceMa'\nSOURCEMAPPING_URL += 'ppingURL'\n\nconst MODULE_RUNNER_SOURCEMAPPING_SOURCE = '//# sourceMappingSource=vite-generated'\n\nfunction processResultSource(environment: DevEnvironment, result: FetchResult): FetchResult {\n  if (!('code' in result)) {\n    return result\n  }\n\n  const node = environment.moduleGraph.getModuleById(result.id)\n  if (node?.transformResult) {\n    // this also overrides node.transformResult.code which is also what the module\n    // runner does under the hood by default (we disable source maps inlining)\n    inlineSourceMap(node.transformResult)\n  }\n\n  return {\n    ...result,\n    code: node?.transformResult?.code || result.code,\n  }\n}\n\nconst OTHER_SOURCE_MAP_REGEXP = new RegExp(\n  `//# ${SOURCEMAPPING_URL}=data:application/json[^,]+base64,([A-Za-z0-9+/=]+)$`,\n  'gm',\n)\n\n// we have to inline the source map ourselves, because\n// - we don't need //# sourceURL since we are running code in VM\n//   - important in stack traces and the V8 coverage\n// - we need to inject an empty line for --inspect-brk\nfunction inlineSourceMap(result: TransformResult) {\n  const map = result.map\n  let code = result.code\n\n  if (\n    !map\n    || !('version' in map)\n    || code.includes(MODULE_RUNNER_SOURCEMAPPING_SOURCE)\n  ) {\n    return result\n  }\n\n  // to reduce the payload size, we only inline vite node source map, because it's also the only one we use\n  OTHER_SOURCE_MAP_REGEXP.lastIndex = 0\n  if (OTHER_SOURCE_MAP_REGEXP.test(code)) {\n    code = code.replace(OTHER_SOURCE_MAP_REGEXP, '')\n  }\n\n  const sourceMap = { ...map }\n\n  // If the first line is not present on source maps, add simple 1:1 mapping ([0,0,0,0], [1,0,0,0])\n  // so that debuggers can be set to break on first line\n  if (sourceMap.mappings[0] === ';') {\n    sourceMap.mappings = `AAAA,CAAA${sourceMap.mappings}`\n  }\n\n  result.code = `${code.trimEnd()}\\n${\n    MODULE_RUNNER_SOURCEMAPPING_SOURCE\n  }\\n//# ${SOURCEMAPPING_URL}=${genSourceMapUrl(sourceMap)}\\n`\n\n  return result\n}\n\nfunction genSourceMapUrl(map: Rollup.SourceMap | string): string {\n  if (typeof map !== 'string') {\n    map = JSON.stringify(map)\n  }\n  return `data:application/json;base64,${Buffer.from(map).toString('base64')}`\n}\n\nfunction getCachedResult(result: Extract<FetchResult, { code: string }>, tmp: string): FetchCachedFileSystemResult {\n  return {\n    cached: true as const,\n    file: result.file,\n    id: result.id,\n    tmp,\n    url: result.url,\n    invalidate: result.invalidate,\n  }\n}\n\nconst MODULE_RUNNER_SOURCEMAPPING_REGEXP = new RegExp(\n  `//# ${SOURCEMAPPING_URL}=data:application/json;base64,(.+)`,\n)\n\nfunction extractSourceMap(code: string): null | Rollup.SourceMap {\n  const pattern = `//# ${SOURCEMAPPING_URL}=data:application/json;base64,`\n  const lastIndex = code.lastIndexOf(pattern)\n  if (lastIndex === -1) {\n    return null\n  }\n\n  const mapString = MODULE_RUNNER_SOURCEMAPPING_REGEXP.exec(\n    code.slice(lastIndex),\n  )?.[1]\n  if (!mapString) {\n    return null\n  }\n  const sourceMap = JSON.parse(Buffer.from(mapString, 'base64').toString('utf-8'))\n  // remove source map mapping added by \"inlineSourceMap\" to keep the original behaviour of transformRequest\n  if (sourceMap.mappings.startsWith('AAAA,CAAA;')) {\n    // 9 because we want to only remove \"AAAA,CAAA\", but keep ; at the start\n    sourceMap.mappings = sourceMap.mappings.slice(9)\n  }\n  return sourceMap\n}\n\n// serialize rollup error on server to preserve details as a test error\nexport function handleRollupError(e: unknown): never {\n  if (\n    e instanceof Error\n    && ('plugin' in e || 'frame' in e || 'id' in e)\n  ) {\n    // eslint-disable-next-line no-throw-literal\n    throw {\n      name: e.name,\n      message: e.message,\n      stack: e.stack,\n      cause: e.cause,\n      __vitest_rollup_error__: {\n        plugin: (e as any).plugin,\n        id: (e as any).id,\n        loc: (e as any).loc,\n        frame: (e as any).frame,\n      },\n    }\n  }\n  throw e\n}\n\ndeclare module 'vite' {\n  export interface TransformResult {\n    __vitestTmp?: string\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/environments/normalizeUrl.ts",
    "content": "import type { DevEnvironment } from 'vite'\nimport { existsSync } from 'node:fs'\nimport path from 'node:path'\nimport { cleanUrl, withTrailingSlash, wrapId } from '@vitest/utils/helpers'\n\n// this is copy pasted from vite\nexport function normalizeResolvedIdToUrl(\n  environment: DevEnvironment,\n  resolvedId: string,\n): string {\n  const root = environment.config.root\n  const depsOptimizer = environment.depsOptimizer\n\n  let url: string\n\n  // normalize all imports into resolved URLs\n  // e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js'`\n  if (resolvedId.startsWith(withTrailingSlash(root))) {\n    // in root: infer short absolute path from root\n    url = resolvedId.slice(root.length)\n  }\n  else if (\n    depsOptimizer?.isOptimizedDepFile(resolvedId)\n    // vite-plugin-react isn't following the leading \\0 virtual module convention.\n    // This is a temporary hack to avoid expensive fs checks for React apps.\n    // We'll remove this as soon we're able to fix the react plugins.\n    || (resolvedId !== '/@react-refresh'\n      && path.isAbsolute(resolvedId)\n      && existsSync(cleanUrl(resolvedId)))\n  ) {\n    // an optimized deps may not yet exists in the filesystem, or\n    // a regular file exists but is out of root: rewrite to absolute /@fs/ paths\n    url = path.posix.join('/@fs/', resolvedId)\n  }\n  else {\n    url = resolvedId\n  }\n\n  // if the resolved id is not a valid browser import specifier,\n  // prefix it to make it valid. We will strip this before feeding it\n  // back into the transform pipeline\n  if (url[0] !== '.' && url[0] !== '/') {\n    url = wrapId(resolvedId)\n  }\n\n  return url\n}\n"
  },
  {
    "path": "packages/vitest/src/node/environments/serverRunner.ts",
    "content": "import type { DevEnvironment } from 'vite'\nimport type { ResolvedConfig } from '../types/config'\nimport type { VitestFetchFunction } from './fetchModule'\nimport { readFile } from 'node:fs/promises'\nimport { VitestModuleEvaluator } from '#module-evaluator'\nimport { ModuleRunner } from 'vite/module-runner'\nimport { normalizeResolvedIdToUrl } from './normalizeUrl'\n\nexport class ServerModuleRunner extends ModuleRunner {\n  constructor(\n    private environment: DevEnvironment,\n    fetcher: VitestFetchFunction,\n    private config: ResolvedConfig,\n  ) {\n    super(\n      {\n        hmr: false,\n        transport: {\n          async invoke(event) {\n            if (event.type !== 'custom') {\n              throw new Error(`Vitest Module Runner doesn't support Vite HMR events.`)\n            }\n            const { name, data } = event.data\n            if (name === 'getBuiltins') {\n              return await environment.hot.handleInvoke(event)\n            }\n            if (name !== 'fetchModule') {\n              return { error: new Error(`Unknown method: ${name}. Expected \"fetchModule\".`) }\n            }\n            try {\n              const result = await fetcher(data[0], data[1], environment, false, data[2])\n              if ('tmp' in result) {\n                const code = await readFile(result.tmp)\n                return { result: { ...result, code } }\n              }\n              return { result }\n            }\n            catch (error) {\n              return { error }\n            }\n          },\n        },\n      },\n      new VitestModuleEvaluator(),\n    )\n  }\n\n  async import(rawId: string): Promise<any> {\n    const resolved = await this.environment.pluginContainer.resolveId(\n      rawId,\n      this.config.root,\n    )\n    if (!resolved) {\n      return super.import(rawId)\n    }\n    // Vite will make \"@vitest/coverage-v8\" into \"@vitest/coverage-v8.js\" url\n    // instead of using an actual file path-like URL, so we resolve it here first\n    const url = normalizeResolvedIdToUrl(this.environment, resolved.id)\n    return super.import(url)\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/errors.ts",
    "content": "export class FilesNotFoundError extends Error {\n  code = 'VITEST_FILES_NOT_FOUND'\n\n  constructor(mode: 'test' | 'benchmark') {\n    super(`No ${mode} files found`)\n  }\n}\n\nexport class GitNotFoundError extends Error {\n  code = 'VITEST_GIT_NOT_FOUND'\n\n  constructor() {\n    super('Could not find Git root. Have you initialized git with `git init`?')\n  }\n}\n\nexport class LocationFilterFileNotFoundError extends Error {\n  code = 'VITEST_LOCATION_FILTER_FILE_NOT_FOUND'\n\n  constructor(filename: string) {\n    super(`Couldn\\'t find file ${filename}. Note when specifying the test `\n      + 'location you have to specify the full test filename.')\n  }\n}\n\nexport class IncludeTaskLocationDisabledError extends Error {\n  code = 'VITEST_INCLUDE_TASK_LOCATION_DISABLED'\n\n  constructor() {\n    super('Received line number filters while `includeTaskLocation` option is disabled')\n  }\n}\n\nexport class RangeLocationFilterProvidedError extends Error {\n  code = 'VITEST_RANGE_LOCATION_FILTER_PROVIDED'\n\n  constructor(filter: string) {\n    super(`Found \"-\" in location filter ${filter}.  Note that range location filters `\n      + `are not supported.  Consider specifying the exact line numbers of your tests.`)\n  }\n}\n\nexport class VitestFilteredOutProjectError extends Error {\n  code = 'VITEST_FILTERED_OUT_PROJECT'\n\n  constructor() {\n    super('VITEST_FILTERED_OUT_PROJECT')\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/git.ts",
    "content": "import type { Output } from 'tinyexec'\nimport { resolve } from 'pathe'\nimport { x } from 'tinyexec'\n\nexport interface GitOptions {\n  changedSince?: string | boolean\n}\n\nexport class VitestGit {\n  private root!: string\n\n  constructor(private cwd: string) {}\n\n  private async resolveFilesWithGitCommand(args: string[]): Promise<string[]> {\n    let result: Output\n\n    try {\n      result = await x('git', args, { nodeOptions: { cwd: this.root } })\n    }\n    catch (e: any) {\n      e.message = e.stderr\n\n      throw e\n    }\n\n    return result.stdout\n      .split('\\n')\n      .filter(s => s !== '')\n      .map(changedPath => resolve(this.root, changedPath))\n  }\n\n  async findChangedFiles(options: GitOptions): Promise<string[] | null> {\n    const root = await this.getRoot(this.cwd)\n    if (!root) {\n      return null\n    }\n\n    this.root = root\n\n    const changedSince = options.changedSince\n    if (typeof changedSince === 'string') {\n      const [committed, staged, unstaged] = await Promise.all([\n        this.getFilesSince(changedSince),\n        this.getStagedFiles(),\n        this.getUnstagedFiles(),\n      ])\n      return [...committed, ...staged, ...unstaged]\n    }\n    const [staged, unstaged] = await Promise.all([\n      this.getStagedFiles(),\n      this.getUnstagedFiles(),\n    ])\n    return [...staged, ...unstaged]\n  }\n\n  private getFilesSince(hash: string) {\n    return this.resolveFilesWithGitCommand([\n      'diff',\n      '--name-only',\n      `${hash}...HEAD`,\n    ])\n  }\n\n  private getStagedFiles() {\n    return this.resolveFilesWithGitCommand(['diff', '--cached', '--name-only'])\n  }\n\n  private getUnstagedFiles() {\n    return this.resolveFilesWithGitCommand([\n      'ls-files',\n      '--other',\n      '--modified',\n      '--exclude-standard',\n    ])\n  }\n\n  async getRoot(cwd: string): Promise<string | null> {\n    const args = ['rev-parse', '--show-cdup']\n\n    try {\n      const result = await x('git', args, { nodeOptions: { cwd } })\n\n      return resolve(cwd, result.stdout.trim())\n    }\n    catch {\n      return null\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/globalSetup.ts",
    "content": "import type { ModuleRunner } from 'vite/module-runner'\nimport type { TestProject } from './project'\nimport { toArray } from '@vitest/utils/helpers'\n\nexport interface GlobalSetupFile {\n  file: string\n  setup?: (context: TestProject) => Promise<Function | void> | void\n  teardown?: Function\n}\n\nexport async function loadGlobalSetupFiles(\n  runner: ModuleRunner,\n  globalSetup: string | string[],\n): Promise<GlobalSetupFile[]> {\n  const globalSetupFiles = toArray(globalSetup)\n  return Promise.all(\n    globalSetupFiles.map(file => loadGlobalSetupFile(file, runner)),\n  )\n}\n\nasync function loadGlobalSetupFile(\n  file: string,\n  runner: ModuleRunner,\n): Promise<GlobalSetupFile> {\n  const m = await runner.import(file)\n  for (const exp of ['default', 'setup', 'teardown']) {\n    if (m[exp] != null && typeof m[exp] !== 'function') {\n      throw new Error(\n        `invalid export in globalSetup file ${file}: ${exp} must be a function`,\n      )\n    }\n  }\n  if (m.default) {\n    return {\n      file,\n      setup: m.default,\n    }\n  }\n  else if (m.setup || m.teardown) {\n    return {\n      file,\n      setup: m.setup,\n      teardown: m.teardown,\n    }\n  }\n  else {\n    throw new Error(\n      `invalid globalSetup file ${file}. Must export setup, teardown or have a default export`,\n    )\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/hash.ts",
    "content": "import crypto from 'node:crypto'\n\nexport const hash: typeof crypto.hash = crypto.hash ?? ((\n  algorithm: string,\n  data: crypto.BinaryLike,\n  outputEncoding: crypto.BinaryToTextEncoding,\n) => crypto.createHash(algorithm).update(data).digest(outputEncoding))\n"
  },
  {
    "path": "packages/vitest/src/node/logger.ts",
    "content": "import type { Task } from '@vitest/runner'\nimport type { Writable } from 'node:stream'\nimport type { TypeCheckError } from '../typecheck/typechecker'\nimport type { Vitest } from './core'\nimport type { TestProject } from './project'\nimport { Console } from 'node:console'\nimport { toArray } from '@vitest/utils/helpers'\nimport c from 'tinyrainbow'\nimport { highlightCode } from '../utils/colors'\nimport { printError } from './printError'\nimport { divider, errorBanner, formatProjectName, withLabel } from './reporters/renderers/utils'\nimport { RandomSequencer } from './sequencers/RandomSequencer'\n\nexport interface ErrorOptions {\n  type?: string\n  fullStack?: boolean\n  project?: TestProject\n  verbose?: boolean\n  screenshotPaths?: string[]\n  task?: Task\n  showCodeFrame?: boolean\n}\n\ntype Listener = () => void\n\nconst PAD = '      '\n\nconst ESC = '\\x1B['\nconst ERASE_DOWN = `${ESC}J`\nconst ERASE_SCROLLBACK = `${ESC}3J`\nconst CURSOR_TO_START = `${ESC}1;1H`\nconst HIDE_CURSOR = `${ESC}?25l`\nconst SHOW_CURSOR = `${ESC}?25h`\nconst CLEAR_SCREEN = '\\x1Bc'\n\nexport class Logger {\n  private _clearScreenPending: string | undefined\n  private _highlights = new Map<string, string>()\n  private cleanupListeners: Listener[] = []\n  public console: Console\n\n  constructor(\n    public ctx: Vitest,\n    public outputStream: NodeJS.WriteStream | Writable = process.stdout,\n    public errorStream: NodeJS.WriteStream | Writable = process.stderr,\n  ) {\n    this.console = new Console({ stdout: outputStream, stderr: errorStream })\n    this._highlights.clear()\n    this.addCleanupListeners()\n    this.registerUnhandledRejection()\n\n    if ((this.outputStream as typeof process.stdout).isTTY) {\n      (this.outputStream as Writable).write(HIDE_CURSOR)\n    }\n  }\n\n  log(...args: any[]): void {\n    this._clearScreen()\n    this.console.log(...args)\n  }\n\n  error(...args: any[]): void {\n    this._clearScreen()\n    this.console.error(...args)\n  }\n\n  warn(...args: any[]): void {\n    this._clearScreen()\n    this.console.warn(...args)\n  }\n\n  clearFullScreen(message = ''): void {\n    if (!this.ctx.config.clearScreen) {\n      this.console.log(message)\n      return\n    }\n\n    if (message) {\n      this.console.log(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}${message}`)\n    }\n    else {\n      (this.outputStream as Writable).write(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}`)\n    }\n  }\n\n  clearScreen(message: string, force = false): void {\n    if (!this.ctx.config.clearScreen) {\n      this.console.log(message)\n      return\n    }\n\n    this._clearScreenPending = message\n    if (force) {\n      this._clearScreen()\n    }\n  }\n\n  private _clearScreen() {\n    if (this._clearScreenPending == null) {\n      return\n    }\n\n    const log = this._clearScreenPending\n    this._clearScreenPending = undefined\n    this.console.log(`${CURSOR_TO_START}${ERASE_DOWN}${log}`)\n  }\n\n  printError(err: unknown, options: ErrorOptions = {}): void {\n    printError(err, this.ctx, this, options)\n  }\n\n  deprecate(message: string): void {\n    this.error(c.bold(c.bgYellow(' DEPRECATED ')), c.yellow(message))\n  }\n\n  clearHighlightCache(filename?: string): void {\n    if (filename) {\n      this._highlights.delete(filename)\n    }\n    else {\n      this._highlights.clear()\n    }\n  }\n\n  highlight(filename: string, source: string): string {\n    if (this._highlights.has(filename)) {\n      return this._highlights.get(filename)!\n    }\n    const code = highlightCode(filename, source)\n    this._highlights.set(filename, code)\n    return code\n  }\n\n  printNoTestTagsFound(): void {\n    this.error(c.bgRed(' ERROR '), c.red('No test tags found in any project. Exiting with code 1.'))\n  }\n\n  printTags(): void {\n    const vitest = this.ctx\n    const rootProject = vitest.getRootProject()\n    const projects = [\n      rootProject,\n      ...vitest.projects.filter(p => p !== rootProject),\n    ]\n\n    const hasTags = projects.some(p => p.config.tags && p.config.tags.length > 0)\n\n    if (!hasTags) {\n      process.exitCode = 1\n      return this.printNoTestTagsFound()\n    }\n\n    for (const project of projects) {\n      const name = project.name\n      if (name) {\n        this.log(formatProjectName(project, ''))\n      }\n      project.config.tags.forEach((tag) => {\n        const tagLog = `${tag.name}${tag.description ? `: ${tag.description}` : ''}`\n        this.log(`  ${tagLog}`)\n      })\n    }\n  }\n\n  printNoTestFound(filters?: string[]): void {\n    const config = this.ctx.config\n\n    if (config.watch && (config.changed || config.related?.length)) {\n      this.log(`No affected ${config.mode} files found\\n`)\n    }\n    else if (config.watch) {\n      this.log(\n        c.red(`No ${config.mode} files found. You can change the file name pattern by pressing \"p\"\\n`),\n      )\n    }\n    else {\n      if (config.passWithNoTests) {\n        this.log(`No ${config.mode} files found, exiting with code 0\\n`)\n      }\n      else {\n        this.error(\n          c.red(`No ${config.mode} files found, exiting with code 1\\n`),\n        )\n      }\n    }\n\n    const comma = c.dim(', ')\n    if (filters?.length) {\n      this.console.error(c.dim('filter: ') + c.yellow(filters.join(comma)))\n    }\n    const projectsFilter = toArray(config.project)\n    if (projectsFilter.length) {\n      this.console.error(\n        c.dim('projects: ') + c.yellow(projectsFilter.join(comma)),\n      )\n    }\n    this.ctx.projects.forEach((project) => {\n      const config = project.config\n      const printConfig = !project.isRootProject() && project.name\n      if (printConfig) {\n        this.console.error(`\\n${formatProjectName(project)}\\n`)\n      }\n      if (config.include) {\n        this.console.error(\n          c.dim('include: ') + c.yellow(config.include.join(comma)),\n        )\n      }\n      if (config.exclude) {\n        this.console.error(\n          c.dim('exclude:  ') + c.yellow(config.exclude.join(comma)),\n        )\n      }\n      if (config.typecheck.enabled) {\n        this.console.error(\n          c.dim('typecheck include: ')\n          + c.yellow(config.typecheck.include.join(comma)),\n        )\n        this.console.error(\n          c.dim('typecheck exclude: ')\n          + c.yellow(config.typecheck.exclude.join(comma)),\n        )\n      }\n    })\n    this.console.error()\n  }\n\n  printBanner(): void {\n    this.log()\n\n    const color = this.ctx.config.watch ? 'blue' : 'cyan'\n    const mode = this.ctx.config.watch ? 'DEV' : 'RUN'\n\n    this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root))\n\n    // Log seed if either files (RandomSequencer) or tests are shuffled\n    if (this.ctx.config.sequence.sequencer === RandomSequencer || this.ctx.config.sequence.shuffle) {\n      this.log(PAD + c.gray(`Running tests with seed \"${this.ctx.config.sequence.seed}\"`))\n    }\n\n    if (this.ctx.config.ui) {\n      const host = this.ctx.config.api?.host || 'localhost'\n      const port = this.ctx.vite.config.server.port\n      const base = this.ctx.config.uiBase\n\n      this.log(PAD + c.dim(c.green(`UI started at http://${host}:${c.bold(port)}${base}`)))\n    }\n    else if (this.ctx.config.api?.port) {\n      const resolvedUrls = this.ctx.vite.resolvedUrls\n      // workaround for https://github.com/vitejs/vite/issues/15438, it was fixed in vite 5.1\n      const fallbackUrl = `http://${this.ctx.config.api.host || 'localhost'}:${this.ctx.config.api.port}`\n      const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl\n\n      this.log(PAD + c.dim(c.green(`API started at ${new URL('/', origin)}`)))\n    }\n\n    if (this.ctx.coverageProvider) {\n      this.log(PAD + c.dim('Coverage enabled with ') + c.yellow(this.ctx.coverageProvider.name))\n    }\n\n    if (this.ctx.config.standalone) {\n      this.log(c.yellow(`\\nVitest is running in standalone mode. Edit a test file to rerun tests.`))\n    }\n    else {\n      this.log()\n    }\n  }\n\n  printBrowserBanner(project: TestProject): void {\n    if (!project.browser) {\n      return\n    }\n\n    const resolvedUrls = project.browser.vite.resolvedUrls\n    const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0]\n    if (!origin) {\n      return\n    }\n\n    const output = project.isRootProject()\n      ? ''\n      : formatProjectName(project)\n    const provider = project.browser.provider?.name\n    const providerString = provider === 'preview' ? '' : ` by ${c.reset(c.bold(provider))}`\n    this.log(\n      c.dim(\n        `${output}Browser runner started${providerString} ${c.dim('at')} ${c.blue(new URL('/__vitest_test__/', origin))}\\n`,\n      ),\n    )\n  }\n\n  printUnhandledErrors(errors: ReadonlyArray<unknown>): void {\n    const errorMessage = c.red(\n      c.bold(\n        `\\nVitest caught ${errors.length} unhandled error${\n          errors.length > 1 ? 's' : ''\n        } during the test run.`\n        + '\\nThis might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.',\n      ),\n    )\n    this.error(errorBanner('Unhandled Errors'))\n    this.error(errorMessage)\n    errors.forEach((err) => {\n      this.printError(err, {\n        fullStack: (err as any).name !== 'EnvironmentTeardownError',\n        type: (err as any).type || 'Unhandled Error',\n      })\n    })\n    this.error(c.red(divider()))\n  }\n\n  printSourceTypeErrors(errors: TypeCheckError[]): void {\n    const errorMessage = c.red(\n      c.bold(\n        `\\nVitest found ${errors.length} error${\n          errors.length > 1 ? 's' : ''\n        } not related to your test files.`,\n      ),\n    )\n    this.log(errorBanner('Source Errors'))\n    this.log(errorMessage)\n    errors.forEach((err) => {\n      this.printError(err, { fullStack: true })\n    })\n    this.log(c.red(divider()))\n  }\n\n  getColumns(): number {\n    return 'columns' in this.outputStream ? this.outputStream.columns : 80\n  }\n\n  onTerminalCleanup(listener: Listener): void {\n    this.cleanupListeners.push(listener)\n  }\n\n  private addCleanupListeners() {\n    const cleanup = () => {\n      this.cleanupListeners.forEach(fn => fn())\n\n      if ((this.outputStream as typeof process.stdout).isTTY) {\n        (this.outputStream as Writable).write(SHOW_CURSOR)\n      }\n    }\n\n    const onExit = (signal?: string | number, exitCode?: number) => {\n      cleanup()\n\n      // Interrupted signals don't set exit code automatically.\n      // Use same exit code as node: https://nodejs.org/api/process.html#signal-events\n      if (process.exitCode === undefined) {\n        process.exitCode = exitCode !== undefined ? (128 + exitCode) : Number(signal)\n      }\n\n      // Timeout to flush stderr\n      setTimeout(() => process.exit(), 1)\n    }\n\n    process.once('SIGINT', onExit)\n    process.once('SIGTERM', onExit)\n    process.once('exit', onExit)\n\n    this.ctx.onClose(() => {\n      process.off('SIGINT', onExit)\n      process.off('SIGTERM', onExit)\n      process.off('exit', onExit)\n      cleanup()\n    })\n  }\n\n  private registerUnhandledRejection() {\n    const onUnhandledRejection = (err: unknown) => {\n      process.exitCode = 1\n\n      this.printError(err, {\n        fullStack: true,\n        type: 'Unhandled Rejection',\n      })\n\n      this.error('\\n\\n')\n      process.exit()\n    }\n\n    process.on('unhandledRejection', onUnhandledRejection)\n\n    this.ctx.onClose(() => {\n      process.off('unhandledRejection', onUnhandledRejection)\n    })\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/module-diagnostic.ts",
    "content": "import type { ImportDuration } from '@vitest/runner'\nimport type { EnvironmentModuleGraph, TransformResult } from 'vite'\nimport type {\n  ModuleDefinitionDiagnostic,\n  ModuleDefinitionDurationsDiagnostic,\n  ModuleDefinitionLocation,\n  SourceModuleDiagnostic,\n  SourceModuleLocations,\n  UntrackedModuleDefinitionDiagnostic,\n} from '../types/module-locations'\nimport type { TestModule } from './reporters/reported-tasks'\nimport type { StateManager } from './state'\nimport { originalPositionFor, TraceMap } from '@jridgewell/trace-mapping'\nimport { createIndexLocationsMap } from '../utils/base'\n\n// this function receives the module diagnostic with the location of imports\n// and populates it with collected import durations; the duration is injected\n// only if the current module is the one that imported the module\n// if testModule is not defined, then Vitest aggregates durations of ALL collected test modules\nexport function collectModuleDurationsDiagnostic(\n  moduleId: string,\n  state: StateManager,\n  moduleDiagnostic: SourceModuleLocations | undefined,\n  testModule?: TestModule,\n): SourceModuleDiagnostic {\n  if (!moduleDiagnostic) {\n    return { modules: [], untrackedModules: [] }\n  }\n\n  const modules: ModuleDefinitionDurationsDiagnostic[] = []\n  const modulesById: Record<string, {\n    selfTime: number\n    totalTime: number\n    transformTime?: number\n    external?: boolean\n    importer?: string\n  }> = {}\n\n  const allModules = [...moduleDiagnostic.modules, ...moduleDiagnostic.untracked]\n\n  const visitedByFiles: Record<string, Set<string>> = {}\n\n  // this aggregates the times for _ALL_ tests if testModule is not passed\n  // so if the module was imported in separate tests, the time will be accumulated\n  for (const files of (testModule ? [[testModule.task]] : state.filesMap.values())) {\n    for (const file of files) {\n      const importDurations = file.importDurations\n      if (!importDurations) {\n        continue\n      }\n      const currentModule = state.getReportedEntity(file) as TestModule | undefined\n      if (!currentModule) {\n        continue\n      }\n      const visitedKey = currentModule.project.config.isolate === false ? 'non-isolate' : file.id\n      if (!visitedByFiles[visitedKey]) {\n        visitedByFiles[visitedKey] = new Set()\n      }\n      const visited = visitedByFiles[visitedKey]\n\n      allModules.forEach(({ resolvedId, resolvedUrl }) => {\n        const durations = importDurations[resolvedId]\n        // do not accumulate if module was already visited by suite (or suites in non-isolate mode)\n        if (!durations || visited.has(resolvedId)) {\n          return\n        }\n\n        const importer = getModuleImporter(moduleId, durations, currentModule)\n\n        modulesById[resolvedId] ??= {\n          selfTime: 0,\n          totalTime: 0,\n          transformTime: 0,\n          external: durations.external,\n          importer,\n        }\n\n        // only track if the current module imported this module,\n        // otherwise it was imported instantly because it's cached\n        if (importer === moduleId) {\n          visited.add(resolvedId)\n          modulesById[resolvedId].selfTime += durations.selfTime\n          modulesById[resolvedId].totalTime += durations.totalTime\n\n          // don't aggregate\n          modulesById[resolvedId].transformTime = state.metadata[currentModule.project.name]?.duration[resolvedUrl]?.[0]\n        }\n      })\n    }\n  }\n\n  // if module was imported twice in the same file,\n  // show only one time - the second should be shown as 0\n  const visitedInFile = new Set<string>()\n  moduleDiagnostic.modules.forEach((diagnostic) => {\n    const durations = modulesById[diagnostic.resolvedId]\n    if (!durations) {\n      return\n    }\n\n    if (visitedInFile.has(diagnostic.resolvedId)) {\n      modules.push({\n        ...diagnostic,\n        selfTime: 0,\n        totalTime: 0,\n        transformTime: 0,\n        external: durations.external,\n        importer: durations.importer,\n      })\n    }\n    else {\n      visitedInFile.add(diagnostic.resolvedId)\n      modules.push({\n        ...diagnostic,\n        ...durations,\n      })\n    }\n  })\n  const untracked: UntrackedModuleDefinitionDiagnostic[] = []\n  moduleDiagnostic.untracked.forEach((diagnostic) => {\n    const durations = modulesById[diagnostic.resolvedId]\n    if (!durations) {\n      return\n    }\n\n    if (visitedInFile.has(diagnostic.resolvedId)) {\n      untracked.push({\n        selfTime: 0,\n        totalTime: 0,\n        transformTime: 0,\n        external: durations.external,\n        importer: durations.importer,\n        resolvedId: diagnostic.resolvedId,\n        resolvedUrl: diagnostic.resolvedUrl,\n        url: diagnostic.rawUrl,\n      })\n    }\n    else {\n      visitedInFile.add(diagnostic.resolvedId)\n      untracked.push({\n        ...durations,\n        resolvedId: diagnostic.resolvedId,\n        resolvedUrl: diagnostic.resolvedUrl,\n        url: diagnostic.rawUrl,\n      })\n    }\n  })\n\n  return {\n    modules,\n    untrackedModules: untracked,\n  }\n}\n\nfunction getModuleImporter(moduleId: string, durations: ImportDuration, testModule: TestModule): string | undefined {\n  if (durations.importer === moduleId) {\n    return moduleId\n  }\n  if (!durations.importer) {\n    if (moduleId === testModule.moduleId) {\n      return testModule.moduleId\n    }\n\n    const setupFiles = testModule.project.config.setupFiles\n    return setupFiles.includes(moduleId)\n      ? moduleId\n      : durations.importer\n  }\n  return durations.importer\n}\n\n// the idea of this is very simple\n// it parses the source code to extract import/export statements\n// it parses SSR transformed file to extract __vite_ssr_import__ and __vite_ssr_dynamic_import__\n// it combines the two by looking at the original positions of SSR primitives\n// in the end, we are able to return a list of modules that were imported by this module\n// mapped to their IDs in Vite's module graph\nexport async function collectSourceModulesLocations(\n  moduleId: string,\n  moduleGraph: EnvironmentModuleGraph,\n): Promise<SourceModuleLocations | undefined> {\n  const transformResult = moduleGraph.getModuleById(moduleId)?.transformResult\n  if (!transformResult || !transformResult.ssr) {\n    return\n  }\n  const map = transformResult.map\n  if (!map || !('version' in map) || !map.sources.length) {\n    return\n  }\n\n  const sourceImports = map.sources.reduce<Record<string, Map<string, SourceStaticImport>>>(\n    (acc, sourceId, index) => {\n      const source = map.sourcesContent?.[index]\n      if (source != null) {\n        acc[sourceId] = parseSourceImportsAndExports(source)\n      }\n      return acc\n    },\n    {},\n  )\n\n  const transformImports = await parseTransformResult(moduleGraph, transformResult)\n  const traceMap = map && 'version' in map && new TraceMap(map as any)\n  const modules: Record<string, ModuleDefinitionDiagnostic[]> = {}\n  const untracked: ModuleDefinitionDiagnostic[] = []\n  transformImports.forEach((row) => {\n    const original = traceMap && originalPositionFor(traceMap, row.start)\n    if (original && original.source != null) {\n      // if there are several at the same position, this is a bug\n      // probably caused by import.meta.glob imports returning incorrect positions\n      // all the new import.meta.glob imports come first, so only the last module on this line is correct\n      const sourceImport = sourceImports[original.source].get(`${original.line}:${original.column}`)\n      if (sourceImport) {\n        if (modules[sourceImport.rawUrl]) {\n          // remove imports with a different resolvedId\n          const differentImports = modules[sourceImport.rawUrl].filter(d => d.resolvedId !== row.resolvedId)\n          untracked.push(...differentImports)\n          modules[sourceImport.rawUrl] = modules[sourceImport.rawUrl].filter(d => d.resolvedId === row.resolvedId)\n        }\n\n        modules[sourceImport.rawUrl] ??= []\n        modules[sourceImport.rawUrl].push({\n          start: sourceImport.start,\n          end: sourceImport.end,\n          startIndex: sourceImport.startIndex,\n          endIndex: sourceImport.endIndex,\n          rawUrl: sourceImport.rawUrl,\n          resolvedId: row.resolvedId,\n          resolvedUrl: row.resolvedUrl,\n        })\n      }\n    }\n  })\n  return {\n    modules: Object.values(modules).flat(),\n    untracked,\n  }\n}\n\ninterface SourceStaticImport {\n  start: ModuleDefinitionLocation\n  end: ModuleDefinitionLocation\n  startIndex: number\n  endIndex: number\n  rawUrl: string\n}\n\nfunction fillSourcesMap(\n  syntax: 'import' | 'export',\n  sourcesMap: Map<string, SourceStaticImport>,\n  source: string,\n  indexMap: Map<number, ModuleDefinitionLocation>,\n) {\n  const splitSeparator = `${syntax} `\n  const splitSources = source.split(splitSeparator)\n  const chunks: {\n    chunk: string\n    startIndex: number\n  }[] = []\n  let index = 0\n  for (const chunk of splitSources) {\n    chunks.push({\n      chunk,\n      startIndex: index,\n    })\n    index += chunk.length + splitSeparator.length\n  }\n\n  chunks.forEach(({ chunk, startIndex }) => {\n    const normalized = chunk.replace(/'/g, '\"')\n    const startQuoteIdx = normalized.indexOf('\"')\n\n    if (startQuoteIdx === -1) {\n      return\n    }\n    const endQuoteIdx = normalized.indexOf('\"', startQuoteIdx + 1)\n    if (endQuoteIdx === -1) {\n      return\n    }\n\n    const staticSyntax = {\n      startIndex: startIndex + startQuoteIdx,\n      endIndex: startIndex + endQuoteIdx + 1,\n      start: indexMap.get(startIndex + startQuoteIdx)!,\n      end: indexMap.get(startIndex + endQuoteIdx + 1)!,\n      rawUrl: normalized.slice(startQuoteIdx + 1, endQuoteIdx),\n    }\n\n    // -7 to include \"import \"\n    for (let i = startIndex - 7; i < staticSyntax.endIndex; i++) {\n      const location = indexMap.get(i)!\n      if (location) {\n        sourcesMap.set(`${location.line}:${location.column}`, staticSyntax)\n      }\n    }\n  })\n}\n\n// this function tries to parse ESM static import and export statements from\n// the source. if the source is not JS/TS, but supports static ESM syntax,\n// then this will also find them because it' only checks the strings, it doesn't parse the AST\nfunction parseSourceImportsAndExports(source: string): Map<string, SourceStaticImport> {\n  if (!source.includes('import ') && !source.includes('export ')) {\n    return new Map()\n  }\n  const sourcesMap = new Map<string, SourceStaticImport>()\n  const indexMap = createIndexLocationsMap(source)\n\n  fillSourcesMap('import', sourcesMap, source, indexMap)\n  fillSourcesMap('export', sourcesMap, source, indexMap)\n\n  return sourcesMap\n}\n\nasync function parseTransformResult(moduleGraph: EnvironmentModuleGraph, transformResult: TransformResult) {\n  const code = transformResult.code\n  const regexp = /(?:__vite_ssr_import__|__vite_ssr_dynamic_import__)\\(\"([^\"]+)\"/g\n  const lineColumnMap = createIndexLocationsMap(code)\n  const importPositions: {\n    raw: string\n    startIndex: number\n    endIndex: number\n  }[] = []\n  let match: RegExpMatchArray | null\n  // eslint-disable-next-line no-cond-assign\n  while (match = regexp.exec(code)) {\n    const startIndex = match.index!\n    const endIndex = match.index! + match[0].length - 1 // 1 is \"\n    importPositions.push({ raw: match[1], startIndex, endIndex })\n  }\n\n  const results = await Promise.all(importPositions.map(async ({ startIndex, endIndex, raw }) => {\n    const position = lineColumnMap.get(startIndex)!\n    const endPosition = lineColumnMap.get(endIndex)!\n    const moduleNode = await moduleGraph.getModuleByUrl(raw)\n    if (!position || !endPosition || !moduleNode || !moduleNode.id) {\n      return\n    }\n\n    return {\n      resolvedId: moduleNode.id,\n      resolvedUrl: moduleNode.url,\n      start: position,\n      end: endPosition,\n      startIndex,\n      endIndex,\n    }\n  }))\n\n  return results.filter(n => n != null)\n}\n"
  },
  {
    "path": "packages/vitest/src/node/packageInstaller.ts",
    "content": "import { createRequire } from 'node:module'\nimport url from 'node:url'\nimport { isPackageExists } from 'local-pkg'\nimport c from 'tinyrainbow'\nimport { isTTY } from '../utils/env'\n\nconst __dirname = url.fileURLToPath(new URL('.', import.meta.url))\n\nexport class VitestPackageInstaller {\n  isPackageExists(name: string, options?: { paths?: string[] }): boolean {\n    return isPackageExists(name, options)\n  }\n\n  async ensureInstalled(dependency: string, root: string, version?: string): Promise<boolean> {\n    if (process.env.VITEST_SKIP_INSTALL_CHECKS) {\n      return true\n    }\n\n    if (process.versions.pnp) {\n      const targetRequire = createRequire(__dirname)\n      try {\n        targetRequire.resolve(dependency, { paths: [root, __dirname] })\n        return true\n      }\n      catch {}\n    }\n\n    if (\n      /* @__PURE__ */ isPackageExists(dependency, { paths: [root, __dirname] })\n    ) {\n      return true\n    }\n\n    process.stderr.write(\n      c.red(\n        `${c.inverse(\n          c.red(' MISSING DEPENDENCY '),\n        )} Cannot find dependency '${dependency}'\\n\\n`,\n      ),\n    )\n\n    if (!isTTY) {\n      return false\n    }\n\n    const prompts = await import('prompts')\n    const { install } = await prompts.default({\n      type: 'confirm',\n      name: 'install',\n      message: c.reset(`Do you want to install ${c.green(dependency)}?`),\n    })\n\n    if (install) {\n      const packageName = version ? `${dependency}@${version}` : dependency\n      await (\n        await import('@antfu/install-pkg')\n      ).installPackage(packageName, { dev: true })\n      // TODO: somehow it fails to load the package after installation, remove this when it's fixed\n      process.stderr.write(\n        c.yellow(\n          `\\nPackage ${packageName} installed, re-run the command to start.\\n`,\n        ),\n      )\n      process.exit()\n      return true\n    }\n\n    return false\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/coverageTransform.ts",
    "content": "import type { Plugin as VitePlugin } from 'vite'\nimport type { Vitest } from '../core'\n\nexport function CoverageTransform(ctx: Vitest): VitePlugin {\n  return {\n    name: 'vitest:coverage-transform',\n    enforce: 'post',\n    transform(srcCode, id) {\n      return ctx.coverageProvider?.onFileTransform?.(\n        srcCode,\n        id,\n        this,\n      )\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/cssEnabler.ts",
    "content": "import type { Plugin as VitePlugin } from 'vite'\nimport type { CSSModuleScopeStrategy, ResolvedConfig } from '../types/config'\nimport { toArray } from '@vitest/utils/helpers'\nimport { relative } from 'pathe'\nimport { generateCssFilenameHash } from '../../integrations/css/css-modules'\n\nconst cssLangs = '\\\\.(?:css|less|sass|scss|styl|stylus|pcss|postcss)(?:$|\\\\?)'\nconst cssLangRE = new RegExp(cssLangs)\nconst cssModuleRE = new RegExp(`\\\\.module${cssLangs}`)\nconst cssInlineRE = /[?&]inline(?:&|$)/\n\nfunction isCSS(id: string) {\n  return cssLangRE.test(id)\n}\n\nfunction isCSSModule(id: string) {\n  return cssModuleRE.test(id)\n}\n\n// inline css requests are expected to just return the\n// string content directly and not the proxy module\nfunction isInline(id: string) {\n  return cssInlineRE.test(id)\n}\n\nfunction getCSSModuleProxyReturn(\n  strategy: CSSModuleScopeStrategy,\n  filename: string,\n) {\n  if (strategy === 'non-scoped') {\n    return 'style'\n  }\n  const hash = generateCssFilenameHash(filename)\n  return `\\`_\\${style}_${hash}\\``\n}\n\nexport function CSSEnablerPlugin(ctx: {\n  config: ResolvedConfig\n}): VitePlugin[] {\n  const shouldProcessCSS = (id: string) => {\n    const { css } = ctx.config\n    if (typeof css === 'boolean') {\n      return css\n    }\n    if (toArray(css.exclude).some(re => re.test(id))) {\n      return false\n    }\n    if (toArray(css.include).some(re => re.test(id))) {\n      return true\n    }\n    return false\n  }\n\n  return [\n    {\n      name: 'vitest:css-disable',\n      enforce: 'pre',\n      transform(code, id) {\n        if (!isCSS(id)) {\n          return\n        }\n        // css plugin inside Vite won't do anything if the code is empty\n        // but it will put __vite__updateStyle anyway\n        if (!shouldProcessCSS(id)) {\n          return { code: '' }\n        }\n      },\n    },\n    {\n      name: 'vitest:css-empty-post',\n      enforce: 'post',\n      transform(_, id) {\n        if (!isCSS(id) || shouldProcessCSS(id)) {\n          return\n        }\n\n        if (isCSSModule(id) && !isInline(id)) {\n          // return proxy for css modules, so that imported module has names:\n          // styles.foo returns a \"foo\" instead of \"undefined\"\n          // we don't use code content to generate hash for \"scoped\", because it's empty\n          const scopeStrategy\n            = (typeof ctx.config.css !== 'boolean'\n              && ctx.config.css.modules?.classNameStrategy)\n            || 'stable'\n          const proxyReturn = getCSSModuleProxyReturn(\n            scopeStrategy,\n            relative(ctx.config.root, id),\n          )\n          const code = `export default new Proxy(Object.create(null), {\n            get(_, style) {\n              return ${proxyReturn};\n            },\n          })`\n          return { code }\n        }\n\n        return { code: 'export default \"\"' }\n      },\n    },\n  ]\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/index.ts",
    "content": "import type { UserConfig as ViteConfig, Plugin as VitePlugin } from 'vite'\nimport type { ResolvedConfig, UserConfig } from '../types/config'\nimport { deepClone, deepMerge, notNullish } from '@vitest/utils/helpers'\nimport { relative, resolve } from 'pathe'\nimport * as vite from 'vite'\nimport { defaultPort } from '../../constants'\nimport { configDefaults } from '../../defaults'\nimport { generateScopedClassName } from '../../integrations/css/css-modules'\nimport { resolveApiServerConfig } from '../config/resolveConfig'\nimport { Vitest } from '../core'\nimport { createViteLogger, silenceImportViteIgnoreWarning } from '../viteLogger'\nimport { CoverageTransform } from './coverageTransform'\nimport { CSSEnablerPlugin } from './cssEnabler'\nimport { MetaEnvReplacerPlugin } from './metaEnvReplacer'\nimport { MocksPlugins } from './mocks'\nimport { NormalizeURLPlugin } from './normalizeURL'\nimport { VitestOptimizer } from './optimizer'\nimport { ModuleRunnerTransform } from './runnerTransform'\nimport {\n  deleteDefineConfig,\n  getDefaultResolveOptions,\n  resolveFsAllow,\n} from './utils'\nimport { VitestCoreResolver } from './vitestResolver'\n\nexport async function VitestPlugin(\n  options: UserConfig = {},\n  vitest: Vitest = new Vitest('test', deepClone(options)),\n): Promise<VitePlugin[]> {\n  const userConfig = deepMerge({}, options) as UserConfig\n\n  async function UIPlugin() {\n    await vitest.packageInstaller.ensureInstalled('@vitest/ui', resolve(options.root || process.cwd()), vitest.version)\n    return (await import('@vitest/ui')).default(vitest)\n  }\n\n  return [\n    <VitePlugin>{\n      name: 'vitest',\n      enforce: 'pre',\n      options() {\n        this.meta.watchMode = false\n      },\n      async config(viteConfig) {\n        if (options.watch) {\n          // Earlier runs have overwritten values of the `options`.\n          // Reset it back to initial user config before setting up the server again.\n          options = deepMerge({}, userConfig) as UserConfig\n        }\n\n        // preliminary merge of options to be able to create server options for vite\n        // however to allow vitest plugins to modify vitest config values\n        // this is repeated in configResolved where the config is final\n        const testConfig = deepMerge(\n          {} as UserConfig,\n          configDefaults,\n          removeUndefinedValues(viteConfig.test ?? {}),\n          options,\n        )\n        testConfig.api = resolveApiServerConfig(testConfig, defaultPort)\n\n        // store defines for globalThis to make them\n        // reassignable when running in worker in src/runtime/setup.ts\n        const originalDefine = { ...viteConfig.define } // stash original defines for browser mode\n        const defines: Record<string, any> = deleteDefineConfig(viteConfig)\n\n        ;(options as unknown as ResolvedConfig).defines = defines\n        ;(options as unknown as ResolvedConfig).viteDefine = originalDefine\n\n        let open: string | boolean | undefined = false\n\n        if (testConfig.ui && testConfig.open) {\n          open = testConfig.uiBase ?? '/__vitest__/'\n        }\n\n        const resolveOptions = getDefaultResolveOptions()\n\n        let config: ViteConfig = {\n          base: '/',\n          root: viteConfig.test?.root || options.root,\n          define: {\n            // disable replacing `process.env.NODE_ENV` with static string by vite:client-inject\n            'process.env.NODE_ENV': 'process.env.NODE_ENV',\n          },\n          resolve: {\n            ...resolveOptions,\n            alias: testConfig.alias,\n          },\n          server: {\n            ...testConfig.api,\n            open,\n            hmr: false,\n            ws: testConfig.api?.middlewareMode ? false : undefined,\n            preTransformRequests: false,\n            fs: {\n              allow: resolveFsAllow(options.root || process.cwd(), testConfig.config),\n            },\n          },\n          build: {\n            // Vitest doesn't use outputDir, but this value affects what folders are watched\n            // https://github.com/vitest-dev/vitest/issues/5429\n            // This works for Vite <5.2.10\n            outDir: 'dummy-non-existing-folder',\n            // This works for Vite >=5.2.10\n            // https://github.com/vitejs/vite/pull/16453\n            emptyOutDir: false,\n          },\n          // eslint-disable-next-line ts/ban-ts-comment\n          // @ts-ignore Vite 6 compat\n          environments: {\n            ssr: {\n              resolve: resolveOptions,\n            },\n            __vitest__: {\n              dev: {},\n            },\n          },\n          test: {\n            root: testConfig.root ?? viteConfig.test?.root,\n            deps: testConfig.deps ?? viteConfig.test?.deps,\n          },\n        }\n\n        if ('rolldownVersion' in vite) {\n          config = {\n            ...config,\n            // eslint-disable-next-line ts/ban-ts-comment\n            // @ts-ignore rolldown-vite only\n            oxc: viteConfig.oxc === false\n              ? false\n              : {\n                  // eslint-disable-next-line ts/ban-ts-comment\n                  // @ts-ignore rolldown-vite only\n                  target: viteConfig.oxc?.target || 'node18',\n                },\n          }\n        }\n        else {\n          config = {\n            ...config,\n            esbuild: viteConfig.esbuild === false\n              ? false\n              : {\n                  // Lowest target Vitest supports is Node18\n                  target: viteConfig.esbuild?.target || 'node18',\n                  sourcemap: 'external',\n                  // Enables using ignore hint for coverage providers with @preserve keyword\n                  legalComments: 'inline',\n                },\n          }\n        }\n\n        // inherit so it's available in VitestOptimizer\n        // I cannot wait to rewrite all of this in Vitest 4\n        if (options.cache != null) {\n          config.test!.cache = options.cache\n        }\n\n        if (vitest.configOverride.project) {\n          // project filter was set by the user, so we need to filter the project\n          options.project = vitest.configOverride.project\n        }\n\n        config.customLogger = createViteLogger(\n          vitest.logger,\n          viteConfig.logLevel || 'warn',\n          {\n            allowClearScreen: false,\n          },\n        )\n        config.customLogger = silenceImportViteIgnoreWarning(config.customLogger)\n\n        // chokidar fsevents is unstable on macos when emitting \"ready\" event\n        if (\n          process.platform === 'darwin'\n          && process.env.VITE_TEST_WATCHER_DEBUG\n        ) {\n          const watch = config.server!.watch\n          if (watch) {\n            // eslint-disable-next-line ts/ban-ts-comment\n            // @ts-ignore Vite 6 compat\n            watch.useFsEvents = false\n            watch.usePolling = false\n          }\n        }\n\n        const classNameStrategy\n          = (typeof testConfig.css !== 'boolean'\n            && testConfig.css?.modules?.classNameStrategy)\n          || 'stable'\n\n        if (classNameStrategy !== 'scoped') {\n          config.css ??= {}\n          config.css.modules ??= {}\n          if (config.css.modules) {\n            config.css.modules.generateScopedName = (\n              name: string,\n              filename: string,\n            ) => {\n              const root = vitest.config.root || options.root || process.cwd()\n              return generateScopedClassName(\n                classNameStrategy,\n                name,\n                relative(root, filename),\n              )!\n            }\n          }\n        }\n\n        return config\n      },\n      async configResolved(viteConfig) {\n        const viteConfigTest = (viteConfig.test as UserConfig) || {}\n        if (viteConfigTest.watch === false) {\n          ;(viteConfigTest as any).run = true\n        }\n\n        if ('alias' in viteConfigTest) {\n          delete viteConfigTest.alias\n        }\n\n        // viteConfig.test is final now, merge it for real\n        options = deepMerge({}, configDefaults, viteConfigTest, options)\n        options.api = resolveApiServerConfig(options, defaultPort)\n\n        // we replace every \"import.meta.env\" with \"process.env\"\n        // to allow reassigning, so we need to put all envs on process.env\n        const { PROD, DEV, ...envs } = viteConfig.env\n\n        // process.env can have only string values and will cast string on it if we pass other type,\n        // so we are making them truthy\n        process.env.PROD ??= PROD ? '1' : ''\n        process.env.DEV ??= DEV ? '1' : ''\n\n        for (const name in envs) {\n          process.env[name] ??= envs[name]\n        }\n\n        // don't watch files in run mode\n        if (!options.watch) {\n          viteConfig.server.watch = null\n        }\n\n        if (options.ui) {\n          // @ts-expect-error mutate readonly\n          viteConfig.plugins.push(await UIPlugin())\n        }\n\n        Object.defineProperty(viteConfig, '_vitest', {\n          value: options,\n          enumerable: false,\n          configurable: true,\n        })\n\n        const originalName = options.name\n        if (options.browser?.instances) {\n          options.browser.instances.forEach((instance) => {\n            instance.name ??= originalName ? `${originalName} (${instance.browser})` : instance.browser\n          })\n        }\n      },\n      configureServer: {\n        async handler(server) {\n          if (options.watch && process.env.VITE_TEST_WATCHER_DEBUG) {\n            server.watcher.on('ready', () => {\n              // eslint-disable-next-line no-console\n              console.log('[debug] watcher is ready')\n            })\n          }\n          await vitest._setServer(options, server)\n          if (options.api && options.watch) {\n            (await import('../../api/setup')).setup(vitest)\n          }\n\n          // #415, in run mode we don't need the watcher, close it would improve the performance\n          if (!options.watch) {\n            await server.watcher.close()\n          }\n        },\n      },\n    },\n    MetaEnvReplacerPlugin(),\n    ...CSSEnablerPlugin(vitest),\n    CoverageTransform(vitest),\n    VitestCoreResolver(vitest),\n    ...MocksPlugins(),\n    VitestOptimizer(),\n    NormalizeURLPlugin(),\n    ModuleRunnerTransform(),\n  ].filter(notNullish)\n}\nfunction removeUndefinedValues<T extends Record<string, any>>(\n  obj: T,\n): T {\n  for (const key in Object.keys(obj)) {\n    if (obj[key] === undefined) {\n      delete obj[key]\n    }\n  }\n  return obj\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/metaEnvReplacer.ts",
    "content": "import type { Plugin } from 'vite'\nimport { cleanUrl } from '@vitest/utils/helpers'\nimport MagicString from 'magic-string'\nimport { stripLiteral } from 'strip-literal'\n\n// so people can reassign envs at runtime\n// import.meta.env.VITE_NAME = 'app' -> process.env.VITE_NAME = 'app'\nexport function MetaEnvReplacerPlugin(): Plugin {\n  return {\n    name: 'vitest:meta-env-replacer',\n    enforce: 'pre',\n    transform(code, id) {\n      if (!/\\bimport\\.meta\\.env\\b/.test(code)) {\n        return null\n      }\n\n      let s: MagicString | null = null\n      const cleanCode = stripLiteral(code)\n      const envs = cleanCode.matchAll(/\\bimport\\.meta\\.env\\b/g)\n\n      for (const env of envs) {\n        s ||= new MagicString(code)\n\n        const startIndex = env.index!\n        const endIndex = startIndex + env[0].length\n\n        s.overwrite(\n          startIndex,\n          endIndex,\n          `Object.assign(/* istanbul ignore next */ globalThis.__vitest_worker__?.metaEnv ?? import.meta.env)`,\n        )\n      }\n\n      if (s) {\n        return {\n          code: s.toString(),\n          map: s.generateMap({\n            hires: 'boundary',\n\n            // Remove possible query parameters, e.g. vue's \"?vue&type=script&src=true&lang.ts\"\n            source: cleanUrl(id),\n          }),\n        }\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/mocks.ts",
    "content": "import type { Plugin } from 'vite'\nimport { automockPlugin, hoistMocksPlugin } from '@vitest/mocker/node'\nimport { normalize } from 'pathe'\nimport { distDir } from '../../paths'\nimport { generateCodeFrame } from '../printError'\n\nexport interface MocksPluginOptions {\n  filter?: (id: string) => boolean\n}\n\nexport function MocksPlugins(options: MocksPluginOptions = {}): Plugin[] {\n  const normalizedDistDir = normalize(distDir)\n  return [\n    hoistMocksPlugin({\n      filter(id) {\n        if (id.includes(normalizedDistDir)) {\n          return false\n        }\n        if (options.filter) {\n          return options.filter(id)\n        }\n        return true\n      },\n      codeFrameGenerator(node, id, code) {\n        return generateCodeFrame(\n          code,\n          4,\n          node.start + 1,\n        )\n      },\n    }),\n    automockPlugin(),\n  ]\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/normalizeURL.ts",
    "content": "import type { Plugin } from 'vite'\nimport { stripLiteral } from 'strip-literal'\n\nconst metaUrlLength = 'import.meta.url'.length\nconst locationString = 'self.location'.padEnd(metaUrlLength, ' ')\n\n// Vite transforms new URL('./path', import.meta.url) to new URL('/path.js', import.meta.url)\n// This makes \"href\" equal to \"http://localhost:3000/path.js\" in the browser, but if we keep it like this,\n// then in tests the URL will become \"file:///path.js\".\n// To battle this, we replace \"import.meta.url\" with \"self.location\" in the code to keep the browser behavior.\nexport function NormalizeURLPlugin(): Plugin {\n  return {\n    name: 'vitest:normalize-url',\n    enforce: 'post',\n    transform(code) {\n      if (\n        this.environment.name !== 'client'\n        || !code.includes('new URL')\n        || !code.includes('import.meta.url')\n      ) {\n        return\n      }\n\n      const cleanString = stripLiteral(code)\n      const assetImportMetaUrlRE\n      // vite injects new URL(path, import.meta.url) in the code\n      // rolldown-vite injects new URL(path, '' + import.meta.url) in the code\n        = /\\bnew\\s+URL\\s*\\(\\s*(?:'[^']+'|\"[^\"]+\"|`[^`]+`)\\s*,\\s*(?:'' \\+ )?import\\.meta\\.url\\s*(?:,\\s*)?\\)/g\n\n      let updatedCode = code\n      let match: RegExpExecArray | null\n      // eslint-disable-next-line no-cond-assign\n      while ((match = assetImportMetaUrlRE.exec(cleanString))) {\n        const { 0: exp, index } = match\n        const metaUrlIndex = index + exp.indexOf('import.meta.url')\n        updatedCode\n          = updatedCode.slice(0, metaUrlIndex)\n            + locationString\n            + updatedCode.slice(metaUrlIndex + metaUrlLength)\n      }\n\n      return {\n        code: updatedCode,\n        map: null,\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/optimizer.ts",
    "content": "import type { Plugin } from 'vite'\nimport { resolve } from 'pathe'\nimport { VitestCache } from '../cache'\n\nexport function VitestOptimizer(): Plugin {\n  return {\n    name: 'vitest:normalize-optimizer',\n    config: {\n      order: 'post',\n      handler(viteConfig) {\n        const testConfig = viteConfig.test || {}\n\n        const root = resolve(viteConfig.root || process.cwd())\n        const name = viteConfig.test?.name\n        const label = typeof name === 'string' ? name : (name?.label || '')\n\n        viteConfig.cacheDir = VitestCache.resolveCacheDir(\n          resolve(root || process.cwd()),\n          testConfig.cache != null && testConfig.cache !== false\n            ? testConfig.cache.dir\n            : viteConfig.cacheDir,\n          label,\n        )\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/publicConfig.ts",
    "content": "import type {\n  ResolvedConfig as ResolvedViteConfig,\n  UserConfig as ViteUserConfig,\n} from 'vite'\nimport type { ResolvedConfig, UserConfig } from '../types/config'\nimport { deepClone, slash } from '@vitest/utils/helpers'\nimport * as find from 'empathic/find'\nimport { resolve } from 'pathe'\nimport { mergeConfig, resolveConfig as resolveViteConfig } from 'vite'\nimport { configFiles } from '../../constants'\nimport { resolveConfig as resolveVitestConfig } from '../config/resolveConfig'\nimport { Vitest } from '../core'\nimport { VitestPlugin } from './index'\n\n// this is only exported as a public function and not used inside vitest\nexport async function resolveConfig(\n  options: UserConfig = {},\n  viteOverrides: ViteUserConfig = {},\n): Promise<{ vitestConfig: ResolvedConfig; viteConfig: ResolvedViteConfig }> {\n  const root = slash(resolve(options.root || process.cwd()))\n\n  const configPath\n    = options.config === false\n      ? false\n      : options.config\n        ? resolve(root, options.config)\n        : find.any(configFiles, { cwd: root })\n  options.config = configPath\n\n  const vitest = new Vitest('test', deepClone(options))\n  const config = await resolveViteConfig(\n    mergeConfig(\n      {\n        configFile: configPath,\n        // this will make \"mode\": \"test\" | \"benchmark\" inside defineConfig\n        mode: options.mode || 'test',\n        plugins: [\n          await VitestPlugin(options, vitest),\n        ],\n      },\n      mergeConfig(viteOverrides, { root: options.root }),\n    ),\n    'serve',\n  )\n  // Reflect just to avoid type error\n  const updatedOptions = Reflect.get(config, '_vitest') as UserConfig\n  const vitestConfig = resolveVitestConfig(\n    vitest,\n    updatedOptions,\n    config,\n  )\n  await vitest.close()\n  return {\n    viteConfig: config,\n    vitestConfig,\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/runnerTransform.ts",
    "content": "import type { ResolveOptions, UserConfig, Plugin as VitePlugin } from 'vite'\nimport { builtinModules } from 'node:module'\nimport { normalize } from 'pathe'\nimport { escapeRegExp } from '../../utils/base'\nimport { resolveOptimizerConfig } from './utils'\n\nexport function ModuleRunnerTransform(): VitePlugin {\n  let testConfig: NonNullable<UserConfig['test']>\n  const noExternal: (string | RegExp)[] = []\n  const external: (string | RegExp)[] = []\n  let noExternalAll = false\n\n  // make sure Vite always applies the module runner transform\n  return {\n    name: 'vitest:environments-module-runner',\n    config: {\n      order: 'post',\n      handler(config) {\n        testConfig = config.test || {}\n\n        config.environments ??= {}\n\n        const names = new Set(Object.keys(config.environments))\n        names.add('client')\n        names.add('ssr')\n\n        const pool = config.test?.pool\n        if (pool === 'vmForks' || pool === 'vmThreads') {\n          names.add('__vitest_vm__')\n        }\n\n        let moduleDirectories = testConfig.deps?.moduleDirectories || []\n\n        const envModuleDirectories\n          = process.env.VITEST_MODULE_DIRECTORIES\n            || process.env.npm_config_VITEST_MODULE_DIRECTORIES\n\n        if (envModuleDirectories) {\n          moduleDirectories.push(...envModuleDirectories.split(','))\n        }\n\n        moduleDirectories = moduleDirectories.map(\n          (dir) => {\n            if (dir[0] !== '/') {\n              dir = `/${dir}`\n            }\n            if (!dir.endsWith('/')) {\n              dir += '/'\n            }\n            return normalize(dir)\n          },\n        )\n        if (!moduleDirectories.includes('/node_modules/')) {\n          moduleDirectories.push('/node_modules/')\n        }\n\n        testConfig.deps ??= {}\n        testConfig.deps.moduleDirectories = moduleDirectories\n\n        for (const name of names) {\n          config.environments[name] ??= {}\n\n          const environment = config.environments[name]\n          environment.dev ??= {}\n          // vm tests run using the native import mechanism\n          if (name === '__vitest_vm__') {\n            environment.dev.moduleRunnerTransform = false\n            environment.consumer = 'client'\n          }\n          else {\n            environment.dev.moduleRunnerTransform = true\n          }\n          environment.dev.preTransformRequests = false\n          environment.keepProcessEnv = true\n        }\n      },\n    },\n    configEnvironment: {\n      order: 'post',\n      handler(name, config) {\n        if (name === '__vitest_vm__' || name === '__vitest__') {\n          return\n        }\n\n        config.resolve ??= {}\n        const envNoExternal = resolveViteResolveOptions('noExternal', config.resolve, testConfig.deps?.moduleDirectories)\n        if (envNoExternal === true) {\n          noExternalAll = true\n        }\n        else if (envNoExternal.length) {\n          noExternal.push(...envNoExternal)\n        }\n\n        const envExternal = resolveViteResolveOptions('external', config.resolve, testConfig.deps?.moduleDirectories)\n        if (envExternal !== true && envExternal.length) {\n          external.push(...envExternal)\n        }\n\n        // remove Vite's externalization logic because we have our own (unfortunately)\n        config.resolve.external = [\n          ...builtinModules,\n          ...builtinModules.map(m => `node:${m}`),\n        ]\n\n        // by setting `noExternal` to `true`, we make sure that\n        // Vite will never use its own externalization mechanism\n        // to externalize modules and always resolve static imports\n        // in both SSR and Client environments\n        config.resolve.noExternal = true\n\n        config.optimizeDeps = resolveOptimizerConfig(\n          testConfig?.deps?.optimizer?.[name],\n          config.optimizeDeps,\n        )\n      },\n    },\n    configResolved: {\n      order: 'pre',\n      handler(config) {\n        const testConfig = config.test!\n        testConfig.server ??= {}\n        testConfig.server.deps ??= {}\n\n        if (testConfig.server.deps.inline !== true) {\n          if (noExternalAll) {\n            testConfig.server.deps.inline = true\n          }\n          else if (noExternal.length) {\n            testConfig.server.deps.inline ??= []\n            testConfig.server.deps.inline.push(...noExternal)\n          }\n        }\n        if (external.length) {\n          testConfig.server.deps.external ??= []\n          testConfig.server.deps.external.push(...external)\n        }\n      },\n    },\n  }\n}\n\nfunction resolveViteResolveOptions(\n  key: 'noExternal' | 'external',\n  options: Pick<ResolveOptions, 'noExternal' | 'external'>,\n  moduleDirectories: string[] | undefined,\n): true | (string | RegExp)[] {\n  if (Array.isArray(options[key])) {\n    // mergeConfig will merge a custom `true` into an array\n    if (options[key].some(p => (p as any) === true)) {\n      return true\n    }\n    return options[key].map(dep => processWildcard(dep, moduleDirectories))\n  }\n  else if (\n    typeof options[key] === 'string'\n    || options[key] instanceof RegExp\n  ) {\n    return [options[key]].map(dep => processWildcard(dep, moduleDirectories))\n  }\n  else if (typeof options[key] === 'boolean') {\n    return true\n  }\n  return []\n}\n\nfunction processWildcard(dep: string | RegExp, moduleDirectories: string[] | undefined) {\n  if (typeof dep !== 'string') {\n    return dep\n  }\n  if (typeof dep === 'string' && dep.includes('*')) {\n    const directories = (moduleDirectories || ['/node_modules/']).map(r => escapeRegExp(r))\n    return new RegExp(\n      `(${directories.join('|')})${dep.replace(/\\*/g, '[\\\\w/]+')}`,\n    )\n  }\n  return dep\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/utils.ts",
    "content": "import type {\n  DepOptimizationOptions,\n  UserConfig as ViteConfig,\n} from 'vite'\nimport type { DepsOptimizationOptions } from '../types/config'\nimport { dirname } from 'pathe'\nimport { searchForWorkspaceRoot, version as viteVersion } from 'vite'\nimport * as vite from 'vite'\nimport { rootDir } from '../../paths'\n\nexport function resolveOptimizerConfig(\n  _testOptions: DepsOptimizationOptions | undefined,\n  viteOptions: DepOptimizationOptions | undefined,\n): DepOptimizationOptions {\n  const testOptions = _testOptions || {}\n  let optimizeDeps: DepOptimizationOptions\n  if (testOptions.enabled !== true) {\n    testOptions.enabled ??= false\n\n    optimizeDeps = {\n      // experimental in Vite >2.9.2, entries remains to help with older versions\n      disabled: true,\n      entries: [],\n    }\n  }\n  else {\n    const currentInclude = testOptions.include || viteOptions?.include || []\n    const exclude = [\n      'vitest',\n      // Ideally, we shouldn't optimize react in test mode, otherwise we need to optimize _every_ dependency that uses react.\n      'react',\n      'vue',\n      ...(testOptions.exclude || viteOptions?.exclude || []),\n    ]\n    const runtime = currentInclude.filter(\n      n => n.endsWith('jsx-dev-runtime') || n.endsWith('jsx-runtime'),\n    )\n    exclude.push(...runtime)\n\n    const include = (testOptions.include || viteOptions?.include || []).filter(\n      (n: string) => !exclude.includes(n),\n    )\n\n    optimizeDeps = {\n      ...viteOptions,\n      ...testOptions,\n      noDiscovery: true,\n      disabled: false,\n      entries: [],\n      exclude,\n      include,\n    }\n  }\n\n  // `optimizeDeps.disabled` is deprecated since v5.1.0-beta.1\n  // https://github.com/vitejs/vite/pull/15184\n  if (optimizeDeps.disabled) {\n    optimizeDeps.noDiscovery = true\n    optimizeDeps.include = []\n  }\n  delete optimizeDeps.disabled\n\n  return optimizeDeps\n}\n\nexport function deleteDefineConfig(viteConfig: ViteConfig): Record<string, any> {\n  const defines: Record<string, any> = {}\n  if (viteConfig.define) {\n    delete viteConfig.define['import.meta.vitest']\n    delete viteConfig.define['process.env']\n    delete viteConfig.define.process\n    delete viteConfig.define.global\n  }\n  for (const key in viteConfig.define) {\n    const val = viteConfig.define[key]\n    let replacement: any\n    try {\n      replacement = typeof val === 'string' ? JSON.parse(val) : val\n    }\n    catch {\n      // probably means it contains reference to some variable,\n      // like this: \"__VAR__\": \"process.env.VAR\"\n      continue\n    }\n    if (key.startsWith('import.meta.env.')) {\n      const envKey = key.slice('import.meta.env.'.length)\n      process.env[envKey] = replacement\n      delete viteConfig.define[key]\n    }\n    else if (key.startsWith('process.env.')) {\n      const envKey = key.slice('process.env.'.length)\n      process.env[envKey] = replacement\n      delete viteConfig.define[key]\n    }\n    else if (!key.includes('.')) {\n      defines[key] = replacement\n      delete viteConfig.define[key]\n    }\n  }\n  return defines\n}\n\nexport function resolveFsAllow(\n  projectRoot: string,\n  rootConfigFile: string | false | undefined,\n): string[] {\n  if (!rootConfigFile) {\n    return [searchForWorkspaceRoot(projectRoot), rootDir]\n  }\n  return [\n    dirname(rootConfigFile),\n    searchForWorkspaceRoot(projectRoot),\n    rootDir,\n  ]\n}\n\nexport function getDefaultResolveOptions(): vite.ResolveOptions {\n  return {\n    // by default Vite resolves `module` field, which is not always a native ESM module\n    // setting this option can bypass that and fallback to cjs version\n    mainFields: [],\n    // same for `module` condition and Vite 5 doesn't even allow excluding it,\n    // but now it's possible since Vite 6.\n    conditions: getDefaultServerConditions(),\n  }\n}\n\nfunction getDefaultServerConditions(): string[] {\n  const viteMajor = Number(viteVersion.split('.')[0])\n  if (viteMajor >= 6) {\n    const conditions: string[] = (vite as any).defaultServerConditions\n    return conditions.filter(c => c !== 'module')\n  }\n  return ['node']\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/vitestResolver.ts",
    "content": "import type { Plugin } from 'vite'\nimport type { Vitest } from '../core'\nimport { join, resolve } from 'pathe'\nimport { distDir } from '../../paths'\n\nexport function VitestProjectResolver(ctx: Vitest): Plugin {\n  const plugin: Plugin = {\n    name: 'vitest:resolve-root',\n    enforce: 'pre',\n    config: {\n      order: 'post',\n      handler() {\n        return {\n          base: '/',\n        }\n      },\n    },\n    async resolveId(id, _, { ssr }) {\n      if (id === 'vitest' || id.startsWith('@vitest/') || id.startsWith('vitest/')) {\n        // always redirect the request to the root vitest plugin since\n        // it will be the one used to run Vitest\n        const resolved = await ctx.vite.pluginContainer.resolveId(id, undefined, {\n          skip: new Set([plugin]),\n          ssr,\n        })\n        return resolved\n      }\n    },\n  }\n  return plugin\n}\n\nexport function VitestCoreResolver(ctx: Vitest): Plugin {\n  return {\n    name: 'vitest:resolve-core',\n    enforce: 'pre',\n    config: {\n      order: 'post',\n      handler() {\n        return {\n          base: '/',\n        }\n      },\n    },\n    async resolveId(id) {\n      if (id === 'vitest') {\n        return resolve(distDir, 'index.js')\n      }\n      if (id.startsWith('@vitest/') || id.startsWith('vitest/')) {\n        // ignore actual importer, we want it to be resolved relative to the root\n        return this.resolve(id, join(ctx.config.root, 'index.html'), {\n          skipSelf: true,\n        })\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/plugins/workspace.ts",
    "content": "import type { UserConfig as ViteConfig, Plugin as VitePlugin } from 'vite'\nimport type { TestProject } from '../project'\nimport type { BrowserConfigOptions, ResolvedConfig, TestProjectInlineConfiguration, UserConfig } from '../types/config'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { deepMerge } from '@vitest/utils/helpers'\nimport { basename, dirname, relative, resolve } from 'pathe'\nimport * as vite from 'vite'\nimport { configDefaults } from '../../defaults'\nimport { generateScopedClassName } from '../../integrations/css/css-modules'\nimport { VitestFilteredOutProjectError } from '../errors'\nimport { createViteLogger, silenceImportViteIgnoreWarning } from '../viteLogger'\nimport { CoverageTransform } from './coverageTransform'\nimport { CSSEnablerPlugin } from './cssEnabler'\nimport { MetaEnvReplacerPlugin } from './metaEnvReplacer'\nimport { MocksPlugins } from './mocks'\nimport { NormalizeURLPlugin } from './normalizeURL'\nimport { VitestOptimizer } from './optimizer'\nimport { ModuleRunnerTransform } from './runnerTransform'\nimport {\n  deleteDefineConfig,\n  getDefaultResolveOptions,\n  resolveFsAllow,\n} from './utils'\nimport { VitestProjectResolver } from './vitestResolver'\n\ninterface WorkspaceOptions extends TestProjectInlineConfiguration {\n  root?: string\n  workspacePath: string | number\n}\n\nexport function WorkspaceVitestPlugin(\n  project: TestProject,\n  options: WorkspaceOptions,\n) {\n  return <VitePlugin[]>[\n    {\n      name: 'vitest:project:name',\n      enforce: 'post',\n      config(viteConfig) {\n        const testConfig = viteConfig.test || {}\n\n        let { label: name, color } = typeof testConfig.name === 'string'\n          ? { label: testConfig.name }\n          : { label: '', ...testConfig.name }\n\n        if (!name) {\n          if (typeof options.workspacePath === 'string') {\n            // if there is a package.json, read the name from it\n            const dir = options.workspacePath.endsWith('/')\n              ? options.workspacePath.slice(0, -1)\n              : dirname(options.workspacePath)\n            const pkgJsonPath = resolve(dir, 'package.json')\n            if (existsSync(pkgJsonPath)) {\n              name = JSON.parse(readFileSync(pkgJsonPath, 'utf-8')).name\n            }\n            if (typeof name !== 'string' || !name) {\n              name = basename(dir)\n            }\n          }\n          else {\n            name = options.workspacePath.toString()\n          }\n        }\n\n        const isUserBrowserEnabled = viteConfig.test?.browser?.enabled\n        const isBrowserEnabled = isUserBrowserEnabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled)\n        // keep project names to potentially filter it out\n        const workspaceNames = [name]\n        const browser = (viteConfig.test!.browser || {}) as BrowserConfigOptions\n        if (isBrowserEnabled && browser.name && !browser.instances?.length) {\n          // vitest injects `instances` in this case later on\n          workspaceNames.push(name ? `${name} (${browser.name})` : browser.name)\n        }\n\n        viteConfig.test?.browser?.instances?.forEach((instance) => {\n          // every instance is a potential project\n          instance.name ??= name ? `${name} (${instance.browser})` : instance.browser\n          if (isBrowserEnabled) {\n            workspaceNames.push(instance.name)\n          }\n        })\n\n        const filters = project.vitest.config.project\n        // if there is `--project=...` filter, check if any of the potential projects match\n        // if projects don't match, we ignore the test project altogether\n        // if some of them match, they will later be filtered again by `resolveWorkspace`\n        if (filters.length) {\n          const hasProject = workspaceNames.some((name) => {\n            return project.vitest.matchesProjectFilter(name)\n          })\n          if (!hasProject) {\n            throw new VitestFilteredOutProjectError()\n          }\n        }\n\n        const vitestConfig: UserConfig = {\n          name: { label: name, color },\n        }\n\n        vitestConfig.experimental ??= {}\n\n        // always inherit the global `fsModuleCache` value even without `extends: true`\n        if (testConfig.experimental?.fsModuleCache == null && project.vitest.config.experimental?.fsModuleCache != null) {\n          vitestConfig.experimental.fsModuleCache = project.vitest.config.experimental.fsModuleCache\n        }\n        if (testConfig.experimental?.fsModuleCachePath == null && project.vitest.config.experimental?.fsModuleCachePath != null) {\n          vitestConfig.experimental.fsModuleCachePath = project.vitest.config.experimental.fsModuleCachePath\n        }\n        if (testConfig.experimental?.viteModuleRunner == null && project.vitest.config.experimental?.viteModuleRunner != null) {\n          vitestConfig.experimental.viteModuleRunner = project.vitest.config.experimental.viteModuleRunner\n        }\n        if (testConfig.experimental?.nodeLoader == null && project.vitest.config.experimental?.nodeLoader != null) {\n          vitestConfig.experimental.nodeLoader = project.vitest.config.experimental.nodeLoader\n        }\n        if (testConfig.experimental?.importDurations == null && project.vitest.config.experimental?.importDurations != null) {\n          vitestConfig.experimental.importDurations = project.vitest.config.experimental.importDurations\n        }\n\n        return {\n          base: '/',\n          environments: {\n            __vitest__: {\n              dev: {},\n            },\n          },\n          test: vitestConfig,\n        }\n      },\n    },\n    {\n      name: 'vitest:project',\n      enforce: 'pre',\n      options() {\n        this.meta.watchMode = false\n      },\n      config(viteConfig) {\n        const originalDefine = { ...viteConfig.define } // stash original defines for browser mode\n        const defines: Record<string, any> = deleteDefineConfig(viteConfig)\n\n        const testConfig = viteConfig.test || {}\n        const root = testConfig.root || viteConfig.root || options.root\n\n        const resolveOptions = getDefaultResolveOptions()\n        let config: ViteConfig = {\n          root,\n          define: {\n            // disable replacing `process.env.NODE_ENV` with static string by vite:client-inject\n            'process.env.NODE_ENV': 'process.env.NODE_ENV',\n          },\n          resolve: {\n            ...resolveOptions,\n            alias: testConfig.alias,\n          },\n          server: {\n            // disable watch mode in workspaces,\n            // because it is handled by the top-level watcher\n            watch: null,\n            open: false,\n            hmr: false,\n            ws: false,\n            preTransformRequests: false,\n            middlewareMode: true,\n            fs: {\n              allow: resolveFsAllow(\n                project.vitest.config.root,\n                project.vitest.vite.config.configFile,\n              ),\n            },\n          },\n          // eslint-disable-next-line ts/ban-ts-comment\n          // @ts-ignore Vite 6 compat\n          environments: {\n            ssr: {\n              resolve: resolveOptions,\n            },\n          },\n          test: {},\n        }\n\n        if ('rolldownVersion' in vite) {\n          config = {\n            ...config,\n            // eslint-disable-next-line ts/ban-ts-comment\n            // @ts-ignore rolldown-vite only\n            oxc: viteConfig.oxc === false\n              ? false\n              : {\n                  // eslint-disable-next-line ts/ban-ts-comment\n                  // @ts-ignore rolldown-vite only\n                  target: viteConfig.oxc?.target || 'node18',\n                },\n          }\n        }\n        else {\n          config = {\n            ...config,\n            esbuild: viteConfig.esbuild === false\n              ? false\n              : {\n                  // Lowest target Vitest supports is Node18\n                  target: viteConfig.esbuild?.target || 'node18',\n                  sourcemap: 'external',\n                  // Enables using ignore hint for coverage providers with @preserve keyword\n                  legalComments: 'inline',\n                },\n          }\n        }\n\n        ;(config.test as ResolvedConfig).defines = defines\n        ;(config.test as ResolvedConfig).viteDefine = originalDefine\n\n        const classNameStrategy\n          = (typeof testConfig.css !== 'boolean'\n            && testConfig.css?.modules?.classNameStrategy)\n          || 'stable'\n\n        if (classNameStrategy !== 'scoped') {\n          config.css ??= {}\n          config.css.modules ??= {}\n          if (config.css.modules) {\n            config.css.modules.generateScopedName = (\n              name: string,\n              filename: string,\n            ) => {\n              const root = project.config.root\n              return generateScopedClassName(\n                classNameStrategy,\n                name,\n                relative(root, filename),\n              )!\n            }\n          }\n        }\n        config.customLogger = createViteLogger(\n          project.vitest.logger,\n          viteConfig.logLevel || 'warn',\n          {\n            allowClearScreen: false,\n          },\n        )\n        config.customLogger = silenceImportViteIgnoreWarning(config.customLogger)\n\n        return config\n      },\n    },\n    {\n      name: 'vitest:project:server',\n      enforce: 'pre',\n      async configureServer(server) {\n        const options = deepMerge({}, configDefaults, server.config.test || {})\n        await project._configureServer(options, server)\n\n        await server.watcher.close()\n      },\n    },\n    MetaEnvReplacerPlugin(),\n    ...CSSEnablerPlugin(project),\n    CoverageTransform(project.vitest),\n    ...MocksPlugins(),\n    VitestProjectResolver(project.vitest),\n    VitestOptimizer(),\n    NormalizeURLPlugin(),\n    ModuleRunnerTransform(),\n  ]\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pool.ts",
    "content": "import type { Awaitable } from '@vitest/utils'\nimport type { ContextTestEnvironment } from '../types/worker'\nimport type { Vitest } from './core'\nimport type { PoolTask } from './pools/types'\nimport type { TestProject } from './project'\nimport type { TestSpecification } from './test-specification'\nimport type { BuiltinPool, ResolvedConfig } from './types/config'\nimport * as nodeos from 'node:os'\nimport { isatty } from 'node:tty'\nimport { resolve } from 'pathe'\nimport { version as viteVersion } from 'vite'\nimport { rootDir } from '../paths'\nimport { isWindows } from '../utils/env'\nimport { getWorkerMemoryLimit, stringToBytes } from '../utils/memory-limit'\nimport { getSpecificationsOptions } from '../utils/test-helpers'\nimport { createBrowserPool } from './pools/browser'\nimport { Pool } from './pools/pool'\n\nconst suppressWarningsPath = resolve(rootDir, './suppress-warnings.cjs')\n\ntype RunWithFiles = (\n  files: TestSpecification[],\n  invalidates?: string[],\n) => Promise<void>\n\nexport interface ProcessPool {\n  name: string\n  runTests: RunWithFiles\n  collectTests: RunWithFiles\n  close?: () => Awaitable<void>\n}\n\nexport interface PoolProcessOptions {\n  execArgv: string[]\n  env: Record<string, string>\n}\n\nexport const builtinPools: BuiltinPool[] = [\n  'forks',\n  'threads',\n  'browser',\n  'vmThreads',\n  'vmForks',\n  'typescript',\n]\n\nexport function getFilePoolName(project: TestProject): ResolvedConfig['pool'] {\n  if (project.config.browser.enabled) {\n    return 'browser'\n  }\n  return project.config.pool\n}\n\nexport function createPool(ctx: Vitest): ProcessPool {\n  const pool = new Pool({\n    distPath: ctx.distPath,\n    teardownTimeout: ctx.config.teardownTimeout,\n    state: ctx.state,\n  }, ctx.logger)\n\n  const options = resolveOptions(ctx)\n\n  const Sequencer = ctx.config.sequence.sequencer\n  const sequencer = new Sequencer(ctx)\n\n  let browserPool: ProcessPool | undefined\n\n  async function executeTests(method: 'run' | 'collect', specs: TestSpecification[], invalidates?: string[]): Promise<void> {\n    ctx.onCancel(() => pool.cancel())\n\n    if (ctx.config.shard) {\n      if (!ctx.config.passWithNoTests && ctx.config.shard.count > specs.length) {\n        throw new Error(\n          '--shard <count> must be a smaller than count of test files. '\n          + `Resolved ${specs.length} test files for --shard=${ctx.config.shard.index}/${ctx.config.shard.count}.`,\n        )\n      }\n      specs = await sequencer.shard(Array.from(specs))\n    }\n\n    const taskGroups: {\n      tasks: PoolTask[]\n      maxWorkers: number\n      // browser pool has a more complex logic, so we keep it separately for now\n      browserSpecs: TestSpecification[]\n    }[] = []\n    let workerId = 0\n\n    const sorted = await sequencer.sort(specs)\n    const { environments, tags } = await getSpecificationsOptions(specs)\n    const groups = groupSpecs(sorted, environments)\n\n    const projectEnvs = new WeakMap<TestProject, Partial<NodeJS.ProcessEnv>>()\n    const projectExecArgvs = new WeakMap<TestProject, string[]>()\n\n    for (const group of groups) {\n      if (!group) {\n        continue\n      }\n\n      const taskGroup: PoolTask[] = []\n      const browserSpecs: TestSpecification[] = []\n      taskGroups.push({\n        tasks: taskGroup,\n        maxWorkers: group.maxWorkers,\n        browserSpecs,\n      })\n\n      for (const specs of group.specs) {\n        const { project, pool } = specs[0]\n        if (pool === 'browser') {\n          browserSpecs.push(...specs)\n          continue\n        }\n\n        const environment = environments.get(specs[0])!\n        if (!environment) {\n          throw new Error(`Cannot find the environment. This is a bug in Vitest.`)\n        }\n\n        let env = projectEnvs.get(project)\n        if (!env) {\n          env = {\n            ...process.env,\n            ...options.env,\n            ...ctx.config.env,\n            ...project.config.env,\n          }\n\n          // env are case-insensitive on Windows, but spawned processes don't support it\n          if (isWindows) {\n            for (const name in env) {\n              env[name.toUpperCase()] = env[name]\n            }\n          }\n          projectEnvs.set(project, env)\n        }\n\n        let execArgv = projectExecArgvs.get(project)\n        if (!execArgv) {\n          const conditions = resolveConditions(project)\n          execArgv = [\n            ...options.execArgv,\n            ...conditions,\n            ...project.config.execArgv,\n          ]\n          projectExecArgvs.set(project, execArgv)\n        }\n\n        taskGroup.push({\n          context: {\n            files: specs.map(spec => ({\n              filepath: spec.moduleId,\n              fileTags: tags.get(spec),\n              testLocations: spec.testLines,\n              testNamePattern: spec.testNamePattern,\n              testIds: spec.testIds,\n              testTagsFilter: spec.testTagsFilter,\n            })),\n            invalidates,\n            providedContext: project.getProvidedContext(),\n            workerId: workerId++,\n            environment,\n          },\n          project,\n          env,\n          execArgv,\n          worker: pool,\n          isolate: project.config.isolate,\n          memoryLimit: getMemoryLimit(ctx.config, pool) ?? null,\n        })\n      }\n    }\n\n    const results: PromiseSettledResult<void>[] = []\n\n    for (const { tasks, browserSpecs, maxWorkers } of taskGroups) {\n      pool.setMaxWorkers(maxWorkers)\n\n      const promises = tasks.map(async (task) => {\n        if (ctx.isCancelling) {\n          return ctx.state.cancelFiles(task.context.files, task.project)\n        }\n\n        try {\n          await pool.run(task, method)\n        }\n        catch (error) {\n          // Intentionally cancelled\n          if (ctx.isCancelling && error instanceof Error && error.message === 'Cancelled') {\n            ctx.state.cancelFiles(task.context.files, task.project)\n          }\n          else {\n            throw error\n          }\n        }\n      })\n\n      if (browserSpecs.length) {\n        browserPool ??= createBrowserPool(ctx)\n        if (method === 'collect') {\n          promises.push(browserPool.collectTests(browserSpecs))\n        }\n        else {\n          promises.push(browserPool.runTests(browserSpecs))\n        }\n      }\n\n      const groupResults = await Promise.allSettled(promises)\n\n      results.push(...groupResults)\n    }\n\n    const errors = results\n      .filter(result => result.status === 'rejected')\n      .map(result => result.reason)\n\n    if (errors.length > 0) {\n      throw new AggregateError(\n        errors,\n        'Errors occurred while running tests. For more information, see serialized error.',\n      )\n    }\n  }\n\n  return {\n    name: 'default',\n    runTests: (files, invalidates) => executeTests('run', files, invalidates),\n    collectTests: (files, invalidates) => executeTests('collect', files, invalidates),\n    async close() {\n      await Promise.all([\n        pool.close(),\n        browserPool?.close?.(),\n        ...ctx.projects.map(project => project.typechecker?.stop()),\n      ])\n    },\n  }\n}\n\nfunction resolveOptions(ctx: Vitest) {\n  // Instead of passing whole process.execArgv to the workers, pick allowed options.\n  // Some options may crash worker, e.g. --prof, --title. nodejs/node#41103\n  const execArgv = process.execArgv.filter(\n    execArg =>\n      execArg.startsWith('--cpu-prof')\n      || execArg.startsWith('--heap-prof')\n      || execArg.startsWith('--diagnostic-dir'),\n  )\n\n  const options: PoolProcessOptions = {\n    execArgv: [\n      ...execArgv,\n      '--experimental-import-meta-resolve',\n      // https://github.com/vitest-dev/vitest/issues/8896\n      ...((globalThis as any).Deno || process.versions.pnp ? [] : ['--require', suppressWarningsPath]),\n    ],\n    env: {\n      TEST: 'true',\n      VITEST: 'true',\n      NODE_ENV: process.env.NODE_ENV || 'test',\n      VITEST_MODE: ctx.config.watch ? 'WATCH' : 'RUN',\n      FORCE_TTY: isatty(1) ? 'true' : '',\n    },\n  }\n\n  return options\n}\n\nfunction resolveConditions(project: TestProject) {\n  // in addition to resolve.conditions Vite also adds production/development,\n  // see: https://github.com/vitejs/vite/blob/af2aa09575229462635b7cbb6d248ca853057ba2/packages/vite/src/node/plugins/resolve.ts#L1056-L1080\n  const viteMajor = Number(viteVersion.split('.')[0])\n  const viteConfig = project.vite.config\n\n  const potentialConditions = new Set(viteMajor >= 6\n    ? (viteConfig.ssr.resolve?.conditions ?? [])\n    : [\n        'production',\n        'development',\n        ...(viteConfig.resolve.conditions ?? []),\n      ])\n\n  return [...potentialConditions]\n    .filter((condition) => {\n      if (condition === 'production') {\n        return viteConfig.isProduction\n      }\n      if (condition === 'development') {\n        return !viteConfig.isProduction\n      }\n      return true\n    })\n    .map((condition) => {\n      if (viteMajor >= 6 && condition === 'development|production') {\n        return viteConfig.isProduction ? 'production' : 'development'\n      }\n      return condition\n    })\n    .flatMap(c => ['--conditions', c])\n}\n\nfunction resolveMaxWorkers(project: TestProject) {\n  if (project.config.maxWorkers) {\n    return project.config.maxWorkers\n  }\n\n  if (project.vitest.config.maxWorkers) {\n    return project.vitest.config.maxWorkers\n  }\n\n  const numCpus = typeof nodeos.availableParallelism === 'function'\n    ? nodeos.availableParallelism()\n    : nodeos.cpus().length\n\n  if (project.vitest.config.watch) {\n    return Math.max(Math.floor(numCpus / 2), 1)\n  }\n\n  return Math.max(numCpus - 1, 1)\n}\n\nfunction getMemoryLimit(config: ResolvedConfig, pool: string) {\n  if (pool !== 'vmForks' && pool !== 'vmThreads') {\n    return null\n  }\n\n  const memory = nodeos.totalmem()\n  const limit = getWorkerMemoryLimit(config)\n\n  if (typeof memory === 'number') {\n    return stringToBytes(limit, config.watch ? memory / 2 : memory)\n  }\n\n  // If totalmem is not supported we cannot resolve percentage based values like 0.5, \"50%\"\n  if (\n    (typeof limit === 'number' && limit > 1)\n    || (typeof limit === 'string' && limit.at(-1) !== '%')\n  ) {\n    return stringToBytes(limit)\n  }\n\n  // just ignore \"memoryLimit\" value because we cannot detect memory limit\n  return null\n}\n\nfunction groupSpecs(specs: TestSpecification[], environments: WeakMap<TestSpecification, ContextTestEnvironment>) {\n  // Test files are passed to test runner one at a time, except for Typechecker or when \"--maxWorker=1 --no-isolate\"\n  type SpecsForRunner = TestSpecification[]\n\n  // Tests in a single group are executed with `maxWorkers` parallelism.\n  // Next group starts running after previous finishes - allows real sequential tests.\n  interface Groups { specs: SpecsForRunner[]; maxWorkers: number; typecheck?: boolean }\n  const groups: Groups[] = []\n\n  // Files without file parallelism but without explicit sequence.groupOrder\n  const sequential: Groups = { specs: [], maxWorkers: 1 }\n\n  // Type tests are run in a single group, per project\n  const typechecks: Record<string, TestSpecification[]> = {}\n\n  const serializedEnvironmentOptions = new Map<ContextTestEnvironment, string>()\n\n  function getSerializedOptions(env: ContextTestEnvironment) {\n    const options = serializedEnvironmentOptions.get(env)\n\n    if (options) {\n      return options\n    }\n\n    const serialized = JSON.stringify(env.options)\n    serializedEnvironmentOptions.set(env, serialized)\n    return serialized\n  }\n\n  function isEqualEnvironments(a: TestSpecification, b: TestSpecification) {\n    const aEnv = environments.get(a)\n    const bEnv = environments.get(b)\n\n    if (!aEnv && !bEnv) {\n      return true\n    }\n\n    if (!aEnv || !bEnv || aEnv.name !== bEnv.name) {\n      return false\n    }\n\n    if (!aEnv.options && !bEnv.options) {\n      return true\n    }\n\n    if (!aEnv.options || !bEnv.options) {\n      return false\n    }\n\n    return getSerializedOptions(aEnv) === getSerializedOptions(bEnv)\n  }\n\n  specs.forEach((spec) => {\n    if (spec.pool === 'typescript') {\n      typechecks[spec.project.name] ||= []\n      typechecks[spec.project.name].push(spec)\n      return\n    }\n\n    const order = spec.project.config.sequence.groupOrder\n    const isolate = spec.project.config.isolate\n\n    // Files that have disabled parallelism and default groupOrder are set into their own group\n    if (isolate === true && order === 0 && spec.project.config.maxWorkers === 1) {\n      return sequential.specs.push([spec])\n    }\n\n    const maxWorkers = resolveMaxWorkers(spec.project)\n    groups[order] ||= { specs: [], maxWorkers }\n\n    // Multiple projects with different maxWorkers but same groupOrder\n    if (groups[order].maxWorkers !== maxWorkers) {\n      const last = groups[order].specs.at(-1)?.at(-1)?.project.name\n\n      throw new Error(`Projects \"${last}\" and \"${spec.project.name}\" have different 'maxWorkers' but same 'sequence.groupOrder'.\\nProvide unique 'sequence.groupOrder' for them.`)\n    }\n\n    // Non-isolated single worker can receive all files at once\n    if (isolate === false && maxWorkers === 1) {\n      const previous = groups[order].specs[0]?.[0]\n\n      if (previous && previous.project.name === spec.project.name && isEqualEnvironments(spec, previous)) {\n        return groups[order].specs[0].push(spec)\n      }\n    }\n\n    groups[order].specs.push([spec])\n  })\n\n  let order = Math.max(0, ...groups.keys()) + 1\n\n  for (const projectName in typechecks) {\n    const maxWorkers = resolveMaxWorkers(typechecks[projectName][0].project)\n    const previous = groups[order - 1]\n    if (previous && previous.typecheck && maxWorkers !== previous.maxWorkers) {\n      order += 1\n    }\n\n    groups[order] ||= { specs: [], maxWorkers, typecheck: true }\n    groups[order].specs.push(typechecks[projectName])\n  }\n\n  if (sequential.specs.length) {\n    groups.push(sequential)\n  }\n\n  return groups\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pools/browser.ts",
    "content": "import type { Context, Span } from '@opentelemetry/api'\nimport type { FileSpecification } from '@vitest/runner'\nimport type { DeferPromise } from '@vitest/utils/helpers'\nimport type { Traces } from '../../utils/traces'\nimport type { Vitest } from '../core'\nimport type { ProcessPool } from '../pool'\nimport type { TestProject } from '../project'\nimport type { TestSpecification } from '../test-specification'\nimport type { BrowserProvider } from '../types/browser'\nimport crypto from 'node:crypto'\nimport { readFile } from 'node:fs/promises'\nimport * as nodeos from 'node:os'\nimport { createDefer } from '@vitest/utils/helpers'\nimport { stringify } from 'flatted'\nimport { createDebugger } from '../../utils/debugger'\nimport { detectCodeBlock } from '../../utils/test-helpers'\n\nconst debug = createDebugger('vitest:browser:pool')\n\nexport function createBrowserPool(vitest: Vitest): ProcessPool {\n  const providers = new Set<BrowserProvider>()\n\n  const numCpus\n    = typeof nodeos.availableParallelism === 'function'\n      ? nodeos.availableParallelism()\n      : nodeos.cpus().length\n\n  // if there are more than ~12 threads (optimistically), the main thread chokes\n  // https://github.com/vitest-dev/vitest/issues/7871\n  const maxThreadsCount = Math.min(12, numCpus - 1)\n  const threadsCount = vitest.config.watch\n    ? Math.max(Math.floor(maxThreadsCount / 2), 1)\n    : Math.max(maxThreadsCount, 1)\n\n  const projectPools = new WeakMap<TestProject, BrowserPool>()\n\n  const ensurePool = (project: TestProject) => {\n    if (projectPools.has(project)) {\n      return projectPools.get(project)!\n    }\n\n    debug?.('creating pool for project %s', project.name)\n\n    const resolvedUrls = project.browser!.vite.resolvedUrls\n    const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0]\n\n    if (!origin) {\n      throw new Error(\n        `Can't find browser origin URL for project \"${project.name}\"`,\n      )\n    }\n\n    const pool: BrowserPool = new BrowserPool(project, {\n      maxWorkers: getThreadsCount(project),\n      origin,\n    })\n    projectPools.set(project, pool)\n    vitest.onCancel(() => {\n      pool.cancel()\n    })\n\n    return pool\n  }\n\n  const runWorkspaceTests = async (method: 'run' | 'collect', specs: TestSpecification[]) => {\n    const groupedFiles = new Map<TestProject, FileSpecification[]>()\n    const testFilesCode = new Map<string, string>()\n    const testFileTags = new WeakMap<TestSpecification, string[]>()\n\n    await Promise.all(specs.map(async (spec) => {\n      let code = testFilesCode.get(spec.moduleId)\n      // TODO: this really should be done only once when collecting specifications\n      if (code == null) {\n        code = await readFile(spec.moduleId, 'utf-8').catch(() => '')\n        testFilesCode.set(spec.moduleId, code)\n      }\n      const { tags } = detectCodeBlock(code)\n      testFileTags.set(spec, tags)\n    }))\n\n    // to keep the sorting, we need to iterate over specs separately\n    for (const spec of specs) {\n      const { project, moduleId, testLines, testIds, testNamePattern, testTagsFilter } = spec\n      const files = groupedFiles.get(project) || []\n      files.push({\n        filepath: moduleId,\n        testLocations: testLines,\n        testIds,\n        testNamePattern,\n        testTagsFilter,\n        fileTags: testFileTags.get(spec),\n      })\n      groupedFiles.set(project, files)\n    }\n\n    let isCancelled = false\n    vitest.onCancel(() => {\n      isCancelled = true\n    })\n\n    const initialisedPools = await Promise.all([...groupedFiles.entries()].map(async ([project, files]) => {\n      await project._initBrowserProvider()\n\n      if (!project.browser) {\n        throw new TypeError(`The browser server was not initialized${project.name ? ` for the \"${project.name}\" project` : ''}. This is a bug in Vitest. Please, open a new issue with reproduction.`)\n      }\n\n      if (isCancelled) {\n        return\n      }\n\n      debug?.('provider is ready for %s project', project.name)\n\n      const pool = ensurePool(project)\n      vitest.state.clearFiles(project, files.map(f => f.filepath))\n      providers.add(project.browser!.provider)\n\n      return {\n        pool,\n        provider: project.browser!.provider,\n        runTests: () => pool.runTests(method, files),\n      }\n    }))\n\n    if (isCancelled) {\n      return\n    }\n\n    const parallelPools: (() => Promise<void>)[] = []\n    const nonParallelPools: (() => Promise<void>)[] = []\n\n    for (const pool of initialisedPools) {\n      if (!pool) {\n        // this means it was cancelled\n        return\n      }\n\n      if (pool.provider.mocker && pool.provider.supportsParallelism) {\n        parallelPools.push(pool.runTests)\n      }\n      else {\n        nonParallelPools.push(pool.runTests)\n      }\n    }\n\n    await Promise.all(parallelPools.map(runTests => runTests()))\n\n    for (const runTests of nonParallelPools) {\n      if (isCancelled) {\n        return\n      }\n\n      await runTests()\n    }\n  }\n\n  function getThreadsCount(project: TestProject) {\n    const config = project.config.browser\n    if (\n      !config.headless\n      || !config.fileParallelism\n      || !project.browser!.provider.supportsParallelism\n    ) {\n      return 1\n    }\n\n    if (project.config.maxWorkers) {\n      return project.config.maxWorkers\n    }\n\n    return threadsCount\n  }\n\n  return {\n    name: 'browser',\n    async close() {\n      await Promise.all([...providers].map(provider => provider.close()))\n      vitest._browserSessions.sessionIds.clear()\n      providers.clear()\n      vitest.projects.forEach((project) => {\n        project.browser?.state.orchestrators.forEach((orchestrator) => {\n          orchestrator.$close()\n        })\n      })\n      debug?.('browser pool closed all providers')\n    },\n    runTests: files => runWorkspaceTests('run', files),\n    collectTests: files => runWorkspaceTests('collect', files),\n  }\n}\n\nfunction escapePathToRegexp(path: string): string {\n  return path.replace(/[/\\\\.?*()^${}|[\\]+]/g, '\\\\$&')\n}\n\nclass BrowserPool {\n  private _queue: FileSpecification[] = []\n  private _promise: DeferPromise<void> | undefined\n  private _providedContext: string | undefined\n\n  private readySessions = new Set<string>()\n\n  private _traces: Traces\n  private _otel: {\n    span: Span\n    context: Context\n  }\n\n  constructor(\n    private project: TestProject,\n    private options: {\n      maxWorkers: number\n      origin: string\n    },\n  ) {\n    this._traces = project.vitest._traces\n    this._otel = this._traces.startContextSpan('vitest.browser')\n    this._otel.span.setAttributes({\n      'vitest.project': project.name,\n      'vitest.browser.provider': this.project.browser!.provider.name,\n    })\n  }\n\n  public cancel(): void {\n    this._queue = []\n    this._otel.span.end()\n  }\n\n  public reject(error: Error): void {\n    this._promise?.reject(error)\n    this._promise = undefined\n    this.cancel()\n  }\n\n  get orchestrators() {\n    return this.project.browser!.state.orchestrators\n  }\n\n  async runTests(method: 'run' | 'collect', files: FileSpecification[]): Promise<void> {\n    this._promise ??= createDefer<void>()\n\n    if (!files.length) {\n      debug?.('no tests found, finishing test run immediately')\n      this._promise.resolve()\n      return this._promise\n    }\n\n    this._providedContext = stringify(this.project.getProvidedContext())\n\n    this._queue.push(...files)\n\n    this.readySessions.forEach((sessionId) => {\n      if (this._queue.length) {\n        this.readySessions.delete(sessionId)\n        this.runNextTest(method, sessionId)\n      }\n    })\n\n    if (this.orchestrators.size >= this.options.maxWorkers) {\n      debug?.('all orchestrators are ready, not creating more')\n      return this._promise\n    }\n\n    // open the minimum amount of tabs\n    // if there is only 1 file running, we don't need 8 tabs running\n    const workerCount = Math.min(\n      this.options.maxWorkers - this.orchestrators.size,\n      files.length,\n    )\n\n    const promises: Promise<void>[] = []\n    for (let i = 0; i < workerCount; i++) {\n      const sessionId = crypto.randomUUID()\n      this.project.vitest._browserSessions.sessionIds.add(sessionId)\n      const project = this.project.name\n      debug?.('[%s] creating session for %s', sessionId, project)\n      let page = this._traces.$(\n        `vitest.browser.open`,\n        {\n          context: this._otel.context,\n          attributes: {\n            'vitest.browser.session_id': sessionId,\n          },\n        },\n        () => this.openPage(sessionId, { parallel: workerCount > 1 }),\n      )\n      page = page.then(() => {\n        // start running tests on the page when it's ready\n        this.runNextTest(method, sessionId)\n      })\n      promises.push(page)\n    }\n    await Promise.all(promises)\n    debug?.('all sessions are created')\n    return this._promise\n  }\n\n  private async openPage(sessionId: string, options: { parallel: boolean }): Promise<void> {\n    const sessionPromise = this.project.vitest._browserSessions.createSession(\n      sessionId,\n      this.project,\n      this,\n    )\n    const browser = this.project.browser!\n    const url = new URL('/__vitest_test__/', this.options.origin)\n    url.searchParams.set('sessionId', sessionId)\n    const otelCarrier = this._traces.getContextCarrier()\n    if (otelCarrier) {\n      url.searchParams.set('otelCarrier', JSON.stringify(otelCarrier))\n    }\n    const pagePromise = browser.provider.openPage(\n      sessionId,\n      url.toString(),\n      options,\n    )\n    await Promise.all([sessionPromise, pagePromise])\n  }\n\n  private getOrchestrator(sessionId: string) {\n    const orchestrator = this.orchestrators.get(sessionId)\n    if (!orchestrator) {\n      throw new Error(`Orchestrator not found for session ${sessionId}. This is a bug in Vitest. Please, open a new issue with reproduction.`)\n    }\n    return orchestrator\n  }\n\n  private finishSession(sessionId: string): void {\n    this.readySessions.add(sessionId)\n\n    // the last worker finished running tests\n    if (this.readySessions.size === this.orchestrators.size) {\n      this._otel.span.end()\n      this._promise?.resolve()\n      this._promise = undefined\n      debug?.('[%s] all tests finished running', sessionId)\n    }\n    else {\n      debug?.(\n        `did not finish sessions for ${sessionId}: |ready - %s| |overall - %s|`,\n        [...this.readySessions].join(', '),\n        [...this.orchestrators.keys()].join(', '),\n      )\n    }\n  }\n\n  private runNextTest(method: 'run' | 'collect', sessionId: string): void {\n    const file = this._queue.shift()\n\n    if (!file) {\n      debug?.('[%s] no more tests to run', sessionId)\n      const isolate = this.project.config.browser.isolate\n      // we don't need to cleanup testers if isolation is enabled,\n      // because cleanup is done at the end of every test\n      if (isolate) {\n        this.finishSession(sessionId)\n        return\n      }\n\n      // we need to cleanup testers first because there is only\n      // one iframe and it does the cleanup only after everything is completed\n      const orchestrator = this.getOrchestrator(sessionId)\n      orchestrator.cleanupTesters()\n        .catch(error => this.reject(error))\n        .finally(() => this.finishSession(sessionId))\n      return\n    }\n\n    if (!this._promise) {\n      throw new Error(`Unexpected empty queue`)\n    }\n\n    const orchestrator = this.getOrchestrator(sessionId)\n    debug?.('[%s] run test %s', sessionId, file)\n\n    this.setBreakpoint(sessionId, file.filepath).then(() => {\n      // this starts running tests inside the orchestrator\n      const testersPromise = this._traces.$(\n        `vitest.browser.run`,\n        {\n          context: this._otel.context,\n          attributes: {\n            'code.file.path': file.filepath,\n          },\n        },\n        async () => {\n          return orchestrator.createTesters(\n            {\n              method,\n              files: [file],\n              // this will be parsed by the test iframe, not the orchestrator\n              // so we need to stringify it first to avoid double serialization\n              providedContext: this._providedContext || '[{}]',\n              otelCarrier: this._traces.getContextCarrier(),\n            },\n          )\n        },\n      )\n      testersPromise\n        .then(() => {\n          debug?.('[%s] test %s finished running', sessionId, file)\n          this.runNextTest(method, sessionId)\n        })\n        .catch((error) => {\n          // if user cancels the test run manually, ignore the error and exit gracefully\n          if (\n            this.project.vitest.isCancelling\n            && error instanceof Error\n            && error.message.startsWith('Browser connection was closed while running tests')\n          ) {\n            this.cancel()\n            this._promise?.resolve()\n            this._promise = undefined\n            debug?.('[%s] browser connection was closed', sessionId)\n            return\n          }\n          debug?.('[%s] error during %s test run: %s', sessionId, file, error)\n          this.reject(\n            new Error(`Failed to run the test ${file.filepath}.`, { cause: error }),\n          )\n        })\n    }).catch(err => this.reject(err))\n  }\n\n  async setBreakpoint(sessionId: string, file: string) {\n    if (!this.project.config.inspector.waitForDebugger) {\n      return\n    }\n\n    const provider = this.project.browser!.provider\n    const browser = this.project.config.browser.name\n\n    if (shouldIgnoreDebugger(provider.name, browser)) {\n      debug?.('[$s] ignoring debugger in %s browser because it is not supported', sessionId, browser)\n      return\n    }\n\n    if (!provider.getCDPSession) {\n      throw new Error('Unable to set breakpoint, CDP not supported')\n    }\n\n    debug?.('[%s] set breakpoint for %s', sessionId, file)\n    const session = await provider.getCDPSession(sessionId)\n    await session.send('Debugger.enable', {})\n    await session.send('Debugger.setBreakpointByUrl', {\n      lineNumber: 0,\n      urlRegex: escapePathToRegexp(file),\n    })\n  }\n}\n\nfunction shouldIgnoreDebugger(provider: string, browser: string) {\n  if (provider === 'webdriverio') {\n    return browser !== 'chrome' && browser !== 'edge'\n  }\n  return browser !== 'chromium'\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pools/pool.ts",
    "content": "import type { Span } from '@opentelemetry/api'\nimport type { ContextTestEnvironment } from '../../types/worker'\nimport type { Logger } from '../logger'\nimport type { StateManager } from '../state'\nimport type { PoolOptions, PoolTask, WorkerResponse } from './types'\nimport { PoolRunner } from './poolRunner'\nimport { ForksPoolWorker } from './workers/forksWorker'\nimport { ThreadsPoolWorker } from './workers/threadsWorker'\nimport { TypecheckPoolWorker } from './workers/typecheckWorker'\nimport { VmForksPoolWorker } from './workers/vmForksWorker'\nimport { VmThreadsPoolWorker } from './workers/vmThreadsWorker'\n\nconst WORKER_START_TIMEOUT = 90_000\n\ninterface Options {\n  distPath: string\n  teardownTimeout: number\n  state: StateManager\n}\n\ninterface QueuedTask {\n  task: PoolTask\n  resolver: ReturnType<typeof withResolvers>\n  method: 'run' | 'collect'\n}\n\ninterface ActiveTask extends QueuedTask {\n  cancelTask: (options?: { force: boolean }) => Promise<void>\n}\n\nexport class Pool {\n  private maxWorkers: number = 0\n  private workerIds = new Map<number, boolean>()\n\n  private queue: QueuedTask[] = []\n  private activeTasks: ActiveTask[] = []\n  private sharedRunners: PoolRunner[] = []\n  private exitPromises: Promise<void>[] = []\n  private _isCancelling: boolean = false\n\n  constructor(private options: Options, private logger: Logger) {}\n\n  setMaxWorkers(maxWorkers: number): void {\n    this.maxWorkers = maxWorkers\n\n    this.workerIds = new Map(\n      Array.from({ length: maxWorkers }).fill(0).map((_, i) => [i + 1, true]),\n    )\n  }\n\n  async run(task: PoolTask, method: 'run' | 'collect'): Promise<void> {\n    // Prevent new tasks from being queued during cancellation\n    if (this._isCancelling) {\n      throw new Error('[vitest-pool]: Cannot run tasks while pool is cancelling')\n    }\n\n    // Every runner related failure should make this promise reject so that it's picked by pool.\n    // This resolver is used to make the error handling in recursive queue easier.\n    const testFinish = withResolvers()\n\n    this.queue.push({ task, resolver: testFinish, method })\n    void this.schedule()\n\n    await testFinish.promise\n  }\n\n  private async schedule(): Promise<void> {\n    if (this.queue.length === 0 || this.activeTasks.length >= this.maxWorkers) {\n      return\n    }\n\n    const { task, resolver, method } = this.queue.shift()!\n\n    try {\n      let isMemoryLimitReached = false\n      const runner = this.getPoolRunner(task, method)\n\n      const poolId = runner.poolId ?? this.getWorkerId()\n      runner.poolId = poolId\n\n      const activeTask = { task, resolver, method, cancelTask }\n      this.activeTasks.push(activeTask)\n\n      // active tasks receive cancel signal and shut down gracefully\n      async function cancelTask(options?: { force: boolean }) {\n        if (options?.force) {\n          await runner.stop({ force: true })\n        }\n\n        await runner.waitForTerminated()\n        resolver.reject(new Error('Cancelled'))\n      }\n\n      const onFinished = (message: WorkerResponse) => {\n        if (message?.__vitest_worker_response__ && message.type === 'testfileFinished') {\n          if (task.memoryLimit && message.usedMemory) {\n            isMemoryLimitReached = message.usedMemory >= task.memoryLimit\n          }\n          if (message.error) {\n            this.options.state.catchError(message.error, 'Test Run Error')\n          }\n\n          runner.off('message', onFinished)\n          resolver.resolve()\n        }\n      }\n\n      runner.on('message', onFinished)\n\n      if (!runner.isStarted) {\n        runner.on('error', (error) => {\n          resolver.reject(\n            new Error(`[vitest-pool]: Worker ${task.worker} emitted error.`, { cause: error }),\n          )\n        })\n\n        const id = setTimeout(\n          () => resolver.reject(new Error(`[vitest-pool]: Timeout starting ${task.worker} runner.`)),\n          WORKER_START_TIMEOUT,\n        )\n\n        await runner.start({ workerId: task.context.workerId })\n          .catch(error =>\n            resolver.reject(\n              new Error(`[vitest-pool]: Failed to start ${task.worker} worker for test files ${formatFiles(task)}.`, { cause: error }),\n            ),\n          )\n          .finally(() => clearTimeout(id))\n      }\n\n      let span: Span | undefined\n\n      if (!resolver.isRejected) {\n        span = runner.startTracesSpan(`vitest.worker.${method}`)\n\n        // Start running the test in the worker\n        runner.request(method, task.context)\n      }\n\n      await resolver.promise\n        .catch(error => span?.recordException(error))\n        .finally(() => span?.end())\n\n      const index = this.activeTasks.indexOf(activeTask)\n      if (index !== -1) {\n        this.activeTasks.splice(index, 1)\n      }\n\n      if (\n        !task.isolate\n        && !isMemoryLimitReached\n        && this.queue[0]?.task.isolate === false\n        && isEqualRunner(runner, this.queue[0].task)\n      ) {\n        this.sharedRunners.push(runner)\n        return this.schedule()\n      }\n\n      // Runner terminations are started but not awaited until the end of full run.\n      // Runner termination can also already start from task cancellation.\n      if (!runner.isTerminated) {\n        const id = setTimeout(\n          () => this.logger.error(`[vitest-pool]: Timeout terminating ${task.worker} worker for test files ${formatFiles(task)}.`),\n          this.options.teardownTimeout,\n        )\n\n        this.exitPromises.push(\n          runner.stop({ force: resolver.isRejected })\n            .then(() => clearTimeout(id))\n            .catch(error => this.logger.error(`[vitest-pool]: Failed to terminate ${task.worker} worker for test files ${formatFiles(task)}.`, error)),\n        )\n      }\n\n      this.freeWorkerId(poolId)\n    }\n\n    // This is mostly to avoid zombie workers when/if Vitest internals run into errors\n    catch (error) {\n      return resolver.reject(error)\n    }\n\n    return this.schedule()\n  }\n\n  async cancel(): Promise<void> {\n    // Force exit if previous cancel is still on-going\n    // for example when user does 'CTRL+c' twice in row\n    const force = this._isCancelling\n\n    // Set flag to prevent new tasks from being queued\n    this._isCancelling = true\n\n    const pendingTasks = this.queue.splice(0)\n\n    if (pendingTasks.length) {\n      const error = new Error('Cancelled')\n      pendingTasks.forEach(task => task.resolver.reject(error))\n    }\n\n    await Promise.all(this.activeTasks.map(task => task.cancelTask({ force })))\n    this.activeTasks = []\n\n    await Promise.all(this.sharedRunners.map(runner => runner.stop()))\n    this.sharedRunners = []\n\n    await Promise.all(this.exitPromises)\n    this.exitPromises = []\n\n    this.workerIds.forEach((_, id) => this.freeWorkerId(id))\n\n    // Reset flag after cancellation completes\n    this._isCancelling = false\n  }\n\n  async close(): Promise<void> {\n    await this.cancel()\n  }\n\n  private getPoolRunner(task: PoolTask, method: 'run' | 'collect'): PoolRunner {\n    if (task.isolate === false) {\n      const index = this.sharedRunners.findIndex(runner => isEqualRunner(runner, task))\n\n      if (index !== -1) {\n        const runner = this.sharedRunners.splice(index, 1)[0]\n        runner.reconfigure(task)\n        return runner\n      }\n    }\n\n    const options: PoolOptions = {\n      distPath: this.options.distPath,\n      project: task.project,\n      method,\n      environment: task.context.environment,\n      env: task.env,\n      execArgv: task.execArgv,\n    }\n\n    switch (task.worker) {\n      case 'forks':\n        return new PoolRunner(options, new ForksPoolWorker(options))\n\n      case 'vmForks':\n        return new PoolRunner(options, new VmForksPoolWorker(options))\n\n      case 'threads':\n        return new PoolRunner(options, new ThreadsPoolWorker(options))\n\n      case 'vmThreads':\n        return new PoolRunner(options, new VmThreadsPoolWorker(options))\n\n      case 'typescript':\n        return new PoolRunner(options, new TypecheckPoolWorker(options))\n    }\n\n    const customPool = task.project.config.poolRunner\n    if (customPool != null && customPool.name === task.worker) {\n      return new PoolRunner(options, customPool.createPoolWorker(options))\n    }\n\n    throw new Error(`Runner ${task.worker} is not supported. Test files: ${formatFiles(task)}.`)\n  }\n\n  private getWorkerId() {\n    let workerId = 0\n\n    this.workerIds.forEach((state, id) => {\n      if (state && !workerId) {\n        workerId = id\n        this.workerIds.set(id, false)\n      }\n    })\n\n    return workerId\n  }\n\n  private freeWorkerId(id: number) {\n    this.workerIds.set(id, true)\n  }\n}\n\nfunction withResolvers() {\n  let resolve = () => {}\n  let reject = (_error: unknown) => {}\n\n  const promise = new Promise<void>((res, rej) => {\n    resolve = res\n    reject = rej\n  })\n\n  const resolver = {\n    promise,\n    resolve,\n    reject: (reason: unknown) => {\n      resolver.isRejected = true\n      reject(reason)\n    },\n    isRejected: false,\n  }\n\n  return resolver\n}\n\nfunction formatFiles(task: PoolTask) {\n  return task.context.files.map(file => file.filepath).join(', ')\n}\n\nfunction isEqualRunner(runner: PoolRunner, task: PoolTask) {\n  if (task.isolate) {\n    throw new Error('Isolated tasks should not share runners')\n  }\n  if (runner.worker.name !== task.worker || runner.project !== task.project) {\n    return false\n  }\n  // by default, check that the environments are the same\n  // some workers (like vmThreads/vmForks) do not need this check\n  if (!runner.worker.canReuse) {\n    return isEnvironmentEqual(task.context.environment, runner.environment)\n  }\n  return runner.worker.canReuse(task)\n}\n\nfunction isEnvironmentEqual(env1: ContextTestEnvironment, env2: ContextTestEnvironment): boolean {\n  if (env1.name !== env2.name) {\n    return false\n  }\n  return deepEqual(env1.options, env2.options)\n}\n\nfunction deepEqual(obj1: any, obj2: any): boolean {\n  if (obj1 === obj2) {\n    return true\n  }\n  if (obj1 == null || obj2 == null) {\n    return obj1 === obj2\n  }\n  if (typeof obj1 !== 'object' || typeof obj2 !== 'object') {\n    return false\n  }\n\n  const keys1 = Object.keys(obj1)\n  const keys2 = Object.keys(obj2)\n\n  if (keys1.length !== keys2.length) {\n    return false\n  }\n\n  for (const key of keys1) {\n    if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {\n      return false\n    }\n  }\n\n  return true\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pools/poolRunner.ts",
    "content": "import type { Span, TimeInput } from '@opentelemetry/api'\nimport type { DeferPromise } from '@vitest/utils/helpers'\nimport type { BirpcReturn } from 'birpc'\nimport type { RunnerRPC, RuntimeRPC } from '../../types/rpc'\nimport type { ContextTestEnvironment, WorkerExecuteContext } from '../../types/worker'\nimport type { Traces } from '../../utils/traces'\nimport type { TestProject } from '../project'\nimport type { PoolOptions, PoolRunnerOTEL, PoolTask, PoolWorker, WorkerRequest, WorkerResponse } from './types'\nimport { EventEmitter } from 'node:events'\nimport { createDefer } from '@vitest/utils/helpers'\nimport { createBirpc } from 'birpc'\nimport { createMethodsRPC } from './rpc'\n\nenum RunnerState {\n  IDLE = 'idle',\n  STARTING = 'starting',\n  STARTED = 'started',\n  START_FAILURE = 'start_failure',\n  STOPPING = 'stopping',\n  STOPPED = 'stopped',\n}\n\ninterface StopOptions {\n  /**\n   * **Do not use unless you have good reason to.**\n   *\n   * Indicates whether to skip waiting for worker's response for `{ type: 'stop' }` message or not.\n   * By default `.stop()` terminates the workers gracefully by sending them stop-message\n   * and waiting for workers response, so that workers can do proper teardown.\n   *\n   * Force exit is used when user presses `CTRL+c` twice in row and intentionally does\n   * non-graceful exit. For example in cases where worker is stuck on synchronous thread\n   * blocking function call and it won't response to `{ type: 'stop' }` messages.\n   */\n  force: boolean\n}\n\nconst START_TIMEOUT = 60_000\nconst STOP_TIMEOUT = 60_000\n\n/** @experimental */\nexport class PoolRunner {\n  /** Exposed to test runner as `VITEST_POOL_ID`. Value is between 1-`maxWorkers`. */\n  public poolId: number | undefined = undefined\n\n  public readonly project: TestProject\n  public environment: ContextTestEnvironment\n\n  private _state: RunnerState = RunnerState.IDLE\n  private _operationLock: DeferPromise<void> | null = null\n  private _terminatePromise: DeferPromise<void> = createDefer()\n\n  private _eventEmitter: EventEmitter<{\n    message: [WorkerResponse]\n    error: [Error]\n    rpc: [unknown]\n  }> = new EventEmitter()\n\n  private _offCancel: () => void\n  private _rpc: BirpcReturn<RunnerRPC, RuntimeRPC>\n\n  private _otel: PoolRunnerOTEL | null = null\n  private _traces: Traces\n\n  public get isTerminated(): boolean {\n    return this._state === RunnerState.STOPPED\n  }\n\n  public waitForTerminated(): Promise<void> {\n    return this._terminatePromise\n  }\n\n  public get isStarted(): boolean {\n    return this._state === RunnerState.STARTED\n  }\n\n  constructor(options: PoolOptions, public worker: PoolWorker) {\n    this.project = options.project\n    this.environment = options.environment\n\n    const vitest = this.project.vitest\n    this._traces = vitest._traces\n    if (this._traces.isEnabled()) {\n      const { span: workerSpan, context } = this._traces.startContextSpan('vitest.worker')\n      this._otel = {\n        span: workerSpan,\n        workerContext: context,\n        files: [],\n      }\n      this._otel.span.setAttributes({\n        'vitest.worker.name': this.worker.name,\n        'vitest.project': this.project.name,\n        'vitest.environment': this.environment.name,\n      })\n    }\n\n    this._rpc = createBirpc<RunnerRPC, RuntimeRPC>(\n      createMethodsRPC(this.project, {\n        collect: options.method === 'collect',\n        cacheFs: worker.cacheFs,\n      }),\n      {\n        eventNames: ['onCancel'],\n        post: (request) => {\n          if (this._state !== RunnerState.STOPPING && this._state !== RunnerState.STOPPED) {\n            this.postMessage(request)\n          }\n        },\n        on: callback => this._eventEmitter.on('rpc', callback),\n        timeout: -1,\n      },\n    )\n\n    this._offCancel = vitest.onCancel(reason => this._rpc.onCancel(reason))\n  }\n\n  /**\n   * \"reconfigure\" can only be called if `environment` is different, since different project always\n   * requires a new PoolRunner instance.\n   */\n  public reconfigure(task: PoolTask): void {\n    this.environment = task.context.environment\n    this._otel?.span.setAttribute('vitest.environment', this.environment.name)\n  }\n\n  postMessage(message: WorkerRequest): void {\n    // Only send messages when runner is active (not fully stopped)\n    // Allow sending during STOPPING state for the 'stop' message itself\n    if (this._state !== RunnerState.STOPPED) {\n      return this.worker.send(message)\n    }\n  }\n\n  startTracesSpan(name: string): Span {\n    const traces = this._traces\n    if (!this._otel) {\n      return traces.startSpan(name)\n    }\n    const { span, context } = traces.startContextSpan(name, this._otel.workerContext)\n    this._otel.currentContext = context\n    const end = span.end.bind(span)\n    span.end = (endTime?: TimeInput) => {\n      this._otel!.currentContext = undefined\n      return end(endTime)\n    }\n    return span\n  }\n\n  request(method: 'run' | 'collect', context: WorkerExecuteContext): void {\n    this._otel?.files.push(...context.files.map(f => f.filepath))\n    return this.postMessage({\n      __vitest_worker_request__: true,\n      type: method,\n      context,\n      otelCarrier: this.getOTELCarrier(),\n    } satisfies WorkerRequest)\n  }\n\n  private getOTELCarrier() {\n    const activeContext = this._otel?.currentContext || this._otel?.workerContext\n    return activeContext\n      ? this._traces.getContextCarrier(activeContext)\n      : undefined\n  }\n\n  async start(options: { workerId: number }): Promise<void> {\n    // Wait for any ongoing operation to complete\n    if (this._operationLock) {\n      await this._operationLock\n    }\n\n    if (this._state === RunnerState.STARTED || this._state === RunnerState.STARTING) {\n      return\n    }\n\n    if (this._state === RunnerState.STOPPED) {\n      throw new Error('[vitest-pool-runner]: Cannot start a stopped runner')\n    }\n\n    // Create operation lock to prevent concurrent start/stop\n    this._operationLock = createDefer()\n\n    let startSpan: Span | undefined\n    try {\n      this._state = RunnerState.STARTING\n\n      await this._traces.$(\n        `vitest.${this.worker.name}.start`,\n        { context: this._otel?.workerContext },\n        () => this.worker.start(),\n      )\n\n      // Attach event listeners AFTER starting worker to avoid issues\n      // if worker.start() fails\n      this.worker.on('error', this.emitWorkerError)\n      this.worker.on('exit', this.emitUnexpectedExit)\n      this.worker.on('message', this.emitWorkerMessage)\n\n      startSpan = this.startTracesSpan('vitest.worker.start')\n      const startPromise = this.withTimeout(this.waitForStart(), START_TIMEOUT)\n      const globalConfig = this.project.vitest.config.experimental.openTelemetry\n      const projectConfig = this.project.config.experimental.openTelemetry\n\n      const tracesEnabled = projectConfig?.enabled ?? globalConfig?.enabled === true\n      const tracesSdk = projectConfig?.sdkPath ?? globalConfig?.sdkPath\n\n      this.postMessage({\n        type: 'start',\n        poolId: this.poolId!,\n        workerId: options.workerId,\n        __vitest_worker_request__: true,\n        options: {\n          reportMemory: this.worker.reportMemory ?? false,\n        },\n        context: {\n          environment: {\n            name: this.environment.name,\n            options: this.environment.options,\n          },\n          config: this.project.serializedConfig,\n          pool: this.worker.name,\n        },\n        traces: {\n          enabled: tracesEnabled,\n          sdkPath: tracesSdk,\n          otelCarrier: this.getOTELCarrier(),\n        },\n      })\n\n      await startPromise\n\n      this._state = RunnerState.STARTED\n    }\n    catch (error: any) {\n      this._state = RunnerState.START_FAILURE\n      startSpan?.recordException(error)\n      throw error\n    }\n    finally {\n      startSpan?.end()\n      this._operationLock.resolve()\n      this._operationLock = null\n    }\n  }\n\n  async stop(options?: StopOptions): Promise<void> {\n    // Wait for any ongoing operation to complete\n    if (this._operationLock) {\n      await this._operationLock\n    }\n\n    if (this._state === RunnerState.STOPPED || this._state === RunnerState.STOPPING) {\n      return\n    }\n\n    this._otel?.span.setAttribute('vitest.worker.files', this._otel.files)\n\n    if (this._state === RunnerState.IDLE) {\n      this._otel?.span.end()\n      this._state = RunnerState.STOPPED\n      return\n    }\n\n    // Create operation lock to prevent concurrent start/stop\n    this._operationLock = createDefer()\n\n    try {\n      this._state = RunnerState.STOPPING\n\n      // Remove exit listener early to avoid \"unexpected exit\" errors during shutdown\n      this.worker.off('exit', this.emitUnexpectedExit)\n\n      const stopSpan = this.startTracesSpan('vitest.worker.stop')\n      await this.withTimeout(\n        new Promise<void>((resolve) => {\n          const onStop = (response: WorkerResponse) => {\n            if (response.type === 'stopped') {\n              if (response.error) {\n                stopSpan.recordException(response.error as Error)\n                this.project.vitest.state.catchError(\n                  response.error,\n                  'Teardown Error',\n                )\n              }\n\n              resolve()\n              this.off('message', onStop)\n            }\n          }\n\n          // Don't wait for graceful exit's response when force exiting\n          if (options?.force) {\n            return onStop({ type: 'stopped', __vitest_worker_response__: true })\n          }\n\n          this.on('message', onStop)\n          this.postMessage({\n            type: 'stop',\n            __vitest_worker_request__: true,\n            otelCarrier: this.getOTELCarrier(),\n          })\n        }),\n        STOP_TIMEOUT,\n      ).finally(() => {\n        stopSpan.end()\n      })\n\n      this._eventEmitter.removeAllListeners()\n      this._offCancel()\n      this._rpc.$close(new Error('[vitest-pool-runner]: Pending methods while closing rpc'))\n\n      // Stop the worker process (this sets _fork/_thread to undefined)\n      // Worker's event listeners (error, message) are implicitly removed when worker terminates\n      await this._traces.$(\n        `vitest.${this.worker.name}.stop`,\n        { context: this._otel?.workerContext },\n        () => this.worker.stop(),\n      )\n\n      this._state = RunnerState.STOPPED\n    }\n    catch (error) {\n      // Ensure we transition to stopped state even on error\n      this._state = RunnerState.STOPPED\n      throw error\n    }\n    finally {\n      this._operationLock.resolve()\n      this._operationLock = null\n      this._otel?.span.end()\n      this._terminatePromise.resolve()\n    }\n  }\n\n  on(event: 'message', callback: (message: WorkerResponse) => void): void\n  on(event: 'error', callback: (error: Error) => void): void\n  on(event: 'message' | 'error', callback: (arg: any) => void): void {\n    this._eventEmitter.on(event, callback)\n  }\n\n  off(event: 'message', callback: (message: WorkerResponse) => void): void\n  off(event: 'error', callback: (error: Error) => void): void\n  off(event: 'message' | 'error', callback: (arg: any) => void): void {\n    this._eventEmitter.off(event, callback)\n  }\n\n  private emitWorkerError = (maybeError: unknown): void => {\n    const error = maybeError instanceof Error ? maybeError : new Error(String(maybeError))\n\n    this._eventEmitter.emit('error', error)\n  }\n\n  private emitWorkerMessage = (response: WorkerResponse | { m: string; __vitest_worker_response__: false }): void => {\n    try {\n      const message = this.worker.deserialize(response) as WorkerResponse\n\n      if (typeof message === 'object' && message != null && message.__vitest_worker_response__) {\n        this._eventEmitter.emit('message', message)\n      }\n      else {\n        this._eventEmitter.emit('rpc', message)\n      }\n    }\n    catch (error) {\n      this._eventEmitter.emit('error', error as Error)\n    }\n  }\n\n  private emitUnexpectedExit = (): void => {\n    const error = new Error('Worker exited unexpectedly')\n\n    this._eventEmitter.emit('error', error)\n  }\n\n  private waitForStart() {\n    return new Promise<void>((resolve, reject) => {\n      const onStart = (message: WorkerResponse) => {\n        if (message.type === 'started') {\n          this.off('message', onStart)\n          if (message.error) {\n            reject(message.error)\n          }\n          else {\n            resolve()\n          }\n        }\n      }\n\n      this.on('message', onStart)\n    })\n  }\n\n  private withTimeout(promise: Promise<unknown>, timeout: number) {\n    return new Promise<unknown>((resolve_, reject_) => {\n      const timer = setTimeout(\n        () => reject(new Error('[vitest-pool-runner]: Timeout waiting for worker to respond')),\n        timeout,\n      )\n\n      function resolve(value: unknown) {\n        clearTimeout(timer)\n        resolve_(value)\n      }\n      function reject(error: Error) {\n        clearTimeout(timer)\n        reject_(error)\n      }\n\n      promise.then(resolve, reject)\n    })\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pools/rpc.ts",
    "content": "import type { RuntimeRPC } from '../../types/rpc'\nimport type { TestProject } from '../project'\nimport type { ResolveSnapshotPathHandlerContext } from '../types/config'\nimport { existsSync, mkdirSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { cleanUrl } from '@vitest/utils/helpers'\nimport { isBuiltin, toBuiltin } from '../../utils/modules'\nimport { handleRollupError } from '../environments/fetchModule'\nimport { normalizeResolvedIdToUrl } from '../environments/normalizeUrl'\n\ninterface MethodsOptions {\n  cacheFs?: boolean\n  // do not report files\n  collect?: boolean\n}\n\nexport function createMethodsRPC(project: TestProject, methodsOptions: MethodsOptions = {}): RuntimeRPC {\n  const vitest = project.vitest\n  const cacheFs = methodsOptions.cacheFs ?? false\n  project.vitest.state.metadata[project.name] ??= {\n    externalized: {},\n    duration: {},\n    tmps: {},\n  }\n  if (project.config.dumpDir && !existsSync(project.config.dumpDir)) {\n    mkdirSync(project.config.dumpDir, { recursive: true })\n  }\n  project.vitest.state.metadata[project.name].dumpDir = project.config.dumpDir\n  return {\n    async fetch(\n      url,\n      importer,\n      environmentName,\n      options,\n      otelCarrier,\n    ) {\n      const environment = project.vite.environments[environmentName]\n      if (!environment) {\n        throw new Error(`The environment ${environmentName} was not defined in the Vite config.`)\n      }\n\n      const start = performance.now()\n\n      return await project._fetcher(url, importer, environment, cacheFs, options, otelCarrier).then((result) => {\n        const duration = performance.now() - start\n        project.vitest.state.transformTime += duration\n        const metadata = project.vitest.state.metadata[project.name]\n        if ('externalize' in result) {\n          metadata.externalized[url] = result.externalize\n        }\n        if ('tmp' in result) {\n          metadata.tmps[url] = result.tmp\n        }\n        metadata.duration[url] ??= []\n        metadata.duration[url].push(duration)\n        return result\n      })\n    },\n    async resolve(id, importer, environmentName) {\n      const environment = project.vite.environments[environmentName]\n      if (!environment) {\n        throw new Error(`The environment ${environmentName} was not defined in the Vite config.`)\n      }\n      const resolved = await environment.pluginContainer.resolveId(id, importer)\n      if (!resolved) {\n        return null\n      }\n      const file = cleanUrl(resolved.id)\n      if (resolved.external) {\n        return {\n          file,\n          // this is only used by the module mocker and it always\n          // standardizes the id to mock \"node:url\" and \"url\" at the same time\n          url: isBuiltin(resolved.id)\n            ? toBuiltin(resolved.id)\n            : resolved.id,\n          id: resolved.id,\n        }\n      }\n      return {\n        file: cleanUrl(resolved.id),\n        url: normalizeResolvedIdToUrl(environment, resolved.id),\n        id: resolved.id,\n      }\n    },\n\n    snapshotSaved(snapshot) {\n      vitest.snapshot.add(snapshot)\n    },\n    resolveSnapshotPath(testPath: string) {\n      return vitest.snapshot.resolvePath<ResolveSnapshotPathHandlerContext>(testPath, {\n        config: project.serializedConfig,\n      })\n    },\n    async transform(id) {\n      const environment = project.vite.environments.__vitest_vm__\n      if (!environment) {\n        throw new Error(`The VM environment was not defined in the Vite config. This is a bug in Vitest. Please, open a new issue with reproduction.`)\n      }\n\n      const url = normalizeResolvedIdToUrl(environment, fileURLToPath(id))\n      const result = await environment.transformRequest(url).catch(handleRollupError)\n      return { code: result?.code }\n    },\n    async onQueued(file) {\n      if (methodsOptions.collect) {\n        vitest.state.collectFiles(project, [file])\n      }\n      else {\n        await vitest._testRun.enqueued(project, file)\n      }\n    },\n    async onCollected(files) {\n      if (methodsOptions.collect) {\n        vitest.state.collectFiles(project, files)\n      }\n      else {\n        await vitest._testRun.collected(project, files)\n      }\n    },\n    onAfterSuiteRun(meta) {\n      vitest.coverageProvider?.onAfterSuiteRun(meta)\n    },\n    async onTaskArtifactRecord(testId, artifact) {\n      return vitest._testRun.recordArtifact(testId, artifact)\n    },\n    async onTaskUpdate(packs, events) {\n      if (methodsOptions.collect) {\n        vitest.state.updateTasks(packs)\n      }\n      else {\n        await vitest._testRun.updated(packs, events)\n      }\n    },\n    async onUserConsoleLog(log) {\n      if (methodsOptions.collect) {\n        vitest.state.updateUserLog(log)\n      }\n      else {\n        await vitest._testRun.log(log)\n      }\n    },\n    onUnhandledError(err, type) {\n      vitest.state.catchError(err, type)\n    },\n    onAsyncLeaks(leaks) {\n      vitest.state.catchLeaks(leaks)\n    },\n    onCancel(reason) {\n      vitest.cancelCurrentRun(reason)\n    },\n    getCountOfFailedTests() {\n      return vitest.state.getCountOfFailedTests()\n    },\n\n    ensureModuleGraphEntry(id, importer) {\n      const filepath = id.startsWith('file:') ? fileURLToPath(id) : id\n      const importerPath = importer.startsWith('file:') ? fileURLToPath(importer) : importer\n      // environment itself doesn't matter\n      const moduleGraph = project.vite.environments.__vitest__?.moduleGraph\n      if (!moduleGraph) {\n        // TODO: is it possible?\n        console.error('no module graph for', id)\n        return\n      }\n      const importerNode = moduleGraph.getModuleById(importerPath) || moduleGraph.createFileOnlyEntry(importerPath)\n      const moduleNode = moduleGraph.getModuleById(filepath) || moduleGraph.createFileOnlyEntry(filepath)\n\n      if (!moduleGraph.idToModuleMap.has(importerPath)) {\n        importerNode.id = importerPath\n        moduleGraph.idToModuleMap.set(importerPath, importerNode)\n      }\n      if (!moduleGraph.idToModuleMap.has(filepath)) {\n        moduleNode.id = filepath\n        moduleGraph.idToModuleMap.set(filepath, moduleNode)\n      }\n\n      // this is checked by the \"printError\" function - TODO: is there a better way?\n      moduleNode.transformResult = {\n        code: ' ',\n        map: null,\n      }\n      importerNode.importedModules.add(moduleNode)\n      moduleNode.importers.add(importerNode)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pools/types.ts",
    "content": "import type { Context, Span } from '@opentelemetry/api'\nimport type { ContextTestEnvironment, WorkerExecuteContext, WorkerTestEnvironment } from '../../types/worker'\nimport type { OTELCarrier } from '../../utils/traces'\nimport type { TestProject } from '../project'\nimport type { SerializedConfig } from '../types/config'\n\nexport interface PoolRunnerInitializer {\n  readonly name: string\n  createPoolWorker: (options: PoolOptions) => PoolWorker\n}\n\nexport interface PoolOptions {\n  distPath: string\n  project: TestProject\n  method: 'run' | 'collect'\n  cacheFs?: boolean\n  environment: ContextTestEnvironment\n  execArgv: string[]\n  env: Partial<NodeJS.ProcessEnv>\n}\n\nexport interface PoolWorker {\n  readonly name: string\n  readonly reportMemory?: boolean\n  readonly cacheFs?: boolean\n\n  on: (event: string, callback: (arg: any) => void) => void\n  off: (event: string, callback: (arg: any) => void) => void\n  send: (message: WorkerRequest) => void\n  deserialize: (data: unknown) => unknown\n\n  start: () => Promise<void>\n  stop: () => Promise<void>\n\n  /**\n   * This is called on workers that already satisfy certain constraints:\n   * - The task has the same worker name\n   * - The task has the same project\n   */\n  canReuse?: (task: PoolTask) => boolean\n}\n\nexport interface PoolTask {\n  worker: 'forks' | 'threads' | 'vmForks' | 'vmThreads' | (string & {})\n  project: TestProject\n  isolate: boolean\n  /**\n   * Custom `process.env`. All tasks in the same project will reference the same object,\n   * so modifying it once will modify it for every task.\n   */\n  env: Partial<NodeJS.ProcessEnv>\n  /**\n   * Custom `execArgv`. All tasks in the same project will reference the same array,\n   * so modifying it once will modify it for every task.\n   */\n  execArgv: string[]\n  context: WorkerExecuteContext\n  memoryLimit: number | null\n}\n\nexport interface PoolRunnerOTEL {\n  span: Span\n  workerContext: Context\n  currentContext?: Context\n  files: string[]\n}\n\nexport type WorkerRequest\n  = { __vitest_worker_request__: true } & (\n    | {\n      type: 'start'\n      poolId: number\n      workerId: WorkerExecuteContext['workerId'] // Initial worker ID, may change when non-isolated worker runs multiple test files\n      options: { reportMemory: boolean }\n      context: {\n        environment: WorkerTestEnvironment\n        config: SerializedConfig\n        pool: string\n      }\n      traces: {\n        enabled: boolean\n        sdkPath?: string\n        otelCarrier?: OTELCarrier\n      }\n    }\n    | {\n      type: 'stop'\n      otelCarrier?: OTELCarrier\n    }\n    | {\n      type: 'run'\n      context: WorkerExecuteContext\n      otelCarrier?: OTELCarrier\n    }\n    | {\n      type: 'collect'\n      context: WorkerExecuteContext\n      otelCarrier?: OTELCarrier\n    }\n    | { type: 'cancel' }\n)\n\nexport type WorkerResponse\n  = { __vitest_worker_response__: true } & (\n    | { type: 'started'; error?: unknown }\n    | { type: 'stopped'; error?: unknown }\n    | { type: 'testfileFinished'; usedMemory?: number; error?: unknown }\n)\n"
  },
  {
    "path": "packages/vitest/src/node/pools/workers/forksWorker.ts",
    "content": "import type { ChildProcess } from 'node:child_process'\nimport type { Writable } from 'node:stream'\nimport type { PoolOptions, PoolWorker, WorkerRequest } from '../types'\nimport { fork } from 'node:child_process'\nimport { resolve } from 'node:path'\n\nconst SIGKILL_TIMEOUT = 500 /** jest does 500ms by default, let's follow it */\n\n/** @experimental */\nexport class ForksPoolWorker implements PoolWorker {\n  public readonly name: string = 'forks'\n  public readonly cacheFs: boolean = true\n\n  protected readonly entrypoint: string\n  protected execArgv: string[]\n  protected env: Partial<NodeJS.ProcessEnv>\n\n  private _fork?: ChildProcess\n  private stdout: NodeJS.WriteStream | Writable\n  private stderr: NodeJS.WriteStream | Writable\n\n  constructor(options: PoolOptions) {\n    this.execArgv = options.execArgv\n    this.env = options.env\n    this.stdout = options.project.vitest.logger.outputStream\n    this.stderr = options.project.vitest.logger.errorStream\n\n    /** Loads {@link file://./../../../runtime/workers/forks.ts} */\n    this.entrypoint = resolve(options.distPath, 'workers/forks.js')\n  }\n\n  on(event: string, callback: (arg: any) => void): void {\n    this.fork.on(event, callback)\n  }\n\n  off(event: string, callback: (arg: any) => void): void {\n    this.fork.off(event, callback)\n  }\n\n  send(message: WorkerRequest): void {\n    this.fork.send(message)\n  }\n\n  async start(): Promise<void> {\n    this._fork ||= fork(this.entrypoint, [], {\n      env: this.env,\n      execArgv: this.execArgv,\n      stdio: 'pipe',\n      serialization: 'advanced',\n    })\n\n    if (this._fork.stdout) {\n      this.stdout.setMaxListeners(1 + this.stdout.getMaxListeners())\n      this._fork.stdout.pipe(this.stdout)\n    }\n\n    if (this._fork.stderr) {\n      this.stderr.setMaxListeners(1 + this.stderr.getMaxListeners())\n      this._fork.stderr.pipe(this.stderr)\n    }\n  }\n\n  async stop(): Promise<void> {\n    const fork = this.fork\n    const waitForExit = new Promise<void>((resolve) => {\n      if (fork.exitCode != null) {\n        resolve()\n      }\n      else {\n        fork.once('exit', resolve)\n      }\n    })\n\n    /*\n     * If process running user's code does not stop on SIGTERM, send SIGKILL.\n     * This is similar to\n     * - https://github.com/jestjs/jest/blob/25a8785584c9d54a05887001ee7f498d489a5441/packages/jest-worker/src/workers/ChildProcessWorker.ts#L463-L477\n     * - https://github.com/tinylibs/tinypool/blob/40b4b3eb926dabfbfd3d0a7e3d1222d4dd1c0d2d/src/runtime/process-worker.ts#L56\n     */\n    const sigkillTimeout = setTimeout(\n      () => fork.kill('SIGKILL'),\n      SIGKILL_TIMEOUT,\n    )\n\n    fork.kill()\n    await waitForExit\n    clearTimeout(sigkillTimeout)\n\n    if (fork.stdout) {\n      fork.stdout?.unpipe(this.stdout)\n      this.stdout.setMaxListeners(this.stdout.getMaxListeners() - 1)\n    }\n\n    if (fork.stderr) {\n      fork.stderr?.unpipe(this.stderr)\n      this.stderr.setMaxListeners(this.stderr.getMaxListeners() - 1)\n    }\n\n    this._fork = undefined\n  }\n\n  deserialize(data: unknown): unknown {\n    return data\n  }\n\n  private get fork() {\n    if (!this._fork) {\n      throw new Error(`The child process was torn down or never initialized. This is a bug in Vitest.`)\n    }\n    return this._fork\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pools/workers/threadsWorker.ts",
    "content": "import type { Writable } from 'node:stream'\nimport type { PoolOptions, PoolWorker, WorkerRequest } from '../types'\nimport { resolve } from 'node:path'\nimport { Worker } from 'node:worker_threads'\n\n/** @experimental */\nexport class ThreadsPoolWorker implements PoolWorker {\n  public readonly name: string = 'threads'\n\n  protected readonly entrypoint: string\n  protected execArgv: string[]\n  protected env: Partial<NodeJS.ProcessEnv>\n\n  private _thread?: Worker\n  private stdout: NodeJS.WriteStream | Writable\n  private stderr: NodeJS.WriteStream | Writable\n\n  constructor(options: PoolOptions) {\n    this.execArgv = options.execArgv\n    this.env = options.env\n    this.stdout = options.project.vitest.logger.outputStream\n    this.stderr = options.project.vitest.logger.errorStream\n\n    /** Loads {@link file://./../../../runtime/workers/threads.ts} */\n    this.entrypoint = resolve(options.distPath, 'workers/threads.js')\n  }\n\n  on(event: string, callback: (arg: any) => void): void {\n    this.thread.on(event, callback)\n  }\n\n  off(event: string, callback: (arg: any) => void): void {\n    this.thread.off(event, callback)\n  }\n\n  send(message: WorkerRequest): void {\n    this.thread.postMessage(message)\n  }\n\n  async start(): Promise<void> {\n    // This can be called multiple times if the runtime is shared.\n    this._thread ||= new Worker(this.entrypoint, {\n      env: this.env,\n      execArgv: this.execArgv,\n      stdout: true,\n      stderr: true,\n    })\n\n    this.stdout.setMaxListeners(1 + this.stdout.getMaxListeners())\n    this._thread.stdout.pipe(this.stdout)\n\n    this.stderr.setMaxListeners(1 + this.stderr.getMaxListeners())\n    this._thread.stderr.pipe(this.stderr)\n  }\n\n  async stop(): Promise<void> {\n    await this.thread.terminate()\n\n    this._thread?.stdout?.unpipe(this.stdout)\n    this.stdout.setMaxListeners(this.stdout.getMaxListeners() - 1)\n\n    this._thread?.stderr?.unpipe(this.stderr)\n    this.stderr.setMaxListeners(this.stderr.getMaxListeners() - 1)\n\n    this._thread = undefined\n  }\n\n  deserialize(data: unknown): unknown {\n    return data\n  }\n\n  private get thread() {\n    if (!this._thread) {\n      throw new Error(`The worker thread was torn down or never initialized. This is a bug in Vitest.`)\n    }\n    return this._thread\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pools/workers/typecheckWorker.ts",
    "content": "import type { FileSpecification } from '@vitest/runner'\nimport type { DeferPromise } from '@vitest/utils'\nimport type { TypecheckResults } from '../../../typecheck/typechecker'\nimport type { Vitest } from '../../core'\nimport type { TestProject } from '../../project'\nimport type { TestRunEndReason } from '../../types/reporter'\nimport type { PoolOptions, PoolWorker, WorkerRequest, WorkerResponse } from '../types'\nimport EventEmitter from 'node:events'\nimport { hasFailed } from '@vitest/runner/utils'\nimport { createDefer } from '@vitest/utils/helpers'\nimport { Typechecker } from '../../../typecheck/typechecker'\n\n/** @experimental */\nexport class TypecheckPoolWorker implements PoolWorker {\n  public readonly name: string = 'typecheck'\n  private readonly project: TestProject\n\n  private _eventEmitter = new EventEmitter()\n\n  constructor(options: PoolOptions) {\n    this.project = options.project\n  }\n\n  async start(): Promise<void> {\n    // noop, onMessage handles it\n  }\n\n  async stop(): Promise<void> {\n    // noop, onMessage handles it\n  }\n\n  canReuse(): boolean {\n    return true\n  }\n\n  send(message: WorkerRequest): void {\n    void onMessage(message, this.project).then((response) => {\n      if (response) {\n        this._eventEmitter.emit('message', response)\n      }\n    })\n  }\n\n  on(event: string, callback: (arg: any) => any): void {\n    this._eventEmitter.on(event, callback)\n  }\n\n  off(event: string, callback: (arg: any) => any): void {\n    this._eventEmitter.on(event, callback)\n  }\n\n  deserialize(data: unknown): unknown {\n    return data\n  }\n}\n\nconst __vitest_worker_response__ = true\nconst runners = new WeakMap<Vitest, ReturnType<typeof createRunner>>()\n\nasync function onMessage(message: WorkerRequest, project: TestProject): Promise<WorkerResponse | void> {\n  if (message?.__vitest_worker_request__ !== true) {\n    return undefined\n  }\n\n  let runner = runners.get(project.vitest)\n  if (!runner) {\n    runner = createRunner(project.vitest)\n    runners.set(project.vitest, runner)\n  }\n\n  let runPromise: Promise<unknown> | undefined\n\n  switch (message.type) {\n    case 'start': {\n      return { type: 'started', __vitest_worker_response__ }\n    }\n\n    case 'run': {\n      runPromise = runner.runTests(message.context.files, project)\n        .catch(error => error)\n      const error = await runPromise\n\n      return { type: 'testfileFinished', error, __vitest_worker_response__ }\n    }\n\n    case 'collect': {\n      runPromise = runner.collectTests(message.context.files, project)\n        .catch(error => error)\n      const error = await runPromise\n\n      return { type: 'testfileFinished', error, __vitest_worker_response__ }\n    }\n\n    case 'stop': {\n      await runPromise\n      return { type: 'stopped', __vitest_worker_response__ }\n    }\n  }\n\n  throw new Error(`Unexpected message ${JSON.stringify(message, null, 2)}`)\n}\n\nfunction createRunner(vitest: Vitest) {\n  const promisesMap = new WeakMap<TestProject, DeferPromise<void>>()\n  const rerunTriggered = new WeakSet<TestProject>()\n\n  async function onParseEnd(\n    project: TestProject,\n    { files, sourceErrors }: TypecheckResults,\n  ) {\n    const checker = project.typechecker!\n\n    const { packs, events } = checker.getTestPacksAndEvents()\n    await vitest._testRun.updated(packs, events)\n\n    if (!project.config.typecheck.ignoreSourceErrors) {\n      sourceErrors.forEach(error =>\n        vitest.state.catchError(error, 'Unhandled Source Error'),\n      )\n    }\n\n    const processError = !hasFailed(files) && !sourceErrors.length && checker.getExitCode()\n    if (processError) {\n      const error = new Error(checker.getOutput())\n      error.stack = ''\n      vitest.state.catchError(error, 'Typecheck Error')\n    }\n\n    promisesMap.get(project)?.resolve()\n\n    rerunTriggered.delete(project)\n\n    // triggered by TSC watcher, not Vitest watcher, so we need to emulate what Vitest does in this case\n    if (vitest.config.watch && !vitest.runningPromise) {\n      const modules = files.map(file => vitest.state.getReportedEntity(file)).filter(e => e?.type === 'module')\n\n      const state: TestRunEndReason = vitest.isCancelling\n        ? 'interrupted'\n        : modules.some(m => !m.ok())\n          ? 'failed'\n          : 'passed'\n\n      await vitest.report('onTestRunEnd', modules, [], state)\n      await vitest.report('onWatcherStart', files, [\n        ...(project.config.typecheck.ignoreSourceErrors ? [] : sourceErrors),\n        ...vitest.state.getUnhandledErrors(),\n      ])\n    }\n  }\n\n  async function createWorkspaceTypechecker(\n    project: TestProject,\n    files: string[],\n  ) {\n    const checker = project.typechecker ?? new Typechecker(project)\n    if (project.typechecker) {\n      return checker\n    }\n\n    project.typechecker = checker\n    checker.setFiles(files)\n\n    checker.onParseStart(async () => {\n      const files = checker.getTestFiles()\n      for (const file of files) {\n        await vitest._testRun.enqueued(project, file)\n      }\n      await vitest._testRun.collected(project, files)\n    })\n\n    checker.onParseEnd(result => onParseEnd(project, result))\n\n    checker.onWatcherRerun(async () => {\n      rerunTriggered.add(project)\n\n      if (!vitest.runningPromise) {\n        vitest.state.clearErrors()\n        await vitest.report(\n          'onWatcherRerun',\n          files,\n          'File change detected. Triggering rerun.',\n        )\n      }\n\n      await checker.collectTests()\n\n      const testFiles = checker.getTestFiles()\n      for (const file of testFiles) {\n        await vitest._testRun.enqueued(project, file)\n      }\n      await vitest._testRun.collected(project, testFiles)\n\n      const { packs, events } = checker.getTestPacksAndEvents()\n      await vitest._testRun.updated(packs, events)\n    })\n\n    return checker\n  }\n\n  async function startTypechecker(project: TestProject, files: string[]) {\n    if (project.typechecker) {\n      return\n    }\n    const checker = await createWorkspaceTypechecker(project, files)\n    await checker.collectTests()\n    await checker.start()\n  }\n\n  async function collectTests(specs: FileSpecification[], project: TestProject) {\n    const files = specs.map(spec => spec.filepath)\n    const checker = await createWorkspaceTypechecker(project, files)\n    checker.setFiles(files)\n    await checker.collectTests()\n    const testFiles = checker.getTestFiles()\n    vitest.state.collectFiles(project, testFiles)\n  }\n\n  async function runTests(specs: FileSpecification[], project: TestProject) {\n    const promises: Promise<void>[] = []\n\n    const files = specs.map(spec => spec.filepath)\n    const promise = createDefer<void>()\n\n    // check that watcher actually triggered rerun\n    const triggered = await new Promise<boolean>((resolve) => {\n      const _i = setInterval(() => {\n        if (!project.typechecker || rerunTriggered.has(project)) {\n          resolve(true)\n          clearInterval(_i)\n        }\n      })\n      setTimeout(() => {\n        resolve(false)\n        clearInterval(_i)\n      }, 500).unref()\n    })\n\n    // Re-run but wasn't triggered by tsc\n    if (promisesMap.has(project) && !triggered) {\n      return promisesMap.get(project)\n    }\n\n    if (project.typechecker && !triggered) {\n      const testFiles = project.typechecker.getTestFiles()\n\n      for (const file of testFiles) {\n        await vitest._testRun.enqueued(project, file)\n      }\n\n      await vitest._testRun.collected(project, testFiles)\n      await onParseEnd(project, project.typechecker.getResult())\n    }\n\n    promises.push(promise)\n    promisesMap.set(project, promise)\n    promises.push(startTypechecker(project, files))\n\n    await Promise.all(promises)\n  }\n\n  return {\n    runTests,\n    collectTests,\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pools/workers/vmForksWorker.ts",
    "content": "import type { PoolOptions } from '../types'\nimport { resolve } from 'node:path'\nimport { ForksPoolWorker } from './forksWorker'\n\n/** @experimental */\nexport class VmForksPoolWorker extends ForksPoolWorker {\n  public readonly name = 'vmForks'\n  public readonly reportMemory = true\n  protected readonly entrypoint: string\n\n  constructor(options: PoolOptions) {\n    super({ ...options, execArgv: [...options.execArgv, '--experimental-vm-modules'] })\n\n    /** Loads {@link file://./../../../runtime/workers/vmForks.ts} */\n    this.entrypoint = resolve(options.distPath, 'workers/vmForks.js')\n  }\n\n  canReuse(): boolean {\n    return true\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/pools/workers/vmThreadsWorker.ts",
    "content": "import type { PoolOptions } from '../types'\nimport { resolve } from 'node:path'\nimport { ThreadsPoolWorker } from './threadsWorker'\n\n/** @experimental */\nexport class VmThreadsPoolWorker extends ThreadsPoolWorker {\n  public readonly name = 'vmThreads'\n  public readonly reportMemory = true\n  protected readonly entrypoint: string\n\n  constructor(options: PoolOptions) {\n    super({ ...options, execArgv: [...options.execArgv, '--experimental-vm-modules'] })\n\n    /** Loads {@link file://./../../../runtime/workers/vmThreads.ts} */\n    this.entrypoint = resolve(options.distPath, 'workers/vmThreads.js')\n  }\n\n  canReuse(): boolean {\n    return true\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/printError.ts",
    "content": "/* eslint-disable prefer-template */\nimport type { ParsedStack, TestError } from '@vitest/utils'\nimport type { Vitest } from './core'\nimport type { ErrorOptions, Logger } from './logger'\nimport type { TestProject } from './project'\nimport { Console } from 'node:console'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { Writable } from 'node:stream'\nimport { stripVTControlCharacters } from 'node:util'\nimport { inspect } from '@vitest/utils/display'\nimport { isPrimitive } from '@vitest/utils/helpers'\nimport { normalize, relative } from 'pathe'\nimport c from 'tinyrainbow'\nimport { TypeCheckError } from '../typecheck/typechecker'\nimport {\n  defaultStackIgnorePatterns,\n  lineSplitRE,\n  parseErrorStacktrace,\n  positionToOffset,\n} from '../utils/source-map'\nimport { F_POINTER } from './reporters/renderers/figures'\nimport { divider, errorBanner, truncateString } from './reporters/renderers/utils'\n\ntype ErrorLogger = Pick<Logger, 'error' | 'highlight'>\n\ninterface PrintErrorOptions {\n  logger: ErrorLogger\n  type?: string\n  showCodeFrame?: boolean\n  printProperties?: boolean\n  screenshotPaths?: string[]\n  parseErrorStacktrace: (error: TestError) => ParsedStack[]\n}\n\ninterface PrintErrorResult {\n  nearest?: ParsedStack\n}\n\n// use Logger with custom Console to capture entire error printing\nexport function capturePrintError(\n  error: unknown,\n  ctx: Vitest,\n  options: ErrorOptions,\n): { nearest: ParsedStack | undefined; output: string } {\n  let output = ''\n  const writable = new Writable({\n    write(chunk, _encoding, callback) {\n      output += String(chunk)\n      callback()\n    },\n  })\n  const console = new Console(writable)\n  const logger: ErrorLogger = {\n    error: console.error.bind(console),\n    highlight: ctx.logger.highlight.bind(ctx.logger),\n  }\n  const result = printError(error, ctx, logger, {\n    showCodeFrame: false,\n    ...options,\n  })\n  return { nearest: result?.nearest, output }\n}\n\nexport function printError(\n  error: unknown,\n  ctx: Vitest,\n  logger: ErrorLogger,\n  options: ErrorOptions,\n): PrintErrorResult | undefined {\n  const project = options.project\n    ?? ctx.coreWorkspaceProject\n    ?? ctx.projects[0]\n  return printErrorInner(error, project, {\n    logger,\n    type: options.type,\n    showCodeFrame: options.showCodeFrame,\n    screenshotPaths: options.screenshotPaths,\n    printProperties: options.verbose,\n    parseErrorStacktrace(error) {\n      if (error.stacks) {\n        if (options.fullStack) {\n          return error.stacks\n        }\n        else {\n          return error.stacks.filter((stack) => {\n            return !defaultStackIgnorePatterns.some(p => stack.file.match(p))\n          })\n        }\n      }\n\n      // browser stack trace needs to be processed differently,\n      // so there is a separate method for that\n      if (options.task?.file.pool === 'browser' && project.browser) {\n        return project.browser.parseErrorStacktrace(error, {\n          frameFilter: project.config.onStackTrace,\n          ignoreStackEntries: options.fullStack ? [] : undefined,\n        })\n      }\n\n      // node.js stack trace already has correct source map locations\n      return parseErrorStacktrace(error, {\n        frameFilter: project.config.onStackTrace,\n        ignoreStackEntries: options.fullStack ? [] : undefined,\n      })\n    },\n  })\n}\n\nfunction printErrorInner(\n  error: unknown,\n  project: TestProject | undefined,\n  options: PrintErrorOptions,\n): PrintErrorResult | undefined {\n  const { showCodeFrame = true, type, printProperties = true } = options\n  const logger = options.logger\n  let e = error as TestError\n\n  if (isPrimitive(e)) {\n    e = {\n      message: String(error).split(/\\n/g)[0],\n      stack: String(error),\n    } as any\n  }\n\n  if (!e) {\n    const error = new Error('unknown error')\n    e = {\n      message: e ?? error.message,\n      stack: error.stack,\n    } as any\n  }\n\n  // Error may have occurred even before the configuration was resolved\n  if (!project) {\n    printErrorMessage(e, logger)\n    return\n  }\n\n  const stacks = options.parseErrorStacktrace(e)\n\n  const nearest\n    = error instanceof TypeCheckError\n      ? error.stacks[0]\n      : stacks.find((stack) => {\n          // we are checking that this module was processed by us at one point\n          try {\n            const environments = [\n              ...Object.values(project._vite?.environments || {}),\n              ...Object.values(project.browser?.vite.environments || {}),\n            ]\n            const hasResult = environments.some((environment) => {\n              const modules = environment.moduleGraph.getModulesByFile(stack.file)\n              return [...modules?.values() || []].some(module => !!module.transformResult)\n            })\n            return hasResult && existsSync(stack.file)\n          }\n          catch {\n            return false\n          }\n        })\n\n  if (type) {\n    printErrorType(type, project.vitest)\n  }\n  printErrorMessage(e, logger)\n  if (options.screenshotPaths?.length) {\n    const uniqueScreenshots = Array.from(new Set(options.screenshotPaths))\n    const length = uniqueScreenshots.length\n    logger.error(`\\nFailure screenshot${length > 1 ? 's' : ''}:`)\n    logger.error(uniqueScreenshots.map(p => `  - ${c.dim(relative(process.cwd(), p))}`).join('\\n'))\n    if (!e.diff) {\n      logger.error()\n    }\n  }\n\n  if (e.codeFrame) {\n    logger.error(`${e.codeFrame}\\n`)\n  }\n\n  if ('__vitest_rollup_error__' in e) {\n    // https://github.com/vitejs/vite/blob/95020ab49e12d143262859e095025cf02423c1d9/packages/vite/src/node/server/middlewares/error.ts#L25-L36\n    const err = e.__vitest_rollup_error__ as any\n    logger.error([\n      err.plugin && `  Plugin: ${c.magenta(err.plugin)}`,\n      err.id && `  File: ${c.cyan(err.id)}${err.loc ? `:${err.loc.line}:${err.loc.column}` : ''}`,\n      err.frame && c.yellow((err.frame as string).split(/\\r?\\n/g).map(l => ` `.repeat(2) + l).join(`\\n`)),\n    ].filter(Boolean).join('\\n'))\n  }\n\n  // E.g. AssertionError from assert does not set showDiff but has both actual and expected properties\n  if (e.diff) {\n    logger.error(`\\n${e.diff}\\n`)\n  }\n\n  // if the error provide the frame\n  if (e.frame) {\n    logger.error(c.yellow(e.frame))\n  }\n  else {\n    const errorProperties = printProperties\n      ? getErrorProperties(e)\n      : {}\n\n    printStack(logger, project, stacks, nearest, errorProperties, (s) => {\n      if (showCodeFrame && s === nearest && nearest) {\n        const sourceCode = readFileSync(nearest.file, 'utf-8')\n        logger.error(\n          generateCodeFrame(\n            sourceCode.length > 100_000\n              ? sourceCode\n              : logger.highlight(nearest.file, sourceCode),\n            4,\n            s,\n          ),\n        )\n      }\n    })\n  }\n\n  const testPath = (e as any).VITEST_TEST_PATH\n  const testName = (e as any).VITEST_TEST_NAME\n  // testName has testPath inside\n  if (testPath) {\n    logger.error(\n      c.red(\n        `This error originated in \"${c.bold(\n          relative(project.config.root, testPath),\n        )}\" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.`,\n      ),\n    )\n  }\n  if (testName) {\n    logger.error(\n      c.red(\n        `The latest test that might've caused the error is \"${c.bold(\n          testName,\n        )}\". It might mean one of the following:`\n        + '\\n- The error was thrown, while Vitest was running this test.'\n        + '\\n- If the error occurred after the test had been completed, this was the last documented test before it was thrown.',\n      ),\n    )\n  }\n\n  if (typeof e.cause === 'object' && e.cause && 'name' in e.cause) {\n    (e.cause as any).name = `Caused by: ${(e.cause as any).name}`\n    printErrorInner(e.cause, project, {\n      showCodeFrame: false,\n      logger: options.logger,\n      parseErrorStacktrace: options.parseErrorStacktrace,\n    })\n  }\n\n  handleImportOutsideModuleError(e.stack || '', logger)\n\n  return { nearest }\n}\n\nfunction printErrorType(type: string, ctx: Vitest) {\n  ctx.logger.error(`\\n${errorBanner(type)}`)\n}\n\nconst skipErrorProperties = new Set([\n  'cause',\n  'stacks',\n  'type',\n  'showDiff',\n  'ok',\n  'operator',\n  'diff',\n  'codeFrame',\n  'actual',\n  'expected',\n  'diffOptions',\n  'runnerError',\n  // webkit props\n  'sourceURL',\n  'column',\n  'line',\n  // firefox props\n  'fileName',\n  'lineNumber',\n  'columnNumber',\n  'VITEST_TEST_NAME',\n  'VITEST_TEST_PATH',\n  '__vitest_rollup_error__',\n  ...Object.getOwnPropertyNames(Error.prototype),\n  ...Object.getOwnPropertyNames(Object.prototype),\n])\n\nfunction getErrorProperties(e: TestError) {\n  const errorObject = Object.create(null)\n  if (e.name === 'AssertionError') {\n    return errorObject\n  }\n\n  for (const key of Object.getOwnPropertyNames(e)) {\n    // print the original stack if it was ever changed manually by the user\n    if (key === 'stack' && e[key] != null && typeof e[key] !== 'string') {\n      errorObject[key] = e[key]\n    }\n    else if (key !== 'stack' && !skipErrorProperties.has(key)) {\n      errorObject[key] = e[key as keyof TestError]\n    }\n  }\n\n  return errorObject\n}\n\nconst esmErrors = [\n  'Cannot use import statement outside a module',\n  'Unexpected token \\'export\\'',\n]\n\nfunction handleImportOutsideModuleError(stack: string, logger: ErrorLogger) {\n  if (!esmErrors.some(e => stack.includes(e))) {\n    return\n  }\n\n  const path = normalize(stack.split('\\n')[0].trim())\n  let name = path.split('/node_modules/').pop() || ''\n  if (name[0] === '@') {\n    name = name.split('/').slice(0, 2).join('/')\n  }\n  else {\n    name = name.split('/')[0]\n  }\n\n  if (name) {\n    printModuleWarningForPackage(logger, path, name)\n  }\n  else {\n    printModuleWarningForSourceCode(logger, path)\n  }\n}\n\nfunction printModuleWarningForPackage(\n  logger: ErrorLogger,\n  path: string,\n  name: string,\n) {\n  logger.error(\n    c.yellow(\n      `Module ${path} seems to be an ES Module but shipped in a CommonJS package. `\n      + `You might want to create an issue to the package ${c.bold(\n        `\"${name}\"`,\n      )} asking `\n      + 'them to ship the file in .mjs extension or add \"type\": \"module\" in their package.json.'\n      + '\\n\\n'\n      + 'As a temporary workaround you can try to inline the package by updating your config:'\n      + '\\n\\n'\n      + c.gray(c.dim('// vitest.config.js'))\n      + '\\n'\n      + c.green(`export default {\n  test: {\n    server: {\n      deps: {\n        inline: [\n          ${c.yellow(c.bold(`\"${name}\"`))}\n        ]\n      }\n    }\n  }\n}\\n`),\n    ),\n  )\n}\n\nfunction printModuleWarningForSourceCode(logger: ErrorLogger, path: string) {\n  logger.error(\n    c.yellow(\n      `Module ${path} seems to be an ES Module but shipped in a CommonJS package. `\n      + 'To fix this issue, change the file extension to .mjs or add \"type\": \"module\" in your package.json.',\n    ),\n  )\n}\n\nfunction printErrorMessage(error: TestError, logger: ErrorLogger) {\n  const errorName = error.name || 'Unknown Error'\n  if (!error.message) {\n    logger.error(error)\n    return\n  }\n  if (error.message.length > 5000) {\n    // Protect against infinite stack trace in tinyrainbow\n    logger.error(`${c.red(c.bold(errorName))}: ${error.message}`)\n  }\n  else {\n    logger.error(c.red(`${c.bold(errorName)}: ${error.message}`))\n  }\n}\n\nexport function printStack(\n  logger: ErrorLogger,\n  project: TestProject,\n  stack: ParsedStack[],\n  highlight: ParsedStack | undefined,\n  errorProperties: Record<string, unknown>,\n  onStack?: (stack: ParsedStack) => void,\n): void {\n  for (const frame of stack) {\n    const color = frame === highlight ? c.cyan : c.gray\n    const path = relative(project.config.root, frame.file)\n\n    logger.error(\n      color(\n        ` ${c.dim(F_POINTER)} ${[\n          frame.method,\n          `${path}:${c.dim(`${frame.line}:${frame.column}`)}`,\n        ]\n          .filter(Boolean)\n          .join(' ')}`,\n      ),\n    )\n    onStack?.(frame)\n  }\n  if (stack.length) {\n    logger.error()\n  }\n  if (hasProperties(errorProperties)) {\n    logger.error(c.red(c.dim(divider())))\n    const propertiesString = inspect(errorProperties)\n    logger.error(c.red(c.bold('Serialized Error:')), c.gray(propertiesString))\n  }\n}\n\nfunction hasProperties(obj: any) {\n  // eslint-disable-next-line no-unreachable-loop\n  for (const _key in obj) {\n    return true\n  }\n  return false\n}\n\nexport function generateCodeFrame(\n  source: string,\n  indent = 0,\n  loc: { line: number; column: number } | number,\n  range = 2,\n): string {\n  const start\n    = typeof loc === 'object'\n      ? positionToOffset(source, loc.line, loc.column)\n      : loc\n  const end = start\n  const lines = source.split(lineSplitRE)\n  const nl = /\\r\\n/.test(source) ? 2 : 1\n  let count = 0\n  let res: string[] = []\n\n  const columns = process.stdout?.columns || 80\n\n  for (let i = 0; i < lines.length; i++) {\n    count += lines[i].length + nl\n    if (count >= start) {\n      for (let j = i - range; j <= i + range || end > count; j++) {\n        if (j < 0 || j >= lines.length) {\n          continue\n        }\n\n        const lineLength = lines[j].length\n        const strippedContent = stripVTControlCharacters(lines[j])\n\n        if (strippedContent.startsWith('//# sourceMappingURL')) {\n          continue\n        }\n\n        // too long, maybe it's a minified file, skip for codeframe\n        if (strippedContent.length > 200) {\n          return ''\n        }\n\n        const truncatedLine = truncateString(lines[j].replace(/\\t/g, ' '), columns - 5 - indent).trimEnd()\n        res.push(lineNo(j + 1) + (truncatedLine ? ' ' + truncatedLine : truncatedLine))\n\n        if (j === i) {\n          // push underline\n          const pad = start - (count - lineLength) + (nl - 1)\n          const length = Math.max(\n            1,\n            end > count ? lineLength - pad : end - start,\n          )\n          res.push(lineNo() + ' '.repeat(pad + 1) + c.red('^'.repeat(length)))\n        }\n        else if (j > i) {\n          if (end > count) {\n            const length = Math.max(1, Math.min(end - count, lineLength))\n            res.push(lineNo() + ' ' + c.red('^'.repeat(length)))\n          }\n          count += lineLength + 1\n        }\n      }\n      break\n    }\n  }\n\n  if (indent) {\n    res = res.map(line => ' '.repeat(indent) + line)\n  }\n\n  return res.join('\\n')\n}\n\nfunction lineNo(no: number | string = '') {\n  return c.gray(`${String(no).padStart(3, ' ')}|`)\n}\n"
  },
  {
    "path": "packages/vitest/src/node/project.ts",
    "content": "import type { GlobOptions } from 'tinyglobby'\nimport type { DevEnvironment, ViteDevServer, InlineConfig as ViteInlineConfig } from 'vite'\nimport type { ModuleRunner } from 'vite/module-runner'\nimport type { Typechecker } from '../typecheck/typechecker'\nimport type { ProvidedContext } from '../types/general'\nimport type { OnTestsRerunHandler, Vitest } from './core'\nimport type { VitestFetchFunction } from './environments/fetchModule'\nimport type { GlobalSetupFile } from './globalSetup'\nimport type { TestSpecificationOptions } from './test-specification'\nimport type { ParentProjectBrowser, ProjectBrowser } from './types/browser'\nimport type {\n  ProjectName,\n  ResolvedConfig,\n  SerializedConfig,\n  TestProjectInlineConfiguration,\n  UserConfig,\n} from './types/config'\nimport { promises as fs, readFileSync } from 'node:fs'\nimport { rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport path from 'node:path'\nimport { deepMerge, nanoid, slash } from '@vitest/utils/helpers'\nimport { isAbsolute, join, relative } from 'pathe'\nimport pm from 'picomatch'\nimport { glob } from 'tinyglobby'\nimport { isRunnableDevEnvironment } from 'vite'\nimport { setup } from '../api/setup'\nimport { createDefinesScript } from '../utils/config-helpers'\nimport { NativeModuleRunner } from '../utils/nativeModuleRunner'\nimport { isBrowserEnabled, resolveConfig } from './config/resolveConfig'\nimport { serializeConfig } from './config/serializeConfig'\nimport { createFetchModuleFunction } from './environments/fetchModule'\nimport { ServerModuleRunner } from './environments/serverRunner'\nimport { loadGlobalSetupFiles } from './globalSetup'\nimport { CoverageTransform } from './plugins/coverageTransform'\nimport { MetaEnvReplacerPlugin } from './plugins/metaEnvReplacer'\nimport { MocksPlugins } from './plugins/mocks'\nimport { WorkspaceVitestPlugin } from './plugins/workspace'\nimport { getFilePoolName } from './pool'\nimport { VitestResolver } from './resolver'\nimport { TestSpecification } from './test-specification'\nimport { createViteServer } from './vite'\n\nexport class TestProject {\n  /**\n   * The global Vitest instance.\n   */\n  public readonly vitest: Vitest\n\n  /**\n   * Resolved global configuration. If there are no workspace projects, this will be the same as `config`.\n   */\n  public readonly globalConfig: ResolvedConfig\n\n  /**\n   * Browser instance if the browser is enabled. This is initialized when the tests run for the first time.\n   */\n  public browser?: ProjectBrowser\n\n  /**\n   * Temporary directory for the project. This is unique for each project. Vitest stores transformed content here.\n   */\n  public readonly tmpDir: string\n\n  /** @internal */ typechecker?: Typechecker\n  /** @internal */ _config?: ResolvedConfig\n  /** @internal */ _vite?: ViteDevServer\n  /** @internal */ _hash?: string\n  /** @internal */ _resolver!: VitestResolver\n  /** @internal */ _fetcher!: VitestFetchFunction\n  /** @internal */ _serializedDefines?: string\n  /** @internal */ testFilesList: string[] | null = null\n\n  private runner!: ModuleRunner\n\n  private closingPromise: Promise<void> | undefined\n\n  private typecheckFilesList: string[] | null = null\n\n  private _globalSetups?: GlobalSetupFile[]\n  private _provided: ProvidedContext = {} as any\n\n  constructor(\n    vitest: Vitest,\n    public options?: InitializeProjectOptions | undefined,\n    tmpDir?: string,\n  ) {\n    this.vitest = vitest\n    this.globalConfig = vitest.config\n    this.tmpDir = tmpDir || join(tmpdir(), nanoid())\n  }\n\n  /**\n   * The unique hash of this project. This value is consistent between the reruns.\n   *\n   * It is based on the root of the project (not consistent between OS) and its name.\n   */\n  public get hash(): string {\n    if (!this._hash) {\n      throw new Error('The server was not set. It means that `project.hash` was called before the Vite server was established.')\n    }\n    return this._hash\n  }\n\n  // \"provide\" is a property, not a method to keep the context when destructed in the global setup,\n  // making it a method would be a breaking change, and can be done in Vitest 3 at minimum\n  /**\n   * Provide a value to the test context. This value will be available to all tests with `inject`.\n   */\n  provide = <T extends keyof ProvidedContext & string>(\n    key: T,\n    value: ProvidedContext[T],\n  ): void => {\n    try {\n      structuredClone(value)\n    }\n    catch (err) {\n      throw new Error(\n        `Cannot provide \"${key}\" because it's not serializable.`,\n        {\n          cause: err,\n        },\n      )\n    }\n    // casting `any` because the default type is `never` since `ProvidedContext` is empty\n    (this._provided as any)[key] = value\n  }\n\n  /**\n   * Get the provided context. The project context is merged with the global context.\n   */\n  getProvidedContext(): ProvidedContext {\n    if (this.isRootProject()) {\n      return this._provided\n    }\n    // globalSetup can run even if core workspace is not part of the test run\n    // so we need to inherit its provided context\n    return {\n      ...this.vitest.getRootProject().getProvidedContext(),\n      ...this._provided,\n    }\n  }\n\n  /**\n   * Creates a new test specification. Specifications describe how to run tests.\n   * @param moduleId The file path\n   */\n  public createSpecification(\n    moduleId: string,\n    locationsOrOptions?: number[] | TestSpecificationOptions | undefined,\n    /** @internal */\n    pool?: string,\n  ): TestSpecification {\n    return new TestSpecification(\n      this,\n      moduleId,\n      pool || getFilePoolName(this),\n      locationsOrOptions,\n    )\n  }\n\n  public toJSON(): SerializedTestProject {\n    return {\n      name: this.name,\n      serializedConfig: this.serializedConfig,\n      context: this.getProvidedContext(),\n    }\n  }\n\n  /**\n   * Vite's dev server instance. Every workspace project has its own server.\n   */\n  public get vite(): ViteDevServer {\n    if (!this._vite) {\n      throw new Error('The server was not set. It means that `project.vite` was called before the Vite server was established.')\n    }\n    // checking it once should be enough\n    Object.defineProperty(this, 'vite', {\n      configurable: true,\n      writable: true,\n      value: this._vite,\n    })\n    return this._vite\n  }\n\n  /**\n   * Resolved project configuration.\n   */\n  public get config(): ResolvedConfig {\n    if (!this._config) {\n      throw new Error('The config was not set. It means that `project.config` was called before the Vite server was established.')\n    }\n    // checking it once should be enough\n    // Object.defineProperty(this, 'config', {\n    //   configurable: true,\n    //   writable: true,\n    //   value: this._config,\n    // })\n    return this._config\n  }\n\n  /**\n   * The name of the project or an empty string if not set.\n   */\n  public get name(): string {\n    return this.config.name || ''\n  }\n\n  /**\n   * The color used when reporting tasks of this project.\n   */\n  public get color(): ProjectName['color'] {\n    return this.config.color\n  }\n\n  /**\n   * Serialized project configuration. This is the config that tests receive.\n   */\n  public get serializedConfig(): SerializedConfig {\n    return this._serializeOverriddenConfig()\n  }\n\n  /**\n   * Check if this is the root project. The root project is the one that has the root config.\n   */\n  public isRootProject(): boolean {\n    return this.vitest.getRootProject() === this\n  }\n\n  /** @internal */\n  async _initializeGlobalSetup() {\n    if (this._globalSetups) {\n      return\n    }\n\n    this._globalSetups = await loadGlobalSetupFiles(\n      this.runner,\n      this.config.globalSetup,\n    )\n\n    for (const globalSetupFile of this._globalSetups) {\n      const teardown = await globalSetupFile.setup?.(this)\n      if (teardown == null || !!globalSetupFile.teardown) {\n        continue\n      }\n      if (typeof teardown !== 'function') {\n        throw new TypeError(\n          `invalid return value in globalSetup file ${globalSetupFile.file}. Must return a function`,\n        )\n      }\n      globalSetupFile.teardown = teardown\n    }\n  }\n\n  onTestsRerun(cb: OnTestsRerunHandler): void {\n    this.vitest.onTestsRerun(cb)\n  }\n\n  /** @internal */\n  async _teardownGlobalSetup(): Promise<void> {\n    if (!this._globalSetups) {\n      return\n    }\n    for (const globalSetupFile of [...this._globalSetups].reverse()) {\n      await globalSetupFile.teardown?.()\n    }\n  }\n\n  /**\n   * Get all files in the project that match the globs in the config and the filters.\n   * @param filters String filters to match the test files.\n   */\n  async globTestFiles(filters: string[] = []): Promise<{\n    /**\n     * Test files that match the filters.\n     */\n    testFiles: string[]\n    /**\n     * Typecheck test files that match the filters. This will be empty unless `typecheck.enabled` is `true`.\n     */\n    typecheckTestFiles: string[]\n  }> {\n    return this.vitest._traces.$('vitest.config.resolve_include_project', async (span) => {\n      const dir = this.config.dir || this.config.root\n\n      const { include, exclude, includeSource } = this.config\n      const typecheck = this.config.typecheck\n      span.setAttributes({\n        cwd: dir,\n        include,\n        exclude,\n        includeSource,\n        typecheck: typecheck.enabled ? typecheck.include : [],\n      })\n\n      const [testFiles, typecheckTestFiles] = await Promise.all([\n        typecheck.enabled && typecheck.only\n          ? []\n          : this.globAllTestFiles(include, exclude, includeSource, dir),\n        typecheck.enabled\n          ? (this.typecheckFilesList || this.globFiles(typecheck.include, typecheck.exclude, dir))\n          : [],\n      ])\n\n      this.typecheckFilesList = typecheckTestFiles\n\n      return {\n        testFiles: this.filterFiles(\n          testFiles,\n          filters,\n          dir,\n        ),\n        typecheckTestFiles: this.filterFiles(\n          typecheckTestFiles,\n          filters,\n          dir,\n        ),\n      }\n    })\n  }\n\n  private async globAllTestFiles(\n    include: string[],\n    exclude: string[],\n    includeSource: string[] | undefined,\n    cwd: string,\n  ): Promise<string[]> {\n    if (this.testFilesList) {\n      return this.testFilesList\n    }\n\n    const testFiles = await this.globFiles(include, exclude, cwd)\n\n    if (includeSource?.length) {\n      const files = await this.globFiles(includeSource, exclude, cwd)\n\n      await Promise.all(\n        files.map(async (file) => {\n          try {\n            const code = await fs.readFile(file, 'utf-8')\n            if (this.isInSourceTestCode(code)) {\n              testFiles.push(file)\n            }\n          }\n          catch {\n            return null\n          }\n        }),\n      )\n    }\n\n    this.testFilesList = testFiles\n\n    return testFiles\n  }\n\n  isBrowserEnabled(): boolean {\n    return isBrowserEnabled(this.config)\n  }\n\n  private markTestFile(testPath: string): void {\n    this.testFilesList?.push(testPath)\n  }\n\n  /** @internal */\n  _removeCachedTestFile(testPath: string): void {\n    if (this.testFilesList) {\n      this.testFilesList = this.testFilesList.filter(file => file !== testPath)\n    }\n  }\n\n  /**\n   * Returns if the file is a test file. Requires `.globTestFiles()` to be called first.\n   * @internal\n   */\n  _isCachedTestFile(testPath: string): boolean {\n    return !!this.testFilesList && this.testFilesList.includes(testPath)\n  }\n\n  /**\n   * Returns if the file is a typecheck test file. Requires `.globTestFiles()` to be called first.\n   * @internal\n   */\n  _isCachedTypecheckFile(testPath: string): boolean {\n    return !!this.typecheckFilesList && this.typecheckFilesList.includes(testPath)\n  }\n\n  /** @internal */\n  async globFiles(include: string[], exclude: string[], cwd: string) {\n    const globOptions: GlobOptions = {\n      dot: true,\n      cwd,\n      ignore: exclude,\n      expandDirectories: false,\n    }\n\n    const files = await glob(include, globOptions)\n    // keep the slashes consistent with Vite\n    // we are not using the pathe here because it normalizes the drive letter on Windows\n    // and we want to keep it the same as working dir\n    return files.map(file => slash(path.resolve(cwd, file)))\n  }\n\n  /**\n   * Test if a file matches the test globs. This does the actual glob matching if the test is not cached, unlike `isCachedTestFile`.\n   */\n  public matchesTestGlob(moduleId: string, source?: () => string): boolean {\n    if (this._isCachedTestFile(moduleId)) {\n      return true\n    }\n    const relativeId = relative(this.config.dir || this.config.root, moduleId)\n    if (pm.isMatch(relativeId, this.config.exclude)) {\n      return false\n    }\n    if (pm.isMatch(relativeId, this.config.include)) {\n      this.markTestFile(moduleId)\n      return true\n    }\n    if (\n      this.config.includeSource?.length\n      && pm.isMatch(relativeId, this.config.includeSource)\n    ) {\n      const code = source?.() || readFileSync(moduleId, 'utf-8')\n      if (this.isInSourceTestCode(code)) {\n        this.markTestFile(moduleId)\n        return true\n      }\n    }\n    return false\n  }\n\n  private isInSourceTestCode(code: string): boolean {\n    return code.includes('import.meta.vitest')\n  }\n\n  private filterFiles(testFiles: string[], filters: string[], dir: string): string[] {\n    if (filters.length && process.platform === 'win32') {\n      filters = filters.map(f => slash(f))\n    }\n\n    if (filters.length) {\n      return testFiles.filter((t) => {\n        const testFile = relative(dir, t).toLocaleLowerCase()\n        return filters.some((f) => {\n          // if filter is a full file path, we should include it if it's in the same folder\n          if (isAbsolute(f) && t.startsWith(f)) {\n            return true\n          }\n\n          const relativePath = f.endsWith('/')\n            ? join(relative(dir, f), '/')\n            : relative(dir, f)\n          return (\n            testFile.includes(f.toLocaleLowerCase())\n            || testFile.includes(relativePath.toLocaleLowerCase())\n          )\n        })\n      })\n    }\n\n    return testFiles\n  }\n\n  private _parentBrowser?: ParentProjectBrowser\n  /** @internal */\n  public _parent?: TestProject\n  /** @internal */\n  _initParentBrowser = deduped(async (childProject: TestProject) => {\n    if (!this.isBrowserEnabled() || this._parentBrowser) {\n      return\n    }\n    const provider = this.config.browser.provider || childProject.config.browser.provider\n    if (provider == null) {\n      throw new Error(`Provider was not specified in the \"browser.provider\" setting. Please, pass down playwright(), webdriverio() or preview() from \"@vitest/browser-playwright\", \"@vitest/browser-webdriverio\" or \"@vitest/browser-preview\" package respectively.`)\n    }\n    if (typeof provider.serverFactory !== 'function') {\n      throw new TypeError(`The browser provider options do not return a \"serverFactory\" function. Are you using the latest \"@vitest/browser-${provider.name}\" package?`)\n    }\n    const browser = await provider.serverFactory({\n      project: this,\n      mocksPlugins: options => MocksPlugins(options),\n      metaEnvReplacer: () => MetaEnvReplacerPlugin(),\n      coveragePlugin: () => CoverageTransform(this.vitest),\n    })\n    this._parentBrowser = browser\n    if (this.config.browser.ui) {\n      setup(this.vitest, browser.vite)\n    }\n  })\n\n  /** @internal */\n  _initBrowserServer = deduped(async () => {\n    await this._parent?._initParentBrowser(this)\n\n    if (!this.browser && this._parent?._parentBrowser) {\n      this.browser = this._parent._parentBrowser.spawn(this)\n      await this.vitest.report('onBrowserInit', this)\n    }\n  })\n\n  /**\n   * Closes the project and all associated resources. This can only be called once; the closing promise is cached until the server restarts.\n   * If the resources are needed again, create a new project.\n   */\n  public close(): Promise<void> {\n    if (!this.closingPromise) {\n      this.closingPromise = Promise.all(\n        [\n          this.vite?.close(),\n          this.typechecker?.stop(),\n          // browser might not be set if it threw an error during initialization\n          (this.browser || this._parent?._parentBrowser?.vite)?.close(),\n          this.clearTmpDir(),\n        ].filter(Boolean),\n      ).then(() => {\n        if (!this.runner.isClosed()) {\n          return this.runner.close()\n        }\n      }).then(() => {\n        this._provided = {} as any\n        this._vite = undefined\n      })\n    }\n    return this.closingPromise\n  }\n\n  /**\n   * Import a file using Vite module runner.\n   * @param moduleId The ID of the module in Vite module graph\n   */\n  public import<T>(moduleId: string): Promise<T> {\n    return this.runner.import(moduleId)\n  }\n\n  private _setHash() {\n    this._hash = generateHash(\n      this._config!.root + this._config!.name,\n    )\n  }\n\n  /** @internal */\n  async _configureServer(options: UserConfig, server: ViteDevServer): Promise<void> {\n    this._config = resolveConfig(\n      this.vitest,\n      {\n        ...options,\n        coverage: this.vitest.config.coverage,\n      },\n      server.config,\n    )\n    this._config.api.token = this.vitest.config.api.token\n    this._setHash()\n    for (const _providedKey in this.config.provide) {\n      const providedKey = _providedKey as keyof ProvidedContext\n      // type is very strict here, so we cast it to any\n      (this.provide as (key: string, value: unknown) => void)(\n        providedKey,\n        this.config.provide[providedKey],\n      )\n    }\n\n    this.closingPromise = undefined\n\n    this._resolver = new VitestResolver(server.config.cacheDir, this._config)\n    this._vite = server\n    this._serializedDefines = createDefinesScript(server.config.define)\n    this._fetcher = createFetchModuleFunction(\n      this._resolver,\n      this._config,\n      this.vitest._fsCache,\n      this.vitest._traces,\n      this.tmpDir,\n    )\n\n    const environment = server.environments.__vitest__\n    this.runner = this._config.experimental.viteModuleRunner === false\n      ? new NativeModuleRunner(this._config.root)\n      : new ServerModuleRunner(\n          environment,\n          this._fetcher,\n          this._config,\n        )\n\n    const ssrEnvironment = server.environments.ssr\n    if (isRunnableDevEnvironment(ssrEnvironment)) {\n      const ssrRunner = new ServerModuleRunner(\n        ssrEnvironment,\n        this._fetcher,\n        this._config,\n      )\n      Object.defineProperty(ssrEnvironment, 'runner', {\n        value: ssrRunner,\n        writable: true,\n        configurable: true,\n      })\n    }\n  }\n\n  /** @internal */\n  public _getViteEnvironments(): DevEnvironment[] {\n    return [\n      ...Object.values(this.browser?.vite.environments || {}),\n      ...Object.values(this.vite.environments || {}),\n    ]\n  }\n\n  private _serializeOverriddenConfig(): SerializedConfig {\n    // TODO: serialize the config _once_ or when needed\n    const config = serializeConfig(this)\n    if (!this.vitest.configOverride) {\n      return config\n    }\n    return deepMerge(\n      config,\n      this.vitest.configOverride,\n    )\n  }\n\n  private async clearTmpDir(): Promise<void> {\n    try {\n      await rm(this.tmpDir, { recursive: true })\n    }\n    catch {}\n  }\n\n  /** @internal */\n  _initBrowserProvider = deduped(async (): Promise<void> => {\n    if (!this.isBrowserEnabled() || this.browser?.provider) {\n      return\n    }\n    if (!this.browser) {\n      await this._initBrowserServer()\n    }\n    await this.browser?.initBrowserProvider(this)\n  })\n\n  /** @internal */\n  public _provideObject(context: Partial<ProvidedContext>): void {\n    for (const _providedKey in context) {\n      const providedKey = _providedKey as keyof ProvidedContext\n      // type is very strict here, so we cast it to any\n      (this.provide as (key: string, value: unknown) => void)(\n        providedKey,\n        context[providedKey],\n      )\n    }\n  }\n\n  /** @internal */\n  static _createBasicProject(vitest: Vitest): TestProject {\n    const project = new TestProject(\n      vitest,\n      undefined,\n      vitest._tmpDir,\n    )\n    project.runner = vitest.runner\n    project._vite = vitest.vite\n    project._config = vitest.config\n    project._resolver = vitest._resolver\n    project._fetcher = vitest._fetcher\n    project._serializedDefines = createDefinesScript(vitest.vite.config.define)\n    project._setHash()\n    project._provideObject(vitest.config.provide)\n    return project\n  }\n\n  /** @internal */\n  static _cloneBrowserProject(parent: TestProject, config: ResolvedConfig): TestProject {\n    const clone = new TestProject(parent.vitest, undefined, parent.tmpDir)\n    clone.runner = parent.runner\n    clone._vite = parent._vite\n    clone._resolver = parent._resolver\n    clone._fetcher = parent._fetcher\n    clone._config = config\n    clone._setHash()\n    clone._parent = parent\n    clone._serializedDefines = parent._serializedDefines\n    clone._provideObject(config.provide)\n    return clone\n  }\n}\n\nfunction deduped<T extends (...args: any[]) => Promise<void>>(cb: T): T {\n  let _promise: Promise<void> | undefined\n  return ((...args: any[]) => {\n    if (!_promise) {\n      _promise = cb(...args).finally(() => {\n        _promise = undefined\n      })\n    }\n    return _promise\n  }) as T\n}\n\nexport interface SerializedTestProject {\n  name: string\n  serializedConfig: SerializedConfig\n  context: ProvidedContext\n}\n\ninterface InitializeProjectOptions extends TestProjectInlineConfiguration {\n  configFile: string | false\n}\n\nexport async function initializeProject(\n  workspacePath: string | number,\n  ctx: Vitest,\n  options: InitializeProjectOptions,\n): Promise<TestProject> {\n  const project = new TestProject(ctx, options)\n\n  const { configFile, ...restOptions } = options\n\n  const config: ViteInlineConfig = {\n    ...restOptions,\n    configFile,\n    configLoader: ctx.vite.config.inlineConfig.configLoader,\n    // this will make \"mode\": \"test\" | \"benchmark\" inside defineConfig\n    mode: options.test?.mode || options.mode || ctx.config.mode,\n    plugins: [\n      ...(options.plugins || []),\n      WorkspaceVitestPlugin(project, { ...options, workspacePath }),\n    ],\n  }\n\n  await createViteServer(config)\n\n  return project\n}\n\nfunction generateHash(str: string): string {\n  let hash = 0\n  if (str.length === 0) {\n    return `${hash}`\n  }\n  for (let i = 0; i < str.length; i++) {\n    const char = str.charCodeAt(i)\n    hash = (hash << 5) - hash + char\n    hash = hash & hash // Convert to 32bit integer\n  }\n  return `${hash}`\n}\n"
  },
  {
    "path": "packages/vitest/src/node/projects/resolveProjects.ts",
    "content": "import type { GlobOptions } from 'tinyglobby'\nimport type { Vitest } from '../core'\nimport type {\n  BrowserInstanceOption,\n  ResolvedConfig,\n  TestProjectConfiguration,\n  UserConfig,\n  UserWorkspaceConfig,\n} from '../types/config'\nimport { existsSync, readdirSync, statSync } from 'node:fs'\nimport os from 'node:os'\nimport { limitConcurrency } from '@vitest/runner/utils'\nimport { deepClone } from '@vitest/utils/helpers'\nimport { basename, dirname, relative, resolve } from 'pathe'\nimport { glob, isDynamicPattern } from 'tinyglobby'\nimport { mergeConfig } from 'vite'\nimport { configFiles as defaultConfigFiles } from '../../constants'\nimport { VitestFilteredOutProjectError } from '../errors'\nimport { initializeProject, TestProject } from '../project'\n\n// vitest.config.*\n// vite.config.*\n// vitest.unit.config.*\n// vite.unit.config.*\n// vitest.unit-test.config.*\nconst CONFIG_REGEXP = /^vite(?:st)?(?:\\.[\\w-]+)?\\.config\\./\n\nexport async function resolveProjects(\n  vitest: Vitest,\n  cliOptions: UserConfig,\n  workspaceConfigPath: string | undefined,\n  projectsDefinition: TestProjectConfiguration[],\n  names: Set<string>,\n): Promise<TestProject[]> {\n  const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(\n    vitest,\n    workspaceConfigPath,\n    projectsDefinition,\n  )\n\n  // cli options that affect the project config,\n  // not all options are allowed to be overridden\n  const overridesOptions = [\n    'logHeapUsage',\n    'detectAsyncLeaks',\n    'allowOnly',\n    'sequence',\n    'testTimeout',\n    'pool',\n    'update',\n    'globals',\n    'expandSnapshotDiff',\n    'disableConsoleIntercept',\n    'retry',\n    'testNamePattern',\n    'passWithNoTests',\n    'bail',\n    'isolate',\n    'printConsoleTrace',\n    'inspect',\n    'inspectBrk',\n    'fileParallelism',\n    'tagsFilter',\n  ] as const\n\n  const cliOverrides = overridesOptions.reduce((acc, name) => {\n    if (name in cliOptions) {\n      acc[name] = cliOptions[name] as any\n    }\n    return acc\n  }, {} as UserConfig)\n\n  const projectPromises: Promise<TestProject>[] = []\n  const fileProjects = [...configFiles, ...nonConfigDirectories]\n  const concurrent = limitConcurrency(os.availableParallelism?.() || os.cpus().length || 5)\n\n  projectConfigs.forEach((options, index) => {\n    const configRoot = workspaceConfigPath ? dirname(workspaceConfigPath) : vitest.config.root\n    // if extends a config file, resolve the file path\n    const configFile = typeof options.extends === 'string'\n      ? resolve(configRoot, options.extends)\n      : options.extends === true\n        ? (vitest.vite.config.configFile || false)\n        : false\n    // if `root` is configured, resolve it relative to the workspace file or vite root (like other options)\n    // if `root` is not specified, inline configs use the same root as the root project\n    const root = options.root\n      ? resolve(configRoot, options.root)\n      : vitest.config.root\n    projectPromises.push(concurrent(() => initializeProject(\n      index,\n      vitest,\n      {\n        ...options,\n        root,\n        configFile,\n        plugins: [\n          {\n            name: 'vitest:tags',\n            // don't inherit tags from workspace config, they are merged separately\n            configResolved(config) {\n              ;(config as any).test ??= {}\n              config.test!.tags = options.test?.tags\n            },\n            api: {\n              vitest: {\n                experimental: { ignoreFsModuleCache: true },\n              },\n            },\n          },\n          ...options.plugins || [],\n        ],\n        test: { ...options.test, ...cliOverrides },\n      },\n    )))\n  })\n\n  for (const path of fileProjects) {\n    // if file leads to the root config, then we can just reuse it because we already initialized it\n    if (vitest.vite.config.configFile === path) {\n      const project = getDefaultTestProject(vitest)\n      if (project) {\n        projectPromises.push(Promise.resolve(project))\n      }\n      continue\n    }\n\n    const configFile = path.endsWith('/') ? false : path\n    const root = path.endsWith('/') ? path : dirname(path)\n\n    projectPromises.push(\n      concurrent(() => initializeProject(\n        path,\n        vitest,\n        { root, configFile, test: cliOverrides },\n      )),\n    )\n  }\n\n  // pretty rare case - the glob didn't match anything and there are no inline configs\n  if (!projectPromises.length) {\n    throw new Error(\n      [\n        'No projects were found. Make sure your configuration is correct. ',\n        vitest.config.project.length ? `The filter matched no projects: ${vitest.config.project.join(', ')}. ` : '',\n        `The projects definition: ${JSON.stringify(projectsDefinition, null, 4)}.`,\n      ].join(''),\n    )\n  }\n\n  const resolvedProjectsPromises = await Promise.allSettled(projectPromises)\n\n  const errors: Error[] = []\n  const resolvedProjects: TestProject[] = []\n\n  for (const result of resolvedProjectsPromises) {\n    if (result.status === 'rejected') {\n      if (result.reason instanceof VitestFilteredOutProjectError) {\n        // filter out filtered out projects\n        continue\n      }\n      errors.push(result.reason)\n    }\n    else {\n      resolvedProjects.push(result.value)\n    }\n  }\n\n  if (errors.length) {\n    throw new AggregateError(\n      errors,\n      'Failed to initialize projects. There were errors during projects setup. See below for more details.',\n    )\n  }\n\n  // project names are guaranteed to be unique\n  for (const project of resolvedProjects) {\n    const name = project.name\n    if (names.has(name)) {\n      const duplicate = resolvedProjects.find(p => p.name === name && p !== project)!\n      const filesError = fileProjects.length\n        ? [\n            '\\n\\nYour config matched these files:\\n',\n            fileProjects.map(p => ` - ${relative(vitest.config.root, p)}`).join('\\n'),\n            '\\n\\n',\n          ].join('')\n        : ' '\n      throw new Error([\n        `Project name \"${name}\"`,\n        project.vite.config.configFile ? ` from \"${relative(vitest.config.root, project.vite.config.configFile)}\"` : '',\n        ' is not unique.',\n        duplicate?.vite.config.configFile ? ` The project is already defined by \"${relative(vitest.config.root, duplicate.vite.config.configFile)}\".` : '',\n        filesError,\n        'All projects should have unique names. Make sure your configuration is correct.',\n      ].join(''))\n    }\n    names.add(name)\n  }\n\n  return resolveBrowserProjects(vitest, names, resolvedProjects)\n}\n\nexport async function resolveBrowserProjects(\n  vitest: Vitest,\n  names: Set<string>,\n  resolvedProjects: TestProject[],\n): Promise<TestProject[]> {\n  const removeProjects = new Set<TestProject>()\n\n  resolvedProjects.forEach((project) => {\n    if (!project.config.browser.enabled) {\n      return\n    }\n    const instances = project.config.browser.instances || []\n    if (instances.length === 0) {\n      removeProjects.add(project)\n      return\n    }\n    const originalName = project.config.name\n    // if original name is in the --project=name filter, keep all instances\n    const filteredInstances = vitest.matchesProjectFilter(originalName)\n      ? instances\n      : instances.filter((instance) => {\n          const newName = instance.name! // name is set in \"workspace\" plugin\n          return vitest.matchesProjectFilter(newName)\n        })\n\n    // every project was filtered out\n    if (!filteredInstances.length) {\n      removeProjects.add(project)\n      return\n    }\n\n    filteredInstances.forEach((config, index) => {\n      const browser = config.browser\n      if (!browser) {\n        const nth = index + 1\n        const ending = nth === 2 ? 'nd' : nth === 3 ? 'rd' : 'th'\n        throw new Error(`The browser configuration must have a \"browser\" property. The ${nth}${ending} item in \"browser.instances\" doesn't have it. Make sure your${originalName ? ` \"${originalName}\"` : ''} configuration is correct.`)\n      }\n      const name = config.name\n\n      if (name == null) {\n        throw new Error(`The browser configuration must have a \"name\" property. This is a bug in Vitest. Please, open a new issue with reproduction`)\n      }\n      if (config.provider?.name != null && project.config.browser.provider?.name != null && config.provider?.name !== project.config.browser.provider?.name) {\n        throw new Error(`The instance cannot have a different provider from its parent. The \"${name}\" instance specifies \"${config.provider?.name}\" provider, but its parent has a \"${project.config.browser.provider?.name}\" provider.`)\n      }\n\n      if (names.has(name)) {\n        throw new Error(\n          [\n            `Cannot define a nested project for a ${browser} browser. The project name \"${name}\" was already defined. `,\n            'If you have multiple instances for the same browser, make sure to define a custom \"name\". ',\n            'All projects should have unique names. Make sure your configuration is correct.',\n          ].join(''),\n        )\n      }\n      names.add(name)\n      const clonedConfig = cloneConfig(project, config)\n      clonedConfig.name = name\n      const clone = TestProject._cloneBrowserProject(project, clonedConfig)\n      resolvedProjects.push(clone)\n    })\n\n    removeProjects.add(project)\n  })\n\n  return resolvedProjects.filter(project => !removeProjects.has(project))\n}\n\nfunction cloneConfig(project: TestProject, { browser, ...config }: BrowserInstanceOption) {\n  const {\n    locators,\n    viewport,\n    testerHtmlPath,\n    headless,\n    screenshotDirectory,\n    screenshotFailures,\n    fileParallelism,\n    // @ts-expect-error remove just in case\n    browser: _browser,\n    name,\n    provider,\n    ...overrideConfig\n  } = config\n  const currentConfig = project.config.browser\n  const clonedConfig = deepClone(project.config)\n  return mergeConfig<any, any>({\n    ...clonedConfig,\n    browser: {\n      ...project.config.browser,\n      locators: locators\n        ? {\n            testIdAttribute: locators.testIdAttribute ?? currentConfig.locators.testIdAttribute,\n          }\n        : project.config.browser.locators,\n      viewport: viewport ?? currentConfig.viewport,\n      testerHtmlPath: testerHtmlPath ?? currentConfig.testerHtmlPath,\n      screenshotDirectory: screenshotDirectory ?? currentConfig.screenshotDirectory,\n      screenshotFailures: screenshotFailures ?? currentConfig.screenshotFailures,\n      headless: headless ?? currentConfig.headless,\n      provider: provider ?? currentConfig.provider,\n      fileParallelism: fileParallelism ?? currentConfig.fileParallelism,\n      name: browser,\n      instances: [], // projects cannot spawn more configs\n    },\n    // If there is no include or exclude or includeSource pattern in browser.instances[], we should use the that's pattern from the parent project\n    include: (overrideConfig.include && overrideConfig.include.length > 0) ? [] : clonedConfig.include,\n    exclude: (overrideConfig.exclude && overrideConfig.exclude.length > 0) ? [] : clonedConfig.exclude,\n    includeSource: (overrideConfig.includeSource && overrideConfig.includeSource.length > 0) ? [] : clonedConfig.includeSource,\n    // TODO: should resolve, not merge/override\n  } satisfies ResolvedConfig, overrideConfig) as ResolvedConfig\n}\n\nasync function resolveTestProjectConfigs(\n  vitest: Vitest,\n  workspaceConfigPath: string | undefined,\n  projectsDefinition: TestProjectConfiguration[],\n) {\n  // project configurations that were specified directly\n  const projectsOptions: (UserWorkspaceConfig & { extends?: true | string })[] = []\n\n  // custom config files that were specified directly or resolved from a directory\n  const projectsConfigFiles: string[] = []\n\n  // custom glob matches that should be resolved as directories or config files\n  const projectsGlobMatches: string[] = []\n\n  // directories that don't have a config file inside, but should be treated as projects\n  const nonConfigProjectDirectories: string[] = []\n\n  for (const definition of projectsDefinition) {\n    if (typeof definition === 'string') {\n      const stringOption = definition.replace('<rootDir>', vitest.config.root)\n      // if the string doesn't contain a glob, we can resolve it directly\n      // ['./vitest.config.js']\n      if (!isDynamicPattern(stringOption)) {\n        const file = resolve(vitest.config.root, stringOption)\n\n        if (!existsSync(file)) {\n          const relativeWorkspaceConfigPath = workspaceConfigPath\n            ? relative(vitest.config.root, workspaceConfigPath)\n            : undefined\n          const note = workspaceConfigPath ? `Workspace config file \"${relativeWorkspaceConfigPath}\"` : 'Projects definition'\n          throw new Error(`${note} references a non-existing file or a directory: ${file}`)\n        }\n\n        const stats = statSync(file)\n        // user can specify a config file directly\n        if (stats.isFile()) {\n          const name = basename(file)\n          if (!CONFIG_REGEXP.test(name)) {\n            throw new Error(\n              `The file \"${relative(vitest.config.root, file)}\" must start with \"vitest.config\"/\"vite.config\" `\n              + `or match the pattern \"(vitest|vite).*.config.*\" to be a valid project config.`,\n            )\n          }\n\n          projectsConfigFiles.push(file)\n        }\n        // user can specify a directory that should be used as a project\n        else if (stats.isDirectory()) {\n          const configFile = resolveDirectoryConfig(file)\n          if (configFile) {\n            projectsConfigFiles.push(configFile)\n          }\n          else {\n            const directory = file.at(-1) === '/' ? file : `${file}/`\n            nonConfigProjectDirectories.push(directory)\n          }\n        }\n        else {\n          // should never happen\n          throw new TypeError(`Unexpected file type: ${file}`)\n        }\n      }\n      // if the string is a glob pattern, resolve it later\n      // ['./packages/*']\n      else {\n        projectsGlobMatches.push(stringOption)\n      }\n    }\n    // if the config is inlined, we can resolve it immediately\n    else if (typeof definition === 'function') {\n      projectsOptions.push(await definition({\n        command: vitest.vite.config.command,\n        mode: vitest.vite.config.mode,\n        isPreview: false,\n        isSsrBuild: false,\n      }))\n    }\n    // the config is an object or a Promise that returns an object\n    else {\n      projectsOptions.push(await definition)\n    }\n  }\n\n  if (projectsGlobMatches.length) {\n    const globOptions: GlobOptions = {\n      absolute: true,\n      dot: true,\n      onlyFiles: false,\n      cwd: vitest.config.root,\n      expandDirectories: false,\n      ignore: [\n        '**/node_modules/**',\n        // temporary vite config file\n        '**/*.timestamp-*',\n        // macOS directory metadata\n        '**/.DS_Store',\n      ],\n    }\n\n    const projectsFs = await glob(projectsGlobMatches, globOptions)\n\n    projectsFs.forEach((path) => {\n      // directories are allowed with a glob like `packages/*`\n      // in this case every directory is treated as a project\n      if (path.endsWith('/')) {\n        const configFile = resolveDirectoryConfig(path)\n        if (configFile) {\n          projectsConfigFiles.push(configFile)\n        }\n        else {\n          nonConfigProjectDirectories.push(path)\n        }\n      }\n      else {\n        const name = basename(path)\n        if (!CONFIG_REGEXP.test(name)) {\n          throw new Error(\n            `The projects glob matched a file \"${relative(vitest.config.root, path)}\", `\n            + `but it should also either start with \"vitest.config\"/\"vite.config\" `\n            + `or match the pattern \"(vitest|vite).*.config.*\".`,\n          )\n        }\n        projectsConfigFiles.push(path)\n      }\n    })\n  }\n\n  const projectConfigFiles = Array.from(new Set(projectsConfigFiles))\n\n  return {\n    projectConfigs: projectsOptions,\n    nonConfigDirectories: nonConfigProjectDirectories,\n    configFiles: projectConfigFiles,\n  }\n}\n\nfunction resolveDirectoryConfig(directory: string) {\n  const files = new Set(readdirSync(directory))\n  // default resolution looks for vitest.config.* or vite.config.* files\n  // this simulates how `findUp` works in packages/vitest/src/node/create.ts:29\n  const configFile = defaultConfigFiles.find(file => files.has(file))\n  if (configFile) {\n    return resolve(directory, configFile)\n  }\n  return null\n}\n\nexport function getDefaultTestProject(vitest: Vitest): TestProject | null {\n  const filter = vitest.config.project\n  const project = vitest._ensureRootProject()\n  if (!filter.length) {\n    return project\n  }\n  // check for the project name and browser names\n  const hasProjects = getPotentialProjectNames(project).some(p =>\n    vitest.matchesProjectFilter(p),\n  )\n  if (hasProjects) {\n    return project\n  }\n  return null\n}\n\nfunction getPotentialProjectNames(project: TestProject) {\n  const names = [project.name]\n  if (project.config.browser.instances) {\n    names.push(...project.config.browser.instances.map(i => i.name!))\n  }\n  else if (project.config.browser.name) {\n    names.push(project.config.browser.name)\n  }\n  return names\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/agent.ts",
    "content": "import type { TestSpecification } from '../test-specification'\nimport type { DefaultReporterOptions } from './default'\nimport type { TestCase, TestModule, TestModuleState } from './reported-tasks'\nimport { DefaultReporter } from './default'\n\nexport class AgentReporter extends DefaultReporter {\n  renderSucceed = false\n\n  constructor(options: DefaultReporterOptions = {}) {\n    super({ silent: 'passed-only', ...options, summary: false })\n  }\n\n  onTestRunStart(specifications: ReadonlyArray<TestSpecification>): void {\n    super.onTestRunStart(specifications)\n    this.renderSucceed = false\n  }\n\n  protected printTestModule(testModule: TestModule): void {\n    if (testModule.state() !== 'failed') {\n      return\n    }\n    super.printTestModule(testModule)\n  }\n\n  protected printTestCase(moduleState: TestModuleState, test: TestCase): void {\n    const testResult = test.result()\n    if (testResult.state === 'failed') {\n      super.printTestCase(moduleState, test)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/base.ts",
    "content": "import type { File, Task, TestAnnotation } from '@vitest/runner'\nimport type { ParsedStack, SerializedError } from '@vitest/utils'\nimport type { AsyncLeak, TestError, UserConsoleLog } from '../../types/general'\nimport type { Vitest } from '../core'\nimport type { TestSpecification } from '../test-specification'\nimport type { Reporter, TestRunEndReason } from '../types/reporter'\nimport type { TestCase, TestCollection, TestModule, TestModuleState, TestResult, TestSuite, TestSuiteState } from './reported-tasks'\nimport { readFileSync } from 'node:fs'\nimport { performance } from 'node:perf_hooks'\nimport { getSuites, getTestName, getTests, hasFailed } from '@vitest/runner/utils'\nimport { toArray } from '@vitest/utils/helpers'\nimport { parseStacktrace } from '@vitest/utils/source-map'\nimport { relative } from 'pathe'\nimport c from 'tinyrainbow'\nimport { groupBy } from '../../utils/base'\nimport { isTTY } from '../../utils/env'\nimport { hasFailedSnapshot } from '../../utils/tasks'\nimport { generateCodeFrame, printStack } from '../printError'\nimport { F_CHECK, F_DOWN_RIGHT, F_POINTER } from './renderers/figures'\nimport {\n  countTestErrors,\n  divider,\n  errorBanner,\n  formatProjectName,\n  formatTime,\n  formatTimeString,\n  getStateString,\n  getStateSymbol,\n  padSummaryTitle,\n  renderSnapshotSummary,\n  separator,\n  taskFail,\n  withLabel,\n} from './renderers/utils'\n\nconst BADGE_PADDING = '       '\n\nexport interface BaseOptions {\n  isTTY?: boolean\n  silent?: boolean | 'passed-only'\n}\n\nexport abstract class BaseReporter implements Reporter {\n  start = 0\n  end = 0\n  watchFilters?: string[]\n  failedUnwatchedFiles: TestModule[] = []\n  isTTY: boolean\n  ctx: Vitest = undefined!\n  renderSucceed = false\n\n  protected verbose = false\n  protected silent?: boolean | 'passed-only'\n\n  private _filesInWatchMode = new Map<string, number>()\n  private _timeStart = formatTimeString(new Date())\n\n  constructor(options: BaseOptions = {}) {\n    this.isTTY = options.isTTY ?? isTTY\n    this.silent = options.silent\n  }\n\n  onInit(ctx: Vitest): void {\n    this.ctx = ctx\n    this.silent ??= this.ctx.config.silent\n\n    this.ctx.logger.printBanner()\n  }\n\n  log(...messages: any): void {\n    this.ctx.logger.log(...messages)\n  }\n\n  error(...messages: any): void {\n    this.ctx.logger.error(...messages)\n  }\n\n  relative(path: string): string {\n    return relative(this.ctx.config.root, path)\n  }\n\n  onTestRunStart(_specifications: ReadonlyArray<TestSpecification>): void {\n    this.start = performance.now()\n    this._timeStart = formatTimeString(new Date())\n  }\n\n  onTestRunEnd(\n    testModules: ReadonlyArray<TestModule>,\n    unhandledErrors: ReadonlyArray<SerializedError>,\n    _reason: TestRunEndReason,\n  ): void {\n    const files = testModules.map(testModule => testModule.task)\n    const errors = [...unhandledErrors]\n\n    this.end = performance.now()\n    if (!files.length && !errors.length) {\n      this.ctx.logger.printNoTestFound(this.ctx.filenamePattern)\n    }\n    else {\n      this.reportSummary(files, errors)\n    }\n  }\n\n  onTestCaseResult(testCase: TestCase): void {\n    if (testCase.result().state === 'failed') {\n      this.logFailedTask(testCase.task)\n    }\n  }\n\n  onTestSuiteResult(testSuite: TestSuite): void {\n    if (testSuite.state() === 'failed') {\n      this.logFailedTask(testSuite.task)\n    }\n  }\n\n  onTestModuleEnd(testModule: TestModule): void {\n    if (testModule.state() === 'failed') {\n      this.logFailedTask(testModule.task)\n    }\n\n    this.printTestModule(testModule)\n  }\n\n  protected logFailedTask(task: Task): void {\n    if (this.silent === 'passed-only') {\n      for (const log of task.logs || []) {\n        this.onUserConsoleLog(log, 'failed')\n      }\n    }\n  }\n\n  protected printTestModule(testModule: TestModule): void {\n    const moduleState = testModule.state()\n    if (moduleState === 'queued' || moduleState === 'pending') {\n      return\n    }\n\n    let testsCount = 0\n    let failedCount = 0\n    let skippedCount = 0\n    let todoCount = 0\n\n    // delaying logs to calculate the test stats first\n    // which minimizes the amount of for loops\n    const logs: string[] = []\n    const originalLog = this.log.bind(this)\n    this.log = (msg: string) => logs.push(msg)\n\n    const visit = (suiteState: TestSuiteState, children: TestCollection) => {\n      for (const child of children) {\n        if (child.type === 'suite') {\n          const suiteState = child.state()\n\n          // Skipped suites are hidden when --hideSkippedTests, print otherwise\n          if (!this.ctx.config.hideSkippedTests || suiteState !== 'skipped' || child.task.mode === 'todo') {\n            this.printTestSuite(child)\n          }\n\n          visit(suiteState, child.children)\n        }\n        else {\n          const testResult = child.result()\n\n          testsCount++\n          if (testResult.state === 'failed') {\n            failedCount++\n          }\n          else if (testResult.state === 'skipped') {\n            if (child.options.mode === 'todo') {\n              todoCount++\n            }\n            else {\n              skippedCount++\n            }\n          }\n\n          if (this.ctx.config.hideSkippedTests && suiteState === 'skipped' && child.options.mode !== 'todo') {\n            // Skipped suites are hidden when --hideSkippedTests\n            continue\n          }\n\n          this.printTestCase(moduleState, child)\n        }\n      }\n    }\n\n    try {\n      visit(moduleState, testModule.children)\n    }\n    finally {\n      this.log = originalLog\n    }\n\n    this.log(this.getModuleLog(testModule, {\n      tests: testsCount,\n      failed: failedCount,\n      skipped: skippedCount,\n      todo: todoCount,\n    }))\n    logs.forEach(log => this.log(log))\n  }\n\n  protected printTestCase(moduleState: TestModuleState, test: TestCase): void {\n    const testResult = test.result()\n\n    const { duration = 0 } = test.diagnostic() || {}\n    const padding = this.getTestIndentation(test.task)\n    const suffix = this.getTestCaseSuffix(test)\n\n    if (testResult.state === 'failed') {\n      this.log(c.red(` ${padding}${taskFail} ${this.getTestName(test.task, separator)}`) + suffix)\n    }\n\n    // also print slow tests\n    else if (duration > this.ctx.config.slowTestThreshold) {\n      this.log(` ${padding}${c.yellow(c.dim(F_CHECK))} ${this.getTestName(test.task, separator)} ${suffix}`)\n    }\n\n    else if (this.ctx.config.hideSkippedTests && testResult.state === 'skipped' && test.options.mode !== 'todo') {\n      // Skipped tests are hidden when --hideSkippedTests\n    }\n\n    else if (this.renderSucceed || moduleState === 'failed') {\n      this.log(` ${padding}${this.getStateSymbol(test)} ${this.getTestName(test.task, separator)}${suffix}`)\n    }\n  }\n\n  private getModuleLog(testModule: TestModule, counts: {\n    tests: number\n    failed: number\n    skipped: number\n    todo: number\n  }): string {\n    let state = c.dim(`${counts.tests} test${counts.tests > 1 ? 's' : ''}`)\n\n    if (counts.failed) {\n      state += c.dim(' | ') + c.red(`${counts.failed} failed`)\n    }\n\n    if (counts.skipped) {\n      state += c.dim(' | ') + c.yellow(`${counts.skipped} skipped`)\n    }\n\n    if (counts.todo) {\n      state += c.dim(' | ') + c.gray(`${counts.todo} todo`)\n    }\n\n    let suffix = c.dim('(') + state + c.dim(')') + this.getDurationPrefix(testModule.task)\n\n    const diagnostic = testModule.diagnostic()\n    if (diagnostic.heap != null) {\n      suffix += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`)\n    }\n\n    const title = this.getEntityPrefix(testModule)\n\n    return ` ${title} ${testModule.task.name} ${suffix}`\n  }\n\n  protected printTestSuite(testSuite: TestSuite): void {\n    if (!this.renderSucceed) {\n      return\n    }\n\n    const indentation = '  '.repeat(getIndentation(testSuite.task))\n    const tests = Array.from(testSuite.children.allTests())\n    const state = this.getStateSymbol(testSuite)\n\n    this.log(` ${indentation}${state} ${testSuite.name} ${c.dim(`(${tests.length})`)}`)\n  }\n\n  protected getTestName(test: Task, _separator?: string): string {\n    return test.name\n  }\n\n  protected getFullName(test: Task, separator?: string): string {\n    if (test === test.file) {\n      return test.name\n    }\n\n    let name = test.file.name\n    if (test.location) {\n      name += c.dim(`:${test.location.line}:${test.location.column}`)\n    }\n    name += separator\n    name += getTestName(test, separator)\n    return name\n  }\n\n  protected getTestIndentation(test: Task): string {\n    return '  '.repeat(getIndentation(test))\n  }\n\n  protected printAnnotations(test: TestCase, console: 'log' | 'error', padding = 0): void {\n    const annotations = test.annotations()\n    if (!annotations.length) {\n      return\n    }\n\n    const PADDING = ' '.repeat(padding)\n\n    const groupedAnnotations: Record<string, TestAnnotation[]> = {}\n\n    annotations.forEach((annotation) => {\n      const { location, type } = annotation\n      let group: string\n      if (location) {\n        const file = relative(test.project.config.root, location.file)\n        group = `${c.gray(`${file}:${location.line}:${location.column}`)} ${c.bold(type)}`\n      }\n      else {\n        group = c.bold(type)\n      }\n\n      groupedAnnotations[group] ??= []\n      groupedAnnotations[group].push(annotation)\n    })\n\n    for (const group in groupedAnnotations) {\n      this[console](`${PADDING}${c.blue(F_POINTER)} ${group}`)\n      groupedAnnotations[group].forEach(({ message }) => {\n        this[console](`${PADDING}  ${c.blue(F_DOWN_RIGHT)} ${message}`)\n      })\n    }\n  }\n\n  protected getEntityPrefix(entity: TestCase | TestModule | TestSuite): string {\n    let title = this.getStateSymbol(entity)\n\n    if (entity.project.name) {\n      title += ` ${formatProjectName(entity.project, '')}`\n    }\n\n    if (entity.meta().typecheck) {\n      title += ` ${c.bgBlue(c.bold(' TS '))}`\n    }\n\n    return title\n  }\n\n  protected getTestCaseSuffix(testCase: TestCase): string {\n    const { heap, retryCount, repeatCount } = testCase.diagnostic() || {}\n    const testResult = testCase.result()\n    let suffix = this.getDurationPrefix(testCase.task)\n\n    if (retryCount != null && retryCount > 0) {\n      suffix += c.yellow(` (retry x${retryCount})`)\n    }\n\n    if (repeatCount != null && repeatCount > 0) {\n      suffix += c.yellow(` (repeat x${repeatCount})`)\n    }\n\n    if (heap != null) {\n      suffix += c.magenta(` ${Math.floor(heap / 1024 / 1024)} MB heap used`)\n    }\n\n    if (testResult.state === 'skipped' && testResult.note) {\n      suffix += c.dim(c.gray(` [${testResult.note}]`))\n    }\n\n    return suffix\n  }\n\n  protected getStateSymbol(test: TestCase | TestModule | TestSuite): string {\n    return getStateSymbol(test.task)\n  }\n\n  private getDurationPrefix(task: Task): string {\n    const duration = task.result?.duration && Math.round(task.result?.duration)\n    if (duration == null) {\n      return ''\n    }\n\n    const color = duration > this.ctx.config.slowTestThreshold\n      ? c.yellow\n      : c.green\n\n    return color(` ${duration}${c.dim('ms')}`)\n  }\n\n  onWatcherStart(files: File[] = this.ctx.state.getFiles(), errors: unknown[] = this.ctx.state.getUnhandledErrors()): void {\n    const failed = errors.length > 0 || hasFailed(files)\n\n    if (failed) {\n      this.log(withLabel('red', 'FAIL', 'Tests failed. Watching for file changes...'))\n    }\n    else if (this.ctx.isCancelling) {\n      this.log(withLabel('red', 'CANCELLED', 'Test run cancelled. Watching for file changes...'))\n    }\n    else {\n      this.log(withLabel('green', 'PASS', 'Waiting for file changes...'))\n    }\n\n    const hints = [c.dim('press ') + c.bold('h') + c.dim(' to show help')]\n\n    if (hasFailedSnapshot(files)) {\n      hints.unshift(c.dim('press ') + c.bold(c.yellow('u')) + c.dim(' to update snapshot'))\n    }\n    else {\n      hints.push(c.dim('press ') + c.bold('q') + c.dim(' to quit'))\n    }\n\n    this.log(BADGE_PADDING + hints.join(c.dim(', ')))\n  }\n\n  onWatcherRerun(files: string[], trigger?: string): void {\n    this.watchFilters = files\n    this.failedUnwatchedFiles = this.ctx.state.getTestModules().filter(testModule =>\n      !files.includes(testModule.task.filepath) && testModule.state() === 'failed',\n    )\n\n    // Update re-run count for each file\n    files.forEach((filepath) => {\n      let reruns = this._filesInWatchMode.get(filepath) ?? 0\n      this._filesInWatchMode.set(filepath, ++reruns)\n    })\n\n    let banner = trigger ? c.dim(`${this.relative(trigger)} `) : ''\n\n    if (files.length === 1) {\n      const rerun = this._filesInWatchMode.get(files[0]) ?? 1\n      banner += c.blue(`x${rerun} `)\n    }\n\n    this.ctx.logger.clearFullScreen()\n    this.log(withLabel('blue', 'RERUN', banner))\n\n    if (this.ctx.configOverride.project) {\n      this.log(BADGE_PADDING + c.dim(' Project name: ') + c.blue(toArray(this.ctx.configOverride.project).join(', ')))\n    }\n\n    if (this.ctx.filenamePattern) {\n      this.log(BADGE_PADDING + c.dim(' Filename pattern: ') + c.blue(this.ctx.filenamePattern.join(', ')))\n    }\n\n    if (this.ctx.configOverride.testNamePattern) {\n      this.log(BADGE_PADDING + c.dim(' Test name pattern: ') + c.blue(String(this.ctx.configOverride.testNamePattern)))\n    }\n\n    this.log('')\n\n    for (const testModule of this.failedUnwatchedFiles) {\n      this.printTestModule(testModule)\n    }\n  }\n\n  onUserConsoleLog(log: UserConsoleLog, taskState?: TestResult['state']): void {\n    if (!this.shouldLog(log, taskState)) {\n      return\n    }\n\n    const output\n      = log.type === 'stdout'\n        ? this.ctx.logger.outputStream\n        : this.ctx.logger.errorStream\n\n    const write = (msg: string) => (output as any).write(msg)\n\n    let headerText = 'unknown test'\n    const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : undefined\n\n    if (task) {\n      headerText = this.getFullName(task, separator)\n    }\n    else if (log.taskId && log.taskId !== '__vitest__unknown_test__') {\n      headerText = log.taskId\n    }\n\n    write(c.gray(log.type + c.dim(` | ${headerText}\\n`)) + log.content)\n\n    if (log.origin) {\n      // browser logs don't have an extra end of line at the end like Node.js does\n      if (log.browser) {\n        write('\\n')\n      }\n\n      const project = task\n        ? this.ctx.getProjectByName(task.file.projectName || '')\n        : this.ctx.getRootProject()\n\n      const stack = log.browser\n        ? (project.browser?.parseStacktrace(log.origin) || [])\n        : parseStacktrace(log.origin)\n\n      const highlight = task && stack.find(i => i.file === task.file.filepath)\n\n      for (const frame of stack) {\n        const color = frame === highlight ? c.cyan : c.gray\n        const path = relative(project.config.root, frame.file)\n\n        const positions = [\n          frame.method,\n          `${path}:${c.dim(`${frame.line}:${frame.column}`)}`,\n        ]\n          .filter(Boolean)\n          .join(' ')\n\n        write(color(` ${c.dim(F_POINTER)} ${positions}\\n`))\n      }\n    }\n\n    write('\\n')\n  }\n\n  onTestRemoved(trigger?: string): void {\n    this.log(c.yellow('Test removed...') + (trigger ? c.dim(` [ ${this.relative(trigger)} ]\\n`) : ''))\n  }\n\n  shouldLog(log: UserConsoleLog, taskState?: TestResult['state']): boolean {\n    if (this.silent === true) {\n      return false\n    }\n\n    if (this.silent === 'passed-only' && taskState !== 'failed') {\n      return false\n    }\n\n    if (this.ctx.config.onConsoleLog) {\n      const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : undefined\n      const entity = task && this.ctx.state.getReportedEntity(task)\n      const shouldLog = this.ctx.config.onConsoleLog(log.content, log.type, entity)\n      if (shouldLog === false) {\n        return false\n      }\n    }\n    return true\n  }\n\n  onServerRestart(reason?: string): void {\n    this.log(c.bold(c.magenta(\n      reason === 'config'\n        ? '\\nRestarting due to config changes...'\n        : '\\nRestarting Vitest...',\n    )))\n  }\n\n  reportSummary(files: File[], errors: unknown[]): void {\n    this.printErrorsSummary(files, errors)\n\n    const leakCount = this.printLeaksSummary()\n\n    if (this.ctx.config.mode === 'benchmark') {\n      this.reportBenchmarkSummary(files)\n    }\n    else {\n      this.reportTestSummary(files, errors, leakCount)\n    }\n  }\n\n  reportTestSummary(files: File[], errors: unknown[], leakCount: number): void {\n    this.log()\n\n    const affectedFiles = [\n      ...this.failedUnwatchedFiles.map(m => m.task),\n      ...files,\n    ]\n    const tests = getTests(affectedFiles)\n\n    const snapshotOutput = renderSnapshotSummary(\n      this.ctx.config.root,\n      this.ctx.snapshot.summary,\n    )\n\n    for (const [index, snapshot] of snapshotOutput.entries()) {\n      const title = index === 0 ? 'Snapshots' : ''\n      this.log(`${padSummaryTitle(title)} ${snapshot}`)\n    }\n\n    if (snapshotOutput.length > 1) {\n      this.log()\n    }\n\n    this.log(padSummaryTitle('Test Files'), getStateString(affectedFiles))\n    this.log(padSummaryTitle('Tests'), getStateString(tests))\n\n    if (this.ctx.projects.some(c => c.config.typecheck.enabled)) {\n      const failed = tests.filter(t => t.meta?.typecheck && t.result?.errors?.length)\n\n      this.log(\n        padSummaryTitle('Type Errors'),\n        failed.length\n          ? c.bold(c.red(`${failed.length} failed`))\n          : c.dim('no errors'),\n      )\n    }\n\n    if (errors.length) {\n      this.log(\n        padSummaryTitle('Errors'),\n        c.bold(c.red(`${errors.length} error${errors.length > 1 ? 's' : ''}`)),\n      )\n    }\n\n    if (leakCount) {\n      this.log(padSummaryTitle('Leaks'), c.bold(c.red(`${leakCount} leak${leakCount > 1 ? 's' : ''}`)))\n    }\n\n    this.log(padSummaryTitle('Start at'), this._timeStart)\n\n    const collectTime = sum(files, file => file.collectDuration)\n    const testsTime = sum(files, file => file.result?.duration)\n    const setupTime = sum(files, file => file.setupDuration)\n\n    if (this.watchFilters) {\n      this.log(padSummaryTitle('Duration'), formatTime(collectTime + testsTime + setupTime))\n    }\n    else {\n      const blobs = this.ctx.state.blobs\n\n      // Execution time is either sum of all runs of `--merge-reports` or the current run's time\n      const executionTime = blobs?.executionTimes ? sum(blobs.executionTimes, time => time) : this.end - this.start\n\n      const environmentTime = sum(files, file => file.environmentLoad)\n      const transformTime = this.ctx.state.transformTime\n      const typecheck = sum(this.ctx.projects, project => project.typechecker?.getResult().time)\n\n      const timers = [\n        `transform ${formatTime(transformTime)}`,\n        `setup ${formatTime(setupTime)}`,\n        `import ${formatTime(collectTime)}`,\n        `tests ${formatTime(testsTime)}`,\n        `environment ${formatTime(environmentTime)}`,\n        typecheck && `typecheck ${formatTime(typecheck)}`,\n      ].filter(Boolean).join(', ')\n\n      this.log(padSummaryTitle('Duration'), formatTime(executionTime) + c.dim(` (${timers})`))\n\n      if (blobs?.executionTimes) {\n        this.log(padSummaryTitle('Per blob') + blobs.executionTimes.map(time => ` ${formatTime(time)}`).join(''))\n      }\n    }\n\n    this.reportImportDurations()\n\n    this.log()\n  }\n\n  private reportImportDurations() {\n    const { print, failOnDanger, thresholds } = this.ctx.config.experimental.importDurations\n    if (!print && !failOnDanger) {\n      return\n    };\n\n    const testModules = this.ctx.state.getTestModules()\n\n    interface ImportEntry {\n      importedModuleId: string\n      selfTime: number\n      external?: boolean\n      totalTime: number\n      testModule: TestModule\n    }\n\n    const allImports: ImportEntry[] = []\n\n    for (const testModule of testModules) {\n      const diagnostic = testModule.diagnostic()\n      const importDurations = diagnostic.importDurations\n\n      for (const filePath in importDurations) {\n        const duration = importDurations[filePath]\n        allImports.push({\n          importedModuleId: filePath,\n          testModule,\n          selfTime: duration.selfTime,\n          totalTime: duration.totalTime,\n          external: duration.external,\n        })\n      }\n    }\n\n    if (allImports.length === 0) {\n      return\n    }\n\n    const dangerImports = allImports.filter(imp => imp.totalTime >= thresholds.danger)\n    const warnImports = allImports.filter(imp => imp.totalTime >= thresholds.warn)\n    const hasDangerImports = dangerImports.length > 0\n    const hasWarnImports = warnImports.length > 0\n\n    // Determine if we should print\n    const shouldFail = failOnDanger && hasDangerImports\n    const shouldPrint = (print === true) || (print === 'on-warn' && hasWarnImports) || shouldFail\n    if (!shouldPrint) {\n      return\n    }\n\n    const sortedImports = allImports.sort((a, b) => b.totalTime - a.totalTime)\n    const maxTotalTime = sortedImports[0].totalTime\n    const limit = this.ctx.config.experimental.importDurations.limit\n    const topImports = sortedImports.slice(0, limit)\n\n    const totalSelfTime = allImports.reduce((sum, imp) => sum + imp.selfTime, 0)\n    const totalTotalTime = allImports.reduce((sum, imp) => sum + imp.totalTime, 0)\n    const slowestImport = sortedImports[0]\n\n    this.log()\n    this.log(c.bold('Import Duration Breakdown') + c.dim(` (Top ${limit})`))\n    this.log()\n    this.log(c.dim(`${'Module'.padEnd(50)} ${'Self'.padStart(6)} ${'Total'.padStart(6)}`))\n\n    // if there are multiple files, it's highly possible that some of them will import the same large file\n    // we group them to show the distinction between those files more easily\n    //     Import Duration Breakdown (Top 10)\n    //\n    //     Module                                              Self     Total\n    //     .../fields/FieldFile/__tests__/FieldFile.spec.ts     7ms    1.01s  ████████████████████\n    //      ↳ tests/support/components/index.ts                 0ms     861ms █████████████████░░░\n    //      ↳ tests/support/components/renderComponent.ts      59ms     861ms █████████████████░░░\n    //     ...s__/apps/desktop/form-updater.desktop.spec.ts     8ms     991ms ████████████████████\n    //     ...sts__/apps/mobile/form-updater.mobile.spec.ts    11ms     990ms ████████████████████\n    //     shared/components/Form/__tests__/Form.spec.ts        5ms     988ms ████████████████████\n    //      ↳ tests/support/components/index.ts                 0ms     935ms ███████████████████░\n    //      ↳ tests/support/components/renderComponent.ts      61ms     935ms ███████████████████░\n    //     ...ditor/features/link/__test__/LinkForm.spec.ts     7ms     972ms ███████████████████░\n    //      ↳ tests/support/components/renderComponent.ts      56ms     936ms ███████████████████░\n\n    const groupedImports = Object.entries(\n      groupBy(topImports, i => i.testModule.id),\n      // the first one is always the highest because the modules are already sorted\n    ).sort(([, imps1], [, imps2]) => imps2[0].totalTime - imps1[0].totalTime)\n\n    for (const [_, group] of groupedImports) {\n      group.forEach((imp, index) => {\n        const barWidth = 20\n        const filledWidth = Math.round((imp.totalTime / maxTotalTime) * barWidth)\n        const bar = c.cyan('█'.repeat(filledWidth)) + c.dim('░'.repeat(barWidth - filledWidth))\n\n        // only show the arrow if there is more than 1 group\n        const pathDisplay = this.ellipsisPath(imp.importedModuleId, imp.external, groupedImports.length > 1 && index > 0)\n\n        this.log(\n          `${pathDisplay} ${this.importDurationTime(imp.selfTime)} ${this.importDurationTime(imp.totalTime)}  ${bar}`,\n        )\n      })\n    }\n\n    this.log()\n    this.log(c.dim('Total imports: ') + allImports.length)\n    this.log(c.dim('Slowest import (total-time): ') + formatTime(slowestImport.totalTime))\n    this.log(c.dim('Total import time (self/total): ') + formatTime(totalSelfTime) + c.dim(' / ') + formatTime(totalTotalTime))\n\n    // Fail if danger threshold exceeded\n    if (shouldFail) {\n      this.log()\n      this.ctx.logger.error(\n        `ERROR: ${dangerImports.length} import(s) exceeded the danger threshold of ${thresholds.danger}ms`,\n      )\n      process.exitCode = 1\n    }\n  }\n\n  private importDurationTime(duration: number) {\n    const { thresholds } = this.ctx.config.experimental.importDurations\n    const color = duration >= thresholds.danger ? c.red : duration >= thresholds.warn ? c.yellow : (c: string) => c\n    return color(formatTime(duration).padStart(6))\n  }\n\n  private ellipsisPath(path: string, external: boolean | undefined, nested: boolean) {\n    const pathDisplay = this.relative(path)\n    const color = external ? c.magenta : (c: string) => c\n    const slicedPath = pathDisplay.slice(-44)\n    let title = ''\n    if (pathDisplay.length > slicedPath.length) {\n      title += '...'\n    }\n    if (nested) {\n      title = ` ${F_DOWN_RIGHT} ${title}`\n    }\n    title += slicedPath\n    return color(title.padEnd(50))\n  }\n\n  private printErrorsSummary(files: File[], errors: unknown[]) {\n    const suites = getSuites(files)\n    const tests = getTests(files)\n\n    const failedSuites = suites.filter(i => i.result?.errors)\n    const failedTests = tests.filter(i => i.result?.state === 'fail')\n    const failedTotal = countTestErrors(failedSuites) + countTestErrors(failedTests)\n\n    // TODO: error divider should take into account merged errors for counting\n    let current = 1\n    const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, undefined, 1)))}\\n`)\n\n    if (failedSuites.length) {\n      this.error(`\\n${errorBanner(`Failed Suites ${failedSuites.length}`)}\\n`)\n      this.printTaskErrors(failedSuites, errorDivider)\n    }\n\n    if (failedTests.length) {\n      this.error(`\\n${errorBanner(`Failed Tests ${failedTests.length}`)}\\n`)\n      this.printTaskErrors(failedTests, errorDivider)\n    }\n\n    if (errors.length) {\n      this.ctx.logger.printUnhandledErrors(errors)\n      this.error()\n    }\n  }\n\n  private printLeaksSummary() {\n    const leaks = this.ctx.state.leakSet\n\n    if (leaks.size === 0) {\n      return 0\n    }\n\n    const leakWithStacks = new Map<string, { leak: AsyncLeak; stacks: ParsedStack[] }>()\n\n    // Leaks can be duplicate, where type and position are identical\n    for (const leak of leaks) {\n      const stacks = parseStacktrace(leak.stack)\n\n      if (stacks.length === 0) {\n        continue\n      }\n\n      const filename = this.relative(leak.filename)\n      const key = `${filename}:${stacks[0].line}:${stacks[0].column}:${leak.type}`\n\n      if (leakWithStacks.has(key)) {\n        continue\n      }\n\n      leakWithStacks.set(key, { leak, stacks })\n    }\n\n    this.error(`\\n${errorBanner(`Async Leaks ${leakWithStacks.size}`)}\\n`)\n\n    for (const { leak, stacks } of leakWithStacks.values()) {\n      const filename = this.relative(leak.filename)\n      this.ctx.logger.error(c.red(`${leak.type} leaking in ${filename}`))\n\n      try {\n        const sourceCode = readFileSync(stacks[0].file, 'utf-8')\n\n        this.ctx.logger.error(generateCodeFrame(\n          sourceCode.length > 100_000\n            ? sourceCode\n            : this.ctx.logger.highlight(stacks[0].file, sourceCode),\n          undefined,\n          stacks[0],\n        ))\n      }\n      catch {\n        // ignore error, do not produce more detailed message with code frame.\n      }\n\n      printStack(\n        this.ctx.logger,\n        this.ctx.getProjectByName(leak.projectName),\n        stacks,\n        stacks[0],\n        {},\n      )\n    }\n\n    return leakWithStacks.size\n  }\n\n  reportBenchmarkSummary(files: File[]): void {\n    const benches = getTests(files)\n    const topBenches = benches.filter(i => i.result?.benchmark?.rank === 1)\n\n    this.log(`\\n${withLabel('cyan', 'BENCH', 'Summary\\n')}`)\n\n    for (const bench of topBenches) {\n      const group = bench.suite || bench.file\n\n      if (!group) {\n        continue\n      }\n\n      const groupName = this.getFullName(group, separator)\n      const project = this.ctx.projects.find(p => p.name === bench.file.projectName)\n\n      this.log(`  ${formatProjectName(project)}${bench.name}${c.dim(` - ${groupName}`)}`)\n\n      const siblings = group.tasks\n        .filter(i => i.meta.benchmark && i.result?.benchmark && i !== bench)\n        .sort((a, b) => a.result!.benchmark!.rank - b.result!.benchmark!.rank)\n\n      for (const sibling of siblings) {\n        const number = (sibling.result!.benchmark!.mean / bench.result!.benchmark!.mean).toFixed(2)\n        this.log(c.green(`    ${number}x `) + c.gray('faster than ') + sibling.name)\n      }\n\n      this.log('')\n    }\n  }\n\n  private printTaskErrors(tasks: Task[], errorDivider: () => void) {\n    const errorsQueue: [error: TestError | undefined, tests: Task[]][] = []\n\n    for (const task of tasks) {\n      // Merge identical errors\n      task.result?.errors?.forEach((error) => {\n        let previous\n\n        if (error?.stack) {\n          previous = errorsQueue.find((i) => {\n            if (i[0]?.stack !== error.stack || i[0]?.diff !== error.diff) {\n              return false\n            }\n\n            const currentProjectName = (task as File)?.projectName || task.file?.projectName || ''\n            const projectName = (i[1][0] as File)?.projectName || i[1][0].file?.projectName || ''\n\n            const currentAnnotations = task.type === 'test' && task.annotations\n            const itemAnnotations = i[1][0].type === 'test' && i[1][0].annotations\n\n            return projectName === currentProjectName && deepEqual(currentAnnotations, itemAnnotations)\n          })\n        }\n\n        if (previous) {\n          previous[1].push(task)\n        }\n        else {\n          errorsQueue.push([error, [task]])\n        }\n      })\n    }\n\n    for (const [error, tasks] of errorsQueue) {\n      for (const task of tasks) {\n        const filepath = (task as File)?.filepath || ''\n        const projectName = (task as File)?.projectName || task.file?.projectName || ''\n        const project = this.ctx.projects.find(p => p.name === projectName)\n\n        let name = this.getFullName(task, separator)\n\n        if (filepath) {\n          name += c.dim(` [ ${this.relative(filepath)} ]`)\n        }\n\n        this.ctx.logger.error(\n          `${c.bgRed(c.bold(' FAIL '))} ${formatProjectName(project)}${name}`,\n        )\n      }\n\n      const screenshotPaths = tasks.reduce<string[]>((paths, t) => {\n        if (t.type === 'test') {\n          for (const artifact of t.artifacts) {\n            if (artifact.type === 'internal:failureScreenshot') {\n              if (artifact.attachments.length) {\n                paths.push(artifact.attachments[0].originalPath)\n              }\n            }\n          }\n        }\n\n        return paths\n      }, [])\n\n      this.ctx.logger.printError(error, {\n        project: this.ctx.getProjectByName(tasks[0].file.projectName || ''),\n        verbose: this.verbose,\n        screenshotPaths,\n        task: tasks[0],\n      })\n\n      if (tasks[0].type === 'test' && tasks[0].annotations.length) {\n        const test = this.ctx.state.getReportedEntity(tasks[0]) as TestCase\n        this.printAnnotations(test, 'error', 1)\n        this.error()\n      }\n\n      errorDivider()\n    }\n  }\n}\n\nfunction deepEqual(a: any, b: any): boolean {\n  if (a === b) {\n    return true\n  }\n  if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {\n    return false\n  }\n\n  const keysA = Object.keys(a)\n  const keysB = Object.keys(b)\n  if (keysA.length !== keysB.length) {\n    return false\n  }\n\n  for (const key of keysA) {\n    if (!keysB.includes(key) || !deepEqual(a[key], b[key])) {\n      return false\n    }\n  }\n  return true\n}\n\nfunction sum<T>(items: T[], cb: (_next: T) => number | undefined) {\n  return items.reduce((total, next) => {\n    return total + Math.max(cb(next) || 0, 0)\n  }, 0)\n}\n\nfunction getIndentation(suite: Task, level = 1): number {\n  if (suite.suite && !('filepath' in suite.suite)) {\n    return getIndentation(suite.suite, level + 1)\n  }\n\n  return level\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/benchmark/index.ts",
    "content": "import { BenchmarkReporter } from './reporter'\nimport { VerboseBenchmarkReporter } from './verbose'\n\nexport {\n  BenchmarkReporter,\n  VerboseBenchmarkReporter,\n}\n\nexport const BenchmarkReportsMap: {\n  default: typeof BenchmarkReporter\n  verbose: typeof VerboseBenchmarkReporter\n} = {\n  default: BenchmarkReporter,\n  verbose: VerboseBenchmarkReporter,\n}\n\nexport type BenchmarkBuiltinReporters = keyof typeof BenchmarkReportsMap\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/benchmark/json-formatter.ts",
    "content": "import type { File } from '@vitest/runner'\nimport type { BenchmarkResult } from '../../../runtime/types/benchmark'\nimport { getFullName, getTasks } from '@vitest/runner/utils'\n\ninterface Report {\n  files: {\n    filepath: string\n    groups: Group[]\n  }[]\n}\n\ninterface Group {\n  fullName: string\n  benchmarks: FormattedBenchmarkResult[]\n}\n\nexport type FormattedBenchmarkResult = BenchmarkResult & {\n  id: string\n}\n\nexport function createBenchmarkJsonReport(files: File[]): Report {\n  const report: Report = { files: [] }\n\n  for (const file of files) {\n    const groups: Group[] = []\n\n    for (const task of getTasks(file)) {\n      if (task?.type === 'suite') {\n        const benchmarks: FormattedBenchmarkResult[] = []\n\n        for (const t of task.tasks) {\n          const benchmark = t.meta.benchmark && t.result?.benchmark\n\n          if (benchmark) {\n            benchmarks.push({ id: t.id, ...benchmark, samples: [] })\n          }\n        }\n\n        if (benchmarks.length) {\n          groups.push({\n            fullName: getFullName(task, ' > '),\n            benchmarks,\n          })\n        }\n      }\n    }\n\n    report.files.push({\n      filepath: file.filepath,\n      groups,\n    })\n  }\n\n  return report\n}\n\nexport function flattenFormattedBenchmarkReport(report: Report): Record<string, FormattedBenchmarkResult> {\n  const flat: Record<FormattedBenchmarkResult['id'], FormattedBenchmarkResult> = {}\n\n  for (const file of report.files) {\n    for (const group of file.groups) {\n      for (const t of group.benchmarks) {\n        flat[t.id] = t\n      }\n    }\n  }\n\n  return flat\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/benchmark/reporter.ts",
    "content": "import type { TaskResultPack } from '@vitest/runner'\nimport type { SerializedError } from '@vitest/utils'\nimport type { Vitest } from '../../core'\nimport type { TestRunEndReason } from '../../types/reporter'\nimport type { TestModule, TestSuite } from '../reported-tasks'\nimport fs from 'node:fs'\nimport { getFullName } from '@vitest/runner/utils'\nimport * as pathe from 'pathe'\nimport c from 'tinyrainbow'\nimport { DefaultReporter } from '../default'\nimport { formatProjectName, getStateSymbol, separator } from '../renderers/utils'\nimport { createBenchmarkJsonReport, flattenFormattedBenchmarkReport } from './json-formatter'\nimport { renderTable } from './tableRender'\n\nexport class BenchmarkReporter extends DefaultReporter {\n  compare?: Parameters<typeof renderTable>[0]['compare']\n\n  async onInit(ctx: Vitest): Promise<void> {\n    super.onInit(ctx)\n\n    if (this.ctx.config.benchmark?.compare) {\n      const compareFile = pathe.resolve(\n        this.ctx.config.root,\n        this.ctx.config.benchmark?.compare,\n      )\n      try {\n        this.compare = flattenFormattedBenchmarkReport(\n          JSON.parse(await fs.promises.readFile(compareFile, 'utf-8')),\n        )\n      }\n      catch (e) {\n        this.error(`Failed to read '${compareFile}'`, e)\n      }\n    }\n  }\n\n  onTaskUpdate(packs: TaskResultPack[]): void {\n    for (const pack of packs) {\n      const task = this.ctx.state.idMap.get(pack[0])\n\n      if (task?.type === 'suite' && task.result?.state !== 'run') {\n        task.tasks.filter(task => task.result?.benchmark)\n          .sort((benchA, benchB) => benchA.result!.benchmark!.mean - benchB.result!.benchmark!.mean)\n          .forEach((bench, idx) => {\n            bench.result!.benchmark!.rank = Number(idx) + 1\n          })\n      }\n    }\n  }\n\n  onTestSuiteResult(testSuite: TestSuite): void {\n    super.onTestSuiteResult(testSuite)\n    this.printSuiteTable(testSuite)\n  }\n\n  protected printTestModule(testModule: TestModule): void {\n    this.printSuiteTable(testModule)\n  }\n\n  private printSuiteTable(testTask: TestModule | TestSuite): void {\n    const state = testTask.state()\n    if (state === 'pending' || state === 'queued') {\n      return\n    }\n\n    const benches = testTask.task.tasks.filter(t => t.meta.benchmark)\n    const duration = testTask.task.result?.duration || 0\n\n    if (benches.length > 0 && benches.every(t => t.result?.state !== 'run' && t.result?.state !== 'queued')) {\n      let title = `\\n ${getStateSymbol(testTask.task)} ${formatProjectName(testTask.project)}${getFullName(testTask.task, separator)}`\n\n      if (duration != null && duration > this.ctx.config.slowTestThreshold) {\n        title += c.yellow(` ${Math.round(duration)}${c.dim('ms')}`)\n      }\n\n      this.log(title)\n      this.log(renderTable({\n        tasks: benches,\n        level: 1,\n        shallow: true,\n        columns: this.ctx.logger.getColumns(),\n        compare: this.compare,\n        showHeap: this.ctx.config.logHeapUsage,\n        slowTestThreshold: this.ctx.config.slowTestThreshold,\n      }))\n    }\n  }\n\n  async onTestRunEnd(\n    testModules: ReadonlyArray<TestModule>,\n    unhandledErrors: ReadonlyArray<SerializedError>,\n    reason: TestRunEndReason,\n  ): Promise<void> {\n    super.onTestRunEnd(testModules, unhandledErrors, reason)\n\n    // write output for future comparison\n    let outputFile = this.ctx.config.benchmark?.outputJson\n\n    if (outputFile) {\n      outputFile = pathe.resolve(this.ctx.config.root, outputFile)\n      const outputDirectory = pathe.dirname(outputFile)\n\n      if (!fs.existsSync(outputDirectory)) {\n        await fs.promises.mkdir(outputDirectory, { recursive: true })\n      }\n\n      const files = testModules.map(t => t.task.file)\n      const output = createBenchmarkJsonReport(files)\n\n      await fs.promises.writeFile(outputFile, JSON.stringify(output, null, 2))\n      this.log(`Benchmark report written to ${outputFile}`)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/benchmark/tableRender.ts",
    "content": "import type { Task } from '@vitest/runner'\nimport type { BenchmarkResult } from '../../../runtime/types/benchmark'\nimport type { FormattedBenchmarkResult } from './json-formatter'\nimport { stripVTControlCharacters } from 'node:util'\nimport { getTests } from '@vitest/runner/utils'\nimport { notNullish } from '@vitest/utils/helpers'\nimport c from 'tinyrainbow'\nimport { F_RIGHT } from '../renderers/figures'\nimport { getStateSymbol, truncateString } from '../renderers/utils'\n\nconst outputMap = new WeakMap<Task, string>()\n\nfunction formatNumber(number: number) {\n  const res = String(number.toFixed(number < 100 ? 4 : 2)).split('.')\n\n  return res[0].replace(/(?=(?:\\d{3})+$)\\B/g, ',') + (res[1] ? `.${res[1]}` : '')\n}\n\nconst tableHead = [\n  'name',\n  'hz',\n  'min',\n  'max',\n  'mean',\n  'p75',\n  'p99',\n  'p995',\n  'p999',\n  'rme',\n  'samples',\n]\n\nfunction renderBenchmarkItems(result: BenchmarkResult) {\n  return [\n    result.name,\n    formatNumber(result.hz || 0),\n    formatNumber(result.min || 0),\n    formatNumber(result.max || 0),\n    formatNumber(result.mean || 0),\n    formatNumber(result.p75 || 0),\n    formatNumber(result.p99 || 0),\n    formatNumber(result.p995 || 0),\n    formatNumber(result.p999 || 0),\n    `±${(result.rme || 0).toFixed(2)}%`,\n    (result.sampleCount || 0).toString(),\n  ]\n}\n\nfunction computeColumnWidths(results: BenchmarkResult[]): number[] {\n  const rows = [tableHead, ...results.map(v => renderBenchmarkItems(v))]\n\n  return Array.from(tableHead, (_, i) =>\n    Math.max(...rows.map(row => stripVTControlCharacters(row[i]).length)))\n}\n\nfunction padRow(row: string[], widths: number[]) {\n  return row.map(\n    (v, i) => (i ? v.padStart(widths[i], ' ') : v.padEnd(widths[i], ' ')), // name\n  )\n}\n\nfunction renderTableHead(widths: number[]) {\n  return ' '.repeat(3) + padRow(tableHead, widths).map(c.bold).join('  ')\n}\n\nfunction renderBenchmark(result: BenchmarkResult, widths: number[]) {\n  const padded = padRow(renderBenchmarkItems(result), widths)\n  return [\n    padded[0], // name\n    c.blue(padded[1]), // hz\n    c.cyan(padded[2]), // min\n    c.cyan(padded[3]), // max\n    c.cyan(padded[4]), // mean\n    c.cyan(padded[5]), // p75\n    c.cyan(padded[6]), // p99\n    c.cyan(padded[7]), // p995\n    c.cyan(padded[8]), // p999\n    c.dim(padded[9]), // rem\n    c.dim(padded[10]), // sample\n  ].join('  ')\n}\n\nexport function renderTable(\n  options: {\n    tasks: Task[]\n    level: number\n    shallow?: boolean\n    showHeap: boolean\n    columns: number\n    slowTestThreshold: number\n    compare?: Record<Task['id'], FormattedBenchmarkResult>\n  },\n): string {\n  const output: string[] = []\n\n  const benchMap: Record<string, { current: BenchmarkResult; baseline?: BenchmarkResult }> = {}\n\n  for (const task of options.tasks) {\n    if (task.meta.benchmark && task.result?.benchmark) {\n      benchMap[task.id] = {\n        current: task.result.benchmark,\n        baseline: options.compare?.[task.id],\n      }\n    }\n  }\n\n  const benchCount = Object.entries(benchMap).length\n\n  const columnWidths = computeColumnWidths(\n    Object.values(benchMap)\n      .flatMap(v => [v.current, v.baseline])\n      .filter(notNullish),\n  )\n\n  let idx = 0\n  const padding = '  '.repeat(options.level ? 1 : 0)\n\n  for (const task of options.tasks) {\n    const duration = task.result?.duration\n    const bench = benchMap[task.id]\n\n    let prefix = ''\n\n    if (idx === 0 && task.meta?.benchmark) {\n      prefix += `${renderTableHead(columnWidths)}\\n${padding}`\n    }\n\n    prefix += ` ${getStateSymbol(task)} `\n\n    let suffix = ''\n\n    if (task.type === 'suite') {\n      suffix += c.dim(` (${getTests(task).length})`)\n    }\n\n    if (task.mode === 'skip' || task.mode === 'todo') {\n      suffix += c.dim(c.gray(' [skipped]'))\n    }\n\n    if (duration != null) {\n      const color = duration > options.slowTestThreshold ? c.yellow : c.green\n\n      suffix += color(` ${Math.round(duration)}${c.dim('ms')}`)\n    }\n\n    if (options.showHeap && task.result?.heap != null) {\n      suffix += c.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`)\n    }\n\n    if (bench) {\n      let body = renderBenchmark(bench.current, columnWidths)\n\n      if (options.compare && bench.baseline) {\n        if (bench.current.hz) {\n          const diff = bench.current.hz / bench.baseline.hz\n          const diffFixed = diff.toFixed(2)\n\n          if (diffFixed === '1.0.0') {\n            body += c.gray(`  [${diffFixed}x]`)\n          }\n\n          if (diff > 1) {\n            body += c.blue(`  [${diffFixed}x] ⇑`)\n          }\n          else {\n            body += c.red(`  [${diffFixed}x] ⇓`)\n          }\n        }\n        output.push(padding + prefix + body + suffix)\n\n        const bodyBaseline = renderBenchmark(bench.baseline, columnWidths)\n        output.push(`${padding}   ${bodyBaseline}  ${c.dim('(baseline)')}`)\n      }\n\n      else {\n        if (bench.current.rank === 1 && benchCount > 1) {\n          body += c.bold(c.green('   fastest'))\n        }\n\n        if (bench.current.rank === benchCount && benchCount > 2) {\n          body += c.bold(c.gray('   slowest'))\n        }\n\n        output.push(padding + prefix + body + suffix)\n      }\n    }\n    else {\n      output.push(padding + prefix + task.name + suffix)\n    }\n\n    if (task.result?.state !== 'pass' && outputMap.get(task) != null) {\n      let data: string | undefined = outputMap.get(task)\n\n      if (typeof data === 'string') {\n        data = stripVTControlCharacters(data.trim().split('\\n').filter(Boolean).pop()!)\n        if (data === '') {\n          data = undefined\n        }\n      }\n\n      if (data != null) {\n        const out = `   ${'  '.repeat(options.level)}${F_RIGHT} ${data}`\n        output.push(c.gray(truncateString(out, options.columns)))\n      }\n    }\n\n    if (!options.shallow && task.type === 'suite' && task.tasks.length > 0) {\n      if (task.result?.state) {\n        output.push(renderTable({\n          ...options,\n          tasks: task.tasks,\n          level: options.level + 1,\n          shallow: false,\n        }))\n      }\n    }\n    idx++\n  }\n\n  return output.filter(Boolean).join('\\n')\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/benchmark/verbose.ts",
    "content": "import { BenchmarkReporter } from './reporter'\n\nexport class VerboseBenchmarkReporter extends BenchmarkReporter {\n  protected verbose = true\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/blob.ts",
    "content": "import type { File } from '@vitest/runner'\nimport type { SerializedError } from '@vitest/utils'\nimport type { DevEnvironment, EnvironmentModuleNode } from 'vite'\nimport type { Vitest } from '../core'\nimport type { TestProject } from '../project'\nimport type { Reporter } from '../types/reporter'\nimport type { TestModule } from './reported-tasks'\nimport { existsSync } from 'node:fs'\nimport { mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises'\nimport { parse, stringify } from 'flatted'\nimport { dirname, resolve } from 'pathe'\nimport { getOutputFile } from '../../utils/config-helpers'\n\nexport interface BlobOptions {\n  outputFile?: string\n}\n\nexport class BlobReporter implements Reporter {\n  start = 0\n  ctx!: Vitest\n  options: BlobOptions\n  coverage: unknown | undefined\n\n  constructor(options: BlobOptions) {\n    this.options = options\n  }\n\n  onInit(ctx: Vitest): void {\n    if (ctx.config.watch) {\n      throw new Error('Blob reporter is not supported in watch mode')\n    }\n\n    this.ctx = ctx\n    this.start = performance.now()\n    this.coverage = undefined\n  }\n\n  onCoverage(coverage: unknown): void {\n    this.coverage = coverage\n  }\n\n  async onTestRunEnd(testModules: ReadonlyArray<TestModule>, unhandledErrors: ReadonlyArray<SerializedError>): Promise<void> {\n    const executionTime = performance.now() - this.start\n\n    const files = testModules.map(testModule => testModule.task)\n    const errors = [...unhandledErrors]\n    const coverage = this.coverage\n\n    let outputFile\n      = this.options.outputFile ?? getOutputFile(this.ctx.config, 'blob')\n    if (!outputFile) {\n      const shard = this.ctx.config.shard\n      outputFile = shard\n        ? `.vitest-reports/blob-${shard.index}-${shard.count}.json`\n        : '.vitest-reports/blob.json'\n    }\n\n    const environmentModules: MergeReportEnvironmentModules = {}\n    this.ctx.projects.forEach((project) => {\n      const serializedProject: MergeReportEnvironmentModules[string] = {\n        environments: {},\n        external: [],\n      }\n      Object.entries(project.vite.environments).forEach(([environmentName, environment]) => {\n        serializedProject.environments[environmentName] = serializeEnvironmentModuleGraph(\n          environment,\n        )\n      })\n\n      if (project.browser?.vite.environments.client) {\n        serializedProject.browser = serializeEnvironmentModuleGraph(\n          project.browser.vite.environments.client,\n        )\n      }\n\n      for (const [id, value] of project._resolver.externalizeCache.entries()) {\n        if (typeof value === 'string') {\n          serializedProject.external.push([id, value])\n        }\n      }\n\n      environmentModules[project.name] = serializedProject\n    })\n\n    const report = [\n      this.ctx.version,\n      files,\n      errors,\n      coverage,\n      executionTime,\n      environmentModules,\n    ] satisfies MergeReport\n\n    const reportFile = resolve(this.ctx.config.root, outputFile)\n    await writeBlob(report, reportFile)\n\n    this.ctx.logger.log('blob report written to', reportFile)\n  }\n}\n\nexport async function writeBlob(content: MergeReport, filename: string): Promise<void> {\n  const report = stringify(content)\n\n  const dir = dirname(filename)\n  if (!existsSync(dir)) {\n    await mkdir(dir, { recursive: true })\n  }\n\n  await writeFile(filename, report, 'utf-8')\n}\n\nexport async function readBlobs(\n  currentVersion: string,\n  blobsDirectory: string,\n  projectsArray: TestProject[],\n): Promise<MergedBlobs> {\n  // using process.cwd() because --merge-reports can only be used in CLI\n  const resolvedDir = resolve(process.cwd(), blobsDirectory)\n  const blobsFiles = await readdir(resolvedDir)\n  const promises = blobsFiles.map(async (filename) => {\n    const fullPath = resolve(resolvedDir, filename)\n    const stats = await stat(fullPath)\n    if (!stats.isFile()) {\n      throw new TypeError(\n        `vitest.mergeReports() expects all paths in \"${blobsDirectory}\" to be files generated by the blob reporter, but \"${filename}\" is not a file`,\n      )\n    }\n    const content = await readFile(fullPath, 'utf-8')\n    const [version, files, errors, coverage, executionTime, environmentModules] = parse(\n      content,\n    ) as MergeReport\n    if (!version) {\n      throw new TypeError(\n        `vitest.mergeReports() expects all paths in \"${blobsDirectory}\" to be files generated by the blob reporter, but \"${filename}\" is not a valid blob file`,\n      )\n    }\n    return { version, files, errors, coverage, file: filename, executionTime, environmentModules }\n  })\n  const blobs = await Promise.all(promises)\n\n  if (!blobs.length) {\n    throw new Error(\n      `vitest.mergeReports() requires at least one blob file in \"${blobsDirectory}\" directory, but none were found`,\n    )\n  }\n\n  const versions = new Set(blobs.map(blob => blob.version))\n  if (versions.size > 1) {\n    throw new Error(\n      `vitest.mergeReports() requires all blob files to be generated by the same Vitest version, received\\n\\n${blobs.map(b => `- \"${b.file}\" uses v${b.version}`).join('\\n')}`,\n    )\n  }\n\n  if (!versions.has(currentVersion)) {\n    throw new Error(\n      `the blobs in \"${blobsDirectory}\" were generated by a different version of Vitest. Expected v${currentVersion}, but received v${blobs[0].version}`,\n    )\n  }\n\n  // Restore module graph\n  const projects = Object.fromEntries(\n    projectsArray.map(p => [p.name, p]),\n  )\n\n  for (const project of projectsArray) {\n    if (project.isBrowserEnabled()) {\n      await project._initBrowserServer()\n    }\n  }\n\n  blobs.forEach((blob) => {\n    Object.entries(blob.environmentModules).forEach(([projectName, modulesByProject]) => {\n      const project = projects[projectName]\n      if (!project) {\n        return\n      }\n\n      modulesByProject.external.forEach(([id, externalized]) => {\n        project._resolver.externalizeCache.set(id, externalized)\n      })\n\n      Object.entries(modulesByProject.environments).forEach(([environmentName, moduleGraph]) => {\n        const environment = project.vite.environments[environmentName]\n        deserializeEnvironmentModuleGraph(environment, moduleGraph)\n      })\n\n      const browserModuleGraph = modulesByProject.browser\n      if (browserModuleGraph) {\n        const browserEnvironment = project.browser!.vite.environments.client\n        deserializeEnvironmentModuleGraph(browserEnvironment, browserModuleGraph)\n      }\n    })\n  })\n\n  const files = blobs\n    .flatMap(blob => blob.files)\n    .sort((f1, f2) => {\n      const time1 = f1.result?.startTime || 0\n      const time2 = f2.result?.startTime || 0\n      return time1 - time2\n    })\n  const errors = blobs.flatMap(blob => blob.errors)\n  const coverages = blobs.map(blob => blob.coverage)\n  const executionTimes = blobs.map(blob => blob.executionTime)\n\n  return {\n    files,\n    errors,\n    coverages,\n    executionTimes,\n  }\n}\n\nexport interface MergedBlobs {\n  files: File[]\n  errors: unknown[]\n  coverages: unknown[]\n  executionTimes: number[]\n}\n\ntype MergeReport = [\n  vitestVersion: string,\n  files: File[],\n  errors: unknown[],\n  coverage: unknown,\n  executionTime: number,\n  environmentModules: MergeReportEnvironmentModules,\n]\n\ninterface MergeReportEnvironmentModules {\n  [projectName: string]: {\n    environments: {\n      [environmentName: string]: SerializedEnvironmentModuleGraph\n    }\n    browser?: SerializedEnvironmentModuleGraph\n    external: [id: string, externalized: string][]\n  }\n}\n\ntype SerializedEnvironmentModuleNode = [\n  id: number,\n  file: number,\n  url: number,\n  importedIds: number[],\n]\n\ninterface SerializedEnvironmentModuleGraph {\n  idTable: string[]\n  modules: SerializedEnvironmentModuleNode[]\n}\n\nfunction serializeEnvironmentModuleGraph(\n  environment: DevEnvironment,\n): SerializedEnvironmentModuleGraph {\n  const idTable: string[] = []\n  const idMap = new Map<string, number>()\n\n  const getIdIndex = (id: string) => {\n    const existing = idMap.get(id)\n    if (existing != null) {\n      return existing\n    }\n    const next = idTable.length\n    idMap.set(id, next)\n    idTable.push(id)\n    return next\n  }\n\n  const modules: SerializedEnvironmentModuleNode[] = []\n  for (const [id, mod] of environment.moduleGraph.idToModuleMap.entries()) {\n    if (!mod.file) {\n      continue\n    }\n\n    const importedIds: number[] = []\n    for (const importedNode of mod.importedModules) {\n      if (importedNode.id) {\n        importedIds.push(getIdIndex(importedNode.id))\n      }\n    }\n\n    modules.push([\n      getIdIndex(id),\n      getIdIndex(mod.file),\n      getIdIndex(mod.url),\n      importedIds,\n    ])\n  }\n\n  return {\n    idTable,\n    modules,\n  }\n}\n\nfunction deserializeEnvironmentModuleGraph(\n  environment: DevEnvironment,\n  serialized: SerializedEnvironmentModuleGraph,\n): void {\n  const nodesById = new Map<string, EnvironmentModuleNode>()\n\n  serialized.modules.forEach(([id, file, url]) => {\n    const moduleId = serialized.idTable[id]\n    const filePath = serialized.idTable[file]\n    const urlPath = serialized.idTable[url]\n    const moduleNode = environment.moduleGraph.createFileOnlyEntry(filePath)\n    moduleNode.url = urlPath\n    moduleNode.id = moduleId\n    moduleNode.transformResult = {\n      // print error checks that transformResult is set\n      code: ' ',\n      map: null,\n    }\n    environment.moduleGraph.idToModuleMap.set(moduleId, moduleNode)\n    nodesById.set(moduleId, moduleNode)\n  })\n\n  serialized.modules.forEach(([id, _file, _url, importedIds]) => {\n    const moduleId = serialized.idTable[id]\n    const moduleNode = nodesById.get(moduleId)!\n    importedIds.forEach((importedIdIndex) => {\n      const importedId = serialized.idTable[importedIdIndex]\n      const importedNode = nodesById.get(importedId)!\n      moduleNode.importedModules.add(importedNode)\n      importedNode.importers.add(moduleNode)\n    })\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/default.ts",
    "content": "import type { SerializedError } from '@vitest/utils'\nimport type { Vitest } from '../core'\nimport type { TestSpecification } from '../test-specification'\nimport type { TestRunEndReason } from '../types/reporter'\nimport type { BaseOptions } from './base'\nimport type { ReportedHookContext, TestCase, TestModule } from './reported-tasks'\nimport { BaseReporter } from './base'\nimport { SummaryReporter } from './summary'\n\nexport interface DefaultReporterOptions extends BaseOptions {\n  summary?: boolean\n}\n\nexport class DefaultReporter extends BaseReporter {\n  private options: DefaultReporterOptions\n  private summary?: SummaryReporter\n\n  constructor(options: DefaultReporterOptions = {}) {\n    super(options)\n    this.options = {\n      summary: true,\n      ...options,\n    }\n\n    if (!this.isTTY) {\n      this.options.summary = false\n    }\n\n    if (this.options.summary) {\n      this.summary = new SummaryReporter()\n    }\n  }\n\n  onTestRunStart(specifications: ReadonlyArray<TestSpecification>): void {\n    if (this.isTTY) {\n      if (this.renderSucceed === undefined) {\n        this.renderSucceed = !!this.renderSucceed\n      }\n\n      if (this.renderSucceed !== true) {\n        this.renderSucceed = specifications.length <= 1\n      }\n    }\n\n    super.onTestRunStart(specifications)\n    this.summary?.onTestRunStart(specifications)\n  }\n\n  onTestRunEnd(\n    testModules: ReadonlyArray<TestModule>,\n    unhandledErrors: ReadonlyArray<SerializedError>,\n    reason: TestRunEndReason,\n  ): void {\n    super.onTestRunEnd(testModules, unhandledErrors, reason)\n    this.summary?.onTestRunEnd()\n  }\n\n  onTestModuleQueued(file: TestModule): void {\n    this.summary?.onTestModuleQueued(file)\n  }\n\n  onTestModuleCollected(module: TestModule): void {\n    this.summary?.onTestModuleCollected(module)\n  }\n\n  onTestModuleEnd(module: TestModule): void {\n    super.onTestModuleEnd(module)\n    this.summary?.onTestModuleEnd(module)\n  }\n\n  onTestCaseReady(test: TestCase): void {\n    this.summary?.onTestCaseReady(test)\n  }\n\n  onTestCaseResult(test: TestCase): void {\n    super.onTestCaseResult(test)\n    this.summary?.onTestCaseResult(test)\n  }\n\n  onHookStart(hook: ReportedHookContext): void {\n    this.summary?.onHookStart(hook)\n  }\n\n  onHookEnd(hook: ReportedHookContext): void {\n    this.summary?.onHookEnd(hook)\n  }\n\n  onInit(ctx: Vitest): void {\n    super.onInit(ctx)\n    this.summary?.onInit(ctx, { verbose: this.verbose })\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/dot.ts",
    "content": "import type { Test } from '@vitest/runner'\nimport type { SerializedError } from '@vitest/utils'\nimport type { Writable } from 'node:stream'\nimport type { Vitest } from '../core'\nimport type { TestSpecification } from '../test-specification'\nimport type { TestRunEndReason } from '../types/reporter'\nimport type { TestCase, TestModule } from './reported-tasks'\nimport c from 'tinyrainbow'\nimport { BaseReporter } from './base'\nimport { WindowRenderer } from './renderers/windowedRenderer'\n\ninterface Icon {\n  char: string\n  color: (char: string) => string\n}\n\ntype TestCaseState = ReturnType<TestCase['result']>['state']\n\nexport class DotReporter extends BaseReporter {\n  private renderer?: WindowRenderer\n  private tests = new Map<Test['id'], TestCaseState>()\n  private finishedTests = new Set<TestCase['id']>()\n\n  onInit(ctx: Vitest): void {\n    super.onInit(ctx)\n\n    if (this.isTTY) {\n      this.renderer = new WindowRenderer({\n        logger: ctx.logger,\n        getWindow: () => this.createSummary(),\n      })\n\n      this.ctx.onClose(() => this.renderer?.stop())\n    }\n  }\n\n  // Ignore default logging of base reporter\n  printTestModule(): void {}\n\n  onTestRunStart(_specifications: ReadonlyArray<TestSpecification>): void {\n    super.onTestRunStart(_specifications)\n\n    this.renderer?.start()\n  }\n\n  onWatcherRerun(files: string[], trigger?: string): void {\n    this.tests.clear()\n    this.renderer?.start()\n    super.onWatcherRerun(files, trigger)\n  }\n\n  onTestRunEnd(\n    testModules: ReadonlyArray<TestModule>,\n    unhandledErrors: ReadonlyArray<SerializedError>,\n    reason: TestRunEndReason,\n  ): void {\n    if (this.isTTY) {\n      const finalLog = formatTests(Array.from(this.tests.values()))\n      this.ctx.logger.log(finalLog)\n    }\n    else {\n      this.ctx.logger.log()\n    }\n\n    this.tests.clear()\n    this.renderer?.finish()\n\n    super.onTestRunEnd(testModules, unhandledErrors, reason)\n  }\n\n  onTestModuleCollected(module: TestModule): void {\n    for (const test of module.children.allTests()) {\n      // Dot reporter marks pending tests as running\n      this.onTestCaseReady(test)\n    }\n  }\n\n  onTestCaseReady(test: TestCase): void {\n    if (this.finishedTests.has(test.id)) {\n      return\n    }\n    this.tests.set(test.id, test.result().state || 'run')\n    this.renderer?.schedule()\n  }\n\n  onTestCaseResult(test: TestCase): void {\n    const result = test.result().state\n\n    // On non-TTY the finished tests are printed immediately\n    if (!this.isTTY && result !== 'pending') {\n      (this.ctx.logger.outputStream as Writable).write(formatTests([result]))\n    }\n\n    super.onTestCaseResult(test)\n\n    this.finishedTests.add(test.id)\n    this.tests.set(test.id, result || 'skipped')\n    this.renderer?.schedule()\n  }\n\n  onTestModuleEnd(testModule: TestModule): void {\n    super.onTestModuleEnd(testModule)\n\n    if (!this.isTTY) {\n      return\n    }\n\n    const columns = this.ctx.logger.getColumns()\n\n    if (this.tests.size < columns) {\n      return\n    }\n\n    const finishedTests = Array.from(this.tests).filter(entry => entry[1] !== 'pending')\n\n    if (finishedTests.length < columns) {\n      return\n    }\n\n    // Remove finished tests from state and render them in static output\n    const states: TestCaseState[] = []\n    let count = 0\n\n    for (const [id, state] of finishedTests) {\n      if (count++ >= columns) {\n        break\n      }\n\n      this.tests.delete(id)\n      states.push(state)\n    }\n\n    this.ctx.logger.log(formatTests(states))\n    this.renderer?.schedule()\n  }\n\n  private createSummary() {\n    return [\n      formatTests(Array.from(this.tests.values())),\n      '',\n    ]\n  }\n}\n\n// These are compared with reference equality in formatTests\nconst pass: Icon = { char: '·', color: c.green }\nconst fail: Icon = { char: 'x', color: c.red }\nconst pending: Icon = { char: '*', color: c.yellow }\nconst skip: Icon = { char: '-', color: (char: string) => c.dim(c.gray(char)) }\n\nfunction getIcon(state: TestCaseState): Icon {\n  switch (state) {\n    case 'passed':\n      return pass\n    case 'failed':\n      return fail\n    case 'skipped':\n      return skip\n    default:\n      return pending\n  }\n}\n\n/**\n * Format test states into string while keeping ANSI escapes at minimal.\n * Sibling icons with same color are merged into a single c.color() call.\n */\nfunction formatTests(states: TestCaseState[]): string {\n  let currentIcon = pending\n  let count = 0\n  let output = ''\n\n  for (const state of states) {\n    const icon = getIcon(state)\n\n    if (currentIcon === icon) {\n      count++\n      continue\n    }\n\n    output += currentIcon.color(currentIcon.char.repeat(count))\n\n    // Start tracking new group\n    count = 1\n    currentIcon = icon\n  }\n\n  output += currentIcon.color(currentIcon.char.repeat(count))\n\n  return output\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/github-actions.ts",
    "content": "import type { File, TestAnnotation } from '@vitest/runner'\nimport type { SerializedError } from '@vitest/utils'\nimport type { Vitest } from '../core'\nimport type { TestProject } from '../project'\nimport type { Reporter } from '../types/reporter'\nimport type { TestCase, TestModule } from './reported-tasks'\nimport { writeFileSync } from 'node:fs'\nimport { stripVTControlCharacters } from 'node:util'\nimport { getFullName, getTasks } from '@vitest/runner/utils'\nimport { deepMerge } from '@vitest/utils/helpers'\nimport { relative } from 'pathe'\nimport { capturePrintError } from '../printError'\nimport { noun } from './renderers/utils'\n\nexport interface GithubActionsReporterOptions {\n  onWritePath?: (path: string) => string\n  /**\n   * @default true\n   */\n  displayAnnotations?: boolean\n  /**\n   * Configuration for the GitHub Actions Job Summary.\n   *\n   * When enabled, a markdown summary of test results is written to the path specified by `outputPath`.\n   */\n  jobSummary?: Partial<JobSummaryOptions>\n}\n\ninterface JobSummaryOptions {\n  /**\n   * Whether to generate the summary.\n   *\n   * @default true\n   */\n  enabled: boolean\n  /**\n   * File path to write the summary to.\n   *\n   * @default process.env.GITHUB_STEP_SUMMARY\n   */\n  outputPath: string | undefined\n  /**\n   * Configuration for generating permalink URLs to source files in the GitHub repository.\n   *\n   * When all three values are available (either from this config or the defaults picked from environment variables), test names in the summary will link to the relevant source lines.\n   */\n  fileLinks: {\n    /**\n     * The GitHub repository in `owner/repo` format.\n     *\n     * @default process.env.GITHUB_REPOSITORY\n     */\n    repository?: string | undefined\n    /**\n     * The commit SHA to use in permalink URLs.\n     *\n     * @default process.env.GITHUB_SHA\n     */\n    commitHash?: string | undefined\n    /**\n     * The absolute path to the root of the repository on disk.\n     *\n     * This value is used to compute relative file paths for the permalink URLs.\n     *\n     * @default process.env.GITHUB_WORKSPACE\n     */\n    workspacePath?: string | undefined\n  }\n}\n\ntype ResolvedOptions = Required<GithubActionsReporterOptions>\n\nconst defaultOptions: ResolvedOptions = {\n  onWritePath: defaultOnWritePath,\n  displayAnnotations: true,\n  jobSummary: {\n    enabled: true,\n    outputPath: process.env.GITHUB_STEP_SUMMARY,\n    fileLinks: {\n      repository: process.env.GITHUB_REPOSITORY,\n      commitHash: process.env.GITHUB_SHA,\n      workspacePath: process.env.GITHUB_WORKSPACE,\n    },\n  },\n}\n\nexport class GithubActionsReporter implements Reporter {\n  ctx: Vitest = undefined!\n  options: ResolvedOptions\n\n  constructor(options: GithubActionsReporterOptions = {}) {\n    this.options = deepMerge(Object.create(null), defaultOptions, options)\n  }\n\n  onInit(ctx: Vitest): void {\n    this.ctx = ctx\n  }\n\n  onTestCaseAnnotate(testCase: TestCase, annotation: TestAnnotation): void {\n    if (!annotation.location || this.options.displayAnnotations === false) {\n      return\n    }\n\n    const type = getTitle(annotation.type)\n    const formatted = formatMessage({\n      command: getType(annotation.type),\n      properties: {\n        file: annotation.location.file,\n        line: String(annotation.location.line),\n        column: String(annotation.location.column),\n        ...(type && { title: type }),\n      },\n      message: stripVTControlCharacters(annotation.message),\n    })\n    this.ctx.logger.log(`\\n${formatted}`)\n  }\n\n  onTestRunEnd(\n    testModules: ReadonlyArray<TestModule>,\n    unhandledErrors: ReadonlyArray<SerializedError>,\n  ): void {\n    const files = testModules.map(testModule => testModule.task)\n    const errors = [...unhandledErrors]\n\n    // collect all errors and associate them with projects\n    const projectErrors = new Array<{\n      project: TestProject\n      title: string\n      error: unknown\n      file?: File\n    }>()\n    for (const error of errors) {\n      projectErrors.push({\n        project: this.ctx.getRootProject(),\n        title: 'Unhandled error',\n        error,\n      })\n    }\n    for (const file of files) {\n      const tasks = getTasks(file)\n      const project = this.ctx.getProjectByName(file.projectName || '')\n      for (const task of tasks) {\n        if (task.result?.state !== 'fail') {\n          continue\n        }\n\n        const title = getFullName(task, ' > ')\n        for (const error of task.result?.errors ?? []) {\n          projectErrors.push({\n            project,\n            title: project.name ? `[${project.name}] ${title}` : title,\n            error,\n            file,\n          })\n        }\n      }\n    }\n\n    // format errors via `printError`\n    for (const { project, title, error, file } of projectErrors) {\n      const result = capturePrintError(error, this.ctx, { project, task: file })\n      const stack = result?.nearest\n      if (!stack) {\n        continue\n      }\n      const formatted = formatMessage({\n        command: 'error',\n        properties: {\n          file: this.options.onWritePath(stack.file),\n          title,\n          line: String(stack.line),\n          column: String(stack.column),\n        },\n        message: stripVTControlCharacters(result.output),\n      })\n      this.ctx.logger.log(`\\n${formatted}`)\n    }\n\n    if (this.options.jobSummary.enabled === true && this.options.jobSummary.outputPath) {\n      const summary = renderSummary(collectSummaryData(testModules), this.options.jobSummary.fileLinks)\n\n      try {\n        writeFileSync(\n          this.options.jobSummary.outputPath,\n          summary,\n          { flag: 'a' },\n        )\n      }\n      catch (error) {\n        this.ctx.logger.warn('Could not write summary to `options.summary.outputPath`', error)\n      }\n    }\n  }\n}\n\nconst BUILT_IN_TYPES = ['notice', 'error', 'warning']\n\nfunction getTitle(type: string) {\n  if (BUILT_IN_TYPES.includes(type)) {\n    return undefined\n  }\n  return type\n}\n\nfunction getType(type: string) {\n  if (BUILT_IN_TYPES.includes(type)) {\n    return type\n  }\n  return 'notice'\n}\n\nfunction defaultOnWritePath(path: string): string {\n  return path\n}\n\n// workflow command formatting based on\n// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message\n// https://github.com/actions/toolkit/blob/f1d9b4b985e6f0f728b4b766db73498403fd5ca3/packages/core/src/command.ts#L80-L85\nfunction formatMessage({\n  command,\n  properties,\n  message,\n}: {\n  command: string\n  properties: Record<string, string>\n  message: string\n}): string {\n  let result = `::${command}`\n  Object.entries(properties).forEach(([k, v], i) => {\n    result += i === 0 ? ' ' : ','\n    result += `${k}=${escapeProperty(v)}`\n  })\n  result += `::${escapeData(message)}`\n  return result\n}\n\nfunction escapeData(s: string): string {\n  return s.replace(/%/g, '%25').replace(/\\r/g, '%0D').replace(/\\n/g, '%0A')\n}\n\nfunction escapeProperty(s: string): string {\n  return s\n    .replace(/%/g, '%25')\n    .replace(/\\r/g, '%0D')\n    .replace(/\\n/g, '%0A')\n    .replace(/:/g, '%3A')\n    .replace(/,/g, '%2C')\n}\n\ntype SummaryTestsStats = Record<'failed' | 'passed' | 'expectedFail' | 'skipped' | 'todo', number>\n\ninterface SummaryData {\n  fileStats: Pick<SummaryTestsStats, 'failed' | 'passed'>\n  testsStats: SummaryTestsStats\n  flakyTests: Array<{\n    path: {\n      relative: string\n      absolute: string\n    }\n    tests: Array<{\n      testName: string\n      line: number | undefined\n      retries: {\n        allowed: number\n        count: number\n        ratio: number\n      }\n    }>\n  }>\n}\n\nfunction collectSummaryData(testModules: ReadonlyArray<TestModule>): SummaryData {\n  const summaryData: SummaryData = {\n    fileStats: {\n      failed: 0,\n      passed: 0,\n    },\n    testsStats: {\n      failed: 0,\n      passed: 0,\n      expectedFail: 0,\n      skipped: 0,\n      todo: 0,\n    },\n    flakyTests: [],\n  }\n\n  for (const module of testModules) {\n    const flakyTests: SummaryData['flakyTests'][number] = {\n      path: { relative: module.relativeModuleId, absolute: module.moduleId },\n      tests: [],\n    }\n\n    switch (module.task.result?.state) {\n      case 'fail': {\n        summaryData.fileStats.failed += 1\n        break\n      }\n      case 'pass': {\n        summaryData.fileStats.passed += 1\n        break\n      }\n    }\n\n    for (const test of module.children.allTests()) {\n      switch (test.task.mode) {\n        case 'skip': {\n          summaryData.testsStats.skipped += 1\n          break\n        }\n        case 'todo': {\n          summaryData.testsStats.todo += 1\n          break\n        }\n        default: {\n          switch (test.task.result?.state) {\n            case 'fail': {\n              summaryData.testsStats.failed += 1\n              break\n            }\n            case 'pass': {\n              if (test.task.fails) {\n                summaryData.testsStats.expectedFail += 1\n              }\n              else {\n                summaryData.testsStats.passed += 1\n              }\n\n              break\n            }\n          }\n        }\n      }\n\n      const diagnostic = test.diagnostic()\n\n      if (diagnostic?.flaky) {\n        const retriesAllowed = typeof test.options.retry === 'number'\n          ? test.options.retry\n          : (test.options.retry?.count\n            // falling back to `retryCount` as this is used as the denominator to compute `retryRatio`\n            ?? diagnostic.retryCount)\n        const retriesRatio = diagnostic.retryCount / retriesAllowed\n\n        flakyTests.tests.push({\n          retries: {\n            allowed: retriesAllowed,\n            count: diagnostic.retryCount,\n            ratio: retriesRatio,\n          },\n          line: test.task.location?.line,\n          testName: test.task.fullTestName,\n        })\n      }\n    }\n\n    if (flakyTests.tests.length > 0) {\n      flakyTests.tests.sort((a, b) => b.retries.ratio - a.retries.ratio)\n\n      summaryData.flakyTests.push(flakyTests)\n    }\n  }\n\n  return summaryData\n}\n\nfunction createGitHubFileLinkCreator(fileLinks?: JobSummaryOptions['fileLinks']): (path: string, line?: number) => string | null {\n  const repository = fileLinks?.repository\n  const commitHash = fileLinks?.commitHash\n  const workspacePath = fileLinks?.workspacePath\n\n  if (repository !== undefined && commitHash !== undefined && workspacePath !== undefined) {\n    return (path, line) => {\n      const lineFragment = line !== undefined ? `#L${line}` : ''\n\n      return `https://github.com/${repository}/blob/${commitHash}/${relative(workspacePath, path)}${lineFragment}`\n    }\n  }\n\n  return () => null\n}\n\nfunction mdLink(text: string, url: string | null): string {\n  return url === null ? text : `[${text}](${url})`\n}\n\nfunction renderStats({ fileStats, testsStats }: SummaryData): string {\n  const SEPARATOR_SYMBOL = ' · '\n\n  const fileInfoTotal = fileStats.failed + fileStats.passed\n  const primaryInfoTotal = testsStats.failed + testsStats.passed + testsStats.expectedFail\n  const secondaryInfoTotal = testsStats.skipped + testsStats.todo\n\n  const fileInfo: string[] = []\n  const primaryInfo: string[] = []\n  const secondaryInfo: string[] = []\n\n  if (fileStats.failed > 0) {\n    fileInfo.push(`❌ **${fileStats.failed} ${noun(fileStats.failed, 'failure', 'failures')}**`)\n  }\n\n  if (fileStats.passed > 0) {\n    fileInfo.push(`✅ **${fileStats.passed} ${noun(fileStats.passed, 'pass', 'passes')}**`)\n  }\n\n  fileInfo.push(`${fileInfoTotal} total`)\n\n  if (testsStats.failed > 0) {\n    primaryInfo.push(`❌ **${testsStats.failed} ${noun(testsStats.failed, 'failure', 'failures')}**`)\n  }\n\n  if (testsStats.passed > 0) {\n    primaryInfo.push(`✅ **${testsStats.passed} ${noun(testsStats.passed, 'pass', 'passes')}**`)\n  }\n\n  if (testsStats.expectedFail > 0) {\n    primaryInfo.push(`🔵 **${testsStats.expectedFail} expected ${noun(testsStats.expectedFail, 'failure', 'failures')}**`)\n  }\n\n  primaryInfo.push(`${primaryInfoTotal} total`)\n\n  if (testsStats.skipped > 0) {\n    secondaryInfo.push(`${testsStats.skipped} ${noun(testsStats.skipped, 'skip', 'skips')}`)\n  }\n\n  if (testsStats.todo > 0) {\n    secondaryInfo.push(`${testsStats.todo} ${noun(testsStats.todo, 'todo', 'todos')}`)\n  }\n\n  let output = `\\n### Summary\\n\\n- **Test Files**: ${fileInfo.join(SEPARATOR_SYMBOL)}\\n- **Test Results**: ${primaryInfo.join(SEPARATOR_SYMBOL)}\\n`\n\n  if (secondaryInfo.length > 0) {\n    secondaryInfo.push(`${secondaryInfoTotal} total`)\n\n    output += `- **Other**: ${secondaryInfo.join(SEPARATOR_SYMBOL)}\\n`\n  }\n\n  return output\n}\n\nconst SUMMARY_HEADER = '## Vitest Test Report\\n'\n\nfunction renderSummary(summaryData: SummaryData, fileLinks?: JobSummaryOptions['fileLinks']): string {\n  const fileLinkCreator = createGitHubFileLinkCreator(fileLinks)\n\n  let summary = `${SUMMARY_HEADER}${renderStats(summaryData)}`\n\n  if (summaryData.flakyTests.length > 0) {\n    summary += '\\n### Flaky Tests\\n\\nThese tests passed only after one or more retries, indicating potential instability.\\n'\n\n    for (const flakyTests of summaryData.flakyTests) {\n      summary += `\\n##### \\`${flakyTests.path.relative}\\` (${flakyTests.tests.length} flaky tests)\\n`\n\n      for (const flakyTest of flakyTests.tests) {\n        const retriesText = `passed on retry ${flakyTest.retries.count} out of ${flakyTest.retries.allowed}`\n\n        summary += `\\n- ${mdLink(`\\`${flakyTest.testName}\\``, fileLinkCreator(flakyTests.path.absolute, flakyTest.line))} (${flakyTest.retries.ratio >= 0.8 ? `**${retriesText}**` : retriesText})`\n      }\n\n      summary += '\\n'\n    }\n  }\n\n  if (!summary.endsWith('\\n')) {\n    summary += '\\n'\n  }\n\n  return summary\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/hanging-process.ts",
    "content": "import type { Reporter } from '../types/reporter'\nimport { createRequire } from 'node:module'\n\nexport class HangingProcessReporter implements Reporter {\n  whyRunning: (() => void) | undefined\n\n  onInit(): void {\n    const _require = createRequire(import.meta.url)\n    this.whyRunning = _require('why-is-node-running')\n  }\n\n  onProcessTimeout(): void {\n    this.whyRunning?.()\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/html.ts",
    "content": "export interface HTMLOptions {\n  outputFile?: string\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/index.ts",
    "content": "import type { Reporter, TestRunEndReason } from '../types/reporter'\nimport type { BaseOptions, BaseReporter } from './base'\nimport type { BlobOptions } from './blob'\nimport type { DefaultReporterOptions } from './default'\nimport type { GithubActionsReporterOptions } from './github-actions'\nimport type { HTMLOptions } from './html'\nimport type { JsonOptions } from './json'\nimport type { JUnitOptions } from './junit'\nimport { AgentReporter } from './agent'\nimport { BlobReporter } from './blob'\nimport { DefaultReporter } from './default'\nimport { DotReporter } from './dot'\nimport { GithubActionsReporter } from './github-actions'\nimport { HangingProcessReporter } from './hanging-process'\nimport { JsonReporter } from './json'\nimport { JUnitReporter } from './junit'\nimport { TapReporter } from './tap'\nimport { TapFlatReporter } from './tap-flat'\nimport { TreeReporter } from './tree'\nimport { VerboseReporter } from './verbose'\n\nexport {\n  AgentReporter,\n  DefaultReporter,\n  DotReporter,\n  GithubActionsReporter,\n  HangingProcessReporter,\n  JsonReporter,\n  JUnitReporter,\n  TapFlatReporter,\n  TapReporter,\n  TreeReporter,\n  VerboseReporter,\n}\nexport type { BaseReporter, Reporter, TestRunEndReason }\n\nexport type { BenchmarkBuiltinReporters } from './benchmark'\nexport {\n  BenchmarkReporter,\n  BenchmarkReportsMap,\n  VerboseBenchmarkReporter,\n} from './benchmark'\nexport type {\n  JsonAssertionResult,\n  JsonTestResult,\n  JsonTestResults,\n} from './json'\n\nexport const ReportersMap = {\n  'default': DefaultReporter as typeof DefaultReporter,\n  'agent': AgentReporter as typeof AgentReporter,\n  'blob': BlobReporter as typeof BlobReporter,\n  'verbose': VerboseReporter as typeof VerboseReporter,\n  'dot': DotReporter as typeof DotReporter,\n  'json': JsonReporter as typeof JsonReporter,\n  'tap': TapReporter as typeof TapReporter,\n  'tap-flat': TapFlatReporter as typeof TapFlatReporter,\n  'junit': JUnitReporter as typeof JUnitReporter,\n  'tree': TreeReporter as typeof TreeReporter,\n  'hanging-process': HangingProcessReporter as typeof HangingProcessReporter,\n  'github-actions': GithubActionsReporter as typeof GithubActionsReporter,\n}\n\nexport type BuiltinReporters = keyof typeof ReportersMap\n\nexport interface BuiltinReporterOptions {\n  'default': DefaultReporterOptions\n  'agent': DefaultReporterOptions\n  'verbose': DefaultReporterOptions\n  'dot': BaseOptions\n  'tree': BaseOptions\n  'json': JsonOptions\n  'blob': BlobOptions\n  'tap': never\n  'tap-flat': never\n  'junit': JUnitOptions\n  'hanging-process': never\n  'html': HTMLOptions\n  'github-actions': GithubActionsReporterOptions\n}\n\nexport type { ReportedHookContext } from './reported-tasks'\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/json.ts",
    "content": "import type { Suite, TaskMeta, TaskState } from '@vitest/runner'\nimport type { SnapshotSummary } from '@vitest/snapshot'\nimport type { CoverageMap } from 'istanbul-lib-coverage'\nimport type { Vitest } from '../core'\nimport type { Reporter } from '../types/reporter'\nimport type { TestModule } from './reported-tasks'\nimport { existsSync, promises as fs } from 'node:fs'\nimport { getSuites, getTests } from '@vitest/runner/utils'\nimport { dirname, resolve } from 'pathe'\nimport { getOutputFile } from '../../utils/config-helpers'\n\n// for compatibility reasons, the reporter produces a JSON similar to the one produced by the Jest JSON reporter\n// the following types are extracted from the Jest repository (and simplified)\n// the commented-out fields are the missing ones\n\ntype Status = 'passed' | 'failed' | 'skipped' | 'pending' | 'todo' | 'disabled'\ntype Milliseconds = number\ninterface Callsite {\n  line: number\n  column: number\n}\n\nconst StatusMap: Record<TaskState, Status> = {\n  fail: 'failed',\n  only: 'pending',\n  pass: 'passed',\n  run: 'pending',\n  skip: 'skipped',\n  todo: 'todo',\n  queued: 'pending',\n}\n\nexport interface JsonAssertionResult {\n  ancestorTitles: Array<string>\n  fullName: string\n  status: Status\n  title: string\n  meta: TaskMeta\n  duration?: Milliseconds | null\n  failureMessages: Array<string> | null\n  location?: Callsite | null\n  tags: string[]\n}\n\nexport interface JsonTestResult {\n  message: string\n  name: string\n  status: 'failed' | 'passed'\n  startTime: number\n  endTime: number\n  assertionResults: Array<JsonAssertionResult>\n  // summary: string\n  // coverage: unknown\n}\n\nexport interface JsonTestResults {\n  numFailedTests: number\n  numFailedTestSuites: number\n  numPassedTests: number\n  numPassedTestSuites: number\n  numPendingTests: number\n  numPendingTestSuites: number\n  numTodoTests: number\n  numTotalTests: number\n  numTotalTestSuites: number\n  startTime: number\n  success: boolean\n  testResults: Array<JsonTestResult>\n  snapshot: SnapshotSummary\n  coverageMap?: CoverageMap | null | undefined\n  // numRuntimeErrorTestSuites: number\n  // wasInterrupted: boolean\n}\n\nexport interface JsonOptions {\n  outputFile?: string\n}\n\nexport class JsonReporter implements Reporter {\n  start = 0\n  ctx!: Vitest\n  options: JsonOptions\n  coverageMap?: CoverageMap\n\n  constructor(options: JsonOptions) {\n    this.options = options\n  }\n\n  onInit(ctx: Vitest): void {\n    this.ctx = ctx\n    this.start = Date.now()\n    this.coverageMap = undefined\n  }\n\n  onCoverage(coverageMap: unknown): void {\n    this.coverageMap = coverageMap as CoverageMap\n  }\n\n  async onTestRunEnd(testModules: ReadonlyArray<TestModule>): Promise<void> {\n    const files = testModules.map(testModule => testModule.task)\n\n    const suites = getSuites(files)\n    const numTotalTestSuites = suites.length\n    const tests = getTests(files)\n    const numTotalTests = tests.length\n\n    const numFailedTestSuites = suites.filter(s => s.result?.state === 'fail').length\n    const numPendingTestSuites = suites.filter(\n      s => s.result?.state === 'run' || s.result?.state === 'queued' || s.mode === 'todo',\n    ).length\n    const numPassedTestSuites = numTotalTestSuites - numFailedTestSuites - numPendingTestSuites\n\n    const numFailedTests = tests.filter(\n      t => t.result?.state === 'fail',\n    ).length\n    const numPassedTests = tests.filter(t => t.result?.state === 'pass').length\n    const numPendingTests = tests.filter(\n      t => t.result?.state === 'run' || t.result?.state === 'queued' || t.mode === 'skip' || t.result?.state === 'skip',\n    ).length\n    const numTodoTests = tests.filter(t => t.mode === 'todo').length\n    const testResults: Array<JsonTestResult> = []\n\n    const success = !!(files.length > 0 || this.ctx.config.passWithNoTests) && numFailedTestSuites === 0 && numFailedTests === 0\n\n    for (const file of files) {\n      const tests = getTests([file])\n      let startTime = tests.reduce(\n        (prev, next) =>\n          Math.min(prev, next.result?.startTime ?? Number.POSITIVE_INFINITY),\n        Number.POSITIVE_INFINITY,\n      )\n      if (startTime === Number.POSITIVE_INFINITY) {\n        startTime = this.start\n      }\n\n      const endTime = tests.reduce(\n        (prev, next) =>\n          Math.max(\n            prev,\n            (next.result?.startTime ?? 0) + (next.result?.duration ?? 0),\n          ),\n        startTime,\n      )\n      const assertionResults = tests.map((t) => {\n        const ancestorTitles: string[] = []\n        let iter: Suite | undefined = t.suite\n        while (iter) {\n          ancestorTitles.push(iter.name)\n          iter = iter.suite\n        }\n        ancestorTitles.reverse()\n\n        return {\n          ancestorTitles,\n          fullName: t.name\n            ? [...ancestorTitles, t.name].join(' ')\n            : ancestorTitles.join(' '),\n          status: StatusMap[t.result?.state || t.mode] || 'skipped',\n          title: t.name,\n          duration: t.result?.duration,\n          failureMessages:\n            t.result?.errors?.map(e => e.stack || e.message) || [],\n          location: t.location,\n          meta: t.meta,\n          tags: t.tags || [],\n        } satisfies JsonAssertionResult\n      })\n\n      if (tests.some(t => t.result?.state === 'run' || t.result?.state === 'queued')) {\n        this.ctx.logger.warn(\n          'WARNING: Some tests are still running when generating the JSON report.'\n          + 'This is likely an internal bug in Vitest.'\n          + 'Please report it to https://github.com/vitest-dev/vitest/issues',\n        )\n      }\n\n      const hasFailedTests = tests.some(t => t.result?.state === 'fail')\n\n      testResults.push({\n        assertionResults,\n        startTime,\n        endTime,\n        status:\n          file.result?.state === 'fail' || hasFailedTests ? 'failed' : 'passed',\n        message: file.result?.errors?.[0]?.message ?? '',\n        name: file.filepath,\n      })\n    }\n\n    const result: JsonTestResults = {\n      numTotalTestSuites,\n      numPassedTestSuites,\n      numFailedTestSuites,\n      numPendingTestSuites,\n      numTotalTests,\n      numPassedTests,\n      numFailedTests,\n      numPendingTests,\n      numTodoTests,\n      snapshot: this.ctx.snapshot.summary,\n      startTime: this.start,\n      success,\n      testResults,\n      coverageMap: this.coverageMap,\n    }\n\n    await this.writeReport(JSON.stringify(result))\n  }\n\n  /**\n   * Writes the report to an output file if specified in the config,\n   * or logs it to the console otherwise.\n   * @param report\n   */\n  async writeReport(report: string): Promise<void> {\n    const outputFile\n      = this.options.outputFile ?? getOutputFile(this.ctx.config, 'json')\n\n    if (outputFile) {\n      const reportFile = resolve(this.ctx.config.root, outputFile)\n\n      const outputDirectory = dirname(reportFile)\n      if (!existsSync(outputDirectory)) {\n        await fs.mkdir(outputDirectory, { recursive: true })\n      }\n\n      await fs.writeFile(reportFile, report, 'utf-8')\n      this.ctx.logger.log(`JSON report written to ${reportFile}`)\n    }\n    else {\n      this.ctx.logger.log(report)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/junit.ts",
    "content": "import type { Task } from '@vitest/runner'\nimport type { Vitest } from '../core'\nimport type { Reporter } from '../types/reporter'\nimport type { TestModule } from './reported-tasks'\nimport { existsSync, promises as fs } from 'node:fs'\n\nimport { hostname } from 'node:os'\nimport { stripVTControlCharacters } from 'node:util'\nimport { getSuites } from '@vitest/runner/utils'\nimport { dirname, relative, resolve } from 'pathe'\nimport { getOutputFile } from '../../utils/config-helpers'\nimport { capturePrintError } from '../printError'\nimport { IndentedLogger } from './renderers/indented-logger'\n\ninterface ClassnameTemplateVariables {\n  filename: string\n  filepath: string\n}\n\nexport interface JUnitOptions {\n  outputFile?: string\n\n  /**\n   * Template for the classname attribute. Can be either a string or a function. The string can contain placeholders {filename} and {filepath}.\n   */\n  classnameTemplate?: string | ((classnameVariables: ClassnameTemplateVariables) => string)\n  suiteName?: string\n  /**\n   * Write <system-out> and <system-err> for console output\n   * @default true\n   */\n  includeConsoleOutput?: boolean\n  /**\n   * Add <testcase file=\"...\"> attribute (validated on CIRCLE CI and GitLab CI)\n   * @default false\n   */\n  addFileAttribute?: boolean\n  /**\n   * Hostname to use in the report. By default, it uses os.hostname()\n   */\n  hostname?: string\n}\n\nfunction flattenTasks(task: Task, baseName = ''): Task[] {\n  const base = baseName ? `${baseName} > ` : ''\n\n  if (task.type === 'suite') {\n    return task.tasks.flatMap(child =>\n      flattenTasks(child, `${base}${task.name}`),\n    )\n  }\n  else {\n    return [\n      {\n        ...task,\n        name: `${base}${task.name}`,\n      },\n    ]\n  }\n}\n\n// https://gist.github.com/john-doherty/b9195065884cdbfd2017a4756e6409cc\nfunction removeInvalidXMLCharacters(\n  value: any,\n  removeDiscouragedChars: boolean,\n): string {\n  let regex\n    // eslint-disable-next-line no-control-regex\n    = /([\\0-\\x08\\v\\f\\x0E-\\x1F\\uFFFD\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF])/g\n  value = String(value || '').replace(regex, '')\n\n  if (removeDiscouragedChars) {\n    // remove everything discouraged by XML 1.0 specifications\n    regex = new RegExp(\n      /* eslint-disable regexp/prefer-character-class, regexp/no-obscure-range, regexp/no-useless-non-capturing-group */\n      '([\\\\x7F-\\\\x84]|[\\\\x86-\\\\x9F]|[\\\\uFDD0-\\\\uFDEF]|\\\\uD83F[\\\\uDFFE\\\\uDFFF]|(?:\\\\uD87F[\\\\uDF'\n      + 'FE\\\\uDFFF])|\\\\uD8BF[\\\\uDFFE\\\\uDFFF]|\\\\uD8FF[\\\\uDFFE\\\\uDFFF]|(?:\\\\uD93F[\\\\uDFFE\\\\uD'\n      + 'FFF])|\\\\uD97F[\\\\uDFFE\\\\uDFFF]|\\\\uD9BF[\\\\uDFFE\\\\uDFFF]|\\\\uD9FF[\\\\uDFFE\\\\uDFFF]'\n      + '|\\\\uDA3F[\\\\uDFFE\\\\uDFFF]|\\\\uDA7F[\\\\uDFFE\\\\uDFFF]|\\\\uDABF[\\\\uDFFE\\\\uDFFF]|(?:\\\\'\n      + 'uDAFF[\\\\uDFFE\\\\uDFFF])|\\\\uDB3F[\\\\uDFFE\\\\uDFFF]|\\\\uDB7F[\\\\uDFFE\\\\uDFFF]|(?:\\\\uDBBF'\n      + '[\\\\uDFFE\\\\uDFFF])|\\\\uDBFF[\\\\uDFFE\\\\uDFFF](?:[\\\\0-\\\\t\\\\v\\\\f\\\\x0E-\\\\u2027\\\\u202A-\\\\uD7FF\\\\'\n      + 'uE000-\\\\uFFFF]|[\\\\uD800-\\\\uDBFF][\\\\uDC00-\\\\uDFFF]|[\\\\uD800-\\\\uDBFF](?![\\\\uDC00-\\\\uDFFF])|'\n      // eslint-disable-next-line regexp/no-useless-assertions\n      + '(?:[^\\\\uD800-\\\\uDBFF]|^)[\\\\uDC00-\\\\uDFFF]))',\n      'g',\n      /* eslint-enable */\n    )\n\n    value = value.replace(regex, '')\n  }\n\n  return value\n}\n\nfunction escapeXML(value: any): string {\n  return removeInvalidXMLCharacters(\n    String(value)\n      .replace(/&/g, '&amp;')\n      .replace(/\"/g, '&quot;')\n      .replace(/'/g, '&apos;')\n      .replace(/</g, '&lt;')\n      .replace(/>/g, '&gt;'),\n    true,\n  )\n}\n\nfunction executionTime(durationMS: number) {\n  return (durationMS / 1000).toLocaleString('en-US', {\n    useGrouping: false,\n    maximumFractionDigits: 10,\n  })\n}\n\nexport function getDuration(task: Task): string | undefined {\n  const duration = task.result?.duration ?? 0\n  return executionTime(duration)\n}\n\nexport class JUnitReporter implements Reporter {\n  private ctx!: Vitest\n  private reportFile?: string\n  private baseLog!: (text: string) => Promise<void>\n  private logger!: IndentedLogger<Promise<void>>\n  private _timeStart = new Date()\n  private fileFd?: fs.FileHandle\n  private options: JUnitOptions\n\n  constructor(options: JUnitOptions) {\n    this.options = { ...options }\n    this.options.includeConsoleOutput ??= true\n  }\n\n  async onInit(ctx: Vitest): Promise<void> {\n    this.ctx = ctx\n\n    const outputFile\n      = this.options.outputFile ?? getOutputFile(this.ctx.config, 'junit')\n\n    if (outputFile) {\n      this.reportFile = resolve(this.ctx.config.root, outputFile)\n\n      const outputDirectory = dirname(this.reportFile)\n      if (!existsSync(outputDirectory)) {\n        await fs.mkdir(outputDirectory, { recursive: true })\n      }\n\n      const fileFd = await fs.open(this.reportFile, 'w+')\n      this.fileFd = fileFd\n\n      this.baseLog = async (text: string) => {\n        if (!this.fileFd) {\n          this.fileFd = await fs.open(this.reportFile!, 'w+')\n        }\n\n        await fs.writeFile(this.fileFd, `${text}\\n`)\n      }\n    }\n    else {\n      this.baseLog = async (text: string) => this.ctx.logger.log(text)\n    }\n\n    this._timeStart = new Date()\n    this.logger = new IndentedLogger(this.baseLog)\n  }\n\n  async writeElement(\n    name: string,\n    attrs: Record<string, any>,\n    children: () => Promise<void>,\n  ): Promise<void> {\n    const pairs: string[] = []\n    for (const key in attrs) {\n      const attr = attrs[key]\n      if (attr === undefined) {\n        continue\n      }\n\n      pairs.push(`${key}=\"${escapeXML(attr)}\"`)\n    }\n\n    await this.logger.log(\n      `<${name}${pairs.length ? ` ${pairs.join(' ')}` : ''}>`,\n    )\n    this.logger.indent()\n    await children.call(this)\n    this.logger.unindent()\n\n    await this.logger.log(`</${name}>`)\n  }\n\n  async writeLogs(task: Task, type: 'err' | 'out'): Promise<void> {\n    if (task.logs == null || task.logs.length === 0) {\n      return\n    }\n\n    const logType = type === 'err' ? 'stderr' : 'stdout'\n    const logs = task.logs.filter(log => log.type === logType)\n\n    if (logs.length === 0) {\n      return\n    }\n\n    await this.writeElement(`system-${type}`, {}, async () => {\n      for (const log of logs) {\n        await this.baseLog(escapeXML(log.content))\n      }\n    })\n  }\n\n  async writeTasks(tasks: Task[], filename: string): Promise<void> {\n    for (const task of tasks) {\n      let classname = filename\n\n      const templateVars: ClassnameTemplateVariables = {\n        filename: task.file.name,\n        filepath: task.file.filepath,\n      }\n\n      if (typeof this.options.classnameTemplate === 'function') {\n        classname = this.options.classnameTemplate(templateVars)\n      }\n      else if (typeof this.options.classnameTemplate === 'string') {\n        classname = this.options.classnameTemplate\n          .replace(/\\{filename\\}/g, templateVars.filename)\n          .replace(/\\{filepath\\}/g, templateVars.filepath)\n      }\n\n      await this.writeElement(\n        'testcase',\n        {\n          classname,\n          file: this.options.addFileAttribute ? filename : undefined,\n          name: task.name,\n          time: getDuration(task),\n        },\n        async () => {\n          if (this.options.includeConsoleOutput) {\n            await this.writeLogs(task, 'out')\n            await this.writeLogs(task, 'err')\n          }\n\n          if (task.mode === 'skip' || task.mode === 'todo') {\n            await this.logger.log('<skipped/>')\n          }\n\n          if (task.type === 'test' && task.annotations.length) {\n            await this.logger.log('<properties>')\n            this.logger.indent()\n\n            for (const annotation of task.annotations) {\n              await this.logger.log(\n                `<property name=\"${escapeXML(annotation.type)}\" value=\"${escapeXML(annotation.message)}\">`,\n              )\n              await this.logger.log('</property>')\n            }\n\n            this.logger.unindent()\n            await this.logger.log('</properties>')\n          }\n\n          if (task.result?.state === 'fail') {\n            const errors = task.result.errors || []\n            for (const error of errors) {\n              await this.writeElement(\n                'failure',\n                {\n                  message: error?.message,\n                  type: error?.name,\n                },\n                async () => {\n                  if (!error) {\n                    return\n                  }\n\n                  const result = capturePrintError(\n                    error,\n                    this.ctx,\n                    { project: this.ctx.getProjectByName(task.file.projectName || ''), task },\n                  )\n                  await this.baseLog(\n                    escapeXML(stripVTControlCharacters(result.output.trim())),\n                  )\n                },\n              )\n            }\n          }\n        },\n      )\n    }\n  }\n\n  async onTestRunEnd(testModules: ReadonlyArray<TestModule>): Promise<void> {\n    const files = testModules.map(testModule => testModule.task)\n\n    await this.logger.log('<?xml version=\"1.0\" encoding=\"UTF-8\" ?>')\n\n    const transformed = files.map((file) => {\n      const tasks = file.tasks.flatMap(task => flattenTasks(task))\n\n      const stats = tasks.reduce(\n        (stats, task) => {\n          return {\n            passed: stats.passed + Number(task.result?.state === 'pass'),\n            failures: stats.failures + Number(task.result?.state === 'fail'),\n            skipped:\n              stats.skipped\n              + Number(task.mode === 'skip' || task.mode === 'todo'),\n          }\n        },\n        {\n          passed: 0,\n          failures: 0,\n          skipped: 0,\n        },\n      )\n\n      // inject failed suites to surface errors during beforeAll/afterAll\n      const suites = getSuites(file)\n      for (const suite of suites) {\n        if (suite.result?.errors) {\n          tasks.push(suite)\n          stats.failures += 1\n        }\n      }\n\n      // If there are no tests, but the file failed to load, we still want to report it as a failure\n      if (tasks.length === 0 && file.result?.state === 'fail') {\n        stats.failures = 1\n\n        tasks.push({\n          id: file.id,\n          type: 'test',\n          name: file.name,\n          fullName: file.name,\n          fullTestName: file.name,\n          mode: 'run',\n          result: file.result,\n          meta: {},\n          timeout: 0,\n          // NOTE: not used in JUnitReporter\n          context: null as any,\n          suite: null as any,\n          file: null as any,\n          annotations: [],\n          artifacts: [],\n        } satisfies Task)\n      }\n\n      return {\n        ...file,\n        tasks,\n        stats,\n      }\n    })\n\n    const stats = transformed.reduce(\n      (stats, file) => {\n        stats.tests += file.tasks.length\n        stats.failures += file.stats.failures\n        stats.time += file.result?.duration || 0\n        return stats\n      },\n      {\n        name: this.options.suiteName || 'vitest tests',\n        tests: 0,\n        failures: 0,\n        errors: 0, // we cannot detect those\n        time: 0,\n      },\n    )\n\n    await this.writeElement('testsuites', { ...stats, time: executionTime(stats.time) }, async () => {\n      for (const file of transformed) {\n        const filename = relative(this.ctx.config.root, file.filepath)\n        await this.writeElement(\n          'testsuite',\n          {\n            name: filename,\n            timestamp: new Date().toISOString(),\n            hostname: this.options.hostname || hostname(),\n            tests: file.tasks.length,\n            failures: file.stats.failures,\n            errors: 0, // An errored test is one that had an unanticipated problem. We cannot detect those.\n            skipped: file.stats.skipped,\n            time: getDuration(file),\n          },\n          async () => {\n            await this.writeTasks(file.tasks, filename)\n          },\n        )\n      }\n    })\n\n    if (this.reportFile) {\n      this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`)\n    }\n\n    await this.fileFd?.close()\n    this.fileFd = undefined\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/renderers/figures.ts",
    "content": "export const F_RIGHT = '→'\nexport const F_DOWN = '↓'\nexport const F_UP = '↑'\nexport const F_DOWN_RIGHT = '↳'\nexport const F_POINTER = '❯'\nexport const F_DOT = '·'\nexport const F_CHECK = '✓'\nexport const F_CROSS = '×'\nexport const F_LONG_DASH = '⎯'\nexport const F_RIGHT_TRI = '▶'\nexport const F_TODO = '□'\nexport const F_TREE_NODE_MIDDLE = '├──'\nexport const F_TREE_NODE_END = '└──'\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/renderers/indented-logger.ts",
    "content": "export class IndentedLogger<T = any> {\n  private currentIndent = ''\n\n  constructor(private baseLog: (text: string) => T) {}\n\n  indent(): void {\n    this.currentIndent += '    '\n  }\n\n  unindent(): void {\n    this.currentIndent = this.currentIndent.substring(\n      0,\n      this.currentIndent.length - 4,\n    )\n  }\n\n  log(text: string): T {\n    return this.baseLog(this.currentIndent + text)\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/renderers/utils.ts",
    "content": "import type { Task } from '@vitest/runner'\nimport type { SnapshotSummary } from '@vitest/snapshot'\nimport type { Formatter } from 'tinyrainbow'\nimport type { TestProject } from '../../project'\nimport { stripVTControlCharacters } from 'node:util'\nimport { slash } from '@vitest/utils/helpers'\nimport { basename, dirname, isAbsolute, relative } from 'pathe'\nimport c from 'tinyrainbow'\nimport {\n  F_CHECK,\n  F_CROSS,\n  F_DOT,\n  F_DOWN,\n  F_DOWN_RIGHT,\n  F_LONG_DASH,\n  F_POINTER,\n  F_TODO,\n} from './figures'\n\nexport const pointer: string = c.yellow(F_POINTER)\nexport const skipped: string = c.dim(c.gray(F_DOWN))\nexport const todo: string = c.dim(c.gray(F_TODO))\nexport const benchmarkPass: string = c.green(F_DOT)\nexport const testPass: string = c.green(F_CHECK)\nexport const taskFail: string = c.red(F_CROSS)\nexport const suiteFail: string = c.red(F_POINTER)\nexport const pending: string = c.gray('·')\nexport const separator: string = c.dim(' > ')\n\nconst labelDefaultColors = [c.bgYellow, c.bgCyan, c.bgGreen, c.bgMagenta] as const\n\nfunction getCols(delta = 0) {\n  let length = process.stdout?.columns\n  if (!length || Number.isNaN(length)) {\n    length = 30\n  }\n  return Math.max(length + delta, 0)\n}\n\nexport function errorBanner(message: string): string {\n  return divider(c.bold(c.bgRed(` ${message} `)), null, null, c.red)\n}\n\nexport function divider(\n  text?: string,\n  left?: number | null,\n  right?: number | null,\n  color?: Formatter,\n): string {\n  const cols = getCols()\n  const c = color || ((text: string) => text)\n\n  if (text) {\n    const textLength = stripVTControlCharacters(text).length\n    if (left == null && right != null) {\n      left = cols - textLength - right\n    }\n    else {\n      left = left ?? Math.floor((cols - textLength) / 2)\n      right = cols - textLength - left\n    }\n    left = Math.max(0, left)\n    right = Math.max(0, right)\n    return `${c(F_LONG_DASH.repeat(left))}${text}${c(F_LONG_DASH.repeat(right))}`\n  }\n  return F_LONG_DASH.repeat(cols)\n}\n\nexport function formatTestPath(root: string, path: string): string {\n  if (isAbsolute(path)) {\n    path = relative(root, path)\n  }\n\n  const dir = dirname(path)\n  const ext = path.match(/(\\.(spec|test)\\.[cm]?[tj]sx?)$/)?.[0] || ''\n  const base = basename(path, ext)\n\n  return slash(c.dim(`${dir}/`) + c.bold(base)) + c.dim(ext)\n}\n\nexport function renderSnapshotSummary(\n  rootDir: string,\n  snapshots: SnapshotSummary,\n): string[] {\n  const summary: string[] = []\n\n  if (snapshots.added) {\n    summary.push(c.bold(c.green(`${snapshots.added} written`)))\n  }\n  if (snapshots.unmatched) {\n    summary.push(c.bold(c.red(`${snapshots.unmatched} failed`)))\n  }\n  if (snapshots.updated) {\n    summary.push(c.bold(c.green(`${snapshots.updated} updated `)))\n  }\n\n  if (snapshots.filesRemoved) {\n    if (snapshots.didUpdate) {\n      summary.push(c.bold(c.green(`${snapshots.filesRemoved} files removed `)))\n    }\n    else {\n      summary.push(\n        c.bold(c.yellow(`${snapshots.filesRemoved} files obsolete `)),\n      )\n    }\n  }\n\n  if (snapshots.filesRemovedList && snapshots.filesRemovedList.length) {\n    const [head, ...tail] = snapshots.filesRemovedList\n    summary.push(`${c.gray(F_DOWN_RIGHT)} ${formatTestPath(rootDir, head)}`)\n\n    tail.forEach((key) => {\n      summary.push(`  ${c.gray(F_DOT)} ${formatTestPath(rootDir, key)}`)\n    })\n  }\n\n  if (snapshots.unchecked) {\n    if (snapshots.didUpdate) {\n      summary.push(c.bold(c.green(`${snapshots.unchecked} removed`)))\n    }\n    else {\n      summary.push(c.bold(c.yellow(`${snapshots.unchecked} obsolete`)))\n    }\n\n    snapshots.uncheckedKeysByFile.forEach((uncheckedFile) => {\n      summary.push(\n        `${c.gray(F_DOWN_RIGHT)} ${formatTestPath(\n          rootDir,\n          uncheckedFile.filePath,\n        )}`,\n      )\n      uncheckedFile.keys.forEach(key =>\n        summary.push(`  ${c.gray(F_DOT)} ${key}`),\n      )\n    })\n  }\n\n  return summary\n}\n\nexport function countTestErrors(tasks: Task[]): number {\n  return tasks.reduce((c, i) => c + (i.result?.errors?.length || 0), 0)\n}\n\nexport function getStateString(\n  tasks: Task[],\n  name = 'tests',\n  showTotal = true,\n): string {\n  if (tasks.length === 0) {\n    return c.dim(`no ${name}`)\n  }\n\n  const passed = tasks.reduce((acc, i) => {\n    // Exclude expected failures from passed count\n    if (i.result?.state === 'pass' && i.type === 'test' && i.fails) {\n      return acc\n    }\n    return i.result?.state === 'pass' ? acc + 1 : acc\n  }, 0)\n  const failed = tasks.reduce((acc, i) => i.result?.state === 'fail' ? acc + 1 : acc, 0)\n  const skipped = tasks.reduce((acc, i) => i.mode === 'skip' ? acc + 1 : acc, 0)\n  const todo = tasks.reduce((acc, i) => i.mode === 'todo' ? acc + 1 : acc, 0)\n  const expectedFail = tasks.reduce((acc, i) => {\n    // Count tests that are marked as .fails and passed (which means they failed as expected)\n    if (i.result?.state === 'pass' && i.type === 'test' && i.fails) {\n      return acc + 1\n    }\n    return acc\n  }, 0)\n\n  return (\n    [\n      failed ? c.bold(c.red(`${failed} failed`)) : null,\n      passed ? c.bold(c.green(`${passed} passed`)) : null,\n      expectedFail ? c.cyan(`${expectedFail} expected fail`) : null,\n      skipped ? c.yellow(`${skipped} skipped`) : null,\n      todo ? c.gray(`${todo} todo`) : null,\n    ]\n      .filter(Boolean)\n      .join(c.dim(' | ')) + (showTotal ? c.gray(` (${tasks.length})`) : '')\n  )\n}\n\nexport function getStateSymbol(task: Task): string {\n  if (task.mode === 'todo') {\n    return todo\n  }\n\n  if (task.mode === 'skip') {\n    return skipped\n  }\n\n  if (!task.result) {\n    return pending\n  }\n\n  if (task.result.state === 'run' || task.result.state === 'queued') {\n    if (task.type === 'suite') {\n      return pointer\n    }\n  }\n\n  if (task.result.state === 'pass') {\n    return task.meta?.benchmark ? benchmarkPass : testPass\n  }\n\n  if (task.result.state === 'fail') {\n    return task.type === 'suite' ? suiteFail : taskFail\n  }\n\n  return ' '\n}\n\nexport function duration(time: number, locale = 'en-us'): string {\n  if (time < 1) {\n    return `${Number((time * 1e3).toFixed(2)).toLocaleString(locale)} ps`\n  }\n\n  if (time < 1e3) {\n    return `${Number(time.toFixed(2)).toLocaleString(locale)} ns`\n  }\n  if (time < 1e6) {\n    return `${Number((time / 1e3).toFixed(2)).toLocaleString(locale)} µs`\n  }\n  if (time < 1e9) {\n    return `${Number((time / 1e6).toFixed(2)).toLocaleString(locale)} ms`\n  }\n  if (time < 1e12) {\n    return `${Number((time / 1e9).toFixed(2)).toLocaleString(locale)} s`\n  }\n  if (time < 36e11) {\n    return `${Number((time / 60e9).toFixed(2)).toLocaleString(locale)} m`\n  }\n\n  return `${Number((time / 36e11).toFixed(2)).toLocaleString(locale)} h`\n}\n\nexport function formatTimeString(date: Date): string {\n  return date.toTimeString().split(' ')[0]\n}\n\nexport function formatTime(time: number): string {\n  if (time > 1000) {\n    return `${(time / 1000).toFixed(2)}s`\n  }\n  return `${Math.round(time)}ms`\n}\n\nexport function formatProjectName(project?: Pick<TestProject, 'name' | 'color'>, suffix = ' '): string {\n  if (!project?.name) {\n    return ''\n  }\n  if (!c.isColorSupported) {\n    return `|${project.name}|${suffix}`\n  }\n\n  let background = project.color && c[`bg${capitalize(project.color)}`]\n\n  if (!background) {\n    const index = project.name\n      .split('')\n      .reduce((acc, v, idx) => acc + v.charCodeAt(0) + idx, 0)\n\n    background = labelDefaultColors[index % labelDefaultColors.length]\n  }\n\n  return c.black(background(` ${project.name} `)) + suffix\n}\n\nexport function withLabel(color: 'red' | 'green' | 'blue' | 'cyan' | 'yellow', label: string, message?: string) {\n  const bgColor = `bg${color.charAt(0).toUpperCase()}${color.slice(1)}` as `bg${Capitalize<typeof color>}`\n  return `${c.bold(c[bgColor](` ${label} `))} ${message ? c[color](message) : ''}`\n}\n\nexport function padSummaryTitle(str: string): string {\n  return c.dim(`${str.padStart(11)} `)\n}\n\nexport function truncateString(text: string, maxLength: number): string {\n  const plainText = stripVTControlCharacters(text)\n\n  if (plainText.length <= maxLength) {\n    return text\n  }\n\n  return `${plainText.slice(0, maxLength - 1)}…`\n}\n\nfunction capitalize<T extends string>(text: T) {\n  return `${text[0].toUpperCase()}${text.slice(1)}` as Capitalize<T>\n}\n\n/**\n * Returns the singular or plural form of a word based on the count.\n */\nexport function noun(count: number, singular: string, plural: string): string {\n  if (count === 1) {\n    return singular\n  }\n\n  return plural\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/renderers/windowedRenderer.ts",
    "content": "import type { Writable } from 'node:stream'\nimport type { Vitest } from '../../core'\nimport { stripVTControlCharacters } from 'node:util'\n\nconst DEFAULT_RENDER_INTERVAL_MS = 1_000\n\nconst ESC = '\\x1B['\nconst CLEAR_LINE = `${ESC}K`\nconst MOVE_CURSOR_ONE_ROW_UP = `${ESC}1A`\nconst SYNC_START = `${ESC}?2026h`\nconst SYNC_END = `${ESC}?2026l`\n\ninterface Options {\n  logger: Vitest['logger']\n  interval?: number\n  getWindow: () => string[]\n}\n\ntype StreamType = 'output' | 'error'\n\n/**\n * Renders content of `getWindow` at the bottom of the terminal and\n * forwards all other intercepted `stdout` and `stderr` logs above it.\n */\nexport class WindowRenderer {\n  private options: Required<Options>\n  private streams!: Record<StreamType, Vitest['logger']['outputStream' | 'errorStream']['write']>\n  private buffer: { type: StreamType; message: string }[] = []\n  private renderInterval: NodeJS.Timeout | undefined = undefined\n  private renderScheduled = false\n\n  private windowHeight = 0\n  private started = false\n  private finished = false\n  private cleanups: (() => void)[] = []\n\n  constructor(options: Options) {\n    this.options = {\n      interval: DEFAULT_RENDER_INTERVAL_MS,\n      ...options,\n    }\n\n    this.streams = {\n      output: options.logger.outputStream.write.bind(options.logger.outputStream),\n      error: options.logger.errorStream.write.bind(options.logger.errorStream),\n    }\n\n    this.cleanups.push(\n      this.interceptStream(process.stdout, 'output'),\n      this.interceptStream(process.stderr, 'error'),\n    )\n\n    // Write buffered content on unexpected exits, e.g. direct `process.exit()` calls\n    this.options.logger.onTerminalCleanup(() => {\n      this.flushBuffer()\n      this.stop()\n    })\n  }\n\n  start(): void {\n    this.started = true\n    this.finished = false\n    this.renderInterval = setInterval(() => this.schedule(), this.options.interval).unref()\n  }\n\n  stop(): void {\n    this.cleanups.splice(0).map(fn => fn())\n    clearInterval(this.renderInterval)\n  }\n\n  /**\n   * Write all buffered output and stop buffering.\n   * All intercepted writes are forwarded to actual write after this.\n   */\n  finish(): void {\n    this.finished = true\n    this.flushBuffer()\n    clearInterval(this.renderInterval)\n  }\n\n  /**\n   * Queue new render update\n   */\n  schedule(): void {\n    if (!this.renderScheduled) {\n      this.renderScheduled = true\n      this.flushBuffer()\n\n      setTimeout(() => {\n        this.renderScheduled = false\n      }, 100).unref()\n    }\n  }\n\n  private flushBuffer() {\n    if (this.buffer.length === 0) {\n      return this.render()\n    }\n\n    let current\n\n    // Concatenate same types into a single render\n    for (const next of this.buffer.splice(0)) {\n      if (!current) {\n        current = next\n        continue\n      }\n\n      if (current.type !== next.type) {\n        this.render(current.message, current.type)\n        current = next\n        continue\n      }\n\n      current.message += next.message\n    }\n\n    if (current) {\n      this.render(current?.message, current?.type)\n    }\n  }\n\n  private render(message?: string, type: StreamType = 'output') {\n    if (this.finished) {\n      this.clearWindow()\n      return this.write(message || '', type)\n    }\n\n    const windowContent = this.options.getWindow()\n    const rowCount = getRenderedRowCount(windowContent, this.options.logger.getColumns())\n    let padding = this.windowHeight - rowCount\n\n    if (padding > 0 && message) {\n      padding -= getRenderedRowCount([message], this.options.logger.getColumns())\n    }\n\n    this.write(SYNC_START)\n    this.clearWindow()\n\n    if (message) {\n      this.write(message, type)\n    }\n\n    if (padding > 0) {\n      this.write('\\n'.repeat(padding))\n    }\n\n    this.write(windowContent.join('\\n'))\n    this.write(SYNC_END)\n\n    this.windowHeight = rowCount + Math.max(0, padding)\n  }\n\n  private clearWindow() {\n    if (this.windowHeight === 0) {\n      return\n    }\n\n    this.write(CLEAR_LINE)\n\n    for (let i = 1; i < this.windowHeight; i++) {\n      this.write(`${MOVE_CURSOR_ONE_ROW_UP}${CLEAR_LINE}`)\n    }\n\n    this.windowHeight = 0\n  }\n\n  private interceptStream(stream: NodeJS.WriteStream, type: StreamType) {\n    const original = stream.write\n\n    // @ts-expect-error -- not sure how 2 overloads should be typed\n    stream.write = (chunk, _, callback) => {\n      if (chunk) {\n        if (this.finished || !this.started) {\n          this.write(chunk.toString(), type)\n        }\n        else {\n          this.buffer.push({ type, message: chunk.toString() })\n        }\n      }\n      callback?.()\n    }\n\n    return function restore() {\n      stream.write = original\n    }\n  }\n\n  private write(message: string, type: 'output' | 'error' = 'output') {\n    (this.streams[type] as Writable['write'])(message)\n  }\n}\n\n/** Calculate the actual row count needed to render `rows` into `stream` */\nfunction getRenderedRowCount(rows: string[], columns: number) {\n  let count = 0\n\n  for (const row of rows) {\n    const text = stripVTControlCharacters(row)\n    count += Math.max(1, Math.ceil(text.length / columns))\n  }\n\n  return count\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/reported-tasks.ts",
    "content": "import type {\n  ImportDuration,\n  Task as RunnerTask,\n  Test as RunnerTestCase,\n  File as RunnerTestFile,\n  Suite as RunnerTestSuite,\n  SerializableRetry,\n  TaskMeta,\n  TestAnnotation,\n  TestArtifact,\n} from '@vitest/runner'\nimport type { SerializedError, TestError } from '@vitest/utils'\nimport type { DevEnvironment } from 'vite'\nimport type { TestProject } from '../project'\nimport type { TestSpecification } from '../test-specification'\n\nclass ReportedTaskImplementation {\n  /**\n   * Task instance.\n   * @internal\n   */\n  public readonly task: RunnerTask\n\n  /**\n   * The project associated with the test or suite.\n   */\n  public readonly project: TestProject\n\n  /**\n   * Unique identifier.\n   * This ID is deterministic and will be the same for the same test across multiple runs.\n   * The ID is based on the project name, module url and test order.\n   */\n  public readonly id: string\n\n  /**\n   * Location in the module where the test or suite is defined.\n   */\n  public readonly location: { line: number; column: number } | undefined\n\n  /** @internal */\n  protected constructor(\n    task: RunnerTask,\n    project: TestProject,\n  ) {\n    this.task = task\n    this.project = project\n    this.id = task.id\n    this.location = task.location\n  }\n\n  /**\n   * Checks if the test did not fail the suite.\n   * If the test is not finished yet or was skipped, it will return `true`.\n   */\n  public ok(): boolean {\n    const result = this.task.result\n    return !result || result.state !== 'fail'\n  }\n\n  /**\n   * Custom metadata that was attached to the test during its execution.\n   */\n  public meta(): TaskMeta {\n    return this.task.meta\n  }\n\n  /**\n   * Creates a new reported task instance and stores it in the project's state for future use.\n   * @internal\n   */\n  static register(task: RunnerTask, project: TestProject) {\n    const state = new this(task, project) as TestCase | TestSuite | TestModule\n    storeTask(project, task, state)\n    return state\n  }\n}\n\nexport class TestCase extends ReportedTaskImplementation {\n  #fullName: string | undefined\n\n  /** @internal */\n  declare public readonly task: RunnerTestCase\n  public readonly type = 'test'\n\n  /**\n   * Direct reference to the test module where the test or suite is defined.\n   */\n  public readonly module: TestModule\n\n  /**\n   * Name of the test.\n   */\n  public readonly name: string\n\n  /**\n   * Options that the test was initiated with.\n   */\n  public readonly options: TaskOptions\n\n  /**\n   * Parent suite. If the test was called directly inside the module, the parent will be the module itself.\n   */\n  public readonly parent: TestSuite | TestModule\n\n  /**\n   * Tags associated with the test.\n   */\n  public readonly tags: string[]\n\n  /** @internal */\n  protected constructor(task: RunnerTestCase, project: TestProject) {\n    super(task, project)\n\n    this.name = task.name\n    this.module = getReportedTask(project, task.file) as TestModule\n    const suite = this.task.suite\n    if (suite) {\n      this.parent = getReportedTask(project, suite) as TestSuite\n    }\n    else {\n      this.parent = this.module\n    }\n    this.options = buildOptions(task)\n    this.tags = this.options.tags || []\n  }\n\n  /**\n   * Full name of the test including all parent suites separated with `>`.\n   */\n  public get fullName(): string {\n    if (this.#fullName === undefined) {\n      if (this.parent.type !== 'module') {\n        this.#fullName = `${this.parent.fullName} > ${this.name}`\n      }\n      else {\n        this.#fullName = this.name\n      }\n    }\n    return this.#fullName\n  }\n\n  /**\n   * Test results.\n   * - **pending**: Test was collected, but didn't finish running yet.\n   * - **passed**: Test passed successfully\n   * - **failed**: Test failed to execute\n   * - **skipped**: Test was skipped during collection or dynamically with `ctx.skip()`.\n   */\n  public result(): TestResult {\n    const result = this.task.result\n    const mode = result?.state || this.task.mode\n\n    if (!result && (mode === 'skip' || mode === 'todo')) {\n      return {\n        state: 'skipped',\n        note: undefined,\n        errors: undefined,\n      }\n    }\n\n    if (!result || result.state === 'run' || result.state === 'queued') {\n      return {\n        state: 'pending',\n        errors: undefined,\n      }\n    }\n    const state = result.state === 'fail'\n      ? 'failed' as const\n      : result.state === 'pass'\n        ? 'passed' as const\n        : 'skipped' as const\n    if (state === 'skipped') {\n      return {\n        state,\n        note: result.note,\n        errors: undefined,\n      } satisfies TestResultSkipped\n    }\n    if (state === 'passed') {\n      return {\n        state,\n        errors: result.errors as TestError[] | undefined,\n      } satisfies TestResultPassed\n    }\n    return {\n      state,\n      errors: (result.errors || []) as TestError[],\n    } satisfies TestResultFailed\n  }\n\n  /**\n   * Test annotations added via the `task.annotate` API during the test execution.\n   */\n  public annotations(): ReadonlyArray<TestAnnotation> {\n    return [...this.task.annotations]\n  }\n\n  /**\n   * @experimental\n   *\n   * Test artifacts recorded via the `recordArtifact` API during the test execution.\n   */\n  public artifacts(): ReadonlyArray<TestArtifact> {\n    return [...this.task.artifacts]\n  }\n\n  /**\n   * Useful information about the test like duration, memory usage, etc.\n   * Diagnostic is only available after the test has finished.\n   */\n  public diagnostic(): TestDiagnostic | undefined {\n    const result = this.task.result\n    // startTime should always be available if the test has properly finished\n    if (!result || !result.startTime) {\n      return undefined\n    }\n    const duration = result.duration || 0\n    const slow = duration > this.project.globalConfig.slowTestThreshold\n    return {\n      slow,\n      heap: result.heap,\n      duration,\n      startTime: result.startTime,\n      retryCount: result.retryCount ?? 0,\n      repeatCount: result.repeatCount ?? 0,\n      flaky: !!result.retryCount && result.state === 'pass' && result.retryCount > 0,\n    }\n  }\n\n  /**\n   * Returns a new test specification that can be used to filter or run this specific test case.\n   */\n  public toTestSpecification(): TestSpecification {\n    const isTypecheck = this.task.meta.typecheck === true\n    return this.project.createSpecification(\n      this.module.moduleId,\n      { testIds: [this.id] },\n      isTypecheck ? 'typecheck' : undefined,\n    )\n  }\n}\n\nclass TestCollection {\n  #task: RunnerTestSuite | RunnerTestFile\n  #project: TestProject\n\n  constructor(task: RunnerTestSuite | RunnerTestFile, project: TestProject) {\n    this.#task = task\n    this.#project = project\n  }\n\n  /**\n   * Returns the test or suite at a specific index.\n   */\n  at(index: number): TestCase | TestSuite | undefined {\n    if (index < 0) {\n      index = this.size + index\n    }\n    return getReportedTask(this.#project, this.#task.tasks[index]) as TestCase | TestSuite | undefined\n  }\n\n  /**\n   * The number of tests and suites in the collection.\n   */\n  get size(): number {\n    return this.#task.tasks.length\n  }\n\n  /**\n   * Returns the collection in array form for easier manipulation.\n   */\n  array(): (TestCase | TestSuite)[] {\n    return Array.from(this)\n  }\n\n  /**\n   * Filters all tests that are part of this collection and its children.\n   */\n  * allTests(state?: TestState): Generator<TestCase, undefined, void> {\n    for (const child of this) {\n      if (child.type === 'suite') {\n        yield* child.children.allTests(state)\n      }\n      else if (state) {\n        const testState = child.result().state\n        if (state === testState) {\n          yield child\n        }\n      }\n      else {\n        yield child\n      }\n    }\n  }\n\n  /**\n   * Filters only the tests that are part of this collection.\n   */\n  * tests(state?: TestState): Generator<TestCase, undefined, void> {\n    for (const child of this) {\n      if (child.type !== 'test') {\n        continue\n      }\n\n      if (state) {\n        const testState = child.result().state\n        if (state === testState) {\n          yield child\n        }\n      }\n      else {\n        yield child\n      }\n    }\n  }\n\n  /**\n   * Filters only the suites that are part of this collection.\n   */\n  * suites(): Generator<TestSuite, undefined, void> {\n    for (const child of this) {\n      if (child.type === 'suite') {\n        yield child\n      }\n    }\n  }\n\n  /**\n   * Filters all suites that are part of this collection and its children.\n   */\n  * allSuites(): Generator<TestSuite, undefined, void> {\n    for (const child of this) {\n      if (child.type === 'suite') {\n        yield child\n        yield* child.children.allSuites()\n      }\n    }\n  }\n\n  * [Symbol.iterator](): Generator<TestSuite | TestCase, undefined, void> {\n    for (const task of this.#task.tasks) {\n      yield getReportedTask(this.#project, task) as TestSuite | TestCase\n    }\n  }\n}\n\nexport type { TestCollection }\n\nexport type ReportedHookContext = {\n  readonly name: 'beforeAll' | 'afterAll'\n  readonly entity: TestSuite | TestModule\n} | {\n  readonly name: 'beforeEach' | 'afterEach'\n  readonly entity: TestCase\n}\n\nabstract class SuiteImplementation extends ReportedTaskImplementation {\n  /** @internal */\n  declare public readonly task: RunnerTestSuite | RunnerTestFile\n\n  /**\n   * Collection of suites and tests that are part of this suite.\n   */\n  public readonly children: TestCollection\n\n  /** @internal */\n  protected constructor(task: RunnerTestSuite | RunnerTestFile, project: TestProject) {\n    super(task, project)\n    this.children = new TestCollection(task, project)\n  }\n\n  /**\n   * Errors that happened outside of the test run during collection, like syntax errors.\n   */\n  public errors(): SerializedError[] {\n    return (this.task.result?.errors as SerializedError[] | undefined) || []\n  }\n}\n\nexport class TestSuite extends SuiteImplementation {\n  #fullName: string | undefined\n\n  /** @internal */\n  declare public readonly task: RunnerTestSuite\n  public readonly type = 'suite'\n\n  /**\n   * Name of the test or the suite.\n   */\n  public readonly name: string\n\n  /**\n   * Direct reference to the test module where the test or suite is defined.\n   */\n  public readonly module: TestModule\n\n  /**\n   * Parent suite. If suite was called directly inside the module, the parent will be the module itself.\n   */\n  public readonly parent: TestSuite | TestModule\n\n  /**\n   * Options that suite was initiated with.\n   */\n  public readonly options: TaskOptions\n\n  /** @internal */\n  protected constructor(task: RunnerTestSuite, project: TestProject) {\n    super(task, project)\n\n    this.name = task.name\n    this.module = getReportedTask(project, task.file) as TestModule\n    const suite = this.task.suite\n    if (suite) {\n      this.parent = getReportedTask(project, suite) as TestSuite\n    }\n    else {\n      this.parent = this.module\n    }\n    this.options = buildOptions(task)\n  }\n\n  /**\n   * Checks if the suite has any failed tests.\n   * This will also return `false` if suite failed during collection.\n   */\n  declare public ok: () => boolean\n\n  /**\n   * The meta information attached to the suite during its collection or execution.\n   */\n  declare public meta: () => TaskMeta\n\n  /**\n   * Checks the running state of the suite.\n   */\n  public state(): TestSuiteState {\n    return getSuiteState(this.task)\n  }\n\n  /**\n   * Returns a new test specification that can be used to filter or run this specific test suite.\n   */\n  public toTestSpecification(): TestSpecification {\n    const isTypecheck = this.task.meta.typecheck === true\n    const testIds = [...this.children.allTests()].map(test => test.id)\n    return this.project.createSpecification(\n      this.module.moduleId,\n      { testIds },\n      isTypecheck ? 'typecheck' : undefined,\n    )\n  }\n\n  /**\n   * Full name of the suite including all parent suites separated with `>`.\n   */\n  public get fullName(): string {\n    if (this.#fullName === undefined) {\n      if (this.parent.type !== 'module') {\n        this.#fullName = `${this.parent.fullName} > ${this.name}`\n      }\n      else {\n        this.#fullName = this.name\n      }\n    }\n    return this.#fullName\n  }\n}\n\nexport class TestModule extends SuiteImplementation {\n  /** @internal */\n  declare public readonly task: RunnerTestFile\n  declare public readonly location: undefined\n  public readonly type = 'module'\n\n  /**\n   * The Vite environment that processes files on the server.\n   *\n   * Can be empty if test module did not run yet.\n   */\n  public readonly viteEnvironment: DevEnvironment | undefined\n\n  /**\n   * This is usually an absolute UNIX file path.\n   * It can be a virtual ID if the file is not on the disk.\n   * This value corresponds to the ID in the Vite's module graph.\n   */\n  public readonly moduleId: string\n\n  /**\n   * Module id relative to the project. This is the same as `task.name`.\n   */\n  public readonly relativeModuleId: string\n\n  /** @internal */\n  protected constructor(task: RunnerTestFile, project: TestProject) {\n    super(task, project)\n    this.moduleId = task.filepath\n    this.relativeModuleId = task.name\n    if (task.viteEnvironment === '__browser__') {\n      this.viteEnvironment = project.browser?.vite.environments.client\n    }\n    else if (typeof task.viteEnvironment === 'string') {\n      this.viteEnvironment = project.vite.environments[task.viteEnvironment]\n    }\n  }\n\n  /**\n   * Returns a new test specification that can be used to filter or run this specific test module.\n   */\n  public toTestSpecification(testCases?: TestCase[]): TestSpecification {\n    const isTypecheck = this.task.meta.typecheck === true\n    return this.project.createSpecification(\n      this.moduleId,\n      testCases?.length ? { testIds: testCases.map(t => t.id) } : undefined,\n      isTypecheck ? 'typecheck' : undefined,\n    )\n  }\n\n  /**\n   * Checks the running state of the test file.\n   */\n  public state(): TestModuleState {\n    const state = this.task.result?.state\n    if (state === 'queued') {\n      return 'queued'\n    }\n    return getSuiteState(this.task)\n  }\n\n  /**\n   * Checks if the module has any failed tests.\n   * This will also return `false` if module failed during collection.\n   */\n  declare public ok: () => boolean\n\n  /**\n   * The meta information attached to the module during its collection or execution.\n   */\n  declare public meta: () => TaskMeta\n\n  /**\n   * Useful information about the module like duration, memory usage, etc.\n   * If the module was not executed yet, all diagnostic values will return `0`.\n   */\n  public diagnostic(): ModuleDiagnostic {\n    const setupDuration = this.task.setupDuration || 0\n    const collectDuration = this.task.collectDuration || 0\n    const prepareDuration = this.task.prepareDuration || 0\n    const environmentSetupDuration = this.task.environmentLoad || 0\n    const duration = this.task.result?.duration || 0\n    const heap = this.task.result?.heap\n    const importDurations = this.task.importDurations ?? {}\n    return {\n      environmentSetupDuration,\n      prepareDuration,\n      collectDuration,\n      setupDuration,\n      duration,\n      heap,\n      importDurations,\n    }\n  }\n}\n\nexport interface TaskOptions {\n  readonly each: boolean | undefined\n  readonly fails: boolean | undefined\n  readonly concurrent: boolean | undefined\n  readonly shuffle: boolean | undefined\n  readonly retry: SerializableRetry | undefined\n  readonly repeats: number | undefined\n  readonly tags: string[] | undefined\n  /**\n   * Only tests have a `timeout` option.\n   */\n  readonly timeout: number | undefined\n  readonly mode: 'run' | 'only' | 'skip' | 'todo'\n}\n\nfunction buildOptions(\n  task: RunnerTestCase | RunnerTestSuite,\n): TaskOptions {\n  return {\n    each: task.each,\n    fails: task.type === 'test' && task.fails,\n    concurrent: task.concurrent,\n    shuffle: task.shuffle,\n    retry: task.retry as SerializableRetry | undefined,\n    repeats: task.repeats,\n    tags: task.tags,\n    timeout: task.type === 'test' ? task.timeout : undefined,\n    // runner types are too broad, but the public API should be more strict\n    // the queued state exists only on Files and this method is called\n    // only for tests and suites\n    mode: task.mode as TaskOptions['mode'],\n  }\n}\n\nexport type TestSuiteState = 'skipped' | 'pending' | 'failed' | 'passed'\nexport type TestModuleState = TestSuiteState | 'queued'\nexport type TestState = TestResult['state']\n\nexport type TestResult\n  = | TestResultPassed\n    | TestResultFailed\n    | TestResultSkipped\n    | TestResultPending\n\nexport interface TestResultPending {\n  /**\n   * The test was collected, but didn't finish running yet.\n   */\n  readonly state: 'pending'\n  /**\n   * Pending tests have no errors.\n   */\n  readonly errors: undefined\n}\n\nexport interface TestResultPassed {\n  /**\n   * The test passed successfully.\n   */\n  readonly state: 'passed'\n  /**\n   * Errors that were thrown during the test execution.\n   *\n   * **Note**: If test was retried successfully, errors will still be reported.\n   */\n  readonly errors: ReadonlyArray<TestError> | undefined\n}\n\nexport interface TestResultFailed {\n  /**\n   * The test failed to execute.\n   */\n  readonly state: 'failed'\n  /**\n   * Errors that were thrown during the test execution.\n   */\n  readonly errors: ReadonlyArray<TestError>\n}\n\nexport interface TestResultSkipped {\n  /**\n   * The test was skipped with `only` (on another test), `skip` or `todo` flag.\n   * You can see which one was used in the `options.mode` option.\n   */\n  readonly state: 'skipped'\n  /**\n   * Skipped tests have no errors.\n   */\n  readonly errors: undefined\n  /**\n   * A custom note passed down to `ctx.skip(note)`.\n   */\n  readonly note: string | undefined\n}\n\nexport interface TestDiagnostic {\n  /**\n   * If the duration of the test is above `slowTestThreshold`.\n   */\n  readonly slow: boolean\n  /**\n   * The amount of memory used by the test in bytes.\n   * This value is only available if the test was executed with `logHeapUsage` flag.\n   */\n  readonly heap: number | undefined\n  /**\n   * The time it takes to execute the test in ms.\n   */\n  readonly duration: number\n  /**\n   * The time in ms when the test started.\n   */\n  readonly startTime: number\n  /**\n   * The amount of times the test was retried.\n   */\n  readonly retryCount: number\n  /**\n   * The amount of times the test was repeated as configured by `repeats` option.\n   * This value can be lower if the test failed during the repeat and no `retry` is configured.\n   */\n  readonly repeatCount: number\n  /**\n   * If test passed on a second retry.\n   */\n  readonly flaky: boolean\n}\n\nexport interface ModuleDiagnostic {\n  /**\n   * The time it takes to import and initiate an environment.\n   */\n  readonly environmentSetupDuration: number\n  /**\n   * The time it takes Vitest to setup test harness (runner, mocks, etc.).\n   */\n  readonly prepareDuration: number\n  /**\n   * The time it takes to import the test module.\n   * This includes importing everything in the module and executing suite callbacks.\n   */\n  readonly collectDuration: number\n  /**\n   * The time it takes to import the setup module.\n   */\n  readonly setupDuration: number\n  /**\n   * Accumulated duration of all tests and hooks in the module.\n   */\n  readonly duration: number\n  /**\n   * The amount of memory used by the test module in bytes.\n   * This value is only available if the test was executed with `logHeapUsage` flag.\n   */\n  readonly heap: number | undefined\n  /**\n   * The time spent importing every non-externalized dependency that Vitest has processed.\n   */\n  readonly importDurations: Record<string, ImportDuration>\n}\n\nfunction storeTask(\n  project: TestProject,\n  runnerTask: RunnerTask,\n  reportedTask: TestCase | TestSuite | TestModule,\n): void {\n  project.vitest.state.reportedTasksMap.set(runnerTask, reportedTask)\n}\n\nfunction getReportedTask(\n  project: TestProject,\n  runnerTask: RunnerTask,\n): TestCase | TestSuite | TestModule {\n  const reportedTask = project.vitest.state.getReportedEntity(runnerTask)\n  if (!reportedTask) {\n    throw new Error(\n      `Task instance was not found for ${runnerTask.type} \"${runnerTask.name}\"`,\n    )\n  }\n  return reportedTask\n}\n\nfunction getSuiteState(task: RunnerTestSuite | RunnerTestFile): TestSuiteState {\n  const mode = task.mode\n  const state = task.result?.state\n  if (mode === 'skip' || mode === 'todo' || state === 'skip' || state === 'todo') {\n    return 'skipped'\n  }\n  if (state == null || state === 'run' || state === 'only') {\n    return 'pending'\n  }\n  if (state === 'fail') {\n    return 'failed'\n  }\n  if (state === 'pass') {\n    return 'passed'\n  }\n  throw new Error(`Unknown suite state: ${state}`)\n}\n\nexport function experimental_getRunnerTask(entity: TestCase): RunnerTestCase\nexport function experimental_getRunnerTask(entity: TestSuite): RunnerTestSuite\nexport function experimental_getRunnerTask(entity: TestModule): RunnerTestFile\nexport function experimental_getRunnerTask(entity: TestCase | TestSuite | TestModule): RunnerTestSuite | RunnerTestFile | RunnerTestCase\nexport function experimental_getRunnerTask(entity: TestCase | TestSuite | TestModule): RunnerTestSuite | RunnerTestFile | RunnerTestCase {\n  return entity.task\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/summary.ts",
    "content": "import type { Vitest } from '../core'\nimport type { TestSpecification } from '../test-specification'\nimport type { Reporter } from '../types/reporter'\nimport type { ReportedHookContext, TestCase, TestModule } from './reported-tasks'\nimport c from 'tinyrainbow'\nimport { F_POINTER, F_TREE_NODE_END, F_TREE_NODE_MIDDLE } from './renderers/figures'\nimport { formatProjectName, formatTime, formatTimeString, padSummaryTitle } from './renderers/utils'\nimport { WindowRenderer } from './renderers/windowedRenderer'\n\nconst DURATION_UPDATE_INTERVAL_MS = 100\nconst FINISHED_TEST_CLEANUP_TIME_MS = 1_000\n\ninterface Options {\n  verbose?: boolean\n}\n\ninterface Counter {\n  total: number\n  completed: number\n  passed: number\n  failed: number\n  skipped: number\n  todo: number\n  expectedFail: number\n}\n\ninterface SlowTask {\n  name: string\n  visible: boolean\n  startTime: number\n  onFinish: () => void\n  hook?: Omit<SlowTask, 'hook'>\n}\n\ninterface RunningModule extends Pick<Counter, 'total' | 'completed'> {\n  filename: TestModule['task']['name']\n  projectName: TestModule['project']['name']\n  projectColor: TestModule['project']['color']\n  hook?: Omit<SlowTask, 'hook'>\n  tests: Map<TestCase['id'], SlowTask>\n  typecheck: boolean\n}\n\n/**\n * Reporter extension that renders summary and forwards all other logs above itself.\n * Intended to be used by other reporters, not as a standalone reporter.\n */\nexport class SummaryReporter implements Reporter {\n  private ctx!: Vitest\n  private options!: Options\n  private renderer!: WindowRenderer\n\n  private modules = emptyCounters()\n  private tests = emptyCounters()\n  private maxParallelTests = 0\n\n  /** Currently running test modules, may include finished test modules too */\n  private runningModules = new Map<TestModule['id'], RunningModule>()\n\n  /** ID of finished `this.runningModules` that are currently being shown */\n  private finishedModules = new Map<TestModule['id'], NodeJS.Timeout>()\n\n  private startTime = ''\n  private currentTime = 0\n  private duration = 0\n  private durationInterval: NodeJS.Timeout | undefined = undefined\n\n  onInit(ctx: Vitest, options: Options = {}): void {\n    this.ctx = ctx\n\n    this.options = {\n      verbose: false,\n      ...options,\n    }\n\n    this.renderer = new WindowRenderer({\n      logger: ctx.logger,\n      getWindow: () => this.createSummary(),\n    })\n\n    this.ctx.onClose(() => {\n      clearInterval(this.durationInterval)\n      this.renderer.stop()\n    })\n  }\n\n  onTestRunStart(specifications: ReadonlyArray<TestSpecification>): void {\n    this.runningModules.clear()\n    this.finishedModules.clear()\n    this.modules = emptyCounters()\n    this.tests = emptyCounters()\n\n    this.startTimers()\n    this.renderer.start()\n\n    this.modules.total = specifications.length\n  }\n\n  onTestRunEnd(): void {\n    this.runningModules.clear()\n    this.finishedModules.clear()\n    this.renderer.finish()\n    clearInterval(this.durationInterval)\n  }\n\n  onTestModuleQueued(module: TestModule): void {\n    // When new test module starts, take the place of previously finished test module, if any\n    if (this.finishedModules.size) {\n      const finished = this.finishedModules.keys().next().value\n      this.removeTestModule(finished)\n    }\n\n    this.runningModules.set(module.id, initializeStats(module))\n    this.renderer.schedule()\n  }\n\n  onTestModuleCollected(module: TestModule): void {\n    let stats = this.runningModules.get(module.id)\n\n    if (!stats) {\n      stats = initializeStats(module)\n      this.runningModules.set(module.id, stats)\n    }\n\n    const total = Array.from(module.children.allTests()).length\n    this.tests.total += total\n    stats.total = total\n\n    this.maxParallelTests = Math.max(this.maxParallelTests, this.runningModules.size)\n    this.renderer.schedule()\n  }\n\n  onHookStart(options: ReportedHookContext): void {\n    const stats = this.getHookStats(options)\n\n    if (!stats) {\n      return\n    }\n\n    const hook = {\n      name: options.name,\n      visible: false,\n      startTime: performance.now(),\n      onFinish: () => {},\n    }\n    stats.hook?.onFinish?.()\n    stats.hook = hook\n\n    const timeout = setTimeout(() => {\n      hook.visible = true\n    }, this.ctx.config.slowTestThreshold).unref()\n\n    hook.onFinish = () => clearTimeout(timeout)\n  }\n\n  onHookEnd(options: ReportedHookContext): void {\n    const stats = this.getHookStats(options)\n\n    if (stats?.hook?.name !== options.name) {\n      return\n    }\n\n    stats.hook.onFinish()\n    stats.hook.visible = false\n  }\n\n  onTestCaseReady(test: TestCase): void {\n    // Track slow running tests only on verbose mode\n    if (!this.options.verbose) {\n      return\n    }\n\n    const stats = this.runningModules.get(test.module.id)\n\n    if (!stats || stats.tests.has(test.id)) {\n      return\n    }\n\n    const slowTest: SlowTask = {\n      name: test.name,\n      visible: false,\n      startTime: performance.now(),\n      onFinish: () => {},\n    }\n\n    const timeout = setTimeout(() => {\n      slowTest.visible = true\n    }, this.ctx.config.slowTestThreshold).unref()\n\n    slowTest.onFinish = () => {\n      slowTest.hook?.onFinish()\n      clearTimeout(timeout)\n    }\n\n    stats.tests.set(test.id, slowTest)\n  }\n\n  onTestCaseResult(test: TestCase): void {\n    const stats = this.runningModules.get(test.module.id)\n\n    if (!stats) {\n      return\n    }\n\n    stats.tests.get(test.id)?.onFinish()\n    stats.tests.delete(test.id)\n\n    stats.completed++\n    const result = test.result()\n\n    if (result?.state === 'passed') {\n      // Check if this is an expected failure (test.fails && passed)\n      if (test.options.fails) {\n        this.tests.expectedFail++\n      }\n      else {\n        this.tests.passed++\n      }\n    }\n    else if (result?.state === 'failed') {\n      this.tests.failed++\n    }\n    else if (!result?.state || result?.state === 'skipped') {\n      if (test.options.mode === 'todo') {\n        this.tests.todo++\n      }\n      else {\n        this.tests.skipped++\n      }\n    }\n\n    this.renderer.schedule()\n  }\n\n  onTestModuleEnd(module: TestModule): void {\n    const state = module.state()\n    this.modules.completed++\n\n    if (state === 'passed') {\n      this.modules.passed++\n    }\n    else if (state === 'failed') {\n      this.modules.failed++\n    }\n    else if (module.task.mode === 'todo' && state === 'skipped') {\n      this.modules.todo++\n    }\n    else if (state === 'skipped') {\n      this.modules.skipped++\n    }\n\n    const left = this.modules.total - this.modules.completed\n\n    // Keep finished tests visible in summary for a while if there are more tests left.\n    // When a new test starts in onTestModuleQueued it will take this ones place.\n    // This reduces flickering by making summary more stable.\n    if (left > this.maxParallelTests) {\n      this.finishedModules.set(module.id, setTimeout(() => {\n        this.removeTestModule(module.id)\n      }, FINISHED_TEST_CLEANUP_TIME_MS).unref())\n    }\n    else {\n      // Run is about to end as there are less tests left than whole run had parallel at max.\n      // Remove finished test immediately.\n      this.removeTestModule(module.id)\n    }\n\n    this.renderer.schedule()\n  }\n\n  private getHookStats({ entity }: ReportedHookContext) {\n    // Track slow running hooks only on verbose mode\n    if (!this.options.verbose) {\n      return\n    }\n\n    const module = entity.type === 'module' ? entity : entity.module\n    const stats = this.runningModules.get(module.id)\n\n    if (!stats) {\n      return\n    }\n\n    return entity.type === 'test' ? stats.tests.get(entity.id) : stats\n  }\n\n  private createSummary() {\n    const summary = ['']\n\n    for (const testFile of Array.from(this.runningModules.values()).sort(sortRunningModules)) {\n      const typecheck = testFile.typecheck ? `${c.bgBlue(c.bold(' TS '))} ` : ''\n      summary.push(\n        c.bold(c.yellow(` ${F_POINTER} `))\n        + formatProjectName({ name: testFile.projectName, color: testFile.projectColor })\n        + typecheck\n        + testFile.filename\n        + c.dim(!testFile.completed && !testFile.total\n          ? ' [queued]'\n          : ` ${testFile.completed}/${testFile.total}`),\n      )\n\n      const slowTasks = [\n        testFile.hook,\n        ...testFile.tests.values(),\n      ].filter((t): t is SlowTask => t != null && t.visible)\n\n      for (const [index, task] of slowTasks.entries()) {\n        const elapsed = this.currentTime - task.startTime\n        const icon = index === slowTasks.length - 1 ? F_TREE_NODE_END : F_TREE_NODE_MIDDLE\n\n        summary.push(\n          c.bold(c.yellow(`   ${icon} `))\n          + task.name\n          + c.bold(c.yellow(` ${formatTime(Math.max(0, elapsed))}`)),\n        )\n\n        if (task.hook?.visible) {\n          summary.push(c.bold(c.yellow(`      ${F_TREE_NODE_END} `)) + task.hook.name)\n        }\n      }\n    }\n\n    if (this.runningModules.size > 0) {\n      summary.push('')\n    }\n\n    summary.push(padSummaryTitle('Test Files') + getStateString(this.modules))\n    summary.push(padSummaryTitle('Tests') + getStateString(this.tests))\n    summary.push(padSummaryTitle('Start at') + this.startTime)\n    summary.push(padSummaryTitle('Duration') + formatTime(this.duration))\n\n    summary.push('')\n\n    return summary\n  }\n\n  private startTimers() {\n    const start = performance.now()\n    this.startTime = formatTimeString(new Date())\n\n    this.durationInterval = setInterval(() => {\n      this.currentTime = performance.now()\n      this.duration = this.currentTime - start\n    }, DURATION_UPDATE_INTERVAL_MS).unref()\n  }\n\n  private removeTestModule(id?: TestModule['id']) {\n    if (!id) {\n      return\n    }\n\n    const testFile = this.runningModules.get(id)\n    testFile?.hook?.onFinish()\n    testFile?.tests?.forEach(test => test.onFinish())\n\n    this.runningModules.delete(id)\n\n    clearTimeout(this.finishedModules.get(id))\n    this.finishedModules.delete(id)\n  }\n}\n\nfunction emptyCounters(): Counter {\n  return { completed: 0, passed: 0, failed: 0, skipped: 0, todo: 0, expectedFail: 0, total: 0 }\n}\n\nfunction getStateString(entry: Counter) {\n  return (\n    [\n      entry.failed ? c.bold(c.red(`${entry.failed} failed`)) : null,\n      c.bold(c.green(`${entry.passed} passed`)),\n      entry.expectedFail ? c.cyan(`${entry.expectedFail} expected fail`) : null,\n      entry.skipped ? c.yellow(`${entry.skipped} skipped`) : null,\n      entry.todo ? c.gray(`${entry.todo} todo`) : null,\n    ]\n      .filter(Boolean)\n      .join(c.dim(' | ')) + c.gray(` (${entry.total})`)\n  )\n}\n\nfunction sortRunningModules(a: RunningModule, b: RunningModule) {\n  if ((a.projectName || '') > (b.projectName || '')) {\n    return 1\n  }\n\n  if ((a.projectName || '') < (b.projectName || '')) {\n    return -1\n  }\n\n  return a.filename.localeCompare(b.filename)\n}\n\nfunction initializeStats(module: TestModule): RunningModule {\n  return {\n    total: 0,\n    completed: 0,\n    filename: module.task.name,\n    projectName: module.project.name,\n    projectColor: module.project.color,\n    tests: new Map(),\n    typecheck: !!module.task.meta.typecheck,\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/tap-flat.ts",
    "content": "import type { Task } from '@vitest/runner'\nimport type { Vitest } from '../core'\nimport type { TestModule } from './reported-tasks'\nimport { TapReporter } from './tap'\n\nfunction flattenTasks(task: Task, baseName = ''): Task[] {\n  const base = baseName ? `${baseName} > ` : ''\n\n  if (task.type === 'suite' && task.tasks.length > 0) {\n    return task.tasks.flatMap(child =>\n      flattenTasks(child, `${base}${task.name}`),\n    )\n  }\n  else {\n    return [\n      {\n        ...task,\n        name: `${base}${task.name}`,\n      },\n    ]\n  }\n}\n\nexport class TapFlatReporter extends TapReporter {\n  onInit(ctx: Vitest): void {\n    super.onInit(ctx)\n  }\n\n  onTestRunEnd(testModules: ReadonlyArray<TestModule>): void {\n    this.ctx.logger.log('TAP version 13')\n\n    const flatTasks = testModules.flatMap(testModule => flattenTasks(testModule.task))\n\n    this.logTasks(flatTasks)\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/tap.ts",
    "content": "import type { Task } from '@vitest/runner'\nimport type { ParsedStack, TestError } from '@vitest/utils'\nimport type { Vitest } from '../core'\nimport type { Reporter } from '../types/reporter'\nimport type { TestModule } from './reported-tasks'\nimport { parseErrorStacktrace } from '../../utils/source-map'\nimport { IndentedLogger } from './renderers/indented-logger'\n\nfunction yamlString(str: string | undefined): string {\n  if (!str) {\n    return ''\n  }\n  return `\"${str.replace(/\"/g, '\\\\\"')}\"`\n}\n\nfunction tapString(str: string): string {\n  return str\n    .replace(/\\\\/g, '\\\\\\\\') // escape slashes\n    .replace(/#/g, '\\\\#') // escape #\n    .replace(/\\n/g, ' ') // remove newlines\n}\n\nexport class TapReporter implements Reporter {\n  protected ctx!: Vitest\n  private logger!: IndentedLogger\n\n  onInit(ctx: Vitest): void {\n    this.ctx = ctx\n    this.logger = new IndentedLogger(ctx.logger.log.bind(ctx.logger))\n  }\n\n  static getComment(task: Task): string {\n    if (task.mode === 'skip') {\n      return ' # SKIP'\n    }\n    else if (task.mode === 'todo') {\n      return ' # TODO'\n    }\n    else if (task.result?.duration != null) {\n      return ` # time=${task.result.duration.toFixed(2)}ms`\n    }\n    else {\n      return ''\n    }\n  }\n\n  private logErrorDetails(error: TestError, stack?: ParsedStack) {\n    const errorName = error.name || 'Unknown Error'\n    this.logger.log(`name: ${yamlString(String(errorName))}`)\n    this.logger.log(`message: ${yamlString(String(error.message))}`)\n\n    if (stack) {\n      // For compatibility with tap-mocha-reporter\n      this.logger.log(\n        `stack: ${yamlString(`${stack.file}:${stack.line}:${stack.column}`)}`,\n      )\n    }\n  }\n\n  protected logTasks(tasks: Task[]): void {\n    this.logger.log(`1..${tasks.length}`)\n\n    for (const [i, task] of tasks.entries()) {\n      const id = i + 1\n\n      const ok\n        = task.result?.state === 'pass'\n          || task.mode === 'skip'\n          || task.mode === 'todo'\n          ? 'ok'\n          : 'not ok'\n\n      const comment = TapReporter.getComment(task)\n\n      if (task.type === 'suite' && task.tasks.length > 0) {\n        this.logger.log(`${ok} ${id} - ${tapString(task.name)}${comment} {`)\n\n        this.logger.indent()\n        this.logTasks(task.tasks)\n        this.logger.unindent()\n\n        this.logger.log('}')\n      }\n      else {\n        this.logger.log(`${ok} ${id} - ${tapString(task.name)}${comment}`)\n\n        const project = this.ctx.getProjectByName(task.file.projectName || '')\n\n        if (task.type === 'test' && task.annotations) {\n          this.logger.indent()\n          task.annotations.forEach(({ type, message }) => {\n            this.logger.log(`# ${type}: ${message}`)\n          })\n          this.logger.unindent()\n        }\n\n        if (task.result?.state === 'fail' && task.result.errors) {\n          this.logger.indent()\n\n          task.result.errors.forEach((error) => {\n            const stacks = task.file.pool === 'browser'\n              ? (project.browser?.parseErrorStacktrace(error) || [])\n              : parseErrorStacktrace(error, {\n                  frameFilter: this.ctx.config.onStackTrace,\n                })\n            const stack = stacks[0]\n\n            this.logger.log('---')\n            this.logger.log('error:')\n\n            this.logger.indent()\n            this.logErrorDetails(error)\n            this.logger.unindent()\n\n            if (stack) {\n              this.logger.log(\n                `at: ${yamlString(\n                  `${stack.file}:${stack.line}:${stack.column}`,\n                )}`,\n              )\n            }\n\n            if (error.showDiff) {\n              this.logger.log(`actual: ${yamlString(error.actual)}`)\n              this.logger.log(`expected: ${yamlString(error.expected)}`)\n            }\n          })\n\n          this.logger.log('...')\n          this.logger.unindent()\n        }\n      }\n    }\n  }\n\n  onTestRunEnd(testModules: ReadonlyArray<TestModule>): void {\n    const files = testModules.map(testModule => testModule.task)\n\n    this.logger.log('TAP version 13')\n\n    this.logTasks(files)\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/tree.ts",
    "content": "import { DefaultReporter } from './default'\n\nexport class TreeReporter extends DefaultReporter {\n  protected verbose = true\n  renderSucceed = true\n}\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/utils.ts",
    "content": "import type { ModuleRunner } from 'vite/module-runner'\nimport type { Vitest } from '../core'\nimport type { ResolvedConfig } from '../types/config'\nimport type { Reporter } from '../types/reporter'\nimport type { BlobReporter } from './blob'\nimport type { BenchmarkBuiltinReporters, BenchmarkReporter, BuiltinReporters, DefaultReporter, DotReporter, GithubActionsReporter, HangingProcessReporter, JsonReporter, JUnitReporter, TapReporter } from './index'\nimport { BenchmarkReportsMap, ReportersMap } from './index'\n\nasync function loadCustomReporterModule<C extends Reporter>(\n  path: string,\n  runner: ModuleRunner,\n): Promise<new (options?: unknown) => C> {\n  let customReporterModule: { default: new () => C }\n  try {\n    customReporterModule = await runner.import(path)\n  }\n  catch (customReporterModuleError) {\n    throw new Error(`Failed to load custom Reporter from ${path}`, {\n      cause: customReporterModuleError as Error,\n    })\n  }\n\n  if (\n    customReporterModule.default === null\n    || customReporterModule.default === undefined\n  ) {\n    throw new Error(\n      `Custom reporter loaded from ${path} was not the default export`,\n    )\n  }\n\n  return customReporterModule.default\n}\n\nfunction createReporters(\n  reporterReferences: ResolvedConfig['reporters'],\n  ctx: Vitest,\n): Promise<Array<Reporter | DefaultReporter | BlobReporter | DotReporter | JsonReporter | TapReporter | JUnitReporter | HangingProcessReporter | GithubActionsReporter>> {\n  const runner = ctx.runner\n  const promisedReporters = reporterReferences.map(\n    async (referenceOrInstance) => {\n      if (Array.isArray(referenceOrInstance)) {\n        const [reporterName, reporterOptions] = referenceOrInstance\n\n        if (reporterName === 'html') {\n          await ctx.packageInstaller.ensureInstalled('@vitest/ui', ctx.config.root, ctx.version)\n          const CustomReporter = await loadCustomReporterModule(\n            '@vitest/ui/reporter',\n            runner,\n          )\n          return new CustomReporter(reporterOptions)\n        }\n        else if (reporterName in ReportersMap) {\n          const BuiltinReporter\n            = ReportersMap[reporterName as BuiltinReporters]\n          return new BuiltinReporter(reporterOptions)\n        }\n        else {\n          const CustomReporter = await loadCustomReporterModule(\n            reporterName,\n            runner,\n          )\n          return new CustomReporter(reporterOptions)\n        }\n      }\n\n      return referenceOrInstance\n    },\n  )\n  return Promise.all(promisedReporters)\n}\n\nfunction createBenchmarkReporters(\n  reporterReferences: Array<string | Reporter | BenchmarkBuiltinReporters>,\n  runner: ModuleRunner,\n): Promise<(Reporter | BenchmarkReporter)[]> {\n  const promisedReporters = reporterReferences.map(\n    async (referenceOrInstance) => {\n      if (typeof referenceOrInstance === 'string') {\n        if (referenceOrInstance in BenchmarkReportsMap) {\n          const BuiltinReporter\n            = BenchmarkReportsMap[\n              referenceOrInstance as BenchmarkBuiltinReporters\n            ]\n          return new BuiltinReporter()\n        }\n        else {\n          const CustomReporter = await loadCustomReporterModule(\n            referenceOrInstance,\n            runner,\n          )\n          return new CustomReporter()\n        }\n      }\n      return referenceOrInstance\n    },\n  )\n  return Promise.all(promisedReporters)\n}\n\nexport { createBenchmarkReporters, createReporters }\n"
  },
  {
    "path": "packages/vitest/src/node/reporters/verbose.ts",
    "content": "import type { TestCase, TestModule } from './reported-tasks'\nimport { getTestName } from '@vitest/runner/utils'\nimport c from 'tinyrainbow'\nimport { DefaultReporter } from './default'\nimport { F_RIGHT } from './renderers/figures'\nimport { separator } from './renderers/utils'\n\nexport class VerboseReporter extends DefaultReporter {\n  protected verbose = true\n  renderSucceed = true\n\n  printTestModule(_module: TestModule): void {\n    // don't print test module, only print tests\n  }\n\n  onTestCaseResult(test: TestCase): void {\n    super.onTestCaseResult(test)\n\n    const testResult = test.result()\n\n    if (this.ctx.config.hideSkippedTests && testResult.state === 'skipped' && test.options.mode !== 'todo') {\n      return\n    }\n\n    let title = ` ${this.getEntityPrefix(test)} `\n\n    title += test.module.task.name\n    if (test.location) {\n      title += c.dim(`:${test.location.line}:${test.location.column}`)\n    }\n    title += separator\n\n    title += getTestName(test.task, separator)\n    title += this.getTestCaseSuffix(test)\n\n    this.log(title)\n\n    if (testResult.state === 'failed') {\n      testResult.errors.forEach(error => this.log(c.red(`   ${F_RIGHT} ${error.message}`)))\n    }\n\n    if (test.annotations().length) {\n      this.log()\n      this.printAnnotations(test, 'log', 3)\n      this.log()\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/resolver.ts",
    "content": "import type { ResolvedConfig, ServerDepsOptions } from './types/config'\nimport { existsSync, promises as fsp } from 'node:fs'\nimport { isBuiltin } from 'node:module'\nimport { pathToFileURL } from 'node:url'\nimport { KNOWN_ASSET_RE } from '@vitest/utils/constants'\nimport { cleanUrl } from '@vitest/utils/helpers'\nimport { findNearestPackageData } from '@vitest/utils/resolver'\nimport * as esModuleLexer from 'es-module-lexer'\nimport { dirname, extname, join, resolve } from 'pathe'\nimport { isWindows } from '../utils/env'\n\nexport class VitestResolver {\n  public readonly options: ExternalizeOptions\n  private externalizeConcurrentCache = new Map<string, Promise<string | false | undefined>>()\n  public externalizeCache: Map<string, string | false | undefined> = new Map()\n\n  constructor(cacheDir: string, config: ResolvedConfig) {\n    // sorting to make cache consistent\n    const inline = config.server.deps?.inline\n    if (Array.isArray(inline)) {\n      inline.sort()\n    }\n    const external = config.server.deps?.external\n    if (Array.isArray(external)) {\n      external.sort()\n    }\n    this.options = {\n      moduleDirectories: config.deps.moduleDirectories?.sort(),\n      inlineFiles: config.setupFiles.flatMap((file) => {\n        if (file.startsWith('file://')) {\n          return file\n        }\n        const resolvedId = resolve(file)\n        return [resolvedId, pathToFileURL(resolvedId).href]\n      }),\n      cacheDir,\n      inline,\n      external,\n    }\n  }\n\n  public wasExternalized(file: string): string | false {\n    const normalizedFile = normalizeId(file)\n    if (!this.externalizeCache.has(normalizedFile)) {\n      return false\n    }\n    return this.externalizeCache.get(normalizedFile) ?? false\n  }\n\n  public async shouldExternalize(file: string): Promise<string | false | undefined> {\n    const normalizedFile = normalizeId(file)\n    if (this.externalizeCache.has(normalizedFile)) {\n      return this.externalizeCache.get(normalizedFile)!\n    }\n\n    return shouldExternalize(normalizeId(file), this.options, this.externalizeConcurrentCache).then((result) => {\n      this.externalizeCache.set(normalizedFile, result)\n      return result\n    }).finally(() => {\n      this.externalizeConcurrentCache.delete(normalizedFile)\n    })\n  }\n}\n\nfunction normalizeId(id: string) {\n  if (id.startsWith('/@fs/')) {\n    id = id.slice(isWindows ? 5 : 4)\n  }\n  return id\n}\n\ninterface ExternalizeOptions extends ServerDepsOptions {\n  moduleDirectories?: string[]\n  inlineFiles?: string[]\n  cacheDir?: string\n}\n\nconst BUILTIN_EXTENSIONS = new Set(['.mjs', '.cjs', '.node', '.wasm'])\n\nconst ESM_EXT_RE = /\\.(es|esm|esm-browser|esm-bundler|es6|module)\\.js$/\nconst ESM_FOLDER_RE = /\\/(es|esm)\\/(.*\\.js)$/\n\nconst defaultInline = [\n  /virtual:/,\n  /\\.[mc]?ts$/,\n\n  // special Vite query strings\n  /[?&](init|raw|url|inline)\\b/,\n  // Vite returns a string for assets imports, even if it's inside \"node_modules\"\n  KNOWN_ASSET_RE,\n\n  /^(?!.*node_modules).*\\.mjs$/,\n  /^(?!.*node_modules).*\\.cjs\\.js$/,\n  // Vite client\n  /vite\\w*\\/dist\\/client\\/env.mjs/,\n]\n\nconst depsExternal = [\n  /\\/node_modules\\/.*\\.cjs\\.js$/,\n  /\\/node_modules\\/.*\\.mjs$/,\n]\n\nexport function guessCJSversion(id: string): string | undefined {\n  if (id.match(ESM_EXT_RE)) {\n    for (const i of [\n      id.replace(ESM_EXT_RE, '.mjs'),\n      id.replace(ESM_EXT_RE, '.umd.js'),\n      id.replace(ESM_EXT_RE, '.cjs.js'),\n      id.replace(ESM_EXT_RE, '.js'),\n    ]) {\n      if (existsSync(i)) {\n        return i\n      }\n    }\n  }\n  if (id.match(ESM_FOLDER_RE)) {\n    for (const i of [\n      id.replace(ESM_FOLDER_RE, '/umd/$1'),\n      id.replace(ESM_FOLDER_RE, '/cjs/$1'),\n      id.replace(ESM_FOLDER_RE, '/lib/$1'),\n      id.replace(ESM_FOLDER_RE, '/$1'),\n    ]) {\n      if (existsSync(i)) {\n        return i\n      }\n    }\n  }\n}\n\n// The code from https://github.com/unjs/mlly/blob/c5bcca0cda175921344fd6de1bc0c499e73e5dac/src/syntax.ts#L51-L98\nasync function isValidNodeImport(id: string) {\n  // clean url to strip off `?v=...` query etc.\n  // node can natively import files with query params, so externalizing them is safe.\n  id = cleanUrl(id)\n\n  const extension = extname(id)\n\n  if (BUILTIN_EXTENSIONS.has(extension)) {\n    return true\n  }\n\n  if (extension !== '.js') {\n    return false\n  }\n\n  id = id.replace('file:///', '')\n\n  const package_ = findNearestPackageData(dirname(id))\n\n  if (package_.type === 'module') {\n    return true\n  }\n\n  if (/\\.(?:\\w+-)?esm?(?:-\\w+)?\\.js$|\\/esm?\\//.test(id)) {\n    return false\n  }\n\n  try {\n    await esModuleLexer.init\n    const code = await fsp.readFile(id, 'utf8')\n    const [, , , hasModuleSyntax] = esModuleLexer.parse(code)\n    return !hasModuleSyntax\n  }\n  catch {\n    return false\n  }\n}\n\nexport async function shouldExternalize(\n  id: string,\n  options: ExternalizeOptions,\n  cache: Map<string, Promise<string | false | undefined>>,\n): Promise<string | false | undefined> {\n  if (!cache.has(id)) {\n    cache.set(id, _shouldExternalize(id, options))\n  }\n  return cache.get(id)!\n}\n\nasync function _shouldExternalize(\n  id: string,\n  options?: ExternalizeOptions,\n): Promise<string | false | undefined> {\n  if (isBuiltin(id)) {\n    return id\n  }\n\n  // data: should be processed by native import,\n  // since it is a feature of ESM.\n  // also externalize network imports since nodejs allows it when --experimental-network-imports\n  if (id.startsWith('data:') || /^(?:https?:)?\\/\\//.test(id)) {\n    return id\n  }\n\n  const moduleDirectories = options?.moduleDirectories || ['/node_modules/']\n\n  if (matchPattern(id, moduleDirectories, options?.inline)) {\n    return false\n  }\n  if (options?.inlineFiles && options?.inlineFiles.includes(id)) {\n    return false\n  }\n  if (matchPattern(id, moduleDirectories, options?.external)) {\n    return id\n  }\n\n  // Unless the user explicitly opted to inline them, externalize Vite deps.\n  // They are too big to inline by default.\n  if (options?.cacheDir && id.includes(options.cacheDir)) {\n    return id\n  }\n\n  const isLibraryModule = moduleDirectories.some(dir => id.includes(dir))\n  const guessCJS = isLibraryModule && options?.fallbackCJS\n  id = guessCJS ? guessCJSversion(id) || id : id\n\n  if (matchPattern(id, moduleDirectories, defaultInline)) {\n    return false\n  }\n  if (matchPattern(id, moduleDirectories, depsExternal)) {\n    return id\n  }\n\n  if (isLibraryModule && (await isValidNodeImport(id))) {\n    return id\n  }\n}\n\nfunction matchPattern(\n  id: string,\n  moduleDirectories: string[],\n  patterns?: (string | RegExp)[] | true,\n) {\n  if (patterns == null) {\n    return false\n  }\n  if (patterns === true) {\n    return true\n  }\n  for (const ex of patterns) {\n    if (typeof ex === 'string') {\n      if (moduleDirectories.some(dir => id.includes(join(dir, ex)))) {\n        return true\n      }\n    }\n    else {\n      if (ex.test(id)) {\n        return true\n      }\n    }\n  }\n  return false\n}\n"
  },
  {
    "path": "packages/vitest/src/node/sequencers/BaseSequencer.ts",
    "content": "import type { Vitest } from '../core'\nimport type { TestSpecification } from '../test-specification'\nimport type { TestSequencer } from './types'\nimport { slash } from '@vitest/utils/helpers'\nimport { relative, resolve } from 'pathe'\nimport { hash } from '../hash'\n\nexport class BaseSequencer implements TestSequencer {\n  protected ctx: Vitest\n\n  constructor(ctx: Vitest) {\n    this.ctx = ctx\n  }\n\n  // async so it can be extended by other sequelizers\n  public async shard(files: TestSpecification[]): Promise<TestSpecification[]> {\n    const { config } = this.ctx\n    const { index, count } = config.shard!\n    const [shardStart, shardEnd] = this.calculateShardRange(files.length, index, count)\n    return [...files]\n      .map((spec) => {\n        const fullPath = resolve(slash(config.root), slash(spec.moduleId))\n        const specPath = fullPath?.slice(config.root.length)\n        return {\n          spec,\n          hash: hash('sha1', specPath, 'hex'),\n        }\n      })\n      .sort((a, b) => (a.hash < b.hash ? -1 : a.hash > b.hash ? 1 : 0))\n      .slice(shardStart, shardEnd)\n      .map(({ spec }) => spec)\n  }\n\n  // async so it can be extended by other sequelizers\n  public async sort(files: TestSpecification[]): Promise<TestSpecification[]> {\n    const cache = this.ctx.cache\n    return [...files].sort((a, b) => {\n      // \"sequence.groupOrder\" is higher priority\n      const groupOrderDiff = a.project.config.sequence.groupOrder - b.project.config.sequence.groupOrder\n      if (groupOrderDiff !== 0) {\n        return groupOrderDiff\n      }\n\n      // Projects run sequential\n      if (a.project.name !== b.project.name) {\n        return a.project.name < b.project.name ? -1 : 1\n      }\n\n      // Isolated run first\n      if (a.project.config.isolate && !b.project.config.isolate) {\n        return -1\n      }\n      if (!a.project.config.isolate && b.project.config.isolate) {\n        return 1\n      }\n\n      const keyA = `${a.project.name}:${relative(this.ctx.config.root, a.moduleId)}`\n      const keyB = `${b.project.name}:${relative(this.ctx.config.root, b.moduleId)}`\n\n      const aState = cache.getFileTestResults(keyA)\n      const bState = cache.getFileTestResults(keyB)\n\n      if (!aState || !bState) {\n        const statsA = cache.getFileStats(keyA)\n        const statsB = cache.getFileStats(keyB)\n\n        // run unknown first\n        if (!statsA || !statsB) {\n          return !statsA && statsB ? -1 : !statsB && statsA ? 1 : 0\n        }\n\n        // run larger files first\n        return statsB.size - statsA.size\n      }\n\n      // run failed first\n      if (aState.failed && !bState.failed) {\n        return -1\n      }\n      if (!aState.failed && bState.failed) {\n        return 1\n      }\n\n      // run longer first\n      return bState.duration - aState.duration\n    })\n  }\n\n  // Calculate distributed shard range [start, end] distributed equally\n  private calculateShardRange(filesCount: number, index: number, count: number): [number, number] {\n    const baseShardSize = Math.floor(filesCount / count)\n    const remainderTestFilesCount = filesCount % count\n    if (remainderTestFilesCount >= index) {\n      const shardSize = baseShardSize + 1\n      const shardStart = shardSize * (index - 1)\n      const shardEnd = shardSize * index\n      return [shardStart, shardEnd]\n    }\n\n    const shardStart = remainderTestFilesCount * (baseShardSize + 1) + (index - remainderTestFilesCount - 1) * baseShardSize\n    const shardEnd = shardStart + baseShardSize\n    return [shardStart, shardEnd]\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/sequencers/RandomSequencer.ts",
    "content": "import type { TestSpecification } from '../test-specification'\nimport { shuffle } from '@vitest/utils/helpers'\nimport { BaseSequencer } from './BaseSequencer'\n\nexport class RandomSequencer extends BaseSequencer {\n  public async sort(files: TestSpecification[]): Promise<TestSpecification[]> {\n    const { sequence } = this.ctx.config\n\n    return shuffle(files, sequence.seed)\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/sequencers/types.ts",
    "content": "import type { Awaitable } from '@vitest/utils'\nimport type { Vitest } from '../core'\nimport type { TestSpecification } from '../test-specification'\n\nexport interface TestSequencer {\n  /**\n   * Slicing tests into shards. Will be run before `sort`.\n   * Only run, if `shard` is defined.\n   */\n  shard: (files: TestSpecification[]) => Awaitable<TestSpecification[]>\n  sort: (files: TestSpecification[]) => Awaitable<TestSpecification[]>\n}\n\nexport interface TestSequencerConstructor {\n  new (ctx: Vitest): TestSequencer\n}\n"
  },
  {
    "path": "packages/vitest/src/node/specifications.ts",
    "content": "import type { Vitest } from './core'\nimport type { TestProject } from './project'\nimport type { TestSpecification } from './test-specification'\nimport { existsSync } from 'node:fs'\nimport { join, relative, resolve } from 'pathe'\nimport pm from 'picomatch'\nimport { isWindows } from '../utils/env'\nimport { groupFilters, parseFilter } from './cli/filter'\nimport { GitNotFoundError, IncludeTaskLocationDisabledError, LocationFilterFileNotFoundError } from './errors'\n\nexport class VitestSpecifications {\n  private readonly _cachedSpecs = new Map<string, TestSpecification[]>()\n\n  constructor(private vitest: Vitest) {}\n\n  public getModuleSpecifications(moduleId: string): TestSpecification[] {\n    const _cached = this.getCachedSpecifications(moduleId)\n    if (_cached) {\n      return _cached\n    }\n\n    const specs: TestSpecification[] = []\n    for (const project of this.vitest.projects) {\n      if (project._isCachedTestFile(moduleId)) {\n        specs.push(project.createSpecification(moduleId))\n      }\n      if (project._isCachedTypecheckFile(moduleId)) {\n        specs.push(project.createSpecification(moduleId, [], 'typescript'))\n      }\n    }\n    specs.forEach(spec => this.ensureSpecificationCached(spec))\n    return specs\n  }\n\n  public async getRelevantTestSpecifications(filters: string[] = []): Promise<TestSpecification[]> {\n    return this.filterTestsBySource(\n      await this.globTestSpecifications(filters),\n    )\n  }\n\n  public async globTestSpecifications(filters: string[] = []): Promise<TestSpecification[]> {\n    const files: TestSpecification[] = []\n    const dir = process.cwd()\n    const parsedFilters = filters.map(f => parseFilter(f))\n\n    // Require includeTaskLocation when a location filter is passed\n    if (\n      !this.vitest.config.includeTaskLocation\n      && parsedFilters.some(f => f.lineNumber !== undefined)\n    ) {\n      throw new IncludeTaskLocationDisabledError()\n    }\n\n    const testLines = groupFilters(parsedFilters.map(\n      f => ({ ...f, filename: resolve(dir, f.filename) }),\n    ))\n\n    // Key is file and val specifies whether we have matched this file with testLocation\n    const testLocHasMatch: { [f: string]: boolean } = {}\n\n    await Promise.all(this.vitest.projects.map(async (project) => {\n      const { testFiles, typecheckTestFiles } = await project.globTestFiles(\n        parsedFilters.map(f => f.filename),\n      )\n\n      testFiles.forEach((file) => {\n        const lines = testLines[file]\n        testLocHasMatch[file] = true\n\n        const spec = project.createSpecification(file, lines)\n        this.ensureSpecificationCached(spec)\n        files.push(spec)\n      })\n      typecheckTestFiles.forEach((file) => {\n        const lines = testLines[file]\n        testLocHasMatch[file] = true\n\n        const spec = project.createSpecification(file, lines, 'typescript')\n        this.ensureSpecificationCached(spec)\n        files.push(spec)\n      })\n    }))\n\n    Object.entries(testLines).forEach(([filepath, loc]) => {\n      if (loc.length !== 0 && !testLocHasMatch[filepath]) {\n        throw new LocationFilterFileNotFoundError(\n          relative(dir, filepath),\n        )\n      }\n    })\n\n    return files\n  }\n\n  public clearCache(moduleId?: string): void {\n    if (moduleId) {\n      this._cachedSpecs.delete(moduleId)\n    }\n    else {\n      this._cachedSpecs.clear()\n    }\n  }\n\n  private getCachedSpecifications(moduleId: string): TestSpecification[] | undefined {\n    return this._cachedSpecs.get(moduleId)\n  }\n\n  public ensureSpecificationCached(spec: TestSpecification): TestSpecification[] {\n    const file = spec.moduleId\n    const specs = this._cachedSpecs.get(file) || []\n    const index = specs.findIndex(_s => _s.project === spec.project && _s.pool === spec.pool)\n    if (index === -1) {\n      specs.push(spec)\n      this._cachedSpecs.set(file, specs)\n    }\n    else {\n      specs.splice(index, 1, spec)\n    }\n    return specs\n  }\n\n  private async filterTestsBySource(specs: TestSpecification[]): Promise<TestSpecification[]> {\n    if (this.vitest.config.changed && !this.vitest.config.related) {\n      const { VitestGit } = await import('./git')\n      const vitestGit = new VitestGit(this.vitest.config.root)\n      const related = await vitestGit.findChangedFiles({\n        changedSince: this.vitest.config.changed,\n      })\n      if (!related) {\n        process.exitCode = 1\n        throw new GitNotFoundError()\n      }\n      this.vitest.config.related = Array.from(new Set(related))\n    }\n\n    const related = this.vitest.config.related\n    if (!related) {\n      return specs\n    }\n\n    const forceRerunTriggers = this.vitest.config.forceRerunTriggers\n    const matcher = forceRerunTriggers.length ? pm(forceRerunTriggers) : undefined\n    if (matcher && related.some(file => matcher(file))) {\n      return specs\n    }\n\n    // don't run anything if no related sources are found\n    // if we are in watch mode, we want to process all tests\n    if (!this.vitest.config.watch && !related.length) {\n      return []\n    }\n\n    const testGraphs = await Promise.all(\n      specs.map(async (spec) => {\n        const deps = await this.getTestDependencies(spec)\n        return [spec, deps] as const\n      }),\n    )\n\n    const runningTests: TestSpecification[] = []\n\n    for (const [specification, deps] of testGraphs) {\n      // if deps or the test itself were changed\n      if (related.some(path => path === specification.moduleId || deps.has(path))) {\n        runningTests.push(specification)\n      }\n    }\n\n    return runningTests\n  }\n\n  private async getTestDependencies(spec: TestSpecification, deps = new Set<string>()): Promise<Set<string>> {\n    const addImports = async (project: TestProject, filepath: string) => {\n      if (deps.has(filepath)) {\n        return\n      }\n      deps.add(filepath)\n\n      const mod = project.vite.environments.ssr.moduleGraph.getModuleById(filepath)\n      const transformed = mod?.transformResult || await project.vite.environments.ssr.transformRequest(filepath)\n      if (!transformed) {\n        return\n      }\n      const dependencies = [...transformed.deps || [], ...transformed.dynamicDeps || []]\n      await Promise.all(dependencies.map(async (dep) => {\n        const fsPath = dep.startsWith('/@fs/')\n          ? dep.slice(isWindows ? 5 : 4)\n          : join(project.config.root, dep)\n        if (!fsPath.includes('node_modules') && !deps.has(fsPath) && existsSync(fsPath)) {\n          await addImports(project, fsPath)\n        }\n      }))\n    }\n\n    await addImports(spec.project, spec.moduleId)\n    deps.delete(spec.moduleId)\n\n    return deps\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/state.ts",
    "content": "import type { File, FileSpecification, Task, TaskResultPack } from '@vitest/runner'\nimport type { AsyncLeak, UserConsoleLog } from '../types/general'\nimport type { TestProject } from './project'\nimport type { MergedBlobs } from './reporters/blob'\nimport type { OnUnhandledErrorCallback } from './types/config'\nimport { createFileTask, generateFileHash } from '@vitest/runner/utils'\nimport { relative } from 'pathe'\nimport { defaultBrowserPort } from '../constants'\nimport { TestCase, TestModule, TestSuite } from './reporters/reported-tasks'\n\nfunction isAggregateError(err: unknown): err is AggregateError {\n  if (typeof AggregateError !== 'undefined' && err instanceof AggregateError) {\n    return true\n  }\n\n  return err instanceof Error && 'errors' in err\n}\n\nexport class StateManager {\n  filesMap: Map<string, File[]> = new Map()\n  pathsSet: Set<string> = new Set()\n  idMap: Map<string, Task> = new Map()\n  taskFileMap: WeakMap<Task, File> = new WeakMap()\n  errorsSet: Set<unknown> = new Set()\n  leakSet: Set<AsyncLeak> = new Set()\n  reportedTasksMap: WeakMap<Task, TestModule | TestCase | TestSuite> = new WeakMap()\n  blobs?: MergedBlobs\n  transformTime = 0\n\n  metadata: Record<string, {\n    externalized: Record<string, string>\n    duration: Record<string, number[]>\n    tmps: Record<string, string>\n    dumpDir?: string\n    outline?: {\n      externalized: number\n      inlined: number\n    }\n  }> = {}\n\n  onUnhandledError?: OnUnhandledErrorCallback\n\n  /** @internal */\n  _data = {\n    browserLastPort: defaultBrowserPort,\n    timeoutIncreased: false,\n  }\n\n  constructor(\n    options: {\n      onUnhandledError?: OnUnhandledErrorCallback\n    },\n  ) {\n    this.onUnhandledError = options.onUnhandledError\n  }\n\n  catchError(error: unknown, type: string): void {\n    if (isAggregateError(error)) {\n      return error.errors.forEach(error => this.catchError(error, type))\n    }\n\n    if (typeof error === 'object' && error !== null) {\n      (error as Record<string, unknown>).type = type\n    }\n    else {\n      error = { type, message: error }\n    }\n\n    const _error = error as Record<string, any>\n    if (_error && typeof _error === 'object' && _error.code === 'VITEST_PENDING') {\n      const task = this.idMap.get(_error.taskId)\n      if (task) {\n        task.mode = 'skip'\n        task.result ??= { state: 'skip' }\n        task.result.state = 'skip'\n        task.result.note = _error.note\n      }\n      return\n    }\n\n    if (!this.onUnhandledError || this.onUnhandledError(error as any) !== false) {\n      this.errorsSet.add(error)\n    }\n  }\n\n  catchLeaks(leaks: AsyncLeak[]): void {\n    leaks.forEach(leak => this.leakSet.add(leak))\n  }\n\n  clearErrors(): void {\n    this.errorsSet.clear()\n    this.leakSet.clear()\n  }\n\n  getUnhandledErrors(): unknown[] {\n    return Array.from(this.errorsSet)\n  }\n\n  getPaths(): string[] {\n    return Array.from(this.pathsSet)\n  }\n\n  /**\n   * Return files that were running or collected.\n   */\n  getFiles(keys?: string[]): File[] {\n    if (keys) {\n      return keys\n        .map(key => this.filesMap.get(key)!)\n        .flat()\n        .filter(file => file && !file.local)\n    }\n    return Array.from(this.filesMap.values()).flat().filter(file => !file.local).sort((f1, f2) => {\n      // print typecheck files first\n      if (f1.meta?.typecheck && f2.meta?.typecheck) {\n        return 0\n      }\n      if (f1.meta?.typecheck) {\n        return -1\n      }\n      return 1\n    })\n  }\n\n  getTestModules(keys?: string[]): TestModule[] {\n    return this.getFiles(keys).map(file => this.getReportedEntity(file) as TestModule)\n  }\n\n  getFilepaths(): string[] {\n    return Array.from(this.filesMap.keys())\n  }\n\n  getFailedFilepaths(): string[] {\n    return this.getFiles()\n      .filter(i => i.result?.state === 'fail')\n      .map(i => i.filepath)\n  }\n\n  collectPaths(paths: string[] = []): void {\n    paths.forEach((path) => {\n      this.pathsSet.add(path)\n    })\n  }\n\n  collectFiles(project: TestProject, files: File[] = []): void {\n    files.forEach((file) => {\n      const existing = this.filesMap.get(file.filepath) || []\n      const otherFiles = existing.filter(\n        i => i.projectName !== file.projectName || i.meta.typecheck !== file.meta.typecheck,\n      )\n      const currentFile = existing.find(\n        i => i.projectName === file.projectName,\n      )\n      // keep logs for the previous file because it should always be initiated before the collections phase\n      // which means that all logs are collected during the collection and not inside tests\n      if (currentFile) {\n        file.logs = currentFile.logs\n      }\n      otherFiles.push(file)\n      this.filesMap.set(file.filepath, otherFiles)\n      this.updateId(file, project)\n    })\n  }\n\n  clearFiles(\n    project: TestProject,\n    paths: string[] = [],\n  ): void {\n    paths.forEach((path) => {\n      const files = this.filesMap.get(path)\n      const fileTask = createFileTask(\n        path,\n        project.config.root,\n        project.config.name,\n      )\n      fileTask.local = true\n      TestModule.register(fileTask, project)\n      this.idMap.set(fileTask.id, fileTask)\n      if (!files) {\n        this.filesMap.set(path, [fileTask])\n        return\n      }\n      const filtered = files.filter(\n        file => file.projectName !== project.config.name,\n      )\n      // always keep a File task, so we can associate logs with it\n      if (!filtered.length) {\n        this.filesMap.set(path, [fileTask])\n      }\n      else {\n        this.filesMap.set(path, [...filtered, fileTask])\n      }\n    })\n  }\n\n  updateId(task: Task, project: TestProject): void {\n    if (this.idMap.get(task.id) === task) {\n      return\n    }\n\n    if (task.type === 'suite' && 'filepath' in task) {\n      TestModule.register(task, project)\n    }\n    else if (task.type === 'suite') {\n      TestSuite.register(task, project)\n    }\n    else {\n      TestCase.register(task, project)\n    }\n\n    this.idMap.set(task.id, task)\n    if (task.type === 'suite') {\n      task.tasks.forEach((task) => {\n        this.updateId(task, project)\n      })\n    }\n  }\n\n  getReportedEntity(task: Task): TestModule | TestCase | TestSuite | undefined {\n    return this.reportedTasksMap.get(task)\n  }\n\n  getReportedEntityById(taskId: string): TestModule | TestCase | TestSuite | undefined {\n    const task = this.idMap.get(taskId)\n    return task ? this.reportedTasksMap.get(task) : undefined\n  }\n\n  updateTasks(packs: TaskResultPack[]): void {\n    for (const [id, result, meta] of packs) {\n      const task = this.idMap.get(id)\n      if (task) {\n        task.result = result\n        task.meta = meta\n        // skipped with new PendingError\n        if (result?.state === 'skip') {\n          task.mode = 'skip'\n        }\n      }\n    }\n  }\n\n  updateUserLog(log: UserConsoleLog): void {\n    const task = log.taskId && this.idMap.get(log.taskId)\n    if (task) {\n      if (!task.logs) {\n        task.logs = []\n      }\n      task.logs.push(log)\n    }\n  }\n\n  getCountOfFailedTests(): number {\n    return Array.from(this.idMap.values()).filter(\n      t => t.result?.state === 'fail',\n    ).length\n  }\n\n  cancelFiles(files: FileSpecification[], project: TestProject): void {\n    // if we don't filter existing modules, they will be overriden by `collectFiles`\n    const nonRegisteredFiles = files.filter(({ filepath }) => {\n      const relativePath = relative(project.config.root, filepath)\n      const id = generateFileHash(relativePath, project.name)\n      return !this.idMap.has(id)\n    })\n\n    this.collectFiles(\n      project,\n      nonRegisteredFiles.map(file =>\n        createFileTask(file.filepath, project.config.root, project.config.name),\n      ),\n    )\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/stdin.ts",
    "content": "import type { File, Task } from '@vitest/runner'\nimport type { Writable } from 'node:stream'\nimport type { Vitest } from './core'\nimport type { FilterObject } from './watch-filter'\nimport readline from 'node:readline'\nimport { isTestCase } from '@vitest/runner/utils'\nimport { relative, resolve } from 'pathe'\nimport prompt from 'prompts'\nimport c from 'tinyrainbow'\nimport { stdout } from '../utils/base'\nimport { isWindows } from '../utils/env'\nimport { WatchFilter } from './watch-filter'\n\nconst keys = [\n  [['a', 'return'], 'rerun all tests'],\n  ['r', 'rerun current pattern tests'],\n  ['f', 'rerun only failed tests'],\n  ['u', 'update snapshot'],\n  ['p', 'filter by a filename'],\n  ['t', 'filter by a test name regex pattern'],\n  ['w', 'filter by a project name'],\n  ['b', 'start the browser server if not started yet'],\n  ['q', 'quit'],\n]\nconst cancelKeys = ['space', 'c', 'h', ...keys.map(key => key[0]).flat()]\n\nexport function printShortcutsHelp(): void {\n  stdout().write(\n    `\n${c.bold('  Watch Usage')}\n${keys\n  .map(\n    i =>\n      c.dim('  press ')\n      + c.reset([i[0]].flat().map(c.bold).join(', '))\n      + c.dim(` to ${i[1]}`),\n  )\n  .join('\\n')}\n`,\n  )\n}\n\nfunction* traverseFilteredTestNames(parentName: string, filter: RegExp, t: Task): Generator<FilterObject> {\n  if (isTestCase(t)) {\n    if (t.name.match(filter)) {\n      const displayName = `${parentName} > ${t.name}`\n      yield { key: t.name, toString: () => displayName }\n    }\n  }\n  else {\n    parentName = parentName.length ? `${parentName} > ${t.name}` : t.name\n    for (const task of t.tasks) {\n      yield* traverseFilteredTestNames(parentName, filter, task)\n    }\n  }\n}\n\nfunction* getFilteredTestNames(pattern: string, suite: File[]): Generator<FilterObject> {\n  try {\n    const reg = new RegExp(pattern)\n    // TODO: we cannot run tests per workspace yet: filtering files\n    const files = new Set<string>()\n    for (const file of suite) {\n      if (!files.has(file.name)) {\n        files.add(file.name)\n        yield* traverseFilteredTestNames('', reg, file)\n      }\n    }\n  }\n  catch {\n    // `new RegExp` may throw error when input is invalid regexp\n  }\n}\n\nexport function registerConsoleShortcuts(\n  ctx: Vitest,\n  stdin: NodeJS.ReadStream | undefined = process.stdin,\n  stdout: NodeJS.WriteStream | Writable,\n) {\n  let latestFilename = ''\n\n  async function _keypressHandler(str: string, key: any) {\n    // Cancel run and exit when ctrl-c or esc is pressed.\n    // If cancelling takes long and key is pressed multiple times, exit forcefully.\n    if (\n      str === '\\x03'\n      || str === '\\x1B'\n      || (key && key.ctrl && key.name === 'c')\n    ) {\n      if (!ctx.isCancelling) {\n        ctx.logger.log(\n          c.red('Cancelling test run. Press CTRL+c again to exit forcefully.\\n'),\n        )\n        process.exitCode = 130\n\n        await ctx.cancelCurrentRun('keyboard-input')\n      }\n      return ctx.exit(true)\n    }\n\n    // window not support suspend\n    if (!isWindows && key && key.ctrl && key.name === 'z') {\n      process.kill(process.ppid, 'SIGTSTP')\n      process.kill(process.pid, 'SIGTSTP')\n      return\n    }\n\n    const name = key?.name\n\n    if (ctx.runningPromise) {\n      if (cancelKeys.includes(name)) {\n        await ctx.cancelCurrentRun('keyboard-input')\n      }\n      return\n    }\n\n    // quit\n    if (name === 'q') {\n      return ctx.exit(true)\n    }\n\n    // help\n    if (name === 'h') {\n      return printShortcutsHelp()\n    }\n    // update snapshot\n    if (name === 'u') {\n      return ctx.updateSnapshot()\n    }\n    // rerun all tests\n    if (name === 'a' || name === 'return') {\n      const files = await ctx._globTestFilepaths()\n      return ctx.changeNamePattern('', files, 'rerun all tests')\n    }\n    // rerun current pattern tests\n    if (name === 'r') {\n      return ctx.rerunFiles()\n    }\n    // rerun only failed tests\n    if (name === 'f') {\n      return ctx.rerunFailed()\n    }\n    // change project filter\n    if (name === 'w') {\n      return inputProjectName()\n    }\n    // change testNamePattern\n    if (name === 't') {\n      return inputNamePattern()\n    }\n    // change fileNamePattern\n    if (name === 'p') {\n      return inputFilePattern()\n    }\n    if (name === 'b') {\n      await ctx._initBrowserServers()\n      ctx.projects.forEach((project) => {\n        ctx.logger.log()\n        ctx.logger.printBrowserBanner(project)\n      })\n      return null\n    }\n  }\n\n  async function keypressHandler(str: string, key: any) {\n    await _keypressHandler(str, key)\n  }\n\n  async function inputNamePattern() {\n    off()\n    const watchFilter = new WatchFilter<'object'>(\n      'Input test name pattern (RegExp)',\n      stdin,\n      stdout,\n    )\n    const filter = await watchFilter.filter((str: string) => {\n      return [...getFilteredTestNames(str, ctx.state.getFiles())]\n    })\n\n    on()\n\n    if (typeof filter === 'undefined') {\n      return\n    }\n\n    const files = ctx.state.getFilepaths()\n    // if running in standalone mode, Vitest instance doesn't know about any test file\n    const cliFiles\n      = ctx.config.standalone && !files.length\n        ? await ctx._globTestFilepaths()\n        : undefined\n\n    await ctx.changeNamePattern(\n      filter?.trim() || '',\n      cliFiles,\n      'change pattern',\n    )\n  }\n\n  async function inputProjectName() {\n    off()\n    const { filter = '' }: { filter: string } = await prompt([\n      {\n        name: 'filter',\n        type: 'text',\n        message: 'Input a single project name',\n        initial: ctx.config.project[0] || '',\n      },\n    ])\n    on()\n    await ctx.changeProjectName(filter.trim())\n  }\n\n  async function inputFilePattern() {\n    off()\n\n    const watchFilter = new WatchFilter(\n      'Input filename pattern',\n      stdin,\n      stdout,\n    )\n\n    const filter = await watchFilter.filter(async (str: string) => {\n      const specifications = await ctx.globTestSpecifications([str])\n\n      return specifications\n        .map(specification => relative(ctx.config.root, specification.moduleId))\n        .filter((file, index, all) => all.indexOf(file) === index)\n    })\n\n    on()\n\n    if (typeof filter === 'undefined') {\n      return\n    }\n\n    latestFilename = filter?.trim() || ''\n    const lastResults = watchFilter.getLastResults()\n\n    await ctx.changeFilenamePattern(\n      latestFilename,\n      filter && lastResults.length\n        ? lastResults.map(i => resolve(ctx.config.root, i))\n        : undefined,\n    )\n  }\n\n  let rl: readline.Interface | undefined\n  function on() {\n    off()\n    rl = readline.createInterface({ input: stdin, escapeCodeTimeout: 50 })\n    readline.emitKeypressEvents(stdin, rl)\n    if (stdin.isTTY) {\n      stdin.setRawMode(true)\n    }\n    stdin.on('keypress', keypressHandler)\n  }\n\n  function off() {\n    rl?.close()\n    rl = undefined\n    stdin.removeListener('keypress', keypressHandler)\n    if (stdin.isTTY) {\n      stdin.setRawMode(false)\n    }\n  }\n\n  on()\n\n  return function cleanup(): void {\n    off()\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/tags.ts",
    "content": "import type { TestTagDefinition } from '@vitest/runner'\nimport type { TestProject } from './project'\n\nexport function populateProjectsTags(rootProject: TestProject, projects: TestProject[]): void {\n  // Include root project if not already in the list\n  const allProjects = projects.includes(rootProject) ? projects : [rootProject, ...projects]\n\n  // Collect all tags from all projects (first definition wins)\n  const globalTags = new Map<string, TestTagDefinition>()\n  for (const project of allProjects) {\n    for (const tag of project.config.tags || []) {\n      if (!globalTags.has(tag.name)) {\n        globalTags.set(tag.name, tag)\n      }\n    }\n  }\n\n  // Add missing tags to each project (without overriding local definitions)\n  for (const project of allProjects) {\n    const projectTagNames = new Set(project.config.tags.map(t => t.name))\n    for (const [tagName, tagDef] of globalTags) {\n      if (!projectTagNames.has(tagName)) {\n        project.config.tags.push(tagDef)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/test-run.ts",
    "content": "import type {\n  File as RunnerTestFile,\n  TaskEventPack,\n  TaskResultPack,\n  TaskUpdateEvent,\n  TestAttachment,\n} from '@vitest/runner'\nimport type { TaskEventData, TestArtifact } from '@vitest/runner/types/tasks'\nimport type { SerializedError } from '@vitest/utils'\nimport type { UserConsoleLog } from '../types/general'\nimport type { Vitest } from './core'\nimport type { TestProject } from './project'\nimport type { ReportedHookContext, TestCase, TestCollection, TestModule } from './reporters/reported-tasks'\nimport type { TestSpecification } from './test-specification'\nimport type { TestRunEndReason } from './types/reporter'\nimport assert from 'node:assert'\nimport { createHash } from 'node:crypto'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { copyFile, mkdir, writeFile } from 'node:fs/promises'\nimport { isPrimitive } from '@vitest/utils/helpers'\nimport { serializeValue } from '@vitest/utils/serialize'\nimport { parseErrorStacktrace } from '@vitest/utils/source-map'\nimport { extractSourcemapFromFile } from '@vitest/utils/source-map/node'\nimport mime from 'mime/lite'\nimport { basename, extname, resolve } from 'pathe'\n\nexport class TestRun {\n  constructor(private vitest: Vitest) {}\n\n  async start(specifications: TestSpecification[]): Promise<void> {\n    const filepaths = specifications.map(spec => spec.moduleId)\n    this.vitest.state.collectPaths(filepaths)\n\n    await this.vitest.report('onTestRunStart', [...specifications])\n  }\n\n  async enqueued(project: TestProject, file: RunnerTestFile): Promise<void> {\n    this.vitest.state.collectFiles(project, [file])\n    const testModule = this.vitest.state.getReportedEntity(file) as TestModule\n    await this.vitest.report('onTestModuleQueued', testModule)\n  }\n\n  async collected(project: TestProject, files: RunnerTestFile[]): Promise<void> {\n    this.vitest.state.collectFiles(project, files)\n    await Promise.all(\n      files.map((file) => {\n        const testModule = this.vitest.state.getReportedEntity(file) as TestModule\n        return this.vitest.report('onTestModuleCollected', testModule)\n      }),\n    )\n  }\n\n  async log(log: UserConsoleLog): Promise<void> {\n    this.vitest.state.updateUserLog(log)\n    await this.vitest.report('onUserConsoleLog', log)\n  }\n\n  async recordArtifact<Artifact extends TestArtifact>(testId: string, artifact: Artifact): Promise<Artifact> {\n    const task = this.vitest.state.idMap.get(testId)\n    const entity = task && this.vitest.state.getReportedEntity(task)\n\n    assert(task && entity, `Entity must be found for task ${task?.name || testId}`)\n    assert(entity.type === 'test', `Artifacts can only be recorded on a test, instead got ${entity.type}`)\n\n    // annotations won't resolve as artifacts for backwards compatibility until next major\n    if (artifact.type === 'internal:annotation') {\n      await this.resolveTestAttachment(entity, artifact.annotation.attachment, artifact.annotation.message)\n\n      entity.task.annotations.push(artifact.annotation)\n\n      await this.vitest.report('onTestCaseAnnotate', entity, artifact.annotation)\n\n      return artifact\n    }\n\n    if (Array.isArray(artifact.attachments)) {\n      await Promise.all(\n        artifact.attachments.map(attachment => this.resolveTestAttachment(entity, attachment)),\n      )\n    }\n\n    entity.task.artifacts.push(artifact)\n\n    await this.vitest.report('onTestCaseArtifactRecord', entity, artifact)\n\n    return artifact\n  }\n\n  async updated(update: TaskResultPack[], events: TaskEventPack[]): Promise<void> {\n    this.syncUpdateStacks(update)\n    this.vitest.state.updateTasks(update)\n\n    for (const [id, event, data] of events) {\n      await this.reportEvent(id, event, data).catch((error) => {\n        this.vitest.state.catchError(serializeValue(error), 'Unhandled Reporter Error')\n      })\n    }\n\n    // TODO: what is the order or reports here?\n    // \"onTaskUpdate\" in parallel with others or before all or after all?\n    // TODO: error handling - what happens if custom reporter throws an error?\n    await this.vitest.report('onTaskUpdate', update, events)\n  }\n\n  async end(specifications: TestSpecification[], errors: unknown[], coverage?: unknown): Promise<void> {\n    if (coverage) {\n      await this.vitest.report('onCoverage', coverage)\n    }\n\n    // specification won't have the File task if they were filtered by the --shard command\n    const modules = specifications.map(spec => spec.testModule).filter(s => s != null)\n\n    const state: TestRunEndReason = this.vitest.isCancelling\n      ? 'interrupted'\n      // by this point, the run will be marked as failed if there are any errors,\n      // should it be done by testRun.end?\n      : this.hasFailed(modules)\n        ? 'failed'\n        : 'passed'\n\n    if (state !== 'passed') {\n      process.exitCode = 1\n    }\n\n    await this.vitest.report('onTestRunEnd', modules, [...errors] as SerializedError[], state)\n\n    for (const project in this.vitest.state.metadata) {\n      const meta = this.vitest.state.metadata[project]\n      if (!meta?.dumpDir) {\n        continue\n      }\n      const path = resolve(meta.dumpDir, 'vitest-metadata.json')\n      meta.outline = {\n        externalized: Object.keys(meta.externalized).length,\n        inlined: Object.keys(meta.tmps).length,\n      }\n      await writeFile(\n        path,\n        JSON.stringify(meta, null, 2),\n        'utf-8',\n      )\n      this.vitest.logger.log(`Metadata written to ${path}`)\n    }\n  }\n\n  private hasFailed(modules: TestModule[]) {\n    if (!modules.length) {\n      return !this.vitest.config.passWithNoTests\n    }\n\n    return modules.some(m => !m.ok())\n  }\n\n  // make sure the error always has a \"stacks\" property\n  private syncUpdateStacks(update: TaskResultPack[]): void {\n    update.forEach(([taskId, result]) => {\n      const task = this.vitest.state.idMap.get(taskId)\n      const isBrowser = task && task.file.pool === 'browser'\n\n      result?.errors?.forEach((error) => {\n        if (isPrimitive(error)) {\n          return\n        }\n\n        const project = this.vitest.getProjectByName(task!.file.projectName || '')\n        if (isBrowser) {\n          error.stacks = project.browser?.parseErrorStacktrace(error, {\n            frameFilter: project.config.onStackTrace,\n          }) || []\n        }\n        else {\n          error.stacks = parseErrorStacktrace(error, {\n            frameFilter: project.config.onStackTrace,\n            getSourceMap(file) {\n              // This only handles external modules since\n              // source map is already applied for inlined modules.\n              // Module node exists due to Vitest fetch module,\n              // but transformResult should be empty for external modules.\n              const mod = project.vite.moduleGraph.getModuleById(file)\n              if (!mod?.transformResult && existsSync(file)) {\n                const code = readFileSync(file, 'utf-8')\n                const result = extractSourcemapFromFile(code, file)\n                return result?.map\n              }\n            },\n          })\n        }\n      })\n    })\n  }\n\n  private async reportEvent(id: string, event: TaskUpdateEvent, data: TaskEventData | undefined) {\n    const task = this.vitest.state.idMap.get(id)\n    const entity = task && this.vitest.state.getReportedEntity(task)\n\n    assert(task && entity, `Entity must be found for task ${task?.name || id}`)\n\n    if (event === 'suite-failed-early' && entity.type === 'module') {\n      // the file failed during import\n      await this.vitest.report('onTestModuleStart', entity)\n      await this.vitest.report('onTestModuleEnd', entity)\n      return\n    }\n\n    if (event === 'suite-prepare' && entity.type === 'suite') {\n      return await this.vitest.report('onTestSuiteReady', entity)\n    }\n\n    if (event === 'suite-prepare' && entity.type === 'module') {\n      return await this.vitest.report('onTestModuleStart', entity)\n    }\n\n    if (event === 'suite-finished') {\n      assert(entity.type === 'suite' || entity.type === 'module', 'Entity type must be suite or module')\n\n      if (entity.state() === 'skipped') {\n        // everything inside suite or a module is skipped,\n        // so we won't get any children events\n        // we need to report everything manually\n        await this.reportChildren(entity.children)\n      }\n\n      if (entity.type === 'module') {\n        await this.vitest.report('onTestModuleEnd', entity)\n      }\n      else {\n        await this.vitest.report('onTestSuiteResult', entity)\n      }\n\n      return\n    }\n\n    if (event === 'test-cancel' && entity.type === 'test') {\n      // This is used to just update state of the task\n      return\n    }\n\n    if (event === 'test-prepare' && entity.type === 'test') {\n      return await this.vitest.report('onTestCaseReady', entity)\n    }\n\n    if (event === 'test-finished' && entity.type === 'test') {\n      return await this.vitest.report('onTestCaseResult', entity)\n    }\n\n    if (event.startsWith('before-hook') || event.startsWith('after-hook')) {\n      const isBefore = event.startsWith('before-hook')\n\n      const hook: ReportedHookContext = entity.type === 'test'\n        ? {\n            name: isBefore ? 'beforeEach' : 'afterEach',\n            entity,\n          }\n        : {\n            name: isBefore ? 'beforeAll' : 'afterAll',\n            entity,\n          }\n\n      if (event.endsWith('-start')) {\n        await this.vitest.report('onHookStart', hook)\n      }\n      else {\n        await this.vitest.report('onHookEnd', hook)\n      }\n\n      // this can only happen in --merge-reports, and annotation is already resolved\n      if (event === 'test-annotation') {\n        const annotation = data?.annotation\n        assert(annotation && entity.type === 'test')\n        await this.vitest.report('onTestCaseAnnotate', entity, annotation)\n      }\n    }\n  }\n\n  private async resolveTestAttachment(test: TestCase, attachment: TestAttachment | undefined, filename?: string): Promise<TestAttachment | undefined> {\n    const project = test.project\n    if (!attachment) {\n      return attachment\n    }\n    const path = attachment.path\n    if (path && !path.startsWith('http://') && !path.startsWith('https://')) {\n      const currentPath = resolve(project.config.root, path)\n      const hash = createHash('sha1').update(currentPath).digest('hex')\n      const newPath = resolve(\n        project.config.attachmentsDir,\n        `${filename ? `${sanitizeFilePath(filename)}-` : ''}${hash}${extname(currentPath)}`,\n      )\n      if (!existsSync(project.config.attachmentsDir)) {\n        await mkdir(project.config.attachmentsDir, { recursive: true })\n      }\n      await copyFile(currentPath, newPath)\n\n      attachment.path = newPath\n      const contentType = attachment.contentType ?? mime.getType(basename(currentPath))\n      attachment.contentType = contentType || undefined\n    }\n    return attachment\n  }\n\n  private async reportChildren(children: TestCollection) {\n    for (const child of children) {\n      if (child.type === 'test') {\n        await this.vitest.report('onTestCaseReady', child)\n        await this.vitest.report('onTestCaseResult', child)\n      }\n      else {\n        await this.vitest.report('onTestSuiteReady', child)\n        await this.reportChildren(child.children)\n        await this.vitest.report('onTestSuiteResult', child)\n      }\n    }\n  }\n}\n\nfunction sanitizeFilePath(s: string): string {\n  // eslint-disable-next-line no-control-regex\n  return s.replace(/[\\x00-\\x2C\\x2E\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7F]+/g, '-')\n}\n"
  },
  {
    "path": "packages/vitest/src/node/test-specification.ts",
    "content": "import type { SerializedTestSpecification } from '../runtime/types/utils'\nimport type { TestProject } from './project'\nimport type { TestModule } from './reporters/reported-tasks'\nimport type { Pool } from './types/config'\nimport { generateFileHash } from '@vitest/runner/utils'\nimport { relative } from 'pathe'\n\nexport interface TestSpecificationOptions {\n  testNamePattern?: RegExp\n  testIds?: string[]\n  testLines?: number[]\n  testTagsFilter?: string[]\n}\n\nexport class TestSpecification {\n  /**\n   * The task id associated with the test module.\n   */\n  public readonly taskId: string\n  /**\n   * The test project that the module belongs to.\n   */\n  public readonly project: TestProject\n  /**\n   * The id of the module in the Vite module graph. It is usually an absolute file path.\n   */\n  public readonly moduleId: string\n  /**\n   * The current test pool. It's possible to have multiple pools in a single test project with `typecheck.enabled`.\n   */\n  public readonly pool: Pool\n  /**\n   * Line numbers of the test locations to run.\n   */\n  public readonly testLines: number[] | undefined\n  /**\n   * Regular expression pattern to filter test names.\n   */\n  public readonly testNamePattern: RegExp | undefined\n  /**\n   * The ids of tasks inside of this specification to run.\n   */\n  public readonly testIds: string[] | undefined\n  /**\n   * The tags of tests to run.\n   */\n  public readonly testTagsFilter: string[] | undefined\n\n  /**\n   * This class represents a test suite for a test module within a single project.\n   * @internal\n   */\n  constructor(\n    project: TestProject,\n    moduleId: string,\n    pool: Pool,\n    testLinesOrOptions?: number[] | TestSpecificationOptions | undefined,\n  ) {\n    const projectName = project.config.name\n    const hashName = pool !== 'typescript'\n      ? projectName\n      : projectName\n      // https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/typecheck/collect.ts#L58\n        ? `${projectName}:__typecheck__`\n        : '__typecheck__'\n    this.taskId = generateFileHash(\n      relative(project.config.root, moduleId),\n      hashName,\n    )\n    this.project = project\n    this.moduleId = moduleId\n    this.pool = pool\n    if (Array.isArray(testLinesOrOptions)) {\n      this.testLines = testLinesOrOptions\n    }\n    else if (testLinesOrOptions && typeof testLinesOrOptions === 'object') {\n      this.testLines = testLinesOrOptions.testLines\n      this.testNamePattern = testLinesOrOptions.testNamePattern\n      this.testIds = testLinesOrOptions.testIds\n      this.testTagsFilter = testLinesOrOptions.testTagsFilter\n    }\n  }\n\n  /**\n   * Test module associated with the specification. This will be `undefined` if tests have not been run yet.\n   */\n  get testModule(): TestModule | undefined {\n    const task = this.project.vitest.state.idMap.get(this.taskId)\n    if (!task) {\n      return undefined\n    }\n    return this.project.vitest.state.getReportedEntity(task) as TestModule | undefined\n  }\n\n  toJSON(): SerializedTestSpecification {\n    return [\n      {\n        name: this.project.config.name,\n        root: this.project.config.root,\n      },\n      this.moduleId,\n      {\n        pool: this.pool,\n        testLines: this.testLines,\n        testIds: this.testIds,\n        testNamePattern: this.testNamePattern,\n        testTagsFilter: this.testTagsFilter,\n      },\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/types/benchmark.ts",
    "content": "import type { Arrayable } from '@vitest/utils'\n\nimport type { BenchmarkBuiltinReporters } from '../reporters'\nimport type { Reporter } from './reporter'\n\nexport interface BenchmarkUserOptions {\n  /**\n   * Include globs for benchmark test files\n   *\n   * @default ['**\\/*.{bench,benchmark}.?(c|m)[jt]s?(x)']\n   */\n  include?: string[]\n\n  /**\n   * Exclude globs for benchmark test files\n   * @default ['**\\/node_modules/**', '**\\/dist/**', '**\\/cypress/**', '**\\/.{idea,git,cache,output,temp}/**', '**\\/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*']\n   */\n  exclude?: string[]\n\n  /**\n   * Include globs for in-source benchmark test files\n   *\n   * @default []\n   */\n  includeSource?: string[]\n\n  /**\n   * Custom reporters to use for output. Can contain one or more built-in reporter names, reporter instances,\n   * and/or paths to custom reporter files to import.\n   *\n   * @default ['default']\n   */\n  reporters?: Arrayable<BenchmarkBuiltinReporters | Reporter | (string & {})>\n\n  /**\n   * @deprecated Use `benchmark.outputJson` instead\n   */\n  outputFile?:\n    | string\n    | (Partial<Record<BenchmarkBuiltinReporters, string>>\n      & Record<string, string>)\n\n  /**\n   * benchmark output file to compare against\n   */\n  compare?: string\n\n  /**\n   * benchmark output file\n   */\n  outputJson?: string\n\n  /**\n   * Include `samples` array of benchmark results for API or custom reporter usages.\n   * This is disabled by default to reduce memory usage.\n   * @default false\n   */\n  includeSamples?: boolean\n}\n"
  },
  {
    "path": "packages/vitest/src/node/types/browser.ts",
    "content": "import type { MockedModule } from '@vitest/mocker'\nimport type { CancelReason } from '@vitest/runner'\nimport type { Awaitable, ParsedStack, TestError } from '@vitest/utils'\nimport type { StackTraceParserOptions } from '@vitest/utils/source-map'\nimport type { Plugin, ViteDevServer } from 'vite'\nimport type { BrowserCommands, CDPSession } from 'vitest/browser'\nimport type { BrowserTraceViewMode } from '../../runtime/config'\nimport type { BrowserTesterOptions } from '../../types/browser'\nimport type { TestProject } from '../project'\nimport type { ApiConfig, ProjectConfig } from './config'\n\nexport type { CDPSession }\n\nexport interface BrowserModuleMocker {\n  register: (sessionId: string, module: MockedModule) => Promise<void>\n  delete: (sessionId: string, url: string) => Promise<void>\n  clear: (sessionId: string) => Promise<void>\n}\n\nexport interface BrowserProviderOption<Options extends object = object> {\n  name: string\n  supportedBrowser?: ReadonlyArray<string>\n  options: Options\n  providerFactory: (project: TestProject) => BrowserProvider\n  serverFactory: BrowserServerFactory\n}\n\nexport interface BrowserServerOptions {\n  project: TestProject\n  coveragePlugin: () => Plugin\n  mocksPlugins: (options: { filter: (id: string) => boolean }) => Plugin[]\n  metaEnvReplacer: () => Plugin\n}\n\nexport interface BrowserServerFactory {\n  (options: BrowserServerOptions): Promise<ParentProjectBrowser>\n}\n\nexport interface BrowserProvider {\n  name: string\n  mocker?: BrowserModuleMocker\n  readonly initScripts?: string[]\n  /**\n   * @experimental opt-in into file parallelisation\n   */\n  supportsParallelism: boolean\n  getCommandsContext: (sessionId: string) => Record<string, unknown>\n  openPage: (sessionId: string, url: string, options: { parallel: boolean }) => Promise<void>\n  getCDPSession?: (sessionId: string) => Promise<CDPSession>\n  close: () => Awaitable<void>\n}\n\nexport type BrowserBuiltinProvider = 'webdriverio' | 'playwright' | 'preview'\nexport interface _BrowserNames {}\n\ntype UnsupportedProperties\n  = | 'browser'\n    | 'typecheck'\n    | 'alias'\n    | 'sequence'\n    | 'root'\n    | 'pool'\n  // browser mode doesn't support a custom runner\n    | 'runner'\n  // non-browser options\n    | 'api'\n    | 'deps'\n    | 'environment'\n    | 'environmentOptions'\n    | 'server'\n    | 'benchmark'\n    | 'name'\n\nexport interface BrowserInstanceOption extends\n  Omit<ProjectConfig, UnsupportedProperties>,\n  Pick<\n    BrowserConfigOptions,\n    | 'headless'\n    | 'locators'\n    | 'viewport'\n    | 'testerHtmlPath'\n    | 'screenshotDirectory'\n    | 'screenshotFailures'\n  > {\n  /**\n   * Name of the browser\n   */\n  browser: keyof _BrowserNames extends never\n    ? string\n    : _BrowserNames[keyof _BrowserNames]\n\n  name?: string\n  provider?: BrowserProviderOption\n}\n\nexport interface BrowserConfigOptions {\n  /**\n   * if running tests in the browser should be the default\n   *\n   * @default false\n   */\n  enabled?: boolean\n\n  /**\n   * Name of the browser\n   * @deprecated use `instances` instead. if both are defined, this will filter `instances` by name.\n   * @internal\n   */\n  name?: string\n\n  /**\n   * Configurations for different browser setups\n   */\n  instances?: BrowserInstanceOption[]\n\n  /**\n   * Browser provider\n   * @example\n   * ```ts\n   * import { playwright } from '@vitest/browser-playwright'\n   * export default defineConfig({\n   *   test: {\n   *     browser: {\n   *       provider: playwright(),\n   *     },\n   *   },\n   * })\n   * ```\n   */\n  provider?: BrowserProviderOption\n\n  /**\n   * enable headless mode\n   *\n   * @default process.env.CI\n   */\n  headless?: boolean\n\n  /**\n   * Serve API options.\n   *\n   * The default port is 63315.\n   */\n  api?: ApiConfig | number\n\n  /**\n   * Isolate test environment after each test\n   *\n   * @default true\n   * @deprecated use top-level `isolate` instead\n   */\n  isolate?: boolean\n\n  /**\n   * Run test files in parallel if provider supports this option\n   * This option only has effect in headless mode (enabled in CI by default)\n   *\n   * @default // Same as \"test.fileParallelism\"\n   * @deprecated use top-level `fileParallelism` instead\n   */\n  fileParallelism?: boolean\n\n  /**\n   * Show Vitest UI\n   *\n   * @default !process.env.CI\n   */\n  ui?: boolean\n\n  /**\n   * Default position for the details panel in browser mode\n   * 'right' shows the details panel on the right side (horizontal split)\n   * 'bottom' shows the details panel at the bottom (vertical split)\n   * @default 'right'\n   */\n  detailsPanelPosition?: 'right' | 'bottom'\n\n  /**\n   * Default viewport size\n   */\n  viewport?: {\n    /**\n     * Width of the viewport\n     * @default 414\n     */\n    width: number\n    /**\n     * Height of the viewport\n     * @default 896\n     */\n    height: number\n  }\n\n  /**\n   * Locator options\n   */\n  locators?: {\n    /**\n     * Attribute used to locate elements by test id\n     * @default 'data-testid'\n     */\n    testIdAttribute?: string\n  }\n\n  /**\n   * Generate traces that can be viewed on https://trace.playwright.dev/\n   *\n   * This option is supported only by **playwright** provider.\n   */\n  trace?: BrowserTraceViewMode | {\n    mode: BrowserTraceViewMode\n    /**\n     * The directory where all traces will be stored. By default, Vitest\n     * stores all traces in `__traces__` folder close to the test file.\n     */\n    tracesDir?: string\n    /**\n     * Whether to capture screenshots during tracing. Screenshots are used to build a timeline preview.\n     * @default true\n     */\n    screenshots?: boolean\n    /**\n     * If this option is true tracing will\n     * - capture DOM snapshot on every action\n     * - record network activity\n     * @default true\n     */\n    snapshots?: boolean\n  }\n\n  /**\n   * Directory where screenshots will be saved when page.screenshot() is called\n   * If not set, all screenshots are saved to __screenshots__ directory in the same folder as the test file.\n   * If this is set, it will be resolved relative to the project root.\n   * @default __screenshots__\n   */\n  screenshotDirectory?: string\n\n  /**\n   * Should Vitest take screenshots if the test fails\n   * @default !browser.ui\n   */\n  screenshotFailures?: boolean\n\n  /**\n   * Path to the index.html file that will be used to run tests.\n   */\n  testerHtmlPath?: string\n\n  /**\n   * Scripts injected into the main window.\n   */\n  orchestratorScripts?: BrowserScript[]\n\n  /**\n   * Commands that will be executed on the server\n   * via the browser `import(\"vitest/browser\").commands` API.\n   * @see {@link https://vitest.dev/api/browser/commands}\n   */\n  commands?: Record<string, BrowserCommand<any>>\n\n  /**\n   * Timeout for connecting to the browser\n   * @default 30000\n   */\n  connectTimeout?: number\n\n  expect?: {\n    toMatchScreenshot?: {\n      [ComparatorName in keyof ToMatchScreenshotComparators]:\n      {\n        /**\n         * The name of the comparator to use for visual diffing.\n         *\n         * @defaultValue `'pixelmatch'`\n         */\n        comparatorName?: ComparatorName\n        comparatorOptions?: ToMatchScreenshotComparators[ComparatorName]\n      }\n    }[keyof ToMatchScreenshotComparators] & ToMatchScreenshotOptions\n  }\n\n  /**\n   * Enables tracking uncaught errors and exceptions so they can be reported by Vitest.\n   *\n   * If you need to hide certain errors, it is recommended to use [`onUnhandledError`](https://vitest.dev/config/onunhandlederror) option instead.\n   *\n   * Disabling this will completely remove all Vitest error handlers, which can help debugging with the \"Pause on exceptions\" checkbox turned on.\n   * @default true\n   */\n  trackUnhandledErrors?: boolean\n}\n\nexport interface BrowserCommandContext {\n  testPath: string | undefined\n  provider: BrowserProvider\n  project: TestProject\n  sessionId: string\n  triggerCommand: <K extends keyof BrowserCommands>(\n    name: K,\n    ...args: Parameters<BrowserCommands[K]>\n  ) => ReturnType<BrowserCommands[K]>\n}\n\nexport interface BrowserServerStateSession {\n  project: TestProject\n  connected: () => void\n  fail: (v: Error) => void\n}\n\nexport interface BrowserOrchestrator {\n  cleanupTesters: () => Promise<void>\n  createTesters: (options: BrowserTesterOptions) => Promise<void>\n  onCancel: (reason: CancelReason) => Promise<void>\n  $close: () => void\n}\n\nexport interface BrowserServerState {\n  orchestrators: Map<string, BrowserOrchestrator>\n}\n\nexport interface ParentProjectBrowser {\n  spawn: (project: TestProject) => ProjectBrowser\n  vite: ViteDevServer\n}\n\nexport interface ProjectBrowser {\n  vite: ViteDevServer\n  state: BrowserServerState\n  provider: BrowserProvider\n  close: () => Promise<void>\n  initBrowserProvider: (project: TestProject) => Promise<void>\n  parseStacktrace: (stack: string) => ParsedStack[]\n  parseErrorStacktrace: (error: TestError, options?: StackTraceParserOptions) => ParsedStack[]\n  registerCommand: <K extends keyof BrowserCommands>(\n    name: K,\n    cb: BrowserCommand<\n      Parameters<BrowserCommands[K]>,\n      ReturnType<BrowserCommands[K]>\n    >,\n  ) => void\n  triggerCommand: <K extends keyof BrowserCommands>(\n    name: K,\n    context: BrowserCommandContext,\n    ...args: Parameters<BrowserCommands[K]>\n  ) => ReturnType<BrowserCommands[K]>\n}\n\nexport interface BrowserCommand<Payload extends unknown[] = [], ReturnValue = any> {\n  (context: BrowserCommandContext, ...payload: Payload): Awaitable<ReturnValue>\n}\n\nexport interface BrowserScript {\n  /**\n   * If \"content\" is provided and type is \"module\", this will be its identifier.\n   *\n   * If you are using TypeScript, you can add `.ts` extension here for example.\n   * @default `injected-${index}.js`\n   */\n  id?: string\n  /**\n   * JavaScript content to be injected. This string is processed by Vite plugins if type is \"module\".\n   *\n   * You can use `id` to give Vite a hint about the file extension.\n   */\n  content?: string\n  /**\n   * Path to the script. This value is resolved by Vite so it can be a node module or a file path.\n   */\n  src?: string\n  /**\n   * If the script should be loaded asynchronously.\n   */\n  async?: boolean\n  /**\n   * Script type.\n   * @default 'module'\n   */\n  type?: string\n}\n\nexport interface ResolvedBrowserOptions extends BrowserConfigOptions {\n  name: string\n  enabled: boolean\n  headless: boolean\n  isolate: boolean\n  fileParallelism: boolean\n  api: ApiConfig\n  ui: boolean\n  viewport: {\n    width: number\n    height: number\n  }\n  screenshotFailures: boolean\n  locators: {\n    testIdAttribute: string\n  }\n  trace: {\n    mode: BrowserTraceViewMode\n    tracesDir?: string\n    screenshots?: boolean\n    snapshots?: boolean\n    sources?: boolean\n  }\n}\n\ntype ToMatchScreenshotResolvePath = (data: {\n  /**\n   * Path **without** extension, sanitized and relative to the test file.\n   *\n   * This comes from the arguments passed to `toMatchScreenshot`; if called\n   * without arguments this will be the auto-generated name.\n   *\n   * @example\n   * test('calls `onClick`', () => {\n   *   expect(locator).toMatchScreenshot()\n   *   // arg = \"calls-onclick-1\"\n   * })\n   *\n   * @example\n   * expect(locator).toMatchScreenshot('foo/bar/baz.png')\n   * // arg = \"foo/bar/baz\"\n   *\n   * @example\n   * expect(locator).toMatchScreenshot('../foo/bar/baz.png')\n   * // arg = \"foo/bar/baz\"\n   */\n  arg: string\n  /**\n   * Screenshot extension, with leading dot.\n   *\n   * This can be set through the arguments passed to `toMatchScreenshot`, but\n   * the value will fall back to `'.png'` if an unsupported extension is used.\n   */\n  ext: string\n  /**\n   * The instance's browser name.\n   */\n  browserName: string\n  /**\n   * The value of {@linkcode process.platform}.\n   */\n  platform: NodeJS.Platform\n  /**\n   * The value provided to\n   * {@linkcode https://vitest.dev/config/browser/screenshotdirectory|browser.screenshotDirectory},\n   * if none is provided, its default value.\n   */\n  screenshotDirectory: string\n  /**\n   * Absolute path to the project's\n   * {@linkcode https://vitest.dev/config/root|root}.\n   */\n  root: string\n  /**\n   * Path to the test file, relative to the project's\n   * {@linkcode https://vitest.dev/config/root|root}.\n   */\n  testFileDirectory: string\n  /**\n   * The test's filename.\n   */\n  testFileName: string\n  /**\n   * The {@linkcode https://vitest.dev/api/#test|test}'s name, including\n   * parent {@linkcode https://vitest.dev/api/#describe|describe}, sanitized.\n   */\n  testName: string\n  /**\n   * The value provided to\n   * {@linkcode https://vitest.dev/config/attachmentsdir|attachmentsDir},\n   * if none is provided, its default value.\n   */\n  attachmentsDir: string\n}) => string\n\nexport interface ToMatchScreenshotOptions {\n  /**\n   * Overrides default reference screenshot path.\n   *\n   * @default `${root}/${testFileDirectory}/${screenshotDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}`\n   */\n  resolveScreenshotPath?: ToMatchScreenshotResolvePath\n  /**\n   * Overrides default screenshot path used for diffs.\n   *\n   * @default `${root}/${attachmentsDir}/${testFileDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}`\n   */\n  resolveDiffPath?: ToMatchScreenshotResolvePath\n}\n\nexport interface ToMatchScreenshotComparators {}\n"
  },
  {
    "path": "packages/vitest/src/node/types/config.ts",
    "content": "import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers'\nimport type { PrettyFormatOptions } from '@vitest/pretty-format'\nimport type { SequenceHooks, SequenceSetupFiles, SerializableRetry, TestTagDefinition } from '@vitest/runner'\nimport type { SnapshotStateOptions } from '@vitest/snapshot'\nimport type { Arrayable } from '@vitest/utils'\nimport type { SerializedDiffOptions } from '@vitest/utils/diff'\nimport type { AliasOptions, ConfigEnv, DepOptimizationConfig, ServerOptions, UserConfig as ViteUserConfig } from 'vite'\nimport type { ChaiConfig } from '../../integrations/chai/config'\nimport type { SerializedConfig } from '../../runtime/config'\nimport type { LabelColor, ParsedStack, ProvidedContext, TestError } from '../../types/general'\nimport type { HappyDOMOptions } from '../../types/happy-dom-options'\nimport type { JSDOMOptions } from '../../types/jsdom-options'\nimport type { PoolRunnerInitializer } from '../pools/types'\nimport type {\n  BuiltinReporterOptions,\n  BuiltinReporters,\n} from '../reporters'\nimport type { TestCase, TestModule, TestSuite } from '../reporters/reported-tasks'\nimport type { TestSequencerConstructor } from '../sequencers/types'\nimport type { WatcherTriggerPattern } from '../watcher'\nimport type { BenchmarkUserOptions } from './benchmark'\nimport type { BrowserConfigOptions, ResolvedBrowserOptions } from './browser'\nimport type { CoverageOptions, ResolvedCoverageOptions } from './coverage'\nimport type { Reporter } from './reporter'\n\nexport type { CoverageOptions, ResolvedCoverageOptions }\nexport type { BenchmarkUserOptions }\nexport type { RuntimeConfig, SerializedConfig } from '../../runtime/config'\nexport type { BrowserConfigOptions, BrowserInstanceOption, BrowserScript } from './browser'\nexport type { CoverageIstanbulOptions, CoverageV8Options } from './coverage'\nexport type { SequenceHooks, SequenceSetupFiles } from '@vitest/runner'\n\nexport type BuiltinEnvironment\n  = | 'node'\n    | 'jsdom'\n    | 'happy-dom'\n    | 'edge-runtime'\n// Record is used, so user can get intellisense for builtin environments, but still allow custom environments\nexport type VitestEnvironment\n  = | BuiltinEnvironment\n    | (string & Record<never, never>)\nexport type CSSModuleScopeStrategy = 'stable' | 'scoped' | 'non-scoped'\n\nexport type ApiConfig = Pick<\n  ServerOptions,\n  'port' | 'strictPort' | 'host' | 'middlewareMode'\n> & {\n  /**\n   * Allow any write operations from the API server.\n   *\n   * @default true if `api.host` is exposed to network, false otherwise\n   */\n  allowWrite?: boolean\n  /**\n   * Allow running test files via the API.\n   * If `api.host` is exposed to network and `allowWrite` is true,\n   * anyone connected to the API server can run arbitrary code on your machine.\n   *\n   * @default true if `api.host` is exposed to network, false otherwise\n   */\n  allowExec?: boolean\n}\n\nexport interface EnvironmentOptions {\n  /**\n   * jsdom options.\n   */\n  jsdom?: JSDOMOptions\n  happyDOM?: HappyDOMOptions\n  [x: string]: unknown\n}\n\nexport type { HappyDOMOptions, JSDOMOptions }\n\nexport type VitestRunMode = 'test' | 'benchmark'\n\nexport interface ProjectName {\n  label: string\n  color?: LabelColor\n}\n\ninterface SequenceOptions {\n  /**\n   * Class that handles sorting and sharding algorithm.\n   * If you only need to change sorting, you can extend\n   * your custom sequencer from `BaseSequencer` from `vitest/node`.\n   * @default BaseSequencer\n   */\n  sequencer?: TestSequencerConstructor\n  /**\n   * Controls the order in which this project runs its tests when using multiple [projects](/guide/projects).\n   *\n   * - Projects with the same group order number will run together, and groups are run from lowest to highest.\n   * - If you don’t set this option, all projects run in parallel.\n   * - If several projects use the same group order, they will run at the same time.\n   * @default 0\n   */\n  groupOrder?: number\n  /**\n   * Should files and tests run in random order.\n   * @default false\n   */\n  shuffle?:\n    | boolean\n    | {\n      /**\n       * Should files run in random order. Long running tests will not start\n       * earlier if you enable this option.\n       * @default false\n       */\n      files?: boolean\n      /**\n       * Should tests run in random order.\n       * @default false\n       */\n      tests?: boolean\n    }\n  /**\n   * Should tests run in parallel.\n   * @default false\n   */\n  concurrent?: boolean\n  /**\n   * Defines how setup files should be ordered\n   * - 'parallel' will run all setup files in parallel\n   * - 'list' will run all setup files in the order they are defined in the config file\n   * @default 'parallel'\n   */\n  setupFiles?: SequenceSetupFiles\n  /**\n   * Seed for the random number generator.\n   * @default Date.now()\n   */\n  seed?: number\n  /**\n   * Defines how hooks should be ordered\n   * - `stack` will order \"after\" hooks in reverse order, \"before\" hooks will run sequentially\n   * - `list` will order hooks in the order they are defined\n   * - `parallel` will run hooks in a single group in parallel\n   * @default 'stack'\n   */\n  hooks?: SequenceHooks\n}\n\nexport type DepsOptimizationOptions = Omit<\n  DepOptimizationConfig,\n  'disabled' | 'noDiscovery'\n> & {\n  enabled?: boolean\n}\n\ninterface DepsOptions {\n  /**\n   * Enable dependency optimization. This can improve the performance of your tests.\n   */\n  optimizer?: Partial<Record<'client' | 'ssr' | ({} & string), DepsOptimizationOptions>>\n  web?: {\n    /**\n     * Should Vitest process assets (.png, .svg, .jpg, etc) files and resolve them like Vite does in the browser.\n     *\n     * These module will have a default export equal to the path to the asset, if no query is specified.\n     *\n     * **At the moment, this option only works with `{ pool: 'vmThreads' }`.**\n     *\n     * @default true\n     */\n    transformAssets?: boolean\n    /**\n     * Should Vitest process CSS (.css, .scss, .sass, etc) files and resolve them like Vite does in the browser.\n     *\n     * If CSS files are disabled with `css` options, this option will just silence UNKNOWN_EXTENSION errors.\n     *\n     * **At the moment, this option only works with `{ pool: 'vmThreads' }`.**\n     *\n     * @default true\n     */\n    transformCss?: boolean\n    /**\n     * Regexp pattern to match external files that should be transformed.\n     *\n     * By default, files inside `node_modules` are externalized and not transformed.\n     *\n     * **At the moment, this option only works with `{ pool: 'vmThreads' }`.**\n     *\n     * @default []\n     */\n    transformGlobPattern?: RegExp | RegExp[]\n  }\n\n  /**\n   * Interpret CJS module's default as named exports\n   *\n   * @default true\n   */\n  interopDefault?: boolean\n\n  /**\n   * A list of directories relative to the config file that should be treated as module directories.\n   *\n   * @default ['node_modules']\n   */\n  moduleDirectories?: string[]\n}\n\ntype InlineReporter = Reporter\ntype ReporterName = BuiltinReporters | 'html' | (string & {})\ntype ReporterWithOptions<Name extends ReporterName = ReporterName>\n  = Name extends keyof BuiltinReporterOptions\n    ? BuiltinReporterOptions[Name] extends never\n      ? [Name, object]\n      : [Name, Partial<BuiltinReporterOptions[Name]>]\n    : [Name, Record<string, unknown>]\n\nexport interface ResolveSnapshotPathHandlerContext { config: SerializedConfig }\n\nexport type ResolveSnapshotPathHandler = (\n  testPath: string,\n  snapExtension: string,\n  context: ResolveSnapshotPathHandlerContext,\n) => string\n\nexport type BuiltinPool\n  = | 'browser'\n    | 'threads'\n    | 'forks'\n    | 'vmThreads'\n    | 'vmForks'\n    | 'typescript'\n\nexport type Pool = BuiltinPool | (string & {})\n\nexport interface InlineConfig {\n  /**\n   * Name of the project. Will be used to display in the reporter.\n   */\n  name?: string | ProjectName\n\n  /**\n   * Benchmark options.\n   *\n   * @default {}\n   */\n  benchmark?: BenchmarkUserOptions\n\n  /**\n   * A list of [glob patterns](https://superchupu.dev/tinyglobby/comparison) that match your test files.\n   *\n   * @default ['**\\/*.{test,spec}.?(c|m)[jt]s?(x)']\n   * @see {@link https://vitest.dev/config/include}\n   */\n  include?: string[]\n\n  /**\n   * Exclude globs for test files\n   * @default ['**\\/node_modules/**', '**\\/.git/**']\n   */\n  exclude?: string[]\n\n  /**\n   * Include globs for in-source test files\n   *\n   * @default []\n   */\n  includeSource?: string[]\n\n  /**\n   * Handling for dependencies inlining or externalizing\n   *\n   */\n  deps?: DepsOptions\n\n  server?: {\n    deps?: ServerDepsOptions\n    debug?: {\n      /**\n       * The folder where Vitest stores the contents of transformed\n       * test files that can be inspected manually.\n       *\n       * If `true`, Vitest dumps the files in `.vitest-dump` folder relative to the root of the project.\n       *\n       * You can also use `VITEST_DEBUG_DUMP` env variable to enable this.\n       */\n      dump?: string | true\n      /**\n       * If dump is enabled, should Vitest load the files from there instead of transforming them.\n       *\n       * You can also use `VITEST_DEBUG_LOAD_DUMP` env variable to enable this.\n       */\n      load?: boolean\n    }\n  }\n\n  /**\n   * Base directory to scan for the test files\n   *\n   * @default `config.root`\n   */\n  dir?: string\n\n  /**\n   * Register apis globally\n   *\n   * @default false\n   */\n  globals?: boolean\n\n  /**\n   * Running environment\n   *\n   * Supports 'node', 'jsdom', 'happy-dom', 'edge-runtime'\n   *\n   * If used unsupported string, will try to load the package `vitest-environment-${env}`\n   *\n   * @default 'node'\n   */\n  environment?: VitestEnvironment\n\n  /**\n   * Environment options.\n   */\n  environmentOptions?: EnvironmentOptions\n\n  /**\n   * Run tests in an isolated environment. This option has no effect on vmThreads pool.\n   *\n   * Disabling this option improves performance if your code doesn't rely on side effects.\n   *\n   * @default true\n   */\n  isolate?: boolean\n\n  /**\n   * Pass additional arguments to `node` process when spawning the worker.\n   *\n   * See [Command-line API | Node.js](https://nodejs.org/docs/latest/api/cli.html) for more information.\n   *\n   * Set to `process.execArgv` to pass all arguments of the current process.\n   *\n   * Be careful when using, it as some options may crash worker, e.g. --prof, --title. See https://github.com/nodejs/node/issues/41103\n   *\n   * @default [] // no execution arguments are passed\n   */\n  execArgv?: string[]\n\n  /**\n   * Specifies the memory limit for `worker_thread` or `child_process` before they are recycled.\n   * If you see memory leaks, try to tinker this value.\n   */\n  vmMemoryLimit?: string | number\n\n  /**\n   * Pool used to run tests in.\n   *\n   * Supports 'threads', 'forks', 'vmThreads', 'vmForks'\n   *\n   * @default 'forks'\n   */\n  pool?: Exclude<Pool, 'browser'> | PoolRunnerInitializer\n\n  /**\n   * Maximum number or percentage of workers to run tests in.\n   */\n  maxWorkers?: number | string\n\n  /**\n   * Should all test files run in parallel. Doesn't affect tests running in the same file.\n   * Setting this to `false` will override `maxWorkers` option to `1`.\n   *\n   * @default true\n   */\n  fileParallelism?: boolean\n\n  /**\n   * Options for projects\n   */\n  projects?: TestProjectConfiguration[]\n\n  /**\n   * Update snapshot\n   *\n   * @default false\n   */\n  update?: boolean | 'all' | 'new' | 'none'\n\n  /**\n   * Watch mode\n   *\n   * @default !process.env.CI\n   */\n  watch?: boolean\n\n  /**\n   * Project root\n   *\n   * @default process.cwd()\n   */\n  root?: string\n\n  /**\n   * Custom reporter for output. Can contain one or more built-in reporter names, reporter instances,\n   * and/or paths to custom reporters.\n   *\n   * @default ['default'] (or ['default', 'github-actions'] when `process.env.GITHUB_ACTIONS === 'true'`)\n   */\n  reporters?:\n    | Arrayable<ReporterName | InlineReporter>\n    | (\n        | (ReporterName | InlineReporter)\n        | [ReporterName]\n        | ReporterWithOptions\n    )[]\n\n  /**\n   * Write test results to a file when the --reporter=json` or `--reporter=junit` option is also specified.\n   * Also definable individually per reporter by using an object instead.\n   */\n  outputFile?:\n    | string\n    | (Partial<Record<BuiltinReporters, string>> & Record<string, string>)\n\n  /**\n   * Default timeout of a test in milliseconds\n   *\n   * @default 5000\n   */\n  testTimeout?: number\n\n  /**\n   * Default timeout of a hook in milliseconds\n   *\n   * @default 10000\n   */\n  hookTimeout?: number\n\n  /**\n   * Default timeout to wait for close when Vitest shuts down, in milliseconds\n   *\n   * @default 10000\n   */\n  teardownTimeout?: number\n\n  /**\n   * Silent mode\n   *\n   * Use `'passed-only'` to see logs from failing tests only.\n   *\n   * @default false\n   */\n  silent?: boolean | 'passed-only'\n\n  /**\n   * Hide logs for skipped tests\n   *\n   * @default false\n   */\n  hideSkippedTests?: boolean\n\n  /**\n   * Path to setup files\n   */\n  setupFiles?: string | string[]\n\n  /**\n   * Path to global setup files\n   */\n  globalSetup?: string | string[]\n\n  /**\n   * Glob pattern of file paths that will trigger the whole suite rerun\n   *\n   * Useful if you are testing calling CLI commands\n   *\n   * @default ['**\\/package.json/**', '**\\/{vitest,vite}.config.*\\/**']\n   */\n  forceRerunTriggers?: string[]\n\n  /**\n   * Pattern configuration to rerun only the tests that are affected\n   * by the changes of specific files in the repository.\n   */\n  watchTriggerPatterns?: WatcherTriggerPattern[]\n\n  /**\n   * Coverage options\n   */\n  coverage?: CoverageOptions\n\n  /**\n   * Run test names with the specified pattern\n   */\n  testNamePattern?: string | RegExp\n\n  /**\n   * Will call `.mockClear()` on all spies before each test\n   * @default false\n   */\n  clearMocks?: boolean\n\n  /**\n   * Will call `.mockReset()` on all spies before each test\n   * @default false\n   */\n  mockReset?: boolean\n\n  /**\n   * Will call `.mockRestore()` on all spies before each test\n   * @default false\n   */\n  restoreMocks?: boolean\n\n  /**\n   * Will restore all global stubs to their original values before each test\n   * @default false\n   */\n  unstubGlobals?: boolean\n\n  /**\n   * Will restore all env stubs to their original values before each test\n   * @default false\n   */\n  unstubEnvs?: boolean\n\n  /**\n   * Serve API options.\n   *\n   * When set to true, the default port is 51204.\n   *\n   * @default false\n   */\n  api?: boolean | number | ApiConfig\n\n  /**\n   * Enable Vitest UI\n   *\n   * @default false\n   */\n  ui?: boolean\n\n  /**\n   * options for test in a browser environment\n   *\n   * @default false\n   */\n  browser?: BrowserConfigOptions\n\n  /**\n   * Open UI automatically.\n   *\n   * @default !process.env.CI\n   */\n  open?: boolean\n\n  /**\n   * Base url for the UI\n   *\n   * @default '/__vitest__/'\n   */\n  uiBase?: string\n\n  /**\n   * Format options for snapshot testing.\n   */\n  snapshotFormat?: Omit<PrettyFormatOptions, 'plugins' | 'compareKeys'> & {\n    compareKeys?: null | undefined\n  }\n\n  /**\n   * Path to a module which has a default export of diff config.\n   */\n  diff?: string | SerializedDiffOptions\n\n  /**\n   * Paths to snapshot serializer modules.\n   */\n  snapshotSerializers?: string[]\n\n  /**\n   * Resolve custom snapshot path\n   */\n  resolveSnapshotPath?: ResolveSnapshotPathHandler\n\n  /**\n   * Path to a custom snapshot environment module that has a default export of `SnapshotEnvironment` object.\n   */\n  snapshotEnvironment?: string\n\n  /**\n   * Pass with no tests\n   */\n  passWithNoTests?: boolean\n\n  /**\n   * Allow tests and suites that are marked as only\n   *\n   * @default !process.env.CI\n   */\n  allowOnly?: boolean\n\n  /**\n   * Show heap usage after each test. Useful for debugging memory leaks.\n   */\n  logHeapUsage?: boolean\n\n  /**\n   * Detect asynchronous resources leaking from the test file.\n   *\n   * @default false\n   */\n  detectAsyncLeaks?: boolean\n\n  /**\n   * Custom environment variables assigned to `process.env` before running tests.\n   */\n  env?: Partial<NodeJS.ProcessEnv>\n\n  /**\n   * Options for @sinon/fake-timers\n   */\n  fakeTimers?: FakeTimerInstallOpts\n\n  /**\n   * Custom handler for console.log in tests.\n   *\n   * Return `false` to ignore the log.\n   */\n  onConsoleLog?: (log: string, type: 'stdout' | 'stderr', entity: TestModule | TestCase | TestSuite | undefined) => boolean | void\n\n  /**\n   * Enable stack trace filtering. If absent, all stack trace frames\n   * will be shown.\n   *\n   * Return `false` to omit the frame.\n   */\n  onStackTrace?: (error: TestError, frame: ParsedStack) => boolean | void\n\n  /**\n   * A callback that can return `false` to ignore an unhandled error\n   */\n  onUnhandledError?: OnUnhandledErrorCallback\n\n  /**\n   * Indicates if CSS files should be processed.\n   *\n   * When excluded, the CSS files will be replaced with empty strings to bypass the subsequent processing.\n   *\n   * @default { include: [], modules: { classNameStrategy: false } }\n   */\n  css?:\n    | boolean\n    | {\n      include?: RegExp | RegExp[]\n      exclude?: RegExp | RegExp[]\n      modules?: {\n        classNameStrategy?: CSSModuleScopeStrategy\n      }\n    }\n  /**\n   * A number of tests that are allowed to run at the same time marked with `test.concurrent`.\n   * @default 5\n   */\n  maxConcurrency?: number\n\n  /**\n   * Options for configuring cache policy.\n   * @default { dir: 'node_modules/.vite/vitest/{project-hash}' }\n   */\n  cache?:\n    | false\n    | {\n      /**\n       * @deprecated Use Vite's \"cacheDir\" instead if you want to change the cache director. Note caches will be written to \"cacheDir\\/vitest\".\n       */\n      dir: string\n    }\n\n  /**\n   * Options for configuring the order of running tests.\n   */\n  sequence?: SequenceOptions\n\n  /**\n   * Specifies an `Object`, or an `Array` of `Object`,\n   * which defines aliases used to replace values in `import` or `require` statements.\n   * Will be merged with the default aliases inside `resolve.alias`.\n   */\n  alias?: AliasOptions\n\n  /**\n   * Ignore any unhandled errors that occur\n   *\n   * @default false\n   */\n  dangerouslyIgnoreUnhandledErrors?: boolean\n\n  /**\n   * Options for configuring typechecking test environment.\n   */\n  typecheck?: Partial<TypecheckConfig>\n\n  /**\n   * The number of milliseconds after which a test is considered slow and reported as such in the results.\n   *\n   * @default 300\n   */\n  slowTestThreshold?: number\n\n  /**\n   * Path to a custom test runner.\n   */\n  runner?: string\n\n  /**\n   * Debug tests by opening `node:inspector` in worker / child process.\n   * Provides similar experience as `--inspect` Node CLI argument.\n   *\n   * Requires `fileParallelism: false`.\n   */\n  inspect?: boolean | string\n\n  /**\n   * Debug tests by opening `node:inspector` in worker / child process and wait for debugger to connect.\n   * Provides similar experience as `--inspect-brk` Node CLI argument.\n   *\n   * Requires `fileParallelism: false`.\n   */\n  inspectBrk?: boolean | string\n\n  /**\n   * Inspector options. If `--inspect` or `--inspect-brk` is enabled, these options will be passed to the inspector.\n   */\n  inspector?: {\n    /**\n     * Enable inspector\n     */\n    enabled?: boolean\n    /**\n     * Port to run inspector on\n     */\n    port?: number\n    /**\n     * Host to run inspector on\n     */\n    host?: string\n    /**\n     * Wait for debugger to connect before running tests\n     */\n    waitForDebugger?: boolean\n  }\n\n  /**\n   * Define variables that will be returned from `inject` in the test environment.\n   * @example\n   * ```ts\n   * // vitest.config.ts\n   * export default defineConfig({\n   *   test: {\n   *     provide: {\n   *       someKey: 'someValue'\n   *     }\n   *   }\n   * })\n   * ```\n   * ```ts\n   * // test file\n   * import { inject } from 'vitest'\n   * const value = inject('someKey') // 'someValue'\n   * ```\n   */\n  provide?: Partial<ProvidedContext>\n\n  /**\n   * Configuration options for expect() matches.\n   */\n  expect?: {\n    /**\n     * Throw an error if tests don't have any expect() assertions.\n     */\n    requireAssertions?: boolean\n    /**\n     * Default options for expect.poll()\n     */\n    poll?: {\n      /**\n       * Timeout in milliseconds\n       * @default 1000\n       */\n      timeout?: number\n      /**\n       * Polling interval in milliseconds\n       * @default 50\n       */\n      interval?: number\n    }\n  }\n\n  /**\n   * Modify default Chai config. Vitest uses Chai for `expect` and `assert` matches.\n   * https://github.com/chaijs/chai/blob/4.x.x/lib/chai/config.js\n   */\n  chaiConfig?: ChaiConfig\n\n  /**\n   * Stop test execution when given number of tests have failed.\n   */\n  bail?: number\n\n  /**\n   * Retry configuration for tests.\n   * - If a number, specifies how many times to retry failed tests\n   * - If an object, allows fine-grained retry control\n   *\n   * ⚠️ WARNING: Function form is NOT supported in a config file\n   * because configurations are serialized when passed to worker threads.\n   * Use the function form only in test files directly.\n   *\n   * @default 0 // Don't retry\n   */\n  retry?: SerializableRetry\n\n  /**\n   * Show full diff when snapshot fails instead of a patch.\n   */\n  expandSnapshotDiff?: boolean\n\n  /**\n   * By default, Vitest automatically intercepts console logging during tests for extra formatting of test file, test title, etc...\n   * This is also required for console log preview on Vitest UI.\n   * However, disabling such interception might help when you want to debug a code with normal synchronous terminal console logging.\n   *\n   * This option has no effect on browser pool since Vitest preserves original logging on browser devtools.\n   *\n   * @default false\n   */\n  disableConsoleIntercept?: boolean\n\n  /**\n   * Always print console stack traces.\n   *\n   * @default false\n   */\n  printConsoleTrace?: boolean\n\n  /**\n   * Include \"location\" property inside the test definition\n   *\n   * @default false\n   */\n  includeTaskLocation?: boolean\n\n  /**\n   * Directory path for storing attachments created by `context.annotate`\n   *\n   * @default '.vitest-attachments'\n   */\n  attachmentsDir?: string\n\n  /**\n   * Experimental features\n   *\n   * @experimental\n   */\n  experimental?: {\n    /**\n     * Enable caching of modules on the file system between reruns.\n     */\n    fsModuleCache?: boolean\n    /**\n     * Path relative to the root of the project where the fs module cache will be stored.\n     * @default node_modules/.experimental-vitest-cache\n     */\n    fsModuleCachePath?: string\n    /**\n     * {@link https://vitest.dev/guide/open-telemetry}\n     */\n    openTelemetry?: {\n      enabled: boolean\n      sdkPath?: string\n      browserSdkPath?: string\n    }\n    /**\n     * Configure import duration collection and display.\n     *\n     * The `limit` option controls how many imports to collect and display.\n     * The `print` option controls CLI terminal output.\n     * UI can always toggle the breakdown display regardless of `print` setting.\n     */\n    importDurations?: {\n      /**\n       * When to print import breakdown to CLI terminal after tests finish.\n       * - `true`: Always print\n       * - `false`: Never print (default)\n       * - `'on-warn'`: Print only when any import exceeds the warn threshold\n       * @default false\n       */\n      print?: boolean | 'on-warn'\n      /**\n       * Maximum number of imports to collect and display.\n       * @default 0 (or 10 if `print` or UI is enabled)\n       */\n      limit?: number\n      /**\n       * Fail the test run if any import exceeds the danger threshold.\n       * When failing, the breakdown is always printed regardless of `print` setting.\n       * @default false\n       */\n      failOnDanger?: boolean\n      /**\n       * Duration thresholds in milliseconds for coloring and warnings.\n       */\n      thresholds?: {\n        /**\n         * Warning threshold - imports exceeding this are shown in yellow/orange.\n         * @default 100\n         */\n        warn?: number\n        /**\n         * Danger threshold - imports exceeding this are shown in red.\n         * @default 500\n         */\n        danger?: number\n      }\n    }\n\n    /**\n     * Controls whether Vitest uses Vite's module runner to run the code or fallback to the native `import`.\n     *\n     * If Node.js cannot process the code, consider registering [module loader](https://nodejs.org/api/module.html#customization-hooks) via `execArgv`.\n     * @default true\n     */\n    viteModuleRunner?: boolean\n    /**\n     * If module runner is disabled, Vitest uses a module loader to transform files to support\n     * `import.meta.vitest` and `vi.mock`.\n     *\n     * If you don't use these features, you can disable this.\n     *\n     * This option only affects `loader.load` method, Vitest always defines a `loader.resolve` to populate the module graph.\n     */\n    nodeLoader?: boolean\n  }\n\n  /**\n   * Define tags available in your test files.\n   *\n   * If test defines a tag that is not listed here, an error will be thrown.\n   */\n  tags?: TestTagDefinition[]\n\n  /**\n   * Should Vitest throw an error if test has a tag that is not defined in the config.\n   * @default true\n   */\n  strictTags?: boolean\n}\n\nexport interface TypecheckConfig {\n  /**\n   * Run typechecking tests alongside regular tests.\n   */\n  enabled?: boolean\n  /**\n   * When typechecking is enabled, only run typechecking tests.\n   */\n  only?: boolean\n  /**\n   * What tools to use for type checking.\n   *\n   * @default 'tsc'\n   */\n  checker: 'tsc' | 'vue-tsc' | (string & Record<never, never>)\n  /**\n   * Pattern for files that should be treated as test files\n   *\n   * @default ['**\\/*.{test,spec}-d.?(c|m)[jt]s?(x)']\n   */\n  include: string[]\n  /**\n   * Pattern for files that should not be treated as test files\n   *\n   * @default ['**\\/node_modules/**', '**\\/dist/**', '**\\/cypress/**', '**\\/.{idea,git,cache,output,temp}/**', '**\\/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*']\n   */\n  exclude: string[]\n  /**\n   * Check JS files that have `@ts-check` comment.\n   * If you have it enabled in tsconfig, this will not overwrite it.\n   */\n  allowJs?: boolean\n  /**\n   * Do not fail, if Vitest found errors outside the test files.\n   */\n  ignoreSourceErrors?: boolean\n  /**\n   * Path to tsconfig, relative to the project root.\n   */\n  tsconfig?: string\n  /**\n   * Minimum time in milliseconds it takes to spawn the typechecker.\n   * @default 10_000\n   */\n  spawnTimeout?: number\n}\n\nexport interface UserConfig extends InlineConfig {\n  /**\n   * Path to the config file.\n   *\n   * Default resolving to `vitest.config.*`, `vite.config.*`\n   *\n   * Setting to `false` will disable config resolving.\n   */\n  config?: string | false | undefined\n\n  /**\n   * Do not run tests when Vitest starts.\n   *\n   * Vitest will only run tests if it's called programmatically or the test file changes.\n   *\n   * If CLI file filters are passed, standalone mode is ignored.\n   */\n  standalone?: boolean\n\n  /**\n   * Use happy-dom\n   */\n  dom?: boolean\n\n  /**\n   * Run tests that cover a list of source files\n   */\n  related?: string[] | string\n\n  /**\n   * Overrides Vite mode\n   * @default 'test'\n   */\n  mode?: string\n\n  /**\n   * Runs tests that are affected by the changes in the repository, or between specified branch or commit hash\n   * Requires initialized git repository\n   * @default false\n   */\n  changed?: boolean | string\n\n  /**\n   * Test suite shard to execute in a format of <index>/<count>.\n   * Will divide tests into a `count` numbers, and run only the `indexed` part.\n   * Cannot be used with enabled watch.\n   * @example --shard=2/3\n   */\n  shard?: string\n\n  /**\n   * Name of the project or projects to run.\n   */\n  project?: string | string[]\n\n  /**\n   * Additional exclude patterns\n   */\n  cliExclude?: string[]\n\n  /**\n   * Override vite config's clearScreen from cli\n   */\n  clearScreen?: boolean\n\n  /**\n   * benchmark.compare option exposed at the top level for cli\n   */\n  compare?: string\n\n  /**\n   * benchmark.outputJson option exposed at the top level for cli\n   */\n  outputJson?: string\n\n  /**\n   * Directory of blob reports to merge\n   * @default '.vitest-reports'\n   */\n  mergeReports?: string\n\n  /**\n   * Delete all Vitest caches, including `experimental.fsModuleCache`.\n   * @experimental\n   */\n  clearCache?: boolean\n\n  /**\n   * Tags expression to filter tests to run. Multiple filters will be applied using AND logic.\n   * @see {@link https://vitest.dev/guide/test-tags#syntax}\n   */\n  tagsFilter?: string[]\n\n  /**\n   * Log all available tags instead of running tests.\n   */\n  listTags?: boolean | 'json'\n}\n\nexport type OnUnhandledErrorCallback = (error: (TestError | Error) & { type: string }) => boolean | void\n\nexport interface ResolvedConfig\n  extends Omit<\n    Required<UserConfig>,\n    | 'project'\n    | 'config'\n    | 'filters'\n    | 'browser'\n    | 'coverage'\n    | 'testNamePattern'\n    | 'related'\n    | 'api'\n    | 'reporters'\n    | 'resolveSnapshotPath'\n    | 'benchmark'\n    | 'shard'\n    | 'cache'\n    | 'sequence'\n    | 'typecheck'\n    | 'runner'\n    | 'pool'\n    | 'cliExclude'\n    | 'diff'\n    | 'setupFiles'\n    | 'snapshotEnvironment'\n    | 'bail'\n    | 'name'\n    | 'vmMemoryLimit'\n    | 'fileParallelism'\n    | 'tagsFilter'\n  > {\n  mode: VitestRunMode\n\n  name: ProjectName['label']\n  color?: ProjectName['color']\n  base?: string\n  diff?: string | SerializedDiffOptions\n  bail?: number\n\n  setupFiles: string[]\n  snapshotEnvironment?: string\n\n  config?: string\n  filters?: string[]\n  testNamePattern?: RegExp\n  related?: string[]\n\n  coverage: ResolvedCoverageOptions\n  snapshotOptions: SnapshotStateOptions\n\n  browser: ResolvedBrowserOptions\n  pool: Pool\n  poolRunner?: PoolRunnerInitializer\n\n  reporters: (InlineReporter | ReporterWithOptions)[]\n\n  defines: Record<string, any>\n  viteDefine: Record<string, any>\n\n  api: ApiConfig & { token: string }\n  cliExclude?: string[]\n\n  project: string[]\n  benchmark?: Required<\n    Omit<BenchmarkUserOptions, 'outputFile' | 'compare' | 'outputJson'>\n  >\n  & Pick<BenchmarkUserOptions, 'outputFile' | 'compare' | 'outputJson'>\n  shard?: {\n    index: number\n    count: number\n  }\n\n  cache:\n    | {\n      /**\n       * @deprecated\n       */\n      dir: string\n    }\n    | false\n\n  sequence: {\n    sequencer: TestSequencerConstructor\n    hooks: SequenceHooks\n    setupFiles: SequenceSetupFiles\n    shuffle?: boolean\n    concurrent?: boolean\n    seed: number\n    groupOrder: number\n  }\n\n  typecheck: Omit<TypecheckConfig, 'enabled'> & {\n    enabled: boolean\n  }\n  runner?: string\n\n  maxWorkers: number\n\n  vmMemoryLimit?: UserConfig['vmMemoryLimit']\n  dumpDir?: string\n  tagsFilter?: string[]\n\n  experimental: Omit<Required<UserConfig>['experimental'], 'importDurations'> & {\n    importDurations: {\n      print: boolean | 'on-warn'\n      limit: number\n      failOnDanger: boolean\n      thresholds: {\n        warn: number\n        danger: number\n      }\n    }\n  }\n}\n\ntype NonProjectOptions\n  = | 'shard'\n    | 'watch'\n    | 'run'\n    | 'cache'\n    | 'update'\n    | 'reporters'\n    | 'outputFile'\n    | 'teardownTimeout'\n    | 'silent'\n    | 'forceRerunTriggers'\n    | 'testNamePattern'\n    | 'ui'\n    | 'open'\n    | 'uiBase'\n    // TODO: allow snapshot options\n    | 'snapshotFormat'\n    | 'resolveSnapshotPath'\n    | 'passWithNoTests'\n    | 'onConsoleLog'\n    | 'onStackTrace'\n    | 'dangerouslyIgnoreUnhandledErrors'\n    | 'slowTestThreshold'\n    | 'inspect'\n    | 'inspectBrk'\n    | 'coverage'\n    | 'watchTriggerPatterns'\n    | 'tagsFilter' // CLI option only\n\nexport interface ServerDepsOptions {\n  /**\n   * Externalize means that Vite will bpass the package to native Node.\n   *\n   * Externalized dependencies will not be applied Vite's transformers and resolvers.\n   * And does not support HMR on reload.\n   *\n   * Typically, packages under `node_modules` are externalized.\n   */\n  external?: (string | RegExp)[]\n  /**\n   * Vite will process inlined modules.\n   *\n   * This could be helpful to handle packages that ship `.js` in ESM format (that Node can't handle).\n   *\n   * If `true`, every dependency will be inlined\n   */\n  inline?: (string | RegExp)[] | true\n  /**\n   * Try to guess the CJS version of a package when it's invalid ESM\n   * @default false\n   */\n  fallbackCJS?: boolean\n}\n\nexport type ProjectConfig = Omit<\n  InlineConfig,\n  NonProjectOptions\n  | 'sequencer'\n  | 'deps'\n> & {\n  mode?: string\n  sequencer?: Omit<SequenceOptions, 'sequencer' | 'seed'>\n  deps?: Omit<DepsOptions, 'moduleDirectories'>\n}\n\nexport type ResolvedProjectConfig = Omit<\n  ResolvedConfig,\n  // some options cannot be set, but they are inherited from the workspace\n  Exclude<NonProjectOptions, 'coverage' | 'watch'>\n>\n\nexport interface UserWorkspaceConfig extends ViteUserConfig {\n  test?: ProjectConfig\n}\n\n// TODO: remove types when \"workspace\" support is removed\nexport type UserProjectConfigFn = (\n  env: ConfigEnv,\n) => UserWorkspaceConfig | Promise<UserWorkspaceConfig>\nexport type UserProjectConfigExport\n  = | UserWorkspaceConfig\n    | Promise<UserWorkspaceConfig>\n    | UserProjectConfigFn\n\nexport type TestProjectInlineConfiguration = (UserWorkspaceConfig & {\n  /**\n   * Relative path to the extendable config. All other options will be merged with this config.\n   * If `true`, the project will inherit all options from the root config.\n   * @example '../vite.config.ts'\n   */\n  extends?: string | true\n})\n\nexport type TestProjectConfiguration\n  = string\n    | TestProjectInlineConfiguration\n    | Promise<UserWorkspaceConfig>\n    | UserProjectConfigFn\n"
  },
  {
    "path": "packages/vitest/src/node/types/coverage.ts",
    "content": "import type { Arrayable } from '@vitest/utils'\nimport type { ReportOptions } from 'istanbul-reports'\nimport type { TransformResult as ViteTransformResult } from 'vite'\nimport type { AfterSuiteRunMeta } from '../../types/general'\nimport type { RuntimeCoverageModuleLoader, RuntimeCoverageProviderModule } from '../../utils/coverage'\nimport type { Vitest } from '../core'\n\ntype TransformResult\n  = | string\n    | Partial<ViteTransformResult>\n    | undefined\n    | null\n    | void\ntype CoverageResults = unknown\n\nexport interface CoverageProvider {\n  name: string\n\n  /** Called when provider is being initialized before tests run */\n  initialize: (ctx: Vitest) => Promise<void> | void\n\n  /** Called when setting coverage options for Vitest context (`ctx.config.coverage`) */\n  resolveOptions: () => ResolvedCoverageOptions\n\n  /** Callback to clean previous reports */\n  clean: (clean?: boolean) => void | Promise<void>\n\n  /** Called with coverage results after a single test file has been run */\n  onAfterSuiteRun: (meta: AfterSuiteRunMeta) => void | Promise<void>\n\n  /** Callback called when test run starts */\n  onTestRunStart?: () => void | Promise<void>\n\n  /** Callback called when test run fails due to test failures */\n  onTestFailure?: () => void | Promise<void>\n\n  /** Callback to generate final coverage results */\n  generateCoverage: (\n    reportContext: ReportContext,\n  ) => CoverageResults | Promise<CoverageResults>\n\n  /** Callback to convert coverage results to coverage reports. Called with results returned from `generateCoverage` */\n  reportCoverage: (\n    coverage: CoverageResults,\n    reportContext: ReportContext,\n  ) => void | Promise<void>\n\n  /** Callback for `--merge-reports` options. Called with multiple coverage results generated by `generateCoverage`. */\n  mergeReports?: (coverages: CoverageResults[]) => void | Promise<void>\n\n  /** Callback called for instrumenting files with coverage counters. */\n  onFileTransform?: (\n    sourceCode: string,\n    id: string,\n    // TODO: when upgrading vite, import Rollup from vite\n    pluginCtx: any,\n  ) => TransformResult | Promise<TransformResult>\n\n  /**\n   * Return `true` if this file is transformed by the coverage provider.\n   * This is used to generate the persistent file hash by `fsModuleCache`\n   * @experimental\n   */\n  requiresTransform?: (id: string) => boolean\n\n  /** Callback that's called when the coverage is enabled via a programmatic `enableCoverage` API. */\n  onEnabled?: () => void | Promise<void>\n}\n\nexport interface ReportContext {\n  /** Indicates whether all tests were run. False when only specific tests were run. */\n  allTestsRun?: boolean\n}\n\nexport interface CoverageModuleLoader extends RuntimeCoverageModuleLoader {\n  import: (id: string) => Promise<{ default: CoverageProviderModule }>\n}\n\nexport interface CoverageProviderModule extends RuntimeCoverageProviderModule {\n  /**\n   * Factory for creating a new coverage provider\n   */\n  getProvider: () => CoverageProvider | Promise<CoverageProvider>\n}\n\nexport type CoverageReporter = keyof ReportOptions | (string & {})\n\nexport type CoverageReporterWithOptions<\n  ReporterName extends CoverageReporter = CoverageReporter,\n> = ReporterName extends keyof ReportOptions\n  ? ReportOptions[ReporterName] extends never\n    ? [ReporterName, object] // E.g. the \"none\" reporter\n    : [ReporterName, Partial<ReportOptions[ReporterName]>]\n  : [ReporterName, Record<string, unknown>]\n\nexport type CoverageProviderName = 'v8' | 'istanbul' | 'custom' | undefined\n\nexport type CoverageOptions<T extends CoverageProviderName = CoverageProviderName>\n  = T extends 'istanbul'\n    ? { provider: T } & CoverageIstanbulOptions\n    : T extends 'v8' ? {\n      /**\n       * Provider to use for coverage collection.\n       *\n       * @default 'v8'\n       */\n      provider: T\n    } & CoverageV8Options\n      : T extends 'custom'\n        ? { provider: T } & CustomProviderOptions\n        : { provider?: T } & CoverageV8Options\n\n/** Fields that have default values. Internally these will always be defined. */\ntype FieldsWithDefaultValues\n  = | 'enabled'\n    | 'clean'\n    | 'cleanOnRerun'\n    | 'reportsDirectory'\n    | 'exclude'\n    | 'reportOnFailure'\n    | 'allowExternal'\n    | 'processingConcurrency'\n\nexport type ResolvedCoverageOptions<T extends CoverageProviderName = CoverageProviderName>\n  = CoverageOptions<T>\n    & Required<Pick<CoverageOptions<T>, FieldsWithDefaultValues>> & { // Resolved fields which may have different typings as public configuration API has\n      reporter: CoverageReporterWithOptions[]\n      htmlDir?: string\n    }\n\nexport interface BaseCoverageOptions {\n  /**\n   * Enables coverage collection. Can be overridden using `--coverage` CLI option.\n   *\n   * @default false\n   */\n  enabled?: boolean\n\n  /**\n   * List of files included in coverage as glob patterns.\n   * By default only files covered by tests are included.\n   *\n   * See [Including and excluding files from coverage report](https://vitest.dev/guide/coverage.html#including-and-excluding-files-from-coverage-report) for examples.\n   */\n  include?: string[]\n\n  /**\n   * List of files excluded from coverage as glob patterns.\n   * Files are first checked against `coverage.include`.\n   *\n   * See [Including and excluding files from coverage report](https://vitest.dev/guide/coverage.html#including-and-excluding-files-from-coverage-report) for examples.\n   */\n  exclude?: string[]\n\n  /**\n   * Clean coverage results before running tests\n   *\n   * @default true\n   */\n  clean?: boolean\n\n  /**\n   * Clean coverage report on watch rerun\n   *\n   * @default true\n   */\n  cleanOnRerun?: boolean\n\n  /**\n   * Directory to write coverage report to\n   *\n   * @default './coverage'\n   */\n  reportsDirectory?: string\n\n  /**\n   * Coverage reporters to use.\n   * See [istanbul documentation](https://istanbul.js.org/docs/advanced/alternative-reporters/) for detailed list of all reporters.\n   *\n   * @default ['text', 'html', 'clover', 'json']\n   */\n  reporter?:\n    | Arrayable<CoverageReporter>\n    | (CoverageReporter | [CoverageReporter] | CoverageReporterWithOptions)[]\n\n  /**\n   * Do not show files with 100% statement, branch, and function coverage\n   *\n   * @default false\n   */\n  skipFull?: boolean\n\n  /**\n   * Configurations for thresholds\n   *\n   * @example\n   *\n   * ```ts\n   * {\n   *   // Thresholds for all files\n   *   functions: 95,\n   *   branches: 70,\n   *   perFile: true,\n   *   autoUpdate: true,\n   *\n   *   // Thresholds for utilities\n   *   'src/utils/**.ts': {\n   *     lines: 100,\n   *     statements: 95,\n   *   }\n   * }\n   * ```\n   */\n  thresholds?:\n    | Thresholds\n    | ({\n      [glob: string]: Pick<\n        Thresholds,\n          100 | 'statements' | 'functions' | 'branches' | 'lines'\n      >\n    } & Thresholds)\n\n  /**\n   * Watermarks for statements, lines, branches and functions.\n   *\n   * Default value is `[50,80]` for each property.\n   */\n  watermarks?: {\n    statements?: [number, number]\n    functions?: [number, number]\n    branches?: [number, number]\n    lines?: [number, number]\n  }\n\n  /**\n   * Generate coverage report even when tests fail.\n   *\n   * @default false\n   */\n  reportOnFailure?: boolean\n\n  /**\n   * Collect coverage of files outside the project `root`.\n   *\n   * @default false\n   */\n  allowExternal?: boolean\n\n  /**\n   * Apply exclusions again after coverage has been remapped to original sources.\n   * This is useful when your source files are transpiled and may contain source maps\n   * of non-source files.\n   *\n   * Use this option when you are seeing files that show up in report even if they\n   * match your `coverage.exclude` patterns.\n   *\n   * @default false\n   */\n  excludeAfterRemap?: boolean\n\n  /**\n   * Concurrency limit used when processing the coverage results.\n   * Defaults to `Math.min(20, os.availableParallelism?.() ?? os.cpus().length)`\n   */\n  processingConcurrency?: number\n\n  /**\n   * Set to array of class method names to ignore for coverage\n   *\n   * @default []\n   */\n  ignoreClassMethods?: string[]\n\n  /**\n   * Directory of HTML coverage output to be served in UI mode and HTML reporter.\n   * This is automatically configured for builtin reporter with html output (`html`, `html-spa`, and `lcov` reporters).\n   * Use this option to override with custom coverage reporting location.\n   */\n  htmlDir?: string\n\n  /**\n   * Collect coverage only for files changed since a specified commit or branch.\n   * Inherits the default value from `test.changed`.\n   *\n   * @default false\n   */\n  changed?: boolean | string\n}\n\nexport interface CoverageIstanbulOptions extends BaseCoverageOptions {}\n\nexport interface CoverageV8Options extends BaseCoverageOptions {}\n\nexport interface CustomProviderOptions\n  extends Pick<BaseCoverageOptions, FieldsWithDefaultValues | 'changed'> {\n  /** Name of the module or path to a file to load the custom provider from */\n  customProviderModule: string\n}\n\ninterface Thresholds {\n  /** Set global thresholds to `100` */\n  100?: boolean\n\n  /** Check thresholds per file. */\n  perFile?: boolean\n\n  /**\n   * Update threshold values automatically when current coverage is higher than earlier thresholds\n   * Also can accept a function to format the new threshold values\n   *\n   * @default false\n   */\n  autoUpdate?: boolean | ((newThreshold: number) => number)\n\n  /** Thresholds for statements */\n  statements?: number\n\n  /** Thresholds for functions */\n  functions?: number\n\n  /** Thresholds for branches */\n  branches?: number\n\n  /** Thresholds for lines */\n  lines?: number\n}\n"
  },
  {
    "path": "packages/vitest/src/node/types/plugin.ts",
    "content": "import type { CacheKeyIdGenerator } from '../cache/fsModuleCache'\nimport type { Vitest } from '../core'\nimport type { TestProject } from '../project'\nimport type { TestProjectConfiguration } from './config'\n\nexport interface VitestPluginContext {\n  vitest: Vitest\n  project: TestProject\n  injectTestProjects: (config: TestProjectConfiguration | TestProjectConfiguration[]) => Promise<TestProject[]>\n  /**\n   * Define a generator that will be applied before hashing the cache key.\n   *\n   * Use this to make sure Vitest generates correct hash. It is a good idea\n   * to define this function if your plugin can be registered with different options.\n   *\n   * This is called only if `experimental.fsModuleCache` is defined.\n   * @experimental\n   */\n  experimental_defineCacheKeyGenerator: (callback: CacheKeyIdGenerator) => void\n}\n"
  },
  {
    "path": "packages/vitest/src/node/types/reporter.ts",
    "content": "import type { File, TaskEventPack, TaskResultPack, TestAnnotation, TestArtifact } from '@vitest/runner'\nimport type { Awaitable, SerializedError } from '@vitest/utils'\nimport type { UserConsoleLog } from '../../types/general'\nimport type { Vitest } from '../core'\nimport type { TestProject } from '../project'\nimport type { ReportedHookContext, TestCase, TestModule, TestSuite } from '../reporters/reported-tasks'\nimport type { TestSpecification } from '../test-specification'\n\nexport type TestRunEndReason = 'passed' | 'interrupted' | 'failed'\n\nexport interface Reporter {\n  onInit?: (vitest: Vitest) => void\n  /**\n   * Called when the project initiated the browser instance.\n   * project.browser will always be defined.\n   */\n  onBrowserInit?: (project: TestProject) => Awaitable<void>\n  /** @internal   */\n  onTaskUpdate?: (packs: TaskResultPack[], events: TaskEventPack[]) => Awaitable<void>\n  onTestRemoved?: (trigger?: string) => Awaitable<void>\n  onWatcherStart?: (files?: File[], errors?: unknown[]) => Awaitable<void>\n  onWatcherRerun?: (files: string[], trigger?: string) => Awaitable<void>\n  onServerRestart?: (reason?: string) => Awaitable<void>\n  onUserConsoleLog?: (log: UserConsoleLog) => Awaitable<void>\n  onProcessTimeout?: () => Awaitable<void>\n\n  /**\n   * Called when the new test run starts.\n   */\n  onTestRunStart?: (specifications: ReadonlyArray<TestSpecification>) => Awaitable<void>\n  /**\n   * Called when the test run is finished.\n   */\n  onTestRunEnd?: (\n    testModules: ReadonlyArray<TestModule>,\n    unhandledErrors: ReadonlyArray<SerializedError>,\n    reason: TestRunEndReason,\n  ) => Awaitable<void>\n\n  /**\n   * Called when the module is enqueued for testing. The file itself is not loaded yet.\n   */\n  onTestModuleQueued?: (testModule: TestModule) => Awaitable<void>\n  /**\n   * Called when the test file is loaded and the module is ready to run tests.\n   */\n  onTestModuleCollected?: (testModule: TestModule) => Awaitable<void>\n  /**\n   * Called when starting to run tests of the test file\n   */\n  onTestModuleStart?: (testModule: TestModule) => Awaitable<void>\n  /**\n   * Called when all tests of the test file have finished running.\n   */\n  onTestModuleEnd?: (testModule: TestModule) => Awaitable<void>\n\n  /**\n   * Called when test case is ready to run.\n   * Called before the `beforeEach` hooks for the test are run.\n   */\n  onTestCaseReady?: (testCase: TestCase) => Awaitable<void>\n  /**\n   * Called after the test and its hooks are finished running.\n   * The `result()` cannot be `pending`.\n   */\n  onTestCaseResult?: (testCase: TestCase) => Awaitable<void>\n\n  /**\n   * Called when annotation is added via the `task.annotate` API.\n   */\n  onTestCaseAnnotate?: (testCase: TestCase, annotation: TestAnnotation) => Awaitable<void>\n\n  /**\n   * Called when artifacts are recorded on tests via the `recordArtifact` utility.\n   */\n  onTestCaseArtifactRecord?: (testCase: TestCase, artifact: TestArtifact) => Awaitable<void>\n\n  /**\n   * Called when test suite is ready to run.\n   * Called before the `beforeAll` hooks for the test are run.\n   */\n  onTestSuiteReady?: (testSuite: TestSuite) => Awaitable<void>\n  /**\n   * Called after the test suite and its hooks are finished running.\n   * The `state` cannot be `pending`.\n   */\n  onTestSuiteResult?: (testSuite: TestSuite) => Awaitable<void>\n\n  /**\n   * Called before the hook starts to run.\n   */\n  onHookStart?: (hook: ReportedHookContext) => Awaitable<void>\n  /**\n   * Called after the hook finished running.\n   */\n  onHookEnd?: (hook: ReportedHookContext) => Awaitable<void>\n\n  onCoverage?: (coverage: unknown) => Awaitable<void>\n}\n"
  },
  {
    "path": "packages/vitest/src/node/types/tests.ts",
    "content": "import type { TestModule } from '../reporters/reported-tasks'\n\nexport interface TestRunResult {\n  testModules: TestModule[]\n  unhandledErrors: unknown[]\n}\n"
  },
  {
    "path": "packages/vitest/src/node/types/vite.ts",
    "content": "/* eslint-disable unused-imports/no-unused-vars */\n\nimport type { HookHandler } from 'vite'\nimport type { InlineConfig } from './config'\nimport type { VitestPluginContext } from './plugin'\n\ntype VitestInlineConfig = InlineConfig\n\ndeclare module 'vite' {\n  interface UserConfig {\n    /**\n     * Options for Vitest\n     */\n    test?: VitestInlineConfig\n  }\n\n  interface Plugin<A = any> {\n    configureVitest?: HookHandler<(context: VitestPluginContext) => void>\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "packages/vitest/src/node/types/worker.ts",
    "content": "import type { ContextRPC } from '../../types/worker'\n\nexport interface WorkerContext extends ContextRPC {}\n"
  },
  {
    "path": "packages/vitest/src/node/vite.ts",
    "content": "import type { InlineConfig, ResolvedConfig, ViteDevServer } from 'vite'\nimport { cleanUrl } from '@vitest/utils/helpers'\nimport { createServer, isFileLoadingAllowed, normalizePath } from 'vite'\n\nexport async function createViteServer(inlineConfig: InlineConfig): Promise<ViteDevServer> {\n  // Vite prints an error (https://github.com/vitejs/vite/issues/14328)\n  // But Vitest works correctly either way\n  const error = console.error\n  console.error = (...args: any[]) => {\n    if (\n      typeof args[0] === 'string'\n      && args[0].includes('WebSocket server error:')\n    ) {\n      return\n    }\n    error(...args)\n  }\n\n  const server = await createServer(inlineConfig)\n\n  console.error = error\n  return server\n}\n\n// backward compat implementation\n/**\n * Check if the url is allowed to be served, via the `server.fs` config.\n * @deprecated Use the `isFileLoadingAllowed` function instead.\n */\nexport function isFileServingAllowed(\n  config: ResolvedConfig,\n  url: string,\n): boolean\nexport function isFileServingAllowed(\n  url: string,\n  server: ViteDevServer,\n): boolean\nexport function isFileServingAllowed(\n  configOrUrl: ResolvedConfig | string,\n  urlOrServer: string | ViteDevServer,\n): boolean {\n  const config = (\n    typeof urlOrServer === 'string' ? configOrUrl : urlOrServer.config\n  ) as ResolvedConfig\n  const url = (\n    typeof urlOrServer === 'string' ? urlOrServer : configOrUrl\n  ) as string\n\n  if (!config.server.fs.strict) {\n    return true\n  }\n  const filePath = fsPathFromUrl(url)\n  return isFileLoadingAllowed(config, filePath)\n}\n\nconst FS_PREFIX = '/@fs/'\nconst VOLUME_RE = /^[A-Z]:/i\n\nfunction fsPathFromId(id: string): string {\n  const fsPath = normalizePath(\n    id.startsWith(FS_PREFIX) ? id.slice(FS_PREFIX.length) : id,\n  )\n  return fsPath[0] === '/' || VOLUME_RE.test(fsPath) ? fsPath : `/${fsPath}`\n}\n\nfunction fsPathFromUrl(url: string): string {\n  return fsPathFromId(cleanUrl(url))\n}\n"
  },
  {
    "path": "packages/vitest/src/node/viteLogger.ts",
    "content": "import type { LogErrorOptions, Logger, LoggerOptions, LogLevel, LogType, Rollup } from 'vite'\nimport type { Logger as VitestLogger } from './logger'\nimport colors from 'tinyrainbow'\n\nconst LogLevels: Record<LogLevel, number> = {\n  silent: 0,\n  error: 1,\n  warn: 2,\n  info: 3,\n}\n\nfunction clearScreen(logger: VitestLogger) {\n  const repeatCount = process.stdout.rows - 2\n  const blank = repeatCount > 0 ? '\\n'.repeat(repeatCount) : ''\n  logger.clearScreen(blank)\n}\n\nlet lastType: LogType | undefined\nlet lastMsg: string | undefined\nlet sameCount = 0\n\n// Only initialize the timeFormatter when the timestamp option is used, and\n// reuse it across all loggers\nlet timeFormatter: Intl.DateTimeFormat\nfunction getTimeFormatter() {\n  timeFormatter ??= new Intl.DateTimeFormat(undefined, {\n    hour: 'numeric',\n    minute: 'numeric',\n    second: 'numeric',\n  })\n  return timeFormatter\n}\n\n// This is copy-pasted and needs to be synced from time to time. Ideally, Vite's `createLogger` should accept a custom `console`\n// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/logger.ts?rgh-link-date=2024-10-16T23%3A29%3A19Z\n// When Vitest supports only Vite 6 and above, we can use Vite's `createLogger({ console })`\n// https://github.com/vitejs/vite/pull/18379\nexport function createViteLogger(\n  console: VitestLogger,\n  level: LogLevel = 'info',\n  options: LoggerOptions = {},\n): Logger {\n  const loggedErrors = new WeakSet<Error | Rollup.RollupError>()\n  const { prefix = '[vite]', allowClearScreen = true } = options\n  const thresh = LogLevels[level]\n  const canClearScreen\n    = allowClearScreen && process.stdout.isTTY && !process.env.CI\n  const clear = canClearScreen ? clearScreen : () => {}\n\n  function format(type: LogType, msg: string, options: LogErrorOptions = {}) {\n    if (options.timestamp) {\n      let tag = ''\n      if (type === 'info') {\n        tag = colors.cyan(colors.bold(prefix))\n      }\n      else if (type === 'warn') {\n        tag = colors.yellow(colors.bold(prefix))\n      }\n      else {\n        tag = colors.red(colors.bold(prefix))\n      }\n      const environment = (options as any).environment ? `${(options as any).environment} ` : ''\n      return `${colors.dim(getTimeFormatter().format(new Date()))} ${tag} ${environment}${msg}`\n    }\n    else {\n      return msg\n    }\n  }\n\n  function output(type: LogType, msg: string, options: LogErrorOptions = {}) {\n    if (thresh >= LogLevels[type]) {\n      const method = type === 'info' ? 'log' : type\n\n      if (options.error) {\n        loggedErrors.add(options.error)\n      }\n      if (canClearScreen) {\n        if (type === lastType && msg === lastMsg) {\n          sameCount++\n          clear(console)\n          console[method](\n            format(type, msg, options),\n            colors.yellow(`(x${sameCount + 1})`),\n          )\n        }\n        else {\n          sameCount = 0\n          lastMsg = msg\n          lastType = type\n          if (options.clear) {\n            clear(console)\n          }\n          console[method](format(type, msg, options))\n        }\n      }\n      else {\n        console[method](format(type, msg, options))\n      }\n    }\n  }\n\n  const warnedMessages = new Set<string>()\n\n  const logger: Logger = {\n    hasWarned: false,\n    info(msg, opts) {\n      output('info', msg, opts)\n    },\n    warn(msg, opts) {\n      logger.hasWarned = true\n      output('warn', msg, opts)\n    },\n    warnOnce(msg, opts) {\n      if (warnedMessages.has(msg)) {\n        return\n      }\n      logger.hasWarned = true\n      output('warn', msg, opts)\n      warnedMessages.add(msg)\n    },\n    error(msg, opts) {\n      logger.hasWarned = true\n      output('error', msg, opts)\n    },\n    clearScreen(type) {\n      if (thresh >= LogLevels[type]) {\n        clear(console)\n      }\n    },\n    hasErrorLogged(error) {\n      return loggedErrors.has(error)\n    },\n  }\n\n  return logger\n}\n\n// silence warning by Vite for statically not analyzable dynamic import\nexport function silenceImportViteIgnoreWarning(logger: Logger): Logger {\n  return {\n    ...logger,\n    warn(msg, options) {\n      if (msg.includes('The above dynamic import cannot be analyzed by Vite')) {\n        return\n      }\n      logger.warn(msg, options)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/watch-filter.ts",
    "content": "import type { Writable } from 'node:stream'\nimport readline from 'node:readline'\nimport { stripVTControlCharacters } from 'node:util'\nimport { createDefer } from '@vitest/utils/helpers'\nimport c from 'tinyrainbow'\nimport { stdout as getStdout } from '../utils/base'\n\nconst MAX_RESULT_COUNT = 10\nconst SELECTION_MAX_INDEX = 7\nconst ESC = '\\u001B['\n\nexport interface FilterObject {\n  key: string\n  toString: () => string\n}\n\ntype FilterItemType<T extends 'string' | 'object' = 'string'> = T extends 'string' ? string : FilterObject\ntype FilterFuncType<T extends 'string' | 'object' = 'string'> = (keyword: string) => Promise<FilterItemType<T>[]> | FilterItemType<T>[]\n\nexport class WatchFilter<T extends 'string' | 'object' = 'string'> {\n  private filterRL: readline.Interface\n  private currentKeyword: string | undefined = undefined\n  private message: string\n  private results: FilterItemType<T>[] = []\n  private selectionIndex = -1\n  private onKeyPress?: (str: string, key: any) => void\n  private stdin: NodeJS.ReadStream\n  private stdout: NodeJS.WriteStream | Writable\n\n  constructor(\n    message: string,\n    stdin: NodeJS.ReadStream = process.stdin,\n    stdout: NodeJS.WriteStream | Writable = getStdout(),\n  ) {\n    this.message = message\n    this.stdin = stdin\n    this.stdout = stdout\n\n    this.filterRL = readline.createInterface({\n      input: this.stdin,\n      escapeCodeTimeout: 50,\n    })\n    readline.emitKeypressEvents(this.stdin, this.filterRL)\n    if (this.stdin.isTTY) {\n      this.stdin.setRawMode(true)\n    }\n  }\n\n  public async filter(filterFunc: FilterFuncType<T>): Promise<string | undefined> {\n    this.write(this.promptLine())\n\n    const resultPromise = createDefer<string | undefined>()\n\n    this.onKeyPress = this.filterHandler(filterFunc, (result) => {\n      resultPromise.resolve(result)\n    })\n    this.stdin.on('keypress', this.onKeyPress)\n    try {\n      return await resultPromise\n    }\n    finally {\n      this.close()\n    }\n  }\n\n  private filterHandler(\n    filterFunc: FilterFuncType<T>,\n    onSubmit: (result?: string) => void,\n  ) {\n    return async (str: string | undefined, key: any) => {\n      switch (true) {\n        case key.sequence === '\\x7F':\n          if (this.currentKeyword && this.currentKeyword?.length > 1) {\n            this.currentKeyword = this.currentKeyword?.slice(0, -1)\n          }\n          else {\n            this.currentKeyword = undefined\n          }\n\n          break\n        case key?.ctrl && key?.name === 'c':\n        case key?.name === 'escape':\n          this.write(`${ESC}1G${ESC}0J`) // clean content\n          onSubmit(undefined)\n          return\n        case key?.name === 'enter':\n        case key?.name === 'return': {\n          const selection = this.results[this.selectionIndex]\n          const result = typeof selection === 'string'\n            ? selection\n            : selection?.key\n          onSubmit(\n            result || this.currentKeyword || '',\n          )\n          this.currentKeyword = undefined\n          break\n        }\n        case key?.name === 'up':\n          if (this.selectionIndex && this.selectionIndex > 0) {\n            this.selectionIndex--\n          }\n          else {\n            this.selectionIndex = -1\n          }\n\n          break\n        case key?.name === 'down':\n          if (this.selectionIndex < this.results.length - 1) {\n            this.selectionIndex++\n          }\n          else if (this.selectionIndex >= this.results.length - 1) {\n            this.selectionIndex = this.results.length - 1\n          }\n\n          break\n        case !key?.ctrl && !key?.meta:\n          if (this.currentKeyword === undefined) {\n            this.currentKeyword = str\n          }\n          else {\n            this.currentKeyword += str || ''\n          }\n          break\n      }\n\n      if (this.currentKeyword) {\n        this.results = await filterFunc(this.currentKeyword)\n      }\n\n      this.render()\n    }\n  }\n\n  private render() {\n    let printStr = this.promptLine()\n    if (!this.currentKeyword) {\n      printStr += '\\nPlease input filter pattern'\n    }\n    else if (this.currentKeyword && this.results.length === 0) {\n      printStr += '\\nPattern matches no results'\n    }\n    else {\n      const resultCountLine\n        = this.results.length === 1\n          ? `Pattern matches ${this.results.length} result`\n          : `Pattern matches ${this.results.length} results`\n\n      let resultBody = ''\n\n      if (this.results.length > MAX_RESULT_COUNT) {\n        const offset\n          = this.selectionIndex > SELECTION_MAX_INDEX\n            ? this.selectionIndex - SELECTION_MAX_INDEX\n            : 0\n        const displayResults = this.results.slice(\n          offset,\n          MAX_RESULT_COUNT + offset,\n        )\n        const remainingResultCount\n          = this.results.length - offset - displayResults.length\n\n        resultBody = `${displayResults\n          .map((result, index) =>\n            index + offset === this.selectionIndex\n              ? c.green(` › ${result}`)\n              : c.dim(` › ${result}`),\n          )\n          .join('\\n')}`\n        if (remainingResultCount > 0) {\n          resultBody\n            += '\\n'\n              + `${c.dim(\n                `   ...and ${remainingResultCount} more ${\n                  remainingResultCount === 1 ? 'result' : 'results'\n                }`,\n              )}`\n        }\n      }\n      else {\n        resultBody = this.results\n          .map((result, index) =>\n            index === this.selectionIndex\n              ? c.green(` › ${result}`)\n              : c.dim(` › ${result}`),\n          )\n          .join('\\n')\n      }\n\n      printStr += `\\n${resultCountLine}\\n${resultBody}`\n    }\n    this.eraseAndPrint(printStr)\n    this.restoreCursor()\n  }\n\n  private keywordOffset() {\n    return `? ${this.message} › `.length + 1\n  }\n\n  private promptLine() {\n    return `${c.cyan('?')} ${c.bold(this.message)} › ${\n      this.currentKeyword || ''\n    }`\n  }\n\n  private eraseAndPrint(str: string) {\n    let rows = 0\n    const lines = str.split(/\\r?\\n/)\n    for (const line of lines) {\n      const columns = 'columns' in this.stdout ? this.stdout.columns : 80\n\n      // We have to take care of screen width in case of long lines\n      rows += 1 + Math.floor(Math.max(stripVTControlCharacters(line).length - 1, 0) / columns)\n    }\n\n    this.write(`${ESC}1G`) // move to the beginning of the line\n    this.write(`${ESC}J`) // erase down\n    this.write(str)\n    this.write(`${ESC}${rows - 1}A`) // moving up lines\n  }\n\n  private close() {\n    this.filterRL.close()\n    if (this.onKeyPress) {\n      this.stdin.removeListener('keypress', this.onKeyPress)\n    }\n\n    if (this.stdin.isTTY) {\n      this.stdin.setRawMode(false)\n    }\n  }\n\n  private restoreCursor() {\n    const cursortPos\n      = this.keywordOffset() + (this.currentKeyword?.length || 0)\n    this.write(`${ESC}${cursortPos}G`)\n  }\n\n  private write(data: string) {\n    this.stdout.write(data)\n  }\n\n  public getLastResults(): string[] {\n    return this.results.map(r => (typeof r === 'string' ? r : r.toString()))\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/node/watcher.ts",
    "content": "import type { Vitest } from './core'\nimport type { TestProject } from './project'\nimport { readFileSync } from 'node:fs'\nimport { noop, slash } from '@vitest/utils/helpers'\nimport { resolve } from 'pathe'\nimport pm from 'picomatch'\n\nexport class VitestWatcher {\n  /**\n   * Modules that will be invalidated on the next run.\n   */\n  public readonly invalidates: Set<string> = new Set()\n  /**\n   * Test files that have changed and need to be rerun.\n   */\n  public readonly changedTests: Set<string> = new Set()\n\n  private readonly _onRerun: ((file: string) => void)[] = []\n\n  constructor(private vitest: Vitest) {}\n\n  /**\n   * Register a handler that will be called when test files need to be rerun.\n   * The callback can receive several files in case the changed file is imported by several test files.\n   * Several invocations of this method will add multiple handlers.\n   * @internal\n   */\n  onWatcherRerun(cb: (file: string) => void): this {\n    this._onRerun.push(cb)\n    return this\n  }\n\n  public close(): void {\n    this.vitest.vite.watcher.close()\n  }\n\n  public unregisterWatcher: () => void = noop\n  public registerWatcher(): this {\n    const watcher = this.vitest.vite.watcher\n\n    if (this.vitest.config.forceRerunTriggers.length) {\n      watcher.add(this.vitest.config.forceRerunTriggers)\n    }\n\n    watcher.on('change', this.onFileChange)\n    watcher.on('unlink', this.onFileDelete)\n    watcher.on('add', this.onFileCreate)\n\n    this.unregisterWatcher = () => {\n      watcher.off('change', this.onFileChange)\n      watcher.off('unlink', this.onFileDelete)\n      watcher.off('add', this.onFileCreate)\n      this.unregisterWatcher = noop\n    }\n    return this\n  }\n\n  private scheduleRerun(file: string): void {\n    this._onRerun.forEach(cb => cb(file))\n  }\n\n  private getTestFilesFromWatcherTrigger(id: string): boolean {\n    if (!this.vitest.config.watchTriggerPatterns) {\n      return false\n    }\n    let triggered = false\n    this.vitest.config.watchTriggerPatterns.forEach((definition) => {\n      const exec = definition.pattern.exec(id)\n      if (exec) {\n        const files = definition.testsToRun(id, exec)\n        if (Array.isArray(files)) {\n          triggered = true\n          files.forEach(file => this.changedTests.add(resolve(this.vitest.config.root, file)))\n        }\n        else if (typeof files === 'string') {\n          triggered = true\n          this.changedTests.add(resolve(this.vitest.config.root, files))\n        }\n      }\n    })\n    return triggered\n  }\n\n  public onFileChange = (id: string): void => {\n    id = slash(id)\n    this.vitest.logger.clearHighlightCache(id)\n    this.vitest.invalidateFile(id)\n    const testFiles = this.getTestFilesFromWatcherTrigger(id)\n    if (testFiles) {\n      this.scheduleRerun(id)\n    }\n    else {\n      const needsRerun = this.handleFileChanged(id)\n      if (needsRerun) {\n        this.scheduleRerun(id)\n      }\n    }\n  }\n\n  public onFileDelete = (id: string): void => {\n    id = slash(id)\n    this.vitest.logger.clearHighlightCache(id)\n    this.invalidates.add(id)\n\n    if (this.vitest.state.filesMap.has(id)) {\n      this.vitest.projects.forEach(project => project._removeCachedTestFile(id))\n      this.vitest.state.filesMap.delete(id)\n      this.vitest.cache.results.removeFromCache(id)\n      this.vitest.cache.stats.removeStats(id)\n      this.changedTests.delete(id)\n      this.vitest.report('onTestRemoved', id)\n    }\n  }\n\n  public onFileCreate = (id: string): void => {\n    id = slash(id)\n    this.vitest.invalidateFile(id)\n\n    const testFiles = this.getTestFilesFromWatcherTrigger(id)\n    if (testFiles) {\n      this.scheduleRerun(id)\n      return\n    }\n\n    let fileContent: string | undefined\n\n    const matchingProjects: TestProject[] = []\n    this.vitest.projects.forEach((project) => {\n      if (project.matchesTestGlob(id, () => (fileContent ??= readFileSync(id, 'utf-8')))) {\n        matchingProjects.push(project)\n      }\n    })\n\n    if (matchingProjects.length > 0) {\n      this.changedTests.add(id)\n      this.scheduleRerun(id)\n    }\n    else {\n      // it's possible that file was already there but watcher triggered \"add\" event instead\n      const needsRerun = this.handleFileChanged(id)\n      if (needsRerun) {\n        this.scheduleRerun(id)\n      }\n    }\n  }\n\n  private handleSetupFile(filepath: string) {\n    let isSetupFile: boolean = false\n\n    this.vitest.projects.forEach((project) => {\n      if (!project.config.setupFiles.includes(filepath)) {\n        return\n      }\n\n      this.vitest.state.filesMap.forEach((files) => {\n        files.forEach((file) => {\n          if (file.projectName === project.name) {\n            isSetupFile = true\n            this.changedTests.add(file.filepath)\n          }\n        })\n      })\n    })\n\n    return isSetupFile\n  }\n\n  /**\n   * @returns A value indicating whether rerun is needed (changedTests was mutated)\n   */\n  private handleFileChanged(filepath: string): boolean {\n    if (this.changedTests.has(filepath) || this.invalidates.has(filepath)) {\n      return false\n    }\n\n    if (pm.isMatch(filepath, this.vitest.config.forceRerunTriggers)) {\n      this.vitest.state.getFilepaths().forEach(file => this.changedTests.add(file))\n      return true\n    }\n\n    if (this.handleSetupFile(filepath)) {\n      return true\n    }\n\n    const projects = this.vitest.projects.filter((project) => {\n      return project._getViteEnvironments().some(({ moduleGraph }) => {\n        return moduleGraph.getModulesByFile(filepath)?.size\n      })\n    })\n    if (!projects.length) {\n      // if there are no modules it's possible that server was restarted\n      // we don't have information about importers anymore, so let's check if the file is a test file at least\n      if (this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some(project => project._isCachedTestFile(filepath))) {\n        this.changedTests.add(filepath)\n        return true\n      }\n      return false\n    }\n\n    const files: string[] = []\n\n    for (const project of projects) {\n      const environmentMods = project._getViteEnvironments().map(({ moduleGraph }) => moduleGraph.getModulesByFile(filepath))\n      if (!environmentMods.length) {\n        continue\n      }\n\n      this.invalidates.add(filepath)\n\n      // one of test files that we already run, or one of test files that we can run\n      if (this.vitest.state.filesMap.has(filepath) || project._isCachedTestFile(filepath)) {\n        this.changedTests.add(filepath)\n        files.push(filepath)\n        continue\n      }\n\n      let rerun = false\n      for (const mods of environmentMods) {\n        for (const mod of mods || []) {\n          mod.importers.forEach((i) => {\n            if (!i.file) {\n              return\n            }\n\n            const needsRerun = this.handleFileChanged(i.file)\n            if (needsRerun) {\n              rerun = true\n            }\n          })\n        }\n      }\n\n      if (rerun) {\n        files.push(filepath)\n      }\n    }\n\n    return !!files.length\n  }\n}\n\nexport interface WatcherTriggerPattern {\n  pattern: RegExp\n  testsToRun: (\n    file: string,\n    match: RegExpMatchArray,\n  ) => string[] | string | null | undefined | void\n}\n"
  },
  {
    "path": "packages/vitest/src/paths.ts",
    "content": "import { resolve } from 'node:path'\nimport url from 'node:url'\n\nexport const rootDir: string = resolve(url.fileURLToPath(import.meta.url), '../../')\nexport const distDir: string = resolve(\n  url.fileURLToPath(import.meta.url),\n  '../../dist',\n)\n"
  },
  {
    "path": "packages/vitest/src/public/browser.ts",
    "content": "export {\n  startCoverageInsideWorker,\n  stopCoverageInsideWorker,\n  takeCoverageInsideWorker,\n} from '../integrations/coverage'\nexport {\n  loadDiffConfig,\n  loadSnapshotSerializers,\n  setupCommonEnv,\n} from '../runtime/setup-common'\nexport { type OTELCarrier, Traces } from '../utils/traces'\nexport { collectTests, startTests } from '@vitest/runner'\nexport * as SpyModule from '@vitest/spy'\nexport type { LoupeOptions, ParsedStack, StringifyOptions } from '@vitest/utils'\nexport {\n  browserFormat,\n  format,\n  inspect,\n  stringify,\n} from '@vitest/utils/display'\nexport { processError } from '@vitest/utils/error'\nexport { getType } from '@vitest/utils/helpers'\nexport {\n  DecodedMap,\n  getOriginalPosition,\n} from '@vitest/utils/source-map'\nexport { getSafeTimers, setSafeTimers } from '@vitest/utils/timers'\n\nexport interface FsOptions {\n  encoding?: BufferEncoding\n  flag?: string | number\n}\n\nexport interface BrowserCommands {\n  readFile: (\n    path: string,\n    options?: BufferEncoding | FsOptions,\n  ) => Promise<string>\n  writeFile: (\n    path: string,\n    content: string,\n    options?: BufferEncoding | (FsOptions & { mode?: number | string }),\n  ) => Promise<void>\n  removeFile: (path: string) => Promise<void>\n}\n\nexport interface CDPSession {\n  // methods are defined by the provider type augmentation\n}\n\n/**\n * @internal\n */\nexport const __INTERNAL: {\n  _asLocator: (lang: 'javascript', selector: string) => string\n  _createLocator: (selector: string) => any\n  _extendedMethods: Set<string>\n} = {\n  _extendedMethods: new Set(),\n} as any\n"
  },
  {
    "path": "packages/vitest/src/public/config.ts",
    "content": "import type { ConfigEnv, UserConfig as ViteUserConfig } from 'vite'\n\nimport type {\n  TestProjectConfiguration,\n  TestProjectInlineConfiguration,\n  UserConfig,\n  UserProjectConfigExport,\n  UserProjectConfigFn,\n  UserWorkspaceConfig,\n} from '../node/types/config'\nimport '../node/types/vite'\n\n// will import vitest declare test in module 'vite'\nexport {\n  configDefaults,\n  coverageConfigDefaults,\n  defaultBrowserPort,\n  defaultExclude,\n  defaultInclude,\n} from '../defaults'\nexport type { WatcherTriggerPattern } from '../node/watcher'\nexport type { TestTagDefinition } from '@vitest/runner'\nexport { mergeConfig } from 'vite'\nexport type { Plugin } from 'vite'\n\nexport type { ConfigEnv, UserConfig as TestUserConfig, ViteUserConfig }\nexport type {\n  TestProjectConfiguration,\n  TestProjectInlineConfiguration,\n  UserProjectConfigExport,\n  UserProjectConfigFn,\n  UserWorkspaceConfig,\n}\nexport type ViteUserConfigFnObject = (env: ConfigEnv) => ViteUserConfig\nexport type ViteUserConfigFnPromise = (env: ConfigEnv) => Promise<ViteUserConfig>\nexport type ViteUserConfigFn = (\n  env: ConfigEnv,\n) => ViteUserConfig | Promise<ViteUserConfig>\nexport type ViteUserConfigExport\n  = | ViteUserConfig\n    | Promise<ViteUserConfig>\n    | ViteUserConfigFnObject\n    | ViteUserConfigFnPromise\n    | ViteUserConfigFn\n\nexport function defineConfig(config: ViteUserConfig): ViteUserConfig\nexport function defineConfig(\n  config: Promise<ViteUserConfig>,\n): Promise<ViteUserConfig>\nexport function defineConfig(config: ViteUserConfigFnObject): ViteUserConfigFnObject\nexport function defineConfig(config: ViteUserConfigFnPromise): ViteUserConfigFnPromise\nexport function defineConfig(config: ViteUserConfigExport): ViteUserConfigExport\nexport function defineConfig(config: ViteUserConfigExport): ViteUserConfigExport {\n  return config\n}\n\nexport function defineProject(config: UserWorkspaceConfig): UserWorkspaceConfig\nexport function defineProject(config: Promise<UserWorkspaceConfig>): Promise<UserWorkspaceConfig>\nexport function defineProject(config: UserProjectConfigFn): UserProjectConfigFn\nexport function defineProject(config: UserProjectConfigExport): UserProjectConfigExport\nexport function defineProject(config: UserProjectConfigExport): UserProjectConfigExport {\n  return config\n}\n"
  },
  {
    "path": "packages/vitest/src/public/coverage.ts",
    "content": "export { BaseCoverageProvider } from '../node/coverage'\n\nconsole.warn('Importing from \"vitest/coverage\" is deprecated since Vitest 4.1. Please use \"vitest/node\" instead.')\n"
  },
  {
    "path": "packages/vitest/src/public/environments.ts",
    "content": "export { environments as builtinEnvironments } from '../integrations/env/index'\nexport { populateGlobal } from '../integrations/env/utils'\nexport type {\n  Environment,\n  EnvironmentReturn,\n  VmEnvironmentReturn,\n} from '../types/environment'\n\nconsole.warn('Importing from \"vitest/environments\" is deprecated since Vitest 4.1. Please use \"vitest/runtime\" instead.')\n"
  },
  {
    "path": "packages/vitest/src/public/index.ts",
    "content": "import type { SerializedTestSpecification } from '../runtime/types/utils'\nimport type {\n  ModuleDefinitionDiagnostic,\n  ModuleDefinitionDurationsDiagnostic,\n  ModuleDefinitionLocation,\n  SourceModuleDiagnostic,\n  SourceModuleLocations,\n  UntrackedModuleDefinitionDiagnostic,\n} from '../types/module-locations'\nimport '../types/global'\n\n// eslint-disable-next-line ts/no-namespace\nexport declare namespace Experimental {\n  export {\n    ModuleDefinitionDiagnostic,\n    ModuleDefinitionDurationsDiagnostic,\n    ModuleDefinitionLocation,\n    SourceModuleDiagnostic,\n    SourceModuleLocations,\n    UntrackedModuleDefinitionDiagnostic,\n  }\n}\n\nexport type {\n  ExternalResult,\n  TransformResultWithSource,\n  WebSocketEvents,\n  WebSocketHandlers,\n  WebSocketRPC,\n} from '../api/types'\nexport { assert, chai, createExpect, expect, should } from '../integrations/chai'\nexport { inject } from '../integrations/inject'\n\nexport { vi, vitest } from '../integrations/vi'\nexport type { VitestUtils } from '../integrations/vi'\nexport { bench } from '../runtime/benchmark'\n\nexport type {\n  RuntimeConfig,\n  SerializedConfig,\n  SerializedCoverageConfig,\n} from '../runtime/config'\n\nexport { VitestEvaluatedModules as EvaluatedModules } from '../runtime/moduleRunner/evaluatedModules'\n\nexport { NodeBenchmarkRunner as BenchmarkRunner } from '../runtime/runners/benchmark'\nexport { TestRunner } from '../runtime/runners/test'\nexport type {\n  BenchFactory,\n  BenchFunction,\n  Benchmark,\n  BenchmarkAPI,\n  BenchmarkResult,\n  BenchOptions,\n  BenchTask,\n  BenchTaskResult,\n} from '../runtime/types/benchmark'\nexport { assertType } from '../typecheck/assertType'\n\nexport type { AssertType } from '../typecheck/assertType'\nexport { expectTypeOf } from '../typecheck/expectTypeOf'\nexport type { ExpectTypeOf } from '../typecheck/expectTypeOf'\n\nexport type { BrowserTesterOptions } from '../types/browser'\nexport type {\n  AfterSuiteRunMeta,\n  LabelColor,\n  ModuleGraphData,\n  ParsedStack,\n  ProvidedContext,\n  TestError,\n  UserConsoleLog,\n} from '../types/general'\n\nexport type {\n  RunnerRPC,\n  RuntimeRPC,\n} from '../types/rpc'\n\nexport type { BrowserUI } from '../types/ui'\n\nexport type {\n  ContextRPC,\n  ContextTestEnvironment,\n  TestExecutionMethod,\n  WorkerGlobalState,\n} from '../types/worker'\nexport type {\n  Assertion,\n  AsymmetricMatchersContaining,\n  DeeplyAllowMatchers,\n  ExpectPollOptions,\n  ExpectStatic,\n  JestAssertion,\n  RawMatcherFn as Matcher,\n  ExpectationResult as MatcherResult,\n  Matchers,\n  MatcherState,\n} from '@vitest/expect'\nexport {\n  afterAll,\n  afterEach,\n  aroundAll,\n  aroundEach,\n  beforeAll,\n  beforeEach,\n  describe,\n  it,\n  onTestFailed,\n  onTestFinished,\n  recordArtifact,\n  suite,\n  test,\n} from '@vitest/runner'\nexport type {\n  ImportDuration,\n  OnTestFailedHandler,\n  OnTestFinishedHandler,\n  RunMode,\n  Task as RunnerTask,\n  TaskBase as RunnerTaskBase,\n  TaskEventPack as RunnerTaskEventPack,\n  TaskResult as RunnerTaskResult,\n  TaskResultPack as RunnerTaskResultPack,\n  Test as RunnerTestCase,\n  File as RunnerTestFile,\n  Suite as RunnerTestSuite,\n  SuiteAPI,\n  SuiteCollector,\n  SuiteFactory,\n  SuiteOptions,\n  TaskCustomOptions,\n  TaskMeta,\n  TaskState,\n  TestAnnotation,\n  TestAnnotationArtifact,\n  TestAPI,\n  TestArtifact,\n  TestArtifactBase,\n  TestArtifactLocation,\n  TestArtifactRegistry,\n  TestAttachment,\n  TestContext,\n  TestFunction,\n  TestOptions,\n  VitestRunnerConfig as TestRunnerConfig,\n\n  TestTags,\n  VitestRunner as VitestTestRunner,\n} from '@vitest/runner'\n\nexport type { CancelReason } from '@vitest/runner'\n\nexport type {\n  SnapshotData,\n  SnapshotMatchOptions,\n  SnapshotResult,\n  SnapshotSerializer,\n  SnapshotStateOptions,\n  SnapshotSummary,\n  SnapshotUpdateState,\n  UncheckedSnapshot,\n} from '@vitest/snapshot'\n\nexport type {\n  Mock,\n  MockContext,\n  Mocked,\n  MockedClass,\n  MockedFunction,\n  MockedObject,\n  MockInstance,\n  MockResult,\n  MockResultIncomplete,\n  MockResultReturn,\n  MockResultThrow,\n  MockSettledResult,\n  MockSettledResultFulfilled,\n  MockSettledResultIncomplete,\n  MockSettledResultRejected,\n} from '@vitest/spy'\n\nexport type { SerializedError } from '@vitest/utils'\nexport type { SerializedTestSpecification }\nexport type { DiffOptions } from '@vitest/utils/diff'\n"
  },
  {
    "path": "packages/vitest/src/public/node.ts",
    "content": "import * as vite from 'vite'\nimport { Vitest } from '../node/core'\n\nexport const version: string = Vitest.version\n\nexport { isValidApiRequest } from '../api/check'\nexport { escapeTestName } from '../node/ast-collect'\nexport type { CacheKeyIdGenerator, CacheKeyIdGeneratorContext } from '../node/cache/fsModuleCache'\nexport { parseCLI } from '../node/cli/cac'\nexport type { CliParseOptions } from '../node/cli/cac'\nexport type { CliOptions } from '../node/cli/cli-api'\nexport { startVitest } from '../node/cli/cli-api'\nexport { resolveApiServerConfig } from '../node/config/resolveConfig'\nexport type {\n  OnServerRestartHandler,\n  OnTestsRerunHandler,\n  Vitest,\n  VitestOptions,\n} from '../node/core'\nexport { BaseCoverageProvider } from '../node/coverage'\nexport { createVitest } from '../node/create'\nexport { GitNotFoundError, FilesNotFoundError as TestsNotFoundError } from '../node/errors'\nexport { VitestPackageInstaller } from '../node/packageInstaller'\nexport { VitestPlugin } from '../node/plugins'\nexport { resolveConfig } from '../node/plugins/publicConfig'\nexport { resolveFsAllow } from '../node/plugins/utils'\nexport type { ProcessPool } from '../node/pool'\nexport { getFilePoolName } from '../node/pool'\nexport { createMethodsRPC } from '../node/pools/rpc'\nexport type {\n  PoolOptions,\n  PoolRunnerInitializer,\n  PoolTask,\n  PoolWorker,\n  WorkerRequest,\n  WorkerResponse,\n} from '../node/pools/types'\nexport { ForksPoolWorker } from '../node/pools/workers/forksWorker'\nexport { ThreadsPoolWorker } from '../node/pools/workers/threadsWorker'\nexport { TypecheckPoolWorker } from '../node/pools/workers/typecheckWorker'\nexport { VmForksPoolWorker } from '../node/pools/workers/vmForksWorker'\nexport { VmThreadsPoolWorker } from '../node/pools/workers/vmThreadsWorker'\nexport type { SerializedTestProject, TestProject } from '../node/project'\n\nexport {\n  AgentReporter,\n  BenchmarkReporter,\n  BenchmarkReportsMap,\n  DefaultReporter,\n  DotReporter,\n  GithubActionsReporter,\n  HangingProcessReporter,\n  JsonReporter,\n  JUnitReporter,\n  ReportersMap,\n  TapFlatReporter,\n  TapReporter,\n  VerboseBenchmarkReporter,\n  VerboseReporter,\n} from '../node/reporters'\nexport type {\n  BaseReporter,\n  BenchmarkBuiltinReporters,\n  BuiltinReporterOptions,\n  BuiltinReporters,\n  JsonAssertionResult,\n  JsonTestResult,\n  JsonTestResults,\n  ReportedHookContext,\n  Reporter,\n  TestRunEndReason,\n} from '../node/reporters'\nexport type { HTMLOptions } from '../node/reporters/html'\nexport type { JsonOptions } from '../node/reporters/json'\n\nexport type { JUnitOptions } from '../node/reporters/junit'\n\nexport type {\n  ModuleDiagnostic,\n  TaskOptions,\n\n  TestCase,\n  TestCollection,\n  TestDiagnostic,\n  TestModule,\n  TestModuleState,\n  TestResult,\n  TestResultFailed,\n  TestResultPassed,\n  TestResultSkipped,\n  TestState,\n  TestSuite,\n  TestSuiteState,\n} from '../node/reporters/reported-tasks'\nexport { experimental_getRunnerTask } from '../node/reporters/reported-tasks'\nexport { BaseSequencer } from '../node/sequencers/BaseSequencer'\n\nexport type {\n  TestSequencer,\n  TestSequencerConstructor,\n} from '../node/sequencers/types'\nexport { registerConsoleShortcuts } from '../node/stdin'\nexport type { TestSpecification, TestSpecificationOptions } from '../node/test-specification'\nexport type { BenchmarkUserOptions } from '../node/types/benchmark'\n\nexport type {\n  _BrowserNames,\n  BrowserBuiltinProvider,\n  BrowserCommand,\n  BrowserCommandContext,\n  BrowserConfigOptions,\n  BrowserInstanceOption,\n  BrowserModuleMocker,\n  BrowserOrchestrator,\n  BrowserProvider,\n  BrowserProviderOption,\n  BrowserScript,\n  BrowserServerFactory,\n  BrowserServerOptions,\n  BrowserServerState,\n  BrowserServerStateSession,\n  CDPSession,\n  ParentProjectBrowser,\n  ProjectBrowser,\n  ResolvedBrowserOptions,\n  ToMatchScreenshotComparators,\n  ToMatchScreenshotOptions,\n} from '../node/types/browser'\nexport const createViteServer: typeof vite.createServer = vite.createServer\nexport type {\n  ApiConfig,\n  BuiltinEnvironment,\n  CSSModuleScopeStrategy,\n  DepsOptimizationOptions,\n  EnvironmentOptions,\n  InlineConfig,\n  Pool,\n  ProjectConfig,\n  ResolvedConfig,\n  ResolvedProjectConfig,\n  ResolveSnapshotPathHandler,\n  ResolveSnapshotPathHandlerContext,\n  RuntimeConfig,\n  SequenceHooks,\n  SequenceSetupFiles,\n  UserConfig as TestUserConfig,\n  TypecheckConfig,\n  UserWorkspaceConfig,\n  VitestEnvironment,\n  VitestRunMode,\n} from '../node/types/config'\nexport type {\n  BaseCoverageOptions,\n  CoverageIstanbulOptions,\n  CoverageOptions,\n  CoverageProvider,\n  CoverageProviderModule,\n  CoverageReporter,\n  CoverageV8Options,\n  CustomProviderOptions,\n  ReportContext,\n  ResolvedCoverageOptions,\n} from '../node/types/coverage'\n\nexport type { VitestPluginContext } from '../node/types/plugin'\nexport type { TestRunResult } from '../node/types/tests'\nexport type { WorkerContext } from '../node/types/worker'\nexport { isFileServingAllowed } from '../node/vite'\nexport { createViteLogger } from '../node/viteLogger'\nexport type { WatcherTriggerPattern } from '../node/watcher'\n\nexport { distDir, rootDir } from '../paths'\n\nexport type {\n  CollectLineNumbers as TypeCheckCollectLineNumbers,\n  CollectLines as TypeCheckCollectLines,\n  Context as TypeCheckContext,\n  TscErrorInfo as TypeCheckErrorInfo,\n  RawErrsMap as TypeCheckRawErrorsMap,\n  RootAndTarget as TypeCheckRootAndTarget,\n} from '../typecheck/types'\n\nexport type { TestExecutionMethod as TestExecutionType } from '../types/worker'\nexport { createDebugger } from '../utils/debugger'\nexport type {\n  RunnerTask,\n  RunnerTaskResult,\n  RunnerTaskResultPack,\n  RunnerTestCase,\n  RunnerTestFile,\n  RunnerTestSuite,\n} from './index'\nexport { generateFileHash } from '@vitest/runner/utils'\nexport type { SerializedError } from '@vitest/utils'\n\nexport {\n  esbuildVersion,\n  isCSSRequest,\n  isFileLoadingAllowed,\n  parseAst,\n  parseAstAsync,\n  rollupVersion,\n  version as viteVersion,\n} from 'vite'\n\n// rolldownVersion is exported only by rolldown-vite\nexport const rolldownVersion: string | undefined = (vite as any).rolldownVersion\n\nexport type * as Vite from 'vite'\n"
  },
  {
    "path": "packages/vitest/src/public/reporters.ts",
    "content": "export {\n  AgentReporter,\n  BenchmarkReporter,\n  BenchmarkReportsMap,\n  DefaultReporter,\n  DotReporter,\n  GithubActionsReporter,\n  HangingProcessReporter,\n  JsonReporter,\n  JUnitReporter,\n  ReportersMap,\n  TapFlatReporter,\n  TapReporter,\n  VerboseBenchmarkReporter,\n  VerboseReporter,\n} from '../node/reporters'\nexport type {\n  BaseReporter,\n  BenchmarkBuiltinReporters,\n  BuiltinReporterOptions,\n  BuiltinReporters,\n  JsonAssertionResult,\n  JsonTestResult,\n  JsonTestResults,\n  ReportedHookContext,\n  Reporter,\n  TestRunEndReason,\n} from '../node/reporters'\n\nconsole.warn('Importing from \"vitest/reporters\" is deprecated since Vitest 4.1. Please use \"vitest/node\" instead.')\n"
  },
  {
    "path": "packages/vitest/src/public/runners.ts",
    "content": "export { NodeBenchmarkRunner } from '../runtime/runners/benchmark'\nexport { TestRunner as VitestTestRunner } from '../runtime/runners/test'\nexport type { VitestRunner } from '@vitest/runner'\n\nconsole.warn('Importing from \"vitest/runners\" is deprecated since Vitest 4.1. Please use \"vitest\" instead.')\n"
  },
  {
    "path": "packages/vitest/src/public/runtime.ts",
    "content": "// #region internal\nimport type { TestModuleRunner } from '../runtime/moduleRunner/testModuleRunner'\nimport { VitestModuleEvaluator } from '../runtime/moduleRunner/moduleEvaluator'\nimport { VitestModuleRunner } from '../runtime/moduleRunner/moduleRunner'\nimport {\n  startVitestModuleRunner,\n  VITEST_VM_CONTEXT_SYMBOL,\n} from '../runtime/moduleRunner/startVitestModuleRunner'\nimport { getWorkerState } from '../runtime/utils'\n// #endregion\n\nexport { environments as builtinEnvironments } from '../integrations/env/index'\nexport { populateGlobal } from '../integrations/env/utils'\nexport { VitestNodeSnapshotEnvironment as VitestSnapshotEnvironment } from '../integrations/snapshot/environments/node'\nexport type {\n  Environment,\n  EnvironmentReturn,\n  VmEnvironmentReturn,\n} from '../types/environment'\nexport type { VitestRunner, VitestRunnerConfig } from '@vitest/runner'\nexport type { SnapshotEnvironment } from '@vitest/snapshot/environment'\n\n// #region internal\n/**\n * @internal\n */\nexport interface __TYPES {\n  VitestModuleRunner: VitestModuleRunner\n  TestModuleRunner: TestModuleRunner\n}\n/**\n * @internal\n */\nexport const __INTERNAL: {\n  VitestModuleEvaluator: typeof VitestModuleEvaluator\n  startVitestModuleRunner: typeof startVitestModuleRunner\n  VITEST_VM_CONTEXT_SYMBOL: typeof VITEST_VM_CONTEXT_SYMBOL\n  getWorkerState: typeof getWorkerState\n} = {\n  VitestModuleEvaluator,\n  VitestModuleRunner,\n  startVitestModuleRunner,\n  VITEST_VM_CONTEXT_SYMBOL,\n  getWorkerState,\n} as any\n// #endregion\n"
  },
  {
    "path": "packages/vitest/src/public/snapshot.ts",
    "content": "export { VitestNodeSnapshotEnvironment as VitestSnapshotEnvironment } from '../integrations/snapshot/environments/node'\nexport type { SnapshotEnvironment } from '@vitest/snapshot/environment'\n\nconsole.warn('Importing from \"vitest/snapshot\" is deprecated since Vitest 4.1. Please use \"vitest/runtime\" instead.')\n"
  },
  {
    "path": "packages/vitest/src/public/suite.ts",
    "content": "export { getBenchFn, getBenchOptions } from '../runtime/benchmark'\nexport {\n  createTaskCollector,\n  getCurrentSuite,\n  getCurrentTest,\n  getFn,\n  getHooks,\n  setFn,\n  setHooks,\n} from '@vitest/runner'\nexport type { VitestRunner, VitestRunnerConfig } from '@vitest/runner'\nexport { createChainable } from '@vitest/runner/utils'\n\nconsole.warn('Importing from \"vitest/suite\" is deprecated since Vitest 4.1. Please use static methods of \"TestRunner\" from the \"vitest\" entry point instead: e.g., `TestRunner.getCurrentTest()`.')\n"
  },
  {
    "path": "packages/vitest/src/public/worker.ts",
    "content": "export { runBaseTests, setupBaseEnvironment as setupEnvironment } from '../runtime/workers/base'\nexport { init } from '../runtime/workers/init'\n"
  },
  {
    "path": "packages/vitest/src/runtime/benchmark.ts",
    "content": "import type { Test } from '@vitest/runner'\nimport type { BenchFunction, BenchmarkAPI, BenchOptions } from './types/benchmark'\nimport { getCurrentSuite } from '@vitest/runner'\nimport { createChainable } from '@vitest/runner/utils'\nimport { noop } from '@vitest/utils/helpers'\nimport { getWorkerState } from './utils'\n\nconst benchFns = new WeakMap<Test, BenchFunction>()\nconst benchOptsMap = new WeakMap()\n\nexport function getBenchOptions(key: Test): BenchOptions {\n  return benchOptsMap.get(key)\n}\n\nexport function getBenchFn(key: Test): BenchFunction {\n  return benchFns.get(key)!\n}\n\nexport const bench: BenchmarkAPI = createBenchmark(function (\n  name,\n  fn: BenchFunction = noop,\n  options: BenchOptions = {},\n) {\n  if (getWorkerState().config.mode !== 'benchmark') {\n    throw new Error('`bench()` is only available in benchmark mode.')\n  }\n\n  const task = getCurrentSuite().task(formatName(name), {\n    ...this,\n    meta: {\n      benchmark: true,\n    },\n  })\n  benchFns.set(task, fn)\n  benchOptsMap.set(task, options)\n  // vitest runner sets mode to `todo` if handler is not passed down\n  // but we store handler separetly\n  if (!this.todo && task.mode === 'todo') {\n    task.mode = 'run'\n  }\n})\n\nfunction createBenchmark(\n  fn: (\n    this: Record<'skip' | 'only' | 'todo', boolean | undefined>,\n    name: string | Function,\n    fn?: BenchFunction,\n    options?: BenchOptions,\n  ) => void,\n) {\n  const benchmark = createChainable(\n    ['skip', 'only', 'todo'],\n    fn,\n  ) as BenchmarkAPI\n\n  benchmark.skipIf = (condition: any) =>\n    (condition ? benchmark.skip : benchmark) as BenchmarkAPI\n  benchmark.runIf = (condition: any) =>\n    (condition ? benchmark : benchmark.skip) as BenchmarkAPI\n\n  return benchmark as BenchmarkAPI\n}\n\nfunction formatName(name: string | Function) {\n  return typeof name === 'string'\n    ? name\n    : typeof name === 'function'\n      ? name.name || '<anonymous>'\n      : String(name)\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/cleanup.ts",
    "content": "const listeners = new Set<() => unknown>()\n\nexport function addCleanupListener(listener: () => unknown): void {\n  listeners.add(listener)\n}\n\nexport function removeCleanupListener(listener: () => unknown): void {\n  listeners.delete(listener)\n}\n\nexport async function cleanup(): Promise<void> {\n  const promises = [...listeners].map(l => l())\n  await Promise.all(promises)\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/config.ts",
    "content": "import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers'\nimport type { PrettyFormatOptions } from '@vitest/pretty-format'\nimport type { SequenceHooks, SequenceSetupFiles, SerializableRetry, TestTagDefinition } from '@vitest/runner'\nimport type { SnapshotEnvironment, SnapshotUpdateState } from '@vitest/snapshot'\nimport type { SerializedDiffOptions } from '@vitest/utils/diff'\n\n/**\n * Config that tests have access to.\n */\nexport interface SerializedConfig {\n  name: string | undefined\n  globals: boolean\n  base: string | undefined\n  snapshotEnvironment?: string\n  disableConsoleIntercept: boolean | undefined\n  runner: string | undefined\n  isolate: boolean\n  maxWorkers: number\n  mode: 'test' | 'benchmark'\n  bail: number | undefined\n  environmentOptions?: Record<string, any>\n  root: string\n  setupFiles: string[]\n  passWithNoTests: boolean\n  testNamePattern: RegExp | undefined\n  allowOnly: boolean\n  testTimeout: number\n  hookTimeout: number\n  clearMocks: boolean\n  mockReset: boolean\n  restoreMocks: boolean\n  unstubGlobals: boolean\n  unstubEnvs: boolean\n  // TODO: make optional\n  fakeTimers: FakeTimerInstallOpts\n  maxConcurrency: number\n  defines: Record<string, any>\n  expect: {\n    requireAssertions?: boolean\n    poll?: {\n      timeout?: number\n      interval?: number\n    }\n  }\n  printConsoleTrace: boolean | undefined\n  sequence: {\n    shuffle?: boolean\n    concurrent?: boolean\n    seed: number\n    hooks: SequenceHooks\n    setupFiles: SequenceSetupFiles\n  }\n  deps: {\n    web: {\n      transformAssets?: boolean\n      transformCss?: boolean\n      transformGlobPattern?: RegExp | RegExp[]\n    }\n    optimizer: Record<string, { enabled: boolean }>\n    interopDefault: boolean | undefined\n    moduleDirectories: string[] | undefined\n  }\n  snapshotOptions: {\n    updateSnapshot: SnapshotUpdateState\n    expand: boolean | undefined\n    snapshotFormat: PrettyFormatOptions | undefined\n    /**\n     * only exists for tests, not available in the main process\n     */\n    snapshotEnvironment: SnapshotEnvironment\n  }\n  pool: string\n  snapshotSerializers: string[]\n  chaiConfig: {\n    includeStack?: boolean\n    showDiff?: boolean\n    truncateThreshold?: number\n  } | undefined\n  api: {\n    allowExec: boolean | undefined\n    allowWrite: boolean | undefined\n  }\n  diff: string | SerializedDiffOptions | undefined\n  retry: SerializableRetry\n  includeTaskLocation: boolean | undefined\n  inspect: boolean | string | undefined\n  inspectBrk: boolean | string | undefined\n  inspector: {\n    enabled?: boolean\n    port?: number\n    host?: string\n    waitForDebugger?: boolean\n  }\n  watch: boolean\n  env: Record<string, any>\n  browser: {\n    name: string\n    headless: boolean\n    isolate: boolean\n    fileParallelism: boolean\n    ui: boolean\n    viewport: {\n      width: number\n      height: number\n    }\n    locators: {\n      testIdAttribute: string\n    }\n    screenshotFailures: boolean\n    providerOptions: {\n      // for playwright\n      actionTimeout?: number\n    }\n    trace: BrowserTraceViewMode\n    trackUnhandledErrors: boolean\n    detailsPanelPosition: 'right' | 'bottom'\n  }\n  standalone: boolean\n  logHeapUsage: boolean | undefined\n  detectAsyncLeaks: boolean\n  coverage: SerializedCoverageConfig\n  benchmark: {\n    includeSamples: boolean\n  } | undefined\n  serializedDefines: string\n  experimental: {\n    fsModuleCache: boolean\n    importDurations: {\n      print: boolean | 'on-warn'\n      limit: number\n      failOnDanger: boolean\n      thresholds: {\n        warn: number\n        danger: number\n      }\n    }\n    viteModuleRunner: boolean\n    nodeLoader: boolean\n    openTelemetry: {\n      enabled: boolean\n      sdkPath?: string\n      browserSdkPath?: string\n    } | undefined\n  }\n  tags: TestTagDefinition[]\n  tagsFilter: string[] | undefined\n  strictTags: boolean\n  slowTestThreshold: number | undefined\n}\n\nexport interface SerializedCoverageConfig {\n  provider: 'istanbul' | 'v8' | 'custom' | undefined\n  reportsDirectory: string\n  htmlDir: string | undefined\n  enabled: boolean\n  customProviderModule: string | undefined\n}\n\nexport type RuntimeConfig = Pick<\n  SerializedConfig,\n  | 'allowOnly'\n  | 'testTimeout'\n  | 'hookTimeout'\n  | 'clearMocks'\n  | 'mockReset'\n  | 'restoreMocks'\n  | 'fakeTimers'\n  | 'maxConcurrency'\n  | 'expect'\n  | 'printConsoleTrace'\n> & {\n  sequence?: {\n    hooks?: SequenceHooks\n  }\n}\n\nexport type RuntimeOptions = Partial<RuntimeConfig>\nexport type BrowserTraceViewMode = 'on' | 'off' | 'on-first-retry' | 'on-all-retries' | 'retain-on-failure'\n"
  },
  {
    "path": "packages/vitest/src/runtime/console.ts",
    "content": "import type { WorkerGlobalState } from '../types/worker'\nimport { Console } from 'node:console'\nimport { relative } from 'node:path'\nimport { Writable } from 'node:stream'\nimport { getSafeTimers } from '@vitest/utils/timers'\nimport c from 'tinyrainbow'\nimport { RealDate } from '../integrations/mock/date'\nimport { getWorkerState } from './utils'\n\nexport const UNKNOWN_TEST_ID = '__vitest__unknown_test__'\n\nfunction getTaskIdByStack(root: string) {\n  const stack = new Error('STACK_TRACE_ERROR').stack?.split('\\n')\n\n  if (!stack) {\n    return UNKNOWN_TEST_ID\n  }\n\n  const index = stack.findIndex(line => line.includes('at Console.value'))\n  const line = index === -1 ? null : stack[index + 2]\n\n  if (!line) {\n    return UNKNOWN_TEST_ID\n  }\n\n  const filepath = line.match(/at\\s(.*)\\s?/)?.[1]\n\n  if (filepath) {\n    return relative(root, filepath)\n  }\n\n  return UNKNOWN_TEST_ID\n}\n\nexport function createCustomConsole(defaultState?: WorkerGlobalState): Console {\n  const stdoutBuffer = new Map<string, any[]>()\n  const stderrBuffer = new Map<string, any[]>()\n  const timers = new Map<\n    string,\n    { stdoutTime: number; stderrTime: number; cancel?: () => void }\n  >()\n\n  const { queueMicrotask } = getSafeTimers()\n\n  function queueCancelableMicrotask(callback: () => void) {\n    let canceled = false\n    queueMicrotask(() => {\n      if (!canceled) {\n        callback()\n      }\n    })\n    return () => {\n      canceled = true\n    }\n  }\n\n  const state = () => defaultState || getWorkerState()\n\n  // group sync console.log calls with micro task\n  function schedule(taskId: string) {\n    const timer = timers.get(taskId)!\n    const { stdoutTime, stderrTime } = timer\n    timer.cancel?.()\n    timer.cancel = queueCancelableMicrotask(() => {\n      if (stderrTime < stdoutTime) {\n        sendStderr(taskId)\n        sendStdout(taskId)\n      }\n      else {\n        sendStdout(taskId)\n        sendStderr(taskId)\n      }\n    })\n  }\n  function sendStdout(taskId: string) {\n    sendBuffer('stdout', taskId)\n  }\n\n  function sendStderr(taskId: string) {\n    sendBuffer('stderr', taskId)\n  }\n\n  function sendBuffer(type: 'stdout' | 'stderr', taskId: string) {\n    const buffers = type === 'stdout' ? stdoutBuffer : stderrBuffer\n    const buffer = buffers.get(taskId)\n    if (!buffer) {\n      return\n    }\n    if (state().config.printConsoleTrace) {\n      buffer.forEach(([buffer, origin]) => {\n        sendLog(type, taskId, String(buffer), buffer.length, origin)\n      })\n    }\n    else {\n      const content = buffer.map(i => String(i[0])).join('')\n      sendLog(type, taskId, content, buffer.length)\n    }\n    const timer = timers.get(taskId)!\n    buffers.delete(taskId)\n    if (type === 'stderr') {\n      timer.stderrTime = 0\n    }\n    else {\n      timer.stdoutTime = 0\n    }\n  }\n\n  function sendLog(\n    type: 'stderr' | 'stdout',\n    taskId: string,\n    content: string,\n    size: number,\n    origin?: string,\n  ) {\n    const timer = timers.get(taskId)!\n    const time = type === 'stderr' ? timer.stderrTime : timer.stdoutTime\n    state().rpc.onUserConsoleLog({\n      type,\n      content: content || '<empty line>',\n      taskId,\n      time: time || RealDate.now(),\n      size,\n      origin,\n    })\n  }\n\n  const stdout = new Writable({\n    write(data, encoding, callback) {\n      const s = state()\n      const id\n        = s?.current?.id\n          || s?.current?.suite?.id\n          || s.current?.file.id\n          || getTaskIdByStack(s.config.root)\n      let timer = timers.get(id)\n      if (timer) {\n        timer.stdoutTime = timer.stdoutTime || RealDate.now()\n      }\n      else {\n        timer = {\n          stdoutTime: RealDate.now(),\n          stderrTime: RealDate.now(),\n        }\n        timers.set(id, timer)\n      }\n      let buffer = stdoutBuffer.get(id)\n      if (!buffer) {\n        buffer = []\n        stdoutBuffer.set(id, buffer)\n      }\n      if (state().config.printConsoleTrace) {\n        const limit = Error.stackTraceLimit\n        Error.stackTraceLimit = limit + 6\n        const stack = new Error('STACK_TRACE').stack\n        const trace = stack?.split('\\n').slice(7).join('\\n')\n        Error.stackTraceLimit = limit\n        buffer.push([data, trace])\n      }\n      else {\n        buffer.push([data, undefined])\n      }\n      schedule(id)\n      callback()\n    },\n  })\n  const stderr = new Writable({\n    write(data, encoding, callback) {\n      const s = state()\n      const id\n        = s?.current?.id\n          || s?.current?.suite?.id\n          || s.current?.file.id\n          || getTaskIdByStack(s.config.root)\n      let timer = timers.get(id)\n      if (timer) {\n        timer.stderrTime = timer.stderrTime || RealDate.now()\n      }\n      else {\n        timer = {\n          stderrTime: RealDate.now(),\n          stdoutTime: RealDate.now(),\n        }\n        timers.set(id, timer)\n      }\n      let buffer = stderrBuffer.get(id)\n      if (!buffer) {\n        buffer = []\n        stderrBuffer.set(id, buffer)\n      }\n      if (state().config.printConsoleTrace) {\n        const limit = Error.stackTraceLimit\n        Error.stackTraceLimit = limit + 6\n        const stack = new Error('STACK_TRACE').stack?.split('\\n')\n        Error.stackTraceLimit = limit\n        const isTrace = stack?.some(line =>\n          line.includes('at Console.trace'),\n        )\n        if (isTrace) {\n          buffer.push([data, undefined])\n        }\n        else {\n          const trace = stack?.slice(7).join('\\n')\n          Error.stackTraceLimit = limit\n          buffer.push([data, trace])\n        }\n      }\n      else {\n        buffer.push([data, undefined])\n      }\n      schedule(id)\n      callback()\n    },\n  })\n  return new Console({\n    stdout,\n    stderr,\n    colorMode: c.isColorSupported,\n    groupIndentation: 2,\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/detect-async-leaks.ts",
    "content": "import type { AsyncLeak } from '../types/general'\nimport { createHook } from 'node:async_hooks'\n\ninterface PossibleLeak extends AsyncLeak {\n  isActive: () => boolean\n}\n\nconst IGNORED_TYPES = new Set([\n  'DNSCHANNEL',\n  'ELDHISTOGRAM',\n  'PerformanceObserver',\n  'RANDOMBYTESREQUEST',\n  'SIGNREQUEST',\n  'STREAM_END_OF_STREAM',\n  'TCPWRAP',\n  'TIMERWRAP',\n  'TLSWRAP',\n  'ZLIB',\n])\n\nexport function detectAsyncLeaks(testFile: string, projectName: string): () => Promise<AsyncLeak[]> {\n  const resources = new Map<number, PossibleLeak>()\n\n  const hook = createHook({\n    init(asyncId, type, triggerAsyncId, resource) {\n      if (IGNORED_TYPES.has(type)) {\n        return\n      }\n\n      let stack = ''\n      const limit = Error.stackTraceLimit\n\n      // VitestModuleEvaluator's async wrapper of node:vm causes out-of-bound stack traces, simply skip it.\n      // Crash fixed in https://github.com/vitejs/vite/pull/21585\n      try {\n        Error.stackTraceLimit = 100\n        stack = new Error('VITEST_DETECT_ASYNC_LEAKS').stack || ''\n      }\n      catch {\n        return\n      }\n      finally {\n        Error.stackTraceLimit = limit\n      }\n\n      if (!stack.includes(testFile)) {\n        const trigger = resources.get(triggerAsyncId)\n\n        if (!trigger) {\n          return\n        }\n\n        stack = trigger.stack\n      }\n\n      let isActive = isActiveDefault\n\n      if ('hasRef' in resource) {\n        const ref = new WeakRef(resource as { hasRef: () => boolean })\n\n        isActive = () => ref.deref()?.hasRef() ?? false\n      }\n\n      resources.set(asyncId, { type, stack, projectName, filename: testFile, isActive })\n    },\n    destroy(asyncId) {\n      if (resources.get(asyncId)?.type !== 'PROMISE') {\n        resources.delete(asyncId)\n      }\n    },\n    promiseResolve(asyncId) {\n      resources.delete(asyncId)\n    },\n  })\n\n  hook.enable()\n\n  return async function collect() {\n    await Promise.resolve(setImmediate)\n\n    hook.disable()\n\n    const leaks = []\n\n    for (const resource of resources.values()) {\n      if (resource.isActive()) {\n        leaks.push({\n          stack: resource.stack,\n          type: resource.type,\n          filename: resource.filename,\n          projectName: resource.projectName,\n        })\n      }\n    }\n\n    resources.clear()\n\n    return leaks\n  }\n}\n\nfunction isActiveDefault() {\n  return true\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/external-executor.ts",
    "content": "import type vm from 'node:vm'\nimport type { RuntimeRPC } from '../types/rpc'\nimport type { FileMap } from './vm/file-map'\nimport type { VMModule } from './vm/types'\nimport fs from 'node:fs'\nimport { isBuiltin } from 'node:module'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { isBareImport } from '@vitest/utils/helpers'\nimport { findNearestPackageData } from '@vitest/utils/resolver'\nimport { extname, normalize } from 'pathe'\nimport { CommonjsExecutor } from './vm/commonjs-executor'\nimport { EsmExecutor } from './vm/esm-executor'\nimport { ViteExecutor } from './vm/vite-executor'\n\nconst { existsSync } = fs\n\n// always defined when we use vm pool\nconst nativeResolve = import.meta.resolve!\n\nexport interface ExternalModulesExecutorOptions {\n  context: vm.Context\n  fileMap: FileMap\n  packageCache: Map<string, any>\n  transform: RuntimeRPC['transform']\n  interopDefault?: boolean\n  viteClientModule: Record<string, unknown>\n}\n\ninterface ModuleInformation {\n  type:\n    | 'data'\n    | 'builtin'\n    | 'vite'\n    | 'wasm'\n    | 'module'\n    | 'commonjs'\n    | 'network'\n  url: string\n  path: string\n}\n\n// TODO: improve Node.js strict mode support in #2854\nexport class ExternalModulesExecutor {\n  private cjs: CommonjsExecutor\n  private esm: EsmExecutor\n  private vite: ViteExecutor\n  private context: vm.Context\n  private fs: FileMap\n  private resolvers: ((id: string, parent: string) => string | undefined)[]\n    = []\n\n  #networkSupported: boolean | null = null\n\n  constructor(private options: ExternalModulesExecutorOptions) {\n    this.context = options.context\n\n    this.fs = options.fileMap\n    this.esm = new EsmExecutor(this, {\n      context: this.context,\n    })\n    this.cjs = new CommonjsExecutor({\n      context: this.context,\n      importModuleDynamically: this.importModuleDynamically,\n      fileMap: options.fileMap,\n      interopDefault: options.interopDefault,\n    })\n    this.vite = new ViteExecutor({\n      esmExecutor: this.esm,\n      context: this.context,\n      transform: options.transform,\n      viteClientModule: options.viteClientModule,\n    })\n    this.resolvers = [this.vite.resolve]\n  }\n\n  async import(identifier: string): Promise<object> {\n    const module = await this.createModule(identifier)\n    await this.esm.evaluateModule(module)\n    return module.namespace\n  }\n\n  require(identifier: string): any {\n    return this.cjs.require(identifier)\n  }\n\n  createRequire(identifier: string): NodeJS.Require {\n    return this.cjs.createRequire(identifier)\n  }\n\n  // dynamic import can be used in both ESM and CJS, so we have it in the executor\n  public importModuleDynamically = async (\n    specifier: string,\n    referencer: VMModule,\n  ): Promise<VMModule> => {\n    const module = await this.resolveModule(specifier, referencer.identifier)\n    return await this.esm.evaluateModule(module)\n  }\n\n  public resolveModule = async (specifier: string, referencer: string): Promise<VMModule> => {\n    let identifier = this.resolve(specifier, referencer) as\n      | string\n      | Promise<string>\n\n    if (identifier instanceof Promise) {\n      identifier = await identifier\n    }\n\n    return await this.createModule(identifier)\n  }\n\n  public resolve(specifier: string, parent: string): string {\n    for (const resolver of this.resolvers) {\n      const id = resolver(specifier, parent)\n      if (id) {\n        return id\n      }\n    }\n\n    // import.meta.resolve can be asynchronous in older +18 Node versions\n    return nativeResolve(specifier, parent)\n  }\n\n  private getModuleInformation(identifier: string): ModuleInformation {\n    if (identifier.startsWith('data:')) {\n      return { type: 'data', url: identifier, path: identifier }\n    }\n\n    const extension = extname(identifier)\n    if (extension === '.node' || isBuiltin(identifier)) {\n      return { type: 'builtin', url: identifier, path: identifier }\n    }\n\n    if (\n      this.isNetworkSupported\n      && (identifier.startsWith('http:') || identifier.startsWith('https:'))\n    ) {\n      return { type: 'network', url: identifier, path: identifier }\n    }\n\n    const isFileUrl = identifier.startsWith('file://')\n    const pathUrl = isFileUrl\n      ? fileURLToPath(identifier.split('?')[0])\n      : identifier\n    const fileUrl = isFileUrl ? identifier : pathToFileURL(pathUrl).toString()\n\n    let type: 'module' | 'commonjs' | 'vite' | 'wasm'\n    if (this.vite.canResolve(fileUrl)) {\n      type = 'vite'\n    }\n    else if (extension === '.mjs') {\n      type = 'module'\n    }\n    else if (extension === '.cjs') {\n      type = 'commonjs'\n    }\n    else if (extension === '.wasm') {\n      // still experimental on NodeJS --experimental-wasm-modules\n      // cf. ESM_FILE_FORMAT(url) in https://nodejs.org/docs/latest-v20.x/api/esm.html#resolution-algorithm\n      type = 'wasm'\n    }\n    else {\n      const pkgData = findNearestPackageData(normalize(pathUrl))\n      type = pkgData.type === 'module' ? 'module' : 'commonjs'\n    }\n\n    return { type, path: pathUrl, url: fileUrl }\n  }\n\n  private createModule(identifier: string): VMModule | Promise<VMModule> {\n    const { type, url, path } = this.getModuleInformation(identifier)\n\n    // create ERR_MODULE_NOT_FOUND on our own since latest NodeJS's import.meta.resolve doesn't throw on non-existing namespace or path\n    // https://github.com/nodejs/node/pull/49038\n    if (\n      (type === 'module' || type === 'commonjs' || type === 'wasm')\n      && !existsSync(path)\n    ) {\n      const error = new Error(`Cannot find ${isBareImport(path) ? 'package' : 'module'} '${path}'`);\n      (error as any).code = 'ERR_MODULE_NOT_FOUND'\n      throw error\n    }\n\n    switch (type) {\n      case 'data':\n        return this.esm.createDataModule(identifier)\n      case 'builtin':\n        return this.cjs.getCoreSyntheticModule(identifier)\n      case 'vite':\n        return this.vite.createViteModule(url)\n      case 'wasm':\n        return this.esm.createWebAssemblyModule(url, () =>\n          this.fs.readBuffer(path))\n      case 'module':\n        return this.esm.createEsModule(url, () =>\n          this.fs.readFileAsync(path))\n      case 'commonjs':\n        return this.cjs.getCjsSyntheticModule(path, identifier)\n      case 'network':\n        return this.esm.createNetworkModule(url)\n      default: {\n        const _deadend: never = type\n        return _deadend\n      }\n    }\n  }\n\n  private get isNetworkSupported() {\n    if (this.#networkSupported == null) {\n      if (process.execArgv.includes('--experimental-network-imports')) {\n        this.#networkSupported = true\n      }\n      else if (\n        process.env.NODE_OPTIONS?.includes('--experimental-network-imports')\n      ) {\n        this.#networkSupported = true\n      }\n      else {\n        this.#networkSupported = false\n      }\n    }\n    return this.#networkSupported\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/inspector.ts",
    "content": "import type { ContextRPC } from '../types/worker'\nimport type { SerializedConfig } from './config'\nimport { createRequire } from 'node:module'\nimport { pathToFileURL } from 'node:url'\n\nconst __require = createRequire(import.meta.url)\nlet inspector: typeof import('node:inspector')\nlet session: InstanceType<typeof inspector.Session>\n\n/**\n * Enables debugging inside `worker_threads` and `child_process`.\n * Should be called as early as possible when worker/process has been set up.\n */\nexport function setupInspect(ctx: ContextRPC) {\n  const config = ctx.config\n  const isEnabled = config.inspector.enabled\n\n  if (isEnabled) {\n    inspector = __require('node:inspector')\n    // Inspector may be open already if \"isolate: false\" is used\n    const isOpen = inspector.url() !== undefined\n\n    if (!isOpen) {\n      inspector.open(\n        config.inspector.port,\n        config.inspector.host,\n        config.inspector.waitForDebugger,\n      )\n\n      if (config.inspectBrk) {\n        const firstTestFile = typeof ctx.files[0] === 'string'\n          ? ctx.files[0]\n          : ctx.files[0].filepath\n\n        // Stop at first test file\n        if (firstTestFile) {\n          session = new inspector.Session()\n          session.connect()\n\n          session.post('Debugger.enable')\n          session.post('Debugger.setBreakpointByUrl', {\n            lineNumber: 0,\n            url: pathToFileURL(firstTestFile),\n          })\n        }\n      }\n    }\n  }\n\n  const keepOpen = shouldKeepOpen(config)\n\n  return function cleanup(): void {\n    if (isEnabled && !keepOpen && inspector) {\n      inspector.close()\n      session?.disconnect()\n    }\n  }\n}\n\nexport function closeInspector(config: SerializedConfig): void {\n  const keepOpen = shouldKeepOpen(config)\n\n  if (inspector && !keepOpen) {\n    inspector.close()\n    session?.disconnect()\n  }\n}\n\nfunction shouldKeepOpen(config: SerializedConfig) {\n  // In watch mode the inspector can persist re-runs if isolation is disabled and a single worker is used\n  return config.watch && config.isolate === false && config.maxWorkers === 1\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/listeners.ts",
    "content": "import type { ModuleRunner } from 'vite/module-runner'\n\nconst cleanupListeners = new Set<() => unknown>()\nconst moduleRunnerListeners = new Set<(runner: ModuleRunner) => unknown>()\n\nexport function onCleanup(cb: () => unknown): void {\n  cleanupListeners.add(cb)\n}\n\nexport async function cleanup(): Promise<void> {\n  await Promise.all([...cleanupListeners].map(l => l()))\n}\n\nexport function onModuleRunner(cb: (runner: ModuleRunner) => unknown): void {\n  moduleRunnerListeners.add(cb)\n}\n\nexport function emitModuleRunner(moduleRunner: ModuleRunner): void {\n  moduleRunnerListeners.forEach(l => l(moduleRunner))\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/bareModuleMocker.ts",
    "content": "import type { MockedModule, MockedModuleType, ModuleMockContext, TestModuleMocker } from '@vitest/mocker'\nimport type { MockFactory, MockOptions, PendingSuiteMock } from '../../types/mocker'\nimport type { Traces } from '../../utils/traces'\nimport { isAbsolute } from 'node:path'\nimport { MockerRegistry, mockObject } from '@vitest/mocker'\nimport { findMockRedirect } from '@vitest/mocker/redirect'\n\nexport interface BareModuleMockerOptions {\n  /**\n   * @internal\n   */\n  traces: Traces\n  spyModule?: typeof import('@vitest/spy')\n  root: string\n  moduleDirectories: string[]\n  resolveId: (id: string, importer?: string) => Promise<{\n    id: string\n    file: string\n    url: string\n  } | null>\n  getCurrentTestFilepath: () => string | undefined\n}\n\nexport class BareModuleMocker implements TestModuleMocker {\n  static pendingIds: PendingSuiteMock[] = []\n  protected spyModule?: typeof import('@vitest/spy')\n  protected primitives: {\n    Object: typeof Object\n    Function: typeof Function\n    RegExp: typeof RegExp\n    Array: typeof Array\n    Map: typeof Map\n    Error: typeof Error\n    Symbol: typeof Symbol\n  }\n\n  protected registries: Map<string, MockerRegistry> = new Map<string, MockerRegistry>()\n\n  protected mockContext: ModuleMockContext = {\n    callstack: null,\n  }\n\n  protected _otel: Traces\n\n  constructor(protected options: BareModuleMockerOptions) {\n    this._otel = options.traces\n    this.primitives = {\n      Object,\n      Error,\n      Function,\n      RegExp,\n      Symbol: globalThis.Symbol,\n      Array,\n      Map,\n    }\n\n    if (options.spyModule) {\n      this.spyModule = options.spyModule\n    }\n  }\n\n  protected get root(): string {\n    return this.options.root\n  }\n\n  protected get moduleDirectories(): string[] {\n    return this.options.moduleDirectories || []\n  }\n\n  protected getMockerRegistry(): MockerRegistry {\n    const suite = this.getSuiteFilepath()\n    if (!this.registries.has(suite)) {\n      this.registries.set(suite, new MockerRegistry())\n    }\n    return this.registries.get(suite)!\n  }\n\n  public reset(): void {\n    this.registries.clear()\n  }\n\n  protected invalidateModuleById(_id: string): void {\n    // implemented by mockers that control the module runner\n  }\n\n  protected isModuleDirectory(path: string): boolean {\n    return this.moduleDirectories.some(dir => path.includes(dir))\n  }\n\n  public getSuiteFilepath(): string {\n    return this.options.getCurrentTestFilepath() || 'global'\n  }\n\n  protected createError(message: string, codeFrame?: string): Error {\n    const Error = this.primitives.Error\n    const error = new Error(message)\n    Object.assign(error, { codeFrame })\n    return error\n  }\n\n  public async resolveId(rawId: string, importer?: string): Promise<{\n    id: string\n    url: string\n    external: string | null\n  }> {\n    return this._otel.$(\n      'vitest.mocker.resolve_id',\n      {\n        attributes: {\n          'vitest.module.raw_id': rawId,\n          'vitest.module.importer': rawId,\n        },\n      },\n      async (span) => {\n        const result = await this.options.resolveId(rawId, importer)\n        if (!result) {\n          span.addEvent('could not resolve id, fallback to unresolved values')\n          const id = normalizeModuleId(rawId)\n          span.setAttributes({\n            'vitest.module.id': id,\n            'vitest.module.url': rawId,\n            'vitest.module.external': id,\n            'vitest.module.fallback': true,\n          })\n          return {\n            id,\n            url: rawId,\n            external: id,\n          }\n        }\n        // external is node_module or unresolved module\n        // for example, some people mock \"vscode\" and don't have it installed\n        const external\n          = !isAbsolute(result.file) || this.isModuleDirectory(result.file) ? normalizeModuleId(rawId) : null\n        const id = normalizeModuleId(result.id)\n        span.setAttributes({\n          'vitest.module.id': id,\n          'vitest.module.url': result.url,\n          'vitest.module.external': external ?? false,\n        })\n        return {\n          ...result,\n          id,\n          external,\n        }\n      },\n    )\n  }\n\n  public async resolveMocks(): Promise<void> {\n    if (!BareModuleMocker.pendingIds.length) {\n      return\n    }\n\n    await Promise.all(\n      BareModuleMocker.pendingIds.map(async (mock) => {\n        const { id, url, external } = await this.resolveId(\n          mock.id,\n          mock.importer,\n        )\n        if (mock.action === 'unmock') {\n          this.unmockPath(id)\n        }\n        if (mock.action === 'mock') {\n          this.mockPath(\n            mock.id,\n            id,\n            url,\n            external,\n            mock.type,\n            mock.factory,\n          )\n        }\n      }),\n    )\n\n    BareModuleMocker.pendingIds = []\n  }\n\n  // public method to avoid circular dependency\n  public getMockContext(): ModuleMockContext {\n    return this.mockContext\n  }\n\n  // path used to store mocked dependencies\n  public getMockPath(dep: string) {\n    return `mock:${dep}`\n  }\n\n  public getDependencyMock(id: string): MockedModule | undefined {\n    const registry = this.getMockerRegistry()\n    return registry.getById(fixLeadingSlashes(id))\n  }\n\n  public getDependencyMockByUrl(url: string): MockedModule | undefined {\n    const registry = this.getMockerRegistry()\n    return registry.get(url)\n  }\n\n  public findMockRedirect(mockPath: string, external: string | null): string | null {\n    return findMockRedirect(this.root, mockPath, external)\n  }\n\n  public mockObject(\n    object: Record<string | symbol, any>,\n    moduleType?: 'automock' | 'autospy',\n  ): Record<string | symbol, any>\n  public mockObject(\n    object: Record<string | symbol, any>,\n    mockExports: Record<string | symbol, any> | undefined,\n    moduleType?: 'automock' | 'autospy',\n  ): Record<string | symbol, any>\n  public mockObject(\n    object: Record<string | symbol, any>,\n    mockExportsOrModuleType?: Record<string | symbol, any> | 'automock' | 'autospy',\n    moduleType?: 'automock' | 'autospy',\n  ): Record<string | symbol, any> {\n    let mockExports: Record<string | symbol, any> | undefined\n    if (mockExportsOrModuleType === 'automock' || mockExportsOrModuleType === 'autospy') {\n      moduleType = mockExportsOrModuleType\n      mockExports = undefined\n    }\n    else {\n      mockExports = mockExportsOrModuleType\n    }\n    moduleType ??= 'automock'\n    const createMockInstance = this.spyModule?.createMockInstance\n    if (!createMockInstance) {\n      throw this.createError(\n        '[vitest] `spyModule` is not defined. This is a Vitest error. Please open a new issue with reproduction.',\n      )\n    }\n    return mockObject(\n      {\n        globalConstructors: this.primitives,\n        createMockInstance,\n        type: moduleType,\n      },\n      object,\n      mockExports,\n    )\n  }\n\n  public unmockPath(id: string): void {\n    const registry = this.getMockerRegistry()\n\n    registry.deleteById(id)\n    this.invalidateModuleById(id)\n  }\n\n  public mockPath(\n    originalId: string,\n    id: string,\n    url: string,\n    external: string | null,\n    mockType: MockedModuleType | undefined,\n    factory: MockFactory | undefined,\n  ): void {\n    const registry = this.getMockerRegistry()\n\n    if (mockType === 'manual') {\n      registry.register('manual', originalId, id, url, factory!)\n    }\n    else if (mockType === 'autospy') {\n      registry.register('autospy', originalId, id, url)\n    }\n    else {\n      const redirect = this.findMockRedirect(id, external)\n      if (redirect) {\n        registry.register('redirect', originalId, id, url, redirect)\n      }\n      else {\n        registry.register('automock', originalId, id, url)\n      }\n    }\n\n    // every time the mock is registered, we remove the previous one from the cache\n    this.invalidateModuleById(id)\n  }\n\n  async importActual<T>(_rawId: string, _importer: string, _callstack?: string[] | null): Promise<T> {\n    throw new Error(`importActual is not implemented`)\n  }\n\n  async importMock<T>(_rawId: string, _importer: string, _callstack?: string[] | null): Promise<T> {\n    throw new Error(`importMock is not implemented`)\n  }\n\n  public queueMock(\n    id: string,\n    importer: string,\n    factoryOrOptions?: MockFactory | MockOptions,\n  ): void {\n    const mockType = getMockType(factoryOrOptions)\n    BareModuleMocker.pendingIds.push({\n      action: 'mock',\n      id,\n      importer,\n      factory: typeof factoryOrOptions === 'function' ? factoryOrOptions : undefined,\n      type: mockType,\n    })\n  }\n\n  public queueUnmock(id: string, importer: string): void {\n    BareModuleMocker.pendingIds.push({\n      action: 'unmock',\n      id,\n      importer,\n    })\n  }\n}\n\ndeclare module 'vite/module-runner' {\n  interface EvaluatedModuleNode {\n    /**\n     * @internal\n     */\n    mockedExports?: Record<string, any>\n  }\n}\n\nfunction getMockType(factoryOrOptions?: MockFactory | MockOptions): MockedModuleType {\n  if (!factoryOrOptions) {\n    return 'automock'\n  }\n  if (typeof factoryOrOptions === 'function') {\n    return 'manual'\n  }\n  return factoryOrOptions.spy ? 'autospy' : 'automock'\n}\n\n// unique id that is not available as \"$bare_import\" like \"test\"\n// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix\nconst prefixedBuiltins = new Set([\n  'node:sea',\n  'node:sqlite',\n  'node:test',\n  'node:test/reporters',\n])\n\nconst isWindows = process.platform === 'win32'\n\n// transform file url to id\n// virtual:custom -> virtual:custom\n// \\0custom -> \\0custom\n// /root/id -> /id\n// /root/id.js -> /id.js\n// C:/root/id.js -> /id.js\n// C:\\root\\id.js -> /id.js\n// TODO: expose this in vite/module-runner\nexport function normalizeModuleId(file: string): string {\n  if (prefixedBuiltins.has(file)) {\n    return file\n  }\n\n  // unix style, but Windows path still starts with the drive letter to check the root\n  const unixFile = slash(file)\n    .replace(/^\\/@fs\\//, isWindows ? '' : '/')\n    .replace(/^node:/, '')\n    .replace(/^\\/+/, '/')\n\n  // if it's not in the root, keep it as a path, not a URL\n  return unixFile.replace(/^file:\\//, '/')\n}\n\nconst windowsSlashRE = /\\\\/g\nfunction slash(p: string): string {\n  return p.replace(windowsSlashRE, '/')\n}\n\nconst multipleSlashRe = /^\\/+/\n// module-runner incorrectly replaces file:///path with `///path`\nfunction fixLeadingSlashes(id: string): string {\n  if (id.startsWith('//')) {\n    return id.replace(multipleSlashRe, '/')\n  }\n  return id\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/cachedResolver.ts",
    "content": "import type { WorkerGlobalState } from '../../types/worker'\nimport { pathToFileURL } from 'node:url'\nimport { join, normalize } from 'pathe'\nimport { distDir } from '../../paths'\n\nconst bareVitestRegexp = /^@?vitest(?:\\/|$)/\nconst normalizedDistDir = normalize(distDir)\nconst relativeIds: Record<string, string> = {}\nconst externalizeMap = new Map<string, string>()\n\n// all Vitest imports always need to be externalized\nexport function getCachedVitestImport(\n  id: string,\n  state: () => WorkerGlobalState,\n): null | { externalize: string; type: 'module' } {\n  if (id.startsWith('/@fs/') || id.startsWith('\\\\@fs\\\\')) {\n    id = id.slice(process.platform === 'win32' ? 5 : 4)\n  }\n\n  if (externalizeMap.has(id)) {\n    return { externalize: externalizeMap.get(id)!, type: 'module' }\n  }\n  // always externalize Vitest because we import from there before running tests\n  // so we already have it cached by Node.js\n  const root = state().config.root\n  const relativeRoot = relativeIds[root] ?? (relativeIds[root] = normalizedDistDir.slice(root.length))\n  if (id.includes(distDir) || id.includes(normalizedDistDir)) {\n    const externalize = id.startsWith('file://')\n      ? id\n      : pathToFileURL(id).toString()\n    externalizeMap.set(id, externalize)\n    return { externalize, type: 'module' }\n  }\n  if (\n    // \"relative\" to root path:\n    // /node_modules/.pnpm/vitest/dist\n    (relativeRoot && relativeRoot !== '/' && id.startsWith(relativeRoot))\n  ) {\n    const path = join(root, id)\n    const externalize = pathToFileURL(path).toString()\n    externalizeMap.set(id, externalize)\n    return { externalize, type: 'module' }\n  }\n  if (bareVitestRegexp.test(id)) {\n    externalizeMap.set(id, id)\n    return { externalize: id, type: 'module' }\n  }\n  return null\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/errorCatcher.ts",
    "content": "import type { WorkerGlobalState } from '../../types/worker'\nimport { serializeValue } from '@vitest/utils/serialize'\n\n// Store globals in case tests overwrite them\nconst processListeners = process.listeners.bind(process)\nconst processOn = process.on.bind(process)\nconst processOff = process.off.bind(process)\n\nconst dispose: (() => void)[] = []\n\nexport function listenForErrors(state: () => WorkerGlobalState): void {\n  dispose.forEach(fn => fn())\n  dispose.length = 0\n\n  function catchError(err: any, type: string, event: 'uncaughtException' | 'unhandledRejection') {\n    const worker = state()\n\n    const listeners = processListeners(event as 'uncaughtException')\n    // if there is another listener, assume that it's handled by user code\n    // one is Vitest's own listener\n    if (listeners.length > 1) {\n      return\n    }\n\n    const error = serializeValue(err)\n\n    if (typeof error === 'object' && error != null) {\n      error.VITEST_TEST_NAME = worker.current?.type === 'test' ? worker.current.name : undefined\n      if (worker.filepath) {\n        error.VITEST_TEST_PATH = worker.filepath\n      }\n    }\n    state().rpc.onUnhandledError(error, type)\n  }\n\n  const uncaughtException = (e: Error) => catchError(e, 'Uncaught Exception', 'uncaughtException')\n  const unhandledRejection = (e: Error) => catchError(e, 'Unhandled Rejection', 'unhandledRejection')\n\n  processOn('uncaughtException', uncaughtException)\n  processOn('unhandledRejection', unhandledRejection)\n\n  dispose.push(() => {\n    processOff('uncaughtException', uncaughtException)\n    processOff('unhandledRejection', unhandledRejection)\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/evaluatedModules.ts",
    "content": "import { dirname, resolve } from 'pathe'\nimport { EvaluatedModules } from 'vite/module-runner'\n\n// TODO: this is not needed in Vite 7.2+\nexport class VitestEvaluatedModules extends EvaluatedModules {\n  getModuleSourceMapById(id: string): any { /** the return type is not exposed by Vite */\n    const map = super.getModuleSourceMapById(id)\n    if (map != null && !('_patched' in map)) {\n      ;(map as any)._patched = true\n      const dir = dirname(map.url)\n      map.resolvedSources = (map.map.sources || []).map(s => resolve(dir, s || ''))\n    }\n    return map\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/moduleDebug.ts",
    "content": "export type ModuleExecutionInfo = Map<string, ModuleExecutionInfoEntry>\n\nexport interface ModuleExecutionInfoEntry {\n  startOffset: number\n\n  /** The duration that was spent executing the module. */\n  duration: number\n\n  /** The time that was spent executing the module itself and externalized imports. */\n  selfTime: number\n\n  external?: boolean\n  importer?: string\n}\n\n/** Stack to track nested module execution for self-time calculation. */\nexport type ExecutionStack = Array<{\n  /** The file that is being executed. */\n  filename: string\n\n  /** The start time of this module's execution. */\n  startTime: number\n\n  /** Accumulated time spent importing all sub-imports. */\n  subImportTime: number\n}>\n\nexport interface ExecutionInfoOptions {\n  startOffset: number\n  external?: boolean\n  importer?: string\n}\n\nconst performanceNow = performance.now.bind(performance)\n\nexport class ModuleDebug {\n  private executionStack: ExecutionStack = []\n\n  startCalculateModuleExecutionInfo(filename: string, options: ExecutionInfoOptions): () => ModuleExecutionInfoEntry {\n    const startTime = performanceNow()\n\n    this.executionStack.push({\n      filename,\n      startTime,\n      subImportTime: 0,\n    })\n\n    return () => {\n      const duration = performanceNow() - startTime\n\n      const currentExecution = this.executionStack.pop()\n\n      if (currentExecution == null) {\n        throw new Error('Execution stack is empty, this should never happen')\n      }\n\n      const selfTime = duration - currentExecution.subImportTime\n\n      if (this.executionStack.length > 0) {\n        this.executionStack.at(-1)!.subImportTime += duration\n      }\n\n      return {\n        startOffset: options.startOffset,\n        external: options.external,\n        importer: options.importer,\n        duration,\n        selfTime,\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/moduleEvaluator.ts",
    "content": "import type { Span } from '@opentelemetry/api'\nimport type {\n  EvaluatedModuleNode,\n  ModuleEvaluator,\n  ModuleRunnerContext,\n  ModuleRunnerImportMeta,\n} from 'vite/module-runner'\nimport type { VitestEvaluatedModules } from './evaluatedModules'\nimport type { ModuleExecutionInfo } from './moduleDebug'\nimport type { VitestVmOptions } from './moduleRunner'\nimport { createRequire, isBuiltin } from 'node:module'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport vm from 'node:vm'\nimport {\n  ssrDynamicImportKey,\n  ssrExportAllKey,\n  ssrImportKey,\n  ssrImportMetaKey,\n  ssrModuleExportsKey,\n} from 'vite/module-runner'\nimport { Traces } from '../../utils/traces'\nimport { ModuleDebug } from './moduleDebug'\n\nconst isWindows = process.platform === 'win32'\n\nexport interface VitestModuleEvaluatorOptions {\n  evaluatedModules?: VitestEvaluatedModules\n  interopDefault?: boolean | undefined\n  moduleExecutionInfo?: ModuleExecutionInfo\n  getCurrentTestFilepath?: () => string | undefined\n  compiledFunctionArgumentsNames?: string[]\n  compiledFunctionArgumentsValues?: unknown[]\n  /**\n   * @internal\n   */\n  traces?: Traces\n}\n\nexport class VitestModuleEvaluator implements ModuleEvaluator {\n  public stubs: Record<string, any> = {}\n  public env: ModuleRunnerImportMeta['env'] = createImportMetaEnvProxy()\n  private vm: VitestVmOptions | undefined\n\n  private compiledFunctionArgumentsNames?: string[]\n  private compiledFunctionArgumentsValues: unknown[] = []\n\n  private primitives: {\n    Object: typeof Object\n    Proxy: typeof Proxy\n    Reflect: typeof Reflect\n  }\n\n  private debug = new ModuleDebug()\n  private _otel: Traces\n  private _evaluatedModules?: VitestEvaluatedModules\n\n  constructor(\n    vmOptions?: VitestVmOptions | undefined,\n    private options: VitestModuleEvaluatorOptions = {},\n  ) {\n    this._otel = options.traces || new Traces({ enabled: false })\n    this.vm = vmOptions\n    this.stubs = getDefaultRequestStubs(vmOptions?.context)\n    this._evaluatedModules = options.evaluatedModules\n    if (options.compiledFunctionArgumentsNames) {\n      this.compiledFunctionArgumentsNames = options.compiledFunctionArgumentsNames\n    }\n    if (options.compiledFunctionArgumentsValues) {\n      this.compiledFunctionArgumentsValues = options.compiledFunctionArgumentsValues\n    }\n    if (vmOptions) {\n      this.primitives = vm.runInContext(\n        '({ Object, Proxy, Reflect })',\n        vmOptions.context,\n      )\n    }\n    else {\n      this.primitives = {\n        Object,\n        Proxy,\n        Reflect,\n      }\n    }\n  }\n\n  private convertIdToImportUrl(id: string) {\n    // TODO: vitest returns paths for external modules, but Vite returns file://\n    // REMOVE WHEN VITE 6 SUPPORT IS OVER\n    // unfortunetly, there is a bug in Vite where ID is resolved incorrectly, so we can't return files until the fix is merged\n    // https://github.com/vitejs/vite/pull/20449\n    if (!isWindows || isBuiltin(id) || /^(?:node:|data:|http:|https:|file:)/.test(id)) {\n      return id\n    }\n    const [filepath, query] = id.split('?')\n    if (query) {\n      return `${pathToFileURL(filepath).toString()}?${query}`\n    }\n    return pathToFileURL(filepath).toString()\n  }\n\n  async runExternalModule(id: string): Promise<any> {\n    if (id in this.stubs) {\n      return this.stubs[id]\n    }\n\n    const file = this.convertIdToImportUrl(id)\n\n    // this will always be 1 element because it's cached after load\n    const importers = this._evaluatedModules?.getModuleById(id)?.importers\n    const importer = importers?.values().next().value\n    const filename = id.startsWith('file://') ? fileURLToPath(id) : id\n    const finishModuleExecutionInfo = this.debug.startCalculateModuleExecutionInfo(\n      filename,\n      {\n        startOffset: 0,\n        external: true,\n        importer,\n      },\n    )\n    const namespace = await this._otel.$(\n      'vitest.module.external',\n      {\n        attributes: { 'code.file.path': file },\n      },\n      () => this.vm\n        ? this.vm.externalModulesExecutor.import(file)\n        : import(file),\n    ).finally(() => {\n      this.options.moduleExecutionInfo?.set(filename, finishModuleExecutionInfo())\n    })\n\n    if (!this.shouldInterop(file, namespace)) {\n      return namespace\n    }\n\n    const { mod, defaultExport } = interopModule(namespace)\n    const { Proxy, Reflect } = this.primitives\n\n    const proxy = new Proxy(mod, {\n      get(mod, prop) {\n        if (prop === 'default') {\n          return defaultExport\n        }\n        return mod[prop] ?? defaultExport?.[prop]\n      },\n      has(mod, prop) {\n        if (prop === 'default') {\n          return defaultExport !== undefined\n        }\n        return prop in mod || (defaultExport && prop in defaultExport)\n      },\n      getOwnPropertyDescriptor(mod, prop) {\n        const descriptor = Reflect.getOwnPropertyDescriptor(mod, prop)\n        if (descriptor) {\n          return descriptor\n        }\n        if (prop === 'default' && defaultExport !== undefined) {\n          return {\n            value: defaultExport,\n            enumerable: true,\n            configurable: true,\n          }\n        }\n      },\n    })\n    return proxy\n  }\n\n  async runInlinedModule(\n    context: ModuleRunnerContext,\n    code: string,\n    module: Readonly<EvaluatedModuleNode>,\n  ): Promise<any> {\n    return this._otel.$(\n      'vitest.module.inline',\n      span => this._runInlinedModule(context, code, module, span),\n    )\n  }\n\n  private _createCJSGlobals(\n    context: ModuleRunnerContext,\n    module: Readonly<EvaluatedModuleNode>,\n    span: Span,\n  ) {\n    const { Reflect, Proxy, Object } = this.primitives\n\n    const exportsObject = context[ssrModuleExportsKey]\n    const SYMBOL_NOT_DEFINED = Symbol('not defined')\n    let moduleExports: unknown = SYMBOL_NOT_DEFINED\n    // this proxy is triggered only on exports.{name} and module.exports access\n    // inside the module itself. imported module is always \"exports\"\n    const cjsExports = new Proxy(exportsObject, {\n      get: (target, p, receiver) => {\n        if (Reflect.has(target, p)) {\n          return Reflect.get(target, p, receiver)\n        }\n        return Reflect.get(Object.prototype, p, receiver)\n      },\n      getPrototypeOf: () => Object.prototype,\n      set: (_, p, value) => {\n        span.addEvent(`cjs export proxy is triggered for ${String(p)}`)\n        // treat \"module.exports =\" the same as \"exports.default =\" to not have nested \"default.default\",\n        // so \"exports.default\" becomes the actual module\n        if (\n          p === 'default'\n          && this.shouldInterop(module.file, { default: value })\n          && cjsExports !== value\n        ) {\n          span.addEvent('`exports.default` is assigned, copying values')\n          exportAll(cjsExports, value)\n          exportsObject.default = value\n          return true\n        }\n\n        if (!Reflect.has(exportsObject, 'default')) {\n          exportsObject.default = {}\n        }\n\n        // returns undefined, when accessing named exports, if default is not an object\n        // but is still present inside hasOwnKeys, this is Node behaviour for CJS\n        if (\n          moduleExports !== SYMBOL_NOT_DEFINED\n          && isPrimitive(moduleExports)\n        ) {\n          span.addEvent(`\\`exports.${String(p)}\\` is assigned, but module.exports is a primitive. assigning \"undefined\" values instead to comply with ESM`)\n          defineExport(exportsObject, p, () => undefined)\n          return true\n        }\n\n        if (!isPrimitive(exportsObject.default)) {\n          exportsObject.default[p] = value\n        }\n\n        if (p !== 'default') {\n          defineExport(exportsObject, p, () => value)\n        }\n\n        return true\n      },\n    })\n\n    const moduleProxy = {\n      set exports(value) {\n        span.addEvent('`module.exports` is assigned directly, copying all properties to `exports`')\n        exportAll(cjsExports, value)\n        exportsObject.default = value\n        moduleExports = value\n      },\n      get exports() {\n        return cjsExports\n      },\n    }\n\n    const require = this.createRequire(context[ssrImportMetaKey].url)\n\n    return {\n      exports: cjsExports,\n      module: moduleProxy,\n      require,\n      __filename: context[ssrImportMetaKey].filename,\n      __dirname: context[ssrImportMetaKey].dirname,\n    }\n  }\n\n  private async _runInlinedModule(\n    context: ModuleRunnerContext,\n    code: string,\n    module: Readonly<EvaluatedModuleNode>,\n    span: Span,\n  ): Promise<any> {\n    const meta = context[ssrImportMetaKey]\n    meta.env = this.env\n\n    const testFilepath = this.options.getCurrentTestFilepath?.()\n    if (testFilepath === module.file) {\n      const globalNamespace = this.vm?.context || globalThis\n      Object.defineProperty(meta, 'vitest', {\n        // @ts-expect-error injected untyped global\n        get: () => globalNamespace.__vitest_index__,\n      })\n    }\n\n    span.setAttribute('code.file.path', meta.filename)\n\n    const argumentsList = [\n      ssrModuleExportsKey,\n      ssrImportMetaKey,\n      ssrImportKey,\n      ssrDynamicImportKey,\n      ssrExportAllKey,\n      // vite 7 support\n      '__vite_ssr_exportName__',\n    ]\n\n    const cjsGlobals = this._createCJSGlobals(context, module, span)\n    argumentsList.push(\n      // TODO@discuss deprecate in Vitest 5, remove in Vitest 6(?)\n      // backwards compat for vite-node\n      '__filename',\n      '__dirname',\n      'module',\n      'exports',\n      'require',\n    )\n\n    if (this.compiledFunctionArgumentsNames) {\n      argumentsList.push(...this.compiledFunctionArgumentsNames)\n    }\n\n    span.setAttribute('vitest.module.arguments', argumentsList)\n\n    // add 'use strict' since ESM enables it by default\n    const codeDefinition = `'use strict';async (${argumentsList.join(\n      ',',\n    )})=>{{`\n    const wrappedCode = `${codeDefinition}${code}\\n}}`\n    const options = {\n      // use original id for auto spy module (vi.mock(..., { spy: true }))\n      filename: module.id.startsWith('mock:') ? module.id.slice(5) : module.id,\n      lineOffset: 0,\n      columnOffset: -codeDefinition.length,\n    }\n\n    // this will always be 1 element because it's cached after load\n    const importer = module.importers.values().next().value\n    const finishModuleExecutionInfo = this.debug.startCalculateModuleExecutionInfo(options.filename, {\n      startOffset: codeDefinition.length,\n      importer,\n    })\n\n    try {\n      const initModule = this.vm\n        ? vm.runInContext(wrappedCode, this.vm.context, options)\n        : vm.runInThisContext(wrappedCode, options)\n\n      await initModule(\n        context[ssrModuleExportsKey],\n        context[ssrImportMetaKey],\n        context[ssrImportKey],\n        context[ssrDynamicImportKey],\n        context[ssrExportAllKey],\n        // vite 7 support, remove when vite 7+ is supported\n        context.__vite_ssr_exportName__\n        || ((name: string, getter: () => unknown) => Object.defineProperty(context[ssrModuleExportsKey], name, {\n          enumerable: true,\n          configurable: true,\n          get: getter,\n        })),\n\n        cjsGlobals.__filename,\n        cjsGlobals.__dirname,\n        cjsGlobals.module,\n        cjsGlobals.exports,\n        cjsGlobals.require,\n\n        ...this.compiledFunctionArgumentsValues,\n      )\n    }\n    finally {\n      // moduleExecutionInfo needs to use Node filename instead of the normalized one\n      // because we rely on this behaviour in coverage-v8, for example\n      this.options.moduleExecutionInfo?.set(options.filename, finishModuleExecutionInfo())\n    }\n  }\n\n  private createRequire(url: string) {\n    if (url.startsWith('data:')) {\n      const _require = (id: string) => {\n        throw new SyntaxError(`require() is not supported in virtual modules. Trying to call require(\"${id}\") in ${url}`)\n      }\n      _require.resolve = _require\n      return _require\n    }\n    return this.vm\n      ? this.vm.externalModulesExecutor.createRequire(url)\n      : createRequire(url)\n  }\n\n  private shouldInterop(path: string, mod: any): boolean {\n    if (this.options.interopDefault === false) {\n      return false\n    }\n    // never interop ESM modules\n    // TODO: should also skip for `.js` with `type=\"module\"`\n    return !path.endsWith('.mjs') && 'default' in mod\n  }\n}\n\nexport function createImportMetaEnvProxy(): ModuleRunnerImportMeta['env'] {\n  // packages/vitest/src/node/plugins/index.ts:146\n  const booleanKeys = ['DEV', 'PROD', 'SSR']\n  return new Proxy(process.env, {\n    get(_, key) {\n      if (typeof key !== 'string') {\n        return undefined\n      }\n      if (booleanKeys.includes(key)) {\n        return !!process.env[key]\n      }\n      return process.env[key]\n    },\n    set(_, key, value) {\n      if (typeof key !== 'string') {\n        return true\n      }\n\n      if (booleanKeys.includes(key)) {\n        process.env[key] = value ? '1' : ''\n      }\n      else {\n        process.env[key] = value\n      }\n\n      return true\n    },\n  }) as ModuleRunnerImportMeta['env']\n}\n\nfunction updateStyle(id: string, css: string) {\n  if (typeof document === 'undefined') {\n    return\n  }\n\n  const element = document.querySelector(`[data-vite-dev-id=\"${id}\"]`)\n  if (element) {\n    element.textContent = css\n    return\n  }\n\n  const head = document.querySelector('head')\n  const style = document.createElement('style')\n  style.setAttribute('type', 'text/css')\n  style.setAttribute('data-vite-dev-id', id)\n  style.textContent = css\n  head?.appendChild(style)\n}\n\nfunction removeStyle(id: string) {\n  if (typeof document === 'undefined') {\n    return\n  }\n  const sheet = document.querySelector(`[data-vite-dev-id=\"${id}\"]`)\n  if (sheet) {\n    document.head.removeChild(sheet)\n  }\n}\n\nconst defaultClientStub = {\n  injectQuery: (id: string) => id,\n  createHotContext: () => {\n    return {\n      accept: () => {},\n      prune: () => {},\n      dispose: () => {},\n      decline: () => {},\n      invalidate: () => {},\n      on: () => {},\n      send: () => {},\n    }\n  },\n  updateStyle: () => {},\n  removeStyle: () => {},\n}\n\nexport function getDefaultRequestStubs(context?: vm.Context): Record<string, any> {\n  if (!context) {\n    const clientStub = {\n      ...defaultClientStub,\n      updateStyle,\n      removeStyle,\n    }\n    return {\n      '/@vite/client': clientStub,\n    }\n  }\n  const clientStub = vm.runInContext(\n    `(defaultClient) => ({ ...defaultClient, updateStyle: ${updateStyle.toString()}, removeStyle: ${removeStyle.toString()} })`,\n    context,\n  )(defaultClientStub)\n  return {\n    '/@vite/client': clientStub,\n  }\n}\n\nfunction exportAll(exports: any, sourceModule: any) {\n  // #1120 when a module exports itself it causes\n  // call stack error\n  if (exports === sourceModule) {\n    return\n  }\n\n  if (\n    isPrimitive(sourceModule)\n    || Array.isArray(sourceModule)\n    || sourceModule instanceof Promise\n  ) {\n    return\n  }\n\n  for (const key in sourceModule) {\n    if (key !== 'default' && !(key in exports)) {\n      try {\n        defineExport(exports, key, () => sourceModule[key])\n      }\n      catch {}\n    }\n  }\n}\n\n// keep consistency with Vite on how exports are defined\nfunction defineExport(exports: any, key: string | symbol, value: () => any) {\n  Object.defineProperty(exports, key, {\n    enumerable: true,\n    configurable: true,\n    get: value,\n  })\n}\n\nexport function isPrimitive(v: any): boolean {\n  const isObject = typeof v === 'object' || typeof v === 'function'\n  return !isObject || v == null\n}\n\nfunction interopModule(mod: any) {\n  if (isPrimitive(mod)) {\n    return {\n      mod: { default: mod },\n      defaultExport: mod,\n    }\n  }\n\n  let defaultExport = 'default' in mod ? mod.default : mod\n\n  if (!isPrimitive(defaultExport) && '__esModule' in defaultExport) {\n    mod = defaultExport\n    if ('default' in defaultExport) {\n      defaultExport = defaultExport.default\n    }\n  }\n\n  return { mod, defaultExport }\n}\n\nconst VALID_ID_PREFIX = `/@id/`\nconst NULL_BYTE_PLACEHOLDER = `__x00__`\n\nexport function wrapId(id: string): string {\n  return id.startsWith(VALID_ID_PREFIX)\n    ? id\n    : VALID_ID_PREFIX + id.replace('\\0', NULL_BYTE_PLACEHOLDER)\n}\n\nexport function unwrapId(id: string): string {\n  return id.startsWith(VALID_ID_PREFIX)\n    ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, '\\0')\n    : id\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/moduleMocker.ts",
    "content": "import type { ManualMockedModule, MockedModule } from '@vitest/mocker'\nimport type { EvaluatedModuleNode } from 'vite/module-runner'\nimport type { BareModuleMockerOptions } from './bareModuleMocker'\nimport type { VitestModuleRunner } from './moduleRunner'\nimport { resolve } from 'node:path'\nimport vm from 'node:vm'\nimport { AutomockedModule, RedirectedModule } from '@vitest/mocker'\nimport { distDir } from '../../paths'\nimport { BareModuleMocker } from './bareModuleMocker'\nimport { injectQuery } from './utils'\n\nconst spyModulePath = resolve(distDir, 'spy.js')\n\nexport interface VitestMockerOptions extends BareModuleMockerOptions {\n  context?: vm.Context\n}\n\nexport class VitestMocker extends BareModuleMocker {\n  private filterPublicKeys: (symbol | string)[]\n\n  constructor(public moduleRunner: VitestModuleRunner, protected options: VitestMockerOptions) {\n    super(options)\n\n    const context = this.options.context\n    if (context) {\n      this.primitives = vm.runInContext(\n        '({ Object, Error, Function, RegExp, Symbol, Array, Map })',\n        context,\n      )\n    }\n\n    const Symbol = this.primitives.Symbol\n\n    this.filterPublicKeys = [\n      '__esModule',\n      Symbol.asyncIterator,\n      Symbol.hasInstance,\n      Symbol.isConcatSpreadable,\n      Symbol.iterator,\n      Symbol.match,\n      Symbol.matchAll,\n      Symbol.replace,\n      Symbol.search,\n      Symbol.split,\n      Symbol.species,\n      Symbol.toPrimitive,\n      Symbol.toStringTag,\n      Symbol.unscopables,\n    ]\n  }\n\n  private get evaluatedModules() {\n    return this.moduleRunner.evaluatedModules\n  }\n\n  public async initializeSpyModule(): Promise<void> {\n    if (this.spyModule) {\n      return\n    }\n\n    this.spyModule = await this.moduleRunner.import(spyModulePath)\n  }\n\n  public reset(): void {\n    this.registries.clear()\n  }\n\n  protected invalidateModuleById(id: string): void {\n    const mockId = this.getMockPath(id)\n    const node = this.evaluatedModules.getModuleById(mockId)\n    if (node) {\n      this.evaluatedModules.invalidateModule(node)\n      node.mockedExports = undefined\n    }\n  }\n\n  private ensureModule(id: string, url: string) {\n    const node = this.evaluatedModules.ensureModule(id, url)\n    // TODO\n    node.meta = { id, url, code: '', file: null, invalidate: false }\n    return node\n  }\n\n  private async callFunctionMock(id: string, url: string, mock: ManualMockedModule) {\n    const node = this.ensureModule(id, url)\n    if (node.exports) {\n      return node.exports\n    }\n    const exports = await mock.resolve()\n\n    const moduleExports = new Proxy(exports, {\n      get: (target, prop) => {\n        const val = target[prop]\n\n        // 'then' can exist on non-Promise objects, need nested instanceof check for logic to work\n        if (prop === 'then') {\n          if (target instanceof Promise) {\n            return target.then.bind(target)\n          }\n        }\n        else if (!(prop in target)) {\n          if (this.filterPublicKeys.includes(prop)) {\n            return undefined\n          }\n          throw this.createError(\n            `[vitest] No \"${String(prop)}\" export is defined on the \"${mock.raw}\" mock. `\n            + 'Did you forget to return it from \"vi.mock\"?'\n            + '\\nIf you need to partially mock a module, you can use \"importOriginal\" helper inside:\\n',\n            `vi.mock(import(\"${mock.raw}\"), async (importOriginal) => {\n  const actual = await importOriginal()\n  return {\n    ...actual,\n    // your mocked methods\n  }\n})`,\n          )\n        }\n\n        return val\n      },\n    })\n\n    node.exports = moduleExports\n\n    return moduleExports\n  }\n\n  public async importActual<T>(\n    rawId: string,\n    importer: string,\n    callstack?: string[] | null,\n  ): Promise<T> {\n    const { url } = await this.resolveId(rawId, importer)\n    const actualUrl = injectQuery(url, '_vitest_original')\n    const node = await this.moduleRunner.fetchModule(actualUrl, importer)\n    const result = await this.moduleRunner.cachedRequest(\n      node.url,\n      node,\n      callstack || [importer],\n      undefined,\n      true,\n    )\n    return result as T\n  }\n\n  public async importMock(rawId: string, importer: string): Promise<any> {\n    const { id, url, external } = await this.resolveId(rawId, importer)\n\n    let mock = this.getDependencyMock(id)\n\n    if (!mock) {\n      const redirect = this.findMockRedirect(id, external)\n      if (redirect) {\n        mock = new RedirectedModule(rawId, id, rawId, redirect)\n      }\n      else {\n        mock = new AutomockedModule(rawId, id, rawId)\n      }\n    }\n\n    if (mock.type === 'automock' || mock.type === 'autospy') {\n      const node = await this.moduleRunner.fetchModule(url, importer)\n      const mod = await this.moduleRunner.cachedRequest(url, node, [importer], undefined, true)\n      const Object = this.primitives.Object\n      return this.mockObject(mod, Object.create(Object.prototype), mock.type)\n    }\n\n    if (mock.type === 'manual') {\n      return this.callFunctionMock(id, url, mock)\n    }\n    const node = await this.moduleRunner.fetchModule(mock.redirect)\n    return this.moduleRunner.cachedRequest(\n      mock.redirect,\n      node,\n      [importer],\n      undefined,\n      true,\n    )\n  }\n\n  public async requestWithMockedModule(\n    url: string,\n    evaluatedNode: EvaluatedModuleNode,\n    callstack: string[],\n    mock: MockedModule,\n  ): Promise<any> {\n    return this._otel.$('vitest.mocker.evaluate', async (span) => {\n      const mockId = this.getMockPath(evaluatedNode.id)\n\n      span.setAttributes({\n        'vitest.module.id': mockId,\n        'vitest.mock.type': mock.type,\n        'vitest.mock.id': mock.id,\n        'vitest.mock.url': mock.url,\n        'vitest.mock.raw': mock.raw,\n      })\n\n      if (mock.type === 'automock' || mock.type === 'autospy') {\n        const cache = this.evaluatedModules.getModuleById(mockId)\n        if (cache && cache.mockedExports) {\n          return cache.mockedExports\n        }\n        const Object = this.primitives.Object\n        // we have to define a separate object that will copy all properties into itself\n        // and can't just use the same `exports` define automatically by Vite before the evaluator\n        const exports = Object.create(null)\n        Object.defineProperty(exports, Symbol.toStringTag, {\n          value: 'Module',\n          configurable: true,\n          writable: true,\n        })\n        const node = this.ensureModule(mockId, this.getMockPath(evaluatedNode.url))\n        node.meta = evaluatedNode.meta\n        node.file = evaluatedNode.file\n        node.mockedExports = exports\n\n        const mod = await this.moduleRunner.cachedRequest(\n          url,\n          node,\n          callstack,\n          undefined,\n          true,\n        )\n        this.mockObject(mod, exports, mock.type)\n        return exports\n      }\n      if (\n        mock.type === 'manual'\n        && !callstack.includes(mockId)\n        && !callstack.includes(url)\n      ) {\n        try {\n          callstack.push(mockId)\n          // this will not work if user does Promise.all(import(), import())\n          // we can also use AsyncLocalStorage to store callstack, but this won't work in the browser\n          // maybe we should improve mock API in the future?\n          this.mockContext.callstack = callstack\n          return await this.callFunctionMock(mockId, this.getMockPath(url), mock)\n        }\n        finally {\n          this.mockContext.callstack = null\n          const indexMock = callstack.indexOf(mockId)\n          callstack.splice(indexMock, 1)\n        }\n      }\n      else if (mock.type === 'redirect' && !callstack.includes(mock.redirect)) {\n        span.setAttribute('vitest.mock.redirect', mock.redirect)\n        return mock.redirect\n      }\n    })\n  }\n\n  public async mockedRequest(url: string, evaluatedNode: EvaluatedModuleNode, callstack: string[]): Promise<any> {\n    const mock = this.getDependencyMock(evaluatedNode.id)\n\n    if (!mock) {\n      return\n    }\n\n    return this.requestWithMockedModule(url, evaluatedNode, callstack, mock)\n  }\n}\n\ndeclare module 'vite/module-runner' {\n  interface EvaluatedModuleNode {\n    /**\n     * @internal\n     */\n    mockedExports?: Record<string, any>\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/moduleRunner.ts",
    "content": "import type { MockedModule } from '@vitest/mocker'\nimport type vm from 'node:vm'\nimport type { EvaluatedModuleNode, EvaluatedModules, SSRImportMetadata } from 'vite/module-runner'\nimport type { WorkerGlobalState } from '../../types/worker'\nimport type { ExternalModulesExecutor } from '../external-executor'\nimport type { ModuleExecutionInfo } from './moduleDebug'\nimport type { VitestModuleEvaluator } from './moduleEvaluator'\nimport type { VitestTransportOptions } from './moduleTransport'\nimport type { TestModuleRunner } from './testModuleRunner'\nimport * as viteModuleRunner from 'vite/module-runner'\nimport { Traces } from '../../utils/traces'\nimport { VitestMocker } from './moduleMocker'\nimport { VitestTransport } from './moduleTransport'\nimport { injectQuery } from './utils'\n\nexport type CreateImportMeta = (modulePath: string) => viteModuleRunner.ModuleRunnerImportMeta | Promise<viteModuleRunner.ModuleRunnerImportMeta>\nexport const createNodeImportMeta: CreateImportMeta = (modulePath: string) => {\n  if (!viteModuleRunner.createDefaultImportMeta) {\n    throw new Error(`createNodeImportMeta is not supported in this version of Vite.`)\n  }\n\n  const defaultMeta = viteModuleRunner.createDefaultImportMeta(modulePath)\n  const href = defaultMeta.url\n\n  const importMetaResolver = createImportMetaResolver()\n\n  return {\n    ...defaultMeta,\n    main: false,\n    resolve(id: string, parent?: string) {\n      const resolver = importMetaResolver ?? defaultMeta.resolve\n      return resolver(id, parent ?? href)\n    },\n  }\n}\n\nfunction createImportMetaResolver() {\n  if (!import.meta.resolve) {\n    return\n  }\n\n  return (specifier: string, importer: string) =>\n    import.meta.resolve(specifier, importer)\n}\n\n// @ts-expect-error overriding private method\nexport class VitestModuleRunner\n  extends viteModuleRunner.ModuleRunner\n  implements TestModuleRunner {\n  public mocker: VitestMocker\n  public moduleExecutionInfo: ModuleExecutionInfo\n  private _otel: Traces\n  private _callstacks: WeakMap<EvaluatedModuleNode, string[]>\n\n  constructor(private vitestOptions: VitestModuleRunnerOptions) {\n    const options = vitestOptions\n    const evaluatedModules = options.evaluatedModules\n    const callstacks = new WeakMap<EvaluatedModuleNode, string[]>()\n    const transport = new VitestTransport(options.transport, evaluatedModules, callstacks)\n    super(\n      {\n        transport,\n        hmr: false,\n        evaluatedModules,\n        sourcemapInterceptor: 'prepareStackTrace',\n        createImportMeta: vitestOptions.createImportMeta,\n      },\n      options.evaluator,\n    )\n    this._callstacks = callstacks\n    this._otel = vitestOptions.traces || new Traces({ enabled: false })\n    this.moduleExecutionInfo = options.getWorkerState().moduleExecutionInfo\n    this.mocker = options.mocker || new VitestMocker(this, {\n      spyModule: options.spyModule,\n      context: options.vm?.context,\n      traces: this._otel,\n      resolveId: options.transport.resolveId,\n      get root() {\n        return options.getWorkerState().config.root\n      },\n      get moduleDirectories() {\n        return options.getWorkerState().config.deps.moduleDirectories || []\n      },\n      getCurrentTestFilepath() {\n        return options.getWorkerState().filepath\n      },\n    })\n\n    if (options.vm) {\n      options.vm.context.__vitest_mocker__ = this.mocker\n    }\n    else {\n      Object.defineProperty(globalThis, '__vitest_mocker__', {\n        configurable: true,\n        writable: true,\n        value: this.mocker,\n      })\n    }\n  }\n\n  /**\n   * Vite checks that the module has exports emulating the Node.js behaviour,\n   * but Vitest is more relaxed.\n   *\n   * We should keep the Vite behavour when there is a `strict` flag.\n   * @internal\n   */\n  processImport(exports: Record<string, any>): Record<string, any> {\n    return exports\n  }\n\n  public async import(rawId: string): Promise<any> {\n    const resolved = await this._otel.$(\n      'vitest.module.resolve_id',\n      {\n        attributes: {\n          'vitest.module.raw_id': rawId,\n        },\n      },\n      async (span) => {\n        const result = await this.vitestOptions.transport.resolveId(rawId)\n        if (result) {\n          span.setAttributes({\n            'vitest.module.url': result.url,\n            'vitest.module.file': result.file,\n            'vitest.module.id': result.id,\n          })\n        }\n        return result\n      },\n    )\n    return super.import(resolved ? resolved.url : rawId)\n  }\n\n  public async fetchModule(url: string, importer?: string): Promise<EvaluatedModuleNode> {\n    const module = await (this as any).cachedModule(url, importer)\n    return module\n  }\n\n  private _cachedRequest(\n    url: string,\n    module: EvaluatedModuleNode,\n    callstack: string[] = [],\n    metadata?: SSRImportMetadata,\n  ) {\n    // @ts-expect-error \"cachedRequest\" is private\n    return super.cachedRequest(url, module, callstack, metadata)\n  }\n\n  /**\n   * @internal\n   */\n  public async cachedRequest(\n    url: string,\n    mod: EvaluatedModuleNode,\n    callstack: string[] = [],\n    metadata?: SSRImportMetadata,\n    ignoreMock = false,\n  ): Promise<any> {\n    // Track for a better error message if dynamic import is not resolved properly\n    this._callstacks.set(mod, callstack)\n\n    if (ignoreMock) {\n      return this._cachedRequest(url, mod, callstack, metadata)\n    }\n\n    let mocked: any\n    if (mod.meta && 'mockedModule' in mod.meta) {\n      const mockedModule = mod.meta.mockedModule as MockedModule\n      const mockId = this.mocker.getMockPath(mod.id)\n      // bypass mock and force \"importActual\" behavior when:\n      // - mock was removed by doUnmock (stale mockedModule in meta)\n      // - self-import: mock factory/file is importing the module it's mocking\n      const isStale = !this.mocker.getDependencyMock(mod.id)\n      const isSelfImport = callstack.includes(mockId)\n        || callstack.includes(url)\n        || ('redirect' in mockedModule && callstack.includes(mockedModule.redirect))\n      if (isStale || isSelfImport) {\n        const node = await this.fetchModule(injectQuery(url, '_vitest_original'))\n        return this._cachedRequest(node.url, node, callstack, metadata)\n      }\n      mocked = await this.mocker.requestWithMockedModule(\n        url,\n        mod,\n        callstack,\n        mockedModule,\n      )\n    }\n    else {\n      mocked = await this.mocker.mockedRequest(url, mod, callstack)\n    }\n\n    if (typeof mocked === 'string') {\n      const node = await this.fetchModule(mocked)\n      return this._cachedRequest(mocked, node, callstack, metadata)\n    }\n    if (mocked != null && typeof mocked === 'object') {\n      return mocked\n    }\n    return this._cachedRequest(url, mod, callstack, metadata)\n  }\n\n  /** @internal */\n  public _invalidateSubTreeById(ids: string[], invalidated = new Set<string>()): void {\n    for (const id of ids) {\n      if (invalidated.has(id)) {\n        continue\n      }\n      const node = this.evaluatedModules.getModuleById(id)\n      if (!node) {\n        continue\n      }\n      invalidated.add(id)\n      const subIds = Array.from(this.evaluatedModules.idToModuleMap)\n        .filter(([, mod]) => mod.importers.has(id))\n        .map(([key]) => key)\n      if (subIds.length) {\n        this._invalidateSubTreeById(subIds, invalidated)\n      }\n      this.evaluatedModules.invalidateModule(node)\n    }\n  }\n}\n\nexport interface VitestModuleRunnerOptions {\n  transport: VitestTransportOptions\n  evaluator: VitestModuleEvaluator\n  evaluatedModules: EvaluatedModules\n  getWorkerState: () => WorkerGlobalState\n  mocker?: VitestMocker\n  vm?: VitestVmOptions\n  /**\n   * @internal\n   */\n  traces?: Traces\n  spyModule?: typeof import('@vitest/spy')\n  createImportMeta?: CreateImportMeta\n}\n\nexport interface VitestVmOptions {\n  context: vm.Context\n  externalModulesExecutor: ExternalModulesExecutor\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/moduleTransport.ts",
    "content": "import type { EvaluatedModuleNode, EvaluatedModules, FetchFunction, ModuleRunnerTransport } from 'vite/module-runner'\nimport type { ResolveFunctionResult } from '../../types/general'\nimport { EnvironmentTeardownError } from '../utils'\n\nexport interface VitestTransportOptions {\n  fetchModule: FetchFunction\n  resolveId: (id: string, importer?: string) => Promise<ResolveFunctionResult | null>\n}\n\nexport class VitestTransport implements ModuleRunnerTransport {\n  constructor(\n    private options: VitestTransportOptions,\n    private evaluatedModules: EvaluatedModules,\n    private callstacks: WeakMap<EvaluatedModuleNode, string[]>,\n  ) {}\n\n  async invoke(event: any): Promise<{ result: any } | { error: any }> {\n    if (event.type !== 'custom') {\n      return { error: new Error(`Vitest Module Runner doesn't support Vite HMR events.`) }\n    }\n    if (event.event !== 'vite:invoke') {\n      return { error: new Error(`Vitest Module Runner doesn't support ${event.event} event.`) }\n    }\n    const { name, data } = event.data\n    if (name === 'getBuiltins') {\n      // we return an empty array here to avoid client-side builtin check,\n      // as we need builtins to go through `fetchModule`\n      return { result: [] }\n    }\n    if (name !== 'fetchModule') {\n      return { error: new Error(`Unknown method: ${name}. Expected \"fetchModule\".`) }\n    }\n    try {\n      const result = await this.options.fetchModule(...data as Parameters<FetchFunction>)\n      return { result }\n    }\n    catch (cause) {\n      if (cause instanceof EnvironmentTeardownError) {\n        const [id, importer] = data as Parameters<FetchFunction>\n        let message = `Cannot load '${id}'${importer ? ` imported from ${importer}` : ''} after the environment was torn down. `\n          + `This is not a bug in Vitest.`\n\n        const moduleNode = importer ? this.evaluatedModules.getModuleById(importer) : undefined\n        const callstack = moduleNode ? this.callstacks.get(moduleNode) : undefined\n        if (callstack) {\n          message += ` The last recorded callstack:\\n- ${[...callstack, importer, id].reverse().join('\\n- ')}`\n        }\n        const error = new EnvironmentTeardownError(message)\n        if (cause.stack) {\n          error.stack = cause.stack.replace(cause.message, error.message)\n        }\n        return { error }\n      }\n      return { error: cause }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/nativeModuleMocker.ts",
    "content": "import type { DeferPromise } from '@vitest/utils/helpers'\nimport type { SourceMap } from 'magic-string'\nimport module, { isBuiltin } from 'node:module'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport {\n  automockModule,\n  collectModuleExports,\n  createManualModuleSource,\n} from '@vitest/mocker/transforms'\nimport { cleanUrl, createDefer } from '@vitest/utils/helpers'\nimport { parse } from 'acorn'\nimport { isAbsolute } from 'pathe'\nimport { toBuiltin } from '../../utils/modules'\nimport { BareModuleMocker, normalizeModuleId } from './bareModuleMocker'\n\nexport class NativeModuleMocker extends BareModuleMocker {\n  public wrapDynamicImport<T>(moduleFactory: () => Promise<T>): Promise<T> {\n    if (typeof moduleFactory === 'function') {\n      const promise = new Promise<T>((resolve, reject) => {\n        this.resolveMocks().finally(() => {\n          moduleFactory().then(resolve, reject)\n        })\n      })\n      return promise\n    }\n    return moduleFactory\n  }\n\n  public resolveMockedModule(url: string, parentURL: string): module.ResolveFnOutput | undefined {\n    // don't mock modules inside of packages because there is\n    // a high chance that it uses `require` which is not mockable\n    // because we use top-level await in \"manual\" mocks.\n    // for the sake of consistency we don't support mocking anything at all\n    if (parentURL.includes('/node_modules/')) {\n      return\n    }\n\n    const filename = url.startsWith('file://') ? fileURLToPath(url) : url\n    const moduleId = normalizeModuleId(filename)\n\n    const mockedModule = this.getDependencyMock(moduleId)\n    if (!mockedModule) {\n      return\n    }\n    if (mockedModule.type === 'redirect') {\n      return {\n        url: pathToFileURL(mockedModule.redirect).toString(),\n        shortCircuit: true,\n      }\n    }\n    if (mockedModule.type === 'automock' || mockedModule.type === 'autospy') {\n      return {\n        url: injectQuery(url, parentURL, `mock=${mockedModule.type}`),\n        shortCircuit: true,\n      }\n    }\n    if (mockedModule.type === 'manual') {\n      return {\n        url: injectQuery(url, parentURL, 'mock=manual'),\n        shortCircuit: true,\n      }\n    }\n  }\n\n  public loadAutomock(url: string, result: module.LoadFnOutput): module.LoadFnOutput | undefined {\n    const filename = url.startsWith('file://') ? fileURLToPath(url) : url\n    const moduleId = cleanUrl(normalizeModuleId(filename))\n    let source: string | undefined\n    if (isBuiltin(moduleId)) {\n      const builtinModule = getBuiltinModule(moduleId)\n      const exports = Object.keys(builtinModule)\n      source = `\nimport * as builtinModule from '${toBuiltin(moduleId)}?mock=actual'\n\n${exports.map((key, index) => {\n  return `\nconst __${index} = builtinModule[\"${key}\"]\nexport { __${index} as \"${key}\" }\n`\n}).join('')}`\n    }\n    else {\n      source = result.source?.toString()\n    }\n\n    if (source == null) {\n      return\n    }\n\n    const mockType = url.includes('mock=automock') ? 'automock' : 'autospy'\n    const transformedCode = transformCode(source, result.format || 'module', moduleId)\n\n    try {\n      const ms = automockModule(\n        transformedCode,\n        mockType,\n        code => parse(code, {\n          sourceType: 'module',\n          ecmaVersion: 'latest',\n        }),\n        { id: moduleId },\n      )\n      const transformed = ms.toString()\n      const map = ms.generateMap({ hires: 'boundary', source: moduleId })\n      const code = `${transformed}\\n//# sourceMappingURL=${genSourceMapUrl(map)}`\n\n      return {\n        format: 'module',\n        source: code,\n        shortCircuit: true,\n      }\n    }\n    catch (cause) {\n      throw new Error(`Cannot automock '${url}' because it failed to parse.`, { cause })\n    }\n  }\n\n  public loadManualMock(url: string, result: module.LoadFnOutput): module.LoadFnOutput | undefined {\n    const filename = url.startsWith('file://') ? fileURLToPath(url) : url\n    const moduleId = cleanUrl(normalizeModuleId(filename))\n    const mockedModule = this.getDependencyMock(moduleId)\n    // should not be possible\n    if (mockedModule?.type !== 'manual') {\n      console.warn(`Vitest detected unregistered manual mock ${moduleId}. This is a bug in Vitest. Please, open a new issue with reproduction.`)\n      return\n    }\n\n    if (isBuiltin(moduleId)) {\n      const builtinModule = getBuiltinModule(toBuiltin(moduleId))\n      const exports = Object.keys(builtinModule)\n      const manualMockedModule = createManualModuleSource(moduleId, exports)\n\n      return {\n        format: 'module',\n        source: manualMockedModule,\n        shortCircuit: true,\n      }\n    }\n    if (!result.source) {\n      return\n    }\n\n    const source = result.source.toString()\n    const transformedCode = transformCode(source, result.format || 'module', moduleId)\n    if (transformedCode == null) {\n      return\n    }\n\n    const format = result.format?.startsWith('module') ? 'module' : 'commonjs'\n    try {\n      // we parse the module with es/cjs-module-lexer to find the original exports -- we assume the same ones are returned from the factory\n      // injecting new keys is not supported (and should not be advised anyway)\n      const exports = collectModuleExports(moduleId, transformedCode, format)\n      const manualMockedModule = createManualModuleSource(moduleId, exports)\n\n      return {\n        format: 'module',\n        source: manualMockedModule,\n        shortCircuit: true,\n      }\n    }\n    catch (cause) {\n      throw new Error(`Failed to mock '${url}'. See the cause for more information.`, { cause })\n    }\n  }\n\n  private processedModules = new Map<string, number>()\n\n  public checkCircularManualMock(url: string): void {\n    const filename = url.startsWith('file://') ? fileURLToPath(url) : url\n    const id = cleanUrl(normalizeModuleId(filename))\n    this.processedModules.set(id, (this.processedModules.get(id) ?? 0) + 1)\n    // the module is mocked and requested a second time, let's resolve\n    // the factory function that will redefine the exports later\n    if (this.originalModulePromises.has(id)) {\n      const factoryPromise = this.factoryPromises.get(id)\n      this.originalModulePromises.get(id)?.resolve({ __factoryPromise: factoryPromise })\n    }\n  }\n\n  private originalModulePromises = new Map<string, DeferPromise<any>>()\n  private factoryPromises = new Map<string, Promise<any>>()\n\n  // potential performance improvement:\n  // store by URL, not ids, no need to call url.*to* methods and normalizeModuleId\n  public getFactoryModule(id: string): any {\n    const registry = this.getMockerRegistry()\n    const mock = registry.getById(id)\n    if (!mock || mock.type !== 'manual') {\n      throw new Error(`Mock ${id} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`)\n    }\n\n    const mockResult = mock.resolve()\n    if (mockResult instanceof Promise) {\n      // to avoid circular dependency, we resolve this function as {__factoryPromise} in `checkCircularManualMock`\n      // when it's requested the second time. then the exports are exposed as `undefined`,\n      // but later redefined when the promise is actually resolved\n      const promise = createDefer()\n      promise.finally(() => {\n        this.originalModulePromises.delete(id)\n      })\n      mockResult.then(promise.resolve, promise.reject).finally(() => {\n        this.factoryPromises.delete(id)\n      })\n      this.factoryPromises.set(id, mockResult)\n      this.originalModulePromises.set(id, promise)\n      // Node.js on windows processes all the files first, and then runs them\n      // unlike Node.js logic on Mac and Unix where it also runs the code while evaluating\n      // So on Linux/Mac this `if` won't be hit because `checkCircularManualMock` will resolve it\n      // And on Windows, the `checkCircularManualMock` will never have `originalModulePromises`\n      // because `getFactoryModule` is not called until the evaluation phase\n      // But if we track how many times the module was transformed,\n      // we can deduce when to return `__factoryPromise` to support circular modules\n      if ((this.processedModules.get(id) ?? 0) > 1) {\n        this.processedModules.set(id, (this.processedModules.get(id) ?? 1) - 1)\n        promise.resolve({ __factoryPromise: mockResult })\n      }\n      return promise\n    }\n\n    return mockResult\n  }\n\n  public importActual<T>(rawId: string, importer: string): Promise<T> {\n    const resolvedId = import.meta.resolve(rawId, pathToFileURL(importer).toString())\n    const url = new URL(resolvedId)\n    url.searchParams.set('mock', 'actual')\n    return import(url.toString())\n  }\n\n  public importMock<T>(rawId: string, importer: string): Promise<T> {\n    const resolvedId = import.meta.resolve(rawId, pathToFileURL(importer).toString())\n    // file is already mocked\n    if (resolvedId.includes('mock=')) {\n      return import(resolvedId)\n    }\n\n    const filename = fileURLToPath(resolvedId)\n    const external = !isAbsolute(filename) || this.isModuleDirectory(resolvedId)\n      ? normalizeModuleId(rawId)\n      : null\n    // file is not mocked, automock or redirect it\n    const redirect = this.findMockRedirect(filename, external)\n    if (redirect) {\n      return import(pathToFileURL(redirect).toString())\n    }\n\n    const url = new URL(resolvedId)\n    url.searchParams.set('mock', 'automock')\n    return import(url.toString())\n  }\n}\n\nconst replacePercentageRE = /%/g\nfunction injectQuery(url: string, importer: string, queryToInject: string): string {\n  // encode percents for consistent behavior with pathToFileURL\n  // see #2614 for details\n  const resolvedUrl = new URL(\n    url.replace(replacePercentageRE, '%25'),\n    importer,\n  )\n  const { search, hash } = resolvedUrl\n  const pathname = cleanUrl(url)\n  return `${pathname}?${queryToInject}${search ? `&${search.slice(1)}` : ''}${\n    hash ?? ''\n  }`\n}\n\nlet __require: NodeJS.Require | undefined\nfunction getBuiltinModule(moduleId: string) {\n  __require ??= module.createRequire(import.meta.url)\n  return __require(`${moduleId}?mock=actual`)\n}\n\nfunction genSourceMapUrl(map: SourceMap | string): string {\n  if (typeof map !== 'string') {\n    map = JSON.stringify(map)\n  }\n  return `data:application/json;base64,${Buffer.from(map).toString('base64')}`\n}\n\nfunction transformCode(code: string, format: string, filename: string) {\n  if (format.includes('typescript')) {\n    if (!module.stripTypeScriptTypes) {\n      throw new Error(`Cannot parse '${filename}' because \"module.stripTypeScriptTypes\" is not supported. Module mocking requires Node.js 22.15 or higher. This is NOT a bug of Vitest.`)\n    }\n    return module.stripTypeScriptTypes(code)\n  }\n  return code\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/startVitestModuleRunner.ts",
    "content": "import type vm from 'node:vm'\nimport type { EvaluatedModules } from 'vite/module-runner'\nimport type { WorkerGlobalState } from '../../types/worker'\nimport type { Traces } from '../../utils/traces'\nimport type { ExternalModulesExecutor } from '../external-executor'\nimport type { CreateImportMeta } from './moduleRunner'\nimport fs from 'node:fs'\nimport { isBareImport } from '@vitest/utils/helpers'\nimport { isBrowserExternal, isBuiltin, toBuiltin } from '../../utils/modules'\nimport { getSafeWorkerState } from '../utils'\nimport { getCachedVitestImport } from './cachedResolver'\nimport { unwrapId, VitestModuleEvaluator } from './moduleEvaluator'\nimport { VitestMocker } from './moduleMocker'\nimport { VitestModuleRunner } from './moduleRunner'\nimport { removeQuery } from './utils'\n\nconst { readFileSync } = fs\n\nexport const VITEST_VM_CONTEXT_SYMBOL: string = '__vitest_vm_context__'\n\nexport interface ContextModuleRunnerOptions {\n  evaluatedModules: EvaluatedModules\n  mocker?: VitestMocker\n  evaluator?: VitestModuleEvaluator\n  context?: vm.Context\n  externalModulesExecutor?: ExternalModulesExecutor\n  state: WorkerGlobalState\n  /**\n   * @internal\n   */\n  traces?: Traces // optional to keep backwards compat\n  spyModule?: typeof import('@vitest/spy')\n  createImportMeta?: CreateImportMeta\n}\n\nconst cwd = process.cwd()\nconst isWindows = process.platform === 'win32'\n\nexport function startVitestModuleRunner(options: ContextModuleRunnerOptions): VitestModuleRunner {\n  const traces = options.traces\n  const state = (): WorkerGlobalState =>\n    getSafeWorkerState() || options.state\n  const rpc = () => state().rpc\n\n  const environment = () => {\n    const environment = state().environment\n    return environment.viteEnvironment || environment.name\n  }\n\n  const vm = options.context && options.externalModulesExecutor\n    ? {\n        context: options.context,\n        externalModulesExecutor: options.externalModulesExecutor,\n      }\n    : undefined\n\n  const evaluator = options.evaluator || new VitestModuleEvaluator(\n    vm,\n    {\n      traces,\n      evaluatedModules: options.evaluatedModules,\n      get moduleExecutionInfo() {\n        return state().moduleExecutionInfo\n      },\n      get interopDefault() {\n        return state().config.deps.interopDefault\n      },\n      getCurrentTestFilepath: () => state().filepath,\n    },\n  )\n\n  const moduleRunner: VitestModuleRunner = new VitestModuleRunner({\n    spyModule: options.spyModule,\n    evaluatedModules: options.evaluatedModules,\n    evaluator,\n    traces,\n    mocker: options.mocker,\n    transport: {\n      async fetchModule(id, importer, options) {\n        const resolvingModules = state().resolvingModules\n\n        if (isWindows) {\n          if (id[1] === ':') {\n            // The drive letter is different for whatever reason, we need to normalize it to CWD\n            if (id[0] !== cwd[0] && id[0].toUpperCase() === cwd[0].toUpperCase()) {\n              const isUpperCase = cwd[0].toUpperCase() === cwd[0]\n              id = (isUpperCase ? id[0].toUpperCase() : id[0].toLowerCase()) + id.slice(1)\n            }\n            // always mark absolute windows paths, otherwise Vite will externalize it\n            id = `/@id/${id}`\n          }\n        }\n\n        const vitest = getCachedVitestImport(id, state)\n        if (vitest) {\n          return vitest\n        }\n\n        // strip _vitest_original query added by importActual so that\n        // the plugin pipeline sees the original import id (e.g. virtual modules's load hook)\n        const isImportActual = id.includes('_vitest_original')\n        if (isImportActual) {\n          id = removeQuery(id, '_vitest_original')\n        }\n\n        const rawId = unwrapId(id)\n        resolvingModules.add(rawId)\n\n        try {\n          if (VitestMocker.pendingIds.length) {\n            await moduleRunner.mocker.resolveMocks()\n          }\n\n          if (!isImportActual) {\n            const resolvedMock = moduleRunner.mocker.getDependencyMockByUrl(id)\n            if (resolvedMock?.type === 'manual' || resolvedMock?.type === 'redirect') {\n              return {\n                code: '',\n                file: null,\n                id: resolvedMock.id,\n                url: resolvedMock.url,\n                invalidate: false,\n                mockedModule: resolvedMock,\n              }\n            }\n          }\n\n          if (isBuiltin(rawId)) {\n            return { externalize: rawId, type: 'builtin' }\n          }\n\n          if (isBrowserExternal(rawId)) {\n            return { externalize: toBuiltin(rawId), type: 'builtin' }\n          }\n\n          // if module is invalidated, the worker will be recreated,\n          // so cached is always true in a single worker\n          if (!isImportActual && options?.cached) {\n            return { cache: true }\n          }\n\n          const otelCarrier = traces?.getContextCarrier()\n          const result = await rpc().fetch(\n            id,\n            importer,\n            environment(),\n            options,\n            otelCarrier,\n          )\n          if ('cached' in result) {\n            const code = readFileSync(result.tmp, 'utf-8')\n            return { code, ...result }\n          }\n          return result\n        }\n        catch (cause: any) {\n          // rethrow vite error if it cannot load the module because it's not resolved\n          if (\n            (typeof cause === 'object' && cause != null && cause.code === 'ERR_LOAD_URL')\n            || (typeof cause?.message === 'string' && cause.message.includes('Failed to load url'))\n            || (typeof cause?.message === 'string' && cause.message.startsWith('Cannot find module \\''))\n          ) {\n            const error = new Error(\n              `Cannot find ${isBareImport(id) ? 'package' : 'module'} '${id}'${importer ? ` imported from ${importer}` : ''}`,\n              { cause },\n            ) as Error & { code: string }\n            error.code = 'ERR_MODULE_NOT_FOUND'\n            throw error\n          }\n\n          throw cause\n        }\n        finally {\n          resolvingModules.delete(rawId)\n        }\n      },\n      resolveId(id, importer) {\n        return rpc().resolve(\n          id,\n          importer,\n          environment(),\n        )\n      },\n    },\n    getWorkerState: state,\n    vm,\n    createImportMeta: options.createImportMeta,\n  })\n\n  return moduleRunner\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/testModuleRunner.ts",
    "content": "import type { TestModuleMocker } from '@vitest/mocker'\nimport type { ModuleExecutionInfo } from './moduleDebug'\n\nexport interface TestModuleRunner {\n  moduleExecutionInfo?: ModuleExecutionInfo\n  mocker?: TestModuleMocker\n  import: <T = any>(moduleId: string) => Promise<T>\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/types.ts",
    "content": "export interface PublicModuleRunner {\n  import: (id: string) => Promise<any>\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/moduleRunner/utils.ts",
    "content": "// copied from vite/src/shared/utils.ts\nconst postfixRE = /[?#].*$/\n\nfunction cleanUrl(url: string): string {\n  return url.replace(postfixRE, '')\n}\nfunction splitFileAndPostfix(path: string): { file: string; postfix: string } {\n  const file = cleanUrl(path)\n  return { file, postfix: path.slice(file.length) }\n}\n\nexport function injectQuery(url: string, queryToInject: string): string {\n  const { file, postfix } = splitFileAndPostfix(url)\n  return `${file}?${queryToInject}${postfix[0] === '?' ? `&${postfix.slice(1)}` : /* hash only */ postfix}`\n}\n\nexport function removeQuery(url: string, queryToRemove: string): string {\n  return url\n    .replace(new RegExp(`[?&]${queryToRemove}(?=[&#]|$)`), '')\n    .replace(/\\?$/, '')\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/nodejsWorkerLoader.ts",
    "content": "import type { InitializeHook, ResolveHook } from 'node:module'\nimport type { MessagePort } from 'node:worker_threads'\nimport { isBuiltin } from 'node:module'\n\nlet port: MessagePort\n\nexport const initialize: InitializeHook = async ({\n  port: _port,\n  time: _time,\n}: {\n  port: MessagePort\n  time: string\n}) => {\n  port = _port\n}\n\nconst NOW_LENGTH = Date.now().toString().length\nconst REGEXP_VITEST = new RegExp(`%3Fvitest=\\\\d{${NOW_LENGTH}}`)\nconst REGEXP_MOCK_ACTUAL = /\\?mock=actual/\n\nexport const resolve: ResolveHook = (specifier, context, defaultResolve) => {\n  if (specifier.includes('mock=actual')) {\n    // url is already resolved by `importActual`\n    const moduleId = specifier.replace(REGEXP_MOCK_ACTUAL, '')\n    return {\n      url: moduleId,\n      format: isBuiltin(moduleId) ? 'builtin' : undefined,\n      shortCircuit: true,\n    }\n  }\n\n  const isVitest = specifier.includes('%3Fvitest=')\n  const result = defaultResolve(\n    isVitest ? specifier.replace(REGEXP_VITEST, '') : specifier,\n    context,\n  )\n  if (!port || !context?.parentURL) {\n    return result\n  }\n\n  if (typeof result === 'object' && 'then' in result) {\n    return result.then((resolved) => {\n      ensureModuleGraphEntry(resolved.url, context.parentURL!)\n      if (isVitest) {\n        resolved.url = `${resolved.url}?vitest=${Date.now()}`\n      }\n      return resolved\n    })\n  }\n\n  if (isVitest) {\n    result.url = `${result.url}?vitest=${Date.now()}`\n  }\n  ensureModuleGraphEntry(result.url, context.parentURL)\n  return result\n}\n\nfunction ensureModuleGraphEntry(url: string, parentURL: string) {\n  if (url.includes('/node_modules/')) {\n    return\n  }\n  port.postMessage({\n    event: 'register-module-graph-entry',\n    url,\n    parentURL,\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/rpc.ts",
    "content": "import type { CancelReason } from '@vitest/runner'\nimport type { BirpcOptions, BirpcReturn } from 'birpc'\nimport type { RunnerRPC, RuntimeRPC } from '../types/rpc'\nimport type { WorkerRPC } from '../types/worker'\nimport { getSafeTimers } from '@vitest/utils/timers'\nimport { createBirpc } from 'birpc'\nimport { getWorkerState } from './utils'\n\nconst { get } = Reflect\n\nfunction withSafeTimers(fn: () => void) {\n  const { setTimeout, clearTimeout, nextTick, setImmediate, clearImmediate }\n    = getSafeTimers()\n\n  const currentSetTimeout = globalThis.setTimeout\n  const currentClearTimeout = globalThis.clearTimeout\n  const currentSetImmediate = globalThis.setImmediate\n  const currentClearImmediate = globalThis.clearImmediate\n\n  const currentNextTick = globalThis.process?.nextTick\n\n  try {\n    globalThis.setTimeout = setTimeout\n    globalThis.clearTimeout = clearTimeout\n\n    if (setImmediate) {\n      globalThis.setImmediate = setImmediate\n    }\n    if (clearImmediate) {\n      globalThis.clearImmediate = clearImmediate\n    }\n\n    if (globalThis.process && nextTick) {\n      globalThis.process.nextTick = nextTick\n    }\n\n    const result = fn()\n    return result\n  }\n  finally {\n    globalThis.setTimeout = currentSetTimeout\n    globalThis.clearTimeout = currentClearTimeout\n    globalThis.setImmediate = currentSetImmediate\n    globalThis.clearImmediate = currentClearImmediate\n\n    if (globalThis.process && nextTick) {\n      nextTick(() => {\n        globalThis.process.nextTick = currentNextTick\n      })\n    }\n  }\n}\n\nconst promises = new Set<Promise<unknown>>()\n\nexport async function rpcDone(): Promise<unknown[] | undefined> {\n  if (!promises.size) {\n    return\n  }\n  const awaitable = Array.from(promises)\n  return Promise.all(awaitable)\n}\n\nconst onCancelCallbacks: ((reason: CancelReason) => void)[] = []\n\nexport function onCancel(callback: (reason: CancelReason) => void): void {\n  onCancelCallbacks.push(callback)\n}\n\nexport function createRuntimeRpc(\n  options: Pick<\n    BirpcOptions<RuntimeRPC>,\n    'on' | 'post' | 'serialize' | 'deserialize'\n  >,\n): WorkerRPC {\n  return createSafeRpc(\n    createBirpc<RuntimeRPC, RunnerRPC>(\n      {\n        async onCancel(reason) {\n          await Promise.all(onCancelCallbacks.map(fn => fn(reason)))\n        },\n      },\n      {\n        eventNames: [\n          'onCancel',\n        ],\n        timeout: -1,\n        ...options,\n      },\n    ),\n  )\n}\n\nexport function createSafeRpc(rpc: WorkerRPC): WorkerRPC {\n  return new Proxy(rpc, {\n    get(target, p, handler) {\n      // keep $rejectPendingCalls as sync function\n      if (p === '$rejectPendingCalls') {\n        return rpc.$rejectPendingCalls\n      }\n\n      const sendCall = get(target, p, handler)\n      const safeSendCall = (...args: any[]) =>\n        withSafeTimers(async () => {\n          const result = sendCall(...args)\n          promises.add(result)\n          try {\n            return await result\n          }\n          finally {\n            promises.delete(result)\n          }\n        })\n      safeSendCall.asEvent = sendCall.asEvent\n      return safeSendCall\n    },\n  })\n}\n\nexport function rpc(): BirpcReturn<RuntimeRPC, RunnerRPC> {\n  const { rpc } = getWorkerState()\n  return rpc\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/runBaseTests.ts",
    "content": "import type { FileSpecification } from '@vitest/runner'\nimport type { Environment } from '../types/environment'\nimport type { Traces } from '../utils/traces'\nimport type { SerializedConfig } from './config'\nimport type { TestModuleRunner } from './moduleRunner/testModuleRunner'\nimport { performance } from 'node:perf_hooks'\nimport { collectTests, startTests } from '@vitest/runner'\nimport {\n  startCoverageInsideWorker,\n  stopCoverageInsideWorker,\n} from '../integrations/coverage'\nimport { resolveSnapshotEnvironment } from '../integrations/snapshot/environments/resolveSnapshotEnvironment'\nimport { vi } from '../integrations/vi'\nimport { detectAsyncLeaks } from './detect-async-leaks'\nimport { closeInspector } from './inspector'\nimport { resolveTestRunner } from './runners'\nimport { setupGlobalEnv } from './setup-node'\nimport { getWorkerState, resetModules } from './utils'\n\n// browser shouldn't call this!\nexport async function run(\n  method: 'run' | 'collect',\n  files: FileSpecification[],\n  config: SerializedConfig,\n  moduleRunner: TestModuleRunner,\n  environment: Environment,\n  traces: Traces,\n): Promise<void> {\n  const workerState = getWorkerState()\n\n  const [testRunner] = await Promise.all([\n    traces.$('vitest.runtime.runner', () => resolveTestRunner(config, moduleRunner, traces)),\n    traces.$('vitest.runtime.global_env', () => setupGlobalEnv(config, environment)),\n    traces.$('vitest.runtime.coverage.start', () => startCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.isolate })),\n    traces.$('vitest.runtime.snapshot.environment', async () => {\n      if (!workerState.config.snapshotOptions.snapshotEnvironment) {\n        workerState.config.snapshotOptions.snapshotEnvironment\n          = await resolveSnapshotEnvironment(config, moduleRunner)\n      }\n    }),\n  ])\n\n  workerState.onCancel((reason) => {\n    closeInspector(config)\n    testRunner.cancel?.(reason)\n  })\n\n  workerState.durations.prepare = performance.now() - workerState.durations.prepare\n  await traces.$(\n    `vitest.test.runner.${method}`,\n    async () => {\n      for (const file of files) {\n        if (config.isolate) {\n          moduleRunner.mocker?.reset()\n          resetModules(workerState.evaluatedModules, true)\n        }\n\n        workerState.filepath = file.filepath\n\n        if (method === 'run') {\n          const collectAsyncLeaks = config.detectAsyncLeaks ? detectAsyncLeaks(file.filepath, workerState.ctx.projectName) : undefined\n\n          await traces.$(\n            `vitest.test.runner.${method}.module`,\n            { attributes: { 'code.file.path': file.filepath } },\n            () => startTests([file], testRunner),\n          )\n\n          const leaks = await collectAsyncLeaks?.()\n\n          if (leaks?.length) {\n            workerState.rpc.onAsyncLeaks(leaks)\n          }\n        }\n        else {\n          await traces.$(\n            `vitest.test.runner.${method}.module`,\n            { attributes: { 'code.file.path': file.filepath } },\n            () => collectTests([file], testRunner),\n          )\n        }\n\n        // reset after tests, because user might call `vi.setConfig` in setupFile\n        vi.resetConfig()\n        // mocks should not affect different files\n        vi.restoreAllMocks()\n      }\n    },\n  )\n\n  await traces.$('vitest.runtime.coverage.stop', () => stopCoverageInsideWorker(config.coverage, moduleRunner, { isolate: config.isolate }))\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/runVmTests.ts",
    "content": "import type { FileSpecification } from '@vitest/runner'\nimport type { Traces } from '../utils/traces'\nimport type { SerializedConfig } from './config'\nimport type { TestModuleRunner } from './moduleRunner/testModuleRunner'\nimport { createRequire } from 'node:module'\nimport { performance } from 'node:perf_hooks'\nimport timers from 'node:timers'\nimport timersPromises from 'node:timers/promises'\nimport util from 'node:util'\nimport { collectTests, startTests } from '@vitest/runner'\nimport { KNOWN_ASSET_TYPES } from '@vitest/utils/constants'\nimport { setupChaiConfig } from '../integrations/chai/config'\nimport {\n  startCoverageInsideWorker,\n  stopCoverageInsideWorker,\n} from '../integrations/coverage'\nimport { resolveSnapshotEnvironment } from '../integrations/snapshot/environments/resolveSnapshotEnvironment'\nimport * as VitestIndex from '../public/index'\nimport { detectAsyncLeaks } from './detect-async-leaks'\nimport { closeInspector } from './inspector'\nimport { resolveTestRunner } from './runners'\nimport { setupCommonEnv } from './setup-common'\nimport { getWorkerState } from './utils'\n\nexport async function run(\n  method: 'run' | 'collect',\n  files: FileSpecification[],\n  config: SerializedConfig,\n  moduleRunner: TestModuleRunner,\n  traces: Traces,\n): Promise<void> {\n  const workerState = getWorkerState()\n\n  await traces.$('vitest.runtime.global_env', () => setupCommonEnv(config))\n\n  Object.defineProperty(globalThis, '__vitest_index__', {\n    value: VitestIndex,\n    enumerable: false,\n  })\n\n  const viteEnvironment = workerState.environment.viteEnvironment || workerState.environment.name\n  VitestIndex.expect.setState({\n    environment: workerState.environment.name,\n  })\n  if (viteEnvironment === 'client') {\n    const _require = createRequire(import.meta.url)\n    // always mock \"required\" `css` files, because we cannot process them\n    _require.extensions['.css'] = resolveCss\n    _require.extensions['.scss'] = resolveCss\n    _require.extensions['.sass'] = resolveCss\n    _require.extensions['.less'] = resolveCss\n    // since we are using Vite, we can assume how these will be resolved\n    KNOWN_ASSET_TYPES.forEach((type) => {\n      _require.extensions[`.${type}`] = resolveAsset\n    })\n    process.env.SSR = ''\n  }\n  else {\n    process.env.SSR = '1'\n  }\n\n  // @ts-expect-error not typed global for patched timers\n  globalThis.__vitest_required__ = {\n    util,\n    timers,\n    timersPromises,\n  }\n\n  await traces.$('vitest.runtime.coverage.start', () => startCoverageInsideWorker(config.coverage, moduleRunner, { isolate: false }))\n\n  if (config.chaiConfig) {\n    setupChaiConfig(config.chaiConfig)\n  }\n\n  const [testRunner, snapshotEnvironment] = await Promise.all([\n    traces.$('vitest.runtime.runner', () => resolveTestRunner(config, moduleRunner, traces)),\n    traces.$('vitest.runtime.snapshot.environment', () => resolveSnapshotEnvironment(config, moduleRunner)),\n  ])\n\n  config.snapshotOptions.snapshotEnvironment = snapshotEnvironment\n\n  workerState.onCancel((reason) => {\n    closeInspector(config)\n    testRunner.cancel?.(reason)\n  })\n\n  workerState.durations.prepare\n    = performance.now() - workerState.durations.prepare\n\n  const { vi } = VitestIndex\n\n  await traces.$(\n    `vitest.test.runner.${method}`,\n    async () => {\n      for (const file of files) {\n        workerState.filepath = file.filepath\n\n        if (method === 'run') {\n          const collectAsyncLeaks = config.detectAsyncLeaks ? detectAsyncLeaks(file.filepath, workerState.ctx.projectName) : undefined\n\n          await traces.$(\n            `vitest.test.runner.${method}.module`,\n            { attributes: { 'code.file.path': file.filepath } },\n            () => startTests([file], testRunner),\n          )\n\n          const leaks = await collectAsyncLeaks?.()\n\n          if (leaks?.length) {\n            workerState.rpc.onAsyncLeaks(leaks)\n          }\n        }\n        else {\n          await traces.$(\n            `vitest.test.runner.${method}.module`,\n            { attributes: { 'code.file.path': file.filepath } },\n            () => collectTests([file], testRunner),\n          )\n        }\n\n        // reset after tests, because user might call `vi.setConfig` in setupFile\n        vi.resetConfig()\n        // mocks should not affect different files\n        vi.restoreAllMocks()\n      }\n    },\n  )\n\n  await traces.$('vitest.runtime.coverage.stop', () => stopCoverageInsideWorker(config.coverage, moduleRunner, { isolate: false }))\n}\n\nfunction resolveCss(mod: NodeJS.Module) {\n  mod.exports = ''\n}\n\nfunction resolveAsset(mod: NodeJS.Module, url: string) {\n  mod.exports = url\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/runners/benchmark.ts",
    "content": "import type {\n  Suite,\n  Task,\n  TaskUpdateEvent,\n  VitestRunner,\n  VitestRunnerImportSource,\n} from '@vitest/runner'\nimport type { ModuleRunner } from 'vite/module-runner'\nimport type { SerializedConfig } from '../config'\n// import type { VitestExecutor } from '../execute'\nimport type {\n  Benchmark,\n  BenchmarkResult,\n  BenchTask,\n} from '../types/benchmark'\nimport { updateTask as updateRunnerTask } from '@vitest/runner'\nimport { createDefer } from '@vitest/utils/helpers'\nimport { getSafeTimers } from '@vitest/utils/timers'\nimport { getBenchFn, getBenchOptions } from '../benchmark'\nimport { getWorkerState } from '../utils'\n\nfunction createBenchmarkResult(name: string): BenchmarkResult {\n  return {\n    name,\n    rank: 0,\n    rme: 0,\n    samples: [] as number[],\n  } as BenchmarkResult\n}\n\nconst benchmarkTasks = new WeakMap<Benchmark, import('tinybench').Task>()\n\nasync function runBenchmarkSuite(suite: Suite, runner: NodeBenchmarkRunner) {\n  const { Task, Bench } = await runner.importTinybench()\n\n  const start = performance.now()\n\n  const benchmarkGroup: Benchmark[] = []\n  const benchmarkSuiteGroup = []\n  for (const task of suite.tasks) {\n    if (task.mode !== 'run' && task.mode !== 'queued') {\n      continue\n    }\n\n    if (task.meta?.benchmark) {\n      benchmarkGroup.push(task as Benchmark)\n    }\n    else if (task.type === 'suite') {\n      benchmarkSuiteGroup.push(task)\n    }\n  }\n\n  // run sub suites sequentially\n  for (const subSuite of benchmarkSuiteGroup) {\n    await runBenchmarkSuite(subSuite, runner)\n  }\n\n  if (benchmarkGroup.length) {\n    const defer = createDefer()\n    suite.result = {\n      state: 'run',\n      startTime: start,\n      benchmark: createBenchmarkResult(suite.name),\n    }\n    updateTask('suite-prepare', suite)\n\n    const addBenchTaskListener = (\n      task: InstanceType<typeof Task>,\n      benchmark: Benchmark,\n    ) => {\n      task.addEventListener(\n        'complete',\n        (e) => {\n          const task = e.task\n          const taskRes = task.result!\n          const result = benchmark.result!.benchmark!\n          benchmark.result!.state = 'pass'\n          Object.assign(result, taskRes)\n          // compute extra stats and free raw samples as early as possible\n          const samples = result.samples\n          result.sampleCount = samples.length\n          result.median = samples.length % 2\n            ? samples[Math.floor(samples.length / 2)]\n            : (samples[samples.length / 2] + samples[samples.length / 2 - 1]) / 2\n          if (!runner.config.benchmark?.includeSamples) {\n            result.samples.length = 0\n          }\n          updateTask('test-finished', benchmark)\n        },\n        {\n          once: true,\n        },\n      )\n      task.addEventListener(\n        'error',\n        (e) => {\n          const task = e.task\n          defer.reject(benchmark ? task.result!.error : e)\n        },\n        {\n          once: true,\n        },\n      )\n    }\n\n    benchmarkGroup.forEach((benchmark) => {\n      const options = getBenchOptions(benchmark)\n      const benchmarkInstance = new Bench(options)\n\n      const benchmarkFn = getBenchFn(benchmark)\n\n      benchmark.result = {\n        state: 'run',\n        startTime: start,\n        benchmark: createBenchmarkResult(benchmark.name),\n      }\n\n      const task = new Task(benchmarkInstance, benchmark.name, benchmarkFn)\n      benchmarkTasks.set(benchmark, task)\n      addBenchTaskListener(task, benchmark)\n    })\n\n    const { setTimeout } = getSafeTimers()\n    const tasks: [BenchTask, Benchmark][] = []\n\n    for (const benchmark of benchmarkGroup) {\n      const task = benchmarkTasks.get(benchmark)!\n      updateTask('test-prepare', benchmark)\n      await task.warmup()\n      tasks.push([\n        await new Promise<BenchTask>(resolve =>\n          setTimeout(async () => {\n            resolve(await task.run())\n          }),\n        ),\n        benchmark,\n      ])\n    }\n\n    suite.result!.duration = performance.now() - start\n    suite.result!.state = 'pass'\n\n    updateTask('suite-finished', suite)\n    defer.resolve(null)\n\n    await defer\n  }\n\n  function updateTask(event: TaskUpdateEvent, task: Task) {\n    updateRunnerTask(event, task, runner)\n  }\n}\n\nexport class NodeBenchmarkRunner implements VitestRunner {\n  private moduleRunner!: ModuleRunner\n\n  constructor(public config: SerializedConfig) {}\n\n  async importTinybench(): Promise<typeof import('tinybench')> {\n    return await import('tinybench')\n  }\n\n  importFile(filepath: string, source: VitestRunnerImportSource): unknown {\n    if (source === 'setup') {\n      const moduleNode = getWorkerState().evaluatedModules.getModuleById(filepath)\n      if (moduleNode) {\n        getWorkerState().evaluatedModules.invalidateModule(moduleNode)\n      }\n    }\n    return this.moduleRunner.import(filepath)\n  }\n\n  async runSuite(suite: Suite): Promise<void> {\n    await runBenchmarkSuite(suite, this)\n  }\n\n  async runTask(): Promise<void> {\n    throw new Error('`test()` and `it()` is only available in test mode.')\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/runners/index.ts",
    "content": "import type { VitestRunner, VitestRunnerConstructor } from '@vitest/runner'\nimport type { Traces } from '../../utils/traces'\nimport type { SerializedConfig } from '../config'\nimport type { TestModuleRunner } from '../moduleRunner/testModuleRunner'\nimport { takeCoverageInsideWorker } from '../../integrations/coverage'\nimport { rpc } from '../rpc'\nimport { loadDiffConfig, loadSnapshotSerializers } from '../setup-common'\nimport { getWorkerState } from '../utils'\nimport { NodeBenchmarkRunner } from './benchmark'\nimport { TestRunner } from './test'\n\nasync function getTestRunnerConstructor(\n  config: SerializedConfig,\n  moduleRunner: TestModuleRunner,\n): Promise<VitestRunnerConstructor> {\n  if (!config.runner) {\n    return (\n      config.mode === 'test' ? TestRunner : NodeBenchmarkRunner\n    ) as any as VitestRunnerConstructor\n  }\n  const mod = await moduleRunner.import(config.runner)\n  if (!mod.default && typeof mod.default !== 'function') {\n    throw new Error(\n      `Runner must export a default function, but got ${typeof mod.default} imported from ${\n        config.runner\n      }`,\n    )\n  }\n  return mod.default as VitestRunnerConstructor\n}\n\nexport async function resolveTestRunner(\n  config: SerializedConfig,\n  moduleRunner: TestModuleRunner,\n  traces: Traces,\n): Promise<VitestRunner> {\n  const TestRunner = await getTestRunnerConstructor(config, moduleRunner)\n  const testRunner = new TestRunner(config)\n\n  // inject private executor to every runner\n  Object.defineProperty(testRunner, 'moduleRunner', {\n    value: moduleRunner,\n    enumerable: false,\n    configurable: false,\n  })\n\n  if (!testRunner.config) {\n    testRunner.config = config\n  }\n\n  if (!testRunner.importFile) {\n    throw new Error('Runner must implement \"importFile\" method.')\n  }\n\n  if ('__setTraces' in testRunner) {\n    (testRunner.__setTraces as any)(traces)\n  }\n\n  const [diffOptions] = await Promise.all([\n    loadDiffConfig(config, moduleRunner),\n    loadSnapshotSerializers(config, moduleRunner),\n  ])\n  testRunner.config.diffOptions = diffOptions\n\n  // patch some methods, so custom runners don't need to call RPC\n  const originalOnTaskUpdate = testRunner.onTaskUpdate\n  testRunner.onTaskUpdate = async (task, events) => {\n    const p = rpc().onTaskUpdate(task, events)\n    await originalOnTaskUpdate?.call(testRunner, task, events)\n    return p\n  }\n\n  // patch some methods, so custom runners don't need to call RPC\n  const originalOnTestAnnotate = testRunner.onTestAnnotate\n  testRunner.onTestAnnotate = async (test, annotation) => {\n    const p = rpc().onTaskArtifactRecord(test.id, { type: 'internal:annotation', location: annotation.location, annotation })\n    const overriddenResult = await originalOnTestAnnotate?.call(testRunner, test, annotation)\n    const vitestResult = await p\n    return overriddenResult || vitestResult.annotation\n  }\n\n  const originalOnTestArtifactRecord = testRunner.onTestArtifactRecord\n  testRunner.onTestArtifactRecord = async (test, artifact) => {\n    const p = rpc().onTaskArtifactRecord(test.id, artifact)\n    const overriddenResult = await originalOnTestArtifactRecord?.call(testRunner, test, artifact)\n    const vitestResult = await p\n    return overriddenResult as typeof artifact || vitestResult\n  }\n\n  const originalOnCollectStart = testRunner.onCollectStart\n  testRunner.onCollectStart = async (file) => {\n    await rpc().onQueued(file)\n    await originalOnCollectStart?.call(testRunner, file)\n  }\n\n  const originalOnCollected = testRunner.onCollected\n  testRunner.onCollected = async (files) => {\n    const state = getWorkerState()\n    files.forEach((file) => {\n      file.prepareDuration = state.durations.prepare\n      file.environmentLoad = state.durations.environment\n      // should be collected only for a single test file in a batch\n      state.durations.prepare = 0\n      state.durations.environment = 0\n    })\n\n    // Strip function conditions from retry config before sending via RPC\n    // Functions cannot be cloned by structured clone algorithm\n    const sanitizeRetryConditions = (task: any) => {\n      if (task.retry && typeof task.retry === 'object' && typeof task.retry.condition === 'function') {\n        // Remove function condition - it can't be serialized\n        task.retry = { ...task.retry, condition: undefined }\n      }\n      if (task.tasks) {\n        task.tasks.forEach(sanitizeRetryConditions)\n      }\n    }\n    files.forEach(sanitizeRetryConditions)\n\n    rpc().onCollected(files)\n    await originalOnCollected?.call(testRunner, files)\n  }\n\n  const originalOnAfterRun = testRunner.onAfterRunFiles\n  testRunner.onAfterRunFiles = async (files) => {\n    const state = getWorkerState()\n    const coverage = await takeCoverageInsideWorker(config.coverage, moduleRunner)\n\n    if (coverage) {\n      rpc().onAfterSuiteRun({\n        coverage,\n        testFiles: files.map(file => file.name).sort(),\n        environment: state.environment.viteEnvironment || state.environment.name,\n        projectName: state.ctx.projectName,\n      })\n    }\n\n    await originalOnAfterRun?.call(testRunner, files)\n  }\n\n  const originalOnAfterRunTask = testRunner.onAfterRunTask\n  testRunner.onAfterRunTask = async (test) => {\n    if (config.bail && test.result?.state === 'fail') {\n      const previousFailures = await rpc().getCountOfFailedTests()\n      const currentFailures = 1 + previousFailures\n\n      if (currentFailures >= config.bail) {\n        rpc().onCancel('test-failure')\n        testRunner.cancel?.('test-failure')\n      }\n    }\n    await originalOnAfterRunTask?.call(testRunner, test)\n  }\n\n  return testRunner\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/runners/test.ts",
    "content": "import type { SpanOptions } from '@opentelemetry/api'\nimport type { ExpectStatic } from '@vitest/expect'\nimport type {\n  CancelReason,\n  File,\n  ImportDuration,\n  Suite,\n  Task,\n  Test,\n  TestContext,\n  VitestRunnerImportSource,\n  VitestRunner as VitestTestRunner,\n} from '@vitest/runner'\nimport type { ModuleRunner } from 'vite/module-runner'\nimport type { Traces } from '../../utils/traces'\nimport type { SerializedConfig } from '../config'\nimport { getState, GLOBAL_EXPECT, setState } from '@vitest/expect'\nimport {\n  createTaskCollector,\n  getCurrentSuite,\n  getCurrentTest,\n  getFn,\n  getHooks,\n} from '@vitest/runner'\nimport { createChainable, getNames, getTestName, getTests } from '@vitest/runner/utils'\nimport { processError } from '@vitest/utils/error'\nimport { normalize } from 'pathe'\nimport { createExpect } from '../../integrations/chai/index'\nimport { inject } from '../../integrations/inject'\nimport { getSnapshotClient } from '../../integrations/snapshot/chai'\nimport { vi } from '../../integrations/vi'\nimport { getBenchFn, getBenchOptions } from '../benchmark'\nimport { rpc } from '../rpc'\nimport { getWorkerState } from '../utils'\n\nexport class TestRunner implements VitestTestRunner {\n  private snapshotClient = getSnapshotClient()\n  private workerState = getWorkerState()\n  private moduleRunner!: ModuleRunner\n  private cancelRun = false\n\n  private assertionsErrors = new WeakMap<Readonly<Task>, Error>()\n\n  public pool: string = this.workerState.ctx.pool\n  private _otel!: Traces\n  public viteEnvironment: string\n  private viteModuleRunner: boolean\n\n  constructor(public config: SerializedConfig) {\n    const environment = this.workerState.environment\n    this.viteEnvironment = environment.viteEnvironment || environment.name\n    this.viteModuleRunner = config.experimental.viteModuleRunner\n  }\n\n  importFile(filepath: string, source: VitestRunnerImportSource): unknown {\n    if (source === 'setup') {\n      const moduleNode = this.workerState.evaluatedModules.getModuleById(filepath)\n      if (moduleNode) {\n        this.workerState.evaluatedModules.invalidateModule(moduleNode)\n      }\n    }\n    return this._otel.$(\n      `vitest.module.import_${source === 'setup' ? 'setup' : 'spec'}`,\n      {\n        attributes: {\n          'code.file.path': filepath,\n        },\n      },\n      () => {\n        if (!this.viteModuleRunner) {\n          filepath = `${filepath}?vitest=${Date.now()}`\n        }\n        return this.moduleRunner.import(filepath)\n      },\n    )\n  }\n\n  onCollectStart(file: File): void {\n    this.workerState.current = file\n  }\n\n  onCleanupWorkerContext(listener: () => unknown): void {\n    this.workerState.onCleanup(listener)\n  }\n\n  onAfterRunFiles(): void {\n    this.snapshotClient.clear()\n    this.workerState.current = undefined\n  }\n\n  async onAfterRunSuite(suite: Suite): Promise<void> {\n    if (this.config.logHeapUsage && typeof process !== 'undefined') {\n      suite.result!.heap = process.memoryUsage().heapUsed\n    }\n\n    if (suite.mode !== 'skip' && 'filepath' in suite) {\n      // mark snapshots in skipped tests as not obsolete\n      for (const test of getTests(suite)) {\n        if (test.mode === 'skip') {\n          const name = getNames(test).slice(1).join(' > ')\n          this.snapshotClient.skipTest(suite.file.filepath, name)\n        }\n      }\n\n      const result = await this.snapshotClient.finish(suite.file.filepath)\n      if (\n        this.workerState.config.snapshotOptions.updateSnapshot === 'none'\n        && result.unchecked\n      ) {\n        let message = `Obsolete snapshots found when no snapshot update is expected.\\n`\n        for (const key of result.uncheckedKeys) {\n          message += `· ${key}\\n`\n        }\n        suite.result!.errors ??= []\n        suite.result!.errors.push(processError(new Error(message)))\n        suite.result!.state = 'fail'\n      }\n      await rpc().snapshotSaved(result)\n    }\n\n    this.workerState.current = suite.suite || suite.file\n  }\n\n  onAfterRunTask(test: Task): void {\n    if (this.config.logHeapUsage && typeof process !== 'undefined') {\n      test.result!.heap = process.memoryUsage().heapUsed\n    }\n\n    this.workerState.current = test.suite || test.file\n  }\n\n  cancel(_reason: CancelReason): void {\n    this.cancelRun = true\n  }\n\n  injectValue(key: string): any {\n    // inject has a very limiting type controlled by ProvidedContext\n    // some tests override it which causes the build to fail\n    return (inject as any)(key)\n  }\n\n  async onBeforeRunTask(test: Task): Promise<void> {\n    if (this.cancelRun) {\n      test.mode = 'skip'\n    }\n\n    if (test.mode !== 'run' && test.mode !== 'queued') {\n      return\n    }\n\n    this.workerState.current = test\n  }\n\n  async onBeforeRunSuite(suite: Suite): Promise<void> {\n    if (this.cancelRun) {\n      suite.mode = 'skip'\n    }\n\n    // initialize snapshot state before running file suite\n    if (suite.mode !== 'skip' && 'filepath' in suite) {\n      await this.snapshotClient.setup(\n        suite.file.filepath,\n        this.workerState.config.snapshotOptions,\n      )\n    }\n\n    this.workerState.current = suite\n  }\n\n  onBeforeTryTask(test: Task): void {\n    clearModuleMocks(this.config)\n    this.snapshotClient.clearTest(test.file.filepath, test.id)\n    setState(\n      {\n        assertionCalls: 0,\n        isExpectingAssertions: false,\n        isExpectingAssertionsError: null,\n        expectedAssertionsNumber: null,\n        expectedAssertionsNumberErrorGen: null,\n        currentTestName: getTestName(test),\n        snapshotState: this.snapshotClient.getSnapshotState(test.file.filepath),\n      },\n      (globalThis as any)[GLOBAL_EXPECT],\n    )\n  }\n\n  onAfterTryTask(test: Test): void {\n    const {\n      assertionCalls,\n      expectedAssertionsNumber,\n      expectedAssertionsNumberErrorGen,\n      isExpectingAssertions,\n      isExpectingAssertionsError,\n    }\n      = test.context._local\n        ? test.context.expect.getState()\n        : getState((globalThis as any)[GLOBAL_EXPECT])\n    if (\n      expectedAssertionsNumber !== null\n      && assertionCalls !== expectedAssertionsNumber\n    ) {\n      throw expectedAssertionsNumberErrorGen!()\n    }\n    if (isExpectingAssertions === true && assertionCalls === 0) {\n      throw isExpectingAssertionsError\n    }\n    if (this.config.expect.requireAssertions && assertionCalls === 0) {\n      throw this.assertionsErrors.get(test)\n    }\n  }\n\n  extendTaskContext(context: TestContext): TestContext {\n    // create error during the test initialization so we have a nice stack trace\n    if (this.config.expect.requireAssertions) {\n      this.assertionsErrors.set(\n        context.task,\n        new Error('expected any number of assertion, but got none'),\n      )\n    }\n    let _expect: ExpectStatic | undefined\n    Object.defineProperty(context, 'expect', {\n      get() {\n        if (!_expect) {\n          _expect = createExpect(context.task)\n        }\n        return _expect\n      },\n    })\n    Object.defineProperty(context, '_local', {\n      get() {\n        return _expect != null\n      },\n    })\n    return context\n  }\n\n  getImportDurations(): Record<string, ImportDuration> {\n    const { limit } = this.config.experimental.importDurations\n    // skip sorting if limit is 0\n    if (limit === 0) {\n      return {}\n    }\n\n    const entries = [...(this.workerState.moduleExecutionInfo?.entries() || [])]\n\n    // Sort by duration descending and keep top entries\n    const sortedEntries = entries\n      .sort(([, a], [, b]) => b.duration - a.duration)\n      .slice(0, limit)\n\n    const importDurations: Record<string, ImportDuration> = {}\n    for (const [filepath, { duration, selfTime, external, importer }] of sortedEntries) {\n      importDurations[normalize(filepath)] = {\n        selfTime,\n        totalTime: duration,\n        external,\n        importer,\n      }\n    }\n\n    return importDurations\n  }\n\n  trace = <T>(name: string, attributes: Record<string, any> | (() => T), cb?: () => T): T => {\n    const options: SpanOptions = typeof attributes === 'object' ? { attributes } : {}\n    return this._otel.$(`vitest.test.runner.${name}`, options, cb || attributes as () => T)\n  }\n\n  __setTraces(traces: Traces): void {\n    this._otel = traces\n  }\n\n  static createTaskCollector: typeof createTaskCollector = createTaskCollector\n  static getCurrentSuite: typeof getCurrentSuite = getCurrentSuite\n  static getCurrentTest: typeof getCurrentTest = getCurrentTest\n  static createChainable: typeof createChainable = createChainable\n  static getSuiteHooks: typeof getHooks = getHooks\n  static getTestFn: typeof getFn = getFn\n  static setSuiteHooks: typeof getHooks = getHooks\n  static setTestFn: typeof getFn = getFn\n\n  /**\n   * @deprecated\n   */\n  static getBenchFn: typeof getBenchFn = getBenchFn\n  /**\n   * @deprecated\n   */\n  static getBenchOptions: typeof getBenchOptions = getBenchOptions\n}\n\nfunction clearModuleMocks(config: SerializedConfig) {\n  const { clearMocks, mockReset, restoreMocks, unstubEnvs, unstubGlobals }\n    = config\n\n  if (restoreMocks) {\n    vi.restoreAllMocks()\n  }\n  if (mockReset) {\n    vi.resetAllMocks()\n  }\n  if (clearMocks) {\n    vi.clearAllMocks()\n  }\n\n  if (unstubEnvs) {\n    vi.unstubAllEnvs()\n  }\n  if (unstubGlobals) {\n    vi.unstubAllGlobals()\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/setup-common.ts",
    "content": "import type { DiffOptions } from '@vitest/expect'\nimport type { SnapshotSerializer } from '@vitest/snapshot'\nimport type { SerializedDiffOptions } from '@vitest/utils/diff'\nimport type { SerializedConfig } from './config'\nimport type { PublicModuleRunner } from './moduleRunner/types'\nimport { addSerializer } from '@vitest/snapshot'\nimport { setSafeTimers } from '@vitest/utils/timers'\nimport { getWorkerState } from './utils'\n\nlet globalSetup = false\nexport async function setupCommonEnv(config: SerializedConfig): Promise<void> {\n  setupDefines(config)\n  setupEnv(config.env)\n\n  if (globalSetup) {\n    return\n  }\n\n  globalSetup = true\n  setSafeTimers()\n\n  if (config.globals) {\n    (await import('../integrations/globals')).registerApiGlobally()\n  }\n}\n\nfunction setupDefines(config: SerializedConfig) {\n  for (const key in config.defines) {\n    (globalThis as any)[key] = config.defines[key]\n  }\n}\n\nfunction setupEnv(env: Record<string, any>) {\n  const state = getWorkerState()\n  // same boolean-to-string assignment as VitestPlugin.configResolved\n  const { PROD, DEV, ...restEnvs } = env\n  state.metaEnv.PROD = PROD\n  state.metaEnv.DEV = DEV\n  for (const key in restEnvs) {\n    state.metaEnv[key] = env[key]\n  }\n}\n\nexport async function loadDiffConfig(\n  config: SerializedConfig,\n  moduleRunner: PublicModuleRunner,\n): Promise<SerializedDiffOptions | undefined> {\n  if (typeof config.diff === 'object') {\n    return config.diff\n  }\n  if (typeof config.diff !== 'string') {\n    return\n  }\n\n  const diffModule = await moduleRunner.import(config.diff)\n\n  if (\n    diffModule\n    && typeof diffModule.default === 'object'\n    && diffModule.default != null\n  ) {\n    return diffModule.default as DiffOptions\n  }\n  else {\n    throw new Error(\n      `invalid diff config file ${config.diff}. Must have a default export with config object`,\n    )\n  }\n}\n\nexport async function loadSnapshotSerializers(\n  config: SerializedConfig,\n  moduleRunner: PublicModuleRunner,\n): Promise<void> {\n  const files = config.snapshotSerializers\n\n  const snapshotSerializers = await Promise.all(\n    files.map(async (file) => {\n      const mo = await moduleRunner.import(file)\n      if (!mo || typeof mo.default !== 'object' || mo.default === null) {\n        throw new Error(\n          `invalid snapshot serializer file ${file}. Must export a default object`,\n        )\n      }\n\n      const config = mo.default\n      if (\n        typeof config.test !== 'function'\n        || (typeof config.serialize !== 'function'\n          && typeof config.print !== 'function')\n      ) {\n        throw new TypeError(\n          `invalid snapshot serializer in ${file}. Must have a 'test' method along with either a 'serialize' or 'print' method.`,\n        )\n      }\n\n      return config as SnapshotSerializer\n    }),\n  )\n\n  snapshotSerializers.forEach(serializer => addSerializer(serializer))\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/setup-node.ts",
    "content": "import type { Environment } from '../types/environment'\nimport type { SerializedConfig } from './config'\nimport { createRequire } from 'node:module'\nimport timers from 'node:timers'\nimport timersPromises from 'node:timers/promises'\nimport util from 'node:util'\nimport { KNOWN_ASSET_TYPES } from '@vitest/utils/constants'\nimport * as VitestIndex from '../public/index'\nimport { setupCommonEnv } from './setup-common'\n\n// this should only be used in Node\nlet globalSetup = false\nexport async function setupGlobalEnv(\n  config: SerializedConfig,\n  environment: Environment,\n): Promise<void> {\n  await setupCommonEnv(config)\n\n  Object.defineProperty(globalThis, '__vitest_index__', {\n    value: VitestIndex,\n    enumerable: false,\n  })\n\n  VitestIndex.expect.setState({\n    environment: environment.name,\n  })\n\n  if (globalSetup) {\n    return\n  }\n\n  globalSetup = true\n\n  const viteEnvironment = environment.viteEnvironment || environment.name\n  if (viteEnvironment === 'client') {\n    const _require = createRequire(import.meta.url)\n    // always mock \"required\" `css` files, because we cannot process them\n    _require.extensions['.css'] = resolveCss\n    _require.extensions['.scss'] = resolveCss\n    _require.extensions['.sass'] = resolveCss\n    _require.extensions['.less'] = resolveCss\n    // since we are using Vite, we can assume how these will be resolved\n    KNOWN_ASSET_TYPES.forEach((type) => {\n      _require.extensions[`.${type}`] = resolveAsset\n    })\n    process.env.SSR = ''\n  }\n  else {\n    process.env.SSR = '1'\n  }\n\n  // @ts-expect-error not typed global for patched timers\n  globalThis.__vitest_required__ = {\n    util,\n    timers,\n    timersPromises,\n  }\n\n  if (!config.disableConsoleIntercept) {\n    await setupConsoleLogSpy()\n  }\n}\n\nfunction resolveCss(mod: NodeJS.Module) {\n  mod.exports = ''\n}\n\nfunction resolveAsset(mod: NodeJS.Module, url: string) {\n  mod.exports = url\n}\n\nexport async function setupConsoleLogSpy(): Promise<void> {\n  const { createCustomConsole } = await import('./console')\n\n  globalThis.console = createCustomConsole()\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/types/benchmark.ts",
    "content": "import type { Test } from '@vitest/runner'\nimport type { ChainableFunction } from '@vitest/runner/utils'\nimport type {\n  Bench as BenchFactory,\n  Options as BenchOptions,\n  Task as BenchTask,\n  TaskResult as BenchTaskResult,\n  TaskResult as TinybenchResult,\n} from 'tinybench'\n\nexport interface Benchmark extends Test {\n  meta: {\n    benchmark: true\n    result?: BenchTaskResult\n  }\n}\n\nexport interface BenchmarkResult extends TinybenchResult {\n  name: string\n  rank: number\n  sampleCount: number\n  median: number\n}\n\nexport type BenchFunction = (this: BenchFactory) => Promise<void> | void\ntype ChainableBenchmarkAPI = ChainableFunction<\n  'skip' | 'only' | 'todo',\n  (name: string | Function, fn?: BenchFunction, options?: BenchOptions) => void\n>\nexport type BenchmarkAPI = ChainableBenchmarkAPI & {\n  skipIf: (condition: any) => ChainableBenchmarkAPI\n  runIf: (condition: any) => ChainableBenchmarkAPI\n}\n\nexport { BenchFactory, BenchOptions, BenchTask, BenchTaskResult }\n"
  },
  {
    "path": "packages/vitest/src/runtime/types/utils.ts",
    "content": "export type SerializedTestSpecification = [\n  project: { name: string | undefined; root: string },\n  file: string,\n  options: {\n    pool: string\n    testLines?: number[] | undefined\n    testIds?: string[] | undefined\n    testNamePattern?: RegExp | undefined\n    testTagsFilter?: string[] | undefined\n  },\n]\n"
  },
  {
    "path": "packages/vitest/src/runtime/utils.ts",
    "content": "import type { EvaluatedModules } from 'vite/module-runner'\nimport type { WorkerGlobalState } from '../types/worker'\nimport { getSafeTimers } from '@vitest/utils/timers'\n\nconst NAME_WORKER_STATE = '__vitest_worker__'\n\nexport class EnvironmentTeardownError extends Error {\n  name = 'EnvironmentTeardownError'\n}\n\nexport function getWorkerState(): WorkerGlobalState {\n  // @ts-expect-error untyped global\n  const workerState = globalThis[NAME_WORKER_STATE]\n  if (!workerState) {\n    const errorMsg\n      = 'Vitest failed to access its internal state.'\n        + '\\n\\nOne of the following is possible:'\n        + '\\n- \"vitest\" is imported directly without running \"vitest\" command'\n        + '\\n- \"vitest\" is imported inside \"globalSetup\" (to fix this, use \"setupFiles\" instead, because \"globalSetup\" runs in a different context)'\n        + '\\n- \"vitest\" is imported inside Vite / Vitest config file'\n        + '\\n- Otherwise, it might be a Vitest bug. Please report it to https://github.com/vitest-dev/vitest/issues\\n'\n    throw new Error(errorMsg)\n  }\n  return workerState\n}\n\nexport function getSafeWorkerState(): WorkerGlobalState | undefined {\n  // @ts-expect-error untyped global\n  return globalThis[NAME_WORKER_STATE]\n}\n\nexport function provideWorkerState(context: any, state: WorkerGlobalState): WorkerGlobalState {\n  Object.defineProperty(context, NAME_WORKER_STATE, {\n    value: state,\n    configurable: true,\n    writable: true,\n    enumerable: false,\n  })\n\n  return state\n}\n\nexport function getCurrentEnvironment(): string {\n  const state = getWorkerState()\n  return state?.environment.name\n}\n\nexport function isChildProcess(): boolean {\n  return typeof process !== 'undefined' && !!process.send\n}\n\nexport function resetModules(modules: EvaluatedModules, resetMocks = false): void {\n  const skipPaths = [\n    // Vitest\n    /\\/vitest\\/dist\\//,\n    // yarn's .store folder\n    /vitest-virtual-\\w+\\/dist/,\n    // cnpm\n    /@vitest\\/dist/,\n    // don't clear mocks\n    ...(!resetMocks ? [/^mock:/] : []),\n  ]\n  modules.idToModuleMap.forEach((node, path) => {\n    if (skipPaths.some(re => re.test(path))) {\n      return\n    }\n\n    node.promise = undefined\n    node.exports = undefined\n    node.evaluated = false\n    node.importers.clear()\n  })\n}\n\nfunction waitNextTick() {\n  const { setTimeout } = getSafeTimers()\n  return new Promise(resolve => setTimeout(resolve, 0))\n}\n\nexport async function waitForImportsToResolve(): Promise<void> {\n  await waitNextTick()\n  const state = getWorkerState()\n  const promises: Promise<unknown>[] = []\n  const resolvingCount = state.resolvingModules.size\n  for (const [_, mod] of state.evaluatedModules.idToModuleMap) {\n    if (mod.promise && !mod.evaluated) {\n      promises.push(mod.promise)\n    }\n  }\n  if (!promises.length && !resolvingCount) {\n    return\n  }\n  await Promise.allSettled(promises)\n  await waitForImportsToResolve()\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/vm/commonjs-executor.ts",
    "content": "import type { FileMap } from './file-map'\nimport type { ImportModuleDynamically, VMSyntheticModule } from './types'\nimport { Module as _Module, createRequire, isBuiltin } from 'node:module'\nimport vm from 'node:vm'\nimport { basename, dirname, extname } from 'pathe'\nimport { interopCommonJsModule, SyntheticModule } from './utils'\n\ninterface CommonjsExecutorOptions {\n  fileMap: FileMap\n  interopDefault?: boolean\n  context: vm.Context\n  importModuleDynamically: ImportModuleDynamically\n}\n\nconst _require = createRequire(import.meta.url)\n\ninterface PrivateNodeModule extends NodeJS.Module {\n  _compile: (code: string, filename: string) => void\n}\n\nconst requiresCache = new WeakMap<NodeJS.Module, NodeJS.Require>()\n\nexport class CommonjsExecutor {\n  private context: vm.Context\n  private requireCache = new Map<string, NodeJS.Module>()\n  private publicRequireCache = this.createProxyCache()\n\n  private moduleCache = new Map<string, VMSyntheticModule>()\n  private builtinCache: Record<string, NodeJS.Module> = Object.create(null)\n  private extensions: Record<\n    string,\n    (m: NodeJS.Module, filename: string) => unknown\n  > = Object.create(null)\n\n  private fs: FileMap\n  private Module: typeof _Module\n  private interopDefault: boolean | undefined\n\n  constructor(options: CommonjsExecutorOptions) {\n    this.context = options.context\n    this.fs = options.fileMap\n    this.interopDefault = options.interopDefault\n\n    const primitives = vm.runInContext(\n      '({ Object, Array, Error })',\n      this.context,\n    ) as {\n      Object: typeof Object\n      Array: typeof Array\n      Error: typeof Error\n    }\n\n    // eslint-disable-next-line ts/no-this-alias\n    const executor = this\n\n    this.Module = class Module {\n      exports: any\n      isPreloading = false\n      id: string\n      filename: string\n      loaded: boolean\n      parent: null | Module | undefined\n      children: Module[] = []\n      path: string\n      paths: string[] = []\n\n      constructor(id = '', parent?: Module) {\n        this.exports = primitives.Object.create(Object.prototype)\n        // in our case the path should always be resolved already\n        this.path = dirname(id)\n        this.id = id\n        this.filename = id\n        this.loaded = false\n        this.parent = parent\n      }\n\n      get require() {\n        const require = requiresCache.get(this)\n        if (require) {\n          return require\n        }\n\n        const _require = Module.createRequire(this.id)\n        requiresCache.set(this, _require)\n        return _require\n      }\n\n      static getSourceMapsSupport = () => ({\n        enabled: false,\n        nodeModules: false,\n        generatedCode: false,\n      })\n\n      static setSourceMapsSupport = () => {\n        // noop\n      }\n\n      static register = () => {\n        throw new Error(\n          `[vitest] \"register\" is not available when running in Vitest.`,\n        )\n      }\n\n      static registerHooks = () => {\n        throw new Error(\n          `[vitest] \"registerHooks\" is not available when running in Vitest.`,\n        )\n      }\n\n      _compile(code: string, filename: string) {\n        const cjsModule = Module.wrap(code)\n        const script = new vm.Script(cjsModule, {\n          filename,\n          importModuleDynamically: options.importModuleDynamically,\n        } as any)\n        // @ts-expect-error mark script with current identifier\n        script.identifier = filename\n        const fn = script.runInContext(executor.context)\n        const __dirname = dirname(filename)\n        executor.requireCache.set(filename, this)\n        try {\n          fn(this.exports, this.require, this, filename, __dirname)\n          return this.exports\n        }\n        finally {\n          this.loaded = true\n        }\n      }\n\n      // exposed for external use, Node.js does the opposite\n      static _load = (\n        request: string,\n        parent: Module | undefined,\n        _isMain: boolean,\n      ) => {\n        const require = Module.createRequire(parent?.filename ?? request)\n        return require(request)\n      }\n\n      static wrap = (script: string) => {\n        return Module.wrapper[0] + script + Module.wrapper[1]\n      }\n\n      static wrapper = new primitives.Array(\n        '(function (exports, require, module, __filename, __dirname) { ',\n        '\\n});',\n      )\n\n      static builtinModules = _Module.builtinModules\n      static findSourceMap = _Module.findSourceMap\n      static SourceMap = _Module.SourceMap\n      static syncBuiltinESMExports = _Module.syncBuiltinESMExports\n\n      static _cache = executor.publicRequireCache\n      static _extensions = executor.extensions\n\n      static createRequire = (filename: string | URL) => {\n        return executor.createRequire(filename)\n      }\n\n      static runMain = () => {\n        throw new primitives.Error('[vitest] \"runMain\" is not implemented.')\n      }\n\n      // @ts-expect-error not typed\n      static _resolveFilename = _Module._resolveFilename\n      // @ts-expect-error not typed\n      static _findPath = _Module._findPath\n      // @ts-expect-error not typed\n      static _initPaths = _Module._initPaths\n      // @ts-expect-error not typed\n      static _preloadModules = _Module._preloadModules\n      // @ts-expect-error not typed\n      static _resolveLookupPaths = _Module._resolveLookupPaths\n      // @ts-expect-error not typed\n      static globalPaths = _Module.globalPaths\n      static isBuiltin = _Module.isBuiltin\n\n      static constants = _Module.constants\n      static enableCompileCache = _Module.enableCompileCache\n      static getCompileCacheDir = _Module.getCompileCacheDir\n      static flushCompileCache = _Module.flushCompileCache\n      static stripTypeScriptTypes = _Module.stripTypeScriptTypes\n      static findPackageJSON = _Module.findPackageJSON\n\n      static Module = Module\n    }\n\n    this.extensions['.js'] = this.requireJs\n    this.extensions['.json'] = this.requireJson\n  }\n\n  private requireJs = (m: NodeJS.Module, filename: string) => {\n    const content = this.fs.readFile(filename);\n    (m as PrivateNodeModule)._compile(content, filename)\n  }\n\n  private requireJson = (m: NodeJS.Module, filename: string) => {\n    const code = this.fs.readFile(filename)\n    m.exports = JSON.parse(code)\n  }\n\n  private static cjsConditions: Set<string> | undefined\n  private static getCjsConditions(): Set<string> {\n    if (!CommonjsExecutor.cjsConditions) {\n      CommonjsExecutor.cjsConditions = parseCjsConditions(\n        process.execArgv,\n        process.env.NODE_OPTIONS,\n      )\n    }\n    return CommonjsExecutor.cjsConditions\n  }\n\n  public createRequire = (filename: string | URL): NodeJS.Require => {\n    const _require = createRequire(filename)\n    const resolve = (id: string, options?: { paths?: string[] }) => {\n      return _require.resolve(id, {\n        ...options,\n        // Works on Node 22.12+ where _resolveFilename supports conditions.\n        // Silently ignored on older Node versions.\n        conditions: CommonjsExecutor.getCjsConditions(),\n      } as any)\n    }\n    const require = ((id: string) => {\n      const resolved = resolve(id)\n      const ext = extname(resolved)\n      if (ext === '.node' || isBuiltin(resolved)) {\n        return this.requireCoreModule(resolved)\n      }\n      const module = new this.Module(resolved)\n      return this.loadCommonJSModule(module, resolved)\n    }) as NodeJS.Require\n    require.resolve = resolve as NodeJS.RequireResolve\n    require.resolve.paths = _require.resolve.paths\n    Object.defineProperty(require, 'extensions', {\n      get: () => this.extensions,\n      set: () => {},\n      configurable: true,\n    })\n    require.main = undefined // there is no main, since we are running tests using ESM\n    require.cache = this.publicRequireCache\n    return require\n  }\n\n  private createProxyCache() {\n    return new Proxy(Object.create(null), {\n      defineProperty: () => true,\n      deleteProperty: () => true,\n      set: () => true,\n      get: (_, key: string) => this.requireCache.get(key),\n      has: (_, key: string) => this.requireCache.has(key),\n      ownKeys: () => Array.from(this.requireCache.keys()),\n      getOwnPropertyDescriptor() {\n        return {\n          configurable: true,\n          enumerable: true,\n        }\n      },\n    })\n  }\n\n  // very naive implementation for Node.js require\n  private loadCommonJSModule(\n    module: NodeJS.Module,\n    filename: string,\n  ): Record<string, unknown> {\n    const cached = this.requireCache.get(filename)\n    if (cached) {\n      return cached.exports\n    }\n\n    const extension = this.findLongestRegisteredExtension(filename)\n    const loader = this.extensions[extension] || this.extensions['.js']\n    loader(module, filename)\n\n    return module.exports\n  }\n\n  private findLongestRegisteredExtension(filename: string) {\n    const name = basename(filename)\n    let currentExtension: string\n    let index: number\n    let startIndex = 0\n    // eslint-disable-next-line no-cond-assign\n    while ((index = name.indexOf('.', startIndex)) !== -1) {\n      startIndex = index + 1\n      if (index === 0) {\n        continue\n      } // Skip dotfiles like .gitignore\n      currentExtension = name.slice(index)\n      if (this.extensions[currentExtension]) {\n        return currentExtension\n      }\n    }\n    return '.js'\n  }\n\n  public getCoreSyntheticModule(identifier: string): VMSyntheticModule {\n    if (this.moduleCache.has(identifier)) {\n      return this.moduleCache.get(identifier)!\n    }\n    const exports = this.require(identifier)\n    const keys = Object.keys(exports)\n    const module = new SyntheticModule([...keys, 'default'], () => {\n      for (const key of keys) {\n        module.setExport(key, exports[key])\n      }\n      module.setExport('default', exports)\n    }, { context: this.context, identifier })\n    this.moduleCache.set(identifier, module)\n    return module\n  }\n\n  public getCjsSyntheticModule(path: string, identifier: string): VMSyntheticModule {\n    if (this.moduleCache.has(identifier)) {\n      return this.moduleCache.get(identifier)!\n    }\n    const exports = this.require(path)\n    // TODO: technically module should be parsed to find static exports, implement for strict mode in #2854\n    const { keys, moduleExports, defaultExport } = interopCommonJsModule(\n      this.interopDefault,\n      exports,\n    )\n    const module = new SyntheticModule([...keys, 'default'], function () {\n      for (const key of keys) {\n        this.setExport(key, moduleExports[key])\n      }\n      this.setExport('default', defaultExport)\n    }, { context: this.context, identifier })\n    this.moduleCache.set(identifier, module)\n    return module\n  }\n\n  // TODO: use this in strict mode, when available in #2854\n  // private _getNamedCjsExports(path: string): Set<string> {\n  //   const cachedNamedExports = this.cjsNamedExportsMap.get(path)\n\n  //   if (cachedNamedExports) {\n  //     return cachedNamedExports\n  //   }\n\n  //   if (extname(path) === '.node') {\n  //     const moduleExports = this.require(path)\n  //     const namedExports = new Set(Object.keys(moduleExports))\n  //     this.cjsNamedExportsMap.set(path, namedExports)\n  //     return namedExports\n  //   }\n\n  //   const code = this.fs.readFile(path)\n  //   const { exports, reexports } = parseCjs(code, path)\n  //   const namedExports = new Set(exports)\n  //   this.cjsNamedExportsMap.set(path, namedExports)\n\n  //   for (const reexport of reexports) {\n  //     if (isNodeBuiltin(reexport)) {\n  //       const exports = this.require(reexport)\n  //       if (exports !== null && typeof exports === 'object') {\n  //         for (const e of Object.keys(exports)) {\n  //           namedExports.add(e)\n  //         }\n  //       }\n  //     }\n  //     else {\n  //       const require = this.createRequire(path)\n  //       const resolved = require.resolve(reexport)\n\n  //       const exports = this._getNamedCjsExports(resolved)\n\n  //       for (const e of exports) {\n  //         namedExports.add(e)\n  //       }\n  //     }\n  //   }\n\n  //   return namedExports\n  // }\n\n  public require(identifier: string): any {\n    const ext = extname(identifier)\n    if (ext === '.node' || isBuiltin(identifier)) {\n      return this.requireCoreModule(identifier)\n    }\n    const module = new this.Module(identifier)\n    return this.loadCommonJSModule(module, identifier)\n  }\n\n  private requireCoreModule(identifier: string) {\n    const normalized = identifier.replace(/^node:/, '')\n    if (this.builtinCache[normalized]) {\n      return this.builtinCache[normalized].exports\n    }\n    const moduleExports = _require(identifier)\n    if (identifier === 'node:module' || identifier === 'module') {\n      const module = new this.Module('/module.js') // path should not matter\n      module.exports = this.Module\n      this.builtinCache[normalized] = module\n      return module.exports\n    }\n    this.builtinCache[normalized] = _require.cache[normalized]!\n    // TODO: should we wrap module to rethrow context errors?\n    return moduleExports\n  }\n}\n\n// The \"module-sync\" exports condition (added in Node 22.12/20.19 when\n// require(esm) was unflagged) can resolve to ESM files that our CJS\n// vm.Script executor cannot handle. We exclude it by passing explicit\n// CJS conditions to require.resolve (Node 22.12+).\n// Must be a Set because Node's internal resolver calls conditions.has().\n// User-specified --conditions/-C flags are respected, except module-sync.\nexport function parseCjsConditions(\n  execArgv: string[],\n  nodeOptions?: string,\n): Set<string> {\n  const conditions = ['node', 'require', 'node-addons']\n  const args = [\n    ...execArgv,\n    ...(nodeOptions?.split(/\\s+/) ?? []),\n  ]\n  for (let i = 0; i < args.length; i++) {\n    const arg = args[i]\n    const eqMatch = arg.match(/^(?:--conditions|-C)=(.+)$/)\n    if (eqMatch) {\n      conditions.push(eqMatch[1])\n    }\n    else if ((arg === '--conditions' || arg === '-C') && i + 1 < args.length) {\n      conditions.push(args[++i])\n    }\n  }\n  return new Set(conditions.filter(c => c !== 'module-sync'))\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/vm/esm-executor.ts",
    "content": "import type vm from 'node:vm'\nimport type { ExternalModulesExecutor } from '../external-executor'\nimport type { VMModule } from './types'\nimport { dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { SourceTextModule, SyntheticModule } from './utils'\n\ninterface EsmExecutorOptions {\n  context: vm.Context\n}\n\nconst dataURIRegex\n  = /^data:(?<mime>text\\/javascript|application\\/json|application\\/wasm)(?:;(?<encoding>charset=utf-8|base64))?,(?<code>.*)$/\n\nexport class EsmExecutor {\n  private moduleCache = new Map<string, VMModule | Promise<VMModule>>()\n\n  private esmLinkMap = new WeakMap<VMModule, Promise<void>>()\n  private context: vm.Context\n\n  #httpIp = IPnumber('127.0.0.0')\n\n  constructor(\n    private executor: ExternalModulesExecutor,\n    options: EsmExecutorOptions,\n  ) {\n    this.context = options.context\n  }\n\n  public async evaluateModule<T extends VMModule>(m: T): Promise<T> {\n    if (m.status === 'unlinked') {\n      this.esmLinkMap.set(\n        m,\n        m.link((identifier, referencer) =>\n          this.executor.resolveModule(identifier, referencer.identifier),\n        ),\n      )\n    }\n\n    await this.esmLinkMap.get(m)\n\n    if (m.status === 'linked') {\n      await m.evaluate()\n    }\n\n    return m\n  }\n\n  public async createEsModule(\n    fileURL: string,\n    getCode: () => Promise<string> | string,\n  ): Promise<VMModule> {\n    const cached = this.moduleCache.get(fileURL)\n    if (cached) {\n      return cached\n    }\n    const promise = this.loadEsModule(fileURL, getCode)\n    this.moduleCache.set(fileURL, promise)\n    return promise\n  }\n\n  private async loadEsModule(\n    fileURL: string,\n    getCode: () => string | Promise<string>,\n  ) {\n    const code = await getCode()\n    // TODO: should not be allowed in strict mode, implement in #2854\n    if (fileURL.endsWith('.json')) {\n      const m = new SyntheticModule(['default'], function () {\n        const result = JSON.parse(code)\n        this.setExport('default', result)\n      })\n      this.moduleCache.set(fileURL, m)\n      return m\n    }\n    const m = new SourceTextModule(code, {\n      identifier: fileURL,\n      context: this.context,\n      importModuleDynamically: this.executor.importModuleDynamically,\n      initializeImportMeta: (meta, mod) => {\n        meta.url = mod.identifier\n        if (mod.identifier.startsWith('file:')) {\n          const filename = fileURLToPath(mod.identifier)\n          meta.filename = filename\n          meta.dirname = dirname(filename)\n        }\n        meta.resolve = (specifier: string, importer?: string | URL) => {\n          return this.executor.resolve(\n            specifier,\n            importer != null ? importer.toString() : mod.identifier,\n          )\n        }\n      },\n    })\n    this.moduleCache.set(fileURL, m)\n    return m\n  }\n\n  public async createWebAssemblyModule(fileUrl: string, getCode: () => Buffer<ArrayBuffer>): Promise<VMModule> {\n    const cached = this.moduleCache.get(fileUrl)\n    if (cached) {\n      return cached\n    }\n    const m = this.loadWebAssemblyModule(getCode(), fileUrl)\n    this.moduleCache.set(fileUrl, m)\n    return m\n  }\n\n  public async createNetworkModule(fileUrl: string): Promise<VMModule> {\n    // https://nodejs.org/api/esm.html#https-and-http-imports\n    if (fileUrl.startsWith('http:')) {\n      const url = new URL(fileUrl)\n      if (\n        url.hostname !== 'localhost'\n        && url.hostname !== '::1'\n        && (IPnumber(url.hostname) & IPmask(8)) !== this.#httpIp\n      ) {\n        throw new Error(\n          // we don't know the importer, so it's undefined (the same happens in --pool=threads)\n          `import of '${fileUrl}' by undefined is not supported: `\n          + 'http can only be used to load local resources (use https instead).',\n        )\n      }\n    }\n\n    return this.createEsModule(fileUrl, () =>\n      fetch(fileUrl).then(r => r.text()))\n  }\n\n  public async loadWebAssemblyModule(source: Buffer<ArrayBuffer>, identifier: string): Promise<VMModule> {\n    const cached = this.moduleCache.get(identifier)\n    if (cached) {\n      return cached\n    }\n\n    const wasmModule = await WebAssembly.compile(source)\n\n    const exports = WebAssembly.Module.exports(wasmModule)\n    const imports = WebAssembly.Module.imports(wasmModule)\n\n    const moduleLookup: Record<string, VMModule> = {}\n    for (const { module } of imports) {\n      if (moduleLookup[module] === undefined) {\n        moduleLookup[module] = await this.executor.resolveModule(\n          module,\n          identifier,\n        )\n      }\n    }\n\n    const evaluateModule = (module: VMModule) => this.evaluateModule(module)\n\n    const syntheticModule = new SyntheticModule(\n      exports.map(({ name }) => name),\n      async function () {\n        const importsObject: WebAssembly.Imports = {}\n        for (const { module, name } of imports) {\n          if (!importsObject[module]) {\n            importsObject[module] = {}\n          }\n          await evaluateModule(moduleLookup[module])\n          importsObject[module][name] = (moduleLookup[module].namespace as any)[\n            name\n          ]\n        }\n        const wasmInstance = new WebAssembly.Instance(\n          wasmModule,\n          importsObject,\n        )\n        for (const { name } of exports) {\n          this.setExport(name, wasmInstance.exports[name])\n        }\n      },\n      { context: this.context, identifier },\n    )\n\n    return syntheticModule\n  }\n\n  public cacheModule(identifier: string, module: VMModule): void {\n    this.moduleCache.set(identifier, module)\n  }\n\n  public resolveCachedModule(identifier: string): VMModule | Promise<VMModule> | undefined {\n    return this.moduleCache.get(identifier)\n  }\n\n  public async createDataModule(identifier: string): Promise<VMModule> {\n    const cached = this.moduleCache.get(identifier)\n    if (cached) {\n      return cached\n    }\n\n    const match = identifier.match(dataURIRegex)\n\n    if (!match || !match.groups) {\n      throw new Error('Invalid data URI')\n    }\n\n    const mime = match.groups.mime\n    const encoding = match.groups.encoding\n\n    if (mime === 'application/wasm') {\n      if (!encoding) {\n        throw new Error('Missing data URI encoding')\n      }\n\n      if (encoding !== 'base64') {\n        throw new Error(`Invalid data URI encoding: ${encoding}`)\n      }\n\n      const module = this.loadWebAssemblyModule(\n        Buffer.from(match.groups.code, 'base64'),\n        identifier,\n      )\n      this.moduleCache.set(identifier, module)\n      return module\n    }\n\n    let code = match.groups.code\n    if (!encoding || encoding === 'charset=utf-8') {\n      code = decodeURIComponent(code)\n    }\n    else if (encoding === 'base64') {\n      code = Buffer.from(code, 'base64').toString()\n    }\n    else {\n      throw new Error(`Invalid data URI encoding: ${encoding}`)\n    }\n\n    if (mime === 'application/json') {\n      const module = new SyntheticModule(\n        ['default'],\n        function () {\n          const obj = JSON.parse(code)\n          this.setExport('default', obj)\n        },\n        { context: this.context, identifier },\n      )\n      this.moduleCache.set(identifier, module)\n      return module\n    }\n\n    return this.createEsModule(identifier, () => code)\n  }\n}\n\nfunction IPnumber(address: string) {\n  const ip = address.match(/^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$/)\n  if (ip) {\n    return (+ip[1] << 24) + (+ip[2] << 16) + (+ip[3] << 8) + +ip[4]\n  }\n\n  throw new Error(`Expected IP address, received ${address}`)\n}\n\nfunction IPmask(maskSize: number) {\n  return -1 << (32 - maskSize)\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/vm/file-map.ts",
    "content": "import fs from 'node:fs'\n\nconst { promises, readFileSync } = fs\n\nexport class FileMap {\n  private fsCache = new Map<string, string>()\n  private fsBufferCache = new Map<string, Buffer<ArrayBuffer>>()\n\n  public async readFileAsync(path: string): Promise<string> {\n    const cached = this.fsCache.get(path)\n    if (cached != null) {\n      return cached\n    }\n    const source = await promises.readFile(path, 'utf-8')\n    this.fsCache.set(path, source)\n    return source\n  }\n\n  public readFile(path: string): string {\n    const cached = this.fsCache.get(path)\n    if (cached != null) {\n      return cached\n    }\n    const source = readFileSync(path, 'utf-8')\n    this.fsCache.set(path, source)\n    return source\n  }\n\n  public readBuffer(path: string): Buffer<ArrayBuffer> {\n    const cached = this.fsBufferCache.get(path)\n    if (cached != null) {\n      return cached\n    }\n    const buffer = readFileSync(path)\n    this.fsBufferCache.set(path, buffer)\n    return buffer\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/vm/types.ts",
    "content": "import type vm from 'node:vm'\n\n// need to copy paste types for vm\n// because they require latest @types/node which we don't bundle\n\ninterface ModuleEvaluateOptions {\n  timeout?: vm.RunningScriptOptions['timeout'] | undefined\n  breakOnSigint?: vm.RunningScriptOptions['breakOnSigint'] | undefined\n}\n\ntype ModuleLinker = (\n  specifier: string,\n  referencingModule: VMModule,\n  extra: { assert: object },\n) => VMModule | Promise<VMModule>\ntype ModuleStatus\n  = | 'unlinked'\n    | 'linking'\n    | 'linked'\n    | 'evaluating'\n    | 'evaluated'\n    | 'errored'\nexport declare class VMModule {\n  dependencySpecifiers: readonly string[]\n  error: any\n  identifier: string\n  context: vm.Context\n  namespace: object\n  status: ModuleStatus\n  evaluate(options?: ModuleEvaluateOptions): Promise<void>\n  link(linker: ModuleLinker): Promise<void>\n}\ninterface SyntheticModuleOptions {\n  /**\n   * String used in stack traces.\n   * @default 'vm:module(i)' where i is a context-specific ascending index.\n   */\n  identifier?: string | undefined\n  /**\n   * The contextified object as returned by the `vm.createContext()` method, to compile and evaluate this module in.\n   */\n  context?: vm.Context | undefined\n}\nexport declare class VMSyntheticModule extends VMModule {\n  /**\n   * Creates a new `SyntheticModule` instance.\n   * @param exportNames Array of names that will be exported from the module.\n   * @param evaluateCallback Called when the module is evaluated.\n   */\n  constructor(\n    exportNames: string[],\n    evaluateCallback: (this: VMSyntheticModule) => void,\n    options?: SyntheticModuleOptions\n  )\n  /**\n   * This method is used after the module is linked to set the values of exports.\n   * If it is called before the module is linked, an `ERR_VM_MODULE_STATUS` error will be thrown.\n   * @param name\n   * @param value\n   */\n  setExport(name: string, value: any): void\n}\n\nexport declare interface ImportModuleDynamically {\n  (specifier: string, script: VMModule, importAssertions: object):\n    | VMModule\n    | Promise<VMModule>\n}\n\nexport interface SourceTextModuleOptions {\n  identifier?: string | undefined\n  cachedData?: vm.ScriptOptions['cachedData'] | undefined\n  context?: vm.Context | undefined\n  lineOffset?: vm.BaseOptions['lineOffset'] | undefined\n  columnOffset?: vm.BaseOptions['columnOffset'] | undefined\n  /**\n   * Called during evaluation of this module to initialize the `import.meta`.\n   */\n  initializeImportMeta?:\n    | ((meta: ImportMeta, module: VMSourceTextModule) => void)\n    | undefined\n  importModuleDynamically?: ImportModuleDynamically\n}\nexport declare class VMSourceTextModule extends VMModule {\n  /**\n   * Creates a new `SourceTextModule` instance.\n   * @param code JavaScript Module code to parse\n   */\n  constructor(code: string, options?: SourceTextModuleOptions)\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/vm/utils.ts",
    "content": "import type { VMSourceTextModule, VMSyntheticModule } from './types'\nimport vm from 'node:vm'\n\nexport function interopCommonJsModule(\n  interopDefault: boolean | undefined,\n  mod: any,\n): {\n  keys: string[]\n  moduleExports: any\n  defaultExport: any\n} {\n  if (isPrimitive(mod) || Array.isArray(mod) || mod instanceof Promise) {\n    return {\n      keys: [],\n      moduleExports: {},\n      defaultExport: mod,\n    }\n  }\n\n  if (\n    interopDefault !== false\n    && '__esModule' in mod\n    && !isPrimitive(mod.default)\n  ) {\n    const defaultKets = Object.keys(mod.default)\n    const moduleKeys = Object.keys(mod)\n    const allKeys = new Set([...defaultKets, ...moduleKeys])\n    allKeys.delete('default')\n    return {\n      keys: Array.from(allKeys),\n      moduleExports: new Proxy(mod, {\n        get(mod, prop) {\n          return mod[prop] ?? mod.default?.[prop]\n        },\n      }),\n      defaultExport: mod,\n    }\n  }\n\n  return {\n    keys: Object.keys(mod).filter(key => key !== 'default'),\n    moduleExports: mod,\n    defaultExport: mod,\n  }\n}\n\nfunction isPrimitive(obj: unknown): boolean {\n  const isObject = obj != null && (typeof obj === 'object' || typeof obj === 'function')\n  return !isObject\n}\n\nexport const SyntheticModule: typeof VMSyntheticModule = (vm as any)\n  .SyntheticModule\nexport const SourceTextModule: typeof VMSourceTextModule = (vm as any)\n  .SourceTextModule\n"
  },
  {
    "path": "packages/vitest/src/runtime/vm/vite-executor.ts",
    "content": "import type vm from 'node:vm'\nimport type { RuntimeRPC } from '../../types/rpc'\nimport type { WorkerGlobalState } from '../../types/worker'\nimport type { EsmExecutor } from './esm-executor'\nimport type { VMModule } from './types'\nimport { pathToFileURL } from 'node:url'\nimport { CSS_LANGS_RE, KNOWN_ASSET_RE } from '@vitest/utils/constants'\nimport { toArray } from '@vitest/utils/helpers'\nimport { SyntheticModule } from './utils'\n\ninterface ViteExecutorOptions {\n  context: vm.Context\n  transform: RuntimeRPC['transform']\n  esmExecutor: EsmExecutor\n  viteClientModule: Record<string, unknown>\n}\n\nconst CLIENT_ID = '/@vite/client'\nconst CLIENT_FILE = pathToFileURL(CLIENT_ID).href\n\nexport class ViteExecutor {\n  private esm: EsmExecutor\n\n  constructor(private options: ViteExecutorOptions) {\n    this.esm = options.esmExecutor\n  }\n\n  public resolve = (identifier: string): string | undefined => {\n    if (identifier === CLIENT_ID) {\n      return identifier\n    }\n  }\n\n  get workerState(): WorkerGlobalState {\n    return this.options.context.__vitest_worker__\n  }\n\n  public async createViteModule(fileUrl: string): Promise<VMModule> {\n    if (fileUrl === CLIENT_FILE || fileUrl === CLIENT_ID) {\n      return this.createViteClientModule()\n    }\n    const cached = this.esm.resolveCachedModule(fileUrl)\n    if (cached) {\n      return cached\n    }\n    return this.esm.createEsModule(fileUrl, async () => {\n      try {\n        const result = await this.options.transform(fileUrl)\n        if (result.code) {\n          return result.code\n        }\n      }\n      catch (cause: any) {\n        // rethrow vite error if it cannot load the module because it's not resolved\n        if (\n          (typeof cause === 'object' && cause.code === 'ERR_LOAD_URL')\n          || (typeof cause?.message === 'string' && cause.message.includes('Failed to load url'))\n        ) {\n          const error = new Error(\n            `Cannot find module '${fileUrl}'`,\n            { cause },\n          ) as Error & { code: string }\n          error.code = 'ERR_MODULE_NOT_FOUND'\n          throw error\n        }\n      }\n\n      throw new Error(\n        `[vitest] Failed to transform ${fileUrl}. Does the file exist?`,\n      )\n    })\n  }\n\n  private createViteClientModule() {\n    const identifier = CLIENT_ID\n    const cached = this.esm.resolveCachedModule(identifier)\n    if (cached) {\n      return cached\n    }\n    const stub = this.options.viteClientModule\n    const moduleKeys = Object.keys(stub)\n    const module = new SyntheticModule(\n      moduleKeys,\n      function () {\n        moduleKeys.forEach((key) => {\n          this.setExport(key, stub[key])\n        })\n      },\n      { context: this.options.context, identifier },\n    )\n    this.esm.cacheModule(identifier, module)\n    return module\n  }\n\n  public canResolve = (fileUrl: string): boolean => {\n    if (fileUrl === CLIENT_FILE) {\n      return true\n    }\n    const config = this.workerState.config.deps?.web || {}\n    const [modulePath] = fileUrl.split('?')\n    if (config.transformCss && CSS_LANGS_RE.test(modulePath)) {\n      return true\n    }\n    if (config.transformAssets && KNOWN_ASSET_RE.test(modulePath)) {\n      return true\n    }\n    if (\n      toArray(config.transformGlobPattern).some(pattern =>\n        pattern.test(modulePath),\n      )\n    ) {\n      return true\n    }\n    return false\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/worker.ts",
    "content": "import type { ContextRPC, WorkerGlobalState } from '../types/worker'\nimport type { Traces } from '../utils/traces'\nimport type { VitestWorker } from './workers/types'\nimport { createStackString, parseStacktrace } from '@vitest/utils/source-map'\nimport { setupInspect } from './inspector'\nimport * as listeners from './listeners'\nimport { VitestEvaluatedModules } from './moduleRunner/evaluatedModules'\nimport { onCancel, rpcDone } from './rpc'\nimport { EnvironmentTeardownError } from './utils'\n\nconst resolvingModules = new Set<string>()\n\nasync function execute(method: 'run' | 'collect', ctx: ContextRPC, worker: VitestWorker, traces: Traces) {\n  const prepareStart = performance.now()\n\n  const cleanups: (() => void | Promise<void>)[] = [setupInspect(ctx)]\n\n  // RPC is used to communicate between worker (be it a thread worker or child process or a custom implementation) and the main thread\n  const rpc = ctx.rpc\n\n  try {\n    // do not close the RPC channel so that we can get the error messages sent to the main thread\n    cleanups.push(async () => {\n      await Promise.all(rpc.$rejectPendingCalls(({ method, reject }) => {\n        reject(new EnvironmentTeardownError(`[vitest-worker]: Closing rpc while \"${method}\" was pending`))\n      }))\n    })\n\n    const state = {\n      ctx,\n      // here we create a new one, workers can reassign this if they need to keep it non-isolated\n      evaluatedModules: new VitestEvaluatedModules(),\n      resolvingModules,\n      moduleExecutionInfo: new Map(),\n      config: ctx.config,\n      // this is set later by vm or base\n      environment: null!,\n      durations: {\n        environment: 0,\n        prepare: prepareStart,\n      },\n      rpc,\n      onCancel,\n      onCleanup: listeners.onCleanup,\n      providedContext: ctx.providedContext,\n      onFilterStackTrace(stack) {\n        return createStackString(parseStacktrace(stack))\n      },\n      metaEnv: createImportMetaEnvProxy(),\n    } satisfies WorkerGlobalState\n\n    const methodName = method === 'collect' ? 'collectTests' : 'runTests'\n\n    if (!worker[methodName] || typeof worker[methodName] !== 'function') {\n      throw new TypeError(\n        `Test worker should expose \"runTests\" method. Received \"${typeof worker.runTests}\".`,\n      )\n    }\n\n    await worker[methodName](state, traces)\n  }\n  finally {\n    await rpcDone().catch(() => {})\n    await Promise.all(cleanups.map(fn => fn())).catch(() => {})\n  }\n}\n\nexport function run(ctx: ContextRPC, worker: VitestWorker, traces: Traces): Promise<void> {\n  return execute('run', ctx, worker, traces)\n}\n\nexport function collect(ctx: ContextRPC, worker: VitestWorker, traces: Traces): Promise<void> {\n  return execute('collect', ctx, worker, traces)\n}\n\nexport async function teardown(): Promise<void> {\n  await listeners.cleanup()\n}\n\nconst env = process.env\n\nfunction createImportMetaEnvProxy(): WorkerGlobalState['metaEnv'] {\n  // packages/vitest/src/node/plugins/index.ts:146\n  const booleanKeys = ['DEV', 'PROD', 'SSR']\n  return new Proxy(env, {\n    get(_, key) {\n      if (typeof key !== 'string') {\n        return undefined\n      }\n      if (booleanKeys.includes(key)) {\n        return !!process.env[key]\n      }\n      return process.env[key]\n    },\n    set(_, key, value) {\n      if (typeof key !== 'string') {\n        return true\n      }\n\n      if (booleanKeys.includes(key)) {\n        process.env[key] = value ? '1' : ''\n      }\n      else {\n        process.env[key] = value\n      }\n\n      return true\n    },\n  }) as WorkerGlobalState['metaEnv']\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/base.ts",
    "content": "import type { TestModuleMocker } from '@vitest/mocker'\nimport type { Environment } from '../../types/environment'\nimport type { WorkerGlobalState, WorkerSetupContext } from '../../types/worker'\nimport type { ContextModuleRunnerOptions } from '../moduleRunner/startVitestModuleRunner'\nimport type { TestModuleRunner } from '../moduleRunner/testModuleRunner'\nimport { runInThisContext } from 'node:vm'\nimport * as spyModule from '@vitest/spy'\nimport { setupChaiConfig } from '../../integrations/chai/config'\nimport { loadEnvironment } from '../../integrations/env/loader'\nimport { NativeModuleRunner } from '../../utils/nativeModuleRunner'\nimport { Traces } from '../../utils/traces'\nimport { emitModuleRunner } from '../listeners'\nimport { listenForErrors } from '../moduleRunner/errorCatcher'\nimport { VitestEvaluatedModules } from '../moduleRunner/evaluatedModules'\nimport { createNodeImportMeta } from '../moduleRunner/moduleRunner'\nimport { startVitestModuleRunner } from '../moduleRunner/startVitestModuleRunner'\nimport { run } from '../runBaseTests'\nimport { getSafeWorkerState, provideWorkerState } from '../utils'\n\nlet _moduleRunner: TestModuleRunner\n\nconst evaluatedModules = new VitestEvaluatedModules()\nconst moduleExecutionInfo = new Map()\n\nasync function startModuleRunner(options: ContextModuleRunnerOptions): Promise<TestModuleRunner> {\n  if (_moduleRunner) {\n    return _moduleRunner\n  }\n\n  process.exit = (code = process.exitCode || 0): never => {\n    throw new Error(`process.exit unexpectedly called with \"${code}\"`)\n  }\n  const state = () => getSafeWorkerState() || options.state\n\n  listenForErrors(state)\n\n  if (options.state.config.experimental.viteModuleRunner === false) {\n    const root = options.state.config.root\n    let mocker: TestModuleMocker | undefined\n    if (options.state.config.experimental.nodeLoader !== false) {\n      // this additionally imports acorn/magic-string\n      const { NativeModuleMocker } = await import('../moduleRunner/nativeModuleMocker')\n      mocker = new NativeModuleMocker({\n        async resolveId(id, importer) {\n          // TODO: use import.meta.resolve instead\n          return state().rpc.resolve(id, importer, '__vitest__')\n        },\n        root,\n        moduleDirectories: state().config.deps.moduleDirectories || ['/node_modules/'],\n        traces: options.traces || new Traces({ enabled: false }),\n        getCurrentTestFilepath() {\n          return state().filepath\n        },\n        spyModule,\n      })\n    }\n    _moduleRunner = new NativeModuleRunner(\n      root,\n      mocker,\n    )\n    return _moduleRunner\n  }\n\n  _moduleRunner = startVitestModuleRunner(options)\n  return _moduleRunner\n}\n\nlet _currentEnvironment!: Environment\nlet _environmentTime: number\n\n/** @experimental */\nexport async function setupBaseEnvironment(context: WorkerSetupContext): Promise<() => Promise<void>> {\n  if (context.config.experimental.viteModuleRunner === false) {\n    const { setupNodeLoaderHooks } = await import('./native')\n    await setupNodeLoaderHooks(context)\n  }\n\n  const startTime = performance.now()\n  const {\n    environment: { name: environmentName, options: environmentOptions },\n    rpc,\n    config,\n  } = context\n\n  // we could load @vite/env, but it would take ~8ms, while this takes ~0,02ms\n  if (context.config.serializedDefines) {\n    try {\n      runInThisContext(`(() =>{\\n${context.config.serializedDefines}})()`, {\n        lineOffset: 1,\n        filename: 'virtual:load-defines.js',\n      })\n    }\n    catch (error: any) {\n      throw new Error(`Failed to load custom \"defines\": ${error.message}`)\n    }\n  }\n  const otel = context.traces\n\n  const { environment, loader } = await loadEnvironment(\n    environmentName,\n    config.root,\n    rpc,\n    otel,\n    context.config.experimental.viteModuleRunner,\n  )\n  _currentEnvironment = environment\n  const env = await otel.$(\n    'vitest.runtime.environment.setup',\n    {\n      attributes: {\n        'vitest.environment': environment.name,\n        'vitest.environment.vite_environment': environment.viteEnvironment || environment.name,\n      },\n    },\n    () => environment.setup(globalThis, environmentOptions || config.environmentOptions || {}),\n  )\n\n  _environmentTime = performance.now() - startTime\n\n  if (config.chaiConfig) {\n    setupChaiConfig(config.chaiConfig)\n  }\n\n  return async () => {\n    await otel.$(\n      'vitest.runtime.environment.teardown',\n      () => env.teardown(globalThis),\n    )\n    await loader?.close()\n  }\n}\n\n/** @experimental */\nexport async function runBaseTests(method: 'run' | 'collect', state: WorkerGlobalState, traces: Traces): Promise<void> {\n  const { ctx } = state\n  state.environment = _currentEnvironment\n  state.durations.environment = _environmentTime\n  // state has new context, but we want to reuse existing ones\n  state.evaluatedModules = evaluatedModules\n  state.moduleExecutionInfo = moduleExecutionInfo\n\n  provideWorkerState(globalThis, state)\n\n  if (ctx.invalidates) {\n    ctx.invalidates.forEach((filepath) => {\n      const modules = state.evaluatedModules.fileToModulesMap.get(filepath) || []\n      modules.forEach((module) => {\n        state.evaluatedModules.invalidateModule(module)\n      })\n    })\n  }\n  ctx.files.forEach((i) => {\n    const filepath = i.filepath\n    const modules = state.evaluatedModules.fileToModulesMap.get(filepath) || []\n    modules.forEach((module) => {\n      state.evaluatedModules.invalidateModule(module)\n    })\n  })\n\n  const moduleRunner = await startModuleRunner({\n    state,\n    evaluatedModules: state.evaluatedModules,\n    spyModule,\n    createImportMeta: createNodeImportMeta,\n    traces,\n  })\n\n  emitModuleRunner(moduleRunner as any)\n\n  await run(\n    method,\n    ctx.files,\n    ctx.config,\n    moduleRunner,\n    _currentEnvironment,\n    traces,\n  )\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/forks.ts",
    "content": "import { runBaseTests, setupBaseEnvironment } from './base'\nimport workerInit from './init-forks'\n\nworkerInit({ runTests: runBaseTests, setup: setupBaseEnvironment })\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/init-forks.ts",
    "content": "import type { WorkerGlobalState, WorkerSetupContext } from '../../types/worker'\nimport type { Traces } from '../../utils/traces'\nimport { init } from './init'\n\nif (!process.send) {\n  throw new Error('Expected worker to be run in node:child_process')\n}\n\n// Store globals in case tests overwrite them\nconst processExit = process.exit.bind(process)\nconst processSend = process.send.bind(process)\nconst processOn = process.on.bind(process)\nconst processOff = process.off.bind(process)\nconst processRemoveAllListeners = process.removeAllListeners.bind(process)\n\nconst isProfiling = process.execArgv.some(\n  execArg =>\n    execArg.startsWith('--prof')\n    || execArg.startsWith('--cpu-prof')\n    || execArg.startsWith('--heap-prof')\n    || execArg.startsWith('--diagnostic-dir'),\n)\n\n// Work-around for nodejs/node#55094\nif (isProfiling) {\n  processOn('SIGTERM', () => processExit())\n}\n\nprocessOn('error', onError)\n\nexport default function workerInit(options: {\n  runTests: (method: 'run' | 'collect', state: WorkerGlobalState, traces: Traces) => Promise<void>\n  setup?: (context: WorkerSetupContext) => void | Promise<() => Promise<unknown>>\n}): void {\n  const { runTests } = options\n\n  init({\n    post: v => processSend(v),\n    on: cb => processOn('message', cb),\n    off: cb => processOff('message', cb),\n    teardown: () => {\n      processRemoveAllListeners('message')\n      processOff('error', onError)\n    },\n    runTests: (state, traces) => executeTests('run', state, traces),\n    collectTests: (state, traces) => executeTests('collect', state, traces),\n    setup: options.setup,\n  })\n\n  async function executeTests(method: 'run' | 'collect', state: WorkerGlobalState, traces: Traces) {\n    try {\n      await runTests(method, state, traces)\n    }\n    finally {\n      process.exit = processExit\n    }\n  }\n}\n\n// Prevent leaving worker in loops where it tries to send message to closed main\n// thread, errors, and tries to send the error.\nfunction onError(error: any) {\n  if (error?.code === 'ERR_IPC_CHANNEL_CLOSED' || error?.code === 'EPIPE') {\n    processExit(1)\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/init-threads.ts",
    "content": "import type { WorkerGlobalState, WorkerSetupContext } from '../../types/worker'\nimport type { Traces } from '../../utils/traces'\nimport { isMainThread, parentPort } from 'node:worker_threads'\nimport { init } from './init'\n\nif (isMainThread || !parentPort) {\n  throw new Error('Expected worker to be run in node:worker_threads')\n}\n\nexport default function workerInit(options: {\n  runTests: (method: 'run' | 'collect', state: WorkerGlobalState, traces: Traces) => Promise<void>\n  setup?: (context: WorkerSetupContext) => void | Promise<() => Promise<unknown>>\n}): void {\n  const { runTests } = options\n\n  init({\n    post: response => parentPort!.postMessage(response),\n    on: callback => parentPort!.on('message', callback),\n    off: callback => parentPort!.off('message', callback),\n    teardown: () => parentPort!.removeAllListeners('message'),\n    runTests: async (state, traces) => runTests('run', state, traces),\n    collectTests: async (state, traces) => runTests('collect', state, traces),\n    setup: options.setup,\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/init.ts",
    "content": "import type { FileSpecification } from '@vitest/runner'\nimport type { WorkerRequest, WorkerResponse } from '../../node/pools/types'\nimport type { WorkerSetupContext } from '../../types/worker'\nimport type { VitestWorker } from './types'\nimport { serializeError } from '@vitest/utils/error'\nimport { Traces } from '../../utils/traces'\nimport * as listeners from '../listeners'\nimport { createRuntimeRpc } from '../rpc'\nimport * as entrypoint from '../worker'\n\ninterface Options extends VitestWorker {\n  teardown?: () => void\n}\n\nconst __vitest_worker_response__ = true\nconst memoryUsage = process.memoryUsage.bind(process)\nlet reportMemory = false\n\nlet traces!: Traces\n\n/** @experimental */\nexport function init(worker: Options): void {\n  worker.on(onMessage)\n  if (worker.onModuleRunner) {\n    listeners.onModuleRunner(worker.onModuleRunner)\n  }\n\n  let runPromise: Promise<unknown> | undefined\n  let isRunning = false\n  let workerTeardown: (() => Promise<unknown>) | undefined | void\n  let setupContext!: WorkerSetupContext\n\n  function send(response: WorkerResponse) {\n    worker.post(worker.serialize ? worker.serialize(response) : response)\n  }\n\n  async function onMessage(rawMessage: unknown) {\n    const message: WorkerRequest = worker.deserialize\n      ? worker.deserialize(rawMessage)\n      : rawMessage\n\n    if (message?.__vitest_worker_request__ !== true) {\n      return\n    }\n\n    switch (message.type) {\n      case 'start': {\n        process.env.VITEST_POOL_ID = String(message.poolId)\n        process.env.VITEST_WORKER_ID = String(message.workerId)\n        reportMemory = message.options.reportMemory\n\n        traces ??= await new Traces({\n          enabled: message.traces.enabled,\n          sdkPath: message.traces.sdkPath,\n        }).waitInit()\n\n        const { environment, config, pool } = message.context\n        const context = traces.getContextFromCarrier(message.traces.otelCarrier)\n\n        // record telemetry as part of \"start\"\n        traces.recordInitSpan(context)\n\n        try {\n          const rpc = createRuntimeRpc(worker)\n          setupContext = {\n            environment,\n            config,\n            pool,\n            rpc,\n            projectName: config.name || '',\n            traces,\n          }\n          workerTeardown = await traces.$(\n            'vitest.runtime.setup',\n            { context },\n            () => worker.setup?.(setupContext),\n          )\n\n          send({ type: 'started', __vitest_worker_response__ })\n        }\n        catch (error) {\n          send({ type: 'started', __vitest_worker_response__, error: serializeError(error) })\n        }\n\n        break\n      }\n\n      case 'run': {\n        // Prevent concurrent execution if worker is already running\n        if (isRunning) {\n          send({\n            type: 'testfileFinished',\n            __vitest_worker_response__,\n            error: serializeError(new Error('[vitest-worker]: Worker is already running tests')),\n          })\n          return\n        }\n\n        try {\n          process.env.VITEST_WORKER_ID = String(message.context.workerId)\n        }\n        catch (error) {\n          return send({\n            type: 'testfileFinished',\n            __vitest_worker_response__,\n            error: serializeError(error),\n            usedMemory: reportMemory ? memoryUsage().heapUsed : undefined,\n          })\n        }\n\n        isRunning = true\n\n        try {\n          const tracesContext = traces.getContextFromCarrier(message.otelCarrier)\n          runPromise = traces.$(\n            'vitest.runtime.run',\n            {\n              context: tracesContext,\n              attributes: {\n                'vitest.worker.specifications': traces.isEnabled()\n                  ? getFilesWithLocations(message.context.files)\n                  : [],\n                'vitest.worker.id': message.context.workerId,\n              },\n            },\n            () => entrypoint.run({ ...setupContext, ...message.context }, worker, traces)\n              .catch(error => serializeError(error)),\n          )\n          const error = await runPromise\n\n          send({\n            type: 'testfileFinished',\n            __vitest_worker_response__,\n            error,\n            usedMemory: reportMemory ? memoryUsage().heapUsed : undefined,\n          })\n        }\n        finally {\n          runPromise = undefined\n          isRunning = false\n        }\n\n        break\n      }\n\n      case 'collect': {\n        // Prevent concurrent execution if worker is already running\n        if (isRunning) {\n          send({\n            type: 'testfileFinished',\n            __vitest_worker_response__,\n            error: serializeError(new Error('[vitest-worker]: Worker is already running tests')),\n          })\n          return\n        }\n\n        try {\n          process.env.VITEST_WORKER_ID = String(message.context.workerId)\n        }\n        catch (error) {\n          return send({\n            type: 'testfileFinished',\n            __vitest_worker_response__,\n            error: serializeError(error),\n            usedMemory: reportMemory ? memoryUsage().heapUsed : undefined,\n          })\n        }\n\n        isRunning = true\n\n        try {\n          const tracesContext = traces.getContextFromCarrier(message.otelCarrier)\n          runPromise = traces.$(\n            'vitest.runtime.collect',\n            {\n              context: tracesContext,\n              attributes: {\n                'vitest.worker.specifications': traces.isEnabled()\n                  ? getFilesWithLocations(message.context.files)\n                  : [],\n                'vitest.worker.id': message.context.workerId,\n              },\n            },\n            () => entrypoint.collect({ ...setupContext, ...message.context }, worker, traces)\n              .catch(error => serializeError(error)),\n          )\n          const error = await runPromise\n\n          send({\n            type: 'testfileFinished',\n            __vitest_worker_response__,\n            error,\n            usedMemory: reportMemory ? memoryUsage().heapUsed : undefined,\n          })\n        }\n        finally {\n          runPromise = undefined\n          isRunning = false\n        }\n\n        break\n      }\n\n      case 'stop': {\n        await runPromise\n\n        try {\n          const context = traces.getContextFromCarrier(message.otelCarrier)\n\n          const error = await traces.$(\n            'vitest.runtime.teardown',\n            { context },\n            async () => {\n              const error = await entrypoint.teardown().catch(error => serializeError(error))\n              await workerTeardown?.()\n              return error\n            },\n          )\n\n          await traces.finish()\n\n          send({ type: 'stopped', error, __vitest_worker_response__ })\n        }\n        catch (error) {\n          send({ type: 'stopped', error: serializeError(error), __vitest_worker_response__ })\n        }\n\n        worker.teardown?.()\n\n        break\n      }\n    }\n  }\n}\n\nfunction getFilesWithLocations(files: FileSpecification[]): string[] {\n  return files.flatMap((file) => {\n    if (!file.testLocations) {\n      return file.filepath\n    }\n    return file.testLocations.map((location) => {\n      return `${file}:${location}`\n    })\n  })\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/native.ts",
    "content": "import type { SourceMap } from 'magic-string'\nimport type { WorkerSetupContext } from '../../types/worker'\nimport type { NativeModuleMocker } from '../moduleRunner/nativeModuleMocker'\nimport module, { isBuiltin } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { MessageChannel } from 'node:worker_threads'\nimport { hoistMocks, initSyntaxLexers } from '@vitest/mocker/transforms'\nimport { cleanUrl } from '@vitest/utils/helpers'\nimport { parse } from 'acorn'\nimport MagicString from 'magic-string'\nimport { resolve } from 'pathe'\nimport c from 'tinyrainbow'\nimport { distDir } from '../../paths'\nimport { toBuiltin } from '../../utils/modules'\n\nconst NOW_LENGTH = Date.now().toString().length\nconst REGEXP_VITEST = new RegExp(`%3Fvitest=\\\\d{${NOW_LENGTH}}`)\nconst REGEXP_MOCK_ACTUAL = /\\?mock=actual/\n\nexport async function setupNodeLoaderHooks(worker: WorkerSetupContext): Promise<void> {\n  if (module.setSourceMapsSupport) {\n    module.setSourceMapsSupport(true)\n  }\n  else if (process.setSourceMapsEnabled) {\n    process.setSourceMapsEnabled(true)\n  }\n\n  if (worker.config.experimental.nodeLoader !== false) {\n    await initSyntaxLexers()\n  }\n\n  if (typeof module.registerHooks === 'function') {\n    module.registerHooks({\n      resolve(specifier, context, nextResolve) {\n        if (specifier.includes('mock=actual')) {\n          // url is already resolved by `importActual`\n          const moduleId = specifier.replace(REGEXP_MOCK_ACTUAL, '')\n          const builtin = isBuiltin(moduleId)\n          const url = builtin ? toBuiltin(moduleId) : moduleId\n          return {\n            url,\n            format: builtin ? 'builtin' : undefined,\n            shortCircuit: true,\n          }\n        }\n\n        const isVitest = specifier.includes('%3Fvitest=')\n        const result = nextResolve(\n          isVitest ? specifier.replace(REGEXP_VITEST, '') : specifier,\n          context,\n        )\n\n        // avoid tracking /node_modules/ module graph for performance reasons\n        if (context.parentURL && result.url && !result.url.includes('/node_modules/')) {\n          worker.rpc.ensureModuleGraphEntry(result.url, context.parentURL).catch(() => {\n            // ignore errors\n          })\n        }\n\n        // this is require for in-source tests to be invalidated if\n        // one of the files already imported it in --maxWorkers=1 --no-isolate\n        if (isVitest) {\n          result.url = `${result.url}?vitest=${Date.now()}`\n        }\n        if (\n          // nodeLoader disables mocking and `import.meta.vitest`\n          worker.config.experimental.nodeLoader === false\n          // something is wrong if there is no parent, we should not mock anything\n          || !context.parentURL\n          // ignore any transforms inside of `vitest` module\n          || result.url.includes(distDir)\n          || context.parentURL?.toString().includes(distDir)\n        ) {\n          return result\n        }\n\n        const mocker = getNativeMocker()\n        const mockedResult = mocker?.resolveMockedModule(result.url, context.parentURL)\n        if (mockedResult != null) {\n          return mockedResult\n        }\n\n        return result\n      },\n      load: worker.config.experimental.nodeLoader === false\n        ? undefined\n        : createLoadHook(worker),\n    })\n  }\n  else if (module.register) {\n    if (worker.config.experimental.nodeLoader !== false) {\n      console.warn(\n        `${c.bgYellow(' WARNING ')} \"module.registerHooks\" is not supported in Node.js ${process.version}. This means that some features like module mocking or in-source testing are not supported. Upgrade your Node.js version to at least 22.15 or disable \"experimental.nodeLoader\" flag manually.\\n`,\n      )\n    }\n    const { port1, port2 } = new MessageChannel()\n    port1.unref()\n    port2.unref()\n    port1.on('message', (data) => {\n      if (!data || typeof data !== 'object') {\n        return\n      }\n      switch (data.event) {\n        case 'register-module-graph-entry': {\n          const { url, parentURL } = data\n          worker.rpc.ensureModuleGraphEntry(url, parentURL)\n          return\n        }\n        default: {\n          console.error('Unknown message event:', data.event)\n        }\n      }\n    })\n    /** Registers {@link file://./../nodejsWorkerLoader.ts} */\n    module.register('#nodejs-worker-loader', {\n      parentURL: import.meta.url,\n      data: { port: port2 },\n      transferList: [port2],\n    })\n  }\n  else if (!process.versions.deno && !process.versions.bun) {\n    console.warn(\n      '\"module.registerHooks\" and \"module.register\" are not supported. Some Vitest features may not work. Please, use Node.js 18.19.0 or higher.',\n    )\n  }\n}\n\nfunction replaceInSourceMarker(url: string, source: string, ms: () => MagicString) {\n  const re = /import\\.meta\\.vitest/g\n  let match: RegExpExecArray | null\n  let overridden = false\n  // eslint-disable-next-line no-cond-assign\n  while ((match = re.exec(source))) {\n    const { index, '0': code } = match\n    overridden = true\n    // should it support process.vitest for CJS modules?\n    ms().overwrite(index, index + code.length, 'IMPORT_META_TEST()') // the length is the same\n  }\n  if (overridden) {\n    const filename = resolve(fileURLToPath(url))\n    // appending instead of prepending because functions are hoisted and we don't change the offset\n    ms().append(`;\\nfunction IMPORT_META_TEST() { return typeof __vitest_worker__ !== 'undefined' && __vitest_worker__.filepath === \"${filename.replace(/\"/g, '\\\\\"')}\" ? __vitest_index__ : undefined; }`)\n  }\n}\n\nconst ignoreFormats = new Set<string>([\n  'addon',\n  'builtin',\n  'wasm',\n])\n\nfunction createLoadHook(_worker: WorkerSetupContext): module.LoadHookSync {\n  return (url, context, nextLoad) => {\n    const result: module.LoadFnOutput = url.includes('mock=') && isBuiltin(cleanUrl(url))\n      ? { format: 'commonjs' } // avoid resolving the builtin module that is supposed to be mocked\n      : nextLoad(url, context)\n    if (\n      (result.format && ignoreFormats.has(result.format))\n      || url.includes(distDir)\n    ) {\n      return result\n    }\n\n    const mocker = getNativeMocker()\n\n    mocker?.checkCircularManualMock(url)\n\n    if (url.includes('mock=automock') || url.includes('mock=autospy')) {\n      const automockedResult = mocker?.loadAutomock(url, result)\n      if (automockedResult != null) {\n        return automockedResult\n      }\n      return result\n    }\n\n    if (url.includes('mock=manual')) {\n      const mockedResult = mocker?.loadManualMock(url, result)\n      if (mockedResult != null) {\n        return mockedResult\n      }\n      return result\n    }\n\n    // ignore non-vitest modules for performance reasons,\n    // vi.hoisted and vi.mock won't work outside of test files or setup files\n    if (!result.source || !url.includes('vitest=')) {\n      return result\n    }\n\n    const filename = url.startsWith('file://') ? fileURLToPath(url) : url\n    const source = result.source.toString()\n    const transformedCode = result.format?.includes('typescript')\n      ? module.stripTypeScriptTypes(source)\n      : source\n\n    let _ms: MagicString | undefined\n    const ms = () => _ms || (_ms = new MagicString(source))\n\n    if (source.includes('import.meta.vitest')) {\n      replaceInSourceMarker(url, source, ms)\n    }\n\n    hoistMocks(\n      transformedCode,\n      filename,\n      code => parse(code, {\n        ecmaVersion: 'latest',\n        sourceType: result.format === 'module' || result.format === 'module-typescript' || result.format === 'typescript'\n          ? 'module'\n          : 'script',\n      }),\n      {\n        magicString: ms,\n        globalThisAccessor: '\"__vitest_mocker__\"',\n      },\n    )\n\n    let code: string\n    if (_ms) {\n      const transformed = _ms.toString()\n      const map = _ms.generateMap({ hires: 'boundary', source: filename })\n      code = `${transformed}\\n//# sourceMappingURL=${genSourceMapUrl(map)}`\n    }\n    else {\n      code = source\n    }\n\n    return {\n      format: result.format,\n      shortCircuit: true,\n      source: code,\n    }\n  }\n}\n\nfunction genSourceMapUrl(map: SourceMap | string): string {\n  if (typeof map !== 'string') {\n    map = JSON.stringify(map)\n  }\n  return `data:application/json;base64,${Buffer.from(map).toString('base64')}`\n}\n\nfunction getNativeMocker() {\n  const mocker: NativeModuleMocker | undefined\n  // @ts-expect-error untyped global\n    = typeof __vitest_mocker__ !== 'undefined' ? __vitest_mocker__ : undefined\n  return mocker\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/threads.ts",
    "content": "import { runBaseTests, setupBaseEnvironment } from './base'\nimport workerInit from './init-threads'\n\nworkerInit({ runTests: runBaseTests, setup: setupBaseEnvironment })\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/types.ts",
    "content": "import type { Awaitable } from '@vitest/utils'\nimport type { BirpcOptions } from 'birpc'\nimport type { ModuleRunner } from 'vite/module-runner'\nimport type { RuntimeRPC } from '../../types/rpc'\nimport type { WorkerGlobalState, WorkerSetupContext } from '../../types/worker'\nimport type { Traces } from '../../utils/traces'\n\ntype WorkerRpcOptions = Pick<\n  BirpcOptions<RuntimeRPC>,\n  'on' | 'off' | 'post' | 'serialize' | 'deserialize'\n>\n\nexport interface VitestWorker extends WorkerRpcOptions {\n  runTests: (state: WorkerGlobalState, traces: Traces) => Awaitable<unknown>\n  collectTests: (state: WorkerGlobalState, traces: Traces) => Awaitable<unknown>\n  onModuleRunner?: (moduleRunner: ModuleRunner) => Awaitable<unknown>\n  setup?: (context: WorkerSetupContext) => void | Promise<() => Promise<unknown>>\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/vm.ts",
    "content": "import type { Context } from 'node:vm'\nimport type { WorkerGlobalState, WorkerSetupContext } from '../../types/worker'\nimport type { Traces } from '../../utils/traces'\nimport { pathToFileURL } from 'node:url'\nimport { isContext, runInContext } from 'node:vm'\nimport { resolve } from 'pathe'\nimport { loadEnvironment } from '../../integrations/env/loader'\nimport { distDir } from '../../paths'\nimport { createCustomConsole } from '../console'\nimport { ExternalModulesExecutor } from '../external-executor'\nimport { emitModuleRunner } from '../listeners'\nimport { listenForErrors } from '../moduleRunner/errorCatcher'\nimport { getDefaultRequestStubs } from '../moduleRunner/moduleEvaluator'\nimport { createNodeImportMeta } from '../moduleRunner/moduleRunner'\nimport { startVitestModuleRunner, VITEST_VM_CONTEXT_SYMBOL } from '../moduleRunner/startVitestModuleRunner'\nimport { provideWorkerState } from '../utils'\nimport { FileMap } from '../vm/file-map'\n\nconst entryFile = pathToFileURL(resolve(distDir, 'workers/runVmTests.js')).href\n\nconst fileMap = new FileMap()\nconst packageCache = new Map<string, string>()\n\nexport async function runVmTests(method: 'run' | 'collect', state: WorkerGlobalState, traces: Traces): Promise<void> {\n  const { ctx, rpc } = state\n\n  const beforeEnvironmentTime = performance.now()\n  const { environment } = await loadEnvironment(ctx.environment.name, ctx.config.root, rpc, traces, true)\n  state.environment = environment\n\n  if (!environment.setupVM) {\n    const envName = ctx.environment.name\n    const packageId\n      = envName[0] === '.' ? envName : `vitest-environment-${envName}`\n    throw new TypeError(\n      `Environment \"${ctx.environment.name}\" is not a valid environment. `\n      + `Path \"${packageId}\" doesn't support vm environment because it doesn't provide \"setupVM\" method.`,\n    )\n  }\n\n  const vm = await traces.$(\n    'vitest.runtime.environment.setup',\n    {\n      attributes: {\n        'vitest.environment': environment.name,\n        'vitest.environment.vite_environment': environment.viteEnvironment || environment.name,\n      },\n    },\n    () => environment.setupVM!(ctx.environment.options || ctx.config.environmentOptions || {}),\n  )\n\n  state.durations.environment = performance.now() - beforeEnvironmentTime\n\n  process.env.VITEST_VM_POOL = '1'\n\n  if (!vm.getVmContext) {\n    throw new TypeError(\n      `Environment ${environment.name} doesn't provide \"getVmContext\" method. It should return a context created by \"vm.createContext\" method.`,\n    )\n  }\n\n  const context: Context | null = vm.getVmContext()\n\n  if (!isContext(context)) {\n    throw new TypeError(\n      `Environment ${environment.name} doesn't provide a valid context. It should be created by \"vm.createContext\" method.`,\n    )\n  }\n\n  provideWorkerState(context, state)\n\n  // this is unfortunately needed for our own dependencies\n  // we need to find a way to not rely on this by default\n  // because browser doesn't provide these globals\n  context.process = process\n  context.global = context\n  context.console = state.config.disableConsoleIntercept\n    ? console\n    : createCustomConsole(state)\n  // TODO: don't hardcode setImmediate in fake timers defaults\n  context.setImmediate = setImmediate\n  context.clearImmediate = clearImmediate\n\n  const stubs = getDefaultRequestStubs(context)\n\n  const externalModulesExecutor = new ExternalModulesExecutor({\n    context,\n    fileMap,\n    packageCache,\n    transform: rpc.transform,\n    viteClientModule: stubs['/@vite/client'],\n  })\n\n  process.exit = (code = process.exitCode || 0): never => {\n    throw new Error(`process.exit unexpectedly called with \"${code}\"`)\n  }\n\n  listenForErrors(() => state)\n\n  const moduleRunner = startVitestModuleRunner({\n    context,\n    evaluatedModules: state.evaluatedModules,\n    state,\n    externalModulesExecutor,\n    createImportMeta: createNodeImportMeta,\n    traces,\n  })\n\n  emitModuleRunner(moduleRunner as any)\n\n  Object.defineProperty(context, VITEST_VM_CONTEXT_SYMBOL, {\n    value: {\n      context,\n      externalModulesExecutor,\n    },\n    configurable: true,\n    enumerable: false,\n    writable: false,\n  })\n  context.__vitest_mocker__ = moduleRunner.mocker\n\n  if (ctx.config.serializedDefines) {\n    try {\n      runInContext(ctx.config.serializedDefines, context, {\n        filename: 'virtual:load-defines.js',\n      })\n    }\n    catch (error: any) {\n      throw new Error(`Failed to load custom \"defines\": ${error.message}`)\n    }\n  }\n  await moduleRunner.mocker.initializeSpyModule()\n\n  const { run } = (await moduleRunner.import(\n    entryFile,\n  )) as typeof import('../runVmTests')\n\n  try {\n    await run(\n      method,\n      ctx.files,\n      ctx.config,\n      moduleRunner,\n      traces,\n    )\n  }\n  finally {\n    await traces.$(\n      'vitest.runtime.environment.teardown',\n      () => vm.teardown?.(),\n    )\n  }\n}\n\nexport function setupVmWorker(context: WorkerSetupContext): void {\n  if (context.config.experimental.viteModuleRunner === false) {\n    throw new Error(`Pool \"${context.pool}\" cannot run with \"experimental.viteModuleRunner: false\". Please, use \"threads\" or \"forks\" instead.`)\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/vmForks.ts",
    "content": "import workerInit from './init-forks'\nimport { runVmTests, setupVmWorker } from './vm'\n\nworkerInit({ runTests: runVmTests, setup: setupVmWorker })\n"
  },
  {
    "path": "packages/vitest/src/runtime/workers/vmThreads.ts",
    "content": "import workerInit from './init-threads'\nimport { runVmTests, setupVmWorker } from './vm'\n\nworkerInit({ runTests: runVmTests, setup: setupVmWorker })\n"
  },
  {
    "path": "packages/vitest/src/shims.dev.d.ts",
    "content": "declare global {\n  const __VITEST_GENERATE_UI_TOKEN__: boolean\n}\n\nexport {}\n"
  },
  {
    "path": "packages/vitest/src/typecheck/assertType.ts",
    "content": "export interface AssertType {\n  <T>(value: T): void\n}\n\nexport const assertType: AssertType = function assertType() {}\n"
  },
  {
    "path": "packages/vitest/src/typecheck/collect.ts",
    "content": "import type { File, RunMode, Suite, Test } from '@vitest/runner'\nimport type { Rollup } from 'vite'\nimport type { TestProject } from '../node/project'\nimport {\n  calculateSuiteHash,\n  createTaskName,\n  generateHash,\n  interpretTaskModes,\n  someTasksAreOnly,\n} from '@vitest/runner/utils'\nimport { ancestor as walkAst } from 'acorn-walk'\nimport { relative } from 'pathe'\nimport { parseAstAsync } from 'vite'\n\ninterface ParsedFile extends File {\n  start: number\n  end: number\n}\n\ninterface ParsedTest extends Test {\n  start: number\n  end: number\n}\n\ninterface ParsedSuite extends Suite {\n  start: number\n  end: number\n}\n\ninterface LocalCallDefinition {\n  start: number\n  end: number\n  name: string\n  type: 'suite' | 'test'\n  mode: RunMode\n  task: ParsedSuite | ParsedFile | ParsedTest\n}\n\nexport interface FileInformation {\n  file: File\n  filepath: string\n  parsed: string\n  map: Rollup.SourceMap | null\n  definitions: LocalCallDefinition[]\n}\n\nexport async function collectTests(\n  ctx: TestProject,\n  filepath: string,\n): Promise<null | FileInformation> {\n  const request = await ctx.vite.environments.ssr.transformRequest(filepath)\n  if (!request) {\n    return null\n  }\n  const ast = await parseAstAsync(request.code)\n  const testFilepath = relative(ctx.config.root, filepath)\n  const projectName = ctx.name\n  const typecheckSubprojectName = projectName ? `${projectName}:__typecheck__` : '__typecheck__'\n  const file: ParsedFile = {\n    filepath,\n    type: 'suite',\n    id: generateHash(`${testFilepath}${typecheckSubprojectName}`),\n    name: testFilepath,\n    fullName: testFilepath,\n    mode: 'run',\n    tasks: [],\n    start: ast.start,\n    end: ast.end,\n    projectName,\n    meta: { typecheck: true },\n    file: null!,\n  }\n  file.file = file\n  const definitions: LocalCallDefinition[] = []\n  const getName = (callee: any): string | null => {\n    if (!callee) {\n      return null\n    }\n    if (callee.type === 'Identifier') {\n      return callee.name\n    }\n    if (callee.type === 'CallExpression') {\n      return getName(callee.callee)\n    }\n    if (callee.type === 'TaggedTemplateExpression') {\n      return getName(callee.tag)\n    }\n    if (callee.type === 'MemberExpression') {\n      if (\n        callee.object?.type === 'Identifier'\n        && ['it', 'test', 'describe', 'suite'].includes(callee.object.name)\n      ) {\n        return callee.object?.name\n      }\n      // direct call as `__vite_ssr_exports_0__.test()`\n      if (callee.object?.name?.startsWith('__vite_ssr_')) {\n        return getName(callee.property)\n      }\n      // call as `__vite_ssr__.test.skip()`\n      return getName(callee.object?.property)\n    }\n    // unwrap (0, ...)\n    if (callee.type === 'SequenceExpression' && callee.expressions.length === 2) {\n      const [e0, e1] = callee.expressions\n      if (e0.type === 'Literal' && e0.value === 0) {\n        return getName(e1)\n      }\n    }\n    return null\n  }\n\n  walkAst(ast as any, {\n    CallExpression(node) {\n      const { callee } = node as any\n      const name = getName(callee)\n      if (!name) {\n        return\n      }\n      if (!['it', 'test', 'describe', 'suite'].includes(name)) {\n        return\n      }\n      const property = callee?.property?.name\n      let mode = !property || property === name ? 'run' : property\n      // they will be picked up in the next iteration\n      if (['each', 'for', 'skipIf', 'runIf'].includes(mode)) {\n        return\n      }\n\n      let start: number\n      const end = node.end\n      // .each\n      if (callee.type === 'CallExpression') {\n        start = callee.end\n      }\n      else if (callee.type === 'TaggedTemplateExpression') {\n        start = callee.end + 1\n      }\n      else {\n        start = node.start\n      }\n\n      const {\n        arguments: [messageNode],\n      } = node\n\n      const isQuoted = messageNode?.type === 'Literal' || messageNode?.type === 'TemplateLiteral'\n      const message = isQuoted\n        ? request.code.slice(messageNode.start + 1, messageNode.end - 1)\n        : request.code.slice(messageNode.start, messageNode.end)\n\n      // cannot statically analyze, so we always skip it\n      if (mode === 'skipIf' || mode === 'runIf') {\n        mode = 'skip'\n      }\n      definitions.push({\n        start,\n        end,\n        name: message,\n        type: name === 'it' || name === 'test' ? 'test' : 'suite',\n        mode,\n        task: null as any,\n      } satisfies LocalCallDefinition)\n    },\n  })\n  let lastSuite: ParsedSuite = file\n  const updateLatestSuite = (index: number) => {\n    while (lastSuite.suite && lastSuite.end < index) {\n      lastSuite = lastSuite.suite as ParsedSuite\n    }\n    return lastSuite\n  }\n  definitions\n    .sort((a, b) => a.start - b.start)\n    .forEach((definition) => {\n      const latestSuite = updateLatestSuite(definition.start)\n      let mode = definition.mode\n      if (latestSuite.mode !== 'run') {\n        // inherit suite mode, if it's set\n        mode = latestSuite.mode\n      }\n      if (definition.type === 'suite') {\n        const task: ParsedSuite = {\n          type: definition.type,\n          id: '',\n          suite: latestSuite,\n          file,\n          tasks: [],\n          mode,\n          name: definition.name,\n          fullName: createTaskName([lastSuite.fullName, definition.name]),\n          fullTestName: createTaskName([lastSuite.fullTestName, definition.name]),\n          end: definition.end,\n          start: definition.start,\n          meta: {\n            typecheck: true,\n          },\n        }\n        definition.task = task\n        latestSuite.tasks.push(task)\n        lastSuite = task\n        return\n      }\n      const task: ParsedTest = {\n        type: definition.type,\n        id: '',\n        suite: latestSuite,\n        file,\n        mode,\n        timeout: 0,\n        context: {} as any, // not used in typecheck\n        name: definition.name,\n        fullName: createTaskName([lastSuite.fullName, definition.name]),\n        fullTestName: createTaskName([lastSuite.fullTestName, definition.name]),\n        end: definition.end,\n        start: definition.start,\n        annotations: [],\n        artifacts: [],\n        meta: {\n          typecheck: true,\n        },\n      }\n      definition.task = task\n      latestSuite.tasks.push(task)\n    })\n  calculateSuiteHash(file)\n  const hasOnly = someTasksAreOnly(file)\n  interpretTaskModes(\n    file,\n    ctx.config.testNamePattern,\n    undefined,\n    undefined,\n    undefined,\n    hasOnly,\n    false,\n    ctx.config.allowOnly,\n  )\n  return {\n    file,\n    parsed: request.code,\n    filepath,\n    map: request.map as Rollup.SourceMap | null,\n    definitions,\n  }\n}\n\nfunction getNodeAsString(node: any, code: string): string {\n  if (node.type === 'Literal') {\n    return String(node.value)\n  }\n  else if (node.type === 'Identifier') {\n    return node.name\n  }\n  else if (node.type === 'TemplateLiteral') {\n    return mergeTemplateLiteral(node, code)\n  }\n  else {\n    return code.slice(node.start, node.end)\n  }\n}\n\nfunction mergeTemplateLiteral(node: any, code: string): string {\n  let result = ''\n  let expressionsIndex = 0\n\n  for (let quasisIndex = 0; quasisIndex < node.quasis.length; quasisIndex++) {\n    result += node.quasis[quasisIndex].value.raw\n    if (expressionsIndex in node.expressions) {\n      const expression = node.expressions[expressionsIndex]\n      const string = expression.type === 'Literal' ? expression.raw : getNodeAsString(expression, code)\n      if (expression.type === 'TemplateLiteral') {\n        result += `\\${\\`${string}\\`}`\n      }\n      else {\n        result += `\\${${string}}`\n      }\n      expressionsIndex++\n    }\n  }\n  return result\n}\n"
  },
  {
    "path": "packages/vitest/src/typecheck/expectTypeOf.ts",
    "content": "export { expectTypeOf, type ExpectTypeOf } from 'expect-type'\n"
  },
  {
    "path": "packages/vitest/src/typecheck/parse.ts",
    "content": "import type { RawErrsMap, TscErrorInfo } from './types'\n\nconst newLineRegExp = /\\r?\\n/\nconst errCodeRegExp = /error TS(?<errCode>\\d+)/\n\nexport async function makeTscErrorInfo(\n  errInfo: string,\n): Promise<[string, TscErrorInfo | null]> {\n  const [errFilePathPos = '', ...errMsgRawArr] = errInfo.split(':')\n  if (\n    !errFilePathPos\n    || errMsgRawArr.length === 0\n    || errMsgRawArr.join('').length === 0\n  ) {\n    return ['unknown filepath', null]\n  }\n\n  const errMsgRaw = errMsgRawArr.join('').trim()\n\n  // get filePath, line, col\n  const [errFilePath, errPos] = errFilePathPos\n    .slice(0, -1) // removes the ')'\n    .split('(')\n  if (!errFilePath || !errPos) {\n    return ['unknown filepath', null]\n  }\n\n  const [errLine, errCol] = errPos.split(',')\n  if (!errLine || !errCol) {\n    return [errFilePath, null]\n  }\n\n  // get errCode, errMsg\n  const execArr = errCodeRegExp.exec(errMsgRaw)\n  if (!execArr) {\n    return [errFilePath, null]\n  }\n\n  const errCodeStr = execArr.groups?.errCode ?? ''\n  if (!errCodeStr) {\n    return [errFilePath, null]\n  }\n\n  const line = Number(errLine)\n  const col = Number(errCol)\n  const errCode = Number(errCodeStr)\n  return [\n    errFilePath,\n    {\n      filePath: errFilePath,\n      errCode,\n      line,\n      column: col,\n      errMsg: errMsgRaw.slice(`error TS${errCode} `.length),\n    },\n  ]\n}\n\nexport async function getRawErrsMapFromTsCompile(tscErrorStdout: string): Promise<RawErrsMap> {\n  const rawErrsMap: RawErrsMap = new Map()\n\n  // Merge details line with main line (i.e. which contains file path)\n  const infos = await Promise.all(\n    tscErrorStdout\n      .split(newLineRegExp)\n      .reduce<string[]>((prev, next) => {\n        if (!next) {\n          return prev\n        }\n        else if (next[0] !== ' ') {\n          prev.push(next)\n        }\n        else {\n          prev[prev.length - 1] += `\\n${next}`\n        }\n\n        return prev\n      }, [])\n      .map(errInfoLine => makeTscErrorInfo(errInfoLine)),\n  )\n  infos.forEach(([errFilePath, errInfo]) => {\n    if (!errInfo) {\n      return\n    }\n\n    if (!rawErrsMap.has(errFilePath)) {\n      rawErrsMap.set(errFilePath, [errInfo])\n    }\n    else {\n      rawErrsMap.get(errFilePath)?.push(errInfo)\n    }\n  })\n  return rawErrsMap\n}\n"
  },
  {
    "path": "packages/vitest/src/typecheck/typechecker.ts",
    "content": "import type { EachMapping } from '@jridgewell/trace-mapping'\nimport type { File, Task, TaskEventPack, TaskResultPack, TaskState } from '@vitest/runner'\nimport type { Awaitable, ParsedStack, TestError } from '@vitest/utils'\nimport type { ChildProcess } from 'node:child_process'\nimport type { Result } from 'tinyexec'\nimport type { Vitest } from '../node/core'\nimport type { TestProject } from '../node/project'\nimport type { FileInformation } from './collect'\nimport type { TscErrorInfo } from './types'\nimport os from 'node:os'\nimport { performance } from 'node:perf_hooks'\nimport { eachMapping, generatedPositionFor, TraceMap } from '@jridgewell/trace-mapping'\nimport { basename, join, resolve } from 'pathe'\nimport { x } from 'tinyexec'\nimport { distDir } from '../paths'\nimport { createLocationsIndexMap } from '../utils/base'\nimport { convertTasksToEvents } from '../utils/tasks'\nimport { collectTests } from './collect'\nimport { getRawErrsMapFromTsCompile } from './parse'\n\nexport class TypeCheckError extends Error {\n  name = 'TypeCheckError'\n\n  constructor(public message: string, public stacks: ParsedStack[]) {\n    super(message)\n  }\n}\n\nexport interface TypecheckResults {\n  files: File[]\n  sourceErrors: TestError[]\n  time: number\n}\n\ntype Callback<Args extends Array<any> = []> = (\n  ...args: Args\n) => Awaitable<void>\n\nexport class Typechecker {\n  private _onParseStart?: Callback\n  private _onParseEnd?: Callback<[TypecheckResults]>\n  private _onWatcherRerun?: Callback\n  private _result: TypecheckResults = {\n    files: [],\n    sourceErrors: [],\n    time: 0,\n  }\n\n  private _startTime = 0\n  private _output = ''\n  private _tests: Record<string, FileInformation> | null = {}\n  private process?: ChildProcess\n\n  protected files: string[] = []\n\n  constructor(protected project: TestProject) { }\n\n  public setFiles(files: string[]): void {\n    this.files = files\n  }\n\n  public onParseStart(fn: Callback): void {\n    this._onParseStart = fn\n  }\n\n  public onParseEnd(fn: Callback<[TypecheckResults]>): void {\n    this._onParseEnd = fn\n  }\n\n  public onWatcherRerun(fn: Callback): void {\n    this._onWatcherRerun = fn\n  }\n\n  protected async collectFileTests(\n    filepath: string,\n  ): Promise<FileInformation | null> {\n    return collectTests(this.project, filepath)\n  }\n\n  protected getFiles(): string[] {\n    return this.files\n  }\n\n  public async collectTests(): Promise<Record<string, FileInformation>> {\n    const tests = (\n      await Promise.all(\n        this.getFiles().map(filepath => this.collectFileTests(filepath)),\n      )\n    ).reduce((acc, data) => {\n      if (!data) {\n        return acc\n      }\n      acc[data.filepath] = data\n      return acc\n    }, {} as Record<string, FileInformation>)\n    this._tests = tests\n    return tests\n  }\n\n  protected markPassed(file: File): void {\n    if (!file.result?.state) {\n      file.result = {\n        state: 'pass',\n      }\n    }\n    const markTasks = (tasks: Task[]): void => {\n      for (const task of tasks) {\n        if ('tasks' in task) {\n          markTasks(task.tasks)\n        }\n        if (!task.result?.state && (task.mode === 'run' || task.mode === 'queued')) {\n          task.result = {\n            state: 'pass',\n          }\n        }\n      }\n    }\n    markTasks(file.tasks)\n  }\n\n  protected async prepareResults(output: string): Promise<{\n    files: File[]\n    sourceErrors: TestError[]\n    time: number\n  }> {\n    // Detect if tsc output is help text instead of error output\n    // This happens when tsconfig.json is missing and tsc can't find any config\n    if (output.includes('The TypeScript Compiler - Version') || output.includes('COMMON COMMANDS')) {\n      const { typecheck } = this.project.config\n      const tsconfigPath = typecheck.tsconfig || 'tsconfig.json'\n      const msg = `TypeScript compiler returned help text instead of type checking results.\\n`\n        + `This usually means the tsconfig file was not found.\\n\\n`\n        + `Possible solutions:\\n`\n        + `  1. Ensure '${tsconfigPath}' exists in your project root\\n`\n        + `  2. If using a custom tsconfig, verify the path in your Vitest config:\\n`\n        + `     test: { typecheck: { tsconfig: 'path/to/tsconfig.json' } }\\n`\n        + `  3. Check that the tsconfig file is valid JSON`\n\n      throw new Error(msg)\n    }\n\n    const typeErrors = await this.parseTscLikeOutput(output)\n    const testFiles = new Set(this.getFiles())\n\n    if (!this._tests) {\n      this._tests = await this.collectTests()\n    }\n\n    const sourceErrors: TestError[] = []\n    const files: File[] = []\n\n    testFiles.forEach((path) => {\n      const { file, definitions, map, parsed } = this._tests![path]\n      const errors = typeErrors.get(path)\n      files.push(file)\n      if (!errors) {\n        this.markPassed(file)\n        return\n      }\n      const sortedDefinitions = [\n        ...definitions.sort((a, b) => b.start - a.start),\n      ]\n      // has no map for \".js\" files that use // @ts-check\n      const traceMap = (map && new TraceMap(map as any))\n      const indexMap = createLocationsIndexMap(parsed)\n      const markState = (task: Task, state: TaskState) => {\n        task.result = {\n          state:\n            task.mode === 'run' || task.mode === 'only' ? state : task.mode,\n        }\n        if (task.suite) {\n          markState(task.suite, state)\n        }\n        else if (task.file && task !== task.file) {\n          markState(task.file, state)\n        }\n      }\n      errors.forEach(({ error, originalError }) => {\n        const processedPos = traceMap\n          ? findGeneratedPosition(traceMap, {\n              line: originalError.line,\n              column: originalError.column,\n              source: basename(path),\n            })\n          : originalError\n        const line = processedPos.line ?? originalError.line\n        const column = processedPos.column ?? originalError.column\n        const index = indexMap.get(`${line}:${column}`)\n        const definition\n          = index != null\n            && sortedDefinitions.find(\n              def => def.start <= index && def.end >= index,\n            )\n        const suite = definition ? definition.task : file\n        const state: TaskState\n          = suite.mode === 'run' || suite.mode === 'only' ? 'fail' : suite.mode\n        const errors = suite.result?.errors || []\n        suite.result = {\n          state,\n          errors,\n        }\n        errors.push(error)\n        if (state === 'fail') {\n          if (suite.suite) {\n            markState(suite.suite, 'fail')\n          }\n          else if (suite.file && suite !== suite.file) {\n            markState(suite.file, 'fail')\n          }\n        }\n      })\n\n      this.markPassed(file)\n    })\n\n    typeErrors.forEach((errors, path) => {\n      if (!testFiles.has(path)) {\n        sourceErrors.push(...errors.map(({ error }) => error))\n      }\n    })\n\n    return {\n      files,\n      sourceErrors,\n      time: performance.now() - this._startTime,\n    }\n  }\n\n  protected async parseTscLikeOutput(output: string): Promise<Map<string, {\n    error: TestError\n    originalError: TscErrorInfo\n  }[]>> {\n    const errorsMap = await getRawErrsMapFromTsCompile(output)\n    const typesErrors = new Map<\n      string,\n      { error: TestError; originalError: TscErrorInfo }[]\n    >()\n    errorsMap.forEach((errors, path) => {\n      const filepath = resolve(this.project.config.root, path)\n      const suiteErrors = errors.map((info) => {\n        const limit = Error.stackTraceLimit\n        Error.stackTraceLimit = 0\n        // Some expect-type errors have the most useful information on the second line e.g. `This expression is not callable.\\n  Type 'ExpectString<number>' has no call signatures.`\n        const errMsg = info.errMsg.replace(\n          /\\r?\\n\\s*(Type .* has no call signatures)/g,\n          ' $1',\n        )\n        const error = new TypeCheckError(errMsg, [\n          {\n            file: filepath,\n            line: info.line,\n            column: info.column,\n            method: '',\n          },\n        ])\n        Error.stackTraceLimit = limit\n        return {\n          originalError: info,\n          error: {\n            name: error.name,\n            message: errMsg,\n            stacks: error.stacks,\n            stack: '',\n          } satisfies TestError,\n        }\n      })\n      typesErrors.set(filepath, suiteErrors)\n    })\n    return typesErrors\n  }\n\n  public async stop(): Promise<void> {\n    this.process?.kill()\n    this.process = undefined\n  }\n\n  protected async ensurePackageInstalled(ctx: Vitest, checker: string): Promise<void> {\n    if (checker !== 'tsc' && checker !== 'vue-tsc') {\n      return\n    }\n    const packageName = checker === 'tsc' ? 'typescript' : 'vue-tsc'\n    await ctx.packageInstaller.ensureInstalled(packageName, ctx.config.root)\n  }\n\n  public getExitCode(): number | false {\n    return this.process?.exitCode != null && this.process.exitCode\n  }\n\n  public getOutput(): string {\n    return this._output\n  }\n\n  private async spawn() {\n    const { root, watch, typecheck } = this.project.config\n\n    const args = [\n      '--noEmit',\n      '--pretty',\n      'false',\n      '--incremental',\n      '--tsBuildInfoFile',\n      join(\n        process.versions.pnp ? join(os.tmpdir(), this.project.hash) : distDir,\n        'tsconfig.tmp.tsbuildinfo',\n      ),\n    ]\n    // use builtin watcher because it's faster\n    if (watch) {\n      args.push('--watch')\n    }\n    if (typecheck.allowJs) {\n      args.push('--allowJs', '--checkJs')\n    }\n    if (typecheck.tsconfig) {\n      args.push('-p', resolve(root, typecheck.tsconfig))\n    }\n    this._output = ''\n    this._startTime = performance.now()\n    const child = x(typecheck.checker, args, {\n      nodeOptions: {\n        cwd: root,\n        stdio: 'pipe',\n      },\n      throwOnError: false,\n    })\n\n    this.process = child.process\n\n    let rerunTriggered = false\n    let dataReceived = false\n\n    return new Promise<{ result: Result }>((resolve, reject) => {\n      if (!child.process || !child.process.stdout) {\n        reject(new Error(`Failed to initialize ${typecheck.checker}. This is a bug in Vitest - please, open an issue with reproduction.`))\n        return\n      }\n\n      let resolved = false\n\n      child.process.stdout.on('data', (chunk) => {\n        dataReceived = true\n        this._output += chunk\n        if (!watch) {\n          return\n        }\n        if (this._output.includes('File change detected') && !rerunTriggered) {\n          this._onWatcherRerun?.()\n          this._startTime = performance.now()\n          this._result.sourceErrors = []\n          this._result.files = []\n          this._tests = null // test structure might've changed\n          rerunTriggered = true\n        }\n        if (/Found \\w+ errors*. Watching for/.test(this._output)) {\n          rerunTriggered = false\n          this.prepareResults(this._output).then((result) => {\n            this._result = result\n            this._onParseEnd?.(result)\n          })\n          this._output = ''\n        }\n      })\n\n      // Also capture stderr for configuration errors like missing tsconfig\n      child.process.stderr?.on('data', (chunk) => {\n        this._output += chunk\n      })\n\n      const timeout = setTimeout(\n        () => reject(new Error(`${typecheck.checker} spawn timed out`)),\n        this.project.config.typecheck.spawnTimeout,\n      )\n\n      let winTimeout: NodeJS.Timeout | undefined\n\n      function onError(cause: Error) {\n        if (resolved) {\n          return\n        }\n        clearTimeout(timeout)\n        clearTimeout(winTimeout)\n        resolved = true\n        reject(new Error('Spawning typechecker failed - is typescript installed?', { cause }))\n      }\n\n      child.process.once('spawn', () => {\n        this._onParseStart?.()\n        child.process?.off('error', onError)\n        clearTimeout(timeout)\n        if (process.platform === 'win32') {\n          // on Windows, the process might be spawned but fail to start\n          // we wait for a potential error here. if \"close\" event didn't trigger,\n          // we resolve the promise\n          winTimeout = setTimeout(() => {\n            resolved = true\n            resolve({ result: child })\n          }, 200)\n        }\n        else {\n          resolved = true\n          resolve({ result: child })\n        }\n      })\n\n      if (process.platform === 'win32') {\n        child.process.once('close', (code) => {\n          if (code != null && code !== 0 && !dataReceived) {\n            onError(new Error(`The ${typecheck.checker} command exited with code ${code}.`))\n          }\n        })\n      }\n      child.process.once('error', onError)\n    })\n  }\n\n  public async start(): Promise<void> {\n    if (this.process) {\n      return\n    }\n\n    const { watch } = this.project.config\n    const { result: child } = await this.spawn()\n\n    if (!watch) {\n      await child\n      this._result = await this.prepareResults(this._output)\n      await this._onParseEnd?.(this._result)\n    }\n  }\n\n  public getResult(): TypecheckResults {\n    return this._result\n  }\n\n  public getTestFiles(): File[] {\n    return Object.values(this._tests || {}).map(i => i.file)\n  }\n\n  public getTestPacksAndEvents(): {\n    packs: TaskResultPack[]\n    events: TaskEventPack[]\n  } {\n    const packs: TaskResultPack[] = []\n    const events: TaskEventPack[] = []\n\n    for (const { file } of Object.values(this._tests || {})) {\n      const result = convertTasksToEvents(file)\n      packs.push(...result.packs)\n      events.push(...result.events)\n    }\n\n    return { packs, events }\n  }\n}\n\nfunction findGeneratedPosition(traceMap: TraceMap, { line, column, source }: { line: number; column: number; source: string }) {\n  const found = generatedPositionFor(traceMap, {\n    line,\n    column,\n    source,\n  })\n  if (found.line !== null) {\n    return found\n  }\n  // find the next source token position when the exact error position doesn't exist in source map.\n  // this can happen, for example, when the type error is in the comment \"// @ts-expect-error\"\n  // and comments are stripped away in the generated code.\n  const mappings: (EachMapping & { originalLine: number })[] = []\n  eachMapping(traceMap, (m) => {\n    if (\n      m.source === source\n      && m.originalLine !== null\n      && m.originalColumn !== null\n      && (line === m.originalLine ? column < m.originalColumn : line < m.originalLine)\n    ) {\n      mappings.push(m)\n    }\n  })\n  const next = mappings\n    .sort((a, b) =>\n      a.originalLine === b.originalLine ? a.originalColumn - b.originalColumn : a.originalLine - b.originalLine,\n    )\n    .at(0)\n  if (next) {\n    return {\n      line: next.generatedLine,\n      column: next.generatedColumn,\n    }\n  }\n  return { line: null, column: null }\n}\n"
  },
  {
    "path": "packages/vitest/src/typecheck/types.ts",
    "content": "export type RawErrsMap = Map<string, TscErrorInfo[]>\nexport interface TscErrorInfo {\n  filePath: string\n  errCode: number\n  errMsg: string\n  line: number\n  column: number\n}\nexport interface CollectLineNumbers {\n  target: number\n  next: number\n  prev?: number\n}\nexport type CollectLines = {\n  [key in keyof CollectLineNumbers]: string;\n}\nexport interface RootAndTarget {\n  root: string\n  targetAbsPath: string\n}\nexport type Context = RootAndTarget & {\n  rawErrsMap: RawErrsMap\n  openedDirs: Set<string>\n  lastActivePath?: string\n}\n"
  },
  {
    "path": "packages/vitest/src/types/browser.ts",
    "content": "import type { FileSpecification } from '@vitest/runner'\nimport type { OTELCarrier } from '../utils/traces'\nimport type { TestExecutionMethod } from './worker'\n\nexport interface BrowserTesterOptions {\n  method: TestExecutionMethod\n  files: FileSpecification[]\n  providedContext: string\n  otelCarrier?: OTELCarrier\n}\n"
  },
  {
    "path": "packages/vitest/src/types/environment.ts",
    "content": "import type { Awaitable } from '@vitest/utils'\n\nexport interface EnvironmentReturn {\n  teardown: (global: any) => Awaitable<void>\n}\n\nexport interface VmEnvironmentReturn {\n  getVmContext: () => { [key: string]: any }\n  teardown: () => Awaitable<void>\n}\n\nexport interface Environment {\n  name: string\n  /**\n   * @deprecated use `viteEnvironment` instead. Uses `name` by default\n   */\n  transformMode?: 'web' | 'ssr'\n  /**\n   * Environment initiated by the Vite server. It is usually available\n   * as `vite.server.environments.${name}`.\n   *\n   * By default, fallbacks to `name`.\n   */\n  viteEnvironment?: 'client' | 'ssr' | ({} & string)\n  setupVM?: (options: Record<string, any>) => Awaitable<VmEnvironmentReturn>\n  setup: (\n    global: any,\n    options: Record<string, any>,\n  ) => Awaitable<EnvironmentReturn>\n}\n\nexport interface ResolvedTestEnvironment {\n  environment: Environment\n  options: Record<string, any> | null\n}\n"
  },
  {
    "path": "packages/vitest/src/types/general.ts",
    "content": "export type { ParsedStack, TestError } from '@vitest/utils'\n\nexport type ArgumentsType<T> = T extends (...args: infer U) => any ? U : never\n\nexport interface AfterSuiteRunMeta {\n  coverage?: unknown\n  testFiles: string[]\n  environment: string\n  projectName?: string\n}\n\nexport interface UserConsoleLog {\n  content: string\n  origin?: string\n  browser?: boolean\n  type: 'stdout' | 'stderr'\n  taskId?: string\n  time: number\n  size: number\n}\n\nexport interface ModuleGraphData {\n  graph: Record<string, string[]>\n  externalized: string[]\n  inlined: string[]\n}\n\nexport interface ProvidedContext {}\n\nexport interface ResolveFunctionResult {\n  id: string\n  file: string\n  url: string\n}\n\nexport interface FetchCachedFileSystemResult {\n  cached: true\n  tmp: string\n  id: string\n  file: string | null\n  url: string\n  invalidate: boolean\n}\n\n// These need to be compatible with Tinyrainbow's bg-colors, and CSS's background-color\nexport type LabelColor = 'black' | 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white'\n\nexport interface AsyncLeak {\n  filename: string\n  projectName: string\n  stack: string\n  type: string\n}\n"
  },
  {
    "path": "packages/vitest/src/types/global.ts",
    "content": "import type { ExpectStatic, PromisifyAssertion, Tester } from '@vitest/expect'\nimport type { Plugin as PrettyFormatPlugin } from '@vitest/pretty-format'\nimport type { SnapshotState } from '@vitest/snapshot'\nimport type { BenchmarkResult } from '../runtime/types/benchmark'\nimport type { UserConsoleLog } from './general'\n\ninterface SnapshotMatcher<T> {\n  <U extends { [P in keyof T]: any }>(\n    snapshot: Partial<U>,\n    hint?: string\n  ): void\n  (hint?: string): void\n}\n\ninterface InlineSnapshotMatcher<T> {\n  <U extends { [P in keyof T]: any }>(\n    properties: Partial<U>,\n    snapshot?: string,\n    hint?: string\n  ): void\n  (hint?: string): void\n}\n\ndeclare module '@vitest/expect' {\n  interface MatcherState {\n    environment: string\n    snapshotState: SnapshotState\n  }\n\n  interface ExpectPollOptions {\n    interval?: number\n    timeout?: number\n    message?: string\n  }\n\n  interface ExpectStatic {\n    assert: Chai.AssertStatic\n    unreachable: (message?: string) => never\n    soft: <T>(actual: T, message?: string) => Assertion<T>\n    poll: <T>(\n      actual: () => T,\n      options?: ExpectPollOptions,\n    ) => PromisifyAssertion<Awaited<T>>\n    addEqualityTesters: (testers: Array<Tester>) => void\n    assertions: (expected: number) => void\n    hasAssertions: () => void\n    addSnapshotSerializer: (plugin: PrettyFormatPlugin) => void\n  }\n\n  interface Assertion<T> {\n    // Snapshots are extended in @vitest/snapshot and are not part of @vitest/expect\n    matchSnapshot: SnapshotMatcher<T>\n    toMatchSnapshot: SnapshotMatcher<T>\n    toMatchInlineSnapshot: InlineSnapshotMatcher<T>\n\n    /**\n     * Checks that an error thrown by a function matches a previously recorded snapshot.\n     *\n     * @param hint - Optional custom error message.\n     *\n     * @example\n     * expect(functionWithError).toThrowErrorMatchingSnapshot();\n     */\n    toThrowErrorMatchingSnapshot: (hint?: string) => void\n\n    /**\n     * Checks that an error thrown by a function matches an inline snapshot within the test file.\n     * Useful for keeping snapshots close to the test code.\n     *\n     * @param snapshot - Optional inline snapshot string to match.\n     * @param hint - Optional custom error message.\n     *\n     * @example\n     * const throwError = () => { throw new Error('Error occurred') };\n     * expect(throwError).toThrowErrorMatchingInlineSnapshot(`\"Error occurred\"`);\n     */\n    toThrowErrorMatchingInlineSnapshot: (\n      snapshot?: string,\n      hint?: string,\n    ) => void\n\n    /**\n     * Compares the received value to a snapshot saved in a specified file.\n     * Useful for cases where snapshot content is large or needs to be shared across tests.\n     *\n     * @param filepath - Path to the snapshot file.\n     * @param hint - Optional custom error message.\n     *\n     * @example\n     * await expect(largeData).toMatchFileSnapshot('path/to/snapshot.json');\n     */\n    toMatchFileSnapshot: (filepath: string, hint?: string) => Promise<void>\n  }\n}\n\ndeclare module '@vitest/runner' {\n  interface TestContext {\n    /**\n     * `expect` instance bound to the current test.\n     *\n     * This API is useful for running snapshot tests concurrently because global expect cannot track them.\n     */\n    readonly expect: ExpectStatic\n    /** @internal */\n    _local: boolean\n  }\n\n  interface TaskMeta {\n    typecheck?: boolean\n    benchmark?: boolean\n  }\n\n  interface File {\n    prepareDuration?: number\n    environmentLoad?: number\n  }\n\n  interface TaskBase {\n    logs?: UserConsoleLog[]\n  }\n\n  interface TaskResult {\n    benchmark?: BenchmarkResult\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/types/happy-dom-options.ts",
    "content": "import type { happyDomTypes } from 'vitest/optional-types.js'\n\nexport type HappyDOMOptions = Omit<\n  NonNullable<ConstructorParameters<typeof happyDomTypes.Window>[0]>,\n  'console'\n>\n"
  },
  {
    "path": "packages/vitest/src/types/jsdom-options.ts",
    "content": "import type { jsdomTypes } from 'vitest/optional-types.js'\n\nexport type JSDOMOptions = ConstructorOptionsOverride & Omit<jsdomTypes.ConstructorOptions, keyof ConstructorOptionsOverride>\n\ninterface ConstructorOptionsOverride {\n  /**\n   * The html content for the test.\n   *\n   * @default '<!DOCTYPE html>'\n   */\n  html?: string | ArrayBufferLike\n  /**\n   * userAgent affects the value read from navigator.userAgent, as well as the User-Agent header sent while fetching subresources.\n   *\n   * @default `Mozilla/5.0 (${process.platform}) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/${jsdomVersion}`\n   */\n  userAgent?: string\n  /**\n   * url sets the value returned by window.location, document.URL, and document.documentURI,\n   * and affects things like resolution of relative URLs within the document\n   * and the same-origin restrictions and referrer used while fetching subresources.\n   *\n   * @default 'http://localhost:3000'.\n   */\n  url?: string\n  /**\n   * Enable console?\n   *\n   * @default false\n   */\n  console?: boolean\n  /**\n   * jsdom does not have the capability to render visual content, and will act like a headless browser by default.\n   * It provides hints to web pages through APIs such as document.hidden that their content is not visible.\n   *\n   * When the `pretendToBeVisual` option is set to `true`, jsdom will pretend that it is rendering and displaying\n   * content.\n   *\n   * @default true\n   */\n  pretendToBeVisual?: boolean\n  /**\n   * Enable CookieJar\n   *\n   * @default false\n   */\n  cookieJar?: boolean\n  resources?: 'usable'\n}\n"
  },
  {
    "path": "packages/vitest/src/types/mocker.ts",
    "content": "import type { MockedModuleType, ModuleMockFactory } from '@vitest/mocker'\n\nexport type {\n  ModuleMockFactory as MockFactory,\n  ModuleMockFactoryWithHelper as MockFactoryWithHelper,\n  ModuleMockOptions as MockOptions,\n} from '@vitest/mocker'\n\nexport interface PendingSuiteMock {\n  id: string\n  importer: string\n  action: 'mock' | 'unmock'\n  type?: MockedModuleType\n  factory?: ModuleMockFactory\n}\n"
  },
  {
    "path": "packages/vitest/src/types/module-locations.ts",
    "content": "export interface ModuleDefinitionLocation {\n  line: number\n  column: number\n}\n\nexport interface SourceModuleLocations {\n  modules: ModuleDefinitionDiagnostic[]\n  untracked: ModuleDefinitionDiagnostic[]\n}\n\nexport interface ModuleDefinitionDiagnostic {\n  start: ModuleDefinitionLocation\n  end: ModuleDefinitionLocation\n  startIndex: number\n  endIndex: number\n  rawUrl: string\n  resolvedUrl: string\n  resolvedId: string\n}\n\nexport interface ModuleDefinitionDurationsDiagnostic extends ModuleDefinitionDiagnostic {\n  selfTime: number\n  totalTime: number\n  transformTime?: number\n  external?: boolean\n  importer?: string\n}\n\nexport interface UntrackedModuleDefinitionDiagnostic {\n  url: string\n  resolvedId: string\n  resolvedUrl: string\n  selfTime: number\n  totalTime: number\n  transformTime?: number\n  external?: boolean\n  importer?: string\n}\n\nexport interface SourceModuleDiagnostic {\n  modules: ModuleDefinitionDurationsDiagnostic[]\n  untrackedModules: UntrackedModuleDefinitionDiagnostic[]\n}\n"
  },
  {
    "path": "packages/vitest/src/types/rpc.ts",
    "content": "import type { CancelReason, File, TaskEventPack, TaskResultPack, TestArtifact } from '@vitest/runner'\nimport type { SnapshotResult } from '@vitest/snapshot'\nimport type { FetchFunctionOptions, FetchResult } from 'vite/module-runner'\nimport type { OTELCarrier } from '../utils/traces'\nimport type { AfterSuiteRunMeta, AsyncLeak, FetchCachedFileSystemResult, ResolveFunctionResult, UserConsoleLog } from './general'\n\nexport interface RuntimeRPC {\n  fetch: (\n    id: string,\n    importer: string | undefined,\n    environment: string,\n    options?: FetchFunctionOptions,\n    otelCarrier?: OTELCarrier,\n  ) => Promise<FetchResult | FetchCachedFileSystemResult>\n  resolve: (id: string, importer: string | undefined, environment: string) => Promise<ResolveFunctionResult | null>\n  transform: (id: string) => Promise<{ code?: string }>\n\n  onUserConsoleLog: (log: UserConsoleLog) => void\n  onUnhandledError: (err: unknown, type: string) => void\n  onAsyncLeaks: (leak: AsyncLeak[]) => void\n  onQueued: (file: File) => void\n  onCollected: (files: File[]) => Promise<void>\n  onAfterSuiteRun: (meta: AfterSuiteRunMeta) => void\n  onTaskArtifactRecord: <Artifact extends TestArtifact>(testId: string, artifact: Artifact) => Promise<Artifact>\n  onTaskUpdate: (pack: TaskResultPack[], events: TaskEventPack[]) => Promise<void>\n  onCancel: (reason: CancelReason) => void\n  getCountOfFailedTests: () => number\n\n  snapshotSaved: (snapshot: SnapshotResult) => void\n  resolveSnapshotPath: (testPath: string) => string\n\n  ensureModuleGraphEntry: (id: string, importer: string) => void\n}\n\nexport interface RunnerRPC {\n  onCancel: (reason: CancelReason) => void\n}\n"
  },
  {
    "path": "packages/vitest/src/types/ui.ts",
    "content": "export interface BrowserUI {\n  setCurrentFileId: (fileId: string) => void\n  setIframeViewport: (width: number, height: number) => Promise<void>\n}\n"
  },
  {
    "path": "packages/vitest/src/types/worker.ts",
    "content": "import type { CancelReason, FileSpecification, Task } from '@vitest/runner'\nimport type { BirpcReturn } from 'birpc'\nimport type { EvaluatedModules } from 'vite/module-runner'\nimport type { SerializedConfig } from '../runtime/config'\nimport type { Traces } from '../utils/traces'\nimport type { Environment } from './environment'\nimport type { RunnerRPC, RuntimeRPC } from './rpc'\n\nexport type WorkerRPC = BirpcReturn<RuntimeRPC, RunnerRPC>\n\nexport interface ContextTestEnvironment {\n  name: string\n  options: Record<string, any> | null\n}\n\nexport interface WorkerTestEnvironment {\n  name: string\n  options: Record<string, any> | null\n}\n\nexport type TestExecutionMethod = 'run' | 'collect'\n\nexport interface WorkerExecuteContext {\n  files: FileSpecification[]\n  providedContext: Record<string, any>\n  invalidates?: string[]\n  environment: ContextTestEnvironment\n\n  /** Exposed to test runner as `VITEST_WORKER_ID`. Value is unique per each isolated worker. */\n  workerId: number\n}\n\nexport interface ContextRPC {\n  pool: string\n  config: SerializedConfig\n  projectName: string\n  environment: WorkerTestEnvironment\n  rpc: WorkerRPC\n  files: FileSpecification[]\n  providedContext: Record<string, any>\n  invalidates?: string[]\n\n  /** Exposed to test runner as `VITEST_WORKER_ID`. Value is unique per each isolated worker. */\n  workerId: number\n}\n\nexport interface WorkerSetupContext {\n  environment: WorkerTestEnvironment\n  pool: string\n  config: SerializedConfig\n  projectName: string\n  rpc: WorkerRPC\n  /**\n   * @internal\n   */\n  traces: Traces\n}\n\nexport interface WorkerGlobalState {\n  ctx: ContextRPC\n  config: SerializedConfig\n  rpc: WorkerRPC\n  current?: Task\n  filepath?: string\n  metaEnv: {\n    [key: string]: any\n    BASE_URL: string\n    MODE: string\n    DEV: boolean\n    PROD: boolean\n    SSR: boolean\n  }\n  environment: Environment\n  evaluatedModules: EvaluatedModules\n  resolvingModules: Set<string>\n  moduleExecutionInfo: Map<string, any>\n  onCancel: (listener: (reason: CancelReason) => unknown) => void\n  onCleanup: (listener: () => unknown) => void\n  providedContext: Record<string, any>\n  durations: {\n    environment: number\n    prepare: number\n  }\n  onFilterStackTrace?: (trace: string) => string\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/base.ts",
    "content": "import type { ModuleDefinitionLocation } from '../types/module-locations'\n\nexport { getCallLastIndex, nanoid, notNullish } from '@vitest/utils/helpers'\n\nexport function groupBy<T, K extends string | number | symbol>(\n  collection: T[],\n  iteratee: (item: T) => K,\n): Record<K, T[]> {\n  return collection.reduce((acc, item) => {\n    const key = iteratee(item)\n    acc[key] ||= []\n    acc[key].push(item)\n    return acc\n  }, {} as Record<K, T[]>)\n}\n\nexport function stdout(): NodeJS.WriteStream {\n  // @ts-expect-error Node.js maps process.stdout to console._stdout\n  // eslint-disable-next-line no-console\n  return console._stdout || process.stdout\n}\n\nexport function escapeRegExp(s: string): string {\n  // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping\n  return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') // $& means the whole matched string\n}\n\nexport function wildcardPatternToRegExp(pattern: string): RegExp {\n  const negated = pattern[0] === '!'\n\n  if (negated) {\n    pattern = pattern.slice(1)\n  }\n\n  let regexp = `${pattern.split('*').map(escapeRegExp).join('.*')}$`\n\n  if (negated) {\n    regexp = `(?!${regexp})`\n  }\n\n  return new RegExp(`^${regexp}`, 'i')\n}\n\nexport function createIndexLocationsMap(source: string): Map<number, ModuleDefinitionLocation> {\n  const map = new Map<number, ModuleDefinitionLocation>()\n  let index = 0\n  let line = 1\n  let column = 1\n  for (const char of source) {\n    map.set(index++, { line, column })\n    if (char === '\\n' || char === '\\r\\n') {\n      line++\n      column = 0\n    }\n    else {\n      column++\n    }\n  }\n  return map\n}\n\nexport function createLocationsIndexMap(source: string): Map<string, number> {\n  const map = new Map<string, number>()\n  let index = 0\n  let line = 1\n  let column = 1\n  for (const char of source) {\n    map.set(`${line}:${column}`, index++)\n    if (char === '\\n' || char === '\\r\\n') {\n      line++\n      column = 0\n    }\n    else {\n      column++\n    }\n  }\n  return map\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/colors.ts",
    "content": "import type { TokenColors } from 'tinyhighlight'\nimport type { Colors } from 'tinyrainbow'\nimport { extname } from 'pathe'\nimport { highlight } from 'tinyhighlight'\nimport c from 'tinyrainbow'\n\nconst HIGHLIGHT_SUPPORTED_EXTS = new Set(\n  ['js', 'ts'].flatMap(lang => [\n    `.${lang}`,\n    `.m${lang}`,\n    `.c${lang}`,\n    `.${lang}x`,\n    `.m${lang}x`,\n    `.c${lang}x`,\n  ]),\n)\n\nexport function highlightCode(id: string, source: string): string {\n  const ext = extname(id)\n  if (!HIGHLIGHT_SUPPORTED_EXTS.has(ext)) {\n    return source\n  }\n  const isJsx = ext.endsWith('x')\n  return highlight(source, { jsx: isJsx, colors: getDefs(c) })\n}\n\nfunction getDefs(c: Colors): TokenColors {\n  const Invalid = (text: string) => c.white(c.bgRed(c.bold(text)))\n  return {\n    Keyword: c.magenta,\n    IdentifierCapitalized: c.yellow,\n    Punctuator: c.yellow,\n    StringLiteral: c.green,\n    NoSubstitutionTemplate: c.green,\n    MultiLineComment: c.gray,\n    SingleLineComment: c.gray,\n    RegularExpressionLiteral: c.cyan,\n    NumericLiteral: c.blue,\n    TemplateHead: text =>\n      c.green(text.slice(0, text.length - 2)) + c.cyan(text.slice(-2)),\n    TemplateTail: text => c.cyan(text.slice(0, 1)) + c.green(text.slice(1)),\n    TemplateMiddle: text =>\n      c.cyan(text.slice(0, 1))\n      + c.green(text.slice(1, text.length - 2))\n      + c.cyan(text.slice(-2)),\n    IdentifierCallable: c.blue,\n    PrivateIdentifierCallable: text => `#${c.blue(text.slice(1))}`,\n    Invalid,\n\n    JSXString: c.green,\n    JSXIdentifier: c.yellow,\n    JSXInvalid: Invalid,\n    JSXPunctuator: c.yellow,\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/config-helpers.ts",
    "content": "import type {\n  BenchmarkBuiltinReporters,\n  BuiltinReporters,\n} from '../node/reporters'\n\ninterface PotentialConfig {\n  outputFile?: string | Partial<Record<string, string>>\n}\n\nexport function getOutputFile(\n  config: PotentialConfig | undefined,\n  reporter: BuiltinReporters | BenchmarkBuiltinReporters | 'html',\n): string | undefined {\n  if (!config?.outputFile) {\n    return\n  }\n\n  if (typeof config.outputFile === 'string') {\n    return config.outputFile\n  }\n\n  return config.outputFile[reporter]\n}\n\nexport function createDefinesScript(define: Record<string, any> | undefined): string {\n  if (!define) {\n    return ''\n  }\n  const serializedDefine = serializeDefine(define)\n  if (serializedDefine === '{}') {\n    return ''\n  }\n  return `\nconst defines = ${serializeDefine(define)}\nObject.keys(defines).forEach((key) => {\n  const segments = key.split('.')\n  let target = globalThis\n  for (let i = 0; i < segments.length; i++) {\n    const segment = segments[i]\n    if (i === segments.length - 1) {\n      target[segment] = defines[key]\n    } else {\n      target = target[segment] || (target[segment] = {})\n    }\n  }\n})\n  `\n}\n\n/**\n * Like `JSON.stringify` but keeps raw string values as a literal\n * in the generated code. For example: `\"window\"` would refer to\n * the global `window` object directly.\n */\nfunction serializeDefine(define: Record<string, any>): string {\n  const userDefine: Record<string, any> = {}\n  for (const key in define) {\n    // vitest sets this to avoid vite:client-inject plugin\n    if (key === 'process.env.NODE_ENV' && define[key] === 'process.env.NODE_ENV') {\n      continue\n    }\n    // import.meta.env.* is handled in `importAnalysis` plugin\n    if (!key.startsWith('import.meta.env.')) {\n      userDefine[key] = define[key]\n    }\n  }\n  let res = `{`\n  const keys = Object.keys(userDefine).sort()\n  for (let i = 0; i < keys.length; i++) {\n    const key = keys[i]\n    const val = userDefine[key]\n    res += `${JSON.stringify(key)}: ${handleDefineValue(val)}`\n    if (i !== keys.length - 1) {\n      res += `, `\n    }\n  }\n  return `${res}}`\n}\n\nfunction handleDefineValue(value: any): string {\n  if (typeof value === 'undefined') {\n    return 'undefined'\n  }\n  if (typeof value === 'string') {\n    return value\n  }\n  return JSON.stringify(value)\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/coverage.ts",
    "content": "import type { SerializedCoverageConfig } from '../runtime/config'\n\nexport interface RuntimeCoverageModuleLoader {\n  import: (id: string) => Promise<{ default: RuntimeCoverageProviderModule }>\n  isBrowser?: boolean\n  moduleExecutionInfo?: Map<string, { startOffset: number }>\n}\n\nexport interface RuntimeCoverageProviderModule {\n  /**\n   * Factory for creating a new coverage provider\n   */\n  getProvider: () => any // not needed for runtime\n\n  /**\n   * Executed before tests are run in the worker thread.\n   */\n  startCoverage?: (runtimeOptions: { isolate: boolean }) => unknown | Promise<unknown>\n\n  /**\n   * Executed on after each run in the worker thread. Possible to return a payload passed to the provider\n   */\n  takeCoverage?: (runtimeOptions?: { moduleExecutionInfo?: Map<string, { startOffset: number }> }) => unknown | Promise<unknown>\n\n  /**\n   * Executed after all tests have been run in the worker thread.\n   */\n  stopCoverage?: (runtimeOptions: { isolate: boolean }) => unknown | Promise<unknown>\n}\n\nexport const CoverageProviderMap: Record<string, string> = {\n  v8: '@vitest/coverage-v8',\n  istanbul: '@vitest/coverage-istanbul',\n}\n\nexport async function resolveCoverageProviderModule(\n  options: SerializedCoverageConfig | undefined,\n  loader: RuntimeCoverageModuleLoader,\n): Promise<RuntimeCoverageProviderModule | null> {\n  if (!options?.enabled || !options.provider) {\n    return null\n  }\n\n  const provider = options.provider\n\n  if (provider === 'v8' || provider === 'istanbul') {\n    let builtInModule = CoverageProviderMap[provider]\n\n    if (provider === 'v8' && loader.isBrowser) {\n      builtInModule += '/browser'\n    }\n\n    const { default: coverageModule } = await loader.import(builtInModule)\n\n    if (!coverageModule) {\n      throw new Error(\n        `Failed to load ${CoverageProviderMap[provider]}. Default export is missing.`,\n      )\n    }\n\n    return coverageModule\n  }\n\n  let customProviderModule\n\n  try {\n    customProviderModule = await loader.import(options.customProviderModule!)\n  }\n  catch (error) {\n    throw new Error(\n      `Failed to load custom CoverageProviderModule from ${options.customProviderModule}`,\n      { cause: error },\n    )\n  }\n\n  if (customProviderModule.default == null) {\n    throw new Error(\n      `Custom CoverageProviderModule loaded from ${options.customProviderModule} was not the default export`,\n    )\n  }\n\n  return customProviderModule.default\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/debugger.ts",
    "content": "import type { Debugger } from 'obug'\nimport { createDebug } from 'obug'\n\nexport function createDebugger(namespace: `vitest:${string}`): Debugger | undefined {\n  const debug = createDebug(namespace)\n  if (debug.enabled) {\n    return debug\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/env.ts",
    "content": "import { isCI } from 'std-env'\n\nexport const isNode: boolean\n  = typeof process < 'u'\n    && typeof process.stdout < 'u'\n    && !process.versions?.deno\n    && !globalThis.window\nexport const isDeno: boolean\n  = typeof process < 'u'\n    && typeof process.stdout < 'u'\n    && process.versions?.deno !== undefined\nexport const isWindows: boolean = (isNode || isDeno) && process.platform === 'win32'\nexport const isBrowser: boolean = typeof window !== 'undefined'\nexport const isTTY: boolean = ((isNode || isDeno) && process.stdout?.isTTY && !isCI)\nexport { isAgent, isCI, provider as stdProvider } from 'std-env'\n"
  },
  {
    "path": "packages/vitest/src/utils/environments.ts",
    "content": "import type { DevEnvironment } from 'vite'\nimport type { TestProject } from '../node/project'\n\nexport function getTestFileEnvironment(project: TestProject, testFile: string, browser = false): DevEnvironment | undefined {\n  if (browser) {\n    return project.browser?.vite.environments.client\n  }\n  else {\n    for (const name in project.vite.environments) {\n      const env = project.vite.environments[name]\n      if (env.moduleGraph.getModuleById(testFile)) {\n        return env\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/graph.ts",
    "content": "import type { EnvironmentModuleNode } from 'vite'\nimport type { Vitest } from '../node/core'\nimport type { ModuleGraphData } from '../types/general'\nimport { getTestFileEnvironment } from './environments'\n\nexport async function getModuleGraph(\n  ctx: Vitest,\n  projectName: string,\n  testFilePath: string,\n  browser = false,\n): Promise<ModuleGraphData> {\n  const graph: Record<string, string[]> = {}\n  const externalized = new Set<string>()\n  const inlined = new Set<string>()\n\n  const project = ctx.getProjectByName(projectName)\n\n  const environment = project.config.experimental.viteModuleRunner === false\n    ? project.vite.environments.__vitest__\n    : getTestFileEnvironment(project, testFilePath, browser)\n\n  if (!environment) {\n    throw new Error(`Cannot find environment for ${testFilePath}`)\n  }\n  const seen = new Map<EnvironmentModuleNode, string>()\n\n  function get(mod?: EnvironmentModuleNode) {\n    if (!mod || !mod.id) {\n      return\n    }\n    if (\n      mod.id === '\\0vitest/browser'\n      // the export helper is injected in all vue files\n      // so the module graph becomes too bouncy\n      || mod.id.includes('plugin-vue:export-helper')\n    ) {\n      return\n    }\n    if (seen.has(mod)) {\n      return seen.get(mod)\n    }\n    const id = clearId(mod.id)\n    seen.set(mod, id)\n    if (id.startsWith('__vite-browser-external:')) {\n      const external = id.slice('__vite-browser-external:'.length)\n      externalized.add(external)\n      return external\n    }\n    const external = project._resolver.wasExternalized(id)\n    if (typeof external === 'string') {\n      externalized.add(external)\n      return external\n    }\n    if (browser && mod.file?.includes(project.browser!.vite.config.cacheDir)) {\n      externalized.add(mod.id)\n      return id\n    }\n    inlined.add(id)\n    const mods = Array.from(mod.importedModules).filter(\n      i => i.id && !i.id.includes('/vitest/dist/'),\n    )\n    graph[id] = mods.map(m => get(m)).filter(\n      Boolean,\n    ) as string[]\n    return id\n  }\n\n  get(environment.moduleGraph.getModuleById(testFilePath))\n  project.config.setupFiles.forEach((setupFile) => {\n    get(environment.moduleGraph.getModuleById(setupFile))\n  })\n\n  return {\n    graph,\n    externalized: Array.from(externalized),\n    inlined: Array.from(inlined),\n  }\n}\n\nfunction clearId(id?: string | null) {\n  return id?.replace(/\\?v=\\w+$/, '') || ''\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/memory-limit.ts",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of facebook/jest GitHub project tree.\n */\n\nimport type { ResolvedConfig } from '../node/types/config'\nimport * as nodeos from 'node:os'\n\nfunction getDefaultThreadsCount(config: Pick<ResolvedConfig, 'watch'>) {\n  const numCpus\n    = typeof nodeos.availableParallelism === 'function'\n      ? nodeos.availableParallelism()\n      : nodeos.cpus().length\n\n  return config.watch\n    ? Math.max(Math.floor(numCpus / 2), 1)\n    : Math.max(numCpus - 1, 1)\n}\n\nexport function getWorkerMemoryLimit(config: Pick<ResolvedConfig, 'vmMemoryLimit' | 'maxWorkers' | 'watch'>): string | number {\n  if (config.vmMemoryLimit) {\n    return config.vmMemoryLimit\n  }\n\n  const workers = config.maxWorkers ?? getDefaultThreadsCount(config)\n\n  return 1 / workers\n}\n\n/**\n * Converts a string representing an amount of memory to bytes.\n *\n * @param input The value to convert to bytes.\n * @param percentageReference The reference value to use when a '%' value is supplied.\n */\nexport function stringToBytes(\n  input: string | number | null | undefined,\n  percentageReference?: number,\n): number | null | undefined {\n  if (input === null || input === undefined) {\n    return input\n  }\n\n  if (typeof input === 'string') {\n    if (Number.isNaN(Number.parseFloat(input.slice(-1)))) {\n      let [, numericString, trailingChars]\n        // eslint-disable-next-line regexp/no-super-linear-backtracking\n        = input.match(/(.*?)([^0-9.-]+)$/) || []\n\n      if (trailingChars && numericString) {\n        const numericValue = Number.parseFloat(numericString)\n        trailingChars = trailingChars.toLowerCase()\n\n        switch (trailingChars) {\n          case '%':\n            input = numericValue / 100\n            break\n          case 'kb':\n          case 'k':\n            return numericValue * 1000\n          case 'kib':\n            return numericValue * 1024\n          case 'mb':\n          case 'm':\n            return numericValue * 1000 * 1000\n          case 'mib':\n            return numericValue * 1024 * 1024\n          case 'gb':\n          case 'g':\n            return numericValue * 1000 * 1000 * 1000\n          case 'gib':\n            return numericValue * 1024 * 1024 * 1024\n        }\n      }\n\n      // It ends in some kind of char so we need to do some parsing\n    }\n    else {\n      input = Number.parseFloat(input)\n    }\n  }\n\n  if (typeof input === 'number') {\n    if (input <= 1 && input > 0) {\n      if (percentageReference) {\n        return Math.floor(input * percentageReference)\n      }\n      else {\n        throw new Error(\n          'For a percentage based memory limit a percentageReference must be supplied',\n        )\n      }\n    }\n    else if (input > 1) {\n      return Math.floor(input)\n    }\n    else {\n      throw new Error('Unexpected numerical input for \"memoryLimit\"')\n    }\n  }\n\n  return null\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/modules.ts",
    "content": "// copied from vite\n// https://github.com/vitejs/vite/blob/814120f2ad387ca3d1e16c7dd403b04ca4b97f75/packages/vite/src/node/utils.ts#L106\nimport { builtinModules } from 'node:module'\n\n// Supported by Node, Deno, Bun\nconst NODE_BUILTIN_NAMESPACE = 'node:'\n// Supported by Deno\nconst NPM_BUILTIN_NAMESPACE = 'npm:'\n// Supported by Bun\nconst BUN_BUILTIN_NAMESPACE = 'bun:'\n// Some runtimes like Bun injects namespaced modules here, which is not a node builtin\nconst nodeBuiltins = builtinModules.filter(id => !id.includes(':'))\n\nconst { bun: isBun, deno: isDeno } = process.versions\n\n// TODO: Use `isBuiltin` from `node:module`, but Deno doesn't support it\nexport function isBuiltin(id: string): boolean {\n  if (isDeno && id.startsWith(NPM_BUILTIN_NAMESPACE)) {\n    return true\n  }\n  if (isBun && id.startsWith(BUN_BUILTIN_NAMESPACE)) {\n    return true\n  }\n  return isNodeBuiltin(id)\n}\n\nexport function isNodeBuiltin(id: string): boolean {\n  if (id.startsWith(NODE_BUILTIN_NAMESPACE)) {\n    return true\n  }\n  return nodeBuiltins.includes(id)\n}\n\nconst browserExternalId = '__vite-browser-external'\nconst browserExternalLength = browserExternalId.length + 1 // 1 is \":\"\n\nexport function isBrowserExternal(id: string): boolean {\n  return id.startsWith(browserExternalId)\n}\n\nexport function toBuiltin(id: string): string {\n  if (id.startsWith(browserExternalId)) {\n    id = id.slice(browserExternalLength)\n  }\n  if (\n    id.startsWith(NPM_BUILTIN_NAMESPACE)\n    || id.startsWith(BUN_BUILTIN_NAMESPACE)\n    || id.startsWith(NODE_BUILTIN_NAMESPACE)\n  ) {\n    return id\n  }\n  if (isDeno || isBun) {\n    return id\n  }\n  return `node:${id}`\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/nativeModuleRunner.ts",
    "content": "import type { TestModuleMocker } from '@vitest/mocker'\nimport { pathToFileURL } from 'node:url'\nimport { resolveModule } from 'local-pkg'\nimport { resolve } from 'pathe'\nimport { ModuleRunner } from 'vite/module-runner'\n\nexport class NativeModuleRunner extends ModuleRunner {\n  /**\n   * @internal\n   */\n  public mocker?: TestModuleMocker\n\n  constructor(private root: string, mocker?: TestModuleMocker) {\n    super({\n      hmr: false,\n      sourcemapInterceptor: false,\n      transport: {\n        invoke() {\n          throw new Error('Unexpected `invoke`')\n        },\n      },\n    })\n    this.mocker = mocker\n    if (mocker) {\n      Object.defineProperty(globalThis, '__vitest_mocker__', {\n        configurable: true,\n        writable: true,\n        value: mocker,\n      })\n    }\n  }\n\n  override async import(moduleId: string): Promise<any> {\n    const path = resolveModule(moduleId, { paths: [this.root] })\n      ?? resolve(this.root, moduleId)\n\n    // resolveModule doesn't keep the query params, so we need to add them back\n    let queryParams = ''\n    if (moduleId.includes('?') && !path.includes('?')) {\n      queryParams = moduleId.slice(moduleId.indexOf('?'))\n    }\n\n    return import(pathToFileURL(path + queryParams).toString())\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/serialization.ts",
    "content": "// Serialization support utils.\n\nfunction cloneByOwnProperties(value: any) {\n  // Clones the value's properties into a new Object. The simpler approach of\n  // Object.assign() won't work in the case that properties are not enumerable.\n  return Object.getOwnPropertyNames(value).reduce<Record<string, any>>(\n    (clone, prop) => {\n      clone[prop] = value[prop]\n      return clone\n    },\n    {},\n  )\n}\n\n/**\n * Replacer function for serialization methods such as JS.stringify() or\n * flatted.stringify().\n */\nexport function stringifyReplace(key: string, value: any): any {\n  if (value instanceof Error) {\n    const cloned = cloneByOwnProperties(value)\n    return {\n      name: value.name,\n      message: value.message,\n      stack: value.stack,\n      ...cloned,\n    }\n  }\n  else {\n    return value\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/source-map.ts",
    "content": "export {\n  lineSplitRE,\n  offsetToLineNumber,\n  positionToOffset,\n} from '@vitest/utils/offset'\nexport {\n  defaultStackIgnorePatterns,\n  parseErrorStacktrace,\n  parseSingleStack,\n  parseStacktrace,\n} from '@vitest/utils/source-map'\n"
  },
  {
    "path": "packages/vitest/src/utils/tasks.ts",
    "content": "import type { File, Suite, Task, TaskEventPack, TaskResultPack } from '@vitest/runner'\nimport type { Arrayable } from '@vitest/utils'\nimport { getTests } from '@vitest/runner/utils'\nimport { toArray } from '@vitest/utils/helpers'\n\nexport function hasBenchmark(suite: Arrayable<Suite>): boolean {\n  return toArray(suite).some(s =>\n    s?.tasks?.some(c => c.meta?.benchmark || hasBenchmark(c as Suite)),\n  )\n}\n\nexport function hasFailedSnapshot(suite: Arrayable<Task>): boolean {\n  return getTests(suite).some((s) => {\n    return s.result?.errors?.some(\n      e =>\n        typeof e?.message === 'string'\n        && e.message.match(/Snapshot .* mismatched/),\n    )\n  })\n}\n\nexport function convertTasksToEvents(file: File, onTask?: (task: Task) => void): {\n  packs: TaskResultPack[]\n  events: TaskEventPack[]\n} {\n  const packs: TaskResultPack[] = []\n  const events: TaskEventPack[] = []\n\n  function visit(suite: Suite | File) {\n    onTask?.(suite)\n\n    packs.push([suite.id, suite.result, suite.meta])\n    events.push([suite.id, 'suite-prepare', undefined])\n    suite.tasks.forEach((task) => {\n      if (task.type === 'suite') {\n        visit(task)\n      }\n      else {\n        onTask?.(task)\n        if (suite.mode !== 'skip' && suite.mode !== 'todo') {\n          packs.push([task.id, task.result, task.meta])\n          events.push([task.id, 'test-prepare', undefined])\n          task.annotations.forEach((annotation) => {\n            events.push([task.id, 'test-annotation', { annotation }])\n          })\n          task.artifacts.forEach((artifact) => {\n            events.push([task.id, 'test-artifact', { artifact }])\n          })\n          events.push([task.id, 'test-finished', undefined])\n        }\n      }\n    })\n    events.push([suite.id, 'suite-finished', undefined])\n  }\n\n  visit(file)\n\n  return { packs, events }\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/test-helpers.ts",
    "content": "import type { TestSpecification } from '../node/test-specification'\nimport type { EnvironmentOptions, VitestEnvironment } from '../node/types/config'\nimport type { ContextTestEnvironment } from '../types/worker'\nimport { promises as fs } from 'node:fs'\n\nexport async function getSpecificationsOptions(\n  specifications: Array<TestSpecification>,\n): Promise<{\n  environments: WeakMap<TestSpecification, ContextTestEnvironment>\n  tags: WeakMap<TestSpecification, string[]>\n}> {\n  const environments = new WeakMap<TestSpecification, ContextTestEnvironment>()\n  const cache = new Map<string, string>()\n  const tags = new WeakMap<TestSpecification, string[]>()\n  await Promise.all(\n    specifications.map(async (spec) => {\n      const { moduleId: filepath, project, pool } = spec\n      // browser pool handles its own environment\n      if (pool === 'browser') {\n        return\n      }\n\n      // reuse if projects have the same test files\n      let code = cache.get(filepath)\n      if (!code) {\n        code = await fs.readFile(filepath, 'utf-8').catch(() => '')\n        cache.set(filepath, code)\n      }\n\n      const {\n        env = project.config.environment || 'node',\n        envOptions,\n        tags: specTags = [],\n      } = detectCodeBlock(code)\n      tags.set(spec, specTags)\n\n      const envKey = env === 'happy-dom' ? 'happyDOM' : env\n      const environment: ContextTestEnvironment = {\n        name: env as VitestEnvironment,\n        options: envOptions\n          ? ({ [envKey]: envOptions } as EnvironmentOptions)\n          : null,\n      }\n      environments.set(spec, environment)\n    }),\n  )\n  return { environments, tags }\n}\n\nexport function detectCodeBlock(content: string): {\n  env?: string\n  envOptions?: Record<string, any>\n  tags: string[]\n} {\n  const env = content.match(/@(?:vitest|jest)-environment\\s+([\\w-]+)\\b/)?.[1]\n  let envOptionsJson = content.match(/@(?:vitest|jest)-environment-options\\s+(.+)/)?.[1]\n  if (envOptionsJson?.endsWith('*/')) {\n    // Trim closing Docblock characters the above regex might have captured\n    envOptionsJson = envOptionsJson.slice(0, -2)\n  }\n  const envOptions = JSON.parse(envOptionsJson || 'null')\n  const tags: string[] = []\n  let tagMatch: RegExpMatchArray | null\n  // eslint-disable-next-line no-cond-assign\n  while (tagMatch = content.match(/(\\/\\/|\\*)\\s*@module-tag\\s+([\\w\\-/]+)\\b/)) {\n    tags.push(tagMatch[2])\n    content = content.slice(tagMatch.index! + tagMatch[0].length)\n  }\n  return { env, envOptions, tags }\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/timers.ts",
    "content": "export { getSafeTimers } from '@vitest/utils/timers'\n"
  },
  {
    "path": "packages/vitest/src/utils/traces.ts",
    "content": "import type {\n  Context,\n  ContextAPI,\n  PropagationAPI,\n  Span,\n  SpanOptions,\n  SpanStatusCode,\n  TraceAPI,\n  Tracer,\n} from '@opentelemetry/api'\n\n// important: this module should not import types, it should only expose them\n// because it is used by browser, node and test types at the same time\n\nexport interface OTELCarrier {\n  traceparent?: string\n  tracestate?: string\n}\n\ninterface TracesOptions {\n  enabled: boolean\n  watchMode?: boolean\n  sdkPath?: string\n  tracerName?: string\n}\n\ninterface TracesSpanOptions extends SpanOptions {\n  context?: Context\n}\n\ninterface OTEL {\n  tracer: Tracer\n  trace: TraceAPI\n  context: ContextAPI\n  SpanStatusCode: typeof SpanStatusCode\n  propagation: PropagationAPI\n}\n\nexport class Traces {\n  /**\n   * otel stands for OpenTelemetry\n   */\n  #otel: OTEL | null = null\n  #sdk: { shutdown: () => Promise<void>; forceFlush?: () => Promise<void> } | null = null\n  #init: Promise<unknown> | null = null\n  #noopSpan = createNoopSpan()\n  #noopContext = createNoopContext()\n  #initStartTime = performance.now()\n  #initEndTime = 0\n  #initRecorded = false\n\n  constructor(options: TracesOptions) {\n    if (options.enabled) {\n      const apiInit = import('@opentelemetry/api').then((api) => {\n        const otel = {\n          tracer: api.trace.getTracer(options.tracerName || 'vitest'),\n          context: api.context,\n          propagation: api.propagation,\n          trace: api.trace,\n          SpanKind: api.SpanKind,\n          SpanStatusCode: api.SpanStatusCode,\n        }\n        this.#otel = otel\n      }).catch(() => {\n        throw new Error(`\"@opentelemetry/api\" is not installed locally. Make sure you have setup OpenTelemetry instrumentation: https://vitest.dev/guide/open-telemetry`)\n      })\n      const sdkInit = (options.sdkPath ? import(/* @vite-ignore */ options.sdkPath!) : Promise.resolve()).catch((cause) => {\n        throw new Error(`Failed to import custom OpenTelemetry SDK script (${options.sdkPath}): ${cause.message}`)\n      })\n      this.#init = Promise.all([sdkInit, apiInit]).then(([sdk]) => {\n        if (sdk != null) {\n          if (sdk.default != null && typeof sdk.default === 'object' && typeof sdk.default.shutdown === 'function') {\n            this.#sdk = sdk.default\n          }\n          else if (options.watchMode !== true && process.env.VITEST_MODE !== 'watch') {\n            console.warn(`OpenTelemetry instrumentation module (${options.sdkPath}) does not have a default export with a \"shutdown\" method. Vitest won't be able to ensure that all traces are processed in time. Try running Vitest in watch mode instead.`)\n          }\n        }\n      }).finally(() => {\n        this.#initEndTime = performance.now()\n        this.#init = null\n      })\n    }\n  }\n\n  public isEnabled(): boolean {\n    return !!this.#otel\n  }\n\n  /**\n   * @internal\n   */\n  async waitInit(): Promise<this> {\n    if (this.#init) {\n      await this.#init\n    }\n    return this\n  }\n\n  /**\n   * @internal\n   */\n  recordInitSpan(context: Context): void {\n    if (this.#initRecorded) {\n      return\n    }\n    this.#initRecorded = true\n    this\n      .startSpan('vitest.runtime.traces', { startTime: this.#initStartTime }, context)\n      .end(this.#initEndTime)\n  }\n\n  /**\n   * @internal\n   */\n  startContextSpan(name: string, currentContext?: Context): {\n    span: Span\n    context: Context\n  } {\n    if (!this.#otel) {\n      return {\n        span: this.#noopSpan,\n        context: this.#noopContext,\n      }\n    }\n\n    const activeContext = currentContext || this.#otel.context.active()\n    const span = this.#otel.tracer.startSpan(\n      name,\n      {},\n      activeContext,\n    )\n    const context = this.#otel.trace.setSpan(activeContext, span)\n    return {\n      span,\n      context,\n    }\n  }\n\n  /**\n   * @internal\n   */\n  getContextFromCarrier(carrier: OTELCarrier | undefined): Context {\n    if (!this.#otel) {\n      return this.#noopContext\n    }\n    const activeContext = this.#otel.context.active()\n    if (!carrier) {\n      return activeContext\n    }\n    return this.#otel.propagation.extract(activeContext, carrier)\n  }\n\n  /**\n   * @internal\n   */\n  getContextFromEnv(env: Record<string, unknown>): Context {\n    if (!this.#otel) {\n      return this.#noopContext\n    }\n    // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/env-carriers.md\n    // some tools sets only `TRACEPARENT` but not `TRACESTATE`\n    const carrier: OTELCarrier = {}\n    if (typeof env.TRACEPARENT === 'string') {\n      carrier.traceparent = env.TRACEPARENT\n    }\n    if (typeof env.TRACESTATE === 'string') {\n      carrier.tracestate = env.TRACESTATE\n    }\n    return this.getContextFromCarrier(carrier)\n  }\n\n  /**\n   * @internal\n   */\n  getContextCarrier(context?: Context): OTELCarrier | undefined {\n    if (!this.#otel) {\n      return undefined\n    }\n    const carrier = {}\n    this.#otel.propagation.inject(context || this.#otel.context.active(), carrier)\n    return carrier\n  }\n\n  #callActiveSpan<T>(span: Span, callback: (span: Span) => T): T {\n    const otel = this.#otel!\n    let result!: T\n    try {\n      result = callback(span)\n      if (result instanceof Promise) {\n        return result\n          .catch((error) => {\n            span.recordException({\n              name: error.name,\n              message: error.message,\n              stack: error.stack,\n            })\n            span.setStatus({\n              code: otel.SpanStatusCode.ERROR,\n            })\n            throw error\n          })\n          .finally(() => span.end()) as T\n      }\n      return result\n    }\n    catch (error) {\n      if (error instanceof Error) {\n        span.recordException({\n          name: error.name,\n          message: error.message,\n          stack: error.stack,\n        })\n        span.setStatus({\n          code: otel.SpanStatusCode.ERROR,\n        })\n      }\n      throw error\n    }\n    finally {\n      // end sync callbcak\n      if (!(result instanceof Promise)) {\n        span.end()\n      }\n    }\n  }\n\n  /**\n   * @internal\n   */\n  $<T>(name: string, fn: (span: Span) => T): T\n  /**\n   * @internal\n   */\n  $<T>(name: string, optionsOrFn: TracesSpanOptions, fn: (span: Span) => T): T\n  /**\n   * @internal\n   */\n  $<T>(name: string, optionsOrFn: TracesSpanOptions | ((span: Span) => T), fn?: (span: Span) => T): T {\n    const callback = typeof optionsOrFn === 'function' ? optionsOrFn : fn!\n    if (!this.#otel) {\n      return callback(this.#noopSpan)\n    }\n\n    const otel = this.#otel\n    const options = typeof optionsOrFn === 'function' ? {} : optionsOrFn\n    const context = options.context\n    if (context) {\n      return otel.tracer.startActiveSpan(\n        name,\n        options,\n        context,\n        span => this.#callActiveSpan(span, callback),\n      )\n    }\n    return otel.tracer.startActiveSpan(\n      name,\n      options,\n      span => this.#callActiveSpan(span, callback),\n    )\n  }\n\n  /**\n   * @internal\n   */\n  startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n    if (!this.#otel) {\n      return this.#noopSpan\n    }\n    const { tracer } = this.#otel\n    return tracer.startSpan(name, options, context)\n  }\n\n  // On browser mode, async context is not automatically propagated,\n  // so we manually bind the `$` calls to the provided context.\n  // TODO: this doesn't bind to user land's `@optelemetry/api` calls\n  /**\n   * @internal\n   */\n  bind(context: Context) {\n    if (!this.#otel) {\n      return\n    }\n    const original = (this.$ as any).__original ?? this.$\n    this.$ = this.#otel.context.bind(context, original)\n    ;(this.$ as any).__original = original\n  }\n\n  /**\n   * @internal\n   */\n  async finish(): Promise<void> {\n    await this.#sdk?.shutdown()\n  }\n\n  /**\n   * @internal\n   */\n  async flush(): Promise<void> {\n    await this.#sdk?.forceFlush?.()\n  }\n}\n\nfunction noopSpan(this: Span) {\n  return this\n}\n\nfunction createNoopSpan(): Span {\n  return {\n    setAttribute: noopSpan,\n    setStatus: noopSpan,\n    addEvent: noopSpan,\n    addLink: noopSpan,\n    addLinks: noopSpan,\n    setAttributes: noopSpan,\n    updateName: noopSpan,\n    end: () => {},\n    isRecording: () => false,\n    recordException: noopSpan,\n    spanContext() {\n      return {\n        spanId: '',\n        traceFlags: 0,\n        traceId: '',\n      }\n    },\n  }\n}\n\nfunction noopContext(this: Context) {\n  return this\n}\n\nfunction createNoopContext(): Context {\n  return {\n    getValue: noopContext,\n    setValue: noopContext,\n    deleteValue: noopContext,\n  }\n}\n"
  },
  {
    "path": "packages/vitest/src/utils/workers.ts",
    "content": "import os from 'node:os'\n\nexport function getWorkersCountByPercentage(percent: string): number {\n  const maxWorkersCount = os.availableParallelism?.() ?? os.cpus().length\n  const workersCountByPercentage = Math.round((Number.parseInt(percent) / 100) * maxWorkersCount)\n\n  return Math.max(1, Math.min(maxWorkersCount, workersCountByPercentage))\n}\n"
  },
  {
    "path": "packages/vitest/suite.d.ts",
    "content": "export * from './dist/suite.js'\n"
  },
  {
    "path": "packages/vitest/suppress-warnings.cjs",
    "content": "// borrowed from tsx implementation:\n// https://github.com/esbuild-kit/tsx\n\nconst ignoreWarnings = new Set([\n  '--experimental-loader is an experimental feature. This feature could change at any time',\n  'Custom ESM Loaders is an experimental feature. This feature could change at any time',\n  'Custom ESM Loaders is an experimental feature and might change at any time',\n  'VM Modules is an experimental feature and might change at any time',\n  'VM Modules is an experimental feature. This feature could change at any time',\n  'stripTypeScriptTypes is an experimental feature and might change at any time',\n])\n\nconst { emit } = process\n\nprocess.emit = function (event, warning) {\n  if (event === 'warning' && ignoreWarnings.has(warning.message)) {\n    return\n  }\n\n  // eslint-disable-next-line prefer-rest-params\n  return Reflect.apply(emit, this, arguments)\n}\n"
  },
  {
    "path": "packages/vitest/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"isolatedDeclarations\": true\n  },\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\"**/dist/**\"]\n}\n"
  },
  {
    "path": "packages/vitest/vitest.mjs",
    "content": "#!/usr/bin/env node\nimport './dist/cli.js'\n"
  },
  {
    "path": "packages/vitest/worker.d.ts",
    "content": "export * from './dist/worker.js'\n"
  },
  {
    "path": "packages/web-worker/README.md",
    "content": "# @vitest/web-worker\n\n[![NPM version](https://img.shields.io/npm/v/@vitest/web-worker?color=a1b858&label=)](https://npmx.dev/package/@vitest/web-worker)\n\n> Web Worker support for Vitest testing. Doesn't require JSDom.\n\nSimulates Web Worker, but in the same thread.\n\nSupported:\n\n- `new Worker(path)`\n- `new SharedWorker(path)`\n- `import MyWorker from './worker?worker'`\n- `import MySharedWorker from './worker?sharedworker'`\n\n## Installing\n\n```bash\n# with npm\nnpm install -D @vitest/web-worker\n\n# with pnpm\npnpm install -D @vitest/web-worker\n\n# with yarn\nyarn add --dev @vitest/web-worker\n```\n\n## Usage\n\nJust import `@vitest/web-worker` in your test file to test only in current suite.\n\nOr add `@vitest/web-worker` in your `setupFiles`, if you want to have a global support.\n\n```ts\nimport { defineConfig } from 'vitest/node'\n\nexport default defineConfig({\n  test: {\n    setupFiles: ['@vitest/web-worker'],\n  },\n})\n```\n\nYou can also import `defineWebWorkers` from `@vitest/web-worker/pure` to define workers, whenever you need:\n\n```js\nimport { defineWebWorkers } from '@vitest/web-worker/pure'\n\nif (process.env.SUPPORT_WORKERS) {\n  defineWebWorkers({ clone: 'none' })\n}\n```\n\nIt accepts options:\n\n- `clone`: `'native' | 'ponyfill' | 'none'`. Defines how should `Worker` clone message, when transferring data. Applies only to `Worker` communication. `SharedWorker` uses `MessageChannel` from Node's `worker_threads` module, and is not configurable.\n\n> **Note**\n> Requires Node 17, if you want to use native `structuredClone`. Otherwise, it fallbacks to [polyfill](https://github.com/ungap/structured-clone), if not specified as `none`. You can also configure this option with `VITEST_WEB_WORKER_CLONE` environmental variable.\n\n## Examples\n\n```ts\n// worker.ts\nself.onmessage = (e) => {\n  self.postMessage(`${e.data} world`)\n}\n```\n\n```ts\n// worker.test.ts\nimport '@vitest/web-worker'\nimport MyWorker from '../worker?worker'\n\nlet worker = new MyWorker()\n// new Worker is also supported\nworker = new Worker(new URL('../src/worker.ts', import.meta.url))\n\nworker.postMessage('hello')\nworker.onmessage = (e) => {\n  // e.data equals to 'hello world'\n}\n```\n\n## Notes\n\n- Worker does not support `onmessage = () => {}`. Please, use `self.onmessage = () => {}`.\n- Shared worker does not support `onconnect = () => {}`. Please, use `self.onconnect = () => {}`.\n- Transferring Buffer will not change its `byteLength`.\n- You have access to shared global space as your tests.\n- You can debug your worker, using `DEBUG=vitest:web-worker` environmental variable.\n\n[GitHub](https://github.com/vitest-dev/vitest/tree/main/packages/web-worker) | [Documentation](https://vitest.dev/)\n"
  },
  {
    "path": "packages/web-worker/index.d.ts",
    "content": ""
  },
  {
    "path": "packages/web-worker/package.json",
    "content": "{\n  \"name\": \"@vitest/web-worker\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"Web Worker support for testing in Vitest\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://github.com/vitest-dev/vitest/tree/main/packages/web-worker#readme\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/web-worker\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    },\n    \"./pure\": {\n      \"types\": \"./pure.d.ts\",\n      \"default\": \"./dist/pure.js\"\n    }\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./index.d.ts\",\n  \"files\": [\n    \"*.d.ts\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch --watch.include 'src/**'\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"peerDependencies\": {\n    \"vitest\": \"workspace:*\"\n  },\n  \"dependencies\": {\n    \"obug\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@types/ungap__structured-clone\": \"^1.2.0\",\n    \"@ungap/structured-clone\": \"^1.3.0\"\n  }\n}\n"
  },
  {
    "path": "packages/web-worker/pure.d.ts",
    "content": "export * from './dist/pure.js'\n"
  },
  {
    "path": "packages/web-worker/rollup.config.js",
    "content": "import { createRequire } from 'node:module'\nimport commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport nodeResolve from '@rollup/plugin-node-resolve'\nimport { defineConfig } from 'rollup'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('./package.json')\n\nconst entries = {\n  index: 'src/index.ts',\n  pure: 'src/pure.ts',\n}\n\nconst external = [\n  ...Object.keys(pkg.dependencies || {}),\n  ...Object.keys(pkg.peerDependencies || {}),\n  /^@?vitest(\\/|$)/,\n]\n\nconst dtsUtils = createDtsUtils()\n\nconst plugins = [\n  ...dtsUtils.isolatedDecl(),\n  json(),\n  nodeResolve(),\n  commonjs(),\n  oxc({\n    transform: { target: 'node20' },\n  }),\n]\n\nexport default () => defineConfig([\n  {\n    input: entries,\n    output: {\n      dir: 'dist',\n      format: 'esm',\n    },\n    external,\n    plugins,\n  },\n  {\n    input: dtsUtils.dtsInput({ pure: '' }),\n    output: {\n      dir: 'dist',\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n  },\n])\n"
  },
  {
    "path": "packages/web-worker/src/index.ts",
    "content": "import { defineWebWorkers } from './pure'\n\ndefineWebWorkers()\n"
  },
  {
    "path": "packages/web-worker/src/pure.ts",
    "content": "import type { DefineWorkerOptions } from './types'\nimport { createSharedWorkerConstructor } from './shared-worker'\nimport { assertGlobalExists } from './utils'\nimport { createWorkerConstructor } from './worker'\n\nexport function defineWebWorkers(options?: DefineWorkerOptions): void {\n  if (\n    typeof Worker === 'undefined'\n    || !('__VITEST_WEB_WORKER__' in globalThis.Worker)\n  ) {\n    assertGlobalExists('EventTarget')\n    assertGlobalExists('MessageEvent')\n\n    globalThis.Worker = createWorkerConstructor(options)\n  }\n\n  if (\n    typeof SharedWorker === 'undefined'\n    || !('__VITEST_WEB_WORKER__' in globalThis.SharedWorker)\n  ) {\n    assertGlobalExists('EventTarget')\n\n    globalThis.SharedWorker = createSharedWorkerConstructor()\n  }\n}\n"
  },
  {
    "path": "packages/web-worker/src/runner.ts",
    "content": "import type { __TYPES } from 'vitest/runtime'\nimport { __INTERNAL } from 'vitest/runtime'\n\nconst {\n  VitestModuleEvaluator,\n  startVitestModuleRunner,\n  VITEST_VM_CONTEXT_SYMBOL,\n  getWorkerState,\n} = __INTERNAL\n\nexport function startWebWorkerModuleRunner(context: Record<string, unknown>): __TYPES['VitestModuleRunner'] {\n  const state = getWorkerState()\n  const mocker = (globalThis as any).__vitest_mocker__\n\n  const compiledFunctionArgumentsNames = Object.keys(context)\n  const compiledFunctionArgumentsValues = Object.values(context)\n  compiledFunctionArgumentsNames.push('importScripts')\n  compiledFunctionArgumentsValues.push(importScripts)\n\n  const vm = (globalThis as any)[VITEST_VM_CONTEXT_SYMBOL]\n\n  const evaluator = new VitestModuleEvaluator(vm, {\n    interopDefault: state.config.deps.interopDefault,\n    moduleExecutionInfo: state.moduleExecutionInfo,\n    getCurrentTestFilepath: () => state.filepath,\n    compiledFunctionArgumentsNames,\n    compiledFunctionArgumentsValues,\n  })\n\n  return startVitestModuleRunner({\n    evaluator,\n    evaluatedModules: state.evaluatedModules,\n    mocker,\n    state,\n  })\n}\n\nfunction importScripts() {\n  throw new Error(\n    '[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead.',\n  )\n}\n"
  },
  {
    "path": "packages/web-worker/src/shared-worker.ts",
    "content": "import type { MessagePort as NodeMessagePort } from 'node:worker_threads'\nimport type { Procedure } from './types'\nimport { MessageChannel } from 'node:worker_threads'\nimport { startWebWorkerModuleRunner } from './runner'\nimport { debug, getFileIdFromUrl } from './utils'\n\nfunction convertNodePortToWebPort(port: NodeMessagePort): MessagePort {\n  if (!('addEventListener' in port)) {\n    Object.defineProperty(port, 'addEventListener', {\n      value(...args: any[]) {\n        return this.addListener(...args)\n      },\n      configurable: true,\n      enumerable: true,\n    })\n  }\n  if (!('removeEventListener' in port)) {\n    Object.defineProperty(port, 'removeEventListener', {\n      value(...args: any[]) {\n        return this.removeListener(...args)\n      },\n      configurable: true,\n      enumerable: true,\n    })\n  }\n  if (!('dispatchEvent' in port)) {\n    const emit = (port as any).emit.bind(port)\n    Object.defineProperty(port, 'emit', {\n      value(event: any) {\n        if (event.name === 'message') {\n          (port as any).onmessage?.(event)\n        }\n        if (event.name === 'messageerror') {\n          (port as any).onmessageerror?.(event)\n        }\n        return emit(event)\n      },\n      configurable: true,\n      enumerable: true,\n    })\n    Object.defineProperty(port, 'dispatchEvent', {\n      value(event: any) {\n        return this.emit(event)\n      },\n      configurable: true,\n      enumerable: true,\n    })\n  }\n  return port as any as MessagePort\n}\n\nexport function createSharedWorkerConstructor(): typeof SharedWorker {\n  return class SharedWorker extends EventTarget {\n    static __VITEST_WEB_WORKER__ = true\n\n    private _vw_workerTarget = new EventTarget()\n    private _vw_name: string\n    private _vw_workerPort: MessagePort\n\n    public onerror: null | Procedure = null\n\n    public port: MessagePort\n\n    constructor(url: URL | string, options?: WorkerOptions | string) {\n      super()\n\n      const name = typeof options === 'string' ? options : options?.name\n      let selfProxy: typeof globalThis\n\n      const context = {\n        onmessage: null,\n        onmessageerror: null,\n        onerror: null,\n        onlanguagechange: null,\n        onoffline: null,\n        ononline: null,\n        onrejectionhandled: null,\n        onrtctransform: null,\n        onunhandledrejection: null,\n        origin: typeof location !== 'undefined' ? location.origin : 'http://localhost:3000',\n        crossOriginIsolated: false,\n        onconnect: null as ((e: MessageEvent) => void) | null,\n        name: name || '',\n        close: () => this.port.close(),\n        dispatchEvent: (event: Event) => {\n          return this._vw_workerTarget.dispatchEvent(event)\n        },\n        addEventListener: (...args: any[]) => {\n          return this._vw_workerTarget.addEventListener(...args as [any, any])\n        },\n        removeEventListener: (...args: any[]) => {\n          return this._vw_workerTarget.removeEventListener(...args as [any, any])\n        },\n        get self() {\n          return selfProxy\n        },\n      }\n\n      selfProxy = new Proxy(context, {\n        get(target, prop, receiver) {\n          if (Reflect.has(target, prop)) {\n            return Reflect.get(target, prop, receiver)\n          }\n          return Reflect.get(globalThis, prop, receiver)\n        },\n      }) as any\n\n      const channel = new MessageChannel()\n      this.port = convertNodePortToWebPort(channel.port1)\n      this._vw_workerPort = convertNodePortToWebPort(channel.port2)\n\n      this._vw_workerTarget.addEventListener('connect', (e) => {\n        context.onconnect?.(e as MessageEvent)\n      })\n\n      const fileId = getFileIdFromUrl(url)\n\n      this._vw_name = fileId\n\n      const runner = startWebWorkerModuleRunner(context)\n      runner.mocker.resolveId(fileId).then(({ url, id: resolvedId }) => {\n        this._vw_name = name ?? url\n        debug('initialize shared worker %s', this._vw_name)\n\n        return runner.import(url).then(() => {\n          runner._invalidateSubTreeById([\n            resolvedId,\n            runner.mocker.getMockPath(resolvedId),\n          ])\n          this._vw_workerTarget.dispatchEvent(\n            new MessageEvent('connect', {\n              ports: [this._vw_workerPort],\n            }),\n          )\n          debug('shared worker %s successfully initialized', this._vw_name)\n        })\n      }).catch((e) => {\n        debug('shared worker %s failed to initialize: %o', this._vw_name, e)\n        const EventConstructor = globalThis.ErrorEvent || globalThis.Event\n        const error = new EventConstructor('error', {\n          error: e,\n          message: e.message,\n        })\n        this.dispatchEvent(error)\n        this.onerror?.(error)\n        console.error(e)\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "packages/web-worker/src/types.ts",
    "content": "export type Procedure = (...args: any[]) => void\nexport type CloneOption = 'native' | 'ponyfill' | 'none'\n\nexport interface DefineWorkerOptions {\n  clone: CloneOption\n}\n"
  },
  {
    "path": "packages/web-worker/src/utils.ts",
    "content": "import type { Debugger } from 'obug'\nimport type { WorkerGlobalState } from 'vitest'\nimport type { CloneOption } from './types'\nimport ponyfillStructuredClone from '@ungap/structured-clone'\nimport { createDebug } from 'obug'\n\nexport const debug: Debugger = createDebug('vitest:web-worker')\n\nexport function getWorkerState(): WorkerGlobalState {\n  // @ts-expect-error untyped global\n  return globalThis.__vitest_worker__\n}\n\nexport function assertGlobalExists(name: string): void {\n  if (!(name in globalThis)) {\n    throw new Error(\n      `[@vitest/web-worker] Cannot initiate a custom Web Worker. \"${name}\" is not supported in this environment. Please, consider using jsdom or happy-dom environment.`,\n    )\n  }\n}\n\nfunction createClonedMessageEvent(\n  data: any,\n  transferOrOptions: StructuredSerializeOptions | Transferable[] | undefined,\n  clone: CloneOption,\n) {\n  const transfer = Array.isArray(transferOrOptions)\n    ? transferOrOptions\n    : transferOrOptions?.transfer\n\n  debug('clone worker message %o', data)\n  const origin = typeof location === 'undefined' ? undefined : location.origin\n  const ports = transfer?.filter((t): t is MessagePort => t instanceof MessagePort)\n  const transferWithoutPorts = transfer?.filter( // `ports` must be excluded from the `transfer` option passed to `structuredClone` to keep the MessagePort objects working correctly in the same thread.\n    t => !(t instanceof MessagePort),\n  )\n\n  if (typeof structuredClone === 'function' && clone === 'native') {\n    debug('create message event, using native structured clone')\n    return new MessageEvent('message', {\n      data: structuredClone(data, { transfer: transferWithoutPorts }),\n      origin,\n      ports,\n    })\n  }\n  if (clone !== 'none') {\n    debug('create message event, using polyfilled structured clone')\n    if (transfer?.length) {\n      console.warn(\n        '[@vitest/web-worker] `structuredClone` is not supported in this environment. '\n        + 'Falling back to polyfill, your transferable options will be lost. '\n        + 'Set `VITEST_WEB_WORKER_CLONE` environmental variable to \"none\", if you don\\'t want to loose it,'\n        + 'or update to Node 17+.',\n      )\n    }\n    return new MessageEvent('message', {\n      data: ponyfillStructuredClone(data, { lossy: true } as any),\n      origin,\n      ports,\n    })\n  }\n  debug('create message event without cloning an object')\n  return new MessageEvent('message', {\n    data,\n    origin,\n    ports,\n  })\n}\n\nexport function createMessageEvent(\n  data: any,\n  transferOrOptions: StructuredSerializeOptions | Transferable[] | undefined,\n  clone: CloneOption,\n): MessageEvent {\n  try {\n    return createClonedMessageEvent(data, transferOrOptions, clone)\n  }\n  catch (error) {\n    debug('failed to clone message, dispatch \"messageerror\" event: %o', error)\n    return new MessageEvent('messageerror', {\n      data: error,\n    })\n  }\n}\n\nfunction stripProtocol(url: string | URL) {\n  return url.toString().replace(/^file:\\/+/, '/')\n}\n\nexport function getFileIdFromUrl(url: URL | string): string {\n  if (typeof self === 'undefined') {\n    return stripProtocol(url)\n  }\n  if (!(url instanceof URL)) {\n    url = new URL(url, self.location.origin)\n  }\n  if (url.protocol === 'http:' || url.protocol === 'https:') {\n    return url.pathname\n  }\n  return stripProtocol(url)\n}\n"
  },
  {
    "path": "packages/web-worker/src/worker.ts",
    "content": "import type {\n  CloneOption,\n  DefineWorkerOptions,\n  Procedure,\n} from './types'\nimport { startWebWorkerModuleRunner } from './runner'\nimport {\n  createMessageEvent,\n  debug,\n  getFileIdFromUrl,\n} from './utils'\n\nexport function createWorkerConstructor(\n  options?: DefineWorkerOptions,\n): typeof Worker {\n  const cloneType = () =>\n    (options?.clone\n      ?? process.env.VITEST_WEB_WORKER_CLONE\n      ?? 'native') as CloneOption\n\n  return class Worker extends EventTarget {\n    static __VITEST_WEB_WORKER__ = true\n\n    private _vw_workerTarget = new EventTarget()\n    private _vw_insideListeners = new Map<\n      string,\n      EventListenerOrEventListenerObject\n    >()\n\n    private _vw_outsideListeners = new Map<\n      string,\n      EventListenerOrEventListenerObject\n    >()\n\n    private _vw_name: string\n    private _vw_messageQueue: any[] | null = []\n\n    public onmessage: null | Procedure = null\n    public onmessageerror: null | Procedure = null\n    public onerror: null | Procedure = null\n\n    constructor(url: URL | string, options?: WorkerOptions) {\n      super()\n\n      let selfProxy: typeof globalThis\n\n      // should be in sync with DedicatedWorkerGlobalScope, but without globalThis\n      const context = {\n        onmessage: null as null | ((e: MessageEvent) => void),\n        onmessageerror: null,\n        onerror: null,\n        onlanguagechange: null,\n        onoffline: null,\n        ononline: null,\n        onrejectionhandled: null,\n        onrtctransform: null,\n        onunhandledrejection: null,\n        origin: typeof location !== 'undefined' ? location.origin : 'http://localhost:3000',\n        crossOriginIsolated: false,\n        name: options?.name || '',\n        close: () => this.terminate(),\n        dispatchEvent: (event: Event) => {\n          return this._vw_workerTarget.dispatchEvent(event)\n        },\n        addEventListener: (...args: any[]) => {\n          if (args[1]) {\n            this._vw_insideListeners.set(args[0], args[1])\n          }\n          return this._vw_workerTarget.addEventListener(...args as [any, any])\n        },\n        removeEventListener: (...args: any[]) => {\n          return this._vw_workerTarget.removeEventListener(...args as [any, any])\n        },\n        postMessage: (...args: any[]) => {\n          if (!args.length) {\n            throw new SyntaxError(\n              '\"postMessage\" requires at least one argument.',\n            )\n          }\n\n          debug(\n            'posting message %o from the worker %s to the main thread',\n            args[0],\n            this._vw_name,\n          )\n          const event = createMessageEvent(args[0], args[1], cloneType())\n          this.dispatchEvent(event)\n        },\n        get self() {\n          return selfProxy\n        },\n      }\n\n      selfProxy = new Proxy(context, {\n        get(target, prop, receiver) {\n          if (Reflect.has(target, prop)) {\n            return Reflect.get(target, prop, receiver)\n          }\n          return globalThis[prop as 'crypto']\n        },\n      }) as any\n\n      this._vw_workerTarget.addEventListener('message', (e) => {\n        context.onmessage?.(e as MessageEvent)\n      })\n\n      this.addEventListener('message', (e) => {\n        this.onmessage?.(e)\n      })\n\n      this.addEventListener('messageerror', (e) => {\n        this.onmessageerror?.(e)\n      })\n\n      const fileId = getFileIdFromUrl(url)\n\n      this._vw_name = fileId\n\n      const runner = startWebWorkerModuleRunner(context)\n      runner.mocker.resolveId(fileId).then(({ url, id: resolvedId }) => {\n        this._vw_name = options?.name ?? url\n        debug('initialize worker %s', this._vw_name)\n\n        return runner.import(url).then(() => {\n          runner._invalidateSubTreeById([\n            resolvedId,\n            runner.mocker.getMockPath(resolvedId),\n          ])\n          const q = this._vw_messageQueue\n          this._vw_messageQueue = null\n          if (q) {\n            q.forEach(\n              ([data, transfer]) => this.postMessage(data, transfer),\n              this,\n            )\n          }\n          debug('worker %s successfully initialized', this._vw_name)\n        })\n      }).catch((e) => {\n        debug('worker %s failed to initialize: %o', this._vw_name, e)\n        const EventConstructor = globalThis.ErrorEvent || globalThis.Event\n        const error = new EventConstructor('error', {\n          error: e,\n          message: e.message,\n        })\n        this.dispatchEvent(error)\n        this.onerror?.(error)\n        console.error(e)\n      })\n    }\n\n    addEventListener(\n      type: string,\n      callback: EventListenerOrEventListenerObject | null,\n      options?: boolean | AddEventListenerOptions,\n    ): void {\n      if (callback) {\n        this._vw_outsideListeners.set(type, callback)\n      }\n      return super.addEventListener(type, callback, options)\n    }\n\n    postMessage(\n      ...args: [any, StructuredSerializeOptions | Transferable[] | undefined]\n    ): void {\n      if (!args.length) {\n        throw new SyntaxError('\"postMessage\" requires at least one argument.')\n      }\n\n      const [data, transferOrOptions] = args\n      if (this._vw_messageQueue != null) {\n        debug(\n          'worker %s is not yet initialized, queue message %s',\n          this._vw_name,\n          data,\n        )\n        this._vw_messageQueue.push([data, transferOrOptions])\n        return\n      }\n\n      debug(\n        'posting message %o from the main thread to the worker %s',\n        data,\n        this._vw_name,\n      )\n\n      const event = createMessageEvent(data, transferOrOptions, cloneType())\n      if (event.type === 'messageerror') {\n        this.dispatchEvent(event)\n      }\n      else {\n        this._vw_workerTarget.dispatchEvent(event)\n      }\n    }\n\n    terminate() {\n      debug('terminating worker %s', this._vw_name)\n      this._vw_outsideListeners.forEach((fn, type) => {\n        this.removeEventListener(type, fn)\n      })\n      this._vw_insideListeners.forEach((fn, type) => {\n        this._vw_workerTarget.removeEventListener(type, fn)\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "packages/web-worker/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"lib\": [\"ESNext\", \"WebWorker\", \"DOM\"],\n    \"isolatedDeclarations\": true\n  },\n  \"exclude\": [\"./dist\"]\n}\n"
  },
  {
    "path": "packages/ws-client/package.json",
    "content": "{\n  \"name\": \"@vitest/ws-client\",\n  \"type\": \"module\",\n  \"version\": \"4.1.0\",\n  \"description\": \"WebSocket client wrapper for communicating with Vitest\",\n  \"author\": \"Anthony Fu <anthonyfu117@hotmail.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://opencollective.com/vitest\",\n  \"homepage\": \"https://github.com/vitest-dev/vitest/tree/main/packages/ws-client#readme\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitest-dev/vitest.git\",\n    \"directory\": \"packages/ws-client\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitest-dev/vitest/issues\"\n  },\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"default\": \"./dist/index.js\"\n    }\n  },\n  \"main\": \"./dist/index.js\",\n  \"module\": \"./dist/index.js\",\n  \"types\": \"./dist/index.d.ts\",\n  \"files\": [\n    \"*.d.ts\",\n    \"*.mjs\",\n    \"dist\"\n  ],\n  \"engines\": {\n    \"node\": \"^20.0.0 || ^22.0.0 || >=24.0.0\"\n  },\n  \"scripts\": {\n    \"build\": \"premove dist && rollup -c\",\n    \"dev\": \"rollup -c --watch --watch.include 'src/**'\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"dependencies\": {\n    \"birpc\": \"catalog:\",\n    \"flatted\": \"catalog:\",\n    \"ws\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@vitest/runner\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/ws-client/rollup.config.js",
    "content": "import commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugin-node-resolve'\nimport oxc from 'unplugin-oxc/rollup'\nimport { createDtsUtils } from '../../scripts/build-utils.js'\n\nconst entry = ['src/index.ts']\n\nconst external = [\n  'ws',\n  'birpc',\n  'worker_threads',\n  'node:worker_threads',\n  'fs',\n  'node:fs',\n  'vitest',\n  'inspector',\n  '@vitest/snapshot/environment',\n  '@vitest/snapshot/manager',\n]\n\nconst dtsUtils = createDtsUtils()\n\nexport default () => [\n  {\n    input: entry,\n    output: {\n      dir: 'dist',\n      format: 'esm',\n    },\n    external,\n    plugins: [\n      ...dtsUtils.isolatedDecl(),\n      resolve({\n        preferBuiltins: true,\n      }),\n      json(),\n      commonjs(),\n      oxc({\n        transform: { target: 'node20' },\n      }),\n    ],\n  },\n  {\n    input: dtsUtils.dtsInput('src/index.ts'),\n    output: {\n      dir: 'dist',\n      entryFileNames: '[name].d.ts',\n      format: 'esm',\n    },\n    watch: false,\n    external,\n    plugins: dtsUtils.dts(),\n  },\n]\n"
  },
  {
    "path": "packages/ws-client/src/index.ts",
    "content": "import type { BirpcOptions, BirpcReturn } from 'birpc'\n// eslint-disable-next-line no-restricted-imports\nimport type { WebSocketEvents, WebSocketHandlers } from 'vitest'\nimport { createBirpc } from 'birpc'\n\nimport { parse, stringify } from 'flatted'\nimport { StateManager } from './state'\n\nexport * from '@vitest/runner/utils'\n\nexport interface VitestClientOptions {\n  handlers?: Partial<WebSocketEvents>\n  autoReconnect?: boolean\n  reconnectInterval?: number\n  reconnectTries?: number\n  connectTimeout?: number\n  reactive?: <T>(v: T, forKey: 'state' | 'idMap' | 'filesMap') => T\n  ref?: <T>(v: T) => { value: T }\n  WebSocketConstructor?: typeof WebSocket\n}\n\nexport interface VitestClient {\n  ws: WebSocket\n  state: StateManager\n  rpc: BirpcReturn<WebSocketHandlers, WebSocketEvents>\n  waitForConnection: () => Promise<void>\n  reconnect: () => Promise<void>\n}\n\nexport function createClient(url: string, options: VitestClientOptions = {}): VitestClient {\n  const {\n    handlers = {},\n    autoReconnect = true,\n    reconnectInterval = 2000,\n    reconnectTries = 10,\n    connectTimeout = 60000,\n    reactive = v => v,\n    WebSocketConstructor = globalThis.WebSocket,\n  } = options\n\n  let tries = reconnectTries\n  const ctx = reactive({\n    ws: new WebSocketConstructor(url),\n    state: new StateManager(),\n    waitForConnection,\n    reconnect,\n  }, 'state') as VitestClient\n\n  ctx.state.filesMap = reactive(ctx.state.filesMap, 'filesMap')\n  ctx.state.idMap = reactive(ctx.state.idMap, 'idMap')\n\n  let onMessage: (data: any) => void\n  const functions: WebSocketEvents = {\n    onTestAnnotate(testId, annotation) {\n      handlers.onTestAnnotate?.(testId, annotation)\n    },\n    onTestArtifactRecord(testId, artifact) {\n      handlers.onTestArtifactRecord?.(testId, artifact)\n    },\n    onSpecsCollected(specs, startTime) {\n      specs?.forEach(([config, file]) => {\n        ctx.state.clearFiles({ config }, [file])\n      })\n      handlers.onSpecsCollected?.(specs, startTime)\n    },\n    onPathsCollected(paths) {\n      ctx.state.collectPaths(paths)\n      handlers.onPathsCollected?.(paths)\n    },\n    onCollected(files) {\n      ctx.state.collectFiles(files)\n      handlers.onCollected?.(files)\n    },\n    onTaskUpdate(packs, events) {\n      ctx.state.updateTasks(packs)\n      handlers.onTaskUpdate?.(packs, events)\n    },\n    onUserConsoleLog(log) {\n      ctx.state.updateUserLog(log)\n      handlers.onUserConsoleLog?.(log)\n    },\n    onFinished(files, errors, coverage, executionTime) {\n      handlers.onFinished?.(files, errors, coverage, executionTime)\n    },\n    onFinishedReportCoverage() {\n      handlers.onFinishedReportCoverage?.()\n    },\n  }\n\n  const birpcHandlers = {\n    post: msg => ctx.ws.send(msg),\n    on: fn => (onMessage = fn),\n    serialize: e =>\n      stringify(e, (_, v) => {\n        if (v instanceof Error) {\n          return {\n            name: v.name,\n            message: v.message,\n            stack: v.stack,\n          }\n        }\n        return v\n      }),\n    deserialize: parse,\n    timeout: -1,\n  } satisfies BirpcOptions<WebSocketHandlers>\n\n  ctx.rpc = createBirpc<WebSocketHandlers, WebSocketEvents>(\n    functions,\n    birpcHandlers,\n  )\n\n  let openPromise: Promise<void>\n\n  function reconnect(reset = false) {\n    if (reset) {\n      tries = reconnectTries\n    }\n    ctx.ws = new WebSocketConstructor(url)\n    registerWS()\n  }\n\n  function registerWS() {\n    openPromise = new Promise((resolve, reject) => {\n      const timeout = setTimeout(() => {\n        reject(\n          new Error(\n            `Cannot connect to the server in ${connectTimeout / 1000} seconds`,\n          ),\n        )\n      }, connectTimeout)?.unref?.()\n      if (ctx.ws.OPEN === ctx.ws.readyState) {\n        resolve()\n      }\n      // still have a listener even if it's already open to update tries\n      ctx.ws.addEventListener('open', () => {\n        tries = reconnectTries\n        resolve()\n        clearTimeout(timeout)\n      })\n    })\n    ctx.ws.addEventListener('message', (v) => {\n      onMessage(v.data)\n    })\n    ctx.ws.addEventListener('close', () => {\n      tries -= 1\n      if (autoReconnect && tries > 0) {\n        setTimeout(reconnect, reconnectInterval)\n      }\n    })\n  }\n\n  registerWS()\n\n  function waitForConnection() {\n    return openPromise\n  }\n\n  return ctx\n}\n"
  },
  {
    "path": "packages/ws-client/src/state.ts",
    "content": "import type { File, Task, TaskResultPack } from '@vitest/runner'\n// eslint-disable-next-line no-restricted-imports\nimport type { UserConsoleLog } from 'vitest'\n\n// can't import actual functions from utils, because it's incompatible with @vitest/browsers\nimport { createFileTask } from '@vitest/runner/utils'\n\n// Note this file is shared for both node and browser, be aware to avoid node specific logic\nexport class StateManager {\n  filesMap: Map<string, File[]> = new Map()\n  pathsSet: Set<string> = new Set()\n  idMap: Map<string, Task> = new Map()\n\n  getPaths(): string[] {\n    return Array.from(this.pathsSet)\n  }\n\n  /**\n   * Return files that were running or collected.\n   */\n  getFiles(keys?: string[]): File[] {\n    if (keys) {\n      return keys\n        .map(key => this.filesMap.get(key)!)\n        .flat()\n        .filter(file => file && !file.local)\n    }\n    return Array.from(this.filesMap.values()).flat().filter(file => !file.local)\n  }\n\n  getFilepaths(): string[] {\n    return Array.from(this.filesMap.keys())\n  }\n\n  getFailedFilepaths(): string[] {\n    return this.getFiles()\n      .filter(i => i.result?.state === 'fail')\n      .map(i => i.filepath)\n  }\n\n  collectPaths(paths: string[] = []): void {\n    paths.forEach((path) => {\n      this.pathsSet.add(path)\n    })\n  }\n\n  collectFiles(files: File[] = []): void {\n    files.forEach((file) => {\n      const existing = this.filesMap.get(file.filepath) || []\n      const otherProject = existing.filter(\n        i => i.projectName !== file.projectName || i.meta.typecheck !== file.meta.typecheck,\n      )\n      const currentFile = existing.find(\n        i => i.projectName === file.projectName,\n      )\n      // keep logs for the previous file because it should always be initiated before the collections phase\n      // which means that all logs are collected during the collection and not inside tests\n      if (currentFile) {\n        file.logs = currentFile.logs\n      }\n      otherProject.push(file)\n      this.filesMap.set(file.filepath, otherProject)\n      this.updateId(file)\n    })\n  }\n\n  // this file is reused by ws-client, and should not rely on heavy dependencies like workspace\n  clearFiles(\n    _project: { config: { name: string | undefined; root: string } },\n    paths: string[] = [],\n  ): void {\n    const project = _project\n    paths.forEach((path) => {\n      const files = this.filesMap.get(path)\n      const fileTask = createFileTask(\n        path,\n        project.config.root,\n        project.config.name || '',\n      )\n      fileTask.local = true\n      this.idMap.set(fileTask.id, fileTask)\n      if (!files) {\n        this.filesMap.set(path, [fileTask])\n        return\n      }\n      const filtered = files.filter(\n        file => file.projectName !== project.config.name,\n      )\n      // always keep a File task, so we can associate logs with it\n      if (!filtered.length) {\n        this.filesMap.set(path, [fileTask])\n      }\n      else {\n        this.filesMap.set(path, [...filtered, fileTask])\n      }\n    })\n  }\n\n  updateId(task: Task): void {\n    if (this.idMap.get(task.id) === task) {\n      return\n    }\n    this.idMap.set(task.id, task)\n    if (task.type === 'suite') {\n      task.tasks.forEach((task) => {\n        this.updateId(task)\n      })\n    }\n  }\n\n  updateTasks(packs: TaskResultPack[]): void {\n    for (const [id, result, meta] of packs) {\n      const task = this.idMap.get(id)\n      if (task) {\n        task.result = result\n        task.meta = meta\n        // skipped with new PendingError\n        if (result?.state === 'skip') {\n          task.mode = 'skip'\n        }\n      }\n    }\n  }\n\n  updateUserLog(log: UserConsoleLog): void {\n    const task = log.taskId && this.idMap.get(log.taskId)\n    if (task) {\n      if (!task.logs) {\n        task.logs = []\n      }\n      task.logs.push(log)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/ws-client/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"lib\": [\"DOM\"],\n    \"isolatedDeclarations\": true\n  },\n  \"exclude\": [\"./dist\"]\n}\n"
  },
  {
    "path": "patches/@sinonjs__fake-timers@15.0.0.patch",
    "content": "diff --git a/src/fake-timers-src.js b/src/fake-timers-src.js\nindex a9bcfd1ca..942539085 100644\n--- a/src/fake-timers-src.js\n+++ b/src/fake-timers-src.js\n@@ -2,14 +2,14 @@\n \n const globalObject = require(\"@sinonjs/commons\").global;\n let timersModule, timersPromisesModule;\n-if (typeof require === \"function\" && typeof module === \"object\") {\n+if (typeof __vitest_required__ !== 'undefined') {\n     try {\n-        timersModule = require(\"timers\");\n+        timersModule = __vitest_required__.timers;\n     } catch (e) {\n         // ignored\n     }\n     try {\n-        timersPromisesModule = require(\"timers/promises\");\n+        timersPromisesModule = __vitest_required__.timersPromises;\n     } catch (e) {\n         // ignored\n     }\n@@ -197,7 +197,7 @@ function withGlobal(_global) {\n         isPresent.hrtime && typeof _global.process.hrtime.bigint === \"function\";\n     isPresent.nextTick =\n         _global.process && typeof _global.process.nextTick === \"function\";\n-    const utilPromisify = _global.process && require(\"util\").promisify;\n+    const utilPromisify = _global.process && _global.__vitest_required__ && _global.__vitest_required__.util.promisify;\n     isPresent.performance =\n         _global.performance && typeof _global.performance.now === \"function\";\n     const hasPerformancePrototype =\n"
  },
  {
    "path": "patches/acorn@8.11.3.patch",
    "content": "diff --git a/package.json b/package.json\nindex 1b8dc76afc3cf5890cc3693c2975577fd3117dd6..d215ae8677dc8b82c0f4d9b9af557b860ac16292 100644\n--- a/package.json\n+++ b/package.json\n@@ -5,6 +5,7 @@\n   \"main\": \"dist/acorn.js\",\n   \"types\": \"dist/acorn.d.ts\",\n   \"module\": \"dist/acorn.mjs\",\n+  \"sideEffects\": false,\n   \"exports\": {\n     \".\": [\n       {\n"
  },
  {
    "path": "patches/cac@6.7.14.patch",
    "content": "diff --git a/dist/index.d.ts b/dist/index.d.ts\nindex 84dcb6642e6633419d94a81f5764f90d10273cfc..a811fd5e7904a6204a15912ad549eae89ec697e9 100644\n--- a/dist/index.d.ts\n+++ b/dist/index.d.ts\n@@ -2,7 +2,7 @@ import { EventEmitter } from 'events';\n \n interface OptionConfig {\n     default?: any;\n-    type?: any[];\n+    type?: any;\n }\n declare class Option {\n     rawName: string;\n@@ -173,7 +173,7 @@ declare class CAC extends EventEmitter {\n     /**\n      * Parse argv\n      */\n-    parse(argv?: string[], { \n+    parse(argv?: string[], {\n     /** Whether to run the action for matched command */\n     run, }?: {\n         run?: boolean | undefined;\ndiff --git a/dist/index.mjs b/dist/index.mjs\nindex 7c1c4440c6ed22a3829f828364b06669c56b31c9..3d742db1a0b9c943152464916d7f241b7e1942c3 100644\n--- a/dist/index.mjs\n+++ b/dist/index.mjs\n@@ -182,25 +182,24 @@ const camelcase = (input) => {\n     return p1 + p2.toUpperCase();\n   });\n };\n-const setDotProp = (obj, keys, val) => {\n+const setDotProp = (obj, keys, val, transforms) => {\n   let i = 0;\n   let length = keys.length;\n   let t = obj;\n   let x;\n+  let convertKey = (i) => {\n+    let key = keys[i]\n+    i--;\n+    while(i >= 0) {\n+      key = keys[i] + '.' + key;\n+      i--;\n+    }\n+    return key\n+  }\n   for (; i < length; ++i) {\n     x = t[keys[i]];\n-    t = t[keys[i]] = i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf(\".\") || !(+keys[i + 1] > -1) ? {} : [];\n-  }\n-};\n-const setByType = (obj, transforms) => {\n-  for (const key of Object.keys(transforms)) {\n-    const transform = transforms[key];\n-    if (transform.shouldTransform) {\n-      obj[key] = Array.prototype.concat.call([], obj[key]);\n-      if (typeof transform.transformFunction === \"function\") {\n-        obj[key] = obj[key].map(transform.transformFunction);\n-      }\n-    }\n+    const transform = transforms[convertKey(i)] || ((v) => v);\n+    t = t[keys[i]] = transform(i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf(\".\") || !(+keys[i + 1] > -1) ? {} : []);\n   }\n };\n const getFileName = (input) => {\n@@ -406,7 +405,11 @@ ${section.body}` : section.body;\n     const {options: parsedOptions, globalCommand} = this.cli;\n     const options = [...globalCommand.options, ...this.options];\n     for (const option of options) {\n-      const value = parsedOptions[option.name.split(\".\")[0]];\n+      // skip dot names because only top level options are required\n+      if (option.name.includes('.')) {\n+        continue;\n+      }\n+      const value = parsedOptions[option.name];\n       if (option.required) {\n         const hasNegated = options.some((o) => o.negated && o.names.includes(option.name));\n         if (value === true || value === false && !hasNegated) {\n@@ -571,19 +574,17 @@ class CAC extends EventEmitter {\n           options[name] = cliOption.config.default;\n         }\n       }\n-      if (Array.isArray(cliOption.config.type)) {\n+      if (cliOption.config.type != null) {\n         if (transforms[cliOption.name] === void 0) {\n-          transforms[cliOption.name] = Object.create(null);\n-          transforms[cliOption.name][\"shouldTransform\"] = true;\n-          transforms[cliOption.name][\"transformFunction\"] = cliOption.config.type[0];\n+          transforms[cliOption.name] = cliOption.config.type;\n         }\n       }\n     }\n     for (const key of Object.keys(parsed)) {\n       if (key !== \"_\") {\n         const keys = key.split(\".\");\n-        setDotProp(options, keys, parsed[key]);\n-        setByType(options, transforms);\n+        setDotProp(options, keys, parsed[key], transforms);\n+        // setByType(options, transforms);\n       }\n     }\n     return {\n"
  },
  {
    "path": "patches/istanbul-lib-instrument.patch",
    "content": "diff --git a/CHANGELOG.md b/CHANGELOG.md\ndeleted file mode 100644\nindex 3c2c978099ce42ef26b9cd86d5772cff79e329af..0000000000000000000000000000000000000000\ndiff --git a/package.json b/package.json\nindex 5e3c704a13d642e07c6d8eb655cb052b69a99e45..743037fa385ac381b193ac7b975e5f548e064727 100644\n--- a/package.json\n+++ b/package.json\n@@ -13,6 +13,7 @@\n   \"dependencies\": {\n     \"@babel/core\": \"^7.23.9\",\n     \"@babel/parser\": \"^7.23.9\",\n+    \"@jridgewell/trace-mapping\": \"^0.3.23\",\n     \"@istanbuljs/schema\": \"^0.1.3\",\n     \"istanbul-lib-coverage\": \"^3.2.0\",\n     \"semver\": \"^7.5.4\"\ndiff --git a/src/ignored-lines.js b/src/ignored-lines.js\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..5392b2b17165b3bbd52871bb931be1306f7fabe1\n--- /dev/null\n+++ b/src/ignored-lines.js\n@@ -0,0 +1,61 @@\n+const IGNORE_LINES_PATTERN = /\\s*istanbul\\s+ignore\\s+(start|stop)/;\n+const EOL_PATTERN = /\\r?\\n/g;\n+\n+/**\n+ * Parse ignore start/stop hints from **text file** based on regular expressions\n+ * - Does not understand what a comment is in Javascript (or JSX, Vue, Svelte)\n+ * - Parses source code (JS, TS, Vue, Svelte, anything) based on text search by\n+ *   matching for `/* istanbul ignore start *\\/` pattern - not by looking for real comments\n+ *\n+ * ```js\n+ * /* istanbul ignore start *\\/\n+ * <!-- /* istanbul ignore start *\\/ -->\n+ * <SomeFrameworkComment content=\"/* istanbul ignore start *\\/\">\n+ * ```\n+ */\n+function getIgnoredLines(text) {\n+    if (!text) {\n+        return new Set();\n+    }\n+\n+    const ranges = [];\n+    let lineNumber = 0;\n+\n+    for (const line of text.split(EOL_PATTERN)) {\n+        lineNumber++;\n+\n+        const match = line.match(IGNORE_LINES_PATTERN);\n+        if (match) {\n+            const type = match[1];\n+\n+            if (type === 'stop') {\n+                const previous = ranges.at(-1);\n+\n+                // Ignore whole \"ignore stop\" if no previous start was found\n+                if (previous && previous.stop === Infinity) {\n+                    previous.stop = lineNumber;\n+                }\n+\n+                continue;\n+            }\n+\n+            ranges.push({ start: lineNumber, stop: Infinity });\n+        }\n+    }\n+\n+    const ignoredLines = new Set();\n+\n+    for (const range of ranges) {\n+        for (let line = range.start; line <= range.stop; line++) {\n+            ignoredLines.add(line);\n+\n+            if (line >= lineNumber) {\n+                break;\n+            }\n+        }\n+    }\n+\n+    return ignoredLines;\n+}\n+\n+module.exports = { getIgnoredLines };\ndiff --git a/src/instrumenter.js b/src/instrumenter.js\nindex ffc4387b9ba9477bdce3823760400fddb021637d..39f5ee8fede4a6d724b28050e1dd1e1942bd665a 100644\n--- a/src/instrumenter.js\n+++ b/src/instrumenter.js\n@@ -21,6 +21,7 @@ const readInitialCoverage = require('./read-coverage');\n  * @param {boolean} [opts.autoWrap=false] set to true to allow `return` statements outside of functions.\n  * @param {boolean} [opts.produceSourceMap=false] set to true to produce a source map for the instrumented code.\n  * @param {Array} [opts.ignoreClassMethods=[]] set to array of class method names to ignore for coverage.\n+ * @param {Array} [opts.ignoreLines=false] enable ignore hints for lines (start, end).\n  * @param {Function} [opts.sourceMapUrlCallback=null] a callback function that is called when a source map URL\n  *     is found in the original code. This function is called with the source file name and the source map URL.\n  * @param {boolean} [opts.debug=false] - turn debugging on.\n@@ -83,6 +84,7 @@ class Instrumenter {\n                             coverageGlobalScopeFunc:\n                                 opts.coverageGlobalScopeFunc,\n                             ignoreClassMethods: opts.ignoreClassMethods,\n+                            ignoreLines: opts.ignoreLines,\n                             inputSourceMap\n                         });\n \ndiff --git a/src/visitor.js b/src/visitor.js\nindex 04e3115f832799fad6d141e8b0aeaa61ac5c98f9..88f8d2420daabecef2ad2def18c8be245b60e253 100644\n--- a/src/visitor.js\n+++ b/src/visitor.js\n@@ -1,8 +1,17 @@\n+const { readFileSync } = require('fs');\n const { createHash } = require('crypto');\n const { template } = require('@babel/core');\n+const {\n+    originalPositionFor,\n+    TraceMap,\n+    GREATEST_LOWER_BOUND,\n+    LEAST_UPPER_BOUND,\n+    sourceContentFor\n+} = require('@jridgewell/trace-mapping');\n const { defaults } = require('@istanbuljs/schema');\n const { SourceCoverage } = require('./source-coverage');\n const { SHA, MAGIC_KEY, MAGIC_VALUE } = require('./constants');\n+const { getIgnoredLines } = require('./ignored-lines');\n \n // pattern for istanbul to ignore a section\n const COMMENT_RE = /^\\s*istanbul\\s+ignore\\s+(if|else|next)(?=\\W|$)/;\n@@ -26,7 +35,8 @@ class VisitState {\n         sourceFilePath,\n         inputSourceMap,\n         ignoreClassMethods = [],\n-        reportLogic = false\n+        reportLogic = false,\n+        ignoreLines = false\n     ) {\n         this.varName = genVar(sourceFilePath);\n         this.attrs = {};\n@@ -35,8 +45,13 @@ class VisitState {\n \n         if (typeof inputSourceMap !== 'undefined') {\n             this.cov.inputSourceMap(inputSourceMap);\n+\n+            if (ignoreLines) {\n+                this.traceMap = new TraceMap(inputSourceMap);\n+            }\n         }\n         this.ignoreClassMethods = ignoreClassMethods;\n+        this.ignoredLines = new Map();\n         this.types = types;\n         this.sourceMappingURL = null;\n         this.reportLogic = reportLogic;\n@@ -45,7 +60,42 @@ class VisitState {\n     // should we ignore the node? Yes, if specifically ignoring\n     // or if the node is generated.\n     shouldIgnore(path) {\n-        return this.nextIgnore || !path.node.loc;\n+        if (this.nextIgnore || !path.node.loc) {\n+            return true;\n+        }\n+\n+        if (!this.traceMap) {\n+            return false;\n+        }\n+\n+        // Anything that starts between the line ignore hints is ignored\n+        const start = originalPositionTryBoth(\n+            this.traceMap,\n+            path.node.loc.start\n+        );\n+\n+        // Generated code\n+        if (start.line == null) {\n+            return false;\n+        }\n+\n+        const filename = start.source;\n+        let ignoredLines = this.ignoredLines.get(filename);\n+\n+        if (!ignoredLines) {\n+            const sources = sourceContentFor(this.traceMap, filename);\n+            ignoredLines = getIgnoredLines(\n+                sources || tryReadFileSync(filename)\n+            );\n+\n+            this.ignoredLines.set(filename, ignoredLines);\n+        }\n+\n+        if (ignoredLines.has(start.line)) {\n+            return true;\n+        }\n+\n+        return false;\n     }\n \n     // extract the ignore comment hint (next|if|else) or null\n@@ -742,6 +792,7 @@ function shouldIgnoreFile(programNode) {\n  * @param {string} [opts.coverageGlobalScope=this] the global coverage variable scope.\n  * @param {boolean} [opts.coverageGlobalScopeFunc=true] use an evaluated function to find coverageGlobalScope.\n  * @param {Array} [opts.ignoreClassMethods=[]] names of methods to ignore by default on classes.\n+ * @param {Array} [opts.ignoreLines=false] enable ignore hints for lines (start, end).\n  * @param {object} [opts.inputSourceMap=undefined] the input source map, that maps the uninstrumented code back to the\n  * original code.\n  */\n@@ -756,7 +807,8 @@ function programVisitor(types, sourceFilePath = 'unknown.js', opts = {}) {\n         sourceFilePath,\n         opts.inputSourceMap,\n         opts.ignoreClassMethods,\n-        opts.reportLogic\n+        opts.reportLogic,\n+        opts.ignoreLines\n     );\n     return {\n         enter(path) {\n@@ -840,4 +892,29 @@ function programVisitor(types, sourceFilePath = 'unknown.js', opts = {}) {\n     };\n }\n \n+function originalPositionTryBoth(sourceMap, { line, column }) {\n+    const mapping = originalPositionFor(sourceMap, {\n+        line,\n+        column,\n+        bias: GREATEST_LOWER_BOUND\n+    });\n+    if (mapping.source === null) {\n+        return originalPositionFor(sourceMap, {\n+            line,\n+            column,\n+            bias: LEAST_UPPER_BOUND\n+        });\n+    } else {\n+        return mapping;\n+    }\n+}\n+\n+function tryReadFileSync(filename) {\n+    try {\n+        return readFileSync(filename, 'utf8');\n+    } catch (_) {\n+        return undefined;\n+    }\n+}\n+\n module.exports = programVisitor;\n"
  },
  {
    "path": "patches/istanbul-lib-source-maps.patch",
    "content": "diff --git a/CHANGELOG.md b/CHANGELOG.md\ndeleted file mode 100644\nindex dad8c06aac26cb8cfced31da5f35ac8e95915f15..0000000000000000000000000000000000000000\ndiff --git a/lib/get-mapping.js b/lib/get-mapping.js\nindex 187a02ed65104d8e3a058d6bfe7dc8bd7c285369..14d21ca5f933f3685e5b0a1be14dad6c9003fd76 100644\n--- a/lib/get-mapping.js\n+++ b/lib/get-mapping.js\n@@ -1,3 +1,5 @@\n+// Contains patch from https://github.com/istanbuljs/istanbuljs/pull/837\n+\n /*\n  Copyright 2015, Yahoo Inc.\n  Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.\n@@ -36,13 +38,27 @@ function originalEndPositionFor(sourceMap, generatedEnd) {\n     // generated file end location. Note however that this position on its\n     // own is not useful because it is the position of the _start_ of the range\n     // on the original file, and we want the _end_ of the range.\n-    const beforeEndMapping = originalPositionTryBoth(\n+    let beforeEndMapping = originalPositionTryBoth(\n         sourceMap,\n         generatedEnd.line,\n         generatedEnd.column - 1\n     );\n     if (beforeEndMapping.source === null) {\n-        return null;\n+        // search the previous lines as the mapping was not found on the same line\n+        for (\n+            let line = generatedEnd.line;\n+            line > 0 && beforeEndMapping.source === null;\n+            line--\n+        ) {\n+            beforeEndMapping = originalPositionTryBoth(\n+                sourceMap,\n+                line,\n+                Infinity\n+            );\n+        }\n+        if (beforeEndMapping.source === null) {\n+            return null;\n+        }\n     }\n \n     // Convert that original position back to a generated one, with a bump\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "catalogMode: prefer\nshellEmulator: true\ntrustPolicy: no-downgrade\ntrustPolicyExclude:\n  - semver@6.3.1\n  - chokidar@4.0.3\n  - webdriverio@9.20.0\n  - webdriver@9.20.0\n  - '@wdio/types@9.20.0'\n  - '@wdio/repl@9.16.2'\n  - '@wdio/utils@9.20.0'\n  - '@wdio/config@9.20.0'\n  - '@wdio/logger@9.18.0'\n  - '@wdio/protocols@9.16.2'\n  - undici-types@6.21.0\n  - undici@6.21.3\n  - rxjs@7.8.2\npackages:\n  - docs\n  - packages/*\n  - examples/*\n  - test/*\n  - test/cli/dts/*\n  - test/config/fixtures/conditions-pkg\noverrides:\n  '@types/node': $@types/node\n  '@vitest/browser': workspace:*\n  '@vitest/browser-playwright': workspace:*\n  '@vitest/browser-preview': workspace:*\n  '@vitest/browser-webdriverio': workspace:*\n  '@vitest/ui': workspace:*\n  acorn: 8.11.3\n  mlly: ^1.8.0\n  rollup: $rollup\n  vite: $vite\n  vitest: workspace:*\npatchedDependencies:\n  '@sinonjs/fake-timers@15.0.0': patches/@sinonjs__fake-timers@15.0.0.patch\n  acorn@8.11.3: patches/acorn@8.11.3.patch\n  cac@6.7.14: patches/cac@6.7.14.patch\n  istanbul-lib-instrument: patches/istanbul-lib-instrument.patch\n  istanbul-lib-source-maps: patches/istanbul-lib-source-maps.patch\ncatalog:\n  '@babel/core': ^7.29.0\n  '@babel/plugin-proposal-decorators': ^7.29.0\n  '@iconify-json/carbon': ^1.2.19\n  '@iconify-json/logos': ^1.2.10\n  '@iconify/vue': ^5.0.0\n  '@jridgewell/remapping': ^2.3.5\n  '@jridgewell/trace-mapping': 0.3.31\n  '@rolldown/plugin-babel': ^0.2.1\n  '@types/chai': ^5.2.2\n  '@types/estree': ^1.0.8\n  '@types/istanbul-lib-coverage': ^2.0.6\n  '@types/istanbul-lib-report': ^3.0.3\n  '@types/istanbul-lib-source-maps': ^4.0.4\n  '@types/istanbul-reports': ^3.0.4\n  '@types/ws': ^8.18.1\n  '@types/yauzl': ^2.10.3\n  '@unocss/reset': ^66.6.6\n  '@vitejs/plugin-vue': ^6.0.4\n  '@vueuse/core': ^14.2.1\n  acorn-walk: ^8.3.5\n  birpc: ^4.0.0\n  cac: ^6.7.14\n  chai: ^6.2.2\n  flatted: 3.4.0\n  istanbul-lib-coverage: ^3.2.2\n  istanbul-lib-report: ^3.0.1\n  istanbul-lib-source-maps: ^5.0.6\n  istanbul-reports: ^3.2.0\n  magic-string: ^0.30.21\n  magicast: ^0.5.2\n  msw: ^2.12.10\n  obug: ^2.1.1\n  pathe: ^2.0.3\n  playwright: ^1.58.2\n  sirv: ^3.0.2\n  std-env: ^4.0.0-rc.1\n  strip-literal: ^3.1.0\n  tinyexec: ^1.0.2\n  tinyglobby: ^0.2.15\n  tinyhighlight: ^0.3.2\n  tinyrainbow: ^3.0.3\n  tinyspy: ^4.0.4\n  typescript: ^5.9.3\n  unocss: ^66.6.6\n  vitest-sonar-reporter: 3.0.0\n  vue: ^3.5.29\n  ws: ^8.19.0\n  yauzl: ^3.2.0\nonlyBuiltDependencies:\n  - '@sveltejs/kit'\n  - '@swc/core'\n  - edgedriver\n  - esbuild\n  - geckodriver\n  - msw\n  - rolldown\n  - sharp\n  - svelte-preprocess\n  - vue-demi\npeerDependencyRules:\n  ignoreMissing:\n    - '@algolia/client-search'\n"
  },
  {
    "path": "scripts/build-utils.js",
    "content": "// @ts-check\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport dts from 'rollup-plugin-dts'\nimport isolatedDecl from 'unplugin-isolated-decl/rollup'\n\nexport function createDtsUtils({\n  isolatedDeclDir = '.types',\n  cleanupDir = '.types',\n} = {}) {\n  return {\n    /**\n     * @returns {import('rollup').Plugin[]} plugins\n     */\n    isolatedDecl() {\n      return [\n        isolatedDecl({\n          transformer: 'oxc',\n          transformOptions: { stripInternal: true },\n          // exclude direct imports to other package sources\n          include: path.join(process.cwd(), '**/*.ts'),\n          extraOutdir: isolatedDeclDir,\n        }),\n        {\n          name: 'isolated-decl-dts-extra',\n          resolveId(source) {\n            // silence node-resolve error by isolated-decl transform of type import\n            if (source.startsWith('vite/types/')) {\n              return { id: '/node_modules/', external: true }\n            }\n          },\n        },\n      ]\n    },\n    /**\n     * @returns {import('rollup').Plugin[]} plugins\n     */\n    dts() {\n      return [\n        dts({ respectExternal: true }),\n        {\n          name: 'isolated-decl-dts-extra',\n          buildEnd(error) {\n            // keep temporary type files on watch mode since removing them makes re-build flaky\n            if (!error && !this.meta.watchMode) {\n              fs.rmSync(`dist/${cleanupDir}`, { recursive: true, force: true })\n            }\n          },\n        },\n      ]\n    },\n    /**\n     * @param {Record<string, string> | string} input\n     */\n    dtsInput(input, { ext = 'ts' } = {}) {\n      if (typeof input === 'string') {\n        input = { index: '' }\n      }\n      return Object.fromEntries(\n        Object.keys(input).map(name => [\n          name,\n          `dist/${isolatedDeclDir}/${name}.d.${ext}`,\n        ]),\n      )\n    },\n  }\n}\n"
  },
  {
    "path": "scripts/explain-types.ts",
    "content": "import { readFileSync } from 'node:fs'\n\n// { dep: ['dep2'], dep2: [] }\nconst dependencies: Record<string, string[]> = {}\nconst content = readFileSync(process.argv[2], 'utf-8').split('\\n')\n\nlet lastKey = content[0]\nfor (let i = 1; i < content.length; i++) {\n  const line = content[i]\n  if (line.startsWith(' ')) {\n    const line = content[i].trim()\n    if (!line.startsWith('Imported via')) {\n      continue\n    }\n\n    const [_, __, from] = (line.includes('with')\n      ? /Imported via '(.*)' from file '(.*)' with/.exec(line)\n      : /Imported via '(.*)' from file '(.*)'/.exec(line)) ?? []\n\n    dependencies[from] ??= []\n    if (!dependencies[from].includes(lastKey)) {\n      dependencies[from].push(lastKey)\n    }\n  }\n  else {\n    lastKey = content[i]\n  }\n}\n\nfunction printTree(start: string, deps: string[], depth = 1, seen = new Set()) {\n  for (const dep of deps) {\n    if (seen.has(dep)) {\n      continue\n    }\n    seen.add(dep)\n    console.error('  '.repeat(depth) + dep)\n    const deps = dependencies[dep]\n    if (deps && !dep.includes('node_modules')) {\n      printTree(start, deps, depth + 1, seen)\n    }\n  }\n}\n\nfor (const key in dependencies) {\n  if (key.startsWith('src/client')) {\n    console.error(key)\n    printTree(key, dependencies[key])\n  }\n}\n"
  },
  {
    "path": "scripts/publish-ci.ts",
    "content": "#!/usr/bin/env zx\n\nimport { readFileSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { $ } from 'zx'\n\nif (process.env.VITEST_GENERATE_UI_TOKEN !== 'true' || process.env.VITE_TEST_WATCHER_DEBUG !== 'false') {\n  throw new Error(`Cannot release Vitest without VITEST_GENERATE_UI_TOKEN=${process.env.VITEST_GENERATE_UI_TOKEN} and VITE_TEST_WATCHER_DEBUG=${process.env.VITE_TEST_WATCHER_DEBUG} environment variable. `)\n}\n\nlet version = process.argv[2]\n\nif (!version) {\n  throw new Error('No tag specified')\n}\n\nif (version.startsWith('v')) {\n  version = version.slice(1)\n}\n\nconst pkgPath = fileURLToPath(new URL('../package.json', import.meta.url))\nconst pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))\n\nif (pkg.version !== version) {\n  throw new Error(\n    `Package version from tag \"${version}\" mismatches with the current version \"${pkg.version}\"`,\n  )\n}\n\nconst releaseTag = version.includes('beta')\n  ? 'beta'\n  : version.includes('alpha')\n    ? 'alpha'\n    : undefined\n\nconsole.log('Publishing version', version, 'with tag', releaseTag || 'latest')\n\nif (releaseTag) {\n  await $`pnpm -r publish --access public --no-git-checks --tag ${releaseTag}`\n}\nelse {\n  await $`pnpm -r publish --access public --no-git-checks`\n}\n"
  },
  {
    "path": "scripts/release.ts",
    "content": "#!/usr/bin/env zx\n\nimport { versionBump } from 'bumpp'\nimport { glob } from 'tinyglobby'\nimport { $ } from 'zx'\n\ntry {\n  const packages = await glob(['package.json', './packages/*/package.json'], { expandDirectories: false })\n\n  console.log('Bumping versions in packages:', packages.join(', '), '\\n')\n\n  const result = await versionBump({\n    files: packages,\n    commit: true,\n    push: true,\n    tag: true,\n  })\n\n  if (!result.newVersion.includes('beta')) {\n    console.log('Pushing to release branch')\n    await $`git update-ref refs/heads/release refs/heads/main`\n    await $`git push origin release`\n  }\n  console.log('New release is ready, waiting for conformation at https://github.com/vitest-dev/vitest/actions')\n}\ncatch (err) {\n  console.error(err)\n}\n"
  },
  {
    "path": "scripts/update-contributors.ts",
    "content": "import { promises as fs } from 'node:fs'\n\ninterface Contributor {\n  login: string\n}\n\nasync function fetchContributors(page = 1) {\n  const collaborators: string[] = []\n  const data = await (await fetch(`https://api.github.com/repos/vitest-dev/vitest/contributors?per_page=100&page=${page}`, {\n    headers: {\n      'content-type': 'application/json',\n    },\n  })).json() as Contributor[] || []\n  collaborators.push(...data.map(i => i.login))\n  if (data.length === 100) {\n    collaborators.push(...(await fetchContributors(page + 1)))\n  }\n  return collaborators.filter(name => !name.includes('[bot]'))\n}\n\nasync function generate() {\n  const collaborators = await fetchContributors()\n  await fs.writeFile('./docs/.vitepress/contributor-names.json', `${JSON.stringify(collaborators, null, 2)}\\n`, 'utf8')\n}\n\ngenerate()\n"
  },
  {
    "path": "shims.d.ts",
    "content": "/// <reference path=\"./packages/vitest/importMeta.d.ts\" />\n"
  },
  {
    "path": "test/README.md",
    "content": "Tests are split by categories. Default categories are:\n\n## core\n\nThese tests are running in different pools with a single config file. If you just need to test a function call, you can place your test here.\n\nThis is the only test category that doesn't start new Vitest instance for every test.\n\n## config\n\nPlace your test here if you are testing a config option.\n\n## cli\n\nIf you are testing a complex interaction, place your tests here.\nType-focused fixtures live under `test/cli/dts/`.\n\n## browser\n\nIf you are testing browser mode, add your tests here.\n\n## ui\n\nThese are e2e tests for UI package. We are using `playwright` to test it.\n\n## watch\n\nPlace your tests here if you are testing Vitest behaviour when file is created/updated/removed.\n\n----\n\nAll other categories just group tests by type.\n"
  },
  {
    "path": "test/browser/README.md",
    "content": "# Browser Tests\n\n```sh\n# run full test with all providers and all browsers\npnpm run test\n\n# run only playwright provider + all browsers\npnpm run test:playwright\n\n# run only playwright provider + chromium\nBROWSER=chromium pnpm run test:playwright\n\n# run specific fixture (default is playwright provider + all browsers)\npnpm run test-fixtures --root ./fixtures/locators\n\n# run specific fixture with selected provider and browser\nPROVIDER=webdriverio BROWSER=firefox pnpm run test-fixtures --root ./fixtures/locators\n```\n\n## Using docker playwright\n\nSome test suites don't support running it remotely (`fixtures/inspect` and `fixtures/insecure-context`).\n\n```sh\n# Start playwright browser server\npnpm docker up -d\n\n# Run tests with BROWSER_WS_ENDPOINT\nBROWSER_WS_ENDPOINT=true pnpm run test:playwright\n```\n"
  },
  {
    "path": "test/browser/bundled-lib/package.json",
    "content": "{\n  \"name\": \"@vitest/bundled-lib\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"main\": \"./src/index.js\"\n}\n"
  },
  {
    "path": "test/browser/bundled-lib/src/a.js",
    "content": "export function a() {\n  return 'a'\n}\n"
  },
  {
    "path": "test/browser/bundled-lib/src/b.js",
    "content": "export function b() {\n  throw new Error('error from b')\n}\n"
  },
  {
    "path": "test/browser/bundled-lib/src/index.d.ts",
    "content": "export declare function index(): string\n"
  },
  {
    "path": "test/browser/bundled-lib/src/index.js",
    "content": "import { a } from './a.js'\nimport { b } from './b.js'\n\nexport function index() {\n  return a() + b()\n}\n"
  },
  {
    "path": "test/browser/cjs-lib/index.js",
    "content": "module.exports = {\n  a: 'a',\n  b: 'b',\n  object: {\n    h: 'h',\n  },\n}\n"
  },
  {
    "path": "test/browser/cjs-lib/lib.d.ts",
    "content": "export function lib(): string\n"
  },
  {
    "path": "test/browser/cjs-lib/lib.mjs",
    "content": "export function lib() {\n  return 'original'\n}\n"
  },
  {
    "path": "test/browser/cjs-lib/package.json",
    "content": "{\n  \"name\": \"@vitest/cjs-lib\",\n  \"type\": \"commonjs\",\n  \"exports\": {\n    \"./lib\": {\n      \"types\": \"./lib.d.ts\",\n      \"default\": \"./lib.mjs\"\n    },\n    \".\": \"./index.js\"\n  }\n}\n"
  },
  {
    "path": "test/browser/custom-diff-config.ts",
    "content": "export default {\n  aAnnotation: 'Expected to be',\n  bAnnotation: 'But got',\n}\n"
  },
  {
    "path": "test/browser/custom-snapshot-env.ts",
    "content": "throw new Error('This file should not be executed')\n"
  },
  {
    "path": "test/browser/custom-tester.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Document</title>\n  <script type=\"text/javascript\">\n    globalThis.__injected = []\n  </script>\n  <script>\n    __injected.push(1)\n  </script>\n  <style>\n    html {\n      padding: 0;\n      margin: 0;\n    }\n    body {\n      padding: 0;\n      margin: 0;\n      min-height: 100vh;\n    }\n  </style>\n  <script type=\"module\" src=\"./injected.ts\"></script>\n</head>\n<body>\n\n</body>\n</html>"
  },
  {
    "path": "test/browser/deps/test-dep-error/index.js",
    "content": "export function throwDepError() {\n  throw new Error('this is test dependency error')\n}\n"
  },
  {
    "path": "test/browser/deps/test-dep-error/package.json",
    "content": "{\n  \"name\": \"test-dep-error\",\n  \"type\": \"module\",\n  \"version\": \"0.0.0\",\n  \"exports\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/browser/docker-compose.yaml",
    "content": "services:\n  playwright:\n    image: mcr.microsoft.com/playwright:v1.58.2-noble\n    command: /bin/sh -c \"npx -y playwright@1.58.1 run-server --port 6677 --host 0.0.0.0\"\n    init: true\n    ipc: host\n    user: pwuser\n    ports:\n      - '6677:6677'\n\n  # This setup employs simpler and robust `network_mode: host` instead of port mapping.\n  # This supports debug inspector, which can only bind to 127.0.0.1.\n  # `connectOptions.exposeNetwork: '<loopback>'` is also not needed for this setup.\n  # Note that `network_mode: host` is supported only on Linux Docker.\n  # Run it by:\n  #   pnpm run docker up playwright-host\n  playwright-host:\n    image: mcr.microsoft.com/playwright:v1.58.2-noble\n    command: /bin/sh -c \"npx -y playwright@1.58.1 run-server --port 6677\"\n    init: true\n    ipc: host\n    user: pwuser\n    network_mode: host\n    profiles: [host]\n"
  },
  {
    "path": "test/browser/fixtures/assertion-helper/basic.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\nconst myEqual = vi.defineHelper((a: any, b: any) => {\n  expect(a).toEqual(b)\n})\n\nconst myEqualAsync = vi.defineHelper(async (a: any, b: any) => {\n  await new Promise(r => setTimeout(r, 1))\n  expect(a).toEqual(b)\n})\n\nconst myEqualSoft = vi.defineHelper((a: any, b: any) => {\n  expect.soft(a).toEqual(b)\n})\n\nconst myEqualSoftAsync = vi.defineHelper(async (a: any, b: any) => {\n  await new Promise(r => setTimeout(r, 1))\n  expect.soft(a).toEqual(b)\n})\n\ntest('sync', () => {\n  myEqual('sync', 'x')\n})\n\ntest('async', async () => {\n  await myEqualAsync('async', 'x')\n})\n\ntest('soft', () => {\n  myEqualSoft('soft', 'x')\n})\n\ntest('soft async', async () => {\n  await myEqualSoftAsync('soft async', 'x')\n})\n"
  },
  {
    "path": "test/browser/fixtures/assertion-helper/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL('./node_modules/.vite', import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/benchmark/basic.bench.ts",
    "content": "import { bench, describe } from 'vitest'\n\ndescribe('suite-a', () => {\n  bench('good', async () => {\n    await sleep(10)\n  }, options)\n\n  bench('bad', async () => {\n    await sleep(300)\n  }, options)\n})\n\ndescribe('suite-b', () => {\n  bench('good', async () => {\n    await sleep(25)\n  }, options)\n\n  describe('suite-b-nested', () => {\n    bench('good', async () => {\n      await sleep(50)\n    }, options)\n  })\n})\n\nconst sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));\n\nconst options = {\n  time: 0,\n  iterations: 2,\n  warmupIterations: 0,\n  warmupTime: 0,\n}\n"
  },
  {
    "path": "test/browser/fixtures/benchmark/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      headless: true,\n      provider,\n      instances,\n    },\n  },\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n})\n"
  },
  {
    "path": "test/browser/fixtures/broken-iframe/submit-form.test.ts",
    "content": "import { userEvent } from 'vitest/browser';\nimport { test } from 'vitest';\n\ntest('submitting a form reloads the iframe with \"?\" query', async () => {\n  const form = document.createElement('form')\n  document.body.append(form)\n  form.id = 'form'\n  const button = document.createElement('button')\n  button.id = 'button'\n  form.append(button)\n  await userEvent.click(button)\n})\n"
  },
  {
    "path": "test/browser/fixtures/broken-iframe/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { provider, instances } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      headless: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/browser-crash/browser-crash.test.ts",
    "content": "import { commands } from 'vitest/browser'\nimport { it } from 'vitest'\n\ndeclare module 'vitest/browser' {\n  interface BrowserCommands {\n    forceCrash: () => Promise<void>\n  }\n}\n\nit('fails gracefully when browser crashes', async () => {\n  await commands.forceCrash()\n})\n"
  },
  {
    "path": "test/browser/fixtures/browser-crash/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\nimport { BrowserCommand } from 'vitest/node'\n\nconst forceCrash: BrowserCommand<[]> = async (context) => {\n  if (context.provider.name === 'playwright') {\n    const browser = context.context.browser().browserType().name()\n    if (browser === 'chromium') {\n      await context.page.goto('chrome://crash')\n    }\n\n    if (browser === 'firefox') {\n      await context.page.goto('about:crashcontent')\n    }\n\n    throw new Error(`Browser crash not supported for ${browser}`)\n  }\n  if (context.provider.name === 'webdriverio') {\n    const browser = context.browser\n    const name = context.project.config.browser.name\n    if (name === 'chrome') {\n      await browser.url('chrome://crash')\n    }\n    if (name === 'firefox') {\n      await browser.url('about:crashcontent')\n    }\n    throw new Error(`Browser crash not supported for ${name}`)\n  }\n}\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      commands: { forceCrash },\n      enabled: true,\n      provider,\n      instances: instances.filter(i => i.browser !== 'webkit').map(instance => ({\n        ...instance,\n        context: {\n          actionTimeout: 500,\n        },\n      })),\n    },\n    expect: {\n      poll: {\n        timeout: 500,\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/error-in-dep/basic.test.ts",
    "content": "import { throwDepError } from 'test-dep-error'\nimport { test } from 'vitest'\n\ntest('fail', () => {\n  throwDepError()\n})\n"
  },
  {
    "path": "test/browser/fixtures/error-in-dep/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL('./node_modules/.vite', import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      headless: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/expect-dom/setup.ts",
    "content": "import { expect } from 'vitest';\n\n// Valid string terminator sequences are BEL, ESC\\, and 0x9c\nconst ST = '(?:\\\\u0007|\\\\u001B\\\\u005C|\\\\u009C)';\nconst pattern = [\n  `[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]+)*|[a-zA-Z\\\\d]+(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?${ST})`,\n  '(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-nq-uy=><~]))',\n].join('|');\n\nconst ansiRegexp = new RegExp(pattern, 'g');\n\nfunction stripAnsi(string: string) {\n\treturn string.replace(ansiRegexp, '');\n}\n\nexpect.addSnapshotSerializer({\n  test: (val) => typeof val === 'string' || val instanceof Error,\n  print: (val: string | Error) => typeof val === 'string'\n    ? stripAnsi(val)\n    : `[${val.name}: ${stripAnsi(val.message)}]`,\n})\n"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toBeChecked.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { render } from './utils'\n\ndescribe('.toBeChecked', () => {\n  test('handles checkbox input', () => {\n    const {queryByTestId} = render(`\n        <input type=\"checkbox\" checked data-testid=\"input-checkbox-checked\" />\n        <input type=\"checkbox\" data-testid=\"input-checkbox-unchecked\" />\n    `)\n\n    expect(queryByTestId('input-checkbox-checked')).toBeChecked()\n    expect(queryByTestId('input-checkbox-unchecked')).not.toBeChecked()\n  })\n\n  test('handles radio input', () => {\n    const {queryByTestId} = render(`\n        <input type=\"radio\" checked value=\"foo\" data-testid=\"input-radio-checked\" />\n        <input type=\"radio\" value=\"foo\" data-testid=\"input-radio-unchecked\" />\n    `)\n\n    expect(queryByTestId('input-radio-checked')).toBeChecked()\n    expect(queryByTestId('input-radio-unchecked')).not.toBeChecked()\n  })\n\n  test('handles element with role=\"checkbox\"', () => {\n    const {queryByTestId} = render(`\n        <div role=\"checkbox\" aria-checked=\"true\" data-testid=\"aria-checkbox-checked\" />\n        <div role=\"checkbox\" aria-checked=\"false\" data-testid=\"aria-checkbox-unchecked\" />\n    `)\n\n    expect(queryByTestId('aria-checkbox-checked')).toBeChecked()\n    expect(queryByTestId('aria-checkbox-unchecked')).not.toBeChecked()\n  })\n\n  test('handles element with role=\"radio\"', () => {\n    const {queryByTestId} = render(`\n        <div role=\"radio\" aria-checked=\"true\" data-testid=\"aria-radio-checked\" />\n        <div role=\"radio\" aria-checked=\"false\" data-testid=\"aria-radio-unchecked\" />\n    `)\n\n    expect(queryByTestId('aria-radio-checked')).toBeChecked()\n    expect(queryByTestId('aria-radio-unchecked')).not.toBeChecked()\n  })\n\n  test('handles element with role=\"switch\"', () => {\n    const {queryByTestId} = render(`\n        <div role=\"switch\" aria-checked=\"true\" data-testid=\"aria-switch-checked\" />\n        <div role=\"switch\" aria-checked=\"false\" data-testid=\"aria-switch-unchecked\" />\n    `)\n\n    expect(queryByTestId('aria-switch-checked')).toBeChecked()\n    expect(queryByTestId('aria-switch-unchecked')).not.toBeChecked()\n  })\n\n  test('handles element with role=\"menuitemcheckbox\"', () => {\n    const {queryByTestId} = render(`\n        <div role=\"menuitemcheckbox\" aria-checked=\"true\" data-testid=\"aria-menuitemcheckbox-checked\" />\n        <div role=\"menuitemcheckbox\" aria-checked=\"false\" data-testid=\"aria-menuitemcheckbox-unchecked\" />\n    `)\n\n    expect(queryByTestId('aria-menuitemcheckbox-checked')).toBeChecked()\n    expect(queryByTestId('aria-menuitemcheckbox-unchecked')).not.toBeChecked()\n  })\n\n  test('throws when checkbox input is checked but expected not to be', () => {\n    const {queryByTestId} = render(\n      `<input type=\"checkbox\" checked data-testid=\"input-checked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('input-checked')).not.toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when input checkbox is not checked but expected to be', () => {\n    const {queryByTestId} = render(\n      `<input type=\"checkbox\" data-testid=\"input-empty\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('input-empty')).toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"checkbox\" is checked but expected not to be', () => {\n    const {queryByTestId} = render(\n      `<div role=\"checkbox\" aria-checked=\"true\" data-testid=\"aria-checkbox-checked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-checkbox-checked')).not.toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"checkbox\" is not checked but expected to be', () => {\n    const {queryByTestId} = render(\n      `<div role=\"checkbox\" aria-checked=\"false\" data-testid=\"aria-checkbox-unchecked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-checkbox-unchecked')).toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when radio input is checked but expected not to be', () => {\n    const {queryByTestId} = render(\n      `<input type=\"radio\" checked data-testid=\"input-radio-checked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('input-radio-checked')).not.toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when input radio is not checked but expected to be', () => {\n    const {queryByTestId} = render(\n      `<input type=\"radio\" data-testid=\"input-radio-unchecked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('input-radio-unchecked')).toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"radio\" is checked but expected not to be', () => {\n    const {queryByTestId} = render(\n      `<div role=\"radio\" aria-checked=\"true\" data-testid=\"aria-radio-checked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-radio-checked')).not.toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"radio\" is not checked but expected to be', () => {\n    const {queryByTestId} = render(\n      `<div role=\"radio\" aria-checked=\"false\" data-testid=\"aria-radio-unchecked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-checkbox-unchecked')).toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"switch\" is checked but expected not to be', () => {\n    const {queryByTestId} = render(\n      `<div role=\"switch\" aria-checked=\"true\" data-testid=\"aria-switch-checked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-switch-checked')).not.toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"switch\" is not checked but expected to be', () => {\n    const {queryByTestId} = render(\n      `<div role=\"switch\" aria-checked=\"false\" data-testid=\"aria-switch-unchecked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-switch-unchecked')).toBeChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"checkbox\" has an invalid aria-checked attribute', () => {\n    const {queryByTestId} = render(\n      `<div role=\"checkbox\" aria-checked=\"something\" data-testid=\"aria-checkbox-invalid\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-checkbox-invalid')).toBeChecked(),\n    ).toThrow(\n      /only inputs with .* a valid aria-checked attribute can be used/,\n    )\n  })\n\n  test('throws when element with role=\"radio\" has an invalid aria-checked attribute', () => {\n    const {queryByTestId} = render(\n      `<div role=\"radio\" aria-checked=\"something\" data-testid=\"aria-radio-invalid\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-radio-invalid')).toBeChecked(),\n    ).toThrow(\n      /only inputs with .* a valid aria-checked attribute can be used/,\n    )\n  })\n\n  test('throws when element with role=\"switch\" has an invalid aria-checked attribute', () => {\n    const {queryByTestId} = render(\n      `<div role=\"switch\" aria-checked=\"something\" data-testid=\"aria-switch-invalid\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-switch-invalid')).toBeChecked(),\n    ).toThrow(\n      /only inputs with .* a valid aria-checked attribute can be used/,\n    )\n  })\n\n  test('throws when the element is not an input', () => {\n    const {queryByTestId} = render(`<select data-testid=\"select\"></select>`)\n    expect(() => expect(queryByTestId('select')).toBeChecked()).toThrow(\n      /only inputs with type=\"checkbox\" or type=\"radio\" or elements with.* role=\"checkbox\".* role=\"menuitemcheckbox\".* role=\"option\".* role=\"radio\".* role=\"switch\".* role=\"menuitemradio\".* role=\"treeitem\" .* can be used/,\n    )\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toBeDisabled.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { render } from './utils'\n\nconst window = document.defaultView\n\nwindow.customElements.define(\n  'custom-element',\n  class extends window.HTMLElement {},\n)\n\ntest('.toBeDisabled', () => {\n  const {queryByTestId} = render(`\n    <div>\n      <button disabled={true} data-testid=\"button-element\">x</button>\n      <textarea disabled={true} data-testid=\"textarea-element\"></textarea>\n      <input type=\"checkbox\" disabled={true} data-testid=\"input-element\" />\n\n      <fieldset disabled={true} data-testid=\"fieldset-element\">\n        <button data-testid=\"fieldset-child-element\">x</button>\n      </fieldset>\n\n      <div disabled={true} data-testid=\"div-element\">\n        <button data-testid=\"div-child-element\">x</button>\n      </div>\n\n      <fieldset disabled={true}>\n        <div>\n          <button data-testid=\"nested-form-element\">x</button>\n\n          <select data-testid=\"deep-select-element\">\n            <optgroup data-testid=\"deep-optgroup-element\">\n              <option data-testid=\"deep-option-element\">x</option>\n            </optgroup>\n          </select>\n        </div>\n        <a href=\"http://github.com\" data-testid=\"deep-a-element\">x</a>\n      </fieldset>\n\n      <a href=\"http://github.com\" disabled={true} data-testid=\"a-element\">x</a>\n    </div>\n    `)\n\n  expect(queryByTestId('button-element')).toBeDisabled()\n  expect(() =>\n    expect(queryByTestId('button-element')).not.toBeDisabled(),\n  ).toThrow()\n  expect(queryByTestId('textarea-element')).toBeDisabled()\n  expect(queryByTestId('input-element')).toBeDisabled()\n\n  // technically, everything inside a disabled fieldset is disabled,\n  // but the fieldset itself is not considered disabled, because its\n  // native tag is not part of\n  // https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings\n  // NOTE: this is different from jest-dom, but closer to how PW works\n  expect(queryByTestId('fieldset-element')).not.toBeDisabled()\n  expect(queryByTestId('fieldset-child-element')).toBeDisabled()\n\n  expect(queryByTestId('div-element')).not.toBeDisabled()\n  expect(queryByTestId('div-child-element')).not.toBeDisabled()\n\n  expect(queryByTestId('nested-form-element')).toBeDisabled()\n  expect(queryByTestId('deep-select-element')).toBeDisabled()\n  expect(queryByTestId('deep-optgroup-element')).toBeDisabled()\n  expect(queryByTestId('deep-option-element')).toBeDisabled()\n\n  expect(queryByTestId('a-element')).not.toBeDisabled()\n  expect(queryByTestId('deep-a-element')).not.toBeDisabled()\n  expect(() => expect(queryByTestId('a-element')).toBeDisabled()).toThrow()\n  expect(() =>\n    expect(queryByTestId('deep-a-element')).toBeDisabled(),\n  ).toThrow()\n})\n\ntest('.toBeDisabled fieldset>legend', () => {\n  const {queryByTestId} = render(`\n    <div>\n      <fieldset disabled={true}>\n        <button data-testid=\"inherited-element\">x</button>\n      </fieldset>\n\n      <fieldset disabled={true}>\n        <legend>\n          <button data-testid=\"inside-legend-element\">x</button>\n        </legend>\n      </fieldset>\n\n      <fieldset disabled={true}>\n        <legend>\n          <div>\n            <button data-testid=\"nested-inside-legend-element\">x</button>\n          </div>\n        </legend>\n      </fieldset>\n\n      <fieldset disabled={true}>\n        <div></div>\n        <legend>\n          <button data-testid=\"first-legend-element\">x</button>\n        </legend>\n        <legend>\n          <button data-testid=\"second-legend-element\">x</button>\n        </legend>\n      </fieldset>\n\n      <fieldset disabled={true}>\n        <fieldset>\n          <legend>\n            <button data-testid=\"outer-fieldset-element\">x</button>\n          </legend>\n        </fieldset>\n      </fieldset>\n    </div>\n    `)\n\n  expect(queryByTestId('inherited-element')).toBeDisabled()\n  expect(queryByTestId('inside-legend-element')).not.toBeDisabled()\n  expect(queryByTestId('nested-inside-legend-element')).not.toBeDisabled()\n\n  expect(queryByTestId('first-legend-element')).not.toBeDisabled()\n  expect(queryByTestId('second-legend-element')).toBeDisabled()\n\n  expect(queryByTestId('outer-fieldset-element')).toBeDisabled()\n})\n\ntest('.toBeDisabled custom element', () => {\n  const {queryByTestId} = render(`\n    <custom-element data-testid=\"disabled-custom-element\" disabled=\"\"></custom-element>\n    <custom-element data-testid=\"enabled-custom-element\"></custom-element>\n  `)\n\n  expect(queryByTestId('disabled-custom-element')).toBeDisabled()\n  expect(() => {\n    expect(queryByTestId('disabled-custom-element')).not.toBeDisabled()\n  }).toThrow('element is disabled')\n\n  expect(queryByTestId('enabled-custom-element')).not.toBeDisabled()\n  expect(() => {\n    expect(queryByTestId('enabled-custom-element')).toBeDisabled()\n  }).toThrow('element is not disabled')\n})\n\ntest('.toBeEnabled', () => {\n  const {queryByTestId} = render(`\n    <div>\n      <button disabled={true} data-testid=\"button-element\">x</button>\n      <textarea disabled={true} data-testid=\"textarea-element\"></textarea>\n      <input type=\"checkbox\" disabled={true} data-testid=\"input-element\" />\n\n      <fieldset disabled={true} data-testid=\"fieldset-element\">\n        <button data-testid=\"fieldset-child-element\">x</button>\n      </fieldset>\n\n      <div disabled={true} data-testid=\"div-element\">\n        <button data-testid=\"div-child-element\">x</button>\n      </div>\n\n      <fieldset disabled={true}>\n        <div>\n          <button data-testid=\"nested-form-element\">x</button>\n\n          <select data-testid=\"deep-select-element\">\n            <optgroup data-testid=\"deep-optgroup-element\">\n              <option data-testid=\"deep-option-element\">x</option>\n            </optgroup>\n          </select>\n        </div>\n        <a href=\"http://github.com\" data-testid=\"deep-a-element\">x</a>\n      </fieldset>\n\n      <a href=\"http://github.com\" disabled={true} data-testid=\"a-element\">x</a>\n    </div>\n    `)\n\n  expect(() => {\n    expect(queryByTestId('button-element')).toBeEnabled()\n  }).toThrow()\n  expect(queryByTestId('button-element')).not.toBeEnabled()\n  expect(() => {\n    expect(queryByTestId('textarea-element')).toBeEnabled()\n  }).toThrow()\n  expect(() => {\n    expect(queryByTestId('input-element')).toBeEnabled()\n  }).toThrow()\n\n  expect(() => {\n    // fieldset elements can't be considered disabled, only their children\n    expect(queryByTestId('fieldset-element')).toBeDisabled()\n  }).toThrow()\n  expect(() => {\n    expect(queryByTestId('fieldset-child-element')).toBeEnabled()\n  }).toThrow()\n\n  expect(queryByTestId('div-element')).toBeEnabled()\n  expect(queryByTestId('div-child-element')).toBeEnabled()\n\n  expect(() => {\n    expect(queryByTestId('nested-form-element')).toBeEnabled()\n  }).toThrow()\n  expect(() => {\n    expect(queryByTestId('deep-select-element')).toBeEnabled()\n  }).toThrow()\n  expect(() => {\n    expect(queryByTestId('deep-optgroup-element')).toBeEnabled()\n  }).toThrow()\n  expect(() => {\n    expect(queryByTestId('deep-option-element')).toBeEnabled()\n  }).toThrow()\n\n  expect(queryByTestId('a-element')).toBeEnabled()\n  expect(() =>\n    expect(queryByTestId('a-element')).not.toBeEnabled(),\n  ).toThrow()\n  expect(queryByTestId('deep-a-element')).toBeEnabled()\n  expect(() =>\n    expect(queryByTestId('deep-a-element')).not.toBeEnabled(),\n  ).toThrow()\n})\n\ntest('.toBeEnabled fieldset>legend', () => {\n  const {queryByTestId} = render(`\n    <div>\n      <fieldset disabled={true}>\n        <button data-testid=\"inherited-element\">x</button>\n      </fieldset>\n\n      <fieldset disabled={true}>\n        <legend>\n          <button data-testid=\"inside-legend-element\">x</button>\n        </legend>\n      </fieldset>\n\n      <fieldset disabled={true}>\n        <legend>\n          <div>\n            <button data-testid=\"nested-inside-legend-element\">x</button>\n          </div>\n        </legend>\n      </fieldset>\n\n      <fieldset disabled={true}>\n        <div></div>\n        <legend>\n          <button data-testid=\"first-legend-element\">x</button>\n        </legend>\n        <legend>\n          <button data-testid=\"second-legend-element\">x</button>\n        </legend>\n      </fieldset>\n\n      <fieldset disabled={true}>\n        <fieldset>\n          <legend>\n            <button data-testid=\"outer-fieldset-element\">x</button>\n          </legend>\n        </fieldset>\n      </fieldset>\n    </div>\n    `)\n\n  expect(() => {\n    expect(queryByTestId('inherited-element')).toBeEnabled()\n  }).toThrow()\n  expect(queryByTestId('inside-legend-element')).toBeEnabled()\n  expect(queryByTestId('nested-inside-legend-element')).toBeEnabled()\n\n  expect(queryByTestId('first-legend-element')).toBeEnabled()\n  expect(() => {\n    expect(queryByTestId('second-legend-element')).toBeEnabled()\n  }).toThrow()\n\n  expect(() => {\n    expect(queryByTestId('outer-fieldset-element')).toBeEnabled()\n  }).toThrow()\n})\n\ntest('.toBeEnabled custom element', () => {\n  const {queryByTestId} = render(`\n    <custom-element data-testid=\"disabled-custom-element\" disabled=\"\"></custom-element>\n    <custom-element data-testid=\"enabled-custom-element\"></custom-element>\n  `)\n\n  expect(queryByTestId('disabled-custom-element')).not.toBeEnabled()\n  expect(() => {\n    expect(queryByTestId('disabled-custom-element')).toBeEnabled()\n  }).toThrow('element is not enabled')\n\n  expect(queryByTestId('enabled-custom-element')).toBeEnabled()\n  expect(() => {\n    expect(queryByTestId('enabled-custom-element')).not.toBeEnabled()\n  }).toThrow('element is enabled')\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toBeEmptyDOMElement.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { render } from './utils'\n\ntest('.toBeEmptyDOMElement', () => {\n  const {queryByTestId} = render(`\n    <span data-testid=\"not-empty\">\n        <span data-testid=\"empty\"></span>\n        <svg data-testid=\"svg-empty\"></svg>\n    </span>\n    <span data-testid=\"with-comment\"><!-- This Comment --></span>\n    <span data-testid=\"with-multiple-comments\"><!-- Comment1 --><!-- Comment2 --></span>\n    <span data-testid=\"with-element\"><span></span></span>\n    <span data-testid=\"with-element-and-comment\"><!--Comment--><span></span></span>\n    <span data-testid=\"with-whitespace\"> </span>\n    <span data-testid=\"with-text\">Text</span>`)\n\n  const empty = queryByTestId('empty')\n  const notEmpty = queryByTestId('not-empty')\n  const svgEmpty = queryByTestId('svg-empty')\n  const withComment = queryByTestId('with-comment')\n  const withMultipleComments = queryByTestId('with-multiple-comments')\n  const withElement = queryByTestId('with-element')\n  const withElementAndComment = queryByTestId('with-element-and-comment')\n  const withWhitespace = queryByTestId('with-whitespace')\n  const withText = queryByTestId('with-whitespace')\n  const nonExistantElement = queryByTestId('not-exists')\n  const fakeElement = {thisIsNot: 'an html element'}\n\n  expect(empty).toBeEmptyDOMElement()\n  expect(svgEmpty).toBeEmptyDOMElement()\n  expect(notEmpty).not.toBeEmptyDOMElement()\n  expect(withComment).toBeEmptyDOMElement()\n  expect(withMultipleComments).toBeEmptyDOMElement()\n  expect(withElement).not.toBeEmptyDOMElement()\n  expect(withElementAndComment).not.toBeEmptyDOMElement()\n  expect(withWhitespace).not.toBeEmptyDOMElement()\n  expect(withText).not.toBeEmptyDOMElement()\n\n  // negative test cases wrapped in throwError assertions for coverage.\n  expect(() => expect(empty).not.toBeEmptyDOMElement()).toThrow()\n\n  expect(() => expect(svgEmpty).not.toBeEmptyDOMElement()).toThrow()\n\n  expect(() => expect(notEmpty).toBeEmptyDOMElement()).toThrow()\n\n  expect(() => expect(withComment).not.toBeEmptyDOMElement()).toThrow()\n\n  expect(() => expect(withMultipleComments).not.toBeEmptyDOMElement()).toThrow()\n\n  expect(() => expect(withElement).toBeEmptyDOMElement()).toThrow()\n\n  expect(() => expect(withElementAndComment).toBeEmptyDOMElement()).toThrow()\n\n  expect(() => expect(withWhitespace).toBeEmptyDOMElement()).toThrow()\n\n  expect(() => expect(withText).toBeEmptyDOMElement()).toThrow()\n\n  expect(() => expect(fakeElement).toBeEmptyDOMElement()).toThrow()\n\n  expect(() => {\n    expect(nonExistantElement).toBeEmptyDOMElement()\n  }).toThrow()\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toBeInTheDocument.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { page } from 'vitest/browser'\n\ntest('.toBeInTheDocument', () => {\n  const window = document.defaultView\n\n  window.customElements.define(\n    'custom-element-document',\n    class extends window.HTMLElement {\n      constructor() {\n        super()\n        this.attachShadow({mode: 'open'}).innerHTML =\n          '<div data-testid=\"custom-element-child\"></div>'\n      }\n    },\n  )\n\n  document.body.innerHTML = `\n    <span data-testid=\"html-element\"><span>Html Element</span></span>\n    <svg data-testid=\"svg-element\"></svg>\n    <custom-element-document data-testid=\"custom-element\"></custom-element-document>`\n\n  const htmlElement = document.querySelector('[data-testid=\"html-element\"]')\n  const svgElement = document.querySelector('[data-testid=\"svg-element\"]')\n  const customElementChild = document\n    .querySelector('[data-testid=\"custom-element\"]')\n    .shadowRoot.querySelector('[data-testid=\"custom-element-child\"]')\n  const detachedElement = document.createElement('div')\n  const fakeElement = {thisIsNot: 'an html element'}\n  const undefinedElement = undefined\n  const nullElement = null\n\n  expect(htmlElement).toBeInTheDocument()\n  expect(svgElement).toBeInTheDocument()\n  expect(customElementChild).toBeInTheDocument()\n  expect(detachedElement).not.toBeInTheDocument()\n  expect(nullElement).not.toBeInTheDocument()\n\n  expect(page.getByTestId('non-existing')).not.toBeInTheDocument()\n\n  // negative test cases wrapped in throwError assertions for coverage.\n  const expectToBe = /expect.*\\.toBeInTheDocument/\n  const expectNotToBe = /expect.*not\\.toBeInTheDocument/\n  const userInputNode = /an HTMLElement or an SVGElement/\n  const notFound = /element could not be found in the document/\n  expect(() => expect(htmlElement).not.toBeInTheDocument()).toThrow(\n    expectNotToBe,\n  )\n  expect(() => expect(svgElement).not.toBeInTheDocument()).toThrow(\n    expectNotToBe,\n  )\n  expect(() => expect(detachedElement).toBeInTheDocument()).toThrow(\n    expectToBe,\n  )\n  expect(() => expect(fakeElement).toBeInTheDocument()).toThrow(\n    userInputNode,\n  )\n  expect(() => expect(nullElement).toBeInTheDocument()).toThrow(\n    notFound,\n  )\n  expect(() => expect(undefinedElement).toBeInTheDocument()).toThrow(\n    notFound,\n  )\n  expect(() => expect(undefinedElement).not.toBeInTheDocument()).not.toThrow()\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toBeInViewport.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { render } from './utils'\n\ndescribe('toBeInViewport', () => {\n  it('should work', async () => {\n    // Apply margin and width to small element, and padding to body and html because firefox's rendering causes a bit space between the element and the viewport\n    const { container } = render(`\n      <style>body, html { padding: 30px; }</style>\n      <div id=\"big\" style=\"height: 10000px;\"></div>\n      <div id=\"small\" style=\"width: 50px; margin: 30px;\">foo</div>\n    `)\n\n    await expect(container.querySelector('#big')).toBeInViewport()\n    await expect(container.querySelector('#small')).not.toBeInViewport()\n    \n    // Scroll to make small element visible\n    container.querySelector('#small')?.scrollIntoView()\n    await expect(container.querySelector('#small')).toBeInViewport()\n    await expect(container.querySelector('#small')).toBeInViewport({ ratio: 1 })\n  })\n\n  it('should respect ratio option', async () => {\n    const { container } = render(`\n      <style>body, div, html { padding: 0; margin: 0; }</style>\n      <div id=\"big\" style=\"height: 400vh;\"></div>\n    `)\n\n    await expect(container.querySelector('div')).toBeInViewport()\n    await expect(container.querySelector('div')).toBeInViewport({ ratio: 0.1 })\n    await expect(container.querySelector('div')).toBeInViewport({ ratio: 0.2 })\n    await expect(container.querySelector('div')).toBeInViewport({ ratio: 0.24 })\n    \n    // In this test, element's ratio is approximately 0.25 (viewport height / element height = 100vh / 400vh = 0.25)\n    // IntersectionObserver may return slightly different values due to browser rendering\n    await expect(container.querySelector('div')).toBeInViewport({ ratio: 0.24 })\n    await expect(container.querySelector('div')).not.toBeInViewport({ ratio: 0.26 })\n    \n    await expect(container.querySelector('div')).not.toBeInViewport({ ratio: 0.3 })\n    await expect(container.querySelector('div')).not.toBeInViewport({ ratio: 0.7 })\n    await expect(container.querySelector('div')).not.toBeInViewport({ ratio: 0.8 })\n  })\n\n  it('should report intersection even if fully covered by other element', async () => {\n    const { container } = render(`\n      <h1>hello</h1>\n      <div style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: red; z-index: 1000;\"></div>\n    `)\n    \n    await expect(container.querySelector('h1')).toBeInViewport()\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toBeInvalid.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { render } from './utils'\n\nfunction getDOMElement(htmlString: string, selector: string) {\n  const doc = document.implementation.createHTMLDocument('')\n  doc.body.innerHTML = htmlString\n  return doc.querySelector(selector)\n}\n\n// A required field without a value is invalid\nconst invalidInputHtml = `<input required>`\n\nconst invalidInputNode = getDOMElement(invalidInputHtml, 'input')\n\n// A form is invalid if it contains an invalid input\nconst invalidFormHtml = `<form>${invalidInputHtml}</form>`\n\nconst invalidFormNode = getDOMElement(invalidFormHtml, 'form')\n\ndescribe('.toBeInvalid', () => {\n  test('handles <input/>', () => {\n    const {queryByTestId} = render(`\n      <div>\n        <input data-testid=\"no-aria-invalid\">\n        <input data-testid=\"aria-invalid\" aria-invalid>\n        <input data-testid=\"aria-invalid-value\" aria-invalid=\"true\">\n        <input data-testid=\"aria-invalid-false\" aria-invalid=\"false\">\n      </div>\n      `)\n\n    expect(queryByTestId('no-aria-invalid')).not.toBeInvalid()\n    expect(queryByTestId('aria-invalid')).toBeInvalid()\n    expect(queryByTestId('aria-invalid-value')).toBeInvalid()\n    expect(queryByTestId('aria-invalid-false')).not.toBeInvalid()\n    expect(invalidInputNode).toBeInvalid()\n\n    // negative test cases wrapped in throwError assertions for coverage.\n    expect(() =>\n      expect(queryByTestId('no-aria-invalid')).toBeInvalid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid')).not.toBeInvalid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid-value')).not.toBeInvalid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid-false')).toBeInvalid(),\n    ).toThrow()\n    expect(() => expect(invalidInputNode).not.toBeInvalid()).toThrow()\n  })\n\n  test('handles <form/>', () => {\n    const {queryByTestId} = render(`\n      <form data-testid=\"valid\">\n        <input>\n      </form>\n      `)\n\n    expect(queryByTestId('valid')).not.toBeInvalid()\n    expect(invalidFormNode).toBeInvalid()\n\n    // negative test cases wrapped in throwError assertions for coverage.\n    expect(() => expect(queryByTestId('valid')).toBeInvalid()).toThrow()\n    expect(() => expect(invalidFormNode).not.toBeInvalid()).toThrow()\n  })\n\n  test('handles any element', () => {\n    const {queryByTestId} = render(`\n      <ol data-testid=\"valid\">\n        <li data-testid=\"no-aria-invalid\" > </li>\n        <li data-testid=\"aria-invalid\" aria-invalid>  </li>\n        <li data-testid=\"aria-invalid-value\" aria-invalid=\"true\">  </li>\n        <li data-testid=\"aria-invalid-false\" aria-invalid=\"false\">  </li>\n      </ol>\n      `)\n\n    expect(queryByTestId('valid')).not.toBeInvalid()\n    expect(queryByTestId('no-aria-invalid')).not.toBeInvalid()\n    expect(queryByTestId('aria-invalid')).toBeInvalid()\n    expect(queryByTestId('aria-invalid-value')).toBeInvalid()\n    expect(queryByTestId('aria-invalid-false')).not.toBeInvalid()\n\n    // negative test cases wrapped in throwError assertions for coverage.\n    expect(() => expect(queryByTestId('valid')).toBeInvalid()).toThrow()\n    expect(() =>\n      expect(queryByTestId('no-aria-invalid')).toBeInvalid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid')).not.toBeInvalid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid-value')).not.toBeInvalid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid-false')).toBeInvalid(),\n    ).toThrow()\n  })\n})\n\ndescribe('.toBeValid', () => {\n  test('handles <input/>', () => {\n    const {queryByTestId} = render(`\n      <div>\n        <input data-testid=\"no-aria-invalid\">\n        <input data-testid=\"aria-invalid\" aria-invalid>\n        <input data-testid=\"aria-invalid-value\" aria-invalid=\"true\">\n        <input data-testid=\"aria-invalid-false\" aria-invalid=\"false\">\n      </div>\n      `)\n\n    expect(queryByTestId('no-aria-invalid')).toBeValid()\n    expect(queryByTestId('aria-invalid')).not.toBeValid()\n    expect(queryByTestId('aria-invalid-value')).not.toBeValid()\n    expect(queryByTestId('aria-invalid-false')).toBeValid()\n    expect(invalidInputNode).not.toBeValid()\n\n    // negative test cases wrapped in throwError assertions for coverage.\n    expect(() =>\n      expect(queryByTestId('no-aria-invalid')).not.toBeValid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid')).toBeValid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid-value')).toBeValid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid-false')).not.toBeValid(),\n    ).toThrow()\n    expect(() => expect(invalidInputNode).toBeValid()).toThrow()\n  })\n\n  test('handles <form/>', () => {\n    const {queryByTestId} = render(`\n      <form data-testid=\"valid\">\n        <input>\n      </form>\n      `)\n\n    expect(queryByTestId('valid')).toBeValid()\n    expect(invalidFormNode).not.toBeValid()\n\n    // negative test cases wrapped in throwError assertions for coverage.\n    expect(() => expect(queryByTestId('valid')).not.toBeValid()).toThrow()\n    expect(() => expect(invalidFormNode).toBeValid()).toThrow()\n  })\n\n  test('handles any element', () => {\n    const {queryByTestId} = render(`\n      <ol data-testid=\"valid\">\n        <li data-testid=\"no-aria-invalid\" > </li>\n        <li data-testid=\"aria-invalid\" aria-invalid>  </li>\n        <li data-testid=\"aria-invalid-value\" aria-invalid=\"true\">  </li>\n        <li data-testid=\"aria-invalid-false\" aria-invalid=\"false\">  </li>\n      </ol>\n      `)\n\n    expect(queryByTestId('valid')).toBeValid()\n    expect(queryByTestId('no-aria-invalid')).toBeValid()\n    expect(queryByTestId('aria-invalid')).not.toBeValid()\n    expect(queryByTestId('aria-invalid-value')).not.toBeValid()\n    expect(queryByTestId('aria-invalid-false')).toBeValid()\n\n    // negative test cases wrapped in throwError assertions for coverage.\n    expect(() => expect(queryByTestId('valid')).not.toBeValid()).toThrow()\n    expect(() =>\n      expect(queryByTestId('no-aria-invalid')).not.toBeValid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid')).toBeValid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid-value')).toBeValid(),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('aria-invalid-false')).not.toBeValid(),\n    ).toThrow()\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toBePartiallyChecked.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { render } from './utils'\n\n// FIXME\n// playwright prioritizes native checked to aria-checked for \"checkbox\" elements\n// jest-dom checks aria-checked=\"mixed\" anyway\ndescribe('.toBePartiallyChecked', () => {\n  test('handles input checkbox with aria-checked', () => {\n    const {queryByTestId} = render(`\n      <input type=\"checkbox\" aria-checked=\"mixed\" data-testid=\"checkbox-mixed\" />\n      <input type=\"checkbox\" checked data-testid=\"checkbox-checked\" />\n      <input type=\"checkbox\" data-testid=\"checkbox-unchecked\" />\n    `)\n\n    expect(queryByTestId('checkbox-mixed')).toBePartiallyChecked()\n    expect(queryByTestId('checkbox-checked')).not.toBePartiallyChecked()\n    expect(queryByTestId('checkbox-unchecked')).not.toBePartiallyChecked()\n  })\n\n  test('handles input checkbox set as indeterminate', () => {\n    const {queryByTestId} = render(`\n      <input type=\"checkbox\" data-testid=\"checkbox-mixed\" />\n      <input type=\"checkbox\" checked data-testid=\"checkbox-checked\" />\n      <input type=\"checkbox\" data-testid=\"checkbox-unchecked\" />\n    `)\n\n    ;(queryByTestId('checkbox-mixed') as HTMLInputElement).indeterminate = true\n\n    expect(queryByTestId('checkbox-mixed')).toBePartiallyChecked()\n    expect(queryByTestId('checkbox-checked')).not.toBePartiallyChecked()\n    expect(queryByTestId('checkbox-unchecked')).not.toBePartiallyChecked()\n  })\n\n  test('handles element with role=\"checkbox\"', () => {\n    const {queryByTestId} = render(`\n      <div role=\"checkbox\" aria-checked=\"mixed\" data-testid=\"aria-checkbox-mixed\" />\n      <div role=\"checkbox\" aria-checked=\"true\" data-testid=\"aria-checkbox-checked\" />\n      <div role=\"checkbox\" aria-checked=\"false\" data-testid=\"aria-checkbox-unchecked\" />\n    `)\n\n    expect(queryByTestId('aria-checkbox-mixed')).toBePartiallyChecked()\n    expect(queryByTestId('aria-checkbox-checked')).not.toBePartiallyChecked()\n    expect(queryByTestId('aria-checkbox-unchecked')).not.toBePartiallyChecked()\n  })\n\n  test('throws when input checkbox is mixed but expected not to be', () => {\n    const {queryByTestId} = render(\n      `<input type=\"checkbox\" aria-checked=\"mixed\" data-testid=\"checkbox-mixed\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('checkbox-mixed')).not.toBePartiallyChecked(),\n    ).toThrow()\n  })\n\n  test('throws when input checkbox is indeterminate but expected not to be', () => {\n    const {queryByTestId} = render(\n      `<input type=\"checkbox\" data-testid=\"checkbox-mixed\" />`,\n    )\n\n    ;(queryByTestId('checkbox-mixed') as HTMLInputElement).indeterminate = true\n\n    expect(() =>\n      expect(queryByTestId('input-mixed')).not.toBePartiallyChecked(),\n    ).toThrow()\n  })\n\n  test('throws when input checkbox is not checked but expected to be', () => {\n    const {queryByTestId} = render(\n      `<input type=\"checkbox\" data-testid=\"checkbox-empty\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('checkbox-empty')).toBePartiallyChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"checkbox\" is partially checked but expected not to be', () => {\n    const {queryByTestId} = render(\n      `<div role=\"checkbox\" aria-checked=\"mixed\" data-testid=\"aria-checkbox-mixed\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-checkbox-mixed')).not.toBePartiallyChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"checkbox\" is checked but expected to be partially checked', () => {\n    const {queryByTestId} = render(\n      `<div role=\"checkbox\" aria-checked=\"true\" data-testid=\"aria-checkbox-checked\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-checkbox-checked')).toBePartiallyChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"checkbox\" is not checked but expected to be', () => {\n    const {queryByTestId} = render(\n      `<div role=\"checkbox\" aria-checked=\"false\" data-testid=\"aria-checkbox\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-checkbox')).toBePartiallyChecked(),\n    ).toThrow()\n  })\n\n  test('throws when element with role=\"checkbox\" has an invalid aria-checked attribute', () => {\n    const {queryByTestId} = render(\n      `<div role=\"checkbox\" aria-checked=\"something\" data-testid=\"aria-checkbox-invalid\" />`,\n    )\n\n    expect(() =>\n      expect(queryByTestId('aria-checkbox-invalid')).toBePartiallyChecked(),\n    ).toThrow()\n  })\n\n  test('throws when the element is not a checkbox', () => {\n    const {queryByTestId} = render(`<select data-testid=\"select\"></select>`)\n    expect(() =>\n      expect(queryByTestId('select')).toBePartiallyChecked(),\n    ).toThrow(\n      'only inputs with type=\"checkbox\" or elements with role=\"checkbox\" and a valid aria-checked attribute can be used with .toBePartiallyChecked(). Use .toHaveValue() instead',\n    )\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toBeRequired.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { render } from './utils'\n\ntest('.toBeRequired', () => {\n  const {queryByTestId} = render(`\n    <div>\n      <input data-testid=\"required-input\" required>\n      <input data-testid=\"aria-required-input\" aria-required=\"true\">\n      <input data-testid=\"conflicted-input\" required aria-required=\"false\">\n      <input data-testid=\"not-required-input\" aria-required=\"false\">\n      <input data-testid=\"basic-input\">\n      <input data-testid=\"unsupported-type\" type=\"image\" required>\n      <select data-testid=\"select\" required></select>\n      <textarea data-testid=\"textarea\" required></textarea>\n      <div data-testid=\"supported-role\" role=\"tree\" required></div>\n      <div data-testid=\"supported-role-aria\" role=\"tree\" aria-required=\"true\"></div>\n    </div>\n    `)\n\n  expect(queryByTestId('required-input')).toBeRequired()\n  expect(queryByTestId('aria-required-input')).toBeRequired()\n  expect(queryByTestId('conflicted-input')).toBeRequired()\n  expect(queryByTestId('not-required-input')).not.toBeRequired()\n  expect(queryByTestId('basic-input')).not.toBeRequired()\n  expect(queryByTestId('unsupported-type')).not.toBeRequired()\n  expect(queryByTestId('select')).toBeRequired()\n  expect(queryByTestId('textarea')).toBeRequired()\n  expect(queryByTestId('supported-role')).not.toBeRequired()\n  expect(queryByTestId('supported-role-aria')).toBeRequired()\n\n  // negative test cases wrapped in throwError assertions for coverage.\n  expect(() =>\n    expect(queryByTestId('required-input')).not.toBeRequired(),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('aria-required-input')).not.toBeRequired(),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('conflicted-input')).not.toBeRequired(),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('not-required-input')).toBeRequired(),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('basic-input')).toBeRequired(),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('unsupported-type')).toBeRequired(),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('select')).not.toBeRequired(),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('textarea')).not.toBeRequired(),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('supported-role')).toBeRequired(),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('supported-role-aria')).not.toBeRequired(),\n  ).toThrow()\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toBeVisible.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, it } from 'vitest'\nimport { render } from './utils'\n\ndescribe('.toBeVisible', () => {\n  it('returns the visibility of an element', () => {\n    const {container} = render(`\n      <div>\n        <header>\n          <h1 style=\"display: none\">Main title</h1>\n          <h2 style=\"visibility: hidden\">Secondary title</h2>\n          <h3 style=\"visibility: collapse\">Secondary title</h3>\n          <h4 style=\"opacity: 0\">Secondary title</h4>\n          <h5 style=\"opacity: 0.1\">Secondary title</h5>\n        </header>\n        <button hidden>Hidden button</button>\n        <section style=\"display: block; visibility: hidden\">\n          <p>Hello <strong>World</strong></p>\n        </section>\n      </div>\n    `)\n\n    expect(container.querySelector('header')).toBeVisible()\n    expect(container.querySelector('h1')).not.toBeVisible()\n    expect(container.querySelector('h2')).not.toBeVisible()\n    expect(container.querySelector('h3')).not.toBeVisible()\n    expect(container.querySelector('h4')).toBeVisible() // element.checkVisibility() returns true for opacity: 0\n    expect(container.querySelector('h5')).toBeVisible()\n    expect(container.querySelector('button')).not.toBeVisible()\n    expect(container.querySelector('strong')).not.toBeVisible()\n\n    expect(() =>\n      expect(container.querySelector('header')).not.toBeVisible(),\n    ).toThrow()\n    expect(() =>\n      expect(container.querySelector('p')).toBeVisible(),\n    ).toThrow()\n  })\n\n  it('detached element is not visible', () => {\n    const subject = document.createElement('div')\n    expect(subject).not.toBeVisible()\n    expect(() => expect(subject).toBeVisible()).toThrow()\n  })\n\n  describe('with a <details /> element', () => {\n    let subject\n\n    afterEach(() => {\n      subject = undefined\n    })\n\n    describe('when the details is opened', () => {\n      beforeEach(() => {\n        subject = render(`\n          <details open>\n            <summary>Title of visible</summary>\n            <div>Visible <small>details</small></div>\n          </details>\n        `)\n      })\n\n      it('returns true to the details content', () => {\n        expect(subject.container.querySelector('div')).toBeVisible()\n      })\n\n      it('returns true to the most inner details content', () => {\n        expect(subject.container.querySelector('small')).toBeVisible()\n      })\n\n      it('returns true to the details summary', () => {\n        expect(subject.container.querySelector('summary')).toBeVisible()\n      })\n\n      describe('when the user clicks on the summary', () => {\n        beforeEach(() => subject.container.querySelector('summary').click())\n\n        it('returns false to the details content', () => {\n          expect(subject.container.querySelector('div')).not.toBeVisible()\n        })\n\n        it('returns true to the details summary', () => {\n          expect(subject.container.querySelector('summary')).toBeVisible()\n        })\n      })\n    })\n\n    describe('when the details is not opened', () => {\n      beforeEach(() => {\n        subject = render(`\n          <details>\n            <summary>Title of hidden</summary>\n            <div>Hidden details</div>\n          </details>\n        `)\n      })\n\n      it('returns false to the details content', () => {\n        expect(subject.container.querySelector('div')).not.toBeVisible()\n      })\n\n      it('returns true to the summary content', () => {\n        expect(subject.container.querySelector('summary')).toBeVisible()\n      })\n\n      describe('when the user clicks on the summary', () => {\n        beforeEach(() => subject.container.querySelector('summary').click())\n\n        it('returns true to the details content', () => {\n          expect(subject.container.querySelector('div')).toBeVisible()\n        })\n\n        it('returns true to the details summary', () => {\n          expect(subject.container.querySelector('summary')).toBeVisible()\n        })\n      })\n    })\n\n    describe('when the details is opened but it is hidden', () => {\n      beforeEach(() => {\n        subject = render(`\n          <details open hidden>\n            <summary>Title of visible</summary>\n            <div>Visible details</div>\n          </details>\n        `)\n      })\n\n      it('returns false to the details content', () => {\n        expect(subject.container.querySelector('div')).not.toBeVisible()\n      })\n\n      it('returns false to the details summary', () => {\n        expect(subject.container.querySelector('summary')).not.toBeVisible()\n      })\n    })\n\n    describe('when the <details /> inner text does not have an enclosing element', () => {\n      describe('when the details is not opened', () => {\n        beforeEach(() => {\n          subject = render(`\n              <details>\n                <summary>Title of hidden innerText</summary>\n                hidden innerText\n              </details>\n            `)\n        })\n\n        it('returns true to the details content', () => {\n          expect(subject.container.querySelector('details')).toBeVisible()\n        })\n\n        it('returns true to the details summary', () => {\n          expect(subject.container.querySelector('summary')).toBeVisible()\n        })\n\n        describe('when the user clicks on the summary', () => {\n          beforeEach(() => subject.container.querySelector('summary').click())\n\n          it('returns true to the details content', () => {\n            expect(subject.container.querySelector('details')).toBeVisible()\n          })\n\n          it('returns true to the details summary', () => {\n            expect(subject.container.querySelector('summary')).toBeVisible()\n          })\n        })\n      })\n\n      describe('when the details is opened', () => {\n        beforeEach(() => {\n          subject = render(`\n              <details open>\n                <summary>Title of visible innerText</summary>\n                visible <small>innerText</small>\n              </details>\n            `)\n        })\n\n        it('returns true to the details content', () => {\n          expect(subject.container.querySelector('details')).toBeVisible()\n        })\n\n        it('returns true to inner small content', () => {\n          expect(subject.container.querySelector('small')).toBeVisible()\n        })\n\n        describe('when the user clicks on the summary', () => {\n          beforeEach(() => subject.container.querySelector('summary').click())\n\n          it('returns true to the details content', () => {\n            expect(subject.container.querySelector('details')).toBeVisible()\n          })\n\n          it('returns false to the inner small content', () => {\n            expect(subject.container.querySelector('small')).not.toBeVisible()\n          })\n\n          it('returns true to the details summary', () => {\n            expect(subject.container.querySelector('summary')).toBeVisible()\n          })\n        })\n      })\n    })\n\n    describe('with a nested <details /> element', () => {\n      describe('when the nested <details /> is opened', () => {\n        beforeEach(() => {\n          subject = render(`\n            <details open>\n              <summary>Title of visible</summary>\n              <div>Outer content</div>\n              <details open>\n                <summary>Title of nested details</summary>\n                <div>Inner content</div>\n              </details>\n            </details>\n          `)\n        })\n\n        it('returns true to the nested details content', () => {\n          expect(\n            subject.container.querySelector('details > details > div'),\n          ).toBeVisible()\n        })\n\n        it('returns true to the nested details summary', () => {\n          expect(\n            subject.container.querySelector('details > details > summary'),\n          ).toBeVisible()\n        })\n\n        it('returns true to the outer details content', () => {\n          expect(subject.container.querySelector('details > div')).toBeVisible()\n        })\n\n        it('returns true to the outer details summary', () => {\n          expect(\n            subject.container.querySelector('details > summary'),\n          ).toBeVisible()\n        })\n      })\n\n      describe('when the nested <details /> is not opened', () => {\n        beforeEach(() => {\n          subject = render(`\n            <details open>\n              <summary>Title of visible</summary>\n              <div>Outer content</div>\n              <details>\n                <summary>Title of nested details</summary>\n                <div>Inner content</div>\n              </details>\n            </details>\n          `)\n        })\n\n        it('returns false to the nested details content', () => {\n          expect(\n            subject.container.querySelector('details > details > div'),\n          ).not.toBeVisible()\n        })\n\n        it('returns true to the nested details summary', () => {\n          expect(\n            subject.container.querySelector('details > details > summary'),\n          ).toBeVisible()\n        })\n\n        it('returns true to the outer details content', () => {\n          expect(subject.container.querySelector('details > div')).toBeVisible()\n        })\n\n        it('returns true to the outer details summary', () => {\n          expect(\n            subject.container.querySelector('details > summary'),\n          ).toBeVisible()\n        })\n      })\n\n      describe('when the outer <details /> is not opened and the nested one is opened', () => {\n        beforeEach(() => {\n          subject = render(`\n            <details>\n              <summary>Title of visible</summary>\n              <div>Outer content</div>\n              <details open>\n                <summary>Title of nested details</summary>\n                <div>Inner content</div>\n              </details>\n            </details>\n          `)\n        })\n\n        it('returns false to the nested details content', () => {\n          expect(\n            subject.container.querySelector('details > details > div'),\n          ).not.toBeVisible()\n        })\n\n        it('returns false to the nested details summary', () => {\n          expect(\n            subject.container.querySelector('details > details > summary'),\n          ).not.toBeVisible()\n        })\n\n        it('returns false to the outer details content', () => {\n          expect(\n            subject.container.querySelector('details > div'),\n          ).not.toBeVisible()\n        })\n\n        it('returns true to the outer details summary', () => {\n          expect(\n            subject.container.querySelector('details > summary'),\n          ).toBeVisible()\n        })\n      })\n\n      describe('with nested details (unenclosed outer, enclosed inner)', () => {\n        describe('when both outer and inner are opened', () => {\n          beforeEach(() => {\n            subject = render(`\n              <details open>\n                <summary>Title of outer unenclosed</summary>\n                Unenclosed innerText\n                <details open>\n                  <summary>Title of inner enclosed</summary>\n                  <div>Enclosed innerText</div>\n                </details>\n              </details>\n            `)\n          })\n\n          it('returns true to outer unenclosed innerText', () => {\n            expect(subject.container.querySelector('details')).toBeVisible()\n          })\n\n          it('returns true to outer summary', () => {\n            expect(subject.container.querySelector('summary')).toBeVisible()\n          })\n\n          it('returns true to inner enclosed innerText', () => {\n            expect(\n              subject.container.querySelector('details > details > div'),\n            ).toBeVisible()\n          })\n\n          it('returns true to inner summary', () => {\n            expect(\n              subject.container.querySelector('details > details > summary'),\n            ).toBeVisible()\n          })\n        })\n\n        describe('when outer is opened and inner is not opened', () => {\n          beforeEach(() => {\n            subject = render(`\n              <details open>\n                <summary>Title of outer unenclosed</summary>\n                Unenclosed innerText\n                <details>\n                  <summary>Title of inner enclosed</summary>\n                  <div>Enclosed innerText</div>\n                </details>\n              </details>\n            `)\n          })\n\n          it('returns true to outer unenclosed innerText', () => {\n            expect(subject.container.querySelector('details')).toBeVisible()\n          })\n\n          it('returns true to outer summary', () => {\n            expect(subject.container.querySelector('summary')).toBeVisible()\n          })\n\n          it('returns false to inner enclosed innerText', () => {\n            expect(\n              subject.container.querySelector('details > details > div'),\n            ).not.toBeVisible()\n          })\n\n          it('returns true to inner summary', () => {\n            expect(\n              subject.container.querySelector('details > details > summary'),\n            ).toBeVisible()\n          })\n        })\n\n        describe('when outer is not opened and inner is opened', () => {\n          beforeEach(() => {\n            subject = render(`\n              <details>\n                <summary>Title of outer unenclosed</summary>\n                Unenclosed innerText\n                <details open>\n                  <summary>Title of inner enclosed</summary>\n                  <div>Enclosed innerText</div>\n                </details>\n              </details>\n            `)\n          })\n\n          it('returns false to outer unenclosed innerText', () => {\n            expect(subject.container.querySelector('details')).toBeVisible()\n          })\n\n          it('returns true to outer summary', () => {\n            expect(subject.container.querySelector('summary')).toBeVisible()\n          })\n\n          it('returns false to inner enclosed innerText', () => {\n            expect(\n              subject.container.querySelector('details > details > div'),\n            ).not.toBeVisible()\n          })\n\n          it('returns true to inner summary', () => {\n            expect(\n              subject.container.querySelector('details > details > summary'),\n            ).not.toBeVisible()\n          })\n        })\n      })\n    })\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toContainElement.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { render } from './utils'\n\nconst {queryByTestId} = render(`\n<span data-testid=\"grandparent\">\n  <span data-testid=\"parent\">\n    <span data-testid=\"child\"></span>\n  </span>\n  <svg data-testid=\"svg-element\"></svg>\n</span>\n`)\n\nconst grandparent = queryByTestId('grandparent')\nconst parent = queryByTestId('parent')\nconst child = queryByTestId('child')\nconst svgElement = queryByTestId('svg-element')\nconst nonExistantElement = queryByTestId('not-exists')\nconst fakeElement = {thisIsNot: 'an html element'}\n\ntest('.toContainElement positive test cases', () => {\n  expect(grandparent).toContainElement(parent)\n  expect(grandparent).toContainElement(child)\n  expect(grandparent).toContainElement(svgElement)\n  expect(parent).toContainElement(child)\n  expect(parent).not.toContainElement(grandparent)\n  expect(parent).not.toContainElement(svgElement)\n  expect(child).not.toContainElement(parent)\n  expect(child).not.toContainElement(grandparent)\n  expect(child).not.toContainElement(svgElement)\n  expect(grandparent).not.toContainElement(nonExistantElement)\n})\n\ntest('.toContainElement negative test cases', () => {\n  expect(() =>\n    expect(nonExistantElement).not.toContainElement(child),\n  ).toThrow()\n  expect(() => expect(parent).toContainElement(grandparent)).toThrow()\n  expect(() =>\n    expect(nonExistantElement).toContainElement(grandparent),\n  ).toThrow()\n  expect(() =>\n    expect(grandparent).toContainElement(nonExistantElement),\n  ).toThrow()\n  expect(() =>\n    expect(nonExistantElement).toContainElement(nonExistantElement),\n  ).toThrow()\n  expect(() =>\n    // @ts-expect-error testing invalid assertion\n    expect(nonExistantElement).toContainElement(fakeElement),\n  ).toThrow()\n  expect(() =>\n    expect(fakeElement).toContainElement(nonExistantElement),\n  ).toThrow()\n  expect(() =>\n    expect(fakeElement).not.toContainElement(nonExistantElement),\n  ).toThrow()\n  expect(() => expect(fakeElement).toContainElement(grandparent)).toThrow()\n    // @ts-expect-error testing invalid assertion\n  expect(() => expect(grandparent).toContainElement(fakeElement)).toThrow()\n    // @ts-expect-error testing invalid assertion\n  expect(() => expect(fakeElement).toContainElement(fakeElement)).toThrow()\n  expect(() => expect(grandparent).not.toContainElement(child)).toThrow()\n  expect(() =>\n    expect(grandparent).not.toContainElement(svgElement),\n  ).toThrow()\n  expect(() =>\n    expect(grandparent).not.toContainElement(undefined),\n  ).toThrow()\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toContainHTML.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { render } from './utils'\n\n/* eslint-disable max-statements */\ndescribe('.toContainHTML', () => {\n  test('handles positive and negative cases', () => {\n    const {queryByTestId} = render(`\n    <span data-testid=\"grandparent\">\n      <span data-testid=\"parent\">\n        <span data-testid=\"child\"></span>\n      </span>\n      <svg data-testid=\"svg-element\"></svg>\n    </span>\n    `)\n\n    const grandparent = queryByTestId('grandparent')\n    const parent = queryByTestId('parent')\n    const child = queryByTestId('child')\n    const nonExistantElement = queryByTestId('not-exists')\n    const fakeElement = {thisIsNot: 'an html element'}\n    const stringChildElement = '<span data-testid=\"child\"></span>'\n    const stringChildElementSelfClosing = '<span data-testid=\"child\" />'\n    const incorrectStringHtml = '<span data-testid=\"child\"></div>'\n    const nonExistantString = '<span> Does not exists </span>'\n    const svgElement = queryByTestId('svg-element')\n\n    expect(grandparent).toContainHTML(stringChildElement)\n    expect(parent).toContainHTML(stringChildElement)\n    expect(child).toContainHTML(stringChildElement)\n    expect(child).toContainHTML(stringChildElementSelfClosing)\n    expect(grandparent).not.toContainHTML(nonExistantString)\n    expect(parent).not.toContainHTML(nonExistantString)\n    expect(child).not.toContainHTML(nonExistantString)\n    expect(child).not.toContainHTML(nonExistantString)\n    expect(grandparent).toContainHTML(incorrectStringHtml)\n    expect(parent).toContainHTML(incorrectStringHtml)\n    expect(child).toContainHTML(incorrectStringHtml)\n\n    // negative test cases wrapped in throwError assertions for coverage.\n    expect(() =>\n      expect(nonExistantElement).not.toContainHTML(stringChildElement),\n    ).toThrow()\n    expect(() =>\n      // @ts-expect-error testing invalid input\n      expect(nonExistantElement).not.toContainHTML(nonExistantElement),\n    ).toThrow()\n    expect(() =>\n      // @ts-expect-error testing invalid input\n      expect(stringChildElement).not.toContainHTML(fakeElement),\n    ).toThrow()\n    expect(() =>\n      expect(svgElement).toContainHTML(stringChildElement),\n    ).toThrow()\n    expect(() =>\n      expect(grandparent).not.toContainHTML(stringChildElement),\n    ).toThrow()\n    expect(() =>\n      expect(parent).not.toContainHTML(stringChildElement),\n    ).toThrow()\n    expect(() =>\n      expect(child).not.toContainHTML(stringChildElement),\n    ).toThrow()\n    expect(() =>\n      expect(child).not.toContainHTML(stringChildElement),\n    ).toThrow()\n    expect(() =>\n      expect(child).not.toContainHTML(stringChildElementSelfClosing),\n    ).toThrow()\n    expect(() => expect(child).toContainHTML(nonExistantString)).toThrow()\n    expect(() => expect(parent).toContainHTML(nonExistantString)).toThrow()\n    expect(() =>\n      expect(grandparent).toContainHTML(nonExistantString),\n    ).toThrow()\n      // @ts-expect-error testing invalid input\n    expect(() => expect(child).toContainHTML(nonExistantElement)).toThrow()\n    expect(() =>\n      // @ts-expect-error testing invalid input\n      expect(parent).toContainHTML(nonExistantElement),\n    ).toThrow()\n    expect(() =>\n      // @ts-expect-error testing invalid input\n      expect(grandparent).toContainHTML(nonExistantElement),\n    ).toThrow()\n    expect(() =>\n      expect(nonExistantElement).not.toContainHTML(incorrectStringHtml),\n    ).toThrow()\n    expect(() =>\n      expect(grandparent).not.toContainHTML(incorrectStringHtml),\n    ).toThrow()\n    expect(() =>\n      expect(child).not.toContainHTML(incorrectStringHtml),\n    ).toThrow()\n    expect(() =>\n      expect(parent).not.toContainHTML(incorrectStringHtml),\n    ).toThrow()\n  })\n\n  test('throws with an expected text', async () => {\n    const {queryByTestId} = render('<span data-testid=\"child\"></span>')\n    const htmlElement = queryByTestId('child')\n    const nonExistantString = '<div> non-existent element </div>'\n\n    let errorMessage\n    try {\n      expect(htmlElement).toContainHTML(nonExistantString)\n    } catch (error) {\n      errorMessage = error.message\n    }\n\n    expect(errorMessage).toMatchInlineSnapshot(`\n      expect(element).toContainHTML()\n      Expected:\n        <div> non-existent element </div>\n      Received:\n        <span\n        data-testid=\"child\"\n      />\n    `)\n  })\n})\n"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveAccessibleDescription.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { render } from './utils'\n\ndescribe('.toHaveAccessibleDescription', () => {\n  it('works with the link title attribute', () => {\n    const {queryByTestId} = render(`\n      <div>\n        <a data-testid=\"link\" href=\"/\" aria-label=\"Home page\" title=\"A link to start over\">Start</a>\n        <a data-testid=\"extra-link\" href=\"/about\" aria-label=\"About page\">About</a>\n      </div>\n   `)\n\n    const link = queryByTestId('link')\n    expect(link).toHaveAccessibleDescription()\n    expect(link).toHaveAccessibleDescription('A link to start over')\n    expect(link).not.toHaveAccessibleDescription('Home page')\n    expect(() => {\n      expect(link).toHaveAccessibleDescription('Invalid description')\n    }).toThrow(/expected element to have accessible description/i)\n    expect(() => {\n      expect(link).not.toHaveAccessibleDescription()\n    }).toThrow(/expected element not to have accessible description/i)\n\n    const extraLink = queryByTestId('extra-link')\n    expect(extraLink).not.toHaveAccessibleDescription()\n    expect(() => {\n      expect(extraLink).toHaveAccessibleDescription()\n    }).toThrow(/expected element to have accessible description/i)\n  })\n\n  it('works with aria-describedby attributes', () => {\n    const {queryByTestId} = render(`\n      <div>\n        <img src=\"avatar.jpg\" data-testid=\"avatar\" alt=\"User profile pic\">\n        <img src=\"logo.jpg\" data-testid=\"logo\" alt=\"Company logo\" aria-describedby=\"t1\">\n        <span id=\"t1\" role=\"presentation\">The logo of Our Company</span>\n      </div>\n   `)\n\n    const avatar = queryByTestId('avatar')\n    expect(avatar).not.toHaveAccessibleDescription()\n    expect(() => {\n      expect(avatar).toHaveAccessibleDescription('User profile pic')\n    }).toThrow(/expected element to have accessible description/i)\n\n    const logo = queryByTestId('logo')\n    expect(logo).not.toHaveAccessibleDescription('Company logo')\n    expect(logo).toHaveAccessibleDescription('The logo of Our Company')\n    expect(logo).toHaveAccessibleDescription(/logo of our company/i)\n    expect(logo).toHaveAccessibleDescription(\n      expect.stringContaining('logo of Our Company'),\n    )\n    expect(() => {\n      expect(logo).toHaveAccessibleDescription(\"Our company's logo\")\n    }).toThrow(/expected element to have accessible description/i)\n    expect(() => {\n      expect(logo).not.toHaveAccessibleDescription('The logo of Our Company')\n    }).toThrow(/expected element not to have accessible description/i)\n  })\n\n  it('works with aria-description attribute', () => {\n    const {queryByTestId} = render(`\n      <img src=\"logo.jpg\" data-testid=\"logo\" alt=\"Company logo\" aria-description=\"The logo of Our Company\">\n   `)\n\n    const logo = queryByTestId('logo')\n    expect(logo).not.toHaveAccessibleDescription('Company logo')\n    expect(logo).toHaveAccessibleDescription('The logo of Our Company')\n    expect(logo).toHaveAccessibleDescription(/logo of our company/i)\n    expect(logo).toHaveAccessibleDescription(\n      expect.stringContaining('logo of Our Company'),\n    )\n    expect(() => {\n      expect(logo).toHaveAccessibleDescription(\"Our company's logo\")\n    }).toThrow(/expected element to have accessible description/i)\n    expect(() => {\n      expect(logo).not.toHaveAccessibleDescription('The logo of Our Company')\n    }).toThrow(/expected element not to have accessible description/i)\n  })\n\n  it('handles multiple ids', () => {\n    const {queryByTestId} = render(`\n      <div>\n        <div id=\"first\">First description</div>\n        <div id=\"second\">Second description</div>\n        <div id=\"third\">Third description</div>\n\n        <div data-testid=\"multiple\" aria-describedby=\"first second third\"></div>\n      </div>\n  `)\n\n    expect(queryByTestId('multiple')).toHaveAccessibleDescription(\n      'First description Second description Third description',\n    )\n    expect(queryByTestId('multiple')).toHaveAccessibleDescription(\n      /Second description Third/,\n    )\n    expect(queryByTestId('multiple')).toHaveAccessibleDescription(\n      expect.stringContaining('Second description Third'),\n    )\n    expect(queryByTestId('multiple')).toHaveAccessibleDescription(\n      expect.stringMatching(/Second description Third/),\n    )\n    expect(queryByTestId('multiple')).not.toHaveAccessibleDescription(\n      'Something else',\n    )\n    expect(queryByTestId('multiple')).not.toHaveAccessibleDescription('First')\n  })\n\n  it('normalizes whitespace', () => {\n    const {queryByTestId} = render(`\n      <div id=\"first\">\n        Step\n          1\n            of\n              4\n      </div>\n      <div id=\"second\">\n        And\n          extra\n            description\n      </div>\n      <div data-testid=\"target\" aria-describedby=\"first second\"></div>\n    `)\n\n    expect(queryByTestId('target')).toHaveAccessibleDescription(\n      'Step 1 of 4 And extra description',\n    )\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveAccessibleErrorMessage.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { render } from './utils'\n\ndescribe('.toHaveAccessibleErrorMessage', () => {\n  const input = 'input'\n  const errorId = 'error-id'\n  const error = 'This field is invalid'\n  const strings = {true: String(true), false: String(false)}\n\n  describe('Positive Test Cases', () => {\n    it(\"Fails the test if an invalid `id` is provided for the target element's `aria-errormessage`\", () => {\n      const secondId = 'id2'\n      const secondError = 'LISTEN TO ME!!!'\n\n      const {queryByTestId} = render(`\n        <div>\n          <${input} data-testid=\"${input}\" aria-invalid=\"${strings.true}\" aria-errormessage=\"${errorId} ${secondId}\" />\n          <div data-testid=\"${errorId}\" id=\"${errorId}\" role=\"alert\">${error}</div>\n          <div data-testid=\"${secondId}\" id=\"${secondId}\" role=\"alert\">${secondError}</div>\n        </div>\n      `)\n\n      const field = queryByTestId('input')\n      expect(field).toHaveAccessibleErrorMessage()\n      expect(field).toHaveAccessibleErrorMessage(new RegExp(error[0]))\n\n      expect(field).toHaveAccessibleErrorMessage(error + ' ' + secondError)\n\n      expect(() => expect(field).toHaveAccessibleErrorMessage(error)).toThrow()\n      expect(() =>\n        expect(field).toHaveAccessibleErrorMessage(secondError),\n      ).toThrow()\n\n      expect(field).toHaveAccessibleErrorMessage(new RegExp(secondError[0]))\n    })\n\n    it('Fails the test if the target element is valid according to the WAI-ARIA spec', () => {\n      const noAriaInvalidAttribute = 'no-aria-invalid-attribute'\n      const validFieldState = 'false'\n      const invalidFieldStates = [\n        'true',\n        // difference with jest-dom\n        // https://www.w3.org/TR/wai-aria-1.2/#aria-invalid\n        // If the attribute is not present, or its value is false, or its value\n        // is an EMPTY STRING, the default value of false applies.\n        // '',\n        'grammar',\n        'spelling',\n        'asfdafbasdfasa',\n      ]\n\n      function renderFieldWithState(state) {\n        return render(`\n          <div>\n            <${input} data-testid=\"${input}\" aria-invalid=\"${state}\" aria-errormessage=\"${errorId}\" />\n            <div data-testid=\"${errorId}\" id=\"${errorId}\" role=\"alert\">${error}</div>\n            <input data-testid=\"${noAriaInvalidAttribute}\" aria-errormessage=\"${errorId}\" />\n          </div>\n        `)\n      }\n\n      // Success Cases\n      invalidFieldStates.forEach(invalidState => {\n        const {queryByTestId} = renderFieldWithState(invalidState)\n        const field = queryByTestId('input')\n\n        expect(field).toHaveAccessibleErrorMessage()\n        expect(field).toHaveAccessibleErrorMessage(error)\n      })\n\n      // Failure Case\n      const {queryByTestId} = renderFieldWithState(validFieldState)\n      const field = queryByTestId('input')\n      const fieldWithoutAttribute = queryByTestId(noAriaInvalidAttribute)\n\n      expect(() => expect(fieldWithoutAttribute).toHaveAccessibleErrorMessage())\n        .toThrowErrorMatchingInlineSnapshot(`\n          [Error: expect(element).toHaveAccessibleErrorMessage()\n\n          Expected element to have accessible error message, but got nothing]\n        `)\n\n      expect(() => expect(field).toHaveAccessibleErrorMessage())\n        .toThrowErrorMatchingInlineSnapshot(`\n          [Error: expect(element).toHaveAccessibleErrorMessage()\n\n          Expected element to have accessible error message, but got nothing]\n        `)\n\n      // Assume the remaining error messages are the EXACT same as above\n      expect(() => expect(field).toHaveAccessibleErrorMessage(error)).toThrow()\n      expect(() =>\n        expect(field).toHaveAccessibleErrorMessage(new RegExp(error, 'i')),\n      ).toThrow()\n    })\n\n    it('Passes the test if the target element has ANY recognized, non-empty error message', () => {\n      const {queryByTestId} = render(`\n        <div>\n          <${input} data-testid=\"${input}\" aria-invalid=\"${strings.true}\" aria-errormessage=\"${errorId}\" />\n          <div data-testid=\"${errorId}\" id=\"${errorId}\" role=\"alert\">${error}</div>\n        </div>\n      `)\n\n      const field = queryByTestId(input)\n      expect(field).toHaveAccessibleErrorMessage()\n    })\n\n    it('Fails the test if NO recognized, non-empty error message was found for the target element', () => {\n      const empty = 'empty'\n      const emptyErrorId = 'empty-error'\n      const missing = 'missing'\n\n      const {queryByTestId} = render(`\n        <div>\n          <input data-testid=\"${empty}\" aria-invalid=\"${strings.true}\" aria-errormessage=\"${emptyErrorId}\" />\n          <div data-testid=\"${emptyErrorId}\" id=\"${emptyErrorId}\" role=\"alert\"></div>\n\n          <input data-testid=\"${missing}\" aria-invalid=\"${strings.true}\" aria-errormessage=\"${missing}-error\" />\n        </div>\n      `)\n\n      const fieldWithEmptyError = queryByTestId(empty)\n      const fieldMissingError = queryByTestId(missing)\n\n      expect(() => expect(fieldWithEmptyError).toHaveAccessibleErrorMessage())\n        .toThrowErrorMatchingInlineSnapshot(`\n          [Error: expect(element).toHaveAccessibleErrorMessage()\n\n          Expected element to have accessible error message, but got nothing]\n        `)\n\n      expect(() => expect(fieldMissingError).toHaveAccessibleErrorMessage())\n        .toThrowErrorMatchingInlineSnapshot(`\n          [Error: expect(element).toHaveAccessibleErrorMessage()\n\n          Expected element to have accessible error message, but got nothing]\n        `)\n    })\n\n    it('Passes the test if the target element has the error message that was SPECIFIED', () => {\n      const {queryByTestId} = render(`\n        <div>\n          <${input} data-testid=\"${input}\" aria-invalid=\"${strings.true}\" aria-errormessage=\"${errorId}\" />\n          <div data-testid=\"${errorId}\" id=\"${errorId}\" role=\"alert\">${error}</div>\n        </div>\n      `)\n\n      const field = queryByTestId(input)\n      const halfOfError = error.slice(0, Math.floor(error.length * 0.5))\n\n      expect(field).toHaveAccessibleErrorMessage(error)\n      expect(field).toHaveAccessibleErrorMessage(new RegExp(halfOfError, 'i'))\n      expect(field).toHaveAccessibleErrorMessage(\n        expect.stringContaining(halfOfError),\n      )\n      expect(field).toHaveAccessibleErrorMessage(\n        expect.stringMatching(new RegExp(halfOfError, 'i')),\n      )\n    })\n\n    it('Fails the test if the target element DOES NOT have the error message that was SPECIFIED', () => {\n      const {queryByTestId} = render(`\n        <div>\n          <${input} data-testid=\"${input}\" aria-invalid=\"${strings.true}\" aria-errormessage=\"${errorId}\" />\n          <div data-testid=\"${errorId}\" id=\"${errorId}\" role=\"alert\">${error}</div>\n        </div>\n      `)\n\n      const field = queryByTestId(input)\n      const msg = 'asdflkje2984fguyvb bnafdsasfa;lj'\n\n      expect(() => expect(field).toHaveAccessibleErrorMessage(''))\n        .toThrowErrorMatchingInlineSnapshot(`\n          [Error: expect(element).toHaveAccessibleErrorMessage()\n\n          Expected element to have accessible error message:\n\n          Received:\n            This field is invalid]\n        `)\n\n      // Assume this error is SIMILAR to the error above\n      expect(() => expect(field).toHaveAccessibleErrorMessage(msg)).toThrow()\n      expect(() =>\n        expect(field).toHaveAccessibleErrorMessage(\n          error.slice(0, Math.floor(error.length * 0.5)),\n        ),\n      ).toThrow()\n\n      expect(() =>\n        expect(field).toHaveAccessibleErrorMessage(new RegExp(msg, 'i')),\n      ).toThrowErrorMatchingInlineSnapshot(`\n        [Error: expect(element).toHaveAccessibleErrorMessage()\n\n        Expected element to have accessible error message:\n          /asdflkje2984fguyvb bnafdsasfa;lj/i\n        Received:\n          This field is invalid]\n      `)\n    })\n\n    it('Normalizes the whitespace of the received error message', () => {\n      const {queryByTestId} = render(`\n        <div>\n          <${input} data-testid=\"${input}\" aria-invalid=\"${strings.true}\" aria-errormessage=\"${errorId}\" />\n          <div data-testid=\"${errorId}\" id=\"${errorId}\" role=\"alert\">\n            Step\n              1\n                of\n                  9000\n          </div>\n        </div>\n      `)\n\n      const field = queryByTestId(input)\n      expect(field).toHaveAccessibleErrorMessage('Step 1 of 9000')\n    })\n  })\n\n  // These tests for the `.not` use cases will help us cover our bases and complete test coverage\n  describe('Negated Test Cases', () => {\n    it('Passes the test if the target element is valid according to the WAI-ARIA spec', () => {\n      const {queryByTestId} = render(`\n        <div>\n          <${input} data-testid=\"${input}\" aria-errormessage=\"${errorId}\" />\n          <div data-testid=\"${errorId}\" id=\"${errorId}\" role=\"alert\">${error}</div>\n        </div>\n      `)\n\n      const field = queryByTestId(input)\n      expect(field).not.toHaveAccessibleErrorMessage()\n      expect(field).not.toHaveAccessibleErrorMessage(error)\n      expect(field).not.toHaveAccessibleErrorMessage(new RegExp(error[0]))\n    })\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveAttribute.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { render } from './utils'\n\ntest('.toHaveAttribute', () => {\n  const {queryByTestId} = render(`\n    <button data-testid=\"ok-button\" type=\"submit\" disabled>\n      OK\n    </button>\n    <svg data-testid=\"svg-element\" width=\"12\"></svg>\n  `)\n\n  expect(queryByTestId('ok-button')).toHaveAttribute('disabled')\n  expect(queryByTestId('ok-button')).toHaveAttribute('type')\n  expect(queryByTestId('ok-button')).not.toHaveAttribute('class')\n  expect(queryByTestId('ok-button')).toHaveAttribute('type', 'submit')\n  expect(queryByTestId('ok-button')).not.toHaveAttribute('type', 'button')\n  expect(queryByTestId('svg-element')).toHaveAttribute('width')\n  expect(queryByTestId('svg-element')).toHaveAttribute('width', '12')\n  expect(queryByTestId('ok-button')).not.toHaveAttribute('height')\n\n  expect(() =>\n    expect(queryByTestId('ok-button')).not.toHaveAttribute('disabled'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('ok-button')).not.toHaveAttribute('type'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('ok-button')).toHaveAttribute('class'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('ok-button')).not.toHaveAttribute('type', 'submit'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('ok-button')).toHaveAttribute('type', 'button'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('svg-element')).not.toHaveAttribute('width'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('svg-element')).not.toHaveAttribute('width', '12'),\n  ).toThrow()\n  expect(() =>\n    // @ts-expect-error invalid signature\n    expect({thisIsNot: 'an html element'}).not.toHaveAttribute(),\n  ).toThrow()\n\n  // Asymmetric matchers\n  expect(queryByTestId('ok-button')).toHaveAttribute(\n    'type',\n    expect.stringContaining('sub'),\n  )\n  expect(queryByTestId('ok-button')).toHaveAttribute(\n    'type',\n    expect.stringMatching(/sub*/),\n  )\n  expect(queryByTestId('ok-button')).toHaveAttribute('type', expect.anything())\n\n  expect(() =>\n    expect(queryByTestId('ok-button')).toHaveAttribute(\n      'type',\n      expect.not.stringContaining('sub'),\n    ),\n  ).toThrow()\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveClass.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { render } from './utils'\n\nconst renderElementWithClasses = () =>\n  render(`\n<div>\n  <button data-testid=\"delete-button\" class=\"btn extra btn-danger\">\n    Delete item\n  </button>\n  <button data-testid=\"cancel-button\">\n    Cancel\n  </button>\n  <svg data-testid=\"svg-spinner\" class=\"spinner clockwise\">\n    <path />\n  </svg>\n  <div data-testid=\"only-one-class\" class=\"alone\"></div>\n  <div data-testid=\"no-classes\"></div>\n</div>\n`)\n\ntest('.toHaveClass', () => {\n  const {queryByTestId} = renderElementWithClasses()\n\n  expect(queryByTestId('delete-button')).toHaveClass('btn')\n  expect(queryByTestId('delete-button')).toHaveClass('btn-danger')\n  expect(queryByTestId('delete-button')).toHaveClass('extra')\n  expect(queryByTestId('delete-button')).not.toHaveClass('xtra')\n  expect(queryByTestId('delete-button')).not.toHaveClass('btn xtra')\n  expect(queryByTestId('delete-button')).not.toHaveClass('btn', 'xtra')\n  expect(queryByTestId('delete-button')).not.toHaveClass('btn', 'extra xtra')\n  expect(queryByTestId('delete-button')).toHaveClass('btn btn-danger')\n  expect(queryByTestId('delete-button')).toHaveClass('btn', 'btn-danger')\n  expect(queryByTestId('delete-button')).toHaveClass(\n    'btn extra',\n    'btn-danger extra',\n  )\n  expect(queryByTestId('delete-button')).not.toHaveClass('btn-link')\n  expect(queryByTestId('cancel-button')).not.toHaveClass('btn-danger')\n  expect(queryByTestId('svg-spinner')).toHaveClass('spinner')\n  expect(queryByTestId('svg-spinner')).toHaveClass('clockwise')\n  expect(queryByTestId('svg-spinner')).not.toHaveClass('wise')\n  expect(queryByTestId('no-classes')).not.toHaveClass()\n  expect(queryByTestId('no-classes')).not.toHaveClass(' ')\n\n  expect(() =>\n    expect(queryByTestId('delete-button')).not.toHaveClass('btn'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('delete-button')).not.toHaveClass('btn-danger'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('delete-button')).not.toHaveClass('extra'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('delete-button')).toHaveClass('xtra'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('delete-button')).toHaveClass('btn', 'extra xtra'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('delete-button')).not.toHaveClass('btn btn-danger'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('delete-button')).not.toHaveClass('btn', 'btn-danger'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('delete-button')).toHaveClass('btn-link'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('cancel-button')).toHaveClass('btn-danger'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('svg-spinner')).not.toHaveClass('spinner'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('svg-spinner')).toHaveClass('wise'),\n  ).toThrow()\n  expect(() =>\n    expect(queryByTestId('delete-button')).toHaveClass(),\n  ).toThrow(/At least one expected class must be provided/)\n  expect(() =>\n    expect(queryByTestId('delete-button')).toHaveClass(''),\n  ).toThrow(/At least one expected class must be provided/)\n  expect(() => expect(queryByTestId('no-classes')).toHaveClass()).toThrow(\n    /At least one expected class must be provided/,\n  )\n  expect(() =>\n    expect(queryByTestId('delete-button')).not.toHaveClass(),\n  ).toThrow(/(none)/)\n  expect(() =>\n    expect(queryByTestId('delete-button')).not.toHaveClass('  '),\n  ).toThrow(/(none)/)\n})\n\ntest('.toHaveClass with regular expressions', () => {\n  const {queryByTestId} = renderElementWithClasses()\n\n  expect(queryByTestId('delete-button')).toHaveClass(/btn/)\n  expect(queryByTestId('delete-button')).toHaveClass(/danger/)\n  expect(queryByTestId('delete-button')).toHaveClass(\n    /-danger$/,\n    'extra',\n    /^btn-[a-z]+$/,\n    /\\bbtn/,\n  )\n\n  // It does not match with \"btn extra\", even though it is a substring of the\n  // class \"btn extra btn-danger\". This is because the regular expression is\n  // matched against each class individually.\n  expect(queryByTestId('delete-button')).not.toHaveClass(/btn extra/)\n\n  expect(() =>\n    expect(queryByTestId('delete-button')).not.toHaveClass(/danger/),\n  ).toThrow()\n\n  expect(() =>\n    expect(queryByTestId('delete-button')).toHaveClass(/dangerous/),\n  ).toThrow()\n})\n\ntest('.toHaveClass with exact mode option', () => {\n  const {queryByTestId} = renderElementWithClasses()\n\n  expect(queryByTestId('delete-button')).toHaveClass('btn extra btn-danger', {\n    exact: true,\n  })\n  expect(queryByTestId('delete-button')).not.toHaveClass('btn extra', {\n    exact: true,\n  })\n  expect(queryByTestId('delete-button')).not.toHaveClass(\n    'btn extra btn-danger foo',\n    {exact: true},\n  )\n\n  expect(queryByTestId('delete-button')).toHaveClass('btn extra btn-danger', {\n    exact: false,\n  })\n  expect(queryByTestId('delete-button')).toHaveClass('btn extra', {\n    exact: false,\n  })\n  expect(queryByTestId('delete-button')).not.toHaveClass(\n    'btn extra btn-danger foo',\n    {exact: false},\n  )\n\n  expect(queryByTestId('delete-button')).toHaveClass(\n    'btn',\n    'extra',\n    'btn-danger',\n    {exact: true},\n  )\n  expect(queryByTestId('delete-button')).not.toHaveClass('btn', 'extra', {\n    exact: true,\n  })\n  expect(queryByTestId('delete-button')).not.toHaveClass(\n    'btn',\n    'extra',\n    'btn-danger',\n    'foo',\n    {exact: true},\n  )\n\n  expect(queryByTestId('delete-button')).toHaveClass(\n    'btn',\n    'extra',\n    'btn-danger',\n    {exact: false},\n  )\n  expect(queryByTestId('delete-button')).toHaveClass('btn', 'extra', {\n    exact: false,\n  })\n  expect(queryByTestId('delete-button')).not.toHaveClass(\n    'btn',\n    'extra',\n    'btn-danger',\n    'foo',\n    {exact: false},\n  )\n\n  expect(queryByTestId('only-one-class')).toHaveClass('alone', {exact: true})\n  expect(queryByTestId('only-one-class')).not.toHaveClass('alone foo', {\n    exact: true,\n  })\n  expect(queryByTestId('only-one-class')).not.toHaveClass('alone', 'foo', {\n    exact: true,\n  })\n\n  expect(queryByTestId('only-one-class')).toHaveClass('alone', {exact: false})\n  expect(queryByTestId('only-one-class')).not.toHaveClass('alone foo', {\n    exact: false,\n  })\n  expect(queryByTestId('only-one-class')).not.toHaveClass('alone', 'foo', {\n    exact: false,\n  })\n\n  expect(() =>\n    expect(queryByTestId('only-one-class')).not.toHaveClass('alone', {\n      exact: true,\n    }),\n  ).toThrow(/Expected the element not to have EXACTLY defined classes/)\n\n  expect(() =>\n    expect(queryByTestId('only-one-class')).toHaveClass('alone', 'foo', {\n      exact: true,\n    }),\n  ).toThrow(/Expected the element to have EXACTLY defined classes/)\n})\n\ntest('.toHaveClass combining {exact:true} and regular expressions throws an error', () => {\n  const {queryByTestId} = renderElementWithClasses()\n\n  expect(() =>\n    // @ts-expect-error regexp is not supported with exact\n    expect(queryByTestId('delete-button')).not.toHaveClass(/btn/, {\n      exact: true,\n    }),\n  ).toThrow()\n\n  expect(() =>\n    expect(queryByTestId('delete-button')).not.toHaveClass(\n      // @ts-expect-error regexp is not supported with exact\n      /-danger$/,\n      'extra',\n      /\\bbtn/,\n      {exact: true},\n    ),\n  ).toThrow()\n\n  expect(() =>\n    // @ts-expect-error regexp is not supported with exact\n    expect(queryByTestId('delete-button')).toHaveClass(/danger/, {exact: true}),\n  ).toThrow()\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveDisplayValue.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { render } from './utils'\n\nit('should work as expected', () => {\n  const {getInputByTestId} = render(`\n    <select id=\"fruits\" data-testid=\"select\">\n      <option value=\"\">Select a fruit...</option>\n      <option value=\"ananas\">Ananas</option>\n      <option value=\"banana\">Banana</option>\n      <option value=\"avocado\">Avocado</option>\n    </select>\n  `)\n\n  expect(getInputByTestId('select')).toHaveDisplayValue('Select a fruit...')\n  expect(getInputByTestId('select')).not.toHaveDisplayValue('Select')\n  expect(getInputByTestId('select')).not.toHaveDisplayValue('Banana')\n  expect(() =>\n    expect(getInputByTestId('select')).not.toHaveDisplayValue('Select a fruit...'),\n  ).toThrow()\n  expect(() =>\n    expect(getInputByTestId('select')).toHaveDisplayValue('Ananas'),\n  ).toThrow()\n\n  getInputByTestId('select').value = 'banana'\n  expect(getInputByTestId('select')).toHaveDisplayValue('Banana')\n  expect(getInputByTestId('select')).toHaveDisplayValue(/[bB]ana/)\n})\n\ndescribe('with multiple select', () => {\n  function mount() {\n    return render(`\n      <select id=\"fruits\" data-testid=\"select\" multiple>\n        <option value=\"\">Select a fruit...</option>\n        <option value=\"ananas\" selected>Ananas</option>\n        <option value=\"banana\">Banana</option>\n        <option value=\"avocado\" selected>Avocado</option>\n      </select>\n    `)\n  }\n\n  it('matches only when all the multiple selected values are equal to all the expected values', () => {\n    const subject = mount()\n    expect(subject.queryByTestId('select')).toHaveDisplayValue([\n      'Ananas',\n      'Avocado',\n    ])\n    expect(() =>\n      expect(subject.queryByTestId('select')).not.toHaveDisplayValue([\n        'Ananas',\n        'Avocado',\n      ]),\n    ).toThrow()\n    expect(subject.queryByTestId('select')).not.toHaveDisplayValue([\n      'Ananas',\n      'Avocado',\n      'Orange',\n    ])\n    expect(subject.queryByTestId('select')).not.toHaveDisplayValue('Ananas')\n    expect(() =>\n      expect(subject.queryByTestId('select')).toHaveDisplayValue('Ananas'),\n    ).toThrow()\n\n    Array.from((subject.queryByTestId('select') as HTMLSelectElement).options).forEach(option => {\n      option.selected = ['ananas', 'banana'].includes(option.value)\n    })\n\n    expect(subject.queryByTestId('select')).toHaveDisplayValue([\n      'Ananas',\n      'Banana',\n    ])\n  })\n\n  it('matches even when the expected values are unordered', () => {\n    const subject = mount()\n    expect(subject.queryByTestId('select')).toHaveDisplayValue([\n      'Avocado',\n      'Ananas',\n    ])\n  })\n\n  it('matches with regex expected values', () => {\n    const subject = mount()\n    expect(subject.queryByTestId('select')).toHaveDisplayValue([\n      /[Aa]nanas/,\n      'Avocado',\n    ])\n  })\n})\n\nit('should work with input elements', () => {\n  const {getInputByTestId} = render(`\n    <input type=\"text\" data-testid=\"input\" value=\"Luca\" />\n  `)\n\n  expect(getInputByTestId('input')).toHaveDisplayValue('Luca')\n  expect(getInputByTestId('input')).toHaveDisplayValue(/Luc/)\n\n  getInputByTestId('input').value = 'Piero'\n  expect(getInputByTestId('input')).toHaveDisplayValue('Piero')\n})\n\nit('should work with textarea elements', () => {\n  const {getInputByTestId} = render(\n    '<textarea data-testid=\"textarea-example\">An example description here.</textarea>',\n  )\n\n  expect(getInputByTestId('textarea-example')).toHaveDisplayValue(\n    'An example description here.',\n  )\n  expect(getInputByTestId('textarea-example')).toHaveDisplayValue(/example/)\n\n  getInputByTestId('textarea-example').value = 'Another example'\n  expect(getInputByTestId('textarea-example')).toHaveDisplayValue(\n    'Another example',\n  )\n})\n\nit('should throw if element is not valid', () => {\n  const {queryByTestId} = render(`\n    <div data-testid=\"div\">Banana</div>\n    <input type=\"radio\" data-testid=\"radio\" value=\"Something\" />\n    <input type=\"checkbox\" data-testid=\"checkbox\" />\n  `)\n\n  let errorMessage\n  try {\n    expect(queryByTestId('div')).toHaveDisplayValue('Banana')\n  } catch (err) {\n    errorMessage = err.message\n  }\n\n  expect(errorMessage).toMatchInlineSnapshot(\n    `.toHaveDisplayValue() currently supports only input, textarea or select elements, try with another matcher instead.`,\n  )\n\n  try {\n    expect(queryByTestId('radio')).toHaveDisplayValue('Something')\n  } catch (err) {\n    errorMessage = err.message\n  }\n\n  expect(errorMessage).toMatchInlineSnapshot(\n    `.toHaveDisplayValue() currently does not support input[type=\"radio\"], try with another matcher instead.`,\n  )\n\n  try {\n    // @ts-expect-error\n    expect(queryByTestId('checkbox')).toHaveDisplayValue(true)\n  } catch (err) {\n    errorMessage = err.message\n  }\n\n  expect(errorMessage).toMatchInlineSnapshot(\n    `.toHaveDisplayValue() currently does not support input[type=\"checkbox\"], try with another matcher instead.`,\n  )\n})\n\nit('should work with numbers', () => {\n  const {queryByTestId} = render(`\n    <select data-testid=\"select\">\n      <option value=\"\">1</option>\n    </select>\n  `)\n\n  expect(queryByTestId('select')).toHaveDisplayValue(1)\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveFocus.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { render } from './utils'\n\ntest('.toHaveFocus', () => {\n  const {container} = render(`\n      <div>\n        <label for=\"focused\">test</label>\n        <input id=\"focused\" type=\"text\" />\n        <button type=\"submit\" id=\"not-focused\">Not Focused</button>\n      </div>`)\n\n  const focused = container.querySelector('#focused') as HTMLInputElement\n  const notFocused = container.querySelector('#not-focused')\n\n  document.body.appendChild(container)\n  focused.focus()\n\n  expect(focused).toHaveFocus()\n  expect(notFocused).not.toHaveFocus()\n\n  expect(() => expect(focused).not.toHaveFocus()).toThrow()\n  expect(() => expect(notFocused).toHaveFocus()).toThrow()\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveFormValues.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { render } from './utils'\n\nconst categories = [\n  {value: '', label: '–'},\n  {value: 'design', label: 'Design'},\n  {value: 'ux', label: 'User Experience'},\n  {value: 'programming', label: 'Programming'},\n]\n\nconst skills = [\n  {value: 'c-sharp', label: 'C#'},\n  {value: 'graphql', label: 'GraphQl'},\n  {value: 'javascript', label: 'JavaScript'},\n  {value: 'ruby-on-rails', label: 'Ruby on Rails'},\n  {value: 'python', label: 'Python'},\n]\n\nconst defaultValues = {\n  title: 'Full-stack developer',\n  salary: 12345,\n  category: 'programming',\n  skills: ['javascript', 'ruby-on-rails'],\n  description: 'You need to know your stuff',\n  remote: true,\n  freelancing: false,\n  'is%Private^': true,\n  'benefits[0]': 'Fruit & free drinks everyday',\n  'benefits[1]': 'Multicultural environment',\n}\n\nfunction renderForm({\n  selectSingle = renderSelectSingle,\n  selectMultiple = renderSelectMultiple,\n  values: valueOverrides = {},\n} = {}) {\n  const values = {\n    ...defaultValues,\n    ...valueOverrides,\n  }\n  const {container} = render(`\n    <form>\n      <label for=\"title\">Job title</label>\n      <input\n        type=\"text\"\n        id=\"title\"\n        name=\"title\"\n        value=\"${values.title || ''}\"\n      />\n\n      <label for=\"salary\">Salary</label>\n      <input\n        type=\"number\"\n        id=\"salary\"\n        name=\"salary\"\n        value=\"${values.salary}\"\n      />\n\n      <label for=\"description\">Description</label>\n      <textarea id=\"description\" name=\"description\">${\n        values.description\n      }</textarea>\n\n      <input\n        type=\"checkbox\"\n        id=\"remote\"\n        name=\"remote\" ${values.remote ? 'checked' : ''}\n      />\n      <label for=\"remote\">Can work remotely?</label>\n\n      <input\n        type=\"checkbox\"\n        id=\"freelancing\"\n        name=\"freelancing\" ${values.freelancing ? 'checked' : ''}\n      />\n      <label for=\"freelancing\">Freelancing?</label>\n\n      <fieldset>\n        <legend>Benefits</legend>\n        <input\n          type=\"text\"\n          id=\"benefits[0]\"\n          name=\"benefits[0]\"\n          value=\"${values['benefits[0]']}\"\n        />\n        <input\n          type=\"text\"\n          id=\"benefits[1]\"\n          name=\"benefits[1]\"\n          value=\"${values['benefits[1]']}\"\n        />\n      </fieldset>\n\n      <label for=\"is%Private^\">Is Private</label>\n      <input\n        type=\"checkbox\"\n        id=\"is%Private^\"\n        name=\"is%Private^\"\n        name=\"isPrivate\" ${values['is%Private^'] ? 'checked' : ''}\n      />\n\n      ${selectSingle('category', 'Category', categories, values.category)}\n      ${selectMultiple('skills', 'Skills', skills, values.skills)}\n    </form>\n  `)\n  return container.querySelector('form')\n}\n\ndescribe('.toHaveFormValues', () => {\n  it('works as expected', () => {\n    expect(renderForm()).toHaveFormValues(defaultValues)\n  })\n\n  it('allows to match partially', () => {\n    expect(renderForm()).toHaveFormValues({\n      category: 'programming',\n      salary: 12345,\n    })\n  })\n\n  it('supports checkboxes for multiple selection', () => {\n    expect(renderForm({selectMultiple: renderCheckboxes})).toHaveFormValues({\n      skills: ['javascript', 'ruby-on-rails'],\n    })\n  })\n\n  it('supports radio-buttons for single selection', () => {\n    expect(renderForm({selectSingle: renderRadioButtons})).toHaveFormValues({\n      category: 'programming',\n    })\n  })\n\n  it('matches sets of selected values regardless of the order', () => {\n    const form = renderForm()\n    expect(form).toHaveFormValues({\n      skills: ['ruby-on-rails', 'javascript'],\n    })\n    expect(form).toHaveFormValues({\n      skills: ['javascript', 'ruby-on-rails'],\n    })\n  })\n\n  it('correctly handles empty values', () => {\n    expect(\n      renderForm({\n        values: {\n          title: '',\n          salary: null,\n          category: null,\n          skills: [],\n          description: '',\n        },\n      }),\n    ).toHaveFormValues({\n      title: '',\n      salary: null,\n      category: '',\n      skills: [],\n      description: '',\n    })\n  })\n\n  it('handles <input type=\"number\"> values correctly', () => {\n    expect(renderForm({values: {salary: 123.456}})).toHaveFormValues({\n      salary: 123.456,\n    })\n    expect(renderForm({values: {salary: '1e5'}})).toHaveFormValues({\n      salary: 1e5,\n    })\n    expect(renderForm({values: {salary: '1.35e5'}})).toHaveFormValues({\n      salary: 135000,\n    })\n    expect(renderForm({values: {salary: '-5.9'}})).toHaveFormValues({\n      salary: -5.9,\n    })\n  })\n\n  describe('edge cases', () => {\n    // This is also to ensure 100% code coverage for edge cases\n    it('detects multiple elements with the same name but different type', () => {\n      const {container} = render(`\n        <form>\n          <input type=\"checkbox\" name=\"accept\">\n          <input type=\"radio\" name=\"accept\">\n        </form>\n      `)\n      const form = container.querySelector('form')\n      expect(() => {\n        expect(form).toHaveFormValues({})\n      }).toThrow(/must be of the same type/)\n    })\n\n    it('detects multiple elements with the same type and name', () => {\n      const {container} = render(`\n        <form>\n          <input type=\"text\" name=\"title\" value=\"one\">\n          <input type=\"text\" name=\"title\" value=\"two\">\n        </form>\n      `)\n      const form = container.querySelector('form')\n      expect(form).toHaveFormValues({\n        title: ['one', 'two'],\n      })\n    })\n\n    it('supports radio buttons with none selected', () => {\n      expect(\n        renderForm({\n          selectSingle: renderRadioButtons,\n          values: {category: undefined},\n        }),\n      ).toHaveFormValues({\n        category: undefined,\n      })\n    })\n\n    it('supports being called only on form and fieldset elements', () => {\n      const expectedValues = {title: 'one', description: 'two'}\n      const {container} = render(`\n        <form>\n          <input type=\"text\" name=\"title\" value=\"one\">\n          <input type=\"text\" name=\"description\" value=\"two\">\n        </form>\n      `)\n      const form = container.querySelector('form')\n      expect(() => {\n        expect(container).toHaveFormValues(expectedValues)\n      }).toThrow(/a form or a fieldset/)\n      expect(() => {\n        expect(form).toHaveFormValues(expectedValues)\n      }).not.toThrow()\n    })\n\n    it('matches change in selected value of select', () => {\n      const oldValue = ''\n      const newValue = 'design'\n\n      const {container} = render(`\n        <form>\n          ${renderSelectSingle('category', 'Category', categories, oldValue)}\n        </form>\n      `)\n\n      const form = container.querySelector('form')\n      const select = container.querySelector('select')\n      expect(form).toHaveFormValues({category: oldValue})\n\n      select.value = newValue\n      expect(form).toHaveFormValues({category: newValue})\n    })\n  })\n\n  describe('failed assertions', () => {\n    it('work as expected', () => {\n      expect(() => {\n        expect(renderForm()).not.toHaveFormValues(defaultValues)\n      }).toThrow(/Expected the element not to have form values/)\n      expect(() => {\n        expect(renderForm()).toHaveFormValues({something: 'missing'})\n      }).toThrow(/Expected the element to have form values/)\n    })\n  })\n})\n\n// Form control renderers\n\nfunction isSelected(value, option) {\n  return Array.isArray(value) && value.indexOf(option.value) >= 0\n}\n\nfunction renderCheckboxes(name, label, options, value = []) {\n  return `\n    <fieldset>\n      <legend>${label}</legend>\n      ${renderList(\n        options,\n        option => `\n          <div>\n            <input\n              type=\"checkbox\"\n              name=\"${name}[]\"\n              id=\"${option.value}\"\n              value=\"${option.value}\"\n              ${isSelected(value, option) ? 'checked' : ''}\n            />\n            <label for=\"${option.value}\">${option.label}</label>\n          </div>\n        `,\n      )}\n    </fieldset>\n  `\n}\n\nfunction renderRadioButtons(name, label, options, value = undefined) {\n  return `\n    <fieldset>\n      <legend>${label}</legend>\n      ${renderList(\n        options,\n        option => `\n          <div>\n            <input\n              type=\"radio\"\n              name=\"${name}\"\n              id=\"${option.value}\"\n              value=\"${option.value}\"\n              ${value === option.value ? 'checked' : ''}\n            />\n            <label for=\"${option.value}\">${option.label}</label>\n          </div>\n        `,\n      )}\n    </fieldset>\n  `\n}\n\nfunction renderSelect(name, label, options, value, multiple) {\n  return `\n    <label for=\"${name}\">${label}</label>\n    <select id=\"${name}\" name=\"${name}\" ${multiple ? 'multiple' : ''}>\n      ${renderList(\n        options,\n        option => `\n          <option\n            value=\"${option.value}\"\n            ${isSelected(value, option) ? 'selected' : ''}\n          >\n            ${option.label}\n          </option>\n        `,\n      )}\n    </select>\n  `\n}\n\nfunction renderSelectSingle(name, label, options, value = undefined) {\n  return renderSelect(\n    name,\n    label,\n    options,\n    value === undefined || value === null ? [] : [value],\n    false,\n  )\n}\n\nfunction renderSelectMultiple(name, label, options, value = []) {\n  return renderSelect(name, label, options, value, true)\n}\n\nfunction renderList(items, mapper) {\n  return items.map(mapper).join('')\n}"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveLength.test.ts",
    "content": "import { describe, expect, test } from 'vitest';\nimport { render } from './utils';\nimport { page } from 'vitest/browser';\n\ndescribe('.toHaveLength', () => {\n  test('accepts locator', async () => {\n    render(`\n      <button></button>\n      <button></button>\n      <button></button>\n    `)\n\n    await expect.element(page.getByRole('button')).toHaveLength(3)\n    await expect.element(page.getByRole('button')).not.toHaveLength(0)\n\n    expect(page.getByRole('button')).toHaveLength(3)\n    expect(page.getByRole('button')).not.toHaveLength(0)\n  })\n})\n"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveRole.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { render } from './utils'\n\ndescribe('.toHaveRole', () => {\n  it('matches implicit role', () => {\n    const {queryByTestId} = render(`\n      <div>\n        <button data-testid=\"continue-button\">Continue</button>\n      </div>\n    `)\n\n    const continueButton = queryByTestId('continue-button')\n\n    expect(continueButton).not.toHaveRole('listitem')\n    expect(continueButton).toHaveRole('button')\n\n    expect(() => {\n      expect(continueButton).toHaveRole('listitem')\n    }).toThrow(/expected element to have role/i)\n    expect(() => {\n      expect(continueButton).not.toHaveRole('button')\n    }).toThrow(/expected element not to have role/i)\n  })\n\n  it('matches explicit role', () => {\n    const {queryByTestId} = render(`\n      <div>\n        <div role=\"button\" data-testid=\"continue-button\">Continue</div>\n      </div>\n    `)\n\n    const continueButton = queryByTestId('continue-button')\n\n    expect(continueButton).not.toHaveRole('listitem')\n    expect(continueButton).toHaveRole('button')\n\n    expect(() => {\n      expect(continueButton).toHaveRole('listitem')\n    }).toThrow(/expected element to have role/i)\n    expect(() => {\n      expect(continueButton).not.toHaveRole('button')\n    }).toThrow(/expected element not to have role/i)\n  })\n\n  it('matches multiple explicit roles', () => {\n    const {queryByTestId} = render(`\n      <div>\n        <div role=\"button switch\" data-testid=\"continue-button\">Continue</div>\n      </div>\n    `)\n\n    const continueButton = queryByTestId('continue-button')\n\n    expect(continueButton).not.toHaveRole('listitem')\n    expect(continueButton).toHaveRole('button')\n    expect(continueButton).not.toHaveRole('switch')\n\n    expect(() => {\n      expect(continueButton).toHaveRole('listitem')\n    }).toThrow(/expected element to have role/i)\n    expect(() => {\n      expect(continueButton).not.toHaveRole('button')\n    }).toThrow(/expected element not to have role/i)\n  })\n})\n"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveSelection.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { render } from './utils'\n\ndescribe('.toHaveSelection', () => {\n  test.each(['text', 'password', 'textarea'])(\n    'handles selection within form elements',\n    testId => {\n      const {getInputByTestId} = render(`\n        <input type=\"text\" value=\"text selected text\" data-testid=\"text\" />\n        <input type=\"password\" value=\"text selected text\" data-testid=\"password\" />\n        <textarea data-testid=\"textarea\">text selected text</textarea>\n    `)\n\n      getInputByTestId(testId).setSelectionRange(5, 13)\n      expect(getInputByTestId(testId)).toHaveSelection('selected')\n\n      getInputByTestId(testId).select()\n      expect(getInputByTestId(testId)).toHaveSelection('text selected text')\n    },\n  )\n\n  test.each(['checkbox', 'radio'])(\n    'returns empty string for form elements without text',\n    testId => {\n      const {getInputByTestId} = render(`\n        <input type=\"checkbox\" value=\"checkbox\" data-testid=\"checkbox\" />\n        <input type=\"radio\" value=\"radio\" data-testid=\"radio\" />\n    `)\n\n      getInputByTestId(testId).select()\n      expect(getInputByTestId(testId)).toHaveSelection('')\n    },\n  )\n\n  test('does not match subset string', () => {\n    const {getInputByTestId} = render(`\n        <input type=\"text\" value=\"text selected text\" data-testid=\"text\" />\n    `)\n\n    getInputByTestId('text').setSelectionRange(5, 13)\n    expect(getInputByTestId('text')).not.toHaveSelection('select')\n    expect(getInputByTestId('text')).toHaveSelection('selected')\n  })\n\n  test('accepts any selection when expected selection is missing', () => {\n    const {getInputByTestId} = render(`\n        <input type=\"text\" value=\"text selected text\" data-testid=\"text\" />\n    `)\n\n    expect(getInputByTestId('text')).not.toHaveSelection()\n\n    getInputByTestId('text').setSelectionRange(5, 13)\n\n    expect(getInputByTestId('text')).toHaveSelection()\n  })\n\n  test('throws when form element is not selected', () => {\n    const {queryByTestId} = render(`\n        <input type=\"text\" value=\"text selected text\" data-testid=\"text\" />\n    `)\n\n    expect(() =>\n      expect(queryByTestId('text')).toHaveSelection(),\n    ).toThrowErrorMatchingInlineSnapshot(`\n      [Error: expect(element).toHaveSelection(expected)\n\n      Expected the element to have selection:\n        (any)\n      Received:\n      ]\n    `)\n  })\n\n  test('throws when form element is selected', () => {\n    const {getInputByTestId} = render(`\n        <input type=\"text\" value=\"text selected text\" data-testid=\"text\" />\n    `)\n    getInputByTestId('text').setSelectionRange(5, 13)\n\n    expect(() =>\n      expect(getInputByTestId('text')).not.toHaveSelection(),\n    ).toThrowErrorMatchingInlineSnapshot(`\n      [Error: expect(element).not.toHaveSelection(expected)\n\n      Expected the element not to have selection:\n        (any)\n      Received:\n        selected]\n    `)\n  })\n\n  test('throws when element is not selected', () => {\n    const {queryByTestId} = render(`\n        <div data-testid=\"text\">text</div>\n    `)\n\n    expect(() =>\n      expect(queryByTestId('text')).toHaveSelection(),\n    ).toThrowErrorMatchingInlineSnapshot(`\n      [Error: expect(element).toHaveSelection(expected)\n\n      Expected the element to have selection:\n        (any)\n      Received:\n      ]\n    `)\n  })\n\n  test('throws when element selection does not match', () => {\n    const {getInputByTestId} = render(`\n        <input type=\"text\" value=\"text selected text\" data-testid=\"text\" />\n    `)\n    getInputByTestId('text').setSelectionRange(0, 4)\n\n    expect(() =>\n      expect(getInputByTestId('text')).toHaveSelection('no match'),\n    ).toThrowErrorMatchingInlineSnapshot(`\n      [Error: expect(element).toHaveSelection(no match)\n\n      Expected the element to have selection:\n        no match\n      Received:\n        text]\n    `)\n  })\n\n  test('handles selection within text nodes', () => {\n    const {queryByTestId} = render(`\n\t\t\t<div>\n        <div data-testid=\"prev\">prev</div>\n        <div data-testid=\"parent\">text <span data-testid=\"child\">selected</span> text</div>\n        <div data-testid=\"next\">next</div>\n\t\t\t</div>\n    `)\n\n    const selection = queryByTestId('child').ownerDocument.getSelection()\n    const range = queryByTestId('child').ownerDocument.createRange()\n    selection.removeAllRanges()\n\t\tselection.empty()\n    selection.addRange(range)\n\n    range.selectNodeContents(queryByTestId('child'))\n\n    expect(queryByTestId('child')).toHaveSelection('selected')\n    expect(queryByTestId('parent')).toHaveSelection('selected')\n\n    range.selectNodeContents(queryByTestId('parent'))\n\n    expect(queryByTestId('child')).toHaveSelection('selected')\n    expect(queryByTestId('parent')).toHaveSelection('text selected text')\n\n    range.setStart(queryByTestId('prev'), 0)\n    range.setEnd(queryByTestId('child').childNodes[0], 3)\n\n    expect(queryByTestId('prev')).toHaveSelection('prev')\n    expect(queryByTestId('child')).toHaveSelection('sel')\n    expect(queryByTestId('parent')).toHaveSelection('text sel')\n    expect(queryByTestId('next')).not.toHaveSelection()\n\n    range.setStart(queryByTestId('child').childNodes[0], 3)\n    range.setEnd(queryByTestId('next').childNodes[0], 2)\n\n    expect(queryByTestId('child')).toHaveSelection('ected')\n    expect(queryByTestId('parent')).toHaveSelection('ected text')\n    expect(queryByTestId('prev')).not.toHaveSelection()\n    expect(queryByTestId('next')).toHaveSelection('ne')\n  })\n\n  test('throws with information when the expected selection is not string', () => {\n    const {container} = render(`<div>1</div>`)\n    const element = container.firstChild\n    const range = element.ownerDocument.createRange()\n    range.selectNodeContents(element)\n    element.ownerDocument.getSelection().addRange(range)\n\n    expect(() =>\n      // @ts-expect-error wrong type\n      expect(element).toHaveSelection(1),\n    ).toThrowErrorMatchingInlineSnapshot(\n      `[Error: expected selection must be a string or undefined]`\n    )\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveStyle.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { render } from './utils'\n\ndescribe('.toHaveStyle', () => {\n  test('handles positive test cases', () => {\n    const { container } = render(`\n          <div class=\"label\" style=\"background-color: blue; height: 100%;\">\n            Hello World\n          </div>\n        `)\n\n    const style = document.createElement('style')\n    style.innerHTML = `\n          .label {\n            align-items: center;\n            background-color: black;\n            color: white;\n            float: left;\n            transition: opacity 0.2s ease-out, top 0.3s cubic-bezier(0.1, 0.7, 1.0, 0.1);\n            transform: translateX(0px);\n          }\n        `\n    document.body.appendChild(style)\n    document.body.appendChild(container)\n\n    // border: fakefake doesn't exist\n    expect(() => {\n      expect(container.querySelector('.label')).toHaveStyle('border: fakefake')\n    }).toThrow()\n\n    expect(container.querySelector('.label')).toHaveStyle(`\n          height: 100%;\n          color: white;\n          background-color: blue;\n        `)\n\n    expect(container.querySelector('.label')).toHaveStyle(`\n          background-color: blue;\n          color: white;\n        `)\n\n    expect(container.querySelector('.label')).toHaveStyle(\n      'transition: opacity 0.2s ease-out, top 0.3s cubic-bezier(0.1, 0.7, 1.0, 0.1)',\n    )\n\n    expect(container.querySelector('.label')).toHaveStyle(\n      'background-color:blue;color:white',\n    )\n\n    expect(container.querySelector('.label')).not.toHaveStyle(`\n          color: white;\n          font-weight: bold;\n        `)\n\n    expect(container.querySelector('.label')).toHaveStyle(`\n        Align-items: center;\n      `)\n\n    expect(container.querySelector('.label')).toHaveStyle(`\n      transform: translateX(0px);\n    `)\n  })\n\n  test('handles negative test cases', () => {\n    const { container } = render(`\n    <div class=\"label\" style=\"background-color: blue; height: 100%\">\n      Hello World\n    </div>\n  `)\n\n    const style = document.createElement('style')\n    style.innerHTML = `\n    .label {\n      background-color: black;\n      color: white;\n      float: left;\n      --var-name: 0px;\n      transition: opacity 0.2s ease-out, top 0.3s cubic-bezier(1.175, 0.885, 0.32, 1.275);\n    }\n  `\n    document.body.appendChild(style)\n    document.body.appendChild(container)\n\n    // CSS parser is forgiving, it doesn't throw\n    // expect(() =>\n    //   expect(container.querySelector('.label')).not.toHaveStyle(\n    //     'font-weight bold',\n    //   ),\n    // ).toThrow()\n\n    expect(() =>\n      expect(container.querySelector('.label')).toHaveStyle(\n        'font-weight: bold',\n      ),\n    ).toThrow()\n\n    expect(() =>\n      expect(container.querySelector('.label')).not.toHaveStyle('color: white'),\n    ).toThrow()\n\n    expect(() =>\n      expect(container.querySelector('.label')).toHaveStyle(\n        'transition: all 0.7s ease, width 1.0s cubic-bezier(3, 4, 5, 6);',\n      ),\n    ).toThrow()\n\n    // Custom property names are case sensitive\n    expect(() =>\n      expect(container.querySelector('.label')).toHaveStyle('--VAR-NAME: 0px;'),\n    ).toThrow()\n\n    expect(() =>\n      expect(container.querySelector('.label')).toHaveStyle('color white'),\n    ).toThrow()\n\n    expect(() =>\n      expect(container.querySelector('.label')).toHaveStyle('--color: black'),\n    ).toThrow()\n    document.body.removeChild(style)\n    document.body.removeChild(container)\n  })\n\n  test('properly normalizes colors', () => {\n    const { queryByTestId } = render(`\n      <span data-testid=\"color-example\" style=\"background-color: #123456\">Hello World</span>\n    `)\n    expect(queryByTestId('color-example')).toHaveStyle(\n      'background-color: #123456',\n    )\n  })\n\n  test('handles inline custom properties (with uppercase letters)', () => {\n    const { queryByTestId } = render(`\n      <span data-testid=\"color-example\" style=\"--accentColor: blue\">Hello World</span>\n    `)\n    expect(queryByTestId('color-example')).toHaveStyle('--accentColor: blue')\n  })\n\n  test('handles global custom properties', () => {\n    const style = document.createElement('style')\n    style.innerHTML = `\n      div {\n        --color: blue;\n      }\n    `\n\n    const { container } = render(`\n      <div>\n        Hello world\n      </div>\n    `)\n\n    document.body.appendChild(style)\n    document.body.appendChild(container)\n\n    expect(container).toHaveStyle(`--color: blue`)\n  })\n\n  test('properly normalizes colors for border', () => {\n    const { queryByTestId } = render(`\n    <span data-testid=\"color-example\" style=\"border: 1px solid #fff\">Hello World</span>\n  `)\n    expect(queryByTestId('color-example')).toHaveStyle('border: 1px solid #fff')\n  })\n\n  test('handles different color declaration formats', () => {\n    const { queryByTestId } = render(`\n      <span data-testid=\"color-example\" style=\"color: rgba(0, 0, 0, 1); background-color: #000000\">Hello World</span>\n    `)\n\n    expect(queryByTestId('color-example')).toHaveStyle('color: #000000')\n    expect(queryByTestId('color-example')).toHaveStyle(\n      'background-color: rgba(0, 0, 0, 1)',\n    )\n  })\n\n  test('handles nonexistent styles', () => {\n    const { container } = render(`\n          <div class=\"label\" style=\"background-color: blue; height: 100%\">\n            Hello World\n          </div>\n        `)\n\n    expect(container.querySelector('.label')).not.toHaveStyle(\n      'whatever: anything',\n    )\n  })\n\n  describe('object syntax', () => {\n    test('handles styles as object', () => {\n      const { container } = render(`\n        <div class=\"label\" style=\"background-color: blue; height: 100%\">\n          Hello World\n        </div>\n      `)\n\n      expect(container.querySelector('.label')).toHaveStyle({\n        backgroundColor: 'blue',\n      })\n      expect(container.querySelector('.label')).toHaveStyle({\n        backgroundColor: 'blue',\n        height: '100%',\n      })\n      expect(container.querySelector('.label')).not.toHaveStyle({\n        backgroundColor: 'red',\n        height: '100%',\n      })\n      expect(container.querySelector('.label')).not.toHaveStyle({\n        whatever: 'anything',\n      })\n    })\n\n    // https://github.com/testing-library/jest-dom/issues/350\n    test('Uses correct computed values', () => {\n      const { container } = render(`\n          <div class=\"label\">\n            Hello World\n          </div>\n      `)\n\n      const style = document.createElement('style')\n      style.innerHTML = `\n            .label {\n              color: #fff;\n              background-color: #000;\n            }\n          `\n      document.body.appendChild(style)\n      document.body.appendChild(container)\n\n      expect(container.querySelector('.label')).toHaveStyle('color: #FFF')\n    })\n\n    test('Uses px as the default unit', () => {\n      const { queryByTestId } = render(`\n        <span data-testid=\"color-example\" style=\"font-size: 12px\">Hello World</span>\n      `)\n      expect(queryByTestId('color-example')).toHaveStyle({\n        // in jest-dom '12' is converted to 12px\n        // but in the browser setting the style to 12 wil have no effect,\n        // so Vitest prioritizes the browser behavior\n        // fontSize: 12,\n        fontSize: '12px',\n      })\n    })\n\n    test('Fails with an invalid unit', () => {\n      const { queryByTestId } = render(`\n        <span data-testid=\"color-example\" style=\"font-size: 12rem\">Hello World</span>\n      `)\n      expect(() => {\n        expect(queryByTestId('color-example')).toHaveStyle({ fontSize: '12px' })\n      }).toThrow()\n    })\n\n    test('supports dash-cased property names', () => {\n      const { container } = render(`\n        <div class=\"label\" style=\"background-color: blue; height: 100%\">\n          Hello World\n        </div>\n      `)\n      expect(container.querySelector('.label')).toHaveStyle({\n        'background-color': 'blue',\n      })\n    })\n\n    test('requires strict empty properties matching', () => {\n      const { container } = render(`\n        <div class=\"label\" style=\"width: 100%;height: 100%\">\n          Hello World\n        </div>\n      `)\n      expect(container.querySelector('.label')).not.toHaveStyle({\n        width: '100%',\n        height: '',\n      })\n      expect(container.querySelector('.label')).not.toHaveStyle({\n        width: '',\n        height: '',\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveTextContent.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { render } from './utils'\n\ndescribe('.toHaveTextContent', () => {\n  test('handles positive test cases', () => {\n    const {queryByTestId} = render(`<span data-testid=\"count-value\">2</span>`)\n\n    expect(queryByTestId('count-value')).toHaveTextContent('2')\n    expect(queryByTestId('count-value')).toHaveTextContent(2)\n    expect(queryByTestId('count-value')).toHaveTextContent(/2/)\n    expect(queryByTestId('count-value')).not.toHaveTextContent('21')\n  })\n\n  test('handles text nodes', () => {\n    const {container} = render(`<span>example</span>`)\n\n    expect(container.querySelector('span').firstChild).toHaveTextContent(\n      'example',\n    )\n  })\n\n  test('handles fragments', () => {\n    const {asFragment} = render(`<span>example</span>`)\n\n    expect(asFragment()).toHaveTextContent('example')\n  })\n\n  test('handles negative test cases', () => {\n    const {queryByTestId} = render(`<span data-testid=\"count-value\">2</span>`)\n\n    expect(() =>\n      expect(queryByTestId('count-value2')).toHaveTextContent('2'),\n    ).toThrow()\n\n    expect(() =>\n      expect(queryByTestId('count-value')).toHaveTextContent('3'),\n    ).toThrow()\n    expect(() =>\n      expect(queryByTestId('count-value')).not.toHaveTextContent('2'),\n    ).toThrow()\n  })\n\n  test('normalizes whitespace by default', () => {\n    const {container} = render(`\n      <span>\n        Step\n          1\n            of\n              4\n      </span>\n    `)\n\n    expect(container.querySelector('span')).toHaveTextContent('Step 1 of 4')\n  })\n\n  test('allows whitespace normalization to be turned off', () => {\n    const {container} = render(`<span>&nbsp;&nbsp;Step 1 of 4</span>`)\n\n    expect(container.querySelector('span')).toHaveTextContent('  Step 1 of 4', {\n      normalizeWhitespace: false,\n    })\n  })\n\n  test('can handle multiple levels', () => {\n    const {container} = render(`<span id=\"parent\"><span>Step 1 \n    \n    of 4</span></span>`)\n\n    expect(container.querySelector('#parent')).toHaveTextContent('Step 1 of 4')\n  })\n\n  test('can handle multiple levels with content spread across decendants', () => {\n    const {container} = render(`\n        <span id=\"parent\">\n            <span>Step</span>\n            <span>      1</span>\n            <span><span>of</span></span>\n\n\n            4</span>\n        </span>\n    `)\n\n    expect(container.querySelector('#parent')).toHaveTextContent('Step 1 of 4')\n  })\n\n  test('does not throw error with empty content', () => {\n    const {container} = render(`<span></span>`)\n    expect(container.querySelector('span')).toHaveTextContent('')\n  })\n\n  test('is case-sensitive', () => {\n    const {container} = render('<span>Sensitive text</span>')\n\n    expect(container.querySelector('span')).toHaveTextContent('Sensitive text')\n    expect(container.querySelector('span')).not.toHaveTextContent(\n      'sensitive text',\n    )\n  })\n\n  test('when matching with empty string and element with content, suggest using toBeEmptyDOMElement instead', () => {\n    // https://github.com/testing-library/jest-dom/issues/104\n    const {container} = render('<span>not empty</span>')\n\n    expect(() =>\n      expect(container.querySelector('span')).toHaveTextContent(''),\n    ).toThrow(/toBeEmptyDOMElement\\(\\)/)\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toHaveValue.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { render } from './utils'\n\ndescribe('.toHaveValue', () => {\n  test('handles value of text input', () => {\n    const {queryByTestId, getInputByTestId} = render(`\n        <input type=\"text\" value=\"foo\" data-testid=\"value\" />\n        <input type=\"text\" value=\"\"  data-testid=\"empty\" />\n        <input type=\"text\" data-testid=\"without\" />\n    `)\n\n    expect(queryByTestId('value')).toHaveValue('foo')\n    expect(queryByTestId('value')).toHaveValue()\n    expect(queryByTestId('value')).not.toHaveValue('bar')\n    expect(queryByTestId('value')).not.toHaveValue('')\n\n    expect(queryByTestId('empty')).toHaveValue('')\n    expect(queryByTestId('empty')).not.toHaveValue()\n    expect(queryByTestId('empty')).not.toHaveValue('foo')\n\n    expect(queryByTestId('without')).toHaveValue('')\n    expect(queryByTestId('without')).not.toHaveValue()\n    expect(queryByTestId('without')).not.toHaveValue('foo')\n    getInputByTestId('without').value = 'bar'\n    expect(queryByTestId('without')).toHaveValue('bar')\n  })\n\n  test('handles value of number input', () => {\n    const {queryByTestId, getInputByTestId} = render(`\n        <input type=\"number\" value=\"5\" data-testid=\"number\" />\n        <input type=\"number\" value=\"\"  data-testid=\"empty\" />\n        <input type=\"number\" data-testid=\"without\" />\n    `)\n\n    expect(queryByTestId('number')).toHaveValue(5)\n    expect(queryByTestId('number')).toHaveValue()\n    expect(queryByTestId('number')).not.toHaveValue(4)\n    expect(queryByTestId('number')).not.toHaveValue('5')\n\n    expect(queryByTestId('empty')).toHaveValue(null)\n    expect(queryByTestId('empty')).not.toHaveValue()\n    expect(queryByTestId('empty')).not.toHaveValue('5')\n\n    expect(queryByTestId('without')).toHaveValue(null)\n    expect(queryByTestId('without')).not.toHaveValue()\n    expect(queryByTestId('without')).not.toHaveValue('10')\n    // @ts-expect-error ts doesn't allow value to be a number, but browser will convert it\n    getInputByTestId('without').value = 10\n    expect(queryByTestId('without')).toHaveValue(10)\n  })\n\n  test('handles value of select element', () => {\n    const {queryByTestId} = render(`\n      <select data-testid=\"single\">\n        <option value=\"first\">First Value</option>\n        <option value=\"second\" selected>Second Value</option>\n        <option value=\"third\">Third Value</option>\n      </select>\n\n      <select data-testid=\"multiple\" multiple>\n        <option value=\"first\">First Value</option>\n        <option value=\"second\" selected>Second Value</option>\n        <option value=\"third\" selected>Third Value</option>\n      </select>\n\n      <select data-testid=\"not-selected\" >\n        <option value=\"\" disabled selected>- Select some value - </option>\n        <option value=\"first\">First Value</option>\n        <option value=\"second\">Second Value</option>\n        <option value=\"third\">Third Value</option>\n      </select>\n    `)\n\n    expect(queryByTestId('single')).toHaveValue('second')\n    expect(queryByTestId('single')).toHaveValue()\n\n    expect(queryByTestId('multiple')).toHaveValue(['second', 'third'])\n    expect(queryByTestId('multiple')).toHaveValue()\n\n    expect(queryByTestId('not-selected')).not.toHaveValue()\n    expect(queryByTestId('not-selected')).toHaveValue('')\n\n    queryByTestId('single').children[0].setAttribute('selected', 'true')\n    expect(queryByTestId('single')).toHaveValue('first')\n  })\n\n  test('handles value of textarea element', () => {\n    const {queryByTestId} = render(`\n      <textarea data-testid=\"textarea\">text value</textarea>\n    `)\n    expect(queryByTestId('textarea')).toHaveValue('text value')\n  })\n\n  test('throws when passed checkbox or radio', () => {\n    const {queryByTestId} = render(`\n        <input data-testid=\"checkbox\" type=\"checkbox\" name=\"checkbox\" value=\"val\" checked />\n        <input data-testid=\"radio\" type=\"radio\" name=\"radio\" value=\"val\" checked />\n    `)\n\n    expect(() => {\n      expect(queryByTestId('checkbox')).toHaveValue('')\n    }).toThrow()\n\n    expect(() => {\n      expect(queryByTestId('radio')).toHaveValue('')\n    }).toThrow()\n  })\n\n  test('throws when the expected input value does not match', () => {\n    const {container} = render(`<input data-testid=\"one\" value=\"foo\" />`)\n    const input = container.firstChild\n    let errorMessage\n    try {\n      expect(input).toHaveValue('something else')\n    } catch (error) {\n      errorMessage = error.message\n    }\n\n    expect(errorMessage).toMatchInlineSnapshot(`\n      expect(element).toHaveValue(something else)\n\n      Expected the element to have value:\n        something else\n      Received:\n        foo\n    `)\n  })\n\n  test('throws with type information when the expected text input value has loose equality with received value', () => {\n    const {container} = render(`<input data-testid=\"one\" value=\"8\" />`)\n    const input = container.firstChild\n    let errorMessage\n    try {\n      expect(input).toHaveValue(8)\n    } catch (error) {\n      errorMessage = error.message\n    }\n\n    expect(errorMessage).toMatchInlineSnapshot(`\n      expect(element).toHaveValue(8)\n\n      Expected the element to have value:\n        8 (number)\n      Received:\n        8 (string)\n    `)\n  })\n\n  test('throws when using not but the expected input value does match', () => {\n    const {container} = render(`<input data-testid=\"one\" value=\"foo\" />`)\n    const input = container.firstChild\n    let errorMessage\n\n    try {\n      expect(input).not.toHaveValue('foo')\n    } catch (error) {\n      errorMessage = error.message\n    }\n    expect(errorMessage).toMatchInlineSnapshot(`\n      expect(element).not.toHaveValue(foo)\n\n      Expected the element not to have value:\n        foo\n      Received:\n        foo\n    `)\n  })\n\n  test('throws when the form has no a value but a value is expected', () => {\n    const {container} = render(`<input data-testid=\"one\" />`)\n    const input = container.firstChild\n    let errorMessage\n\n    try {\n      expect(input).toHaveValue()\n    } catch (error) {\n      errorMessage = error.message\n    }\n    expect(errorMessage).toMatchInlineSnapshot(`\n      expect(element).toHaveValue(expected)\n\n      Expected the element to have value:\n        (any)\n      Received:\n    `)\n  })\n\n  test('throws when the form has a value but none is expected', () => {\n    const {container} = render(`<input data-testid=\"one\" value=\"foo\" />`)\n    const input = container.firstChild\n    let errorMessage\n\n    try {\n      expect(input).not.toHaveValue()\n    } catch (error) {\n      errorMessage = error.message\n    }\n    expect(errorMessage).toMatchInlineSnapshot(`\n      expect(element).not.toHaveValue(expected)\n\n      Expected the element not to have value:\n        (any)\n      Received:\n        foo\n    `)\n  })\n\n  test('handles value of aria-valuenow', () => {\n    const valueToCheck = 70\n    const {queryByTestId} = render(`\n        <div role=\"meter\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"${valueToCheck}\" data-testid=\"meter\"></div>\n        <div role=\"textbox\" aria-valuenow=\"${valueToCheck}\" data-testid=\"textbox\"></div>\n    `)\n\n    expect(queryByTestId('meter')).toHaveValue(valueToCheck)\n    expect(queryByTestId('meter')).not.toHaveValue(valueToCheck + 1)\n\n    // Role that does not support aria-valuenow\n    expect(queryByTestId('textbox')).not.toHaveValue(70)\n  })\n})"
  },
  {
    "path": "test/browser/fixtures/expect-dom/toMatchScreenshot.test.ts",
    "content": "import { afterEach, describe, expect, test } from 'vitest'\nimport { extractToMatchScreenshotPaths, render } from './utils'\nimport { page, server } from 'vitest/browser'\nimport { join } from 'pathe'\n\nconst blockSize = 19\nconst blocks = 5\nconst dataTestId = 'colors-box'\n\nconst renderTestCase = (colors: readonly [string, string, string]) =>\n  render(`\n    <div style=\"--size: ${blockSize}px; display: flex; justify-content: center; height: var(--size); width: calc(var(--size) * ${blocks});\" data-testid=\"${dataTestId}\">\n      <div data-testid=\"${dataTestId}-1\" style=\"background-color: ${colors[0]}; width: var(--size);\"></div>\n      <div data-testid=\"${dataTestId}-2\" style=\"background-color: ${colors[1]}; width: var(--size);\"></div>\n      <div data-testid=\"${dataTestId}-3\" style=\"background-color: ${colors[2]}; width: var(--size);\"></div>\n    </div>\n  `)\n\ndeclare module 'vitest/browser' {\n  interface ScreenshotComparatorRegistry {\n    failing: Record<string, never>\n  }\n}\n\n/**\n * ## Screenshot Testing Strategy\n *\n * Tests create reference screenshots on-the-fly on demand, then compare\n * against them. References are cleaned up after each test.\n *\n * Screenshot references are unstable across environments (headless vs UI mode,\n * different operating systems, different browsers). Storing references for\n * every environment combination would create a maintenance burden.\n */\ndescribe('.toMatchScreenshot', () => {\n  test('compares screenshots correctly', async ({ onTestFinished }) => {\n    const filename = globalThis.crypto.randomUUID()\n    const path = join(\n      '__screenshots__',\n      'toMatchScreenshot.test.ts',\n      `${filename}-${server.browser}-${server.platform}.png`,\n    )\n\n    onTestFinished(async () => {\n      await server.commands.removeFile(path)\n    })\n\n    renderTestCase([\n      'oklch(39.6% 0.141 25.723)',\n      'oklch(40.5% 0.101 131.063)',\n      'oklch(37.9% 0.146 265.522)',\n    ])\n\n    const locator = page.getByTestId(dataTestId)\n\n    // Create a reference screenshot by explicitly saving one\n    await locator.screenshot({\n      save: true,\n      path,\n    })\n\n    // Test that `toMatchScreenshot()` correctly finds and compares against\n    // this reference; since the element hasn't changed, it should match\n    await expect(locator).toMatchScreenshot(filename)\n  })\n\n  // Only run this test if snapshots aren't being updated\n  test.runIf(server.config.snapshotOptions.updateSnapshot !== 'all')(\n    \"throws when screenshots don't match\",\n    async ({ onTestFinished }) => {\n      const filename = globalThis.crypto.randomUUID()\n      const path = join(\n        '__screenshots__',\n        'toMatchScreenshot.test.ts',\n        `${filename}-${server.browser}-${server.platform}.png`,\n      )\n\n      onTestFinished(async () => {\n        await server.commands.removeFile(path)\n      })\n\n      // Create reference with first color set\n      renderTestCase([\n        'oklch(39.6% 0.141 25.723)',\n        'oklch(40.5% 0.101 131.063)',\n        'oklch(37.9% 0.146 265.522)',\n      ])\n\n      const locator = page.getByTestId(dataTestId)\n\n      await locator.screenshot({\n        save: true,\n        path,\n      })\n\n      // Change to different colors - this should cause comparison to fail\n      renderTestCase([\n        'oklch(84.1% 0.238 128.85)',\n        'oklch(84.1% 0.238 128.85)',\n        'oklch(84.1% 0.238 128.85)',\n      ])\n\n      let errorMessage: string\n\n      try {\n        await expect(locator).toMatchScreenshot(filename)\n      } catch (error) {\n        errorMessage = error.message\n      }\n\n      const [referencePath, actualPath, diffPath] = extractToMatchScreenshotPaths(\n        errorMessage,\n        filename,\n      )\n\n      expect(referencePath).toMatch(new RegExp(`${path}$`))\n      expect(typeof actualPath).toBe('string')\n      expect(typeof diffPath).toBe('string')\n\n      onTestFinished(async () => {\n        await Promise.all([\n          server.commands.removeFile(actualPath),\n          server.commands.removeFile(diffPath),\n        ])\n      })\n\n      const { pixels, ratio } =\n        /(?<pixels>\\d+).*?ratio (?<ratio>[01]\\.\\d{2})/.exec(errorMessage)\n          ?.groups ?? {}\n\n      expect(pixels).toMatch(/\\d+/)\n      expect(ratio).toMatch(/[01]\\.\\d{2}/)\n\n      expect(errorMessage).toMatchInlineSnapshot(`\n        expect(element).toMatchScreenshot()\n\n        Screenshot does not match the stored reference.\n        ${pixels} pixels (ratio ${ratio}) differ.\n\n        Reference screenshot:\n          ${referencePath}\n\n        Actual screenshot:\n          ${actualPath}\n\n        Diff image:\n          ${diffPath}\n      `)\n    },\n  )\n\n  // Only run this test if snapshots aren't being updated\n  test.runIf(server.config.snapshotOptions.updateSnapshot !== 'all')(\n    'throws when creating a screenshot for the first time',\n    async ({\n      onTestFinished,\n    }) => {\n      const { queryByTestId } = renderTestCase([\n        'oklch(37.9% 0.146 265.522)',\n        'oklch(40.5% 0.101 131.063)',\n        'oklch(39.6% 0.141 25.723)',\n      ])\n\n      let errorMessage: string\n\n      const filename = globalThis.crypto.randomUUID()\n\n      try {\n        await expect(queryByTestId(dataTestId)).toMatchScreenshot(filename)\n      } catch (error) {\n        errorMessage = error.message\n      }\n\n      const [referencePath] = extractToMatchScreenshotPaths(errorMessage, filename)\n\n      expect(typeof referencePath).toBe('string')\n\n      onTestFinished(async () => {\n        await server.commands.removeFile(referencePath)\n      })\n\n      expect(errorMessage).toMatchInlineSnapshot(`\n        expect(element).toMatchScreenshot()\n\n        No existing reference screenshot found${\n          server.config.snapshotOptions.updateSnapshot === 'none'\n            ? '.'\n            : '; a new one was created. Review it before running tests again.'\n        }\n\n        Reference screenshot:\n          ${referencePath}\n      `)\n    },\n  )\n\n  test(\n    'throws when not able to capture a stable screenshot',\n    async ({ onTestFailed }) => {\n      const filename = globalThis.crypto.randomUUID()\n\n      const { queryByTestId } = render(`\n        <div style=\"--size: 20px; --blocks: 10; height: var(--size); width: calc(var(--size) * var(--blocks));\" data-testid=\"${dataTestId}\">\n          <div style=\"height: 100%; aspect-ratio: 1; transform: translateX(calc(var(--size) * (var(--blocks) - 1))); animation: pong 4.5ms linear infinite;\"></div>\n        </div>\n        <style>\n          @keyframes pong {\n            0% {\n              --blocks: 0;\n              background-color: oklch(0% 0 0);\n            }\n            11.11% {\n              --blocks: 1;\n              background-color: oklch(100% 0 0);\n            }\n            22.22% {\n              --blocks: 2;\n              background-color: oklch(0% 0 0);\n            }\n            33.33% {\n              --blocks: 3;\n              background-color: oklch(100% 0 0);\n            }\n            44.44% {\n              --blocks: 4;\n              background-color: oklch(0% 0 0);\n            }\n            55.55% {\n              --blocks: 5;\n              background-color: oklch(100% 0 0);\n            }\n            66.66% {\n              --blocks: 6;\n              background-color: oklch(0% 0 0);\n            }\n            77.77% {\n              --blocks: 7;\n              background-color: oklch(100% 0 0);\n            }\n            88.88% {\n              --blocks: 8;\n              background-color: oklch(0% 0 0);\n            }\n            100% {\n              --blocks: 9;\n              background-color: oklch(100% 0 0);\n            }\n          }\n        </style>\n      `)\n\n      let errorMessage: string\n\n      try {\n        await expect(queryByTestId(dataTestId)).toMatchScreenshot(filename, {\n          screenshotOptions: { animations: 'allow' },\n          timeout: 1,\n        })\n      } catch (error) {\n        errorMessage = error.message\n      }\n\n      onTestFailed(async () => {\n        const [referencePath] = extractToMatchScreenshotPaths(errorMessage, filename)\n\n        if (typeof referencePath === 'string') {\n          await server.commands.removeFile(referencePath)\n        }\n      })\n\n      expect(errorMessage).toMatchInlineSnapshot(`\n        expect(element).toMatchScreenshot()\n\n        Could not capture a stable screenshot within 1ms.\n      `)\n    },\n  )\n\n  test(\n    'creates correct automatic screenshot names',\n    async ({ onTestFinished }) => {\n      const basename = 'toMatchScreenshot-creates-correct-automatic-screenshot-names'\n      const path = join(\n        '__screenshots__',\n        'toMatchScreenshot.test.ts',\n      )\n\n      const firstPath = join(\n        path,\n        `${basename}-1-${server.browser}-${server.platform}.png`\n      )\n      const secondPath = join(\n        path,\n        `${basename}-2-${server.browser}-${server.platform}.png`\n      )\n\n      onTestFinished(async () => {\n        await Promise.all([\n          server.commands.removeFile(firstPath),\n          server.commands.removeFile(secondPath),\n        ])\n      })\n\n      renderTestCase([\n        'oklch(39.6% 0.141 25.723)',\n        'oklch(40.5% 0.101 131.063)',\n        'oklch(37.9% 0.146 265.522)',\n      ])\n\n      const locator = page.getByTestId(dataTestId)\n\n      await locator.screenshot({\n        save: true,\n        path: firstPath,\n      })\n      await locator.screenshot({\n        save: true,\n        path: secondPath,\n      })\n\n      await expect(locator).toMatchScreenshot()\n      await expect(locator).toMatchScreenshot()\n    },\n  )\n\n  // `mask` is a Playwright-only screenshot feature\n  test.runIf(server.provider === 'playwright')(\n    \"works with masks\",\n    async ({ onTestFinished }) => {\n      const filename = globalThis.crypto.randomUUID()\n      const path = join(\n        '__screenshots__',\n        'toMatchScreenshot.test.ts',\n        `${filename}-${server.browser}-${server.platform}.png`,\n      )\n\n      onTestFinished(async () => {\n        await server.commands.removeFile(path)\n      })\n\n      renderTestCase([\n        'oklch(39.6% 0.141 25.723)',\n        'oklch(40.5% 0.101 131.063)',\n        'oklch(37.9% 0.146 265.522)',\n      ])\n\n      const locator = page.getByTestId(dataTestId)\n\n      const maskColor = 'oklch(84.1% 0.238 128.85)'\n      const mask = [page.getByTestId(`${dataTestId}-3`)]\n\n      // Create reference with the third box masked\n      await locator.screenshot({\n        save: true,\n        path,\n        maskColor,\n        mask,\n      })\n\n      // Change the last box's color so we're sure `mask` works\n      // The test would otherwise fail as the screenshots wouldn't match\n      renderTestCase([\n        'oklch(39.6% 0.141 25.723)',\n        'oklch(40.5% 0.101 131.063)',\n        'oklch(39.6% 0.141 25.723)',\n      ])\n\n      await expect(locator).toMatchScreenshot(\n        filename,\n        {\n          screenshotOptions: {\n            maskColor,\n            mask,\n          },\n        },\n      )\n    },\n  )\n\n  test('can use custom comparators', async ({ onTestFinished }) => {\n    const filename = globalThis.crypto.randomUUID()\n    const path = join(\n      '__screenshots__',\n      'toMatchScreenshot.test.ts',\n      `${filename}-${server.browser}-${server.platform}.png`,\n    )\n\n    onTestFinished(async () => {\n      await server.commands.removeFile(path)\n    })\n\n    renderTestCase([\n      'oklch(39.6% 0.141 25.723)',\n      'oklch(40.5% 0.101 131.063)',\n      'oklch(37.9% 0.146 265.522)',\n    ])\n\n    const locator = page.getByTestId(dataTestId)\n\n    // Create a reference screenshot by explicitly saving one\n    await locator.screenshot({\n      save: true,\n      path,\n    })\n\n    // Test that `toMatchScreenshot()` correctly uses a custom comparator; since\n    //  the element hasn't changed, it should match, but this custom comparator\n    //  will always fail\n    await expect(locator).toMatchScreenshot(filename)\n\n    let errorMessage: string\n\n    try {\n      await expect(locator).toMatchScreenshot(filename, {\n        comparatorName: 'failing',\n        timeout: 100,\n      })\n    } catch (error) {\n      errorMessage = error.message\n    }\n\n    expect(errorMessage).matches(/^Could not capture a stable screenshot within 100ms\\.$/m)\n  })\n\n  // Only run this test if snapshots aren't being updated\n  test.runIf(server.config.snapshotOptions.updateSnapshot !== 'all')(\n    'runs only once after resolving the element',\n    async ({ onTestFinished }) => {\n      const filename = `toMatchScreenshot-runs-only-once-after-resolving-the-element-1`\n      const path = join(\n        '__screenshots__',\n        'toMatchScreenshot.test.ts',\n      )\n\n      const screenshotPath = join(\n        path,\n        `${filename}-${server.browser}-${server.platform}.png`\n      )\n\n      // Create baseline screenshot with original colors\n      renderTestCase([\n        'oklch(39.6% 0.141 25.723)',\n        'oklch(40.5% 0.101 131.063)',\n        'oklch(37.9% 0.146 265.522)',\n      ])\n      const locator = page.getByTestId(dataTestId)\n\n      await locator.screenshot({\n        save: true,\n        path: screenshotPath,\n      })\n\n      onTestFinished(async () => {\n        await server.commands.removeFile(screenshotPath)\n      })\n\n      // Remove element, then re-render with inverted colors after a delay\n      document.body.innerHTML = ''\n\n      const renderDelay = 500\n      setTimeout(() => {\n        renderTestCase([\n          'oklch(37.9% 0.146 265.522)',\n          'oklch(40.5% 0.101 131.063)',\n          'oklch(39.6% 0.141 25.723)',\n        ])\n      }, renderDelay)\n\n      const start = performance.now()\n\n      // Expected behavior:\n      // 1. `expect.element()` polls until element exists (~500ms)\n      // 2. `toMatchScreenshot()` runs ONCE and fails (colors don't match baseline)\n      //\n      // If `toMatchScreenshot()` polled internally, it would retry for 30s.\n      // By checking the elapsed time we verify it only ran once.\n\n      let errorMessage: string\n\n      try {\n        await expect.element(locator).toMatchScreenshot()\n      } catch (error) {\n        errorMessage = error.message\n      }\n\n      expect(typeof errorMessage).toBe('string')\n\n      const [referencePath, actualPath, diffPath] = extractToMatchScreenshotPaths(\n        errorMessage,\n        filename,\n      )\n\n      expect(typeof referencePath).toBe('string')\n      expect(typeof actualPath).toBe('string')\n      expect(typeof diffPath).toBe('string')\n\n      expect(referencePath).toMatch(new RegExp(`${screenshotPath}$`))\n\n      onTestFinished(async () => {\n        await Promise.all([\n          server.commands.removeFile(actualPath),\n          server.commands.removeFile(diffPath),\n        ])\n      })\n\n      expect(\n        errorMessage\n          .replace(/(?:\\d+)(.*?)(?:0\\.\\d{2})/, '<pixels>$1<ratio>')\n          .replace(referencePath, '<reference>')\n          .replace(actualPath, '<actual>')\n          .replace(diffPath, '<diff>')\n      ).toMatchInlineSnapshot(`\n        expect(element).toMatchScreenshot()\n\n        Screenshot does not match the stored reference.\n        <pixels> pixels (ratio <ratio>) differ.\n\n        Reference screenshot:\n          <reference>\n\n        Actual screenshot:\n          <actual>\n\n        Diff image:\n          <diff>\n      `)\n\n      const elapsed = performance.now() - start\n\n      // Elapsed time should be lower than the default `poll`/`element` timeout\n      expect(elapsed).toBeLessThan(30_000)\n    },\n  )\n})\n"
  },
  {
    "path": "test/browser/fixtures/expect-dom/utils.ts",
    "content": "function extractToMatchScreenshotPaths (errorMessage: string, filename: string): string[] {\n  // `map` on `Iterator` is only available in Node >= 22\n  return Array.from(\n    errorMessage.matchAll(\n      new RegExp(`^.*?((?:[A-Z]:)?/.*?${filename}-[\\\\w-]+\\\\.png)`, 'gm'),\n    ),\n    ([_, path]) => path,\n  )\n}\n\nfunction render(html: string) {\n  const container = document.createElement('div')\n  container.innerHTML = html\n  const queryByTestId = (testId: string) =>\n    container.querySelector(`[data-testid=\"${testId}\"]`) as HTMLElement | SVGElement | null\n  // asFragment has been stolen from react-testing-library\n  const asFragment = () =>\n    document.createRange().createContextualFragment(container.innerHTML)\n  const getInputByTestId = (testId: string) => queryByTestId(testId) as HTMLInputElement\n\n  // Some tests need to look up global ids with document.getElementById()\n  // so we need to be inside an actual document.\n  document.body.innerHTML = ''\n  document.body.appendChild(container)\n\n  return { container, queryByTestId, asFragment, getInputByTestId }\n}\n\nexport { extractToMatchScreenshotPaths, render }\n"
  },
  {
    "path": "test/browser/fixtures/expect-dom/vitest.config.js",
    "content": "import { defineConfig } from 'vitest/config'\nimport { fileURLToPath } from 'node:url'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      isolate: false,\n      expect: {\n        toMatchScreenshot: {\n          comparators: {\n            failing: () => ({ pass: false, diff: null, message: null }),\n          },\n        },\n      },\n    },\n    setupFiles: './setup.ts',\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/failing/failing.snaphot.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('file snapshot', async () => {\n  await expect('inaccessible snapshot content')\n    .toMatchFileSnapshot('/inaccesible/path')\n})\n"
  },
  {
    "path": "test/browser/fixtures/failing/failing.test.ts",
    "content": "import { page, userEvent } from 'vitest/browser'\nimport { index } from '@vitest/bundled-lib'\nimport { expect, it } from 'vitest'\nimport { throwError } from './src/error'\n\ndocument.body.innerHTML = `\n  <button>Click me!</button>\n`\n\nit('correctly fails and prints a diff', () => {\n  expect(1).toBe(2)\n})\n\nit('correctly print error in another file', () => {\n  throwError()\n})\n\nit('several locator methods are not awaited', () => {\n  page.getByRole('button').dblClick()\n  page.getByRole('button').click()\n  page.getByRole('button').tripleClick()\n  userEvent.type(page.getByRole('textbox'), '123')\n  userEvent.keyboard('123')\n  userEvent.copy()\n  userEvent.cut()\n  userEvent.paste()\n  userEvent.tab()\n  userEvent.dragAndDrop(page.getByRole('button'), page.getByRole('button'))\n  userEvent.fill(page.getByRole('textbox'), '123')\n  userEvent.upload(page.getByRole('textbox'), './file.js')\n  userEvent.unhover(page.getByRole('button'))\n  userEvent.hover(page.getByRole('button'))\n  userEvent.clear(page.getByRole('button'))\n  userEvent.selectOptions(page.getByRole('button'), '123')\n  userEvent.wheel(page.getByRole('button'), { direction: 'down' })\n})\n\nit('correctly prints error from a bundled file', () => {\n  index()\n})\n\nit('not awaited but with then/catch/finally', async () => {\n  await page.getByRole('button').click().then()\n  await page.getByRole('button').click().catch()\n  await page.getByRole('button').click().finally()\n  await userEvent.click(page.getByRole('button')).then()\n  await userEvent.click(page.getByRole('button')).catch()\n  await userEvent.click(page.getByRole('button')).finally()\n  page.getByRole('button').click().then()\n  page.getByRole('button').click().catch()\n  page.getByRole('button').click().finally()\n})\n"
  },
  {
    "path": "test/browser/fixtures/failing/src/error.ts",
    "content": "interface _SomeType {\n  _unused: string\n}\n\n// this should affect the line number\n\nexport function throwError(_opts?: _SomeType) {\n  throw new Error('error')\n}\n"
  },
  {
    "path": "test/browser/fixtures/failing/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport { fileURLToPath } from 'node:url'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      isolate: false,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/insecure-context/src/basic.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"basic\", async () => {\n  expect(window.isSecureContext).toBe(false);\n  expect(1).toBe((await import(\"./dynamic-import\")).default);\n});\n"
  },
  {
    "path": "test/browser/fixtures/insecure-context/src/dynamic-import.ts",
    "content": "export default 1;\n"
  },
  {
    "path": "test/browser/fixtures/insecure-context/vitest.config.ts",
    "content": "import { fileURLToPath } from \"node:url\";\nimport os from \"node:os\";\nimport { defineConfig } from \"vitest/config\";\nimport { instances, provider } from \"../../settings\";\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      headless: true,\n      provider,\n      instances,\n    },\n  },\n  server: {\n    host: os.hostname(), // To force an insecure-context, a host which is not 127.0.0.1 or localhost is needed\n  },\n});\n"
  },
  {
    "path": "test/browser/fixtures/inspect/math.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"sum\", () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/browser/fixtures/inspect/vitest.config.ts",
    "content": "import { provider } from '../../settings'\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  server: { port: 5199 },\n  test: {\n    watch: false,\n    browser: {\n      enabled: true,\n      provider,\n      instances: [\n        { browser: provider.name === 'webdriverio' ? \"chrome\" : \"chromium\" },\n      ],\n      headless: true,\n    },\n  },\n});\n"
  },
  {
    "path": "test/browser/fixtures/inspect/vitest.config.with-workspace.ts",
    "content": "import { defineConfig } from \"vitest/config\";\nimport { provider } from '../../settings'\n\nexport default defineConfig({\n  server: { port: 5199 },\n  test: {\n    watch: false,\n\n    projects: [\n      {\n        test: {\n          name: \"Browser in workspace\",\n          browser: {\n            provider,\n            enabled: true,\n            headless: true,\n            instances: [\n              { browser: provider.name === 'webdriverio' ? \"chrome\" : \"chromium\" },\n            ],\n          },\n        },\n      },\n    ],\n  },\n});\n"
  },
  {
    "path": "test/browser/fixtures/isolate-and-setup-file/a.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { counter } from './counter'\n\ntest('increment counter', () => {\n  counter.increment()\n  expect(counter.get()).toBe(1)\n});\n"
  },
  {
    "path": "test/browser/fixtures/isolate-and-setup-file/b.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { counter } from './counter'\n\ntest('make sure the counter is reset by the setup file beforeEach hook', () => {\n  counter.increment()\n  expect(counter.get()).toBe(1)\n});\n"
  },
  {
    "path": "test/browser/fixtures/isolate-and-setup-file/browser-setup.ts",
    "content": "import { beforeEach } from 'vitest'\nimport { counter } from './counter'\n\nbeforeEach(() => counter.reset())\n"
  },
  {
    "path": "test/browser/fixtures/isolate-and-setup-file/counter.ts",
    "content": "const g = globalThis as unknown as { counter: number };\nexport const counter = {\n  get: () => g.counter,\n  increment: () => g.counter++,\n  reset: () => (g.counter = 0),\n};\n"
  },
  {
    "path": "test/browser/fixtures/isolate-and-setup-file/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    setupFiles: ['./browser-setup.ts'],\n    browser: {\n      enabled: true,\n      isolate: false,\n      provider,\n      instances,\n      headless: false,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/locators/blog.test.tsx",
    "content": "import { expect, test } from 'vitest'\nimport { page, userEvent } from 'vitest/browser'\nimport Blog from '../../src/blog-app/blog'\n\ntest('renders blog posts', async () => {\n  const screen = await page.render(<Blog />)\n\n  await expect.element(screen.getByRole('heading', { name: 'Blog' })).toBeInTheDocument()\n\n  const posts = screen.getByRole('listitem').all()\n\n  expect(posts).toHaveLength(4)\n\n  const [firstPost, secondPost] = posts\n\n  expect(firstPost.element()).toHaveTextContent(/molestiae ut ut quas/)\n  expect(firstPost.getByRole('heading').element()).toHaveTextContent(/occaecati excepturi/)\n\n  await expect.element(secondPost.getByRole('heading')).toHaveTextContent('qui est esse')\n\n  await userEvent.click(secondPost.getByRole('button', { name: 'Delete' }))\n\n  expect(screen.getByRole('listitem').all()).toHaveLength(3)\n\n  expect(screen.getByRole('listitem').nth(0).element()).toHaveTextContent(/molestiae ut ut quas/)\n  await expect.element(screen.getByRole('listitem').nth(666)).not.toBeInTheDocument()\n  expect(screen.getByRole('listitem').first().element()).toHaveTextContent(/molestiae ut ut quas/)\n  expect(screen.getByRole('listitem').last().element()).toHaveTextContent(/eum et est/)\n\n  expect(screen.getByPlaceholder('non-existing').query()).not.toBeInTheDocument()\n})\n"
  },
  {
    "path": "test/browser/fixtures/locators/query.test.ts",
    "content": "import { page } from 'vitest/browser';\nimport { afterEach, describe, expect, test } from 'vitest';\n\nafterEach(() => {\n  document.body.innerHTML = ''\n})\n\ntest('can find a body element', () => {\n  expect(page.elementLocator(document.body).element()).toBe(document.body);\n})\n\ntest('can find elements inside the body', () => {\n  document.body.innerHTML = '<div><span>hello</span></div>'\n  const screen = page.elementLocator(document.body)\n  expect(screen.getByText('hello').element()).toBe(document.querySelector('span'));\n})\n\ndescribe('locator.and', () => {\n  test('can find a button matching multiple criteria', () => {\n    document.body.innerHTML = `\n    <button title=\"Testing framework\">Vitest</button>\n    `\n    const locator = page.getByRole('button').and(page.getByTitle('Testing framework'))\n    expect(locator.element()).toBe(document.querySelector('button'))\n  })\n\n  test('throws an error if matches multiple elements', () => {\n    document.body.innerHTML = `\n    <button title=\"Testing framework\">Vitest</button>\n    <button title=\"Testing framework\">Vitest</button>\n    `\n    const locator = page.getByRole('button').and(page.getByTitle('Testing framework'))\n    expect(() => locator.element()).toThrow(\n      `strict mode violation: getByRole('button').and(getByTitle('Testing framework')) resolved to 2 elements`\n    )\n  })\n})\n\ndescribe('locator.or', () => {\n  test('can find a button matching one of the criteria', () => {\n    document.body.innerHTML = `\n    <button title=\"Testing framework\">Vitest</button>\n    `\n    const locator1 = page.getByRole('button').or(page.getByTitle('Non-existing title'))\n    expect(locator1.element()).toBe(document.querySelector('button'))\n\n    const locator2 = page.getByTitle('Testing framework').or(page.getByRole('alertdialog'))\n    expect(locator2.element()).toBe(document.querySelector('button'))\n  })\n\n  test('can find a button matching both criteria', () => {\n    document.body.innerHTML = `\n    <button title=\"Testing framework\">Vitest</button>\n    `\n    const locator = page.getByRole('button').or(page.getByTitle('Testing framework'))\n    expect(locator.element()).toBe(document.querySelector('button'))\n  })\n\n  test('throws an error if matches multiple elements', () => {\n    document.body.innerHTML = `\n    <button title=\"Testing framework\">Vitest</button>\n    <a href=\"https://vitest.dev\" title=\"Testing framework\">Vitest</a>\n    `\n    const locator = page.getByRole('button').or(page.getByTitle('Testing framework'))\n    expect(() => locator.element()).toThrow(\n      `strict mode violation: getByRole('button').or(getByTitle('Testing framework')) resolved to 2 elements`\n    )\n  })\n})\n\ndescribe('locator.filter', () => {\n  test('can find element with a text inside', () => {\n    document.body.innerHTML = `\n    <button>Vitest</button>\n    `\n    const locator = page.getByRole('button').filter({ hasText: 'Vitest' })\n    expect(locator.element()).toBe(document.querySelector('button'))\n  })\n\n  test('can find element with a text deep inside', () => {\n    document.body.innerHTML = `\n    <article><div><span>Vitest</span></div></article>\n    `\n    const locator = page.getByRole('article').filter({ hasText: 'Vitest' })\n    expect(locator.element()).toBe(document.querySelector('article'))\n  })\n\n  test('can find element with non matching text', () => {\n    document.body.innerHTML = `\n    <button>Vitest</button>\n    `\n    const locator1 = page.getByRole('button').filter({ hasNotText: 'Non-existing text' })\n    expect(locator1.element()).toBe(document.querySelector('button'))\n\n    const locator2 = page.getByRole('button').filter({ hasNotText: 'Vitest' })\n    expect(() => locator2.element()).toThrow(\n      `Cannot find element with locator: getByRole('button').filter({ hasNotText: 'Vitest' })`\n    )\n  })\n\n  test('can find element with non matching text deep inside', () => {\n    document.body.innerHTML = `\n    <article><div><span>Vitest</span></div></article>\n    `\n    const locator1 = page.getByRole('article').filter({ hasNotText: 'Non-existing text' })\n    expect(locator1.element()).toBe(document.querySelector('article'))\n\n    const locator2 = page.getByRole('article').filter({ hasNotText: 'Vitest' })\n    expect(() => locator2.element()).toThrow(\n      `Cannot find element with locator: getByRole('article').filter({ hasNotText: 'Vitest' })`\n    )\n  })\n\n  test('can find element with a locator inside', () => {\n    document.body.innerHTML = `\n    <article><div><button>Vitest</button></div></article>\n    `\n\n    const locator1 = page.getByRole('article').filter({ has: page.getByRole('button') })\n    expect(locator1.element()).toBe(document.querySelector('article'))\n\n    const locator2 = page.getByRole('article').filter({ has: page.getByRole('button').filter({ hasText: 'Vitest' }) })\n    expect(locator2.element()).toBe(document.querySelector('article'))\n\n    const locator3 = page.getByRole('article').filter({ has: page.getByRole('alert') })\n    expect(() => locator3.element()).toThrow(\n      `Cannot find element with locator: getByRole('article').filter({ has: getByRole('alert') })`\n    )\n\n    // locators reversed\n    const locator4 = page.getByRole('button').filter({ has: page.getByRole('article') })\n    expect(() => locator4.element()).toThrow(\n      `Cannot find element with locator: getByRole('button').filter({ has: getByRole('article') })`\n    )\n\n    document.body.innerHTML = `\n    <article><div><button>Vitest</button></div></article>\n    <article><div><button>Vitest</button></div></article>\n    `\n\n    expect(() => locator1.element()).toThrow(\n      `strict mode violation: getByRole('article').filter({ has: getByRole('button') }) resolved to 2 elements`\n    )\n  })\n\n  test('can find element with hasNot', () => {\n    document.body.innerHTML = `\n    <article><div><button>Vitest</button></div></article>\n    `\n\n    const locator1 = page.getByRole('article').filter({ hasNot: page.getByRole('alert') })\n    expect(locator1.element()).toBe(document.querySelector('article'))\n\n    const locator2 = page.getByRole('article').filter({ hasNot: page.getByRole('button') })\n    expect(() => locator2.element()).toThrow(\n      `Cannot find element with locator: getByRole('article').filter({ hasNot: getByRole('button') })`\n    )\n  })\n})\n"
  },
  {
    "path": "test/browser/fixtures/locators/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  optimizeDeps: {\n    include: ['react/jsx-dev-runtime'],\n  },\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    setupFiles: ['vitest-browser-react'],\n    browser: {\n      enabled: true,\n      provider,\n      headless: true,\n      instances,\n    },\n    onConsoleLog(log) {\n      if (log.includes('ReactDOMTestUtils.act')) {\n        return false\n      }\n    }\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/locators-custom/basic.test.tsx",
    "content": "import type { BrowserPage, Locator } from 'vitest/browser';\nimport { locators, page, utils } from 'vitest/browser';\nimport { beforeEach, expect, test } from 'vitest';\n\ndeclare module 'vitest/browser' {\n  interface LocatorSelectors {\n    getByCustomTitle: (title: string) => Locator\n    getByNestedTitle: (title: string) => Locator\n    updateHtml(this: Locator, html: string): Promise<void>\n    updateDocumentHtml(this: BrowserPage, html: string): Promise<void>\n  }\n}\n\nlocators.extend({\n  getByCustomTitle(title) {\n    return `[data-title=\"${title}\"]`\n  },\n  getByNestedTitle(title) {\n    return `[data-parent] >> [data-title=\"${title}\"]`\n  },\n  async updateHtml(this: Locator, html) {\n    this.element().innerHTML = html\n  },\n  async updateDocumentHtml(html) {\n    document.body.innerHTML = html\n  },\n})\n\nbeforeEach(() => {\n  document.body.innerHTML = ''\n})\n\ntest('new selector works on both page and locator', async () => {\n  document.body.innerHTML = `\n  <article>\n    <h1>Hello World</h1>\n    <div data-title=\"Hello World\">Text Content</div>\n  </article>\n  `\n\n  await expect.element(page.getByCustomTitle('Hello World')).toBeVisible()\n  await expect.element(page.getByRole('article').getByCustomTitle('Hello World')).toBeVisible()\n\n  await expect.element(page.getByCustomTitle('NonExisting Title')).not.toBeInTheDocument()\n})\n\ntest('new nested selector works on both page and locator', async () => {\n  document.body.innerHTML = `\n  <article>\n    <h1>Hello World</h1>\n    <div data-parent>\n      <div data-title=\"Hello World\">Text Content</div>\n    </div>\n  </article>\n  `\n\n  await expect.element(page.getByNestedTitle('Hello World')).toBeVisible()\n  await expect.element(page.getByRole('article').getByNestedTitle('Hello World')).toBeVisible()\n\n  await expect.element(page.getByNestedTitle('NonExisting Title')).not.toBeInTheDocument()\n})\n\ntest('new added method works on the locator', async () => {\n  document.body.innerHTML = `\n    <div data-title=\"Hello World\">Text Content</div>\n  `\n\n  const title = page.getByCustomTitle('Hello World')\n\n  await expect.element(title).toHaveTextContent('Text Content')\n\n  await title.updateHtml('New Content')\n\n  await expect.element(title).toHaveTextContent('New Content')\n})\n\ntest('new added method works on the page', async () => {\n  document.body.innerHTML = `\n    Hello World\n  `\n\n  expect(document.body).toHaveTextContent('Hello World')\n\n  await page.updateDocumentHtml('New Content')\n\n  expect(document.body).toHaveTextContent('New Content')\n})\n\ntest('locators are available from getElementLocatorSelectors', () => {\n  const locators = utils.getElementLocatorSelectors(document.body)\n\n  expect(locators.updateHtml).toBeTypeOf('function')\n  expect(locators.getByCustomTitle).toBeTypeOf('function')\n  expect(locators.updateDocumentHtml).toBeTypeOf('function')\n  expect(locators.getByNestedTitle).toBeTypeOf('function')\n})\n"
  },
  {
    "path": "test/browser/fixtures/locators-custom/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      headless: true,\n      instances,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/automocked.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { calculator } from './src/calculator'\n\nvi.mock('./src/calculator')\n\ntest('adds', () => {\n  vi.mocked(calculator).mockReturnValue(4)\n  expect(calculator('plus', 1, 2)).toBe(4)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/autospying.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { calculator } from './src/calculator'\nimport * as mocks_calculator from './src/mocks_calculator'\n\nvi.mock('./src/calculator', { spy: true })\nvi.mock('./src/mocks_calculator', { spy: true })\n\ntest('correctly spies on a regular module', () => {\n  expect(calculator('plus', 1, 2)).toBe(3)\n  expect(calculator).toHaveBeenCalled()\n})\n\ntest('spy options overrides __mocks__ folder', () => {\n  expect(mocks_calculator.calculator('plus', 1, 2)).toBe(3)\n  expect(mocks_calculator.calculator).toHaveBeenCalled()\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/import-actual-dep.test.ts",
    "content": "import { a, b } from '@vitest/cjs-lib'\nimport { expect, test, vi } from 'vitest'\n\nvi.mock(import('@vitest/cjs-lib'), async (importOriginal) => {\n  return {\n    ...await importOriginal(),\n  }\n})\n\ntest('mocking works correctly', () => {\n  expect(a).toBe('a')\n  expect(b).toBe('b')\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/import-actual-in-mock.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { calculator, mocked } from './src/mocks_factory'\n\nvi.mock(import('./src/mocks_factory'), async (importOriginal) => {\n  const original = await importOriginal()\n  return {\n    ...original,\n    mocked: true,\n  }\n})\n\ntest('actual is overriding import', () => {\n  expect(mocked).toBe(true)\n  expect(calculator('plus', 1, 2)).toBe(3)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/import-actual-query.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport rawFactory from './src/mocks_factory?raw'\n\nvi.mock(import('./src/mocks_factory?raw'), async (importOriginal) => {\n  const original = await importOriginal()\n  return {\n    default: original.default.replace('mocked: boolean = false', 'mocked: boolean = \"mocked!\"'),\n  }\n})\n\ntest('factory with a query', () => {\n  expect(rawFactory).toBe(`\nexport function calculator(_action: string, _a: number, _b: number) {\n  return _a + _b\n}\n\nexport const mocked: boolean = \"mocked!\"\n`.trimStart())\n})"
  },
  {
    "path": "test/browser/fixtures/mocking/import-mock.test.ts",
    "content": "import { test, vi, expect } from 'vitest'\n\nvi.mock(import('./src/mocks_factory'), () => {\n  return {\n    calculator: () => 55,\n    mocked: true,\n  }\n})\n\ntest('all mocked are valid', async () => {\n  const example = await vi.importMock<typeof import('./src/example')>('./src/example')\n\n  // creates a new mocked function with no formal arguments.\n  expect(example.square.name).toEqual('square')\n  expect(example.square.length).toEqual(2)\n\n  // async functions get the same treatment as standard synchronous functions.\n  expect(example.asyncSquare.name).toEqual('asyncSquare')\n  expect(example.asyncSquare.length).toEqual(2)\n\n  // creates a new class with the same interface, member functions and properties are mocked.\n  expect(example.someClasses.constructor.name).toEqual('Bar')\n  expect(example.someClasses.foo.name).toEqual('foo')\n  expect(vi.isMockFunction(example.someClasses.foo)).toBe(true)\n  expect(example.someClasses.array.length).toEqual(0)\n\n  // creates a deeply cloned version of the original object.\n  expect(example.object).toEqual({\n    baz: 'foo',\n    bar: {\n      fiz: 1,\n      buzz: [],\n    },\n  })\n\n  // creates a new empty array, ignoring the original array.\n  expect(example.array.length).toEqual(0)\n\n  // creates a new property with the same primitive value as the original property.\n  expect(example.number).toEqual(123)\n  expect(example.string).toEqual('baz')\n  expect(example.boolean).toEqual(true)\n  expect(example.symbol).toEqual(Symbol.for('a.b.c'))\n})\n\ntest('import from a factory if defined', async () => {\n  const { calculator, mocked } = await vi.importMock<typeof import('./src/mocks_factory')>(\n    './src/mocks_factory'\n  )\n  expect(calculator('add', 1, 2)).toBe(55)\n  expect(mocked).toBe(true)\n})\n\ntest('imports from __mocks__', async () => {\n  const { calculator } = await vi.importMock<typeof import('./src/mocks_calculator')>(\n    './src/mocks_calculator'\n  )\n  expect(calculator('plus', 1, 2)).toBe(42)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/mocked-__mocks__.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { calculator } from './src/mocks_calculator'\n\nvi.mock(import('./src/mocks_calculator'))\n\ntest('adds', () => {\n  expect(calculator('plus', 1, 2)).toBe(42)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/mocked-do-mock-factory.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\ntest('adds', async () => {\n  vi.doMock(import('./src/mocks_factory'), () => {\n    return {\n      calculator: () => 1166,\n      mocked: true,\n    }\n  })\n\n  const { mocked, calculator } = await import('./src/mocks_factory')\n  expect(mocked).toBe(true)\n  expect(calculator('plus', 1, 2)).toBe(1166)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/mocked-factory-hoisted.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { calculator } from './src/mocks_factory'\n\nconst fn = vi.hoisted(() => vi.fn())\n\nvi.mock(import('./src/mocks_factory'), () => {\n  return {\n    calculator: fn,\n  }\n})\n\ntest('adds', () => {\n  fn.mockReturnValue(448)\n  expect(calculator('plus', 1, 2)).toBe(448)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/mocked-factory.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { calculator, mocked } from './src/mocks_factory'\nimport factoryMany from './src/mocks_factory_many'\n\nvi.mock(import('./src/mocks_factory'), () => {\n  return {\n    calculator: () => 1166,\n    mocked: true,\n  }\n})\n\nvi.mock(import('./src/mocks_factory_many_dep1'), () => ({\n  dep1: \"dep1-mocked\"\n}))\nvi.mock(import('./src/mocks_factory_many_dep2'), () => ({\n  dep2: \"dep2-mocked\"\n}))\n\ntest('adds', () => {\n  expect(mocked).toBe(true)\n  expect(calculator('plus', 1, 2)).toBe(1166)\n\n  expect(factoryMany).toEqual({\n    \"dep1\": \"dep1-mocked\",\n    \"dep2\": \"dep2-mocked\",\n  })\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/mocked-nested.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { parent } from './src/nested_parent'\n\nconst child = vi.hoisted(() => vi.fn())\n\nvi.mock(import('./src/nested_child'), () => {\n  return {\n    child,\n  }\n})\n\ntest('adds', () => {\n  child.mockReturnValue(42)\n  expect(parent()).toBe(42)\n})\n\ntest('actual', async () => {\n  const { child } = await vi.importActual<\n    typeof import('./src/nested_child')\n  >('./src/nested_child')\n\n  expect(child()).toBe(true)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/mocking-dep.test.ts",
    "content": "import { a } from '@vitest/cjs-lib'\nimport { expect, test, vi } from 'vitest'\n\nvi.mock(import('@vitest/cjs-lib'), () => {\n  return {\n    a: 'mocked',\n  }\n})\n\ntest('mocking works correctly', () => {\n  expect(a).toBe('mocked')\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/not-mocked-nested.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { parent } from './src/nested_parent'\n\ntest('adds', () => {\n  expect(parent()).toBe(true)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/not-mocked.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { calculator } from './src/calculator'\n\ntest('adds', () => {\n  expect(calculator('plus', 1, 2)).toBe(3)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking/service-worker.js",
    "content": "self.addEventListener(\"install\", (event) => {\n  event.waitUntil(self.skipWaiting());\n});\n\nself.addEventListener(\"activate\", (event) => {\n  event.waitUntil(self.clients.claim());\n});\n\nself.addEventListener(\"fetch\", (event) => {\n  if (event.request.url.includes(\"/hello\")) {\n    event.respondWith(\n      new Response(\"Hello from Service Worker!\", {\n        status: 200,\n        headers: { \"Content-Type\": \"text/plain\" },\n      })\n    );\n  } else {\n    // Pass through other requests\n    event.respondWith(fetch(event.request));\n  }\n});\n\n// Handle messages from the test\nself.addEventListener(\"message\", (event) => {\n  if (event.data.type === \"PING\") {\n    event.ports[0].postMessage({ type: \"PONG\" });\n  }\n});\n"
  },
  {
    "path": "test/browser/fixtures/mocking/service-worker.test.ts",
    "content": "import { expect, test, vi } from \"vitest\";\nimport { server } from 'vitest/browser'\n\nvi.mock(\"./src/actions\", () => ({\n  plus: vi.fn().mockReturnValue(12345),\n}));\n\n\ntest.runIf(server.config.name === 'chromium')(\"Service worker does not break vi.mock\", async (t) => {\n  const registration = await navigator.serviceWorker.register(\n    new URL(\"./service-worker.js\", import.meta.url)\n  );\n  t.onTestFinished(async () => {\n    await registration.unregister()\n  })\n\n  await vi.waitFor(() => expect(registration.active?.state).toBe(\"activated\"));\n  await navigator.serviceWorker.ready;\n  let swResponseMessage = null;\n  const messageChannel = new MessageChannel();\n  messageChannel.port1.onmessage = (event) => {\n    swResponseMessage = event.data;\n  };\n  registration.active.postMessage({ type: \"PING\" }, [messageChannel.port2]);\n  await vi.waitFor(() => expect(swResponseMessage.type).toBe(\"PONG\"));\n\n  // Send a mocked API request to the service worker\n  const response = await fetch(\"/hello\");\n  // Assert the service worker intercepted the request\n  const responseText = await response.text();\n  expect(response.status).toBe(200);\n  expect(responseText).toBe(\"Hello from Service Worker!\");\n\n  // Send an import, which will be intercepted by the service worker\n  // Verify vi.mock is still functional after mocking the network with a service worker\n  const { plus } = await import(\"./src/actions\");\n  const result = plus(1, 2);\n  expect(plus).toHaveBeenCalled();\n  expect(result).toBe(12345);\n});\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/__mocks__/mocks_calculator.ts",
    "content": "export function calculator() {\n  return 42\n}\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/actions.ts",
    "content": "export function plus(a: number, b: number) {\n  return a + b\n}\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/calculator.ts",
    "content": "import { plus } from './actions'\n\nexport function calculator(operation: 'plus', a: number, b: number) {\n  if (operation === 'plus')\n    return plus(a, b)\n\n  throw new Error('unknown operation')\n}\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/example.ts",
    "content": "export function square(a: number, b: number) {\n  return a * b\n}\nexport async function asyncSquare(a: number, b: number) {\n  const result = (await a) * b\n  return result\n}\nexport const someClasses = new (class Bar {\n  public array: number[]\n  constructor() {\n    this.array = [1, 2, 3]\n  }\n\n  foo() {}\n})()\nexport const object = {\n  baz: 'foo',\n  bar: {\n    fiz: 1,\n    buzz: [1, 2, 3],\n  },\n}\nexport const array = [1, 2, 3]\nexport const number = 123\nexport const string = 'baz'\nexport const boolean = true\nexport const symbol = Symbol.for('a.b.c')\nexport default 'a default'\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/mocks_calculator.ts",
    "content": "import { plus } from './actions'\n\nexport function calculator(operation: 'plus', a: number, b: number) {\n  if (operation === 'plus')\n    return plus(a, b)\n\n  throw new Error('unknown operation')\n}\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/mocks_factory.ts",
    "content": "export function calculator(_action: string, _a: number, _b: number) {\n  return _a + _b\n}\n\nexport const mocked: boolean = false\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/mocks_factory_many.ts",
    "content": "import { dep1 } from \"./mocks_factory_many_dep1\";\nimport { dep2 } from \"./mocks_factory_many_dep2\";\n\nexport default { dep1, dep2 }\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/mocks_factory_many_dep1.ts",
    "content": "export const dep1: string = \"dep1\"\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/mocks_factory_many_dep2.ts",
    "content": "export const dep2: string = \"dep2\"\n"
  },
  {
    "path": "test/browser/fixtures/mocking/src/nested_child.ts",
    "content": "export function child() {\n  return true\n}"
  },
  {
    "path": "test/browser/fixtures/mocking/src/nested_parent.ts",
    "content": "import { child } from './nested_child'\n\nexport function parent() {\n  return child()\n}\n"
  },
  {
    "path": "test/browser/fixtures/mocking/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  optimizeDeps: {\n    include: ['@vitest/cjs-lib'],\n    needsInterop: ['@vitest/cjs-lib'],\n  },\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      headless: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking-out-of-root/project1/basic.test.js",
    "content": "import { test, expect, vi } from 'vitest';\nimport project2 from \"../project2/index.js\"\nimport \"./imported-test.js\"\nimport \"../project3/imported-test.js\"\n\nvi.mock(\"../project2/index.js\", () => ({\n  default: 'project2-mocked'\n}))\n\ntest(\"basic\", () => {\n  expect(project2).toMatchInlineSnapshot(`\"project2-mocked\"`)\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking-out-of-root/project1/imported-test.js",
    "content": "import { vi, test, expect } from \"vitest\"\nimport lib from \"./lib.js\";\n\nvi.mock(\"./lib.js\", () => ({ default: \"mocked\" }))\n\ntest(\"project1 imported\", () => {\n  expect(lib).toBe(\"mocked\");\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking-out-of-root/project1/lib.js",
    "content": "export default \"lib\"\n"
  },
  {
    "path": "test/browser/fixtures/mocking-out-of-root/project1/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\nimport { fileURLToPath } from 'node:url'\nimport { instances, provider } from '../../../settings'\n\n// BROWSER=chromium pnpm -C test/browser test-fixtures --root fixtures/mocking-out-of-root/project1\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  root: import.meta.dirname,\n  test: {\n    browser: {\n      enabled: true,\n      provider: provider,\n      screenshotFailures: false,\n      headless: true,\n      instances,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking-out-of-root/project2/index.js",
    "content": "export default \"project2\"\n"
  },
  {
    "path": "test/browser/fixtures/mocking-out-of-root/project3/imported-test.js",
    "content": "import { vi, test, expect } from \"vitest\"\nimport lib from \"./lib.js\";\n\nvi.mock(\"./lib.js\", () => ({ default: \"mocked\" }))\n\ntest(\"project3 imported\", () => {\n  expect(lib).toBe(\"mocked\");\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking-out-of-root/project3/lib.js",
    "content": "export default \"lib\"\n"
  },
  {
    "path": "test/browser/fixtures/mocking-watch/1_mocked-on-watch-change.test.ts",
    "content": "import { lib } from '@vitest/cjs-lib/lib'\nimport { vi, test, expect } from 'vitest'\n\nvi.mock(import('@vitest/cjs-lib/lib'), () => {\n  return {\n    lib: vi.fn(() => 'mocked')\n  }\n})\n\ntest('mocks correctly', () => {\n  expect(lib()).toBe('mocked')\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking-watch/2_not-mocked-import.test.ts",
    "content": "import { lib } from '@vitest/cjs-lib/lib'\nimport { test, expect } from 'vitest'\n\ntest('not mocked', () => {\n  expect(lib()).toBe('original')\n})\n"
  },
  {
    "path": "test/browser/fixtures/mocking-watch/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  optimizeDeps: {\n    include: ['@vitest/cjs-lib', '@vitest/cjs-lib/lib'],\n  },\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      fileParallelism: false,\n      enabled: true,\n      provider,\n      instances,\n      headless: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/multiple-different-configs/basic.test.js",
    "content": "import { test as baseTest, expect, inject } from 'vitest';\nimport { server } from 'vitest/browser'\n\nconst test = baseTest.extend({\n  // chromium should inject the value as \"true\"\n  // firefox doesn't provide this value in the config, it will stay undefined\n  providedVar: [undefined, { injected: true }]\n})\n\ntest('html injected', ({ providedVar }) => {\n  // window.HTML_INJECTED_VAR is injected only for chromium via a script in customTester.html\n  console.log(`[${server.config.name}] HTML_INJECTED_VAR is ${window.HTML_INJECTED_VAR}`)\n  expect(providedVar).toBe(window.HTML_INJECTED_VAR)\n})\n\ntest.runIf(server.config.name === 'firefox')('[firefox] firefoxValue injected', ({ providedVar }) => {\n  expect(providedVar).toBeUndefined()\n  expect(inject('firefoxValue')).toBe(true)\n})\n\ntest.runIf(server.config.name === 'chromium')('[chromium] firefoxValue is not injected', () => {\n  expect(inject('firefoxValue')).toBeUndefined()\n})"
  },
  {
    "path": "test/browser/fixtures/multiple-different-configs/customTester.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Document</title>\n</head>\n<body>\n  <script>\n  var HTML_INJECTED_VAR = true\n  </script>\n</body>\n</html>"
  },
  {
    "path": "test/browser/fixtures/multiple-different-configs/vitest.config.js",
    "content": "import { defineConfig } from 'vitest/config';\nimport { fileURLToPath } from 'node:url'\nimport { provider } from '../../settings'\n\nexport default defineConfig({\n  clearScreen: false,\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      provider,\n      enabled: true,\n      headless: true,\n      screenshotFailures: false,\n      instances: [\n        {\n          browser: provider.name === 'playwright' ? 'chromium' : 'chrome',\n          testerHtmlPath: './customTester.html',\n          provide: {\n            providedVar: true,\n          },\n          name: 'chromium',\n        },\n        {\n          browser: 'firefox',\n          provide: {\n            firefoxValue: true,\n          },\n        },\n      ],\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/playwright-connect/basic.test.js",
    "content": "import { test, expect } from 'vitest';\n\ntest('[playwright] Run basic test in browser via connect mode', () => {\n  expect(1).toBe(1)\n})\n\ntest('[playwright] Run browser-only test in browser via connect mode', () => {\n  const element = document.createElement(\"div\")\n  expect(element instanceof HTMLDivElement).toBe(true)\n  expect(element instanceof HTMLElement).toBe(true)\n  expect(element instanceof HTMLInputElement).not.toBe(true)\n})\n\ntest('[playwright] applies launch options from connect header', () => {\n  expect(navigator.userAgent).toContain('VitestLaunchOptionsTester')\n})\n"
  },
  {
    "path": "test/browser/fixtures/playwright-connect/vitest.config.js",
    "content": "import { defineConfig } from 'vitest/config';\nimport { fileURLToPath } from 'node:url'\n\nexport default defineConfig({\n  clearScreen: false,\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      headless: true,\n      screenshotFailures: false,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/print-logs/test/dialog.test.ts",
    "content": "/* eslint-disable no-alert */\n\nimport { expect, it } from 'vitest'\n\nit('alert', async () => {\n  expect(alert('test')).toBeUndefined()\n})\n\nit('prompt', async () => {\n  expect(prompt('test')).toBeNull()\n})\n\nit('confirm', async () => {\n  expect(confirm('test')).toBe(false)\n})\n"
  },
  {
    "path": "test/browser/fixtures/print-logs/test/logs.test.ts",
    "content": "/* eslint-disable no-console */\nimport { test, vi } from 'vitest'\n\ntest('logging to stdout', () => {\n  console.log('hello from console.log')\n  console.info('hello from console.info')\n  console.debug('hello from console.debug')\n  console.dir({ hello: 'from dir' })\n  console.dirxml({ hello: 'from dirxml' })\n  console.trace('hello from console.trace')\n})\n\ntest('logging to stderr', () => {\n  console.error('hello from console.error')\n  console.warn('hello from console.warn')\n})\n\ntest('logging DOM element', () => {\n  const element = document.createElement('div')\n  console.log('dom', element)\n})\n\ntest('logging default counter', () => {\n  console.count()\n  console.count()\n  console.count()\n  console.countReset()\n  console.count()\n})\n\ntest('logging custom counter', () => {\n  console.count('count')\n  console.count('count')\n  console.count('count')\n  console.countReset('count')\n  console.count('count')\n})\n\ntest('logging default time', () => {\n  console.time()\n  console.timeLog()\n  console.timeEnd()\n})\n\ntest('logging custom time', () => {\n  console.time('time')\n  console.timeLog('time')\n  console.timeEnd('time')\n})\n\ntest('logging invalid time', () => {\n  console.timeLog('invalid timeLog')\n  console.timeEnd('invalid timeEnd')\n})\n\ntest('logging the stack', () => {\n  vi.setConfig({ printConsoleTrace: true })\n  console.log('log with a stack')\n  console.error('error with a stack')\n  console.trace('trace with a stack')\n})\n\ntest('console.time', async () => {\n  vi.useFakeTimers({\n    toFake: ['Date', 'performance'],\n  })\n  console.time('[console-time-fake]')\n  await new Promise(r => setTimeout(r, 500))\n  console.timeEnd('[console-time-fake]')\n})\n\ntest('log with placeholders', () => {\n  console.log('hello from %s', \"one\")\n  console.log('hello from %s', \"two\", { hello: 'object' })\n})\n"
  },
  {
    "path": "test/browser/fixtures/print-logs/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport { fileURLToPath } from 'node:url'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      isolate: false,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/project-name-encoding/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('basic test', () => {\n  expect(true).toBe(true)\n})\n"
  },
  {
    "path": "test/browser/fixtures/project-name-encoding/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    name: 'Components & Hooks',\n    browser: {\n      enabled: true,\n      headless: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/server-url/basic.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"basic\", () => {\n  expect(1).toBe(1);\n})\n"
  },
  {
    "path": "test/browser/fixtures/server-url/vitest.config.ts",
    "content": "import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport basicSsl from '@vitejs/plugin-basic-ssl'\nimport { instances, providers, provider } from '../../settings'\n\n// test https by\n//   TEST_HTTPS=1 pnpm test-fixtures --root fixtures/server-url\n\n// ignore https errors due to self-signed certificate from plugin-basic-ssl\n// https://playwright.dev/docs/api/class-browser#browser-new-context-option-ignore-https-errors\n// https://webdriver.io/docs/configuration/#strictssl and acceptInsecureCerts in https://webdriver.io/docs/api/browser/#properties\nconst configuredProvider = (function () {\n  switch (provider.name) {\n    case 'playwright': return providers.playwright()\n    case 'webdriverio': return providers.webdriverio({ strictSSL: false, capabilities: { acceptInsecureCerts: true } })\n    default: {\n      throw new Error(`Invalid provider: ${provider.name}`)\n    }\n  }\n})()\n\nexport default defineConfig({\n  plugins: [\n    !!process.env.TEST_HTTPS && basicSsl(),\n  ],\n  test: {\n    browser: {\n      api: process.env.TEST_HTTPS ? 51122 : 51133,\n      enabled: true,\n      provider: configuredProvider,\n      instances,\n    },\n  },\n  // separate cacheDir from test/browser/vite.config.ts\n  // to prevent pre-bundling related flakiness on Webkit\n  cacheDir: path.join(path.dirname(fileURLToPath(import.meta.url)), \"node_modules/.vite\")\n})\n"
  },
  {
    "path": "test/browser/fixtures/setup-file/browser-setup.ts",
    "content": "import { beforeEach } from 'vitest';\nimport * as source from './source';\n\nbeforeEach<{ source: any }>((t) => {\n  t.source = source\n})\n"
  },
  {
    "path": "test/browser/fixtures/setup-file/module-equality.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport * as source from './source'\n\ntest<{ source: any }>('modules are the same', (t) => {\n  expect(source).toBe(t.source)\n})\n"
  },
  {
    "path": "test/browser/fixtures/setup-file/source.ts",
    "content": "export function answer() {\n  return 42\n}\n"
  },
  {
    "path": "test/browser/fixtures/setup-file/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    setupFiles: ['./browser-setup.ts'],\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      headless: false,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/timeout/timeout.test.ts",
    "content": "import { page } from 'vitest/browser';\nimport { afterEach, expect, test } from 'vitest';\n\nafterEach(() => {\n  document.body.innerHTML = ''\n})\n\ntest('click default', async () => {\n  document.body.innerHTML = '<div><span>hello</span></div>'\n  await page.getByText('world').click()\n})\n\ntest('click override', async () => {\n  document.body.innerHTML = '<div><span>hello</span></div>'\n  await page.getByText('world').click({ timeout: 345 })\n})\n\ntest('element', async () => {\n  document.body.innerHTML = '<div><span>hello</span></div>'\n  await expect.element(page.getByText('world')).toBeVisible()\n})\n"
  },
  {
    "path": "test/browser/fixtures/timeout/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider, providers } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider: provider.name === 'playwright'\n        ? providers.playwright({ actionTimeout: 500 })\n        : provider,\n      instances,\n    },\n    expect: {\n      poll: {\n        timeout: 500,\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/timeout-hooks/hooks-timeout.test.ts",
    "content": "import { page, server } from 'vitest/browser';\nimport { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, onTestFailed, onTestFinished } from 'vitest';\n\ndescribe.runIf(server.provider === 'playwright')('timeouts are failing correctly', () => {\n  it('click on non-existing element fails', async () => {\n    await page.getByRole('code').click()\n  }, 150)\n\n  it('expect.element on non-existing element fails', async () => {\n    await expect.element(page.getByRole('code')).toBeVisible()\n  }, 150)\n\n  describe('beforeEach', () => {\n    beforeEach(async () => {\n      await page.getByTestId('non-existing').click()\n    }, 150)\n\n    it('skipped', () => {})\n  })\n\n  describe('afterEach', () => {\n    afterEach(async () => {\n      await page.getByTestId('non-existing').click()\n    }, 150)\n\n    it('skipped', () => {})\n  })\n\n  describe('beforeAll', () => {\n    beforeAll(async () => {\n      await page.getByTestId('non-existing').click()\n    }, 150)\n\n    it('skipped', () => {})\n  })\n\n  describe('afterAll', () => {\n    afterAll(async () => {\n      await page.getByTestId('non-existing').click()\n    }, 150)\n\n    it('skipped', () => {})\n  })\n\n  describe('onTestFinished', () => {\n    it('fails', ({ onTestFinished }) => {\n      onTestFinished(async () => {\n        await page.getByTestId('non-existing').click()\n      }, 150)\n    })\n\n    it('fails global', () => {\n      onTestFinished(async () => {\n        await page.getByTestId('non-existing').click()\n      }, 150)\n    })\n  })\n\n  describe('onTestFailed', () => {\n    it('fails', ({ onTestFailed }) => {\n      onTestFailed(async () => {\n        await page.getByTestId('non-existing').click()\n      }, 150)\n\n      expect.unreachable()\n    })\n\n    it('fails global', () => {\n      onTestFailed(async () => {\n        await page.getByTestId('non-existing').click()\n      }, 150)\n\n      expect.unreachable()\n    })\n  })\n})\n"
  },
  {
    "path": "test/browser/fixtures/timeout-hooks/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      screenshotFailures: false,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/trace-mark/basic.test.ts",
    "content": "import { beforeEach, expect, test, vi } from \"vitest\";\nimport { page } from \"vitest/browser\";\n\nbeforeEach(() => {\n  document.body.innerHTML = \"\";\n});\n\ntest(\"locator.mark\", async () => {\n  document.body.innerHTML = \"<button>Hello</button>\";\n  await page.getByRole(\"button\").mark(\"button rendered - locator\");\n});\n\ntest(\"page.mark\", async () => {\n  document.body.innerHTML = \"<button>Hello</button>\";\n  await page.mark(\"button rendered - page\");\n});\n\ntest(\"expect.element pass\", async () => {\n  document.body.innerHTML = \"<button>Hello</button>\";\n  await expect.element(page.getByRole(\"button\")).toHaveTextContent(\"Hello\");\n});\n\ntest(\"expect.element fail\", async () => {\n  document.body.innerHTML = \"<button>Hello</button>\";\n  await page.mark(\"button rendered\");\n  await expect.element(page.getByRole(\"button\"), { timeout: 100 }).toHaveTextContent(\"World\");\n});\n\ntest(\"failure\", async () => {\n  document.body.innerHTML = \"<button>Hello</button>\";\n  throw new Error(\"Test failure\");\n});\n\ntest(\"click\", async () => {\n  document.body.innerHTML = \"<button>Hello</button>\";\n  await page.getByRole(\"button\").click();\n});\n\nconst myRender = vi.defineHelper(async (content: string) => {\n  document.body.innerHTML = content;\n  await  page.elementLocator(document.body).mark(\"render helper\");\n});\n\ntest(\"helper\", async () => {\n  await myRender(\"<button>Hello</button>\");\n});\n\ntest(\"stack\", async () => {\n  document.body.innerHTML = \"<button>Hello</button>\";\n  const error = new Error(\"Custom error for stack trace\");\n  await page.getByRole(\"button\").mark(\"button rendered - stack\", { stack: error.stack });\n});\n\ntest(\"mark group\", async () => {\n  await page.mark(\"render group\", async () => {\n    document.body.innerHTML = \"<button>Hello</button>\";\n  })\n});\n"
  },
  {
    "path": "test/browser/fixtures/trace-mark/vitest.config.ts",
    "content": "import { fileURLToPath } from \"node:url\";\nimport { defineConfig } from \"vitest/config\";\nimport { instances, providers } from \"../../settings\";\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider: providers.playwright(),\n      instances,\n    },\n  },\n});\n"
  },
  {
    "path": "test/browser/fixtures/trace-view/basic.test.ts",
    "content": "import { describe, test } from 'vitest';\n\ntest('a single test', () => {\n  // ...\n})\n\ntest('repeated test', { repeats: 2 }, () => {\n  // ...\n})\n\ntest('retried test', { retry: 2 }, ({ task }) => {\n  if (task.result?.retryCount !== 2) {\n    throw new Error('failed test')\n  }\n})\n\ntest('repeated retried tests', { repeats: 2, retry: 2 }, ({ task }) => {\n  if (task.result?.retryCount !== 2) {\n    throw new Error('failed test')\n  }\n})\n\ndescribe('nested suite', () => {\n  test('suite test', () => {\n    // ...\n  })\n\n  test.skip('skipped test', () => {\n    // ...\n  })\n})\n"
  },
  {
    "path": "test/browser/fixtures/trace-view/failing.special.ts",
    "content": "import { test } from 'vitest';\n\ntest('fail', () => {\n  throw new Error('fail')\n})\n\ntest('retried fail', { retry: 2 }, () => {\n  throw new Error('fail')\n})\n\ntest('repeated fail', { repeats: 2 }, () => {\n  throw new Error('fail')\n})\n"
  },
  {
    "path": "test/browser/fixtures/trace-view/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { providers } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider: providers.playwright(),\n      instances: [\n        { browser: 'chromium' },\n        { browser: 'firefox' },\n        { browser: 'webkit' },\n      ],\n      headless: true,\n      trace: 'off',\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/unhandled/throw-unhandled-error.test.ts",
    "content": "import { test } from 'vitest';\n\ninterface _Unused {\n  _fake: never\n}\n\ntest('unhandled exception', async () => {\n  ;(async () => {\n    throw new Error('custom_unhandled_error')\n  })()\n  // trigger the error during the test so the report includes the helpful message\n  // in reality, most tests will have something going on here already\n  await new Promise<void>((resolve) => setTimeout(() => resolve(), 50))\n})\n"
  },
  {
    "path": "test/browser/fixtures/unhandled/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      headless: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/unhandled-non-error/basic.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"ResizeObserver error\", async () => {\n\tconst divElem = document.createElement(\"div\");\n\tdivElem.style.width = \"100px\";\n\tdivElem.style.height = \"100px\";\n\tdocument.body.appendChild(divElem);\n\n\tconst resizeObserver = new ResizeObserver((entries) => {\n\t\tfor (const entry of entries) {\n\t\t\t(entry.target as HTMLElement).style.width =\n\t\t\t\t`${entry.contentBoxSize[0].inlineSize + 10}px`;\n\t\t}\n\t});\n\tconst promise = Promise.withResolvers();\n\twindow.addEventListener(\"error\", (event) => {\n\t\tif (event.message.includes(\"ResizeObserver loop\")) {\n\t\t\tpromise.resolve(null);\n\t\t}\n\t});\n\tresizeObserver.observe(divElem);\n\tawait promise.promise;\n\tresizeObserver.unobserve(divElem);\n});\n"
  },
  {
    "path": "test/browser/fixtures/unhandled-non-error/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n      headless: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/update-snapshot/__snapshots__/basic.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`basic 1`] = `2`;\n"
  },
  {
    "path": "test/browser/fixtures/update-snapshot/__snapshots__/custom/my_snapshot",
    "content": "my snapshot content"
  },
  {
    "path": "test/browser/fixtures/update-snapshot/basic-fixture.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\ninterface _BasicInterface {\n  willBeRemoved: boolean\n  leavingSourceMapIncorrect: boolean\n}\n\ntest('inline snapshot', () => {\n  expect(1).toMatchInlineSnapshot('1')\n})\n\ntest('basic', () => {\n  expect(1).toMatchSnapshot()\n})\n\ntest('renders inline mock snapshot', () => {\n  const fn = vi.fn()\n  expect(fn).toMatchInlineSnapshot()\n  fn('hello', 'world', 2)\n  expect(fn).toMatchInlineSnapshot()\n})\n\ntest('file snapshot', async () => {\n  await expect('my snapshot content')\n    .toMatchFileSnapshot('./__snapshots__/custom/my_snapshot')\n})\n\n"
  },
  {
    "path": "test/browser/fixtures/update-snapshot/vitest.config.ts",
    "content": "import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\n/*\nmanually test snapshot by\n  pnpm -C test/browser test-fixtures --root fixtures/update-snapshot\n*/\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n    },\n  },\n  cacheDir: path.join(\n    path.dirname(fileURLToPath(import.meta.url)),\n    'node_modules/.vite'\n  ),\n})\n"
  },
  {
    "path": "test/browser/fixtures/user-event/cleanup-retry.test.ts",
    "content": "import { expect, onTestFinished, test } from 'vitest'\nimport { userEvent } from 'vitest/browser'\n\ntest('cleanup retry', { retry: 1 }, async (ctx) => {\n  let logs: any[] = [];\n  function handler(e: KeyboardEvent) {\n    logs.push([e.key, e.altKey]);\n  };\n  document.addEventListener('keydown', handler)\n  onTestFinished(() => {\n    document.removeEventListener('keydown', handler);\n  })\n\n  await userEvent.keyboard('{Tab}')\n  await userEvent.keyboard(\"{Alt>}\")\n  if (ctx.task.result.retryCount === 0) {\n    throw new Error(\"test retry\")\n  }\n  expect(logs).toEqual(\n    [\n      [\n        \"Tab\",\n        false,\n      ],\n      [\n        \"Alt\",\n        true,\n      ],\n    ]\n  )\n})\n"
  },
  {
    "path": "test/browser/fixtures/user-event/cleanup1.test.ts",
    "content": "import { expect, onTestFinished, test } from 'vitest'\nimport { userEvent } from 'vitest/browser'\n\ntest('cleanup1', async () => {\n  let logs: any[] = [];\n  function handler(e: KeyboardEvent) {\n    logs.push([e.key, e.altKey]);\n  };\n  document.addEventListener('keydown', handler)\n  onTestFinished(() => {\n    document.removeEventListener('keydown', handler);\n  })\n\n  await userEvent.keyboard('{Tab}')\n  await userEvent.keyboard(\"{Alt>}\")\n  expect(logs).toMatchInlineSnapshot(`\n    [\n      [\n        \"Tab\",\n        false,\n      ],\n      [\n        \"Alt\",\n        true,\n      ],\n    ]\n  `)\n})\n\n// test per-test cleanup\ntest('cleanup1.2', async () => {\n  let logs: any[] = [];\n  function handler(e: KeyboardEvent) {\n    logs.push([e.key, e.altKey]);\n  };\n  document.addEventListener('keydown', handler)\n  onTestFinished(() => {\n    document.removeEventListener('keydown', handler);\n  })\n\n  await userEvent.keyboard('{Tab}')\n  await userEvent.keyboard(\"{Alt>}\")\n  expect(logs).toMatchInlineSnapshot(`\n    [\n      [\n        \"Tab\",\n        false,\n      ],\n      [\n        \"Alt\",\n        true,\n      ],\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/browser/fixtures/user-event/cleanup2.test.ts",
    "content": "import { expect, onTestFinished, test } from 'vitest'\nimport { userEvent } from 'vitest/browser'\n\n// test per-test-file cleanup just in case\n\ntest('cleanup2', async () => {\n  let logs: any[] = [];\n  function handler(e: KeyboardEvent) {\n    logs.push([e.key, e.altKey]);\n  };\n  document.addEventListener('keydown', handler)\n  onTestFinished(() => {\n    document.removeEventListener('keydown', handler);\n  })\n\n  await userEvent.keyboard('{Tab}')\n  await userEvent.keyboard(\"{Alt>}\")\n  expect(logs).toMatchInlineSnapshot(`\n    [\n      [\n        \"Tab\",\n        false,\n      ],\n      [\n        \"Alt\",\n        true,\n      ],\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/browser/fixtures/user-event/clipboard.test.ts",
    "content": "import { expect, test } from 'vitest';\nimport { page, userEvent } from 'vitest/browser';\n\ntest('clipboard', async () => {\n  // make it smaller since webdriverio fails when scaled\n  page.viewport(300, 300)\n\n  document.body.innerHTML = `\n    <input placeholder=\"first\" />\n    <input placeholder=\"second\" />\n    <input placeholder=\"third\" />\n  `;\n\n  // write first \"hello\" and copy to clipboard\n  await userEvent.click(page.getByPlaceholder('first'));\n  await userEvent.keyboard('hello');\n  await userEvent.dblClick(page.getByPlaceholder('first'));\n  await userEvent.copy();\n\n  // paste into second\n  await userEvent.click(page.getByPlaceholder('second'));\n  await userEvent.paste();\n\n  // append first \"world\" and cut\n  await userEvent.click(page.getByPlaceholder('first'));\n  await userEvent.keyboard('world');\n  await userEvent.dblClick(page.getByPlaceholder('first'));\n  await userEvent.cut();\n\n  // paste it to third\n  await userEvent.click(page.getByPlaceholder('third'));\n  await userEvent.paste();\n\n  expect([\n    (page.getByPlaceholder('first').element() as any).value,\n    (page.getByPlaceholder('second').element() as any).value,\n    (page.getByPlaceholder('third').element() as any).value,\n  ]).toMatchInlineSnapshot(`\n    [\n      \"\",\n      \"hello\",\n      \"helloworld\",\n    ]\n  `)\n});\n"
  },
  {
    "path": "test/browser/fixtures/user-event/keyboard.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { userEvent, page, server } from 'vitest/browser'\n\ntest('non US keys', async () => {\n  document.body.innerHTML = `\n    <input placeholder=\"type-#7396\" />\n    <input placeholder=\"fill-#7396\" />\n    <input placeholder=\"type-emoji\" />\n    <input placeholder=\"fill-emoji\" />\n  `;\n\n  await userEvent.type(page.getByPlaceholder(\"type-#7396\"), 'éèù')\n  await expect.element(page.getByPlaceholder(\"type-#7396\")).toHaveValue('éèù')\n  await userEvent.fill(page.getByPlaceholder(\"fill-#7396\"), 'éèù')\n  await expect.element(page.getByPlaceholder(\"fill-#7396\")).toHaveValue('éèù')\n\n  // playwright: garbled characters\n  // webdriverio: error: invalid argument: missing command parameters\n  // preview: ok\n  if (server.provider === 'playwright') {\n    await userEvent.type(page.getByPlaceholder(\"type-emoji\"), '😊😍')\n    if (server.browser === 'chromium') {\n      await expect.element(page.getByPlaceholder(\"type-emoji\")).toHaveValue('����')\n    } else {\n      await expect.element(page.getByPlaceholder(\"type-emoji\")).toHaveValue('😊😍')\n    }\n  } else if (server.provider === 'webdriverio') {\n    await expect(() =>\n      userEvent.type(page.getByPlaceholder(\"type-emoji\"), '😊😍')\n    ).rejects.toThrow()\n  } else {\n    await userEvent.type(page.getByPlaceholder(\"type-emoji\"), '😊😍')\n    await expect.element(page.getByPlaceholder(\"type-emoji\")).toHaveValue('😊😍')\n  }\n\n  // playwright: ok\n  // webdriverio: error: ChromeDriver only supports characters in the BMP\n  // preview: ok\n  if (server.provider === 'webdriverio') {\n    if (server.browser === 'firefox') {\n      await userEvent.fill(page.getByPlaceholder(\"fill-emoji\"), '😊😍')\n      await expect.element(page.getByPlaceholder(\"fill-emoji\")).toHaveValue('😊😍')\n    } else {\n      await expect(() =>\n        userEvent.fill(page.getByPlaceholder(\"fill-emoji\"), '😊😍')\n      ).rejects.toThrow()\n    }\n  } else {\n    await userEvent.fill(page.getByPlaceholder(\"fill-emoji\"), '😊😍')\n    await expect.element(page.getByPlaceholder(\"fill-emoji\")).toHaveValue('😊😍')\n  }\n})\n\ntest('click with modifier', async () => {\n  document.body.innerHTML = `\n    <div id=\"test\">test shift and click</div>\n  `\n  const el = document.getElementById(\"test\")\n  el.addEventListener(\"pointerup\", (e) => {\n    if (e.shiftKey && e.type === 'pointerup') {\n      el.textContent += \" [ok]\"\n    }\n  });\n\n  await userEvent.keyboard('{Shift>}')\n  // By using an empty object as the option, this opts in to using a chain of actions instead of an elementClick in webdriver.\n  await userEvent.click(el, {})\n  await userEvent.keyboard('{/Shift}')\n  await expect.poll(() => el.textContent).toContain(\"[ok]\")\n})\n\n// TODO: https://github.com/vitest-dev/vitest/issues/7118\n// https://testing-library.com/docs/user-event/keyboard\n// https://github.com/testing-library/user-event/blob/main/src/keyboard/keyMap.ts\n// https://playwright.dev/docs/api/class-keyboard\n// https://webdriver.io/docs/api/browser/keys/\ntest('special keys', async () => {\n  async function testKeyboard(text: string) {\n    let data: any;\n    function handler(e: KeyboardEvent) {\n      data = `${e.key}|${e.code}|${e.location}`;\n    }\n    document.addEventListener('keydown', handler)\n    try {\n      await userEvent.keyboard(text)\n    } catch(e) {\n      return 'ERROR';\n    } finally {\n      document.removeEventListener('keydown', handler)\n    }\n    return data\n  }\n\n  if (server.provider === 'playwright') {\n    expect(await testKeyboard('{Shift}')).toMatchInlineSnapshot(`\"Shift|ShiftLeft|1\"`);\n    expect(await testKeyboard('{ShiftLeft}')).toMatchInlineSnapshot(`\"Shift|ShiftLeft|1\"`);\n    expect(await testKeyboard('{ShiftRight}')).toMatchInlineSnapshot(`\"Shift|ShiftRight|2\"`);\n    expect(await testKeyboard('[Shift]')).toMatchInlineSnapshot(`undefined`);\n    expect(await testKeyboard('[ShiftLeft]')).toMatchInlineSnapshot(`\"Shift|ShiftLeft|1\"`);\n    expect(await testKeyboard('[ShiftRight]')).toMatchInlineSnapshot(`\"Shift|ShiftLeft|1\"`);\n  }\n  if (server.provider === 'webdriverio') {\n    expect(await testKeyboard('{Shift}')).toMatchInlineSnapshot(`\"Shift|ShiftLeft|1\"`);\n    expect(await testKeyboard('{ShiftLeft}')).toMatchInlineSnapshot(`\"ERROR\"`);\n    expect(await testKeyboard('{ShiftRight}')).toMatchInlineSnapshot(`\"ERROR\"`);\n    expect(await testKeyboard('[Shift]')).toMatchInlineSnapshot(`\"ERROR\"`);\n    expect(await testKeyboard('[ShiftLeft]')).toMatchInlineSnapshot(`\"Shift|ShiftLeft|1\"`);\n    expect(await testKeyboard('[ShiftRight]')).toMatchInlineSnapshot(`\"Shift|ShiftLeft|1\"`);\n  }\n  if (server.provider === 'preview') {\n    expect(await testKeyboard('{Shift}')).toMatchInlineSnapshot(`\"Shift|ShiftLeft|0\"`);\n    expect(await testKeyboard('{ShiftLeft}')).toMatchInlineSnapshot(`\"ShiftLeft|Unknown|0\"`);\n    expect(await testKeyboard('{ShiftRight}')).toMatchInlineSnapshot(`\"ShiftRight|Unknown|0\"`);\n    expect(await testKeyboard('[Shift]')).toMatchInlineSnapshot(`\"Unknown|Shift|0\"`);\n    expect(await testKeyboard('[ShiftLeft]')).toMatchInlineSnapshot(`\"Shift|ShiftLeft|0\"`);\n    expect(await testKeyboard('[ShiftRight]')).toMatchInlineSnapshot(`\"Shift|ShiftRight|0\"`);\n  }\n})\n"
  },
  {
    "path": "test/browser/fixtures/user-event/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { provider, instances } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/fixtures/user-event/wheel.test.ts",
    "content": "import { describe, test, vi } from 'vitest'\nimport { userEvent, page } from 'vitest/browser'\n\ndescribe.for([\n  'userEvent',\n  'locator'\n] as const)('`%s`', (testType) => {\n  test.for([\n    ['up', { deltaX: 0, deltaY: -100 }],\n    ['down', { deltaX: 0, deltaY: 100 }],\n    ['left', { deltaX: -100, deltaY: 0 }],\n    ['right', { deltaX: 100, deltaY: 0 }]\n  ] as const)('scrolls %s with default delta of 100', async ([direction, { deltaX, deltaY }], { expect }) => {\n    document.body.innerHTML = `\n        <div style=\"padding: 1rem;\">\n          <button>Scroll Me</button>\n        </div>\n      `;\n\n    const wheel = vi.fn<(event: WheelEvent) => void>()\n    document.body.querySelector('button').addEventListener('wheel', wheel, { passive: true })\n\n    const options = { direction }\n    const selector = page.getByRole(\"button\")\n\n    await (testType === 'userEvent' ? userEvent.wheel(selector, options) : selector.wheel(options))\n\n    await expect.poll(() => wheel).toHaveBeenCalledOnce()\n    expect(wheel.mock.calls[0][0].deltaX).toBe(deltaX)\n    expect(wheel.mock.calls[0][0].deltaY).toBe(deltaY)\n  })\n\n  test.for([\n    { deltaX: 0, deltaY: -50 },\n    { deltaX: 0, deltaY: 50 },\n    { deltaX: -50, deltaY: 0 },\n    { deltaX: 50, deltaY: 0 }\n  ] as const)('scrolls with custom delta values %o', async ({ deltaX, deltaY }, { expect }) => {\n    document.body.innerHTML = `\n        <div style=\"padding: 1rem;\">\n          <button>Scroll Me</button>\n        </div>\n      `;\n\n    const wheel = vi.fn<(event: WheelEvent) => void>()\n    document.body.querySelector('button').addEventListener('wheel', wheel, { passive: true })\n\n    const options = {\n      delta: {\n        x: deltaX,\n        y: deltaY,\n      },\n    }\n    const selector = page.getByRole(\"button\")\n\n    await (testType === 'userEvent' ? userEvent.wheel(selector, options) : selector.wheel(options))\n\n    expect(wheel).toHaveBeenCalledOnce()\n    expect(wheel.mock.calls[0][0].deltaX).toBe(deltaX)\n    expect(wheel.mock.calls[0][0].deltaY).toBe(deltaY)\n  })\n\n  test(\"fires wheel event multiple times when `times` option is set\", { retry: 5 }, async ({ expect }) => {\n    document.body.innerHTML = `\n        <div style=\"padding: 1rem;\">\n          <button>Scroll Me</button>\n        </div>\n      `;\n\n    const wheel = vi.fn<(event: WheelEvent) => void>()\n    document.body.querySelector('button').addEventListener('wheel', wheel, { passive: true })\n\n    const options = { direction: 'down', times: 5 } as const\n    const selector = page.getByRole(\"button\")\n\n    await (testType === 'userEvent' ? userEvent.wheel(selector, options) : selector.wheel(options))\n\n    expect(wheel).toHaveBeenCalledTimes(5)\n\n    for (const call of wheel.mock.calls) {\n      expect(call[0].deltaX).toBe(0)\n      expect(call[0].deltaY).toBe(100)\n    }\n  })\n})\n"
  },
  {
    "path": "test/browser/fixtures/viewport/basic.test.ts",
    "content": "import { page, userEvent, server } from \"vitest/browser\";\nimport { expect, test } from \"vitest\";\n\ntest(\"drag and drop over large viewport\", async () => {\n  // put boxes horizontally [1] [2] ... [30]\n  // then drag-and-drop from [1] to [30]\n\n  const wrapper = document.createElement(\"div\");\n  wrapper.style.cssText = \"display: flex; width: 3000px;\";\n  document.body.appendChild(wrapper);\n\n  const events: { i: number; type: string }[] = [];\n\n  for (let i = 1; i <= 30; i++) {\n    const el = document.createElement(\"div\");\n    el.textContent = `[${i}]`;\n    el.style.cssText = `\n      flex: none;\n      width: 100px;\n      height: 100px;\n      border: 1px solid black;\n      box-sizing: border-box;\n      display: flex;\n      justify-content: center;\n      align-items: center;\n    `;\n    el.draggable = true;\n    wrapper.append(el);\n\n    el.addEventListener(\"dragstart\", (ev) => {\n      ev.dataTransfer.effectAllowed = \"move\";\n      events.push({ type: \"dragstart\", i });\n    });\n    el.addEventListener(\"dragover\", (ev) => {\n      ev.preventDefault();\n      ev.dataTransfer.dropEffect = \"move\";\n      events.push({ type: \"dragover\", i });\n    });\n    el.addEventListener(\"drop\", (ev) => {\n      ev.preventDefault();\n      events.push({ type: \"drop\", i });\n    });\n  }\n\n  // drag and drop only works reliably on playwright\n  if (server.provider !== 'playwright') {\n    return\n  }\n\n  await userEvent.dragAndDrop(page.getByText(\"[1]\"), page.getByText(\"[30]\"));\n\n  expect(events).toMatchObject(\n    expect.arrayContaining([\n      { type: \"dragstart\", i: 1 },\n      { type: \"drop\", i: 30 },\n    ]),\n  );\n});\n"
  },
  {
    "path": "test/browser/fixtures/viewport/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from '../../settings'\n\n// pnpm -C test/browser test-fixtures --root fixtures/viewport --browser.ui=false\n// pnpm -C test/browser test-fixtures --root fixtures/viewport --browser.headless=true\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances: instances.map(instance => ({\n        ...instance,\n        viewport: { width: 3000, height: 400 }\n      })),\n\n    },\n  },\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n})\n"
  },
  {
    "path": "test/browser/fixtures/worker/src/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('worker dynamic dep', async () => {\n  const worker = new Worker(new URL('./worker', import.meta.url), { type: 'module' });\n  const data = await new Promise((resolve, reject) => {\n    worker.addEventListener(\"message\", (e) => resolve(e.data))\n    worker.addEventListener(\"messageerror\", (e) => reject(e))\n    worker.postMessage(\"ping\");\n  });\n  expect(data).toMatchInlineSnapshot(`\"worker-dynamic-dep-ok\"`);\n})\n"
  },
  {
    "path": "test/browser/fixtures/worker/src/worker-dynamic-dep.ts",
    "content": "export default \"worker-dynamic-dep-ok\"\n"
  },
  {
    "path": "test/browser/fixtures/worker/src/worker.ts",
    "content": "self.onmessage = async () => {\n  const mod = await import(\"./worker-dynamic-dep\");\n  self.postMessage(mod.default);\n}\n"
  },
  {
    "path": "test/browser/fixtures/worker/vitest.config.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\nimport { provider, instances } from '../../settings'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    browser: {\n      enabled: true,\n      provider,\n      instances,\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/injected.ts",
    "content": "// @ts-expect-error not typed global\n;(__injected as string[]).push(2)\n"
  },
  {
    "path": "test/browser/package.json",
    "content": "{\n  \"name\": \"@vitest/test-browser\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"pnpm run test:webdriverio && pnpm run test:playwright\",\n    \"test:unit\": \"vitest --no-watch --config=vitest.config.unit.mts\",\n    \"test:webdriverio\": \"PROVIDER=webdriverio pnpm run test:unit\",\n    \"test:playwright\": \"PROVIDER=playwright pnpm run test:unit\",\n    \"test:safaridriver\": \"PROVIDER=webdriverio BROWSER=safari pnpm run test:unit\",\n    \"test-fixtures\": \"vitest\",\n    \"test-expect-dom\": \"vitest --root ./fixtures/expect-dom\",\n    \"test-mocking\": \"vitest --root ./fixtures/mocking\",\n    \"test-logs\": \"vitest --root ./fixtures/print-logs\",\n    \"test-failing\": \"vitest --root ./fixtures/failing\",\n    \"test-timeout\": \"vitest --root ./fixtures/timeout\",\n    \"test-timeout-hooks\": \"vitest --root ./fixtures/timeout-hooks\",\n    \"test-mocking-watch\": \"vitest --root ./fixtures/mocking-watch\",\n    \"test-locators\": \"vitest --root ./fixtures/locators\",\n    \"test-locators-custom\": \"vitest --root ./fixtures/locators-custom\",\n    \"test-different-configs\": \"vitest --root ./fixtures/multiple-different-configs\",\n    \"test-setup-file\": \"vitest --root ./fixtures/setup-file\",\n    \"test-snapshots\": \"vitest --root ./fixtures/update-snapshot\",\n    \"test-broken-iframe\": \"vitest --root ./fixtures/broken-iframe\",\n    \"coverage\": \"vitest --coverage.enabled --coverage.provider=istanbul --browser.headless=yes\",\n    \"test:browser:preview\": \"PROVIDER=preview vitest\",\n    \"test:browser:playwright\": \"PROVIDER=playwright vitest\",\n    \"test:browser:webdriverio\": \"PROVIDER=webdriverio vitest\",\n    \"test:browser:playwright:html\": \"PROVIDER=playwright vitest --reporter=html\",\n    \"docker\": \"docker compose\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.14\",\n    \"@types/yauzl\": \"catalog:\",\n    \"@vitejs/plugin-basic-ssl\": \"^2.1.4\",\n    \"@vitest/browser\": \"workspace:*\",\n    \"@vitest/browser-playwright\": \"workspace:*\",\n    \"@vitest/browser-preview\": \"workspace:*\",\n    \"@vitest/browser-webdriverio\": \"workspace:*\",\n    \"@vitest/bundled-lib\": \"link:./bundled-lib\",\n    \"@vitest/cjs-lib\": \"link:./cjs-lib\",\n    \"playwright\": \"^1.58.2\",\n    \"react\": \"^19.2.4\",\n    \"react-dom\": \"^19.2.4\",\n    \"test-dep-error\": \"file:./deps/test-dep-error\",\n    \"tinyexec\": \"catalog:\",\n    \"url\": \"^0.11.4\",\n    \"vitest\": \"workspace:*\",\n    \"vitest-browser-react\": \"^2.0.5\",\n    \"ws\": \"catalog:\",\n    \"yauzl\": \"catalog:\"\n  }\n}\n"
  },
  {
    "path": "test/browser/settings.ts",
    "content": "import type { BrowserInstanceOption } from 'vitest/node'\nimport { playwright } from '@vitest/browser-playwright'\nimport { preview } from '@vitest/browser-preview'\nimport { webdriverio } from '@vitest/browser-webdriverio'\n\nconst providerName = (process.env.PROVIDER || 'playwright') as 'playwright' | 'webdriverio' | 'preview'\n\nconst wsEndpoint = process.env.BROWSER_WS_ENDPOINT === 'true' ? 'ws://127.0.0.1:6677/' : process.env.BROWSER_WS_ENDPOINT\n\nexport const providers = {\n  playwright: (options?: Parameters<typeof playwright>[0]) => playwright(wsEndpoint\n    ? {\n        ...options,\n        connectOptions: {\n          wsEndpoint,\n          exposeNetwork: '<loopback>',\n        },\n      }\n    : options),\n  preview,\n  webdriverio,\n}\n\nexport const provider = providers[providerName]()\n\nconst playwrightInstances: BrowserInstanceOption[] = [\n  { browser: 'chromium' },\n  { browser: 'firefox' },\n  // hard to setup playwright webkit on some machines (e.g. ArchLinux)\n  // this allows skipping it locally by BROWSER_NO_WEBKIT=true\n  ...(process.env.BROWSER_NO_WEBKIT ? [] : [{ browser: 'webkit' as const }]),\n]\n\nconst webdriverioInstances: BrowserInstanceOption[] = [\n  { browser: 'chrome' },\n  { browser: 'firefox' },\n]\n\nexport const instances: BrowserInstanceOption[] = process.env.BROWSER\n  ? [\n      {\n        browser: process.env.BROWSER as any,\n        headless: process.env.BROWSER === 'safari' ? false : undefined,\n      },\n    ]\n  : provider.name === 'playwright'\n    ? playwrightInstances\n    : webdriverioInstances\n"
  },
  {
    "path": "test/browser/setup.unit.ts",
    "content": "import type { BrowserInstanceOption } from 'vitest/node'\nimport { expect } from 'vitest'\n\ninterface SummaryOptions {\n  passed?: number\n}\n\nexpect.extend({\n  toReportPassedTest(stdout: string, testName: string, testProject?: string | BrowserInstanceOption[]) {\n    const checks: BrowserInstanceOption[] | undefined = Array.isArray(testProject)\n      ? testProject\n      : (testProject && [{ browser: testProject }])\n\n    const pass = checks?.length\n      ? checks.every(({ browser }) => {\n          const includePattern = `✓ |${browser}| ${testName}`\n          return stdout.includes(includePattern)\n        })\n      : stdout.includes(`✓ ${testName}`)\n\n    return {\n      pass,\n      message: () => {\n        const includePattern = checks?.length\n          ? checks.map(check => `✓ |${check.browser}| ${testName}`).join('\\n')\n          : `✓ ${testName}`\n        return `expected ${pass ? 'not ' : ''}to have \"${includePattern}\" in the report.\\n\\nstdout:\\n${stdout}`\n      },\n    }\n  },\n  toReportSummaryTestFiles(stdout: string, { passed }: SummaryOptions) {\n    const includePattern = `Test Files  ${passed} passed`\n    const pass = !passed || stdout.includes(includePattern)\n    return {\n      pass,\n      message: () => `expected ${pass ? 'not ' : ''}to have \"${includePattern}\" in the report.\\n\\nstdout:\\n${stdout}`,\n    }\n  },\n  toReportSummaryTests(stdout: string, { passed }: SummaryOptions) {\n    const includePattern = `Tests  ${passed} passed`\n    const pass = !passed || stdout.includes(includePattern)\n    return {\n      pass,\n      message: () => `expected ${pass ? 'not ' : ''}to have \"${includePattern}\" in the report.\\n\\nstdout:\\n${stdout}`,\n    }\n  },\n  toReportNoErrors(stderr: string) {\n    const pass = !stderr\n    return {\n      pass,\n      message: () => `expected ${pass ? 'not ' : ''}to have no errors.\\n\\nstderr:\\n${stderr}`,\n    }\n  },\n})\n\ndeclare module 'vitest' {\n  interface Matchers {\n    // eslint-disable-next-line ts/method-signature-style\n    toReportPassedTest(testName: string, testProject?: string | BrowserInstanceOption[]): void\n    // eslint-disable-next-line ts/method-signature-style\n    toReportSummaryTestFiles(options: SummaryOptions): void\n    // eslint-disable-next-line ts/method-signature-style\n    toReportSummaryTests(options: SummaryOptions): void\n    // eslint-disable-next-line ts/method-signature-style\n    toReportNoErrors(): void\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "test/browser/specs/__snapshots__/expect-element-no-awaited.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`should fail for non-awaited expect.element 1`] = `\n\"\n⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n FAIL  |browser (chromium)| expect-element.test.js > not awaited\nError: expect.element(locator).toBeInTheDocument() was not awaited. This assertion is asynchronous and must be awaited; otherwise, it is not executed to avoid unhandled rejections:\n\nawait expect.element(locator).toBeInTheDocument()\n\n ❯ expect-element.test.js:18:33\n     16|         const element = page.getByText(\"Hello Vitest!\");\n     17|\n     18|         expect.element(element).toBeInTheDocument();\n       |                                 ^\n     19|       })\n     20|\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n\"\n`;\n"
  },
  {
    "path": "test/browser/specs/__snapshots__/update-snapshot.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`update snapshot 1`] = `\n\"import { expect, test, vi } from 'vitest'\n\ninterface _BasicInterface {\n  willBeRemoved: boolean\n  leavingSourceMapIncorrect: boolean\n}\n\ntest('inline snapshot', () => {\n  expect(1).toMatchInlineSnapshot('1')\n})\n\ntest('basic', () => {\n  expect(1).toMatchSnapshot()\n})\n\ntest('renders inline mock snapshot', () => {\n  const fn = vi.fn()\n  expect(fn).toMatchInlineSnapshot(\\`[MockFunction]\\`)\n  fn('hello', 'world', 2)\n  expect(fn).toMatchInlineSnapshot(\\`\n    [MockFunction] {\n      \"calls\": [\n        [\n          \"hello\",\n          \"world\",\n          2,\n        ],\n      ],\n      \"results\": [\n        {\n          \"type\": \"return\",\n          \"value\": undefined,\n        },\n      ],\n    }\n  \\`)\n})\n\ntest('file snapshot', async () => {\n  await expect('my snapshot content')\n    .toMatchFileSnapshot('./__snapshots__/custom/my_snapshot')\n})\n\n\"\n`;\n"
  },
  {
    "path": "test/browser/specs/assertion-helper.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { instances, runBrowserTests } from './utils'\n\ntest('vi.defineHelper hides internal stack traces', async () => {\n  const { errorTree } = await runBrowserTests({\n    root: './fixtures/assertion-helper',\n  })\n\n  const projectTree = errorTree({ project: true, stackTrace: true })\n  expect(Object.keys(projectTree).sort()).toEqual(instances.map(i => i.browser).sort())\n\n  for (const [name, tree] of Object.entries(projectTree)) {\n    if (name === 'firefox') {\n      expect.soft(tree).toMatchInlineSnapshot(`\n        {\n          \"basic.test.ts\": {\n            \"async\": [\n              \"expected 'async' to deeply equal 'x'\n            at basic.test.ts:26:8\",\n            ],\n            \"soft\": [\n              \"expected 'soft' to deeply equal 'x'\n            at basic.test.ts:30:14\",\n            ],\n            \"soft async\": [\n              \"expected 'soft async' to deeply equal 'x'\n            at basic.test.ts:34:8\",\n            ],\n            \"sync\": [\n              \"expected 'sync' to deeply equal 'x'\n            at basic.test.ts:22:10\",\n            ],\n          },\n        }\n      `)\n    }\n    else if (name === 'webkit') {\n      // async stack trace is incomplete on webkit\n      // waiting for https://github.com/WebKit/WebKit/pull/57832 to land on playwright\n      // bun has already landed https://github.com/oven-sh/bun/pull/22517\n      expect.soft(tree).toMatchInlineSnapshot(`\n        {\n          \"basic.test.ts\": {\n            \"async\": [\n              \"expected 'async' to deeply equal 'x'\n            at basic.test.ts:9:20\",\n            ],\n            \"soft\": [\n              \"expected 'soft' to deeply equal 'x'\n            at basic.test.ts:30:14\",\n            ],\n            \"soft async\": [\n              \"expected 'soft async' to deeply equal 'x'\n            at basic.test.ts:18:25\",\n            ],\n            \"sync\": [\n              \"expected 'sync' to deeply equal 'x'\n            at basic.test.ts:22:10\",\n            ],\n          },\n        }\n      `)\n    }\n    else {\n      expect.soft(tree).toMatchInlineSnapshot(`\n        {\n          \"basic.test.ts\": {\n            \"async\": [\n              \"expected 'async' to deeply equal 'x'\n            at basic.test.ts:26:2\",\n            ],\n            \"soft\": [\n              \"expected 'soft' to deeply equal 'x'\n            at basic.test.ts:30:2\",\n            ],\n            \"soft async\": [\n              \"expected 'soft async' to deeply equal 'x'\n            at basic.test.ts:34:2\",\n            ],\n            \"sync\": [\n              \"expected 'sync' to deeply equal 'x'\n            at basic.test.ts:22:2\",\n            ],\n          },\n        }\n      `)\n    }\n  }\n})\n"
  },
  {
    "path": "test/browser/specs/bail-out.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runBrowserTests } from './utils'\n\ntest('fails gracefully when browser crashes', async () => {\n  const { stderr } = await runBrowserTests({\n    root: './fixtures/browser-crash',\n    reporters: [['verbose', { isTTY: false }]],\n  })\n\n  expect(stderr).toContain('Browser connection was closed while running tests. Was the page closed unexpectedly?')\n})\n\ntest('vitest bails out when the iframe is no longer accessible', async () => {\n  const { stderr } = await runBrowserTests({\n    root: './fixtures/broken-iframe',\n    reporters: [['verbose', { isTTY: false }]],\n  }, [], {}, { fails: true })\n  expect(stderr).toContain(\n    'Cannot connect to the iframe. Did you change the location or submitted a form? If so, don\\'t forget to call `event.preventDefault()` to avoid reloading the page.',\n  )\n  expect(stderr).toContain('Received URL: http://')\n  expect(stderr).toContain('Expected: http://')\n})\n"
  },
  {
    "path": "test/browser/specs/benchmark.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nconst IS_PLAYWRIGHT = process.env.PROVIDER === 'playwright'\n\ntest('benchmark', async () => {\n  const result = await runVitest({ root: 'fixtures/benchmark' }, [], { mode: 'benchmark' })\n  expect(result.stderr).toReportNoErrors()\n\n  if (IS_PLAYWRIGHT) {\n    expect(result.stdout).toContain('✓ |chromium| basic.bench.ts > suite-a')\n    expect(result.stdout).toContain('✓ |firefox| basic.bench.ts > suite-a')\n    expect(result.stdout).toContain('✓ |webkit| basic.bench.ts > suite-a')\n  }\n  else {\n    expect(result.stdout).toContain('✓ |chrome| basic.bench.ts > suite-a')\n    expect(result.stdout).toContain('✓ |firefox| basic.bench.ts > suite-a')\n  }\n\n  expect(result.exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/browser/specs/errors.test.ts",
    "content": "import path from 'pathe'\nimport { expect, test } from 'vitest'\nimport { rolldownVersion } from 'vitest/node'\nimport { buildTestProjectTree } from '../../test-utils'\nimport { instances, runBrowserTests, runInlineBrowserTests } from './utils'\n\ntest('prints correct unhandled error stack', async () => {\n  const { stderr } = await runBrowserTests({\n    root: './fixtures/unhandled',\n  })\n\n  expect(stderr).toContain('throw-unhandled-error.test.ts:9:10')\n  expect(stderr).toContain('This error originated in \"throw-unhandled-error.test.ts\" test file.')\n  expect(stderr).toContain('The latest test that might\\'ve caused the error is \"unhandled exception\".')\n\n  if (instances.some(({ browser }) => browser === 'webkit')) {\n    expect(stderr).toContain('throw-unhandled-error.test.ts:9:20')\n  }\n})\n\ntest('ignores unhandled errors', async () => {\n  const { stderr } = await runBrowserTests({\n    root: './fixtures/unhandled',\n    onUnhandledError(error) {\n      if (error.message.includes('custom_unhandled_error')) {\n        return false\n      }\n    },\n  })\n\n  expect(stderr).toBe('')\n})\n\ntest('disables tracking', async () => {\n  const { stderr } = await runBrowserTests({\n    root: './fixtures/unhandled',\n    browser: {\n      trackUnhandledErrors: false,\n    },\n  })\n  expect(stderr).toBe('')\n})\n\ntest('print unhandled non error', async () => {\n  const { testTree, stderr } = await runBrowserTests({\n    root: './fixtures/unhandled-non-error',\n  })\n  expect(stderr).toContain('[Error: ResizeObserver loop completed with undelivered notifications.]')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"ResizeObserver error\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('throws an error if test reloads the iframe during a test run', async () => {\n  const { stderr, fs } = await runInlineBrowserTests({\n    'iframe-reload.test.ts': `\n      import { test } from 'vitest';\n\n      test('reload iframe', () => {\n        location.reload();\n      });\n    `,\n  })\n  expect(stderr).toContain(\n    `The iframe for \"${fs.resolveFile('./iframe-reload.test.ts')}\" was reloaded during a test.`,\n  )\n})\n\ntest('cannot use fs commands if write is disabled', async () => {\n  const { stderr, fs } = await runInlineBrowserTests({\n    'fs-commands.test.ts': `\n      import { test, expect, recordArtifact } from 'vitest'\n      import { commands } from 'vitest/browser'\n\n      test.describe('fs security', () => {\n        test('fs writeFile throws an error', async () => {\n          await commands.writeFile('/test-file.txt', 'Hello World')\n        })\n\n        test('fs removeFile throws an error', async () => {\n          await commands.removeFile('/test-file.txt')\n        })\n\n        test('doesnt write attachment to disk', async ({ annotate }) => {\n          await annotate('test-attachment', { data: 'Test Attachment', path: '/test-attachment.txt' })\n        })\n\n        test('cannot record attachments inside artifact', async ({ task }) => {\n          await recordArtifact(task, {\n            attachments: [{ data: 'Artifact Attachment', path: '/artifact-attachment.txt' }],\n            type: 'my-custom',\n          })\n        })\n\n        test('snapshot saves are not saved', () => {\n          expect('snapshot content').toMatchSnapshot()\n        })\n      })\n    `,\n    './__snapshots__/basic.test.js.snap': `// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html`,\n    'basic.test.js': `\n      import { test } from 'vitest'\n\n      test('basic test', () => {\n        expect(1 + 1).toBe(2)\n      })\n    `,\n  }, {\n    browser: {\n      api: {\n        allowExec: false,\n        allowWrite: false,\n      },\n    },\n    $cliOptions: {\n      update: true,\n    },\n  })\n\n  const errors = stderr.split('\\n').filter(line => line.includes('Cannot modify file \"/test-file.txt\".'))\n  expect(errors).toHaveLength(2 * instances.length)\n\n  expect(stderr).toContain(\n    `Cannot save snapshot file \"${fs.resolveFile('./__snapshots__/fs-commands.test.ts.snap')}\". File writing is disabled because server is exposed to the internet`,\n  )\n  expect(stderr).toContain(\n    `Cannot remove snapshot file \"${fs.resolveFile('./__snapshots__/basic.test.js.snap')}\". File writing is disabled because server is exposed to the internet`,\n  )\n\n  // we don't throw an error if cannot write attachment, just warn\n  expect(stderr).toContain(\n    'Cannot record annotation attachment because file writing is disabled',\n  )\n  expect(stderr).toContain(\n    'Cannot record attachments (\"/artifact-attachment.txt\") because file writing is disabled, removing attachments from artifact \"my-custom\".',\n  )\n})\n\ntest('prints source-mapped stack for optimized dependency', async () => {\n  const { results, ctx } = await runBrowserTests({\n    root: './fixtures/error-in-dep',\n  })\n\n  const projectTree = buildTestProjectTree(results, (testCase) => {\n    const result = testCase.result()\n    return result.errors.map((e) => {\n      const stacks = e.stacks.map((s) => {\n        const normalizedFile = path\n          .relative(ctx.config.root, s.file)\n          .replace(\n            /node_modules[\\\\/]\\.pnpm[\\\\/][^\\\\/\\n]+[\\\\/]node_modules[\\\\/]/g,\n            'node_modules/.pnpm/<normalized>/node_modules/',\n          )\n        return `${s.method} at ${normalizedFile}:${s.line}:${s.column}`\n      })\n      return ({ message: e.message, stacks })\n    })\n  })\n  expect(Object.keys(projectTree).sort()).toEqual(instances.map(i => i.browser).sort())\n\n  for (const [name, tree] of Object.entries(projectTree)) {\n    if (name === 'webkit') {\n      if (rolldownVersion) {\n        expect(tree).toMatchInlineSnapshot(`\n          {\n            \"basic.test.ts\": {\n              \"fail\": [\n                {\n                  \"message\": \"this is test dependency error\",\n                  \"stacks\": [\n                    \"throwDepError at ../../../../node_modules/.pnpm/<normalized>/node_modules/test-dep-error/index.js:2:18\",\n                    \" at basic.test.ts:5:2\",\n                  ],\n                },\n              ],\n            },\n          }\n        `)\n      }\n      else {\n        expect(tree).toMatchInlineSnapshot(`\n          {\n            \"basic.test.ts\": {\n              \"fail\": [\n                {\n                  \"message\": \"this is test dependency error\",\n                  \"stacks\": [\n                    \"throwDepError at ../../../../node_modules/.pnpm/<normalized>/node_modules/test-dep-error/index.js:2:18\",\n                    \" at basic.test.ts:5:16\",\n                  ],\n                },\n              ],\n            },\n          }\n        `)\n      }\n    }\n    else {\n      expect(tree).toMatchInlineSnapshot(`\n        {\n          \"basic.test.ts\": {\n            \"fail\": [\n              {\n                \"message\": \"this is test dependency error\",\n                \"stacks\": [\n                  \"throwDepError at ../../../../node_modules/.pnpm/<normalized>/node_modules/test-dep-error/index.js:2:8\",\n                  \" at basic.test.ts:5:2\",\n                ],\n              },\n            ],\n          },\n        }\n      `)\n    }\n  }\n})\n"
  },
  {
    "path": "test/browser/specs/expect-dom.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { instances, runBrowserTests } from './utils'\n\nconst testNames = Object.keys(import.meta.glob('../fixtures/expect-dom/*.test.ts', {\n  eager: false,\n})).map(path => path.slice('../fixtures/expect-dom/'.length))\n\ntest('expect-dom works correctly', async () => {\n  const { stderr, stdout } = await runBrowserTests({\n    root: './fixtures/expect-dom',\n  })\n\n  expect(stderr).toReportNoErrors()\n  instances.forEach(({ browser }) => {\n    testNames.forEach((name) => {\n      expect(stdout).toReportPassedTest(name, browser)\n    })\n  })\n\n  expect(stdout).toContain(`Test Files  ${instances.length * testNames.length} passed`)\n})\n"
  },
  {
    "path": "test/browser/specs/expect-element-no-awaited.test.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\nimport { expect, test } from 'vitest'\nimport { runInlineTests, ts } from '../../test-utils'\n\ntest('should fail for non-awaited expect.element', async () => {\n  const { stderr } = await runInlineTests({\n    'expect-element.test.js': ts`\n      import { expect, test, beforeAll } from 'vitest';\n      import { page } from 'vitest/browser';\n\n      beforeAll(() => {\n        document.body.innerHTML = 'Hello Vitest!';\n      });\n  \n      test('awaited', async () => {\n        const element = page.getByText(\"Hello Vitest!\");\n\n        await expect.element(element).toBeInTheDocument();\n      })\n\n      test('not awaited', () => {\n        const element = page.getByText(\"Hello Vitest!\");\n\n        expect.element(element).toBeInTheDocument();\n      })\n      `,\n  }, {\n    projects: [\n      {\n        test: {\n          name: 'browser',\n          browser: {\n            enabled: true,\n            headless: true,\n            provider: playwright(),\n            instances: [\n              { browser: 'chromium' },\n            ],\n          },\n        },\n      },\n    ],\n  })\n\n  expect(stderr).toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/browser/specs/filter.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { instances, runBrowserTests } from './utils'\n\ntest('filter', async () => {\n  const { stderr, stdout } = await runBrowserTests({\n    testNamePattern: 'basic 2',\n    reporters: ['verbose'],\n  }, ['test/basic.test.ts'])\n\n  expect(stderr).toBe('')\n  instances.forEach(({ browser }) => {\n    expect(stdout).toReportPassedTest('test/basic.test.ts > basic 2', browser)\n  })\n  expect(stdout).toContain(`Test Files  ${instances.length} passed`)\n  expect(stdout).toContain(`Tests  ${instances.length} passed | ${instances.length * 3} skipped`)\n})\n"
  },
  {
    "path": "test/browser/specs/fix-4686.test.ts",
    "content": "// fix #4686\n\nimport { expect, test } from 'vitest'\nimport { instances, runBrowserTests } from './utils'\n\ntest('tests run in presence of config.base', async () => {\n  const { stderr, stdout } = await runBrowserTests(\n    {\n      config: './vitest.config-basepath.mts',\n    },\n    ['test/basic.test.ts'],\n  )\n\n  expect(stderr).toBe('')\n  expect(stdout).toReportPassedTest('test/basic.test.ts', instances)\n})\n"
  },
  {
    "path": "test/browser/specs/insecure-context.test.ts",
    "content": "import os from 'node:os'\nimport { expect, test } from 'vitest'\nimport { instances, runBrowserTests } from './utils'\n\n// server.host = os.hostname // doesnt work on mac, therefore the test is only run on linux\ntest.runIf(os.platform() === 'linux')('server-host check dynamic import at insecure context', async () => {\n  const { stdout, stderr } = await runBrowserTests({\n    root: './fixtures/insecure-context',\n  })\n\n  expect(stderr).toBe('')\n  expect(stdout).toReportSummaryTestFiles({ passed: instances.length })\n})\n"
  },
  {
    "path": "test/browser/specs/inspect.test.ts",
    "content": "import type { InspectorNotification } from 'node:inspector'\nimport { expect, test, vi } from 'vitest'\nimport WebSocket from 'ws'\n\nimport { runVitestCli } from '../../test-utils'\n\ntype Message = Partial<InspectorNotification<any>>\n\nconst REMOTE_DEBUG_URL = '127.0.0.1:9123'\n\ntest.each(['', 'with workspace'])('--inspect-brk stops at test file %s', async (isWorkspace) => {\n  const options = ['--root', 'fixtures/inspect', '--no-file-parallelism', '--inspect-brk', REMOTE_DEBUG_URL]\n\n  if (isWorkspace) {\n    options.push('--config')\n    options.push('vitest.config.with-workspace.ts')\n  }\n\n  const { vitest, waitForClose } = await runVitestCli(...options)\n\n  await vitest.waitForStdout(`Debugger listening on ws://${REMOTE_DEBUG_URL}`)\n\n  const url = await vi.waitFor(() => fetch(`http://${REMOTE_DEBUG_URL}/json/list`)\n    .then(response => response.json())\n    .then(json => json[0].webSocketDebuggerUrl), { timeout: 30_000 })\n\n  const { receive, send } = await createChannel(url)\n\n  const paused = receive('Debugger.paused')\n  send({ method: 'Debugger.enable' })\n  send({ method: 'Runtime.enable' })\n\n  await receive('Runtime.executionContextCreated')\n  send({ method: 'Runtime.runIfWaitingForDebugger' })\n\n  const { params } = await paused\n  const scriptId = params.callFrames[0].functionLocation.scriptId\n\n  // Verify that debugger paused on test file\n  const { result } = await send({ method: 'Debugger.getScriptSource', params: { scriptId } })\n\n  expect(result.scriptSource).toContain('test(\"sum\", () => {')\n  expect(result.scriptSource).toContain('expect(1 + 1).toBe(2)')\n\n  send({ method: 'Debugger.resume' })\n\n  await vitest.waitForStdout('Test Files  1 passed (1)')\n  await waitForClose()\n}, 60_000)\n\nasync function createChannel(url: string) {\n  const ws = new WebSocket(url)\n\n  let id = 1\n  let listeners = []\n\n  ws.onmessage = (message) => {\n    const response = JSON.parse(message.data.toString())\n    listeners.forEach(listener => listener(response))\n  }\n\n  async function receive(methodOrId?: string | { id: number }): Promise<Message> {\n    const { promise, resolve, reject } = withResolvers()\n    listeners.push(listener)\n    ws.onerror = reject\n\n    function listener(message) {\n      const filter = typeof methodOrId === 'string' ? { method: methodOrId } : { id: methodOrId.id }\n\n      const methodMatch = message.method && message.method === filter.method\n      const idMatch = message.id && message.id === filter.id\n\n      if (methodMatch || idMatch) {\n        resolve(message)\n        listeners = listeners.filter(l => l !== listener)\n        ws.onerror = undefined\n      }\n      else if (!filter.id && !filter.method) {\n        resolve(message)\n      }\n    }\n\n    return promise\n  }\n\n  async function send(message: Message): Promise<any> {\n    const currentId = id++\n    const json = JSON.stringify({ ...message, id: currentId })\n\n    const receiver = receive({ id: currentId })\n    ws.send(json)\n\n    return receiver\n  }\n\n  await new Promise((resolve, reject) => {\n    ws.onerror = reject\n    ws.on('open', resolve)\n  })\n\n  return { receive, send }\n}\n\nfunction withResolvers() {\n  let reject: (error: unknown) => void\n  let resolve: (response: Message) => void\n\n  const promise: Promise<Message> = new Promise((...args) => {\n    [resolve, reject] = args\n  })\n\n  return { promise, resolve, reject }\n}\n"
  },
  {
    "path": "test/browser/specs/locators.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { instances, runBrowserTests } from './utils'\n\ntest('locators work correctly', async () => {\n  const { stderr, stdout } = await runBrowserTests({\n    root: './fixtures/locators',\n    reporters: [\n      ['verbose', { isTTY: false }],\n    ],\n  })\n\n  expect(stderr).toReportNoErrors()\n\n  instances.forEach(({ browser }) => {\n    expect(stdout).toReportPassedTest('blog.test.tsx', browser)\n    expect(stdout).toReportPassedTest('query.test.ts', browser)\n  })\n\n  const COUNT_TEST_FILES = 2\n  const COUNT_TESTS_OVERALL = 14\n\n  expect(stdout).toReportSummaryTestFiles({ passed: instances.length * COUNT_TEST_FILES })\n  expect(stdout).toReportSummaryTests({ passed: instances.length * COUNT_TESTS_OVERALL })\n})\n\ntest('custom locators work', async () => {\n  const { stderr, stdout } = await runBrowserTests({\n    root: './fixtures/locators-custom',\n    reporters: [['verbose', { isTTY: false }]],\n  })\n\n  expect(stderr).toReportNoErrors()\n\n  instances.forEach(({ browser }) => {\n    expect(stdout).toReportPassedTest('basic.test.tsx', browser)\n  })\n\n  const COUNT_TEST_FILES = 1\n  const COUNT_TESTS_OVERALL = 5\n\n  expect(stdout).toReportSummaryTestFiles({ passed: instances.length * COUNT_TEST_FILES })\n  expect(stdout).toReportSummaryTests({ passed: instances.length * COUNT_TESTS_OVERALL })\n})\n"
  },
  {
    "path": "test/browser/specs/mocking.test.ts",
    "content": "import { expect, onTestFailed, onTestFinished, test } from 'vitest'\nimport { editFile, runVitest } from '../../test-utils'\nimport { instances } from '../settings'\n\n// TODO: investigate `isolate: false` tests.\n// Doesn't seem like we can run things in parallel if there are mocks\ntest.each([true/* , false */])('mocking works correctly - isolated %s', async (isolate) => {\n  const result = await runVitest({\n    root: 'fixtures/mocking',\n    isolate,\n  })\n\n  onTestFailed(() => {\n    console.error(result.stdout)\n    console.error(result.stderr)\n  })\n\n  expect(result.stderr).toReportNoErrors()\n\n  instances.forEach(({ browser }) => {\n    expect(result.stdout).toReportPassedTest('automocked.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('mocked-__mocks__.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('mocked-factory.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('mocked-factory-hoisted.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('not-mocked.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('mocked-nested.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('not-mocked-nested.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('import-actual-in-mock.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('import-actual-query.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('import-mock.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('mocked-do-mock-factory.test.ts', browser)\n    expect(result.stdout).toReportPassedTest('import-actual-dep.test.ts', browser)\n  })\n\n  expect(result.exitCode).toBe(0)\n})\n\ntest('mocking dependency correctly invalidates it on rerun', async () => {\n  const { vitest, ctx } = await runVitest({\n    root: 'fixtures/mocking-watch',\n    watch: true,\n  })\n  onTestFinished(async () => {\n    await ctx.close()\n  })\n\n  await vitest.waitForStdout('Waiting for file changes...')\n\n  expect(vitest.stderr).toReportNoErrors()\n\n  instances.forEach(({ browser }) => {\n    expect(vitest.stdout).toReportPassedTest('1_mocked-on-watch-change.test.ts', browser)\n    expect(vitest.stdout).toReportPassedTest('2_not-mocked-import.test.ts', browser)\n  })\n\n  vitest.resetOutput()\n  editFile('./fixtures/mocking-watch/1_mocked-on-watch-change.test.ts', content => `${content}\\n`)\n\n  await vitest.waitForStdout('Waiting for file changes...')\n\n  expect(vitest.stderr).toReportNoErrors()\n\n  instances.forEach(({ browser }) => {\n    expect(vitest.stdout).toReportPassedTest('1_mocked-on-watch-change.test.ts', browser)\n    expect(vitest.stdout).not.toReportPassedTest('2_not-mocked-import.test.ts', browser)\n  })\n})\n\ntest('mocking out of root', async () => {\n  const { vitest, ctx } = await runVitest({\n    root: 'fixtures/mocking-out-of-root/project1',\n  })\n  onTestFinished(async () => {\n    await ctx.close()\n  })\n  expect(vitest.stderr).toReportNoErrors()\n  instances.forEach(({ browser }) => {\n    expect(vitest.stdout).toReportPassedTest('basic.test.js', browser)\n  })\n})\n"
  },
  {
    "path": "test/browser/specs/multiple-different-configs.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { provider } from '../settings'\nimport { runBrowserTests } from './utils'\n\ntest.runIf(provider.name === 'playwright')('[playwright] runs multiple different configurations correctly', async () => {\n  const { stdout, exitCode, stderr } = await runBrowserTests({\n    root: './fixtures/multiple-different-configs',\n  })\n\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n  expect(stdout).toContain('[chromium] HTML_INJECTED_VAR is true')\n  expect(stdout).toContain('[firefox] HTML_INJECTED_VAR is undefined')\n})\n\ntest.runIf(provider.name === 'webdriverio')('[webdriverio] runs multiple different configurations correctly', async () => {\n  const { stdout, exitCode, stderr } = await runBrowserTests({\n    root: './fixtures/multiple-different-configs',\n  })\n\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n  expect(stdout).toContain('[chromium] HTML_INJECTED_VAR is true')\n  expect(stdout).toContain('[firefox] HTML_INJECTED_VAR is undefined')\n})\n"
  },
  {
    "path": "test/browser/specs/playwright-connect.test.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { playwright } from '@vitest/browser-playwright'\nimport { x } from 'tinyexec'\nimport { expect, test } from 'vitest'\nimport { Cli } from '../../test-utils/cli'\nimport { provider } from '../settings'\nimport { runBrowserTests } from './utils'\n\ntest.runIf(provider.name === 'playwright')('[playwright] runs in connect mode', async ({ onTestFinished }) => {\n  const cliPath = fileURLToPath(new URL('./cli.js', import.meta.resolve('@playwright/test')))\n  const subprocess = x(process.execPath, [cliPath, 'run-server', '--port', '9898']).process\n  const cli = new Cli({\n    stdin: subprocess.stdin,\n    stdout: subprocess.stdout,\n    stderr: subprocess.stderr,\n  })\n  let setDone: (value?: unknown) => void\n  const isDone = new Promise(resolve => (setDone = resolve))\n  subprocess.on('exit', () => setDone())\n  onTestFinished(async () => {\n    subprocess.kill('SIGILL')\n    await isDone\n  })\n\n  await cli.waitForStdout('Listening on ws://localhost:9898')\n\n  const result = await runBrowserTests({\n    root: './fixtures/playwright-connect',\n    browser: {\n      instances: [\n        {\n          browser: 'chromium',\n          name: 'chromium',\n          provider: playwright({\n            connectOptions: {\n              wsEndpoint: 'ws://localhost:9898',\n            },\n            launchOptions: {\n              args: [`--user-agent=VitestLaunchOptionsTester`],\n            },\n          }),\n        },\n      ],\n    },\n  }, ['basic.test.js'])\n\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"[playwright] Run basic test in browser via connect mode\": \"passed\",\n        \"[playwright] Run browser-only test in browser via connect mode\": \"passed\",\n        \"[playwright] applies launch options from connect header\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/browser/specs/playwright-trace-mark.test.ts",
    "content": "import { readdirSync, rmSync } from 'node:fs'\nimport path from 'node:path'\nimport { stripVTControlCharacters } from 'node:util'\nimport { resolve } from 'pathe'\nimport { afterEach, describe, expect, test } from 'vitest'\nimport { rolldownVersion } from 'vitest/node'\nimport * as yauzl from 'yauzl'\nimport { buildTestProjectTree } from '../../test-utils'\nimport { instances, provider, runBrowserTests } from './utils'\n\nconst tracesFolder = resolve(import.meta.dirname, '../fixtures/trace-mark/__traces__')\nconst basicTestTracesFolder = resolve(tracesFolder, 'basic.test.ts')\n\ndescribe.runIf(provider.name === 'playwright')('playwright trace marks', () => {\n  afterEach(() => {\n    rmSync(tracesFolder, { recursive: true, force: true })\n  })\n\n  test('vitest mark is present in zipped trace events', async () => {\n    const { results, ctx } = await runBrowserTests({\n      root: './fixtures/trace-mark',\n      browser: {\n        trace: {\n          mode: 'on',\n          screenshots: false, // makes it lighter\n        },\n      },\n    })\n    const projectTree = buildTestProjectTree(results, (testCase) => {\n      const result = testCase.result()\n      return result.state === 'failed'\n        ? result.errors.map(e => stripVTControlCharacters(e.message))\n        : result.state\n    })\n    expect(Object.keys(projectTree).sort()).toEqual(instances.map(i => i.browser).sort())\n\n    for (const [name, tree] of Object.entries(projectTree)) {\n      expect.soft(tree).toMatchInlineSnapshot(`\n        {\n          \"basic.test.ts\": {\n            \"click\": \"passed\",\n            \"expect.element fail\": [\n              \"expect(element).toHaveTextContent()\n\n        Expected element to have text content:\n          World\n        Received:\n          Hello\",\n            ],\n            \"expect.element pass\": \"passed\",\n            \"failure\": [\n              \"Test failure\",\n            ],\n            \"helper\": \"passed\",\n            \"locator.mark\": \"passed\",\n            \"mark group\": \"passed\",\n            \"page.mark\": \"passed\",\n            \"stack\": \"passed\",\n          },\n        }\n      `)\n\n      const traceFiles = readdirSync(basicTestTracesFolder)\n        .filter(file => file.startsWith(`${name}-`) && file.endsWith('.trace.zip'))\n        .sort()\n      expect.soft(traceFiles).toEqual([\n        expect.stringContaining('click'),\n        expect.stringContaining('expect-element-fail'),\n        expect.stringContaining('expect-element-pass'),\n        expect.stringContaining('failure'),\n        expect.stringContaining('helper'),\n        expect.stringContaining('locator-mark'),\n        expect.stringContaining('mark-group'),\n        expect.stringContaining('page-mark'),\n        expect.stringContaining('stack'),\n      ])\n\n      function formatStack(event: any) {\n        return event.stack\n          ?.map(\n            (frame: any) =>\n              `${path.relative(ctx.config.root, frame.file)}:${frame.line}:${frame.column}`,\n          )\n          .join('\\n')\n      }\n\n      for (const traceFile of traceFiles) {\n        const zipPath = resolve(basicTestTracesFolder, traceFile)\n        const parsed = await readTraceZip(zipPath)\n        const events = parsed.events.filter(event => event.type === 'before')\n\n        if (traceFile.includes('locator-mark')) {\n          expect(events).toEqual(\n            expect.arrayContaining([\n              expect.objectContaining({\n                method: 'tracingGroup',\n                title: 'button rendered - locator',\n              }),\n              expect.objectContaining({\n                method: 'expect',\n                params: expect.objectContaining({\n                  selector: expect.stringContaining(`internal:describe=\"getByRole('button')`),\n                }),\n              }),\n            ]),\n          )\n          const markerEvent = events.find(e => e.title === 'button rendered - locator')\n          const formattedFrame = formatStack(markerEvent)\n          if (name === 'webkit') {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:10:38\"`)\n          }\n          else {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:10:33\"`)\n          }\n        }\n\n        if (traceFile.includes('page-mark') && !traceFile.includes('custom-stack')) {\n          expect(events).toEqual(\n            expect.arrayContaining([\n              expect.objectContaining({\n                method: 'tracingGroup',\n                title: 'button rendered - page',\n              }),\n              expect.objectContaining({\n                method: 'evaluateExpression',\n              }),\n            ]),\n          )\n          const markerEvent = events.find(e => e.title === 'button rendered - page')\n          const formattedFrame = formatStack(markerEvent)\n          if (name === 'webkit') {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:15:18\"`)\n          }\n          else {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:15:13\"`)\n          }\n        }\n\n        if (traceFile.includes('expect-element-pass')) {\n          expect(events).toEqual(\n            expect.arrayContaining([\n              expect.objectContaining({\n                method: 'tracingGroup',\n                title: 'expect.element().toHaveTextContent',\n              }),\n              expect.objectContaining({\n                method: 'expect',\n                params: expect.objectContaining({\n                  selector: expect.stringContaining(`internal:describe=\"getByRole('button')`),\n                }),\n              }),\n            ]),\n          )\n          const markerEvent = events.find(e => e.title === 'expect.element().toHaveTextContent')\n          const formattedFrame = formatStack(markerEvent)\n          if (name === 'webkit') {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:20:23\"`)\n          }\n          else {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:20:15\"`)\n          }\n        }\n\n        if (traceFile.includes('expect-element-fail')) {\n          expect(events).toEqual(\n            expect.arrayContaining([\n              expect.objectContaining({\n                method: 'tracingGroup',\n                title: 'button rendered',\n              }),\n              expect.objectContaining({\n                method: 'tracingGroup',\n                title: 'expect.element().toHaveTextContent [ERROR]',\n              }),\n              expect.objectContaining({\n                method: 'expect',\n                params: expect.objectContaining({\n                  selector: expect.stringContaining(`internal:describe=\"getByRole('button')`),\n                }),\n              }),\n            ]),\n          )\n          const markerEvent = events.find(e => e.title === 'expect.element().toHaveTextContent [ERROR]')\n          const formattedFrame = formatStack(markerEvent)\n          if (name === 'webkit') {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:26:23\"`)\n          }\n          else {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:26:15\"`)\n          }\n        }\n\n        if (traceFile.includes('failure')) {\n          const markerEvent = events.find(e => e.title === 'onAfterRetryTask [fail]')\n          const formattedFrame = formatStack(markerEvent)\n          if (name === 'webkit') {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:31:18\"`)\n          }\n          else {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:31:8\"`)\n          }\n        }\n\n        if (traceFile.includes('click')) {\n          expect(events).toEqual(\n            expect.arrayContaining([\n              // vitest command group (with source)\n              expect.objectContaining({\n                method: 'tracingGroup',\n                title: '__vitest_click',\n              }),\n              // playwright action (without source)\n              expect.objectContaining({\n                method: 'click',\n                params: expect.objectContaining({\n                  selector: expect.stringContaining(`internal:describe=\"getByRole('button')`),\n                }),\n              }),\n            ]),\n          )\n          const markerEvent = events.find(e => e.title === '__vitest_click')\n          const formattedFrame = formatStack(markerEvent)\n          if (name === 'webkit') {\n            if (rolldownVersion) {\n              expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:36:33\"`)\n            }\n            else {\n              expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:36:39\"`)\n            }\n          }\n          else {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:36:33\"`)\n          }\n        }\n\n        if (traceFile.includes('helper')) {\n          expect(events).toEqual(\n            expect.arrayContaining([\n              expect.objectContaining({\n                title: 'render helper',\n              }),\n            ]),\n          )\n          const markerEvent = events.find(e => e.title === 'render helper')\n          const formattedFrame = formatStack(markerEvent)\n          if (name === 'webkit') {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:45:17\"`)\n          }\n          else {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:45:8\"`)\n          }\n        }\n\n        if (traceFile.includes('stack')) {\n          expect(events).toEqual(\n            expect.arrayContaining([\n              expect.objectContaining({\n                title: 'button rendered - stack',\n              }),\n            ]),\n          )\n          const markerEvent = events.find(e => e.title === 'button rendered - stack')\n          const formattedFrame = formatStack(markerEvent)\n          if (name === 'webkit') {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:50:26\"`)\n          }\n          else {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:50:16\"`)\n          }\n        }\n\n        if (traceFile.includes('mark-group')) {\n          expect(events).toEqual(\n            expect.arrayContaining([\n              expect.objectContaining({\n                title: 'render group',\n              }),\n            ]),\n          )\n          const markerEvent = events.find(e => e.title === 'render group')\n          const formattedFrame = formatStack(markerEvent)\n          if (name === 'webkit') {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:55:18\"`)\n          }\n          else {\n            expect(formattedFrame).toMatchInlineSnapshot(`\"basic.test.ts:55:13\"`)\n          }\n        }\n      }\n    }\n  })\n})\n\nasync function readTraceZip(zipPath: string): Promise<{ entries: string[]; events: any[] }> {\n  const zipFile = new ZipFile(zipPath)\n  try {\n    const entries = await zipFile.entries()\n    const traceText = (await zipFile.read('trace.trace')).toString('utf-8')\n    const events = traceText\n      .split('\\n')\n      .filter(Boolean)\n      .map((line) => {\n        return JSON.parse(line)\n      })\n    return { entries, events }\n  }\n  finally {\n    zipFile.close()\n  }\n}\n\n// https://github.com/microsoft/playwright/blob/cd36dab6ecc7f4b3adeec333e55f9ac03711a9b1/packages/playwright-core/src/server/utils/zipFile.ts#L21\nclass ZipFile {\n  private readonly fileName: string\n  private zipFile?: yauzl.ZipFile\n  private readonly openedPromise: Promise<void>\n  private readonly entriesMap = new Map<string, yauzl.Entry>()\n\n  constructor(fileName: string) {\n    this.fileName = fileName\n    this.openedPromise = this.open()\n  }\n\n  private async open(): Promise<void> {\n    this.zipFile = await new Promise<yauzl.ZipFile>((resolve, reject) => {\n      yauzl.open(this.fileName, { lazyEntries: true, autoClose: false }, (error, zipFile) => {\n        if (error || !zipFile) {\n          reject(error || new Error(`Cannot open zip: ${this.fileName}`))\n          return\n        }\n        resolve(zipFile)\n      })\n    })\n\n    await new Promise<void>((resolve, reject) => {\n      this.zipFile!.readEntry()\n      this.zipFile!.on('entry', (entry) => {\n        this.entriesMap.set(entry.fileName, entry)\n        this.zipFile!.readEntry()\n      })\n      this.zipFile!.on('end', resolve)\n      this.zipFile!.on('error', reject)\n    })\n  }\n\n  async entries(): Promise<string[]> {\n    await this.openedPromise\n    return [...this.entriesMap.keys()]\n  }\n\n  async read(entryPath: string): Promise<Buffer> {\n    await this.openedPromise\n    const entry = this.entriesMap.get(entryPath)\n    if (!entry || !this.zipFile) {\n      throw new Error(`${entryPath} not found in file ${this.fileName}`)\n    }\n\n    return await new Promise((resolve, reject) => {\n      this.zipFile!.openReadStream(entry, (error, stream) => {\n        if (error || !stream) {\n          reject(error || new Error(`Cannot read ${entryPath} from file ${this.fileName}`))\n          return\n        }\n\n        const buffers: Buffer[] = []\n        stream.on('data', data => buffers.push(data))\n        stream.on('error', reject)\n        stream.on('end', () => resolve(Buffer.concat(buffers)))\n      })\n    })\n  }\n\n  close(): void {\n    this.zipFile?.close()\n  }\n}\n"
  },
  {
    "path": "test/browser/specs/playwright-trace.test.ts",
    "content": "import { readdirSync, rmSync } from 'node:fs'\nimport { resolve } from 'pathe'\nimport { afterEach, describe, expect, test } from 'vitest'\nimport { provider, runBrowserTests } from './utils'\n\nconst tracesFolder = resolve(import.meta.dirname, '../fixtures/trace-view/__traces__')\nconst basicTestTracesFolder = resolve(tracesFolder, 'basic.test.ts')\n\ndescribe.runIf(provider.name === 'playwright')('playwright tracing', () => {\n  afterEach(() => {\n    rmSync(tracesFolder, { recursive: true, force: true })\n  })\n\n  test('vitest generates trace files when running with `on`', async () => {\n    const { stderr, ctx } = await runBrowserTests({\n      root: './fixtures/trace-view',\n      browser: {\n        trace: 'on',\n      },\n      includeTaskLocation: true,\n    })\n\n    expect(stderr).toBe('')\n    expect(readdirSync(tracesFolder)).toEqual(['basic.test.ts'])\n    expect(readdirSync(basicTestTracesFolder).sort()).toMatchInlineSnapshot(`\n    [\n      \"chromium-a-single-test-0-0.trace.zip\",\n      \"chromium-nested-suite-suite-test-0-0.trace.zip\",\n      \"chromium-repeated-retried-tests-0-0.trace.zip\",\n      \"chromium-repeated-retried-tests-0-1.trace.zip\",\n      \"chromium-repeated-retried-tests-0-2.trace.zip\",\n      \"chromium-repeated-retried-tests-1-0.trace.zip\",\n      \"chromium-repeated-retried-tests-2-0.trace.zip\",\n      \"chromium-repeated-test-0-0.trace.zip\",\n      \"chromium-repeated-test-1-0.trace.zip\",\n      \"chromium-repeated-test-2-0.trace.zip\",\n      \"chromium-retried-test-0-0.trace.zip\",\n      \"chromium-retried-test-0-1.trace.zip\",\n      \"chromium-retried-test-0-2.trace.zip\",\n      \"firefox-a-single-test-0-0.trace.zip\",\n      \"firefox-nested-suite-suite-test-0-0.trace.zip\",\n      \"firefox-repeated-retried-tests-0-0.trace.zip\",\n      \"firefox-repeated-retried-tests-0-1.trace.zip\",\n      \"firefox-repeated-retried-tests-0-2.trace.zip\",\n      \"firefox-repeated-retried-tests-1-0.trace.zip\",\n      \"firefox-repeated-retried-tests-2-0.trace.zip\",\n      \"firefox-repeated-test-0-0.trace.zip\",\n      \"firefox-repeated-test-1-0.trace.zip\",\n      \"firefox-repeated-test-2-0.trace.zip\",\n      \"firefox-retried-test-0-0.trace.zip\",\n      \"firefox-retried-test-0-1.trace.zip\",\n      \"firefox-retried-test-0-2.trace.zip\",\n      \"webkit-a-single-test-0-0.trace.zip\",\n      \"webkit-nested-suite-suite-test-0-0.trace.zip\",\n      \"webkit-repeated-retried-tests-0-0.trace.zip\",\n      \"webkit-repeated-retried-tests-0-1.trace.zip\",\n      \"webkit-repeated-retried-tests-0-2.trace.zip\",\n      \"webkit-repeated-retried-tests-1-0.trace.zip\",\n      \"webkit-repeated-retried-tests-2-0.trace.zip\",\n      \"webkit-repeated-test-0-0.trace.zip\",\n      \"webkit-repeated-test-1-0.trace.zip\",\n      \"webkit-repeated-test-2-0.trace.zip\",\n      \"webkit-retried-test-0-0.trace.zip\",\n      \"webkit-retried-test-0-1.trace.zip\",\n      \"webkit-retried-test-0-2.trace.zip\",\n    ]\n  `)\n\n    // traces are also stored in attachments so they are visible in all reporters\n    const testModules = ctx.state.getTestModules()\n    expect(testModules).toHaveLength(3)\n    testModules.forEach((testModule) => {\n      for (const test of testModule.children.allTests()) {\n        if (test.result().state === 'skipped') {\n          continue\n        }\n\n        const annotations = test.annotations()\n        expect(annotations.length).toBeGreaterThan(0)\n\n        annotations.forEach((annotation) => {\n          expect(annotation.message).toContain('basic.test.ts/')\n          expect(annotation.type).toBe('traces')\n          expect(annotation.attachment!.contentType).toBe('application/octet-stream')\n          expect(annotation.location).toEqual({\n            file: test.module.moduleId,\n            line: test.location.line,\n            column: test.location.column,\n          })\n        })\n      }\n    })\n  })\n\n  test('vitest generates trace files when running with `on-all-retries`', async () => {\n    const { stderr } = await runBrowserTests({\n      root: './fixtures/trace-view',\n      browser: {\n        trace: 'on-all-retries',\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(readdirSync(tracesFolder)).toEqual(['basic.test.ts'])\n    expect(readdirSync(basicTestTracesFolder).sort()).toMatchInlineSnapshot(`\n    [\n      \"chromium-repeated-retried-tests-0-1.trace.zip\",\n      \"chromium-repeated-retried-tests-0-2.trace.zip\",\n      \"chromium-retried-test-0-1.trace.zip\",\n      \"chromium-retried-test-0-2.trace.zip\",\n      \"firefox-repeated-retried-tests-0-1.trace.zip\",\n      \"firefox-repeated-retried-tests-0-2.trace.zip\",\n      \"firefox-retried-test-0-1.trace.zip\",\n      \"firefox-retried-test-0-2.trace.zip\",\n      \"webkit-repeated-retried-tests-0-1.trace.zip\",\n      \"webkit-repeated-retried-tests-0-2.trace.zip\",\n      \"webkit-retried-test-0-1.trace.zip\",\n      \"webkit-retried-test-0-2.trace.zip\",\n    ]\n  `)\n  })\n\n  test('vitest generates trace files when running with `on-first-retries`', async () => {\n    const { stderr } = await runBrowserTests({\n      root: './fixtures/trace-view',\n      browser: {\n        trace: 'on-first-retry',\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(readdirSync(tracesFolder)).toEqual(['basic.test.ts'])\n    expect(readdirSync(basicTestTracesFolder).sort()).toMatchInlineSnapshot(`\n    [\n      \"chromium-repeated-retried-tests-0-1.trace.zip\",\n      \"chromium-retried-test-0-1.trace.zip\",\n      \"firefox-repeated-retried-tests-0-1.trace.zip\",\n      \"firefox-retried-test-0-1.trace.zip\",\n      \"webkit-repeated-retried-tests-0-1.trace.zip\",\n      \"webkit-retried-test-0-1.trace.zip\",\n    ]\n  `)\n  })\n\n  test('vitest generates trace files when running with `retain-on-failure`', async () => {\n    const { stderr } = await runBrowserTests({\n      root: './fixtures/trace-view',\n      include: ['./*.test.ts', './*.special.ts'],\n      browser: {\n        trace: 'retain-on-failure',\n      },\n    })\n\n    const failingTestTracesFolder = resolve(tracesFolder, 'failing.special.ts')\n\n    expect(readdirSync(tracesFolder)).toEqual([\n      'basic.test.ts',\n      'failing.special.ts',\n    ])\n    expect(readdirSync(basicTestTracesFolder).sort()).toMatchInlineSnapshot(`[]`)\n    expect(readdirSync(failingTestTracesFolder).sort()).toMatchInlineSnapshot(`\n    [\n      \"chromium-fail-0-0.trace.zip\",\n      \"chromium-repeated-fail-0-0.trace.zip\",\n      \"chromium-repeated-fail-1-0.trace.zip\",\n      \"chromium-repeated-fail-2-0.trace.zip\",\n      \"chromium-retried-fail-0-0.trace.zip\",\n      \"chromium-retried-fail-0-1.trace.zip\",\n      \"chromium-retried-fail-0-2.trace.zip\",\n      \"firefox-fail-0-0.trace.zip\",\n      \"firefox-repeated-fail-0-0.trace.zip\",\n      \"firefox-repeated-fail-1-0.trace.zip\",\n      \"firefox-repeated-fail-2-0.trace.zip\",\n      \"firefox-retried-fail-0-0.trace.zip\",\n      \"firefox-retried-fail-0-1.trace.zip\",\n      \"firefox-retried-fail-0-2.trace.zip\",\n      \"webkit-fail-0-0.trace.zip\",\n      \"webkit-repeated-fail-0-0.trace.zip\",\n      \"webkit-repeated-fail-1-0.trace.zip\",\n      \"webkit-repeated-fail-2-0.trace.zip\",\n      \"webkit-retried-fail-0-0.trace.zip\",\n      \"webkit-retried-fail-0-1.trace.zip\",\n      \"webkit-retried-fail-0-2.trace.zip\",\n    ]\n  `)\n\n    // the default reporter outputs attachments\n    expect(stderr).toContain('❯ traces')\n    expect(stderr).toContain('↳ __traces__/failing.special.ts/')\n  })\n})\n"
  },
  {
    "path": "test/browser/specs/project-name-encoding.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { instances, provider, runBrowserTests } from './utils'\n\ntest('runs tests correctly when project name contains special characters', async () => {\n  const { stderr, stdout, exitCode, ctx } = await runBrowserTests({\n    root: './fixtures/project-name-encoding',\n    browser: {\n      provider,\n      instances,\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n\n  const projectName = ctx.config.name\n\n  instances.forEach(({ browser }) => {\n    expect(stdout).toReportPassedTest('basic.test.ts', `${projectName} (${browser})`)\n  })\n})\n"
  },
  {
    "path": "test/browser/specs/runner.test.ts",
    "content": "import type { JsonTestResults, Vitest } from 'vitest/node'\nimport { readdirSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { beforeAll, describe, expect, onTestFailed, test } from 'vitest'\nimport { rolldownVersion } from 'vitest/node'\nimport { buildTestTree } from '../../test-utils'\nimport { instances, provider, runBrowserTests } from './utils'\n\nfunction noop() {}\n\ndescribe('running browser tests', async () => {\n  let stderr: string\n  let stdout: string\n  let browserResultJson: JsonTestResults\n  let passedTests: any[]\n  let failedTests: any[]\n  let vitest: Vitest\n  const events: string[] = []\n\n  beforeAll(async () => {\n    ({\n      stderr,\n      stdout,\n      ctx: vitest,\n    } = await runBrowserTests({\n      allowOnly: true,\n      reporters: [\n        {\n          onBrowserInit(project) {\n            events.push(`onBrowserInit ${project.name}`)\n          },\n        },\n        'json',\n        {\n          onInit: noop,\n          onTestRunStart: noop,\n          onTestModuleCollected: noop,\n          onTestRunEnd: noop,\n          onTestRemoved: noop,\n          onWatcherStart: noop,\n          onWatcherRerun: noop,\n          onServerRestart: noop,\n          onUserConsoleLog: noop,\n        },\n        'default',\n      ],\n    }))\n\n    const browserResult = await readFile('./browser.json', 'utf-8')\n    browserResultJson = JSON.parse(browserResult)\n    const getPassed = results => results.filter(result => result.status === 'passed' && !result.message)\n    const getFailed = results => results.filter(result => result.status === 'failed')\n    passedTests = getPassed(browserResultJson.testResults)\n    failedTests = getFailed(browserResultJson.testResults)\n  })\n\n  test('tests are actually running', () => {\n    expect(stderr).toBe('')\n\n    const testFiles = browserResultJson.testResults.map(t => t.name)\n\n    vitest.projects.forEach((project) => {\n      // the order is non-deterministic\n      expect(events).toContain(`onBrowserInit ${project.name}`)\n    })\n\n    // test files are optimized automatically (type-check-only files are excluded)\n    const runtimeTestFiles = testFiles.filter(f => !f.endsWith('.test-d.ts'))\n    expect(vitest.projects.map(p => p.browser?.vite.config.optimizeDeps.entries))\n      .toEqual(vitest.projects.map(() => expect.arrayContaining(runtimeTestFiles)))\n\n    const testFilesCount = readdirSync('./test')\n      .filter(n => n.includes('.test.') || n.includes('.test-d.'))\n      .length + 1 // 1 is in-source-test\n\n    expect(browserResultJson.testResults).toHaveLength(testFilesCount * instances.length)\n    expect(passedTests).toHaveLength(browserResultJson.testResults.length)\n    expect(failedTests).toHaveLength(0)\n  })\n\n  test('tags are collected', () => {\n    expect(vitest.config.tags).toEqual([\n      { name: 'e2e', priority: 10 },\n      { name: 'test', priority: 5 },\n      { name: 'browser', priority: 1 },\n    ])\n\n    const testModule = vitest.state.getTestModules().find(m => m.moduleId.includes('tags.test.ts'))\n    expect.assert(testModule)\n    expect(buildTestTree([testModule], t => t.tags)).toMatchInlineSnapshot(`\n      {\n        \"test/tags.test.ts\": {\n          \"suite 1\": {\n            \"suite 2\": {\n              \"test 2\": [\n                \"browser\",\n                \"e2e\",\n              ],\n            },\n            \"test 1\": [\n              \"browser\",\n              \"test\",\n            ],\n          },\n        },\n      }\n    `)\n  })\n\n  test('runs in-source tests', () => {\n    expect(stdout).toContain('src/actions.ts')\n    const actionsTest = passedTests.find(t => t.name.includes('/actions.ts'))\n    expect(actionsTest).toBeDefined()\n    expect(actionsTest.assertionResults).toHaveLength(1)\n  })\n\n  test('unsubscribes cancel listeners after run', async () => {\n    // should not throw birpc closing errors\n    await expect(vitest.cancelCurrentRun('keyboard-input')).resolves.not.toThrow()\n  })\n})\n\ndescribe('console logging tests', async () => {\n  let stderr: string\n  let stdout: string\n  beforeAll(async () => {\n    ({\n      stderr,\n      stdout,\n    } = await runBrowserTests({\n      root: './fixtures/print-logs',\n    }))\n  })\n\n  test('logs are redirected to stdout', () => {\n    expect(stdout).toContain('stdout | test/logs.test.ts > logging to stdout')\n    expect(stdout).toContain('hello from console.log')\n    expect(stdout).toContain('hello from console.info')\n    expect(stdout).toContain('hello from console.debug')\n    expect(stdout).toContain(`\n{\n  \"hello\": \"from dir\",\n}\n      `.trim())\n    expect(stdout).toContain(`\n{\n  \"hello\": \"from dirxml\",\n}\n      `.trim())\n    expect(stdout).toContain('dom <div />')\n    expect(stdout).toContain('default: 1')\n    expect(stdout).toContain('default: 2')\n    expect(stdout).toContain('default: 3')\n    expect(stdout).toContain('count: 1')\n    expect(stdout).toContain('count: 2')\n    expect(stdout).toContain('count: 3')\n    expect(stdout).toMatch(/default: [\\d.]+ ms/)\n    expect(stdout).toMatch(/time: [\\d.]+ ms/)\n    expect(stdout).toMatch(/\\[console-time-fake\\]: [\\d.]+ ms/)\n    expect(stdout).not.toContain('[console-time-fake]: 0 ms')\n    expect(stdout).toContain('hello from one')\n    expect(stdout).toContain(`hello from two {\n  \"hello\": \"object\",\n}`)\n  })\n\n  test('logs are redirected to stderr', () => {\n    expect(stderr).toContain('stderr | test/logs.test.ts > logging to stderr')\n    expect(stderr).toContain('hello from console.error')\n    expect(stderr).toContain('hello from console.warn')\n    expect(stderr).toContain('Timer \"invalid timeLog\" does not exist')\n    expect(stderr).toContain('Timer \"invalid timeEnd\" does not exist')\n    // safari logs the stack files with @https://...\n    expect(stderr).toMatch(/hello from console.trace\\s+(\\w+|@)/)\n  })\n\n  test(`logs have stack traces`, () => {\n    expect(stdout).toMatch(`\nlog with a stack\n ❯ test/logs.test.ts:58:10\n    `.trim())\n    expect(stderr).toMatch(`\nerror with a stack\n ❯ test/logs.test.ts:59:10\n    `.trim())\n    // console.trace processes the stack trace correctly\n    expect(stderr).toMatch('test/logs.test.ts:60:10')\n\n    if (instances.some(({ browser }) => browser === 'webkit')) {\n    // safari print stack trace in a different place\n      expect(stdout).toMatch(`\nlog with a stack\n ❯ test/logs.test.ts:58:14\n    `.trim())\n      expect(stderr).toMatch(`\nerror with a stack\n ❯ test/logs.test.ts:59:16\n    `.trim())\n      // console.trace processes the stack trace correctly\n      expect(stderr).toMatch('test/logs.test.ts:60:16')\n    }\n  })\n\n  test('popup apis should log a warning', () => {\n    expect(stderr).toContain('Vitest encountered a `alert(\"test\")`')\n    expect(stderr).toContain('Vitest encountered a `confirm(\"test\")`')\n    expect(stderr).toContain('Vitest encountered a `prompt(\"test\")`')\n  })\n})\n\ntest(`stack trace points to correct file in every browser when failed`, async () => {\n  expect.assertions(30)\n  const { stderr } = await runBrowserTests({\n    root: './fixtures/failing',\n    reporters: [\n      'default',\n      {\n        onTestCaseReady(testCase) {\n          if (testCase.name !== 'correctly fails and prints a diff') {\n            return\n          }\n          if (testCase.project.name === 'chromium' || testCase.project.name === 'chrome') {\n            expect(testCase.result().errors[0].stacks).toEqual([\n              {\n                line: 11,\n                column: 12,\n                file: testCase.module.moduleId,\n                method: '',\n              },\n            ])\n          }\n        },\n      },\n    ],\n  })\n\n  expect(stderr).toContain('expected 1 to be 2')\n  expect(stderr).toMatch(/- 2\\s+\\+ 1/)\n  // expect(stderr).toContain('Expected to be')\n  // expect(stderr).toContain('But got')\n  expect(stderr).toContain('Failure screenshot')\n  expect(stderr).toContain('__screenshots__/failing')\n\n  expect(stderr).toContain('Access denied to \"/inaccesible/path\".')\n\n  // depending on the browser it references either `.toBe()` or `expect()`\n  expect(stderr).toMatch(/failing.test.ts:11:(12|17)/)\n\n  // column is 18 in safari, 8 in others\n  expect(stderr).toMatch(/throwError src\\/error.ts:8:(18|8)/)\n\n  expect(stderr).toContain('The call was not awaited. This method is asynchronous and must be awaited; otherwise, the call will not start to avoid unhandled rejections.')\n  expect(stderr).toMatch(/failing.test.ts:19:(27|36)/)\n  expect(stderr).toMatch(/failing.test.ts:20:(27|33)/)\n  expect(stderr).toMatch(/failing.test.ts:21:(27|39)/)\n  expect(stderr).toMatch(/failing.test.ts:22:(12|17)/)\n  expect(stderr).toMatch(/failing.test.ts:23:(12|21)/)\n  expect(stderr).toMatch(/failing.test.ts:24:(12|17)/)\n  expect(stderr).toMatch(/failing.test.ts:25:(12|16)/)\n  expect(stderr).toMatch(/failing.test.ts:26:(12|18)/)\n  expect(stderr).toMatch(/failing.test.ts:27:(12|16)/)\n  expect(stderr).toMatch(/failing.test.ts:28:(12|24)/)\n  expect(stderr).toMatch(/failing.test.ts:29:(12|17)/)\n  expect(stderr).toMatch(/failing.test.ts:30:(12|19)/)\n  expect(stderr).toMatch(/failing.test.ts:31:(12|20)/)\n  expect(stderr).toMatch(/failing.test.ts:32:(12|18)/)\n  expect(stderr).toMatch(/failing.test.ts:33:(12|18)/)\n  expect(stderr).toMatch(/failing.test.ts:34:(12|26)/)\n  expect(stderr).toMatch(/failing.test.ts:35:(12|18)/)\n\n  expect(stderr).toMatch(/bundled-lib\\/src\\/b.js:2:(9|19)/)\n  expect(stderr).toMatch(/bundled-lib\\/src\\/index.js:5:(16|18)/)\n\n  // index() is called from a bundled file\n  expect(stderr).toMatch(/failing.test.ts:39:(2|8)/)\n\n  // \"not awaited but with then/catch/finally\" test should not produce warnings\n  expect(stderr).not.toMatch(/failing.test.ts:4[3-8]/)\n})\n\ntest('user-event', async () => {\n  const { stdout, stderr } = await runBrowserTests({\n    root: './fixtures/user-event',\n  })\n  if (provider.name !== 'webdriverio') {\n    expect(stderr).toBe('')\n  }\n  onTestFailed(() => console.error(stderr))\n  instances.forEach(({ browser }) => {\n    expect(stdout).toReportPassedTest('cleanup-retry.test.ts', browser)\n    expect(stdout).toReportPassedTest('cleanup1.test.ts', browser)\n    expect(stdout).toReportPassedTest('cleanup2.test.ts', browser)\n    expect(stdout).toReportPassedTest('keyboard.test.ts', browser)\n    expect(stdout).toReportPassedTest('clipboard.test.ts', browser)\n  })\n})\n\ntest('timeout settings', async () => {\n  const { stderr } = await runBrowserTests({\n    root: './fixtures/timeout',\n  })\n  expect(stderr).toContain('Matcher did not succeed in time.')\n  if (provider.name === 'playwright') {\n    expect(stderr).toContain('locator.click: Timeout 500ms exceeded.')\n    expect(stderr).toContain('locator.click: Timeout 345ms exceeded.')\n  }\n  if (provider.name === 'webdriverio') {\n    expect(stderr).toContain('Cannot find element with locator')\n  }\n})\n\ntest('viewport', async () => {\n  const { stdout, stderr } = await runBrowserTests({\n    root: './fixtures/viewport',\n  })\n  expect(stderr).toBe('')\n  instances.forEach(({ browser }) => {\n    expect(stdout).toReportPassedTest('basic.test.ts', browser)\n  })\n})\n\ntest('in-source tests don\\'t run when the module is imported by the test', async () => {\n  const { stderr, stdout } = await runBrowserTests({}, ['mocking.test.ts'])\n  expect(stderr).toBe('')\n\n  instances.forEach(({ browser }) => {\n    expect(stdout).toReportPassedTest('test/mocking.test.ts', browser)\n  })\n\n  // there is only one file with one test inside\n  // if this stops working, it will report twice as much tests\n  expect(stdout).toContain(`Test Files  ${instances.length} passed`)\n  expect(stdout).toContain(`Tests  ${instances.length} passed`)\n})\n\ntest('in-source tests run correctly when filtered', async () => {\n  const { stderr, stdout } = await runBrowserTests({}, ['actions.ts'])\n  expect(stderr).toBe('')\n\n  instances.forEach(({ browser }) => {\n    expect(stdout).toReportPassedTest('src/actions.ts', browser)\n  })\n\n  // there is only one file with one test inside\n  expect(stdout).toContain(`Test Files  ${instances.length} passed`)\n  expect(stdout).toContain(`Tests  ${instances.length} passed`)\n})\n\ntest('re-evaluate setupFiles on each test run even when isolate is false', async () => {\n  const { exitCode, stderr, stdout } = await runBrowserTests({\n    root: './fixtures/isolate-and-setup-file',\n  })\n\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n  instances.forEach(({ browser }) => {\n    expect(stdout).toReportPassedTest('a.test.ts', browser)\n    expect(stdout).toReportPassedTest('b.test.ts', browser)\n  })\n})\n\ntest.runIf(provider.name === 'playwright')('timeout hooks', async ({ onTestFailed }) => {\n  const { stderr } = await runBrowserTests({\n    root: './fixtures/timeout-hooks',\n  })\n\n  onTestFailed(() => {\n    console.error(stderr)\n  })\n\n  const lines = stderr.split('\\n')\n  const timeoutErrorsIndexes = []\n  lines.forEach((line, index) => {\n    if (line.includes('TimeoutError:')) {\n      timeoutErrorsIndexes.push(index)\n    }\n  })\n\n  const snapshot = timeoutErrorsIndexes.map((index) => {\n    return [\n      lines[index - 1],\n      lines[index].replace(/Timeout \\d+ms exceeded/, 'Timeout <ms> exceeded'),\n      lines[index + 4],\n    ].join('\\n')\n  }).sort().join('\\n\\n')\n\n  // rolldown has better source maps\n  if (rolldownVersion) {\n    expect(snapshot).toMatchInlineSnapshot(`\n      \" FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > afterAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:39:45\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > afterEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:23:45\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > beforeAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:31:45\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > beforeEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:15:45\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > click on non-existing element fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:6:33\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:62:47\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:70:47\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:48:47\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:54:47\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > afterAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:39:45\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > afterEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:23:45\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > beforeAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:31:45\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > beforeEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:15:45\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > click on non-existing element fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:6:33\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:62:47\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:70:47\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:48:47\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:54:47\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > afterAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:39:45\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > afterEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:23:45\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > beforeAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:31:45\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > beforeEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:15:45\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > click on non-existing element fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:6:33\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:62:47\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:70:47\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:48:47\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:54:47\"\n    `)\n  }\n  else {\n    expect(snapshot).toMatchInlineSnapshot(`\n      \" FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > afterAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:39:45\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > afterEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:23:45\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > beforeAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:31:45\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > beforeEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:15:45\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > click on non-existing element fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:6:33\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:62:47\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:70:47\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:48:47\n\n       FAIL  |chromium| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:54:47\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > afterAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:39:45\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > afterEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:23:45\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > beforeAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:31:45\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > beforeEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:15:45\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > click on non-existing element fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:6:33\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:62:47\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:70:47\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:48:47\n\n       FAIL  |firefox| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:54:47\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > afterAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:39:51\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > afterEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:23:51\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > beforeAll\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:31:51\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > beforeEach > skipped\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:15:51\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > click on non-existing element fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:6:39\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:62:53\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > onTestFailed > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:70:53\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:48:53\n\n       FAIL  |webkit| hooks-timeout.test.ts > timeouts are failing correctly > onTestFinished > fails global\n      TimeoutError: locator.click: Timeout <ms> exceeded.\n       ❯ hooks-timeout.test.ts:54:53\"\n    `)\n  }\n\n  // page.getByRole('code').click()\n  expect(stderr).toContain('locator.click: Timeout')\n  // playwright error is proxied from the server to the client and back correctly\n  expect(stderr).toContain('waiting for locator(\\'[data-vitest=\"true\"]\\').contentFrame().getByRole(\\'code\\')')\n  expect(stderr).toMatch(/hooks-timeout.test.ts:6:(33|39)/)\n  // await expect.element().toBeVisible()\n  expect(stderr).toContain('Cannot find element with locator: getByRole(\\'code\\')')\n  expect(stderr).toMatch(/hooks-timeout.test.ts:10:(49|61)/)\n}, 120_000 * 3)\n"
  },
  {
    "path": "test/browser/specs/server-url.test.ts",
    "content": "import { afterEach, expect, test } from 'vitest'\nimport { instances, runBrowserTests } from './utils'\n\nafterEach(() => {\n  delete process.env.TEST_HTTPS\n})\n\ntest('server-url http', async () => {\n  const { stderr, ctx } = await runBrowserTests({\n    root: './fixtures/server-url',\n    watch: true, // otherwise the browser is closed before we can get the url\n  })\n  const url = ctx?.projects[0].browser?.vite.resolvedUrls?.local[0]\n  expect(stderr).toBe('')\n  expect(url).toBeDefined()\n  expect(new URL(url).port).toBe('51133')\n})\n\ntest('server-url https', async () => {\n  process.env.TEST_HTTPS = '1'\n  const { stdout, stderr, ctx } = await runBrowserTests({\n    root: './fixtures/server-url',\n    watch: true, // otherwise the browser is closed before we can get the url\n  })\n  expect(stderr).toBe('')\n  const url = ctx?.projects[0].browser?.vite.resolvedUrls?.local[0]\n  expect(url).toBeDefined()\n  expect(new URL(url).port).toBe('51122')\n  expect(stdout).toReportSummaryTestFiles({ passed: instances.length })\n})\n"
  },
  {
    "path": "test/browser/specs/setup-file.test.ts",
    "content": "// fix https://github.com/vitest-dev/vitest/issues/6690\n\nimport { expect, test } from 'vitest'\nimport { instances, runBrowserTests } from './utils'\n\ntest('setup file imports the same modules', async () => {\n  const { stderr, stdout } = await runBrowserTests(\n    {\n      root: './fixtures/setup-file',\n    },\n  )\n\n  expect(stderr).toReportNoErrors()\n  expect(stdout).toReportPassedTest('module-equality.test.ts', instances)\n})\n"
  },
  {
    "path": "test/browser/specs/to-match-screenshot.test.ts",
    "content": "import type { ViteUserConfig } from 'vitest/config'\nimport type { TestFsStructure } from '../../test-utils'\nimport { platform } from 'node:os'\nimport { describe, expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\nimport { extractToMatchScreenshotPaths } from '../fixtures/expect-dom/utils'\nimport utilsContent from '../fixtures/expect-dom/utils?raw'\nimport { provider } from '../settings'\n\nconst testFilename = 'basic.test.ts'\nconst testName = 'screenshot-snapshot'\nconst bgColor = '#fff'\n\nconst testContent = /* ts */`\nimport { page, server } from 'vitest/browser'\nimport { describe, test } from 'vitest'\nimport { render } from './utils'\n\nconst dataTestId = 'inline-test'\n\ntest('${testName}', async ({ expect }) => {\n  render('<div data-testid=\"' + dataTestId + '\" style=\"background-color: ${bgColor};\">Inline Test</div>')\n\n  await expect(page.getByTestId(dataTestId)).toMatchScreenshot()\n})\n`\n\nconst browser = 'chromium'\n\nasync function runBrowserTests(\n  structure: TestFsStructure,\n  config: ViteUserConfig['test'] = {},\n) {\n  return runInlineTests({\n    ...structure,\n    'vitest.config.js': `\n      import { playwright } from '@vitest/browser-playwright'\n      export default {\n        test: {\n          browser: {\n            enabled: true,\n            screenshotFailures: false,\n            provider: playwright(),\n            headless: true,\n            instances: [{ browser: ${JSON.stringify(browser)} }],\n          },\n          reporters: ['verbose'],\n          ...${JSON.stringify(config)},\n        },\n      }`,\n  }, {\n    $cliOptions: {\n      watch: true,\n    },\n  })\n}\n\ndescribe.runIf(provider.name === 'playwright')('--watch', () => {\n  test(\n    'fails when creating a snapshot for the first time and does NOT update it afterwards',\n    async () => {\n      const { fs, stderr, vitest } = await runBrowserTests(\n        {\n          [testFilename]: testContent,\n          'utils.ts': utilsContent,\n        },\n        {\n          update: 'new',\n        },\n      )\n\n      const [referencePath] = extractToMatchScreenshotPaths(stderr, testName)\n\n      expect(stderr).toContain(`No existing reference screenshot found; a new one was created. Review it before running tests again.\\n\\nReference screenshot:\\n  ${referencePath}`)\n\n      const { atime: _1, atimeMs: _2, ...referenceStat } = fs.statFile(referencePath)\n\n      fs.editFile(testFilename, content => `${content}\\n`)\n\n      vitest.resetOutput()\n      await vitest.waitForStdout('Test Files  1 passed')\n\n      expect(vitest.stdout).toContain('✓ |chromium| basic.test.ts > screenshot-snapshot')\n\n      const { atime: _3, atimeMs: _4, ...newReferenceStat } = fs.statFile(referencePath)\n\n      expect(referenceStat).toEqual(newReferenceStat)\n    },\n  )\n\n  test(\n    'creates a reference and fails when changing the DOM content',\n    async () => {\n      const { fs, stderr, vitest } = await runBrowserTests(\n        {\n          [testFilename]: testContent,\n          'utils.ts': utilsContent,\n        },\n        {\n          update: 'new',\n        },\n      )\n\n      expect(stderr).toContain(`No existing reference screenshot found; a new one was created. Review it before running tests again.\\n\\nReference screenshot:`)\n\n      fs.editFile(testFilename, content => content.replace(bgColor, '#0ff'))\n\n      vitest.resetOutput()\n      await vitest.waitForStdout('Test Files  1 failed')\n\n      expect(vitest.stdout).toContain('× |chromium| basic.test.ts > screenshot-snapshot')\n      expect(vitest.stdout).toContain('Screenshot does not match the stored reference.')\n      expect(vitest.stdout).toMatch(/\\d+ pixels \\(ratio 0.\\d{2}\\) differ\\./)\n    },\n  )\n\n  describe('--update', () => {\n    test(\n      'creates snapshot and does NOT update it if reference matches',\n      async () => {\n        const { fs, stderr, vitest } = await runBrowserTests(\n          {\n            [testFilename]: testContent,\n            'utils.ts': utilsContent,\n          },\n          {\n            update: true,\n          },\n        )\n\n        expect(stderr).toMatchInlineSnapshot(`\"\"`)\n\n        const osPlatform = platform()\n        const referencePath = `__screenshots__/${testFilename}/${testName}-1-${browser}-${osPlatform}.png`\n        const referenceStat = fs.statFile(referencePath)\n\n        fs.editFile(testFilename, content => `${content}\\n`)\n\n        vitest.resetOutput()\n        await vitest.waitForStdout('Test Files  1 passed')\n\n        expect(vitest.stdout).toContain('✓ |chromium| basic.test.ts > screenshot-snapshot')\n\n        // only atime should change since reference should NOT be updated\n\n        const {\n          atime,\n          atimeMs,\n          ...diffs\n        } = fs.statFile(referencePath)\n\n        expect(referenceStat).toEqual(expect.objectContaining(diffs))\n\n        // win32 does not update `atime` by default\n        if (osPlatform === 'win32') {\n          expect(atime.getTime()).toEqual(referenceStat.atime.getTime())\n          expect(atimeMs).toEqual(referenceStat.atimeMs)\n        }\n        else {\n          expect(atime.getTime()).toBeGreaterThan(referenceStat.atime.getTime())\n          expect(atimeMs).toBeGreaterThan(referenceStat.atimeMs)\n        }\n      },\n    )\n\n    test(\n      'creates snapshot and updates it if reference mismatches',\n      async () => {\n        const { fs, stderr, vitest } = await runBrowserTests(\n          {\n            [testFilename]: testContent,\n            'utils.ts': utilsContent,\n          },\n          {\n            update: true,\n          },\n        )\n\n        expect(stderr).toMatchInlineSnapshot(`\"\"`)\n\n        const referencePath = `__screenshots__/${testFilename}/${testName}-1-${browser}-${platform()}.png`\n        const referenceStat = fs.statFile(referencePath)\n\n        fs.editFile(testFilename, content => content.replace(bgColor, '#000'))\n\n        vitest.resetOutput()\n        await vitest.waitForStdout('Test Files  1 passed')\n\n        expect(vitest.stdout).toContain('✓ |chromium| basic.test.ts > screenshot-snapshot')\n\n        // atime, ctime, mtime, and size should change since reference should be updated\n\n        const {\n          atime,\n          atimeMs,\n          ctime,\n          ctimeMs,\n          mtime,\n          mtimeMs,\n          size,\n          ...diffs\n        } = fs.statFile(referencePath)\n\n        expect(referenceStat).toEqual(expect.objectContaining(diffs))\n\n        expect(atime.getTime()).toBeGreaterThan(referenceStat.atime.getTime())\n        expect(ctime.getTime()).toBeGreaterThan(referenceStat.ctime.getTime())\n        expect(mtime.getTime()).toBeGreaterThan(referenceStat.mtime.getTime())\n\n        expect(atimeMs).toBeGreaterThan(referenceStat.atimeMs)\n        expect(ctimeMs).toBeGreaterThan(referenceStat.ctimeMs)\n        expect(mtimeMs).toBeGreaterThan(referenceStat.mtimeMs)\n      },\n    )\n  })\n})\n"
  },
  {
    "path": "test/browser/specs/update-snapshot.test.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { expect, onTestFailed, onTestFinished, test } from 'vitest'\nimport { createFile, editFile } from '../../test-utils'\nimport { instances, runBrowserTests } from './utils'\n\ntest('update snapshot', async () => {\n  // setup wrong snapshot value\n  const snapshotPath = './fixtures/update-snapshot/__snapshots__/basic.test.ts.snap'\n  editFile(snapshotPath, data => data.replace('`1`', '`2`'))\n  const basicFixturePath = './fixtures/update-snapshot/basic-fixture.ts'\n  const testPath = './fixtures/update-snapshot/basic.test.ts'\n  createFile(testPath, readFileSync(basicFixturePath, 'utf-8'))\n\n  // run vitest watch mode\n  const ctx = await runBrowserTests({\n    watch: true,\n    root: './fixtures/update-snapshot',\n    project: [instances[0].browser], // TODO 2024-12-11 Sheremet V.A. test with multiple browsers\n    reporters: ['default'], // use simple reporter to not pollute stdout\n    browser: { headless: true },\n  }, [], {\n    server: {\n      // ignore the watcher update\n      watch: null,\n    },\n  })\n  const { exitCode, ctx: vitest } = ctx\n  onTestFinished(() => vitest.close())\n  onTestFailed(() => {\n    console.error(ctx.stdout)\n    console.error(ctx.stderr)\n  })\n\n  // test fails\n  expect(exitCode).toBe(1)\n\n  const files = vitest.state.getFiles()\n  expect(files).toHaveLength(1)\n  expect(files[0].result.state).toBe('fail')\n\n  // updateSnapshot API to simulate \"u\" command\n  await vitest.updateSnapshot()\n\n  // verify snapshot value is updated\n  const snapshotData = readFileSync(snapshotPath, 'utf-8')\n  expect(snapshotData).toContain('`1`')\n\n  const testFile = readFileSync(testPath, 'utf-8')\n  expect(testFile).toContain('expect(fn).toMatchInlineSnapshot(`[MockFunction]`)')\n  expect(testFile).toMatchSnapshot()\n\n  // test passes\n  expect(vitest.state.getFiles()[0].result.state).toBe('pass')\n})\n"
  },
  {
    "path": "test/browser/specs/utils.ts",
    "content": "import type { UserConfig as ViteUserConfig } from 'vite'\nimport type { TestUserConfig } from 'vitest/node'\nimport type { RunVitestConfig, TestFsStructure, VitestRunnerCLIOptions } from '../../test-utils'\nimport { runInlineTests, runVitest } from '../../test-utils'\nimport { instances, provider } from '../settings'\n\nexport { instances, provider } from '../settings'\n\nexport async function runInlineBrowserTests(\n  structure: TestFsStructure,\n  config?: RunVitestConfig,\n  options?: VitestRunnerCLIOptions,\n) {\n  return runInlineTests(\n    structure,\n    {\n      watch: false,\n      reporters: 'none',\n      ...config,\n      browser: {\n        enabled: true,\n        provider,\n        instances,\n        headless: true,\n        ...config?.browser,\n      } as TestUserConfig['browser'],\n    },\n    options,\n  )\n}\n\nexport async function runBrowserTests(\n  config?: Omit<TestUserConfig, 'browser'> & { browser?: Partial<TestUserConfig['browser']> },\n  include?: string[],\n  viteOverrides?: Partial<ViteUserConfig>,\n  runnerOptions?: VitestRunnerCLIOptions,\n) {\n  const result = await runVitest({\n    watch: false,\n    reporters: 'none',\n    ...config,\n    browser: { headless: true, ...config?.browser },\n    $viteConfig: viteOverrides,\n  }, include, runnerOptions)\n\n  return { ...result, stderr: result.stderr.replace('Testing types with tsc and vue-tsc is an experimental feature.\\nBreaking changes might not follow SemVer, please pin Vitest\\'s version when using it.\\n', '') }\n}\n"
  },
  {
    "path": "test/browser/specs/viewport.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runBrowserTests } from './utils'\n\ntest('viewport', async () => {\n  const { stderr, ctx } = await runBrowserTests({\n    root: './fixtures/viewport',\n  })\n\n  expect(stderr).toBe('')\n  expect(\n    Object.fromEntries(\n      ctx.state.getFiles().map(f => [f.name, f.result.state]),\n    ),\n  ).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": \"pass\",\n    }\n  `)\n})\n"
  },
  {
    "path": "test/browser/specs/worker.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runBrowserTests } from './utils'\n\ntest('worker', async () => {\n  const { ctx, stderr } = await runBrowserTests({\n    root: './fixtures/worker',\n  })\n  expect(stderr).toBe('')\n  expect(Object.fromEntries(ctx.state.getFiles().map(f => [f.name, f.result.state]))).toMatchInlineSnapshot(`\n    {\n      \"src/basic.test.ts\": \"pass\",\n    }\n  `)\n})\n"
  },
  {
    "path": "test/browser/src/__mocks__/_calculator.ts",
    "content": "export function calculator() {\n  return 4\n}\n"
  },
  {
    "path": "test/browser/src/actions.ts",
    "content": "export function plus(a: number, b: number) {\n  return a + b\n}\n\nif (import.meta.vitest) {\n  const { test, expect } = import.meta.vitest\n\n  test('in-source plus works correctly', () => {\n    expect(plus(1, 2)).toBe(3)\n  })\n}\n"
  },
  {
    "path": "test/browser/src/blog-app/blog.tsx",
    "content": "import React from 'react'\n\nexport default function App() {\n  const [posts, setPosts] = React.useState(() => [\n    {\n      userId: 1,\n      id: 1,\n      title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',\n      body: 'quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto',\n    },\n    {\n      userId: 1,\n      id: 2,\n      title: 'qui est esse',\n      body: 'est rerum tempore vitae\\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\\nqui aperiam non debitis possimus qui neque nisi nulla',\n    },\n    {\n      userId: 1,\n      id: 3,\n      title: 'ea molestias quasi exercitationem repellat qui ipsa sit aut',\n      body: 'et iusto sed quo iure\\nvoluptatem occaecati omnis eligendi aut ad\\nvoluptatem doloribus vel accusantium quis pariatur\\nmolestiae porro eius odio et labore et velit aut',\n    },\n    {\n      userId: 1,\n      id: 4,\n      title: 'eum et est occaecati',\n      body: 'ullam et saepe reiciendis voluptatem adipisci\\nsit amet autem assumenda provident rerum culpa\\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\\nquis sunt voluptatem rerum illo velit',\n    },\n  ])\n\n  function removePost(index: number) {\n    setPosts(posts => posts.filter((_, i) => i !== index))\n  }\n\n  return (\n    <div>\n      <h1>Blog</h1>\n      <ul>\n        {posts.map((post, index) => (\n          <li key={post.id}>\n            <h2>{post.title}</h2>\n            <p>{post.body}</p>\n            <button onClick={() => removePost(index)}>Delete</button>\n          </li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n"
  },
  {
    "path": "test/browser/src/button.css",
    "content": ".wrapper {\n  padding: 12px;\n  font-family: Readex Pro,sans-serif;\n  font-size: large;\n  font-weight: bold;\n  text-align: center;\n}\n\n.node {\n  background-color: #3f3f3f;\n  border-radius: 12px;\n  height: 30px;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  color: white;\n}\n"
  },
  {
    "path": "test/browser/src/calculator.ts",
    "content": "import { plus } from './actions'\n\nexport function calculator(operation: 'plus', a: number, b: number) {\n  if (operation === 'plus') {\n    return plus(a, b)\n  }\n\n  throw new Error('unknown operation')\n}\n"
  },
  {
    "path": "test/browser/src/createNode.ts",
    "content": "export function createNode() {\n  const div = document.createElement('div')\n  div.className = 'node'\n  div.textContent = 'Hello World!'\n  return div\n}\n"
  },
  {
    "path": "test/browser/src/dynamic.ts",
    "content": "window.dispatchEvent(new CustomEvent('module:loaded'))\n\nexport {}\n"
  },
  {
    "path": "test/browser/src/env.ts",
    "content": "export function getAuthToken() {\n  return import.meta.env.AUTH_TOKEN\n}\n"
  },
  {
    "path": "test/browser/test/__snapshots__/custom/my_snapshot",
    "content": "my snapshot content"
  },
  {
    "path": "test/browser/test/__snapshots__/snapshot.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`snapshot 1`] = `1`;\n"
  },
  {
    "path": "test/browser/test/__snapshots__/utils.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`prints default document 1`] = `\"<body />\"`;\n\nexports[`prints default document 2`] = `\n\"<body>\n  <div>\n    <span>\n      hello\n    </span>\n  </div>\n</body>\"\n`;\n\nexports[`prints the element 1`] = `\n\"<body>\n  <div>\n    <span>\n      hello\n    </span>\n  </div>\n</body>\"\n`;\n\nexports[`prints the element with attributes 1`] = `\n\"<body>\n  <div>\n    <span\n      class=\"some-name\"\n      data-test-id=\"33\"\n      id=\"5\"\n    >\n      hello\n    </span>\n  </div>\n</body>\"\n`;\n\nexports[`should be able to opt out of shadow DOM content 1`] = `\n\"<body>\n  <div>\n    <no-shadow-root />\n  </div>\n</body>\"\n`;\n\nexports[`should handle DOM content bigger than maxLength 1`] = `\n\"<body>\n  <div>\n    <div>\n      <div … />\n    </div>\n  </div>\n</body>...\"\n`;\n\nexports[`should handle shadow DOM content 1`] = `\n\"<body>\n  <div>\n    <custom-element>\n      #shadow-root\n        <span\n          class=\"some-name\"\n          data-test-id=\"33\"\n          id=\"5\"\n        >\n          hello\n        </span>\n    </custom-element>\n  </div>\n</body>\"\n`;\n"
  },
  {
    "path": "test/browser/test/another.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('basic 3', async () => {\n  expect(globalThis.window).toBeDefined()\n})\n\nit('no process', () => {\n  expect(globalThis.process).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/test/basic.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('basic', async () => {\n  expect(globalThis.performance).toBeDefined()\n})\n\nit('basic 2', () => {\n  expect(globalThis.window).toBeDefined()\n})\n\nit.each([\n  ['x', true],\n  ['y', false],\n])('%s is x', (val, expectedResult) => {\n  expect(val === 'x').toBe(expectedResult)\n})\n"
  },
  {
    "path": "test/browser/test/cdp.test-d.ts",
    "content": "import { PlaywrightBrowserProvider } from '@vitest/browser-playwright'\nimport { expectTypeOf, test } from 'vitest'\nimport { cdp } from 'vitest/browser'\nimport { } from 'vitest/config'\n\ntest('server side cdp', async () => {\n  const session = await (new PlaywrightBrowserProvider('project' as any, {}).getCDPSession(''))\n\n  expectTypeOf(session).toHaveProperty('on')\n  expectTypeOf(session).toHaveProperty('off')\n  expectTypeOf(session).toHaveProperty('once')\n  expectTypeOf(session).toHaveProperty('send')\n  expectTypeOf(session).not.toHaveProperty('emit')\n\n  session.on('Profiler.preciseCoverageDeltaUpdate', (event) => {\n    expectTypeOf(event).toHaveProperty('result').items.toHaveProperty('functions').items.toHaveProperty('ranges').items.toHaveProperty('startOffset')\n  })\n\n  expectTypeOf(session.send('Profiler.startPreciseCoverage', {\n    allowTriggeredUpdates: true,\n    callCount: true,\n    detailed: true,\n  })).resolves.toHaveProperty('timestamp')\n\n  expectTypeOf(session.send).toBeCallableWith('Fetch.enable')\n\n  // @ts-expect-error -- not.toBeCallableWith() does not work\n  expectTypeOf(session.send).toBeCallableWith('Some.NonExisting.Command')\n})\n\ntest('client side cdps', async () => {\n  const session = cdp()\n\n  expectTypeOf(session).toHaveProperty('on')\n  expectTypeOf(session).toHaveProperty('off')\n  expectTypeOf(session).toHaveProperty('once')\n  expectTypeOf(session).toHaveProperty('send')\n  expectTypeOf(session).not.toHaveProperty('emit')\n\n  session.on('Profiler.preciseCoverageDeltaUpdate', (event) => {\n    expectTypeOf(event).toHaveProperty('result').items.toHaveProperty('functions').items.toHaveProperty('ranges').items.toHaveProperty('startOffset')\n  })\n\n  expectTypeOf(session.send('Profiler.startPreciseCoverage', {\n    allowTriggeredUpdates: true,\n    callCount: true,\n    detailed: true,\n  })).resolves.toHaveProperty('timestamp')\n\n  expectTypeOf(session.send).toBeCallableWith('Fetch.enable')\n\n  // @ts-expect-error -- not.toBeCallableWith() does not work\n  expectTypeOf(session.send).toBeCallableWith('Some.NonExisting.Command')\n})\n"
  },
  {
    "path": "test/browser/test/cdp.test.ts",
    "content": "import { describe, expect, it, onTestFinished, vi } from 'vitest'\nimport { cdp, server } from 'vitest/browser'\n\ndescribe.runIf(\n  server.provider === 'playwright' && server.browser === 'chromium',\n)('cdp in chromium browsers', () => {\n  it('cdp sends events correctly', async () => {\n    const messageAdded = vi.fn()\n\n    await cdp().send('Console.enable')\n\n    cdp().on('Console.messageAdded', messageAdded)\n\n    onTestFinished(async () => {\n      await cdp().send('Console.disable')\n    })\n\n    console.error('MESSAGE ADDED')\n\n    await vi.waitFor(() => {\n      expect(messageAdded).toHaveBeenCalledWith({\n        message: expect.objectContaining({\n          column: expect.any(Number),\n          text: 'MESSAGE ADDED',\n          source: 'console-api',\n          url: expect.any(String),\n        }),\n      })\n    })\n  })\n\n  it('cdp keyboard works correctly', async () => {\n    const input = document.createElement('input')\n    document.body.appendChild(input)\n    input.focus()\n\n    await cdp().send('Input.dispatchKeyEvent', {\n      type: 'keyDown',\n      text: 'a',\n    })\n    expect(input).toHaveValue('a')\n\n    await cdp().send('Input.insertText', {\n      text: 'some text',\n    })\n    expect(input).toHaveValue('asome text')\n  })\n\n  it('click events are fired correctly', async () => {\n    const clickEvent = vi.fn()\n    document.body.addEventListener('click', clickEvent)\n\n    const parent = window.top\n    const iframePosition = parent.document.querySelector('iframe').getBoundingClientRect()\n\n    await cdp().send('Input.dispatchMouseEvent', {\n      type: 'mousePressed',\n      x: iframePosition.x + 10,\n      y: iframePosition.y + 10,\n      button: 'left',\n      clickCount: 1,\n    })\n    await cdp().send('Input.dispatchMouseEvent', {\n      type: 'mouseReleased',\n      x: iframePosition.x + 10,\n      y: iframePosition.y + 10,\n      button: 'left',\n      clickCount: 1,\n    })\n\n    expect(clickEvent).toHaveBeenCalledOnce()\n  })\n})\n"
  },
  {
    "path": "test/browser/test/cjs-lib.test.ts",
    "content": "import cjsDefault, { a as cjsNamed } from '@vitest/cjs-lib'\nimport * as cjsNamespace from '@vitest/cjs-lib'\nimport { expect, test } from 'vitest'\n\ntest('cjs namespace import', () => {\n  expect(cjsNamespace).toEqual({\n    a: 'a',\n    b: 'b',\n    object: {\n      h: 'h',\n    },\n    default: {\n      a: 'a',\n      b: 'b',\n      object: {\n        h: 'h',\n      },\n    },\n  })\n})\n\ntest('cjs named import', () => {\n  expect(cjsNamed).toEqual('a')\n})\n\ntest('cjs default import not supported when slowHijackESM', () => {\n  expect(cjsDefault).toEqual({\n    a: 'a',\n    b: 'b',\n    object: {\n      h: 'h',\n    },\n  })\n})\n"
  },
  {
    "path": "test/browser/test/commands.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { server } from 'vitest/browser'\n\nconst { readFile, writeFile, removeFile, myCustomCommand } = server.commands\n\nit('can manipulate files', async () => {\n  const file = './test.txt'\n\n  try {\n    await readFile(file)\n    expect.unreachable()\n  }\n  catch (err) {\n    expect(err.message).toMatch(`ENOENT: no such file or directory, open`)\n    if (server.platform === 'win32') {\n      expect(err.message).toMatch('test\\\\browser\\\\test.txt')\n    }\n    else {\n      expect(err.message).toMatch('test/browser/test.txt')\n    }\n  }\n\n  await writeFile(file, 'hello world')\n  const content = await readFile(file)\n\n  expect(content).toBe('hello world')\n\n  await removeFile(file)\n\n  try {\n    await readFile(file)\n    expect.unreachable()\n  }\n  catch (err) {\n    expect(err.message).toMatch(`ENOENT: no such file or directory, open`)\n    if (server.platform === 'win32') {\n      expect(err.message).toMatch('test\\\\browser\\\\test.txt')\n    }\n    else {\n      expect(err.message).toMatch('test/browser/test.txt')\n    }\n  }\n})\n\nit('can run custom commands', async () => {\n  const result = await myCustomCommand('arg1', 'arg2')\n  expect(result).toEqual({\n    testPath: expect.stringMatching('test/browser/test/commands.test.ts'),\n    arg1: 'arg1',\n    arg2: 'arg2',\n  })\n})\n\ndeclare module 'vitest/browser' {\n  interface BrowserCommands {\n    myCustomCommand: (arg1: string, arg2: string) => Promise<{\n      testPath: string\n      arg1: string\n      arg2: string\n    }>\n\n    stripVTControlCharacters: (text: string) => Promise<string>\n    startTrace: () => Promise<void>\n    stopTrace: () => Promise<void>\n  }\n}\n"
  },
  {
    "path": "test/browser/test/dom.test.ts",
    "content": "import { createNode } from '#src/createNode'\nimport { afterAll, beforeEach, describe, expect, test } from 'vitest'\nimport { page, server } from 'vitest/browser'\nimport '../src/button.css'\n\nafterAll(() => {\n  document.body.removeAttribute('style')\n})\n\ndescribe('dom related activity', () => {\n  beforeEach(() => {\n    document.body.replaceChildren()\n  })\n\n  test('viewport works correctly', async () => {\n    await page.viewport(800, 600)\n    expect(window.innerWidth).toBe(800)\n    expect(window.innerHeight).toBe(600)\n  })\n\n  test('element doesn\\'t exist', async () => {\n    await expect.element(page.getByText('empty')).not.toBeInTheDocument()\n  })\n\n  test('renders div', async () => {\n    const wrapper = createWrapper()\n    const div = createNode()\n    wrapper.appendChild(div)\n\n    await expect.element(div).toHaveTextContent('Hello World!')\n    const screenshotPath = await page.screenshot({\n      element: wrapper,\n    })\n    expect(screenshotPath).toMatch(\n      /__screenshots__\\/dom.test.ts\\/dom-related-activity-renders-div-1.png/,\n    )\n\n    // test typing\n    if (0) {\n      await expect.element(div).toHaveClass('x', { exact: true })\n      await expect.element(div).toHaveClass('x', 'y')\n      await expect.element(div).toHaveClass('x', /y/)\n      await expect.element(div).toHaveClass(/x/, 'y')\n      await expect.element(div).toHaveClass('x', /y/, 'z')\n      await expect.element(div).toHaveClass(/x/, 'y', /z/)\n      // @ts-expect-error error\n      await expect.element(div).toHaveClass('x', { exact: 1234 })\n      // @ts-expect-error error\n      await expect.element(div).toHaveClass('x', 1234)\n    }\n  })\n\n  test('resolves base64 screenshot', async () => {\n    const wrapper = createWrapper()\n    const div = createNode()\n    wrapper.appendChild(div)\n\n    const { path, base64 } = await page.screenshot({\n      element: wrapper,\n      base64: true,\n    })\n    expect(path).toMatch(\n      /__screenshots__\\/dom.test.ts\\/dom-related-activity-resolves-base64-screenshot-1.png/,\n    )\n    expect(base64).toBeTypeOf('string')\n  })\n\n  test('doesn\\'t save base64', async () => {\n    const wrapper = createWrapper()\n    const div = createNode()\n    wrapper.appendChild(div)\n\n    const base64 = await page.screenshot({\n      element: wrapper,\n      save: false,\n    })\n    expect(base64).toBeTypeOf('string')\n    expect(base64).not.toContain('__screenshots__')\n    expect(base64).not.toContain('dom.test.ts')\n  })\n\n  test('shadow dom screenshot', async () => {\n    const wrapper = createWrapper()\n    const div = createNode()\n    wrapper.appendChild(div)\n\n    const shadow = div.attachShadow({ mode: 'open' })\n    const shadowDiv = createNode()\n    shadow.appendChild(shadowDiv)\n\n    const screenshotPath = await page.screenshot({\n      element: shadowDiv,\n    })\n    expect(screenshotPath).toMatch(\n      /__screenshots__\\/dom.test.ts\\/dom-related-activity-shadow-dom-screenshot-1.png/,\n    )\n  })\n\n  test('svg screenshot', async () => {\n    const wrapper = createWrapper()\n    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n    svg.setAttribute('width', '100')\n    svg.setAttribute('height', '100')\n    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')\n    rect.setAttribute('width', '100')\n    rect.setAttribute('height', '100')\n    rect.setAttribute('fill', 'red')\n    svg.appendChild(rect)\n    wrapper.appendChild(svg)\n\n    const screenshotPath = await page.screenshot({\n      element: svg,\n    })\n    expect(screenshotPath).toMatch(\n      /__screenshots__\\/dom.test.ts\\/dom-related-activity-svg-screenshot-1.png/,\n    )\n  })\n\n  test.runIf(server.provider === 'webdriverio')('shadow dom works with multiple elements', async () => {\n    const wrapper = createWrapper()\n    const div = createNode()\n    wrapper.appendChild(div)\n\n    const shadow = div.attachShadow({ mode: 'open' })\n    const shadowDiv1 = createNode()\n    shadowDiv1.role = 'tab'\n    const shadowDiv2 = createNode()\n    shadowDiv2.role = 'tab'\n    shadow.appendChild(shadowDiv1)\n    shadow.appendChild(shadowDiv2)\n\n    expect(\n      page.getByRole('tab').selector,\n      'there is only a single >>> in the selector',\n    ).toBe('>>>html > body > div > div > div, html > body > div > div > div')\n  })\n})\n\nfunction createWrapper() {\n  const wrapper = document.createElement('div')\n  wrapper.className = 'wrapper'\n  document.body.appendChild(wrapper)\n  wrapper.style.height = '200px'\n  wrapper.style.width = '200px'\n  return wrapper\n}\n"
  },
  {
    "path": "test/browser/test/dynamic-module.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\ntest('can await the end of the dynamic import', async () => {\n  const _promise = import('../src/dynamic')\n  const spy = vi.fn()\n  window.addEventListener('module:loaded', spy)\n  await vi.dynamicImportSettled()\n  expect(spy).toHaveBeenCalled()\n})\n"
  },
  {
    "path": "test/browser/test/env.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { getAuthToken } from '../src/env'\n\ntest('reads envs from .env file', () => {\n  expect(import.meta.env.VITE_TEST_ENV).toBe('local')\n})\n\ntest('can reassign env locally', () => {\n  import.meta.env.VITEST_ENV = 'TEST'\n  expect(import.meta.env.VITEST_ENV).toBe('TEST')\n})\n\ntest('can reassign env everywhere', () => {\n  import.meta.env.AUTH_TOKEN = '123'\n  expect(getAuthToken()).toBe('123')\n})\n\ntest('custom env', () => {\n  expect(import.meta.env.CUSTOM_ENV).toBe('foo')\n})\n\ntest('import.meta.env via define', () => {\n  expect(import.meta.env.DEFINE_CUSTOM_ENV).toBe('define-custom-env')\n})\n\ntest('ignores import.meta.env in string literals', () => {\n  expect('import.meta.env').toBe('import' + '.meta.env')\n})\n\ntest('define process and using import.meta.env together', () => {\n  const process = {}\n  expect(process).toMatchObject({})\n  expect(import.meta.env.MODE).toEqual('test')\n})\n\ntest('PROD, DEV, SSR should be boolean', () => {\n  expect(import.meta.env.PROD).toBe(false)\n  expect(import.meta.env.DEV).toBe(true)\n\n  expect(import.meta.env.SSR).toBe(false)\n\n  import.meta.env.SSR = true\n  expect(import.meta.env.SSR).toEqual(true)\n})\n"
  },
  {
    "path": "test/browser/test/expect-element.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { page } from 'vitest/browser'\n\n// element selector uses prettyDOM under the hood, which is an expensive call\n// that should not be called on each failed locator attempt to avoid memory leak:\n// https://github.com/vitest-dev/vitest/issues/7139\ntest('should only use element selector on last expect.element attempt', async () => {\n  const div = document.createElement('div')\n  const spanString = '<span>test</span>'\n  div.innerHTML = spanString\n  document.body.append(div)\n\n  const locator = page.getByText('non-existent')\n  const locatorElementMock = vi.spyOn(locator, 'element')\n  const locatorQueryMock = vi.spyOn(locator, 'query')\n\n  try {\n    await expect.element(locator, { timeout: 500, interval: 100 }).toBeInTheDocument()\n  }\n  catch {}\n\n  expect(locatorElementMock).toBeCalledTimes(1)\n  expect(locatorElementMock).toHaveBeenCalledAfter(locatorQueryMock)\n})\n"
  },
  {
    "path": "test/browser/test/findElement.test.ts",
    "content": "import { beforeEach, expect, test, vi } from 'vitest'\nimport { page } from 'vitest/browser'\n\nbeforeEach(() => {\n  document.body.innerHTML = ''\n})\n\ntest('locator.findElement can find the element if it exists', async () => {\n  const button = createButton()\n\n  const element = await page.getByRole('button').findElement()\n  expect(element).toBeInTheDocument()\n  expect(button).toBe(element)\n})\n\ntest('locator.findElement can find the element if it appears', async () => {\n  let button: HTMLButtonElement\n\n  setTimeout(() => {\n    button = createButton()\n  }, 50)\n\n  const element = await page.getByRole('button').findElement()\n  expect(element).toBeInTheDocument()\n  expect(button).toBe(element)\n})\n\ntest('locator.findElement fails if it cannot find the element', async () => {\n  const locator = page.getByRole('button')\n  const elementsSpy = vi.spyOn(locator, 'elements')\n  await expect(() => {\n    return locator.findElement({ timeout: 100 })\n  }).rejects.toThrow('Cannot find element with locator: getByRole(\\'button\\')')\n  // Normally it would be 5:\n  // Immidiate, 0 (next tick), 20, 50, 100\n  // But on CI it can be less because resources are limited\n  expect(elementsSpy.mock.calls.length).toBeGreaterThanOrEqual(3)\n})\n\ntest('locator.findElement fails if there are multiple elements by default', async () => {\n  createButton()\n  createButton()\n\n  await expect(\n    () => page.getByRole('button').findElement(),\n  ).rejects.toThrowErrorMatchingInlineSnapshot(`\n    [Error: strict mode violation: getByRole('button') resolved to 2 elements:\n        1) <button></button> aka getByRole('button').first()\n        2) <button></button> aka getByRole('button').nth(1)\n    ]\n  `)\n})\n\ntest('locator.findElement fails if there are multiple elements if strict mode is specified', async () => {\n  createButton()\n  createButton()\n\n  await expect(\n    () => page.getByRole('button').findElement({ strict: true }),\n  ).rejects.toThrowErrorMatchingInlineSnapshot(`\n    [Error: strict mode violation: getByRole('button') resolved to 2 elements:\n        1) <button></button> aka getByRole('button').first()\n        2) <button></button> aka getByRole('button').nth(1)\n    ]\n  `)\n})\n\ntest('locator.findElement fails if multiple elements appear later with strict mode', async () => {\n  setTimeout(() => {\n    createButton()\n    createButton()\n  }, 50)\n\n  await expect(\n    () => page.getByRole('button').findElement(),\n  ).rejects.toThrowErrorMatchingInlineSnapshot(`\n    [Error: strict mode violation: getByRole('button') resolved to 2 elements:\n        1) <button></button> aka getByRole('button').first()\n        2) <button></button> aka getByRole('button').nth(1)\n    ]\n  `)\n})\n\ntest('locator.findElement returns the first button if strict is disabled', async () => {\n  const button = createButton()\n  createButton()\n\n  const element = await page.getByRole('button').findElement({ strict: false })\n  expect(element).toBeInTheDocument()\n  expect(button).toBe(element)\n})\n\ntest('locator.findElement returns the first button if strict is disabled after element appears', async () => {\n  let button: HTMLButtonElement\n\n  setTimeout(() => {\n    button = createButton()\n    createButton()\n  }, 50)\n\n  const element = await page.getByRole('button').findElement({ strict: false })\n  expect(element).toBeInTheDocument()\n  expect(button).toBe(element)\n})\n\nfunction createButton() {\n  const button = document.createElement('button')\n  document.body.append(button)\n  return button\n}\n"
  },
  {
    "path": "test/browser/test/iframe.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { page, server } from 'vitest/browser'\n\ntest.runIf(server.provider === 'playwright')('locates an iframe', async () => {\n  const iframe = document.createElement('iframe')\n  iframe.setAttribute('data-testid', 'iframe')\n  iframe.srcdoc = '<div onclick=\"console.log\">Hello World!</div>'\n  document.body.append(iframe)\n  const frame = page.frameLocator(\n    page.getByTestId('iframe'),\n  )\n\n  await frame.getByText('Hello World').click()\n  await expect.element(frame.getByText('Hello World')).toHaveTextContent('Hello World')\n})\n"
  },
  {
    "path": "test/browser/test/injected.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('injected values are correct', () => {\n  expect((globalThis as any).__injected).toEqual([\n    1,\n    2,\n  ])\n})\n"
  },
  {
    "path": "test/browser/test/mocking.test.ts",
    "content": "import { expect, it, vi } from 'vitest'\nimport * as module from '../src/calculator'\n\nit('spying on an esm module prints an error', () => {\n  const error: Error = (() => {\n    try {\n      vi.spyOn(module, 'calculator')\n      expect.unreachable()\n    }\n    catch (err) {\n      return err\n    }\n  })()\n  expect(error.name).toBe('TypeError')\n  expect(error.message).toMatchInlineSnapshot(`\"Cannot spy on export \"calculator\". Module namespace is not configurable in ESM. See: https://vitest.dev/guide/browser/#limitations\"`)\n\n  expect(error.cause).toBeInstanceOf(TypeError)\n})\n"
  },
  {
    "path": "test/browser/test/polyfill-lib.test.ts",
    "content": "// eslint-disable-next-line unicorn/prefer-node-protocol\nimport * as url from 'url'\nimport { expect, test } from 'vitest'\n\ntest('url is polyfilled because it\\'s installed in dependencies', () => {\n  expect(url.format).toBeDefined()\n})\n"
  },
  {
    "path": "test/browser/test/server-headers.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('server.headers', async () => {\n  const res = await fetch('/')\n  expect(res.ok)\n  expect(res.headers.get('x-custom')).toBe('hello')\n})\n"
  },
  {
    "path": "test/browser/test/snapshot.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('inline snapshot', () => {\n  expect(1).toMatchInlineSnapshot('1')\n})\n\ntest('snapshot', () => {\n  expect(1).toMatchSnapshot()\n})\n\ntest('file snapshot', async () => {\n  await expect('my snapshot content')\n    .toMatchFileSnapshot('./__snapshots__/custom/my_snapshot')\n})\n\ntest('vitest attribute is hidden', () => {\n  const div = document.createElement('div')\n  div.setAttribute('data-testid', '__vitest_1__')\n  expect(div).toMatchInlineSnapshot(`\n    <div />\n  `)\n})\n"
  },
  {
    "path": "test/browser/test/tags.test.ts",
    "content": "/**\n * @module-tag browser\n */\n\nimport { describe, test } from 'vitest'\n\ndescribe('suite 1', () => {\n  test('test 1', { tags: ['test'] }, () => {})\n\n  describe('suite 2', { tags: ['e2e'] }, () => {\n    test('test 2', () => {})\n  })\n})\n"
  },
  {
    "path": "test/browser/test/timers.test.ts",
    "content": "import { afterEach, expect, it, vi } from 'vitest'\n\nafterEach(() => {\n  vi.useRealTimers()\n})\n\nit('only runs a setTimeout callback once (ever)', () => {\n  vi.useFakeTimers()\n\n  const fn = vi.fn()\n  setTimeout(fn, 0)\n  expect(fn).toHaveBeenCalledTimes(0)\n\n  vi.runAllTimers()\n  expect(fn).toHaveBeenCalledTimes(1)\n\n  vi.runAllTimers()\n  expect(fn).toHaveBeenCalledTimes(1)\n})\n"
  },
  {
    "path": "test/browser/test/userEvent.test.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { userEvent as _uE, page, server } from 'vitest/browser'\nimport '../src/button.css'\n\nbeforeEach(() => {\n  // clear body\n  document.body.replaceChildren()\n})\n\nconst userEvent = _uE.setup()\n\ndescribe('userEvent.click', () => {\n  test('correctly clicks a button', async () => {\n    const wrapper = document.createElement('div')\n    wrapper.style.height = '100px'\n    wrapper.style.width = '200px'\n    wrapper.style.backgroundColor = 'red'\n    wrapper.style.display = 'flex'\n    wrapper.style.justifyContent = 'center'\n    wrapper.style.alignItems = 'center'\n    const button = document.createElement('button')\n    button.textContent = 'Click me'\n    document.body.appendChild(button)\n    const onClick = vi.fn()\n    const dblClick = vi.fn()\n    // Make sure a contextmenu doesn't actually appear, as it may make some\n    // tests fail later.\n    const onContextmenu = vi.fn(e => e.preventDefault())\n    button.addEventListener('click', onClick)\n    button.addEventListener('dblclick', onClick)\n    button.addEventListener('contextmenu', onContextmenu)\n\n    await userEvent.click(button)\n\n    expect(onClick).toHaveBeenCalled()\n    expect(dblClick).not.toHaveBeenCalled()\n    expect(onContextmenu).not.toHaveBeenCalled()\n\n    onClick.mockClear()\n    await userEvent.click(button, { button: 'right' })\n    expect(onClick).not.toHaveBeenCalled()\n    expect(onContextmenu).toHaveBeenCalled()\n  })\n\n  test('correctly doesn\\'t click on a disabled button', async () => {\n    const button = document.createElement('button')\n    button.textContent = 'Click me'\n    button.disabled = true\n    document.body.appendChild(button)\n    const onClick = vi.fn()\n    button.addEventListener('click', onClick)\n\n    await userEvent.click(button, {\n      // playwright requires force: true to click on a disabled button\n      force: true,\n    })\n\n    expect(onClick).not.toHaveBeenCalled()\n  })\n\n  test('click inside shadow dom', async () => {\n    const shadowRoot = createShadowRoot()\n    const button = document.createElement('button')\n    button.textContent = 'Click me'\n    shadowRoot.appendChild(button)\n\n    const onClick = vi.fn()\n    button.addEventListener('click', onClick)\n\n    await userEvent.click(button)\n\n    expect(onClick).toHaveBeenCalled()\n  })\n\n  test('clicks inside svg', async () => {\n    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n    const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\n    circle.setAttribute('cx', '50')\n    circle.setAttribute('cy', '50')\n    circle.setAttribute('r', '40')\n    svg.appendChild(circle)\n    document.body.appendChild(svg)\n\n    const onClick = vi.fn()\n    circle.addEventListener('click', onClick)\n\n    await userEvent.click(circle)\n\n    expect(onClick).toHaveBeenCalled()\n  })\n\n  test('clicks a button with complex HTML ID', async () => {\n    const container = document.createElement('div')\n    // This is similar to unique IDs generated by React's useId()\n    container.id = ':r3:'\n    const button = document.createElement('button')\n    // Use uppercase and special characters\n    button.id = 'A:Button'\n    button.textContent = 'Click me'\n    container.appendChild(button)\n    document.body.appendChild(container)\n\n    const onClick = vi.fn()\n    const dblClick = vi.fn()\n    button.addEventListener('click', onClick)\n\n    await userEvent.click(button)\n\n    expect(onClick).toHaveBeenCalled()\n    expect(dblClick).not.toHaveBeenCalled()\n  })\n\n  test.runIf(server.provider === 'playwright')('clicks with x/y coords', async () => {\n    const canvas = document.createElement('canvas')\n    canvas.width = 400\n    canvas.height = 300\n    canvas.style.backgroundColor = 'pink'\n\n    const spy = vi.fn()\n\n    // draw a blue square in the middle of the rectangle\n    const ctx: CanvasRenderingContext2D | null = canvas.getContext('2d')\n    // If the user clicks on the blue square, it should turn red, and vice versa\n    const onClick = (event: PointerEvent) => {\n      const x = event.offsetX\n      const y = event.offsetY\n      if (x > 150 && x < 250 && y > 100 && y < 200) {\n        if (!ctx) {\n          throw new Error('Canvas is not defined')\n        }\n        if (ctx.fillStyle === '#ff0000') {\n          ctx.fillStyle = 'blue'\n        }\n        else {\n          ctx.fillStyle = 'red'\n        }\n\n        ctx.fillRect(150, 100, 100, 100)\n      }\n\n      spy({ x, y })\n    }\n\n    canvas.addEventListener('click', onClick)\n    document.body.appendChild(canvas)\n\n    await userEvent.click(document.body, {\n      position: {\n        x: 200,\n        y: 150,\n      },\n    })\n\n    // not exact due to scaling and rounding\n    expect(spy).toHaveBeenCalledWith({\n      x: expect.closeTo(200, -1),\n      y: expect.closeTo(150, -1),\n    })\n  })\n\n  test('click throws an error with multiple elements', async () => {\n    const button1 = document.createElement('button')\n    const button2 = document.createElement('button')\n    document.body.append(button1, button2)\n\n    await expect(() => page.getByRole('button').click()).rejects.toThrow(\n      `strict mode violation: getByRole('button') resolved to 2 elements:\\n`\n      + `    1) <button></button> aka getByRole('button').first()\\n`\n      + `    2) <button></button> aka getByRole('button').nth(1)`,\n    )\n  })\n})\n\ndescribe('userEvent.dblClick', () => {\n  test('correctly clicks a button', async () => {\n    const button = document.createElement('button')\n    button.textContent = 'Click me'\n    document.body.appendChild(button)\n    const onClick = vi.fn()\n    const dblClick = vi.fn()\n    button.addEventListener('click', onClick)\n    button.addEventListener('dblclick', dblClick)\n\n    await userEvent.dblClick(button)\n\n    expect(onClick).toHaveBeenCalledTimes(2)\n    expect(dblClick).toHaveBeenCalledTimes(1)\n  })\n\n  test('correctly doesn\\'t click on a disabled button', async () => {\n    const button = document.createElement('button')\n    button.textContent = 'Click me'\n    button.disabled = true\n    document.body.appendChild(button)\n    const onClick = vi.fn()\n    const dblClick = vi.fn()\n    button.addEventListener('click', onClick)\n    button.addEventListener('dblclick', dblClick)\n\n    await userEvent.dblClick(button, {\n      // playwright requires force: true to click on a disabled button\n      force: true,\n    })\n\n    expect(onClick).not.toHaveBeenCalled()\n    expect(dblClick).not.toHaveBeenCalled()\n  })\n\n  test('double click throws an error with multiple elements', async () => {\n    const button1 = document.createElement('button')\n    const button2 = document.createElement('button')\n    document.body.append(button1, button2)\n\n    await expect(() => page.getByRole('button').dblClick()).rejects.toThrow(\n      `strict mode violation: getByRole('button') resolved to 2 elements:\\n`\n      + `    1) <button></button> aka getByRole('button').first()\\n`\n      + `    2) <button></button> aka getByRole('button').nth(1)`,\n    )\n  })\n})\n\ndescribe('userEvent.tripleClick', () => {\n  test('correctly clicks a button', async () => {\n    const button = document.createElement('button')\n    button.textContent = 'Click me'\n    document.body.appendChild(button)\n    const onClick = vi.fn()\n    const dblClick = vi.fn()\n    const tripleClick = vi.fn()\n    button.addEventListener('click', onClick)\n    button.addEventListener('dblclick', dblClick)\n    button.addEventListener('click', tripleClick)\n\n    await userEvent.tripleClick(button)\n\n    expect(onClick).toHaveBeenCalledTimes(3)\n    expect(dblClick).toHaveBeenCalledTimes(1)\n    expect(tripleClick).toHaveBeenCalledTimes(3)\n    expect(tripleClick.mock.calls.length).toBe(3)\n    expect(tripleClick.mock.calls\n      .map(c => c[0] as MouseEvent)\n      .filter(c => c.detail === 3)).toHaveLength(1)\n  })\n\n  test('correctly doesn\\'t click on a disabled button', async () => {\n    const button = document.createElement('button')\n    button.textContent = 'Click me'\n    button.disabled = true\n    document.body.appendChild(button)\n    const onClick = vi.fn()\n    const dblClick = vi.fn()\n    const tripleClick = vi.fn()\n    button.addEventListener('click', onClick)\n    button.addEventListener('dblclick', dblClick)\n    button.addEventListener('click', tripleClick)\n\n    await userEvent.tripleClick(button, {\n      // playwright requires force: true to click on a disabled button\n      force: true,\n    })\n\n    expect(onClick).not.toHaveBeenCalled()\n    expect(dblClick).not.toHaveBeenCalled()\n    expect(tripleClick).not.toHaveBeenCalled()\n  })\n\n  test('triple click throws an error with multiple elements', async () => {\n    const button1 = document.createElement('button')\n    const button2 = document.createElement('button')\n    document.body.append(button1, button2)\n\n    await expect(() => page.getByRole('button').tripleClick()).rejects.toThrow(\n      `strict mode violation: getByRole('button') resolved to 2 elements:\\n`\n      + `    1) <button></button> aka getByRole('button').first()\\n`\n      + `    2) <button></button> aka getByRole('button').nth(1)`,\n    )\n  })\n})\n\ndescribe('userEvent.hover, userEvent.unhover', () => {\n  test('hover, unhover works correctly', async () => {\n    const target = document.createElement('div')\n    target.style.width = '100px'\n    target.style.height = '100px'\n\n    let mouseEntered = false\n    let pointerEntered = false\n\n    target.addEventListener('mouseover', () => {\n      mouseEntered = true\n    })\n    target.addEventListener('pointerenter', () => {\n      pointerEntered = true\n    })\n    target.addEventListener('pointerleave', () => {\n      pointerEntered = false\n    })\n    target.addEventListener('mouseout', () => {\n      mouseEntered = false\n    })\n\n    document.body.appendChild(target)\n\n    await userEvent.hover(target)\n\n    expect(pointerEntered).toBe(true)\n    expect(mouseEntered).toBe(true)\n\n    await userEvent.unhover(target)\n\n    expect(pointerEntered).toBe(false)\n    expect(mouseEntered).toBe(false)\n  })\n\n  test('hover throws an error with multiple elements', async () => {\n    const button1 = document.createElement('button')\n    const button2 = document.createElement('button')\n    document.body.append(button1, button2)\n\n    await expect(() => page.getByRole('button').hover()).rejects.toThrow(\n      `strict mode violation: getByRole('button') resolved to 2 elements:\\n`\n      + `    1) <button></button> aka getByRole('button').first()\\n`\n      + `    2) <button></button> aka getByRole('button').nth(1)`,\n    )\n  })\n\n  test.runIf(server.provider === 'playwright')('hover, unhover correctly pass options', async () => {\n    interface ModifiersDetected { shift: boolean; control: boolean }\n    type ModifierKeys = 'Shift' | 'Control' | 'Alt' | 'ControlOrMeta' | 'Meta'\n\n    const hoverOptions = { modifiers: ['Shift'] as ModifierKeys[] }\n    const unhoverOptions = { modifiers: ['Control'] as ModifierKeys[] }\n\n    const target = document.createElement('div')\n    target.style.width = '100px'\n    target.style.height = '100px'\n\n    let modifiersDetected: ModifiersDetected = {\n      shift: false,\n      control: false,\n    }\n\n    target.addEventListener('mouseover', (e) => {\n      modifiersDetected.shift = e.shiftKey\n      modifiersDetected.control = e.ctrlKey\n    })\n\n    target.addEventListener('mouseout', (e) => {\n      modifiersDetected.shift = e.shiftKey\n      modifiersDetected.control = e.ctrlKey\n    })\n\n    document.body.appendChild(target)\n\n    await userEvent.hover(target, hoverOptions)\n\n    expect(modifiersDetected.shift).toEqual(hoverOptions.modifiers.includes('Shift'))\n    expect(modifiersDetected.control).toEqual(hoverOptions.modifiers.includes('Control'))\n    modifiersDetected = { shift: false, control: false }\n\n    await userEvent.unhover(target, unhoverOptions)\n\n    expect(modifiersDetected.shift).toEqual(unhoverOptions.modifiers.includes('Shift'))\n    expect(modifiersDetected.control).toEqual(unhoverOptions.modifiers.includes('Control'))\n  })\n\n  test('hover works with shadow root', async () => {\n    const shadowRoot = createShadowRoot()\n    const target = document.createElement('div')\n    target.style.width = '100px'\n    target.style.height = '100px'\n\n    let mouseEntered = false\n    let pointerEntered = false\n    target.addEventListener('mouseover', () => {\n      mouseEntered = true\n    })\n    target.addEventListener('pointerenter', () => {\n      pointerEntered = true\n    })\n    target.addEventListener('pointerleave', () => {\n      pointerEntered = false\n    })\n    target.addEventListener('mouseout', () => {\n      mouseEntered = false\n    })\n\n    shadowRoot.appendChild(target)\n\n    await userEvent.hover(target)\n\n    expect(pointerEntered).toBe(true)\n    expect(mouseEntered).toBe(true)\n\n    await userEvent.unhover(target)\n\n    expect(pointerEntered).toBe(false)\n    expect(mouseEntered).toBe(false)\n  })\n\n  test('hover works with svg', async () => {\n    const target = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n    const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\n    circle.setAttribute('cx', '50')\n    circle.setAttribute('cy', '50')\n    circle.setAttribute('r', '40')\n    target.appendChild(circle)\n    document.body.appendChild(target)\n    target.style.width = '100px'\n    target.style.height = '100px'\n\n    let mouseEntered = false\n    let pointerEntered = false\n    target.addEventListener('mouseover', () => {\n      mouseEntered = true\n    })\n    target.addEventListener('pointerenter', () => {\n      pointerEntered = true\n    })\n    target.addEventListener('pointerleave', () => {\n      pointerEntered = false\n    })\n    target.addEventListener('mouseout', () => {\n      mouseEntered = false\n    })\n\n    document.body.appendChild(target)\n\n    await userEvent.hover(target)\n\n    expect(pointerEntered).toBe(true)\n    expect(mouseEntered).toBe(true)\n\n    await userEvent.unhover(target)\n\n    expect(pointerEntered).toBe(false)\n    expect(mouseEntered).toBe(false)\n  })\n})\n\nconst inputLike = [\n  () => {\n    const input = document.createElement('input')\n    input.type = 'text'\n    input.placeholder = 'Type here'\n    return input\n  },\n  () => {\n    const input = document.createElement('textarea')\n    input.placeholder = 'Type here'\n    return input\n  },\n  () => {\n    const contentEditable = document.createElement('div')\n    contentEditable.contentEditable = 'true'\n    return contentEditable\n  },\n]\n\ntest('type throws an error with multiple elements', async () => {\n  const button1 = document.createElement('button')\n  const button2 = document.createElement('button')\n  document.body.append(button1, button2)\n\n  await expect(() => userEvent.type(page.getByRole('button'), 'Hello World')).rejects.toThrow(\n    `strict mode violation: getByRole('button') resolved to 2 elements:\\n`\n    + `    1) <button></button> aka getByRole('button').first()\\n`\n    + `    2) <button></button> aka getByRole('button').nth(1)`,\n  )\n})\n\ntest('fill throws an error with multiple elements', async () => {\n  const button1 = document.createElement('button')\n  const button2 = document.createElement('button')\n  document.body.append(button1, button2)\n\n  await expect(() => page.getByRole('button').fill('Hello World')).rejects.toThrow(\n    `strict mode violation: getByRole('button') resolved to 2 elements:\\n`\n    + `    1) <button></button> aka getByRole('button').first()\\n`\n    + `    2) <button></button> aka getByRole('button').nth(1)`,\n  )\n})\n\ndescribe.each(inputLike)('userEvent.type', (getElement) => {\n  test('types into an input', async () => {\n    const { input, keydown, keyup, value } = createTextInput()\n\n    await userEvent.type(input, 'Hello World!')\n    expect(value()).toBe('Hello World!')\n    expect(keydown).toEqual([\n      'H',\n      'e',\n      'l',\n      'l',\n      'o',\n      ' ',\n      'W',\n      'o',\n      'r',\n      'l',\n      'd',\n      '!',\n    ])\n    expect(keyup).toEqual([\n      'H',\n      'e',\n      'l',\n      'l',\n      'o',\n      ' ',\n      'W',\n      'o',\n      'r',\n      'l',\n      'd',\n      '!',\n    ])\n    keydown.length = 0\n    keyup.length = 0\n\n    await userEvent.type(input, '{a>3}4')\n    expect(value()).toBe('Hello World!aaa4')\n\n    await userEvent.type(input, '{backspace}')\n    expect(value()).toBe('Hello World!aaa')\n\n    // doesn't affect the input value\n    await userEvent.type(input, '{/a}')\n    expect(value()).toBe('Hello World!aaa')\n\n    expect(keydown).toEqual([\n      'a',\n      'a',\n      'a',\n      '4',\n      'Backspace',\n    ])\n\n    await userEvent.type(input, '{Shift}b{/Shift}')\n\n    // this follow userEvent logic\n    expect(value()).toBe('Hello World!aaab')\n\n    await userEvent.clear(input)\n\n    expect(value()).toBe('')\n  })\n\n  test('repeating without manual up works correctly', async () => {\n    const { input, keydown, keyup, value } = createTextInput()\n\n    const userEvent = _uE.setup()\n    await userEvent.type(input, '{a>2}4')\n    expect(value()).toBe('aa4')\n\n    expect(keydown).toEqual([\n      'a',\n      'a',\n      '4',\n    ])\n    // keyup is released at the end by userEvent\n    expect(keyup).toEqual([\n      '4',\n      'a',\n    ])\n  })\n\n  test('repeating with manual up works correctly', async () => {\n    const { input, keydown, keyup, value } = createTextInput()\n\n    const userEvent = _uE.setup()\n    await userEvent.type(input, '{a>3/}4')\n    expect(value()).toBe('aaa4')\n\n    expect(keydown).toEqual([\n      'a',\n      'a',\n      'a',\n      '4',\n    ])\n    // keyup is released with \"/\" syntax\n    expect(keyup).toEqual([\n      'a',\n      '4',\n    ])\n  })\n\n  test('repeating with disabled up works correctly', async () => {\n    const { input, keydown, keyup, value } = createTextInput()\n\n    const userEvent = _uE.setup()\n    await userEvent.type(input, '{a>3}4', {\n      skipAutoClose: true,\n    })\n    expect(value()).toBe('aaa4')\n\n    expect(keydown).toEqual([\n      'a',\n      'a',\n      'a',\n      '4',\n    ])\n    // keyup is not released at the end by userEvent\n    expect(keyup).toEqual([\n      '4',\n    ])\n  })\n\n  test('types into a shadow root input', async () => {\n    const shadowRoot = createShadowRoot()\n    const { input, keydown, value } = createTextInput(shadowRoot)\n\n    const userEvent = _uE.setup()\n    await userEvent.type(input, 'Hello')\n    expect(value()).toBe('Hello')\n    expect(keydown).toEqual([\n      'H',\n      'e',\n      'l',\n      'l',\n      'o',\n    ])\n  })\n\n  // strangely enough, original userEvent doesn't support this,\n  // but we can implement it\n  test.skipIf(server.provider === 'preview')('selectall works correctly', async () => {\n    const input = document.createElement('input')\n    input.type = 'text'\n    input.placeholder = 'Type here'\n    document.body.appendChild(input)\n    await userEvent.type(input, 'Hello World!')\n    await userEvent.type(input, '{selectall}')\n    await userEvent.type(input, '{backspace}')\n    expect(input.value).toBe('')\n  })\n\n  function createTextInput(root: Node = document.body) {\n    const input = getElement()\n    const keydown: string[] = []\n    const keyup: string[] = []\n    input.addEventListener('keydown', (event: KeyboardEvent) => {\n      keydown.push(event.key)\n    })\n    input.addEventListener('keyup', (event: KeyboardEvent) => {\n      keyup.push(event.key)\n    })\n    root.appendChild(input)\n    return {\n      input,\n      keydown,\n      keyup,\n      value() {\n        if ('value' in input) {\n          return input.value\n        }\n        return input.textContent\n      },\n    }\n  }\n})\n\ndescribe('userEvent.tab', () => {\n  test('tab correctly switches focus', async () => {\n    const input1 = document.createElement('input')\n    input1.type = 'text'\n    const input2 = document.createElement('input')\n    input2.type = 'text'\n    document.body.appendChild(input1)\n    document.body.appendChild(input2)\n\n    input1.focus()\n    await userEvent.tab()\n\n    expect(document.activeElement).toBe(input2)\n\n    await userEvent.tab({ shift: true })\n\n    expect(document.activeElement).toBe(input1)\n  })\n})\n\ndescribe.each(inputLike)('userEvent.fill', async (getInput) => {\n  test('correctly fills the input value', async () => {\n    const input = getInput()\n    document.body.appendChild(input)\n    function value() {\n      if ('value' in input) {\n        return input.value\n      }\n      return input.textContent\n    }\n\n    await userEvent.fill(input, 'Hello World!')\n    expect(value()).toBe('Hello World!')\n\n    await userEvent.fill(input, 'Another Value')\n    expect(value()).toBe('Another Value')\n  })\n\n  test.skipIf(server.provider === 'preview')('fill input in shadow root', async () => {\n    const input = getInput()\n    const shadowRoot = createShadowRoot()\n    shadowRoot.appendChild(input)\n    function value() {\n      if ('value' in input) {\n        return input.value\n      }\n      return input.textContent\n    }\n\n    await userEvent.fill(input, 'Hello')\n    expect(value()).toBe('Hello')\n  })\n})\n\ndescribe('userEvent.keyboard', async () => {\n  test('standalone keyboard works correctly with a body in focus', async () => {\n    const pressed: string[] = []\n    document.addEventListener('keydown', (event) => {\n      pressed.push(event.key)\n    })\n    expect(document.activeElement).toBe(document.body)\n    await userEvent.keyboard('Hello')\n    expect(pressed).toEqual([\n      'H',\n      'e',\n      'l',\n      'l',\n      'o',\n    ])\n  })\n\n  test('standalone keyboard works correctly with an active non-input', async () => {\n    const documentKeydown: string[] = []\n    const divKeydown: string[] = []\n    const div = document.createElement('div')\n    div.style.width = '100px'\n    div.style.height = '100px'\n    div.tabIndex = 0\n    div.addEventListener('keydown', (event) => {\n      divKeydown.push(event.key)\n      event.stopPropagation()\n      event.preventDefault()\n    })\n    document.body.appendChild(div)\n    document.addEventListener('keydown', (event) => {\n      documentKeydown.push(event.key)\n    })\n    expect(document.activeElement).toBe(document.body)\n    div.focus()\n    expect(document.activeElement).toBe(div)\n    await userEvent.keyboard('Hello{backspace}')\n    expect(documentKeydown).toEqual([])\n    expect(divKeydown).toEqual([\n      'H',\n      'e',\n      'l',\n      'l',\n      'o',\n      'Backspace',\n    ])\n  })\n\n  // looks like wdio doesn't support releasing Enter on its own\n  test('should not auto release', async () => {\n    const spyKeydown = vi.fn()\n    const spyKeyup = vi.fn()\n    const button = document.createElement('button')\n    document.body.appendChild(button)\n    button.addEventListener('keydown', spyKeydown)\n    button.addEventListener('keyup', spyKeyup)\n    button.focus()\n    await userEvent.keyboard('{Enter>}')\n    expect(spyKeydown).toHaveBeenCalledOnce()\n    expect(spyKeyup).not.toHaveBeenCalled()\n    await userEvent.keyboard('{/Enter}')\n    expect(spyKeyup).toHaveBeenCalled()\n  })\n\n  test('standalone keyboard works correctly with active input', async () => {\n    const documentKeydown: string[] = []\n    const inputKeydown: string[] = []\n    const input = document.createElement('input')\n    input.addEventListener('keydown', (event) => {\n      inputKeydown.push(event.key)\n      event.stopPropagation()\n    })\n    document.body.appendChild(input)\n    document.addEventListener('keydown', (event) => {\n      documentKeydown.push(event.key)\n    })\n    expect(document.activeElement).toBe(document.body)\n    input.focus()\n    expect(document.activeElement).toBe(input)\n\n    await userEvent.keyboard('Hello{backspace}')\n\n    expect(input.value).toBe('Hell')\n    expect(documentKeydown).toEqual([])\n    expect(inputKeydown).toEqual([\n      'H',\n      'e',\n      'l',\n      'l',\n      'o',\n      'Backspace',\n    ])\n  })\n})\n\ndescribe.skipIf(server.provider === 'preview')('userEvent.dragAndDrop', async () => {\n  test('drag and drop works', async () => {\n    const source = document.createElement('div')\n    source.textContent = 'Drag me'\n    source.style.width = '100px'\n    source.style.height = '100px'\n    source.style.background = 'red'\n    source.draggable = true\n\n    const dragstart = vi.fn()\n\n    source.addEventListener('dragstart', dragstart)\n\n    const target = document.createElement('div')\n    target.style.width = '100px'\n    target.style.height = '100px'\n    target.style.background = 'blue'\n\n    const dragover = vi.fn(() => {\n      target.textContent = 'Dropped'\n    })\n\n    target.addEventListener('dragover', dragover)\n\n    document.body.appendChild(source)\n    document.body.appendChild(target)\n\n    expect(target.textContent).toBe('')\n\n    await userEvent.dragAndDrop(source, target)\n\n    await expect.poll(() => dragstart).toHaveBeenCalled()\n    await expect.poll(() => dragover).toHaveBeenCalled()\n\n    expect(target.textContent).toBe('Dropped')\n  })\n})\n\ndescribe.each([\n  [\n    'select',\n    function createSelect() {\n      const select = document.createElement('select')\n      const option1 = document.createElement('option')\n      option1.value = '1'\n      option1.textContent = 'Option 1'\n      const option2 = document.createElement('option')\n      option2.value = '2'\n      option2.textContent = 'Option 2'\n      select.appendChild(option1)\n      select.appendChild(option2)\n      document.body.appendChild(select)\n\n      return { select, options: [option1, option2] }\n    },\n  ],\n  // TODO: support listbox\n  // [\n  //   'listbox',\n  //   function createSelect() {\n  //     const select = document.createElement('div')\n  //     select.setAttribute('role', 'listbox')\n  //     const option1 = document.createElement('div')\n  //     option1.setAttribute('role', 'option')\n  //     // option1.value = '1'\n  //     option1.textContent = 'Option 1'\n  //     const option2 = document.createElement('div')\n  //     option2.setAttribute('role', 'option')\n  //     // option2.value = '2'\n  //     option2.textContent = 'Option 2'\n  //     select.appendChild(option1)\n  //     select.appendChild(option2)\n  //     document.body.appendChild(select)\n\n  //     return { select, options: [option1, option2] }\n  //   },\n  // ],\n])('selectOptions in \"%s\" works correctly', (name, createSelect) => {\n  test(`${name} throws an error with multiple elements`, async () => {\n    const button1 = document.createElement('button')\n    const button2 = document.createElement('button')\n    document.body.append(button1, button2)\n\n    await expect(() => page.getByRole('button').selectOptions('Hello World')).rejects.toThrow(\n      `strict mode violation: getByRole('button') resolved to 2 elements:\\n`\n      + `    1) <button></button> aka getByRole('button').first()\\n`\n      + `    2) <button></button> aka getByRole('button').nth(1)`,\n    )\n  })\n\n  test('can select a single primitive value', async () => {\n    const { select } = createSelect()\n\n    await userEvent.selectOptions(select, '2')\n\n    expect(select.value).toBe('2')\n  })\n\n  test('can select a single primitive value by label', async () => {\n    const { select } = createSelect()\n\n    await userEvent.selectOptions(select, 'Option 2')\n\n    expect(select.value).toBe('2')\n  })\n\n  test('can select a single element value', async () => {\n    const { select, options } = createSelect()\n\n    await userEvent.selectOptions(select, options[1])\n\n    expect(select.value).toBe('2')\n  })\n\n  // webdriverio doesn't support selecting multiple values\n  describe.skipIf(server.provider === 'webdriverio')('multiple values', () => {\n    test('can select multiple values', async () => {\n      const { select, options } = createSelect()\n      select.multiple = true\n\n      await userEvent.selectOptions(select, ['1', '2'])\n\n      const selected = document.querySelectorAll('option:checked')\n\n      expect(selected).toHaveLength(2)\n      expect(selected[0]).toBe(options[0])\n      expect(selected[1]).toBe(options[1])\n    })\n\n    test('can select multiple values by label', async () => {\n      const { select, options } = createSelect()\n      select.multiple = true\n\n      await userEvent.selectOptions(select, ['Option 1', 'Option 2'])\n\n      const selected = document.querySelectorAll('option:checked')\n\n      expect(selected).toHaveLength(2)\n      expect(selected[0]).toBe(options[0])\n      expect(selected[1]).toBe(options[1])\n    })\n\n    test('can select multiple element values', async () => {\n      const { select, options } = createSelect()\n      select.multiple = true\n\n      await userEvent.selectOptions(select, options)\n\n      const selected = document.querySelectorAll('option:checked')\n\n      expect(selected).toHaveLength(2)\n      expect(selected[0]).toBe(options[0])\n      expect(selected[1]).toBe(options[1])\n    })\n  })\n})\n\ndescribe('uploading files', async () => {\n  test.skipIf(server.provider === 'webdriverio')('can upload an instance of File', async () => {\n    const file = new File(['hello'], 'hello.png', { type: 'image/png' })\n    const input = document.createElement('input')\n    input.id = 'file'\n    input.type = 'file'\n    document.body.appendChild(input)\n    await userEvent.upload(input, file)\n    await expect.poll(() => input.files.length).toBe(1)\n\n    const uploadedFile = input.files[0]\n    expect(uploadedFile.name).toBe('hello.png')\n    expect(uploadedFile.type).toBe('image/png')\n    expect(await uploadedFile.text()).toBe('hello')\n  })\n\n  test.skipIf(server.provider === 'webdriverio')('can upload several instances of File', async () => {\n    const file1 = new File(['hello1'], 'hello1.png', { type: 'image/png' })\n    const file2 = new File(['hello2'], 'hello2.png', { type: 'image/png' })\n    const input = document.createElement('input')\n    input.id = 'file'\n    input.type = 'file'\n    input.multiple = true\n    document.body.appendChild(input)\n    await userEvent.upload(input, [file1, file2])\n    await expect.poll(() => input.files.length).toBe(2)\n\n    const uploadedFile1 = input.files[0]\n    expect(uploadedFile1.name).toBe('hello1.png')\n    expect(uploadedFile1.type).toBe('image/png')\n\n    const uploadedFile2 = input.files[1]\n    expect(uploadedFile2.name).toBe('hello2.png')\n    expect(uploadedFile2.type).toBe('image/png')\n  })\n\n  test.skipIf(\n    server.provider === 'webdriverio' && server.browser === 'firefox',\n  )('can upload a file by filepath relative to test file', async () => {\n    const input = document.createElement('input')\n    input.id = 'file'\n    input.type = 'file'\n    document.body.appendChild(input)\n    await userEvent.upload(input, './src/button.css')\n    await expect.poll(() => input.files.length).toBe(1)\n\n    const uploadedFile = input.files[0]\n    expect(uploadedFile.name).toBe('button.css')\n    expect(uploadedFile.type).toBe('text/css')\n  })\n\n  test.skipIf(\n    server.provider === 'webdriverio' && server.browser === 'firefox',\n  )('can upload several files by filepath relative to test file', async () => {\n    const input = document.createElement('input')\n    input.id = 'file'\n    input.type = 'file'\n    input.multiple = true\n    document.body.appendChild(input)\n    await userEvent.upload(input, ['./src/button.css', './package.json'])\n    await expect.poll(() => input.files.length).toBe(2)\n\n    const uploadedFile1 = input.files[0]\n    expect(uploadedFile1.name).toBe('button.css')\n    expect(uploadedFile1.type).toBe('text/css')\n\n    const uploadedFile2 = input.files[1]\n    expect(uploadedFile2.name).toBe('package.json')\n    expect(uploadedFile2.type).toBe('application/json')\n  })\n})\n\nfunction createShadowRoot() {\n  const div = document.createElement('div')\n  const shadowRoot = div.attachShadow({ mode: 'open' })\n  document.body.appendChild(div)\n  return shadowRoot\n}\n"
  },
  {
    "path": "test/browser/test/utils.test.ts",
    "content": "import { afterEach, beforeEach, expect, it, test } from 'vitest'\nimport { commands, utils } from 'vitest/browser'\n\nimport { inspect } from 'vitest/internal/browser'\n\nafterEach(() => {\n  document.body.innerHTML = ''\n})\n\nbeforeEach(() => {\n  utils.configurePrettyDOM({})\n})\n\nit('utils package correctly uses loupe', async () => {\n  expect(inspect({ test: 1 })).toBe('{ test: 1 }')\n})\n\ntest('prints default document', async () => {\n  expect(await commands.stripVTControlCharacters(utils.prettyDOM())).toMatchSnapshot()\n\n  const div = document.createElement('div')\n  div.innerHTML = '<span>hello</span>'\n  document.body.append(div)\n\n  expect(await commands.stripVTControlCharacters(utils.prettyDOM())).toMatchSnapshot()\n})\n\ntest('prints the element', async () => {\n  const div = document.createElement('div')\n  div.innerHTML = '<span>hello</span>'\n  document.body.append(div)\n\n  expect(await commands.stripVTControlCharacters(utils.prettyDOM())).toMatchSnapshot()\n})\n\ntest('prints the element with attributes', async () => {\n  const div = document.createElement('div')\n  div.innerHTML = '<span class=\"some-name\" data-test-id=\"33\" id=\"5\">hello</span>'\n  document.body.append(div)\n\n  expect(await commands.stripVTControlCharacters(utils.prettyDOM())).toMatchSnapshot()\n})\n\ntest('should handle DOM content bigger than maxLength', async () => {\n  const depth = 100\n  const maxContent = 150\n\n  const openingTags = '<div>'.repeat(depth)\n  const closingTags = '</div>'.repeat(depth)\n  const domString = `${openingTags}${closingTags}`\n\n  const parentDiv = document.createElement('div')\n  parentDiv.innerHTML = domString\n\n  document.body.appendChild(parentDiv)\n  expect(await commands.stripVTControlCharacters(utils.prettyDOM(undefined, maxContent))).toMatchSnapshot()\n})\n\ntest('should handle shadow DOM content', async () => {\n  class CustomElement extends HTMLElement {\n    connectedCallback() {\n      const shadowRoot = this.attachShadow({ mode: 'open' })\n      const span = document.createElement('span')\n      span.classList.add('some-name')\n      span.setAttribute('data-test-id', '33')\n      span.setAttribute('id', '5')\n      span.textContent = 'hello'\n      shadowRoot.appendChild(span)\n    }\n  }\n  customElements.define('custom-element', CustomElement)\n\n  const div = document.createElement('div')\n  div.innerHTML = '<custom-element></custom-element>'\n  document.body.append(div)\n\n  expect(await commands.stripVTControlCharacters(utils.prettyDOM())).toMatchSnapshot()\n})\n\ntest('should be able to opt out of shadow DOM content', async () => {\n  class CustomElement extends HTMLElement {\n    connectedCallback() {\n      const shadowRoot = this.attachShadow({ mode: 'open' })\n      const span = document.createElement('span')\n      span.classList.add('some-name')\n      span.setAttribute('data-test-id', '33')\n      span.setAttribute('id', '5')\n      span.textContent = 'hello'\n      shadowRoot.appendChild(span)\n    }\n  }\n  customElements.define('no-shadow-root', CustomElement)\n\n  const div = document.createElement('div')\n  div.innerHTML = '<no-shadow-root></no-shadow-root>'\n  document.body.append(div)\n\n  expect(await commands.stripVTControlCharacters(utils.prettyDOM(undefined, undefined, { printShadowRoot: false }))).toMatchSnapshot()\n})\n\ntest('changing the defaults works', async () => {\n  utils.configurePrettyDOM({\n    maxDepth: 1,\n  })\n\n  const div = document.createElement('div')\n  div.innerHTML = '<div><div><div><div></div></div></div></div>'\n  document.body.append(div)\n\n  expect(await commands.stripVTControlCharacters(utils.prettyDOM(div))).toMatchInlineSnapshot(`\n    \"<div>\n      <div … />\n    </div>\"\n  `)\n})\n\ntest('filterNode option filters out matching elements', async () => {\n  const div = document.createElement('div')\n  div.innerHTML = `\n    <div>\n      <script>console.log('test')</script>\n      <style>.test { color: red; }</style>\n      <span data-test-hide=\"true\">hidden content</span>\n      <span>visible content</span>\n    </div>\n  `\n  document.body.append(div)\n\n  const result = await commands.stripVTControlCharacters(utils.prettyDOM(div, undefined, { filterNode: 'script, style, [data-test-hide]' }))\n\n  expect(result).not.toContain('console.log')\n  expect(result).not.toContain('color: red')\n  expect(result).not.toContain('hidden content')\n  expect(result).toContain('visible content')\n  expect(result).toMatchInlineSnapshot(`\n    \"<div>\n      <div>\n        <span>\n          visible content\n        </span>\n      </div>\n    </div>\"\n  `)\n})\n\ntest('filterNode with configurePrettyDOM affects default behavior', async () => {\n  utils.configurePrettyDOM({ filterNode: 'script, style, [data-test-hide]' })\n\n  const div = document.createElement('div')\n  div.innerHTML = `\n    <div>\n      <script>console.log('test')</script>\n      <style>.test { color: red; }</style>\n      <span data-test-hide=\"true\">hidden content</span>\n      <span>visible content</span>\n    </div>\n  `\n  document.body.append(div)\n\n  const result = await commands.stripVTControlCharacters(utils.prettyDOM(div))\n\n  expect(result).not.toContain('console.log')\n  expect(result).not.toContain('color: red')\n  expect(result).not.toContain('hidden content')\n  expect(result).toContain('visible content')\n  expect(result).toMatchInlineSnapshot(`\n    \"<div>\n      <div>\n        <span>\n          visible content\n        </span>\n      </div>\n    </div>\"\n  `)\n})\n\ntest('filterNode with wildcard selector filters nested content', async () => {\n  const div = document.createElement('div')\n  div.innerHTML = `\n    <div>\n      <div data-test-hide-content>\n        <span>nested hidden</span>\n        <div>deeply nested hidden</div>\n      </div>\n      <span>visible</span>\n    </div>\n  `\n  document.body.append(div)\n\n  const result = await commands.stripVTControlCharacters(utils.prettyDOM(div, undefined, { filterNode: '[data-test-hide-content] *' }))\n\n  expect(result).not.toContain('nested hidden')\n  expect(result).not.toContain('deeply nested hidden')\n  expect(result).toContain('visible')\n  expect(result).toContain('data-test-hide-content')\n  expect(result).toMatchInlineSnapshot(`\n    \"<div>\n      <div>\n        <div\n          data-test-hide-content=\\\"\\\"\n        />\n        <span>\n          visible\n        </span>\n      </div>\n    </div>\"\n  `)\n})\n"
  },
  {
    "path": "test/browser/test/viewport.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { server } from 'vitest/browser'\n\ndescribe.skipIf(\n  // preview cannot control viewport\n  server.provider === 'preview'\n  // other tests affect the viewport if they run in a different order\n  || server.config.browser.isolate === false,\n)('viewport window has been properly initialized', () => {\n  it.skipIf(!server.config.browser.headless)('viewport has proper size', () => {\n    const { width, height } = server.config.browser.viewport\n    const { width: actualWidth, height: actualHeight } = window.document.documentElement.getBoundingClientRect()\n\n    expect(actualWidth).toBe(width)\n    expect(actualHeight).toBe(height)\n  })\n\n  it.skipIf(server.config.browser.headless)('window has been maximized', () => {\n    let topWindow = window\n    while (topWindow.parent && topWindow !== topWindow.parent) {\n      topWindow = topWindow.parent as unknown as any\n    }\n\n    // edge will show the Hub Apps right panel\n    if (server.browser === 'edge') {\n      expect(topWindow.visualViewport.width - topWindow.innerWidth === 0).toBe(true)\n    }\n    else {\n      expect(screen.availWidth - topWindow.innerWidth === 0).toBe(true)\n    }\n  })\n})\n"
  },
  {
    "path": "test/browser/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"jsx\": \"react-jsx\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"paths\": {\n      \"#src/*\": [\"./src/*\"]\n    },\n    \"types\": [\n      \"vite/client\",\n      \"vitest-browser-react\",\n      \"vitest/import-meta\"\n    ],\n    \"noEmit\": true,\n    \"esModuleInterop\": true\n  },\n  \"include\": [\n    \"fixtures\",\n    \"test\",\n    \"specs\",\n    \"./vitest.config.*\",\n    \"./setup.unit.ts\"\n  ]\n}\n"
  },
  {
    "path": "test/browser/vitest.config-basepath.mts",
    "content": "import { defineConfig, mergeConfig } from 'vitest/config'\nimport baseConfig from './vitest.config.mjs'\n\nexport default mergeConfig(baseConfig, defineConfig({ base: '/fix-4686' }))\n"
  },
  {
    "path": "test/browser/vitest.config.mts",
    "content": "import type { BrowserCommand } from 'vitest/node'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport * as util from 'node:util'\nimport { defineConfig } from 'vitest/config'\nimport { instances, provider } from './settings'\n\nconst dir = dirname(fileURLToPath(import.meta.url))\n\nconst myCustomCommand: BrowserCommand<[arg1: string, arg2: string]> = ({ testPath }, arg1, arg2) => {\n  return { testPath, arg1, arg2 }\n}\n\nconst stripVTControlCharacters: BrowserCommand<[text: string]> = (_, text) => {\n  return util.stripVTControlCharacters(text)\n}\n\nexport default defineConfig({\n  server: {\n    headers: {\n      'x-custom': 'hello',\n      // Vitest iframe should still be loaded\n      'X-Frame-Options': 'DENY',\n      'content-security-policy': 'frame-src https://example.com; frame-ancestors https://example.com',\n    },\n  },\n  optimizeDeps: {\n    include: ['@vitest/cjs-lib', '@vitest/bundled-lib', 'react/jsx-dev-runtime'],\n  },\n  define: {\n    'import.meta.env.DEFINE_CUSTOM_ENV': JSON.stringify('define-custom-env'),\n  },\n  test: {\n    include: ['test/**.test.{ts,js,tsx}'],\n    includeSource: ['src/*.ts'],\n    // having a snapshot environment doesn't affect browser tests\n    snapshotEnvironment: './custom-snapshot-env.ts',\n    env: {\n      CUSTOM_ENV: 'foo',\n    },\n    browser: {\n      enabled: true,\n      headless: false,\n      instances,\n      provider,\n      // isolate: false,\n      testerHtmlPath: './custom-tester.html',\n      orchestratorScripts: [\n        {\n          content: 'console.log(\"Hello, World\");globalThis.__injected = []',\n          type: 'text/javascript',\n        },\n        {\n          content: 'import \"./injected.ts\"',\n        },\n        {\n          content: 'if(__injected[0] !== 2) throw new Error(\"injected not working\")',\n        },\n      ],\n      commands: {\n        myCustomCommand,\n        stripVTControlCharacters,\n        async startTrace(ctx) {\n          await ctx.page.context().tracing.start({ screenshots: true, snapshots: true })\n        },\n        async stopTrace(ctx) {\n          await ctx.page.context().tracing.stop({ path: 'trace.zip' })\n        },\n      },\n    },\n    tags: [\n      { name: 'e2e', priority: 10 },\n      { name: 'test', priority: 5 },\n      { name: 'browser', priority: 1 },\n    ],\n    alias: {\n      '#src': resolve(dir, './src'),\n    },\n    open: false,\n    diff: './custom-diff-config.ts',\n    outputFile: {\n      html: './html/index.html',\n      json: './browser.json',\n    },\n    onConsoleLog(log) {\n      if (log.includes('MESSAGE ADDED')) {\n        return false\n      }\n    },\n    typecheck: {\n      enabled: true,\n      include: ['test/*.test-d.ts'],\n      ignoreSourceErrors: true,\n    },\n  },\n  plugins: [\n    {\n      name: 'test-no-transform-ui',\n      transform(_code, id, _options) {\n        if (id.includes('/__vitest__/')) {\n          throw new Error(`Unexpected transform: ${id}`)\n        }\n      },\n    },\n    {\n      name: 'test-early-transform',\n      async configureServer(server) {\n        await server.ssrLoadModule('/package.json')\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "test/browser/vitest.config.unit.mts",
    "content": "import type { TestSpecification } from 'vitest/node'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: ['specs/**/*.{spec,test}.ts'],\n    pool: 'threads',\n    fileParallelism: false,\n    reporters: 'verbose',\n    setupFiles: ['./setup.unit.ts'],\n    // 3 is the maximum of browser instances - in a perfect world they will run in parallel\n    hookTimeout: process.env.CI ? 120_000 * 3 : 20_000,\n    testTimeout: process.env.CI ? 120_000 * 3 : 20_000,\n    sequence: {\n      sequencer: class Sequencer {\n        sort(specifications: TestSpecification[]) {\n          return specifications.sort((spec1, spec2) => {\n            // just sort by name, ignore the cache optimization\n            return spec1.moduleId.localeCompare(spec2.moduleId)\n          })\n        }\n\n        shard(): TestSpecification[] {\n          throw new Error('not supported')\n        }\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "test/cli/.gitignore",
    "content": "sonar-config.xml"
  },
  {
    "path": "test/cli/custom.ts",
    "content": "import type { Environment } from 'vitest/runtime'\nimport vm from 'node:vm'\nimport { createDebug } from 'obug'\n\n// test that external packages (obug) are loaded correctly\nconst log = createDebug('test:env')\n\nexport default <Environment>{\n  name: 'custom',\n  viteEnvironment: 'ssr',\n  setupVM({ custom }) {\n    const context = vm.createContext({\n      testEnvironment: 'custom',\n      option: custom.option,\n      setTimeout,\n      clearTimeout,\n    })\n    return {\n      getVmContext() {\n        return context\n      },\n      teardown() {\n        delete context.testEnvironment\n        delete context.option\n      },\n    }\n  },\n  setup(global, { custom }) {\n    global.testEnvironment = 'custom'\n    global.option = custom.option\n    return {\n      teardown() {\n        delete global.testEnvironment\n        delete global.option\n\n        if (global.__exists) {\n          log('should not log')\n        }\n      },\n    }\n  },\n}\n"
  },
  {
    "path": "test/cli/deps/dep-invalid/package.json",
    "content": "{\n  \"name\": \"test-dep-invalid\",\n  \"private\": true\n}\n"
  },
  {
    "path": "test/cli/deps/dep-simple/index.js",
    "content": "export default 'test-dep-simple'\n"
  },
  {
    "path": "test/cli/deps/dep-simple/package.json",
    "content": "{\n  \"name\": \"test-dep-simple\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"exports\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/cli/deps/dep-url/index.js",
    "content": "export const importMetaUrl = import.meta.url\n"
  },
  {
    "path": "test/cli/deps/dep-url/package.json",
    "content": "{\n  \"name\": \"@test/test-dep-url\",\n  \"type\": \"module\",\n  \"exports\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/cli/deps/error/index.js",
    "content": "import 'node:path'\n\nexport default function testStack() {\n  innerTestStack()\n}\n\nimport 'node:util'\n\nfunction innerTestStack() {\n  throw new Error('__TEST_STACK__')\n}\n"
  },
  {
    "path": "test/cli/deps/error/package.json",
    "content": "{\n  \"name\": \"@test/test-dep-error\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./*\": \"./*\"\n  }\n}\n"
  },
  {
    "path": "test/cli/deps/error/transpiled-inline.js",
    "content": "import \"node:path\";\nexport default function testStack() {\n  innerTestStack();\n}\nimport \"node:util\";\nfunction innerTestStack() {\n  throw new Error(\"__TEST_STACK_TRANSPILED_INLINE__\");\n}\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidHJhbnNwaWxlZC1pbmxpbmUudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCAnbm9kZTpwYXRoJ1xuXG5leHBvcnQgdHlwZSBEdW1teSA9IHtcbiAgZm9vOiBcImZvb1wiLFxufVxuXG4vKipcbiAqIGR1bW15XG4gKiBkdW1teVxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiB0ZXN0U3RhY2soKSB7XG4gIGlubmVyVGVzdFN0YWNrKClcbn1cblxuaW1wb3J0ICdub2RlOnV0aWwnXG5cbi8qKlxuICogYmFyXG4gKiBiYXJcbiAqL1xuZnVuY3Rpb24gaW5uZXJUZXN0U3RhY2soKSB7XG4gIHRocm93IG5ldyBFcnJvcignX19URVNUX1NUQUNLX1RSQU5TUElMRURfSU5MSU5FX18nKVxufSJdLAogICJtYXBwaW5ncyI6ICJBQUFBLE9BQU87QUFVUCx3QkFBd0IsWUFBWTtBQUNsQyxpQkFBZTtBQUNqQjtBQUVBLE9BQU87QUFNUCxTQUFTLGlCQUFpQjtBQUN4QixRQUFNLElBQUksTUFBTSxrQ0FBa0M7QUFDcEQ7IiwKICAibmFtZXMiOiBbXQp9Cg==\n"
  },
  {
    "path": "test/cli/deps/error/transpiled-inline.ts",
    "content": "import 'node:path'\n\nexport type Dummy = {\n  foo: \"foo\",\n}\n\n/**\n * dummy\n * dummy\n */\nexport default function testStack() {\n  innerTestStack()\n}\n\nimport 'node:util'\n\n/**\n * bar\n * bar\n */\nfunction innerTestStack() {\n  throw new Error('__TEST_STACK_TRANSPILED_INLINE__')\n}\n\n// transpiled-inline.js is copied from\n// https://esbuild.github.io/try/#dAAwLjI1LjAALS1sb2FkZXI9dHMgLS1zb3VyY2VtYXA9aW5saW5lIC0tc291cmNlZmlsZT10cmFuc3BpbGVkLWlubGluZS50cwBpbXBvcnQgJ25vZGU6cGF0aCcKCmV4cG9ydCB0eXBlIER1bW15ID0gewogIGZvbzogImZvbyIsCn0KCi8qKgogKiBkdW1teQogKiBkdW1teQogKi8KZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdGVzdFN0YWNrKCkgewogIGlubmVyVGVzdFN0YWNrKCkKfQoKaW1wb3J0ICdub2RlOnV0aWwnCgovKioKICogYmFyCiAqIGJhcgogKi8KZnVuY3Rpb24gaW5uZXJUZXN0U3RhY2soKSB7CiAgdGhyb3cgbmV3IEVycm9yKCdfX1RFU1RfU1RBQ0tfVFJBTlNQSUxFRF9JTkxJTkVfXycpCn0\n"
  },
  {
    "path": "test/cli/deps/error/transpiled.js",
    "content": "import \"node:path\";\nexport default function testStack() {\n  innerTestStack();\n}\nimport \"node:util\";\nfunction innerTestStack() {\n  throw new Error(\"__TEST_STACK_TRANSPILED__\");\n}\n//# sourceMappingURL=transpiled.js.map\n"
  },
  {
    "path": "test/cli/deps/error/transpiled.ts",
    "content": "import 'node:path'\n\nexport type Dummy = {\n  foo: \"foo\",\n}\n\n/**\n * dummy\n * dummy\n */\nexport default function testStack() {\n  innerTestStack()\n}\n\nimport 'node:util'\n\n/**\n * bar\n * bar\n */\nfunction innerTestStack() {\n  throw new Error('__TEST_STACK_TRANSPILED__')\n}\n\n// transpiled.js and transpiled.js.map are copied from\n// https://esbuild.github.io/try/#dAAwLjI1LjAALS1sb2FkZXI9dHMgLS1zb3VyY2VtYXAgLS1zb3VyY2VmaWxlPXRyYW5zcGlsZWQudHMAaW1wb3J0ICdub2RlOnBhdGgnCgpleHBvcnQgdHlwZSBEdW1teSA9IHsKICBmb286ICJmb28iLAp9CgovKioKICogZHVtbXkKICogZHVtbXkKICovCmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIHRlc3RTdGFjaygpIHsKICBpbm5lclRlc3RTdGFjaygpCn0KCmltcG9ydCAnbm9kZTp1dGlsJwoKLyoqCiAqIGJhcgogKiBiYXIKICovCmZ1bmN0aW9uIGlubmVyVGVzdFN0YWNrKCkgewogIHRocm93IG5ldyBFcnJvcignX19URVNUX1NUQUNLX1RSQU5TUElMRURfXycpCn0\n"
  },
  {
    "path": "test/cli/deps/error/ts.ts",
    "content": "import 'node:path'\n\nexport type Dummy = {\n  foo: \"foo\",\n}\n\n/**\n * dummy\n * dummy\n */\nexport default function testStack() {\n  innerTestStack()\n}\n\nimport 'node:util'\n\n/**\n * bar\n * bar\n */\nfunction innerTestStack() {\n  throw new Error('__TEST_STACK_TS__')\n}\n"
  },
  {
    "path": "test/cli/deps/linked/index.ts",
    "content": "export default 'ok' satisfies string\n"
  },
  {
    "path": "test/cli/deps/linked/package.json",
    "content": "{\n  \"name\": \"@test/test-dep-linked\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"exports\": {\n    \"./ts\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "test/cli/deps/pkg-reporter/index.js",
    "content": "export default class PackageReporter {\n  onInit(ctx) {\n    this.ctx = ctx\n  }\n\n  onTestRunEnd() {\n    this.ctx.logger.log('hello from package reporter')\n  }\n}\n"
  },
  {
    "path": "test/cli/deps/pkg-reporter/package.json",
    "content": "{\n  \"name\": \"@test/pkg-reporter\",\n  \"main\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/cli/dts/_shared/happy-dom-patch.ts",
    "content": "// happy-dom's dts will break `skipLibCheck: false`.\n// for now, override happy-dom type for the sake of testing other packages.\nexport const Window = {} as any\n"
  },
  {
    "path": "test/cli/dts/_shared/tsconfig.patch.json",
    "content": "{\n  \"compilerOptions\": {\n    \"paths\": {\n      \"happy-dom\": [\"./happy-dom-patch.ts\"]\n    }\n  }\n}\n"
  },
  {
    "path": "test/cli/dts/browser-playwright/package.json",
    "content": "{\n  \"name\": \"@vitest/test-integration-dts-browser-playwright\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"tsc -b\"\n  },\n  \"devDependencies\": {\n    \"@vitest/browser-playwright\": \"workspace:*\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/cli/dts/browser-playwright/src/basic.test.ts",
    "content": "import { test } from 'vitest'\nimport { page, userEvent } from 'vitest/browser'\n\ntest('basic', async () => {\n  document.body.innerHTML = `<button>hello</button>`\n  await userEvent.click(page.getByRole('button'), { force: true })\n})\n"
  },
  {
    "path": "test/cli/dts/browser-playwright/tsconfig.json",
    "content": "{\n  \"extends\": [\"../_shared/tsconfig.patch.json\"],\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"noEmit\": true\n  },\n  \"include\": [\"src\", \"*.ts\"]\n}\n"
  },
  {
    "path": "test/cli/dts/browser-playwright/vite.config.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright({\n        launchOptions: {\n          timeout: 1234,\n          // @ts-expect-error test type error\n          slowMo: 'wrong',\n        },\n      }),\n      instances: [\n        {\n          browser: 'chromium',\n          provider: playwright({\n            launchOptions: {\n              timeout: 1234,\n              // @ts-expect-error test type error\n              slowMo: 'wrong',\n            },\n          }),\n        },\n      ],\n    },\n  },\n})\n"
  },
  {
    "path": "test/cli/dts/config/package.json",
    "content": "{\n  \"name\": \"@vitest/test-integration-dts-config\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"tsc -b\"\n  },\n  \"devDependencies\": {\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/cli/dts/config/tsconfig.json",
    "content": "{\n  \"extends\": [\"../_shared/tsconfig.patch.json\"],\n  \"compilerOptions\": {\n    \"noUncheckedSideEffectImports\": true,\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"types\": [],\n    \"strict\": true,\n    \"noEmit\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "test/cli/dts/config/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/dts/exact-optional-property/package.json",
    "content": "{\n  \"name\": \"@vitest/test-integration-dts-exact-optional-property\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"tsc -b\"\n  },\n  \"devDependencies\": {\n    \"@vitest/runner\": \"workspace:*\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/cli/dts/exact-optional-property/src/reporter.ts",
    "content": "import type { File } from '@vitest/runner'\nimport { DefaultReporter } from 'vitest/reporters'\n\nexport class MyReporter extends DefaultReporter {\n  override reportTestSummary(files: File[], errors: unknown[], leakCount: number): void {\n    super.reportTestSummary(files, errors, leakCount)\n  }\n}\n"
  },
  {
    "path": "test/cli/dts/exact-optional-property/src/runner.ts",
    "content": "import type { VitestRunner } from '@vitest/runner'\nimport { VitestTestRunner } from 'vitest/runners'\n\nexport class MyRunner extends VitestTestRunner implements VitestRunner {}\n"
  },
  {
    "path": "test/cli/dts/exact-optional-property/tsconfig.json",
    "content": "{\n  \"extends\": [\"../_shared/tsconfig.patch.json\"],\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"exactOptionalPropertyTypes\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"outDir\": \"dist\",\n    \"sourceMap\": true,\n    \"verbatimModuleSyntax\": true,\n    \"skipLibCheck\": true\n  }\n}\n"
  },
  {
    "path": "test/cli/dts/fixture-extend/package.json",
    "content": "{\n  \"name\": \"@vitest/test-integration-dts-fixture-extend\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"build\": \"premove dist && tsc -p tsconfig.json\",\n    \"check\": \"tsc -p tsconfig.check.json\",\n    \"test\": \"pnpm build && pnpm check\"\n  },\n  \"devDependencies\": {\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/cli/dts/fixture-extend/src/repro.ts",
    "content": "import { test } from 'vitest'\n\nexport const myTest = test.extend<{ now: number }>({\n  now: async ({}, use) => {\n    await use(Date.now())\n  },\n})\n"
  },
  {
    "path": "test/cli/dts/fixture-extend/tsconfig.check.json",
    "content": "{\n  \"extends\": [\"../_shared/tsconfig.patch.json\"],\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\",\n    \"types\": [],\n    \"strict\": true,\n    \"noEmit\": true,\n    \"verbatimModuleSyntax\": true\n  },\n  \"include\": [\"dist\"]\n}\n"
  },
  {
    "path": "test/cli/dts/fixture-extend/tsconfig.json",
    "content": "{\n  \"extends\": [\"../_shared/tsconfig.patch.json\"],\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"outDir\": \"dist\",\n    \"sourceMap\": true,\n    \"verbatimModuleSyntax\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "test/cli/fixtures/assertion-helper/basic.test.ts",
    "content": "import { expect, test, vi } from \"vitest\";\n\nconst myEqual = vi.defineHelper((a: any, b: any) => {\n  expect(a).toEqual(b);\n});\n\nconst myEqualAsync = vi.defineHelper(async (a: any, b: any) => {\n  await new Promise((r) => setTimeout(r, 1));\n  expect(a).toEqual(b);\n});\n\nconst myEqualSoft = vi.defineHelper((a: any, b: any) => {\n  expect.soft(a).toEqual(b);\n});\n\nconst myEqualSoftAsync = vi.defineHelper(async (a: any, b: any) => {\n  await new Promise((r) => setTimeout(r, 1));\n  expect.soft(a).toEqual(b);\n});\n\ntest(\"sync\", () => {\n  myEqual(\"sync\", \"x\");\n});\n\ntest(\"async\", async () => {\n  await myEqualAsync(\"async\", \"x\");\n});\n\ntest(\"soft\", () => {\n  myEqualSoft(\"soft\", \"x\");\n});\n\ntest(\"soft async\", async () => {\n  await myEqualSoftAsync(\"soft async\", \"x\");\n});\n\n// Nested helpers: outermost marker wins\nconst innerHelper = vi.defineHelper((a: any, b: any) => {\n  expect(a).toEqual(b);\n});\nconst outerHelper = vi.defineHelper((a: any, b: any) => {\n  innerHelper(a, b);\n});\n\ntest(\"nested\", () => {\n  outerHelper(\"nested\", \"x\");\n});\n\n// Helper that passes\ntest(\"pass sync\", () => {\n  myEqual(1, 1);\n});\n\ntest(\"pass async\", async () => {\n  await myEqualAsync(1, 1);\n});\n\n// Helper returning value\nconst myAdd = vi.defineHelper((a: number, b: number) => {\n  return a + b;\n});\nconst myAddAsync = vi.defineHelper(async (a: number, b: number) => {\n  await new Promise((r) => setTimeout(r, 1));\n  return a + b;\n});\n\ntest(\"return sync\", () => {\n  expect(myAdd(1, 2)).toBe(3);\n});\n\ntest(\"return async\", async () => {\n  expect(await myAddAsync(1, 2)).toBe(3);\n});\n\n// Multiple soft errors in one test\ntest(\"multiple soft\", () => {\n  myEqualSoft(\"first\", \"x\");\n  myEqualSoft(\"second\", \"y\");\n});\n\n// Custom error in helper\nconst throwCustom = vi.defineHelper(() => {\n  throw new Error(\"custom error from helper\");\n});\n\ntest(\"custom error\", () => {\n  throwCustom();\n});\n\n// non-helper wrapper calling a helper: stack should include the wrapper\nfunction assertEqualValues(a: any, b: any) {\n  myEqual(a, b);\n}\n\ntest(\"non-helper wrapper\", () => {\n  assertEqualValues(\"wrapper\", \"x\");\n});\n\n// printConsoleTrace also hides internal stacks\nconst myHelperWithLogs = vi.defineHelper(() => {\n  console.error(\"[test-myHelperWithLogs]\");\n});\n\ntest(\"helper with logs\", () => {\n  myHelperWithLogs();\n});\n"
  },
  {
    "path": "test/cli/fixtures/bail-race/a.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('adds two numbers', () => {\n  expect(2 + 3).toBe(5)\n})\n\ntest('fails adding two numbers', () => {\n  expect(2 + 3).toBe(6)\n})\n"
  },
  {
    "path": "test/cli/fixtures/bail-race/b.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('does not run', () => {\n  throw new Error(\"Should never run\")\n})\n"
  },
  {
    "path": "test/cli/fixtures/basic/basic.test.ts",
    "content": "import { expect, test } from 'vitest';\n\ntest('basic test', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/basic/base.bench.ts",
    "content": "import { bench, describe } from 'vitest'\n\ndescribe('sort', () => {\n  bench('normal', () => {\n    const x = [1, 5, 4, 2, 3]\n    x.sort((a, b) => {\n      return a - b\n    })\n  }, { iterations: 5, time: 0 })\n\n  bench('reverse', () => {\n    const x = [1, 5, 4, 2, 3]\n    x.reverse().sort((a, b) => {\n      return a - b\n    })\n  }, { iterations: 5, time: 0 })\n\n  // TODO: move to failed tests\n  // should not be collected\n  // it('test', () => {\n  //   expect(1 + 1).toBe(3)\n  // })\n})\n\nfunction timeout(time: number) {\n  return new Promise((resolve) => {\n    setTimeout(resolve, time)\n  })\n}\n\ndescribe('timeout', () => {\n  bench('timeout100', async () => {\n    await timeout(100)\n  }, {\n    setup() {\n\n    },\n    teardown() {\n\n    },\n    ...benchOptions\n  })\n\n  bench('timeout75', async () => {\n    await timeout(75)\n  }, benchOptions)\n\n  bench('timeout50', async () => {\n    await timeout(50)\n  }, benchOptions)\n\n  bench('timeout25', async () => {\n    await timeout(25)\n  }, benchOptions)\n\n  // TODO: move to failed tests\n  // test('reduce', () => {\n  //   expect(1 - 1).toBe(2)\n  // })\n})\n\nconst benchOptions = {\n  time: 0,\n  iterations: 3,\n  warmupIterations: 0,\n  warmupTime: 0,\n}\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/basic/mode.bench.ts",
    "content": "import { bench, describe } from 'vitest'\n\ndescribe.todo('unimplemented suite')\n\ndescribe.skip('skipped', () => {\n  bench('skipped', () => {\n    throw new Error('should be skipped')\n  })\n\n  bench.todo('unimplemented test')\n})\n\nbench.skip('skipped', () => {\n  throw new Error('should be skipped')\n})\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/basic/only.bench.ts",
    "content": "import { bench, describe, expect, assert } from 'vitest'\n\nconst run = [false, false, false, false, false]\n\ndescribe('a0', () => {\n  bench.only('0', () => {\n    run[0] = true\n  }, { iterations: 1, time: 0 })\n  bench('s0', () => {\n    expect(true).toBe(false)\n  })\n})\n\ndescribe('a1', () => {\n  describe('b1', () => {\n    describe('c1', () => {\n      bench.only('1', () => {\n        run[1] = true\n      }, { iterations: 1, time: 0 })\n    })\n    bench('s1', () => {\n      expect(true).toBe(false)\n    })\n  })\n})\n\ndescribe.only('a2', () => {\n  bench('2', () => {\n    run[2] = true\n  }, { iterations: 1, time: 0 })\n})\n\nbench('s2', () => {\n  expect(true).toBe(false)\n})\n\ndescribe.only('a3', () => {\n  describe('b3', () => {\n    bench('3', () => {\n      run[3] = true\n    }, { iterations: 1, time: 0 })\n  })\n  bench.skip('s3', () => {\n    expect(true).toBe(false)\n  })\n})\n\ndescribe('a4', () => {\n  describe.only('b4', () => {\n    bench('4', () => {\n      run[4] = true\n    }, { iterations: 1, time: 0 })\n  })\n  describe('sb4', () => {\n    bench('s4', () => {\n      expect(true).toBe(false)\n    })\n  })\n})\n\nbench.only(\n  'visited',\n  () => {\n    assert.deepEqual(run, [true, true, true, true, true])\n  },\n  { iterations: 1, time: 0 },\n)\n\nbench.only(\n  'visited2',\n  () => {\n    assert.deepEqual(run, [true, true, true, true, true])\n  },\n  { iterations: 1, time: 0 },\n)\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/basic/should-not-run.test-d.ts",
    "content": "import { describe, expectTypeOf, test } from 'vitest'\n\ndescribe('test', () => {\n  test('some-test', () => {\n    expectTypeOf({ a: 1 }).toEqualTypeOf({ a: \"should not match\" })\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/basic/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/compare/basic.bench.ts",
    "content": "import { bench, describe } from 'vitest'\n\nconst sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));\n\ndescribe('suite', () => {\n  bench('sleep10', async () => {\n    await sleep(10)\n  }, { time: 20, iterations: 0 })\n\n  bench('sleep100', async () => {\n    await sleep(100);\n  }, { time: 200, iterations: 0 })\n})\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/compare/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/reporter/multiple.bench.ts",
    "content": "import { bench, describe } from 'vitest'\nimport { setTimeout } from 'node:timers/promises'\n\nconst options = { iterations: 1, warmupIterations: 1 }\n\nbench('first', async () => {\n  await setTimeout(500)\n}, options)\n\nbench('second', async () => {\n  await setTimeout(500)\n}, options)\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/reporter/summary.bench.ts",
    "content": "import { bench, describe } from 'vitest'\n\ndescribe('suite-a', () => {\n  bench('good', async () => {\n    await sleep(10)\n  }, options)\n\n  bench('bad', async () => {\n    await sleep(300)\n  }, options)\n})\n\ndescribe('suite-b', () => {\n  bench('good', async () => {\n    await sleep(25)\n  }, options)\n\n  describe('suite-b-nested', () => {\n    bench('good', async () => {\n      await sleep(50)\n    }, options)\n  })\n})\n\nconst sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));\n\nconst options = {\n  time: 0,\n  iterations: 2,\n  warmupIterations: 0,\n  warmupTime: 0,\n}\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/reporter/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/sequential/f1.bench.ts",
    "content": "import { bench, describe } from \"vitest\"\nimport { appendLog, benchOptions, sleepBench } from \"./helper\";\n\nbench(\"B1\", async () => {\n  await appendLog(\"F1 / B1\")\n  await sleepBench();\n}, benchOptions)\n\ndescribe(\"S1\", () => {\n  bench(\"B1\", async () => {\n    await appendLog(\"F1 / S1 / B1\")\n    await sleepBench();\n  }, benchOptions)\n\n  bench(\"B2\", async () => {\n    await appendLog(\"F1 / S1 / B2\")\n    await sleepBench();\n  }, benchOptions)\n})\n\ndescribe(\"S2\", () => {\n  bench(\"B1\", async () => {\n    await appendLog(\"F1 / S2 / B1\")\n    await sleepBench();\n  }, benchOptions)\n})\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/sequential/f2.bench.ts",
    "content": "import { bench, describe } from \"vitest\"\nimport { appendLog, benchOptions, sleepBench } from \"./helper\";\n\ndescribe(\"S1\", () => {\n  bench(\"B1\", async () => {\n    await appendLog(\"F2 / S1 / B1\")\n    await sleepBench();\n  }, benchOptions)\n})\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/sequential/helper.ts",
    "content": "import fs from \"node:fs\";\n\nconst SLEEP_BENCH_MS = Number(process.env[\"SLEEP_BENCH_MS\"] || 10);\nconst BENCH_ITERATIONS = Number(process.env[\"BENCH_ITERATIONS\"] || 3);\n\nexport const sleepBench = () => new Promise(resolve => setTimeout(resolve, SLEEP_BENCH_MS))\n\nexport const testLogFile = new URL(\"./test.log\", import.meta.url);\n\nexport async function appendLog(data: string) {\n  await fs.promises.appendFile(testLogFile, data + \"\\n\");\n}\n\nexport const benchOptions = {\n  time: 0,\n  iterations: BENCH_ITERATIONS,\n  warmupIterations: 0,\n  warmupTime: 0,\n}\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/sequential/setup.ts",
    "content": "import fs from \"node:fs\";\nimport { testLogFile } from \"./helper\";\n\nexport default async function setup() {\n  await fs.promises.rm(testLogFile, { force: true });\n}\n"
  },
  {
    "path": "test/cli/fixtures/benchmarking/sequential/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\"\n\n// to see the difference better, increase sleep time and iterations e.g. by\n// SLEEP_BENCH_MS=100 pnpm -C test/benchmark test bench -- --root fixtures/sequential --fileParallelism\n\nexport default defineConfig({\n  test: {\n    globalSetup: [\"./setup.ts\"]\n  }\n});\n"
  },
  {
    "path": "test/cli/fixtures/browser-init/package.json",
    "content": "{\n  \"scripts\": {\n    \"test:browser\": \"vitest --config=vitest.browser.config.ts\"\n  },\n  \"dependencies\": {\n    \"vitest\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@vitest/browser-preview\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/browser-init/vitest.config.ts",
    "content": "{}"
  },
  {
    "path": "test/cli/fixtures/browser-multiple/basic.test.js",
    "content": "import { test } from 'vitest';\n\ntest('passes', () => {})\n"
  },
  {
    "path": "test/cli/fixtures/browser-multiple/package.json",
    "content": "{\n  \"name\": \"browser-multiple\"\n}"
  },
  {
    "path": "test/cli/fixtures/browser-multiple/vitest.config.ts",
    "content": "import { playwright } from '@vitest/browser-playwright';\nimport { resolve } from 'pathe';\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        cacheDir: resolve(import.meta.dirname, 'basic-1'),\n        test: {\n          name: 'basic-1',\n          dir: import.meta.dirname,\n          include: ['./basic.test.js'],\n          browser: {\n            enabled: true,\n            instances: [{ browser: 'chromium' }],\n            provider: playwright(),\n            headless: true,\n          }\n        }\n      },\n      {\n        cacheDir: resolve(import.meta.dirname, 'basic-2'),\n        test: {\n          name: 'basic-2',\n          dir: import.meta.dirname,\n          include: ['./basic.test.js'],\n          browser: {\n            enabled: true,\n            instances: [{ browser: 'chromium' }],\n            provider: playwright(),\n            headless: true,\n          }\n        }\n      },\n    ],\n  },\n})"
  },
  {
    "path": "test/cli/fixtures/caching/dynamic-cache-key/replaced.test.js",
    "content": "import { test, expect } from 'vitest'\n\ntest('replaced variable is the same', () => {\n  expect(__REPLACED__).toBe(process.env.REPLACED)\n})\n"
  },
  {
    "path": "test/cli/fixtures/caching/dynamic-cache-key/vitest.config.bails.js",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'test:replacer',\n      transform(code) {\n        return code.replace('__REPLACED__', JSON.stringify(process.env.REPLACED))\n      },\n      configureVitest(ctx) {\n        ctx.experimental_defineCacheKeyGenerator(() => {\n          return false\n        })\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "test/cli/fixtures/caching/dynamic-cache-key/vitest.config.fails.js",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'test:replacer',\n      transform(code) {\n        return code.replace('__REPLACED__', JSON.stringify(process.env.REPLACED))\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "test/cli/fixtures/caching/dynamic-cache-key/vitest.config.passes.js",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'test:replacer',\n      transform(code) {\n        return code.replace('__REPLACED__', JSON.stringify(process.env.REPLACED))\n      },\n      configureVitest(ctx) {\n        ctx.experimental_defineCacheKeyGenerator(() => {\n          return String(process.env.REPLACED)\n        })\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "test/cli/fixtures/caching/import-meta-glob/glob.test.js",
    "content": "import { test, expect, inject } from 'vitest'\n\ntest('replaced variable is the same', () => {\n  const files = import.meta.glob('./generated/*')\n  expect(Object.keys(files)).toEqual(inject('generated'))\n})\n"
  },
  {
    "path": "test/cli/fixtures/caching/import-meta-glob/vitest.config.js",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/cancel-run/blocked-test-cases.test.ts",
    "content": "import { afterEach, describe, test } from 'vitest'\n\nafterEach(async (context) => {\n  (context.task.meta as any).afterEachDone = true\n})\n\ndescribe('these should pass', () => {\n  test('one', async () => {})\n  test('two', async () => {})\n})\n\ntest('this test starts and gets cancelled, its after each should be called', async ({ annotate }) => {\n  await annotate('Running long test, do the cancelling now!')\n\n  await new Promise(resolve => setTimeout(resolve, 100_000))\n})\n\ndescribe('these should not start but should be skipped', () => {\n  test('third, no after each expected', async () => {})\n\n  describe(\"nested\", () => {\n    test('fourth, no after each expected', async () => {})\n  });\n})\n\ntest('fifth, no after each expected', async () => {})"
  },
  {
    "path": "test/cli/fixtures/cancel-run/blocked-thread.test.ts",
    "content": "import { execSync } from 'node:child_process'\nimport { test } from 'vitest'\n\ntest('block whole test runner thread/process', { timeout: 30_000 }, async () => {\n  // Note that this can also block the RPC before onTestCaseReady is emitted to main thread\n  execSync(\"sleep 40\")\n})\n"
  },
  {
    "path": "test/cli/fixtures/config/bail/test/first.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('1 - first.test.ts - this should pass', async () => {\n  await new Promise(resolve => setTimeout(resolve, 250))\n  expect(true).toBeTruthy()\n})\n\ntest('2 - first.test.ts - this should fail', () => {\n  expect(false).toBeTruthy()\n})\n\ntest('3 - first.test.ts - this should be skipped', () => {\n  expect(true).toBeTruthy()\n})\n"
  },
  {
    "path": "test/cli/fixtures/config/bail/test/second.test.ts",
    "content": "import { expect, test } from 'vitest'\n\n// When using multi threads/forks the first test will start before failing.test.ts fails\nconst isThreads = import.meta.env.THREADS === 'true'\n\ntest(`1 - second.test.ts - this should ${isThreads ? 'pass' : 'be skipped'}`, async () => {\n  await new Promise(resolve => setTimeout(resolve, 1500))\n  expect(true).toBeTruthy()\n})\n\ntest('2 - second.test.ts - this should be skipped', () => {\n  expect(true).toBeTruthy()\n})\n\ntest('3 - second.test.ts - this should be skipped', () => {\n  expect(true).toBeTruthy()\n})\n"
  },
  {
    "path": "test/cli/fixtures/config/bail/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport type { TestSpecification } from 'vitest/node'\n\nclass TestNameSequencer {\n  async sort(files: TestSpecification[]): Promise<TestSpecification[]> {\n    return [...files].sort((a, b) => {\n      if (a.moduleId > b.moduleId)\n        return 1\n\n      if (a.moduleId < b.moduleId)\n        return -1\n\n      return 0\n    })\n  }\n\n  public async shard(files: TestSpecification[]): Promise<TestSpecification[]> {\n    return files\n  }\n}\n\nexport default defineConfig({\n  test: {\n    reporters: 'verbose',\n    cache: false,\n    watch: false,\n    sequence: {\n      sequencer: TestNameSequencer,\n    },\n    browser: {\n      headless: true,\n      instances: [],\n    },\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/config/browser-custom-html/browser-basic.test.ts",
    "content": "import { test, expect } from 'vitest';\n\ntest('basic', async () => {\n  const div = document.createElement('div')\n  div.textContent = ' Vitest'\n  document.body.appendChild(div)\n  expect(document.body.textContent).toContain('HELLO WORLD')\n  expect(document.body.textContent).toContain('Vitest')\n})\n"
  },
  {
    "path": "test/cli/fixtures/config/browser-custom-html/browser-custom.test.ts",
    "content": "import { test, expect } from 'vitest';\n\ntest('custom', () => {\n  expect(window).toHaveProperty('CUSTOM_INJECTED', true)\n})\n\ntest('importmap is injected', () => {\n  expect(import.meta.resolve('some-lib')).toBe('https://vitest.dev/some-lib')\n})\n"
  },
  {
    "path": "test/cli/fixtures/config/browser-custom-html/custom-html.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Document</title>\n</head>\n<body>\n  HELLO WORLD\n</body>\n</html>"
  },
  {
    "path": "test/cli/fixtures/config/browser-custom-html/vitest.config.correct.ts",
    "content": "import { playwright } from '@vitest/browser-playwright';\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    include: ['browser-basic.test.ts'],\n    browser: {\n      instances: [{ browser: 'chromium' }],\n      enabled: true,\n      headless: true,\n      provider: playwright(),\n      testerHtmlPath: './custom-html.html'\n    },\n  },\n})"
  },
  {
    "path": "test/cli/fixtures/config/browser-custom-html/vitest.config.custom-transformIndexHtml.ts",
    "content": "import { playwright } from '@vitest/browser-playwright';\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'test:html',\n      transformIndexHtml() {\n        return [\n          {\n            tag: 'script',\n            injectTo: 'head-prepend',\n            attrs: {\n              type: 'importmap'\n            },\n            children: JSON.stringify({\n              \"imports\": {\n                \"some-lib\": \"https://vitest.dev/some-lib\",\n              },\n            })\n          },\n          {\n            tag: 'script',\n            children: 'window.CUSTOM_INJECTED = true',\n            injectTo: 'head',\n          },\n        ]\n      },\n    },\n  ],\n  test: {\n    include: ['./browser-custom.test.ts'],\n    browser: {\n      instances: [{ browser: 'chromium' }],\n      enabled: true,\n      headless: true,\n      provider: playwright(),\n      testerHtmlPath: './custom-html.html',\n    },\n  },\n})"
  },
  {
    "path": "test/cli/fixtures/config/browser-custom-html/vitest.config.default-transformIndexHtml.ts",
    "content": "import { playwright } from '@vitest/browser-playwright';\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'test:html',\n      transformIndexHtml() {\n        return [\n          {\n            tag: 'script',\n            injectTo: 'head-prepend',\n            attrs: {\n              type: 'importmap'\n            },\n            children: JSON.stringify({\n              \"imports\": {\n                \"some-lib\": \"https://vitest.dev/some-lib\",\n              },\n            })\n          },\n          {\n            tag: 'script',\n            children: 'window.CUSTOM_INJECTED = true',\n            injectTo: 'head',\n          }\n        ]\n      },\n    },\n  ],\n  test: {\n    include: ['./browser-custom.test.ts'],\n    browser: {\n      instances: [{ browser: 'chromium' }],\n      enabled: true,\n      headless: true,\n      provider: playwright(),\n    },\n  },\n})"
  },
  {
    "path": "test/cli/fixtures/config/browser-custom-html/vitest.config.error-hook.ts",
    "content": "import { playwright } from '@vitest/browser-playwright';\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'test:html',\n      transformIndexHtml() {\n        throw new Error('expected error in transformIndexHtml')\n      },\n    },\n  ],\n  test: {\n    include: ['./browser-basic.test.ts'],\n    browser: {\n      instances: [{ browser: 'chromium' }],\n      enabled: true,\n      headless: true,\n      provider: playwright(),\n      testerHtmlPath: './custom-html.html'\n    },\n  },\n})"
  },
  {
    "path": "test/cli/fixtures/config/browser-custom-html/vitest.config.non-existing.ts",
    "content": "import { playwright } from '@vitest/browser-playwright';\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    browser: {\n      instances: [{ browser: 'chromium' }],\n      enabled: true,\n      headless: true,\n      provider: playwright(),\n      testerHtmlPath: './some-non-existing-path'\n    },\n  },\n})"
  },
  {
    "path": "test/cli/fixtures/config/browser-define/basic.test.ts",
    "content": "import { test, expect } from 'vitest'\n\ntest('passes', () => {\n  expect(process.env.TEST_PROCESS_ENV).toBe('PROCESS_OK')\n  expect(import.meta.env.TEST_META_ENV).toBe('META_OK')\n})\n"
  },
  {
    "path": "test/cli/fixtures/config/browser-define/vitest.config.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nlet config = defineConfig({\n  define: {\n    'process.env.TEST_PROCESS_ENV': JSON.stringify('PROCESS_OK'),\n    'import.meta.env.TEST_META_ENV': JSON.stringify('META_OK'),\n  },\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      headless: true,\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  },\n})\n\nif (process.env.BROWSER_DEFINE_TEST_PROEJCT === \"true\") {\n  config = defineConfig({\n    test: {\n      projects: [config],\n    },\n  })\n}\n\nexport default config\n"
  },
  {
    "path": "test/cli/fixtures/config/watch-trigger-pattern/folder/fs/basic.test.ts",
    "content": "import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { expect, test } from 'vitest';\n\nconst filepath = resolve(import.meta.dirname, './text.txt');\n\ntest('basic', () => {\n  expect(readFileSync(filepath, 'utf-8')).toBe('hello world\\n');\n})\n"
  },
  {
    "path": "test/cli/fixtures/config/watch-trigger-pattern/folder/fs/text.txt",
    "content": "hello world\n"
  },
  {
    "path": "test/cli/fixtures/config/watch-trigger-pattern/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    watchTriggerPatterns: [\n      {\n        pattern: /folder\\/(\\w+)\\/.*\\.txt$/,\n        testsToRun: (id, match) => {\n          return `./folder/${match[1]}/basic.test.ts`;\n        },\n      }\n    ]\n  }\n})"
  },
  {
    "path": "test/cli/fixtures/config-loader/browser/basic.test.ts",
    "content": "import { test } from \"vitest\"\n\ntest(\"browser ok\", () => {})\n"
  },
  {
    "path": "test/cli/fixtures/config-loader/browser/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\"\nimport \"@test/test-dep-linked/ts\";\nimport { playwright } from '@vitest/browser-playwright';\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      headless: true,\n      instances: [\n        {\n          browser: 'chromium',\n        }\n      ]\n    }\n  }\n})\n"
  },
  {
    "path": "test/cli/fixtures/config-loader/node/basic.test.ts",
    "content": "import { test } from \"vitest\"\n\ntest(\"node ok\", () => {})\n"
  },
  {
    "path": "test/cli/fixtures/config-loader/node/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\"\nimport \"@test/test-dep-linked/ts\";\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/config-loader/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\"\nimport \"@test/test-dep-linked/ts\";\n\nexport default defineConfig({\n  test: {\n    projects: [\n      \"browser/vitest.config.ts\",\n      \"node/vitest.config.ts\",\n    ],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/console/trace.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('logging to stdout', () => {\n  console.log('log with trace')\n  console.info('info with trace')\n  console.debug('debug with trace')\n  console.dir({ hello: 'from dir with trace' })\n  console.warn('warn with trace')\n  console.assert(false, 'assert with trace')\n  console.error('error with trace')\n  console.trace('trace with trace')\n})\n"
  },
  {
    "path": "test/cli/fixtures/console/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    printConsoleTrace: true,\n  }\n})"
  },
  {
    "path": "test/cli/fixtures/create-vitest/basic.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"basic\", () => {\n  expect(1).toBe(1);\n})\n"
  },
  {
    "path": "test/cli/fixtures/create-vitest/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/custom-file-env/custom-file-env.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('custom env is defined', () => {\n  expect(expect.getState().environment).toBe('custom')\n  expect((globalThis as any).testEnvironment).toBe('custom')\n  expect((globalThis as any).option).toBe('custom-option')\n})\n"
  },
  {
    "path": "test/cli/fixtures/custom-pool/pool/custom-pool.ts",
    "content": "import type { RunnerTestCase } from 'vitest'\nimport type { PoolWorker, PoolRunnerInitializer, TestProject, Vitest, WorkerRequest, WorkerResponse, PoolOptions } from 'vitest/node'\nimport { createFileTask } from '@vitest/runner/utils'\nimport { normalize } from 'pathe'\nimport EventEmitter from 'node:events';\n\ninterface OptionsCustomPool {\n  print: any;\n  array: any;\n}\n\nexport function createCustomPool(settings: OptionsCustomPool): PoolRunnerInitializer {\n  return {\n    name: 'custom',\n    createPoolWorker: (options) => new CustomRuntimeWorker(options, settings),\n  }\n}\n\nexport class CustomRuntimeWorker implements PoolWorker {\n  public readonly name = 'custom'\n  private vitest: Vitest\n  private customEvents = new EventEmitter()\n  private project: TestProject\n\n  constructor(options: PoolOptions, private settings: OptionsCustomPool) {\n    this.vitest = options.project.vitest\n    this.project = options.project\n  }\n\n  send(request: WorkerRequest) {\n    void onMessage(request, this.project, this.settings).then((response) => {\n      if (response) {\n        this.customEvents.emit('message', response)\n      }\n    })\n  }\n\n  on(event: string, callback: (arg: any) => void): void {\n    this.customEvents.on(event, callback)\n  }\n\n  off(event: string, callback: (arg: any) => void): void {\n    this.customEvents.off(event, callback)\n  }\n\n  deserialize(data: unknown): unknown {\n    return data\n  }\n\n  async start() {\n    // noop\n  }\n\n  async stop() {\n    this.vitest.logger.console.warn('[pool] custom pool is closed!')\n  }\n}\n\nconst __vitest_worker_response__ = true\n\nasync function onMessage(message: WorkerRequest, project: TestProject, options: OptionsCustomPool): Promise<WorkerResponse | void> {\n  if (message?.__vitest_worker_request__ !== true) {\n    return undefined\n  }\n  const vitest = project.vitest\n\n  switch (message.type) {\n    case 'start': {\n      return { type: 'started', __vitest_worker_response__ }\n    }\n\n    case 'run': {\n      vitest.logger.console.warn('[pool] printing:', options.print)\n      vitest.logger.console.warn('[pool] array option', options.array)\n      for (const { filepath: moduleId } of message.context.files) {\n        vitest.state.clearFiles(project)\n        vitest.logger.console.warn('[pool] running tests for', project.name, 'in', normalize(moduleId).toLowerCase().replace(normalize(process.cwd()).toLowerCase(), ''))\n        const taskFile = createFileTask(\n          moduleId,\n          project.config.root,\n          project.name,\n          'custom'\n        )\n        taskFile.mode = 'run'\n        taskFile.result = { state: 'pass' }\n        const taskName = 'custom test'\n        const taskTest: RunnerTestCase = {\n          type: 'test',\n          name: taskName,\n          fullName: `${taskFile.fullName} > ${taskName}`,\n          fullTestName: `${taskFile.fullTestName} > ${taskName}`,\n          id: `${taskFile.id}_0`,\n          context: {} as any,\n          suite: taskFile,\n          mode: 'run',\n          meta: {},\n          annotations: [],\n          artifacts: [],\n          timeout: 0,\n          file: taskFile,\n          result: {\n            state: 'pass',\n          },\n        }\n        taskFile.tasks.push(taskTest)\n        await vitest._reportFileTask(taskFile)\n      }\n\n      return { type: 'testfileFinished', __vitest_worker_response__ }\n    }\n\n    case 'stop': {\n      return { type: 'stopped', __vitest_worker_response__ }\n    }\n  }\n\n  throw new Error(`Unexpected message ${JSON.stringify(message, null, 2)}`)\n}\n"
  },
  {
    "path": "test/cli/fixtures/custom-pool/tests/custom-not-run.spec.ts",
    "content": "throw new Error('this file is not actually running')\n"
  },
  {
    "path": "test/cli/fixtures/custom-pool/tests/custom-run.threads.spec.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('correctly runs threads test while there is a custom pool', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/custom-pool/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport { createCustomPool } from './pool/custom-pool'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        extends: true,\n        test: {\n          name: 'custom-pool-test',\n          pool: createCustomPool({\n            print: 'options are respected',\n            array: [1, 2, 3],\n          }),\n          exclude: ['**/*.threads.spec.ts'],\n        },\n       },\n      {\n        extends: true,\n        test: {\n          name: 'threads-pool-test',\n          include: ['**/*.threads.spec.ts'],\n          pool: 'threads',\n        },\n      },\n    ]\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/custom-runner/custom-runner.test.ts",
    "content": "import {describe, expect, test as baseTest, type TestAPI} from 'vitest'\nimport { getSuiteNames } from './utils';\n\nconst test = baseTest as TestAPI<{__suiteNames: string[]}>\n\ntest(\"test-a\", (ctx) => {\n\texpect(ctx.__suiteNames).toEqual([]);\n\texpect(ctx.__suiteNames).toEqual(getSuiteNames(ctx.task.suite))\n})\n\ndescribe(\"suite-x\", () => {\n\ttest(\"test-b\", (ctx) => {\n\t\texpect(ctx.__suiteNames).toEqual(['suite-x'])\n\t\texpect(ctx.__suiteNames).toEqual(getSuiteNames(ctx.task.suite))\n\t})\n\n\tdescribe(\"suite-y\", () => {\n\t\ttest(\"test-c\", (ctx) => {\n\t\t\texpect(ctx.__suiteNames).toEqual(['suite-y', 'suite-x'])\n\t\t\texpect(ctx.__suiteNames).toEqual(getSuiteNames(ctx.task.suite))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/cli/fixtures/custom-runner/test-runner.ts",
    "content": "import type { TestContext } from '@vitest/runner'\nimport { TestRunner } from 'vitest'\nimport { getSuiteNames } from './utils';\n\nclass CustomTestRunner extends TestRunner {\n\textendTaskContext(context: TestContext) {\n    super.extendTaskContext(context);\n\t\t(context as any).__suiteNames = getSuiteNames(context.task.suite)\n    return context\n\t}\n}\n\nexport default CustomTestRunner\n"
  },
  {
    "path": "test/cli/fixtures/custom-runner/utils.ts",
    "content": "import { Suite } from \"@vitest/runner\"\n\nexport function getSuiteNames(suite?: Suite) {\n  const names = []\n  while (suite) {\n    names.push(suite.name)\n    suite = suite.suite\n  }\n  return names\n}\n"
  },
  {
    "path": "test/cli/fixtures/custom-runner/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    runner: './test-runner.ts',\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/dotted-files/.cache/projects/test/should-run.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('should run', () => {\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/cli/fixtures/expect-soft/expects/soft.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ninterface CustomMatchers<R = unknown> {\n  toBeAsync: (expected: unknown) => Promise<R>;\n  toBeDividedBy(divisor: number): R\n}\n\ndeclare module 'vitest' {\n  interface Assertion<T = any> extends CustomMatchers<T> {}\n}\n\nexpect.extend({\n  toBeAsync: async function (received, expected) {\n    return {\n      pass: received === expected,\n      message: () => `expected ${received} to be ${expected} (asynchronously)`,\n    };\n  },\n  toBeDividedBy(received, divisor) {\n    const pass = received % divisor === 0\n    if (pass) {\n      return {\n        message: () =>\n          `expected ${received} not to be divisible by ${divisor}`,\n        pass: true,\n      }\n    }\n    else {\n      return {\n        message: () =>\n          `expected ${received} to be divisible by ${divisor}`,\n        pass: false,\n      }\n    }\n  },\n})\n\ntest('basic', () => {\n  expect.soft(1).toBe(2)\n  expect.soft(2).toBe(3)\n})\n\ntest('promise', async () => {\n  await expect.soft(\n    new Promise((resolve) => {\n      setTimeout(() => {\n        resolve(1)\n      })\n    }),\n  ).resolves.toBe(2)\n  await expect.soft(\n    new Promise((resolve) => {\n      setTimeout(() => {\n        resolve(2)\n      })\n    }),\n  ).resolves.toBe(3)\n})\n\ntest('with expect', () => {\n  expect.soft(1).toEqual(2)\n  expect(10).toEqual(20)\n  expect.soft(2).toEqual(3)\n})\n\ntest('with expect.extend', () => {\n  expect.soft(1).toEqual(2)\n  expect.soft(3).toBeDividedBy(4)\n  expect(5).toEqual(6)\n})\n\ntest('promise with expect.extend', async () => {\n  await expect.soft(1 + 1).toBeAsync(3);\n  await expect.soft(1 + 2).toBeAsync(3);\n  await expect.soft(2 + 2).toBeAsync(3);\n});\n\ntest('promise rejection', async () => {\n  await expect\n    .soft(\n      Promise.resolve().then(() => {\n        throw new Error('boom 1st')\n      }),\n    )\n    .resolves.toBe('1st')\n\n  await expect\n    .soft(\n      Promise.resolve().then(() => {\n        throw new Error('boom 2nd')\n      }),\n    )\n    .resolves.toBe('2nd')\n})\n\ntest('promise resolved instead of rejecting', async () => {\n  await expect.soft(Promise.resolve('value 1')).rejects.toBe('1st')\n  await expect.soft(Promise.resolve('value 2')).rejects.toBe('2nd')\n})\n\ntest('passed', () => {\n  expect.soft(1).toEqual(1)\n  expect(10).toEqual(10)\n  expect.soft(2).toEqual(2)\n})\n\nlet num = 0\ntest('retry will passed', { retry: 1 }, () => {\n  expect.soft(num += 1).toBe(3)\n  expect.soft(num += 1).toBe(4)\n})\n\nnum = 0\ntest('retry will failed', { retry: 1 }, () => {\n  expect.soft(num += 1).toBe(4)\n  expect.soft(num += 1).toBe(5)\n})\n"
  },
  {
    "path": "test/cli/fixtures/expect-soft/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    pool: 'forks',\n    isolate: false,\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/.dot-folder/dot-test.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('check that tests inside folder with . is run', () => {\n  expect(true).toBe(false)\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/async-assertion.test.ts",
    "content": "import { test, expect } from \"vitest\"\n\ntest('multiple errors', () => {\n  expect(new Promise((r) => r(\"xx\"))).resolves.toBe(\"yy\");\n  expect(new Promise((r) => setTimeout(() => r(\"xx\"), 10))).resolves.toBe(\"zz\");\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/each-timeout.test.ts",
    "content": "import { test } from 'vitest'\n\ntest.each([1])('test each timeout', async () => {\n  await new Promise(resolve => setTimeout(resolve, 20))\n}, 10)\n"
  },
  {
    "path": "test/cli/fixtures/fails/empty.test.ts",
    "content": ""
  },
  {
    "path": "test/cli/fixtures/fails/expect-soft.test.ts",
    "content": "import { expect } from 'vitest'\n\nexpect.soft(1 + 1).toEqual(3)\n"
  },
  {
    "path": "test/cli/fixtures/fails/expect-unreachable.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('', () => {\n  expect.unreachable('hi')\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/expect.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('hi', () => {\n  expect(1 + 1).toEqual(3)\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/exports-error.test.js",
    "content": "import { test, vi } from 'vitest'\n\ntest('__vite_ssr_import__ is removed in error', () => {\n  // vi is not a function\n  vi()\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/hook-timeout.test.ts",
    "content": "import { beforeEach, describe, expect, it } from 'vitest'\n\ndescribe('hooks should timeout', () => {\n  beforeEach(async () => {\n    await new Promise(resolve => setTimeout(resolve, 20))\n  }, 10)\n  it('hello', () => {\n    expect(true).toBe(true)\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/hooks-called.test.ts",
    "content": "import { afterAll, beforeAll, expect, test } from 'vitest'\n\nbeforeAll(() => {\n  // should both appear in snapshot\n  throw new Error('before all')\n})\n\nafterAll(() => {\n  // should both appear in snapshot\n  throw new Error('after all')\n})\n\ntest('1 = 1', () => {\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/hooks-fail-afterAll.test.ts",
    "content": "import { describe, test, afterAll } from 'vitest';\n\ndescribe('afterAll hooks fail', () => {\n  // @ts-ignore expects a function\n  afterAll('fail')\n  test.todo('todo')\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/hooks-fail-afterEach.test.ts",
    "content": "import { afterEach, describe, test } from 'vitest';\n\ndescribe('afterEach hooks fail', () => {\n  // @ts-ignore expects a function\n  afterEach('fail')\n  test.todo('todo')\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/hooks-fail-beforeAll.test.ts",
    "content": "import { beforeAll, describe, test } from 'vitest';\n\ndescribe('beforeAll hooks fail', () => {\n  // @ts-ignore expects a function\n  beforeAll('fail')\n  test.todo('todo')\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/hooks-fail-beforeEach.test.ts",
    "content": "import { beforeEach, describe, test } from 'vitest';\n\ndescribe('beforeEach hooks fail', () => {\n  // @ts-ignore expects a function\n  beforeEach('fail')\n  test.todo('todo')\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/hooks-timeout-before-hook-cleanup-callback.test.ts",
    "content": "import { beforeEach, beforeAll, describe, test, expect } from 'vitest';\n\ndescribe('beforeEach cleanup timeout', () => {\n  beforeEach(() => () => new Promise(() => {}), 101)\n  test(\"ok\", () => {\n    expect(0).toBe(0)\n  })\n})\n\ndescribe('beforeAll cleanup timeout', () => {\n  beforeAll(() => () => new Promise(() => {}), 102)\n  test(\"ok\", () => {\n    expect(0).toBe(0)\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/mock-import-proxy-module.test.ts",
    "content": "import { expect, test, vi } from './proxy-module'\n\n// This can be used only when imported directly from vitest\nvi.mock('vite')\n\ntest('hi', () => {\n  expect(1 + 1).toEqual(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/nested-suite.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('a', () => {\n  describe('b', () => {\n    describe('c', () => {\n      describe('d', () => {\n        describe('e', () => {\n          it('very deep', () => {\n            expect(true).toBe(false)\n          })\n        })\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/no-assertions.test.ts",
    "content": "import { it } from 'vitest'\n\nit('test without assertions', () => {})"
  },
  {
    "path": "test/cli/fixtures/fails/node-browser-context.test.ts",
    "content": "import { page } from 'vitest/browser'\n\nconsole.log(page)\n"
  },
  {
    "path": "test/cli/fixtures/fails/poll-no-awaited.test.ts",
    "content": "import { expect, test } from 'vitest';\n\ntest('poll is not awaited once', () => {\n  expect.poll(() => 2).toBe(2)\n})\n\ntest('poll is not awaited several times', () => {\n  expect.poll(() => 3).toBe(3)\n  expect.poll(() => 'string').not.toBe('correct')\n})\n\ntest('poll is not awaited but there is an async assertion afterwards', async () => {\n  expect.poll(() => 4).toBe(4)\n  await expect(new Promise((r) => setTimeout(() => r(3), 50))).resolves.toBe(3)\n})\n\ntest('poll is not awaited but there is an error afterwards', async () => {\n  expect.poll(() => 4).toBe(4)\n  expect(3).toBe(4)\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/primitive-error.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('primitive error thrown', () => {\n  // eslint-disable-next-line no-throw-literal\n  throw 42\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/proxy-module.ts",
    "content": "export * from 'vitest'\n"
  },
  {
    "path": "test/cli/fixtures/fails/skip-conditional.test.ts",
    "content": "import { expect, it } from 'vitest';\n\nit('skips correctly', ({ skip }) => {\n  skip(true)\n  expect.unreachable()\n})\n\nit('doesnt skip correctly', ({ skip }) => {\n  skip(false)\n  throw new Error('doesnt skip')\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/snapshot-with-not.test.ts",
    "content": "import { expect, test } from \"vitest\"\n\ntest.each([\n  'toMatchSnapshot',\n  'toMatchFileSnapshot',\n  'toMatchInlineSnapshot',\n  'toThrowErrorMatchingSnapshot',\n  'toThrowErrorMatchingInlineSnapshot',\n])('%s should fail with not', (api) => {\n  (expect(0).not as any)[api]()\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/stall.test.ts",
    "content": "import { test } from 'vitest'\n\n// https://github.com/vitest-dev/vitest/issues/374\n// Passing `Error` instances across message channels could cause the test runner to stall, if\n// multiple tests fail. This suite is successful if it does not timeout, which is verified by the\n// test runner.\n\ntest('test 1', () => {\n  throw new TypeError('failure')\n})\ntest('test 2', () => {\n  throw new TypeError('failure')\n})\ntest('test 3', () => {\n  throw new TypeError('failure')\n})\ntest('test 4', () => {\n  throw new TypeError('failure')\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/test-extend/circular-dependency.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nconst myTest = test.extend<{ a: number; b: number }>({\n  a: async ({ b }, use) => {\n    await use(b)\n  },\n  b: async ({ a }, use) => {\n    await use(a)\n  },\n})\n\nmyTest('', ({ a }) => {\n  expect(a).toBe(0)\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/test-extend/fixture-error.test.ts",
    "content": "import { afterEach, beforeEach, describe, expectTypeOf, test, expect } from 'vitest'\n\ndescribe('error thrown in beforeEach fixtures', () => {\n  const myTest = test.extend<{ a: never }>({\n    a: async () => {\n      throw new Error('Error thrown in beforeEach fixture')\n    },\n  })\n\n  // eslint-disable-next-line unused-imports/no-unused-vars\n  beforeEach<{ a: never }>(({ a }) => {})\n\n  myTest('error is handled', () => {\n    expect(1).toBe(1)\n  })\n})\n\ndescribe('error thrown in afterEach fixtures', () => {\n  const myTest = test.extend<{ a: never }>({\n    a: async () => {\n      throw new Error('Error thrown in afterEach fixture')\n    },\n  })\n\n  // eslint-disable-next-line unused-imports/no-unused-vars\n  afterEach<{ a: never }>(({ a }) => {})\n\n  myTest('fixture errors', () => {\n    expect(1).toBe(1)\n    expectTypeOf(1).toEqualTypeOf<number>()\n  })\n})\n\ndescribe('error thrown in test fixtures', () => {\n  const myTest = test.extend<{ a: never }>({\n    a: async () => {\n      throw new Error('Error thrown in test fixture')\n    },\n  })\n\n  // eslint-disable-next-line unused-imports/no-unused-vars\n  myTest('fixture errors', ({ a }) => {})\n})\n\ndescribe('correctly fails when test times out', () => {\n  const myTest = test.extend<{ a: number }>({\n    a: async ({}, use) => {\n      await use(2)\n    },\n  })\n  myTest('test times out', async ({ a }) => {\n    await new Promise((resolve) => setTimeout(resolve, 1000))\n    expect(a).toBe(2)\n  }, 20)\n})\n\ndescribe('error thrown during fixture teardown', () => {\n  const myTest = test.extend<{ a: string }>({\n    a: async ({}, use) => {\n      await use(\"hello\");\n      throw new Error('Error fixture teardown')\n    },\n  })\n\n  myTest('no error in test', ({ a }) => {\n    expect(a).toBe(\"hello\");\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/test-extend/fixture-rest-params.test.ts",
    "content": "import { test } from 'vitest'\n\ntest.extend({\n  // eslint-disable-next-line unused-imports/no-unused-vars\n  a: async (...rest) => {},\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/test-extend/fixture-rest-props.test.ts",
    "content": "import { test } from 'vitest'\n\ntest.extend({\n  // eslint-disable-next-line unused-imports/no-unused-vars\n  a: async ({ ...rest }) => {},\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/test-extend/fixture-without-destructuring.test.ts",
    "content": "import { test } from 'vitest'\n\ntest.extend({\n  // eslint-disable-next-line unused-imports/no-unused-vars\n  a: async (context) => {},\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/test-extend/test-rest-params.test.ts",
    "content": "import { test } from 'vitest'\n\nconst myTest = test.extend({ a: 1 })\n\n// eslint-disable-next-line unused-imports/no-unused-vars\nmyTest('', (...rest) => {\n\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/test-extend/test-rest-props.test.ts",
    "content": "import { test } from 'vitest'\n\nconst myTest = test.extend({ a: 1 })\n\n// eslint-disable-next-line unused-imports/no-unused-vars\nmyTest('', ({ ...rest }) => {\n\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/test-extend/test-without-destructuring.test.ts",
    "content": "import { test } from 'vitest'\n\nconst myTest = test.extend({ a: 1 })\n\n// eslint-disable-next-line unused-imports/no-unused-vars\nmyTest('', (context) => {\n\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/test-timeout.test.ts",
    "content": "import { beforeAll, beforeEach, expect, suite, test } from 'vitest'\n\ntest('hi', async () => {\n  await new Promise(resolve => setTimeout(resolve, 1000))\n}, 10)\n\ntest('timeout on long synchronous task', async () => {\n  const start = Date.now();\n\n  while (Date.now() < start + 20) {\n  }\n}, 15)\n\nsuite('timeout beforeAll', () => {\n  beforeAll(() => {\n    const start = Date.now();\n    while (Date.now() < start + 20) {}\n  }, 16)\n\n  test(\"ok\", () => {})\n})\n\nsuite('timeout beforeEach', () => {\n  beforeEach(() => {\n    const start = Date.now();\n    while (Date.now() < start + 20) {}\n  }, 17)\n\n  test(\"ok\", () => {})\n})\n\nsuite('suite timeout', {\n  timeout: 100,\n}, () => {\n  test('hi', async () => {\n    await new Promise(resolve => setTimeout(resolve, 500))\n  })\n})\n\nsuite('suite timeout simple input', () => {\n  test('hi', async () => {\n    await new Promise(resolve => setTimeout(resolve, 500))\n  })\n}, 200)\n\ntest('auto await async assertion', { timeout: 20 }, () => {\n  expect(new Promise(() => {})).resolves.toBe(0)\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/unhandled-suite.test.ts",
    "content": "import { expect, it } from 'vitest';\n\nit('foo', () => {\n  expect(1).toBe(1)\n  new Promise((resolve, reject) => {\n    reject('promise error');\n  });\n});\n"
  },
  {
    "path": "test/cli/fixtures/fails/unhandled.test.ts",
    "content": "// @vitest-environment jsdom\n\nimport { expect, test } from 'vitest'\n\ntest('unhandled exception', () => {\n  expect(1).toBe(1)\n  addEventListener('custom', () => {\n    throw new Error('some error')\n  })\n  dispatchEvent(new Event('custom'))\n})\n"
  },
  {
    "path": "test/cli/fixtures/fails/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    pool: 'forks',\n    isolate: false,\n    expect: {\n      requireAssertions: true,\n    }\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/file-tags/error-file-one-line-comment.test.ts",
    "content": "// @module-tag invalid\n// @module-tag unknown\n\nimport { describe, test } from 'vitest'\n\ndescribe('suite 1', () => {\n  test('test 1', { tags: ['test'] }, () => {})\n})\n"
  },
  {
    "path": "test/cli/fixtures/file-tags/error-file-tags.test.ts",
    "content": "/**\n * @module-tag invalid\n * @module-tag unknown\n */\n\nimport { describe, test } from 'vitest'\n\ndescribe('suite 1', () => {\n  test('test 1', { tags: ['test'] }, () => {})\n})\n"
  },
  {
    "path": "test/cli/fixtures/file-tags/valid-file-one-line-comment.test.ts",
    "content": "// @module-tag file\n// @module-tag file-2\n// @module-tag file/slash\n\nimport { describe, test } from 'vitest'\n\ndescribe('suite 1', () => {\n  test('test 1', { tags: ['test'] }, () => {})\n})\n"
  },
  {
    "path": "test/cli/fixtures/file-tags/valid-file-tags.test.ts",
    "content": "/**\n * @module-tag file\n * @module-tag file-2\n * @module-tag file/slash\n */\n\nimport { describe, test } from 'vitest'\n\ndescribe('suite 1', () => {\n  test('test 1', { tags: ['test'] }, () => {})\n})\n"
  },
  {
    "path": "test/cli/fixtures/forks-channel/process-send.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"calls IPC channel\", () => {\n  if (!process.send) {\n    throw new Error(\"Expected test case to run inside child_process\")\n  }\n\n  process.send({ \"not serialized\": \"with v8 serializer\" })\n})\n"
  },
  {
    "path": "test/cli/fixtures/forks-channel/vitest.config.ts",
    "content": "export default {}"
  },
  {
    "path": "test/cli/fixtures/git-changed/related/deep-related-exports.test.ts",
    "content": "import { access } from 'node:fs'\nimport { sep } from 'pathe'\nimport { expect, test } from 'vitest'\nimport { A } from './src/sourceC'\n\ntest('values', () => {\n  expect(A).toBe('A')\n  expect(typeof sep).toBe('string')\n  // doesn't throw\n  expect(typeof access).toBe('function')\n})\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/related/deep-related-imports.test.ts",
    "content": "import { access } from 'node:fs'\nimport { sep } from 'pathe'\nimport { expect, test } from 'vitest'\nimport { A } from './src/sourceD'\n\ntest('values', () => {\n  expect(A).toBe('A')\n  expect(typeof sep).toBe('string')\n  // doesn't throw\n  expect(typeof access).toBe('function')\n})\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/related/not-related.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { B } from './src/sourceB'\n\ntest('shouldn\\'t run', () => {\n  expect(B).toBe('B')\n  expect.fail()\n})\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/related/related.test.ts",
    "content": "import { access } from 'node:fs'\nimport { sep } from 'pathe'\nimport { expect, test } from 'vitest'\nimport { A } from './src/sourceA'\n\ntest('A equals A', () => {\n  expect(A).toBe('A')\n  expect(typeof sep).toBe('string')\n  // doesn't throw\n  expect(typeof access).toBe('function')\n})\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/related/src/sourceA.ts",
    "content": "export const A = 'A'\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/related/src/sourceB.ts",
    "content": "export const B = 'B'\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/related/src/sourceC.ts",
    "content": "// re-exporting for deep changed detection\nexport { A } from './sourceA'\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/related/src/sourceD.ts",
    "content": "// import and re-exporting for deep changed detection\nimport { A as sourceA } from './sourceA'\n\nexport const A = sourceA\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/related/vitest.config.js",
    "content": "export default {}"
  },
  {
    "path": "test/cli/fixtures/git-changed/workspace/package.json",
    "content": "{\n  \"type\": \"commonjs\"\n}"
  },
  {
    "path": "test/cli/fixtures/git-changed/workspace/packages/packageA/index.js",
    "content": "export default function getLetter() {\n  return 'c';\n}\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/workspace/packages/packageA/index.test.js",
    "content": "import { describe, expect, it } from 'vitest';\nimport getLetter from './index';\ndescribe('getLetter', () => {\n  const result = getLetter();\n  it('should return c', () => {\n    expect(result).toBe('c');\n  });\n});\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/workspace/packages/packageA/vitest.config.mjs",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({});\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/workspace/packages/packageB/index.js",
    "content": "export default function getNumber() {\n  return 3;\n}\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/workspace/packages/packageB/index.test.js",
    "content": "import { describe, expect, it } from 'vitest';\nimport getNumber from './index';\ndescribe('getNumber', () => {\n  const result = getNumber();\n  it('should return 3', () => {\n    expect(result).toBe(3);\n  });\n});\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/workspace/packages/packageB/vitest.config.mjs",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({});\n"
  },
  {
    "path": "test/cli/fixtures/git-changed/workspace/vitest.config.mjs",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      \"packages/*/vitest.config.mjs\",\n    ]\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/globalSetup/another-vite-instance.ts",
    "content": "import { resolve } from 'pathe'\nimport { createServer } from 'vite'\n\nlet teardownHappened = false\n\nexport async function setup() {\n  const server = await createServer({\n    root: resolve(import.meta.dirname, '..'),\n    server: {\n      port: 9988,\n    },\n  })\n\n  await server.listen(9988)\n  return async () => {\n    if (teardownHappened) {\n      throw new Error('teardown called twice')\n    }\n    teardownHappened = true\n    await server.close()\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/globalSetup/default-export.js",
    "content": "async function sleep(n) {\n  return new Promise(resolve => setTimeout(resolve, n))\n}\n\nlet teardownHappened = false\n\nexport default async function () {\n  // setup something eg start a server, db or whatever\n  // const server = await start()\n  // console.log('globalSetup default-export.js')\n  // const start = Date.now()\n  await sleep(25)\n\n  return async () => {\n    if (teardownHappened) {\n      throw new Error('teardown called twice')\n    }\n    teardownHappened = true\n    // tear it down here\n    // await server.close()\n    await sleep(25)\n    // const duration = Date.now() - start\n    // console.log(`globalTeardown default-export.js, took ${(duration)}ms`)\n    // if (duration > 2000)\n    //   throw new Error('error from teardown in globalSetup default-export.js')\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/globalSetup/named-exports.js",
    "content": "async function sleep(n) {\n  return new Promise(resolve => setTimeout(resolve, n))\n}\n\nlet teardownHappened = false\n\n// let start\n\nexport async function setup() {\n  // setup something eg start a server, db or whatever\n  // const server = await start()\n  // console.log('globalSetup named-exports.js')\n  // start = Date.now()\n  await sleep(25)\n}\n\nexport async function teardown() {\n  if (teardownHappened) {\n    throw new Error('teardown called twice')\n  }\n  teardownHappened = true\n  // tear it down here\n  // await server.close()\n  await sleep(25)\n  // const duration = Date.now() - start\n  // console.log(`globalTeardown named-exports.js, took ${(duration)}ms`)\n  // if (duration > 4000)\n  //  throw new Error('error from teardown in globalSetup named-exports.js')\n}\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/globalSetup/server.ts",
    "content": "import http from 'node:http'\n\nexport async function startServer(host: string, port: number): Promise<http.Server> {\n  return new Promise((resolve) => {\n    const server = http.createServer((req, res) => {\n      res.writeHead(200, { 'Content-Type': 'text/plain' })\n      res.end('Hello Vitest\\n')\n    })\n    server.listen(port, host, () => resolve(server))\n  })\n}\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/globalSetup/ts-with-imports.ts",
    "content": "import { startServer } from './server'\n\nlet teardown = false\n\nexport default async function () {\n  const server = await startServer('0.0.0.0', 9876)\n  return async () => {\n    if (teardown) {\n      throw new Error('teardown called twice')\n    }\n    teardown = true\n    return new Promise<void>(resolve => server.close(() => resolve()))\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/globalSetup/update-env.ts",
    "content": "export default () => {\n  process.env.NEW_VALUE = 'true'\n}\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/index.html",
    "content": "Hello Vitest\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/setupFiles/add-something-to-global.ts",
    "content": "import { afterAll, beforeAll, beforeEach } from 'vitest'\n\nbeforeAll(() => {\n  // @ts-expect-error type\n  globalThis.something = 'something'\n})\n\nbeforeAll(async () => {\n  await new Promise((resolve) => {\n    setTimeout(() => {\n      resolve(null)\n    }, 300)\n  })\n})\n\nbeforeEach(async () => {\n  await new Promise((resolve) => {\n    setTimeout(() => {\n      resolve(null)\n    }, 10)\n  })\n})\n\nafterAll(() => {\n  // @ts-expect-error type\n  delete globalThis.something\n})\n\nafterAll(async () => {\n  await new Promise((resolve) => {\n    setTimeout(() => {\n      resolve(null)\n    }, 500)\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/setupFiles/without-relative-path-prefix.ts",
    "content": "import { afterAll, beforeAll } from 'vitest'\n\nbeforeAll(() => {\n  // @ts-expect-error type\n  globalThis.loaded = true\n})\n\nafterAll(() => {\n  // @ts-expect-error type\n  delete globalThis.loaded\n})\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/test/global-setup.test.ts",
    "content": "import { afterEach, beforeEach, expect, test } from 'vitest'\n\nbeforeEach(async () => {\n  await new Promise((resolve) => {\n    setTimeout(() => {\n      resolve(null)\n    }, 300)\n  })\n})\n\nafterEach(async () => {\n  await new Promise((resolve) => {\n    setTimeout(() => {\n      resolve(null)\n    }, 300)\n  })\n})\n\ntest('server running', async () => {\n  const res = await (await fetch('http://0.0.0.0:9876')).text()\n  expect(res).toBe('Hello Vitest\\n')\n})\n\ntest('vite instance running', async () => {\n  const res = await (await fetch('http://localhost:9988')).text()\n  expect(res).toContain('<script type=\"module\" src=\"/@vite/client\">')\n  expect(res).toContain('Hello Vitest\\n')\n})\n"
  },
  {
    "path": "test/cli/fixtures/global-setup/test/setup-files.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('something has been added to global by setupFiles entry', async () => {\n  // @ts-expect-error type\n  const result = something\n  expect(result).toBe('something')\n})\n\ntest('setup file has been loaded without relative path prefix', () => {\n  // @ts-expect-error type\n  const result = loaded\n  expect(result).toBeTruthy()\n})\n\ntest('the process.env is injected correctly', () => {\n  expect(process.env.NEW_VALUE).toBe('true')\n})\n"
  },
  {
    "path": "test/cli/fixtures/global-setup-fail/example.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('example test', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/global-setup-fail/globalSetup/error.ts",
    "content": "interface _Test {\n  method: () => void\n}\n\nexport default function () {\n  throw new Error('error')\n}\n"
  },
  {
    "path": "test/cli/fixtures/global-setup-fail/vitest.config.ts",
    "content": "import { resolve } from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    globalSetup: [\n      resolve(import.meta.dirname, './globalSetup/error.ts'),\n    ],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/inspect/math.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"sum\", () => {\n  expect(1 + 1).toBe(2)\n})"
  },
  {
    "path": "test/cli/fixtures/inspect/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: ['./**.test.ts'],\n    watch: false,\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/inspect/vitest.config.ts.timestamp-1713887058308-b154731a64b17.mjs",
    "content": "// fixtures/inspect/vitest.config.ts\nimport { defineConfig } from \"file:///Users/sheremet.mac/Projects/vitest/packages/vitest/dist/config.js\";\nvar vitest_config_default = defineConfig({\n  test: {\n    include: [\"./**.test.ts\"],\n    watch: false\n  }\n});\nexport {\n  vitest_config_default as default\n};\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZml4dHVyZXMvaW5zcGVjdC92aXRlc3QuY29uZmlnLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3NoZXJlbWV0Lm1hYy9Qcm9qZWN0cy92aXRlc3QvdGVzdC9jbGkvZml4dHVyZXMvaW5zcGVjdFwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL3NoZXJlbWV0Lm1hYy9Qcm9qZWN0cy92aXRlc3QvdGVzdC9jbGkvZml4dHVyZXMvaW5zcGVjdC92aXRlc3QuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9zaGVyZW1ldC5tYWMvUHJvamVjdHMvdml0ZXN0L3Rlc3QvY2xpL2ZpeHR1cmVzL2luc3BlY3Qvdml0ZXN0LmNvbmZpZy50c1wiO2ltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gJ3ZpdGVzdC9jb25maWcnXG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG4gIHRlc3Q6IHtcbiAgICBpbmNsdWRlOiBbJy4vKioudGVzdC50cyddLFxuICAgIHdhdGNoOiBmYWxzZSxcbiAgfSxcbn0pXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQTZXLFNBQVMsb0JBQW9CO0FBRTFZLElBQU8sd0JBQVEsYUFBYTtBQUFBLEVBQzFCLE1BQU07QUFBQSxJQUNKLFNBQVMsQ0FBQyxjQUFjO0FBQUEsSUFDeEIsT0FBTztBQUFBLEVBQ1Q7QUFDRixDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo=\n"
  },
  {
    "path": "test/cli/fixtures/invalid-package/mock-bad-dep.test.ts",
    "content": "// @ts-expect-error no type\nimport * as dep from 'test-dep-invalid'\nimport { expect, test, vi } from 'vitest'\n\nvi.mock('test-dep-invalid', () => ({ mocked: 'ok' }))\n\ntest('basic', () => {\n  expect(dep).toMatchObject({ mocked: 'ok' })\n})\n"
  },
  {
    "path": "test/cli/fixtures/invalid-package/mock-wrapper-and-bad-dep.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { hello } from './wrapper.js'\n\nvi.mock('test-dep-invalid', () => ({}))\n\nvi.mock(import('./wrapper.js'), () => {\n  return { hello: () => 'mock-hello' }\n})\n\ntest('basic', () => {\n  expect(hello()).toBe('mock-hello')\n})\n"
  },
  {
    "path": "test/cli/fixtures/invalid-package/mock-wrapper.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { hello } from './wrapper.js'\n\nvi.mock(import('./wrapper.js'), () => {\n  return { hello: () => 'mock-hello' }\n})\n\ntest('basic', () => {\n  expect(hello()).toBe('mock-hello')\n})\n"
  },
  {
    "path": "test/cli/fixtures/invalid-package/wrapper.ts",
    "content": "// @ts-expect-error no type\nimport * as dep from 'test-dep-invalid'\n\nexport const hello = () => dep\n"
  },
  {
    "path": "test/cli/fixtures/list/basic.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('basic suite', () => {\n  describe('inner suite', () => {\n    it('some test', () => {\n      expect(1).toBe(1)\n    })\n\n    it('another test', () => {\n      expect(1).toBe(1)\n    })\n  })\n\n  it('basic test', () => {\n    expect(1).toBe(1)\n  })\n})\n\nit('outside test', () => {\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/cli/fixtures/list/custom.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: ['basic.test.ts', 'math.test.ts'],\n    name: 'custom',\n    includeTaskLocation: true,\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/list/describe-error.test.ts",
    "content": "import { describe, expect, it } from 'vitest';\n\ndescribe('describe error', () => {\n  throw new Error('describe error')\n\n  it('wont run', () => {\n    expect(true).toBe(true)\n  })\n})"
  },
  {
    "path": "test/cli/fixtures/list/fail.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: ['top-level-error.test.ts', 'describe-error.test.ts'],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/list/math.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nconsole.log('logging during collection')\n\nit('1 plus 1', () => {\n  expect(1 + 1).toBe(2)\n})\n\nit('failing test', () => {\n  expect(1 + 1).toBe(3)\n})\n"
  },
  {
    "path": "test/cli/fixtures/list/top-level-error.test.ts",
    "content": "throw new Error('top level error')\n"
  },
  {
    "path": "test/cli/fixtures/list/type.test-d.ts",
    "content": "import { expectTypeOf, it } from 'vitest'\n\nit('1 plus 1', () => {\n  expectTypeOf(1 + 1).toBeNumber()\n})\n"
  },
  {
    "path": "test/cli/fixtures/list/vitest.config.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\nimport { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  cacheDir: fileURLToPath(new URL(\"./node_modules/.vite\", import.meta.url)),\n  test: {\n    include: ['basic.test.ts', 'math.test.ts'],\n    browser: {\n      instances: [{ browser: 'chromium' }],\n      provider: playwright(),\n      headless: true,\n      api: 7523,\n    }\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/location-filters/basic.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('basic suite', () => {\n  describe('inner suite', () => {\n    it('some test', () => {\n      expect(1).toBe(1)\n    })\n\n    it('another test', () => {\n      expect(1).toBe(1)\n    })\n  })\n\n  it('basic test', () => {\n    expect(1).toBe(1)\n  })\n})\n\nit('outside test', () => {\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/cli/fixtures/location-filters/math-with-dashes-in-name.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('1 plus 1', () => {\n  expect(1 + 1).toBe(2)\n})\n\nit('2 plus 2', () => {\n  expect(2 + 2).toBe(4)\n})\n"
  },
  {
    "path": "test/cli/fixtures/location-filters/math.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('1 plus 1', () => {\n  expect(1 + 1).toBe(2)\n})\n\nit('2 plus 2', () => {\n  expect(2 + 2).toBe(4)\n})\n"
  },
  {
    "path": "test/cli/fixtures/location-filters/no-task-location.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    includeTaskLocation: false,\n  },\n})\n\n"
  },
  {
    "path": "test/cli/fixtures/location-filters/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    includeTaskLocation: true,\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/mocker/automock/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Document</title>\n</head>\n<body>\n  <script type=\"module\" src=\"./index.js\"></script>\n  <div id=\"mocked\"></div>\n</body>\n</html>"
  },
  {
    "path": "test/cli/fixtures/mocker/automock/index.js",
    "content": "import { mocker } from 'virtual:mocker'\nimport { calculate } from './test'\n\nmocker.customMock(import('./test'), { spy: true })\n\ncalculate.mockReturnValue(42)\n\ndocument.querySelector('#mocked').textContent = calculate(1, 2)\n"
  },
  {
    "path": "test/cli/fixtures/mocker/automock/test.js",
    "content": "export function calculate (a, b) {\n  return a + b\n}\n"
  },
  {
    "path": "test/cli/fixtures/mocker/autospy/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Document</title>\n</head>\n<body>\n  <script type=\"module\" src=\"./index.js\"></script>\n  <div id=\"mocked\"></div>\n</body>\n</html>"
  },
  {
    "path": "test/cli/fixtures/mocker/autospy/index.js",
    "content": "import { mocker } from 'virtual:mocker'\nimport { calculate } from './test'\n\nmocker.customMock(import('./test'))\n\ndocument.querySelector('#mocked').textContent = calculate(1, 2)\n\ncalculate.mockReturnValue(42)\n\ndocument.querySelector('#mocked').textContent += `, ${calculate(1, 2)}`\n"
  },
  {
    "path": "test/cli/fixtures/mocker/autospy/test.js",
    "content": "export function calculate (a, b) {\n  return a + b\n}\n"
  },
  {
    "path": "test/cli/fixtures/mocker/manual-mock/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Document</title>\n</head>\n<body>\n  <script type=\"module\" src=\"./index.js\"></script>\n  <div id=\"mocked\"></div>\n</body>\n</html>"
  },
  {
    "path": "test/cli/fixtures/mocker/manual-mock/index.js",
    "content": "import { mocker } from 'virtual:mocker'\nimport { mocked } from './test'\n\nmocker.customMock(import('./test'), () => {\n  return { mocked: true }\n})\n\ndocument.querySelector('#mocked').textContent = mocked\n"
  },
  {
    "path": "test/cli/fixtures/mocker/manual-mock/test.js",
    "content": "export const mocked = false\n"
  },
  {
    "path": "test/cli/fixtures/mocker/redirect/__mocks__/test.js",
    "content": "export function calculate() {\n  return 42\n}"
  },
  {
    "path": "test/cli/fixtures/mocker/redirect/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Document</title>\n</head>\n<body>\n  <script type=\"module\" src=\"./index.js\"></script>\n  <div id=\"mocked\"></div>\n</body>\n</html>"
  },
  {
    "path": "test/cli/fixtures/mocker/redirect/index.js",
    "content": "import { mocker } from 'virtual:mocker'\nimport { calculate } from './test'\n\nmocker.customMock(import('./test'))\n\ndocument.querySelector('#mocked').textContent = calculate(1, 2)\n"
  },
  {
    "path": "test/cli/fixtures/mocker/redirect/test.js",
    "content": "export function calculate (a, b) {\n  return a + b\n}\n"
  },
  {
    "path": "test/cli/fixtures/network-imports/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\n// @ts-expect-error network imports\nimport slash from 'http://localhost:9602/slash@3.0.0.js'\n\n// test without local server\n// import slash from 'https://esm.sh/slash@3.0.0'\n\ntest('network imports', () => {\n  expect(slash('foo\\\\bar')).toBe('foo/bar')\n})\n\ntest('doesn\\'t work for http outside localhost', async () => {\n  // @ts-expect-error network imports\n  await expect(() => import('http://100.0.0.0/')).rejects.toThrow(\n    'import of \\'http://100.0.0.0/\\' by undefined is not supported: http can only be used to load local resources (use https instead).',\n  )\n})\n"
  },
  {
    "path": "test/cli/fixtures/network-imports/public/slash@3.0.0.js",
    "content": "/* eslint-disable */\n// copied from https://esm.sh/v133/slash@3.0.0/es2022/slash.mjs to reduce network issues in CI \n\n/* esm.sh - esbuild bundle(slash@3.0.0) es2022 production */\nvar a=Object.create;var d=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var g=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty;var A=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),E=(e,t)=>{for(var r in t)d(e,r,{get:t[r],enumerable:!0})},u=(e,t,r,i)=>{if(t&&typeof t==\"object\"||typeof t==\"function\")for(let n of x(t))!p.call(e,n)&&n!==r&&d(e,n,{get:()=>t[n],enumerable:!(i=m(t,n))||i.enumerable});return e},o=(e,t,r)=>(u(e,t,\"default\"),r&&u(r,t,\"default\")),c=(e,t,r)=>(r=e!=null?a(g(e)):{},u(t||!e||!e.__esModule?d(r,\"default\",{value:e,enumerable:!0}):r,e));var f=A((h,_)=>{\"use strict\";_.exports=e=>{let t=/^\\\\\\\\\\?\\\\/.test(e),r=/[^\\u0000-\\u0080]+/.test(e);return t||r?e:e.replace(/\\\\/g,\"/\")}});var s={};E(s,{default:()=>P});var L=c(f());o(s,c(f()));var{default:l,...N}=L,P=l!==void 0?l:N;export{P as default};\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/jsSetup.js",
    "content": "import { initJsSetup } from './src/setups.ts'\n\ninitJsSetup()\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/package.json",
    "content": "{\n  \"name\": \"@vitest/test-native\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"license\": \"MIT\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"test:ui\": \"vitest --ui\",\n    \"test:run\": \"vitest run\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^24.12.0\",\n    \"@vitest/ui\": \"workspace:*\",\n    \"tinyspy\": \"^4.0.4\",\n    \"vite\": \"latest\",\n    \"vitest\": \"workspace:*\"\n  },\n  \"stackblitz\": {\n    \"startCommand\": \"npm run test:ui\"\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/__mocks__/redirect.ts",
    "content": "export default true\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/basic.ts",
    "content": "export const squared = (n: number) => n * n\nexport * from './dependency.ts'\nexport { helloMe as hello } from './index.ts'\nexport default 'hello world'\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/dependency.ts",
    "content": "export function add(a: number, b: number) {\n  return a + b\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/from-async.ts",
    "content": "import { answer } from './mock-async.ts'\n\nconst topLevelAnswer = answer\nexport { topLevelAnswer }\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/in-source/add.ts",
    "content": "export function add(...args: number[]) {\n  return args.reduce((a, b) => a + b, 0)\n}\n\n// in-source test suites\nif (import.meta.vitest) {\n  const { it, expect } = import.meta.vitest\n  it('add', () => {\n    expect(add()).toBe(0)\n    expect(add(1)).toBe(1)\n    expect(add(1, 2, 3)).toBe(6)\n  })\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/in-source/fibonacci.ts",
    "content": "import { add } from './add.ts'\n\nexport function fibonacci(n: number): number {\n  if (n < 2) {\n    return n\n  }\n  return add(fibonacci(n - 1), fibonacci(n - 2))\n}\n\nif (import.meta.vitest) {\n  const { it, expect } = import.meta.vitest\n  it('fibonacci', () => {\n    expect(fibonacci(0)).toBe(0)\n    expect(fibonacci(1)).toBe(1)\n    expect(fibonacci(2)).toBe(1)\n    expect(fibonacci(3)).toBe(2)\n    expect(fibonacci(4)).toBe(3)\n    expect(fibonacci(5)).toBe(5)\n    expect(fibonacci(6)).toBe(8)\n    expect(fibonacci(7)).toBe(13)\n    expect(fibonacci(8)).toBe(21)\n    expect(fibonacci(9)).toMatchInlineSnapshot('34')\n  })\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/in-source/index.ts",
    "content": "export * from './add.ts'\nexport * from './fibonacci.ts'\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/index.ts",
    "content": "export { add, hello, squared } from './basic.ts'\nexport const helloMe = 'world'\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/minus.ts",
    "content": "export function minus(a: number, b: number): number {\n  return a - b\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/mock-async.ts",
    "content": "export const answer = 0\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/mock-js.d.ts",
    "content": "export declare function mockJs(): number\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/mock-js.js",
    "content": "export function mockJs() {\n  return 0\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/mock-sync.ts",
    "content": "export function syncMock() {\n  return 0\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/no-mock.ts",
    "content": "// added annotation for coverage check\nexport function notMocked(): boolean {\n  return true\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/redirect.ts",
    "content": "throw new Error('Should be redirected!')\nexport default false\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/src/setups.ts",
    "content": "import { vi } from 'vitest'\n\nlet jsSetup = false\nlet tsSetup = false\n\nexport const initJsSetup = vi.fn(() => {\n  jsSetup = true\n})\n\nexport const initTsSetup = vi.fn(() => {\n  tsSetup = true\n})\n\nexport function getSetupStates() {\n  return {\n    jsSetup,\n    tsSetup,\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/test/__snapshots__/suite.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`suite name > snapshot 1`] = `\n{\n  \"foo\": \"bar\",\n}\n`;\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/test/automock.test.ts",
    "content": "import * as fs from 'node:fs'\nimport { expect, test, vi } from 'vitest'\nimport basicDefault, { add, hello, squared } from '../src/basic.ts'\n\nvi.mock(import('../src/basic.ts'))\nvi.mock(import('node:fs'))\n\ntest('squared is mocked', () => {\n  expect(vi.isMockFunction(squared)).toBe(true)\n  expect(vi.isMockFunction(add)).toBe(true)\n  expect(squared(2)).toBe(undefined)\n  expect(add(1, 1)).toBe(undefined)\n  expect(hello).toBe('world')\n  expect(basicDefault).toBe('hello world')\n})\n\ntest('fs is mocked', () => {\n  expect(vi.isMockFunction(fs.readFile)).toBe(true)\n  fs.readFile('path/to/file', 'utf-8', () => {})\n  expect(fs.readFile).toHaveBeenCalledWith('path/to/file', 'utf-8', expect.any(Function))\n})\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/test/autospy.test.ts",
    "content": "import * as fs from 'node:fs'\nimport { expect, test, vi } from 'vitest'\nimport basicDefault, { add, hello, squared } from '../src/basic.ts'\n\nvi.mock(import('../src/basic.ts'), { spy: true })\nvi.mock(import('node:fs'))\n\ntest('squared is mocked', () => {\n  expect(vi.isMockFunction(squared)).toBe(true)\n  expect(vi.isMockFunction(add)).toBe(true)\n  expect(squared(2)).toBe(4)\n  expect(squared).toHaveBeenCalled()\n\n  expect(add(1, 1)).toBe(2)\n  expect(add).toHaveBeenCalled()\n\n  expect(hello).toBe('world')\n  expect(basicDefault).toBe('hello world')\n})\n\ntest('fs is mocked', () => {\n  expect(vi.isMockFunction(fs.readFile)).toBe(true)\n  fs.readFile('path/to/file', 'utf-8', (_error) => {\n    // the first argument will be an error because the file does not exist\n  })\n  expect(fs.readFile).toHaveBeenCalledWith('path/to/file', 'utf-8', expect.any(Function))\n})\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/test/basic.test.ts",
    "content": "import { assert, expect, test } from 'vitest'\nimport { squared } from '../src/basic.ts'\n// importing from the barrel file\nimport { add } from '../src/in-source/index.ts'\n\n// Edit an assertion and save to see HMR in action\n\ntest('Math.sqrt()', () => {\n  expect(Math.sqrt(4)).toBe(2)\n  expect(Math.sqrt(144)).toBe(12)\n  expect(Math.sqrt(2)).toBe(Math.SQRT2)\n})\n\ntest('add', () => {\n  expect(add(1, 2)).toBe(3)\n})\n\ntest('Squared', () => {\n  expect(squared(2)).toBe(4)\n  expect(squared(12)).toBe(144)\n})\n\ntest('JSON', () => {\n  const input = {\n    foo: 'hello',\n    bar: 'world',\n  }\n\n  const output = JSON.stringify(input)\n\n  expect(output).eq('{\"foo\":\"hello\",\"bar\":\"world\"}')\n  assert.deepEqual(JSON.parse(output), input, 'matches original')\n})\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/test/manual-mock.test.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport * as tinyspy from 'tinyspy'\nimport { expect, test, vi } from 'vitest'\nimport { add, hello, helloMe, squared } from '../src/index.ts'\nimport { minus } from '../src/minus.ts'\nimport { mockJs } from '../src/mock-js.js'\nimport { syncMock } from '../src/mock-sync.ts'\n\n// automocked\nvi.mock(import('tinyspy'))\n\nvi.mock('node:fs', async (importOriginal) => {\n  // can import actual built-in module\n  const _originalModule = await importOriginal()\n  return {\n    readFileSync: vi.fn<() => string>(() => 'mock'),\n  }\n})\n\nvi.mock(import('../src/minus.ts'), async (importOriginal) => {\n  // original module can be imported\n  const _originalModule = await importOriginal()\n  return {\n    minus() {\n      return 42\n    },\n  }\n})\n\nvi.mock(import('../src/mock-js.js'), async () => {\n  return {\n    mockJs() {\n      return 42\n    },\n  }\n})\n\nvi.mock(import('../src/mock-sync.ts'), () => {\n  return {\n    syncMock() {\n      return 42\n    },\n  }\n})\n\nvi.mock(import('../src/index.ts'), async (importOriginal) => {\n  // doesn't hang even though it's circular!\n  const originalModule = await importOriginal()\n  return {\n    squared() {\n      return 42\n    },\n    add() {\n      return 42\n    },\n    helloMe: originalModule.helloMe,\n    hello: 'mock' as 'world', // keep the TS syntax to check that file is transformed\n  } as const\n})\n\ntest('builtin node modules are mocked', () => {\n  expect(vi.isMockFunction(readFileSync)).toBe(true)\n})\n\ntest('deps in node_modules are mocked', () => {\n  expect(vi.isMockFunction(tinyspy.createInternalSpy)).toBe(true)\n})\n\ntest('exports are mocked', () => {\n  expect(hello).toBe('mock')\n  expect(helloMe).toBe('world')\n  expect(add(1, 1)).toBe(42)\n  expect(squared(2)).toBe(42)\n  expect(minus(1, 2)).toBe(42)\n  expect(syncMock()).toBe(42)\n  expect(mockJs()).toBe(42)\n})\n\ntest('importMock works', async () => {\n  // wasnt't mocked by vi.mock, but importMock did\n  const mockedUnmocked = await vi.importMock<typeof import('../src/no-mock.ts')>('../src/no-mock.ts')\n  expect(vi.isMockFunction(mockedUnmocked.notMocked)).toBe(true)\n  expect(mockedUnmocked.notMocked()).toBeUndefined()\n\n  // redirects to correct vi.mock\n  const mockedFs = await vi.importMock<typeof import('node:fs')>('node:fs')\n  expect(mockedFs.readFileSync('return-value-is-mocked')).toBe('mock')\n\n  // automocks to correct vi.mock\n  const mockedIndex = await vi.importMock<typeof import('../src/index.ts')>('../src/index.ts')\n  expect(mockedIndex.squared(2)).toBe(42)\n  expect(mockedIndex.hello).toBe('mock')\n\n  // redirects to __mocks__ even though vi.mock is not present in this file\n  const mockedRedirect = await vi.importMock<typeof import('../src/redirect.ts')>('../src/redirect.ts')\n  expect(mockedRedirect.default).toBe(true)\n})\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/test/mock-async-factory.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { topLevelAnswer } from '../src/from-async.ts'\n\n// for the test to be accurate, the factory has to be async\nvi.mock(import('../src/mock-async.ts'), async () => {\n  return {\n    answer: 42 as 0,\n  }\n})\n\ntest('imported value is defined', () => {\n  expect(topLevelAnswer).toBe(42)\n})\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/test/redirect-mock.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport redirect from '../src/redirect.ts'\n\nvi.mock(import('../src/redirect.ts'))\n\ntest('squared is mocked', () => {\n  expect(redirect).toBe(true)\n})\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/test/suite.test.ts",
    "content": "import { assert, describe, expect, it } from 'vitest'\nimport { getSetupStates, initJsSetup, initTsSetup } from '../src/setups.ts'\n\ndescribe('suite name', () => {\n  it('foo', () => {\n    assert.equal(Math.sqrt(4), 2)\n  })\n\n  it('setups work', () => {\n    // TODO: a separate CLI test that confirms --maxWorkers=1 --no-isolate runs the setup file for every test file\n    expect(initJsSetup).toHaveBeenCalled()\n    expect(initTsSetup).toHaveBeenCalled()\n\n    expect(getSetupStates()).toEqual({\n      jsSetup: true,\n      tsSetup: true,\n    })\n  })\n\n  it('snapshot', () => {\n    expect({ foo: 'bar' }).toMatchSnapshot()\n  })\n\n  it('inline snapshot', () => {\n    expect({ foo: 'bar' }).toMatchInlineSnapshot(`\n      {\n        \"foo\": \"bar\",\n      }\n    `)\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/tsSetup.ts",
    "content": "import { initTsSetup } from './src/setups.ts'\n\ninitTsSetup()\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"module\": \"nodenext\",\n    \"moduleResolution\": \"node16\",\n    \"types\": [\"vitest/importMeta\", \"@types/node\"],\n    \"allowImportingTsExtensions\": true,\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"noEmit\": true,\n    \"sourceMap\": true,\n    \"verbatimModuleSyntax\": true\n  },\n  \"include\": [\"src\", \"test\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "test/cli/fixtures/no-module-runner/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    setupFiles: [\n      './jsSetup.js',\n      './tsSetup.ts',\n    ],\n    includeSource: ['./src/in-source/*'],\n    experimental: {\n      viteModuleRunner: false,\n    },\n    coverage: {\n      provider: 'v8',\n      include: ['./src/**'],\n      exclude: ['**/__mocks__/**']\n    },\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-1.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 1\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-10.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 10\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-11.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 11\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-12.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 12\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-2.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 2\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-3.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 3\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-4.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 4\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-5.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 5\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-6.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 6\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-7.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 7\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-8.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 8\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/no-unexpected-logging/fixture-9.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"test 9\", () => { })\n"
  },
  {
    "path": "test/cli/fixtures/optimize-deps/ssr.test.ts",
    "content": "// @vitest-environment node\n\n// @ts-expect-error untyped\nimport { importMetaUrl } from '@test/test-dep-url'\n\nimport { expect, test } from 'vitest'\n\n// TODO: flaky on Windows\n// https://github.com/vitest-dev/vitest/pull/5215#discussion_r1492066033\ntest('import.meta.url', () => {\n  if (process.platform !== 'win32') {\n    expect(importMetaUrl).toContain('/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/deps_ssr/')\n  }\n})\n"
  },
  {
    "path": "test/cli/fixtures/optimize-deps/web.test.ts",
    "content": "// @vitest-environment happy-dom\n\n// @ts-expect-error untyped\nimport { importMetaUrl } from '@test/test-dep-url'\n\nimport { expect, test } from 'vitest'\n\ntest('import.meta.url', () => {\n  expect(importMetaUrl).toContain('/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/deps/')\n})\n"
  },
  {
    "path": "test/cli/fixtures/otel-tests/basic.test.ts",
    "content": "import { test, expect } from 'vitest';\n\ntest('passes', () => {\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/cli/fixtures/otel-tests/otel.browser.sdk.js",
    "content": "import {\n  WebTracerProvider,\n  ConsoleSpanExporter,\n  SimpleSpanProcessor,\n} from '@opentelemetry/sdk-trace-web'\n\nconst provider = new WebTracerProvider({\n  spanProcessors: [\n    new SimpleSpanProcessor(new ConsoleSpanExporter()),\n  ],\n})\nprovider.register()\nexport default provider\n"
  },
  {
    "path": "test/cli/fixtures/otel-tests/otel.sdk.js",
    "content": "import { NodeSDK } from '@opentelemetry/sdk-node'\n\nconst sdk = new NodeSDK({\n  serviceName: 'vitest',\n})\n\n// sdk.start() do not start to keep traces noop,\n// but Vitest will still be able to see otel\nexport default sdk\n"
  },
  {
    "path": "test/cli/fixtures/otel-tests/vitest.config.ts",
    "content": "export default {\n  test: {\n    // experimental: {\n    //   openTelemetry: {\n    //     enabled: true,\n    //     sdkPath: './otel.sdk.js',\n    //   },\n    // },\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/path-filter/basic.test.ts",
    "content": "import { describe, expect, test } from \"vitest\";\n\ndescribe('basic path filter', () => {\n  test(\"foo\", () => {\n    expect(1).toBe(1);\n  })\n  test(\"bar\", () => {\n    expect(1).toBe(1);\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/path-filter/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/plugin/basic.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"basic\", () => {\n  expect(1).toBe(1);\n})\n"
  },
  {
    "path": "test/cli/fixtures/plugin/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nfunction logHook(...args: unknown[]) {\n  ((globalThis as any).__testHooks ??= []).push(args[0]);\n\n  if (process.env[\"LOG_HOOK\"]) {\n    console.log(...args);\n  }\n}\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: \"test-default\",\n      configureServer() {\n        logHook(\"configureServer(default)\")\n      },\n      buildStart() {\n        logHook(\"buildStart(default)\")\n      },\n      resolveId(source) {\n        logHook(\"resolveId(default)\", source)\n      },\n      transform(_code, id) {\n        logHook(\"transform(default)\", id)\n      },\n    },\n    {\n      name: \"test-pre\",\n      enforce: \"pre\",\n      configureServer() {\n        logHook(\"configureServer(pre)\")\n      },\n      buildStart() {\n        logHook(\"buildStart(pre)\")\n      },\n      resolveId(source) {\n        logHook(\"resolveId(pre)\", source)\n      },\n      transform(_code, id) {\n        logHook(\"transform(pre)\", id)\n      },\n    }\n  ]\n})\n"
  },
  {
    "path": "test/cli/fixtures/project/packages/project_1/base.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"\", () => {\n  expect(1).toBe(1);\n})\n"
  },
  {
    "path": "test/cli/fixtures/project/packages/project_2/base.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"\", () => {\n  expect(1).toBe(1);\n})\n"
  },
  {
    "path": "test/cli/fixtures/project/packages/space_1/base.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"\", () => {\n  expect(1).toBe(1);\n})\n"
  },
  {
    "path": "test/cli/fixtures/project/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    projects: [\n      'packages/*'\n    ]\n  }\n})\n"
  },
  {
    "path": "test/cli/fixtures/public-api/custom.spec.ts",
    "content": "import { afterAll, test } from 'vitest'\n\ndeclare module 'vitest' {\n  interface TaskMeta {\n    done?: boolean\n    custom?: string\n  }\n}\n\nafterAll(({}, suite) => {\n  suite.meta.done = true\n})\n\ntest('custom', ({ task }) => {\n  task.meta.custom = 'some-custom-hanlder'\n})\n\ntest.each([1, 2])('custom %s', () => {\n  // support locations\n})\n"
  },
  {
    "path": "test/cli/fixtures/public-api/vitest.config.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      provider: playwright(),\n      instances: [{ browser: 'chromium' }],\n      headless: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/reported-tasks/1_first.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\nit('runs a test', async () => {\n  await new Promise(r => setTimeout(r, 10))\n  expect(1).toBe(1)\n})\n\nit('fails a test', async () => {\n  await new Promise(r => setTimeout(r, 10))\n  expect(1).toBe(2)\n})\n\nit('fails multiple times', () => {\n  expect.soft(1).toBe(2)\n  expect.soft(3).toBe(3)\n  expect.soft(2).toBe(3)\n})\n\nit('skips an option test', { skip: true })\nit.skip('skips a .modifier test')\nit('skips an ctx.skip() test', (ctx) => ctx.skip())\n\nit('todos an option test', { todo: true })\nit.todo('todos a .modifier test')\n\nit('retries a test', { retry: 5 }, () => {\n  expect(1).toBe(2)\n})\n\nlet counter = 0\nit('retries a test with success', { retry: 5 }, () => {\n  expect(counter++).toBe(2)\n})\n\nit('repeats a test', { repeats: 5 }, () => {\n  expect(1).toBe(2)\n})\n\ndescribe('a group', () => {\n  it('runs a test in a group', () => {\n    expect(1).toBe(1)\n  })\n\n  it('todos an option test in a group', { todo: true })\n\n  describe('a nested group', () => {\n    it('runs a test in a nested group', () => {\n      expect(1).toBe(1)\n    })\n\n    it('fails a test in a nested group', () => {\n      expect(1).toBe(2)\n    })\n\n    it.concurrent('runs first concurrent test in a nested group', () => {\n      expect(1).toBe(1)\n    })\n\n    it.concurrent('runs second concurrent test in a nested group', () => {\n      expect(1).toBe(1)\n    })\n  })\n})\n\ndescribe.todo('todo group', () => {\n  it('test inside todo group', () => {})\n})\n\ndescribe.skip('skipped group', () => {\n  it('test inside skipped group', () => {})\n})\n\ndescribe.shuffle('shuffled group', () => {\n  it('runs a test in a shuffled group', () => {\n    expect(1).toBe(1)\n  })\n})\n\ndescribe.each([1])('each group %s', (groupValue) => {\n  it.each([2])('each test %s', (itValue) => {\n    expect(groupValue + itValue).toBe(3)\n  })\n})\n\nit('registers a metadata', (ctx) => {\n  ctx.task.meta.key = 'value'\n})\n\nit('should not show up as pending test when finished (#9689)', { retry: 2, repeats: 2 }, ({ task }) => {\n  expect(task.result?.state).toBe('run')\n})\n\ndeclare module 'vitest' {\n  interface TaskMeta {\n    key?: string\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/.gitignore",
    "content": "html\n"
  },
  {
    "path": "test/cli/fixtures/reporters/all-passing-or-skipped.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('2 + 3 = 5', () => {\n  expect(2 + 3).toBe(5)\n})\n\ntest.skip('3 + 3 = 6', () => {\n  expect(3 + 3).toBe(6)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/all-skipped.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest.todo('2 + 3 = 5', () => {\n  expect(2 + 3).toBe(5)\n})\n\ntest.skip('3 + 3 = 6', () => {\n  expect(3 + 3).toBe(6)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/basic/basic.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('basic reporter test', () => {\n  // This is a placeholder test file for basic reporter tests.\n})"
  },
  {
    "path": "test/cli/fixtures/reporters/basic/vitest.config.override.js",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    reporters: [\n      {\n        onInit(vitest) {\n          vitest.logger.log('hello from override')\n        },\n      },\n    ],\n  },\n})"
  },
  {
    "path": "test/cli/fixtures/reporters/better-testsuite-name/space-1/test/base.test.ts",
    "content": "import { describe, test } from \"vitest\";\n\ndescribe('space 1', () => {\n  test('base', () => {})\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/better-testsuite-name/space-2/test/base.test.ts",
    "content": "import { describe, test } from \"vitest\";\n\ndescribe('space 2', () => {\n  test('base', () => {})\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/better-testsuite-name/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: ['space-1', 'space-2'],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/code-frame-line-limit.test.ts",
    "content": "import { test, expect } from \"vitest\"\n\ntest(\"basic\", () => {\n  // line length is 85 but highlight makes this line 245 chars\n  expect([{ prop: 7 }, { prop: 7 }, { prop: 7 }, { prop: 7 }]).toBe([{ another: 8 }])\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/console-interleave.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('repro', async () => {\n  console.log(1);\n  await new Promise((r) => setTimeout(r, 10));\n  console.error(2);\n  await new Promise((r) => setTimeout(r, 10));\n  console.log(3);\n});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/console-simple.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\ntest('test', () => {\n  console.log('__test_stdout__')\n  console.error('__test_stderr__')\n  expect(0).toBe(0)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/console-some-failing.test.ts",
    "content": "import { beforeAll, describe, expect, test } from \"vitest\"\n\nconsole.log(\"Log from failed file\")\n\ntest(\"passed test #1\", () => {\n  console.log(\"Log from passed test\")\n})\n\ntest(\"failed test #1\", () => {\n  console.log(\"Log from failed test\")\n  expect(1).toBe(2)\n})\n\ndescribe(\"failed suite #1\", () => {\n  beforeAll(() => {\n    console.log(\"Log from failed suite\")\n  })\n\n  test(\"passed test #2\", () => {\n    console.log(\"Log from passed test\")\n  })\n\n  test(\"failed test #2\", () => {\n    console.log(\"Log from failed test\")\n    expect(2).toBe(3)\n  })\n})\n\ndescribe(\"passed suite #2\", () => {\n  beforeAll(() => {\n    console.log(\"Log from passed suite\")\n  })\n\n  test(\"passed test #3\", () => {\n    console.log(\"Log from passed test\")\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/console.test.ts",
    "content": "import { afterAll, beforeAll, describe, expect, test } from 'vitest'\n\nbeforeAll(() => {\n  console.log('global stdin beforeAll')\n  console.error('global stderr beforeAll')\n})\n\nafterAll(() => {\n  console.log('global stdin afterAll')\n  console.error('global stderr afterAll')\n})\n\ndescribe('suite', () => {\n  beforeAll(() => {\n    console.log('suite stdin beforeAll')\n    console.error('suite stderr beforeAll')\n  })\n\n  afterAll(() => {\n    console.log('suite stdin afterAll')\n    console.error('suite stderr afterAll')\n  })\n\n  describe('nested suite', () => {\n    beforeAll(() => {\n      console.log('nested suite stdin beforeAll')\n      console.error('nested suite stderr beforeAll')\n    })\n\n    afterAll(() => {\n      console.log('nested suite stdin afterAll')\n      console.error('nested suite stderr afterAll')\n    })\n\n    test('test', async () => {\n      await new Promise((resolve) => setTimeout(resolve, 100))\n      expect(true).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/custom-diff-config.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('', () => {\n  expect({ foo: 1 }).toMatchInlineSnapshot('xxx')\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/custom-diff-config.ts",
    "content": "export default {\n  aAnnotation: 'Expected to be',\n  bAnnotation: 'But got',\n}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/custom-error/basic.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('no name object', () => {\n  throw { noName: 'hi' };\n});\n\ntest('string', () => {\n  throw \"hi\";\n});\n\ntest('number', () => {\n  throw 1234;\n});\n\ntest('number name object', () => {\n  throw { name: 1234 };\n});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/custom-error/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/default/a.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\ndescribe('a passed', () => {\n  test.each([1, 2, 3])('a%d test', (d) => {\n    expect(d).toBe(d)\n  })\n  describe('nested a', () => {\n    test.each([1, 2, 3])('nested a%d test', (d) => {\n      expect(d).toBe(d)\n    })\n  })\n})\n\ndescribe('a failed', () => {\n  test.each([1, 2, 3])('a failed %d test', (d) => {\n    expect(d).toBe(d)\n  })\n  test('a failed test', () => {\n    expect(1).toBe(2)\n  })\n  describe('nested a failed', () => {\n    test.each([1, 2, 3])('nested a failed %d test', (d) => {\n      expect(d).toBe(d)\n    })\n  })\n})\n\ndescribe('a skipped', () => {\n  test('skipped with note', ({ skip }) => {\n    skip('reason')\n  })\n\n  test('condition', ({ skip }) => {\n    skip(true)\n  })\n\n  test('condition with note', ({ skip }) => {\n    skip(true, 'note')\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/default/b1.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\ndescribe('b1 passed', () => {\n  test.each([1, 2, 3])('b%d test', (d) => {\n    expect(d).toBe(d)\n  })\n  describe('nested b', () => {\n    test.each([1, 2, 3])('nested b%d test', (d) => {\n      expect(d).toBe(d)\n    })\n  })\n})\n\ndescribe('b1 failed', () => {\n  test.each([1, 2, 3])('b%d test', (d) => {\n    expect(d).toBe(d)\n  })\n  test('b failed test', () => {\n    expect(1).toBe(2)\n  })\n  describe('nested b', () => {\n    test.each([1, 2, 3])('nested b%d test', (d) => {\n      expect(d).toBe(d)\n    })\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/default/b2.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\ndescribe('b2 passed', () => {\n  test.each([1, 2, 3])('b%d test', (d) => {\n    expect(d).toBe(d)\n  })\n  describe('nested b', () => {\n    test.each([1, 2, 3])('nested b%d test', (d) => {\n      expect(d).toBe(d)\n    })\n  })\n})\n\ndescribe('b2 failed', () => {\n  test.each([1, 2, 3])('b%d test', (d) => {\n    expect(d).toBe(d)\n  })\n  test('b failed test', () => {\n    expect(1).toBe(2)\n  })\n  describe('nested b', () => {\n    test.each([1, 2, 3])('nested b%d test', (d) => {\n      expect(d).toBe(d)\n    })\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/default/print-index.test.ts",
    "content": "import { describe, expect, test } from \"vitest\";\n\ndescribe('passed', () => {\n  test.each([4, 5, 6])('0-based index of the test case is %#', (d) => {\n    expect(d).toBe(d)\n  })\n\n  test.each([4, 5, 6])('1-based index of the test case is %$', (d) => {\n    expect(d).toBe(d)\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/default/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nprocess.stdin.isTTY = true\nprocess.stdin.setRawMode = () => process.stdin\n\nexport default defineConfig({\n  test: {\n    reporters: [['default', { isTTY: true, summary: false }]],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/duration/basic.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('fast', () => {\n});\n\ntest('slow', async () => {\n  await sleep(300)\n});\n\nconst sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))\n"
  },
  {
    "path": "test/cli/fixtures/reporters/duration/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    slowTestThreshold: 290\n  }\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/error-props/basic.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('throws', () => {\n  const error = new Error('error with properties')\n  Object.assign(error, {\n    code: 404,\n    status: 'not found',\n  })\n  throw error\n});\n\n"
  },
  {
    "path": "test/cli/fixtures/reporters/error-to-json.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"error serialization with toJSON\", () => {\n  throw Object.assign(new Error(\"hello\"), { date: new Date(0) })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/error.test.ts",
    "content": "import { afterAll, it, expect } from \"vitest\";\n\nafterAll(() => {\n  throwSuite()\n})\n\nit('stack', () => {\n  throwDeep()\n})\n\nit('diff', () => {\n  expect({ hello: 'x' }).toEqual({ hello: 'y' })\n})\n\nit('unhandled', () => {\n  (async () => throwSimple())()\n})\n\nit('no name object', () => {\n  throw { noName: 'hi' };\n});\n\nit('string', () => {\n  throw \"hi\";\n});\n\nit('number', () => {\n  throw 1234;\n});\n\nit('number name object', () => {\n  throw { name: 1234 };\n});\n\nit('xml', () => {\n  throw new Error('error message that has XML in it <div><input/></div>');\n})\n\nfunction throwDeep() {\n  throwSimple()\n}\n\nfunction throwSimple() {\n  throw new Error('throwSimple')\n}\n\nfunction throwSuite() {\n  throw new Error('throwSuite')\n}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/function-as-name.bench.ts",
    "content": "import { bench } from 'vitest'\n\nconst options = {\n  time: 0,\n  iterations: 3,\n  warmupTime: 0,\n  warmupIterations: 0,\n}\n\nfunction foo() {}\nclass Bar {}\n\nbench(foo, () => {}, options)\nbench(Bar, () => {}, options)\nbench(() => {}, () => {}, options)\n"
  },
  {
    "path": "test/cli/fixtures/reporters/function-as-name.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\nfunction foo() {}\nclass Bar {}\n\ndescribe(foo, () => {\n  test(Bar, () => {\n    expect(0).toBe(0)\n  })\n})\n\ndescribe(Bar, () => {\n  test(foo, () => {\n    expect(0).toBe(0)\n  })\n})\n\ndescribe(() => {}, () => {\n  test(foo, () => {\n    expect(0).toBe(0)\n  })\n})\n\ndescribe(foo, () => {\n  test(() => {}, () => {\n    expect(0).toBe(0)\n  })\n})\n\ndescribe.each([1])(foo, () => {\n  test.each([1])(foo, () => {\n    expect(0).toBe(0)\n  })\n})\n\ndescribe.each([1])(Bar, () => {\n  test.each([1])(Bar, () => {\n    expect(0).toBe(0)\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/github-actions/flaky/math.spec.ts",
    "content": "import { test } from 'vitest'\n\ntest('should add numbers correctly', { retry: 5 }, ({ expect, task }) => {\n  expect(task.result?.retryCount).toBe(0)\n})\n\ntest('should subtract numbers correctly', { retry: 5 }, ({ expect, task }) => {\n  expect(task.result?.retryCount).toBe(1)\n})\n\ntest('should multiply numbers correctly', { retry: 5 }, ({ expect, task }) => {\n  expect(task.result?.retryCount).toBe(5)\n})\n\ntest('should divide numbers correctly', { retry: 5 }, ({ expect, task }) => {\n  expect(task.result?.retryCount).toBe(2)\n})\n\ntest('should handle edge cases', { retry: 5 }, ({ expect, task }) => {\n  expect(task.result?.retryCount).toBe(4)\n})\n\ntest('should validate input properly', { retry: 5 }, ({ expect, task }) => {\n  expect(task.result?.retryCount).toBe(4)\n})\n\ntest.todo('should compute percentages')\n\ntest.skip('should divide by zero', ({ expect }) => {\n  expect.unreachable()\n})\n\ntest.fails('should work with linear equations', ({ expect }) => {\n  expect(true).toBe(false)\n})\n\ntest('should compute square root of negative numbers', ({ expect }) => {\n  expect.unreachable()\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/github-actions/flaky/network.spec.ts",
    "content": "import { describe, test } from 'vitest'\n\ndescribe('network', () => {\n  test('should fetch user data from API', { retry: 3 }, ({ expect, task }) => {\n    expect(task.result?.retryCount).toBe(2)\n  })\n\n  test('should handle network timeouts gracefully', { retry: 4 }, ({ expect, task }) => {\n    expect(task.result?.retryCount).toBe(4)\n  })\n\n  test('should retry failed requests', { retry: 3 }, ({ expect, task }) => {\n    expect(task.result?.retryCount).toBe(1)\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/implementations/custom-reporter.js",
    "content": "export default class TestReporter {\n  onInit(ctx) {\n    this.ctx = ctx\n  }\n\n  onTestRunEnd() {\n    this.ctx.logger.log('hello from custom reporter')\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/implementations/custom-reporter.ts",
    "content": "import type { Reporter, Vitest } from 'vitest/node'\n\nexport default class TestReporter implements Reporter {\n  ctx!: Vitest\n  options?: unknown\n\n  constructor(options?: unknown) {\n    this.options = options\n  }\n\n  onInit(ctx: Vitest) {\n    this.ctx = ctx\n  }\n\n  onTestRunEnd() {\n    this.ctx.logger.log('hello from custom reporter')\n\n    if (this.options) {\n      this.ctx.logger.log(`custom reporter options ${JSON.stringify(this.options)}`)\n    }\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/import-durations-25ms-throws.ts",
    "content": "await new Promise(resolve => setTimeout(resolve, 25))\n\nthrow new Error('test')\n\nexport {}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/import-durations-25ms.ts",
    "content": "await new Promise(resolve => setTimeout(resolve, 25))\n\nexport {}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/import-durations-50ms.ts",
    "content": "import './import-durations-25ms'\n\nawait new Promise(resolve => setTimeout(resolve, 50))\n"
  },
  {
    "path": "test/cli/fixtures/reporters/import-durations-throws.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport './import-durations-25ms-throws'\n\ntest('works', async () => {\n  expect(true).toBe(true)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/import-durations.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport './import-durations-50ms'\n\ntest('works', async () => {\n  expect(true).toBe(true)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/indicator-position.test.js",
    "content": "/* eslint-disable no-multiple-empty-lines */\r\n// this file should be in CRLF format\r\nimport { expect, test } from 'vitest'\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\ntest('', async () => {\r\n  expect(1 + 1).toBe(3)\r\n  expect(1 + 1).toBe(2)\r\n  expect(2 + 2).toBe(4)\r\n})\r\n"
  },
  {
    "path": "test/cli/fixtures/reporters/invalid-diff-config.ts",
    "content": "export const diffOptions = {}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/json-fail-import.test.ts",
    "content": "throw new Error('failed test suite')\n"
  },
  {
    "path": "test/cli/fixtures/reporters/json-fail.test.ts",
    "content": "import { expect, test } from 'vitest'\n\n// I am comment1\n// I am comment2\ntest('should fail', { tags: ['fail'] }, () => {\n  // eslint-disable-next-line no-console\n  console.log('json-fail>should fail')\n  expect(2).toEqual(1)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/junit-cli-options/sample.test.ts",
    "content": "import { test, expect } from 'vitest'\n\ntest('simple test', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/junit-cli-options/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    reporters: [\n      ['junit', {\n        suiteName: 'custom-suite-name',\n        addFileAttribute: true,\n      }],\n    ],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/long-loading-task.test.ts",
    "content": "import { test } from 'vitest'\n\nawait new Promise(r => setTimeout(r, 500))\n\ntest('works', () => {})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/many-errors/basic.test.ts",
    "content": "import { test } from \"vitest\"\n\ntest.for([...Array(20)].map((_, j) => j))('%i', (i) => {\n  throw new Error(`error-${i}`)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-errors/basic.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\n// not merged\ntest.for([1, 2])(\"test-a %$\", (n) => {\n  expect(n).toBe(0);\n});\n\n// merged\ntest.for([1, 2])(\"test-b %$\", (n) => {\n  expect(1).toBe(0);\n});\n\n// not merged\ntest.each([\n  {\n    actual: [\"a\".repeat(50)],\n    expected: [\"b\".repeat(50)],\n  },\n  {\n    actual: [\"c\".repeat(50)],\n    expected: [\"d\".repeat(50)],\n  },\n])(\"test-c %$\", async ({ actual, expected }) => {\n  expect(actual).toEqual(expect.arrayContaining(expected));\n});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-reports/first.test.ts",
    "content": "import { test, expect, beforeEach } from 'vitest'\n\nconsole.log('global scope')\n\nbeforeEach(() => {\n  console.log('beforeEach')\n})\n\ntest('test 1-1', () => {\n  expect(1).toBe(1)\n})\n\ntest('test 1-2', () => {\n  console.log('test 1-2')\n  expect(1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-reports/second.test.ts",
    "content": "import { describe, test, expect } from 'vitest'\n\ntest('test 2-1', () => {\n  console.log('test 2-1')\n  expect(1).toBe(2)\n})\n\ndescribe('group', () => {\n  test('test 2-2', () => {\n    expect(1).toBe(1)\n  })\n\n  test('test 2-3', () => {\n    expect(1).toBe(1)\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-reports/vitest.config.js",
    "content": "export default {}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-reports-module-graph/basic.test.ts",
    "content": "import { test, expect } from 'vitest'\nimport { formatHello } from './sub/format'\nimport { hello } from './util'\n\ntest('passes', () => {\n  expect(hello()).toBe('Hello, graph!')\n  expect(formatHello()).toBe('Hello, graph!')\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-reports-module-graph/second.test.ts",
    "content": "import { test, expect } from 'vitest'\nimport { hello } from './util'\nimport * as obug from \"obug\"\n\ntest('also passes', () => {\n  expect(hello()).toBe('Hello, graph!')\n})\n\ntest('external', () => {\n  expect(obug).toBeTypeOf('object')\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-reports-module-graph/sub/format.ts",
    "content": "import { getSubject } from './subject'\n\nexport function formatHello() {\n  return `Hello, ${getSubject()}!`\n}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-reports-module-graph/sub/subject.ts",
    "content": "export function getSubject() {\n  return 'graph'\n}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-reports-module-graph/util.ts",
    "content": "import { getSubject } from './sub/subject'\n\nexport function hello() {\n  return `Hello, ${getSubject()}!`\n}\n"
  },
  {
    "path": "test/cli/fixtures/reporters/merge-reports-module-graph/vitest.config.js",
    "content": "import { defineConfig } from \"vitest/config\"\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/metadata/metadata.test.ts",
    "content": "import {expect, test } from 'vitest';\n\ntest('pass', ({ task }) => {\n  task.meta.custom = \"Passing test added this\"\n});\n\n\ntest('fails', ({ task }) => {\n  task.meta.custom = \"Failing test added this\"\n\n  expect(true).toBe(false)\n});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/metadata/vitest.config.ts",
    "content": "export default {}"
  },
  {
    "path": "test/cli/fixtures/reporters/ok.test.ts",
    "content": "import { test } from \"vitest\"\n\ntest(\"ok\", () => {});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/pass-and-skip-test-suites.test.ts",
    "content": "import { describe, test } from 'vitest'\n\ntest('passing test #1', () => {})\n\ndescribe(\"passing suite\", () => {\n  test('passing test #2', () => {})\n})\n\ntest.skip('skipped test #1', () => {})\n\ntest.todo('todo test #1')\n\ndescribe.skip(\"skipped suite\", () => {\n  test('skipped test #2', () => {})\n})"
  },
  {
    "path": "test/cli/fixtures/reporters/project-name/example.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"example test\", () => {\n  //\n})"
  },
  {
    "path": "test/cli/fixtures/reporters/project-name/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    watch: false,\n    name: {\n      label: \"Example project\",\n      color: \"magenta\",\n    },\n    env: {\n      CI: '1',\n      FORCE_COLOR: '1',\n      NO_COLOR: undefined,\n      GITHUB_ACTIONS: undefined,\n    },\n  },\n});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/repeats.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('repeat couple of times',{ repeats: 3 },  () => {\n  expect(true).toBe(true)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/reporter-error/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('basic', () => {\n  console.log('trigger-reporter-error')\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/retry.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nlet number = 0\n\ntest('pass after retries', () => {\n  expect(number++).toBe(3)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/some-failing.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('2 + 3 = 5', () => {\n  expect(2 + 3).toBe(5)\n})\n\ntest('3 + 3 = 7', () => {\n  expect(3 + 3).toBe(7)\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/suite-hook-failure/basic.test.ts",
    "content": "import {\n  afterAll,\n  beforeAll,\n  describe,\n  it,\n} from 'vitest';\n\ndescribe('suite with beforeAll', () => {\n  beforeAll(() => {\n    throw new Error('beforeAll error');\n  });\n\n  it('ok 1', () => {});\n  it('ok 2', () => {});\n  it.skip('skip 1', () => {});\n});\n\ndescribe('suite with afterAll', () => {\n  afterAll(() => {\n    throw new Error('afterAll error');\n  });\n\n  it('ok 1', () => {});\n  it('ok 2', () => {});\n  it.skip('skip 1', () => {});\n});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/suite-hook-failure/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/test-for-title.test.ts",
    "content": "import { expect, test } from \"vitest\"\n\ntest.for([\n  { 0: 'a', 1: {}, 2: { te: \"st\" } },\n  { \"0\": 'b', \"1\": [], \"2\": [\"test\"] },\n])('test.for object : 0 = $0, 2 = $2', () => {});\n\ntest.each([\n  { 0: 'a', 1: {}, 2: { te: \"st\" } },\n  { \"0\": 'b', \"1\": [], \"2\": [\"test\"] },\n])('test.each object : 0 = $0, 2 = $2 ', () => {});\n\ntest.for([\n  ['a', {}, { te: \"st\" }],\n  ['b', [], [ \"test\" ]],\n])('test.for array : 0 = $0, 2 = $2', () => {});\n\ntest.each([\n  ['a', {}, { te: \"st\" }],\n  ['b', [], [ \"test\" ]],\n])('test.each array : 0 = $0, 2 = $2', () => {});\n\ntest.each([\n  { a: 1, b: 1, expected: 2 },\n  { a: 1, b: 2, expected: 3 },\n  { a: 2, b: 1, expected: 3 },\n])('object : add($a, $b) -> $expected', ({ a, b, expected }) => {\n  expect(a + b).toBe(expected)\n})\n\ntest.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('array : add($0, $1) -> $2', (a, b, expected) => {\n  expect(a + b).toBe(expected)\n})\n\ntest.for([\n  [{ k1: \"v1\" }, { k2: \"v2\" }],\n])('first array element is object: 0 = $0, 1 = $1, k1 = $k1, k2 = $k2', () => {})\n\ntest.for([\n  [\"foo\", \"bar\"],\n])('first array element is not object: 0 = $0, 1 = $1, k = $k', () => {})\n\ntest.for([\n  { k: \"v1\" },\n  { k: \"v2\" },\n])('not array: 0 = $0, 1 = $1, k = $k', () => {})\n\n\ntest.each([[343434, \"$343,434.00\"]])(\n  \"handles whole numbers: %s as %s\",\n  (input, expected) => {\n    expect(\n      new Intl.NumberFormat(\"en-US\", {\n        style: \"currency\",\n        currency: \"USD\",\n      }).format(input),\n    ).toBe(expected);\n  },\n);\n\ntest.each([{ a: \"$b\", b: \"yay\" }])(\"%o\", () => {});\ntest.each([{ a: \"%o\" }])(\"$a\", () => {});\ntest.each([{ a: \"%o\" }])(\"%o\", () => {});\ntest.each([{ a: \"%o\" }])(\"$a %o\", () => {});\ntest.each([{ a: \"%o\" }])(\"%o $a\", () => {});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/verbose/example-1.test.ts",
    "content": "import { test, describe, expect } from \"vitest\";\n\ntest(\"test pass in root\", () => {});\n\ntest.skip(\"test skip in root\", () => {});\n\ndescribe(\"suite in root\", () => {\n  test(\"test pass in 1. suite #1\", () => {});\n\n  test(\"test pass in 1. suite #2\", () => {});\n\n  describe(\"suite in suite\", () => {\n    test(\"test pass in nested suite #1\", () => {});\n\n    test(\"test pass in nested suite #2\", () => {});\n\n    describe(\"suite in nested suite\", () => {\n      test(\"test failure in 2x nested suite\", () => {\n        expect(\"should fail\").toBe(\"as expected\");\n      });\n    });\n  });\n});\n\ndescribe.skip(\"suite skip in root\", () => {\n  test(\"test 1.3\", () => {});\n\n  describe(\"suite in suite\", () => {\n    test(\"test in nested suite\", () => {});\n\n    test(\"test failure in nested suite of skipped suite\", () => {\n      expect(\"should fail\").toBe(\"but should not run\");\n    });\n  });\n});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/verbose/example-2.test.ts",
    "content": "import { test, describe } from \"vitest\";\n\ntest(\"test 0.1\", () => {});\n\ntest.skip(\"test 0.2\", () => {});\n\ndescribe(\"suite 1.1\", () => {\n  test(\"test 1.1\", () => {});\n});\n"
  },
  {
    "path": "test/cli/fixtures/reporters/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    tags: [{ name: 'fail' }],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/reporters/with-syntax-error.test.js",
    "content": "// NOTE: This file is intentionally not valid JavaScript.\n\nit('should fail', () => {\n)\n"
  },
  {
    "path": "test/cli/fixtures/restricted-fs/src/math.js",
    "content": "export function multiply(a, b) {\n  return a * b\n}\n"
  },
  {
    "path": "test/cli/fixtures/restricted-fs/tests/basic.spec.js",
    "content": "import { expect, it } from 'vitest'\nimport { multiply } from '../src/math'\n\nit('2 x 2 = 4', () => {\n  expect(multiply(2, 2)).toBe(4)\n  expect(multiply(2, 2)).toBe(Math.sqrt(16))\n})\n"
  },
  {
    "path": "test/cli/fixtures/restricted-fs/vitest.config.ts",
    "content": "import { resolve } from 'pathe'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [\n    {\n      // simulates restrictive FS\n      name: 'restrict-fs',\n      config() {\n        return {\n          server: {\n            fs: {\n              allow: [\n                resolve(import.meta.dirname, 'src'),\n              ],\n            },\n          },\n        }\n      },\n    },\n  ],\n  test: {\n    environment: 'jsdom',\n    include: ['tests/**/*.spec.{js,ts}'],\n    setupFiles: [\n      './vitest.setup.js',\n    ],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/restricted-fs/vitest.setup.js",
    "content": "globalThis.SOME_TEST_VARIABLE = '3'\n"
  },
  {
    "path": "test/cli/fixtures/retry-config/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    retry: {\n      count: 3,\n      // @ts-expect-error\n      condition: () => true\n    }\n  }\n})\n"
  },
  {
    "path": "test/cli/fixtures/rollup-error/not-found-export.test.ts",
    "content": "import \"vite/no-such-export\"\n"
  },
  {
    "path": "test/cli/fixtures/rollup-error/not-found-package.test.ts",
    "content": "import '@vitejs/no-such-package'\n"
  },
  {
    "path": "test/cli/fixtures/rollup-error/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\n// pnpm -C test/cli test -- --root fixtures/rollup-error --environment happy-dom\n// pnpm -C test/cli test -- --root fixtures/rollup-error --environment node\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/setup-files/console-setup.ts",
    "content": "// eslint-disable-next-line no-console\nconsole.log('setup')\n\nconsole.error('setup')\n"
  },
  {
    "path": "test/cli/fixtures/setup-files/empty-setup.ts",
    "content": ""
  },
  {
    "path": "test/cli/fixtures/setup-files/empty.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('empty', () => {})\n"
  },
  {
    "path": "test/cli/fixtures/skip-note/basic.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('my skipped test', ctx => {\n  ctx.skip('custom message')\n})\n"
  },
  {
    "path": "test/cli/fixtures/ssr-runner/basic.test.ts",
    "content": "import { test, expect } from 'vitest'\n\ntest('basic', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/ssr-runner/test-runner.js",
    "content": "import * as vite from 'vite'\nexport default vite\n"
  },
  {
    "path": "test/cli/fixtures/ssr-runner/vitest.config.ts",
    "content": "import assert from 'node:assert'\nimport { isRunnableDevEnvironment, createServer } from 'vite'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'test-ssr-runner',\n      // test ssr runner.import() with correct external semantics in configureServer hook\n      // vite should be externalized and reference-equal to the directly imported one\n      async configureServer(server) {\n        const ssr = server.environments.ssr\n        if (isRunnableDevEnvironment(ssr)) {\n          const m = await ssr.runner.import<{ default: typeof import(\"vite\") }>('./test-runner.js')\n          assert(m.default.createServer === createServer)\n          ;(globalThis as any).__testSsrRunner = m.default.version\n        }\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "test/cli/fixtures/ssr-runner-project/project/basic.test.ts",
    "content": "import { test, expect } from 'vitest'\n\ntest('basic', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/ssr-runner-project/project/test-runner.js",
    "content": "import * as vite from 'vite'\nexport default vite\n"
  },
  {
    "path": "test/cli/fixtures/ssr-runner-project/project/vitest.config.ts",
    "content": "import assert from 'node:assert'\nimport { isRunnableDevEnvironment, createServer } from 'vite'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'test-ssr-runner',\n      // test ssr runner.import() with correct external semantics in configureServer hook\n      // vite should be externalized and reference-equal to the directly imported one\n      async configureServer(server) {\n        const ssr = server.environments.ssr\n        if (isRunnableDevEnvironment(ssr)) {\n          const m = await ssr.runner.import<{ default: typeof import(\"vite\") }>('./test-runner.js')\n          assert(m.default.createServer === createServer)\n          ;(globalThis as any).__testSsrRunnerProject = m.default.version\n        }\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "test/cli/fixtures/ssr-runner-project/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    projects: [\"project\"],\n  },\n});\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/add-in-imba.test.imba",
    "content": "import {it, expect} from 'vitest'\n\nexport def add(...args)\n\treturn args.reduce((do(a, b) a + b), 0)\n\nit \"add\", do\n\texpect(add()).toBe 0\n\texpect(add(1)).toBe 3\n\texpect(add(1, 2, 3)).toBe 6\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/add-in-js.test.js",
    "content": "/* body */\nimport { expect, it } from 'vitest'\nimport { add } from './utils'\n\nit('add', () => {\n  expect(add()).toBe(100)\n  expect(add(1)).toBe(1)\n  return expect(add(1, 2, 3)).toBe(6)\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/add.test.ts",
    "content": "/* body */\nimport { expect, it } from 'vitest'\nimport { add } from './utils'\n\ninterface Num {\n  count: number\n}\n\nconst a: Num = { count: 10 }\n\nit('add', () => {\n  expect(add(a.count)).toBe(100)\n  expect(add(1)).toBe(1)\n  return expect(add(1, 2, 3)).toBe(6)\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/error-in-deps.test.js",
    "content": "import { test } from 'vitest'\nimport { add } from './foo'\n\ntest('error in deps', () => {\n  add()\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/error-in-package.test.js",
    "content": "import { test } from 'vitest'\nimport testStack from \"@test/test-dep-error\"\nimport testStackTs from \"@test/test-dep-error/ts.ts\"\nimport testStackTranspiled from \"@test/test-dep-error/transpiled.js\"\nimport testStackTranspiledInline from \"@test/test-dep-error/transpiled-inline.js\"\n\ntest('js', () => {\n  testStack()\n})\n\ntest('ts', () => {\n  testStackTs()\n})\n\ntest('transpiled', () => {\n  testStackTranspiled()\n})\n\ntest('transpiled inline', () => {\n  testStackTranspiledInline()\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/error-with-stack.test.js",
    "content": "import { test } from 'vitest'\n\ntest('error in deps', () => {\n  a()\n})\n\nfunction a() {\n  b()\n}\n\nfunction b() {\n  c()\n}\n\nfunction c() {\n  d()\n}\n\nfunction d() {\n  throw new Error('Something truly horrible has happened!')\n}\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/foo.js",
    "content": "export function add() {\n  // eslint-disable-next-line no-undef\n  return bar()\n}\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/frame.spec.imba",
    "content": "describe \"Test\" do\n\ttest(\"1+1\") do\n\t\texpect(1+1).toBe 2\n\t\tciyet."
  },
  {
    "path": "test/cli/fixtures/stacktraces/mocked-global.test.js",
    "content": "/* eslint-disable no-undef */\n\nvi.mock('./path')\n\ntest('failed', () => {\n  expect(1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/mocked-imported.test.js",
    "content": "import { expect, test, vi } from 'vitest'\n\nvi.mock('./path')\n\ntest('failed', () => {\n  expect(1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/mocked-imported.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\nvi.mock('./path')\n\ntest('failed', () => {\n  expect(1).toBe(2)\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/require-assertions.test.js",
    "content": "import { test } from 'vitest'\n\ntest('assertion is not called', () => {\n  // no expect\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/reset-modules.test.ts",
    "content": "import { assert, describe, expect, it, vi } from 'vitest'\n\ndescribe('suite name', () => {\n  it('foo', () => {\n    vi.resetModules()\n    // a comment here\n    // another comment\n    // another comment\n    // another comment\n    // another comment\n    // another comment\n    // this will mess up the stacktrace lines\n    expect(1 + 1).eq(2)\n    expect(2 + 1).eq(3)\n    assert.equal(Math.sqrt(4), 2)\n    expect(Math.sqrt(4)).toBe(1)\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/setup.js",
    "content": "import { expect, test, vi } from 'vitest'\n\nglobalThis.vi = vi\nglobalThis.test = test\nglobalThis.expect = expect\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/utils.ts",
    "content": "export function add(...args: number[]) {\n  return args.reduce((a, b) => a + b, 0)\n}\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [{\n    name: 'vite-plugin-imba',\n    transform(code, id) {\n      if (id.endsWith('frame.spec.imba')) {\n        // eslint-disable-next-line no-throw-literal\n        throw {\n          name: 'imba-parser error',\n          id,\n          message: 'Unexpected \\'CALL_END\\'',\n          code,\n          frame:\n              '4 | test(\"1+1\") do\\n5 |  expect(1+1).toBe 2\\n6 |  frame.\\n  |        ^\\n7 |\\n',\n          loc: {\n            line: 3,\n            column: 11,\n            file: id,\n          },\n        }\n      }\n      if (id.endsWith('.imba')) {\n        return {\n          code:\n            '\\n/*body*/\\nimport {it,expect} from \\'vitest\\';\\n\\nexport function add(...args){\\n\\t\\n\\treturn args.reduce(function(a,b) { return a + b; },0);\\n};\\n\\nit(\"add\",function() {\\n\\t\\n\\texpect(add()).toBe(0);\\n\\texpect(add(1)).toBe(3);\\n\\treturn expect(add(1,2,3)).toBe(6);\\n});',\n          map: {\n            version: 3,\n            file: 'add-in-imba.test.imba',\n            names: [],\n            sourceRoot: '',\n            sources: ['add-in-imba.test.imba'],\n            sourcesContent: [\n              'import {it, expect} from \\'vitest\\'\\n\\nexport def add(...args)\\n\\treturn args.reduce((do(a, b) a + b), 0)\\n\\nit \"add\", do\\n\\texpect(add()).toBe 0\\n\\texpect(add(1)).toBe 3\\n\\texpect(add(1, 2, 3)).toBe 6\\n',\n            ],\n            mappings:\n              ';;AAAA,MAAM,EAAE,EAAE,CAAE,MAAM,OAAO,QAAQ;;AAEjC,MAAM,CAAC,QAAG,CAAC,GAAG,IAAI,IAAI,CAAC;;CACtB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAE,QAAE,CAAC,CAAC,CAAE,CAAC,IAAE,OAAA,CAAC,CAAC,CAAC,CAAC,CAAC,IAAG,CAAC,CAAC;CAAA;;AAExC,EAAE,CAAC,KAAK,CAAE,QAAE,GAAA;;CACX,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;CACpB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;CACrB,OAAA,MAAM,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;CAAA,CAH1B;AAIF;',\n          },\n        }\n      }\n    },\n  }],\n  test: {\n    isolate: false,\n    pool: 'forks',\n    include: ['**/*.{test,spec}.{imba,?(c|m)[jt]s?(x)}'],\n    setupFiles: ['./setup.js'],\n    expect: {\n      requireAssertions: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces-custom-helper/basic.test.ts",
    "content": "import { test } from \"vitest\";\nimport { assertHelper, assertHelperAsync, assertHelperBad } from \"./helper.js\";\n\ntest(\"sync\", async () => {\n  assertHelper(3, 4);\n});\n\ntest(\"async\", async () => {\n  await assertHelperAsync(3, 4)\n})\n\ntest(\"bad\", () => {\n  assertHelperBad(3, 4)\n})\n"
  },
  {
    "path": "test/cli/fixtures/stacktraces-custom-helper/helper.ts",
    "content": "import { expect } from \"vitest\";\n\nexport function assertHelper(expected: any, actual: any) {\n  try {\n    expect(expected).toBe(actual);\n  } catch (error: any) {\n    Error.captureStackTrace(error, assertHelper);\n    throw error;\n  }\n}\n\nexport async function assertHelperAsync(expected: any, actual: any) {\n  try {\n    await Promise.resolve();\n    expect(expected).toBe(actual);\n  } catch (error: any) {\n    Error.captureStackTrace(error, assertHelperAsync);\n    throw error;\n  }\n}\n\nexport function assertHelperBad(expected: any, actual: any) {\n  expect(expected).toBe(actual);\n}\n"
  },
  {
    "path": "test/cli/fixtures/standalone/basic.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest(\"example\", () => {\n  expect(1).toBe(1);\n})\n"
  },
  {
    "path": "test/cli/fixtures/standalone/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/test-tags/basic.test.ts",
    "content": "import { describe, test } from 'vitest'\n\ndescribe('suite 1', { tags: ['suite', 'alone'] }, () => {\n  test('test 1', () => {})\n  test('test 2', { tags: ['test'] }, () => {})\n\n  describe('suite 2', { tags: ['suite_2', 'suite'] }, () => {\n    test('test 3', () => {})\n    test('test 4', { tags: ['test_2'] }, () => {})\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/tty/example.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { getHelloWorld } from './example'\n\ntest('getHello', async () => {\n  expect(getHelloWorld()).toBe('Hello world')\n})\n"
  },
  {
    "path": "test/cli/fixtures/tty/example.ts",
    "content": "export function getHelloWorld() {\n  return 'Hello world'\n}\n"
  },
  {
    "path": "test/cli/fixtures/tty/math.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { sum } from './math'\n\ntest('sum', () => {\n  expect(sum(1, 2)).toBe(3)\n})\n"
  },
  {
    "path": "test/cli/fixtures/tty/math.ts",
    "content": "export function sum(a: number, b: number) {\n  return a + b\n}\n"
  },
  {
    "path": "test/cli/fixtures/tty/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\n// Patch stdin on the process so that we can fake it to seem like a real interactive terminal and pass the TTY checks\nprocess.stdin.isTTY = true\nprocess.stdin.setRawMode = () => process.stdin\n\nexport default defineConfig({\n  test: {\n    watch: false,\n    reporters: 'verbose',\n    teardownTimeout: 5_000,\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/vitest.config.js",
    "content": "// an empty config so the main one is not accidentally inherited by the tests\nexport default {}\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/import-external-css-assets.test.js",
    "content": "// @vitest-environment jsdom\n\nimport { describe, expect, test } from 'vitest'\n\nimport './src/external/css/empty.css'\nimport './src/external/css/processed.css'\n\nimport processedModule from './src/external/css/processed.module.css'\n\nimport file1 from './src/external/assets/file1.png'\nimport file2 from './src/external/assets/file2.txt'\nimport file3 from './src/external/assets/file3.svg'\n\ndescribe('import external css', () => {\n  test('when importing empty.css, element doesn\\'t change style', () => {\n    const el = document.createElement('div')\n    el.classList.add('test1')\n    expect(el.classList.contains('test1')).toBe(true)\n    expect(window.getComputedStyle(el).color).toBe('rgb(0, 0, 0)')\n  })\n\n  test('when importing processed.css, element changes style', () => {\n    const el = document.createElement('div')\n    el.classList.add('test2')\n    expect(el.classList.contains('test2')).toBe(true)\n    expect(window.getComputedStyle(el).color).toBe('rgb(0, 128, 0)')\n  })\n\n  test('when importing processed.module.css, element changes style', () => {\n    const el = document.createElement('div')\n    el.classList.add(processedModule.test3)\n    expect(el.classList.contains(processedModule.test3)).toBe(true)\n    expect(window.getComputedStyle(el).color).toBe('rgb(255, 255, 0)')\n  })\n})\n\ndescribe('import external assets', () => {\n  test('correctly imports assets as paths', () => {\n    expect(file1).toBe('/src/external/assets/file1.png')\n    expect(file2).toBe('/src/external/assets/file2.txt')\n    expect(file3).toBe('/src/external/assets/file3.svg')\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/module.test.js",
    "content": "import { Module } from 'node:module'\nimport { expect, it } from 'vitest'\n\nit('can create modules with incorrect filepath', () => {\n  expect(() => new Module('name')).not.toThrow()\n  // require will not work for these modules because native createRequire fails\n  expect(() => new Module('some-other-name').require('node:url')).toThrow()\n})\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/not-found.test.ts",
    "content": "import { expect, it } from 'vitest'\n\n// @ts-expect-error untyped\nimport * as notFound from './src/external/not-found.js'\n\nit('path', async () => {\n  await expect(() => notFound.importPath()).rejects.toMatchObject({\n    code: 'ERR_MODULE_NOT_FOUND',\n    message: expect.stringMatching(/Cannot find module '.*?non-existing-path'/),\n  })\n})\n\n// NodeJs's import.meta.resolve throws ERR_MODULE_NOT_FOUND error only this case.\n// For other cases, similar errors are fabricated by Vitest to mimic NodeJs's behavior.\nit('package', async () => {\n  await expect(() => notFound.importPackage()).rejects.toMatchObject({\n    code: 'ERR_MODULE_NOT_FOUND',\n    message: expect.stringContaining('Cannot find package \\'@vitest/non-existing-package\\''),\n  })\n})\n\nit('builtin', async () => {\n  await expect(() => notFound.importBuiltin()).rejects.toMatchObject({\n    code: 'ERR_MODULE_NOT_FOUND',\n    message: 'Cannot find package \\'node:non-existing-builtin\\'',\n  })\n})\n\n// this test fails before node 20.3.0 since it throws a different error (cf. https://github.com/nodejs/node/pull/47824)\n// > Only URLs with a scheme in: file and data are supported by the default ESM loader. Received protocol 'non-existing-namespace:'\nit('namespace', async () => {\n  await expect(() => notFound.importNamespace()).rejects.toMatchObject({\n    code: 'ERR_MODULE_NOT_FOUND',\n    message: 'Cannot find package \\'non-existing-namespace:xyz\\'',\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/require-cjs.test.js",
    "content": "import { createRequire } from 'node:module'\nimport { describe, expect, test } from 'vitest'\n\nconst require = createRequire(import.meta.url)\n\ntest('can require if package.json is null', () => {\n  expect(() => require('./src/external/package-null/package-null.js')).not.toThrow()\n})\n\ndescribe('validating nested defaults in isolation', async () => {\n  const nestedDefaultExternalCjs = await import('./src/external/export-nested-default-cjs.js')\n  const moduleDefaultCjs = await import('./src/external/export-default-cjs.js')\n\n  test('nested default should be resolved', () => {\n    expect(nestedDefaultExternalCjs).toHaveProperty('default')\n    expect(nestedDefaultExternalCjs.default).not.toHaveProperty('default')\n    expect(nestedDefaultExternalCjs.default.a).toBe('a')\n    expect(nestedDefaultExternalCjs.default.b).toBe('b')\n    expect(nestedDefaultExternalCjs.a).toBe('a')\n    expect(nestedDefaultExternalCjs.b).toBe('b')\n  })\n\n  test('externalized \"module.exports\" CJS module interops default', () => {\n    expect(moduleDefaultCjs).toHaveProperty('default')\n    expect(moduleDefaultCjs.default).toHaveProperty('a')\n    expect(moduleDefaultCjs.default.a).toBe('a')\n    expect(moduleDefaultCjs).toHaveProperty('a')\n    expect(moduleDefaultCjs.a).toBe('a')\n  })\n})\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/assets/file2.txt",
    "content": ""
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/css/empty.css",
    "content": ".test1 {\n  color: red;\n}\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/css/processed.css",
    "content": ".test2 {\n  color: green;\n}\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/css/processed.module.css",
    "content": ".test3 {\n  color: yellow;\n}\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/default-cjs.cjs",
    "content": "module.exports = {\n  a: 'a',\n  b: 'b',\n  object: {\n    h: 'h',\n  },\n}\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/export-default-cjs.js",
    "content": "export * from './default-cjs.cjs'\nexport { default } from './default-cjs.cjs'\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/export-nested-default-cjs.js",
    "content": "export * from './nested-default-cjs.cjs'\nexport { default } from './nested-default-cjs.cjs'\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/nested-default-cjs.cjs",
    "content": "exports.default = {\n  a: 'a',\n  b: 'b',\n  object: {\n    h: 'h',\n  },\n}\nObject.defineProperty(exports, '__esModule', { value: true, enumerable: false })\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/not-found.js",
    "content": "export async function importPackage() {\n  await import('@vitest/non-existing-package')\n}\n\nexport async function importPath() {\n  await import('./non-existing-path')\n}\n\nexport async function importBuiltin() {\n  await import('node:non-existing-builtin')\n}\n\nexport async function importNamespace() {\n  await import('non-existing-namespace:xyz')\n}\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/package-null/package-null.js",
    "content": "module.exports = 42\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/src/external/primitive-cjs.cjs",
    "content": "module.exports = 'string'\n"
  },
  {
    "path": "test/cli/fixtures/vm-threads/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    pool: 'vmThreads',\n    css: {\n      include: [/processed/],\n    },\n    server: {\n      deps: {\n        external: [/src\\/external/],\n      },\n    },\n  },\n  build: {\n    assetsInlineLimit: 0,\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/watch/42.txt",
    "content": "42\n\n\n\n"
  },
  {
    "path": "test/cli/fixtures/watch/example.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { getHelloWorld } from './example'\n\n// @ts-expect-error not typed txt\nimport answer from './42.txt?raw'\n\ntest('answer is 42', () => {\n  expect(answer).toContain('42')\n})\n\ntest('getHello', async () => {\n  expect(getHelloWorld()).toBe('Hello world')\n})\n"
  },
  {
    "path": "test/cli/fixtures/watch/example.ts",
    "content": "export function getHelloWorld() {\n  return 'Hello world'\n}\n"
  },
  {
    "path": "test/cli/fixtures/watch/force-watch/trigger.js",
    "content": "export const trigger = false\n"
  },
  {
    "path": "test/cli/fixtures/watch/global-setup.ts",
    "content": "import { TestProject } from 'vitest/node';\n\nconst calls: string[] = [];\n\n(globalThis as any).__CALLS = calls\n\nexport default (project: TestProject) => {\n  calls.push('start')\n  project.onTestsRerun(() => {\n    calls.push('rerun')\n  })\n  return () => {\n    calls.push('end')\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/watch/math.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { sum } from './math'\n\ntest('sum', () => {\n  expect(sum(1, 2)).toBe(3)\n})\n"
  },
  {
    "path": "test/cli/fixtures/watch/math.ts",
    "content": "export function sum(a: number, b: number) {\n  return a + b\n}\n"
  },
  {
    "path": "test/cli/fixtures/watch/vitest.config.ts",
    "content": "import { defaultExclude, defineConfig } from 'vitest/config'\n\n// Patch stdin on the process so that we can fake it to seem like a real interactive terminal and pass the TTY checks\nprocess.stdin.isTTY = true\nprocess.stdin.setRawMode = () => process.stdin\n\nexport default defineConfig({\n  test: {\n    watch: true,\n    exclude: [\n      ...defaultExclude,\n      '**/single-failed/**',\n    ],\n\n    // This configuration is edited by tests\n    reporters: 'verbose',\n\n    forceRerunTriggers: [\n      '**/force-watch/**',\n    ],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/windows-drive-case/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('basic test', () => {\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/api/basic.test.ts",
    "content": "import { expect, it } from 'vitest';\n\nit('correctly inherits values', ({ task }) => {\n  const project = task.file.projectName\n  switch (project) {\n    case 'project-1': {\n      expect(process.env.TEST_ROOT).toBe('1')\n      return\n    }\n    case 'project-2': {\n      expect(process.env.TEST_ROOT).toBe('2')\n      return\n    }\n    case 'project-3': {\n      // even if not inherited from the config directly, the `env` is always inherited from root\n      expect(process.env.TEST_ROOT).toBe('1')\n      expect(process.env.TEST_PROJECT).toBe('project-3')\n      return\n    }\n    default: {\n      expect.unreachable()\n    }\n  }\n})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/api/vite.custom.config.js",
    "content": "export default {\n  test: {\n    env: {\n      TEST_PROJECT: 'project-3',\n    },\n  },\n}"
  },
  {
    "path": "test/cli/fixtures/workspace/config-empty/vitest.config.js",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/config-extends/repro.test.js",
    "content": "import { test, expect } from 'vitest';\nimport repro from 'virtual:repro';\n\ntest('importing a virtual module', () => {\n  expect(repro).toBe('Hello, world!');\n});\n"
  },
  {
    "path": "test/cli/fixtures/workspace/config-extends/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'virtual',\n      resolveId(source) {\n        if (source === 'virtual:repro') {\n          return '\\0virtual:repro';\n        }\n      },\n      load(id) {\n        if (id === '\\0virtual:repro') {\n          return `export default \"Hello, world!\"`;\n        }\n      },\n    },\n  ],\n  test: {\n    projects: [\n      {\n        extends: true,\n        test: {\n          name: 'node',\n          environment: 'node',\n        },\n      },\n    ],\n  },\n});\n"
  },
  {
    "path": "test/cli/fixtures/workspace/config-import-analysis/dep.ts",
    "content": "export default [] satisfies string[];\n"
  },
  {
    "path": "test/cli/fixtures/workspace/config-import-analysis/packages/a/package.json",
    "content": "{\n  \"name\": \"a\"\n}\n"
  },
  {
    "path": "test/cli/fixtures/workspace/config-import-analysis/packages/a/test.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('test - a')\n"
  },
  {
    "path": "test/cli/fixtures/workspace/config-import-analysis/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport depAsJs from \"./dep.js\"\n\nexport default defineConfig({\n  test: {\n    projects: [\n      \"./packages/*\",\n      ...depAsJs,\n    ],\n  }\n})"
  },
  {
    "path": "test/cli/fixtures/workspace/invalid-duplicate-configs/vitest.config.one.js",
    "content": "export default {\n  test: {\n    name: 'test',\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/workspace/invalid-duplicate-configs/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      './vitest.config.one.js',\n      './vitest.config.two.js',\n    ],\n  }\n})"
  },
  {
    "path": "test/cli/fixtures/workspace/invalid-duplicate-configs/vitest.config.two.js",
    "content": "export default {\n  test: {\n    name: 'test',\n  }\n}\n"
  },
  {
    "path": "test/cli/fixtures/workspace/invalid-duplicate-inline/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: 'test',\n        },\n      },\n      {\n        test: {\n          name: 'test',\n        },\n      },\n    ]\n  }\n})"
  },
  {
    "path": "test/cli/fixtures/workspace/invalid-non-existing-config/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      './vitest.config.js'\n    ],\n  },\n})"
  },
  {
    "path": "test/cli/fixtures/workspace/negated/packages/a/package.json",
    "content": "{\n  \"name\": \"a\"\n}\n"
  },
  {
    "path": "test/cli/fixtures/workspace/negated/packages/a/test.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('test - a')\n"
  },
  {
    "path": "test/cli/fixtures/workspace/negated/packages/b/package.json",
    "content": "{\n  \"name\": \"b\"\n}\n"
  },
  {
    "path": "test/cli/fixtures/workspace/negated/packages/b/test.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('test - b')\n"
  },
  {
    "path": "test/cli/fixtures/workspace/negated/packages/c/package.json",
    "content": "{\n  \"name\": \"c\"\n}\n"
  },
  {
    "path": "test/cli/fixtures/workspace/negated/packages/c/test.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('test - c')\n"
  },
  {
    "path": "test/cli/fixtures/workspace/negated/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    projects: [\n      'packages/*',\n      '!packages/b'\n    ],\n  },\n})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/project-1/calculator-1.test.ts",
    "content": "import { expect, it } from 'vitest';\n\nit('1 + 1 = 2', () => {\n  expect(1 + 1).toBe(2);\n})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/project-2/calculator-2.test.ts",
    "content": "import { expect, it } from 'vitest';\n\nit('2 + 2 = 4', () => {\n  expect(2 + 2).toBe(4);\n})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/several-configs/test/1_test.test.ts",
    "content": "import { expect, test } from 'vitest';\n\ntest('1 + 1 = 2', () => {\n  expect(1 + 1).toBe(2);\n})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/several-configs/test/2_test.test.ts",
    "content": "import { expect, test } from 'vitest';\n\ntest('2 + 2 = 4', () => {\n  expect(2 + 2).toBe(4);\n})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/several-configs/test/vitest.config.one.ts",
    "content": "import { defineProject } from 'vitest/config';\n\nexport default defineProject({\n  test: {\n    name: '1_test',\n    include: ['./1_test.test.ts'],\n  }\n})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/several-configs/test/vitest.config.two.ts",
    "content": "import { defineProject } from 'vitest/config';\n\nexport default defineProject({\n  test: {\n    name: '2_test',\n    include: ['./2_test.test.ts'],\n  }\n})\n"
  },
  {
    "path": "test/cli/fixtures/workspace/several-configs/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      './test/*.config.*.ts',\n    ],\n  },\n})"
  },
  {
    "path": "test/cli/fixtures/workspace/several-folders/apps/b/package.json",
    "content": "{\n  \"name\": \"b\"\n}"
  },
  {
    "path": "test/cli/fixtures/workspace/several-folders/apps/b/test.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('test - b')"
  },
  {
    "path": "test/cli/fixtures/workspace/several-folders/projects/a/package.json",
    "content": "{\n  \"name\": \"a\"\n}"
  },
  {
    "path": "test/cli/fixtures/workspace/several-folders/projects/a/test.test.ts",
    "content": "import { test } from 'vitest';\n\ntest('test - a')"
  },
  {
    "path": "test/cli/fixtures/workspace/several-folders/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    projects: [\n      'projects/*',\n      'apps/*'\n    ],\n  },\n})"
  },
  {
    "path": "test/cli/package.json",
    "content": "{\n  \"name\": \"@vitest/test-cli\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"imports\": {\n    \"#test-utils\": \"../test-utils/index.ts\"\n  },\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"stacktraces\": \"vitest --root=./fixtures/stacktraces --watch=false\",\n    \"native\": \"vitest --root=./fixtures/no-module-runner --watch=false --no-isolate --max-workers=1\"\n  },\n  \"devDependencies\": {\n    \"@opentelemetry/api\": \"^1.9.0\",\n    \"@opentelemetry/sdk-node\": \"^0.213.0\",\n    \"@opentelemetry/sdk-trace-web\": \"^2.6.0\",\n    \"@test/pkg-reporter\": \"link:./deps/pkg-reporter\",\n    \"@test/test-dep-error\": \"file:./deps/error\",\n    \"@test/test-dep-linked\": \"link:./deps/linked\",\n    \"@test/test-dep-url\": \"link:./deps/dep-url\",\n    \"@types/ws\": \"catalog:\",\n    \"@vitejs/plugin-basic-ssl\": \"^2.1.4\",\n    \"@vitest/browser-playwright\": \"workspace:*\",\n    \"@vitest/browser-preview\": \"workspace:*\",\n    \"@vitest/browser-webdriverio\": \"workspace:*\",\n    \"@vitest/mocker\": \"workspace:*\",\n    \"@vitest/runner\": \"workspace:*\",\n    \"@vitest/utils\": \"workspace:*\",\n    \"flatted\": \"catalog:\",\n    \"obug\": \"^2.1.1\",\n    \"playwright\": \"catalog:\",\n    \"test-dep-invalid\": \"link:./deps/dep-invalid\",\n    \"test-dep-simple\": \"file:./deps/dep-simple\",\n    \"tinyspy\": \"catalog:\",\n    \"typescript\": \"catalog:\",\n    \"unplugin-swc\": \"^1.5.9\",\n    \"vite\": \"latest\",\n    \"vitest\": \"workspace:*\",\n    \"vitest-sonar-reporter\": \"catalog:\",\n    \"ws\": \"catalog:\"\n  }\n}\n"
  },
  {
    "path": "test/cli/test/__snapshots__/benchmarking.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`sequential 1`] = `\n\"F1 / S1 / B1\nF1 / S1 / B1\nF1 / S1 / B1\nF1 / S1 / B2\nF1 / S1 / B2\nF1 / S1 / B2\nF1 / S2 / B1\nF1 / S2 / B1\nF1 / S2 / B1\nF1 / B1\nF1 / B1\nF1 / B1\nF2 / S1 / B1\nF2 / S1 / B1\nF2 / S1 / B1\n\"\n`;\n\nexports[`summary 1`] = `\n\"\n\n  good - summary.bench.ts > suite-a\n    (?) faster than bad\n\n  good - summary.bench.ts > suite-b\n\n  good - summary.bench.ts > suite-b > suite-b-nested\n\n\"\n`;\n"
  },
  {
    "path": "test/cli/test/__snapshots__/fails.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`should fail .dot-folder/dot-test.test.ts 1`] = `\"AssertionError: expected true to be false // Object.is equality\"`;\n\nexports[`should fail async-assertion.test.ts 1`] = `\n\"AssertionError: expected 'xx' to be 'zz' // Object.is equality\nAssertionError: expected 'xx' to be 'yy' // Object.is equality\"\n`;\n\nexports[`should fail each-timeout.test.ts 1`] = `\"Error: Test timed out in 10ms.\"`;\n\nexports[`should fail empty.test.ts 1`] = `\"Error: No test suite found in file <rootDir>/empty.test.ts\"`;\n\nexports[`should fail expect.test.ts 1`] = `\"AssertionError: expected 2 to deeply equal 3\"`;\n\nexports[`should fail expect-soft.test.ts 1`] = `\"Error: expect.soft() can only be used inside a test\"`;\n\nexports[`should fail expect-unreachable.test.ts 1`] = `\"AssertionError: expected \"hi\" not to be reached\"`;\n\nexports[`should fail exports-error.test.js 1`] = `\"TypeError: vi is not a function\"`;\n\nexports[`should fail hook-timeout.test.ts 1`] = `\"Error: Hook timed out in 10ms.\"`;\n\nexports[`should fail hooks-called.test.ts 1`] = `\n\"Error: after all\nError: before all\"\n`;\n\nexports[`should fail hooks-fail-afterAll.test.ts 1`] = `\"TypeError: \"afterAll\" callback value must be function, received \"string\"\"`;\n\nexports[`should fail hooks-fail-afterEach.test.ts 1`] = `\"TypeError: \"afterEach\" callback value must be function, received \"string\"\"`;\n\nexports[`should fail hooks-fail-beforeAll.test.ts 1`] = `\"TypeError: \"beforeAll\" callback value must be function, received \"string\"\"`;\n\nexports[`should fail hooks-fail-beforeEach.test.ts 1`] = `\"TypeError: \"beforeEach\" callback value must be function, received \"string\"\"`;\n\nexports[`should fail hooks-timeout-before-hook-cleanup-callback.test.ts 1`] = `\n\"Error: Hook timed out in 101ms.\nError: Hook timed out in 102ms.\"\n`;\n\nexports[`should fail mock-import-proxy-module.test.ts 1`] = `\"Error: There are some problems in resolving the mocks API.\"`;\n\nexports[`should fail nested-suite.test.ts 1`] = `\"AssertionError: expected true to be false // Object.is equality\"`;\n\nexports[`should fail no-assertions.test.ts 1`] = `\"Error: expected any number of assertion, but got none\"`;\n\nexports[`should fail node-browser-context.test.ts 1`] = `\"Error: vitest/browser can be imported only inside the Browser Mode. Your test is running in forks pool. Make sure your regular tests are excluded from the \"test.include\" glob pattern.\"`;\n\nexports[`should fail poll-no-awaited.test.ts 1`] = `\n\"Error: expect.poll(assertion).toBe() was not awaited. This assertion is asynchronous and must be awaited; otherwise, it is not executed to avoid unhandled rejections:\nAssertionError: expected 3 to be 4 // Object.is equality\nError: expect.poll(assertion).toBe() was not awaited. This assertion is asynchronous and must be awaited; otherwise, it is not executed to avoid unhandled rejections:\nError: expect.poll(assertion).toBe() was not awaited. This assertion is asynchronous and must be awaited; otherwise, it is not executed to avoid unhandled rejections:\nError: expect.poll(assertion).not.toBe() was not awaited. This assertion is asynchronous and must be awaited; otherwise, it is not executed to avoid unhandled rejections:\nError: expect.poll(assertion).toBe() was not awaited. This assertion is asynchronous and must be awaited; otherwise, it is not executed to avoid unhandled rejections:\"\n`;\n\nexports[`should fail primitive-error.test.ts 1`] = `\"Unknown Error: 42\"`;\n\nexports[`should fail skip-conditional.test.ts 1`] = `\"Error: doesnt skip\"`;\n\nexports[`should fail snapshot-with-not.test.ts 1`] = `\n\"Error: toThrowErrorMatchingInlineSnapshot cannot be used with \"not\"\nError: toThrowErrorMatchingSnapshot cannot be used with \"not\"\nError: toMatchInlineSnapshot cannot be used with \"not\"\nError: toMatchFileSnapshot cannot be used with \"not\"\nError: toMatchSnapshot cannot be used with \"not\"\"\n`;\n\nexports[`should fail stall.test.ts 1`] = `\n\"TypeError: failure\nTypeError: failure\nTypeError: failure\nTypeError: failure\"\n`;\n\nexports[`should fail test-extend/circular-dependency.test.ts 1`] = `\"Error: Circular fixture dependency detected: a <- b <- a\"`;\n\nexports[`should fail test-extend/fixture-error.test.ts 1`] = `\n\"Error: Error fixture teardown\nError: Test timed out in 20ms.\nError: Error thrown in test fixture\nError: Error thrown in afterEach fixture\nError: Error thrown in beforeEach fixture\"\n`;\n\nexports[`should fail test-extend/fixture-rest-params.test.ts 1`] = `\"FixtureParseError: The 1st argument inside a fixture must use object destructuring pattern, e.g. ({ task } => {}). Instead, received \"...rest\".\"`;\n\nexports[`should fail test-extend/fixture-rest-props.test.ts 1`] = `\"FixtureParseError: Rest parameters are not supported in fixtures, received \"...rest\".\"`;\n\nexports[`should fail test-extend/fixture-without-destructuring.test.ts 1`] = `\"FixtureParseError: The 1st argument inside a fixture must use object destructuring pattern, e.g. ({ task } => {}). Instead, received \"context\".\"`;\n\nexports[`should fail test-extend/test-rest-params.test.ts 1`] = `\"FixtureParseError: The 1st argument inside a fixture must use object destructuring pattern, e.g. ({ task } => {}). Instead, received \"...rest\".\"`;\n\nexports[`should fail test-extend/test-rest-props.test.ts 1`] = `\"FixtureParseError: Rest parameters are not supported in fixtures, received \"...rest\".\"`;\n\nexports[`should fail test-extend/test-without-destructuring.test.ts 1`] = `\"FixtureParseError: The 1st argument inside a fixture must use object destructuring pattern, e.g. ({ task } => {}). Instead, received \"context\".\"`;\n\nexports[`should fail test-timeout.test.ts 1`] = `\n\"Error: Test timed out in 20ms.\nError: Test timed out in 200ms.\nError: Test timed out in 100ms.\nError: Hook timed out in 17ms.\nError: Test timed out in 15ms.\nError: Test timed out in 10ms.\nError: Hook timed out in 16ms.\"\n`;\n\nexports[`should fail unhandled.test.ts 1`] = `\"Error: some error\"`;\n\nexports[`should fail unhandled-suite.test.ts 1`] = `\"Unknown Error: promise error\"`;\n"
  },
  {
    "path": "test/cli/test/__snapshots__/list.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`basic output shows error 1`] = `\n\"Error: describe error\n ❯ describe-error.test.ts:4:9\n      2|\n      3| describe('describe error', () => {\n      4|   throw new Error('describe error')\n       |         ^\n      5|\n      6|   it('wont run', () => {\n\nError: top level error\n ❯ top-level-error.test.ts:1:7\n      1| throw new Error('top level error')\n       |       ^\n      2|\n\n\"\n`;\n\nexports[`correctly outputs all tests with args: \"--browser.enabled\" 1`] = `\n\"[chromium] basic.test.ts > basic suite > inner suite > some test\n[chromium] basic.test.ts > basic suite > inner suite > another test\n[chromium] basic.test.ts > basic suite > basic test\n[chromium] basic.test.ts > outside test\n[chromium] math.test.ts > 1 plus 1\n[chromium] math.test.ts > failing test\n\"\n`;\n\nexports[`correctly outputs all tests with args: \"--pool=forks\" 1`] = `\n\"basic.test.ts > basic suite > inner suite > some test\nbasic.test.ts > basic suite > inner suite > another test\nbasic.test.ts > basic suite > basic test\nbasic.test.ts > outside test\nmath.test.ts > 1 plus 1\nmath.test.ts > failing test\n\"\n`;\n\nexports[`correctly outputs all tests with args: \"--pool=threads\" 1`] = `\n\"basic.test.ts > basic suite > inner suite > some test\nbasic.test.ts > basic suite > inner suite > another test\nbasic.test.ts > basic suite > basic test\nbasic.test.ts > outside test\nmath.test.ts > 1 plus 1\nmath.test.ts > failing test\n\"\n`;\n\nexports[`correctly outputs all tests with args: \"--pool=vmForks\" 1`] = `\n\"basic.test.ts > basic suite > inner suite > some test\nbasic.test.ts > basic suite > inner suite > another test\nbasic.test.ts > basic suite > basic test\nbasic.test.ts > outside test\nmath.test.ts > 1 plus 1\nmath.test.ts > failing test\n\"\n`;\n\nexports[`correctly outputs all tests with args: \"--static-parse\" 1`] = `\n\"basic.test.ts > basic suite > inner suite > some test\nbasic.test.ts > basic suite > inner suite > another test\nbasic.test.ts > basic suite > basic test\nbasic.test.ts > outside test\nmath.test.ts > 1 plus 1\nmath.test.ts > failing test\n\"\n`;\n\nexports[`correctly outputs all tests with args: \"--typecheck\" 1`] = `\n\"type.test-d.ts > 1 plus 1\nbasic.test.ts > basic suite > inner suite > some test\nbasic.test.ts > basic suite > inner suite > another test\nbasic.test.ts > basic suite > basic test\nbasic.test.ts > outside test\nmath.test.ts > 1 plus 1\nmath.test.ts > failing test\n\"\n`;\n\nexports[`correctly outputs all tests with args: \"--typecheck.only\" 1`] = `\n\"type.test-d.ts > 1 plus 1\n\"\n`;\n\nexports[`json output shows error 1`] = `\n\"Error: describe error\n ❯ describe-error.test.ts:4:9\n      2|\n      3| describe('describe error', () => {\n      4|   throw new Error('describe error')\n       |         ^\n      5|\n      6|   it('wont run', () => {\n\nError: top level error\n ❯ top-level-error.test.ts:1:7\n      1| throw new Error('top level error')\n       |       ^\n      2|\n\n\"\n`;\n\nexports[`json with a file output shows error 1`] = `\n\"Error: describe error\n ❯ describe-error.test.ts:4:9\n      2|\n      3| describe('describe error', () => {\n      4|   throw new Error('describe error')\n       |         ^\n      5|\n      6|   it('wont run', () => {\n\nError: top level error\n ❯ top-level-error.test.ts:1:7\n      1| throw new Error('top level error')\n       |       ^\n      2|\n\n\"\n`;\n"
  },
  {
    "path": "test/cli/test/__snapshots__/no-module-runner.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`supported > v8 coverage works 1`] = `\n{\n  \"<process-cwd>/fixtures/no-module-runner/src/basic.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {\n      \"0\": 3,\n    },\n    \"fnMap\": {\n      \"0\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 24,\n            \"line\": 1,\n          },\n          \"start\": {\n            \"column\": 23,\n            \"line\": 1,\n          },\n        },\n        \"line\": 1,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 1,\n          },\n          \"start\": {\n            \"column\": 38,\n            \"line\": 1,\n          },\n        },\n        \"name\": \"(anonymous_0)\",\n      },\n    },\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 1,\n      \"lastStatement\": 2,\n      \"seen\": {\n        \"f:1:23:1:24\": 0,\n        \"s:1:23:1:Infinity\": 0,\n        \"s:1:38:1:Infinity\": 1,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/basic.ts\",\n    \"s\": {\n      \"0\": 3,\n      \"1\": 3,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 1,\n        },\n        \"start\": {\n          \"column\": 23,\n          \"line\": 1,\n        },\n      },\n      \"1\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 1,\n        },\n        \"start\": {\n          \"column\": 38,\n          \"line\": 1,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/dependency.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {\n      \"0\": 1,\n    },\n    \"fnMap\": {\n      \"0\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 19,\n            \"line\": 1,\n          },\n          \"start\": {\n            \"column\": 16,\n            \"line\": 1,\n          },\n        },\n        \"line\": 1,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 3,\n          },\n          \"start\": {\n            \"column\": 42,\n            \"line\": 1,\n          },\n        },\n        \"name\": \"add\",\n      },\n    },\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 1,\n      \"lastStatement\": 1,\n      \"seen\": {\n        \"f:1:16:1:19\": 0,\n        \"s:2:2:2:Infinity\": 0,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/dependency.ts\",\n    \"s\": {\n      \"0\": 1,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 2,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 2,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/from-async.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {},\n    \"fnMap\": {},\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 0,\n      \"lastStatement\": 1,\n      \"seen\": {\n        \"s:3:23:3:Infinity\": 0,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/from-async.ts\",\n    \"s\": {\n      \"0\": 1,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 3,\n        },\n        \"start\": {\n          \"column\": 23,\n          \"line\": 3,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/in-source/add.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {\n      \"0\": 135,\n      \"1\": 269,\n    },\n    \"fnMap\": {\n      \"0\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 19,\n            \"line\": 1,\n          },\n          \"start\": {\n            \"column\": 16,\n            \"line\": 1,\n          },\n        },\n        \"line\": 1,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 3,\n          },\n          \"start\": {\n            \"column\": 39,\n            \"line\": 1,\n          },\n        },\n        \"name\": \"add\",\n      },\n      \"1\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 22,\n            \"line\": 2,\n          },\n          \"start\": {\n            \"column\": 21,\n            \"line\": 2,\n          },\n        },\n        \"line\": 2,\n        \"loc\": {\n          \"end\": {\n            \"column\": 36,\n            \"line\": 2,\n          },\n          \"start\": {\n            \"column\": 31,\n            \"line\": 2,\n          },\n        },\n        \"name\": \"(anonymous_1)\",\n      },\n    },\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 2,\n      \"lastStatement\": 2,\n      \"seen\": {\n        \"f:1:16:1:19\": 0,\n        \"f:2:21:2:22\": 1,\n        \"s:2:2:2:Infinity\": 0,\n        \"s:2:31:2:36\": 1,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/in-source/add.ts\",\n    \"s\": {\n      \"0\": 135,\n      \"1\": 269,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 2,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 2,\n        },\n      },\n      \"1\": {\n        \"end\": {\n          \"column\": 36,\n          \"line\": 2,\n        },\n        \"start\": {\n          \"column\": 31,\n          \"line\": 2,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/in-source/fibonacci.ts\": {\n    \"b\": {\n      \"0\": [\n        1,\n        0,\n      ],\n    },\n    \"branchMap\": {\n      \"0\": {\n        \"line\": 4,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 6,\n          },\n          \"start\": {\n            \"column\": 2,\n            \"line\": 4,\n          },\n        },\n        \"locations\": [\n          {\n            \"end\": {\n              \"column\": null,\n              \"line\": 6,\n            },\n            \"start\": {\n              \"column\": 2,\n              \"line\": 4,\n            },\n          },\n          {\n            \"end\": {},\n            \"start\": {},\n          },\n        ],\n        \"type\": \"if\",\n      },\n    },\n    \"f\": {\n      \"0\": 1,\n    },\n    \"fnMap\": {\n      \"0\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 25,\n            \"line\": 3,\n          },\n          \"start\": {\n            \"column\": 16,\n            \"line\": 3,\n          },\n        },\n        \"line\": 3,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 8,\n          },\n          \"start\": {\n            \"column\": 45,\n            \"line\": 3,\n          },\n        },\n        \"name\": \"fibonacci\",\n      },\n    },\n    \"meta\": {\n      \"lastBranch\": 1,\n      \"lastFunction\": 1,\n      \"lastStatement\": 3,\n      \"seen\": {\n        \"b:4:2:6:Infinity:undefined:undefined:undefined:undefined\": 0,\n        \"f:3:16:3:25\": 0,\n        \"s:4:2:6:Infinity\": 0,\n        \"s:5:4:5:Infinity\": 1,\n        \"s:7:2:7:Infinity\": 2,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/in-source/fibonacci.ts\",\n    \"s\": {\n      \"0\": 1,\n      \"1\": 1,\n      \"2\": 1,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 6,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 4,\n        },\n      },\n      \"1\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 5,\n        },\n        \"start\": {\n          \"column\": 4,\n          \"line\": 5,\n        },\n      },\n      \"2\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 7,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 7,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/in-source/index.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {},\n    \"fnMap\": {},\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 0,\n      \"lastStatement\": 0,\n      \"seen\": {},\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/in-source/index.ts\",\n    \"s\": {},\n    \"statementMap\": {},\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/index.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {},\n    \"fnMap\": {},\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 0,\n      \"lastStatement\": 1,\n      \"seen\": {\n        \"s:2:23:2:Infinity\": 0,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/index.ts\",\n    \"s\": {\n      \"0\": 2,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 2,\n        },\n        \"start\": {\n          \"column\": 23,\n          \"line\": 2,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/minus.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {\n      \"0\": 1,\n    },\n    \"fnMap\": {\n      \"0\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 21,\n            \"line\": 1,\n          },\n          \"start\": {\n            \"column\": 16,\n            \"line\": 1,\n          },\n        },\n        \"line\": 1,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 3,\n          },\n          \"start\": {\n            \"column\": 52,\n            \"line\": 1,\n          },\n        },\n        \"name\": \"minus\",\n      },\n    },\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 1,\n      \"lastStatement\": 1,\n      \"seen\": {\n        \"f:1:16:1:21\": 0,\n        \"s:2:2:2:Infinity\": 0,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/minus.ts\",\n    \"s\": {\n      \"0\": 1,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 2,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 2,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/mock-async.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {},\n    \"fnMap\": {},\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 0,\n      \"lastStatement\": 1,\n      \"seen\": {\n        \"s:1:22:1:Infinity\": 0,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/mock-async.ts\",\n    \"s\": {\n      \"0\": 1,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 1,\n        },\n        \"start\": {\n          \"column\": 22,\n          \"line\": 1,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/mock-js.d.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {},\n    \"fnMap\": {},\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 0,\n      \"lastStatement\": 0,\n      \"seen\": {},\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/mock-js.d.ts\",\n    \"s\": {},\n    \"statementMap\": {},\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/mock-js.js\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {\n      \"0\": 1,\n    },\n    \"fnMap\": {\n      \"0\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 22,\n            \"line\": 1,\n          },\n          \"start\": {\n            \"column\": 16,\n            \"line\": 1,\n          },\n        },\n        \"line\": 1,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 3,\n          },\n          \"start\": {\n            \"column\": 25,\n            \"line\": 1,\n          },\n        },\n        \"name\": \"mockJs\",\n      },\n    },\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 1,\n      \"lastStatement\": 1,\n      \"seen\": {\n        \"f:1:16:1:22\": 0,\n        \"s:2:2:2:Infinity\": 0,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/mock-js.js\",\n    \"s\": {\n      \"0\": 1,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 2,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 2,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/mock-sync.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {\n      \"0\": 1,\n    },\n    \"fnMap\": {\n      \"0\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 24,\n            \"line\": 1,\n          },\n          \"start\": {\n            \"column\": 16,\n            \"line\": 1,\n          },\n        },\n        \"line\": 1,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 3,\n          },\n          \"start\": {\n            \"column\": 27,\n            \"line\": 1,\n          },\n        },\n        \"name\": \"syncMock\",\n      },\n    },\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 1,\n      \"lastStatement\": 1,\n      \"seen\": {\n        \"f:1:16:1:24\": 0,\n        \"s:2:2:2:Infinity\": 0,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/mock-sync.ts\",\n    \"s\": {\n      \"0\": 1,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 2,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 2,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/no-mock.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {\n      \"0\": 0,\n    },\n    \"fnMap\": {\n      \"0\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 25,\n            \"line\": 2,\n          },\n          \"start\": {\n            \"column\": 16,\n            \"line\": 2,\n          },\n        },\n        \"line\": 2,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 4,\n          },\n          \"start\": {\n            \"column\": 37,\n            \"line\": 2,\n          },\n        },\n        \"name\": \"notMocked\",\n      },\n    },\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 1,\n      \"lastStatement\": 1,\n      \"seen\": {\n        \"f:2:16:2:25\": 0,\n        \"s:3:2:3:Infinity\": 0,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/no-mock.ts\",\n    \"s\": {\n      \"0\": 0,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 3,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 3,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/redirect.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {},\n    \"fnMap\": {},\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 0,\n      \"lastStatement\": 1,\n      \"seen\": {\n        \"s:1:0:1:Infinity\": 0,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/redirect.ts\",\n    \"s\": {\n      \"0\": 0,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 1,\n        },\n        \"start\": {\n          \"column\": 0,\n          \"line\": 1,\n        },\n      },\n    },\n  },\n  \"<process-cwd>/fixtures/no-module-runner/src/setups.ts\": {\n    \"b\": {},\n    \"branchMap\": {},\n    \"f\": {\n      \"0\": 9,\n      \"1\": 9,\n      \"2\": 1,\n    },\n    \"fnMap\": {\n      \"0\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 34,\n            \"line\": 6,\n          },\n          \"start\": {\n            \"column\": 33,\n            \"line\": 6,\n          },\n        },\n        \"line\": 6,\n        \"loc\": {\n          \"end\": {\n            \"column\": 1,\n            \"line\": 8,\n          },\n          \"start\": {\n            \"column\": 39,\n            \"line\": 6,\n          },\n        },\n        \"name\": \"(anonymous_0)\",\n      },\n      \"1\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 34,\n            \"line\": 10,\n          },\n          \"start\": {\n            \"column\": 33,\n            \"line\": 10,\n          },\n        },\n        \"line\": 10,\n        \"loc\": {\n          \"end\": {\n            \"column\": 1,\n            \"line\": 12,\n          },\n          \"start\": {\n            \"column\": 39,\n            \"line\": 10,\n          },\n        },\n        \"name\": \"(anonymous_1)\",\n      },\n      \"2\": {\n        \"decl\": {\n          \"end\": {\n            \"column\": 30,\n            \"line\": 14,\n          },\n          \"start\": {\n            \"column\": 16,\n            \"line\": 14,\n          },\n        },\n        \"line\": 14,\n        \"loc\": {\n          \"end\": {\n            \"column\": null,\n            \"line\": 19,\n          },\n          \"start\": {\n            \"column\": 33,\n            \"line\": 14,\n          },\n        },\n        \"name\": \"getSetupStates\",\n      },\n    },\n    \"meta\": {\n      \"lastBranch\": 0,\n      \"lastFunction\": 3,\n      \"lastStatement\": 7,\n      \"seen\": {\n        \"f:10:33:10:34\": 1,\n        \"f:14:16:14:30\": 2,\n        \"f:6:33:6:34\": 0,\n        \"s:10:27:12:Infinity\": 4,\n        \"s:11:2:11:Infinity\": 5,\n        \"s:15:2:18:Infinity\": 6,\n        \"s:3:14:3:Infinity\": 0,\n        \"s:4:14:4:Infinity\": 1,\n        \"s:6:27:8:Infinity\": 2,\n        \"s:7:2:7:Infinity\": 3,\n      },\n    },\n    \"path\": \"<process-cwd>/fixtures/no-module-runner/src/setups.ts\",\n    \"s\": {\n      \"0\": 1,\n      \"1\": 1,\n      \"2\": 1,\n      \"3\": 9,\n      \"4\": 1,\n      \"5\": 9,\n      \"6\": 1,\n    },\n    \"statementMap\": {\n      \"0\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 3,\n        },\n        \"start\": {\n          \"column\": 14,\n          \"line\": 3,\n        },\n      },\n      \"1\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 4,\n        },\n        \"start\": {\n          \"column\": 14,\n          \"line\": 4,\n        },\n      },\n      \"2\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 8,\n        },\n        \"start\": {\n          \"column\": 27,\n          \"line\": 6,\n        },\n      },\n      \"3\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 7,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 7,\n        },\n      },\n      \"4\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 12,\n        },\n        \"start\": {\n          \"column\": 27,\n          \"line\": 10,\n        },\n      },\n      \"5\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 11,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 11,\n        },\n      },\n      \"6\": {\n        \"end\": {\n          \"column\": null,\n          \"line\": 18,\n        },\n        \"start\": {\n          \"column\": 2,\n          \"line\": 15,\n        },\n      },\n    },\n  },\n}\n`;\n"
  },
  {
    "path": "test/cli/test/__snapshots__/stacktraces.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`stacktrace filtering > filters stacktraces 1`] = `\n\"\n⎯⎯ Failed Tests 1 ⎯⎯\n\n FAIL  error-with-stack.test.js > error in deps\nError: Something truly horrible has happened!\n ❯ d error-with-stack.test.js:20:9\n     18|\n     19| function d() {\n     20|   throw new Error('Something truly horrible has happened!')\n       |         ^\n     21| }\n     22|\n ❯ c error-with-stack.test.js:16:3\n ❯ a error-with-stack.test.js:8:3\n ❯ error-with-stack.test.js:4:3\n\n⎯⎯[1/1]⎯\n\n\"\n`;\n\nexports[`stacktrace in dependency package > external 1`] = `\n\"\n⎯⎯ Failed Tests 4 ⎯⎯\n\n FAIL  error-in-package.test.js > js\nError: __TEST_STACK__\n ❯ innerTestStack (NODE_MODULES)/@test/test-dep-error/index.js:10:9\n ❯ testStack (NODE_MODULES)/@test/test-dep-error/index.js:4:3\n ❯ error-in-package.test.js:8:12\n      6|\n      7| test('js', () => {\n      8|   testStack()\n       |            ^\n      9| })\n     10|\n\n⎯⎯[1/4]⎯\n\n FAIL  error-in-package.test.js > ts\nError: __TEST_STACK_TS__\n ❯ innerTestStack (NODE_MODULES)/@test/test-dep-error/ts.ts:22:9\n     20|  */\n     21| function innerTestStack() {\n     22|   throw new Error('__TEST_STACK_TS__')\n       |         ^\n     23| }\n     24|\n ❯ testStack (NODE_MODULES)/@test/test-dep-error/ts.ts:12:3\n ❯ error-in-package.test.js:12:14\n\n⎯⎯[2/4]⎯\n\n FAIL  error-in-package.test.js > transpiled\nError: __TEST_STACK_TRANSPILED__\n ❯ innerTestStack (NODE_MODULES)/@test/test-dep-error/transpiled.ts:22:8\n ❯ testStack (NODE_MODULES)/@test/test-dep-error/transpiled.ts:12:2\n ❯ error-in-package.test.js:16:22\n     14|\n     15| test('transpiled', () => {\n     16|   testStackTranspiled()\n       |                      ^\n     17| })\n     18|\n\n⎯⎯[3/4]⎯\n\n FAIL  error-in-package.test.js > transpiled inline\nError: __TEST_STACK_TRANSPILED_INLINE__\n ❯ innerTestStack (NODE_MODULES)/@test/test-dep-error/transpiled-inline.ts:22:8\n ❯ testStack (NODE_MODULES)/@test/test-dep-error/transpiled-inline.ts:12:2\n ❯ error-in-package.test.js:20:28\n     18|\n     19| test('transpiled inline', () => {\n     20|   testStackTranspiledInline()\n       |                            ^\n     21| })\n     22|\n\n⎯⎯[4/4]⎯\n\n\"\n`;\n\nexports[`stacktrace in dependency package > inline 1`] = `\n\"\n⎯⎯ Failed Tests 4 ⎯⎯\n\n FAIL  error-in-package.test.js > js\nError: __TEST_STACK__\n ❯ innerTestStack (NODE_MODULES)/@test/test-dep-error/index.js:10:9\n      8|\n      9| function innerTestStack() {\n     10|   throw new Error('__TEST_STACK__')\n       |         ^\n     11| }\n     12|\n ❯ testStack (NODE_MODULES)/@test/test-dep-error/index.js:4:3\n ❯ error-in-package.test.js:8:12\n\n⎯⎯[1/4]⎯\n\n FAIL  error-in-package.test.js > ts\nError: __TEST_STACK_TS__\n ❯ innerTestStack (NODE_MODULES)/@test/test-dep-error/ts.ts:22:9\n     20|  */\n     21| function innerTestStack() {\n     22|   throw new Error('__TEST_STACK_TS__')\n       |         ^\n     23| }\n     24|\n ❯ testStack (NODE_MODULES)/@test/test-dep-error/ts.ts:12:3\n ❯ error-in-package.test.js:12:14\n\n⎯⎯[2/4]⎯\n\n FAIL  error-in-package.test.js > transpiled\nError: __TEST_STACK_TRANSPILED__\n ❯ innerTestStack (NODE_MODULES)/@test/test-dep-error/transpiled.ts:22:9\n ❯ testStack (NODE_MODULES)/@test/test-dep-error/transpiled.ts:12:3\n ❯ error-in-package.test.js:16:22\n     14|\n     15| test('transpiled', () => {\n     16|   testStackTranspiled()\n       |                      ^\n     17| })\n     18|\n\n⎯⎯[3/4]⎯\n\n FAIL  error-in-package.test.js > transpiled inline\nError: __TEST_STACK_TRANSPILED_INLINE__\n ❯ innerTestStack (NODE_MODULES)/@test/test-dep-error/transpiled-inline.ts:22:9\n ❯ testStack (NODE_MODULES)/@test/test-dep-error/transpiled-inline.ts:12:3\n ❯ error-in-package.test.js:20:28\n     18|\n     19| test('transpiled inline', () => {\n     20|   testStackTranspiledInline()\n       |                            ^\n     21| })\n     22|\n\n⎯⎯[4/4]⎯\n\n\"\n`;\n\nexports[`stacktrace in vmThreads 1`] = `\n\"\n⎯⎯ Failed Tests 1 ⎯⎯\n\n FAIL  error-with-stack.test.js > error in deps\nError: Something truly horrible has happened!\n ❯ d error-with-stack.test.js:20:9\n     18|\n     19| function d() {\n     20|   throw new Error('Something truly horrible has happened!')\n       |         ^\n     21| }\n     22|\n ❯ c error-with-stack.test.js:16:3\n ❯ b error-with-stack.test.js:12:3\n ❯ a error-with-stack.test.js:8:3\n ❯ error-with-stack.test.js:4:3\n\n⎯⎯[1/1]⎯\n\n\"\n`;\n\nexports[`stacktrace should print error frame source file correctly > error-in-deps 1`] = `\n\"\n⎯⎯ Failed Tests 1 ⎯⎯\n\n FAIL  error-in-deps.test.js > error in deps\nReferenceError: bar is not defined\n ❯ add foo.js:3:3\n      1| export function add() {\n      2|   // eslint-disable-next-line no-undef\n      3|   return bar()\n       |   ^\n      4| }\n      5|\n ❯ error-in-deps.test.js:5:6\n\n⎯⎯[1/1]⎯\n\n\"\n`;\n\nexports[`stacktraces should pick error frame if present > frame.spec.imba 1`] = `\n\" FAIL  frame.spec.imba [ frame.spec.imba ]\nimba-parser error: Unexpected 'CALL_END'\n4 | test(\"1+1\") do\n5 |  expect(1+1).toBe 2\n6 |  frame.\n  |        ^\n7 |\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > add.test.ts 1`] = `\n\" ❯ add.test.ts:12:24\n     10|\n     11| it('add', () => {\n     12|   expect(add(a.count)).toBe(100)\n       |                        ^\n     13|   expect(add(1)).toBe(1)\n     14|   return expect(add(1, 2, 3)).toBe(6)\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > add-in-imba.test.imba 1`] = `\n\" ❯ add-in-imba.test.imba:8:17\n      6| it \"add\", do\n      7|  expect(add()).toBe 0\n      8|  expect(add(1)).toBe 3\n       |                 ^\n      9|  expect(add(1, 2, 3)).toBe 6\n     10|\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > add-in-js.test.js 1`] = `\n\" ❯ add-in-js.test.js:6:17\n      4|\n      5| it('add', () => {\n      6|   expect(add()).toBe(100)\n       |                 ^\n      7|   expect(add(1)).toBe(1)\n      8|   return expect(add(1, 2, 3)).toBe(6)\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > error-in-deps.test.js 1`] = `\n\" ❯ error-in-deps.test.js:5:6\n\n⎯⎯[1/1]⎯\n\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > error-in-package.test.js 1`] = `\n\" ❯ error-in-package.test.js:8:12\n      6|\n      7| test('js', () => {\n      8|   testStack()\n       |            ^\n      9| })\n     10|\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > error-with-stack.test.js 1`] = `\n\" ❯ d error-with-stack.test.js:20:9\n     18|\n     19| function d() {\n     20|   throw new Error('Something truly horrible has happened!')\n       |         ^\n     21| }\n     22|\n ❯ c error-with-stack.test.js:16:3\"\n`;\n\nexports[`stacktraces should respect sourcemaps > mocked-global.test.js 1`] = `\n\" ❯ mocked-global.test.js:6:13\n      4|\n      5| test('failed', () => {\n      6|   expect(1).toBe(2)\n       |             ^\n      7| })\n      8|\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > mocked-imported.test.js 1`] = `\n\" ❯ mocked-imported.test.js:6:13\n      4|\n      5| test('failed', () => {\n      6|   expect(1).toBe(2)\n       |             ^\n      7| })\n      8|\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > mocked-imported.test.ts 1`] = `\n\" ❯ mocked-imported.test.ts:6:13\n      4|\n      5| test('failed', () => {\n      6|   expect(1).toBe(2)\n       |             ^\n      7| })\n      8|\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > require-assertions.test.js 1`] = `\n\" ❯ require-assertions.test.js:3:5\n      1| import { test } from 'vitest'\n      2|\n      3| test('assertion is not called', () => {\n       |     ^\n      4|   // no expect\n      5| })\n\"\n`;\n\nexports[`stacktraces should respect sourcemaps > reset-modules.test.ts 1`] = `\n\" ❯ reset-modules.test.ts:16:26\n     14|     expect(2 + 1).eq(3)\n     15|     assert.equal(Math.sqrt(4), 2)\n     16|     expect(Math.sqrt(4)).toBe(1)\n       |                          ^\n     17|   })\n     18| })\n\"\n`;\n"
  },
  {
    "path": "test/cli/test/annotations.test.ts",
    "content": "import type { TestArtifact } from '@vitest/runner'\nimport type { TestAnnotation } from 'vitest'\nimport { playwright } from '@vitest/browser-playwright'\nimport { describe, expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\nconst test3Content = /* ts */`\nexport async function externalAnnotate(annotate) {\n  await annotate('external')\n}\n`\n\nconst annotationTest = /* ts */`\nimport { test, describe } from 'vitest'\nimport { externalAnnotate } from './test-3.js'\n\ntest('simple', async ({ annotate }) => {\n  await annotate('1')\n  await annotate('2', 'warning')\n  await annotate('3', { path: './test-3.js' })\n  await annotate('4', 'warning', { path: './test-4.js' })\n  await externalAnnotate(annotate)\n  await annotate('with base64 body', { body: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' })\n  await annotate('with Uint8Array body', { body: new Uint8Array(Array.from({ length: 256 }).map((_, i) => i)) })\n  await annotate('with contentType', { body: '', contentType: 'text/plain' })\n})\n\ndescribe('suite', () => {\n  test('second', async ({ annotate }) => {\n    await annotate('5')\n    await annotate('6', { path: 'https://absolute-path.com' })\n  })\n})\n`\n\ndescribe('API', () => {\n  test.for([\n    { name: 'forks', pool: 'forks' },\n    { name: 'threads', pool: 'threads' },\n    {\n      name: 'browser',\n      browser: {\n        enabled: true,\n        provider: playwright(),\n        headless: true,\n        instances: [\n          { browser: 'chromium' as const },\n        ],\n      },\n    },\n  ])('annotations are exposed correctly in $name', async (options) => {\n    const events: string[] = []\n    const annotations: Record<string, ReadonlyArray<TestAnnotation>> = {}\n    const artifacts: Record<string, ReadonlyArray<TestArtifact>> = {}\n\n    const { stderr } = await runInlineTests(\n      {\n        'basic.test.ts': annotationTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n        'vitest.config.js': { test: options },\n      },\n      {\n        includeTaskLocation: true,\n        reporters: [\n          'default',\n          {\n            onTestCaseAnnotate(testCase, annotation) {\n              const path = annotation.attachment?.path?.replace(testCase.project.config.root, '<root>').replace(/\\w+\\.js$/, '<hash>.js')\n              events.push(`[annotate] ${testCase.name} ${annotation.message} ${annotation.type} path=${path} contentType=${annotation.attachment?.contentType} body=${annotation.attachment?.body}`)\n            },\n            onTestCaseArtifactRecord() {\n              events.push('[artifact]')\n            },\n            onTestCaseReady(testCase) {\n              events.push(`[ready] ${testCase.name}`)\n            },\n            onTestCaseResult(testCase) {\n              events.push(`[result] ${testCase.name}`)\n              annotations[testCase.name] = testCase.annotations().map((annotation) => {\n                if (annotation.attachment?.path) {\n                  annotation.attachment.path = annotation.attachment.path.replace(\n                    testCase.project.config.root,\n                    '<root>',\n                  ).replace(/\\w+\\.js$/, '<hash>.js')\n                }\n                if (annotation.location) {\n                  annotation.location.file = annotation.location.file.replace(\n                    testCase.project.config.root,\n                    '<root>',\n                  )\n                }\n                return annotation\n              })\n              // artifacts should be empty until next major so no handling needed\n              artifacts[testCase.name] = testCase.artifacts()\n            },\n          },\n        ],\n      },\n    )\n\n    expect(stderr).toBe('')\n    expect(events).toMatchInlineSnapshot(`\n      [\n        \"[ready] simple\",\n        \"[annotate] simple 1 notice path=undefined contentType=undefined body=undefined\",\n        \"[annotate] simple 2 warning path=undefined contentType=undefined body=undefined\",\n        \"[annotate] simple 3 notice path=<root>/.vitest-attachments/3-<hash>.js contentType=text/javascript body=undefined\",\n        \"[annotate] simple 4 warning path=<root>/.vitest-attachments/4-<hash>.js contentType=text/javascript body=undefined\",\n        \"[annotate] simple external notice path=undefined contentType=undefined body=undefined\",\n        \"[annotate] simple with base64 body notice path=undefined contentType=undefined body=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",\n        \"[annotate] simple with Uint8Array body notice path=undefined contentType=undefined body=AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\",\n        \"[annotate] simple with contentType notice path=undefined contentType=text/plain body=\",\n        \"[result] simple\",\n        \"[ready] second\",\n        \"[annotate] second 5 notice path=undefined contentType=undefined body=undefined\",\n        \"[annotate] second 6 notice path=https://absolute-path.com contentType=undefined body=undefined\",\n        \"[result] second\",\n      ]\n    `)\n\n    expect(artifacts).toMatchInlineSnapshot(`\n      {\n        \"second\": [],\n        \"simple\": [],\n      }\n    `)\n    expect(annotations).toMatchInlineSnapshot(`\n      {\n        \"second\": [\n          {\n            \"location\": {\n              \"column\": 11,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 18,\n            },\n            \"message\": \"5\",\n            \"type\": \"notice\",\n          },\n          {\n            \"attachment\": {\n              \"path\": \"https://absolute-path.com\",\n            },\n            \"location\": {\n              \"column\": 11,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 19,\n            },\n            \"message\": \"6\",\n            \"type\": \"notice\",\n          },\n        ],\n        \"simple\": [\n          {\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 6,\n            },\n            \"message\": \"1\",\n            \"type\": \"notice\",\n          },\n          {\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 7,\n            },\n            \"message\": \"2\",\n            \"type\": \"warning\",\n          },\n          {\n            \"attachment\": {\n              \"contentType\": \"text/javascript\",\n              \"path\": \"<root>/.vitest-attachments/3-<hash>.js\",\n            },\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 8,\n            },\n            \"message\": \"3\",\n            \"type\": \"notice\",\n          },\n          {\n            \"attachment\": {\n              \"contentType\": \"text/javascript\",\n              \"path\": \"<root>/.vitest-attachments/4-<hash>.js\",\n            },\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 9,\n            },\n            \"message\": \"4\",\n            \"type\": \"warning\",\n          },\n          {\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 10,\n            },\n            \"message\": \"external\",\n            \"type\": \"notice\",\n          },\n          {\n            \"attachment\": {\n              \"body\": \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",\n            },\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 11,\n            },\n            \"message\": \"with base64 body\",\n            \"type\": \"notice\",\n          },\n          {\n            \"attachment\": {\n              \"body\": \"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\",\n            },\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 12,\n            },\n            \"message\": \"with Uint8Array body\",\n            \"type\": \"notice\",\n          },\n          {\n            \"attachment\": {\n              \"body\": \"\",\n              \"contentType\": \"text/plain\",\n            },\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 13,\n            },\n            \"message\": \"with contentType\",\n            \"type\": \"notice\",\n          },\n        ],\n      }\n    `)\n  })\n\n  test('cannot annotate tests when the test finished running', async () => {\n    const { stderr } = await runInlineTests({\n      'basic.test.ts': `\n        test('finished early', ({ annotate }) => {\n          setTimeout(() => {\n            annotate('invalid annotations')\n          }, 50)\n        })\n\n        test('long running test ', async () => {\n          await new Promise(r => setTimeout(() => r(), 100))\n        })\n      `,\n    }, { globals: true })\n    expect(stderr).toContain('Cannot annotate tests outside of the test run. The test \"finished early\" finished running with the \"pass\" state already.')\n  })\n})\n\ndescribe('reporters', () => {\n  test('tap reporter prints annotations', async () => {\n    const { stdout } = await runInlineTests(\n      {\n        'basic.test.ts': annotationTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: ['tap'] },\n    )\n\n    expect(stdout.replace(/[\\d.]+ms/g, '<time>')).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..1\n      ok 1 - basic.test.ts # time=<time> {\n          1..2\n          ok 1 - simple # time=<time>\n              # notice: 1\n              # warning: 2\n              # notice: 3\n              # warning: 4\n              # notice: external\n              # notice: with base64 body\n              # notice: with Uint8Array body\n              # notice: with contentType\n          ok 2 - suite # time=<time> {\n              1..1\n              ok 1 - second # time=<time>\n                  # notice: 5\n                  # notice: 6\n          }\n      }\n      \"\n    `)\n  })\n\n  test('tap-flat reporter prints annotations', async () => {\n    const { stdout } = await runInlineTests(\n      {\n        'basic.test.ts': annotationTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: ['tap-flat'] },\n    )\n\n    expect(stdout.replace(/[\\d.]+ms/g, '<time>')).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..2\n      ok 1 - basic.test.ts > simple # time=<time>\n          # notice: 1\n          # warning: 2\n          # notice: 3\n          # warning: 4\n          # notice: external\n          # notice: with base64 body\n          # notice: with Uint8Array body\n          # notice: with contentType\n      ok 2 - basic.test.ts > suite > second # time=<time>\n          # notice: 5\n          # notice: 6\n      \"\n    `)\n  })\n\n  test('junit reporter prints annotations', async () => {\n    const { stdout } = await runInlineTests(\n      {\n        'basic.test.ts': annotationTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: ['junit'] },\n    )\n\n    const result = stdout\n      .replace(/time=\"[\\d.]+\"/g, 'time=\"0\"')\n      .replace(/timestamp=\"[\\w\\-:.]+\"/g, 'timestamp=\"0\"')\n      .replace(/hostname=\"[\\w.\\-]+\"/g, 'hostname=\"CI\"')\n\n    expect(result).toMatchInlineSnapshot(`\n      \"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n      <testsuites name=\"vitest tests\" tests=\"2\" failures=\"0\" errors=\"0\" time=\"0\">\n          <testsuite name=\"basic.test.ts\" timestamp=\"0\" hostname=\"CI\" tests=\"2\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0\">\n              <testcase classname=\"basic.test.ts\" name=\"simple\" time=\"0\">\n                  <properties>\n                      <property name=\"notice\" value=\"1\">\n                      </property>\n                      <property name=\"warning\" value=\"2\">\n                      </property>\n                      <property name=\"notice\" value=\"3\">\n                      </property>\n                      <property name=\"warning\" value=\"4\">\n                      </property>\n                      <property name=\"notice\" value=\"external\">\n                      </property>\n                      <property name=\"notice\" value=\"with base64 body\">\n                      </property>\n                      <property name=\"notice\" value=\"with Uint8Array body\">\n                      </property>\n                      <property name=\"notice\" value=\"with contentType\">\n                      </property>\n                  </properties>\n              </testcase>\n              <testcase classname=\"basic.test.ts\" name=\"suite &gt; second\" time=\"0\">\n                  <properties>\n                      <property name=\"notice\" value=\"5\">\n                      </property>\n                      <property name=\"notice\" value=\"6\">\n                      </property>\n                  </properties>\n              </testcase>\n          </testsuite>\n      </testsuites>\n      \"\n    `)\n  })\n\n  test('github-actions reporter prints annotations', async () => {\n    const { stdout, ctx } = await runInlineTests(\n      {\n        'basic.test.ts': annotationTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: ['github-actions'] },\n    )\n\n    expect(ctx).toBeDefined()\n\n    // the file path is escaped on windows\n    const result = stdout\n      .replace(/file=(\\w)%3A/g, 'file=$1:')\n      .replace(new RegExp(ctx!.config.root, 'g'), '<root>')\n    expect(result).toMatchInlineSnapshot(`\n      \"\n      ::notice file=<root>/basic.test.ts,line=6,column=9::1\n\n      ::warning file=<root>/basic.test.ts,line=7,column=9::2\n\n      ::notice file=<root>/basic.test.ts,line=8,column=9::3\n\n      ::warning file=<root>/basic.test.ts,line=9,column=9::4\n\n      ::notice file=<root>/basic.test.ts,line=10,column=9::external\n\n      ::notice file=<root>/basic.test.ts,line=11,column=9::with base64 body\n\n      ::notice file=<root>/basic.test.ts,line=12,column=9::with Uint8Array body\n\n      ::notice file=<root>/basic.test.ts,line=13,column=9::with contentType\n\n      ::notice file=<root>/basic.test.ts,line=18,column=11::5\n\n      ::notice file=<root>/basic.test.ts,line=19,column=11::6\n      \"\n    `)\n  })\n\n  test('verbose non-tty reporter prints annotations', async () => {\n    const { stdout } = await runInlineTests(\n      {\n        'basic.test.ts': annotationTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: [['verbose', { isTTY: false }]] },\n    )\n\n    const result = stdout\n      .replace(/\\d+ms/g, '<time>')\n      .split('\\n')\n      // remove banner and summary\n      .slice(3, -6)\n      .join('\\n')\n\n    expect(result).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > simple <time>\n\n         ❯ basic.test.ts:6:9 notice\n           ↳ 1\n         ❯ basic.test.ts:7:9 warning\n           ↳ 2\n         ❯ basic.test.ts:8:9 notice\n           ↳ 3\n         ❯ basic.test.ts:9:9 warning\n           ↳ 4\n         ❯ basic.test.ts:10:9 notice\n           ↳ external\n         ❯ basic.test.ts:11:9 notice\n           ↳ with base64 body\n         ❯ basic.test.ts:12:9 notice\n           ↳ with Uint8Array body\n         ❯ basic.test.ts:13:9 notice\n           ↳ with contentType\n\n       ✓ basic.test.ts > suite > second <time>\n\n         ❯ basic.test.ts:18:11 notice\n           ↳ 5\n         ❯ basic.test.ts:19:11 notice\n           ↳ 6\n\n      \"\n    `)\n  })\n\n  describe('default', () => {\n    test('default reporter prints annotations after the error', async () => {\n      const { stdout, stderr } = await runInlineTests(\n        {\n          'basic.test.ts': /* ts */`\n            import { test } from 'vitest'\n\n            test('non-failing test', ({ annotate }) => {\n              annotate('[non-failing] not printed')\n            })\n\n            test('failed test', ({ annotate }) => {\n              annotate('printed')\n              annotate('also printed', 'warning')\n              throw new Error('thrown error')\n            })\n          `,\n        },\n        { reporters: [['default', { isTTY: false }]] },\n      )\n\n      expect(stdout).not.toContain('[non-failing] not printed')\n      expect(stderr).not.toContain('[non-failing] not printed')\n\n      expect(stderr).toMatchInlineSnapshot(`\n        \"\n        ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n         FAIL  basic.test.ts > failed test\n        Error: thrown error\n         ❯ basic.test.ts:11:21\n              9|               annotate('printed')\n             10|               annotate('also printed', 'warning')\n             11|               throw new Error('thrown error')\n               |                     ^\n             12|             })\n             13|\n\n         ❯ basic.test.ts:9:15 notice\n           ↳ printed\n         ❯ basic.test.ts:10:15 warning\n           ↳ also printed\n\n        ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n        \"\n      `)\n    })\n\n    test('default reporter prints the same error with the same annotations only once', async () => {\n      const { stderr } = await runInlineTests(\n        {\n          'basic.test.ts': /* ts */`\n            import { test } from 'vitest'\n\n            test.for([1, 2])('failed test %i', (num, { annotate }) => {\n              annotate('printed')\n              throw new Error('thrown error')\n            })\n          `,\n        },\n        { reporters: [['default', { isTTY: false }]] },\n      )\n\n      expect(stderr).toMatchInlineSnapshot(`\n        \"\n        ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 2 ⎯⎯⎯⎯⎯⎯⎯\n\n         FAIL  basic.test.ts > failed test 1\n         FAIL  basic.test.ts > failed test 2\n        Error: thrown error\n         ❯ basic.test.ts:6:21\n              4|             test.for([1, 2])('failed test %i', (num, { annotate }) => {\n              5|               annotate('printed')\n              6|               throw new Error('thrown error')\n               |                     ^\n              7|             })\n              8|\n\n         ❯ basic.test.ts:5:15 notice\n           ↳ printed\n\n        ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯\n\n        \"\n      `)\n    })\n\n    test('default reporter prints different annotations after the same error', async () => {\n      const { stderr } = await runInlineTests(\n        {\n          'basic.test.ts': /* ts */`\n            import { test } from 'vitest'\n\n            test.for([1, 2])('failed test %i', (num, { annotate }) => {\n              annotate('printed ' + num)\n              throw new Error('thrown error')\n            })\n          `,\n        },\n        { reporters: [['default', { isTTY: false }]] },\n      )\n\n      expect(stderr).toMatchInlineSnapshot(`\n        \"\n        ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 2 ⎯⎯⎯⎯⎯⎯⎯\n\n         FAIL  basic.test.ts > failed test 1\n        Error: thrown error\n         ❯ basic.test.ts:6:21\n              4|             test.for([1, 2])('failed test %i', (num, { annotate }) => {\n              5|               annotate('printed ' + num)\n              6|               throw new Error('thrown error')\n               |                     ^\n              7|             })\n              8|\n\n         ❯ basic.test.ts:5:15 notice\n           ↳ printed 1\n\n        ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯\n\n         FAIL  basic.test.ts > failed test 2\n        Error: thrown error\n         ❯ basic.test.ts:6:21\n              4|             test.for([1, 2])('failed test %i', (num, { annotate }) => {\n              5|               annotate('printed ' + num)\n              6|               throw new Error('thrown error')\n               |                     ^\n              7|             })\n              8|\n\n         ❯ basic.test.ts:5:15 notice\n           ↳ printed 2\n\n        ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/2]⎯\n\n        \"\n      `)\n    })\n  })\n})\n"
  },
  {
    "path": "test/cli/test/around-each.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\nfunction extractLogs(stdout: string): string {\n  return stdout.split('\\n').filter(l => l.includes('>>')).join('\\n')\n}\n\ntest('basic aroundEach wraps the test', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'basic.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> before test')\n        await runTest()\n        console.log('>> after test')\n      })\n\n      test('test 1', () => {\n        console.log('>> inside test')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> before test\n    >> inside test\n    >> after test\"\n  `)\n})\n\ntest('multiple aroundEach hooks are nested (first is outermost)', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'nested-hooks.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> outer before')\n        await runTest()\n        console.log('>> outer after')\n      })\n\n      aroundEach(async (runTest) => {\n        console.log('>> inner before')\n        await runTest()\n        console.log('>> inner after')\n      })\n\n      test('test 1', () => {\n        console.log('>> test')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n\n  // Extract log lines\n  const logs = stdout.split('\\n').filter(line => line.startsWith('>> ')).map(l => l.trim())\n  expect(logs).toEqual([\n    '>> outer before',\n    '>> inner before',\n    '>> test',\n    '>> inner after',\n    '>> outer after',\n  ])\n})\n\ntest('aroundEach in nested suites wraps correctly', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'nested-suites.test.ts': `\n      import { aroundEach, describe, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> root before')\n        await runTest()\n        console.log('>> root after')\n      })\n\n      describe('suite 1', () => {\n        aroundEach(async (runTest) => {\n          console.log('>> suite1 before')\n          await runTest()\n          console.log('>> suite1 after')\n        })\n\n        test('test in suite 1', () => {\n          console.log('>> test suite1')\n        })\n\n        describe('nested suite', () => {\n          aroundEach(async (runTest) => {\n            console.log('>> nested before')\n            await runTest()\n            console.log('>> nested after')\n          })\n\n          test('test in nested suite', () => {\n            console.log('>> test nested')\n          })\n        })\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> root before\n    >> suite1 before\n    >> test suite1\n    >> suite1 after\n    >> root after\n    >> root before\n    >> suite1 before\n    >> nested before\n    >> test nested\n    >> nested after\n    >> suite1 after\n    >> root after\"\n  `)\n})\n\ntest('throws error when runTest is called multiple times', async () => {\n  const { stderr } = await runInlineTests({\n    'multiple-calls.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        await runTest()\n        await runTest() // second call should throw\n      })\n\n      test('test 1', () => {\n        console.log('>> test ran')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  multiple-calls.test.ts > test 1\n    AroundHookMultipleCallsError: The \\`runTest()\\` callback was called multiple times in the \\`aroundEach\\` hook. The callback can only be called once per hook.\n     ❯ multiple-calls.test.ts:6:15\n          4|       aroundEach(async (runTest) => {\n          5|         await runTest()\n          6|         await runTest() // second call should throw\n           |               ^\n          7|       })\n          8|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('throws error when runTest is not called', async () => {\n  const { stderr } = await runInlineTests({\n    'no-runtest.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (_runTest) => {\n        console.log('>> aroundEach without calling runTest')\n        // Not calling runTest()\n      })\n\n      test('test 1', () => {\n        console.log('>> test should not run')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  no-runtest.test.ts > test 1\n    AroundHookSetupError: The \\`runTest()\\` callback was not called in the \\`aroundEach\\` hook. Make sure to call \\`runTest()\\` to run the test.\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('aroundEach with async operations', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'async.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> setup start')\n        await new Promise(r => setTimeout(r, 10))\n        console.log('>> setup done')\n        await runTest()\n        console.log('>> cleanup start')\n        await new Promise(r => setTimeout(r, 10))\n        console.log('>> cleanup done')\n      })\n\n      test('async test', async () => {\n        console.log('>> test running')\n        await new Promise(r => setTimeout(r, 10))\n        console.log('>> test done')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"async.test.ts\": {\n        \"async test\": \"passed\",\n      },\n    }\n  `)\n\n  const logs = stdout.split('\\n').filter(line => line.startsWith('>> ')).map(l => l.trim())\n  expect(logs).toEqual([\n    '>> setup start',\n    '>> setup done',\n    '>> test running',\n    '>> test done',\n    '>> cleanup start',\n    '>> cleanup done',\n  ])\n})\n\ntest('aroundEach runs for each test', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'each-test.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      let counter = 0\n\n      aroundEach(async (runTest) => {\n        counter++\n        console.log('>> aroundEach run ' + counter)\n        await runTest()\n      })\n\n      test('test 1', () => {\n        console.log('>> test 1')\n      })\n\n      test('test 2', () => {\n        console.log('>> test 2')\n      })\n\n      test('test 3', () => {\n        console.log('>> test 3')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundEach run 1\n    >> test 1\n    >> aroundEach run 2\n    >> test 2\n    >> aroundEach run 3\n    >> test 3\"\n  `)\n})\n\ntest('aroundEach with beforeEach and afterEach', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'with-hooks.test.ts': `\n      import { aroundEach, beforeEach, afterEach, test } from 'vitest'\n\n      beforeEach(() => {\n        console.log('>> beforeEach')\n      })\n\n      aroundEach(async (runTest) => {\n        console.log('>> aroundEach before')\n        await runTest()\n        console.log('>> aroundEach after')\n      })\n\n      afterEach(() => {\n        console.log('>> afterEach')\n      })\n\n      test('test 1', () => {\n        console.log('>> test')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n\n  // aroundEach should wrap around beforeEach/test/afterEach\n  const logs = stdout.split('\\n').filter(line => line.startsWith('>> ')).map(l => l.trim())\n  expect(logs).toEqual([\n    '>> aroundEach before',\n    '>> beforeEach',\n    '>> test',\n    '>> afterEach',\n    '>> aroundEach after',\n  ])\n})\n\ntest('aroundEach receives test context', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'context.test.ts': `\n      import { aroundEach, test, expect } from 'vitest'\n\n      aroundEach(async (runTest, context) => {\n        console.log('>> test name:', context.task.name)\n        await runTest()\n      })\n\n      test('my test name', () => {\n        console.log('>> inside test')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> test name: my test name\n    >> inside test\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"context.test.ts\": {\n        \"my test name\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach cleanup runs even on test failure', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'test-failure.test.ts': `\n      import { aroundEach, test, expect } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> setup')\n        await runTest()\n        console.log('>> cleanup (should run)')\n      })\n\n      test('failing test', () => {\n        console.log('>> test running')\n        expect(1).toBe(2) // This will fail\n      })\n    `,\n  })\n\n  // Cleanup should still run even when test fails\n  expect(stderr).toContain('expected 1 to be 2')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> setup\n    >> test running\n    >> cleanup (should run)\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"test-failure.test.ts\": {\n        \"failing test\": [\n          \"expected 1 to be 2 // Object.is equality\",\n        ],\n      },\n    }\n  `)\n})\n\ntest('aroundEach error prevents test from running', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'hook-error.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> before error')\n        throw new Error('aroundEach error')\n        await runTest() // unreachable\n      })\n\n      test('test 1', () => {\n        console.log('>> test should not run')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  hook-error.test.ts > test 1\n    Error: aroundEach error\n     ❯ hook-error.test.ts:6:15\n          4|       aroundEach(async (runTest) => {\n          5|         console.log('>> before error')\n          6|         throw new Error('aroundEach error')\n           |               ^\n          7|         await runTest() // unreachable\n          8|       })\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\">> before error\"`)\n})\n\ntest('aroundEach cleanup error is reported', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'cleanup-error.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> setup')\n        await runTest()\n        console.log('>> cleanup before error')\n        throw new Error('cleanup error')\n      })\n\n      test('test 1', () => {\n        console.log('>> test ran')\n      })\n    `,\n  })\n\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> setup\n    >> test ran\n    >> cleanup before error\"\n  `)\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  cleanup-error.test.ts > test 1\n    Error: cleanup error\n     ❯ cleanup-error.test.ts:8:15\n          6|         await runTest()\n          7|         console.log('>> cleanup before error')\n          8|         throw new Error('cleanup error')\n           |               ^\n          9|       })\n         10|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('aroundEach with database transaction pattern', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'transaction.test.ts': `\n      import { aroundEach, test, expect } from 'vitest'\n\n      // Simulating a database transaction pattern\n      const db = {\n        data: [] as string[],\n        inTransaction: false,\n        beginTransaction() {\n          this.inTransaction = true\n          console.log('>> BEGIN TRANSACTION')\n        },\n        commit() {\n          this.inTransaction = false\n          console.log('>> COMMIT')\n        },\n        rollback() {\n          this.data = []\n          this.inTransaction = false\n          console.log('>> ROLLBACK')\n        },\n        insert(value: string) {\n          if (!this.inTransaction) throw new Error('Not in transaction')\n          this.data.push(value)\n          console.log('>> INSERT:', value)\n        }\n      }\n\n      aroundEach(async (runTest) => {\n        db.beginTransaction()\n        try {\n          await runTest()\n        } finally {\n          db.rollback() // Always rollback to keep tests isolated\n        }\n      })\n\n      test('insert data', () => {\n        db.insert('test1')\n        expect(db.data).toContain('test1')\n      })\n\n      test('data is rolled back', () => {\n        expect(db.data).toEqual([]) // Previous test's data was rolled back\n        db.insert('test2')\n        expect(db.data).toContain('test2')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"transaction.test.ts\": {\n        \"data is rolled back\": \"passed\",\n        \"insert data\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach with globals: true', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'globals.test.ts': `\n      aroundEach(async (runTest) => {\n        console.log('>> aroundEach global')\n        await runTest()\n        console.log('>> aroundEach global done')\n      })\n\n      test('test with globals', () => {\n        console.log('>> test')\n      })\n    `,\n  }, { globals: true })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundEach global\n    >> test\n    >> aroundEach global done\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"globals.test.ts\": {\n        \"test with globals\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach with test.each', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'test-each.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest, context) => {\n        console.log('>> aroundEach for:', context.task.name)\n        await runTest()\n      })\n\n      test.each([1, 2, 3])('test %i', (num) => {\n        console.log('>> test value:', num)\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundEach for: test 1\n    >> test value: 1\n    >> aroundEach for: test 2\n    >> test value: 2\n    >> aroundEach for: test 3\n    >> test value: 3\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"test-each.test.ts\": {\n        \"test 1\": \"passed\",\n        \"test 2\": \"passed\",\n        \"test 3\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach with concurrent tests', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'concurrent.test.ts': `\n      import { aroundEach, describe, test } from 'vitest'\n\n      const logs: string[] = []\n\n      aroundEach(async (runTest, context) => {\n        logs.push('start ' + context.task.name)\n        await runTest()\n        logs.push('end ' + context.task.name)\n      })\n\n      describe('concurrent suite', { concurrent: true }, () => {\n        test('test 1', async () => {\n          await new Promise(r => setTimeout(r, 50))\n        })\n\n        test('test 2', async () => {\n          await new Promise(r => setTimeout(r, 30))\n        })\n\n        test('test 3', async () => {\n          await new Promise(r => setTimeout(r, 10))\n        })\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"concurrent.test.ts\": {\n        \"concurrent suite\": {\n          \"test 1\": \"passed\",\n          \"test 2\": \"passed\",\n          \"test 3\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('aroundEach with retry', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'retry.test.ts': `\n      import { aroundEach, test, expect } from 'vitest'\n\n      let attempt = 0\n\n      aroundEach(async (runTest) => {\n        attempt++\n        console.log('>> aroundEach attempt:', attempt)\n        await runTest()\n      })\n\n      test('retried test', { retry: 2 }, () => {\n        console.log('>> test attempt:', attempt)\n        if (attempt < 3) {\n          throw new Error('fail on purpose')\n        }\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundEach attempt: 1\n    >> test attempt: 1\n    >> aroundEach attempt: 2\n    >> test attempt: 2\n    >> aroundEach attempt: 3\n    >> test attempt: 3\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"retry.test.ts\": {\n        \"retried test\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach receives suite as third argument', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'suite-arg.test.ts': `\n      import { aroundEach, describe, test } from 'vitest'\n\n      describe('my suite', () => {\n        aroundEach(async (runTest, _context, suite) => {\n          console.log('>> suite name:', suite.name)\n          await runTest()\n        })\n\n        test('test 1', () => {\n          console.log('>> test')\n        })\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> suite name: my suite\n    >> test\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"suite-arg.test.ts\": {\n        \"my suite\": {\n          \"test 1\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('aroundEach skipped when test is skipped', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'skipped.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest, context) => {\n        console.log('>> aroundEach for:', context.task.name)\n        await runTest()\n      })\n\n      test('normal test', () => {\n        console.log('>> normal test')\n      })\n\n      test.skip('skipped test', () => {\n        console.log('>> skipped test')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundEach for: normal test\n    >> normal test\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"skipped.test.ts\": {\n        \"normal test\": \"passed\",\n        \"skipped test\": \"skipped\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach setup phase timeout', async () => {\n  const { stderr } = await runInlineTests({\n    'setup-timeout.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> setup start')\n        // Simulate slow setup\n        await new Promise(r => setTimeout(r, 5000))\n        console.log('>> setup end (should not reach)')\n        await runTest()\n        console.log('>> teardown')\n      }, 100) // 100ms timeout\n\n      test('test with slow setup', () => {\n        console.log('>> test (should not run)')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  setup-timeout.test.ts > test with slow setup\n    AroundHookSetupError: The setup phase of \"aroundEach\" hook timed out after 100ms.\n     ❯ setup-timeout.test.ts:4:7\n          2|       import { aroundEach, test } from 'vitest'\n          3|\n          4|       aroundEach(async (runTest) => {\n           |       ^\n          5|         console.log('>> setup start')\n          6|         // Simulate slow setup\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('aroundEach teardown phase timeout', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'teardown-timeout.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> setup')\n        await runTest()\n        console.log('>> teardown start')\n        // Simulate slow teardown\n        await new Promise(r => setTimeout(r, 5000))\n        console.log('>> teardown end (should not reach)')\n      }, 100) // 100ms timeout\n\n      test('test with slow teardown', () => {\n        console.log('>> test')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  teardown-timeout.test.ts > test with slow teardown\n    AroundHookTeardownError: The teardown phase of \"aroundEach\" hook timed out after 100ms.\n     ❯ teardown-timeout.test.ts:4:7\n          2|       import { aroundEach, test } from 'vitest'\n          3|\n          4|       aroundEach(async (runTest) => {\n           |       ^\n          5|         console.log('>> setup')\n          6|         await runTest()\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> setup\n    >> test\n    >> teardown start\"\n  `)\n})\n\ntest('aroundEach setup and teardown have independent timeouts', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'independent-timeouts.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        // Setup takes 80ms - under the 100ms timeout\n        console.log('>> setup start')\n        await new Promise(r => setTimeout(r, 80))\n        console.log('>> setup end')\n        await runTest()\n        // Teardown takes 80ms - under the 100ms timeout\n        console.log('>> teardown start')\n        await new Promise(r => setTimeout(r, 80))\n        console.log('>> teardown end')\n      }, 100) // 100ms timeout for each phase\n\n      test('test with slow but valid phases', () => {\n        console.log('>> test')\n      })\n    `,\n  })\n\n  // Both phases complete within their individual timeouts\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> setup start\n    >> setup end\n    >> test\n    >> teardown start\n    >> teardown end\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"independent-timeouts.test.ts\": {\n        \"test with slow but valid phases\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach default timeout uses hookTimeout config', async () => {\n  const { stderr } = await runInlineTests({\n    'default-timeout.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        // Setup takes longer than hookTimeout (10ms)\n        await new Promise(r => setTimeout(r, 200))\n        await runTest()\n      })\n\n      test('test', () => {})\n    `,\n  }, { hookTimeout: 10 })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  default-timeout.test.ts > test\n    AroundHookSetupError: The setup phase of \"aroundEach\" hook timed out after 10ms.\n     ❯ default-timeout.test.ts:4:7\n          2|       import { aroundEach, test } from 'vitest'\n          3|\n          4|       aroundEach(async (runTest) => {\n           |       ^\n          5|         // Setup takes longer than hookTimeout (10ms)\n          6|         await new Promise(r => setTimeout(r, 200))\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('multiple aroundEach hooks with different timeouts', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'multiple-timeouts.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      // Outer hook with 200ms timeout\n      aroundEach(async (runTest) => {\n        console.log('>> outer setup')\n        await runTest()\n        console.log('>> outer teardown')\n      }, 200)\n\n      // Inner hook with 50ms timeout - this should timeout during setup\n      aroundEach(async (runTest) => {\n        console.log('>> inner setup start')\n        await new Promise(r => setTimeout(r, 100)) // 100ms > 50ms timeout\n        console.log('>> inner setup end (should not reach)')\n        await runTest()\n        console.log('>> inner teardown')\n      }, 10)\n\n      test('test', () => {\n        console.log('>> test (should not run)')\n      })\n    `,\n  })\n\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer setup\n    >> inner setup start\n    >> outer teardown\"\n  `)\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  multiple-timeouts.test.ts > test\n    AroundHookSetupError: The setup phase of \"aroundEach\" hook timed out after 10ms.\n     ❯ multiple-timeouts.test.ts:12:7\n         10|\n         11|       // Inner hook with 50ms timeout - this should timeout during set…\n         12|       aroundEach(async (runTest) => {\n           |       ^\n         13|         console.log('>> inner setup start')\n         14|         await new Promise(r => setTimeout(r, 100)) // 100ms > 50ms tim…\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"multiple-timeouts.test.ts\": {\n        \"test\": [\n          \"The setup phase of \"aroundEach\" hook timed out after 10ms.\",\n        ],\n      },\n    }\n  `)\n})\n\ntest('multiple aroundEach hooks where inner teardown times out', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'multiple-teardown-timeout.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      // Outer hook with 200ms timeout\n      aroundEach(async (runTest) => {\n        console.log('>> outer setup')\n        await runTest()\n        console.log('>> outer teardown')\n      }, 200)\n\n      // Inner hook with 50ms timeout - this should timeout during teardown\n      aroundEach(async (runTest) => {\n        console.log('>> inner setup')\n        await runTest()\n        console.log('>> inner teardown start')\n        await new Promise(r => setTimeout(r, 100)) // 100ms > 50ms timeout\n        console.log('>> inner teardown end (should not reach)')\n      }, 10)\n\n      test('test', () => {\n        console.log('>> test')\n      })\n    `,\n  })\n\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer setup\n    >> inner setup\n    >> test\n    >> inner teardown start\n    >> outer teardown\"\n  `)\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  multiple-teardown-timeout.test.ts > test\n    AroundHookTeardownError: The teardown phase of \"aroundEach\" hook timed out after 10ms.\n     ❯ multiple-teardown-timeout.test.ts:12:7\n         10|\n         11|       // Inner hook with 50ms timeout - this should timeout during tea…\n         12|       aroundEach(async (runTest) => {\n           |       ^\n         13|         console.log('>> inner setup')\n         14|         await runTest()\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"multiple-teardown-timeout.test.ts\": {\n        \"test\": [\n          \"The teardown phase of \"aroundEach\" hook timed out after 10ms.\",\n        ],\n      },\n    }\n  `)\n})\n\ntest('aroundEach hook timeouts are independent of each other', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'independent-hook-timeouts.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      // First hook with short 50ms timeout - but completes quickly\n      aroundEach(async (runTest) => {\n        console.log('>> first hook setup')\n        await runTest()\n        console.log('>> first hook teardown')\n      }, 10)\n\n      // Second hook with 200ms timeout - takes 100ms which is longer than\n      // the first hook's 50ms timeout, but within its own 200ms timeout\n      aroundEach(async (runTest) => {\n        console.log('>> second hook setup start')\n        await new Promise(r => setTimeout(r, 100))\n        console.log('>> second hook setup end')\n        await runTest()\n        console.log('>> second hook teardown start')\n        await new Promise(r => setTimeout(r, 100))\n        console.log('>> second hook teardown end')\n      }, 200)\n\n      test('test', () => {\n        console.log('>> test')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> first hook setup\n    >> second hook setup start\n    >> second hook setup end\n    >> test\n    >> second hook teardown start\n    >> second hook teardown end\n    >> first hook teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"independent-hook-timeouts.test.ts\": {\n        \"test\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach teardown timeout works when runTest error is caught', async () => {\n  const { errorTree } = await runInlineTests({\n    'caught-inner-error-timeout.test.ts': `\n      import { aroundEach, describe, expect, test } from 'vitest'\n\n      describe('suite', () => {\n        aroundEach(async (runTest) => {\n          try {\n            await runTest()\n          }\n          catch {\n            // swallow inner hook failure, then run teardown work\n          }\n          await new Promise(resolve => setTimeout(resolve, 200))\n        }, 50)\n\n        aroundEach(async (runTest) => {\n          await runTest()\n          throw new Error('inner aroundEach teardown failure')\n        })\n\n        test('test', () => {\n          expect(1).toBe(1)\n        })\n      })\n    `,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"caught-inner-error-timeout.test.ts\": {\n        \"suite\": {\n          \"test\": [\n            \"inner aroundEach teardown failure\",\n            \"The teardown phase of \"aroundEach\" hook timed out after 50ms.\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('aroundEach with AsyncLocalStorage', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'async-local-storage.test.ts': `\n      import { AsyncLocalStorage } from 'node:async_hooks'\n      import { aroundEach, test, expect } from 'vitest'\n\n      const requestContext = new AsyncLocalStorage<{ requestId: number }>()\n      let requestIdx = 0\n\n      aroundEach(async (runTest) => {\n        const ctx = { requestId: ++requestIdx }\n        console.log('>> setting context:', ctx.requestId)\n        await requestContext.run(ctx, runTest)\n        console.log('>> context cleared')\n      })\n\n      test('first test gets requestId 1', () => {\n        const ctx = requestContext.getStore()\n        console.log('>> test got context:', ctx?.requestId)\n        expect(ctx).toBeDefined()\n        expect(ctx?.requestId).toBe(1)\n      })\n\n      test('second test gets fresh context with requestId 2', () => {\n        const ctx = requestContext.getStore()\n        console.log('>> test got context:', ctx?.requestId)\n        expect(ctx?.requestId).toBe(2)\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> setting context: 1\n    >> test got context: 1\n    >> context cleared\n    >> setting context: 2\n    >> test got context: 2\n    >> context cleared\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"async-local-storage.test.ts\": {\n        \"first test gets requestId 1\": \"passed\",\n        \"second test gets fresh context with requestId 2\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach with fixtures', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'fixtures.test.ts': `\n      import { test as base, aroundEach, expect } from 'vitest'\n\n      const test = base.extend<{ db: { query: (sql: string) => string } }>({\n        db: async ({}, use) => {\n          console.log('>> db fixture setup')\n          await use({\n            query: (sql: string) => \\`result of: \\${sql}\\`\n          })\n          console.log('>> db fixture teardown')\n        },\n        user: async ({}, use) => {\n          console.log('>> user fixture setup')\n          await use({ name: 'test-user' })\n          console.log('>> user fixture teardown')\n        },\n      })\n\n      test.aroundEach(async (runTest, { db }) => {\n        console.log('>> aroundEach setup, db available:', !!db)\n        const result = db.query('SELECT 1')\n        console.log('>> query result:', result)\n        await runTest()\n        console.log('>> aroundEach teardown')\n      })\n\n      test('test with fixture in aroundEach', ({ db, user }) => {\n        console.log('>> test running, db available:', !!db)\n        expect(db.query('SELECT 2')).toBe('result of: SELECT 2')\n        expect(user.name).toBe('test-user')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> db fixture setup\n    >> aroundEach setup, db available: true\n    >> query result: result of: SELECT 1\n    >> user fixture setup\n    >> test running, db available: true\n    >> user fixture teardown\n    >> aroundEach teardown\n    >> db fixture teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"fixtures.test.ts\": {\n        \"test with fixture in aroundEach\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach with AsyncLocalStorage fixture and value fixture', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'als-fixtures.test.ts': `\n      import { test as base, aroundEach, expect } from 'vitest'\n      import { AsyncLocalStorage } from 'node:async_hooks'\n\n      interface RequestContext {\n        requestId: number\n      }\n\n      let requestIdx = 0\n\n      const test = base.extend<{\n        requestContext: AsyncLocalStorage<RequestContext>\n        currentRequestId: number\n      }>({\n        requestContext: async ({}, use) => {\n          const als = new AsyncLocalStorage<RequestContext>()\n          await use(als)\n        },\n        currentRequestId: async ({ requestContext }, use) => {\n          const store = requestContext.getStore()\n          await use(store?.requestId)\n        }\n      })\n\n      aroundEach(async (runTest, { requestContext }) => {\n        const id = ++requestIdx\n        console.log('>> setting context:', id)\n        await requestContext.run({ requestId: id }, async () => {\n          await runTest()\n        })\n        console.log('>> context cleared')\n      })\n\n      test('first test gets requestId 1 via fixture', ({ currentRequestId }) => {\n        console.log('>> test got requestId:', currentRequestId)\n        expect(currentRequestId).toBe(1)\n      })\n\n      test('second test gets requestId 2 via fixture', ({ currentRequestId }) => {\n        console.log('>> test got requestId:', currentRequestId)\n        expect(currentRequestId).toBe(2)\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> setting context: 1\n    >> test got requestId: 1\n    >> context cleared\n    >> setting context: 2\n    >> test got requestId: 2\n    >> context cleared\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"als-fixtures.test.ts\": {\n        \"first test gets requestId 1 via fixture\": \"passed\",\n        \"second test gets requestId 2 via fixture\": \"passed\",\n      },\n    }\n  `)\n})\n\n// aroundAll tests\n\ntest('basic aroundAll wraps the suite', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': `\n      import { test, aroundAll } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> aroundAll setup')\n        await runSuite()\n        console.log('>> aroundAll teardown')\n      })\n\n      test('first test', () => {\n        console.log('>> first test running')\n      })\n\n      test('second test', () => {\n        console.log('>> second test running')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundAll setup\n    >> first test running\n    >> second test running\n    >> aroundAll teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"first test\": \"passed\",\n        \"second test\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('multiple aroundAll hooks are nested (first is outermost)', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'nested.test.ts': `\n      import { test, aroundAll } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> outer setup')\n        await runSuite()\n        console.log('>> outer teardown')\n      })\n\n      aroundAll(async (runSuite) => {\n        console.log('>> inner setup')\n        await runSuite()\n        console.log('>> inner teardown')\n      })\n\n      test('test', () => {\n        console.log('>> test running')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer setup\n    >> inner setup\n    >> test running\n    >> inner teardown\n    >> outer teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"nested.test.ts\": {\n        \"test\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundAll in nested suites wraps correctly', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'nested-suite.test.ts': `\n      import { test, describe, aroundAll } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> root aroundAll setup')\n        await runSuite()\n        console.log('>> root aroundAll teardown')\n      })\n\n      test('root test', () => {\n        console.log('>> root test running')\n      })\n\n      describe('nested suite', () => {\n        aroundAll(async (runSuite) => {\n          console.log('>> nested aroundAll setup')\n          await runSuite()\n          console.log('>> nested aroundAll teardown')\n        })\n\n        test('nested test', () => {\n          console.log('>> nested test running')\n        })\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> root aroundAll setup\n    >> root test running\n    >> nested aroundAll setup\n    >> nested test running\n    >> nested aroundAll teardown\n    >> root aroundAll teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"nested-suite.test.ts\": {\n        \"nested suite\": {\n          \"nested test\": \"passed\",\n        },\n        \"root test\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundAll throws error when runSuite is called multiple times', async () => {\n  const { stderr } = await runInlineTests({\n    'multiple-calls.test.ts': `\n      import { test, aroundAll } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        await runSuite()\n        await runSuite() // second call should throw\n      })\n\n      test('test', () => {\n        console.log('>> test running')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  multiple-calls.test.ts [ multiple-calls.test.ts ]\n    AroundHookMultipleCallsError: The \\`runSuite()\\` callback was called multiple times in the \\`aroundAll\\` hook. The callback can only be called once per hook.\n     ❯ multiple-calls.test.ts:6:15\n          4|       aroundAll(async (runSuite) => {\n          5|         await runSuite()\n          6|         await runSuite() // second call should throw\n           |               ^\n          7|       })\n          8|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('aroundAll throws error when runSuite is not called', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'no-run.test.ts': `\n      import { test, aroundAll } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> aroundAll setup but not calling runSuite')\n      })\n\n      test('test', () => {\n        console.log('>> test running')\n      })\n    `,\n  })\n\n  expect(stderr).toContain('runSuite()')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"no-run.test.ts\": {\n        \"__module_errors__\": [\n          \"The \\`runSuite()\\` callback was not called in the \\`aroundAll\\` hook. Make sure to call \\`runSuite()\\` to run the suite.\",\n        ],\n        \"test\": \"skipped\",\n      },\n    }\n  `)\n})\n\ntest('aroundAll cleanup runs even on test failure', async () => {\n  const { stdout, errorTree } = await runInlineTests({\n    'cleanup.test.ts': `\n      import { test, aroundAll, expect } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> aroundAll setup')\n        await runSuite()\n        console.log('>> aroundAll teardown')\n      })\n\n      test('failing test', () => {\n        console.log('>> failing test running')\n        expect(true).toBe(false)\n      })\n    `,\n  })\n\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundAll setup\n    >> failing test running\n    >> aroundAll teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"cleanup.test.ts\": {\n        \"failing test\": [\n          \"expected true to be false // Object.is equality\",\n        ],\n      },\n    }\n  `)\n})\n\ntest('aroundAll with beforeAll and afterAll', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'with-hooks.test.ts': `\n      import { test, beforeAll, afterAll, aroundAll } from 'vitest'\n\n      beforeAll(() => {\n        console.log('>> beforeAll')\n      })\n\n      aroundAll(async (runSuite) => {\n        console.log('>> aroundAll setup')\n        await runSuite()\n        console.log('>> aroundAll teardown')\n      })\n\n      afterAll(() => {\n        console.log('>> afterAll')\n      })\n\n      test('test', () => {\n        console.log('>> test running')\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundAll setup\n    >> beforeAll\n    >> test running\n    >> afterAll\n    >> aroundAll teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"with-hooks.test.ts\": {\n        \"test\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundAll setup phase timeout', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'timeout.test.ts': `\n      import { test, aroundAll } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> aroundAll setup starting')\n        await new Promise(resolve => setTimeout(resolve, 200))\n        console.log('>> aroundAll setup done')\n        await runSuite()\n      }, 10)\n\n      test('test', () => {\n        console.log('>> test running')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  timeout.test.ts [ timeout.test.ts ]\n    AroundHookSetupError: The setup phase of \"aroundAll\" hook timed out after 10ms.\n     ❯ timeout.test.ts:4:7\n          2|       import { test, aroundAll } from 'vitest'\n          3|\n          4|       aroundAll(async (runSuite) => {\n           |       ^\n          5|         console.log('>> aroundAll setup starting')\n          6|         await new Promise(resolve => setTimeout(resolve, 200))\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"timeout.test.ts\": {\n        \"__module_errors__\": [\n          \"The setup phase of \"aroundAll\" hook timed out after 10ms.\",\n        ],\n        \"test\": \"skipped\",\n      },\n    }\n  `)\n})\n\ntest('aroundAll teardown phase timeout', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'teardown-timeout.test.ts': `\n      import { test, aroundAll } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> aroundAll setup')\n        await runSuite()\n        console.log('>> aroundAll teardown starting')\n        await new Promise(resolve => setTimeout(resolve, 200))\n        console.log('>> aroundAll teardown done')\n      }, 10)\n\n      test('test', () => {\n        console.log('>> test running')\n      })\n    `,\n  })\n\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundAll setup\n    >> test running\n    >> aroundAll teardown starting\"\n  `)\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  teardown-timeout.test.ts [ teardown-timeout.test.ts ]\n    AroundHookTeardownError: The teardown phase of \"aroundAll\" hook timed out after 10ms.\n     ❯ teardown-timeout.test.ts:4:7\n          2|       import { test, aroundAll } from 'vitest'\n          3|\n          4|       aroundAll(async (runSuite) => {\n           |       ^\n          5|         console.log('>> aroundAll setup')\n          6|         await runSuite()\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"teardown-timeout.test.ts\": {\n        \"__module_errors__\": [\n          \"The teardown phase of \"aroundAll\" hook timed out after 10ms.\",\n        ],\n        \"test\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundAll receives suite as third argument', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'suite-arg.test.ts': `\n      import { test, describe, aroundAll } from 'vitest'\n\n      describe('my suite', () => {\n        aroundAll(async (runSuite, {}, suite) => {\n          console.log('>> suite name:', suite.name)\n          await runSuite()\n        })\n\n        test('test', () => {\n          console.log('>> test running')\n        })\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> suite name: my suite\n    >> test running\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"suite-arg.test.ts\": {\n        \"my suite\": {\n          \"test\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('aroundAll teardown timeout works when runSuite error is caught', async () => {\n  const { errorTree } = await runInlineTests({\n    'caught-inner-suite-error-timeout.test.ts': `\n      import { aroundAll, describe, expect, test } from 'vitest'\n\n      describe('suite', () => {\n        aroundAll(async (runSuite) => {\n          try {\n            await runSuite()\n          }\n          catch {\n            // swallow inner hook failure, then run teardown work\n          }\n          await new Promise(resolve => setTimeout(resolve, 200))\n        }, 50)\n\n        aroundAll(async (runSuite) => {\n          await runSuite()\n          throw new Error('inner aroundAll teardown failure')\n        })\n\n        test('test', () => {\n          expect(1).toBe(1)\n        })\n      })\n    `,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"caught-inner-suite-error-timeout.test.ts\": {\n        \"suite\": {\n          \"__suite_errors__\": [\n            \"inner aroundAll teardown failure\",\n            \"The teardown phase of \"aroundAll\" hook timed out after 50ms.\",\n          ],\n          \"test\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('aroundAll with server start/stop pattern', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'server.test.ts': `\n      import { test, aroundAll, expect } from 'vitest'\n\n      let serverPort: number | null = null\n\n      aroundAll(async (runSuite) => {\n        // Simulate server start\n        serverPort = 3000\n        console.log('>> server started on port', serverPort)\n        await runSuite()\n        // Simulate server stop\n        console.log('>> server stopping')\n        serverPort = null\n      })\n\n      test('first request', () => {\n        console.log('>> making request to port', serverPort)\n        expect(serverPort).toBe(3000)\n      })\n\n      test('second request', () => {\n        console.log('>> making request to port', serverPort)\n        expect(serverPort).toBe(3000)\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> server started on port 3000\n    >> making request to port 3000\n    >> making request to port 3000\n    >> server stopping\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"server.test.ts\": {\n        \"first request\": \"passed\",\n        \"second request\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('aroundAll with multiple suites and multiple hooks in same suite', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'multi-suite.test.ts': `\n      import { test, describe, aroundAll } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> root aroundAll 1 setup')\n        await runSuite()\n        console.log('>> root aroundAll 1 teardown')\n      })\n\n      aroundAll(async (runSuite) => {\n        console.log('>> root aroundAll 2 setup')\n        await runSuite()\n        console.log('>> root aroundAll 2 teardown')\n      })\n\n      test('root test', () => {\n        console.log('>> root test')\n      })\n\n      describe('suite A', () => {\n        aroundAll(async (runSuite) => {\n          console.log('>> suite A aroundAll 1 setup')\n          await runSuite()\n          console.log('>> suite A aroundAll 1 teardown')\n        })\n\n        aroundAll(async (runSuite) => {\n          console.log('>> suite A aroundAll 2 setup')\n          await runSuite()\n          console.log('>> suite A aroundAll 2 teardown')\n        })\n\n        test('test A1', () => {\n          console.log('>> test A1')\n        })\n\n        test('test A2', () => {\n          console.log('>> test A2')\n        })\n      })\n\n      describe('suite B', () => {\n        aroundAll(async (runSuite) => {\n          console.log('>> suite B aroundAll setup')\n          await runSuite()\n          console.log('>> suite B aroundAll teardown')\n        })\n\n        test('test B1', () => {\n          console.log('>> test B1')\n        })\n\n        describe('nested suite', () => {\n          aroundAll(async (runSuite) => {\n            console.log('>> nested aroundAll setup')\n            await runSuite()\n            console.log('>> nested aroundAll teardown')\n          })\n\n          test('nested test', () => {\n            console.log('>> nested test')\n          })\n        })\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> root aroundAll 1 setup\n    >> root aroundAll 2 setup\n    >> root test\n    >> suite A aroundAll 1 setup\n    >> suite A aroundAll 2 setup\n    >> test A1\n    >> test A2\n    >> suite A aroundAll 2 teardown\n    >> suite A aroundAll 1 teardown\n    >> suite B aroundAll setup\n    >> test B1\n    >> nested aroundAll setup\n    >> nested test\n    >> nested aroundAll teardown\n    >> suite B aroundAll teardown\n    >> root aroundAll 2 teardown\n    >> root aroundAll 1 teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"multi-suite.test.ts\": {\n        \"root test\": \"passed\",\n        \"suite A\": {\n          \"test A1\": \"passed\",\n          \"test A2\": \"passed\",\n        },\n        \"suite B\": {\n          \"nested suite\": {\n            \"nested test\": \"passed\",\n          },\n          \"test B1\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('aroundAll with module-level AsyncLocalStorage and test fixture', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'module-als.test.ts': `\n      import { test as base, aroundAll, expect } from 'vitest'\n      import { AsyncLocalStorage } from 'node:async_hooks'\n\n      interface RequestContext {\n        requestId: number\n      }\n\n      // Module-level AsyncLocalStorage shared between aroundAll and fixtures\n      const requestContext = new AsyncLocalStorage<RequestContext>()\n      let suiteRequestId = 0\n\n      const test = base.extend<{\n        currentRequestId: number\n      }>({\n        currentRequestId: async ({}, use) => {\n          const store = requestContext.getStore()\n          console.log('>> currentRequestId fixture reading store:', store?.requestId)\n          await use(store?.requestId)\n        }\n      })\n\n      aroundAll(async (runSuite) => {\n        suiteRequestId++\n        console.log('>> aroundAll setup, setting requestId:', suiteRequestId)\n        await requestContext.run({ requestId: suiteRequestId }, async () => {\n          await runSuite()\n        })\n        console.log('>> aroundAll teardown')\n      })\n\n      test('first test gets requestId from aroundAll context', ({ currentRequestId }) => {\n        console.log('>> first test, currentRequestId:', currentRequestId)\n        expect(currentRequestId).toBe(1)\n      })\n\n      test('second test gets same requestId from aroundAll context', ({ currentRequestId }) => {\n        console.log('>> second test, currentRequestId:', currentRequestId)\n        expect(currentRequestId).toBe(1)\n      })\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> aroundAll setup, setting requestId: 1\n    >> currentRequestId fixture reading store: 1\n    >> first test, currentRequestId: 1\n    >> currentRequestId fixture reading store: 1\n    >> second test, currentRequestId: 1\n    >> aroundAll teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"module-als.test.ts\": {\n        \"first test gets requestId from aroundAll context\": \"passed\",\n        \"second test gets same requestId from aroundAll context\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('tests are skipped when aroundAll setup fails', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'aroundAll-setup-error.test.ts': `\n      import { test, aroundAll } from 'vitest'\n\n      aroundAll(async () => {\n        throw new Error('aroundAll setup error')\n      })\n\n      test('test should be skipped', () => {\n        console.log('>> test should not run')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  aroundAll-setup-error.test.ts [ aroundAll-setup-error.test.ts ]\n    Error: aroundAll setup error\n     ❯ aroundAll-setup-error.test.ts:5:15\n          3|\n          4|       aroundAll(async () => {\n          5|         throw new Error('aroundAll setup error')\n           |               ^\n          6|       })\n          7|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n\n  // Test should be skipped because aroundAll setup failed\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"aroundAll-setup-error.test.ts\": {\n        \"__module_errors__\": [\n          \"aroundAll setup error\",\n        ],\n        \"test should be skipped\": \"skipped\",\n      },\n    }\n  `)\n})\n\ntest('aroundEach teardown timeout works when inner fails', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'caught-inner-error-timeout.test.ts': `\n      import { aroundEach, afterAll, describe, expect, test } from 'vitest'\n\n      let errorCaught = false\n\n      afterAll(() => {\n        expect(errorCaught).toBe(false)\n      })\n\n      describe('suite', () => {\n        aroundEach(async (runTest) => {\n          try {\n            await runTest()\n          }\n          catch {\n            errorCaught = true\n          }\n          // this should timeout\n          await new Promise(resolve => setTimeout(resolve, 200))\n        }, 50)\n\n        aroundEach(async (runTest) => {\n          await runTest()\n          throw new Error('inner aroundEach teardown failure')\n        })\n\n        test('test', () => {\n          expect(1).toBe(1)\n        })\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  caught-inner-error-timeout.test.ts > suite > test\n    Error: inner aroundEach teardown failure\n     ❯ caught-inner-error-timeout.test.ts:24:17\n         22|         aroundEach(async (runTest) => {\n         23|           await runTest()\n         24|           throw new Error('inner aroundEach teardown failure')\n           |                 ^\n         25|         })\n         26|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯\n\n     FAIL  caught-inner-error-timeout.test.ts > suite > test\n    AroundHookTeardownError: The teardown phase of \"aroundEach\" hook timed out after 50ms.\n     ❯ caught-inner-error-timeout.test.ts:11:9\n          9|\n         10|       describe('suite', () => {\n         11|         aroundEach(async (runTest) => {\n           |         ^\n         12|           try {\n         13|             await runTest()\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/2]⎯\n\n    \"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"caught-inner-error-timeout.test.ts\": {\n        \"suite\": {\n          \"test\": [\n            \"inner aroundEach teardown failure\",\n            \"The teardown phase of \"aroundEach\" hook timed out after 50ms.\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('aroundAll teardown timeout works when inner fails', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'caught-inner-error-timeout.test.ts': `\n      import { aroundAll, afterAll, describe, expect, test } from 'vitest'\n\n      let errorCaught = false\n\n      afterAll(() => {\n        expect(errorCaught).toBe(false)\n      })\n\n      describe('suite', () => {\n        aroundAll(async (runTest) => {\n          try {\n            await runTest()\n          }\n          catch {\n            errorCaught = true\n          }\n          // this should timeout\n          await new Promise(resolve => setTimeout(resolve, 200))\n        }, 50)\n\n        aroundAll(async (runTest) => {\n          await runTest()\n          throw new Error('inner aroundAll teardown failure')\n        })\n\n        test('test', () => {\n          expect(1).toBe(1)\n        })\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  caught-inner-error-timeout.test.ts > suite\n    Error: inner aroundAll teardown failure\n     ❯ caught-inner-error-timeout.test.ts:24:17\n         22|         aroundAll(async (runTest) => {\n         23|           await runTest()\n         24|           throw new Error('inner aroundAll teardown failure')\n           |                 ^\n         25|         })\n         26|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯\n\n     FAIL  caught-inner-error-timeout.test.ts > suite\n    AroundHookTeardownError: The teardown phase of \"aroundAll\" hook timed out after 50ms.\n     ❯ caught-inner-error-timeout.test.ts:11:9\n          9|\n         10|       describe('suite', () => {\n         11|         aroundAll(async (runTest) => {\n           |         ^\n         12|           try {\n         13|             await runTest()\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/2]⎯\n\n    \"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"caught-inner-error-timeout.test.ts\": {\n        \"suite\": {\n          \"__suite_errors__\": [\n            \"inner aroundAll teardown failure\",\n            \"The teardown phase of \"aroundAll\" hook timed out after 50ms.\",\n          ],\n          \"test\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('aroundEach aborts late runTest after setup timeout', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'late-run-test-after-timeout.test.ts': `\n      import { afterAll, aroundEach, test } from 'vitest'\n\n      afterAll(async () => {\n        console.log('>> afterAll 0ms')\n        await new Promise(r => setTimeout(r, 200))\n        console.log('>> afterAll 200ms')\n      })\n\n      aroundEach(async (runTest) => {\n        console.log(\">> outer aroundEach setup 0ms\")\n        await new Promise(r => setTimeout(r, 100))\n        // this is still executed after timeout error\n        console.log(\">> outer aroundEach setup 100ms\")\n        // but this shouldn't continue to inner aroundEach or test\n        await runTest()\n        console.log(\">> outer aroundEach teardown\")\n      }, 10)\n\n      aroundEach(async (runTest) => {\n        console.log('>> inner aroundEach setup')\n        await runTest()\n        console.log('>> inner aroundEach teardown')\n      })\n\n      test('basic', () => {\n        console.log('>> test')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  late-run-test-after-timeout.test.ts > basic\n    AroundHookSetupError: The setup phase of \"aroundEach\" hook timed out after 10ms.\n     ❯ late-run-test-after-timeout.test.ts:10:7\n          8|       })\n          9|\n         10|       aroundEach(async (runTest) => {\n           |       ^\n         11|         console.log(\">> outer aroundEach setup 0ms\")\n         12|         await new Promise(r => setTimeout(r, 100))\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer aroundEach setup 0ms\n    >> afterAll 0ms\n    >> outer aroundEach setup 100ms\n    >> afterAll 200ms\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"late-run-test-after-timeout.test.ts\": {\n        \"basic\": [\n          \"The setup phase of \"aroundEach\" hook timed out after 10ms.\",\n        ],\n      },\n    }\n  `)\n})\n\ntest('aroundAll aborts late runSuite after setup timeout', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'late-run-suite-after-timeout.test.ts': `\n      import { afterAll, aroundAll, describe, test } from 'vitest'\n\n      afterAll(async () => {\n        console.log('>> afterAll 0ms')\n        await new Promise(r => setTimeout(r, 200))\n        console.log('>> afterAll 200ms')\n      })\n\n      describe('timed out suite', () => {\n        aroundAll(async (runSuite) => {\n          console.log('>> outer aroundAll setup 0ms')\n          await new Promise(r => setTimeout(r, 100))\n          // this is still executed after timeout error\n          console.log('>> outer aroundAll setup 100ms')\n          // but this should not continue to inner aroundAll or tests\n          await runSuite()\n          console.log('>> outer aroundAll teardown')\n        }, 10)\n\n        aroundAll(async (runSuite) => {\n          console.log('>> inner aroundAll setup')\n          await runSuite()\n          console.log('>> inner aroundAll teardown')\n        })\n\n        test('basic', () => {\n          console.log('>> test')\n        })\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  late-run-suite-after-timeout.test.ts > timed out suite\n    AroundHookSetupError: The setup phase of \"aroundAll\" hook timed out after 10ms.\n     ❯ late-run-suite-after-timeout.test.ts:11:9\n          9|\n         10|       describe('timed out suite', () => {\n         11|         aroundAll(async (runSuite) => {\n           |         ^\n         12|           console.log('>> outer aroundAll setup 0ms')\n         13|           await new Promise(r => setTimeout(r, 100))\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer aroundAll setup 0ms\n    >> afterAll 0ms\n    >> outer aroundAll setup 100ms\n    >> afterAll 200ms\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"late-run-suite-after-timeout.test.ts\": {\n        \"timed out suite\": {\n          \"__suite_errors__\": [\n            \"The setup phase of \"aroundAll\" hook timed out after 10ms.\",\n          ],\n          \"basic\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('nested aroundEach setup error is not propagated to outer runTest catch', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'nested-around-each-setup-error.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> outer setup')\n        try {\n          await runTest()\n        }\n        catch (error) {\n          console.log('>> outer caught', String(error))\n        }\n        console.log('>> outer teardown')\n      })\n\n      aroundEach(async (_runTest) => {\n        console.log('>> inner setup')\n        throw new Error('inner aroundEach setup error')\n      })\n\n      test('repro', () => {\n        console.log('>> test body')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  nested-around-each-setup-error.test.ts > repro\n    Error: inner aroundEach setup error\n     ❯ nested-around-each-setup-error.test.ts:17:15\n         15|       aroundEach(async (_runTest) => {\n         16|         console.log('>> inner setup')\n         17|         throw new Error('inner aroundEach setup error')\n           |               ^\n         18|       })\n         19|\n     ❯ nested-around-each-setup-error.test.ts:7:11\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer setup\n    >> inner setup\n    >> outer teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"nested-around-each-setup-error.test.ts\": {\n        \"repro\": [\n          \"inner aroundEach setup error\",\n        ],\n      },\n    }\n  `)\n})\n\ntest('nested aroundEach teardown error is not propagated to outer runTest catch', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'nested-around-each-teardown-error.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> outer setup')\n        try {\n          await runTest()\n        }\n        catch (error) {\n          console.log('>> outer caught', String(error))\n        }\n        console.log('>> outer teardown')\n      })\n\n      aroundEach(async (runTest) => {\n        console.log('>> inner setup')\n        await runTest()\n        console.log('>> inner teardown')\n        throw new Error('inner aroundEach teardown error')\n      })\n\n      test('repro', () => {\n        console.log('>> test body')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  nested-around-each-teardown-error.test.ts > repro\n    Error: inner aroundEach teardown error\n     ❯ nested-around-each-teardown-error.test.ts:19:15\n         17|         await runTest()\n         18|         console.log('>> inner teardown')\n         19|         throw new Error('inner aroundEach teardown error')\n           |               ^\n         20|       })\n         21|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer setup\n    >> inner setup\n    >> test body\n    >> inner teardown\n    >> outer teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"nested-around-each-teardown-error.test.ts\": {\n        \"repro\": [\n          \"inner aroundEach teardown error\",\n        ],\n      },\n    }\n  `)\n})\n\ntest('nested aroundAll setup error is not propagated to outer runSuite catch', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'nested-around-all-setup-error.test.ts': `\n      import { aroundAll, test } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> outer setup')\n        try {\n          await runSuite()\n        }\n        catch (error) {\n          console.log('>> outer caught', String(error))\n        }\n        console.log('>> outer teardown')\n      })\n\n      aroundAll(async (_runSuite) => {\n        console.log('>> inner setup')\n        throw new Error('inner aroundAll setup error')\n      })\n\n      test('repro', () => {\n        console.log('>> test body')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  nested-around-all-setup-error.test.ts [ nested-around-all-setup-error.test.ts ]\n    Error: inner aroundAll setup error\n     ❯ nested-around-all-setup-error.test.ts:17:15\n         15|       aroundAll(async (_runSuite) => {\n         16|         console.log('>> inner setup')\n         17|         throw new Error('inner aroundAll setup error')\n           |               ^\n         18|       })\n         19|\n     ❯ nested-around-all-setup-error.test.ts:7:11\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer setup\n    >> inner setup\n    >> outer teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"nested-around-all-setup-error.test.ts\": {\n        \"__module_errors__\": [\n          \"inner aroundAll setup error\",\n        ],\n        \"repro\": \"skipped\",\n      },\n    }\n  `)\n})\n\ntest('nested aroundAll teardown error is not propagated to outer runSuite catch', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'nested-around-all-teardown-error.test.ts': `\n      import { aroundAll, test } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> outer setup')\n        try {\n          await runSuite()\n        }\n        catch (error) {\n          console.log('>> outer caught', String(error))\n        }\n        console.log('>> outer teardown')\n      })\n\n      aroundAll(async (runSuite) => {\n        console.log('>> inner setup')\n        await runSuite()\n        console.log('>> inner teardown')\n        throw new Error('inner aroundAll teardown error')\n      })\n\n      test('repro', () => {\n        console.log('>> test body')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  nested-around-all-teardown-error.test.ts [ nested-around-all-teardown-error.test.ts ]\n    Error: inner aroundAll teardown error\n     ❯ nested-around-all-teardown-error.test.ts:19:15\n         17|         await runSuite()\n         18|         console.log('>> inner teardown')\n         19|         throw new Error('inner aroundAll teardown error')\n           |               ^\n         20|       })\n         21|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer setup\n    >> inner setup\n    >> test body\n    >> inner teardown\n    >> outer teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"nested-around-all-teardown-error.test.ts\": {\n        \"__module_errors__\": [\n          \"inner aroundAll teardown error\",\n        ],\n        \"repro\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('three nested aroundEach teardown errors are all reported', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'triple-around-each-teardown-errors.test.ts': `\n      import { aroundEach, test } from 'vitest'\n\n      aroundEach(async (runTest) => {\n        console.log('>> outer setup')\n        await runTest()\n        console.log('>> outer teardown')\n        throw new Error('outer aroundEach teardown error')\n      })\n\n      aroundEach(async (runTest) => {\n        console.log('>> middle setup')\n        await runTest()\n        console.log('>> middle teardown')\n        throw new Error('middle aroundEach teardown error')\n      })\n\n      aroundEach(async (runTest) => {\n        console.log('>> inner setup')\n        await runTest()\n        console.log('>> inner teardown')\n        throw new Error('inner aroundEach teardown error')\n      })\n\n      test('repro', () => {\n        console.log('>> test body')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  triple-around-each-teardown-errors.test.ts > repro\n    Error: inner aroundEach teardown error\n     ❯ triple-around-each-teardown-errors.test.ts:22:15\n         20|         await runTest()\n         21|         console.log('>> inner teardown')\n         22|         throw new Error('inner aroundEach teardown error')\n           |               ^\n         23|       })\n         24|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯\n\n     FAIL  triple-around-each-teardown-errors.test.ts > repro\n    Error: middle aroundEach teardown error\n     ❯ triple-around-each-teardown-errors.test.ts:15:15\n         13|         await runTest()\n         14|         console.log('>> middle teardown')\n         15|         throw new Error('middle aroundEach teardown error')\n           |               ^\n         16|       })\n         17|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯\n\n     FAIL  triple-around-each-teardown-errors.test.ts > repro\n    Error: outer aroundEach teardown error\n     ❯ triple-around-each-teardown-errors.test.ts:8:15\n          6|         await runTest()\n          7|         console.log('>> outer teardown')\n          8|         throw new Error('outer aroundEach teardown error')\n           |               ^\n          9|       })\n         10|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer setup\n    >> middle setup\n    >> inner setup\n    >> test body\n    >> inner teardown\n    >> middle teardown\n    >> outer teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"triple-around-each-teardown-errors.test.ts\": {\n        \"repro\": [\n          \"inner aroundEach teardown error\",\n          \"middle aroundEach teardown error\",\n          \"outer aroundEach teardown error\",\n        ],\n      },\n    }\n  `)\n})\n\ntest('three nested aroundAll teardown errors are all reported', async () => {\n  const { stdout, stderr, errorTree } = await runInlineTests({\n    'triple-around-all-teardown-errors.test.ts': `\n      import { aroundAll, test } from 'vitest'\n\n      aroundAll(async (runSuite) => {\n        console.log('>> outer setup')\n        await runSuite()\n        console.log('>> outer teardown')\n        throw new Error('outer aroundAll teardown error')\n      })\n\n      aroundAll(async (runSuite) => {\n        console.log('>> middle setup')\n        await runSuite()\n        console.log('>> middle teardown')\n        throw new Error('middle aroundAll teardown error')\n      })\n\n      aroundAll(async (runSuite) => {\n        console.log('>> inner setup')\n        await runSuite()\n        console.log('>> inner teardown')\n        throw new Error('inner aroundAll teardown error')\n      })\n\n      test('repro', () => {\n        console.log('>> test body')\n      })\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  triple-around-all-teardown-errors.test.ts [ triple-around-all-teardown-errors.test.ts ]\n    Error: inner aroundAll teardown error\n     ❯ triple-around-all-teardown-errors.test.ts:22:15\n         20|         await runSuite()\n         21|         console.log('>> inner teardown')\n         22|         throw new Error('inner aroundAll teardown error')\n           |               ^\n         23|       })\n         24|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯\n\n     FAIL  triple-around-all-teardown-errors.test.ts [ triple-around-all-teardown-errors.test.ts ]\n    Error: middle aroundAll teardown error\n     ❯ triple-around-all-teardown-errors.test.ts:15:15\n         13|         await runSuite()\n         14|         console.log('>> middle teardown')\n         15|         throw new Error('middle aroundAll teardown error')\n           |               ^\n         16|       })\n         17|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯\n\n     FAIL  triple-around-all-teardown-errors.test.ts [ triple-around-all-teardown-errors.test.ts ]\n    Error: outer aroundAll teardown error\n     ❯ triple-around-all-teardown-errors.test.ts:8:15\n          6|         await runSuite()\n          7|         console.log('>> outer teardown')\n          8|         throw new Error('outer aroundAll teardown error')\n           |               ^\n          9|       })\n         10|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯\n\n    \"\n  `)\n  expect(extractLogs(stdout)).toMatchInlineSnapshot(`\n    \">> outer setup\n    >> middle setup\n    >> inner setup\n    >> test body\n    >> inner teardown\n    >> middle teardown\n    >> outer teardown\"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"triple-around-all-teardown-errors.test.ts\": {\n        \"__module_errors__\": [\n          \"inner aroundAll teardown error\",\n          \"middle aroundAll teardown error\",\n          \"outer aroundAll teardown error\",\n        ],\n        \"repro\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/artifacts.test.ts",
    "content": "import type { TestAnnotation, TestArtifact } from 'vitest'\nimport { format } from 'node:util'\nimport { playwright } from '@vitest/browser-playwright'\nimport { describe, expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\nconst test3Content = /* ts */`\nexport async function externalArtifactRecord(recordArtifact, task) {\n  await recordArtifact(task, { type: 'external' })\n}\n`\n\nconst artifactsTest = /* ts */`\nimport { test, describe, recordArtifact } from 'vitest'\nimport { externalArtifactRecord } from './test-3.js'\n\ntest('simple', async ({ task }) => {\n  await recordArtifact(task, { type: 'with-no-attachments' })\n  await recordArtifact(task, { type: 'with-one-attachment', attachments: [{ path: './test-3.js' }] })\n  await recordArtifact(task, { type: 'with-multiple-attachments', attachments: [{ path: './test-3.js' }, { path: './test-4.js' }] })\n  await externalArtifactRecord(recordArtifact, task)\n  await recordArtifact(task, { type: 'with-base64', attachments: [{ body: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' }]})\n  await recordArtifact(task, { type: 'with-bytes', attachments: [{ body: new Uint8Array(Array.from({ length: 256 }).map((_, i) => i)) }] })\n  await recordArtifact(task, { type: 'with-contentType', attachments: [{ body: '', contentType: 'text/plain' }] })\n})\n\ndescribe('suite', () => {\n  test('second', async ({ task }) => {\n    await recordArtifact(task, { type: 'with-external-link', attachments: [{ path: 'https://absolute-path.com' }] })\n  })\n})\n`\n\ndescribe('API', () => {\n  test.for([\n    { name: 'forks', pool: 'forks' },\n    { name: 'threads', pool: 'threads' },\n    {\n      name: 'browser',\n      browser: {\n        enabled: true,\n        provider: playwright(),\n        headless: true,\n        instances: [\n          { browser: 'chromium' as const },\n        ],\n      },\n    },\n  ])('artifacts are exposed correctly in $name', async (options) => {\n    const events: string[] = []\n    const annotations: Record<string, ReadonlyArray<TestAnnotation>> = {}\n    const artifacts: Record<string, ReadonlyArray<TestArtifact>> = {}\n\n    const { stderr } = await runInlineTests(\n      {\n        'basic.test.ts': artifactsTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      {\n        ...options,\n        includeTaskLocation: true,\n        reporters: [\n          'default',\n          {\n            onTestCaseAnnotate() {\n              events.push('[annotate]')\n            },\n            onTestCaseArtifactRecord(testCase, artifact) {\n              const path = artifact.attachments?.map(\n                attachment => attachment.path?.replace(testCase.project.config.root, '<root>').replace(/\\w+\\.js$/, '<hash>.js'),\n              )\n              events.push(`[artifact] ${testCase.name} ${artifact.type} path=${format(path)} contentType=${format(artifact.attachments?.map(attachment => attachment.contentType))} body=${format(artifact.attachments?.map(attachment => attachment.body))}`)\n            },\n            onTestCaseReady(testCase) {\n              events.push(`[ready] ${testCase.name}`)\n            },\n            onTestCaseResult(testCase) {\n              events.push(`[result] ${testCase.name}`)\n              annotations[testCase.name] = testCase.annotations()\n              artifacts[testCase.name] = testCase.artifacts().map((artifact) => {\n                if (Array.isArray(artifact.attachments)) {\n                  for (const attachment of artifact.attachments) {\n                    if (attachment?.path) {\n                      attachment.path = attachment.path.replace(\n                        testCase.project.config.root,\n                        '<root>',\n                      ).replace(/\\w+\\.js$/, '<hash>.js')\n                    }\n                  }\n                }\n                if (artifact.location) {\n                  artifact.location.file = artifact.location.file.replace(\n                    testCase.project.config.root,\n                    '<root>',\n                  )\n                }\n                return artifact\n              })\n            },\n          },\n        ],\n      },\n    )\n\n    expect(stderr).toBe('')\n    expect(events).toMatchInlineSnapshot(`\n      [\n        \"[ready] simple\",\n        \"[artifact] simple with-no-attachments path=undefined contentType=undefined body=undefined\",\n        \"[artifact] simple with-one-attachment path=[ '<root>/.vitest-attachments/<hash>.js' ] contentType=[ 'text/javascript' ] body=[ undefined ]\",\n        \"[artifact] simple with-multiple-attachments path=[\n        '<root>/.vitest-attachments/<hash>.js',\n        '<root>/.vitest-attachments/<hash>.js'\n      ] contentType=[ 'text/javascript', 'text/javascript' ] body=[ undefined, undefined ]\",\n        \"[artifact] simple external path=undefined contentType=undefined body=undefined\",\n        \"[artifact] simple with-base64 path=[ undefined ] contentType=[ undefined ] body=[ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ]\",\n        \"[artifact] simple with-bytes path=[ undefined ] contentType=[ undefined ] body=[\n        'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=='\n      ]\",\n        \"[artifact] simple with-contentType path=[ undefined ] contentType=[ 'text/plain' ] body=[ '' ]\",\n        \"[result] simple\",\n        \"[ready] second\",\n        \"[artifact] second with-external-link path=[ 'https://absolute-path.com' ] contentType=[ undefined ] body=[ undefined ]\",\n        \"[result] second\",\n      ]\n    `)\n\n    expect(artifacts).toMatchInlineSnapshot(`\n      {\n        \"second\": [\n          {\n            \"attachments\": [\n              {\n                \"path\": \"https://absolute-path.com\",\n              },\n            ],\n            \"location\": {\n              \"column\": 11,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 17,\n            },\n            \"type\": \"with-external-link\",\n          },\n        ],\n        \"simple\": [\n          {\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 6,\n            },\n            \"type\": \"with-no-attachments\",\n          },\n          {\n            \"attachments\": [\n              {\n                \"contentType\": \"text/javascript\",\n                \"path\": \"<root>/.vitest-attachments/<hash>.js\",\n              },\n            ],\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 7,\n            },\n            \"type\": \"with-one-attachment\",\n          },\n          {\n            \"attachments\": [\n              {\n                \"contentType\": \"text/javascript\",\n                \"path\": \"<root>/.vitest-attachments/<hash>.js\",\n              },\n              {\n                \"contentType\": \"text/javascript\",\n                \"path\": \"<root>/.vitest-attachments/<hash>.js\",\n              },\n            ],\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 8,\n            },\n            \"type\": \"with-multiple-attachments\",\n          },\n          {\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 9,\n            },\n            \"type\": \"external\",\n          },\n          {\n            \"attachments\": [\n              {\n                \"body\": \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",\n              },\n            ],\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 10,\n            },\n            \"type\": \"with-base64\",\n          },\n          {\n            \"attachments\": [\n              {\n                \"body\": \"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\",\n              },\n            ],\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 11,\n            },\n            \"type\": \"with-bytes\",\n          },\n          {\n            \"attachments\": [\n              {\n                \"body\": \"\",\n                \"contentType\": \"text/plain\",\n              },\n            ],\n            \"location\": {\n              \"column\": 9,\n              \"file\": \"<root>/basic.test.ts\",\n              \"line\": 12,\n            },\n            \"type\": \"with-contentType\",\n          },\n        ],\n      }\n    `)\n    expect(annotations).toMatchInlineSnapshot(`\n      {\n        \"second\": [],\n        \"simple\": [],\n      }\n    `)\n  })\n\n  test('can record artifacts even after the test finished running', async () => {\n    const { stderr } = await runInlineTests({\n      'basic.test.ts': `\n        import { recordArtifact } from 'vitest'\n        test('finished early', ({ task }) => {\n          setTimeout(() => {\n            recordArtifact(task, { type: 'invalid-artifact' })\n          }, 50)\n        })\n\n        test('long running test ', async () => {\n          await new Promise(r => setTimeout(() => r(), 100))\n        })\n      `,\n    }, { globals: true })\n    expect(stderr).toBe('')\n  })\n})\n\ndescribe('reporters', () => {\n  test('tap', async () => {\n    const { stdout } = await runInlineTests(\n      {\n        'basic.test.ts': artifactsTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: ['tap'] },\n    )\n\n    expect(stdout.replace(/[\\d.]+ms/g, '<time>')).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..1\n      ok 1 - basic.test.ts # time=<time> {\n          1..2\n          ok 1 - simple # time=<time>\n          ok 2 - suite # time=<time> {\n              1..1\n              ok 1 - second # time=<time>\n          }\n      }\n      \"\n    `)\n  })\n\n  test('tap-flat', async () => {\n    const { stdout } = await runInlineTests(\n      {\n        'basic.test.ts': artifactsTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: ['tap-flat'] },\n    )\n\n    expect(stdout.replace(/[\\d.]+ms/g, '<time>')).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..2\n      ok 1 - basic.test.ts > simple # time=<time>\n      ok 2 - basic.test.ts > suite > second # time=<time>\n      \"\n    `)\n  })\n\n  test('junit', async () => {\n    const { stdout } = await runInlineTests(\n      {\n        'basic.test.ts': artifactsTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: ['junit'] },\n    )\n\n    const result = stdout\n      .replace(/time=\"[\\d.]+\"/g, 'time=\"0\"')\n      .replace(/timestamp=\"[\\w\\-:.]+\"/g, 'timestamp=\"0\"')\n      .replace(/hostname=\"[\\w.\\-]+\"/g, 'hostname=\"CI\"')\n\n    expect(result).toMatchInlineSnapshot(`\n      \"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n      <testsuites name=\"vitest tests\" tests=\"2\" failures=\"0\" errors=\"0\" time=\"0\">\n          <testsuite name=\"basic.test.ts\" timestamp=\"0\" hostname=\"CI\" tests=\"2\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0\">\n              <testcase classname=\"basic.test.ts\" name=\"simple\" time=\"0\">\n              </testcase>\n              <testcase classname=\"basic.test.ts\" name=\"suite &gt; second\" time=\"0\">\n              </testcase>\n          </testsuite>\n      </testsuites>\n      \"\n    `)\n  })\n\n  test('github-actions', async () => {\n    const { stdout, ctx } = await runInlineTests(\n      {\n        'basic.test.ts': artifactsTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: ['github-actions'] },\n    )\n\n    expect(ctx).toBeDefined()\n\n    expect(stdout).toMatchInlineSnapshot(`\"\"`)\n  })\n\n  test('verbose non-tty', async () => {\n    const { stdout, ctx } = await runInlineTests(\n      {\n        'basic.test.ts': artifactsTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: [['verbose', { isTTY: false }]] },\n    )\n\n    expect(\n      stdout\n        .replace(/\\d+\\.\\d+\\.\\d+(-beta\\.\\d+)?/, '<version>')\n        .replace(ctx!.config.root, '<root>')\n        .replace(/\\d+:\\d+:\\d+/, '<time>')\n        .replace(/\\d+(?:\\.\\d+)?m?s/g, '<duration>'),\n    ).toMatchInlineSnapshot(`\n      \"\n       RUN  v<version> <root>\n\n       ✓ basic.test.ts > simple <duration>\n       ✓ basic.test.ts > suite > second <duration>\n\n       Test Files  1 passed (1)\n            Tests  2 passed (2)\n         Start at  <time>\n         Duration  <duration> (transform <duration>, setup <duration>, import <duration>, tests <duration>, environment <duration>)\n\n      \"\n    `)\n  })\n\n  test('default', async () => {\n    const { stdout, stderr, ctx } = await runInlineTests(\n      {\n        'basic.test.ts': artifactsTest,\n        'test-3.js': test3Content,\n        'test-4.js': '',\n      },\n      { reporters: [['default', { isTTY: false }]] },\n    )\n\n    expect(\n      stdout\n        .replace(/\\d+\\.\\d+\\.\\d+(-beta\\.\\d+)?/, '<version>')\n        .replace(ctx!.config.root, '<root>')\n        .replace(/\\d+:\\d+:\\d+/, '<time>')\n        .replace(/\\d+(?:\\.\\d+)?m?s/g, '<duration>'),\n    ).toMatchInlineSnapshot(`\n      \"\n       RUN  v<version> <root>\n\n       ✓ basic.test.ts (2 tests) <duration>\n\n       Test Files  1 passed (1)\n            Tests  2 passed (2)\n         Start at  <time>\n         Duration  <duration> (transform <duration>, setup <duration>, import <duration>, tests <duration>, environment <duration>)\n\n      \"\n    `)\n    expect(stderr).toMatchInlineSnapshot(`\"\"`)\n  })\n})\n"
  },
  {
    "path": "test/cli/test/assertion-helper.test.ts",
    "content": "import { resolve } from 'pathe'\nimport { expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nit('assertion helper', async () => {\n  const { stderr, errorTree } = await runVitest({\n    root: resolve(import.meta.dirname, '../fixtures/assertion-helper'),\n    printConsoleTrace: true,\n  })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"stderr | basic.test.ts > helper with logs\n    [test-myHelperWithLogs]\n     ❯ basic.test.ts:105:3\n\n\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 8 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts > sync\n    AssertionError: expected 'sync' to deeply equal 'x'\n\n    Expected: \"x\"\n    Received: \"sync\"\n\n     ❯ basic.test.ts:22:3\n         20|\n         21| test(\"sync\", () => {\n         22|   myEqual(\"sync\", \"x\");\n           |   ^\n         23| });\n         24|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/9]⎯\n\n     FAIL  basic.test.ts > async\n    AssertionError: expected 'async' to deeply equal 'x'\n\n    Expected: \"x\"\n    Received: \"async\"\n\n     ❯ basic.test.ts:26:3\n         24|\n         25| test(\"async\", async () => {\n         26|   await myEqualAsync(\"async\", \"x\");\n           |   ^\n         27| });\n         28|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/9]⎯\n\n     FAIL  basic.test.ts > soft\n    AssertionError: expected 'soft' to deeply equal 'x'\n\n    Expected: \"x\"\n    Received: \"soft\"\n\n     ❯ basic.test.ts:30:3\n         28|\n         29| test(\"soft\", () => {\n         30|   myEqualSoft(\"soft\", \"x\");\n           |   ^\n         31| });\n         32|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/9]⎯\n\n     FAIL  basic.test.ts > soft async\n    AssertionError: expected 'soft async' to deeply equal 'x'\n\n    Expected: \"x\"\n    Received: \"soft async\"\n\n     ❯ basic.test.ts:34:3\n         32|\n         33| test(\"soft async\", async () => {\n         34|   await myEqualSoftAsync(\"soft async\", \"x\");\n           |   ^\n         35| });\n         36|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/9]⎯\n\n     FAIL  basic.test.ts > nested\n    AssertionError: expected 'nested' to deeply equal 'x'\n\n    Expected: \"x\"\n    Received: \"nested\"\n\n     ❯ basic.test.ts:46:3\n         44|\n         45| test(\"nested\", () => {\n         46|   outerHelper(\"nested\", \"x\");\n           |   ^\n         47| });\n         48|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/9]⎯\n\n     FAIL  basic.test.ts > multiple soft\n    AssertionError: expected 'first' to deeply equal 'x'\n\n    Expected: \"x\"\n    Received: \"first\"\n\n     ❯ basic.test.ts:77:3\n         75| // Multiple soft errors in one test\n         76| test(\"multiple soft\", () => {\n         77|   myEqualSoft(\"first\", \"x\");\n           |   ^\n         78|   myEqualSoft(\"second\", \"y\");\n         79| });\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/9]⎯\n\n     FAIL  basic.test.ts > multiple soft\n    AssertionError: expected 'second' to deeply equal 'y'\n\n    Expected: \"y\"\n    Received: \"second\"\n\n     ❯ basic.test.ts:78:3\n         76| test(\"multiple soft\", () => {\n         77|   myEqualSoft(\"first\", \"x\");\n         78|   myEqualSoft(\"second\", \"y\");\n           |   ^\n         79| });\n         80|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/9]⎯\n\n     FAIL  basic.test.ts > custom error\n    Error: custom error from helper\n     ❯ basic.test.ts:87:3\n         85|\n         86| test(\"custom error\", () => {\n         87|   throwCustom();\n           |   ^\n         88| });\n         89|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/9]⎯\n\n     FAIL  basic.test.ts > non-helper wrapper\n    AssertionError: expected 'wrapper' to deeply equal 'x'\n\n    Expected: \"x\"\n    Received: \"wrapper\"\n\n     ❯ assertEqualValues basic.test.ts:92:3\n         90| // non-helper wrapper calling a helper: stack should include the wrapp…\n         91| function assertEqualValues(a: any, b: any) {\n         92|   myEqual(a, b);\n           |   ^\n         93| }\n         94|\n     ❯ basic.test.ts:96:3\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/9]⎯\n\n    \"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"async\": [\n          \"expected 'async' to deeply equal 'x'\",\n        ],\n        \"custom error\": [\n          \"custom error from helper\",\n        ],\n        \"helper with logs\": \"passed\",\n        \"multiple soft\": [\n          \"expected 'first' to deeply equal 'x'\",\n          \"expected 'second' to deeply equal 'y'\",\n        ],\n        \"nested\": [\n          \"expected 'nested' to deeply equal 'x'\",\n        ],\n        \"non-helper wrapper\": [\n          \"expected 'wrapper' to deeply equal 'x'\",\n        ],\n        \"pass async\": \"passed\",\n        \"pass sync\": \"passed\",\n        \"return async\": \"passed\",\n        \"return sync\": \"passed\",\n        \"soft\": [\n          \"expected 'soft' to deeply equal 'x'\",\n        ],\n        \"soft async\": [\n          \"expected 'soft async' to deeply equal 'x'\",\n        ],\n        \"sync\": [\n          \"expected 'sync' to deeply equal 'x'\",\n        ],\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/bail-race.test.ts",
    "content": "import { resolve } from 'pathe'\nimport { expect, onTestFinished, test } from 'vitest'\nimport { createVitest } from 'vitest/node'\nimport { StableTestFileOrderSorter } from '../../test-utils'\n\ntest('cancels previous run before starting new one', async () => {\n  const errors: unknown[] = []\n\n  const vitest = await createVitest('test', {\n    maxWorkers: 1,\n    maxConcurrency: 1,\n    watch: false,\n    bail: 1,\n    root: resolve(import.meta.dirname, '../fixtures/bail-race'),\n    sequence: { sequencer: StableTestFileOrderSorter },\n    reporters: [{\n      onTestRunEnd(_, unhandledErrors) {\n        if (unhandledErrors.length) {\n          errors.push(...unhandledErrors)\n        }\n      },\n    }],\n  })\n  onTestFinished(() => vitest.close())\n\n  for (let i = 0; i <= 4; i++) {\n    await vitest.start()\n  }\n\n  // No \"Error: [vitest-pool]: Cannot run tasks while pool is cancelling\" errors should show up\n  expect(errors).toHaveLength(0)\n})\n"
  },
  {
    "path": "test/cli/test/benchmarking.test.ts",
    "content": "import type { createBenchmarkJsonReport } from 'vitest/src/node/reporters/benchmark/json-formatter.js'\nimport fs from 'node:fs'\nimport * as pathe from 'pathe'\nimport { assert, expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nit('sequential', async () => {\n  const root = pathe.join(import.meta.dirname, '../fixtures/benchmarking/sequential')\n  await runVitest({ root }, [], { mode: 'benchmark' })\n  const testLog = await fs.promises.readFile(pathe.join(root, 'test.log'), 'utf-8')\n  expect(testLog).toMatchSnapshot()\n})\n\nit('summary', async () => {\n  const root = pathe.join(import.meta.dirname, '../fixtures/benchmarking/reporter')\n  const result = await runVitest({ root }, ['summary.bench.ts'], { mode: 'benchmark' })\n  expect(result.stderr).toBe('')\n  expect(result.stdout).not.toContain('NaNx')\n  expect(result.stdout.split('BENCH  Summary')[1].replaceAll(/[0-9.]+x/g, '(?)')).toMatchSnapshot()\n})\n\nit('non-tty', async () => {\n  const root = pathe.join(import.meta.dirname, '../fixtures/benchmarking/basic')\n  const result = await runVitest({ root }, ['base.bench.ts'], { mode: 'benchmark' })\n  const lines = result.stdout.split('\\n').slice(4).slice(0, 11)\n  const expected = `\\\n ✓ base.bench.ts > sort\n     name\n   · normal\n   · reverse\n\n ✓ base.bench.ts > timeout\n     name\n   · timeout100\n   · timeout75\n   · timeout50\n   · timeout25\n`\n\n  for (const [index, line] of expected.trim().split('\\n').entries()) {\n    expect(lines[index]).toMatch(line)\n  }\n})\n\nit.for([true, false])('includeSamples %s', async (includeSamples) => {\n  const result = await runVitest(\n    {\n      root: pathe.join(import.meta.dirname, '../fixtures/benchmarking/reporter'),\n      benchmark: { includeSamples },\n    },\n    ['summary.bench.ts'],\n    { mode: 'benchmark' },\n  )\n  assert(result.ctx)\n  const allSamples = [...result.ctx.state.idMap.values()]\n    .filter(t => t.meta.benchmark)\n    .map(t => t.result?.benchmark?.samples)\n  if (includeSamples) {\n    expect(allSamples[0]).not.toEqual([])\n  }\n  else {\n    expect(allSamples[0]).toEqual([])\n  }\n})\n\nit('compare', async () => {\n  await fs.promises.rm('./fixtures/benchmarking/compare/bench.json', { force: true })\n\n  // --outputJson\n  {\n    const result = await runVitest({\n      root: './fixtures/benchmarking/compare',\n      outputJson: './bench.json',\n      reporters: ['default'],\n    }, [], { mode: 'benchmark' })\n    expect(result.exitCode).toBe(0)\n    expect(fs.existsSync('./fixtures/benchmarking/compare/bench.json')).toBe(true)\n  }\n\n  // --compare\n  {\n    const result = await runVitest({\n      root: './fixtures/benchmarking/compare',\n      compare: './bench.json',\n      reporters: ['default'],\n    }, [], { mode: 'benchmark' })\n    expect(result.exitCode).toBe(0)\n    const lines = result.stdout.split('\\n').slice(4).slice(0, 6)\n    const expected = `\n✓ basic.bench.ts > suite\n    name\n  · sleep10\n             (baseline)\n  · sleep100\n             (baseline)\n  `\n\n    for (const [index, line] of expected.trim().split('\\n').entries()) {\n      expect(lines[index]).toMatch(line.trim())\n    }\n  }\n})\n\nit('basic', { timeout: 60_000 }, async () => {\n  const root = pathe.join(import.meta.dirname, '../fixtures/benchmarking/basic')\n  const benchFile = pathe.join(root, 'bench.json')\n  fs.rmSync(benchFile, { force: true })\n\n  const result = await runVitest({\n    root,\n    allowOnly: true,\n    outputJson: 'bench.json',\n\n    // Verify that type testing cannot be used with benchmark\n    typecheck: { enabled: true },\n  }, [], { mode: 'benchmark' })\n  expect(result.stderr).toBe('')\n  expect(result.exitCode).toBe(0)\n\n  const benchResult = await fs.promises.readFile(benchFile, 'utf-8')\n  const resultJson: ReturnType<typeof createBenchmarkJsonReport> = JSON.parse(benchResult)\n  const names = resultJson.files.map(f => f.groups.map(g => [g.fullName, g.benchmarks.map(b => b.name)]))\n  expect(names).toMatchInlineSnapshot(`\n    [\n      [\n        [\n          \"base.bench.ts > sort\",\n          [\n            \"normal\",\n            \"reverse\",\n          ],\n        ],\n        [\n          \"base.bench.ts > timeout\",\n          [\n            \"timeout100\",\n            \"timeout75\",\n            \"timeout50\",\n            \"timeout25\",\n          ],\n        ],\n      ],\n      [],\n      [\n        [\n          \"only.bench.ts\",\n          [\n            \"visited\",\n            \"visited2\",\n          ],\n        ],\n        [\n          \"only.bench.ts > a0\",\n          [\n            \"0\",\n          ],\n        ],\n        [\n          \"only.bench.ts > a1 > b1 > c1\",\n          [\n            \"1\",\n          ],\n        ],\n        [\n          \"only.bench.ts > a2\",\n          [\n            \"2\",\n          ],\n        ],\n        [\n          \"only.bench.ts > a3 > b3\",\n          [\n            \"3\",\n          ],\n        ],\n        [\n          \"only.bench.ts > a4 > b4\",\n          [\n            \"4\",\n          ],\n        ],\n      ],\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/browser-multiple.test.ts",
    "content": "import type { Vitest } from 'vitest/node'\nimport { resolve } from 'pathe'\n\nimport { expect, it, onTestFinished, vi } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nit('automatically assigns the port', async () => {\n  const root = resolve(import.meta.dirname, '../fixtures/browser-multiple')\n  const spy = vi.spyOn(console, 'log')\n  onTestFinished(() => spy.mockRestore())\n  let ctx: Vitest\n  let urls: (string | undefined)[] = []\n  const { stderr } = await runVitest({\n    root,\n    dir: root,\n    watch: false,\n    reporters: [\n      {\n        onInit(ctx_) {\n          ctx = ctx_\n        },\n        onTestRunEnd() {\n          urls = ctx.projects.map(p => p.browser?.vite.resolvedUrls?.local[0])\n        },\n      },\n    ],\n  })\n\n  expect(spy).not.toHaveBeenCalled()\n  expect(stderr).not.toContain('is in use, trying another one...')\n  expect(urls).toContain('http://localhost:63315/')\n  expect(urls).toContain('http://localhost:63316/')\n})\n"
  },
  {
    "path": "test/cli/test/caching.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest, useFS } from '../../test-utils'\n\ntest('if file has import.meta.glob, it\\'s not cached', async () => {\n  const { createFile } = useFS('./fixtures/caching/import-meta-glob/generated', {\n    1: '1',\n    2: '2',\n  }, false)\n\n  const { errorTree: errorTree1 } = await runVitest({\n    root: './fixtures/caching/import-meta-glob',\n    provide: {\n      generated: ['./generated/1', './generated/2'],\n    },\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/.vitest-fs-cache',\n    },\n  })\n\n  expect(errorTree1()).toMatchInlineSnapshot(`\n    {\n      \"glob.test.js\": {\n        \"replaced variable is the same\": \"passed\",\n      },\n    }\n  `)\n\n  createFile('3', '3')\n\n  const { errorTree: errorTree2 } = await runVitest({\n    root: './fixtures/caching/import-meta-glob',\n    provide: {\n      generated: [\n        './generated/1',\n        './generated/2',\n        './generated/3',\n      ],\n    },\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/.vitest-fs-cache',\n    },\n  })\n\n  expect(errorTree2()).toMatchInlineSnapshot(`\n    {\n      \"glob.test.js\": {\n        \"replaced variable is the same\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('if no cache key generator is defined, the hash is invalid', async () => {\n  process.env.REPLACED = 'value1'\n\n  const { errorTree: errorTree1 } = await runVitest({\n    root: './fixtures/caching/dynamic-cache-key',\n    config: './vitest.config.fails.js',\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/.vitest-fs-cache',\n    },\n    reporters: [\n      {\n        async onInit(vitest) {\n          // make sure cache is empty\n          await vitest.experimental_clearCache()\n        },\n      },\n    ],\n  })\n\n  expect(errorTree1()).toMatchInlineSnapshot(`\n    {\n      \"replaced.test.js\": {\n        \"replaced variable is the same\": \"passed\",\n      },\n    }\n  `)\n\n  process.env.REPLACED = 'value2'\n\n  const { errorTree: errorTree2 } = await runVitest({\n    root: './fixtures/caching/dynamic-cache-key',\n    config: './vitest.config.fails.js',\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/.vitest-fs-cache',\n    },\n  })\n\n  expect(errorTree2()).toMatchInlineSnapshot(`\n    {\n      \"replaced.test.js\": {\n        \"replaced variable is the same\": [\n          \"expected 'value1' to be 'value2' // Object.is equality\",\n        ],\n      },\n    }\n  `)\n})\n\ntest('if cache key generator is defined, the hash is valid', async () => {\n  process.env.REPLACED = 'value1'\n\n  const { errorTree: errorTree1 } = await runVitest({\n    root: './fixtures/caching/dynamic-cache-key',\n    config: './vitest.config.passes.js',\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/.vitest-fs-cache',\n    },\n    reporters: [\n      {\n        async onInit(vitest) {\n          // make sure cache is empty\n          await vitest.experimental_clearCache()\n        },\n      },\n    ],\n  })\n\n  expect(errorTree1()).toMatchInlineSnapshot(`\n    {\n      \"replaced.test.js\": {\n        \"replaced variable is the same\": \"passed\",\n      },\n    }\n  `)\n\n  process.env.REPLACED = 'value2'\n\n  const { errorTree: errorTree2 } = await runVitest({\n    root: './fixtures/caching/dynamic-cache-key',\n    config: './vitest.config.passes.js',\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/.vitest-fs-cache',\n    },\n  })\n\n  expect(errorTree2()).toMatchInlineSnapshot(`\n    {\n      \"replaced.test.js\": {\n        \"replaced variable is the same\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('if cache key generator bails out, the file is not cached', async () => {\n  process.env.REPLACED = 'value1'\n\n  const { errorTree: errorTree1 } = await runVitest({\n    root: './fixtures/caching/dynamic-cache-key',\n    config: './vitest.config.bails.js',\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/.vitest-fs-cache',\n    },\n    reporters: [\n      {\n        async onInit(vitest) {\n          // make sure cache is empty\n          await vitest.experimental_clearCache()\n        },\n      },\n    ],\n  })\n\n  expect(errorTree1()).toMatchInlineSnapshot(`\n    {\n      \"replaced.test.js\": {\n        \"replaced variable is the same\": \"passed\",\n      },\n    }\n  `)\n\n  process.env.REPLACED = 'value2'\n\n  const { errorTree: errorTree2 } = await runVitest({\n    root: './fixtures/caching/dynamic-cache-key',\n    config: './vitest.config.bails.js',\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/.vitest-fs-cache',\n    },\n  })\n\n  expect(errorTree2()).toMatchInlineSnapshot(`\n    {\n      \"replaced.test.js\": {\n        \"replaced variable is the same\": \"passed\",\n      },\n    }\n  `)\n})\n\ndeclare module 'vitest' {\n  export interface ProvidedContext {\n    generated: string[]\n  }\n}\n"
  },
  {
    "path": "test/cli/test/cancel-run.test.ts",
    "content": "import type { TestModule } from 'vitest/node'\nimport { Readable, Writable } from 'node:stream'\nimport { stripVTControlCharacters } from 'node:util'\nimport { createDefer } from '@vitest/utils/helpers'\nimport { expect, onTestFinished, test, vi } from 'vitest'\nimport { createVitest, registerConsoleShortcuts } from 'vitest/node'\n\nconst CTRL_C = '\\x03'\n\ntest('can force cancel a run via CLI', async () => {\n  const onExit = vi.fn<never>()\n  const exit = process.exit\n  onTestFinished(() => {\n    process.exit = exit\n  })\n  process.exit = onExit\n\n  const onTestModuleStart = createDefer<void>()\n  const vitest = await createVitest('test', {\n    root: 'fixtures/cancel-run',\n    include: ['blocked-thread.test.ts'],\n    reporters: [{ onTestModuleStart: () => onTestModuleStart.resolve() }],\n  })\n  onTestFinished(() => vitest.close())\n\n  const stdin = new Readable({ read: () => '' }) as NodeJS.ReadStream\n  stdin.isTTY = true\n  stdin.setRawMode = () => stdin\n  registerConsoleShortcuts(vitest, stdin, new Writable())\n\n  const onLog = vi.spyOn(vitest.logger, 'log').mockImplementation(() => {})\n  const promise = vitest.start()\n\n  await onTestModuleStart\n\n  // First CTRL+c should log warning about graceful exit\n  stdin.emit('data', CTRL_C)\n\n  // Let the test case start running\n  await new Promise(resolve => setTimeout(resolve, 100))\n\n  const logs = onLog.mock.calls.map(log => stripVTControlCharacters(log[0] || '').trim())\n  expect(logs).toContain('Cancelling test run. Press CTRL+c again to exit forcefully.')\n\n  // Second CTRL+c should stop run\n  stdin.emit('data', CTRL_C)\n  await promise\n\n  expect(onExit).toHaveBeenCalled()\n})\n\ntest('cancelling test run stops test execution immediately', async () => {\n  const onTestRunEnd = createDefer<readonly TestModule[]>()\n  const onSlowTestRunning = createDefer<void>()\n  const onTestCaseHooks: string[] = []\n\n  const vitest = await createVitest('test', {\n    root: 'fixtures/cancel-run',\n    include: ['blocked-test-cases.test.ts'],\n    reporters: [{\n      onTestCaseReady(testCase) {\n        onTestCaseHooks.push(`onTestCaseReady ${testCase.name}`)\n      },\n      onTestCaseResult(testCase) {\n        onTestCaseHooks.push(`onTestCaseResult ${testCase.name}`)\n        onTestCaseHooks.push('') // padding\n      },\n      onTestCaseAnnotate: (_, annotation) => {\n        if (annotation.message === 'Running long test, do the cancelling now!') {\n          onSlowTestRunning.resolve()\n        }\n      },\n      onTestRunEnd(testModules) {\n        onTestRunEnd.resolve(testModules)\n      },\n    }],\n  })\n  onTestFinished(() => vitest.close())\n\n  const promise = vitest.start()\n\n  await onSlowTestRunning\n  await vitest.cancelCurrentRun('keyboard-input')\n\n  const testModules = await onTestRunEnd\n  await Promise.all([vitest.close(), promise])\n\n  expect(testModules).toHaveLength(1)\n\n  const tests = Array.from(testModules[0].children.allTests()).map(test => ({\n    name: test.name,\n    status: test.result().state,\n    note: (test.result() as any).note,\n    afterEachRun: (test.meta() as any).afterEachDone === true,\n  }))\n\n  expect(tests).toMatchInlineSnapshot(`\n    [\n      {\n        \"afterEachRun\": true,\n        \"name\": \"one\",\n        \"note\": undefined,\n        \"status\": \"passed\",\n      },\n      {\n        \"afterEachRun\": true,\n        \"name\": \"two\",\n        \"note\": undefined,\n        \"status\": \"passed\",\n      },\n      {\n        \"afterEachRun\": true,\n        \"name\": \"this test starts and gets cancelled, its after each should be called\",\n        \"note\": \"The test run was aborted by the user.\",\n        \"status\": \"skipped\",\n      },\n      {\n        \"afterEachRun\": false,\n        \"name\": \"third, no after each expected\",\n        \"note\": \"The test run was aborted by the user.\",\n        \"status\": \"skipped\",\n      },\n      {\n        \"afterEachRun\": false,\n        \"name\": \"fourth, no after each expected\",\n        \"note\": \"The test run was aborted by the user.\",\n        \"status\": \"skipped\",\n      },\n      {\n        \"afterEachRun\": false,\n        \"name\": \"fifth, no after each expected\",\n        \"note\": \"The test run was aborted by the user.\",\n        \"status\": \"skipped\",\n      },\n    ]\n  `)\n\n  expect(onTestCaseHooks).toMatchInlineSnapshot(`\n    [\n      \"onTestCaseReady one\",\n      \"onTestCaseResult one\",\n      \"\",\n      \"onTestCaseReady two\",\n      \"onTestCaseResult two\",\n      \"\",\n      \"onTestCaseReady this test starts and gets cancelled, its after each should be called\",\n      \"onTestCaseResult this test starts and gets cancelled, its after each should be called\",\n      \"\",\n      \"onTestCaseReady third, no after each expected\",\n      \"onTestCaseResult third, no after each expected\",\n      \"\",\n      \"onTestCaseReady fourth, no after each expected\",\n      \"onTestCaseResult fourth, no after each expected\",\n      \"\",\n      \"onTestCaseReady fifth, no after each expected\",\n      \"onTestCaseResult fifth, no after each expected\",\n      \"\",\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/concurrent.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\n// 3 tests depend on each other,\n// so they will deadlock when maxConcurrency < 3\n//\n//  [a]  [b]  [c]\n//   * ->\n//        * ->\n//          <- *\n//     <------\n\nconst deadlockSource = `\nimport { describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\ndescribe.concurrent('wrapper', () => {\n  const defers = [\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n  ]\n\n  test('a', async () => {\n    expect(1).toBe(1)\n    defers[0].resolve()\n    await defers[2]\n  })\n\n  test('b', async () => {\n    expect(1).toBe(1)\n    await defers[0]\n    defers[1].resolve()\n    await defers[2]\n  })\n\n  test('c', async () => {\n    expect(1).toBe(1)\n    await defers[1]\n    defers[2].resolve()\n  })\n})\n`\n\ntest('deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': deadlockSource,\n  }, {\n    maxConcurrency: 2,\n    testTimeout: 500,\n  })\n\n  // \"a\" and \"b\" fill both concurrency slots and wait for `defers[2]`.\n  // \"c\" is queued until one slot is released by timeout, then it starts,\n  // observes `defers[1]` already resolved by \"b\", resolves `defers[2]`, and passes.\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"a\": [\n            \"Test timed out in 500ms.\n    If this is a long-running test, pass a timeout value as the last argument or configure it globally with \"testTimeout\".\",\n          ],\n          \"b\": [\n            \"Test timed out in 500ms.\n    If this is a long-running test, pass a timeout value as the last argument or configure it globally with \"testTimeout\".\",\n          ],\n          \"c\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': deadlockSource,\n  }, {\n    maxConcurrency: 3,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"a\": \"passed\",\n          \"b\": \"passed\",\n          \"c\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst suiteDeadlockSource = `\nimport { describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\ndescribe.concurrent('wrapper', () => {\n  const defers = [\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n  ]\n\n  describe('1st suite', () => {\n    test('a', async () => {\n      expect(1).toBe(1)\n      defers[0].resolve()\n      await defers[2]\n    })\n\n    test('b', async () => {\n      expect(1).toBe(1)\n      await defers[0]\n      defers[1].resolve()\n      await defers[2]\n    })\n  })\n\n  describe('2nd suite', () => {\n    test('c', async () => {\n      expect(1).toBe(1)\n      await defers[1]\n      defers[2].resolve()\n    })\n  })\n})\n`\n\ntest('suite deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': suiteDeadlockSource,\n  }, {\n    maxConcurrency: 2,\n    testTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"1st suite\": {\n            \"a\": [\n              \"Test timed out in 500ms.\n    If this is a long-running test, pass a timeout value as the last argument or configure it globally with \"testTimeout\".\",\n            ],\n            \"b\": [\n              \"Test timed out in 500ms.\n    If this is a long-running test, pass a timeout value as the last argument or configure it globally with \"testTimeout\".\",\n            ],\n          },\n          \"2nd suite\": {\n            \"c\": \"passed\",\n          },\n        },\n      },\n    }\n  `)\n})\n\ntest('suite passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': suiteDeadlockSource,\n  }, {\n    maxConcurrency: 3,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"1st suite\": {\n            \"a\": \"passed\",\n            \"b\": \"passed\",\n          },\n          \"2nd suite\": {\n            \"c\": \"passed\",\n          },\n        },\n      },\n    }\n  `)\n})\n\nconst beforeAllNeighboringSuitesSource = `\nimport { beforeAll, describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\nconst defers = [\n  createDefer<void>(),\n  createDefer<void>(),\n]\n\ndescribe.concurrent('s1', () => {\n  beforeAll(async () => {\n    defers[0].resolve()\n    await defers[1]\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n})\n\ndescribe.concurrent('s2', () => {\n  beforeAll(async () => {\n    await defers[0]\n    defers[1].resolve()\n  })\n\n  test('b', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('neighboring suite beforeAll deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': beforeAllNeighboringSuitesSource,\n  }, {\n    maxConcurrency: 1,\n    hookTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"s1\": {\n          \"__suite_errors__\": [\n            \"Hook timed out in 500ms.\n    If this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\",\n          ],\n          \"a\": \"skipped\",\n        },\n        \"s2\": {\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('neighboring suite beforeAll passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': beforeAllNeighboringSuitesSource,\n  }, {\n    maxConcurrency: 2,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"s1\": {\n          \"a\": \"passed\",\n        },\n        \"s2\": {\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst afterAllNeighboringSuitesSource = `\nimport { afterAll, describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\nconst defers = [\n  createDefer<void>(),\n  createDefer<void>(),\n]\n\ndescribe.concurrent('s1', () => {\n  afterAll(async () => {\n    defers[0].resolve()\n    await defers[1]\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n})\n\ndescribe.concurrent('s2', () => {\n  afterAll(async () => {\n    await defers[0]\n    defers[1].resolve()\n  })\n\n  test('b', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('neighboring suite afterAll deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': afterAllNeighboringSuitesSource,\n  }, {\n    maxConcurrency: 1,\n    hookTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"s1\": {\n          \"__suite_errors__\": [\n            \"Hook timed out in 500ms.\n    If this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\",\n          ],\n          \"a\": \"passed\",\n        },\n        \"s2\": {\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('neighboring suite afterAll passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': afterAllNeighboringSuitesSource,\n  }, {\n    maxConcurrency: 2,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"s1\": {\n          \"a\": \"passed\",\n        },\n        \"s2\": {\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst beforeEachDeadlockSource = `\nimport { beforeEach, describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\ndescribe.concurrent('wrapper', () => {\n  const defers = [\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n  ]\n\n  beforeEach(async () => {\n    defers[0].resolve()\n    await defers[2]\n  })\n\n  beforeEach(async () => {\n    await defers[0]\n    defers[1].resolve()\n    await defers[2]\n  })\n\n  beforeEach(async () => {\n    await defers[1]\n    defers[2].resolve()\n  })\n\n  test('t', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('beforeEach deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': beforeEachDeadlockSource,\n  }, {\n    maxConcurrency: 2,\n    sequence: { hooks: 'parallel' },\n    hookTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"t\": [\n            \"Hook timed out in 500ms.\n    If this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('beforeEach passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': beforeEachDeadlockSource,\n  }, {\n    maxConcurrency: 3,\n    sequence: { hooks: 'parallel' },\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"t\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst afterEachDeadlockSource = `\nimport { afterEach, describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\ndescribe.concurrent('wrapper', () => {\n  const defers = [\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n  ]\n\n  afterEach(async () => {\n    defers[0].resolve()\n    await defers[2]\n  })\n\n  afterEach(async () => {\n    await defers[0]\n    defers[1].resolve()\n    await defers[2]\n  })\n\n  afterEach(async () => {\n    await defers[1]\n    defers[2].resolve()\n  })\n\n  test('t', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('afterEach deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': afterEachDeadlockSource,\n  }, {\n    maxConcurrency: 2,\n    sequence: { hooks: 'parallel' },\n    hookTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"t\": [\n            \"Hook timed out in 500ms.\n    If this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('afterEach passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': afterEachDeadlockSource,\n  }, {\n    maxConcurrency: 3,\n    sequence: { hooks: 'parallel' },\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"t\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst aroundAllNeighboringSuitesSource = `\nimport { aroundAll, describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\nconst defers = [\n  createDefer<void>(),\n  createDefer<void>(),\n]\n\ndescribe.concurrent('s1', () => {\n  aroundAll(async (runSuite) => {\n    defers[0].resolve()\n    await defers[1]\n    await runSuite()\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n})\n\ndescribe.concurrent('s2', () => {\n  aroundAll(async (runSuite) => {\n    await defers[0]\n    defers[1].resolve()\n    await runSuite()\n  })\n\n  test('b', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('neighboring suite aroundAll deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': aroundAllNeighboringSuitesSource,\n  }, {\n    maxConcurrency: 1,\n    hookTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"s1\": {\n          \"__suite_errors__\": [\n            \"The setup phase of \"aroundAll\" hook timed out after 500ms.\",\n          ],\n          \"a\": \"skipped\",\n        },\n        \"s2\": {\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('neighboring suite aroundAll passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': aroundAllNeighboringSuitesSource,\n  }, {\n    maxConcurrency: 2,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"s1\": {\n          \"a\": \"passed\",\n        },\n        \"s2\": {\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst aroundAllNeighboringSuitesPostSource = `\nimport { aroundAll, describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\nconst defers = [\n  createDefer<void>(),\n  createDefer<void>(),\n]\n\ndescribe.concurrent('s1', () => {\n  aroundAll(async (runSuite) => {\n    await runSuite()\n    defers[0].resolve()\n    await defers[1]\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n})\n\ndescribe.concurrent('s2', () => {\n  aroundAll(async (runSuite) => {\n    await runSuite()\n    await defers[0]\n    defers[1].resolve()\n  })\n\n  test('b', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('neighboring suite aroundAll teardown deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': aroundAllNeighboringSuitesPostSource,\n  }, {\n    maxConcurrency: 1,\n    hookTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"s1\": {\n          \"__suite_errors__\": [\n            \"The teardown phase of \\\"aroundAll\\\" hook timed out after 500ms.\",\n          ],\n          \"a\": \"passed\",\n        },\n        \"s2\": {\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('neighboring suite aroundAll teardown passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': aroundAllNeighboringSuitesPostSource,\n  }, {\n    maxConcurrency: 2,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"s1\": {\n          \"a\": \"passed\",\n        },\n        \"s2\": {\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst aroundAllSetupTimeoutLateTeardownAcquireSource = `\nimport { aroundAll, describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\nconst unblockS1Setup = createDefer<void>()\nconst allowS2TestFinish = createDefer<void>()\nconst blockForever = createDefer<void>()\n\ndescribe.concurrent('s1', () => {\n  aroundAll(async (runSuite) => {\n    await unblockS1Setup\n    await runSuite()\n    allowS2TestFinish.resolve()\n    await blockForever\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n})\n\ndescribe.concurrent('s2', () => {\n  aroundAll(async (runSuite) => {\n    unblockS1Setup.resolve()\n    await runSuite()\n  })\n\n  test('b', async () => {\n    await allowS2TestFinish\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('neighboring suite aroundAll does not hang when setup times out before late teardown acquire', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': aroundAllSetupTimeoutLateTeardownAcquireSource,\n  }, {\n    maxConcurrency: 1,\n    hookTimeout: 500,\n    testTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"s1\": {\n          \"__suite_errors__\": [\n            \"The setup phase of \"aroundAll\" hook timed out after 500ms.\",\n          ],\n          \"a\": \"skipped\",\n        },\n        \"s2\": {\n          \"b\": [\n            \"Test timed out in 500ms.\n    If this is a long-running test, pass a timeout value as the last argument or configure it globally with \"testTimeout\".\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\nconst aroundEachNeighboringTestsSource = `\nimport { aroundEach, describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\nconst defers = [\n  createDefer<void>(),\n  createDefer<void>(),\n]\n\ndescribe.concurrent('wrapper', () => {\n  aroundEach(async (runTest, context) => {\n    if (context.task.name === 'a') {\n      defers[0].resolve()\n      await defers[1]\n      await runTest()\n      return\n    }\n\n    await defers[0]\n    defers[1].resolve()\n    await runTest()\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n\n  test('b', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('neighboring test aroundEach deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': aroundEachNeighboringTestsSource,\n  }, {\n    maxConcurrency: 1,\n    hookTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"a\": [\n            \"The setup phase of \\\"aroundEach\\\" hook timed out after 500ms.\",\n          ],\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('neighboring test aroundEach passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': aroundEachNeighboringTestsSource,\n  }, {\n    maxConcurrency: 2,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"a\": \"passed\",\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst aroundEachNeighboringTestsPostSource = `\nimport { aroundEach, describe, expect, test } from 'vitest'\nimport { createDefer } from '@vitest/utils/helpers'\n\nconst defers = [\n  createDefer<void>(),\n  createDefer<void>(),\n]\n\ndescribe.concurrent('wrapper', () => {\n  aroundEach(async (runTest, context) => {\n    await runTest()\n\n    if (context.task.name === 'a') {\n      defers[0].resolve()\n      await defers[1]\n      return\n    }\n\n    await defers[0]\n    defers[1].resolve()\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n\n  test('b', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('neighboring test aroundEach teardown deadlocks with insufficient maxConcurrency', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': aroundEachNeighboringTestsPostSource,\n  }, {\n    maxConcurrency: 1,\n    hookTimeout: 500,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"a\": [\n            \"The teardown phase of \\\"aroundEach\\\" hook timed out after 500ms.\",\n          ],\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('neighboring test aroundEach teardown passes when maxConcurrency is high enough', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.ts': aroundEachNeighboringTestsPostSource,\n  }, {\n    maxConcurrency: 2,\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"a\": \"passed\",\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst aroundEachOuterCatchesInnerErrorSource = `\nimport { aroundEach, describe, expect, test } from 'vitest'\n\ndescribe.concurrent('wrapper', () => {\n  aroundEach(async (runTest) => {\n    let runTestError: unknown\n    try {\n      await runTest()\n    }\n    catch (error) {\n      runTestError = error\n    }\n\n    await Promise.resolve()\n\n    if (runTestError) {\n      throw runTestError\n    }\n  })\n\n  aroundEach(async (runTest, context) => {\n    await runTest()\n    if (context.task.name === 'a') {\n      throw new Error('inner aroundEach teardown failure')\n    }\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n\n  test('b', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('aroundEach continues protocol when outer hook catches runTest error', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': aroundEachOuterCatchesInnerErrorSource,\n  }, {\n    maxConcurrency: 1,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"a\": [\n            \"inner aroundEach teardown failure\",\n          ],\n          \"b\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst aroundAllOuterCatchesInnerErrorSource = `\nimport { aroundAll, describe, expect, test } from 'vitest'\n\ndescribe.concurrent('suite', () => {\n  aroundAll(async (runSuite) => {\n    let runSuiteError: unknown\n    try {\n      await runSuite()\n    }\n    catch (error) {\n      runSuiteError = error\n    }\n\n    await Promise.resolve()\n\n    if (runSuiteError) {\n      throw runSuiteError\n    }\n  })\n\n  aroundAll(async (runSuite) => {\n    await runSuite()\n    throw new Error('inner aroundAll teardown failure')\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('aroundAll continues protocol when outer hook catches runSuite error', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': aroundAllOuterCatchesInnerErrorSource,\n  }, {\n    maxConcurrency: 1,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"suite\": {\n          \"__suite_errors__\": [\n            \"inner aroundAll teardown failure\",\n          ],\n          \"a\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\nconst aroundEachCaughtInnerErrorTeardownTimeoutSource = `\nimport { aroundEach, describe, expect, test } from 'vitest'\n\ndescribe.concurrent('wrapper', () => {\n  aroundEach(async (runTest) => {\n    try {\n      await runTest()\n    }\n    catch {\n      // swallow inner failure, then run long teardown logic\n    }\n    await new Promise(resolve => setTimeout(resolve, 200))\n  }, 50)\n\n  aroundEach(async (runTest) => {\n    await runTest()\n    throw new Error('inner aroundEach teardown failure')\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('aroundEach enforces teardown timeout when inner error is caught', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': aroundEachCaughtInnerErrorTeardownTimeoutSource,\n  }, {\n    maxConcurrency: 1,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"wrapper\": {\n          \"a\": [\n            \"inner aroundEach teardown failure\",\n            \"The teardown phase of \"aroundEach\" hook timed out after 50ms.\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\nconst aroundAllCaughtInnerErrorTeardownTimeoutSource = `\nimport { aroundAll, describe, expect, test } from 'vitest'\n\ndescribe.concurrent('suite', () => {\n  aroundAll(async (runSuite) => {\n    try {\n      await runSuite()\n    }\n    catch {\n      // swallow inner failure, then run long teardown logic\n    }\n    await new Promise(resolve => setTimeout(resolve, 200))\n  }, 50)\n\n  aroundAll(async (runSuite) => {\n    await runSuite()\n    throw new Error('inner aroundAll teardown failure')\n  })\n\n  test('a', () => {\n    expect(1).toBe(1)\n  })\n})\n`\n\ntest('aroundAll enforces teardown timeout when inner error is caught', async () => {\n  const { errorTree } = await runInlineTests({\n    'basic.test.ts': aroundAllCaughtInnerErrorTeardownTimeoutSource,\n  }, {\n    maxConcurrency: 1,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"suite\": {\n          \"__suite_errors__\": [\n            \"inner aroundAll teardown failure\",\n            \"The teardown phase of \"aroundAll\" hook timed out after 50ms.\",\n          ],\n          \"a\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/config/bail.test.ts",
    "content": "import type { TestUserConfig } from 'vitest/node'\nimport { runVitest } from '#test-utils'\nimport { playwright } from '@vitest/browser-playwright'\nimport { expect, test } from 'vitest'\n\nconst configs: TestUserConfig[] = []\nconst pools: TestUserConfig[] = [\n  { pool: 'threads' },\n  { pool: 'forks' },\n  { pool: 'threads', fileParallelism: false },\n]\n\nif (process.platform !== 'win32') {\n  pools.push(\n    {\n      browser: {\n        enabled: true,\n        provider: playwright(),\n        headless: true,\n        fileParallelism: false,\n        instances: [\n          { browser: 'chromium' },\n        ],\n      },\n    },\n    {\n      browser: {\n        enabled: true,\n        provider: playwright(),\n        headless: true,\n        fileParallelism: true,\n        instances: [\n          { browser: 'chromium' },\n        ],\n      },\n    },\n  )\n}\n\nfor (const isolate of [true, false]) {\n  for (const pool of pools) {\n    configs.push({\n      ...pool,\n      isolate,\n      browser: {\n        ...pool.browser!,\n        isolate,\n      },\n    })\n  }\n}\n\nfor (const config of configs) {\n  test(\n    `should bail with \"${JSON.stringify(config)}\"`,\n    {\n      retry: config.browser?.enabled ? 3 : 0,\n    },\n    async () => {\n      const isParallel\n        = (config.pool === 'threads' && config.fileParallelism !== false)\n          || (config.pool === 'forks' && config.fileParallelism !== false)\n          || (config.browser?.enabled && config.browser.fileParallelism)\n\n      // THREADS here means that multiple tests are run parallel\n      process.env.THREADS = isParallel ? 'true' : 'false'\n\n      const { exitCode, stdout, ctx } = await runVitest({\n        root: './fixtures/config/bail',\n        bail: 1,\n        ...config,\n        env: {\n          THREADS: process.env.THREADS,\n        },\n      }, [])\n\n      expect(ctx?.config.pool).toBe(config.pool || 'forks')\n      expect(ctx?.config.browser.enabled).toBe(config.browser?.enabled ?? false)\n\n      const browser = config.browser?.enabled\n\n      expect(exitCode).toBe(1)\n      if (browser) {\n        expect(stdout).toMatch(`✓ |chromium| test/first.test.ts > 1 - first.test.ts - this should pass`)\n        expect(stdout).toMatch(`× |chromium| test/first.test.ts > 2 - first.test.ts - this should fail`)\n\n        expect(stdout).not.toMatch('✓ |chromium| test/first.test.ts > 3 - first.test.ts - this should be skipped')\n        expect(stdout).not.toMatch('✓ |chromium| test/second.test.ts > 1 - second.test.ts - this should be skipped')\n        expect(stdout).not.toMatch('✓ |chromium| test/second.test.ts > 2 - second.test.ts - this should be skipped')\n        expect(stdout).not.toMatch('✓ |chromium| test/second.test.ts > 3 - second.test.ts - this should be skipped')\n      }\n      else {\n        expect(stdout).toMatch('✓ test/first.test.ts > 1 - first.test.ts - this should pass')\n        expect(stdout).toMatch('× test/first.test.ts > 2 - first.test.ts - this should fail')\n\n        expect(stdout).not.toMatch('✓ test/first.test.ts > 3 - first.test.ts - this should be skipped')\n        expect(stdout).not.toMatch('✓ test/second.test.ts > 1 - second.test.ts - this should be skipped')\n        expect(stdout).not.toMatch('✓ test/second.test.ts > 2 - second.test.ts - this should be skipped')\n        expect(stdout).not.toMatch('✓ test/second.test.ts > 3 - second.test.ts - this should be skipped')\n      }\n    },\n  )\n}\n"
  },
  {
    "path": "test/cli/test/config/browser-configs.test.ts",
    "content": "import type { TestFsStructure } from '#test-utils'\nimport type { ViteUserConfig } from 'vitest/config'\nimport type { TestUserConfig, VitestOptions } from 'vitest/node'\nimport crypto from 'node:crypto'\nimport { runVitest, runVitestCli, useFS } from '#test-utils'\nimport { playwright } from '@vitest/browser-playwright'\nimport { preview } from '@vitest/browser-preview'\nimport { resolve } from 'pathe'\nimport { describe, expect, onTestFinished, test } from 'vitest'\nimport { createVitest } from 'vitest/node'\n\nasync function vitest(cliOptions: TestUserConfig, configValue: TestUserConfig = {}, viteConfig: ViteUserConfig = {}, vitestOptions: VitestOptions = {}) {\n  const vitest = await createVitest('test', { ...cliOptions, watch: false, config: false }, { ...viteConfig, test: configValue as any }, vitestOptions)\n  onTestFinished(() => vitest.close())\n  return vitest\n}\n\ntest('assigns names as browsers', async () => {\n  const { projects } = await vitest({}, {\n    browser: {\n      enabled: true,\n      headless: true,\n      provider: preview(),\n      instances: [\n        { browser: 'chromium' },\n        { browser: 'firefox' },\n        { browser: 'webkit' },\n      ],\n    },\n  })\n  expect(projects.map(p => p.name)).toEqual([\n    'chromium',\n    'firefox',\n    'webkit',\n  ])\n})\n\ntest('filters projects', async () => {\n  const { projects } = await vitest({ project: 'chromium' }, {\n    browser: {\n      enabled: true,\n      provider: preview(),\n      instances: [\n        { browser: 'chromium' },\n        { browser: 'firefox' },\n        { browser: 'webkit' },\n      ],\n    },\n  })\n  expect(projects.map(p => p.name)).toEqual([\n    'chromium',\n  ])\n})\n\ntest('filters projects with a wildcard', async () => {\n  const { projects } = await vitest({ project: 'chrom*' }, {\n    browser: {\n      enabled: true,\n      provider: preview(),\n      instances: [\n        { browser: 'chromium' },\n        { browser: 'firefox' },\n        { browser: 'webkit' },\n      ],\n    },\n  })\n  expect(projects.map(p => p.name)).toEqual([\n    'chromium',\n  ])\n})\n\ntest('assigns names as browsers in a custom project', async () => {\n  const { projects } = await vitest({}, {\n    projects: [\n      {\n        test: {\n          name: 'custom',\n          browser: {\n            enabled: true,\n            headless: true,\n            provider: preview(),\n            instances: [\n              { browser: 'chromium' },\n              { browser: 'firefox' },\n              { browser: 'webkit' },\n              { browser: 'webkit', name: 'hello-world' },\n            ],\n          },\n        },\n      },\n    ],\n  })\n  expect(projects.map(p => p.name)).toEqual([\n    'custom (chromium)',\n    'custom (firefox)',\n    'custom (webkit)',\n    'hello-world',\n  ])\n})\n\ntest('inherits browser options', async () => {\n  const { projects } = await vitest({}, {\n    setupFiles: ['/test/setup.ts'],\n    provide: {\n      browser: true,\n    } as any,\n    browser: {\n      enabled: true,\n      provider: preview(),\n      headless: true,\n      screenshotFailures: false,\n      testerHtmlPath: '/custom-path.html',\n      screenshotDirectory: '/custom-directory',\n      fileParallelism: false,\n      viewport: {\n        width: 300,\n        height: 900,\n      },\n      locators: {\n        testIdAttribute: 'data-tid',\n      },\n      instances: [\n        {\n          browser: 'chromium',\n          screenshotFailures: true,\n        },\n        {\n          browser: 'firefox',\n          screenshotFailures: true,\n          locators: {\n            testIdAttribute: 'data-custom',\n          },\n          viewport: {\n            width: 900,\n            height: 300,\n          },\n          testerHtmlPath: '/custom-overridden-path.html',\n          screenshotDirectory: '/custom-overridden-directory',\n        },\n      ],\n    },\n  })\n  expect(projects.map(p => p.config)).toMatchObject([\n    {\n      name: 'chromium',\n      setupFiles: ['/test/setup.ts'],\n      provide: {\n        browser: true,\n      } as any,\n      browser: {\n        enabled: true,\n        headless: true,\n        screenshotFailures: true,\n        screenshotDirectory: '/custom-directory',\n        viewport: {\n          width: 300,\n          height: 900,\n        },\n        locators: {\n          testIdAttribute: 'data-tid',\n        },\n        fileParallelism: false,\n        testerHtmlPath: '/custom-path.html',\n      },\n    },\n    {\n      name: 'firefox',\n      setupFiles: ['/test/setup.ts'],\n      provide: {\n        browser: true,\n      } as any,\n      browser: {\n        enabled: true,\n        headless: true,\n        screenshotFailures: true,\n        viewport: {\n          width: 900,\n          height: 300,\n        },\n        screenshotDirectory: '/custom-overridden-directory',\n        locators: {\n          testIdAttribute: 'data-custom',\n        },\n        testerHtmlPath: '/custom-overridden-path.html',\n      },\n    },\n  ])\n})\n\ntest('coverage provider v8 works correctly in browser mode if instances are filtered', async () => {\n  const { projects } = await vitest(\n    {\n      project: 'chromium',\n    },\n    {\n      coverage: {\n        enabled: true,\n        provider: 'v8',\n      },\n      browser: {\n        enabled: true,\n        provider: playwright(),\n        instances: [\n          { browser: 'chromium' },\n          { browser: 'firefox' },\n          { browser: 'webkit' },\n        ],\n      },\n    },\n  )\n  expect(projects.map(p => p.name)).toEqual([\n    'chromium',\n  ])\n})\n\ntest('coverage provider v8 works correctly in workspaced browser mode if instances are filtered', async () => {\n  const { projects } = await vitest({ project: 'browser (chromium)' }, {\n    projects: [\n      {\n        test: {\n          name: 'browser',\n          browser: {\n            enabled: true,\n            provider: playwright(),\n            instances: [\n              { browser: 'chromium' },\n              { browser: 'firefox' },\n              { browser: 'webkit' },\n            ],\n          },\n        },\n      },\n    ],\n    coverage: {\n      enabled: true,\n      provider: 'v8',\n    },\n  })\n  expect(projects.map(p => p.name)).toEqual([\n    'browser (chromium)',\n  ])\n})\n\ntest('browser instances with include/exclude/includeSource option override parent that patterns', async () => {\n  const { projects } = await vitest({ config: false }, {\n    include: ['**/*.global.test.{js,ts}', '**/*.shared.test.{js,ts}'],\n    exclude: ['**/*.skip.test.{js,ts}'],\n    includeSource: ['src/**/*.{js,ts}'],\n    browser: {\n      enabled: true,\n      provider: preview(),\n      headless: true,\n      instances: [\n        { browser: 'chromium' },\n        { browser: 'firefox', include: ['test/firefox-specific.test.ts'], exclude: ['test/webkit-only.test.ts', 'test/webkit-extra.test.ts'], includeSource: ['src/firefox-compat.ts'] },\n        { browser: 'webkit', include: ['test/webkit-only.test.ts', 'test/webkit-extra.test.ts'], exclude: ['test/firefox-specific.test.ts'], includeSource: ['src/webkit-compat.ts'] },\n      ],\n    },\n  })\n\n  // Chromium should inherit parent include/exclude/includeSource patterns (plus default test pattern)\n  expect(projects[0].name).toEqual('chromium')\n  expect(projects[0].config.include).toEqual([\n    '**/*.global.test.{js,ts}',\n    '**/*.shared.test.{js,ts}',\n  ])\n  expect(projects[0].config.exclude).toEqual([\n    '**/*.skip.test.{js,ts}',\n  ])\n  expect(projects[0].config.includeSource).toEqual([\n    'src/**/*.{js,ts}',\n  ])\n\n  // Firefox should only have its specific include/exclude/includeSource pattern (not parent patterns)\n  expect(projects[1].name).toEqual('firefox')\n  expect(projects[1].config.include).toEqual([\n    'test/firefox-specific.test.ts',\n  ])\n  expect(projects[1].config.exclude).toEqual([\n    'test/webkit-only.test.ts',\n    'test/webkit-extra.test.ts',\n  ])\n  expect(projects[1].config.includeSource).toEqual([\n    'src/firefox-compat.ts',\n  ])\n\n  // Webkit should only have its specific include/exclude/includeSource patterns (not parent patterns)\n  expect(projects[2].name).toEqual('webkit')\n  expect(projects[2].config.include).toEqual([\n    'test/webkit-only.test.ts',\n    'test/webkit-extra.test.ts',\n  ])\n  expect(projects[2].config.exclude).toEqual([\n    'test/firefox-specific.test.ts',\n  ])\n  expect(projects[2].config.includeSource).toEqual([\n    'src/webkit-compat.ts',\n  ])\n})\n\ntest('browser instances with empty include array should get parent include patterns', async () => {\n  const { projects } = await vitest({ config: false }, {\n    include: ['**/*.test.{js,ts}'],\n    browser: {\n      enabled: true,\n      provider: preview(),\n      headless: true,\n      instances: [\n        { browser: 'chromium', include: [] },\n        { browser: 'firefox' },\n      ],\n    },\n  })\n\n  // Both instances should inherit parent include patterns when include is empty or not specified\n  expect(projects[0].config.include).toEqual(['**/*.test.{js,ts}'])\n  expect(projects[1].config.include).toEqual(['**/*.test.{js,ts}'])\n})\n\ntest('filter for the global browser project includes all browser instances', async () => {\n  const { projects } = await vitest({ project: 'myproject' }, {\n    projects: [\n      {\n        test: {\n          name: 'myproject',\n          browser: {\n            enabled: true,\n            provider: playwright(),\n            headless: true,\n            instances: [\n              { browser: 'chromium' },\n              { browser: 'firefox' },\n              { browser: 'webkit' },\n            ],\n          },\n        },\n      },\n      {\n        test: {\n          name: 'skip',\n        },\n      },\n    ],\n  })\n  expect(projects.map(p => p.name)).toEqual([\n    'myproject (chromium)',\n    'myproject (firefox)',\n    'myproject (webkit)',\n  ])\n})\n\ntest('can enable browser-cli options for multi-project workspace', async () => {\n  const { projects } = await vitest(\n    {\n      browser: {\n        enabled: true,\n        provider: preview(),\n        headless: true,\n        instances: [],\n      },\n    },\n    {\n      projects: [\n        {\n          test: {\n            name: 'unit',\n          },\n        },\n        {\n          test: {\n            browser: {\n              enabled: true,\n              provider: playwright(),\n              instances: [\n                { browser: 'chromium', name: 'browser' },\n              ],\n            },\n          },\n        },\n      ],\n    },\n  )\n  expect(projects.map(p => p.name)).toEqual([\n    'unit',\n    'browser',\n  ])\n\n  // unit config\n  expect(projects[0].config.browser.enabled).toBe(false)\n\n  // browser config\n  expect(projects[1].config.browser.enabled).toBe(true)\n  expect(projects[1].config.browser.headless).toBe(true)\n})\n\ntest('core provider has options if `provider` is playwright', async () => {\n  const v = await vitest({}, {\n    browser: {\n      enabled: true,\n      provider: playwright({ actionTimeout: 1000 }),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  })\n  expect(v.config.browser.provider?.options).toEqual({\n    actionTimeout: 1000,\n  })\n})\n\ntest('core provider has options if `provider` is wdio', async () => {\n  const v = await vitest({}, {\n    browser: {\n      enabled: true,\n      provider: playwright({ contextOptions: { hasTouch: true } }),\n      instances: [\n        { browser: 'chrome' },\n      ],\n    },\n  })\n  expect(v.config.browser.provider?.options).toEqual({\n    contextOptions: { hasTouch: true },\n  })\n})\n\ntest('core provider has options if `provider` is preview', async () => {\n  const v = await vitest({}, {\n    browser: {\n      enabled: true,\n      provider: preview(),\n      instances: [\n        { browser: 'chrome' },\n      ],\n    },\n  })\n  expect(v.config.browser.provider?.options).toEqual({})\n})\n\ntest('provider options can be changed dynamically', async () => {\n  const v = await vitest({}, {\n    browser: {\n      enabled: true,\n      provider: playwright({ actionTimeout: 1000 }),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  }, {\n    plugins: [\n      {\n        name: 'update-options',\n        configureVitest({ project }) {\n          if (project.config.browser.provider) {\n            const options = project.config.browser.provider.options as any\n            options.actionTimeout = 400\n            options.someDifferentOption = 'test'\n          }\n        },\n      },\n    ],\n  })\n  expect(v.config.browser.provider?.options).toEqual({\n    actionTimeout: 400,\n    someDifferentOption: 'test',\n  })\n})\n\ntest('provider options can be changed dynamically if no options are specified', async () => {\n  const v = await vitest({}, {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  }, {\n    plugins: [\n      {\n        name: 'update-options',\n        configureVitest({ project }) {\n          if (project.config.browser.provider) {\n            const options = project.config.browser.provider.options as any\n            options.actionTimeout = 400\n            options.someDifferentOption = 'test'\n          }\n        },\n      },\n    ],\n  })\n  expect(v.config.browser.provider?.options).toEqual({\n    actionTimeout: 400,\n    someDifferentOption: 'test',\n  })\n})\n\ntest('provider options can be changed dynamically in CLI', async () => {\n  const v = await vitest({\n    browser: {\n      provider: {\n        name: 'playwright',\n        _cli: true,\n      } as any,\n      instances: [],\n    },\n  }, {\n    browser: {\n      enabled: true,\n      provider: preview(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  }, {\n    plugins: [\n      {\n        name: 'update-options',\n        configureVitest({ project }) {\n          if (project.config.browser.provider) {\n            const options = project.config.browser.provider.options as any\n            options.actionTimeout = 400\n            options.someDifferentOption = 'test'\n          }\n        },\n      },\n    ],\n  })\n  expect(v.config.browser.provider?.options).toEqual({\n    actionTimeout: 400,\n    someDifferentOption: 'test',\n  })\n})\n\ntest('fileParallelism on the instance works properly', async () => {\n  const v = await vitest({}, {\n    fileParallelism: true,\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        {\n          browser: 'chromium',\n          fileParallelism: false,\n        },\n        {\n          browser: 'firefox',\n          fileParallelism: true,\n        },\n      ],\n    },\n  })\n  expect(v.projects).toHaveLength(2)\n  expect(v.projects[0].config.browser.fileParallelism).toBe(false)\n  expect(v.projects[1].config.browser.fileParallelism).toBe(true)\n})\n\ntest('detailsPanelPosition defaults to right', async () => {\n  const { projects } = await vitest({}, {\n    browser: {\n      enabled: true,\n      provider: preview(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  })\n  expect(projects[0].config.browser.detailsPanelPosition).toBe('right')\n})\n\ntest('detailsPanelPosition from config file is respected', async () => {\n  const { projects } = await vitest({}, {\n    browser: {\n      enabled: true,\n      provider: preview(),\n      detailsPanelPosition: 'bottom',\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  })\n  expect(projects[0].config.browser.detailsPanelPosition).toBe('bottom')\n})\n\ntest('CLI option --browser.detailsPanelPosition overrides config', async () => {\n  const { projects } = await vitest({\n    browser: {\n      detailsPanelPosition: 'bottom',\n    },\n  }, {\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      detailsPanelPosition: 'right',\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  })\n  expect(projects[0].config.browser.detailsPanelPosition).toBe('bottom')\n})\n\nfunction getCliConfig(options: TestUserConfig, cli: string[], fs: TestFsStructure = {}) {\n  const root = resolve(process.cwd(), `vitest-test-${crypto.randomUUID()}`)\n  useFS(root, {\n    ...fs,\n    'basic.test.ts': /* ts */`\n      import { test } from 'vitest'\n      test('basic', () => {\n        expect(1).toBe(1)\n      })\n    `,\n    'vitest.config.ts': /* ts */ `\n      export default {\n        test: {\n          reporters: [\n            {\n              onInit(vitest) {\n                const browser = vitest.config.browser\n                const workspace = (p) => ({\n                  name: p.name,\n                  headless: p.config.browser.headless,\n                  browser: p.config.browser.enabled,\n                  ui: p.config.browser.ui,\n                })\n                console.log(JSON.stringify({\n                  browser: {\n                    headless: browser.headless,\n                    browser: browser.enabled,\n                    ui: browser.ui,\n                  },\n                  workspace: vitest.projects.map(p => {\n                    return {\n                      ...workspace(p),\n                      parent: p._parent ? workspace(p._parent) : null,\n                    }\n                  })\n                }))\n                // throw an error to avoid running tests\n                throw new Error('stop')\n              },\n            },\n          ],\n          ...${JSON.stringify(options)}\n        }\n      }\n    `,\n  })\n  return runVitestCli(\n    {\n      nodeOptions: {\n        env: {\n          CI: '',\n          GITHUB_ACTIONS: undefined,\n        },\n      },\n    },\n    '--root',\n    root,\n    '--no-watch',\n    ...cli,\n  )\n}\n\ndescribe('[e2e] workspace configs are affected by the CLI options', () => {\n  test('UI is not enabled by default in headless config', async () => {\n    const vitest = await getCliConfig({\n      projects: [\n        {\n          test: {\n            name: 'unit',\n          },\n        },\n        {\n          test: {\n            name: 'browser',\n            browser: {\n              enabled: true,\n              headless: true,\n              provider: playwright(),\n              instances: [\n                {\n                  browser: 'chromium',\n                },\n              ],\n            },\n          },\n        },\n      ],\n    }, [])\n\n    const config = JSON.parse(vitest.stdout)\n\n    expect(config.workspace).toHaveLength(2)\n    expect(config.workspace[0]).toEqual({\n      name: 'unit',\n      headless: false,\n      browser: false,\n      ui: true,\n      parent: null,\n    })\n\n    expect(config.workspace[1]).toEqual({\n      name: 'browser (chromium)',\n      // headless was set in the config\n      headless: true,\n      browser: true,\n      // UI is false because headless is enabled\n      ui: false,\n      parent: {\n        name: 'browser',\n        headless: true,\n        browser: true,\n        ui: false,\n      },\n    })\n  })\n\n  test('CLI options correctly override inline workspace options', async () => {\n    const vitest = await getCliConfig({\n      projects: [\n        {\n          test: {\n            name: 'unit',\n          },\n        },\n        {\n          test: {\n            name: 'browser',\n            browser: {\n              enabled: true,\n              headless: true,\n              provider: playwright(),\n              instances: [\n                {\n                  browser: 'chromium',\n                },\n              ],\n            },\n          },\n        },\n      ],\n    }, ['--browser.headless=false'])\n\n    const config = JSON.parse(vitest.stdout)\n\n    expect(config.workspace).toHaveLength(2)\n    expect(config.workspace[0]).toEqual({\n      name: 'unit',\n      headless: false,\n      browser: false,\n      ui: true,\n      parent: null,\n    })\n\n    expect(config.workspace[1]).toEqual({\n      name: 'browser (chromium)',\n      // headless was overridden by CLI options\n      headless: false,\n      browser: true,\n      // UI should be true because we always set CI to false,\n      // if headless was `true`, ui would be `false`\n      ui: true,\n      parent: {\n        name: 'browser',\n        headless: false,\n        browser: true,\n        ui: true,\n      },\n    })\n  })\n\n  test('CLI options correctly override config file workspace options', async () => {\n    const vitest = await getCliConfig(\n      {\n        projects: [\n          {\n            test: {\n              name: 'unit',\n            },\n          },\n          './vitest.browser.config.ts',\n        ],\n      },\n      ['--browser.headless=false'],\n      {\n        'vitest.browser.config.ts': {\n          test: {\n            name: 'browser',\n            browser: {\n              enabled: true,\n              headless: true,\n              provider: playwright(),\n              instances: [\n                {\n                  browser: 'chromium',\n                },\n              ],\n            },\n          },\n        },\n      },\n    )\n\n    const config = JSON.parse(vitest.stdout)\n\n    expect(config.workspace).toHaveLength(2)\n    expect(config.workspace[0]).toEqual({\n      name: 'unit',\n      headless: false,\n      browser: false,\n      ui: true,\n      parent: null,\n    })\n\n    expect(config.workspace[1]).toEqual({\n      name: 'browser (chromium)',\n      headless: false,\n      browser: true,\n      ui: true,\n      parent: {\n        name: 'browser',\n        headless: false,\n        browser: true,\n        ui: true,\n      },\n    })\n  })\n\n  test('correctly resolves extended project', async () => {\n    const { stdout } = await getCliConfig({\n      browser: {\n        provider: playwright(),\n        headless: true,\n        instances: [\n          { browser: 'chromium' },\n        ],\n      },\n      projects: [\n        {\n          extends: true,\n          test: {\n            name: 'node',\n          },\n        },\n        {\n          extends: true,\n          test: {\n            name: 'browser',\n            browser: {\n              enabled: true,\n              provider: preview(),\n              instances: [],\n            },\n          },\n        },\n      ],\n    }, [])\n\n    const config = JSON.parse(stdout)\n\n    expect(config.workspace).toHaveLength(2)\n    expect(config.workspace[0]).toEqual({\n      name: 'node',\n      headless: true,\n      browser: false,\n      ui: false,\n      parent: null,\n    })\n\n    expect(config.workspace[1]).toEqual({\n      name: 'browser (chromium)',\n      headless: true,\n      browser: true,\n      ui: false,\n      parent: {\n        name: 'browser',\n        headless: true,\n        browser: true,\n        ui: false,\n      },\n    })\n  })\n\n  test('correctly overrides extended project', async () => {\n    const { stdout } = await getCliConfig({\n      browser: {\n        provider: playwright(),\n        headless: true,\n        instances: [\n          { browser: 'chromium' },\n        ],\n      },\n      projects: [\n        {\n          extends: true,\n          test: {\n            name: 'node',\n          },\n        },\n        {\n          extends: true,\n          test: {\n            name: 'browser',\n            browser: {\n              enabled: true,\n              provider: preview(),\n              instances: [],\n            },\n          },\n        },\n      ],\n    }, ['--browser.headless=false'])\n\n    const config = JSON.parse(stdout)\n\n    expect(config.workspace).toHaveLength(2)\n    expect(config.workspace[0]).toEqual({\n      name: 'node',\n      headless: false,\n      browser: false,\n      ui: true,\n      parent: null,\n    })\n\n    expect(config.workspace[1]).toEqual({\n      name: 'browser (chromium)',\n      headless: false,\n      browser: true,\n      ui: true,\n      parent: {\n        name: 'browser',\n        headless: false,\n        browser: true,\n        ui: true,\n      },\n    })\n  })\n\n  test('CLI options override the config if --browser.enabled is passed down manually', async () => {\n    const { stdout } = await getCliConfig({\n      browser: {\n        enabled: false,\n        provider: playwright(),\n        headless: true,\n        instances: [\n          { browser: 'chromium' },\n        ],\n      },\n    }, ['--browser.headless=false', '--browser.enabled'])\n\n    const config = JSON.parse(stdout)\n    expect(config).toEqual({\n      browser: {\n        headless: false,\n        browser: true,\n        ui: true,\n      },\n      workspace: [\n        {\n          name: 'chromium',\n          headless: false,\n          browser: true,\n          ui: true,\n          parent: {\n            name: '',\n            headless: false,\n            browser: true,\n            ui: true,\n          },\n        },\n      ],\n    })\n  })\n})\n\ntest('browser root', async () => {\n  process.env.BROWSER_DEFINE_TEST_PROEJCT = 'false'\n  const { testTree, stderr } = await runVitest({\n    root: './fixtures/config/browser-define',\n    browser: {\n      headless: true,\n    },\n  })\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"passes\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('browser project', async () => {\n  process.env.BROWSER_DEFINE_TEST_PROEJCT = 'true'\n  const { testTree, stderr } = await runVitest({\n    root: './fixtures/config/browser-define',\n    browser: {\n      headless: true,\n    },\n  })\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"passes\": \"passed\",\n      },\n    }\n  `)\n})\n\nconst customHtmlRoot = resolve(import.meta.dirname, '../../fixtures/config/browser-custom-html')\n\ntest('throws an error with non-existing path', async () => {\n  const { stderr } = await runVitest({\n    root: customHtmlRoot,\n    config: './vitest.config.non-existing.ts',\n  }, [], { fails: true })\n  expect(stderr).toContain(`Tester HTML file \"${resolve(customHtmlRoot, './some-non-existing-path')}\" doesn't exist.`)\n})\n\ntest('throws an error and exits if there is an error in the html file hook', async () => {\n  const { stderr, exitCode } = await runVitest({\n    root: customHtmlRoot,\n    config: './vitest.config.error-hook.ts',\n  })\n  expect(stderr).toContain('Error: expected error in transformIndexHtml')\n  expect(stderr).toContain('[vite] Internal server error: expected error in transformIndexHtml')\n  expect(exitCode).toBe(1)\n})\n\ntest('allows correct custom html', async () => {\n  const { stderr, stdout, exitCode } = await runVitest({\n    root: customHtmlRoot,\n    config: './vitest.config.correct.ts',\n    reporters: [['default', { summary: false }]],\n  })\n  expect(stderr).toBe('')\n  expect(stdout).toContain('✓ |chromium| browser-basic.test.ts')\n  expect(exitCode).toBe(0)\n})\n\ntest('allows custom transformIndexHtml with custom html file', async () => {\n  const { stderr, stdout, exitCode } = await runVitest({\n    root: customHtmlRoot,\n    config: './vitest.config.custom-transformIndexHtml.ts',\n    reporters: [['default', { summary: false }]],\n  })\n  expect(stderr).toBe('')\n  expect(stdout).toContain('✓ |chromium| browser-custom.test.ts')\n  expect(exitCode).toBe(0)\n})\n\ntest('allows custom transformIndexHtml without custom html file', async () => {\n  const { stderr, stdout, exitCode } = await runVitest({\n    root: customHtmlRoot,\n    config: './vitest.config.default-transformIndexHtml.ts',\n    reporters: [['default', { summary: false }]],\n  })\n  expect(stderr).toBe('')\n  expect(stdout).toContain('✓ |chromium| browser-custom.test.ts')\n  expect(exitCode).toBe(0)\n})\n\ntest('show a warning if host is exposed', async () => {\n  const { stderr } = await runVitest({\n    config: false,\n    root: './fixtures/basic',\n    reporters: [\n      {\n        onInit() {\n          throw new Error('stop')\n        },\n      },\n    ],\n    browser: {\n      api: {\n        host: 'custom-host',\n      },\n    },\n  })\n  expect(stderr).toContain(\n    'API server is exposed to network, disabling write and exec operations by default for security reasons. This can cause some APIs to not work as expected. Set `browser.api.allowExec` manually to hide this warning. See https://vitest.dev/config/browser/api for more details.',\n  )\n})\n"
  },
  {
    "path": "test/cli/test/config/passWithNoTests.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { runInlineTests } from '../../../test-utils'\n\nit('vitest doesnt fail when running empty files', async () => {\n  const { exitCode } = await runInlineTests(\n    { 'empty.test.js': '' },\n    { passWithNoTests: true },\n  )\n  expect(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/cli/test/config/sequence-shuffle.test.ts",
    "content": "import type { InlineConfig } from 'vitest/node'\nimport { runInlineTests, runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\n\nfunction run(sequence: InlineConfig['sequence']) {\n  return runVitest({\n    sequence,\n    include: [],\n    standalone: true,\n    watch: true,\n  })\n}\n\nclass CustomSequencer {\n  sort() {\n    return []\n  }\n\n  shard() {\n    return []\n  }\n}\n\ntest.each([\n  false,\n  { files: false, tests: false },\n  { files: false, tests: true },\n],\n)('should use BaseSequencer if shuffle is %o', async (shuffle) => {\n  const { ctx } = await run({ shuffle })\n  expect(ctx?.config.sequence.sequencer.name).toBe('BaseSequencer')\n})\n\ntest.each([\n  true,\n  { files: true, tests: false },\n  { files: true, tests: true },\n])('should use RandomSequencer if shuffle is %o', async (shuffle) => {\n  const { ctx } = await run({ shuffle })\n  expect(ctx?.config.sequence.sequencer.name).toBe('RandomSequencer')\n})\n\ntest.each([\n  false,\n  true,\n  { files: true, tests: false },\n  { files: true, tests: true },\n])('should always use CustomSequencer if passed', async (shuffle) => {\n  const { ctx } = await run({ shuffle, sequencer: CustomSequencer })\n  expect(ctx?.config.sequence.sequencer.name).toBe('CustomSequencer')\n})\n\ntest('shuffle with a known seed', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'basic.test.js': /* js */ `\n      import { afterAll, describe, expect, test } from 'vitest'\n\n      const numbers = []\n\n      test.for([1, 2, 3, 4, 5])('test %s', (v) => {\n        numbers.push(10 + v)\n      })\n\n      describe(\"inherit shuffle\", () => {\n        test.for([1, 2, 3, 4, 5])('test %s', (v) => {\n          numbers.push(20 + v)\n        })\n      })\n\n      describe('unshuffle', { shuffle: false }, () => {\n        test.for([1, 2, 3, 4, 5])('test %s', (v) => {\n          numbers.push(30 + v)\n        })\n      })\n\n      afterAll(() => {\n        expect(numbers).toEqual([\n          11, 14, 13, 15, 12,\n          31, 32, 33, 34, 35,\n          21, 24, 23, 25, 22\n        ])\n      })\n    `,\n  }, {\n    sequence: {\n      seed: 101,\n      shuffle: true,\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"inherit shuffle\": {\n          \"test 1\": \"passed\",\n          \"test 2\": \"passed\",\n          \"test 3\": \"passed\",\n          \"test 4\": \"passed\",\n          \"test 5\": \"passed\",\n        },\n        \"test 1\": \"passed\",\n        \"test 2\": \"passed\",\n        \"test 3\": \"passed\",\n        \"test 4\": \"passed\",\n        \"test 5\": \"passed\",\n        \"unshuffle\": {\n          \"test 1\": \"passed\",\n          \"test 2\": \"passed\",\n          \"test 3\": \"passed\",\n          \"test 4\": \"passed\",\n          \"test 5\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('should log seed when only shuffle.tests is enabled', async () => {\n  const { stdout } = await runInlineTests({\n    'basic.test.js': /* js */ `\n      import { test } from 'vitest'\n      test('example', () => {})\n    `,\n  }, {\n    sequence: {\n      seed: 12345,\n      shuffle: { files: false, tests: true },\n    },\n  })\n\n  expect(stdout).toContain('Running tests with seed \"12345\"')\n})\n\ntest('should log seed when shuffle is true', async () => {\n  const { stdout } = await runInlineTests({\n    'basic.test.js': /* js */ `\n      import { test } from 'vitest'\n      test('example', () => {})\n    `,\n  }, {\n    sequence: {\n      seed: 67890,\n      shuffle: true,\n    },\n  })\n\n  expect(stdout).toContain('Running tests with seed \"67890\"')\n})\n\ntest('should not log seed when shuffle is disabled', async () => {\n  const { stdout } = await runInlineTests({\n    'basic.test.js': /* js */ `\n      import { test } from 'vitest'\n      test('example', () => {})\n    `,\n  }, {\n    sequence: {\n      shuffle: false,\n    },\n  })\n\n  expect(stdout).not.toContain('Running tests with seed')\n})\n"
  },
  {
    "path": "test/cli/test/config/watchTriggerPattern.test.ts",
    "content": "import { resolve } from 'node:path'\nimport { editFile, runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\n\nconst root = resolve(import.meta.dirname, '../../fixtures/config/watch-trigger-pattern')\n\ntest('watch trigger pattern picks up the file', async () => {\n  const { stderr, vitest } = await runVitest({\n    root,\n    watch: true,\n  })\n\n  expect(stderr).toBe('')\n\n  await vitest.waitForStdout('Waiting for file changes')\n\n  editFile(\n    resolve(root, 'folder/fs/text.txt'),\n    content => content.replace('world', 'vitest'),\n  )\n\n  await vitest.waitForStderr('basic.test.ts')\n\n  expect(vitest.stderr).toContain(`expected 'hello vitest\\\\n' to be 'hello world\\\\n'`)\n})\n"
  },
  {
    "path": "test/cli/test/config-loader.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nconst isTypeStrippingSupported = !!process.features.typescript\n\ntest.runIf(isTypeStrippingSupported)('configLoader native', async () => {\n  const { stderr, exitCode, ctx } = await runVitest({\n    root: 'fixtures/config-loader',\n    standalone: true,\n    watch: true,\n    $cliOptions: {\n      configLoader: 'native',\n    },\n  })\n  expect(ctx?.projects.map(p => p.name)).toMatchInlineSnapshot(`\n    [\n      \"node\",\n      \"browser (chromium)\",\n    ]\n  `)\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n})\n\ntest('configLoader runner', async () => {\n  const { vitest, exitCode, ctx } = await runVitest({\n    root: 'fixtures/config-loader',\n    standalone: true,\n    watch: true,\n    $cliOptions: {\n      configLoader: 'runner',\n    },\n  })\n  expect(ctx?.projects.map(p => p.name)).toMatchInlineSnapshot(`\n    [\n      \"node\",\n      \"browser (chromium)\",\n    ]\n  `)\n  expect(vitest.stderr).toBe('')\n  expect(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/cli/test/configureVitest.test.ts",
    "content": "import type { ViteUserConfig } from 'vitest/config'\nimport type { TestProject, TestUserConfig, VitestOptions } from 'vitest/node'\nimport { expect, onTestFinished, test } from 'vitest'\nimport { createVitest } from 'vitest/node'\n\nasync function vitest(cliOptions: TestUserConfig, configValue: TestUserConfig = {}, viteConfig: ViteUserConfig = {}, vitestOptions: VitestOptions = {}) {\n  const vitest = await createVitest('test', { ...cliOptions, config: false, watch: false }, { ...viteConfig, test: configValue as any }, vitestOptions)\n  onTestFinished(() => vitest.close())\n  return vitest\n}\n\ntest('can change global configuration', async () => {\n  const v = await vitest({}, {}, {\n    plugins: [\n      {\n        name: 'test',\n        configureVitest({ vitest }) {\n          vitest.config.coverage.enabled = true\n          vitest.config.coverage.exclude = ['**/*']\n          vitest.config.setupFiles.push('test/setup.ts')\n        },\n      },\n    ],\n  })\n  expect(v.config.coverage.enabled).toBe(true)\n  expect(v.config.coverage.exclude).toEqual(['**/*'])\n  // setup is not resolved\n  expect(v.config.setupFiles).toEqual(['test/setup.ts'])\n})\n\ntest('can change the project and the global configurations', async () => {\n  const v = await vitest({}, {\n    projects: [\n      {\n        plugins: [\n          {\n            name: 'test',\n            configureVitest({ vitest, project }) {\n              vitest.config.setupFiles.push('test/setup.ts')\n              project.config.setupFiles.push('test/project-setup.ts')\n            },\n          },\n        ],\n      },\n    ],\n  })\n\n  expect(v.config.setupFiles).toEqual(['test/setup.ts'])\n  const rootProject = v.getRootProject()\n\n  expect(v.projects).toHaveLength(1)\n\n  const project = v.projects[0]\n  expect(project).not.toBe(rootProject)\n  expect(project.config.setupFiles).toEqual(['test/project-setup.ts'])\n})\n\ntest('plugin is not called if the project is filtered out', async () => {\n  const { projects } = await vitest({\n    project: 'project-2',\n  }, {\n    projects: [\n      {\n        test: {\n          name: 'project-1',\n        },\n        plugins: [\n          {\n            name: 'test',\n            configureVitest() {\n              expect.unreachable()\n            },\n          },\n        ],\n      },\n      {\n        test: {\n          name: 'project-2',\n        },\n      },\n    ],\n  })\n  expect(projects).toHaveLength(1)\n  expect(projects[0].name).toBe('project-2')\n})\n\ntest('can inject the plugin', async () => {\n  let newWorkspace: TestProject[] = []\n  const v = await vitest({}, {}, {\n    plugins: [\n      {\n        name: 'test',\n        async configureVitest({ injectTestProjects }) {\n          newWorkspace = await injectTestProjects({\n            test: {\n              name: 'project-1',\n            },\n          })\n        },\n      },\n    ],\n  })\n  expect(v.projects).toHaveLength(2)\n  // the default project that called configureVitest\n  expect(v.projects[0].name).toBe('')\n  expect(v.projects[1].name).toBe('project-1')\n\n  expect(newWorkspace).toHaveLength(1)\n  expect(newWorkspace[0].name).toBe('project-1')\n})\n\ntest('injected plugin is filtered by the --project filter', async () => {\n  let newWorkspace: TestProject[] = []\n  const { projects } = await vitest({\n    project: 'project-1',\n    projects: [\n      {\n        test: {\n          name: 'project-1',\n        },\n        plugins: [\n          {\n            name: 'test',\n            async configureVitest({ injectTestProjects }) {\n              newWorkspace = await injectTestProjects({\n                test: {\n                  name: 'project-2',\n                },\n              })\n            },\n          },\n        ],\n      },\n    ],\n  })\n  expect(projects).toHaveLength(1)\n  expect(projects[0].name).toBe('project-1')\n\n  expect(newWorkspace).toHaveLength(0)\n})\n\ntest('injected plugin is not filtered by the --project filter when it\\'s overridden', async () => {\n  let newWorkspace: TestProject[] = []\n  const { projects } = await vitest({\n    project: 'project-1',\n    projects: [\n      {\n        test: {\n          name: 'project-1',\n        },\n        plugins: [\n          {\n            name: 'test',\n            async configureVitest({ vitest, injectTestProjects }) {\n              vitest.config.project.push('project-2')\n              newWorkspace = await injectTestProjects({\n                test: {\n                  name: 'project-2',\n                },\n              })\n            },\n          },\n        ],\n      },\n    ],\n  })\n  expect(projects).toHaveLength(2)\n  expect(projects[0].name).toBe('project-1')\n  expect(projects[1].name).toBe('project-2')\n\n  expect(newWorkspace).toHaveLength(1)\n  expect(newWorkspace[0].name).toBe('project-2')\n})\n\ntest('adding a plugin with existing name throws and error', async () => {\n  await expect(() => throws({\n    projects: [\n      {\n        test: {\n          name: 'project-1',\n        },\n        plugins: [\n          {\n            name: 'test',\n            async configureVitest({ injectTestProjects }) {\n              await injectTestProjects({\n                test: {\n                  name: 'project-1',\n                },\n              })\n            },\n          },\n        ],\n      },\n    ],\n  }),\n  ).rejects.toThrow('Project name \"project-1\" is not unique. All projects should have unique names. Make sure your configuration is correct.')\n\n  await expect(() => throws({\n    projects: [\n      {\n        plugins: [\n          {\n            name: 'test',\n            async configureVitest({ injectTestProjects }) {\n              await injectTestProjects({\n                test: {\n                  name: 'project-1',\n                },\n              })\n              await injectTestProjects({\n                test: {\n                  name: 'project-1',\n                },\n              })\n            },\n          },\n        ],\n      },\n    ],\n  }),\n  ).rejects.toThrow('Project name \"project-1\" is not unique. All projects should have unique names. Make sure your configuration is correct.')\n\n  await expect(() => throws({\n    projects: [\n      {\n        plugins: [\n          {\n            name: 'test',\n            async configureVitest({ injectTestProjects }) {\n              await injectTestProjects([\n                {\n                  test: {\n                    name: 'project-1',\n                  },\n                },\n                {\n                  test: {\n                    name: 'project-1',\n                  },\n                },\n              ])\n            },\n          },\n        ],\n      },\n    ],\n  }),\n  ).rejects.toThrow('Project name \"project-1\" is not unique. All projects should have unique names. Make sure your configuration is correct.')\n})\n\nasync function throws(cliOptions: TestUserConfig) {\n  await vitest(cliOptions)\n}\n"
  },
  {
    "path": "test/cli/test/console.test.ts",
    "content": "import { relative, resolve } from 'pathe'\nimport { expect, test } from 'vitest'\nimport { DefaultReporter } from 'vitest/node'\nimport { runInlineTests, runVitest } from '../../test-utils'\n\ntest('can run custom pools with Vitest', async () => {\n  const reporter = new DefaultReporter()\n  const vitest = await runVitest({\n    root: './fixtures/console',\n    reporters: [\n      {\n        onInit(ctx) {\n          reporter.onInit(ctx as any)\n        },\n        onUserConsoleLog(ctx) {\n          reporter.onUserConsoleLog(ctx)\n        },\n      },\n    ],\n  })\n  // removed the banner with version and timestamp\n  expect(vitest.stdout.split('\\n').slice(2).join('\\n')).toMatchInlineSnapshot(`\n    \"\n    stdout | trace.test.ts > logging to stdout\n    log with trace\n     ❯ trace.test.ts:4:11\n\n    stdout | trace.test.ts > logging to stdout\n    info with trace\n     ❯ trace.test.ts:5:11\n\n    stdout | trace.test.ts > logging to stdout\n    debug with trace\n     ❯ trace.test.ts:6:11\n\n    stdout | trace.test.ts > logging to stdout\n    { hello: 'from dir with trace' }\n     ❯ trace.test.ts:7:11\n\n    \"\n  `)\n  const stderrArray = vitest.stderr.split('\\n')\n  // remove stack trace\n  const stderr = stderrArray.slice(0, -14).join('\\n')\n  const stackStderr = stderrArray.slice(-14).join('\\n')\n  expect(stderr).toMatchInlineSnapshot(`\n    \"stderr | trace.test.ts > logging to stdout\n    warn with trace\n     ❯ trace.test.ts:8:11\n\n    stderr | trace.test.ts > logging to stdout\n    Assertion failed: assert with trace\n     ❯ trace.test.ts:9:11\n\n    stderr | trace.test.ts > logging to stdout\n    error with trace\n     ❯ trace.test.ts:10:11\n    \"\n  `)\n  // shows built-in stack because we don't intercept it, but doesn't show the new one\n  expect(stackStderr).toMatch('Trace: trace with trace')\n  expect(stackStderr).toMatch('trace.test.ts:11:11')\n  expect(stackStderr).toMatch('   at ')\n  expect(stackStderr).not.toMatch('❯ ')\n  if (process.platform !== 'win32') {\n    const root = resolve(process.cwd(), '../..')\n    const trace = stackStderr.replace(new RegExp(root, 'g'), '<root>').replace(/\\d+:\\d+/g, 'ln:cl').split('\\n').slice(0, 3).join('\\n')\n    expect(trace).toMatchInlineSnapshot(`\n      \"stderr | trace.test.ts > logging to stdout\n      Trace: trace with trace\n          at <root>/test/cli/fixtures/console/trace.test.ts:ln:cl\"\n    `)\n  }\n})\n\ntest('onConsoleLog receives the entity', async () => {\n  const logs: {\n    log: string\n    type: 'stderr' | 'stdout'\n    entity: { type: string; name: string } | undefined\n  }[] = []\n  const { stderr } = await runInlineTests(\n    {\n      'basic.test.ts': `\n    console.log('module')\n\n    describe('suite', () => {\n      beforeAll(() => {\n        console.log('suite')\n      })\n\n      test('test', () => {\n        console.log('test')\n      })\n    })\n    `,\n    },\n    {\n      globals: true,\n      onConsoleLog(log, type, entity) {\n        logs.push({\n          log,\n          type,\n          entity: entity\n            ? {\n                type: entity.type,\n                name: entity.type === 'module'\n                  ? relative(entity.project.config.root, entity.moduleId)\n                  : entity.name,\n              }\n            : undefined,\n        })\n      },\n    },\n  )\n  expect(stderr).toBe('')\n  expect(logs).toMatchInlineSnapshot(`\n    [\n      {\n        \"entity\": {\n          \"name\": \"basic.test.ts\",\n          \"type\": \"module\",\n        },\n        \"log\": \"module\n    \",\n        \"type\": \"stdout\",\n      },\n      {\n        \"entity\": {\n          \"name\": \"suite\",\n          \"type\": \"suite\",\n        },\n        \"log\": \"suite\n    \",\n        \"type\": \"stdout\",\n      },\n      {\n        \"entity\": {\n          \"name\": \"test\",\n          \"type\": \"test\",\n        },\n        \"log\": \"test\n    \",\n        \"type\": \"stdout\",\n      },\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/create-vitest.test.ts",
    "content": "import type { TestModule } from 'vitest/node'\nimport { expect, it, onTestFinished, vi } from 'vitest'\nimport { createVitest } from 'vitest/node'\n\nit(createVitest, async () => {\n  const onTestRunEnd = vi.fn()\n  const ctx = await createVitest('test', {\n    watch: false,\n    root: 'fixtures/create-vitest',\n    reporters: [\n      {\n        onTestRunEnd,\n      },\n    ],\n  })\n  onTestFinished(() => ctx.close())\n  const testFiles = await ctx.globTestSpecifications()\n  await ctx.runTestSpecifications(testFiles, false)\n\n  const [testModules, errors, reason] = onTestRunEnd.mock.calls[0]\n  expect(testModules).toHaveLength(1)\n\n  const testModule = testModules[0]\n  expect((testModule as TestModule).task?.name).toBe('basic.test.ts')\n  expect((testModule as TestModule).state()).toBe('passed')\n\n  expect(errors).toHaveLength(0)\n  expect(reason).toBe('passed')\n})\n"
  },
  {
    "path": "test/cli/test/custom-pool.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('can run custom pools with Vitest', async () => {\n  const vitest = await runVitest({\n    root: './fixtures/custom-pool',\n    reporters: [['default', { isTTY: false }]],\n  })\n\n  expect(vitest.stderr).toMatchInlineSnapshot(`\n    \"[pool] printing: options are respected\n    [pool] array option [ 1, 2, 3 ]\n    [pool] running tests for custom-pool-test in /fixtures/custom-pool/tests/custom-not-run.spec.ts\n    [pool] custom pool is closed!\n    \"\n  `)\n\n  expect(vitest.stdout).toContain('✓ |custom-pool-test| tests/custom-not-run.spec.ts')\n  expect(vitest.stdout).toContain('✓ |threads-pool-test| tests/custom-run.threads.spec.ts')\n  expect(vitest.stdout).toContain('Test Files  2 passed')\n  expect(vitest.stdout).toContain('Tests  2 passed')\n})\n"
  },
  {
    "path": "test/cli/test/custom-runner.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('extendTaskContext provides correct context.task.suite', async () => {\n  const vitest = await runVitest({\n    root: './fixtures/custom-runner',\n    reporters: [['default', { isTTY: false }]],\n  })\n  expect(vitest.stderr).toBe('')\n  expect(vitest.stdout).toContain('✓ custom-runner.test.ts')\n})\n"
  },
  {
    "path": "test/cli/test/detect-async-leaks.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runInlineTests as base } from '../../test-utils'\n\ntest('does not report leaks when disabled', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'packages/example/test/example.test.ts': `\n      test('leaks', () => {\n        setTimeout(() => {}, 100_000)\n        setInterval(() => {}, 100_000)\n        new Promise((resolve) => {})\n      })\n    `,\n  }, {\n    detectAsyncLeaks: false,\n  })\n\n  expect.soft(stdout).not.toContain('Leak')\n  expect.soft(stderr).toBe('')\n})\n\ntest('timeout', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'packages/example/test/example.test.ts': `\n      import source from '../src/source'\n\n      test('leak in test file', () => {\n        setTimeout(() => {}, 100_000)\n      })\n\n      test('leak in separate file', () => {\n        source()\n      })\n\n      test('not a leak', () => {\n        const timeout = setTimeout(() => {}, 100_000)\n        clearTimeout(timeout)\n      })\n    `,\n    'packages/example/src/source.ts': `\n      export default function execute() {\n        setTimeout(() => {}, 100_000)\n      }\n    `,\n  })\n\n  expect.soft(stdout).toContain('Leaks  2 leaks')\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Async Leaks 2 ⎯⎯⎯⎯⎯⎯⎯⎯\n\n    Timeout leaking in packages/example/test/example.test.ts\n      3|\n      4|       test('leak in test file', () => {\n      5|         setTimeout(() => {}, 100_000)\n       |         ^\n      6|       })\n      7|\n     ❯ packages/example/test/example.test.ts:5:9\n\n    Timeout leaking in packages/example/test/example.test.ts\n      1|\n      2|       export default function execute() {\n      3|         setTimeout(() => {}, 100_000)\n       |         ^\n      4|       }\n      5|\n     ❯ execute packages/example/src/source.ts:3:9\n     ❯ packages/example/test/example.test.ts:9:9\n\n    \"\n  `)\n})\n\ntest('interval', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'packages/example/test/example.test.ts': `\n      test('leak', () => {\n        setInterval(() => {}, 100_000)\n      })\n\n      test('not a leak', () => {\n        const interval = setInterval(() => {}, 100_000)\n        clearInterval(interval)\n      })\n    `,\n  })\n\n  expect.soft(stdout).toContain('Leaks  1 leak')\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Async Leaks 1 ⎯⎯⎯⎯⎯⎯⎯⎯\n\n    Timeout leaking in packages/example/test/example.test.ts\n      1|\n      2|       test('leak', () => {\n      3|         setInterval(() => {}, 100_000)\n       |         ^\n      4|       })\n      5|\n     ❯ packages/example/test/example.test.ts:3:9\n\n    \"\n  `)\n})\n\ntest('promise', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'packages/example/test/example.test.ts': `\n      test('leak', () => {\n        new Promise((resolve) => {})\n      })\n\n      test('nested leaks', () => {\n        new Promise((resolve) => {\n          new Promise((resolve2) => {})\n        })\n      })\n\n      test('not a leak', () => {\n        new Promise((resolve) => resolve())\n        new Promise((resolve, reject) => reject()).catch(() => {})\n      })\n    `,\n  })\n\n  expect.soft(stdout).toContain('Leaks  3 leaks')\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Async Leaks 3 ⎯⎯⎯⎯⎯⎯⎯⎯\n\n    PROMISE leaking in packages/example/test/example.test.ts\n      1|\n      2|       test('leak', () => {\n      3|         new Promise((resolve) => {})\n       |         ^\n      4|       })\n      5|\n     ❯ packages/example/test/example.test.ts:3:9\n\n    PROMISE leaking in packages/example/test/example.test.ts\n      5|\n      6|       test('nested leaks', () => {\n      7|         new Promise((resolve) => {\n       |         ^\n      8|           new Promise((resolve2) => {})\n      9|         })\n     ❯ packages/example/test/example.test.ts:7:9\n\n    PROMISE leaking in packages/example/test/example.test.ts\n      6|       test('nested leaks', () => {\n      7|         new Promise((resolve) => {\n      8|           new Promise((resolve2) => {})\n       |           ^\n      9|         })\n     10|       })\n     ❯ packages/example/test/example.test.ts:8:11\n     ❯ packages/example/test/example.test.ts:7:9\n\n    \"\n  `)\n})\n\ntest('fetch', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'packages/example/test/example.test.ts': `\n      test('not a leak', async () => {\n        await fetch('https://vitest.dev').then(response => response.text())\n      })\n    `,\n\n    'packages/example/test/example-2.test.ts': `\n      import { createServer } from \"node:http\";\n\n      let setConnected = () => {}\n      let waitConnection = new Promise(resolve => (setConnected = resolve))\n\n      beforeAll(async () => {\n        const server = createServer((_, res) => {\n          setConnected();\n          setTimeout(() => res.end(\"Hello after 10 seconds!\"), 10_000).unref();\n        });\n        await new Promise((resolve) => server.listen(5179, resolve));\n        return () => server.close();\n      });\n\n      test(\"is a leak\", async () => {\n        fetch('http://localhost:5179');\n        await waitConnection;\n      });\n    `,\n  })\n\n  expect.soft(stdout).toContain('Leaks  1 leak')\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Async Leaks 1 ⎯⎯⎯⎯⎯⎯⎯⎯\n\n    PROMISE leaking in packages/example/test/example-2.test.ts\n     15|\n     16|       test(\"is a leak\", async () => {\n     17|         fetch('http://localhost:5179');\n       |         ^\n     18|         await waitConnection;\n     19|       });\n     ❯ packages/example/test/example-2.test.ts:17:9\n\n    \"\n  `)\n})\n\ntest('fs handle', async () => {\n  const { stderr } = await runInlineTests({\n    'packages/example/test/example.test.ts': `\n      import { readFile } from 'node:fs'\n\n      test('leaking fs handle', () => {\n        readFile(import.meta.filename, () => {});\n      })\n    `,\n    'packages/example/test/example-2.test.ts': `\n      import { readFile } from 'node:fs'\n\n      test('not a leak', async () => {\n        await new Promise(resolve => readFile(import.meta.filename, () => { resolve() }));\n      })\n    `,\n  })\n\n  // This might be racy. Sometimes readFile fires two FSREQCALLBACK's, sometimes just one.\n  expect(stderr).toContain(`\\\nFSREQCALLBACK leaking in packages/example/test/example.test.ts\n  3|\n  4|       test('leaking fs handle', () => {\n  5|         readFile(import.meta.filename, () => {});\n   |         ^\n  6|       })\n  7|\n ❯ packages/example/test/example.test.ts:5:9\n`)\n})\n\ntest('http server', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'packages/example/test/example.test.ts': `\n      import { Server } from \"http\";\n\n      test('leak', async () => {\n        const app = new Server();\n        await new Promise(resolve => app.listen({ host: \"localhost\", port: 0 }, resolve));\n      })\n\n      test('not a leak', async () => {\n        const app = new Server();\n        await new Promise(resolve => app.listen({ host: \"localhost\", port: 0 }, resolve));\n        app.close()\n      })\n    `,\n  })\n\n  expect.soft(stdout).toContain('Leaks  1 leak')\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Async Leaks 1 ⎯⎯⎯⎯⎯⎯⎯⎯\n\n    TCPSERVERWRAP leaking in packages/example/test/example.test.ts\n      4|       test('leak', async () => {\n      5|         const app = new Server();\n      6|         await new Promise(resolve => app.listen({ host: \"localhost\", port:…\n       |                                          ^\n      7|       })\n      8|\n     ❯ packages/example/test/example.test.ts:6:42\n     ❯ packages/example/test/example.test.ts:6:15\n\n    \"\n  `)\n})\n\ntest('leak in project setup', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'packages/first/test/example-1.test.ts': `\n      import { test } from 'vitest';\n\n      test('leaking timeout', () => {\n        setTimeout(() => {}, 100_000)\n      })\n    `,\n    'packages/second/test/example-2.test.ts': `\n      import { test } from 'vitest';\n      import source from '../src/source'\n\n      test('leaking timeout', () => {\n        source()\n      })\n    `,\n    'packages/second/src/source.ts': `\n      export default function source() {\n        setTimeout(() => {}, 100_000)\n      }\n    `,\n  }, { projects: ['packages/*'] })\n\n  expect.soft(stdout).toContain('Leaks  2 leak')\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Async Leaks 2 ⎯⎯⎯⎯⎯⎯⎯⎯\n\n    Timeout leaking in packages/first/test/example-1.test.ts\n      3|\n      4|       test('leaking timeout', () => {\n      5|         setTimeout(() => {}, 100_000)\n       |         ^\n      6|       })\n      7|\n     ❯ test/example-1.test.ts:5:9\n\n    Timeout leaking in packages/second/test/example-2.test.ts\n      1|\n      2|       export default function source() {\n      3|         setTimeout(() => {}, 100_000)\n       |         ^\n      4|       }\n      5|\n     ❯ source src/source.ts:3:9\n     ❯ test/example-2.test.ts:6:9\n\n    \"\n  `)\n})\n\nasync function runInlineTests(...params: Parameters<typeof base>) {\n  const result = await base(params[0], { globals: true, detectAsyncLeaks: true, ...params[1] }, params[2])\n\n  return { ...result, stderr: trimWhitespace(result.stderr) }\n}\n\nfunction trimWhitespace(value: string) {\n  return value\n    .split('\\n')\n    .map(line => line.replace(/[ \\t]+$/g, ''))\n    .join('\\n')\n}\n"
  },
  {
    "path": "test/cli/test/dotted-files.test.ts",
    "content": "import { resolve } from 'node:path'\nimport { expect, it } from 'vitest'\nimport { runVitestCli } from '../../test-utils'\n\nit('run tests even though they are inside the .cache directory', async () => {\n  const { stderr } = await runVitestCli({\n    nodeOptions: { cwd: resolve(process.cwd(), 'fixtures/dotted-files/.cache/projects/test') },\n  }, '--no-watch')\n  expect(stderr).toBe('')\n})\n"
  },
  {
    "path": "test/cli/test/expect-soft.test.ts",
    "content": "import type { TestUserConfig } from 'vitest/node'\nimport { resolve } from 'node:path'\nimport { describe, expect, test, TestRunner } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ndescribe('expect.soft', () => {\n  const run = (config?: TestUserConfig) => runVitest({\n    root: resolve('./fixtures/expect-soft'),\n    include: ['expects/soft.test.ts'],\n    setupFiles: [],\n    testNamePattern: TestRunner.getCurrentTest()?.name,\n    testTimeout: 4000,\n    ...config,\n  }, ['soft'])\n\n  test('basic', async () => {\n    const { stderr } = await run()\n    expect.soft(stderr).toContain('AssertionError: expected 1 to be 2')\n    expect.soft(stderr).toContain('AssertionError: expected 2 to be 3')\n  })\n\n  test('promise', async () => {\n    const { stderr } = await run()\n    expect.soft(stderr).toContain('AssertionError: expected 2 to be 3')\n    expect.soft(stderr).toContain('AssertionError: expected 1 to be 2')\n  })\n\n  test('with expect', async () => {\n    const { stderr } = await run()\n    expect.soft(stderr).toContain('AssertionError: expected 1 to deeply equal 2')\n    expect.soft(stderr).toContain('AssertionError: expected 10 to deeply equal 20')\n    expect.soft(stderr).not.toContain('AssertionError: expected 2 to deeply equal 3')\n  })\n\n  test('with expect.extend', async () => {\n    const { stderr } = await run()\n    expect.soft(stderr).toContain('AssertionError: expected 1 to deeply equal 2')\n    expect.soft(stderr).toContain('Error: expected 3 to be divisible by 4')\n    expect.soft(stderr).toContain('AssertionError: expected 5 to deeply equal 6')\n  })\n\n  test('promise with expect.extend', async () => {\n    const { stderr } = await run()\n    expect.soft(stderr).toContain('Error: expected 2 to be 3')\n    expect.soft(stderr).toContain('Error: expected 4 to be 3')\n  })\n\n  test('promise rejection', async () => {\n    const { stderr } = await run()\n    // both assertions should execute (not abort after first rejection)\n    expect.soft(stderr).toContain('promise rejected \"Error: boom 1st\" instead of resolving')\n    expect.soft(stderr).toContain('promise rejected \"Error: boom 2nd\" instead of resolving')\n  })\n\n  test('promise resolved instead of rejecting', async () => {\n    const { stderr } = await run()\n    // both assertions should execute\n    expect.soft(stderr).toContain('promise resolved \"\\'value 1\\'\" instead of rejecting')\n    expect.soft(stderr).toContain('promise resolved \"\\'value 2\\'\" instead of rejecting')\n  })\n\n  test('passed', async () => {\n    const { stdout } = await run()\n    expect.soft(stdout).toContain('soft.test.ts > passed')\n  })\n\n  test('retry will passed', async () => {\n    const { stdout } = await run()\n    expect.soft(stdout).toContain('soft.test.ts > retry will passed')\n  })\n\n  test('retry will failed', async () => {\n    const { stderr } = await run()\n    expect.soft(stderr).toContain('AssertionError: expected 1 to be 4')\n    expect.soft(stderr).toContain('AssertionError: expected 2 to be 5')\n    expect.soft(stderr).toContain('AssertionError: expected 3 to be 4')\n    expect.soft(stderr).toContain('AssertionError: expected 4 to be 5')\n    expect.soft(stderr).toContain('4/4')\n  })\n})\n"
  },
  {
    "path": "test/cli/test/expect-task.test.ts",
    "content": "import { describe, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\nconst toMatchTest = /* ts */`\nexport function toMatchTest(this, expected) {\n  if (this.task?.name !== expected) {\n    return { pass: false, message: () => 'Active: \"' + this.task?.name + '\"\\\\nExpected: \"' + expected + '\"' }\n  }\n\n  return { pass: true, message: () => undefined }\n}\n\nexport function delay() {\n  return new Promise(resolve => {\n    setTimeout(resolve, 100)\n  })\n}\n`\n\nconst globals = /* ts */`\n  import { test, describe } from 'vitest'\n  import { delay, toMatchTest } from './to-match-test.ts'\n\n  expect.extend({ toMatchTest })\n\n  describe('tests', { /* options */ }, async () => {\n    test('first', async () => {\n      await delay()\n\n      expect('first').toMatchTest()\n    })\n\n    test('second', () => {\n      expect('second').toMatchTest()\n    })\n  })\n`\n\nconst globalImport = /* ts */`\n  import { test, describe, expect } from 'vitest'\n  import { delay, toMatchTest } from './to-match-test.ts'\n\n  expect.extend({ toMatchTest })\n\n  describe('tests', { /* options */ }, async () => {\n    test('first', async () => {\n      await delay()\n\n      expect('first').toMatchTest()\n    })\n\n    test('second', () => {\n      expect('second').toMatchTest()\n    })\n  })\n`\n\nconst fromContextGlobalExtend = /* ts */`\n  import { test, describe, expect } from 'vitest'\n  import { delay, toMatchTest } from './to-match-test.ts'\n\n  expect.extend({ toMatchTest })\n\n  describe('tests', { /* options */ }, async () => {\n    test('first', async ({ expect }) => {\n      await delay()\n\n      expect('first').toMatchTest()\n    })\n\n    test('second', ({ expect }) => {\n      expect('second').toMatchTest()\n    })\n  })\n`\n\nconst fromContextLocalExtend = /* ts */`\n  import { test, describe } from 'vitest'\n  import { delay, toMatchTest } from './to-match-test.ts'\n\n  describe('tests', { /* options */ }, async () => {\n    test('first', async ({ expect }) => {\n      expect.extend({ toMatchTest })\n\n      await delay()\n\n      expect('first').toMatchTest()\n    })\n\n    test('second', ({ expect }) => {\n      expect.extend({ toMatchTest })\n\n      expect('second').toMatchTest()\n    })\n  })\n`\n\nconst testBoundGlobalExtend = /* ts */`\n  import { test, describe, expect, createExpect } from 'vitest'\n  import { delay, toMatchTest } from './to-match-test.ts'\n\n  expect.extend({ toMatchTest })\n\n  describe('tests', { /* options */ }, async () => {\n    test('first', async ({ task }) => {\n      const expect = createExpect(task)\n\n      await delay()\n\n      expect('first').toMatchTest()\n    })\n\n    test('second', ({ task }) => {\n      const expect = createExpect(task)\n\n      expect('second').toMatchTest()\n    })\n  })\n`\n\nconst testBoundLocalExtend = /* ts */`\n  import { test, describe, createExpect } from 'vitest'\n  import { delay, toMatchTest } from './to-match-test.ts'\n\n  describe('tests', { /* options */ }, async () => {\n    test('first', async ({ task }) => {\n      const expect = createExpect(task)\n      expect.extend({ toMatchTest })\n\n      await delay()\n\n      expect('first').toMatchTest()\n    })\n\n    test('second', ({ task }) => {\n      const expect = createExpect(task)\n      expect.extend({ toMatchTest })\n\n      expect('second').toMatchTest()\n    })\n  })\n`\n\nfunction withConcurrency(test: string): string {\n  return test.replace('/* options */', 'concurrent: true')\n}\n\ndescribe('serial', { concurrent: true }, () => {\n  test.for([\n    {\n      name: 'globals',\n      test: globals,\n      options: { globals: true },\n    },\n    {\n      name: 'global import',\n      test: globalImport,\n    },\n    {\n      name: 'context destructuring & global extend',\n      test: fromContextGlobalExtend,\n    },\n    {\n      name: 'context destructuring & local extend',\n      test: fromContextLocalExtend,\n    },\n    {\n      name: 'test-bound extend & global extend',\n      test: testBoundGlobalExtend,\n    },\n    {\n      name: 'test-bound extend & local extend',\n      test: testBoundLocalExtend,\n    },\n  ] as const)('works with $name', async ({ options, test }, { task, expect }) => {\n    const { stdout, stderr } = await runInlineTests(\n      {\n        'basic.test.ts': test,\n        'to-match-test.ts': toMatchTest,\n      },\n      { reporters: ['tap'], ...options },\n      undefined,\n      task,\n    )\n\n    expect(stderr).toBe('')\n    expect(stdout.replace(/[\\d.]+ms/g, '<time>')).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..1\n      ok 1 - basic.test.ts # time=<time> {\n          1..1\n          ok 1 - tests # time=<time> {\n              1..2\n              ok 1 - first # time=<time>\n              ok 2 - second # time=<time>\n          }\n      }\n      \"\n    `)\n  })\n})\n\ndescribe('concurrent', { concurrent: true }, () => {\n  // when using globals or global `expect`, context is \"lost\" or not tracked in concurrent mode\n  test.for([\n    {\n      name: 'globals',\n      test: withConcurrency(globals),\n      options: { globals: true },\n    },\n    {\n      name: 'global import',\n      test: withConcurrency(globalImport),\n    },\n  ] as const)('fails with $name', async ({ options, test }, { task, expect }) => {\n    const { stdout, ctx } = await runInlineTests(\n      {\n        'basic.test.ts': test,\n        'to-match-test.ts': toMatchTest,\n      },\n      { reporters: ['tap'], ...options },\n      undefined,\n      task,\n    )\n\n    expect(\n      stdout\n        .replace(/[\\d.]+m?s/g, '<time>')\n        .replace(ctx!.config.root, '<root>')\n        .replace(/:\\d+:\\d+/, ':<line>:<column>'),\n    ).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..1\n      not ok 1 - basic.test.ts # time=<time> {\n          1..1\n          not ok 1 - tests # time=<time> {\n              1..2\n              not ok 1 - first # time=<time>\n                  ---\n                  error:\n                      name: \"Error\"\n                      message: \"Active: \\\\\"undefined\\\\\"\n      Expected: \\\\\"first\\\\\"\"\n                  at: \"<root>/basic.test.ts:<line>:<column>\"\n                  ...\n              ok 2 - second # time=<time>\n          }\n      }\n      \"\n    `)\n  })\n\n  test.for([\n    {\n      name: 'context destructuring & global extend',\n      test: withConcurrency(fromContextGlobalExtend),\n    },\n    {\n      name: 'context destructuring & local extend',\n      test: withConcurrency(fromContextLocalExtend),\n    },\n    {\n      name: 'test-bound extend & global extend',\n      test: withConcurrency(testBoundGlobalExtend),\n    },\n    {\n      name: 'test-bound extend & local extend',\n      test: withConcurrency(testBoundLocalExtend),\n    },\n  ])('works with $name', async ({ test }, { task, expect }) => {\n    const { stdout } = await runInlineTests(\n      {\n        'basic.test.ts': test,\n        'to-match-test.ts': toMatchTest,\n      },\n      { reporters: ['tap'] },\n      undefined,\n      task,\n    )\n\n    expect(stdout.replace(/[\\d.]+m?s/g, '<time>')).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..1\n      ok 1 - basic.test.ts # time=<time> {\n          1..1\n          ok 1 - tests # time=<time> {\n              1..2\n              ok 1 - first # time=<time>\n              ok 2 - second # time=<time>\n          }\n      }\n      \"\n    `)\n  })\n})\n"
  },
  {
    "path": "test/cli/test/fails.test.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\n\nimport { resolve } from 'pathe'\nimport { glob } from 'tinyglobby'\nimport { expect, it } from 'vitest'\nimport { runInlineTests, runVitest, ts } from '../../test-utils'\n\nconst root = resolve(import.meta.dirname, '../fixtures/fails')\nconst files = await glob(['**/*.test.{ts,js}'], { cwd: root, dot: true, expandDirectories: false })\n\nit.each(files)('should fail %s', async (file) => {\n  const { stderr } = await runVitest({ root }, [file])\n\n  expect(stderr).toBeTruthy()\n  const msg = String(stderr)\n    .split(/\\n/g)\n    .reverse()\n    .filter(i => i.includes('Error: ') && !i.includes('Command failed') && !i.includes('stackStr') && !i.includes('at runTest') && !i.includes('at runWithTimeout') && !i.includes('file:'))\n    .map(i => i.trim().replace(root, '<rootDir>'),\n    )\n    .join('\\n')\n  expect(msg).toMatchSnapshot()\n}, 30_000)\n\nit('should report coverage when \"coverage.reportOnFailure: true\" and tests fail', async () => {\n  const { stdout } = await runVitest({\n    root,\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      reportOnFailure: true,\n      reporter: ['text'],\n    },\n  }, [files[0]])\n\n  expect(stdout).toMatch('Coverage report from istanbul')\n})\n\nit('should not report coverage when \"coverage.reportOnFailure\" has default value and tests fail', async () => {\n  const { stdout } = await runVitest({\n    root,\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n      reporter: ['text'],\n    },\n  }, [files[0]])\n\n  expect(stdout).not.toMatch('Coverage report from istanbul')\n})\n\nit('prints a warning if the assertion is not awaited', async () => {\n  const { stderr, root, errorTree } = await runInlineTests({\n    'base.test.js': ts`\n    import { expect, test } from 'vitest';\n\n    test('single not awaited', () => {\n      expect(Promise.resolve(1)).resolves.toBe(1)\n    })\n\n    test('several not awaited', () => {\n      expect(Promise.resolve(1)).resolves.toBe(1)\n      expect(Promise.reject(1)).rejects.toBe(1)\n    })\n\n    test('not awaited and failed', () => {\n      expect(Promise.resolve(1)).resolves.toBe(1)\n      expect(1).toBe(2)\n    })\n\n    test('toMatchFileSnapshot not awaited', () => {\n      expect(1).toMatchFileSnapshot('./snapshot.txt')\n    })\n\n    test('soft + toMatchFileSnapshot not awaited', () => {\n      expect.soft(1).toMatchFileSnapshot('./snapshot-soft.txt')\n    })\n    `,\n  }, {\n    update: true,\n  })\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"base.test.js\": {\n        \"not awaited and failed\": [\n          \"expected 1 to be 2 // Object.is equality\",\n        ],\n        \"several not awaited\": \"passed\",\n        \"single not awaited\": \"passed\",\n        \"soft + toMatchFileSnapshot not awaited\": \"passed\",\n        \"toMatchFileSnapshot not awaited\": \"passed\",\n      },\n    }\n  `)\n  const warnings: string[] = []\n  const lines = stderr.split('\\n')\n  lines.forEach((line, index) => {\n    if (line.includes('Promise returned by')) {\n      warnings.push(lines.slice(index, index + 2).join('\\n').replace(`${root}/`, '<rootDir>/'))\n    }\n  })\n  expect(warnings).toMatchInlineSnapshot(`\n    [\n      \"Promise returned by \\`expect(actual).resolves.toBe(expected)\\` was not awaited. Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in the next Vitest major. Please remember to await the assertion.\n        at <rootDir>/base.test.js:5:33\",\n      \"Promise returned by \\`expect(actual).rejects.toBe(expected)\\` was not awaited. Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in the next Vitest major. Please remember to await the assertion.\n        at <rootDir>/base.test.js:10:32\",\n      \"Promise returned by \\`expect(actual).resolves.toBe(expected)\\` was not awaited. Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in the next Vitest major. Please remember to await the assertion.\n        at <rootDir>/base.test.js:9:33\",\n      \"Promise returned by \\`expect(actual).resolves.toBe(expected)\\` was not awaited. Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in the next Vitest major. Please remember to await the assertion.\n        at <rootDir>/base.test.js:14:33\",\n      \"Promise returned by \\`expect(actual).toMatchFileSnapshot(expected)\\` was not awaited. Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in the next Vitest major. Please remember to await the assertion.\n        at <rootDir>/base.test.js:19:17\",\n      \"Promise returned by \\`expect.soft(actual).toMatchFileSnapshot(expected)\\` was not awaited. Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in the next Vitest major. Please remember to await the assertion.\n        at <rootDir>/base.test.js:23:22\",\n    ]\n  `)\n})\n\nit('no async tracking after then/catch/finally', async () => {\n  // resolve + then/catch/finally\n  // rejects + then/catch/finally\n  // expect.poll + then/catch/finally\n  const { stderr, errorTree } = await runInlineTests({\n    'await.test.js': ts`\n      import { expect, test } from 'vitest';\n\n      test('resolves + then', async () => {\n        await expect(Promise.resolve(1)).resolves.toBe(1).then()\n      })\n\n      test('resolves + catch', async () => {\n        await expect(Promise.resolve(1)).resolves.toBe(1).catch()\n      })\n\n      test('resolves + finally', async () => {\n        await expect(Promise.resolve(1)).resolves.toBe(1).finally()\n      })\n\n      test('rejects + then', async () => {\n        await expect(Promise.reject(1)).rejects.toBe(1).then()\n      })\n\n      test('rejects + catch', async () => {\n        await expect(Promise.reject(1)).rejects.toBe(1).catch()\n      })\n\n      test('rejects + finally', async () => {\n        await expect(Promise.reject(1)).rejects.toBe(1).finally()\n      })\n\n      test('expect.poll + then', async () => {\n        await expect.poll(() => 2).toBe(2).then()\n      })\n\n      test('expect.poll + catch', async () => {\n        await expect.poll(() => 2).toBe(2).catch()\n      })\n\n      test('expect.poll + finally', async () => {\n        await expect.poll(() => 2).toBe(2).finally()\n      })\n    `,\n    'hang.test.js': ts`\n      import { expect, test } from 'vitest';\n\n      test('resolves + then', async () => {\n        expect(Promise.resolve(1)).resolves.toBe(1).then()\n      })\n\n      test('resolves + catch', async () => {\n        expect(Promise.resolve(1)).resolves.toBe(1).catch()\n      })\n\n      test('resolves + finally', async () => {\n        expect(Promise.resolve(1)).resolves.toBe(1).finally()\n      })\n\n      test('rejects + then', async () => {\n        expect(Promise.reject(1)).rejects.toBe(1).then()\n      })\n\n      test('rejects + catch', async () => {\n        expect(Promise.reject(1)).rejects.toBe(1).catch()\n      })\n\n      test('rejects + finally', async () => {\n        expect(Promise.reject(1)).rejects.toBe(1).finally()\n      })\n\n      test('expect.poll + then', async () => {\n        expect.poll(() => 2).toBe(2).then()\n      })\n\n      test('expect.poll + catch', async () => {\n        expect.poll(() => 2).toBe(2).catch()\n      })\n\n      test('expect.poll + finally', async () => {\n        expect.poll(() => 2).toBe(2).finally()\n      })\n    `,\n  })\n  expect(stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"await.test.js\": {\n        \"expect.poll + catch\": \"passed\",\n        \"expect.poll + finally\": \"passed\",\n        \"expect.poll + then\": \"passed\",\n        \"rejects + catch\": \"passed\",\n        \"rejects + finally\": \"passed\",\n        \"rejects + then\": \"passed\",\n        \"resolves + catch\": \"passed\",\n        \"resolves + finally\": \"passed\",\n        \"resolves + then\": \"passed\",\n      },\n      \"hang.test.js\": {\n        \"expect.poll + catch\": \"passed\",\n        \"expect.poll + finally\": \"passed\",\n        \"expect.poll + then\": \"passed\",\n        \"rejects + catch\": \"passed\",\n        \"rejects + finally\": \"passed\",\n        \"rejects + then\": \"passed\",\n        \"resolves + catch\": \"passed\",\n        \"resolves + finally\": \"passed\",\n        \"resolves + then\": \"passed\",\n      },\n    }\n  `)\n})\n\nit('prints a warning if the assertion is not awaited in the browser mode', async () => {\n  const { stderr } = await runInlineTests({\n    'base.test.js': ts`\n    import { expect, test } from 'vitest';\n\n    test('single not awaited', () => {\n      expect(Promise.resolve(1)).resolves.toBe(1)\n    })\n    `,\n  }, {\n    browser: {\n      enabled: true,\n      instances: [{ browser: 'chromium' }],\n      provider: playwright(),\n      headless: true,\n    },\n  })\n  expect(stderr).toContain('Promise returned by \\`expect(actual).resolves.toBe(expected)\\` was not awaited')\n  expect(stderr).toContain('base.test.js:5:33')\n})\n\nit('reports test file if it failed to load', async () => {\n  const hooks: string[] = []\n  await runInlineTests({\n    'basic.test.js': `throw new Error('fail')`,\n  }, {\n    reporters: [\n      'default',\n      {\n        onTestModuleQueued(testModule) {\n          hooks.push(`onTestModuleQueued:${testModule.relativeModuleId}`)\n        },\n        onTestModuleStart(testModule) {\n          hooks.push(`onTestModuleStart:${testModule.relativeModuleId}`)\n        },\n        onTestModuleCollected(testModule) {\n          hooks.push(`onTestModuleCollected:${testModule.relativeModuleId}`)\n        },\n        onTestModuleEnd(testModule) {\n          hooks.push(`onTestModuleEnd:${testModule.relativeModuleId}`)\n        },\n      },\n    ],\n  })\n\n  expect(hooks).toMatchInlineSnapshot(`\n    [\n      \"onTestModuleQueued:basic.test.js\",\n      \"onTestModuleCollected:basic.test.js\",\n      \"onTestModuleStart:basic.test.js\",\n      \"onTestModuleEnd:basic.test.js\",\n    ]\n  `)\n})\n\nit('should warn if retry.condition is a function in config', async () => {\n  const { stderr } = await runVitest({\n    root: 'fixtures/retry-config',\n  })\n\n  expect(stderr).toContain('Warning: retry.condition function cannot be used inside a config file.')\n})\n"
  },
  {
    "path": "test/cli/test/fixtures/reporters/html/all-passing-or-skipped/assets/index-BUCFJtth.js",
    "content": "(function(){const t=document.createElement(\"link\").relList;if(t&&t.supports&&t.supports(\"modulepreload\"))return;for(const s of document.querySelectorAll('link[rel=\"modulepreload\"]'))o(s);new MutationObserver(s=>{for(const c of s)if(c.type===\"childList\")for(const f of c.addedNodes)f.tagName===\"LINK\"&&f.rel===\"modulepreload\"&&o(f)}).observe(document,{childList:!0,subtree:!0});function r(s){const c={};return s.integrity&&(c.integrity=s.integrity),s.referrerPolicy&&(c.referrerPolicy=s.referrerPolicy),s.crossOrigin===\"use-credentials\"?c.credentials=\"include\":s.crossOrigin===\"anonymous\"?c.credentials=\"omit\":c.credentials=\"same-origin\",c}function o(s){if(s.ep)return;s.ep=!0;const c=r(s);fetch(s.href,c)}})();/**\n* @vue/shared v3.5.25\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/function Fh(e){const t=Object.create(null);for(const r of e.split(\",\"))t[r]=1;return r=>r in t}const vt={},Rs=[],Xr=()=>{},C0=()=>!1,$u=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Hh=e=>e.startsWith(\"onUpdate:\"),on=Object.assign,Bh=(e,t)=>{const r=e.indexOf(t);r>-1&&e.splice(r,1)},$S=Object.prototype.hasOwnProperty,wt=(e,t)=>$S.call(e,t),Ze=Array.isArray,$s=e=>Oa(e)===\"[object Map]\",Iu=e=>Oa(e)===\"[object Set]\",Bm=e=>Oa(e)===\"[object Date]\",et=e=>typeof e==\"function\",Ht=e=>typeof e==\"string\",Pr=e=>typeof e==\"symbol\",kt=e=>e!==null&&typeof e==\"object\",E0=e=>(kt(e)||et(e))&&et(e.then)&&et(e.catch),A0=Object.prototype.toString,Oa=e=>A0.call(e),IS=e=>Oa(e).slice(8,-1),L0=e=>Oa(e)===\"[object Object]\",Du=e=>Ht(e)&&e!==\"NaN\"&&e[0]!==\"-\"&&\"\"+parseInt(e,10)===e,Xl=Fh(\",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted\"),zu=e=>{const t=Object.create(null);return(r=>t[r]||(t[r]=e(r)))},DS=/-\\w/g,sr=zu(e=>e.replace(DS,t=>t.slice(1).toUpperCase())),zS=/\\B([A-Z])/g,Ai=zu(e=>e.replace(zS,\"-$1\").toLowerCase()),Fu=zu(e=>e.charAt(0).toUpperCase()+e.slice(1)),qc=zu(e=>e?`on${Fu(e)}`:\"\"),Gn=(e,t)=>!Object.is(e,t),jc=(e,...t)=>{for(let r=0;r<e.length;r++)e[r](...t)},M0=(e,t,r,o=!1)=>{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:o,value:r})},Wh=e=>{const t=parseFloat(e);return isNaN(t)?e:t},N0=e=>{const t=Ht(e)?Number(e):NaN;return isNaN(t)?e:t};let Wm;const Hu=()=>Wm||(Wm=typeof globalThis<\"u\"?globalThis:typeof self<\"u\"?self:typeof window<\"u\"?window:typeof global<\"u\"?global:{});function zt(e){if(Ze(e)){const t={};for(let r=0;r<e.length;r++){const o=e[r],s=Ht(o)?WS(o):zt(o);if(s)for(const c in s)t[c]=s[c]}return t}else if(Ht(e)||kt(e))return e}const FS=/;(?![^(]*\\))/g,HS=/:([^]+)/,BS=/\\/\\*[^]*?\\*\\//g;function WS(e){const t={};return e.replace(BS,\"\").split(FS).forEach(r=>{if(r){const o=r.split(HS);o.length>1&&(t[o[0].trim()]=o[1].trim())}}),t}function ot(e){let t=\"\";if(Ht(e))t=e;else if(Ze(e))for(let r=0;r<e.length;r++){const o=ot(e[r]);o&&(t+=o+\" \")}else if(kt(e))for(const r in e)e[r]&&(t+=r+\" \");return t.trim()}function qS(e){if(!e)return null;let{class:t,style:r}=e;return t&&!Ht(t)&&(e.class=ot(t)),r&&(e.style=zt(r)),e}const jS=\"itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly\",US=Fh(jS);function O0(e){return!!e||e===\"\"}function VS(e,t){if(e.length!==t.length)return!1;let r=!0;for(let o=0;r&&o<e.length;o++)r=Bu(e[o],t[o]);return r}function Bu(e,t){if(e===t)return!0;let r=Bm(e),o=Bm(t);if(r||o)return r&&o?e.getTime()===t.getTime():!1;if(r=Pr(e),o=Pr(t),r||o)return e===t;if(r=Ze(e),o=Ze(t),r||o)return r&&o?VS(e,t):!1;if(r=kt(e),o=kt(t),r||o){if(!r||!o)return!1;const s=Object.keys(e).length,c=Object.keys(t).length;if(s!==c)return!1;for(const f in e){const d=e.hasOwnProperty(f),h=t.hasOwnProperty(f);if(d&&!h||!d&&h||!Bu(e[f],t[f]))return!1}}return String(e)===String(t)}function P0(e,t){return e.findIndex(r=>Bu(r,t))}const R0=e=>!!(e&&e.__v_isRef===!0),Re=e=>Ht(e)?e:e==null?\"\":Ze(e)||kt(e)&&(e.toString===A0||!et(e.toString))?R0(e)?Re(e.value):JSON.stringify(e,$0,2):String(e),$0=(e,t)=>R0(t)?$0(e,t.value):$s(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((r,[o,s],c)=>(r[fd(o,c)+\" =>\"]=s,r),{})}:Iu(t)?{[`Set(${t.size})`]:[...t.values()].map(r=>fd(r))}:Pr(t)?fd(t):kt(t)&&!Ze(t)&&!L0(t)?String(t):t,fd=(e,t=\"\")=>{var r;return Pr(e)?`Symbol(${(r=e.description)!=null?r:t})`:e};/**\n* @vue/reactivity v3.5.25\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/let bn;class GS{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=bn,!t&&bn&&(this.index=(bn.scopes||(bn.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,r;if(this.scopes)for(t=0,r=this.scopes.length;t<r;t++)this.scopes[t].pause();for(t=0,r=this.effects.length;t<r;t++)this.effects[t].pause()}}resume(){if(this._active&&this._isPaused){this._isPaused=!1;let t,r;if(this.scopes)for(t=0,r=this.scopes.length;t<r;t++)this.scopes[t].resume();for(t=0,r=this.effects.length;t<r;t++)this.effects[t].resume()}}run(t){if(this._active){const r=bn;try{return bn=this,t()}finally{bn=r}}}on(){++this._on===1&&(this.prevScope=bn,bn=this)}off(){this._on>0&&--this._on===0&&(bn=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let r,o;for(r=0,o=this.effects.length;r<o;r++)this.effects[r].stop();for(this.effects.length=0,r=0,o=this.cleanups.length;r<o;r++)this.cleanups[r]();if(this.cleanups.length=0,this.scopes){for(r=0,o=this.scopes.length;r<o;r++)this.scopes[r].stop(!0);this.scopes.length=0}if(!this.detached&&this.parent&&!t){const s=this.parent.scopes.pop();s&&s!==this&&(this.parent.scopes[this.index]=s,s.index=this.index)}this.parent=void 0}}}function I0(){return bn}function KS(e,t=!1){bn&&bn.cleanups.push(e)}let Tt;const dd=new WeakSet;class D0{constructor(t){this.fn=t,this.deps=void 0,this.depsTail=void 0,this.flags=5,this.next=void 0,this.cleanup=void 0,this.scheduler=void 0,bn&&bn.active&&bn.effects.push(this)}pause(){this.flags|=64}resume(){this.flags&64&&(this.flags&=-65,dd.has(this)&&(dd.delete(this),this.trigger()))}notify(){this.flags&2&&!(this.flags&32)||this.flags&8||F0(this)}run(){if(!(this.flags&1))return this.fn();this.flags|=2,qm(this),H0(this);const t=Tt,r=Nr;Tt=this,Nr=!0;try{return this.fn()}finally{B0(this),Tt=t,Nr=r,this.flags&=-3}}stop(){if(this.flags&1){for(let t=this.deps;t;t=t.nextDep)Uh(t);this.deps=this.depsTail=void 0,qm(this),this.onStop&&this.onStop(),this.flags&=-2}}trigger(){this.flags&64?dd.add(this):this.scheduler?this.scheduler():this.runIfDirty()}runIfDirty(){jd(this)&&this.run()}get dirty(){return jd(this)}}let z0=0,Yl,Zl;function F0(e,t=!1){if(e.flags|=8,t){e.next=Zl,Zl=e;return}e.next=Yl,Yl=e}function qh(){z0++}function jh(){if(--z0>0)return;if(Zl){let t=Zl;for(Zl=void 0;t;){const r=t.next;t.next=void 0,t.flags&=-9,t=r}}let e;for(;Yl;){let t=Yl;for(Yl=void 0;t;){const r=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(o){e||(e=o)}t=r}}if(e)throw e}function H0(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function B0(e){let t,r=e.depsTail,o=r;for(;o;){const s=o.prevDep;o.version===-1?(o===r&&(r=s),Uh(o),XS(o)):t=o,o.dep.activeLink=o.prevActiveLink,o.prevActiveLink=void 0,o=s}e.deps=t,e.depsTail=r}function jd(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(W0(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function W0(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===aa)||(e.globalVersion=aa,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!jd(e))))return;e.flags|=2;const t=e.dep,r=Tt,o=Nr;Tt=e,Nr=!0;try{H0(e);const s=e.fn(e._value);(t.version===0||Gn(s,e._value))&&(e.flags|=128,e._value=s,t.version++)}catch(s){throw t.version++,s}finally{Tt=r,Nr=o,B0(e),e.flags&=-3}}function Uh(e,t=!1){const{dep:r,prevSub:o,nextSub:s}=e;if(o&&(o.nextSub=s,e.prevSub=void 0),s&&(s.prevSub=o,e.nextSub=void 0),r.subs===e&&(r.subs=o,!o&&r.computed)){r.computed.flags&=-5;for(let c=r.computed.deps;c;c=c.nextDep)Uh(c,!0)}!t&&!--r.sc&&r.map&&r.map.delete(r.key)}function XS(e){const{prevDep:t,nextDep:r}=e;t&&(t.nextDep=r,e.prevDep=void 0),r&&(r.prevDep=t,e.nextDep=void 0)}let Nr=!0;const q0=[];function Si(){q0.push(Nr),Nr=!1}function _i(){const e=q0.pop();Nr=e===void 0?!0:e}function qm(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const r=Tt;Tt=void 0;try{t()}finally{Tt=r}}}let aa=0;class YS{constructor(t,r){this.sub=t,this.dep=r,this.version=r.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Wu{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!Tt||!Nr||Tt===this.computed)return;let r=this.activeLink;if(r===void 0||r.sub!==Tt)r=this.activeLink=new YS(Tt,this),Tt.deps?(r.prevDep=Tt.depsTail,Tt.depsTail.nextDep=r,Tt.depsTail=r):Tt.deps=Tt.depsTail=r,j0(r);else if(r.version===-1&&(r.version=this.version,r.nextDep)){const o=r.nextDep;o.prevDep=r.prevDep,r.prevDep&&(r.prevDep.nextDep=o),r.prevDep=Tt.depsTail,r.nextDep=void 0,Tt.depsTail.nextDep=r,Tt.depsTail=r,Tt.deps===r&&(Tt.deps=o)}return r}trigger(t){this.version++,aa++,this.notify(t)}notify(t){qh();try{for(let r=this.subs;r;r=r.prevSub)r.sub.notify()&&r.sub.dep.notify()}finally{jh()}}}function j0(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let o=t.deps;o;o=o.nextDep)j0(o)}const r=e.dep.subs;r!==e&&(e.prevSub=r,r&&(r.nextSub=e)),e.dep.subs=e}}const iu=new WeakMap,qo=Symbol(\"\"),Ud=Symbol(\"\"),ca=Symbol(\"\");function wn(e,t,r){if(Nr&&Tt){let o=iu.get(e);o||iu.set(e,o=new Map);let s=o.get(r);s||(o.set(r,s=new Wu),s.map=o,s.key=r),s.track()}}function bi(e,t,r,o,s,c){const f=iu.get(e);if(!f){aa++;return}const d=h=>{h&&h.trigger()};if(qh(),t===\"clear\")f.forEach(d);else{const h=Ze(e),p=h&&Du(r);if(h&&r===\"length\"){const g=Number(o);f.forEach((v,b)=>{(b===\"length\"||b===ca||!Pr(b)&&b>=g)&&d(v)})}else switch((r!==void 0||f.has(void 0))&&d(f.get(r)),p&&d(f.get(ca)),t){case\"add\":h?p&&d(f.get(\"length\")):(d(f.get(qo)),$s(e)&&d(f.get(Ud)));break;case\"delete\":h||(d(f.get(qo)),$s(e)&&d(f.get(Ud)));break;case\"set\":$s(e)&&d(f.get(qo));break}}jh()}function ZS(e,t){const r=iu.get(e);return r&&r.get(t)}function _s(e){const t=mt(e);return t===e?t:(wn(t,\"iterate\",ca),or(e)?t:t.map(Rr))}function qu(e){return wn(e=mt(e),\"iterate\",ca),e}function Yi(e,t){return Ti(e)?jo(e)?Ks(Rr(t)):Ks(t):Rr(t)}const JS={__proto__:null,[Symbol.iterator](){return hd(this,Symbol.iterator,e=>Yi(this,e))},concat(...e){return _s(this).concat(...e.map(t=>Ze(t)?_s(t):t))},entries(){return hd(this,\"entries\",e=>(e[1]=Yi(this,e[1]),e))},every(e,t){return fi(this,\"every\",e,t,void 0,arguments)},filter(e,t){return fi(this,\"filter\",e,t,r=>r.map(o=>Yi(this,o)),arguments)},find(e,t){return fi(this,\"find\",e,t,r=>Yi(this,r),arguments)},findIndex(e,t){return fi(this,\"findIndex\",e,t,void 0,arguments)},findLast(e,t){return fi(this,\"findLast\",e,t,r=>Yi(this,r),arguments)},findLastIndex(e,t){return fi(this,\"findLastIndex\",e,t,void 0,arguments)},forEach(e,t){return fi(this,\"forEach\",e,t,void 0,arguments)},includes(...e){return pd(this,\"includes\",e)},indexOf(...e){return pd(this,\"indexOf\",e)},join(e){return _s(this).join(e)},lastIndexOf(...e){return pd(this,\"lastIndexOf\",e)},map(e,t){return fi(this,\"map\",e,t,void 0,arguments)},pop(){return Dl(this,\"pop\")},push(...e){return Dl(this,\"push\",e)},reduce(e,...t){return jm(this,\"reduce\",e,t)},reduceRight(e,...t){return jm(this,\"reduceRight\",e,t)},shift(){return Dl(this,\"shift\")},some(e,t){return fi(this,\"some\",e,t,void 0,arguments)},splice(...e){return Dl(this,\"splice\",e)},toReversed(){return _s(this).toReversed()},toSorted(e){return _s(this).toSorted(e)},toSpliced(...e){return _s(this).toSpliced(...e)},unshift(...e){return Dl(this,\"unshift\",e)},values(){return hd(this,\"values\",e=>Yi(this,e))}};function hd(e,t,r){const o=qu(e),s=o[t]();return o!==e&&!or(e)&&(s._next=s.next,s.next=()=>{const c=s._next();return c.done||(c.value=r(c.value)),c}),s}const QS=Array.prototype;function fi(e,t,r,o,s,c){const f=qu(e),d=f!==e&&!or(e),h=f[t];if(h!==QS[t]){const v=h.apply(e,c);return d?Rr(v):v}let p=r;f!==e&&(d?p=function(v,b){return r.call(this,Yi(e,v),b,e)}:r.length>2&&(p=function(v,b){return r.call(this,v,b,e)}));const g=h.call(f,p,o);return d&&s?s(g):g}function jm(e,t,r,o){const s=qu(e);let c=r;return s!==e&&(or(e)?r.length>3&&(c=function(f,d,h){return r.call(this,f,d,h,e)}):c=function(f,d,h){return r.call(this,f,Yi(e,d),h,e)}),s[t](c,...o)}function pd(e,t,r){const o=mt(e);wn(o,\"iterate\",ca);const s=o[t](...r);return(s===-1||s===!1)&&ju(r[0])?(r[0]=mt(r[0]),o[t](...r)):s}function Dl(e,t,r=[]){Si(),qh();const o=mt(e)[t].apply(e,r);return jh(),_i(),o}const e_=Fh(\"__proto__,__v_isRef,__isVue\"),U0=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!==\"arguments\"&&e!==\"caller\").map(e=>Symbol[e]).filter(Pr));function t_(e){Pr(e)||(e=String(e));const t=mt(this);return wn(t,\"has\",e),t.hasOwnProperty(e)}class V0{constructor(t=!1,r=!1){this._isReadonly=t,this._isShallow=r}get(t,r,o){if(r===\"__v_skip\")return t.__v_skip;const s=this._isReadonly,c=this._isShallow;if(r===\"__v_isReactive\")return!s;if(r===\"__v_isReadonly\")return s;if(r===\"__v_isShallow\")return c;if(r===\"__v_raw\")return o===(s?c?f_:Y0:c?X0:K0).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(o)?t:void 0;const f=Ze(t);if(!s){let h;if(f&&(h=JS[r]))return h;if(r===\"hasOwnProperty\")return t_}const d=Reflect.get(t,r,Mt(t)?t:o);if((Pr(r)?U0.has(r):e_(r))||(s||wn(t,\"get\",r),c))return d;if(Mt(d)){const h=f&&Du(r)?d:d.value;return s&&kt(h)?Gs(h):h}return kt(d)?s?Gs(d):ir(d):d}}class G0 extends V0{constructor(t=!1){super(!1,t)}set(t,r,o,s){let c=t[r];const f=Ze(t)&&Du(r);if(!this._isShallow){const p=Ti(c);if(!or(o)&&!Ti(o)&&(c=mt(c),o=mt(o)),!f&&Mt(c)&&!Mt(o))return p||(c.value=o),!0}const d=f?Number(r)<t.length:wt(t,r),h=Reflect.set(t,r,o,Mt(t)?t:s);return t===mt(s)&&(d?Gn(o,c)&&bi(t,\"set\",r,o):bi(t,\"add\",r,o)),h}deleteProperty(t,r){const o=wt(t,r);t[r];const s=Reflect.deleteProperty(t,r);return s&&o&&bi(t,\"delete\",r,void 0),s}has(t,r){const o=Reflect.has(t,r);return(!Pr(r)||!U0.has(r))&&wn(t,\"has\",r),o}ownKeys(t){return wn(t,\"iterate\",Ze(t)?\"length\":qo),Reflect.ownKeys(t)}}class n_ extends V0{constructor(t=!1){super(!0,t)}set(t,r){return!0}deleteProperty(t,r){return!0}}const r_=new G0,i_=new n_,o_=new G0(!0);const Vd=e=>e,Tc=e=>Reflect.getPrototypeOf(e);function s_(e,t,r){return function(...o){const s=this.__v_raw,c=mt(s),f=$s(c),d=e===\"entries\"||e===Symbol.iterator&&f,h=e===\"keys\"&&f,p=s[e](...o),g=r?Vd:t?Ks:Rr;return!t&&wn(c,\"iterate\",h?Ud:qo),{next(){const{value:v,done:b}=p.next();return b?{value:v,done:b}:{value:d?[g(v[0]),g(v[1])]:g(v),done:b}},[Symbol.iterator](){return this}}}}function Cc(e){return function(...t){return e===\"delete\"?!1:e===\"clear\"?void 0:this}}function l_(e,t){const r={get(s){const c=this.__v_raw,f=mt(c),d=mt(s);e||(Gn(s,d)&&wn(f,\"get\",s),wn(f,\"get\",d));const{has:h}=Tc(f),p=t?Vd:e?Ks:Rr;if(h.call(f,s))return p(c.get(s));if(h.call(f,d))return p(c.get(d));c!==f&&c.get(s)},get size(){const s=this.__v_raw;return!e&&wn(mt(s),\"iterate\",qo),s.size},has(s){const c=this.__v_raw,f=mt(c),d=mt(s);return e||(Gn(s,d)&&wn(f,\"has\",s),wn(f,\"has\",d)),s===d?c.has(s):c.has(s)||c.has(d)},forEach(s,c){const f=this,d=f.__v_raw,h=mt(d),p=t?Vd:e?Ks:Rr;return!e&&wn(h,\"iterate\",qo),d.forEach((g,v)=>s.call(c,p(g),p(v),f))}};return on(r,e?{add:Cc(\"add\"),set:Cc(\"set\"),delete:Cc(\"delete\"),clear:Cc(\"clear\")}:{add(s){!t&&!or(s)&&!Ti(s)&&(s=mt(s));const c=mt(this);return Tc(c).has.call(c,s)||(c.add(s),bi(c,\"add\",s,s)),this},set(s,c){!t&&!or(c)&&!Ti(c)&&(c=mt(c));const f=mt(this),{has:d,get:h}=Tc(f);let p=d.call(f,s);p||(s=mt(s),p=d.call(f,s));const g=h.call(f,s);return f.set(s,c),p?Gn(c,g)&&bi(f,\"set\",s,c):bi(f,\"add\",s,c),this},delete(s){const c=mt(this),{has:f,get:d}=Tc(c);let h=f.call(c,s);h||(s=mt(s),h=f.call(c,s)),d&&d.call(c,s);const p=c.delete(s);return h&&bi(c,\"delete\",s,void 0),p},clear(){const s=mt(this),c=s.size!==0,f=s.clear();return c&&bi(s,\"clear\",void 0,void 0),f}}),[\"keys\",\"values\",\"entries\",Symbol.iterator].forEach(s=>{r[s]=s_(s,e,t)}),r}function Vh(e,t){const r=l_(e,t);return(o,s,c)=>s===\"__v_isReactive\"?!e:s===\"__v_isReadonly\"?e:s===\"__v_raw\"?o:Reflect.get(wt(r,s)&&s in o?r:o,s,c)}const a_={get:Vh(!1,!1)},c_={get:Vh(!1,!0)},u_={get:Vh(!0,!1)};const K0=new WeakMap,X0=new WeakMap,Y0=new WeakMap,f_=new WeakMap;function d_(e){switch(e){case\"Object\":case\"Array\":return 1;case\"Map\":case\"Set\":case\"WeakMap\":case\"WeakSet\":return 2;default:return 0}}function h_(e){return e.__v_skip||!Object.isExtensible(e)?0:d_(IS(e))}function ir(e){return Ti(e)?e:Kh(e,!1,r_,a_,K0)}function Gh(e){return Kh(e,!1,o_,c_,X0)}function Gs(e){return Kh(e,!0,i_,u_,Y0)}function Kh(e,t,r,o,s){if(!kt(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const c=h_(e);if(c===0)return e;const f=s.get(e);if(f)return f;const d=new Proxy(e,c===2?o:r);return s.set(e,d),d}function jo(e){return Ti(e)?jo(e.__v_raw):!!(e&&e.__v_isReactive)}function Ti(e){return!!(e&&e.__v_isReadonly)}function or(e){return!!(e&&e.__v_isShallow)}function ju(e){return e?!!e.__v_raw:!1}function mt(e){const t=e&&e.__v_raw;return t?mt(t):e}function Uu(e){return!wt(e,\"__v_skip\")&&Object.isExtensible(e)&&M0(e,\"__v_skip\",!0),e}const Rr=e=>kt(e)?ir(e):e,Ks=e=>kt(e)?Gs(e):e;function Mt(e){return e?e.__v_isRef===!0:!1}function Ge(e){return Z0(e,!1)}function Ft(e){return Z0(e,!0)}function Z0(e,t){return Mt(e)?e:new p_(e,t)}class p_{constructor(t,r){this.dep=new Wu,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=r?t:mt(t),this._value=r?t:Rr(t),this.__v_isShallow=r}get value(){return this.dep.track(),this._value}set value(t){const r=this._rawValue,o=this.__v_isShallow||or(t)||Ti(t);t=o?t:mt(t),Gn(t,r)&&(this._rawValue=t,this._value=o?t:Rr(t),this.dep.trigger())}}function K(e){return Mt(e)?e.value:e}function Xt(e){return et(e)?e():K(e)}const g_={get:(e,t,r)=>t===\"__v_raw\"?e:K(Reflect.get(e,t,r)),set:(e,t,r,o)=>{const s=e[t];return Mt(s)&&!Mt(r)?(s.value=r,!0):Reflect.set(e,t,r,o)}};function J0(e){return jo(e)?e:new Proxy(e,g_)}class m_{constructor(t){this.__v_isRef=!0,this._value=void 0;const r=this.dep=new Wu,{get:o,set:s}=t(r.track.bind(r),r.trigger.bind(r));this._get=o,this._set=s}get value(){return this._value=this._get()}set value(t){this._set(t)}}function Q0(e){return new m_(e)}function v_(e){const t=Ze(e)?new Array(e.length):{};for(const r in e)t[r]=eb(e,r);return t}class y_{constructor(t,r,o){this._object=t,this._key=r,this._defaultValue=o,this.__v_isRef=!0,this._value=void 0,this._raw=mt(t);let s=!0,c=t;if(!Ze(t)||!Du(String(r)))do s=!ju(c)||or(c);while(s&&(c=c.__v_raw));this._shallow=s}get value(){let t=this._object[this._key];return this._shallow&&(t=K(t)),this._value=t===void 0?this._defaultValue:t}set value(t){if(this._shallow&&Mt(this._raw[this._key])){const r=this._object[this._key];if(Mt(r)){r.value=t;return}}this._object[this._key]=t}get dep(){return ZS(this._raw,this._key)}}class b_{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function w_(e,t,r){return Mt(e)?e:et(e)?new b_(e):kt(e)&&arguments.length>1?eb(e,t,r):Ge(e)}function eb(e,t,r){return new y_(e,t,r)}class x_{constructor(t,r,o){this.fn=t,this.setter=r,this._value=void 0,this.dep=new Wu(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=aa-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!r,this.isSSR=o}notify(){if(this.flags|=16,!(this.flags&8)&&Tt!==this)return F0(this,!0),!0}get value(){const t=this.dep.track();return W0(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function k_(e,t,r=!1){let o,s;return et(e)?o=e:(o=e.get,s=e.set),new x_(o,s,r)}const Ec={},ou=new WeakMap;let $o;function S_(e,t=!1,r=$o){if(r){let o=ou.get(r);o||ou.set(r,o=[]),o.push(e)}}function __(e,t,r=vt){const{immediate:o,deep:s,once:c,scheduler:f,augmentJob:d,call:h}=r,p=_=>s?_:or(_)||s===!1||s===0?wi(_,1):wi(_);let g,v,b,w,E=!1,L=!1;if(Mt(e)?(v=()=>e.value,E=or(e)):jo(e)?(v=()=>p(e),E=!0):Ze(e)?(L=!0,E=e.some(_=>jo(_)||or(_)),v=()=>e.map(_=>{if(Mt(_))return _.value;if(jo(_))return p(_);if(et(_))return h?h(_,2):_()})):et(e)?t?v=h?()=>h(e,2):e:v=()=>{if(b){Si();try{b()}finally{_i()}}const _=$o;$o=g;try{return h?h(e,3,[w]):e(w)}finally{$o=_}}:v=Xr,t&&s){const _=v,$=s===!0?1/0:s;v=()=>wi(_(),$)}const P=I0(),M=()=>{g.stop(),P&&P.active&&Bh(P.effects,g)};if(c&&t){const _=t;t=(...$)=>{_(...$),M()}}let R=L?new Array(e.length).fill(Ec):Ec;const I=_=>{if(!(!(g.flags&1)||!g.dirty&&!_))if(t){const $=g.run();if(s||E||(L?$.some((W,ne)=>Gn(W,R[ne])):Gn($,R))){b&&b();const W=$o;$o=g;try{const ne=[$,R===Ec?void 0:L&&R[0]===Ec?[]:R,w];R=$,h?h(t,3,ne):t(...ne)}finally{$o=W}}}else g.run()};return d&&d(I),g=new D0(v),g.scheduler=f?()=>f(I,!1):I,w=_=>S_(_,!1,g),b=g.onStop=()=>{const _=ou.get(g);if(_){if(h)h(_,4);else for(const $ of _)$();ou.delete(g)}},t?o?I(!0):R=g.run():f?f(I.bind(null,!0),!0):g.run(),M.pause=g.pause.bind(g),M.resume=g.resume.bind(g),M.stop=M,M}function wi(e,t=1/0,r){if(t<=0||!kt(e)||e.__v_skip||(r=r||new Map,(r.get(e)||0)>=t))return e;if(r.set(e,t),t--,Mt(e))wi(e.value,t,r);else if(Ze(e))for(let o=0;o<e.length;o++)wi(e[o],t,r);else if(Iu(e)||$s(e))e.forEach(o=>{wi(o,t,r)});else if(L0(e)){for(const o in e)wi(e[o],t,r);for(const o of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,o)&&wi(e[o],t,r)}return e}/**\n* @vue/runtime-core v3.5.25\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/function Pa(e,t,r,o){try{return o?e(...o):e()}catch(s){Ra(s,t,r)}}function $r(e,t,r,o){if(et(e)){const s=Pa(e,t,r,o);return s&&E0(s)&&s.catch(c=>{Ra(c,t,r)}),s}if(Ze(e)){const s=[];for(let c=0;c<e.length;c++)s.push($r(e[c],t,r,o));return s}}function Ra(e,t,r,o=!0){const s=t?t.vnode:null,{errorHandler:c,throwUnhandledErrorInProduction:f}=t&&t.appContext.config||vt;if(t){let d=t.parent;const h=t.proxy,p=`https://vuejs.org/error-reference/#runtime-${r}`;for(;d;){const g=d.ec;if(g){for(let v=0;v<g.length;v++)if(g[v](e,h,p)===!1)return}d=d.parent}if(c){Si(),Pa(c,null,10,[e,h,p]),_i();return}}T_(e,r,s,o,f)}function T_(e,t,r,o=!0,s=!1){if(s)throw e;console.error(e)}const Pn=[];let Gr=-1;const Is=[];let Zi=null,Es=0;const tb=Promise.resolve();let su=null;function Et(e){const t=su||tb;return e?t.then(this?e.bind(this):e):t}function C_(e){let t=Gr+1,r=Pn.length;for(;t<r;){const o=t+r>>>1,s=Pn[o],c=ua(s);c<e||c===e&&s.flags&2?t=o+1:r=o}return t}function Xh(e){if(!(e.flags&1)){const t=ua(e),r=Pn[Pn.length-1];!r||!(e.flags&2)&&t>=ua(r)?Pn.push(e):Pn.splice(C_(t),0,e),e.flags|=1,nb()}}function nb(){su||(su=tb.then(ib))}function Gd(e){Ze(e)?Is.push(...e):Zi&&e.id===-1?Zi.splice(Es+1,0,e):e.flags&1||(Is.push(e),e.flags|=1),nb()}function Um(e,t,r=Gr+1){for(;r<Pn.length;r++){const o=Pn[r];if(o&&o.flags&2){if(e&&o.id!==e.uid)continue;Pn.splice(r,1),r--,o.flags&4&&(o.flags&=-2),o(),o.flags&4||(o.flags&=-2)}}}function rb(e){if(Is.length){const t=[...new Set(Is)].sort((r,o)=>ua(r)-ua(o));if(Is.length=0,Zi){Zi.push(...t);return}for(Zi=t,Es=0;Es<Zi.length;Es++){const r=Zi[Es];r.flags&4&&(r.flags&=-2),r.flags&8||r(),r.flags&=-2}Zi=null,Es=0}}const ua=e=>e.id==null?e.flags&2?-1:1/0:e.id;function ib(e){try{for(Gr=0;Gr<Pn.length;Gr++){const t=Pn[Gr];t&&!(t.flags&8)&&(t.flags&4&&(t.flags&=-2),Pa(t,t.i,t.i?15:14),t.flags&4||(t.flags&=-2))}}finally{for(;Gr<Pn.length;Gr++){const t=Pn[Gr];t&&(t.flags&=-2)}Gr=-1,Pn.length=0,rb(),su=null,(Pn.length||Is.length)&&ib()}}let mn=null,Vu=null;function lu(e){const t=mn;return mn=e,Vu=e&&e.type.__scopeId||null,t}function ob(e){Vu=e}function sb(){Vu=null}const lb=e=>We;function We(e,t=mn,r){if(!t||e._n)return e;const o=(...s)=>{o._d&&Ys(-1);const c=lu(t);let f;try{f=e(...s)}finally{lu(c),o._d&&Ys(1)}return f};return o._n=!0,o._c=!0,o._d=!0,o}function at(e,t){if(mn===null)return e;const r=Qu(mn),o=e.dirs||(e.dirs=[]);for(let s=0;s<t.length;s++){let[c,f,d,h=vt]=t[s];c&&(et(c)&&(c={mounted:c,updated:c}),c.deep&&wi(f),o.push({dir:c,instance:r,value:f,oldValue:void 0,arg:d,modifiers:h}))}return e}function Mo(e,t,r,o){const s=e.dirs,c=t&&t.dirs;for(let f=0;f<s.length;f++){const d=s[f];c&&(d.oldValue=c[f].value);let h=d.dir[o];h&&(Si(),$r(h,r,8,[e.el,d,e,t]),_i())}}const E_=Symbol(\"_vte\"),ab=e=>e.__isTeleport,yi=Symbol(\"_leaveCb\"),Ac=Symbol(\"_enterCb\");function A_(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return Mi(()=>{e.isMounted=!0}),$a(()=>{e.isUnmounting=!0}),e}const ur=[Function,Array],cb={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:ur,onEnter:ur,onAfterEnter:ur,onEnterCancelled:ur,onBeforeLeave:ur,onLeave:ur,onAfterLeave:ur,onLeaveCancelled:ur,onBeforeAppear:ur,onAppear:ur,onAfterAppear:ur,onAppearCancelled:ur},ub=e=>{const t=e.subTree;return t.component?ub(t.component):t},L_={name:\"BaseTransition\",props:cb,setup(e,{slots:t}){const r=ti(),o=A_();return()=>{const s=t.default&&hb(t.default(),!0);if(!s||!s.length)return;const c=fb(s),f=mt(e),{mode:d}=f;if(o.isLeaving)return gd(c);const h=Vm(c);if(!h)return gd(c);let p=Kd(h,f,o,r,v=>p=v);h.type!==ln&&fa(h,p);let g=r.subTree&&Vm(r.subTree);if(g&&g.type!==ln&&!Kr(g,h)&&ub(r).type!==ln){let v=Kd(g,f,o,r);if(fa(g,v),d===\"out-in\"&&h.type!==ln)return o.isLeaving=!0,v.afterLeave=()=>{o.isLeaving=!1,r.job.flags&8||r.update(),delete v.afterLeave,g=void 0},gd(c);d===\"in-out\"&&h.type!==ln?v.delayLeave=(b,w,E)=>{const L=db(o,g);L[String(g.key)]=g,b[yi]=()=>{w(),b[yi]=void 0,delete p.delayedLeave,g=void 0},p.delayedLeave=()=>{E(),delete p.delayedLeave,g=void 0}}:g=void 0}else g&&(g=void 0);return c}}};function fb(e){let t=e[0];if(e.length>1){for(const r of e)if(r.type!==ln){t=r;break}}return t}const M_=L_;function db(e,t){const{leavingVNodes:r}=e;let o=r.get(t.type);return o||(o=Object.create(null),r.set(t.type,o)),o}function Kd(e,t,r,o,s){const{appear:c,mode:f,persisted:d=!1,onBeforeEnter:h,onEnter:p,onAfterEnter:g,onEnterCancelled:v,onBeforeLeave:b,onLeave:w,onAfterLeave:E,onLeaveCancelled:L,onBeforeAppear:P,onAppear:M,onAfterAppear:R,onAppearCancelled:I}=t,_=String(e.key),$=db(r,e),W=(Z,G)=>{Z&&$r(Z,o,9,G)},ne=(Z,G)=>{const j=G[1];W(Z,G),Ze(Z)?Z.every(N=>N.length<=1)&&j():Z.length<=1&&j()},ee={mode:f,persisted:d,beforeEnter(Z){let G=h;if(!r.isMounted)if(c)G=P||h;else return;Z[yi]&&Z[yi](!0);const j=$[_];j&&Kr(e,j)&&j.el[yi]&&j.el[yi](),W(G,[Z])},enter(Z){let G=p,j=g,N=v;if(!r.isMounted)if(c)G=M||p,j=R||g,N=I||v;else return;let O=!1;const C=Z[Ac]=k=>{O||(O=!0,k?W(N,[Z]):W(j,[Z]),ee.delayedLeave&&ee.delayedLeave(),Z[Ac]=void 0)};G?ne(G,[Z,C]):C()},leave(Z,G){const j=String(e.key);if(Z[Ac]&&Z[Ac](!0),r.isUnmounting)return G();W(b,[Z]);let N=!1;const O=Z[yi]=C=>{N||(N=!0,G(),C?W(L,[Z]):W(E,[Z]),Z[yi]=void 0,$[j]===e&&delete $[j])};$[j]=e,w?ne(w,[Z,O]):O()},clone(Z){const G=Kd(Z,t,r,o,s);return s&&s(G),G}};return ee}function gd(e){if(Gu(e))return e=uo(e),e.children=null,e}function Vm(e){if(!Gu(e))return ab(e.type)&&e.children?fb(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:r}=e;if(r){if(t&16)return r[0];if(t&32&&et(r.default))return r.default()}}function fa(e,t){e.shapeFlag&6&&e.component?(e.transition=t,fa(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function hb(e,t=!1,r){let o=[],s=0;for(let c=0;c<e.length;c++){let f=e[c];const d=r==null?f.key:String(r)+String(f.key!=null?f.key:c);f.type===nt?(f.patchFlag&128&&s++,o=o.concat(hb(f.children,t,d))):(t||f.type!==ln)&&o.push(d!=null?uo(f,{key:d}):f)}if(s>1)for(let c=0;c<o.length;c++)o[c].patchFlag=-2;return o}function rt(e,t){return et(e)?on({name:e.name},t,{setup:e}):e}function Yh(){const e=ti();return e?(e.appContext.config.idPrefix||\"v\")+\"-\"+e.ids[0]+e.ids[1]++:\"\"}function pb(e){e.ids=[e.ids[0]+e.ids[2]+++\"-\",0,0]}const au=new WeakMap;function Jl(e,t,r,o,s=!1){if(Ze(e)){e.forEach((E,L)=>Jl(E,t&&(Ze(t)?t[L]:t),r,o,s));return}if(Ds(o)&&!s){o.shapeFlag&512&&o.type.__asyncResolved&&o.component.subTree.component&&Jl(e,t,r,o.component.subTree);return}const c=o.shapeFlag&4?Qu(o.component):o.el,f=s?null:c,{i:d,r:h}=e,p=t&&t.r,g=d.refs===vt?d.refs={}:d.refs,v=d.setupState,b=mt(v),w=v===vt?C0:E=>wt(b,E);if(p!=null&&p!==h){if(Gm(t),Ht(p))g[p]=null,w(p)&&(v[p]=null);else if(Mt(p)){p.value=null;const E=t;E.k&&(g[E.k]=null)}}if(et(h))Pa(h,d,12,[f,g]);else{const E=Ht(h),L=Mt(h);if(E||L){const P=()=>{if(e.f){const M=E?w(h)?v[h]:g[h]:h.value;if(s)Ze(M)&&Bh(M,c);else if(Ze(M))M.includes(c)||M.push(c);else if(E)g[h]=[c],w(h)&&(v[h]=g[h]);else{const R=[c];h.value=R,e.k&&(g[e.k]=R)}}else E?(g[h]=f,w(h)&&(v[h]=f)):L&&(h.value=f,e.k&&(g[e.k]=f))};if(f){const M=()=>{P(),au.delete(e)};M.id=-1,au.set(e,M),jn(M,r)}else Gm(e),P()}}}function Gm(e){const t=au.get(e);t&&(t.flags|=8,au.delete(e))}Hu().requestIdleCallback;Hu().cancelIdleCallback;const Ds=e=>!!e.type.__asyncLoader,Gu=e=>e.type.__isKeepAlive;function N_(e,t){gb(e,\"a\",t)}function O_(e,t){gb(e,\"da\",t)}function gb(e,t,r=xn){const o=e.__wdc||(e.__wdc=()=>{let s=r;for(;s;){if(s.isDeactivated)return;s=s.parent}return e()});if(Ku(t,o,r),r){let s=r.parent;for(;s&&s.parent;)Gu(s.parent.vnode)&&P_(o,t,r,s),s=s.parent}}function P_(e,t,r,o){const s=Ku(t,e,o,!0);Ia(()=>{Bh(o[t],s)},r)}function Ku(e,t,r=xn,o=!1){if(r){const s=r[e]||(r[e]=[]),c=t.__weh||(t.__weh=(...f)=>{Si();const d=Da(r),h=$r(t,r,e,f);return d(),_i(),h});return o?s.unshift(c):s.push(c),c}}const Li=e=>(t,r=xn)=>{(!pa||e===\"sp\")&&Ku(e,(...o)=>t(...o),r)},R_=Li(\"bm\"),Mi=Li(\"m\"),$_=Li(\"bu\"),I_=Li(\"u\"),$a=Li(\"bum\"),Ia=Li(\"um\"),D_=Li(\"sp\"),z_=Li(\"rtg\"),F_=Li(\"rtc\");function H_(e,t=xn){Ku(\"ec\",e,t)}const Zh=\"components\",B_=\"directives\";function Go(e,t){return Jh(Zh,e,!0,t)||e}const mb=Symbol.for(\"v-ndc\");function Xd(e){return Ht(e)?Jh(Zh,e,!1)||e:e||mb}function vr(e){return Jh(B_,e)}function Jh(e,t,r=!0,o=!1){const s=mn||xn;if(s){const c=s.type;if(e===Zh){const d=PT(c,!1);if(d&&(d===t||d===sr(t)||d===Fu(sr(t))))return c}const f=Km(s[e]||c[e],t)||Km(s.appContext[e],t);return!f&&o?c:f}}function Km(e,t){return e&&(e[t]||e[sr(t)]||e[Fu(sr(t))])}function $n(e,t,r,o){let s;const c=r,f=Ze(e);if(f||Ht(e)){const d=f&&jo(e);let h=!1,p=!1;d&&(h=!or(e),p=Ti(e),e=qu(e)),s=new Array(e.length);for(let g=0,v=e.length;g<v;g++)s[g]=t(h?p?Ks(Rr(e[g])):Rr(e[g]):e[g],g,void 0,c)}else if(typeof e==\"number\"){s=new Array(e);for(let d=0;d<e;d++)s[d]=t(d+1,d,void 0,c)}else if(kt(e))if(e[Symbol.iterator])s=Array.from(e,(d,h)=>t(d,h,void 0,c));else{const d=Object.keys(e);s=new Array(d.length);for(let h=0,p=d.length;h<p;h++){const g=d[h];s[h]=t(e[g],g,h,c)}}else s=[];return s}function W_(e,t){for(let r=0;r<t.length;r++){const o=t[r];if(Ze(o))for(let s=0;s<o.length;s++)e[o[s].name]=o[s].fn;else o&&(e[o.name]=o.key?(...s)=>{const c=o.fn(...s);return c&&(c.key=o.key),c}:o.fn)}return e}function Dt(e,t,r={},o,s){if(mn.ce||mn.parent&&Ds(mn.parent)&&mn.parent.ce){const p=Object.keys(r).length>0;return t!==\"default\"&&(r.name=t),ie(),Ve(nt,null,[Ne(\"slot\",r,o&&o())],p?-2:64)}let c=e[t];c&&c._c&&(c._d=!1),ie();const f=c&&vb(c(r)),d=r.key||f&&f.key,h=Ve(nt,{key:(d&&!Pr(d)?d:`_${t}`)+(!f&&o?\"_fb\":\"\")},f||(o?o():[]),f&&e._===1?64:-2);return h.scopeId&&(h.slotScopeIds=[h.scopeId+\"-s\"]),c&&c._c&&(c._d=!0),h}function vb(e){return e.some(t=>Zs(t)?!(t.type===ln||t.type===nt&&!vb(t.children)):!0)?e:null}function q_(e,t){const r={};for(const o in e)r[qc(o)]=e[o];return r}const Yd=e=>e?jb(e)?Qu(e):Yd(e.parent):null,Ql=on(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Yd(e.parent),$root:e=>Yd(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>xb(e),$forceUpdate:e=>e.f||(e.f=()=>{Xh(e.update)}),$nextTick:e=>e.n||(e.n=Et.bind(e.proxy)),$watch:e=>nT.bind(e)}),md=(e,t)=>e!==vt&&!e.__isScriptSetup&&wt(e,t),j_={get({_:e},t){if(t===\"__v_skip\")return!0;const{ctx:r,setupState:o,data:s,props:c,accessCache:f,type:d,appContext:h}=e;if(t[0]!==\"$\"){const b=f[t];if(b!==void 0)switch(b){case 1:return o[t];case 2:return s[t];case 4:return r[t];case 3:return c[t]}else{if(md(o,t))return f[t]=1,o[t];if(s!==vt&&wt(s,t))return f[t]=2,s[t];if(wt(c,t))return f[t]=3,c[t];if(r!==vt&&wt(r,t))return f[t]=4,r[t];Zd&&(f[t]=0)}}const p=Ql[t];let g,v;if(p)return t===\"$attrs\"&&wn(e.attrs,\"get\",\"\"),p(e);if((g=d.__cssModules)&&(g=g[t]))return g;if(r!==vt&&wt(r,t))return f[t]=4,r[t];if(v=h.config.globalProperties,wt(v,t))return v[t]},set({_:e},t,r){const{data:o,setupState:s,ctx:c}=e;return md(s,t)?(s[t]=r,!0):o!==vt&&wt(o,t)?(o[t]=r,!0):wt(e.props,t)||t[0]===\"$\"&&t.slice(1)in e?!1:(c[t]=r,!0)},has({_:{data:e,setupState:t,accessCache:r,ctx:o,appContext:s,props:c,type:f}},d){let h;return!!(r[d]||e!==vt&&d[0]!==\"$\"&&wt(e,d)||md(t,d)||wt(c,d)||wt(o,d)||wt(Ql,d)||wt(s.config.globalProperties,d)||(h=f.__cssModules)&&h[d])},defineProperty(e,t,r){return r.get!=null?e._.accessCache[t]=0:wt(r,\"value\")&&this.set(e,t,r.value,null),Reflect.defineProperty(e,t,r)}};function yb(){return bb().slots}function U_(){return bb().attrs}function bb(e){const t=ti();return t.setupContext||(t.setupContext=Vb(t))}function cu(e){return Ze(e)?e.reduce((t,r)=>(t[r]=null,t),{}):e}function da(e,t){return!e||!t?e||t:Ze(e)&&Ze(t)?e.concat(t):on({},cu(e),cu(t))}let Zd=!0;function V_(e){const t=xb(e),r=e.proxy,o=e.ctx;Zd=!1,t.beforeCreate&&Xm(t.beforeCreate,e,\"bc\");const{data:s,computed:c,methods:f,watch:d,provide:h,inject:p,created:g,beforeMount:v,mounted:b,beforeUpdate:w,updated:E,activated:L,deactivated:P,beforeDestroy:M,beforeUnmount:R,destroyed:I,unmounted:_,render:$,renderTracked:W,renderTriggered:ne,errorCaptured:ee,serverPrefetch:Z,expose:G,inheritAttrs:j,components:N,directives:O,filters:C}=t;if(p&&G_(p,o,null),f)for(const B in f){const ce=f[B];et(ce)&&(o[B]=ce.bind(r))}if(s){const B=s.call(r,r);kt(B)&&(e.data=ir(B))}if(Zd=!0,c)for(const B in c){const ce=c[B],be=et(ce)?ce.bind(r,r):et(ce.get)?ce.get.bind(r,r):Xr,Se=!et(ce)&&et(ce.set)?ce.set.bind(r):Xr,Be=ke({get:be,set:Se});Object.defineProperty(o,B,{enumerable:!0,configurable:!0,get:()=>Be.value,set:Ae=>Be.value=Ae})}if(d)for(const B in d)wb(d[B],o,r,B);if(h){const B=et(h)?h.call(r):h;Reflect.ownKeys(B).forEach(ce=>{dr(ce,B[ce])})}g&&Xm(g,e,\"c\");function z(B,ce){Ze(ce)?ce.forEach(be=>B(be.bind(r))):ce&&B(ce.bind(r))}if(z(R_,v),z(Mi,b),z($_,w),z(I_,E),z(N_,L),z(O_,P),z(H_,ee),z(F_,W),z(z_,ne),z($a,R),z(Ia,_),z(D_,Z),Ze(G))if(G.length){const B=e.exposed||(e.exposed={});G.forEach(ce=>{Object.defineProperty(B,ce,{get:()=>r[ce],set:be=>r[ce]=be,enumerable:!0})})}else e.exposed||(e.exposed={});$&&e.render===Xr&&(e.render=$),j!=null&&(e.inheritAttrs=j),N&&(e.components=N),O&&(e.directives=O),Z&&pb(e)}function G_(e,t,r=Xr){Ze(e)&&(e=Jd(e));for(const o in e){const s=e[o];let c;kt(s)?\"default\"in s?c=pn(s.from||o,s.default,!0):c=pn(s.from||o):c=pn(s),Mt(c)?Object.defineProperty(t,o,{enumerable:!0,configurable:!0,get:()=>c.value,set:f=>c.value=f}):t[o]=c}}function Xm(e,t,r){$r(Ze(e)?e.map(o=>o.bind(t.proxy)):e.bind(t.proxy),t,r)}function wb(e,t,r,o){let s=o.includes(\".\")?Tb(r,o):()=>r[o];if(Ht(e)){const c=t[e];et(c)&&xt(s,c)}else if(et(e))xt(s,e.bind(r));else if(kt(e))if(Ze(e))e.forEach(c=>wb(c,t,r,o));else{const c=et(e.handler)?e.handler.bind(r):t[e.handler];et(c)&&xt(s,c,e)}}function xb(e){const t=e.type,{mixins:r,extends:o}=t,{mixins:s,optionsCache:c,config:{optionMergeStrategies:f}}=e.appContext,d=c.get(t);let h;return d?h=d:!s.length&&!r&&!o?h=t:(h={},s.length&&s.forEach(p=>uu(h,p,f,!0)),uu(h,t,f)),kt(t)&&c.set(t,h),h}function uu(e,t,r,o=!1){const{mixins:s,extends:c}=t;c&&uu(e,c,r,!0),s&&s.forEach(f=>uu(e,f,r,!0));for(const f in t)if(!(o&&f===\"expose\")){const d=K_[f]||r&&r[f];e[f]=d?d(e[f],t[f]):t[f]}return e}const K_={data:Ym,props:Zm,emits:Zm,methods:Ul,computed:Ul,beforeCreate:Mn,created:Mn,beforeMount:Mn,mounted:Mn,beforeUpdate:Mn,updated:Mn,beforeDestroy:Mn,beforeUnmount:Mn,destroyed:Mn,unmounted:Mn,activated:Mn,deactivated:Mn,errorCaptured:Mn,serverPrefetch:Mn,components:Ul,directives:Ul,watch:Y_,provide:Ym,inject:X_};function Ym(e,t){return t?e?function(){return on(et(e)?e.call(this,this):e,et(t)?t.call(this,this):t)}:t:e}function X_(e,t){return Ul(Jd(e),Jd(t))}function Jd(e){if(Ze(e)){const t={};for(let r=0;r<e.length;r++)t[e[r]]=e[r];return t}return e}function Mn(e,t){return e?[...new Set([].concat(e,t))]:t}function Ul(e,t){return e?on(Object.create(null),e,t):t}function Zm(e,t){return e?Ze(e)&&Ze(t)?[...new Set([...e,...t])]:on(Object.create(null),cu(e),cu(t??{})):t}function Y_(e,t){if(!e)return t;if(!t)return e;const r=on(Object.create(null),e);for(const o in t)r[o]=Mn(e[o],t[o]);return r}function kb(){return{app:null,config:{isNativeTag:C0,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let Z_=0;function J_(e,t){return function(o,s=null){et(o)||(o=on({},o)),s!=null&&!kt(s)&&(s=null);const c=kb(),f=new WeakSet,d=[];let h=!1;const p=c.app={_uid:Z_++,_component:o,_props:s,_container:null,_context:c,_instance:null,version:$T,get config(){return c.config},set config(g){},use(g,...v){return f.has(g)||(g&&et(g.install)?(f.add(g),g.install(p,...v)):et(g)&&(f.add(g),g(p,...v))),p},mixin(g){return c.mixins.includes(g)||c.mixins.push(g),p},component(g,v){return v?(c.components[g]=v,p):c.components[g]},directive(g,v){return v?(c.directives[g]=v,p):c.directives[g]},mount(g,v,b){if(!h){const w=p._ceVNode||Ne(o,s);return w.appContext=c,b===!0?b=\"svg\":b===!1&&(b=void 0),e(w,g,b),h=!0,p._container=g,g.__vue_app__=p,Qu(w.component)}},onUnmount(g){d.push(g)},unmount(){h&&($r(d,p._instance,16),e(null,p._container),delete p._container.__vue_app__)},provide(g,v){return c.provides[g]=v,p},runWithContext(g){const v=Uo;Uo=p;try{return g()}finally{Uo=v}}};return p}}let Uo=null;function dr(e,t){if(xn){let r=xn.provides;const o=xn.parent&&xn.parent.provides;o===r&&(r=xn.provides=Object.create(o)),r[e]=t}}function pn(e,t,r=!1){const o=ti();if(o||Uo){let s=Uo?Uo._context.provides:o?o.parent==null||o.ce?o.vnode.appContext&&o.vnode.appContext.provides:o.parent.provides:void 0;if(s&&e in s)return s[e];if(arguments.length>1)return r&&et(t)?t.call(o&&o.proxy):t}}function Sb(){return!!(ti()||Uo)}const Q_=Symbol.for(\"v-scx\"),eT=()=>pn(Q_);function _b(e,t){return Xu(e,null,t)}function tT(e,t){return Xu(e,null,{flush:\"sync\"})}function xt(e,t,r){return Xu(e,t,r)}function Xu(e,t,r=vt){const{immediate:o,deep:s,flush:c,once:f}=r,d=on({},r),h=t&&o||!t&&c!==\"post\";let p;if(pa){if(c===\"sync\"){const w=eT();p=w.__watcherHandles||(w.__watcherHandles=[])}else if(!h){const w=()=>{};return w.stop=Xr,w.resume=Xr,w.pause=Xr,w}}const g=xn;d.call=(w,E,L)=>$r(w,g,E,L);let v=!1;c===\"post\"?d.scheduler=w=>{jn(w,g&&g.suspense)}:c!==\"sync\"&&(v=!0,d.scheduler=(w,E)=>{E?w():Xh(w)}),d.augmentJob=w=>{t&&(w.flags|=4),v&&(w.flags|=2,g&&(w.id=g.uid,w.i=g))};const b=__(e,t,d);return pa&&(p?p.push(b):h&&b()),b}function nT(e,t,r){const o=this.proxy,s=Ht(e)?e.includes(\".\")?Tb(o,e):()=>o[e]:e.bind(o,o);let c;et(t)?c=t:(c=t.handler,r=t);const f=Da(this),d=Xu(s,c.bind(o),r);return f(),d}function Tb(e,t){const r=t.split(\".\");return()=>{let o=e;for(let s=0;s<r.length&&o;s++)o=o[r[s]];return o}}function Yu(e,t,r=vt){const o=ti(),s=sr(t),c=Ai(t),f=Cb(e,s),d=Q0((h,p)=>{let g,v=vt,b;return tT(()=>{const w=e[s];Gn(g,w)&&(g=w,p())}),{get(){return h(),r.get?r.get(g):g},set(w){const E=r.set?r.set(w):w;if(!Gn(E,g)&&!(v!==vt&&Gn(w,v)))return;const L=o.vnode.props;L&&(t in L||s in L||c in L)&&(`onUpdate:${t}`in L||`onUpdate:${s}`in L||`onUpdate:${c}`in L)||(g=w,p()),o.emit(`update:${t}`,E),Gn(w,E)&&Gn(w,v)&&!Gn(E,b)&&p(),v=w,b=E}}});return d[Symbol.iterator]=()=>{let h=0;return{next(){return h<2?{value:h++?f||vt:d,done:!1}:{done:!0}}}},d}const Cb=(e,t)=>t===\"modelValue\"||t===\"model-value\"?e.modelModifiers:e[`${t}Modifiers`]||e[`${sr(t)}Modifiers`]||e[`${Ai(t)}Modifiers`];function rT(e,t,...r){if(e.isUnmounted)return;const o=e.vnode.props||vt;let s=r;const c=t.startsWith(\"update:\"),f=c&&Cb(o,t.slice(7));f&&(f.trim&&(s=r.map(g=>Ht(g)?g.trim():g)),f.number&&(s=r.map(Wh)));let d,h=o[d=qc(t)]||o[d=qc(sr(t))];!h&&c&&(h=o[d=qc(Ai(t))]),h&&$r(h,e,6,s);const p=o[d+\"Once\"];if(p){if(!e.emitted)e.emitted={};else if(e.emitted[d])return;e.emitted[d]=!0,$r(p,e,6,s)}}const iT=new WeakMap;function Eb(e,t,r=!1){const o=r?iT:t.emitsCache,s=o.get(e);if(s!==void 0)return s;const c=e.emits;let f={},d=!1;if(!et(e)){const h=p=>{const g=Eb(p,t,!0);g&&(d=!0,on(f,g))};!r&&t.mixins.length&&t.mixins.forEach(h),e.extends&&h(e.extends),e.mixins&&e.mixins.forEach(h)}return!c&&!d?(kt(e)&&o.set(e,null),null):(Ze(c)?c.forEach(h=>f[h]=null):on(f,c),kt(e)&&o.set(e,f),f)}function Zu(e,t){return!e||!$u(t)?!1:(t=t.slice(2).replace(/Once$/,\"\"),wt(e,t[0].toLowerCase()+t.slice(1))||wt(e,Ai(t))||wt(e,t))}function Jm(e){const{type:t,vnode:r,proxy:o,withProxy:s,propsOptions:[c],slots:f,attrs:d,emit:h,render:p,renderCache:g,props:v,data:b,setupState:w,ctx:E,inheritAttrs:L}=e,P=lu(e);let M,R;try{if(r.shapeFlag&4){const _=s||o,$=_;M=Lr(p.call($,_,g,v,w,b,E)),R=d}else{const _=t;M=Lr(_.length>1?_(v,{attrs:d,slots:f,emit:h}):_(v,null)),R=t.props?d:sT(d)}}catch(_){ea.length=0,Ra(_,e,1),M=Ne(ln)}let I=M;if(R&&L!==!1){const _=Object.keys(R),{shapeFlag:$}=I;_.length&&$&7&&(c&&_.some(Hh)&&(R=lT(R,c)),I=uo(I,R,!1,!0))}return r.dirs&&(I=uo(I,null,!1,!0),I.dirs=I.dirs?I.dirs.concat(r.dirs):r.dirs),r.transition&&fa(I,r.transition),M=I,lu(P),M}function oT(e,t=!0){let r;for(let o=0;o<e.length;o++){const s=e[o];if(Zs(s)){if(s.type!==ln||s.children===\"v-if\"){if(r)return;r=s}}else return}return r}const sT=e=>{let t;for(const r in e)(r===\"class\"||r===\"style\"||$u(r))&&((t||(t={}))[r]=e[r]);return t},lT=(e,t)=>{const r={};for(const o in e)(!Hh(o)||!(o.slice(9)in t))&&(r[o]=e[o]);return r};function aT(e,t,r){const{props:o,children:s,component:c}=e,{props:f,children:d,patchFlag:h}=t,p=c.emitsOptions;if(t.dirs||t.transition)return!0;if(r&&h>=0){if(h&1024)return!0;if(h&16)return o?Qm(o,f,p):!!f;if(h&8){const g=t.dynamicProps;for(let v=0;v<g.length;v++){const b=g[v];if(f[b]!==o[b]&&!Zu(p,b))return!0}}}else return(s||d)&&(!d||!d.$stable)?!0:o===f?!1:o?f?Qm(o,f,p):!0:!!f;return!1}function Qm(e,t,r){const o=Object.keys(t);if(o.length!==Object.keys(e).length)return!0;for(let s=0;s<o.length;s++){const c=o[s];if(t[c]!==e[c]&&!Zu(r,c))return!0}return!1}function Qh({vnode:e,parent:t},r){for(;t;){const o=t.subTree;if(o.suspense&&o.suspense.activeBranch===e&&(o.el=e.el),o===e)(e=t.vnode).el=r,t=t.parent;else break}}const Ab={},Lb=()=>Object.create(Ab),Mb=e=>Object.getPrototypeOf(e)===Ab;function cT(e,t,r,o=!1){const s={},c=Lb();e.propsDefaults=Object.create(null),Nb(e,t,s,c);for(const f in e.propsOptions[0])f in s||(s[f]=void 0);r?e.props=o?s:Gh(s):e.type.props?e.props=s:e.props=c,e.attrs=c}function uT(e,t,r,o){const{props:s,attrs:c,vnode:{patchFlag:f}}=e,d=mt(s),[h]=e.propsOptions;let p=!1;if((o||f>0)&&!(f&16)){if(f&8){const g=e.vnode.dynamicProps;for(let v=0;v<g.length;v++){let b=g[v];if(Zu(e.emitsOptions,b))continue;const w=t[b];if(h)if(wt(c,b))w!==c[b]&&(c[b]=w,p=!0);else{const E=sr(b);s[E]=Qd(h,d,E,w,e,!1)}else w!==c[b]&&(c[b]=w,p=!0)}}}else{Nb(e,t,s,c)&&(p=!0);let g;for(const v in d)(!t||!wt(t,v)&&((g=Ai(v))===v||!wt(t,g)))&&(h?r&&(r[v]!==void 0||r[g]!==void 0)&&(s[v]=Qd(h,d,v,void 0,e,!0)):delete s[v]);if(c!==d)for(const v in c)(!t||!wt(t,v))&&(delete c[v],p=!0)}p&&bi(e.attrs,\"set\",\"\")}function Nb(e,t,r,o){const[s,c]=e.propsOptions;let f=!1,d;if(t)for(let h in t){if(Xl(h))continue;const p=t[h];let g;s&&wt(s,g=sr(h))?!c||!c.includes(g)?r[g]=p:(d||(d={}))[g]=p:Zu(e.emitsOptions,h)||(!(h in o)||p!==o[h])&&(o[h]=p,f=!0)}if(c){const h=mt(r),p=d||vt;for(let g=0;g<c.length;g++){const v=c[g];r[v]=Qd(s,h,v,p[v],e,!wt(p,v))}}return f}function Qd(e,t,r,o,s,c){const f=e[r];if(f!=null){const d=wt(f,\"default\");if(d&&o===void 0){const h=f.default;if(f.type!==Function&&!f.skipFactory&&et(h)){const{propsDefaults:p}=s;if(r in p)o=p[r];else{const g=Da(s);o=p[r]=h.call(null,t),g()}}else o=h;s.ce&&s.ce._setProp(r,o)}f[0]&&(c&&!d?o=!1:f[1]&&(o===\"\"||o===Ai(r))&&(o=!0))}return o}const fT=new WeakMap;function Ob(e,t,r=!1){const o=r?fT:t.propsCache,s=o.get(e);if(s)return s;const c=e.props,f={},d=[];let h=!1;if(!et(e)){const g=v=>{h=!0;const[b,w]=Ob(v,t,!0);on(f,b),w&&d.push(...w)};!r&&t.mixins.length&&t.mixins.forEach(g),e.extends&&g(e.extends),e.mixins&&e.mixins.forEach(g)}if(!c&&!h)return kt(e)&&o.set(e,Rs),Rs;if(Ze(c))for(let g=0;g<c.length;g++){const v=sr(c[g]);ev(v)&&(f[v]=vt)}else if(c)for(const g in c){const v=sr(g);if(ev(v)){const b=c[g],w=f[v]=Ze(b)||et(b)?{type:b}:on({},b),E=w.type;let L=!1,P=!0;if(Ze(E))for(let M=0;M<E.length;++M){const R=E[M],I=et(R)&&R.name;if(I===\"Boolean\"){L=!0;break}else I===\"String\"&&(P=!1)}else L=et(E)&&E.name===\"Boolean\";w[0]=L,w[1]=P,(L||wt(w,\"default\"))&&d.push(v)}}const p=[f,d];return kt(e)&&o.set(e,p),p}function ev(e){return e[0]!==\"$\"&&!Xl(e)}const ep=e=>e===\"_\"||e===\"_ctx\"||e===\"$stable\",tp=e=>Ze(e)?e.map(Lr):[Lr(e)],dT=(e,t,r)=>{if(t._n)return t;const o=We((...s)=>tp(t(...s)),r);return o._c=!1,o},Pb=(e,t,r)=>{const o=e._ctx;for(const s in e){if(ep(s))continue;const c=e[s];if(et(c))t[s]=dT(s,c,o);else if(c!=null){const f=tp(c);t[s]=()=>f}}},Rb=(e,t)=>{const r=tp(t);e.slots.default=()=>r},$b=(e,t,r)=>{for(const o in t)(r||!ep(o))&&(e[o]=t[o])},hT=(e,t,r)=>{const o=e.slots=Lb();if(e.vnode.shapeFlag&32){const s=t._;s?($b(o,t,r),r&&M0(o,\"_\",s,!0)):Pb(t,o)}else t&&Rb(e,t)},pT=(e,t,r)=>{const{vnode:o,slots:s}=e;let c=!0,f=vt;if(o.shapeFlag&32){const d=t._;d?r&&d===1?c=!1:$b(s,t,r):(c=!t.$stable,Pb(t,s)),f=t}else t&&(Rb(e,t),f={default:1});if(c)for(const d in s)!ep(d)&&f[d]==null&&delete s[d]},jn=_T;function gT(e){return mT(e)}function mT(e,t){const r=Hu();r.__VUE__=!0;const{insert:o,remove:s,patchProp:c,createElement:f,createText:d,createComment:h,setText:p,setElementText:g,parentNode:v,nextSibling:b,setScopeId:w=Xr,insertStaticContent:E}=e,L=(D,q,Q,he=null,de=null,ge=null,Ce=void 0,Ee=null,xe=!!q.dynamicChildren)=>{if(D===q)return;D&&!Kr(D,q)&&(he=F(D),Ae(D,de,ge,!0),D=null),q.patchFlag===-2&&(xe=!1,q.dynamicChildren=null);const{type:ye,ref:J,shapeFlag:ue}=q;switch(ye){case Ju:P(D,q,Q,he);break;case ln:M(D,q,Q,he);break;case yd:D==null&&R(q,Q,he,Ce);break;case nt:N(D,q,Q,he,de,ge,Ce,Ee,xe);break;default:ue&1?$(D,q,Q,he,de,ge,Ce,Ee,xe):ue&6?O(D,q,Q,he,de,ge,Ce,Ee,xe):(ue&64||ue&128)&&ye.process(D,q,Q,he,de,ge,Ce,Ee,xe,le)}J!=null&&de?Jl(J,D&&D.ref,ge,q||D,!q):J==null&&D&&D.ref!=null&&Jl(D.ref,null,ge,D,!0)},P=(D,q,Q,he)=>{if(D==null)o(q.el=d(q.children),Q,he);else{const de=q.el=D.el;q.children!==D.children&&p(de,q.children)}},M=(D,q,Q,he)=>{D==null?o(q.el=h(q.children||\"\"),Q,he):q.el=D.el},R=(D,q,Q,he)=>{[D.el,D.anchor]=E(D.children,q,Q,he,D.el,D.anchor)},I=({el:D,anchor:q},Q,he)=>{let de;for(;D&&D!==q;)de=b(D),o(D,Q,he),D=de;o(q,Q,he)},_=({el:D,anchor:q})=>{let Q;for(;D&&D!==q;)Q=b(D),s(D),D=Q;s(q)},$=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{if(q.type===\"svg\"?Ce=\"svg\":q.type===\"math\"&&(Ce=\"mathml\"),D==null)W(q,Q,he,de,ge,Ce,Ee,xe);else{const ye=D.el&&D.el._isVueCE?D.el:null;try{ye&&ye._beginPatch(),Z(D,q,de,ge,Ce,Ee,xe)}finally{ye&&ye._endPatch()}}},W=(D,q,Q,he,de,ge,Ce,Ee)=>{let xe,ye;const{props:J,shapeFlag:ue,transition:oe,dirs:$e}=D;if(xe=D.el=f(D.type,ge,J&&J.is,J),ue&8?g(xe,D.children):ue&16&&ee(D.children,xe,null,he,de,vd(D,ge),Ce,Ee),$e&&Mo(D,null,he,\"created\"),ne(xe,D,D.scopeId,Ce,he),J){for(const ct in J)ct!==\"value\"&&!Xl(ct)&&c(xe,ct,null,J[ct],ge,he);\"value\"in J&&c(xe,\"value\",null,J.value,ge),(ye=J.onVnodeBeforeMount)&&Vr(ye,he,D)}$e&&Mo(D,null,he,\"beforeMount\");const Je=vT(de,oe);Je&&oe.beforeEnter(xe),o(xe,q,Q),((ye=J&&J.onVnodeMounted)||Je||$e)&&jn(()=>{ye&&Vr(ye,he,D),Je&&oe.enter(xe),$e&&Mo(D,null,he,\"mounted\")},de)},ne=(D,q,Q,he,de)=>{if(Q&&w(D,Q),he)for(let ge=0;ge<he.length;ge++)w(D,he[ge]);if(de){let ge=de.subTree;if(q===ge||zb(ge.type)&&(ge.ssContent===q||ge.ssFallback===q)){const Ce=de.vnode;ne(D,Ce,Ce.scopeId,Ce.slotScopeIds,de.parent)}}},ee=(D,q,Q,he,de,ge,Ce,Ee,xe=0)=>{for(let ye=xe;ye<D.length;ye++){const J=D[ye]=Ee?Ji(D[ye]):Lr(D[ye]);L(null,J,q,Q,he,de,ge,Ce,Ee)}},Z=(D,q,Q,he,de,ge,Ce)=>{const Ee=q.el=D.el;let{patchFlag:xe,dynamicChildren:ye,dirs:J}=q;xe|=D.patchFlag&16;const ue=D.props||vt,oe=q.props||vt;let $e;if(Q&&No(Q,!1),($e=oe.onVnodeBeforeUpdate)&&Vr($e,Q,q,D),J&&Mo(q,D,Q,\"beforeUpdate\"),Q&&No(Q,!0),(ue.innerHTML&&oe.innerHTML==null||ue.textContent&&oe.textContent==null)&&g(Ee,\"\"),ye?G(D.dynamicChildren,ye,Ee,Q,he,vd(q,de),ge):Ce||ce(D,q,Ee,null,Q,he,vd(q,de),ge,!1),xe>0){if(xe&16)j(Ee,ue,oe,Q,de);else if(xe&2&&ue.class!==oe.class&&c(Ee,\"class\",null,oe.class,de),xe&4&&c(Ee,\"style\",ue.style,oe.style,de),xe&8){const Je=q.dynamicProps;for(let ct=0;ct<Je.length;ct++){const dt=Je[ct],Nt=ue[dt],ut=oe[dt];(ut!==Nt||dt===\"value\")&&c(Ee,dt,Nt,ut,de,Q)}}xe&1&&D.children!==q.children&&g(Ee,q.children)}else!Ce&&ye==null&&j(Ee,ue,oe,Q,de);(($e=oe.onVnodeUpdated)||J)&&jn(()=>{$e&&Vr($e,Q,q,D),J&&Mo(q,D,Q,\"updated\")},he)},G=(D,q,Q,he,de,ge,Ce)=>{for(let Ee=0;Ee<q.length;Ee++){const xe=D[Ee],ye=q[Ee],J=xe.el&&(xe.type===nt||!Kr(xe,ye)||xe.shapeFlag&198)?v(xe.el):Q;L(xe,ye,J,null,he,de,ge,Ce,!0)}},j=(D,q,Q,he,de)=>{if(q!==Q){if(q!==vt)for(const ge in q)!Xl(ge)&&!(ge in Q)&&c(D,ge,q[ge],null,de,he);for(const ge in Q){if(Xl(ge))continue;const Ce=Q[ge],Ee=q[ge];Ce!==Ee&&ge!==\"value\"&&c(D,ge,Ee,Ce,de,he)}\"value\"in Q&&c(D,\"value\",q.value,Q.value,de)}},N=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{const ye=q.el=D?D.el:d(\"\"),J=q.anchor=D?D.anchor:d(\"\");let{patchFlag:ue,dynamicChildren:oe,slotScopeIds:$e}=q;$e&&(Ee=Ee?Ee.concat($e):$e),D==null?(o(ye,Q,he),o(J,Q,he),ee(q.children||[],Q,J,de,ge,Ce,Ee,xe)):ue>0&&ue&64&&oe&&D.dynamicChildren?(G(D.dynamicChildren,oe,Q,de,ge,Ce,Ee),(q.key!=null||de&&q===de.subTree)&&Ib(D,q,!0)):ce(D,q,Q,J,de,ge,Ce,Ee,xe)},O=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{q.slotScopeIds=Ee,D==null?q.shapeFlag&512?de.ctx.activate(q,Q,he,Ce,xe):C(q,Q,he,de,ge,Ce,xe):k(D,q,xe)},C=(D,q,Q,he,de,ge,Ce)=>{const Ee=D.component=LT(D,he,de);if(Gu(D)&&(Ee.ctx.renderer=le),MT(Ee,!1,Ce),Ee.asyncDep){if(de&&de.registerDep(Ee,z,Ce),!D.el){const xe=Ee.subTree=Ne(ln);M(null,xe,q,Q),D.placeholder=xe.el}}else z(Ee,D,q,Q,de,ge,Ce)},k=(D,q,Q)=>{const he=q.component=D.component;if(aT(D,q,Q))if(he.asyncDep&&!he.asyncResolved){B(he,q,Q);return}else he.next=q,he.update();else q.el=D.el,he.vnode=q},z=(D,q,Q,he,de,ge,Ce)=>{const Ee=()=>{if(D.isMounted){let{next:ue,bu:oe,u:$e,parent:Je,vnode:ct}=D;{const jt=Db(D);if(jt){ue&&(ue.el=ct.el,B(D,ue,Ce)),jt.asyncDep.then(()=>{D.isUnmounted||Ee()});return}}let dt=ue,Nt;No(D,!1),ue?(ue.el=ct.el,B(D,ue,Ce)):ue=ct,oe&&jc(oe),(Nt=ue.props&&ue.props.onVnodeBeforeUpdate)&&Vr(Nt,Je,ue,ct),No(D,!0);const ut=Jm(D),Yt=D.subTree;D.subTree=ut,L(Yt,ut,v(Yt.el),F(Yt),D,de,ge),ue.el=ut.el,dt===null&&Qh(D,ut.el),$e&&jn($e,de),(Nt=ue.props&&ue.props.onVnodeUpdated)&&jn(()=>Vr(Nt,Je,ue,ct),de)}else{let ue;const{el:oe,props:$e}=q,{bm:Je,m:ct,parent:dt,root:Nt,type:ut}=D,Yt=Ds(q);No(D,!1),Je&&jc(Je),!Yt&&(ue=$e&&$e.onVnodeBeforeMount)&&Vr(ue,dt,q),No(D,!0);{Nt.ce&&Nt.ce._def.shadowRoot!==!1&&Nt.ce._injectChildStyle(ut);const jt=D.subTree=Jm(D);L(null,jt,Q,he,D,de,ge),q.el=jt.el}if(ct&&jn(ct,de),!Yt&&(ue=$e&&$e.onVnodeMounted)){const jt=q;jn(()=>Vr(ue,dt,jt),de)}(q.shapeFlag&256||dt&&Ds(dt.vnode)&&dt.vnode.shapeFlag&256)&&D.a&&jn(D.a,de),D.isMounted=!0,q=Q=he=null}};D.scope.on();const xe=D.effect=new D0(Ee);D.scope.off();const ye=D.update=xe.run.bind(xe),J=D.job=xe.runIfDirty.bind(xe);J.i=D,J.id=D.uid,xe.scheduler=()=>Xh(J),No(D,!0),ye()},B=(D,q,Q)=>{q.component=D;const he=D.vnode.props;D.vnode=q,D.next=null,uT(D,q.props,he,Q),pT(D,q.children,Q),Si(),Um(D),_i()},ce=(D,q,Q,he,de,ge,Ce,Ee,xe=!1)=>{const ye=D&&D.children,J=D?D.shapeFlag:0,ue=q.children,{patchFlag:oe,shapeFlag:$e}=q;if(oe>0){if(oe&128){Se(ye,ue,Q,he,de,ge,Ce,Ee,xe);return}else if(oe&256){be(ye,ue,Q,he,de,ge,Ce,Ee,xe);return}}$e&8?(J&16&&Pe(ye,de,ge),ue!==ye&&g(Q,ue)):J&16?$e&16?Se(ye,ue,Q,he,de,ge,Ce,Ee,xe):Pe(ye,de,ge,!0):(J&8&&g(Q,\"\"),$e&16&&ee(ue,Q,he,de,ge,Ce,Ee,xe))},be=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{D=D||Rs,q=q||Rs;const ye=D.length,J=q.length,ue=Math.min(ye,J);let oe;for(oe=0;oe<ue;oe++){const $e=q[oe]=xe?Ji(q[oe]):Lr(q[oe]);L(D[oe],$e,Q,null,de,ge,Ce,Ee,xe)}ye>J?Pe(D,de,ge,!0,!1,ue):ee(q,Q,he,de,ge,Ce,Ee,xe,ue)},Se=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{let ye=0;const J=q.length;let ue=D.length-1,oe=J-1;for(;ye<=ue&&ye<=oe;){const $e=D[ye],Je=q[ye]=xe?Ji(q[ye]):Lr(q[ye]);if(Kr($e,Je))L($e,Je,Q,null,de,ge,Ce,Ee,xe);else break;ye++}for(;ye<=ue&&ye<=oe;){const $e=D[ue],Je=q[oe]=xe?Ji(q[oe]):Lr(q[oe]);if(Kr($e,Je))L($e,Je,Q,null,de,ge,Ce,Ee,xe);else break;ue--,oe--}if(ye>ue){if(ye<=oe){const $e=oe+1,Je=$e<J?q[$e].el:he;for(;ye<=oe;)L(null,q[ye]=xe?Ji(q[ye]):Lr(q[ye]),Q,Je,de,ge,Ce,Ee,xe),ye++}}else if(ye>oe)for(;ye<=ue;)Ae(D[ye],de,ge,!0),ye++;else{const $e=ye,Je=ye,ct=new Map;for(ye=Je;ye<=oe;ye++){const Bt=q[ye]=xe?Ji(q[ye]):Lr(q[ye]);Bt.key!=null&&ct.set(Bt.key,ye)}let dt,Nt=0;const ut=oe-Je+1;let Yt=!1,jt=0;const Fn=new Array(ut);for(ye=0;ye<ut;ye++)Fn[ye]=0;for(ye=$e;ye<=ue;ye++){const Bt=D[ye];if(Nt>=ut){Ae(Bt,de,ge,!0);continue}let Hn;if(Bt.key!=null)Hn=ct.get(Bt.key);else for(dt=Je;dt<=oe;dt++)if(Fn[dt-Je]===0&&Kr(Bt,q[dt])){Hn=dt;break}Hn===void 0?Ae(Bt,de,ge,!0):(Fn[Hn-Je]=ye+1,Hn>=jt?jt=Hn:Yt=!0,L(Bt,q[Hn],Q,null,de,ge,Ce,Ee,xe),Nt++)}const Hr=Yt?yT(Fn):Rs;for(dt=Hr.length-1,ye=ut-1;ye>=0;ye--){const Bt=Je+ye,Hn=q[Bt],lt=q[Bt+1],yo=Bt+1<J?lt.el||lt.placeholder:he;Fn[ye]===0?L(null,Hn,Q,yo,de,ge,Ce,Ee,xe):Yt&&(dt<0||ye!==Hr[dt]?Be(Hn,Q,yo,2):dt--)}}},Be=(D,q,Q,he,de=null)=>{const{el:ge,type:Ce,transition:Ee,children:xe,shapeFlag:ye}=D;if(ye&6){Be(D.component.subTree,q,Q,he);return}if(ye&128){D.suspense.move(q,Q,he);return}if(ye&64){Ce.move(D,q,Q,le);return}if(Ce===nt){o(ge,q,Q);for(let ue=0;ue<xe.length;ue++)Be(xe[ue],q,Q,he);o(D.anchor,q,Q);return}if(Ce===yd){I(D,q,Q);return}if(he!==2&&ye&1&&Ee)if(he===0)Ee.beforeEnter(ge),o(ge,q,Q),jn(()=>Ee.enter(ge),de);else{const{leave:ue,delayLeave:oe,afterLeave:$e}=Ee,Je=()=>{D.ctx.isUnmounted?s(ge):o(ge,q,Q)},ct=()=>{ge._isLeaving&&ge[yi](!0),ue(ge,()=>{Je(),$e&&$e()})};oe?oe(ge,Je,ct):ct()}else o(ge,q,Q)},Ae=(D,q,Q,he=!1,de=!1)=>{const{type:ge,props:Ce,ref:Ee,children:xe,dynamicChildren:ye,shapeFlag:J,patchFlag:ue,dirs:oe,cacheIndex:$e}=D;if(ue===-2&&(de=!1),Ee!=null&&(Si(),Jl(Ee,null,Q,D,!0),_i()),$e!=null&&(q.renderCache[$e]=void 0),J&256){q.ctx.deactivate(D);return}const Je=J&1&&oe,ct=!Ds(D);let dt;if(ct&&(dt=Ce&&Ce.onVnodeBeforeUnmount)&&Vr(dt,q,D),J&6)Fe(D.component,Q,he);else{if(J&128){D.suspense.unmount(Q,he);return}Je&&Mo(D,null,q,\"beforeUnmount\"),J&64?D.type.remove(D,q,Q,le,he):ye&&!ye.hasOnce&&(ge!==nt||ue>0&&ue&64)?Pe(ye,q,Q,!1,!0):(ge===nt&&ue&384||!de&&J&16)&&Pe(xe,q,Q),he&&Ke(D)}(ct&&(dt=Ce&&Ce.onVnodeUnmounted)||Je)&&jn(()=>{dt&&Vr(dt,q,D),Je&&Mo(D,null,q,\"unmounted\")},Q)},Ke=D=>{const{type:q,el:Q,anchor:he,transition:de}=D;if(q===nt){je(Q,he);return}if(q===yd){_(D);return}const ge=()=>{s(Q),de&&!de.persisted&&de.afterLeave&&de.afterLeave()};if(D.shapeFlag&1&&de&&!de.persisted){const{leave:Ce,delayLeave:Ee}=de,xe=()=>Ce(Q,ge);Ee?Ee(D.el,ge,xe):xe()}else ge()},je=(D,q)=>{let Q;for(;D!==q;)Q=b(D),s(D),D=Q;s(q)},Fe=(D,q,Q)=>{const{bum:he,scope:de,job:ge,subTree:Ce,um:Ee,m:xe,a:ye}=D;tv(xe),tv(ye),he&&jc(he),de.stop(),ge&&(ge.flags|=8,Ae(Ce,D,q,Q)),Ee&&jn(Ee,q),jn(()=>{D.isUnmounted=!0},q)},Pe=(D,q,Q,he=!1,de=!1,ge=0)=>{for(let Ce=ge;Ce<D.length;Ce++)Ae(D[Ce],q,Q,he,de)},F=D=>{if(D.shapeFlag&6)return F(D.component.subTree);if(D.shapeFlag&128)return D.suspense.next();const q=b(D.anchor||D.el),Q=q&&q[E_];return Q?b(Q):q};let Y=!1;const re=(D,q,Q)=>{D==null?q._vnode&&Ae(q._vnode,null,null,!0):L(q._vnode||null,D,q,null,null,null,Q),q._vnode=D,Y||(Y=!0,Um(),rb(),Y=!1)},le={p:L,um:Ae,m:Be,r:Ke,mt:C,mc:ee,pc:ce,pbc:G,n:F,o:e};return{render:re,hydrate:void 0,createApp:J_(re)}}function vd({type:e,props:t},r){return r===\"svg\"&&e===\"foreignObject\"||r===\"mathml\"&&e===\"annotation-xml\"&&t&&t.encoding&&t.encoding.includes(\"html\")?void 0:r}function No({effect:e,job:t},r){r?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function vT(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Ib(e,t,r=!1){const o=e.children,s=t.children;if(Ze(o)&&Ze(s))for(let c=0;c<o.length;c++){const f=o[c];let d=s[c];d.shapeFlag&1&&!d.dynamicChildren&&((d.patchFlag<=0||d.patchFlag===32)&&(d=s[c]=Ji(s[c]),d.el=f.el),!r&&d.patchFlag!==-2&&Ib(f,d)),d.type===Ju&&d.patchFlag!==-1&&(d.el=f.el),d.type===ln&&!d.el&&(d.el=f.el)}}function yT(e){const t=e.slice(),r=[0];let o,s,c,f,d;const h=e.length;for(o=0;o<h;o++){const p=e[o];if(p!==0){if(s=r[r.length-1],e[s]<p){t[o]=s,r.push(o);continue}for(c=0,f=r.length-1;c<f;)d=c+f>>1,e[r[d]]<p?c=d+1:f=d;p<e[r[c]]&&(c>0&&(t[o]=r[c-1]),r[c]=o)}}for(c=r.length,f=r[c-1];c-- >0;)r[c]=f,f=t[f];return r}function Db(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Db(t)}function tv(e){if(e)for(let t=0;t<e.length;t++)e[t].flags|=8}const zb=e=>e.__isSuspense;let eh=0;const bT={name:\"Suspense\",__isSuspense:!0,process(e,t,r,o,s,c,f,d,h,p){if(e==null)wT(t,r,o,s,c,f,d,h,p);else{if(c&&c.deps>0&&!e.suspense.isInFallback){t.suspense=e.suspense,t.suspense.vnode=t,t.el=e.el;return}xT(e,t,r,o,s,f,d,h,p)}},hydrate:kT,normalize:ST},np=bT;function ha(e,t){const r=e.props&&e.props[t];et(r)&&r()}function wT(e,t,r,o,s,c,f,d,h){const{p,o:{createElement:g}}=h,v=g(\"div\"),b=e.suspense=Fb(e,s,o,t,v,r,c,f,d,h);p(null,b.pendingBranch=e.ssContent,v,null,o,b,c,f),b.deps>0?(ha(e,\"onPending\"),ha(e,\"onFallback\"),p(null,e.ssFallback,t,r,o,null,c,f),zs(b,e.ssFallback)):b.resolve(!1,!0)}function xT(e,t,r,o,s,c,f,d,{p:h,um:p,o:{createElement:g}}){const v=t.suspense=e.suspense;v.vnode=t,t.el=e.el;const b=t.ssContent,w=t.ssFallback,{activeBranch:E,pendingBranch:L,isInFallback:P,isHydrating:M}=v;if(L)v.pendingBranch=b,Kr(L,b)?(h(L,b,v.hiddenContainer,null,s,v,c,f,d),v.deps<=0?v.resolve():P&&(M||(h(E,w,r,o,s,null,c,f,d),zs(v,w)))):(v.pendingId=eh++,M?(v.isHydrating=!1,v.activeBranch=L):p(L,s,v),v.deps=0,v.effects.length=0,v.hiddenContainer=g(\"div\"),P?(h(null,b,v.hiddenContainer,null,s,v,c,f,d),v.deps<=0?v.resolve():(h(E,w,r,o,s,null,c,f,d),zs(v,w))):E&&Kr(E,b)?(h(E,b,r,o,s,v,c,f,d),v.resolve(!0)):(h(null,b,v.hiddenContainer,null,s,v,c,f,d),v.deps<=0&&v.resolve()));else if(E&&Kr(E,b))h(E,b,r,o,s,v,c,f,d),zs(v,b);else if(ha(t,\"onPending\"),v.pendingBranch=b,b.shapeFlag&512?v.pendingId=b.component.suspenseId:v.pendingId=eh++,h(null,b,v.hiddenContainer,null,s,v,c,f,d),v.deps<=0)v.resolve();else{const{timeout:R,pendingId:I}=v;R>0?setTimeout(()=>{v.pendingId===I&&v.fallback(w)},R):R===0&&v.fallback(w)}}function Fb(e,t,r,o,s,c,f,d,h,p,g=!1){const{p:v,m:b,um:w,n:E,o:{parentNode:L,remove:P}}=p;let M;const R=TT(e);R&&t&&t.pendingBranch&&(M=t.pendingId,t.deps++);const I=e.props?N0(e.props.timeout):void 0,_=c,$={vnode:e,parent:t,parentComponent:r,namespace:f,container:o,hiddenContainer:s,deps:0,pendingId:eh++,timeout:typeof I==\"number\"?I:-1,activeBranch:null,pendingBranch:null,isInFallback:!g,isHydrating:g,isUnmounted:!1,effects:[],resolve(W=!1,ne=!1){const{vnode:ee,activeBranch:Z,pendingBranch:G,pendingId:j,effects:N,parentComponent:O,container:C,isInFallback:k}=$;let z=!1;$.isHydrating?$.isHydrating=!1:W||(z=Z&&G.transition&&G.transition.mode===\"out-in\",z&&(Z.transition.afterLeave=()=>{j===$.pendingId&&(b(G,C,c===_?E(Z):c,0),Gd(N),k&&ee.ssFallback&&(ee.ssFallback.el=null))}),Z&&(L(Z.el)===C&&(c=E(Z)),w(Z,O,$,!0),!z&&k&&ee.ssFallback&&jn(()=>ee.ssFallback.el=null,$)),z||b(G,C,c,0)),zs($,G),$.pendingBranch=null,$.isInFallback=!1;let B=$.parent,ce=!1;for(;B;){if(B.pendingBranch){B.effects.push(...N),ce=!0;break}B=B.parent}!ce&&!z&&Gd(N),$.effects=[],R&&t&&t.pendingBranch&&M===t.pendingId&&(t.deps--,t.deps===0&&!ne&&t.resolve()),ha(ee,\"onResolve\")},fallback(W){if(!$.pendingBranch)return;const{vnode:ne,activeBranch:ee,parentComponent:Z,container:G,namespace:j}=$;ha(ne,\"onFallback\");const N=E(ee),O=()=>{$.isInFallback&&(v(null,W,G,N,Z,null,j,d,h),zs($,W))},C=W.transition&&W.transition.mode===\"out-in\";C&&(ee.transition.afterLeave=O),$.isInFallback=!0,w(ee,Z,null,!0),C||O()},move(W,ne,ee){$.activeBranch&&b($.activeBranch,W,ne,ee),$.container=W},next(){return $.activeBranch&&E($.activeBranch)},registerDep(W,ne,ee){const Z=!!$.pendingBranch;Z&&$.deps++;const G=W.vnode.el;W.asyncDep.catch(j=>{Ra(j,W,0)}).then(j=>{if(W.isUnmounted||$.isUnmounted||$.pendingId!==W.suspenseId)return;W.asyncResolved=!0;const{vnode:N}=W;nh(W,j),G&&(N.el=G);const O=!G&&W.subTree.el;ne(W,N,L(G||W.subTree.el),G?null:E(W.subTree),$,f,ee),O&&(N.placeholder=null,P(O)),Qh(W,N.el),Z&&--$.deps===0&&$.resolve()})},unmount(W,ne){$.isUnmounted=!0,$.activeBranch&&w($.activeBranch,r,W,ne),$.pendingBranch&&w($.pendingBranch,r,W,ne)}};return $}function kT(e,t,r,o,s,c,f,d,h){const p=t.suspense=Fb(t,o,r,e.parentNode,document.createElement(\"div\"),null,s,c,f,d,!0),g=h(e,p.pendingBranch=t.ssContent,r,p,c,f);return p.deps===0&&p.resolve(!1,!0),g}function ST(e){const{shapeFlag:t,children:r}=e,o=t&32;e.ssContent=nv(o?r.default:r),e.ssFallback=o?nv(r.fallback):Ne(ln)}function nv(e){let t;if(et(e)){const r=Xs&&e._c;r&&(e._d=!1,ie()),e=e(),r&&(e._d=!0,t=Xn,Hb())}return Ze(e)&&(e=oT(e)),e=Lr(e),t&&!e.dynamicChildren&&(e.dynamicChildren=t.filter(r=>r!==e)),e}function _T(e,t){t&&t.pendingBranch?Ze(e)?t.effects.push(...e):t.effects.push(e):Gd(e)}function zs(e,t){e.activeBranch=t;const{vnode:r,parentComponent:o}=e;let s=t.el;for(;!s&&t.component;)t=t.component.subTree,s=t.el;r.el=s,o&&o.subTree===r&&(o.vnode.el=s,Qh(o,s))}function TT(e){const t=e.props&&e.props.suspensible;return t!=null&&t!==!1}const nt=Symbol.for(\"v-fgt\"),Ju=Symbol.for(\"v-txt\"),ln=Symbol.for(\"v-cmt\"),yd=Symbol.for(\"v-stc\"),ea=[];let Xn=null;function ie(e=!1){ea.push(Xn=e?null:[])}function Hb(){ea.pop(),Xn=ea[ea.length-1]||null}let Xs=1;function Ys(e,t=!1){Xs+=e,e<0&&Xn&&t&&(Xn.hasOnce=!0)}function Bb(e){return e.dynamicChildren=Xs>0?Xn||Rs:null,Hb(),Xs>0&&Xn&&Xn.push(e),e}function ve(e,t,r,o,s,c){return Bb(X(e,t,r,o,s,c,!0))}function Ve(e,t,r,o,s){return Bb(Ne(e,t,r,o,s,!0))}function Zs(e){return e?e.__v_isVNode===!0:!1}function Kr(e,t){return e.type===t.type&&e.key===t.key}const Wb=({key:e})=>e??null,Uc=({ref:e,ref_key:t,ref_for:r})=>(typeof e==\"number\"&&(e=\"\"+e),e!=null?Ht(e)||Mt(e)||et(e)?{i:mn,r:e,k:t,f:!!r}:e:null);function X(e,t=null,r=null,o=0,s=null,c=e===nt?0:1,f=!1,d=!1){const h={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Wb(t),ref:t&&Uc(t),scopeId:Vu,slotScopeIds:null,children:r,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:c,patchFlag:o,dynamicProps:s,dynamicChildren:null,appContext:null,ctx:mn};return d?(rp(h,r),c&128&&e.normalize(h)):r&&(h.shapeFlag|=Ht(r)?8:16),Xs>0&&!f&&Xn&&(h.patchFlag>0||c&6)&&h.patchFlag!==32&&Xn.push(h),h}const Ne=CT;function CT(e,t=null,r=null,o=0,s=null,c=!1){if((!e||e===mb)&&(e=ln),Zs(e)){const d=uo(e,t,!0);return r&&rp(d,r),Xs>0&&!c&&Xn&&(d.shapeFlag&6?Xn[Xn.indexOf(e)]=d:Xn.push(d)),d.patchFlag=-2,d}if(RT(e)&&(e=e.__vccOpts),t){t=qb(t);let{class:d,style:h}=t;d&&!Ht(d)&&(t.class=ot(d)),kt(h)&&(ju(h)&&!Ze(h)&&(h=on({},h)),t.style=zt(h))}const f=Ht(e)?1:zb(e)?128:ab(e)?64:kt(e)?4:et(e)?2:0;return X(e,t,r,o,s,f,c,!0)}function qb(e){return e?ju(e)||Mb(e)?on({},e):e:null}function uo(e,t,r=!1,o=!1){const{props:s,ref:c,patchFlag:f,children:d,transition:h}=e,p=t?ki(s||{},t):s,g={__v_isVNode:!0,__v_skip:!0,type:e.type,props:p,key:p&&Wb(p),ref:t&&t.ref?r&&c?Ze(c)?c.concat(Uc(t)):[c,Uc(t)]:Uc(t):c,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:d,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==nt?f===-1?16:f|16:f,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:h,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&uo(e.ssContent),ssFallback:e.ssFallback&&uo(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return h&&o&&fa(g,h.clone(g)),g}function Qe(e=\" \",t=0){return Ne(Ju,null,e,t)}function He(e=\"\",t=!1){return t?(ie(),Ve(ln,null,e)):Ne(ln,null,e)}function Lr(e){return e==null||typeof e==\"boolean\"?Ne(ln):Ze(e)?Ne(nt,null,e.slice()):Zs(e)?Ji(e):Ne(Ju,null,String(e))}function Ji(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:uo(e)}function rp(e,t){let r=0;const{shapeFlag:o}=e;if(t==null)t=null;else if(Ze(t))r=16;else if(typeof t==\"object\")if(o&65){const s=t.default;s&&(s._c&&(s._d=!1),rp(e,s()),s._c&&(s._d=!0));return}else{r=32;const s=t._;!s&&!Mb(t)?t._ctx=mn:s===3&&mn&&(mn.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else et(t)?(t={default:t,_ctx:mn},r=32):(t=String(t),o&64?(r=16,t=[Qe(t)]):r=8);e.children=t,e.shapeFlag|=r}function ki(...e){const t={};for(let r=0;r<e.length;r++){const o=e[r];for(const s in o)if(s===\"class\")t.class!==o.class&&(t.class=ot([t.class,o.class]));else if(s===\"style\")t.style=zt([t.style,o.style]);else if($u(s)){const c=t[s],f=o[s];f&&c!==f&&!(Ze(c)&&c.includes(f))&&(t[s]=c?[].concat(c,f):f)}else s!==\"\"&&(t[s]=o[s])}return t}function Vr(e,t,r,o=null){$r(e,t,7,[r,o])}const ET=kb();let AT=0;function LT(e,t,r){const o=e.type,s=(t?t.appContext:e.appContext)||ET,c={uid:AT++,vnode:e,type:o,parent:t,appContext:s,root:null,next:null,subTree:null,effect:null,update:null,job:null,scope:new GS(!0),render:null,proxy:null,exposed:null,exposeProxy:null,withProxy:null,provides:t?t.provides:Object.create(s.provides),ids:t?t.ids:[\"\",0,0],accessCache:null,renderCache:[],components:null,directives:null,propsOptions:Ob(o,s),emitsOptions:Eb(o,s),emit:null,emitted:null,propsDefaults:vt,inheritAttrs:o.inheritAttrs,ctx:vt,data:vt,props:vt,attrs:vt,slots:vt,refs:vt,setupState:vt,setupContext:null,suspense:r,suspenseId:r?r.pendingId:0,asyncDep:null,asyncResolved:!1,isMounted:!1,isUnmounted:!1,isDeactivated:!1,bc:null,c:null,bm:null,m:null,bu:null,u:null,um:null,bum:null,da:null,a:null,rtg:null,rtc:null,ec:null,sp:null};return c.ctx={_:c},c.root=t?t.root:c,c.emit=rT.bind(null,c),e.ce&&e.ce(c),c}let xn=null;const ti=()=>xn||mn;let fu,th;{const e=Hu(),t=(r,o)=>{let s;return(s=e[r])||(s=e[r]=[]),s.push(o),c=>{s.length>1?s.forEach(f=>f(c)):s[0](c)}};fu=t(\"__VUE_INSTANCE_SETTERS__\",r=>xn=r),th=t(\"__VUE_SSR_SETTERS__\",r=>pa=r)}const Da=e=>{const t=xn;return fu(e),e.scope.on(),()=>{e.scope.off(),fu(t)}},rv=()=>{xn&&xn.scope.off(),fu(null)};function jb(e){return e.vnode.shapeFlag&4}let pa=!1;function MT(e,t=!1,r=!1){t&&th(t);const{props:o,children:s}=e.vnode,c=jb(e);cT(e,o,c,t),hT(e,s,r||t);const f=c?NT(e,t):void 0;return t&&th(!1),f}function NT(e,t){const r=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,j_);const{setup:o}=r;if(o){Si();const s=e.setupContext=o.length>1?Vb(e):null,c=Da(e),f=Pa(o,e,0,[e.props,s]),d=E0(f);if(_i(),c(),(d||e.sp)&&!Ds(e)&&pb(e),d){if(f.then(rv,rv),t)return f.then(h=>{nh(e,h)}).catch(h=>{Ra(h,e,0)});e.asyncDep=f}else nh(e,f)}else Ub(e)}function nh(e,t,r){et(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:kt(t)&&(e.setupState=J0(t)),Ub(e)}function Ub(e,t,r){const o=e.type;e.render||(e.render=o.render||Xr);{const s=Da(e);Si();try{V_(e)}finally{_i(),s()}}}const OT={get(e,t){return wn(e,\"get\",\"\"),e[t]}};function Vb(e){const t=r=>{e.exposed=r||{}};return{attrs:new Proxy(e.attrs,OT),slots:e.slots,emit:e.emit,expose:t}}function Qu(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(J0(Uu(e.exposed)),{get(t,r){if(r in t)return t[r];if(r in Ql)return Ql[r](e)},has(t,r){return r in t||r in Ql}})):e.proxy}function PT(e,t=!0){return et(e)?e.displayName||e.name:e.name||t&&e.__name}function RT(e){return et(e)&&\"__vccOpts\"in e}const ke=(e,t)=>k_(e,t,pa);function za(e,t,r){try{Ys(-1);const o=arguments.length;return o===2?kt(t)&&!Ze(t)?Zs(t)?Ne(e,null,[t]):Ne(e,t):Ne(e,null,t):(o>3?r=Array.prototype.slice.call(arguments,2):o===3&&Zs(r)&&(r=[r]),Ne(e,t,r))}finally{Ys(1)}}const $T=\"3.5.25\";/**\n* @vue/runtime-dom v3.5.25\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/let rh;const iv=typeof window<\"u\"&&window.trustedTypes;if(iv)try{rh=iv.createPolicy(\"vue\",{createHTML:e=>e})}catch{}const Gb=rh?e=>rh.createHTML(e):e=>e,IT=\"http://www.w3.org/2000/svg\",DT=\"http://www.w3.org/1998/Math/MathML\",mi=typeof document<\"u\"?document:null,ov=mi&&mi.createElement(\"template\"),zT={insert:(e,t,r)=>{t.insertBefore(e,r||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,r,o)=>{const s=t===\"svg\"?mi.createElementNS(IT,e):t===\"mathml\"?mi.createElementNS(DT,e):r?mi.createElement(e,{is:r}):mi.createElement(e);return e===\"select\"&&o&&o.multiple!=null&&s.setAttribute(\"multiple\",o.multiple),s},createText:e=>mi.createTextNode(e),createComment:e=>mi.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>mi.querySelector(e),setScopeId(e,t){e.setAttribute(t,\"\")},insertStaticContent(e,t,r,o,s,c){const f=r?r.previousSibling:t.lastChild;if(s&&(s===c||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),r),!(s===c||!(s=s.nextSibling)););else{ov.innerHTML=Gb(o===\"svg\"?`<svg>${e}</svg>`:o===\"mathml\"?`<math>${e}</math>`:e);const d=ov.content;if(o===\"svg\"||o===\"mathml\"){const h=d.firstChild;for(;h.firstChild;)d.appendChild(h.firstChild);d.removeChild(h)}t.insertBefore(d,r)}return[f?f.nextSibling:t.firstChild,r?r.previousSibling:t.lastChild]}},Ui=\"transition\",zl=\"animation\",ga=Symbol(\"_vtc\"),Kb={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},FT=on({},cb,Kb),HT=e=>(e.displayName=\"Transition\",e.props=FT,e),BT=HT((e,{slots:t})=>za(M_,WT(e),t)),Oo=(e,t=[])=>{Ze(e)?e.forEach(r=>r(...t)):e&&e(...t)},sv=e=>e?Ze(e)?e.some(t=>t.length>1):e.length>1:!1;function WT(e){const t={};for(const N in e)N in Kb||(t[N]=e[N]);if(e.css===!1)return t;const{name:r=\"v\",type:o,duration:s,enterFromClass:c=`${r}-enter-from`,enterActiveClass:f=`${r}-enter-active`,enterToClass:d=`${r}-enter-to`,appearFromClass:h=c,appearActiveClass:p=f,appearToClass:g=d,leaveFromClass:v=`${r}-leave-from`,leaveActiveClass:b=`${r}-leave-active`,leaveToClass:w=`${r}-leave-to`}=e,E=qT(s),L=E&&E[0],P=E&&E[1],{onBeforeEnter:M,onEnter:R,onEnterCancelled:I,onLeave:_,onLeaveCancelled:$,onBeforeAppear:W=M,onAppear:ne=R,onAppearCancelled:ee=I}=t,Z=(N,O,C,k)=>{N._enterCancelled=k,Po(N,O?g:d),Po(N,O?p:f),C&&C()},G=(N,O)=>{N._isLeaving=!1,Po(N,v),Po(N,w),Po(N,b),O&&O()},j=N=>(O,C)=>{const k=N?ne:R,z=()=>Z(O,N,C);Oo(k,[O,z]),lv(()=>{Po(O,N?h:c),di(O,N?g:d),sv(k)||av(O,o,L,z)})};return on(t,{onBeforeEnter(N){Oo(M,[N]),di(N,c),di(N,f)},onBeforeAppear(N){Oo(W,[N]),di(N,h),di(N,p)},onEnter:j(!1),onAppear:j(!0),onLeave(N,O){N._isLeaving=!0;const C=()=>G(N,O);di(N,v),N._enterCancelled?(di(N,b),fv(N)):(fv(N),di(N,b)),lv(()=>{N._isLeaving&&(Po(N,v),di(N,w),sv(_)||av(N,o,P,C))}),Oo(_,[N,C])},onEnterCancelled(N){Z(N,!1,void 0,!0),Oo(I,[N])},onAppearCancelled(N){Z(N,!0,void 0,!0),Oo(ee,[N])},onLeaveCancelled(N){G(N),Oo($,[N])}})}function qT(e){if(e==null)return null;if(kt(e))return[bd(e.enter),bd(e.leave)];{const t=bd(e);return[t,t]}}function bd(e){return N0(e)}function di(e,t){t.split(/\\s+/).forEach(r=>r&&e.classList.add(r)),(e[ga]||(e[ga]=new Set)).add(t)}function Po(e,t){t.split(/\\s+/).forEach(o=>o&&e.classList.remove(o));const r=e[ga];r&&(r.delete(t),r.size||(e[ga]=void 0))}function lv(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let jT=0;function av(e,t,r,o){const s=e._endId=++jT,c=()=>{s===e._endId&&o()};if(r!=null)return setTimeout(c,r);const{type:f,timeout:d,propCount:h}=UT(e,t);if(!f)return o();const p=f+\"end\";let g=0;const v=()=>{e.removeEventListener(p,b),c()},b=w=>{w.target===e&&++g>=h&&v()};setTimeout(()=>{g<h&&v()},d+1),e.addEventListener(p,b)}function UT(e,t){const r=window.getComputedStyle(e),o=E=>(r[E]||\"\").split(\", \"),s=o(`${Ui}Delay`),c=o(`${Ui}Duration`),f=cv(s,c),d=o(`${zl}Delay`),h=o(`${zl}Duration`),p=cv(d,h);let g=null,v=0,b=0;t===Ui?f>0&&(g=Ui,v=f,b=c.length):t===zl?p>0&&(g=zl,v=p,b=h.length):(v=Math.max(f,p),g=v>0?f>p?Ui:zl:null,b=g?g===Ui?c.length:h.length:0);const w=g===Ui&&/\\b(?:transform|all)(?:,|$)/.test(o(`${Ui}Property`).toString());return{type:g,timeout:v,propCount:b,hasTransform:w}}function cv(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max(...t.map((r,o)=>uv(r)+uv(e[o])))}function uv(e){return e===\"auto\"?0:Number(e.slice(0,-1).replace(\",\",\".\"))*1e3}function fv(e){return(e?e.ownerDocument:document).body.offsetHeight}function VT(e,t,r){const o=e[ga];o&&(t=(t?[t,...o]:[...o]).join(\" \")),t==null?e.removeAttribute(\"class\"):r?e.setAttribute(\"class\",t):e.className=t}const du=Symbol(\"_vod\"),Xb=Symbol(\"_vsh\"),ro={name:\"show\",beforeMount(e,{value:t},{transition:r}){e[du]=e.style.display===\"none\"?\"\":e.style.display,r&&t?r.beforeEnter(e):Fl(e,t)},mounted(e,{value:t},{transition:r}){r&&t&&r.enter(e)},updated(e,{value:t,oldValue:r},{transition:o}){!t!=!r&&(o?t?(o.beforeEnter(e),Fl(e,!0),o.enter(e)):o.leave(e,()=>{Fl(e,!1)}):Fl(e,t))},beforeUnmount(e,{value:t}){Fl(e,t)}};function Fl(e,t){e.style.display=t?e[du]:\"none\",e[Xb]=!t}const GT=Symbol(\"\"),KT=/(?:^|;)\\s*display\\s*:/;function XT(e,t,r){const o=e.style,s=Ht(r);let c=!1;if(r&&!s){if(t)if(Ht(t))for(const f of t.split(\";\")){const d=f.slice(0,f.indexOf(\":\")).trim();r[d]==null&&Vc(o,d,\"\")}else for(const f in t)r[f]==null&&Vc(o,f,\"\");for(const f in r)f===\"display\"&&(c=!0),Vc(o,f,r[f])}else if(s){if(t!==r){const f=o[GT];f&&(r+=\";\"+f),o.cssText=r,c=KT.test(r)}}else t&&e.removeAttribute(\"style\");du in e&&(e[du]=c?o.display:\"\",e[Xb]&&(o.display=\"none\"))}const dv=/\\s*!important$/;function Vc(e,t,r){if(Ze(r))r.forEach(o=>Vc(e,t,o));else if(r==null&&(r=\"\"),t.startsWith(\"--\"))e.setProperty(t,r);else{const o=YT(e,t);dv.test(r)?e.setProperty(Ai(o),r.replace(dv,\"\"),\"important\"):e[o]=r}}const hv=[\"Webkit\",\"Moz\",\"ms\"],wd={};function YT(e,t){const r=wd[t];if(r)return r;let o=sr(t);if(o!==\"filter\"&&o in e)return wd[t]=o;o=Fu(o);for(let s=0;s<hv.length;s++){const c=hv[s]+o;if(c in e)return wd[t]=c}return t}const pv=\"http://www.w3.org/1999/xlink\";function gv(e,t,r,o,s,c=US(t)){o&&t.startsWith(\"xlink:\")?r==null?e.removeAttributeNS(pv,t.slice(6,t.length)):e.setAttributeNS(pv,t,r):r==null||c&&!O0(r)?e.removeAttribute(t):e.setAttribute(t,c?\"\":Pr(r)?String(r):r)}function mv(e,t,r,o,s){if(t===\"innerHTML\"||t===\"textContent\"){r!=null&&(e[t]=t===\"innerHTML\"?Gb(r):r);return}const c=e.tagName;if(t===\"value\"&&c!==\"PROGRESS\"&&!c.includes(\"-\")){const d=c===\"OPTION\"?e.getAttribute(\"value\")||\"\":e.value,h=r==null?e.type===\"checkbox\"?\"on\":\"\":String(r);(d!==h||!(\"_value\"in e))&&(e.value=h),r==null&&e.removeAttribute(t),e._value=r;return}let f=!1;if(r===\"\"||r==null){const d=typeof e[t];d===\"boolean\"?r=O0(r):r==null&&d===\"string\"?(r=\"\",f=!0):d===\"number\"&&(r=0,f=!0)}try{e[t]=r}catch{}f&&e.removeAttribute(s||t)}function zo(e,t,r,o){e.addEventListener(t,r,o)}function ZT(e,t,r,o){e.removeEventListener(t,r,o)}const vv=Symbol(\"_vei\");function JT(e,t,r,o,s=null){const c=e[vv]||(e[vv]={}),f=c[t];if(o&&f)f.value=o;else{const[d,h]=QT(t);if(o){const p=c[t]=nC(o,s);zo(e,d,p,h)}else f&&(ZT(e,d,f,h),c[t]=void 0)}}const yv=/(?:Once|Passive|Capture)$/;function QT(e){let t;if(yv.test(e)){t={};let o;for(;o=e.match(yv);)e=e.slice(0,e.length-o[0].length),t[o[0].toLowerCase()]=!0}return[e[2]===\":\"?e.slice(3):Ai(e.slice(2)),t]}let xd=0;const eC=Promise.resolve(),tC=()=>xd||(eC.then(()=>xd=0),xd=Date.now());function nC(e,t){const r=o=>{if(!o._vts)o._vts=Date.now();else if(o._vts<=r.attached)return;$r(rC(o,r.value),t,5,[o])};return r.value=e,r.attached=tC(),r}function rC(e,t){if(Ze(t)){const r=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{r.call(e),e._stopped=!0},t.map(o=>s=>!s._stopped&&o&&o(s))}else return t}const bv=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,iC=(e,t,r,o,s,c)=>{const f=s===\"svg\";t===\"class\"?VT(e,o,f):t===\"style\"?XT(e,r,o):$u(t)?Hh(t)||JT(e,t,r,o,c):(t[0]===\".\"?(t=t.slice(1),!0):t[0]===\"^\"?(t=t.slice(1),!1):oC(e,t,o,f))?(mv(e,t,o),!e.tagName.includes(\"-\")&&(t===\"value\"||t===\"checked\"||t===\"selected\")&&gv(e,t,o,f,c,t!==\"value\")):e._isVueCE&&(/[A-Z]/.test(t)||!Ht(o))?mv(e,sr(t),o,c,t):(t===\"true-value\"?e._trueValue=o:t===\"false-value\"&&(e._falseValue=o),gv(e,t,o,f))};function oC(e,t,r,o){if(o)return!!(t===\"innerHTML\"||t===\"textContent\"||t in e&&bv(t)&&et(r));if(t===\"spellcheck\"||t===\"draggable\"||t===\"translate\"||t===\"autocorrect\"||t===\"sandbox\"&&e.tagName===\"IFRAME\"||t===\"form\"||t===\"list\"&&e.tagName===\"INPUT\"||t===\"type\"&&e.tagName===\"TEXTAREA\")return!1;if(t===\"width\"||t===\"height\"){const s=e.tagName;if(s===\"IMG\"||s===\"VIDEO\"||s===\"CANVAS\"||s===\"SOURCE\")return!1}return bv(t)&&Ht(r)?!1:t in e}const hu=e=>{const t=e.props[\"onUpdate:modelValue\"]||!1;return Ze(t)?r=>jc(t,r):t};function sC(e){e.target.composing=!0}function wv(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event(\"input\")))}const Fs=Symbol(\"_assign\");function xv(e,t,r){return t&&(e=e.trim()),r&&(e=Wh(e)),e}const Yb={created(e,{modifiers:{lazy:t,trim:r,number:o}},s){e[Fs]=hu(s);const c=o||s.props&&s.props.type===\"number\";zo(e,t?\"change\":\"input\",f=>{f.target.composing||e[Fs](xv(e.value,r,c))}),(r||c)&&zo(e,\"change\",()=>{e.value=xv(e.value,r,c)}),t||(zo(e,\"compositionstart\",sC),zo(e,\"compositionend\",wv),zo(e,\"change\",wv))},mounted(e,{value:t}){e.value=t??\"\"},beforeUpdate(e,{value:t,oldValue:r,modifiers:{lazy:o,trim:s,number:c}},f){if(e[Fs]=hu(f),e.composing)return;const d=(c||e.type===\"number\")&&!/^0\\d/.test(e.value)?Wh(e.value):e.value,h=t??\"\";d!==h&&(document.activeElement===e&&e.type!==\"range\"&&(o&&t===r||s&&e.value.trim()===h)||(e.value=h))}},Zb={deep:!0,created(e,t,r){e[Fs]=hu(r),zo(e,\"change\",()=>{const o=e._modelValue,s=lC(e),c=e.checked,f=e[Fs];if(Ze(o)){const d=P0(o,s),h=d!==-1;if(c&&!h)f(o.concat(s));else if(!c&&h){const p=[...o];p.splice(d,1),f(p)}}else if(Iu(o)){const d=new Set(o);c?d.add(s):d.delete(s),f(d)}else f(Jb(e,c))})},mounted:kv,beforeUpdate(e,t,r){e[Fs]=hu(r),kv(e,t,r)}};function kv(e,{value:t,oldValue:r},o){e._modelValue=t;let s;if(Ze(t))s=P0(t,o.props.value)>-1;else if(Iu(t))s=t.has(o.props.value);else{if(t===r)return;s=Bu(t,Jb(e,!0))}e.checked!==s&&(e.checked=s)}function lC(e){return\"_value\"in e?e._value:e.value}function Jb(e,t){const r=t?\"_trueValue\":\"_falseValue\";return r in e?e[r]:t}const aC=[\"ctrl\",\"shift\",\"alt\",\"meta\"],cC={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>\"button\"in e&&e.button!==0,middle:e=>\"button\"in e&&e.button!==1,right:e=>\"button\"in e&&e.button!==2,exact:(e,t)=>aC.some(r=>e[`${r}Key`]&&!t.includes(r))},Gc=(e,t)=>{const r=e._withMods||(e._withMods={}),o=t.join(\".\");return r[o]||(r[o]=((s,...c)=>{for(let f=0;f<t.length;f++){const d=cC[t[f]];if(d&&d(s,t))return}return e(s,...c)}))},uC={esc:\"escape\",space:\" \",up:\"arrow-up\",left:\"arrow-left\",right:\"arrow-right\",down:\"arrow-down\",delete:\"backspace\"},ih=(e,t)=>{const r=e._withKeys||(e._withKeys={}),o=t.join(\".\");return r[o]||(r[o]=(s=>{if(!(\"key\"in s))return;const c=Ai(s.key);if(t.some(f=>f===c||uC[f]===c))return e(s)}))},fC=on({patchProp:iC},zT);let Sv;function dC(){return Sv||(Sv=gT(fC))}const Qb=((...e)=>{const t=dC().createApp(...e),{mount:r}=t;return t.mount=o=>{const s=pC(o);if(!s)return;const c=t._component;!et(c)&&!c.render&&!c.template&&(c.template=s.innerHTML),s.nodeType===1&&(s.textContent=\"\");const f=r(s,!1,hC(s));return s instanceof Element&&(s.removeAttribute(\"v-cloak\"),s.setAttribute(\"data-v-app\",\"\")),f},t});function hC(e){if(e instanceof SVGElement)return\"svg\";if(typeof MathMLElement==\"function\"&&e instanceof MathMLElement)return\"mathml\"}function pC(e){return Ht(e)?document.querySelector(e):e}const Ni=(e,t)=>{const r=e.__vccOpts||e;for(const[o,s]of t)r[o]=s;return r},gC={};function mC(e,t){const r=Go(\"RouterView\");return ie(),Ve(r)}const vC=Ni(gC,[[\"render\",mC]]),yC=[\"top\",\"right\",\"bottom\",\"left\"],_v=[\"start\",\"end\"],Tv=yC.reduce((e,t)=>e.concat(t,t+\"-\"+_v[0],t+\"-\"+_v[1]),[]),ma=Math.min,Io=Math.max,bC={left:\"right\",right:\"left\",bottom:\"top\",top:\"bottom\"},wC={start:\"end\",end:\"start\"};function oh(e,t,r){return Io(e,ma(t,r))}function Xo(e,t){return typeof e==\"function\"?e(t):e}function Qr(e){return e.split(\"-\")[0]}function Or(e){return e.split(\"-\")[1]}function ew(e){return e===\"x\"?\"y\":\"x\"}function ip(e){return e===\"y\"?\"height\":\"width\"}function Fa(e){return[\"top\",\"bottom\"].includes(Qr(e))?\"y\":\"x\"}function op(e){return ew(Fa(e))}function tw(e,t,r){r===void 0&&(r=!1);const o=Or(e),s=op(e),c=ip(s);let f=s===\"x\"?o===(r?\"end\":\"start\")?\"right\":\"left\":o===\"start\"?\"bottom\":\"top\";return t.reference[c]>t.floating[c]&&(f=gu(f)),[f,gu(f)]}function xC(e){const t=gu(e);return[pu(e),t,pu(t)]}function pu(e){return e.replace(/start|end/g,t=>wC[t])}function kC(e,t,r){const o=[\"left\",\"right\"],s=[\"right\",\"left\"],c=[\"top\",\"bottom\"],f=[\"bottom\",\"top\"];switch(e){case\"top\":case\"bottom\":return r?t?s:o:t?o:s;case\"left\":case\"right\":return t?c:f;default:return[]}}function SC(e,t,r,o){const s=Or(e);let c=kC(Qr(e),r===\"start\",o);return s&&(c=c.map(f=>f+\"-\"+s),t&&(c=c.concat(c.map(pu)))),c}function gu(e){return e.replace(/left|right|bottom|top/g,t=>bC[t])}function _C(e){return{top:0,right:0,bottom:0,left:0,...e}}function nw(e){return typeof e!=\"number\"?_C(e):{top:e,right:e,bottom:e,left:e}}function ta(e){return{...e,top:e.y,left:e.x,right:e.x+e.width,bottom:e.y+e.height}}function Cv(e,t,r){let{reference:o,floating:s}=e;const c=Fa(t),f=op(t),d=ip(f),h=Qr(t),p=c===\"y\",g=o.x+o.width/2-s.width/2,v=o.y+o.height/2-s.height/2,b=o[d]/2-s[d]/2;let w;switch(h){case\"top\":w={x:g,y:o.y-s.height};break;case\"bottom\":w={x:g,y:o.y+o.height};break;case\"right\":w={x:o.x+o.width,y:v};break;case\"left\":w={x:o.x-s.width,y:v};break;default:w={x:o.x,y:o.y}}switch(Or(t)){case\"start\":w[f]-=b*(r&&p?-1:1);break;case\"end\":w[f]+=b*(r&&p?-1:1);break}return w}const TC=async(e,t,r)=>{const{placement:o=\"bottom\",strategy:s=\"absolute\",middleware:c=[],platform:f}=r,d=c.filter(Boolean),h=await(f.isRTL==null?void 0:f.isRTL(t));let p=await f.getElementRects({reference:e,floating:t,strategy:s}),{x:g,y:v}=Cv(p,o,h),b=o,w={},E=0;for(let L=0;L<d.length;L++){const{name:P,fn:M}=d[L],{x:R,y:I,data:_,reset:$}=await M({x:g,y:v,initialPlacement:o,placement:b,strategy:s,middlewareData:w,rects:p,platform:f,elements:{reference:e,floating:t}});g=R??g,v=I??v,w={...w,[P]:{...w[P],..._}},$&&E<=50&&(E++,typeof $==\"object\"&&($.placement&&(b=$.placement),$.rects&&(p=$.rects===!0?await f.getElementRects({reference:e,floating:t,strategy:s}):$.rects),{x:g,y:v}=Cv(p,b,h)),L=-1)}return{x:g,y:v,placement:b,strategy:s,middlewareData:w}};async function ef(e,t){var r;t===void 0&&(t={});const{x:o,y:s,platform:c,rects:f,elements:d,strategy:h}=e,{boundary:p=\"clippingAncestors\",rootBoundary:g=\"viewport\",elementContext:v=\"floating\",altBoundary:b=!1,padding:w=0}=Xo(t,e),E=nw(w),P=d[b?v===\"floating\"?\"reference\":\"floating\":v],M=ta(await c.getClippingRect({element:(r=await(c.isElement==null?void 0:c.isElement(P)))==null||r?P:P.contextElement||await(c.getDocumentElement==null?void 0:c.getDocumentElement(d.floating)),boundary:p,rootBoundary:g,strategy:h})),R=v===\"floating\"?{...f.floating,x:o,y:s}:f.reference,I=await(c.getOffsetParent==null?void 0:c.getOffsetParent(d.floating)),_=await(c.isElement==null?void 0:c.isElement(I))?await(c.getScale==null?void 0:c.getScale(I))||{x:1,y:1}:{x:1,y:1},$=ta(c.convertOffsetParentRelativeRectToViewportRelativeRect?await c.convertOffsetParentRelativeRectToViewportRelativeRect({elements:d,rect:R,offsetParent:I,strategy:h}):R);return{top:(M.top-$.top+E.top)/_.y,bottom:($.bottom-M.bottom+E.bottom)/_.y,left:(M.left-$.left+E.left)/_.x,right:($.right-M.right+E.right)/_.x}}const CC=e=>({name:\"arrow\",options:e,async fn(t){const{x:r,y:o,placement:s,rects:c,platform:f,elements:d,middlewareData:h}=t,{element:p,padding:g=0}=Xo(e,t)||{};if(p==null)return{};const v=nw(g),b={x:r,y:o},w=op(s),E=ip(w),L=await f.getDimensions(p),P=w===\"y\",M=P?\"top\":\"left\",R=P?\"bottom\":\"right\",I=P?\"clientHeight\":\"clientWidth\",_=c.reference[E]+c.reference[w]-b[w]-c.floating[E],$=b[w]-c.reference[w],W=await(f.getOffsetParent==null?void 0:f.getOffsetParent(p));let ne=W?W[I]:0;(!ne||!await(f.isElement==null?void 0:f.isElement(W)))&&(ne=d.floating[I]||c.floating[E]);const ee=_/2-$/2,Z=ne/2-L[E]/2-1,G=ma(v[M],Z),j=ma(v[R],Z),N=G,O=ne-L[E]-j,C=ne/2-L[E]/2+ee,k=oh(N,C,O),z=!h.arrow&&Or(s)!=null&&C!==k&&c.reference[E]/2-(C<N?G:j)-L[E]/2<0,B=z?C<N?C-N:C-O:0;return{[w]:b[w]+B,data:{[w]:k,centerOffset:C-k-B,...z&&{alignmentOffset:B}},reset:z}}});function EC(e,t,r){return(e?[...r.filter(s=>Or(s)===e),...r.filter(s=>Or(s)!==e)]:r.filter(s=>Qr(s)===s)).filter(s=>e?Or(s)===e||(t?pu(s)!==s:!1):!0)}const AC=function(e){return e===void 0&&(e={}),{name:\"autoPlacement\",options:e,async fn(t){var r,o,s;const{rects:c,middlewareData:f,placement:d,platform:h,elements:p}=t,{crossAxis:g=!1,alignment:v,allowedPlacements:b=Tv,autoAlignment:w=!0,...E}=Xo(e,t),L=v!==void 0||b===Tv?EC(v||null,w,b):b,P=await ef(t,E),M=((r=f.autoPlacement)==null?void 0:r.index)||0,R=L[M];if(R==null)return{};const I=tw(R,c,await(h.isRTL==null?void 0:h.isRTL(p.floating)));if(d!==R)return{reset:{placement:L[0]}};const _=[P[Qr(R)],P[I[0]],P[I[1]]],$=[...((o=f.autoPlacement)==null?void 0:o.overflows)||[],{placement:R,overflows:_}],W=L[M+1];if(W)return{data:{index:M+1,overflows:$},reset:{placement:W}};const ne=$.map(G=>{const j=Or(G.placement);return[G.placement,j&&g?G.overflows.slice(0,2).reduce((N,O)=>N+O,0):G.overflows[0],G.overflows]}).sort((G,j)=>G[1]-j[1]),Z=((s=ne.filter(G=>G[2].slice(0,Or(G[0])?2:3).every(j=>j<=0))[0])==null?void 0:s[0])||ne[0][0];return Z!==d?{data:{index:M+1,overflows:$},reset:{placement:Z}}:{}}}},LC=function(e){return e===void 0&&(e={}),{name:\"flip\",options:e,async fn(t){var r,o;const{placement:s,middlewareData:c,rects:f,initialPlacement:d,platform:h,elements:p}=t,{mainAxis:g=!0,crossAxis:v=!0,fallbackPlacements:b,fallbackStrategy:w=\"bestFit\",fallbackAxisSideDirection:E=\"none\",flipAlignment:L=!0,...P}=Xo(e,t);if((r=c.arrow)!=null&&r.alignmentOffset)return{};const M=Qr(s),R=Qr(d)===d,I=await(h.isRTL==null?void 0:h.isRTL(p.floating)),_=b||(R||!L?[gu(d)]:xC(d));!b&&E!==\"none\"&&_.push(...SC(d,L,E,I));const $=[d,..._],W=await ef(t,P),ne=[];let ee=((o=c.flip)==null?void 0:o.overflows)||[];if(g&&ne.push(W[M]),v){const N=tw(s,f,I);ne.push(W[N[0]],W[N[1]])}if(ee=[...ee,{placement:s,overflows:ne}],!ne.every(N=>N<=0)){var Z,G;const N=(((Z=c.flip)==null?void 0:Z.index)||0)+1,O=$[N];if(O)return{data:{index:N,overflows:ee},reset:{placement:O}};let C=(G=ee.filter(k=>k.overflows[0]<=0).sort((k,z)=>k.overflows[1]-z.overflows[1])[0])==null?void 0:G.placement;if(!C)switch(w){case\"bestFit\":{var j;const k=(j=ee.map(z=>[z.placement,z.overflows.filter(B=>B>0).reduce((B,ce)=>B+ce,0)]).sort((z,B)=>z[1]-B[1])[0])==null?void 0:j[0];k&&(C=k);break}case\"initialPlacement\":C=d;break}if(s!==C)return{reset:{placement:C}}}return{}}}};async function MC(e,t){const{placement:r,platform:o,elements:s}=e,c=await(o.isRTL==null?void 0:o.isRTL(s.floating)),f=Qr(r),d=Or(r),h=Fa(r)===\"y\",p=[\"left\",\"top\"].includes(f)?-1:1,g=c&&h?-1:1,v=Xo(t,e);let{mainAxis:b,crossAxis:w,alignmentAxis:E}=typeof v==\"number\"?{mainAxis:v,crossAxis:0,alignmentAxis:null}:{mainAxis:0,crossAxis:0,alignmentAxis:null,...v};return d&&typeof E==\"number\"&&(w=d===\"end\"?E*-1:E),h?{x:w*g,y:b*p}:{x:b*p,y:w*g}}const NC=function(e){return e===void 0&&(e=0),{name:\"offset\",options:e,async fn(t){var r,o;const{x:s,y:c,placement:f,middlewareData:d}=t,h=await MC(t,e);return f===((r=d.offset)==null?void 0:r.placement)&&(o=d.arrow)!=null&&o.alignmentOffset?{}:{x:s+h.x,y:c+h.y,data:{...h,placement:f}}}}},OC=function(e){return e===void 0&&(e={}),{name:\"shift\",options:e,async fn(t){const{x:r,y:o,placement:s}=t,{mainAxis:c=!0,crossAxis:f=!1,limiter:d={fn:P=>{let{x:M,y:R}=P;return{x:M,y:R}}},...h}=Xo(e,t),p={x:r,y:o},g=await ef(t,h),v=Fa(Qr(s)),b=ew(v);let w=p[b],E=p[v];if(c){const P=b===\"y\"?\"top\":\"left\",M=b===\"y\"?\"bottom\":\"right\",R=w+g[P],I=w-g[M];w=oh(R,w,I)}if(f){const P=v===\"y\"?\"top\":\"left\",M=v===\"y\"?\"bottom\":\"right\",R=E+g[P],I=E-g[M];E=oh(R,E,I)}const L=d.fn({...t,[b]:w,[v]:E});return{...L,data:{x:L.x-r,y:L.y-o}}}}},PC=function(e){return e===void 0&&(e={}),{name:\"size\",options:e,async fn(t){const{placement:r,rects:o,platform:s,elements:c}=t,{apply:f=()=>{},...d}=Xo(e,t),h=await ef(t,d),p=Qr(r),g=Or(r),v=Fa(r)===\"y\",{width:b,height:w}=o.floating;let E,L;p===\"top\"||p===\"bottom\"?(E=p,L=g===(await(s.isRTL==null?void 0:s.isRTL(c.floating))?\"start\":\"end\")?\"left\":\"right\"):(L=p,E=g===\"end\"?\"top\":\"bottom\");const P=w-h[E],M=b-h[L],R=!t.middlewareData.shift;let I=P,_=M;if(v){const W=b-h.left-h.right;_=g||R?ma(M,W):W}else{const W=w-h.top-h.bottom;I=g||R?ma(P,W):W}if(R&&!g){const W=Io(h.left,0),ne=Io(h.right,0),ee=Io(h.top,0),Z=Io(h.bottom,0);v?_=b-2*(W!==0||ne!==0?W+ne:Io(h.left,h.right)):I=w-2*(ee!==0||Z!==0?ee+Z:Io(h.top,h.bottom))}await f({...t,availableWidth:_,availableHeight:I});const $=await s.getDimensions(c.floating);return b!==$.width||w!==$.height?{reset:{rects:!0}}:{}}}};function hr(e){var t;return((t=e.ownerDocument)==null?void 0:t.defaultView)||window}function Yr(e){return hr(e).getComputedStyle(e)}const Ev=Math.min,na=Math.max,mu=Math.round;function rw(e){const t=Yr(e);let r=parseFloat(t.width),o=parseFloat(t.height);const s=e.offsetWidth,c=e.offsetHeight,f=mu(r)!==s||mu(o)!==c;return f&&(r=s,o=c),{width:r,height:o,fallback:f}}function fo(e){return ow(e)?(e.nodeName||\"\").toLowerCase():\"\"}let Lc;function iw(){if(Lc)return Lc;const e=navigator.userAgentData;return e&&Array.isArray(e.brands)?(Lc=e.brands.map((t=>t.brand+\"/\"+t.version)).join(\" \"),Lc):navigator.userAgent}function Zr(e){return e instanceof hr(e).HTMLElement}function so(e){return e instanceof hr(e).Element}function ow(e){return e instanceof hr(e).Node}function Av(e){return typeof ShadowRoot>\"u\"?!1:e instanceof hr(e).ShadowRoot||e instanceof ShadowRoot}function tf(e){const{overflow:t,overflowX:r,overflowY:o,display:s}=Yr(e);return/auto|scroll|overlay|hidden|clip/.test(t+o+r)&&![\"inline\",\"contents\"].includes(s)}function RC(e){return[\"table\",\"td\",\"th\"].includes(fo(e))}function sh(e){const t=/firefox/i.test(iw()),r=Yr(e),o=r.backdropFilter||r.WebkitBackdropFilter;return r.transform!==\"none\"||r.perspective!==\"none\"||!!o&&o!==\"none\"||t&&r.willChange===\"filter\"||t&&!!r.filter&&r.filter!==\"none\"||[\"transform\",\"perspective\"].some((s=>r.willChange.includes(s)))||[\"paint\",\"layout\",\"strict\",\"content\"].some((s=>{const c=r.contain;return c!=null&&c.includes(s)}))}function sw(){return!/^((?!chrome|android).)*safari/i.test(iw())}function sp(e){return[\"html\",\"body\",\"#document\"].includes(fo(e))}function lw(e){return so(e)?e:e.contextElement}const aw={x:1,y:1};function Hs(e){const t=lw(e);if(!Zr(t))return aw;const r=t.getBoundingClientRect(),{width:o,height:s,fallback:c}=rw(t);let f=(c?mu(r.width):r.width)/o,d=(c?mu(r.height):r.height)/s;return f&&Number.isFinite(f)||(f=1),d&&Number.isFinite(d)||(d=1),{x:f,y:d}}function va(e,t,r,o){var s,c;t===void 0&&(t=!1),r===void 0&&(r=!1);const f=e.getBoundingClientRect(),d=lw(e);let h=aw;t&&(o?so(o)&&(h=Hs(o)):h=Hs(e));const p=d?hr(d):window,g=!sw()&&r;let v=(f.left+(g&&((s=p.visualViewport)==null?void 0:s.offsetLeft)||0))/h.x,b=(f.top+(g&&((c=p.visualViewport)==null?void 0:c.offsetTop)||0))/h.y,w=f.width/h.x,E=f.height/h.y;if(d){const L=hr(d),P=o&&so(o)?hr(o):o;let M=L.frameElement;for(;M&&o&&P!==L;){const R=Hs(M),I=M.getBoundingClientRect(),_=getComputedStyle(M);I.x+=(M.clientLeft+parseFloat(_.paddingLeft))*R.x,I.y+=(M.clientTop+parseFloat(_.paddingTop))*R.y,v*=R.x,b*=R.y,w*=R.x,E*=R.y,v+=I.x,b+=I.y,M=hr(M).frameElement}}return{width:w,height:E,top:b,right:v+w,bottom:b+E,left:v,x:v,y:b}}function lo(e){return((ow(e)?e.ownerDocument:e.document)||window.document).documentElement}function nf(e){return so(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function cw(e){return va(lo(e)).left+nf(e).scrollLeft}function ya(e){if(fo(e)===\"html\")return e;const t=e.assignedSlot||e.parentNode||Av(e)&&e.host||lo(e);return Av(t)?t.host:t}function uw(e){const t=ya(e);return sp(t)?t.ownerDocument.body:Zr(t)&&tf(t)?t:uw(t)}function vu(e,t){var r;t===void 0&&(t=[]);const o=uw(e),s=o===((r=e.ownerDocument)==null?void 0:r.body),c=hr(o);return s?t.concat(c,c.visualViewport||[],tf(o)?o:[]):t.concat(o,vu(o))}function Lv(e,t,r){return t===\"viewport\"?ta((function(o,s){const c=hr(o),f=lo(o),d=c.visualViewport;let h=f.clientWidth,p=f.clientHeight,g=0,v=0;if(d){h=d.width,p=d.height;const b=sw();(b||!b&&s===\"fixed\")&&(g=d.offsetLeft,v=d.offsetTop)}return{width:h,height:p,x:g,y:v}})(e,r)):so(t)?ta((function(o,s){const c=va(o,!0,s===\"fixed\"),f=c.top+o.clientTop,d=c.left+o.clientLeft,h=Zr(o)?Hs(o):{x:1,y:1};return{width:o.clientWidth*h.x,height:o.clientHeight*h.y,x:d*h.x,y:f*h.y}})(t,r)):ta((function(o){const s=lo(o),c=nf(o),f=o.ownerDocument.body,d=na(s.scrollWidth,s.clientWidth,f.scrollWidth,f.clientWidth),h=na(s.scrollHeight,s.clientHeight,f.scrollHeight,f.clientHeight);let p=-c.scrollLeft+cw(o);const g=-c.scrollTop;return Yr(f).direction===\"rtl\"&&(p+=na(s.clientWidth,f.clientWidth)-d),{width:d,height:h,x:p,y:g}})(lo(e)))}function Mv(e){return Zr(e)&&Yr(e).position!==\"fixed\"?e.offsetParent:null}function Nv(e){const t=hr(e);let r=Mv(e);for(;r&&RC(r)&&Yr(r).position===\"static\";)r=Mv(r);return r&&(fo(r)===\"html\"||fo(r)===\"body\"&&Yr(r).position===\"static\"&&!sh(r))?t:r||(function(o){let s=ya(o);for(;Zr(s)&&!sp(s);){if(sh(s))return s;s=ya(s)}return null})(e)||t}function $C(e,t,r){const o=Zr(t),s=lo(t),c=va(e,!0,r===\"fixed\",t);let f={scrollLeft:0,scrollTop:0};const d={x:0,y:0};if(o||!o&&r!==\"fixed\")if((fo(t)!==\"body\"||tf(s))&&(f=nf(t)),Zr(t)){const h=va(t,!0);d.x=h.x+t.clientLeft,d.y=h.y+t.clientTop}else s&&(d.x=cw(s));return{x:c.left+f.scrollLeft-d.x,y:c.top+f.scrollTop-d.y,width:c.width,height:c.height}}const IC={getClippingRect:function(e){let{element:t,boundary:r,rootBoundary:o,strategy:s}=e;const c=r===\"clippingAncestors\"?(function(p,g){const v=g.get(p);if(v)return v;let b=vu(p).filter((P=>so(P)&&fo(P)!==\"body\")),w=null;const E=Yr(p).position===\"fixed\";let L=E?ya(p):p;for(;so(L)&&!sp(L);){const P=Yr(L),M=sh(L);(E?M||w:M||P.position!==\"static\"||!w||![\"absolute\",\"fixed\"].includes(w.position))?w=P:b=b.filter((R=>R!==L)),L=ya(L)}return g.set(p,b),b})(t,this._c):[].concat(r),f=[...c,o],d=f[0],h=f.reduce(((p,g)=>{const v=Lv(t,g,s);return p.top=na(v.top,p.top),p.right=Ev(v.right,p.right),p.bottom=Ev(v.bottom,p.bottom),p.left=na(v.left,p.left),p}),Lv(t,d,s));return{width:h.right-h.left,height:h.bottom-h.top,x:h.left,y:h.top}},convertOffsetParentRelativeRectToViewportRelativeRect:function(e){let{rect:t,offsetParent:r,strategy:o}=e;const s=Zr(r),c=lo(r);if(r===c)return t;let f={scrollLeft:0,scrollTop:0},d={x:1,y:1};const h={x:0,y:0};if((s||!s&&o!==\"fixed\")&&((fo(r)!==\"body\"||tf(c))&&(f=nf(r)),Zr(r))){const p=va(r);d=Hs(r),h.x=p.x+r.clientLeft,h.y=p.y+r.clientTop}return{width:t.width*d.x,height:t.height*d.y,x:t.x*d.x-f.scrollLeft*d.x+h.x,y:t.y*d.y-f.scrollTop*d.y+h.y}},isElement:so,getDimensions:function(e){return Zr(e)?rw(e):e.getBoundingClientRect()},getOffsetParent:Nv,getDocumentElement:lo,getScale:Hs,async getElementRects(e){let{reference:t,floating:r,strategy:o}=e;const s=this.getOffsetParent||Nv,c=this.getDimensions;return{reference:$C(t,await s(r),o),floating:{x:0,y:0,...await c(r)}}},getClientRects:e=>Array.from(e.getClientRects()),isRTL:e=>Yr(e).direction===\"rtl\"},DC=(e,t,r)=>{const o=new Map,s={platform:IC,...r},c={...s.platform,_c:o};return TC(e,t,{...s,platform:c})},ao={disabled:!1,distance:5,skidding:0,container:\"body\",boundary:void 0,instantMove:!1,disposeTimeout:150,popperTriggers:[],strategy:\"absolute\",preventOverflow:!0,flip:!0,shift:!0,overflowPadding:0,arrowPadding:0,arrowOverflow:!0,autoHideOnMousedown:!1,themes:{tooltip:{placement:\"top\",triggers:[\"hover\",\"focus\",\"touch\"],hideTriggers:e=>[...e,\"click\"],delay:{show:200,hide:0},handleResize:!1,html:!1,loadingContent:\"...\"},dropdown:{placement:\"bottom\",triggers:[\"click\"],delay:0,handleResize:!0,autoHide:!0},menu:{$extend:\"dropdown\",triggers:[\"hover\",\"focus\"],popperTriggers:[\"hover\"],delay:{show:0,hide:400}}}};function ba(e,t){let r=ao.themes[e]||{},o;do o=r[t],typeof o>\"u\"?r.$extend?r=ao.themes[r.$extend]||{}:(r=null,o=ao[t]):r=null;while(r);return o}function zC(e){const t=[e];let r=ao.themes[e]||{};do r.$extend&&!r.$resetCss?(t.push(r.$extend),r=ao.themes[r.$extend]||{}):r=null;while(r);return t.map(o=>`v-popper--theme-${o}`)}function Ov(e){const t=[e];let r=ao.themes[e]||{};do r.$extend?(t.push(r.$extend),r=ao.themes[r.$extend]||{}):r=null;while(r);return t}let wa=!1;if(typeof window<\"u\"){wa=!1;try{const e=Object.defineProperty({},\"passive\",{get(){wa=!0}});window.addEventListener(\"test\",null,e)}catch{}}let fw=!1;typeof window<\"u\"&&typeof navigator<\"u\"&&(fw=/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream);const dw=[\"auto\",\"top\",\"bottom\",\"left\",\"right\"].reduce((e,t)=>e.concat([t,`${t}-start`,`${t}-end`]),[]),Pv={hover:\"mouseenter\",focus:\"focus\",click:\"click\",touch:\"touchstart\",pointer:\"pointerdown\"},Rv={hover:\"mouseleave\",focus:\"blur\",click:\"click\",touch:\"touchend\",pointer:\"pointerup\"};function $v(e,t){const r=e.indexOf(t);r!==-1&&e.splice(r,1)}function kd(){return new Promise(e=>requestAnimationFrame(()=>{requestAnimationFrame(e)}))}const nr=[];let Ro=null;const Iv={};function Dv(e){let t=Iv[e];return t||(t=Iv[e]=[]),t}let lh=function(){};typeof window<\"u\"&&(lh=window.Element);function ht(e){return function(t){return ba(t.theme,e)}}const Sd=\"__floating-vue__popper\",hw=()=>rt({name:\"VPopper\",provide(){return{[Sd]:{parentPopper:this}}},inject:{[Sd]:{default:null}},props:{theme:{type:String,required:!0},targetNodes:{type:Function,required:!0},referenceNode:{type:Function,default:null},popperNode:{type:Function,required:!0},shown:{type:Boolean,default:!1},showGroup:{type:String,default:null},ariaId:{default:null},disabled:{type:Boolean,default:ht(\"disabled\")},positioningDisabled:{type:Boolean,default:ht(\"positioningDisabled\")},placement:{type:String,default:ht(\"placement\"),validator:e=>dw.includes(e)},delay:{type:[String,Number,Object],default:ht(\"delay\")},distance:{type:[Number,String],default:ht(\"distance\")},skidding:{type:[Number,String],default:ht(\"skidding\")},triggers:{type:Array,default:ht(\"triggers\")},showTriggers:{type:[Array,Function],default:ht(\"showTriggers\")},hideTriggers:{type:[Array,Function],default:ht(\"hideTriggers\")},popperTriggers:{type:Array,default:ht(\"popperTriggers\")},popperShowTriggers:{type:[Array,Function],default:ht(\"popperShowTriggers\")},popperHideTriggers:{type:[Array,Function],default:ht(\"popperHideTriggers\")},container:{type:[String,Object,lh,Boolean],default:ht(\"container\")},boundary:{type:[String,lh],default:ht(\"boundary\")},strategy:{type:String,validator:e=>[\"absolute\",\"fixed\"].includes(e),default:ht(\"strategy\")},autoHide:{type:[Boolean,Function],default:ht(\"autoHide\")},handleResize:{type:Boolean,default:ht(\"handleResize\")},instantMove:{type:Boolean,default:ht(\"instantMove\")},eagerMount:{type:Boolean,default:ht(\"eagerMount\")},popperClass:{type:[String,Array,Object],default:ht(\"popperClass\")},computeTransformOrigin:{type:Boolean,default:ht(\"computeTransformOrigin\")},autoMinSize:{type:Boolean,default:ht(\"autoMinSize\")},autoSize:{type:[Boolean,String],default:ht(\"autoSize\")},autoMaxSize:{type:Boolean,default:ht(\"autoMaxSize\")},autoBoundaryMaxSize:{type:Boolean,default:ht(\"autoBoundaryMaxSize\")},preventOverflow:{type:Boolean,default:ht(\"preventOverflow\")},overflowPadding:{type:[Number,String],default:ht(\"overflowPadding\")},arrowPadding:{type:[Number,String],default:ht(\"arrowPadding\")},arrowOverflow:{type:Boolean,default:ht(\"arrowOverflow\")},flip:{type:Boolean,default:ht(\"flip\")},shift:{type:Boolean,default:ht(\"shift\")},shiftCrossAxis:{type:Boolean,default:ht(\"shiftCrossAxis\")},noAutoFocus:{type:Boolean,default:ht(\"noAutoFocus\")},disposeTimeout:{type:Number,default:ht(\"disposeTimeout\")}},emits:{show:()=>!0,hide:()=>!0,\"update:shown\":e=>!0,\"apply-show\":()=>!0,\"apply-hide\":()=>!0,\"close-group\":()=>!0,\"close-directive\":()=>!0,\"auto-hide\":()=>!0,resize:()=>!0},data(){return{isShown:!1,isMounted:!1,skipTransition:!1,classes:{showFrom:!1,showTo:!1,hideFrom:!1,hideTo:!0},result:{x:0,y:0,placement:\"\",strategy:this.strategy,arrow:{x:0,y:0,centerOffset:0},transformOrigin:null},randomId:`popper_${[Math.random(),Date.now()].map(e=>e.toString(36).substring(2,10)).join(\"_\")}`,shownChildren:new Set,lastAutoHide:!0,pendingHide:!1,containsGlobalTarget:!1,isDisposed:!0,mouseDownContains:!1}},computed:{popperId(){return this.ariaId!=null?this.ariaId:this.randomId},shouldMountContent(){return this.eagerMount||this.isMounted},slotData(){return{popperId:this.popperId,isShown:this.isShown,shouldMountContent:this.shouldMountContent,skipTransition:this.skipTransition,autoHide:typeof this.autoHide==\"function\"?this.lastAutoHide:this.autoHide,show:this.show,hide:this.hide,handleResize:this.handleResize,onResize:this.onResize,classes:{...this.classes,popperClass:this.popperClass},result:this.positioningDisabled?null:this.result,attrs:this.$attrs}},parentPopper(){var e;return(e=this[Sd])==null?void 0:e.parentPopper},hasPopperShowTriggerHover(){var e,t;return((e=this.popperTriggers)==null?void 0:e.includes(\"hover\"))||((t=this.popperShowTriggers)==null?void 0:t.includes(\"hover\"))}},watch:{shown:\"$_autoShowHide\",disabled(e){e?this.dispose():this.init()},async container(){this.isShown&&(this.$_ensureTeleport(),await this.$_computePosition())},triggers:{handler:\"$_refreshListeners\",deep:!0},positioningDisabled:\"$_refreshListeners\",...[\"placement\",\"distance\",\"skidding\",\"boundary\",\"strategy\",\"overflowPadding\",\"arrowPadding\",\"preventOverflow\",\"shift\",\"shiftCrossAxis\",\"flip\"].reduce((e,t)=>(e[t]=\"$_computePosition\",e),{})},created(){this.autoMinSize&&console.warn('[floating-vue] `autoMinSize` option is deprecated. Use `autoSize=\"min\"` instead.'),this.autoMaxSize&&console.warn(\"[floating-vue] `autoMaxSize` option is deprecated. Use `autoBoundaryMaxSize` instead.\")},mounted(){this.init(),this.$_detachPopperNode()},activated(){this.$_autoShowHide()},deactivated(){this.hide()},beforeUnmount(){this.dispose()},methods:{show({event:e=null,skipDelay:t=!1,force:r=!1}={}){var o,s;(o=this.parentPopper)!=null&&o.lockedChild&&this.parentPopper.lockedChild!==this||(this.pendingHide=!1,(r||!this.disabled)&&(((s=this.parentPopper)==null?void 0:s.lockedChild)===this&&(this.parentPopper.lockedChild=null),this.$_scheduleShow(e,t),this.$emit(\"show\"),this.$_showFrameLocked=!0,requestAnimationFrame(()=>{this.$_showFrameLocked=!1})),this.$emit(\"update:shown\",!0))},hide({event:e=null,skipDelay:t=!1}={}){var r;if(!this.$_hideInProgress){if(this.shownChildren.size>0){this.pendingHide=!0;return}if(this.hasPopperShowTriggerHover&&this.$_isAimingPopper()){this.parentPopper&&(this.parentPopper.lockedChild=this,clearTimeout(this.parentPopper.lockedChildTimer),this.parentPopper.lockedChildTimer=setTimeout(()=>{this.parentPopper.lockedChild===this&&(this.parentPopper.lockedChild.hide({skipDelay:t}),this.parentPopper.lockedChild=null)},1e3));return}((r=this.parentPopper)==null?void 0:r.lockedChild)===this&&(this.parentPopper.lockedChild=null),this.pendingHide=!1,this.$_scheduleHide(e,t),this.$emit(\"hide\"),this.$emit(\"update:shown\",!1)}},init(){var e;this.isDisposed&&(this.isDisposed=!1,this.isMounted=!1,this.$_events=[],this.$_preventShow=!1,this.$_referenceNode=((e=this.referenceNode)==null?void 0:e.call(this))??this.$el,this.$_targetNodes=this.targetNodes().filter(t=>t.nodeType===t.ELEMENT_NODE),this.$_popperNode=this.popperNode(),this.$_innerNode=this.$_popperNode.querySelector(\".v-popper__inner\"),this.$_arrowNode=this.$_popperNode.querySelector(\".v-popper__arrow-container\"),this.$_swapTargetAttrs(\"title\",\"data-original-title\"),this.$_detachPopperNode(),this.triggers.length&&this.$_addEventListeners(),this.shown&&this.show())},dispose(){this.isDisposed||(this.isDisposed=!0,this.$_removeEventListeners(),this.hide({skipDelay:!0}),this.$_detachPopperNode(),this.isMounted=!1,this.isShown=!1,this.$_updateParentShownChildren(!1),this.$_swapTargetAttrs(\"data-original-title\",\"title\"))},async onResize(){this.isShown&&(await this.$_computePosition(),this.$emit(\"resize\"))},async $_computePosition(){if(this.isDisposed||this.positioningDisabled)return;const e={strategy:this.strategy,middleware:[]};(this.distance||this.skidding)&&e.middleware.push(NC({mainAxis:this.distance,crossAxis:this.skidding}));const t=this.placement.startsWith(\"auto\");if(t?e.middleware.push(AC({alignment:this.placement.split(\"-\")[1]??\"\"})):e.placement=this.placement,this.preventOverflow&&(this.shift&&e.middleware.push(OC({padding:this.overflowPadding,boundary:this.boundary,crossAxis:this.shiftCrossAxis})),!t&&this.flip&&e.middleware.push(LC({padding:this.overflowPadding,boundary:this.boundary}))),e.middleware.push(CC({element:this.$_arrowNode,padding:this.arrowPadding})),this.arrowOverflow&&e.middleware.push({name:\"arrowOverflow\",fn:({placement:o,rects:s,middlewareData:c})=>{let f;const{centerOffset:d}=c.arrow;return o.startsWith(\"top\")||o.startsWith(\"bottom\")?f=Math.abs(d)>s.reference.width/2:f=Math.abs(d)>s.reference.height/2,{data:{overflow:f}}}}),this.autoMinSize||this.autoSize){const o=this.autoSize?this.autoSize:this.autoMinSize?\"min\":null;e.middleware.push({name:\"autoSize\",fn:({rects:s,placement:c,middlewareData:f})=>{var d;if((d=f.autoSize)!=null&&d.skip)return{};let h,p;return c.startsWith(\"top\")||c.startsWith(\"bottom\")?h=s.reference.width:p=s.reference.height,this.$_innerNode.style[o===\"min\"?\"minWidth\":o===\"max\"?\"maxWidth\":\"width\"]=h!=null?`${h}px`:null,this.$_innerNode.style[o===\"min\"?\"minHeight\":o===\"max\"?\"maxHeight\":\"height\"]=p!=null?`${p}px`:null,{data:{skip:!0},reset:{rects:!0}}}})}(this.autoMaxSize||this.autoBoundaryMaxSize)&&(this.$_innerNode.style.maxWidth=null,this.$_innerNode.style.maxHeight=null,e.middleware.push(PC({boundary:this.boundary,padding:this.overflowPadding,apply:({availableWidth:o,availableHeight:s})=>{this.$_innerNode.style.maxWidth=o!=null?`${o}px`:null,this.$_innerNode.style.maxHeight=s!=null?`${s}px`:null}})));const r=await DC(this.$_referenceNode,this.$_popperNode,e);Object.assign(this.result,{x:r.x,y:r.y,placement:r.placement,strategy:r.strategy,arrow:{...r.middlewareData.arrow,...r.middlewareData.arrowOverflow}})},$_scheduleShow(e,t=!1){if(this.$_updateParentShownChildren(!0),this.$_hideInProgress=!1,clearTimeout(this.$_scheduleTimer),Ro&&this.instantMove&&Ro.instantMove&&Ro!==this.parentPopper){Ro.$_applyHide(!0),this.$_applyShow(!0);return}t?this.$_applyShow():this.$_scheduleTimer=setTimeout(this.$_applyShow.bind(this),this.$_computeDelay(\"show\"))},$_scheduleHide(e,t=!1){if(this.shownChildren.size>0){this.pendingHide=!0;return}this.$_updateParentShownChildren(!1),this.$_hideInProgress=!0,clearTimeout(this.$_scheduleTimer),this.isShown&&(Ro=this),t?this.$_applyHide():this.$_scheduleTimer=setTimeout(this.$_applyHide.bind(this),this.$_computeDelay(\"hide\"))},$_computeDelay(e){const t=this.delay;return parseInt(t&&t[e]||t||0)},async $_applyShow(e=!1){clearTimeout(this.$_disposeTimer),clearTimeout(this.$_scheduleTimer),this.skipTransition=e,!this.isShown&&(this.$_ensureTeleport(),await kd(),await this.$_computePosition(),await this.$_applyShowEffect(),this.positioningDisabled||this.$_registerEventListeners([...vu(this.$_referenceNode),...vu(this.$_popperNode)],\"scroll\",()=>{this.$_computePosition()}))},async $_applyShowEffect(){if(this.$_hideInProgress)return;if(this.computeTransformOrigin){const t=this.$_referenceNode.getBoundingClientRect(),r=this.$_popperNode.querySelector(\".v-popper__wrapper\"),o=r.parentNode.getBoundingClientRect(),s=t.x+t.width/2-(o.left+r.offsetLeft),c=t.y+t.height/2-(o.top+r.offsetTop);this.result.transformOrigin=`${s}px ${c}px`}this.isShown=!0,this.$_applyAttrsToTarget({\"aria-describedby\":this.popperId,\"data-popper-shown\":\"\"});const e=this.showGroup;if(e){let t;for(let r=0;r<nr.length;r++)t=nr[r],t.showGroup!==e&&(t.hide(),t.$emit(\"close-group\"))}nr.push(this),document.body.classList.add(\"v-popper--some-open\");for(const t of Ov(this.theme))Dv(t).push(this),document.body.classList.add(`v-popper--some-open--${t}`);this.$emit(\"apply-show\"),this.classes.showFrom=!0,this.classes.showTo=!1,this.classes.hideFrom=!1,this.classes.hideTo=!1,await kd(),this.classes.showFrom=!1,this.classes.showTo=!0,this.noAutoFocus||this.$_popperNode.focus()},async $_applyHide(e=!1){if(this.shownChildren.size>0){this.pendingHide=!0,this.$_hideInProgress=!1;return}if(clearTimeout(this.$_scheduleTimer),!this.isShown)return;this.skipTransition=e,$v(nr,this),nr.length===0&&document.body.classList.remove(\"v-popper--some-open\");for(const r of Ov(this.theme)){const o=Dv(r);$v(o,this),o.length===0&&document.body.classList.remove(`v-popper--some-open--${r}`)}Ro===this&&(Ro=null),this.isShown=!1,this.$_applyAttrsToTarget({\"aria-describedby\":void 0,\"data-popper-shown\":void 0}),clearTimeout(this.$_disposeTimer);const t=this.disposeTimeout;t!==null&&(this.$_disposeTimer=setTimeout(()=>{this.$_popperNode&&(this.$_detachPopperNode(),this.isMounted=!1)},t)),this.$_removeEventListeners(\"scroll\"),this.$emit(\"apply-hide\"),this.classes.showFrom=!1,this.classes.showTo=!1,this.classes.hideFrom=!0,this.classes.hideTo=!1,await kd(),this.classes.hideFrom=!1,this.classes.hideTo=!0},$_autoShowHide(){this.shown?this.show():this.hide()},$_ensureTeleport(){if(this.isDisposed)return;let e=this.container;if(typeof e==\"string\"?e=window.document.querySelector(e):e===!1&&(e=this.$_targetNodes[0].parentNode),!e)throw new Error(\"No container for popover: \"+this.container);e.appendChild(this.$_popperNode),this.isMounted=!0},$_addEventListeners(){const e=r=>{this.isShown&&!this.$_hideInProgress||(r.usedByTooltip=!0,!this.$_preventShow&&this.show({event:r}))};this.$_registerTriggerListeners(this.$_targetNodes,Pv,this.triggers,this.showTriggers,e),this.$_registerTriggerListeners([this.$_popperNode],Pv,this.popperTriggers,this.popperShowTriggers,e);const t=r=>{r.usedByTooltip||this.hide({event:r})};this.$_registerTriggerListeners(this.$_targetNodes,Rv,this.triggers,this.hideTriggers,t),this.$_registerTriggerListeners([this.$_popperNode],Rv,this.popperTriggers,this.popperHideTriggers,t)},$_registerEventListeners(e,t,r){this.$_events.push({targetNodes:e,eventType:t,handler:r}),e.forEach(o=>o.addEventListener(t,r,wa?{passive:!0}:void 0))},$_registerTriggerListeners(e,t,r,o,s){let c=r;o!=null&&(c=typeof o==\"function\"?o(c):o),c.forEach(f=>{const d=t[f];d&&this.$_registerEventListeners(e,d,s)})},$_removeEventListeners(e){const t=[];this.$_events.forEach(r=>{const{targetNodes:o,eventType:s,handler:c}=r;!e||e===s?o.forEach(f=>f.removeEventListener(s,c)):t.push(r)}),this.$_events=t},$_refreshListeners(){this.isDisposed||(this.$_removeEventListeners(),this.$_addEventListeners())},$_handleGlobalClose(e,t=!1){this.$_showFrameLocked||(this.hide({event:e}),e.closePopover?this.$emit(\"close-directive\"):this.$emit(\"auto-hide\"),t&&(this.$_preventShow=!0,setTimeout(()=>{this.$_preventShow=!1},300)))},$_detachPopperNode(){this.$_popperNode.parentNode&&this.$_popperNode.parentNode.removeChild(this.$_popperNode)},$_swapTargetAttrs(e,t){for(const r of this.$_targetNodes){const o=r.getAttribute(e);o&&(r.removeAttribute(e),r.setAttribute(t,o))}},$_applyAttrsToTarget(e){for(const t of this.$_targetNodes)for(const r in e){const o=e[r];o==null?t.removeAttribute(r):t.setAttribute(r,o)}},$_updateParentShownChildren(e){let t=this.parentPopper;for(;t;)e?t.shownChildren.add(this.randomId):(t.shownChildren.delete(this.randomId),t.pendingHide&&t.hide()),t=t.parentPopper},$_isAimingPopper(){const e=this.$_referenceNode.getBoundingClientRect();if(ra>=e.left&&ra<=e.right&&ia>=e.top&&ia<=e.bottom){const t=this.$_popperNode.getBoundingClientRect(),r=ra-Ki,o=ia-Xi,s=t.left+t.width/2-Ki+(t.top+t.height/2)-Xi+t.width+t.height,c=Ki+r*s,f=Xi+o*s;return Mc(Ki,Xi,c,f,t.left,t.top,t.left,t.bottom)||Mc(Ki,Xi,c,f,t.left,t.top,t.right,t.top)||Mc(Ki,Xi,c,f,t.right,t.top,t.right,t.bottom)||Mc(Ki,Xi,c,f,t.left,t.bottom,t.right,t.bottom)}return!1}},render(){return this.$slots.default(this.slotData)}});if(typeof document<\"u\"&&typeof window<\"u\"){if(fw){const e=wa?{passive:!0,capture:!0}:!0;document.addEventListener(\"touchstart\",t=>zv(t),e),document.addEventListener(\"touchend\",t=>Fv(t,!0),e)}else window.addEventListener(\"mousedown\",e=>zv(e),!0),window.addEventListener(\"click\",e=>Fv(e,!1),!0);window.addEventListener(\"resize\",BC)}function zv(e,t){for(let r=0;r<nr.length;r++){const o=nr[r];try{o.mouseDownContains=o.popperNode().contains(e.target)}catch{}}}function Fv(e,t){FC(e,t)}function FC(e,t){const r={};for(let o=nr.length-1;o>=0;o--){const s=nr[o];try{const c=s.containsGlobalTarget=s.mouseDownContains||s.popperNode().contains(e.target);s.pendingHide=!1,requestAnimationFrame(()=>{if(s.pendingHide=!1,!r[s.randomId]&&Hv(s,c,e)){if(s.$_handleGlobalClose(e,t),!e.closeAllPopover&&e.closePopover&&c){let d=s.parentPopper;for(;d;)r[d.randomId]=!0,d=d.parentPopper;return}let f=s.parentPopper;for(;f&&Hv(f,f.containsGlobalTarget,e);)f.$_handleGlobalClose(e,t),f=f.parentPopper}})}catch{}}}function Hv(e,t,r){return r.closeAllPopover||r.closePopover&&t||HC(e,r)&&!t}function HC(e,t){if(typeof e.autoHide==\"function\"){const r=e.autoHide(t);return e.lastAutoHide=r,r}return e.autoHide}function BC(){for(let e=0;e<nr.length;e++)nr[e].$_computePosition()}function Bv(){for(let e=0;e<nr.length;e++)nr[e].hide()}let Ki=0,Xi=0,ra=0,ia=0;typeof window<\"u\"&&window.addEventListener(\"mousemove\",e=>{Ki=ra,Xi=ia,ra=e.clientX,ia=e.clientY},wa?{passive:!0}:void 0);function Mc(e,t,r,o,s,c,f,d){const h=((f-s)*(t-c)-(d-c)*(e-s))/((d-c)*(r-e)-(f-s)*(o-t)),p=((r-e)*(t-c)-(o-t)*(e-s))/((d-c)*(r-e)-(f-s)*(o-t));return h>=0&&h<=1&&p>=0&&p<=1}const WC={extends:hw()},rf=(e,t)=>{const r=e.__vccOpts||e;for(const[o,s]of t)r[o]=s;return r};function qC(e,t,r,o,s,c){return ie(),ve(\"div\",{ref:\"reference\",class:ot([\"v-popper\",{\"v-popper--shown\":e.slotData.isShown}])},[Dt(e.$slots,\"default\",qS(qb(e.slotData)))],2)}const jC=rf(WC,[[\"render\",qC]]);function UC(){var e=window.navigator.userAgent,t=e.indexOf(\"MSIE \");if(t>0)return parseInt(e.substring(t+5,e.indexOf(\".\",t)),10);var r=e.indexOf(\"Trident/\");if(r>0){var o=e.indexOf(\"rv:\");return parseInt(e.substring(o+3,e.indexOf(\".\",o)),10)}var s=e.indexOf(\"Edge/\");return s>0?parseInt(e.substring(s+5,e.indexOf(\".\",s)),10):-1}let Kc;function ah(){ah.init||(ah.init=!0,Kc=UC()!==-1)}var of={name:\"ResizeObserver\",props:{emitOnMount:{type:Boolean,default:!1},ignoreWidth:{type:Boolean,default:!1},ignoreHeight:{type:Boolean,default:!1}},emits:[\"notify\"],mounted(){ah(),Et(()=>{this._w=this.$el.offsetWidth,this._h=this.$el.offsetHeight,this.emitOnMount&&this.emitSize()});const e=document.createElement(\"object\");this._resizeObject=e,e.setAttribute(\"aria-hidden\",\"true\"),e.setAttribute(\"tabindex\",-1),e.onload=this.addResizeHandlers,e.type=\"text/html\",Kc&&this.$el.appendChild(e),e.data=\"about:blank\",Kc||this.$el.appendChild(e)},beforeUnmount(){this.removeResizeHandlers()},methods:{compareAndNotify(){(!this.ignoreWidth&&this._w!==this.$el.offsetWidth||!this.ignoreHeight&&this._h!==this.$el.offsetHeight)&&(this._w=this.$el.offsetWidth,this._h=this.$el.offsetHeight,this.emitSize())},emitSize(){this.$emit(\"notify\",{width:this._w,height:this._h})},addResizeHandlers(){this._resizeObject.contentDocument.defaultView.addEventListener(\"resize\",this.compareAndNotify),this.compareAndNotify()},removeResizeHandlers(){this._resizeObject&&this._resizeObject.onload&&(!Kc&&this._resizeObject.contentDocument&&this._resizeObject.contentDocument.defaultView.removeEventListener(\"resize\",this.compareAndNotify),this.$el.removeChild(this._resizeObject),this._resizeObject.onload=null,this._resizeObject=null)}}};const VC=lb();ob(\"data-v-b329ee4c\");const GC={class:\"resize-observer\",tabindex:\"-1\"};sb();const KC=VC((e,t,r,o,s,c)=>(ie(),Ve(\"div\",GC)));of.render=KC;of.__scopeId=\"data-v-b329ee4c\";of.__file=\"src/components/ResizeObserver.vue\";const pw=(e=\"theme\")=>({computed:{themeClass(){return zC(this[e])}}}),XC=rt({name:\"VPopperContent\",components:{ResizeObserver:of},mixins:[pw()],props:{popperId:String,theme:String,shown:Boolean,mounted:Boolean,skipTransition:Boolean,autoHide:Boolean,handleResize:Boolean,classes:Object,result:Object},emits:[\"hide\",\"resize\"],methods:{toPx(e){return e!=null&&!isNaN(e)?`${e}px`:null}}}),YC=[\"id\",\"aria-hidden\",\"tabindex\",\"data-popper-placement\"],ZC={ref:\"inner\",class:\"v-popper__inner\"},JC=X(\"div\",{class:\"v-popper__arrow-outer\"},null,-1),QC=X(\"div\",{class:\"v-popper__arrow-inner\"},null,-1),eE=[JC,QC];function tE(e,t,r,o,s,c){const f=Go(\"ResizeObserver\");return ie(),ve(\"div\",{id:e.popperId,ref:\"popover\",class:ot([\"v-popper__popper\",[e.themeClass,e.classes.popperClass,{\"v-popper__popper--shown\":e.shown,\"v-popper__popper--hidden\":!e.shown,\"v-popper__popper--show-from\":e.classes.showFrom,\"v-popper__popper--show-to\":e.classes.showTo,\"v-popper__popper--hide-from\":e.classes.hideFrom,\"v-popper__popper--hide-to\":e.classes.hideTo,\"v-popper__popper--skip-transition\":e.skipTransition,\"v-popper__popper--arrow-overflow\":e.result&&e.result.arrow.overflow,\"v-popper__popper--no-positioning\":!e.result}]]),style:zt(e.result?{position:e.result.strategy,transform:`translate3d(${Math.round(e.result.x)}px,${Math.round(e.result.y)}px,0)`}:void 0),\"aria-hidden\":e.shown?\"false\":\"true\",tabindex:e.autoHide?0:void 0,\"data-popper-placement\":e.result?e.result.placement:void 0,onKeyup:t[2]||(t[2]=ih(d=>e.autoHide&&e.$emit(\"hide\"),[\"esc\"]))},[X(\"div\",{class:\"v-popper__backdrop\",onClick:t[0]||(t[0]=d=>e.autoHide&&e.$emit(\"hide\"))}),X(\"div\",{class:\"v-popper__wrapper\",style:zt(e.result?{transformOrigin:e.result.transformOrigin}:void 0)},[X(\"div\",ZC,[e.mounted?(ie(),ve(nt,{key:0},[X(\"div\",null,[Dt(e.$slots,\"default\")]),e.handleResize?(ie(),Ve(f,{key:0,onNotify:t[1]||(t[1]=d=>e.$emit(\"resize\",d))})):He(\"\",!0)],64)):He(\"\",!0)],512),X(\"div\",{ref:\"arrow\",class:\"v-popper__arrow-container\",style:zt(e.result?{left:e.toPx(e.result.arrow.x),top:e.toPx(e.result.arrow.y)}:void 0)},eE,4)],4)],46,YC)}const gw=rf(XC,[[\"render\",tE]]),mw={methods:{show(...e){return this.$refs.popper.show(...e)},hide(...e){return this.$refs.popper.hide(...e)},dispose(...e){return this.$refs.popper.dispose(...e)},onResize(...e){return this.$refs.popper.onResize(...e)}}};let ch=function(){};typeof window<\"u\"&&(ch=window.Element);const nE=rt({name:\"VPopperWrapper\",components:{Popper:jC,PopperContent:gw},mixins:[mw,pw(\"finalTheme\")],props:{theme:{type:String,default:null},referenceNode:{type:Function,default:null},shown:{type:Boolean,default:!1},showGroup:{type:String,default:null},ariaId:{default:null},disabled:{type:Boolean,default:void 0},positioningDisabled:{type:Boolean,default:void 0},placement:{type:String,default:void 0},delay:{type:[String,Number,Object],default:void 0},distance:{type:[Number,String],default:void 0},skidding:{type:[Number,String],default:void 0},triggers:{type:Array,default:void 0},showTriggers:{type:[Array,Function],default:void 0},hideTriggers:{type:[Array,Function],default:void 0},popperTriggers:{type:Array,default:void 0},popperShowTriggers:{type:[Array,Function],default:void 0},popperHideTriggers:{type:[Array,Function],default:void 0},container:{type:[String,Object,ch,Boolean],default:void 0},boundary:{type:[String,ch],default:void 0},strategy:{type:String,default:void 0},autoHide:{type:[Boolean,Function],default:void 0},handleResize:{type:Boolean,default:void 0},instantMove:{type:Boolean,default:void 0},eagerMount:{type:Boolean,default:void 0},popperClass:{type:[String,Array,Object],default:void 0},computeTransformOrigin:{type:Boolean,default:void 0},autoMinSize:{type:Boolean,default:void 0},autoSize:{type:[Boolean,String],default:void 0},autoMaxSize:{type:Boolean,default:void 0},autoBoundaryMaxSize:{type:Boolean,default:void 0},preventOverflow:{type:Boolean,default:void 0},overflowPadding:{type:[Number,String],default:void 0},arrowPadding:{type:[Number,String],default:void 0},arrowOverflow:{type:Boolean,default:void 0},flip:{type:Boolean,default:void 0},shift:{type:Boolean,default:void 0},shiftCrossAxis:{type:Boolean,default:void 0},noAutoFocus:{type:Boolean,default:void 0},disposeTimeout:{type:Number,default:void 0}},emits:{show:()=>!0,hide:()=>!0,\"update:shown\":e=>!0,\"apply-show\":()=>!0,\"apply-hide\":()=>!0,\"close-group\":()=>!0,\"close-directive\":()=>!0,\"auto-hide\":()=>!0,resize:()=>!0},computed:{finalTheme(){return this.theme??this.$options.vPopperTheme}},methods:{getTargetNodes(){return Array.from(this.$el.children).filter(e=>e!==this.$refs.popperContent.$el)}}});function rE(e,t,r,o,s,c){const f=Go(\"PopperContent\"),d=Go(\"Popper\");return ie(),Ve(d,ki({ref:\"popper\"},e.$props,{theme:e.finalTheme,\"target-nodes\":e.getTargetNodes,\"popper-node\":()=>e.$refs.popperContent.$el,class:[e.themeClass],onShow:t[0]||(t[0]=()=>e.$emit(\"show\")),onHide:t[1]||(t[1]=()=>e.$emit(\"hide\")),\"onUpdate:shown\":t[2]||(t[2]=h=>e.$emit(\"update:shown\",h)),onApplyShow:t[3]||(t[3]=()=>e.$emit(\"apply-show\")),onApplyHide:t[4]||(t[4]=()=>e.$emit(\"apply-hide\")),onCloseGroup:t[5]||(t[5]=()=>e.$emit(\"close-group\")),onCloseDirective:t[6]||(t[6]=()=>e.$emit(\"close-directive\")),onAutoHide:t[7]||(t[7]=()=>e.$emit(\"auto-hide\")),onResize:t[8]||(t[8]=()=>e.$emit(\"resize\"))}),{default:We(({popperId:h,isShown:p,shouldMountContent:g,skipTransition:v,autoHide:b,show:w,hide:E,handleResize:L,onResize:P,classes:M,result:R})=>[Dt(e.$slots,\"default\",{shown:p,show:w,hide:E}),Ne(f,{ref:\"popperContent\",\"popper-id\":h,theme:e.finalTheme,shown:p,mounted:g,\"skip-transition\":v,\"auto-hide\":b,\"handle-resize\":L,classes:M,result:R,onHide:E,onResize:P},{default:We(()=>[Dt(e.$slots,\"popper\",{shown:p,hide:E})]),_:2},1032,[\"popper-id\",\"theme\",\"shown\",\"mounted\",\"skip-transition\",\"auto-hide\",\"handle-resize\",\"classes\",\"result\",\"onHide\",\"onResize\"])]),_:3},16,[\"theme\",\"target-nodes\",\"popper-node\",\"class\"])}const lp=rf(nE,[[\"render\",rE]]);({...lp});({...lp});const iE={...lp,name:\"VTooltip\",vPopperTheme:\"tooltip\"},oE=rt({name:\"VTooltipDirective\",components:{Popper:hw(),PopperContent:gw},mixins:[mw],inheritAttrs:!1,props:{theme:{type:String,default:\"tooltip\"},html:{type:Boolean,default:e=>ba(e.theme,\"html\")},content:{type:[String,Number,Function],default:null},loadingContent:{type:String,default:e=>ba(e.theme,\"loadingContent\")},targetNodes:{type:Function,required:!0}},data(){return{asyncContent:null}},computed:{isContentAsync(){return typeof this.content==\"function\"},loading(){return this.isContentAsync&&this.asyncContent==null},finalContent(){return this.isContentAsync?this.loading?this.loadingContent:this.asyncContent:this.content}},watch:{content:{handler(){this.fetchContent(!0)},immediate:!0},async finalContent(){await this.$nextTick(),this.$refs.popper.onResize()}},created(){this.$_fetchId=0},methods:{fetchContent(e){if(typeof this.content==\"function\"&&this.$_isShown&&(e||!this.$_loading&&this.asyncContent==null)){this.asyncContent=null,this.$_loading=!0;const t=++this.$_fetchId,r=this.content(this);r.then?r.then(o=>this.onResult(t,o)):this.onResult(t,r)}},onResult(e,t){e===this.$_fetchId&&(this.$_loading=!1,this.asyncContent=t)},onShow(){this.$_isShown=!0,this.fetchContent()},onHide(){this.$_isShown=!1}}}),sE=[\"innerHTML\"],lE=[\"textContent\"];function aE(e,t,r,o,s,c){const f=Go(\"PopperContent\"),d=Go(\"Popper\");return ie(),Ve(d,ki({ref:\"popper\"},e.$attrs,{theme:e.theme,\"target-nodes\":e.targetNodes,\"popper-node\":()=>e.$refs.popperContent.$el,onApplyShow:e.onShow,onApplyHide:e.onHide}),{default:We(({popperId:h,isShown:p,shouldMountContent:g,skipTransition:v,autoHide:b,hide:w,handleResize:E,onResize:L,classes:P,result:M})=>[Ne(f,{ref:\"popperContent\",class:ot({\"v-popper--tooltip-loading\":e.loading}),\"popper-id\":h,theme:e.theme,shown:p,mounted:g,\"skip-transition\":v,\"auto-hide\":b,\"handle-resize\":E,classes:P,result:M,onHide:w,onResize:L},{default:We(()=>[e.html?(ie(),ve(\"div\",{key:0,innerHTML:e.finalContent},null,8,sE)):(ie(),ve(\"div\",{key:1,textContent:Re(e.finalContent)},null,8,lE))]),_:2},1032,[\"class\",\"popper-id\",\"theme\",\"shown\",\"mounted\",\"skip-transition\",\"auto-hide\",\"handle-resize\",\"classes\",\"result\",\"onHide\",\"onResize\"])]),_:1},16,[\"theme\",\"target-nodes\",\"popper-node\",\"onApplyShow\",\"onApplyHide\"])}const cE=rf(oE,[[\"render\",aE]]),vw=\"v-popper--has-tooltip\";function uE(e,t){let r=e.placement;if(!r&&t)for(const o of dw)t[o]&&(r=o);return r||(r=ba(e.theme||\"tooltip\",\"placement\")),r}function yw(e,t,r){let o;const s=typeof t;return s===\"string\"?o={content:t}:t&&s===\"object\"?o=t:o={content:!1},o.placement=uE(o,r),o.targetNodes=()=>[e],o.referenceNode=()=>e,o}let _d,xa,fE=0;function dE(){if(_d)return;xa=Ge([]),_d=Qb({name:\"VTooltipDirectiveApp\",setup(){return{directives:xa}},render(){return this.directives.map(t=>za(cE,{...t.options,shown:t.shown||t.options.shown,key:t.id}))},devtools:{hide:!0}});const e=document.createElement(\"div\");document.body.appendChild(e),_d.mount(e)}function bw(e,t,r){dE();const o=Ge(yw(e,t,r)),s=Ge(!1),c={id:fE++,options:o,shown:s};return xa.value.push(c),e.classList&&e.classList.add(vw),e.$_popper={options:o,item:c,show(){s.value=!0},hide(){s.value=!1}}}function ap(e){if(e.$_popper){const t=xa.value.indexOf(e.$_popper.item);t!==-1&&xa.value.splice(t,1),delete e.$_popper,delete e.$_popperOldShown,delete e.$_popperMountTarget}e.classList&&e.classList.remove(vw)}function Wv(e,{value:t,modifiers:r}){const o=yw(e,t,r);if(!o.content||ba(o.theme||\"tooltip\",\"disabled\"))ap(e);else{let s;e.$_popper?(s=e.$_popper,s.options.value=o):s=bw(e,t,r),typeof t.shown<\"u\"&&t.shown!==e.$_popperOldShown&&(e.$_popperOldShown=t.shown,t.shown?s.show():s.hide())}}const hE={beforeMount:Wv,updated:Wv,beforeUnmount(e){ap(e)}},pE=hE,Qi=iE,ww={options:ao};function cp(e){return I0()?(KS(e),!0):!1}const Td=new WeakMap,gE=(...e)=>{var t;const r=e[0],o=(t=ti())==null?void 0:t.proxy;if(o==null&&!Sb())throw new Error(\"injectLocal must be called in setup\");return o&&Td.has(o)&&r in Td.get(o)?Td.get(o)[r]:pn(...e)},mE=typeof window<\"u\"&&typeof document<\"u\";typeof WorkerGlobalScope<\"u\"&&globalThis instanceof WorkerGlobalScope;const vE=Object.prototype.toString,yE=e=>vE.call(e)===\"[object Object]\",bE=()=>+Date.now(),yu=()=>{};function up(e,t){function r(...o){return new Promise((s,c)=>{Promise.resolve(e(()=>t.apply(this,o),{fn:t,thisArg:this,args:o})).then(s).catch(c)})}return r}const fp=e=>e();function xw(e,t={}){let r,o,s=yu;const c=h=>{clearTimeout(h),s(),s=yu};let f;return h=>{const p=Xt(e),g=Xt(t.maxWait);return r&&c(r),p<=0||g!==void 0&&g<=0?(o&&(c(o),o=null),Promise.resolve(h())):new Promise((v,b)=>{s=t.rejectOnCancel?b:v,f=h,g&&!o&&(o=setTimeout(()=>{r&&c(r),o=null,v(f())},g)),r=setTimeout(()=>{o&&c(o),o=null,v(h())},p)})}}function kw(e=fp,t={}){const{initialState:r=\"active\"}=t,o=Yo(r===\"active\");function s(){o.value=!1}function c(){o.value=!0}const f=(...d)=>{o.value&&e(...d)};return{isActive:Gs(o),pause:s,resume:c,eventFilter:f}}function qv(e,t=!1,r=\"Timeout\"){return new Promise((o,s)=>{setTimeout(t?()=>s(r):o,e)})}function jv(e){return e.endsWith(\"rem\")?Number.parseFloat(e)*16:Number.parseFloat(e)}function wE(e){return ti()}function Cd(e){return Array.isArray(e)?e:[e]}function Yo(...e){if(e.length!==1)return w_(...e);const t=e[0];return typeof t==\"function\"?Gs(Q0(()=>({get:t,set:yu}))):Ge(t)}function Nc(e,t=200,r={}){return up(xw(t,r),e)}function Sw(e,t,r={}){const{eventFilter:o=fp,...s}=r;return xt(e,up(o,t),s)}function _w(e,t,r={}){const{eventFilter:o,initialState:s=\"active\",...c}=r,{eventFilter:f,pause:d,resume:h,isActive:p}=kw(o,{initialState:s});return{stop:Sw(e,t,{...c,eventFilter:f}),pause:d,resume:h,isActive:p}}function dp(e,t=!0,r){wE()?Mi(e,r):t?e():Et(e)}function uh(e,t=!1){function r(v,{flush:b=\"sync\",deep:w=!1,timeout:E,throwOnTimeout:L}={}){let P=null;const R=[new Promise(I=>{P=xt(e,_=>{v(_)!==t&&(P?P():Et(()=>P?.()),I(_))},{flush:b,deep:w,immediate:!0})})];return E!=null&&R.push(qv(E,L).then(()=>Xt(e)).finally(()=>P?.())),Promise.race(R)}function o(v,b){if(!Mt(v))return r(_=>_===v,b);const{flush:w=\"sync\",deep:E=!1,timeout:L,throwOnTimeout:P}=b??{};let M=null;const I=[new Promise(_=>{M=xt([e,v],([$,W])=>{t!==($===W)&&(M?M():Et(()=>M?.()),_($))},{flush:w,deep:E,immediate:!0})})];return L!=null&&I.push(qv(L,P).then(()=>Xt(e)).finally(()=>(M?.(),Xt(e)))),Promise.race(I)}function s(v){return r(b=>!!b,v)}function c(v){return o(null,v)}function f(v){return o(void 0,v)}function d(v){return r(Number.isNaN,v)}function h(v,b){return r(w=>{const E=Array.from(w);return E.includes(v)||E.includes(Xt(v))},b)}function p(v){return g(1,v)}function g(v=1,b){let w=-1;return r(()=>(w+=1,w>=v),b)}return Array.isArray(Xt(e))?{toMatch:r,toContains:h,changed:p,changedTimes:g,get not(){return uh(e,!t)}}:{toMatch:r,toBe:o,toBeTruthy:s,toBeNull:c,toBeNaN:d,toBeUndefined:f,changed:p,changedTimes:g,get not(){return uh(e,!t)}}}function Uv(e){return uh(e)}function xE(e=!1,t={}){const{truthyValue:r=!0,falsyValue:o=!1}=t,s=Mt(e),c=Ft(e);function f(d){if(arguments.length)return c.value=d,c.value;{const h=Xt(r);return c.value=c.value===h?Xt(o):h,c.value}}return s?f:[c,f]}function hp(e,t,r={}){const{debounce:o=0,maxWait:s=void 0,...c}=r;return Sw(e,t,{...c,eventFilter:xw(o,{maxWait:s})})}function kE(e,t,r={}){const{eventFilter:o=fp,...s}=r,c=up(o,t);let f,d,h;if(s.flush===\"sync\"){const p=Ft(!1);d=()=>{},f=g=>{p.value=!0,g(),p.value=!1},h=xt(e,(...g)=>{p.value||c(...g)},s)}else{const p=[],g=Ft(0),v=Ft(0);d=()=>{g.value=v.value},p.push(xt(e,()=>{v.value++},{...s,flush:\"sync\"})),f=b=>{const w=v.value;b(),g.value+=v.value-w},p.push(xt(e,(...b)=>{const w=g.value>0&&g.value===v.value;g.value=0,v.value=0,!w&&c(...b)},s)),h=()=>{p.forEach(b=>b())}}return{stop:h,ignoreUpdates:f,ignorePrevAsyncUpdates:d}}function SE(e,t,r){return xt(e,t,{...r,immediate:!0})}function _E(e,t,r){const o=xt(e,(...s)=>(Et(()=>o()),t(...s)),r);return o}function TE(e,t,r){let o;Mt(r)?o={evaluating:r}:o={};const{lazy:s=!1,evaluating:c=void 0,shallow:f=!0,onError:d=yu}=o,h=Ft(!s),p=f?Ft(t):Ge(t);let g=0;return _b(async v=>{if(!h.value)return;g++;const b=g;let w=!1;c&&Promise.resolve().then(()=>{c.value=!0});try{const E=await e(L=>{v(()=>{c&&(c.value=!1),w||L()})});b===g&&(p.value=E)}catch(E){d(E)}finally{c&&b===g&&(c.value=!1),w=!0}}),s?ke(()=>(h.value=!0,p.value)):p}const Ir=mE?window:void 0;function bu(e){var t;const r=Xt(e);return(t=r?.$el)!=null?t:r}function ho(...e){const t=[],r=()=>{t.forEach(d=>d()),t.length=0},o=(d,h,p,g)=>(d.addEventListener(h,p,g),()=>d.removeEventListener(h,p,g)),s=ke(()=>{const d=Cd(Xt(e[0])).filter(h=>h!=null);return d.every(h=>typeof h!=\"string\")?d:void 0}),c=SE(()=>{var d,h;return[(h=(d=s.value)==null?void 0:d.map(p=>bu(p)))!=null?h:[Ir].filter(p=>p!=null),Cd(Xt(s.value?e[1]:e[0])),Cd(K(s.value?e[2]:e[1])),Xt(s.value?e[3]:e[2])]},([d,h,p,g])=>{if(r(),!d?.length||!h?.length||!p?.length)return;const v=yE(g)?{...g}:g;t.push(...d.flatMap(b=>h.flatMap(w=>p.map(E=>o(b,w,E,v)))))},{flush:\"post\"}),f=()=>{c(),r()};return cp(r),f}function CE(){const e=Ft(!1),t=ti();return t&&Mi(()=>{e.value=!0},t),e}function Tw(e){const t=CE();return ke(()=>(t.value,!!e()))}function EE(e){return typeof e==\"function\"?e:typeof e==\"string\"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function Cw(...e){let t,r,o={};e.length===3?(t=e[0],r=e[1],o=e[2]):e.length===2?typeof e[1]==\"object\"?(t=!0,r=e[0],o=e[1]):(t=e[0],r=e[1]):(t=!0,r=e[0]);const{target:s=Ir,eventName:c=\"keydown\",passive:f=!1,dedupe:d=!1}=o,h=EE(t);return ho(s,c,g=>{g.repeat&&Xt(d)||h(g)&&r(g)},f)}function AE(e,t={}){const{immediate:r=!0,fpsLimit:o=void 0,window:s=Ir,once:c=!1}=t,f=Ft(!1),d=ke(()=>o?1e3/Xt(o):null);let h=0,p=null;function g(w){if(!f.value||!s)return;h||(h=w);const E=w-h;if(d.value&&E<d.value){p=s.requestAnimationFrame(g);return}if(h=w,e({delta:E,timestamp:w}),c){f.value=!1,p=null;return}p=s.requestAnimationFrame(g)}function v(){!f.value&&s&&(f.value=!0,h=0,p=s.requestAnimationFrame(g))}function b(){f.value=!1,p!=null&&s&&(s.cancelAnimationFrame(p),p=null)}return r&&v(),cp(b),{isActive:Gs(f),pause:b,resume:v}}const LE=Symbol(\"vueuse-ssr-width\");function ME(){const e=Sb()?gE(LE,null):null;return typeof e==\"number\"?e:void 0}function Ew(e,t={}){const{window:r=Ir,ssrWidth:o=ME()}=t,s=Tw(()=>r&&\"matchMedia\"in r&&typeof r.matchMedia==\"function\"),c=Ft(typeof o==\"number\"),f=Ft(),d=Ft(!1),h=p=>{d.value=p.matches};return _b(()=>{if(c.value){c.value=!s.value;const p=Xt(e).split(\",\");d.value=p.some(g=>{const v=g.includes(\"not all\"),b=g.match(/\\(\\s*min-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/),w=g.match(/\\(\\s*max-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/);let E=!!(b||w);return b&&E&&(E=o>=jv(b[1])),w&&E&&(E=o<=jv(w[1])),v?!E:E});return}s.value&&(f.value=r.matchMedia(Xt(e)),d.value=f.value.matches)}),ho(f,\"change\",h,{passive:!0}),ke(()=>d.value)}function Aw(e){return JSON.parse(JSON.stringify(e))}const Oc=typeof globalThis<\"u\"?globalThis:typeof window<\"u\"?window:typeof global<\"u\"?global:typeof self<\"u\"?self:{},Pc=\"__vueuse_ssr_handlers__\",NE=OE();function OE(){return Pc in Oc||(Oc[Pc]=Oc[Pc]||{}),Oc[Pc]}function Lw(e,t){return NE[e]||t}function PE(e){return Ew(\"(prefers-color-scheme: dark)\",e)}function RE(e){return e==null?\"any\":e instanceof Set?\"set\":e instanceof Map?\"map\":e instanceof Date?\"date\":typeof e==\"boolean\"?\"boolean\":typeof e==\"string\"?\"string\":typeof e==\"object\"?\"object\":Number.isNaN(e)?\"any\":\"number\"}const $E={boolean:{read:e=>e===\"true\",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Vv=\"vueuse-storage\";function Mw(e,t,r,o={}){var s;const{flush:c=\"pre\",deep:f=!0,listenToStorageChanges:d=!0,writeDefaults:h=!0,mergeDefaults:p=!1,shallow:g,window:v=Ir,eventFilter:b,onError:w=j=>{console.error(j)},initOnMounted:E}=o,L=(g?Ft:Ge)(typeof t==\"function\"?t():t),P=ke(()=>Xt(e));if(!r)try{r=Lw(\"getDefaultStorage\",()=>{var j;return(j=Ir)==null?void 0:j.localStorage})()}catch(j){w(j)}if(!r)return L;const M=Xt(t),R=RE(M),I=(s=o.serializer)!=null?s:$E[R],{pause:_,resume:$}=_w(L,()=>ne(L.value),{flush:c,deep:f,eventFilter:b});xt(P,()=>Z(),{flush:c}),v&&d&&dp(()=>{r instanceof Storage?ho(v,\"storage\",Z,{passive:!0}):ho(v,Vv,G),E&&Z()}),E||Z();function W(j,N){if(v){const O={key:P.value,oldValue:j,newValue:N,storageArea:r};v.dispatchEvent(r instanceof Storage?new StorageEvent(\"storage\",O):new CustomEvent(Vv,{detail:O}))}}function ne(j){try{const N=r.getItem(P.value);if(j==null)W(N,null),r.removeItem(P.value);else{const O=I.write(j);N!==O&&(r.setItem(P.value,O),W(N,O))}}catch(N){w(N)}}function ee(j){const N=j?j.newValue:r.getItem(P.value);if(N==null)return h&&M!=null&&r.setItem(P.value,I.write(M)),M;if(!j&&p){const O=I.read(N);return typeof p==\"function\"?p(O,M):R===\"object\"&&!Array.isArray(O)?{...M,...O}:O}else return typeof N!=\"string\"?N:I.read(N)}function Z(j){if(!(j&&j.storageArea!==r)){if(j&&j.key==null){L.value=M;return}if(!(j&&j.key!==P.value)){_();try{j?.newValue!==I.write(L.value)&&(L.value=ee(j))}catch(N){w(N)}finally{j?Et($):$()}}}}function G(j){Z(j.detail)}return L}const IE=\"*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}\";function DE(e={}){const{selector:t=\"html\",attribute:r=\"class\",initialValue:o=\"auto\",window:s=Ir,storage:c,storageKey:f=\"vueuse-color-scheme\",listenToStorageChanges:d=!0,storageRef:h,emitAuto:p,disableTransition:g=!0}=e,v={auto:\"\",light:\"light\",dark:\"dark\",...e.modes||{}},b=PE({window:s}),w=ke(()=>b.value?\"dark\":\"light\"),E=h||(f==null?Yo(o):Mw(f,o,c,{window:s,listenToStorageChanges:d})),L=ke(()=>E.value===\"auto\"?w.value:E.value),P=Lw(\"updateHTMLAttrs\",(_,$,W)=>{const ne=typeof _==\"string\"?s?.document.querySelector(_):bu(_);if(!ne)return;const ee=new Set,Z=new Set;let G=null;if($===\"class\"){const N=W.split(/\\s/g);Object.values(v).flatMap(O=>(O||\"\").split(/\\s/g)).filter(Boolean).forEach(O=>{N.includes(O)?ee.add(O):Z.add(O)})}else G={key:$,value:W};if(ee.size===0&&Z.size===0&&G===null)return;let j;g&&(j=s.document.createElement(\"style\"),j.appendChild(document.createTextNode(IE)),s.document.head.appendChild(j));for(const N of ee)ne.classList.add(N);for(const N of Z)ne.classList.remove(N);G&&ne.setAttribute(G.key,G.value),g&&(s.getComputedStyle(j).opacity,document.head.removeChild(j))});function M(_){var $;P(t,r,($=v[_])!=null?$:_)}function R(_){e.onChanged?e.onChanged(_,M):M(_)}xt(L,R,{flush:\"post\",immediate:!0}),dp(()=>R(L.value));const I=ke({get(){return p?E.value:L.value},set(_){E.value=_}});return Object.assign(I,{store:E,system:w,state:L})}function zE(e={}){const{valueDark:t=\"dark\",valueLight:r=\"\"}=e,o=DE({...e,onChanged:(f,d)=>{var h;e.onChanged?(h=e.onChanged)==null||h.call(e,f===\"dark\",d,f):d(f)},modes:{dark:t,light:r}}),s=ke(()=>o.system.value);return ke({get(){return o.value===\"dark\"},set(f){const d=f?\"dark\":\"light\";s.value===d?o.value=\"auto\":o.value=d}})}function Nw(e){return e}function FE(e,t){return e.value=t}function HE(e){return e?typeof e==\"function\"?e:Aw:Nw}function BE(e){return e?typeof e==\"function\"?e:Aw:Nw}function WE(e,t={}){const{clone:r=!1,dump:o=HE(r),parse:s=BE(r),setSource:c=FE}=t;function f(){return Uu({snapshot:o(e.value),timestamp:bE()})}const d=Ge(f()),h=Ge([]),p=Ge([]),g=I=>{c(e,s(I.snapshot)),d.value=I},v=()=>{h.value.unshift(d.value),d.value=f(),t.capacity&&h.value.length>t.capacity&&h.value.splice(t.capacity,Number.POSITIVE_INFINITY),p.value.length&&p.value.splice(0,p.value.length)},b=()=>{h.value.splice(0,h.value.length),p.value.splice(0,p.value.length)},w=()=>{const I=h.value.shift();I&&(p.value.unshift(d.value),g(I))},E=()=>{const I=p.value.shift();I&&(h.value.unshift(d.value),g(I))},L=()=>{g(d.value)},P=ke(()=>[d.value,...h.value]),M=ke(()=>h.value.length>0),R=ke(()=>p.value.length>0);return{source:e,undoStack:h,redoStack:p,last:d,history:P,canUndo:M,canRedo:R,clear:b,commit:v,reset:L,undo:w,redo:E}}function qE(e,t={}){const{deep:r=!1,flush:o=\"pre\",eventFilter:s}=t,{eventFilter:c,pause:f,resume:d,isActive:h}=kw(s),{ignoreUpdates:p,ignorePrevAsyncUpdates:g,stop:v}=kE(e,P,{deep:r,flush:o,eventFilter:c});function b(_,$){g(),p(()=>{_.value=$})}const w=WE(e,{...t,clone:t.clone||r,setSource:b}),{clear:E,commit:L}=w;function P(){g(),L()}function M(_){d(),_&&P()}function R(_){let $=!1;const W=()=>$=!0;p(()=>{_(W)}),$||P()}function I(){v(),E()}return{...w,isTracking:h,pause:f,resume:M,commit:P,batch:R,dispose:I}}function Ow(e,t,r={}){const{window:o=Ir,...s}=r;let c;const f=Tw(()=>o&&\"ResizeObserver\"in o),d=()=>{c&&(c.disconnect(),c=void 0)},h=ke(()=>{const v=Xt(e);return Array.isArray(v)?v.map(b=>bu(b)):[bu(v)]}),p=xt(h,v=>{if(d(),f.value&&o){c=new ResizeObserver(t);for(const b of v)b&&c.observe(b,s)}},{immediate:!0,flush:\"post\"}),g=()=>{d(),p()};return cp(g),{isSupported:f,stop:g}}function sf(e,t,r={}){const{window:o=Ir}=r;return Mw(e,t,o?.localStorage,r)}function jE(e=\"history\",t={}){const{initialValue:r={},removeNullishValues:o=!0,removeFalsyValues:s=!1,write:c=!0,writeMode:f=\"replace\",window:d=Ir}=t;if(!d)return ir(r);const h=ir({});function p(){if(e===\"history\")return d.location.search||\"\";if(e===\"hash\"){const I=d.location.hash||\"\",_=I.indexOf(\"?\");return _>0?I.slice(_):\"\"}else return(d.location.hash||\"\").replace(/^#/,\"\")}function g(I){const _=I.toString();if(e===\"history\")return`${_?`?${_}`:\"\"}${d.location.hash||\"\"}`;if(e===\"hash-params\")return`${d.location.search||\"\"}${_?`#${_}`:\"\"}`;const $=d.location.hash||\"#\",W=$.indexOf(\"?\");return W>0?`${d.location.search||\"\"}${$.slice(0,W)}${_?`?${_}`:\"\"}`:`${d.location.search||\"\"}${$}${_?`?${_}`:\"\"}`}function v(){return new URLSearchParams(p())}function b(I){const _=new Set(Object.keys(h));for(const $ of I.keys()){const W=I.getAll($);h[$]=W.length>1?W:I.get($)||\"\",_.delete($)}Array.from(_).forEach($=>delete h[$])}const{pause:w,resume:E}=_w(h,()=>{const I=new URLSearchParams(\"\");Object.keys(h).forEach(_=>{const $=h[_];Array.isArray($)?$.forEach(W=>I.append(_,W)):o&&$==null||s&&!$?I.delete(_):I.set(_,$)}),L(I,!1)},{deep:!0});function L(I,_){w(),_&&b(I),f===\"replace\"?d.history.replaceState(d.history.state,d.document.title,d.location.pathname+g(I)):d.history.pushState(d.history.state,d.document.title,d.location.pathname+g(I)),E()}function P(){c&&L(v(),!0)}const M={passive:!0};ho(d,\"popstate\",P,M),e!==\"history\"&&ho(d,\"hashchange\",P,M);const R=v();return R.keys().next().value?b(R):Object.assign(h,r),h}function Pw(e={}){const{window:t=Ir,initialWidth:r=Number.POSITIVE_INFINITY,initialHeight:o=Number.POSITIVE_INFINITY,listenOrientation:s=!0,includeScrollbar:c=!0,type:f=\"inner\"}=e,d=Ft(r),h=Ft(o),p=()=>{if(t)if(f===\"outer\")d.value=t.outerWidth,h.value=t.outerHeight;else if(f===\"visual\"&&t.visualViewport){const{width:v,height:b,scale:w}=t.visualViewport;d.value=Math.round(v*w),h.value=Math.round(b*w)}else c?(d.value=t.innerWidth,h.value=t.innerHeight):(d.value=t.document.documentElement.clientWidth,h.value=t.document.documentElement.clientHeight)};p(),dp(p);const g={passive:!0};if(ho(\"resize\",p,g),t&&f===\"visual\"&&t.visualViewport&&ho(t.visualViewport,\"resize\",p,g),s){const v=Ew(\"(orientation: portrait)\");xt(v,()=>p())}return{width:d,height:h}}const Gv={__name:\"splitpanes\",props:{horizontal:{type:Boolean,default:!1},pushOtherPanes:{type:Boolean,default:!0},maximizePanes:{type:Boolean,default:!0},rtl:{type:Boolean,default:!1},firstSplitter:{type:Boolean,default:!1}},emits:[\"ready\",\"resize\",\"resized\",\"pane-click\",\"pane-maximize\",\"pane-add\",\"pane-remove\",\"splitter-click\",\"splitter-dblclick\"],setup(e,{emit:t}){const r=t,o=e,s=yb(),c=Ge([]),f=ke(()=>c.value.reduce((F,Y)=>(F[~~Y.id]=Y)&&F,{})),d=ke(()=>c.value.length),h=Ge(null),p=Ge(!1),g=Ge({mouseDown:!1,dragging:!1,activeSplitter:null,cursorOffset:0}),v=Ge({splitter:null,timeoutId:null}),b=ke(()=>({[`splitpanes splitpanes--${o.horizontal?\"horizontal\":\"vertical\"}`]:!0,\"splitpanes--dragging\":g.value.dragging})),w=()=>{document.addEventListener(\"mousemove\",P,{passive:!1}),document.addEventListener(\"mouseup\",M),\"ontouchstart\"in window&&(document.addEventListener(\"touchmove\",P,{passive:!1}),document.addEventListener(\"touchend\",M))},E=()=>{document.removeEventListener(\"mousemove\",P,{passive:!1}),document.removeEventListener(\"mouseup\",M),\"ontouchstart\"in window&&(document.removeEventListener(\"touchmove\",P,{passive:!1}),document.removeEventListener(\"touchend\",M))},L=(F,Y)=>{const re=F.target.closest(\".splitpanes__splitter\");if(re){const{left:le,top:ae}=re.getBoundingClientRect(),{clientX:D,clientY:q}=\"ontouchstart\"in window&&F.touches?F.touches[0]:F;g.value.cursorOffset=o.horizontal?q-ae:D-le}w(),g.value.mouseDown=!0,g.value.activeSplitter=Y},P=F=>{g.value.mouseDown&&(F.preventDefault(),g.value.dragging=!0,requestAnimationFrame(()=>{ne($(F)),Fe(\"resize\",{event:F},!0)}))},M=F=>{g.value.dragging&&(window.getSelection().removeAllRanges(),Fe(\"resized\",{event:F},!0)),g.value.mouseDown=!1,g.value.activeSplitter=null,setTimeout(()=>{g.value.dragging=!1,E()},100)},R=(F,Y)=>{\"ontouchstart\"in window&&(F.preventDefault(),v.value.splitter===Y?(clearTimeout(v.value.timeoutId),v.value.timeoutId=null,I(F,Y),v.value.splitter=null):(v.value.splitter=Y,v.value.timeoutId=setTimeout(()=>v.value.splitter=null,500))),g.value.dragging||Fe(\"splitter-click\",{event:F,index:Y},!0)},I=(F,Y)=>{if(Fe(\"splitter-dblclick\",{event:F,index:Y},!0),o.maximizePanes){let re=0;c.value=c.value.map((le,ae)=>(le.size=ae===Y?le.max:le.min,ae!==Y&&(re+=le.min),le)),c.value[Y].size-=re,Fe(\"pane-maximize\",{event:F,index:Y,pane:c.value[Y]}),Fe(\"resized\",{event:F,index:Y},!0)}},_=(F,Y)=>{Fe(\"pane-click\",{event:F,index:f.value[Y].index,pane:f.value[Y]})},$=F=>{const Y=h.value.getBoundingClientRect(),{clientX:re,clientY:le}=\"ontouchstart\"in window&&F.touches?F.touches[0]:F;return{x:re-(o.horizontal?0:g.value.cursorOffset)-Y.left,y:le-(o.horizontal?g.value.cursorOffset:0)-Y.top}},W=F=>{F=F[o.horizontal?\"y\":\"x\"];const Y=h.value[o.horizontal?\"clientHeight\":\"clientWidth\"];return o.rtl&&!o.horizontal&&(F=Y-F),F*100/Y},ne=F=>{const Y=g.value.activeSplitter;let re={prevPanesSize:Z(Y),nextPanesSize:G(Y),prevReachedMinPanes:0,nextReachedMinPanes:0};const le=0+(o.pushOtherPanes?0:re.prevPanesSize),ae=100-(o.pushOtherPanes?0:re.nextPanesSize),D=Math.max(Math.min(W(F),ae),le);let q=[Y,Y+1],Q=c.value[q[0]]||null,he=c.value[q[1]]||null;const de=Q.max<100&&D>=Q.max+re.prevPanesSize,ge=he.max<100&&D<=100-(he.max+G(Y+1));if(de||ge){de?(Q.size=Q.max,he.size=Math.max(100-Q.max-re.prevPanesSize-re.nextPanesSize,0)):(Q.size=Math.max(100-he.max-re.prevPanesSize-G(Y+1),0),he.size=he.max);return}if(o.pushOtherPanes){const Ce=ee(re,D);if(!Ce)return;({sums:re,panesToResize:q}=Ce),Q=c.value[q[0]]||null,he=c.value[q[1]]||null}Q!==null&&(Q.size=Math.min(Math.max(D-re.prevPanesSize-re.prevReachedMinPanes,Q.min),Q.max)),he!==null&&(he.size=Math.min(Math.max(100-D-re.nextPanesSize-re.nextReachedMinPanes,he.min),he.max))},ee=(F,Y)=>{const re=g.value.activeSplitter,le=[re,re+1];return Y<F.prevPanesSize+c.value[le[0]].min&&(le[0]=j(re).index,F.prevReachedMinPanes=0,le[0]<re&&c.value.forEach((ae,D)=>{D>le[0]&&D<=re&&(ae.size=ae.min,F.prevReachedMinPanes+=ae.min)}),F.prevPanesSize=Z(le[0]),le[0]===void 0)?(F.prevReachedMinPanes=0,c.value[0].size=c.value[0].min,c.value.forEach((ae,D)=>{D>0&&D<=re&&(ae.size=ae.min,F.prevReachedMinPanes+=ae.min)}),c.value[le[1]].size=100-F.prevReachedMinPanes-c.value[0].min-F.prevPanesSize-F.nextPanesSize,null):Y>100-F.nextPanesSize-c.value[le[1]].min&&(le[1]=N(re).index,F.nextReachedMinPanes=0,le[1]>re+1&&c.value.forEach((ae,D)=>{D>re&&D<le[1]&&(ae.size=ae.min,F.nextReachedMinPanes+=ae.min)}),F.nextPanesSize=G(le[1]-1),le[1]===void 0)?(F.nextReachedMinPanes=0,c.value.forEach((ae,D)=>{D<d.value-1&&D>=re+1&&(ae.size=ae.min,F.nextReachedMinPanes+=ae.min)}),c.value[le[0]].size=100-F.prevPanesSize-G(le[0]-1),null):{sums:F,panesToResize:le}},Z=F=>c.value.reduce((Y,re,le)=>Y+(le<F?re.size:0),0),G=F=>c.value.reduce((Y,re,le)=>Y+(le>F+1?re.size:0),0),j=F=>[...c.value].reverse().find(Y=>Y.index<F&&Y.size>Y.min)||{},N=F=>c.value.find(Y=>Y.index>F+1&&Y.size>Y.min)||{},O=()=>{var F;const Y=Array.from(((F=h.value)==null?void 0:F.children)||[]);for(const re of Y){const le=re.classList.contains(\"splitpanes__pane\"),ae=re.classList.contains(\"splitpanes__splitter\");!le&&!ae&&(re.remove(),console.warn(\"Splitpanes: Only <pane> elements are allowed at the root of <splitpanes>. One of your DOM nodes was removed.\"))}},C=(F,Y,re=!1)=>{const le=F-1,ae=document.createElement(\"div\");ae.classList.add(\"splitpanes__splitter\"),re||(ae.onmousedown=D=>L(D,le),typeof window<\"u\"&&\"ontouchstart\"in window&&(ae.ontouchstart=D=>L(D,le)),ae.onclick=D=>R(D,le+1)),ae.ondblclick=D=>I(D,le+1),Y.parentNode.insertBefore(ae,Y)},k=F=>{F.onmousedown=void 0,F.onclick=void 0,F.ondblclick=void 0,F.remove()},z=()=>{var F;const Y=Array.from(((F=h.value)==null?void 0:F.children)||[]);for(const le of Y)le.className.includes(\"splitpanes__splitter\")&&k(le);let re=0;for(const le of Y)le.className.includes(\"splitpanes__pane\")&&(!re&&o.firstSplitter?C(re,le,!0):re&&C(re,le),re++)},B=({uid:F,...Y})=>{const re=f.value[F];for(const[le,ae]of Object.entries(Y))re[le]=ae},ce=F=>{var Y;let re=-1;Array.from(((Y=h.value)==null?void 0:Y.children)||[]).some(le=>(le.className.includes(\"splitpanes__pane\")&&re++,le.isSameNode(F.el))),c.value.splice(re,0,{...F,index:re}),c.value.forEach((le,ae)=>le.index=ae),p.value&&Et(()=>{z(),Se({addedPane:c.value[re]}),Fe(\"pane-add\",{pane:c.value[re]})})},be=F=>{const Y=c.value.findIndex(le=>le.id===F);c.value[Y].el=null;const re=c.value.splice(Y,1)[0];c.value.forEach((le,ae)=>le.index=ae),Et(()=>{z(),Fe(\"pane-remove\",{pane:re}),Se({removedPane:{...re}})})},Se=(F={})=>{!F.addedPane&&!F.removedPane?Ae():c.value.some(Y=>Y.givenSize!==null||Y.min||Y.max<100)?Ke(F):Be(),p.value&&Fe(\"resized\")},Be=()=>{const F=100/d.value;let Y=0;const re=[],le=[];for(const ae of c.value)ae.size=Math.max(Math.min(F,ae.max),ae.min),Y-=ae.size,ae.size>=ae.max&&re.push(ae.id),ae.size<=ae.min&&le.push(ae.id);Y>.1&&je(Y,re,le)},Ae=()=>{let F=100;const Y=[],re=[];let le=0;for(const D of c.value)F-=D.size,D.givenSize!==null&&le++,D.size>=D.max&&Y.push(D.id),D.size<=D.min&&re.push(D.id);let ae=100;if(F>.1){for(const D of c.value)D.givenSize===null&&(D.size=Math.max(Math.min(F/(d.value-le),D.max),D.min)),ae-=D.size;ae>.1&&je(ae,Y,re)}},Ke=({addedPane:F,removedPane:Y}={})=>{let re=100/d.value,le=0;const ae=[],D=[];(F?.givenSize??null)!==null&&(re=(100-F.givenSize)/(d.value-1));for(const q of c.value)le-=q.size,q.size>=q.max&&ae.push(q.id),q.size<=q.min&&D.push(q.id);if(!(Math.abs(le)<.1)){for(const q of c.value)F?.givenSize!==null&&F?.id===q.id||(q.size=Math.max(Math.min(re,q.max),q.min)),le-=q.size,q.size>=q.max&&ae.push(q.id),q.size<=q.min&&D.push(q.id);le>.1&&je(le,ae,D)}},je=(F,Y,re)=>{let le;F>0?le=F/(d.value-Y.length):le=F/(d.value-re.length),c.value.forEach((ae,D)=>{if(F>0&&!Y.includes(ae.id)){const q=Math.max(Math.min(ae.size+le,ae.max),ae.min),Q=q-ae.size;F-=Q,ae.size=q}else if(!re.includes(ae.id)){const q=Math.max(Math.min(ae.size+le,ae.max),ae.min),Q=q-ae.size;F-=Q,ae.size=q}}),Math.abs(F)>.1&&Et(()=>{p.value&&console.warn(\"Splitpanes: Could not resize panes correctly due to their constraints.\")})},Fe=(F,Y=void 0,re=!1)=>{const le=Y?.index??g.value.activeSplitter??null;r(F,{...Y,...le!==null&&{index:le},...re&&le!==null&&{prevPane:c.value[le-(o.firstSplitter?1:0)],nextPane:c.value[le+(o.firstSplitter?0:1)]},panes:c.value.map(ae=>({min:ae.min,max:ae.max,size:ae.size}))})};xt(()=>o.firstSplitter,()=>z()),Mi(()=>{O(),z(),Se(),Fe(\"ready\"),p.value=!0}),$a(()=>p.value=!1);const Pe=()=>{var F;return za(\"div\",{ref:h,class:b.value},(F=s.default)==null?void 0:F.call(s))};return dr(\"panes\",c),dr(\"indexedPanes\",f),dr(\"horizontal\",ke(()=>o.horizontal)),dr(\"requestUpdate\",B),dr(\"onPaneAdd\",ce),dr(\"onPaneRemove\",be),dr(\"onPaneClick\",_),(F,Y)=>(ie(),Ve(Xd(Pe)))}},Rc={__name:\"pane\",props:{size:{type:[Number,String]},minSize:{type:[Number,String],default:0},maxSize:{type:[Number,String],default:100}},setup(e){var t;const r=e,o=pn(\"requestUpdate\"),s=pn(\"onPaneAdd\"),c=pn(\"horizontal\"),f=pn(\"onPaneRemove\"),d=pn(\"onPaneClick\"),h=(t=ti())==null?void 0:t.uid,p=pn(\"indexedPanes\"),g=ke(()=>p.value[h]),v=Ge(null),b=ke(()=>{const P=isNaN(r.size)||r.size===void 0?0:parseFloat(r.size);return Math.max(Math.min(P,E.value),w.value)}),w=ke(()=>{const P=parseFloat(r.minSize);return isNaN(P)?0:P}),E=ke(()=>{const P=parseFloat(r.maxSize);return isNaN(P)?100:P}),L=ke(()=>{var P;return`${c.value?\"height\":\"width\"}: ${(P=g.value)==null?void 0:P.size}%`});return xt(()=>b.value,P=>o({uid:h,size:P})),xt(()=>w.value,P=>o({uid:h,min:P})),xt(()=>E.value,P=>o({uid:h,max:P})),Mi(()=>{s({id:h,el:v.value,min:w.value,max:E.value,givenSize:r.size===void 0?null:b.value,size:b.value})}),$a(()=>f(h)),(P,M)=>(ie(),ve(\"div\",{ref_key:\"paneEl\",ref:v,class:\"splitpanes__pane\",onClick:M[0]||(M[0]=R=>K(d)(R,P._.uid)),style:zt(L.value)},[Dt(P.$slots,\"default\")],4))}},tr=Ge([414,896]);function Rw(e){return e!=null}function pp(e){return e==null&&(e=[]),Array.isArray(e)?e:[e]}const UE=/^[A-Za-z]:\\//;function VE(e=\"\"){return e&&e.replace(/\\\\/g,\"/\").replace(UE,t=>t.toUpperCase())}const GE=/^[/\\\\](?![/\\\\])|^[/\\\\]{2}(?!\\.)|^[A-Za-z]:[/\\\\]/;function KE(){return typeof process<\"u\"&&typeof process.cwd==\"function\"?process.cwd().replace(/\\\\/g,\"/\"):\"/\"}const $w=function(...e){e=e.map(o=>VE(o));let t=\"\",r=!1;for(let o=e.length-1;o>=-1&&!r;o--){const s=o>=0?e[o]:KE();!s||s.length===0||(t=`${s}/${t}`,r=Kv(s))}return t=XE(t,!r),r&&!Kv(t)?`/${t}`:t.length>0?t:\".\"};function XE(e,t){let r=\"\",o=0,s=-1,c=0,f=null;for(let d=0;d<=e.length;++d){if(d<e.length)f=e[d];else{if(f===\"/\")break;f=\"/\"}if(f===\"/\"){if(!(s===d-1||c===1))if(c===2){if(r.length<2||o!==2||r[r.length-1]!==\".\"||r[r.length-2]!==\".\"){if(r.length>2){const h=r.lastIndexOf(\"/\");h===-1?(r=\"\",o=0):(r=r.slice(0,h),o=r.length-1-r.lastIndexOf(\"/\")),s=d,c=0;continue}else if(r.length>0){r=\"\",o=0,s=d,c=0;continue}}t&&(r+=r.length>0?\"/..\":\"..\",o=2)}else r.length>0?r+=`/${e.slice(s+1,d)}`:r=e.slice(s+1,d),o=d-s-1;s=d,c=0}else f===\".\"&&c!==-1?++c:c=-1}return r}const Kv=function(e){return GE.test(e)};var YE=44,Xv=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",ZE=new Uint8Array(64),Iw=new Uint8Array(128);for(let e=0;e<Xv.length;e++){const t=Xv.charCodeAt(e);ZE[e]=t,Iw[t]=e}function Hl(e,t){let r=0,o=0,s=0;do{const f=e.next();s=Iw[f],r|=(s&31)<<o,o+=5}while(s&32);const c=r&1;return r>>>=1,c&&(r=-2147483648|-r),t+r}function Yv(e,t){return e.pos>=t?!1:e.peek()!==YE}var JE=class{constructor(e){this.pos=0,this.buffer=e}next(){return this.buffer.charCodeAt(this.pos++)}peek(){return this.buffer.charCodeAt(this.pos)}indexOf(e){const{buffer:t,pos:r}=this,o=t.indexOf(e,r);return o===-1?t.length:o}};function QE(e){const{length:t}=e,r=new JE(e),o=[];let s=0,c=0,f=0,d=0,h=0;do{const p=r.indexOf(\";\"),g=[];let v=!0,b=0;for(s=0;r.pos<p;){let w;s=Hl(r,s),s<b&&(v=!1),b=s,Yv(r,p)?(c=Hl(r,c),f=Hl(r,f),d=Hl(r,d),Yv(r,p)?(h=Hl(r,h),w=[s,c,f,d,h]):w=[s,c,f,d]):w=[s],g.push(w),r.pos++}v||eA(g),o.push(g),r.pos=p+1}while(r.pos<=t);return o}function eA(e){e.sort(tA)}function tA(e,t){return e[0]-t[0]}var lf=0,nA=1,rA=2,iA=3,oA=4,wu=!1;function sA(e,t,r,o){for(;r<=o;){const s=r+(o-r>>1),c=e[s][lf]-t;if(c===0)return wu=!0,s;c<0?r=s+1:o=s-1}return wu=!1,r-1}function lA(e,t,r){for(let o=r+1;o<e.length&&e[o][lf]===t;r=o++);return r}function aA(e,t,r){for(let o=r-1;o>=0&&e[o][lf]===t;r=o--);return r}function cA(e,t,r,o){const{lastKey:s,lastNeedle:c,lastIndex:f}=r;let d=0,h=e.length-1;if(o===s){if(t===c)return wu=f!==-1&&e[f][lf]===t,f;t>=c?d=f===-1?0:f:h=f}return r.lastKey=o,r.lastNeedle=t,r.lastIndex=sA(e,t,d,h)}var uA=\"`line` must be greater than 0 (lines start at line 1)\",fA=\"`column` must be greater than or equal to 0 (columns start at column 0)\",Zv=-1,dA=1;function hA(e){var t;return(t=e)._decoded||(t._decoded=QE(e._encoded))}function pA(e,t){let{line:r,column:o,bias:s}=t;if(r--,r<0)throw new Error(uA);if(o<0)throw new Error(fA);const c=hA(e);if(r>=c.length)return $c(null,null,null,null);const f=c[r],d=gA(f,e._decodedMemo,r,o,s||dA);if(d===-1)return $c(null,null,null,null);const h=f[d];if(h.length===1)return $c(null,null,null,null);const{names:p,resolvedSources:g}=e;return $c(g[h[nA]],h[rA]+1,h[iA],h.length===5?p[h[oA]]:null)}function $c(e,t,r,o){return{source:e,line:t,column:r,name:o}}function gA(e,t,r,o,s){let c=cA(e,o,t,r);return wu?c=(s===Zv?lA:aA)(e,o,c):s===Zv&&c++,c===-1||c===e.length?-1:c}const Dw=/^\\s*at .*(?:\\S:\\d+|\\(native\\))/m,mA=/^(?:eval@)?(?:\\[native code\\])?$/,vA=[\"node:internal\",/\\/packages\\/\\w+\\/dist\\//,/\\/@vitest\\/\\w+\\/dist\\//,\"/vitest/dist/\",\"/vitest/src/\",\"/node_modules/chai/\",\"/node_modules/tinyspy/\",\"/vite/dist/node/module-runner\",\"/rolldown-vite/dist/node/module-runner\",\"/deps/chunk-\",\"/deps/@vitest\",\"/deps/loupe\",\"/deps/chai\",\"/browser-playwright/dist/locators.js\",\"/browser-webdriverio/dist/locators.js\",\"/browser-preview/dist/locators.js\",/node:\\w+/,/__vitest_test__/,/__vitest_browser__/,/\\/deps\\/vitest_/];function zw(e){if(!e.includes(\":\"))return[e];const r=/(.+?)(?::(\\d+))?(?::(\\d+))?$/.exec(e.replace(/^\\(|\\)$/g,\"\"));if(!r)return[e];let o=r[1];if(o.startsWith(\"async \")&&(o=o.slice(6)),o.startsWith(\"http:\")||o.startsWith(\"https:\")){const s=new URL(o);s.searchParams.delete(\"import\"),s.searchParams.delete(\"browserv\"),o=s.pathname+s.hash+s.search}if(o.startsWith(\"/@fs/\")){const s=/^\\/@fs\\/[a-zA-Z]:\\//.test(o);o=o.slice(s?5:4)}return[o,r[2]||void 0,r[3]||void 0]}function yA(e){let t=e.trim();if(mA.test(t)||(t.includes(\" > eval\")&&(t=t.replace(/ line (\\d+)(?: > eval line \\d+)* > eval:\\d+:\\d+/g,\":$1\")),!t.includes(\"@\")))return null;let r=-1,o=\"\",s;for(let h=0;h<t.length;h++)if(t[h]===\"@\"){const p=t.slice(h+1);if(p.includes(\":\")&&p.length>=3){r=h,o=p,s=h>0?t.slice(0,h):void 0;break}}if(r===-1||!o.includes(\":\")||o.length<3)return null;const[c,f,d]=zw(o);return!c||!f||!d?null:{file:c,method:s||\"\",line:Number.parseInt(f),column:Number.parseInt(d)}}function bA(e){let t=e.trim();if(!Dw.test(t))return null;t.includes(\"(eval \")&&(t=t.replace(/eval code/g,\"eval\").replace(/(\\(eval at [^()]*)|(,.*$)/g,\"\"));let r=t.replace(/^\\s+/,\"\").replace(/\\(eval code/g,\"(\").replace(/^.*?\\s+/,\"\");const o=r.match(/ (\\(.+\\)$)/);r=o?r.replace(o[0],\"\"):r;const[s,c,f]=zw(o?o[1]:r);let d=o&&r||\"\",h=s&&[\"eval\",\"<anonymous>\"].includes(s)?void 0:s;return!h||!c||!f?null:(d.startsWith(\"async \")&&(d=d.slice(6)),h.startsWith(\"file://\")&&(h=h.slice(7)),h=h.startsWith(\"node:\")||h.startsWith(\"internal:\")?h:$w(h),d&&(d=d.replace(/__vite_ssr_import_\\d+__\\./g,\"\").replace(/(Object\\.)?__vite_ssr_export_default__\\s?/g,\"\")),{method:d,file:h,line:Number.parseInt(c),column:Number.parseInt(f)})}function wA(e,t={}){const{ignoreStackEntries:r=vA}=t;return(Dw.test(e)?kA(e):xA(e)).map(s=>{var c;t.getUrlId&&(s.file=t.getUrlId(s.file));const f=(c=t.getSourceMap)===null||c===void 0?void 0:c.call(t,s.file);if(!f||typeof f!=\"object\"||!f.version)return Jv(r,s.file)?null:s;const d=new SA(f,s.file),h=TA(d,s);if(!h)return s;const{line:p,column:g,source:v,name:b}=h;let w=v||s.file;return w.match(/\\/\\w:\\//)&&(w=w.slice(1)),Jv(r,w)?null:p!=null&&g!=null?{line:p,column:g,file:w,method:b||s.method}:s}).filter(s=>s!=null)}function Jv(e,t){return e.some(r=>t.match(r))}function xA(e){return e.split(`\n`).map(t=>yA(t)).filter(Rw)}function kA(e){return e.split(`\n`).map(t=>bA(t)).filter(Rw)}class SA{_encoded;_decoded;_decodedMemo;url;version;names=[];resolvedSources;constructor(t,r){this.map=t;const{mappings:o,names:s,sources:c}=t;this.version=t.version,this.names=s||[],this._encoded=o||\"\",this._decodedMemo=_A(),this.url=r,this.resolvedSources=(c||[]).map(f=>$w(f||\"\",r))}}function _A(){return{lastKey:-1,lastNeedle:-1,lastIndex:-1}}function TA(e,t){const r=pA(e,t);return r.column==null?null:r}const CA=/^[A-Za-z]:\\//;function Fw(e=\"\"){return e&&e.replace(/\\\\/g,\"/\").replace(CA,t=>t.toUpperCase())}const EA=/^[/\\\\]{2}/,AA=/^[/\\\\](?![/\\\\])|^[/\\\\]{2}(?!\\.)|^[A-Za-z]:[/\\\\]/,LA=/^[A-Za-z]:$/,Qv=/^\\/([A-Za-z]:)?$/,MA=function(e){if(e.length===0)return\".\";e=Fw(e);const t=e.match(EA),r=xu(e),o=e[e.length-1]===\"/\";return e=Hw(e,!r),e.length===0?r?\"/\":o?\"./\":\".\":(o&&(e+=\"/\"),LA.test(e)&&(e+=\"/\"),t?r?`//${e}`:`//./${e}`:r&&!xu(e)?`/${e}`:e)},NA=function(...e){let t=\"\";for(const r of e)if(r)if(t.length>0){const o=t[t.length-1]===\"/\",s=r[0]===\"/\";o&&s?t+=r.slice(1):t+=o||s?r:`/${r}`}else t+=r;return MA(t)};function OA(){return typeof process<\"u\"&&typeof process.cwd==\"function\"?process.cwd().replace(/\\\\/g,\"/\"):\"/\"}const ey=function(...e){e=e.map(o=>Fw(o));let t=\"\",r=!1;for(let o=e.length-1;o>=-1&&!r;o--){const s=o>=0?e[o]:OA();!s||s.length===0||(t=`${s}/${t}`,r=xu(s))}return t=Hw(t,!r),r&&!xu(t)?`/${t}`:t.length>0?t:\".\"};function Hw(e,t){let r=\"\",o=0,s=-1,c=0,f=null;for(let d=0;d<=e.length;++d){if(d<e.length)f=e[d];else{if(f===\"/\")break;f=\"/\"}if(f===\"/\"){if(!(s===d-1||c===1))if(c===2){if(r.length<2||o!==2||r[r.length-1]!==\".\"||r[r.length-2]!==\".\"){if(r.length>2){const h=r.lastIndexOf(\"/\");h===-1?(r=\"\",o=0):(r=r.slice(0,h),o=r.length-1-r.lastIndexOf(\"/\")),s=d,c=0;continue}else if(r.length>0){r=\"\",o=0,s=d,c=0;continue}}t&&(r+=r.length>0?\"/..\":\"..\",o=2)}else r.length>0?r+=`/${e.slice(s+1,d)}`:r=e.slice(s+1,d),o=d-s-1;s=d,c=0}else f===\".\"&&c!==-1?++c:c=-1}return r}const xu=function(e){return AA.test(e)},af=function(e,t){const r=ey(e).replace(Qv,\"$1\").split(\"/\"),o=ey(t).replace(Qv,\"$1\").split(\"/\");if(o[0][1]===\":\"&&r[0][1]===\":\"&&r[0]!==o[0])return o.join(\"/\");const s=[...r];for(const c of s){if(o[0]!==c)break;r.shift(),o.shift()}return[...r.map(()=>\"..\"),...o].join(\"/\")};function PA(e){let t=0;if(e.length===0)return`${t}`;for(let r=0;r<e.length;r++){const o=e.charCodeAt(r);t=(t<<5)-t+o,t=t&t}return`${t}`}function Bw(e,t,r,o,s){const c=af(t,e),f={id:RA(c,r),name:c,fullName:c,type:\"suite\",mode:\"queued\",filepath:e,tasks:[],meta:Object.create(null),projectName:r,file:void 0,pool:o,viteEnvironment:s};return f.file=f,f}function RA(e,t){return PA(`${e}${t||\"\"}`)}function Js(e){return e.type===\"test\"}function Ww(e){const t=[],r=pp(e);for(const o of r)if(Js(o))t.push(o);else for(const s of o.tasks)if(Js(s))t.push(s);else{const c=Ww(s);for(const f of c)t.push(f)}return t}function gp(e=[]){return pp(e).flatMap(t=>Js(t)?[t]:[t,...gp(t.tasks)])}function $A(e){const t=[e.name];let r=e;for(;r?.suite;)r=r.suite,r?.name&&t.unshift(r.name);return r!==e.file&&t.unshift(e.file.name),t}const ty=\"q\",ny=\"s\";function IA(){let e,t;return{promise:new Promise((r,o)=>{e=r,t=o}),resolve:e,reject:t}}const DA=Math.random.bind(Math),zA=\"useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict\";function FA(e=21){let t=\"\",r=e;for(;r--;)t+=zA[DA()*64|0];return t}const HA=6e4,qw=e=>e,BA=qw,{clearTimeout:ry,setTimeout:WA}=globalThis;function qA(e,t){const{post:r,on:o,off:s=()=>{},eventNames:c=[],serialize:f=qw,deserialize:d=BA,resolver:h,bind:p=\"rpc\",timeout:g=HA,proxify:v=!0}=t;let b=!1;const w=new Map;let E,L;async function P($,W,ne,ee){if(b)throw new Error(`[birpc] rpc is closed, cannot call \"${$}\"`);const Z={m:$,a:W,t:ty};ee&&(Z.o=!0);const G=async B=>r(f(B));if(ne){await G(Z);return}if(E)try{await E}finally{E=void 0}let{promise:j,resolve:N,reject:O}=IA();const C=FA();Z.i=C;let k;async function z(B=Z){return g>=0&&(k=WA(()=>{try{if(t.onTimeoutError?.call(L,$,W)!==!0)throw new Error(`[birpc] timeout on calling \"${$}\"`)}catch(ce){O(ce)}w.delete(C)},g),typeof k==\"object\"&&(k=k.unref?.())),w.set(C,{resolve:N,reject:O,timeoutId:k,method:$}),await G(B),j}try{t.onRequest?await t.onRequest.call(L,Z,z,N):await z()}catch(B){if(t.onGeneralError?.call(L,B)!==!0)throw B;return}finally{ry(k),w.delete(C)}return j}const M={$call:($,...W)=>P($,W,!1),$callOptional:($,...W)=>P($,W,!1,!0),$callEvent:($,...W)=>P($,W,!0),$callRaw:$=>P($.method,$.args,$.event,$.optional),$rejectPendingCalls:I,get $closed(){return b},get $meta(){return t.meta},$close:R,$functions:e};v?L=new Proxy({},{get($,W){if(Object.prototype.hasOwnProperty.call(M,W))return M[W];if(W===\"then\"&&!c.includes(\"then\")&&!(\"then\"in e))return;const ne=(...Z)=>P(W,Z,!0);if(c.includes(W))return ne.asEvent=ne,ne;const ee=(...Z)=>P(W,Z,!1);return ee.asEvent=ne,ee}}):L=M;function R($){b=!0,w.forEach(({reject:W,method:ne})=>{const ee=new Error(`[birpc] rpc is closed, cannot call \"${ne}\"`);if($)return $.cause??=ee,W($);W(ee)}),w.clear(),s(_)}function I($){const W=Array.from(w.values()).map(({method:ne,reject:ee})=>$?$({method:ne,reject:ee}):ee(new Error(`[birpc]: rejected pending call \"${ne}\".`)));return w.clear(),W}async function _($,...W){let ne;try{ne=d($)}catch(ee){if(t.onGeneralError?.call(L,ee)!==!0)throw ee;return}if(ne.t===ty){const{m:ee,a:Z,o:G}=ne;let j,N,O=await(h?h.call(L,ee,e[ee]):e[ee]);if(G&&(O||=()=>{}),!O)N=new Error(`[birpc] function \"${ee}\" not found`);else try{j=await O.apply(p===\"rpc\"?L:e,Z)}catch(C){N=C}if(ne.i){if(N&&t.onFunctionError&&t.onFunctionError.call(L,N,ee,Z)===!0)return;if(!N)try{await r(f({t:ny,i:ne.i,r:j}),...W);return}catch(C){if(N=C,t.onGeneralError?.call(L,C,ee,Z)!==!0)throw C}try{await r(f({t:ny,i:ne.i,e:N}),...W)}catch(C){if(t.onGeneralError?.call(L,C,ee,Z)!==!0)throw C}}}else{const{i:ee,r:Z,e:G}=ne,j=w.get(ee);j&&(ry(j.timeoutId),G?j.reject(G):j.resolve(Z)),w.delete(ee)}}return E=o(_),L}const{parse:jw,stringify:jA}=JSON,{keys:UA}=Object,ka=String,Uw=\"string\",iy={},ku=\"object\",Vw=(e,t)=>t,VA=e=>e instanceof ka?ka(e):e,GA=(e,t)=>typeof t===Uw?new ka(t):t,Gw=(e,t,r,o)=>{const s=[];for(let c=UA(r),{length:f}=c,d=0;d<f;d++){const h=c[d],p=r[h];if(p instanceof ka){const g=e[p];typeof g===ku&&!t.has(g)?(t.add(g),r[h]=iy,s.push({k:h,a:[e,t,g,o]})):r[h]=o.call(r,h,g)}else r[h]!==iy&&(r[h]=o.call(r,h,p))}for(let{length:c}=s,f=0;f<c;f++){const{k:d,a:h}=s[f];r[d]=o.call(r,d,Gw.apply(null,h))}return r},oy=(e,t,r)=>{const o=ka(t.push(r)-1);return e.set(r,o),o},fh=(e,t)=>{const r=jw(e,GA).map(VA),o=r[0],s=t||Vw,c=typeof o===ku&&o?Gw(r,new Set,o,s):o;return s.call({\"\":c},\"\",c)},Kw=(e,t,r)=>{const o=t&&typeof t===ku?(g,v)=>g===\"\"||-1<t.indexOf(g)?v:void 0:t||Vw,s=new Map,c=[],f=[];let d=+oy(s,c,o.call({\"\":e},\"\",e)),h=!d;for(;d<c.length;)h=!0,f[d]=jA(c[d++],p,r);return\"[\"+f.join(\",\")+\"]\";function p(g,v){if(h)return h=!h,v;const b=o.call(this,g,v);switch(typeof b){case ku:if(b===null)return b;case Uw:return s.get(b)||oy(s,c,b)}return b}},KA=e=>jw(Kw(e));class Xw{filesMap=new Map;pathsSet=new Set;idMap=new Map;getPaths(){return Array.from(this.pathsSet)}getFiles(t){return t?t.map(r=>this.filesMap.get(r)).flat().filter(r=>r&&!r.local):Array.from(this.filesMap.values()).flat().filter(r=>!r.local)}getFilepaths(){return Array.from(this.filesMap.keys())}getFailedFilepaths(){return this.getFiles().filter(t=>t.result?.state===\"fail\").map(t=>t.filepath)}collectPaths(t=[]){t.forEach(r=>{this.pathsSet.add(r)})}collectFiles(t=[]){t.forEach(r=>{const o=this.filesMap.get(r.filepath)||[],s=o.filter(f=>f.projectName!==r.projectName||f.meta.typecheck!==r.meta.typecheck),c=o.find(f=>f.projectName===r.projectName);c&&(r.logs=c.logs),s.push(r),this.filesMap.set(r.filepath,s),this.updateId(r)})}clearFiles(t,r=[]){const o=t;r.forEach(s=>{const c=this.filesMap.get(s),f=Bw(s,o.config.root,o.config.name||\"\");if(f.local=!0,this.idMap.set(f.id,f),!c){this.filesMap.set(s,[f]);return}const d=c.filter(h=>h.projectName!==o.config.name);d.length?this.filesMap.set(s,[...d,f]):this.filesMap.set(s,[f])})}updateId(t){this.idMap.get(t.id)!==t&&(this.idMap.set(t.id,t),t.type===\"suite\"&&t.tasks.forEach(r=>{this.updateId(r)}))}updateTasks(t){for(const[r,o,s]of t){const c=this.idMap.get(r);c&&(c.result=o,c.meta=s,o?.state===\"skip\"&&(c.mode=\"skip\"))}}updateUserLog(t){const r=t.taskId&&this.idMap.get(t.taskId);r&&(r.logs||(r.logs=[]),r.logs.push(t))}}function XA(e,t={}){const{handlers:r={},autoReconnect:o=!0,reconnectInterval:s=2e3,reconnectTries:c=10,connectTimeout:f=6e4,reactive:d=R=>R,WebSocketConstructor:h=globalThis.WebSocket}=t;let p=c;const g=d({ws:new h(e),state:new Xw,waitForConnection:M,reconnect:L},\"state\");g.state.filesMap=d(g.state.filesMap,\"filesMap\"),g.state.idMap=d(g.state.idMap,\"idMap\");let v;const b={onTestAnnotate(R,I){r.onTestAnnotate?.(R,I)},onTestArtifactRecord(R,I){r.onTestArtifactRecord?.(R,I)},onSpecsCollected(R,I){R?.forEach(([_,$])=>{g.state.clearFiles({config:_},[$])}),r.onSpecsCollected?.(R,I)},onPathsCollected(R){g.state.collectPaths(R),r.onPathsCollected?.(R)},onCollected(R){g.state.collectFiles(R),r.onCollected?.(R)},onTaskUpdate(R,I){g.state.updateTasks(R),r.onTaskUpdate?.(R,I)},onUserConsoleLog(R){g.state.updateUserLog(R),r.onUserConsoleLog?.(R)},onFinished(R,I,_,$){r.onFinished?.(R,I,_,$)},onFinishedReportCoverage(){r.onFinishedReportCoverage?.()}},w={post:R=>g.ws.send(R),on:R=>v=R,serialize:R=>Kw(R,(I,_)=>_ instanceof Error?{name:_.name,message:_.message,stack:_.stack}:_),deserialize:fh,timeout:-1};g.rpc=qA(b,w);let E;function L(R=!1){R&&(p=c),g.ws=new h(e),P()}function P(){E=new Promise((R,I)=>{const _=setTimeout(()=>{I(new Error(`Cannot connect to the server in ${f/1e3} seconds`))},f)?.unref?.();g.ws.OPEN===g.ws.readyState&&R(),g.ws.addEventListener(\"open\",()=>{p=c,R(),clearTimeout(_)})}),g.ws.addEventListener(\"message\",R=>{v(R.data)}),g.ws.addEventListener(\"close\",()=>{p-=1,o&&p>0&&setTimeout(L,s)})}P();function M(){return E}return g}const dh=Ft([]),Jn=Ft([]),Dr=sf(\"vitest-ui_task-tree-opened\",[],{shallow:!0}),Su=ke(()=>new Set(Dr.value)),gn=sf(\"vitest-ui_task-tree-filter\",{expandAll:void 0,failed:!1,success:!1,skipped:!1,onlyTests:!1,search:\"\"}),Vn=Ge(gn.value.search),YA={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\"};function Yw(e){return e.replace(/[&<>\"']/g,t=>YA[t])}const ZA=ke(()=>{const e=Vn.value.toLowerCase();return e.length?new RegExp(`(${Yw(e)})`,\"gi\"):null}),Zw=ke(()=>Vn.value.trim()!==\"\"),it=ir({failed:gn.value.failed,success:gn.value.success,skipped:gn.value.skipped,onlyTests:gn.value.onlyTests}),hh=ke(()=>!!(it.failed||it.success||it.skipped)),cf=Ft([]),Qs=Ge(!1),sy=ke(()=>{const e=gn.value.expandAll;return Dr.value.length>0?e!==!0:e!==!1}),JA=ke(()=>{const e=Zw.value,t=hh.value,r=it.onlyTests,o=Oe.summary.filesFailed,s=Oe.summary.filesSuccess,c=Oe.summary.filesSkipped,f=Oe.summary.filesRunning,d=cf.value;return Oe.collectTestsTotal(e||t,r,d,{failed:o,success:s,skipped:c,running:f})});function Ha(e){return Object.hasOwn(e,\"tasks\")}function QA(e,t){return typeof e!=\"string\"||typeof t!=\"string\"?!1:e.toLowerCase().includes(t.toLowerCase())}function Fo(e){return e>1e3?`${(e/1e3).toFixed(2)}s`:`${Math.round(e)}ms`}function Ed(e){return e>1e3?`${(e/1e3).toFixed(2)}s`:`${e.toFixed(2)}ms`}function eL(e){const t=new Map,r=new Map,o=[];for(;;){let s=0;if(e.forEach((c,f)=>{const{splits:d,finished:h}=c;if(h){s++;const{raw:g,candidate:v}=c;t.set(g,v);return}if(d.length===0){c.finished=!0;return}const p=d[0];r.has(p)?(c.candidate+=c.candidate===\"\"?p:`/${p}`,r.get(p)?.push(f),d.shift()):(r.set(p,[f]),o.push(f))}),o.forEach(c=>{const f=e[c],d=f.splits.shift();f.candidate+=f.candidate===\"\"?d:`/${d}`}),r.forEach(c=>{if(c.length===1){const f=c[0];e[f].finished=!0}}),r.clear(),o.length=0,s===e.length)break}return t}function Jw(e){let t=e;t.includes(\"/node_modules/\")&&(t=e.split(/\\/node_modules\\//g).pop());const r=t.split(/\\//g);return{raw:t,splits:r,candidate:\"\",finished:!1,id:e}}function tL(e){return Jw(e).raw}function Xc(e){if(e>=500)return\"danger\";if(e>=100)return\"warning\"}function _u(e){const t=Xc(e);if(t===\"danger\")return\"text-red\";if(t===\"warning\")return\"text-orange\"}function Qw(e){if(!e)return\"\";const t=e.split(\"\").reduce((o,s,c)=>o+s.charCodeAt(0)+c,0),r=[\"yellow\",\"cyan\",\"green\",\"magenta\"];return r[t%r.length]}function ex(e){switch(e){case\"blue\":case\"green\":case\"magenta\":case\"black\":case\"red\":return\"white\";case\"yellow\":case\"cyan\":case\"white\":default:return\"black\"}}function nL(e){return e.type===\"test\"}function rL(e){return e.mode===\"run\"&&e.type===\"test\"}function In(e){return e.type===\"file\"}function Ci(e){return e.type===\"file\"||e.type===\"suite\"}function iL(e=Oe.root.tasks){return e.sort((t,r)=>`${t.filepath}:${t.projectName}`.localeCompare(`${r.filepath}:${r.projectName}`))}function Sa(e,t=!1){let r=Oe.nodes.get(e.id);if(r?(r.typecheck=!!e.meta&&\"typecheck\"in e.meta,r.state=e.result?.state,r.mode=e.mode,r.duration=typeof e.result?.duration==\"number\"?Math.round(e.result.duration):void 0,r.collectDuration=e.collectDuration,r.setupDuration=e.setupDuration,r.environmentLoad=e.environmentLoad,r.prepareDuration=e.prepareDuration):(r={id:e.id,parentId:\"root\",name:e.name,mode:e.mode,expandable:!0,expanded:Su.value.size>0&&Su.value.has(e.id),type:\"file\",children:new Set,tasks:[],typecheck:!!e.meta&&\"typecheck\"in e.meta,indent:0,duration:typeof e.result?.duration==\"number\"?Math.round(e.result.duration):void 0,filepath:e.filepath,projectName:e.projectName||\"\",projectNameColor:Oe.colors.get(e.projectName||\"\")||Qw(e.projectName),collectDuration:e.collectDuration,setupDuration:e.setupDuration,environmentLoad:e.environmentLoad,prepareDuration:e.prepareDuration,state:e.result?.state},Oe.nodes.set(e.id,r),Oe.root.tasks.push(r)),t)for(let o=0;o<e.tasks.length;o++)Ba(e.id,e.tasks[o],!0)}function tx(e,t){const r=Oe.nodes.get(e);if(!r||!Ci(r))return;const o=ft.state.idMap.get(e);if(!(!o||!Ha(o)))return Ba(r.parentId,o,t&&o.tasks.length>0),[r,o]}function oL(e){const t=Oe.nodes.get(e);if(!t)return;const r=ft.state.idMap.get(e);!r||!Js(r)||Ba(t.parentId,r,!1)}function Ba(e,t,r){const o=Oe.nodes.get(e);let s;const c=typeof t.result?.duration==\"number\"?Math.round(t.result.duration):void 0;if(o&&(s=Oe.nodes.get(t.id),s?(o.children.has(t.id)||(o.tasks.push(s),o.children.add(t.id)),s.name=t.name,s.mode=t.mode,s.duration=c,s.state=t.result?.state):(Js(t)?s={id:t.id,fileId:t.file.id,parentId:e,name:t.name,mode:t.mode,type:t.type,expandable:!1,expanded:!1,indent:o.indent+1,duration:c,state:t.result?.state}:s={id:t.id,fileId:t.file.id,parentId:e,name:t.name,mode:t.mode,type:\"suite\",expandable:!0,expanded:Su.value.size>0&&Su.value.has(t.id),children:new Set,tasks:[],indent:o.indent+1,duration:c,state:t.result?.state},Oe.nodes.set(t.id,s),o.tasks.push(s),o.children.add(t.id)),s&&r&&Ha(t)))for(let f=0;f<t.tasks.length;f++)Ba(s.id,t.tasks[f],r)}function sL(e){const t=Oe.nodes.get(e);if(!t||!Ci(t))return;const r=new Set(Dr.value);r.delete(t.id);const o=[...aL(t)];Dr.value=Array.from(r),Jn.value=o}function lL(){ph(Oe.root.tasks);const e=[...Jn.value.filter(In)];ph(e),Dr.value=[],gn.value.expandAll=!0,Jn.value=e}function ph(e){for(const t of e)Ci(t)&&(t.expanded=!1,ph(t.tasks))}function*nx(e,t){if(t&&(yield e.id),Ci(e))for(let r=0;r<e.tasks.length;r++)yield*nx(e.tasks[r],!0)}function*aL(e){const t=e.id,r=new Set(nx(e,!1));for(let o=0;o<Jn.value.length;o++){const s=Jn.value[o];if(s.id===t){s.expanded=!1,yield s;continue}if(r.has(s.id)){r.delete(s.id);continue}yield s}}const uf=Ge(\"idle\"),Ms=ke(()=>uf.value===\"idle\"),eo=Ge([]);function cL(e,t,r){return e?ox(e,t,r):!1}function mp(e,t){const r=[...rx(e,t)];Jn.value=r,cf.value=r.filter(In).map(o=>mr(o.id))}function*rx(e,t){for(const r of iL())yield*ix(r,e,t)}function*ix(e,t,r){const o=new Set,s=new Map,c=[];let f;if(r.onlyTests)for(const[v,b]of gh(e,o,w=>ly(w,t,r)))c.push([v,b]);else{for(const[v,b]of gh(e,o,w=>ly(w,t,r)))Ci(b)?(s.set(b.id,v),In(b)?(v&&(f=b.id),c.push([v,b])):c.push([v||s.get(b.parentId)===!0,b])):c.push([v||s.get(b.parentId)===!0,b]);!f&&!In(e)&&\"fileId\"in e&&(f=e.fileId)}const d=new Set,h=[...fL(c,r.onlyTests,o,d,f)].reverse(),p=Oe.nodes,g=new Set(h.filter(v=>In(v)||Ci(v)&&p.get(v.parentId)?.expanded).map(v=>v.id));yield*h.filter(v=>In(v)||g.has(v.parentId)&&p.get(v.parentId)?.expanded)}function uL(e,t,r,o,s){if(o){if(In(t))return s.has(t.id)?t:void 0;if(r.has(t.id)){const c=Oe.nodes.get(t.parentId);return c&&In(c)&&s.add(c.id),t}}else if(e||r.has(t.id)||s.has(t.id)){const c=Oe.nodes.get(t.parentId);return c&&In(c)&&s.add(c.id),t}}function*fL(e,t,r,o,s){for(let c=e.length-1;c>=0;c--){const[f,d]=e[c],h=Ci(d);if(!t&&s&&r.has(s)&&\"fileId\"in d&&d.fileId===s){h&&r.add(d.id);let p=Oe.nodes.get(d.parentId);for(;p;)r.add(p.id),In(p)&&o.add(p.id),p=Oe.nodes.get(p.parentId);yield d;continue}if(h){const p=uL(f,d,r,t,o);p&&(yield p)}else if(f){const p=Oe.nodes.get(d.parentId);p&&In(p)&&o.add(p.id),yield d}}}function dL(e,t){return(t.success||t.failed)&&\"result\"in e&&(t.success&&e.result?.state===\"pass\"||t.failed&&e.result?.state===\"fail\")?!0:t.skipped&&\"mode\"in e?e.mode===\"skip\"||e.mode===\"todo\":!1}function ox(e,t,r){if(t.length===0||QA(e.name,t))if(r.success||r.failed||r.skipped){if(dL(e,r))return!0}else return!0;return!1}function*gh(e,t,r){const o=r(e);if(o)if(nL(e)){let s=Oe.nodes.get(e.parentId);for(;s;)t.add(s.id),s=Oe.nodes.get(s.parentId)}else if(In(e))t.add(e.id);else{t.add(e.id);let s=Oe.nodes.get(e.parentId);for(;s;)t.add(s.id),s=Oe.nodes.get(s.parentId)}if(yield[o,e],Ci(e))for(let s=0;s<e.tasks.length;s++)yield*gh(e.tasks[s],t,r)}function ly(e,t,r){const o=ft.state.idMap.get(e.id);return o?ox(o,t,r):!1}function hL(e,t,r){const o=tx(e,!1);if(!o)return;const[s,c]=o;for(const p of c.tasks)Ba(s.id,p,!1);s.expanded=!0;const f=new Set(Dr.value);f.add(s.id);const d=new Set(ix(s,t,r)),h=[...mL(s,d)];Dr.value=Array.from(f),Jn.value=h}function pL(e,t){vp(Oe.root.tasks,!1);const r=[...rx(e,t)];gn.value.expandAll=!1,Dr.value=[],Jn.value=r,cf.value=r.filter(In).map(o=>mr(o.id))}function gL(e,t){if(e.size)for(const r of Jn.value)e.has(r.id)&&(r.expanded=!0);else t&&vp(Jn.value.filter(In),!0)}function vp(e,t){for(const r of e)Ci(r)&&(r.expanded=!0,vp(r.tasks,!1));t&&(gn.value.expandAll=!1,Dr.value=[])}function*mL(e,t){const r=e.id,o=new Set(Array.from(t).map(s=>s.id));for(const s of Jn.value)s.id===r?(s.expanded=!0,o.has(s.id)||(yield e),yield*t):o.has(s.id)||(yield s)}function yp(e){return Ww(e).some(t=>t.result?.errors?.some(r=>typeof r?.message==\"string\"&&r.message.match(/Snapshot .* mismatched/)))}function vL(e,t,r,o){e.map(s=>[`${s.filepath}:${s.projectName||\"\"}`,s]).sort(([s],[c])=>s.localeCompare(c)).map(([,s])=>Sa(s,t)),dh.value=[...Oe.root.tasks],mp(r.trim(),{failed:o.failed,success:o.success,skipped:o.skipped,onlyTests:o.onlyTests})}function yL(e){queueMicrotask(()=>{const t=Oe.pendingTasks,r=ft.state.idMap;for(const o of e)if(o[1]){const c=r.get(o[0]);if(c){let f=t.get(c.file.id);f||(f=new Set,t.set(c.file.id,f)),f.add(c.id)}}})}function bL(e,t){const r=Oe.pendingTasks,s=ft.state.idMap.get(e);if(s?.type===\"test\"){let c=r.get(s.file.id);c||(c=new Set,r.set(s.file.id,c)),c.add(s.id),t.type===\"internal:annotation\"?s.annotations.push(t.annotation):s.artifacts.push(t)}}function ay(e,t,r,o,s,c){e&&TL(r);const f=!e;queueMicrotask(()=>{t?kL(f):SL(f)}),queueMicrotask(()=>{CL(r,c)}),queueMicrotask(()=>{t&&(r.failedSnapshot=dh.value&&yp(dh.value.map(d=>mr(d.id))),r.failedSnapshotEnabled=!0)}),queueMicrotask(()=>{_L(o,s,t)})}function*wL(){yield*Jn.value.filter(rL)}function xL(){const e=ft.state.idMap;let t;for(const r of wL())t=e.get(r.parentId),t&&Ha(t)&&t.mode===\"todo\"&&(t=e.get(r.id),t&&(t.mode=\"todo\"))}function kL(e){const t=ft.state.getFiles(),r=Oe.nodes,o=t.filter(c=>!r.has(c.id));for(let c=0;c<o.length;c++)Sa(o[c],e),Tu(o[c].tasks);const s=Oe.root.tasks;for(let c=0;c<s.length;c++){const f=s[c],d=mr(f.id);!d||(Sa(d,e),!d.tasks?.length)||Tu(d.tasks)}}function SL(e){const t=new Map(Oe.pendingTasks.entries());Oe.pendingTasks.clear();const r=Oe.nodes,o=Array.from(t.keys()).filter(d=>!r.has(d)).map(d=>mr(d)).filter(Boolean);let s;for(let d=0;d<o.length;d++)s=o[d],Sa(s,!1),Tu(s.tasks),t.delete(s.id);const c=ft.state.idMap,f=Oe.root.tasks;for(let d=0;d<f.length;d++){const h=f[d],p=mr(h.id);if(!p)continue;const g=t.get(p.id);g&&(Sa(p,e),Tu(Array.from(g,v=>c.get(v)).filter(Boolean)))}}function _L(e,t,r=!1){const o=gn.value.expandAll,s=o!==!0,c=new Set(Dr.value),f=c.size>0&&o===!1||s;queueMicrotask(()=>{cy(e,t,r)}),Qs.value||queueMicrotask(()=>{(Jn.value.length||r)&&(Qs.value=!0)}),f&&(queueMicrotask(()=>{gL(c,r),s&&(gn.value.expandAll=!1)}),queueMicrotask(()=>{cy(e,t,r)}))}function cy(e,t,r){mp(e,t),r&&(xL(),uf.value=\"idle\")}function Tu(e){let t;for(let r=0;r<e.length;r++)t=e[r],Ha(t)?tx(t.id,!0):oL(t.id)}function TL(e){e.files=0,e.time=\"\",e.filesFailed=0,e.filesSuccess=0,e.filesIgnore=0,e.filesRunning=0,e.filesSkipped=0,e.filesTodo=0,e.testsFailed=0,e.testsSuccess=0,e.testsIgnore=0,e.testsSkipped=0,e.testsTodo=0,e.totalTests=0,e.failedSnapshotEnabled=!1}function CL(e,t){const r=ft.state.idMap,o=new Map(Oe.root.tasks.filter(f=>r.has(f.id)).map(f=>[f.id,f])),s=Array.from(o.values(),f=>[f.id,mr(f.id)]),c={files:o.size,time:t>1e3?`${(t/1e3).toFixed(2)}s`:`${Math.round(t)}ms`,filesFailed:0,filesSuccess:0,filesIgnore:0,filesRunning:0,filesSkipped:0,filesTodo:0,testsFailed:0,testsSuccess:0,testsIgnore:0,testsSkipped:0,testsTodo:0,totalTests:0};for(const[f,d]of s){if(!d)continue;d.result?.state===\"fail\"?c.filesFailed++:d.result?.state===\"pass\"?c.filesSuccess++:d.mode===\"skip\"?(c.filesIgnore++,c.filesSkipped++):d.mode===\"todo\"?(c.filesIgnore++,c.filesTodo++):c.filesRunning++;const{failed:h,success:p,skipped:g,total:v,ignored:b,todo:w}=sx(d);c.totalTests+=v,c.testsFailed+=h,c.testsSuccess+=p,c.testsSkipped+=g,c.testsTodo+=w,c.testsIgnore+=b}e.files=c.files,e.time=c.time,e.filesFailed=c.filesFailed,e.filesSuccess=c.filesSuccess,e.filesIgnore=c.filesIgnore,e.filesRunning=c.filesRunning,e.filesSkipped=c.filesSkipped,e.filesTodo=c.filesTodo,e.testsFailed=c.testsFailed,e.testsSuccess=c.testsSuccess,e.testsFailed=c.testsFailed,e.testsTodo=c.testsTodo,e.testsIgnore=c.testsIgnore,e.testsSkipped=c.testsSkipped,e.totalTests=c.totalTests}function sx(e,t=\"\",r){const o={failed:0,success:0,skipped:0,running:0,total:0,ignored:0,todo:0};for(const s of lx(e))(!r||cL(s,t,r))&&(o.total++,s.result?.state===\"fail\"?o.failed++:s.result?.state===\"pass\"?o.success++:s.mode===\"skip\"?(o.ignored++,o.skipped++):s.mode===\"todo\"&&(o.ignored++,o.todo++));return o.running=o.total-o.failed-o.success-o.ignored,o}function EL(e,t,r,o,s,c){if(t)return r.map(f=>sx(f,s,c)).reduce((f,{failed:d,success:h,ignored:p,running:g})=>(f.failed+=d,f.success+=h,f.skipped+=p,f.running+=g,f),{failed:0,success:0,skipped:0,running:0});if(e){const f={failed:0,success:0,skipped:0,running:0},d=!c.success&&!c.failed,h=c.failed||d,p=c.success||d;for(const g of r)g.result?.state===\"fail\"?f.failed+=h?1:0:g.result?.state===\"pass\"?f.success+=p?1:0:g.mode===\"skip\"||g.mode===\"todo\"||f.running++;return f}return o}function*lx(e){const t=pp(e);let r;for(let o=0;o<t.length;o++)r=t[o],Js(r)?yield r:yield*lx(r.tasks)}class AL{constructor(t=[],r=new Map,o=!1,s=500,c={id:\"vitest-root-node\",expandable:!0,expanded:!0,tasks:[]},f=new Map,d=new Map,h=ir({files:0,time:\"\",filesFailed:0,filesSuccess:0,filesIgnore:0,filesRunning:0,filesSkipped:0,filesSnapshotFailed:0,filesTodo:0,testsFailed:0,testsSuccess:0,testsIgnore:0,testsSkipped:0,testsTodo:0,totalTests:0,failedSnapshot:!1,failedSnapshotEnabled:!1})){this.projects=t,this.colors=r,this.onTaskUpdateCalled=o,this.resumeEndTimeout=s,this.root=c,this.pendingTasks=f,this.nodes=d,this.summary=h,this.rafCollector=AE(this.runCollect.bind(this),{fpsLimit:10,immediate:!1})}rafCollector;resumeEndRunId;startTime=0;executionTime=0;loadFiles(t,r){this.projects.splice(0,this.projects.length,...r.map(o=>o.name)),this.colors=new Map(r.map(o=>[o.name,o.color])),vL(t,!0,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})}startRun(){this.startTime=performance.now(),this.resumeEndRunId=setTimeout(()=>this.endRun(),this.resumeEndTimeout),this.collect(!0,!1)}recordTestArtifact(t,r){bL(t,r),this.onTaskUpdateCalled||(clearTimeout(this.resumeEndRunId),this.onTaskUpdateCalled=!0,this.collect(!0,!1,!1),this.rafCollector.resume())}resumeRun(t,r){yL(t),this.onTaskUpdateCalled||(clearTimeout(this.resumeEndRunId),this.onTaskUpdateCalled=!0,this.collect(!0,!1,!1),this.rafCollector.resume())}endRun(t=performance.now()-this.startTime){this.executionTime=t,this.rafCollector.pause(),this.onTaskUpdateCalled=!1,this.collect(!1,!0)}runCollect(){this.collect(!1,!1)}collect(t,r,o=!0){o?queueMicrotask(()=>{ay(t,r,this.summary,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests},r?this.executionTime:performance.now()-this.startTime)}):ay(t,r,this.summary,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests},r?this.executionTime:performance.now()-this.startTime)}collectTestsTotal(t,r,o,s){return EL(t,r,o,s,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})}collapseNode(t){queueMicrotask(()=>{sL(t)})}expandNode(t){queueMicrotask(()=>{hL(t,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})})}collapseAllNodes(){queueMicrotask(()=>{lL()})}expandAllNodes(){queueMicrotask(()=>{pL(Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})})}filterNodes(){queueMicrotask(()=>{mp(Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})})}}const Oe=new AL;function ax(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,\"default\")?e.default:e}var Yc={exports:{}},LL=Yc.exports,uy;function vo(){return uy||(uy=1,(function(e,t){(function(r,o){e.exports=o()})(LL,(function(){var r=navigator.userAgent,o=navigator.platform,s=/gecko\\/\\d/i.test(r),c=/MSIE \\d/.test(r),f=/Trident\\/(?:[7-9]|\\d{2,})\\..*rv:(\\d+)/.exec(r),d=/Edge\\/(\\d+)/.exec(r),h=c||f||d,p=h&&(c?document.documentMode||6:+(d||f)[1]),g=!d&&/WebKit\\//.test(r),v=g&&/Qt\\/\\d+\\.\\d+/.test(r),b=!d&&/Chrome\\/(\\d+)/.exec(r),w=b&&+b[1],E=/Opera\\//.test(r),L=/Apple Computer/.test(navigator.vendor),P=/Mac OS X 1\\d\\D([8-9]|\\d\\d)\\D/.test(r),M=/PhantomJS/.test(r),R=L&&(/Mobile\\/\\w+/.test(r)||navigator.maxTouchPoints>2),I=/Android/.test(r),_=R||I||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(r),$=R||/Mac/.test(o),W=/\\bCrOS\\b/.test(r),ne=/win/i.test(o),ee=E&&r.match(/Version\\/(\\d*\\.\\d*)/);ee&&(ee=Number(ee[1])),ee&&ee>=15&&(E=!1,g=!0);var Z=$&&(v||E&&(ee==null||ee<12.11)),G=s||h&&p>=9;function j(n){return new RegExp(\"(^|\\\\s)\"+n+\"(?:$|\\\\s)\\\\s*\")}var N=function(n,i){var a=n.className,l=j(i).exec(a);if(l){var u=a.slice(l.index+l[0].length);n.className=a.slice(0,l.index)+(u?l[1]+u:\"\")}};function O(n){for(var i=n.childNodes.length;i>0;--i)n.removeChild(n.firstChild);return n}function C(n,i){return O(n).appendChild(i)}function k(n,i,a,l){var u=document.createElement(n);if(a&&(u.className=a),l&&(u.style.cssText=l),typeof i==\"string\")u.appendChild(document.createTextNode(i));else if(i)for(var m=0;m<i.length;++m)u.appendChild(i[m]);return u}function z(n,i,a,l){var u=k(n,i,a,l);return u.setAttribute(\"role\",\"presentation\"),u}var B;document.createRange?B=function(n,i,a,l){var u=document.createRange();return u.setEnd(l||n,a),u.setStart(n,i),u}:B=function(n,i,a){var l=document.body.createTextRange();try{l.moveToElementText(n.parentNode)}catch{return l}return l.collapse(!0),l.moveEnd(\"character\",a),l.moveStart(\"character\",i),l};function ce(n,i){if(i.nodeType==3&&(i=i.parentNode),n.contains)return n.contains(i);do if(i.nodeType==11&&(i=i.host),i==n)return!0;while(i=i.parentNode)}function be(n){var i=n.ownerDocument||n,a;try{a=n.activeElement}catch{a=i.body||null}for(;a&&a.shadowRoot&&a.shadowRoot.activeElement;)a=a.shadowRoot.activeElement;return a}function Se(n,i){var a=n.className;j(i).test(a)||(n.className+=(a?\" \":\"\")+i)}function Be(n,i){for(var a=n.split(\" \"),l=0;l<a.length;l++)a[l]&&!j(a[l]).test(i)&&(i+=\" \"+a[l]);return i}var Ae=function(n){n.select()};R?Ae=function(n){n.selectionStart=0,n.selectionEnd=n.value.length}:h&&(Ae=function(n){try{n.select()}catch{}});function Ke(n){return n.display.wrapper.ownerDocument}function je(n){return Fe(n.display.wrapper)}function Fe(n){return n.getRootNode?n.getRootNode():n.ownerDocument}function Pe(n){return Ke(n).defaultView}function F(n){var i=Array.prototype.slice.call(arguments,1);return function(){return n.apply(null,i)}}function Y(n,i,a){i||(i={});for(var l in n)n.hasOwnProperty(l)&&(a!==!1||!i.hasOwnProperty(l))&&(i[l]=n[l]);return i}function re(n,i,a,l,u){i==null&&(i=n.search(/[^\\s\\u00a0]/),i==-1&&(i=n.length));for(var m=l||0,y=u||0;;){var x=n.indexOf(\"\t\",m);if(x<0||x>=i)return y+(i-m);y+=x-m,y+=a-y%a,m=x+1}}var le=function(){this.id=null,this.f=null,this.time=0,this.handler=F(this.onTimeout,this)};le.prototype.onTimeout=function(n){n.id=0,n.time<=+new Date?n.f():setTimeout(n.handler,n.time-+new Date)},le.prototype.set=function(n,i){this.f=i;var a=+new Date+n;(!this.id||a<this.time)&&(clearTimeout(this.id),this.id=setTimeout(this.handler,n),this.time=a)};function ae(n,i){for(var a=0;a<n.length;++a)if(n[a]==i)return a;return-1}var D=50,q={toString:function(){return\"CodeMirror.Pass\"}},Q={scroll:!1},he={origin:\"*mouse\"},de={origin:\"+move\"};function ge(n,i,a){for(var l=0,u=0;;){var m=n.indexOf(\"\t\",l);m==-1&&(m=n.length);var y=m-l;if(m==n.length||u+y>=i)return l+Math.min(y,i-u);if(u+=m-l,u+=a-u%a,l=m+1,u>=i)return l}}var Ce=[\"\"];function Ee(n){for(;Ce.length<=n;)Ce.push(xe(Ce)+\" \");return Ce[n]}function xe(n){return n[n.length-1]}function ye(n,i){for(var a=[],l=0;l<n.length;l++)a[l]=i(n[l],l);return a}function J(n,i,a){for(var l=0,u=a(i);l<n.length&&a(n[l])<=u;)l++;n.splice(l,0,i)}function ue(){}function oe(n,i){var a;return Object.create?a=Object.create(n):(ue.prototype=n,a=new ue),i&&Y(i,a),a}var $e=/[\\u00df\\u0587\\u0590-\\u05f4\\u0600-\\u06ff\\u3040-\\u309f\\u30a0-\\u30ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\uac00-\\ud7af]/;function Je(n){return/\\w/.test(n)||n>\"\"&&(n.toUpperCase()!=n.toLowerCase()||$e.test(n))}function ct(n,i){return i?i.source.indexOf(\"\\\\w\")>-1&&Je(n)?!0:i.test(n):Je(n)}function dt(n){for(var i in n)if(n.hasOwnProperty(i)&&n[i])return!1;return!0}var Nt=/[\\u0300-\\u036f\\u0483-\\u0489\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u064b-\\u065e\\u0670\\u06d6-\\u06dc\\u06de-\\u06e4\\u06e7\\u06e8\\u06ea-\\u06ed\\u0711\\u0730-\\u074a\\u07a6-\\u07b0\\u07eb-\\u07f3\\u0816-\\u0819\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0900-\\u0902\\u093c\\u0941-\\u0948\\u094d\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09bc\\u09be\\u09c1-\\u09c4\\u09cd\\u09d7\\u09e2\\u09e3\\u0a01\\u0a02\\u0a3c\\u0a41\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a70\\u0a71\\u0a75\\u0a81\\u0a82\\u0abc\\u0ac1-\\u0ac5\\u0ac7\\u0ac8\\u0acd\\u0ae2\\u0ae3\\u0b01\\u0b3c\\u0b3e\\u0b3f\\u0b41-\\u0b44\\u0b4d\\u0b56\\u0b57\\u0b62\\u0b63\\u0b82\\u0bbe\\u0bc0\\u0bcd\\u0bd7\\u0c3e-\\u0c40\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62\\u0c63\\u0cbc\\u0cbf\\u0cc2\\u0cc6\\u0ccc\\u0ccd\\u0cd5\\u0cd6\\u0ce2\\u0ce3\\u0d3e\\u0d41-\\u0d44\\u0d4d\\u0d57\\u0d62\\u0d63\\u0dca\\u0dcf\\u0dd2-\\u0dd4\\u0dd6\\u0ddf\\u0e31\\u0e34-\\u0e3a\\u0e47-\\u0e4e\\u0eb1\\u0eb4-\\u0eb9\\u0ebb\\u0ebc\\u0ec8-\\u0ecd\\u0f18\\u0f19\\u0f35\\u0f37\\u0f39\\u0f71-\\u0f7e\\u0f80-\\u0f84\\u0f86\\u0f87\\u0f90-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u102d-\\u1030\\u1032-\\u1037\\u1039\\u103a\\u103d\\u103e\\u1058\\u1059\\u105e-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108d\\u109d\\u135f\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17b7-\\u17bd\\u17c6\\u17c9-\\u17d3\\u17dd\\u180b-\\u180d\\u18a9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193b\\u1a17\\u1a18\\u1a56\\u1a58-\\u1a5e\\u1a60\\u1a62\\u1a65-\\u1a6c\\u1a73-\\u1a7c\\u1a7f\\u1b00-\\u1b03\\u1b34\\u1b36-\\u1b3a\\u1b3c\\u1b42\\u1b6b-\\u1b73\\u1b80\\u1b81\\u1ba2-\\u1ba5\\u1ba8\\u1ba9\\u1c2c-\\u1c33\\u1c36\\u1c37\\u1cd0-\\u1cd2\\u1cd4-\\u1ce0\\u1ce2-\\u1ce8\\u1ced\\u1dc0-\\u1de6\\u1dfd-\\u1dff\\u200c\\u200d\\u20d0-\\u20f0\\u2cef-\\u2cf1\\u2de0-\\u2dff\\u302a-\\u302f\\u3099\\u309a\\ua66f-\\ua672\\ua67c\\ua67d\\ua6f0\\ua6f1\\ua802\\ua806\\ua80b\\ua825\\ua826\\ua8c4\\ua8e0-\\ua8f1\\ua926-\\ua92d\\ua947-\\ua951\\ua980-\\ua982\\ua9b3\\ua9b6-\\ua9b9\\ua9bc\\uaa29-\\uaa2e\\uaa31\\uaa32\\uaa35\\uaa36\\uaa43\\uaa4c\\uaab0\\uaab2-\\uaab4\\uaab7\\uaab8\\uaabe\\uaabf\\uaac1\\uabe5\\uabe8\\uabed\\udc00-\\udfff\\ufb1e\\ufe00-\\ufe0f\\ufe20-\\ufe26\\uff9e\\uff9f]/;function ut(n){return n.charCodeAt(0)>=768&&Nt.test(n)}function Yt(n,i,a){for(;(a<0?i>0:i<n.length)&&ut(n.charAt(i));)i+=a;return i}function jt(n,i,a){for(var l=i>a?-1:1;;){if(i==a)return i;var u=(i+a)/2,m=l<0?Math.ceil(u):Math.floor(u);if(m==i)return n(m)?i:a;n(m)?a=m:i=m+l}}function Fn(n,i,a,l){if(!n)return l(i,a,\"ltr\",0);for(var u=!1,m=0;m<n.length;++m){var y=n[m];(y.from<a&&y.to>i||i==a&&y.to==i)&&(l(Math.max(y.from,i),Math.min(y.to,a),y.level==1?\"rtl\":\"ltr\",m),u=!0)}u||l(i,a,\"ltr\")}var Hr=null;function Bt(n,i,a){var l;Hr=null;for(var u=0;u<n.length;++u){var m=n[u];if(m.from<i&&m.to>i)return u;m.to==i&&(m.from!=m.to&&a==\"before\"?l=u:Hr=u),m.from==i&&(m.from!=m.to&&a!=\"before\"?l=u:Hr=u)}return l??Hr}var Hn=(function(){var n=\"bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN\",i=\"nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111\";function a(T){return T<=247?n.charAt(T):1424<=T&&T<=1524?\"R\":1536<=T&&T<=1785?i.charAt(T-1536):1774<=T&&T<=2220?\"r\":8192<=T&&T<=8203?\"w\":T==8204?\"b\":\"L\"}var l=/[\\u0590-\\u05f4\\u0600-\\u06ff\\u0700-\\u08ac]/,u=/[stwN]/,m=/[LRr]/,y=/[Lb1n]/,x=/[1n]/;function S(T,H,V){this.level=T,this.from=H,this.to=V}return function(T,H){var V=H==\"ltr\"?\"L\":\"R\";if(T.length==0||H==\"ltr\"&&!l.test(T))return!1;for(var se=T.length,te=[],pe=0;pe<se;++pe)te.push(a(T.charCodeAt(pe)));for(var we=0,Te=V;we<se;++we){var Le=te[we];Le==\"m\"?te[we]=Te:Te=Le}for(var De=0,Me=V;De<se;++De){var ze=te[De];ze==\"1\"&&Me==\"r\"?te[De]=\"n\":m.test(ze)&&(Me=ze,ze==\"r\"&&(te[De]=\"R\"))}for(var Ye=1,Ue=te[0];Ye<se-1;++Ye){var st=te[Ye];st==\"+\"&&Ue==\"1\"&&te[Ye+1]==\"1\"?te[Ye]=\"1\":st==\",\"&&Ue==te[Ye+1]&&(Ue==\"1\"||Ue==\"n\")&&(te[Ye]=Ue),Ue=st}for(var St=0;St<se;++St){var tn=te[St];if(tn==\",\")te[St]=\"N\";else if(tn==\"%\"){var Ot=void 0;for(Ot=St+1;Ot<se&&te[Ot]==\"%\";++Ot);for(var qn=St&&te[St-1]==\"!\"||Ot<se&&te[Ot]==\"1\"?\"1\":\"N\",Cn=St;Cn<Ot;++Cn)te[Cn]=qn;St=Ot-1}}for(var Ut=0,En=V;Ut<se;++Ut){var sn=te[Ut];En==\"L\"&&sn==\"1\"?te[Ut]=\"L\":m.test(sn)&&(En=sn)}for(var Kt=0;Kt<se;++Kt)if(u.test(te[Kt])){var Vt=void 0;for(Vt=Kt+1;Vt<se&&u.test(te[Vt]);++Vt);for(var It=(Kt?te[Kt-1]:V)==\"L\",An=(Vt<se?te[Vt]:V)==\"L\",ks=It==An?It?\"L\":\"R\":V,ji=Kt;ji<Vt;++ji)te[ji]=ks;Kt=Vt-1}for(var fn=[],Ur,nn=0;nn<se;)if(y.test(te[nn])){var cd=nn;for(++nn;nn<se&&y.test(te[nn]);++nn);fn.push(new S(0,cd,nn))}else{var ui=nn,Ao=fn.length,Lo=H==\"rtl\"?1:0;for(++nn;nn<se&&te[nn]!=\"L\";++nn);for(var yn=ui;yn<nn;)if(x.test(te[yn])){ui<yn&&(fn.splice(Ao,0,new S(1,ui,yn)),Ao+=Lo);var Ss=yn;for(++yn;yn<nn&&x.test(te[yn]);++yn);fn.splice(Ao,0,new S(2,Ss,yn)),Ao+=Lo,ui=yn}else++yn;ui<nn&&fn.splice(Ao,0,new S(1,ui,nn))}return H==\"ltr\"&&(fn[0].level==1&&(Ur=T.match(/^\\s+/))&&(fn[0].from=Ur[0].length,fn.unshift(new S(0,0,Ur[0].length))),xe(fn).level==1&&(Ur=T.match(/\\s+$/))&&(xe(fn).to-=Ur[0].length,fn.push(new S(0,se-Ur[0].length,se)))),H==\"rtl\"?fn.reverse():fn}})();function lt(n,i){var a=n.order;return a==null&&(a=n.order=Hn(n.text,i)),a}var yo=[],Xe=function(n,i,a){if(n.addEventListener)n.addEventListener(i,a,!1);else if(n.attachEvent)n.attachEvent(\"on\"+i,a);else{var l=n._handlers||(n._handlers={});l[i]=(l[i]||yo).concat(a)}};function ri(n,i){return n._handlers&&n._handlers[i]||yo}function an(n,i,a){if(n.removeEventListener)n.removeEventListener(i,a,!1);else if(n.detachEvent)n.detachEvent(\"on\"+i,a);else{var l=n._handlers,u=l&&l[i];if(u){var m=ae(u,a);m>-1&&(l[i]=u.slice(0,m).concat(u.slice(m+1)))}}}function Pt(n,i){var a=ri(n,i);if(a.length)for(var l=Array.prototype.slice.call(arguments,2),u=0;u<a.length;++u)a[u].apply(null,l)}function Rt(n,i,a){return typeof i==\"string\"&&(i={type:i,preventDefault:function(){this.defaultPrevented=!0}}),Pt(n,a||i.type,n,i),kn(i)||i.codemirrorIgnore}function ar(n){var i=n._handlers&&n._handlers.cursorActivity;if(i)for(var a=n.curOp.cursorActivityHandlers||(n.curOp.cursorActivityHandlers=[]),l=0;l<i.length;++l)ae(a,i[l])==-1&&a.push(i[l])}function Bn(n,i){return ri(n,i).length>0}function yr(n){n.prototype.on=function(i,a){Xe(this,i,a)},n.prototype.off=function(i,a){an(this,i,a)}}function cn(n){n.preventDefault?n.preventDefault():n.returnValue=!1}function Zo(n){n.stopPropagation?n.stopPropagation():n.cancelBubble=!0}function kn(n){return n.defaultPrevented!=null?n.defaultPrevented:n.returnValue==!1}function Oi(n){cn(n),Zo(n)}function sl(n){return n.target||n.srcElement}function br(n){var i=n.which;return i==null&&(n.button&1?i=1:n.button&2?i=3:n.button&4&&(i=2)),$&&n.ctrlKey&&i==1&&(i=3),i}var mf=(function(){if(h&&p<9)return!1;var n=k(\"div\");return\"draggable\"in n||\"dragDrop\"in n})(),Jo;function Ga(n){if(Jo==null){var i=k(\"span\",\"​\");C(n,k(\"span\",[i,document.createTextNode(\"x\")])),n.firstChild.offsetHeight!=0&&(Jo=i.offsetWidth<=1&&i.offsetHeight>2&&!(h&&p<8))}var a=Jo?k(\"span\",\"​\"):k(\"span\",\" \",null,\"display: inline-block; width: 1px; margin-right: -1px\");return a.setAttribute(\"cm-text\",\"\"),a}var ll;function Pi(n){if(ll!=null)return ll;var i=C(n,document.createTextNode(\"AخA\")),a=B(i,0,1).getBoundingClientRect(),l=B(i,1,2).getBoundingClientRect();return O(n),!a||a.left==a.right?!1:ll=l.right-a.right<3}var cr=`\n\nb`.split(/\\n/).length!=3?function(n){for(var i=0,a=[],l=n.length;i<=l;){var u=n.indexOf(`\n`,i);u==-1&&(u=n.length);var m=n.slice(i,n.charAt(u-1)==\"\\r\"?u-1:u),y=m.indexOf(\"\\r\");y!=-1?(a.push(m.slice(0,y)),i+=y+1):(a.push(m),i=u+1)}return a}:function(n){return n.split(/\\r\\n?|\\n/)},Ri=window.getSelection?function(n){try{return n.selectionStart!=n.selectionEnd}catch{return!1}}:function(n){var i;try{i=n.ownerDocument.selection.createRange()}catch{}return!i||i.parentElement()!=n?!1:i.compareEndPoints(\"StartToEnd\",i)!=0},Ka=(function(){var n=k(\"div\");return\"oncopy\"in n?!0:(n.setAttribute(\"oncopy\",\"return;\"),typeof n.oncopy==\"function\")})(),wr=null;function vf(n){if(wr!=null)return wr;var i=C(n,k(\"span\",\"x\")),a=i.getBoundingClientRect(),l=B(i,0,1).getBoundingClientRect();return wr=Math.abs(a.left-l.left)>1}var Qo={},xr={};function kr(n,i){arguments.length>2&&(i.dependencies=Array.prototype.slice.call(arguments,2)),Qo[n]=i}function bo(n,i){xr[n]=i}function es(n){if(typeof n==\"string\"&&xr.hasOwnProperty(n))n=xr[n];else if(n&&typeof n.name==\"string\"&&xr.hasOwnProperty(n.name)){var i=xr[n.name];typeof i==\"string\"&&(i={name:i}),n=oe(i,n),n.name=i.name}else{if(typeof n==\"string\"&&/^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(n))return es(\"application/xml\");if(typeof n==\"string\"&&/^[\\w\\-]+\\/[\\w\\-]+\\+json$/.test(n))return es(\"application/json\")}return typeof n==\"string\"?{name:n}:n||{name:\"null\"}}function ts(n,i){i=es(i);var a=Qo[i.name];if(!a)return ts(n,\"text/plain\");var l=a(n,i);if($i.hasOwnProperty(i.name)){var u=$i[i.name];for(var m in u)u.hasOwnProperty(m)&&(l.hasOwnProperty(m)&&(l[\"_\"+m]=l[m]),l[m]=u[m])}if(l.name=i.name,i.helperType&&(l.helperType=i.helperType),i.modeProps)for(var y in i.modeProps)l[y]=i.modeProps[y];return l}var $i={};function ns(n,i){var a=$i.hasOwnProperty(n)?$i[n]:$i[n]={};Y(i,a)}function Br(n,i){if(i===!0)return i;if(n.copyState)return n.copyState(i);var a={};for(var l in i){var u=i[l];u instanceof Array&&(u=u.concat([])),a[l]=u}return a}function al(n,i){for(var a;n.innerMode&&(a=n.innerMode(i),!(!a||a.mode==n));)i=a.state,n=a.mode;return a||{mode:n,state:i}}function rs(n,i,a){return n.startState?n.startState(i,a):!0}var $t=function(n,i,a){this.pos=this.start=0,this.string=n,this.tabSize=i||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=a};$t.prototype.eol=function(){return this.pos>=this.string.length},$t.prototype.sol=function(){return this.pos==this.lineStart},$t.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},$t.prototype.next=function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},$t.prototype.eat=function(n){var i=this.string.charAt(this.pos),a;if(typeof n==\"string\"?a=i==n:a=i&&(n.test?n.test(i):n(i)),a)return++this.pos,i},$t.prototype.eatWhile=function(n){for(var i=this.pos;this.eat(n););return this.pos>i},$t.prototype.eatSpace=function(){for(var n=this.pos;/[\\s\\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>n},$t.prototype.skipToEnd=function(){this.pos=this.string.length},$t.prototype.skipTo=function(n){var i=this.string.indexOf(n,this.pos);if(i>-1)return this.pos=i,!0},$t.prototype.backUp=function(n){this.pos-=n},$t.prototype.column=function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=re(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?re(this.string,this.lineStart,this.tabSize):0)},$t.prototype.indentation=function(){return re(this.string,null,this.tabSize)-(this.lineStart?re(this.string,this.lineStart,this.tabSize):0)},$t.prototype.match=function(n,i,a){if(typeof n==\"string\"){var l=function(y){return a?y.toLowerCase():y},u=this.string.substr(this.pos,n.length);if(l(u)==l(n))return i!==!1&&(this.pos+=n.length),!0}else{var m=this.string.slice(this.pos).match(n);return m&&m.index>0?null:(m&&i!==!1&&(this.pos+=m[0].length),m)}},$t.prototype.current=function(){return this.string.slice(this.start,this.pos)},$t.prototype.hideFirstChars=function(n,i){this.lineStart+=n;try{return i()}finally{this.lineStart-=n}},$t.prototype.lookAhead=function(n){var i=this.lineOracle;return i&&i.lookAhead(n)},$t.prototype.baseToken=function(){var n=this.lineOracle;return n&&n.baseToken(this.pos)};function qe(n,i){if(i-=n.first,i<0||i>=n.size)throw new Error(\"There is no line \"+(i+n.first)+\" in the document.\");for(var a=n;!a.lines;)for(var l=0;;++l){var u=a.children[l],m=u.chunkSize();if(i<m){a=u;break}i-=m}return a.lines[i]}function ii(n,i,a){var l=[],u=i.line;return n.iter(i.line,a.line+1,function(m){var y=m.text;u==a.line&&(y=y.slice(0,a.ch)),u==i.line&&(y=y.slice(i.ch)),l.push(y),++u}),l}function cl(n,i,a){var l=[];return n.iter(i,a,function(u){l.push(u.text)}),l}function Qn(n,i){var a=i-n.height;if(a)for(var l=n;l;l=l.parent)l.height+=a}function A(n){if(n.parent==null)return null;for(var i=n.parent,a=ae(i.lines,n),l=i.parent;l;i=l,l=l.parent)for(var u=0;l.children[u]!=i;++u)a+=l.children[u].chunkSize();return a+i.first}function U(n,i){var a=n.first;e:do{for(var l=0;l<n.children.length;++l){var u=n.children[l],m=u.height;if(i<m){n=u;continue e}i-=m,a+=u.chunkSize()}return a}while(!n.lines);for(var y=0;y<n.lines.length;++y){var x=n.lines[y],S=x.height;if(i<S)break;i-=S}return a+y}function me(n,i){return i>=n.first&&i<n.first+n.size}function _e(n,i){return String(n.lineNumberFormatter(i+n.firstLineNumber))}function fe(n,i,a){if(a===void 0&&(a=null),!(this instanceof fe))return new fe(n,i,a);this.line=n,this.ch=i,this.sticky=a}function Ie(n,i){return n.line-i.line||n.ch-i.ch}function pt(n,i){return n.sticky==i.sticky&&Ie(n,i)==0}function Zt(n){return fe(n.line,n.ch)}function Sn(n,i){return Ie(n,i)<0?i:n}function is(n,i){return Ie(n,i)<0?n:i}function Wp(n,i){return Math.max(n.first,Math.min(i,n.first+n.size-1))}function tt(n,i){if(i.line<n.first)return fe(n.first,0);var a=n.first+n.size-1;return i.line>a?fe(a,qe(n,a).text.length):I1(i,qe(n,i.line).text.length)}function I1(n,i){var a=n.ch;return a==null||a>i?fe(n.line,i):a<0?fe(n.line,0):n}function qp(n,i){for(var a=[],l=0;l<i.length;l++)a[l]=tt(n,i[l]);return a}var Xa=function(n,i){this.state=n,this.lookAhead=i},Wr=function(n,i,a,l){this.state=i,this.doc=n,this.line=a,this.maxLookAhead=l||0,this.baseTokens=null,this.baseTokenPos=1};Wr.prototype.lookAhead=function(n){var i=this.doc.getLine(this.line+n);return i!=null&&n>this.maxLookAhead&&(this.maxLookAhead=n),i},Wr.prototype.baseToken=function(n){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=n;)this.baseTokenPos+=2;var i=this.baseTokens[this.baseTokenPos+1];return{type:i&&i.replace(/( |^)overlay .*/,\"\"),size:this.baseTokens[this.baseTokenPos]-n}},Wr.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},Wr.fromSaved=function(n,i,a){return i instanceof Xa?new Wr(n,Br(n.mode,i.state),a,i.lookAhead):new Wr(n,Br(n.mode,i),a)},Wr.prototype.save=function(n){var i=n!==!1?Br(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new Xa(i,this.maxLookAhead):i};function jp(n,i,a,l){var u=[n.state.modeGen],m={};Yp(n,i.text,n.doc.mode,a,function(T,H){return u.push(T,H)},m,l);for(var y=a.state,x=function(T){a.baseTokens=u;var H=n.state.overlays[T],V=1,se=0;a.state=!0,Yp(n,i.text,H.mode,a,function(te,pe){for(var we=V;se<te;){var Te=u[V];Te>te&&u.splice(V,1,te,u[V+1],Te),V+=2,se=Math.min(te,Te)}if(pe)if(H.opaque)u.splice(we,V-we,te,\"overlay \"+pe),V=we+2;else for(;we<V;we+=2){var Le=u[we+1];u[we+1]=(Le?Le+\" \":\"\")+\"overlay \"+pe}},m),a.state=y,a.baseTokens=null,a.baseTokenPos=1},S=0;S<n.state.overlays.length;++S)x(S);return{styles:u,classes:m.bgClass||m.textClass?m:null}}function Up(n,i,a){if(!i.styles||i.styles[0]!=n.state.modeGen){var l=ul(n,A(i)),u=i.text.length>n.options.maxHighlightLength&&Br(n.doc.mode,l.state),m=jp(n,i,l);u&&(l.state=u),i.stateAfter=l.save(!u),i.styles=m.styles,m.classes?i.styleClasses=m.classes:i.styleClasses&&(i.styleClasses=null),a===n.doc.highlightFrontier&&(n.doc.modeFrontier=Math.max(n.doc.modeFrontier,++n.doc.highlightFrontier))}return i.styles}function ul(n,i,a){var l=n.doc,u=n.display;if(!l.mode.startState)return new Wr(l,!0,i);var m=D1(n,i,a),y=m>l.first&&qe(l,m-1).stateAfter,x=y?Wr.fromSaved(l,y,m):new Wr(l,rs(l.mode),m);return l.iter(m,i,function(S){yf(n,S.text,x);var T=x.line;S.stateAfter=T==i-1||T%5==0||T>=u.viewFrom&&T<u.viewTo?x.save():null,x.nextLine()}),a&&(l.modeFrontier=x.line),x}function yf(n,i,a,l){var u=n.doc.mode,m=new $t(i,n.options.tabSize,a);for(m.start=m.pos=l||0,i==\"\"&&Vp(u,a.state);!m.eol();)bf(u,m,a.state),m.start=m.pos}function Vp(n,i){if(n.blankLine)return n.blankLine(i);if(n.innerMode){var a=al(n,i);if(a.mode.blankLine)return a.mode.blankLine(a.state)}}function bf(n,i,a,l){for(var u=0;u<10;u++){l&&(l[0]=al(n,a).mode);var m=n.token(i,a);if(i.pos>i.start)return m}throw new Error(\"Mode \"+n.name+\" failed to advance stream.\")}var Gp=function(n,i,a){this.start=n.start,this.end=n.pos,this.string=n.current(),this.type=i||null,this.state=a};function Kp(n,i,a,l){var u=n.doc,m=u.mode,y;i=tt(u,i);var x=qe(u,i.line),S=ul(n,i.line,a),T=new $t(x.text,n.options.tabSize,S),H;for(l&&(H=[]);(l||T.pos<i.ch)&&!T.eol();)T.start=T.pos,y=bf(m,T,S.state),l&&H.push(new Gp(T,y,Br(u.mode,S.state)));return l?H:new Gp(T,y,S.state)}function Xp(n,i){if(n)for(;;){var a=n.match(/(?:^|\\s+)line-(background-)?(\\S+)/);if(!a)break;n=n.slice(0,a.index)+n.slice(a.index+a[0].length);var l=a[1]?\"bgClass\":\"textClass\";i[l]==null?i[l]=a[2]:new RegExp(\"(?:^|\\\\s)\"+a[2]+\"(?:$|\\\\s)\").test(i[l])||(i[l]+=\" \"+a[2])}return n}function Yp(n,i,a,l,u,m,y){var x=a.flattenSpans;x==null&&(x=n.options.flattenSpans);var S=0,T=null,H=new $t(i,n.options.tabSize,l),V,se=n.options.addModeClass&&[null];for(i==\"\"&&Xp(Vp(a,l.state),m);!H.eol();){if(H.pos>n.options.maxHighlightLength?(x=!1,y&&yf(n,i,l,H.pos),H.pos=i.length,V=null):V=Xp(bf(a,H,l.state,se),m),se){var te=se[0].name;te&&(V=\"m-\"+(V?te+\" \"+V:te))}if(!x||T!=V){for(;S<H.start;)S=Math.min(H.start,S+5e3),u(S,T);T=V}H.start=H.pos}for(;S<H.pos;){var pe=Math.min(H.pos,S+5e3);u(pe,T),S=pe}}function D1(n,i,a){for(var l,u,m=n.doc,y=a?-1:i-(n.doc.mode.innerMode?1e3:100),x=i;x>y;--x){if(x<=m.first)return m.first;var S=qe(m,x-1),T=S.stateAfter;if(T&&(!a||x+(T instanceof Xa?T.lookAhead:0)<=m.modeFrontier))return x;var H=re(S.text,null,n.options.tabSize);(u==null||l>H)&&(u=x-1,l=H)}return u}function z1(n,i){if(n.modeFrontier=Math.min(n.modeFrontier,i),!(n.highlightFrontier<i-10)){for(var a=n.first,l=i-1;l>a;l--){var u=qe(n,l).stateAfter;if(u&&(!(u instanceof Xa)||l+u.lookAhead<i)){a=l+1;break}}n.highlightFrontier=Math.min(n.highlightFrontier,a)}}var Zp=!1,oi=!1;function F1(){Zp=!0}function H1(){oi=!0}function Ya(n,i,a){this.marker=n,this.from=i,this.to=a}function fl(n,i){if(n)for(var a=0;a<n.length;++a){var l=n[a];if(l.marker==i)return l}}function B1(n,i){for(var a,l=0;l<n.length;++l)n[l]!=i&&(a||(a=[])).push(n[l]);return a}function W1(n,i,a){var l=a&&window.WeakSet&&(a.markedSpans||(a.markedSpans=new WeakSet));l&&n.markedSpans&&l.has(n.markedSpans)?n.markedSpans.push(i):(n.markedSpans=n.markedSpans?n.markedSpans.concat([i]):[i],l&&l.add(n.markedSpans)),i.marker.attachLine(n)}function q1(n,i,a){var l;if(n)for(var u=0;u<n.length;++u){var m=n[u],y=m.marker,x=m.from==null||(y.inclusiveLeft?m.from<=i:m.from<i);if(x||m.from==i&&y.type==\"bookmark\"&&(!a||!m.marker.insertLeft)){var S=m.to==null||(y.inclusiveRight?m.to>=i:m.to>i);(l||(l=[])).push(new Ya(y,m.from,S?null:m.to))}}return l}function j1(n,i,a){var l;if(n)for(var u=0;u<n.length;++u){var m=n[u],y=m.marker,x=m.to==null||(y.inclusiveRight?m.to>=i:m.to>i);if(x||m.from==i&&y.type==\"bookmark\"&&(!a||m.marker.insertLeft)){var S=m.from==null||(y.inclusiveLeft?m.from<=i:m.from<i);(l||(l=[])).push(new Ya(y,S?null:m.from-i,m.to==null?null:m.to-i))}}return l}function wf(n,i){if(i.full)return null;var a=me(n,i.from.line)&&qe(n,i.from.line).markedSpans,l=me(n,i.to.line)&&qe(n,i.to.line).markedSpans;if(!a&&!l)return null;var u=i.from.ch,m=i.to.ch,y=Ie(i.from,i.to)==0,x=q1(a,u,y),S=j1(l,m,y),T=i.text.length==1,H=xe(i.text).length+(T?u:0);if(x)for(var V=0;V<x.length;++V){var se=x[V];if(se.to==null){var te=fl(S,se.marker);te?T&&(se.to=te.to==null?null:te.to+H):se.to=u}}if(S)for(var pe=0;pe<S.length;++pe){var we=S[pe];if(we.to!=null&&(we.to+=H),we.from==null){var Te=fl(x,we.marker);Te||(we.from=H,T&&(x||(x=[])).push(we))}else we.from+=H,T&&(x||(x=[])).push(we)}x&&(x=Jp(x)),S&&S!=x&&(S=Jp(S));var Le=[x];if(!T){var De=i.text.length-2,Me;if(De>0&&x)for(var ze=0;ze<x.length;++ze)x[ze].to==null&&(Me||(Me=[])).push(new Ya(x[ze].marker,null,null));for(var Ye=0;Ye<De;++Ye)Le.push(Me);Le.push(S)}return Le}function Jp(n){for(var i=0;i<n.length;++i){var a=n[i];a.from!=null&&a.from==a.to&&a.marker.clearWhenEmpty!==!1&&n.splice(i--,1)}return n.length?n:null}function U1(n,i,a){var l=null;if(n.iter(i.line,a.line+1,function(te){if(te.markedSpans)for(var pe=0;pe<te.markedSpans.length;++pe){var we=te.markedSpans[pe].marker;we.readOnly&&(!l||ae(l,we)==-1)&&(l||(l=[])).push(we)}}),!l)return null;for(var u=[{from:i,to:a}],m=0;m<l.length;++m)for(var y=l[m],x=y.find(0),S=0;S<u.length;++S){var T=u[S];if(!(Ie(T.to,x.from)<0||Ie(T.from,x.to)>0)){var H=[S,1],V=Ie(T.from,x.from),se=Ie(T.to,x.to);(V<0||!y.inclusiveLeft&&!V)&&H.push({from:T.from,to:x.from}),(se>0||!y.inclusiveRight&&!se)&&H.push({from:x.to,to:T.to}),u.splice.apply(u,H),S+=H.length-3}}return u}function Qp(n){var i=n.markedSpans;if(i){for(var a=0;a<i.length;++a)i[a].marker.detachLine(n);n.markedSpans=null}}function eg(n,i){if(i){for(var a=0;a<i.length;++a)i[a].marker.attachLine(n);n.markedSpans=i}}function Za(n){return n.inclusiveLeft?-1:0}function Ja(n){return n.inclusiveRight?1:0}function xf(n,i){var a=n.lines.length-i.lines.length;if(a!=0)return a;var l=n.find(),u=i.find(),m=Ie(l.from,u.from)||Za(n)-Za(i);if(m)return-m;var y=Ie(l.to,u.to)||Ja(n)-Ja(i);return y||i.id-n.id}function tg(n,i){var a=oi&&n.markedSpans,l;if(a)for(var u=void 0,m=0;m<a.length;++m)u=a[m],u.marker.collapsed&&(i?u.from:u.to)==null&&(!l||xf(l,u.marker)<0)&&(l=u.marker);return l}function ng(n){return tg(n,!0)}function Qa(n){return tg(n,!1)}function V1(n,i){var a=oi&&n.markedSpans,l;if(a)for(var u=0;u<a.length;++u){var m=a[u];m.marker.collapsed&&(m.from==null||m.from<i)&&(m.to==null||m.to>i)&&(!l||xf(l,m.marker)<0)&&(l=m.marker)}return l}function rg(n,i,a,l,u){var m=qe(n,i),y=oi&&m.markedSpans;if(y)for(var x=0;x<y.length;++x){var S=y[x];if(S.marker.collapsed){var T=S.marker.find(0),H=Ie(T.from,a)||Za(S.marker)-Za(u),V=Ie(T.to,l)||Ja(S.marker)-Ja(u);if(!(H>=0&&V<=0||H<=0&&V>=0)&&(H<=0&&(S.marker.inclusiveRight&&u.inclusiveLeft?Ie(T.to,a)>=0:Ie(T.to,a)>0)||H>=0&&(S.marker.inclusiveRight&&u.inclusiveLeft?Ie(T.from,l)<=0:Ie(T.from,l)<0)))return!0}}}function Sr(n){for(var i;i=ng(n);)n=i.find(-1,!0).line;return n}function G1(n){for(var i;i=Qa(n);)n=i.find(1,!0).line;return n}function K1(n){for(var i,a;i=Qa(n);)n=i.find(1,!0).line,(a||(a=[])).push(n);return a}function kf(n,i){var a=qe(n,i),l=Sr(a);return a==l?i:A(l)}function ig(n,i){if(i>n.lastLine())return i;var a=qe(n,i),l;if(!Ii(n,a))return i;for(;l=Qa(a);)a=l.find(1,!0).line;return A(a)+1}function Ii(n,i){var a=oi&&i.markedSpans;if(a){for(var l=void 0,u=0;u<a.length;++u)if(l=a[u],!!l.marker.collapsed){if(l.from==null)return!0;if(!l.marker.widgetNode&&l.from==0&&l.marker.inclusiveLeft&&Sf(n,i,l))return!0}}}function Sf(n,i,a){if(a.to==null){var l=a.marker.find(1,!0);return Sf(n,l.line,fl(l.line.markedSpans,a.marker))}if(a.marker.inclusiveRight&&a.to==i.text.length)return!0;for(var u=void 0,m=0;m<i.markedSpans.length;++m)if(u=i.markedSpans[m],u.marker.collapsed&&!u.marker.widgetNode&&u.from==a.to&&(u.to==null||u.to!=a.from)&&(u.marker.inclusiveLeft||a.marker.inclusiveRight)&&Sf(n,i,u))return!0}function si(n){n=Sr(n);for(var i=0,a=n.parent,l=0;l<a.lines.length;++l){var u=a.lines[l];if(u==n)break;i+=u.height}for(var m=a.parent;m;a=m,m=a.parent)for(var y=0;y<m.children.length;++y){var x=m.children[y];if(x==a)break;i+=x.height}return i}function ec(n){if(n.height==0)return 0;for(var i=n.text.length,a,l=n;a=ng(l);){var u=a.find(0,!0);l=u.from.line,i+=u.from.ch-u.to.ch}for(l=n;a=Qa(l);){var m=a.find(0,!0);i-=l.text.length-m.from.ch,l=m.to.line,i+=l.text.length-m.to.ch}return i}function _f(n){var i=n.display,a=n.doc;i.maxLine=qe(a,a.first),i.maxLineLength=ec(i.maxLine),i.maxLineChanged=!0,a.iter(function(l){var u=ec(l);u>i.maxLineLength&&(i.maxLineLength=u,i.maxLine=l)})}var os=function(n,i,a){this.text=n,eg(this,i),this.height=a?a(this):1};os.prototype.lineNo=function(){return A(this)},yr(os);function X1(n,i,a,l){n.text=i,n.stateAfter&&(n.stateAfter=null),n.styles&&(n.styles=null),n.order!=null&&(n.order=null),Qp(n),eg(n,a);var u=l?l(n):1;u!=n.height&&Qn(n,u)}function Y1(n){n.parent=null,Qp(n)}var Z1={},J1={};function og(n,i){if(!n||/^\\s*$/.test(n))return null;var a=i.addModeClass?J1:Z1;return a[n]||(a[n]=n.replace(/\\S+/g,\"cm-$&\"))}function sg(n,i){var a=z(\"span\",null,null,g?\"padding-right: .1px\":null),l={pre:z(\"pre\",[a],\"CodeMirror-line\"),content:a,col:0,pos:0,cm:n,trailingSpace:!1,splitSpaces:n.getOption(\"lineWrapping\")};i.measure={};for(var u=0;u<=(i.rest?i.rest.length:0);u++){var m=u?i.rest[u-1]:i.line,y=void 0;l.pos=0,l.addToken=ek,Pi(n.display.measure)&&(y=lt(m,n.doc.direction))&&(l.addToken=nk(l.addToken,y)),l.map=[];var x=i!=n.display.externalMeasured&&A(m);rk(m,l,Up(n,m,x)),m.styleClasses&&(m.styleClasses.bgClass&&(l.bgClass=Be(m.styleClasses.bgClass,l.bgClass||\"\")),m.styleClasses.textClass&&(l.textClass=Be(m.styleClasses.textClass,l.textClass||\"\"))),l.map.length==0&&l.map.push(0,0,l.content.appendChild(Ga(n.display.measure))),u==0?(i.measure.map=l.map,i.measure.cache={}):((i.measure.maps||(i.measure.maps=[])).push(l.map),(i.measure.caches||(i.measure.caches=[])).push({}))}if(g){var S=l.content.lastChild;(/\\bcm-tab\\b/.test(S.className)||S.querySelector&&S.querySelector(\".cm-tab\"))&&(l.content.className=\"cm-tab-wrap-hack\")}return Pt(n,\"renderLine\",n,i.line,l.pre),l.pre.className&&(l.textClass=Be(l.pre.className,l.textClass||\"\")),l}function Q1(n){var i=k(\"span\",\"•\",\"cm-invalidchar\");return i.title=\"\\\\u\"+n.charCodeAt(0).toString(16),i.setAttribute(\"aria-label\",i.title),i}function ek(n,i,a,l,u,m,y){if(i){var x=n.splitSpaces?tk(i,n.trailingSpace):i,S=n.cm.state.specialChars,T=!1,H;if(!S.test(i))n.col+=i.length,H=document.createTextNode(x),n.map.push(n.pos,n.pos+i.length,H),h&&p<9&&(T=!0),n.pos+=i.length;else{H=document.createDocumentFragment();for(var V=0;;){S.lastIndex=V;var se=S.exec(i),te=se?se.index-V:i.length-V;if(te){var pe=document.createTextNode(x.slice(V,V+te));h&&p<9?H.appendChild(k(\"span\",[pe])):H.appendChild(pe),n.map.push(n.pos,n.pos+te,pe),n.col+=te,n.pos+=te}if(!se)break;V+=te+1;var we=void 0;if(se[0]==\"\t\"){var Te=n.cm.options.tabSize,Le=Te-n.col%Te;we=H.appendChild(k(\"span\",Ee(Le),\"cm-tab\")),we.setAttribute(\"role\",\"presentation\"),we.setAttribute(\"cm-text\",\"\t\"),n.col+=Le}else se[0]==\"\\r\"||se[0]==`\n`?(we=H.appendChild(k(\"span\",se[0]==\"\\r\"?\"␍\":\"␤\",\"cm-invalidchar\")),we.setAttribute(\"cm-text\",se[0]),n.col+=1):(we=n.cm.options.specialCharPlaceholder(se[0]),we.setAttribute(\"cm-text\",se[0]),h&&p<9?H.appendChild(k(\"span\",[we])):H.appendChild(we),n.col+=1);n.map.push(n.pos,n.pos+1,we),n.pos++}}if(n.trailingSpace=x.charCodeAt(i.length-1)==32,a||l||u||T||m||y){var De=a||\"\";l&&(De+=l),u&&(De+=u);var Me=k(\"span\",[H],De,m);if(y)for(var ze in y)y.hasOwnProperty(ze)&&ze!=\"style\"&&ze!=\"class\"&&Me.setAttribute(ze,y[ze]);return n.content.appendChild(Me)}n.content.appendChild(H)}}function tk(n,i){if(n.length>1&&!/  /.test(n))return n;for(var a=i,l=\"\",u=0;u<n.length;u++){var m=n.charAt(u);m==\" \"&&a&&(u==n.length-1||n.charCodeAt(u+1)==32)&&(m=\" \"),l+=m,a=m==\" \"}return l}function nk(n,i){return function(a,l,u,m,y,x,S){u=u?u+\" cm-force-border\":\"cm-force-border\";for(var T=a.pos,H=T+l.length;;){for(var V=void 0,se=0;se<i.length&&(V=i[se],!(V.to>T&&V.from<=T));se++);if(V.to>=H)return n(a,l,u,m,y,x,S);n(a,l.slice(0,V.to-T),u,m,null,x,S),m=null,l=l.slice(V.to-T),T=V.to}}}function lg(n,i,a,l){var u=!l&&a.widgetNode;u&&n.map.push(n.pos,n.pos+i,u),!l&&n.cm.display.input.needsContentAttribute&&(u||(u=n.content.appendChild(document.createElement(\"span\"))),u.setAttribute(\"cm-marker\",a.id)),u&&(n.cm.display.input.setUneditable(u),n.content.appendChild(u)),n.pos+=i,n.trailingSpace=!1}function rk(n,i,a){var l=n.markedSpans,u=n.text,m=0;if(!l){for(var y=1;y<a.length;y+=2)i.addToken(i,u.slice(m,m=a[y]),og(a[y+1],i.cm.options));return}for(var x=u.length,S=0,T=1,H=\"\",V,se,te=0,pe,we,Te,Le,De;;){if(te==S){pe=we=Te=se=\"\",De=null,Le=null,te=1/0;for(var Me=[],ze=void 0,Ye=0;Ye<l.length;++Ye){var Ue=l[Ye],st=Ue.marker;if(st.type==\"bookmark\"&&Ue.from==S&&st.widgetNode)Me.push(st);else if(Ue.from<=S&&(Ue.to==null||Ue.to>S||st.collapsed&&Ue.to==S&&Ue.from==S)){if(Ue.to!=null&&Ue.to!=S&&te>Ue.to&&(te=Ue.to,we=\"\"),st.className&&(pe+=\" \"+st.className),st.css&&(se=(se?se+\";\":\"\")+st.css),st.startStyle&&Ue.from==S&&(Te+=\" \"+st.startStyle),st.endStyle&&Ue.to==te&&(ze||(ze=[])).push(st.endStyle,Ue.to),st.title&&((De||(De={})).title=st.title),st.attributes)for(var St in st.attributes)(De||(De={}))[St]=st.attributes[St];st.collapsed&&(!Le||xf(Le.marker,st)<0)&&(Le=Ue)}else Ue.from>S&&te>Ue.from&&(te=Ue.from)}if(ze)for(var tn=0;tn<ze.length;tn+=2)ze[tn+1]==te&&(we+=\" \"+ze[tn]);if(!Le||Le.from==S)for(var Ot=0;Ot<Me.length;++Ot)lg(i,0,Me[Ot]);if(Le&&(Le.from||0)==S){if(lg(i,(Le.to==null?x+1:Le.to)-S,Le.marker,Le.from==null),Le.to==null)return;Le.to==S&&(Le=!1)}}if(S>=x)break;for(var qn=Math.min(x,te);;){if(H){var Cn=S+H.length;if(!Le){var Ut=Cn>qn?H.slice(0,qn-S):H;i.addToken(i,Ut,V?V+pe:pe,Te,S+Ut.length==te?we:\"\",se,De)}if(Cn>=qn){H=H.slice(qn-S),S=qn;break}S=Cn,Te=\"\"}H=u.slice(m,m=a[T++]),V=og(a[T++],i.cm.options)}}}function ag(n,i,a){this.line=i,this.rest=K1(i),this.size=this.rest?A(xe(this.rest))-a+1:1,this.node=this.text=null,this.hidden=Ii(n,i)}function tc(n,i,a){for(var l=[],u,m=i;m<a;m=u){var y=new ag(n.doc,qe(n.doc,m),m);u=m+y.size,l.push(y)}return l}var ss=null;function ik(n){ss?ss.ops.push(n):n.ownsGroup=ss={ops:[n],delayedCallbacks:[]}}function ok(n){var i=n.delayedCallbacks,a=0;do{for(;a<i.length;a++)i[a].call(null);for(var l=0;l<n.ops.length;l++){var u=n.ops[l];if(u.cursorActivityHandlers)for(;u.cursorActivityCalled<u.cursorActivityHandlers.length;)u.cursorActivityHandlers[u.cursorActivityCalled++].call(null,u.cm)}}while(a<i.length)}function sk(n,i){var a=n.ownsGroup;if(a)try{ok(a)}finally{ss=null,i(a)}}var dl=null;function Jt(n,i){var a=ri(n,i);if(a.length){var l=Array.prototype.slice.call(arguments,2),u;ss?u=ss.delayedCallbacks:dl?u=dl:(u=dl=[],setTimeout(lk,0));for(var m=function(x){u.push(function(){return a[x].apply(null,l)})},y=0;y<a.length;++y)m(y)}}function lk(){var n=dl;dl=null;for(var i=0;i<n.length;++i)n[i]()}function cg(n,i,a,l){for(var u=0;u<i.changes.length;u++){var m=i.changes[u];m==\"text\"?ck(n,i):m==\"gutter\"?fg(n,i,a,l):m==\"class\"?Tf(n,i):m==\"widget\"&&uk(n,i,l)}i.changes=null}function hl(n){return n.node==n.text&&(n.node=k(\"div\",null,null,\"position: relative\"),n.text.parentNode&&n.text.parentNode.replaceChild(n.node,n.text),n.node.appendChild(n.text),h&&p<8&&(n.node.style.zIndex=2)),n.node}function ak(n,i){var a=i.bgClass?i.bgClass+\" \"+(i.line.bgClass||\"\"):i.line.bgClass;if(a&&(a+=\" CodeMirror-linebackground\"),i.background)a?i.background.className=a:(i.background.parentNode.removeChild(i.background),i.background=null);else if(a){var l=hl(i);i.background=l.insertBefore(k(\"div\",null,a),l.firstChild),n.display.input.setUneditable(i.background)}}function ug(n,i){var a=n.display.externalMeasured;return a&&a.line==i.line?(n.display.externalMeasured=null,i.measure=a.measure,a.built):sg(n,i)}function ck(n,i){var a=i.text.className,l=ug(n,i);i.text==i.node&&(i.node=l.pre),i.text.parentNode.replaceChild(l.pre,i.text),i.text=l.pre,l.bgClass!=i.bgClass||l.textClass!=i.textClass?(i.bgClass=l.bgClass,i.textClass=l.textClass,Tf(n,i)):a&&(i.text.className=a)}function Tf(n,i){ak(n,i),i.line.wrapClass?hl(i).className=i.line.wrapClass:i.node!=i.text&&(i.node.className=\"\");var a=i.textClass?i.textClass+\" \"+(i.line.textClass||\"\"):i.line.textClass;i.text.className=a||\"\"}function fg(n,i,a,l){if(i.gutter&&(i.node.removeChild(i.gutter),i.gutter=null),i.gutterBackground&&(i.node.removeChild(i.gutterBackground),i.gutterBackground=null),i.line.gutterClass){var u=hl(i);i.gutterBackground=k(\"div\",null,\"CodeMirror-gutter-background \"+i.line.gutterClass,\"left: \"+(n.options.fixedGutter?l.fixedPos:-l.gutterTotalWidth)+\"px; width: \"+l.gutterTotalWidth+\"px\"),n.display.input.setUneditable(i.gutterBackground),u.insertBefore(i.gutterBackground,i.text)}var m=i.line.gutterMarkers;if(n.options.lineNumbers||m){var y=hl(i),x=i.gutter=k(\"div\",null,\"CodeMirror-gutter-wrapper\",\"left: \"+(n.options.fixedGutter?l.fixedPos:-l.gutterTotalWidth)+\"px\");if(x.setAttribute(\"aria-hidden\",\"true\"),n.display.input.setUneditable(x),y.insertBefore(x,i.text),i.line.gutterClass&&(x.className+=\" \"+i.line.gutterClass),n.options.lineNumbers&&(!m||!m[\"CodeMirror-linenumbers\"])&&(i.lineNumber=x.appendChild(k(\"div\",_e(n.options,a),\"CodeMirror-linenumber CodeMirror-gutter-elt\",\"left: \"+l.gutterLeft[\"CodeMirror-linenumbers\"]+\"px; width: \"+n.display.lineNumInnerWidth+\"px\"))),m)for(var S=0;S<n.display.gutterSpecs.length;++S){var T=n.display.gutterSpecs[S].className,H=m.hasOwnProperty(T)&&m[T];H&&x.appendChild(k(\"div\",[H],\"CodeMirror-gutter-elt\",\"left: \"+l.gutterLeft[T]+\"px; width: \"+l.gutterWidth[T]+\"px\"))}}}function uk(n,i,a){i.alignable&&(i.alignable=null);for(var l=j(\"CodeMirror-linewidget\"),u=i.node.firstChild,m=void 0;u;u=m)m=u.nextSibling,l.test(u.className)&&i.node.removeChild(u);dg(n,i,a)}function fk(n,i,a,l){var u=ug(n,i);return i.text=i.node=u.pre,u.bgClass&&(i.bgClass=u.bgClass),u.textClass&&(i.textClass=u.textClass),Tf(n,i),fg(n,i,a,l),dg(n,i,l),i.node}function dg(n,i,a){if(hg(n,i.line,i,a,!0),i.rest)for(var l=0;l<i.rest.length;l++)hg(n,i.rest[l],i,a,!1)}function hg(n,i,a,l,u){if(i.widgets)for(var m=hl(a),y=0,x=i.widgets;y<x.length;++y){var S=x[y],T=k(\"div\",[S.node],\"CodeMirror-linewidget\"+(S.className?\" \"+S.className:\"\"));S.handleMouseEvents||T.setAttribute(\"cm-ignore-events\",\"true\"),dk(S,T,a,l),n.display.input.setUneditable(T),u&&S.above?m.insertBefore(T,a.gutter||a.text):m.appendChild(T),Jt(S,\"redraw\")}}function dk(n,i,a,l){if(n.noHScroll){(a.alignable||(a.alignable=[])).push(i);var u=l.wrapperWidth;i.style.left=l.fixedPos+\"px\",n.coverGutter||(u-=l.gutterTotalWidth,i.style.paddingLeft=l.gutterTotalWidth+\"px\"),i.style.width=u+\"px\"}n.coverGutter&&(i.style.zIndex=5,i.style.position=\"relative\",n.noHScroll||(i.style.marginLeft=-l.gutterTotalWidth+\"px\"))}function pl(n){if(n.height!=null)return n.height;var i=n.doc.cm;if(!i)return 0;if(!ce(document.body,n.node)){var a=\"position: relative;\";n.coverGutter&&(a+=\"margin-left: -\"+i.display.gutters.offsetWidth+\"px;\"),n.noHScroll&&(a+=\"width: \"+i.display.wrapper.clientWidth+\"px;\"),C(i.display.measure,k(\"div\",[n.node],null,a))}return n.height=n.node.parentNode.offsetHeight}function li(n,i){for(var a=sl(i);a!=n.wrapper;a=a.parentNode)if(!a||a.nodeType==1&&a.getAttribute(\"cm-ignore-events\")==\"true\"||a.parentNode==n.sizer&&a!=n.mover)return!0}function nc(n){return n.lineSpace.offsetTop}function Cf(n){return n.mover.offsetHeight-n.lineSpace.offsetHeight}function pg(n){if(n.cachedPaddingH)return n.cachedPaddingH;var i=C(n.measure,k(\"pre\",\"x\",\"CodeMirror-line-like\")),a=window.getComputedStyle?window.getComputedStyle(i):i.currentStyle,l={left:parseInt(a.paddingLeft),right:parseInt(a.paddingRight)};return!isNaN(l.left)&&!isNaN(l.right)&&(n.cachedPaddingH=l),l}function qr(n){return D-n.display.nativeBarWidth}function wo(n){return n.display.scroller.clientWidth-qr(n)-n.display.barWidth}function Ef(n){return n.display.scroller.clientHeight-qr(n)-n.display.barHeight}function hk(n,i,a){var l=n.options.lineWrapping,u=l&&wo(n);if(!i.measure.heights||l&&i.measure.width!=u){var m=i.measure.heights=[];if(l){i.measure.width=u;for(var y=i.text.firstChild.getClientRects(),x=0;x<y.length-1;x++){var S=y[x],T=y[x+1];Math.abs(S.bottom-T.bottom)>2&&m.push((S.bottom+T.top)/2-a.top)}}m.push(a.bottom-a.top)}}function gg(n,i,a){if(n.line==i)return{map:n.measure.map,cache:n.measure.cache};if(n.rest){for(var l=0;l<n.rest.length;l++)if(n.rest[l]==i)return{map:n.measure.maps[l],cache:n.measure.caches[l]};for(var u=0;u<n.rest.length;u++)if(A(n.rest[u])>a)return{map:n.measure.maps[u],cache:n.measure.caches[u],before:!0}}}function pk(n,i){i=Sr(i);var a=A(i),l=n.display.externalMeasured=new ag(n.doc,i,a);l.lineN=a;var u=l.built=sg(n,l);return l.text=u.pre,C(n.display.lineMeasure,u.pre),l}function mg(n,i,a,l){return jr(n,ls(n,i),a,l)}function Af(n,i){if(i>=n.display.viewFrom&&i<n.display.viewTo)return n.display.view[So(n,i)];var a=n.display.externalMeasured;if(a&&i>=a.lineN&&i<a.lineN+a.size)return a}function ls(n,i){var a=A(i),l=Af(n,a);l&&!l.text?l=null:l&&l.changes&&(cg(n,l,a,Pf(n)),n.curOp.forceUpdate=!0),l||(l=pk(n,i));var u=gg(l,i,a);return{line:i,view:l,rect:null,map:u.map,cache:u.cache,before:u.before,hasHeights:!1}}function jr(n,i,a,l,u){i.before&&(a=-1);var m=a+(l||\"\"),y;return i.cache.hasOwnProperty(m)?y=i.cache[m]:(i.rect||(i.rect=i.view.text.getBoundingClientRect()),i.hasHeights||(hk(n,i.view,i.rect),i.hasHeights=!0),y=mk(n,i,a,l),y.bogus||(i.cache[m]=y)),{left:y.left,right:y.right,top:u?y.rtop:y.top,bottom:u?y.rbottom:y.bottom}}var vg={left:0,right:0,top:0,bottom:0};function yg(n,i,a){for(var l,u,m,y,x,S,T=0;T<n.length;T+=3)if(x=n[T],S=n[T+1],i<x?(u=0,m=1,y=\"left\"):i<S?(u=i-x,m=u+1):(T==n.length-3||i==S&&n[T+3]>i)&&(m=S-x,u=m-1,i>=S&&(y=\"right\")),u!=null){if(l=n[T+2],x==S&&a==(l.insertLeft?\"left\":\"right\")&&(y=a),a==\"left\"&&u==0)for(;T&&n[T-2]==n[T-3]&&n[T-1].insertLeft;)l=n[(T-=3)+2],y=\"left\";if(a==\"right\"&&u==S-x)for(;T<n.length-3&&n[T+3]==n[T+4]&&!n[T+5].insertLeft;)l=n[(T+=3)+2],y=\"right\";break}return{node:l,start:u,end:m,collapse:y,coverStart:x,coverEnd:S}}function gk(n,i){var a=vg;if(i==\"left\")for(var l=0;l<n.length&&(a=n[l]).left==a.right;l++);else for(var u=n.length-1;u>=0&&(a=n[u]).left==a.right;u--);return a}function mk(n,i,a,l){var u=yg(i.map,a,l),m=u.node,y=u.start,x=u.end,S=u.collapse,T;if(m.nodeType==3){for(var H=0;H<4;H++){for(;y&&ut(i.line.text.charAt(u.coverStart+y));)--y;for(;u.coverStart+x<u.coverEnd&&ut(i.line.text.charAt(u.coverStart+x));)++x;if(h&&p<9&&y==0&&x==u.coverEnd-u.coverStart?T=m.parentNode.getBoundingClientRect():T=gk(B(m,y,x).getClientRects(),l),T.left||T.right||y==0)break;x=y,y=y-1,S=\"right\"}h&&p<11&&(T=vk(n.display.measure,T))}else{y>0&&(S=l=\"right\");var V;n.options.lineWrapping&&(V=m.getClientRects()).length>1?T=V[l==\"right\"?V.length-1:0]:T=m.getBoundingClientRect()}if(h&&p<9&&!y&&(!T||!T.left&&!T.right)){var se=m.parentNode.getClientRects()[0];se?T={left:se.left,right:se.left+cs(n.display),top:se.top,bottom:se.bottom}:T=vg}for(var te=T.top-i.rect.top,pe=T.bottom-i.rect.top,we=(te+pe)/2,Te=i.view.measure.heights,Le=0;Le<Te.length-1&&!(we<Te[Le]);Le++);var De=Le?Te[Le-1]:0,Me=Te[Le],ze={left:(S==\"right\"?T.right:T.left)-i.rect.left,right:(S==\"left\"?T.left:T.right)-i.rect.left,top:De,bottom:Me};return!T.left&&!T.right&&(ze.bogus=!0),n.options.singleCursorHeightPerLine||(ze.rtop=te,ze.rbottom=pe),ze}function vk(n,i){if(!window.screen||screen.logicalXDPI==null||screen.logicalXDPI==screen.deviceXDPI||!vf(n))return i;var a=screen.logicalXDPI/screen.deviceXDPI,l=screen.logicalYDPI/screen.deviceYDPI;return{left:i.left*a,right:i.right*a,top:i.top*l,bottom:i.bottom*l}}function bg(n){if(n.measure&&(n.measure.cache={},n.measure.heights=null,n.rest))for(var i=0;i<n.rest.length;i++)n.measure.caches[i]={}}function wg(n){n.display.externalMeasure=null,O(n.display.lineMeasure);for(var i=0;i<n.display.view.length;i++)bg(n.display.view[i])}function gl(n){wg(n),n.display.cachedCharWidth=n.display.cachedTextHeight=n.display.cachedPaddingH=null,n.options.lineWrapping||(n.display.maxLineChanged=!0),n.display.lineNumChars=null}function xg(n){return b&&I?-(n.body.getBoundingClientRect().left-parseInt(getComputedStyle(n.body).marginLeft)):n.defaultView.pageXOffset||(n.documentElement||n.body).scrollLeft}function kg(n){return b&&I?-(n.body.getBoundingClientRect().top-parseInt(getComputedStyle(n.body).marginTop)):n.defaultView.pageYOffset||(n.documentElement||n.body).scrollTop}function Lf(n){var i=Sr(n),a=i.widgets,l=0;if(a)for(var u=0;u<a.length;++u)a[u].above&&(l+=pl(a[u]));return l}function rc(n,i,a,l,u){if(!u){var m=Lf(i);a.top+=m,a.bottom+=m}if(l==\"line\")return a;l||(l=\"local\");var y=si(i);if(l==\"local\"?y+=nc(n.display):y-=n.display.viewOffset,l==\"page\"||l==\"window\"){var x=n.display.lineSpace.getBoundingClientRect();y+=x.top+(l==\"window\"?0:kg(Ke(n)));var S=x.left+(l==\"window\"?0:xg(Ke(n)));a.left+=S,a.right+=S}return a.top+=y,a.bottom+=y,a}function Sg(n,i,a){if(a==\"div\")return i;var l=i.left,u=i.top;if(a==\"page\")l-=xg(Ke(n)),u-=kg(Ke(n));else if(a==\"local\"||!a){var m=n.display.sizer.getBoundingClientRect();l+=m.left,u+=m.top}var y=n.display.lineSpace.getBoundingClientRect();return{left:l-y.left,top:u-y.top}}function ic(n,i,a,l,u){return l||(l=qe(n.doc,i.line)),rc(n,l,mg(n,l,i.ch,u),a)}function _r(n,i,a,l,u,m){l=l||qe(n.doc,i.line),u||(u=ls(n,l));function y(pe,we){var Te=jr(n,u,pe,we?\"right\":\"left\",m);return we?Te.left=Te.right:Te.right=Te.left,rc(n,l,Te,a)}var x=lt(l,n.doc.direction),S=i.ch,T=i.sticky;if(S>=l.text.length?(S=l.text.length,T=\"before\"):S<=0&&(S=0,T=\"after\"),!x)return y(T==\"before\"?S-1:S,T==\"before\");function H(pe,we,Te){var Le=x[we],De=Le.level==1;return y(Te?pe-1:pe,De!=Te)}var V=Bt(x,S,T),se=Hr,te=H(S,V,T==\"before\");return se!=null&&(te.other=H(S,se,T!=\"before\")),te}function _g(n,i){var a=0;i=tt(n.doc,i),n.options.lineWrapping||(a=cs(n.display)*i.ch);var l=qe(n.doc,i.line),u=si(l)+nc(n.display);return{left:a,right:a,top:u,bottom:u+l.height}}function Mf(n,i,a,l,u){var m=fe(n,i,a);return m.xRel=u,l&&(m.outside=l),m}function Nf(n,i,a){var l=n.doc;if(a+=n.display.viewOffset,a<0)return Mf(l.first,0,null,-1,-1);var u=U(l,a),m=l.first+l.size-1;if(u>m)return Mf(l.first+l.size-1,qe(l,m).text.length,null,1,1);i<0&&(i=0);for(var y=qe(l,u);;){var x=yk(n,y,u,i,a),S=V1(y,x.ch+(x.xRel>0||x.outside>0?1:0));if(!S)return x;var T=S.find(1);if(T.line==u)return T;y=qe(l,u=T.line)}}function Tg(n,i,a,l){l-=Lf(i);var u=i.text.length,m=jt(function(y){return jr(n,a,y-1).bottom<=l},u,0);return u=jt(function(y){return jr(n,a,y).top>l},m,u),{begin:m,end:u}}function Cg(n,i,a,l){a||(a=ls(n,i));var u=rc(n,i,jr(n,a,l),\"line\").top;return Tg(n,i,a,u)}function Of(n,i,a,l){return n.bottom<=a?!1:n.top>a?!0:(l?n.left:n.right)>i}function yk(n,i,a,l,u){u-=si(i);var m=ls(n,i),y=Lf(i),x=0,S=i.text.length,T=!0,H=lt(i,n.doc.direction);if(H){var V=(n.options.lineWrapping?wk:bk)(n,i,a,m,H,l,u);T=V.level!=1,x=T?V.from:V.to-1,S=T?V.to:V.from-1}var se=null,te=null,pe=jt(function(Ye){var Ue=jr(n,m,Ye);return Ue.top+=y,Ue.bottom+=y,Of(Ue,l,u,!1)?(Ue.top<=u&&Ue.left<=l&&(se=Ye,te=Ue),!0):!1},x,S),we,Te,Le=!1;if(te){var De=l-te.left<te.right-l,Me=De==T;pe=se+(Me?0:1),Te=Me?\"after\":\"before\",we=De?te.left:te.right}else{!T&&(pe==S||pe==x)&&pe++,Te=pe==0?\"after\":pe==i.text.length?\"before\":jr(n,m,pe-(T?1:0)).bottom+y<=u==T?\"after\":\"before\";var ze=_r(n,fe(a,pe,Te),\"line\",i,m);we=ze.left,Le=u<ze.top?-1:u>=ze.bottom?1:0}return pe=Yt(i.text,pe,1),Mf(a,pe,Te,Le,l-we)}function bk(n,i,a,l,u,m,y){var x=jt(function(V){var se=u[V],te=se.level!=1;return Of(_r(n,fe(a,te?se.to:se.from,te?\"before\":\"after\"),\"line\",i,l),m,y,!0)},0,u.length-1),S=u[x];if(x>0){var T=S.level!=1,H=_r(n,fe(a,T?S.from:S.to,T?\"after\":\"before\"),\"line\",i,l);Of(H,m,y,!0)&&H.top>y&&(S=u[x-1])}return S}function wk(n,i,a,l,u,m,y){var x=Tg(n,i,l,y),S=x.begin,T=x.end;/\\s/.test(i.text.charAt(T-1))&&T--;for(var H=null,V=null,se=0;se<u.length;se++){var te=u[se];if(!(te.from>=T||te.to<=S)){var pe=te.level!=1,we=jr(n,l,pe?Math.min(T,te.to)-1:Math.max(S,te.from)).right,Te=we<m?m-we+1e9:we-m;(!H||V>Te)&&(H=te,V=Te)}}return H||(H=u[u.length-1]),H.from<S&&(H={from:S,to:H.to,level:H.level}),H.to>T&&(H={from:H.from,to:T,level:H.level}),H}var xo;function as(n){if(n.cachedTextHeight!=null)return n.cachedTextHeight;if(xo==null){xo=k(\"pre\",null,\"CodeMirror-line-like\");for(var i=0;i<49;++i)xo.appendChild(document.createTextNode(\"x\")),xo.appendChild(k(\"br\"));xo.appendChild(document.createTextNode(\"x\"))}C(n.measure,xo);var a=xo.offsetHeight/50;return a>3&&(n.cachedTextHeight=a),O(n.measure),a||1}function cs(n){if(n.cachedCharWidth!=null)return n.cachedCharWidth;var i=k(\"span\",\"xxxxxxxxxx\"),a=k(\"pre\",[i],\"CodeMirror-line-like\");C(n.measure,a);var l=i.getBoundingClientRect(),u=(l.right-l.left)/10;return u>2&&(n.cachedCharWidth=u),u||10}function Pf(n){for(var i=n.display,a={},l={},u=i.gutters.clientLeft,m=i.gutters.firstChild,y=0;m;m=m.nextSibling,++y){var x=n.display.gutterSpecs[y].className;a[x]=m.offsetLeft+m.clientLeft+u,l[x]=m.clientWidth}return{fixedPos:Rf(i),gutterTotalWidth:i.gutters.offsetWidth,gutterLeft:a,gutterWidth:l,wrapperWidth:i.wrapper.clientWidth}}function Rf(n){return n.scroller.getBoundingClientRect().left-n.sizer.getBoundingClientRect().left}function Eg(n){var i=as(n.display),a=n.options.lineWrapping,l=a&&Math.max(5,n.display.scroller.clientWidth/cs(n.display)-3);return function(u){if(Ii(n.doc,u))return 0;var m=0;if(u.widgets)for(var y=0;y<u.widgets.length;y++)u.widgets[y].height&&(m+=u.widgets[y].height);return a?m+(Math.ceil(u.text.length/l)||1)*i:m+i}}function $f(n){var i=n.doc,a=Eg(n);i.iter(function(l){var u=a(l);u!=l.height&&Qn(l,u)})}function ko(n,i,a,l){var u=n.display;if(!a&&sl(i).getAttribute(\"cm-not-content\")==\"true\")return null;var m,y,x=u.lineSpace.getBoundingClientRect();try{m=i.clientX-x.left,y=i.clientY-x.top}catch{return null}var S=Nf(n,m,y),T;if(l&&S.xRel>0&&(T=qe(n.doc,S.line).text).length==S.ch){var H=re(T,T.length,n.options.tabSize)-T.length;S=fe(S.line,Math.max(0,Math.round((m-pg(n.display).left)/cs(n.display))-H))}return S}function So(n,i){if(i>=n.display.viewTo||(i-=n.display.viewFrom,i<0))return null;for(var a=n.display.view,l=0;l<a.length;l++)if(i-=a[l].size,i<0)return l}function _n(n,i,a,l){i==null&&(i=n.doc.first),a==null&&(a=n.doc.first+n.doc.size),l||(l=0);var u=n.display;if(l&&a<u.viewTo&&(u.updateLineNumbers==null||u.updateLineNumbers>i)&&(u.updateLineNumbers=i),n.curOp.viewChanged=!0,i>=u.viewTo)oi&&kf(n.doc,i)<u.viewTo&&zi(n);else if(a<=u.viewFrom)oi&&ig(n.doc,a+l)>u.viewFrom?zi(n):(u.viewFrom+=l,u.viewTo+=l);else if(i<=u.viewFrom&&a>=u.viewTo)zi(n);else if(i<=u.viewFrom){var m=oc(n,a,a+l,1);m?(u.view=u.view.slice(m.index),u.viewFrom=m.lineN,u.viewTo+=l):zi(n)}else if(a>=u.viewTo){var y=oc(n,i,i,-1);y?(u.view=u.view.slice(0,y.index),u.viewTo=y.lineN):zi(n)}else{var x=oc(n,i,i,-1),S=oc(n,a,a+l,1);x&&S?(u.view=u.view.slice(0,x.index).concat(tc(n,x.lineN,S.lineN)).concat(u.view.slice(S.index)),u.viewTo+=l):zi(n)}var T=u.externalMeasured;T&&(a<T.lineN?T.lineN+=l:i<T.lineN+T.size&&(u.externalMeasured=null))}function Di(n,i,a){n.curOp.viewChanged=!0;var l=n.display,u=n.display.externalMeasured;if(u&&i>=u.lineN&&i<u.lineN+u.size&&(l.externalMeasured=null),!(i<l.viewFrom||i>=l.viewTo)){var m=l.view[So(n,i)];if(m.node!=null){var y=m.changes||(m.changes=[]);ae(y,a)==-1&&y.push(a)}}}function zi(n){n.display.viewFrom=n.display.viewTo=n.doc.first,n.display.view=[],n.display.viewOffset=0}function oc(n,i,a,l){var u=So(n,i),m,y=n.display.view;if(!oi||a==n.doc.first+n.doc.size)return{index:u,lineN:a};for(var x=n.display.viewFrom,S=0;S<u;S++)x+=y[S].size;if(x!=i){if(l>0){if(u==y.length-1)return null;m=x+y[u].size-i,u++}else m=x-i;i+=m,a+=m}for(;kf(n.doc,a)!=a;){if(u==(l<0?0:y.length-1))return null;a+=l*y[u-(l<0?1:0)].size,u+=l}return{index:u,lineN:a}}function xk(n,i,a){var l=n.display,u=l.view;u.length==0||i>=l.viewTo||a<=l.viewFrom?(l.view=tc(n,i,a),l.viewFrom=i):(l.viewFrom>i?l.view=tc(n,i,l.viewFrom).concat(l.view):l.viewFrom<i&&(l.view=l.view.slice(So(n,i))),l.viewFrom=i,l.viewTo<a?l.view=l.view.concat(tc(n,l.viewTo,a)):l.viewTo>a&&(l.view=l.view.slice(0,So(n,a)))),l.viewTo=a}function Ag(n){for(var i=n.display.view,a=0,l=0;l<i.length;l++){var u=i[l];!u.hidden&&(!u.node||u.changes)&&++a}return a}function ml(n){n.display.input.showSelection(n.display.input.prepareSelection())}function Lg(n,i){i===void 0&&(i=!0);var a=n.doc,l={},u=l.cursors=document.createDocumentFragment(),m=l.selection=document.createDocumentFragment(),y=n.options.$customCursor;y&&(i=!0);for(var x=0;x<a.sel.ranges.length;x++)if(!(!i&&x==a.sel.primIndex)){var S=a.sel.ranges[x];if(!(S.from().line>=n.display.viewTo||S.to().line<n.display.viewFrom)){var T=S.empty();if(y){var H=y(n,S);H&&If(n,H,u)}else(T||n.options.showCursorWhenSelecting)&&If(n,S.head,u);T||kk(n,S,m)}}return l}function If(n,i,a){var l=_r(n,i,\"div\",null,null,!n.options.singleCursorHeightPerLine),u=a.appendChild(k(\"div\",\" \",\"CodeMirror-cursor\"));if(u.style.left=l.left+\"px\",u.style.top=l.top+\"px\",u.style.height=Math.max(0,l.bottom-l.top)*n.options.cursorHeight+\"px\",/\\bcm-fat-cursor\\b/.test(n.getWrapperElement().className)){var m=ic(n,i,\"div\",null,null),y=m.right-m.left;u.style.width=(y>0?y:n.defaultCharWidth())+\"px\"}if(l.other){var x=a.appendChild(k(\"div\",\" \",\"CodeMirror-cursor CodeMirror-secondarycursor\"));x.style.display=\"\",x.style.left=l.other.left+\"px\",x.style.top=l.other.top+\"px\",x.style.height=(l.other.bottom-l.other.top)*.85+\"px\"}}function sc(n,i){return n.top-i.top||n.left-i.left}function kk(n,i,a){var l=n.display,u=n.doc,m=document.createDocumentFragment(),y=pg(n.display),x=y.left,S=Math.max(l.sizerWidth,wo(n)-l.sizer.offsetLeft)-y.right,T=u.direction==\"ltr\";function H(Me,ze,Ye,Ue){ze<0&&(ze=0),ze=Math.round(ze),Ue=Math.round(Ue),m.appendChild(k(\"div\",null,\"CodeMirror-selected\",\"position: absolute; left: \"+Me+`px;\n                             top: `+ze+\"px; width: \"+(Ye??S-Me)+`px;\n                             height: `+(Ue-ze)+\"px\"))}function V(Me,ze,Ye){var Ue=qe(u,Me),st=Ue.text.length,St,tn;function Ot(Ut,En){return ic(n,fe(Me,Ut),\"div\",Ue,En)}function qn(Ut,En,sn){var Kt=Cg(n,Ue,null,Ut),Vt=En==\"ltr\"==(sn==\"after\")?\"left\":\"right\",It=sn==\"after\"?Kt.begin:Kt.end-(/\\s/.test(Ue.text.charAt(Kt.end-1))?2:1);return Ot(It,Vt)[Vt]}var Cn=lt(Ue,u.direction);return Fn(Cn,ze||0,Ye??st,function(Ut,En,sn,Kt){var Vt=sn==\"ltr\",It=Ot(Ut,Vt?\"left\":\"right\"),An=Ot(En-1,Vt?\"right\":\"left\"),ks=ze==null&&Ut==0,ji=Ye==null&&En==st,fn=Kt==0,Ur=!Cn||Kt==Cn.length-1;if(An.top-It.top<=3){var nn=(T?ks:ji)&&fn,cd=(T?ji:ks)&&Ur,ui=nn?x:(Vt?It:An).left,Ao=cd?S:(Vt?An:It).right;H(ui,It.top,Ao-ui,It.bottom)}else{var Lo,yn,Ss,ud;Vt?(Lo=T&&ks&&fn?x:It.left,yn=T?S:qn(Ut,sn,\"before\"),Ss=T?x:qn(En,sn,\"after\"),ud=T&&ji&&Ur?S:An.right):(Lo=T?qn(Ut,sn,\"before\"):x,yn=!T&&ks&&fn?S:It.right,Ss=!T&&ji&&Ur?x:An.left,ud=T?qn(En,sn,\"after\"):S),H(Lo,It.top,yn-Lo,It.bottom),It.bottom<An.top&&H(x,It.bottom,null,An.top),H(Ss,An.top,ud-Ss,An.bottom)}(!St||sc(It,St)<0)&&(St=It),sc(An,St)<0&&(St=An),(!tn||sc(It,tn)<0)&&(tn=It),sc(An,tn)<0&&(tn=An)}),{start:St,end:tn}}var se=i.from(),te=i.to();if(se.line==te.line)V(se.line,se.ch,te.ch);else{var pe=qe(u,se.line),we=qe(u,te.line),Te=Sr(pe)==Sr(we),Le=V(se.line,se.ch,Te?pe.text.length+1:null).end,De=V(te.line,Te?0:null,te.ch).start;Te&&(Le.top<De.top-2?(H(Le.right,Le.top,null,Le.bottom),H(x,De.top,De.left,De.bottom)):H(Le.right,Le.top,De.left-Le.right,Le.bottom)),Le.bottom<De.top&&H(x,Le.bottom,null,De.top)}a.appendChild(m)}function Df(n){if(n.state.focused){var i=n.display;clearInterval(i.blinker);var a=!0;i.cursorDiv.style.visibility=\"\",n.options.cursorBlinkRate>0?i.blinker=setInterval(function(){n.hasFocus()||us(n),i.cursorDiv.style.visibility=(a=!a)?\"\":\"hidden\"},n.options.cursorBlinkRate):n.options.cursorBlinkRate<0&&(i.cursorDiv.style.visibility=\"hidden\")}}function Mg(n){n.hasFocus()||(n.display.input.focus(),n.state.focused||Ff(n))}function zf(n){n.state.delayingBlurEvent=!0,setTimeout(function(){n.state.delayingBlurEvent&&(n.state.delayingBlurEvent=!1,n.state.focused&&us(n))},100)}function Ff(n,i){n.state.delayingBlurEvent&&!n.state.draggingText&&(n.state.delayingBlurEvent=!1),n.options.readOnly!=\"nocursor\"&&(n.state.focused||(Pt(n,\"focus\",n,i),n.state.focused=!0,Se(n.display.wrapper,\"CodeMirror-focused\"),!n.curOp&&n.display.selForContextMenu!=n.doc.sel&&(n.display.input.reset(),g&&setTimeout(function(){return n.display.input.reset(!0)},20)),n.display.input.receivedFocus()),Df(n))}function us(n,i){n.state.delayingBlurEvent||(n.state.focused&&(Pt(n,\"blur\",n,i),n.state.focused=!1,N(n.display.wrapper,\"CodeMirror-focused\")),clearInterval(n.display.blinker),setTimeout(function(){n.state.focused||(n.display.shift=!1)},150))}function lc(n){for(var i=n.display,a=i.lineDiv.offsetTop,l=Math.max(0,i.scroller.getBoundingClientRect().top),u=i.lineDiv.getBoundingClientRect().top,m=0,y=0;y<i.view.length;y++){var x=i.view[y],S=n.options.lineWrapping,T=void 0,H=0;if(!x.hidden){if(u+=x.line.height,h&&p<8){var V=x.node.offsetTop+x.node.offsetHeight;T=V-a,a=V}else{var se=x.node.getBoundingClientRect();T=se.bottom-se.top,!S&&x.text.firstChild&&(H=x.text.firstChild.getBoundingClientRect().right-se.left-1)}var te=x.line.height-T;if((te>.005||te<-.005)&&(u<l&&(m-=te),Qn(x.line,T),Ng(x.line),x.rest))for(var pe=0;pe<x.rest.length;pe++)Ng(x.rest[pe]);if(H>n.display.sizerWidth){var we=Math.ceil(H/cs(n.display));we>n.display.maxLineLength&&(n.display.maxLineLength=we,n.display.maxLine=x.line,n.display.maxLineChanged=!0)}}}Math.abs(m)>2&&(i.scroller.scrollTop+=m)}function Ng(n){if(n.widgets)for(var i=0;i<n.widgets.length;++i){var a=n.widgets[i],l=a.node.parentNode;l&&(a.height=l.offsetHeight)}}function ac(n,i,a){var l=a&&a.top!=null?Math.max(0,a.top):n.scroller.scrollTop;l=Math.floor(l-nc(n));var u=a&&a.bottom!=null?a.bottom:l+n.wrapper.clientHeight,m=U(i,l),y=U(i,u);if(a&&a.ensure){var x=a.ensure.from.line,S=a.ensure.to.line;x<m?(m=x,y=U(i,si(qe(i,x))+n.wrapper.clientHeight)):Math.min(S,i.lastLine())>=y&&(m=U(i,si(qe(i,S))-n.wrapper.clientHeight),y=S)}return{from:m,to:Math.max(y,m+1)}}function Sk(n,i){if(!Rt(n,\"scrollCursorIntoView\")){var a=n.display,l=a.sizer.getBoundingClientRect(),u=null,m=a.wrapper.ownerDocument;if(i.top+l.top<0?u=!0:i.bottom+l.top>(m.defaultView.innerHeight||m.documentElement.clientHeight)&&(u=!1),u!=null&&!M){var y=k(\"div\",\"​\",null,`position: absolute;\n                         top: `+(i.top-a.viewOffset-nc(n.display))+`px;\n                         height: `+(i.bottom-i.top+qr(n)+a.barHeight)+`px;\n                         left: `+i.left+\"px; width: \"+Math.max(2,i.right-i.left)+\"px;\");n.display.lineSpace.appendChild(y),y.scrollIntoView(u),n.display.lineSpace.removeChild(y)}}}function _k(n,i,a,l){l==null&&(l=0);var u;!n.options.lineWrapping&&i==a&&(a=i.sticky==\"before\"?fe(i.line,i.ch+1,\"before\"):i,i=i.ch?fe(i.line,i.sticky==\"before\"?i.ch-1:i.ch,\"after\"):i);for(var m=0;m<5;m++){var y=!1,x=_r(n,i),S=!a||a==i?x:_r(n,a);u={left:Math.min(x.left,S.left),top:Math.min(x.top,S.top)-l,right:Math.max(x.left,S.left),bottom:Math.max(x.bottom,S.bottom)+l};var T=Hf(n,u),H=n.doc.scrollTop,V=n.doc.scrollLeft;if(T.scrollTop!=null&&(yl(n,T.scrollTop),Math.abs(n.doc.scrollTop-H)>1&&(y=!0)),T.scrollLeft!=null&&(_o(n,T.scrollLeft),Math.abs(n.doc.scrollLeft-V)>1&&(y=!0)),!y)break}return u}function Tk(n,i){var a=Hf(n,i);a.scrollTop!=null&&yl(n,a.scrollTop),a.scrollLeft!=null&&_o(n,a.scrollLeft)}function Hf(n,i){var a=n.display,l=as(n.display);i.top<0&&(i.top=0);var u=n.curOp&&n.curOp.scrollTop!=null?n.curOp.scrollTop:a.scroller.scrollTop,m=Ef(n),y={};i.bottom-i.top>m&&(i.bottom=i.top+m);var x=n.doc.height+Cf(a),S=i.top<l,T=i.bottom>x-l;if(i.top<u)y.scrollTop=S?0:i.top;else if(i.bottom>u+m){var H=Math.min(i.top,(T?x:i.bottom)-m);H!=u&&(y.scrollTop=H)}var V=n.options.fixedGutter?0:a.gutters.offsetWidth,se=n.curOp&&n.curOp.scrollLeft!=null?n.curOp.scrollLeft:a.scroller.scrollLeft-V,te=wo(n)-a.gutters.offsetWidth,pe=i.right-i.left>te;return pe&&(i.right=i.left+te),i.left<10?y.scrollLeft=0:i.left<se?y.scrollLeft=Math.max(0,i.left+V-(pe?0:10)):i.right>te+se-3&&(y.scrollLeft=i.right+(pe?0:10)-te),y}function Bf(n,i){i!=null&&(cc(n),n.curOp.scrollTop=(n.curOp.scrollTop==null?n.doc.scrollTop:n.curOp.scrollTop)+i)}function fs(n){cc(n);var i=n.getCursor();n.curOp.scrollToPos={from:i,to:i,margin:n.options.cursorScrollMargin}}function vl(n,i,a){(i!=null||a!=null)&&cc(n),i!=null&&(n.curOp.scrollLeft=i),a!=null&&(n.curOp.scrollTop=a)}function Ck(n,i){cc(n),n.curOp.scrollToPos=i}function cc(n){var i=n.curOp.scrollToPos;if(i){n.curOp.scrollToPos=null;var a=_g(n,i.from),l=_g(n,i.to);Og(n,a,l,i.margin)}}function Og(n,i,a,l){var u=Hf(n,{left:Math.min(i.left,a.left),top:Math.min(i.top,a.top)-l,right:Math.max(i.right,a.right),bottom:Math.max(i.bottom,a.bottom)+l});vl(n,u.scrollLeft,u.scrollTop)}function yl(n,i){Math.abs(n.doc.scrollTop-i)<2||(s||qf(n,{top:i}),Pg(n,i,!0),s&&qf(n),xl(n,100))}function Pg(n,i,a){i=Math.max(0,Math.min(n.display.scroller.scrollHeight-n.display.scroller.clientHeight,i)),!(n.display.scroller.scrollTop==i&&!a)&&(n.doc.scrollTop=i,n.display.scrollbars.setScrollTop(i),n.display.scroller.scrollTop!=i&&(n.display.scroller.scrollTop=i))}function _o(n,i,a,l){i=Math.max(0,Math.min(i,n.display.scroller.scrollWidth-n.display.scroller.clientWidth)),!((a?i==n.doc.scrollLeft:Math.abs(n.doc.scrollLeft-i)<2)&&!l)&&(n.doc.scrollLeft=i,zg(n),n.display.scroller.scrollLeft!=i&&(n.display.scroller.scrollLeft=i),n.display.scrollbars.setScrollLeft(i))}function bl(n){var i=n.display,a=i.gutters.offsetWidth,l=Math.round(n.doc.height+Cf(n.display));return{clientHeight:i.scroller.clientHeight,viewHeight:i.wrapper.clientHeight,scrollWidth:i.scroller.scrollWidth,clientWidth:i.scroller.clientWidth,viewWidth:i.wrapper.clientWidth,barLeft:n.options.fixedGutter?a:0,docHeight:l,scrollHeight:l+qr(n)+i.barHeight,nativeBarWidth:i.nativeBarWidth,gutterWidth:a}}var To=function(n,i,a){this.cm=a;var l=this.vert=k(\"div\",[k(\"div\",null,null,\"min-width: 1px\")],\"CodeMirror-vscrollbar\"),u=this.horiz=k(\"div\",[k(\"div\",null,null,\"height: 100%; min-height: 1px\")],\"CodeMirror-hscrollbar\");l.tabIndex=u.tabIndex=-1,n(l),n(u),Xe(l,\"scroll\",function(){l.clientHeight&&i(l.scrollTop,\"vertical\")}),Xe(u,\"scroll\",function(){u.clientWidth&&i(u.scrollLeft,\"horizontal\")}),this.checkedZeroWidth=!1,h&&p<8&&(this.horiz.style.minHeight=this.vert.style.minWidth=\"18px\")};To.prototype.update=function(n){var i=n.scrollWidth>n.clientWidth+1,a=n.scrollHeight>n.clientHeight+1,l=n.nativeBarWidth;if(a){this.vert.style.display=\"block\",this.vert.style.bottom=i?l+\"px\":\"0\";var u=n.viewHeight-(i?l:0);this.vert.firstChild.style.height=Math.max(0,n.scrollHeight-n.clientHeight+u)+\"px\"}else this.vert.scrollTop=0,this.vert.style.display=\"\",this.vert.firstChild.style.height=\"0\";if(i){this.horiz.style.display=\"block\",this.horiz.style.right=a?l+\"px\":\"0\",this.horiz.style.left=n.barLeft+\"px\";var m=n.viewWidth-n.barLeft-(a?l:0);this.horiz.firstChild.style.width=Math.max(0,n.scrollWidth-n.clientWidth+m)+\"px\"}else this.horiz.style.display=\"\",this.horiz.firstChild.style.width=\"0\";return!this.checkedZeroWidth&&n.clientHeight>0&&(l==0&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:a?l:0,bottom:i?l:0}},To.prototype.setScrollLeft=function(n){this.horiz.scrollLeft!=n&&(this.horiz.scrollLeft=n),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,\"horiz\")},To.prototype.setScrollTop=function(n){this.vert.scrollTop!=n&&(this.vert.scrollTop=n),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,\"vert\")},To.prototype.zeroWidthHack=function(){var n=$&&!P?\"12px\":\"18px\";this.horiz.style.height=this.vert.style.width=n,this.horiz.style.visibility=this.vert.style.visibility=\"hidden\",this.disableHoriz=new le,this.disableVert=new le},To.prototype.enableZeroWidthBar=function(n,i,a){n.style.visibility=\"\";function l(){var u=n.getBoundingClientRect(),m=a==\"vert\"?document.elementFromPoint(u.right-1,(u.top+u.bottom)/2):document.elementFromPoint((u.right+u.left)/2,u.bottom-1);m!=n?n.style.visibility=\"hidden\":i.set(1e3,l)}i.set(1e3,l)},To.prototype.clear=function(){var n=this.horiz.parentNode;n.removeChild(this.horiz),n.removeChild(this.vert)};var wl=function(){};wl.prototype.update=function(){return{bottom:0,right:0}},wl.prototype.setScrollLeft=function(){},wl.prototype.setScrollTop=function(){},wl.prototype.clear=function(){};function ds(n,i){i||(i=bl(n));var a=n.display.barWidth,l=n.display.barHeight;Rg(n,i);for(var u=0;u<4&&a!=n.display.barWidth||l!=n.display.barHeight;u++)a!=n.display.barWidth&&n.options.lineWrapping&&lc(n),Rg(n,bl(n)),a=n.display.barWidth,l=n.display.barHeight}function Rg(n,i){var a=n.display,l=a.scrollbars.update(i);a.sizer.style.paddingRight=(a.barWidth=l.right)+\"px\",a.sizer.style.paddingBottom=(a.barHeight=l.bottom)+\"px\",a.heightForcer.style.borderBottom=l.bottom+\"px solid transparent\",l.right&&l.bottom?(a.scrollbarFiller.style.display=\"block\",a.scrollbarFiller.style.height=l.bottom+\"px\",a.scrollbarFiller.style.width=l.right+\"px\"):a.scrollbarFiller.style.display=\"\",l.bottom&&n.options.coverGutterNextToScrollbar&&n.options.fixedGutter?(a.gutterFiller.style.display=\"block\",a.gutterFiller.style.height=l.bottom+\"px\",a.gutterFiller.style.width=i.gutterWidth+\"px\"):a.gutterFiller.style.display=\"\"}var $g={native:To,null:wl};function Ig(n){n.display.scrollbars&&(n.display.scrollbars.clear(),n.display.scrollbars.addClass&&N(n.display.wrapper,n.display.scrollbars.addClass)),n.display.scrollbars=new $g[n.options.scrollbarStyle](function(i){n.display.wrapper.insertBefore(i,n.display.scrollbarFiller),Xe(i,\"mousedown\",function(){n.state.focused&&setTimeout(function(){return n.display.input.focus()},0)}),i.setAttribute(\"cm-not-content\",\"true\")},function(i,a){a==\"horizontal\"?_o(n,i):yl(n,i)},n),n.display.scrollbars.addClass&&Se(n.display.wrapper,n.display.scrollbars.addClass)}var Ek=0;function Co(n){n.curOp={cm:n,viewChanged:!1,startHeight:n.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Ek,markArrays:null},ik(n.curOp)}function Eo(n){var i=n.curOp;i&&sk(i,function(a){for(var l=0;l<a.ops.length;l++)a.ops[l].cm.curOp=null;Ak(a)})}function Ak(n){for(var i=n.ops,a=0;a<i.length;a++)Lk(i[a]);for(var l=0;l<i.length;l++)Mk(i[l]);for(var u=0;u<i.length;u++)Nk(i[u]);for(var m=0;m<i.length;m++)Ok(i[m]);for(var y=0;y<i.length;y++)Pk(i[y])}function Lk(n){var i=n.cm,a=i.display;$k(i),n.updateMaxLine&&_f(i),n.mustUpdate=n.viewChanged||n.forceUpdate||n.scrollTop!=null||n.scrollToPos&&(n.scrollToPos.from.line<a.viewFrom||n.scrollToPos.to.line>=a.viewTo)||a.maxLineChanged&&i.options.lineWrapping,n.update=n.mustUpdate&&new uc(i,n.mustUpdate&&{top:n.scrollTop,ensure:n.scrollToPos},n.forceUpdate)}function Mk(n){n.updatedDisplay=n.mustUpdate&&Wf(n.cm,n.update)}function Nk(n){var i=n.cm,a=i.display;n.updatedDisplay&&lc(i),n.barMeasure=bl(i),a.maxLineChanged&&!i.options.lineWrapping&&(n.adjustWidthTo=mg(i,a.maxLine,a.maxLine.text.length).left+3,i.display.sizerWidth=n.adjustWidthTo,n.barMeasure.scrollWidth=Math.max(a.scroller.clientWidth,a.sizer.offsetLeft+n.adjustWidthTo+qr(i)+i.display.barWidth),n.maxScrollLeft=Math.max(0,a.sizer.offsetLeft+n.adjustWidthTo-wo(i))),(n.updatedDisplay||n.selectionChanged)&&(n.preparedSelection=a.input.prepareSelection())}function Ok(n){var i=n.cm;n.adjustWidthTo!=null&&(i.display.sizer.style.minWidth=n.adjustWidthTo+\"px\",n.maxScrollLeft<i.doc.scrollLeft&&_o(i,Math.min(i.display.scroller.scrollLeft,n.maxScrollLeft),!0),i.display.maxLineChanged=!1);var a=n.focus&&n.focus==be(je(i));n.preparedSelection&&i.display.input.showSelection(n.preparedSelection,a),(n.updatedDisplay||n.startHeight!=i.doc.height)&&ds(i,n.barMeasure),n.updatedDisplay&&Uf(i,n.barMeasure),n.selectionChanged&&Df(i),i.state.focused&&n.updateInput&&i.display.input.reset(n.typing),a&&Mg(n.cm)}function Pk(n){var i=n.cm,a=i.display,l=i.doc;if(n.updatedDisplay&&Dg(i,n.update),a.wheelStartX!=null&&(n.scrollTop!=null||n.scrollLeft!=null||n.scrollToPos)&&(a.wheelStartX=a.wheelStartY=null),n.scrollTop!=null&&Pg(i,n.scrollTop,n.forceScroll),n.scrollLeft!=null&&_o(i,n.scrollLeft,!0,!0),n.scrollToPos){var u=_k(i,tt(l,n.scrollToPos.from),tt(l,n.scrollToPos.to),n.scrollToPos.margin);Sk(i,u)}var m=n.maybeHiddenMarkers,y=n.maybeUnhiddenMarkers;if(m)for(var x=0;x<m.length;++x)m[x].lines.length||Pt(m[x],\"hide\");if(y)for(var S=0;S<y.length;++S)y[S].lines.length&&Pt(y[S],\"unhide\");a.wrapper.offsetHeight&&(l.scrollTop=i.display.scroller.scrollTop),n.changeObjs&&Pt(i,\"changes\",i,n.changeObjs),n.update&&n.update.finish()}function Wn(n,i){if(n.curOp)return i();Co(n);try{return i()}finally{Eo(n)}}function Qt(n,i){return function(){if(n.curOp)return i.apply(n,arguments);Co(n);try{return i.apply(n,arguments)}finally{Eo(n)}}}function vn(n){return function(){if(this.curOp)return n.apply(this,arguments);Co(this);try{return n.apply(this,arguments)}finally{Eo(this)}}}function en(n){return function(){var i=this.cm;if(!i||i.curOp)return n.apply(this,arguments);Co(i);try{return n.apply(this,arguments)}finally{Eo(i)}}}function xl(n,i){n.doc.highlightFrontier<n.display.viewTo&&n.state.highlight.set(i,F(Rk,n))}function Rk(n){var i=n.doc;if(!(i.highlightFrontier>=n.display.viewTo)){var a=+new Date+n.options.workTime,l=ul(n,i.highlightFrontier),u=[];i.iter(l.line,Math.min(i.first+i.size,n.display.viewTo+500),function(m){if(l.line>=n.display.viewFrom){var y=m.styles,x=m.text.length>n.options.maxHighlightLength?Br(i.mode,l.state):null,S=jp(n,m,l,!0);x&&(l.state=x),m.styles=S.styles;var T=m.styleClasses,H=S.classes;H?m.styleClasses=H:T&&(m.styleClasses=null);for(var V=!y||y.length!=m.styles.length||T!=H&&(!T||!H||T.bgClass!=H.bgClass||T.textClass!=H.textClass),se=0;!V&&se<y.length;++se)V=y[se]!=m.styles[se];V&&u.push(l.line),m.stateAfter=l.save(),l.nextLine()}else m.text.length<=n.options.maxHighlightLength&&yf(n,m.text,l),m.stateAfter=l.line%5==0?l.save():null,l.nextLine();if(+new Date>a)return xl(n,n.options.workDelay),!0}),i.highlightFrontier=l.line,i.modeFrontier=Math.max(i.modeFrontier,l.line),u.length&&Wn(n,function(){for(var m=0;m<u.length;m++)Di(n,u[m],\"text\")})}}var uc=function(n,i,a){var l=n.display;this.viewport=i,this.visible=ac(l,n.doc,i),this.editorIsHidden=!l.wrapper.offsetWidth,this.wrapperHeight=l.wrapper.clientHeight,this.wrapperWidth=l.wrapper.clientWidth,this.oldDisplayWidth=wo(n),this.force=a,this.dims=Pf(n),this.events=[]};uc.prototype.signal=function(n,i){Bn(n,i)&&this.events.push(arguments)},uc.prototype.finish=function(){for(var n=0;n<this.events.length;n++)Pt.apply(null,this.events[n])};function $k(n){var i=n.display;!i.scrollbarsClipped&&i.scroller.offsetWidth&&(i.nativeBarWidth=i.scroller.offsetWidth-i.scroller.clientWidth,i.heightForcer.style.height=qr(n)+\"px\",i.sizer.style.marginBottom=-i.nativeBarWidth+\"px\",i.sizer.style.borderRightWidth=qr(n)+\"px\",i.scrollbarsClipped=!0)}function Ik(n){if(n.hasFocus())return null;var i=be(je(n));if(!i||!ce(n.display.lineDiv,i))return null;var a={activeElt:i};if(window.getSelection){var l=Pe(n).getSelection();l.anchorNode&&l.extend&&ce(n.display.lineDiv,l.anchorNode)&&(a.anchorNode=l.anchorNode,a.anchorOffset=l.anchorOffset,a.focusNode=l.focusNode,a.focusOffset=l.focusOffset)}return a}function Dk(n){if(!(!n||!n.activeElt||n.activeElt==be(Fe(n.activeElt)))&&(n.activeElt.focus(),!/^(INPUT|TEXTAREA)$/.test(n.activeElt.nodeName)&&n.anchorNode&&ce(document.body,n.anchorNode)&&ce(document.body,n.focusNode))){var i=n.activeElt.ownerDocument,a=i.defaultView.getSelection(),l=i.createRange();l.setEnd(n.anchorNode,n.anchorOffset),l.collapse(!1),a.removeAllRanges(),a.addRange(l),a.extend(n.focusNode,n.focusOffset)}}function Wf(n,i){var a=n.display,l=n.doc;if(i.editorIsHidden)return zi(n),!1;if(!i.force&&i.visible.from>=a.viewFrom&&i.visible.to<=a.viewTo&&(a.updateLineNumbers==null||a.updateLineNumbers>=a.viewTo)&&a.renderedView==a.view&&Ag(n)==0)return!1;Fg(n)&&(zi(n),i.dims=Pf(n));var u=l.first+l.size,m=Math.max(i.visible.from-n.options.viewportMargin,l.first),y=Math.min(u,i.visible.to+n.options.viewportMargin);a.viewFrom<m&&m-a.viewFrom<20&&(m=Math.max(l.first,a.viewFrom)),a.viewTo>y&&a.viewTo-y<20&&(y=Math.min(u,a.viewTo)),oi&&(m=kf(n.doc,m),y=ig(n.doc,y));var x=m!=a.viewFrom||y!=a.viewTo||a.lastWrapHeight!=i.wrapperHeight||a.lastWrapWidth!=i.wrapperWidth;xk(n,m,y),a.viewOffset=si(qe(n.doc,a.viewFrom)),n.display.mover.style.top=a.viewOffset+\"px\";var S=Ag(n);if(!x&&S==0&&!i.force&&a.renderedView==a.view&&(a.updateLineNumbers==null||a.updateLineNumbers>=a.viewTo))return!1;var T=Ik(n);return S>4&&(a.lineDiv.style.display=\"none\"),zk(n,a.updateLineNumbers,i.dims),S>4&&(a.lineDiv.style.display=\"\"),a.renderedView=a.view,Dk(T),O(a.cursorDiv),O(a.selectionDiv),a.gutters.style.height=a.sizer.style.minHeight=0,x&&(a.lastWrapHeight=i.wrapperHeight,a.lastWrapWidth=i.wrapperWidth,xl(n,400)),a.updateLineNumbers=null,!0}function Dg(n,i){for(var a=i.viewport,l=!0;;l=!1){if(!l||!n.options.lineWrapping||i.oldDisplayWidth==wo(n)){if(a&&a.top!=null&&(a={top:Math.min(n.doc.height+Cf(n.display)-Ef(n),a.top)}),i.visible=ac(n.display,n.doc,a),i.visible.from>=n.display.viewFrom&&i.visible.to<=n.display.viewTo)break}else l&&(i.visible=ac(n.display,n.doc,a));if(!Wf(n,i))break;lc(n);var u=bl(n);ml(n),ds(n,u),Uf(n,u),i.force=!1}i.signal(n,\"update\",n),(n.display.viewFrom!=n.display.reportedViewFrom||n.display.viewTo!=n.display.reportedViewTo)&&(i.signal(n,\"viewportChange\",n,n.display.viewFrom,n.display.viewTo),n.display.reportedViewFrom=n.display.viewFrom,n.display.reportedViewTo=n.display.viewTo)}function qf(n,i){var a=new uc(n,i);if(Wf(n,a)){lc(n),Dg(n,a);var l=bl(n);ml(n),ds(n,l),Uf(n,l),a.finish()}}function zk(n,i,a){var l=n.display,u=n.options.lineNumbers,m=l.lineDiv,y=m.firstChild;function x(pe){var we=pe.nextSibling;return g&&$&&n.display.currentWheelTarget==pe?pe.style.display=\"none\":pe.parentNode.removeChild(pe),we}for(var S=l.view,T=l.viewFrom,H=0;H<S.length;H++){var V=S[H];if(!V.hidden)if(!V.node||V.node.parentNode!=m){var se=fk(n,V,T,a);m.insertBefore(se,y)}else{for(;y!=V.node;)y=x(y);var te=u&&i!=null&&i<=T&&V.lineNumber;V.changes&&(ae(V.changes,\"gutter\")>-1&&(te=!1),cg(n,V,T,a)),te&&(O(V.lineNumber),V.lineNumber.appendChild(document.createTextNode(_e(n.options,T)))),y=V.node.nextSibling}T+=V.size}for(;y;)y=x(y)}function jf(n){var i=n.gutters.offsetWidth;n.sizer.style.marginLeft=i+\"px\",Jt(n,\"gutterChanged\",n)}function Uf(n,i){n.display.sizer.style.minHeight=i.docHeight+\"px\",n.display.heightForcer.style.top=i.docHeight+\"px\",n.display.gutters.style.height=i.docHeight+n.display.barHeight+qr(n)+\"px\"}function zg(n){var i=n.display,a=i.view;if(!(!i.alignWidgets&&(!i.gutters.firstChild||!n.options.fixedGutter))){for(var l=Rf(i)-i.scroller.scrollLeft+n.doc.scrollLeft,u=i.gutters.offsetWidth,m=l+\"px\",y=0;y<a.length;y++)if(!a[y].hidden){n.options.fixedGutter&&(a[y].gutter&&(a[y].gutter.style.left=m),a[y].gutterBackground&&(a[y].gutterBackground.style.left=m));var x=a[y].alignable;if(x)for(var S=0;S<x.length;S++)x[S].style.left=m}n.options.fixedGutter&&(i.gutters.style.left=l+u+\"px\")}}function Fg(n){if(!n.options.lineNumbers)return!1;var i=n.doc,a=_e(n.options,i.first+i.size-1),l=n.display;if(a.length!=l.lineNumChars){var u=l.measure.appendChild(k(\"div\",[k(\"div\",a)],\"CodeMirror-linenumber CodeMirror-gutter-elt\")),m=u.firstChild.offsetWidth,y=u.offsetWidth-m;return l.lineGutter.style.width=\"\",l.lineNumInnerWidth=Math.max(m,l.lineGutter.offsetWidth-y)+1,l.lineNumWidth=l.lineNumInnerWidth+y,l.lineNumChars=l.lineNumInnerWidth?a.length:-1,l.lineGutter.style.width=l.lineNumWidth+\"px\",jf(n.display),!0}return!1}function Vf(n,i){for(var a=[],l=!1,u=0;u<n.length;u++){var m=n[u],y=null;if(typeof m!=\"string\"&&(y=m.style,m=m.className),m==\"CodeMirror-linenumbers\")if(i)l=!0;else continue;a.push({className:m,style:y})}return i&&!l&&a.push({className:\"CodeMirror-linenumbers\",style:null}),a}function Hg(n){var i=n.gutters,a=n.gutterSpecs;O(i),n.lineGutter=null;for(var l=0;l<a.length;++l){var u=a[l],m=u.className,y=u.style,x=i.appendChild(k(\"div\",null,\"CodeMirror-gutter \"+m));y&&(x.style.cssText=y),m==\"CodeMirror-linenumbers\"&&(n.lineGutter=x,x.style.width=(n.lineNumWidth||1)+\"px\")}i.style.display=a.length?\"\":\"none\",jf(n)}function kl(n){Hg(n.display),_n(n),zg(n)}function Fk(n,i,a,l){var u=this;this.input=a,u.scrollbarFiller=k(\"div\",null,\"CodeMirror-scrollbar-filler\"),u.scrollbarFiller.setAttribute(\"cm-not-content\",\"true\"),u.gutterFiller=k(\"div\",null,\"CodeMirror-gutter-filler\"),u.gutterFiller.setAttribute(\"cm-not-content\",\"true\"),u.lineDiv=z(\"div\",null,\"CodeMirror-code\"),u.selectionDiv=k(\"div\",null,null,\"position: relative; z-index: 1\"),u.cursorDiv=k(\"div\",null,\"CodeMirror-cursors\"),u.measure=k(\"div\",null,\"CodeMirror-measure\"),u.lineMeasure=k(\"div\",null,\"CodeMirror-measure\"),u.lineSpace=z(\"div\",[u.measure,u.lineMeasure,u.selectionDiv,u.cursorDiv,u.lineDiv],null,\"position: relative; outline: none\");var m=z(\"div\",[u.lineSpace],\"CodeMirror-lines\");u.mover=k(\"div\",[m],null,\"position: relative\"),u.sizer=k(\"div\",[u.mover],\"CodeMirror-sizer\"),u.sizerWidth=null,u.heightForcer=k(\"div\",null,null,\"position: absolute; height: \"+D+\"px; width: 1px;\"),u.gutters=k(\"div\",null,\"CodeMirror-gutters\"),u.lineGutter=null,u.scroller=k(\"div\",[u.sizer,u.heightForcer,u.gutters],\"CodeMirror-scroll\"),u.scroller.setAttribute(\"tabIndex\",\"-1\"),u.wrapper=k(\"div\",[u.scrollbarFiller,u.gutterFiller,u.scroller],\"CodeMirror\"),b&&w>=105&&(u.wrapper.style.clipPath=\"inset(0px)\"),u.wrapper.setAttribute(\"translate\",\"no\"),h&&p<8&&(u.gutters.style.zIndex=-1,u.scroller.style.paddingRight=0),!g&&!(s&&_)&&(u.scroller.draggable=!0),n&&(n.appendChild?n.appendChild(u.wrapper):n(u.wrapper)),u.viewFrom=u.viewTo=i.first,u.reportedViewFrom=u.reportedViewTo=i.first,u.view=[],u.renderedView=null,u.externalMeasured=null,u.viewOffset=0,u.lastWrapHeight=u.lastWrapWidth=0,u.updateLineNumbers=null,u.nativeBarWidth=u.barHeight=u.barWidth=0,u.scrollbarsClipped=!1,u.lineNumWidth=u.lineNumInnerWidth=u.lineNumChars=null,u.alignWidgets=!1,u.cachedCharWidth=u.cachedTextHeight=u.cachedPaddingH=null,u.maxLine=null,u.maxLineLength=0,u.maxLineChanged=!1,u.wheelDX=u.wheelDY=u.wheelStartX=u.wheelStartY=null,u.shift=!1,u.selForContextMenu=null,u.activeTouch=null,u.gutterSpecs=Vf(l.gutters,l.lineNumbers),Hg(u),a.init(u)}var fc=0,ai=null;h?ai=-.53:s?ai=15:b?ai=-.7:L&&(ai=-1/3);function Bg(n){var i=n.wheelDeltaX,a=n.wheelDeltaY;return i==null&&n.detail&&n.axis==n.HORIZONTAL_AXIS&&(i=n.detail),a==null&&n.detail&&n.axis==n.VERTICAL_AXIS?a=n.detail:a==null&&(a=n.wheelDelta),{x:i,y:a}}function Hk(n){var i=Bg(n);return i.x*=ai,i.y*=ai,i}function Wg(n,i){b&&w==102&&(n.display.chromeScrollHack==null?n.display.sizer.style.pointerEvents=\"none\":clearTimeout(n.display.chromeScrollHack),n.display.chromeScrollHack=setTimeout(function(){n.display.chromeScrollHack=null,n.display.sizer.style.pointerEvents=\"\"},100));var a=Bg(i),l=a.x,u=a.y,m=ai;i.deltaMode===0&&(l=i.deltaX,u=i.deltaY,m=1);var y=n.display,x=y.scroller,S=x.scrollWidth>x.clientWidth,T=x.scrollHeight>x.clientHeight;if(l&&S||u&&T){if(u&&$&&g){e:for(var H=i.target,V=y.view;H!=x;H=H.parentNode)for(var se=0;se<V.length;se++)if(V[se].node==H){n.display.currentWheelTarget=H;break e}}if(l&&!s&&!E&&m!=null){u&&T&&yl(n,Math.max(0,x.scrollTop+u*m)),_o(n,Math.max(0,x.scrollLeft+l*m)),(!u||u&&T)&&cn(i),y.wheelStartX=null;return}if(u&&m!=null){var te=u*m,pe=n.doc.scrollTop,we=pe+y.wrapper.clientHeight;te<0?pe=Math.max(0,pe+te-50):we=Math.min(n.doc.height,we+te+50),qf(n,{top:pe,bottom:we})}fc<20&&i.deltaMode!==0&&(y.wheelStartX==null?(y.wheelStartX=x.scrollLeft,y.wheelStartY=x.scrollTop,y.wheelDX=l,y.wheelDY=u,setTimeout(function(){if(y.wheelStartX!=null){var Te=x.scrollLeft-y.wheelStartX,Le=x.scrollTop-y.wheelStartY,De=Le&&y.wheelDY&&Le/y.wheelDY||Te&&y.wheelDX&&Te/y.wheelDX;y.wheelStartX=y.wheelStartY=null,De&&(ai=(ai*fc+De)/(fc+1),++fc)}},200)):(y.wheelDX+=l,y.wheelDY+=u))}}var er=function(n,i){this.ranges=n,this.primIndex=i};er.prototype.primary=function(){return this.ranges[this.primIndex]},er.prototype.equals=function(n){if(n==this)return!0;if(n.primIndex!=this.primIndex||n.ranges.length!=this.ranges.length)return!1;for(var i=0;i<this.ranges.length;i++){var a=this.ranges[i],l=n.ranges[i];if(!pt(a.anchor,l.anchor)||!pt(a.head,l.head))return!1}return!0},er.prototype.deepCopy=function(){for(var n=[],i=0;i<this.ranges.length;i++)n[i]=new gt(Zt(this.ranges[i].anchor),Zt(this.ranges[i].head));return new er(n,this.primIndex)},er.prototype.somethingSelected=function(){for(var n=0;n<this.ranges.length;n++)if(!this.ranges[n].empty())return!0;return!1},er.prototype.contains=function(n,i){i||(i=n);for(var a=0;a<this.ranges.length;a++){var l=this.ranges[a];if(Ie(i,l.from())>=0&&Ie(n,l.to())<=0)return a}return-1};var gt=function(n,i){this.anchor=n,this.head=i};gt.prototype.from=function(){return is(this.anchor,this.head)},gt.prototype.to=function(){return Sn(this.anchor,this.head)},gt.prototype.empty=function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch};function Tr(n,i,a){var l=n&&n.options.selectionsMayTouch,u=i[a];i.sort(function(se,te){return Ie(se.from(),te.from())}),a=ae(i,u);for(var m=1;m<i.length;m++){var y=i[m],x=i[m-1],S=Ie(x.to(),y.from());if(l&&!y.empty()?S>0:S>=0){var T=is(x.from(),y.from()),H=Sn(x.to(),y.to()),V=x.empty()?y.from()==y.head:x.from()==x.head;m<=a&&--a,i.splice(--m,2,new gt(V?H:T,V?T:H))}}return new er(i,a)}function Fi(n,i){return new er([new gt(n,i||n)],0)}function Hi(n){return n.text?fe(n.from.line+n.text.length-1,xe(n.text).length+(n.text.length==1?n.from.ch:0)):n.to}function qg(n,i){if(Ie(n,i.from)<0)return n;if(Ie(n,i.to)<=0)return Hi(i);var a=n.line+i.text.length-(i.to.line-i.from.line)-1,l=n.ch;return n.line==i.to.line&&(l+=Hi(i).ch-i.to.ch),fe(a,l)}function Gf(n,i){for(var a=[],l=0;l<n.sel.ranges.length;l++){var u=n.sel.ranges[l];a.push(new gt(qg(u.anchor,i),qg(u.head,i)))}return Tr(n.cm,a,n.sel.primIndex)}function jg(n,i,a){return n.line==i.line?fe(a.line,n.ch-i.ch+a.ch):fe(a.line+(n.line-i.line),n.ch)}function Bk(n,i,a){for(var l=[],u=fe(n.first,0),m=u,y=0;y<i.length;y++){var x=i[y],S=jg(x.from,u,m),T=jg(Hi(x),u,m);if(u=x.to,m=T,a==\"around\"){var H=n.sel.ranges[y],V=Ie(H.head,H.anchor)<0;l[y]=new gt(V?T:S,V?S:T)}else l[y]=new gt(S,S)}return new er(l,n.sel.primIndex)}function Kf(n){n.doc.mode=ts(n.options,n.doc.modeOption),Sl(n)}function Sl(n){n.doc.iter(function(i){i.stateAfter&&(i.stateAfter=null),i.styles&&(i.styles=null)}),n.doc.modeFrontier=n.doc.highlightFrontier=n.doc.first,xl(n,100),n.state.modeGen++,n.curOp&&_n(n)}function Ug(n,i){return i.from.ch==0&&i.to.ch==0&&xe(i.text)==\"\"&&(!n.cm||n.cm.options.wholeLineUpdateBefore)}function Xf(n,i,a,l){function u(De){return a?a[De]:null}function m(De,Me,ze){X1(De,Me,ze,l),Jt(De,\"change\",De,i)}function y(De,Me){for(var ze=[],Ye=De;Ye<Me;++Ye)ze.push(new os(T[Ye],u(Ye),l));return ze}var x=i.from,S=i.to,T=i.text,H=qe(n,x.line),V=qe(n,S.line),se=xe(T),te=u(T.length-1),pe=S.line-x.line;if(i.full)n.insert(0,y(0,T.length)),n.remove(T.length,n.size-T.length);else if(Ug(n,i)){var we=y(0,T.length-1);m(V,V.text,te),pe&&n.remove(x.line,pe),we.length&&n.insert(x.line,we)}else if(H==V)if(T.length==1)m(H,H.text.slice(0,x.ch)+se+H.text.slice(S.ch),te);else{var Te=y(1,T.length-1);Te.push(new os(se+H.text.slice(S.ch),te,l)),m(H,H.text.slice(0,x.ch)+T[0],u(0)),n.insert(x.line+1,Te)}else if(T.length==1)m(H,H.text.slice(0,x.ch)+T[0]+V.text.slice(S.ch),u(0)),n.remove(x.line+1,pe);else{m(H,H.text.slice(0,x.ch)+T[0],u(0)),m(V,se+V.text.slice(S.ch),te);var Le=y(1,T.length-1);pe>1&&n.remove(x.line+1,pe-1),n.insert(x.line+1,Le)}Jt(n,\"change\",n,i)}function Bi(n,i,a){function l(u,m,y){if(u.linked)for(var x=0;x<u.linked.length;++x){var S=u.linked[x];if(S.doc!=m){var T=y&&S.sharedHist;a&&!T||(i(S.doc,T),l(S.doc,u,T))}}}l(n,null,!0)}function Vg(n,i){if(i.cm)throw new Error(\"This document is already in use.\");n.doc=i,i.cm=n,$f(n),Kf(n),Gg(n),n.options.direction=i.direction,n.options.lineWrapping||_f(n),n.options.mode=i.modeOption,_n(n)}function Gg(n){(n.doc.direction==\"rtl\"?Se:N)(n.display.lineDiv,\"CodeMirror-rtl\")}function Wk(n){Wn(n,function(){Gg(n),_n(n)})}function dc(n){this.done=[],this.undone=[],this.undoDepth=n?n.undoDepth:1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=n?n.maxGeneration:1}function Yf(n,i){var a={from:Zt(i.from),to:Hi(i),text:ii(n,i.from,i.to)};return Yg(n,a,i.from.line,i.to.line+1),Bi(n,function(l){return Yg(l,a,i.from.line,i.to.line+1)},!0),a}function Kg(n){for(;n.length;){var i=xe(n);if(i.ranges)n.pop();else break}}function qk(n,i){if(i)return Kg(n.done),xe(n.done);if(n.done.length&&!xe(n.done).ranges)return xe(n.done);if(n.done.length>1&&!n.done[n.done.length-2].ranges)return n.done.pop(),xe(n.done)}function Xg(n,i,a,l){var u=n.history;u.undone.length=0;var m=+new Date,y,x;if((u.lastOp==l||u.lastOrigin==i.origin&&i.origin&&(i.origin.charAt(0)==\"+\"&&u.lastModTime>m-(n.cm?n.cm.options.historyEventDelay:500)||i.origin.charAt(0)==\"*\"))&&(y=qk(u,u.lastOp==l)))x=xe(y.changes),Ie(i.from,i.to)==0&&Ie(i.from,x.to)==0?x.to=Hi(i):y.changes.push(Yf(n,i));else{var S=xe(u.done);for((!S||!S.ranges)&&hc(n.sel,u.done),y={changes:[Yf(n,i)],generation:u.generation},u.done.push(y);u.done.length>u.undoDepth;)u.done.shift(),u.done[0].ranges||u.done.shift()}u.done.push(a),u.generation=++u.maxGeneration,u.lastModTime=u.lastSelTime=m,u.lastOp=u.lastSelOp=l,u.lastOrigin=u.lastSelOrigin=i.origin,x||Pt(n,\"historyAdded\")}function jk(n,i,a,l){var u=i.charAt(0);return u==\"*\"||u==\"+\"&&a.ranges.length==l.ranges.length&&a.somethingSelected()==l.somethingSelected()&&new Date-n.history.lastSelTime<=(n.cm?n.cm.options.historyEventDelay:500)}function Uk(n,i,a,l){var u=n.history,m=l&&l.origin;a==u.lastSelOp||m&&u.lastSelOrigin==m&&(u.lastModTime==u.lastSelTime&&u.lastOrigin==m||jk(n,m,xe(u.done),i))?u.done[u.done.length-1]=i:hc(i,u.done),u.lastSelTime=+new Date,u.lastSelOrigin=m,u.lastSelOp=a,l&&l.clearRedo!==!1&&Kg(u.undone)}function hc(n,i){var a=xe(i);a&&a.ranges&&a.equals(n)||i.push(n)}function Yg(n,i,a,l){var u=i[\"spans_\"+n.id],m=0;n.iter(Math.max(n.first,a),Math.min(n.first+n.size,l),function(y){y.markedSpans&&((u||(u=i[\"spans_\"+n.id]={}))[m]=y.markedSpans),++m})}function Vk(n){if(!n)return null;for(var i,a=0;a<n.length;++a)n[a].marker.explicitlyCleared?i||(i=n.slice(0,a)):i&&i.push(n[a]);return i?i.length?i:null:n}function Gk(n,i){var a=i[\"spans_\"+n.id];if(!a)return null;for(var l=[],u=0;u<i.text.length;++u)l.push(Vk(a[u]));return l}function Zg(n,i){var a=Gk(n,i),l=wf(n,i);if(!a)return l;if(!l)return a;for(var u=0;u<a.length;++u){var m=a[u],y=l[u];if(m&&y)e:for(var x=0;x<y.length;++x){for(var S=y[x],T=0;T<m.length;++T)if(m[T].marker==S.marker)continue e;m.push(S)}else y&&(a[u]=y)}return a}function hs(n,i,a){for(var l=[],u=0;u<n.length;++u){var m=n[u];if(m.ranges){l.push(a?er.prototype.deepCopy.call(m):m);continue}var y=m.changes,x=[];l.push({changes:x});for(var S=0;S<y.length;++S){var T=y[S],H=void 0;if(x.push({from:T.from,to:T.to,text:T.text}),i)for(var V in T)(H=V.match(/^spans_(\\d+)$/))&&ae(i,Number(H[1]))>-1&&(xe(x)[V]=T[V],delete T[V])}}return l}function Zf(n,i,a,l){if(l){var u=n.anchor;if(a){var m=Ie(i,u)<0;m!=Ie(a,u)<0?(u=i,i=a):m!=Ie(i,a)<0&&(i=a)}return new gt(u,i)}else return new gt(a||i,i)}function pc(n,i,a,l,u){u==null&&(u=n.cm&&(n.cm.display.shift||n.extend)),un(n,new er([Zf(n.sel.primary(),i,a,u)],0),l)}function Jg(n,i,a){for(var l=[],u=n.cm&&(n.cm.display.shift||n.extend),m=0;m<n.sel.ranges.length;m++)l[m]=Zf(n.sel.ranges[m],i[m],null,u);var y=Tr(n.cm,l,n.sel.primIndex);un(n,y,a)}function Jf(n,i,a,l){var u=n.sel.ranges.slice(0);u[i]=a,un(n,Tr(n.cm,u,n.sel.primIndex),l)}function Qg(n,i,a,l){un(n,Fi(i,a),l)}function Kk(n,i,a){var l={ranges:i.ranges,update:function(u){this.ranges=[];for(var m=0;m<u.length;m++)this.ranges[m]=new gt(tt(n,u[m].anchor),tt(n,u[m].head))},origin:a&&a.origin};return Pt(n,\"beforeSelectionChange\",n,l),n.cm&&Pt(n.cm,\"beforeSelectionChange\",n.cm,l),l.ranges!=i.ranges?Tr(n.cm,l.ranges,l.ranges.length-1):i}function em(n,i,a){var l=n.history.done,u=xe(l);u&&u.ranges?(l[l.length-1]=i,gc(n,i,a)):un(n,i,a)}function un(n,i,a){gc(n,i,a),Uk(n,n.sel,n.cm?n.cm.curOp.id:NaN,a)}function gc(n,i,a){(Bn(n,\"beforeSelectionChange\")||n.cm&&Bn(n.cm,\"beforeSelectionChange\"))&&(i=Kk(n,i,a));var l=a&&a.bias||(Ie(i.primary().head,n.sel.primary().head)<0?-1:1);tm(n,rm(n,i,l,!0)),!(a&&a.scroll===!1)&&n.cm&&n.cm.getOption(\"readOnly\")!=\"nocursor\"&&fs(n.cm)}function tm(n,i){i.equals(n.sel)||(n.sel=i,n.cm&&(n.cm.curOp.updateInput=1,n.cm.curOp.selectionChanged=!0,ar(n.cm)),Jt(n,\"cursorActivity\",n))}function nm(n){tm(n,rm(n,n.sel,null,!1))}function rm(n,i,a,l){for(var u,m=0;m<i.ranges.length;m++){var y=i.ranges[m],x=i.ranges.length==n.sel.ranges.length&&n.sel.ranges[m],S=mc(n,y.anchor,x&&x.anchor,a,l),T=y.head==y.anchor?S:mc(n,y.head,x&&x.head,a,l);(u||S!=y.anchor||T!=y.head)&&(u||(u=i.ranges.slice(0,m)),u[m]=new gt(S,T))}return u?Tr(n.cm,u,i.primIndex):i}function ps(n,i,a,l,u){var m=qe(n,i.line);if(m.markedSpans)for(var y=0;y<m.markedSpans.length;++y){var x=m.markedSpans[y],S=x.marker,T=\"selectLeft\"in S?!S.selectLeft:S.inclusiveLeft,H=\"selectRight\"in S?!S.selectRight:S.inclusiveRight;if((x.from==null||(T?x.from<=i.ch:x.from<i.ch))&&(x.to==null||(H?x.to>=i.ch:x.to>i.ch))){if(u&&(Pt(S,\"beforeCursorEnter\"),S.explicitlyCleared))if(m.markedSpans){--y;continue}else break;if(!S.atomic)continue;if(a){var V=S.find(l<0?1:-1),se=void 0;if((l<0?H:T)&&(V=im(n,V,-l,V&&V.line==i.line?m:null)),V&&V.line==i.line&&(se=Ie(V,a))&&(l<0?se<0:se>0))return ps(n,V,i,l,u)}var te=S.find(l<0?-1:1);return(l<0?T:H)&&(te=im(n,te,l,te.line==i.line?m:null)),te?ps(n,te,i,l,u):null}}return i}function mc(n,i,a,l,u){var m=l||1,y=ps(n,i,a,m,u)||!u&&ps(n,i,a,m,!0)||ps(n,i,a,-m,u)||!u&&ps(n,i,a,-m,!0);return y||(n.cantEdit=!0,fe(n.first,0))}function im(n,i,a,l){return a<0&&i.ch==0?i.line>n.first?tt(n,fe(i.line-1)):null:a>0&&i.ch==(l||qe(n,i.line)).text.length?i.line<n.first+n.size-1?fe(i.line+1,0):null:new fe(i.line,i.ch+a)}function om(n){n.setSelection(fe(n.firstLine(),0),fe(n.lastLine()),Q)}function sm(n,i,a){var l={canceled:!1,from:i.from,to:i.to,text:i.text,origin:i.origin,cancel:function(){return l.canceled=!0}};return a&&(l.update=function(u,m,y,x){u&&(l.from=tt(n,u)),m&&(l.to=tt(n,m)),y&&(l.text=y),x!==void 0&&(l.origin=x)}),Pt(n,\"beforeChange\",n,l),n.cm&&Pt(n.cm,\"beforeChange\",n.cm,l),l.canceled?(n.cm&&(n.cm.curOp.updateInput=2),null):{from:l.from,to:l.to,text:l.text,origin:l.origin}}function gs(n,i,a){if(n.cm){if(!n.cm.curOp)return Qt(n.cm,gs)(n,i,a);if(n.cm.state.suppressEdits)return}if(!((Bn(n,\"beforeChange\")||n.cm&&Bn(n.cm,\"beforeChange\"))&&(i=sm(n,i,!0),!i))){var l=Zp&&!a&&U1(n,i.from,i.to);if(l)for(var u=l.length-1;u>=0;--u)lm(n,{from:l[u].from,to:l[u].to,text:u?[\"\"]:i.text,origin:i.origin});else lm(n,i)}}function lm(n,i){if(!(i.text.length==1&&i.text[0]==\"\"&&Ie(i.from,i.to)==0)){var a=Gf(n,i);Xg(n,i,a,n.cm?n.cm.curOp.id:NaN),_l(n,i,a,wf(n,i));var l=[];Bi(n,function(u,m){!m&&ae(l,u.history)==-1&&(fm(u.history,i),l.push(u.history)),_l(u,i,null,wf(u,i))})}}function vc(n,i,a){var l=n.cm&&n.cm.state.suppressEdits;if(!(l&&!a)){for(var u=n.history,m,y=n.sel,x=i==\"undo\"?u.done:u.undone,S=i==\"undo\"?u.undone:u.done,T=0;T<x.length&&(m=x[T],!(a?m.ranges&&!m.equals(n.sel):!m.ranges));T++);if(T!=x.length){for(u.lastOrigin=u.lastSelOrigin=null;;)if(m=x.pop(),m.ranges){if(hc(m,S),a&&!m.equals(n.sel)){un(n,m,{clearRedo:!1});return}y=m}else if(l){x.push(m);return}else break;var H=[];hc(y,S),S.push({changes:H,generation:u.generation}),u.generation=m.generation||++u.maxGeneration;for(var V=Bn(n,\"beforeChange\")||n.cm&&Bn(n.cm,\"beforeChange\"),se=function(we){var Te=m.changes[we];if(Te.origin=i,V&&!sm(n,Te,!1))return x.length=0,{};H.push(Yf(n,Te));var Le=we?Gf(n,Te):xe(x);_l(n,Te,Le,Zg(n,Te)),!we&&n.cm&&n.cm.scrollIntoView({from:Te.from,to:Hi(Te)});var De=[];Bi(n,function(Me,ze){!ze&&ae(De,Me.history)==-1&&(fm(Me.history,Te),De.push(Me.history)),_l(Me,Te,null,Zg(Me,Te))})},te=m.changes.length-1;te>=0;--te){var pe=se(te);if(pe)return pe.v}}}}function am(n,i){if(i!=0&&(n.first+=i,n.sel=new er(ye(n.sel.ranges,function(u){return new gt(fe(u.anchor.line+i,u.anchor.ch),fe(u.head.line+i,u.head.ch))}),n.sel.primIndex),n.cm)){_n(n.cm,n.first,n.first-i,i);for(var a=n.cm.display,l=a.viewFrom;l<a.viewTo;l++)Di(n.cm,l,\"gutter\")}}function _l(n,i,a,l){if(n.cm&&!n.cm.curOp)return Qt(n.cm,_l)(n,i,a,l);if(i.to.line<n.first){am(n,i.text.length-1-(i.to.line-i.from.line));return}if(!(i.from.line>n.lastLine())){if(i.from.line<n.first){var u=i.text.length-1-(n.first-i.from.line);am(n,u),i={from:fe(n.first,0),to:fe(i.to.line+u,i.to.ch),text:[xe(i.text)],origin:i.origin}}var m=n.lastLine();i.to.line>m&&(i={from:i.from,to:fe(m,qe(n,m).text.length),text:[i.text[0]],origin:i.origin}),i.removed=ii(n,i.from,i.to),a||(a=Gf(n,i)),n.cm?Xk(n.cm,i,l):Xf(n,i,l),gc(n,a,Q),n.cantEdit&&mc(n,fe(n.firstLine(),0))&&(n.cantEdit=!1)}}function Xk(n,i,a){var l=n.doc,u=n.display,m=i.from,y=i.to,x=!1,S=m.line;n.options.lineWrapping||(S=A(Sr(qe(l,m.line))),l.iter(S,y.line+1,function(te){if(te==u.maxLine)return x=!0,!0})),l.sel.contains(i.from,i.to)>-1&&ar(n),Xf(l,i,a,Eg(n)),n.options.lineWrapping||(l.iter(S,m.line+i.text.length,function(te){var pe=ec(te);pe>u.maxLineLength&&(u.maxLine=te,u.maxLineLength=pe,u.maxLineChanged=!0,x=!1)}),x&&(n.curOp.updateMaxLine=!0)),z1(l,m.line),xl(n,400);var T=i.text.length-(y.line-m.line)-1;i.full?_n(n):m.line==y.line&&i.text.length==1&&!Ug(n.doc,i)?Di(n,m.line,\"text\"):_n(n,m.line,y.line+1,T);var H=Bn(n,\"changes\"),V=Bn(n,\"change\");if(V||H){var se={from:m,to:y,text:i.text,removed:i.removed,origin:i.origin};V&&Jt(n,\"change\",n,se),H&&(n.curOp.changeObjs||(n.curOp.changeObjs=[])).push(se)}n.display.selForContextMenu=null}function ms(n,i,a,l,u){var m;l||(l=a),Ie(l,a)<0&&(m=[l,a],a=m[0],l=m[1]),typeof i==\"string\"&&(i=n.splitLines(i)),gs(n,{from:a,to:l,text:i,origin:u})}function cm(n,i,a,l){a<n.line?n.line+=l:i<n.line&&(n.line=i,n.ch=0)}function um(n,i,a,l){for(var u=0;u<n.length;++u){var m=n[u],y=!0;if(m.ranges){m.copied||(m=n[u]=m.deepCopy(),m.copied=!0);for(var x=0;x<m.ranges.length;x++)cm(m.ranges[x].anchor,i,a,l),cm(m.ranges[x].head,i,a,l);continue}for(var S=0;S<m.changes.length;++S){var T=m.changes[S];if(a<T.from.line)T.from=fe(T.from.line+l,T.from.ch),T.to=fe(T.to.line+l,T.to.ch);else if(i<=T.to.line){y=!1;break}}y||(n.splice(0,u+1),u=0)}}function fm(n,i){var a=i.from.line,l=i.to.line,u=i.text.length-(l-a)-1;um(n.done,a,l,u),um(n.undone,a,l,u)}function Tl(n,i,a,l){var u=i,m=i;return typeof i==\"number\"?m=qe(n,Wp(n,i)):u=A(i),u==null?null:(l(m,u)&&n.cm&&Di(n.cm,u,a),m)}function Cl(n){this.lines=n,this.parent=null;for(var i=0,a=0;a<n.length;++a)n[a].parent=this,i+=n[a].height;this.height=i}Cl.prototype={chunkSize:function(){return this.lines.length},removeInner:function(n,i){for(var a=n,l=n+i;a<l;++a){var u=this.lines[a];this.height-=u.height,Y1(u),Jt(u,\"delete\")}this.lines.splice(n,i)},collapse:function(n){n.push.apply(n,this.lines)},insertInner:function(n,i,a){this.height+=a,this.lines=this.lines.slice(0,n).concat(i).concat(this.lines.slice(n));for(var l=0;l<i.length;++l)i[l].parent=this},iterN:function(n,i,a){for(var l=n+i;n<l;++n)if(a(this.lines[n]))return!0}};function El(n){this.children=n;for(var i=0,a=0,l=0;l<n.length;++l){var u=n[l];i+=u.chunkSize(),a+=u.height,u.parent=this}this.size=i,this.height=a,this.parent=null}El.prototype={chunkSize:function(){return this.size},removeInner:function(n,i){this.size-=i;for(var a=0;a<this.children.length;++a){var l=this.children[a],u=l.chunkSize();if(n<u){var m=Math.min(i,u-n),y=l.height;if(l.removeInner(n,m),this.height-=y-l.height,u==m&&(this.children.splice(a--,1),l.parent=null),(i-=m)==0)break;n=0}else n-=u}if(this.size-i<25&&(this.children.length>1||!(this.children[0]instanceof Cl))){var x=[];this.collapse(x),this.children=[new Cl(x)],this.children[0].parent=this}},collapse:function(n){for(var i=0;i<this.children.length;++i)this.children[i].collapse(n)},insertInner:function(n,i,a){this.size+=i.length,this.height+=a;for(var l=0;l<this.children.length;++l){var u=this.children[l],m=u.chunkSize();if(n<=m){if(u.insertInner(n,i,a),u.lines&&u.lines.length>50){for(var y=u.lines.length%25+25,x=y;x<u.lines.length;){var S=new Cl(u.lines.slice(x,x+=25));u.height-=S.height,this.children.splice(++l,0,S),S.parent=this}u.lines=u.lines.slice(0,y),this.maybeSpill()}break}n-=m}},maybeSpill:function(){if(!(this.children.length<=10)){var n=this;do{var i=n.children.splice(n.children.length-5,5),a=new El(i);if(n.parent){n.size-=a.size,n.height-=a.height;var u=ae(n.parent.children,n);n.parent.children.splice(u+1,0,a)}else{var l=new El(n.children);l.parent=n,n.children=[l,a],n=l}a.parent=n.parent}while(n.children.length>10);n.parent.maybeSpill()}},iterN:function(n,i,a){for(var l=0;l<this.children.length;++l){var u=this.children[l],m=u.chunkSize();if(n<m){var y=Math.min(i,m-n);if(u.iterN(n,y,a))return!0;if((i-=y)==0)break;n=0}else n-=m}}};var Al=function(n,i,a){if(a)for(var l in a)a.hasOwnProperty(l)&&(this[l]=a[l]);this.doc=n,this.node=i};Al.prototype.clear=function(){var n=this.doc.cm,i=this.line.widgets,a=this.line,l=A(a);if(!(l==null||!i)){for(var u=0;u<i.length;++u)i[u]==this&&i.splice(u--,1);i.length||(a.widgets=null);var m=pl(this);Qn(a,Math.max(0,a.height-m)),n&&(Wn(n,function(){dm(n,a,-m),Di(n,l,\"widget\")}),Jt(n,\"lineWidgetCleared\",n,this,l))}},Al.prototype.changed=function(){var n=this,i=this.height,a=this.doc.cm,l=this.line;this.height=null;var u=pl(this)-i;u&&(Ii(this.doc,l)||Qn(l,l.height+u),a&&Wn(a,function(){a.curOp.forceUpdate=!0,dm(a,l,u),Jt(a,\"lineWidgetChanged\",a,n,A(l))}))},yr(Al);function dm(n,i,a){si(i)<(n.curOp&&n.curOp.scrollTop||n.doc.scrollTop)&&Bf(n,a)}function Yk(n,i,a,l){var u=new Al(n,a,l),m=n.cm;return m&&u.noHScroll&&(m.display.alignWidgets=!0),Tl(n,i,\"widget\",function(y){var x=y.widgets||(y.widgets=[]);if(u.insertAt==null?x.push(u):x.splice(Math.min(x.length,Math.max(0,u.insertAt)),0,u),u.line=y,m&&!Ii(n,y)){var S=si(y)<n.scrollTop;Qn(y,y.height+pl(u)),S&&Bf(m,u.height),m.curOp.forceUpdate=!0}return!0}),m&&Jt(m,\"lineWidgetAdded\",m,u,typeof i==\"number\"?i:A(i)),u}var hm=0,Wi=function(n,i){this.lines=[],this.type=i,this.doc=n,this.id=++hm};Wi.prototype.clear=function(){if(!this.explicitlyCleared){var n=this.doc.cm,i=n&&!n.curOp;if(i&&Co(n),Bn(this,\"clear\")){var a=this.find();a&&Jt(this,\"clear\",a.from,a.to)}for(var l=null,u=null,m=0;m<this.lines.length;++m){var y=this.lines[m],x=fl(y.markedSpans,this);n&&!this.collapsed?Di(n,A(y),\"text\"):n&&(x.to!=null&&(u=A(y)),x.from!=null&&(l=A(y))),y.markedSpans=B1(y.markedSpans,x),x.from==null&&this.collapsed&&!Ii(this.doc,y)&&n&&Qn(y,as(n.display))}if(n&&this.collapsed&&!n.options.lineWrapping)for(var S=0;S<this.lines.length;++S){var T=Sr(this.lines[S]),H=ec(T);H>n.display.maxLineLength&&(n.display.maxLine=T,n.display.maxLineLength=H,n.display.maxLineChanged=!0)}l!=null&&n&&this.collapsed&&_n(n,l,u+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,n&&nm(n.doc)),n&&Jt(n,\"markerCleared\",n,this,l,u),i&&Eo(n),this.parent&&this.parent.clear()}},Wi.prototype.find=function(n,i){n==null&&this.type==\"bookmark\"&&(n=1);for(var a,l,u=0;u<this.lines.length;++u){var m=this.lines[u],y=fl(m.markedSpans,this);if(y.from!=null&&(a=fe(i?m:A(m),y.from),n==-1))return a;if(y.to!=null&&(l=fe(i?m:A(m),y.to),n==1))return l}return a&&{from:a,to:l}},Wi.prototype.changed=function(){var n=this,i=this.find(-1,!0),a=this,l=this.doc.cm;!i||!l||Wn(l,function(){var u=i.line,m=A(i.line),y=Af(l,m);if(y&&(bg(y),l.curOp.selectionChanged=l.curOp.forceUpdate=!0),l.curOp.updateMaxLine=!0,!Ii(a.doc,u)&&a.height!=null){var x=a.height;a.height=null;var S=pl(a)-x;S&&Qn(u,u.height+S)}Jt(l,\"markerChanged\",l,n)})},Wi.prototype.attachLine=function(n){if(!this.lines.length&&this.doc.cm){var i=this.doc.cm.curOp;(!i.maybeHiddenMarkers||ae(i.maybeHiddenMarkers,this)==-1)&&(i.maybeUnhiddenMarkers||(i.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(n)},Wi.prototype.detachLine=function(n){if(this.lines.splice(ae(this.lines,n),1),!this.lines.length&&this.doc.cm){var i=this.doc.cm.curOp;(i.maybeHiddenMarkers||(i.maybeHiddenMarkers=[])).push(this)}},yr(Wi);function vs(n,i,a,l,u){if(l&&l.shared)return Zk(n,i,a,l,u);if(n.cm&&!n.cm.curOp)return Qt(n.cm,vs)(n,i,a,l,u);var m=new Wi(n,u),y=Ie(i,a);if(l&&Y(l,m,!1),y>0||y==0&&m.clearWhenEmpty!==!1)return m;if(m.replacedWith&&(m.collapsed=!0,m.widgetNode=z(\"span\",[m.replacedWith],\"CodeMirror-widget\"),l.handleMouseEvents||m.widgetNode.setAttribute(\"cm-ignore-events\",\"true\"),l.insertLeft&&(m.widgetNode.insertLeft=!0)),m.collapsed){if(rg(n,i.line,i,a,m)||i.line!=a.line&&rg(n,a.line,i,a,m))throw new Error(\"Inserting collapsed marker partially overlapping an existing one\");H1()}m.addToHistory&&Xg(n,{from:i,to:a,origin:\"markText\"},n.sel,NaN);var x=i.line,S=n.cm,T;if(n.iter(x,a.line+1,function(V){S&&m.collapsed&&!S.options.lineWrapping&&Sr(V)==S.display.maxLine&&(T=!0),m.collapsed&&x!=i.line&&Qn(V,0),W1(V,new Ya(m,x==i.line?i.ch:null,x==a.line?a.ch:null),n.cm&&n.cm.curOp),++x}),m.collapsed&&n.iter(i.line,a.line+1,function(V){Ii(n,V)&&Qn(V,0)}),m.clearOnEnter&&Xe(m,\"beforeCursorEnter\",function(){return m.clear()}),m.readOnly&&(F1(),(n.history.done.length||n.history.undone.length)&&n.clearHistory()),m.collapsed&&(m.id=++hm,m.atomic=!0),S){if(T&&(S.curOp.updateMaxLine=!0),m.collapsed)_n(S,i.line,a.line+1);else if(m.className||m.startStyle||m.endStyle||m.css||m.attributes||m.title)for(var H=i.line;H<=a.line;H++)Di(S,H,\"text\");m.atomic&&nm(S.doc),Jt(S,\"markerAdded\",S,m)}return m}var Ll=function(n,i){this.markers=n,this.primary=i;for(var a=0;a<n.length;++a)n[a].parent=this};Ll.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var n=0;n<this.markers.length;++n)this.markers[n].clear();Jt(this,\"clear\")}},Ll.prototype.find=function(n,i){return this.primary.find(n,i)},yr(Ll);function Zk(n,i,a,l,u){l=Y(l),l.shared=!1;var m=[vs(n,i,a,l,u)],y=m[0],x=l.widgetNode;return Bi(n,function(S){x&&(l.widgetNode=x.cloneNode(!0)),m.push(vs(S,tt(S,i),tt(S,a),l,u));for(var T=0;T<S.linked.length;++T)if(S.linked[T].isParent)return;y=xe(m)}),new Ll(m,y)}function pm(n){return n.findMarks(fe(n.first,0),n.clipPos(fe(n.lastLine())),function(i){return i.parent})}function Jk(n,i){for(var a=0;a<i.length;a++){var l=i[a],u=l.find(),m=n.clipPos(u.from),y=n.clipPos(u.to);if(Ie(m,y)){var x=vs(n,m,y,l.primary,l.primary.type);l.markers.push(x),x.parent=l}}}function Qk(n){for(var i=function(l){var u=n[l],m=[u.primary.doc];Bi(u.primary.doc,function(S){return m.push(S)});for(var y=0;y<u.markers.length;y++){var x=u.markers[y];ae(m,x.doc)==-1&&(x.parent=null,u.markers.splice(y--,1))}},a=0;a<n.length;a++)i(a)}var eS=0,Tn=function(n,i,a,l,u){if(!(this instanceof Tn))return new Tn(n,i,a,l,u);a==null&&(a=0),El.call(this,[new Cl([new os(\"\",null)])]),this.first=a,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1,this.modeFrontier=this.highlightFrontier=a;var m=fe(a,0);this.sel=Fi(m),this.history=new dc(null),this.id=++eS,this.modeOption=i,this.lineSep=l,this.direction=u==\"rtl\"?\"rtl\":\"ltr\",this.extend=!1,typeof n==\"string\"&&(n=this.splitLines(n)),Xf(this,{from:m,to:m,text:n}),un(this,Fi(m),Q)};Tn.prototype=oe(El.prototype,{constructor:Tn,iter:function(n,i,a){a?this.iterN(n-this.first,i-n,a):this.iterN(this.first,this.first+this.size,n)},insert:function(n,i){for(var a=0,l=0;l<i.length;++l)a+=i[l].height;this.insertInner(n-this.first,i,a)},remove:function(n,i){this.removeInner(n-this.first,i)},getValue:function(n){var i=cl(this,this.first,this.first+this.size);return n===!1?i:i.join(n||this.lineSeparator())},setValue:en(function(n){var i=fe(this.first,0),a=this.first+this.size-1;gs(this,{from:i,to:fe(a,qe(this,a).text.length),text:this.splitLines(n),origin:\"setValue\",full:!0},!0),this.cm&&vl(this.cm,0,0),un(this,Fi(i),Q)}),replaceRange:function(n,i,a,l){i=tt(this,i),a=a?tt(this,a):i,ms(this,n,i,a,l)},getRange:function(n,i,a){var l=ii(this,tt(this,n),tt(this,i));return a===!1?l:a===\"\"?l.join(\"\"):l.join(a||this.lineSeparator())},getLine:function(n){var i=this.getLineHandle(n);return i&&i.text},getLineHandle:function(n){if(me(this,n))return qe(this,n)},getLineNumber:function(n){return A(n)},getLineHandleVisualStart:function(n){return typeof n==\"number\"&&(n=qe(this,n)),Sr(n)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(n){return tt(this,n)},getCursor:function(n){var i=this.sel.primary(),a;return n==null||n==\"head\"?a=i.head:n==\"anchor\"?a=i.anchor:n==\"end\"||n==\"to\"||n===!1?a=i.to():a=i.from(),a},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:en(function(n,i,a){Qg(this,tt(this,typeof n==\"number\"?fe(n,i||0):n),null,a)}),setSelection:en(function(n,i,a){Qg(this,tt(this,n),tt(this,i||n),a)}),extendSelection:en(function(n,i,a){pc(this,tt(this,n),i&&tt(this,i),a)}),extendSelections:en(function(n,i){Jg(this,qp(this,n),i)}),extendSelectionsBy:en(function(n,i){var a=ye(this.sel.ranges,n);Jg(this,qp(this,a),i)}),setSelections:en(function(n,i,a){if(n.length){for(var l=[],u=0;u<n.length;u++)l[u]=new gt(tt(this,n[u].anchor),tt(this,n[u].head||n[u].anchor));i==null&&(i=Math.min(n.length-1,this.sel.primIndex)),un(this,Tr(this.cm,l,i),a)}}),addSelection:en(function(n,i,a){var l=this.sel.ranges.slice(0);l.push(new gt(tt(this,n),tt(this,i||n))),un(this,Tr(this.cm,l,l.length-1),a)}),getSelection:function(n){for(var i=this.sel.ranges,a,l=0;l<i.length;l++){var u=ii(this,i[l].from(),i[l].to());a=a?a.concat(u):u}return n===!1?a:a.join(n||this.lineSeparator())},getSelections:function(n){for(var i=[],a=this.sel.ranges,l=0;l<a.length;l++){var u=ii(this,a[l].from(),a[l].to());n!==!1&&(u=u.join(n||this.lineSeparator())),i[l]=u}return i},replaceSelection:function(n,i,a){for(var l=[],u=0;u<this.sel.ranges.length;u++)l[u]=n;this.replaceSelections(l,i,a||\"+input\")},replaceSelections:en(function(n,i,a){for(var l=[],u=this.sel,m=0;m<u.ranges.length;m++){var y=u.ranges[m];l[m]={from:y.from(),to:y.to(),text:this.splitLines(n[m]),origin:a}}for(var x=i&&i!=\"end\"&&Bk(this,l,i),S=l.length-1;S>=0;S--)gs(this,l[S]);x?em(this,x):this.cm&&fs(this.cm)}),undo:en(function(){vc(this,\"undo\")}),redo:en(function(){vc(this,\"redo\")}),undoSelection:en(function(){vc(this,\"undo\",!0)}),redoSelection:en(function(){vc(this,\"redo\",!0)}),setExtending:function(n){this.extend=n},getExtending:function(){return this.extend},historySize:function(){for(var n=this.history,i=0,a=0,l=0;l<n.done.length;l++)n.done[l].ranges||++i;for(var u=0;u<n.undone.length;u++)n.undone[u].ranges||++a;return{undo:i,redo:a}},clearHistory:function(){var n=this;this.history=new dc(this.history),Bi(this,function(i){return i.history=n.history},!0)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(n){return n&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(n){return this.history.generation==(n||this.cleanGeneration)},getHistory:function(){return{done:hs(this.history.done),undone:hs(this.history.undone)}},setHistory:function(n){var i=this.history=new dc(this.history);i.done=hs(n.done.slice(0),null,!0),i.undone=hs(n.undone.slice(0),null,!0)},setGutterMarker:en(function(n,i,a){return Tl(this,n,\"gutter\",function(l){var u=l.gutterMarkers||(l.gutterMarkers={});return u[i]=a,!a&&dt(u)&&(l.gutterMarkers=null),!0})}),clearGutter:en(function(n){var i=this;this.iter(function(a){a.gutterMarkers&&a.gutterMarkers[n]&&Tl(i,a,\"gutter\",function(){return a.gutterMarkers[n]=null,dt(a.gutterMarkers)&&(a.gutterMarkers=null),!0})})}),lineInfo:function(n){var i;if(typeof n==\"number\"){if(!me(this,n)||(i=n,n=qe(this,n),!n))return null}else if(i=A(n),i==null)return null;return{line:i,handle:n,text:n.text,gutterMarkers:n.gutterMarkers,textClass:n.textClass,bgClass:n.bgClass,wrapClass:n.wrapClass,widgets:n.widgets}},addLineClass:en(function(n,i,a){return Tl(this,n,i==\"gutter\"?\"gutter\":\"class\",function(l){var u=i==\"text\"?\"textClass\":i==\"background\"?\"bgClass\":i==\"gutter\"?\"gutterClass\":\"wrapClass\";if(!l[u])l[u]=a;else{if(j(a).test(l[u]))return!1;l[u]+=\" \"+a}return!0})}),removeLineClass:en(function(n,i,a){return Tl(this,n,i==\"gutter\"?\"gutter\":\"class\",function(l){var u=i==\"text\"?\"textClass\":i==\"background\"?\"bgClass\":i==\"gutter\"?\"gutterClass\":\"wrapClass\",m=l[u];if(m)if(a==null)l[u]=null;else{var y=m.match(j(a));if(!y)return!1;var x=y.index+y[0].length;l[u]=m.slice(0,y.index)+(!y.index||x==m.length?\"\":\" \")+m.slice(x)||null}else return!1;return!0})}),addLineWidget:en(function(n,i,a){return Yk(this,n,i,a)}),removeLineWidget:function(n){n.clear()},markText:function(n,i,a){return vs(this,tt(this,n),tt(this,i),a,a&&a.type||\"range\")},setBookmark:function(n,i){var a={replacedWith:i&&(i.nodeType==null?i.widget:i),insertLeft:i&&i.insertLeft,clearWhenEmpty:!1,shared:i&&i.shared,handleMouseEvents:i&&i.handleMouseEvents};return n=tt(this,n),vs(this,n,n,a,\"bookmark\")},findMarksAt:function(n){n=tt(this,n);var i=[],a=qe(this,n.line).markedSpans;if(a)for(var l=0;l<a.length;++l){var u=a[l];(u.from==null||u.from<=n.ch)&&(u.to==null||u.to>=n.ch)&&i.push(u.marker.parent||u.marker)}return i},findMarks:function(n,i,a){n=tt(this,n),i=tt(this,i);var l=[],u=n.line;return this.iter(n.line,i.line+1,function(m){var y=m.markedSpans;if(y)for(var x=0;x<y.length;x++){var S=y[x];!(S.to!=null&&u==n.line&&n.ch>=S.to||S.from==null&&u!=n.line||S.from!=null&&u==i.line&&S.from>=i.ch)&&(!a||a(S.marker))&&l.push(S.marker.parent||S.marker)}++u}),l},getAllMarks:function(){var n=[];return this.iter(function(i){var a=i.markedSpans;if(a)for(var l=0;l<a.length;++l)a[l].from!=null&&n.push(a[l].marker)}),n},posFromIndex:function(n){var i,a=this.first,l=this.lineSeparator().length;return this.iter(function(u){var m=u.text.length+l;if(m>n)return i=n,!0;n-=m,++a}),tt(this,fe(a,i))},indexFromPos:function(n){n=tt(this,n);var i=n.ch;if(n.line<this.first||n.ch<0)return 0;var a=this.lineSeparator().length;return this.iter(this.first,n.line,function(l){i+=l.text.length+a}),i},copy:function(n){var i=new Tn(cl(this,this.first,this.first+this.size),this.modeOption,this.first,this.lineSep,this.direction);return i.scrollTop=this.scrollTop,i.scrollLeft=this.scrollLeft,i.sel=this.sel,i.extend=!1,n&&(i.history.undoDepth=this.history.undoDepth,i.setHistory(this.getHistory())),i},linkedDoc:function(n){n||(n={});var i=this.first,a=this.first+this.size;n.from!=null&&n.from>i&&(i=n.from),n.to!=null&&n.to<a&&(a=n.to);var l=new Tn(cl(this,i,a),n.mode||this.modeOption,i,this.lineSep,this.direction);return n.sharedHist&&(l.history=this.history),(this.linked||(this.linked=[])).push({doc:l,sharedHist:n.sharedHist}),l.linked=[{doc:this,isParent:!0,sharedHist:n.sharedHist}],Jk(l,pm(this)),l},unlinkDoc:function(n){if(n instanceof Ct&&(n=n.doc),this.linked)for(var i=0;i<this.linked.length;++i){var a=this.linked[i];if(a.doc==n){this.linked.splice(i,1),n.unlinkDoc(this),Qk(pm(this));break}}if(n.history==this.history){var l=[n.id];Bi(n,function(u){return l.push(u.id)},!0),n.history=new dc(null),n.history.done=hs(this.history.done,l),n.history.undone=hs(this.history.undone,l)}},iterLinkedDocs:function(n){Bi(this,n)},getMode:function(){return this.mode},getEditor:function(){return this.cm},splitLines:function(n){return this.lineSep?n.split(this.lineSep):cr(n)},lineSeparator:function(){return this.lineSep||`\n`},setDirection:en(function(n){n!=\"rtl\"&&(n=\"ltr\"),n!=this.direction&&(this.direction=n,this.iter(function(i){return i.order=null}),this.cm&&Wk(this.cm))})}),Tn.prototype.eachLine=Tn.prototype.iter;var gm=0;function tS(n){var i=this;if(mm(i),!(Rt(i,n)||li(i.display,n))){cn(n),h&&(gm=+new Date);var a=ko(i,n,!0),l=n.dataTransfer.files;if(!(!a||i.isReadOnly()))if(l&&l.length&&window.FileReader&&window.File)for(var u=l.length,m=Array(u),y=0,x=function(){++y==u&&Qt(i,function(){a=tt(i.doc,a);var te={from:a,to:a,text:i.doc.splitLines(m.filter(function(pe){return pe!=null}).join(i.doc.lineSeparator())),origin:\"paste\"};gs(i.doc,te),em(i.doc,Fi(tt(i.doc,a),tt(i.doc,Hi(te))))})()},S=function(te,pe){if(i.options.allowDropFileTypes&&ae(i.options.allowDropFileTypes,te.type)==-1){x();return}var we=new FileReader;we.onerror=function(){return x()},we.onload=function(){var Te=we.result;if(/[\\x00-\\x08\\x0e-\\x1f]{2}/.test(Te)){x();return}m[pe]=Te,x()},we.readAsText(te)},T=0;T<l.length;T++)S(l[T],T);else{if(i.state.draggingText&&i.doc.sel.contains(a)>-1){i.state.draggingText(n),setTimeout(function(){return i.display.input.focus()},20);return}try{var H=n.dataTransfer.getData(\"Text\");if(H){var V;if(i.state.draggingText&&!i.state.draggingText.copy&&(V=i.listSelections()),gc(i.doc,Fi(a,a)),V)for(var se=0;se<V.length;++se)ms(i.doc,\"\",V[se].anchor,V[se].head,\"drag\");i.replaceSelection(H,\"around\",\"paste\"),i.display.input.focus()}}catch{}}}}function nS(n,i){if(h&&(!n.state.draggingText||+new Date-gm<100)){Oi(i);return}if(!(Rt(n,i)||li(n.display,i))&&(i.dataTransfer.setData(\"Text\",n.getSelection()),i.dataTransfer.effectAllowed=\"copyMove\",i.dataTransfer.setDragImage&&!L)){var a=k(\"img\",null,null,\"position: fixed; left: 0; top: 0;\");a.src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\",E&&(a.width=a.height=1,n.display.wrapper.appendChild(a),a._top=a.offsetTop),i.dataTransfer.setDragImage(a,0,0),E&&a.parentNode.removeChild(a)}}function rS(n,i){var a=ko(n,i);if(a){var l=document.createDocumentFragment();If(n,a,l),n.display.dragCursor||(n.display.dragCursor=k(\"div\",null,\"CodeMirror-cursors CodeMirror-dragcursors\"),n.display.lineSpace.insertBefore(n.display.dragCursor,n.display.cursorDiv)),C(n.display.dragCursor,l)}}function mm(n){n.display.dragCursor&&(n.display.lineSpace.removeChild(n.display.dragCursor),n.display.dragCursor=null)}function vm(n){if(document.getElementsByClassName){for(var i=document.getElementsByClassName(\"CodeMirror\"),a=[],l=0;l<i.length;l++){var u=i[l].CodeMirror;u&&a.push(u)}a.length&&a[0].operation(function(){for(var m=0;m<a.length;m++)n(a[m])})}}var ym=!1;function iS(){ym||(oS(),ym=!0)}function oS(){var n;Xe(window,\"resize\",function(){n==null&&(n=setTimeout(function(){n=null,vm(sS)},100))}),Xe(window,\"blur\",function(){return vm(us)})}function sS(n){var i=n.display;i.cachedCharWidth=i.cachedTextHeight=i.cachedPaddingH=null,i.scrollbarsClipped=!1,n.setSize()}for(var qi={3:\"Pause\",8:\"Backspace\",9:\"Tab\",13:\"Enter\",16:\"Shift\",17:\"Ctrl\",18:\"Alt\",19:\"Pause\",20:\"CapsLock\",27:\"Esc\",32:\"Space\",33:\"PageUp\",34:\"PageDown\",35:\"End\",36:\"Home\",37:\"Left\",38:\"Up\",39:\"Right\",40:\"Down\",44:\"PrintScrn\",45:\"Insert\",46:\"Delete\",59:\";\",61:\"=\",91:\"Mod\",92:\"Mod\",93:\"Mod\",106:\"*\",107:\"=\",109:\"-\",110:\".\",111:\"/\",145:\"ScrollLock\",173:\"-\",186:\";\",187:\"=\",188:\",\",189:\"-\",190:\".\",191:\"/\",192:\"`\",219:\"[\",220:\"\\\\\",221:\"]\",222:\"'\",224:\"Mod\",63232:\"Up\",63233:\"Down\",63234:\"Left\",63235:\"Right\",63272:\"Delete\",63273:\"Home\",63275:\"End\",63276:\"PageUp\",63277:\"PageDown\",63302:\"Insert\"},Ml=0;Ml<10;Ml++)qi[Ml+48]=qi[Ml+96]=String(Ml);for(var yc=65;yc<=90;yc++)qi[yc]=String.fromCharCode(yc);for(var Nl=1;Nl<=12;Nl++)qi[Nl+111]=qi[Nl+63235]=\"F\"+Nl;var ci={};ci.basic={Left:\"goCharLeft\",Right:\"goCharRight\",Up:\"goLineUp\",Down:\"goLineDown\",End:\"goLineEnd\",Home:\"goLineStartSmart\",PageUp:\"goPageUp\",PageDown:\"goPageDown\",Delete:\"delCharAfter\",Backspace:\"delCharBefore\",\"Shift-Backspace\":\"delCharBefore\",Tab:\"defaultTab\",\"Shift-Tab\":\"indentAuto\",Enter:\"newlineAndIndent\",Insert:\"toggleOverwrite\",Esc:\"singleSelection\"},ci.pcDefault={\"Ctrl-A\":\"selectAll\",\"Ctrl-D\":\"deleteLine\",\"Ctrl-Z\":\"undo\",\"Shift-Ctrl-Z\":\"redo\",\"Ctrl-Y\":\"redo\",\"Ctrl-Home\":\"goDocStart\",\"Ctrl-End\":\"goDocEnd\",\"Ctrl-Up\":\"goLineUp\",\"Ctrl-Down\":\"goLineDown\",\"Ctrl-Left\":\"goGroupLeft\",\"Ctrl-Right\":\"goGroupRight\",\"Alt-Left\":\"goLineStart\",\"Alt-Right\":\"goLineEnd\",\"Ctrl-Backspace\":\"delGroupBefore\",\"Ctrl-Delete\":\"delGroupAfter\",\"Ctrl-S\":\"save\",\"Ctrl-F\":\"find\",\"Ctrl-G\":\"findNext\",\"Shift-Ctrl-G\":\"findPrev\",\"Shift-Ctrl-F\":\"replace\",\"Shift-Ctrl-R\":\"replaceAll\",\"Ctrl-[\":\"indentLess\",\"Ctrl-]\":\"indentMore\",\"Ctrl-U\":\"undoSelection\",\"Shift-Ctrl-U\":\"redoSelection\",\"Alt-U\":\"redoSelection\",fallthrough:\"basic\"},ci.emacsy={\"Ctrl-F\":\"goCharRight\",\"Ctrl-B\":\"goCharLeft\",\"Ctrl-P\":\"goLineUp\",\"Ctrl-N\":\"goLineDown\",\"Ctrl-A\":\"goLineStart\",\"Ctrl-E\":\"goLineEnd\",\"Ctrl-V\":\"goPageDown\",\"Shift-Ctrl-V\":\"goPageUp\",\"Ctrl-D\":\"delCharAfter\",\"Ctrl-H\":\"delCharBefore\",\"Alt-Backspace\":\"delWordBefore\",\"Ctrl-K\":\"killLine\",\"Ctrl-T\":\"transposeChars\",\"Ctrl-O\":\"openLine\"},ci.macDefault={\"Cmd-A\":\"selectAll\",\"Cmd-D\":\"deleteLine\",\"Cmd-Z\":\"undo\",\"Shift-Cmd-Z\":\"redo\",\"Cmd-Y\":\"redo\",\"Cmd-Home\":\"goDocStart\",\"Cmd-Up\":\"goDocStart\",\"Cmd-End\":\"goDocEnd\",\"Cmd-Down\":\"goDocEnd\",\"Alt-Left\":\"goGroupLeft\",\"Alt-Right\":\"goGroupRight\",\"Cmd-Left\":\"goLineLeft\",\"Cmd-Right\":\"goLineRight\",\"Alt-Backspace\":\"delGroupBefore\",\"Ctrl-Alt-Backspace\":\"delGroupAfter\",\"Alt-Delete\":\"delGroupAfter\",\"Cmd-S\":\"save\",\"Cmd-F\":\"find\",\"Cmd-G\":\"findNext\",\"Shift-Cmd-G\":\"findPrev\",\"Cmd-Alt-F\":\"replace\",\"Shift-Cmd-Alt-F\":\"replaceAll\",\"Cmd-[\":\"indentLess\",\"Cmd-]\":\"indentMore\",\"Cmd-Backspace\":\"delWrappedLineLeft\",\"Cmd-Delete\":\"delWrappedLineRight\",\"Cmd-U\":\"undoSelection\",\"Shift-Cmd-U\":\"redoSelection\",\"Ctrl-Up\":\"goDocStart\",\"Ctrl-Down\":\"goDocEnd\",fallthrough:[\"basic\",\"emacsy\"]},ci.default=$?ci.macDefault:ci.pcDefault;function lS(n){var i=n.split(/-(?!$)/);n=i[i.length-1];for(var a,l,u,m,y=0;y<i.length-1;y++){var x=i[y];if(/^(cmd|meta|m)$/i.test(x))m=!0;else if(/^a(lt)?$/i.test(x))a=!0;else if(/^(c|ctrl|control)$/i.test(x))l=!0;else if(/^s(hift)?$/i.test(x))u=!0;else throw new Error(\"Unrecognized modifier name: \"+x)}return a&&(n=\"Alt-\"+n),l&&(n=\"Ctrl-\"+n),m&&(n=\"Cmd-\"+n),u&&(n=\"Shift-\"+n),n}function aS(n){var i={};for(var a in n)if(n.hasOwnProperty(a)){var l=n[a];if(/^(name|fallthrough|(de|at)tach)$/.test(a))continue;if(l==\"...\"){delete n[a];continue}for(var u=ye(a.split(\" \"),lS),m=0;m<u.length;m++){var y=void 0,x=void 0;m==u.length-1?(x=u.join(\" \"),y=l):(x=u.slice(0,m+1).join(\" \"),y=\"...\");var S=i[x];if(!S)i[x]=y;else if(S!=y)throw new Error(\"Inconsistent bindings for \"+x)}delete n[a]}for(var T in i)n[T]=i[T];return n}function ys(n,i,a,l){i=bc(i);var u=i.call?i.call(n,l):i[n];if(u===!1)return\"nothing\";if(u===\"...\")return\"multi\";if(u!=null&&a(u))return\"handled\";if(i.fallthrough){if(Object.prototype.toString.call(i.fallthrough)!=\"[object Array]\")return ys(n,i.fallthrough,a,l);for(var m=0;m<i.fallthrough.length;m++){var y=ys(n,i.fallthrough[m],a,l);if(y)return y}}}function bm(n){var i=typeof n==\"string\"?n:qi[n.keyCode];return i==\"Ctrl\"||i==\"Alt\"||i==\"Shift\"||i==\"Mod\"}function wm(n,i,a){var l=n;return i.altKey&&l!=\"Alt\"&&(n=\"Alt-\"+n),(Z?i.metaKey:i.ctrlKey)&&l!=\"Ctrl\"&&(n=\"Ctrl-\"+n),(Z?i.ctrlKey:i.metaKey)&&l!=\"Mod\"&&(n=\"Cmd-\"+n),!a&&i.shiftKey&&l!=\"Shift\"&&(n=\"Shift-\"+n),n}function xm(n,i){if(E&&n.keyCode==34&&n.char)return!1;var a=qi[n.keyCode];return a==null||n.altGraphKey?!1:(n.keyCode==3&&n.code&&(a=n.code),wm(a,n,i))}function bc(n){return typeof n==\"string\"?ci[n]:n}function bs(n,i){for(var a=n.doc.sel.ranges,l=[],u=0;u<a.length;u++){for(var m=i(a[u]);l.length&&Ie(m.from,xe(l).to)<=0;){var y=l.pop();if(Ie(y.from,m.from)<0){m.from=y.from;break}}l.push(m)}Wn(n,function(){for(var x=l.length-1;x>=0;x--)ms(n.doc,\"\",l[x].from,l[x].to,\"+delete\");fs(n)})}function Qf(n,i,a){var l=Yt(n.text,i+a,a);return l<0||l>n.text.length?null:l}function ed(n,i,a){var l=Qf(n,i.ch,a);return l==null?null:new fe(i.line,l,a<0?\"after\":\"before\")}function td(n,i,a,l,u){if(n){i.doc.direction==\"rtl\"&&(u=-u);var m=lt(a,i.doc.direction);if(m){var y=u<0?xe(m):m[0],x=u<0==(y.level==1),S=x?\"after\":\"before\",T;if(y.level>0||i.doc.direction==\"rtl\"){var H=ls(i,a);T=u<0?a.text.length-1:0;var V=jr(i,H,T).top;T=jt(function(se){return jr(i,H,se).top==V},u<0==(y.level==1)?y.from:y.to-1,T),S==\"before\"&&(T=Qf(a,T,1))}else T=u<0?y.to:y.from;return new fe(l,T,S)}}return new fe(l,u<0?a.text.length:0,u<0?\"before\":\"after\")}function cS(n,i,a,l){var u=lt(i,n.doc.direction);if(!u)return ed(i,a,l);a.ch>=i.text.length?(a.ch=i.text.length,a.sticky=\"before\"):a.ch<=0&&(a.ch=0,a.sticky=\"after\");var m=Bt(u,a.ch,a.sticky),y=u[m];if(n.doc.direction==\"ltr\"&&y.level%2==0&&(l>0?y.to>a.ch:y.from<a.ch))return ed(i,a,l);var x=function(Le,De){return Qf(i,Le instanceof fe?Le.ch:Le,De)},S,T=function(Le){return n.options.lineWrapping?(S=S||ls(n,i),Cg(n,i,S,Le)):{begin:0,end:i.text.length}},H=T(a.sticky==\"before\"?x(a,-1):a.ch);if(n.doc.direction==\"rtl\"||y.level==1){var V=y.level==1==l<0,se=x(a,V?1:-1);if(se!=null&&(V?se<=y.to&&se<=H.end:se>=y.from&&se>=H.begin)){var te=V?\"before\":\"after\";return new fe(a.line,se,te)}}var pe=function(Le,De,Me){for(var ze=function(St,tn){return tn?new fe(a.line,x(St,1),\"before\"):new fe(a.line,St,\"after\")};Le>=0&&Le<u.length;Le+=De){var Ye=u[Le],Ue=De>0==(Ye.level!=1),st=Ue?Me.begin:x(Me.end,-1);if(Ye.from<=st&&st<Ye.to||(st=Ue?Ye.from:x(Ye.to,-1),Me.begin<=st&&st<Me.end))return ze(st,Ue)}},we=pe(m+l,l,H);if(we)return we;var Te=l>0?H.end:x(H.begin,-1);return Te!=null&&!(l>0&&Te==i.text.length)&&(we=pe(l>0?0:u.length-1,l,T(Te)),we)?we:null}var Ol={selectAll:om,singleSelection:function(n){return n.setSelection(n.getCursor(\"anchor\"),n.getCursor(\"head\"),Q)},killLine:function(n){return bs(n,function(i){if(i.empty()){var a=qe(n.doc,i.head.line).text.length;return i.head.ch==a&&i.head.line<n.lastLine()?{from:i.head,to:fe(i.head.line+1,0)}:{from:i.head,to:fe(i.head.line,a)}}else return{from:i.from(),to:i.to()}})},deleteLine:function(n){return bs(n,function(i){return{from:fe(i.from().line,0),to:tt(n.doc,fe(i.to().line+1,0))}})},delLineLeft:function(n){return bs(n,function(i){return{from:fe(i.from().line,0),to:i.from()}})},delWrappedLineLeft:function(n){return bs(n,function(i){var a=n.charCoords(i.head,\"div\").top+5,l=n.coordsChar({left:0,top:a},\"div\");return{from:l,to:i.from()}})},delWrappedLineRight:function(n){return bs(n,function(i){var a=n.charCoords(i.head,\"div\").top+5,l=n.coordsChar({left:n.display.lineDiv.offsetWidth+100,top:a},\"div\");return{from:i.from(),to:l}})},undo:function(n){return n.undo()},redo:function(n){return n.redo()},undoSelection:function(n){return n.undoSelection()},redoSelection:function(n){return n.redoSelection()},goDocStart:function(n){return n.extendSelection(fe(n.firstLine(),0))},goDocEnd:function(n){return n.extendSelection(fe(n.lastLine()))},goLineStart:function(n){return n.extendSelectionsBy(function(i){return km(n,i.head.line)},{origin:\"+move\",bias:1})},goLineStartSmart:function(n){return n.extendSelectionsBy(function(i){return Sm(n,i.head)},{origin:\"+move\",bias:1})},goLineEnd:function(n){return n.extendSelectionsBy(function(i){return uS(n,i.head.line)},{origin:\"+move\",bias:-1})},goLineRight:function(n){return n.extendSelectionsBy(function(i){var a=n.cursorCoords(i.head,\"div\").top+5;return n.coordsChar({left:n.display.lineDiv.offsetWidth+100,top:a},\"div\")},de)},goLineLeft:function(n){return n.extendSelectionsBy(function(i){var a=n.cursorCoords(i.head,\"div\").top+5;return n.coordsChar({left:0,top:a},\"div\")},de)},goLineLeftSmart:function(n){return n.extendSelectionsBy(function(i){var a=n.cursorCoords(i.head,\"div\").top+5,l=n.coordsChar({left:0,top:a},\"div\");return l.ch<n.getLine(l.line).search(/\\S/)?Sm(n,i.head):l},de)},goLineUp:function(n){return n.moveV(-1,\"line\")},goLineDown:function(n){return n.moveV(1,\"line\")},goPageUp:function(n){return n.moveV(-1,\"page\")},goPageDown:function(n){return n.moveV(1,\"page\")},goCharLeft:function(n){return n.moveH(-1,\"char\")},goCharRight:function(n){return n.moveH(1,\"char\")},goColumnLeft:function(n){return n.moveH(-1,\"column\")},goColumnRight:function(n){return n.moveH(1,\"column\")},goWordLeft:function(n){return n.moveH(-1,\"word\")},goGroupRight:function(n){return n.moveH(1,\"group\")},goGroupLeft:function(n){return n.moveH(-1,\"group\")},goWordRight:function(n){return n.moveH(1,\"word\")},delCharBefore:function(n){return n.deleteH(-1,\"codepoint\")},delCharAfter:function(n){return n.deleteH(1,\"char\")},delWordBefore:function(n){return n.deleteH(-1,\"word\")},delWordAfter:function(n){return n.deleteH(1,\"word\")},delGroupBefore:function(n){return n.deleteH(-1,\"group\")},delGroupAfter:function(n){return n.deleteH(1,\"group\")},indentAuto:function(n){return n.indentSelection(\"smart\")},indentMore:function(n){return n.indentSelection(\"add\")},indentLess:function(n){return n.indentSelection(\"subtract\")},insertTab:function(n){return n.replaceSelection(\"\t\")},insertSoftTab:function(n){for(var i=[],a=n.listSelections(),l=n.options.tabSize,u=0;u<a.length;u++){var m=a[u].from(),y=re(n.getLine(m.line),m.ch,l);i.push(Ee(l-y%l))}n.replaceSelections(i)},defaultTab:function(n){n.somethingSelected()?n.indentSelection(\"add\"):n.execCommand(\"insertTab\")},transposeChars:function(n){return Wn(n,function(){for(var i=n.listSelections(),a=[],l=0;l<i.length;l++)if(i[l].empty()){var u=i[l].head,m=qe(n.doc,u.line).text;if(m){if(u.ch==m.length&&(u=new fe(u.line,u.ch-1)),u.ch>0)u=new fe(u.line,u.ch+1),n.replaceRange(m.charAt(u.ch-1)+m.charAt(u.ch-2),fe(u.line,u.ch-2),u,\"+transpose\");else if(u.line>n.doc.first){var y=qe(n.doc,u.line-1).text;y&&(u=new fe(u.line,1),n.replaceRange(m.charAt(0)+n.doc.lineSeparator()+y.charAt(y.length-1),fe(u.line-1,y.length-1),u,\"+transpose\"))}}a.push(new gt(u,u))}n.setSelections(a)})},newlineAndIndent:function(n){return Wn(n,function(){for(var i=n.listSelections(),a=i.length-1;a>=0;a--)n.replaceRange(n.doc.lineSeparator(),i[a].anchor,i[a].head,\"+input\");i=n.listSelections();for(var l=0;l<i.length;l++)n.indentLine(i[l].from().line,null,!0);fs(n)})},openLine:function(n){return n.replaceSelection(`\n`,\"start\")},toggleOverwrite:function(n){return n.toggleOverwrite()}};function km(n,i){var a=qe(n.doc,i),l=Sr(a);return l!=a&&(i=A(l)),td(!0,n,l,i,1)}function uS(n,i){var a=qe(n.doc,i),l=G1(a);return l!=a&&(i=A(l)),td(!0,n,a,i,-1)}function Sm(n,i){var a=km(n,i.line),l=qe(n.doc,a.line),u=lt(l,n.doc.direction);if(!u||u[0].level==0){var m=Math.max(a.ch,l.text.search(/\\S/)),y=i.line==a.line&&i.ch<=m&&i.ch;return fe(a.line,y?0:m,a.sticky)}return a}function wc(n,i,a){if(typeof i==\"string\"&&(i=Ol[i],!i))return!1;n.display.input.ensurePolled();var l=n.display.shift,u=!1;try{n.isReadOnly()&&(n.state.suppressEdits=!0),a&&(n.display.shift=!1),u=i(n)!=q}finally{n.display.shift=l,n.state.suppressEdits=!1}return u}function fS(n,i,a){for(var l=0;l<n.state.keyMaps.length;l++){var u=ys(i,n.state.keyMaps[l],a,n);if(u)return u}return n.options.extraKeys&&ys(i,n.options.extraKeys,a,n)||ys(i,n.options.keyMap,a,n)}var dS=new le;function Pl(n,i,a,l){var u=n.state.keySeq;if(u){if(bm(i))return\"handled\";if(/\\'$/.test(i)?n.state.keySeq=null:dS.set(50,function(){n.state.keySeq==u&&(n.state.keySeq=null,n.display.input.reset())}),_m(n,u+\" \"+i,a,l))return!0}return _m(n,i,a,l)}function _m(n,i,a,l){var u=fS(n,i,l);return u==\"multi\"&&(n.state.keySeq=i),u==\"handled\"&&Jt(n,\"keyHandled\",n,i,a),(u==\"handled\"||u==\"multi\")&&(cn(a),Df(n)),!!u}function Tm(n,i){var a=xm(i,!0);return a?i.shiftKey&&!n.state.keySeq?Pl(n,\"Shift-\"+a,i,function(l){return wc(n,l,!0)})||Pl(n,a,i,function(l){if(typeof l==\"string\"?/^go[A-Z]/.test(l):l.motion)return wc(n,l)}):Pl(n,a,i,function(l){return wc(n,l)}):!1}function hS(n,i,a){return Pl(n,\"'\"+a+\"'\",i,function(l){return wc(n,l,!0)})}var nd=null;function Cm(n){var i=this;if(!(n.target&&n.target!=i.display.input.getField())&&(i.curOp.focus=be(je(i)),!Rt(i,n))){h&&p<11&&n.keyCode==27&&(n.returnValue=!1);var a=n.keyCode;i.display.shift=a==16||n.shiftKey;var l=Tm(i,n);E&&(nd=l?a:null,!l&&a==88&&!Ka&&($?n.metaKey:n.ctrlKey)&&i.replaceSelection(\"\",null,\"cut\")),s&&!$&&!l&&a==46&&n.shiftKey&&!n.ctrlKey&&document.execCommand&&document.execCommand(\"cut\"),a==18&&!/\\bCodeMirror-crosshair\\b/.test(i.display.lineDiv.className)&&pS(i)}}function pS(n){var i=n.display.lineDiv;Se(i,\"CodeMirror-crosshair\");function a(l){(l.keyCode==18||!l.altKey)&&(N(i,\"CodeMirror-crosshair\"),an(document,\"keyup\",a),an(document,\"mouseover\",a))}Xe(document,\"keyup\",a),Xe(document,\"mouseover\",a)}function Em(n){n.keyCode==16&&(this.doc.sel.shift=!1),Rt(this,n)}function Am(n){var i=this;if(!(n.target&&n.target!=i.display.input.getField())&&!(li(i.display,n)||Rt(i,n)||n.ctrlKey&&!n.altKey||$&&n.metaKey)){var a=n.keyCode,l=n.charCode;if(E&&a==nd){nd=null,cn(n);return}if(!(E&&(!n.which||n.which<10)&&Tm(i,n))){var u=String.fromCharCode(l??a);u!=\"\\b\"&&(hS(i,n,u)||i.display.input.onKeyPress(n))}}}var gS=400,rd=function(n,i,a){this.time=n,this.pos=i,this.button=a};rd.prototype.compare=function(n,i,a){return this.time+gS>n&&Ie(i,this.pos)==0&&a==this.button};var Rl,$l;function mS(n,i){var a=+new Date;return $l&&$l.compare(a,n,i)?(Rl=$l=null,\"triple\"):Rl&&Rl.compare(a,n,i)?($l=new rd(a,n,i),Rl=null,\"double\"):(Rl=new rd(a,n,i),$l=null,\"single\")}function Lm(n){var i=this,a=i.display;if(!(Rt(i,n)||a.activeTouch&&a.input.supportsTouch())){if(a.input.ensurePolled(),a.shift=n.shiftKey,li(a,n)){g||(a.scroller.draggable=!1,setTimeout(function(){return a.scroller.draggable=!0},100));return}if(!id(i,n)){var l=ko(i,n),u=br(n),m=l?mS(l,u):\"single\";Pe(i).focus(),u==1&&i.state.selectingText&&i.state.selectingText(n),!(l&&vS(i,u,l,m,n))&&(u==1?l?bS(i,l,m,n):sl(n)==a.scroller&&cn(n):u==2?(l&&pc(i.doc,l),setTimeout(function(){return a.input.focus()},20)):u==3&&(G?i.display.input.onContextMenu(n):zf(i)))}}}function vS(n,i,a,l,u){var m=\"Click\";return l==\"double\"?m=\"Double\"+m:l==\"triple\"&&(m=\"Triple\"+m),m=(i==1?\"Left\":i==2?\"Middle\":\"Right\")+m,Pl(n,wm(m,u),u,function(y){if(typeof y==\"string\"&&(y=Ol[y]),!y)return!1;var x=!1;try{n.isReadOnly()&&(n.state.suppressEdits=!0),x=y(n,a)!=q}finally{n.state.suppressEdits=!1}return x})}function yS(n,i,a){var l=n.getOption(\"configureMouse\"),u=l?l(n,i,a):{};if(u.unit==null){var m=W?a.shiftKey&&a.metaKey:a.altKey;u.unit=m?\"rectangle\":i==\"single\"?\"char\":i==\"double\"?\"word\":\"line\"}return(u.extend==null||n.doc.extend)&&(u.extend=n.doc.extend||a.shiftKey),u.addNew==null&&(u.addNew=$?a.metaKey:a.ctrlKey),u.moveOnDrag==null&&(u.moveOnDrag=!($?a.altKey:a.ctrlKey)),u}function bS(n,i,a,l){h?setTimeout(F(Mg,n),0):n.curOp.focus=be(je(n));var u=yS(n,a,l),m=n.doc.sel,y;n.options.dragDrop&&mf&&!n.isReadOnly()&&a==\"single\"&&(y=m.contains(i))>-1&&(Ie((y=m.ranges[y]).from(),i)<0||i.xRel>0)&&(Ie(y.to(),i)>0||i.xRel<0)?wS(n,l,i,u):xS(n,l,i,u)}function wS(n,i,a,l){var u=n.display,m=!1,y=Qt(n,function(T){g&&(u.scroller.draggable=!1),n.state.draggingText=!1,n.state.delayingBlurEvent&&(n.hasFocus()?n.state.delayingBlurEvent=!1:zf(n)),an(u.wrapper.ownerDocument,\"mouseup\",y),an(u.wrapper.ownerDocument,\"mousemove\",x),an(u.scroller,\"dragstart\",S),an(u.scroller,\"drop\",y),m||(cn(T),l.addNew||pc(n.doc,a,null,null,l.extend),g&&!L||h&&p==9?setTimeout(function(){u.wrapper.ownerDocument.body.focus({preventScroll:!0}),u.input.focus()},20):u.input.focus())}),x=function(T){m=m||Math.abs(i.clientX-T.clientX)+Math.abs(i.clientY-T.clientY)>=10},S=function(){return m=!0};g&&(u.scroller.draggable=!0),n.state.draggingText=y,y.copy=!l.moveOnDrag,Xe(u.wrapper.ownerDocument,\"mouseup\",y),Xe(u.wrapper.ownerDocument,\"mousemove\",x),Xe(u.scroller,\"dragstart\",S),Xe(u.scroller,\"drop\",y),n.state.delayingBlurEvent=!0,setTimeout(function(){return u.input.focus()},20),u.scroller.dragDrop&&u.scroller.dragDrop()}function Mm(n,i,a){if(a==\"char\")return new gt(i,i);if(a==\"word\")return n.findWordAt(i);if(a==\"line\")return new gt(fe(i.line,0),tt(n.doc,fe(i.line+1,0)));var l=a(n,i);return new gt(l.from,l.to)}function xS(n,i,a,l){h&&zf(n);var u=n.display,m=n.doc;cn(i);var y,x,S=m.sel,T=S.ranges;if(l.addNew&&!l.extend?(x=m.sel.contains(a),x>-1?y=T[x]:y=new gt(a,a)):(y=m.sel.primary(),x=m.sel.primIndex),l.unit==\"rectangle\")l.addNew||(y=new gt(a,a)),a=ko(n,i,!0,!0),x=-1;else{var H=Mm(n,a,l.unit);l.extend?y=Zf(y,H.anchor,H.head,l.extend):y=H}l.addNew?x==-1?(x=T.length,un(m,Tr(n,T.concat([y]),x),{scroll:!1,origin:\"*mouse\"})):T.length>1&&T[x].empty()&&l.unit==\"char\"&&!l.extend?(un(m,Tr(n,T.slice(0,x).concat(T.slice(x+1)),0),{scroll:!1,origin:\"*mouse\"}),S=m.sel):Jf(m,x,y,he):(x=0,un(m,new er([y],0),he),S=m.sel);var V=a;function se(Me){if(Ie(V,Me)!=0)if(V=Me,l.unit==\"rectangle\"){for(var ze=[],Ye=n.options.tabSize,Ue=re(qe(m,a.line).text,a.ch,Ye),st=re(qe(m,Me.line).text,Me.ch,Ye),St=Math.min(Ue,st),tn=Math.max(Ue,st),Ot=Math.min(a.line,Me.line),qn=Math.min(n.lastLine(),Math.max(a.line,Me.line));Ot<=qn;Ot++){var Cn=qe(m,Ot).text,Ut=ge(Cn,St,Ye);St==tn?ze.push(new gt(fe(Ot,Ut),fe(Ot,Ut))):Cn.length>Ut&&ze.push(new gt(fe(Ot,Ut),fe(Ot,ge(Cn,tn,Ye))))}ze.length||ze.push(new gt(a,a)),un(m,Tr(n,S.ranges.slice(0,x).concat(ze),x),{origin:\"*mouse\",scroll:!1}),n.scrollIntoView(Me)}else{var En=y,sn=Mm(n,Me,l.unit),Kt=En.anchor,Vt;Ie(sn.anchor,Kt)>0?(Vt=sn.head,Kt=is(En.from(),sn.anchor)):(Vt=sn.anchor,Kt=Sn(En.to(),sn.head));var It=S.ranges.slice(0);It[x]=kS(n,new gt(tt(m,Kt),Vt)),un(m,Tr(n,It,x),he)}}var te=u.wrapper.getBoundingClientRect(),pe=0;function we(Me){var ze=++pe,Ye=ko(n,Me,!0,l.unit==\"rectangle\");if(Ye)if(Ie(Ye,V)!=0){n.curOp.focus=be(je(n)),se(Ye);var Ue=ac(u,m);(Ye.line>=Ue.to||Ye.line<Ue.from)&&setTimeout(Qt(n,function(){pe==ze&&we(Me)}),150)}else{var st=Me.clientY<te.top?-20:Me.clientY>te.bottom?20:0;st&&setTimeout(Qt(n,function(){pe==ze&&(u.scroller.scrollTop+=st,we(Me))}),50)}}function Te(Me){n.state.selectingText=!1,pe=1/0,Me&&(cn(Me),u.input.focus()),an(u.wrapper.ownerDocument,\"mousemove\",Le),an(u.wrapper.ownerDocument,\"mouseup\",De),m.history.lastSelOrigin=null}var Le=Qt(n,function(Me){Me.buttons===0||!br(Me)?Te(Me):we(Me)}),De=Qt(n,Te);n.state.selectingText=De,Xe(u.wrapper.ownerDocument,\"mousemove\",Le),Xe(u.wrapper.ownerDocument,\"mouseup\",De)}function kS(n,i){var a=i.anchor,l=i.head,u=qe(n.doc,a.line);if(Ie(a,l)==0&&a.sticky==l.sticky)return i;var m=lt(u);if(!m)return i;var y=Bt(m,a.ch,a.sticky),x=m[y];if(x.from!=a.ch&&x.to!=a.ch)return i;var S=y+(x.from==a.ch==(x.level!=1)?0:1);if(S==0||S==m.length)return i;var T;if(l.line!=a.line)T=(l.line-a.line)*(n.doc.direction==\"ltr\"?1:-1)>0;else{var H=Bt(m,l.ch,l.sticky),V=H-y||(l.ch-a.ch)*(x.level==1?-1:1);H==S-1||H==S?T=V<0:T=V>0}var se=m[S+(T?-1:0)],te=T==(se.level==1),pe=te?se.from:se.to,we=te?\"after\":\"before\";return a.ch==pe&&a.sticky==we?i:new gt(new fe(a.line,pe,we),l)}function Nm(n,i,a,l){var u,m;if(i.touches)u=i.touches[0].clientX,m=i.touches[0].clientY;else try{u=i.clientX,m=i.clientY}catch{return!1}if(u>=Math.floor(n.display.gutters.getBoundingClientRect().right))return!1;l&&cn(i);var y=n.display,x=y.lineDiv.getBoundingClientRect();if(m>x.bottom||!Bn(n,a))return kn(i);m-=x.top-y.viewOffset;for(var S=0;S<n.display.gutterSpecs.length;++S){var T=y.gutters.childNodes[S];if(T&&T.getBoundingClientRect().right>=u){var H=U(n.doc,m),V=n.display.gutterSpecs[S];return Pt(n,a,n,H,V.className,i),kn(i)}}}function id(n,i){return Nm(n,i,\"gutterClick\",!0)}function Om(n,i){li(n.display,i)||SS(n,i)||Rt(n,i,\"contextmenu\")||G||n.display.input.onContextMenu(i)}function SS(n,i){return Bn(n,\"gutterContextMenu\")?Nm(n,i,\"gutterContextMenu\",!1):!1}function Pm(n){n.display.wrapper.className=n.display.wrapper.className.replace(/\\s*cm-s-\\S+/g,\"\")+n.options.theme.replace(/(^|\\s)\\s*/g,\" cm-s-\"),gl(n)}var ws={toString:function(){return\"CodeMirror.Init\"}},Rm={},xc={};function _S(n){var i=n.optionHandlers;function a(l,u,m,y){n.defaults[l]=u,m&&(i[l]=y?function(x,S,T){T!=ws&&m(x,S,T)}:m)}n.defineOption=a,n.Init=ws,a(\"value\",\"\",function(l,u){return l.setValue(u)},!0),a(\"mode\",null,function(l,u){l.doc.modeOption=u,Kf(l)},!0),a(\"indentUnit\",2,Kf,!0),a(\"indentWithTabs\",!1),a(\"smartIndent\",!0),a(\"tabSize\",4,function(l){Sl(l),gl(l),_n(l)},!0),a(\"lineSeparator\",null,function(l,u){if(l.doc.lineSep=u,!!u){var m=[],y=l.doc.first;l.doc.iter(function(S){for(var T=0;;){var H=S.text.indexOf(u,T);if(H==-1)break;T=H+u.length,m.push(fe(y,H))}y++});for(var x=m.length-1;x>=0;x--)ms(l.doc,u,m[x],fe(m[x].line,m[x].ch+u.length))}}),a(\"specialChars\",/[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u061c\\u200b\\u200e\\u200f\\u2028\\u2029\\u202d\\u202e\\u2066\\u2067\\u2069\\ufeff\\ufff9-\\ufffc]/g,function(l,u,m){l.state.specialChars=new RegExp(u.source+(u.test(\"\t\")?\"\":\"|\t\"),\"g\"),m!=ws&&l.refresh()}),a(\"specialCharPlaceholder\",Q1,function(l){return l.refresh()},!0),a(\"electricChars\",!0),a(\"inputStyle\",_?\"contenteditable\":\"textarea\",function(){throw new Error(\"inputStyle can not (yet) be changed in a running editor\")},!0),a(\"spellcheck\",!1,function(l,u){return l.getInputField().spellcheck=u},!0),a(\"autocorrect\",!1,function(l,u){return l.getInputField().autocorrect=u},!0),a(\"autocapitalize\",!1,function(l,u){return l.getInputField().autocapitalize=u},!0),a(\"rtlMoveVisually\",!ne),a(\"wholeLineUpdateBefore\",!0),a(\"theme\",\"default\",function(l){Pm(l),kl(l)},!0),a(\"keyMap\",\"default\",function(l,u,m){var y=bc(u),x=m!=ws&&bc(m);x&&x.detach&&x.detach(l,y),y.attach&&y.attach(l,x||null)}),a(\"extraKeys\",null),a(\"configureMouse\",null),a(\"lineWrapping\",!1,CS,!0),a(\"gutters\",[],function(l,u){l.display.gutterSpecs=Vf(u,l.options.lineNumbers),kl(l)},!0),a(\"fixedGutter\",!0,function(l,u){l.display.gutters.style.left=u?Rf(l.display)+\"px\":\"0\",l.refresh()},!0),a(\"coverGutterNextToScrollbar\",!1,function(l){return ds(l)},!0),a(\"scrollbarStyle\",\"native\",function(l){Ig(l),ds(l),l.display.scrollbars.setScrollTop(l.doc.scrollTop),l.display.scrollbars.setScrollLeft(l.doc.scrollLeft)},!0),a(\"lineNumbers\",!1,function(l,u){l.display.gutterSpecs=Vf(l.options.gutters,u),kl(l)},!0),a(\"firstLineNumber\",1,kl,!0),a(\"lineNumberFormatter\",function(l){return l},kl,!0),a(\"showCursorWhenSelecting\",!1,ml,!0),a(\"resetSelectionOnContextMenu\",!0),a(\"lineWiseCopyCut\",!0),a(\"pasteLinesPerSelection\",!0),a(\"selectionsMayTouch\",!1),a(\"readOnly\",!1,function(l,u){u==\"nocursor\"&&(us(l),l.display.input.blur()),l.display.input.readOnlyChanged(u)}),a(\"screenReaderLabel\",null,function(l,u){u=u===\"\"?null:u,l.display.input.screenReaderLabelChanged(u)}),a(\"disableInput\",!1,function(l,u){u||l.display.input.reset()},!0),a(\"dragDrop\",!0,TS),a(\"allowDropFileTypes\",null),a(\"cursorBlinkRate\",530),a(\"cursorScrollMargin\",0),a(\"cursorHeight\",1,ml,!0),a(\"singleCursorHeightPerLine\",!0,ml,!0),a(\"workTime\",100),a(\"workDelay\",100),a(\"flattenSpans\",!0,Sl,!0),a(\"addModeClass\",!1,Sl,!0),a(\"pollInterval\",100),a(\"undoDepth\",200,function(l,u){return l.doc.history.undoDepth=u}),a(\"historyEventDelay\",1250),a(\"viewportMargin\",10,function(l){return l.refresh()},!0),a(\"maxHighlightLength\",1e4,Sl,!0),a(\"moveInputWithCursor\",!0,function(l,u){u||l.display.input.resetPosition()}),a(\"tabindex\",null,function(l,u){return l.display.input.getField().tabIndex=u||\"\"}),a(\"autofocus\",null),a(\"direction\",\"ltr\",function(l,u){return l.doc.setDirection(u)},!0),a(\"phrases\",null)}function TS(n,i,a){var l=a&&a!=ws;if(!i!=!l){var u=n.display.dragFunctions,m=i?Xe:an;m(n.display.scroller,\"dragstart\",u.start),m(n.display.scroller,\"dragenter\",u.enter),m(n.display.scroller,\"dragover\",u.over),m(n.display.scroller,\"dragleave\",u.leave),m(n.display.scroller,\"drop\",u.drop)}}function CS(n){n.options.lineWrapping?(Se(n.display.wrapper,\"CodeMirror-wrap\"),n.display.sizer.style.minWidth=\"\",n.display.sizerWidth=null):(N(n.display.wrapper,\"CodeMirror-wrap\"),_f(n)),$f(n),_n(n),gl(n),setTimeout(function(){return ds(n)},100)}function Ct(n,i){var a=this;if(!(this instanceof Ct))return new Ct(n,i);this.options=i=i?Y(i):{},Y(Rm,i,!1);var l=i.value;typeof l==\"string\"?l=new Tn(l,i.mode,null,i.lineSeparator,i.direction):i.mode&&(l.modeOption=i.mode),this.doc=l;var u=new Ct.inputStyles[i.inputStyle](this),m=this.display=new Fk(n,l,u,i);m.wrapper.CodeMirror=this,Pm(this),i.lineWrapping&&(this.display.wrapper.className+=\" CodeMirror-wrap\"),Ig(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new le,keySeq:null,specialChars:null},i.autofocus&&!_&&m.input.focus(),h&&p<11&&setTimeout(function(){return a.display.input.reset(!0)},20),ES(this),iS(),Co(this),this.curOp.forceUpdate=!0,Vg(this,l),i.autofocus&&!_||this.hasFocus()?setTimeout(function(){a.hasFocus()&&!a.state.focused&&Ff(a)},20):us(this);for(var y in xc)xc.hasOwnProperty(y)&&xc[y](this,i[y],ws);Fg(this),i.finishInit&&i.finishInit(this);for(var x=0;x<od.length;++x)od[x](this);Eo(this),g&&i.lineWrapping&&getComputedStyle(m.lineDiv).textRendering==\"optimizelegibility\"&&(m.lineDiv.style.textRendering=\"auto\")}Ct.defaults=Rm,Ct.optionHandlers=xc;function ES(n){var i=n.display;Xe(i.scroller,\"mousedown\",Qt(n,Lm)),h&&p<11?Xe(i.scroller,\"dblclick\",Qt(n,function(S){if(!Rt(n,S)){var T=ko(n,S);if(!(!T||id(n,S)||li(n.display,S))){cn(S);var H=n.findWordAt(T);pc(n.doc,H.anchor,H.head)}}})):Xe(i.scroller,\"dblclick\",function(S){return Rt(n,S)||cn(S)}),Xe(i.scroller,\"contextmenu\",function(S){return Om(n,S)}),Xe(i.input.getField(),\"contextmenu\",function(S){i.scroller.contains(S.target)||Om(n,S)});var a,l={end:0};function u(){i.activeTouch&&(a=setTimeout(function(){return i.activeTouch=null},1e3),l=i.activeTouch,l.end=+new Date)}function m(S){if(S.touches.length!=1)return!1;var T=S.touches[0];return T.radiusX<=1&&T.radiusY<=1}function y(S,T){if(T.left==null)return!0;var H=T.left-S.left,V=T.top-S.top;return H*H+V*V>400}Xe(i.scroller,\"touchstart\",function(S){if(!Rt(n,S)&&!m(S)&&!id(n,S)){i.input.ensurePolled(),clearTimeout(a);var T=+new Date;i.activeTouch={start:T,moved:!1,prev:T-l.end<=300?l:null},S.touches.length==1&&(i.activeTouch.left=S.touches[0].pageX,i.activeTouch.top=S.touches[0].pageY)}}),Xe(i.scroller,\"touchmove\",function(){i.activeTouch&&(i.activeTouch.moved=!0)}),Xe(i.scroller,\"touchend\",function(S){var T=i.activeTouch;if(T&&!li(i,S)&&T.left!=null&&!T.moved&&new Date-T.start<300){var H=n.coordsChar(i.activeTouch,\"page\"),V;!T.prev||y(T,T.prev)?V=new gt(H,H):!T.prev.prev||y(T,T.prev.prev)?V=n.findWordAt(H):V=new gt(fe(H.line,0),tt(n.doc,fe(H.line+1,0))),n.setSelection(V.anchor,V.head),n.focus(),cn(S)}u()}),Xe(i.scroller,\"touchcancel\",u),Xe(i.scroller,\"scroll\",function(){i.scroller.clientHeight&&(yl(n,i.scroller.scrollTop),_o(n,i.scroller.scrollLeft,!0),Pt(n,\"scroll\",n))}),Xe(i.scroller,\"mousewheel\",function(S){return Wg(n,S)}),Xe(i.scroller,\"DOMMouseScroll\",function(S){return Wg(n,S)}),Xe(i.wrapper,\"scroll\",function(){return i.wrapper.scrollTop=i.wrapper.scrollLeft=0}),i.dragFunctions={enter:function(S){Rt(n,S)||Oi(S)},over:function(S){Rt(n,S)||(rS(n,S),Oi(S))},start:function(S){return nS(n,S)},drop:Qt(n,tS),leave:function(S){Rt(n,S)||mm(n)}};var x=i.input.getField();Xe(x,\"keyup\",function(S){return Em.call(n,S)}),Xe(x,\"keydown\",Qt(n,Cm)),Xe(x,\"keypress\",Qt(n,Am)),Xe(x,\"focus\",function(S){return Ff(n,S)}),Xe(x,\"blur\",function(S){return us(n,S)})}var od=[];Ct.defineInitHook=function(n){return od.push(n)};function Il(n,i,a,l){var u=n.doc,m;a==null&&(a=\"add\"),a==\"smart\"&&(u.mode.indent?m=ul(n,i).state:a=\"prev\");var y=n.options.tabSize,x=qe(u,i),S=re(x.text,null,y);x.stateAfter&&(x.stateAfter=null);var T=x.text.match(/^\\s*/)[0],H;if(!l&&!/\\S/.test(x.text))H=0,a=\"not\";else if(a==\"smart\"&&(H=u.mode.indent(m,x.text.slice(T.length),x.text),H==q||H>150)){if(!l)return;a=\"prev\"}a==\"prev\"?i>u.first?H=re(qe(u,i-1).text,null,y):H=0:a==\"add\"?H=S+n.options.indentUnit:a==\"subtract\"?H=S-n.options.indentUnit:typeof a==\"number\"&&(H=S+a),H=Math.max(0,H);var V=\"\",se=0;if(n.options.indentWithTabs)for(var te=Math.floor(H/y);te;--te)se+=y,V+=\"\t\";if(se<H&&(V+=Ee(H-se)),V!=T)return ms(u,V,fe(i,0),fe(i,T.length),\"+input\"),x.stateAfter=null,!0;for(var pe=0;pe<u.sel.ranges.length;pe++){var we=u.sel.ranges[pe];if(we.head.line==i&&we.head.ch<T.length){var Te=fe(i,T.length);Jf(u,pe,new gt(Te,Te));break}}}var Cr=null;function kc(n){Cr=n}function sd(n,i,a,l,u){var m=n.doc;n.display.shift=!1,l||(l=m.sel);var y=+new Date-200,x=u==\"paste\"||n.state.pasteIncoming>y,S=cr(i),T=null;if(x&&l.ranges.length>1)if(Cr&&Cr.text.join(`\n`)==i){if(l.ranges.length%Cr.text.length==0){T=[];for(var H=0;H<Cr.text.length;H++)T.push(m.splitLines(Cr.text[H]))}}else S.length==l.ranges.length&&n.options.pasteLinesPerSelection&&(T=ye(S,function(Le){return[Le]}));for(var V=n.curOp.updateInput,se=l.ranges.length-1;se>=0;se--){var te=l.ranges[se],pe=te.from(),we=te.to();te.empty()&&(a&&a>0?pe=fe(pe.line,pe.ch-a):n.state.overwrite&&!x?we=fe(we.line,Math.min(qe(m,we.line).text.length,we.ch+xe(S).length)):x&&Cr&&Cr.lineWise&&Cr.text.join(`\n`)==S.join(`\n`)&&(pe=we=fe(pe.line,0)));var Te={from:pe,to:we,text:T?T[se%T.length]:S,origin:u||(x?\"paste\":n.state.cutIncoming>y?\"cut\":\"+input\")};gs(n.doc,Te),Jt(n,\"inputRead\",n,Te)}i&&!x&&Im(n,i),fs(n),n.curOp.updateInput<2&&(n.curOp.updateInput=V),n.curOp.typing=!0,n.state.pasteIncoming=n.state.cutIncoming=-1}function $m(n,i){var a=n.clipboardData&&n.clipboardData.getData(\"Text\");if(a)return n.preventDefault(),!i.isReadOnly()&&!i.options.disableInput&&i.hasFocus()&&Wn(i,function(){return sd(i,a,0,null,\"paste\")}),!0}function Im(n,i){if(!(!n.options.electricChars||!n.options.smartIndent))for(var a=n.doc.sel,l=a.ranges.length-1;l>=0;l--){var u=a.ranges[l];if(!(u.head.ch>100||l&&a.ranges[l-1].head.line==u.head.line)){var m=n.getModeAt(u.head),y=!1;if(m.electricChars){for(var x=0;x<m.electricChars.length;x++)if(i.indexOf(m.electricChars.charAt(x))>-1){y=Il(n,u.head.line,\"smart\");break}}else m.electricInput&&m.electricInput.test(qe(n.doc,u.head.line).text.slice(0,u.head.ch))&&(y=Il(n,u.head.line,\"smart\"));y&&Jt(n,\"electricInput\",n,u.head.line)}}}function Dm(n){for(var i=[],a=[],l=0;l<n.doc.sel.ranges.length;l++){var u=n.doc.sel.ranges[l].head.line,m={anchor:fe(u,0),head:fe(u+1,0)};a.push(m),i.push(n.getRange(m.anchor,m.head))}return{text:i,ranges:a}}function ld(n,i,a,l){n.setAttribute(\"autocorrect\",a?\"on\":\"off\"),n.setAttribute(\"autocapitalize\",l?\"on\":\"off\"),n.setAttribute(\"spellcheck\",!!i)}function zm(){var n=k(\"textarea\",null,null,\"position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; min-height: 1em; outline: none\"),i=k(\"div\",[n],null,\"overflow: hidden; position: relative; width: 3px; height: 0px;\");return g?n.style.width=\"1000px\":n.setAttribute(\"wrap\",\"off\"),R&&(n.style.border=\"1px solid black\"),i}function AS(n){var i=n.optionHandlers,a=n.helpers={};n.prototype={constructor:n,focus:function(){Pe(this).focus(),this.display.input.focus()},setOption:function(l,u){var m=this.options,y=m[l];m[l]==u&&l!=\"mode\"||(m[l]=u,i.hasOwnProperty(l)&&Qt(this,i[l])(this,u,y),Pt(this,\"optionChange\",this,l))},getOption:function(l){return this.options[l]},getDoc:function(){return this.doc},addKeyMap:function(l,u){this.state.keyMaps[u?\"push\":\"unshift\"](bc(l))},removeKeyMap:function(l){for(var u=this.state.keyMaps,m=0;m<u.length;++m)if(u[m]==l||u[m].name==l)return u.splice(m,1),!0},addOverlay:vn(function(l,u){var m=l.token?l:n.getMode(this.options,l);if(m.startState)throw new Error(\"Overlays may not be stateful.\");J(this.state.overlays,{mode:m,modeSpec:l,opaque:u&&u.opaque,priority:u&&u.priority||0},function(y){return y.priority}),this.state.modeGen++,_n(this)}),removeOverlay:vn(function(l){for(var u=this.state.overlays,m=0;m<u.length;++m){var y=u[m].modeSpec;if(y==l||typeof l==\"string\"&&y.name==l){u.splice(m,1),this.state.modeGen++,_n(this);return}}}),indentLine:vn(function(l,u,m){typeof u!=\"string\"&&typeof u!=\"number\"&&(u==null?u=this.options.smartIndent?\"smart\":\"prev\":u=u?\"add\":\"subtract\"),me(this.doc,l)&&Il(this,l,u,m)}),indentSelection:vn(function(l){for(var u=this.doc.sel.ranges,m=-1,y=0;y<u.length;y++){var x=u[y];if(x.empty())x.head.line>m&&(Il(this,x.head.line,l,!0),m=x.head.line,y==this.doc.sel.primIndex&&fs(this));else{var S=x.from(),T=x.to(),H=Math.max(m,S.line);m=Math.min(this.lastLine(),T.line-(T.ch?0:1))+1;for(var V=H;V<m;++V)Il(this,V,l);var se=this.doc.sel.ranges;S.ch==0&&u.length==se.length&&se[y].from().ch>0&&Jf(this.doc,y,new gt(S,se[y].to()),Q)}}}),getTokenAt:function(l,u){return Kp(this,l,u)},getLineTokens:function(l,u){return Kp(this,fe(l),u,!0)},getTokenTypeAt:function(l){l=tt(this.doc,l);var u=Up(this,qe(this.doc,l.line)),m=0,y=(u.length-1)/2,x=l.ch,S;if(x==0)S=u[2];else for(;;){var T=m+y>>1;if((T?u[T*2-1]:0)>=x)y=T;else if(u[T*2+1]<x)m=T+1;else{S=u[T*2+2];break}}var H=S?S.indexOf(\"overlay \"):-1;return H<0?S:H==0?null:S.slice(0,H-1)},getModeAt:function(l){var u=this.doc.mode;return u.innerMode?n.innerMode(u,this.getTokenAt(l).state).mode:u},getHelper:function(l,u){return this.getHelpers(l,u)[0]},getHelpers:function(l,u){var m=[];if(!a.hasOwnProperty(u))return m;var y=a[u],x=this.getModeAt(l);if(typeof x[u]==\"string\")y[x[u]]&&m.push(y[x[u]]);else if(x[u])for(var S=0;S<x[u].length;S++){var T=y[x[u][S]];T&&m.push(T)}else x.helperType&&y[x.helperType]?m.push(y[x.helperType]):y[x.name]&&m.push(y[x.name]);for(var H=0;H<y._global.length;H++){var V=y._global[H];V.pred(x,this)&&ae(m,V.val)==-1&&m.push(V.val)}return m},getStateAfter:function(l,u){var m=this.doc;return l=Wp(m,l??m.first+m.size-1),ul(this,l+1,u).state},cursorCoords:function(l,u){var m,y=this.doc.sel.primary();return l==null?m=y.head:typeof l==\"object\"?m=tt(this.doc,l):m=l?y.from():y.to(),_r(this,m,u||\"page\")},charCoords:function(l,u){return ic(this,tt(this.doc,l),u||\"page\")},coordsChar:function(l,u){return l=Sg(this,l,u||\"page\"),Nf(this,l.left,l.top)},lineAtHeight:function(l,u){return l=Sg(this,{top:l,left:0},u||\"page\").top,U(this.doc,l+this.display.viewOffset)},heightAtLine:function(l,u,m){var y=!1,x;if(typeof l==\"number\"){var S=this.doc.first+this.doc.size-1;l<this.doc.first?l=this.doc.first:l>S&&(l=S,y=!0),x=qe(this.doc,l)}else x=l;return rc(this,x,{top:0,left:0},u||\"page\",m||y).top+(y?this.doc.height-si(x):0)},defaultTextHeight:function(){return as(this.display)},defaultCharWidth:function(){return cs(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(l,u,m,y,x){var S=this.display;l=_r(this,tt(this.doc,l));var T=l.bottom,H=l.left;if(u.style.position=\"absolute\",u.setAttribute(\"cm-ignore-events\",\"true\"),this.display.input.setUneditable(u),S.sizer.appendChild(u),y==\"over\")T=l.top;else if(y==\"above\"||y==\"near\"){var V=Math.max(S.wrapper.clientHeight,this.doc.height),se=Math.max(S.sizer.clientWidth,S.lineSpace.clientWidth);(y==\"above\"||l.bottom+u.offsetHeight>V)&&l.top>u.offsetHeight?T=l.top-u.offsetHeight:l.bottom+u.offsetHeight<=V&&(T=l.bottom),H+u.offsetWidth>se&&(H=se-u.offsetWidth)}u.style.top=T+\"px\",u.style.left=u.style.right=\"\",x==\"right\"?(H=S.sizer.clientWidth-u.offsetWidth,u.style.right=\"0px\"):(x==\"left\"?H=0:x==\"middle\"&&(H=(S.sizer.clientWidth-u.offsetWidth)/2),u.style.left=H+\"px\"),m&&Tk(this,{left:H,top:T,right:H+u.offsetWidth,bottom:T+u.offsetHeight})},triggerOnKeyDown:vn(Cm),triggerOnKeyPress:vn(Am),triggerOnKeyUp:Em,triggerOnMouseDown:vn(Lm),execCommand:function(l){if(Ol.hasOwnProperty(l))return Ol[l].call(null,this)},triggerElectric:vn(function(l){Im(this,l)}),findPosH:function(l,u,m,y){var x=1;u<0&&(x=-1,u=-u);for(var S=tt(this.doc,l),T=0;T<u&&(S=ad(this.doc,S,x,m,y),!S.hitSide);++T);return S},moveH:vn(function(l,u){var m=this;this.extendSelectionsBy(function(y){return m.display.shift||m.doc.extend||y.empty()?ad(m.doc,y.head,l,u,m.options.rtlMoveVisually):l<0?y.from():y.to()},de)}),deleteH:vn(function(l,u){var m=this.doc.sel,y=this.doc;m.somethingSelected()?y.replaceSelection(\"\",null,\"+delete\"):bs(this,function(x){var S=ad(y,x.head,l,u,!1);return l<0?{from:S,to:x.head}:{from:x.head,to:S}})}),findPosV:function(l,u,m,y){var x=1,S=y;u<0&&(x=-1,u=-u);for(var T=tt(this.doc,l),H=0;H<u;++H){var V=_r(this,T,\"div\");if(S==null?S=V.left:V.left=S,T=Fm(this,V,x,m),T.hitSide)break}return T},moveV:vn(function(l,u){var m=this,y=this.doc,x=[],S=!this.display.shift&&!y.extend&&y.sel.somethingSelected();if(y.extendSelectionsBy(function(H){if(S)return l<0?H.from():H.to();var V=_r(m,H.head,\"div\");H.goalColumn!=null&&(V.left=H.goalColumn),x.push(V.left);var se=Fm(m,V,l,u);return u==\"page\"&&H==y.sel.primary()&&Bf(m,ic(m,se,\"div\").top-V.top),se},de),x.length)for(var T=0;T<y.sel.ranges.length;T++)y.sel.ranges[T].goalColumn=x[T]}),findWordAt:function(l){var u=this.doc,m=qe(u,l.line).text,y=l.ch,x=l.ch;if(m){var S=this.getHelper(l,\"wordChars\");(l.sticky==\"before\"||x==m.length)&&y?--y:++x;for(var T=m.charAt(y),H=ct(T,S)?function(V){return ct(V,S)}:/\\s/.test(T)?function(V){return/\\s/.test(V)}:function(V){return!/\\s/.test(V)&&!ct(V)};y>0&&H(m.charAt(y-1));)--y;for(;x<m.length&&H(m.charAt(x));)++x}return new gt(fe(l.line,y),fe(l.line,x))},toggleOverwrite:function(l){l!=null&&l==this.state.overwrite||((this.state.overwrite=!this.state.overwrite)?Se(this.display.cursorDiv,\"CodeMirror-overwrite\"):N(this.display.cursorDiv,\"CodeMirror-overwrite\"),Pt(this,\"overwriteToggle\",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==be(je(this))},isReadOnly:function(){return!!(this.options.readOnly||this.doc.cantEdit)},scrollTo:vn(function(l,u){vl(this,l,u)}),getScrollInfo:function(){var l=this.display.scroller;return{left:l.scrollLeft,top:l.scrollTop,height:l.scrollHeight-qr(this)-this.display.barHeight,width:l.scrollWidth-qr(this)-this.display.barWidth,clientHeight:Ef(this),clientWidth:wo(this)}},scrollIntoView:vn(function(l,u){l==null?(l={from:this.doc.sel.primary().head,to:null},u==null&&(u=this.options.cursorScrollMargin)):typeof l==\"number\"?l={from:fe(l,0),to:null}:l.from==null&&(l={from:l,to:null}),l.to||(l.to=l.from),l.margin=u||0,l.from.line!=null?Ck(this,l):Og(this,l.from,l.to,l.margin)}),setSize:vn(function(l,u){var m=this,y=function(S){return typeof S==\"number\"||/^\\d+$/.test(String(S))?S+\"px\":S};l!=null&&(this.display.wrapper.style.width=y(l)),u!=null&&(this.display.wrapper.style.height=y(u)),this.options.lineWrapping&&wg(this);var x=this.display.viewFrom;this.doc.iter(x,this.display.viewTo,function(S){if(S.widgets){for(var T=0;T<S.widgets.length;T++)if(S.widgets[T].noHScroll){Di(m,x,\"widget\");break}}++x}),this.curOp.forceUpdate=!0,Pt(this,\"refresh\",this)}),operation:function(l){return Wn(this,l)},startOperation:function(){return Co(this)},endOperation:function(){return Eo(this)},refresh:vn(function(){var l=this.display.cachedTextHeight;_n(this),this.curOp.forceUpdate=!0,gl(this),vl(this,this.doc.scrollLeft,this.doc.scrollTop),jf(this.display),(l==null||Math.abs(l-as(this.display))>.5||this.options.lineWrapping)&&$f(this),Pt(this,\"refresh\",this)}),swapDoc:vn(function(l){var u=this.doc;return u.cm=null,this.state.selectingText&&this.state.selectingText(),Vg(this,l),gl(this),this.display.input.reset(),vl(this,l.scrollLeft,l.scrollTop),this.curOp.forceScroll=!0,Jt(this,\"swapDoc\",this,u),u}),phrase:function(l){var u=this.options.phrases;return u&&Object.prototype.hasOwnProperty.call(u,l)?u[l]:l},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},yr(n),n.registerHelper=function(l,u,m){a.hasOwnProperty(l)||(a[l]=n[l]={_global:[]}),a[l][u]=m},n.registerGlobalHelper=function(l,u,m,y){n.registerHelper(l,u,y),a[l]._global.push({pred:m,val:y})}}function ad(n,i,a,l,u){var m=i,y=a,x=qe(n,i.line),S=u&&n.direction==\"rtl\"?-a:a;function T(){var De=i.line+S;return De<n.first||De>=n.first+n.size?!1:(i=new fe(De,i.ch,i.sticky),x=qe(n,De))}function H(De){var Me;if(l==\"codepoint\"){var ze=x.text.charCodeAt(i.ch+(a>0?0:-1));if(isNaN(ze))Me=null;else{var Ye=a>0?ze>=55296&&ze<56320:ze>=56320&&ze<57343;Me=new fe(i.line,Math.max(0,Math.min(x.text.length,i.ch+a*(Ye?2:1))),-a)}}else u?Me=cS(n.cm,x,i,a):Me=ed(x,i,a);if(Me==null)if(!De&&T())i=td(u,n.cm,x,i.line,S);else return!1;else i=Me;return!0}if(l==\"char\"||l==\"codepoint\")H();else if(l==\"column\")H(!0);else if(l==\"word\"||l==\"group\")for(var V=null,se=l==\"group\",te=n.cm&&n.cm.getHelper(i,\"wordChars\"),pe=!0;!(a<0&&!H(!pe));pe=!1){var we=x.text.charAt(i.ch)||`\n`,Te=ct(we,te)?\"w\":se&&we==`\n`?\"n\":!se||/\\s/.test(we)?null:\"p\";if(se&&!pe&&!Te&&(Te=\"s\"),V&&V!=Te){a<0&&(a=1,H(),i.sticky=\"after\");break}if(Te&&(V=Te),a>0&&!H(!pe))break}var Le=mc(n,i,m,y,!0);return pt(m,Le)&&(Le.hitSide=!0),Le}function Fm(n,i,a,l){var u=n.doc,m=i.left,y;if(l==\"page\"){var x=Math.min(n.display.wrapper.clientHeight,Pe(n).innerHeight||u(n).documentElement.clientHeight),S=Math.max(x-.5*as(n.display),3);y=(a>0?i.bottom:i.top)+a*S}else l==\"line\"&&(y=a>0?i.bottom+3:i.top-3);for(var T;T=Nf(n,m,y),!!T.outside;){if(a<0?y<=0:y>=u.height){T.hitSide=!0;break}y+=a*5}return T}var yt=function(n){this.cm=n,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new le,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};yt.prototype.init=function(n){var i=this,a=this,l=a.cm,u=a.div=n.lineDiv;u.contentEditable=!0,ld(u,l.options.spellcheck,l.options.autocorrect,l.options.autocapitalize);function m(x){for(var S=x.target;S;S=S.parentNode){if(S==u)return!0;if(/\\bCodeMirror-(?:line)?widget\\b/.test(S.className))break}return!1}Xe(u,\"paste\",function(x){!m(x)||Rt(l,x)||$m(x,l)||p<=11&&setTimeout(Qt(l,function(){return i.updateFromDOM()}),20)}),Xe(u,\"compositionstart\",function(x){i.composing={data:x.data,done:!1}}),Xe(u,\"compositionupdate\",function(x){i.composing||(i.composing={data:x.data,done:!1})}),Xe(u,\"compositionend\",function(x){i.composing&&(x.data!=i.composing.data&&i.readFromDOMSoon(),i.composing.done=!0)}),Xe(u,\"touchstart\",function(){return a.forceCompositionEnd()}),Xe(u,\"input\",function(){i.composing||i.readFromDOMSoon()});function y(x){if(!(!m(x)||Rt(l,x))){if(l.somethingSelected())kc({lineWise:!1,text:l.getSelections()}),x.type==\"cut\"&&l.replaceSelection(\"\",null,\"cut\");else if(l.options.lineWiseCopyCut){var S=Dm(l);kc({lineWise:!0,text:S.text}),x.type==\"cut\"&&l.operation(function(){l.setSelections(S.ranges,0,Q),l.replaceSelection(\"\",null,\"cut\")})}else return;if(x.clipboardData){x.clipboardData.clearData();var T=Cr.text.join(`\n`);if(x.clipboardData.setData(\"Text\",T),x.clipboardData.getData(\"Text\")==T){x.preventDefault();return}}var H=zm(),V=H.firstChild;ld(V),l.display.lineSpace.insertBefore(H,l.display.lineSpace.firstChild),V.value=Cr.text.join(`\n`);var se=be(Fe(u));Ae(V),setTimeout(function(){l.display.lineSpace.removeChild(H),se.focus(),se==u&&a.showPrimarySelection()},50)}}Xe(u,\"copy\",y),Xe(u,\"cut\",y)},yt.prototype.screenReaderLabelChanged=function(n){n?this.div.setAttribute(\"aria-label\",n):this.div.removeAttribute(\"aria-label\")},yt.prototype.prepareSelection=function(){var n=Lg(this.cm,!1);return n.focus=be(Fe(this.div))==this.div,n},yt.prototype.showSelection=function(n,i){!n||!this.cm.display.view.length||((n.focus||i)&&this.showPrimarySelection(),this.showMultipleSelections(n))},yt.prototype.getSelection=function(){return this.cm.display.wrapper.ownerDocument.getSelection()},yt.prototype.showPrimarySelection=function(){var n=this.getSelection(),i=this.cm,a=i.doc.sel.primary(),l=a.from(),u=a.to();if(i.display.viewTo==i.display.viewFrom||l.line>=i.display.viewTo||u.line<i.display.viewFrom){n.removeAllRanges();return}var m=Sc(i,n.anchorNode,n.anchorOffset),y=Sc(i,n.focusNode,n.focusOffset);if(!(m&&!m.bad&&y&&!y.bad&&Ie(is(m,y),l)==0&&Ie(Sn(m,y),u)==0)){var x=i.display.view,S=l.line>=i.display.viewFrom&&Hm(i,l)||{node:x[0].measure.map[2],offset:0},T=u.line<i.display.viewTo&&Hm(i,u);if(!T){var H=x[x.length-1].measure,V=H.maps?H.maps[H.maps.length-1]:H.map;T={node:V[V.length-1],offset:V[V.length-2]-V[V.length-3]}}if(!S||!T){n.removeAllRanges();return}var se=n.rangeCount&&n.getRangeAt(0),te;try{te=B(S.node,S.offset,T.offset,T.node)}catch{}te&&(!s&&i.state.focused?(n.collapse(S.node,S.offset),te.collapsed||(n.removeAllRanges(),n.addRange(te))):(n.removeAllRanges(),n.addRange(te)),se&&n.anchorNode==null?n.addRange(se):s&&this.startGracePeriod()),this.rememberSelection()}},yt.prototype.startGracePeriod=function(){var n=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){n.gracePeriod=!1,n.selectionChanged()&&n.cm.operation(function(){return n.cm.curOp.selectionChanged=!0})},20)},yt.prototype.showMultipleSelections=function(n){C(this.cm.display.cursorDiv,n.cursors),C(this.cm.display.selectionDiv,n.selection)},yt.prototype.rememberSelection=function(){var n=this.getSelection();this.lastAnchorNode=n.anchorNode,this.lastAnchorOffset=n.anchorOffset,this.lastFocusNode=n.focusNode,this.lastFocusOffset=n.focusOffset},yt.prototype.selectionInEditor=function(){var n=this.getSelection();if(!n.rangeCount)return!1;var i=n.getRangeAt(0).commonAncestorContainer;return ce(this.div,i)},yt.prototype.focus=function(){this.cm.options.readOnly!=\"nocursor\"&&((!this.selectionInEditor()||be(Fe(this.div))!=this.div)&&this.showSelection(this.prepareSelection(),!0),this.div.focus())},yt.prototype.blur=function(){this.div.blur()},yt.prototype.getField=function(){return this.div},yt.prototype.supportsTouch=function(){return!0},yt.prototype.receivedFocus=function(){var n=this,i=this;this.selectionInEditor()?setTimeout(function(){return n.pollSelection()},20):Wn(this.cm,function(){return i.cm.curOp.selectionChanged=!0});function a(){i.cm.state.focused&&(i.pollSelection(),i.polling.set(i.cm.options.pollInterval,a))}this.polling.set(this.cm.options.pollInterval,a)},yt.prototype.selectionChanged=function(){var n=this.getSelection();return n.anchorNode!=this.lastAnchorNode||n.anchorOffset!=this.lastAnchorOffset||n.focusNode!=this.lastFocusNode||n.focusOffset!=this.lastFocusOffset},yt.prototype.pollSelection=function(){if(!(this.readDOMTimeout!=null||this.gracePeriod||!this.selectionChanged())){var n=this.getSelection(),i=this.cm;if(I&&b&&this.cm.display.gutterSpecs.length&&LS(n.anchorNode)){this.cm.triggerOnKeyDown({type:\"keydown\",keyCode:8,preventDefault:Math.abs}),this.blur(),this.focus();return}if(!this.composing){this.rememberSelection();var a=Sc(i,n.anchorNode,n.anchorOffset),l=Sc(i,n.focusNode,n.focusOffset);a&&l&&Wn(i,function(){un(i.doc,Fi(a,l),Q),(a.bad||l.bad)&&(i.curOp.selectionChanged=!0)})}}},yt.prototype.pollContent=function(){this.readDOMTimeout!=null&&(clearTimeout(this.readDOMTimeout),this.readDOMTimeout=null);var n=this.cm,i=n.display,a=n.doc.sel.primary(),l=a.from(),u=a.to();if(l.ch==0&&l.line>n.firstLine()&&(l=fe(l.line-1,qe(n.doc,l.line-1).length)),u.ch==qe(n.doc,u.line).text.length&&u.line<n.lastLine()&&(u=fe(u.line+1,0)),l.line<i.viewFrom||u.line>i.viewTo-1)return!1;var m,y,x;l.line==i.viewFrom||(m=So(n,l.line))==0?(y=A(i.view[0].line),x=i.view[0].node):(y=A(i.view[m].line),x=i.view[m-1].node.nextSibling);var S=So(n,u.line),T,H;if(S==i.view.length-1?(T=i.viewTo-1,H=i.lineDiv.lastChild):(T=A(i.view[S+1].line)-1,H=i.view[S+1].node.previousSibling),!x)return!1;for(var V=n.doc.splitLines(MS(n,x,H,y,T)),se=ii(n.doc,fe(y,0),fe(T,qe(n.doc,T).text.length));V.length>1&&se.length>1;)if(xe(V)==xe(se))V.pop(),se.pop(),T--;else if(V[0]==se[0])V.shift(),se.shift(),y++;else break;for(var te=0,pe=0,we=V[0],Te=se[0],Le=Math.min(we.length,Te.length);te<Le&&we.charCodeAt(te)==Te.charCodeAt(te);)++te;for(var De=xe(V),Me=xe(se),ze=Math.min(De.length-(V.length==1?te:0),Me.length-(se.length==1?te:0));pe<ze&&De.charCodeAt(De.length-pe-1)==Me.charCodeAt(Me.length-pe-1);)++pe;if(V.length==1&&se.length==1&&y==l.line)for(;te&&te>l.ch&&De.charCodeAt(De.length-pe-1)==Me.charCodeAt(Me.length-pe-1);)te--,pe++;V[V.length-1]=De.slice(0,De.length-pe).replace(/^\\u200b+/,\"\"),V[0]=V[0].slice(te).replace(/\\u200b+$/,\"\");var Ye=fe(y,te),Ue=fe(T,se.length?xe(se).length-pe:0);if(V.length>1||V[0]||Ie(Ye,Ue))return ms(n.doc,V,Ye,Ue,\"+input\"),!0},yt.prototype.ensurePolled=function(){this.forceCompositionEnd()},yt.prototype.reset=function(){this.forceCompositionEnd()},yt.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},yt.prototype.readFromDOMSoon=function(){var n=this;this.readDOMTimeout==null&&(this.readDOMTimeout=setTimeout(function(){if(n.readDOMTimeout=null,n.composing)if(n.composing.done)n.composing=null;else return;n.updateFromDOM()},80))},yt.prototype.updateFromDOM=function(){var n=this;(this.cm.isReadOnly()||!this.pollContent())&&Wn(this.cm,function(){return _n(n.cm)})},yt.prototype.setUneditable=function(n){n.contentEditable=\"false\"},yt.prototype.onKeyPress=function(n){n.charCode==0||this.composing||(n.preventDefault(),this.cm.isReadOnly()||Qt(this.cm,sd)(this.cm,String.fromCharCode(n.charCode==null?n.keyCode:n.charCode),0))},yt.prototype.readOnlyChanged=function(n){this.div.contentEditable=String(n!=\"nocursor\")},yt.prototype.onContextMenu=function(){},yt.prototype.resetPosition=function(){},yt.prototype.needsContentAttribute=!0;function Hm(n,i){var a=Af(n,i.line);if(!a||a.hidden)return null;var l=qe(n.doc,i.line),u=gg(a,l,i.line),m=lt(l,n.doc.direction),y=\"left\";if(m){var x=Bt(m,i.ch);y=x%2?\"right\":\"left\"}var S=yg(u.map,i.ch,y);return S.offset=S.collapse==\"right\"?S.end:S.start,S}function LS(n){for(var i=n;i;i=i.parentNode)if(/CodeMirror-gutter-wrapper/.test(i.className))return!0;return!1}function xs(n,i){return i&&(n.bad=!0),n}function MS(n,i,a,l,u){var m=\"\",y=!1,x=n.doc.lineSeparator(),S=!1;function T(te){return function(pe){return pe.id==te}}function H(){y&&(m+=x,S&&(m+=x),y=S=!1)}function V(te){te&&(H(),m+=te)}function se(te){if(te.nodeType==1){var pe=te.getAttribute(\"cm-text\");if(pe){V(pe);return}var we=te.getAttribute(\"cm-marker\"),Te;if(we){var Le=n.findMarks(fe(l,0),fe(u+1,0),T(+we));Le.length&&(Te=Le[0].find(0))&&V(ii(n.doc,Te.from,Te.to).join(x));return}if(te.getAttribute(\"contenteditable\")==\"false\")return;var De=/^(pre|div|p|li|table|br)$/i.test(te.nodeName);if(!/^br$/i.test(te.nodeName)&&te.textContent.length==0)return;De&&H();for(var Me=0;Me<te.childNodes.length;Me++)se(te.childNodes[Me]);/^(pre|p)$/i.test(te.nodeName)&&(S=!0),De&&(y=!0)}else te.nodeType==3&&V(te.nodeValue.replace(/\\u200b/g,\"\").replace(/\\u00a0/g,\" \"))}for(;se(i),i!=a;)i=i.nextSibling,S=!1;return m}function Sc(n,i,a){var l;if(i==n.display.lineDiv){if(l=n.display.lineDiv.childNodes[a],!l)return xs(n.clipPos(fe(n.display.viewTo-1)),!0);i=null,a=0}else for(l=i;;l=l.parentNode){if(!l||l==n.display.lineDiv)return null;if(l.parentNode&&l.parentNode==n.display.lineDiv)break}for(var u=0;u<n.display.view.length;u++){var m=n.display.view[u];if(m.node==l)return NS(m,i,a)}}function NS(n,i,a){var l=n.text.firstChild,u=!1;if(!i||!ce(l,i))return xs(fe(A(n.line),0),!0);if(i==l&&(u=!0,i=l.childNodes[a],a=0,!i)){var m=n.rest?xe(n.rest):n.line;return xs(fe(A(m),m.text.length),u)}var y=i.nodeType==3?i:null,x=i;for(!y&&i.childNodes.length==1&&i.firstChild.nodeType==3&&(y=i.firstChild,a&&(a=y.nodeValue.length));x.parentNode!=l;)x=x.parentNode;var S=n.measure,T=S.maps;function H(Te,Le,De){for(var Me=-1;Me<(T?T.length:0);Me++)for(var ze=Me<0?S.map:T[Me],Ye=0;Ye<ze.length;Ye+=3){var Ue=ze[Ye+2];if(Ue==Te||Ue==Le){var st=A(Me<0?n.line:n.rest[Me]),St=ze[Ye]+De;return(De<0||Ue!=Te)&&(St=ze[Ye+(De?1:0)]),fe(st,St)}}}var V=H(y,x,a);if(V)return xs(V,u);for(var se=x.nextSibling,te=y?y.nodeValue.length-a:0;se;se=se.nextSibling){if(V=H(se,se.firstChild,0),V)return xs(fe(V.line,V.ch-te),u);te+=se.textContent.length}for(var pe=x.previousSibling,we=a;pe;pe=pe.previousSibling){if(V=H(pe,pe.firstChild,-1),V)return xs(fe(V.line,V.ch+we),u);we+=pe.textContent.length}}var Wt=function(n){this.cm=n,this.prevInput=\"\",this.pollingFast=!1,this.polling=new le,this.hasSelection=!1,this.composing=null,this.resetting=!1};Wt.prototype.init=function(n){var i=this,a=this,l=this.cm;this.createField(n);var u=this.textarea;n.wrapper.insertBefore(this.wrapper,n.wrapper.firstChild),R&&(u.style.width=\"0px\"),Xe(u,\"input\",function(){h&&p>=9&&i.hasSelection&&(i.hasSelection=null),a.poll()}),Xe(u,\"paste\",function(y){Rt(l,y)||$m(y,l)||(l.state.pasteIncoming=+new Date,a.fastPoll())});function m(y){if(!Rt(l,y)){if(l.somethingSelected())kc({lineWise:!1,text:l.getSelections()});else if(l.options.lineWiseCopyCut){var x=Dm(l);kc({lineWise:!0,text:x.text}),y.type==\"cut\"?l.setSelections(x.ranges,null,Q):(a.prevInput=\"\",u.value=x.text.join(`\n`),Ae(u))}else return;y.type==\"cut\"&&(l.state.cutIncoming=+new Date)}}Xe(u,\"cut\",m),Xe(u,\"copy\",m),Xe(n.scroller,\"paste\",function(y){if(!(li(n,y)||Rt(l,y))){if(!u.dispatchEvent){l.state.pasteIncoming=+new Date,a.focus();return}var x=new Event(\"paste\");x.clipboardData=y.clipboardData,u.dispatchEvent(x)}}),Xe(n.lineSpace,\"selectstart\",function(y){li(n,y)||cn(y)}),Xe(u,\"compositionstart\",function(){var y=l.getCursor(\"from\");a.composing&&a.composing.range.clear(),a.composing={start:y,range:l.markText(y,l.getCursor(\"to\"),{className:\"CodeMirror-composing\"})}}),Xe(u,\"compositionend\",function(){a.composing&&(a.poll(),a.composing.range.clear(),a.composing=null)})},Wt.prototype.createField=function(n){this.wrapper=zm(),this.textarea=this.wrapper.firstChild;var i=this.cm.options;ld(this.textarea,i.spellcheck,i.autocorrect,i.autocapitalize)},Wt.prototype.screenReaderLabelChanged=function(n){n?this.textarea.setAttribute(\"aria-label\",n):this.textarea.removeAttribute(\"aria-label\")},Wt.prototype.prepareSelection=function(){var n=this.cm,i=n.display,a=n.doc,l=Lg(n);if(n.options.moveInputWithCursor){var u=_r(n,a.sel.primary().head,\"div\"),m=i.wrapper.getBoundingClientRect(),y=i.lineDiv.getBoundingClientRect();l.teTop=Math.max(0,Math.min(i.wrapper.clientHeight-10,u.top+y.top-m.top)),l.teLeft=Math.max(0,Math.min(i.wrapper.clientWidth-10,u.left+y.left-m.left))}return l},Wt.prototype.showSelection=function(n){var i=this.cm,a=i.display;C(a.cursorDiv,n.cursors),C(a.selectionDiv,n.selection),n.teTop!=null&&(this.wrapper.style.top=n.teTop+\"px\",this.wrapper.style.left=n.teLeft+\"px\")},Wt.prototype.reset=function(n){if(!(this.contextMenuPending||this.composing&&n)){var i=this.cm;if(this.resetting=!0,i.somethingSelected()){this.prevInput=\"\";var a=i.getSelection();this.textarea.value=a,i.state.focused&&Ae(this.textarea),h&&p>=9&&(this.hasSelection=a)}else n||(this.prevInput=this.textarea.value=\"\",h&&p>=9&&(this.hasSelection=null));this.resetting=!1}},Wt.prototype.getField=function(){return this.textarea},Wt.prototype.supportsTouch=function(){return!1},Wt.prototype.focus=function(){if(this.cm.options.readOnly!=\"nocursor\"&&(!_||be(Fe(this.textarea))!=this.textarea))try{this.textarea.focus()}catch{}},Wt.prototype.blur=function(){this.textarea.blur()},Wt.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Wt.prototype.receivedFocus=function(){this.slowPoll()},Wt.prototype.slowPoll=function(){var n=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){n.poll(),n.cm.state.focused&&n.slowPoll()})},Wt.prototype.fastPoll=function(){var n=!1,i=this;i.pollingFast=!0;function a(){var l=i.poll();!l&&!n?(n=!0,i.polling.set(60,a)):(i.pollingFast=!1,i.slowPoll())}i.polling.set(20,a)},Wt.prototype.poll=function(){var n=this,i=this.cm,a=this.textarea,l=this.prevInput;if(this.contextMenuPending||this.resetting||!i.state.focused||Ri(a)&&!l&&!this.composing||i.isReadOnly()||i.options.disableInput||i.state.keySeq)return!1;var u=a.value;if(u==l&&!i.somethingSelected())return!1;if(h&&p>=9&&this.hasSelection===u||$&&/[\\uf700-\\uf7ff]/.test(u))return i.display.input.reset(),!1;if(i.doc.sel==i.display.selForContextMenu){var m=u.charCodeAt(0);if(m==8203&&!l&&(l=\"​\"),m==8666)return this.reset(),this.cm.execCommand(\"undo\")}for(var y=0,x=Math.min(l.length,u.length);y<x&&l.charCodeAt(y)==u.charCodeAt(y);)++y;return Wn(i,function(){sd(i,u.slice(y),l.length-y,null,n.composing?\"*compose\":null),u.length>1e3||u.indexOf(`\n`)>-1?a.value=n.prevInput=\"\":n.prevInput=u,n.composing&&(n.composing.range.clear(),n.composing.range=i.markText(n.composing.start,i.getCursor(\"to\"),{className:\"CodeMirror-composing\"}))}),!0},Wt.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Wt.prototype.onKeyPress=function(){h&&p>=9&&(this.hasSelection=null),this.fastPoll()},Wt.prototype.onContextMenu=function(n){var i=this,a=i.cm,l=a.display,u=i.textarea;i.contextMenuPending&&i.contextMenuPending();var m=ko(a,n),y=l.scroller.scrollTop;if(!m||E)return;var x=a.options.resetSelectionOnContextMenu;x&&a.doc.sel.contains(m)==-1&&Qt(a,un)(a.doc,Fi(m),Q);var S=u.style.cssText,T=i.wrapper.style.cssText,H=i.wrapper.offsetParent.getBoundingClientRect();i.wrapper.style.cssText=\"position: static\",u.style.cssText=`position: absolute; width: 30px; height: 30px;\n      top: `+(n.clientY-H.top-5)+\"px; left: \"+(n.clientX-H.left-5)+`px;\n      z-index: 1000; background: `+(h?\"rgba(255, 255, 255, .05)\":\"transparent\")+`;\n      outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);`;var V;g&&(V=u.ownerDocument.defaultView.scrollY),l.input.focus(),g&&u.ownerDocument.defaultView.scrollTo(null,V),l.input.reset(),a.somethingSelected()||(u.value=i.prevInput=\" \"),i.contextMenuPending=te,l.selForContextMenu=a.doc.sel,clearTimeout(l.detectingSelectAll);function se(){if(u.selectionStart!=null){var we=a.somethingSelected(),Te=\"​\"+(we?u.value:\"\");u.value=\"⇚\",u.value=Te,i.prevInput=we?\"\":\"​\",u.selectionStart=1,u.selectionEnd=Te.length,l.selForContextMenu=a.doc.sel}}function te(){if(i.contextMenuPending==te&&(i.contextMenuPending=!1,i.wrapper.style.cssText=T,u.style.cssText=S,h&&p<9&&l.scrollbars.setScrollTop(l.scroller.scrollTop=y),u.selectionStart!=null)){(!h||h&&p<9)&&se();var we=0,Te=function(){l.selForContextMenu==a.doc.sel&&u.selectionStart==0&&u.selectionEnd>0&&i.prevInput==\"​\"?Qt(a,om)(a):we++<10?l.detectingSelectAll=setTimeout(Te,500):(l.selForContextMenu=null,l.input.reset())};l.detectingSelectAll=setTimeout(Te,200)}}if(h&&p>=9&&se(),G){Oi(n);var pe=function(){an(window,\"mouseup\",pe),setTimeout(te,20)};Xe(window,\"mouseup\",pe)}else setTimeout(te,50)},Wt.prototype.readOnlyChanged=function(n){n||this.reset(),this.textarea.disabled=n==\"nocursor\",this.textarea.readOnly=!!n},Wt.prototype.setUneditable=function(){},Wt.prototype.needsContentAttribute=!1;function OS(n,i){if(i=i?Y(i):{},i.value=n.value,!i.tabindex&&n.tabIndex&&(i.tabindex=n.tabIndex),!i.placeholder&&n.placeholder&&(i.placeholder=n.placeholder),i.autofocus==null){var a=be(Fe(n));i.autofocus=a==n||n.getAttribute(\"autofocus\")!=null&&a==document.body}function l(){n.value=x.getValue()}var u;if(n.form&&(Xe(n.form,\"submit\",l),!i.leaveSubmitMethodAlone)){var m=n.form;u=m.submit;try{var y=m.submit=function(){l(),m.submit=u,m.submit(),m.submit=y}}catch{}}i.finishInit=function(S){S.save=l,S.getTextArea=function(){return n},S.toTextArea=function(){S.toTextArea=isNaN,l(),n.parentNode.removeChild(S.getWrapperElement()),n.style.display=\"\",n.form&&(an(n.form,\"submit\",l),!i.leaveSubmitMethodAlone&&typeof n.form.submit==\"function\"&&(n.form.submit=u))}},n.style.display=\"none\";var x=Ct(function(S){return n.parentNode.insertBefore(S,n.nextSibling)},i);return x}function PS(n){n.off=an,n.on=Xe,n.wheelEventPixels=Hk,n.Doc=Tn,n.splitLines=cr,n.countColumn=re,n.findColumn=ge,n.isWordChar=Je,n.Pass=q,n.signal=Pt,n.Line=os,n.changeEnd=Hi,n.scrollbarModel=$g,n.Pos=fe,n.cmpPos=Ie,n.modes=Qo,n.mimeModes=xr,n.resolveMode=es,n.getMode=ts,n.modeExtensions=$i,n.extendMode=ns,n.copyState=Br,n.startState=rs,n.innerMode=al,n.commands=Ol,n.keyMap=ci,n.keyName=xm,n.isModifierKey=bm,n.lookupKey=ys,n.normalizeKeyMap=aS,n.StringStream=$t,n.SharedTextMarker=Ll,n.TextMarker=Wi,n.LineWidget=Al,n.e_preventDefault=cn,n.e_stopPropagation=Zo,n.e_stop=Oi,n.addClass=Se,n.contains=ce,n.rmClass=N,n.keyNames=qi}_S(Ct),AS(Ct);var RS=\"iter insert remove copy getEditor constructor\".split(\" \");for(var _c in Tn.prototype)Tn.prototype.hasOwnProperty(_c)&&ae(RS,_c)<0&&(Ct.prototype[_c]=(function(n){return function(){return n.apply(this.doc,arguments)}})(Tn.prototype[_c]));return yr(Tn),Ct.inputStyles={textarea:Wt,contenteditable:yt},Ct.defineMode=function(n){!Ct.defaults.mode&&n!=\"null\"&&(Ct.defaults.mode=n),kr.apply(this,arguments)},Ct.defineMIME=bo,Ct.defineMode(\"null\",function(){return{token:function(n){return n.skipToEnd()}}}),Ct.defineMIME(\"text/plain\",\"null\"),Ct.defineExtension=function(n,i){Ct.prototype[n]=i},Ct.defineDocExtension=function(n,i){Tn.prototype[n]=i},Ct.fromTextArea=OS,PS(Ct),Ct.version=\"5.65.18\",Ct}))})(Yc)),Yc.exports}var ML=vo();const NL=ax(ML);var Ad={},Er={};const OL=\"Á\",PL=\"á\",RL=\"Ă\",$L=\"ă\",IL=\"∾\",DL=\"∿\",zL=\"∾̳\",FL=\"Â\",HL=\"â\",BL=\"´\",WL=\"А\",qL=\"а\",jL=\"Æ\",UL=\"æ\",VL=\"⁡\",GL=\"𝔄\",KL=\"𝔞\",XL=\"À\",YL=\"à\",ZL=\"ℵ\",JL=\"ℵ\",QL=\"Α\",eM=\"α\",tM=\"Ā\",nM=\"ā\",rM=\"⨿\",iM=\"&\",oM=\"&\",sM=\"⩕\",lM=\"⩓\",aM=\"∧\",cM=\"⩜\",uM=\"⩘\",fM=\"⩚\",dM=\"∠\",hM=\"⦤\",pM=\"∠\",gM=\"⦨\",mM=\"⦩\",vM=\"⦪\",yM=\"⦫\",bM=\"⦬\",wM=\"⦭\",xM=\"⦮\",kM=\"⦯\",SM=\"∡\",_M=\"∟\",TM=\"⊾\",CM=\"⦝\",EM=\"∢\",AM=\"Å\",LM=\"⍼\",MM=\"Ą\",NM=\"ą\",OM=\"𝔸\",PM=\"𝕒\",RM=\"⩯\",$M=\"≈\",IM=\"⩰\",DM=\"≊\",zM=\"≋\",FM=\"'\",HM=\"⁡\",BM=\"≈\",WM=\"≊\",qM=\"Å\",jM=\"å\",UM=\"𝒜\",VM=\"𝒶\",GM=\"≔\",KM=\"*\",XM=\"≈\",YM=\"≍\",ZM=\"Ã\",JM=\"ã\",QM=\"Ä\",eN=\"ä\",tN=\"∳\",nN=\"⨑\",rN=\"≌\",iN=\"϶\",oN=\"‵\",sN=\"∽\",lN=\"⋍\",aN=\"∖\",cN=\"⫧\",uN=\"⊽\",fN=\"⌅\",dN=\"⌆\",hN=\"⌅\",pN=\"⎵\",gN=\"⎶\",mN=\"≌\",vN=\"Б\",yN=\"б\",bN=\"„\",wN=\"∵\",xN=\"∵\",kN=\"∵\",SN=\"⦰\",_N=\"϶\",TN=\"ℬ\",CN=\"ℬ\",EN=\"Β\",AN=\"β\",LN=\"ℶ\",MN=\"≬\",NN=\"𝔅\",ON=\"𝔟\",PN=\"⋂\",RN=\"◯\",$N=\"⋃\",IN=\"⨀\",DN=\"⨁\",zN=\"⨂\",FN=\"⨆\",HN=\"★\",BN=\"▽\",WN=\"△\",qN=\"⨄\",jN=\"⋁\",UN=\"⋀\",VN=\"⤍\",GN=\"⧫\",KN=\"▪\",XN=\"▴\",YN=\"▾\",ZN=\"◂\",JN=\"▸\",QN=\"␣\",e2=\"▒\",t2=\"░\",n2=\"▓\",r2=\"█\",i2=\"=⃥\",o2=\"≡⃥\",s2=\"⫭\",l2=\"⌐\",a2=\"𝔹\",c2=\"𝕓\",u2=\"⊥\",f2=\"⊥\",d2=\"⋈\",h2=\"⧉\",p2=\"┐\",g2=\"╕\",m2=\"╖\",v2=\"╗\",y2=\"┌\",b2=\"╒\",w2=\"╓\",x2=\"╔\",k2=\"─\",S2=\"═\",_2=\"┬\",T2=\"╤\",C2=\"╥\",E2=\"╦\",A2=\"┴\",L2=\"╧\",M2=\"╨\",N2=\"╩\",O2=\"⊟\",P2=\"⊞\",R2=\"⊠\",$2=\"┘\",I2=\"╛\",D2=\"╜\",z2=\"╝\",F2=\"└\",H2=\"╘\",B2=\"╙\",W2=\"╚\",q2=\"│\",j2=\"║\",U2=\"┼\",V2=\"╪\",G2=\"╫\",K2=\"╬\",X2=\"┤\",Y2=\"╡\",Z2=\"╢\",J2=\"╣\",Q2=\"├\",eO=\"╞\",tO=\"╟\",nO=\"╠\",rO=\"‵\",iO=\"˘\",oO=\"˘\",sO=\"¦\",lO=\"𝒷\",aO=\"ℬ\",cO=\"⁏\",uO=\"∽\",fO=\"⋍\",dO=\"⧅\",hO=\"\\\\\",pO=\"⟈\",gO=\"•\",mO=\"•\",vO=\"≎\",yO=\"⪮\",bO=\"≏\",wO=\"≎\",xO=\"≏\",kO=\"Ć\",SO=\"ć\",_O=\"⩄\",TO=\"⩉\",CO=\"⩋\",EO=\"∩\",AO=\"⋒\",LO=\"⩇\",MO=\"⩀\",NO=\"ⅅ\",OO=\"∩︀\",PO=\"⁁\",RO=\"ˇ\",$O=\"ℭ\",IO=\"⩍\",DO=\"Č\",zO=\"č\",FO=\"Ç\",HO=\"ç\",BO=\"Ĉ\",WO=\"ĉ\",qO=\"∰\",jO=\"⩌\",UO=\"⩐\",VO=\"Ċ\",GO=\"ċ\",KO=\"¸\",XO=\"¸\",YO=\"⦲\",ZO=\"¢\",JO=\"·\",QO=\"·\",eP=\"𝔠\",tP=\"ℭ\",nP=\"Ч\",rP=\"ч\",iP=\"✓\",oP=\"✓\",sP=\"Χ\",lP=\"χ\",aP=\"ˆ\",cP=\"≗\",uP=\"↺\",fP=\"↻\",dP=\"⊛\",hP=\"⊚\",pP=\"⊝\",gP=\"⊙\",mP=\"®\",vP=\"Ⓢ\",yP=\"⊖\",bP=\"⊕\",wP=\"⊗\",xP=\"○\",kP=\"⧃\",SP=\"≗\",_P=\"⨐\",TP=\"⫯\",CP=\"⧂\",EP=\"∲\",AP=\"”\",LP=\"’\",MP=\"♣\",NP=\"♣\",OP=\":\",PP=\"∷\",RP=\"⩴\",$P=\"≔\",IP=\"≔\",DP=\",\",zP=\"@\",FP=\"∁\",HP=\"∘\",BP=\"∁\",WP=\"ℂ\",qP=\"≅\",jP=\"⩭\",UP=\"≡\",VP=\"∮\",GP=\"∯\",KP=\"∮\",XP=\"𝕔\",YP=\"ℂ\",ZP=\"∐\",JP=\"∐\",QP=\"©\",eR=\"©\",tR=\"℗\",nR=\"∳\",rR=\"↵\",iR=\"✗\",oR=\"⨯\",sR=\"𝒞\",lR=\"𝒸\",aR=\"⫏\",cR=\"⫑\",uR=\"⫐\",fR=\"⫒\",dR=\"⋯\",hR=\"⤸\",pR=\"⤵\",gR=\"⋞\",mR=\"⋟\",vR=\"↶\",yR=\"⤽\",bR=\"⩈\",wR=\"⩆\",xR=\"≍\",kR=\"∪\",SR=\"⋓\",_R=\"⩊\",TR=\"⊍\",CR=\"⩅\",ER=\"∪︀\",AR=\"↷\",LR=\"⤼\",MR=\"⋞\",NR=\"⋟\",OR=\"⋎\",PR=\"⋏\",RR=\"¤\",$R=\"↶\",IR=\"↷\",DR=\"⋎\",zR=\"⋏\",FR=\"∲\",HR=\"∱\",BR=\"⌭\",WR=\"†\",qR=\"‡\",jR=\"ℸ\",UR=\"↓\",VR=\"↡\",GR=\"⇓\",KR=\"‐\",XR=\"⫤\",YR=\"⊣\",ZR=\"⤏\",JR=\"˝\",QR=\"Ď\",e$=\"ď\",t$=\"Д\",n$=\"д\",r$=\"‡\",i$=\"⇊\",o$=\"ⅅ\",s$=\"ⅆ\",l$=\"⤑\",a$=\"⩷\",c$=\"°\",u$=\"∇\",f$=\"Δ\",d$=\"δ\",h$=\"⦱\",p$=\"⥿\",g$=\"𝔇\",m$=\"𝔡\",v$=\"⥥\",y$=\"⇃\",b$=\"⇂\",w$=\"´\",x$=\"˙\",k$=\"˝\",S$=\"`\",_$=\"˜\",T$=\"⋄\",C$=\"⋄\",E$=\"⋄\",A$=\"♦\",L$=\"♦\",M$=\"¨\",N$=\"ⅆ\",O$=\"ϝ\",P$=\"⋲\",R$=\"÷\",$$=\"÷\",I$=\"⋇\",D$=\"⋇\",z$=\"Ђ\",F$=\"ђ\",H$=\"⌞\",B$=\"⌍\",W$=\"$\",q$=\"𝔻\",j$=\"𝕕\",U$=\"¨\",V$=\"˙\",G$=\"⃜\",K$=\"≐\",X$=\"≑\",Y$=\"≐\",Z$=\"∸\",J$=\"∔\",Q$=\"⊡\",eI=\"⌆\",tI=\"∯\",nI=\"¨\",rI=\"⇓\",iI=\"⇐\",oI=\"⇔\",sI=\"⫤\",lI=\"⟸\",aI=\"⟺\",cI=\"⟹\",uI=\"⇒\",fI=\"⊨\",dI=\"⇑\",hI=\"⇕\",pI=\"∥\",gI=\"⤓\",mI=\"↓\",vI=\"↓\",yI=\"⇓\",bI=\"⇵\",wI=\"̑\",xI=\"⇊\",kI=\"⇃\",SI=\"⇂\",_I=\"⥐\",TI=\"⥞\",CI=\"⥖\",EI=\"↽\",AI=\"⥟\",LI=\"⥗\",MI=\"⇁\",NI=\"↧\",OI=\"⊤\",PI=\"⤐\",RI=\"⌟\",$I=\"⌌\",II=\"𝒟\",DI=\"𝒹\",zI=\"Ѕ\",FI=\"ѕ\",HI=\"⧶\",BI=\"Đ\",WI=\"đ\",qI=\"⋱\",jI=\"▿\",UI=\"▾\",VI=\"⇵\",GI=\"⥯\",KI=\"⦦\",XI=\"Џ\",YI=\"џ\",ZI=\"⟿\",JI=\"É\",QI=\"é\",eD=\"⩮\",tD=\"Ě\",nD=\"ě\",rD=\"Ê\",iD=\"ê\",oD=\"≖\",sD=\"≕\",lD=\"Э\",aD=\"э\",cD=\"⩷\",uD=\"Ė\",fD=\"ė\",dD=\"≑\",hD=\"ⅇ\",pD=\"≒\",gD=\"𝔈\",mD=\"𝔢\",vD=\"⪚\",yD=\"È\",bD=\"è\",wD=\"⪖\",xD=\"⪘\",kD=\"⪙\",SD=\"∈\",_D=\"⏧\",TD=\"ℓ\",CD=\"⪕\",ED=\"⪗\",AD=\"Ē\",LD=\"ē\",MD=\"∅\",ND=\"∅\",OD=\"◻\",PD=\"∅\",RD=\"▫\",$D=\" \",ID=\" \",DD=\" \",zD=\"Ŋ\",FD=\"ŋ\",HD=\" \",BD=\"Ę\",WD=\"ę\",qD=\"𝔼\",jD=\"𝕖\",UD=\"⋕\",VD=\"⧣\",GD=\"⩱\",KD=\"ε\",XD=\"Ε\",YD=\"ε\",ZD=\"ϵ\",JD=\"≖\",QD=\"≕\",ez=\"≂\",tz=\"⪖\",nz=\"⪕\",rz=\"⩵\",iz=\"=\",oz=\"≂\",sz=\"≟\",lz=\"⇌\",az=\"≡\",cz=\"⩸\",uz=\"⧥\",fz=\"⥱\",dz=\"≓\",hz=\"ℯ\",pz=\"ℰ\",gz=\"≐\",mz=\"⩳\",vz=\"≂\",yz=\"Η\",bz=\"η\",wz=\"Ð\",xz=\"ð\",kz=\"Ë\",Sz=\"ë\",_z=\"€\",Tz=\"!\",Cz=\"∃\",Ez=\"∃\",Az=\"ℰ\",Lz=\"ⅇ\",Mz=\"ⅇ\",Nz=\"≒\",Oz=\"Ф\",Pz=\"ф\",Rz=\"♀\",$z=\"ﬃ\",Iz=\"ﬀ\",Dz=\"ﬄ\",zz=\"𝔉\",Fz=\"𝔣\",Hz=\"ﬁ\",Bz=\"◼\",Wz=\"▪\",qz=\"fj\",jz=\"♭\",Uz=\"ﬂ\",Vz=\"▱\",Gz=\"ƒ\",Kz=\"𝔽\",Xz=\"𝕗\",Yz=\"∀\",Zz=\"∀\",Jz=\"⋔\",Qz=\"⫙\",eF=\"ℱ\",tF=\"⨍\",nF=\"½\",rF=\"⅓\",iF=\"¼\",oF=\"⅕\",sF=\"⅙\",lF=\"⅛\",aF=\"⅔\",cF=\"⅖\",uF=\"¾\",fF=\"⅗\",dF=\"⅜\",hF=\"⅘\",pF=\"⅚\",gF=\"⅝\",mF=\"⅞\",vF=\"⁄\",yF=\"⌢\",bF=\"𝒻\",wF=\"ℱ\",xF=\"ǵ\",kF=\"Γ\",SF=\"γ\",_F=\"Ϝ\",TF=\"ϝ\",CF=\"⪆\",EF=\"Ğ\",AF=\"ğ\",LF=\"Ģ\",MF=\"Ĝ\",NF=\"ĝ\",OF=\"Г\",PF=\"г\",RF=\"Ġ\",$F=\"ġ\",IF=\"≥\",DF=\"≧\",zF=\"⪌\",FF=\"⋛\",HF=\"≥\",BF=\"≧\",WF=\"⩾\",qF=\"⪩\",jF=\"⩾\",UF=\"⪀\",VF=\"⪂\",GF=\"⪄\",KF=\"⋛︀\",XF=\"⪔\",YF=\"𝔊\",ZF=\"𝔤\",JF=\"≫\",QF=\"⋙\",eH=\"⋙\",tH=\"ℷ\",nH=\"Ѓ\",rH=\"ѓ\",iH=\"⪥\",oH=\"≷\",sH=\"⪒\",lH=\"⪤\",aH=\"⪊\",cH=\"⪊\",uH=\"⪈\",fH=\"≩\",dH=\"⪈\",hH=\"≩\",pH=\"⋧\",gH=\"𝔾\",mH=\"𝕘\",vH=\"`\",yH=\"≥\",bH=\"⋛\",wH=\"≧\",xH=\"⪢\",kH=\"≷\",SH=\"⩾\",_H=\"≳\",TH=\"𝒢\",CH=\"ℊ\",EH=\"≳\",AH=\"⪎\",LH=\"⪐\",MH=\"⪧\",NH=\"⩺\",OH=\">\",PH=\">\",RH=\"≫\",$H=\"⋗\",IH=\"⦕\",DH=\"⩼\",zH=\"⪆\",FH=\"⥸\",HH=\"⋗\",BH=\"⋛\",WH=\"⪌\",qH=\"≷\",jH=\"≳\",UH=\"≩︀\",VH=\"≩︀\",GH=\"ˇ\",KH=\" \",XH=\"½\",YH=\"ℋ\",ZH=\"Ъ\",JH=\"ъ\",QH=\"⥈\",e3=\"↔\",t3=\"⇔\",n3=\"↭\",r3=\"^\",i3=\"ℏ\",o3=\"Ĥ\",s3=\"ĥ\",l3=\"♥\",a3=\"♥\",c3=\"…\",u3=\"⊹\",f3=\"𝔥\",d3=\"ℌ\",h3=\"ℋ\",p3=\"⤥\",g3=\"⤦\",m3=\"⇿\",v3=\"∻\",y3=\"↩\",b3=\"↪\",w3=\"𝕙\",x3=\"ℍ\",k3=\"―\",S3=\"─\",_3=\"𝒽\",T3=\"ℋ\",C3=\"ℏ\",E3=\"Ħ\",A3=\"ħ\",L3=\"≎\",M3=\"≏\",N3=\"⁃\",O3=\"‐\",P3=\"Í\",R3=\"í\",$3=\"⁣\",I3=\"Î\",D3=\"î\",z3=\"И\",F3=\"и\",H3=\"İ\",B3=\"Е\",W3=\"е\",q3=\"¡\",j3=\"⇔\",U3=\"𝔦\",V3=\"ℑ\",G3=\"Ì\",K3=\"ì\",X3=\"ⅈ\",Y3=\"⨌\",Z3=\"∭\",J3=\"⧜\",Q3=\"℩\",eB=\"Ĳ\",tB=\"ĳ\",nB=\"Ī\",rB=\"ī\",iB=\"ℑ\",oB=\"ⅈ\",sB=\"ℐ\",lB=\"ℑ\",aB=\"ı\",cB=\"ℑ\",uB=\"⊷\",fB=\"Ƶ\",dB=\"⇒\",hB=\"℅\",pB=\"∞\",gB=\"⧝\",mB=\"ı\",vB=\"⊺\",yB=\"∫\",bB=\"∬\",wB=\"ℤ\",xB=\"∫\",kB=\"⊺\",SB=\"⋂\",_B=\"⨗\",TB=\"⨼\",CB=\"⁣\",EB=\"⁢\",AB=\"Ё\",LB=\"ё\",MB=\"Į\",NB=\"į\",OB=\"𝕀\",PB=\"𝕚\",RB=\"Ι\",$B=\"ι\",IB=\"⨼\",DB=\"¿\",zB=\"𝒾\",FB=\"ℐ\",HB=\"∈\",BB=\"⋵\",WB=\"⋹\",qB=\"⋴\",jB=\"⋳\",UB=\"∈\",VB=\"⁢\",GB=\"Ĩ\",KB=\"ĩ\",XB=\"І\",YB=\"і\",ZB=\"Ï\",JB=\"ï\",QB=\"Ĵ\",e5=\"ĵ\",t5=\"Й\",n5=\"й\",r5=\"𝔍\",i5=\"𝔧\",o5=\"ȷ\",s5=\"𝕁\",l5=\"𝕛\",a5=\"𝒥\",c5=\"𝒿\",u5=\"Ј\",f5=\"ј\",d5=\"Є\",h5=\"є\",p5=\"Κ\",g5=\"κ\",m5=\"ϰ\",v5=\"Ķ\",y5=\"ķ\",b5=\"К\",w5=\"к\",x5=\"𝔎\",k5=\"𝔨\",S5=\"ĸ\",_5=\"Х\",T5=\"х\",C5=\"Ќ\",E5=\"ќ\",A5=\"𝕂\",L5=\"𝕜\",M5=\"𝒦\",N5=\"𝓀\",O5=\"⇚\",P5=\"Ĺ\",R5=\"ĺ\",$5=\"⦴\",I5=\"ℒ\",D5=\"Λ\",z5=\"λ\",F5=\"⟨\",H5=\"⟪\",B5=\"⦑\",W5=\"⟨\",q5=\"⪅\",j5=\"ℒ\",U5=\"«\",V5=\"⇤\",G5=\"⤟\",K5=\"←\",X5=\"↞\",Y5=\"⇐\",Z5=\"⤝\",J5=\"↩\",Q5=\"↫\",e8=\"⤹\",t8=\"⥳\",n8=\"↢\",r8=\"⤙\",i8=\"⤛\",o8=\"⪫\",s8=\"⪭\",l8=\"⪭︀\",a8=\"⤌\",c8=\"⤎\",u8=\"❲\",f8=\"{\",d8=\"[\",h8=\"⦋\",p8=\"⦏\",g8=\"⦍\",m8=\"Ľ\",v8=\"ľ\",y8=\"Ļ\",b8=\"ļ\",w8=\"⌈\",x8=\"{\",k8=\"Л\",S8=\"л\",_8=\"⤶\",T8=\"“\",C8=\"„\",E8=\"⥧\",A8=\"⥋\",L8=\"↲\",M8=\"≤\",N8=\"≦\",O8=\"⟨\",P8=\"⇤\",R8=\"←\",$8=\"←\",I8=\"⇐\",D8=\"⇆\",z8=\"↢\",F8=\"⌈\",H8=\"⟦\",B8=\"⥡\",W8=\"⥙\",q8=\"⇃\",j8=\"⌊\",U8=\"↽\",V8=\"↼\",G8=\"⇇\",K8=\"↔\",X8=\"↔\",Y8=\"⇔\",Z8=\"⇆\",J8=\"⇋\",Q8=\"↭\",eW=\"⥎\",tW=\"↤\",nW=\"⊣\",rW=\"⥚\",iW=\"⋋\",oW=\"⧏\",sW=\"⊲\",lW=\"⊴\",aW=\"⥑\",cW=\"⥠\",uW=\"⥘\",fW=\"↿\",dW=\"⥒\",hW=\"↼\",pW=\"⪋\",gW=\"⋚\",mW=\"≤\",vW=\"≦\",yW=\"⩽\",bW=\"⪨\",wW=\"⩽\",xW=\"⩿\",kW=\"⪁\",SW=\"⪃\",_W=\"⋚︀\",TW=\"⪓\",CW=\"⪅\",EW=\"⋖\",AW=\"⋚\",LW=\"⪋\",MW=\"⋚\",NW=\"≦\",OW=\"≶\",PW=\"≶\",RW=\"⪡\",$W=\"≲\",IW=\"⩽\",DW=\"≲\",zW=\"⥼\",FW=\"⌊\",HW=\"𝔏\",BW=\"𝔩\",WW=\"≶\",qW=\"⪑\",jW=\"⥢\",UW=\"↽\",VW=\"↼\",GW=\"⥪\",KW=\"▄\",XW=\"Љ\",YW=\"љ\",ZW=\"⇇\",JW=\"≪\",QW=\"⋘\",e4=\"⌞\",t4=\"⇚\",n4=\"⥫\",r4=\"◺\",i4=\"Ŀ\",o4=\"ŀ\",s4=\"⎰\",l4=\"⎰\",a4=\"⪉\",c4=\"⪉\",u4=\"⪇\",f4=\"≨\",d4=\"⪇\",h4=\"≨\",p4=\"⋦\",g4=\"⟬\",m4=\"⇽\",v4=\"⟦\",y4=\"⟵\",b4=\"⟵\",w4=\"⟸\",x4=\"⟷\",k4=\"⟷\",S4=\"⟺\",_4=\"⟼\",T4=\"⟶\",C4=\"⟶\",E4=\"⟹\",A4=\"↫\",L4=\"↬\",M4=\"⦅\",N4=\"𝕃\",O4=\"𝕝\",P4=\"⨭\",R4=\"⨴\",$4=\"∗\",I4=\"_\",D4=\"↙\",z4=\"↘\",F4=\"◊\",H4=\"◊\",B4=\"⧫\",W4=\"(\",q4=\"⦓\",j4=\"⇆\",U4=\"⌟\",V4=\"⇋\",G4=\"⥭\",K4=\"‎\",X4=\"⊿\",Y4=\"‹\",Z4=\"𝓁\",J4=\"ℒ\",Q4=\"↰\",eq=\"↰\",tq=\"≲\",nq=\"⪍\",rq=\"⪏\",iq=\"[\",oq=\"‘\",sq=\"‚\",lq=\"Ł\",aq=\"ł\",cq=\"⪦\",uq=\"⩹\",fq=\"<\",dq=\"<\",hq=\"≪\",pq=\"⋖\",gq=\"⋋\",mq=\"⋉\",vq=\"⥶\",yq=\"⩻\",bq=\"◃\",wq=\"⊴\",xq=\"◂\",kq=\"⦖\",Sq=\"⥊\",_q=\"⥦\",Tq=\"≨︀\",Cq=\"≨︀\",Eq=\"¯\",Aq=\"♂\",Lq=\"✠\",Mq=\"✠\",Nq=\"↦\",Oq=\"↦\",Pq=\"↧\",Rq=\"↤\",$q=\"↥\",Iq=\"▮\",Dq=\"⨩\",zq=\"М\",Fq=\"м\",Hq=\"—\",Bq=\"∺\",Wq=\"∡\",qq=\" \",jq=\"ℳ\",Uq=\"𝔐\",Vq=\"𝔪\",Gq=\"℧\",Kq=\"µ\",Xq=\"*\",Yq=\"⫰\",Zq=\"∣\",Jq=\"·\",Qq=\"⊟\",ej=\"−\",tj=\"∸\",nj=\"⨪\",rj=\"∓\",ij=\"⫛\",oj=\"…\",sj=\"∓\",lj=\"⊧\",aj=\"𝕄\",cj=\"𝕞\",uj=\"∓\",fj=\"𝓂\",dj=\"ℳ\",hj=\"∾\",pj=\"Μ\",gj=\"μ\",mj=\"⊸\",vj=\"⊸\",yj=\"∇\",bj=\"Ń\",wj=\"ń\",xj=\"∠⃒\",kj=\"≉\",Sj=\"⩰̸\",_j=\"≋̸\",Tj=\"ŉ\",Cj=\"≉\",Ej=\"♮\",Aj=\"ℕ\",Lj=\"♮\",Mj=\" \",Nj=\"≎̸\",Oj=\"≏̸\",Pj=\"⩃\",Rj=\"Ň\",$j=\"ň\",Ij=\"Ņ\",Dj=\"ņ\",zj=\"≇\",Fj=\"⩭̸\",Hj=\"⩂\",Bj=\"Н\",Wj=\"н\",qj=\"–\",jj=\"⤤\",Uj=\"↗\",Vj=\"⇗\",Gj=\"↗\",Kj=\"≠\",Xj=\"≐̸\",Yj=\"​\",Zj=\"​\",Jj=\"​\",Qj=\"​\",eU=\"≢\",tU=\"⤨\",nU=\"≂̸\",rU=\"≫\",iU=\"≪\",oU=`\n`,sU=\"∄\",lU=\"∄\",aU=\"𝔑\",cU=\"𝔫\",uU=\"≧̸\",fU=\"≱\",dU=\"≱\",hU=\"≧̸\",pU=\"⩾̸\",gU=\"⩾̸\",mU=\"⋙̸\",vU=\"≵\",yU=\"≫⃒\",bU=\"≯\",wU=\"≯\",xU=\"≫̸\",kU=\"↮\",SU=\"⇎\",_U=\"⫲\",TU=\"∋\",CU=\"⋼\",EU=\"⋺\",AU=\"∋\",LU=\"Њ\",MU=\"њ\",NU=\"↚\",OU=\"⇍\",PU=\"‥\",RU=\"≦̸\",$U=\"≰\",IU=\"↚\",DU=\"⇍\",zU=\"↮\",FU=\"⇎\",HU=\"≰\",BU=\"≦̸\",WU=\"⩽̸\",qU=\"⩽̸\",jU=\"≮\",UU=\"⋘̸\",VU=\"≴\",GU=\"≪⃒\",KU=\"≮\",XU=\"⋪\",YU=\"⋬\",ZU=\"≪̸\",JU=\"∤\",QU=\"⁠\",e6=\" \",t6=\"𝕟\",n6=\"ℕ\",r6=\"⫬\",i6=\"¬\",o6=\"≢\",s6=\"≭\",l6=\"∦\",a6=\"∉\",c6=\"≠\",u6=\"≂̸\",f6=\"∄\",d6=\"≯\",h6=\"≱\",p6=\"≧̸\",g6=\"≫̸\",m6=\"≹\",v6=\"⩾̸\",y6=\"≵\",b6=\"≎̸\",w6=\"≏̸\",x6=\"∉\",k6=\"⋵̸\",S6=\"⋹̸\",_6=\"∉\",T6=\"⋷\",C6=\"⋶\",E6=\"⧏̸\",A6=\"⋪\",L6=\"⋬\",M6=\"≮\",N6=\"≰\",O6=\"≸\",P6=\"≪̸\",R6=\"⩽̸\",$6=\"≴\",I6=\"⪢̸\",D6=\"⪡̸\",z6=\"∌\",F6=\"∌\",H6=\"⋾\",B6=\"⋽\",W6=\"⊀\",q6=\"⪯̸\",j6=\"⋠\",U6=\"∌\",V6=\"⧐̸\",G6=\"⋫\",K6=\"⋭\",X6=\"⊏̸\",Y6=\"⋢\",Z6=\"⊐̸\",J6=\"⋣\",Q6=\"⊂⃒\",eV=\"⊈\",tV=\"⊁\",nV=\"⪰̸\",rV=\"⋡\",iV=\"≿̸\",oV=\"⊃⃒\",sV=\"⊉\",lV=\"≁\",aV=\"≄\",cV=\"≇\",uV=\"≉\",fV=\"∤\",dV=\"∦\",hV=\"∦\",pV=\"⫽⃥\",gV=\"∂̸\",mV=\"⨔\",vV=\"⊀\",yV=\"⋠\",bV=\"⊀\",wV=\"⪯̸\",xV=\"⪯̸\",kV=\"⤳̸\",SV=\"↛\",_V=\"⇏\",TV=\"↝̸\",CV=\"↛\",EV=\"⇏\",AV=\"⋫\",LV=\"⋭\",MV=\"⊁\",NV=\"⋡\",OV=\"⪰̸\",PV=\"𝒩\",RV=\"𝓃\",$V=\"∤\",IV=\"∦\",DV=\"≁\",zV=\"≄\",FV=\"≄\",HV=\"∤\",BV=\"∦\",WV=\"⋢\",qV=\"⋣\",jV=\"⊄\",UV=\"⫅̸\",VV=\"⊈\",GV=\"⊂⃒\",KV=\"⊈\",XV=\"⫅̸\",YV=\"⊁\",ZV=\"⪰̸\",JV=\"⊅\",QV=\"⫆̸\",eG=\"⊉\",tG=\"⊃⃒\",nG=\"⊉\",rG=\"⫆̸\",iG=\"≹\",oG=\"Ñ\",sG=\"ñ\",lG=\"≸\",aG=\"⋪\",cG=\"⋬\",uG=\"⋫\",fG=\"⋭\",dG=\"Ν\",hG=\"ν\",pG=\"#\",gG=\"№\",mG=\" \",vG=\"≍⃒\",yG=\"⊬\",bG=\"⊭\",wG=\"⊮\",xG=\"⊯\",kG=\"≥⃒\",SG=\">⃒\",_G=\"⤄\",TG=\"⧞\",CG=\"⤂\",EG=\"≤⃒\",AG=\"<⃒\",LG=\"⊴⃒\",MG=\"⤃\",NG=\"⊵⃒\",OG=\"∼⃒\",PG=\"⤣\",RG=\"↖\",$G=\"⇖\",IG=\"↖\",DG=\"⤧\",zG=\"Ó\",FG=\"ó\",HG=\"⊛\",BG=\"Ô\",WG=\"ô\",qG=\"⊚\",jG=\"О\",UG=\"о\",VG=\"⊝\",GG=\"Ő\",KG=\"ő\",XG=\"⨸\",YG=\"⊙\",ZG=\"⦼\",JG=\"Œ\",QG=\"œ\",e9=\"⦿\",t9=\"𝔒\",n9=\"𝔬\",r9=\"˛\",i9=\"Ò\",o9=\"ò\",s9=\"⧁\",l9=\"⦵\",a9=\"Ω\",c9=\"∮\",u9=\"↺\",f9=\"⦾\",d9=\"⦻\",h9=\"‾\",p9=\"⧀\",g9=\"Ō\",m9=\"ō\",v9=\"Ω\",y9=\"ω\",b9=\"Ο\",w9=\"ο\",x9=\"⦶\",k9=\"⊖\",S9=\"𝕆\",_9=\"𝕠\",T9=\"⦷\",C9=\"“\",E9=\"‘\",A9=\"⦹\",L9=\"⊕\",M9=\"↻\",N9=\"⩔\",O9=\"∨\",P9=\"⩝\",R9=\"ℴ\",$9=\"ℴ\",I9=\"ª\",D9=\"º\",z9=\"⊶\",F9=\"⩖\",H9=\"⩗\",B9=\"⩛\",W9=\"Ⓢ\",q9=\"𝒪\",j9=\"ℴ\",U9=\"Ø\",V9=\"ø\",G9=\"⊘\",K9=\"Õ\",X9=\"õ\",Y9=\"⨶\",Z9=\"⨷\",J9=\"⊗\",Q9=\"Ö\",eK=\"ö\",tK=\"⌽\",nK=\"‾\",rK=\"⏞\",iK=\"⎴\",oK=\"⏜\",sK=\"¶\",lK=\"∥\",aK=\"∥\",cK=\"⫳\",uK=\"⫽\",fK=\"∂\",dK=\"∂\",hK=\"П\",pK=\"п\",gK=\"%\",mK=\".\",vK=\"‰\",yK=\"⊥\",bK=\"‱\",wK=\"𝔓\",xK=\"𝔭\",kK=\"Φ\",SK=\"φ\",_K=\"ϕ\",TK=\"ℳ\",CK=\"☎\",EK=\"Π\",AK=\"π\",LK=\"⋔\",MK=\"ϖ\",NK=\"ℏ\",OK=\"ℎ\",PK=\"ℏ\",RK=\"⨣\",$K=\"⊞\",IK=\"⨢\",DK=\"+\",zK=\"∔\",FK=\"⨥\",HK=\"⩲\",BK=\"±\",WK=\"±\",qK=\"⨦\",jK=\"⨧\",UK=\"±\",VK=\"ℌ\",GK=\"⨕\",KK=\"𝕡\",XK=\"ℙ\",YK=\"£\",ZK=\"⪷\",JK=\"⪻\",QK=\"≺\",e7=\"≼\",t7=\"⪷\",n7=\"≺\",r7=\"≼\",i7=\"≺\",o7=\"⪯\",s7=\"≼\",l7=\"≾\",a7=\"⪯\",c7=\"⪹\",u7=\"⪵\",f7=\"⋨\",d7=\"⪯\",h7=\"⪳\",p7=\"≾\",g7=\"′\",m7=\"″\",v7=\"ℙ\",y7=\"⪹\",b7=\"⪵\",w7=\"⋨\",x7=\"∏\",k7=\"∏\",S7=\"⌮\",_7=\"⌒\",T7=\"⌓\",C7=\"∝\",E7=\"∝\",A7=\"∷\",L7=\"∝\",M7=\"≾\",N7=\"⊰\",O7=\"𝒫\",P7=\"𝓅\",R7=\"Ψ\",$7=\"ψ\",I7=\" \",D7=\"𝔔\",z7=\"𝔮\",F7=\"⨌\",H7=\"𝕢\",B7=\"ℚ\",W7=\"⁗\",q7=\"𝒬\",j7=\"𝓆\",U7=\"ℍ\",V7=\"⨖\",G7=\"?\",K7=\"≟\",X7='\"',Y7='\"',Z7=\"⇛\",J7=\"∽̱\",Q7=\"Ŕ\",eX=\"ŕ\",tX=\"√\",nX=\"⦳\",rX=\"⟩\",iX=\"⟫\",oX=\"⦒\",sX=\"⦥\",lX=\"⟩\",aX=\"»\",cX=\"⥵\",uX=\"⇥\",fX=\"⤠\",dX=\"⤳\",hX=\"→\",pX=\"↠\",gX=\"⇒\",mX=\"⤞\",vX=\"↪\",yX=\"↬\",bX=\"⥅\",wX=\"⥴\",xX=\"⤖\",kX=\"↣\",SX=\"↝\",_X=\"⤚\",TX=\"⤜\",CX=\"∶\",EX=\"ℚ\",AX=\"⤍\",LX=\"⤏\",MX=\"⤐\",NX=\"❳\",OX=\"}\",PX=\"]\",RX=\"⦌\",$X=\"⦎\",IX=\"⦐\",DX=\"Ř\",zX=\"ř\",FX=\"Ŗ\",HX=\"ŗ\",BX=\"⌉\",WX=\"}\",qX=\"Р\",jX=\"р\",UX=\"⤷\",VX=\"⥩\",GX=\"”\",KX=\"”\",XX=\"↳\",YX=\"ℜ\",ZX=\"ℛ\",JX=\"ℜ\",QX=\"ℝ\",eY=\"ℜ\",tY=\"▭\",nY=\"®\",rY=\"®\",iY=\"∋\",oY=\"⇋\",sY=\"⥯\",lY=\"⥽\",aY=\"⌋\",cY=\"𝔯\",uY=\"ℜ\",fY=\"⥤\",dY=\"⇁\",hY=\"⇀\",pY=\"⥬\",gY=\"Ρ\",mY=\"ρ\",vY=\"ϱ\",yY=\"⟩\",bY=\"⇥\",wY=\"→\",xY=\"→\",kY=\"⇒\",SY=\"⇄\",_Y=\"↣\",TY=\"⌉\",CY=\"⟧\",EY=\"⥝\",AY=\"⥕\",LY=\"⇂\",MY=\"⌋\",NY=\"⇁\",OY=\"⇀\",PY=\"⇄\",RY=\"⇌\",$Y=\"⇉\",IY=\"↝\",DY=\"↦\",zY=\"⊢\",FY=\"⥛\",HY=\"⋌\",BY=\"⧐\",WY=\"⊳\",qY=\"⊵\",jY=\"⥏\",UY=\"⥜\",VY=\"⥔\",GY=\"↾\",KY=\"⥓\",XY=\"⇀\",YY=\"˚\",ZY=\"≓\",JY=\"⇄\",QY=\"⇌\",eZ=\"‏\",tZ=\"⎱\",nZ=\"⎱\",rZ=\"⫮\",iZ=\"⟭\",oZ=\"⇾\",sZ=\"⟧\",lZ=\"⦆\",aZ=\"𝕣\",cZ=\"ℝ\",uZ=\"⨮\",fZ=\"⨵\",dZ=\"⥰\",hZ=\")\",pZ=\"⦔\",gZ=\"⨒\",mZ=\"⇉\",vZ=\"⇛\",yZ=\"›\",bZ=\"𝓇\",wZ=\"ℛ\",xZ=\"↱\",kZ=\"↱\",SZ=\"]\",_Z=\"’\",TZ=\"’\",CZ=\"⋌\",EZ=\"⋊\",AZ=\"▹\",LZ=\"⊵\",MZ=\"▸\",NZ=\"⧎\",OZ=\"⧴\",PZ=\"⥨\",RZ=\"℞\",$Z=\"Ś\",IZ=\"ś\",DZ=\"‚\",zZ=\"⪸\",FZ=\"Š\",HZ=\"š\",BZ=\"⪼\",WZ=\"≻\",qZ=\"≽\",jZ=\"⪰\",UZ=\"⪴\",VZ=\"Ş\",GZ=\"ş\",KZ=\"Ŝ\",XZ=\"ŝ\",YZ=\"⪺\",ZZ=\"⪶\",JZ=\"⋩\",QZ=\"⨓\",eJ=\"≿\",tJ=\"С\",nJ=\"с\",rJ=\"⊡\",iJ=\"⋅\",oJ=\"⩦\",sJ=\"⤥\",lJ=\"↘\",aJ=\"⇘\",cJ=\"↘\",uJ=\"§\",fJ=\";\",dJ=\"⤩\",hJ=\"∖\",pJ=\"∖\",gJ=\"✶\",mJ=\"𝔖\",vJ=\"𝔰\",yJ=\"⌢\",bJ=\"♯\",wJ=\"Щ\",xJ=\"щ\",kJ=\"Ш\",SJ=\"ш\",_J=\"↓\",TJ=\"←\",CJ=\"∣\",EJ=\"∥\",AJ=\"→\",LJ=\"↑\",MJ=\"­\",NJ=\"Σ\",OJ=\"σ\",PJ=\"ς\",RJ=\"ς\",$J=\"∼\",IJ=\"⩪\",DJ=\"≃\",zJ=\"≃\",FJ=\"⪞\",HJ=\"⪠\",BJ=\"⪝\",WJ=\"⪟\",qJ=\"≆\",jJ=\"⨤\",UJ=\"⥲\",VJ=\"←\",GJ=\"∘\",KJ=\"∖\",XJ=\"⨳\",YJ=\"⧤\",ZJ=\"∣\",JJ=\"⌣\",QJ=\"⪪\",eQ=\"⪬\",tQ=\"⪬︀\",nQ=\"Ь\",rQ=\"ь\",iQ=\"⌿\",oQ=\"⧄\",sQ=\"/\",lQ=\"𝕊\",aQ=\"𝕤\",cQ=\"♠\",uQ=\"♠\",fQ=\"∥\",dQ=\"⊓\",hQ=\"⊓︀\",pQ=\"⊔\",gQ=\"⊔︀\",mQ=\"√\",vQ=\"⊏\",yQ=\"⊑\",bQ=\"⊏\",wQ=\"⊑\",xQ=\"⊐\",kQ=\"⊒\",SQ=\"⊐\",_Q=\"⊒\",TQ=\"□\",CQ=\"□\",EQ=\"⊓\",AQ=\"⊏\",LQ=\"⊑\",MQ=\"⊐\",NQ=\"⊒\",OQ=\"⊔\",PQ=\"▪\",RQ=\"□\",$Q=\"▪\",IQ=\"→\",DQ=\"𝒮\",zQ=\"𝓈\",FQ=\"∖\",HQ=\"⌣\",BQ=\"⋆\",WQ=\"⋆\",qQ=\"☆\",jQ=\"★\",UQ=\"ϵ\",VQ=\"ϕ\",GQ=\"¯\",KQ=\"⊂\",XQ=\"⋐\",YQ=\"⪽\",ZQ=\"⫅\",JQ=\"⊆\",QQ=\"⫃\",eee=\"⫁\",tee=\"⫋\",nee=\"⊊\",ree=\"⪿\",iee=\"⥹\",oee=\"⊂\",see=\"⋐\",lee=\"⊆\",aee=\"⫅\",cee=\"⊆\",uee=\"⊊\",fee=\"⫋\",dee=\"⫇\",hee=\"⫕\",pee=\"⫓\",gee=\"⪸\",mee=\"≻\",vee=\"≽\",yee=\"≻\",bee=\"⪰\",wee=\"≽\",xee=\"≿\",kee=\"⪰\",See=\"⪺\",_ee=\"⪶\",Tee=\"⋩\",Cee=\"≿\",Eee=\"∋\",Aee=\"∑\",Lee=\"∑\",Mee=\"♪\",Nee=\"¹\",Oee=\"²\",Pee=\"³\",Ree=\"⊃\",$ee=\"⋑\",Iee=\"⪾\",Dee=\"⫘\",zee=\"⫆\",Fee=\"⊇\",Hee=\"⫄\",Bee=\"⊃\",Wee=\"⊇\",qee=\"⟉\",jee=\"⫗\",Uee=\"⥻\",Vee=\"⫂\",Gee=\"⫌\",Kee=\"⊋\",Xee=\"⫀\",Yee=\"⊃\",Zee=\"⋑\",Jee=\"⊇\",Qee=\"⫆\",ete=\"⊋\",tte=\"⫌\",nte=\"⫈\",rte=\"⫔\",ite=\"⫖\",ote=\"⤦\",ste=\"↙\",lte=\"⇙\",ate=\"↙\",cte=\"⤪\",ute=\"ß\",fte=\"\t\",dte=\"⌖\",hte=\"Τ\",pte=\"τ\",gte=\"⎴\",mte=\"Ť\",vte=\"ť\",yte=\"Ţ\",bte=\"ţ\",wte=\"Т\",xte=\"т\",kte=\"⃛\",Ste=\"⌕\",_te=\"𝔗\",Tte=\"𝔱\",Cte=\"∴\",Ete=\"∴\",Ate=\"∴\",Lte=\"Θ\",Mte=\"θ\",Nte=\"ϑ\",Ote=\"ϑ\",Pte=\"≈\",Rte=\"∼\",$te=\"  \",Ite=\" \",Dte=\" \",zte=\"≈\",Fte=\"∼\",Hte=\"Þ\",Bte=\"þ\",Wte=\"˜\",qte=\"∼\",jte=\"≃\",Ute=\"≅\",Vte=\"≈\",Gte=\"⨱\",Kte=\"⊠\",Xte=\"×\",Yte=\"⨰\",Zte=\"∭\",Jte=\"⤨\",Qte=\"⌶\",ene=\"⫱\",tne=\"⊤\",nne=\"𝕋\",rne=\"𝕥\",ine=\"⫚\",one=\"⤩\",sne=\"‴\",lne=\"™\",ane=\"™\",cne=\"▵\",une=\"▿\",fne=\"◃\",dne=\"⊴\",hne=\"≜\",pne=\"▹\",gne=\"⊵\",mne=\"◬\",vne=\"≜\",yne=\"⨺\",bne=\"⃛\",wne=\"⨹\",xne=\"⧍\",kne=\"⨻\",Sne=\"⏢\",_ne=\"𝒯\",Tne=\"𝓉\",Cne=\"Ц\",Ene=\"ц\",Ane=\"Ћ\",Lne=\"ћ\",Mne=\"Ŧ\",Nne=\"ŧ\",One=\"≬\",Pne=\"↞\",Rne=\"↠\",$ne=\"Ú\",Ine=\"ú\",Dne=\"↑\",zne=\"↟\",Fne=\"⇑\",Hne=\"⥉\",Bne=\"Ў\",Wne=\"ў\",qne=\"Ŭ\",jne=\"ŭ\",Une=\"Û\",Vne=\"û\",Gne=\"У\",Kne=\"у\",Xne=\"⇅\",Yne=\"Ű\",Zne=\"ű\",Jne=\"⥮\",Qne=\"⥾\",ere=\"𝔘\",tre=\"𝔲\",nre=\"Ù\",rre=\"ù\",ire=\"⥣\",ore=\"↿\",sre=\"↾\",lre=\"▀\",are=\"⌜\",cre=\"⌜\",ure=\"⌏\",fre=\"◸\",dre=\"Ū\",hre=\"ū\",pre=\"¨\",gre=\"_\",mre=\"⏟\",vre=\"⎵\",yre=\"⏝\",bre=\"⋃\",wre=\"⊎\",xre=\"Ų\",kre=\"ų\",Sre=\"𝕌\",_re=\"𝕦\",Tre=\"⤒\",Cre=\"↑\",Ere=\"↑\",Are=\"⇑\",Lre=\"⇅\",Mre=\"↕\",Nre=\"↕\",Ore=\"⇕\",Pre=\"⥮\",Rre=\"↿\",$re=\"↾\",Ire=\"⊎\",Dre=\"↖\",zre=\"↗\",Fre=\"υ\",Hre=\"ϒ\",Bre=\"ϒ\",Wre=\"Υ\",qre=\"υ\",jre=\"↥\",Ure=\"⊥\",Vre=\"⇈\",Gre=\"⌝\",Kre=\"⌝\",Xre=\"⌎\",Yre=\"Ů\",Zre=\"ů\",Jre=\"◹\",Qre=\"𝒰\",eie=\"𝓊\",tie=\"⋰\",nie=\"Ũ\",rie=\"ũ\",iie=\"▵\",oie=\"▴\",sie=\"⇈\",lie=\"Ü\",aie=\"ü\",cie=\"⦧\",uie=\"⦜\",fie=\"ϵ\",die=\"ϰ\",hie=\"∅\",pie=\"ϕ\",gie=\"ϖ\",mie=\"∝\",vie=\"↕\",yie=\"⇕\",bie=\"ϱ\",wie=\"ς\",xie=\"⊊︀\",kie=\"⫋︀\",Sie=\"⊋︀\",_ie=\"⫌︀\",Tie=\"ϑ\",Cie=\"⊲\",Eie=\"⊳\",Aie=\"⫨\",Lie=\"⫫\",Mie=\"⫩\",Nie=\"В\",Oie=\"в\",Pie=\"⊢\",Rie=\"⊨\",$ie=\"⊩\",Iie=\"⊫\",Die=\"⫦\",zie=\"⊻\",Fie=\"∨\",Hie=\"⋁\",Bie=\"≚\",Wie=\"⋮\",qie=\"|\",jie=\"‖\",Uie=\"|\",Vie=\"‖\",Gie=\"∣\",Kie=\"|\",Xie=\"❘\",Yie=\"≀\",Zie=\" \",Jie=\"𝔙\",Qie=\"𝔳\",eoe=\"⊲\",toe=\"⊂⃒\",noe=\"⊃⃒\",roe=\"𝕍\",ioe=\"𝕧\",ooe=\"∝\",soe=\"⊳\",loe=\"𝒱\",aoe=\"𝓋\",coe=\"⫋︀\",uoe=\"⊊︀\",foe=\"⫌︀\",doe=\"⊋︀\",hoe=\"⊪\",poe=\"⦚\",goe=\"Ŵ\",moe=\"ŵ\",voe=\"⩟\",yoe=\"∧\",boe=\"⋀\",woe=\"≙\",xoe=\"℘\",koe=\"𝔚\",Soe=\"𝔴\",_oe=\"𝕎\",Toe=\"𝕨\",Coe=\"℘\",Eoe=\"≀\",Aoe=\"≀\",Loe=\"𝒲\",Moe=\"𝓌\",Noe=\"⋂\",Ooe=\"◯\",Poe=\"⋃\",Roe=\"▽\",$oe=\"𝔛\",Ioe=\"𝔵\",Doe=\"⟷\",zoe=\"⟺\",Foe=\"Ξ\",Hoe=\"ξ\",Boe=\"⟵\",Woe=\"⟸\",qoe=\"⟼\",joe=\"⋻\",Uoe=\"⨀\",Voe=\"𝕏\",Goe=\"𝕩\",Koe=\"⨁\",Xoe=\"⨂\",Yoe=\"⟶\",Zoe=\"⟹\",Joe=\"𝒳\",Qoe=\"𝓍\",ese=\"⨆\",tse=\"⨄\",nse=\"△\",rse=\"⋁\",ise=\"⋀\",ose=\"Ý\",sse=\"ý\",lse=\"Я\",ase=\"я\",cse=\"Ŷ\",use=\"ŷ\",fse=\"Ы\",dse=\"ы\",hse=\"¥\",pse=\"𝔜\",gse=\"𝔶\",mse=\"Ї\",vse=\"ї\",yse=\"𝕐\",bse=\"𝕪\",wse=\"𝒴\",xse=\"𝓎\",kse=\"Ю\",Sse=\"ю\",_se=\"ÿ\",Tse=\"Ÿ\",Cse=\"Ź\",Ese=\"ź\",Ase=\"Ž\",Lse=\"ž\",Mse=\"З\",Nse=\"з\",Ose=\"Ż\",Pse=\"ż\",Rse=\"ℨ\",$se=\"​\",Ise=\"Ζ\",Dse=\"ζ\",zse=\"𝔷\",Fse=\"ℨ\",Hse=\"Ж\",Bse=\"ж\",Wse=\"⇝\",qse=\"𝕫\",jse=\"ℤ\",Use=\"𝒵\",Vse=\"𝓏\",Gse=\"‍\",Kse=\"‌\",cx={Aacute:OL,aacute:PL,Abreve:RL,abreve:$L,ac:IL,acd:DL,acE:zL,Acirc:FL,acirc:HL,acute:BL,Acy:WL,acy:qL,AElig:jL,aelig:UL,af:VL,Afr:GL,afr:KL,Agrave:XL,agrave:YL,alefsym:ZL,aleph:JL,Alpha:QL,alpha:eM,Amacr:tM,amacr:nM,amalg:rM,amp:iM,AMP:oM,andand:sM,And:lM,and:aM,andd:cM,andslope:uM,andv:fM,ang:dM,ange:hM,angle:pM,angmsdaa:gM,angmsdab:mM,angmsdac:vM,angmsdad:yM,angmsdae:bM,angmsdaf:wM,angmsdag:xM,angmsdah:kM,angmsd:SM,angrt:_M,angrtvb:TM,angrtvbd:CM,angsph:EM,angst:AM,angzarr:LM,Aogon:MM,aogon:NM,Aopf:OM,aopf:PM,apacir:RM,ap:$M,apE:IM,ape:DM,apid:zM,apos:FM,ApplyFunction:HM,approx:BM,approxeq:WM,Aring:qM,aring:jM,Ascr:UM,ascr:VM,Assign:GM,ast:KM,asymp:XM,asympeq:YM,Atilde:ZM,atilde:JM,Auml:QM,auml:eN,awconint:tN,awint:nN,backcong:rN,backepsilon:iN,backprime:oN,backsim:sN,backsimeq:lN,Backslash:aN,Barv:cN,barvee:uN,barwed:fN,Barwed:dN,barwedge:hN,bbrk:pN,bbrktbrk:gN,bcong:mN,Bcy:vN,bcy:yN,bdquo:bN,becaus:wN,because:xN,Because:kN,bemptyv:SN,bepsi:_N,bernou:TN,Bernoullis:CN,Beta:EN,beta:AN,beth:LN,between:MN,Bfr:NN,bfr:ON,bigcap:PN,bigcirc:RN,bigcup:$N,bigodot:IN,bigoplus:DN,bigotimes:zN,bigsqcup:FN,bigstar:HN,bigtriangledown:BN,bigtriangleup:WN,biguplus:qN,bigvee:jN,bigwedge:UN,bkarow:VN,blacklozenge:GN,blacksquare:KN,blacktriangle:XN,blacktriangledown:YN,blacktriangleleft:ZN,blacktriangleright:JN,blank:QN,blk12:e2,blk14:t2,blk34:n2,block:r2,bne:i2,bnequiv:o2,bNot:s2,bnot:l2,Bopf:a2,bopf:c2,bot:u2,bottom:f2,bowtie:d2,boxbox:h2,boxdl:p2,boxdL:g2,boxDl:m2,boxDL:v2,boxdr:y2,boxdR:b2,boxDr:w2,boxDR:x2,boxh:k2,boxH:S2,boxhd:_2,boxHd:T2,boxhD:C2,boxHD:E2,boxhu:A2,boxHu:L2,boxhU:M2,boxHU:N2,boxminus:O2,boxplus:P2,boxtimes:R2,boxul:$2,boxuL:I2,boxUl:D2,boxUL:z2,boxur:F2,boxuR:H2,boxUr:B2,boxUR:W2,boxv:q2,boxV:j2,boxvh:U2,boxvH:V2,boxVh:G2,boxVH:K2,boxvl:X2,boxvL:Y2,boxVl:Z2,boxVL:J2,boxvr:Q2,boxvR:eO,boxVr:tO,boxVR:nO,bprime:rO,breve:iO,Breve:oO,brvbar:sO,bscr:lO,Bscr:aO,bsemi:cO,bsim:uO,bsime:fO,bsolb:dO,bsol:hO,bsolhsub:pO,bull:gO,bullet:mO,bump:vO,bumpE:yO,bumpe:bO,Bumpeq:wO,bumpeq:xO,Cacute:kO,cacute:SO,capand:_O,capbrcup:TO,capcap:CO,cap:EO,Cap:AO,capcup:LO,capdot:MO,CapitalDifferentialD:NO,caps:OO,caret:PO,caron:RO,Cayleys:$O,ccaps:IO,Ccaron:DO,ccaron:zO,Ccedil:FO,ccedil:HO,Ccirc:BO,ccirc:WO,Cconint:qO,ccups:jO,ccupssm:UO,Cdot:VO,cdot:GO,cedil:KO,Cedilla:XO,cemptyv:YO,cent:ZO,centerdot:JO,CenterDot:QO,cfr:eP,Cfr:tP,CHcy:nP,chcy:rP,check:iP,checkmark:oP,Chi:sP,chi:lP,circ:aP,circeq:cP,circlearrowleft:uP,circlearrowright:fP,circledast:dP,circledcirc:hP,circleddash:pP,CircleDot:gP,circledR:mP,circledS:vP,CircleMinus:yP,CirclePlus:bP,CircleTimes:wP,cir:xP,cirE:kP,cire:SP,cirfnint:_P,cirmid:TP,cirscir:CP,ClockwiseContourIntegral:EP,CloseCurlyDoubleQuote:AP,CloseCurlyQuote:LP,clubs:MP,clubsuit:NP,colon:OP,Colon:PP,Colone:RP,colone:$P,coloneq:IP,comma:DP,commat:zP,comp:FP,compfn:HP,complement:BP,complexes:WP,cong:qP,congdot:jP,Congruent:UP,conint:VP,Conint:GP,ContourIntegral:KP,copf:XP,Copf:YP,coprod:ZP,Coproduct:JP,copy:QP,COPY:eR,copysr:tR,CounterClockwiseContourIntegral:nR,crarr:rR,cross:iR,Cross:oR,Cscr:sR,cscr:lR,csub:aR,csube:cR,csup:uR,csupe:fR,ctdot:dR,cudarrl:hR,cudarrr:pR,cuepr:gR,cuesc:mR,cularr:vR,cularrp:yR,cupbrcap:bR,cupcap:wR,CupCap:xR,cup:kR,Cup:SR,cupcup:_R,cupdot:TR,cupor:CR,cups:ER,curarr:AR,curarrm:LR,curlyeqprec:MR,curlyeqsucc:NR,curlyvee:OR,curlywedge:PR,curren:RR,curvearrowleft:$R,curvearrowright:IR,cuvee:DR,cuwed:zR,cwconint:FR,cwint:HR,cylcty:BR,dagger:WR,Dagger:qR,daleth:jR,darr:UR,Darr:VR,dArr:GR,dash:KR,Dashv:XR,dashv:YR,dbkarow:ZR,dblac:JR,Dcaron:QR,dcaron:e$,Dcy:t$,dcy:n$,ddagger:r$,ddarr:i$,DD:o$,dd:s$,DDotrahd:l$,ddotseq:a$,deg:c$,Del:u$,Delta:f$,delta:d$,demptyv:h$,dfisht:p$,Dfr:g$,dfr:m$,dHar:v$,dharl:y$,dharr:b$,DiacriticalAcute:w$,DiacriticalDot:x$,DiacriticalDoubleAcute:k$,DiacriticalGrave:S$,DiacriticalTilde:_$,diam:T$,diamond:C$,Diamond:E$,diamondsuit:A$,diams:L$,die:M$,DifferentialD:N$,digamma:O$,disin:P$,div:R$,divide:$$,divideontimes:I$,divonx:D$,DJcy:z$,djcy:F$,dlcorn:H$,dlcrop:B$,dollar:W$,Dopf:q$,dopf:j$,Dot:U$,dot:V$,DotDot:G$,doteq:K$,doteqdot:X$,DotEqual:Y$,dotminus:Z$,dotplus:J$,dotsquare:Q$,doublebarwedge:eI,DoubleContourIntegral:tI,DoubleDot:nI,DoubleDownArrow:rI,DoubleLeftArrow:iI,DoubleLeftRightArrow:oI,DoubleLeftTee:sI,DoubleLongLeftArrow:lI,DoubleLongLeftRightArrow:aI,DoubleLongRightArrow:cI,DoubleRightArrow:uI,DoubleRightTee:fI,DoubleUpArrow:dI,DoubleUpDownArrow:hI,DoubleVerticalBar:pI,DownArrowBar:gI,downarrow:mI,DownArrow:vI,Downarrow:yI,DownArrowUpArrow:bI,DownBreve:wI,downdownarrows:xI,downharpoonleft:kI,downharpoonright:SI,DownLeftRightVector:_I,DownLeftTeeVector:TI,DownLeftVectorBar:CI,DownLeftVector:EI,DownRightTeeVector:AI,DownRightVectorBar:LI,DownRightVector:MI,DownTeeArrow:NI,DownTee:OI,drbkarow:PI,drcorn:RI,drcrop:$I,Dscr:II,dscr:DI,DScy:zI,dscy:FI,dsol:HI,Dstrok:BI,dstrok:WI,dtdot:qI,dtri:jI,dtrif:UI,duarr:VI,duhar:GI,dwangle:KI,DZcy:XI,dzcy:YI,dzigrarr:ZI,Eacute:JI,eacute:QI,easter:eD,Ecaron:tD,ecaron:nD,Ecirc:rD,ecirc:iD,ecir:oD,ecolon:sD,Ecy:lD,ecy:aD,eDDot:cD,Edot:uD,edot:fD,eDot:dD,ee:hD,efDot:pD,Efr:gD,efr:mD,eg:vD,Egrave:yD,egrave:bD,egs:wD,egsdot:xD,el:kD,Element:SD,elinters:_D,ell:TD,els:CD,elsdot:ED,Emacr:AD,emacr:LD,empty:MD,emptyset:ND,EmptySmallSquare:OD,emptyv:PD,EmptyVerySmallSquare:RD,emsp13:$D,emsp14:ID,emsp:DD,ENG:zD,eng:FD,ensp:HD,Eogon:BD,eogon:WD,Eopf:qD,eopf:jD,epar:UD,eparsl:VD,eplus:GD,epsi:KD,Epsilon:XD,epsilon:YD,epsiv:ZD,eqcirc:JD,eqcolon:QD,eqsim:ez,eqslantgtr:tz,eqslantless:nz,Equal:rz,equals:iz,EqualTilde:oz,equest:sz,Equilibrium:lz,equiv:az,equivDD:cz,eqvparsl:uz,erarr:fz,erDot:dz,escr:hz,Escr:pz,esdot:gz,Esim:mz,esim:vz,Eta:yz,eta:bz,ETH:wz,eth:xz,Euml:kz,euml:Sz,euro:_z,excl:Tz,exist:Cz,Exists:Ez,expectation:Az,exponentiale:Lz,ExponentialE:Mz,fallingdotseq:Nz,Fcy:Oz,fcy:Pz,female:Rz,ffilig:$z,fflig:Iz,ffllig:Dz,Ffr:zz,ffr:Fz,filig:Hz,FilledSmallSquare:Bz,FilledVerySmallSquare:Wz,fjlig:qz,flat:jz,fllig:Uz,fltns:Vz,fnof:Gz,Fopf:Kz,fopf:Xz,forall:Yz,ForAll:Zz,fork:Jz,forkv:Qz,Fouriertrf:eF,fpartint:tF,frac12:nF,frac13:rF,frac14:iF,frac15:oF,frac16:sF,frac18:lF,frac23:aF,frac25:cF,frac34:uF,frac35:fF,frac38:dF,frac45:hF,frac56:pF,frac58:gF,frac78:mF,frasl:vF,frown:yF,fscr:bF,Fscr:wF,gacute:xF,Gamma:kF,gamma:SF,Gammad:_F,gammad:TF,gap:CF,Gbreve:EF,gbreve:AF,Gcedil:LF,Gcirc:MF,gcirc:NF,Gcy:OF,gcy:PF,Gdot:RF,gdot:$F,ge:IF,gE:DF,gEl:zF,gel:FF,geq:HF,geqq:BF,geqslant:WF,gescc:qF,ges:jF,gesdot:UF,gesdoto:VF,gesdotol:GF,gesl:KF,gesles:XF,Gfr:YF,gfr:ZF,gg:JF,Gg:QF,ggg:eH,gimel:tH,GJcy:nH,gjcy:rH,gla:iH,gl:oH,glE:sH,glj:lH,gnap:aH,gnapprox:cH,gne:uH,gnE:fH,gneq:dH,gneqq:hH,gnsim:pH,Gopf:gH,gopf:mH,grave:vH,GreaterEqual:yH,GreaterEqualLess:bH,GreaterFullEqual:wH,GreaterGreater:xH,GreaterLess:kH,GreaterSlantEqual:SH,GreaterTilde:_H,Gscr:TH,gscr:CH,gsim:EH,gsime:AH,gsiml:LH,gtcc:MH,gtcir:NH,gt:OH,GT:PH,Gt:RH,gtdot:$H,gtlPar:IH,gtquest:DH,gtrapprox:zH,gtrarr:FH,gtrdot:HH,gtreqless:BH,gtreqqless:WH,gtrless:qH,gtrsim:jH,gvertneqq:UH,gvnE:VH,Hacek:GH,hairsp:KH,half:XH,hamilt:YH,HARDcy:ZH,hardcy:JH,harrcir:QH,harr:e3,hArr:t3,harrw:n3,Hat:r3,hbar:i3,Hcirc:o3,hcirc:s3,hearts:l3,heartsuit:a3,hellip:c3,hercon:u3,hfr:f3,Hfr:d3,HilbertSpace:h3,hksearow:p3,hkswarow:g3,hoarr:m3,homtht:v3,hookleftarrow:y3,hookrightarrow:b3,hopf:w3,Hopf:x3,horbar:k3,HorizontalLine:S3,hscr:_3,Hscr:T3,hslash:C3,Hstrok:E3,hstrok:A3,HumpDownHump:L3,HumpEqual:M3,hybull:N3,hyphen:O3,Iacute:P3,iacute:R3,ic:$3,Icirc:I3,icirc:D3,Icy:z3,icy:F3,Idot:H3,IEcy:B3,iecy:W3,iexcl:q3,iff:j3,ifr:U3,Ifr:V3,Igrave:G3,igrave:K3,ii:X3,iiiint:Y3,iiint:Z3,iinfin:J3,iiota:Q3,IJlig:eB,ijlig:tB,Imacr:nB,imacr:rB,image:iB,ImaginaryI:oB,imagline:sB,imagpart:lB,imath:aB,Im:cB,imof:uB,imped:fB,Implies:dB,incare:hB,in:\"∈\",infin:pB,infintie:gB,inodot:mB,intcal:vB,int:yB,Int:bB,integers:wB,Integral:xB,intercal:kB,Intersection:SB,intlarhk:_B,intprod:TB,InvisibleComma:CB,InvisibleTimes:EB,IOcy:AB,iocy:LB,Iogon:MB,iogon:NB,Iopf:OB,iopf:PB,Iota:RB,iota:$B,iprod:IB,iquest:DB,iscr:zB,Iscr:FB,isin:HB,isindot:BB,isinE:WB,isins:qB,isinsv:jB,isinv:UB,it:VB,Itilde:GB,itilde:KB,Iukcy:XB,iukcy:YB,Iuml:ZB,iuml:JB,Jcirc:QB,jcirc:e5,Jcy:t5,jcy:n5,Jfr:r5,jfr:i5,jmath:o5,Jopf:s5,jopf:l5,Jscr:a5,jscr:c5,Jsercy:u5,jsercy:f5,Jukcy:d5,jukcy:h5,Kappa:p5,kappa:g5,kappav:m5,Kcedil:v5,kcedil:y5,Kcy:b5,kcy:w5,Kfr:x5,kfr:k5,kgreen:S5,KHcy:_5,khcy:T5,KJcy:C5,kjcy:E5,Kopf:A5,kopf:L5,Kscr:M5,kscr:N5,lAarr:O5,Lacute:P5,lacute:R5,laemptyv:$5,lagran:I5,Lambda:D5,lambda:z5,lang:F5,Lang:H5,langd:B5,langle:W5,lap:q5,Laplacetrf:j5,laquo:U5,larrb:V5,larrbfs:G5,larr:K5,Larr:X5,lArr:Y5,larrfs:Z5,larrhk:J5,larrlp:Q5,larrpl:e8,larrsim:t8,larrtl:n8,latail:r8,lAtail:i8,lat:o8,late:s8,lates:l8,lbarr:a8,lBarr:c8,lbbrk:u8,lbrace:f8,lbrack:d8,lbrke:h8,lbrksld:p8,lbrkslu:g8,Lcaron:m8,lcaron:v8,Lcedil:y8,lcedil:b8,lceil:w8,lcub:x8,Lcy:k8,lcy:S8,ldca:_8,ldquo:T8,ldquor:C8,ldrdhar:E8,ldrushar:A8,ldsh:L8,le:M8,lE:N8,LeftAngleBracket:O8,LeftArrowBar:P8,leftarrow:R8,LeftArrow:$8,Leftarrow:I8,LeftArrowRightArrow:D8,leftarrowtail:z8,LeftCeiling:F8,LeftDoubleBracket:H8,LeftDownTeeVector:B8,LeftDownVectorBar:W8,LeftDownVector:q8,LeftFloor:j8,leftharpoondown:U8,leftharpoonup:V8,leftleftarrows:G8,leftrightarrow:K8,LeftRightArrow:X8,Leftrightarrow:Y8,leftrightarrows:Z8,leftrightharpoons:J8,leftrightsquigarrow:Q8,LeftRightVector:eW,LeftTeeArrow:tW,LeftTee:nW,LeftTeeVector:rW,leftthreetimes:iW,LeftTriangleBar:oW,LeftTriangle:sW,LeftTriangleEqual:lW,LeftUpDownVector:aW,LeftUpTeeVector:cW,LeftUpVectorBar:uW,LeftUpVector:fW,LeftVectorBar:dW,LeftVector:hW,lEg:pW,leg:gW,leq:mW,leqq:vW,leqslant:yW,lescc:bW,les:wW,lesdot:xW,lesdoto:kW,lesdotor:SW,lesg:_W,lesges:TW,lessapprox:CW,lessdot:EW,lesseqgtr:AW,lesseqqgtr:LW,LessEqualGreater:MW,LessFullEqual:NW,LessGreater:OW,lessgtr:PW,LessLess:RW,lesssim:$W,LessSlantEqual:IW,LessTilde:DW,lfisht:zW,lfloor:FW,Lfr:HW,lfr:BW,lg:WW,lgE:qW,lHar:jW,lhard:UW,lharu:VW,lharul:GW,lhblk:KW,LJcy:XW,ljcy:YW,llarr:ZW,ll:JW,Ll:QW,llcorner:e4,Lleftarrow:t4,llhard:n4,lltri:r4,Lmidot:i4,lmidot:o4,lmoustache:s4,lmoust:l4,lnap:a4,lnapprox:c4,lne:u4,lnE:f4,lneq:d4,lneqq:h4,lnsim:p4,loang:g4,loarr:m4,lobrk:v4,longleftarrow:y4,LongLeftArrow:b4,Longleftarrow:w4,longleftrightarrow:x4,LongLeftRightArrow:k4,Longleftrightarrow:S4,longmapsto:_4,longrightarrow:T4,LongRightArrow:C4,Longrightarrow:E4,looparrowleft:A4,looparrowright:L4,lopar:M4,Lopf:N4,lopf:O4,loplus:P4,lotimes:R4,lowast:$4,lowbar:I4,LowerLeftArrow:D4,LowerRightArrow:z4,loz:F4,lozenge:H4,lozf:B4,lpar:W4,lparlt:q4,lrarr:j4,lrcorner:U4,lrhar:V4,lrhard:G4,lrm:K4,lrtri:X4,lsaquo:Y4,lscr:Z4,Lscr:J4,lsh:Q4,Lsh:eq,lsim:tq,lsime:nq,lsimg:rq,lsqb:iq,lsquo:oq,lsquor:sq,Lstrok:lq,lstrok:aq,ltcc:cq,ltcir:uq,lt:fq,LT:dq,Lt:hq,ltdot:pq,lthree:gq,ltimes:mq,ltlarr:vq,ltquest:yq,ltri:bq,ltrie:wq,ltrif:xq,ltrPar:kq,lurdshar:Sq,luruhar:_q,lvertneqq:Tq,lvnE:Cq,macr:Eq,male:Aq,malt:Lq,maltese:Mq,Map:\"⤅\",map:Nq,mapsto:Oq,mapstodown:Pq,mapstoleft:Rq,mapstoup:$q,marker:Iq,mcomma:Dq,Mcy:zq,mcy:Fq,mdash:Hq,mDDot:Bq,measuredangle:Wq,MediumSpace:qq,Mellintrf:jq,Mfr:Uq,mfr:Vq,mho:Gq,micro:Kq,midast:Xq,midcir:Yq,mid:Zq,middot:Jq,minusb:Qq,minus:ej,minusd:tj,minusdu:nj,MinusPlus:rj,mlcp:ij,mldr:oj,mnplus:sj,models:lj,Mopf:aj,mopf:cj,mp:uj,mscr:fj,Mscr:dj,mstpos:hj,Mu:pj,mu:gj,multimap:mj,mumap:vj,nabla:yj,Nacute:bj,nacute:wj,nang:xj,nap:kj,napE:Sj,napid:_j,napos:Tj,napprox:Cj,natural:Ej,naturals:Aj,natur:Lj,nbsp:Mj,nbump:Nj,nbumpe:Oj,ncap:Pj,Ncaron:Rj,ncaron:$j,Ncedil:Ij,ncedil:Dj,ncong:zj,ncongdot:Fj,ncup:Hj,Ncy:Bj,ncy:Wj,ndash:qj,nearhk:jj,nearr:Uj,neArr:Vj,nearrow:Gj,ne:Kj,nedot:Xj,NegativeMediumSpace:Yj,NegativeThickSpace:Zj,NegativeThinSpace:Jj,NegativeVeryThinSpace:Qj,nequiv:eU,nesear:tU,nesim:nU,NestedGreaterGreater:rU,NestedLessLess:iU,NewLine:oU,nexist:sU,nexists:lU,Nfr:aU,nfr:cU,ngE:uU,nge:fU,ngeq:dU,ngeqq:hU,ngeqslant:pU,nges:gU,nGg:mU,ngsim:vU,nGt:yU,ngt:bU,ngtr:wU,nGtv:xU,nharr:kU,nhArr:SU,nhpar:_U,ni:TU,nis:CU,nisd:EU,niv:AU,NJcy:LU,njcy:MU,nlarr:NU,nlArr:OU,nldr:PU,nlE:RU,nle:$U,nleftarrow:IU,nLeftarrow:DU,nleftrightarrow:zU,nLeftrightarrow:FU,nleq:HU,nleqq:BU,nleqslant:WU,nles:qU,nless:jU,nLl:UU,nlsim:VU,nLt:GU,nlt:KU,nltri:XU,nltrie:YU,nLtv:ZU,nmid:JU,NoBreak:QU,NonBreakingSpace:e6,nopf:t6,Nopf:n6,Not:r6,not:i6,NotCongruent:o6,NotCupCap:s6,NotDoubleVerticalBar:l6,NotElement:a6,NotEqual:c6,NotEqualTilde:u6,NotExists:f6,NotGreater:d6,NotGreaterEqual:h6,NotGreaterFullEqual:p6,NotGreaterGreater:g6,NotGreaterLess:m6,NotGreaterSlantEqual:v6,NotGreaterTilde:y6,NotHumpDownHump:b6,NotHumpEqual:w6,notin:x6,notindot:k6,notinE:S6,notinva:_6,notinvb:T6,notinvc:C6,NotLeftTriangleBar:E6,NotLeftTriangle:A6,NotLeftTriangleEqual:L6,NotLess:M6,NotLessEqual:N6,NotLessGreater:O6,NotLessLess:P6,NotLessSlantEqual:R6,NotLessTilde:$6,NotNestedGreaterGreater:I6,NotNestedLessLess:D6,notni:z6,notniva:F6,notnivb:H6,notnivc:B6,NotPrecedes:W6,NotPrecedesEqual:q6,NotPrecedesSlantEqual:j6,NotReverseElement:U6,NotRightTriangleBar:V6,NotRightTriangle:G6,NotRightTriangleEqual:K6,NotSquareSubset:X6,NotSquareSubsetEqual:Y6,NotSquareSuperset:Z6,NotSquareSupersetEqual:J6,NotSubset:Q6,NotSubsetEqual:eV,NotSucceeds:tV,NotSucceedsEqual:nV,NotSucceedsSlantEqual:rV,NotSucceedsTilde:iV,NotSuperset:oV,NotSupersetEqual:sV,NotTilde:lV,NotTildeEqual:aV,NotTildeFullEqual:cV,NotTildeTilde:uV,NotVerticalBar:fV,nparallel:dV,npar:hV,nparsl:pV,npart:gV,npolint:mV,npr:vV,nprcue:yV,nprec:bV,npreceq:wV,npre:xV,nrarrc:kV,nrarr:SV,nrArr:_V,nrarrw:TV,nrightarrow:CV,nRightarrow:EV,nrtri:AV,nrtrie:LV,nsc:MV,nsccue:NV,nsce:OV,Nscr:PV,nscr:RV,nshortmid:$V,nshortparallel:IV,nsim:DV,nsime:zV,nsimeq:FV,nsmid:HV,nspar:BV,nsqsube:WV,nsqsupe:qV,nsub:jV,nsubE:UV,nsube:VV,nsubset:GV,nsubseteq:KV,nsubseteqq:XV,nsucc:YV,nsucceq:ZV,nsup:JV,nsupE:QV,nsupe:eG,nsupset:tG,nsupseteq:nG,nsupseteqq:rG,ntgl:iG,Ntilde:oG,ntilde:sG,ntlg:lG,ntriangleleft:aG,ntrianglelefteq:cG,ntriangleright:uG,ntrianglerighteq:fG,Nu:dG,nu:hG,num:pG,numero:gG,numsp:mG,nvap:vG,nvdash:yG,nvDash:bG,nVdash:wG,nVDash:xG,nvge:kG,nvgt:SG,nvHarr:_G,nvinfin:TG,nvlArr:CG,nvle:EG,nvlt:AG,nvltrie:LG,nvrArr:MG,nvrtrie:NG,nvsim:OG,nwarhk:PG,nwarr:RG,nwArr:$G,nwarrow:IG,nwnear:DG,Oacute:zG,oacute:FG,oast:HG,Ocirc:BG,ocirc:WG,ocir:qG,Ocy:jG,ocy:UG,odash:VG,Odblac:GG,odblac:KG,odiv:XG,odot:YG,odsold:ZG,OElig:JG,oelig:QG,ofcir:e9,Ofr:t9,ofr:n9,ogon:r9,Ograve:i9,ograve:o9,ogt:s9,ohbar:l9,ohm:a9,oint:c9,olarr:u9,olcir:f9,olcross:d9,oline:h9,olt:p9,Omacr:g9,omacr:m9,Omega:v9,omega:y9,Omicron:b9,omicron:w9,omid:x9,ominus:k9,Oopf:S9,oopf:_9,opar:T9,OpenCurlyDoubleQuote:C9,OpenCurlyQuote:E9,operp:A9,oplus:L9,orarr:M9,Or:N9,or:O9,ord:P9,order:R9,orderof:$9,ordf:I9,ordm:D9,origof:z9,oror:F9,orslope:H9,orv:B9,oS:W9,Oscr:q9,oscr:j9,Oslash:U9,oslash:V9,osol:G9,Otilde:K9,otilde:X9,otimesas:Y9,Otimes:Z9,otimes:J9,Ouml:Q9,ouml:eK,ovbar:tK,OverBar:nK,OverBrace:rK,OverBracket:iK,OverParenthesis:oK,para:sK,parallel:lK,par:aK,parsim:cK,parsl:uK,part:fK,PartialD:dK,Pcy:hK,pcy:pK,percnt:gK,period:mK,permil:vK,perp:yK,pertenk:bK,Pfr:wK,pfr:xK,Phi:kK,phi:SK,phiv:_K,phmmat:TK,phone:CK,Pi:EK,pi:AK,pitchfork:LK,piv:MK,planck:NK,planckh:OK,plankv:PK,plusacir:RK,plusb:$K,pluscir:IK,plus:DK,plusdo:zK,plusdu:FK,pluse:HK,PlusMinus:BK,plusmn:WK,plussim:qK,plustwo:jK,pm:UK,Poincareplane:VK,pointint:GK,popf:KK,Popf:XK,pound:YK,prap:ZK,Pr:JK,pr:QK,prcue:e7,precapprox:t7,prec:n7,preccurlyeq:r7,Precedes:i7,PrecedesEqual:o7,PrecedesSlantEqual:s7,PrecedesTilde:l7,preceq:a7,precnapprox:c7,precneqq:u7,precnsim:f7,pre:d7,prE:h7,precsim:p7,prime:g7,Prime:m7,primes:v7,prnap:y7,prnE:b7,prnsim:w7,prod:x7,Product:k7,profalar:S7,profline:_7,profsurf:T7,prop:C7,Proportional:E7,Proportion:A7,propto:L7,prsim:M7,prurel:N7,Pscr:O7,pscr:P7,Psi:R7,psi:$7,puncsp:I7,Qfr:D7,qfr:z7,qint:F7,qopf:H7,Qopf:B7,qprime:W7,Qscr:q7,qscr:j7,quaternions:U7,quatint:V7,quest:G7,questeq:K7,quot:X7,QUOT:Y7,rAarr:Z7,race:J7,Racute:Q7,racute:eX,radic:tX,raemptyv:nX,rang:rX,Rang:iX,rangd:oX,range:sX,rangle:lX,raquo:aX,rarrap:cX,rarrb:uX,rarrbfs:fX,rarrc:dX,rarr:hX,Rarr:pX,rArr:gX,rarrfs:mX,rarrhk:vX,rarrlp:yX,rarrpl:bX,rarrsim:wX,Rarrtl:xX,rarrtl:kX,rarrw:SX,ratail:_X,rAtail:TX,ratio:CX,rationals:EX,rbarr:AX,rBarr:LX,RBarr:MX,rbbrk:NX,rbrace:OX,rbrack:PX,rbrke:RX,rbrksld:$X,rbrkslu:IX,Rcaron:DX,rcaron:zX,Rcedil:FX,rcedil:HX,rceil:BX,rcub:WX,Rcy:qX,rcy:jX,rdca:UX,rdldhar:VX,rdquo:GX,rdquor:KX,rdsh:XX,real:YX,realine:ZX,realpart:JX,reals:QX,Re:eY,rect:tY,reg:nY,REG:rY,ReverseElement:iY,ReverseEquilibrium:oY,ReverseUpEquilibrium:sY,rfisht:lY,rfloor:aY,rfr:cY,Rfr:uY,rHar:fY,rhard:dY,rharu:hY,rharul:pY,Rho:gY,rho:mY,rhov:vY,RightAngleBracket:yY,RightArrowBar:bY,rightarrow:wY,RightArrow:xY,Rightarrow:kY,RightArrowLeftArrow:SY,rightarrowtail:_Y,RightCeiling:TY,RightDoubleBracket:CY,RightDownTeeVector:EY,RightDownVectorBar:AY,RightDownVector:LY,RightFloor:MY,rightharpoondown:NY,rightharpoonup:OY,rightleftarrows:PY,rightleftharpoons:RY,rightrightarrows:$Y,rightsquigarrow:IY,RightTeeArrow:DY,RightTee:zY,RightTeeVector:FY,rightthreetimes:HY,RightTriangleBar:BY,RightTriangle:WY,RightTriangleEqual:qY,RightUpDownVector:jY,RightUpTeeVector:UY,RightUpVectorBar:VY,RightUpVector:GY,RightVectorBar:KY,RightVector:XY,ring:YY,risingdotseq:ZY,rlarr:JY,rlhar:QY,rlm:eZ,rmoustache:tZ,rmoust:nZ,rnmid:rZ,roang:iZ,roarr:oZ,robrk:sZ,ropar:lZ,ropf:aZ,Ropf:cZ,roplus:uZ,rotimes:fZ,RoundImplies:dZ,rpar:hZ,rpargt:pZ,rppolint:gZ,rrarr:mZ,Rrightarrow:vZ,rsaquo:yZ,rscr:bZ,Rscr:wZ,rsh:xZ,Rsh:kZ,rsqb:SZ,rsquo:_Z,rsquor:TZ,rthree:CZ,rtimes:EZ,rtri:AZ,rtrie:LZ,rtrif:MZ,rtriltri:NZ,RuleDelayed:OZ,ruluhar:PZ,rx:RZ,Sacute:$Z,sacute:IZ,sbquo:DZ,scap:zZ,Scaron:FZ,scaron:HZ,Sc:BZ,sc:WZ,sccue:qZ,sce:jZ,scE:UZ,Scedil:VZ,scedil:GZ,Scirc:KZ,scirc:XZ,scnap:YZ,scnE:ZZ,scnsim:JZ,scpolint:QZ,scsim:eJ,Scy:tJ,scy:nJ,sdotb:rJ,sdot:iJ,sdote:oJ,searhk:sJ,searr:lJ,seArr:aJ,searrow:cJ,sect:uJ,semi:fJ,seswar:dJ,setminus:hJ,setmn:pJ,sext:gJ,Sfr:mJ,sfr:vJ,sfrown:yJ,sharp:bJ,SHCHcy:wJ,shchcy:xJ,SHcy:kJ,shcy:SJ,ShortDownArrow:_J,ShortLeftArrow:TJ,shortmid:CJ,shortparallel:EJ,ShortRightArrow:AJ,ShortUpArrow:LJ,shy:MJ,Sigma:NJ,sigma:OJ,sigmaf:PJ,sigmav:RJ,sim:$J,simdot:IJ,sime:DJ,simeq:zJ,simg:FJ,simgE:HJ,siml:BJ,simlE:WJ,simne:qJ,simplus:jJ,simrarr:UJ,slarr:VJ,SmallCircle:GJ,smallsetminus:KJ,smashp:XJ,smeparsl:YJ,smid:ZJ,smile:JJ,smt:QJ,smte:eQ,smtes:tQ,SOFTcy:nQ,softcy:rQ,solbar:iQ,solb:oQ,sol:sQ,Sopf:lQ,sopf:aQ,spades:cQ,spadesuit:uQ,spar:fQ,sqcap:dQ,sqcaps:hQ,sqcup:pQ,sqcups:gQ,Sqrt:mQ,sqsub:vQ,sqsube:yQ,sqsubset:bQ,sqsubseteq:wQ,sqsup:xQ,sqsupe:kQ,sqsupset:SQ,sqsupseteq:_Q,square:TQ,Square:CQ,SquareIntersection:EQ,SquareSubset:AQ,SquareSubsetEqual:LQ,SquareSuperset:MQ,SquareSupersetEqual:NQ,SquareUnion:OQ,squarf:PQ,squ:RQ,squf:$Q,srarr:IQ,Sscr:DQ,sscr:zQ,ssetmn:FQ,ssmile:HQ,sstarf:BQ,Star:WQ,star:qQ,starf:jQ,straightepsilon:UQ,straightphi:VQ,strns:GQ,sub:KQ,Sub:XQ,subdot:YQ,subE:ZQ,sube:JQ,subedot:QQ,submult:eee,subnE:tee,subne:nee,subplus:ree,subrarr:iee,subset:oee,Subset:see,subseteq:lee,subseteqq:aee,SubsetEqual:cee,subsetneq:uee,subsetneqq:fee,subsim:dee,subsub:hee,subsup:pee,succapprox:gee,succ:mee,succcurlyeq:vee,Succeeds:yee,SucceedsEqual:bee,SucceedsSlantEqual:wee,SucceedsTilde:xee,succeq:kee,succnapprox:See,succneqq:_ee,succnsim:Tee,succsim:Cee,SuchThat:Eee,sum:Aee,Sum:Lee,sung:Mee,sup1:Nee,sup2:Oee,sup3:Pee,sup:Ree,Sup:$ee,supdot:Iee,supdsub:Dee,supE:zee,supe:Fee,supedot:Hee,Superset:Bee,SupersetEqual:Wee,suphsol:qee,suphsub:jee,suplarr:Uee,supmult:Vee,supnE:Gee,supne:Kee,supplus:Xee,supset:Yee,Supset:Zee,supseteq:Jee,supseteqq:Qee,supsetneq:ete,supsetneqq:tte,supsim:nte,supsub:rte,supsup:ite,swarhk:ote,swarr:ste,swArr:lte,swarrow:ate,swnwar:cte,szlig:ute,Tab:fte,target:dte,Tau:hte,tau:pte,tbrk:gte,Tcaron:mte,tcaron:vte,Tcedil:yte,tcedil:bte,Tcy:wte,tcy:xte,tdot:kte,telrec:Ste,Tfr:_te,tfr:Tte,there4:Cte,therefore:Ete,Therefore:Ate,Theta:Lte,theta:Mte,thetasym:Nte,thetav:Ote,thickapprox:Pte,thicksim:Rte,ThickSpace:$te,ThinSpace:Ite,thinsp:Dte,thkap:zte,thksim:Fte,THORN:Hte,thorn:Bte,tilde:Wte,Tilde:qte,TildeEqual:jte,TildeFullEqual:Ute,TildeTilde:Vte,timesbar:Gte,timesb:Kte,times:Xte,timesd:Yte,tint:Zte,toea:Jte,topbot:Qte,topcir:ene,top:tne,Topf:nne,topf:rne,topfork:ine,tosa:one,tprime:sne,trade:lne,TRADE:ane,triangle:cne,triangledown:une,triangleleft:fne,trianglelefteq:dne,triangleq:hne,triangleright:pne,trianglerighteq:gne,tridot:mne,trie:vne,triminus:yne,TripleDot:bne,triplus:wne,trisb:xne,tritime:kne,trpezium:Sne,Tscr:_ne,tscr:Tne,TScy:Cne,tscy:Ene,TSHcy:Ane,tshcy:Lne,Tstrok:Mne,tstrok:Nne,twixt:One,twoheadleftarrow:Pne,twoheadrightarrow:Rne,Uacute:$ne,uacute:Ine,uarr:Dne,Uarr:zne,uArr:Fne,Uarrocir:Hne,Ubrcy:Bne,ubrcy:Wne,Ubreve:qne,ubreve:jne,Ucirc:Une,ucirc:Vne,Ucy:Gne,ucy:Kne,udarr:Xne,Udblac:Yne,udblac:Zne,udhar:Jne,ufisht:Qne,Ufr:ere,ufr:tre,Ugrave:nre,ugrave:rre,uHar:ire,uharl:ore,uharr:sre,uhblk:lre,ulcorn:are,ulcorner:cre,ulcrop:ure,ultri:fre,Umacr:dre,umacr:hre,uml:pre,UnderBar:gre,UnderBrace:mre,UnderBracket:vre,UnderParenthesis:yre,Union:bre,UnionPlus:wre,Uogon:xre,uogon:kre,Uopf:Sre,uopf:_re,UpArrowBar:Tre,uparrow:Cre,UpArrow:Ere,Uparrow:Are,UpArrowDownArrow:Lre,updownarrow:Mre,UpDownArrow:Nre,Updownarrow:Ore,UpEquilibrium:Pre,upharpoonleft:Rre,upharpoonright:$re,uplus:Ire,UpperLeftArrow:Dre,UpperRightArrow:zre,upsi:Fre,Upsi:Hre,upsih:Bre,Upsilon:Wre,upsilon:qre,UpTeeArrow:jre,UpTee:Ure,upuparrows:Vre,urcorn:Gre,urcorner:Kre,urcrop:Xre,Uring:Yre,uring:Zre,urtri:Jre,Uscr:Qre,uscr:eie,utdot:tie,Utilde:nie,utilde:rie,utri:iie,utrif:oie,uuarr:sie,Uuml:lie,uuml:aie,uwangle:cie,vangrt:uie,varepsilon:fie,varkappa:die,varnothing:hie,varphi:pie,varpi:gie,varpropto:mie,varr:vie,vArr:yie,varrho:bie,varsigma:wie,varsubsetneq:xie,varsubsetneqq:kie,varsupsetneq:Sie,varsupsetneqq:_ie,vartheta:Tie,vartriangleleft:Cie,vartriangleright:Eie,vBar:Aie,Vbar:Lie,vBarv:Mie,Vcy:Nie,vcy:Oie,vdash:Pie,vDash:Rie,Vdash:$ie,VDash:Iie,Vdashl:Die,veebar:zie,vee:Fie,Vee:Hie,veeeq:Bie,vellip:Wie,verbar:qie,Verbar:jie,vert:Uie,Vert:Vie,VerticalBar:Gie,VerticalLine:Kie,VerticalSeparator:Xie,VerticalTilde:Yie,VeryThinSpace:Zie,Vfr:Jie,vfr:Qie,vltri:eoe,vnsub:toe,vnsup:noe,Vopf:roe,vopf:ioe,vprop:ooe,vrtri:soe,Vscr:loe,vscr:aoe,vsubnE:coe,vsubne:uoe,vsupnE:foe,vsupne:doe,Vvdash:hoe,vzigzag:poe,Wcirc:goe,wcirc:moe,wedbar:voe,wedge:yoe,Wedge:boe,wedgeq:woe,weierp:xoe,Wfr:koe,wfr:Soe,Wopf:_oe,wopf:Toe,wp:Coe,wr:Eoe,wreath:Aoe,Wscr:Loe,wscr:Moe,xcap:Noe,xcirc:Ooe,xcup:Poe,xdtri:Roe,Xfr:$oe,xfr:Ioe,xharr:Doe,xhArr:zoe,Xi:Foe,xi:Hoe,xlarr:Boe,xlArr:Woe,xmap:qoe,xnis:joe,xodot:Uoe,Xopf:Voe,xopf:Goe,xoplus:Koe,xotime:Xoe,xrarr:Yoe,xrArr:Zoe,Xscr:Joe,xscr:Qoe,xsqcup:ese,xuplus:tse,xutri:nse,xvee:rse,xwedge:ise,Yacute:ose,yacute:sse,YAcy:lse,yacy:ase,Ycirc:cse,ycirc:use,Ycy:fse,ycy:dse,yen:hse,Yfr:pse,yfr:gse,YIcy:mse,yicy:vse,Yopf:yse,yopf:bse,Yscr:wse,yscr:xse,YUcy:kse,yucy:Sse,yuml:_se,Yuml:Tse,Zacute:Cse,zacute:Ese,Zcaron:Ase,zcaron:Lse,Zcy:Mse,zcy:Nse,Zdot:Ose,zdot:Pse,zeetrf:Rse,ZeroWidthSpace:$se,Zeta:Ise,zeta:Dse,zfr:zse,Zfr:Fse,ZHcy:Hse,zhcy:Bse,zigrarr:Wse,zopf:qse,Zopf:jse,Zscr:Use,zscr:Vse,zwj:Gse,zwnj:Kse},Xse=\"Á\",Yse=\"á\",Zse=\"Â\",Jse=\"â\",Qse=\"´\",ele=\"Æ\",tle=\"æ\",nle=\"À\",rle=\"à\",ile=\"&\",ole=\"&\",sle=\"Å\",lle=\"å\",ale=\"Ã\",cle=\"ã\",ule=\"Ä\",fle=\"ä\",dle=\"¦\",hle=\"Ç\",ple=\"ç\",gle=\"¸\",mle=\"¢\",vle=\"©\",yle=\"©\",ble=\"¤\",wle=\"°\",xle=\"÷\",kle=\"É\",Sle=\"é\",_le=\"Ê\",Tle=\"ê\",Cle=\"È\",Ele=\"è\",Ale=\"Ð\",Lle=\"ð\",Mle=\"Ë\",Nle=\"ë\",Ole=\"½\",Ple=\"¼\",Rle=\"¾\",$le=\">\",Ile=\">\",Dle=\"Í\",zle=\"í\",Fle=\"Î\",Hle=\"î\",Ble=\"¡\",Wle=\"Ì\",qle=\"ì\",jle=\"¿\",Ule=\"Ï\",Vle=\"ï\",Gle=\"«\",Kle=\"<\",Xle=\"<\",Yle=\"¯\",Zle=\"µ\",Jle=\"·\",Qle=\" \",eae=\"¬\",tae=\"Ñ\",nae=\"ñ\",rae=\"Ó\",iae=\"ó\",oae=\"Ô\",sae=\"ô\",lae=\"Ò\",aae=\"ò\",cae=\"ª\",uae=\"º\",fae=\"Ø\",dae=\"ø\",hae=\"Õ\",pae=\"õ\",gae=\"Ö\",mae=\"ö\",vae=\"¶\",yae=\"±\",bae=\"£\",wae='\"',xae='\"',kae=\"»\",Sae=\"®\",_ae=\"®\",Tae=\"§\",Cae=\"­\",Eae=\"¹\",Aae=\"²\",Lae=\"³\",Mae=\"ß\",Nae=\"Þ\",Oae=\"þ\",Pae=\"×\",Rae=\"Ú\",$ae=\"ú\",Iae=\"Û\",Dae=\"û\",zae=\"Ù\",Fae=\"ù\",Hae=\"¨\",Bae=\"Ü\",Wae=\"ü\",qae=\"Ý\",jae=\"ý\",Uae=\"¥\",Vae=\"ÿ\",Gae={Aacute:Xse,aacute:Yse,Acirc:Zse,acirc:Jse,acute:Qse,AElig:ele,aelig:tle,Agrave:nle,agrave:rle,amp:ile,AMP:ole,Aring:sle,aring:lle,Atilde:ale,atilde:cle,Auml:ule,auml:fle,brvbar:dle,Ccedil:hle,ccedil:ple,cedil:gle,cent:mle,copy:vle,COPY:yle,curren:ble,deg:wle,divide:xle,Eacute:kle,eacute:Sle,Ecirc:_le,ecirc:Tle,Egrave:Cle,egrave:Ele,ETH:Ale,eth:Lle,Euml:Mle,euml:Nle,frac12:Ole,frac14:Ple,frac34:Rle,gt:$le,GT:Ile,Iacute:Dle,iacute:zle,Icirc:Fle,icirc:Hle,iexcl:Ble,Igrave:Wle,igrave:qle,iquest:jle,Iuml:Ule,iuml:Vle,laquo:Gle,lt:Kle,LT:Xle,macr:Yle,micro:Zle,middot:Jle,nbsp:Qle,not:eae,Ntilde:tae,ntilde:nae,Oacute:rae,oacute:iae,Ocirc:oae,ocirc:sae,Ograve:lae,ograve:aae,ordf:cae,ordm:uae,Oslash:fae,oslash:dae,Otilde:hae,otilde:pae,Ouml:gae,ouml:mae,para:vae,plusmn:yae,pound:bae,quot:wae,QUOT:xae,raquo:kae,reg:Sae,REG:_ae,sect:Tae,shy:Cae,sup1:Eae,sup2:Aae,sup3:Lae,szlig:Mae,THORN:Nae,thorn:Oae,times:Pae,Uacute:Rae,uacute:$ae,Ucirc:Iae,ucirc:Dae,Ugrave:zae,ugrave:Fae,uml:Hae,Uuml:Bae,uuml:Wae,Yacute:qae,yacute:jae,yen:Uae,yuml:Vae},Kae=\"&\",Xae=\"'\",Yae=\">\",Zae=\"<\",Jae='\"',ux={amp:Kae,apos:Xae,gt:Yae,lt:Zae,quot:Jae};var Ts={};const Qae={0:65533,128:8364,130:8218,131:402,132:8222,133:8230,134:8224,135:8225,136:710,137:8240,138:352,139:8249,140:338,142:381,145:8216,146:8217,147:8220,148:8221,149:8226,150:8211,151:8212,152:732,153:8482,154:353,155:8250,156:339,158:382,159:376};var fy;function ece(){if(fy)return Ts;fy=1;var e=Ts&&Ts.__importDefault||function(s){return s&&s.__esModule?s:{default:s}};Object.defineProperty(Ts,\"__esModule\",{value:!0});var t=e(Qae),r=String.fromCodePoint||function(s){var c=\"\";return s>65535&&(s-=65536,c+=String.fromCharCode(s>>>10&1023|55296),s=56320|s&1023),c+=String.fromCharCode(s),c};function o(s){return s>=55296&&s<=57343||s>1114111?\"�\":(s in t.default&&(s=t.default[s]),r(s))}return Ts.default=o,Ts}var dy;function hy(){if(dy)return Er;dy=1;var e=Er&&Er.__importDefault||function(p){return p&&p.__esModule?p:{default:p}};Object.defineProperty(Er,\"__esModule\",{value:!0}),Er.decodeHTML=Er.decodeHTMLStrict=Er.decodeXML=void 0;var t=e(cx),r=e(Gae),o=e(ux),s=e(ece()),c=/&(?:[a-zA-Z0-9]+|#[xX][\\da-fA-F]+|#\\d+);/g;Er.decodeXML=f(o.default),Er.decodeHTMLStrict=f(t.default);function f(p){var g=h(p);return function(v){return String(v).replace(c,g)}}var d=function(p,g){return p<g?1:-1};Er.decodeHTML=(function(){for(var p=Object.keys(r.default).sort(d),g=Object.keys(t.default).sort(d),v=0,b=0;v<g.length;v++)p[b]===g[v]?(g[v]+=\";?\",b++):g[v]+=\";\";var w=new RegExp(\"&(?:\"+g.join(\"|\")+\"|#[xX][\\\\da-fA-F]+;?|#\\\\d+;?)\",\"g\"),E=h(t.default);function L(P){return P.substr(-1)!==\";\"&&(P+=\";\"),E(P)}return function(P){return String(P).replace(w,L)}})();function h(p){return function(v){if(v.charAt(1)===\"#\"){var b=v.charAt(2);return b===\"X\"||b===\"x\"?s.default(parseInt(v.substr(3),16)):s.default(parseInt(v.substr(2),10))}return p[v.slice(1,-1)]||v}}return Er}var Ln={},py;function gy(){if(py)return Ln;py=1;var e=Ln&&Ln.__importDefault||function(M){return M&&M.__esModule?M:{default:M}};Object.defineProperty(Ln,\"__esModule\",{value:!0}),Ln.escapeUTF8=Ln.escape=Ln.encodeNonAsciiHTML=Ln.encodeHTML=Ln.encodeXML=void 0;var t=e(ux),r=d(t.default),o=h(r);Ln.encodeXML=P(r);var s=e(cx),c=d(s.default),f=h(c);Ln.encodeHTML=b(c,f),Ln.encodeNonAsciiHTML=P(c);function d(M){return Object.keys(M).sort().reduce(function(R,I){return R[M[I]]=\"&\"+I+\";\",R},{})}function h(M){for(var R=[],I=[],_=0,$=Object.keys(M);_<$.length;_++){var W=$[_];W.length===1?R.push(\"\\\\\"+W):I.push(W)}R.sort();for(var ne=0;ne<R.length-1;ne++){for(var ee=ne;ee<R.length-1&&R[ee].charCodeAt(1)+1===R[ee+1].charCodeAt(1);)ee+=1;var Z=1+ee-ne;Z<3||R.splice(ne,Z,R[ne]+\"-\"+R[ee])}return I.unshift(\"[\"+R.join(\"\")+\"]\"),new RegExp(I.join(\"|\"),\"g\")}var p=/(?:[\\x80-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF])/g,g=String.prototype.codePointAt!=null?function(M){return M.codePointAt(0)}:function(M){return(M.charCodeAt(0)-55296)*1024+M.charCodeAt(1)-56320+65536};function v(M){return\"&#x\"+(M.length>1?g(M):M.charCodeAt(0)).toString(16).toUpperCase()+\";\"}function b(M,R){return function(I){return I.replace(R,function(_){return M[_]}).replace(p,v)}}var w=new RegExp(o.source+\"|\"+p.source,\"g\");function E(M){return M.replace(w,v)}Ln.escape=E;function L(M){return M.replace(o,v)}Ln.escapeUTF8=L;function P(M){return function(R){return R.replace(w,function(I){return M[I]||v(I)})}}return Ln}var my;function tce(){return my||(my=1,(function(e){Object.defineProperty(e,\"__esModule\",{value:!0}),e.decodeXMLStrict=e.decodeHTML5Strict=e.decodeHTML4Strict=e.decodeHTML5=e.decodeHTML4=e.decodeHTMLStrict=e.decodeHTML=e.decodeXML=e.encodeHTML5=e.encodeHTML4=e.escapeUTF8=e.escape=e.encodeNonAsciiHTML=e.encodeHTML=e.encodeXML=e.encode=e.decodeStrict=e.decode=void 0;var t=hy(),r=gy();function o(h,p){return(!p||p<=0?t.decodeXML:t.decodeHTML)(h)}e.decode=o;function s(h,p){return(!p||p<=0?t.decodeXML:t.decodeHTMLStrict)(h)}e.decodeStrict=s;function c(h,p){return(!p||p<=0?r.encodeXML:r.encodeHTML)(h)}e.encode=c;var f=gy();Object.defineProperty(e,\"encodeXML\",{enumerable:!0,get:function(){return f.encodeXML}}),Object.defineProperty(e,\"encodeHTML\",{enumerable:!0,get:function(){return f.encodeHTML}}),Object.defineProperty(e,\"encodeNonAsciiHTML\",{enumerable:!0,get:function(){return f.encodeNonAsciiHTML}}),Object.defineProperty(e,\"escape\",{enumerable:!0,get:function(){return f.escape}}),Object.defineProperty(e,\"escapeUTF8\",{enumerable:!0,get:function(){return f.escapeUTF8}}),Object.defineProperty(e,\"encodeHTML4\",{enumerable:!0,get:function(){return f.encodeHTML}}),Object.defineProperty(e,\"encodeHTML5\",{enumerable:!0,get:function(){return f.encodeHTML}});var d=hy();Object.defineProperty(e,\"decodeXML\",{enumerable:!0,get:function(){return d.decodeXML}}),Object.defineProperty(e,\"decodeHTML\",{enumerable:!0,get:function(){return d.decodeHTML}}),Object.defineProperty(e,\"decodeHTMLStrict\",{enumerable:!0,get:function(){return d.decodeHTMLStrict}}),Object.defineProperty(e,\"decodeHTML4\",{enumerable:!0,get:function(){return d.decodeHTML}}),Object.defineProperty(e,\"decodeHTML5\",{enumerable:!0,get:function(){return d.decodeHTML}}),Object.defineProperty(e,\"decodeHTML4Strict\",{enumerable:!0,get:function(){return d.decodeHTMLStrict}}),Object.defineProperty(e,\"decodeHTML5Strict\",{enumerable:!0,get:function(){return d.decodeHTMLStrict}}),Object.defineProperty(e,\"decodeXMLStrict\",{enumerable:!0,get:function(){return d.decodeXML}})})(Ad)),Ad}var Ld,vy;function nce(){if(vy)return Ld;vy=1;function e(N,O){if(!(N instanceof O))throw new TypeError(\"Cannot call a class as a function\")}function t(N,O){for(var C=0;C<O.length;C++){var k=O[C];k.enumerable=k.enumerable||!1,k.configurable=!0,\"value\"in k&&(k.writable=!0),Object.defineProperty(N,k.key,k)}}function r(N,O,C){return O&&t(N.prototype,O),N}function o(N,O){var C=typeof Symbol<\"u\"&&N[Symbol.iterator]||N[\"@@iterator\"];if(!C){if(Array.isArray(N)||(C=s(N))||O){C&&(N=C);var k=0,z=function(){};return{s:z,n:function(){return k>=N.length?{done:!0}:{done:!1,value:N[k++]}},e:function(Be){throw Be},f:z}}throw new TypeError(`Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var B=!0,ce=!1,be;return{s:function(){C=C.call(N)},n:function(){var Be=C.next();return B=Be.done,Be},e:function(Be){ce=!0,be=Be},f:function(){try{!B&&C.return!=null&&C.return()}finally{if(ce)throw be}}}}function s(N,O){if(N){if(typeof N==\"string\")return c(N,O);var C=Object.prototype.toString.call(N).slice(8,-1);if(C===\"Object\"&&N.constructor&&(C=N.constructor.name),C===\"Map\"||C===\"Set\")return Array.from(N);if(C===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(C))return c(N,O)}}function c(N,O){(O==null||O>N.length)&&(O=N.length);for(var C=0,k=new Array(O);C<O;C++)k[C]=N[C];return k}var f=tce(),d={fg:\"#FFF\",bg:\"#000\",newline:!1,escapeXML:!1,stream:!1,colors:h()};function h(){var N={0:\"#000\",1:\"#A00\",2:\"#0A0\",3:\"#A50\",4:\"#00A\",5:\"#A0A\",6:\"#0AA\",7:\"#AAA\",8:\"#555\",9:\"#F55\",10:\"#5F5\",11:\"#FF5\",12:\"#55F\",13:\"#F5F\",14:\"#5FF\",15:\"#FFF\"};return P(0,5).forEach(function(O){P(0,5).forEach(function(C){P(0,5).forEach(function(k){return p(O,C,k,N)})})}),P(0,23).forEach(function(O){var C=O+232,k=g(O*10+8);N[C]=\"#\"+k+k+k}),N}function p(N,O,C,k){var z=16+N*36+O*6+C,B=N>0?N*40+55:0,ce=O>0?O*40+55:0,be=C>0?C*40+55:0;k[z]=v([B,ce,be])}function g(N){for(var O=N.toString(16);O.length<2;)O=\"0\"+O;return O}function v(N){var O=[],C=o(N),k;try{for(C.s();!(k=C.n()).done;){var z=k.value;O.push(g(z))}}catch(B){C.e(B)}finally{C.f()}return\"#\"+O.join(\"\")}function b(N,O,C,k){var z;return O===\"text\"?z=I(C,k):O===\"display\"?z=E(N,C,k):O===\"xterm256Foreground\"?z=W(N,k.colors[C]):O===\"xterm256Background\"?z=ne(N,k.colors[C]):O===\"rgb\"&&(z=w(N,C)),z}function w(N,O){O=O.substring(2).slice(0,-1);var C=+O.substr(0,2),k=O.substring(5).split(\";\"),z=k.map(function(B){return(\"0\"+Number(B).toString(16)).substr(-2)}).join(\"\");return $(N,(C===38?\"color:#\":\"background-color:#\")+z)}function E(N,O,C){O=parseInt(O,10);var k={\"-1\":function(){return\"<br/>\"},0:function(){return N.length&&L(N)},1:function(){return _(N,\"b\")},3:function(){return _(N,\"i\")},4:function(){return _(N,\"u\")},8:function(){return $(N,\"display:none\")},9:function(){return _(N,\"strike\")},22:function(){return $(N,\"font-weight:normal;text-decoration:none;font-style:normal\")},23:function(){return ee(N,\"i\")},24:function(){return ee(N,\"u\")},39:function(){return W(N,C.fg)},49:function(){return ne(N,C.bg)},53:function(){return $(N,\"text-decoration:overline\")}},z;return k[O]?z=k[O]():4<O&&O<7?z=_(N,\"blink\"):29<O&&O<38?z=W(N,C.colors[O-30]):39<O&&O<48?z=ne(N,C.colors[O-40]):89<O&&O<98?z=W(N,C.colors[8+(O-90)]):99<O&&O<108&&(z=ne(N,C.colors[8+(O-100)])),z}function L(N){var O=N.slice(0);return N.length=0,O.reverse().map(function(C){return\"</\"+C+\">\"}).join(\"\")}function P(N,O){for(var C=[],k=N;k<=O;k++)C.push(k);return C}function M(N){return function(O){return(N===null||O.category!==N)&&N!==\"all\"}}function R(N){N=parseInt(N,10);var O=null;return N===0?O=\"all\":N===1?O=\"bold\":2<N&&N<5?O=\"underline\":4<N&&N<7?O=\"blink\":N===8?O=\"hide\":N===9?O=\"strike\":29<N&&N<38||N===39||89<N&&N<98?O=\"foreground-color\":(39<N&&N<48||N===49||99<N&&N<108)&&(O=\"background-color\"),O}function I(N,O){return O.escapeXML?f.encodeXML(N):N}function _(N,O,C){return C||(C=\"\"),N.push(O),\"<\".concat(O).concat(C?' style=\"'.concat(C,'\"'):\"\",\">\")}function $(N,O){return _(N,\"span\",O)}function W(N,O){return _(N,\"span\",\"color:\"+O)}function ne(N,O){return _(N,\"span\",\"background-color:\"+O)}function ee(N,O){var C;if(N.slice(-1)[0]===O&&(C=N.pop()),C)return\"</\"+O+\">\"}function Z(N,O,C){var k=!1,z=3;function B(){return\"\"}function ce(q,Q){return C(\"xterm256Foreground\",Q),\"\"}function be(q,Q){return C(\"xterm256Background\",Q),\"\"}function Se(q){return O.newline?C(\"display\",-1):C(\"text\",q),\"\"}function Be(q,Q){k=!0,Q.trim().length===0&&(Q=\"0\"),Q=Q.trimRight(\";\").split(\";\");var he=o(Q),de;try{for(he.s();!(de=he.n()).done;){var ge=de.value;C(\"display\",ge)}}catch(Ce){he.e(Ce)}finally{he.f()}return\"\"}function Ae(q){return C(\"text\",q),\"\"}function Ke(q){return C(\"rgb\",q),\"\"}var je=[{pattern:/^\\x08+/,sub:B},{pattern:/^\\x1b\\[[012]?K/,sub:B},{pattern:/^\\x1b\\[\\(B/,sub:B},{pattern:/^\\x1b\\[[34]8;2;\\d+;\\d+;\\d+m/,sub:Ke},{pattern:/^\\x1b\\[38;5;(\\d+)m/,sub:ce},{pattern:/^\\x1b\\[48;5;(\\d+)m/,sub:be},{pattern:/^\\n/,sub:Se},{pattern:/^\\r+\\n/,sub:Se},{pattern:/^\\r/,sub:Se},{pattern:/^\\x1b\\[((?:\\d{1,3};?)+|)m/,sub:Be},{pattern:/^\\x1b\\[\\d?J/,sub:B},{pattern:/^\\x1b\\[\\d{0,3};\\d{0,3}f/,sub:B},{pattern:/^\\x1b\\[?[\\d;]{0,3}/,sub:B},{pattern:/^(([^\\x1b\\x08\\r\\n])+)/,sub:Ae}];function Fe(q,Q){Q>z&&k||(k=!1,N=N.replace(q.pattern,q.sub))}var Pe=[],F=N,Y=F.length;e:for(;Y>0;){for(var re=0,le=0,ae=je.length;le<ae;re=++le){var D=je[re];if(Fe(D,re),N.length!==Y){Y=N.length;continue e}}if(N.length===Y)break;Pe.push(0),Y=N.length}return Pe}function G(N,O,C){return O!==\"text\"&&(N=N.filter(M(R(C))),N.push({token:O,data:C,category:R(C)})),N}var j=(function(){function N(O){e(this,N),O=O||{},O.colors&&(O.colors=Object.assign({},d.colors,O.colors)),this.options=Object.assign({},d,O),this.stack=[],this.stickyStack=[]}return r(N,[{key:\"toHtml\",value:function(C){var k=this;C=typeof C==\"string\"?[C]:C;var z=this.stack,B=this.options,ce=[];return this.stickyStack.forEach(function(be){var Se=b(z,be.token,be.data,B);Se&&ce.push(Se)}),Z(C.join(\"\"),B,function(be,Se){var Be=b(z,be,Se,B);Be&&ce.push(Be),B.stream&&(k.stickyStack=G(k.stickyStack,be,Se))}),z.length&&ce.push(L(z)),ce.join(\"\")}}]),N})();return Ld=j,Ld}var rce=nce();const ice=ax(rce);function oa(e){return e.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\")}function oce(e,t){return t&&e.endsWith(t)}async function bp(e,t,r){const o=encodeURI(`${e}:${t}:${r}`);await fetch(`/__open-in-editor?file=${o}`)}function wp(e){return new ice({fg:e?\"#FFF\":\"#000\",bg:e?\"#000\":\"#FFF\"})}function sce(e){return e===null||typeof e!=\"function\"&&typeof e!=\"object\"}function fx(e){let t=e;if(sce(e)&&(t={message:String(t).split(/\\n/g)[0],stack:String(t),name:\"\",stacks:[]}),!e){const r=new Error(\"unknown error\");t={message:r.message,stack:r.stack,name:\"\",stacks:[]}}return t.stacks=wA(t.stack||\"\",{ignoreStackEntries:[]}),t}function lce(e,t){let r=\"\";return t.message?.includes(\"\\x1B\")&&(r=`<b>${t.name}</b>: ${e.toHtml(oa(t.message))}`),t.stack?.includes(\"\\x1B\")&&(r.length>0?r+=e.toHtml(oa(t.stack)):r=`<b>${t.name}</b>: ${t.message}${e.toHtml(oa(t.stack))}`),r.length>0?r:null}function dx(e,t){const r=wp(e);return t.map(o=>{const s=o.result;if(!s||s.htmlError)return o;const c=s.errors?.map(f=>lce(r,f)).filter(f=>f!=null).join(\"<br><br>\");return c?.length&&(s.htmlError=c),o})}const Wa=jE(\"hash\",{initialValue:{file:\"\",view:null,line:null,test:null,column:null}}),po=Yo(Wa,\"file\"),hn=Yo(Wa,\"view\"),hx=Yo(Wa,\"line\"),px=Yo(Wa,\"column\"),Bs=Yo(Wa,\"test\");var yy={exports:{}},by;function xp(){return by||(by=1,(function(e,t){(function(r){r(vo())})(function(r){r.defineMode(\"javascript\",function(o,s){var c=o.indentUnit,f=s.statementIndent,d=s.jsonld,h=s.json||d,p=s.trackScope!==!1,g=s.typescript,v=s.wordCharacters||/[\\w$\\xa1-\\uffff]/,b=(function(){function A(Zt){return{type:Zt,style:\"keyword\"}}var U=A(\"keyword a\"),me=A(\"keyword b\"),_e=A(\"keyword c\"),fe=A(\"keyword d\"),Ie=A(\"operator\"),pt={type:\"atom\",style:\"atom\"};return{if:A(\"if\"),while:U,with:U,else:me,do:me,try:me,finally:me,return:fe,break:fe,continue:fe,new:A(\"new\"),delete:_e,void:_e,throw:_e,debugger:A(\"debugger\"),var:A(\"var\"),const:A(\"var\"),let:A(\"var\"),function:A(\"function\"),catch:A(\"catch\"),for:A(\"for\"),switch:A(\"switch\"),case:A(\"case\"),default:A(\"default\"),in:Ie,typeof:Ie,instanceof:Ie,true:pt,false:pt,null:pt,undefined:pt,NaN:pt,Infinity:pt,this:A(\"this\"),class:A(\"class\"),super:A(\"atom\"),yield:_e,export:A(\"export\"),import:A(\"import\"),extends:_e,await:_e}})(),w=/[+\\-*&%=<>!?|~^@]/,E=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)\"/;function L(A){for(var U=!1,me,_e=!1;(me=A.next())!=null;){if(!U){if(me==\"/\"&&!_e)return;me==\"[\"?_e=!0:_e&&me==\"]\"&&(_e=!1)}U=!U&&me==\"\\\\\"}}var P,M;function R(A,U,me){return P=A,M=me,U}function I(A,U){var me=A.next();if(me=='\"'||me==\"'\")return U.tokenize=_(me),U.tokenize(A,U);if(me==\".\"&&A.match(/^\\d[\\d_]*(?:[eE][+\\-]?[\\d_]+)?/))return R(\"number\",\"number\");if(me==\".\"&&A.match(\"..\"))return R(\"spread\",\"meta\");if(/[\\[\\]{}\\(\\),;\\:\\.]/.test(me))return R(me);if(me==\"=\"&&A.eat(\">\"))return R(\"=>\",\"operator\");if(me==\"0\"&&A.match(/^(?:x[\\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/))return R(\"number\",\"number\");if(/\\d/.test(me))return A.match(/^[\\d_]*(?:n|(?:\\.[\\d_]*)?(?:[eE][+\\-]?[\\d_]+)?)?/),R(\"number\",\"number\");if(me==\"/\")return A.eat(\"*\")?(U.tokenize=$,$(A,U)):A.eat(\"/\")?(A.skipToEnd(),R(\"comment\",\"comment\")):Qn(A,U,1)?(L(A),A.match(/^\\b(([gimyus])(?![gimyus]*\\2))+\\b/),R(\"regexp\",\"string-2\")):(A.eat(\"=\"),R(\"operator\",\"operator\",A.current()));if(me==\"`\")return U.tokenize=W,W(A,U);if(me==\"#\"&&A.peek()==\"!\")return A.skipToEnd(),R(\"meta\",\"meta\");if(me==\"#\"&&A.eatWhile(v))return R(\"variable\",\"property\");if(me==\"<\"&&A.match(\"!--\")||me==\"-\"&&A.match(\"->\")&&!/\\S/.test(A.string.slice(0,A.start)))return A.skipToEnd(),R(\"comment\",\"comment\");if(w.test(me))return(me!=\">\"||!U.lexical||U.lexical.type!=\">\")&&(A.eat(\"=\")?(me==\"!\"||me==\"=\")&&A.eat(\"=\"):/[<>*+\\-|&?]/.test(me)&&(A.eat(me),me==\">\"&&A.eat(me))),me==\"?\"&&A.eat(\".\")?R(\".\"):R(\"operator\",\"operator\",A.current());if(v.test(me)){A.eatWhile(v);var _e=A.current();if(U.lastType!=\".\"){if(b.propertyIsEnumerable(_e)){var fe=b[_e];return R(fe.type,fe.style,_e)}if(_e==\"async\"&&A.match(/^(\\s|\\/\\*([^*]|\\*(?!\\/))*?\\*\\/)*[\\[\\(\\w]/,!1))return R(\"async\",\"keyword\",_e)}return R(\"variable\",\"variable\",_e)}}function _(A){return function(U,me){var _e=!1,fe;if(d&&U.peek()==\"@\"&&U.match(E))return me.tokenize=I,R(\"jsonld-keyword\",\"meta\");for(;(fe=U.next())!=null&&!(fe==A&&!_e);)_e=!_e&&fe==\"\\\\\";return _e||(me.tokenize=I),R(\"string\",\"string\")}}function $(A,U){for(var me=!1,_e;_e=A.next();){if(_e==\"/\"&&me){U.tokenize=I;break}me=_e==\"*\"}return R(\"comment\",\"comment\")}function W(A,U){for(var me=!1,_e;(_e=A.next())!=null;){if(!me&&(_e==\"`\"||_e==\"$\"&&A.eat(\"{\"))){U.tokenize=I;break}me=!me&&_e==\"\\\\\"}return R(\"quasi\",\"string-2\",A.current())}var ne=\"([{}])\";function ee(A,U){U.fatArrowAt&&(U.fatArrowAt=null);var me=A.string.indexOf(\"=>\",A.start);if(!(me<0)){if(g){var _e=/:\\s*(?:\\w+(?:<[^>]*>|\\[\\])?|\\{[^}]*\\})\\s*$/.exec(A.string.slice(A.start,me));_e&&(me=_e.index)}for(var fe=0,Ie=!1,pt=me-1;pt>=0;--pt){var Zt=A.string.charAt(pt),Sn=ne.indexOf(Zt);if(Sn>=0&&Sn<3){if(!fe){++pt;break}if(--fe==0){Zt==\"(\"&&(Ie=!0);break}}else if(Sn>=3&&Sn<6)++fe;else if(v.test(Zt))Ie=!0;else if(/[\"'\\/`]/.test(Zt))for(;;--pt){if(pt==0)return;var is=A.string.charAt(pt-1);if(is==Zt&&A.string.charAt(pt-2)!=\"\\\\\"){pt--;break}}else if(Ie&&!fe){++pt;break}}Ie&&!fe&&(U.fatArrowAt=pt)}}var Z={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,this:!0,import:!0,\"jsonld-keyword\":!0};function G(A,U,me,_e,fe,Ie){this.indented=A,this.column=U,this.type=me,this.prev=fe,this.info=Ie,_e!=null&&(this.align=_e)}function j(A,U){if(!p)return!1;for(var me=A.localVars;me;me=me.next)if(me.name==U)return!0;for(var _e=A.context;_e;_e=_e.prev)for(var me=_e.vars;me;me=me.next)if(me.name==U)return!0}function N(A,U,me,_e,fe){var Ie=A.cc;for(O.state=A,O.stream=fe,O.marked=null,O.cc=Ie,O.style=U,A.lexical.hasOwnProperty(\"align\")||(A.lexical.align=!0);;){var pt=Ie.length?Ie.pop():h?ae:re;if(pt(me,_e)){for(;Ie.length&&Ie[Ie.length-1].lex;)Ie.pop()();return O.marked?O.marked:me==\"variable\"&&j(A,_e)?\"variable-2\":U}}}var O={state:null,marked:null,cc:null};function C(){for(var A=arguments.length-1;A>=0;A--)O.cc.push(arguments[A])}function k(){return C.apply(null,arguments),!0}function z(A,U){for(var me=U;me;me=me.next)if(me.name==A)return!0;return!1}function B(A){var U=O.state;if(O.marked=\"def\",!!p){if(U.context){if(U.lexical.info==\"var\"&&U.context&&U.context.block){var me=ce(A,U.context);if(me!=null){U.context=me;return}}else if(!z(A,U.localVars)){U.localVars=new Be(A,U.localVars);return}}s.globalVars&&!z(A,U.globalVars)&&(U.globalVars=new Be(A,U.globalVars))}}function ce(A,U){if(U)if(U.block){var me=ce(A,U.prev);return me?me==U.prev?U:new Se(me,U.vars,!0):null}else return z(A,U.vars)?U:new Se(U.prev,new Be(A,U.vars),!1);else return null}function be(A){return A==\"public\"||A==\"private\"||A==\"protected\"||A==\"abstract\"||A==\"readonly\"}function Se(A,U,me){this.prev=A,this.vars=U,this.block=me}function Be(A,U){this.name=A,this.next=U}var Ae=new Be(\"this\",new Be(\"arguments\",null));function Ke(){O.state.context=new Se(O.state.context,O.state.localVars,!1),O.state.localVars=Ae}function je(){O.state.context=new Se(O.state.context,O.state.localVars,!0),O.state.localVars=null}Ke.lex=je.lex=!0;function Fe(){O.state.localVars=O.state.context.vars,O.state.context=O.state.context.prev}Fe.lex=!0;function Pe(A,U){var me=function(){var _e=O.state,fe=_e.indented;if(_e.lexical.type==\"stat\")fe=_e.lexical.indented;else for(var Ie=_e.lexical;Ie&&Ie.type==\")\"&&Ie.align;Ie=Ie.prev)fe=Ie.indented;_e.lexical=new G(fe,O.stream.column(),A,null,_e.lexical,U)};return me.lex=!0,me}function F(){var A=O.state;A.lexical.prev&&(A.lexical.type==\")\"&&(A.indented=A.lexical.indented),A.lexical=A.lexical.prev)}F.lex=!0;function Y(A){function U(me){return me==A?k():A==\";\"||me==\"}\"||me==\")\"||me==\"]\"?C():k(U)}return U}function re(A,U){return A==\"var\"?k(Pe(\"vardef\",U),Zo,Y(\";\"),F):A==\"keyword a\"?k(Pe(\"form\"),q,re,F):A==\"keyword b\"?k(Pe(\"form\"),re,F):A==\"keyword d\"?O.stream.match(/^\\s*$/,!1)?k():k(Pe(\"stat\"),he,Y(\";\"),F):A==\"debugger\"?k(Y(\";\")):A==\"{\"?k(Pe(\"}\"),je,jt,F,Fe):A==\";\"?k():A==\"if\"?(O.state.lexical.info==\"else\"&&O.state.cc[O.state.cc.length-1]==F&&O.state.cc.pop()(),k(Pe(\"form\"),q,re,F,Jo)):A==\"function\"?k(cr):A==\"for\"?k(Pe(\"form\"),je,Ga,re,Fe,F):A==\"class\"||g&&U==\"interface\"?(O.marked=\"keyword\",k(Pe(\"form\",A==\"class\"?A:U),Qo,F)):A==\"variable\"?g&&U==\"declare\"?(O.marked=\"keyword\",k(re)):g&&(U==\"module\"||U==\"enum\"||U==\"type\")&&O.stream.match(/^\\s*\\w/,!1)?(O.marked=\"keyword\",U==\"enum\"?k(qe):U==\"type\"?k(Ka,Y(\"operator\"),lt,Y(\";\")):k(Pe(\"form\"),kn,Y(\"{\"),Pe(\"}\"),jt,F,F)):g&&U==\"namespace\"?(O.marked=\"keyword\",k(Pe(\"form\"),ae,re,F)):g&&U==\"abstract\"?(O.marked=\"keyword\",k(re)):k(Pe(\"stat\"),$e):A==\"switch\"?k(Pe(\"form\"),q,Y(\"{\"),Pe(\"}\",\"switch\"),je,jt,F,F,Fe):A==\"case\"?k(ae,Y(\":\")):A==\"default\"?k(Y(\":\")):A==\"catch\"?k(Pe(\"form\"),Ke,le,re,F,Fe):A==\"export\"?k(Pe(\"stat\"),es,F):A==\"import\"?k(Pe(\"stat\"),$i,F):A==\"async\"?k(re):U==\"@\"?k(ae,re):C(Pe(\"stat\"),ae,Y(\";\"),F)}function le(A){if(A==\"(\")return k(wr,Y(\")\"))}function ae(A,U){return Q(A,U,!1)}function D(A,U){return Q(A,U,!0)}function q(A){return A!=\"(\"?C():k(Pe(\")\"),he,Y(\")\"),F)}function Q(A,U,me){if(O.state.fatArrowAt==O.stream.start){var _e=me?ye:xe;if(A==\"(\")return k(Ke,Pe(\")\"),ut(wr,\")\"),F,Y(\"=>\"),_e,Fe);if(A==\"variable\")return C(Ke,kn,Y(\"=>\"),_e,Fe)}var fe=me?ge:de;return Z.hasOwnProperty(A)?k(fe):A==\"function\"?k(cr,fe):A==\"class\"||g&&U==\"interface\"?(O.marked=\"keyword\",k(Pe(\"form\"),vf,F)):A==\"keyword c\"||A==\"async\"?k(me?D:ae):A==\"(\"?k(Pe(\")\"),he,Y(\")\"),F,fe):A==\"operator\"||A==\"spread\"?k(me?D:ae):A==\"[\"?k(Pe(\"]\"),$t,F,fe):A==\"{\"?Yt(ct,\"}\",null,fe):A==\"quasi\"?C(Ce,fe):A==\"new\"?k(J(me)):k()}function he(A){return A.match(/[;\\}\\)\\],]/)?C():C(ae)}function de(A,U){return A==\",\"?k(he):ge(A,U,!1)}function ge(A,U,me){var _e=me==!1?de:ge,fe=me==!1?ae:D;if(A==\"=>\")return k(Ke,me?ye:xe,Fe);if(A==\"operator\")return/\\+\\+|--/.test(U)||g&&U==\"!\"?k(_e):g&&U==\"<\"&&O.stream.match(/^([^<>]|<[^<>]*>)*>\\s*\\(/,!1)?k(Pe(\">\"),ut(lt,\">\"),F,_e):U==\"?\"?k(ae,Y(\":\"),fe):k(fe);if(A==\"quasi\")return C(Ce,_e);if(A!=\";\"){if(A==\"(\")return Yt(D,\")\",\"call\",_e);if(A==\".\")return k(Je,_e);if(A==\"[\")return k(Pe(\"]\"),he,Y(\"]\"),F,_e);if(g&&U==\"as\")return O.marked=\"keyword\",k(lt,_e);if(A==\"regexp\")return O.state.lastType=O.marked=\"operator\",O.stream.backUp(O.stream.pos-O.stream.start-1),k(fe)}}function Ce(A,U){return A!=\"quasi\"?C():U.slice(U.length-2)!=\"${\"?k(Ce):k(he,Ee)}function Ee(A){if(A==\"}\")return O.marked=\"string-2\",O.state.tokenize=W,k(Ce)}function xe(A){return ee(O.stream,O.state),C(A==\"{\"?re:ae)}function ye(A){return ee(O.stream,O.state),C(A==\"{\"?re:D)}function J(A){return function(U){return U==\".\"?k(A?oe:ue):U==\"variable\"&&g?k(Bn,A?ge:de):C(A?D:ae)}}function ue(A,U){if(U==\"target\")return O.marked=\"keyword\",k(de)}function oe(A,U){if(U==\"target\")return O.marked=\"keyword\",k(ge)}function $e(A){return A==\":\"?k(F,re):C(de,Y(\";\"),F)}function Je(A){if(A==\"variable\")return O.marked=\"property\",k()}function ct(A,U){if(A==\"async\")return O.marked=\"property\",k(ct);if(A==\"variable\"||O.style==\"keyword\"){if(O.marked=\"property\",U==\"get\"||U==\"set\")return k(dt);var me;return g&&O.state.fatArrowAt==O.stream.start&&(me=O.stream.match(/^\\s*:\\s*/,!1))&&(O.state.fatArrowAt=O.stream.pos+me[0].length),k(Nt)}else{if(A==\"number\"||A==\"string\")return O.marked=d?\"property\":O.style+\" property\",k(Nt);if(A==\"jsonld-keyword\")return k(Nt);if(g&&be(U))return O.marked=\"keyword\",k(ct);if(A==\"[\")return k(ae,Fn,Y(\"]\"),Nt);if(A==\"spread\")return k(D,Nt);if(U==\"*\")return O.marked=\"keyword\",k(ct);if(A==\":\")return C(Nt)}}function dt(A){return A!=\"variable\"?C(Nt):(O.marked=\"property\",k(cr))}function Nt(A){if(A==\":\")return k(D);if(A==\"(\")return C(cr)}function ut(A,U,me){function _e(fe,Ie){if(me?me.indexOf(fe)>-1:fe==\",\"){var pt=O.state.lexical;return pt.info==\"call\"&&(pt.pos=(pt.pos||0)+1),k(function(Zt,Sn){return Zt==U||Sn==U?C():C(A)},_e)}return fe==U||Ie==U?k():me&&me.indexOf(\";\")>-1?C(A):k(Y(U))}return function(fe,Ie){return fe==U||Ie==U?k():C(A,_e)}}function Yt(A,U,me){for(var _e=3;_e<arguments.length;_e++)O.cc.push(arguments[_e]);return k(Pe(U,me),ut(A,U),F)}function jt(A){return A==\"}\"?k():C(re,jt)}function Fn(A,U){if(g){if(A==\":\")return k(lt);if(U==\"?\")return k(Fn)}}function Hr(A,U){if(g&&(A==\":\"||U==\"in\"))return k(lt)}function Bt(A){if(g&&A==\":\")return O.stream.match(/^\\s*\\w+\\s+is\\b/,!1)?k(ae,Hn,lt):k(lt)}function Hn(A,U){if(U==\"is\")return O.marked=\"keyword\",k()}function lt(A,U){if(U==\"keyof\"||U==\"typeof\"||U==\"infer\"||U==\"readonly\")return O.marked=\"keyword\",k(U==\"typeof\"?D:lt);if(A==\"variable\"||U==\"void\")return O.marked=\"type\",k(ar);if(U==\"|\"||U==\"&\")return k(lt);if(A==\"string\"||A==\"number\"||A==\"atom\")return k(ar);if(A==\"[\")return k(Pe(\"]\"),ut(lt,\"]\",\",\"),F,ar);if(A==\"{\")return k(Pe(\"}\"),Xe,F,ar);if(A==\"(\")return k(ut(Rt,\")\"),yo,ar);if(A==\"<\")return k(ut(lt,\">\"),lt);if(A==\"quasi\")return C(an,ar)}function yo(A){if(A==\"=>\")return k(lt)}function Xe(A){return A.match(/[\\}\\)\\]]/)?k():A==\",\"||A==\";\"?k(Xe):C(ri,Xe)}function ri(A,U){if(A==\"variable\"||O.style==\"keyword\")return O.marked=\"property\",k(ri);if(U==\"?\"||A==\"number\"||A==\"string\")return k(ri);if(A==\":\")return k(lt);if(A==\"[\")return k(Y(\"variable\"),Hr,Y(\"]\"),ri);if(A==\"(\")return C(Ri,ri);if(!A.match(/[;\\}\\)\\],]/))return k()}function an(A,U){return A!=\"quasi\"?C():U.slice(U.length-2)!=\"${\"?k(an):k(lt,Pt)}function Pt(A){if(A==\"}\")return O.marked=\"string-2\",O.state.tokenize=W,k(an)}function Rt(A,U){return A==\"variable\"&&O.stream.match(/^\\s*[?:]/,!1)||U==\"?\"?k(Rt):A==\":\"?k(lt):A==\"spread\"?k(Rt):C(lt)}function ar(A,U){if(U==\"<\")return k(Pe(\">\"),ut(lt,\">\"),F,ar);if(U==\"|\"||A==\".\"||U==\"&\")return k(lt);if(A==\"[\")return k(lt,Y(\"]\"),ar);if(U==\"extends\"||U==\"implements\")return O.marked=\"keyword\",k(lt);if(U==\"?\")return k(lt,Y(\":\"),lt)}function Bn(A,U){if(U==\"<\")return k(Pe(\">\"),ut(lt,\">\"),F,ar)}function yr(){return C(lt,cn)}function cn(A,U){if(U==\"=\")return k(lt)}function Zo(A,U){return U==\"enum\"?(O.marked=\"keyword\",k(qe)):C(kn,Fn,br,mf)}function kn(A,U){if(g&&be(U))return O.marked=\"keyword\",k(kn);if(A==\"variable\")return B(U),k();if(A==\"spread\")return k(kn);if(A==\"[\")return Yt(sl,\"]\");if(A==\"{\")return Yt(Oi,\"}\")}function Oi(A,U){return A==\"variable\"&&!O.stream.match(/^\\s*:/,!1)?(B(U),k(br)):(A==\"variable\"&&(O.marked=\"property\"),A==\"spread\"?k(kn):A==\"}\"?C():A==\"[\"?k(ae,Y(\"]\"),Y(\":\"),Oi):k(Y(\":\"),kn,br))}function sl(){return C(kn,br)}function br(A,U){if(U==\"=\")return k(D)}function mf(A){if(A==\",\")return k(Zo)}function Jo(A,U){if(A==\"keyword b\"&&U==\"else\")return k(Pe(\"form\",\"else\"),re,F)}function Ga(A,U){if(U==\"await\")return k(Ga);if(A==\"(\")return k(Pe(\")\"),ll,F)}function ll(A){return A==\"var\"?k(Zo,Pi):A==\"variable\"?k(Pi):C(Pi)}function Pi(A,U){return A==\")\"?k():A==\";\"?k(Pi):U==\"in\"||U==\"of\"?(O.marked=\"keyword\",k(ae,Pi)):C(ae,Pi)}function cr(A,U){if(U==\"*\")return O.marked=\"keyword\",k(cr);if(A==\"variable\")return B(U),k(cr);if(A==\"(\")return k(Ke,Pe(\")\"),ut(wr,\")\"),F,Bt,re,Fe);if(g&&U==\"<\")return k(Pe(\">\"),ut(yr,\">\"),F,cr)}function Ri(A,U){if(U==\"*\")return O.marked=\"keyword\",k(Ri);if(A==\"variable\")return B(U),k(Ri);if(A==\"(\")return k(Ke,Pe(\")\"),ut(wr,\")\"),F,Bt,Fe);if(g&&U==\"<\")return k(Pe(\">\"),ut(yr,\">\"),F,Ri)}function Ka(A,U){if(A==\"keyword\"||A==\"variable\")return O.marked=\"type\",k(Ka);if(U==\"<\")return k(Pe(\">\"),ut(yr,\">\"),F)}function wr(A,U){return U==\"@\"&&k(ae,wr),A==\"spread\"?k(wr):g&&be(U)?(O.marked=\"keyword\",k(wr)):g&&A==\"this\"?k(Fn,br):C(kn,Fn,br)}function vf(A,U){return A==\"variable\"?Qo(A,U):xr(A,U)}function Qo(A,U){if(A==\"variable\")return B(U),k(xr)}function xr(A,U){if(U==\"<\")return k(Pe(\">\"),ut(yr,\">\"),F,xr);if(U==\"extends\"||U==\"implements\"||g&&A==\",\")return U==\"implements\"&&(O.marked=\"keyword\"),k(g?lt:ae,xr);if(A==\"{\")return k(Pe(\"}\"),kr,F)}function kr(A,U){if(A==\"async\"||A==\"variable\"&&(U==\"static\"||U==\"get\"||U==\"set\"||g&&be(U))&&O.stream.match(/^\\s+#?[\\w$\\xa1-\\uffff]/,!1))return O.marked=\"keyword\",k(kr);if(A==\"variable\"||O.style==\"keyword\")return O.marked=\"property\",k(bo,kr);if(A==\"number\"||A==\"string\")return k(bo,kr);if(A==\"[\")return k(ae,Fn,Y(\"]\"),bo,kr);if(U==\"*\")return O.marked=\"keyword\",k(kr);if(g&&A==\"(\")return C(Ri,kr);if(A==\";\"||A==\",\")return k(kr);if(A==\"}\")return k();if(U==\"@\")return k(ae,kr)}function bo(A,U){if(U==\"!\"||U==\"?\")return k(bo);if(A==\":\")return k(lt,br);if(U==\"=\")return k(D);var me=O.state.lexical.prev,_e=me&&me.info==\"interface\";return C(_e?Ri:cr)}function es(A,U){return U==\"*\"?(O.marked=\"keyword\",k(rs,Y(\";\"))):U==\"default\"?(O.marked=\"keyword\",k(ae,Y(\";\"))):A==\"{\"?k(ut(ts,\"}\"),rs,Y(\";\")):C(re)}function ts(A,U){if(U==\"as\")return O.marked=\"keyword\",k(Y(\"variable\"));if(A==\"variable\")return C(D,ts)}function $i(A){return A==\"string\"?k():A==\"(\"?C(ae):A==\".\"?C(de):C(ns,Br,rs)}function ns(A,U){return A==\"{\"?Yt(ns,\"}\"):(A==\"variable\"&&B(U),U==\"*\"&&(O.marked=\"keyword\"),k(al))}function Br(A){if(A==\",\")return k(ns,Br)}function al(A,U){if(U==\"as\")return O.marked=\"keyword\",k(ns)}function rs(A,U){if(U==\"from\")return O.marked=\"keyword\",k(ae)}function $t(A){return A==\"]\"?k():C(ut(D,\"]\"))}function qe(){return C(Pe(\"form\"),kn,Y(\"{\"),Pe(\"}\"),ut(ii,\"}\"),F,F)}function ii(){return C(kn,br)}function cl(A,U){return A.lastType==\"operator\"||A.lastType==\",\"||w.test(U.charAt(0))||/[,.]/.test(U.charAt(0))}function Qn(A,U,me){return U.tokenize==I&&/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\\[{}\\(,;:]|=>)$/.test(U.lastType)||U.lastType==\"quasi\"&&/\\{\\s*$/.test(A.string.slice(0,A.pos-(me||0)))}return{startState:function(A){var U={tokenize:I,lastType:\"sof\",cc:[],lexical:new G((A||0)-c,0,\"block\",!1),localVars:s.localVars,context:s.localVars&&new Se(null,null,!1),indented:A||0};return s.globalVars&&typeof s.globalVars==\"object\"&&(U.globalVars=s.globalVars),U},token:function(A,U){if(A.sol()&&(U.lexical.hasOwnProperty(\"align\")||(U.lexical.align=!1),U.indented=A.indentation(),ee(A,U)),U.tokenize!=$&&A.eatSpace())return null;var me=U.tokenize(A,U);return P==\"comment\"?me:(U.lastType=P==\"operator\"&&(M==\"++\"||M==\"--\")?\"incdec\":P,N(U,me,P,M,A))},indent:function(A,U){if(A.tokenize==$||A.tokenize==W)return r.Pass;if(A.tokenize!=I)return 0;var me=U&&U.charAt(0),_e=A.lexical,fe;if(!/^\\s*else\\b/.test(U))for(var Ie=A.cc.length-1;Ie>=0;--Ie){var pt=A.cc[Ie];if(pt==F)_e=_e.prev;else if(pt!=Jo&&pt!=Fe)break}for(;(_e.type==\"stat\"||_e.type==\"form\")&&(me==\"}\"||(fe=A.cc[A.cc.length-1])&&(fe==de||fe==ge)&&!/^[,\\.=+\\-*:?[\\(]/.test(U));)_e=_e.prev;f&&_e.type==\")\"&&_e.prev.type==\"stat\"&&(_e=_e.prev);var Zt=_e.type,Sn=me==Zt;return Zt==\"vardef\"?_e.indented+(A.lastType==\"operator\"||A.lastType==\",\"?_e.info.length+1:0):Zt==\"form\"&&me==\"{\"?_e.indented:Zt==\"form\"?_e.indented+c:Zt==\"stat\"?_e.indented+(cl(A,U)?f||c:0):_e.info==\"switch\"&&!Sn&&s.doubleIndentSwitch!=!1?_e.indented+(/^(?:case|default)\\b/.test(U)?c:2*c):_e.align?_e.column+(Sn?0:1):_e.indented+(Sn?0:c)},electricInput:/^\\s*(?:case .*?:|default:|\\{|\\})$/,blockCommentStart:h?null:\"/*\",blockCommentEnd:h?null:\"*/\",blockCommentContinue:h?null:\" * \",lineComment:h?null:\"//\",fold:\"brace\",closeBrackets:\"()[]{}''\\\"\\\"``\",helperType:h?\"json\":\"javascript\",jsonldMode:d,jsonMode:h,expressionAllowed:Qn,skipExpression:function(A){N(A,\"atom\",\"atom\",\"true\",new r.StringStream(\"\",2,null))}}}),r.registerHelper(\"wordChars\",\"javascript\",/[\\w$]/),r.defineMIME(\"text/javascript\",\"javascript\"),r.defineMIME(\"text/ecmascript\",\"javascript\"),r.defineMIME(\"application/javascript\",\"javascript\"),r.defineMIME(\"application/x-javascript\",\"javascript\"),r.defineMIME(\"application/ecmascript\",\"javascript\"),r.defineMIME(\"application/json\",{name:\"javascript\",json:!0}),r.defineMIME(\"application/x-json\",{name:\"javascript\",json:!0}),r.defineMIME(\"application/manifest+json\",{name:\"javascript\",json:!0}),r.defineMIME(\"application/ld+json\",{name:\"javascript\",jsonld:!0}),r.defineMIME(\"text/typescript\",{name:\"javascript\",typescript:!0}),r.defineMIME(\"application/typescript\",{name:\"javascript\",typescript:!0})})})()),yy.exports}xp();var wy={exports:{}},xy;function kp(){return xy||(xy=1,(function(e,t){(function(r){r(vo())})(function(r){var o={autoSelfClosers:{area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,frame:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0,menuitem:!0},implicitlyClosed:{dd:!0,li:!0,optgroup:!0,option:!0,p:!0,rp:!0,rt:!0,tbody:!0,td:!0,tfoot:!0,th:!0,tr:!0},contextGrabbers:{dd:{dd:!0,dt:!0},dt:{dd:!0,dt:!0},li:{li:!0},option:{option:!0,optgroup:!0},optgroup:{optgroup:!0},p:{address:!0,article:!0,aside:!0,blockquote:!0,dir:!0,div:!0,dl:!0,fieldset:!0,footer:!0,form:!0,h1:!0,h2:!0,h3:!0,h4:!0,h5:!0,h6:!0,header:!0,hgroup:!0,hr:!0,menu:!0,nav:!0,ol:!0,p:!0,pre:!0,section:!0,table:!0,ul:!0},rp:{rp:!0,rt:!0},rt:{rp:!0,rt:!0},tbody:{tbody:!0,tfoot:!0},td:{td:!0,th:!0},tfoot:{tbody:!0},th:{td:!0,th:!0},thead:{tbody:!0,tfoot:!0},tr:{tr:!0}},doNotIndent:{pre:!0},allowUnquoted:!0,allowMissing:!0,caseFold:!0},s={autoSelfClosers:{},implicitlyClosed:{},contextGrabbers:{},doNotIndent:{},allowUnquoted:!1,allowMissing:!1,allowMissingTagName:!1,caseFold:!1};r.defineMode(\"xml\",function(c,f){var d=c.indentUnit,h={},p=f.htmlMode?o:s;for(var g in p)h[g]=p[g];for(var g in f)h[g]=f[g];var v,b;function w(k,z){function B(Se){return z.tokenize=Se,Se(k,z)}var ce=k.next();if(ce==\"<\")return k.eat(\"!\")?k.eat(\"[\")?k.match(\"CDATA[\")?B(P(\"atom\",\"]]>\")):null:k.match(\"--\")?B(P(\"comment\",\"-->\")):k.match(\"DOCTYPE\",!0,!0)?(k.eatWhile(/[\\w\\._\\-]/),B(M(1))):null:k.eat(\"?\")?(k.eatWhile(/[\\w\\._\\-]/),z.tokenize=P(\"meta\",\"?>\"),\"meta\"):(v=k.eat(\"/\")?\"closeTag\":\"openTag\",z.tokenize=E,\"tag bracket\");if(ce==\"&\"){var be;return k.eat(\"#\")?k.eat(\"x\")?be=k.eatWhile(/[a-fA-F\\d]/)&&k.eat(\";\"):be=k.eatWhile(/[\\d]/)&&k.eat(\";\"):be=k.eatWhile(/[\\w\\.\\-:]/)&&k.eat(\";\"),be?\"atom\":\"error\"}else return k.eatWhile(/[^&<]/),null}w.isInText=!0;function E(k,z){var B=k.next();if(B==\">\"||B==\"/\"&&k.eat(\">\"))return z.tokenize=w,v=B==\">\"?\"endTag\":\"selfcloseTag\",\"tag bracket\";if(B==\"=\")return v=\"equals\",null;if(B==\"<\"){z.tokenize=w,z.state=W,z.tagName=z.tagStart=null;var ce=z.tokenize(k,z);return ce?ce+\" tag error\":\"tag error\"}else return/[\\'\\\"]/.test(B)?(z.tokenize=L(B),z.stringStartCol=k.column(),z.tokenize(k,z)):(k.match(/^[^\\s\\u00a0=<>\\\"\\']*[^\\s\\u00a0=<>\\\"\\'\\/]/),\"word\")}function L(k){var z=function(B,ce){for(;!B.eol();)if(B.next()==k){ce.tokenize=E;break}return\"string\"};return z.isInAttribute=!0,z}function P(k,z){return function(B,ce){for(;!B.eol();){if(B.match(z)){ce.tokenize=w;break}B.next()}return k}}function M(k){return function(z,B){for(var ce;(ce=z.next())!=null;){if(ce==\"<\")return B.tokenize=M(k+1),B.tokenize(z,B);if(ce==\">\")if(k==1){B.tokenize=w;break}else return B.tokenize=M(k-1),B.tokenize(z,B)}return\"meta\"}}function R(k){return k&&k.toLowerCase()}function I(k,z,B){this.prev=k.context,this.tagName=z||\"\",this.indent=k.indented,this.startOfLine=B,(h.doNotIndent.hasOwnProperty(z)||k.context&&k.context.noIndent)&&(this.noIndent=!0)}function _(k){k.context&&(k.context=k.context.prev)}function $(k,z){for(var B;;){if(!k.context||(B=k.context.tagName,!h.contextGrabbers.hasOwnProperty(R(B))||!h.contextGrabbers[R(B)].hasOwnProperty(R(z))))return;_(k)}}function W(k,z,B){return k==\"openTag\"?(B.tagStart=z.column(),ne):k==\"closeTag\"?ee:W}function ne(k,z,B){return k==\"word\"?(B.tagName=z.current(),b=\"tag\",j):h.allowMissingTagName&&k==\"endTag\"?(b=\"tag bracket\",j(k,z,B)):(b=\"error\",ne)}function ee(k,z,B){if(k==\"word\"){var ce=z.current();return B.context&&B.context.tagName!=ce&&h.implicitlyClosed.hasOwnProperty(R(B.context.tagName))&&_(B),B.context&&B.context.tagName==ce||h.matchClosing===!1?(b=\"tag\",Z):(b=\"tag error\",G)}else return h.allowMissingTagName&&k==\"endTag\"?(b=\"tag bracket\",Z(k,z,B)):(b=\"error\",G)}function Z(k,z,B){return k!=\"endTag\"?(b=\"error\",Z):(_(B),W)}function G(k,z,B){return b=\"error\",Z(k,z,B)}function j(k,z,B){if(k==\"word\")return b=\"attribute\",N;if(k==\"endTag\"||k==\"selfcloseTag\"){var ce=B.tagName,be=B.tagStart;return B.tagName=B.tagStart=null,k==\"selfcloseTag\"||h.autoSelfClosers.hasOwnProperty(R(ce))?$(B,ce):($(B,ce),B.context=new I(B,ce,be==B.indented)),W}return b=\"error\",j}function N(k,z,B){return k==\"equals\"?O:(h.allowMissing||(b=\"error\"),j(k,z,B))}function O(k,z,B){return k==\"string\"?C:k==\"word\"&&h.allowUnquoted?(b=\"string\",j):(b=\"error\",j(k,z,B))}function C(k,z,B){return k==\"string\"?C:j(k,z,B)}return{startState:function(k){var z={tokenize:w,state:W,indented:k||0,tagName:null,tagStart:null,context:null};return k!=null&&(z.baseIndent=k),z},token:function(k,z){if(!z.tagName&&k.sol()&&(z.indented=k.indentation()),k.eatSpace())return null;v=null;var B=z.tokenize(k,z);return(B||v)&&B!=\"comment\"&&(b=null,z.state=z.state(v||B,k,z),b&&(B=b==\"error\"?B+\" error\":b)),B},indent:function(k,z,B){var ce=k.context;if(k.tokenize.isInAttribute)return k.tagStart==k.indented?k.stringStartCol+1:k.indented+d;if(ce&&ce.noIndent)return r.Pass;if(k.tokenize!=E&&k.tokenize!=w)return B?B.match(/^(\\s*)/)[0].length:0;if(k.tagName)return h.multilineTagIndentPastTag!==!1?k.tagStart+k.tagName.length+2:k.tagStart+d*(h.multilineTagIndentFactor||1);if(h.alignCDATA&&/<!\\[CDATA\\[/.test(z))return 0;var be=z&&/^<(\\/)?([\\w_:\\.-]*)/.exec(z);if(be&&be[1])for(;ce;)if(ce.tagName==be[2]){ce=ce.prev;break}else if(h.implicitlyClosed.hasOwnProperty(R(ce.tagName)))ce=ce.prev;else break;else if(be)for(;ce;){var Se=h.contextGrabbers[R(ce.tagName)];if(Se&&Se.hasOwnProperty(R(be[2])))ce=ce.prev;else break}for(;ce&&ce.prev&&!ce.startOfLine;)ce=ce.prev;return ce?ce.indent+d:k.baseIndent||0},electricInput:/<\\/[\\s\\w:]+>$/,blockCommentStart:\"<!--\",blockCommentEnd:\"-->\",configuration:h.htmlMode?\"html\":\"xml\",helperType:h.htmlMode?\"html\":\"xml\",skipAttribute:function(k){k.state==O&&(k.state=j)},xmlCurrentTag:function(k){return k.tagName?{name:k.tagName,close:k.type==\"closeTag\"}:null},xmlCurrentContext:function(k){for(var z=[],B=k.context;B;B=B.prev)z.push(B.tagName);return z.reverse()}}}),r.defineMIME(\"text/xml\",\"xml\"),r.defineMIME(\"application/xml\",\"xml\"),r.mimeModes.hasOwnProperty(\"text/html\")||r.defineMIME(\"text/html\",{name:\"xml\",htmlMode:!0})})})()),wy.exports}kp();var ky={exports:{}},Sy={exports:{}},_y;function ace(){return _y||(_y=1,(function(e,t){(function(r){r(vo())})(function(r){r.defineMode(\"css\",function(G,j){var N=j.inline;j.propertyKeywords||(j=r.resolveMode(\"text/css\"));var O=G.indentUnit,C=j.tokenHooks,k=j.documentTypes||{},z=j.mediaTypes||{},B=j.mediaFeatures||{},ce=j.mediaValueKeywords||{},be=j.propertyKeywords||{},Se=j.nonStandardPropertyKeywords||{},Be=j.fontProperties||{},Ae=j.counterDescriptors||{},Ke=j.colorKeywords||{},je=j.valueKeywords||{},Fe=j.allowNested,Pe=j.lineComment,F=j.supportsAtComponent===!0,Y=G.highlightNonStandardPropertyKeywords!==!1,re,le;function ae(J,ue){return re=ue,J}function D(J,ue){var oe=J.next();if(C[oe]){var $e=C[oe](J,ue);if($e!==!1)return $e}if(oe==\"@\")return J.eatWhile(/[\\w\\\\\\-]/),ae(\"def\",J.current());if(oe==\"=\"||(oe==\"~\"||oe==\"|\")&&J.eat(\"=\"))return ae(null,\"compare\");if(oe=='\"'||oe==\"'\")return ue.tokenize=q(oe),ue.tokenize(J,ue);if(oe==\"#\")return J.eatWhile(/[\\w\\\\\\-]/),ae(\"atom\",\"hash\");if(oe==\"!\")return J.match(/^\\s*\\w*/),ae(\"keyword\",\"important\");if(/\\d/.test(oe)||oe==\".\"&&J.eat(/\\d/))return J.eatWhile(/[\\w.%]/),ae(\"number\",\"unit\");if(oe===\"-\"){if(/[\\d.]/.test(J.peek()))return J.eatWhile(/[\\w.%]/),ae(\"number\",\"unit\");if(J.match(/^-[\\w\\\\\\-]*/))return J.eatWhile(/[\\w\\\\\\-]/),J.match(/^\\s*:/,!1)?ae(\"variable-2\",\"variable-definition\"):ae(\"variable-2\",\"variable\");if(J.match(/^\\w+-/))return ae(\"meta\",\"meta\")}else return/[,+>*\\/]/.test(oe)?ae(null,\"select-op\"):oe==\".\"&&J.match(/^-?[_a-z][_a-z0-9-]*/i)?ae(\"qualifier\",\"qualifier\"):/[:;{}\\[\\]\\(\\)]/.test(oe)?ae(null,oe):J.match(/^[\\w-.]+(?=\\()/)?(/^(url(-prefix)?|domain|regexp)$/i.test(J.current())&&(ue.tokenize=Q),ae(\"variable callee\",\"variable\")):/[\\w\\\\\\-]/.test(oe)?(J.eatWhile(/[\\w\\\\\\-]/),ae(\"property\",\"word\")):ae(null,null)}function q(J){return function(ue,oe){for(var $e=!1,Je;(Je=ue.next())!=null;){if(Je==J&&!$e){J==\")\"&&ue.backUp(1);break}$e=!$e&&Je==\"\\\\\"}return(Je==J||!$e&&J!=\")\")&&(oe.tokenize=null),ae(\"string\",\"string\")}}function Q(J,ue){return J.next(),J.match(/^\\s*[\\\"\\')]/,!1)?ue.tokenize=null:ue.tokenize=q(\")\"),ae(null,\"(\")}function he(J,ue,oe){this.type=J,this.indent=ue,this.prev=oe}function de(J,ue,oe,$e){return J.context=new he(oe,ue.indentation()+($e===!1?0:O),J.context),oe}function ge(J){return J.context.prev&&(J.context=J.context.prev),J.context.type}function Ce(J,ue,oe){return ye[oe.context.type](J,ue,oe)}function Ee(J,ue,oe,$e){for(var Je=$e||1;Je>0;Je--)oe.context=oe.context.prev;return Ce(J,ue,oe)}function xe(J){var ue=J.current().toLowerCase();je.hasOwnProperty(ue)?le=\"atom\":Ke.hasOwnProperty(ue)?le=\"keyword\":le=\"variable\"}var ye={};return ye.top=function(J,ue,oe){if(J==\"{\")return de(oe,ue,\"block\");if(J==\"}\"&&oe.context.prev)return ge(oe);if(F&&/@component/i.test(J))return de(oe,ue,\"atComponentBlock\");if(/^@(-moz-)?document$/i.test(J))return de(oe,ue,\"documentTypes\");if(/^@(media|supports|(-moz-)?document|import)$/i.test(J))return de(oe,ue,\"atBlock\");if(/^@(font-face|counter-style)/i.test(J))return oe.stateArg=J,\"restricted_atBlock_before\";if(/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(J))return\"keyframes\";if(J&&J.charAt(0)==\"@\")return de(oe,ue,\"at\");if(J==\"hash\")le=\"builtin\";else if(J==\"word\")le=\"tag\";else{if(J==\"variable-definition\")return\"maybeprop\";if(J==\"interpolation\")return de(oe,ue,\"interpolation\");if(J==\":\")return\"pseudo\";if(Fe&&J==\"(\")return de(oe,ue,\"parens\")}return oe.context.type},ye.block=function(J,ue,oe){if(J==\"word\"){var $e=ue.current().toLowerCase();return be.hasOwnProperty($e)?(le=\"property\",\"maybeprop\"):Se.hasOwnProperty($e)?(le=Y?\"string-2\":\"property\",\"maybeprop\"):Fe?(le=ue.match(/^\\s*:(?:\\s|$)/,!1)?\"property\":\"tag\",\"block\"):(le+=\" error\",\"maybeprop\")}else return J==\"meta\"?\"block\":!Fe&&(J==\"hash\"||J==\"qualifier\")?(le=\"error\",\"block\"):ye.top(J,ue,oe)},ye.maybeprop=function(J,ue,oe){return J==\":\"?de(oe,ue,\"prop\"):Ce(J,ue,oe)},ye.prop=function(J,ue,oe){if(J==\";\")return ge(oe);if(J==\"{\"&&Fe)return de(oe,ue,\"propBlock\");if(J==\"}\"||J==\"{\")return Ee(J,ue,oe);if(J==\"(\")return de(oe,ue,\"parens\");if(J==\"hash\"&&!/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(ue.current()))le+=\" error\";else if(J==\"word\")xe(ue);else if(J==\"interpolation\")return de(oe,ue,\"interpolation\");return\"prop\"},ye.propBlock=function(J,ue,oe){return J==\"}\"?ge(oe):J==\"word\"?(le=\"property\",\"maybeprop\"):oe.context.type},ye.parens=function(J,ue,oe){return J==\"{\"||J==\"}\"?Ee(J,ue,oe):J==\")\"?ge(oe):J==\"(\"?de(oe,ue,\"parens\"):J==\"interpolation\"?de(oe,ue,\"interpolation\"):(J==\"word\"&&xe(ue),\"parens\")},ye.pseudo=function(J,ue,oe){return J==\"meta\"?\"pseudo\":J==\"word\"?(le=\"variable-3\",oe.context.type):Ce(J,ue,oe)},ye.documentTypes=function(J,ue,oe){return J==\"word\"&&k.hasOwnProperty(ue.current())?(le=\"tag\",oe.context.type):ye.atBlock(J,ue,oe)},ye.atBlock=function(J,ue,oe){if(J==\"(\")return de(oe,ue,\"atBlock_parens\");if(J==\"}\"||J==\";\")return Ee(J,ue,oe);if(J==\"{\")return ge(oe)&&de(oe,ue,Fe?\"block\":\"top\");if(J==\"interpolation\")return de(oe,ue,\"interpolation\");if(J==\"word\"){var $e=ue.current().toLowerCase();$e==\"only\"||$e==\"not\"||$e==\"and\"||$e==\"or\"?le=\"keyword\":z.hasOwnProperty($e)?le=\"attribute\":B.hasOwnProperty($e)?le=\"property\":ce.hasOwnProperty($e)?le=\"keyword\":be.hasOwnProperty($e)?le=\"property\":Se.hasOwnProperty($e)?le=Y?\"string-2\":\"property\":je.hasOwnProperty($e)?le=\"atom\":Ke.hasOwnProperty($e)?le=\"keyword\":le=\"error\"}return oe.context.type},ye.atComponentBlock=function(J,ue,oe){return J==\"}\"?Ee(J,ue,oe):J==\"{\"?ge(oe)&&de(oe,ue,Fe?\"block\":\"top\",!1):(J==\"word\"&&(le=\"error\"),oe.context.type)},ye.atBlock_parens=function(J,ue,oe){return J==\")\"?ge(oe):J==\"{\"||J==\"}\"?Ee(J,ue,oe,2):ye.atBlock(J,ue,oe)},ye.restricted_atBlock_before=function(J,ue,oe){return J==\"{\"?de(oe,ue,\"restricted_atBlock\"):J==\"word\"&&oe.stateArg==\"@counter-style\"?(le=\"variable\",\"restricted_atBlock_before\"):Ce(J,ue,oe)},ye.restricted_atBlock=function(J,ue,oe){return J==\"}\"?(oe.stateArg=null,ge(oe)):J==\"word\"?(oe.stateArg==\"@font-face\"&&!Be.hasOwnProperty(ue.current().toLowerCase())||oe.stateArg==\"@counter-style\"&&!Ae.hasOwnProperty(ue.current().toLowerCase())?le=\"error\":le=\"property\",\"maybeprop\"):\"restricted_atBlock\"},ye.keyframes=function(J,ue,oe){return J==\"word\"?(le=\"variable\",\"keyframes\"):J==\"{\"?de(oe,ue,\"top\"):Ce(J,ue,oe)},ye.at=function(J,ue,oe){return J==\";\"?ge(oe):J==\"{\"||J==\"}\"?Ee(J,ue,oe):(J==\"word\"?le=\"tag\":J==\"hash\"&&(le=\"builtin\"),\"at\")},ye.interpolation=function(J,ue,oe){return J==\"}\"?ge(oe):J==\"{\"||J==\";\"?Ee(J,ue,oe):(J==\"word\"?le=\"variable\":J!=\"variable\"&&J!=\"(\"&&J!=\")\"&&(le=\"error\"),\"interpolation\")},{startState:function(J){return{tokenize:null,state:N?\"block\":\"top\",stateArg:null,context:new he(N?\"block\":\"top\",J||0,null)}},token:function(J,ue){if(!ue.tokenize&&J.eatSpace())return null;var oe=(ue.tokenize||D)(J,ue);return oe&&typeof oe==\"object\"&&(re=oe[1],oe=oe[0]),le=oe,re!=\"comment\"&&(ue.state=ye[ue.state](re,J,ue)),le},indent:function(J,ue){var oe=J.context,$e=ue&&ue.charAt(0),Je=oe.indent;return oe.type==\"prop\"&&($e==\"}\"||$e==\")\")&&(oe=oe.prev),oe.prev&&($e==\"}\"&&(oe.type==\"block\"||oe.type==\"top\"||oe.type==\"interpolation\"||oe.type==\"restricted_atBlock\")?(oe=oe.prev,Je=oe.indent):($e==\")\"&&(oe.type==\"parens\"||oe.type==\"atBlock_parens\")||$e==\"{\"&&(oe.type==\"at\"||oe.type==\"atBlock\"))&&(Je=Math.max(0,oe.indent-O))),Je},electricChars:\"}\",blockCommentStart:\"/*\",blockCommentEnd:\"*/\",blockCommentContinue:\" * \",lineComment:Pe,fold:\"brace\"}});function o(G){for(var j={},N=0;N<G.length;++N)j[G[N].toLowerCase()]=!0;return j}var s=[\"domain\",\"regexp\",\"url\",\"url-prefix\"],c=o(s),f=[\"all\",\"aural\",\"braille\",\"handheld\",\"print\",\"projection\",\"screen\",\"tty\",\"tv\",\"embossed\"],d=o(f),h=[\"width\",\"min-width\",\"max-width\",\"height\",\"min-height\",\"max-height\",\"device-width\",\"min-device-width\",\"max-device-width\",\"device-height\",\"min-device-height\",\"max-device-height\",\"aspect-ratio\",\"min-aspect-ratio\",\"max-aspect-ratio\",\"device-aspect-ratio\",\"min-device-aspect-ratio\",\"max-device-aspect-ratio\",\"color\",\"min-color\",\"max-color\",\"color-index\",\"min-color-index\",\"max-color-index\",\"monochrome\",\"min-monochrome\",\"max-monochrome\",\"resolution\",\"min-resolution\",\"max-resolution\",\"scan\",\"grid\",\"orientation\",\"device-pixel-ratio\",\"min-device-pixel-ratio\",\"max-device-pixel-ratio\",\"pointer\",\"any-pointer\",\"hover\",\"any-hover\",\"prefers-color-scheme\",\"dynamic-range\",\"video-dynamic-range\"],p=o(h),g=[\"landscape\",\"portrait\",\"none\",\"coarse\",\"fine\",\"on-demand\",\"hover\",\"interlace\",\"progressive\",\"dark\",\"light\",\"standard\",\"high\"],v=o(g),b=[\"align-content\",\"align-items\",\"align-self\",\"alignment-adjust\",\"alignment-baseline\",\"all\",\"anchor-point\",\"animation\",\"animation-delay\",\"animation-direction\",\"animation-duration\",\"animation-fill-mode\",\"animation-iteration-count\",\"animation-name\",\"animation-play-state\",\"animation-timing-function\",\"appearance\",\"azimuth\",\"backdrop-filter\",\"backface-visibility\",\"background\",\"background-attachment\",\"background-blend-mode\",\"background-clip\",\"background-color\",\"background-image\",\"background-origin\",\"background-position\",\"background-position-x\",\"background-position-y\",\"background-repeat\",\"background-size\",\"baseline-shift\",\"binding\",\"bleed\",\"block-size\",\"bookmark-label\",\"bookmark-level\",\"bookmark-state\",\"bookmark-target\",\"border\",\"border-bottom\",\"border-bottom-color\",\"border-bottom-left-radius\",\"border-bottom-right-radius\",\"border-bottom-style\",\"border-bottom-width\",\"border-collapse\",\"border-color\",\"border-image\",\"border-image-outset\",\"border-image-repeat\",\"border-image-slice\",\"border-image-source\",\"border-image-width\",\"border-left\",\"border-left-color\",\"border-left-style\",\"border-left-width\",\"border-radius\",\"border-right\",\"border-right-color\",\"border-right-style\",\"border-right-width\",\"border-spacing\",\"border-style\",\"border-top\",\"border-top-color\",\"border-top-left-radius\",\"border-top-right-radius\",\"border-top-style\",\"border-top-width\",\"border-width\",\"bottom\",\"box-decoration-break\",\"box-shadow\",\"box-sizing\",\"break-after\",\"break-before\",\"break-inside\",\"caption-side\",\"caret-color\",\"clear\",\"clip\",\"color\",\"color-profile\",\"column-count\",\"column-fill\",\"column-gap\",\"column-rule\",\"column-rule-color\",\"column-rule-style\",\"column-rule-width\",\"column-span\",\"column-width\",\"columns\",\"contain\",\"content\",\"counter-increment\",\"counter-reset\",\"crop\",\"cue\",\"cue-after\",\"cue-before\",\"cursor\",\"direction\",\"display\",\"dominant-baseline\",\"drop-initial-after-adjust\",\"drop-initial-after-align\",\"drop-initial-before-adjust\",\"drop-initial-before-align\",\"drop-initial-size\",\"drop-initial-value\",\"elevation\",\"empty-cells\",\"fit\",\"fit-content\",\"fit-position\",\"flex\",\"flex-basis\",\"flex-direction\",\"flex-flow\",\"flex-grow\",\"flex-shrink\",\"flex-wrap\",\"float\",\"float-offset\",\"flow-from\",\"flow-into\",\"font\",\"font-family\",\"font-feature-settings\",\"font-kerning\",\"font-language-override\",\"font-optical-sizing\",\"font-size\",\"font-size-adjust\",\"font-stretch\",\"font-style\",\"font-synthesis\",\"font-variant\",\"font-variant-alternates\",\"font-variant-caps\",\"font-variant-east-asian\",\"font-variant-ligatures\",\"font-variant-numeric\",\"font-variant-position\",\"font-variation-settings\",\"font-weight\",\"gap\",\"grid\",\"grid-area\",\"grid-auto-columns\",\"grid-auto-flow\",\"grid-auto-rows\",\"grid-column\",\"grid-column-end\",\"grid-column-gap\",\"grid-column-start\",\"grid-gap\",\"grid-row\",\"grid-row-end\",\"grid-row-gap\",\"grid-row-start\",\"grid-template\",\"grid-template-areas\",\"grid-template-columns\",\"grid-template-rows\",\"hanging-punctuation\",\"height\",\"hyphens\",\"icon\",\"image-orientation\",\"image-rendering\",\"image-resolution\",\"inline-box-align\",\"inset\",\"inset-block\",\"inset-block-end\",\"inset-block-start\",\"inset-inline\",\"inset-inline-end\",\"inset-inline-start\",\"isolation\",\"justify-content\",\"justify-items\",\"justify-self\",\"left\",\"letter-spacing\",\"line-break\",\"line-height\",\"line-height-step\",\"line-stacking\",\"line-stacking-ruby\",\"line-stacking-shift\",\"line-stacking-strategy\",\"list-style\",\"list-style-image\",\"list-style-position\",\"list-style-type\",\"margin\",\"margin-bottom\",\"margin-left\",\"margin-right\",\"margin-top\",\"marks\",\"marquee-direction\",\"marquee-loop\",\"marquee-play-count\",\"marquee-speed\",\"marquee-style\",\"mask-clip\",\"mask-composite\",\"mask-image\",\"mask-mode\",\"mask-origin\",\"mask-position\",\"mask-repeat\",\"mask-size\",\"mask-type\",\"max-block-size\",\"max-height\",\"max-inline-size\",\"max-width\",\"min-block-size\",\"min-height\",\"min-inline-size\",\"min-width\",\"mix-blend-mode\",\"move-to\",\"nav-down\",\"nav-index\",\"nav-left\",\"nav-right\",\"nav-up\",\"object-fit\",\"object-position\",\"offset\",\"offset-anchor\",\"offset-distance\",\"offset-path\",\"offset-position\",\"offset-rotate\",\"opacity\",\"order\",\"orphans\",\"outline\",\"outline-color\",\"outline-offset\",\"outline-style\",\"outline-width\",\"overflow\",\"overflow-style\",\"overflow-wrap\",\"overflow-x\",\"overflow-y\",\"padding\",\"padding-bottom\",\"padding-left\",\"padding-right\",\"padding-top\",\"page\",\"page-break-after\",\"page-break-before\",\"page-break-inside\",\"page-policy\",\"pause\",\"pause-after\",\"pause-before\",\"perspective\",\"perspective-origin\",\"pitch\",\"pitch-range\",\"place-content\",\"place-items\",\"place-self\",\"play-during\",\"position\",\"presentation-level\",\"punctuation-trim\",\"quotes\",\"region-break-after\",\"region-break-before\",\"region-break-inside\",\"region-fragment\",\"rendering-intent\",\"resize\",\"rest\",\"rest-after\",\"rest-before\",\"richness\",\"right\",\"rotate\",\"rotation\",\"rotation-point\",\"row-gap\",\"ruby-align\",\"ruby-overhang\",\"ruby-position\",\"ruby-span\",\"scale\",\"scroll-behavior\",\"scroll-margin\",\"scroll-margin-block\",\"scroll-margin-block-end\",\"scroll-margin-block-start\",\"scroll-margin-bottom\",\"scroll-margin-inline\",\"scroll-margin-inline-end\",\"scroll-margin-inline-start\",\"scroll-margin-left\",\"scroll-margin-right\",\"scroll-margin-top\",\"scroll-padding\",\"scroll-padding-block\",\"scroll-padding-block-end\",\"scroll-padding-block-start\",\"scroll-padding-bottom\",\"scroll-padding-inline\",\"scroll-padding-inline-end\",\"scroll-padding-inline-start\",\"scroll-padding-left\",\"scroll-padding-right\",\"scroll-padding-top\",\"scroll-snap-align\",\"scroll-snap-type\",\"shape-image-threshold\",\"shape-inside\",\"shape-margin\",\"shape-outside\",\"size\",\"speak\",\"speak-as\",\"speak-header\",\"speak-numeral\",\"speak-punctuation\",\"speech-rate\",\"stress\",\"string-set\",\"tab-size\",\"table-layout\",\"target\",\"target-name\",\"target-new\",\"target-position\",\"text-align\",\"text-align-last\",\"text-combine-upright\",\"text-decoration\",\"text-decoration-color\",\"text-decoration-line\",\"text-decoration-skip\",\"text-decoration-skip-ink\",\"text-decoration-style\",\"text-emphasis\",\"text-emphasis-color\",\"text-emphasis-position\",\"text-emphasis-style\",\"text-height\",\"text-indent\",\"text-justify\",\"text-orientation\",\"text-outline\",\"text-overflow\",\"text-rendering\",\"text-shadow\",\"text-size-adjust\",\"text-space-collapse\",\"text-transform\",\"text-underline-position\",\"text-wrap\",\"top\",\"touch-action\",\"transform\",\"transform-origin\",\"transform-style\",\"transition\",\"transition-delay\",\"transition-duration\",\"transition-property\",\"transition-timing-function\",\"translate\",\"unicode-bidi\",\"user-select\",\"vertical-align\",\"visibility\",\"voice-balance\",\"voice-duration\",\"voice-family\",\"voice-pitch\",\"voice-range\",\"voice-rate\",\"voice-stress\",\"voice-volume\",\"volume\",\"white-space\",\"widows\",\"width\",\"will-change\",\"word-break\",\"word-spacing\",\"word-wrap\",\"writing-mode\",\"z-index\",\"clip-path\",\"clip-rule\",\"mask\",\"enable-background\",\"filter\",\"flood-color\",\"flood-opacity\",\"lighting-color\",\"stop-color\",\"stop-opacity\",\"pointer-events\",\"color-interpolation\",\"color-interpolation-filters\",\"color-rendering\",\"fill\",\"fill-opacity\",\"fill-rule\",\"image-rendering\",\"marker\",\"marker-end\",\"marker-mid\",\"marker-start\",\"paint-order\",\"shape-rendering\",\"stroke\",\"stroke-dasharray\",\"stroke-dashoffset\",\"stroke-linecap\",\"stroke-linejoin\",\"stroke-miterlimit\",\"stroke-opacity\",\"stroke-width\",\"text-rendering\",\"baseline-shift\",\"dominant-baseline\",\"glyph-orientation-horizontal\",\"glyph-orientation-vertical\",\"text-anchor\",\"writing-mode\"],w=o(b),E=[\"accent-color\",\"aspect-ratio\",\"border-block\",\"border-block-color\",\"border-block-end\",\"border-block-end-color\",\"border-block-end-style\",\"border-block-end-width\",\"border-block-start\",\"border-block-start-color\",\"border-block-start-style\",\"border-block-start-width\",\"border-block-style\",\"border-block-width\",\"border-inline\",\"border-inline-color\",\"border-inline-end\",\"border-inline-end-color\",\"border-inline-end-style\",\"border-inline-end-width\",\"border-inline-start\",\"border-inline-start-color\",\"border-inline-start-style\",\"border-inline-start-width\",\"border-inline-style\",\"border-inline-width\",\"content-visibility\",\"margin-block\",\"margin-block-end\",\"margin-block-start\",\"margin-inline\",\"margin-inline-end\",\"margin-inline-start\",\"overflow-anchor\",\"overscroll-behavior\",\"padding-block\",\"padding-block-end\",\"padding-block-start\",\"padding-inline\",\"padding-inline-end\",\"padding-inline-start\",\"scroll-snap-stop\",\"scrollbar-3d-light-color\",\"scrollbar-arrow-color\",\"scrollbar-base-color\",\"scrollbar-dark-shadow-color\",\"scrollbar-face-color\",\"scrollbar-highlight-color\",\"scrollbar-shadow-color\",\"scrollbar-track-color\",\"searchfield-cancel-button\",\"searchfield-decoration\",\"searchfield-results-button\",\"searchfield-results-decoration\",\"shape-inside\",\"zoom\"],L=o(E),P=[\"font-display\",\"font-family\",\"src\",\"unicode-range\",\"font-variant\",\"font-feature-settings\",\"font-stretch\",\"font-weight\",\"font-style\"],M=o(P),R=[\"additive-symbols\",\"fallback\",\"negative\",\"pad\",\"prefix\",\"range\",\"speak-as\",\"suffix\",\"symbols\",\"system\"],I=o(R),_=[\"aliceblue\",\"antiquewhite\",\"aqua\",\"aquamarine\",\"azure\",\"beige\",\"bisque\",\"black\",\"blanchedalmond\",\"blue\",\"blueviolet\",\"brown\",\"burlywood\",\"cadetblue\",\"chartreuse\",\"chocolate\",\"coral\",\"cornflowerblue\",\"cornsilk\",\"crimson\",\"cyan\",\"darkblue\",\"darkcyan\",\"darkgoldenrod\",\"darkgray\",\"darkgreen\",\"darkgrey\",\"darkkhaki\",\"darkmagenta\",\"darkolivegreen\",\"darkorange\",\"darkorchid\",\"darkred\",\"darksalmon\",\"darkseagreen\",\"darkslateblue\",\"darkslategray\",\"darkslategrey\",\"darkturquoise\",\"darkviolet\",\"deeppink\",\"deepskyblue\",\"dimgray\",\"dimgrey\",\"dodgerblue\",\"firebrick\",\"floralwhite\",\"forestgreen\",\"fuchsia\",\"gainsboro\",\"ghostwhite\",\"gold\",\"goldenrod\",\"gray\",\"grey\",\"green\",\"greenyellow\",\"honeydew\",\"hotpink\",\"indianred\",\"indigo\",\"ivory\",\"khaki\",\"lavender\",\"lavenderblush\",\"lawngreen\",\"lemonchiffon\",\"lightblue\",\"lightcoral\",\"lightcyan\",\"lightgoldenrodyellow\",\"lightgray\",\"lightgreen\",\"lightgrey\",\"lightpink\",\"lightsalmon\",\"lightseagreen\",\"lightskyblue\",\"lightslategray\",\"lightslategrey\",\"lightsteelblue\",\"lightyellow\",\"lime\",\"limegreen\",\"linen\",\"magenta\",\"maroon\",\"mediumaquamarine\",\"mediumblue\",\"mediumorchid\",\"mediumpurple\",\"mediumseagreen\",\"mediumslateblue\",\"mediumspringgreen\",\"mediumturquoise\",\"mediumvioletred\",\"midnightblue\",\"mintcream\",\"mistyrose\",\"moccasin\",\"navajowhite\",\"navy\",\"oldlace\",\"olive\",\"olivedrab\",\"orange\",\"orangered\",\"orchid\",\"palegoldenrod\",\"palegreen\",\"paleturquoise\",\"palevioletred\",\"papayawhip\",\"peachpuff\",\"peru\",\"pink\",\"plum\",\"powderblue\",\"purple\",\"rebeccapurple\",\"red\",\"rosybrown\",\"royalblue\",\"saddlebrown\",\"salmon\",\"sandybrown\",\"seagreen\",\"seashell\",\"sienna\",\"silver\",\"skyblue\",\"slateblue\",\"slategray\",\"slategrey\",\"snow\",\"springgreen\",\"steelblue\",\"tan\",\"teal\",\"thistle\",\"tomato\",\"turquoise\",\"violet\",\"wheat\",\"white\",\"whitesmoke\",\"yellow\",\"yellowgreen\"],$=o(_),W=[\"above\",\"absolute\",\"activeborder\",\"additive\",\"activecaption\",\"afar\",\"after-white-space\",\"ahead\",\"alias\",\"all\",\"all-scroll\",\"alphabetic\",\"alternate\",\"always\",\"amharic\",\"amharic-abegede\",\"antialiased\",\"appworkspace\",\"arabic-indic\",\"armenian\",\"asterisks\",\"attr\",\"auto\",\"auto-flow\",\"avoid\",\"avoid-column\",\"avoid-page\",\"avoid-region\",\"axis-pan\",\"background\",\"backwards\",\"baseline\",\"below\",\"bidi-override\",\"binary\",\"bengali\",\"blink\",\"block\",\"block-axis\",\"blur\",\"bold\",\"bolder\",\"border\",\"border-box\",\"both\",\"bottom\",\"break\",\"break-all\",\"break-word\",\"brightness\",\"bullets\",\"button\",\"buttonface\",\"buttonhighlight\",\"buttonshadow\",\"buttontext\",\"calc\",\"cambodian\",\"capitalize\",\"caps-lock-indicator\",\"caption\",\"captiontext\",\"caret\",\"cell\",\"center\",\"checkbox\",\"circle\",\"cjk-decimal\",\"cjk-earthly-branch\",\"cjk-heavenly-stem\",\"cjk-ideographic\",\"clear\",\"clip\",\"close-quote\",\"col-resize\",\"collapse\",\"color\",\"color-burn\",\"color-dodge\",\"column\",\"column-reverse\",\"compact\",\"condensed\",\"conic-gradient\",\"contain\",\"content\",\"contents\",\"content-box\",\"context-menu\",\"continuous\",\"contrast\",\"copy\",\"counter\",\"counters\",\"cover\",\"crop\",\"cross\",\"crosshair\",\"cubic-bezier\",\"currentcolor\",\"cursive\",\"cyclic\",\"darken\",\"dashed\",\"decimal\",\"decimal-leading-zero\",\"default\",\"default-button\",\"dense\",\"destination-atop\",\"destination-in\",\"destination-out\",\"destination-over\",\"devanagari\",\"difference\",\"disc\",\"discard\",\"disclosure-closed\",\"disclosure-open\",\"document\",\"dot-dash\",\"dot-dot-dash\",\"dotted\",\"double\",\"down\",\"drop-shadow\",\"e-resize\",\"ease\",\"ease-in\",\"ease-in-out\",\"ease-out\",\"element\",\"ellipse\",\"ellipsis\",\"embed\",\"end\",\"ethiopic\",\"ethiopic-abegede\",\"ethiopic-abegede-am-et\",\"ethiopic-abegede-gez\",\"ethiopic-abegede-ti-er\",\"ethiopic-abegede-ti-et\",\"ethiopic-halehame-aa-er\",\"ethiopic-halehame-aa-et\",\"ethiopic-halehame-am-et\",\"ethiopic-halehame-gez\",\"ethiopic-halehame-om-et\",\"ethiopic-halehame-sid-et\",\"ethiopic-halehame-so-et\",\"ethiopic-halehame-ti-er\",\"ethiopic-halehame-ti-et\",\"ethiopic-halehame-tig\",\"ethiopic-numeric\",\"ew-resize\",\"exclusion\",\"expanded\",\"extends\",\"extra-condensed\",\"extra-expanded\",\"fantasy\",\"fast\",\"fill\",\"fill-box\",\"fixed\",\"flat\",\"flex\",\"flex-end\",\"flex-start\",\"footnotes\",\"forwards\",\"from\",\"geometricPrecision\",\"georgian\",\"grayscale\",\"graytext\",\"grid\",\"groove\",\"gujarati\",\"gurmukhi\",\"hand\",\"hangul\",\"hangul-consonant\",\"hard-light\",\"hebrew\",\"help\",\"hidden\",\"hide\",\"higher\",\"highlight\",\"highlighttext\",\"hiragana\",\"hiragana-iroha\",\"horizontal\",\"hsl\",\"hsla\",\"hue\",\"hue-rotate\",\"icon\",\"ignore\",\"inactiveborder\",\"inactivecaption\",\"inactivecaptiontext\",\"infinite\",\"infobackground\",\"infotext\",\"inherit\",\"initial\",\"inline\",\"inline-axis\",\"inline-block\",\"inline-flex\",\"inline-grid\",\"inline-table\",\"inset\",\"inside\",\"intrinsic\",\"invert\",\"italic\",\"japanese-formal\",\"japanese-informal\",\"justify\",\"kannada\",\"katakana\",\"katakana-iroha\",\"keep-all\",\"khmer\",\"korean-hangul-formal\",\"korean-hanja-formal\",\"korean-hanja-informal\",\"landscape\",\"lao\",\"large\",\"larger\",\"left\",\"level\",\"lighter\",\"lighten\",\"line-through\",\"linear\",\"linear-gradient\",\"lines\",\"list-item\",\"listbox\",\"listitem\",\"local\",\"logical\",\"loud\",\"lower\",\"lower-alpha\",\"lower-armenian\",\"lower-greek\",\"lower-hexadecimal\",\"lower-latin\",\"lower-norwegian\",\"lower-roman\",\"lowercase\",\"ltr\",\"luminosity\",\"malayalam\",\"manipulation\",\"match\",\"matrix\",\"matrix3d\",\"media-play-button\",\"media-slider\",\"media-sliderthumb\",\"media-volume-slider\",\"media-volume-sliderthumb\",\"medium\",\"menu\",\"menulist\",\"menulist-button\",\"menutext\",\"message-box\",\"middle\",\"min-intrinsic\",\"mix\",\"mongolian\",\"monospace\",\"move\",\"multiple\",\"multiple_mask_images\",\"multiply\",\"myanmar\",\"n-resize\",\"narrower\",\"ne-resize\",\"nesw-resize\",\"no-close-quote\",\"no-drop\",\"no-open-quote\",\"no-repeat\",\"none\",\"normal\",\"not-allowed\",\"nowrap\",\"ns-resize\",\"numbers\",\"numeric\",\"nw-resize\",\"nwse-resize\",\"oblique\",\"octal\",\"opacity\",\"open-quote\",\"optimizeLegibility\",\"optimizeSpeed\",\"oriya\",\"oromo\",\"outset\",\"outside\",\"outside-shape\",\"overlay\",\"overline\",\"padding\",\"padding-box\",\"painted\",\"page\",\"paused\",\"persian\",\"perspective\",\"pinch-zoom\",\"plus-darker\",\"plus-lighter\",\"pointer\",\"polygon\",\"portrait\",\"pre\",\"pre-line\",\"pre-wrap\",\"preserve-3d\",\"progress\",\"push-button\",\"radial-gradient\",\"radio\",\"read-only\",\"read-write\",\"read-write-plaintext-only\",\"rectangle\",\"region\",\"relative\",\"repeat\",\"repeating-linear-gradient\",\"repeating-radial-gradient\",\"repeating-conic-gradient\",\"repeat-x\",\"repeat-y\",\"reset\",\"reverse\",\"rgb\",\"rgba\",\"ridge\",\"right\",\"rotate\",\"rotate3d\",\"rotateX\",\"rotateY\",\"rotateZ\",\"round\",\"row\",\"row-resize\",\"row-reverse\",\"rtl\",\"run-in\",\"running\",\"s-resize\",\"sans-serif\",\"saturate\",\"saturation\",\"scale\",\"scale3d\",\"scaleX\",\"scaleY\",\"scaleZ\",\"screen\",\"scroll\",\"scrollbar\",\"scroll-position\",\"se-resize\",\"searchfield\",\"searchfield-cancel-button\",\"searchfield-decoration\",\"searchfield-results-button\",\"searchfield-results-decoration\",\"self-start\",\"self-end\",\"semi-condensed\",\"semi-expanded\",\"separate\",\"sepia\",\"serif\",\"show\",\"sidama\",\"simp-chinese-formal\",\"simp-chinese-informal\",\"single\",\"skew\",\"skewX\",\"skewY\",\"skip-white-space\",\"slide\",\"slider-horizontal\",\"slider-vertical\",\"sliderthumb-horizontal\",\"sliderthumb-vertical\",\"slow\",\"small\",\"small-caps\",\"small-caption\",\"smaller\",\"soft-light\",\"solid\",\"somali\",\"source-atop\",\"source-in\",\"source-out\",\"source-over\",\"space\",\"space-around\",\"space-between\",\"space-evenly\",\"spell-out\",\"square\",\"square-button\",\"start\",\"static\",\"status-bar\",\"stretch\",\"stroke\",\"stroke-box\",\"sub\",\"subpixel-antialiased\",\"svg_masks\",\"super\",\"sw-resize\",\"symbolic\",\"symbols\",\"system-ui\",\"table\",\"table-caption\",\"table-cell\",\"table-column\",\"table-column-group\",\"table-footer-group\",\"table-header-group\",\"table-row\",\"table-row-group\",\"tamil\",\"telugu\",\"text\",\"text-bottom\",\"text-top\",\"textarea\",\"textfield\",\"thai\",\"thick\",\"thin\",\"threeddarkshadow\",\"threedface\",\"threedhighlight\",\"threedlightshadow\",\"threedshadow\",\"tibetan\",\"tigre\",\"tigrinya-er\",\"tigrinya-er-abegede\",\"tigrinya-et\",\"tigrinya-et-abegede\",\"to\",\"top\",\"trad-chinese-formal\",\"trad-chinese-informal\",\"transform\",\"translate\",\"translate3d\",\"translateX\",\"translateY\",\"translateZ\",\"transparent\",\"ultra-condensed\",\"ultra-expanded\",\"underline\",\"unidirectional-pan\",\"unset\",\"up\",\"upper-alpha\",\"upper-armenian\",\"upper-greek\",\"upper-hexadecimal\",\"upper-latin\",\"upper-norwegian\",\"upper-roman\",\"uppercase\",\"urdu\",\"url\",\"var\",\"vertical\",\"vertical-text\",\"view-box\",\"visible\",\"visibleFill\",\"visiblePainted\",\"visibleStroke\",\"visual\",\"w-resize\",\"wait\",\"wave\",\"wider\",\"window\",\"windowframe\",\"windowtext\",\"words\",\"wrap\",\"wrap-reverse\",\"x-large\",\"x-small\",\"xor\",\"xx-large\",\"xx-small\"],ne=o(W),ee=s.concat(f).concat(h).concat(g).concat(b).concat(E).concat(_).concat(W);r.registerHelper(\"hintWords\",\"css\",ee);function Z(G,j){for(var N=!1,O;(O=G.next())!=null;){if(N&&O==\"/\"){j.tokenize=null;break}N=O==\"*\"}return[\"comment\",\"comment\"]}r.defineMIME(\"text/css\",{documentTypes:c,mediaTypes:d,mediaFeatures:p,mediaValueKeywords:v,propertyKeywords:w,nonStandardPropertyKeywords:L,fontProperties:M,counterDescriptors:I,colorKeywords:$,valueKeywords:ne,tokenHooks:{\"/\":function(G,j){return G.eat(\"*\")?(j.tokenize=Z,Z(G,j)):!1}},name:\"css\"}),r.defineMIME(\"text/x-scss\",{mediaTypes:d,mediaFeatures:p,mediaValueKeywords:v,propertyKeywords:w,nonStandardPropertyKeywords:L,colorKeywords:$,valueKeywords:ne,fontProperties:M,allowNested:!0,lineComment:\"//\",tokenHooks:{\"/\":function(G,j){return G.eat(\"/\")?(G.skipToEnd(),[\"comment\",\"comment\"]):G.eat(\"*\")?(j.tokenize=Z,Z(G,j)):[\"operator\",\"operator\"]},\":\":function(G){return G.match(/^\\s*\\{/,!1)?[null,null]:!1},$:function(G){return G.match(/^[\\w-]+/),G.match(/^\\s*:/,!1)?[\"variable-2\",\"variable-definition\"]:[\"variable-2\",\"variable\"]},\"#\":function(G){return G.eat(\"{\")?[null,\"interpolation\"]:!1}},name:\"css\",helperType:\"scss\"}),r.defineMIME(\"text/x-less\",{mediaTypes:d,mediaFeatures:p,mediaValueKeywords:v,propertyKeywords:w,nonStandardPropertyKeywords:L,colorKeywords:$,valueKeywords:ne,fontProperties:M,allowNested:!0,lineComment:\"//\",tokenHooks:{\"/\":function(G,j){return G.eat(\"/\")?(G.skipToEnd(),[\"comment\",\"comment\"]):G.eat(\"*\")?(j.tokenize=Z,Z(G,j)):[\"operator\",\"operator\"]},\"@\":function(G){return G.eat(\"{\")?[null,\"interpolation\"]:G.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\\b/i,!1)?!1:(G.eatWhile(/[\\w\\\\\\-]/),G.match(/^\\s*:/,!1)?[\"variable-2\",\"variable-definition\"]:[\"variable-2\",\"variable\"])},\"&\":function(){return[\"atom\",\"atom\"]}},name:\"css\",helperType:\"less\"}),r.defineMIME(\"text/x-gss\",{documentTypes:c,mediaTypes:d,mediaFeatures:p,propertyKeywords:w,nonStandardPropertyKeywords:L,fontProperties:M,counterDescriptors:I,colorKeywords:$,valueKeywords:ne,supportsAtComponent:!0,tokenHooks:{\"/\":function(G,j){return G.eat(\"*\")?(j.tokenize=Z,Z(G,j)):!1}},name:\"css\",helperType:\"gss\"})})})()),Sy.exports}var Ty;function cce(){return Ty||(Ty=1,(function(e,t){(function(r){r(vo(),kp(),xp(),ace())})(function(r){var o={script:[[\"lang\",/(javascript|babel)/i,\"javascript\"],[\"type\",/^(?:text|application)\\/(?:x-)?(?:java|ecma)script$|^module$|^$/i,\"javascript\"],[\"type\",/./,\"text/plain\"],[null,null,\"javascript\"]],style:[[\"lang\",/^css$/i,\"css\"],[\"type\",/^(text\\/)?(x-)?(stylesheet|css)$/i,\"css\"],[\"type\",/./,\"text/plain\"],[null,null,\"css\"]]};function s(v,b,w){var E=v.current(),L=E.search(b);return L>-1?v.backUp(E.length-L):E.match(/<\\/?$/)&&(v.backUp(E.length),v.match(b,!1)||v.match(E)),w}var c={};function f(v){var b=c[v];return b||(c[v]=new RegExp(\"\\\\s+\"+v+`\\\\s*=\\\\s*('|\")?([^'\"]+)('|\")?\\\\s*`))}function d(v,b){var w=v.match(f(b));return w?/^\\s*(.*?)\\s*$/.exec(w[2])[1]:\"\"}function h(v,b){return new RegExp((b?\"^\":\"\")+\"</\\\\s*\"+v+\"\\\\s*>\",\"i\")}function p(v,b){for(var w in v)for(var E=b[w]||(b[w]=[]),L=v[w],P=L.length-1;P>=0;P--)E.unshift(L[P])}function g(v,b){for(var w=0;w<v.length;w++){var E=v[w];if(!E[0]||E[1].test(d(b,E[0])))return E[2]}}r.defineMode(\"htmlmixed\",function(v,b){var w=r.getMode(v,{name:\"xml\",htmlMode:!0,multilineTagIndentFactor:b.multilineTagIndentFactor,multilineTagIndentPastTag:b.multilineTagIndentPastTag,allowMissingTagName:b.allowMissingTagName}),E={},L=b&&b.tags,P=b&&b.scriptTypes;if(p(o,E),L&&p(L,E),P)for(var M=P.length-1;M>=0;M--)E.script.unshift([\"type\",P[M].matches,P[M].mode]);function R(I,_){var $=w.token(I,_.htmlState),W=/\\btag\\b/.test($),ne;if(W&&!/[<>\\s\\/]/.test(I.current())&&(ne=_.htmlState.tagName&&_.htmlState.tagName.toLowerCase())&&E.hasOwnProperty(ne))_.inTag=ne+\" \";else if(_.inTag&&W&&/>$/.test(I.current())){var ee=/^([\\S]+) (.*)/.exec(_.inTag);_.inTag=null;var Z=I.current()==\">\"&&g(E[ee[1]],ee[2]),G=r.getMode(v,Z),j=h(ee[1],!0),N=h(ee[1],!1);_.token=function(O,C){return O.match(j,!1)?(C.token=R,C.localState=C.localMode=null,null):s(O,N,C.localMode.token(O,C.localState))},_.localMode=G,_.localState=r.startState(G,w.indent(_.htmlState,\"\",\"\"))}else _.inTag&&(_.inTag+=I.current(),I.eol()&&(_.inTag+=\" \"));return $}return{startState:function(){var I=r.startState(w);return{token:R,inTag:null,localMode:null,localState:null,htmlState:I}},copyState:function(I){var _;return I.localState&&(_=r.copyState(I.localMode,I.localState)),{token:I.token,inTag:I.inTag,localMode:I.localMode,localState:_,htmlState:r.copyState(w,I.htmlState)}},token:function(I,_){return _.token(I,_)},indent:function(I,_,$){return!I.localMode||/^\\s*<\\//.test(_)?w.indent(I.htmlState,_,$):I.localMode.indent?I.localMode.indent(I.localState,_,$):r.Pass},innerMode:function(I){return{state:I.localState||I.htmlState,mode:I.localMode||w}}}},\"xml\",\"javascript\",\"css\"),r.defineMIME(\"text/html\",\"htmlmixed\")})})()),ky.exports}cce();var Cy={exports:{}},Ey;function uce(){return Ey||(Ey=1,(function(e,t){(function(r){r(vo(),kp(),xp())})(function(r){function o(c,f,d,h){this.state=c,this.mode=f,this.depth=d,this.prev=h}function s(c){return new o(r.copyState(c.mode,c.state),c.mode,c.depth,c.prev&&s(c.prev))}r.defineMode(\"jsx\",function(c,f){var d=r.getMode(c,{name:\"xml\",allowMissing:!0,multilineTagIndentPastTag:!1,allowMissingTagName:!0}),h=r.getMode(c,f&&f.base||\"javascript\");function p(w){var E=w.tagName;w.tagName=null;var L=d.indent(w,\"\",\"\");return w.tagName=E,L}function g(w,E){return E.context.mode==d?v(w,E,E.context):b(w,E,E.context)}function v(w,E,L){if(L.depth==2)return w.match(/^.*?\\*\\//)?L.depth=1:w.skipToEnd(),\"comment\";if(w.peek()==\"{\"){d.skipAttribute(L.state);var P=p(L.state),M=L.state.context;if(M&&w.match(/^[^>]*>\\s*$/,!1)){for(;M.prev&&!M.startOfLine;)M=M.prev;M.startOfLine?P-=c.indentUnit:L.prev.state.lexical&&(P=L.prev.state.lexical.indented)}else L.depth==1&&(P+=c.indentUnit);return E.context=new o(r.startState(h,P),h,0,E.context),null}if(L.depth==1){if(w.peek()==\"<\")return d.skipAttribute(L.state),E.context=new o(r.startState(d,p(L.state)),d,0,E.context),null;if(w.match(\"//\"))return w.skipToEnd(),\"comment\";if(w.match(\"/*\"))return L.depth=2,g(w,E)}var R=d.token(w,L.state),I=w.current(),_;return/\\btag\\b/.test(R)?/>$/.test(I)?L.state.context?L.depth=0:E.context=E.context.prev:/^</.test(I)&&(L.depth=1):!R&&(_=I.indexOf(\"{\"))>-1&&w.backUp(I.length-_),R}function b(w,E,L){if(w.peek()==\"<\"&&!w.match(/^<([^<>]|<[^>]*>)+,\\s*>/,!1)&&h.expressionAllowed(w,L.state))return E.context=new o(r.startState(d,h.indent(L.state,\"\",\"\")),d,0,E.context),h.skipExpression(L.state),null;var P=h.token(w,L.state);if(!P&&L.depth!=null){var M=w.current();M==\"{\"?L.depth++:M==\"}\"&&--L.depth==0&&(E.context=E.context.prev)}return P}return{startState:function(){return{context:new o(r.startState(h),h)}},copyState:function(w){return{context:s(w.context)}},token:g,indent:function(w,E,L){return w.context.mode.indent(w.context.state,E,L)},innerMode:function(w){return w.context}}},\"xml\",\"javascript\"),r.defineMIME(\"text/jsx\",\"jsx\"),r.defineMIME(\"text/typescript-jsx\",{name:\"jsx\",base:{name:\"javascript\",typescript:!0}})})})()),Cy.exports}uce();var Ay={exports:{}},Ly;function fce(){return Ly||(Ly=1,(function(e,t){(function(r){r(vo())})(function(r){r.defineOption(\"placeholder\",\"\",function(p,g,v){var b=v&&v!=r.Init;if(g&&!b)p.on(\"blur\",f),p.on(\"change\",d),p.on(\"swapDoc\",d),r.on(p.getInputField(),\"compositionupdate\",p.state.placeholderCompose=function(){c(p)}),d(p);else if(!g&&b){p.off(\"blur\",f),p.off(\"change\",d),p.off(\"swapDoc\",d),r.off(p.getInputField(),\"compositionupdate\",p.state.placeholderCompose),o(p);var w=p.getWrapperElement();w.className=w.className.replace(\" CodeMirror-empty\",\"\")}g&&!p.hasFocus()&&f(p)});function o(p){p.state.placeholder&&(p.state.placeholder.parentNode.removeChild(p.state.placeholder),p.state.placeholder=null)}function s(p){o(p);var g=p.state.placeholder=document.createElement(\"pre\");g.style.cssText=\"height: 0; overflow: visible\",g.style.direction=p.getOption(\"direction\"),g.className=\"CodeMirror-placeholder CodeMirror-line-like\";var v=p.getOption(\"placeholder\");typeof v==\"string\"&&(v=document.createTextNode(v)),g.appendChild(v),p.display.lineSpace.insertBefore(g,p.display.lineSpace.firstChild)}function c(p){setTimeout(function(){var g=!1;if(p.lineCount()==1){var v=p.getInputField();g=v.nodeName==\"TEXTAREA\"?!p.getLine(0).length:!/[^\\u200b]/.test(v.querySelector(\".CodeMirror-line\").textContent)}g?s(p):o(p)},20)}function f(p){h(p)&&s(p)}function d(p){var g=p.getWrapperElement(),v=h(p);g.className=g.className.replace(\" CodeMirror-empty\",\"\")+(v?\" CodeMirror-empty\":\"\"),v?s(p):o(p)}function h(p){return p.lineCount()===1&&p.getLine(0)===\"\"}})})()),Ay.exports}fce();var My={exports:{}},Ny;function dce(){return Ny||(Ny=1,(function(e,t){(function(r){r(vo())})(function(r){function o(f,d,h){this.orientation=d,this.scroll=h,this.screen=this.total=this.size=1,this.pos=0,this.node=document.createElement(\"div\"),this.node.className=f+\"-\"+d,this.inner=this.node.appendChild(document.createElement(\"div\"));var p=this;r.on(this.inner,\"mousedown\",function(v){if(v.which!=1)return;r.e_preventDefault(v);var b=p.orientation==\"horizontal\"?\"pageX\":\"pageY\",w=v[b],E=p.pos;function L(){r.off(document,\"mousemove\",P),r.off(document,\"mouseup\",L)}function P(M){if(M.which!=1)return L();p.moveTo(E+(M[b]-w)*(p.total/p.size))}r.on(document,\"mousemove\",P),r.on(document,\"mouseup\",L)}),r.on(this.node,\"click\",function(v){r.e_preventDefault(v);var b=p.inner.getBoundingClientRect(),w;p.orientation==\"horizontal\"?w=v.clientX<b.left?-1:v.clientX>b.right?1:0:w=v.clientY<b.top?-1:v.clientY>b.bottom?1:0,p.moveTo(p.pos+w*p.screen)});function g(v){var b=r.wheelEventPixels(v)[p.orientation==\"horizontal\"?\"x\":\"y\"],w=p.pos;p.moveTo(p.pos+b),p.pos!=w&&r.e_preventDefault(v)}r.on(this.node,\"mousewheel\",g),r.on(this.node,\"DOMMouseScroll\",g)}o.prototype.setPos=function(f,d){return f<0&&(f=0),f>this.total-this.screen&&(f=this.total-this.screen),!d&&f==this.pos?!1:(this.pos=f,this.inner.style[this.orientation==\"horizontal\"?\"left\":\"top\"]=f*(this.size/this.total)+\"px\",!0)},o.prototype.moveTo=function(f){this.setPos(f)&&this.scroll(f,this.orientation)};var s=10;o.prototype.update=function(f,d,h){var p=this.screen!=d||this.total!=f||this.size!=h;p&&(this.screen=d,this.total=f,this.size=h);var g=this.screen*(this.size/this.total);g<s&&(this.size-=s-g,g=s),this.inner.style[this.orientation==\"horizontal\"?\"width\":\"height\"]=g+\"px\",this.setPos(this.pos,p)};function c(f,d,h){this.addClass=f,this.horiz=new o(f,\"horizontal\",h),d(this.horiz.node),this.vert=new o(f,\"vertical\",h),d(this.vert.node),this.width=null}c.prototype.update=function(f){if(this.width==null){var d=window.getComputedStyle?window.getComputedStyle(this.horiz.node):this.horiz.node.currentStyle;d&&(this.width=parseInt(d.height))}var h=this.width||0,p=f.scrollWidth>f.clientWidth+1,g=f.scrollHeight>f.clientHeight+1;return this.vert.node.style.display=g?\"block\":\"none\",this.horiz.node.style.display=p?\"block\":\"none\",g&&(this.vert.update(f.scrollHeight,f.clientHeight,f.viewHeight-(p?h:0)),this.vert.node.style.bottom=p?h+\"px\":\"0\"),p&&(this.horiz.update(f.scrollWidth,f.clientWidth,f.viewWidth-(g?h:0)-f.barLeft),this.horiz.node.style.right=g?h+\"px\":\"0\",this.horiz.node.style.left=f.barLeft+\"px\"),{right:g?h:0,bottom:p?h:0}},c.prototype.setScrollTop=function(f){this.vert.setPos(f)},c.prototype.setScrollLeft=function(f){this.horiz.setPos(f)},c.prototype.clear=function(){var f=this.horiz.node.parentNode;f.removeChild(this.horiz.node),f.removeChild(this.vert.node)},r.scrollbarModel.simple=function(f,d){return new c(\"CodeMirror-simplescroll\",f,d)},r.scrollbarModel.overlay=function(f,d){return new c(\"CodeMirror-overlayscroll\",f,d)}})})()),My.exports}dce();const Nn=Ft();function hce(e,t,r={}){const o=NL.fromTextArea(e.value,{theme:\"vars\",...r,scrollbarStyle:\"simple\"});let s=!1;return o.on(\"change\",()=>{if(s){s=!1;return}t.value=o.getValue()}),xt(t,c=>{if(c!==o.getValue()){s=!0;const f=o.listSelections();o.replaceRange(c,o.posFromIndex(0),o.posFromIndex(Number.POSITIVE_INFINITY)),o.setSelections(f)}},{immediate:!0}),Ia(()=>{Nn.value=void 0}),Uu(o)}async function gx(e){_a({file:e.file.id,line:e.location?.line??1,view:\"editor\",test:e.id,column:null})}function pce(e,t){_a({file:e,column:t.column-1,line:t.line,view:\"editor\",test:Bs.value})}function gce(e,t){if(!t)return;const{line:r,column:o,file:s}=t;if(e.file.filepath!==s)return bp(s,r,o);_a({file:e.file.id,column:o-1,line:r,view:\"editor\",test:Bs.value})}const pr=Ge(),Ws=Ge(!0),go=Ge(!1),Cu=Ge(!0),Ns=ke(()=>ei.value?.coverage),mh=ke(()=>Ns.value?.enabled),Os=ke(()=>mh.value&&!!Ns.value.htmlReporter),qs=sf(\"vitest-ui_splitpanes-mainSizes\",[33,67]),co=sf(\"vitest-ui_splitpanes-detailSizes\",[window.__vitest_browser_runner__?.provider===\"webdriverio\"?tr.value[0]/window.outerWidth*100:33,67]),At=ir({navigation:qs.value[0],details:{size:qs.value[1],browser:co.value[0],main:co.value[1]}}),Oy=ke(()=>{if(Os.value){const e=Ns.value.reportsDirectory.lastIndexOf(\"/\"),t=Ns.value.htmlReporter?.subdir;return t?`/${Ns.value.reportsDirectory.slice(e+1)}/${t}/index.html`:`/${Ns.value.reportsDirectory.slice(e+1)}/index.html`}});xt(uf,e=>{Cu.value=e===\"running\"},{immediate:!0});function mce(){const e=po.value;if(e&&e.length>0){const t=mr(e);t?(pr.value=t,Ws.value=!1,go.value=!1):_E(()=>ft.state.getFiles(),()=>{pr.value=mr(e),Ws.value=!1,go.value=!1})}return Ws}function Eu(e){Ws.value=e,go.value=!1,e&&(pr.value=void 0,po.value=\"\")}function _a({file:e,line:t,view:r,test:o,column:s}){po.value=e,hx.value=t,px.value=s,hn.value=r,Bs.value=o,pr.value=mr(e),Eu(!1)}function vce(e){e.type===\"test\"?hn.value===\"editor\"?gx(e):_a({file:e.file.id,line:null,column:null,view:hn.value,test:e.id}):_a({file:e.file.id,test:null,line:null,view:hn.value,column:null})}function yce(){go.value=!0,Ws.value=!1,pr.value=void 0,po.value=\"\"}function bce(){At.details.browser=100,At.details.main=0,co.value=[100,0]}function mx(){if(Zn?.provider===\"webdriverio\"){const e=window.outerWidth*(At.details.size/100);return(tr.value[0]+20)/e*100}return 33}function wce(){At.details.browser=mx(),At.details.main=100-At.details.browser,co.value=[At.details.browser,At.details.main]}function xce(){At.navigation=33,At.details.size=67,qs.value=[33,67]}function vx(){At.details.main!==0&&(At.details.browser=mx(),At.details.main=100-At.details.browser,co.value=[At.details.browser,At.details.main])}const kce={setCurrentFileId(e){po.value=e,pr.value=mr(e),Eu(!1)},async setIframeViewport(e,t){tr.value=[e,t],Zn?.provider===\"webdriverio\"&&vx(),await new Promise(r=>requestAnimationFrame(r))}},Sce=location.port,_ce=[location.hostname,Sce].filter(Boolean).join(\":\"),Tce=`${location.protocol===\"https:\"?\"wss:\":\"ws:\"}//${_ce}/__vitest_api__?token=${window.VITEST_API_TOKEN||\"0\"}`,gr=!!window.METADATA_PATH;var rr=Uint8Array,Ps=Uint16Array,Cce=Int32Array,yx=new rr([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),bx=new rr([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Ece=new rr([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),wx=function(e,t){for(var r=new Ps(31),o=0;o<31;++o)r[o]=t+=1<<e[o-1];for(var s=new Cce(r[30]),o=1;o<30;++o)for(var c=r[o];c<r[o+1];++c)s[c]=c-r[o]<<5|o;return{b:r,r:s}},xx=wx(yx,2),kx=xx.b,Ace=xx.r;kx[28]=258,Ace[258]=28;var Lce=wx(bx,0),Mce=Lce.b,vh=new Ps(32768);for(var Lt=0;Lt<32768;++Lt){var Vi=(Lt&43690)>>1|(Lt&21845)<<1;Vi=(Vi&52428)>>2|(Vi&13107)<<2,Vi=(Vi&61680)>>4|(Vi&3855)<<4,vh[Lt]=((Vi&65280)>>8|(Vi&255)<<8)>>1}var sa=(function(e,t,r){for(var o=e.length,s=0,c=new Ps(t);s<o;++s)e[s]&&++c[e[s]-1];var f=new Ps(t);for(s=1;s<t;++s)f[s]=f[s-1]+c[s-1]<<1;var d;if(r){d=new Ps(1<<t);var h=15-t;for(s=0;s<o;++s)if(e[s])for(var p=s<<4|e[s],g=t-e[s],v=f[e[s]-1]++<<g,b=v|(1<<g)-1;v<=b;++v)d[vh[v]>>h]=p}else for(d=new Ps(o),s=0;s<o;++s)e[s]&&(d[s]=vh[f[e[s]-1]++]>>15-e[s]);return d}),qa=new rr(288);for(var Lt=0;Lt<144;++Lt)qa[Lt]=8;for(var Lt=144;Lt<256;++Lt)qa[Lt]=9;for(var Lt=256;Lt<280;++Lt)qa[Lt]=7;for(var Lt=280;Lt<288;++Lt)qa[Lt]=8;var Sx=new rr(32);for(var Lt=0;Lt<32;++Lt)Sx[Lt]=5;var Nce=sa(qa,9,1),Oce=sa(Sx,5,1),Md=function(e){for(var t=e[0],r=1;r<e.length;++r)e[r]>t&&(t=e[r]);return t},Ar=function(e,t,r){var o=t/8|0;return(e[o]|e[o+1]<<8)>>(t&7)&r},Nd=function(e,t){var r=t/8|0;return(e[r]|e[r+1]<<8|e[r+2]<<16)>>(t&7)},Pce=function(e){return(e+7)/8|0},_x=function(e,t,r){return(t==null||t<0)&&(t=0),(r==null||r>e.length)&&(r=e.length),new rr(e.subarray(t,r))},Rce=[\"unexpected EOF\",\"invalid block type\",\"invalid length/literal\",\"invalid distance\",\"stream finished\",\"no stream handler\",,\"no callback\",\"invalid UTF-8 data\",\"extra field too long\",\"date not in range 1980-2099\",\"filename too long\",\"stream finishing\",\"invalid zip data\"],Un=function(e,t,r){var o=new Error(t||Rce[e]);if(o.code=e,Error.captureStackTrace&&Error.captureStackTrace(o,Un),!r)throw o;return o},Sp=function(e,t,r,o){var s=e.length,c=0;if(!s||t.f&&!t.l)return r||new rr(0);var f=!r,d=f||t.i!=2,h=t.i;f&&(r=new rr(s*3));var p=function(ae){var D=r.length;if(ae>D){var q=new rr(Math.max(D*2,ae));q.set(r),r=q}},g=t.f||0,v=t.p||0,b=t.b||0,w=t.l,E=t.d,L=t.m,P=t.n,M=s*8;do{if(!w){g=Ar(e,v,1);var R=Ar(e,v+1,3);if(v+=3,R)if(R==1)w=Nce,E=Oce,L=9,P=5;else if(R==2){var W=Ar(e,v,31)+257,ne=Ar(e,v+10,15)+4,ee=W+Ar(e,v+5,31)+1;v+=14;for(var Z=new rr(ee),G=new rr(19),j=0;j<ne;++j)G[Ece[j]]=Ar(e,v+j*3,7);v+=ne*3;for(var N=Md(G),O=(1<<N)-1,C=sa(G,N,1),j=0;j<ee;){var k=C[Ar(e,v,O)];v+=k&15;var I=k>>4;if(I<16)Z[j++]=I;else{var z=0,B=0;for(I==16?(B=3+Ar(e,v,3),v+=2,z=Z[j-1]):I==17?(B=3+Ar(e,v,7),v+=3):I==18&&(B=11+Ar(e,v,127),v+=7);B--;)Z[j++]=z}}var ce=Z.subarray(0,W),be=Z.subarray(W);L=Md(ce),P=Md(be),w=sa(ce,L,1),E=sa(be,P,1)}else Un(1);else{var I=Pce(v)+4,_=e[I-4]|e[I-3]<<8,$=I+_;if($>s){h&&Un(0);break}d&&p(b+_),r.set(e.subarray(I,$),b),t.b=b+=_,t.p=v=$*8,t.f=g;continue}if(v>M){h&&Un(0);break}}d&&p(b+131072);for(var Se=(1<<L)-1,Be=(1<<P)-1,Ae=v;;Ae=v){var z=w[Nd(e,v)&Se],Ke=z>>4;if(v+=z&15,v>M){h&&Un(0);break}if(z||Un(2),Ke<256)r[b++]=Ke;else if(Ke==256){Ae=v,w=null;break}else{var je=Ke-254;if(Ke>264){var j=Ke-257,Fe=yx[j];je=Ar(e,v,(1<<Fe)-1)+kx[j],v+=Fe}var Pe=E[Nd(e,v)&Be],F=Pe>>4;Pe||Un(3),v+=Pe&15;var be=Mce[F];if(F>3){var Fe=bx[F];be+=Nd(e,v)&(1<<Fe)-1,v+=Fe}if(v>M){h&&Un(0);break}d&&p(b+131072);var Y=b+je;if(b<be){var re=c-be,le=Math.min(be,Y);for(re+b<0&&Un(3);b<le;++b)r[b]=o[re+b]}for(;b<Y;++b)r[b]=r[b-be]}}t.l=w,t.p=Ae,t.b=b,t.f=g,w&&(g=1,t.m=L,t.d=E,t.n=P)}while(!g);return b!=r.length&&f?_x(r,0,b):r.subarray(0,b)},$ce=new rr(0),Ice=function(e){(e[0]!=31||e[1]!=139||e[2]!=8)&&Un(6,\"invalid gzip data\");var t=e[3],r=10;t&4&&(r+=(e[10]|e[11]<<8)+2);for(var o=(t>>3&1)+(t>>4&1);o>0;o-=!e[r++]);return r+(t&2)},Dce=function(e){var t=e.length;return(e[t-4]|e[t-3]<<8|e[t-2]<<16|e[t-1]<<24)>>>0},zce=function(e,t){return((e[0]&15)!=8||e[0]>>4>7||(e[0]<<8|e[1])%31)&&Un(6,\"invalid zlib data\"),(e[1]>>5&1)==1&&Un(6,\"invalid zlib data: \"+(e[1]&32?\"need\":\"unexpected\")+\" dictionary\"),(e[1]>>3&4)+2};function Fce(e,t){return Sp(e,{i:2},t,t)}function Hce(e,t){var r=Ice(e);return r+8>e.length&&Un(6,\"invalid gzip data\"),Sp(e.subarray(r,-8),{i:2},new rr(Dce(e)),t)}function Bce(e,t){return Sp(e.subarray(zce(e),-4),{i:2},t,t)}function Wce(e,t){return e[0]==31&&e[1]==139&&e[2]==8?Hce(e,t):(e[0]&15)!=8||e[0]>>4>7||(e[0]<<8|e[1])%31?Fce(e,t):Bce(e,t)}var yh=typeof TextDecoder<\"u\"&&new TextDecoder,qce=0;try{yh.decode($ce,{stream:!0}),qce=1}catch{}var jce=function(e){for(var t=\"\",r=0;;){var o=e[r++],s=(o>127)+(o>223)+(o>239);if(r+s>e.length)return{s:t,r:_x(e,r-1)};s?s==3?(o=((o&15)<<18|(e[r++]&63)<<12|(e[r++]&63)<<6|e[r++]&63)-65536,t+=String.fromCharCode(55296|o>>10,56320|o&1023)):s&1?t+=String.fromCharCode((o&31)<<6|e[r++]&63):t+=String.fromCharCode((o&15)<<12|(e[r++]&63)<<6|e[r++]&63):t+=String.fromCharCode(o)}};function Py(e,t){var r;if(yh)return yh.decode(e);var o=jce(e),s=o.s,r=o.r;return r.length&&Un(8),s}const Od=()=>{},dn=()=>Promise.resolve();function Uce(){const e=ir({state:new Xw,waitForConnection:f,reconnect:s,ws:new EventTarget});e.state.filesMap=ir(e.state.filesMap),e.state.idMap=ir(e.state.idMap);let t;const r={getFiles:()=>t.files,getPaths:()=>t.paths,getConfig:()=>t.config,getResolvedProjectNames:()=>t.projects,getResolvedProjectLabels:()=>[],getModuleGraph:async(d,h)=>t.moduleGraph[d]?.[h],getUnhandledErrors:()=>t.unhandledErrors,getExternalResult:dn,getTransformResult:dn,onDone:Od,onTaskUpdate:Od,writeFile:dn,rerun:dn,rerunTask:dn,updateSnapshot:dn,resolveSnapshotPath:dn,snapshotSaved:dn,onAfterSuiteRun:dn,onCancel:dn,getCountOfFailedTests:()=>0,sendLog:dn,resolveSnapshotRawPath:dn,readSnapshotFile:dn,saveSnapshotFile:dn,readTestFile:async d=>t.sources[d],removeSnapshotFile:dn,onUnhandledError:Od,saveTestFile:dn,getProvidedContext:()=>({}),getTestFiles:dn};e.rpc=r;const o=Promise.resolve();function s(){c()}async function c(){const d=await fetch(window.METADATA_PATH),h=new Uint8Array(await d.arrayBuffer());if(h.length>=2&&h[0]===31&&h[1]===139){const g=Py(Wce(h));t=fh(g)}else t=fh(Py(h));const p=new Event(\"open\");e.ws.dispatchEvent(p)}c();function f(){return o}return e}const ft=(function(){return gr?Uce():XA(Tce,{reactive:(t,r)=>r===\"state\"?ir(t):Ft(t),handlers:{onTestAnnotate(t,r){Oe.recordTestArtifact(t,{type:\"internal:annotation\",annotation:r,location:r.location})},onTestArtifactRecord(t,r){Oe.recordTestArtifact(t,r)},onTaskUpdate(t,r){Oe.resumeRun(t,r),uf.value=\"running\"},onSpecsCollected(t,r){Oe.startTime=r||performance.now()},onFinished(t,r,o,s){Oe.endRun(s),eo.value=(r||[]).map(fx)},onFinishedReportCoverage(){const t=document.querySelector(\"iframe#vitest-ui-coverage\");t instanceof HTMLIFrameElement&&t.contentWindow&&t.contentWindow.location.reload()}}})})(),ei=Ft({}),Ho=Ge(\"CONNECTING\"),Gt=ke(()=>{const e=po.value;return e?mr(e):void 0}),Tx=ke(()=>gp(Gt.value).map(e=>e?.logs||[]).flat()||[]);function mr(e){const t=ft.state.idMap.get(e);return t||void 0}const Vce=ke(()=>Ho.value===\"OPEN\"),Pd=ke(()=>Ho.value===\"CONNECTING\");ke(()=>Ho.value===\"CLOSED\");function Gce(){return _p(ft.state.getFiles())}function Cx(e){delete e.result;const t=Oe.nodes.get(e.id);if(t&&(t.state=void 0,t.duration=void 0,Ha(e)))for(const r of e.tasks)Cx(r)}function Kce(e){const t=Oe.nodes;e.forEach(r=>{delete r.result,gp(r).forEach(s=>{if(delete s.result,t.has(s.id)){const c=t.get(s.id);c&&(c.state=void 0,c.duration=void 0)}});const o=t.get(r.id);o&&(o.state=void 0,o.duration=void 0,In(o)&&(o.collectDuration=void 0))})}function _p(e){return Kce(e),Oe.startRun(),ft.rpc.rerun(e.map(t=>t.filepath),!0)}function Xce(e){return Cx(e),Oe.startRun(),ft.rpc.rerunTask(e.id)}const Zn=window.__vitest_browser_runner__;window.__vitest_ui_api__=kce;xt(()=>ft.ws,e=>{Ho.value=gr?\"OPEN\":\"CONNECTING\",e.addEventListener(\"open\",async()=>{Ho.value=\"OPEN\",ft.state.filesMap.clear();let[t,r,o,s]=await Promise.all([ft.rpc.getFiles(),ft.rpc.getConfig(),ft.rpc.getUnhandledErrors(),ft.rpc.getResolvedProjectLabels()]);r.standalone&&(t=(await ft.rpc.getTestFiles()).map(([{name:f,root:d},h])=>{const p=Bw(h,d,f);return p.mode=\"skip\",p})),Oe.loadFiles(t,s),ft.state.collectFiles(t),Oe.startRun(),eo.value=(o||[]).map(fx),ei.value=r}),e.addEventListener(\"close\",()=>{setTimeout(()=>{Ho.value===\"CONNECTING\"&&(Ho.value=\"CLOSED\")},1e3)})},{immediate:!0});const Yce=[\"aria-label\",\"opacity\",\"disabled\",\"hover\"],_t=rt({__name:\"IconButton\",props:{icon:{},title:{},disabled:{type:Boolean},active:{type:Boolean}},setup(e){return(t,r)=>(ie(),ve(\"button\",{\"aria-label\":e.title,role:\"button\",opacity:e.disabled?10:70,rounded:\"\",disabled:e.disabled,hover:e.disabled||e.active?\"\":\"bg-active op100\",class:ot([\"w-1.4em h-1.4em flex\",[{\"bg-gray-500:35 op100\":e.active}]])},[Dt(t.$slots,\"default\",{},()=>[X(\"span\",{class:ot(e.icon),ma:\"\",block:\"\"},null,2)])],10,Yce))}}),Zce={h:\"full\",flex:\"~ col\"},Jce={p:\"3\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},Qce={p:\"l3 y2 r2\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b-2 base\"},eue={class:\"pointer-events-none\",\"text-sm\":\"\"},tue={key:0},nue={id:\"tester-container\",relative:\"\"},rue=[\"data-scale\"],Ry=20,iue=100,oue=rt({__name:\"BrowserIframe\",setup(e){const t={\"small-mobile\":[320,568],\"large-mobile\":[414,896],tablet:[834,1112]};function r(p){const g=t[p];return tr.value[0]===g[0]&&tr.value[1]===g[1]}const{width:o,height:s}=Pw();async function c(p){tr.value=t[p],Zn?.provider===\"webdriverio\"&&vx()}const f=ke(()=>{if(Zn?.provider===\"webdriverio\"){const[w,E]=tr.value;return{width:w,height:E}}const v=o.value*(At.details.size/100)*(At.details.browser/100)-Ry,b=s.value-iue;return{width:v,height:b}}),d=ke(()=>{if(Zn?.provider===\"webdriverio\")return 1;const[p,g]=tr.value,{width:v,height:b}=f.value,w=v>p?1:v/p,E=b>g?1:b/g;return Math.min(1,w,E)}),h=ke(()=>{const p=f.value.width,g=tr.value[0];return`${Math.trunc((p+Ry-g)/2)}px`});return(p,g)=>{const v=vr(\"tooltip\");return ie(),ve(\"div\",Zce,[X(\"div\",Jce,[at(Ne(_t,{title:\"Show Navigation Panel\",\"rotate-180\":\"\",icon:\"i-carbon:side-panel-close\",onClick:g[0]||(g[0]=b=>K(xce)())},null,512),[[ro,K(At).navigation<=15],[v,\"Show Navigation Panel\",void 0,{bottom:!0}]]),g[6]||(g[6]=X(\"div\",{class:\"i-carbon-content-delivery-network\"},null,-1)),g[7]||(g[7]=X(\"span\",{\"pl-1\":\"\",\"font-bold\":\"\",\"text-sm\":\"\",\"flex-auto\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",truncate:\"\"},\"Browser UI\",-1)),at(Ne(_t,{title:\"Hide Right Panel\",icon:\"i-carbon:side-panel-close\",\"rotate-180\":\"\",onClick:g[1]||(g[1]=b=>K(bce)())},null,512),[[ro,K(At).details.main>0],[v,\"Hide Right Panel\",void 0,{bottom:!0}]]),at(Ne(_t,{title:\"Show Right Panel\",icon:\"i-carbon:side-panel-close\",onClick:g[2]||(g[2]=b=>K(wce)())},null,512),[[ro,K(At).details.main===0],[v,\"Show Right Panel\",void 0,{bottom:!0}]])]),X(\"div\",Qce,[at(Ne(_t,{title:\"Small mobile\",icon:\"i-carbon:mobile\",active:r(\"small-mobile\"),onClick:g[3]||(g[3]=b=>c(\"small-mobile\"))},null,8,[\"active\"]),[[v,\"Small mobile\",void 0,{bottom:!0}]]),at(Ne(_t,{title:\"Large mobile\",icon:\"i-carbon:mobile-add\",active:r(\"large-mobile\"),onClick:g[4]||(g[4]=b=>c(\"large-mobile\"))},null,8,[\"active\"]),[[v,\"Large mobile\",void 0,{bottom:!0}]]),at(Ne(_t,{title:\"Tablet\",icon:\"i-carbon:tablet\",active:r(\"tablet\"),onClick:g[5]||(g[5]=b=>c(\"tablet\"))},null,8,[\"active\"]),[[v,\"Tablet\",void 0,{bottom:!0}]]),X(\"span\",eue,[Qe(Re(K(tr)[0])+\"x\"+Re(K(tr)[1])+\"px \",1),d.value<1?(ie(),ve(\"span\",tue,\"(\"+Re((d.value*100).toFixed(0))+\"%)\",1)):He(\"\",!0)])]),X(\"div\",nue,[X(\"div\",{id:\"tester-ui\",class:\"flex h-full justify-center items-center font-light op70\",\"data-scale\":d.value,style:zt({\"--viewport-width\":`${K(tr)[0]}px`,\"--viewport-height\":`${K(tr)[1]}px`,\"--tester-transform\":`scale(${d.value})`,\"--tester-margin-left\":h.value})},\" Select a test to run \",12,rue)])])}}}),sue=Ni(oue,[[\"__scopeId\",\"data-v-2e86b8c3\"]]),lue={\"text-2xl\":\"\"},aue={\"text-lg\":\"\",op50:\"\"},cue=rt({__name:\"ConnectionOverlay\",setup(e){return(t,r)=>K(Vce)?He(\"\",!0):(ie(),ve(\"div\",{key:0,fixed:\"\",\"inset-0\":\"\",p2:\"\",\"z-10\":\"\",\"select-none\":\"\",text:\"center sm\",bg:\"overlay\",\"backdrop-blur-sm\":\"\",\"backdrop-saturate-0\":\"\",onClick:r[0]||(r[0]=(...o)=>K(ft).reconnect&&K(ft).reconnect(...o))},[X(\"div\",{\"h-full\":\"\",flex:\"~ col gap-2\",\"items-center\":\"\",\"justify-center\":\"\",class:ot(K(Pd)?\"animate-pulse\":\"\")},[X(\"div\",{text:\"5xl\",class:ot(K(Pd)?\"i-carbon:renew animate-spin animate-reverse\":\"i-carbon-wifi-off\")},null,2),X(\"div\",lue,Re(K(Pd)?\"Connecting...\":\"Disconnected\"),1),X(\"div\",aue,\" Check your terminal or start a new server with `\"+Re(K(Zn)?`vitest --browser=${K(Zn).config.browser.name}`:\"vitest --ui\")+\"` \",1)],2)]))}}),uue={h:\"full\",flex:\"~ col\"},fue={\"flex-auto\":\"\",\"py-1\":\"\",\"bg-white\":\"\"},due=[\"src\"],$y=rt({__name:\"Coverage\",props:{src:{}},setup(e){return(t,r)=>(ie(),ve(\"div\",uue,[r[0]||(r[0]=X(\"div\",{p:\"3\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},[X(\"div\",{class:\"i-carbon:folder-details-reference\"}),X(\"span\",{\"pl-1\":\"\",\"font-bold\":\"\",\"text-sm\":\"\",\"flex-auto\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",truncate:\"\"},\"Coverage\")],-1)),X(\"div\",fue,[X(\"iframe\",{id:\"vitest-ui-coverage\",src:e.src},null,8,due)])]))}}),hue={bg:\"red500/10\",\"p-1\":\"\",\"mb-1\":\"\",\"mt-2\":\"\",rounded:\"\"},pue={\"font-bold\":\"\"},gue={key:0,class:\"scrolls\",text:\"xs\",\"font-mono\":\"\",\"mx-1\":\"\",\"my-2\":\"\",\"pb-2\":\"\",\"overflow-auto\":\"\"},mue=[\"font-bold\"],vue={text:\"red500/70\"},yue={key:1,text:\"sm\",\"mb-2\":\"\"},bue={\"font-bold\":\"\"},wue={key:2,text:\"sm\",\"mb-2\":\"\"},xue={\"font-bold\":\"\"},kue=rt({__name:\"ErrorEntry\",props:{error:{}},setup(e){return(t,r)=>(ie(),ve(nt,null,[X(\"h4\",hue,[X(\"span\",pue,[Qe(Re(e.error.name||e.error.nameStr||\"Unknown Error\"),1),e.error.message?(ie(),ve(nt,{key:0},[Qe(\":\")],64)):He(\"\",!0)]),Qe(\" \"+Re(e.error.message),1)]),e.error.stacks?.length?(ie(),ve(\"p\",gue,[(ie(!0),ve(nt,null,$n(e.error.stacks,(o,s)=>(ie(),ve(\"span\",{key:s,\"whitespace-pre\":\"\",\"font-bold\":s===0?\"\":null},[Qe(\"❯ \"+Re(o.method)+\" \"+Re(o.file)+\":\",1),X(\"span\",vue,Re(o.line)+\":\"+Re(o.column),1),r[0]||(r[0]=X(\"br\",null,null,-1))],8,mue))),128))])):He(\"\",!0),e.error.VITEST_TEST_PATH?(ie(),ve(\"p\",yue,[r[1]||(r[1]=Qe(\" This error originated in \",-1)),X(\"span\",bue,Re(e.error.VITEST_TEST_PATH),1),r[2]||(r[2]=Qe(\" test file. It doesn't mean the error was thrown inside the file itself, but while it was running. \",-1))])):He(\"\",!0),e.error.VITEST_TEST_NAME?(ie(),ve(\"div\",wue,[r[3]||(r[3]=Qe(\" The latest test that might've caused the error is \",-1)),X(\"span\",xue,Re(e.error.VITEST_TEST_NAME),1),r[4]||(r[4]=Qe(\". It might mean one of the following:\",-1)),r[5]||(r[5]=X(\"br\",null,null,-1)),r[6]||(r[6]=X(\"ul\",null,[X(\"li\",null,\" The error was thrown, while Vitest was running this test. \"),X(\"li\",null,\" If the error occurred after the test had been completed, this was the last documented test before it was thrown. \")],-1))])):He(\"\",!0)],64))}}),Sue={\"data-testid\":\"test-files-entry\",grid:\"~ cols-[min-content_1fr_min-content]\",\"items-center\":\"\",gap:\"x-2 y-3\",p:\"x4\",relative:\"\",\"font-light\":\"\",\"w-80\":\"\",op80:\"\"},_ue={class:\"number\",\"data-testid\":\"num-files\"},Tue={class:\"number\"},Cue={class:\"number\",\"text-red5\":\"\"},Eue={class:\"number\",\"text-red5\":\"\"},Aue={class:\"number\",\"text-red5\":\"\"},Lue={class:\"number\",\"data-testid\":\"run-time\"},Mue={key:0,bg:\"red500/10\",text:\"red500\",p:\"x3 y2\",\"max-w-xl\":\"\",\"m-2\":\"\",rounded:\"\"},Nue={text:\"sm\",\"font-thin\":\"\",\"mb-2\":\"\",\"data-testid\":\"unhandled-errors\"},Oue={\"data-testid\":\"unhandled-errors-details\",class:\"scrolls unhandled-errors\",text:\"sm\",\"font-thin\":\"\",\"pe-2.5\":\"\",\"open:max-h-52\":\"\",\"overflow-auto\":\"\"},Pue=rt({__name:\"TestFilesEntry\",setup(e){return(t,r)=>(ie(),ve(nt,null,[X(\"div\",Sue,[r[8]||(r[8]=X(\"div\",{\"i-carbon-document\":\"\"},null,-1)),r[9]||(r[9]=X(\"div\",null,\"Files\",-1)),X(\"div\",_ue,Re(K(Oe).summary.files),1),K(Oe).summary.filesSuccess?(ie(),ve(nt,{key:0},[r[0]||(r[0]=X(\"div\",{\"i-carbon-checkmark\":\"\"},null,-1)),r[1]||(r[1]=X(\"div\",null,\"Pass\",-1)),X(\"div\",Tue,Re(K(Oe).summary.filesSuccess),1)],64)):He(\"\",!0),K(Oe).summary.filesFailed?(ie(),ve(nt,{key:1},[r[2]||(r[2]=X(\"div\",{\"i-carbon-close\":\"\"},null,-1)),r[3]||(r[3]=X(\"div\",null,\" Fail \",-1)),X(\"div\",Cue,Re(K(Oe).summary.filesFailed),1)],64)):He(\"\",!0),K(Oe).summary.filesSnapshotFailed?(ie(),ve(nt,{key:2},[r[4]||(r[4]=X(\"div\",{\"i-carbon-compare\":\"\"},null,-1)),r[5]||(r[5]=X(\"div\",null,\" Snapshot Fail \",-1)),X(\"div\",Eue,Re(K(Oe).summary.filesSnapshotFailed),1)],64)):He(\"\",!0),K(eo).length?(ie(),ve(nt,{key:3},[r[6]||(r[6]=X(\"div\",{\"i-carbon-checkmark-outline-error\":\"\"},null,-1)),r[7]||(r[7]=X(\"div\",null,\" Errors \",-1)),X(\"div\",Aue,Re(K(eo).length),1)],64)):He(\"\",!0),r[10]||(r[10]=X(\"div\",{\"i-carbon-timer\":\"\"},null,-1)),r[11]||(r[11]=X(\"div\",null,\"Time\",-1)),X(\"div\",Lue,Re(K(Oe).summary.time),1)]),K(eo).length?(ie(),ve(\"div\",Mue,[r[15]||(r[15]=X(\"h3\",{\"text-center\":\"\",\"mb-2\":\"\"},\" Unhandled Errors \",-1)),X(\"p\",Nue,[Qe(\" Vitest caught \"+Re(K(eo).length)+\" error\"+Re(K(eo).length>1?\"s\":\"\")+\" during the test run.\",1),r[12]||(r[12]=X(\"br\",null,null,-1)),r[13]||(r[13]=Qe(\" This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected. \",-1))]),X(\"details\",Oue,[r[14]||(r[14]=X(\"summary\",{\"font-bold\":\"\",\"cursor-pointer\":\"\"},\" Errors \",-1)),(ie(!0),ve(nt,null,$n(K(eo),(o,s)=>(ie(),Ve(kue,{key:s,error:o},null,8,[\"error\"]))),128))])])):He(\"\",!0)],64))}}),Rue=Ni(Pue,[[\"__scopeId\",\"data-v-1bd0f2ea\"]]),$ue={\"p-2\":\"\",\"text-center\":\"\",flex:\"\"},Iue={\"text-4xl\":\"\",\"min-w-2em\":\"\"},Due={\"text-md\":\"\"},Bl=rt({__name:\"DashboardEntry\",setup(e){return(t,r)=>(ie(),ve(\"div\",$ue,[X(\"div\",null,[X(\"div\",Iue,[Dt(t.$slots,\"body\")]),X(\"div\",Due,[Dt(t.$slots,\"header\")])])]))}}),zue={flex:\"~ wrap\",\"justify-evenly\":\"\",\"gap-2\":\"\",p:\"x-4\",relative:\"\"},Fue=rt({__name:\"TestsEntry\",setup(e){function t(r){it.success=!1,it.failed=!1,it.skipped=!1,r!==\"total\"&&(it[r]=!0)}return(r,o)=>(ie(),ve(\"div\",zue,[Ne(Bl,{\"text-green5\":\"\",\"data-testid\":\"pass-entry\",\"cursor-pointer\":\"\",hover:\"op80\",onClick:o[0]||(o[0]=s=>t(\"success\"))},{header:We(()=>[...o[4]||(o[4]=[Qe(\" Pass \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.testsSuccess),1)]),_:1}),Ne(Bl,{class:ot({\"text-red5\":K(Oe).summary.testsFailed,op50:!K(Oe).summary.testsFailed}),\"data-testid\":\"fail-entry\",\"cursor-pointer\":\"\",hover:\"op80\",onClick:o[1]||(o[1]=s=>t(\"failed\"))},{header:We(()=>[...o[5]||(o[5]=[Qe(\" Fail \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.testsFailed),1)]),_:1},8,[\"class\"]),K(Oe).summary.testsSkipped?(ie(),Ve(Bl,{key:0,op50:\"\",\"data-testid\":\"skipped-entry\",\"cursor-pointer\":\"\",hover:\"op80\",onClick:o[2]||(o[2]=s=>t(\"skipped\"))},{header:We(()=>[...o[6]||(o[6]=[Qe(\" Skip \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.testsSkipped),1)]),_:1})):He(\"\",!0),K(Oe).summary.testsTodo?(ie(),Ve(Bl,{key:1,op50:\"\",\"data-testid\":\"todo-entry\"},{header:We(()=>[...o[7]||(o[7]=[Qe(\" Todo \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.testsTodo),1)]),_:1})):He(\"\",!0),Ne(Bl,{tail:!0,\"data-testid\":\"total-entry\",\"cursor-pointer\":\"\",hover:\"op80\",onClick:o[3]||(o[3]=s=>t(\"total\"))},{header:We(()=>[...o[8]||(o[8]=[Qe(\" Total \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.totalTests),1)]),_:1})]))}}),Hue={\"gap-0\":\"\",flex:\"~ col gap-4\",\"h-full\":\"\",\"justify-center\":\"\",\"items-center\":\"\"},Bue={key:0,class:\"text-gray-5\"},Wue={\"aria-labelledby\":\"tests\",m:\"y-4 x-2\"},que=rt({__name:\"TestsFilesContainer\",setup(e){return(t,r)=>(ie(),ve(\"div\",Hue,[K(Oe).summary.files===0&&K(Ms)?(ie(),ve(\"div\",Bue,\" No tests found \")):He(\"\",!0),X(\"section\",Wue,[Ne(Fue)]),Ne(Rue)]))}}),jue={h:\"full\",flex:\"~ col\"},Uue={class:\"scrolls\",\"flex-auto\":\"\",\"py-1\":\"\"},Iy=rt({__name:\"Dashboard\",setup(e){return(t,r)=>(ie(),ve(\"div\",jue,[r[0]||(r[0]=X(\"div\",{p:\"3\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},[X(\"div\",{class:\"i-carbon-dashboard\"}),X(\"span\",{\"pl-1\":\"\",\"font-bold\":\"\",\"text-sm\":\"\",\"flex-auto\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",truncate:\"\"},\"Dashboard\")],-1)),X(\"div\",Uue,[Ne(que)])]))}});function Vue(e,t){let r;return(...o)=>{r!==void 0&&clearTimeout(r),r=setTimeout(()=>e(...o),t)}}var bh=\"http://www.w3.org/1999/xhtml\";const Dy={svg:\"http://www.w3.org/2000/svg\",xhtml:bh,xlink:\"http://www.w3.org/1999/xlink\",xml:\"http://www.w3.org/XML/1998/namespace\",xmlns:\"http://www.w3.org/2000/xmlns/\"};function ff(e){var t=e+=\"\",r=t.indexOf(\":\");return r>=0&&(t=e.slice(0,r))!==\"xmlns\"&&(e=e.slice(r+1)),Dy.hasOwnProperty(t)?{space:Dy[t],local:e}:e}function Gue(e){return function(){var t=this.ownerDocument,r=this.namespaceURI;return r===bh&&t.documentElement.namespaceURI===bh?t.createElement(e):t.createElementNS(r,e)}}function Kue(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function Ex(e){var t=ff(e);return(t.local?Kue:Gue)(t)}function Xue(){}function Tp(e){return e==null?Xue:function(){return this.querySelector(e)}}function Yue(e){typeof e!=\"function\"&&(e=Tp(e));for(var t=this._groups,r=t.length,o=new Array(r),s=0;s<r;++s)for(var c=t[s],f=c.length,d=o[s]=new Array(f),h,p,g=0;g<f;++g)(h=c[g])&&(p=e.call(h,h.__data__,g,c))&&(\"__data__\"in h&&(p.__data__=h.__data__),d[g]=p);return new lr(o,this._parents)}function Zue(e){return e==null?[]:Array.isArray(e)?e:Array.from(e)}function Jue(){return[]}function Ax(e){return e==null?Jue:function(){return this.querySelectorAll(e)}}function Que(e){return function(){return Zue(e.apply(this,arguments))}}function efe(e){typeof e==\"function\"?e=Que(e):e=Ax(e);for(var t=this._groups,r=t.length,o=[],s=[],c=0;c<r;++c)for(var f=t[c],d=f.length,h,p=0;p<d;++p)(h=f[p])&&(o.push(e.call(h,h.__data__,p,f)),s.push(h));return new lr(o,s)}function Lx(e){return function(){return this.matches(e)}}function Mx(e){return function(t){return t.matches(e)}}var tfe=Array.prototype.find;function nfe(e){return function(){return tfe.call(this.children,e)}}function rfe(){return this.firstElementChild}function ife(e){return this.select(e==null?rfe:nfe(typeof e==\"function\"?e:Mx(e)))}var ofe=Array.prototype.filter;function sfe(){return Array.from(this.children)}function lfe(e){return function(){return ofe.call(this.children,e)}}function afe(e){return this.selectAll(e==null?sfe:lfe(typeof e==\"function\"?e:Mx(e)))}function cfe(e){typeof e!=\"function\"&&(e=Lx(e));for(var t=this._groups,r=t.length,o=new Array(r),s=0;s<r;++s)for(var c=t[s],f=c.length,d=o[s]=[],h,p=0;p<f;++p)(h=c[p])&&e.call(h,h.__data__,p,c)&&d.push(h);return new lr(o,this._parents)}function Nx(e){return new Array(e.length)}function ufe(){return new lr(this._enter||this._groups.map(Nx),this._parents)}function Au(e,t){this.ownerDocument=e.ownerDocument,this.namespaceURI=e.namespaceURI,this._next=null,this._parent=e,this.__data__=t}Au.prototype={constructor:Au,appendChild:function(e){return this._parent.insertBefore(e,this._next)},insertBefore:function(e,t){return this._parent.insertBefore(e,t)},querySelector:function(e){return this._parent.querySelector(e)},querySelectorAll:function(e){return this._parent.querySelectorAll(e)}};function ffe(e){return function(){return e}}function dfe(e,t,r,o,s,c){for(var f=0,d,h=t.length,p=c.length;f<p;++f)(d=t[f])?(d.__data__=c[f],o[f]=d):r[f]=new Au(e,c[f]);for(;f<h;++f)(d=t[f])&&(s[f]=d)}function hfe(e,t,r,o,s,c,f){var d,h,p=new Map,g=t.length,v=c.length,b=new Array(g),w;for(d=0;d<g;++d)(h=t[d])&&(b[d]=w=f.call(h,h.__data__,d,t)+\"\",p.has(w)?s[d]=h:p.set(w,h));for(d=0;d<v;++d)w=f.call(e,c[d],d,c)+\"\",(h=p.get(w))?(o[d]=h,h.__data__=c[d],p.delete(w)):r[d]=new Au(e,c[d]);for(d=0;d<g;++d)(h=t[d])&&p.get(b[d])===h&&(s[d]=h)}function pfe(e){return e.__data__}function gfe(e,t){if(!arguments.length)return Array.from(this,pfe);var r=t?hfe:dfe,o=this._parents,s=this._groups;typeof e!=\"function\"&&(e=ffe(e));for(var c=s.length,f=new Array(c),d=new Array(c),h=new Array(c),p=0;p<c;++p){var g=o[p],v=s[p],b=v.length,w=mfe(e.call(g,g&&g.__data__,p,o)),E=w.length,L=d[p]=new Array(E),P=f[p]=new Array(E),M=h[p]=new Array(b);r(g,v,L,P,M,w,t);for(var R=0,I=0,_,$;R<E;++R)if(_=L[R]){for(R>=I&&(I=R+1);!($=P[I])&&++I<E;);_._next=$||null}}return f=new lr(f,o),f._enter=d,f._exit=h,f}function mfe(e){return typeof e==\"object\"&&\"length\"in e?e:Array.from(e)}function vfe(){return new lr(this._exit||this._groups.map(Nx),this._parents)}function yfe(e,t,r){var o=this.enter(),s=this,c=this.exit();return typeof e==\"function\"?(o=e(o),o&&(o=o.selection())):o=o.append(e+\"\"),t!=null&&(s=t(s),s&&(s=s.selection())),r==null?c.remove():r(c),o&&s?o.merge(s).order():s}function bfe(e){for(var t=e.selection?e.selection():e,r=this._groups,o=t._groups,s=r.length,c=o.length,f=Math.min(s,c),d=new Array(s),h=0;h<f;++h)for(var p=r[h],g=o[h],v=p.length,b=d[h]=new Array(v),w,E=0;E<v;++E)(w=p[E]||g[E])&&(b[E]=w);for(;h<s;++h)d[h]=r[h];return new lr(d,this._parents)}function wfe(){for(var e=this._groups,t=-1,r=e.length;++t<r;)for(var o=e[t],s=o.length-1,c=o[s],f;--s>=0;)(f=o[s])&&(c&&f.compareDocumentPosition(c)^4&&c.parentNode.insertBefore(f,c),c=f);return this}function xfe(e){e||(e=kfe);function t(v,b){return v&&b?e(v.__data__,b.__data__):!v-!b}for(var r=this._groups,o=r.length,s=new Array(o),c=0;c<o;++c){for(var f=r[c],d=f.length,h=s[c]=new Array(d),p,g=0;g<d;++g)(p=f[g])&&(h[g]=p);h.sort(t)}return new lr(s,this._parents).order()}function kfe(e,t){return e<t?-1:e>t?1:e>=t?0:NaN}function Sfe(){var e=arguments[0];return arguments[0]=this,e.apply(null,arguments),this}function _fe(){return Array.from(this)}function Tfe(){for(var e=this._groups,t=0,r=e.length;t<r;++t)for(var o=e[t],s=0,c=o.length;s<c;++s){var f=o[s];if(f)return f}return null}function Cfe(){let e=0;for(const t of this)++e;return e}function Efe(){return!this.node()}function Afe(e){for(var t=this._groups,r=0,o=t.length;r<o;++r)for(var s=t[r],c=0,f=s.length,d;c<f;++c)(d=s[c])&&e.call(d,d.__data__,c,s);return this}function Lfe(e){return function(){this.removeAttribute(e)}}function Mfe(e){return function(){this.removeAttributeNS(e.space,e.local)}}function Nfe(e,t){return function(){this.setAttribute(e,t)}}function Ofe(e,t){return function(){this.setAttributeNS(e.space,e.local,t)}}function Pfe(e,t){return function(){var r=t.apply(this,arguments);r==null?this.removeAttribute(e):this.setAttribute(e,r)}}function Rfe(e,t){return function(){var r=t.apply(this,arguments);r==null?this.removeAttributeNS(e.space,e.local):this.setAttributeNS(e.space,e.local,r)}}function $fe(e,t){var r=ff(e);if(arguments.length<2){var o=this.node();return r.local?o.getAttributeNS(r.space,r.local):o.getAttribute(r)}return this.each((t==null?r.local?Mfe:Lfe:typeof t==\"function\"?r.local?Rfe:Pfe:r.local?Ofe:Nfe)(r,t))}function Ox(e){return e.ownerDocument&&e.ownerDocument.defaultView||e.document&&e||e.defaultView}function Ife(e){return function(){this.style.removeProperty(e)}}function Dfe(e,t,r){return function(){this.style.setProperty(e,t,r)}}function zfe(e,t,r){return function(){var o=t.apply(this,arguments);o==null?this.style.removeProperty(e):this.style.setProperty(e,o,r)}}function Ffe(e,t,r){return arguments.length>1?this.each((t==null?Ife:typeof t==\"function\"?zfe:Dfe)(e,t,r??\"\")):el(this.node(),e)}function el(e,t){return e.style.getPropertyValue(t)||Ox(e).getComputedStyle(e,null).getPropertyValue(t)}function Hfe(e){return function(){delete this[e]}}function Bfe(e,t){return function(){this[e]=t}}function Wfe(e,t){return function(){var r=t.apply(this,arguments);r==null?delete this[e]:this[e]=r}}function qfe(e,t){return arguments.length>1?this.each((t==null?Hfe:typeof t==\"function\"?Wfe:Bfe)(e,t)):this.node()[e]}function Px(e){return e.trim().split(/^|\\s+/)}function Cp(e){return e.classList||new Rx(e)}function Rx(e){this._node=e,this._names=Px(e.getAttribute(\"class\")||\"\")}Rx.prototype={add:function(e){var t=this._names.indexOf(e);t<0&&(this._names.push(e),this._node.setAttribute(\"class\",this._names.join(\" \")))},remove:function(e){var t=this._names.indexOf(e);t>=0&&(this._names.splice(t,1),this._node.setAttribute(\"class\",this._names.join(\" \")))},contains:function(e){return this._names.indexOf(e)>=0}};function $x(e,t){for(var r=Cp(e),o=-1,s=t.length;++o<s;)r.add(t[o])}function Ix(e,t){for(var r=Cp(e),o=-1,s=t.length;++o<s;)r.remove(t[o])}function jfe(e){return function(){$x(this,e)}}function Ufe(e){return function(){Ix(this,e)}}function Vfe(e,t){return function(){(t.apply(this,arguments)?$x:Ix)(this,e)}}function Gfe(e,t){var r=Px(e+\"\");if(arguments.length<2){for(var o=Cp(this.node()),s=-1,c=r.length;++s<c;)if(!o.contains(r[s]))return!1;return!0}return this.each((typeof t==\"function\"?Vfe:t?jfe:Ufe)(r,t))}function Kfe(){this.textContent=\"\"}function Xfe(e){return function(){this.textContent=e}}function Yfe(e){return function(){var t=e.apply(this,arguments);this.textContent=t??\"\"}}function Zfe(e){return arguments.length?this.each(e==null?Kfe:(typeof e==\"function\"?Yfe:Xfe)(e)):this.node().textContent}function Jfe(){this.innerHTML=\"\"}function Qfe(e){return function(){this.innerHTML=e}}function ede(e){return function(){var t=e.apply(this,arguments);this.innerHTML=t??\"\"}}function tde(e){return arguments.length?this.each(e==null?Jfe:(typeof e==\"function\"?ede:Qfe)(e)):this.node().innerHTML}function nde(){this.nextSibling&&this.parentNode.appendChild(this)}function rde(){return this.each(nde)}function ide(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function ode(){return this.each(ide)}function sde(e){var t=typeof e==\"function\"?e:Ex(e);return this.select(function(){return this.appendChild(t.apply(this,arguments))})}function lde(){return null}function ade(e,t){var r=typeof e==\"function\"?e:Ex(e),o=t==null?lde:typeof t==\"function\"?t:Tp(t);return this.select(function(){return this.insertBefore(r.apply(this,arguments),o.apply(this,arguments)||null)})}function cde(){var e=this.parentNode;e&&e.removeChild(this)}function ude(){return this.each(cde)}function fde(){var e=this.cloneNode(!1),t=this.parentNode;return t?t.insertBefore(e,this.nextSibling):e}function dde(){var e=this.cloneNode(!0),t=this.parentNode;return t?t.insertBefore(e,this.nextSibling):e}function hde(e){return this.select(e?dde:fde)}function pde(e){return arguments.length?this.property(\"__data__\",e):this.node().__data__}function gde(e){return function(t){e.call(this,t,this.__data__)}}function mde(e){return e.trim().split(/^|\\s+/).map(function(t){var r=\"\",o=t.indexOf(\".\");return o>=0&&(r=t.slice(o+1),t=t.slice(0,o)),{type:t,name:r}})}function vde(e){return function(){var t=this.__on;if(t){for(var r=0,o=-1,s=t.length,c;r<s;++r)c=t[r],(!e.type||c.type===e.type)&&c.name===e.name?this.removeEventListener(c.type,c.listener,c.options):t[++o]=c;++o?t.length=o:delete this.__on}}}function yde(e,t,r){return function(){var o=this.__on,s,c=gde(t);if(o){for(var f=0,d=o.length;f<d;++f)if((s=o[f]).type===e.type&&s.name===e.name){this.removeEventListener(s.type,s.listener,s.options),this.addEventListener(s.type,s.listener=c,s.options=r),s.value=t;return}}this.addEventListener(e.type,c,r),s={type:e.type,name:e.name,value:t,listener:c,options:r},o?o.push(s):this.__on=[s]}}function bde(e,t,r){var o=mde(e+\"\"),s,c=o.length,f;if(arguments.length<2){var d=this.node().__on;if(d){for(var h=0,p=d.length,g;h<p;++h)for(s=0,g=d[h];s<c;++s)if((f=o[s]).type===g.type&&f.name===g.name)return g.value}return}for(d=t?yde:vde,s=0;s<c;++s)this.each(d(o[s],t,r));return this}function Dx(e,t,r){var o=Ox(e),s=o.CustomEvent;typeof s==\"function\"?s=new s(t,r):(s=o.document.createEvent(\"Event\"),r?(s.initEvent(t,r.bubbles,r.cancelable),s.detail=r.detail):s.initEvent(t,!1,!1)),e.dispatchEvent(s)}function wde(e,t){return function(){return Dx(this,e,t)}}function xde(e,t){return function(){return Dx(this,e,t.apply(this,arguments))}}function kde(e,t){return this.each((typeof t==\"function\"?xde:wde)(e,t))}function*Sde(){for(var e=this._groups,t=0,r=e.length;t<r;++t)for(var o=e[t],s=0,c=o.length,f;s<c;++s)(f=o[s])&&(yield f)}var zx=[null];function lr(e,t){this._groups=e,this._parents=t}function ja(){return new lr([[document.documentElement]],zx)}function _de(){return this}lr.prototype=ja.prototype={constructor:lr,select:Yue,selectAll:efe,selectChild:ife,selectChildren:afe,filter:cfe,data:gfe,enter:ufe,exit:vfe,join:yfe,merge:bfe,selection:_de,order:wfe,sort:xfe,call:Sfe,nodes:_fe,node:Tfe,size:Cfe,empty:Efe,each:Afe,attr:$fe,style:Ffe,property:qfe,classed:Gfe,text:Zfe,html:tde,raise:rde,lower:ode,append:sde,insert:ade,remove:ude,clone:hde,datum:pde,on:bde,dispatch:kde,[Symbol.iterator]:Sde};function Kn(e){return typeof e==\"string\"?new lr([[document.querySelector(e)]],[document.documentElement]):new lr([[e]],zx)}function Tde(e){let t;for(;t=e.sourceEvent;)e=t;return e}function vi(e,t){if(e=Tde(e),t===void 0&&(t=e.currentTarget),t){var r=t.ownerSVGElement||t;if(r.createSVGPoint){var o=r.createSVGPoint();return o.x=e.clientX,o.y=e.clientY,o=o.matrixTransform(t.getScreenCTM().inverse()),[o.x,o.y]}if(t.getBoundingClientRect){var s=t.getBoundingClientRect();return[e.clientX-s.left-t.clientLeft,e.clientY-s.top-t.clientTop]}}return[e.pageX,e.pageY]}var tl=class gi{x;y;static of([t,r]){return new gi(t,r)}constructor(t,r){this.x=t,this.y=r}add(t){return new gi(this.x+t.x,this.y+t.y)}subtract(t){return new gi(this.x-t.x,this.y-t.y)}multiply(t){return new gi(this.x*t,this.y*t)}divide(t){return new gi(this.x/t,this.y/t)}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-t.x*this.y}hadamard(t){return new gi(this.x*t.x,this.y*t.y)}length(){return Math.sqrt(this.x**2+this.y**2)}normalize(){const t=this.length();return new gi(this.x/t,this.y/t)}rotateByRadians(t){const r=Math.cos(t),o=Math.sin(t);return new gi(this.x*r-this.y*o,this.x*o+this.y*r)}rotateByDegrees(t){return this.rotateByRadians(t*Math.PI/180)}},Cde={value:()=>{}};function Ua(){for(var e=0,t=arguments.length,r={},o;e<t;++e){if(!(o=arguments[e]+\"\")||o in r||/[\\s.]/.test(o))throw new Error(\"illegal type: \"+o);r[o]=[]}return new Zc(r)}function Zc(e){this._=e}function Ede(e,t){return e.trim().split(/^|\\s+/).map(function(r){var o=\"\",s=r.indexOf(\".\");if(s>=0&&(o=r.slice(s+1),r=r.slice(0,s)),r&&!t.hasOwnProperty(r))throw new Error(\"unknown type: \"+r);return{type:r,name:o}})}Zc.prototype=Ua.prototype={constructor:Zc,on:function(e,t){var r=this._,o=Ede(e+\"\",r),s,c=-1,f=o.length;if(arguments.length<2){for(;++c<f;)if((s=(e=o[c]).type)&&(s=Ade(r[s],e.name)))return s;return}if(t!=null&&typeof t!=\"function\")throw new Error(\"invalid callback: \"+t);for(;++c<f;)if(s=(e=o[c]).type)r[s]=zy(r[s],e.name,t);else if(t==null)for(s in r)r[s]=zy(r[s],e.name,null);return this},copy:function(){var e={},t=this._;for(var r in t)e[r]=t[r].slice();return new Zc(e)},call:function(e,t){if((s=arguments.length-2)>0)for(var r=new Array(s),o=0,s,c;o<s;++o)r[o]=arguments[o+2];if(!this._.hasOwnProperty(e))throw new Error(\"unknown type: \"+e);for(c=this._[e],o=0,s=c.length;o<s;++o)c[o].value.apply(t,r)},apply:function(e,t,r){if(!this._.hasOwnProperty(e))throw new Error(\"unknown type: \"+e);for(var o=this._[e],s=0,c=o.length;s<c;++s)o[s].value.apply(t,r)}};function Ade(e,t){for(var r=0,o=e.length,s;r<o;++r)if((s=e[r]).name===t)return s.value}function zy(e,t,r){for(var o=0,s=e.length;o<s;++o)if(e[o].name===t){e[o]=Cde,e=e.slice(0,o).concat(e.slice(o+1));break}return r!=null&&e.push({name:t,value:r}),e}const Lde={passive:!1},Ta={capture:!0,passive:!1};function Rd(e){e.stopImmediatePropagation()}function js(e){e.preventDefault(),e.stopImmediatePropagation()}function Fx(e){var t=e.document.documentElement,r=Kn(e).on(\"dragstart.drag\",js,Ta);\"onselectstart\"in t?r.on(\"selectstart.drag\",js,Ta):(t.__noselect=t.style.MozUserSelect,t.style.MozUserSelect=\"none\")}function Hx(e,t){var r=e.document.documentElement,o=Kn(e).on(\"dragstart.drag\",null);t&&(o.on(\"click.drag\",js,Ta),setTimeout(function(){o.on(\"click.drag\",null)},0)),\"onselectstart\"in r?o.on(\"selectstart.drag\",null):(r.style.MozUserSelect=r.__noselect,delete r.__noselect)}const Ic=e=>()=>e;function wh(e,{sourceEvent:t,subject:r,target:o,identifier:s,active:c,x:f,y:d,dx:h,dy:p,dispatch:g}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},subject:{value:r,enumerable:!0,configurable:!0},target:{value:o,enumerable:!0,configurable:!0},identifier:{value:s,enumerable:!0,configurable:!0},active:{value:c,enumerable:!0,configurable:!0},x:{value:f,enumerable:!0,configurable:!0},y:{value:d,enumerable:!0,configurable:!0},dx:{value:h,enumerable:!0,configurable:!0},dy:{value:p,enumerable:!0,configurable:!0},_:{value:g}})}wh.prototype.on=function(){var e=this._.on.apply(this._,arguments);return e===this._?this:e};function Mde(e){return!e.ctrlKey&&!e.button}function Nde(){return this.parentNode}function Ode(e,t){return t??{x:e.x,y:e.y}}function Pde(){return navigator.maxTouchPoints||\"ontouchstart\"in this}function Rde(){var e=Mde,t=Nde,r=Ode,o=Pde,s={},c=Ua(\"start\",\"drag\",\"end\"),f=0,d,h,p,g,v=0;function b(_){_.on(\"mousedown.drag\",w).filter(o).on(\"touchstart.drag\",P).on(\"touchmove.drag\",M,Lde).on(\"touchend.drag touchcancel.drag\",R).style(\"touch-action\",\"none\").style(\"-webkit-tap-highlight-color\",\"rgba(0,0,0,0)\")}function w(_,$){if(!(g||!e.call(this,_,$))){var W=I(this,t.call(this,_,$),_,$,\"mouse\");W&&(Kn(_.view).on(\"mousemove.drag\",E,Ta).on(\"mouseup.drag\",L,Ta),Fx(_.view),Rd(_),p=!1,d=_.clientX,h=_.clientY,W(\"start\",_))}}function E(_){if(js(_),!p){var $=_.clientX-d,W=_.clientY-h;p=$*$+W*W>v}s.mouse(\"drag\",_)}function L(_){Kn(_.view).on(\"mousemove.drag mouseup.drag\",null),Hx(_.view,p),js(_),s.mouse(\"end\",_)}function P(_,$){if(e.call(this,_,$)){var W=_.changedTouches,ne=t.call(this,_,$),ee=W.length,Z,G;for(Z=0;Z<ee;++Z)(G=I(this,ne,_,$,W[Z].identifier,W[Z]))&&(Rd(_),G(\"start\",_,W[Z]))}}function M(_){var $=_.changedTouches,W=$.length,ne,ee;for(ne=0;ne<W;++ne)(ee=s[$[ne].identifier])&&(js(_),ee(\"drag\",_,$[ne]))}function R(_){var $=_.changedTouches,W=$.length,ne,ee;for(g&&clearTimeout(g),g=setTimeout(function(){g=null},500),ne=0;ne<W;++ne)(ee=s[$[ne].identifier])&&(Rd(_),ee(\"end\",_,$[ne]))}function I(_,$,W,ne,ee,Z){var G=c.copy(),j=vi(Z||W,$),N,O,C;if((C=r.call(_,new wh(\"beforestart\",{sourceEvent:W,target:b,identifier:ee,active:f,x:j[0],y:j[1],dx:0,dy:0,dispatch:G}),ne))!=null)return N=C.x-j[0]||0,O=C.y-j[1]||0,function k(z,B,ce){var be=j,Se;switch(z){case\"start\":s[ee]=k,Se=f++;break;case\"end\":delete s[ee],--f;case\"drag\":j=vi(ce||B,$),Se=f;break}G.call(z,_,new wh(z,{sourceEvent:B,subject:C,target:b,identifier:ee,active:Se,x:j[0]+N,y:j[1]+O,dx:j[0]-be[0],dy:j[1]-be[1],dispatch:G}),ne)}}return b.filter=function(_){return arguments.length?(e=typeof _==\"function\"?_:Ic(!!_),b):e},b.container=function(_){return arguments.length?(t=typeof _==\"function\"?_:Ic(_),b):t},b.subject=function(_){return arguments.length?(r=typeof _==\"function\"?_:Ic(_),b):r},b.touchable=function(_){return arguments.length?(o=typeof _==\"function\"?_:Ic(!!_),b):o},b.on=function(){var _=c.on.apply(c,arguments);return _===c?b:_},b.clickDistance=function(_){return arguments.length?(v=(_=+_)*_,b):Math.sqrt(v)},b}function Ep(e,t,r){e.prototype=t.prototype=r,r.constructor=e}function Bx(e,t){var r=Object.create(e.prototype);for(var o in t)r[o]=t[o];return r}function Va(){}var Ca=.7,Lu=1/Ca,Us=\"\\\\s*([+-]?\\\\d+)\\\\s*\",Ea=\"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)\\\\s*\",Jr=\"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)%\\\\s*\",$de=/^#([0-9a-f]{3,8})$/,Ide=new RegExp(`^rgb\\\\(${Us},${Us},${Us}\\\\)$`),Dde=new RegExp(`^rgb\\\\(${Jr},${Jr},${Jr}\\\\)$`),zde=new RegExp(`^rgba\\\\(${Us},${Us},${Us},${Ea}\\\\)$`),Fde=new RegExp(`^rgba\\\\(${Jr},${Jr},${Jr},${Ea}\\\\)$`),Hde=new RegExp(`^hsl\\\\(${Ea},${Jr},${Jr}\\\\)$`),Bde=new RegExp(`^hsla\\\\(${Ea},${Jr},${Jr},${Ea}\\\\)$`),Fy={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};Ep(Va,Aa,{copy(e){return Object.assign(new this.constructor,this,e)},displayable(){return this.rgb().displayable()},hex:Hy,formatHex:Hy,formatHex8:Wde,formatHsl:qde,formatRgb:By,toString:By});function Hy(){return this.rgb().formatHex()}function Wde(){return this.rgb().formatHex8()}function qde(){return Wx(this).formatHsl()}function By(){return this.rgb().formatRgb()}function Aa(e){var t,r;return e=(e+\"\").trim().toLowerCase(),(t=$de.exec(e))?(r=t[1].length,t=parseInt(t[1],16),r===6?Wy(t):r===3?new Yn(t>>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):r===8?Dc(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):r===4?Dc(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=Ide.exec(e))?new Yn(t[1],t[2],t[3],1):(t=Dde.exec(e))?new Yn(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=zde.exec(e))?Dc(t[1],t[2],t[3],t[4]):(t=Fde.exec(e))?Dc(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=Hde.exec(e))?Uy(t[1],t[2]/100,t[3]/100,1):(t=Bde.exec(e))?Uy(t[1],t[2]/100,t[3]/100,t[4]):Fy.hasOwnProperty(e)?Wy(Fy[e]):e===\"transparent\"?new Yn(NaN,NaN,NaN,0):null}function Wy(e){return new Yn(e>>16&255,e>>8&255,e&255,1)}function Dc(e,t,r,o){return o<=0&&(e=t=r=NaN),new Yn(e,t,r,o)}function jde(e){return e instanceof Va||(e=Aa(e)),e?(e=e.rgb(),new Yn(e.r,e.g,e.b,e.opacity)):new Yn}function xh(e,t,r,o){return arguments.length===1?jde(e):new Yn(e,t,r,o??1)}function Yn(e,t,r,o){this.r=+e,this.g=+t,this.b=+r,this.opacity=+o}Ep(Yn,xh,Bx(Va,{brighter(e){return e=e==null?Lu:Math.pow(Lu,e),new Yn(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?Ca:Math.pow(Ca,e),new Yn(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new Yn(Vo(this.r),Vo(this.g),Vo(this.b),Mu(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:qy,formatHex:qy,formatHex8:Ude,formatRgb:jy,toString:jy}));function qy(){return`#${Bo(this.r)}${Bo(this.g)}${Bo(this.b)}`}function Ude(){return`#${Bo(this.r)}${Bo(this.g)}${Bo(this.b)}${Bo((isNaN(this.opacity)?1:this.opacity)*255)}`}function jy(){const e=Mu(this.opacity);return`${e===1?\"rgb(\":\"rgba(\"}${Vo(this.r)}, ${Vo(this.g)}, ${Vo(this.b)}${e===1?\")\":`, ${e})`}`}function Mu(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function Vo(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function Bo(e){return e=Vo(e),(e<16?\"0\":\"\")+e.toString(16)}function Uy(e,t,r,o){return o<=0?e=t=r=NaN:r<=0||r>=1?e=t=NaN:t<=0&&(e=NaN),new Mr(e,t,r,o)}function Wx(e){if(e instanceof Mr)return new Mr(e.h,e.s,e.l,e.opacity);if(e instanceof Va||(e=Aa(e)),!e)return new Mr;if(e instanceof Mr)return e;e=e.rgb();var t=e.r/255,r=e.g/255,o=e.b/255,s=Math.min(t,r,o),c=Math.max(t,r,o),f=NaN,d=c-s,h=(c+s)/2;return d?(t===c?f=(r-o)/d+(r<o)*6:r===c?f=(o-t)/d+2:f=(t-r)/d+4,d/=h<.5?c+s:2-c-s,f*=60):d=h>0&&h<1?0:f,new Mr(f,d,h,e.opacity)}function Vde(e,t,r,o){return arguments.length===1?Wx(e):new Mr(e,t,r,o??1)}function Mr(e,t,r,o){this.h=+e,this.s=+t,this.l=+r,this.opacity=+o}Ep(Mr,Vde,Bx(Va,{brighter(e){return e=e==null?Lu:Math.pow(Lu,e),new Mr(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?Ca:Math.pow(Ca,e),new Mr(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,r=this.l,o=r+(r<.5?r:1-r)*t,s=2*r-o;return new Yn($d(e>=240?e-240:e+120,s,o),$d(e,s,o),$d(e<120?e+240:e-120,s,o),this.opacity)},clamp(){return new Mr(Vy(this.h),zc(this.s),zc(this.l),Mu(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const e=Mu(this.opacity);return`${e===1?\"hsl(\":\"hsla(\"}${Vy(this.h)}, ${zc(this.s)*100}%, ${zc(this.l)*100}%${e===1?\")\":`, ${e})`}`}}));function Vy(e){return e=(e||0)%360,e<0?e+360:e}function zc(e){return Math.max(0,Math.min(1,e||0))}function $d(e,t,r){return(e<60?t+(r-t)*e/60:e<180?r:e<240?t+(r-t)*(240-e)/60:t)*255}const qx=e=>()=>e;function Gde(e,t){return function(r){return e+r*t}}function Kde(e,t,r){return e=Math.pow(e,r),t=Math.pow(t,r)-e,r=1/r,function(o){return Math.pow(e+o*t,r)}}function Xde(e){return(e=+e)==1?jx:function(t,r){return r-t?Kde(t,r,e):qx(isNaN(t)?r:t)}}function jx(e,t){var r=t-e;return r?Gde(e,r):qx(isNaN(e)?t:e)}const Gy=(function e(t){var r=Xde(t);function o(s,c){var f=r((s=xh(s)).r,(c=xh(c)).r),d=r(s.g,c.g),h=r(s.b,c.b),p=jx(s.opacity,c.opacity);return function(g){return s.r=f(g),s.g=d(g),s.b=h(g),s.opacity=p(g),s+\"\"}}return o.gamma=e,o})(1);function to(e,t){return e=+e,t=+t,function(r){return e*(1-r)+t*r}}var kh=/[-+]?(?:\\d+\\.?\\d*|\\.?\\d+)(?:[eE][-+]?\\d+)?/g,Id=new RegExp(kh.source,\"g\");function Yde(e){return function(){return e}}function Zde(e){return function(t){return e(t)+\"\"}}function Jde(e,t){var r=kh.lastIndex=Id.lastIndex=0,o,s,c,f=-1,d=[],h=[];for(e=e+\"\",t=t+\"\";(o=kh.exec(e))&&(s=Id.exec(t));)(c=s.index)>r&&(c=t.slice(r,c),d[f]?d[f]+=c:d[++f]=c),(o=o[0])===(s=s[0])?d[f]?d[f]+=s:d[++f]=s:(d[++f]=null,h.push({i:f,x:to(o,s)})),r=Id.lastIndex;return r<t.length&&(c=t.slice(r),d[f]?d[f]+=c:d[++f]=c),d.length<2?h[0]?Zde(h[0].x):Yde(t):(t=h.length,function(p){for(var g=0,v;g<t;++g)d[(v=h[g]).i]=v.x(p);return d.join(\"\")})}var Ky=180/Math.PI,Sh={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function Ux(e,t,r,o,s,c){var f,d,h;return(f=Math.sqrt(e*e+t*t))&&(e/=f,t/=f),(h=e*r+t*o)&&(r-=e*h,o-=t*h),(d=Math.sqrt(r*r+o*o))&&(r/=d,o/=d,h/=d),e*o<t*r&&(e=-e,t=-t,h=-h,f=-f),{translateX:s,translateY:c,rotate:Math.atan2(t,e)*Ky,skewX:Math.atan(h)*Ky,scaleX:f,scaleY:d}}var Fc;function Qde(e){const t=new(typeof DOMMatrix==\"function\"?DOMMatrix:WebKitCSSMatrix)(e+\"\");return t.isIdentity?Sh:Ux(t.a,t.b,t.c,t.d,t.e,t.f)}function ehe(e){return e==null||(Fc||(Fc=document.createElementNS(\"http://www.w3.org/2000/svg\",\"g\")),Fc.setAttribute(\"transform\",e),!(e=Fc.transform.baseVal.consolidate()))?Sh:(e=e.matrix,Ux(e.a,e.b,e.c,e.d,e.e,e.f))}function Vx(e,t,r,o){function s(p){return p.length?p.pop()+\" \":\"\"}function c(p,g,v,b,w,E){if(p!==v||g!==b){var L=w.push(\"translate(\",null,t,null,r);E.push({i:L-4,x:to(p,v)},{i:L-2,x:to(g,b)})}else(v||b)&&w.push(\"translate(\"+v+t+b+r)}function f(p,g,v,b){p!==g?(p-g>180?g+=360:g-p>180&&(p+=360),b.push({i:v.push(s(v)+\"rotate(\",null,o)-2,x:to(p,g)})):g&&v.push(s(v)+\"rotate(\"+g+o)}function d(p,g,v,b){p!==g?b.push({i:v.push(s(v)+\"skewX(\",null,o)-2,x:to(p,g)}):g&&v.push(s(v)+\"skewX(\"+g+o)}function h(p,g,v,b,w,E){if(p!==v||g!==b){var L=w.push(s(w)+\"scale(\",null,\",\",null,\")\");E.push({i:L-4,x:to(p,v)},{i:L-2,x:to(g,b)})}else(v!==1||b!==1)&&w.push(s(w)+\"scale(\"+v+\",\"+b+\")\")}return function(p,g){var v=[],b=[];return p=e(p),g=e(g),c(p.translateX,p.translateY,g.translateX,g.translateY,v,b),f(p.rotate,g.rotate,v,b),d(p.skewX,g.skewX,v,b),h(p.scaleX,p.scaleY,g.scaleX,g.scaleY,v,b),p=g=null,function(w){for(var E=-1,L=b.length,P;++E<L;)v[(P=b[E]).i]=P.x(w);return v.join(\"\")}}}var the=Vx(Qde,\"px, \",\"px)\",\"deg)\"),nhe=Vx(ehe,\", \",\")\",\")\"),rhe=1e-12;function Xy(e){return((e=Math.exp(e))+1/e)/2}function ihe(e){return((e=Math.exp(e))-1/e)/2}function ohe(e){return((e=Math.exp(2*e))-1)/(e+1)}const she=(function e(t,r,o){function s(c,f){var d=c[0],h=c[1],p=c[2],g=f[0],v=f[1],b=f[2],w=g-d,E=v-h,L=w*w+E*E,P,M;if(L<rhe)M=Math.log(b/p)/t,P=function(ne){return[d+ne*w,h+ne*E,p*Math.exp(t*ne*M)]};else{var R=Math.sqrt(L),I=(b*b-p*p+o*L)/(2*p*r*R),_=(b*b-p*p-o*L)/(2*b*r*R),$=Math.log(Math.sqrt(I*I+1)-I),W=Math.log(Math.sqrt(_*_+1)-_);M=(W-$)/t,P=function(ne){var ee=ne*M,Z=Xy($),G=p/(r*R)*(Z*ohe(t*ee+$)-ihe($));return[d+G*w,h+G*E,p*Z/Xy(t*ee+$)]}}return P.duration=M*1e3*t/Math.SQRT2,P}return s.rho=function(c){var f=Math.max(.001,+c),d=f*f,h=d*d;return e(f,d,h)},s})(Math.SQRT2,2,4);var nl=0,Vl=0,Wl=0,Gx=1e3,Nu,Gl,Ou=0,Ko=0,df=0,La=typeof performance==\"object\"&&performance.now?performance:Date,Kx=typeof window==\"object\"&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(e){setTimeout(e,17)};function Ap(){return Ko||(Kx(lhe),Ko=La.now()+df)}function lhe(){Ko=0}function Pu(){this._call=this._time=this._next=null}Pu.prototype=Lp.prototype={constructor:Pu,restart:function(e,t,r){if(typeof e!=\"function\")throw new TypeError(\"callback is not a function\");r=(r==null?Ap():+r)+(t==null?0:+t),!this._next&&Gl!==this&&(Gl?Gl._next=this:Nu=this,Gl=this),this._call=e,this._time=r,_h()},stop:function(){this._call&&(this._call=null,this._time=1/0,_h())}};function Lp(e,t,r){var o=new Pu;return o.restart(e,t,r),o}function ahe(){Ap(),++nl;for(var e=Nu,t;e;)(t=Ko-e._time)>=0&&e._call.call(void 0,t),e=e._next;--nl}function Yy(){Ko=(Ou=La.now())+df,nl=Vl=0;try{ahe()}finally{nl=0,uhe(),Ko=0}}function che(){var e=La.now(),t=e-Ou;t>Gx&&(df-=t,Ou=e)}function uhe(){for(var e,t=Nu,r,o=1/0;t;)t._call?(o>t._time&&(o=t._time),e=t,t=t._next):(r=t._next,t._next=null,t=e?e._next=r:Nu=r);Gl=e,_h(o)}function _h(e){if(!nl){Vl&&(Vl=clearTimeout(Vl));var t=e-Ko;t>24?(e<1/0&&(Vl=setTimeout(Yy,e-La.now()-df)),Wl&&(Wl=clearInterval(Wl))):(Wl||(Ou=La.now(),Wl=setInterval(che,Gx)),nl=1,Kx(Yy))}}function Zy(e,t,r){var o=new Pu;return t=t==null?0:+t,o.restart(s=>{o.stop(),e(s+t)},t,r),o}var fhe=Ua(\"start\",\"end\",\"cancel\",\"interrupt\"),dhe=[],Xx=0,Jy=1,Th=2,Jc=3,Qy=4,Ch=5,Qc=6;function hf(e,t,r,o,s,c){var f=e.__transition;if(!f)e.__transition={};else if(r in f)return;hhe(e,r,{name:t,index:o,group:s,on:fhe,tween:dhe,time:c.time,delay:c.delay,duration:c.duration,ease:c.ease,timer:null,state:Xx})}function Mp(e,t){var r=Fr(e,t);if(r.state>Xx)throw new Error(\"too late; already scheduled\");return r}function ni(e,t){var r=Fr(e,t);if(r.state>Jc)throw new Error(\"too late; already running\");return r}function Fr(e,t){var r=e.__transition;if(!r||!(r=r[t]))throw new Error(\"transition not found\");return r}function hhe(e,t,r){var o=e.__transition,s;o[t]=r,r.timer=Lp(c,0,r.time);function c(p){r.state=Jy,r.timer.restart(f,r.delay,r.time),r.delay<=p&&f(p-r.delay)}function f(p){var g,v,b,w;if(r.state!==Jy)return h();for(g in o)if(w=o[g],w.name===r.name){if(w.state===Jc)return Zy(f);w.state===Qy?(w.state=Qc,w.timer.stop(),w.on.call(\"interrupt\",e,e.__data__,w.index,w.group),delete o[g]):+g<t&&(w.state=Qc,w.timer.stop(),w.on.call(\"cancel\",e,e.__data__,w.index,w.group),delete o[g])}if(Zy(function(){r.state===Jc&&(r.state=Qy,r.timer.restart(d,r.delay,r.time),d(p))}),r.state=Th,r.on.call(\"start\",e,e.__data__,r.index,r.group),r.state===Th){for(r.state=Jc,s=new Array(b=r.tween.length),g=0,v=-1;g<b;++g)(w=r.tween[g].value.call(e,e.__data__,r.index,r.group))&&(s[++v]=w);s.length=v+1}}function d(p){for(var g=p<r.duration?r.ease.call(null,p/r.duration):(r.timer.restart(h),r.state=Ch,1),v=-1,b=s.length;++v<b;)s[v].call(e,g);r.state===Ch&&(r.on.call(\"end\",e,e.__data__,r.index,r.group),h())}function h(){r.state=Qc,r.timer.stop(),delete o[t];for(var p in o)return;delete e.__transition}}function eu(e,t){var r=e.__transition,o,s,c=!0,f;if(r){t=t==null?null:t+\"\";for(f in r){if((o=r[f]).name!==t){c=!1;continue}s=o.state>Th&&o.state<Ch,o.state=Qc,o.timer.stop(),o.on.call(s?\"interrupt\":\"cancel\",e,e.__data__,o.index,o.group),delete r[f]}c&&delete e.__transition}}function phe(e){return this.each(function(){eu(this,e)})}function ghe(e,t){var r,o;return function(){var s=ni(this,e),c=s.tween;if(c!==r){o=r=c;for(var f=0,d=o.length;f<d;++f)if(o[f].name===t){o=o.slice(),o.splice(f,1);break}}s.tween=o}}function mhe(e,t,r){var o,s;if(typeof r!=\"function\")throw new Error;return function(){var c=ni(this,e),f=c.tween;if(f!==o){s=(o=f).slice();for(var d={name:t,value:r},h=0,p=s.length;h<p;++h)if(s[h].name===t){s[h]=d;break}h===p&&s.push(d)}c.tween=s}}function vhe(e,t){var r=this._id;if(e+=\"\",arguments.length<2){for(var o=Fr(this.node(),r).tween,s=0,c=o.length,f;s<c;++s)if((f=o[s]).name===e)return f.value;return null}return this.each((t==null?ghe:mhe)(r,e,t))}function Np(e,t,r){var o=e._id;return e.each(function(){var s=ni(this,o);(s.value||(s.value={}))[t]=r.apply(this,arguments)}),function(s){return Fr(s,o).value[t]}}function Yx(e,t){var r;return(typeof t==\"number\"?to:t instanceof Aa?Gy:(r=Aa(t))?(t=r,Gy):Jde)(e,t)}function yhe(e){return function(){this.removeAttribute(e)}}function bhe(e){return function(){this.removeAttributeNS(e.space,e.local)}}function whe(e,t,r){var o,s=r+\"\",c;return function(){var f=this.getAttribute(e);return f===s?null:f===o?c:c=t(o=f,r)}}function xhe(e,t,r){var o,s=r+\"\",c;return function(){var f=this.getAttributeNS(e.space,e.local);return f===s?null:f===o?c:c=t(o=f,r)}}function khe(e,t,r){var o,s,c;return function(){var f,d=r(this),h;return d==null?void this.removeAttribute(e):(f=this.getAttribute(e),h=d+\"\",f===h?null:f===o&&h===s?c:(s=h,c=t(o=f,d)))}}function She(e,t,r){var o,s,c;return function(){var f,d=r(this),h;return d==null?void this.removeAttributeNS(e.space,e.local):(f=this.getAttributeNS(e.space,e.local),h=d+\"\",f===h?null:f===o&&h===s?c:(s=h,c=t(o=f,d)))}}function _he(e,t){var r=ff(e),o=r===\"transform\"?nhe:Yx;return this.attrTween(e,typeof t==\"function\"?(r.local?She:khe)(r,o,Np(this,\"attr.\"+e,t)):t==null?(r.local?bhe:yhe)(r):(r.local?xhe:whe)(r,o,t))}function The(e,t){return function(r){this.setAttribute(e,t.call(this,r))}}function Che(e,t){return function(r){this.setAttributeNS(e.space,e.local,t.call(this,r))}}function Ehe(e,t){var r,o;function s(){var c=t.apply(this,arguments);return c!==o&&(r=(o=c)&&Che(e,c)),r}return s._value=t,s}function Ahe(e,t){var r,o;function s(){var c=t.apply(this,arguments);return c!==o&&(r=(o=c)&&The(e,c)),r}return s._value=t,s}function Lhe(e,t){var r=\"attr.\"+e;if(arguments.length<2)return(r=this.tween(r))&&r._value;if(t==null)return this.tween(r,null);if(typeof t!=\"function\")throw new Error;var o=ff(e);return this.tween(r,(o.local?Ehe:Ahe)(o,t))}function Mhe(e,t){return function(){Mp(this,e).delay=+t.apply(this,arguments)}}function Nhe(e,t){return t=+t,function(){Mp(this,e).delay=t}}function Ohe(e){var t=this._id;return arguments.length?this.each((typeof e==\"function\"?Mhe:Nhe)(t,e)):Fr(this.node(),t).delay}function Phe(e,t){return function(){ni(this,e).duration=+t.apply(this,arguments)}}function Rhe(e,t){return t=+t,function(){ni(this,e).duration=t}}function $he(e){var t=this._id;return arguments.length?this.each((typeof e==\"function\"?Phe:Rhe)(t,e)):Fr(this.node(),t).duration}function Ihe(e,t){if(typeof t!=\"function\")throw new Error;return function(){ni(this,e).ease=t}}function Dhe(e){var t=this._id;return arguments.length?this.each(Ihe(t,e)):Fr(this.node(),t).ease}function zhe(e,t){return function(){var r=t.apply(this,arguments);if(typeof r!=\"function\")throw new Error;ni(this,e).ease=r}}function Fhe(e){if(typeof e!=\"function\")throw new Error;return this.each(zhe(this._id,e))}function Hhe(e){typeof e!=\"function\"&&(e=Lx(e));for(var t=this._groups,r=t.length,o=new Array(r),s=0;s<r;++s)for(var c=t[s],f=c.length,d=o[s]=[],h,p=0;p<f;++p)(h=c[p])&&e.call(h,h.__data__,p,c)&&d.push(h);return new Ei(o,this._parents,this._name,this._id)}function Bhe(e){if(e._id!==this._id)throw new Error;for(var t=this._groups,r=e._groups,o=t.length,s=r.length,c=Math.min(o,s),f=new Array(o),d=0;d<c;++d)for(var h=t[d],p=r[d],g=h.length,v=f[d]=new Array(g),b,w=0;w<g;++w)(b=h[w]||p[w])&&(v[w]=b);for(;d<o;++d)f[d]=t[d];return new Ei(f,this._parents,this._name,this._id)}function Whe(e){return(e+\"\").trim().split(/^|\\s+/).every(function(t){var r=t.indexOf(\".\");return r>=0&&(t=t.slice(0,r)),!t||t===\"start\"})}function qhe(e,t,r){var o,s,c=Whe(t)?Mp:ni;return function(){var f=c(this,e),d=f.on;d!==o&&(s=(o=d).copy()).on(t,r),f.on=s}}function jhe(e,t){var r=this._id;return arguments.length<2?Fr(this.node(),r).on.on(e):this.each(qhe(r,e,t))}function Uhe(e){return function(){var t=this.parentNode;for(var r in this.__transition)if(+r!==e)return;t&&t.removeChild(this)}}function Vhe(){return this.on(\"end.remove\",Uhe(this._id))}function Ghe(e){var t=this._name,r=this._id;typeof e!=\"function\"&&(e=Tp(e));for(var o=this._groups,s=o.length,c=new Array(s),f=0;f<s;++f)for(var d=o[f],h=d.length,p=c[f]=new Array(h),g,v,b=0;b<h;++b)(g=d[b])&&(v=e.call(g,g.__data__,b,d))&&(\"__data__\"in g&&(v.__data__=g.__data__),p[b]=v,hf(p[b],t,r,b,p,Fr(g,r)));return new Ei(c,this._parents,t,r)}function Khe(e){var t=this._name,r=this._id;typeof e!=\"function\"&&(e=Ax(e));for(var o=this._groups,s=o.length,c=[],f=[],d=0;d<s;++d)for(var h=o[d],p=h.length,g,v=0;v<p;++v)if(g=h[v]){for(var b=e.call(g,g.__data__,v,h),w,E=Fr(g,r),L=0,P=b.length;L<P;++L)(w=b[L])&&hf(w,t,r,L,b,E);c.push(b),f.push(g)}return new Ei(c,f,t,r)}var Xhe=ja.prototype.constructor;function Yhe(){return new Xhe(this._groups,this._parents)}function Zhe(e,t){var r,o,s;return function(){var c=el(this,e),f=(this.style.removeProperty(e),el(this,e));return c===f?null:c===r&&f===o?s:s=t(r=c,o=f)}}function Zx(e){return function(){this.style.removeProperty(e)}}function Jhe(e,t,r){var o,s=r+\"\",c;return function(){var f=el(this,e);return f===s?null:f===o?c:c=t(o=f,r)}}function Qhe(e,t,r){var o,s,c;return function(){var f=el(this,e),d=r(this),h=d+\"\";return d==null&&(h=d=(this.style.removeProperty(e),el(this,e))),f===h?null:f===o&&h===s?c:(s=h,c=t(o=f,d))}}function epe(e,t){var r,o,s,c=\"style.\"+t,f=\"end.\"+c,d;return function(){var h=ni(this,e),p=h.on,g=h.value[c]==null?d||(d=Zx(t)):void 0;(p!==r||s!==g)&&(o=(r=p).copy()).on(f,s=g),h.on=o}}function tpe(e,t,r){var o=(e+=\"\")==\"transform\"?the:Yx;return t==null?this.styleTween(e,Zhe(e,o)).on(\"end.style.\"+e,Zx(e)):typeof t==\"function\"?this.styleTween(e,Qhe(e,o,Np(this,\"style.\"+e,t))).each(epe(this._id,e)):this.styleTween(e,Jhe(e,o,t),r).on(\"end.style.\"+e,null)}function npe(e,t,r){return function(o){this.style.setProperty(e,t.call(this,o),r)}}function rpe(e,t,r){var o,s;function c(){var f=t.apply(this,arguments);return f!==s&&(o=(s=f)&&npe(e,f,r)),o}return c._value=t,c}function ipe(e,t,r){var o=\"style.\"+(e+=\"\");if(arguments.length<2)return(o=this.tween(o))&&o._value;if(t==null)return this.tween(o,null);if(typeof t!=\"function\")throw new Error;return this.tween(o,rpe(e,t,r??\"\"))}function ope(e){return function(){this.textContent=e}}function spe(e){return function(){var t=e(this);this.textContent=t??\"\"}}function lpe(e){return this.tween(\"text\",typeof e==\"function\"?spe(Np(this,\"text\",e)):ope(e==null?\"\":e+\"\"))}function ape(e){return function(t){this.textContent=e.call(this,t)}}function cpe(e){var t,r;function o(){var s=e.apply(this,arguments);return s!==r&&(t=(r=s)&&ape(s)),t}return o._value=e,o}function upe(e){var t=\"text\";if(arguments.length<1)return(t=this.tween(t))&&t._value;if(e==null)return this.tween(t,null);if(typeof e!=\"function\")throw new Error;return this.tween(t,cpe(e))}function fpe(){for(var e=this._name,t=this._id,r=Jx(),o=this._groups,s=o.length,c=0;c<s;++c)for(var f=o[c],d=f.length,h,p=0;p<d;++p)if(h=f[p]){var g=Fr(h,t);hf(h,e,r,p,f,{time:g.time+g.delay+g.duration,delay:0,duration:g.duration,ease:g.ease})}return new Ei(o,this._parents,e,r)}function dpe(){var e,t,r=this,o=r._id,s=r.size();return new Promise(function(c,f){var d={value:f},h={value:function(){--s===0&&c()}};r.each(function(){var p=ni(this,o),g=p.on;g!==e&&(t=(e=g).copy(),t._.cancel.push(d),t._.interrupt.push(d),t._.end.push(h)),p.on=t}),s===0&&c()})}var hpe=0;function Ei(e,t,r,o){this._groups=e,this._parents=t,this._name=r,this._id=o}function Jx(){return++hpe}var hi=ja.prototype;Ei.prototype={constructor:Ei,select:Ghe,selectAll:Khe,selectChild:hi.selectChild,selectChildren:hi.selectChildren,filter:Hhe,merge:Bhe,selection:Yhe,transition:fpe,call:hi.call,nodes:hi.nodes,node:hi.node,size:hi.size,empty:hi.empty,each:hi.each,on:jhe,attr:_he,attrTween:Lhe,style:tpe,styleTween:ipe,text:lpe,textTween:upe,remove:Vhe,tween:vhe,delay:Ohe,duration:$he,ease:Dhe,easeVarying:Fhe,end:dpe,[Symbol.iterator]:hi[Symbol.iterator]};function ppe(e){return((e*=2)<=1?e*e*e:(e-=2)*e*e+2)/2}var gpe={time:null,delay:0,duration:250,ease:ppe};function mpe(e,t){for(var r;!(r=e.__transition)||!(r=r[t]);)if(!(e=e.parentNode))throw new Error(`transition ${t} not found`);return r}function vpe(e){var t,r;e instanceof Ei?(t=e._id,e=e._name):(t=Jx(),(r=gpe).time=Ap(),e=e==null?null:e+\"\");for(var o=this._groups,s=o.length,c=0;c<s;++c)for(var f=o[c],d=f.length,h,p=0;p<d;++p)(h=f[p])&&hf(h,e,t,p,f,r||mpe(h,t));return new Ei(o,this._parents,e,t)}ja.prototype.interrupt=phe;ja.prototype.transition=vpe;const Hc=e=>()=>e;function ype(e,{sourceEvent:t,target:r,transform:o,dispatch:s}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},transform:{value:o,enumerable:!0,configurable:!0},_:{value:s}})}function xi(e,t,r){this.k=e,this.x=t,this.y=r}xi.prototype={constructor:xi,scale:function(e){return e===1?this:new xi(this.k*e,this.x,this.y)},translate:function(e,t){return e===0&t===0?this:new xi(this.k,this.x+this.k*e,this.y+this.k*t)},apply:function(e){return[e[0]*this.k+this.x,e[1]*this.k+this.y]},applyX:function(e){return e*this.k+this.x},applyY:function(e){return e*this.k+this.y},invert:function(e){return[(e[0]-this.x)/this.k,(e[1]-this.y)/this.k]},invertX:function(e){return(e-this.x)/this.k},invertY:function(e){return(e-this.y)/this.k},rescaleX:function(e){return e.copy().domain(e.range().map(this.invertX,this).map(e.invert,e))},rescaleY:function(e){return e.copy().domain(e.range().map(this.invertY,this).map(e.invert,e))},toString:function(){return\"translate(\"+this.x+\",\"+this.y+\") scale(\"+this.k+\")\"}};var Op=new xi(1,0,0);xi.prototype;function Dd(e){e.stopImmediatePropagation()}function ql(e){e.preventDefault(),e.stopImmediatePropagation()}function bpe(e){return(!e.ctrlKey||e.type===\"wheel\")&&!e.button}function wpe(){var e=this;return e instanceof SVGElement?(e=e.ownerSVGElement||e,e.hasAttribute(\"viewBox\")?(e=e.viewBox.baseVal,[[e.x,e.y],[e.x+e.width,e.y+e.height]]):[[0,0],[e.width.baseVal.value,e.height.baseVal.value]]):[[0,0],[e.clientWidth,e.clientHeight]]}function e0(){return this.__zoom||Op}function xpe(e){return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*(e.ctrlKey?10:1)}function kpe(){return navigator.maxTouchPoints||\"ontouchstart\"in this}function Spe(e,t,r){var o=e.invertX(t[0][0])-r[0][0],s=e.invertX(t[1][0])-r[1][0],c=e.invertY(t[0][1])-r[0][1],f=e.invertY(t[1][1])-r[1][1];return e.translate(s>o?(o+s)/2:Math.min(0,o)||Math.max(0,s),f>c?(c+f)/2:Math.min(0,c)||Math.max(0,f))}function _pe(){var e=bpe,t=wpe,r=Spe,o=xpe,s=kpe,c=[0,1/0],f=[[-1/0,-1/0],[1/0,1/0]],d=250,h=she,p=Ua(\"start\",\"zoom\",\"end\"),g,v,b,w=500,E=150,L=0,P=10;function M(C){C.property(\"__zoom\",e0).on(\"wheel.zoom\",ee,{passive:!1}).on(\"mousedown.zoom\",Z).on(\"dblclick.zoom\",G).filter(s).on(\"touchstart.zoom\",j).on(\"touchmove.zoom\",N).on(\"touchend.zoom touchcancel.zoom\",O).style(\"-webkit-tap-highlight-color\",\"rgba(0,0,0,0)\")}M.transform=function(C,k,z,B){var ce=C.selection?C.selection():C;ce.property(\"__zoom\",e0),C!==ce?$(C,k,z,B):ce.interrupt().each(function(){W(this,arguments).event(B).start().zoom(null,typeof k==\"function\"?k.apply(this,arguments):k).end()})},M.scaleBy=function(C,k,z,B){M.scaleTo(C,function(){var ce=this.__zoom.k,be=typeof k==\"function\"?k.apply(this,arguments):k;return ce*be},z,B)},M.scaleTo=function(C,k,z,B){M.transform(C,function(){var ce=t.apply(this,arguments),be=this.__zoom,Se=z==null?_(ce):typeof z==\"function\"?z.apply(this,arguments):z,Be=be.invert(Se),Ae=typeof k==\"function\"?k.apply(this,arguments):k;return r(I(R(be,Ae),Se,Be),ce,f)},z,B)},M.translateBy=function(C,k,z,B){M.transform(C,function(){return r(this.__zoom.translate(typeof k==\"function\"?k.apply(this,arguments):k,typeof z==\"function\"?z.apply(this,arguments):z),t.apply(this,arguments),f)},null,B)},M.translateTo=function(C,k,z,B,ce){M.transform(C,function(){var be=t.apply(this,arguments),Se=this.__zoom,Be=B==null?_(be):typeof B==\"function\"?B.apply(this,arguments):B;return r(Op.translate(Be[0],Be[1]).scale(Se.k).translate(typeof k==\"function\"?-k.apply(this,arguments):-k,typeof z==\"function\"?-z.apply(this,arguments):-z),be,f)},B,ce)};function R(C,k){return k=Math.max(c[0],Math.min(c[1],k)),k===C.k?C:new xi(k,C.x,C.y)}function I(C,k,z){var B=k[0]-z[0]*C.k,ce=k[1]-z[1]*C.k;return B===C.x&&ce===C.y?C:new xi(C.k,B,ce)}function _(C){return[(+C[0][0]+ +C[1][0])/2,(+C[0][1]+ +C[1][1])/2]}function $(C,k,z,B){C.on(\"start.zoom\",function(){W(this,arguments).event(B).start()}).on(\"interrupt.zoom end.zoom\",function(){W(this,arguments).event(B).end()}).tween(\"zoom\",function(){var ce=this,be=arguments,Se=W(ce,be).event(B),Be=t.apply(ce,be),Ae=z==null?_(Be):typeof z==\"function\"?z.apply(ce,be):z,Ke=Math.max(Be[1][0]-Be[0][0],Be[1][1]-Be[0][1]),je=ce.__zoom,Fe=typeof k==\"function\"?k.apply(ce,be):k,Pe=h(je.invert(Ae).concat(Ke/je.k),Fe.invert(Ae).concat(Ke/Fe.k));return function(F){if(F===1)F=Fe;else{var Y=Pe(F),re=Ke/Y[2];F=new xi(re,Ae[0]-Y[0]*re,Ae[1]-Y[1]*re)}Se.zoom(null,F)}})}function W(C,k,z){return!z&&C.__zooming||new ne(C,k)}function ne(C,k){this.that=C,this.args=k,this.active=0,this.sourceEvent=null,this.extent=t.apply(C,k),this.taps=0}ne.prototype={event:function(C){return C&&(this.sourceEvent=C),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit(\"start\")),this},zoom:function(C,k){return this.mouse&&C!==\"mouse\"&&(this.mouse[1]=k.invert(this.mouse[0])),this.touch0&&C!==\"touch\"&&(this.touch0[1]=k.invert(this.touch0[0])),this.touch1&&C!==\"touch\"&&(this.touch1[1]=k.invert(this.touch1[0])),this.that.__zoom=k,this.emit(\"zoom\"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit(\"end\")),this},emit:function(C){var k=Kn(this.that).datum();p.call(C,this.that,new ype(C,{sourceEvent:this.sourceEvent,target:M,transform:this.that.__zoom,dispatch:p}),k)}};function ee(C,...k){if(!e.apply(this,arguments))return;var z=W(this,k).event(C),B=this.__zoom,ce=Math.max(c[0],Math.min(c[1],B.k*Math.pow(2,o.apply(this,arguments)))),be=vi(C);if(z.wheel)(z.mouse[0][0]!==be[0]||z.mouse[0][1]!==be[1])&&(z.mouse[1]=B.invert(z.mouse[0]=be)),clearTimeout(z.wheel);else{if(B.k===ce)return;z.mouse=[be,B.invert(be)],eu(this),z.start()}ql(C),z.wheel=setTimeout(Se,E),z.zoom(\"mouse\",r(I(R(B,ce),z.mouse[0],z.mouse[1]),z.extent,f));function Se(){z.wheel=null,z.end()}}function Z(C,...k){if(b||!e.apply(this,arguments))return;var z=C.currentTarget,B=W(this,k,!0).event(C),ce=Kn(C.view).on(\"mousemove.zoom\",Ae,!0).on(\"mouseup.zoom\",Ke,!0),be=vi(C,z),Se=C.clientX,Be=C.clientY;Fx(C.view),Dd(C),B.mouse=[be,this.__zoom.invert(be)],eu(this),B.start();function Ae(je){if(ql(je),!B.moved){var Fe=je.clientX-Se,Pe=je.clientY-Be;B.moved=Fe*Fe+Pe*Pe>L}B.event(je).zoom(\"mouse\",r(I(B.that.__zoom,B.mouse[0]=vi(je,z),B.mouse[1]),B.extent,f))}function Ke(je){ce.on(\"mousemove.zoom mouseup.zoom\",null),Hx(je.view,B.moved),ql(je),B.event(je).end()}}function G(C,...k){if(e.apply(this,arguments)){var z=this.__zoom,B=vi(C.changedTouches?C.changedTouches[0]:C,this),ce=z.invert(B),be=z.k*(C.shiftKey?.5:2),Se=r(I(R(z,be),B,ce),t.apply(this,k),f);ql(C),d>0?Kn(this).transition().duration(d).call($,Se,B,C):Kn(this).call(M.transform,Se,B,C)}}function j(C,...k){if(e.apply(this,arguments)){var z=C.touches,B=z.length,ce=W(this,k,C.changedTouches.length===B).event(C),be,Se,Be,Ae;for(Dd(C),Se=0;Se<B;++Se)Be=z[Se],Ae=vi(Be,this),Ae=[Ae,this.__zoom.invert(Ae),Be.identifier],ce.touch0?!ce.touch1&&ce.touch0[2]!==Ae[2]&&(ce.touch1=Ae,ce.taps=0):(ce.touch0=Ae,be=!0,ce.taps=1+!!g);g&&(g=clearTimeout(g)),be&&(ce.taps<2&&(v=Ae[0],g=setTimeout(function(){g=null},w)),eu(this),ce.start())}}function N(C,...k){if(this.__zooming){var z=W(this,k).event(C),B=C.changedTouches,ce=B.length,be,Se,Be,Ae;for(ql(C),be=0;be<ce;++be)Se=B[be],Be=vi(Se,this),z.touch0&&z.touch0[2]===Se.identifier?z.touch0[0]=Be:z.touch1&&z.touch1[2]===Se.identifier&&(z.touch1[0]=Be);if(Se=z.that.__zoom,z.touch1){var Ke=z.touch0[0],je=z.touch0[1],Fe=z.touch1[0],Pe=z.touch1[1],F=(F=Fe[0]-Ke[0])*F+(F=Fe[1]-Ke[1])*F,Y=(Y=Pe[0]-je[0])*Y+(Y=Pe[1]-je[1])*Y;Se=R(Se,Math.sqrt(F/Y)),Be=[(Ke[0]+Fe[0])/2,(Ke[1]+Fe[1])/2],Ae=[(je[0]+Pe[0])/2,(je[1]+Pe[1])/2]}else if(z.touch0)Be=z.touch0[0],Ae=z.touch0[1];else return;z.zoom(\"touch\",r(I(Se,Be,Ae),z.extent,f))}}function O(C,...k){if(this.__zooming){var z=W(this,k).event(C),B=C.changedTouches,ce=B.length,be,Se;for(Dd(C),b&&clearTimeout(b),b=setTimeout(function(){b=null},w),be=0;be<ce;++be)Se=B[be],z.touch0&&z.touch0[2]===Se.identifier?delete z.touch0:z.touch1&&z.touch1[2]===Se.identifier&&delete z.touch1;if(z.touch1&&!z.touch0&&(z.touch0=z.touch1,delete z.touch1),z.touch0)z.touch0[1]=this.__zoom.invert(z.touch0[0]);else if(z.end(),z.taps===2&&(Se=vi(Se,this),Math.hypot(v[0]-Se[0],v[1]-Se[1])<P)){var Be=Kn(this).on(\"dblclick.zoom\");Be&&Be.apply(this,arguments)}}}return M.wheelDelta=function(C){return arguments.length?(o=typeof C==\"function\"?C:Hc(+C),M):o},M.filter=function(C){return arguments.length?(e=typeof C==\"function\"?C:Hc(!!C),M):e},M.touchable=function(C){return arguments.length?(s=typeof C==\"function\"?C:Hc(!!C),M):s},M.extent=function(C){return arguments.length?(t=typeof C==\"function\"?C:Hc([[+C[0][0],+C[0][1]],[+C[1][0],+C[1][1]]]),M):t},M.scaleExtent=function(C){return arguments.length?(c[0]=+C[0],c[1]=+C[1],M):[c[0],c[1]]},M.translateExtent=function(C){return arguments.length?(f[0][0]=+C[0][0],f[1][0]=+C[1][0],f[0][1]=+C[0][1],f[1][1]=+C[1][1],M):[[f[0][0],f[0][1]],[f[1][0],f[1][1]]]},M.constrain=function(C){return arguments.length?(r=C,M):r},M.duration=function(C){return arguments.length?(d=+C,M):d},M.interpolate=function(C){return arguments.length?(h=C,M):h},M.on=function(){var C=p.on.apply(p,arguments);return C===p?M:C},M.clickDistance=function(C){return arguments.length?(L=(C=+C)*C,M):Math.sqrt(L)},M.tapDistance=function(C){return arguments.length?(P=+C,M):P},M}function Tpe(e){const t=+this._x.call(null,e),r=+this._y.call(null,e);return Qx(this.cover(t,r),t,r,e)}function Qx(e,t,r,o){if(isNaN(t)||isNaN(r))return e;var s,c=e._root,f={data:o},d=e._x0,h=e._y0,p=e._x1,g=e._y1,v,b,w,E,L,P,M,R;if(!c)return e._root=f,e;for(;c.length;)if((L=t>=(v=(d+p)/2))?d=v:p=v,(P=r>=(b=(h+g)/2))?h=b:g=b,s=c,!(c=c[M=P<<1|L]))return s[M]=f,e;if(w=+e._x.call(null,c.data),E=+e._y.call(null,c.data),t===w&&r===E)return f.next=c,s?s[M]=f:e._root=f,e;do s=s?s[M]=new Array(4):e._root=new Array(4),(L=t>=(v=(d+p)/2))?d=v:p=v,(P=r>=(b=(h+g)/2))?h=b:g=b;while((M=P<<1|L)===(R=(E>=b)<<1|w>=v));return s[R]=c,s[M]=f,e}function Cpe(e){var t,r,o=e.length,s,c,f=new Array(o),d=new Array(o),h=1/0,p=1/0,g=-1/0,v=-1/0;for(r=0;r<o;++r)isNaN(s=+this._x.call(null,t=e[r]))||isNaN(c=+this._y.call(null,t))||(f[r]=s,d[r]=c,s<h&&(h=s),s>g&&(g=s),c<p&&(p=c),c>v&&(v=c));if(h>g||p>v)return this;for(this.cover(h,p).cover(g,v),r=0;r<o;++r)Qx(this,f[r],d[r],e[r]);return this}function Epe(e,t){if(isNaN(e=+e)||isNaN(t=+t))return this;var r=this._x0,o=this._y0,s=this._x1,c=this._y1;if(isNaN(r))s=(r=Math.floor(e))+1,c=(o=Math.floor(t))+1;else{for(var f=s-r||1,d=this._root,h,p;r>e||e>=s||o>t||t>=c;)switch(p=(t<o)<<1|e<r,h=new Array(4),h[p]=d,d=h,f*=2,p){case 0:s=r+f,c=o+f;break;case 1:r=s-f,c=o+f;break;case 2:s=r+f,o=c-f;break;case 3:r=s-f,o=c-f;break}this._root&&this._root.length&&(this._root=d)}return this._x0=r,this._y0=o,this._x1=s,this._y1=c,this}function Ape(){var e=[];return this.visit(function(t){if(!t.length)do e.push(t.data);while(t=t.next)}),e}function Lpe(e){return arguments.length?this.cover(+e[0][0],+e[0][1]).cover(+e[1][0],+e[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]}function Rn(e,t,r,o,s){this.node=e,this.x0=t,this.y0=r,this.x1=o,this.y1=s}function Mpe(e,t,r){var o,s=this._x0,c=this._y0,f,d,h,p,g=this._x1,v=this._y1,b=[],w=this._root,E,L;for(w&&b.push(new Rn(w,s,c,g,v)),r==null?r=1/0:(s=e-r,c=t-r,g=e+r,v=t+r,r*=r);E=b.pop();)if(!(!(w=E.node)||(f=E.x0)>g||(d=E.y0)>v||(h=E.x1)<s||(p=E.y1)<c))if(w.length){var P=(f+h)/2,M=(d+p)/2;b.push(new Rn(w[3],P,M,h,p),new Rn(w[2],f,M,P,p),new Rn(w[1],P,d,h,M),new Rn(w[0],f,d,P,M)),(L=(t>=M)<<1|e>=P)&&(E=b[b.length-1],b[b.length-1]=b[b.length-1-L],b[b.length-1-L]=E)}else{var R=e-+this._x.call(null,w.data),I=t-+this._y.call(null,w.data),_=R*R+I*I;if(_<r){var $=Math.sqrt(r=_);s=e-$,c=t-$,g=e+$,v=t+$,o=w.data}}return o}function Npe(e){if(isNaN(g=+this._x.call(null,e))||isNaN(v=+this._y.call(null,e)))return this;var t,r=this._root,o,s,c,f=this._x0,d=this._y0,h=this._x1,p=this._y1,g,v,b,w,E,L,P,M;if(!r)return this;if(r.length)for(;;){if((E=g>=(b=(f+h)/2))?f=b:h=b,(L=v>=(w=(d+p)/2))?d=w:p=w,t=r,!(r=r[P=L<<1|E]))return this;if(!r.length)break;(t[P+1&3]||t[P+2&3]||t[P+3&3])&&(o=t,M=P)}for(;r.data!==e;)if(s=r,!(r=r.next))return this;return(c=r.next)&&delete r.next,s?(c?s.next=c:delete s.next,this):t?(c?t[P]=c:delete t[P],(r=t[0]||t[1]||t[2]||t[3])&&r===(t[3]||t[2]||t[1]||t[0])&&!r.length&&(o?o[M]=r:this._root=r),this):(this._root=c,this)}function Ope(e){for(var t=0,r=e.length;t<r;++t)this.remove(e[t]);return this}function Ppe(){return this._root}function Rpe(){var e=0;return this.visit(function(t){if(!t.length)do++e;while(t=t.next)}),e}function $pe(e){var t=[],r,o=this._root,s,c,f,d,h;for(o&&t.push(new Rn(o,this._x0,this._y0,this._x1,this._y1));r=t.pop();)if(!e(o=r.node,c=r.x0,f=r.y0,d=r.x1,h=r.y1)&&o.length){var p=(c+d)/2,g=(f+h)/2;(s=o[3])&&t.push(new Rn(s,p,g,d,h)),(s=o[2])&&t.push(new Rn(s,c,g,p,h)),(s=o[1])&&t.push(new Rn(s,p,f,d,g)),(s=o[0])&&t.push(new Rn(s,c,f,p,g))}return this}function Ipe(e){var t=[],r=[],o;for(this._root&&t.push(new Rn(this._root,this._x0,this._y0,this._x1,this._y1));o=t.pop();){var s=o.node;if(s.length){var c,f=o.x0,d=o.y0,h=o.x1,p=o.y1,g=(f+h)/2,v=(d+p)/2;(c=s[0])&&t.push(new Rn(c,f,d,g,v)),(c=s[1])&&t.push(new Rn(c,g,d,h,v)),(c=s[2])&&t.push(new Rn(c,f,v,g,p)),(c=s[3])&&t.push(new Rn(c,g,v,h,p))}r.push(o)}for(;o=r.pop();)e(o.node,o.x0,o.y0,o.x1,o.y1);return this}function Dpe(e){return e[0]}function zpe(e){return arguments.length?(this._x=e,this):this._x}function Fpe(e){return e[1]}function Hpe(e){return arguments.length?(this._y=e,this):this._y}function Pp(e,t,r){var o=new Rp(t??Dpe,r??Fpe,NaN,NaN,NaN,NaN);return e==null?o:o.addAll(e)}function Rp(e,t,r,o,s,c){this._x=e,this._y=t,this._x0=r,this._y0=o,this._x1=s,this._y1=c,this._root=void 0}function t0(e){for(var t={data:e.data},r=t;e=e.next;)r=r.next={data:e.data};return t}var zn=Pp.prototype=Rp.prototype;zn.copy=function(){var e=new Rp(this._x,this._y,this._x0,this._y0,this._x1,this._y1),t=this._root,r,o;if(!t)return e;if(!t.length)return e._root=t0(t),e;for(r=[{source:t,target:e._root=new Array(4)}];t=r.pop();)for(var s=0;s<4;++s)(o=t.source[s])&&(o.length?r.push({source:o,target:t.target[s]=new Array(4)}):t.target[s]=t0(o));return e};zn.add=Tpe;zn.addAll=Cpe;zn.cover=Epe;zn.data=Ape;zn.extent=Lpe;zn.find=Mpe;zn.remove=Npe;zn.removeAll=Ope;zn.root=Ppe;zn.size=Rpe;zn.visit=$pe;zn.visitAfter=Ipe;zn.x=zpe;zn.y=Hpe;function Dn(e){return function(){return e}}function io(e){return(e()-.5)*1e-6}function Bpe(e){return e.x+e.vx}function Wpe(e){return e.y+e.vy}function qpe(e){var t,r,o,s=1,c=1;typeof e!=\"function\"&&(e=Dn(e==null?1:+e));function f(){for(var p,g=t.length,v,b,w,E,L,P,M=0;M<c;++M)for(v=Pp(t,Bpe,Wpe).visitAfter(d),p=0;p<g;++p)b=t[p],L=r[b.index],P=L*L,w=b.x+b.vx,E=b.y+b.vy,v.visit(R);function R(I,_,$,W,ne){var ee=I.data,Z=I.r,G=L+Z;if(ee){if(ee.index>b.index){var j=w-ee.x-ee.vx,N=E-ee.y-ee.vy,O=j*j+N*N;O<G*G&&(j===0&&(j=io(o),O+=j*j),N===0&&(N=io(o),O+=N*N),O=(G-(O=Math.sqrt(O)))/O*s,b.vx+=(j*=O)*(G=(Z*=Z)/(P+Z)),b.vy+=(N*=O)*G,ee.vx-=j*(G=1-G),ee.vy-=N*G)}return}return _>w+G||W<w-G||$>E+G||ne<E-G}}function d(p){if(p.data)return p.r=r[p.data.index];for(var g=p.r=0;g<4;++g)p[g]&&p[g].r>p.r&&(p.r=p[g].r)}function h(){if(t){var p,g=t.length,v;for(r=new Array(g),p=0;p<g;++p)v=t[p],r[v.index]=+e(v,p,t)}}return f.initialize=function(p,g){t=p,o=g,h()},f.iterations=function(p){return arguments.length?(c=+p,f):c},f.strength=function(p){return arguments.length?(s=+p,f):s},f.radius=function(p){return arguments.length?(e=typeof p==\"function\"?p:Dn(+p),h(),f):e},f}function jpe(e){return e.index}function n0(e,t){var r=e.get(t);if(!r)throw new Error(\"node not found: \"+t);return r}function Upe(e){var t=jpe,r=v,o,s=Dn(30),c,f,d,h,p,g=1;e==null&&(e=[]);function v(P){return 1/Math.min(d[P.source.index],d[P.target.index])}function b(P){for(var M=0,R=e.length;M<g;++M)for(var I=0,_,$,W,ne,ee,Z,G;I<R;++I)_=e[I],$=_.source,W=_.target,ne=W.x+W.vx-$.x-$.vx||io(p),ee=W.y+W.vy-$.y-$.vy||io(p),Z=Math.sqrt(ne*ne+ee*ee),Z=(Z-c[I])/Z*P*o[I],ne*=Z,ee*=Z,W.vx-=ne*(G=h[I]),W.vy-=ee*G,$.vx+=ne*(G=1-G),$.vy+=ee*G}function w(){if(f){var P,M=f.length,R=e.length,I=new Map(f.map(($,W)=>[t($,W,f),$])),_;for(P=0,d=new Array(M);P<R;++P)_=e[P],_.index=P,typeof _.source!=\"object\"&&(_.source=n0(I,_.source)),typeof _.target!=\"object\"&&(_.target=n0(I,_.target)),d[_.source.index]=(d[_.source.index]||0)+1,d[_.target.index]=(d[_.target.index]||0)+1;for(P=0,h=new Array(R);P<R;++P)_=e[P],h[P]=d[_.source.index]/(d[_.source.index]+d[_.target.index]);o=new Array(R),E(),c=new Array(R),L()}}function E(){if(f)for(var P=0,M=e.length;P<M;++P)o[P]=+r(e[P],P,e)}function L(){if(f)for(var P=0,M=e.length;P<M;++P)c[P]=+s(e[P],P,e)}return b.initialize=function(P,M){f=P,p=M,w()},b.links=function(P){return arguments.length?(e=P,w(),b):e},b.id=function(P){return arguments.length?(t=P,b):t},b.iterations=function(P){return arguments.length?(g=+P,b):g},b.strength=function(P){return arguments.length?(r=typeof P==\"function\"?P:Dn(+P),E(),b):r},b.distance=function(P){return arguments.length?(s=typeof P==\"function\"?P:Dn(+P),L(),b):s},b}const Vpe=1664525,Gpe=1013904223,r0=4294967296;function Kpe(){let e=1;return()=>(e=(Vpe*e+Gpe)%r0)/r0}function Xpe(e){return e.x}function Ype(e){return e.y}var Zpe=10,Jpe=Math.PI*(3-Math.sqrt(5));function Qpe(e){var t,r=1,o=.001,s=1-Math.pow(o,1/300),c=0,f=.6,d=new Map,h=Lp(v),p=Ua(\"tick\",\"end\"),g=Kpe();e==null&&(e=[]);function v(){b(),p.call(\"tick\",t),r<o&&(h.stop(),p.call(\"end\",t))}function b(L){var P,M=e.length,R;L===void 0&&(L=1);for(var I=0;I<L;++I)for(r+=(c-r)*s,d.forEach(function(_){_(r)}),P=0;P<M;++P)R=e[P],R.fx==null?R.x+=R.vx*=f:(R.x=R.fx,R.vx=0),R.fy==null?R.y+=R.vy*=f:(R.y=R.fy,R.vy=0);return t}function w(){for(var L=0,P=e.length,M;L<P;++L){if(M=e[L],M.index=L,M.fx!=null&&(M.x=M.fx),M.fy!=null&&(M.y=M.fy),isNaN(M.x)||isNaN(M.y)){var R=Zpe*Math.sqrt(.5+L),I=L*Jpe;M.x=R*Math.cos(I),M.y=R*Math.sin(I)}(isNaN(M.vx)||isNaN(M.vy))&&(M.vx=M.vy=0)}}function E(L){return L.initialize&&L.initialize(e,g),L}return w(),t={tick:b,restart:function(){return h.restart(v),t},stop:function(){return h.stop(),t},nodes:function(L){return arguments.length?(e=L,w(),d.forEach(E),t):e},alpha:function(L){return arguments.length?(r=+L,t):r},alphaMin:function(L){return arguments.length?(o=+L,t):o},alphaDecay:function(L){return arguments.length?(s=+L,t):+s},alphaTarget:function(L){return arguments.length?(c=+L,t):c},velocityDecay:function(L){return arguments.length?(f=1-L,t):1-f},randomSource:function(L){return arguments.length?(g=L,d.forEach(E),t):g},force:function(L,P){return arguments.length>1?(P==null?d.delete(L):d.set(L,E(P)),t):d.get(L)},find:function(L,P,M){var R=0,I=e.length,_,$,W,ne,ee;for(M==null?M=1/0:M*=M,R=0;R<I;++R)ne=e[R],_=L-ne.x,$=P-ne.y,W=_*_+$*$,W<M&&(ee=ne,M=W);return ee},on:function(L,P){return arguments.length>1?(p.on(L,P),t):p.on(L)}}}function ege(){var e,t,r,o,s=Dn(-30),c,f=1,d=1/0,h=.81;function p(w){var E,L=e.length,P=Pp(e,Xpe,Ype).visitAfter(v);for(o=w,E=0;E<L;++E)t=e[E],P.visit(b)}function g(){if(e){var w,E=e.length,L;for(c=new Array(E),w=0;w<E;++w)L=e[w],c[L.index]=+s(L,w,e)}}function v(w){var E=0,L,P,M=0,R,I,_;if(w.length){for(R=I=_=0;_<4;++_)(L=w[_])&&(P=Math.abs(L.value))&&(E+=L.value,M+=P,R+=P*L.x,I+=P*L.y);w.x=R/M,w.y=I/M}else{L=w,L.x=L.data.x,L.y=L.data.y;do E+=c[L.data.index];while(L=L.next)}w.value=E}function b(w,E,L,P){if(!w.value)return!0;var M=w.x-t.x,R=w.y-t.y,I=P-E,_=M*M+R*R;if(I*I/h<_)return _<d&&(M===0&&(M=io(r),_+=M*M),R===0&&(R=io(r),_+=R*R),_<f&&(_=Math.sqrt(f*_)),t.vx+=M*w.value*o/_,t.vy+=R*w.value*o/_),!0;if(w.length||_>=d)return;(w.data!==t||w.next)&&(M===0&&(M=io(r),_+=M*M),R===0&&(R=io(r),_+=R*R),_<f&&(_=Math.sqrt(f*_)));do w.data!==t&&(I=c[w.data.index]*o/_,t.vx+=M*I,t.vy+=R*I);while(w=w.next)}return p.initialize=function(w,E){e=w,r=E,g()},p.strength=function(w){return arguments.length?(s=typeof w==\"function\"?w:Dn(+w),g(),p):s},p.distanceMin=function(w){return arguments.length?(f=w*w,p):Math.sqrt(f)},p.distanceMax=function(w){return arguments.length?(d=w*w,p):Math.sqrt(d)},p.theta=function(w){return arguments.length?(h=w*w,p):Math.sqrt(h)},p}function tge(e){var t=Dn(.1),r,o,s;typeof e!=\"function\"&&(e=Dn(e==null?0:+e));function c(d){for(var h=0,p=r.length,g;h<p;++h)g=r[h],g.vx+=(s[h]-g.x)*o[h]*d}function f(){if(r){var d,h=r.length;for(o=new Array(h),s=new Array(h),d=0;d<h;++d)o[d]=isNaN(s[d]=+e(r[d],d,r))?0:+t(r[d],d,r)}}return c.initialize=function(d){r=d,f()},c.strength=function(d){return arguments.length?(t=typeof d==\"function\"?d:Dn(+d),f(),c):t},c.x=function(d){return arguments.length?(e=typeof d==\"function\"?d:Dn(+d),f(),c):e},c}function nge(e){var t=Dn(.1),r,o,s;typeof e!=\"function\"&&(e=Dn(e==null?0:+e));function c(d){for(var h=0,p=r.length,g;h<p;++h)g=r[h],g.vy+=(s[h]-g.y)*o[h]*d}function f(){if(r){var d,h=r.length;for(o=new Array(h),s=new Array(h),d=0;d<h;++d)o[d]=isNaN(s[d]=+e(r[d],d,r))?0:+t(r[d],d,r)}}return c.initialize=function(d){r=d,f()},c.strength=function(d){return arguments.length?(t=typeof d==\"function\"?d:Dn(+d),f(),c):t},c.y=function(d){return arguments.length?(e=typeof d==\"function\"?d:Dn(+d),f(),c):e},c}function rge(){return{drag:{end:0,start:.1},filter:{link:1,type:.1,unlinked:{include:.1,exclude:.1}},focus:{acquire:()=>.1,release:()=>.1},initialize:1,labels:{links:{hide:0,show:0},nodes:{hide:0,show:0}},resize:.5}}function i0(e){if(typeof e==\"object\"&&e!==null){if(typeof Object.getPrototypeOf==\"function\"){const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}return Object.prototype.toString.call(e)===\"[object Object]\"}return!1}function oo(...e){return e.reduce((t,r)=>{if(Array.isArray(r))throw new TypeError(\"Arguments provided to deepmerge must be objects, not arrays.\");return Object.keys(r).forEach(o=>{[\"__proto__\",\"constructor\",\"prototype\"].includes(o)||(Array.isArray(t[o])&&Array.isArray(r[o])?t[o]=oo.options.mergeArrays?Array.from(new Set(t[o].concat(r[o]))):r[o]:i0(t[o])&&i0(r[o])?t[o]=oo(t[o],r[o]):t[o]=r[o])}),t},{})}const e1={mergeArrays:!0};oo.options=e1;oo.withOptions=(e,...t)=>{oo.options={mergeArrays:!0,...e};const r=oo(...t);return oo.options=e1,r};var ige=oo;function oge(){return{centering:{enabled:!0,strength:.1},charge:{enabled:!0,strength:-1},collision:{enabled:!0,strength:1,radiusMultiplier:2},link:{enabled:!0,strength:1,length:128}}}function sge(){return{includeUnlinked:!0,linkFilter:()=>!0,nodeTypeFilter:void 0,showLinkLabels:!0,showNodeLabels:!0}}function t1(e){e.preventDefault(),e.stopPropagation()}function n1(e){return typeof e==\"number\"}function mo(e,t){return n1(e.nodeRadius)?e.nodeRadius:e.nodeRadius(t)}function lge(e){return`${e.source.id}-${e.target.id}`}function r1(e){return`link-arrow-${e}`.replace(/[()]/g,\"~\")}function age(e){return`url(#${r1(e.color)})`}function cge(e){return{size:e,padding:(t,r)=>mo(r,t)+2*e,ref:[e/2,e/2],path:[[0,0],[0,e],[e,e/2]],viewBox:[0,0,e,e].join(\",\")}}const i1={Arrow:e=>cge(e)},uge=(e,t,r)=>[t/2,r/2],fge=(e,t,r)=>[o0(0,t),o0(0,r)];function o0(e,t){return Math.random()*(t-e)+e}const Eh={Centered:uge,Randomized:fge};function dge(){return{autoResize:!1,callbacks:{},hooks:{},initial:sge(),nodeRadius:16,marker:i1.Arrow(4),modifiers:{},positionInitializer:Eh.Centered,simulation:{alphas:rge(),forces:oge()},zoom:{initial:1,min:.1,max:2}}}function hge(e={}){return ige.withOptions({mergeArrays:!1},dge(),e)}function pge({applyZoom:e,container:t,onDoubleClick:r,onPointerMoved:o,onPointerUp:s,offset:[c,f],scale:d,zoom:h}){const p=t.classed(\"graph\",!0).append(\"svg\").attr(\"height\",\"100%\").attr(\"width\",\"100%\").call(h).on(\"contextmenu\",g=>t1(g)).on(\"dblclick\",g=>r?.(g)).on(\"dblclick.zoom\",null).on(\"pointermove\",g=>o?.(g)).on(\"pointerup\",g=>s?.(g)).style(\"cursor\",\"grab\");return e&&p.call(h.transform,Op.translate(c,f).scale(d)),p.append(\"g\")}function gge({canvas:e,scale:t,xOffset:r,yOffset:o}){e?.attr(\"transform\",`translate(${r},${o})scale(${t})`)}function mge({config:e,onDragStart:t,onDragEnd:r}){const o=Rde().filter(s=>s.type===\"mousedown\"?s.button===0:s.type===\"touchstart\"?s.touches.length===1:!1).on(\"start\",(s,c)=>{s.active===0&&t(s,c),Kn(s.sourceEvent.target).classed(\"grabbed\",!0),c.fx=c.x,c.fy=c.y}).on(\"drag\",(s,c)=>{c.fx=s.x,c.fy=s.y}).on(\"end\",(s,c)=>{s.active===0&&r(s,c),Kn(s.sourceEvent.target).classed(\"grabbed\",!1),c.fx=void 0,c.fy=void 0});return e.modifiers.drag?.(o),o}function vge({graph:e,filter:t,focusedNode:r,includeUnlinked:o,linkFilter:s}){const c=e.links.filter(h=>t.includes(h.source.type)&&t.includes(h.target.type)&&s(h)),f=h=>c.find(p=>p.source.id===h.id||p.target.id===h.id)!==void 0,d=e.nodes.filter(h=>t.includes(h.type)&&(o||f(h)));return r===void 0||!t.includes(r.type)?{nodes:d,links:c}:yge({links:c},r)}function yge(e,t){const r=[...bge(e,t),...wge(e,t)],o=r.flatMap(s=>[s.source,s.target]);return{nodes:[...new Set([...o,t])],links:[...new Set(r)]}}function bge(e,t){return o1(e,t,(r,o)=>r.target.id===o.id)}function wge(e,t){return o1(e,t,(r,o)=>r.source.id===o.id)}function o1(e,t,r){const o=new Set(e.links),s=new Set([t]),c=[];for(;o.size>0;){const f=[...o].filter(d=>[...s].some(h=>r(d,h)));if(f.length===0)return c;f.forEach(d=>{s.add(d.source),s.add(d.target),c.push(d),o.delete(d)})}return c}function Ah(e){return e.x??0}function Lh(e){return e.y??0}function $p({source:e,target:t}){const r=new tl(Ah(e),Lh(e)),o=new tl(Ah(t),Lh(t)),s=o.subtract(r),c=s.length(),f=s.normalize();return{s:r,t:o,dist:c,norm:f,endNorm:f.multiply(-1)}}function s1({center:e,node:t}){const r=new tl(Ah(t),Lh(t));let o=e;return r.x===o.x&&r.y===o.y&&(o=o.add(new tl(0,1))),{n:r,c:o}}function l1({config:e,source:t,target:r}){const{s:o,t:s,norm:c}=$p({source:t,target:r});return{start:o.add(c.multiply(mo(e,t)-1)),end:s.subtract(c.multiply(e.marker.padding(r,e)))}}function xge(e){const{start:t,end:r}=l1(e);return`M${t.x},${t.y}\n          L${r.x},${r.y}`}function kge(e){const{start:t,end:r}=l1(e),o=r.subtract(t).multiply(.5),s=t.add(o);return`translate(${s.x-8},${s.y-4})`}function Sge({config:e,source:t,target:r}){const{s:o,t:s,dist:c,norm:f,endNorm:d}=$p({source:t,target:r}),h=10,p=f.rotateByDegrees(-h).multiply(mo(e,t)-1).add(o),g=d.rotateByDegrees(h).multiply(mo(e,r)).add(s).add(d.rotateByDegrees(h).multiply(2*e.marker.size)),v=1.2*c;return`M${p.x},${p.y}\n          A${v},${v},0,0,1,${g.x},${g.y}`}function _ge({center:e,config:t,node:r}){const{n:o,c:s}=s1({center:e,node:r}),c=mo(t,r),f=o.subtract(s),d=f.multiply(1/f.length()),h=40,p=d.rotateByDegrees(h).multiply(c-1).add(o),g=d.rotateByDegrees(-h).multiply(c).add(o).add(d.rotateByDegrees(-h).multiply(2*t.marker.size));return`M${p.x},${p.y}\n          A${c},${c},0,1,0,${g.x},${g.y}`}function Tge({config:e,source:t,target:r}){const{t:o,dist:s,endNorm:c}=$p({source:t,target:r}),f=c.rotateByDegrees(10).multiply(.5*s).add(o);return`translate(${f.x},${f.y})`}function Cge({center:e,config:t,node:r}){const{n:o,c:s}=s1({center:e,node:r}),c=o.subtract(s),f=c.multiply(1/c.length()).multiply(3*mo(t,r)+8).add(o);return`translate(${f.x},${f.y})`}const Vs={line:{labelTransform:kge,path:xge},arc:{labelTransform:Tge,path:Sge},reflexive:{labelTransform:Cge,path:_ge}};function Ege(e){return e.append(\"g\").classed(\"links\",!0).selectAll(\"path\")}function Age({config:e,graph:t,selection:r,showLabels:o}){const s=r?.data(t.links,c=>lge(c)).join(c=>{const f=c.append(\"g\"),d=f.append(\"path\").classed(\"link\",!0).style(\"marker-end\",p=>age(p)).style(\"stroke\",p=>p.color);e.modifiers.link?.(d);const h=f.append(\"text\").classed(\"link__label\",!0).style(\"fill\",p=>p.label?p.label.color:null).style(\"font-size\",p=>p.label?p.label.fontSize:null).text(p=>p.label?p.label.text:null);return e.modifiers.linkLabel?.(h),f});return s?.select(\".link__label\").attr(\"opacity\",c=>c.label&&o?1:0),s}function Lge(e){Mge(e),Nge(e)}function Mge({center:e,config:t,graph:r,selection:o}){o?.selectAll(\"path\").attr(\"d\",s=>s.source.x===void 0||s.source.y===void 0||s.target.x===void 0||s.target.y===void 0?\"\":s.source.id===s.target.id?Vs.reflexive.path({config:t,node:s.source,center:e}):a1(r,s.source,s.target)?Vs.arc.path({config:t,source:s.source,target:s.target}):Vs.line.path({config:t,source:s.source,target:s.target}))}function Nge({config:e,center:t,graph:r,selection:o}){o?.select(\".link__label\").attr(\"transform\",s=>s.source.x===void 0||s.source.y===void 0||s.target.x===void 0||s.target.y===void 0?\"translate(0, 0)\":s.source.id===s.target.id?Vs.reflexive.labelTransform({config:e,node:s.source,center:t}):a1(r,s.source,s.target)?Vs.arc.labelTransform({config:e,source:s.source,target:s.target}):Vs.line.labelTransform({config:e,source:s.source,target:s.target}))}function a1(e,t,r){return t.id!==r.id&&e.links.some(o=>o.target.id===t.id&&o.source.id===r.id)&&e.links.some(o=>o.target.id===r.id&&o.source.id===t.id)}function Oge(e){return e.append(\"defs\").selectAll(\"marker\")}function Pge({config:e,graph:t,selection:r}){return r?.data(Rge(t),o=>o).join(o=>{const s=o.append(\"marker\").attr(\"id\",c=>r1(c)).attr(\"markerHeight\",4*e.marker.size).attr(\"markerWidth\",4*e.marker.size).attr(\"markerUnits\",\"userSpaceOnUse\").attr(\"orient\",\"auto\").attr(\"refX\",e.marker.ref[0]).attr(\"refY\",e.marker.ref[1]).attr(\"viewBox\",e.marker.viewBox).style(\"fill\",c=>c);return s.append(\"path\").attr(\"d\",$ge(e.marker.path)),s})}function Rge(e){return[...new Set(e.links.map(t=>t.color))]}function $ge(e){const[t,...r]=e;if(!t)return\"M0,0\";const[o,s]=t;return r.reduce((c,[f,d])=>`${c}L${f},${d}`,`M${o},${s}`)}function Ige(e){return e.append(\"g\").classed(\"nodes\",!0).selectAll(\"circle\")}function Dge({config:e,drag:t,graph:r,onNodeContext:o,onNodeSelected:s,selection:c,showLabels:f}){const d=c?.data(r.nodes,h=>h.id).join(h=>{const p=h.append(\"g\");t!==void 0&&p.call(t);const g=p.append(\"circle\").classed(\"node\",!0).attr(\"r\",b=>mo(e,b)).on(\"contextmenu\",(b,w)=>{t1(b),o(w)}).on(\"pointerdown\",(b,w)=>Fge(b,w,s??o)).style(\"fill\",b=>b.color);e.modifiers.node?.(g);const v=p.append(\"text\").classed(\"node__label\",!0).attr(\"dy\",\"0.33em\").style(\"fill\",b=>b.label?b.label.color:null).style(\"font-size\",b=>b.label?b.label.fontSize:null).style(\"stroke\",\"none\").text(b=>b.label?b.label.text:null);return e.modifiers.nodeLabel?.(v),p});return d?.select(\".node\").classed(\"focused\",h=>h.isFocused),d?.select(\".node__label\").attr(\"opacity\",f?1:0),d}const zge=500;function Fge(e,t,r){if(e.button!==void 0&&e.button!==0)return;const o=t.lastInteractionTimestamp,s=Date.now();if(o===void 0||s-o>zge){t.lastInteractionTimestamp=s;return}t.lastInteractionTimestamp=void 0,r(t)}function Hge(e){e?.attr(\"transform\",t=>`translate(${t.x??0},${t.y??0})`)}function Bge({center:e,config:t,graph:r,onTick:o}){const s=Qpe(r.nodes),c=t.simulation.forces.centering;if(c&&c.enabled){const p=c.strength;s.force(\"x\",tge(()=>e().x).strength(p)).force(\"y\",nge(()=>e().y).strength(p))}const f=t.simulation.forces.charge;f&&f.enabled&&s.force(\"charge\",ege().strength(f.strength));const d=t.simulation.forces.collision;d&&d.enabled&&s.force(\"collision\",qpe().radius(p=>d.radiusMultiplier*mo(t,p)));const h=t.simulation.forces.link;return h&&h.enabled&&s.force(\"link\",Upe(r.links).id(p=>p.id).distance(t.simulation.forces.link.length).strength(h.strength)),s.on(\"tick\",()=>o()),t.modifiers.simulation?.(s),s}function Wge({canvasContainer:e,config:t,min:r,max:o,onZoom:s}){const c=_pe().scaleExtent([r,o]).filter(f=>f.button===0||f.touches?.length>=2).on(\"start\",()=>e().classed(\"grabbed\",!0)).on(\"zoom\",f=>s(f)).on(\"end\",()=>e().classed(\"grabbed\",!1));return t.modifiers.zoom?.(c),c}var qge=class{nodeTypes;_nodeTypeFilter;_includeUnlinked=!0;_linkFilter=()=>!0;_showLinkLabels=!0;_showNodeLabels=!0;filteredGraph;width=0;height=0;simulation;canvas;linkSelection;nodeSelection;markerSelection;zoom;drag;xOffset=0;yOffset=0;scale;focusedNode=void 0;resizeObserver;container;graph;config;constructor(e,t,r){if(this.container=e,this.graph=t,this.config=r,this.scale=r.zoom.initial,this.resetView(),this.graph.nodes.forEach(o=>{const[s,c]=r.positionInitializer(o,this.effectiveWidth,this.effectiveHeight);o.x=o.x??s,o.y=o.y??c}),this.nodeTypes=[...new Set(t.nodes.map(o=>o.type))],this._nodeTypeFilter=[...this.nodeTypes],r.initial){const{includeUnlinked:o,nodeTypeFilter:s,linkFilter:c,showLinkLabels:f,showNodeLabels:d}=r.initial;this._includeUnlinked=o??this._includeUnlinked,this._showLinkLabels=f??this._showLinkLabels,this._showNodeLabels=d??this._showNodeLabels,this._nodeTypeFilter=s??this._nodeTypeFilter,this._linkFilter=c??this._linkFilter}this.filterGraph(void 0),this.initGraph(),this.restart(r.simulation.alphas.initialize),r.autoResize&&(this.resizeObserver=new ResizeObserver(Vue(()=>this.resize())),this.resizeObserver.observe(this.container))}get nodeTypeFilter(){return this._nodeTypeFilter}get includeUnlinked(){return this._includeUnlinked}set includeUnlinked(e){this._includeUnlinked=e,this.filterGraph(this.focusedNode);const{include:t,exclude:r}=this.config.simulation.alphas.filter.unlinked,o=e?t:r;this.restart(o)}set linkFilter(e){this._linkFilter=e,this.filterGraph(this.focusedNode),this.restart(this.config.simulation.alphas.filter.link)}get linkFilter(){return this._linkFilter}get showNodeLabels(){return this._showNodeLabels}set showNodeLabels(e){this._showNodeLabels=e;const{hide:t,show:r}=this.config.simulation.alphas.labels.nodes,o=e?r:t;this.restart(o)}get showLinkLabels(){return this._showLinkLabels}set showLinkLabels(e){this._showLinkLabels=e;const{hide:t,show:r}=this.config.simulation.alphas.labels.links,o=e?r:t;this.restart(o)}get effectiveWidth(){return this.width/this.scale}get effectiveHeight(){return this.height/this.scale}get effectiveCenter(){return tl.of([this.width,this.height]).divide(2).subtract(tl.of([this.xOffset,this.yOffset])).divide(this.scale)}resize(){const e=this.width,t=this.height,r=this.container.getBoundingClientRect().width,o=this.container.getBoundingClientRect().height,s=e.toFixed()!==r.toFixed(),c=t.toFixed()!==o.toFixed();if(!s&&!c)return;this.width=this.container.getBoundingClientRect().width,this.height=this.container.getBoundingClientRect().height;const f=this.config.simulation.alphas.resize;this.restart(n1(f)?f:f({oldWidth:e,oldHeight:t,newWidth:r,newHeight:o}))}restart(e){this.markerSelection=Pge({config:this.config,graph:this.filteredGraph,selection:this.markerSelection}),this.linkSelection=Age({config:this.config,graph:this.filteredGraph,selection:this.linkSelection,showLabels:this._showLinkLabels}),this.nodeSelection=Dge({config:this.config,drag:this.drag,graph:this.filteredGraph,onNodeContext:t=>this.toggleNodeFocus(t),onNodeSelected:this.config.callbacks.nodeClicked,selection:this.nodeSelection,showLabels:this._showNodeLabels}),this.simulation?.stop(),this.simulation=Bge({center:()=>this.effectiveCenter,config:this.config,graph:this.filteredGraph,onTick:()=>this.onTick()}).alpha(e).restart()}filterNodesByType(e,t){e?this._nodeTypeFilter.push(t):this._nodeTypeFilter=this._nodeTypeFilter.filter(r=>r!==t),this.filterGraph(this.focusedNode),this.restart(this.config.simulation.alphas.filter.type)}shutdown(){this.focusedNode!==void 0&&(this.focusedNode.isFocused=!1,this.focusedNode=void 0),this.resizeObserver?.unobserve(this.container),this.simulation?.stop()}initGraph(){this.zoom=Wge({config:this.config,canvasContainer:()=>Kn(this.container).select(\"svg\"),min:this.config.zoom.min,max:this.config.zoom.max,onZoom:e=>this.onZoom(e)}),this.canvas=pge({applyZoom:this.scale!==1,container:Kn(this.container),offset:[this.xOffset,this.yOffset],scale:this.scale,zoom:this.zoom}),this.applyZoom(),this.linkSelection=Ege(this.canvas),this.nodeSelection=Ige(this.canvas),this.markerSelection=Oge(this.canvas),this.drag=mge({config:this.config,onDragStart:()=>this.simulation?.alphaTarget(this.config.simulation.alphas.drag.start).restart(),onDragEnd:()=>this.simulation?.alphaTarget(this.config.simulation.alphas.drag.end).restart()})}onTick(){Hge(this.nodeSelection),Lge({config:this.config,center:this.effectiveCenter,graph:this.filteredGraph,selection:this.linkSelection})}resetView(){this.simulation?.stop(),Kn(this.container).selectChildren().remove(),this.zoom=void 0,this.canvas=void 0,this.linkSelection=void 0,this.nodeSelection=void 0,this.markerSelection=void 0,this.simulation=void 0,this.width=this.container.getBoundingClientRect().width,this.height=this.container.getBoundingClientRect().height}onZoom(e){this.xOffset=e.transform.x,this.yOffset=e.transform.y,this.scale=e.transform.k,this.applyZoom(),this.config.hooks.afterZoom?.(this.scale,this.xOffset,this.yOffset),this.simulation?.restart()}applyZoom(){gge({canvas:this.canvas,scale:this.scale,xOffset:this.xOffset,yOffset:this.yOffset})}toggleNodeFocus(e){e.isFocused?(this.filterGraph(void 0),this.restart(this.config.simulation.alphas.focus.release(e))):this.focusNode(e)}focusNode(e){this.filterGraph(e),this.restart(this.config.simulation.alphas.focus.acquire(e))}filterGraph(e){this.focusedNode!==void 0&&(this.focusedNode.isFocused=!1,this.focusedNode=void 0),e!==void 0&&this._nodeTypeFilter.includes(e.type)&&(e.isFocused=!0,this.focusedNode=e),this.filteredGraph=vge({graph:this.graph,filter:this._nodeTypeFilter,focusedNode:this.focusedNode,includeUnlinked:this._includeUnlinked,linkFilter:this._linkFilter})}};function s0({nodes:e,links:t}){return{nodes:e??[],links:t??[]}}function jge(e){return{...e}}function Ip(e){return{...e,isFocused:!1,lastInteractionTimestamp:void 0}}function Uge(e){const t=e.map(o=>Jw(o)),r=eL(t);return t.map(({raw:o,id:s,splits:c})=>Ip({color:\"var(--color-node-external)\",label:{color:\"var(--color-node-external)\",fontSize:\"0.875rem\",text:s.includes(\"node_modules\")?r.get(o)??o:c.pop()},isFocused:!1,id:s,type:\"external\"}))}function Vge(e,t){return Ip({color:t?\"var(--color-node-root)\":\"var(--color-node-inline)\",label:{color:t?\"var(--color-node-root)\":\"var(--color-node-inline)\",fontSize:\"0.875rem\",text:e.split(/\\//g).pop()},isFocused:!1,id:e,type:\"inline\"})}function Gge(e,t){if(!e)return s0({});const r=Uge(e.externalized),o=e.inlined.map(d=>Vge(d,d===t))??[],s=[...r,...o],c=Object.fromEntries(s.map(d=>[d.id,d])),f=Object.entries(e.graph).flatMap(([d,h])=>h.map(p=>{const g=c[d],v=c[p];if(!(g===void 0||v===void 0))return jge({source:g,target:v,color:\"var(--color-link)\",label:!1})}).filter(p=>p!==void 0));return s0({nodes:s,links:f})}const Kge={key:0,\"text-green-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:checkmark\":\"\"},Xge={key:1,\"text-red-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:compare\":\"\"},Yge={key:2,\"text-red-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:close\":\"\"},Zge={key:3,\"text-gray-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:document-blank\":\"\"},Jge={key:4,\"text-gray-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:redo\":\"\",\"rotate-90\":\"\"},Qge={key:5,\"text-yellow-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:circle-dash\":\"\",\"animate-spin\":\"\"},c1=rt({__name:\"StatusIcon\",props:{state:{},mode:{},failedSnapshot:{type:Boolean}},setup(e){return(t,r)=>{const o=vr(\"tooltip\");return e.state===\"pass\"?(ie(),ve(\"div\",Kge)):e.failedSnapshot?at((ie(),ve(\"div\",Xge,null,512)),[[o,\"Contains failed snapshot\",void 0,{right:!0}]]):e.state===\"fail\"?(ie(),ve(\"div\",Yge)):e.mode===\"todo\"?at((ie(),ve(\"div\",Zge,null,512)),[[o,\"Todo\",void 0,{right:!0}]]):e.mode===\"skip\"||e.state===\"skip\"?at((ie(),ve(\"div\",Jge,null,512)),[[o,\"Skipped\",void 0,{right:!0}]]):(ie(),ve(\"div\",Qge))}}}),ol=zE(),eme=xE(ol),tme={border:\"b base\",\"p-4\":\"\"},nme=[\"innerHTML\"],rme=rt({__name:\"ViewConsoleOutputEntry\",props:{taskName:{},type:{},time:{},content:{}},setup(e){function t(r){return new Date(r).toLocaleTimeString()}return(r,o)=>(ie(),ve(\"div\",tme,[X(\"div\",{\"text-xs\":\"\",\"mb-1\":\"\",class:ot(e.type===\"stderr\"?\"text-red-600 dark:text-red-300\":\"op30\")},Re(t(e.time))+\" | \"+Re(e.taskName)+\" | \"+Re(e.type),3),X(\"pre\",{\"data-type\":\"html\",innerHTML:e.content},null,8,nme)]))}}),ime={key:0,\"h-full\":\"\",class:\"scrolls\",flex:\"\",\"flex-col\":\"\",\"data-testid\":\"logs\"},ome={key:1,p6:\"\"},sme=rt({__name:\"ViewConsoleOutput\",setup(e){const t=ke(()=>{const o=Tx.value;if(o){const s=wp(ol.value);return o.map(({taskId:c,type:f,time:d,content:h})=>({taskId:c,type:f,time:d,content:s.toHtml(oa(h))}))}});function r(o){const s=o&&ft.state.idMap.get(o);return s&&\"filepath\"in s?s.name:(s?$A(s).slice(1).join(\" > \"):\"-\")||\"-\"}return(o,s)=>t.value?.length?(ie(),ve(\"div\",ime,[(ie(!0),ve(nt,null,$n(t.value,({taskId:c,type:f,time:d,content:h})=>(ie(),ve(\"div\",{key:c,\"font-mono\":\"\"},[Ne(rme,{\"task-name\":r(c),type:f,time:d,content:h},null,8,[\"task-name\",\"type\",\"time\",\"content\"])]))),128))])):(ie(),ve(\"div\",ome,[...s[0]||(s[0]=[Qe(\" Log something in your test and it would print here. (e.g. \",-1),X(\"pre\",{inline:\"\"},\"console.log(foo)\",-1),Qe(\") \",-1)])]))}}),u1={\"application/andrew-inset\":[\"ez\"],\"application/appinstaller\":[\"appinstaller\"],\"application/applixware\":[\"aw\"],\"application/appx\":[\"appx\"],\"application/appxbundle\":[\"appxbundle\"],\"application/atom+xml\":[\"atom\"],\"application/atomcat+xml\":[\"atomcat\"],\"application/atomdeleted+xml\":[\"atomdeleted\"],\"application/atomsvc+xml\":[\"atomsvc\"],\"application/atsc-dwd+xml\":[\"dwd\"],\"application/atsc-held+xml\":[\"held\"],\"application/atsc-rsat+xml\":[\"rsat\"],\"application/automationml-aml+xml\":[\"aml\"],\"application/automationml-amlx+zip\":[\"amlx\"],\"application/bdoc\":[\"bdoc\"],\"application/calendar+xml\":[\"xcs\"],\"application/ccxml+xml\":[\"ccxml\"],\"application/cdfx+xml\":[\"cdfx\"],\"application/cdmi-capability\":[\"cdmia\"],\"application/cdmi-container\":[\"cdmic\"],\"application/cdmi-domain\":[\"cdmid\"],\"application/cdmi-object\":[\"cdmio\"],\"application/cdmi-queue\":[\"cdmiq\"],\"application/cpl+xml\":[\"cpl\"],\"application/cu-seeme\":[\"cu\"],\"application/cwl\":[\"cwl\"],\"application/dash+xml\":[\"mpd\"],\"application/dash-patch+xml\":[\"mpp\"],\"application/davmount+xml\":[\"davmount\"],\"application/dicom\":[\"dcm\"],\"application/docbook+xml\":[\"dbk\"],\"application/dssc+der\":[\"dssc\"],\"application/dssc+xml\":[\"xdssc\"],\"application/ecmascript\":[\"ecma\"],\"application/emma+xml\":[\"emma\"],\"application/emotionml+xml\":[\"emotionml\"],\"application/epub+zip\":[\"epub\"],\"application/exi\":[\"exi\"],\"application/express\":[\"exp\"],\"application/fdf\":[\"fdf\"],\"application/fdt+xml\":[\"fdt\"],\"application/font-tdpfr\":[\"pfr\"],\"application/geo+json\":[\"geojson\"],\"application/gml+xml\":[\"gml\"],\"application/gpx+xml\":[\"gpx\"],\"application/gxf\":[\"gxf\"],\"application/gzip\":[\"gz\"],\"application/hjson\":[\"hjson\"],\"application/hyperstudio\":[\"stk\"],\"application/inkml+xml\":[\"ink\",\"inkml\"],\"application/ipfix\":[\"ipfix\"],\"application/its+xml\":[\"its\"],\"application/java-archive\":[\"jar\",\"war\",\"ear\"],\"application/java-serialized-object\":[\"ser\"],\"application/java-vm\":[\"class\"],\"application/javascript\":[\"*js\"],\"application/json\":[\"json\",\"map\"],\"application/json5\":[\"json5\"],\"application/jsonml+json\":[\"jsonml\"],\"application/ld+json\":[\"jsonld\"],\"application/lgr+xml\":[\"lgr\"],\"application/lost+xml\":[\"lostxml\"],\"application/mac-binhex40\":[\"hqx\"],\"application/mac-compactpro\":[\"cpt\"],\"application/mads+xml\":[\"mads\"],\"application/manifest+json\":[\"webmanifest\"],\"application/marc\":[\"mrc\"],\"application/marcxml+xml\":[\"mrcx\"],\"application/mathematica\":[\"ma\",\"nb\",\"mb\"],\"application/mathml+xml\":[\"mathml\"],\"application/mbox\":[\"mbox\"],\"application/media-policy-dataset+xml\":[\"mpf\"],\"application/mediaservercontrol+xml\":[\"mscml\"],\"application/metalink+xml\":[\"metalink\"],\"application/metalink4+xml\":[\"meta4\"],\"application/mets+xml\":[\"mets\"],\"application/mmt-aei+xml\":[\"maei\"],\"application/mmt-usd+xml\":[\"musd\"],\"application/mods+xml\":[\"mods\"],\"application/mp21\":[\"m21\",\"mp21\"],\"application/mp4\":[\"*mp4\",\"*mpg4\",\"mp4s\",\"m4p\"],\"application/msix\":[\"msix\"],\"application/msixbundle\":[\"msixbundle\"],\"application/msword\":[\"doc\",\"dot\"],\"application/mxf\":[\"mxf\"],\"application/n-quads\":[\"nq\"],\"application/n-triples\":[\"nt\"],\"application/node\":[\"cjs\"],\"application/octet-stream\":[\"bin\",\"dms\",\"lrf\",\"mar\",\"so\",\"dist\",\"distz\",\"pkg\",\"bpk\",\"dump\",\"elc\",\"deploy\",\"exe\",\"dll\",\"deb\",\"dmg\",\"iso\",\"img\",\"msi\",\"msp\",\"msm\",\"buffer\"],\"application/oda\":[\"oda\"],\"application/oebps-package+xml\":[\"opf\"],\"application/ogg\":[\"ogx\"],\"application/omdoc+xml\":[\"omdoc\"],\"application/onenote\":[\"onetoc\",\"onetoc2\",\"onetmp\",\"onepkg\",\"one\",\"onea\"],\"application/oxps\":[\"oxps\"],\"application/p2p-overlay+xml\":[\"relo\"],\"application/patch-ops-error+xml\":[\"xer\"],\"application/pdf\":[\"pdf\"],\"application/pgp-encrypted\":[\"pgp\"],\"application/pgp-keys\":[\"asc\"],\"application/pgp-signature\":[\"sig\",\"*asc\"],\"application/pics-rules\":[\"prf\"],\"application/pkcs10\":[\"p10\"],\"application/pkcs7-mime\":[\"p7m\",\"p7c\"],\"application/pkcs7-signature\":[\"p7s\"],\"application/pkcs8\":[\"p8\"],\"application/pkix-attr-cert\":[\"ac\"],\"application/pkix-cert\":[\"cer\"],\"application/pkix-crl\":[\"crl\"],\"application/pkix-pkipath\":[\"pkipath\"],\"application/pkixcmp\":[\"pki\"],\"application/pls+xml\":[\"pls\"],\"application/postscript\":[\"ai\",\"eps\",\"ps\"],\"application/provenance+xml\":[\"provx\"],\"application/pskc+xml\":[\"pskcxml\"],\"application/raml+yaml\":[\"raml\"],\"application/rdf+xml\":[\"rdf\",\"owl\"],\"application/reginfo+xml\":[\"rif\"],\"application/relax-ng-compact-syntax\":[\"rnc\"],\"application/resource-lists+xml\":[\"rl\"],\"application/resource-lists-diff+xml\":[\"rld\"],\"application/rls-services+xml\":[\"rs\"],\"application/route-apd+xml\":[\"rapd\"],\"application/route-s-tsid+xml\":[\"sls\"],\"application/route-usd+xml\":[\"rusd\"],\"application/rpki-ghostbusters\":[\"gbr\"],\"application/rpki-manifest\":[\"mft\"],\"application/rpki-roa\":[\"roa\"],\"application/rsd+xml\":[\"rsd\"],\"application/rss+xml\":[\"rss\"],\"application/rtf\":[\"rtf\"],\"application/sbml+xml\":[\"sbml\"],\"application/scvp-cv-request\":[\"scq\"],\"application/scvp-cv-response\":[\"scs\"],\"application/scvp-vp-request\":[\"spq\"],\"application/scvp-vp-response\":[\"spp\"],\"application/sdp\":[\"sdp\"],\"application/senml+xml\":[\"senmlx\"],\"application/sensml+xml\":[\"sensmlx\"],\"application/set-payment-initiation\":[\"setpay\"],\"application/set-registration-initiation\":[\"setreg\"],\"application/shf+xml\":[\"shf\"],\"application/sieve\":[\"siv\",\"sieve\"],\"application/smil+xml\":[\"smi\",\"smil\"],\"application/sparql-query\":[\"rq\"],\"application/sparql-results+xml\":[\"srx\"],\"application/sql\":[\"sql\"],\"application/srgs\":[\"gram\"],\"application/srgs+xml\":[\"grxml\"],\"application/sru+xml\":[\"sru\"],\"application/ssdl+xml\":[\"ssdl\"],\"application/ssml+xml\":[\"ssml\"],\"application/swid+xml\":[\"swidtag\"],\"application/tei+xml\":[\"tei\",\"teicorpus\"],\"application/thraud+xml\":[\"tfi\"],\"application/timestamped-data\":[\"tsd\"],\"application/toml\":[\"toml\"],\"application/trig\":[\"trig\"],\"application/ttml+xml\":[\"ttml\"],\"application/ubjson\":[\"ubj\"],\"application/urc-ressheet+xml\":[\"rsheet\"],\"application/urc-targetdesc+xml\":[\"td\"],\"application/voicexml+xml\":[\"vxml\"],\"application/wasm\":[\"wasm\"],\"application/watcherinfo+xml\":[\"wif\"],\"application/widget\":[\"wgt\"],\"application/winhlp\":[\"hlp\"],\"application/wsdl+xml\":[\"wsdl\"],\"application/wspolicy+xml\":[\"wspolicy\"],\"application/xaml+xml\":[\"xaml\"],\"application/xcap-att+xml\":[\"xav\"],\"application/xcap-caps+xml\":[\"xca\"],\"application/xcap-diff+xml\":[\"xdf\"],\"application/xcap-el+xml\":[\"xel\"],\"application/xcap-ns+xml\":[\"xns\"],\"application/xenc+xml\":[\"xenc\"],\"application/xfdf\":[\"xfdf\"],\"application/xhtml+xml\":[\"xhtml\",\"xht\"],\"application/xliff+xml\":[\"xlf\"],\"application/xml\":[\"xml\",\"xsl\",\"xsd\",\"rng\"],\"application/xml-dtd\":[\"dtd\"],\"application/xop+xml\":[\"xop\"],\"application/xproc+xml\":[\"xpl\"],\"application/xslt+xml\":[\"*xsl\",\"xslt\"],\"application/xspf+xml\":[\"xspf\"],\"application/xv+xml\":[\"mxml\",\"xhvml\",\"xvml\",\"xvm\"],\"application/yang\":[\"yang\"],\"application/yin+xml\":[\"yin\"],\"application/zip\":[\"zip\"],\"application/zip+dotlottie\":[\"lottie\"],\"audio/3gpp\":[\"*3gpp\"],\"audio/aac\":[\"adts\",\"aac\"],\"audio/adpcm\":[\"adp\"],\"audio/amr\":[\"amr\"],\"audio/basic\":[\"au\",\"snd\"],\"audio/midi\":[\"mid\",\"midi\",\"kar\",\"rmi\"],\"audio/mobile-xmf\":[\"mxmf\"],\"audio/mp3\":[\"*mp3\"],\"audio/mp4\":[\"m4a\",\"mp4a\",\"m4b\"],\"audio/mpeg\":[\"mpga\",\"mp2\",\"mp2a\",\"mp3\",\"m2a\",\"m3a\"],\"audio/ogg\":[\"oga\",\"ogg\",\"spx\",\"opus\"],\"audio/s3m\":[\"s3m\"],\"audio/silk\":[\"sil\"],\"audio/wav\":[\"wav\"],\"audio/wave\":[\"*wav\"],\"audio/webm\":[\"weba\"],\"audio/xm\":[\"xm\"],\"font/collection\":[\"ttc\"],\"font/otf\":[\"otf\"],\"font/ttf\":[\"ttf\"],\"font/woff\":[\"woff\"],\"font/woff2\":[\"woff2\"],\"image/aces\":[\"exr\"],\"image/apng\":[\"apng\"],\"image/avci\":[\"avci\"],\"image/avcs\":[\"avcs\"],\"image/avif\":[\"avif\"],\"image/bmp\":[\"bmp\",\"dib\"],\"image/cgm\":[\"cgm\"],\"image/dicom-rle\":[\"drle\"],\"image/dpx\":[\"dpx\"],\"image/emf\":[\"emf\"],\"image/fits\":[\"fits\"],\"image/g3fax\":[\"g3\"],\"image/gif\":[\"gif\"],\"image/heic\":[\"heic\"],\"image/heic-sequence\":[\"heics\"],\"image/heif\":[\"heif\"],\"image/heif-sequence\":[\"heifs\"],\"image/hej2k\":[\"hej2\"],\"image/ief\":[\"ief\"],\"image/jaii\":[\"jaii\"],\"image/jais\":[\"jais\"],\"image/jls\":[\"jls\"],\"image/jp2\":[\"jp2\",\"jpg2\"],\"image/jpeg\":[\"jpg\",\"jpeg\",\"jpe\"],\"image/jph\":[\"jph\"],\"image/jphc\":[\"jhc\"],\"image/jpm\":[\"jpm\",\"jpgm\"],\"image/jpx\":[\"jpx\",\"jpf\"],\"image/jxl\":[\"jxl\"],\"image/jxr\":[\"jxr\"],\"image/jxra\":[\"jxra\"],\"image/jxrs\":[\"jxrs\"],\"image/jxs\":[\"jxs\"],\"image/jxsc\":[\"jxsc\"],\"image/jxsi\":[\"jxsi\"],\"image/jxss\":[\"jxss\"],\"image/ktx\":[\"ktx\"],\"image/ktx2\":[\"ktx2\"],\"image/pjpeg\":[\"jfif\"],\"image/png\":[\"png\"],\"image/sgi\":[\"sgi\"],\"image/svg+xml\":[\"svg\",\"svgz\"],\"image/t38\":[\"t38\"],\"image/tiff\":[\"tif\",\"tiff\"],\"image/tiff-fx\":[\"tfx\"],\"image/webp\":[\"webp\"],\"image/wmf\":[\"wmf\"],\"message/disposition-notification\":[\"disposition-notification\"],\"message/global\":[\"u8msg\"],\"message/global-delivery-status\":[\"u8dsn\"],\"message/global-disposition-notification\":[\"u8mdn\"],\"message/global-headers\":[\"u8hdr\"],\"message/rfc822\":[\"eml\",\"mime\",\"mht\",\"mhtml\"],\"model/3mf\":[\"3mf\"],\"model/gltf+json\":[\"gltf\"],\"model/gltf-binary\":[\"glb\"],\"model/iges\":[\"igs\",\"iges\"],\"model/jt\":[\"jt\"],\"model/mesh\":[\"msh\",\"mesh\",\"silo\"],\"model/mtl\":[\"mtl\"],\"model/obj\":[\"obj\"],\"model/prc\":[\"prc\"],\"model/step\":[\"step\",\"stp\",\"stpnc\",\"p21\",\"210\"],\"model/step+xml\":[\"stpx\"],\"model/step+zip\":[\"stpz\"],\"model/step-xml+zip\":[\"stpxz\"],\"model/stl\":[\"stl\"],\"model/u3d\":[\"u3d\"],\"model/vrml\":[\"wrl\",\"vrml\"],\"model/x3d+binary\":[\"*x3db\",\"x3dbz\"],\"model/x3d+fastinfoset\":[\"x3db\"],\"model/x3d+vrml\":[\"*x3dv\",\"x3dvz\"],\"model/x3d+xml\":[\"x3d\",\"x3dz\"],\"model/x3d-vrml\":[\"x3dv\"],\"text/cache-manifest\":[\"appcache\",\"manifest\"],\"text/calendar\":[\"ics\",\"ifb\"],\"text/coffeescript\":[\"coffee\",\"litcoffee\"],\"text/css\":[\"css\"],\"text/csv\":[\"csv\"],\"text/html\":[\"html\",\"htm\",\"shtml\"],\"text/jade\":[\"jade\"],\"text/javascript\":[\"js\",\"mjs\"],\"text/jsx\":[\"jsx\"],\"text/less\":[\"less\"],\"text/markdown\":[\"md\",\"markdown\"],\"text/mathml\":[\"mml\"],\"text/mdx\":[\"mdx\"],\"text/n3\":[\"n3\"],\"text/plain\":[\"txt\",\"text\",\"conf\",\"def\",\"list\",\"log\",\"in\",\"ini\"],\"text/richtext\":[\"rtx\"],\"text/rtf\":[\"*rtf\"],\"text/sgml\":[\"sgml\",\"sgm\"],\"text/shex\":[\"shex\"],\"text/slim\":[\"slim\",\"slm\"],\"text/spdx\":[\"spdx\"],\"text/stylus\":[\"stylus\",\"styl\"],\"text/tab-separated-values\":[\"tsv\"],\"text/troff\":[\"t\",\"tr\",\"roff\",\"man\",\"me\",\"ms\"],\"text/turtle\":[\"ttl\"],\"text/uri-list\":[\"uri\",\"uris\",\"urls\"],\"text/vcard\":[\"vcard\"],\"text/vtt\":[\"vtt\"],\"text/wgsl\":[\"wgsl\"],\"text/xml\":[\"*xml\"],\"text/yaml\":[\"yaml\",\"yml\"],\"video/3gpp\":[\"3gp\",\"3gpp\"],\"video/3gpp2\":[\"3g2\"],\"video/h261\":[\"h261\"],\"video/h263\":[\"h263\"],\"video/h264\":[\"h264\"],\"video/iso.segment\":[\"m4s\"],\"video/jpeg\":[\"jpgv\"],\"video/jpm\":[\"*jpm\",\"*jpgm\"],\"video/mj2\":[\"mj2\",\"mjp2\"],\"video/mp2t\":[\"ts\",\"m2t\",\"m2ts\",\"mts\"],\"video/mp4\":[\"mp4\",\"mp4v\",\"mpg4\"],\"video/mpeg\":[\"mpeg\",\"mpg\",\"mpe\",\"m1v\",\"m2v\"],\"video/ogg\":[\"ogv\"],\"video/quicktime\":[\"qt\",\"mov\"],\"video/webm\":[\"webm\"]};Object.freeze(u1);var fr=function(e,t,r,o){if(r===\"a\"&&!o)throw new TypeError(\"Private accessor was defined without a getter\");if(typeof t==\"function\"?e!==t||!o:!t.has(e))throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");return r===\"m\"?o:r===\"a\"?o.call(e):o?o.value:t.get(e)},As,Kl,Do;class lme{constructor(...t){As.set(this,new Map),Kl.set(this,new Map),Do.set(this,new Map);for(const r of t)this.define(r)}define(t,r=!1){for(let[o,s]of Object.entries(t)){o=o.toLowerCase(),s=s.map(d=>d.toLowerCase()),fr(this,Do,\"f\").has(o)||fr(this,Do,\"f\").set(o,new Set);const c=fr(this,Do,\"f\").get(o);let f=!0;for(let d of s){const h=d.startsWith(\"*\");if(d=h?d.slice(1):d,c?.add(d),f&&fr(this,Kl,\"f\").set(o,d),f=!1,h)continue;const p=fr(this,As,\"f\").get(d);if(p&&p!=o&&!r)throw new Error(`\"${o} -> ${d}\" conflicts with \"${p} -> ${d}\". Pass \\`force=true\\` to override this definition.`);fr(this,As,\"f\").set(d,o)}}return this}getType(t){if(typeof t!=\"string\")return null;const r=t.replace(/^.*[/\\\\]/s,\"\").toLowerCase(),o=r.replace(/^.*\\./s,\"\").toLowerCase(),s=r.length<t.length;return!(o.length<r.length-1)&&s?null:fr(this,As,\"f\").get(o)??null}getExtension(t){return typeof t!=\"string\"?null:(t=t?.split?.(\";\")[0],(t&&fr(this,Kl,\"f\").get(t.trim().toLowerCase()))??null)}getAllExtensions(t){return typeof t!=\"string\"?null:fr(this,Do,\"f\").get(t.toLowerCase())??null}_freeze(){this.define=()=>{throw new Error(\"define() not allowed for built-in Mime objects. See https://github.com/broofa/mime/blob/main/README.md#custom-mime-instances\")},Object.freeze(this);for(const t of fr(this,Do,\"f\").values())Object.freeze(t);return this}_getTestState(){return{types:fr(this,As,\"f\"),extensions:fr(this,Kl,\"f\")}}}As=new WeakMap,Kl=new WeakMap,Do=new WeakMap;const ame=new lme(u1)._freeze();function Ma(e){if(gr)return`/data/${e.path}`;const t=e.contentType??\"application/octet-stream\";return e.path?`/__vitest_attachment__?path=${encodeURIComponent(e.path)}&contentType=${t}&token=${window.VITEST_API_TOKEN}`:`data:${t};base64,${e.body}`}function f1(e,t){const r=t?ame.getExtension(t):null;return e.replace(/[\\x00-\\x2C\\x2E\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7F]+/g,\"-\")+(r?`.${r}`:\"\")}function d1(e){const t=e.path||e.body;return typeof t==\"string\"&&(t.startsWith(\"http://\")||t.startsWith(\"https://\"))}function Mh(e){const t=e.path||e.body;return typeof t==\"string\"&&(t.startsWith(\"http://\")||t.startsWith(\"https://\"))?t:Ma(e)}const tu=rt({__name:\"CodeMirrorContainer\",props:da({mode:{},readOnly:{type:Boolean},saving:{type:Boolean}},{modelValue:{},modelModifiers:{}}),emits:da([\"save\",\"codemirror\"],[\"update:modelValue\"]),setup(e,{emit:t}){const r=t,o=Yu(e,\"modelValue\"),s=U_(),c={html:\"htmlmixed\",vue:\"htmlmixed\",svelte:\"htmlmixed\",js:\"javascript\",mjs:\"javascript\",cjs:\"javascript\",ts:{name:\"javascript\",typescript:!0},mts:{name:\"javascript\",typescript:!0},cts:{name:\"javascript\",typescript:!0},jsx:{name:\"javascript\",jsx:!0},tsx:{name:\"javascript\",typescript:!0,jsx:!0}},f=Ge();return Mi(async()=>{const d=hce(f,o,{...s,mode:c[e.mode||\"\"]||e.mode,readOnly:e.readOnly?!0:void 0,extraKeys:{\"Cmd-S\":function(h){h.getOption(\"readOnly\")||r(\"save\",h.getValue())},\"Ctrl-S\":function(h){h.getOption(\"readOnly\")||r(\"save\",h.getValue())}}});d.on(\"refresh\",()=>{r(\"codemirror\",d)}),d.on(\"change\",()=>{r(\"codemirror\",d)}),d.setSize(\"100%\",\"100%\"),d.clearHistory(),Nn.value=d,setTimeout(()=>Nn.value?.refresh(),100)}),(d,h)=>(ie(),ve(\"div\",{relative:\"\",\"font-mono\":\"\",\"text-sm\":\"\",class:ot([\"codemirror-scrolls\",e.saving?\"codemirror-busy\":void 0])},[X(\"textarea\",{ref_key:\"el\",ref:f},null,512)],2))}}),cme=rt({__name:\"ViewEditor\",props:{file:{}},emits:[\"draft\"],setup(e,{emit:t}){const r=e,o=t,s=Ge(\"\"),c=Ft(void 0),f=Ge(!1),d=Ge(!0),h=Ge(!1),p=Ge();xt(()=>r.file,async()=>{if(!h.value){d.value=!0;try{if(!r.file||!r.file?.filepath){s.value=\"\",c.value=s.value,f.value=!1,d.value=!1;return}s.value=await ft.rpc.readTestFile(r.file.filepath)||\"\",c.value=s.value,f.value=!1}catch(Z){console.error(\"cannot fetch file\",Z)}await Et(),d.value=!1}},{immediate:!0}),xt(()=>[d.value,h.value,r.file,hx.value,px.value],([Z,G,j,N,O])=>{!Z&&!G&&(N!=null?Et(()=>{const C=p.value,k=C??{line:(N??1)-1,ch:O??0};C?p.value=void 0:(Nn.value?.scrollIntoView(k,100),Et(()=>{Nn.value?.focus(),Nn.value?.setCursor(k)}))}):Et(()=>{Nn.value?.focus()}))},{flush:\"post\"});const g=ke(()=>r.file?.filepath?.split(/\\./g).pop()||\"js\"),v=Ge(),b=ke(()=>{const Z=[];function G(j){j.result?.errors&&Z.push(...j.result.errors),j.type===\"suite\"&&j.tasks.forEach(G)}return r.file?.tasks.forEach(G),Z}),w=ke(()=>{const Z=[];function G(j){j.type===\"test\"&&Z.push(...j.annotations),j.type===\"suite\"&&j.tasks.forEach(G)}return r.file?.tasks.forEach(G),Z}),E=[],L=[],P=[],M=Ge(!1);function R(){P.forEach(([Z,G,j])=>{Z.removeEventListener(\"click\",G),j()}),P.length=0}Ow(v,()=>{Nn.value?.refresh()});function I(){f.value=c.value!==Nn.value.getValue()}xt(f,Z=>{o(\"draft\",Z)},{immediate:!0});function _(Z){const j=(Z?.stacks||[]).filter(z=>z.file&&z.file===r.file?.filepath)?.[0];if(!j)return;const N=document.createElement(\"div\");N.className=\"op80 flex gap-x-2 items-center\";const O=document.createElement(\"pre\");O.className=\"c-red-600 dark:c-red-400\",O.textContent=`${\" \".repeat(j.column)}^ ${Z.name}: ${Z?.message||\"\"}`,N.appendChild(O);const C=document.createElement(\"span\");C.className=\"i-carbon-launch c-red-600 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em\",C.tabIndex=0,C.ariaLabel=\"Open in Editor\",bw(C,{content:\"Open in Editor\",placement:\"bottom\"},!1);const k=async()=>{await bp(j.file,j.line,j.column)};C.addEventListener(\"click\",k),N.appendChild(C),P.push([C,k,()=>ap(C)]),L.push(Nn.value.addLineClass(j.line-1,\"wrap\",\"bg-red-500/10\")),E.push(Nn.value.addLineWidget(j.line-1,N))}function $(Z){if(!Z.location)return;const{line:G,file:j}=Z.location;if(j!==r.file?.filepath)return;const N=document.createElement(\"div\");N.classList.add(\"wrap\",\"bg-active\",\"py-3\",\"px-6\",\"my-1\"),N.role=\"note\";const O=document.createElement(\"div\");O.classList.add(\"block\",\"text-black\",\"dark:text-white\");const C=document.createElement(\"span\");C.textContent=`${Z.type}: `,C.classList.add(\"font-bold\");const k=document.createElement(\"span\");k.classList.add(\"whitespace-pre\"),k.textContent=Z.message.replace(/[^\\r]\\n/,`\\r\n`),O.append(C,k),N.append(O);const z=Z.attachment;if(z?.path||z?.body)if(z.contentType?.startsWith(\"image/\")){const B=document.createElement(\"a\"),ce=document.createElement(\"img\");B.classList.add(\"inline-block\",\"mt-3\"),B.style.maxWidth=\"50vw\";const be=z.path||z.body;typeof be==\"string\"&&(be.startsWith(\"http://\")||be.startsWith(\"https://\"))?(ce.setAttribute(\"src\",be),B.referrerPolicy=\"no-referrer\"):ce.setAttribute(\"src\",Ma(z)),B.target=\"_blank\",B.href=ce.src,B.append(ce),N.append(B)}else{const B=document.createElement(\"a\");B.href=Ma(z),B.download=f1(Z.message,z.contentType),B.classList.add(\"flex\",\"w-min\",\"gap-2\",\"items-center\",\"font-sans\",\"underline\",\"cursor-pointer\");const ce=document.createElement(\"div\");ce.classList.add(\"i-carbon:download\",\"block\");const be=document.createElement(\"span\");be.textContent=\"Download\",B.append(ce,be),N.append(B)}E.push(Nn.value.addLineWidget(G-1,N))}const{pause:W,resume:ne}=xt([Nn,b,w,Ms],([Z,G,j,N])=>{if(!Z){E.length=0,L.length=0,R();return}N&&(Z.off(\"changes\",I),R(),E.forEach(O=>O.clear()),L.forEach(O=>Z?.removeLineClass(O,\"wrap\")),E.length=0,L.length=0,setTimeout(()=>{G.forEach(_),j.forEach($),M.value||Z.clearHistory(),Z.on(\"changes\",I)},100))},{flush:\"post\"});hp(()=>[Ms.value,h.value,p.value],([Z,G],j)=>{Z&&!G&&j&&j[2]&&Nn.value?.setCursor(j[2])},{debounce:100,flush:\"post\"});async function ee(Z){if(h.value)return;W(),h.value=!0,await Et();const G=Nn.value;G&&(G.setOption(\"readOnly\",!0),await Et(),G.refresh()),p.value=G?.getCursor(),G?.off(\"changes\",I),R(),E.forEach(j=>j.clear()),L.forEach(j=>G?.removeLineClass(j,\"wrap\")),E.length=0,L.length=0;try{M.value=!0,await ft.rpc.saveTestFile(r.file.filepath,Z),c.value=Z,f.value=!1}catch(j){console.error(\"error saving file\",j)}M.value||G?.clearHistory();try{await Uv(Ms).toBe(!1,{flush:\"sync\",timeout:1e3,throwOnTimeout:!0}),await Uv(Ms).toBe(!0,{flush:\"sync\",timeout:1e3,throwOnTimeout:!1})}catch{}b.value.forEach(_),w.value.forEach($),G?.on(\"changes\",I),h.value=!1,await Et(),G&&(G.setOption(\"readOnly\",!1),await Et(),G.refresh()),ne()}return $a(R),(Z,G)=>(ie(),Ve(tu,ki({ref_key:\"editor\",ref:v,modelValue:s.value,\"onUpdate:modelValue\":G[0]||(G[0]=j=>s.value=j),\"h-full\":\"\"},{lineNumbers:!0,readOnly:K(gr),saving:h.value},{mode:g.value,\"data-testid\":\"code-mirror\",onSave:ee}),null,16,[\"modelValue\",\"mode\"]))}}),Dp=rt({__name:\"Modal\",props:da({direction:{default:\"bottom\"}},{modelValue:{type:Boolean,default:!1},modelModifiers:{}}),emits:[\"update:modelValue\"],setup(e){const t=Yu(e,\"modelValue\"),r=ke(()=>{switch(e.direction){case\"bottom\":return\"bottom-0 left-0 right-0 border-t\";case\"top\":return\"top-0 left-0 right-0 border-b\";case\"left\":return\"bottom-0 left-0 top-0 border-r\";case\"right\":return\"bottom-0 top-0 right-0 border-l\";default:return\"\"}}),o=ke(()=>{switch(e.direction){case\"bottom\":return\"translateY(100%)\";case\"top\":return\"translateY(-100%)\";case\"left\":return\"translateX(-100%)\";case\"right\":return\"translateX(100%)\";default:return\"\"}}),s=()=>t.value=!1;return(c,f)=>(ie(),ve(\"div\",{class:ot([\"fixed inset-0 z-40\",t.value?\"\":\"pointer-events-none\"])},[X(\"div\",{class:ot([\"bg-base inset-0 absolute transition-opacity duration-500 ease-out\",t.value?\"opacity-50\":\"opacity-0\"]),onClick:s},null,2),X(\"div\",{class:ot([\"bg-base border-base absolute transition-all duration-200 ease-out scrolls\",[r.value]]),style:zt(t.value?{}:{transform:o.value})},[Dt(c.$slots,\"default\")],6)],2))}}),ume={class:\"overflow-auto max-h-120\"},fme={\"my-2\":\"\",\"mx-4\":\"\"},dme={\"op-70\":\"\"},hme={\"my-2\":\"\",\"mx-4\":\"\",\"text-sm\":\"\",\"font-light\":\"\",\"op-90\":\"\"},pme=[\"onClick\"],gme=rt({__name:\"ModuleGraphImportBreakdown\",emits:[\"select\"],setup(e,{emit:t}){const r=t,o=Ge(10),s=ke(()=>{const h=pr.value?.importDurations;if(!h)return[];const p=ei.value.root,g=[];for(const b in h){const w=h[b],E=w.external?tL(b):af(p,b);g.push({importedFile:b,relativeFile:f(E),selfTime:w.selfTime,totalTime:w.totalTime,formattedSelfTime:Fo(w.selfTime),formattedTotalTime:Fo(w.totalTime),selfTimeClass:_u(w.selfTime),totalTimeClass:_u(w.totalTime),external:w.external})}return g.sort((b,w)=>w.totalTime-b.totalTime)}),c=ke(()=>s.value.slice(0,o.value));function f(d){return d.length<=45?d:`...${d.slice(-45)}`}return(d,h)=>(ie(),ve(\"div\",ume,[X(\"h1\",fme,[h[1]||(h[1]=Qe(\" Import Duration Breakdown \",-1)),X(\"span\",dme,\"(ordered by Total Time) (Top \"+Re(Math.min(o.value,c.value.length))+\")\",1)]),X(\"table\",hme,[h[2]||(h[2]=X(\"thead\",null,[X(\"tr\",null,[X(\"th\",null,\" Module \"),X(\"th\",null,\" Self \"),X(\"th\",null,\" Total \"),X(\"th\",null,\" % \")])],-1)),X(\"tbody\",null,[(ie(!0),ve(nt,null,$n(c.value,p=>(ie(),ve(\"tr\",{key:p.importedFile},[X(\"td\",{class:\"cursor-pointer pr-2\",style:zt({color:p.external?\"var(--color-node-external)\":void 0}),onClick:g=>r(\"select\",p.importedFile,p.external?\"external\":\"inline\")},Re(p.relativeFile),13,pme),X(\"td\",{\"pr-2\":\"\",class:ot(p.selfTimeClass)},Re(p.formattedSelfTime),3),X(\"td\",{\"pr-2\":\"\",class:ot(p.totalTimeClass)},Re(p.formattedTotalTime),3),X(\"td\",{\"pr-2\":\"\",class:ot(p.totalTimeClass)},Re(Math.round(p.totalTime/s.value[0].totalTime*100))+\"% \",3)]))),128))])]),o.value<s.value.length?(ie(),ve(\"button\",{key:0,class:\"flex w-full justify-center h-8 text-sm z-10 relative font-light\",onClick:h[0]||(h[0]=p=>o.value+=5)},\" Show more \")):He(\"\",!0)]))}}),Cs=rt({__name:\"Badge\",props:{type:{default:\"info\"}},setup(e){return(t,r)=>(ie(),ve(\"span\",{class:ot([\"rounded-full py-0.5 px-2 text-xs text-white select-none\",{\"bg-red\":e.type===\"danger\",\"bg-orange\":e.type===\"warning\",\"bg-gray\":e.type===\"info\",\"bg-indigo/60\":e.type===\"tip\"}])},[Dt(t.$slots,\"default\")],2))}}),mme={\"w-350\":\"\",\"max-w-screen\":\"\",\"h-full\":\"\",flex:\"\",\"flex-col\":\"\"},vme={\"p-4\":\"\",relative:\"\"},yme={flex:\"\",\"justify-between\":\"\"},bme={\"mr-8\":\"\",flex:\"\",\"gap-2\":\"\",\"items-center\":\"\"},wme={op50:\"\",\"font-mono\":\"\",\"text-sm\":\"\"},xme={key:0,\"p-5\":\"\"},kme={key:0,p:\"x3 y-1\",\"bg-overlay\":\"\",border:\"base b t\"},Sme={key:0},_me={p:\"x3 y-1\",\"bg-overlay\":\"\",border:\"base b t\"},Tme=rt({__name:\"ModuleTransformResultView\",props:{id:{},projectName:{},type:{},canUndo:{type:Boolean}},emits:[\"close\",\"select\",\"back\"],setup(e,{emit:t}){const r=e,o=t,s=TE(()=>{if(pr.value?.id){if(r.type===\"inline\")return ft.rpc.getTransformResult(r.projectName,r.id,pr.value.id,!!Zn);if(r.type===\"external\")return ft.rpc.getExternalResult(r.id,pr.value.id)}}),c=ke(()=>{const I=pr.value?.importDurations||{};return I[r.id]||I[NA(\"/@fs/\",r.id)]||{}}),f=ke(()=>r.id?.split(/\\./g).pop()||\"js\"),d=ke(()=>s.value?.source?.trim()||\"\"),h=ke(()=>!s.value||!(\"code\"in s.value)||!ei.value.experimental?.fsModuleCache?void 0:s.value.code.lastIndexOf(\"vitestCache=\")!==-1),p=ke(()=>!s.value||!(\"code\"in s.value)?null:s.value.code.replace(/\\/\\/# sourceMappingURL=.*\\n/,\"\").replace(/\\/\\/# sourceMappingSource=.*\\n/,\"\").replace(/\\/\\/# vitestCache=.*\\n?/,\"\").trim()||\"\"),g=ke(()=>!s.value||!(\"map\"in s.value)?{mappings:\"\"}:{mappings:s.value?.map?.mappings??\"\",version:s.value?.map?.version}),v=[],b=[],w=[];function E(I,_){const $=I.coordsChar({left:_.clientX,top:_.clientY}),W=I.findMarksAt($);if(W.length!==1)return;const ne=W[0].title;if(ne){const ee=W[0].attributes?.[\"data-external\"]===\"true\"?\"external\":\"inline\";o(\"select\",ne,ee)}}function L(I){const _=document.createElement(\"div\");return _.classList.add(\"mb-5\"),I.forEach(({resolvedId:$,totalTime:W,external:ne})=>{const ee=document.createElement(\"div\");ee.append(document.createTextNode(\"import \"));const Z=document.createElement(\"span\"),G=af(ei.value.root,$);Z.textContent=`\"/${G}\"`,Z.className=\"hover:underline decoration-gray cursor-pointer select-none\",ee.append(Z),Z.addEventListener(\"click\",()=>{o(\"select\",$,ne?\"external\":\"inline\")});const j=document.createElement(\"span\");j.textContent=` ${Fo(W)}`;const N=_u(W);N&&j.classList.add(N),ee.append(j),_.append(ee)}),_}function P(I){const _=document.createElement(\"div\");_.className=\"flex ml-2\",_.textContent=Fo(I);const $=_u(I);return $&&_.classList.add($),_}function M(I){if(w.forEach(_=>_.clear()),w.length=0,v.forEach(_=>_.remove()),v.length=0,b.forEach(_=>_.clear()),b.length=0,s.value&&\"modules\"in s.value){I.off(\"mousedown\",E),I.on(\"mousedown\",E);const _=s.value.untrackedModules;if(_?.length){const $=L(_);v.push($),w.push(I.addLineWidget(0,$,{above:!0}))}s.value.modules?.forEach($=>{const W={line:$.start.line-1,ch:$.start.column},ne={line:$.end.line-1,ch:$.end.column},ee=I.markText(W,ne,{title:$.resolvedId,attributes:{\"data-external\":String($.external===!0)},className:\"hover:underline decoration-red cursor-pointer select-none\"});b.push(ee);const Z=P($.totalTime+($.transformTime||0));_?.length||Z.classList.add(\"-mt-5\"),v.push(Z),I.addWidget({line:$.end.line-1,ch:$.end.column+1},Z,!1)})}}function R(){o(\"back\")}return Cw(\"Escape\",()=>{o(\"close\")}),(I,_)=>{const $=vr(\"tooltip\");return ie(),ve(\"div\",mme,[X(\"div\",vme,[X(\"div\",yme,[X(\"p\",null,[e.canUndo?at((ie(),Ve(_t,{key:0,icon:\"i-carbon-arrow-left\",class:\"flex-inline\",onClick:_[0]||(_[0]=W=>R())},null,512)),[[$,\"Go Back\",void 0,{bottom:!0}]]):He(\"\",!0),_[7]||(_[7]=Qe(\" Module Info \",-1)),Ne(K(Qi),{class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[Qe(\" This is module is \"+Re(e.type===\"external\"?\"externalized\":\"inlined\")+\". \",1),e.type===\"external\"?(ie(),ve(nt,{key:0},[Qe(\" It means that the module was not processed by Vite plugins, but instead was directly imported by the environment. \")],64)):(ie(),ve(nt,{key:1},[Qe(\" It means that the module was processed by Vite plugins. \")],64))]),default:We(()=>[Ne(Cs,{type:\"custom\",\"ml-1\":\"\",style:zt({backgroundColor:`var(--color-node-${e.type})`})},{default:We(()=>[Qe(Re(e.type),1)]),_:1},8,[\"style\"])]),_:1}),h.value===!0?(ie(),Ve(K(Qi),{key:1,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[..._[4]||(_[4]=[Qe(' This module is cached on the file system under `experimental.fsModuleCachePath` (\"node_modules/.exprtimental-vitest-cache\" by default). ',-1)])]),default:We(()=>[Ne(Cs,{type:\"tip\",\"ml-2\":\"\"},{default:We(()=>[..._[3]||(_[3]=[Qe(\" cached \",-1)])]),_:1})]),_:1})):He(\"\",!0),h.value===!1?(ie(),Ve(K(Qi),{key:2,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[..._[6]||(_[6]=[X(\"p\",null,\"This module is not cached on the file system. It might be the first test run after cache invalidation or\",-1),X(\"p\",null,\"it was excluded manually via `experimental_defineCacheKeyGenerator`, or it cannot be cached (modules with `import.meta.glob`, for example).\",-1)])]),default:We(()=>[Ne(Cs,{type:\"warning\",\"ml-2\":\"\"},{default:We(()=>[..._[5]||(_[5]=[Qe(\" not cached \",-1)])]),_:1})]),_:1})):He(\"\",!0)]),X(\"div\",bme,[c.value.selfTime!=null&&c.value.external!==!0?(ie(),Ve(K(Qi),{key:0,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[Qe(\" It took \"+Re(K(Ed)(c.value.selfTime))+\" to import this module, excluding static imports. \",1)]),default:We(()=>[Ne(Cs,{type:K(Xc)(c.value.selfTime)},{default:We(()=>[Qe(\" self: \"+Re(K(Fo)(c.value.selfTime)),1)]),_:1},8,[\"type\"])]),_:1})):He(\"\",!0),c.value.totalTime!=null?(ie(),Ve(K(Qi),{key:1,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[Qe(\" It took \"+Re(K(Ed)(c.value.totalTime))+\" to import the whole module, including static imports. \",1)]),default:We(()=>[Ne(Cs,{type:K(Xc)(c.value.totalTime)},{default:We(()=>[Qe(\" total: \"+Re(K(Fo)(c.value.totalTime)),1)]),_:1},8,[\"type\"])]),_:1})):He(\"\",!0),K(s)&&\"transformTime\"in K(s)&&K(s).transformTime?(ie(),Ve(K(Qi),{key:2,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[Qe(\" It took \"+Re(K(Ed)(K(s).transformTime))+\" to transform this module by Vite plugins. \",1)]),default:We(()=>[Ne(Cs,{type:K(Xc)(K(s).transformTime)},{default:We(()=>[Qe(\" transform: \"+Re(K(Fo)(K(s).transformTime)),1)]),_:1},8,[\"type\"])]),_:1})):He(\"\",!0)])]),X(\"p\",wme,Re(e.id),1),Ne(_t,{icon:\"i-carbon-close\",absolute:\"\",\"top-5px\":\"\",\"right-5px\":\"\",\"text-2xl\":\"\",onClick:_[1]||(_[1]=W=>o(\"close\"))})]),K(s)?(ie(),ve(nt,{key:1},[X(\"div\",{grid:\"~ rows-[min-content_auto]\",\"overflow-hidden\":\"\",\"flex-auto\":\"\",class:ot({\"cols-2\":p.value!=null})},[_[8]||(_[8]=X(\"div\",{p:\"x3 y-1\",\"bg-overlay\":\"\",border:\"base b t r\"},\" Source \",-1)),p.value!=null?(ie(),ve(\"div\",kme,\" Transformed \")):He(\"\",!0),(ie(),Ve(tu,ki({key:e.id,\"h-full\":\"\",\"model-value\":d.value,\"read-only\":\"\"},{lineNumbers:!0},{mode:f.value,onCodemirror:_[2]||(_[2]=W=>M(W))}),null,16,[\"model-value\",\"mode\"])),p.value!=null?(ie(),Ve(tu,ki({key:1,\"h-full\":\"\",\"model-value\":p.value,\"read-only\":\"\"},{lineNumbers:!0},{mode:\"js\"}),null,16,[\"model-value\"])):He(\"\",!0)],2),g.value.mappings!==\"\"?(ie(),ve(\"div\",Sme,[X(\"div\",_me,\" Source map (v\"+Re(g.value.version)+\") \",1),Ne(tu,ki({\"model-value\":g.value.mappings,\"read-only\":\"\"},{lineNumbers:!0}),null,16,[\"model-value\"])])):He(\"\",!0)],64)):(ie(),ve(\"div\",xme,\" No transform result found for this module. \"))])}}}),Cme={\"h-full\":\"\",\"min-h-75\":\"\",\"flex-1\":\"\",overflow:\"hidden\"},Eme={flex:\"\",\"items-center\":\"\",\"gap-2\":\"\",\"px-3\":\"\",\"py-2\":\"\"},Ame={flex:\"~ gap-1\",\"items-center\":\"\",\"select-none\":\"\"},Lme={class:\"pr-2\"},Mme=[\"id\",\"checked\",\"onChange\"],Nme=[\"for\"],Ome={key:0,class:\"absolute bg-[#eee] dark:bg-[#222] border-base right-0 mr-2 rounded-xl mt-2\"},Pme=rt({__name:\"ViewModuleGraph\",props:da({graph:{},projectName:{}},{modelValue:{type:Boolean,required:!0},modelModifiers:{}}),emits:[\"update:modelValue\"],setup(e){const t=e,r=Yu(e,\"modelValue\"),{graph:o}=v_(t),s=Ge(),c=Ge(!1),f=Ge(),d=qE(f),h=Ge(),p=Ge(null),g=Ft(o.value),v=ke(()=>{let j=\"\";const N=pr.value?.importDurations||{};for(const O in N){const{totalTime:C}=N[O];if(C>=500){j=\"text-red\";break}else C>=100&&(j=\"text-orange\")}return j}),b=Ge(ei.value?.experimental?.printImportBreakdown??v.value===\"text-red\");Mi(()=>{g.value=L(o.value,null,2),ne()}),Ia(()=>{h.value?.shutdown()}),xt(o,()=>{g.value=L(o.value,p.value,2),ne()});function w(){g.value=o.value,ne()}function E(){b.value=!b.value}function L(j,N,O=2){if(!j.nodes.length||j.nodes.length<=50)return j;const C=new Map;j.nodes.forEach(Ae=>C.set(Ae.id,new Set)),j.links.forEach(Ae=>{const Ke=typeof Ae.source==\"object\"?Ae.source.id:String(Ae.source),je=typeof Ae.target==\"object\"?Ae.target.id:String(Ae.target);C.get(Ke)?.add(je),C.get(je)?.add(Ke)});let k;if(N)k=[N];else{const Ae=new Set(j.links.map(je=>typeof je.target==\"object\"?je.target.id:String(je.target))),Ke=j.nodes.filter(je=>je.type===\"inline\"&&!Ae.has(je.id));k=Ke.length>0?[Ke[0].id]:[j.nodes[0].id]}const z=new Set,B=k.map(Ae=>({id:Ae,level:0}));for(;B.length>0;){const{id:Ae,level:Ke}=B.shift();z.has(Ae)||Ke>O||(z.add(Ae),Ke<O&&(C.get(Ae)||new Set).forEach(Fe=>{z.has(Fe)||B.push({id:Fe,level:Ke+1})}))}const ce=new Map(j.nodes.map(Ae=>[Ae.id,Ae])),be=Array.from(z).map(Ae=>ce.get(Ae)).filter(Ae=>Ae!==void 0),Se=new Map(be.map(Ae=>[Ae.id,Ae])),Be=j.links.map(Ae=>{const Ke=typeof Ae.source==\"object\"?Ae.source.id:String(Ae.source),je=typeof Ae.target==\"object\"?Ae.target.id:String(Ae.target);if(z.has(Ke)&&z.has(je)){const Fe=Se.get(Ke),Pe=Se.get(je);if(Fe&&Pe)return{...Ae,source:Fe,target:Pe}}return null}).filter(Ae=>Ae!==null);return{nodes:be,links:Be}}function P(j,N){h.value?.filterNodesByType(N,j)}function M(j,N){f.value={id:j,type:N},c.value=!0}function R(){d.undo()}function I(){c.value=!1,d.clear()}function _(j){p.value=j,g.value=L(o.value,j,2),W(),ne()}function $(){p.value=null,g.value=L(o.value,null,2),W(),ne()}function W(){const j=g.value.nodes.map(C=>{let k,z;return C.id===p.value?(k=\"var(--color-node-focused)\",z=\"var(--color-node-focused)\"):C.type===\"inline\"?(k=C.color===\"var(--color-node-root)\"?\"var(--color-node-root)\":\"var(--color-node-inline)\",z=k):(k=\"var(--color-node-external)\",z=\"var(--color-node-external)\"),Ip({...C,color:k,label:C.label?{...C.label,color:z}:C.label})}),N=new Map(j.map(C=>[C.id,C])),O=g.value.links.map(C=>{const k=typeof C.source==\"object\"?C.source.id:String(C.source),z=typeof C.target==\"object\"?C.target.id:String(C.target);return{...C,source:N.get(k),target:N.get(z)}});g.value={nodes:j,links:O}}function ne(j=!1){if(h.value?.shutdown(),j&&!r.value){r.value=!0;return}if(!g.value||!s.value)return;const N=g.value.nodes.length;let O=1,C=.5;N>300?(O=.3,C=.2):N>200?(O=.4,C=.3):N>100?(O=.5,C=.3):N>50&&(O=.7,O=.4),h.value=new qge(s.value,g.value,hge({nodeRadius:10,autoResize:!0,simulation:{alphas:{initialize:1,resize:({newHeight:k,newWidth:z})=>k===0&&z===0?0:.05},forces:{collision:{radiusMultiplier:10},link:{length:140}}},marker:i1.Arrow(2),modifiers:{node:G},positionInitializer:o.value.nodes.length===1?Eh.Centered:Eh.Randomized,zoom:{initial:O,min:C,max:1.5}}))}const ee=j=>j.button===0,Z=j=>j.button===2;function G(j){if(gr)return;let N=0,O=0,C=0,k=!1;j.on(\"pointerdown\",(z,B)=>{!B.x||!B.y||(k=Z(z),!(!ee(z)&&!k)&&(N=B.x,O=B.y,C=Date.now()))}).on(\"pointerup\",(z,B)=>{if(!B.x||!B.y)return;const ce=Z(z);if(!ee(z)&&!ce||Date.now()-C>500)return;const be=B.x-N,Se=B.y-O;be**2+Se**2<100&&(!ce&&!z.shiftKey?M(B.id,B.type):(ce||z.shiftKey)&&(z.preventDefault(),B.type===\"inline\"&&_(B.id)))}).on(\"contextmenu\",z=>{z.preventDefault()})}return(j,N)=>{const O=vr(\"tooltip\");return ie(),ve(\"div\",Cme,[X(\"div\",null,[X(\"div\",Eme,[X(\"div\",Ame,[X(\"div\",Lme,Re(g.value.nodes.length)+\"/\"+Re(K(o).nodes.length)+\" \"+Re(g.value.nodes.length===1?\"module\":\"modules\"),1),at(X(\"input\",{id:\"hide-node-modules\",\"onUpdate:modelValue\":N[0]||(N[0]=C=>r.value=C),type:\"checkbox\"},null,512),[[Zb,r.value]]),N[9]||(N[9]=X(\"label\",{\"font-light\":\"\",\"text-sm\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",\"select-none\":\"\",truncate:\"\",for:\"hide-node-modules\",\"border-b-2\":\"\",border:\"$cm-namespace\"},\"Hide node_modules\",-1))]),(ie(!0),ve(nt,null,$n(h.value?.nodeTypes.sort(),C=>(ie(),ve(\"div\",{key:C,flex:\"~ gap-1\",\"items-center\":\"\",\"select-none\":\"\"},[X(\"input\",{id:`type-${C}`,type:\"checkbox\",checked:h.value?.nodeTypeFilter.includes(C),onChange:k=>P(C,k.target.checked)},null,40,Mme),X(\"label\",{\"font-light\":\"\",\"text-sm\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",capitalize:\"\",\"select-none\":\"\",truncate:\"\",for:`type-${C}`,\"border-b-2\":\"\",style:zt({\"border-color\":`var(--color-node-${C})`})},Re(C)+\" Modules\",13,Nme)]))),128)),N[10]||(N[10]=X(\"div\",{\"flex-auto\":\"\"},null,-1)),N[11]||(N[11]=X(\"div\",{flex:\"~ gap-2\",\"items-center\":\"\",\"text-xs\":\"\",\"opacity-60\":\"\"},[X(\"span\",null,\"Click on node: details • Right-click/Shift: expand graph\")],-1)),X(\"div\",null,[at(Ne(_t,{icon:\"i-carbon-notebook\",class:ot(v.value),onClick:N[1]||(N[1]=C=>E())},null,8,[\"class\"]),[[O,`${b.value?\"Hide\":\"Show\"} Import Breakdown`,void 0,{bottom:!0}]])]),X(\"div\",null,[at(Ne(_t,{icon:\"i-carbon-ibm-cloud-direct-link-2-connect\",onClick:N[2]||(N[2]=C=>w())},null,512),[[O,\"Show Full Graph\",void 0,{bottom:!0}]])]),X(\"div\",null,[at(Ne(_t,{icon:\"i-carbon-reset\",onClick:N[3]||(N[3]=C=>$())},null,512),[[O,\"Reset\",void 0,{bottom:!0}]])])])]),b.value?(ie(),ve(\"div\",Ome,[Ne(gme,{onSelect:N[4]||(N[4]=(C,k)=>M(C,k))})])):He(\"\",!0),X(\"div\",{ref_key:\"el\",ref:s},null,512),Ne(Dp,{modelValue:c.value,\"onUpdate:modelValue\":N[8]||(N[8]=C=>c.value=C),direction:\"right\"},{default:We(()=>[f.value?(ie(),Ve(np,{key:0},{default:We(()=>[Ne(Tme,{id:f.value.id,\"project-name\":e.projectName,type:f.value.type,\"can-undo\":K(d).undoStack.value.length>1,onClose:N[5]||(N[5]=C=>I()),onSelect:N[6]||(N[6]=(C,k)=>M(C,k)),onBack:N[7]||(N[7]=C=>R())},null,8,[\"id\",\"project-name\",\"type\",\"can-undo\"])]),_:1})):He(\"\",!0)]),_:1},8,[\"modelValue\"])])}}});function h1(e){const t=e.meta?.failScreenshotPath;t&&fetch(`/__open-in-editor?file=${encodeURIComponent(t)}`)}function p1(){const e=Ge(!1),t=Ge(Date.now()),r=Ge(),o=ke(()=>{const c=r.value?.id,f=t.value;return c?`/__screenshot-error?id=${encodeURIComponent(c)}&t=${f}`:void 0});function s(c){r.value=c,t.value=Date.now(),e.value=!0}return{currentTask:r,showScreenshot:e,currentScreenshotUrl:o,showScreenshotModal:s}}const Rme={\"w-350\":\"\",\"max-w-screen\":\"\",\"h-full\":\"\",flex:\"\",\"flex-col\":\"\"},$me={\"p-4\":\"\",relative:\"\",border:\"base b\"},Ime={op50:\"\",\"font-mono\":\"\",\"text-sm\":\"\"},Dme={op50:\"\",\"font-mono\":\"\",\"text-sm\":\"\"},zme={class:\"scrolls\",grid:\"~ cols-1 rows-[min-content]\",\"p-4\":\"\"},Fme=[\"src\",\"alt\"],Hme={key:1},Bme=rt({__name:\"ScreenshotError\",props:{file:{},name:{},url:{}},emits:[\"close\"],setup(e,{emit:t}){const r=t;return Cw(\"Escape\",()=>{r(\"close\")}),(o,s)=>(ie(),ve(\"div\",Rme,[X(\"div\",$me,[s[1]||(s[1]=X(\"p\",null,\"Screenshot error\",-1)),X(\"p\",Ime,Re(e.file),1),X(\"p\",Dme,Re(e.name),1),Ne(_t,{icon:\"i-carbon:close\",title:\"Close\",absolute:\"\",\"top-5px\":\"\",\"right-5px\":\"\",\"text-2xl\":\"\",onClick:s[0]||(s[0]=c=>r(\"close\"))})]),X(\"div\",zme,[e.url?(ie(),ve(\"img\",{key:0,src:e.url,alt:`Screenshot error for '${e.name}' test in file '${e.file}'`,border:\"base t r b l dotted red-500\"},null,8,Fme)):(ie(),ve(\"div\",Hme,\" Something was wrong, the image cannot be resolved. \"))])]))}}),g1=Ni(Bme,[[\"__scopeId\",\"data-v-08ce44b7\"]]),Wme={class:\"scrolls scrolls-rounded task-error\"},qme=[\"onClickPassive\"],jme=[\"innerHTML\"],Ume=rt({__name:\"ViewReportError\",props:{fileId:{},root:{},filename:{},error:{}},setup(e){const t=e;function r(d){return d.startsWith(t.root)?d.slice(t.root.length):d}const o=ke(()=>wp(ol.value)),s=ke(()=>!!t.error?.diff),c=ke(()=>t.error.diff?o.value.toHtml(oa(t.error.diff)):void 0);function f(d){return oce(d.file,t.filename)?pce(t.fileId,d):bp(d.file,d.line,d.column)}return(d,h)=>{const p=vr(\"tooltip\");return ie(),ve(\"div\",Wme,[X(\"pre\",null,[X(\"b\",null,Re(e.error.name),1),Qe(\": \"+Re(e.error.message),1)]),(ie(!0),ve(nt,null,$n(e.error.stacks,(g,v)=>(ie(),ve(\"div\",{key:v,class:\"op80 flex gap-x-2 items-center\",\"data-testid\":\"stack\"},[X(\"pre\",null,\" - \"+Re(r(g.file))+\":\"+Re(g.line)+\":\"+Re(g.column),1),at(X(\"div\",{class:\"i-carbon-launch c-red-600 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em\",tabindex:\"0\",\"aria-label\":\"Open in Editor\",onClickPassive:b=>f(g)},null,40,qme),[[p,\"Open in Editor\",void 0,{bottom:!0}]])]))),128)),s.value?(ie(),ve(\"pre\",{key:0,\"data-testid\":\"diff\",innerHTML:c.value},null,8,jme)):He(\"\",!0)])}}}),m1=Ni(Ume,[[\"__scopeId\",\"data-v-1fcfe7a4\"]]),Vme={\"h-full\":\"\",class:\"scrolls\"},Gme=[\"id\"],Kme={flex:\"~ gap-2 items-center\"},Xme={key:0,class:\"scrolls scrolls-rounded task-error\",\"data-testid\":\"task-error\"},Yme=[\"innerHTML\"],Zme={key:1,bg:\"green-500/10\",text:\"green-500 sm\",p:\"x4 y2\",\"m-2\":\"\",rounded:\"\"},Jme=rt({__name:\"ViewReport\",props:{file:{}},setup(e){const t=e;function r(h,p){return h.result?.state!==\"fail\"?[]:h.type===\"test\"?[{...h,level:p}]:[{...h,level:p},...h.tasks.flatMap(g=>r(g,p+1))]}const o=ke(()=>{const h=t.file,p=h.tasks?.flatMap(b=>r(b,0))??[],g=h.result;if(g?.errors?.[0]){const b={id:h.id,file:h,name:h.name,fullName:h.name,level:0,type:\"suite\",mode:\"run\",meta:{},tasks:[],result:g};p.unshift(b)}return p.length>0?dx(ol.value,p):p}),{currentTask:s,showScreenshot:c,showScreenshotModal:f,currentScreenshotUrl:d}=p1();return(h,p)=>{const g=vr(\"tooltip\");return ie(),ve(\"div\",Vme,[o.value.length?(ie(!0),ve(nt,{key:0},$n(o.value,v=>(ie(),ve(\"div\",{id:v.id,key:v.id},[X(\"div\",{bg:\"red-500/10\",text:\"red-500 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\",style:zt({\"margin-left\":`${v.result?.htmlError?.5:2*v.level+.5}rem`})},[X(\"div\",Kme,[X(\"span\",null,Re(v.name),1),K(Zn)&&v.meta?.failScreenshotPath?(ie(),ve(nt,{key:0},[at(Ne(_t,{class:\"!op-100\",icon:\"i-carbon:image\",title:\"View screenshot error\",onClick:b=>K(f)(v)},null,8,[\"onClick\"]),[[g,\"View screenshot error\",void 0,{bottom:!0}]]),at(Ne(_t,{class:\"!op-100\",icon:\"i-carbon:image-reference\",title:\"Open screenshot error in editor\",onClick:b=>K(h1)(v)},null,8,[\"onClick\"]),[[g,\"Open screenshot error in editor\",void 0,{bottom:!0}]])],64)):He(\"\",!0)]),v.result?.htmlError?(ie(),ve(\"div\",Xme,[X(\"pre\",{innerHTML:v.result.htmlError},null,8,Yme)])):v.result?.errors?(ie(!0),ve(nt,{key:1},$n(v.result.errors,(b,w)=>(ie(),Ve(m1,{key:w,error:b,filename:e.file.name,root:K(ei).root,\"file-id\":e.file.id},null,8,[\"error\",\"filename\",\"root\",\"file-id\"]))),128)):He(\"\",!0)],4)],8,Gme))),128)):(ie(),ve(\"div\",Zme,\" All tests passed in this file \")),K(Zn)?(ie(),Ve(Dp,{key:2,modelValue:K(c),\"onUpdate:modelValue\":p[1]||(p[1]=v=>Mt(c)?c.value=v:null),direction:\"right\"},{default:We(()=>[K(s)?(ie(),Ve(np,{key:0},{default:We(()=>[Ne(g1,{file:K(s).file.filepath,name:K(s).name,url:K(d),onClose:p[0]||(p[0]=v=>c.value=!1)},null,8,[\"file\",\"name\",\"url\"])]),_:1})):He(\"\",!0)]),_:1},8,[\"modelValue\"])):He(\"\",!0)])}}}),Qme=Ni(Jme,[[\"__scopeId\",\"data-v-9d875d6e\"]]),eve=[\"href\",\"referrerPolicy\"],tve=[\"src\"],nve=rt({__name:\"AnnotationAttachmentImage\",props:{annotation:{}},setup(e){const t=e,r=ke(()=>{const o=t.annotation.attachment,s=o.path||o.body;return typeof s==\"string\"&&(s.startsWith(\"http://\")||s.startsWith(\"https://\"))?s:Ma(o)});return(o,s)=>e.annotation.attachment&&e.annotation.attachment.contentType?.startsWith(\"image/\")?(ie(),ve(\"a\",{key:0,target:\"_blank\",class:\"inline-block mt-2\",style:{maxWidth:\"600px\"},href:r.value,referrerPolicy:K(d1)(e.annotation.attachment)?\"no-referrer\":void 0},[X(\"img\",{src:r.value},null,8,tve)],8,eve)):He(\"\",!0)}}),rve={class:\"flex flex-col gap-4\"},ive={key:0},ove=rt({__name:\"ArtifactTemplate\",setup(e){const t=yb();return(r,o)=>(ie(),ve(\"article\",rve,[X(\"h1\",null,[Dt(r.$slots,\"title\")]),K(t).message?(ie(),ve(\"p\",ive,[Dt(r.$slots,\"message\")])):He(\"\",!0),Dt(r.$slots,\"default\")]))}}),v1=Symbol(\"tabContext\"),Ru={tab:(e,t)=>`${t}-${e}-tab`,tabpanel:(e,t)=>`${t}-${e}-tabpanel`},sve={class:\"flex flex-col items-center gap-6\"},lve={role:\"tablist\",\"aria-orientation\":\"horizontal\",class:\"flex gap-4\"},ave=[\"id\",\"aria-selected\",\"aria-controls\",\"onClick\"],cve=rt({__name:\"SmallTabs\",setup(e){const t=Ge(null),r=Ge([]),o=Yh();return dr(v1,{id:o,activeTab:t,registerTab:s=>{r.value.some(({id:c})=>c===s.id)||r.value.push(s),r.value.length===1&&(t.value=s.id)},unregisterTab:s=>{const c=r.value.findIndex(({id:f})=>f===s.id);c>-1&&r.value.splice(c,1),t.value===s.id&&(t.value=r.value[0]?.id??null)}}),(s,c)=>(ie(),ve(\"div\",sve,[X(\"div\",lve,[(ie(!0),ve(nt,null,$n(r.value,f=>(ie(),ve(\"button\",{id:K(Ru).tab(f.id,K(o)),key:f.id,role:\"tab\",\"aria-selected\":t.value===f.id,\"aria-controls\":K(Ru).tabpanel(f.id,K(o)),type:\"button\",class:\"aria-[selected=true]:underline underline-offset-4\",onClick:d=>t.value=f.id},Re(f.title),9,ave))),128))]),Dt(s.$slots,\"default\")]))}}),uve=[\"id\",\"aria-labelledby\",\"hidden\"],Bc=rt({__name:\"SmallTabsPane\",props:{title:{}},setup(e){const t=e,r=pn(v1);if(!r)throw new Error(\"TabPane must be used within Tabs\");const o=Yh(),s=ke(()=>r.activeTab.value===o);return Mi(()=>{r.registerTab({...t,id:o})}),Ia(()=>{r.unregisterTab({...t,id:o})}),(c,f)=>(ie(),ve(\"div\",{id:K(Ru).tabpanel(K(o),K(r).id),role:\"tabpanel\",\"aria-labelledby\":K(Ru).tab(K(o),K(r).id),hidden:!s.value,class:\"max-w-full\"},[Dt(c.$slots,\"default\")],8,uve))}}),y1=rt({__name:\"VisualRegressionImageContainer\",setup(e){const t=`url(\"${CSS.escape('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 2 2\"><path d=\"M1 2V0h1v1H0v1z\" fill-opacity=\".05\"/></svg>')}\")`;return(r,o)=>(ie(),ve(\"div\",{class:\"max-w-full w-fit mx-auto bg-[size:16px_16px] bg-[#fafafa] dark:bg-[#3a3a3a] bg-center p-4 rounded user-select-none outline-0 outline-black dark:outline-white outline-offset-4 outline-solid focus-within:has-focus-visible:outline-2\",style:zt({backgroundImage:t})},[Dt(r.$slots,\"default\")],4))}}),fve=[\"href\",\"referrerPolicy\"],dve=[\"src\"],zd=rt({__name:\"VisualRegressionImage\",props:{attachment:{}},setup(e){const t=ke(()=>Mh(e.attachment));return(r,o)=>(ie(),Ve(y1,null,{default:We(()=>[X(\"a\",{target:\"_blank\",href:t.value,referrerPolicy:K(d1)(e.attachment)?\"no-referrer\":void 0},[X(\"img\",{src:t.value},null,8,dve)],8,fve)]),_:1}))}}),hve={class:\"absolute w-full h-full place-content-center place-items-center [clip-path:polygon(0%_0%,var(--split)_0%,var(--split)_100%,0%_100%)]\",\"aria-hidden\":\"true\",role:\"presentation\"},pve=[\"src\"],gve={class:\"absolute w-full h-full place-content-center place-items-center [clip-path:polygon(var(--split)_0%,100%_0%,100%_100%,var(--split)_100%)]\",\"aria-hidden\":\"true\",role:\"presentation\"},mve=[\"src\"],vve=[\"id\"],yve=[\"for\"],bve=rt({__name:\"VisualRegressionSlider\",props:{reference:{},actual:{}},setup(e){const t=ke(()=>Mh(e.reference)),r=ke(()=>Mh(e.actual)),o=ke(()=>Math.max(e.reference.width,e.actual.width)),s=ke(()=>Math.max(e.reference.height,e.actual.height)),c=Ge(50),f=Yh();return(d,h)=>(ie(),Ve(y1,null,{default:We(()=>[X(\"div\",{\"aria-label\":\"Image comparison slider showing reference and actual screenshots\",class:\"relative max-w-full h-full overflow-hidden\",style:zt({\"--split\":`${c.value}%`,aspectRatio:`${o.value} / ${s.value}`,width:`${o.value}px`})},[X(\"div\",hve,[X(\"img\",{src:t.value},null,8,pve)]),X(\"div\",gve,[X(\"img\",{src:r.value},null,8,mve)]),h[1]||(h[1]=X(\"div\",{class:\"absolute left-[--split] h-full w-[2px] -translate-x-1/2 bg-white shadow-[0_0_3px_rgb(0_0_0/.2),0_0_10px_rgb(0_0_0/.5)] before:content-[''] before:absolute before:top-1/2 before:size-[16px] before:bg-white before:border-[2px] before:border-black before:rounded-full before:-translate-y-1/2 before:translate-x-[calc(-50%+1px)]\",\"aria-hidden\":\"true\",role:\"presentation\"},null,-1)),at(X(\"input\",{id:K(f),\"onUpdate:modelValue\":h[0]||(h[0]=p=>c.value=p),type:\"range\",min:\"0\",max:\"100\",step:\"0.1\",\"aria-label\":\"Adjust slider to compare reference and actual images\",class:\"absolute inset-0 opacity-0 cursor-col-resize\"},null,8,vve),[[Yb,c.value]]),X(\"output\",{for:K(f),class:\"sr-only\"},\" Showing \"+Re(c.value)+\"% reference, \"+Re(100-c.value)+\"% actual \",9,yve)],4)]),_:1}))}}),wve=rt({__name:\"VisualRegression\",props:{regression:{}},setup(e){const t=ke(()=>({diff:e.regression.attachments.find(r=>r.name===\"diff\"),reference:e.regression.attachments.find(r=>r.name===\"reference\"),actual:e.regression.attachments.find(r=>r.name===\"actual\")}));return(r,o)=>(ie(),Ve(ove,null,{title:We(()=>[...o[0]||(o[0]=[Qe(\" Visual Regression \",-1)])]),message:We(()=>[Qe(Re(e.regression.message),1)]),default:We(()=>[Ne(cve,null,{default:We(()=>[t.value.diff?(ie(),Ve(Bc,{key:t.value.diff.path,title:\"Diff\"},{default:We(()=>[Ne(zd,{attachment:t.value.diff},null,8,[\"attachment\"])]),_:1})):He(\"\",!0),t.value.reference?(ie(),Ve(Bc,{key:t.value.reference.path,title:\"Reference\"},{default:We(()=>[Ne(zd,{attachment:t.value.reference},null,8,[\"attachment\"])]),_:1})):He(\"\",!0),t.value.actual?(ie(),Ve(Bc,{key:t.value.actual.path,title:\"Actual\"},{default:We(()=>[Ne(zd,{attachment:t.value.actual},null,8,[\"attachment\"])]),_:1})):He(\"\",!0),t.value.reference&&t.value.actual?(ie(),Ve(Bc,{key:(t.value.reference.path??\"\")+(t.value.actual.path??\"\"),title:\"Slider\"},{default:We(()=>[Ne(bve,{actual:t.value.actual,reference:t.value.reference},null,8,[\"actual\",\"reference\"])]),_:1})):He(\"\",!0)]),_:1})]),_:1}))}}),xve={\"h-full\":\"\",class:\"scrolls\"},kve={key:0},Sve={bg:\"red-500/10\",text:\"red-500 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\"},_ve={flex:\"~ gap-2 items-center\"},Tve={key:0,class:\"scrolls scrolls-rounded task-error\",\"data-testid\":\"task-error\"},Cve=[\"innerHTML\"],Eve={key:1,bg:\"green-500/10\",text:\"green-500 sm\",p:\"x4 y2\",\"m-2\":\"\",rounded:\"\"},Ave={flex:\"~ gap-2 items-center justify-between\",\"overflow-hidden\":\"\"},Lve={class:\"flex gap-2\",\"overflow-hidden\":\"\"},Mve={class:\"font-bold\",\"ws-nowrap\":\"\",truncate:\"\"},Nve=[\"href\",\"download\"],Ove=[\"onClick\"],Pve={key:1,class:\"flex gap-1 text-yellow-500/80\",\"ws-nowrap\":\"\"},Rve={class:\"scrolls scrolls-rounded task-error\",\"data-testid\":\"task-error\"},$ve={flex:\"~ gap-2 items-center justify-between\",\"overflow-hidden\":\"\"},Ive=[\"onClick\"],Dve={key:1,class:\"flex gap-1 text-yellow-500/80\",\"ws-nowrap\":\"\"},zve={bg:\"gray/10\",text:\"black-100 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\",class:\"grid grid-cols-1 md:grid-cols-[200px_1fr] gap-2\",\"overflow-hidden\":\"\"},Fve={\"font-bold\":\"\",\"ws-nowrap\":\"\",truncate:\"\",\"py-2\":\"\"},Hve={\"overflow-auto\":\"\",bg:\"gray/30\",rounded:\"\",\"p-2\":\"\"},Bve=rt({__name:\"ViewTestReport\",props:{test:{}},setup(e){const t=e,r=ke(()=>!t.test.result||!t.test.result.errors?.length?null:dx(ol.value,[t.test])[0]);function o(v){return gce(t.test,v)}const{currentTask:s,showScreenshot:c,showScreenshotModal:f,currentScreenshotUrl:d}=p1();function h(v){return`${af(ei.value.root,v.file)}:${v.line}:${v.column}`}const p=new Set([\"benchmark\",\"typecheck\",\"failScreenshotPath\"]),g=ke(()=>Object.entries(t.test.meta).filter(([v])=>!p.has(v)));return(v,b)=>{const w=vr(\"tooltip\");return ie(),ve(\"div\",xve,[r.value?(ie(),ve(\"div\",kve,[X(\"div\",Sve,[X(\"div\",_ve,[K(Zn)&&e.test.meta?.failScreenshotPath?(ie(),ve(nt,{key:0},[at(Ne(_t,{class:\"!op-100\",icon:\"i-carbon:image\",title:\"View screenshot error\",onClick:b[0]||(b[0]=E=>K(f)(e.test))},null,512),[[w,\"View screenshot error\",void 0,{bottom:!0}]]),at(Ne(_t,{class:\"!op-100\",icon:\"i-carbon:image-reference\",title:\"Open screenshot error in editor\",onClick:b[1]||(b[1]=E=>K(h1)(e.test))},null,512),[[w,\"Open screenshot error in editor\",void 0,{bottom:!0}]])],64)):He(\"\",!0)]),e.test.result?.htmlError?(ie(),ve(\"div\",Tve,[X(\"pre\",{innerHTML:e.test.result.htmlError},null,8,Cve)])):e.test.result?.errors?(ie(!0),ve(nt,{key:1},$n(e.test.result.errors,(E,L)=>(ie(),Ve(m1,{key:L,\"file-id\":e.test.file.id,error:E,filename:e.test.file.name,root:K(ei).root},null,8,[\"file-id\",\"error\",\"filename\",\"root\"]))),128)):He(\"\",!0)])])):(ie(),ve(\"div\",Eve,\" All tests passed in this file \")),e.test.annotations.length?(ie(),ve(nt,{key:2},[b[5]||(b[5]=X(\"h1\",{\"m-2\":\"\"},\" Test Annotations \",-1)),(ie(!0),ve(nt,null,$n(e.test.annotations,E=>(ie(),ve(\"div\",{key:E.type+E.message,bg:\"yellow-500/10\",text:\"yellow-500 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\",role:\"note\"},[X(\"div\",Ave,[X(\"div\",Lve,[X(\"span\",Mve,Re(E.type),1),E.attachment&&!E.attachment.contentType?.startsWith(\"image/\")?(ie(),ve(\"a\",{key:0,class:\"flex gap-1 items-center text-yellow-500/80 cursor-pointer\",href:K(Ma)(E.attachment),download:K(f1)(E.message,E.attachment.contentType)},[...b[4]||(b[4]=[X(\"span\",{class:\"i-carbon:download block\"},null,-1),Qe(\" Download \",-1)])],8,Nve)):He(\"\",!0)]),X(\"div\",null,[E.location&&E.location.file===e.test.file.filepath?at((ie(),ve(\"span\",{key:0,title:\"Open in Editor\",class:\"flex gap-1 text-yellow-500/80 cursor-pointer\",\"ws-nowrap\":\"\",onClick:L=>o(E.location)},[Qe(Re(h(E.location)),1)],8,Ove)),[[w,\"Open in Editor\",void 0,{bottom:!0}]]):E.location&&E.location.file!==e.test.file.filepath?(ie(),ve(\"span\",Pve,Re(h(E.location)),1)):He(\"\",!0)])]),X(\"div\",Rve,Re(E.message),1),Ne(nve,{annotation:E},null,8,[\"annotation\"])]))),128))],64)):He(\"\",!0),e.test.artifacts.length?(ie(),ve(nt,{key:3},[b[6]||(b[6]=X(\"h1\",{\"m-2\":\"\"},\" Test Artifacts \",-1)),(ie(!0),ve(nt,null,$n(e.test.artifacts,(E,L)=>(ie(),ve(\"div\",{key:E.type+L,bg:\"yellow-500/10\",text:\"yellow-500 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\",role:\"note\"},[X(\"div\",$ve,[X(\"div\",null,[E.location&&E.location.file===e.test.file.filepath?at((ie(),ve(\"span\",{key:0,title:\"Open in Editor\",class:\"flex gap-1 text-yellow-500/80 cursor-pointer\",\"ws-nowrap\":\"\",onClick:P=>o(E.location)},[Qe(Re(h(E.location)),1)],8,Ive)),[[w,\"Open in Editor\",void 0,{bottom:!0}]]):E.location&&E.location.file!==e.test.file.filepath?(ie(),ve(\"span\",Dve,Re(h(E.location)),1)):He(\"\",!0)])]),E.type===\"internal:toMatchScreenshot\"&&E.kind===\"visual-regression\"?(ie(),Ve(wve,{key:0,regression:E},null,8,[\"regression\"])):He(\"\",!0)]))),128))],64)):He(\"\",!0),g.value.length?(ie(),ve(nt,{key:4},[b[7]||(b[7]=X(\"h1\",{\"m-2\":\"\"},\" Test Meta \",-1)),X(\"div\",zve,[(ie(!0),ve(nt,null,$n(g.value,([E,L])=>(ie(),ve(nt,{key:E},[X(\"div\",Fve,Re(E),1),X(\"pre\",Hve,Re(L),1)],64))),128))])],64)):He(\"\",!0),K(Zn)?(ie(),Ve(Dp,{key:5,modelValue:K(c),\"onUpdate:modelValue\":b[3]||(b[3]=E=>Mt(c)?c.value=E:null),direction:\"right\"},{default:We(()=>[K(s)?(ie(),Ve(np,{key:0},{default:We(()=>[Ne(g1,{file:K(s).file.filepath,name:K(s).name,url:K(d),onClose:b[2]||(b[2]=E=>c.value=!1)},null,8,[\"file\",\"name\",\"url\"])]),_:1})):He(\"\",!0)]),_:1},8,[\"modelValue\"])):He(\"\",!0)])}}}),Wve=Ni(Bve,[[\"__scopeId\",\"data-v-1a68630b\"]]),qve={key:0,flex:\"\",\"flex-col\":\"\",\"h-full\":\"\",\"max-h-full\":\"\",\"overflow-hidden\":\"\",\"data-testid\":\"file-detail\"},jve={p:\"2\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},Uve={key:0,class:\"i-logos:typescript-icon\",\"flex-shrink-0\":\"\"},Vve={\"flex-1\":\"\",\"font-light\":\"\",\"op-50\":\"\",\"ws-nowrap\":\"\",truncate:\"\",\"text-sm\":\"\"},Gve={class:\"flex text-lg\"},Kve={flex:\"~\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b-2 base\",\"text-sm\":\"\",\"h-41px\":\"\"},Xve={key:0,class:\"block w-1.4em h-1.4em i-carbon:circle-dash animate-spin animate-2s\"},Yve={key:1,class:\"block w-1.4em h-1.4em i-carbon:chart-relationship\"},Zve={flex:\"\",\"flex-col\":\"\",\"flex-1\":\"\",overflow:\"hidden\"},Jve=[\"flex-1\"],l0=rt({__name:\"FileDetails\",setup(e){const t=Ge({nodes:[],links:[]}),r=Ge(!1),o=Ge(!1),s=Ge(!1),c=Ge(void 0),f=Ge(!0),d=ke(()=>Bs.value?ft.state.idMap.get(Bs.value):void 0),h=ke(()=>{const _=Gt.value;if(!(!_||!_.filepath))return{filepath:_.filepath,projectName:_.file.projectName||\"\"}}),p=ke(()=>Gt.value&&yp(Gt.value)),g=ke(()=>!!Gt.value?.meta?.typecheck);function v(){const _=Gt.value?.filepath;_&&fetch(`/__open-in-editor?file=${encodeURIComponent(_)}`)}function b(_){_===\"graph\"&&(o.value=!0),hn.value=_}const w=ke(()=>Tx.value?.reduce((_,{size:$})=>_+$,0)??0);function E(_){r.value=_}const L=/[/\\\\]node_modules[/\\\\]/;async function P(_=!1){if(!(s.value||h.value?.filepath===c.value&&!_)){s.value=!0,await Et();try{const $=h.value;if(!$){s.value=!1;return}if(_||!c.value||$.filepath!==c.value||!t.value.nodes.length&&!t.value.links.length){let W=await ft.rpc.getModuleGraph($.projectName,$.filepath,!!Zn);f.value&&(gr&&(W=typeof window.structuredClone<\"u\"?window.structuredClone(W):KA(W)),W.inlined=W.inlined.filter(ne=>!L.test(ne)),W.externalized=W.externalized.filter(ne=>!L.test(ne))),t.value=Gge(W,$.filepath),c.value=$.filepath}b(\"graph\")}finally{await new Promise($=>setTimeout($,100)),s.value=!1}}}hp(()=>[h.value,hn.value,f.value],([,_,$],W)=>{_===\"graph\"&&P(W&&$!==W[2])},{debounce:100,immediate:!0});const M=ke(()=>{const _=Gt.value?.file.projectName||\"\";return Oe.colors.get(_)||Qw(Gt.value?.file.projectName)}),R=ke(()=>ex(M.value)),I=ke(()=>{const _=Bs.value;if(!_)return Gt.value?.name;const $=[];let W=ft.state.idMap.get(_);for(;W;)$.push(W.name),W=W.suite?W.suite:W===W.file?void 0:W.file;return $.reverse().join(\" > \")});return(_,$)=>{const W=vr(\"tooltip\");return K(Gt)?(ie(),ve(\"div\",qve,[X(\"div\",null,[X(\"div\",jve,[Ne(c1,{state:K(Gt).result?.state,mode:K(Gt).mode,\"failed-snapshot\":p.value},null,8,[\"state\",\"mode\",\"failed-snapshot\"]),g.value?at((ie(),ve(\"div\",Uve,null,512)),[[W,\"This is a typecheck test. It won't report results of the runtime tests\",void 0,{bottom:!0}]]):He(\"\",!0),K(Gt)?.file.projectName?(ie(),ve(\"span\",{key:1,class:\"rounded-full py-0.5 px-2 text-xs font-light\",style:zt({backgroundColor:M.value,color:R.value})},Re(K(Gt).file.projectName),5)):He(\"\",!0),X(\"div\",Vve,Re(I.value),1),X(\"div\",Gve,[K(gr)?He(\"\",!0):at((ie(),Ve(_t,{key:0,title:\"Open in editor\",icon:\"i-carbon-launch\",disabled:!K(Gt)?.filepath,onClick:v},null,8,[\"disabled\"])),[[W,\"Open in editor\",void 0,{bottom:!0}]])])]),X(\"div\",Kve,[X(\"button\",{\"tab-button\":\"\",class:ot([\"flex items-center gap-2\",{\"tab-button-active\":K(hn)==null}]),\"data-testid\":\"btn-report\",onClick:$[0]||($[0]=ne=>b(null))},[...$[5]||($[5]=[X(\"span\",{class:\"block w-1.4em h-1.4em i-carbon:report\"},null,-1),Qe(\" Report \",-1)])],2),X(\"button\",{\"tab-button\":\"\",\"data-testid\":\"btn-graph\",class:ot([\"flex items-center gap-2\",{\"tab-button-active\":K(hn)===\"graph\"}]),onClick:$[1]||($[1]=ne=>b(\"graph\"))},[s.value?(ie(),ve(\"span\",Xve)):(ie(),ve(\"span\",Yve)),$[6]||($[6]=Qe(\" Module Graph \",-1))],2),X(\"button\",{\"tab-button\":\"\",\"data-testid\":\"btn-code\",class:ot([\"flex items-center gap-2\",{\"tab-button-active\":K(hn)===\"editor\"}]),onClick:$[2]||($[2]=ne=>b(\"editor\"))},[$[7]||($[7]=X(\"span\",{class:\"block w-1.4em h-1.4em i-carbon:code\"},null,-1)),Qe(\" \"+Re(r.value?\"* \":\"\")+\"Code \",1)],2),X(\"button\",{\"tab-button\":\"\",\"data-testid\":\"btn-console\",class:ot([\"flex items-center gap-2\",{\"tab-button-active\":K(hn)===\"console\",op20:K(hn)!==\"console\"&&w.value===0}]),onClick:$[3]||($[3]=ne=>b(\"console\"))},[$[8]||($[8]=X(\"span\",{class:\"block w-1.4em h-1.4em i-carbon:terminal-3270\"},null,-1)),Qe(\" Console (\"+Re(w.value)+\") \",1)],2)])]),X(\"div\",Zve,[o.value?(ie(),ve(\"div\",{key:0,\"flex-1\":K(hn)===\"graph\"&&\"\"},[at(Ne(Pme,{modelValue:f.value,\"onUpdate:modelValue\":$[4]||($[4]=ne=>f.value=ne),graph:t.value,\"data-testid\":\"graph\",\"project-name\":K(Gt).file.projectName||\"\"},null,8,[\"modelValue\",\"graph\",\"project-name\"]),[[ro,K(hn)===\"graph\"&&!s.value]])],8,Jve)):He(\"\",!0),K(hn)===\"editor\"?(ie(),Ve(cme,{key:K(Gt).id,file:K(Gt),\"data-testid\":\"editor\",onDraft:E},null,8,[\"file\"])):K(hn)===\"console\"?(ie(),Ve(sme,{key:2,file:K(Gt),\"data-testid\":\"console\"},null,8,[\"file\"])):!K(hn)&&!d.value&&K(Gt)?(ie(),Ve(Qme,{key:3,file:K(Gt),\"data-testid\":\"report\"},null,8,[\"file\"])):!K(hn)&&d.value?(ie(),Ve(Wve,{key:4,test:d.value,\"data-testid\":\"report\"},null,8,[\"test\"])):He(\"\",!0)])])):He(\"\",!0)}}}),Qve=\"\"+new URL(\"../favicon.svg\",import.meta.url).href;function eye(){var e=window.navigator.userAgent,t=e.indexOf(\"MSIE \");if(t>0)return parseInt(e.substring(t+5,e.indexOf(\".\",t)),10);var r=e.indexOf(\"Trident/\");if(r>0){var o=e.indexOf(\"rv:\");return parseInt(e.substring(o+3,e.indexOf(\".\",o)),10)}var s=e.indexOf(\"Edge/\");return s>0?parseInt(e.substring(s+5,e.indexOf(\".\",s)),10):-1}let nu;function Nh(){Nh.init||(Nh.init=!0,nu=eye()!==-1)}var pf={name:\"ResizeObserver\",props:{emitOnMount:{type:Boolean,default:!1},ignoreWidth:{type:Boolean,default:!1},ignoreHeight:{type:Boolean,default:!1}},emits:[\"notify\"],mounted(){Nh(),Et(()=>{this._w=this.$el.offsetWidth,this._h=this.$el.offsetHeight,this.emitOnMount&&this.emitSize()});const e=document.createElement(\"object\");this._resizeObject=e,e.setAttribute(\"aria-hidden\",\"true\"),e.setAttribute(\"tabindex\",-1),e.onload=this.addResizeHandlers,e.type=\"text/html\",nu&&this.$el.appendChild(e),e.data=\"about:blank\",nu||this.$el.appendChild(e)},beforeUnmount(){this.removeResizeHandlers()},methods:{compareAndNotify(){(!this.ignoreWidth&&this._w!==this.$el.offsetWidth||!this.ignoreHeight&&this._h!==this.$el.offsetHeight)&&(this._w=this.$el.offsetWidth,this._h=this.$el.offsetHeight,this.emitSize())},emitSize(){this.$emit(\"notify\",{width:this._w,height:this._h})},addResizeHandlers(){this._resizeObject.contentDocument.defaultView.addEventListener(\"resize\",this.compareAndNotify),this.compareAndNotify()},removeResizeHandlers(){this._resizeObject&&this._resizeObject.onload&&(!nu&&this._resizeObject.contentDocument&&this._resizeObject.contentDocument.defaultView.removeEventListener(\"resize\",this.compareAndNotify),this.$el.removeChild(this._resizeObject),this._resizeObject.onload=null,this._resizeObject=null)}}};const tye=lb();ob(\"data-v-b329ee4c\");const nye={class:\"resize-observer\",tabindex:\"-1\"};sb();const rye=tye((e,t,r,o,s,c)=>(ie(),Ve(\"div\",nye)));pf.render=rye;pf.__scopeId=\"data-v-b329ee4c\";pf.__file=\"src/components/ResizeObserver.vue\";function ru(e){\"@babel/helpers - typeof\";return typeof Symbol==\"function\"&&typeof Symbol.iterator==\"symbol\"?ru=function(t){return typeof t}:ru=function(t){return t&&typeof Symbol==\"function\"&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},ru(e)}function iye(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}function oye(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,\"value\"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}function sye(e,t,r){return t&&oye(e.prototype,t),e}function a0(e){return lye(e)||aye(e)||cye(e)||uye()}function lye(e){if(Array.isArray(e))return Oh(e)}function aye(e){if(typeof Symbol<\"u\"&&Symbol.iterator in Object(e))return Array.from(e)}function cye(e,t){if(e){if(typeof e==\"string\")return Oh(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if(r===\"Object\"&&e.constructor&&(r=e.constructor.name),r===\"Map\"||r===\"Set\")return Array.from(e);if(r===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return Oh(e,t)}}function Oh(e,t){(t==null||t>e.length)&&(t=e.length);for(var r=0,o=new Array(t);r<t;r++)o[r]=e[r];return o}function uye(){throw new TypeError(`Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function fye(e){var t;return typeof e==\"function\"?t={callback:e}:t=e,t}function dye(e,t){var r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},o,s,c,f=function(h){for(var p=arguments.length,g=new Array(p>1?p-1:0),v=1;v<p;v++)g[v-1]=arguments[v];if(c=g,!(o&&h===s)){var b=r.leading;typeof b==\"function\"&&(b=b(h,s)),(!o||h!==s)&&b&&e.apply(void 0,[h].concat(a0(c))),s=h,clearTimeout(o),o=setTimeout(function(){e.apply(void 0,[h].concat(a0(c))),o=0},t)}};return f._clear=function(){clearTimeout(o),o=null},f}function b1(e,t){if(e===t)return!0;if(ru(e)===\"object\"){for(var r in e)if(!b1(e[r],t[r]))return!1;return!0}return!1}var hye=(function(){function e(t,r,o){iye(this,e),this.el=t,this.observer=null,this.frozen=!1,this.createObserver(r,o)}return sye(e,[{key:\"createObserver\",value:function(r,o){var s=this;if(this.observer&&this.destroyObserver(),!this.frozen){if(this.options=fye(r),this.callback=function(d,h){s.options.callback(d,h),d&&s.options.once&&(s.frozen=!0,s.destroyObserver())},this.callback&&this.options.throttle){var c=this.options.throttleOptions||{},f=c.leading;this.callback=dye(this.callback,this.options.throttle,{leading:function(h){return f===\"both\"||f===\"visible\"&&h||f===\"hidden\"&&!h}})}this.oldResult=void 0,this.observer=new IntersectionObserver(function(d){var h=d[0];if(d.length>1){var p=d.find(function(v){return v.isIntersecting});p&&(h=p)}if(s.callback){var g=h.isIntersecting&&h.intersectionRatio>=s.threshold;if(g===s.oldResult)return;s.oldResult=g,s.callback(g,h)}},this.options.intersection),Et(function(){s.observer&&s.observer.observe(s.el)})}}},{key:\"destroyObserver\",value:function(){this.observer&&(this.observer.disconnect(),this.observer=null),this.callback&&this.callback._clear&&(this.callback._clear(),this.callback=null)}},{key:\"threshold\",get:function(){return this.options.intersection&&typeof this.options.intersection.threshold==\"number\"?this.options.intersection.threshold:0}}]),e})();function w1(e,t,r){var o=t.value;if(o)if(typeof IntersectionObserver>\"u\")console.warn(\"[vue-observe-visibility] IntersectionObserver API is not available in your browser. Please install this polyfill: https://github.com/w3c/IntersectionObserver/tree/master/polyfill\");else{var s=new hye(e,o,r);e._vue_visibilityState=s}}function pye(e,t,r){var o=t.value,s=t.oldValue;if(!b1(o,s)){var c=e._vue_visibilityState;if(!o){x1(e);return}c?c.createObserver(o,r):w1(e,{value:o},r)}}function x1(e){var t=e._vue_visibilityState;t&&(t.destroyObserver(),delete e._vue_visibilityState)}var gye={beforeMount:w1,updated:pye,unmounted:x1},mye={itemsLimit:1e3},vye=/(auto|scroll)/;function k1(e,t){return e.parentNode===null?t:k1(e.parentNode,t.concat([e]))}var Fd=function(t,r){return getComputedStyle(t,null).getPropertyValue(r)},yye=function(t){return Fd(t,\"overflow\")+Fd(t,\"overflow-y\")+Fd(t,\"overflow-x\")},bye=function(t){return vye.test(yye(t))};function c0(e){if(e instanceof HTMLElement||e instanceof SVGElement){for(var t=k1(e.parentNode,[]),r=0;r<t.length;r+=1)if(bye(t[r]))return t[r];return document.scrollingElement||document.documentElement}}function Ph(e){\"@babel/helpers - typeof\";return Ph=typeof Symbol==\"function\"&&typeof Symbol.iterator==\"symbol\"?function(t){return typeof t}:function(t){return t&&typeof Symbol==\"function\"&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},Ph(e)}var wye={items:{type:Array,required:!0},keyField:{type:String,default:\"id\"},direction:{type:String,default:\"vertical\",validator:function(t){return[\"vertical\",\"horizontal\"].includes(t)}},listTag:{type:String,default:\"div\"},itemTag:{type:String,default:\"div\"}};function xye(){return this.items.length&&Ph(this.items[0])!==\"object\"}var Rh=!1;if(typeof window<\"u\"){Rh=!1;try{var kye=Object.defineProperty({},\"passive\",{get:function(){Rh=!0}});window.addEventListener(\"test\",null,kye)}catch{}}let Sye=0;var zp={name:\"RecycleScroller\",components:{ResizeObserver:pf},directives:{ObserveVisibility:gye},props:{...wye,itemSize:{type:Number,default:null},gridItems:{type:Number,default:void 0},itemSecondarySize:{type:Number,default:void 0},minItemSize:{type:[Number,String],default:null},sizeField:{type:String,default:\"size\"},typeField:{type:String,default:\"type\"},buffer:{type:Number,default:200},pageMode:{type:Boolean,default:!1},prerender:{type:Number,default:0},emitUpdate:{type:Boolean,default:!1},updateInterval:{type:Number,default:0},skipHover:{type:Boolean,default:!1},listTag:{type:String,default:\"div\"},itemTag:{type:String,default:\"div\"},listClass:{type:[String,Object,Array],default:\"\"},itemClass:{type:[String,Object,Array],default:\"\"}},emits:[\"resize\",\"visible\",\"hidden\",\"update\",\"scroll-start\",\"scroll-end\"],data(){return{pool:[],totalSize:0,ready:!1,hoverKey:null}},computed:{sizes(){if(this.itemSize===null){const e={\"-1\":{accumulator:0}},t=this.items,r=this.sizeField,o=this.minItemSize;let s=1e4,c=0,f;for(let d=0,h=t.length;d<h;d++)f=t[d][r]||o,f<s&&(s=f),c+=f,e[d]={accumulator:c,size:f};return this.$_computedMinItemSize=s,e}return[]},simpleArray:xye,itemIndexByKey(){const{keyField:e,items:t}=this,r={};for(let o=0,s=t.length;o<s;o++)r[t[o][e]]=o;return r}},watch:{items(){this.updateVisibleItems(!0)},pageMode(){this.applyPageMode(),this.updateVisibleItems(!1)},sizes:{handler(){this.updateVisibleItems(!1)},deep:!0},gridItems(){this.updateVisibleItems(!0)},itemSecondarySize(){this.updateVisibleItems(!0)}},created(){this.$_startIndex=0,this.$_endIndex=0,this.$_views=new Map,this.$_unusedViews=new Map,this.$_scrollDirty=!1,this.$_lastUpdateScrollPosition=0,this.prerender&&(this.$_prerender=!0,this.updateVisibleItems(!1)),this.gridItems&&!this.itemSize&&console.error(\"[vue-recycle-scroller] You must provide an itemSize when using gridItems\")},mounted(){this.applyPageMode(),this.$nextTick(()=>{this.$_prerender=!1,this.updateVisibleItems(!0),this.ready=!0})},activated(){const e=this.$_lastUpdateScrollPosition;typeof e==\"number\"&&this.$nextTick(()=>{this.scrollToPosition(e)})},beforeUnmount(){this.removeListeners()},methods:{addView(e,t,r,o,s){const c=Uu({id:Sye++,index:t,used:!0,key:o,type:s}),f=Gh({item:r,position:0,nr:c});return e.push(f),f},unuseView(e,t=!1){const r=this.$_unusedViews,o=e.nr.type;let s=r.get(o);s||(s=[],r.set(o,s)),s.push(e),t||(e.nr.used=!1,e.position=-9999)},handleResize(){this.$emit(\"resize\"),this.ready&&this.updateVisibleItems(!1)},handleScroll(e){if(!this.$_scrollDirty){if(this.$_scrollDirty=!0,this.$_updateTimeout)return;const t=()=>requestAnimationFrame(()=>{this.$_scrollDirty=!1;const{continuous:r}=this.updateVisibleItems(!1,!0);r||(clearTimeout(this.$_refreshTimout),this.$_refreshTimout=setTimeout(this.handleScroll,this.updateInterval+100))});t(),this.updateInterval&&(this.$_updateTimeout=setTimeout(()=>{this.$_updateTimeout=0,this.$_scrollDirty&&t()},this.updateInterval))}},handleVisibilityChange(e,t){this.ready&&(e||t.boundingClientRect.width!==0||t.boundingClientRect.height!==0?(this.$emit(\"visible\"),requestAnimationFrame(()=>{this.updateVisibleItems(!1)})):this.$emit(\"hidden\"))},updateVisibleItems(e,t=!1){const r=this.itemSize,o=this.gridItems||1,s=this.itemSecondarySize||r,c=this.$_computedMinItemSize,f=this.typeField,d=this.simpleArray?null:this.keyField,h=this.items,p=h.length,g=this.sizes,v=this.$_views,b=this.$_unusedViews,w=this.pool,E=this.itemIndexByKey;let L,P,M,R,I;if(!p)L=P=R=I=M=0;else if(this.$_prerender)L=R=0,P=I=Math.min(this.prerender,h.length),M=null;else{const G=this.getScroll();if(t){let O=G.start-this.$_lastUpdateScrollPosition;if(O<0&&(O=-O),r===null&&O<c||O<r)return{continuous:!0}}this.$_lastUpdateScrollPosition=G.start;const j=this.buffer;G.start-=j,G.end+=j;let N=0;if(this.$refs.before&&(N=this.$refs.before.scrollHeight,G.start-=N),this.$refs.after){const O=this.$refs.after.scrollHeight;G.end+=O}if(r===null){let O,C=0,k=p-1,z=~~(p/2),B;do B=z,O=g[z].accumulator,O<G.start?C=z:z<p-1&&g[z+1].accumulator>G.start&&(k=z),z=~~((C+k)/2);while(z!==B);for(z<0&&(z=0),L=z,M=g[p-1].accumulator,P=z;P<p&&g[P].accumulator<G.end;P++);for(P===-1?P=h.length-1:(P++,P>p&&(P=p)),R=L;R<p&&N+g[R].accumulator<G.start;R++);for(I=R;I<p&&N+g[I].accumulator<G.end;I++);}else{L=~~(G.start/r*o);const O=L%o;L-=O,P=Math.ceil(G.end/r*o),R=Math.max(0,Math.floor((G.start-N)/r*o)),I=Math.floor((G.end-N)/r*o),L<0&&(L=0),P>p&&(P=p),R<0&&(R=0),I>p&&(I=p),M=Math.ceil(p/o)*r}}P-L>mye.itemsLimit&&this.itemsLimitError(),this.totalSize=M;let _;const $=L<=this.$_endIndex&&P>=this.$_startIndex;if($)for(let G=0,j=w.length;G<j;G++)_=w[G],_.nr.used&&(e&&(_.nr.index=E[_.item[d]]),(_.nr.index==null||_.nr.index<L||_.nr.index>=P)&&this.unuseView(_));const W=$?null:new Map;let ne,ee,Z;for(let G=L;G<P;G++){ne=h[G];const j=d?ne[d]:ne;if(j==null)throw new Error(`Key is ${j} on item (keyField is '${d}')`);if(_=v.get(j),!r&&!g[G].size){_&&this.unuseView(_);continue}ee=ne[f];let N=b.get(ee),O=!1;if(!_)$?N&&N.length?_=N.pop():_=this.addView(w,G,ne,j,ee):(Z=W.get(ee)||0,(!N||Z>=N.length)&&(_=this.addView(w,G,ne,j,ee),this.unuseView(_,!0),N=b.get(ee)),_=N[Z],W.set(ee,Z+1)),v.delete(_.nr.key),_.nr.used=!0,_.nr.index=G,_.nr.key=j,_.nr.type=ee,v.set(j,_),O=!0;else if(!_.nr.used&&(_.nr.used=!0,O=!0,N)){const C=N.indexOf(_);C!==-1&&N.splice(C,1)}_.item=ne,O&&(G===h.length-1&&this.$emit(\"scroll-end\"),G===0&&this.$emit(\"scroll-start\")),r===null?(_.position=g[G-1].accumulator,_.offset=0):(_.position=Math.floor(G/o)*r,_.offset=G%o*s)}return this.$_startIndex=L,this.$_endIndex=P,this.emitUpdate&&this.$emit(\"update\",L,P,R,I),clearTimeout(this.$_sortTimer),this.$_sortTimer=setTimeout(this.sortViews,this.updateInterval+300),{continuous:$}},getListenerTarget(){let e=c0(this.$el);return window.document&&(e===window.document.documentElement||e===window.document.body)&&(e=window),e},getScroll(){const{$el:e,direction:t}=this,r=t===\"vertical\";let o;if(this.pageMode){const s=e.getBoundingClientRect(),c=r?s.height:s.width;let f=-(r?s.top:s.left),d=r?window.innerHeight:window.innerWidth;f<0&&(d+=f,f=0),f+d>c&&(d=c-f),o={start:f,end:f+d}}else r?o={start:e.scrollTop,end:e.scrollTop+e.clientHeight}:o={start:e.scrollLeft,end:e.scrollLeft+e.clientWidth};return o},applyPageMode(){this.pageMode?this.addListeners():this.removeListeners()},addListeners(){this.listenerTarget=this.getListenerTarget(),this.listenerTarget.addEventListener(\"scroll\",this.handleScroll,Rh?{passive:!0}:!1),this.listenerTarget.addEventListener(\"resize\",this.handleResize)},removeListeners(){this.listenerTarget&&(this.listenerTarget.removeEventListener(\"scroll\",this.handleScroll),this.listenerTarget.removeEventListener(\"resize\",this.handleResize),this.listenerTarget=null)},scrollToItem(e){let t;const r=this.gridItems||1;this.itemSize===null?t=e>0?this.sizes[e-1].accumulator:0:t=Math.floor(e/r)*this.itemSize,this.scrollToPosition(t)},scrollToPosition(e){const t=this.direction===\"vertical\"?{scroll:\"scrollTop\",start:\"top\"}:{scroll:\"scrollLeft\",start:\"left\"};let r,o,s;if(this.pageMode){const c=c0(this.$el),f=c.tagName===\"HTML\"?0:c[t.scroll],d=c.getBoundingClientRect(),p=this.$el.getBoundingClientRect()[t.start]-d[t.start];r=c,o=t.scroll,s=e+f+p}else r=this.$el,o=t.scroll,s=e;r[o]=s},itemsLimitError(){throw setTimeout(()=>{console.log(\"It seems the scroller element isn't scrolling, so it tries to render all the items at once.\",\"Scroller:\",this.$el),console.log(\"Make sure the scroller has a fixed height (or width) and 'overflow-y' (or 'overflow-x') set to 'auto' so it can scroll correctly and only render the items visible in the scroll viewport.\")}),new Error(\"Rendered items limit reached\")},sortViews(){this.pool.sort((e,t)=>e.nr.index-t.nr.index)}}};const _ye={key:0,ref:\"before\",class:\"vue-recycle-scroller__slot\"},Tye={key:1,ref:\"after\",class:\"vue-recycle-scroller__slot\"};function Cye(e,t,r,o,s,c){const f=Go(\"ResizeObserver\"),d=vr(\"observe-visibility\");return at((ie(),ve(\"div\",{class:ot([\"vue-recycle-scroller\",{ready:s.ready,\"page-mode\":r.pageMode,[`direction-${e.direction}`]:!0}]),onScrollPassive:t[0]||(t[0]=(...h)=>c.handleScroll&&c.handleScroll(...h))},[e.$slots.before?(ie(),ve(\"div\",_ye,[Dt(e.$slots,\"before\")],512)):He(\"v-if\",!0),(ie(),Ve(Xd(r.listTag),{ref:\"wrapper\",style:zt({[e.direction===\"vertical\"?\"minHeight\":\"minWidth\"]:s.totalSize+\"px\"}),class:ot([\"vue-recycle-scroller__item-wrapper\",r.listClass])},{default:We(()=>[(ie(!0),ve(nt,null,$n(s.pool,h=>(ie(),Ve(Xd(r.itemTag),ki({key:h.nr.id,style:s.ready?{transform:`translate${e.direction===\"vertical\"?\"Y\":\"X\"}(${h.position}px) translate${e.direction===\"vertical\"?\"X\":\"Y\"}(${h.offset}px)`,width:r.gridItems?`${e.direction===\"vertical\"&&r.itemSecondarySize||r.itemSize}px`:void 0,height:r.gridItems?`${e.direction===\"horizontal\"&&r.itemSecondarySize||r.itemSize}px`:void 0}:null,class:[\"vue-recycle-scroller__item-view\",[r.itemClass,{hover:!r.skipHover&&s.hoverKey===h.nr.key}]]},q_(r.skipHover?{}:{mouseenter:()=>{s.hoverKey=h.nr.key},mouseleave:()=>{s.hoverKey=null}})),{default:We(()=>[Dt(e.$slots,\"default\",{item:h.item,index:h.nr.index,active:h.nr.used})]),_:2},1040,[\"style\",\"class\"]))),128)),Dt(e.$slots,\"empty\")]),_:3},8,[\"style\",\"class\"])),e.$slots.after?(ie(),ve(\"div\",Tye,[Dt(e.$slots,\"after\")],512)):He(\"v-if\",!0),Ne(f,{onNotify:c.handleResize},null,8,[\"onNotify\"])],34)),[[d,c.handleVisibilityChange]])}zp.render=Cye;zp.__file=\"src/components/RecycleScroller.vue\";function Eye(e){const t=ke(()=>hh.value?!1:!it.onlyTests),r=ke(()=>Vn.value===\"\"),o=Ge(Vn.value);hp(()=>Vn.value,h=>{o.value=h?.trim()??\"\"},{debounce:256});function s(h){Vn.value=\"\",h&&e.value?.focus()}function c(h){it.failed=!1,it.success=!1,it.skipped=!1,it.onlyTests=!1,h&&e.value?.focus()}function f(){c(!1),s(!0)}function d(h,p,g,v,b){Qs.value&&(gn.value.search=h?.trim()??\"\",gn.value.failed=p,gn.value.success=g,gn.value.skipped=v,gn.value.onlyTests=b)}return xt(()=>[o.value,it.failed,it.success,it.skipped,it.onlyTests],([h,p,g,v,b])=>{d(h,p,g,v,b),Oe.filterNodes()},{flush:\"post\"}),xt(()=>Dr.value.length,h=>{h&&(gn.value.expandAll=void 0)},{flush:\"post\"}),{initialized:Qs,filter:it,search:Vn,disableFilter:t,isFiltered:Zw,isFilteredByStatus:hh,disableClearSearch:r,clearAll:f,clearSearch:s,clearFilter:c,filteredFiles:cf,testsTotal:JA,uiEntries:Jn}}const Aye=[\"open\"],Lye=rt({__name:\"DetailsPanel\",props:{color:{}},setup(e){const t=Ge(!0);return(r,o)=>(ie(),ve(\"div\",{open:t.value,class:\"details-panel\",\"data-testid\":\"details-panel\",onToggle:o[0]||(o[0]=s=>t.value=s.target.open)},[X(\"div\",{p:\"y1\",\"text-sm\":\"\",\"bg-base\":\"\",\"items-center\":\"\",\"z-5\":\"\",\"gap-2\":\"\",class:ot(e.color),\"w-full\":\"\",flex:\"\",\"select-none\":\"\",sticky:\"\",top:\"-1\"},[o[1]||(o[1]=X(\"div\",{\"flex-1\":\"\",\"h-1px\":\"\",border:\"base b\",op80:\"\"},null,-1)),Dt(r.$slots,\"summary\",{open:t.value}),o[2]||(o[2]=X(\"div\",{\"flex-1\":\"\",\"h-1px\":\"\",border:\"base b\",op80:\"\"},null,-1))],2),Dt(r.$slots,\"default\")],40,Aye))}}),Mye={\"flex-1\":\"\",\"ms-2\":\"\",\"select-none\":\"\"},Wc=rt({__name:\"FilterStatus\",props:da({label:{}},{modelValue:{type:[Boolean,null]},modelModifiers:{}}),emits:[\"update:modelValue\"],setup(e){const t=Yu(e,\"modelValue\");return(r,o)=>(ie(),ve(\"label\",ki({class:\"font-light text-sm checkbox flex items-center cursor-pointer py-1 text-sm w-full gap-y-1 mb-1px\"},r.$attrs,{onClick:o[1]||(o[1]=Gc(s=>t.value=!t.value,[\"prevent\"]))}),[X(\"span\",{class:ot([t.value?\"i-carbon:checkbox-checked-filled\":\"i-carbon:checkbox\"]),\"text-lg\":\"\",\"aria-hidden\":\"true\"},null,2),at(X(\"input\",{\"onUpdate:modelValue\":o[0]||(o[0]=s=>t.value=s),type:\"checkbox\",\"sr-only\":\"\"},null,512),[[Zb,t.value]]),X(\"span\",Mye,Re(e.label),1)],16))}}),Nye={type:\"button\",dark:\"op75\",bg:\"gray-200 dark:#111\",hover:\"op100\",\"rounded-1\":\"\",\"p-0.5\":\"\"},Oye=rt({__name:\"IconAction\",props:{icon:{}},setup(e){return(t,r)=>(ie(),ve(\"button\",Nye,[X(\"span\",{block:\"\",class:ot([e.icon,\"dark:op85 hover:op100\"]),op65:\"\"},null,2)]))}}),Pye=[\"aria-label\",\"data-current\"],Rye={key:1,\"w-4\":\"\"},$ye={flex:\"\",\"items-end\":\"\",\"gap-2\":\"\",\"overflow-hidden\":\"\"},Iye={key:0,class:\"i-logos:typescript-icon\",\"flex-shrink-0\":\"\"},Dye={\"text-sm\":\"\",truncate:\"\",\"font-light\":\"\"},zye=[\"text\",\"innerHTML\"],Fye={key:1,text:\"xs\",op20:\"\",style:{\"white-space\":\"nowrap\"}},Hye={\"gap-1\":\"\",\"justify-end\":\"\",\"flex-grow-1\":\"\",\"pl-1\":\"\",class:\"test-actions\"},Bye={key:0,class:\"op100 gap-1 p-y-1\",grid:\"~ items-center cols-[1.5em_1fr]\"},Wye={key:1},qye=rt({__name:\"ExplorerItem\",props:{taskId:{},name:{},indent:{},typecheck:{type:Boolean},duration:{},state:{},current:{type:Boolean},type:{},opened:{type:Boolean},expandable:{type:Boolean},search:{},projectName:{},projectNameColor:{},disableTaskLocation:{type:Boolean},onItemClick:{type:Function}},setup(e){const t=ke(()=>ft.state.idMap.get(e.taskId)),r=ke(()=>{if(gr)return!1;const P=t.value;return P&&yp(P)});function o(){if(!e.expandable){e.onItemClick?.(t.value);return}e.opened?Oe.collapseNode(e.taskId):Oe.expandNode(e.taskId)}async function s(P){e.onItemClick?.(P),Os.value&&(Cu.value=!0,await Et()),e.type===\"file\"?await _p([P.file]):await Xce(P)}function c(P){return ft.rpc.updateSnapshot(P.file)}const f=ke(()=>e.indent<=0?[]:Array.from({length:e.indent},(P,M)=>`${e.taskId}-${M}`)),d=ke(()=>{const P=f.value,M=[];return(e.type===\"file\"||e.type===\"suite\")&&M.push(\"min-content\"),M.push(\"min-content\"),e.type===\"suite\"&&e.typecheck&&M.push(\"min-content\"),M.push(\"minmax(0, 1fr)\"),M.push(\"min-content\"),`grid-template-columns: ${P.map(()=>\"1rem\").join(\" \")} ${M.join(\" \")};`}),h=ke(()=>e.type===\"file\"?\"Run current file\":e.type===\"suite\"?\"Run all tests in this suite\":\"Run current test\"),p=ke(()=>Yw(e.name)),g=ke(()=>{const P=ZA.value,M=p.value;return P?M.replace(P,R=>`<span class=\"highlight\">${R}</span>`):M}),v=ke(()=>e.type!==\"file\"&&e.disableTaskLocation),b=ke(()=>e.type===\"file\"?\"Open test details\":e.type===\"suite\"?\"View Suite Source Code\":\"View Test Source Code\"),w=ke(()=>v.value?\"color-red5 dark:color-#f43f5e\":null);function E(){const P=t.value;e.type===\"file\"?e.onItemClick?.(P):gx(P)}const L=ke(()=>ex(e.projectNameColor));return(P,M)=>{const R=vr(\"tooltip\");return t.value?(ie(),ve(\"div\",{key:0,\"items-center\":\"\",p:\"x-2 y-1\",grid:\"~ rows-1 items-center gap-x-2\",\"w-full\":\"\",\"h-28px\":\"\",\"border-rounded\":\"\",hover:\"bg-active\",\"cursor-pointer\":\"\",class:\"item-wrapper\",style:zt(d.value),\"aria-label\":e.name,\"data-current\":e.current,onClick:M[2]||(M[2]=I=>o())},[e.indent>0?(ie(!0),ve(nt,{key:0},$n(f.value,I=>(ie(),ve(\"div\",{key:I,border:\"solid gray-500 dark:gray-400\",class:\"vertical-line\",\"h-28px\":\"\",\"inline-flex\":\"\",\"mx-2\":\"\",op20:\"\"}))),128)):He(\"\",!0),e.type===\"file\"||e.type===\"suite\"?(ie(),ve(\"div\",Rye,[X(\"div\",{class:ot(e.opened?\"i-carbon:chevron-down\":\"i-carbon:chevron-right op20\"),op20:\"\"},null,2)])):He(\"\",!0),Ne(c1,{state:e.state,mode:t.value.mode,\"failed-snapshot\":r.value,\"w-4\":\"\"},null,8,[\"state\",\"mode\",\"failed-snapshot\"]),X(\"div\",$ye,[e.type===\"file\"&&e.typecheck?at((ie(),ve(\"div\",Iye,null,512)),[[R,\"This is a typecheck test. It won't report results of the runtime tests\",void 0,{bottom:!0}]]):He(\"\",!0),X(\"span\",Dye,[e.type===\"file\"&&e.projectName?(ie(),ve(\"span\",{key:0,class:\"rounded-full py-0.5 px-2 mr-1 text-xs\",style:zt({backgroundColor:e.projectNameColor,color:L.value})},Re(e.projectName),5)):He(\"\",!0),X(\"span\",{text:e.state===\"fail\"?\"red-500\":\"\",innerHTML:g.value},null,8,zye)]),typeof e.duration==\"number\"?(ie(),ve(\"span\",Fye,Re(e.duration>0?e.duration:\"< 1\")+\"ms \",1)):He(\"\",!0)]),X(\"div\",Hye,[!K(gr)&&r.value?at((ie(),Ve(Oye,{key:0,\"data-testid\":\"btn-fix-snapshot\",title:\"Fix failed snapshot(s)\",icon:\"i-carbon:result-old\",onClick:M[0]||(M[0]=Gc(I=>c(t.value),[\"prevent\",\"stop\"]))},null,512)),[[R,\"Fix failed snapshot(s)\",void 0,{bottom:!0}]]):He(\"\",!0),Ne(K(Qi),{placement:\"bottom\",class:ot([\"w-1.4em h-1.4em op100 rounded flex\",w.value])},{popper:We(()=>[v.value?(ie(),ve(\"div\",Bye,[M[5]||(M[5]=X(\"div\",{class:\"i-carbon:information-square w-1.5em h-1.5em\"},null,-1)),X(\"div\",null,[Qe(Re(b.value)+\": this feature is not available, you have disabled \",1),M[3]||(M[3]=X(\"span\",{class:\"text-[#add467]\"},\"includeTaskLocation\",-1)),M[4]||(M[4]=Qe(\" in your configuration file.\",-1))]),M[6]||(M[6]=X(\"div\",{style:{\"grid-column\":\"2\"}},\" Clicking this button the code tab will position the cursor at first line in the source code since the UI doesn't have the information available. \",-1))])):(ie(),ve(\"div\",Wye,Re(b.value),1))]),default:We(()=>[Ne(_t,{\"data-testid\":\"btn-open-details\",icon:e.type===\"file\"?\"i-carbon:intrusion-prevention\":\"i-carbon:code-reference\",onClick:Gc(E,[\"prevent\",\"stop\"])},null,8,[\"icon\"])]),_:1},8,[\"class\"]),K(gr)?He(\"\",!0):at((ie(),Ve(_t,{key:1,\"data-testid\":\"btn-run-test\",title:h.value,icon:\"i-carbon:play-filled-alt\",\"text-green5\":\"\",onClick:M[1]||(M[1]=Gc(I=>s(t.value),[\"prevent\",\"stop\"]))},null,8,[\"title\"])),[[R,h.value,void 0,{bottom:!0}]])])],12,Pye)):He(\"\",!0)}}}),jye=Ni(qye,[[\"__scopeId\",\"data-v-58d301d8\"]]),Uye={p:\"2\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},Vye={p:\"l3 y2 r2\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b-2 base\"},Gye=[\"op\"],Kye={grid:\"~ items-center gap-x-1 cols-[auto_min-content_auto] rows-[min-content_min-content]\"},Xye={\"text-red5\":\"\"},Yye={\"text-yellow5\":\"\"},Zye={\"text-green5\":\"\"},Jye={class:\"text-purple5:50\"},Qye={key:0,flex:\"~ col\",\"items-center\":\"\",p:\"x4 y4\",\"font-light\":\"\"},e0e=[\"disabled\"],t0e=[\"disabled\"],n0e={key:1,flex:\"~ col\",\"items-center\":\"\",p:\"x4 y4\",\"font-light\":\"\"},r0e=rt({inheritAttrs:!1,__name:\"Explorer\",props:{onItemClick:{type:Function}},emits:[\"item-click\",\"run\"],setup(e,{emit:t}){const r=t,o=ke(()=>ei.value.includeTaskLocation),s=Ge(),{initialized:c,filter:f,search:d,disableFilter:h,isFiltered:p,isFilteredByStatus:g,disableClearSearch:v,clearAll:b,clearSearch:w,clearFilter:E,filteredFiles:L,testsTotal:P,uiEntries:M}=Eye(s),R=Ge(\"grid-cols-2\"),I=Ge(\"grid-col-span-2\"),_=Ge();return Ow(()=>_.value,([{contentRect:$}])=>{$.width<420?(R.value=\"grid-cols-2\",I.value=\"grid-col-span-2\"):(R.value=\"grid-cols-4\",I.value=\"grid-col-span-4\")}),($,W)=>{const ne=vr(\"tooltip\");return ie(),ve(\"div\",{ref_key:\"testExplorerRef\",ref:_,h:\"full\",flex:\"~ col\"},[X(\"div\",null,[X(\"div\",Uye,[Dt($.$slots,\"header\",{filteredFiles:K(p)||K(g)?K(L):void 0})]),X(\"div\",Vye,[W[13]||(W[13]=X(\"div\",{class:\"i-carbon:search\",\"flex-shrink-0\":\"\"},null,-1)),at(X(\"input\",{ref_key:\"searchBox\",ref:s,\"onUpdate:modelValue\":W[0]||(W[0]=ee=>Mt(d)?d.value=ee:null),placeholder:\"Search...\",outline:\"none\",bg:\"transparent\",font:\"light\",text:\"sm\",\"flex-1\":\"\",\"pl-1\":\"\",op:K(d).length?\"100\":\"50\",onKeydown:[W[1]||(W[1]=ih(ee=>K(w)(!1),[\"esc\"])),W[2]||(W[2]=ih(ee=>r(\"run\",K(p)||K(g)?K(L):void 0),[\"enter\"]))]},null,40,Gye),[[Yb,K(d)]]),at(Ne(_t,{disabled:K(v),title:\"Clear search\",icon:\"i-carbon:filter-remove\",onClickPassive:W[3]||(W[3]=ee=>K(w)(!0))},null,8,[\"disabled\"]),[[ne,\"Clear search\",void 0,{bottom:!0}]])]),X(\"div\",{p:\"l3 y2 r2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b-2 base\",grid:\"~ items-center gap-x-2 rows-[auto_auto]\",class:ot(R.value)},[X(\"div\",{class:ot(I.value),flex:\"~ gap-2 items-center\"},[W[14]||(W[14]=X(\"div\",{\"aria-hidden\":\"true\",class:\"i-carbon:filter\"},null,-1)),W[15]||(W[15]=X(\"div\",{\"flex-grow-1\":\"\",\"text-sm\":\"\"},\" Filter \",-1)),at(Ne(_t,{disabled:K(h),title:\"Clear search\",icon:\"i-carbon:filter-remove\",onClickPassive:W[4]||(W[4]=ee=>K(E)(!1))},null,8,[\"disabled\"]),[[ne,\"Clear Filter\",void 0,{bottom:!0}]])],2),Ne(Wc,{modelValue:K(f).failed,\"onUpdate:modelValue\":W[5]||(W[5]=ee=>K(f).failed=ee),label:\"Fail\"},null,8,[\"modelValue\"]),Ne(Wc,{modelValue:K(f).success,\"onUpdate:modelValue\":W[6]||(W[6]=ee=>K(f).success=ee),label:\"Pass\"},null,8,[\"modelValue\"]),Ne(Wc,{modelValue:K(f).skipped,\"onUpdate:modelValue\":W[7]||(W[7]=ee=>K(f).skipped=ee),label:\"Skip\"},null,8,[\"modelValue\"]),Ne(Wc,{modelValue:K(f).onlyTests,\"onUpdate:modelValue\":W[8]||(W[8]=ee=>K(f).onlyTests=ee),label:\"Only Tests\"},null,8,[\"modelValue\"])],2)]),X(\"div\",{class:\"scrolls\",\"flex-auto\":\"\",\"py-1\":\"\",onScrollPassive:W[12]||(W[12]=(...ee)=>K(Bv)&&K(Bv)(...ee))},[Ne(Lye,null,W_({default:We(()=>[(K(p)||K(g))&&K(M).length===0?(ie(),ve(nt,{key:0},[K(c)?(ie(),ve(\"div\",Qye,[W[18]||(W[18]=X(\"div\",{op30:\"\"},\" No matched test \",-1)),X(\"button\",{type:\"button\",\"font-light\":\"\",\"text-sm\":\"\",border:\"~ gray-400/50 rounded\",p:\"x2 y0.5\",m:\"t2\",op:\"50\",class:ot(K(v)?null:\"hover:op100\"),disabled:K(v),onClickPassive:W[9]||(W[9]=ee=>K(w)(!0))},\" Clear Search \",42,e0e),X(\"button\",{type:\"button\",\"font-light\":\"\",\"text-sm\":\"\",border:\"~ gray-400/50 rounded\",p:\"x2 y0.5\",m:\"t2\",op:\"50\",class:ot(K(h)?null:\"hover:op100\"),disabled:K(h),onClickPassive:W[10]||(W[10]=ee=>K(E)(!0))},\" Clear Filter \",42,t0e),X(\"button\",{type:\"button\",\"font-light\":\"\",op:\"50 hover:100\",\"text-sm\":\"\",border:\"~ gray-400/50 rounded\",p:\"x2 y0.5\",m:\"t2\",onClickPassive:W[11]||(W[11]=(...ee)=>K(b)&&K(b)(...ee))},\" Clear All \",32)])):(ie(),ve(\"div\",n0e,[...W[19]||(W[19]=[X(\"div\",{class:\"i-carbon:circle-dash animate-spin\"},null,-1),X(\"div\",{op30:\"\"},\" Loading... \",-1)])]))],64)):(ie(),Ve(K(zp),{key:1,\"page-mode\":\"\",\"key-field\":\"id\",\"item-size\":28,items:K(M),buffer:100},{default:We(({item:ee})=>[Ne(jye,{class:ot([\"h-28px m-0 p-0\",K(po)===ee.id?\"bg-active\":\"\"]),\"task-id\":ee.id,expandable:ee.expandable,type:ee.type,current:K(po)===ee.id,indent:ee.indent,name:ee.name,typecheck:ee.typecheck===!0,\"project-name\":ee.projectName??\"\",\"project-name-color\":ee.projectNameColor??\"\",state:ee.state,duration:ee.duration,opened:ee.expanded,\"disable-task-location\":!o.value,\"on-item-click\":e.onItemClick},null,8,[\"task-id\",\"expandable\",\"type\",\"current\",\"indent\",\"name\",\"typecheck\",\"project-name\",\"project-name-color\",\"state\",\"duration\",\"opened\",\"disable-task-location\",\"class\",\"on-item-click\"])]),_:1},8,[\"items\"]))]),_:2},[K(c)?{name:\"summary\",fn:We(()=>[X(\"div\",Kye,[X(\"span\",Xye,\" FAIL (\"+Re(K(P).failed)+\") \",1),W[16]||(W[16]=X(\"span\",null,\"/\",-1)),X(\"span\",Yye,\" RUNNING (\"+Re(K(P).running)+\") \",1),X(\"span\",Zye,\" PASS (\"+Re(K(P).success)+\") \",1),W[17]||(W[17]=X(\"span\",null,\"/\",-1)),X(\"span\",Jye,\" SKIP (\"+Re(K(f).onlyTests?K(P).skipped:\"--\")+\") \",1)])]),key:\"0\"}:void 0]),1024)],32)],512)}}}),i0e={class:\"flex text-lg\"},o0e=rt({__name:\"Navigation\",setup(e){function t(){return ft.rpc.updateSnapshot()}const r=ke(()=>ol.value?\"light\":\"dark\");async function o(f){Os.value&&(Cu.value=!0,await Et(),go.value&&(Eu(!0),await Et())),f?.length?await _p(f):await Gce()}function s(){Oe.collapseAllNodes()}function c(){Oe.expandAllNodes()}return(f,d)=>{const h=vr(\"tooltip\");return ie(),Ve(r0e,{border:\"r base\",\"on-item-click\":K(vce),nested:!0,onRun:o},{header:We(({filteredFiles:p})=>[d[8]||(d[8]=X(\"img\",{\"w-6\":\"\",\"h-6\":\"\",src:Qve,alt:\"Vitest logo\"},null,-1)),d[9]||(d[9]=X(\"span\",{\"font-light\":\"\",\"text-sm\":\"\",\"flex-1\":\"\"},\"Vitest\",-1)),X(\"div\",i0e,[at(Ne(_t,{title:\"Collapse tests\",disabled:!K(Qs),\"data-testid\":\"collapse-all\",icon:\"i-carbon:collapse-all\",onClick:d[0]||(d[0]=g=>s())},null,8,[\"disabled\"]),[[ro,!K(sy)],[h,\"Collapse tests\",void 0,{bottom:!0}]]),at(Ne(_t,{disabled:!K(Qs),title:\"Expand tests\",\"data-testid\":\"expand-all\",icon:\"i-carbon:expand-all\",onClick:d[1]||(d[1]=g=>c())},null,8,[\"disabled\"]),[[ro,K(sy)],[h,\"Expand tests\",void 0,{bottom:!0}]]),at(Ne(_t,{title:\"Show dashboard\",class:\"!animate-100ms\",\"animate-count-1\":\"\",icon:\"i-carbon:dashboard\",onClick:d[2]||(d[2]=g=>K(Eu)(!0))},null,512),[[ro,K(mh)&&!K(Os)||!K(Ws)],[h,\"Dashboard\",void 0,{bottom:!0}]]),K(mh)&&!K(Os)?(ie(),Ve(K(Qi),{key:0,title:\"Coverage enabled but missing html reporter\",class:\"w-1.4em h-1.4em op100 rounded flex color-red5 dark:color-#f43f5e cursor-help\"},{popper:We(()=>[...d[6]||(d[6]=[X(\"div\",{class:\"op100 gap-1 p-y-1\",grid:\"~ items-center cols-[1.5em_1fr]\"},[X(\"div\",{class:\"i-carbon:information-square w-1.5em h-1.5em\"}),X(\"div\",null,\"Coverage enabled but missing html reporter.\"),X(\"div\",{style:{\"grid-column\":\"2\"}},\" Add html reporter to your configuration to see coverage here. \")],-1)])]),default:We(()=>[d[7]||(d[7]=X(\"div\",{class:\"i-carbon:folder-off ma\"},null,-1))]),_:1})):He(\"\",!0),K(Os)?at((ie(),Ve(_t,{key:1,disabled:K(Cu),title:\"Show coverage\",class:\"!animate-100ms\",\"animate-count-1\":\"\",icon:\"i-carbon:folder-details-reference\",onClick:d[3]||(d[3]=g=>K(yce)())},null,8,[\"disabled\"])),[[ro,!K(go)],[h,\"Coverage\",void 0,{bottom:!0}]]):He(\"\",!0),K(Oe).summary.failedSnapshot&&!K(gr)?at((ie(),Ve(_t,{key:2,icon:\"i-carbon:result-old\",disabled:!K(Oe).summary.failedSnapshotEnabled,onClick:d[4]||(d[4]=g=>K(Oe).summary.failedSnapshotEnabled&&t())},null,8,[\"disabled\"])),[[h,\"Update all failed snapshot(s)\",void 0,{bottom:!0}]]):He(\"\",!0),K(gr)?He(\"\",!0):at((ie(),Ve(_t,{key:3,disabled:p?.length===0,icon:\"i-carbon:play\",onClick:g=>o(p)},null,8,[\"disabled\",\"onClick\"])),[[h,p?p.length===0?\"No test to run (clear filter)\":\"Rerun filtered\":\"Rerun all\",void 0,{bottom:!0}]]),at(Ne(_t,{icon:\"dark:i-carbon-moon i-carbon:sun\",onClick:d[5]||(d[5]=g=>K(eme)())},null,512),[[h,`Toggle to ${r.value} mode`,void 0,{bottom:!0}]])])]),_:1},8,[\"on-item-click\"])}}}),s0e={\"h-3px\":\"\",relative:\"\",\"overflow-hidden\":\"\",class:\"px-0\",\"w-screen\":\"\"},l0e=rt({__name:\"ProgressBar\",setup(e){const{width:t}=Pw(),r=ke(()=>[Oe.summary.files===0&&\"!bg-gray-4 !dark:bg-gray-7\",!Ms.value&&\"in-progress\"].filter(Boolean).join(\" \")),o=ke(()=>{const d=Oe.summary.files;return d>0?t.value*Oe.summary.filesSuccess/d:0}),s=ke(()=>{const d=Oe.summary.files;return d>0?t.value*Oe.summary.filesFailed/d:0}),c=ke(()=>Oe.summary.files-Oe.summary.filesFailed-Oe.summary.filesSuccess),f=ke(()=>{const d=Oe.summary.files;return d>0?t.value*c.value/d:0});return(d,h)=>(ie(),ve(\"div\",{absolute:\"\",\"t-0\":\"\",\"l-0\":\"\",\"r-0\":\"\",\"z-index-1031\":\"\",\"pointer-events-none\":\"\",\"p-0\":\"\",\"h-3px\":\"\",grid:\"~ auto-cols-max\",\"justify-items-center\":\"\",\"w-screen\":\"\",class:ot(r.value)},[X(\"div\",s0e,[X(\"div\",{absolute:\"\",\"l-0\":\"\",\"t-0\":\"\",\"bg-red5\":\"\",\"h-3px\":\"\",class:ot(r.value),style:zt(`width: ${s.value}px;`)},\"   \",6),X(\"div\",{absolute:\"\",\"l-0\":\"\",\"t-0\":\"\",\"bg-green5\":\"\",\"h-3px\":\"\",class:ot(r.value),style:zt(`left: ${s.value}px; width: ${o.value}px;`)},\"   \",6),X(\"div\",{absolute:\"\",\"l-0\":\"\",\"t-0\":\"\",\"bg-yellow5\":\"\",\"h-3px\":\"\",class:ot(r.value),style:zt(`left: ${o.value+s.value}px; width: ${f.value}px;`)},\"   \",6)])],2))}}),a0e=Ni(l0e,[[\"__scopeId\",\"data-v-5320005b\"]]),c0e={\"h-screen\":\"\",\"w-screen\":\"\",overflow:\"hidden\"},u0e=rt({__name:\"index\",setup(e){const t=mce(),r=Nc(({panes:g})=>{h(),d(g)},0),o=Nc(({panes:g})=>{g.forEach((v,b)=>{qs.value[b]=v.size}),f(g),p()},0),s=Nc(({panes:g})=>{g.forEach((v,b)=>{co.value[b]=v.size}),d(g),p()},0),c=Nc(({panes:g})=>{f(g),h()},0);function f(g){At.navigation=g[0].size,At.details.size=g[1].size}function d(g){At.details.browser=g[0].size,At.details.main=g[1].size}function h(){const g=document.querySelector(\"#tester-ui\");g&&(g.style.pointerEvents=\"none\")}function p(){const g=document.querySelector(\"#tester-ui\");g&&(g.style.pointerEvents=\"\")}return(g,v)=>(ie(),ve(nt,null,[Ne(a0e),X(\"div\",c0e,[Ne(K(Gv),{class:\"pt-4px\",onResized:K(o),onResize:K(c)},{default:We(()=>[Ne(K(Rc),{size:K(qs)[0]},{default:We(()=>[Ne(o0e)]),_:1},8,[\"size\"]),Ne(K(Rc),{size:K(qs)[1]},{default:We(()=>[K(Zn)?(ie(),Ve(K(Gv),{id:\"details-splitpanes\",key:\"browser-detail\",onResize:K(r),onResized:K(s)},{default:We(()=>[Ne(K(Rc),{size:K(co)[0],\"min-size\":\"10\"},{default:We(()=>[v[0]||(Ys(-1,!0),(v[0]=Ne(sue)).cacheIndex=0,Ys(1),v[0])]),_:1},8,[\"size\"]),Ne(K(Rc),{size:K(co)[1]},{default:We(()=>[K(t)?(ie(),Ve(Iy,{key:\"summary\"})):K(go)?(ie(),Ve($y,{key:\"coverage\",src:K(Oy)},null,8,[\"src\"])):(ie(),Ve(l0,{key:\"details\"}))]),_:1},8,[\"size\"])]),_:1},8,[\"onResize\",\"onResized\"])):(ie(),Ve(BT,{key:\"ui-detail\"},{default:We(()=>[K(t)?(ie(),Ve(Iy,{key:\"summary\"})):K(go)?(ie(),Ve($y,{key:\"coverage\",src:K(Oy)},null,8,[\"src\"])):(ie(),Ve(l0,{key:\"details\"}))]),_:1}))]),_:1},8,[\"size\"])]),_:1},8,[\"onResized\",\"onResize\"])]),Ne(cue)],64))}}),f0e=[{name:\"index\",path:\"/\",component:u0e,props:!0}];/*!\n * vue-router v4.6.3\n * (c) 2025 Eduardo San Martin Morote\n * @license MIT\n */const Ls=typeof document<\"u\";function S1(e){return typeof e==\"object\"||\"displayName\"in e||\"props\"in e||\"__vccOpts\"in e}function d0e(e){return e.__esModule||e[Symbol.toStringTag]===\"Module\"||e.default&&S1(e.default)}const bt=Object.assign;function Hd(e,t){const r={};for(const o in t){const s=t[o];r[o]=zr(s)?s.map(e):e(s)}return r}const la=()=>{},zr=Array.isArray;function u0(e,t){const r={};for(const o in e)r[o]=o in t?t[o]:e[o];return r}const _1=/#/g,h0e=/&/g,p0e=/\\//g,g0e=/=/g,m0e=/\\?/g,T1=/\\+/g,v0e=/%5B/g,y0e=/%5D/g,C1=/%5E/g,b0e=/%60/g,E1=/%7B/g,w0e=/%7C/g,A1=/%7D/g,x0e=/%20/g;function Fp(e){return e==null?\"\":encodeURI(\"\"+e).replace(w0e,\"|\").replace(v0e,\"[\").replace(y0e,\"]\")}function k0e(e){return Fp(e).replace(E1,\"{\").replace(A1,\"}\").replace(C1,\"^\")}function $h(e){return Fp(e).replace(T1,\"%2B\").replace(x0e,\"+\").replace(_1,\"%23\").replace(h0e,\"%26\").replace(b0e,\"`\").replace(E1,\"{\").replace(A1,\"}\").replace(C1,\"^\")}function S0e(e){return $h(e).replace(g0e,\"%3D\")}function _0e(e){return Fp(e).replace(_1,\"%23\").replace(m0e,\"%3F\")}function T0e(e){return _0e(e).replace(p0e,\"%2F\")}function Na(e){if(e==null)return null;try{return decodeURIComponent(\"\"+e)}catch{}return\"\"+e}const C0e=/\\/$/,E0e=e=>e.replace(C0e,\"\");function Bd(e,t,r=\"/\"){let o,s={},c=\"\",f=\"\";const d=t.indexOf(\"#\");let h=t.indexOf(\"?\");return h=d>=0&&h>d?-1:h,h>=0&&(o=t.slice(0,h),c=t.slice(h,d>0?d:t.length),s=e(c.slice(1))),d>=0&&(o=o||t.slice(0,d),f=t.slice(d,t.length)),o=N0e(o??t,r),{fullPath:o+c+f,path:o,query:s,hash:Na(f)}}function A0e(e,t){const r=t.query?e(t.query):\"\";return t.path+(r&&\"?\")+r+(t.hash||\"\")}function f0(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||\"/\"}function L0e(e,t,r){const o=t.matched.length-1,s=r.matched.length-1;return o>-1&&o===s&&rl(t.matched[o],r.matched[s])&&L1(t.params,r.params)&&e(t.query)===e(r.query)&&t.hash===r.hash}function rl(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function L1(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const r in e)if(!M0e(e[r],t[r]))return!1;return!0}function M0e(e,t){return zr(e)?d0(e,t):zr(t)?d0(t,e):e===t}function d0(e,t){return zr(t)?e.length===t.length&&e.every((r,o)=>r===t[o]):e.length===1&&e[0]===t}function N0e(e,t){if(e.startsWith(\"/\"))return e;if(!e)return t;const r=t.split(\"/\"),o=e.split(\"/\"),s=o[o.length-1];(s===\"..\"||s===\".\")&&o.push(\"\");let c=r.length-1,f,d;for(f=0;f<o.length;f++)if(d=o[f],d!==\".\")if(d===\"..\")c>1&&c--;else break;return r.slice(0,c).join(\"/\")+\"/\"+o.slice(f).join(\"/\")}const Gi={path:\"/\",name:void 0,params:{},query:{},hash:\"\",fullPath:\"/\",matched:[],meta:{},redirectedFrom:void 0};let Ih=(function(e){return e.pop=\"pop\",e.push=\"push\",e})({}),Wd=(function(e){return e.back=\"back\",e.forward=\"forward\",e.unknown=\"\",e})({});function O0e(e){if(!e)if(Ls){const t=document.querySelector(\"base\");e=t&&t.getAttribute(\"href\")||\"/\",e=e.replace(/^\\w+:\\/\\/[^\\/]+/,\"\")}else e=\"/\";return e[0]!==\"/\"&&e[0]!==\"#\"&&(e=\"/\"+e),E0e(e)}const P0e=/^[^#]+#/;function R0e(e,t){return e.replace(P0e,\"#\")+t}function $0e(e,t){const r=document.documentElement.getBoundingClientRect(),o=e.getBoundingClientRect();return{behavior:t.behavior,left:o.left-r.left-(t.left||0),top:o.top-r.top-(t.top||0)}}const gf=()=>({left:window.scrollX,top:window.scrollY});function I0e(e){let t;if(\"el\"in e){const r=e.el,o=typeof r==\"string\"&&r.startsWith(\"#\"),s=typeof r==\"string\"?o?document.getElementById(r.slice(1)):document.querySelector(r):r;if(!s)return;t=$0e(s,e)}else t=e;\"scrollBehavior\"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function h0(e,t){return(history.state?history.state.position-t:-1)+e}const Dh=new Map;function D0e(e,t){Dh.set(e,t)}function z0e(e){const t=Dh.get(e);return Dh.delete(e),t}function F0e(e){return typeof e==\"string\"||e&&typeof e==\"object\"}function M1(e){return typeof e==\"string\"||typeof e==\"symbol\"}let qt=(function(e){return e[e.MATCHER_NOT_FOUND=1]=\"MATCHER_NOT_FOUND\",e[e.NAVIGATION_GUARD_REDIRECT=2]=\"NAVIGATION_GUARD_REDIRECT\",e[e.NAVIGATION_ABORTED=4]=\"NAVIGATION_ABORTED\",e[e.NAVIGATION_CANCELLED=8]=\"NAVIGATION_CANCELLED\",e[e.NAVIGATION_DUPLICATED=16]=\"NAVIGATION_DUPLICATED\",e})({});const N1=Symbol(\"\");qt.MATCHER_NOT_FOUND+\"\",qt.NAVIGATION_GUARD_REDIRECT+\"\",qt.NAVIGATION_ABORTED+\"\",qt.NAVIGATION_CANCELLED+\"\",qt.NAVIGATION_DUPLICATED+\"\";function il(e,t){return bt(new Error,{type:e,[N1]:!0},t)}function pi(e,t){return e instanceof Error&&N1 in e&&(t==null||!!(e.type&t))}const H0e=[\"params\",\"query\",\"hash\"];function B0e(e){if(typeof e==\"string\")return e;if(e.path!=null)return e.path;const t={};for(const r of H0e)r in e&&(t[r]=e[r]);return JSON.stringify(t,null,2)}function W0e(e){const t={};if(e===\"\"||e===\"?\")return t;const r=(e[0]===\"?\"?e.slice(1):e).split(\"&\");for(let o=0;o<r.length;++o){const s=r[o].replace(T1,\" \"),c=s.indexOf(\"=\"),f=Na(c<0?s:s.slice(0,c)),d=c<0?null:Na(s.slice(c+1));if(f in t){let h=t[f];zr(h)||(h=t[f]=[h]),h.push(d)}else t[f]=d}return t}function p0(e){let t=\"\";for(let r in e){const o=e[r];if(r=S0e(r),o==null){o!==void 0&&(t+=(t.length?\"&\":\"\")+r);continue}(zr(o)?o.map(s=>s&&$h(s)):[o&&$h(o)]).forEach(s=>{s!==void 0&&(t+=(t.length?\"&\":\"\")+r,s!=null&&(t+=\"=\"+s))})}return t}function q0e(e){const t={};for(const r in e){const o=e[r];o!==void 0&&(t[r]=zr(o)?o.map(s=>s==null?null:\"\"+s):o==null?o:\"\"+o)}return t}const j0e=Symbol(\"\"),g0=Symbol(\"\"),Hp=Symbol(\"\"),O1=Symbol(\"\"),zh=Symbol(\"\");function jl(){let e=[];function t(o){return e.push(o),()=>{const s=e.indexOf(o);s>-1&&e.splice(s,1)}}function r(){e=[]}return{add:t,list:()=>e.slice(),reset:r}}function no(e,t,r,o,s,c=f=>f()){const f=o&&(o.enterCallbacks[s]=o.enterCallbacks[s]||[]);return()=>new Promise((d,h)=>{const p=b=>{b===!1?h(il(qt.NAVIGATION_ABORTED,{from:r,to:t})):b instanceof Error?h(b):F0e(b)?h(il(qt.NAVIGATION_GUARD_REDIRECT,{from:t,to:b})):(f&&o.enterCallbacks[s]===f&&typeof b==\"function\"&&f.push(b),d())},g=c(()=>e.call(o&&o.instances[s],t,r,p));let v=Promise.resolve(g);e.length<3&&(v=v.then(p)),v.catch(b=>h(b))})}function qd(e,t,r,o,s=c=>c()){const c=[];for(const f of e)for(const d in f.components){let h=f.components[d];if(!(t!==\"beforeRouteEnter\"&&!f.instances[d]))if(S1(h)){const p=(h.__vccOpts||h)[t];p&&c.push(no(p,r,o,f,d,s))}else{let p=h();c.push(()=>p.then(g=>{if(!g)throw new Error(`Couldn't resolve component \"${d}\" at \"${f.path}\"`);const v=d0e(g)?g.default:g;f.mods[d]=g,f.components[d]=v;const b=(v.__vccOpts||v)[t];return b&&no(b,r,o,f,d,s)()}))}}return c}function U0e(e,t){const r=[],o=[],s=[],c=Math.max(t.matched.length,e.matched.length);for(let f=0;f<c;f++){const d=t.matched[f];d&&(e.matched.find(p=>rl(p,d))?o.push(d):r.push(d));const h=e.matched[f];h&&(t.matched.find(p=>rl(p,h))||s.push(h))}return[r,o,s]}/*!\n * vue-router v4.6.3\n * (c) 2025 Eduardo San Martin Morote\n * @license MIT\n */let V0e=()=>location.protocol+\"//\"+location.host;function P1(e,t){const{pathname:r,search:o,hash:s}=t,c=e.indexOf(\"#\");if(c>-1){let f=s.includes(e.slice(c))?e.slice(c).length:1,d=s.slice(f);return d[0]!==\"/\"&&(d=\"/\"+d),f0(d,\"\")}return f0(r,e)+o+s}function G0e(e,t,r,o){let s=[],c=[],f=null;const d=({state:b})=>{const w=P1(e,location),E=r.value,L=t.value;let P=0;if(b){if(r.value=w,t.value=b,f&&f===E){f=null;return}P=L?b.position-L.position:0}else o(w);s.forEach(M=>{M(r.value,E,{delta:P,type:Ih.pop,direction:P?P>0?Wd.forward:Wd.back:Wd.unknown})})};function h(){f=r.value}function p(b){s.push(b);const w=()=>{const E=s.indexOf(b);E>-1&&s.splice(E,1)};return c.push(w),w}function g(){if(document.visibilityState===\"hidden\"){const{history:b}=window;if(!b.state)return;b.replaceState(bt({},b.state,{scroll:gf()}),\"\")}}function v(){for(const b of c)b();c=[],window.removeEventListener(\"popstate\",d),window.removeEventListener(\"pagehide\",g),document.removeEventListener(\"visibilitychange\",g)}return window.addEventListener(\"popstate\",d),window.addEventListener(\"pagehide\",g),document.addEventListener(\"visibilitychange\",g),{pauseListeners:h,listen:p,destroy:v}}function m0(e,t,r,o=!1,s=!1){return{back:e,current:t,forward:r,replaced:o,position:window.history.length,scroll:s?gf():null}}function K0e(e){const{history:t,location:r}=window,o={value:P1(e,r)},s={value:t.state};s.value||c(o.value,{back:null,current:o.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function c(h,p,g){const v=e.indexOf(\"#\"),b=v>-1?(r.host&&document.querySelector(\"base\")?e:e.slice(v))+h:V0e()+e+h;try{t[g?\"replaceState\":\"pushState\"](p,\"\",b),s.value=p}catch(w){console.error(w),r[g?\"replace\":\"assign\"](b)}}function f(h,p){c(h,bt({},t.state,m0(s.value.back,h,s.value.forward,!0),p,{position:s.value.position}),!0),o.value=h}function d(h,p){const g=bt({},s.value,t.state,{forward:h,scroll:gf()});c(g.current,g,!0),c(h,bt({},m0(o.value,h,null),{position:g.position+1},p),!1),o.value=h}return{location:o,state:s,push:d,replace:f}}function X0e(e){e=O0e(e);const t=K0e(e),r=G0e(e,t.state,t.location,t.replace);function o(c,f=!0){f||r.pauseListeners(),history.go(c)}const s=bt({location:\"\",base:e,go:o,createHref:R0e.bind(null,e)},t,r);return Object.defineProperty(s,\"location\",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(s,\"state\",{enumerable:!0,get:()=>t.state.value}),s}function Y0e(e){return e=location.host?e||location.pathname+location.search:\"\",e.includes(\"#\")||(e+=\"#\"),X0e(e)}let Wo=(function(e){return e[e.Static=0]=\"Static\",e[e.Param=1]=\"Param\",e[e.Group=2]=\"Group\",e})({});var rn=(function(e){return e[e.Static=0]=\"Static\",e[e.Param=1]=\"Param\",e[e.ParamRegExp=2]=\"ParamRegExp\",e[e.ParamRegExpEnd=3]=\"ParamRegExpEnd\",e[e.EscapeNext=4]=\"EscapeNext\",e})(rn||{});const Z0e={type:Wo.Static,value:\"\"},J0e=/[a-zA-Z0-9_]/;function Q0e(e){if(!e)return[[]];if(e===\"/\")return[[Z0e]];if(!e.startsWith(\"/\"))throw new Error(`Invalid path \"${e}\"`);function t(w){throw new Error(`ERR (${r})/\"${p}\": ${w}`)}let r=rn.Static,o=r;const s=[];let c;function f(){c&&s.push(c),c=[]}let d=0,h,p=\"\",g=\"\";function v(){p&&(r===rn.Static?c.push({type:Wo.Static,value:p}):r===rn.Param||r===rn.ParamRegExp||r===rn.ParamRegExpEnd?(c.length>1&&(h===\"*\"||h===\"+\")&&t(`A repeatable param (${p}) must be alone in its segment. eg: '/:ids+.`),c.push({type:Wo.Param,value:p,regexp:g,repeatable:h===\"*\"||h===\"+\",optional:h===\"*\"||h===\"?\"})):t(\"Invalid state to consume buffer\"),p=\"\")}function b(){p+=h}for(;d<e.length;){if(h=e[d++],h===\"\\\\\"&&r!==rn.ParamRegExp){o=r,r=rn.EscapeNext;continue}switch(r){case rn.Static:h===\"/\"?(p&&v(),f()):h===\":\"?(v(),r=rn.Param):b();break;case rn.EscapeNext:b(),r=o;break;case rn.Param:h===\"(\"?r=rn.ParamRegExp:J0e.test(h)?b():(v(),r=rn.Static,h!==\"*\"&&h!==\"?\"&&h!==\"+\"&&d--);break;case rn.ParamRegExp:h===\")\"?g[g.length-1]==\"\\\\\"?g=g.slice(0,-1)+h:r=rn.ParamRegExpEnd:g+=h;break;case rn.ParamRegExpEnd:v(),r=rn.Static,h!==\"*\"&&h!==\"?\"&&h!==\"+\"&&d--,g=\"\";break;default:t(\"Unknown state\");break}}return r===rn.ParamRegExp&&t(`Unfinished custom RegExp for param \"${p}\"`),v(),f(),s}const v0=\"[^/]+?\",ebe={sensitive:!1,strict:!1,start:!0,end:!0};var On=(function(e){return e[e._multiplier=10]=\"_multiplier\",e[e.Root=90]=\"Root\",e[e.Segment=40]=\"Segment\",e[e.SubSegment=30]=\"SubSegment\",e[e.Static=40]=\"Static\",e[e.Dynamic=20]=\"Dynamic\",e[e.BonusCustomRegExp=10]=\"BonusCustomRegExp\",e[e.BonusWildcard=-50]=\"BonusWildcard\",e[e.BonusRepeatable=-20]=\"BonusRepeatable\",e[e.BonusOptional=-8]=\"BonusOptional\",e[e.BonusStrict=.7000000000000001]=\"BonusStrict\",e[e.BonusCaseSensitive=.25]=\"BonusCaseSensitive\",e})(On||{});const tbe=/[.+*?^${}()[\\]/\\\\]/g;function nbe(e,t){const r=bt({},ebe,t),o=[];let s=r.start?\"^\":\"\";const c=[];for(const p of e){const g=p.length?[]:[On.Root];r.strict&&!p.length&&(s+=\"/\");for(let v=0;v<p.length;v++){const b=p[v];let w=On.Segment+(r.sensitive?On.BonusCaseSensitive:0);if(b.type===Wo.Static)v||(s+=\"/\"),s+=b.value.replace(tbe,\"\\\\$&\"),w+=On.Static;else if(b.type===Wo.Param){const{value:E,repeatable:L,optional:P,regexp:M}=b;c.push({name:E,repeatable:L,optional:P});const R=M||v0;if(R!==v0){w+=On.BonusCustomRegExp;try{`${R}`}catch(_){throw new Error(`Invalid custom RegExp for param \"${E}\" (${R}): `+_.message)}}let I=L?`((?:${R})(?:/(?:${R}))*)`:`(${R})`;v||(I=P&&p.length<2?`(?:/${I})`:\"/\"+I),P&&(I+=\"?\"),s+=I,w+=On.Dynamic,P&&(w+=On.BonusOptional),L&&(w+=On.BonusRepeatable),R===\".*\"&&(w+=On.BonusWildcard)}g.push(w)}o.push(g)}if(r.strict&&r.end){const p=o.length-1;o[p][o[p].length-1]+=On.BonusStrict}r.strict||(s+=\"/?\"),r.end?s+=\"$\":r.strict&&!s.endsWith(\"/\")&&(s+=\"(?:/|$)\");const f=new RegExp(s,r.sensitive?\"\":\"i\");function d(p){const g=p.match(f),v={};if(!g)return null;for(let b=1;b<g.length;b++){const w=g[b]||\"\",E=c[b-1];v[E.name]=w&&E.repeatable?w.split(\"/\"):w}return v}function h(p){let g=\"\",v=!1;for(const b of e){(!v||!g.endsWith(\"/\"))&&(g+=\"/\"),v=!1;for(const w of b)if(w.type===Wo.Static)g+=w.value;else if(w.type===Wo.Param){const{value:E,repeatable:L,optional:P}=w,M=E in p?p[E]:\"\";if(zr(M)&&!L)throw new Error(`Provided param \"${E}\" is an array but it is not repeatable (* or + modifiers)`);const R=zr(M)?M.join(\"/\"):M;if(!R)if(P)b.length<2&&(g.endsWith(\"/\")?g=g.slice(0,-1):v=!0);else throw new Error(`Missing required param \"${E}\"`);g+=R}}return g||\"/\"}return{re:f,score:o,keys:c,parse:d,stringify:h}}function rbe(e,t){let r=0;for(;r<e.length&&r<t.length;){const o=t[r]-e[r];if(o)return o;r++}return e.length<t.length?e.length===1&&e[0]===On.Static+On.Segment?-1:1:e.length>t.length?t.length===1&&t[0]===On.Static+On.Segment?1:-1:0}function R1(e,t){let r=0;const o=e.score,s=t.score;for(;r<o.length&&r<s.length;){const c=rbe(o[r],s[r]);if(c)return c;r++}if(Math.abs(s.length-o.length)===1){if(y0(o))return 1;if(y0(s))return-1}return s.length-o.length}function y0(e){const t=e[e.length-1];return e.length>0&&t[t.length-1]<0}const ibe={strict:!1,end:!0,sensitive:!1};function obe(e,t,r){const o=nbe(Q0e(e.path),r),s=bt(o,{record:e,parent:t,children:[],alias:[]});return t&&!s.record.aliasOf==!t.record.aliasOf&&t.children.push(s),s}function sbe(e,t){const r=[],o=new Map;t=u0(ibe,t);function s(v){return o.get(v)}function c(v,b,w){const E=!w,L=w0(v);L.aliasOf=w&&w.record;const P=u0(t,v),M=[L];if(\"alias\"in v){const _=typeof v.alias==\"string\"?[v.alias]:v.alias;for(const $ of _)M.push(w0(bt({},L,{components:w?w.record.components:L.components,path:$,aliasOf:w?w.record:L})))}let R,I;for(const _ of M){const{path:$}=_;if(b&&$[0]!==\"/\"){const W=b.record.path,ne=W[W.length-1]===\"/\"?\"\":\"/\";_.path=b.record.path+($&&ne+$)}if(R=obe(_,b,P),w?w.alias.push(R):(I=I||R,I!==R&&I.alias.push(R),E&&v.name&&!x0(R)&&f(v.name)),$1(R)&&h(R),L.children){const W=L.children;for(let ne=0;ne<W.length;ne++)c(W[ne],R,w&&w.children[ne])}w=w||R}return I?()=>{f(I)}:la}function f(v){if(M1(v)){const b=o.get(v);b&&(o.delete(v),r.splice(r.indexOf(b),1),b.children.forEach(f),b.alias.forEach(f))}else{const b=r.indexOf(v);b>-1&&(r.splice(b,1),v.record.name&&o.delete(v.record.name),v.children.forEach(f),v.alias.forEach(f))}}function d(){return r}function h(v){const b=cbe(v,r);r.splice(b,0,v),v.record.name&&!x0(v)&&o.set(v.record.name,v)}function p(v,b){let w,E={},L,P;if(\"name\"in v&&v.name){if(w=o.get(v.name),!w)throw il(qt.MATCHER_NOT_FOUND,{location:v});P=w.record.name,E=bt(b0(b.params,w.keys.filter(I=>!I.optional).concat(w.parent?w.parent.keys.filter(I=>I.optional):[]).map(I=>I.name)),v.params&&b0(v.params,w.keys.map(I=>I.name))),L=w.stringify(E)}else if(v.path!=null)L=v.path,w=r.find(I=>I.re.test(L)),w&&(E=w.parse(L),P=w.record.name);else{if(w=b.name?o.get(b.name):r.find(I=>I.re.test(b.path)),!w)throw il(qt.MATCHER_NOT_FOUND,{location:v,currentLocation:b});P=w.record.name,E=bt({},b.params,v.params),L=w.stringify(E)}const M=[];let R=w;for(;R;)M.unshift(R.record),R=R.parent;return{name:P,path:L,params:E,matched:M,meta:abe(M)}}e.forEach(v=>c(v));function g(){r.length=0,o.clear()}return{addRoute:c,resolve:p,removeRoute:f,clearRoutes:g,getRoutes:d,getRecordMatcher:s}}function b0(e,t){const r={};for(const o of t)o in e&&(r[o]=e[o]);return r}function w0(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:lbe(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:\"components\"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,\"mods\",{value:{}}),t}function lbe(e){const t={},r=e.props||!1;if(\"component\"in e)t.default=r;else for(const o in e.components)t[o]=typeof r==\"object\"?r[o]:r;return t}function x0(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function abe(e){return e.reduce((t,r)=>bt(t,r.meta),{})}function cbe(e,t){let r=0,o=t.length;for(;r!==o;){const c=r+o>>1;R1(e,t[c])<0?o=c:r=c+1}const s=ube(e);return s&&(o=t.lastIndexOf(s,o-1)),o}function ube(e){let t=e;for(;t=t.parent;)if($1(t)&&R1(e,t)===0)return t}function $1({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function k0(e){const t=pn(Hp),r=pn(O1),o=ke(()=>{const h=K(e.to);return t.resolve(h)}),s=ke(()=>{const{matched:h}=o.value,{length:p}=h,g=h[p-1],v=r.matched;if(!g||!v.length)return-1;const b=v.findIndex(rl.bind(null,g));if(b>-1)return b;const w=S0(h[p-2]);return p>1&&S0(g)===w&&v[v.length-1].path!==w?v.findIndex(rl.bind(null,h[p-2])):b}),c=ke(()=>s.value>-1&&gbe(r.params,o.value.params)),f=ke(()=>s.value>-1&&s.value===r.matched.length-1&&L1(r.params,o.value.params));function d(h={}){if(pbe(h)){const p=t[K(e.replace)?\"replace\":\"push\"](K(e.to)).catch(la);return e.viewTransition&&typeof document<\"u\"&&\"startViewTransition\"in document&&document.startViewTransition(()=>p),p}return Promise.resolve()}return{route:o,href:ke(()=>o.value.href),isActive:c,isExactActive:f,navigate:d}}function fbe(e){return e.length===1?e[0]:e}const dbe=rt({name:\"RouterLink\",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:\"page\"},viewTransition:Boolean},useLink:k0,setup(e,{slots:t}){const r=ir(k0(e)),{options:o}=pn(Hp),s=ke(()=>({[_0(e.activeClass,o.linkActiveClass,\"router-link-active\")]:r.isActive,[_0(e.exactActiveClass,o.linkExactActiveClass,\"router-link-exact-active\")]:r.isExactActive}));return()=>{const c=t.default&&fbe(t.default(r));return e.custom?c:za(\"a\",{\"aria-current\":r.isExactActive?e.ariaCurrentValue:null,href:r.href,onClick:r.navigate,class:s.value},c)}}}),hbe=dbe;function pbe(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute(\"target\");if(/\\b_blank\\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function gbe(e,t){for(const r in t){const o=t[r],s=e[r];if(typeof o==\"string\"){if(o!==s)return!1}else if(!zr(s)||s.length!==o.length||o.some((c,f)=>c!==s[f]))return!1}return!0}function S0(e){return e?e.aliasOf?e.aliasOf.path:e.path:\"\"}const _0=(e,t,r)=>e??t??r,mbe=rt({name:\"RouterView\",inheritAttrs:!1,props:{name:{type:String,default:\"default\"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:r}){const o=pn(zh),s=ke(()=>e.route||o.value),c=pn(g0,0),f=ke(()=>{let p=K(c);const{matched:g}=s.value;let v;for(;(v=g[p])&&!v.components;)p++;return p}),d=ke(()=>s.value.matched[f.value]);dr(g0,ke(()=>f.value+1)),dr(j0e,d),dr(zh,s);const h=Ge();return xt(()=>[h.value,d.value,e.name],([p,g,v],[b,w,E])=>{g&&(g.instances[v]=p,w&&w!==g&&p&&p===b&&(g.leaveGuards.size||(g.leaveGuards=w.leaveGuards),g.updateGuards.size||(g.updateGuards=w.updateGuards))),p&&g&&(!w||!rl(g,w)||!b)&&(g.enterCallbacks[v]||[]).forEach(L=>L(p))},{flush:\"post\"}),()=>{const p=s.value,g=e.name,v=d.value,b=v&&v.components[g];if(!b)return T0(r.default,{Component:b,route:p});const w=v.props[g],E=w?w===!0?p.params:typeof w==\"function\"?w(p):w:null,P=za(b,bt({},E,t,{onVnodeUnmounted:M=>{M.component.isUnmounted&&(v.instances[g]=null)},ref:h}));return T0(r.default,{Component:P,route:p})||P}}});function T0(e,t){if(!e)return null;const r=e(t);return r.length===1?r[0]:r}const vbe=mbe;function ybe(e){const t=sbe(e.routes,e),r=e.parseQuery||W0e,o=e.stringifyQuery||p0,s=e.history,c=jl(),f=jl(),d=jl(),h=Ft(Gi);let p=Gi;Ls&&e.scrollBehavior&&\"scrollRestoration\"in history&&(history.scrollRestoration=\"manual\");const g=Hd.bind(null,F=>\"\"+F),v=Hd.bind(null,T0e),b=Hd.bind(null,Na);function w(F,Y){let re,le;return M1(F)?(re=t.getRecordMatcher(F),le=Y):le=F,t.addRoute(le,re)}function E(F){const Y=t.getRecordMatcher(F);Y&&t.removeRoute(Y)}function L(){return t.getRoutes().map(F=>F.record)}function P(F){return!!t.getRecordMatcher(F)}function M(F,Y){if(Y=bt({},Y||h.value),typeof F==\"string\"){const Q=Bd(r,F,Y.path),he=t.resolve({path:Q.path},Y),de=s.createHref(Q.fullPath);return bt(Q,he,{params:b(he.params),hash:Na(Q.hash),redirectedFrom:void 0,href:de})}let re;if(F.path!=null)re=bt({},F,{path:Bd(r,F.path,Y.path).path});else{const Q=bt({},F.params);for(const he in Q)Q[he]==null&&delete Q[he];re=bt({},F,{params:v(Q)}),Y.params=v(Y.params)}const le=t.resolve(re,Y),ae=F.hash||\"\";le.params=g(b(le.params));const D=A0e(o,bt({},F,{hash:k0e(ae),path:le.path})),q=s.createHref(D);return bt({fullPath:D,hash:ae,query:o===p0?q0e(F.query):F.query||{}},le,{redirectedFrom:void 0,href:q})}function R(F){return typeof F==\"string\"?Bd(r,F,h.value.path):bt({},F)}function I(F,Y){if(p!==F)return il(qt.NAVIGATION_CANCELLED,{from:Y,to:F})}function _(F){return ne(F)}function $(F){return _(bt(R(F),{replace:!0}))}function W(F,Y){const re=F.matched[F.matched.length-1];if(re&&re.redirect){const{redirect:le}=re;let ae=typeof le==\"function\"?le(F,Y):le;return typeof ae==\"string\"&&(ae=ae.includes(\"?\")||ae.includes(\"#\")?ae=R(ae):{path:ae},ae.params={}),bt({query:F.query,hash:F.hash,params:ae.path!=null?{}:F.params},ae)}}function ne(F,Y){const re=p=M(F),le=h.value,ae=F.state,D=F.force,q=F.replace===!0,Q=W(re,le);if(Q)return ne(bt(R(Q),{state:typeof Q==\"object\"?bt({},ae,Q.state):ae,force:D,replace:q}),Y||re);const he=re;he.redirectedFrom=Y;let de;return!D&&L0e(o,le,re)&&(de=il(qt.NAVIGATION_DUPLICATED,{to:he,from:le}),Be(le,le,!0,!1)),(de?Promise.resolve(de):G(he,le)).catch(ge=>pi(ge)?pi(ge,qt.NAVIGATION_GUARD_REDIRECT)?ge:Se(ge):ce(ge,he,le)).then(ge=>{if(ge){if(pi(ge,qt.NAVIGATION_GUARD_REDIRECT))return ne(bt({replace:q},R(ge.to),{state:typeof ge.to==\"object\"?bt({},ae,ge.to.state):ae,force:D}),Y||he)}else ge=N(he,le,!0,q,ae);return j(he,le,ge),ge})}function ee(F,Y){const re=I(F,Y);return re?Promise.reject(re):Promise.resolve()}function Z(F){const Y=je.values().next().value;return Y&&typeof Y.runWithContext==\"function\"?Y.runWithContext(F):F()}function G(F,Y){let re;const[le,ae,D]=U0e(F,Y);re=qd(le.reverse(),\"beforeRouteLeave\",F,Y);for(const Q of le)Q.leaveGuards.forEach(he=>{re.push(no(he,F,Y))});const q=ee.bind(null,F,Y);return re.push(q),Pe(re).then(()=>{re=[];for(const Q of c.list())re.push(no(Q,F,Y));return re.push(q),Pe(re)}).then(()=>{re=qd(ae,\"beforeRouteUpdate\",F,Y);for(const Q of ae)Q.updateGuards.forEach(he=>{re.push(no(he,F,Y))});return re.push(q),Pe(re)}).then(()=>{re=[];for(const Q of D)if(Q.beforeEnter)if(zr(Q.beforeEnter))for(const he of Q.beforeEnter)re.push(no(he,F,Y));else re.push(no(Q.beforeEnter,F,Y));return re.push(q),Pe(re)}).then(()=>(F.matched.forEach(Q=>Q.enterCallbacks={}),re=qd(D,\"beforeRouteEnter\",F,Y,Z),re.push(q),Pe(re))).then(()=>{re=[];for(const Q of f.list())re.push(no(Q,F,Y));return re.push(q),Pe(re)}).catch(Q=>pi(Q,qt.NAVIGATION_CANCELLED)?Q:Promise.reject(Q))}function j(F,Y,re){d.list().forEach(le=>Z(()=>le(F,Y,re)))}function N(F,Y,re,le,ae){const D=I(F,Y);if(D)return D;const q=Y===Gi,Q=Ls?history.state:{};re&&(le||q?s.replace(F.fullPath,bt({scroll:q&&Q&&Q.scroll},ae)):s.push(F.fullPath,ae)),h.value=F,Be(F,Y,re,q),Se()}let O;function C(){O||(O=s.listen((F,Y,re)=>{if(!Fe.listening)return;const le=M(F),ae=W(le,Fe.currentRoute.value);if(ae){ne(bt(ae,{replace:!0,force:!0}),le).catch(la);return}p=le;const D=h.value;Ls&&D0e(h0(D.fullPath,re.delta),gf()),G(le,D).catch(q=>pi(q,qt.NAVIGATION_ABORTED|qt.NAVIGATION_CANCELLED)?q:pi(q,qt.NAVIGATION_GUARD_REDIRECT)?(ne(bt(R(q.to),{force:!0}),le).then(Q=>{pi(Q,qt.NAVIGATION_ABORTED|qt.NAVIGATION_DUPLICATED)&&!re.delta&&re.type===Ih.pop&&s.go(-1,!1)}).catch(la),Promise.reject()):(re.delta&&s.go(-re.delta,!1),ce(q,le,D))).then(q=>{q=q||N(le,D,!1),q&&(re.delta&&!pi(q,qt.NAVIGATION_CANCELLED)?s.go(-re.delta,!1):re.type===Ih.pop&&pi(q,qt.NAVIGATION_ABORTED|qt.NAVIGATION_DUPLICATED)&&s.go(-1,!1)),j(le,D,q)}).catch(la)}))}let k=jl(),z=jl(),B;function ce(F,Y,re){Se(F);const le=z.list();return le.length?le.forEach(ae=>ae(F,Y,re)):console.error(F),Promise.reject(F)}function be(){return B&&h.value!==Gi?Promise.resolve():new Promise((F,Y)=>{k.add([F,Y])})}function Se(F){return B||(B=!F,C(),k.list().forEach(([Y,re])=>F?re(F):Y()),k.reset()),F}function Be(F,Y,re,le){const{scrollBehavior:ae}=e;if(!Ls||!ae)return Promise.resolve();const D=!re&&z0e(h0(F.fullPath,0))||(le||!re)&&history.state&&history.state.scroll||null;return Et().then(()=>ae(F,Y,D)).then(q=>q&&I0e(q)).catch(q=>ce(q,F,Y))}const Ae=F=>s.go(F);let Ke;const je=new Set,Fe={currentRoute:h,listening:!0,addRoute:w,removeRoute:E,clearRoutes:t.clearRoutes,hasRoute:P,getRoutes:L,resolve:M,options:e,push:_,replace:$,go:Ae,back:()=>Ae(-1),forward:()=>Ae(1),beforeEach:c.add,beforeResolve:f.add,afterEach:d.add,onError:z.add,isReady:be,install(F){F.component(\"RouterLink\",hbe),F.component(\"RouterView\",vbe),F.config.globalProperties.$router=Fe,Object.defineProperty(F.config.globalProperties,\"$route\",{enumerable:!0,get:()=>K(h)}),Ls&&!Ke&&h.value===Gi&&(Ke=!0,_(s.location).catch(le=>{}));const Y={};for(const le in Gi)Object.defineProperty(Y,le,{get:()=>h.value[le],enumerable:!0});F.provide(Hp,Fe),F.provide(O1,Gh(Y)),F.provide(zh,h);const re=F.unmount;je.add(F),F.unmount=function(){je.delete(F),je.size<1&&(p=Gi,O&&O(),O=null,h.value=Gi,Ke=!1,B=!1),re()}}};function Pe(F){return F.reduce((Y,re)=>Y.then(()=>Z(re)),Promise.resolve())}return Fe}const bbe={tooltip:pE};ww.options.instantMove=!0;ww.options.distance=10;function wbe(){return ybe({history:Y0e(),routes:f0e})}const xbe=[wbe],Bp=Qb(vC);xbe.forEach(e=>{Bp.use(e())});Object.entries(bbe).forEach(([e,t])=>{Bp.directive(e,t)});Bp.mount(\"#app\");\n"
  },
  {
    "path": "test/cli/test/fixtures/reporters/html/all-passing-or-skipped/assets/index-DlhE0rqZ.css",
    "content": ".CodeMirror-simplescroll-horizontal div,.CodeMirror-simplescroll-vertical div{position:absolute;background:#ccc;-moz-box-sizing:border-box;box-sizing:border-box;border:1px solid #bbb;border-radius:2px}.CodeMirror-simplescroll-horizontal,.CodeMirror-simplescroll-vertical{position:absolute;z-index:6;background:#eee}.CodeMirror-simplescroll-horizontal{bottom:0;left:0;height:8px}.CodeMirror-simplescroll-horizontal div{bottom:0;height:100%}.CodeMirror-simplescroll-vertical{right:0;top:0;width:8px}.CodeMirror-simplescroll-vertical div{right:0;width:100%}.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler,.CodeMirror-overlayscroll .CodeMirror-gutter-filler{display:none}.CodeMirror-overlayscroll-horizontal div,.CodeMirror-overlayscroll-vertical div{position:absolute;background:#bcd;border-radius:3px}.CodeMirror-overlayscroll-horizontal,.CodeMirror-overlayscroll-vertical{position:absolute;z-index:6}.CodeMirror-overlayscroll-horizontal{bottom:0;left:0;height:6px}.CodeMirror-overlayscroll-horizontal div{bottom:0;height:100%}.CodeMirror-overlayscroll-vertical{right:0;top:0;width:6px}.CodeMirror-overlayscroll-vertical div{right:0;width:100%}#tester-container[data-v-2e86b8c3]:not([data-ready]){width:100%;height:100%;display:flex;align-items:center;justify-content:center}[data-ready] #tester-ui[data-v-2e86b8c3]{width:var(--viewport-width);height:var(--viewport-height);transform:var(--tester-transform);margin-left:var(--tester-margin-left)}#vitest-ui-coverage{width:100%;height:calc(100vh - 42px);border:none}.number[data-v-1bd0f2ea]{font-weight:400;text-align:right}.unhandled-errors[data-v-1bd0f2ea]{--cm-ttc-c-thumb: #ccc}html.dark .unhandled-errors[data-v-1bd0f2ea]{--cm-ttc-c-thumb: #444}:root{--color-link-label: var(--color-text);--color-link: #ddd;--color-node-external: #6C5C33;--color-node-inline: #8bc4a0;--color-node-root: #6e9aa5;--color-node-focused: #e67e22;--color-node-label: var(--color-text);--color-node-stroke: var(--color-text)}html.dark{--color-text: #fff;--color-link: #333;--color-node-external: #c0ad79;--color-node-inline: #468b60;--color-node-root: #467d8b;--color-node-focused: #f39c12}.graph{height:calc(100% - 39px)!important}.graph .node{stroke-width:2px;stroke-opacity:.5}.graph .link{stroke-width:2px}.graph .node:hover:not(.focused){filter:none!important}.graph .node__label{transform:translateY(20px);font-weight:100;filter:brightness(.5)}html.dark .graph .node__label{filter:brightness(1.2)}.scrolls[data-v-08ce44b7]{place-items:center}.task-error[data-v-1fcfe7a4]{--cm-ttc-c-thumb: #ccc}html.dark .task-error[data-v-1fcfe7a4]{--cm-ttc-c-thumb: #444}.task-error[data-v-9d875d6e]{--cm-ttc-c-thumb: #ccc}html.dark .task-error[data-v-9d875d6e]{--cm-ttc-c-thumb: #444}.task-error[data-v-1a68630b]{--cm-ttc-c-thumb: #ccc}html.dark .task-error[data-v-1a68630b]{--cm-ttc-c-thumb: #444}.details-panel{-webkit-user-select:none;user-select:none;width:100%}.checkbox:focus-within{outline:none;margin-bottom:0!important;border-bottom-width:1px}.vertical-line[data-v-58d301d8]:first-of-type{border-left-width:2px}.vertical-line+.vertical-line[data-v-58d301d8]{border-right-width:1px}.test-actions[data-v-58d301d8]{display:none}.item-wrapper:hover .test-actions[data-v-58d301d8]{display:flex}.vue-recycle-scroller{position:relative}.vue-recycle-scroller.direction-vertical:not(.page-mode){overflow-y:auto}.vue-recycle-scroller.direction-horizontal:not(.page-mode){overflow-x:auto}.vue-recycle-scroller.direction-horizontal{display:flex}.vue-recycle-scroller__slot{flex:auto 0 0}.vue-recycle-scroller__item-wrapper{flex:1;box-sizing:border-box;overflow:hidden;position:relative}.vue-recycle-scroller.ready .vue-recycle-scroller__item-view{position:absolute;top:0;left:0;will-change:transform}.vue-recycle-scroller.direction-vertical .vue-recycle-scroller__item-wrapper{width:100%}.vue-recycle-scroller.direction-horizontal .vue-recycle-scroller__item-wrapper{height:100%}.vue-recycle-scroller.ready.direction-vertical .vue-recycle-scroller__item-view{width:100%}.vue-recycle-scroller.ready.direction-horizontal .vue-recycle-scroller__item-view{height:100%}.in-progress[data-v-5320005b]{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px;animation:in-progress-stripes-5320005b 2s linear infinite}@keyframes in-progress-stripes-5320005b{0%{background-position:40px 0}to{background-position:0 0}}.graph,.graph>svg{display:block}.graph{height:100%;touch-action:none;width:100%}.graph *{-webkit-touch-callout:none!important;-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.link{fill:none;stroke-width:4px}.node{--color-stroke: var(--color-node-stroke, rgba(0, 0, 0, .5));cursor:pointer;stroke:none;stroke-width:2px;transition:filter .25s ease,stroke .25s ease,stroke-dasharray .25s ease}.node:hover:not(.focused){filter:brightness(80%);stroke:var(--color-stroke);stroke-dasharray:4px}.node.focused{stroke:var(--color-stroke)}.link__label,.node__label{pointer-events:none;text-anchor:middle}.grabbed{cursor:grabbing!important}.splitpanes{display:flex;width:100%;height:100%}.splitpanes--vertical{flex-direction:row}.splitpanes--horizontal{flex-direction:column}.splitpanes--dragging .splitpanes__pane,*:has(.splitpanes--dragging){-webkit-user-select:none;user-select:none;pointer-events:none}.splitpanes__pane{width:100%;height:100%;overflow:hidden}.splitpanes--vertical .splitpanes__pane{transition:width .2s ease-out;will-change:width}.splitpanes--horizontal .splitpanes__pane{transition:height .2s ease-out;will-change:height}.splitpanes--dragging .splitpanes__pane{transition:none}.splitpanes__splitter{touch-action:none}.splitpanes--vertical>.splitpanes__splitter{min-width:1px;cursor:col-resize}.splitpanes--horizontal>.splitpanes__splitter{min-height:1px;cursor:row-resize}.default-theme.splitpanes .splitpanes__pane{background-color:#f2f2f2}.default-theme.splitpanes .splitpanes__splitter{background-color:#fff;box-sizing:border-box;position:relative;flex-shrink:0}.default-theme.splitpanes .splitpanes__splitter:before,.default-theme.splitpanes .splitpanes__splitter:after{content:\"\";position:absolute;top:50%;left:50%;background-color:#00000026;transition:background-color .3s}.default-theme.splitpanes .splitpanes__splitter:hover:before,.default-theme.splitpanes .splitpanes__splitter:hover:after{background-color:#00000040}.default-theme.splitpanes .splitpanes__splitter:first-child{cursor:auto}.default-theme.splitpanes .splitpanes .splitpanes__splitter{z-index:1}.default-theme.splitpanes--vertical>.splitpanes__splitter,.default-theme .splitpanes--vertical>.splitpanes__splitter{width:7px;border-left:1px solid #eee;margin-left:-1px}.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:after{transform:translateY(-50%);width:1px;height:30px}.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:before{margin-left:-2px}.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:after{margin-left:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter,.default-theme .splitpanes--horizontal>.splitpanes__splitter{height:7px;border-top:1px solid #eee;margin-top:-1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after{transform:translate(-50%);width:30px;height:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before{margin-top:-2px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after{margin-top:1px}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color, #e5e7eb)}:before,:after{--un-content: \"\"}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid black;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor .CodeMirror-line::selection,.cm-fat-cursor .CodeMirror-line>span::selection,.cm-fat-cursor .CodeMirror-line>span>span::selection{background:transparent}.cm-fat-cursor .CodeMirror-line::-moz-selection,.cm-fat-cursor .CodeMirror-line>span::-moz-selection,.cm-fat-cursor .CodeMirror-line>span>span::-moz-selection{background:transparent}.cm-fat-cursor{caret-color:transparent}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;inset:-50px 0 0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3,.cm-s-default .cm-type{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error,.cm-invalidchar{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:#ff96004d}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative;z-index:0}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none;outline:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;inset:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:none}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}div.CodeMirror-dragcursors,.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:#ff06}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:\"\"}span.CodeMirror-selectedtext{background:none}:root{--cm-scheme: light;--cm-foreground: #6e6e6e;--cm-background: #f4f4f4;--cm-comment: #a8a8a8;--cm-string: #555555;--cm-literal: #333333;--cm-keyword: #000000;--cm-function: #4f4f4f;--cm-deleted: #333333;--cm-class: #333333;--cm-builtin: #757575;--cm-property: #333333;--cm-namespace: #4f4f4f;--cm-punctuation: #ababab;--cm-decorator: var(--cm-class);--cm-operator: var(--cm-punctuation);--cm-number: var(--cm-literal);--cm-boolean: var(--cm-literal);--cm-variable: var(--cm-literal);--cm-constant: var(--cm-literal);--cm-symbol: var(--cm-literal);--cm-interpolation: var(--cm-literal);--cm-selector: var(--cm-keyword);--cm-keyword-control: var(--cm-keyword);--cm-regex: var(--cm-string);--cm-json-property: var(--cm-property);--cm-inline-background: var(--cm-background);--cm-comment-style: italic;--cm-url-decoration: underline;--cm-line-number: #a5a5a5;--cm-line-number-gutter: #333333;--cm-line-highlight-background: #eeeeee;--cm-selection-background: #aaaaaa;--cm-marker-color: var(--cm-foreground);--cm-marker-opacity: .4;--cm-marker-font-size: .8em;--cm-font-size: 1em;--cm-line-height: 1.5em;--cm-font-family: monospace;--cm-inline-font-size: var(--cm-font-size);--cm-block-font-size: var(--cm-font-size);--cm-tab-size: 2;--cm-block-padding-x: 1em;--cm-block-padding-y: 1em;--cm-block-margin-x: 0;--cm-block-margin-y: .5em;--cm-block-radius: .3em;--cm-inline-padding-x: .3em;--cm-inline-padding-y: .1em;--cm-inline-radius: .3em}.cm-s-vars.CodeMirror{background-color:var(--cm-background);color:var(--cm-foreground)}.cm-s-vars .CodeMirror-gutters{background:var(--cm-line-number-gutter);color:var(--cm-line-number);border:none}.cm-s-vars .CodeMirror-guttermarker,.cm-s-vars .CodeMirror-guttermarker-subtle,.cm-s-vars .CodeMirror-linenumber{color:var(--cm-line-number)}.cm-s-vars div.CodeMirror-selected,.cm-s-vars.CodeMirror-focused div.CodeMirror-selected{background:var(--cm-selection-background)}.cm-s-vars .CodeMirror-line::selection,.cm-s-vars .CodeMirror-line>span::selection,.cm-s-vars .CodeMirror-line>span>span::selection{background:var(--cm-selection-background)}.cm-s-vars .CodeMirror-line::-moz-selection,.cm-s-vars .CodeMirror-line>span::-moz-selection,.cm-s-vars .CodeMirror-line>span>span::-moz-selection{background:var(--cm-selection-background)}.cm-s-vars .CodeMirror-activeline-background{background:var(--cm-line-highlight-background)}.cm-s-vars .cm-keyword{color:var(--cm-keyword)}.cm-s-vars .cm-variable,.cm-s-vars .cm-variable-2,.cm-s-vars .cm-variable-3,.cm-s-vars .cm-type{color:var(--cm-variable)}.cm-s-vars .cm-builtin{color:var(--cm-builtin)}.cm-s-vars .cm-atom{color:var(--cm-literal)}.cm-s-vars .cm-number{color:var(--cm-number)}.cm-s-vars .cm-def{color:var(--cm-decorator)}.cm-s-vars .cm-string,.cm-s-vars .cm-string-2{color:var(--cm-string)}.cm-s-vars .cm-comment{color:var(--cm-comment)}.cm-s-vars .cm-tag{color:var(--cm-builtin)}.cm-s-vars .cm-meta{color:var(--cm-namespace)}.cm-s-vars .cm-attribute,.cm-s-vars .cm-property{color:var(--cm-property)}.cm-s-vars .cm-qualifier{color:var(--cm-keyword)}.cm-s-vars .cm-error{color:var(--prism-deleted)}.cm-s-vars .cm-operator,.cm-s-vars .cm-bracket{color:var(--cm-punctuation)}.cm-s-vars .CodeMirror-matchingbracket{text-decoration:underline}.cm-s-vars .CodeMirror-cursor{border-left:1px solid currentColor}html,body{height:100%;font-family:Readex Pro,sans-serif;scroll-behavior:smooth}:root{--color-text-light: #000;--color-text-dark: #ddd;--color-text: var(--color-text-light);--background-color: #e4e4e4}html.dark{--color-text: var(--color-text-dark);--background-color: #141414;color:var(--color-text);background-color:var(--background-color);color-scheme:dark}.CodeMirror{height:100%!important;width:100%!important;font-family:inherit}.cm-s-vars .cm-tag{color:var(--cm-keyword)}:root{--cm-foreground: #393a3480;--cm-background: transparent;--cm-comment: #a0ada0;--cm-string: #b56959;--cm-literal: #2f8a89;--cm-number: #296aa3;--cm-keyword: #1c6b48;--cm-function: #6c7834;--cm-boolean: #1c6b48;--cm-constant: #a65e2b;--cm-deleted: #a14f55;--cm-class: #2993a3;--cm-builtin: #ab5959;--cm-property: #b58451;--cm-namespace: #b05a78;--cm-punctuation: #8e8f8b;--cm-decorator: #bd8f8f;--cm-regex: #ab5e3f;--cm-json-property: #698c96;--cm-line-number-gutter: #f8f8f8;--cm-ttc-c-thumb: #eee;--cm-ttc-c-track: white}html.dark{--cm-scheme: dark;--cm-foreground: #d4cfbf80;--cm-background: transparent;--cm-comment: #758575;--cm-string: #d48372;--cm-literal: #429988;--cm-keyword: #4d9375;--cm-boolean: #1c6b48;--cm-number: #6394bf;--cm-variable: #c2b36e;--cm-function: #a1b567;--cm-deleted: #a14f55;--cm-class: #54b1bf;--cm-builtin: #e0a569;--cm-property: #dd8e6e;--cm-namespace: #db889a;--cm-punctuation: #858585;--cm-decorator: #bd8f8f;--cm-regex: #ab5e3f;--cm-json-property: #6b8b9e;--cm-line-number: #888888;--cm-line-number-gutter: #161616;--cm-line-highlight-background: #444444;--cm-selection-background: #44444450;--cm-ttc-c-thumb: #222;--cm-ttc-c-track: #111}.splitpanes__pane{background-color:unset!important}.splitpanes__splitter{position:relative;background-color:#7d7d7d1a;z-index:10}.splitpanes__splitter:before{content:\"\";position:absolute;left:0;top:0;transition:opacity .4s;background-color:#7d7d7d1a;opacity:0;z-index:1}.splitpanes__splitter:hover:before{opacity:1}.splitpanes--vertical>.splitpanes__splitter:before{left:0;right:-10px;height:100%}.splitpanes--horizontal>.splitpanes__splitter:before{top:0;bottom:-10px;width:100%}.splitpanes.loading .splitpanes__pane{transition:none!important;height:100%}.CodeMirror-scroll{scrollbar-width:none}.CodeMirror-scroll::-webkit-scrollbar,.codemirror-scrolls::-webkit-scrollbar{display:none}.codemirror-scrolls{overflow:auto!important;scrollbar-width:thin;scrollbar-color:var(--cm-ttc-c-thumb) var(--cm-ttc-c-track)}.CodeMirror-simplescroll-horizontal,.CodeMirror-simplescroll-vertical{background-color:var(--cm-ttc-c-track)!important;border:none!important}.CodeMirror-simplescroll-horizontal div,.CodeMirror-simplescroll-vertical div{background-color:var(--cm-ttc-c-thumb)!important;border:none!important}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:var(--cm-ttc-c-track)!important}.CodeMirror{overflow:unset!important}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar{display:none!important}.CodeMirror-scroll{margin-bottom:unset!important;margin-right:unset!important;padding-bottom:unset!important}.scrolls::-webkit-scrollbar{width:8px;height:8px}.scrolls{overflow:auto!important;scrollbar-width:thin;scrollbar-color:var(--cm-ttc-c-thumb) var(--cm-ttc-c-track)}.scrolls::-webkit-scrollbar-track{background:var(--cm-ttc-c-track)}.scrolls::-webkit-scrollbar-thumb{background-color:var(--cm-ttc-c-thumb);border:2px solid var(--cm-ttc-c-thumb)}.scrolls::-webkit-scrollbar-thumb,.scrolls-rounded::-webkit-scrollbar-track{border-radius:3px}.scrolls::-webkit-scrollbar-corner{background-color:var(--cm-ttc-c-track)}.v-popper__popper .v-popper__inner{font-size:12px;padding:4px 6px;border-radius:4px;background-color:var(--background-color);color:var(--color-text)}.v-popper__popper .v-popper__arrow-outer{border-color:var(--background-color)}.codemirror-busy>.CodeMirror>.CodeMirror-scroll>.CodeMirror-sizer .CodeMirror-lines{cursor:wait!important}.resize-observer[data-v-b329ee4c]{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;border:none;background-color:transparent;pointer-events:none;display:block;overflow:hidden;opacity:0}.resize-observer[data-v-b329ee4c] object{display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1}.v-popper__popper{z-index:10000;top:0;left:0;outline:none}.v-popper__popper.v-popper__popper--hidden{visibility:hidden;opacity:0;transition:opacity .15s,visibility .15s;pointer-events:none}.v-popper__popper.v-popper__popper--shown{visibility:visible;opacity:1;transition:opacity .15s}.v-popper__popper.v-popper__popper--skip-transition,.v-popper__popper.v-popper__popper--skip-transition>.v-popper__wrapper{transition:none!important}.v-popper__backdrop{position:absolute;top:0;left:0;width:100%;height:100%;display:none}.v-popper__inner{position:relative;box-sizing:border-box;overflow-y:auto}.v-popper__inner>div{position:relative;z-index:1;max-width:inherit;max-height:inherit}.v-popper__arrow-container{position:absolute;width:10px;height:10px}.v-popper__popper--arrow-overflow .v-popper__arrow-container,.v-popper__popper--no-positioning .v-popper__arrow-container{display:none}.v-popper__arrow-inner,.v-popper__arrow-outer{border-style:solid;position:absolute;top:0;left:0;width:0;height:0}.v-popper__arrow-inner{visibility:hidden;border-width:7px}.v-popper__arrow-outer{border-width:6px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner{left:-2px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{left:-1px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer{border-bottom-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-container{top:0}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{border-top-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-top-color:transparent!important}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner{top:-4px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{top:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{top:-1px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{border-left-width:0;border-left-color:transparent!important;border-top-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{left:-4px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{left:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-container{right:-10px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer{border-right-width:0;border-top-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner{left:-2px}.v-popper--theme-tooltip .v-popper__inner{background:#000c;color:#fff;border-radius:6px;padding:7px 12px 6px}.v-popper--theme-tooltip .v-popper__arrow-outer{border-color:#000c}.v-popper--theme-dropdown .v-popper__inner{background:#fff;color:#000;border-radius:6px;border:1px solid #ddd;box-shadow:0 6px 30px #0000001a}.v-popper--theme-dropdown .v-popper__arrow-inner{visibility:visible;border-color:#fff}.v-popper--theme-dropdown .v-popper__arrow-outer{border-color:#ddd}*,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }.dark .dark\\:i-carbon-moon{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M13.503 5.414a15.076 15.076 0 0 0 11.593 18.194a11.1 11.1 0 0 1-7.975 3.39c-.138 0-.278.005-.418 0a11.094 11.094 0 0 1-3.2-21.584M14.98 3a1 1 0 0 0-.175.016a13.096 13.096 0 0 0 1.825 25.981c.164.006.328 0 .49 0a13.07 13.07 0 0 0 10.703-5.555a1.01 1.01 0 0 0-.783-1.565A13.08 13.08 0 0 1 15.89 4.38A1.015 1.015 0 0 0 14.98 3'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-arrow-left{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m14 26l1.41-1.41L7.83 17H28v-2H7.83l7.58-7.59L14 6L4 16z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-checkmark,.i-carbon\\:checkmark,[i-carbon-checkmark=\"\"],[i-carbon\\:checkmark=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m13 24l-9-9l1.414-1.414L13 21.171L26.586 7.586L28 9z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-checkmark-outline-error,[i-carbon-checkmark-outline-error=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M14 24a10 10 0 1 1 10-10h2a12 12 0 1 0-12 12Z'/%3E%3Cpath fill='currentColor' d='M12 15.59L9.41 13L8 14.41l4 4l7-7L17.59 10zM30 24a6 6 0 1 0-6 6a6.007 6.007 0 0 0 6-6m-2 0a3.95 3.95 0 0 1-.567 2.019l-5.452-5.452A3.95 3.95 0 0 1 24 20a4.005 4.005 0 0 1 4 4m-8 0a3.95 3.95 0 0 1 .567-2.019l5.452 5.452A3.95 3.95 0 0 1 24 28a4.005 4.005 0 0 1-4-4'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-close,.i-carbon\\:close,[i-carbon-close=\"\"],[i-carbon\\:close=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M17.414 16L24 9.414L22.586 8L16 14.586L9.414 8L8 9.414L14.586 16L8 22.586L9.414 24L16 17.414L22.586 24L24 22.586z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-compare,.i-carbon\\:compare,[i-carbon-compare=\"\"],[i-carbon\\:compare=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M28 6H18V4a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h10v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2M4 15h6.17l-2.58 2.59L9 19l5-5l-5-5l-1.41 1.41L10.17 13H4V4h12v20H4Zm12 13v-2a2 2 0 0 0 2-2V8h10v9h-6.17l2.58-2.59L23 13l-5 5l5 5l1.41-1.41L21.83 19H28v9Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-content-delivery-network{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Ccircle cx='21' cy='21' r='2' fill='currentColor'/%3E%3Ccircle cx='7' cy='7' r='2' fill='currentColor'/%3E%3Cpath fill='currentColor' d='M27 31a4 4 0 1 1 4-4a4.01 4.01 0 0 1-4 4m0-6a2 2 0 1 0 2 2a2.006 2.006 0 0 0-2-2'/%3E%3Cpath fill='currentColor' d='M30 16A14.04 14.04 0 0 0 16 2a13.04 13.04 0 0 0-6.8 1.8l1.1 1.7a24 24 0 0 1 2.4-1A25.1 25.1 0 0 0 10 15H4a11.15 11.15 0 0 1 1.4-4.7L3.9 9A13.84 13.84 0 0 0 2 16a14 14 0 0 0 14 14a13.4 13.4 0 0 0 5.2-1l-.6-1.9a11.44 11.44 0 0 1-5.2.9A21.07 21.07 0 0 1 12 17h17.9a3.4 3.4 0 0 0 .1-1M12.8 27.6a13 13 0 0 1-5.3-3.1A12.5 12.5 0 0 1 4 17h6a25 25 0 0 0 2.8 10.6M12 15a21.45 21.45 0 0 1 3.3-11h1.4A21.45 21.45 0 0 1 20 15Zm10 0a23.3 23.3 0 0 0-2.8-10.6A12.09 12.09 0 0 1 27.9 15Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-dashboard,.i-carbon\\:dashboard{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M24 21h2v5h-2zm-4-5h2v10h-2zm-9 10a5.006 5.006 0 0 1-5-5h2a3 3 0 1 0 3-3v-2a5 5 0 0 1 0 10'/%3E%3Cpath fill='currentColor' d='M28 2H4a2 2 0 0 0-2 2v24a2 2 0 0 0 2 2h24a2.003 2.003 0 0 0 2-2V4a2 2 0 0 0-2-2m0 9H14V4h14ZM12 4v7H4V4ZM4 28V13h24l.002 15Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-document,[i-carbon-document=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m25.7 9.3l-7-7c-.2-.2-.4-.3-.7-.3H8c-1.1 0-2 .9-2 2v24c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V10c0-.3-.1-.5-.3-.7M18 4.4l5.6 5.6H18zM24 28H8V4h8v6c0 1.1.9 2 2 2h6z'/%3E%3Cpath fill='currentColor' d='M10 22h12v2H10zm0-6h12v2H10z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-ibm-cloud-direct-link-2-connect{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M17.2 13c.4 1.2 1.5 2 2.8 2c1.7 0 3-1.3 3-3s-1.3-3-3-3c-1.3 0-2.4.8-2.8 2H5c-1.1 0-2 .9-2 2v6H0v2h3v6c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-4h-2v4H5V13zm2.8-2c.6 0 1 .4 1 1s-.4 1-1 1s-1-.4-1-1s.4-1 1-1'/%3E%3Cpath fill='currentColor' d='M29 11V5c0-1.1-.9-2-2-2H13c-1.1 0-2 .9-2 2v4h2V5h14v14H14.8c-.4-1.2-1.5-2-2.8-2c-1.7 0-3 1.3-3 3s1.3 3 3 3c1.3 0 2.4-.8 2.8-2H27c1.1 0 2-.9 2-2v-6h3v-2zM12 21c-.6 0-1-.4-1-1s.4-1 1-1s1 .4 1 1s-.4 1-1 1'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-launch{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 28H6a2.003 2.003 0 0 1-2-2V6a2.003 2.003 0 0 1 2-2h10v2H6v20h20V16h2v10a2.003 2.003 0 0 1-2 2'/%3E%3Cpath fill='currentColor' d='M20 2v2h6.586L18 12.586L19.414 14L28 5.414V12h2V2z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-notebook{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 10h7v2h-7zm0 5h7v2h-7zm0 5h7v2h-7z'/%3E%3Cpath fill='currentColor' d='M28 5H4a2 2 0 0 0-2 2v18a2 2 0 0 0 2 2h24a2.003 2.003 0 0 0 2-2V7a2 2 0 0 0-2-2M4 7h11v18H4Zm13 18V7h11l.002 18Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-reset{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M18 28A12 12 0 1 0 6 16v6.2l-3.6-3.6L1 20l6 6l6-6l-1.4-1.4L8 22.2V16a10 10 0 1 1 10 10Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-timer,[i-carbon-timer=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M15 11h2v9h-2zm-2-9h6v2h-6z'/%3E%3Cpath fill='currentColor' d='m28 9l-1.42-1.41l-2.25 2.25a10.94 10.94 0 1 0 1.18 1.65ZM16 26a9 9 0 1 1 9-9a9 9 0 0 1-9 9'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-wifi-off{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Ccircle cx='16' cy='25' r='2' fill='currentColor'/%3E%3Cpath fill='currentColor' d='M30 3.414L28.586 2L2 28.586L3.414 30l10.682-10.682a5.94 5.94 0 0 1 6.01 1.32l1.414-1.414a7.97 7.97 0 0 0-5.125-2.204l3.388-3.388a12 12 0 0 1 4.564 2.765l1.413-1.414a14 14 0 0 0-4.426-2.903l2.997-2.997a18 18 0 0 1 4.254 3.075L30 10.743v-.002a20 20 0 0 0-4.19-3.138zm-15.32 9.664l2.042-2.042C16.48 11.023 16.243 11 16 11a13.95 13.95 0 0 0-9.771 3.993l1.414 1.413a11.97 11.97 0 0 1 7.037-3.328M16 7a18 18 0 0 1 4.232.525l1.643-1.642A19.95 19.95 0 0 0 2 10.74v.023l1.404 1.404A17.92 17.92 0 0 1 16 7'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:chart-relationship{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 6a3.996 3.996 0 0 0-3.858 3H17.93A7.996 7.996 0 1 0 9 17.93v4.212a4 4 0 1 0 2 0v-4.211a7.95 7.95 0 0 0 3.898-1.62l3.669 3.67A3.95 3.95 0 0 0 18 22a4 4 0 1 0 4-4a3.95 3.95 0 0 0-2.019.567l-3.67-3.67A7.95 7.95 0 0 0 17.932 11h4.211A3.993 3.993 0 1 0 26 6M12 26a2 2 0 1 1-2-2a2 2 0 0 1 2 2m-2-10a6 6 0 1 1 6-6a6.007 6.007 0 0 1-6 6m14 6a2 2 0 1 1-2-2a2 2 0 0 1 2 2m2-10a2 2 0 1 1 2-2a2 2 0 0 1-2 2'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:checkbox{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2M6 26V6h20v20Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:checkbox-checked-filled{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2M14 21.5l-5-4.957L10.59 15L14 18.346L21.409 11L23 12.577Z'/%3E%3Cpath fill='none' d='m14 21.5l-5-4.957L10.59 15L14 18.346L21.409 11L23 12.577Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:chevron-down{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M16 22L6 12l1.4-1.4l8.6 8.6l8.6-8.6L26 12z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:chevron-right{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M22 16L12 26l-1.4-1.4l8.6-8.6l-8.6-8.6L12 6z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:circle-dash,[i-carbon\\:circle-dash=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M7.7 4.7a14.7 14.7 0 0 0-3 3.1L6.3 9a13.3 13.3 0 0 1 2.6-2.7zm-3.1 7.6l-1.9-.6A12.5 12.5 0 0 0 2 16h2a11.5 11.5 0 0 1 .6-3.7m-1.9 8.1a14.4 14.4 0 0 0 2 3.9l1.6-1.2a12.9 12.9 0 0 1-1.7-3.3zm5.1 6.9a14.4 14.4 0 0 0 3.9 2l.6-1.9A12.9 12.9 0 0 1 9 25.7zm3.9-24.6l.6 1.9A11.5 11.5 0 0 1 16 4V2a12.5 12.5 0 0 0-4.3.7m12.5 24.6a15.2 15.2 0 0 0 3.1-3.1L25.7 23a11.5 11.5 0 0 1-2.7 2.7zm3.2-7.6l1.9.6A15.5 15.5 0 0 0 30 16h-2a11.5 11.5 0 0 1-.6 3.7m1.8-8.1a14.4 14.4 0 0 0-2-3.9l-1.6 1.2a12.9 12.9 0 0 1 1.7 3.3zm-5.1-7a14.4 14.4 0 0 0-3.9-2l-.6 1.9a12.9 12.9 0 0 1 3.3 1.7zm-3.8 24.7l-.6-1.9a11.5 11.5 0 0 1-3.7.6v2a21.4 21.4 0 0 0 4.3-.7'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:code{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m31 16l-7 7l-1.41-1.41L28.17 16l-5.58-5.59L24 9zM1 16l7-7l1.41 1.41L3.83 16l5.58 5.59L8 23zm11.42 9.484L17.64 6l1.932.517L14.352 26z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:code-reference,[i-carbon\\:code-reference=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M4 20v2h4.586L2 28.586L3.414 30L10 23.414V28h2v-8zm26-10l-6-6l-1.414 1.414L27.172 10l-4.586 4.586L24 16zm-16.08 7.484l4.15-15.483l1.932.517l-4.15 15.484zM4 10l6-6l1.414 1.414L6.828 10l4.586 4.586L10 16z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:collapse-all{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M30 15h-2V7H13V5h15a2 2 0 0 1 2 2Z'/%3E%3Cpath fill='currentColor' d='M25 20h-2v-8H8v-2h15a2 2 0 0 1 2 2Z'/%3E%3Cpath fill='currentColor' d='M18 27H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2M4 17v8h14.001L18 17Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:document-blank,[i-carbon\\:document-blank=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m25.7 9.3l-7-7A.9.9 0 0 0 18 2H8a2.006 2.006 0 0 0-2 2v24a2.006 2.006 0 0 0 2 2h16a2.006 2.006 0 0 0 2-2V10a.9.9 0 0 0-.3-.7M18 4.4l5.6 5.6H18ZM24 28H8V4h8v6a2.006 2.006 0 0 0 2 2h6Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:download{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 24v4H6v-4H4v4a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2v-4zm0-10l-1.41-1.41L17 20.17V2h-2v18.17l-7.59-7.58L6 14l10 10z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:expand-all{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 10h14a2.003 2.003 0 0 0 2-2V4a2.003 2.003 0 0 0-2-2H12a2.003 2.003 0 0 0-2 2v1H6V2H4v23a2.003 2.003 0 0 0 2 2h4v1a2.003 2.003 0 0 0 2 2h14a2.003 2.003 0 0 0 2-2v-4a2.003 2.003 0 0 0-2-2H12a2.003 2.003 0 0 0-2 2v1H6v-8h4v1a2.003 2.003 0 0 0 2 2h14a2.003 2.003 0 0 0 2-2v-4a2.003 2.003 0 0 0-2-2H12a2.003 2.003 0 0 0-2 2v1H6V7h4v1a2.003 2.003 0 0 0 2 2m0-6h14l.001 4H12Zm0 20h14l.001 4H12Zm0-10h14l.001 4H12Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:filter{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M18 28h-4a2 2 0 0 1-2-2v-7.59L4.59 11A2 2 0 0 1 4 9.59V6a2 2 0 0 1 2-2h20a2 2 0 0 1 2 2v3.59a2 2 0 0 1-.59 1.41L20 18.41V26a2 2 0 0 1-2 2M6 6v3.59l8 8V26h4v-8.41l8-8V6Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:filter-remove{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M30 11.414L28.586 10L24 14.586L19.414 10L18 11.414L22.586 16L18 20.585L19.415 22L24 17.414L28.587 22L30 20.587L25.414 16z'/%3E%3Cpath fill='currentColor' d='M4 4a2 2 0 0 0-2 2v3.17a2 2 0 0 0 .586 1.415L10 18v8a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-2h-2v2h-4v-8.83l-.586-.585L4 9.171V6h20v2h2V6a2 2 0 0 0-2-2Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:folder-details-reference{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M16 28h7v2h-7zm0-4h14v2H16zm0-4h14v2H16zM4 20v2h4.586L2 28.586L3.414 30L10 23.414V28h2v-8zM28 8H16l-3.414-3.414A2 2 0 0 0 11.172 4H4a2 2 0 0 0-2 2v12h2V6h7.172l3.414 3.414l.586.586H28v8h2v-8a2 2 0 0 0-2-2'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:folder-off{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M28 8h-2.586L30 3.414L28.586 2L2 28.586L3.414 30l2-2H28a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2m0 18H7.414l16-16H28zM4 6h7.172l3.414 3.414l.586.586H18V8h-2l-3.414-3.414A2 2 0 0 0 11.172 4H4a2 2 0 0 0-2 2v18h2z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:image{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 14a3 3 0 1 0-3-3a3 3 0 0 0 3 3m0-4a1 1 0 1 1-1 1a1 1 0 0 1 1-1'/%3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2m0 22H6v-6l5-5l5.59 5.59a2 2 0 0 0 2.82 0L21 19l5 5Zm0-4.83l-3.59-3.59a2 2 0 0 0-2.82 0L18 19.17l-5.59-5.59a2 2 0 0 0-2.82 0L6 17.17V6h20Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:image-reference{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M4 20v2h4.586L2 28.586L3.414 30L10 23.414V28h2v-8zm15-6a3 3 0 1 0-3-3a3 3 0 0 0 3 3m0-4a1 1 0 1 1-1 1a1 1 0 0 1 1-1'/%3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v10h2V6h20v15.17l-3.59-3.59a2 2 0 0 0-2.82 0L18 19.17L11.83 13l-1.414 1.416L14 18l2.59 2.59a2 2 0 0 0 2.82 0L21 19l5 5v2H16v2h10a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:information-square,[i-carbon\\:information-square=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M17 22v-8h-4v2h2v6h-3v2h8v-2zM16 8a1.5 1.5 0 1 0 1.5 1.5A1.5 1.5 0 0 0 16 8'/%3E%3Cpath fill='currentColor' d='M26 28H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h20a2 2 0 0 1 2 2v20a2 2 0 0 1-2 2M6 6v20h20V6Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:intrusion-prevention{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Ccircle cx='22' cy='23.887' r='2' fill='currentColor'/%3E%3Cpath fill='currentColor' d='M29.777 23.479A8.64 8.64 0 0 0 22 18a8.64 8.64 0 0 0-7.777 5.479L14 24l.223.522A8.64 8.64 0 0 0 22 30a8.64 8.64 0 0 0 7.777-5.478L30 24zM22 28a4 4 0 1 1 4-4a4.005 4.005 0 0 1-4 4m3-18H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h21a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2M4 4v4h21V4zm8 24H4v-4h8v-2H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h8z'/%3E%3Cpath fill='currentColor' d='M28 12H7a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h5v-2H7v-4h21v2h2v-2a2 2 0 0 0-2-2'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:mobile{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M22 4H10a2 2 0 0 0-2 2v22a2 2 0 0 0 2 2h12a2.003 2.003 0 0 0 2-2V6a2 2 0 0 0-2-2m0 2v2H10V6ZM10 28V10h12v18Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:mobile-add{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M28 24h-4v-4h-2v4h-4v2h4v4h2v-4h4z'/%3E%3Cpath fill='currentColor' d='M10 28V10h12v7h2V6a2 2 0 0 0-2-2H10a2 2 0 0 0-2 2v22a2 2 0 0 0 2 2h6v-2Zm0-22h12v2H10Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:play{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M7 28a1 1 0 0 1-1-1V5a1 1 0 0 1 1.482-.876l20 11a1 1 0 0 1 0 1.752l-20 11A1 1 0 0 1 7 28M8 6.69v18.62L24.925 16Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:play-filled-alt{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M7 28a1 1 0 0 1-1-1V5a1 1 0 0 1 1.482-.876l20 11a1 1 0 0 1 0 1.752l-20 11A1 1 0 0 1 7 28'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:redo,[i-carbon\\:redo=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 10h12.185l-3.587-3.586L22 5l6 6l-6 6l-1.402-1.415L24.182 12H12a6 6 0 0 0 0 12h8v2h-8a8 8 0 0 1 0-16'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:renew{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 10H6.78A11 11 0 0 1 27 16h2A13 13 0 0 0 6 7.68V4H4v8h8zm8 12h5.22A11 11 0 0 1 5 16H3a13 13 0 0 0 23 8.32V28h2v-8h-8z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:report{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M10 18h8v2h-8zm0-5h12v2H10zm0 10h5v2h-5z'/%3E%3Cpath fill='currentColor' d='M25 5h-3V4a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v1H7a2 2 0 0 0-2 2v21a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2M12 4h8v4h-8Zm13 24H7V7h3v3h12V7h3Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:result-old{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M10 13h2v2h-2zm4 0h8v2h-8zm-4 5h2v2h-2zm0 5h2v2h-2z'/%3E%3Cpath fill='currentColor' d='M7 28V7h3v3h12V7h3v8h2V7a2 2 0 0 0-2-2h-3V4a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v1H7a2 2 0 0 0-2 2v21a2 2 0 0 0 2 2h9v-2Zm5-24h8v4h-8Z'/%3E%3Cpath fill='currentColor' d='M18 19v2.413A6.996 6.996 0 1 1 24 32v-2a5 5 0 1 0-4.576-7H22v2h-6v-6Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:search{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m29 27.586l-7.552-7.552a11.018 11.018 0 1 0-1.414 1.414L27.586 29ZM4 13a9 9 0 1 1 9 9a9.01 9.01 0 0 1-9-9'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:side-panel-close{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M28 4H4c-1.1 0-2 .9-2 2v20c0 1.1.9 2 2 2h24c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2M10 26H4V6h6zm18-11H17.8l3.6-3.6L20 10l-6 6l6 6l1.4-1.4l-3.6-3.6H28v9H12V6h16z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:sun{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M16 12.005a4 4 0 1 1-4 4a4.005 4.005 0 0 1 4-4m0-2a6 6 0 1 0 6 6a6 6 0 0 0-6-6M5.394 6.813L6.81 5.399l3.505 3.506L8.9 10.319zM2 15.005h5v2H2zm3.394 10.193L8.9 21.692l1.414 1.414l-3.505 3.506zM15 25.005h2v5h-2zm6.687-1.9l1.414-1.414l3.506 3.506l-1.414 1.414zm3.313-8.1h5v2h-5zm-3.313-6.101l3.506-3.506l1.414 1.414l-3.506 3.506zM15 2.005h2v5h-2z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:tablet{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 24v2h-6v-2z'/%3E%3Cpath fill='currentColor' d='M25 30H7a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h18a2 2 0 0 1 2 2v24a2.003 2.003 0 0 1-2 2M7 4v24h18V4Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:terminal-3270{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M10 21h6v2h-6z'/%3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2m0 2v4H6V6ZM6 26V12h20v14Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-logos\\:typescript-icon{background:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='%233178C6' d='M20 0h216c11.046 0 20 8.954 20 20v216c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20V20C0 8.954 8.954 0 20 0'/%3E%3Cpath fill='%23FFF' d='M150.518 200.475v27.62q6.738 3.453 15.938 5.179T185.849 235q9.934 0 18.874-1.899t15.678-6.257q6.738-4.359 10.669-11.394q3.93-7.033 3.93-17.391q0-7.51-2.246-13.163a30.8 30.8 0 0 0-6.479-10.055q-4.232-4.402-10.149-7.898t-13.347-6.602q-5.442-2.245-9.761-4.359t-7.342-4.316q-3.024-2.2-4.665-4.661t-1.641-5.567q0-2.848 1.468-5.135q1.469-2.288 4.147-3.927t6.565-2.547q3.887-.906 8.638-.906q3.456 0 7.299.518q3.844.517 7.732 1.597a54 54 0 0 1 7.558 2.719a41.7 41.7 0 0 1 6.781 3.797v-25.807q-6.306-2.417-13.778-3.582T198.633 107q-9.847 0-18.658 2.115q-8.811 2.114-15.506 6.602q-6.694 4.49-10.582 11.437Q150 134.102 150 143.769q0 12.342 7.127 21.06t21.638 14.759a292 292 0 0 1 10.625 4.575q4.924 2.244 8.509 4.66t5.658 5.265t2.073 6.474a9.9 9.9 0 0 1-1.296 4.963q-1.295 2.287-3.93 3.97t-6.565 2.632t-9.2.95q-8.983 0-17.794-3.151t-16.327-9.451m-46.036-68.733H140V109H41v22.742h35.345V233h28.137z'/%3E%3C/svg%3E\") no-repeat;background-size:100% 100%;background-color:transparent;width:1em;height:1em}.container{width:100%}.tab-button,[tab-button=\"\"]{height:100%;padding-left:1rem;padding-right:1rem;font-weight:300;opacity:.5}.border-base,[border~=base]{border-color:#6b72801a}.bg-active{background-color:#6b728014}.bg-base,[bg-base=\"\"]{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity))}.dark .bg-base,.dark [bg-base=\"\"]{--un-bg-opacity:1;background-color:rgb(17 17 17 / var(--un-bg-opacity))}.bg-header,[bg-header=\"\"]{background-color:#6b72800d}.bg-overlay,[bg-overlay=\"\"],[bg~=overlay]{background-color:#eeeeee80}.dark .bg-overlay,.dark [bg-overlay=\"\"],.dark [bg~=overlay]{background-color:#22222280}.dark .highlight{--un-bg-opacity:1;background-color:rgb(50 50 56 / var(--un-bg-opacity));--un-text-opacity:1;color:rgb(234 179 6 / var(--un-text-opacity))}.highlight{--un-bg-opacity:1;background-color:rgb(234 179 6 / var(--un-bg-opacity));--un-text-opacity:1;color:rgb(50 50 56 / var(--un-text-opacity))}.tab-button-active{background-color:#6b72801a;opacity:1}[hover~=bg-active]:hover{background-color:#6b728014}.tab-button:hover,[tab-button=\"\"]:hover{opacity:.8}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.\\[clip-path\\:polygon\\(0\\%_0\\%\\,var\\(--split\\)_0\\%\\,var\\(--split\\)_100\\%\\,0\\%_100\\%\\)\\]{clip-path:polygon(0% 0%,var(--split) 0%,var(--split) 100%,0% 100%)}.\\[clip-path\\:polygon\\(var\\(--split\\)_0\\%\\,100\\%_0\\%\\,100\\%_100\\%\\,var\\(--split\\)_100\\%\\)\\]{clip-path:polygon(var(--split) 0%,100% 0%,100% 100%,var(--split) 100%)}.sr-only,[sr-only=\"\"]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none,[pointer-events-none=\"\"]{pointer-events:none}.absolute,[absolute=\"\"]{position:absolute}.fixed,[fixed=\"\"]{position:fixed}.relative,[relative=\"\"]{position:relative}.sticky,[sticky=\"\"]{position:sticky}.before\\:absolute:before{position:absolute}.static{position:static}.inset-0,[inset-0=\"\"]{inset:0}.bottom-0{bottom:0}.left-\\[--split\\]{left:var(--split)}.left-0{left:0}.right-0,[right~=\"0\"]{right:0}.right-5px,[right-5px=\"\"]{right:5px}.top-0{top:0}.top-5px,[top-5px=\"\"]{top:5px}[top~=\"-1\"]{top:-.25rem}.before\\:top-1\\/2:before{top:50%}.z-10,[z-10=\"\"]{z-index:10}.z-40{z-index:40}.z-5,[z-5=\"\"]{z-index:5}.grid,[grid~=\"~\"]{display:grid}.grid-col-span-2{grid-column:span 2/span 2}.grid-col-span-4,[grid-col-span-4=\"\"],[grid-col-span-4~=\"~\"]{grid-column:span 4/span 4}[grid-col-span-4~=\"placeholder:\"]::placeholder{grid-column:span 4/span 4}.auto-cols-max,[grid~=auto-cols-max]{grid-auto-columns:max-content}.cols-\\[1\\.5em_1fr\\],[grid~=\"cols-[1.5em_1fr]\"]{grid-template-columns:1.5em 1fr}.cols-\\[auto_min-content_auto\\],[grid~=\"cols-[auto_min-content_auto]\"]{grid-template-columns:auto min-content auto}.cols-\\[min-content_1fr_min-content\\],[grid~=\"cols-[min-content_1fr_min-content]\"]{grid-template-columns:min-content 1fr min-content}.rows-\\[auto_auto\\],[grid~=\"rows-[auto_auto]\"]{grid-template-rows:auto auto}.rows-\\[min-content_auto\\],[grid~=\"rows-[min-content_auto]\"]{grid-template-rows:min-content auto}.rows-\\[min-content_min-content\\],[grid~=\"rows-[min-content_min-content]\"]{grid-template-rows:min-content min-content}.rows-\\[min-content\\],[grid~=\"rows-[min-content]\"]{grid-template-rows:min-content}.cols-1,.grid-cols-1,[grid~=cols-1]{grid-template-columns:repeat(1,minmax(0,1fr))}.cols-2,.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.rows-1,[grid~=rows-1]{grid-template-rows:repeat(1,minmax(0,1fr))}.m-0{margin:0}.m-2,[m-2=\"\"]{margin:.5rem}.ma,[ma=\"\"]{margin:auto}.mx-1,[mx-1=\"\"]{margin-left:.25rem;margin-right:.25rem}.mx-2,[m~=x-2],[mx-2=\"\"]{margin-left:.5rem;margin-right:.5rem}.mx-4,[mx-4=\"\"]{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0,[my-0=\"\"]{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2,[my-2=\"\"]{margin-top:.5rem;margin-bottom:.5rem}[m~=y-4]{margin-top:1rem;margin-bottom:1rem}.-mt-5{margin-top:-1.25rem}.\\!mb-none{margin-bottom:0!important}.mb-1,[mb-1=\"\"]{margin-bottom:.25rem}.mb-1px{margin-bottom:1px}.mb-2,[mb-2=\"\"]{margin-bottom:.5rem}.mb-5{margin-bottom:1.25rem}.ml-1,[ml-1=\"\"]{margin-left:.25rem}.ml-2,[ml-2=\"\"]{margin-left:.5rem}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-8,[mr-8=\"\"]{margin-right:2rem}.ms,[ms=\"\"]{margin-inline-start:1rem}.ms-2,[ms-2=\"\"]{margin-inline-start:.5rem}.mt-\\[8px\\]{margin-top:8px}.mt-2,[m~=t2],[mt-2=\"\"]{margin-top:.5rem}.mt-3{margin-top:.75rem}.inline,[inline=\"\"]{display:inline}.block,[block=\"\"]{display:block}.inline-block{display:inline-block}.hidden{display:none}.before\\:size-\\[16px\\]:before{width:16px;height:16px}.h-1\\.4em,[h-1\\.4em=\"\"]{height:1.4em}.h-1\\.5em{height:1.5em}.h-10,[h-10=\"\"]{height:2.5rem}.h-1px,[h-1px=\"\"]{height:1px}.h-28px,[h-28px=\"\"]{height:28px}.h-3px,[h-3px=\"\"]{height:3px}.h-41px,[h-41px=\"\"]{height:41px}.h-6,[h-6=\"\"]{height:1.5rem}.h-8,[h-8=\"\"]{height:2rem}.h-full,[h-full=\"\"],[h~=full]{height:100%}.h-screen,[h-screen=\"\"]{height:100vh}.h1{height:.25rem}.h3{height:.75rem}.h4{height:1rem}.max-h-120{max-height:30rem}.max-h-full,[max-h-full=\"\"]{max-height:100%}.max-w-full{max-width:100%}.max-w-screen,[max-w-screen=\"\"]{max-width:100vw}.max-w-xl,[max-w-xl=\"\"]{max-width:36rem}.min-h-1em{min-height:1em}.min-h-75,[min-h-75=\"\"]{min-height:18.75rem}.min-w-1em{min-width:1em}.min-w-2em,[min-w-2em=\"\"]{min-width:2em}.w-\\[2px\\],.w-2px,[w-2px=\"\"]{width:2px}.w-1\\.4em,[w-1\\.4em=\"\"]{width:1.4em}.w-1\\.5em,[w-1\\.5em=\"\"]{width:1.5em}.w-350,[w-350=\"\"]{width:87.5rem}.w-4,[w-4=\"\"]{width:1rem}.w-6,[w-6=\"\"]{width:1.5rem}.w-80,[w-80=\"\"]{width:20rem}.w-fit{width:fit-content}.w-full,[w-full=\"\"]{width:100%}.w-min{width:min-content}.w-screen,[w-screen=\"\"]{width:100vw}.open\\:max-h-52[open],[open\\:max-h-52=\"\"][open]{max-height:13rem}.flex,[flex=\"\"],[flex~=\"~\"]{display:flex}.flex-inline,.inline-flex,[inline-flex=\"\"]{display:inline-flex}.flex-1,[flex-1=\"\"]{flex:1 1 0%}.flex-auto,[flex-auto=\"\"]{flex:1 1 auto}.flex-shrink-0,[flex-shrink-0=\"\"]{flex-shrink:0}.flex-grow-1,[flex-grow-1=\"\"]{flex-grow:1}.flex-col,[flex-col=\"\"],[flex~=col]{flex-direction:column}[flex~=wrap]{flex-wrap:wrap}.table{display:table}.origin-center,[origin-center=\"\"]{transform-origin:center}.origin-top{transform-origin:top}.-translate-x-1\\/2{--un-translate-x:-50%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.translate-x-3,[translate-x-3=\"\"]{--un-translate-x:.75rem;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.before\\:-translate-y-1\\/2:before{--un-translate-y:-50%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.before\\:translate-x-\\[calc\\(-50\\%\\+1px\\)\\]:before{--un-translate-x: calc(-50% + 1px) ;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.rotate-0,[rotate-0=\"\"]{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:0deg;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.rotate-180,[rotate-180=\"\"]{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:180deg;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.rotate-90,[rotate-90=\"\"]{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:90deg;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.transform{transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.animate-spin,[animate-spin=\"\"]{animation:spin 1s linear infinite}.animate-reverse{animation-direction:reverse}.animate-count-1,[animate-count-1=\"\"]{animation-iteration-count:1}.cursor-help,[cursor-help=\"\"]{cursor:help}.cursor-pointer,[cursor-pointer=\"\"],.hover\\:cursor-pointer:hover{cursor:pointer}.cursor-col-resize{cursor:col-resize}.select-none,[select-none=\"\"]{-webkit-user-select:none;user-select:none}.resize{resize:both}.place-content-center{place-content:center}.place-items-center{place-items:center}.items-end,[items-end=\"\"]{align-items:flex-end}.items-center,[flex~=items-center],[grid~=items-center],[items-center=\"\"]{align-items:center}.justify-end,[justify-end=\"\"]{justify-content:flex-end}.justify-center,[justify-center=\"\"]{justify-content:center}.justify-between,[flex~=justify-between],[justify-between=\"\"]{justify-content:space-between}.justify-evenly,[justify-evenly=\"\"]{justify-content:space-evenly}.justify-items-center,[justify-items-center=\"\"]{justify-items:center}.gap-0,[gap-0=\"\"]{gap:0}.gap-1,[flex~=gap-1],[gap-1=\"\"]{gap:.25rem}.gap-2,[flex~=gap-2],[gap-2=\"\"]{gap:.5rem}.gap-4,[flex~=gap-4]{gap:1rem}.gap-6{gap:1.5rem}.gap-x-1,[grid~=gap-x-1]{column-gap:.25rem}.gap-x-2,[gap-x-2=\"\"],[gap~=x-2],[grid~=gap-x-2]{column-gap:.5rem}.gap-y-1{row-gap:.25rem}[gap~=y-3]{row-gap:.75rem}.overflow-auto,[overflow-auto=\"\"]{overflow:auto}.overflow-hidden,[overflow-hidden=\"\"],[overflow~=hidden]{overflow:hidden}.truncate,[truncate=\"\"]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre,[whitespace-pre=\"\"]{white-space:pre}.ws-nowrap,[ws-nowrap=\"\"]{white-space:nowrap}.b,.border,[border~=\"~\"]{border-width:1px}.b-2,[b-2=\"\"]{border-width:2px}.before\\:border-\\[2px\\]:before{border-width:2px}.border-b,.border-b-1,[border~=b]{border-bottom-width:1px}.border-b-2,[border-b-2=\"\"],[border~=b-2]{border-bottom-width:2px}.border-l,[border~=l]{border-left-width:1px}.border-l-2px{border-left-width:2px}.border-r,.border-r-1px,[border~=r]{border-right-width:1px}.border-t,[border~=t]{border-top-width:1px}.dark [border~=\"dark:gray-400\"]{--un-border-opacity:1;border-color:rgb(156 163 175 / var(--un-border-opacity))}[border~=\"$cm-namespace\"]{border-color:var(--cm-namespace)}[border~=\"gray-400/50\"]{border-color:#9ca3af80}[border~=gray-500]{--un-border-opacity:1;border-color:rgb(107 114 128 / var(--un-border-opacity))}[border~=red-500]{--un-border-opacity:1;border-color:rgb(239 68 68 / var(--un-border-opacity))}.before\\:border-black:before{--un-border-opacity:1;border-color:rgb(0 0 0 / var(--un-border-opacity))}.border-rounded,.rounded,.rounded-1,[border-rounded=\"\"],[border~=rounded],[rounded-1=\"\"],[rounded=\"\"]{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-xl{border-radius:.75rem}.before\\:rounded-full:before{border-radius:9999px}[border~=dotted]{border-style:dotted}[border~=solid]{border-style:solid}.\\!bg-gray-4{--un-bg-opacity:1 !important;background-color:rgb(156 163 175 / var(--un-bg-opacity))!important}.bg-\\[\\#eee\\]{--un-bg-opacity:1;background-color:rgb(238 238 238 / var(--un-bg-opacity))}.bg-\\[\\#fafafa\\]{--un-bg-opacity:1;background-color:rgb(250 250 250 / var(--un-bg-opacity))}.bg-\\[size\\:16px_16px\\]{background-size:16px 16px}.bg-current,[bg-current=\"\"]{background-color:currentColor}.bg-gray{--un-bg-opacity:1;background-color:rgb(156 163 175 / var(--un-bg-opacity))}.bg-gray-500\\:35{background-color:#6b728059}.bg-green5,[bg-green5=\"\"]{--un-bg-opacity:1;background-color:rgb(34 197 94 / var(--un-bg-opacity))}.bg-indigo\\/60{background-color:#818cf899}.bg-orange{--un-bg-opacity:1;background-color:rgb(251 146 60 / var(--un-bg-opacity))}.bg-red{--un-bg-opacity:1;background-color:rgb(248 113 113 / var(--un-bg-opacity))}.bg-red-500\\/10,[bg~=\"red-500/10\"],[bg~=\"red500/10\"]{background-color:#ef44441a}.bg-red5,[bg-red5=\"\"]{--un-bg-opacity:1;background-color:rgb(239 68 68 / var(--un-bg-opacity))}.bg-white,[bg-white=\"\"]{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity))}.bg-yellow5,[bg-yellow5=\"\"]{--un-bg-opacity:1;background-color:rgb(234 179 8 / var(--un-bg-opacity))}.dark .\\!dark\\:bg-gray-7{--un-bg-opacity:1 !important;background-color:rgb(55 65 81 / var(--un-bg-opacity))!important}.dark .dark\\:bg-\\[\\#222\\]{--un-bg-opacity:1;background-color:rgb(34 34 34 / var(--un-bg-opacity))}.dark .dark\\:bg-\\[\\#3a3a3a\\]{--un-bg-opacity:1;background-color:rgb(58 58 58 / var(--un-bg-opacity))}.dark [bg~=\"dark:#111\"]{--un-bg-opacity:1;background-color:rgb(17 17 17 / var(--un-bg-opacity))}[bg~=gray-200]{--un-bg-opacity:1;background-color:rgb(229 231 235 / var(--un-bg-opacity))}[bg~=\"gray/10\"]{background-color:#9ca3af1a}[bg~=\"gray/30\"]{background-color:#9ca3af4d}[bg~=\"green-500/10\"]{background-color:#22c55e1a}[bg~=transparent]{background-color:transparent}[bg~=\"yellow-500/10\"]{background-color:#eab3081a}.before\\:bg-white:before{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity))}.bg-center{background-position:center}[fill-opacity~=\".05\"]{--un-fill-opacity:.0005}.p-0,[p-0=\"\"]{padding:0}.p-0\\.5,[p-0\\.5=\"\"]{padding:.125rem}.p-1,[p-1=\"\"]{padding:.25rem}.p-2,.p2,[p-2=\"\"],[p~=\"2\"],[p2=\"\"]{padding:.5rem}.p-4,[p-4=\"\"]{padding:1rem}.p-5,[p-5=\"\"]{padding:1.25rem}.p6,[p6=\"\"]{padding:1.5rem}[p~=\"3\"]{padding:.75rem}.p-y-1,.py-1,[p~=y-1],[p~=y1],[py-1=\"\"]{padding-top:.25rem;padding-bottom:.25rem}.px,[p~=x-4],[p~=x4]{padding-left:1rem;padding-right:1rem}.px-0{padding-left:0;padding-right:0}.px-2,[p~=x-2],[p~=x2]{padding-left:.5rem;padding-right:.5rem}.px-3,[p~=x3],[px-3=\"\"]{padding-left:.75rem;padding-right:.75rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py,[p~=y4]{padding-top:1rem;padding-bottom:1rem}.py-0\\.5,[p~=\"y0.5\"]{padding-top:.125rem;padding-bottom:.125rem}.py-2,[p~=y2],[py-2=\"\"]{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pb-2,[pb-2=\"\"]{padding-bottom:.5rem}.pe-2\\.5,[pe-2\\.5=\"\"]{padding-inline-end:.625rem}.pl-1,[pl-1=\"\"]{padding-left:.25rem}.pr-2,[p~=r2],[pr-2=\"\"]{padding-right:.5rem}.pt{padding-top:1rem}.pt-4px{padding-top:4px}[p~=l3]{padding-left:.75rem}.text-center,[text-center=\"\"],[text~=center]{text-align:center}.indent,[indent=\"\"]{text-indent:1.5rem}.text-2xl,[text-2xl=\"\"]{font-size:1.5rem;line-height:2rem}.text-4xl,[text-4xl=\"\"]{font-size:2.25rem;line-height:2.5rem}.text-lg,[text-lg=\"\"]{font-size:1.125rem;line-height:1.75rem}.text-sm,[text-sm=\"\"],[text~=sm]{font-size:.875rem;line-height:1.25rem}.text-xs,[text-xs=\"\"],[text~=xs]{font-size:.75rem;line-height:1rem}[text~=\"5xl\"]{font-size:3rem;line-height:1}.dark .dark\\:text-red-300{--un-text-opacity:1;color:rgb(252 165 165 / var(--un-text-opacity))}.dark .dark\\:text-white,.text-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity))}.text-\\[\\#add467\\]{--un-text-opacity:1;color:rgb(173 212 103 / var(--un-text-opacity))}.text-black{--un-text-opacity:1;color:rgb(0 0 0 / var(--un-text-opacity))}.text-gray-5,.text-gray-500,[text-gray-500=\"\"]{--un-text-opacity:1;color:rgb(107 114 128 / var(--un-text-opacity))}.text-green-500,.text-green5,[text-green-500=\"\"],[text-green5=\"\"],[text~=green-500]{--un-text-opacity:1;color:rgb(34 197 94 / var(--un-text-opacity))}.text-orange{--un-text-opacity:1;color:rgb(251 146 60 / var(--un-text-opacity))}.text-purple5\\:50{color:#a855f780}.dark .dark\\:c-red-400,.text-red{--un-text-opacity:1;color:rgb(248 113 113 / var(--un-text-opacity))}.color-red5,.text-red-500,.text-red5,[text-red-500=\"\"],[text-red5=\"\"],[text~=red-500],[text~=red500]{--un-text-opacity:1;color:rgb(239 68 68 / var(--un-text-opacity))}.c-red-600,.text-red-600{--un-text-opacity:1;color:rgb(220 38 38 / var(--un-text-opacity))}.text-yellow-500,.text-yellow5,[text-yellow-500=\"\"],[text-yellow5=\"\"],[text~=yellow-500]{--un-text-opacity:1;color:rgb(234 179 8 / var(--un-text-opacity))}.text-yellow-500\\/80{color:#eab308cc}[text~=\"red500/70\"]{color:#ef4444b3}.dark .dark\\:color-\\#f43f5e{--un-text-opacity:1;color:rgb(244 63 94 / var(--un-text-opacity))}.font-bold,[font-bold=\"\"]{font-weight:700}.font-light,[font-light=\"\"],[font~=light]{font-weight:300}.font-thin,[font-thin=\"\"]{font-weight:100}.font-mono,[font-mono=\"\"]{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}.capitalize,[capitalize=\"\"]{text-transform:capitalize}.aria-\\[selected\\=true\\]\\:underline[aria-selected=true],.underline,.hover\\:underline:hover{text-decoration-line:underline}.decoration-gray{-webkit-text-decoration-color:rgb(156 163 175 / var(--un-line-opacity));--un-line-opacity:1;text-decoration-color:rgb(156 163 175 / var(--un-line-opacity))}.decoration-red{-webkit-text-decoration-color:rgb(248 113 113 / var(--un-line-opacity));--un-line-opacity:1;text-decoration-color:rgb(248 113 113 / var(--un-line-opacity))}.underline-offset-4{text-underline-offset:4px}.tab,[tab=\"\"]{-moz-tab-size:4;-o-tab-size:4;tab-size:4}.\\!op-100{opacity:1!important}.dark .dark\\:op85{opacity:.85}.dark [dark~=op75],.op75{opacity:.75}.op-50,.op50,.opacity-50,[op-50=\"\"],[op~=\"50\"],[op50=\"\"]{opacity:.5}.op-70,.op70,[op-70=\"\"],[opacity~=\"70\"]{opacity:.7}.op-90,[op-90=\"\"]{opacity:.9}.op100,[op~=\"100\"],[op100=\"\"]{opacity:1}.op20,[op20=\"\"]{opacity:.2}.op30,[op30=\"\"]{opacity:.3}.op65,[op65=\"\"]{opacity:.65}.op80,[op80=\"\"]{opacity:.8}.opacity-0{opacity:0}.opacity-60,[opacity-60=\"\"]{opacity:.6}[opacity~=\"10\"]{opacity:.1}[hover\\:op100~=\"default:\"]:hover:default{opacity:1}.hover\\:op100:hover,[hover\\:op100~=\"~\"]:hover,[hover~=op100]:hover{opacity:1}[hover~=op80]:hover{opacity:.8}[op~=\"hover:100\"]:hover{opacity:1}[hover\\:op100~=\"disabled:\"]:hover:disabled{opacity:1}.shadow-\\[0_0_3px_rgb\\(0_0_0\\/\\.2\\)\\,0_0_10px_rgb\\(0_0_0\\/\\.5\\)\\]{--un-shadow:0 0 3px rgb(0 0 0/.2),0 0 10px rgb(0 0 0/.5);box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.outline-0{outline-width:0px}.focus-within\\:has-focus-visible\\:outline-2:has(:focus-visible):focus-within{outline-width:2px}.dark .dark\\:outline-white{--un-outline-color-opacity:1;outline-color:rgb(255 255 255 / var(--un-outline-color-opacity))}.outline-black{--un-outline-color-opacity:1;outline-color:rgb(0 0 0 / var(--un-outline-color-opacity))}.outline-offset-4{outline-offset:4px}.outline,.outline-solid{outline-style:solid}[outline~=none]{outline:2px solid transparent;outline-offset:2px}.backdrop-blur-sm,[backdrop-blur-sm=\"\"]{--un-backdrop-blur:blur(4px);-webkit-backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia)}.backdrop-saturate-0,[backdrop-saturate-0=\"\"]{--un-backdrop-saturate:saturate(0);-webkit-backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia)}.filter,[filter=\"\"]{filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-500{transition-duration:.5s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.before\\:content-\\[\\'\\'\\]:before{content:\"\"}@media (min-width: 768px){.md\\:grid-cols-\\[200px_1fr\\]{grid-template-columns:200px 1fr}}\n"
  },
  {
    "path": "test/cli/test/fixtures/reporters/html/all-passing-or-skipped/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"./favicon.ico\" sizes=\"48x48\">\n    <link rel=\"icon\" href=\"./favicon.svg\" sizes=\"any\" type=\"image/svg+xml\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vitest</title>\n    <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n    <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n    <link\n      href=\"https://fonts.googleapis.com/css2?family=Readex+Pro:wght@300;400&display=swap\"\n      rel=\"stylesheet\"\n    />\n    <script>\n      (function () {\n        const prefersDark =\n          window.matchMedia &&\n          window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n        const setting = localStorage.getItem(\"vueuse-color-scheme\") || \"auto\";\n        if (setting === \"dark\" || (prefersDark && setting !== \"light\"))\n          document.documentElement.classList.toggle(\"dark\", true);\n      })();\n    </script>\n    <script>window.METADATA_PATH=\"html.meta.json.gz\"</script>\n    <script type=\"module\" src=\"./assets/index-BUCFJtth.js\"></script>\n    <link rel=\"stylesheet\" href=\"./assets/index-DlhE0rqZ.css\">\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "test/cli/test/fixtures/reporters/html/fail/assets/index-BUCFJtth.js",
    "content": "(function(){const t=document.createElement(\"link\").relList;if(t&&t.supports&&t.supports(\"modulepreload\"))return;for(const s of document.querySelectorAll('link[rel=\"modulepreload\"]'))o(s);new MutationObserver(s=>{for(const c of s)if(c.type===\"childList\")for(const f of c.addedNodes)f.tagName===\"LINK\"&&f.rel===\"modulepreload\"&&o(f)}).observe(document,{childList:!0,subtree:!0});function r(s){const c={};return s.integrity&&(c.integrity=s.integrity),s.referrerPolicy&&(c.referrerPolicy=s.referrerPolicy),s.crossOrigin===\"use-credentials\"?c.credentials=\"include\":s.crossOrigin===\"anonymous\"?c.credentials=\"omit\":c.credentials=\"same-origin\",c}function o(s){if(s.ep)return;s.ep=!0;const c=r(s);fetch(s.href,c)}})();/**\n* @vue/shared v3.5.25\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/function Fh(e){const t=Object.create(null);for(const r of e.split(\",\"))t[r]=1;return r=>r in t}const vt={},Rs=[],Xr=()=>{},C0=()=>!1,$u=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Hh=e=>e.startsWith(\"onUpdate:\"),on=Object.assign,Bh=(e,t)=>{const r=e.indexOf(t);r>-1&&e.splice(r,1)},$S=Object.prototype.hasOwnProperty,wt=(e,t)=>$S.call(e,t),Ze=Array.isArray,$s=e=>Oa(e)===\"[object Map]\",Iu=e=>Oa(e)===\"[object Set]\",Bm=e=>Oa(e)===\"[object Date]\",et=e=>typeof e==\"function\",Ht=e=>typeof e==\"string\",Pr=e=>typeof e==\"symbol\",kt=e=>e!==null&&typeof e==\"object\",E0=e=>(kt(e)||et(e))&&et(e.then)&&et(e.catch),A0=Object.prototype.toString,Oa=e=>A0.call(e),IS=e=>Oa(e).slice(8,-1),L0=e=>Oa(e)===\"[object Object]\",Du=e=>Ht(e)&&e!==\"NaN\"&&e[0]!==\"-\"&&\"\"+parseInt(e,10)===e,Xl=Fh(\",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted\"),zu=e=>{const t=Object.create(null);return(r=>t[r]||(t[r]=e(r)))},DS=/-\\w/g,sr=zu(e=>e.replace(DS,t=>t.slice(1).toUpperCase())),zS=/\\B([A-Z])/g,Ai=zu(e=>e.replace(zS,\"-$1\").toLowerCase()),Fu=zu(e=>e.charAt(0).toUpperCase()+e.slice(1)),qc=zu(e=>e?`on${Fu(e)}`:\"\"),Gn=(e,t)=>!Object.is(e,t),jc=(e,...t)=>{for(let r=0;r<e.length;r++)e[r](...t)},M0=(e,t,r,o=!1)=>{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:o,value:r})},Wh=e=>{const t=parseFloat(e);return isNaN(t)?e:t},N0=e=>{const t=Ht(e)?Number(e):NaN;return isNaN(t)?e:t};let Wm;const Hu=()=>Wm||(Wm=typeof globalThis<\"u\"?globalThis:typeof self<\"u\"?self:typeof window<\"u\"?window:typeof global<\"u\"?global:{});function zt(e){if(Ze(e)){const t={};for(let r=0;r<e.length;r++){const o=e[r],s=Ht(o)?WS(o):zt(o);if(s)for(const c in s)t[c]=s[c]}return t}else if(Ht(e)||kt(e))return e}const FS=/;(?![^(]*\\))/g,HS=/:([^]+)/,BS=/\\/\\*[^]*?\\*\\//g;function WS(e){const t={};return e.replace(BS,\"\").split(FS).forEach(r=>{if(r){const o=r.split(HS);o.length>1&&(t[o[0].trim()]=o[1].trim())}}),t}function ot(e){let t=\"\";if(Ht(e))t=e;else if(Ze(e))for(let r=0;r<e.length;r++){const o=ot(e[r]);o&&(t+=o+\" \")}else if(kt(e))for(const r in e)e[r]&&(t+=r+\" \");return t.trim()}function qS(e){if(!e)return null;let{class:t,style:r}=e;return t&&!Ht(t)&&(e.class=ot(t)),r&&(e.style=zt(r)),e}const jS=\"itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly\",US=Fh(jS);function O0(e){return!!e||e===\"\"}function VS(e,t){if(e.length!==t.length)return!1;let r=!0;for(let o=0;r&&o<e.length;o++)r=Bu(e[o],t[o]);return r}function Bu(e,t){if(e===t)return!0;let r=Bm(e),o=Bm(t);if(r||o)return r&&o?e.getTime()===t.getTime():!1;if(r=Pr(e),o=Pr(t),r||o)return e===t;if(r=Ze(e),o=Ze(t),r||o)return r&&o?VS(e,t):!1;if(r=kt(e),o=kt(t),r||o){if(!r||!o)return!1;const s=Object.keys(e).length,c=Object.keys(t).length;if(s!==c)return!1;for(const f in e){const d=e.hasOwnProperty(f),h=t.hasOwnProperty(f);if(d&&!h||!d&&h||!Bu(e[f],t[f]))return!1}}return String(e)===String(t)}function P0(e,t){return e.findIndex(r=>Bu(r,t))}const R0=e=>!!(e&&e.__v_isRef===!0),Re=e=>Ht(e)?e:e==null?\"\":Ze(e)||kt(e)&&(e.toString===A0||!et(e.toString))?R0(e)?Re(e.value):JSON.stringify(e,$0,2):String(e),$0=(e,t)=>R0(t)?$0(e,t.value):$s(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((r,[o,s],c)=>(r[fd(o,c)+\" =>\"]=s,r),{})}:Iu(t)?{[`Set(${t.size})`]:[...t.values()].map(r=>fd(r))}:Pr(t)?fd(t):kt(t)&&!Ze(t)&&!L0(t)?String(t):t,fd=(e,t=\"\")=>{var r;return Pr(e)?`Symbol(${(r=e.description)!=null?r:t})`:e};/**\n* @vue/reactivity v3.5.25\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/let bn;class GS{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=bn,!t&&bn&&(this.index=(bn.scopes||(bn.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,r;if(this.scopes)for(t=0,r=this.scopes.length;t<r;t++)this.scopes[t].pause();for(t=0,r=this.effects.length;t<r;t++)this.effects[t].pause()}}resume(){if(this._active&&this._isPaused){this._isPaused=!1;let t,r;if(this.scopes)for(t=0,r=this.scopes.length;t<r;t++)this.scopes[t].resume();for(t=0,r=this.effects.length;t<r;t++)this.effects[t].resume()}}run(t){if(this._active){const r=bn;try{return bn=this,t()}finally{bn=r}}}on(){++this._on===1&&(this.prevScope=bn,bn=this)}off(){this._on>0&&--this._on===0&&(bn=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let r,o;for(r=0,o=this.effects.length;r<o;r++)this.effects[r].stop();for(this.effects.length=0,r=0,o=this.cleanups.length;r<o;r++)this.cleanups[r]();if(this.cleanups.length=0,this.scopes){for(r=0,o=this.scopes.length;r<o;r++)this.scopes[r].stop(!0);this.scopes.length=0}if(!this.detached&&this.parent&&!t){const s=this.parent.scopes.pop();s&&s!==this&&(this.parent.scopes[this.index]=s,s.index=this.index)}this.parent=void 0}}}function I0(){return bn}function KS(e,t=!1){bn&&bn.cleanups.push(e)}let Tt;const dd=new WeakSet;class D0{constructor(t){this.fn=t,this.deps=void 0,this.depsTail=void 0,this.flags=5,this.next=void 0,this.cleanup=void 0,this.scheduler=void 0,bn&&bn.active&&bn.effects.push(this)}pause(){this.flags|=64}resume(){this.flags&64&&(this.flags&=-65,dd.has(this)&&(dd.delete(this),this.trigger()))}notify(){this.flags&2&&!(this.flags&32)||this.flags&8||F0(this)}run(){if(!(this.flags&1))return this.fn();this.flags|=2,qm(this),H0(this);const t=Tt,r=Nr;Tt=this,Nr=!0;try{return this.fn()}finally{B0(this),Tt=t,Nr=r,this.flags&=-3}}stop(){if(this.flags&1){for(let t=this.deps;t;t=t.nextDep)Uh(t);this.deps=this.depsTail=void 0,qm(this),this.onStop&&this.onStop(),this.flags&=-2}}trigger(){this.flags&64?dd.add(this):this.scheduler?this.scheduler():this.runIfDirty()}runIfDirty(){jd(this)&&this.run()}get dirty(){return jd(this)}}let z0=0,Yl,Zl;function F0(e,t=!1){if(e.flags|=8,t){e.next=Zl,Zl=e;return}e.next=Yl,Yl=e}function qh(){z0++}function jh(){if(--z0>0)return;if(Zl){let t=Zl;for(Zl=void 0;t;){const r=t.next;t.next=void 0,t.flags&=-9,t=r}}let e;for(;Yl;){let t=Yl;for(Yl=void 0;t;){const r=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(o){e||(e=o)}t=r}}if(e)throw e}function H0(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function B0(e){let t,r=e.depsTail,o=r;for(;o;){const s=o.prevDep;o.version===-1?(o===r&&(r=s),Uh(o),XS(o)):t=o,o.dep.activeLink=o.prevActiveLink,o.prevActiveLink=void 0,o=s}e.deps=t,e.depsTail=r}function jd(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(W0(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function W0(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===aa)||(e.globalVersion=aa,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!jd(e))))return;e.flags|=2;const t=e.dep,r=Tt,o=Nr;Tt=e,Nr=!0;try{H0(e);const s=e.fn(e._value);(t.version===0||Gn(s,e._value))&&(e.flags|=128,e._value=s,t.version++)}catch(s){throw t.version++,s}finally{Tt=r,Nr=o,B0(e),e.flags&=-3}}function Uh(e,t=!1){const{dep:r,prevSub:o,nextSub:s}=e;if(o&&(o.nextSub=s,e.prevSub=void 0),s&&(s.prevSub=o,e.nextSub=void 0),r.subs===e&&(r.subs=o,!o&&r.computed)){r.computed.flags&=-5;for(let c=r.computed.deps;c;c=c.nextDep)Uh(c,!0)}!t&&!--r.sc&&r.map&&r.map.delete(r.key)}function XS(e){const{prevDep:t,nextDep:r}=e;t&&(t.nextDep=r,e.prevDep=void 0),r&&(r.prevDep=t,e.nextDep=void 0)}let Nr=!0;const q0=[];function Si(){q0.push(Nr),Nr=!1}function _i(){const e=q0.pop();Nr=e===void 0?!0:e}function qm(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const r=Tt;Tt=void 0;try{t()}finally{Tt=r}}}let aa=0;class YS{constructor(t,r){this.sub=t,this.dep=r,this.version=r.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Wu{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!Tt||!Nr||Tt===this.computed)return;let r=this.activeLink;if(r===void 0||r.sub!==Tt)r=this.activeLink=new YS(Tt,this),Tt.deps?(r.prevDep=Tt.depsTail,Tt.depsTail.nextDep=r,Tt.depsTail=r):Tt.deps=Tt.depsTail=r,j0(r);else if(r.version===-1&&(r.version=this.version,r.nextDep)){const o=r.nextDep;o.prevDep=r.prevDep,r.prevDep&&(r.prevDep.nextDep=o),r.prevDep=Tt.depsTail,r.nextDep=void 0,Tt.depsTail.nextDep=r,Tt.depsTail=r,Tt.deps===r&&(Tt.deps=o)}return r}trigger(t){this.version++,aa++,this.notify(t)}notify(t){qh();try{for(let r=this.subs;r;r=r.prevSub)r.sub.notify()&&r.sub.dep.notify()}finally{jh()}}}function j0(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let o=t.deps;o;o=o.nextDep)j0(o)}const r=e.dep.subs;r!==e&&(e.prevSub=r,r&&(r.nextSub=e)),e.dep.subs=e}}const iu=new WeakMap,qo=Symbol(\"\"),Ud=Symbol(\"\"),ca=Symbol(\"\");function wn(e,t,r){if(Nr&&Tt){let o=iu.get(e);o||iu.set(e,o=new Map);let s=o.get(r);s||(o.set(r,s=new Wu),s.map=o,s.key=r),s.track()}}function bi(e,t,r,o,s,c){const f=iu.get(e);if(!f){aa++;return}const d=h=>{h&&h.trigger()};if(qh(),t===\"clear\")f.forEach(d);else{const h=Ze(e),p=h&&Du(r);if(h&&r===\"length\"){const g=Number(o);f.forEach((v,b)=>{(b===\"length\"||b===ca||!Pr(b)&&b>=g)&&d(v)})}else switch((r!==void 0||f.has(void 0))&&d(f.get(r)),p&&d(f.get(ca)),t){case\"add\":h?p&&d(f.get(\"length\")):(d(f.get(qo)),$s(e)&&d(f.get(Ud)));break;case\"delete\":h||(d(f.get(qo)),$s(e)&&d(f.get(Ud)));break;case\"set\":$s(e)&&d(f.get(qo));break}}jh()}function ZS(e,t){const r=iu.get(e);return r&&r.get(t)}function _s(e){const t=mt(e);return t===e?t:(wn(t,\"iterate\",ca),or(e)?t:t.map(Rr))}function qu(e){return wn(e=mt(e),\"iterate\",ca),e}function Yi(e,t){return Ti(e)?jo(e)?Ks(Rr(t)):Ks(t):Rr(t)}const JS={__proto__:null,[Symbol.iterator](){return hd(this,Symbol.iterator,e=>Yi(this,e))},concat(...e){return _s(this).concat(...e.map(t=>Ze(t)?_s(t):t))},entries(){return hd(this,\"entries\",e=>(e[1]=Yi(this,e[1]),e))},every(e,t){return fi(this,\"every\",e,t,void 0,arguments)},filter(e,t){return fi(this,\"filter\",e,t,r=>r.map(o=>Yi(this,o)),arguments)},find(e,t){return fi(this,\"find\",e,t,r=>Yi(this,r),arguments)},findIndex(e,t){return fi(this,\"findIndex\",e,t,void 0,arguments)},findLast(e,t){return fi(this,\"findLast\",e,t,r=>Yi(this,r),arguments)},findLastIndex(e,t){return fi(this,\"findLastIndex\",e,t,void 0,arguments)},forEach(e,t){return fi(this,\"forEach\",e,t,void 0,arguments)},includes(...e){return pd(this,\"includes\",e)},indexOf(...e){return pd(this,\"indexOf\",e)},join(e){return _s(this).join(e)},lastIndexOf(...e){return pd(this,\"lastIndexOf\",e)},map(e,t){return fi(this,\"map\",e,t,void 0,arguments)},pop(){return Dl(this,\"pop\")},push(...e){return Dl(this,\"push\",e)},reduce(e,...t){return jm(this,\"reduce\",e,t)},reduceRight(e,...t){return jm(this,\"reduceRight\",e,t)},shift(){return Dl(this,\"shift\")},some(e,t){return fi(this,\"some\",e,t,void 0,arguments)},splice(...e){return Dl(this,\"splice\",e)},toReversed(){return _s(this).toReversed()},toSorted(e){return _s(this).toSorted(e)},toSpliced(...e){return _s(this).toSpliced(...e)},unshift(...e){return Dl(this,\"unshift\",e)},values(){return hd(this,\"values\",e=>Yi(this,e))}};function hd(e,t,r){const o=qu(e),s=o[t]();return o!==e&&!or(e)&&(s._next=s.next,s.next=()=>{const c=s._next();return c.done||(c.value=r(c.value)),c}),s}const QS=Array.prototype;function fi(e,t,r,o,s,c){const f=qu(e),d=f!==e&&!or(e),h=f[t];if(h!==QS[t]){const v=h.apply(e,c);return d?Rr(v):v}let p=r;f!==e&&(d?p=function(v,b){return r.call(this,Yi(e,v),b,e)}:r.length>2&&(p=function(v,b){return r.call(this,v,b,e)}));const g=h.call(f,p,o);return d&&s?s(g):g}function jm(e,t,r,o){const s=qu(e);let c=r;return s!==e&&(or(e)?r.length>3&&(c=function(f,d,h){return r.call(this,f,d,h,e)}):c=function(f,d,h){return r.call(this,f,Yi(e,d),h,e)}),s[t](c,...o)}function pd(e,t,r){const o=mt(e);wn(o,\"iterate\",ca);const s=o[t](...r);return(s===-1||s===!1)&&ju(r[0])?(r[0]=mt(r[0]),o[t](...r)):s}function Dl(e,t,r=[]){Si(),qh();const o=mt(e)[t].apply(e,r);return jh(),_i(),o}const e_=Fh(\"__proto__,__v_isRef,__isVue\"),U0=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!==\"arguments\"&&e!==\"caller\").map(e=>Symbol[e]).filter(Pr));function t_(e){Pr(e)||(e=String(e));const t=mt(this);return wn(t,\"has\",e),t.hasOwnProperty(e)}class V0{constructor(t=!1,r=!1){this._isReadonly=t,this._isShallow=r}get(t,r,o){if(r===\"__v_skip\")return t.__v_skip;const s=this._isReadonly,c=this._isShallow;if(r===\"__v_isReactive\")return!s;if(r===\"__v_isReadonly\")return s;if(r===\"__v_isShallow\")return c;if(r===\"__v_raw\")return o===(s?c?f_:Y0:c?X0:K0).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(o)?t:void 0;const f=Ze(t);if(!s){let h;if(f&&(h=JS[r]))return h;if(r===\"hasOwnProperty\")return t_}const d=Reflect.get(t,r,Mt(t)?t:o);if((Pr(r)?U0.has(r):e_(r))||(s||wn(t,\"get\",r),c))return d;if(Mt(d)){const h=f&&Du(r)?d:d.value;return s&&kt(h)?Gs(h):h}return kt(d)?s?Gs(d):ir(d):d}}class G0 extends V0{constructor(t=!1){super(!1,t)}set(t,r,o,s){let c=t[r];const f=Ze(t)&&Du(r);if(!this._isShallow){const p=Ti(c);if(!or(o)&&!Ti(o)&&(c=mt(c),o=mt(o)),!f&&Mt(c)&&!Mt(o))return p||(c.value=o),!0}const d=f?Number(r)<t.length:wt(t,r),h=Reflect.set(t,r,o,Mt(t)?t:s);return t===mt(s)&&(d?Gn(o,c)&&bi(t,\"set\",r,o):bi(t,\"add\",r,o)),h}deleteProperty(t,r){const o=wt(t,r);t[r];const s=Reflect.deleteProperty(t,r);return s&&o&&bi(t,\"delete\",r,void 0),s}has(t,r){const o=Reflect.has(t,r);return(!Pr(r)||!U0.has(r))&&wn(t,\"has\",r),o}ownKeys(t){return wn(t,\"iterate\",Ze(t)?\"length\":qo),Reflect.ownKeys(t)}}class n_ extends V0{constructor(t=!1){super(!0,t)}set(t,r){return!0}deleteProperty(t,r){return!0}}const r_=new G0,i_=new n_,o_=new G0(!0);const Vd=e=>e,Tc=e=>Reflect.getPrototypeOf(e);function s_(e,t,r){return function(...o){const s=this.__v_raw,c=mt(s),f=$s(c),d=e===\"entries\"||e===Symbol.iterator&&f,h=e===\"keys\"&&f,p=s[e](...o),g=r?Vd:t?Ks:Rr;return!t&&wn(c,\"iterate\",h?Ud:qo),{next(){const{value:v,done:b}=p.next();return b?{value:v,done:b}:{value:d?[g(v[0]),g(v[1])]:g(v),done:b}},[Symbol.iterator](){return this}}}}function Cc(e){return function(...t){return e===\"delete\"?!1:e===\"clear\"?void 0:this}}function l_(e,t){const r={get(s){const c=this.__v_raw,f=mt(c),d=mt(s);e||(Gn(s,d)&&wn(f,\"get\",s),wn(f,\"get\",d));const{has:h}=Tc(f),p=t?Vd:e?Ks:Rr;if(h.call(f,s))return p(c.get(s));if(h.call(f,d))return p(c.get(d));c!==f&&c.get(s)},get size(){const s=this.__v_raw;return!e&&wn(mt(s),\"iterate\",qo),s.size},has(s){const c=this.__v_raw,f=mt(c),d=mt(s);return e||(Gn(s,d)&&wn(f,\"has\",s),wn(f,\"has\",d)),s===d?c.has(s):c.has(s)||c.has(d)},forEach(s,c){const f=this,d=f.__v_raw,h=mt(d),p=t?Vd:e?Ks:Rr;return!e&&wn(h,\"iterate\",qo),d.forEach((g,v)=>s.call(c,p(g),p(v),f))}};return on(r,e?{add:Cc(\"add\"),set:Cc(\"set\"),delete:Cc(\"delete\"),clear:Cc(\"clear\")}:{add(s){!t&&!or(s)&&!Ti(s)&&(s=mt(s));const c=mt(this);return Tc(c).has.call(c,s)||(c.add(s),bi(c,\"add\",s,s)),this},set(s,c){!t&&!or(c)&&!Ti(c)&&(c=mt(c));const f=mt(this),{has:d,get:h}=Tc(f);let p=d.call(f,s);p||(s=mt(s),p=d.call(f,s));const g=h.call(f,s);return f.set(s,c),p?Gn(c,g)&&bi(f,\"set\",s,c):bi(f,\"add\",s,c),this},delete(s){const c=mt(this),{has:f,get:d}=Tc(c);let h=f.call(c,s);h||(s=mt(s),h=f.call(c,s)),d&&d.call(c,s);const p=c.delete(s);return h&&bi(c,\"delete\",s,void 0),p},clear(){const s=mt(this),c=s.size!==0,f=s.clear();return c&&bi(s,\"clear\",void 0,void 0),f}}),[\"keys\",\"values\",\"entries\",Symbol.iterator].forEach(s=>{r[s]=s_(s,e,t)}),r}function Vh(e,t){const r=l_(e,t);return(o,s,c)=>s===\"__v_isReactive\"?!e:s===\"__v_isReadonly\"?e:s===\"__v_raw\"?o:Reflect.get(wt(r,s)&&s in o?r:o,s,c)}const a_={get:Vh(!1,!1)},c_={get:Vh(!1,!0)},u_={get:Vh(!0,!1)};const K0=new WeakMap,X0=new WeakMap,Y0=new WeakMap,f_=new WeakMap;function d_(e){switch(e){case\"Object\":case\"Array\":return 1;case\"Map\":case\"Set\":case\"WeakMap\":case\"WeakSet\":return 2;default:return 0}}function h_(e){return e.__v_skip||!Object.isExtensible(e)?0:d_(IS(e))}function ir(e){return Ti(e)?e:Kh(e,!1,r_,a_,K0)}function Gh(e){return Kh(e,!1,o_,c_,X0)}function Gs(e){return Kh(e,!0,i_,u_,Y0)}function Kh(e,t,r,o,s){if(!kt(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const c=h_(e);if(c===0)return e;const f=s.get(e);if(f)return f;const d=new Proxy(e,c===2?o:r);return s.set(e,d),d}function jo(e){return Ti(e)?jo(e.__v_raw):!!(e&&e.__v_isReactive)}function Ti(e){return!!(e&&e.__v_isReadonly)}function or(e){return!!(e&&e.__v_isShallow)}function ju(e){return e?!!e.__v_raw:!1}function mt(e){const t=e&&e.__v_raw;return t?mt(t):e}function Uu(e){return!wt(e,\"__v_skip\")&&Object.isExtensible(e)&&M0(e,\"__v_skip\",!0),e}const Rr=e=>kt(e)?ir(e):e,Ks=e=>kt(e)?Gs(e):e;function Mt(e){return e?e.__v_isRef===!0:!1}function Ge(e){return Z0(e,!1)}function Ft(e){return Z0(e,!0)}function Z0(e,t){return Mt(e)?e:new p_(e,t)}class p_{constructor(t,r){this.dep=new Wu,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=r?t:mt(t),this._value=r?t:Rr(t),this.__v_isShallow=r}get value(){return this.dep.track(),this._value}set value(t){const r=this._rawValue,o=this.__v_isShallow||or(t)||Ti(t);t=o?t:mt(t),Gn(t,r)&&(this._rawValue=t,this._value=o?t:Rr(t),this.dep.trigger())}}function K(e){return Mt(e)?e.value:e}function Xt(e){return et(e)?e():K(e)}const g_={get:(e,t,r)=>t===\"__v_raw\"?e:K(Reflect.get(e,t,r)),set:(e,t,r,o)=>{const s=e[t];return Mt(s)&&!Mt(r)?(s.value=r,!0):Reflect.set(e,t,r,o)}};function J0(e){return jo(e)?e:new Proxy(e,g_)}class m_{constructor(t){this.__v_isRef=!0,this._value=void 0;const r=this.dep=new Wu,{get:o,set:s}=t(r.track.bind(r),r.trigger.bind(r));this._get=o,this._set=s}get value(){return this._value=this._get()}set value(t){this._set(t)}}function Q0(e){return new m_(e)}function v_(e){const t=Ze(e)?new Array(e.length):{};for(const r in e)t[r]=eb(e,r);return t}class y_{constructor(t,r,o){this._object=t,this._key=r,this._defaultValue=o,this.__v_isRef=!0,this._value=void 0,this._raw=mt(t);let s=!0,c=t;if(!Ze(t)||!Du(String(r)))do s=!ju(c)||or(c);while(s&&(c=c.__v_raw));this._shallow=s}get value(){let t=this._object[this._key];return this._shallow&&(t=K(t)),this._value=t===void 0?this._defaultValue:t}set value(t){if(this._shallow&&Mt(this._raw[this._key])){const r=this._object[this._key];if(Mt(r)){r.value=t;return}}this._object[this._key]=t}get dep(){return ZS(this._raw,this._key)}}class b_{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function w_(e,t,r){return Mt(e)?e:et(e)?new b_(e):kt(e)&&arguments.length>1?eb(e,t,r):Ge(e)}function eb(e,t,r){return new y_(e,t,r)}class x_{constructor(t,r,o){this.fn=t,this.setter=r,this._value=void 0,this.dep=new Wu(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=aa-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!r,this.isSSR=o}notify(){if(this.flags|=16,!(this.flags&8)&&Tt!==this)return F0(this,!0),!0}get value(){const t=this.dep.track();return W0(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function k_(e,t,r=!1){let o,s;return et(e)?o=e:(o=e.get,s=e.set),new x_(o,s,r)}const Ec={},ou=new WeakMap;let $o;function S_(e,t=!1,r=$o){if(r){let o=ou.get(r);o||ou.set(r,o=[]),o.push(e)}}function __(e,t,r=vt){const{immediate:o,deep:s,once:c,scheduler:f,augmentJob:d,call:h}=r,p=_=>s?_:or(_)||s===!1||s===0?wi(_,1):wi(_);let g,v,b,w,E=!1,L=!1;if(Mt(e)?(v=()=>e.value,E=or(e)):jo(e)?(v=()=>p(e),E=!0):Ze(e)?(L=!0,E=e.some(_=>jo(_)||or(_)),v=()=>e.map(_=>{if(Mt(_))return _.value;if(jo(_))return p(_);if(et(_))return h?h(_,2):_()})):et(e)?t?v=h?()=>h(e,2):e:v=()=>{if(b){Si();try{b()}finally{_i()}}const _=$o;$o=g;try{return h?h(e,3,[w]):e(w)}finally{$o=_}}:v=Xr,t&&s){const _=v,$=s===!0?1/0:s;v=()=>wi(_(),$)}const P=I0(),M=()=>{g.stop(),P&&P.active&&Bh(P.effects,g)};if(c&&t){const _=t;t=(...$)=>{_(...$),M()}}let R=L?new Array(e.length).fill(Ec):Ec;const I=_=>{if(!(!(g.flags&1)||!g.dirty&&!_))if(t){const $=g.run();if(s||E||(L?$.some((W,ne)=>Gn(W,R[ne])):Gn($,R))){b&&b();const W=$o;$o=g;try{const ne=[$,R===Ec?void 0:L&&R[0]===Ec?[]:R,w];R=$,h?h(t,3,ne):t(...ne)}finally{$o=W}}}else g.run()};return d&&d(I),g=new D0(v),g.scheduler=f?()=>f(I,!1):I,w=_=>S_(_,!1,g),b=g.onStop=()=>{const _=ou.get(g);if(_){if(h)h(_,4);else for(const $ of _)$();ou.delete(g)}},t?o?I(!0):R=g.run():f?f(I.bind(null,!0),!0):g.run(),M.pause=g.pause.bind(g),M.resume=g.resume.bind(g),M.stop=M,M}function wi(e,t=1/0,r){if(t<=0||!kt(e)||e.__v_skip||(r=r||new Map,(r.get(e)||0)>=t))return e;if(r.set(e,t),t--,Mt(e))wi(e.value,t,r);else if(Ze(e))for(let o=0;o<e.length;o++)wi(e[o],t,r);else if(Iu(e)||$s(e))e.forEach(o=>{wi(o,t,r)});else if(L0(e)){for(const o in e)wi(e[o],t,r);for(const o of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,o)&&wi(e[o],t,r)}return e}/**\n* @vue/runtime-core v3.5.25\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/function Pa(e,t,r,o){try{return o?e(...o):e()}catch(s){Ra(s,t,r)}}function $r(e,t,r,o){if(et(e)){const s=Pa(e,t,r,o);return s&&E0(s)&&s.catch(c=>{Ra(c,t,r)}),s}if(Ze(e)){const s=[];for(let c=0;c<e.length;c++)s.push($r(e[c],t,r,o));return s}}function Ra(e,t,r,o=!0){const s=t?t.vnode:null,{errorHandler:c,throwUnhandledErrorInProduction:f}=t&&t.appContext.config||vt;if(t){let d=t.parent;const h=t.proxy,p=`https://vuejs.org/error-reference/#runtime-${r}`;for(;d;){const g=d.ec;if(g){for(let v=0;v<g.length;v++)if(g[v](e,h,p)===!1)return}d=d.parent}if(c){Si(),Pa(c,null,10,[e,h,p]),_i();return}}T_(e,r,s,o,f)}function T_(e,t,r,o=!0,s=!1){if(s)throw e;console.error(e)}const Pn=[];let Gr=-1;const Is=[];let Zi=null,Es=0;const tb=Promise.resolve();let su=null;function Et(e){const t=su||tb;return e?t.then(this?e.bind(this):e):t}function C_(e){let t=Gr+1,r=Pn.length;for(;t<r;){const o=t+r>>>1,s=Pn[o],c=ua(s);c<e||c===e&&s.flags&2?t=o+1:r=o}return t}function Xh(e){if(!(e.flags&1)){const t=ua(e),r=Pn[Pn.length-1];!r||!(e.flags&2)&&t>=ua(r)?Pn.push(e):Pn.splice(C_(t),0,e),e.flags|=1,nb()}}function nb(){su||(su=tb.then(ib))}function Gd(e){Ze(e)?Is.push(...e):Zi&&e.id===-1?Zi.splice(Es+1,0,e):e.flags&1||(Is.push(e),e.flags|=1),nb()}function Um(e,t,r=Gr+1){for(;r<Pn.length;r++){const o=Pn[r];if(o&&o.flags&2){if(e&&o.id!==e.uid)continue;Pn.splice(r,1),r--,o.flags&4&&(o.flags&=-2),o(),o.flags&4||(o.flags&=-2)}}}function rb(e){if(Is.length){const t=[...new Set(Is)].sort((r,o)=>ua(r)-ua(o));if(Is.length=0,Zi){Zi.push(...t);return}for(Zi=t,Es=0;Es<Zi.length;Es++){const r=Zi[Es];r.flags&4&&(r.flags&=-2),r.flags&8||r(),r.flags&=-2}Zi=null,Es=0}}const ua=e=>e.id==null?e.flags&2?-1:1/0:e.id;function ib(e){try{for(Gr=0;Gr<Pn.length;Gr++){const t=Pn[Gr];t&&!(t.flags&8)&&(t.flags&4&&(t.flags&=-2),Pa(t,t.i,t.i?15:14),t.flags&4||(t.flags&=-2))}}finally{for(;Gr<Pn.length;Gr++){const t=Pn[Gr];t&&(t.flags&=-2)}Gr=-1,Pn.length=0,rb(),su=null,(Pn.length||Is.length)&&ib()}}let mn=null,Vu=null;function lu(e){const t=mn;return mn=e,Vu=e&&e.type.__scopeId||null,t}function ob(e){Vu=e}function sb(){Vu=null}const lb=e=>We;function We(e,t=mn,r){if(!t||e._n)return e;const o=(...s)=>{o._d&&Ys(-1);const c=lu(t);let f;try{f=e(...s)}finally{lu(c),o._d&&Ys(1)}return f};return o._n=!0,o._c=!0,o._d=!0,o}function at(e,t){if(mn===null)return e;const r=Qu(mn),o=e.dirs||(e.dirs=[]);for(let s=0;s<t.length;s++){let[c,f,d,h=vt]=t[s];c&&(et(c)&&(c={mounted:c,updated:c}),c.deep&&wi(f),o.push({dir:c,instance:r,value:f,oldValue:void 0,arg:d,modifiers:h}))}return e}function Mo(e,t,r,o){const s=e.dirs,c=t&&t.dirs;for(let f=0;f<s.length;f++){const d=s[f];c&&(d.oldValue=c[f].value);let h=d.dir[o];h&&(Si(),$r(h,r,8,[e.el,d,e,t]),_i())}}const E_=Symbol(\"_vte\"),ab=e=>e.__isTeleport,yi=Symbol(\"_leaveCb\"),Ac=Symbol(\"_enterCb\");function A_(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return Mi(()=>{e.isMounted=!0}),$a(()=>{e.isUnmounting=!0}),e}const ur=[Function,Array],cb={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:ur,onEnter:ur,onAfterEnter:ur,onEnterCancelled:ur,onBeforeLeave:ur,onLeave:ur,onAfterLeave:ur,onLeaveCancelled:ur,onBeforeAppear:ur,onAppear:ur,onAfterAppear:ur,onAppearCancelled:ur},ub=e=>{const t=e.subTree;return t.component?ub(t.component):t},L_={name:\"BaseTransition\",props:cb,setup(e,{slots:t}){const r=ti(),o=A_();return()=>{const s=t.default&&hb(t.default(),!0);if(!s||!s.length)return;const c=fb(s),f=mt(e),{mode:d}=f;if(o.isLeaving)return gd(c);const h=Vm(c);if(!h)return gd(c);let p=Kd(h,f,o,r,v=>p=v);h.type!==ln&&fa(h,p);let g=r.subTree&&Vm(r.subTree);if(g&&g.type!==ln&&!Kr(g,h)&&ub(r).type!==ln){let v=Kd(g,f,o,r);if(fa(g,v),d===\"out-in\"&&h.type!==ln)return o.isLeaving=!0,v.afterLeave=()=>{o.isLeaving=!1,r.job.flags&8||r.update(),delete v.afterLeave,g=void 0},gd(c);d===\"in-out\"&&h.type!==ln?v.delayLeave=(b,w,E)=>{const L=db(o,g);L[String(g.key)]=g,b[yi]=()=>{w(),b[yi]=void 0,delete p.delayedLeave,g=void 0},p.delayedLeave=()=>{E(),delete p.delayedLeave,g=void 0}}:g=void 0}else g&&(g=void 0);return c}}};function fb(e){let t=e[0];if(e.length>1){for(const r of e)if(r.type!==ln){t=r;break}}return t}const M_=L_;function db(e,t){const{leavingVNodes:r}=e;let o=r.get(t.type);return o||(o=Object.create(null),r.set(t.type,o)),o}function Kd(e,t,r,o,s){const{appear:c,mode:f,persisted:d=!1,onBeforeEnter:h,onEnter:p,onAfterEnter:g,onEnterCancelled:v,onBeforeLeave:b,onLeave:w,onAfterLeave:E,onLeaveCancelled:L,onBeforeAppear:P,onAppear:M,onAfterAppear:R,onAppearCancelled:I}=t,_=String(e.key),$=db(r,e),W=(Z,G)=>{Z&&$r(Z,o,9,G)},ne=(Z,G)=>{const j=G[1];W(Z,G),Ze(Z)?Z.every(N=>N.length<=1)&&j():Z.length<=1&&j()},ee={mode:f,persisted:d,beforeEnter(Z){let G=h;if(!r.isMounted)if(c)G=P||h;else return;Z[yi]&&Z[yi](!0);const j=$[_];j&&Kr(e,j)&&j.el[yi]&&j.el[yi](),W(G,[Z])},enter(Z){let G=p,j=g,N=v;if(!r.isMounted)if(c)G=M||p,j=R||g,N=I||v;else return;let O=!1;const C=Z[Ac]=k=>{O||(O=!0,k?W(N,[Z]):W(j,[Z]),ee.delayedLeave&&ee.delayedLeave(),Z[Ac]=void 0)};G?ne(G,[Z,C]):C()},leave(Z,G){const j=String(e.key);if(Z[Ac]&&Z[Ac](!0),r.isUnmounting)return G();W(b,[Z]);let N=!1;const O=Z[yi]=C=>{N||(N=!0,G(),C?W(L,[Z]):W(E,[Z]),Z[yi]=void 0,$[j]===e&&delete $[j])};$[j]=e,w?ne(w,[Z,O]):O()},clone(Z){const G=Kd(Z,t,r,o,s);return s&&s(G),G}};return ee}function gd(e){if(Gu(e))return e=uo(e),e.children=null,e}function Vm(e){if(!Gu(e))return ab(e.type)&&e.children?fb(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:r}=e;if(r){if(t&16)return r[0];if(t&32&&et(r.default))return r.default()}}function fa(e,t){e.shapeFlag&6&&e.component?(e.transition=t,fa(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function hb(e,t=!1,r){let o=[],s=0;for(let c=0;c<e.length;c++){let f=e[c];const d=r==null?f.key:String(r)+String(f.key!=null?f.key:c);f.type===nt?(f.patchFlag&128&&s++,o=o.concat(hb(f.children,t,d))):(t||f.type!==ln)&&o.push(d!=null?uo(f,{key:d}):f)}if(s>1)for(let c=0;c<o.length;c++)o[c].patchFlag=-2;return o}function rt(e,t){return et(e)?on({name:e.name},t,{setup:e}):e}function Yh(){const e=ti();return e?(e.appContext.config.idPrefix||\"v\")+\"-\"+e.ids[0]+e.ids[1]++:\"\"}function pb(e){e.ids=[e.ids[0]+e.ids[2]+++\"-\",0,0]}const au=new WeakMap;function Jl(e,t,r,o,s=!1){if(Ze(e)){e.forEach((E,L)=>Jl(E,t&&(Ze(t)?t[L]:t),r,o,s));return}if(Ds(o)&&!s){o.shapeFlag&512&&o.type.__asyncResolved&&o.component.subTree.component&&Jl(e,t,r,o.component.subTree);return}const c=o.shapeFlag&4?Qu(o.component):o.el,f=s?null:c,{i:d,r:h}=e,p=t&&t.r,g=d.refs===vt?d.refs={}:d.refs,v=d.setupState,b=mt(v),w=v===vt?C0:E=>wt(b,E);if(p!=null&&p!==h){if(Gm(t),Ht(p))g[p]=null,w(p)&&(v[p]=null);else if(Mt(p)){p.value=null;const E=t;E.k&&(g[E.k]=null)}}if(et(h))Pa(h,d,12,[f,g]);else{const E=Ht(h),L=Mt(h);if(E||L){const P=()=>{if(e.f){const M=E?w(h)?v[h]:g[h]:h.value;if(s)Ze(M)&&Bh(M,c);else if(Ze(M))M.includes(c)||M.push(c);else if(E)g[h]=[c],w(h)&&(v[h]=g[h]);else{const R=[c];h.value=R,e.k&&(g[e.k]=R)}}else E?(g[h]=f,w(h)&&(v[h]=f)):L&&(h.value=f,e.k&&(g[e.k]=f))};if(f){const M=()=>{P(),au.delete(e)};M.id=-1,au.set(e,M),jn(M,r)}else Gm(e),P()}}}function Gm(e){const t=au.get(e);t&&(t.flags|=8,au.delete(e))}Hu().requestIdleCallback;Hu().cancelIdleCallback;const Ds=e=>!!e.type.__asyncLoader,Gu=e=>e.type.__isKeepAlive;function N_(e,t){gb(e,\"a\",t)}function O_(e,t){gb(e,\"da\",t)}function gb(e,t,r=xn){const o=e.__wdc||(e.__wdc=()=>{let s=r;for(;s;){if(s.isDeactivated)return;s=s.parent}return e()});if(Ku(t,o,r),r){let s=r.parent;for(;s&&s.parent;)Gu(s.parent.vnode)&&P_(o,t,r,s),s=s.parent}}function P_(e,t,r,o){const s=Ku(t,e,o,!0);Ia(()=>{Bh(o[t],s)},r)}function Ku(e,t,r=xn,o=!1){if(r){const s=r[e]||(r[e]=[]),c=t.__weh||(t.__weh=(...f)=>{Si();const d=Da(r),h=$r(t,r,e,f);return d(),_i(),h});return o?s.unshift(c):s.push(c),c}}const Li=e=>(t,r=xn)=>{(!pa||e===\"sp\")&&Ku(e,(...o)=>t(...o),r)},R_=Li(\"bm\"),Mi=Li(\"m\"),$_=Li(\"bu\"),I_=Li(\"u\"),$a=Li(\"bum\"),Ia=Li(\"um\"),D_=Li(\"sp\"),z_=Li(\"rtg\"),F_=Li(\"rtc\");function H_(e,t=xn){Ku(\"ec\",e,t)}const Zh=\"components\",B_=\"directives\";function Go(e,t){return Jh(Zh,e,!0,t)||e}const mb=Symbol.for(\"v-ndc\");function Xd(e){return Ht(e)?Jh(Zh,e,!1)||e:e||mb}function vr(e){return Jh(B_,e)}function Jh(e,t,r=!0,o=!1){const s=mn||xn;if(s){const c=s.type;if(e===Zh){const d=PT(c,!1);if(d&&(d===t||d===sr(t)||d===Fu(sr(t))))return c}const f=Km(s[e]||c[e],t)||Km(s.appContext[e],t);return!f&&o?c:f}}function Km(e,t){return e&&(e[t]||e[sr(t)]||e[Fu(sr(t))])}function $n(e,t,r,o){let s;const c=r,f=Ze(e);if(f||Ht(e)){const d=f&&jo(e);let h=!1,p=!1;d&&(h=!or(e),p=Ti(e),e=qu(e)),s=new Array(e.length);for(let g=0,v=e.length;g<v;g++)s[g]=t(h?p?Ks(Rr(e[g])):Rr(e[g]):e[g],g,void 0,c)}else if(typeof e==\"number\"){s=new Array(e);for(let d=0;d<e;d++)s[d]=t(d+1,d,void 0,c)}else if(kt(e))if(e[Symbol.iterator])s=Array.from(e,(d,h)=>t(d,h,void 0,c));else{const d=Object.keys(e);s=new Array(d.length);for(let h=0,p=d.length;h<p;h++){const g=d[h];s[h]=t(e[g],g,h,c)}}else s=[];return s}function W_(e,t){for(let r=0;r<t.length;r++){const o=t[r];if(Ze(o))for(let s=0;s<o.length;s++)e[o[s].name]=o[s].fn;else o&&(e[o.name]=o.key?(...s)=>{const c=o.fn(...s);return c&&(c.key=o.key),c}:o.fn)}return e}function Dt(e,t,r={},o,s){if(mn.ce||mn.parent&&Ds(mn.parent)&&mn.parent.ce){const p=Object.keys(r).length>0;return t!==\"default\"&&(r.name=t),ie(),Ve(nt,null,[Ne(\"slot\",r,o&&o())],p?-2:64)}let c=e[t];c&&c._c&&(c._d=!1),ie();const f=c&&vb(c(r)),d=r.key||f&&f.key,h=Ve(nt,{key:(d&&!Pr(d)?d:`_${t}`)+(!f&&o?\"_fb\":\"\")},f||(o?o():[]),f&&e._===1?64:-2);return h.scopeId&&(h.slotScopeIds=[h.scopeId+\"-s\"]),c&&c._c&&(c._d=!0),h}function vb(e){return e.some(t=>Zs(t)?!(t.type===ln||t.type===nt&&!vb(t.children)):!0)?e:null}function q_(e,t){const r={};for(const o in e)r[qc(o)]=e[o];return r}const Yd=e=>e?jb(e)?Qu(e):Yd(e.parent):null,Ql=on(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Yd(e.parent),$root:e=>Yd(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>xb(e),$forceUpdate:e=>e.f||(e.f=()=>{Xh(e.update)}),$nextTick:e=>e.n||(e.n=Et.bind(e.proxy)),$watch:e=>nT.bind(e)}),md=(e,t)=>e!==vt&&!e.__isScriptSetup&&wt(e,t),j_={get({_:e},t){if(t===\"__v_skip\")return!0;const{ctx:r,setupState:o,data:s,props:c,accessCache:f,type:d,appContext:h}=e;if(t[0]!==\"$\"){const b=f[t];if(b!==void 0)switch(b){case 1:return o[t];case 2:return s[t];case 4:return r[t];case 3:return c[t]}else{if(md(o,t))return f[t]=1,o[t];if(s!==vt&&wt(s,t))return f[t]=2,s[t];if(wt(c,t))return f[t]=3,c[t];if(r!==vt&&wt(r,t))return f[t]=4,r[t];Zd&&(f[t]=0)}}const p=Ql[t];let g,v;if(p)return t===\"$attrs\"&&wn(e.attrs,\"get\",\"\"),p(e);if((g=d.__cssModules)&&(g=g[t]))return g;if(r!==vt&&wt(r,t))return f[t]=4,r[t];if(v=h.config.globalProperties,wt(v,t))return v[t]},set({_:e},t,r){const{data:o,setupState:s,ctx:c}=e;return md(s,t)?(s[t]=r,!0):o!==vt&&wt(o,t)?(o[t]=r,!0):wt(e.props,t)||t[0]===\"$\"&&t.slice(1)in e?!1:(c[t]=r,!0)},has({_:{data:e,setupState:t,accessCache:r,ctx:o,appContext:s,props:c,type:f}},d){let h;return!!(r[d]||e!==vt&&d[0]!==\"$\"&&wt(e,d)||md(t,d)||wt(c,d)||wt(o,d)||wt(Ql,d)||wt(s.config.globalProperties,d)||(h=f.__cssModules)&&h[d])},defineProperty(e,t,r){return r.get!=null?e._.accessCache[t]=0:wt(r,\"value\")&&this.set(e,t,r.value,null),Reflect.defineProperty(e,t,r)}};function yb(){return bb().slots}function U_(){return bb().attrs}function bb(e){const t=ti();return t.setupContext||(t.setupContext=Vb(t))}function cu(e){return Ze(e)?e.reduce((t,r)=>(t[r]=null,t),{}):e}function da(e,t){return!e||!t?e||t:Ze(e)&&Ze(t)?e.concat(t):on({},cu(e),cu(t))}let Zd=!0;function V_(e){const t=xb(e),r=e.proxy,o=e.ctx;Zd=!1,t.beforeCreate&&Xm(t.beforeCreate,e,\"bc\");const{data:s,computed:c,methods:f,watch:d,provide:h,inject:p,created:g,beforeMount:v,mounted:b,beforeUpdate:w,updated:E,activated:L,deactivated:P,beforeDestroy:M,beforeUnmount:R,destroyed:I,unmounted:_,render:$,renderTracked:W,renderTriggered:ne,errorCaptured:ee,serverPrefetch:Z,expose:G,inheritAttrs:j,components:N,directives:O,filters:C}=t;if(p&&G_(p,o,null),f)for(const B in f){const ce=f[B];et(ce)&&(o[B]=ce.bind(r))}if(s){const B=s.call(r,r);kt(B)&&(e.data=ir(B))}if(Zd=!0,c)for(const B in c){const ce=c[B],be=et(ce)?ce.bind(r,r):et(ce.get)?ce.get.bind(r,r):Xr,Se=!et(ce)&&et(ce.set)?ce.set.bind(r):Xr,Be=ke({get:be,set:Se});Object.defineProperty(o,B,{enumerable:!0,configurable:!0,get:()=>Be.value,set:Ae=>Be.value=Ae})}if(d)for(const B in d)wb(d[B],o,r,B);if(h){const B=et(h)?h.call(r):h;Reflect.ownKeys(B).forEach(ce=>{dr(ce,B[ce])})}g&&Xm(g,e,\"c\");function z(B,ce){Ze(ce)?ce.forEach(be=>B(be.bind(r))):ce&&B(ce.bind(r))}if(z(R_,v),z(Mi,b),z($_,w),z(I_,E),z(N_,L),z(O_,P),z(H_,ee),z(F_,W),z(z_,ne),z($a,R),z(Ia,_),z(D_,Z),Ze(G))if(G.length){const B=e.exposed||(e.exposed={});G.forEach(ce=>{Object.defineProperty(B,ce,{get:()=>r[ce],set:be=>r[ce]=be,enumerable:!0})})}else e.exposed||(e.exposed={});$&&e.render===Xr&&(e.render=$),j!=null&&(e.inheritAttrs=j),N&&(e.components=N),O&&(e.directives=O),Z&&pb(e)}function G_(e,t,r=Xr){Ze(e)&&(e=Jd(e));for(const o in e){const s=e[o];let c;kt(s)?\"default\"in s?c=pn(s.from||o,s.default,!0):c=pn(s.from||o):c=pn(s),Mt(c)?Object.defineProperty(t,o,{enumerable:!0,configurable:!0,get:()=>c.value,set:f=>c.value=f}):t[o]=c}}function Xm(e,t,r){$r(Ze(e)?e.map(o=>o.bind(t.proxy)):e.bind(t.proxy),t,r)}function wb(e,t,r,o){let s=o.includes(\".\")?Tb(r,o):()=>r[o];if(Ht(e)){const c=t[e];et(c)&&xt(s,c)}else if(et(e))xt(s,e.bind(r));else if(kt(e))if(Ze(e))e.forEach(c=>wb(c,t,r,o));else{const c=et(e.handler)?e.handler.bind(r):t[e.handler];et(c)&&xt(s,c,e)}}function xb(e){const t=e.type,{mixins:r,extends:o}=t,{mixins:s,optionsCache:c,config:{optionMergeStrategies:f}}=e.appContext,d=c.get(t);let h;return d?h=d:!s.length&&!r&&!o?h=t:(h={},s.length&&s.forEach(p=>uu(h,p,f,!0)),uu(h,t,f)),kt(t)&&c.set(t,h),h}function uu(e,t,r,o=!1){const{mixins:s,extends:c}=t;c&&uu(e,c,r,!0),s&&s.forEach(f=>uu(e,f,r,!0));for(const f in t)if(!(o&&f===\"expose\")){const d=K_[f]||r&&r[f];e[f]=d?d(e[f],t[f]):t[f]}return e}const K_={data:Ym,props:Zm,emits:Zm,methods:Ul,computed:Ul,beforeCreate:Mn,created:Mn,beforeMount:Mn,mounted:Mn,beforeUpdate:Mn,updated:Mn,beforeDestroy:Mn,beforeUnmount:Mn,destroyed:Mn,unmounted:Mn,activated:Mn,deactivated:Mn,errorCaptured:Mn,serverPrefetch:Mn,components:Ul,directives:Ul,watch:Y_,provide:Ym,inject:X_};function Ym(e,t){return t?e?function(){return on(et(e)?e.call(this,this):e,et(t)?t.call(this,this):t)}:t:e}function X_(e,t){return Ul(Jd(e),Jd(t))}function Jd(e){if(Ze(e)){const t={};for(let r=0;r<e.length;r++)t[e[r]]=e[r];return t}return e}function Mn(e,t){return e?[...new Set([].concat(e,t))]:t}function Ul(e,t){return e?on(Object.create(null),e,t):t}function Zm(e,t){return e?Ze(e)&&Ze(t)?[...new Set([...e,...t])]:on(Object.create(null),cu(e),cu(t??{})):t}function Y_(e,t){if(!e)return t;if(!t)return e;const r=on(Object.create(null),e);for(const o in t)r[o]=Mn(e[o],t[o]);return r}function kb(){return{app:null,config:{isNativeTag:C0,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let Z_=0;function J_(e,t){return function(o,s=null){et(o)||(o=on({},o)),s!=null&&!kt(s)&&(s=null);const c=kb(),f=new WeakSet,d=[];let h=!1;const p=c.app={_uid:Z_++,_component:o,_props:s,_container:null,_context:c,_instance:null,version:$T,get config(){return c.config},set config(g){},use(g,...v){return f.has(g)||(g&&et(g.install)?(f.add(g),g.install(p,...v)):et(g)&&(f.add(g),g(p,...v))),p},mixin(g){return c.mixins.includes(g)||c.mixins.push(g),p},component(g,v){return v?(c.components[g]=v,p):c.components[g]},directive(g,v){return v?(c.directives[g]=v,p):c.directives[g]},mount(g,v,b){if(!h){const w=p._ceVNode||Ne(o,s);return w.appContext=c,b===!0?b=\"svg\":b===!1&&(b=void 0),e(w,g,b),h=!0,p._container=g,g.__vue_app__=p,Qu(w.component)}},onUnmount(g){d.push(g)},unmount(){h&&($r(d,p._instance,16),e(null,p._container),delete p._container.__vue_app__)},provide(g,v){return c.provides[g]=v,p},runWithContext(g){const v=Uo;Uo=p;try{return g()}finally{Uo=v}}};return p}}let Uo=null;function dr(e,t){if(xn){let r=xn.provides;const o=xn.parent&&xn.parent.provides;o===r&&(r=xn.provides=Object.create(o)),r[e]=t}}function pn(e,t,r=!1){const o=ti();if(o||Uo){let s=Uo?Uo._context.provides:o?o.parent==null||o.ce?o.vnode.appContext&&o.vnode.appContext.provides:o.parent.provides:void 0;if(s&&e in s)return s[e];if(arguments.length>1)return r&&et(t)?t.call(o&&o.proxy):t}}function Sb(){return!!(ti()||Uo)}const Q_=Symbol.for(\"v-scx\"),eT=()=>pn(Q_);function _b(e,t){return Xu(e,null,t)}function tT(e,t){return Xu(e,null,{flush:\"sync\"})}function xt(e,t,r){return Xu(e,t,r)}function Xu(e,t,r=vt){const{immediate:o,deep:s,flush:c,once:f}=r,d=on({},r),h=t&&o||!t&&c!==\"post\";let p;if(pa){if(c===\"sync\"){const w=eT();p=w.__watcherHandles||(w.__watcherHandles=[])}else if(!h){const w=()=>{};return w.stop=Xr,w.resume=Xr,w.pause=Xr,w}}const g=xn;d.call=(w,E,L)=>$r(w,g,E,L);let v=!1;c===\"post\"?d.scheduler=w=>{jn(w,g&&g.suspense)}:c!==\"sync\"&&(v=!0,d.scheduler=(w,E)=>{E?w():Xh(w)}),d.augmentJob=w=>{t&&(w.flags|=4),v&&(w.flags|=2,g&&(w.id=g.uid,w.i=g))};const b=__(e,t,d);return pa&&(p?p.push(b):h&&b()),b}function nT(e,t,r){const o=this.proxy,s=Ht(e)?e.includes(\".\")?Tb(o,e):()=>o[e]:e.bind(o,o);let c;et(t)?c=t:(c=t.handler,r=t);const f=Da(this),d=Xu(s,c.bind(o),r);return f(),d}function Tb(e,t){const r=t.split(\".\");return()=>{let o=e;for(let s=0;s<r.length&&o;s++)o=o[r[s]];return o}}function Yu(e,t,r=vt){const o=ti(),s=sr(t),c=Ai(t),f=Cb(e,s),d=Q0((h,p)=>{let g,v=vt,b;return tT(()=>{const w=e[s];Gn(g,w)&&(g=w,p())}),{get(){return h(),r.get?r.get(g):g},set(w){const E=r.set?r.set(w):w;if(!Gn(E,g)&&!(v!==vt&&Gn(w,v)))return;const L=o.vnode.props;L&&(t in L||s in L||c in L)&&(`onUpdate:${t}`in L||`onUpdate:${s}`in L||`onUpdate:${c}`in L)||(g=w,p()),o.emit(`update:${t}`,E),Gn(w,E)&&Gn(w,v)&&!Gn(E,b)&&p(),v=w,b=E}}});return d[Symbol.iterator]=()=>{let h=0;return{next(){return h<2?{value:h++?f||vt:d,done:!1}:{done:!0}}}},d}const Cb=(e,t)=>t===\"modelValue\"||t===\"model-value\"?e.modelModifiers:e[`${t}Modifiers`]||e[`${sr(t)}Modifiers`]||e[`${Ai(t)}Modifiers`];function rT(e,t,...r){if(e.isUnmounted)return;const o=e.vnode.props||vt;let s=r;const c=t.startsWith(\"update:\"),f=c&&Cb(o,t.slice(7));f&&(f.trim&&(s=r.map(g=>Ht(g)?g.trim():g)),f.number&&(s=r.map(Wh)));let d,h=o[d=qc(t)]||o[d=qc(sr(t))];!h&&c&&(h=o[d=qc(Ai(t))]),h&&$r(h,e,6,s);const p=o[d+\"Once\"];if(p){if(!e.emitted)e.emitted={};else if(e.emitted[d])return;e.emitted[d]=!0,$r(p,e,6,s)}}const iT=new WeakMap;function Eb(e,t,r=!1){const o=r?iT:t.emitsCache,s=o.get(e);if(s!==void 0)return s;const c=e.emits;let f={},d=!1;if(!et(e)){const h=p=>{const g=Eb(p,t,!0);g&&(d=!0,on(f,g))};!r&&t.mixins.length&&t.mixins.forEach(h),e.extends&&h(e.extends),e.mixins&&e.mixins.forEach(h)}return!c&&!d?(kt(e)&&o.set(e,null),null):(Ze(c)?c.forEach(h=>f[h]=null):on(f,c),kt(e)&&o.set(e,f),f)}function Zu(e,t){return!e||!$u(t)?!1:(t=t.slice(2).replace(/Once$/,\"\"),wt(e,t[0].toLowerCase()+t.slice(1))||wt(e,Ai(t))||wt(e,t))}function Jm(e){const{type:t,vnode:r,proxy:o,withProxy:s,propsOptions:[c],slots:f,attrs:d,emit:h,render:p,renderCache:g,props:v,data:b,setupState:w,ctx:E,inheritAttrs:L}=e,P=lu(e);let M,R;try{if(r.shapeFlag&4){const _=s||o,$=_;M=Lr(p.call($,_,g,v,w,b,E)),R=d}else{const _=t;M=Lr(_.length>1?_(v,{attrs:d,slots:f,emit:h}):_(v,null)),R=t.props?d:sT(d)}}catch(_){ea.length=0,Ra(_,e,1),M=Ne(ln)}let I=M;if(R&&L!==!1){const _=Object.keys(R),{shapeFlag:$}=I;_.length&&$&7&&(c&&_.some(Hh)&&(R=lT(R,c)),I=uo(I,R,!1,!0))}return r.dirs&&(I=uo(I,null,!1,!0),I.dirs=I.dirs?I.dirs.concat(r.dirs):r.dirs),r.transition&&fa(I,r.transition),M=I,lu(P),M}function oT(e,t=!0){let r;for(let o=0;o<e.length;o++){const s=e[o];if(Zs(s)){if(s.type!==ln||s.children===\"v-if\"){if(r)return;r=s}}else return}return r}const sT=e=>{let t;for(const r in e)(r===\"class\"||r===\"style\"||$u(r))&&((t||(t={}))[r]=e[r]);return t},lT=(e,t)=>{const r={};for(const o in e)(!Hh(o)||!(o.slice(9)in t))&&(r[o]=e[o]);return r};function aT(e,t,r){const{props:o,children:s,component:c}=e,{props:f,children:d,patchFlag:h}=t,p=c.emitsOptions;if(t.dirs||t.transition)return!0;if(r&&h>=0){if(h&1024)return!0;if(h&16)return o?Qm(o,f,p):!!f;if(h&8){const g=t.dynamicProps;for(let v=0;v<g.length;v++){const b=g[v];if(f[b]!==o[b]&&!Zu(p,b))return!0}}}else return(s||d)&&(!d||!d.$stable)?!0:o===f?!1:o?f?Qm(o,f,p):!0:!!f;return!1}function Qm(e,t,r){const o=Object.keys(t);if(o.length!==Object.keys(e).length)return!0;for(let s=0;s<o.length;s++){const c=o[s];if(t[c]!==e[c]&&!Zu(r,c))return!0}return!1}function Qh({vnode:e,parent:t},r){for(;t;){const o=t.subTree;if(o.suspense&&o.suspense.activeBranch===e&&(o.el=e.el),o===e)(e=t.vnode).el=r,t=t.parent;else break}}const Ab={},Lb=()=>Object.create(Ab),Mb=e=>Object.getPrototypeOf(e)===Ab;function cT(e,t,r,o=!1){const s={},c=Lb();e.propsDefaults=Object.create(null),Nb(e,t,s,c);for(const f in e.propsOptions[0])f in s||(s[f]=void 0);r?e.props=o?s:Gh(s):e.type.props?e.props=s:e.props=c,e.attrs=c}function uT(e,t,r,o){const{props:s,attrs:c,vnode:{patchFlag:f}}=e,d=mt(s),[h]=e.propsOptions;let p=!1;if((o||f>0)&&!(f&16)){if(f&8){const g=e.vnode.dynamicProps;for(let v=0;v<g.length;v++){let b=g[v];if(Zu(e.emitsOptions,b))continue;const w=t[b];if(h)if(wt(c,b))w!==c[b]&&(c[b]=w,p=!0);else{const E=sr(b);s[E]=Qd(h,d,E,w,e,!1)}else w!==c[b]&&(c[b]=w,p=!0)}}}else{Nb(e,t,s,c)&&(p=!0);let g;for(const v in d)(!t||!wt(t,v)&&((g=Ai(v))===v||!wt(t,g)))&&(h?r&&(r[v]!==void 0||r[g]!==void 0)&&(s[v]=Qd(h,d,v,void 0,e,!0)):delete s[v]);if(c!==d)for(const v in c)(!t||!wt(t,v))&&(delete c[v],p=!0)}p&&bi(e.attrs,\"set\",\"\")}function Nb(e,t,r,o){const[s,c]=e.propsOptions;let f=!1,d;if(t)for(let h in t){if(Xl(h))continue;const p=t[h];let g;s&&wt(s,g=sr(h))?!c||!c.includes(g)?r[g]=p:(d||(d={}))[g]=p:Zu(e.emitsOptions,h)||(!(h in o)||p!==o[h])&&(o[h]=p,f=!0)}if(c){const h=mt(r),p=d||vt;for(let g=0;g<c.length;g++){const v=c[g];r[v]=Qd(s,h,v,p[v],e,!wt(p,v))}}return f}function Qd(e,t,r,o,s,c){const f=e[r];if(f!=null){const d=wt(f,\"default\");if(d&&o===void 0){const h=f.default;if(f.type!==Function&&!f.skipFactory&&et(h)){const{propsDefaults:p}=s;if(r in p)o=p[r];else{const g=Da(s);o=p[r]=h.call(null,t),g()}}else o=h;s.ce&&s.ce._setProp(r,o)}f[0]&&(c&&!d?o=!1:f[1]&&(o===\"\"||o===Ai(r))&&(o=!0))}return o}const fT=new WeakMap;function Ob(e,t,r=!1){const o=r?fT:t.propsCache,s=o.get(e);if(s)return s;const c=e.props,f={},d=[];let h=!1;if(!et(e)){const g=v=>{h=!0;const[b,w]=Ob(v,t,!0);on(f,b),w&&d.push(...w)};!r&&t.mixins.length&&t.mixins.forEach(g),e.extends&&g(e.extends),e.mixins&&e.mixins.forEach(g)}if(!c&&!h)return kt(e)&&o.set(e,Rs),Rs;if(Ze(c))for(let g=0;g<c.length;g++){const v=sr(c[g]);ev(v)&&(f[v]=vt)}else if(c)for(const g in c){const v=sr(g);if(ev(v)){const b=c[g],w=f[v]=Ze(b)||et(b)?{type:b}:on({},b),E=w.type;let L=!1,P=!0;if(Ze(E))for(let M=0;M<E.length;++M){const R=E[M],I=et(R)&&R.name;if(I===\"Boolean\"){L=!0;break}else I===\"String\"&&(P=!1)}else L=et(E)&&E.name===\"Boolean\";w[0]=L,w[1]=P,(L||wt(w,\"default\"))&&d.push(v)}}const p=[f,d];return kt(e)&&o.set(e,p),p}function ev(e){return e[0]!==\"$\"&&!Xl(e)}const ep=e=>e===\"_\"||e===\"_ctx\"||e===\"$stable\",tp=e=>Ze(e)?e.map(Lr):[Lr(e)],dT=(e,t,r)=>{if(t._n)return t;const o=We((...s)=>tp(t(...s)),r);return o._c=!1,o},Pb=(e,t,r)=>{const o=e._ctx;for(const s in e){if(ep(s))continue;const c=e[s];if(et(c))t[s]=dT(s,c,o);else if(c!=null){const f=tp(c);t[s]=()=>f}}},Rb=(e,t)=>{const r=tp(t);e.slots.default=()=>r},$b=(e,t,r)=>{for(const o in t)(r||!ep(o))&&(e[o]=t[o])},hT=(e,t,r)=>{const o=e.slots=Lb();if(e.vnode.shapeFlag&32){const s=t._;s?($b(o,t,r),r&&M0(o,\"_\",s,!0)):Pb(t,o)}else t&&Rb(e,t)},pT=(e,t,r)=>{const{vnode:o,slots:s}=e;let c=!0,f=vt;if(o.shapeFlag&32){const d=t._;d?r&&d===1?c=!1:$b(s,t,r):(c=!t.$stable,Pb(t,s)),f=t}else t&&(Rb(e,t),f={default:1});if(c)for(const d in s)!ep(d)&&f[d]==null&&delete s[d]},jn=_T;function gT(e){return mT(e)}function mT(e,t){const r=Hu();r.__VUE__=!0;const{insert:o,remove:s,patchProp:c,createElement:f,createText:d,createComment:h,setText:p,setElementText:g,parentNode:v,nextSibling:b,setScopeId:w=Xr,insertStaticContent:E}=e,L=(D,q,Q,he=null,de=null,ge=null,Ce=void 0,Ee=null,xe=!!q.dynamicChildren)=>{if(D===q)return;D&&!Kr(D,q)&&(he=F(D),Ae(D,de,ge,!0),D=null),q.patchFlag===-2&&(xe=!1,q.dynamicChildren=null);const{type:ye,ref:J,shapeFlag:ue}=q;switch(ye){case Ju:P(D,q,Q,he);break;case ln:M(D,q,Q,he);break;case yd:D==null&&R(q,Q,he,Ce);break;case nt:N(D,q,Q,he,de,ge,Ce,Ee,xe);break;default:ue&1?$(D,q,Q,he,de,ge,Ce,Ee,xe):ue&6?O(D,q,Q,he,de,ge,Ce,Ee,xe):(ue&64||ue&128)&&ye.process(D,q,Q,he,de,ge,Ce,Ee,xe,le)}J!=null&&de?Jl(J,D&&D.ref,ge,q||D,!q):J==null&&D&&D.ref!=null&&Jl(D.ref,null,ge,D,!0)},P=(D,q,Q,he)=>{if(D==null)o(q.el=d(q.children),Q,he);else{const de=q.el=D.el;q.children!==D.children&&p(de,q.children)}},M=(D,q,Q,he)=>{D==null?o(q.el=h(q.children||\"\"),Q,he):q.el=D.el},R=(D,q,Q,he)=>{[D.el,D.anchor]=E(D.children,q,Q,he,D.el,D.anchor)},I=({el:D,anchor:q},Q,he)=>{let de;for(;D&&D!==q;)de=b(D),o(D,Q,he),D=de;o(q,Q,he)},_=({el:D,anchor:q})=>{let Q;for(;D&&D!==q;)Q=b(D),s(D),D=Q;s(q)},$=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{if(q.type===\"svg\"?Ce=\"svg\":q.type===\"math\"&&(Ce=\"mathml\"),D==null)W(q,Q,he,de,ge,Ce,Ee,xe);else{const ye=D.el&&D.el._isVueCE?D.el:null;try{ye&&ye._beginPatch(),Z(D,q,de,ge,Ce,Ee,xe)}finally{ye&&ye._endPatch()}}},W=(D,q,Q,he,de,ge,Ce,Ee)=>{let xe,ye;const{props:J,shapeFlag:ue,transition:oe,dirs:$e}=D;if(xe=D.el=f(D.type,ge,J&&J.is,J),ue&8?g(xe,D.children):ue&16&&ee(D.children,xe,null,he,de,vd(D,ge),Ce,Ee),$e&&Mo(D,null,he,\"created\"),ne(xe,D,D.scopeId,Ce,he),J){for(const ct in J)ct!==\"value\"&&!Xl(ct)&&c(xe,ct,null,J[ct],ge,he);\"value\"in J&&c(xe,\"value\",null,J.value,ge),(ye=J.onVnodeBeforeMount)&&Vr(ye,he,D)}$e&&Mo(D,null,he,\"beforeMount\");const Je=vT(de,oe);Je&&oe.beforeEnter(xe),o(xe,q,Q),((ye=J&&J.onVnodeMounted)||Je||$e)&&jn(()=>{ye&&Vr(ye,he,D),Je&&oe.enter(xe),$e&&Mo(D,null,he,\"mounted\")},de)},ne=(D,q,Q,he,de)=>{if(Q&&w(D,Q),he)for(let ge=0;ge<he.length;ge++)w(D,he[ge]);if(de){let ge=de.subTree;if(q===ge||zb(ge.type)&&(ge.ssContent===q||ge.ssFallback===q)){const Ce=de.vnode;ne(D,Ce,Ce.scopeId,Ce.slotScopeIds,de.parent)}}},ee=(D,q,Q,he,de,ge,Ce,Ee,xe=0)=>{for(let ye=xe;ye<D.length;ye++){const J=D[ye]=Ee?Ji(D[ye]):Lr(D[ye]);L(null,J,q,Q,he,de,ge,Ce,Ee)}},Z=(D,q,Q,he,de,ge,Ce)=>{const Ee=q.el=D.el;let{patchFlag:xe,dynamicChildren:ye,dirs:J}=q;xe|=D.patchFlag&16;const ue=D.props||vt,oe=q.props||vt;let $e;if(Q&&No(Q,!1),($e=oe.onVnodeBeforeUpdate)&&Vr($e,Q,q,D),J&&Mo(q,D,Q,\"beforeUpdate\"),Q&&No(Q,!0),(ue.innerHTML&&oe.innerHTML==null||ue.textContent&&oe.textContent==null)&&g(Ee,\"\"),ye?G(D.dynamicChildren,ye,Ee,Q,he,vd(q,de),ge):Ce||ce(D,q,Ee,null,Q,he,vd(q,de),ge,!1),xe>0){if(xe&16)j(Ee,ue,oe,Q,de);else if(xe&2&&ue.class!==oe.class&&c(Ee,\"class\",null,oe.class,de),xe&4&&c(Ee,\"style\",ue.style,oe.style,de),xe&8){const Je=q.dynamicProps;for(let ct=0;ct<Je.length;ct++){const dt=Je[ct],Nt=ue[dt],ut=oe[dt];(ut!==Nt||dt===\"value\")&&c(Ee,dt,Nt,ut,de,Q)}}xe&1&&D.children!==q.children&&g(Ee,q.children)}else!Ce&&ye==null&&j(Ee,ue,oe,Q,de);(($e=oe.onVnodeUpdated)||J)&&jn(()=>{$e&&Vr($e,Q,q,D),J&&Mo(q,D,Q,\"updated\")},he)},G=(D,q,Q,he,de,ge,Ce)=>{for(let Ee=0;Ee<q.length;Ee++){const xe=D[Ee],ye=q[Ee],J=xe.el&&(xe.type===nt||!Kr(xe,ye)||xe.shapeFlag&198)?v(xe.el):Q;L(xe,ye,J,null,he,de,ge,Ce,!0)}},j=(D,q,Q,he,de)=>{if(q!==Q){if(q!==vt)for(const ge in q)!Xl(ge)&&!(ge in Q)&&c(D,ge,q[ge],null,de,he);for(const ge in Q){if(Xl(ge))continue;const Ce=Q[ge],Ee=q[ge];Ce!==Ee&&ge!==\"value\"&&c(D,ge,Ee,Ce,de,he)}\"value\"in Q&&c(D,\"value\",q.value,Q.value,de)}},N=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{const ye=q.el=D?D.el:d(\"\"),J=q.anchor=D?D.anchor:d(\"\");let{patchFlag:ue,dynamicChildren:oe,slotScopeIds:$e}=q;$e&&(Ee=Ee?Ee.concat($e):$e),D==null?(o(ye,Q,he),o(J,Q,he),ee(q.children||[],Q,J,de,ge,Ce,Ee,xe)):ue>0&&ue&64&&oe&&D.dynamicChildren?(G(D.dynamicChildren,oe,Q,de,ge,Ce,Ee),(q.key!=null||de&&q===de.subTree)&&Ib(D,q,!0)):ce(D,q,Q,J,de,ge,Ce,Ee,xe)},O=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{q.slotScopeIds=Ee,D==null?q.shapeFlag&512?de.ctx.activate(q,Q,he,Ce,xe):C(q,Q,he,de,ge,Ce,xe):k(D,q,xe)},C=(D,q,Q,he,de,ge,Ce)=>{const Ee=D.component=LT(D,he,de);if(Gu(D)&&(Ee.ctx.renderer=le),MT(Ee,!1,Ce),Ee.asyncDep){if(de&&de.registerDep(Ee,z,Ce),!D.el){const xe=Ee.subTree=Ne(ln);M(null,xe,q,Q),D.placeholder=xe.el}}else z(Ee,D,q,Q,de,ge,Ce)},k=(D,q,Q)=>{const he=q.component=D.component;if(aT(D,q,Q))if(he.asyncDep&&!he.asyncResolved){B(he,q,Q);return}else he.next=q,he.update();else q.el=D.el,he.vnode=q},z=(D,q,Q,he,de,ge,Ce)=>{const Ee=()=>{if(D.isMounted){let{next:ue,bu:oe,u:$e,parent:Je,vnode:ct}=D;{const jt=Db(D);if(jt){ue&&(ue.el=ct.el,B(D,ue,Ce)),jt.asyncDep.then(()=>{D.isUnmounted||Ee()});return}}let dt=ue,Nt;No(D,!1),ue?(ue.el=ct.el,B(D,ue,Ce)):ue=ct,oe&&jc(oe),(Nt=ue.props&&ue.props.onVnodeBeforeUpdate)&&Vr(Nt,Je,ue,ct),No(D,!0);const ut=Jm(D),Yt=D.subTree;D.subTree=ut,L(Yt,ut,v(Yt.el),F(Yt),D,de,ge),ue.el=ut.el,dt===null&&Qh(D,ut.el),$e&&jn($e,de),(Nt=ue.props&&ue.props.onVnodeUpdated)&&jn(()=>Vr(Nt,Je,ue,ct),de)}else{let ue;const{el:oe,props:$e}=q,{bm:Je,m:ct,parent:dt,root:Nt,type:ut}=D,Yt=Ds(q);No(D,!1),Je&&jc(Je),!Yt&&(ue=$e&&$e.onVnodeBeforeMount)&&Vr(ue,dt,q),No(D,!0);{Nt.ce&&Nt.ce._def.shadowRoot!==!1&&Nt.ce._injectChildStyle(ut);const jt=D.subTree=Jm(D);L(null,jt,Q,he,D,de,ge),q.el=jt.el}if(ct&&jn(ct,de),!Yt&&(ue=$e&&$e.onVnodeMounted)){const jt=q;jn(()=>Vr(ue,dt,jt),de)}(q.shapeFlag&256||dt&&Ds(dt.vnode)&&dt.vnode.shapeFlag&256)&&D.a&&jn(D.a,de),D.isMounted=!0,q=Q=he=null}};D.scope.on();const xe=D.effect=new D0(Ee);D.scope.off();const ye=D.update=xe.run.bind(xe),J=D.job=xe.runIfDirty.bind(xe);J.i=D,J.id=D.uid,xe.scheduler=()=>Xh(J),No(D,!0),ye()},B=(D,q,Q)=>{q.component=D;const he=D.vnode.props;D.vnode=q,D.next=null,uT(D,q.props,he,Q),pT(D,q.children,Q),Si(),Um(D),_i()},ce=(D,q,Q,he,de,ge,Ce,Ee,xe=!1)=>{const ye=D&&D.children,J=D?D.shapeFlag:0,ue=q.children,{patchFlag:oe,shapeFlag:$e}=q;if(oe>0){if(oe&128){Se(ye,ue,Q,he,de,ge,Ce,Ee,xe);return}else if(oe&256){be(ye,ue,Q,he,de,ge,Ce,Ee,xe);return}}$e&8?(J&16&&Pe(ye,de,ge),ue!==ye&&g(Q,ue)):J&16?$e&16?Se(ye,ue,Q,he,de,ge,Ce,Ee,xe):Pe(ye,de,ge,!0):(J&8&&g(Q,\"\"),$e&16&&ee(ue,Q,he,de,ge,Ce,Ee,xe))},be=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{D=D||Rs,q=q||Rs;const ye=D.length,J=q.length,ue=Math.min(ye,J);let oe;for(oe=0;oe<ue;oe++){const $e=q[oe]=xe?Ji(q[oe]):Lr(q[oe]);L(D[oe],$e,Q,null,de,ge,Ce,Ee,xe)}ye>J?Pe(D,de,ge,!0,!1,ue):ee(q,Q,he,de,ge,Ce,Ee,xe,ue)},Se=(D,q,Q,he,de,ge,Ce,Ee,xe)=>{let ye=0;const J=q.length;let ue=D.length-1,oe=J-1;for(;ye<=ue&&ye<=oe;){const $e=D[ye],Je=q[ye]=xe?Ji(q[ye]):Lr(q[ye]);if(Kr($e,Je))L($e,Je,Q,null,de,ge,Ce,Ee,xe);else break;ye++}for(;ye<=ue&&ye<=oe;){const $e=D[ue],Je=q[oe]=xe?Ji(q[oe]):Lr(q[oe]);if(Kr($e,Je))L($e,Je,Q,null,de,ge,Ce,Ee,xe);else break;ue--,oe--}if(ye>ue){if(ye<=oe){const $e=oe+1,Je=$e<J?q[$e].el:he;for(;ye<=oe;)L(null,q[ye]=xe?Ji(q[ye]):Lr(q[ye]),Q,Je,de,ge,Ce,Ee,xe),ye++}}else if(ye>oe)for(;ye<=ue;)Ae(D[ye],de,ge,!0),ye++;else{const $e=ye,Je=ye,ct=new Map;for(ye=Je;ye<=oe;ye++){const Bt=q[ye]=xe?Ji(q[ye]):Lr(q[ye]);Bt.key!=null&&ct.set(Bt.key,ye)}let dt,Nt=0;const ut=oe-Je+1;let Yt=!1,jt=0;const Fn=new Array(ut);for(ye=0;ye<ut;ye++)Fn[ye]=0;for(ye=$e;ye<=ue;ye++){const Bt=D[ye];if(Nt>=ut){Ae(Bt,de,ge,!0);continue}let Hn;if(Bt.key!=null)Hn=ct.get(Bt.key);else for(dt=Je;dt<=oe;dt++)if(Fn[dt-Je]===0&&Kr(Bt,q[dt])){Hn=dt;break}Hn===void 0?Ae(Bt,de,ge,!0):(Fn[Hn-Je]=ye+1,Hn>=jt?jt=Hn:Yt=!0,L(Bt,q[Hn],Q,null,de,ge,Ce,Ee,xe),Nt++)}const Hr=Yt?yT(Fn):Rs;for(dt=Hr.length-1,ye=ut-1;ye>=0;ye--){const Bt=Je+ye,Hn=q[Bt],lt=q[Bt+1],yo=Bt+1<J?lt.el||lt.placeholder:he;Fn[ye]===0?L(null,Hn,Q,yo,de,ge,Ce,Ee,xe):Yt&&(dt<0||ye!==Hr[dt]?Be(Hn,Q,yo,2):dt--)}}},Be=(D,q,Q,he,de=null)=>{const{el:ge,type:Ce,transition:Ee,children:xe,shapeFlag:ye}=D;if(ye&6){Be(D.component.subTree,q,Q,he);return}if(ye&128){D.suspense.move(q,Q,he);return}if(ye&64){Ce.move(D,q,Q,le);return}if(Ce===nt){o(ge,q,Q);for(let ue=0;ue<xe.length;ue++)Be(xe[ue],q,Q,he);o(D.anchor,q,Q);return}if(Ce===yd){I(D,q,Q);return}if(he!==2&&ye&1&&Ee)if(he===0)Ee.beforeEnter(ge),o(ge,q,Q),jn(()=>Ee.enter(ge),de);else{const{leave:ue,delayLeave:oe,afterLeave:$e}=Ee,Je=()=>{D.ctx.isUnmounted?s(ge):o(ge,q,Q)},ct=()=>{ge._isLeaving&&ge[yi](!0),ue(ge,()=>{Je(),$e&&$e()})};oe?oe(ge,Je,ct):ct()}else o(ge,q,Q)},Ae=(D,q,Q,he=!1,de=!1)=>{const{type:ge,props:Ce,ref:Ee,children:xe,dynamicChildren:ye,shapeFlag:J,patchFlag:ue,dirs:oe,cacheIndex:$e}=D;if(ue===-2&&(de=!1),Ee!=null&&(Si(),Jl(Ee,null,Q,D,!0),_i()),$e!=null&&(q.renderCache[$e]=void 0),J&256){q.ctx.deactivate(D);return}const Je=J&1&&oe,ct=!Ds(D);let dt;if(ct&&(dt=Ce&&Ce.onVnodeBeforeUnmount)&&Vr(dt,q,D),J&6)Fe(D.component,Q,he);else{if(J&128){D.suspense.unmount(Q,he);return}Je&&Mo(D,null,q,\"beforeUnmount\"),J&64?D.type.remove(D,q,Q,le,he):ye&&!ye.hasOnce&&(ge!==nt||ue>0&&ue&64)?Pe(ye,q,Q,!1,!0):(ge===nt&&ue&384||!de&&J&16)&&Pe(xe,q,Q),he&&Ke(D)}(ct&&(dt=Ce&&Ce.onVnodeUnmounted)||Je)&&jn(()=>{dt&&Vr(dt,q,D),Je&&Mo(D,null,q,\"unmounted\")},Q)},Ke=D=>{const{type:q,el:Q,anchor:he,transition:de}=D;if(q===nt){je(Q,he);return}if(q===yd){_(D);return}const ge=()=>{s(Q),de&&!de.persisted&&de.afterLeave&&de.afterLeave()};if(D.shapeFlag&1&&de&&!de.persisted){const{leave:Ce,delayLeave:Ee}=de,xe=()=>Ce(Q,ge);Ee?Ee(D.el,ge,xe):xe()}else ge()},je=(D,q)=>{let Q;for(;D!==q;)Q=b(D),s(D),D=Q;s(q)},Fe=(D,q,Q)=>{const{bum:he,scope:de,job:ge,subTree:Ce,um:Ee,m:xe,a:ye}=D;tv(xe),tv(ye),he&&jc(he),de.stop(),ge&&(ge.flags|=8,Ae(Ce,D,q,Q)),Ee&&jn(Ee,q),jn(()=>{D.isUnmounted=!0},q)},Pe=(D,q,Q,he=!1,de=!1,ge=0)=>{for(let Ce=ge;Ce<D.length;Ce++)Ae(D[Ce],q,Q,he,de)},F=D=>{if(D.shapeFlag&6)return F(D.component.subTree);if(D.shapeFlag&128)return D.suspense.next();const q=b(D.anchor||D.el),Q=q&&q[E_];return Q?b(Q):q};let Y=!1;const re=(D,q,Q)=>{D==null?q._vnode&&Ae(q._vnode,null,null,!0):L(q._vnode||null,D,q,null,null,null,Q),q._vnode=D,Y||(Y=!0,Um(),rb(),Y=!1)},le={p:L,um:Ae,m:Be,r:Ke,mt:C,mc:ee,pc:ce,pbc:G,n:F,o:e};return{render:re,hydrate:void 0,createApp:J_(re)}}function vd({type:e,props:t},r){return r===\"svg\"&&e===\"foreignObject\"||r===\"mathml\"&&e===\"annotation-xml\"&&t&&t.encoding&&t.encoding.includes(\"html\")?void 0:r}function No({effect:e,job:t},r){r?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function vT(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function Ib(e,t,r=!1){const o=e.children,s=t.children;if(Ze(o)&&Ze(s))for(let c=0;c<o.length;c++){const f=o[c];let d=s[c];d.shapeFlag&1&&!d.dynamicChildren&&((d.patchFlag<=0||d.patchFlag===32)&&(d=s[c]=Ji(s[c]),d.el=f.el),!r&&d.patchFlag!==-2&&Ib(f,d)),d.type===Ju&&d.patchFlag!==-1&&(d.el=f.el),d.type===ln&&!d.el&&(d.el=f.el)}}function yT(e){const t=e.slice(),r=[0];let o,s,c,f,d;const h=e.length;for(o=0;o<h;o++){const p=e[o];if(p!==0){if(s=r[r.length-1],e[s]<p){t[o]=s,r.push(o);continue}for(c=0,f=r.length-1;c<f;)d=c+f>>1,e[r[d]]<p?c=d+1:f=d;p<e[r[c]]&&(c>0&&(t[o]=r[c-1]),r[c]=o)}}for(c=r.length,f=r[c-1];c-- >0;)r[c]=f,f=t[f];return r}function Db(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Db(t)}function tv(e){if(e)for(let t=0;t<e.length;t++)e[t].flags|=8}const zb=e=>e.__isSuspense;let eh=0;const bT={name:\"Suspense\",__isSuspense:!0,process(e,t,r,o,s,c,f,d,h,p){if(e==null)wT(t,r,o,s,c,f,d,h,p);else{if(c&&c.deps>0&&!e.suspense.isInFallback){t.suspense=e.suspense,t.suspense.vnode=t,t.el=e.el;return}xT(e,t,r,o,s,f,d,h,p)}},hydrate:kT,normalize:ST},np=bT;function ha(e,t){const r=e.props&&e.props[t];et(r)&&r()}function wT(e,t,r,o,s,c,f,d,h){const{p,o:{createElement:g}}=h,v=g(\"div\"),b=e.suspense=Fb(e,s,o,t,v,r,c,f,d,h);p(null,b.pendingBranch=e.ssContent,v,null,o,b,c,f),b.deps>0?(ha(e,\"onPending\"),ha(e,\"onFallback\"),p(null,e.ssFallback,t,r,o,null,c,f),zs(b,e.ssFallback)):b.resolve(!1,!0)}function xT(e,t,r,o,s,c,f,d,{p:h,um:p,o:{createElement:g}}){const v=t.suspense=e.suspense;v.vnode=t,t.el=e.el;const b=t.ssContent,w=t.ssFallback,{activeBranch:E,pendingBranch:L,isInFallback:P,isHydrating:M}=v;if(L)v.pendingBranch=b,Kr(L,b)?(h(L,b,v.hiddenContainer,null,s,v,c,f,d),v.deps<=0?v.resolve():P&&(M||(h(E,w,r,o,s,null,c,f,d),zs(v,w)))):(v.pendingId=eh++,M?(v.isHydrating=!1,v.activeBranch=L):p(L,s,v),v.deps=0,v.effects.length=0,v.hiddenContainer=g(\"div\"),P?(h(null,b,v.hiddenContainer,null,s,v,c,f,d),v.deps<=0?v.resolve():(h(E,w,r,o,s,null,c,f,d),zs(v,w))):E&&Kr(E,b)?(h(E,b,r,o,s,v,c,f,d),v.resolve(!0)):(h(null,b,v.hiddenContainer,null,s,v,c,f,d),v.deps<=0&&v.resolve()));else if(E&&Kr(E,b))h(E,b,r,o,s,v,c,f,d),zs(v,b);else if(ha(t,\"onPending\"),v.pendingBranch=b,b.shapeFlag&512?v.pendingId=b.component.suspenseId:v.pendingId=eh++,h(null,b,v.hiddenContainer,null,s,v,c,f,d),v.deps<=0)v.resolve();else{const{timeout:R,pendingId:I}=v;R>0?setTimeout(()=>{v.pendingId===I&&v.fallback(w)},R):R===0&&v.fallback(w)}}function Fb(e,t,r,o,s,c,f,d,h,p,g=!1){const{p:v,m:b,um:w,n:E,o:{parentNode:L,remove:P}}=p;let M;const R=TT(e);R&&t&&t.pendingBranch&&(M=t.pendingId,t.deps++);const I=e.props?N0(e.props.timeout):void 0,_=c,$={vnode:e,parent:t,parentComponent:r,namespace:f,container:o,hiddenContainer:s,deps:0,pendingId:eh++,timeout:typeof I==\"number\"?I:-1,activeBranch:null,pendingBranch:null,isInFallback:!g,isHydrating:g,isUnmounted:!1,effects:[],resolve(W=!1,ne=!1){const{vnode:ee,activeBranch:Z,pendingBranch:G,pendingId:j,effects:N,parentComponent:O,container:C,isInFallback:k}=$;let z=!1;$.isHydrating?$.isHydrating=!1:W||(z=Z&&G.transition&&G.transition.mode===\"out-in\",z&&(Z.transition.afterLeave=()=>{j===$.pendingId&&(b(G,C,c===_?E(Z):c,0),Gd(N),k&&ee.ssFallback&&(ee.ssFallback.el=null))}),Z&&(L(Z.el)===C&&(c=E(Z)),w(Z,O,$,!0),!z&&k&&ee.ssFallback&&jn(()=>ee.ssFallback.el=null,$)),z||b(G,C,c,0)),zs($,G),$.pendingBranch=null,$.isInFallback=!1;let B=$.parent,ce=!1;for(;B;){if(B.pendingBranch){B.effects.push(...N),ce=!0;break}B=B.parent}!ce&&!z&&Gd(N),$.effects=[],R&&t&&t.pendingBranch&&M===t.pendingId&&(t.deps--,t.deps===0&&!ne&&t.resolve()),ha(ee,\"onResolve\")},fallback(W){if(!$.pendingBranch)return;const{vnode:ne,activeBranch:ee,parentComponent:Z,container:G,namespace:j}=$;ha(ne,\"onFallback\");const N=E(ee),O=()=>{$.isInFallback&&(v(null,W,G,N,Z,null,j,d,h),zs($,W))},C=W.transition&&W.transition.mode===\"out-in\";C&&(ee.transition.afterLeave=O),$.isInFallback=!0,w(ee,Z,null,!0),C||O()},move(W,ne,ee){$.activeBranch&&b($.activeBranch,W,ne,ee),$.container=W},next(){return $.activeBranch&&E($.activeBranch)},registerDep(W,ne,ee){const Z=!!$.pendingBranch;Z&&$.deps++;const G=W.vnode.el;W.asyncDep.catch(j=>{Ra(j,W,0)}).then(j=>{if(W.isUnmounted||$.isUnmounted||$.pendingId!==W.suspenseId)return;W.asyncResolved=!0;const{vnode:N}=W;nh(W,j),G&&(N.el=G);const O=!G&&W.subTree.el;ne(W,N,L(G||W.subTree.el),G?null:E(W.subTree),$,f,ee),O&&(N.placeholder=null,P(O)),Qh(W,N.el),Z&&--$.deps===0&&$.resolve()})},unmount(W,ne){$.isUnmounted=!0,$.activeBranch&&w($.activeBranch,r,W,ne),$.pendingBranch&&w($.pendingBranch,r,W,ne)}};return $}function kT(e,t,r,o,s,c,f,d,h){const p=t.suspense=Fb(t,o,r,e.parentNode,document.createElement(\"div\"),null,s,c,f,d,!0),g=h(e,p.pendingBranch=t.ssContent,r,p,c,f);return p.deps===0&&p.resolve(!1,!0),g}function ST(e){const{shapeFlag:t,children:r}=e,o=t&32;e.ssContent=nv(o?r.default:r),e.ssFallback=o?nv(r.fallback):Ne(ln)}function nv(e){let t;if(et(e)){const r=Xs&&e._c;r&&(e._d=!1,ie()),e=e(),r&&(e._d=!0,t=Xn,Hb())}return Ze(e)&&(e=oT(e)),e=Lr(e),t&&!e.dynamicChildren&&(e.dynamicChildren=t.filter(r=>r!==e)),e}function _T(e,t){t&&t.pendingBranch?Ze(e)?t.effects.push(...e):t.effects.push(e):Gd(e)}function zs(e,t){e.activeBranch=t;const{vnode:r,parentComponent:o}=e;let s=t.el;for(;!s&&t.component;)t=t.component.subTree,s=t.el;r.el=s,o&&o.subTree===r&&(o.vnode.el=s,Qh(o,s))}function TT(e){const t=e.props&&e.props.suspensible;return t!=null&&t!==!1}const nt=Symbol.for(\"v-fgt\"),Ju=Symbol.for(\"v-txt\"),ln=Symbol.for(\"v-cmt\"),yd=Symbol.for(\"v-stc\"),ea=[];let Xn=null;function ie(e=!1){ea.push(Xn=e?null:[])}function Hb(){ea.pop(),Xn=ea[ea.length-1]||null}let Xs=1;function Ys(e,t=!1){Xs+=e,e<0&&Xn&&t&&(Xn.hasOnce=!0)}function Bb(e){return e.dynamicChildren=Xs>0?Xn||Rs:null,Hb(),Xs>0&&Xn&&Xn.push(e),e}function ve(e,t,r,o,s,c){return Bb(X(e,t,r,o,s,c,!0))}function Ve(e,t,r,o,s){return Bb(Ne(e,t,r,o,s,!0))}function Zs(e){return e?e.__v_isVNode===!0:!1}function Kr(e,t){return e.type===t.type&&e.key===t.key}const Wb=({key:e})=>e??null,Uc=({ref:e,ref_key:t,ref_for:r})=>(typeof e==\"number\"&&(e=\"\"+e),e!=null?Ht(e)||Mt(e)||et(e)?{i:mn,r:e,k:t,f:!!r}:e:null);function X(e,t=null,r=null,o=0,s=null,c=e===nt?0:1,f=!1,d=!1){const h={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Wb(t),ref:t&&Uc(t),scopeId:Vu,slotScopeIds:null,children:r,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:c,patchFlag:o,dynamicProps:s,dynamicChildren:null,appContext:null,ctx:mn};return d?(rp(h,r),c&128&&e.normalize(h)):r&&(h.shapeFlag|=Ht(r)?8:16),Xs>0&&!f&&Xn&&(h.patchFlag>0||c&6)&&h.patchFlag!==32&&Xn.push(h),h}const Ne=CT;function CT(e,t=null,r=null,o=0,s=null,c=!1){if((!e||e===mb)&&(e=ln),Zs(e)){const d=uo(e,t,!0);return r&&rp(d,r),Xs>0&&!c&&Xn&&(d.shapeFlag&6?Xn[Xn.indexOf(e)]=d:Xn.push(d)),d.patchFlag=-2,d}if(RT(e)&&(e=e.__vccOpts),t){t=qb(t);let{class:d,style:h}=t;d&&!Ht(d)&&(t.class=ot(d)),kt(h)&&(ju(h)&&!Ze(h)&&(h=on({},h)),t.style=zt(h))}const f=Ht(e)?1:zb(e)?128:ab(e)?64:kt(e)?4:et(e)?2:0;return X(e,t,r,o,s,f,c,!0)}function qb(e){return e?ju(e)||Mb(e)?on({},e):e:null}function uo(e,t,r=!1,o=!1){const{props:s,ref:c,patchFlag:f,children:d,transition:h}=e,p=t?ki(s||{},t):s,g={__v_isVNode:!0,__v_skip:!0,type:e.type,props:p,key:p&&Wb(p),ref:t&&t.ref?r&&c?Ze(c)?c.concat(Uc(t)):[c,Uc(t)]:Uc(t):c,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:d,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==nt?f===-1?16:f|16:f,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:h,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&uo(e.ssContent),ssFallback:e.ssFallback&&uo(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return h&&o&&fa(g,h.clone(g)),g}function Qe(e=\" \",t=0){return Ne(Ju,null,e,t)}function He(e=\"\",t=!1){return t?(ie(),Ve(ln,null,e)):Ne(ln,null,e)}function Lr(e){return e==null||typeof e==\"boolean\"?Ne(ln):Ze(e)?Ne(nt,null,e.slice()):Zs(e)?Ji(e):Ne(Ju,null,String(e))}function Ji(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:uo(e)}function rp(e,t){let r=0;const{shapeFlag:o}=e;if(t==null)t=null;else if(Ze(t))r=16;else if(typeof t==\"object\")if(o&65){const s=t.default;s&&(s._c&&(s._d=!1),rp(e,s()),s._c&&(s._d=!0));return}else{r=32;const s=t._;!s&&!Mb(t)?t._ctx=mn:s===3&&mn&&(mn.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else et(t)?(t={default:t,_ctx:mn},r=32):(t=String(t),o&64?(r=16,t=[Qe(t)]):r=8);e.children=t,e.shapeFlag|=r}function ki(...e){const t={};for(let r=0;r<e.length;r++){const o=e[r];for(const s in o)if(s===\"class\")t.class!==o.class&&(t.class=ot([t.class,o.class]));else if(s===\"style\")t.style=zt([t.style,o.style]);else if($u(s)){const c=t[s],f=o[s];f&&c!==f&&!(Ze(c)&&c.includes(f))&&(t[s]=c?[].concat(c,f):f)}else s!==\"\"&&(t[s]=o[s])}return t}function Vr(e,t,r,o=null){$r(e,t,7,[r,o])}const ET=kb();let AT=0;function LT(e,t,r){const o=e.type,s=(t?t.appContext:e.appContext)||ET,c={uid:AT++,vnode:e,type:o,parent:t,appContext:s,root:null,next:null,subTree:null,effect:null,update:null,job:null,scope:new GS(!0),render:null,proxy:null,exposed:null,exposeProxy:null,withProxy:null,provides:t?t.provides:Object.create(s.provides),ids:t?t.ids:[\"\",0,0],accessCache:null,renderCache:[],components:null,directives:null,propsOptions:Ob(o,s),emitsOptions:Eb(o,s),emit:null,emitted:null,propsDefaults:vt,inheritAttrs:o.inheritAttrs,ctx:vt,data:vt,props:vt,attrs:vt,slots:vt,refs:vt,setupState:vt,setupContext:null,suspense:r,suspenseId:r?r.pendingId:0,asyncDep:null,asyncResolved:!1,isMounted:!1,isUnmounted:!1,isDeactivated:!1,bc:null,c:null,bm:null,m:null,bu:null,u:null,um:null,bum:null,da:null,a:null,rtg:null,rtc:null,ec:null,sp:null};return c.ctx={_:c},c.root=t?t.root:c,c.emit=rT.bind(null,c),e.ce&&e.ce(c),c}let xn=null;const ti=()=>xn||mn;let fu,th;{const e=Hu(),t=(r,o)=>{let s;return(s=e[r])||(s=e[r]=[]),s.push(o),c=>{s.length>1?s.forEach(f=>f(c)):s[0](c)}};fu=t(\"__VUE_INSTANCE_SETTERS__\",r=>xn=r),th=t(\"__VUE_SSR_SETTERS__\",r=>pa=r)}const Da=e=>{const t=xn;return fu(e),e.scope.on(),()=>{e.scope.off(),fu(t)}},rv=()=>{xn&&xn.scope.off(),fu(null)};function jb(e){return e.vnode.shapeFlag&4}let pa=!1;function MT(e,t=!1,r=!1){t&&th(t);const{props:o,children:s}=e.vnode,c=jb(e);cT(e,o,c,t),hT(e,s,r||t);const f=c?NT(e,t):void 0;return t&&th(!1),f}function NT(e,t){const r=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,j_);const{setup:o}=r;if(o){Si();const s=e.setupContext=o.length>1?Vb(e):null,c=Da(e),f=Pa(o,e,0,[e.props,s]),d=E0(f);if(_i(),c(),(d||e.sp)&&!Ds(e)&&pb(e),d){if(f.then(rv,rv),t)return f.then(h=>{nh(e,h)}).catch(h=>{Ra(h,e,0)});e.asyncDep=f}else nh(e,f)}else Ub(e)}function nh(e,t,r){et(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:kt(t)&&(e.setupState=J0(t)),Ub(e)}function Ub(e,t,r){const o=e.type;e.render||(e.render=o.render||Xr);{const s=Da(e);Si();try{V_(e)}finally{_i(),s()}}}const OT={get(e,t){return wn(e,\"get\",\"\"),e[t]}};function Vb(e){const t=r=>{e.exposed=r||{}};return{attrs:new Proxy(e.attrs,OT),slots:e.slots,emit:e.emit,expose:t}}function Qu(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(J0(Uu(e.exposed)),{get(t,r){if(r in t)return t[r];if(r in Ql)return Ql[r](e)},has(t,r){return r in t||r in Ql}})):e.proxy}function PT(e,t=!0){return et(e)?e.displayName||e.name:e.name||t&&e.__name}function RT(e){return et(e)&&\"__vccOpts\"in e}const ke=(e,t)=>k_(e,t,pa);function za(e,t,r){try{Ys(-1);const o=arguments.length;return o===2?kt(t)&&!Ze(t)?Zs(t)?Ne(e,null,[t]):Ne(e,t):Ne(e,null,t):(o>3?r=Array.prototype.slice.call(arguments,2):o===3&&Zs(r)&&(r=[r]),Ne(e,t,r))}finally{Ys(1)}}const $T=\"3.5.25\";/**\n* @vue/runtime-dom v3.5.25\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/let rh;const iv=typeof window<\"u\"&&window.trustedTypes;if(iv)try{rh=iv.createPolicy(\"vue\",{createHTML:e=>e})}catch{}const Gb=rh?e=>rh.createHTML(e):e=>e,IT=\"http://www.w3.org/2000/svg\",DT=\"http://www.w3.org/1998/Math/MathML\",mi=typeof document<\"u\"?document:null,ov=mi&&mi.createElement(\"template\"),zT={insert:(e,t,r)=>{t.insertBefore(e,r||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,r,o)=>{const s=t===\"svg\"?mi.createElementNS(IT,e):t===\"mathml\"?mi.createElementNS(DT,e):r?mi.createElement(e,{is:r}):mi.createElement(e);return e===\"select\"&&o&&o.multiple!=null&&s.setAttribute(\"multiple\",o.multiple),s},createText:e=>mi.createTextNode(e),createComment:e=>mi.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>mi.querySelector(e),setScopeId(e,t){e.setAttribute(t,\"\")},insertStaticContent(e,t,r,o,s,c){const f=r?r.previousSibling:t.lastChild;if(s&&(s===c||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),r),!(s===c||!(s=s.nextSibling)););else{ov.innerHTML=Gb(o===\"svg\"?`<svg>${e}</svg>`:o===\"mathml\"?`<math>${e}</math>`:e);const d=ov.content;if(o===\"svg\"||o===\"mathml\"){const h=d.firstChild;for(;h.firstChild;)d.appendChild(h.firstChild);d.removeChild(h)}t.insertBefore(d,r)}return[f?f.nextSibling:t.firstChild,r?r.previousSibling:t.lastChild]}},Ui=\"transition\",zl=\"animation\",ga=Symbol(\"_vtc\"),Kb={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},FT=on({},cb,Kb),HT=e=>(e.displayName=\"Transition\",e.props=FT,e),BT=HT((e,{slots:t})=>za(M_,WT(e),t)),Oo=(e,t=[])=>{Ze(e)?e.forEach(r=>r(...t)):e&&e(...t)},sv=e=>e?Ze(e)?e.some(t=>t.length>1):e.length>1:!1;function WT(e){const t={};for(const N in e)N in Kb||(t[N]=e[N]);if(e.css===!1)return t;const{name:r=\"v\",type:o,duration:s,enterFromClass:c=`${r}-enter-from`,enterActiveClass:f=`${r}-enter-active`,enterToClass:d=`${r}-enter-to`,appearFromClass:h=c,appearActiveClass:p=f,appearToClass:g=d,leaveFromClass:v=`${r}-leave-from`,leaveActiveClass:b=`${r}-leave-active`,leaveToClass:w=`${r}-leave-to`}=e,E=qT(s),L=E&&E[0],P=E&&E[1],{onBeforeEnter:M,onEnter:R,onEnterCancelled:I,onLeave:_,onLeaveCancelled:$,onBeforeAppear:W=M,onAppear:ne=R,onAppearCancelled:ee=I}=t,Z=(N,O,C,k)=>{N._enterCancelled=k,Po(N,O?g:d),Po(N,O?p:f),C&&C()},G=(N,O)=>{N._isLeaving=!1,Po(N,v),Po(N,w),Po(N,b),O&&O()},j=N=>(O,C)=>{const k=N?ne:R,z=()=>Z(O,N,C);Oo(k,[O,z]),lv(()=>{Po(O,N?h:c),di(O,N?g:d),sv(k)||av(O,o,L,z)})};return on(t,{onBeforeEnter(N){Oo(M,[N]),di(N,c),di(N,f)},onBeforeAppear(N){Oo(W,[N]),di(N,h),di(N,p)},onEnter:j(!1),onAppear:j(!0),onLeave(N,O){N._isLeaving=!0;const C=()=>G(N,O);di(N,v),N._enterCancelled?(di(N,b),fv(N)):(fv(N),di(N,b)),lv(()=>{N._isLeaving&&(Po(N,v),di(N,w),sv(_)||av(N,o,P,C))}),Oo(_,[N,C])},onEnterCancelled(N){Z(N,!1,void 0,!0),Oo(I,[N])},onAppearCancelled(N){Z(N,!0,void 0,!0),Oo(ee,[N])},onLeaveCancelled(N){G(N),Oo($,[N])}})}function qT(e){if(e==null)return null;if(kt(e))return[bd(e.enter),bd(e.leave)];{const t=bd(e);return[t,t]}}function bd(e){return N0(e)}function di(e,t){t.split(/\\s+/).forEach(r=>r&&e.classList.add(r)),(e[ga]||(e[ga]=new Set)).add(t)}function Po(e,t){t.split(/\\s+/).forEach(o=>o&&e.classList.remove(o));const r=e[ga];r&&(r.delete(t),r.size||(e[ga]=void 0))}function lv(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let jT=0;function av(e,t,r,o){const s=e._endId=++jT,c=()=>{s===e._endId&&o()};if(r!=null)return setTimeout(c,r);const{type:f,timeout:d,propCount:h}=UT(e,t);if(!f)return o();const p=f+\"end\";let g=0;const v=()=>{e.removeEventListener(p,b),c()},b=w=>{w.target===e&&++g>=h&&v()};setTimeout(()=>{g<h&&v()},d+1),e.addEventListener(p,b)}function UT(e,t){const r=window.getComputedStyle(e),o=E=>(r[E]||\"\").split(\", \"),s=o(`${Ui}Delay`),c=o(`${Ui}Duration`),f=cv(s,c),d=o(`${zl}Delay`),h=o(`${zl}Duration`),p=cv(d,h);let g=null,v=0,b=0;t===Ui?f>0&&(g=Ui,v=f,b=c.length):t===zl?p>0&&(g=zl,v=p,b=h.length):(v=Math.max(f,p),g=v>0?f>p?Ui:zl:null,b=g?g===Ui?c.length:h.length:0);const w=g===Ui&&/\\b(?:transform|all)(?:,|$)/.test(o(`${Ui}Property`).toString());return{type:g,timeout:v,propCount:b,hasTransform:w}}function cv(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max(...t.map((r,o)=>uv(r)+uv(e[o])))}function uv(e){return e===\"auto\"?0:Number(e.slice(0,-1).replace(\",\",\".\"))*1e3}function fv(e){return(e?e.ownerDocument:document).body.offsetHeight}function VT(e,t,r){const o=e[ga];o&&(t=(t?[t,...o]:[...o]).join(\" \")),t==null?e.removeAttribute(\"class\"):r?e.setAttribute(\"class\",t):e.className=t}const du=Symbol(\"_vod\"),Xb=Symbol(\"_vsh\"),ro={name:\"show\",beforeMount(e,{value:t},{transition:r}){e[du]=e.style.display===\"none\"?\"\":e.style.display,r&&t?r.beforeEnter(e):Fl(e,t)},mounted(e,{value:t},{transition:r}){r&&t&&r.enter(e)},updated(e,{value:t,oldValue:r},{transition:o}){!t!=!r&&(o?t?(o.beforeEnter(e),Fl(e,!0),o.enter(e)):o.leave(e,()=>{Fl(e,!1)}):Fl(e,t))},beforeUnmount(e,{value:t}){Fl(e,t)}};function Fl(e,t){e.style.display=t?e[du]:\"none\",e[Xb]=!t}const GT=Symbol(\"\"),KT=/(?:^|;)\\s*display\\s*:/;function XT(e,t,r){const o=e.style,s=Ht(r);let c=!1;if(r&&!s){if(t)if(Ht(t))for(const f of t.split(\";\")){const d=f.slice(0,f.indexOf(\":\")).trim();r[d]==null&&Vc(o,d,\"\")}else for(const f in t)r[f]==null&&Vc(o,f,\"\");for(const f in r)f===\"display\"&&(c=!0),Vc(o,f,r[f])}else if(s){if(t!==r){const f=o[GT];f&&(r+=\";\"+f),o.cssText=r,c=KT.test(r)}}else t&&e.removeAttribute(\"style\");du in e&&(e[du]=c?o.display:\"\",e[Xb]&&(o.display=\"none\"))}const dv=/\\s*!important$/;function Vc(e,t,r){if(Ze(r))r.forEach(o=>Vc(e,t,o));else if(r==null&&(r=\"\"),t.startsWith(\"--\"))e.setProperty(t,r);else{const o=YT(e,t);dv.test(r)?e.setProperty(Ai(o),r.replace(dv,\"\"),\"important\"):e[o]=r}}const hv=[\"Webkit\",\"Moz\",\"ms\"],wd={};function YT(e,t){const r=wd[t];if(r)return r;let o=sr(t);if(o!==\"filter\"&&o in e)return wd[t]=o;o=Fu(o);for(let s=0;s<hv.length;s++){const c=hv[s]+o;if(c in e)return wd[t]=c}return t}const pv=\"http://www.w3.org/1999/xlink\";function gv(e,t,r,o,s,c=US(t)){o&&t.startsWith(\"xlink:\")?r==null?e.removeAttributeNS(pv,t.slice(6,t.length)):e.setAttributeNS(pv,t,r):r==null||c&&!O0(r)?e.removeAttribute(t):e.setAttribute(t,c?\"\":Pr(r)?String(r):r)}function mv(e,t,r,o,s){if(t===\"innerHTML\"||t===\"textContent\"){r!=null&&(e[t]=t===\"innerHTML\"?Gb(r):r);return}const c=e.tagName;if(t===\"value\"&&c!==\"PROGRESS\"&&!c.includes(\"-\")){const d=c===\"OPTION\"?e.getAttribute(\"value\")||\"\":e.value,h=r==null?e.type===\"checkbox\"?\"on\":\"\":String(r);(d!==h||!(\"_value\"in e))&&(e.value=h),r==null&&e.removeAttribute(t),e._value=r;return}let f=!1;if(r===\"\"||r==null){const d=typeof e[t];d===\"boolean\"?r=O0(r):r==null&&d===\"string\"?(r=\"\",f=!0):d===\"number\"&&(r=0,f=!0)}try{e[t]=r}catch{}f&&e.removeAttribute(s||t)}function zo(e,t,r,o){e.addEventListener(t,r,o)}function ZT(e,t,r,o){e.removeEventListener(t,r,o)}const vv=Symbol(\"_vei\");function JT(e,t,r,o,s=null){const c=e[vv]||(e[vv]={}),f=c[t];if(o&&f)f.value=o;else{const[d,h]=QT(t);if(o){const p=c[t]=nC(o,s);zo(e,d,p,h)}else f&&(ZT(e,d,f,h),c[t]=void 0)}}const yv=/(?:Once|Passive|Capture)$/;function QT(e){let t;if(yv.test(e)){t={};let o;for(;o=e.match(yv);)e=e.slice(0,e.length-o[0].length),t[o[0].toLowerCase()]=!0}return[e[2]===\":\"?e.slice(3):Ai(e.slice(2)),t]}let xd=0;const eC=Promise.resolve(),tC=()=>xd||(eC.then(()=>xd=0),xd=Date.now());function nC(e,t){const r=o=>{if(!o._vts)o._vts=Date.now();else if(o._vts<=r.attached)return;$r(rC(o,r.value),t,5,[o])};return r.value=e,r.attached=tC(),r}function rC(e,t){if(Ze(t)){const r=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{r.call(e),e._stopped=!0},t.map(o=>s=>!s._stopped&&o&&o(s))}else return t}const bv=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,iC=(e,t,r,o,s,c)=>{const f=s===\"svg\";t===\"class\"?VT(e,o,f):t===\"style\"?XT(e,r,o):$u(t)?Hh(t)||JT(e,t,r,o,c):(t[0]===\".\"?(t=t.slice(1),!0):t[0]===\"^\"?(t=t.slice(1),!1):oC(e,t,o,f))?(mv(e,t,o),!e.tagName.includes(\"-\")&&(t===\"value\"||t===\"checked\"||t===\"selected\")&&gv(e,t,o,f,c,t!==\"value\")):e._isVueCE&&(/[A-Z]/.test(t)||!Ht(o))?mv(e,sr(t),o,c,t):(t===\"true-value\"?e._trueValue=o:t===\"false-value\"&&(e._falseValue=o),gv(e,t,o,f))};function oC(e,t,r,o){if(o)return!!(t===\"innerHTML\"||t===\"textContent\"||t in e&&bv(t)&&et(r));if(t===\"spellcheck\"||t===\"draggable\"||t===\"translate\"||t===\"autocorrect\"||t===\"sandbox\"&&e.tagName===\"IFRAME\"||t===\"form\"||t===\"list\"&&e.tagName===\"INPUT\"||t===\"type\"&&e.tagName===\"TEXTAREA\")return!1;if(t===\"width\"||t===\"height\"){const s=e.tagName;if(s===\"IMG\"||s===\"VIDEO\"||s===\"CANVAS\"||s===\"SOURCE\")return!1}return bv(t)&&Ht(r)?!1:t in e}const hu=e=>{const t=e.props[\"onUpdate:modelValue\"]||!1;return Ze(t)?r=>jc(t,r):t};function sC(e){e.target.composing=!0}function wv(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event(\"input\")))}const Fs=Symbol(\"_assign\");function xv(e,t,r){return t&&(e=e.trim()),r&&(e=Wh(e)),e}const Yb={created(e,{modifiers:{lazy:t,trim:r,number:o}},s){e[Fs]=hu(s);const c=o||s.props&&s.props.type===\"number\";zo(e,t?\"change\":\"input\",f=>{f.target.composing||e[Fs](xv(e.value,r,c))}),(r||c)&&zo(e,\"change\",()=>{e.value=xv(e.value,r,c)}),t||(zo(e,\"compositionstart\",sC),zo(e,\"compositionend\",wv),zo(e,\"change\",wv))},mounted(e,{value:t}){e.value=t??\"\"},beforeUpdate(e,{value:t,oldValue:r,modifiers:{lazy:o,trim:s,number:c}},f){if(e[Fs]=hu(f),e.composing)return;const d=(c||e.type===\"number\")&&!/^0\\d/.test(e.value)?Wh(e.value):e.value,h=t??\"\";d!==h&&(document.activeElement===e&&e.type!==\"range\"&&(o&&t===r||s&&e.value.trim()===h)||(e.value=h))}},Zb={deep:!0,created(e,t,r){e[Fs]=hu(r),zo(e,\"change\",()=>{const o=e._modelValue,s=lC(e),c=e.checked,f=e[Fs];if(Ze(o)){const d=P0(o,s),h=d!==-1;if(c&&!h)f(o.concat(s));else if(!c&&h){const p=[...o];p.splice(d,1),f(p)}}else if(Iu(o)){const d=new Set(o);c?d.add(s):d.delete(s),f(d)}else f(Jb(e,c))})},mounted:kv,beforeUpdate(e,t,r){e[Fs]=hu(r),kv(e,t,r)}};function kv(e,{value:t,oldValue:r},o){e._modelValue=t;let s;if(Ze(t))s=P0(t,o.props.value)>-1;else if(Iu(t))s=t.has(o.props.value);else{if(t===r)return;s=Bu(t,Jb(e,!0))}e.checked!==s&&(e.checked=s)}function lC(e){return\"_value\"in e?e._value:e.value}function Jb(e,t){const r=t?\"_trueValue\":\"_falseValue\";return r in e?e[r]:t}const aC=[\"ctrl\",\"shift\",\"alt\",\"meta\"],cC={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>\"button\"in e&&e.button!==0,middle:e=>\"button\"in e&&e.button!==1,right:e=>\"button\"in e&&e.button!==2,exact:(e,t)=>aC.some(r=>e[`${r}Key`]&&!t.includes(r))},Gc=(e,t)=>{const r=e._withMods||(e._withMods={}),o=t.join(\".\");return r[o]||(r[o]=((s,...c)=>{for(let f=0;f<t.length;f++){const d=cC[t[f]];if(d&&d(s,t))return}return e(s,...c)}))},uC={esc:\"escape\",space:\" \",up:\"arrow-up\",left:\"arrow-left\",right:\"arrow-right\",down:\"arrow-down\",delete:\"backspace\"},ih=(e,t)=>{const r=e._withKeys||(e._withKeys={}),o=t.join(\".\");return r[o]||(r[o]=(s=>{if(!(\"key\"in s))return;const c=Ai(s.key);if(t.some(f=>f===c||uC[f]===c))return e(s)}))},fC=on({patchProp:iC},zT);let Sv;function dC(){return Sv||(Sv=gT(fC))}const Qb=((...e)=>{const t=dC().createApp(...e),{mount:r}=t;return t.mount=o=>{const s=pC(o);if(!s)return;const c=t._component;!et(c)&&!c.render&&!c.template&&(c.template=s.innerHTML),s.nodeType===1&&(s.textContent=\"\");const f=r(s,!1,hC(s));return s instanceof Element&&(s.removeAttribute(\"v-cloak\"),s.setAttribute(\"data-v-app\",\"\")),f},t});function hC(e){if(e instanceof SVGElement)return\"svg\";if(typeof MathMLElement==\"function\"&&e instanceof MathMLElement)return\"mathml\"}function pC(e){return Ht(e)?document.querySelector(e):e}const Ni=(e,t)=>{const r=e.__vccOpts||e;for(const[o,s]of t)r[o]=s;return r},gC={};function mC(e,t){const r=Go(\"RouterView\");return ie(),Ve(r)}const vC=Ni(gC,[[\"render\",mC]]),yC=[\"top\",\"right\",\"bottom\",\"left\"],_v=[\"start\",\"end\"],Tv=yC.reduce((e,t)=>e.concat(t,t+\"-\"+_v[0],t+\"-\"+_v[1]),[]),ma=Math.min,Io=Math.max,bC={left:\"right\",right:\"left\",bottom:\"top\",top:\"bottom\"},wC={start:\"end\",end:\"start\"};function oh(e,t,r){return Io(e,ma(t,r))}function Xo(e,t){return typeof e==\"function\"?e(t):e}function Qr(e){return e.split(\"-\")[0]}function Or(e){return e.split(\"-\")[1]}function ew(e){return e===\"x\"?\"y\":\"x\"}function ip(e){return e===\"y\"?\"height\":\"width\"}function Fa(e){return[\"top\",\"bottom\"].includes(Qr(e))?\"y\":\"x\"}function op(e){return ew(Fa(e))}function tw(e,t,r){r===void 0&&(r=!1);const o=Or(e),s=op(e),c=ip(s);let f=s===\"x\"?o===(r?\"end\":\"start\")?\"right\":\"left\":o===\"start\"?\"bottom\":\"top\";return t.reference[c]>t.floating[c]&&(f=gu(f)),[f,gu(f)]}function xC(e){const t=gu(e);return[pu(e),t,pu(t)]}function pu(e){return e.replace(/start|end/g,t=>wC[t])}function kC(e,t,r){const o=[\"left\",\"right\"],s=[\"right\",\"left\"],c=[\"top\",\"bottom\"],f=[\"bottom\",\"top\"];switch(e){case\"top\":case\"bottom\":return r?t?s:o:t?o:s;case\"left\":case\"right\":return t?c:f;default:return[]}}function SC(e,t,r,o){const s=Or(e);let c=kC(Qr(e),r===\"start\",o);return s&&(c=c.map(f=>f+\"-\"+s),t&&(c=c.concat(c.map(pu)))),c}function gu(e){return e.replace(/left|right|bottom|top/g,t=>bC[t])}function _C(e){return{top:0,right:0,bottom:0,left:0,...e}}function nw(e){return typeof e!=\"number\"?_C(e):{top:e,right:e,bottom:e,left:e}}function ta(e){return{...e,top:e.y,left:e.x,right:e.x+e.width,bottom:e.y+e.height}}function Cv(e,t,r){let{reference:o,floating:s}=e;const c=Fa(t),f=op(t),d=ip(f),h=Qr(t),p=c===\"y\",g=o.x+o.width/2-s.width/2,v=o.y+o.height/2-s.height/2,b=o[d]/2-s[d]/2;let w;switch(h){case\"top\":w={x:g,y:o.y-s.height};break;case\"bottom\":w={x:g,y:o.y+o.height};break;case\"right\":w={x:o.x+o.width,y:v};break;case\"left\":w={x:o.x-s.width,y:v};break;default:w={x:o.x,y:o.y}}switch(Or(t)){case\"start\":w[f]-=b*(r&&p?-1:1);break;case\"end\":w[f]+=b*(r&&p?-1:1);break}return w}const TC=async(e,t,r)=>{const{placement:o=\"bottom\",strategy:s=\"absolute\",middleware:c=[],platform:f}=r,d=c.filter(Boolean),h=await(f.isRTL==null?void 0:f.isRTL(t));let p=await f.getElementRects({reference:e,floating:t,strategy:s}),{x:g,y:v}=Cv(p,o,h),b=o,w={},E=0;for(let L=0;L<d.length;L++){const{name:P,fn:M}=d[L],{x:R,y:I,data:_,reset:$}=await M({x:g,y:v,initialPlacement:o,placement:b,strategy:s,middlewareData:w,rects:p,platform:f,elements:{reference:e,floating:t}});g=R??g,v=I??v,w={...w,[P]:{...w[P],..._}},$&&E<=50&&(E++,typeof $==\"object\"&&($.placement&&(b=$.placement),$.rects&&(p=$.rects===!0?await f.getElementRects({reference:e,floating:t,strategy:s}):$.rects),{x:g,y:v}=Cv(p,b,h)),L=-1)}return{x:g,y:v,placement:b,strategy:s,middlewareData:w}};async function ef(e,t){var r;t===void 0&&(t={});const{x:o,y:s,platform:c,rects:f,elements:d,strategy:h}=e,{boundary:p=\"clippingAncestors\",rootBoundary:g=\"viewport\",elementContext:v=\"floating\",altBoundary:b=!1,padding:w=0}=Xo(t,e),E=nw(w),P=d[b?v===\"floating\"?\"reference\":\"floating\":v],M=ta(await c.getClippingRect({element:(r=await(c.isElement==null?void 0:c.isElement(P)))==null||r?P:P.contextElement||await(c.getDocumentElement==null?void 0:c.getDocumentElement(d.floating)),boundary:p,rootBoundary:g,strategy:h})),R=v===\"floating\"?{...f.floating,x:o,y:s}:f.reference,I=await(c.getOffsetParent==null?void 0:c.getOffsetParent(d.floating)),_=await(c.isElement==null?void 0:c.isElement(I))?await(c.getScale==null?void 0:c.getScale(I))||{x:1,y:1}:{x:1,y:1},$=ta(c.convertOffsetParentRelativeRectToViewportRelativeRect?await c.convertOffsetParentRelativeRectToViewportRelativeRect({elements:d,rect:R,offsetParent:I,strategy:h}):R);return{top:(M.top-$.top+E.top)/_.y,bottom:($.bottom-M.bottom+E.bottom)/_.y,left:(M.left-$.left+E.left)/_.x,right:($.right-M.right+E.right)/_.x}}const CC=e=>({name:\"arrow\",options:e,async fn(t){const{x:r,y:o,placement:s,rects:c,platform:f,elements:d,middlewareData:h}=t,{element:p,padding:g=0}=Xo(e,t)||{};if(p==null)return{};const v=nw(g),b={x:r,y:o},w=op(s),E=ip(w),L=await f.getDimensions(p),P=w===\"y\",M=P?\"top\":\"left\",R=P?\"bottom\":\"right\",I=P?\"clientHeight\":\"clientWidth\",_=c.reference[E]+c.reference[w]-b[w]-c.floating[E],$=b[w]-c.reference[w],W=await(f.getOffsetParent==null?void 0:f.getOffsetParent(p));let ne=W?W[I]:0;(!ne||!await(f.isElement==null?void 0:f.isElement(W)))&&(ne=d.floating[I]||c.floating[E]);const ee=_/2-$/2,Z=ne/2-L[E]/2-1,G=ma(v[M],Z),j=ma(v[R],Z),N=G,O=ne-L[E]-j,C=ne/2-L[E]/2+ee,k=oh(N,C,O),z=!h.arrow&&Or(s)!=null&&C!==k&&c.reference[E]/2-(C<N?G:j)-L[E]/2<0,B=z?C<N?C-N:C-O:0;return{[w]:b[w]+B,data:{[w]:k,centerOffset:C-k-B,...z&&{alignmentOffset:B}},reset:z}}});function EC(e,t,r){return(e?[...r.filter(s=>Or(s)===e),...r.filter(s=>Or(s)!==e)]:r.filter(s=>Qr(s)===s)).filter(s=>e?Or(s)===e||(t?pu(s)!==s:!1):!0)}const AC=function(e){return e===void 0&&(e={}),{name:\"autoPlacement\",options:e,async fn(t){var r,o,s;const{rects:c,middlewareData:f,placement:d,platform:h,elements:p}=t,{crossAxis:g=!1,alignment:v,allowedPlacements:b=Tv,autoAlignment:w=!0,...E}=Xo(e,t),L=v!==void 0||b===Tv?EC(v||null,w,b):b,P=await ef(t,E),M=((r=f.autoPlacement)==null?void 0:r.index)||0,R=L[M];if(R==null)return{};const I=tw(R,c,await(h.isRTL==null?void 0:h.isRTL(p.floating)));if(d!==R)return{reset:{placement:L[0]}};const _=[P[Qr(R)],P[I[0]],P[I[1]]],$=[...((o=f.autoPlacement)==null?void 0:o.overflows)||[],{placement:R,overflows:_}],W=L[M+1];if(W)return{data:{index:M+1,overflows:$},reset:{placement:W}};const ne=$.map(G=>{const j=Or(G.placement);return[G.placement,j&&g?G.overflows.slice(0,2).reduce((N,O)=>N+O,0):G.overflows[0],G.overflows]}).sort((G,j)=>G[1]-j[1]),Z=((s=ne.filter(G=>G[2].slice(0,Or(G[0])?2:3).every(j=>j<=0))[0])==null?void 0:s[0])||ne[0][0];return Z!==d?{data:{index:M+1,overflows:$},reset:{placement:Z}}:{}}}},LC=function(e){return e===void 0&&(e={}),{name:\"flip\",options:e,async fn(t){var r,o;const{placement:s,middlewareData:c,rects:f,initialPlacement:d,platform:h,elements:p}=t,{mainAxis:g=!0,crossAxis:v=!0,fallbackPlacements:b,fallbackStrategy:w=\"bestFit\",fallbackAxisSideDirection:E=\"none\",flipAlignment:L=!0,...P}=Xo(e,t);if((r=c.arrow)!=null&&r.alignmentOffset)return{};const M=Qr(s),R=Qr(d)===d,I=await(h.isRTL==null?void 0:h.isRTL(p.floating)),_=b||(R||!L?[gu(d)]:xC(d));!b&&E!==\"none\"&&_.push(...SC(d,L,E,I));const $=[d,..._],W=await ef(t,P),ne=[];let ee=((o=c.flip)==null?void 0:o.overflows)||[];if(g&&ne.push(W[M]),v){const N=tw(s,f,I);ne.push(W[N[0]],W[N[1]])}if(ee=[...ee,{placement:s,overflows:ne}],!ne.every(N=>N<=0)){var Z,G;const N=(((Z=c.flip)==null?void 0:Z.index)||0)+1,O=$[N];if(O)return{data:{index:N,overflows:ee},reset:{placement:O}};let C=(G=ee.filter(k=>k.overflows[0]<=0).sort((k,z)=>k.overflows[1]-z.overflows[1])[0])==null?void 0:G.placement;if(!C)switch(w){case\"bestFit\":{var j;const k=(j=ee.map(z=>[z.placement,z.overflows.filter(B=>B>0).reduce((B,ce)=>B+ce,0)]).sort((z,B)=>z[1]-B[1])[0])==null?void 0:j[0];k&&(C=k);break}case\"initialPlacement\":C=d;break}if(s!==C)return{reset:{placement:C}}}return{}}}};async function MC(e,t){const{placement:r,platform:o,elements:s}=e,c=await(o.isRTL==null?void 0:o.isRTL(s.floating)),f=Qr(r),d=Or(r),h=Fa(r)===\"y\",p=[\"left\",\"top\"].includes(f)?-1:1,g=c&&h?-1:1,v=Xo(t,e);let{mainAxis:b,crossAxis:w,alignmentAxis:E}=typeof v==\"number\"?{mainAxis:v,crossAxis:0,alignmentAxis:null}:{mainAxis:0,crossAxis:0,alignmentAxis:null,...v};return d&&typeof E==\"number\"&&(w=d===\"end\"?E*-1:E),h?{x:w*g,y:b*p}:{x:b*p,y:w*g}}const NC=function(e){return e===void 0&&(e=0),{name:\"offset\",options:e,async fn(t){var r,o;const{x:s,y:c,placement:f,middlewareData:d}=t,h=await MC(t,e);return f===((r=d.offset)==null?void 0:r.placement)&&(o=d.arrow)!=null&&o.alignmentOffset?{}:{x:s+h.x,y:c+h.y,data:{...h,placement:f}}}}},OC=function(e){return e===void 0&&(e={}),{name:\"shift\",options:e,async fn(t){const{x:r,y:o,placement:s}=t,{mainAxis:c=!0,crossAxis:f=!1,limiter:d={fn:P=>{let{x:M,y:R}=P;return{x:M,y:R}}},...h}=Xo(e,t),p={x:r,y:o},g=await ef(t,h),v=Fa(Qr(s)),b=ew(v);let w=p[b],E=p[v];if(c){const P=b===\"y\"?\"top\":\"left\",M=b===\"y\"?\"bottom\":\"right\",R=w+g[P],I=w-g[M];w=oh(R,w,I)}if(f){const P=v===\"y\"?\"top\":\"left\",M=v===\"y\"?\"bottom\":\"right\",R=E+g[P],I=E-g[M];E=oh(R,E,I)}const L=d.fn({...t,[b]:w,[v]:E});return{...L,data:{x:L.x-r,y:L.y-o}}}}},PC=function(e){return e===void 0&&(e={}),{name:\"size\",options:e,async fn(t){const{placement:r,rects:o,platform:s,elements:c}=t,{apply:f=()=>{},...d}=Xo(e,t),h=await ef(t,d),p=Qr(r),g=Or(r),v=Fa(r)===\"y\",{width:b,height:w}=o.floating;let E,L;p===\"top\"||p===\"bottom\"?(E=p,L=g===(await(s.isRTL==null?void 0:s.isRTL(c.floating))?\"start\":\"end\")?\"left\":\"right\"):(L=p,E=g===\"end\"?\"top\":\"bottom\");const P=w-h[E],M=b-h[L],R=!t.middlewareData.shift;let I=P,_=M;if(v){const W=b-h.left-h.right;_=g||R?ma(M,W):W}else{const W=w-h.top-h.bottom;I=g||R?ma(P,W):W}if(R&&!g){const W=Io(h.left,0),ne=Io(h.right,0),ee=Io(h.top,0),Z=Io(h.bottom,0);v?_=b-2*(W!==0||ne!==0?W+ne:Io(h.left,h.right)):I=w-2*(ee!==0||Z!==0?ee+Z:Io(h.top,h.bottom))}await f({...t,availableWidth:_,availableHeight:I});const $=await s.getDimensions(c.floating);return b!==$.width||w!==$.height?{reset:{rects:!0}}:{}}}};function hr(e){var t;return((t=e.ownerDocument)==null?void 0:t.defaultView)||window}function Yr(e){return hr(e).getComputedStyle(e)}const Ev=Math.min,na=Math.max,mu=Math.round;function rw(e){const t=Yr(e);let r=parseFloat(t.width),o=parseFloat(t.height);const s=e.offsetWidth,c=e.offsetHeight,f=mu(r)!==s||mu(o)!==c;return f&&(r=s,o=c),{width:r,height:o,fallback:f}}function fo(e){return ow(e)?(e.nodeName||\"\").toLowerCase():\"\"}let Lc;function iw(){if(Lc)return Lc;const e=navigator.userAgentData;return e&&Array.isArray(e.brands)?(Lc=e.brands.map((t=>t.brand+\"/\"+t.version)).join(\" \"),Lc):navigator.userAgent}function Zr(e){return e instanceof hr(e).HTMLElement}function so(e){return e instanceof hr(e).Element}function ow(e){return e instanceof hr(e).Node}function Av(e){return typeof ShadowRoot>\"u\"?!1:e instanceof hr(e).ShadowRoot||e instanceof ShadowRoot}function tf(e){const{overflow:t,overflowX:r,overflowY:o,display:s}=Yr(e);return/auto|scroll|overlay|hidden|clip/.test(t+o+r)&&![\"inline\",\"contents\"].includes(s)}function RC(e){return[\"table\",\"td\",\"th\"].includes(fo(e))}function sh(e){const t=/firefox/i.test(iw()),r=Yr(e),o=r.backdropFilter||r.WebkitBackdropFilter;return r.transform!==\"none\"||r.perspective!==\"none\"||!!o&&o!==\"none\"||t&&r.willChange===\"filter\"||t&&!!r.filter&&r.filter!==\"none\"||[\"transform\",\"perspective\"].some((s=>r.willChange.includes(s)))||[\"paint\",\"layout\",\"strict\",\"content\"].some((s=>{const c=r.contain;return c!=null&&c.includes(s)}))}function sw(){return!/^((?!chrome|android).)*safari/i.test(iw())}function sp(e){return[\"html\",\"body\",\"#document\"].includes(fo(e))}function lw(e){return so(e)?e:e.contextElement}const aw={x:1,y:1};function Hs(e){const t=lw(e);if(!Zr(t))return aw;const r=t.getBoundingClientRect(),{width:o,height:s,fallback:c}=rw(t);let f=(c?mu(r.width):r.width)/o,d=(c?mu(r.height):r.height)/s;return f&&Number.isFinite(f)||(f=1),d&&Number.isFinite(d)||(d=1),{x:f,y:d}}function va(e,t,r,o){var s,c;t===void 0&&(t=!1),r===void 0&&(r=!1);const f=e.getBoundingClientRect(),d=lw(e);let h=aw;t&&(o?so(o)&&(h=Hs(o)):h=Hs(e));const p=d?hr(d):window,g=!sw()&&r;let v=(f.left+(g&&((s=p.visualViewport)==null?void 0:s.offsetLeft)||0))/h.x,b=(f.top+(g&&((c=p.visualViewport)==null?void 0:c.offsetTop)||0))/h.y,w=f.width/h.x,E=f.height/h.y;if(d){const L=hr(d),P=o&&so(o)?hr(o):o;let M=L.frameElement;for(;M&&o&&P!==L;){const R=Hs(M),I=M.getBoundingClientRect(),_=getComputedStyle(M);I.x+=(M.clientLeft+parseFloat(_.paddingLeft))*R.x,I.y+=(M.clientTop+parseFloat(_.paddingTop))*R.y,v*=R.x,b*=R.y,w*=R.x,E*=R.y,v+=I.x,b+=I.y,M=hr(M).frameElement}}return{width:w,height:E,top:b,right:v+w,bottom:b+E,left:v,x:v,y:b}}function lo(e){return((ow(e)?e.ownerDocument:e.document)||window.document).documentElement}function nf(e){return so(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function cw(e){return va(lo(e)).left+nf(e).scrollLeft}function ya(e){if(fo(e)===\"html\")return e;const t=e.assignedSlot||e.parentNode||Av(e)&&e.host||lo(e);return Av(t)?t.host:t}function uw(e){const t=ya(e);return sp(t)?t.ownerDocument.body:Zr(t)&&tf(t)?t:uw(t)}function vu(e,t){var r;t===void 0&&(t=[]);const o=uw(e),s=o===((r=e.ownerDocument)==null?void 0:r.body),c=hr(o);return s?t.concat(c,c.visualViewport||[],tf(o)?o:[]):t.concat(o,vu(o))}function Lv(e,t,r){return t===\"viewport\"?ta((function(o,s){const c=hr(o),f=lo(o),d=c.visualViewport;let h=f.clientWidth,p=f.clientHeight,g=0,v=0;if(d){h=d.width,p=d.height;const b=sw();(b||!b&&s===\"fixed\")&&(g=d.offsetLeft,v=d.offsetTop)}return{width:h,height:p,x:g,y:v}})(e,r)):so(t)?ta((function(o,s){const c=va(o,!0,s===\"fixed\"),f=c.top+o.clientTop,d=c.left+o.clientLeft,h=Zr(o)?Hs(o):{x:1,y:1};return{width:o.clientWidth*h.x,height:o.clientHeight*h.y,x:d*h.x,y:f*h.y}})(t,r)):ta((function(o){const s=lo(o),c=nf(o),f=o.ownerDocument.body,d=na(s.scrollWidth,s.clientWidth,f.scrollWidth,f.clientWidth),h=na(s.scrollHeight,s.clientHeight,f.scrollHeight,f.clientHeight);let p=-c.scrollLeft+cw(o);const g=-c.scrollTop;return Yr(f).direction===\"rtl\"&&(p+=na(s.clientWidth,f.clientWidth)-d),{width:d,height:h,x:p,y:g}})(lo(e)))}function Mv(e){return Zr(e)&&Yr(e).position!==\"fixed\"?e.offsetParent:null}function Nv(e){const t=hr(e);let r=Mv(e);for(;r&&RC(r)&&Yr(r).position===\"static\";)r=Mv(r);return r&&(fo(r)===\"html\"||fo(r)===\"body\"&&Yr(r).position===\"static\"&&!sh(r))?t:r||(function(o){let s=ya(o);for(;Zr(s)&&!sp(s);){if(sh(s))return s;s=ya(s)}return null})(e)||t}function $C(e,t,r){const o=Zr(t),s=lo(t),c=va(e,!0,r===\"fixed\",t);let f={scrollLeft:0,scrollTop:0};const d={x:0,y:0};if(o||!o&&r!==\"fixed\")if((fo(t)!==\"body\"||tf(s))&&(f=nf(t)),Zr(t)){const h=va(t,!0);d.x=h.x+t.clientLeft,d.y=h.y+t.clientTop}else s&&(d.x=cw(s));return{x:c.left+f.scrollLeft-d.x,y:c.top+f.scrollTop-d.y,width:c.width,height:c.height}}const IC={getClippingRect:function(e){let{element:t,boundary:r,rootBoundary:o,strategy:s}=e;const c=r===\"clippingAncestors\"?(function(p,g){const v=g.get(p);if(v)return v;let b=vu(p).filter((P=>so(P)&&fo(P)!==\"body\")),w=null;const E=Yr(p).position===\"fixed\";let L=E?ya(p):p;for(;so(L)&&!sp(L);){const P=Yr(L),M=sh(L);(E?M||w:M||P.position!==\"static\"||!w||![\"absolute\",\"fixed\"].includes(w.position))?w=P:b=b.filter((R=>R!==L)),L=ya(L)}return g.set(p,b),b})(t,this._c):[].concat(r),f=[...c,o],d=f[0],h=f.reduce(((p,g)=>{const v=Lv(t,g,s);return p.top=na(v.top,p.top),p.right=Ev(v.right,p.right),p.bottom=Ev(v.bottom,p.bottom),p.left=na(v.left,p.left),p}),Lv(t,d,s));return{width:h.right-h.left,height:h.bottom-h.top,x:h.left,y:h.top}},convertOffsetParentRelativeRectToViewportRelativeRect:function(e){let{rect:t,offsetParent:r,strategy:o}=e;const s=Zr(r),c=lo(r);if(r===c)return t;let f={scrollLeft:0,scrollTop:0},d={x:1,y:1};const h={x:0,y:0};if((s||!s&&o!==\"fixed\")&&((fo(r)!==\"body\"||tf(c))&&(f=nf(r)),Zr(r))){const p=va(r);d=Hs(r),h.x=p.x+r.clientLeft,h.y=p.y+r.clientTop}return{width:t.width*d.x,height:t.height*d.y,x:t.x*d.x-f.scrollLeft*d.x+h.x,y:t.y*d.y-f.scrollTop*d.y+h.y}},isElement:so,getDimensions:function(e){return Zr(e)?rw(e):e.getBoundingClientRect()},getOffsetParent:Nv,getDocumentElement:lo,getScale:Hs,async getElementRects(e){let{reference:t,floating:r,strategy:o}=e;const s=this.getOffsetParent||Nv,c=this.getDimensions;return{reference:$C(t,await s(r),o),floating:{x:0,y:0,...await c(r)}}},getClientRects:e=>Array.from(e.getClientRects()),isRTL:e=>Yr(e).direction===\"rtl\"},DC=(e,t,r)=>{const o=new Map,s={platform:IC,...r},c={...s.platform,_c:o};return TC(e,t,{...s,platform:c})},ao={disabled:!1,distance:5,skidding:0,container:\"body\",boundary:void 0,instantMove:!1,disposeTimeout:150,popperTriggers:[],strategy:\"absolute\",preventOverflow:!0,flip:!0,shift:!0,overflowPadding:0,arrowPadding:0,arrowOverflow:!0,autoHideOnMousedown:!1,themes:{tooltip:{placement:\"top\",triggers:[\"hover\",\"focus\",\"touch\"],hideTriggers:e=>[...e,\"click\"],delay:{show:200,hide:0},handleResize:!1,html:!1,loadingContent:\"...\"},dropdown:{placement:\"bottom\",triggers:[\"click\"],delay:0,handleResize:!0,autoHide:!0},menu:{$extend:\"dropdown\",triggers:[\"hover\",\"focus\"],popperTriggers:[\"hover\"],delay:{show:0,hide:400}}}};function ba(e,t){let r=ao.themes[e]||{},o;do o=r[t],typeof o>\"u\"?r.$extend?r=ao.themes[r.$extend]||{}:(r=null,o=ao[t]):r=null;while(r);return o}function zC(e){const t=[e];let r=ao.themes[e]||{};do r.$extend&&!r.$resetCss?(t.push(r.$extend),r=ao.themes[r.$extend]||{}):r=null;while(r);return t.map(o=>`v-popper--theme-${o}`)}function Ov(e){const t=[e];let r=ao.themes[e]||{};do r.$extend?(t.push(r.$extend),r=ao.themes[r.$extend]||{}):r=null;while(r);return t}let wa=!1;if(typeof window<\"u\"){wa=!1;try{const e=Object.defineProperty({},\"passive\",{get(){wa=!0}});window.addEventListener(\"test\",null,e)}catch{}}let fw=!1;typeof window<\"u\"&&typeof navigator<\"u\"&&(fw=/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream);const dw=[\"auto\",\"top\",\"bottom\",\"left\",\"right\"].reduce((e,t)=>e.concat([t,`${t}-start`,`${t}-end`]),[]),Pv={hover:\"mouseenter\",focus:\"focus\",click:\"click\",touch:\"touchstart\",pointer:\"pointerdown\"},Rv={hover:\"mouseleave\",focus:\"blur\",click:\"click\",touch:\"touchend\",pointer:\"pointerup\"};function $v(e,t){const r=e.indexOf(t);r!==-1&&e.splice(r,1)}function kd(){return new Promise(e=>requestAnimationFrame(()=>{requestAnimationFrame(e)}))}const nr=[];let Ro=null;const Iv={};function Dv(e){let t=Iv[e];return t||(t=Iv[e]=[]),t}let lh=function(){};typeof window<\"u\"&&(lh=window.Element);function ht(e){return function(t){return ba(t.theme,e)}}const Sd=\"__floating-vue__popper\",hw=()=>rt({name:\"VPopper\",provide(){return{[Sd]:{parentPopper:this}}},inject:{[Sd]:{default:null}},props:{theme:{type:String,required:!0},targetNodes:{type:Function,required:!0},referenceNode:{type:Function,default:null},popperNode:{type:Function,required:!0},shown:{type:Boolean,default:!1},showGroup:{type:String,default:null},ariaId:{default:null},disabled:{type:Boolean,default:ht(\"disabled\")},positioningDisabled:{type:Boolean,default:ht(\"positioningDisabled\")},placement:{type:String,default:ht(\"placement\"),validator:e=>dw.includes(e)},delay:{type:[String,Number,Object],default:ht(\"delay\")},distance:{type:[Number,String],default:ht(\"distance\")},skidding:{type:[Number,String],default:ht(\"skidding\")},triggers:{type:Array,default:ht(\"triggers\")},showTriggers:{type:[Array,Function],default:ht(\"showTriggers\")},hideTriggers:{type:[Array,Function],default:ht(\"hideTriggers\")},popperTriggers:{type:Array,default:ht(\"popperTriggers\")},popperShowTriggers:{type:[Array,Function],default:ht(\"popperShowTriggers\")},popperHideTriggers:{type:[Array,Function],default:ht(\"popperHideTriggers\")},container:{type:[String,Object,lh,Boolean],default:ht(\"container\")},boundary:{type:[String,lh],default:ht(\"boundary\")},strategy:{type:String,validator:e=>[\"absolute\",\"fixed\"].includes(e),default:ht(\"strategy\")},autoHide:{type:[Boolean,Function],default:ht(\"autoHide\")},handleResize:{type:Boolean,default:ht(\"handleResize\")},instantMove:{type:Boolean,default:ht(\"instantMove\")},eagerMount:{type:Boolean,default:ht(\"eagerMount\")},popperClass:{type:[String,Array,Object],default:ht(\"popperClass\")},computeTransformOrigin:{type:Boolean,default:ht(\"computeTransformOrigin\")},autoMinSize:{type:Boolean,default:ht(\"autoMinSize\")},autoSize:{type:[Boolean,String],default:ht(\"autoSize\")},autoMaxSize:{type:Boolean,default:ht(\"autoMaxSize\")},autoBoundaryMaxSize:{type:Boolean,default:ht(\"autoBoundaryMaxSize\")},preventOverflow:{type:Boolean,default:ht(\"preventOverflow\")},overflowPadding:{type:[Number,String],default:ht(\"overflowPadding\")},arrowPadding:{type:[Number,String],default:ht(\"arrowPadding\")},arrowOverflow:{type:Boolean,default:ht(\"arrowOverflow\")},flip:{type:Boolean,default:ht(\"flip\")},shift:{type:Boolean,default:ht(\"shift\")},shiftCrossAxis:{type:Boolean,default:ht(\"shiftCrossAxis\")},noAutoFocus:{type:Boolean,default:ht(\"noAutoFocus\")},disposeTimeout:{type:Number,default:ht(\"disposeTimeout\")}},emits:{show:()=>!0,hide:()=>!0,\"update:shown\":e=>!0,\"apply-show\":()=>!0,\"apply-hide\":()=>!0,\"close-group\":()=>!0,\"close-directive\":()=>!0,\"auto-hide\":()=>!0,resize:()=>!0},data(){return{isShown:!1,isMounted:!1,skipTransition:!1,classes:{showFrom:!1,showTo:!1,hideFrom:!1,hideTo:!0},result:{x:0,y:0,placement:\"\",strategy:this.strategy,arrow:{x:0,y:0,centerOffset:0},transformOrigin:null},randomId:`popper_${[Math.random(),Date.now()].map(e=>e.toString(36).substring(2,10)).join(\"_\")}`,shownChildren:new Set,lastAutoHide:!0,pendingHide:!1,containsGlobalTarget:!1,isDisposed:!0,mouseDownContains:!1}},computed:{popperId(){return this.ariaId!=null?this.ariaId:this.randomId},shouldMountContent(){return this.eagerMount||this.isMounted},slotData(){return{popperId:this.popperId,isShown:this.isShown,shouldMountContent:this.shouldMountContent,skipTransition:this.skipTransition,autoHide:typeof this.autoHide==\"function\"?this.lastAutoHide:this.autoHide,show:this.show,hide:this.hide,handleResize:this.handleResize,onResize:this.onResize,classes:{...this.classes,popperClass:this.popperClass},result:this.positioningDisabled?null:this.result,attrs:this.$attrs}},parentPopper(){var e;return(e=this[Sd])==null?void 0:e.parentPopper},hasPopperShowTriggerHover(){var e,t;return((e=this.popperTriggers)==null?void 0:e.includes(\"hover\"))||((t=this.popperShowTriggers)==null?void 0:t.includes(\"hover\"))}},watch:{shown:\"$_autoShowHide\",disabled(e){e?this.dispose():this.init()},async container(){this.isShown&&(this.$_ensureTeleport(),await this.$_computePosition())},triggers:{handler:\"$_refreshListeners\",deep:!0},positioningDisabled:\"$_refreshListeners\",...[\"placement\",\"distance\",\"skidding\",\"boundary\",\"strategy\",\"overflowPadding\",\"arrowPadding\",\"preventOverflow\",\"shift\",\"shiftCrossAxis\",\"flip\"].reduce((e,t)=>(e[t]=\"$_computePosition\",e),{})},created(){this.autoMinSize&&console.warn('[floating-vue] `autoMinSize` option is deprecated. Use `autoSize=\"min\"` instead.'),this.autoMaxSize&&console.warn(\"[floating-vue] `autoMaxSize` option is deprecated. Use `autoBoundaryMaxSize` instead.\")},mounted(){this.init(),this.$_detachPopperNode()},activated(){this.$_autoShowHide()},deactivated(){this.hide()},beforeUnmount(){this.dispose()},methods:{show({event:e=null,skipDelay:t=!1,force:r=!1}={}){var o,s;(o=this.parentPopper)!=null&&o.lockedChild&&this.parentPopper.lockedChild!==this||(this.pendingHide=!1,(r||!this.disabled)&&(((s=this.parentPopper)==null?void 0:s.lockedChild)===this&&(this.parentPopper.lockedChild=null),this.$_scheduleShow(e,t),this.$emit(\"show\"),this.$_showFrameLocked=!0,requestAnimationFrame(()=>{this.$_showFrameLocked=!1})),this.$emit(\"update:shown\",!0))},hide({event:e=null,skipDelay:t=!1}={}){var r;if(!this.$_hideInProgress){if(this.shownChildren.size>0){this.pendingHide=!0;return}if(this.hasPopperShowTriggerHover&&this.$_isAimingPopper()){this.parentPopper&&(this.parentPopper.lockedChild=this,clearTimeout(this.parentPopper.lockedChildTimer),this.parentPopper.lockedChildTimer=setTimeout(()=>{this.parentPopper.lockedChild===this&&(this.parentPopper.lockedChild.hide({skipDelay:t}),this.parentPopper.lockedChild=null)},1e3));return}((r=this.parentPopper)==null?void 0:r.lockedChild)===this&&(this.parentPopper.lockedChild=null),this.pendingHide=!1,this.$_scheduleHide(e,t),this.$emit(\"hide\"),this.$emit(\"update:shown\",!1)}},init(){var e;this.isDisposed&&(this.isDisposed=!1,this.isMounted=!1,this.$_events=[],this.$_preventShow=!1,this.$_referenceNode=((e=this.referenceNode)==null?void 0:e.call(this))??this.$el,this.$_targetNodes=this.targetNodes().filter(t=>t.nodeType===t.ELEMENT_NODE),this.$_popperNode=this.popperNode(),this.$_innerNode=this.$_popperNode.querySelector(\".v-popper__inner\"),this.$_arrowNode=this.$_popperNode.querySelector(\".v-popper__arrow-container\"),this.$_swapTargetAttrs(\"title\",\"data-original-title\"),this.$_detachPopperNode(),this.triggers.length&&this.$_addEventListeners(),this.shown&&this.show())},dispose(){this.isDisposed||(this.isDisposed=!0,this.$_removeEventListeners(),this.hide({skipDelay:!0}),this.$_detachPopperNode(),this.isMounted=!1,this.isShown=!1,this.$_updateParentShownChildren(!1),this.$_swapTargetAttrs(\"data-original-title\",\"title\"))},async onResize(){this.isShown&&(await this.$_computePosition(),this.$emit(\"resize\"))},async $_computePosition(){if(this.isDisposed||this.positioningDisabled)return;const e={strategy:this.strategy,middleware:[]};(this.distance||this.skidding)&&e.middleware.push(NC({mainAxis:this.distance,crossAxis:this.skidding}));const t=this.placement.startsWith(\"auto\");if(t?e.middleware.push(AC({alignment:this.placement.split(\"-\")[1]??\"\"})):e.placement=this.placement,this.preventOverflow&&(this.shift&&e.middleware.push(OC({padding:this.overflowPadding,boundary:this.boundary,crossAxis:this.shiftCrossAxis})),!t&&this.flip&&e.middleware.push(LC({padding:this.overflowPadding,boundary:this.boundary}))),e.middleware.push(CC({element:this.$_arrowNode,padding:this.arrowPadding})),this.arrowOverflow&&e.middleware.push({name:\"arrowOverflow\",fn:({placement:o,rects:s,middlewareData:c})=>{let f;const{centerOffset:d}=c.arrow;return o.startsWith(\"top\")||o.startsWith(\"bottom\")?f=Math.abs(d)>s.reference.width/2:f=Math.abs(d)>s.reference.height/2,{data:{overflow:f}}}}),this.autoMinSize||this.autoSize){const o=this.autoSize?this.autoSize:this.autoMinSize?\"min\":null;e.middleware.push({name:\"autoSize\",fn:({rects:s,placement:c,middlewareData:f})=>{var d;if((d=f.autoSize)!=null&&d.skip)return{};let h,p;return c.startsWith(\"top\")||c.startsWith(\"bottom\")?h=s.reference.width:p=s.reference.height,this.$_innerNode.style[o===\"min\"?\"minWidth\":o===\"max\"?\"maxWidth\":\"width\"]=h!=null?`${h}px`:null,this.$_innerNode.style[o===\"min\"?\"minHeight\":o===\"max\"?\"maxHeight\":\"height\"]=p!=null?`${p}px`:null,{data:{skip:!0},reset:{rects:!0}}}})}(this.autoMaxSize||this.autoBoundaryMaxSize)&&(this.$_innerNode.style.maxWidth=null,this.$_innerNode.style.maxHeight=null,e.middleware.push(PC({boundary:this.boundary,padding:this.overflowPadding,apply:({availableWidth:o,availableHeight:s})=>{this.$_innerNode.style.maxWidth=o!=null?`${o}px`:null,this.$_innerNode.style.maxHeight=s!=null?`${s}px`:null}})));const r=await DC(this.$_referenceNode,this.$_popperNode,e);Object.assign(this.result,{x:r.x,y:r.y,placement:r.placement,strategy:r.strategy,arrow:{...r.middlewareData.arrow,...r.middlewareData.arrowOverflow}})},$_scheduleShow(e,t=!1){if(this.$_updateParentShownChildren(!0),this.$_hideInProgress=!1,clearTimeout(this.$_scheduleTimer),Ro&&this.instantMove&&Ro.instantMove&&Ro!==this.parentPopper){Ro.$_applyHide(!0),this.$_applyShow(!0);return}t?this.$_applyShow():this.$_scheduleTimer=setTimeout(this.$_applyShow.bind(this),this.$_computeDelay(\"show\"))},$_scheduleHide(e,t=!1){if(this.shownChildren.size>0){this.pendingHide=!0;return}this.$_updateParentShownChildren(!1),this.$_hideInProgress=!0,clearTimeout(this.$_scheduleTimer),this.isShown&&(Ro=this),t?this.$_applyHide():this.$_scheduleTimer=setTimeout(this.$_applyHide.bind(this),this.$_computeDelay(\"hide\"))},$_computeDelay(e){const t=this.delay;return parseInt(t&&t[e]||t||0)},async $_applyShow(e=!1){clearTimeout(this.$_disposeTimer),clearTimeout(this.$_scheduleTimer),this.skipTransition=e,!this.isShown&&(this.$_ensureTeleport(),await kd(),await this.$_computePosition(),await this.$_applyShowEffect(),this.positioningDisabled||this.$_registerEventListeners([...vu(this.$_referenceNode),...vu(this.$_popperNode)],\"scroll\",()=>{this.$_computePosition()}))},async $_applyShowEffect(){if(this.$_hideInProgress)return;if(this.computeTransformOrigin){const t=this.$_referenceNode.getBoundingClientRect(),r=this.$_popperNode.querySelector(\".v-popper__wrapper\"),o=r.parentNode.getBoundingClientRect(),s=t.x+t.width/2-(o.left+r.offsetLeft),c=t.y+t.height/2-(o.top+r.offsetTop);this.result.transformOrigin=`${s}px ${c}px`}this.isShown=!0,this.$_applyAttrsToTarget({\"aria-describedby\":this.popperId,\"data-popper-shown\":\"\"});const e=this.showGroup;if(e){let t;for(let r=0;r<nr.length;r++)t=nr[r],t.showGroup!==e&&(t.hide(),t.$emit(\"close-group\"))}nr.push(this),document.body.classList.add(\"v-popper--some-open\");for(const t of Ov(this.theme))Dv(t).push(this),document.body.classList.add(`v-popper--some-open--${t}`);this.$emit(\"apply-show\"),this.classes.showFrom=!0,this.classes.showTo=!1,this.classes.hideFrom=!1,this.classes.hideTo=!1,await kd(),this.classes.showFrom=!1,this.classes.showTo=!0,this.noAutoFocus||this.$_popperNode.focus()},async $_applyHide(e=!1){if(this.shownChildren.size>0){this.pendingHide=!0,this.$_hideInProgress=!1;return}if(clearTimeout(this.$_scheduleTimer),!this.isShown)return;this.skipTransition=e,$v(nr,this),nr.length===0&&document.body.classList.remove(\"v-popper--some-open\");for(const r of Ov(this.theme)){const o=Dv(r);$v(o,this),o.length===0&&document.body.classList.remove(`v-popper--some-open--${r}`)}Ro===this&&(Ro=null),this.isShown=!1,this.$_applyAttrsToTarget({\"aria-describedby\":void 0,\"data-popper-shown\":void 0}),clearTimeout(this.$_disposeTimer);const t=this.disposeTimeout;t!==null&&(this.$_disposeTimer=setTimeout(()=>{this.$_popperNode&&(this.$_detachPopperNode(),this.isMounted=!1)},t)),this.$_removeEventListeners(\"scroll\"),this.$emit(\"apply-hide\"),this.classes.showFrom=!1,this.classes.showTo=!1,this.classes.hideFrom=!0,this.classes.hideTo=!1,await kd(),this.classes.hideFrom=!1,this.classes.hideTo=!0},$_autoShowHide(){this.shown?this.show():this.hide()},$_ensureTeleport(){if(this.isDisposed)return;let e=this.container;if(typeof e==\"string\"?e=window.document.querySelector(e):e===!1&&(e=this.$_targetNodes[0].parentNode),!e)throw new Error(\"No container for popover: \"+this.container);e.appendChild(this.$_popperNode),this.isMounted=!0},$_addEventListeners(){const e=r=>{this.isShown&&!this.$_hideInProgress||(r.usedByTooltip=!0,!this.$_preventShow&&this.show({event:r}))};this.$_registerTriggerListeners(this.$_targetNodes,Pv,this.triggers,this.showTriggers,e),this.$_registerTriggerListeners([this.$_popperNode],Pv,this.popperTriggers,this.popperShowTriggers,e);const t=r=>{r.usedByTooltip||this.hide({event:r})};this.$_registerTriggerListeners(this.$_targetNodes,Rv,this.triggers,this.hideTriggers,t),this.$_registerTriggerListeners([this.$_popperNode],Rv,this.popperTriggers,this.popperHideTriggers,t)},$_registerEventListeners(e,t,r){this.$_events.push({targetNodes:e,eventType:t,handler:r}),e.forEach(o=>o.addEventListener(t,r,wa?{passive:!0}:void 0))},$_registerTriggerListeners(e,t,r,o,s){let c=r;o!=null&&(c=typeof o==\"function\"?o(c):o),c.forEach(f=>{const d=t[f];d&&this.$_registerEventListeners(e,d,s)})},$_removeEventListeners(e){const t=[];this.$_events.forEach(r=>{const{targetNodes:o,eventType:s,handler:c}=r;!e||e===s?o.forEach(f=>f.removeEventListener(s,c)):t.push(r)}),this.$_events=t},$_refreshListeners(){this.isDisposed||(this.$_removeEventListeners(),this.$_addEventListeners())},$_handleGlobalClose(e,t=!1){this.$_showFrameLocked||(this.hide({event:e}),e.closePopover?this.$emit(\"close-directive\"):this.$emit(\"auto-hide\"),t&&(this.$_preventShow=!0,setTimeout(()=>{this.$_preventShow=!1},300)))},$_detachPopperNode(){this.$_popperNode.parentNode&&this.$_popperNode.parentNode.removeChild(this.$_popperNode)},$_swapTargetAttrs(e,t){for(const r of this.$_targetNodes){const o=r.getAttribute(e);o&&(r.removeAttribute(e),r.setAttribute(t,o))}},$_applyAttrsToTarget(e){for(const t of this.$_targetNodes)for(const r in e){const o=e[r];o==null?t.removeAttribute(r):t.setAttribute(r,o)}},$_updateParentShownChildren(e){let t=this.parentPopper;for(;t;)e?t.shownChildren.add(this.randomId):(t.shownChildren.delete(this.randomId),t.pendingHide&&t.hide()),t=t.parentPopper},$_isAimingPopper(){const e=this.$_referenceNode.getBoundingClientRect();if(ra>=e.left&&ra<=e.right&&ia>=e.top&&ia<=e.bottom){const t=this.$_popperNode.getBoundingClientRect(),r=ra-Ki,o=ia-Xi,s=t.left+t.width/2-Ki+(t.top+t.height/2)-Xi+t.width+t.height,c=Ki+r*s,f=Xi+o*s;return Mc(Ki,Xi,c,f,t.left,t.top,t.left,t.bottom)||Mc(Ki,Xi,c,f,t.left,t.top,t.right,t.top)||Mc(Ki,Xi,c,f,t.right,t.top,t.right,t.bottom)||Mc(Ki,Xi,c,f,t.left,t.bottom,t.right,t.bottom)}return!1}},render(){return this.$slots.default(this.slotData)}});if(typeof document<\"u\"&&typeof window<\"u\"){if(fw){const e=wa?{passive:!0,capture:!0}:!0;document.addEventListener(\"touchstart\",t=>zv(t),e),document.addEventListener(\"touchend\",t=>Fv(t,!0),e)}else window.addEventListener(\"mousedown\",e=>zv(e),!0),window.addEventListener(\"click\",e=>Fv(e,!1),!0);window.addEventListener(\"resize\",BC)}function zv(e,t){for(let r=0;r<nr.length;r++){const o=nr[r];try{o.mouseDownContains=o.popperNode().contains(e.target)}catch{}}}function Fv(e,t){FC(e,t)}function FC(e,t){const r={};for(let o=nr.length-1;o>=0;o--){const s=nr[o];try{const c=s.containsGlobalTarget=s.mouseDownContains||s.popperNode().contains(e.target);s.pendingHide=!1,requestAnimationFrame(()=>{if(s.pendingHide=!1,!r[s.randomId]&&Hv(s,c,e)){if(s.$_handleGlobalClose(e,t),!e.closeAllPopover&&e.closePopover&&c){let d=s.parentPopper;for(;d;)r[d.randomId]=!0,d=d.parentPopper;return}let f=s.parentPopper;for(;f&&Hv(f,f.containsGlobalTarget,e);)f.$_handleGlobalClose(e,t),f=f.parentPopper}})}catch{}}}function Hv(e,t,r){return r.closeAllPopover||r.closePopover&&t||HC(e,r)&&!t}function HC(e,t){if(typeof e.autoHide==\"function\"){const r=e.autoHide(t);return e.lastAutoHide=r,r}return e.autoHide}function BC(){for(let e=0;e<nr.length;e++)nr[e].$_computePosition()}function Bv(){for(let e=0;e<nr.length;e++)nr[e].hide()}let Ki=0,Xi=0,ra=0,ia=0;typeof window<\"u\"&&window.addEventListener(\"mousemove\",e=>{Ki=ra,Xi=ia,ra=e.clientX,ia=e.clientY},wa?{passive:!0}:void 0);function Mc(e,t,r,o,s,c,f,d){const h=((f-s)*(t-c)-(d-c)*(e-s))/((d-c)*(r-e)-(f-s)*(o-t)),p=((r-e)*(t-c)-(o-t)*(e-s))/((d-c)*(r-e)-(f-s)*(o-t));return h>=0&&h<=1&&p>=0&&p<=1}const WC={extends:hw()},rf=(e,t)=>{const r=e.__vccOpts||e;for(const[o,s]of t)r[o]=s;return r};function qC(e,t,r,o,s,c){return ie(),ve(\"div\",{ref:\"reference\",class:ot([\"v-popper\",{\"v-popper--shown\":e.slotData.isShown}])},[Dt(e.$slots,\"default\",qS(qb(e.slotData)))],2)}const jC=rf(WC,[[\"render\",qC]]);function UC(){var e=window.navigator.userAgent,t=e.indexOf(\"MSIE \");if(t>0)return parseInt(e.substring(t+5,e.indexOf(\".\",t)),10);var r=e.indexOf(\"Trident/\");if(r>0){var o=e.indexOf(\"rv:\");return parseInt(e.substring(o+3,e.indexOf(\".\",o)),10)}var s=e.indexOf(\"Edge/\");return s>0?parseInt(e.substring(s+5,e.indexOf(\".\",s)),10):-1}let Kc;function ah(){ah.init||(ah.init=!0,Kc=UC()!==-1)}var of={name:\"ResizeObserver\",props:{emitOnMount:{type:Boolean,default:!1},ignoreWidth:{type:Boolean,default:!1},ignoreHeight:{type:Boolean,default:!1}},emits:[\"notify\"],mounted(){ah(),Et(()=>{this._w=this.$el.offsetWidth,this._h=this.$el.offsetHeight,this.emitOnMount&&this.emitSize()});const e=document.createElement(\"object\");this._resizeObject=e,e.setAttribute(\"aria-hidden\",\"true\"),e.setAttribute(\"tabindex\",-1),e.onload=this.addResizeHandlers,e.type=\"text/html\",Kc&&this.$el.appendChild(e),e.data=\"about:blank\",Kc||this.$el.appendChild(e)},beforeUnmount(){this.removeResizeHandlers()},methods:{compareAndNotify(){(!this.ignoreWidth&&this._w!==this.$el.offsetWidth||!this.ignoreHeight&&this._h!==this.$el.offsetHeight)&&(this._w=this.$el.offsetWidth,this._h=this.$el.offsetHeight,this.emitSize())},emitSize(){this.$emit(\"notify\",{width:this._w,height:this._h})},addResizeHandlers(){this._resizeObject.contentDocument.defaultView.addEventListener(\"resize\",this.compareAndNotify),this.compareAndNotify()},removeResizeHandlers(){this._resizeObject&&this._resizeObject.onload&&(!Kc&&this._resizeObject.contentDocument&&this._resizeObject.contentDocument.defaultView.removeEventListener(\"resize\",this.compareAndNotify),this.$el.removeChild(this._resizeObject),this._resizeObject.onload=null,this._resizeObject=null)}}};const VC=lb();ob(\"data-v-b329ee4c\");const GC={class:\"resize-observer\",tabindex:\"-1\"};sb();const KC=VC((e,t,r,o,s,c)=>(ie(),Ve(\"div\",GC)));of.render=KC;of.__scopeId=\"data-v-b329ee4c\";of.__file=\"src/components/ResizeObserver.vue\";const pw=(e=\"theme\")=>({computed:{themeClass(){return zC(this[e])}}}),XC=rt({name:\"VPopperContent\",components:{ResizeObserver:of},mixins:[pw()],props:{popperId:String,theme:String,shown:Boolean,mounted:Boolean,skipTransition:Boolean,autoHide:Boolean,handleResize:Boolean,classes:Object,result:Object},emits:[\"hide\",\"resize\"],methods:{toPx(e){return e!=null&&!isNaN(e)?`${e}px`:null}}}),YC=[\"id\",\"aria-hidden\",\"tabindex\",\"data-popper-placement\"],ZC={ref:\"inner\",class:\"v-popper__inner\"},JC=X(\"div\",{class:\"v-popper__arrow-outer\"},null,-1),QC=X(\"div\",{class:\"v-popper__arrow-inner\"},null,-1),eE=[JC,QC];function tE(e,t,r,o,s,c){const f=Go(\"ResizeObserver\");return ie(),ve(\"div\",{id:e.popperId,ref:\"popover\",class:ot([\"v-popper__popper\",[e.themeClass,e.classes.popperClass,{\"v-popper__popper--shown\":e.shown,\"v-popper__popper--hidden\":!e.shown,\"v-popper__popper--show-from\":e.classes.showFrom,\"v-popper__popper--show-to\":e.classes.showTo,\"v-popper__popper--hide-from\":e.classes.hideFrom,\"v-popper__popper--hide-to\":e.classes.hideTo,\"v-popper__popper--skip-transition\":e.skipTransition,\"v-popper__popper--arrow-overflow\":e.result&&e.result.arrow.overflow,\"v-popper__popper--no-positioning\":!e.result}]]),style:zt(e.result?{position:e.result.strategy,transform:`translate3d(${Math.round(e.result.x)}px,${Math.round(e.result.y)}px,0)`}:void 0),\"aria-hidden\":e.shown?\"false\":\"true\",tabindex:e.autoHide?0:void 0,\"data-popper-placement\":e.result?e.result.placement:void 0,onKeyup:t[2]||(t[2]=ih(d=>e.autoHide&&e.$emit(\"hide\"),[\"esc\"]))},[X(\"div\",{class:\"v-popper__backdrop\",onClick:t[0]||(t[0]=d=>e.autoHide&&e.$emit(\"hide\"))}),X(\"div\",{class:\"v-popper__wrapper\",style:zt(e.result?{transformOrigin:e.result.transformOrigin}:void 0)},[X(\"div\",ZC,[e.mounted?(ie(),ve(nt,{key:0},[X(\"div\",null,[Dt(e.$slots,\"default\")]),e.handleResize?(ie(),Ve(f,{key:0,onNotify:t[1]||(t[1]=d=>e.$emit(\"resize\",d))})):He(\"\",!0)],64)):He(\"\",!0)],512),X(\"div\",{ref:\"arrow\",class:\"v-popper__arrow-container\",style:zt(e.result?{left:e.toPx(e.result.arrow.x),top:e.toPx(e.result.arrow.y)}:void 0)},eE,4)],4)],46,YC)}const gw=rf(XC,[[\"render\",tE]]),mw={methods:{show(...e){return this.$refs.popper.show(...e)},hide(...e){return this.$refs.popper.hide(...e)},dispose(...e){return this.$refs.popper.dispose(...e)},onResize(...e){return this.$refs.popper.onResize(...e)}}};let ch=function(){};typeof window<\"u\"&&(ch=window.Element);const nE=rt({name:\"VPopperWrapper\",components:{Popper:jC,PopperContent:gw},mixins:[mw,pw(\"finalTheme\")],props:{theme:{type:String,default:null},referenceNode:{type:Function,default:null},shown:{type:Boolean,default:!1},showGroup:{type:String,default:null},ariaId:{default:null},disabled:{type:Boolean,default:void 0},positioningDisabled:{type:Boolean,default:void 0},placement:{type:String,default:void 0},delay:{type:[String,Number,Object],default:void 0},distance:{type:[Number,String],default:void 0},skidding:{type:[Number,String],default:void 0},triggers:{type:Array,default:void 0},showTriggers:{type:[Array,Function],default:void 0},hideTriggers:{type:[Array,Function],default:void 0},popperTriggers:{type:Array,default:void 0},popperShowTriggers:{type:[Array,Function],default:void 0},popperHideTriggers:{type:[Array,Function],default:void 0},container:{type:[String,Object,ch,Boolean],default:void 0},boundary:{type:[String,ch],default:void 0},strategy:{type:String,default:void 0},autoHide:{type:[Boolean,Function],default:void 0},handleResize:{type:Boolean,default:void 0},instantMove:{type:Boolean,default:void 0},eagerMount:{type:Boolean,default:void 0},popperClass:{type:[String,Array,Object],default:void 0},computeTransformOrigin:{type:Boolean,default:void 0},autoMinSize:{type:Boolean,default:void 0},autoSize:{type:[Boolean,String],default:void 0},autoMaxSize:{type:Boolean,default:void 0},autoBoundaryMaxSize:{type:Boolean,default:void 0},preventOverflow:{type:Boolean,default:void 0},overflowPadding:{type:[Number,String],default:void 0},arrowPadding:{type:[Number,String],default:void 0},arrowOverflow:{type:Boolean,default:void 0},flip:{type:Boolean,default:void 0},shift:{type:Boolean,default:void 0},shiftCrossAxis:{type:Boolean,default:void 0},noAutoFocus:{type:Boolean,default:void 0},disposeTimeout:{type:Number,default:void 0}},emits:{show:()=>!0,hide:()=>!0,\"update:shown\":e=>!0,\"apply-show\":()=>!0,\"apply-hide\":()=>!0,\"close-group\":()=>!0,\"close-directive\":()=>!0,\"auto-hide\":()=>!0,resize:()=>!0},computed:{finalTheme(){return this.theme??this.$options.vPopperTheme}},methods:{getTargetNodes(){return Array.from(this.$el.children).filter(e=>e!==this.$refs.popperContent.$el)}}});function rE(e,t,r,o,s,c){const f=Go(\"PopperContent\"),d=Go(\"Popper\");return ie(),Ve(d,ki({ref:\"popper\"},e.$props,{theme:e.finalTheme,\"target-nodes\":e.getTargetNodes,\"popper-node\":()=>e.$refs.popperContent.$el,class:[e.themeClass],onShow:t[0]||(t[0]=()=>e.$emit(\"show\")),onHide:t[1]||(t[1]=()=>e.$emit(\"hide\")),\"onUpdate:shown\":t[2]||(t[2]=h=>e.$emit(\"update:shown\",h)),onApplyShow:t[3]||(t[3]=()=>e.$emit(\"apply-show\")),onApplyHide:t[4]||(t[4]=()=>e.$emit(\"apply-hide\")),onCloseGroup:t[5]||(t[5]=()=>e.$emit(\"close-group\")),onCloseDirective:t[6]||(t[6]=()=>e.$emit(\"close-directive\")),onAutoHide:t[7]||(t[7]=()=>e.$emit(\"auto-hide\")),onResize:t[8]||(t[8]=()=>e.$emit(\"resize\"))}),{default:We(({popperId:h,isShown:p,shouldMountContent:g,skipTransition:v,autoHide:b,show:w,hide:E,handleResize:L,onResize:P,classes:M,result:R})=>[Dt(e.$slots,\"default\",{shown:p,show:w,hide:E}),Ne(f,{ref:\"popperContent\",\"popper-id\":h,theme:e.finalTheme,shown:p,mounted:g,\"skip-transition\":v,\"auto-hide\":b,\"handle-resize\":L,classes:M,result:R,onHide:E,onResize:P},{default:We(()=>[Dt(e.$slots,\"popper\",{shown:p,hide:E})]),_:2},1032,[\"popper-id\",\"theme\",\"shown\",\"mounted\",\"skip-transition\",\"auto-hide\",\"handle-resize\",\"classes\",\"result\",\"onHide\",\"onResize\"])]),_:3},16,[\"theme\",\"target-nodes\",\"popper-node\",\"class\"])}const lp=rf(nE,[[\"render\",rE]]);({...lp});({...lp});const iE={...lp,name:\"VTooltip\",vPopperTheme:\"tooltip\"},oE=rt({name:\"VTooltipDirective\",components:{Popper:hw(),PopperContent:gw},mixins:[mw],inheritAttrs:!1,props:{theme:{type:String,default:\"tooltip\"},html:{type:Boolean,default:e=>ba(e.theme,\"html\")},content:{type:[String,Number,Function],default:null},loadingContent:{type:String,default:e=>ba(e.theme,\"loadingContent\")},targetNodes:{type:Function,required:!0}},data(){return{asyncContent:null}},computed:{isContentAsync(){return typeof this.content==\"function\"},loading(){return this.isContentAsync&&this.asyncContent==null},finalContent(){return this.isContentAsync?this.loading?this.loadingContent:this.asyncContent:this.content}},watch:{content:{handler(){this.fetchContent(!0)},immediate:!0},async finalContent(){await this.$nextTick(),this.$refs.popper.onResize()}},created(){this.$_fetchId=0},methods:{fetchContent(e){if(typeof this.content==\"function\"&&this.$_isShown&&(e||!this.$_loading&&this.asyncContent==null)){this.asyncContent=null,this.$_loading=!0;const t=++this.$_fetchId,r=this.content(this);r.then?r.then(o=>this.onResult(t,o)):this.onResult(t,r)}},onResult(e,t){e===this.$_fetchId&&(this.$_loading=!1,this.asyncContent=t)},onShow(){this.$_isShown=!0,this.fetchContent()},onHide(){this.$_isShown=!1}}}),sE=[\"innerHTML\"],lE=[\"textContent\"];function aE(e,t,r,o,s,c){const f=Go(\"PopperContent\"),d=Go(\"Popper\");return ie(),Ve(d,ki({ref:\"popper\"},e.$attrs,{theme:e.theme,\"target-nodes\":e.targetNodes,\"popper-node\":()=>e.$refs.popperContent.$el,onApplyShow:e.onShow,onApplyHide:e.onHide}),{default:We(({popperId:h,isShown:p,shouldMountContent:g,skipTransition:v,autoHide:b,hide:w,handleResize:E,onResize:L,classes:P,result:M})=>[Ne(f,{ref:\"popperContent\",class:ot({\"v-popper--tooltip-loading\":e.loading}),\"popper-id\":h,theme:e.theme,shown:p,mounted:g,\"skip-transition\":v,\"auto-hide\":b,\"handle-resize\":E,classes:P,result:M,onHide:w,onResize:L},{default:We(()=>[e.html?(ie(),ve(\"div\",{key:0,innerHTML:e.finalContent},null,8,sE)):(ie(),ve(\"div\",{key:1,textContent:Re(e.finalContent)},null,8,lE))]),_:2},1032,[\"class\",\"popper-id\",\"theme\",\"shown\",\"mounted\",\"skip-transition\",\"auto-hide\",\"handle-resize\",\"classes\",\"result\",\"onHide\",\"onResize\"])]),_:1},16,[\"theme\",\"target-nodes\",\"popper-node\",\"onApplyShow\",\"onApplyHide\"])}const cE=rf(oE,[[\"render\",aE]]),vw=\"v-popper--has-tooltip\";function uE(e,t){let r=e.placement;if(!r&&t)for(const o of dw)t[o]&&(r=o);return r||(r=ba(e.theme||\"tooltip\",\"placement\")),r}function yw(e,t,r){let o;const s=typeof t;return s===\"string\"?o={content:t}:t&&s===\"object\"?o=t:o={content:!1},o.placement=uE(o,r),o.targetNodes=()=>[e],o.referenceNode=()=>e,o}let _d,xa,fE=0;function dE(){if(_d)return;xa=Ge([]),_d=Qb({name:\"VTooltipDirectiveApp\",setup(){return{directives:xa}},render(){return this.directives.map(t=>za(cE,{...t.options,shown:t.shown||t.options.shown,key:t.id}))},devtools:{hide:!0}});const e=document.createElement(\"div\");document.body.appendChild(e),_d.mount(e)}function bw(e,t,r){dE();const o=Ge(yw(e,t,r)),s=Ge(!1),c={id:fE++,options:o,shown:s};return xa.value.push(c),e.classList&&e.classList.add(vw),e.$_popper={options:o,item:c,show(){s.value=!0},hide(){s.value=!1}}}function ap(e){if(e.$_popper){const t=xa.value.indexOf(e.$_popper.item);t!==-1&&xa.value.splice(t,1),delete e.$_popper,delete e.$_popperOldShown,delete e.$_popperMountTarget}e.classList&&e.classList.remove(vw)}function Wv(e,{value:t,modifiers:r}){const o=yw(e,t,r);if(!o.content||ba(o.theme||\"tooltip\",\"disabled\"))ap(e);else{let s;e.$_popper?(s=e.$_popper,s.options.value=o):s=bw(e,t,r),typeof t.shown<\"u\"&&t.shown!==e.$_popperOldShown&&(e.$_popperOldShown=t.shown,t.shown?s.show():s.hide())}}const hE={beforeMount:Wv,updated:Wv,beforeUnmount(e){ap(e)}},pE=hE,Qi=iE,ww={options:ao};function cp(e){return I0()?(KS(e),!0):!1}const Td=new WeakMap,gE=(...e)=>{var t;const r=e[0],o=(t=ti())==null?void 0:t.proxy;if(o==null&&!Sb())throw new Error(\"injectLocal must be called in setup\");return o&&Td.has(o)&&r in Td.get(o)?Td.get(o)[r]:pn(...e)},mE=typeof window<\"u\"&&typeof document<\"u\";typeof WorkerGlobalScope<\"u\"&&globalThis instanceof WorkerGlobalScope;const vE=Object.prototype.toString,yE=e=>vE.call(e)===\"[object Object]\",bE=()=>+Date.now(),yu=()=>{};function up(e,t){function r(...o){return new Promise((s,c)=>{Promise.resolve(e(()=>t.apply(this,o),{fn:t,thisArg:this,args:o})).then(s).catch(c)})}return r}const fp=e=>e();function xw(e,t={}){let r,o,s=yu;const c=h=>{clearTimeout(h),s(),s=yu};let f;return h=>{const p=Xt(e),g=Xt(t.maxWait);return r&&c(r),p<=0||g!==void 0&&g<=0?(o&&(c(o),o=null),Promise.resolve(h())):new Promise((v,b)=>{s=t.rejectOnCancel?b:v,f=h,g&&!o&&(o=setTimeout(()=>{r&&c(r),o=null,v(f())},g)),r=setTimeout(()=>{o&&c(o),o=null,v(h())},p)})}}function kw(e=fp,t={}){const{initialState:r=\"active\"}=t,o=Yo(r===\"active\");function s(){o.value=!1}function c(){o.value=!0}const f=(...d)=>{o.value&&e(...d)};return{isActive:Gs(o),pause:s,resume:c,eventFilter:f}}function qv(e,t=!1,r=\"Timeout\"){return new Promise((o,s)=>{setTimeout(t?()=>s(r):o,e)})}function jv(e){return e.endsWith(\"rem\")?Number.parseFloat(e)*16:Number.parseFloat(e)}function wE(e){return ti()}function Cd(e){return Array.isArray(e)?e:[e]}function Yo(...e){if(e.length!==1)return w_(...e);const t=e[0];return typeof t==\"function\"?Gs(Q0(()=>({get:t,set:yu}))):Ge(t)}function Nc(e,t=200,r={}){return up(xw(t,r),e)}function Sw(e,t,r={}){const{eventFilter:o=fp,...s}=r;return xt(e,up(o,t),s)}function _w(e,t,r={}){const{eventFilter:o,initialState:s=\"active\",...c}=r,{eventFilter:f,pause:d,resume:h,isActive:p}=kw(o,{initialState:s});return{stop:Sw(e,t,{...c,eventFilter:f}),pause:d,resume:h,isActive:p}}function dp(e,t=!0,r){wE()?Mi(e,r):t?e():Et(e)}function uh(e,t=!1){function r(v,{flush:b=\"sync\",deep:w=!1,timeout:E,throwOnTimeout:L}={}){let P=null;const R=[new Promise(I=>{P=xt(e,_=>{v(_)!==t&&(P?P():Et(()=>P?.()),I(_))},{flush:b,deep:w,immediate:!0})})];return E!=null&&R.push(qv(E,L).then(()=>Xt(e)).finally(()=>P?.())),Promise.race(R)}function o(v,b){if(!Mt(v))return r(_=>_===v,b);const{flush:w=\"sync\",deep:E=!1,timeout:L,throwOnTimeout:P}=b??{};let M=null;const I=[new Promise(_=>{M=xt([e,v],([$,W])=>{t!==($===W)&&(M?M():Et(()=>M?.()),_($))},{flush:w,deep:E,immediate:!0})})];return L!=null&&I.push(qv(L,P).then(()=>Xt(e)).finally(()=>(M?.(),Xt(e)))),Promise.race(I)}function s(v){return r(b=>!!b,v)}function c(v){return o(null,v)}function f(v){return o(void 0,v)}function d(v){return r(Number.isNaN,v)}function h(v,b){return r(w=>{const E=Array.from(w);return E.includes(v)||E.includes(Xt(v))},b)}function p(v){return g(1,v)}function g(v=1,b){let w=-1;return r(()=>(w+=1,w>=v),b)}return Array.isArray(Xt(e))?{toMatch:r,toContains:h,changed:p,changedTimes:g,get not(){return uh(e,!t)}}:{toMatch:r,toBe:o,toBeTruthy:s,toBeNull:c,toBeNaN:d,toBeUndefined:f,changed:p,changedTimes:g,get not(){return uh(e,!t)}}}function Uv(e){return uh(e)}function xE(e=!1,t={}){const{truthyValue:r=!0,falsyValue:o=!1}=t,s=Mt(e),c=Ft(e);function f(d){if(arguments.length)return c.value=d,c.value;{const h=Xt(r);return c.value=c.value===h?Xt(o):h,c.value}}return s?f:[c,f]}function hp(e,t,r={}){const{debounce:o=0,maxWait:s=void 0,...c}=r;return Sw(e,t,{...c,eventFilter:xw(o,{maxWait:s})})}function kE(e,t,r={}){const{eventFilter:o=fp,...s}=r,c=up(o,t);let f,d,h;if(s.flush===\"sync\"){const p=Ft(!1);d=()=>{},f=g=>{p.value=!0,g(),p.value=!1},h=xt(e,(...g)=>{p.value||c(...g)},s)}else{const p=[],g=Ft(0),v=Ft(0);d=()=>{g.value=v.value},p.push(xt(e,()=>{v.value++},{...s,flush:\"sync\"})),f=b=>{const w=v.value;b(),g.value+=v.value-w},p.push(xt(e,(...b)=>{const w=g.value>0&&g.value===v.value;g.value=0,v.value=0,!w&&c(...b)},s)),h=()=>{p.forEach(b=>b())}}return{stop:h,ignoreUpdates:f,ignorePrevAsyncUpdates:d}}function SE(e,t,r){return xt(e,t,{...r,immediate:!0})}function _E(e,t,r){const o=xt(e,(...s)=>(Et(()=>o()),t(...s)),r);return o}function TE(e,t,r){let o;Mt(r)?o={evaluating:r}:o={};const{lazy:s=!1,evaluating:c=void 0,shallow:f=!0,onError:d=yu}=o,h=Ft(!s),p=f?Ft(t):Ge(t);let g=0;return _b(async v=>{if(!h.value)return;g++;const b=g;let w=!1;c&&Promise.resolve().then(()=>{c.value=!0});try{const E=await e(L=>{v(()=>{c&&(c.value=!1),w||L()})});b===g&&(p.value=E)}catch(E){d(E)}finally{c&&b===g&&(c.value=!1),w=!0}}),s?ke(()=>(h.value=!0,p.value)):p}const Ir=mE?window:void 0;function bu(e){var t;const r=Xt(e);return(t=r?.$el)!=null?t:r}function ho(...e){const t=[],r=()=>{t.forEach(d=>d()),t.length=0},o=(d,h,p,g)=>(d.addEventListener(h,p,g),()=>d.removeEventListener(h,p,g)),s=ke(()=>{const d=Cd(Xt(e[0])).filter(h=>h!=null);return d.every(h=>typeof h!=\"string\")?d:void 0}),c=SE(()=>{var d,h;return[(h=(d=s.value)==null?void 0:d.map(p=>bu(p)))!=null?h:[Ir].filter(p=>p!=null),Cd(Xt(s.value?e[1]:e[0])),Cd(K(s.value?e[2]:e[1])),Xt(s.value?e[3]:e[2])]},([d,h,p,g])=>{if(r(),!d?.length||!h?.length||!p?.length)return;const v=yE(g)?{...g}:g;t.push(...d.flatMap(b=>h.flatMap(w=>p.map(E=>o(b,w,E,v)))))},{flush:\"post\"}),f=()=>{c(),r()};return cp(r),f}function CE(){const e=Ft(!1),t=ti();return t&&Mi(()=>{e.value=!0},t),e}function Tw(e){const t=CE();return ke(()=>(t.value,!!e()))}function EE(e){return typeof e==\"function\"?e:typeof e==\"string\"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function Cw(...e){let t,r,o={};e.length===3?(t=e[0],r=e[1],o=e[2]):e.length===2?typeof e[1]==\"object\"?(t=!0,r=e[0],o=e[1]):(t=e[0],r=e[1]):(t=!0,r=e[0]);const{target:s=Ir,eventName:c=\"keydown\",passive:f=!1,dedupe:d=!1}=o,h=EE(t);return ho(s,c,g=>{g.repeat&&Xt(d)||h(g)&&r(g)},f)}function AE(e,t={}){const{immediate:r=!0,fpsLimit:o=void 0,window:s=Ir,once:c=!1}=t,f=Ft(!1),d=ke(()=>o?1e3/Xt(o):null);let h=0,p=null;function g(w){if(!f.value||!s)return;h||(h=w);const E=w-h;if(d.value&&E<d.value){p=s.requestAnimationFrame(g);return}if(h=w,e({delta:E,timestamp:w}),c){f.value=!1,p=null;return}p=s.requestAnimationFrame(g)}function v(){!f.value&&s&&(f.value=!0,h=0,p=s.requestAnimationFrame(g))}function b(){f.value=!1,p!=null&&s&&(s.cancelAnimationFrame(p),p=null)}return r&&v(),cp(b),{isActive:Gs(f),pause:b,resume:v}}const LE=Symbol(\"vueuse-ssr-width\");function ME(){const e=Sb()?gE(LE,null):null;return typeof e==\"number\"?e:void 0}function Ew(e,t={}){const{window:r=Ir,ssrWidth:o=ME()}=t,s=Tw(()=>r&&\"matchMedia\"in r&&typeof r.matchMedia==\"function\"),c=Ft(typeof o==\"number\"),f=Ft(),d=Ft(!1),h=p=>{d.value=p.matches};return _b(()=>{if(c.value){c.value=!s.value;const p=Xt(e).split(\",\");d.value=p.some(g=>{const v=g.includes(\"not all\"),b=g.match(/\\(\\s*min-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/),w=g.match(/\\(\\s*max-width:\\s*(-?\\d+(?:\\.\\d*)?[a-z]+\\s*)\\)/);let E=!!(b||w);return b&&E&&(E=o>=jv(b[1])),w&&E&&(E=o<=jv(w[1])),v?!E:E});return}s.value&&(f.value=r.matchMedia(Xt(e)),d.value=f.value.matches)}),ho(f,\"change\",h,{passive:!0}),ke(()=>d.value)}function Aw(e){return JSON.parse(JSON.stringify(e))}const Oc=typeof globalThis<\"u\"?globalThis:typeof window<\"u\"?window:typeof global<\"u\"?global:typeof self<\"u\"?self:{},Pc=\"__vueuse_ssr_handlers__\",NE=OE();function OE(){return Pc in Oc||(Oc[Pc]=Oc[Pc]||{}),Oc[Pc]}function Lw(e,t){return NE[e]||t}function PE(e){return Ew(\"(prefers-color-scheme: dark)\",e)}function RE(e){return e==null?\"any\":e instanceof Set?\"set\":e instanceof Map?\"map\":e instanceof Date?\"date\":typeof e==\"boolean\"?\"boolean\":typeof e==\"string\"?\"string\":typeof e==\"object\"?\"object\":Number.isNaN(e)?\"any\":\"number\"}const $E={boolean:{read:e=>e===\"true\",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Vv=\"vueuse-storage\";function Mw(e,t,r,o={}){var s;const{flush:c=\"pre\",deep:f=!0,listenToStorageChanges:d=!0,writeDefaults:h=!0,mergeDefaults:p=!1,shallow:g,window:v=Ir,eventFilter:b,onError:w=j=>{console.error(j)},initOnMounted:E}=o,L=(g?Ft:Ge)(typeof t==\"function\"?t():t),P=ke(()=>Xt(e));if(!r)try{r=Lw(\"getDefaultStorage\",()=>{var j;return(j=Ir)==null?void 0:j.localStorage})()}catch(j){w(j)}if(!r)return L;const M=Xt(t),R=RE(M),I=(s=o.serializer)!=null?s:$E[R],{pause:_,resume:$}=_w(L,()=>ne(L.value),{flush:c,deep:f,eventFilter:b});xt(P,()=>Z(),{flush:c}),v&&d&&dp(()=>{r instanceof Storage?ho(v,\"storage\",Z,{passive:!0}):ho(v,Vv,G),E&&Z()}),E||Z();function W(j,N){if(v){const O={key:P.value,oldValue:j,newValue:N,storageArea:r};v.dispatchEvent(r instanceof Storage?new StorageEvent(\"storage\",O):new CustomEvent(Vv,{detail:O}))}}function ne(j){try{const N=r.getItem(P.value);if(j==null)W(N,null),r.removeItem(P.value);else{const O=I.write(j);N!==O&&(r.setItem(P.value,O),W(N,O))}}catch(N){w(N)}}function ee(j){const N=j?j.newValue:r.getItem(P.value);if(N==null)return h&&M!=null&&r.setItem(P.value,I.write(M)),M;if(!j&&p){const O=I.read(N);return typeof p==\"function\"?p(O,M):R===\"object\"&&!Array.isArray(O)?{...M,...O}:O}else return typeof N!=\"string\"?N:I.read(N)}function Z(j){if(!(j&&j.storageArea!==r)){if(j&&j.key==null){L.value=M;return}if(!(j&&j.key!==P.value)){_();try{j?.newValue!==I.write(L.value)&&(L.value=ee(j))}catch(N){w(N)}finally{j?Et($):$()}}}}function G(j){Z(j.detail)}return L}const IE=\"*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}\";function DE(e={}){const{selector:t=\"html\",attribute:r=\"class\",initialValue:o=\"auto\",window:s=Ir,storage:c,storageKey:f=\"vueuse-color-scheme\",listenToStorageChanges:d=!0,storageRef:h,emitAuto:p,disableTransition:g=!0}=e,v={auto:\"\",light:\"light\",dark:\"dark\",...e.modes||{}},b=PE({window:s}),w=ke(()=>b.value?\"dark\":\"light\"),E=h||(f==null?Yo(o):Mw(f,o,c,{window:s,listenToStorageChanges:d})),L=ke(()=>E.value===\"auto\"?w.value:E.value),P=Lw(\"updateHTMLAttrs\",(_,$,W)=>{const ne=typeof _==\"string\"?s?.document.querySelector(_):bu(_);if(!ne)return;const ee=new Set,Z=new Set;let G=null;if($===\"class\"){const N=W.split(/\\s/g);Object.values(v).flatMap(O=>(O||\"\").split(/\\s/g)).filter(Boolean).forEach(O=>{N.includes(O)?ee.add(O):Z.add(O)})}else G={key:$,value:W};if(ee.size===0&&Z.size===0&&G===null)return;let j;g&&(j=s.document.createElement(\"style\"),j.appendChild(document.createTextNode(IE)),s.document.head.appendChild(j));for(const N of ee)ne.classList.add(N);for(const N of Z)ne.classList.remove(N);G&&ne.setAttribute(G.key,G.value),g&&(s.getComputedStyle(j).opacity,document.head.removeChild(j))});function M(_){var $;P(t,r,($=v[_])!=null?$:_)}function R(_){e.onChanged?e.onChanged(_,M):M(_)}xt(L,R,{flush:\"post\",immediate:!0}),dp(()=>R(L.value));const I=ke({get(){return p?E.value:L.value},set(_){E.value=_}});return Object.assign(I,{store:E,system:w,state:L})}function zE(e={}){const{valueDark:t=\"dark\",valueLight:r=\"\"}=e,o=DE({...e,onChanged:(f,d)=>{var h;e.onChanged?(h=e.onChanged)==null||h.call(e,f===\"dark\",d,f):d(f)},modes:{dark:t,light:r}}),s=ke(()=>o.system.value);return ke({get(){return o.value===\"dark\"},set(f){const d=f?\"dark\":\"light\";s.value===d?o.value=\"auto\":o.value=d}})}function Nw(e){return e}function FE(e,t){return e.value=t}function HE(e){return e?typeof e==\"function\"?e:Aw:Nw}function BE(e){return e?typeof e==\"function\"?e:Aw:Nw}function WE(e,t={}){const{clone:r=!1,dump:o=HE(r),parse:s=BE(r),setSource:c=FE}=t;function f(){return Uu({snapshot:o(e.value),timestamp:bE()})}const d=Ge(f()),h=Ge([]),p=Ge([]),g=I=>{c(e,s(I.snapshot)),d.value=I},v=()=>{h.value.unshift(d.value),d.value=f(),t.capacity&&h.value.length>t.capacity&&h.value.splice(t.capacity,Number.POSITIVE_INFINITY),p.value.length&&p.value.splice(0,p.value.length)},b=()=>{h.value.splice(0,h.value.length),p.value.splice(0,p.value.length)},w=()=>{const I=h.value.shift();I&&(p.value.unshift(d.value),g(I))},E=()=>{const I=p.value.shift();I&&(h.value.unshift(d.value),g(I))},L=()=>{g(d.value)},P=ke(()=>[d.value,...h.value]),M=ke(()=>h.value.length>0),R=ke(()=>p.value.length>0);return{source:e,undoStack:h,redoStack:p,last:d,history:P,canUndo:M,canRedo:R,clear:b,commit:v,reset:L,undo:w,redo:E}}function qE(e,t={}){const{deep:r=!1,flush:o=\"pre\",eventFilter:s}=t,{eventFilter:c,pause:f,resume:d,isActive:h}=kw(s),{ignoreUpdates:p,ignorePrevAsyncUpdates:g,stop:v}=kE(e,P,{deep:r,flush:o,eventFilter:c});function b(_,$){g(),p(()=>{_.value=$})}const w=WE(e,{...t,clone:t.clone||r,setSource:b}),{clear:E,commit:L}=w;function P(){g(),L()}function M(_){d(),_&&P()}function R(_){let $=!1;const W=()=>$=!0;p(()=>{_(W)}),$||P()}function I(){v(),E()}return{...w,isTracking:h,pause:f,resume:M,commit:P,batch:R,dispose:I}}function Ow(e,t,r={}){const{window:o=Ir,...s}=r;let c;const f=Tw(()=>o&&\"ResizeObserver\"in o),d=()=>{c&&(c.disconnect(),c=void 0)},h=ke(()=>{const v=Xt(e);return Array.isArray(v)?v.map(b=>bu(b)):[bu(v)]}),p=xt(h,v=>{if(d(),f.value&&o){c=new ResizeObserver(t);for(const b of v)b&&c.observe(b,s)}},{immediate:!0,flush:\"post\"}),g=()=>{d(),p()};return cp(g),{isSupported:f,stop:g}}function sf(e,t,r={}){const{window:o=Ir}=r;return Mw(e,t,o?.localStorage,r)}function jE(e=\"history\",t={}){const{initialValue:r={},removeNullishValues:o=!0,removeFalsyValues:s=!1,write:c=!0,writeMode:f=\"replace\",window:d=Ir}=t;if(!d)return ir(r);const h=ir({});function p(){if(e===\"history\")return d.location.search||\"\";if(e===\"hash\"){const I=d.location.hash||\"\",_=I.indexOf(\"?\");return _>0?I.slice(_):\"\"}else return(d.location.hash||\"\").replace(/^#/,\"\")}function g(I){const _=I.toString();if(e===\"history\")return`${_?`?${_}`:\"\"}${d.location.hash||\"\"}`;if(e===\"hash-params\")return`${d.location.search||\"\"}${_?`#${_}`:\"\"}`;const $=d.location.hash||\"#\",W=$.indexOf(\"?\");return W>0?`${d.location.search||\"\"}${$.slice(0,W)}${_?`?${_}`:\"\"}`:`${d.location.search||\"\"}${$}${_?`?${_}`:\"\"}`}function v(){return new URLSearchParams(p())}function b(I){const _=new Set(Object.keys(h));for(const $ of I.keys()){const W=I.getAll($);h[$]=W.length>1?W:I.get($)||\"\",_.delete($)}Array.from(_).forEach($=>delete h[$])}const{pause:w,resume:E}=_w(h,()=>{const I=new URLSearchParams(\"\");Object.keys(h).forEach(_=>{const $=h[_];Array.isArray($)?$.forEach(W=>I.append(_,W)):o&&$==null||s&&!$?I.delete(_):I.set(_,$)}),L(I,!1)},{deep:!0});function L(I,_){w(),_&&b(I),f===\"replace\"?d.history.replaceState(d.history.state,d.document.title,d.location.pathname+g(I)):d.history.pushState(d.history.state,d.document.title,d.location.pathname+g(I)),E()}function P(){c&&L(v(),!0)}const M={passive:!0};ho(d,\"popstate\",P,M),e!==\"history\"&&ho(d,\"hashchange\",P,M);const R=v();return R.keys().next().value?b(R):Object.assign(h,r),h}function Pw(e={}){const{window:t=Ir,initialWidth:r=Number.POSITIVE_INFINITY,initialHeight:o=Number.POSITIVE_INFINITY,listenOrientation:s=!0,includeScrollbar:c=!0,type:f=\"inner\"}=e,d=Ft(r),h=Ft(o),p=()=>{if(t)if(f===\"outer\")d.value=t.outerWidth,h.value=t.outerHeight;else if(f===\"visual\"&&t.visualViewport){const{width:v,height:b,scale:w}=t.visualViewport;d.value=Math.round(v*w),h.value=Math.round(b*w)}else c?(d.value=t.innerWidth,h.value=t.innerHeight):(d.value=t.document.documentElement.clientWidth,h.value=t.document.documentElement.clientHeight)};p(),dp(p);const g={passive:!0};if(ho(\"resize\",p,g),t&&f===\"visual\"&&t.visualViewport&&ho(t.visualViewport,\"resize\",p,g),s){const v=Ew(\"(orientation: portrait)\");xt(v,()=>p())}return{width:d,height:h}}const Gv={__name:\"splitpanes\",props:{horizontal:{type:Boolean,default:!1},pushOtherPanes:{type:Boolean,default:!0},maximizePanes:{type:Boolean,default:!0},rtl:{type:Boolean,default:!1},firstSplitter:{type:Boolean,default:!1}},emits:[\"ready\",\"resize\",\"resized\",\"pane-click\",\"pane-maximize\",\"pane-add\",\"pane-remove\",\"splitter-click\",\"splitter-dblclick\"],setup(e,{emit:t}){const r=t,o=e,s=yb(),c=Ge([]),f=ke(()=>c.value.reduce((F,Y)=>(F[~~Y.id]=Y)&&F,{})),d=ke(()=>c.value.length),h=Ge(null),p=Ge(!1),g=Ge({mouseDown:!1,dragging:!1,activeSplitter:null,cursorOffset:0}),v=Ge({splitter:null,timeoutId:null}),b=ke(()=>({[`splitpanes splitpanes--${o.horizontal?\"horizontal\":\"vertical\"}`]:!0,\"splitpanes--dragging\":g.value.dragging})),w=()=>{document.addEventListener(\"mousemove\",P,{passive:!1}),document.addEventListener(\"mouseup\",M),\"ontouchstart\"in window&&(document.addEventListener(\"touchmove\",P,{passive:!1}),document.addEventListener(\"touchend\",M))},E=()=>{document.removeEventListener(\"mousemove\",P,{passive:!1}),document.removeEventListener(\"mouseup\",M),\"ontouchstart\"in window&&(document.removeEventListener(\"touchmove\",P,{passive:!1}),document.removeEventListener(\"touchend\",M))},L=(F,Y)=>{const re=F.target.closest(\".splitpanes__splitter\");if(re){const{left:le,top:ae}=re.getBoundingClientRect(),{clientX:D,clientY:q}=\"ontouchstart\"in window&&F.touches?F.touches[0]:F;g.value.cursorOffset=o.horizontal?q-ae:D-le}w(),g.value.mouseDown=!0,g.value.activeSplitter=Y},P=F=>{g.value.mouseDown&&(F.preventDefault(),g.value.dragging=!0,requestAnimationFrame(()=>{ne($(F)),Fe(\"resize\",{event:F},!0)}))},M=F=>{g.value.dragging&&(window.getSelection().removeAllRanges(),Fe(\"resized\",{event:F},!0)),g.value.mouseDown=!1,g.value.activeSplitter=null,setTimeout(()=>{g.value.dragging=!1,E()},100)},R=(F,Y)=>{\"ontouchstart\"in window&&(F.preventDefault(),v.value.splitter===Y?(clearTimeout(v.value.timeoutId),v.value.timeoutId=null,I(F,Y),v.value.splitter=null):(v.value.splitter=Y,v.value.timeoutId=setTimeout(()=>v.value.splitter=null,500))),g.value.dragging||Fe(\"splitter-click\",{event:F,index:Y},!0)},I=(F,Y)=>{if(Fe(\"splitter-dblclick\",{event:F,index:Y},!0),o.maximizePanes){let re=0;c.value=c.value.map((le,ae)=>(le.size=ae===Y?le.max:le.min,ae!==Y&&(re+=le.min),le)),c.value[Y].size-=re,Fe(\"pane-maximize\",{event:F,index:Y,pane:c.value[Y]}),Fe(\"resized\",{event:F,index:Y},!0)}},_=(F,Y)=>{Fe(\"pane-click\",{event:F,index:f.value[Y].index,pane:f.value[Y]})},$=F=>{const Y=h.value.getBoundingClientRect(),{clientX:re,clientY:le}=\"ontouchstart\"in window&&F.touches?F.touches[0]:F;return{x:re-(o.horizontal?0:g.value.cursorOffset)-Y.left,y:le-(o.horizontal?g.value.cursorOffset:0)-Y.top}},W=F=>{F=F[o.horizontal?\"y\":\"x\"];const Y=h.value[o.horizontal?\"clientHeight\":\"clientWidth\"];return o.rtl&&!o.horizontal&&(F=Y-F),F*100/Y},ne=F=>{const Y=g.value.activeSplitter;let re={prevPanesSize:Z(Y),nextPanesSize:G(Y),prevReachedMinPanes:0,nextReachedMinPanes:0};const le=0+(o.pushOtherPanes?0:re.prevPanesSize),ae=100-(o.pushOtherPanes?0:re.nextPanesSize),D=Math.max(Math.min(W(F),ae),le);let q=[Y,Y+1],Q=c.value[q[0]]||null,he=c.value[q[1]]||null;const de=Q.max<100&&D>=Q.max+re.prevPanesSize,ge=he.max<100&&D<=100-(he.max+G(Y+1));if(de||ge){de?(Q.size=Q.max,he.size=Math.max(100-Q.max-re.prevPanesSize-re.nextPanesSize,0)):(Q.size=Math.max(100-he.max-re.prevPanesSize-G(Y+1),0),he.size=he.max);return}if(o.pushOtherPanes){const Ce=ee(re,D);if(!Ce)return;({sums:re,panesToResize:q}=Ce),Q=c.value[q[0]]||null,he=c.value[q[1]]||null}Q!==null&&(Q.size=Math.min(Math.max(D-re.prevPanesSize-re.prevReachedMinPanes,Q.min),Q.max)),he!==null&&(he.size=Math.min(Math.max(100-D-re.nextPanesSize-re.nextReachedMinPanes,he.min),he.max))},ee=(F,Y)=>{const re=g.value.activeSplitter,le=[re,re+1];return Y<F.prevPanesSize+c.value[le[0]].min&&(le[0]=j(re).index,F.prevReachedMinPanes=0,le[0]<re&&c.value.forEach((ae,D)=>{D>le[0]&&D<=re&&(ae.size=ae.min,F.prevReachedMinPanes+=ae.min)}),F.prevPanesSize=Z(le[0]),le[0]===void 0)?(F.prevReachedMinPanes=0,c.value[0].size=c.value[0].min,c.value.forEach((ae,D)=>{D>0&&D<=re&&(ae.size=ae.min,F.prevReachedMinPanes+=ae.min)}),c.value[le[1]].size=100-F.prevReachedMinPanes-c.value[0].min-F.prevPanesSize-F.nextPanesSize,null):Y>100-F.nextPanesSize-c.value[le[1]].min&&(le[1]=N(re).index,F.nextReachedMinPanes=0,le[1]>re+1&&c.value.forEach((ae,D)=>{D>re&&D<le[1]&&(ae.size=ae.min,F.nextReachedMinPanes+=ae.min)}),F.nextPanesSize=G(le[1]-1),le[1]===void 0)?(F.nextReachedMinPanes=0,c.value.forEach((ae,D)=>{D<d.value-1&&D>=re+1&&(ae.size=ae.min,F.nextReachedMinPanes+=ae.min)}),c.value[le[0]].size=100-F.prevPanesSize-G(le[0]-1),null):{sums:F,panesToResize:le}},Z=F=>c.value.reduce((Y,re,le)=>Y+(le<F?re.size:0),0),G=F=>c.value.reduce((Y,re,le)=>Y+(le>F+1?re.size:0),0),j=F=>[...c.value].reverse().find(Y=>Y.index<F&&Y.size>Y.min)||{},N=F=>c.value.find(Y=>Y.index>F+1&&Y.size>Y.min)||{},O=()=>{var F;const Y=Array.from(((F=h.value)==null?void 0:F.children)||[]);for(const re of Y){const le=re.classList.contains(\"splitpanes__pane\"),ae=re.classList.contains(\"splitpanes__splitter\");!le&&!ae&&(re.remove(),console.warn(\"Splitpanes: Only <pane> elements are allowed at the root of <splitpanes>. One of your DOM nodes was removed.\"))}},C=(F,Y,re=!1)=>{const le=F-1,ae=document.createElement(\"div\");ae.classList.add(\"splitpanes__splitter\"),re||(ae.onmousedown=D=>L(D,le),typeof window<\"u\"&&\"ontouchstart\"in window&&(ae.ontouchstart=D=>L(D,le)),ae.onclick=D=>R(D,le+1)),ae.ondblclick=D=>I(D,le+1),Y.parentNode.insertBefore(ae,Y)},k=F=>{F.onmousedown=void 0,F.onclick=void 0,F.ondblclick=void 0,F.remove()},z=()=>{var F;const Y=Array.from(((F=h.value)==null?void 0:F.children)||[]);for(const le of Y)le.className.includes(\"splitpanes__splitter\")&&k(le);let re=0;for(const le of Y)le.className.includes(\"splitpanes__pane\")&&(!re&&o.firstSplitter?C(re,le,!0):re&&C(re,le),re++)},B=({uid:F,...Y})=>{const re=f.value[F];for(const[le,ae]of Object.entries(Y))re[le]=ae},ce=F=>{var Y;let re=-1;Array.from(((Y=h.value)==null?void 0:Y.children)||[]).some(le=>(le.className.includes(\"splitpanes__pane\")&&re++,le.isSameNode(F.el))),c.value.splice(re,0,{...F,index:re}),c.value.forEach((le,ae)=>le.index=ae),p.value&&Et(()=>{z(),Se({addedPane:c.value[re]}),Fe(\"pane-add\",{pane:c.value[re]})})},be=F=>{const Y=c.value.findIndex(le=>le.id===F);c.value[Y].el=null;const re=c.value.splice(Y,1)[0];c.value.forEach((le,ae)=>le.index=ae),Et(()=>{z(),Fe(\"pane-remove\",{pane:re}),Se({removedPane:{...re}})})},Se=(F={})=>{!F.addedPane&&!F.removedPane?Ae():c.value.some(Y=>Y.givenSize!==null||Y.min||Y.max<100)?Ke(F):Be(),p.value&&Fe(\"resized\")},Be=()=>{const F=100/d.value;let Y=0;const re=[],le=[];for(const ae of c.value)ae.size=Math.max(Math.min(F,ae.max),ae.min),Y-=ae.size,ae.size>=ae.max&&re.push(ae.id),ae.size<=ae.min&&le.push(ae.id);Y>.1&&je(Y,re,le)},Ae=()=>{let F=100;const Y=[],re=[];let le=0;for(const D of c.value)F-=D.size,D.givenSize!==null&&le++,D.size>=D.max&&Y.push(D.id),D.size<=D.min&&re.push(D.id);let ae=100;if(F>.1){for(const D of c.value)D.givenSize===null&&(D.size=Math.max(Math.min(F/(d.value-le),D.max),D.min)),ae-=D.size;ae>.1&&je(ae,Y,re)}},Ke=({addedPane:F,removedPane:Y}={})=>{let re=100/d.value,le=0;const ae=[],D=[];(F?.givenSize??null)!==null&&(re=(100-F.givenSize)/(d.value-1));for(const q of c.value)le-=q.size,q.size>=q.max&&ae.push(q.id),q.size<=q.min&&D.push(q.id);if(!(Math.abs(le)<.1)){for(const q of c.value)F?.givenSize!==null&&F?.id===q.id||(q.size=Math.max(Math.min(re,q.max),q.min)),le-=q.size,q.size>=q.max&&ae.push(q.id),q.size<=q.min&&D.push(q.id);le>.1&&je(le,ae,D)}},je=(F,Y,re)=>{let le;F>0?le=F/(d.value-Y.length):le=F/(d.value-re.length),c.value.forEach((ae,D)=>{if(F>0&&!Y.includes(ae.id)){const q=Math.max(Math.min(ae.size+le,ae.max),ae.min),Q=q-ae.size;F-=Q,ae.size=q}else if(!re.includes(ae.id)){const q=Math.max(Math.min(ae.size+le,ae.max),ae.min),Q=q-ae.size;F-=Q,ae.size=q}}),Math.abs(F)>.1&&Et(()=>{p.value&&console.warn(\"Splitpanes: Could not resize panes correctly due to their constraints.\")})},Fe=(F,Y=void 0,re=!1)=>{const le=Y?.index??g.value.activeSplitter??null;r(F,{...Y,...le!==null&&{index:le},...re&&le!==null&&{prevPane:c.value[le-(o.firstSplitter?1:0)],nextPane:c.value[le+(o.firstSplitter?0:1)]},panes:c.value.map(ae=>({min:ae.min,max:ae.max,size:ae.size}))})};xt(()=>o.firstSplitter,()=>z()),Mi(()=>{O(),z(),Se(),Fe(\"ready\"),p.value=!0}),$a(()=>p.value=!1);const Pe=()=>{var F;return za(\"div\",{ref:h,class:b.value},(F=s.default)==null?void 0:F.call(s))};return dr(\"panes\",c),dr(\"indexedPanes\",f),dr(\"horizontal\",ke(()=>o.horizontal)),dr(\"requestUpdate\",B),dr(\"onPaneAdd\",ce),dr(\"onPaneRemove\",be),dr(\"onPaneClick\",_),(F,Y)=>(ie(),Ve(Xd(Pe)))}},Rc={__name:\"pane\",props:{size:{type:[Number,String]},minSize:{type:[Number,String],default:0},maxSize:{type:[Number,String],default:100}},setup(e){var t;const r=e,o=pn(\"requestUpdate\"),s=pn(\"onPaneAdd\"),c=pn(\"horizontal\"),f=pn(\"onPaneRemove\"),d=pn(\"onPaneClick\"),h=(t=ti())==null?void 0:t.uid,p=pn(\"indexedPanes\"),g=ke(()=>p.value[h]),v=Ge(null),b=ke(()=>{const P=isNaN(r.size)||r.size===void 0?0:parseFloat(r.size);return Math.max(Math.min(P,E.value),w.value)}),w=ke(()=>{const P=parseFloat(r.minSize);return isNaN(P)?0:P}),E=ke(()=>{const P=parseFloat(r.maxSize);return isNaN(P)?100:P}),L=ke(()=>{var P;return`${c.value?\"height\":\"width\"}: ${(P=g.value)==null?void 0:P.size}%`});return xt(()=>b.value,P=>o({uid:h,size:P})),xt(()=>w.value,P=>o({uid:h,min:P})),xt(()=>E.value,P=>o({uid:h,max:P})),Mi(()=>{s({id:h,el:v.value,min:w.value,max:E.value,givenSize:r.size===void 0?null:b.value,size:b.value})}),$a(()=>f(h)),(P,M)=>(ie(),ve(\"div\",{ref_key:\"paneEl\",ref:v,class:\"splitpanes__pane\",onClick:M[0]||(M[0]=R=>K(d)(R,P._.uid)),style:zt(L.value)},[Dt(P.$slots,\"default\")],4))}},tr=Ge([414,896]);function Rw(e){return e!=null}function pp(e){return e==null&&(e=[]),Array.isArray(e)?e:[e]}const UE=/^[A-Za-z]:\\//;function VE(e=\"\"){return e&&e.replace(/\\\\/g,\"/\").replace(UE,t=>t.toUpperCase())}const GE=/^[/\\\\](?![/\\\\])|^[/\\\\]{2}(?!\\.)|^[A-Za-z]:[/\\\\]/;function KE(){return typeof process<\"u\"&&typeof process.cwd==\"function\"?process.cwd().replace(/\\\\/g,\"/\"):\"/\"}const $w=function(...e){e=e.map(o=>VE(o));let t=\"\",r=!1;for(let o=e.length-1;o>=-1&&!r;o--){const s=o>=0?e[o]:KE();!s||s.length===0||(t=`${s}/${t}`,r=Kv(s))}return t=XE(t,!r),r&&!Kv(t)?`/${t}`:t.length>0?t:\".\"};function XE(e,t){let r=\"\",o=0,s=-1,c=0,f=null;for(let d=0;d<=e.length;++d){if(d<e.length)f=e[d];else{if(f===\"/\")break;f=\"/\"}if(f===\"/\"){if(!(s===d-1||c===1))if(c===2){if(r.length<2||o!==2||r[r.length-1]!==\".\"||r[r.length-2]!==\".\"){if(r.length>2){const h=r.lastIndexOf(\"/\");h===-1?(r=\"\",o=0):(r=r.slice(0,h),o=r.length-1-r.lastIndexOf(\"/\")),s=d,c=0;continue}else if(r.length>0){r=\"\",o=0,s=d,c=0;continue}}t&&(r+=r.length>0?\"/..\":\"..\",o=2)}else r.length>0?r+=`/${e.slice(s+1,d)}`:r=e.slice(s+1,d),o=d-s-1;s=d,c=0}else f===\".\"&&c!==-1?++c:c=-1}return r}const Kv=function(e){return GE.test(e)};var YE=44,Xv=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",ZE=new Uint8Array(64),Iw=new Uint8Array(128);for(let e=0;e<Xv.length;e++){const t=Xv.charCodeAt(e);ZE[e]=t,Iw[t]=e}function Hl(e,t){let r=0,o=0,s=0;do{const f=e.next();s=Iw[f],r|=(s&31)<<o,o+=5}while(s&32);const c=r&1;return r>>>=1,c&&(r=-2147483648|-r),t+r}function Yv(e,t){return e.pos>=t?!1:e.peek()!==YE}var JE=class{constructor(e){this.pos=0,this.buffer=e}next(){return this.buffer.charCodeAt(this.pos++)}peek(){return this.buffer.charCodeAt(this.pos)}indexOf(e){const{buffer:t,pos:r}=this,o=t.indexOf(e,r);return o===-1?t.length:o}};function QE(e){const{length:t}=e,r=new JE(e),o=[];let s=0,c=0,f=0,d=0,h=0;do{const p=r.indexOf(\";\"),g=[];let v=!0,b=0;for(s=0;r.pos<p;){let w;s=Hl(r,s),s<b&&(v=!1),b=s,Yv(r,p)?(c=Hl(r,c),f=Hl(r,f),d=Hl(r,d),Yv(r,p)?(h=Hl(r,h),w=[s,c,f,d,h]):w=[s,c,f,d]):w=[s],g.push(w),r.pos++}v||eA(g),o.push(g),r.pos=p+1}while(r.pos<=t);return o}function eA(e){e.sort(tA)}function tA(e,t){return e[0]-t[0]}var lf=0,nA=1,rA=2,iA=3,oA=4,wu=!1;function sA(e,t,r,o){for(;r<=o;){const s=r+(o-r>>1),c=e[s][lf]-t;if(c===0)return wu=!0,s;c<0?r=s+1:o=s-1}return wu=!1,r-1}function lA(e,t,r){for(let o=r+1;o<e.length&&e[o][lf]===t;r=o++);return r}function aA(e,t,r){for(let o=r-1;o>=0&&e[o][lf]===t;r=o--);return r}function cA(e,t,r,o){const{lastKey:s,lastNeedle:c,lastIndex:f}=r;let d=0,h=e.length-1;if(o===s){if(t===c)return wu=f!==-1&&e[f][lf]===t,f;t>=c?d=f===-1?0:f:h=f}return r.lastKey=o,r.lastNeedle=t,r.lastIndex=sA(e,t,d,h)}var uA=\"`line` must be greater than 0 (lines start at line 1)\",fA=\"`column` must be greater than or equal to 0 (columns start at column 0)\",Zv=-1,dA=1;function hA(e){var t;return(t=e)._decoded||(t._decoded=QE(e._encoded))}function pA(e,t){let{line:r,column:o,bias:s}=t;if(r--,r<0)throw new Error(uA);if(o<0)throw new Error(fA);const c=hA(e);if(r>=c.length)return $c(null,null,null,null);const f=c[r],d=gA(f,e._decodedMemo,r,o,s||dA);if(d===-1)return $c(null,null,null,null);const h=f[d];if(h.length===1)return $c(null,null,null,null);const{names:p,resolvedSources:g}=e;return $c(g[h[nA]],h[rA]+1,h[iA],h.length===5?p[h[oA]]:null)}function $c(e,t,r,o){return{source:e,line:t,column:r,name:o}}function gA(e,t,r,o,s){let c=cA(e,o,t,r);return wu?c=(s===Zv?lA:aA)(e,o,c):s===Zv&&c++,c===-1||c===e.length?-1:c}const Dw=/^\\s*at .*(?:\\S:\\d+|\\(native\\))/m,mA=/^(?:eval@)?(?:\\[native code\\])?$/,vA=[\"node:internal\",/\\/packages\\/\\w+\\/dist\\//,/\\/@vitest\\/\\w+\\/dist\\//,\"/vitest/dist/\",\"/vitest/src/\",\"/node_modules/chai/\",\"/node_modules/tinyspy/\",\"/vite/dist/node/module-runner\",\"/rolldown-vite/dist/node/module-runner\",\"/deps/chunk-\",\"/deps/@vitest\",\"/deps/loupe\",\"/deps/chai\",\"/browser-playwright/dist/locators.js\",\"/browser-webdriverio/dist/locators.js\",\"/browser-preview/dist/locators.js\",/node:\\w+/,/__vitest_test__/,/__vitest_browser__/,/\\/deps\\/vitest_/];function zw(e){if(!e.includes(\":\"))return[e];const r=/(.+?)(?::(\\d+))?(?::(\\d+))?$/.exec(e.replace(/^\\(|\\)$/g,\"\"));if(!r)return[e];let o=r[1];if(o.startsWith(\"async \")&&(o=o.slice(6)),o.startsWith(\"http:\")||o.startsWith(\"https:\")){const s=new URL(o);s.searchParams.delete(\"import\"),s.searchParams.delete(\"browserv\"),o=s.pathname+s.hash+s.search}if(o.startsWith(\"/@fs/\")){const s=/^\\/@fs\\/[a-zA-Z]:\\//.test(o);o=o.slice(s?5:4)}return[o,r[2]||void 0,r[3]||void 0]}function yA(e){let t=e.trim();if(mA.test(t)||(t.includes(\" > eval\")&&(t=t.replace(/ line (\\d+)(?: > eval line \\d+)* > eval:\\d+:\\d+/g,\":$1\")),!t.includes(\"@\")))return null;let r=-1,o=\"\",s;for(let h=0;h<t.length;h++)if(t[h]===\"@\"){const p=t.slice(h+1);if(p.includes(\":\")&&p.length>=3){r=h,o=p,s=h>0?t.slice(0,h):void 0;break}}if(r===-1||!o.includes(\":\")||o.length<3)return null;const[c,f,d]=zw(o);return!c||!f||!d?null:{file:c,method:s||\"\",line:Number.parseInt(f),column:Number.parseInt(d)}}function bA(e){let t=e.trim();if(!Dw.test(t))return null;t.includes(\"(eval \")&&(t=t.replace(/eval code/g,\"eval\").replace(/(\\(eval at [^()]*)|(,.*$)/g,\"\"));let r=t.replace(/^\\s+/,\"\").replace(/\\(eval code/g,\"(\").replace(/^.*?\\s+/,\"\");const o=r.match(/ (\\(.+\\)$)/);r=o?r.replace(o[0],\"\"):r;const[s,c,f]=zw(o?o[1]:r);let d=o&&r||\"\",h=s&&[\"eval\",\"<anonymous>\"].includes(s)?void 0:s;return!h||!c||!f?null:(d.startsWith(\"async \")&&(d=d.slice(6)),h.startsWith(\"file://\")&&(h=h.slice(7)),h=h.startsWith(\"node:\")||h.startsWith(\"internal:\")?h:$w(h),d&&(d=d.replace(/__vite_ssr_import_\\d+__\\./g,\"\").replace(/(Object\\.)?__vite_ssr_export_default__\\s?/g,\"\")),{method:d,file:h,line:Number.parseInt(c),column:Number.parseInt(f)})}function wA(e,t={}){const{ignoreStackEntries:r=vA}=t;return(Dw.test(e)?kA(e):xA(e)).map(s=>{var c;t.getUrlId&&(s.file=t.getUrlId(s.file));const f=(c=t.getSourceMap)===null||c===void 0?void 0:c.call(t,s.file);if(!f||typeof f!=\"object\"||!f.version)return Jv(r,s.file)?null:s;const d=new SA(f,s.file),h=TA(d,s);if(!h)return s;const{line:p,column:g,source:v,name:b}=h;let w=v||s.file;return w.match(/\\/\\w:\\//)&&(w=w.slice(1)),Jv(r,w)?null:p!=null&&g!=null?{line:p,column:g,file:w,method:b||s.method}:s}).filter(s=>s!=null)}function Jv(e,t){return e.some(r=>t.match(r))}function xA(e){return e.split(`\n`).map(t=>yA(t)).filter(Rw)}function kA(e){return e.split(`\n`).map(t=>bA(t)).filter(Rw)}class SA{_encoded;_decoded;_decodedMemo;url;version;names=[];resolvedSources;constructor(t,r){this.map=t;const{mappings:o,names:s,sources:c}=t;this.version=t.version,this.names=s||[],this._encoded=o||\"\",this._decodedMemo=_A(),this.url=r,this.resolvedSources=(c||[]).map(f=>$w(f||\"\",r))}}function _A(){return{lastKey:-1,lastNeedle:-1,lastIndex:-1}}function TA(e,t){const r=pA(e,t);return r.column==null?null:r}const CA=/^[A-Za-z]:\\//;function Fw(e=\"\"){return e&&e.replace(/\\\\/g,\"/\").replace(CA,t=>t.toUpperCase())}const EA=/^[/\\\\]{2}/,AA=/^[/\\\\](?![/\\\\])|^[/\\\\]{2}(?!\\.)|^[A-Za-z]:[/\\\\]/,LA=/^[A-Za-z]:$/,Qv=/^\\/([A-Za-z]:)?$/,MA=function(e){if(e.length===0)return\".\";e=Fw(e);const t=e.match(EA),r=xu(e),o=e[e.length-1]===\"/\";return e=Hw(e,!r),e.length===0?r?\"/\":o?\"./\":\".\":(o&&(e+=\"/\"),LA.test(e)&&(e+=\"/\"),t?r?`//${e}`:`//./${e}`:r&&!xu(e)?`/${e}`:e)},NA=function(...e){let t=\"\";for(const r of e)if(r)if(t.length>0){const o=t[t.length-1]===\"/\",s=r[0]===\"/\";o&&s?t+=r.slice(1):t+=o||s?r:`/${r}`}else t+=r;return MA(t)};function OA(){return typeof process<\"u\"&&typeof process.cwd==\"function\"?process.cwd().replace(/\\\\/g,\"/\"):\"/\"}const ey=function(...e){e=e.map(o=>Fw(o));let t=\"\",r=!1;for(let o=e.length-1;o>=-1&&!r;o--){const s=o>=0?e[o]:OA();!s||s.length===0||(t=`${s}/${t}`,r=xu(s))}return t=Hw(t,!r),r&&!xu(t)?`/${t}`:t.length>0?t:\".\"};function Hw(e,t){let r=\"\",o=0,s=-1,c=0,f=null;for(let d=0;d<=e.length;++d){if(d<e.length)f=e[d];else{if(f===\"/\")break;f=\"/\"}if(f===\"/\"){if(!(s===d-1||c===1))if(c===2){if(r.length<2||o!==2||r[r.length-1]!==\".\"||r[r.length-2]!==\".\"){if(r.length>2){const h=r.lastIndexOf(\"/\");h===-1?(r=\"\",o=0):(r=r.slice(0,h),o=r.length-1-r.lastIndexOf(\"/\")),s=d,c=0;continue}else if(r.length>0){r=\"\",o=0,s=d,c=0;continue}}t&&(r+=r.length>0?\"/..\":\"..\",o=2)}else r.length>0?r+=`/${e.slice(s+1,d)}`:r=e.slice(s+1,d),o=d-s-1;s=d,c=0}else f===\".\"&&c!==-1?++c:c=-1}return r}const xu=function(e){return AA.test(e)},af=function(e,t){const r=ey(e).replace(Qv,\"$1\").split(\"/\"),o=ey(t).replace(Qv,\"$1\").split(\"/\");if(o[0][1]===\":\"&&r[0][1]===\":\"&&r[0]!==o[0])return o.join(\"/\");const s=[...r];for(const c of s){if(o[0]!==c)break;r.shift(),o.shift()}return[...r.map(()=>\"..\"),...o].join(\"/\")};function PA(e){let t=0;if(e.length===0)return`${t}`;for(let r=0;r<e.length;r++){const o=e.charCodeAt(r);t=(t<<5)-t+o,t=t&t}return`${t}`}function Bw(e,t,r,o,s){const c=af(t,e),f={id:RA(c,r),name:c,fullName:c,type:\"suite\",mode:\"queued\",filepath:e,tasks:[],meta:Object.create(null),projectName:r,file:void 0,pool:o,viteEnvironment:s};return f.file=f,f}function RA(e,t){return PA(`${e}${t||\"\"}`)}function Js(e){return e.type===\"test\"}function Ww(e){const t=[],r=pp(e);for(const o of r)if(Js(o))t.push(o);else for(const s of o.tasks)if(Js(s))t.push(s);else{const c=Ww(s);for(const f of c)t.push(f)}return t}function gp(e=[]){return pp(e).flatMap(t=>Js(t)?[t]:[t,...gp(t.tasks)])}function $A(e){const t=[e.name];let r=e;for(;r?.suite;)r=r.suite,r?.name&&t.unshift(r.name);return r!==e.file&&t.unshift(e.file.name),t}const ty=\"q\",ny=\"s\";function IA(){let e,t;return{promise:new Promise((r,o)=>{e=r,t=o}),resolve:e,reject:t}}const DA=Math.random.bind(Math),zA=\"useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict\";function FA(e=21){let t=\"\",r=e;for(;r--;)t+=zA[DA()*64|0];return t}const HA=6e4,qw=e=>e,BA=qw,{clearTimeout:ry,setTimeout:WA}=globalThis;function qA(e,t){const{post:r,on:o,off:s=()=>{},eventNames:c=[],serialize:f=qw,deserialize:d=BA,resolver:h,bind:p=\"rpc\",timeout:g=HA,proxify:v=!0}=t;let b=!1;const w=new Map;let E,L;async function P($,W,ne,ee){if(b)throw new Error(`[birpc] rpc is closed, cannot call \"${$}\"`);const Z={m:$,a:W,t:ty};ee&&(Z.o=!0);const G=async B=>r(f(B));if(ne){await G(Z);return}if(E)try{await E}finally{E=void 0}let{promise:j,resolve:N,reject:O}=IA();const C=FA();Z.i=C;let k;async function z(B=Z){return g>=0&&(k=WA(()=>{try{if(t.onTimeoutError?.call(L,$,W)!==!0)throw new Error(`[birpc] timeout on calling \"${$}\"`)}catch(ce){O(ce)}w.delete(C)},g),typeof k==\"object\"&&(k=k.unref?.())),w.set(C,{resolve:N,reject:O,timeoutId:k,method:$}),await G(B),j}try{t.onRequest?await t.onRequest.call(L,Z,z,N):await z()}catch(B){if(t.onGeneralError?.call(L,B)!==!0)throw B;return}finally{ry(k),w.delete(C)}return j}const M={$call:($,...W)=>P($,W,!1),$callOptional:($,...W)=>P($,W,!1,!0),$callEvent:($,...W)=>P($,W,!0),$callRaw:$=>P($.method,$.args,$.event,$.optional),$rejectPendingCalls:I,get $closed(){return b},get $meta(){return t.meta},$close:R,$functions:e};v?L=new Proxy({},{get($,W){if(Object.prototype.hasOwnProperty.call(M,W))return M[W];if(W===\"then\"&&!c.includes(\"then\")&&!(\"then\"in e))return;const ne=(...Z)=>P(W,Z,!0);if(c.includes(W))return ne.asEvent=ne,ne;const ee=(...Z)=>P(W,Z,!1);return ee.asEvent=ne,ee}}):L=M;function R($){b=!0,w.forEach(({reject:W,method:ne})=>{const ee=new Error(`[birpc] rpc is closed, cannot call \"${ne}\"`);if($)return $.cause??=ee,W($);W(ee)}),w.clear(),s(_)}function I($){const W=Array.from(w.values()).map(({method:ne,reject:ee})=>$?$({method:ne,reject:ee}):ee(new Error(`[birpc]: rejected pending call \"${ne}\".`)));return w.clear(),W}async function _($,...W){let ne;try{ne=d($)}catch(ee){if(t.onGeneralError?.call(L,ee)!==!0)throw ee;return}if(ne.t===ty){const{m:ee,a:Z,o:G}=ne;let j,N,O=await(h?h.call(L,ee,e[ee]):e[ee]);if(G&&(O||=()=>{}),!O)N=new Error(`[birpc] function \"${ee}\" not found`);else try{j=await O.apply(p===\"rpc\"?L:e,Z)}catch(C){N=C}if(ne.i){if(N&&t.onFunctionError&&t.onFunctionError.call(L,N,ee,Z)===!0)return;if(!N)try{await r(f({t:ny,i:ne.i,r:j}),...W);return}catch(C){if(N=C,t.onGeneralError?.call(L,C,ee,Z)!==!0)throw C}try{await r(f({t:ny,i:ne.i,e:N}),...W)}catch(C){if(t.onGeneralError?.call(L,C,ee,Z)!==!0)throw C}}}else{const{i:ee,r:Z,e:G}=ne,j=w.get(ee);j&&(ry(j.timeoutId),G?j.reject(G):j.resolve(Z)),w.delete(ee)}}return E=o(_),L}const{parse:jw,stringify:jA}=JSON,{keys:UA}=Object,ka=String,Uw=\"string\",iy={},ku=\"object\",Vw=(e,t)=>t,VA=e=>e instanceof ka?ka(e):e,GA=(e,t)=>typeof t===Uw?new ka(t):t,Gw=(e,t,r,o)=>{const s=[];for(let c=UA(r),{length:f}=c,d=0;d<f;d++){const h=c[d],p=r[h];if(p instanceof ka){const g=e[p];typeof g===ku&&!t.has(g)?(t.add(g),r[h]=iy,s.push({k:h,a:[e,t,g,o]})):r[h]=o.call(r,h,g)}else r[h]!==iy&&(r[h]=o.call(r,h,p))}for(let{length:c}=s,f=0;f<c;f++){const{k:d,a:h}=s[f];r[d]=o.call(r,d,Gw.apply(null,h))}return r},oy=(e,t,r)=>{const o=ka(t.push(r)-1);return e.set(r,o),o},fh=(e,t)=>{const r=jw(e,GA).map(VA),o=r[0],s=t||Vw,c=typeof o===ku&&o?Gw(r,new Set,o,s):o;return s.call({\"\":c},\"\",c)},Kw=(e,t,r)=>{const o=t&&typeof t===ku?(g,v)=>g===\"\"||-1<t.indexOf(g)?v:void 0:t||Vw,s=new Map,c=[],f=[];let d=+oy(s,c,o.call({\"\":e},\"\",e)),h=!d;for(;d<c.length;)h=!0,f[d]=jA(c[d++],p,r);return\"[\"+f.join(\",\")+\"]\";function p(g,v){if(h)return h=!h,v;const b=o.call(this,g,v);switch(typeof b){case ku:if(b===null)return b;case Uw:return s.get(b)||oy(s,c,b)}return b}},KA=e=>jw(Kw(e));class Xw{filesMap=new Map;pathsSet=new Set;idMap=new Map;getPaths(){return Array.from(this.pathsSet)}getFiles(t){return t?t.map(r=>this.filesMap.get(r)).flat().filter(r=>r&&!r.local):Array.from(this.filesMap.values()).flat().filter(r=>!r.local)}getFilepaths(){return Array.from(this.filesMap.keys())}getFailedFilepaths(){return this.getFiles().filter(t=>t.result?.state===\"fail\").map(t=>t.filepath)}collectPaths(t=[]){t.forEach(r=>{this.pathsSet.add(r)})}collectFiles(t=[]){t.forEach(r=>{const o=this.filesMap.get(r.filepath)||[],s=o.filter(f=>f.projectName!==r.projectName||f.meta.typecheck!==r.meta.typecheck),c=o.find(f=>f.projectName===r.projectName);c&&(r.logs=c.logs),s.push(r),this.filesMap.set(r.filepath,s),this.updateId(r)})}clearFiles(t,r=[]){const o=t;r.forEach(s=>{const c=this.filesMap.get(s),f=Bw(s,o.config.root,o.config.name||\"\");if(f.local=!0,this.idMap.set(f.id,f),!c){this.filesMap.set(s,[f]);return}const d=c.filter(h=>h.projectName!==o.config.name);d.length?this.filesMap.set(s,[...d,f]):this.filesMap.set(s,[f])})}updateId(t){this.idMap.get(t.id)!==t&&(this.idMap.set(t.id,t),t.type===\"suite\"&&t.tasks.forEach(r=>{this.updateId(r)}))}updateTasks(t){for(const[r,o,s]of t){const c=this.idMap.get(r);c&&(c.result=o,c.meta=s,o?.state===\"skip\"&&(c.mode=\"skip\"))}}updateUserLog(t){const r=t.taskId&&this.idMap.get(t.taskId);r&&(r.logs||(r.logs=[]),r.logs.push(t))}}function XA(e,t={}){const{handlers:r={},autoReconnect:o=!0,reconnectInterval:s=2e3,reconnectTries:c=10,connectTimeout:f=6e4,reactive:d=R=>R,WebSocketConstructor:h=globalThis.WebSocket}=t;let p=c;const g=d({ws:new h(e),state:new Xw,waitForConnection:M,reconnect:L},\"state\");g.state.filesMap=d(g.state.filesMap,\"filesMap\"),g.state.idMap=d(g.state.idMap,\"idMap\");let v;const b={onTestAnnotate(R,I){r.onTestAnnotate?.(R,I)},onTestArtifactRecord(R,I){r.onTestArtifactRecord?.(R,I)},onSpecsCollected(R,I){R?.forEach(([_,$])=>{g.state.clearFiles({config:_},[$])}),r.onSpecsCollected?.(R,I)},onPathsCollected(R){g.state.collectPaths(R),r.onPathsCollected?.(R)},onCollected(R){g.state.collectFiles(R),r.onCollected?.(R)},onTaskUpdate(R,I){g.state.updateTasks(R),r.onTaskUpdate?.(R,I)},onUserConsoleLog(R){g.state.updateUserLog(R),r.onUserConsoleLog?.(R)},onFinished(R,I,_,$){r.onFinished?.(R,I,_,$)},onFinishedReportCoverage(){r.onFinishedReportCoverage?.()}},w={post:R=>g.ws.send(R),on:R=>v=R,serialize:R=>Kw(R,(I,_)=>_ instanceof Error?{name:_.name,message:_.message,stack:_.stack}:_),deserialize:fh,timeout:-1};g.rpc=qA(b,w);let E;function L(R=!1){R&&(p=c),g.ws=new h(e),P()}function P(){E=new Promise((R,I)=>{const _=setTimeout(()=>{I(new Error(`Cannot connect to the server in ${f/1e3} seconds`))},f)?.unref?.();g.ws.OPEN===g.ws.readyState&&R(),g.ws.addEventListener(\"open\",()=>{p=c,R(),clearTimeout(_)})}),g.ws.addEventListener(\"message\",R=>{v(R.data)}),g.ws.addEventListener(\"close\",()=>{p-=1,o&&p>0&&setTimeout(L,s)})}P();function M(){return E}return g}const dh=Ft([]),Jn=Ft([]),Dr=sf(\"vitest-ui_task-tree-opened\",[],{shallow:!0}),Su=ke(()=>new Set(Dr.value)),gn=sf(\"vitest-ui_task-tree-filter\",{expandAll:void 0,failed:!1,success:!1,skipped:!1,onlyTests:!1,search:\"\"}),Vn=Ge(gn.value.search),YA={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\"};function Yw(e){return e.replace(/[&<>\"']/g,t=>YA[t])}const ZA=ke(()=>{const e=Vn.value.toLowerCase();return e.length?new RegExp(`(${Yw(e)})`,\"gi\"):null}),Zw=ke(()=>Vn.value.trim()!==\"\"),it=ir({failed:gn.value.failed,success:gn.value.success,skipped:gn.value.skipped,onlyTests:gn.value.onlyTests}),hh=ke(()=>!!(it.failed||it.success||it.skipped)),cf=Ft([]),Qs=Ge(!1),sy=ke(()=>{const e=gn.value.expandAll;return Dr.value.length>0?e!==!0:e!==!1}),JA=ke(()=>{const e=Zw.value,t=hh.value,r=it.onlyTests,o=Oe.summary.filesFailed,s=Oe.summary.filesSuccess,c=Oe.summary.filesSkipped,f=Oe.summary.filesRunning,d=cf.value;return Oe.collectTestsTotal(e||t,r,d,{failed:o,success:s,skipped:c,running:f})});function Ha(e){return Object.hasOwn(e,\"tasks\")}function QA(e,t){return typeof e!=\"string\"||typeof t!=\"string\"?!1:e.toLowerCase().includes(t.toLowerCase())}function Fo(e){return e>1e3?`${(e/1e3).toFixed(2)}s`:`${Math.round(e)}ms`}function Ed(e){return e>1e3?`${(e/1e3).toFixed(2)}s`:`${e.toFixed(2)}ms`}function eL(e){const t=new Map,r=new Map,o=[];for(;;){let s=0;if(e.forEach((c,f)=>{const{splits:d,finished:h}=c;if(h){s++;const{raw:g,candidate:v}=c;t.set(g,v);return}if(d.length===0){c.finished=!0;return}const p=d[0];r.has(p)?(c.candidate+=c.candidate===\"\"?p:`/${p}`,r.get(p)?.push(f),d.shift()):(r.set(p,[f]),o.push(f))}),o.forEach(c=>{const f=e[c],d=f.splits.shift();f.candidate+=f.candidate===\"\"?d:`/${d}`}),r.forEach(c=>{if(c.length===1){const f=c[0];e[f].finished=!0}}),r.clear(),o.length=0,s===e.length)break}return t}function Jw(e){let t=e;t.includes(\"/node_modules/\")&&(t=e.split(/\\/node_modules\\//g).pop());const r=t.split(/\\//g);return{raw:t,splits:r,candidate:\"\",finished:!1,id:e}}function tL(e){return Jw(e).raw}function Xc(e){if(e>=500)return\"danger\";if(e>=100)return\"warning\"}function _u(e){const t=Xc(e);if(t===\"danger\")return\"text-red\";if(t===\"warning\")return\"text-orange\"}function Qw(e){if(!e)return\"\";const t=e.split(\"\").reduce((o,s,c)=>o+s.charCodeAt(0)+c,0),r=[\"yellow\",\"cyan\",\"green\",\"magenta\"];return r[t%r.length]}function ex(e){switch(e){case\"blue\":case\"green\":case\"magenta\":case\"black\":case\"red\":return\"white\";case\"yellow\":case\"cyan\":case\"white\":default:return\"black\"}}function nL(e){return e.type===\"test\"}function rL(e){return e.mode===\"run\"&&e.type===\"test\"}function In(e){return e.type===\"file\"}function Ci(e){return e.type===\"file\"||e.type===\"suite\"}function iL(e=Oe.root.tasks){return e.sort((t,r)=>`${t.filepath}:${t.projectName}`.localeCompare(`${r.filepath}:${r.projectName}`))}function Sa(e,t=!1){let r=Oe.nodes.get(e.id);if(r?(r.typecheck=!!e.meta&&\"typecheck\"in e.meta,r.state=e.result?.state,r.mode=e.mode,r.duration=typeof e.result?.duration==\"number\"?Math.round(e.result.duration):void 0,r.collectDuration=e.collectDuration,r.setupDuration=e.setupDuration,r.environmentLoad=e.environmentLoad,r.prepareDuration=e.prepareDuration):(r={id:e.id,parentId:\"root\",name:e.name,mode:e.mode,expandable:!0,expanded:Su.value.size>0&&Su.value.has(e.id),type:\"file\",children:new Set,tasks:[],typecheck:!!e.meta&&\"typecheck\"in e.meta,indent:0,duration:typeof e.result?.duration==\"number\"?Math.round(e.result.duration):void 0,filepath:e.filepath,projectName:e.projectName||\"\",projectNameColor:Oe.colors.get(e.projectName||\"\")||Qw(e.projectName),collectDuration:e.collectDuration,setupDuration:e.setupDuration,environmentLoad:e.environmentLoad,prepareDuration:e.prepareDuration,state:e.result?.state},Oe.nodes.set(e.id,r),Oe.root.tasks.push(r)),t)for(let o=0;o<e.tasks.length;o++)Ba(e.id,e.tasks[o],!0)}function tx(e,t){const r=Oe.nodes.get(e);if(!r||!Ci(r))return;const o=ft.state.idMap.get(e);if(!(!o||!Ha(o)))return Ba(r.parentId,o,t&&o.tasks.length>0),[r,o]}function oL(e){const t=Oe.nodes.get(e);if(!t)return;const r=ft.state.idMap.get(e);!r||!Js(r)||Ba(t.parentId,r,!1)}function Ba(e,t,r){const o=Oe.nodes.get(e);let s;const c=typeof t.result?.duration==\"number\"?Math.round(t.result.duration):void 0;if(o&&(s=Oe.nodes.get(t.id),s?(o.children.has(t.id)||(o.tasks.push(s),o.children.add(t.id)),s.name=t.name,s.mode=t.mode,s.duration=c,s.state=t.result?.state):(Js(t)?s={id:t.id,fileId:t.file.id,parentId:e,name:t.name,mode:t.mode,type:t.type,expandable:!1,expanded:!1,indent:o.indent+1,duration:c,state:t.result?.state}:s={id:t.id,fileId:t.file.id,parentId:e,name:t.name,mode:t.mode,type:\"suite\",expandable:!0,expanded:Su.value.size>0&&Su.value.has(t.id),children:new Set,tasks:[],indent:o.indent+1,duration:c,state:t.result?.state},Oe.nodes.set(t.id,s),o.tasks.push(s),o.children.add(t.id)),s&&r&&Ha(t)))for(let f=0;f<t.tasks.length;f++)Ba(s.id,t.tasks[f],r)}function sL(e){const t=Oe.nodes.get(e);if(!t||!Ci(t))return;const r=new Set(Dr.value);r.delete(t.id);const o=[...aL(t)];Dr.value=Array.from(r),Jn.value=o}function lL(){ph(Oe.root.tasks);const e=[...Jn.value.filter(In)];ph(e),Dr.value=[],gn.value.expandAll=!0,Jn.value=e}function ph(e){for(const t of e)Ci(t)&&(t.expanded=!1,ph(t.tasks))}function*nx(e,t){if(t&&(yield e.id),Ci(e))for(let r=0;r<e.tasks.length;r++)yield*nx(e.tasks[r],!0)}function*aL(e){const t=e.id,r=new Set(nx(e,!1));for(let o=0;o<Jn.value.length;o++){const s=Jn.value[o];if(s.id===t){s.expanded=!1,yield s;continue}if(r.has(s.id)){r.delete(s.id);continue}yield s}}const uf=Ge(\"idle\"),Ms=ke(()=>uf.value===\"idle\"),eo=Ge([]);function cL(e,t,r){return e?ox(e,t,r):!1}function mp(e,t){const r=[...rx(e,t)];Jn.value=r,cf.value=r.filter(In).map(o=>mr(o.id))}function*rx(e,t){for(const r of iL())yield*ix(r,e,t)}function*ix(e,t,r){const o=new Set,s=new Map,c=[];let f;if(r.onlyTests)for(const[v,b]of gh(e,o,w=>ly(w,t,r)))c.push([v,b]);else{for(const[v,b]of gh(e,o,w=>ly(w,t,r)))Ci(b)?(s.set(b.id,v),In(b)?(v&&(f=b.id),c.push([v,b])):c.push([v||s.get(b.parentId)===!0,b])):c.push([v||s.get(b.parentId)===!0,b]);!f&&!In(e)&&\"fileId\"in e&&(f=e.fileId)}const d=new Set,h=[...fL(c,r.onlyTests,o,d,f)].reverse(),p=Oe.nodes,g=new Set(h.filter(v=>In(v)||Ci(v)&&p.get(v.parentId)?.expanded).map(v=>v.id));yield*h.filter(v=>In(v)||g.has(v.parentId)&&p.get(v.parentId)?.expanded)}function uL(e,t,r,o,s){if(o){if(In(t))return s.has(t.id)?t:void 0;if(r.has(t.id)){const c=Oe.nodes.get(t.parentId);return c&&In(c)&&s.add(c.id),t}}else if(e||r.has(t.id)||s.has(t.id)){const c=Oe.nodes.get(t.parentId);return c&&In(c)&&s.add(c.id),t}}function*fL(e,t,r,o,s){for(let c=e.length-1;c>=0;c--){const[f,d]=e[c],h=Ci(d);if(!t&&s&&r.has(s)&&\"fileId\"in d&&d.fileId===s){h&&r.add(d.id);let p=Oe.nodes.get(d.parentId);for(;p;)r.add(p.id),In(p)&&o.add(p.id),p=Oe.nodes.get(p.parentId);yield d;continue}if(h){const p=uL(f,d,r,t,o);p&&(yield p)}else if(f){const p=Oe.nodes.get(d.parentId);p&&In(p)&&o.add(p.id),yield d}}}function dL(e,t){return(t.success||t.failed)&&\"result\"in e&&(t.success&&e.result?.state===\"pass\"||t.failed&&e.result?.state===\"fail\")?!0:t.skipped&&\"mode\"in e?e.mode===\"skip\"||e.mode===\"todo\":!1}function ox(e,t,r){if(t.length===0||QA(e.name,t))if(r.success||r.failed||r.skipped){if(dL(e,r))return!0}else return!0;return!1}function*gh(e,t,r){const o=r(e);if(o)if(nL(e)){let s=Oe.nodes.get(e.parentId);for(;s;)t.add(s.id),s=Oe.nodes.get(s.parentId)}else if(In(e))t.add(e.id);else{t.add(e.id);let s=Oe.nodes.get(e.parentId);for(;s;)t.add(s.id),s=Oe.nodes.get(s.parentId)}if(yield[o,e],Ci(e))for(let s=0;s<e.tasks.length;s++)yield*gh(e.tasks[s],t,r)}function ly(e,t,r){const o=ft.state.idMap.get(e.id);return o?ox(o,t,r):!1}function hL(e,t,r){const o=tx(e,!1);if(!o)return;const[s,c]=o;for(const p of c.tasks)Ba(s.id,p,!1);s.expanded=!0;const f=new Set(Dr.value);f.add(s.id);const d=new Set(ix(s,t,r)),h=[...mL(s,d)];Dr.value=Array.from(f),Jn.value=h}function pL(e,t){vp(Oe.root.tasks,!1);const r=[...rx(e,t)];gn.value.expandAll=!1,Dr.value=[],Jn.value=r,cf.value=r.filter(In).map(o=>mr(o.id))}function gL(e,t){if(e.size)for(const r of Jn.value)e.has(r.id)&&(r.expanded=!0);else t&&vp(Jn.value.filter(In),!0)}function vp(e,t){for(const r of e)Ci(r)&&(r.expanded=!0,vp(r.tasks,!1));t&&(gn.value.expandAll=!1,Dr.value=[])}function*mL(e,t){const r=e.id,o=new Set(Array.from(t).map(s=>s.id));for(const s of Jn.value)s.id===r?(s.expanded=!0,o.has(s.id)||(yield e),yield*t):o.has(s.id)||(yield s)}function yp(e){return Ww(e).some(t=>t.result?.errors?.some(r=>typeof r?.message==\"string\"&&r.message.match(/Snapshot .* mismatched/)))}function vL(e,t,r,o){e.map(s=>[`${s.filepath}:${s.projectName||\"\"}`,s]).sort(([s],[c])=>s.localeCompare(c)).map(([,s])=>Sa(s,t)),dh.value=[...Oe.root.tasks],mp(r.trim(),{failed:o.failed,success:o.success,skipped:o.skipped,onlyTests:o.onlyTests})}function yL(e){queueMicrotask(()=>{const t=Oe.pendingTasks,r=ft.state.idMap;for(const o of e)if(o[1]){const c=r.get(o[0]);if(c){let f=t.get(c.file.id);f||(f=new Set,t.set(c.file.id,f)),f.add(c.id)}}})}function bL(e,t){const r=Oe.pendingTasks,s=ft.state.idMap.get(e);if(s?.type===\"test\"){let c=r.get(s.file.id);c||(c=new Set,r.set(s.file.id,c)),c.add(s.id),t.type===\"internal:annotation\"?s.annotations.push(t.annotation):s.artifacts.push(t)}}function ay(e,t,r,o,s,c){e&&TL(r);const f=!e;queueMicrotask(()=>{t?kL(f):SL(f)}),queueMicrotask(()=>{CL(r,c)}),queueMicrotask(()=>{t&&(r.failedSnapshot=dh.value&&yp(dh.value.map(d=>mr(d.id))),r.failedSnapshotEnabled=!0)}),queueMicrotask(()=>{_L(o,s,t)})}function*wL(){yield*Jn.value.filter(rL)}function xL(){const e=ft.state.idMap;let t;for(const r of wL())t=e.get(r.parentId),t&&Ha(t)&&t.mode===\"todo\"&&(t=e.get(r.id),t&&(t.mode=\"todo\"))}function kL(e){const t=ft.state.getFiles(),r=Oe.nodes,o=t.filter(c=>!r.has(c.id));for(let c=0;c<o.length;c++)Sa(o[c],e),Tu(o[c].tasks);const s=Oe.root.tasks;for(let c=0;c<s.length;c++){const f=s[c],d=mr(f.id);!d||(Sa(d,e),!d.tasks?.length)||Tu(d.tasks)}}function SL(e){const t=new Map(Oe.pendingTasks.entries());Oe.pendingTasks.clear();const r=Oe.nodes,o=Array.from(t.keys()).filter(d=>!r.has(d)).map(d=>mr(d)).filter(Boolean);let s;for(let d=0;d<o.length;d++)s=o[d],Sa(s,!1),Tu(s.tasks),t.delete(s.id);const c=ft.state.idMap,f=Oe.root.tasks;for(let d=0;d<f.length;d++){const h=f[d],p=mr(h.id);if(!p)continue;const g=t.get(p.id);g&&(Sa(p,e),Tu(Array.from(g,v=>c.get(v)).filter(Boolean)))}}function _L(e,t,r=!1){const o=gn.value.expandAll,s=o!==!0,c=new Set(Dr.value),f=c.size>0&&o===!1||s;queueMicrotask(()=>{cy(e,t,r)}),Qs.value||queueMicrotask(()=>{(Jn.value.length||r)&&(Qs.value=!0)}),f&&(queueMicrotask(()=>{gL(c,r),s&&(gn.value.expandAll=!1)}),queueMicrotask(()=>{cy(e,t,r)}))}function cy(e,t,r){mp(e,t),r&&(xL(),uf.value=\"idle\")}function Tu(e){let t;for(let r=0;r<e.length;r++)t=e[r],Ha(t)?tx(t.id,!0):oL(t.id)}function TL(e){e.files=0,e.time=\"\",e.filesFailed=0,e.filesSuccess=0,e.filesIgnore=0,e.filesRunning=0,e.filesSkipped=0,e.filesTodo=0,e.testsFailed=0,e.testsSuccess=0,e.testsIgnore=0,e.testsSkipped=0,e.testsTodo=0,e.totalTests=0,e.failedSnapshotEnabled=!1}function CL(e,t){const r=ft.state.idMap,o=new Map(Oe.root.tasks.filter(f=>r.has(f.id)).map(f=>[f.id,f])),s=Array.from(o.values(),f=>[f.id,mr(f.id)]),c={files:o.size,time:t>1e3?`${(t/1e3).toFixed(2)}s`:`${Math.round(t)}ms`,filesFailed:0,filesSuccess:0,filesIgnore:0,filesRunning:0,filesSkipped:0,filesTodo:0,testsFailed:0,testsSuccess:0,testsIgnore:0,testsSkipped:0,testsTodo:0,totalTests:0};for(const[f,d]of s){if(!d)continue;d.result?.state===\"fail\"?c.filesFailed++:d.result?.state===\"pass\"?c.filesSuccess++:d.mode===\"skip\"?(c.filesIgnore++,c.filesSkipped++):d.mode===\"todo\"?(c.filesIgnore++,c.filesTodo++):c.filesRunning++;const{failed:h,success:p,skipped:g,total:v,ignored:b,todo:w}=sx(d);c.totalTests+=v,c.testsFailed+=h,c.testsSuccess+=p,c.testsSkipped+=g,c.testsTodo+=w,c.testsIgnore+=b}e.files=c.files,e.time=c.time,e.filesFailed=c.filesFailed,e.filesSuccess=c.filesSuccess,e.filesIgnore=c.filesIgnore,e.filesRunning=c.filesRunning,e.filesSkipped=c.filesSkipped,e.filesTodo=c.filesTodo,e.testsFailed=c.testsFailed,e.testsSuccess=c.testsSuccess,e.testsFailed=c.testsFailed,e.testsTodo=c.testsTodo,e.testsIgnore=c.testsIgnore,e.testsSkipped=c.testsSkipped,e.totalTests=c.totalTests}function sx(e,t=\"\",r){const o={failed:0,success:0,skipped:0,running:0,total:0,ignored:0,todo:0};for(const s of lx(e))(!r||cL(s,t,r))&&(o.total++,s.result?.state===\"fail\"?o.failed++:s.result?.state===\"pass\"?o.success++:s.mode===\"skip\"?(o.ignored++,o.skipped++):s.mode===\"todo\"&&(o.ignored++,o.todo++));return o.running=o.total-o.failed-o.success-o.ignored,o}function EL(e,t,r,o,s,c){if(t)return r.map(f=>sx(f,s,c)).reduce((f,{failed:d,success:h,ignored:p,running:g})=>(f.failed+=d,f.success+=h,f.skipped+=p,f.running+=g,f),{failed:0,success:0,skipped:0,running:0});if(e){const f={failed:0,success:0,skipped:0,running:0},d=!c.success&&!c.failed,h=c.failed||d,p=c.success||d;for(const g of r)g.result?.state===\"fail\"?f.failed+=h?1:0:g.result?.state===\"pass\"?f.success+=p?1:0:g.mode===\"skip\"||g.mode===\"todo\"||f.running++;return f}return o}function*lx(e){const t=pp(e);let r;for(let o=0;o<t.length;o++)r=t[o],Js(r)?yield r:yield*lx(r.tasks)}class AL{constructor(t=[],r=new Map,o=!1,s=500,c={id:\"vitest-root-node\",expandable:!0,expanded:!0,tasks:[]},f=new Map,d=new Map,h=ir({files:0,time:\"\",filesFailed:0,filesSuccess:0,filesIgnore:0,filesRunning:0,filesSkipped:0,filesSnapshotFailed:0,filesTodo:0,testsFailed:0,testsSuccess:0,testsIgnore:0,testsSkipped:0,testsTodo:0,totalTests:0,failedSnapshot:!1,failedSnapshotEnabled:!1})){this.projects=t,this.colors=r,this.onTaskUpdateCalled=o,this.resumeEndTimeout=s,this.root=c,this.pendingTasks=f,this.nodes=d,this.summary=h,this.rafCollector=AE(this.runCollect.bind(this),{fpsLimit:10,immediate:!1})}rafCollector;resumeEndRunId;startTime=0;executionTime=0;loadFiles(t,r){this.projects.splice(0,this.projects.length,...r.map(o=>o.name)),this.colors=new Map(r.map(o=>[o.name,o.color])),vL(t,!0,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})}startRun(){this.startTime=performance.now(),this.resumeEndRunId=setTimeout(()=>this.endRun(),this.resumeEndTimeout),this.collect(!0,!1)}recordTestArtifact(t,r){bL(t,r),this.onTaskUpdateCalled||(clearTimeout(this.resumeEndRunId),this.onTaskUpdateCalled=!0,this.collect(!0,!1,!1),this.rafCollector.resume())}resumeRun(t,r){yL(t),this.onTaskUpdateCalled||(clearTimeout(this.resumeEndRunId),this.onTaskUpdateCalled=!0,this.collect(!0,!1,!1),this.rafCollector.resume())}endRun(t=performance.now()-this.startTime){this.executionTime=t,this.rafCollector.pause(),this.onTaskUpdateCalled=!1,this.collect(!1,!0)}runCollect(){this.collect(!1,!1)}collect(t,r,o=!0){o?queueMicrotask(()=>{ay(t,r,this.summary,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests},r?this.executionTime:performance.now()-this.startTime)}):ay(t,r,this.summary,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests},r?this.executionTime:performance.now()-this.startTime)}collectTestsTotal(t,r,o,s){return EL(t,r,o,s,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})}collapseNode(t){queueMicrotask(()=>{sL(t)})}expandNode(t){queueMicrotask(()=>{hL(t,Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})})}collapseAllNodes(){queueMicrotask(()=>{lL()})}expandAllNodes(){queueMicrotask(()=>{pL(Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})})}filterNodes(){queueMicrotask(()=>{mp(Vn.value.trim(),{failed:it.failed,success:it.success,skipped:it.skipped,onlyTests:it.onlyTests})})}}const Oe=new AL;function ax(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,\"default\")?e.default:e}var Yc={exports:{}},LL=Yc.exports,uy;function vo(){return uy||(uy=1,(function(e,t){(function(r,o){e.exports=o()})(LL,(function(){var r=navigator.userAgent,o=navigator.platform,s=/gecko\\/\\d/i.test(r),c=/MSIE \\d/.test(r),f=/Trident\\/(?:[7-9]|\\d{2,})\\..*rv:(\\d+)/.exec(r),d=/Edge\\/(\\d+)/.exec(r),h=c||f||d,p=h&&(c?document.documentMode||6:+(d||f)[1]),g=!d&&/WebKit\\//.test(r),v=g&&/Qt\\/\\d+\\.\\d+/.test(r),b=!d&&/Chrome\\/(\\d+)/.exec(r),w=b&&+b[1],E=/Opera\\//.test(r),L=/Apple Computer/.test(navigator.vendor),P=/Mac OS X 1\\d\\D([8-9]|\\d\\d)\\D/.test(r),M=/PhantomJS/.test(r),R=L&&(/Mobile\\/\\w+/.test(r)||navigator.maxTouchPoints>2),I=/Android/.test(r),_=R||I||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(r),$=R||/Mac/.test(o),W=/\\bCrOS\\b/.test(r),ne=/win/i.test(o),ee=E&&r.match(/Version\\/(\\d*\\.\\d*)/);ee&&(ee=Number(ee[1])),ee&&ee>=15&&(E=!1,g=!0);var Z=$&&(v||E&&(ee==null||ee<12.11)),G=s||h&&p>=9;function j(n){return new RegExp(\"(^|\\\\s)\"+n+\"(?:$|\\\\s)\\\\s*\")}var N=function(n,i){var a=n.className,l=j(i).exec(a);if(l){var u=a.slice(l.index+l[0].length);n.className=a.slice(0,l.index)+(u?l[1]+u:\"\")}};function O(n){for(var i=n.childNodes.length;i>0;--i)n.removeChild(n.firstChild);return n}function C(n,i){return O(n).appendChild(i)}function k(n,i,a,l){var u=document.createElement(n);if(a&&(u.className=a),l&&(u.style.cssText=l),typeof i==\"string\")u.appendChild(document.createTextNode(i));else if(i)for(var m=0;m<i.length;++m)u.appendChild(i[m]);return u}function z(n,i,a,l){var u=k(n,i,a,l);return u.setAttribute(\"role\",\"presentation\"),u}var B;document.createRange?B=function(n,i,a,l){var u=document.createRange();return u.setEnd(l||n,a),u.setStart(n,i),u}:B=function(n,i,a){var l=document.body.createTextRange();try{l.moveToElementText(n.parentNode)}catch{return l}return l.collapse(!0),l.moveEnd(\"character\",a),l.moveStart(\"character\",i),l};function ce(n,i){if(i.nodeType==3&&(i=i.parentNode),n.contains)return n.contains(i);do if(i.nodeType==11&&(i=i.host),i==n)return!0;while(i=i.parentNode)}function be(n){var i=n.ownerDocument||n,a;try{a=n.activeElement}catch{a=i.body||null}for(;a&&a.shadowRoot&&a.shadowRoot.activeElement;)a=a.shadowRoot.activeElement;return a}function Se(n,i){var a=n.className;j(i).test(a)||(n.className+=(a?\" \":\"\")+i)}function Be(n,i){for(var a=n.split(\" \"),l=0;l<a.length;l++)a[l]&&!j(a[l]).test(i)&&(i+=\" \"+a[l]);return i}var Ae=function(n){n.select()};R?Ae=function(n){n.selectionStart=0,n.selectionEnd=n.value.length}:h&&(Ae=function(n){try{n.select()}catch{}});function Ke(n){return n.display.wrapper.ownerDocument}function je(n){return Fe(n.display.wrapper)}function Fe(n){return n.getRootNode?n.getRootNode():n.ownerDocument}function Pe(n){return Ke(n).defaultView}function F(n){var i=Array.prototype.slice.call(arguments,1);return function(){return n.apply(null,i)}}function Y(n,i,a){i||(i={});for(var l in n)n.hasOwnProperty(l)&&(a!==!1||!i.hasOwnProperty(l))&&(i[l]=n[l]);return i}function re(n,i,a,l,u){i==null&&(i=n.search(/[^\\s\\u00a0]/),i==-1&&(i=n.length));for(var m=l||0,y=u||0;;){var x=n.indexOf(\"\t\",m);if(x<0||x>=i)return y+(i-m);y+=x-m,y+=a-y%a,m=x+1}}var le=function(){this.id=null,this.f=null,this.time=0,this.handler=F(this.onTimeout,this)};le.prototype.onTimeout=function(n){n.id=0,n.time<=+new Date?n.f():setTimeout(n.handler,n.time-+new Date)},le.prototype.set=function(n,i){this.f=i;var a=+new Date+n;(!this.id||a<this.time)&&(clearTimeout(this.id),this.id=setTimeout(this.handler,n),this.time=a)};function ae(n,i){for(var a=0;a<n.length;++a)if(n[a]==i)return a;return-1}var D=50,q={toString:function(){return\"CodeMirror.Pass\"}},Q={scroll:!1},he={origin:\"*mouse\"},de={origin:\"+move\"};function ge(n,i,a){for(var l=0,u=0;;){var m=n.indexOf(\"\t\",l);m==-1&&(m=n.length);var y=m-l;if(m==n.length||u+y>=i)return l+Math.min(y,i-u);if(u+=m-l,u+=a-u%a,l=m+1,u>=i)return l}}var Ce=[\"\"];function Ee(n){for(;Ce.length<=n;)Ce.push(xe(Ce)+\" \");return Ce[n]}function xe(n){return n[n.length-1]}function ye(n,i){for(var a=[],l=0;l<n.length;l++)a[l]=i(n[l],l);return a}function J(n,i,a){for(var l=0,u=a(i);l<n.length&&a(n[l])<=u;)l++;n.splice(l,0,i)}function ue(){}function oe(n,i){var a;return Object.create?a=Object.create(n):(ue.prototype=n,a=new ue),i&&Y(i,a),a}var $e=/[\\u00df\\u0587\\u0590-\\u05f4\\u0600-\\u06ff\\u3040-\\u309f\\u30a0-\\u30ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\uac00-\\ud7af]/;function Je(n){return/\\w/.test(n)||n>\"\"&&(n.toUpperCase()!=n.toLowerCase()||$e.test(n))}function ct(n,i){return i?i.source.indexOf(\"\\\\w\")>-1&&Je(n)?!0:i.test(n):Je(n)}function dt(n){for(var i in n)if(n.hasOwnProperty(i)&&n[i])return!1;return!0}var Nt=/[\\u0300-\\u036f\\u0483-\\u0489\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u064b-\\u065e\\u0670\\u06d6-\\u06dc\\u06de-\\u06e4\\u06e7\\u06e8\\u06ea-\\u06ed\\u0711\\u0730-\\u074a\\u07a6-\\u07b0\\u07eb-\\u07f3\\u0816-\\u0819\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0900-\\u0902\\u093c\\u0941-\\u0948\\u094d\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09bc\\u09be\\u09c1-\\u09c4\\u09cd\\u09d7\\u09e2\\u09e3\\u0a01\\u0a02\\u0a3c\\u0a41\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a70\\u0a71\\u0a75\\u0a81\\u0a82\\u0abc\\u0ac1-\\u0ac5\\u0ac7\\u0ac8\\u0acd\\u0ae2\\u0ae3\\u0b01\\u0b3c\\u0b3e\\u0b3f\\u0b41-\\u0b44\\u0b4d\\u0b56\\u0b57\\u0b62\\u0b63\\u0b82\\u0bbe\\u0bc0\\u0bcd\\u0bd7\\u0c3e-\\u0c40\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62\\u0c63\\u0cbc\\u0cbf\\u0cc2\\u0cc6\\u0ccc\\u0ccd\\u0cd5\\u0cd6\\u0ce2\\u0ce3\\u0d3e\\u0d41-\\u0d44\\u0d4d\\u0d57\\u0d62\\u0d63\\u0dca\\u0dcf\\u0dd2-\\u0dd4\\u0dd6\\u0ddf\\u0e31\\u0e34-\\u0e3a\\u0e47-\\u0e4e\\u0eb1\\u0eb4-\\u0eb9\\u0ebb\\u0ebc\\u0ec8-\\u0ecd\\u0f18\\u0f19\\u0f35\\u0f37\\u0f39\\u0f71-\\u0f7e\\u0f80-\\u0f84\\u0f86\\u0f87\\u0f90-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u102d-\\u1030\\u1032-\\u1037\\u1039\\u103a\\u103d\\u103e\\u1058\\u1059\\u105e-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108d\\u109d\\u135f\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17b7-\\u17bd\\u17c6\\u17c9-\\u17d3\\u17dd\\u180b-\\u180d\\u18a9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193b\\u1a17\\u1a18\\u1a56\\u1a58-\\u1a5e\\u1a60\\u1a62\\u1a65-\\u1a6c\\u1a73-\\u1a7c\\u1a7f\\u1b00-\\u1b03\\u1b34\\u1b36-\\u1b3a\\u1b3c\\u1b42\\u1b6b-\\u1b73\\u1b80\\u1b81\\u1ba2-\\u1ba5\\u1ba8\\u1ba9\\u1c2c-\\u1c33\\u1c36\\u1c37\\u1cd0-\\u1cd2\\u1cd4-\\u1ce0\\u1ce2-\\u1ce8\\u1ced\\u1dc0-\\u1de6\\u1dfd-\\u1dff\\u200c\\u200d\\u20d0-\\u20f0\\u2cef-\\u2cf1\\u2de0-\\u2dff\\u302a-\\u302f\\u3099\\u309a\\ua66f-\\ua672\\ua67c\\ua67d\\ua6f0\\ua6f1\\ua802\\ua806\\ua80b\\ua825\\ua826\\ua8c4\\ua8e0-\\ua8f1\\ua926-\\ua92d\\ua947-\\ua951\\ua980-\\ua982\\ua9b3\\ua9b6-\\ua9b9\\ua9bc\\uaa29-\\uaa2e\\uaa31\\uaa32\\uaa35\\uaa36\\uaa43\\uaa4c\\uaab0\\uaab2-\\uaab4\\uaab7\\uaab8\\uaabe\\uaabf\\uaac1\\uabe5\\uabe8\\uabed\\udc00-\\udfff\\ufb1e\\ufe00-\\ufe0f\\ufe20-\\ufe26\\uff9e\\uff9f]/;function ut(n){return n.charCodeAt(0)>=768&&Nt.test(n)}function Yt(n,i,a){for(;(a<0?i>0:i<n.length)&&ut(n.charAt(i));)i+=a;return i}function jt(n,i,a){for(var l=i>a?-1:1;;){if(i==a)return i;var u=(i+a)/2,m=l<0?Math.ceil(u):Math.floor(u);if(m==i)return n(m)?i:a;n(m)?a=m:i=m+l}}function Fn(n,i,a,l){if(!n)return l(i,a,\"ltr\",0);for(var u=!1,m=0;m<n.length;++m){var y=n[m];(y.from<a&&y.to>i||i==a&&y.to==i)&&(l(Math.max(y.from,i),Math.min(y.to,a),y.level==1?\"rtl\":\"ltr\",m),u=!0)}u||l(i,a,\"ltr\")}var Hr=null;function Bt(n,i,a){var l;Hr=null;for(var u=0;u<n.length;++u){var m=n[u];if(m.from<i&&m.to>i)return u;m.to==i&&(m.from!=m.to&&a==\"before\"?l=u:Hr=u),m.from==i&&(m.from!=m.to&&a!=\"before\"?l=u:Hr=u)}return l??Hr}var Hn=(function(){var n=\"bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN\",i=\"nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111\";function a(T){return T<=247?n.charAt(T):1424<=T&&T<=1524?\"R\":1536<=T&&T<=1785?i.charAt(T-1536):1774<=T&&T<=2220?\"r\":8192<=T&&T<=8203?\"w\":T==8204?\"b\":\"L\"}var l=/[\\u0590-\\u05f4\\u0600-\\u06ff\\u0700-\\u08ac]/,u=/[stwN]/,m=/[LRr]/,y=/[Lb1n]/,x=/[1n]/;function S(T,H,V){this.level=T,this.from=H,this.to=V}return function(T,H){var V=H==\"ltr\"?\"L\":\"R\";if(T.length==0||H==\"ltr\"&&!l.test(T))return!1;for(var se=T.length,te=[],pe=0;pe<se;++pe)te.push(a(T.charCodeAt(pe)));for(var we=0,Te=V;we<se;++we){var Le=te[we];Le==\"m\"?te[we]=Te:Te=Le}for(var De=0,Me=V;De<se;++De){var ze=te[De];ze==\"1\"&&Me==\"r\"?te[De]=\"n\":m.test(ze)&&(Me=ze,ze==\"r\"&&(te[De]=\"R\"))}for(var Ye=1,Ue=te[0];Ye<se-1;++Ye){var st=te[Ye];st==\"+\"&&Ue==\"1\"&&te[Ye+1]==\"1\"?te[Ye]=\"1\":st==\",\"&&Ue==te[Ye+1]&&(Ue==\"1\"||Ue==\"n\")&&(te[Ye]=Ue),Ue=st}for(var St=0;St<se;++St){var tn=te[St];if(tn==\",\")te[St]=\"N\";else if(tn==\"%\"){var Ot=void 0;for(Ot=St+1;Ot<se&&te[Ot]==\"%\";++Ot);for(var qn=St&&te[St-1]==\"!\"||Ot<se&&te[Ot]==\"1\"?\"1\":\"N\",Cn=St;Cn<Ot;++Cn)te[Cn]=qn;St=Ot-1}}for(var Ut=0,En=V;Ut<se;++Ut){var sn=te[Ut];En==\"L\"&&sn==\"1\"?te[Ut]=\"L\":m.test(sn)&&(En=sn)}for(var Kt=0;Kt<se;++Kt)if(u.test(te[Kt])){var Vt=void 0;for(Vt=Kt+1;Vt<se&&u.test(te[Vt]);++Vt);for(var It=(Kt?te[Kt-1]:V)==\"L\",An=(Vt<se?te[Vt]:V)==\"L\",ks=It==An?It?\"L\":\"R\":V,ji=Kt;ji<Vt;++ji)te[ji]=ks;Kt=Vt-1}for(var fn=[],Ur,nn=0;nn<se;)if(y.test(te[nn])){var cd=nn;for(++nn;nn<se&&y.test(te[nn]);++nn);fn.push(new S(0,cd,nn))}else{var ui=nn,Ao=fn.length,Lo=H==\"rtl\"?1:0;for(++nn;nn<se&&te[nn]!=\"L\";++nn);for(var yn=ui;yn<nn;)if(x.test(te[yn])){ui<yn&&(fn.splice(Ao,0,new S(1,ui,yn)),Ao+=Lo);var Ss=yn;for(++yn;yn<nn&&x.test(te[yn]);++yn);fn.splice(Ao,0,new S(2,Ss,yn)),Ao+=Lo,ui=yn}else++yn;ui<nn&&fn.splice(Ao,0,new S(1,ui,nn))}return H==\"ltr\"&&(fn[0].level==1&&(Ur=T.match(/^\\s+/))&&(fn[0].from=Ur[0].length,fn.unshift(new S(0,0,Ur[0].length))),xe(fn).level==1&&(Ur=T.match(/\\s+$/))&&(xe(fn).to-=Ur[0].length,fn.push(new S(0,se-Ur[0].length,se)))),H==\"rtl\"?fn.reverse():fn}})();function lt(n,i){var a=n.order;return a==null&&(a=n.order=Hn(n.text,i)),a}var yo=[],Xe=function(n,i,a){if(n.addEventListener)n.addEventListener(i,a,!1);else if(n.attachEvent)n.attachEvent(\"on\"+i,a);else{var l=n._handlers||(n._handlers={});l[i]=(l[i]||yo).concat(a)}};function ri(n,i){return n._handlers&&n._handlers[i]||yo}function an(n,i,a){if(n.removeEventListener)n.removeEventListener(i,a,!1);else if(n.detachEvent)n.detachEvent(\"on\"+i,a);else{var l=n._handlers,u=l&&l[i];if(u){var m=ae(u,a);m>-1&&(l[i]=u.slice(0,m).concat(u.slice(m+1)))}}}function Pt(n,i){var a=ri(n,i);if(a.length)for(var l=Array.prototype.slice.call(arguments,2),u=0;u<a.length;++u)a[u].apply(null,l)}function Rt(n,i,a){return typeof i==\"string\"&&(i={type:i,preventDefault:function(){this.defaultPrevented=!0}}),Pt(n,a||i.type,n,i),kn(i)||i.codemirrorIgnore}function ar(n){var i=n._handlers&&n._handlers.cursorActivity;if(i)for(var a=n.curOp.cursorActivityHandlers||(n.curOp.cursorActivityHandlers=[]),l=0;l<i.length;++l)ae(a,i[l])==-1&&a.push(i[l])}function Bn(n,i){return ri(n,i).length>0}function yr(n){n.prototype.on=function(i,a){Xe(this,i,a)},n.prototype.off=function(i,a){an(this,i,a)}}function cn(n){n.preventDefault?n.preventDefault():n.returnValue=!1}function Zo(n){n.stopPropagation?n.stopPropagation():n.cancelBubble=!0}function kn(n){return n.defaultPrevented!=null?n.defaultPrevented:n.returnValue==!1}function Oi(n){cn(n),Zo(n)}function sl(n){return n.target||n.srcElement}function br(n){var i=n.which;return i==null&&(n.button&1?i=1:n.button&2?i=3:n.button&4&&(i=2)),$&&n.ctrlKey&&i==1&&(i=3),i}var mf=(function(){if(h&&p<9)return!1;var n=k(\"div\");return\"draggable\"in n||\"dragDrop\"in n})(),Jo;function Ga(n){if(Jo==null){var i=k(\"span\",\"​\");C(n,k(\"span\",[i,document.createTextNode(\"x\")])),n.firstChild.offsetHeight!=0&&(Jo=i.offsetWidth<=1&&i.offsetHeight>2&&!(h&&p<8))}var a=Jo?k(\"span\",\"​\"):k(\"span\",\" \",null,\"display: inline-block; width: 1px; margin-right: -1px\");return a.setAttribute(\"cm-text\",\"\"),a}var ll;function Pi(n){if(ll!=null)return ll;var i=C(n,document.createTextNode(\"AخA\")),a=B(i,0,1).getBoundingClientRect(),l=B(i,1,2).getBoundingClientRect();return O(n),!a||a.left==a.right?!1:ll=l.right-a.right<3}var cr=`\n\nb`.split(/\\n/).length!=3?function(n){for(var i=0,a=[],l=n.length;i<=l;){var u=n.indexOf(`\n`,i);u==-1&&(u=n.length);var m=n.slice(i,n.charAt(u-1)==\"\\r\"?u-1:u),y=m.indexOf(\"\\r\");y!=-1?(a.push(m.slice(0,y)),i+=y+1):(a.push(m),i=u+1)}return a}:function(n){return n.split(/\\r\\n?|\\n/)},Ri=window.getSelection?function(n){try{return n.selectionStart!=n.selectionEnd}catch{return!1}}:function(n){var i;try{i=n.ownerDocument.selection.createRange()}catch{}return!i||i.parentElement()!=n?!1:i.compareEndPoints(\"StartToEnd\",i)!=0},Ka=(function(){var n=k(\"div\");return\"oncopy\"in n?!0:(n.setAttribute(\"oncopy\",\"return;\"),typeof n.oncopy==\"function\")})(),wr=null;function vf(n){if(wr!=null)return wr;var i=C(n,k(\"span\",\"x\")),a=i.getBoundingClientRect(),l=B(i,0,1).getBoundingClientRect();return wr=Math.abs(a.left-l.left)>1}var Qo={},xr={};function kr(n,i){arguments.length>2&&(i.dependencies=Array.prototype.slice.call(arguments,2)),Qo[n]=i}function bo(n,i){xr[n]=i}function es(n){if(typeof n==\"string\"&&xr.hasOwnProperty(n))n=xr[n];else if(n&&typeof n.name==\"string\"&&xr.hasOwnProperty(n.name)){var i=xr[n.name];typeof i==\"string\"&&(i={name:i}),n=oe(i,n),n.name=i.name}else{if(typeof n==\"string\"&&/^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(n))return es(\"application/xml\");if(typeof n==\"string\"&&/^[\\w\\-]+\\/[\\w\\-]+\\+json$/.test(n))return es(\"application/json\")}return typeof n==\"string\"?{name:n}:n||{name:\"null\"}}function ts(n,i){i=es(i);var a=Qo[i.name];if(!a)return ts(n,\"text/plain\");var l=a(n,i);if($i.hasOwnProperty(i.name)){var u=$i[i.name];for(var m in u)u.hasOwnProperty(m)&&(l.hasOwnProperty(m)&&(l[\"_\"+m]=l[m]),l[m]=u[m])}if(l.name=i.name,i.helperType&&(l.helperType=i.helperType),i.modeProps)for(var y in i.modeProps)l[y]=i.modeProps[y];return l}var $i={};function ns(n,i){var a=$i.hasOwnProperty(n)?$i[n]:$i[n]={};Y(i,a)}function Br(n,i){if(i===!0)return i;if(n.copyState)return n.copyState(i);var a={};for(var l in i){var u=i[l];u instanceof Array&&(u=u.concat([])),a[l]=u}return a}function al(n,i){for(var a;n.innerMode&&(a=n.innerMode(i),!(!a||a.mode==n));)i=a.state,n=a.mode;return a||{mode:n,state:i}}function rs(n,i,a){return n.startState?n.startState(i,a):!0}var $t=function(n,i,a){this.pos=this.start=0,this.string=n,this.tabSize=i||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=a};$t.prototype.eol=function(){return this.pos>=this.string.length},$t.prototype.sol=function(){return this.pos==this.lineStart},$t.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},$t.prototype.next=function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},$t.prototype.eat=function(n){var i=this.string.charAt(this.pos),a;if(typeof n==\"string\"?a=i==n:a=i&&(n.test?n.test(i):n(i)),a)return++this.pos,i},$t.prototype.eatWhile=function(n){for(var i=this.pos;this.eat(n););return this.pos>i},$t.prototype.eatSpace=function(){for(var n=this.pos;/[\\s\\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>n},$t.prototype.skipToEnd=function(){this.pos=this.string.length},$t.prototype.skipTo=function(n){var i=this.string.indexOf(n,this.pos);if(i>-1)return this.pos=i,!0},$t.prototype.backUp=function(n){this.pos-=n},$t.prototype.column=function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=re(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?re(this.string,this.lineStart,this.tabSize):0)},$t.prototype.indentation=function(){return re(this.string,null,this.tabSize)-(this.lineStart?re(this.string,this.lineStart,this.tabSize):0)},$t.prototype.match=function(n,i,a){if(typeof n==\"string\"){var l=function(y){return a?y.toLowerCase():y},u=this.string.substr(this.pos,n.length);if(l(u)==l(n))return i!==!1&&(this.pos+=n.length),!0}else{var m=this.string.slice(this.pos).match(n);return m&&m.index>0?null:(m&&i!==!1&&(this.pos+=m[0].length),m)}},$t.prototype.current=function(){return this.string.slice(this.start,this.pos)},$t.prototype.hideFirstChars=function(n,i){this.lineStart+=n;try{return i()}finally{this.lineStart-=n}},$t.prototype.lookAhead=function(n){var i=this.lineOracle;return i&&i.lookAhead(n)},$t.prototype.baseToken=function(){var n=this.lineOracle;return n&&n.baseToken(this.pos)};function qe(n,i){if(i-=n.first,i<0||i>=n.size)throw new Error(\"There is no line \"+(i+n.first)+\" in the document.\");for(var a=n;!a.lines;)for(var l=0;;++l){var u=a.children[l],m=u.chunkSize();if(i<m){a=u;break}i-=m}return a.lines[i]}function ii(n,i,a){var l=[],u=i.line;return n.iter(i.line,a.line+1,function(m){var y=m.text;u==a.line&&(y=y.slice(0,a.ch)),u==i.line&&(y=y.slice(i.ch)),l.push(y),++u}),l}function cl(n,i,a){var l=[];return n.iter(i,a,function(u){l.push(u.text)}),l}function Qn(n,i){var a=i-n.height;if(a)for(var l=n;l;l=l.parent)l.height+=a}function A(n){if(n.parent==null)return null;for(var i=n.parent,a=ae(i.lines,n),l=i.parent;l;i=l,l=l.parent)for(var u=0;l.children[u]!=i;++u)a+=l.children[u].chunkSize();return a+i.first}function U(n,i){var a=n.first;e:do{for(var l=0;l<n.children.length;++l){var u=n.children[l],m=u.height;if(i<m){n=u;continue e}i-=m,a+=u.chunkSize()}return a}while(!n.lines);for(var y=0;y<n.lines.length;++y){var x=n.lines[y],S=x.height;if(i<S)break;i-=S}return a+y}function me(n,i){return i>=n.first&&i<n.first+n.size}function _e(n,i){return String(n.lineNumberFormatter(i+n.firstLineNumber))}function fe(n,i,a){if(a===void 0&&(a=null),!(this instanceof fe))return new fe(n,i,a);this.line=n,this.ch=i,this.sticky=a}function Ie(n,i){return n.line-i.line||n.ch-i.ch}function pt(n,i){return n.sticky==i.sticky&&Ie(n,i)==0}function Zt(n){return fe(n.line,n.ch)}function Sn(n,i){return Ie(n,i)<0?i:n}function is(n,i){return Ie(n,i)<0?n:i}function Wp(n,i){return Math.max(n.first,Math.min(i,n.first+n.size-1))}function tt(n,i){if(i.line<n.first)return fe(n.first,0);var a=n.first+n.size-1;return i.line>a?fe(a,qe(n,a).text.length):I1(i,qe(n,i.line).text.length)}function I1(n,i){var a=n.ch;return a==null||a>i?fe(n.line,i):a<0?fe(n.line,0):n}function qp(n,i){for(var a=[],l=0;l<i.length;l++)a[l]=tt(n,i[l]);return a}var Xa=function(n,i){this.state=n,this.lookAhead=i},Wr=function(n,i,a,l){this.state=i,this.doc=n,this.line=a,this.maxLookAhead=l||0,this.baseTokens=null,this.baseTokenPos=1};Wr.prototype.lookAhead=function(n){var i=this.doc.getLine(this.line+n);return i!=null&&n>this.maxLookAhead&&(this.maxLookAhead=n),i},Wr.prototype.baseToken=function(n){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=n;)this.baseTokenPos+=2;var i=this.baseTokens[this.baseTokenPos+1];return{type:i&&i.replace(/( |^)overlay .*/,\"\"),size:this.baseTokens[this.baseTokenPos]-n}},Wr.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},Wr.fromSaved=function(n,i,a){return i instanceof Xa?new Wr(n,Br(n.mode,i.state),a,i.lookAhead):new Wr(n,Br(n.mode,i),a)},Wr.prototype.save=function(n){var i=n!==!1?Br(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new Xa(i,this.maxLookAhead):i};function jp(n,i,a,l){var u=[n.state.modeGen],m={};Yp(n,i.text,n.doc.mode,a,function(T,H){return u.push(T,H)},m,l);for(var y=a.state,x=function(T){a.baseTokens=u;var H=n.state.overlays[T],V=1,se=0;a.state=!0,Yp(n,i.text,H.mode,a,function(te,pe){for(var we=V;se<te;){var Te=u[V];Te>te&&u.splice(V,1,te,u[V+1],Te),V+=2,se=Math.min(te,Te)}if(pe)if(H.opaque)u.splice(we,V-we,te,\"overlay \"+pe),V=we+2;else for(;we<V;we+=2){var Le=u[we+1];u[we+1]=(Le?Le+\" \":\"\")+\"overlay \"+pe}},m),a.state=y,a.baseTokens=null,a.baseTokenPos=1},S=0;S<n.state.overlays.length;++S)x(S);return{styles:u,classes:m.bgClass||m.textClass?m:null}}function Up(n,i,a){if(!i.styles||i.styles[0]!=n.state.modeGen){var l=ul(n,A(i)),u=i.text.length>n.options.maxHighlightLength&&Br(n.doc.mode,l.state),m=jp(n,i,l);u&&(l.state=u),i.stateAfter=l.save(!u),i.styles=m.styles,m.classes?i.styleClasses=m.classes:i.styleClasses&&(i.styleClasses=null),a===n.doc.highlightFrontier&&(n.doc.modeFrontier=Math.max(n.doc.modeFrontier,++n.doc.highlightFrontier))}return i.styles}function ul(n,i,a){var l=n.doc,u=n.display;if(!l.mode.startState)return new Wr(l,!0,i);var m=D1(n,i,a),y=m>l.first&&qe(l,m-1).stateAfter,x=y?Wr.fromSaved(l,y,m):new Wr(l,rs(l.mode),m);return l.iter(m,i,function(S){yf(n,S.text,x);var T=x.line;S.stateAfter=T==i-1||T%5==0||T>=u.viewFrom&&T<u.viewTo?x.save():null,x.nextLine()}),a&&(l.modeFrontier=x.line),x}function yf(n,i,a,l){var u=n.doc.mode,m=new $t(i,n.options.tabSize,a);for(m.start=m.pos=l||0,i==\"\"&&Vp(u,a.state);!m.eol();)bf(u,m,a.state),m.start=m.pos}function Vp(n,i){if(n.blankLine)return n.blankLine(i);if(n.innerMode){var a=al(n,i);if(a.mode.blankLine)return a.mode.blankLine(a.state)}}function bf(n,i,a,l){for(var u=0;u<10;u++){l&&(l[0]=al(n,a).mode);var m=n.token(i,a);if(i.pos>i.start)return m}throw new Error(\"Mode \"+n.name+\" failed to advance stream.\")}var Gp=function(n,i,a){this.start=n.start,this.end=n.pos,this.string=n.current(),this.type=i||null,this.state=a};function Kp(n,i,a,l){var u=n.doc,m=u.mode,y;i=tt(u,i);var x=qe(u,i.line),S=ul(n,i.line,a),T=new $t(x.text,n.options.tabSize,S),H;for(l&&(H=[]);(l||T.pos<i.ch)&&!T.eol();)T.start=T.pos,y=bf(m,T,S.state),l&&H.push(new Gp(T,y,Br(u.mode,S.state)));return l?H:new Gp(T,y,S.state)}function Xp(n,i){if(n)for(;;){var a=n.match(/(?:^|\\s+)line-(background-)?(\\S+)/);if(!a)break;n=n.slice(0,a.index)+n.slice(a.index+a[0].length);var l=a[1]?\"bgClass\":\"textClass\";i[l]==null?i[l]=a[2]:new RegExp(\"(?:^|\\\\s)\"+a[2]+\"(?:$|\\\\s)\").test(i[l])||(i[l]+=\" \"+a[2])}return n}function Yp(n,i,a,l,u,m,y){var x=a.flattenSpans;x==null&&(x=n.options.flattenSpans);var S=0,T=null,H=new $t(i,n.options.tabSize,l),V,se=n.options.addModeClass&&[null];for(i==\"\"&&Xp(Vp(a,l.state),m);!H.eol();){if(H.pos>n.options.maxHighlightLength?(x=!1,y&&yf(n,i,l,H.pos),H.pos=i.length,V=null):V=Xp(bf(a,H,l.state,se),m),se){var te=se[0].name;te&&(V=\"m-\"+(V?te+\" \"+V:te))}if(!x||T!=V){for(;S<H.start;)S=Math.min(H.start,S+5e3),u(S,T);T=V}H.start=H.pos}for(;S<H.pos;){var pe=Math.min(H.pos,S+5e3);u(pe,T),S=pe}}function D1(n,i,a){for(var l,u,m=n.doc,y=a?-1:i-(n.doc.mode.innerMode?1e3:100),x=i;x>y;--x){if(x<=m.first)return m.first;var S=qe(m,x-1),T=S.stateAfter;if(T&&(!a||x+(T instanceof Xa?T.lookAhead:0)<=m.modeFrontier))return x;var H=re(S.text,null,n.options.tabSize);(u==null||l>H)&&(u=x-1,l=H)}return u}function z1(n,i){if(n.modeFrontier=Math.min(n.modeFrontier,i),!(n.highlightFrontier<i-10)){for(var a=n.first,l=i-1;l>a;l--){var u=qe(n,l).stateAfter;if(u&&(!(u instanceof Xa)||l+u.lookAhead<i)){a=l+1;break}}n.highlightFrontier=Math.min(n.highlightFrontier,a)}}var Zp=!1,oi=!1;function F1(){Zp=!0}function H1(){oi=!0}function Ya(n,i,a){this.marker=n,this.from=i,this.to=a}function fl(n,i){if(n)for(var a=0;a<n.length;++a){var l=n[a];if(l.marker==i)return l}}function B1(n,i){for(var a,l=0;l<n.length;++l)n[l]!=i&&(a||(a=[])).push(n[l]);return a}function W1(n,i,a){var l=a&&window.WeakSet&&(a.markedSpans||(a.markedSpans=new WeakSet));l&&n.markedSpans&&l.has(n.markedSpans)?n.markedSpans.push(i):(n.markedSpans=n.markedSpans?n.markedSpans.concat([i]):[i],l&&l.add(n.markedSpans)),i.marker.attachLine(n)}function q1(n,i,a){var l;if(n)for(var u=0;u<n.length;++u){var m=n[u],y=m.marker,x=m.from==null||(y.inclusiveLeft?m.from<=i:m.from<i);if(x||m.from==i&&y.type==\"bookmark\"&&(!a||!m.marker.insertLeft)){var S=m.to==null||(y.inclusiveRight?m.to>=i:m.to>i);(l||(l=[])).push(new Ya(y,m.from,S?null:m.to))}}return l}function j1(n,i,a){var l;if(n)for(var u=0;u<n.length;++u){var m=n[u],y=m.marker,x=m.to==null||(y.inclusiveRight?m.to>=i:m.to>i);if(x||m.from==i&&y.type==\"bookmark\"&&(!a||m.marker.insertLeft)){var S=m.from==null||(y.inclusiveLeft?m.from<=i:m.from<i);(l||(l=[])).push(new Ya(y,S?null:m.from-i,m.to==null?null:m.to-i))}}return l}function wf(n,i){if(i.full)return null;var a=me(n,i.from.line)&&qe(n,i.from.line).markedSpans,l=me(n,i.to.line)&&qe(n,i.to.line).markedSpans;if(!a&&!l)return null;var u=i.from.ch,m=i.to.ch,y=Ie(i.from,i.to)==0,x=q1(a,u,y),S=j1(l,m,y),T=i.text.length==1,H=xe(i.text).length+(T?u:0);if(x)for(var V=0;V<x.length;++V){var se=x[V];if(se.to==null){var te=fl(S,se.marker);te?T&&(se.to=te.to==null?null:te.to+H):se.to=u}}if(S)for(var pe=0;pe<S.length;++pe){var we=S[pe];if(we.to!=null&&(we.to+=H),we.from==null){var Te=fl(x,we.marker);Te||(we.from=H,T&&(x||(x=[])).push(we))}else we.from+=H,T&&(x||(x=[])).push(we)}x&&(x=Jp(x)),S&&S!=x&&(S=Jp(S));var Le=[x];if(!T){var De=i.text.length-2,Me;if(De>0&&x)for(var ze=0;ze<x.length;++ze)x[ze].to==null&&(Me||(Me=[])).push(new Ya(x[ze].marker,null,null));for(var Ye=0;Ye<De;++Ye)Le.push(Me);Le.push(S)}return Le}function Jp(n){for(var i=0;i<n.length;++i){var a=n[i];a.from!=null&&a.from==a.to&&a.marker.clearWhenEmpty!==!1&&n.splice(i--,1)}return n.length?n:null}function U1(n,i,a){var l=null;if(n.iter(i.line,a.line+1,function(te){if(te.markedSpans)for(var pe=0;pe<te.markedSpans.length;++pe){var we=te.markedSpans[pe].marker;we.readOnly&&(!l||ae(l,we)==-1)&&(l||(l=[])).push(we)}}),!l)return null;for(var u=[{from:i,to:a}],m=0;m<l.length;++m)for(var y=l[m],x=y.find(0),S=0;S<u.length;++S){var T=u[S];if(!(Ie(T.to,x.from)<0||Ie(T.from,x.to)>0)){var H=[S,1],V=Ie(T.from,x.from),se=Ie(T.to,x.to);(V<0||!y.inclusiveLeft&&!V)&&H.push({from:T.from,to:x.from}),(se>0||!y.inclusiveRight&&!se)&&H.push({from:x.to,to:T.to}),u.splice.apply(u,H),S+=H.length-3}}return u}function Qp(n){var i=n.markedSpans;if(i){for(var a=0;a<i.length;++a)i[a].marker.detachLine(n);n.markedSpans=null}}function eg(n,i){if(i){for(var a=0;a<i.length;++a)i[a].marker.attachLine(n);n.markedSpans=i}}function Za(n){return n.inclusiveLeft?-1:0}function Ja(n){return n.inclusiveRight?1:0}function xf(n,i){var a=n.lines.length-i.lines.length;if(a!=0)return a;var l=n.find(),u=i.find(),m=Ie(l.from,u.from)||Za(n)-Za(i);if(m)return-m;var y=Ie(l.to,u.to)||Ja(n)-Ja(i);return y||i.id-n.id}function tg(n,i){var a=oi&&n.markedSpans,l;if(a)for(var u=void 0,m=0;m<a.length;++m)u=a[m],u.marker.collapsed&&(i?u.from:u.to)==null&&(!l||xf(l,u.marker)<0)&&(l=u.marker);return l}function ng(n){return tg(n,!0)}function Qa(n){return tg(n,!1)}function V1(n,i){var a=oi&&n.markedSpans,l;if(a)for(var u=0;u<a.length;++u){var m=a[u];m.marker.collapsed&&(m.from==null||m.from<i)&&(m.to==null||m.to>i)&&(!l||xf(l,m.marker)<0)&&(l=m.marker)}return l}function rg(n,i,a,l,u){var m=qe(n,i),y=oi&&m.markedSpans;if(y)for(var x=0;x<y.length;++x){var S=y[x];if(S.marker.collapsed){var T=S.marker.find(0),H=Ie(T.from,a)||Za(S.marker)-Za(u),V=Ie(T.to,l)||Ja(S.marker)-Ja(u);if(!(H>=0&&V<=0||H<=0&&V>=0)&&(H<=0&&(S.marker.inclusiveRight&&u.inclusiveLeft?Ie(T.to,a)>=0:Ie(T.to,a)>0)||H>=0&&(S.marker.inclusiveRight&&u.inclusiveLeft?Ie(T.from,l)<=0:Ie(T.from,l)<0)))return!0}}}function Sr(n){for(var i;i=ng(n);)n=i.find(-1,!0).line;return n}function G1(n){for(var i;i=Qa(n);)n=i.find(1,!0).line;return n}function K1(n){for(var i,a;i=Qa(n);)n=i.find(1,!0).line,(a||(a=[])).push(n);return a}function kf(n,i){var a=qe(n,i),l=Sr(a);return a==l?i:A(l)}function ig(n,i){if(i>n.lastLine())return i;var a=qe(n,i),l;if(!Ii(n,a))return i;for(;l=Qa(a);)a=l.find(1,!0).line;return A(a)+1}function Ii(n,i){var a=oi&&i.markedSpans;if(a){for(var l=void 0,u=0;u<a.length;++u)if(l=a[u],!!l.marker.collapsed){if(l.from==null)return!0;if(!l.marker.widgetNode&&l.from==0&&l.marker.inclusiveLeft&&Sf(n,i,l))return!0}}}function Sf(n,i,a){if(a.to==null){var l=a.marker.find(1,!0);return Sf(n,l.line,fl(l.line.markedSpans,a.marker))}if(a.marker.inclusiveRight&&a.to==i.text.length)return!0;for(var u=void 0,m=0;m<i.markedSpans.length;++m)if(u=i.markedSpans[m],u.marker.collapsed&&!u.marker.widgetNode&&u.from==a.to&&(u.to==null||u.to!=a.from)&&(u.marker.inclusiveLeft||a.marker.inclusiveRight)&&Sf(n,i,u))return!0}function si(n){n=Sr(n);for(var i=0,a=n.parent,l=0;l<a.lines.length;++l){var u=a.lines[l];if(u==n)break;i+=u.height}for(var m=a.parent;m;a=m,m=a.parent)for(var y=0;y<m.children.length;++y){var x=m.children[y];if(x==a)break;i+=x.height}return i}function ec(n){if(n.height==0)return 0;for(var i=n.text.length,a,l=n;a=ng(l);){var u=a.find(0,!0);l=u.from.line,i+=u.from.ch-u.to.ch}for(l=n;a=Qa(l);){var m=a.find(0,!0);i-=l.text.length-m.from.ch,l=m.to.line,i+=l.text.length-m.to.ch}return i}function _f(n){var i=n.display,a=n.doc;i.maxLine=qe(a,a.first),i.maxLineLength=ec(i.maxLine),i.maxLineChanged=!0,a.iter(function(l){var u=ec(l);u>i.maxLineLength&&(i.maxLineLength=u,i.maxLine=l)})}var os=function(n,i,a){this.text=n,eg(this,i),this.height=a?a(this):1};os.prototype.lineNo=function(){return A(this)},yr(os);function X1(n,i,a,l){n.text=i,n.stateAfter&&(n.stateAfter=null),n.styles&&(n.styles=null),n.order!=null&&(n.order=null),Qp(n),eg(n,a);var u=l?l(n):1;u!=n.height&&Qn(n,u)}function Y1(n){n.parent=null,Qp(n)}var Z1={},J1={};function og(n,i){if(!n||/^\\s*$/.test(n))return null;var a=i.addModeClass?J1:Z1;return a[n]||(a[n]=n.replace(/\\S+/g,\"cm-$&\"))}function sg(n,i){var a=z(\"span\",null,null,g?\"padding-right: .1px\":null),l={pre:z(\"pre\",[a],\"CodeMirror-line\"),content:a,col:0,pos:0,cm:n,trailingSpace:!1,splitSpaces:n.getOption(\"lineWrapping\")};i.measure={};for(var u=0;u<=(i.rest?i.rest.length:0);u++){var m=u?i.rest[u-1]:i.line,y=void 0;l.pos=0,l.addToken=ek,Pi(n.display.measure)&&(y=lt(m,n.doc.direction))&&(l.addToken=nk(l.addToken,y)),l.map=[];var x=i!=n.display.externalMeasured&&A(m);rk(m,l,Up(n,m,x)),m.styleClasses&&(m.styleClasses.bgClass&&(l.bgClass=Be(m.styleClasses.bgClass,l.bgClass||\"\")),m.styleClasses.textClass&&(l.textClass=Be(m.styleClasses.textClass,l.textClass||\"\"))),l.map.length==0&&l.map.push(0,0,l.content.appendChild(Ga(n.display.measure))),u==0?(i.measure.map=l.map,i.measure.cache={}):((i.measure.maps||(i.measure.maps=[])).push(l.map),(i.measure.caches||(i.measure.caches=[])).push({}))}if(g){var S=l.content.lastChild;(/\\bcm-tab\\b/.test(S.className)||S.querySelector&&S.querySelector(\".cm-tab\"))&&(l.content.className=\"cm-tab-wrap-hack\")}return Pt(n,\"renderLine\",n,i.line,l.pre),l.pre.className&&(l.textClass=Be(l.pre.className,l.textClass||\"\")),l}function Q1(n){var i=k(\"span\",\"•\",\"cm-invalidchar\");return i.title=\"\\\\u\"+n.charCodeAt(0).toString(16),i.setAttribute(\"aria-label\",i.title),i}function ek(n,i,a,l,u,m,y){if(i){var x=n.splitSpaces?tk(i,n.trailingSpace):i,S=n.cm.state.specialChars,T=!1,H;if(!S.test(i))n.col+=i.length,H=document.createTextNode(x),n.map.push(n.pos,n.pos+i.length,H),h&&p<9&&(T=!0),n.pos+=i.length;else{H=document.createDocumentFragment();for(var V=0;;){S.lastIndex=V;var se=S.exec(i),te=se?se.index-V:i.length-V;if(te){var pe=document.createTextNode(x.slice(V,V+te));h&&p<9?H.appendChild(k(\"span\",[pe])):H.appendChild(pe),n.map.push(n.pos,n.pos+te,pe),n.col+=te,n.pos+=te}if(!se)break;V+=te+1;var we=void 0;if(se[0]==\"\t\"){var Te=n.cm.options.tabSize,Le=Te-n.col%Te;we=H.appendChild(k(\"span\",Ee(Le),\"cm-tab\")),we.setAttribute(\"role\",\"presentation\"),we.setAttribute(\"cm-text\",\"\t\"),n.col+=Le}else se[0]==\"\\r\"||se[0]==`\n`?(we=H.appendChild(k(\"span\",se[0]==\"\\r\"?\"␍\":\"␤\",\"cm-invalidchar\")),we.setAttribute(\"cm-text\",se[0]),n.col+=1):(we=n.cm.options.specialCharPlaceholder(se[0]),we.setAttribute(\"cm-text\",se[0]),h&&p<9?H.appendChild(k(\"span\",[we])):H.appendChild(we),n.col+=1);n.map.push(n.pos,n.pos+1,we),n.pos++}}if(n.trailingSpace=x.charCodeAt(i.length-1)==32,a||l||u||T||m||y){var De=a||\"\";l&&(De+=l),u&&(De+=u);var Me=k(\"span\",[H],De,m);if(y)for(var ze in y)y.hasOwnProperty(ze)&&ze!=\"style\"&&ze!=\"class\"&&Me.setAttribute(ze,y[ze]);return n.content.appendChild(Me)}n.content.appendChild(H)}}function tk(n,i){if(n.length>1&&!/  /.test(n))return n;for(var a=i,l=\"\",u=0;u<n.length;u++){var m=n.charAt(u);m==\" \"&&a&&(u==n.length-1||n.charCodeAt(u+1)==32)&&(m=\" \"),l+=m,a=m==\" \"}return l}function nk(n,i){return function(a,l,u,m,y,x,S){u=u?u+\" cm-force-border\":\"cm-force-border\";for(var T=a.pos,H=T+l.length;;){for(var V=void 0,se=0;se<i.length&&(V=i[se],!(V.to>T&&V.from<=T));se++);if(V.to>=H)return n(a,l,u,m,y,x,S);n(a,l.slice(0,V.to-T),u,m,null,x,S),m=null,l=l.slice(V.to-T),T=V.to}}}function lg(n,i,a,l){var u=!l&&a.widgetNode;u&&n.map.push(n.pos,n.pos+i,u),!l&&n.cm.display.input.needsContentAttribute&&(u||(u=n.content.appendChild(document.createElement(\"span\"))),u.setAttribute(\"cm-marker\",a.id)),u&&(n.cm.display.input.setUneditable(u),n.content.appendChild(u)),n.pos+=i,n.trailingSpace=!1}function rk(n,i,a){var l=n.markedSpans,u=n.text,m=0;if(!l){for(var y=1;y<a.length;y+=2)i.addToken(i,u.slice(m,m=a[y]),og(a[y+1],i.cm.options));return}for(var x=u.length,S=0,T=1,H=\"\",V,se,te=0,pe,we,Te,Le,De;;){if(te==S){pe=we=Te=se=\"\",De=null,Le=null,te=1/0;for(var Me=[],ze=void 0,Ye=0;Ye<l.length;++Ye){var Ue=l[Ye],st=Ue.marker;if(st.type==\"bookmark\"&&Ue.from==S&&st.widgetNode)Me.push(st);else if(Ue.from<=S&&(Ue.to==null||Ue.to>S||st.collapsed&&Ue.to==S&&Ue.from==S)){if(Ue.to!=null&&Ue.to!=S&&te>Ue.to&&(te=Ue.to,we=\"\"),st.className&&(pe+=\" \"+st.className),st.css&&(se=(se?se+\";\":\"\")+st.css),st.startStyle&&Ue.from==S&&(Te+=\" \"+st.startStyle),st.endStyle&&Ue.to==te&&(ze||(ze=[])).push(st.endStyle,Ue.to),st.title&&((De||(De={})).title=st.title),st.attributes)for(var St in st.attributes)(De||(De={}))[St]=st.attributes[St];st.collapsed&&(!Le||xf(Le.marker,st)<0)&&(Le=Ue)}else Ue.from>S&&te>Ue.from&&(te=Ue.from)}if(ze)for(var tn=0;tn<ze.length;tn+=2)ze[tn+1]==te&&(we+=\" \"+ze[tn]);if(!Le||Le.from==S)for(var Ot=0;Ot<Me.length;++Ot)lg(i,0,Me[Ot]);if(Le&&(Le.from||0)==S){if(lg(i,(Le.to==null?x+1:Le.to)-S,Le.marker,Le.from==null),Le.to==null)return;Le.to==S&&(Le=!1)}}if(S>=x)break;for(var qn=Math.min(x,te);;){if(H){var Cn=S+H.length;if(!Le){var Ut=Cn>qn?H.slice(0,qn-S):H;i.addToken(i,Ut,V?V+pe:pe,Te,S+Ut.length==te?we:\"\",se,De)}if(Cn>=qn){H=H.slice(qn-S),S=qn;break}S=Cn,Te=\"\"}H=u.slice(m,m=a[T++]),V=og(a[T++],i.cm.options)}}}function ag(n,i,a){this.line=i,this.rest=K1(i),this.size=this.rest?A(xe(this.rest))-a+1:1,this.node=this.text=null,this.hidden=Ii(n,i)}function tc(n,i,a){for(var l=[],u,m=i;m<a;m=u){var y=new ag(n.doc,qe(n.doc,m),m);u=m+y.size,l.push(y)}return l}var ss=null;function ik(n){ss?ss.ops.push(n):n.ownsGroup=ss={ops:[n],delayedCallbacks:[]}}function ok(n){var i=n.delayedCallbacks,a=0;do{for(;a<i.length;a++)i[a].call(null);for(var l=0;l<n.ops.length;l++){var u=n.ops[l];if(u.cursorActivityHandlers)for(;u.cursorActivityCalled<u.cursorActivityHandlers.length;)u.cursorActivityHandlers[u.cursorActivityCalled++].call(null,u.cm)}}while(a<i.length)}function sk(n,i){var a=n.ownsGroup;if(a)try{ok(a)}finally{ss=null,i(a)}}var dl=null;function Jt(n,i){var a=ri(n,i);if(a.length){var l=Array.prototype.slice.call(arguments,2),u;ss?u=ss.delayedCallbacks:dl?u=dl:(u=dl=[],setTimeout(lk,0));for(var m=function(x){u.push(function(){return a[x].apply(null,l)})},y=0;y<a.length;++y)m(y)}}function lk(){var n=dl;dl=null;for(var i=0;i<n.length;++i)n[i]()}function cg(n,i,a,l){for(var u=0;u<i.changes.length;u++){var m=i.changes[u];m==\"text\"?ck(n,i):m==\"gutter\"?fg(n,i,a,l):m==\"class\"?Tf(n,i):m==\"widget\"&&uk(n,i,l)}i.changes=null}function hl(n){return n.node==n.text&&(n.node=k(\"div\",null,null,\"position: relative\"),n.text.parentNode&&n.text.parentNode.replaceChild(n.node,n.text),n.node.appendChild(n.text),h&&p<8&&(n.node.style.zIndex=2)),n.node}function ak(n,i){var a=i.bgClass?i.bgClass+\" \"+(i.line.bgClass||\"\"):i.line.bgClass;if(a&&(a+=\" CodeMirror-linebackground\"),i.background)a?i.background.className=a:(i.background.parentNode.removeChild(i.background),i.background=null);else if(a){var l=hl(i);i.background=l.insertBefore(k(\"div\",null,a),l.firstChild),n.display.input.setUneditable(i.background)}}function ug(n,i){var a=n.display.externalMeasured;return a&&a.line==i.line?(n.display.externalMeasured=null,i.measure=a.measure,a.built):sg(n,i)}function ck(n,i){var a=i.text.className,l=ug(n,i);i.text==i.node&&(i.node=l.pre),i.text.parentNode.replaceChild(l.pre,i.text),i.text=l.pre,l.bgClass!=i.bgClass||l.textClass!=i.textClass?(i.bgClass=l.bgClass,i.textClass=l.textClass,Tf(n,i)):a&&(i.text.className=a)}function Tf(n,i){ak(n,i),i.line.wrapClass?hl(i).className=i.line.wrapClass:i.node!=i.text&&(i.node.className=\"\");var a=i.textClass?i.textClass+\" \"+(i.line.textClass||\"\"):i.line.textClass;i.text.className=a||\"\"}function fg(n,i,a,l){if(i.gutter&&(i.node.removeChild(i.gutter),i.gutter=null),i.gutterBackground&&(i.node.removeChild(i.gutterBackground),i.gutterBackground=null),i.line.gutterClass){var u=hl(i);i.gutterBackground=k(\"div\",null,\"CodeMirror-gutter-background \"+i.line.gutterClass,\"left: \"+(n.options.fixedGutter?l.fixedPos:-l.gutterTotalWidth)+\"px; width: \"+l.gutterTotalWidth+\"px\"),n.display.input.setUneditable(i.gutterBackground),u.insertBefore(i.gutterBackground,i.text)}var m=i.line.gutterMarkers;if(n.options.lineNumbers||m){var y=hl(i),x=i.gutter=k(\"div\",null,\"CodeMirror-gutter-wrapper\",\"left: \"+(n.options.fixedGutter?l.fixedPos:-l.gutterTotalWidth)+\"px\");if(x.setAttribute(\"aria-hidden\",\"true\"),n.display.input.setUneditable(x),y.insertBefore(x,i.text),i.line.gutterClass&&(x.className+=\" \"+i.line.gutterClass),n.options.lineNumbers&&(!m||!m[\"CodeMirror-linenumbers\"])&&(i.lineNumber=x.appendChild(k(\"div\",_e(n.options,a),\"CodeMirror-linenumber CodeMirror-gutter-elt\",\"left: \"+l.gutterLeft[\"CodeMirror-linenumbers\"]+\"px; width: \"+n.display.lineNumInnerWidth+\"px\"))),m)for(var S=0;S<n.display.gutterSpecs.length;++S){var T=n.display.gutterSpecs[S].className,H=m.hasOwnProperty(T)&&m[T];H&&x.appendChild(k(\"div\",[H],\"CodeMirror-gutter-elt\",\"left: \"+l.gutterLeft[T]+\"px; width: \"+l.gutterWidth[T]+\"px\"))}}}function uk(n,i,a){i.alignable&&(i.alignable=null);for(var l=j(\"CodeMirror-linewidget\"),u=i.node.firstChild,m=void 0;u;u=m)m=u.nextSibling,l.test(u.className)&&i.node.removeChild(u);dg(n,i,a)}function fk(n,i,a,l){var u=ug(n,i);return i.text=i.node=u.pre,u.bgClass&&(i.bgClass=u.bgClass),u.textClass&&(i.textClass=u.textClass),Tf(n,i),fg(n,i,a,l),dg(n,i,l),i.node}function dg(n,i,a){if(hg(n,i.line,i,a,!0),i.rest)for(var l=0;l<i.rest.length;l++)hg(n,i.rest[l],i,a,!1)}function hg(n,i,a,l,u){if(i.widgets)for(var m=hl(a),y=0,x=i.widgets;y<x.length;++y){var S=x[y],T=k(\"div\",[S.node],\"CodeMirror-linewidget\"+(S.className?\" \"+S.className:\"\"));S.handleMouseEvents||T.setAttribute(\"cm-ignore-events\",\"true\"),dk(S,T,a,l),n.display.input.setUneditable(T),u&&S.above?m.insertBefore(T,a.gutter||a.text):m.appendChild(T),Jt(S,\"redraw\")}}function dk(n,i,a,l){if(n.noHScroll){(a.alignable||(a.alignable=[])).push(i);var u=l.wrapperWidth;i.style.left=l.fixedPos+\"px\",n.coverGutter||(u-=l.gutterTotalWidth,i.style.paddingLeft=l.gutterTotalWidth+\"px\"),i.style.width=u+\"px\"}n.coverGutter&&(i.style.zIndex=5,i.style.position=\"relative\",n.noHScroll||(i.style.marginLeft=-l.gutterTotalWidth+\"px\"))}function pl(n){if(n.height!=null)return n.height;var i=n.doc.cm;if(!i)return 0;if(!ce(document.body,n.node)){var a=\"position: relative;\";n.coverGutter&&(a+=\"margin-left: -\"+i.display.gutters.offsetWidth+\"px;\"),n.noHScroll&&(a+=\"width: \"+i.display.wrapper.clientWidth+\"px;\"),C(i.display.measure,k(\"div\",[n.node],null,a))}return n.height=n.node.parentNode.offsetHeight}function li(n,i){for(var a=sl(i);a!=n.wrapper;a=a.parentNode)if(!a||a.nodeType==1&&a.getAttribute(\"cm-ignore-events\")==\"true\"||a.parentNode==n.sizer&&a!=n.mover)return!0}function nc(n){return n.lineSpace.offsetTop}function Cf(n){return n.mover.offsetHeight-n.lineSpace.offsetHeight}function pg(n){if(n.cachedPaddingH)return n.cachedPaddingH;var i=C(n.measure,k(\"pre\",\"x\",\"CodeMirror-line-like\")),a=window.getComputedStyle?window.getComputedStyle(i):i.currentStyle,l={left:parseInt(a.paddingLeft),right:parseInt(a.paddingRight)};return!isNaN(l.left)&&!isNaN(l.right)&&(n.cachedPaddingH=l),l}function qr(n){return D-n.display.nativeBarWidth}function wo(n){return n.display.scroller.clientWidth-qr(n)-n.display.barWidth}function Ef(n){return n.display.scroller.clientHeight-qr(n)-n.display.barHeight}function hk(n,i,a){var l=n.options.lineWrapping,u=l&&wo(n);if(!i.measure.heights||l&&i.measure.width!=u){var m=i.measure.heights=[];if(l){i.measure.width=u;for(var y=i.text.firstChild.getClientRects(),x=0;x<y.length-1;x++){var S=y[x],T=y[x+1];Math.abs(S.bottom-T.bottom)>2&&m.push((S.bottom+T.top)/2-a.top)}}m.push(a.bottom-a.top)}}function gg(n,i,a){if(n.line==i)return{map:n.measure.map,cache:n.measure.cache};if(n.rest){for(var l=0;l<n.rest.length;l++)if(n.rest[l]==i)return{map:n.measure.maps[l],cache:n.measure.caches[l]};for(var u=0;u<n.rest.length;u++)if(A(n.rest[u])>a)return{map:n.measure.maps[u],cache:n.measure.caches[u],before:!0}}}function pk(n,i){i=Sr(i);var a=A(i),l=n.display.externalMeasured=new ag(n.doc,i,a);l.lineN=a;var u=l.built=sg(n,l);return l.text=u.pre,C(n.display.lineMeasure,u.pre),l}function mg(n,i,a,l){return jr(n,ls(n,i),a,l)}function Af(n,i){if(i>=n.display.viewFrom&&i<n.display.viewTo)return n.display.view[So(n,i)];var a=n.display.externalMeasured;if(a&&i>=a.lineN&&i<a.lineN+a.size)return a}function ls(n,i){var a=A(i),l=Af(n,a);l&&!l.text?l=null:l&&l.changes&&(cg(n,l,a,Pf(n)),n.curOp.forceUpdate=!0),l||(l=pk(n,i));var u=gg(l,i,a);return{line:i,view:l,rect:null,map:u.map,cache:u.cache,before:u.before,hasHeights:!1}}function jr(n,i,a,l,u){i.before&&(a=-1);var m=a+(l||\"\"),y;return i.cache.hasOwnProperty(m)?y=i.cache[m]:(i.rect||(i.rect=i.view.text.getBoundingClientRect()),i.hasHeights||(hk(n,i.view,i.rect),i.hasHeights=!0),y=mk(n,i,a,l),y.bogus||(i.cache[m]=y)),{left:y.left,right:y.right,top:u?y.rtop:y.top,bottom:u?y.rbottom:y.bottom}}var vg={left:0,right:0,top:0,bottom:0};function yg(n,i,a){for(var l,u,m,y,x,S,T=0;T<n.length;T+=3)if(x=n[T],S=n[T+1],i<x?(u=0,m=1,y=\"left\"):i<S?(u=i-x,m=u+1):(T==n.length-3||i==S&&n[T+3]>i)&&(m=S-x,u=m-1,i>=S&&(y=\"right\")),u!=null){if(l=n[T+2],x==S&&a==(l.insertLeft?\"left\":\"right\")&&(y=a),a==\"left\"&&u==0)for(;T&&n[T-2]==n[T-3]&&n[T-1].insertLeft;)l=n[(T-=3)+2],y=\"left\";if(a==\"right\"&&u==S-x)for(;T<n.length-3&&n[T+3]==n[T+4]&&!n[T+5].insertLeft;)l=n[(T+=3)+2],y=\"right\";break}return{node:l,start:u,end:m,collapse:y,coverStart:x,coverEnd:S}}function gk(n,i){var a=vg;if(i==\"left\")for(var l=0;l<n.length&&(a=n[l]).left==a.right;l++);else for(var u=n.length-1;u>=0&&(a=n[u]).left==a.right;u--);return a}function mk(n,i,a,l){var u=yg(i.map,a,l),m=u.node,y=u.start,x=u.end,S=u.collapse,T;if(m.nodeType==3){for(var H=0;H<4;H++){for(;y&&ut(i.line.text.charAt(u.coverStart+y));)--y;for(;u.coverStart+x<u.coverEnd&&ut(i.line.text.charAt(u.coverStart+x));)++x;if(h&&p<9&&y==0&&x==u.coverEnd-u.coverStart?T=m.parentNode.getBoundingClientRect():T=gk(B(m,y,x).getClientRects(),l),T.left||T.right||y==0)break;x=y,y=y-1,S=\"right\"}h&&p<11&&(T=vk(n.display.measure,T))}else{y>0&&(S=l=\"right\");var V;n.options.lineWrapping&&(V=m.getClientRects()).length>1?T=V[l==\"right\"?V.length-1:0]:T=m.getBoundingClientRect()}if(h&&p<9&&!y&&(!T||!T.left&&!T.right)){var se=m.parentNode.getClientRects()[0];se?T={left:se.left,right:se.left+cs(n.display),top:se.top,bottom:se.bottom}:T=vg}for(var te=T.top-i.rect.top,pe=T.bottom-i.rect.top,we=(te+pe)/2,Te=i.view.measure.heights,Le=0;Le<Te.length-1&&!(we<Te[Le]);Le++);var De=Le?Te[Le-1]:0,Me=Te[Le],ze={left:(S==\"right\"?T.right:T.left)-i.rect.left,right:(S==\"left\"?T.left:T.right)-i.rect.left,top:De,bottom:Me};return!T.left&&!T.right&&(ze.bogus=!0),n.options.singleCursorHeightPerLine||(ze.rtop=te,ze.rbottom=pe),ze}function vk(n,i){if(!window.screen||screen.logicalXDPI==null||screen.logicalXDPI==screen.deviceXDPI||!vf(n))return i;var a=screen.logicalXDPI/screen.deviceXDPI,l=screen.logicalYDPI/screen.deviceYDPI;return{left:i.left*a,right:i.right*a,top:i.top*l,bottom:i.bottom*l}}function bg(n){if(n.measure&&(n.measure.cache={},n.measure.heights=null,n.rest))for(var i=0;i<n.rest.length;i++)n.measure.caches[i]={}}function wg(n){n.display.externalMeasure=null,O(n.display.lineMeasure);for(var i=0;i<n.display.view.length;i++)bg(n.display.view[i])}function gl(n){wg(n),n.display.cachedCharWidth=n.display.cachedTextHeight=n.display.cachedPaddingH=null,n.options.lineWrapping||(n.display.maxLineChanged=!0),n.display.lineNumChars=null}function xg(n){return b&&I?-(n.body.getBoundingClientRect().left-parseInt(getComputedStyle(n.body).marginLeft)):n.defaultView.pageXOffset||(n.documentElement||n.body).scrollLeft}function kg(n){return b&&I?-(n.body.getBoundingClientRect().top-parseInt(getComputedStyle(n.body).marginTop)):n.defaultView.pageYOffset||(n.documentElement||n.body).scrollTop}function Lf(n){var i=Sr(n),a=i.widgets,l=0;if(a)for(var u=0;u<a.length;++u)a[u].above&&(l+=pl(a[u]));return l}function rc(n,i,a,l,u){if(!u){var m=Lf(i);a.top+=m,a.bottom+=m}if(l==\"line\")return a;l||(l=\"local\");var y=si(i);if(l==\"local\"?y+=nc(n.display):y-=n.display.viewOffset,l==\"page\"||l==\"window\"){var x=n.display.lineSpace.getBoundingClientRect();y+=x.top+(l==\"window\"?0:kg(Ke(n)));var S=x.left+(l==\"window\"?0:xg(Ke(n)));a.left+=S,a.right+=S}return a.top+=y,a.bottom+=y,a}function Sg(n,i,a){if(a==\"div\")return i;var l=i.left,u=i.top;if(a==\"page\")l-=xg(Ke(n)),u-=kg(Ke(n));else if(a==\"local\"||!a){var m=n.display.sizer.getBoundingClientRect();l+=m.left,u+=m.top}var y=n.display.lineSpace.getBoundingClientRect();return{left:l-y.left,top:u-y.top}}function ic(n,i,a,l,u){return l||(l=qe(n.doc,i.line)),rc(n,l,mg(n,l,i.ch,u),a)}function _r(n,i,a,l,u,m){l=l||qe(n.doc,i.line),u||(u=ls(n,l));function y(pe,we){var Te=jr(n,u,pe,we?\"right\":\"left\",m);return we?Te.left=Te.right:Te.right=Te.left,rc(n,l,Te,a)}var x=lt(l,n.doc.direction),S=i.ch,T=i.sticky;if(S>=l.text.length?(S=l.text.length,T=\"before\"):S<=0&&(S=0,T=\"after\"),!x)return y(T==\"before\"?S-1:S,T==\"before\");function H(pe,we,Te){var Le=x[we],De=Le.level==1;return y(Te?pe-1:pe,De!=Te)}var V=Bt(x,S,T),se=Hr,te=H(S,V,T==\"before\");return se!=null&&(te.other=H(S,se,T!=\"before\")),te}function _g(n,i){var a=0;i=tt(n.doc,i),n.options.lineWrapping||(a=cs(n.display)*i.ch);var l=qe(n.doc,i.line),u=si(l)+nc(n.display);return{left:a,right:a,top:u,bottom:u+l.height}}function Mf(n,i,a,l,u){var m=fe(n,i,a);return m.xRel=u,l&&(m.outside=l),m}function Nf(n,i,a){var l=n.doc;if(a+=n.display.viewOffset,a<0)return Mf(l.first,0,null,-1,-1);var u=U(l,a),m=l.first+l.size-1;if(u>m)return Mf(l.first+l.size-1,qe(l,m).text.length,null,1,1);i<0&&(i=0);for(var y=qe(l,u);;){var x=yk(n,y,u,i,a),S=V1(y,x.ch+(x.xRel>0||x.outside>0?1:0));if(!S)return x;var T=S.find(1);if(T.line==u)return T;y=qe(l,u=T.line)}}function Tg(n,i,a,l){l-=Lf(i);var u=i.text.length,m=jt(function(y){return jr(n,a,y-1).bottom<=l},u,0);return u=jt(function(y){return jr(n,a,y).top>l},m,u),{begin:m,end:u}}function Cg(n,i,a,l){a||(a=ls(n,i));var u=rc(n,i,jr(n,a,l),\"line\").top;return Tg(n,i,a,u)}function Of(n,i,a,l){return n.bottom<=a?!1:n.top>a?!0:(l?n.left:n.right)>i}function yk(n,i,a,l,u){u-=si(i);var m=ls(n,i),y=Lf(i),x=0,S=i.text.length,T=!0,H=lt(i,n.doc.direction);if(H){var V=(n.options.lineWrapping?wk:bk)(n,i,a,m,H,l,u);T=V.level!=1,x=T?V.from:V.to-1,S=T?V.to:V.from-1}var se=null,te=null,pe=jt(function(Ye){var Ue=jr(n,m,Ye);return Ue.top+=y,Ue.bottom+=y,Of(Ue,l,u,!1)?(Ue.top<=u&&Ue.left<=l&&(se=Ye,te=Ue),!0):!1},x,S),we,Te,Le=!1;if(te){var De=l-te.left<te.right-l,Me=De==T;pe=se+(Me?0:1),Te=Me?\"after\":\"before\",we=De?te.left:te.right}else{!T&&(pe==S||pe==x)&&pe++,Te=pe==0?\"after\":pe==i.text.length?\"before\":jr(n,m,pe-(T?1:0)).bottom+y<=u==T?\"after\":\"before\";var ze=_r(n,fe(a,pe,Te),\"line\",i,m);we=ze.left,Le=u<ze.top?-1:u>=ze.bottom?1:0}return pe=Yt(i.text,pe,1),Mf(a,pe,Te,Le,l-we)}function bk(n,i,a,l,u,m,y){var x=jt(function(V){var se=u[V],te=se.level!=1;return Of(_r(n,fe(a,te?se.to:se.from,te?\"before\":\"after\"),\"line\",i,l),m,y,!0)},0,u.length-1),S=u[x];if(x>0){var T=S.level!=1,H=_r(n,fe(a,T?S.from:S.to,T?\"after\":\"before\"),\"line\",i,l);Of(H,m,y,!0)&&H.top>y&&(S=u[x-1])}return S}function wk(n,i,a,l,u,m,y){var x=Tg(n,i,l,y),S=x.begin,T=x.end;/\\s/.test(i.text.charAt(T-1))&&T--;for(var H=null,V=null,se=0;se<u.length;se++){var te=u[se];if(!(te.from>=T||te.to<=S)){var pe=te.level!=1,we=jr(n,l,pe?Math.min(T,te.to)-1:Math.max(S,te.from)).right,Te=we<m?m-we+1e9:we-m;(!H||V>Te)&&(H=te,V=Te)}}return H||(H=u[u.length-1]),H.from<S&&(H={from:S,to:H.to,level:H.level}),H.to>T&&(H={from:H.from,to:T,level:H.level}),H}var xo;function as(n){if(n.cachedTextHeight!=null)return n.cachedTextHeight;if(xo==null){xo=k(\"pre\",null,\"CodeMirror-line-like\");for(var i=0;i<49;++i)xo.appendChild(document.createTextNode(\"x\")),xo.appendChild(k(\"br\"));xo.appendChild(document.createTextNode(\"x\"))}C(n.measure,xo);var a=xo.offsetHeight/50;return a>3&&(n.cachedTextHeight=a),O(n.measure),a||1}function cs(n){if(n.cachedCharWidth!=null)return n.cachedCharWidth;var i=k(\"span\",\"xxxxxxxxxx\"),a=k(\"pre\",[i],\"CodeMirror-line-like\");C(n.measure,a);var l=i.getBoundingClientRect(),u=(l.right-l.left)/10;return u>2&&(n.cachedCharWidth=u),u||10}function Pf(n){for(var i=n.display,a={},l={},u=i.gutters.clientLeft,m=i.gutters.firstChild,y=0;m;m=m.nextSibling,++y){var x=n.display.gutterSpecs[y].className;a[x]=m.offsetLeft+m.clientLeft+u,l[x]=m.clientWidth}return{fixedPos:Rf(i),gutterTotalWidth:i.gutters.offsetWidth,gutterLeft:a,gutterWidth:l,wrapperWidth:i.wrapper.clientWidth}}function Rf(n){return n.scroller.getBoundingClientRect().left-n.sizer.getBoundingClientRect().left}function Eg(n){var i=as(n.display),a=n.options.lineWrapping,l=a&&Math.max(5,n.display.scroller.clientWidth/cs(n.display)-3);return function(u){if(Ii(n.doc,u))return 0;var m=0;if(u.widgets)for(var y=0;y<u.widgets.length;y++)u.widgets[y].height&&(m+=u.widgets[y].height);return a?m+(Math.ceil(u.text.length/l)||1)*i:m+i}}function $f(n){var i=n.doc,a=Eg(n);i.iter(function(l){var u=a(l);u!=l.height&&Qn(l,u)})}function ko(n,i,a,l){var u=n.display;if(!a&&sl(i).getAttribute(\"cm-not-content\")==\"true\")return null;var m,y,x=u.lineSpace.getBoundingClientRect();try{m=i.clientX-x.left,y=i.clientY-x.top}catch{return null}var S=Nf(n,m,y),T;if(l&&S.xRel>0&&(T=qe(n.doc,S.line).text).length==S.ch){var H=re(T,T.length,n.options.tabSize)-T.length;S=fe(S.line,Math.max(0,Math.round((m-pg(n.display).left)/cs(n.display))-H))}return S}function So(n,i){if(i>=n.display.viewTo||(i-=n.display.viewFrom,i<0))return null;for(var a=n.display.view,l=0;l<a.length;l++)if(i-=a[l].size,i<0)return l}function _n(n,i,a,l){i==null&&(i=n.doc.first),a==null&&(a=n.doc.first+n.doc.size),l||(l=0);var u=n.display;if(l&&a<u.viewTo&&(u.updateLineNumbers==null||u.updateLineNumbers>i)&&(u.updateLineNumbers=i),n.curOp.viewChanged=!0,i>=u.viewTo)oi&&kf(n.doc,i)<u.viewTo&&zi(n);else if(a<=u.viewFrom)oi&&ig(n.doc,a+l)>u.viewFrom?zi(n):(u.viewFrom+=l,u.viewTo+=l);else if(i<=u.viewFrom&&a>=u.viewTo)zi(n);else if(i<=u.viewFrom){var m=oc(n,a,a+l,1);m?(u.view=u.view.slice(m.index),u.viewFrom=m.lineN,u.viewTo+=l):zi(n)}else if(a>=u.viewTo){var y=oc(n,i,i,-1);y?(u.view=u.view.slice(0,y.index),u.viewTo=y.lineN):zi(n)}else{var x=oc(n,i,i,-1),S=oc(n,a,a+l,1);x&&S?(u.view=u.view.slice(0,x.index).concat(tc(n,x.lineN,S.lineN)).concat(u.view.slice(S.index)),u.viewTo+=l):zi(n)}var T=u.externalMeasured;T&&(a<T.lineN?T.lineN+=l:i<T.lineN+T.size&&(u.externalMeasured=null))}function Di(n,i,a){n.curOp.viewChanged=!0;var l=n.display,u=n.display.externalMeasured;if(u&&i>=u.lineN&&i<u.lineN+u.size&&(l.externalMeasured=null),!(i<l.viewFrom||i>=l.viewTo)){var m=l.view[So(n,i)];if(m.node!=null){var y=m.changes||(m.changes=[]);ae(y,a)==-1&&y.push(a)}}}function zi(n){n.display.viewFrom=n.display.viewTo=n.doc.first,n.display.view=[],n.display.viewOffset=0}function oc(n,i,a,l){var u=So(n,i),m,y=n.display.view;if(!oi||a==n.doc.first+n.doc.size)return{index:u,lineN:a};for(var x=n.display.viewFrom,S=0;S<u;S++)x+=y[S].size;if(x!=i){if(l>0){if(u==y.length-1)return null;m=x+y[u].size-i,u++}else m=x-i;i+=m,a+=m}for(;kf(n.doc,a)!=a;){if(u==(l<0?0:y.length-1))return null;a+=l*y[u-(l<0?1:0)].size,u+=l}return{index:u,lineN:a}}function xk(n,i,a){var l=n.display,u=l.view;u.length==0||i>=l.viewTo||a<=l.viewFrom?(l.view=tc(n,i,a),l.viewFrom=i):(l.viewFrom>i?l.view=tc(n,i,l.viewFrom).concat(l.view):l.viewFrom<i&&(l.view=l.view.slice(So(n,i))),l.viewFrom=i,l.viewTo<a?l.view=l.view.concat(tc(n,l.viewTo,a)):l.viewTo>a&&(l.view=l.view.slice(0,So(n,a)))),l.viewTo=a}function Ag(n){for(var i=n.display.view,a=0,l=0;l<i.length;l++){var u=i[l];!u.hidden&&(!u.node||u.changes)&&++a}return a}function ml(n){n.display.input.showSelection(n.display.input.prepareSelection())}function Lg(n,i){i===void 0&&(i=!0);var a=n.doc,l={},u=l.cursors=document.createDocumentFragment(),m=l.selection=document.createDocumentFragment(),y=n.options.$customCursor;y&&(i=!0);for(var x=0;x<a.sel.ranges.length;x++)if(!(!i&&x==a.sel.primIndex)){var S=a.sel.ranges[x];if(!(S.from().line>=n.display.viewTo||S.to().line<n.display.viewFrom)){var T=S.empty();if(y){var H=y(n,S);H&&If(n,H,u)}else(T||n.options.showCursorWhenSelecting)&&If(n,S.head,u);T||kk(n,S,m)}}return l}function If(n,i,a){var l=_r(n,i,\"div\",null,null,!n.options.singleCursorHeightPerLine),u=a.appendChild(k(\"div\",\" \",\"CodeMirror-cursor\"));if(u.style.left=l.left+\"px\",u.style.top=l.top+\"px\",u.style.height=Math.max(0,l.bottom-l.top)*n.options.cursorHeight+\"px\",/\\bcm-fat-cursor\\b/.test(n.getWrapperElement().className)){var m=ic(n,i,\"div\",null,null),y=m.right-m.left;u.style.width=(y>0?y:n.defaultCharWidth())+\"px\"}if(l.other){var x=a.appendChild(k(\"div\",\" \",\"CodeMirror-cursor CodeMirror-secondarycursor\"));x.style.display=\"\",x.style.left=l.other.left+\"px\",x.style.top=l.other.top+\"px\",x.style.height=(l.other.bottom-l.other.top)*.85+\"px\"}}function sc(n,i){return n.top-i.top||n.left-i.left}function kk(n,i,a){var l=n.display,u=n.doc,m=document.createDocumentFragment(),y=pg(n.display),x=y.left,S=Math.max(l.sizerWidth,wo(n)-l.sizer.offsetLeft)-y.right,T=u.direction==\"ltr\";function H(Me,ze,Ye,Ue){ze<0&&(ze=0),ze=Math.round(ze),Ue=Math.round(Ue),m.appendChild(k(\"div\",null,\"CodeMirror-selected\",\"position: absolute; left: \"+Me+`px;\n                             top: `+ze+\"px; width: \"+(Ye??S-Me)+`px;\n                             height: `+(Ue-ze)+\"px\"))}function V(Me,ze,Ye){var Ue=qe(u,Me),st=Ue.text.length,St,tn;function Ot(Ut,En){return ic(n,fe(Me,Ut),\"div\",Ue,En)}function qn(Ut,En,sn){var Kt=Cg(n,Ue,null,Ut),Vt=En==\"ltr\"==(sn==\"after\")?\"left\":\"right\",It=sn==\"after\"?Kt.begin:Kt.end-(/\\s/.test(Ue.text.charAt(Kt.end-1))?2:1);return Ot(It,Vt)[Vt]}var Cn=lt(Ue,u.direction);return Fn(Cn,ze||0,Ye??st,function(Ut,En,sn,Kt){var Vt=sn==\"ltr\",It=Ot(Ut,Vt?\"left\":\"right\"),An=Ot(En-1,Vt?\"right\":\"left\"),ks=ze==null&&Ut==0,ji=Ye==null&&En==st,fn=Kt==0,Ur=!Cn||Kt==Cn.length-1;if(An.top-It.top<=3){var nn=(T?ks:ji)&&fn,cd=(T?ji:ks)&&Ur,ui=nn?x:(Vt?It:An).left,Ao=cd?S:(Vt?An:It).right;H(ui,It.top,Ao-ui,It.bottom)}else{var Lo,yn,Ss,ud;Vt?(Lo=T&&ks&&fn?x:It.left,yn=T?S:qn(Ut,sn,\"before\"),Ss=T?x:qn(En,sn,\"after\"),ud=T&&ji&&Ur?S:An.right):(Lo=T?qn(Ut,sn,\"before\"):x,yn=!T&&ks&&fn?S:It.right,Ss=!T&&ji&&Ur?x:An.left,ud=T?qn(En,sn,\"after\"):S),H(Lo,It.top,yn-Lo,It.bottom),It.bottom<An.top&&H(x,It.bottom,null,An.top),H(Ss,An.top,ud-Ss,An.bottom)}(!St||sc(It,St)<0)&&(St=It),sc(An,St)<0&&(St=An),(!tn||sc(It,tn)<0)&&(tn=It),sc(An,tn)<0&&(tn=An)}),{start:St,end:tn}}var se=i.from(),te=i.to();if(se.line==te.line)V(se.line,se.ch,te.ch);else{var pe=qe(u,se.line),we=qe(u,te.line),Te=Sr(pe)==Sr(we),Le=V(se.line,se.ch,Te?pe.text.length+1:null).end,De=V(te.line,Te?0:null,te.ch).start;Te&&(Le.top<De.top-2?(H(Le.right,Le.top,null,Le.bottom),H(x,De.top,De.left,De.bottom)):H(Le.right,Le.top,De.left-Le.right,Le.bottom)),Le.bottom<De.top&&H(x,Le.bottom,null,De.top)}a.appendChild(m)}function Df(n){if(n.state.focused){var i=n.display;clearInterval(i.blinker);var a=!0;i.cursorDiv.style.visibility=\"\",n.options.cursorBlinkRate>0?i.blinker=setInterval(function(){n.hasFocus()||us(n),i.cursorDiv.style.visibility=(a=!a)?\"\":\"hidden\"},n.options.cursorBlinkRate):n.options.cursorBlinkRate<0&&(i.cursorDiv.style.visibility=\"hidden\")}}function Mg(n){n.hasFocus()||(n.display.input.focus(),n.state.focused||Ff(n))}function zf(n){n.state.delayingBlurEvent=!0,setTimeout(function(){n.state.delayingBlurEvent&&(n.state.delayingBlurEvent=!1,n.state.focused&&us(n))},100)}function Ff(n,i){n.state.delayingBlurEvent&&!n.state.draggingText&&(n.state.delayingBlurEvent=!1),n.options.readOnly!=\"nocursor\"&&(n.state.focused||(Pt(n,\"focus\",n,i),n.state.focused=!0,Se(n.display.wrapper,\"CodeMirror-focused\"),!n.curOp&&n.display.selForContextMenu!=n.doc.sel&&(n.display.input.reset(),g&&setTimeout(function(){return n.display.input.reset(!0)},20)),n.display.input.receivedFocus()),Df(n))}function us(n,i){n.state.delayingBlurEvent||(n.state.focused&&(Pt(n,\"blur\",n,i),n.state.focused=!1,N(n.display.wrapper,\"CodeMirror-focused\")),clearInterval(n.display.blinker),setTimeout(function(){n.state.focused||(n.display.shift=!1)},150))}function lc(n){for(var i=n.display,a=i.lineDiv.offsetTop,l=Math.max(0,i.scroller.getBoundingClientRect().top),u=i.lineDiv.getBoundingClientRect().top,m=0,y=0;y<i.view.length;y++){var x=i.view[y],S=n.options.lineWrapping,T=void 0,H=0;if(!x.hidden){if(u+=x.line.height,h&&p<8){var V=x.node.offsetTop+x.node.offsetHeight;T=V-a,a=V}else{var se=x.node.getBoundingClientRect();T=se.bottom-se.top,!S&&x.text.firstChild&&(H=x.text.firstChild.getBoundingClientRect().right-se.left-1)}var te=x.line.height-T;if((te>.005||te<-.005)&&(u<l&&(m-=te),Qn(x.line,T),Ng(x.line),x.rest))for(var pe=0;pe<x.rest.length;pe++)Ng(x.rest[pe]);if(H>n.display.sizerWidth){var we=Math.ceil(H/cs(n.display));we>n.display.maxLineLength&&(n.display.maxLineLength=we,n.display.maxLine=x.line,n.display.maxLineChanged=!0)}}}Math.abs(m)>2&&(i.scroller.scrollTop+=m)}function Ng(n){if(n.widgets)for(var i=0;i<n.widgets.length;++i){var a=n.widgets[i],l=a.node.parentNode;l&&(a.height=l.offsetHeight)}}function ac(n,i,a){var l=a&&a.top!=null?Math.max(0,a.top):n.scroller.scrollTop;l=Math.floor(l-nc(n));var u=a&&a.bottom!=null?a.bottom:l+n.wrapper.clientHeight,m=U(i,l),y=U(i,u);if(a&&a.ensure){var x=a.ensure.from.line,S=a.ensure.to.line;x<m?(m=x,y=U(i,si(qe(i,x))+n.wrapper.clientHeight)):Math.min(S,i.lastLine())>=y&&(m=U(i,si(qe(i,S))-n.wrapper.clientHeight),y=S)}return{from:m,to:Math.max(y,m+1)}}function Sk(n,i){if(!Rt(n,\"scrollCursorIntoView\")){var a=n.display,l=a.sizer.getBoundingClientRect(),u=null,m=a.wrapper.ownerDocument;if(i.top+l.top<0?u=!0:i.bottom+l.top>(m.defaultView.innerHeight||m.documentElement.clientHeight)&&(u=!1),u!=null&&!M){var y=k(\"div\",\"​\",null,`position: absolute;\n                         top: `+(i.top-a.viewOffset-nc(n.display))+`px;\n                         height: `+(i.bottom-i.top+qr(n)+a.barHeight)+`px;\n                         left: `+i.left+\"px; width: \"+Math.max(2,i.right-i.left)+\"px;\");n.display.lineSpace.appendChild(y),y.scrollIntoView(u),n.display.lineSpace.removeChild(y)}}}function _k(n,i,a,l){l==null&&(l=0);var u;!n.options.lineWrapping&&i==a&&(a=i.sticky==\"before\"?fe(i.line,i.ch+1,\"before\"):i,i=i.ch?fe(i.line,i.sticky==\"before\"?i.ch-1:i.ch,\"after\"):i);for(var m=0;m<5;m++){var y=!1,x=_r(n,i),S=!a||a==i?x:_r(n,a);u={left:Math.min(x.left,S.left),top:Math.min(x.top,S.top)-l,right:Math.max(x.left,S.left),bottom:Math.max(x.bottom,S.bottom)+l};var T=Hf(n,u),H=n.doc.scrollTop,V=n.doc.scrollLeft;if(T.scrollTop!=null&&(yl(n,T.scrollTop),Math.abs(n.doc.scrollTop-H)>1&&(y=!0)),T.scrollLeft!=null&&(_o(n,T.scrollLeft),Math.abs(n.doc.scrollLeft-V)>1&&(y=!0)),!y)break}return u}function Tk(n,i){var a=Hf(n,i);a.scrollTop!=null&&yl(n,a.scrollTop),a.scrollLeft!=null&&_o(n,a.scrollLeft)}function Hf(n,i){var a=n.display,l=as(n.display);i.top<0&&(i.top=0);var u=n.curOp&&n.curOp.scrollTop!=null?n.curOp.scrollTop:a.scroller.scrollTop,m=Ef(n),y={};i.bottom-i.top>m&&(i.bottom=i.top+m);var x=n.doc.height+Cf(a),S=i.top<l,T=i.bottom>x-l;if(i.top<u)y.scrollTop=S?0:i.top;else if(i.bottom>u+m){var H=Math.min(i.top,(T?x:i.bottom)-m);H!=u&&(y.scrollTop=H)}var V=n.options.fixedGutter?0:a.gutters.offsetWidth,se=n.curOp&&n.curOp.scrollLeft!=null?n.curOp.scrollLeft:a.scroller.scrollLeft-V,te=wo(n)-a.gutters.offsetWidth,pe=i.right-i.left>te;return pe&&(i.right=i.left+te),i.left<10?y.scrollLeft=0:i.left<se?y.scrollLeft=Math.max(0,i.left+V-(pe?0:10)):i.right>te+se-3&&(y.scrollLeft=i.right+(pe?0:10)-te),y}function Bf(n,i){i!=null&&(cc(n),n.curOp.scrollTop=(n.curOp.scrollTop==null?n.doc.scrollTop:n.curOp.scrollTop)+i)}function fs(n){cc(n);var i=n.getCursor();n.curOp.scrollToPos={from:i,to:i,margin:n.options.cursorScrollMargin}}function vl(n,i,a){(i!=null||a!=null)&&cc(n),i!=null&&(n.curOp.scrollLeft=i),a!=null&&(n.curOp.scrollTop=a)}function Ck(n,i){cc(n),n.curOp.scrollToPos=i}function cc(n){var i=n.curOp.scrollToPos;if(i){n.curOp.scrollToPos=null;var a=_g(n,i.from),l=_g(n,i.to);Og(n,a,l,i.margin)}}function Og(n,i,a,l){var u=Hf(n,{left:Math.min(i.left,a.left),top:Math.min(i.top,a.top)-l,right:Math.max(i.right,a.right),bottom:Math.max(i.bottom,a.bottom)+l});vl(n,u.scrollLeft,u.scrollTop)}function yl(n,i){Math.abs(n.doc.scrollTop-i)<2||(s||qf(n,{top:i}),Pg(n,i,!0),s&&qf(n),xl(n,100))}function Pg(n,i,a){i=Math.max(0,Math.min(n.display.scroller.scrollHeight-n.display.scroller.clientHeight,i)),!(n.display.scroller.scrollTop==i&&!a)&&(n.doc.scrollTop=i,n.display.scrollbars.setScrollTop(i),n.display.scroller.scrollTop!=i&&(n.display.scroller.scrollTop=i))}function _o(n,i,a,l){i=Math.max(0,Math.min(i,n.display.scroller.scrollWidth-n.display.scroller.clientWidth)),!((a?i==n.doc.scrollLeft:Math.abs(n.doc.scrollLeft-i)<2)&&!l)&&(n.doc.scrollLeft=i,zg(n),n.display.scroller.scrollLeft!=i&&(n.display.scroller.scrollLeft=i),n.display.scrollbars.setScrollLeft(i))}function bl(n){var i=n.display,a=i.gutters.offsetWidth,l=Math.round(n.doc.height+Cf(n.display));return{clientHeight:i.scroller.clientHeight,viewHeight:i.wrapper.clientHeight,scrollWidth:i.scroller.scrollWidth,clientWidth:i.scroller.clientWidth,viewWidth:i.wrapper.clientWidth,barLeft:n.options.fixedGutter?a:0,docHeight:l,scrollHeight:l+qr(n)+i.barHeight,nativeBarWidth:i.nativeBarWidth,gutterWidth:a}}var To=function(n,i,a){this.cm=a;var l=this.vert=k(\"div\",[k(\"div\",null,null,\"min-width: 1px\")],\"CodeMirror-vscrollbar\"),u=this.horiz=k(\"div\",[k(\"div\",null,null,\"height: 100%; min-height: 1px\")],\"CodeMirror-hscrollbar\");l.tabIndex=u.tabIndex=-1,n(l),n(u),Xe(l,\"scroll\",function(){l.clientHeight&&i(l.scrollTop,\"vertical\")}),Xe(u,\"scroll\",function(){u.clientWidth&&i(u.scrollLeft,\"horizontal\")}),this.checkedZeroWidth=!1,h&&p<8&&(this.horiz.style.minHeight=this.vert.style.minWidth=\"18px\")};To.prototype.update=function(n){var i=n.scrollWidth>n.clientWidth+1,a=n.scrollHeight>n.clientHeight+1,l=n.nativeBarWidth;if(a){this.vert.style.display=\"block\",this.vert.style.bottom=i?l+\"px\":\"0\";var u=n.viewHeight-(i?l:0);this.vert.firstChild.style.height=Math.max(0,n.scrollHeight-n.clientHeight+u)+\"px\"}else this.vert.scrollTop=0,this.vert.style.display=\"\",this.vert.firstChild.style.height=\"0\";if(i){this.horiz.style.display=\"block\",this.horiz.style.right=a?l+\"px\":\"0\",this.horiz.style.left=n.barLeft+\"px\";var m=n.viewWidth-n.barLeft-(a?l:0);this.horiz.firstChild.style.width=Math.max(0,n.scrollWidth-n.clientWidth+m)+\"px\"}else this.horiz.style.display=\"\",this.horiz.firstChild.style.width=\"0\";return!this.checkedZeroWidth&&n.clientHeight>0&&(l==0&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:a?l:0,bottom:i?l:0}},To.prototype.setScrollLeft=function(n){this.horiz.scrollLeft!=n&&(this.horiz.scrollLeft=n),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,\"horiz\")},To.prototype.setScrollTop=function(n){this.vert.scrollTop!=n&&(this.vert.scrollTop=n),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,\"vert\")},To.prototype.zeroWidthHack=function(){var n=$&&!P?\"12px\":\"18px\";this.horiz.style.height=this.vert.style.width=n,this.horiz.style.visibility=this.vert.style.visibility=\"hidden\",this.disableHoriz=new le,this.disableVert=new le},To.prototype.enableZeroWidthBar=function(n,i,a){n.style.visibility=\"\";function l(){var u=n.getBoundingClientRect(),m=a==\"vert\"?document.elementFromPoint(u.right-1,(u.top+u.bottom)/2):document.elementFromPoint((u.right+u.left)/2,u.bottom-1);m!=n?n.style.visibility=\"hidden\":i.set(1e3,l)}i.set(1e3,l)},To.prototype.clear=function(){var n=this.horiz.parentNode;n.removeChild(this.horiz),n.removeChild(this.vert)};var wl=function(){};wl.prototype.update=function(){return{bottom:0,right:0}},wl.prototype.setScrollLeft=function(){},wl.prototype.setScrollTop=function(){},wl.prototype.clear=function(){};function ds(n,i){i||(i=bl(n));var a=n.display.barWidth,l=n.display.barHeight;Rg(n,i);for(var u=0;u<4&&a!=n.display.barWidth||l!=n.display.barHeight;u++)a!=n.display.barWidth&&n.options.lineWrapping&&lc(n),Rg(n,bl(n)),a=n.display.barWidth,l=n.display.barHeight}function Rg(n,i){var a=n.display,l=a.scrollbars.update(i);a.sizer.style.paddingRight=(a.barWidth=l.right)+\"px\",a.sizer.style.paddingBottom=(a.barHeight=l.bottom)+\"px\",a.heightForcer.style.borderBottom=l.bottom+\"px solid transparent\",l.right&&l.bottom?(a.scrollbarFiller.style.display=\"block\",a.scrollbarFiller.style.height=l.bottom+\"px\",a.scrollbarFiller.style.width=l.right+\"px\"):a.scrollbarFiller.style.display=\"\",l.bottom&&n.options.coverGutterNextToScrollbar&&n.options.fixedGutter?(a.gutterFiller.style.display=\"block\",a.gutterFiller.style.height=l.bottom+\"px\",a.gutterFiller.style.width=i.gutterWidth+\"px\"):a.gutterFiller.style.display=\"\"}var $g={native:To,null:wl};function Ig(n){n.display.scrollbars&&(n.display.scrollbars.clear(),n.display.scrollbars.addClass&&N(n.display.wrapper,n.display.scrollbars.addClass)),n.display.scrollbars=new $g[n.options.scrollbarStyle](function(i){n.display.wrapper.insertBefore(i,n.display.scrollbarFiller),Xe(i,\"mousedown\",function(){n.state.focused&&setTimeout(function(){return n.display.input.focus()},0)}),i.setAttribute(\"cm-not-content\",\"true\")},function(i,a){a==\"horizontal\"?_o(n,i):yl(n,i)},n),n.display.scrollbars.addClass&&Se(n.display.wrapper,n.display.scrollbars.addClass)}var Ek=0;function Co(n){n.curOp={cm:n,viewChanged:!1,startHeight:n.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Ek,markArrays:null},ik(n.curOp)}function Eo(n){var i=n.curOp;i&&sk(i,function(a){for(var l=0;l<a.ops.length;l++)a.ops[l].cm.curOp=null;Ak(a)})}function Ak(n){for(var i=n.ops,a=0;a<i.length;a++)Lk(i[a]);for(var l=0;l<i.length;l++)Mk(i[l]);for(var u=0;u<i.length;u++)Nk(i[u]);for(var m=0;m<i.length;m++)Ok(i[m]);for(var y=0;y<i.length;y++)Pk(i[y])}function Lk(n){var i=n.cm,a=i.display;$k(i),n.updateMaxLine&&_f(i),n.mustUpdate=n.viewChanged||n.forceUpdate||n.scrollTop!=null||n.scrollToPos&&(n.scrollToPos.from.line<a.viewFrom||n.scrollToPos.to.line>=a.viewTo)||a.maxLineChanged&&i.options.lineWrapping,n.update=n.mustUpdate&&new uc(i,n.mustUpdate&&{top:n.scrollTop,ensure:n.scrollToPos},n.forceUpdate)}function Mk(n){n.updatedDisplay=n.mustUpdate&&Wf(n.cm,n.update)}function Nk(n){var i=n.cm,a=i.display;n.updatedDisplay&&lc(i),n.barMeasure=bl(i),a.maxLineChanged&&!i.options.lineWrapping&&(n.adjustWidthTo=mg(i,a.maxLine,a.maxLine.text.length).left+3,i.display.sizerWidth=n.adjustWidthTo,n.barMeasure.scrollWidth=Math.max(a.scroller.clientWidth,a.sizer.offsetLeft+n.adjustWidthTo+qr(i)+i.display.barWidth),n.maxScrollLeft=Math.max(0,a.sizer.offsetLeft+n.adjustWidthTo-wo(i))),(n.updatedDisplay||n.selectionChanged)&&(n.preparedSelection=a.input.prepareSelection())}function Ok(n){var i=n.cm;n.adjustWidthTo!=null&&(i.display.sizer.style.minWidth=n.adjustWidthTo+\"px\",n.maxScrollLeft<i.doc.scrollLeft&&_o(i,Math.min(i.display.scroller.scrollLeft,n.maxScrollLeft),!0),i.display.maxLineChanged=!1);var a=n.focus&&n.focus==be(je(i));n.preparedSelection&&i.display.input.showSelection(n.preparedSelection,a),(n.updatedDisplay||n.startHeight!=i.doc.height)&&ds(i,n.barMeasure),n.updatedDisplay&&Uf(i,n.barMeasure),n.selectionChanged&&Df(i),i.state.focused&&n.updateInput&&i.display.input.reset(n.typing),a&&Mg(n.cm)}function Pk(n){var i=n.cm,a=i.display,l=i.doc;if(n.updatedDisplay&&Dg(i,n.update),a.wheelStartX!=null&&(n.scrollTop!=null||n.scrollLeft!=null||n.scrollToPos)&&(a.wheelStartX=a.wheelStartY=null),n.scrollTop!=null&&Pg(i,n.scrollTop,n.forceScroll),n.scrollLeft!=null&&_o(i,n.scrollLeft,!0,!0),n.scrollToPos){var u=_k(i,tt(l,n.scrollToPos.from),tt(l,n.scrollToPos.to),n.scrollToPos.margin);Sk(i,u)}var m=n.maybeHiddenMarkers,y=n.maybeUnhiddenMarkers;if(m)for(var x=0;x<m.length;++x)m[x].lines.length||Pt(m[x],\"hide\");if(y)for(var S=0;S<y.length;++S)y[S].lines.length&&Pt(y[S],\"unhide\");a.wrapper.offsetHeight&&(l.scrollTop=i.display.scroller.scrollTop),n.changeObjs&&Pt(i,\"changes\",i,n.changeObjs),n.update&&n.update.finish()}function Wn(n,i){if(n.curOp)return i();Co(n);try{return i()}finally{Eo(n)}}function Qt(n,i){return function(){if(n.curOp)return i.apply(n,arguments);Co(n);try{return i.apply(n,arguments)}finally{Eo(n)}}}function vn(n){return function(){if(this.curOp)return n.apply(this,arguments);Co(this);try{return n.apply(this,arguments)}finally{Eo(this)}}}function en(n){return function(){var i=this.cm;if(!i||i.curOp)return n.apply(this,arguments);Co(i);try{return n.apply(this,arguments)}finally{Eo(i)}}}function xl(n,i){n.doc.highlightFrontier<n.display.viewTo&&n.state.highlight.set(i,F(Rk,n))}function Rk(n){var i=n.doc;if(!(i.highlightFrontier>=n.display.viewTo)){var a=+new Date+n.options.workTime,l=ul(n,i.highlightFrontier),u=[];i.iter(l.line,Math.min(i.first+i.size,n.display.viewTo+500),function(m){if(l.line>=n.display.viewFrom){var y=m.styles,x=m.text.length>n.options.maxHighlightLength?Br(i.mode,l.state):null,S=jp(n,m,l,!0);x&&(l.state=x),m.styles=S.styles;var T=m.styleClasses,H=S.classes;H?m.styleClasses=H:T&&(m.styleClasses=null);for(var V=!y||y.length!=m.styles.length||T!=H&&(!T||!H||T.bgClass!=H.bgClass||T.textClass!=H.textClass),se=0;!V&&se<y.length;++se)V=y[se]!=m.styles[se];V&&u.push(l.line),m.stateAfter=l.save(),l.nextLine()}else m.text.length<=n.options.maxHighlightLength&&yf(n,m.text,l),m.stateAfter=l.line%5==0?l.save():null,l.nextLine();if(+new Date>a)return xl(n,n.options.workDelay),!0}),i.highlightFrontier=l.line,i.modeFrontier=Math.max(i.modeFrontier,l.line),u.length&&Wn(n,function(){for(var m=0;m<u.length;m++)Di(n,u[m],\"text\")})}}var uc=function(n,i,a){var l=n.display;this.viewport=i,this.visible=ac(l,n.doc,i),this.editorIsHidden=!l.wrapper.offsetWidth,this.wrapperHeight=l.wrapper.clientHeight,this.wrapperWidth=l.wrapper.clientWidth,this.oldDisplayWidth=wo(n),this.force=a,this.dims=Pf(n),this.events=[]};uc.prototype.signal=function(n,i){Bn(n,i)&&this.events.push(arguments)},uc.prototype.finish=function(){for(var n=0;n<this.events.length;n++)Pt.apply(null,this.events[n])};function $k(n){var i=n.display;!i.scrollbarsClipped&&i.scroller.offsetWidth&&(i.nativeBarWidth=i.scroller.offsetWidth-i.scroller.clientWidth,i.heightForcer.style.height=qr(n)+\"px\",i.sizer.style.marginBottom=-i.nativeBarWidth+\"px\",i.sizer.style.borderRightWidth=qr(n)+\"px\",i.scrollbarsClipped=!0)}function Ik(n){if(n.hasFocus())return null;var i=be(je(n));if(!i||!ce(n.display.lineDiv,i))return null;var a={activeElt:i};if(window.getSelection){var l=Pe(n).getSelection();l.anchorNode&&l.extend&&ce(n.display.lineDiv,l.anchorNode)&&(a.anchorNode=l.anchorNode,a.anchorOffset=l.anchorOffset,a.focusNode=l.focusNode,a.focusOffset=l.focusOffset)}return a}function Dk(n){if(!(!n||!n.activeElt||n.activeElt==be(Fe(n.activeElt)))&&(n.activeElt.focus(),!/^(INPUT|TEXTAREA)$/.test(n.activeElt.nodeName)&&n.anchorNode&&ce(document.body,n.anchorNode)&&ce(document.body,n.focusNode))){var i=n.activeElt.ownerDocument,a=i.defaultView.getSelection(),l=i.createRange();l.setEnd(n.anchorNode,n.anchorOffset),l.collapse(!1),a.removeAllRanges(),a.addRange(l),a.extend(n.focusNode,n.focusOffset)}}function Wf(n,i){var a=n.display,l=n.doc;if(i.editorIsHidden)return zi(n),!1;if(!i.force&&i.visible.from>=a.viewFrom&&i.visible.to<=a.viewTo&&(a.updateLineNumbers==null||a.updateLineNumbers>=a.viewTo)&&a.renderedView==a.view&&Ag(n)==0)return!1;Fg(n)&&(zi(n),i.dims=Pf(n));var u=l.first+l.size,m=Math.max(i.visible.from-n.options.viewportMargin,l.first),y=Math.min(u,i.visible.to+n.options.viewportMargin);a.viewFrom<m&&m-a.viewFrom<20&&(m=Math.max(l.first,a.viewFrom)),a.viewTo>y&&a.viewTo-y<20&&(y=Math.min(u,a.viewTo)),oi&&(m=kf(n.doc,m),y=ig(n.doc,y));var x=m!=a.viewFrom||y!=a.viewTo||a.lastWrapHeight!=i.wrapperHeight||a.lastWrapWidth!=i.wrapperWidth;xk(n,m,y),a.viewOffset=si(qe(n.doc,a.viewFrom)),n.display.mover.style.top=a.viewOffset+\"px\";var S=Ag(n);if(!x&&S==0&&!i.force&&a.renderedView==a.view&&(a.updateLineNumbers==null||a.updateLineNumbers>=a.viewTo))return!1;var T=Ik(n);return S>4&&(a.lineDiv.style.display=\"none\"),zk(n,a.updateLineNumbers,i.dims),S>4&&(a.lineDiv.style.display=\"\"),a.renderedView=a.view,Dk(T),O(a.cursorDiv),O(a.selectionDiv),a.gutters.style.height=a.sizer.style.minHeight=0,x&&(a.lastWrapHeight=i.wrapperHeight,a.lastWrapWidth=i.wrapperWidth,xl(n,400)),a.updateLineNumbers=null,!0}function Dg(n,i){for(var a=i.viewport,l=!0;;l=!1){if(!l||!n.options.lineWrapping||i.oldDisplayWidth==wo(n)){if(a&&a.top!=null&&(a={top:Math.min(n.doc.height+Cf(n.display)-Ef(n),a.top)}),i.visible=ac(n.display,n.doc,a),i.visible.from>=n.display.viewFrom&&i.visible.to<=n.display.viewTo)break}else l&&(i.visible=ac(n.display,n.doc,a));if(!Wf(n,i))break;lc(n);var u=bl(n);ml(n),ds(n,u),Uf(n,u),i.force=!1}i.signal(n,\"update\",n),(n.display.viewFrom!=n.display.reportedViewFrom||n.display.viewTo!=n.display.reportedViewTo)&&(i.signal(n,\"viewportChange\",n,n.display.viewFrom,n.display.viewTo),n.display.reportedViewFrom=n.display.viewFrom,n.display.reportedViewTo=n.display.viewTo)}function qf(n,i){var a=new uc(n,i);if(Wf(n,a)){lc(n),Dg(n,a);var l=bl(n);ml(n),ds(n,l),Uf(n,l),a.finish()}}function zk(n,i,a){var l=n.display,u=n.options.lineNumbers,m=l.lineDiv,y=m.firstChild;function x(pe){var we=pe.nextSibling;return g&&$&&n.display.currentWheelTarget==pe?pe.style.display=\"none\":pe.parentNode.removeChild(pe),we}for(var S=l.view,T=l.viewFrom,H=0;H<S.length;H++){var V=S[H];if(!V.hidden)if(!V.node||V.node.parentNode!=m){var se=fk(n,V,T,a);m.insertBefore(se,y)}else{for(;y!=V.node;)y=x(y);var te=u&&i!=null&&i<=T&&V.lineNumber;V.changes&&(ae(V.changes,\"gutter\")>-1&&(te=!1),cg(n,V,T,a)),te&&(O(V.lineNumber),V.lineNumber.appendChild(document.createTextNode(_e(n.options,T)))),y=V.node.nextSibling}T+=V.size}for(;y;)y=x(y)}function jf(n){var i=n.gutters.offsetWidth;n.sizer.style.marginLeft=i+\"px\",Jt(n,\"gutterChanged\",n)}function Uf(n,i){n.display.sizer.style.minHeight=i.docHeight+\"px\",n.display.heightForcer.style.top=i.docHeight+\"px\",n.display.gutters.style.height=i.docHeight+n.display.barHeight+qr(n)+\"px\"}function zg(n){var i=n.display,a=i.view;if(!(!i.alignWidgets&&(!i.gutters.firstChild||!n.options.fixedGutter))){for(var l=Rf(i)-i.scroller.scrollLeft+n.doc.scrollLeft,u=i.gutters.offsetWidth,m=l+\"px\",y=0;y<a.length;y++)if(!a[y].hidden){n.options.fixedGutter&&(a[y].gutter&&(a[y].gutter.style.left=m),a[y].gutterBackground&&(a[y].gutterBackground.style.left=m));var x=a[y].alignable;if(x)for(var S=0;S<x.length;S++)x[S].style.left=m}n.options.fixedGutter&&(i.gutters.style.left=l+u+\"px\")}}function Fg(n){if(!n.options.lineNumbers)return!1;var i=n.doc,a=_e(n.options,i.first+i.size-1),l=n.display;if(a.length!=l.lineNumChars){var u=l.measure.appendChild(k(\"div\",[k(\"div\",a)],\"CodeMirror-linenumber CodeMirror-gutter-elt\")),m=u.firstChild.offsetWidth,y=u.offsetWidth-m;return l.lineGutter.style.width=\"\",l.lineNumInnerWidth=Math.max(m,l.lineGutter.offsetWidth-y)+1,l.lineNumWidth=l.lineNumInnerWidth+y,l.lineNumChars=l.lineNumInnerWidth?a.length:-1,l.lineGutter.style.width=l.lineNumWidth+\"px\",jf(n.display),!0}return!1}function Vf(n,i){for(var a=[],l=!1,u=0;u<n.length;u++){var m=n[u],y=null;if(typeof m!=\"string\"&&(y=m.style,m=m.className),m==\"CodeMirror-linenumbers\")if(i)l=!0;else continue;a.push({className:m,style:y})}return i&&!l&&a.push({className:\"CodeMirror-linenumbers\",style:null}),a}function Hg(n){var i=n.gutters,a=n.gutterSpecs;O(i),n.lineGutter=null;for(var l=0;l<a.length;++l){var u=a[l],m=u.className,y=u.style,x=i.appendChild(k(\"div\",null,\"CodeMirror-gutter \"+m));y&&(x.style.cssText=y),m==\"CodeMirror-linenumbers\"&&(n.lineGutter=x,x.style.width=(n.lineNumWidth||1)+\"px\")}i.style.display=a.length?\"\":\"none\",jf(n)}function kl(n){Hg(n.display),_n(n),zg(n)}function Fk(n,i,a,l){var u=this;this.input=a,u.scrollbarFiller=k(\"div\",null,\"CodeMirror-scrollbar-filler\"),u.scrollbarFiller.setAttribute(\"cm-not-content\",\"true\"),u.gutterFiller=k(\"div\",null,\"CodeMirror-gutter-filler\"),u.gutterFiller.setAttribute(\"cm-not-content\",\"true\"),u.lineDiv=z(\"div\",null,\"CodeMirror-code\"),u.selectionDiv=k(\"div\",null,null,\"position: relative; z-index: 1\"),u.cursorDiv=k(\"div\",null,\"CodeMirror-cursors\"),u.measure=k(\"div\",null,\"CodeMirror-measure\"),u.lineMeasure=k(\"div\",null,\"CodeMirror-measure\"),u.lineSpace=z(\"div\",[u.measure,u.lineMeasure,u.selectionDiv,u.cursorDiv,u.lineDiv],null,\"position: relative; outline: none\");var m=z(\"div\",[u.lineSpace],\"CodeMirror-lines\");u.mover=k(\"div\",[m],null,\"position: relative\"),u.sizer=k(\"div\",[u.mover],\"CodeMirror-sizer\"),u.sizerWidth=null,u.heightForcer=k(\"div\",null,null,\"position: absolute; height: \"+D+\"px; width: 1px;\"),u.gutters=k(\"div\",null,\"CodeMirror-gutters\"),u.lineGutter=null,u.scroller=k(\"div\",[u.sizer,u.heightForcer,u.gutters],\"CodeMirror-scroll\"),u.scroller.setAttribute(\"tabIndex\",\"-1\"),u.wrapper=k(\"div\",[u.scrollbarFiller,u.gutterFiller,u.scroller],\"CodeMirror\"),b&&w>=105&&(u.wrapper.style.clipPath=\"inset(0px)\"),u.wrapper.setAttribute(\"translate\",\"no\"),h&&p<8&&(u.gutters.style.zIndex=-1,u.scroller.style.paddingRight=0),!g&&!(s&&_)&&(u.scroller.draggable=!0),n&&(n.appendChild?n.appendChild(u.wrapper):n(u.wrapper)),u.viewFrom=u.viewTo=i.first,u.reportedViewFrom=u.reportedViewTo=i.first,u.view=[],u.renderedView=null,u.externalMeasured=null,u.viewOffset=0,u.lastWrapHeight=u.lastWrapWidth=0,u.updateLineNumbers=null,u.nativeBarWidth=u.barHeight=u.barWidth=0,u.scrollbarsClipped=!1,u.lineNumWidth=u.lineNumInnerWidth=u.lineNumChars=null,u.alignWidgets=!1,u.cachedCharWidth=u.cachedTextHeight=u.cachedPaddingH=null,u.maxLine=null,u.maxLineLength=0,u.maxLineChanged=!1,u.wheelDX=u.wheelDY=u.wheelStartX=u.wheelStartY=null,u.shift=!1,u.selForContextMenu=null,u.activeTouch=null,u.gutterSpecs=Vf(l.gutters,l.lineNumbers),Hg(u),a.init(u)}var fc=0,ai=null;h?ai=-.53:s?ai=15:b?ai=-.7:L&&(ai=-1/3);function Bg(n){var i=n.wheelDeltaX,a=n.wheelDeltaY;return i==null&&n.detail&&n.axis==n.HORIZONTAL_AXIS&&(i=n.detail),a==null&&n.detail&&n.axis==n.VERTICAL_AXIS?a=n.detail:a==null&&(a=n.wheelDelta),{x:i,y:a}}function Hk(n){var i=Bg(n);return i.x*=ai,i.y*=ai,i}function Wg(n,i){b&&w==102&&(n.display.chromeScrollHack==null?n.display.sizer.style.pointerEvents=\"none\":clearTimeout(n.display.chromeScrollHack),n.display.chromeScrollHack=setTimeout(function(){n.display.chromeScrollHack=null,n.display.sizer.style.pointerEvents=\"\"},100));var a=Bg(i),l=a.x,u=a.y,m=ai;i.deltaMode===0&&(l=i.deltaX,u=i.deltaY,m=1);var y=n.display,x=y.scroller,S=x.scrollWidth>x.clientWidth,T=x.scrollHeight>x.clientHeight;if(l&&S||u&&T){if(u&&$&&g){e:for(var H=i.target,V=y.view;H!=x;H=H.parentNode)for(var se=0;se<V.length;se++)if(V[se].node==H){n.display.currentWheelTarget=H;break e}}if(l&&!s&&!E&&m!=null){u&&T&&yl(n,Math.max(0,x.scrollTop+u*m)),_o(n,Math.max(0,x.scrollLeft+l*m)),(!u||u&&T)&&cn(i),y.wheelStartX=null;return}if(u&&m!=null){var te=u*m,pe=n.doc.scrollTop,we=pe+y.wrapper.clientHeight;te<0?pe=Math.max(0,pe+te-50):we=Math.min(n.doc.height,we+te+50),qf(n,{top:pe,bottom:we})}fc<20&&i.deltaMode!==0&&(y.wheelStartX==null?(y.wheelStartX=x.scrollLeft,y.wheelStartY=x.scrollTop,y.wheelDX=l,y.wheelDY=u,setTimeout(function(){if(y.wheelStartX!=null){var Te=x.scrollLeft-y.wheelStartX,Le=x.scrollTop-y.wheelStartY,De=Le&&y.wheelDY&&Le/y.wheelDY||Te&&y.wheelDX&&Te/y.wheelDX;y.wheelStartX=y.wheelStartY=null,De&&(ai=(ai*fc+De)/(fc+1),++fc)}},200)):(y.wheelDX+=l,y.wheelDY+=u))}}var er=function(n,i){this.ranges=n,this.primIndex=i};er.prototype.primary=function(){return this.ranges[this.primIndex]},er.prototype.equals=function(n){if(n==this)return!0;if(n.primIndex!=this.primIndex||n.ranges.length!=this.ranges.length)return!1;for(var i=0;i<this.ranges.length;i++){var a=this.ranges[i],l=n.ranges[i];if(!pt(a.anchor,l.anchor)||!pt(a.head,l.head))return!1}return!0},er.prototype.deepCopy=function(){for(var n=[],i=0;i<this.ranges.length;i++)n[i]=new gt(Zt(this.ranges[i].anchor),Zt(this.ranges[i].head));return new er(n,this.primIndex)},er.prototype.somethingSelected=function(){for(var n=0;n<this.ranges.length;n++)if(!this.ranges[n].empty())return!0;return!1},er.prototype.contains=function(n,i){i||(i=n);for(var a=0;a<this.ranges.length;a++){var l=this.ranges[a];if(Ie(i,l.from())>=0&&Ie(n,l.to())<=0)return a}return-1};var gt=function(n,i){this.anchor=n,this.head=i};gt.prototype.from=function(){return is(this.anchor,this.head)},gt.prototype.to=function(){return Sn(this.anchor,this.head)},gt.prototype.empty=function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch};function Tr(n,i,a){var l=n&&n.options.selectionsMayTouch,u=i[a];i.sort(function(se,te){return Ie(se.from(),te.from())}),a=ae(i,u);for(var m=1;m<i.length;m++){var y=i[m],x=i[m-1],S=Ie(x.to(),y.from());if(l&&!y.empty()?S>0:S>=0){var T=is(x.from(),y.from()),H=Sn(x.to(),y.to()),V=x.empty()?y.from()==y.head:x.from()==x.head;m<=a&&--a,i.splice(--m,2,new gt(V?H:T,V?T:H))}}return new er(i,a)}function Fi(n,i){return new er([new gt(n,i||n)],0)}function Hi(n){return n.text?fe(n.from.line+n.text.length-1,xe(n.text).length+(n.text.length==1?n.from.ch:0)):n.to}function qg(n,i){if(Ie(n,i.from)<0)return n;if(Ie(n,i.to)<=0)return Hi(i);var a=n.line+i.text.length-(i.to.line-i.from.line)-1,l=n.ch;return n.line==i.to.line&&(l+=Hi(i).ch-i.to.ch),fe(a,l)}function Gf(n,i){for(var a=[],l=0;l<n.sel.ranges.length;l++){var u=n.sel.ranges[l];a.push(new gt(qg(u.anchor,i),qg(u.head,i)))}return Tr(n.cm,a,n.sel.primIndex)}function jg(n,i,a){return n.line==i.line?fe(a.line,n.ch-i.ch+a.ch):fe(a.line+(n.line-i.line),n.ch)}function Bk(n,i,a){for(var l=[],u=fe(n.first,0),m=u,y=0;y<i.length;y++){var x=i[y],S=jg(x.from,u,m),T=jg(Hi(x),u,m);if(u=x.to,m=T,a==\"around\"){var H=n.sel.ranges[y],V=Ie(H.head,H.anchor)<0;l[y]=new gt(V?T:S,V?S:T)}else l[y]=new gt(S,S)}return new er(l,n.sel.primIndex)}function Kf(n){n.doc.mode=ts(n.options,n.doc.modeOption),Sl(n)}function Sl(n){n.doc.iter(function(i){i.stateAfter&&(i.stateAfter=null),i.styles&&(i.styles=null)}),n.doc.modeFrontier=n.doc.highlightFrontier=n.doc.first,xl(n,100),n.state.modeGen++,n.curOp&&_n(n)}function Ug(n,i){return i.from.ch==0&&i.to.ch==0&&xe(i.text)==\"\"&&(!n.cm||n.cm.options.wholeLineUpdateBefore)}function Xf(n,i,a,l){function u(De){return a?a[De]:null}function m(De,Me,ze){X1(De,Me,ze,l),Jt(De,\"change\",De,i)}function y(De,Me){for(var ze=[],Ye=De;Ye<Me;++Ye)ze.push(new os(T[Ye],u(Ye),l));return ze}var x=i.from,S=i.to,T=i.text,H=qe(n,x.line),V=qe(n,S.line),se=xe(T),te=u(T.length-1),pe=S.line-x.line;if(i.full)n.insert(0,y(0,T.length)),n.remove(T.length,n.size-T.length);else if(Ug(n,i)){var we=y(0,T.length-1);m(V,V.text,te),pe&&n.remove(x.line,pe),we.length&&n.insert(x.line,we)}else if(H==V)if(T.length==1)m(H,H.text.slice(0,x.ch)+se+H.text.slice(S.ch),te);else{var Te=y(1,T.length-1);Te.push(new os(se+H.text.slice(S.ch),te,l)),m(H,H.text.slice(0,x.ch)+T[0],u(0)),n.insert(x.line+1,Te)}else if(T.length==1)m(H,H.text.slice(0,x.ch)+T[0]+V.text.slice(S.ch),u(0)),n.remove(x.line+1,pe);else{m(H,H.text.slice(0,x.ch)+T[0],u(0)),m(V,se+V.text.slice(S.ch),te);var Le=y(1,T.length-1);pe>1&&n.remove(x.line+1,pe-1),n.insert(x.line+1,Le)}Jt(n,\"change\",n,i)}function Bi(n,i,a){function l(u,m,y){if(u.linked)for(var x=0;x<u.linked.length;++x){var S=u.linked[x];if(S.doc!=m){var T=y&&S.sharedHist;a&&!T||(i(S.doc,T),l(S.doc,u,T))}}}l(n,null,!0)}function Vg(n,i){if(i.cm)throw new Error(\"This document is already in use.\");n.doc=i,i.cm=n,$f(n),Kf(n),Gg(n),n.options.direction=i.direction,n.options.lineWrapping||_f(n),n.options.mode=i.modeOption,_n(n)}function Gg(n){(n.doc.direction==\"rtl\"?Se:N)(n.display.lineDiv,\"CodeMirror-rtl\")}function Wk(n){Wn(n,function(){Gg(n),_n(n)})}function dc(n){this.done=[],this.undone=[],this.undoDepth=n?n.undoDepth:1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=n?n.maxGeneration:1}function Yf(n,i){var a={from:Zt(i.from),to:Hi(i),text:ii(n,i.from,i.to)};return Yg(n,a,i.from.line,i.to.line+1),Bi(n,function(l){return Yg(l,a,i.from.line,i.to.line+1)},!0),a}function Kg(n){for(;n.length;){var i=xe(n);if(i.ranges)n.pop();else break}}function qk(n,i){if(i)return Kg(n.done),xe(n.done);if(n.done.length&&!xe(n.done).ranges)return xe(n.done);if(n.done.length>1&&!n.done[n.done.length-2].ranges)return n.done.pop(),xe(n.done)}function Xg(n,i,a,l){var u=n.history;u.undone.length=0;var m=+new Date,y,x;if((u.lastOp==l||u.lastOrigin==i.origin&&i.origin&&(i.origin.charAt(0)==\"+\"&&u.lastModTime>m-(n.cm?n.cm.options.historyEventDelay:500)||i.origin.charAt(0)==\"*\"))&&(y=qk(u,u.lastOp==l)))x=xe(y.changes),Ie(i.from,i.to)==0&&Ie(i.from,x.to)==0?x.to=Hi(i):y.changes.push(Yf(n,i));else{var S=xe(u.done);for((!S||!S.ranges)&&hc(n.sel,u.done),y={changes:[Yf(n,i)],generation:u.generation},u.done.push(y);u.done.length>u.undoDepth;)u.done.shift(),u.done[0].ranges||u.done.shift()}u.done.push(a),u.generation=++u.maxGeneration,u.lastModTime=u.lastSelTime=m,u.lastOp=u.lastSelOp=l,u.lastOrigin=u.lastSelOrigin=i.origin,x||Pt(n,\"historyAdded\")}function jk(n,i,a,l){var u=i.charAt(0);return u==\"*\"||u==\"+\"&&a.ranges.length==l.ranges.length&&a.somethingSelected()==l.somethingSelected()&&new Date-n.history.lastSelTime<=(n.cm?n.cm.options.historyEventDelay:500)}function Uk(n,i,a,l){var u=n.history,m=l&&l.origin;a==u.lastSelOp||m&&u.lastSelOrigin==m&&(u.lastModTime==u.lastSelTime&&u.lastOrigin==m||jk(n,m,xe(u.done),i))?u.done[u.done.length-1]=i:hc(i,u.done),u.lastSelTime=+new Date,u.lastSelOrigin=m,u.lastSelOp=a,l&&l.clearRedo!==!1&&Kg(u.undone)}function hc(n,i){var a=xe(i);a&&a.ranges&&a.equals(n)||i.push(n)}function Yg(n,i,a,l){var u=i[\"spans_\"+n.id],m=0;n.iter(Math.max(n.first,a),Math.min(n.first+n.size,l),function(y){y.markedSpans&&((u||(u=i[\"spans_\"+n.id]={}))[m]=y.markedSpans),++m})}function Vk(n){if(!n)return null;for(var i,a=0;a<n.length;++a)n[a].marker.explicitlyCleared?i||(i=n.slice(0,a)):i&&i.push(n[a]);return i?i.length?i:null:n}function Gk(n,i){var a=i[\"spans_\"+n.id];if(!a)return null;for(var l=[],u=0;u<i.text.length;++u)l.push(Vk(a[u]));return l}function Zg(n,i){var a=Gk(n,i),l=wf(n,i);if(!a)return l;if(!l)return a;for(var u=0;u<a.length;++u){var m=a[u],y=l[u];if(m&&y)e:for(var x=0;x<y.length;++x){for(var S=y[x],T=0;T<m.length;++T)if(m[T].marker==S.marker)continue e;m.push(S)}else y&&(a[u]=y)}return a}function hs(n,i,a){for(var l=[],u=0;u<n.length;++u){var m=n[u];if(m.ranges){l.push(a?er.prototype.deepCopy.call(m):m);continue}var y=m.changes,x=[];l.push({changes:x});for(var S=0;S<y.length;++S){var T=y[S],H=void 0;if(x.push({from:T.from,to:T.to,text:T.text}),i)for(var V in T)(H=V.match(/^spans_(\\d+)$/))&&ae(i,Number(H[1]))>-1&&(xe(x)[V]=T[V],delete T[V])}}return l}function Zf(n,i,a,l){if(l){var u=n.anchor;if(a){var m=Ie(i,u)<0;m!=Ie(a,u)<0?(u=i,i=a):m!=Ie(i,a)<0&&(i=a)}return new gt(u,i)}else return new gt(a||i,i)}function pc(n,i,a,l,u){u==null&&(u=n.cm&&(n.cm.display.shift||n.extend)),un(n,new er([Zf(n.sel.primary(),i,a,u)],0),l)}function Jg(n,i,a){for(var l=[],u=n.cm&&(n.cm.display.shift||n.extend),m=0;m<n.sel.ranges.length;m++)l[m]=Zf(n.sel.ranges[m],i[m],null,u);var y=Tr(n.cm,l,n.sel.primIndex);un(n,y,a)}function Jf(n,i,a,l){var u=n.sel.ranges.slice(0);u[i]=a,un(n,Tr(n.cm,u,n.sel.primIndex),l)}function Qg(n,i,a,l){un(n,Fi(i,a),l)}function Kk(n,i,a){var l={ranges:i.ranges,update:function(u){this.ranges=[];for(var m=0;m<u.length;m++)this.ranges[m]=new gt(tt(n,u[m].anchor),tt(n,u[m].head))},origin:a&&a.origin};return Pt(n,\"beforeSelectionChange\",n,l),n.cm&&Pt(n.cm,\"beforeSelectionChange\",n.cm,l),l.ranges!=i.ranges?Tr(n.cm,l.ranges,l.ranges.length-1):i}function em(n,i,a){var l=n.history.done,u=xe(l);u&&u.ranges?(l[l.length-1]=i,gc(n,i,a)):un(n,i,a)}function un(n,i,a){gc(n,i,a),Uk(n,n.sel,n.cm?n.cm.curOp.id:NaN,a)}function gc(n,i,a){(Bn(n,\"beforeSelectionChange\")||n.cm&&Bn(n.cm,\"beforeSelectionChange\"))&&(i=Kk(n,i,a));var l=a&&a.bias||(Ie(i.primary().head,n.sel.primary().head)<0?-1:1);tm(n,rm(n,i,l,!0)),!(a&&a.scroll===!1)&&n.cm&&n.cm.getOption(\"readOnly\")!=\"nocursor\"&&fs(n.cm)}function tm(n,i){i.equals(n.sel)||(n.sel=i,n.cm&&(n.cm.curOp.updateInput=1,n.cm.curOp.selectionChanged=!0,ar(n.cm)),Jt(n,\"cursorActivity\",n))}function nm(n){tm(n,rm(n,n.sel,null,!1))}function rm(n,i,a,l){for(var u,m=0;m<i.ranges.length;m++){var y=i.ranges[m],x=i.ranges.length==n.sel.ranges.length&&n.sel.ranges[m],S=mc(n,y.anchor,x&&x.anchor,a,l),T=y.head==y.anchor?S:mc(n,y.head,x&&x.head,a,l);(u||S!=y.anchor||T!=y.head)&&(u||(u=i.ranges.slice(0,m)),u[m]=new gt(S,T))}return u?Tr(n.cm,u,i.primIndex):i}function ps(n,i,a,l,u){var m=qe(n,i.line);if(m.markedSpans)for(var y=0;y<m.markedSpans.length;++y){var x=m.markedSpans[y],S=x.marker,T=\"selectLeft\"in S?!S.selectLeft:S.inclusiveLeft,H=\"selectRight\"in S?!S.selectRight:S.inclusiveRight;if((x.from==null||(T?x.from<=i.ch:x.from<i.ch))&&(x.to==null||(H?x.to>=i.ch:x.to>i.ch))){if(u&&(Pt(S,\"beforeCursorEnter\"),S.explicitlyCleared))if(m.markedSpans){--y;continue}else break;if(!S.atomic)continue;if(a){var V=S.find(l<0?1:-1),se=void 0;if((l<0?H:T)&&(V=im(n,V,-l,V&&V.line==i.line?m:null)),V&&V.line==i.line&&(se=Ie(V,a))&&(l<0?se<0:se>0))return ps(n,V,i,l,u)}var te=S.find(l<0?-1:1);return(l<0?T:H)&&(te=im(n,te,l,te.line==i.line?m:null)),te?ps(n,te,i,l,u):null}}return i}function mc(n,i,a,l,u){var m=l||1,y=ps(n,i,a,m,u)||!u&&ps(n,i,a,m,!0)||ps(n,i,a,-m,u)||!u&&ps(n,i,a,-m,!0);return y||(n.cantEdit=!0,fe(n.first,0))}function im(n,i,a,l){return a<0&&i.ch==0?i.line>n.first?tt(n,fe(i.line-1)):null:a>0&&i.ch==(l||qe(n,i.line)).text.length?i.line<n.first+n.size-1?fe(i.line+1,0):null:new fe(i.line,i.ch+a)}function om(n){n.setSelection(fe(n.firstLine(),0),fe(n.lastLine()),Q)}function sm(n,i,a){var l={canceled:!1,from:i.from,to:i.to,text:i.text,origin:i.origin,cancel:function(){return l.canceled=!0}};return a&&(l.update=function(u,m,y,x){u&&(l.from=tt(n,u)),m&&(l.to=tt(n,m)),y&&(l.text=y),x!==void 0&&(l.origin=x)}),Pt(n,\"beforeChange\",n,l),n.cm&&Pt(n.cm,\"beforeChange\",n.cm,l),l.canceled?(n.cm&&(n.cm.curOp.updateInput=2),null):{from:l.from,to:l.to,text:l.text,origin:l.origin}}function gs(n,i,a){if(n.cm){if(!n.cm.curOp)return Qt(n.cm,gs)(n,i,a);if(n.cm.state.suppressEdits)return}if(!((Bn(n,\"beforeChange\")||n.cm&&Bn(n.cm,\"beforeChange\"))&&(i=sm(n,i,!0),!i))){var l=Zp&&!a&&U1(n,i.from,i.to);if(l)for(var u=l.length-1;u>=0;--u)lm(n,{from:l[u].from,to:l[u].to,text:u?[\"\"]:i.text,origin:i.origin});else lm(n,i)}}function lm(n,i){if(!(i.text.length==1&&i.text[0]==\"\"&&Ie(i.from,i.to)==0)){var a=Gf(n,i);Xg(n,i,a,n.cm?n.cm.curOp.id:NaN),_l(n,i,a,wf(n,i));var l=[];Bi(n,function(u,m){!m&&ae(l,u.history)==-1&&(fm(u.history,i),l.push(u.history)),_l(u,i,null,wf(u,i))})}}function vc(n,i,a){var l=n.cm&&n.cm.state.suppressEdits;if(!(l&&!a)){for(var u=n.history,m,y=n.sel,x=i==\"undo\"?u.done:u.undone,S=i==\"undo\"?u.undone:u.done,T=0;T<x.length&&(m=x[T],!(a?m.ranges&&!m.equals(n.sel):!m.ranges));T++);if(T!=x.length){for(u.lastOrigin=u.lastSelOrigin=null;;)if(m=x.pop(),m.ranges){if(hc(m,S),a&&!m.equals(n.sel)){un(n,m,{clearRedo:!1});return}y=m}else if(l){x.push(m);return}else break;var H=[];hc(y,S),S.push({changes:H,generation:u.generation}),u.generation=m.generation||++u.maxGeneration;for(var V=Bn(n,\"beforeChange\")||n.cm&&Bn(n.cm,\"beforeChange\"),se=function(we){var Te=m.changes[we];if(Te.origin=i,V&&!sm(n,Te,!1))return x.length=0,{};H.push(Yf(n,Te));var Le=we?Gf(n,Te):xe(x);_l(n,Te,Le,Zg(n,Te)),!we&&n.cm&&n.cm.scrollIntoView({from:Te.from,to:Hi(Te)});var De=[];Bi(n,function(Me,ze){!ze&&ae(De,Me.history)==-1&&(fm(Me.history,Te),De.push(Me.history)),_l(Me,Te,null,Zg(Me,Te))})},te=m.changes.length-1;te>=0;--te){var pe=se(te);if(pe)return pe.v}}}}function am(n,i){if(i!=0&&(n.first+=i,n.sel=new er(ye(n.sel.ranges,function(u){return new gt(fe(u.anchor.line+i,u.anchor.ch),fe(u.head.line+i,u.head.ch))}),n.sel.primIndex),n.cm)){_n(n.cm,n.first,n.first-i,i);for(var a=n.cm.display,l=a.viewFrom;l<a.viewTo;l++)Di(n.cm,l,\"gutter\")}}function _l(n,i,a,l){if(n.cm&&!n.cm.curOp)return Qt(n.cm,_l)(n,i,a,l);if(i.to.line<n.first){am(n,i.text.length-1-(i.to.line-i.from.line));return}if(!(i.from.line>n.lastLine())){if(i.from.line<n.first){var u=i.text.length-1-(n.first-i.from.line);am(n,u),i={from:fe(n.first,0),to:fe(i.to.line+u,i.to.ch),text:[xe(i.text)],origin:i.origin}}var m=n.lastLine();i.to.line>m&&(i={from:i.from,to:fe(m,qe(n,m).text.length),text:[i.text[0]],origin:i.origin}),i.removed=ii(n,i.from,i.to),a||(a=Gf(n,i)),n.cm?Xk(n.cm,i,l):Xf(n,i,l),gc(n,a,Q),n.cantEdit&&mc(n,fe(n.firstLine(),0))&&(n.cantEdit=!1)}}function Xk(n,i,a){var l=n.doc,u=n.display,m=i.from,y=i.to,x=!1,S=m.line;n.options.lineWrapping||(S=A(Sr(qe(l,m.line))),l.iter(S,y.line+1,function(te){if(te==u.maxLine)return x=!0,!0})),l.sel.contains(i.from,i.to)>-1&&ar(n),Xf(l,i,a,Eg(n)),n.options.lineWrapping||(l.iter(S,m.line+i.text.length,function(te){var pe=ec(te);pe>u.maxLineLength&&(u.maxLine=te,u.maxLineLength=pe,u.maxLineChanged=!0,x=!1)}),x&&(n.curOp.updateMaxLine=!0)),z1(l,m.line),xl(n,400);var T=i.text.length-(y.line-m.line)-1;i.full?_n(n):m.line==y.line&&i.text.length==1&&!Ug(n.doc,i)?Di(n,m.line,\"text\"):_n(n,m.line,y.line+1,T);var H=Bn(n,\"changes\"),V=Bn(n,\"change\");if(V||H){var se={from:m,to:y,text:i.text,removed:i.removed,origin:i.origin};V&&Jt(n,\"change\",n,se),H&&(n.curOp.changeObjs||(n.curOp.changeObjs=[])).push(se)}n.display.selForContextMenu=null}function ms(n,i,a,l,u){var m;l||(l=a),Ie(l,a)<0&&(m=[l,a],a=m[0],l=m[1]),typeof i==\"string\"&&(i=n.splitLines(i)),gs(n,{from:a,to:l,text:i,origin:u})}function cm(n,i,a,l){a<n.line?n.line+=l:i<n.line&&(n.line=i,n.ch=0)}function um(n,i,a,l){for(var u=0;u<n.length;++u){var m=n[u],y=!0;if(m.ranges){m.copied||(m=n[u]=m.deepCopy(),m.copied=!0);for(var x=0;x<m.ranges.length;x++)cm(m.ranges[x].anchor,i,a,l),cm(m.ranges[x].head,i,a,l);continue}for(var S=0;S<m.changes.length;++S){var T=m.changes[S];if(a<T.from.line)T.from=fe(T.from.line+l,T.from.ch),T.to=fe(T.to.line+l,T.to.ch);else if(i<=T.to.line){y=!1;break}}y||(n.splice(0,u+1),u=0)}}function fm(n,i){var a=i.from.line,l=i.to.line,u=i.text.length-(l-a)-1;um(n.done,a,l,u),um(n.undone,a,l,u)}function Tl(n,i,a,l){var u=i,m=i;return typeof i==\"number\"?m=qe(n,Wp(n,i)):u=A(i),u==null?null:(l(m,u)&&n.cm&&Di(n.cm,u,a),m)}function Cl(n){this.lines=n,this.parent=null;for(var i=0,a=0;a<n.length;++a)n[a].parent=this,i+=n[a].height;this.height=i}Cl.prototype={chunkSize:function(){return this.lines.length},removeInner:function(n,i){for(var a=n,l=n+i;a<l;++a){var u=this.lines[a];this.height-=u.height,Y1(u),Jt(u,\"delete\")}this.lines.splice(n,i)},collapse:function(n){n.push.apply(n,this.lines)},insertInner:function(n,i,a){this.height+=a,this.lines=this.lines.slice(0,n).concat(i).concat(this.lines.slice(n));for(var l=0;l<i.length;++l)i[l].parent=this},iterN:function(n,i,a){for(var l=n+i;n<l;++n)if(a(this.lines[n]))return!0}};function El(n){this.children=n;for(var i=0,a=0,l=0;l<n.length;++l){var u=n[l];i+=u.chunkSize(),a+=u.height,u.parent=this}this.size=i,this.height=a,this.parent=null}El.prototype={chunkSize:function(){return this.size},removeInner:function(n,i){this.size-=i;for(var a=0;a<this.children.length;++a){var l=this.children[a],u=l.chunkSize();if(n<u){var m=Math.min(i,u-n),y=l.height;if(l.removeInner(n,m),this.height-=y-l.height,u==m&&(this.children.splice(a--,1),l.parent=null),(i-=m)==0)break;n=0}else n-=u}if(this.size-i<25&&(this.children.length>1||!(this.children[0]instanceof Cl))){var x=[];this.collapse(x),this.children=[new Cl(x)],this.children[0].parent=this}},collapse:function(n){for(var i=0;i<this.children.length;++i)this.children[i].collapse(n)},insertInner:function(n,i,a){this.size+=i.length,this.height+=a;for(var l=0;l<this.children.length;++l){var u=this.children[l],m=u.chunkSize();if(n<=m){if(u.insertInner(n,i,a),u.lines&&u.lines.length>50){for(var y=u.lines.length%25+25,x=y;x<u.lines.length;){var S=new Cl(u.lines.slice(x,x+=25));u.height-=S.height,this.children.splice(++l,0,S),S.parent=this}u.lines=u.lines.slice(0,y),this.maybeSpill()}break}n-=m}},maybeSpill:function(){if(!(this.children.length<=10)){var n=this;do{var i=n.children.splice(n.children.length-5,5),a=new El(i);if(n.parent){n.size-=a.size,n.height-=a.height;var u=ae(n.parent.children,n);n.parent.children.splice(u+1,0,a)}else{var l=new El(n.children);l.parent=n,n.children=[l,a],n=l}a.parent=n.parent}while(n.children.length>10);n.parent.maybeSpill()}},iterN:function(n,i,a){for(var l=0;l<this.children.length;++l){var u=this.children[l],m=u.chunkSize();if(n<m){var y=Math.min(i,m-n);if(u.iterN(n,y,a))return!0;if((i-=y)==0)break;n=0}else n-=m}}};var Al=function(n,i,a){if(a)for(var l in a)a.hasOwnProperty(l)&&(this[l]=a[l]);this.doc=n,this.node=i};Al.prototype.clear=function(){var n=this.doc.cm,i=this.line.widgets,a=this.line,l=A(a);if(!(l==null||!i)){for(var u=0;u<i.length;++u)i[u]==this&&i.splice(u--,1);i.length||(a.widgets=null);var m=pl(this);Qn(a,Math.max(0,a.height-m)),n&&(Wn(n,function(){dm(n,a,-m),Di(n,l,\"widget\")}),Jt(n,\"lineWidgetCleared\",n,this,l))}},Al.prototype.changed=function(){var n=this,i=this.height,a=this.doc.cm,l=this.line;this.height=null;var u=pl(this)-i;u&&(Ii(this.doc,l)||Qn(l,l.height+u),a&&Wn(a,function(){a.curOp.forceUpdate=!0,dm(a,l,u),Jt(a,\"lineWidgetChanged\",a,n,A(l))}))},yr(Al);function dm(n,i,a){si(i)<(n.curOp&&n.curOp.scrollTop||n.doc.scrollTop)&&Bf(n,a)}function Yk(n,i,a,l){var u=new Al(n,a,l),m=n.cm;return m&&u.noHScroll&&(m.display.alignWidgets=!0),Tl(n,i,\"widget\",function(y){var x=y.widgets||(y.widgets=[]);if(u.insertAt==null?x.push(u):x.splice(Math.min(x.length,Math.max(0,u.insertAt)),0,u),u.line=y,m&&!Ii(n,y)){var S=si(y)<n.scrollTop;Qn(y,y.height+pl(u)),S&&Bf(m,u.height),m.curOp.forceUpdate=!0}return!0}),m&&Jt(m,\"lineWidgetAdded\",m,u,typeof i==\"number\"?i:A(i)),u}var hm=0,Wi=function(n,i){this.lines=[],this.type=i,this.doc=n,this.id=++hm};Wi.prototype.clear=function(){if(!this.explicitlyCleared){var n=this.doc.cm,i=n&&!n.curOp;if(i&&Co(n),Bn(this,\"clear\")){var a=this.find();a&&Jt(this,\"clear\",a.from,a.to)}for(var l=null,u=null,m=0;m<this.lines.length;++m){var y=this.lines[m],x=fl(y.markedSpans,this);n&&!this.collapsed?Di(n,A(y),\"text\"):n&&(x.to!=null&&(u=A(y)),x.from!=null&&(l=A(y))),y.markedSpans=B1(y.markedSpans,x),x.from==null&&this.collapsed&&!Ii(this.doc,y)&&n&&Qn(y,as(n.display))}if(n&&this.collapsed&&!n.options.lineWrapping)for(var S=0;S<this.lines.length;++S){var T=Sr(this.lines[S]),H=ec(T);H>n.display.maxLineLength&&(n.display.maxLine=T,n.display.maxLineLength=H,n.display.maxLineChanged=!0)}l!=null&&n&&this.collapsed&&_n(n,l,u+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,n&&nm(n.doc)),n&&Jt(n,\"markerCleared\",n,this,l,u),i&&Eo(n),this.parent&&this.parent.clear()}},Wi.prototype.find=function(n,i){n==null&&this.type==\"bookmark\"&&(n=1);for(var a,l,u=0;u<this.lines.length;++u){var m=this.lines[u],y=fl(m.markedSpans,this);if(y.from!=null&&(a=fe(i?m:A(m),y.from),n==-1))return a;if(y.to!=null&&(l=fe(i?m:A(m),y.to),n==1))return l}return a&&{from:a,to:l}},Wi.prototype.changed=function(){var n=this,i=this.find(-1,!0),a=this,l=this.doc.cm;!i||!l||Wn(l,function(){var u=i.line,m=A(i.line),y=Af(l,m);if(y&&(bg(y),l.curOp.selectionChanged=l.curOp.forceUpdate=!0),l.curOp.updateMaxLine=!0,!Ii(a.doc,u)&&a.height!=null){var x=a.height;a.height=null;var S=pl(a)-x;S&&Qn(u,u.height+S)}Jt(l,\"markerChanged\",l,n)})},Wi.prototype.attachLine=function(n){if(!this.lines.length&&this.doc.cm){var i=this.doc.cm.curOp;(!i.maybeHiddenMarkers||ae(i.maybeHiddenMarkers,this)==-1)&&(i.maybeUnhiddenMarkers||(i.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(n)},Wi.prototype.detachLine=function(n){if(this.lines.splice(ae(this.lines,n),1),!this.lines.length&&this.doc.cm){var i=this.doc.cm.curOp;(i.maybeHiddenMarkers||(i.maybeHiddenMarkers=[])).push(this)}},yr(Wi);function vs(n,i,a,l,u){if(l&&l.shared)return Zk(n,i,a,l,u);if(n.cm&&!n.cm.curOp)return Qt(n.cm,vs)(n,i,a,l,u);var m=new Wi(n,u),y=Ie(i,a);if(l&&Y(l,m,!1),y>0||y==0&&m.clearWhenEmpty!==!1)return m;if(m.replacedWith&&(m.collapsed=!0,m.widgetNode=z(\"span\",[m.replacedWith],\"CodeMirror-widget\"),l.handleMouseEvents||m.widgetNode.setAttribute(\"cm-ignore-events\",\"true\"),l.insertLeft&&(m.widgetNode.insertLeft=!0)),m.collapsed){if(rg(n,i.line,i,a,m)||i.line!=a.line&&rg(n,a.line,i,a,m))throw new Error(\"Inserting collapsed marker partially overlapping an existing one\");H1()}m.addToHistory&&Xg(n,{from:i,to:a,origin:\"markText\"},n.sel,NaN);var x=i.line,S=n.cm,T;if(n.iter(x,a.line+1,function(V){S&&m.collapsed&&!S.options.lineWrapping&&Sr(V)==S.display.maxLine&&(T=!0),m.collapsed&&x!=i.line&&Qn(V,0),W1(V,new Ya(m,x==i.line?i.ch:null,x==a.line?a.ch:null),n.cm&&n.cm.curOp),++x}),m.collapsed&&n.iter(i.line,a.line+1,function(V){Ii(n,V)&&Qn(V,0)}),m.clearOnEnter&&Xe(m,\"beforeCursorEnter\",function(){return m.clear()}),m.readOnly&&(F1(),(n.history.done.length||n.history.undone.length)&&n.clearHistory()),m.collapsed&&(m.id=++hm,m.atomic=!0),S){if(T&&(S.curOp.updateMaxLine=!0),m.collapsed)_n(S,i.line,a.line+1);else if(m.className||m.startStyle||m.endStyle||m.css||m.attributes||m.title)for(var H=i.line;H<=a.line;H++)Di(S,H,\"text\");m.atomic&&nm(S.doc),Jt(S,\"markerAdded\",S,m)}return m}var Ll=function(n,i){this.markers=n,this.primary=i;for(var a=0;a<n.length;++a)n[a].parent=this};Ll.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var n=0;n<this.markers.length;++n)this.markers[n].clear();Jt(this,\"clear\")}},Ll.prototype.find=function(n,i){return this.primary.find(n,i)},yr(Ll);function Zk(n,i,a,l,u){l=Y(l),l.shared=!1;var m=[vs(n,i,a,l,u)],y=m[0],x=l.widgetNode;return Bi(n,function(S){x&&(l.widgetNode=x.cloneNode(!0)),m.push(vs(S,tt(S,i),tt(S,a),l,u));for(var T=0;T<S.linked.length;++T)if(S.linked[T].isParent)return;y=xe(m)}),new Ll(m,y)}function pm(n){return n.findMarks(fe(n.first,0),n.clipPos(fe(n.lastLine())),function(i){return i.parent})}function Jk(n,i){for(var a=0;a<i.length;a++){var l=i[a],u=l.find(),m=n.clipPos(u.from),y=n.clipPos(u.to);if(Ie(m,y)){var x=vs(n,m,y,l.primary,l.primary.type);l.markers.push(x),x.parent=l}}}function Qk(n){for(var i=function(l){var u=n[l],m=[u.primary.doc];Bi(u.primary.doc,function(S){return m.push(S)});for(var y=0;y<u.markers.length;y++){var x=u.markers[y];ae(m,x.doc)==-1&&(x.parent=null,u.markers.splice(y--,1))}},a=0;a<n.length;a++)i(a)}var eS=0,Tn=function(n,i,a,l,u){if(!(this instanceof Tn))return new Tn(n,i,a,l,u);a==null&&(a=0),El.call(this,[new Cl([new os(\"\",null)])]),this.first=a,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1,this.modeFrontier=this.highlightFrontier=a;var m=fe(a,0);this.sel=Fi(m),this.history=new dc(null),this.id=++eS,this.modeOption=i,this.lineSep=l,this.direction=u==\"rtl\"?\"rtl\":\"ltr\",this.extend=!1,typeof n==\"string\"&&(n=this.splitLines(n)),Xf(this,{from:m,to:m,text:n}),un(this,Fi(m),Q)};Tn.prototype=oe(El.prototype,{constructor:Tn,iter:function(n,i,a){a?this.iterN(n-this.first,i-n,a):this.iterN(this.first,this.first+this.size,n)},insert:function(n,i){for(var a=0,l=0;l<i.length;++l)a+=i[l].height;this.insertInner(n-this.first,i,a)},remove:function(n,i){this.removeInner(n-this.first,i)},getValue:function(n){var i=cl(this,this.first,this.first+this.size);return n===!1?i:i.join(n||this.lineSeparator())},setValue:en(function(n){var i=fe(this.first,0),a=this.first+this.size-1;gs(this,{from:i,to:fe(a,qe(this,a).text.length),text:this.splitLines(n),origin:\"setValue\",full:!0},!0),this.cm&&vl(this.cm,0,0),un(this,Fi(i),Q)}),replaceRange:function(n,i,a,l){i=tt(this,i),a=a?tt(this,a):i,ms(this,n,i,a,l)},getRange:function(n,i,a){var l=ii(this,tt(this,n),tt(this,i));return a===!1?l:a===\"\"?l.join(\"\"):l.join(a||this.lineSeparator())},getLine:function(n){var i=this.getLineHandle(n);return i&&i.text},getLineHandle:function(n){if(me(this,n))return qe(this,n)},getLineNumber:function(n){return A(n)},getLineHandleVisualStart:function(n){return typeof n==\"number\"&&(n=qe(this,n)),Sr(n)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(n){return tt(this,n)},getCursor:function(n){var i=this.sel.primary(),a;return n==null||n==\"head\"?a=i.head:n==\"anchor\"?a=i.anchor:n==\"end\"||n==\"to\"||n===!1?a=i.to():a=i.from(),a},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:en(function(n,i,a){Qg(this,tt(this,typeof n==\"number\"?fe(n,i||0):n),null,a)}),setSelection:en(function(n,i,a){Qg(this,tt(this,n),tt(this,i||n),a)}),extendSelection:en(function(n,i,a){pc(this,tt(this,n),i&&tt(this,i),a)}),extendSelections:en(function(n,i){Jg(this,qp(this,n),i)}),extendSelectionsBy:en(function(n,i){var a=ye(this.sel.ranges,n);Jg(this,qp(this,a),i)}),setSelections:en(function(n,i,a){if(n.length){for(var l=[],u=0;u<n.length;u++)l[u]=new gt(tt(this,n[u].anchor),tt(this,n[u].head||n[u].anchor));i==null&&(i=Math.min(n.length-1,this.sel.primIndex)),un(this,Tr(this.cm,l,i),a)}}),addSelection:en(function(n,i,a){var l=this.sel.ranges.slice(0);l.push(new gt(tt(this,n),tt(this,i||n))),un(this,Tr(this.cm,l,l.length-1),a)}),getSelection:function(n){for(var i=this.sel.ranges,a,l=0;l<i.length;l++){var u=ii(this,i[l].from(),i[l].to());a=a?a.concat(u):u}return n===!1?a:a.join(n||this.lineSeparator())},getSelections:function(n){for(var i=[],a=this.sel.ranges,l=0;l<a.length;l++){var u=ii(this,a[l].from(),a[l].to());n!==!1&&(u=u.join(n||this.lineSeparator())),i[l]=u}return i},replaceSelection:function(n,i,a){for(var l=[],u=0;u<this.sel.ranges.length;u++)l[u]=n;this.replaceSelections(l,i,a||\"+input\")},replaceSelections:en(function(n,i,a){for(var l=[],u=this.sel,m=0;m<u.ranges.length;m++){var y=u.ranges[m];l[m]={from:y.from(),to:y.to(),text:this.splitLines(n[m]),origin:a}}for(var x=i&&i!=\"end\"&&Bk(this,l,i),S=l.length-1;S>=0;S--)gs(this,l[S]);x?em(this,x):this.cm&&fs(this.cm)}),undo:en(function(){vc(this,\"undo\")}),redo:en(function(){vc(this,\"redo\")}),undoSelection:en(function(){vc(this,\"undo\",!0)}),redoSelection:en(function(){vc(this,\"redo\",!0)}),setExtending:function(n){this.extend=n},getExtending:function(){return this.extend},historySize:function(){for(var n=this.history,i=0,a=0,l=0;l<n.done.length;l++)n.done[l].ranges||++i;for(var u=0;u<n.undone.length;u++)n.undone[u].ranges||++a;return{undo:i,redo:a}},clearHistory:function(){var n=this;this.history=new dc(this.history),Bi(this,function(i){return i.history=n.history},!0)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(n){return n&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(n){return this.history.generation==(n||this.cleanGeneration)},getHistory:function(){return{done:hs(this.history.done),undone:hs(this.history.undone)}},setHistory:function(n){var i=this.history=new dc(this.history);i.done=hs(n.done.slice(0),null,!0),i.undone=hs(n.undone.slice(0),null,!0)},setGutterMarker:en(function(n,i,a){return Tl(this,n,\"gutter\",function(l){var u=l.gutterMarkers||(l.gutterMarkers={});return u[i]=a,!a&&dt(u)&&(l.gutterMarkers=null),!0})}),clearGutter:en(function(n){var i=this;this.iter(function(a){a.gutterMarkers&&a.gutterMarkers[n]&&Tl(i,a,\"gutter\",function(){return a.gutterMarkers[n]=null,dt(a.gutterMarkers)&&(a.gutterMarkers=null),!0})})}),lineInfo:function(n){var i;if(typeof n==\"number\"){if(!me(this,n)||(i=n,n=qe(this,n),!n))return null}else if(i=A(n),i==null)return null;return{line:i,handle:n,text:n.text,gutterMarkers:n.gutterMarkers,textClass:n.textClass,bgClass:n.bgClass,wrapClass:n.wrapClass,widgets:n.widgets}},addLineClass:en(function(n,i,a){return Tl(this,n,i==\"gutter\"?\"gutter\":\"class\",function(l){var u=i==\"text\"?\"textClass\":i==\"background\"?\"bgClass\":i==\"gutter\"?\"gutterClass\":\"wrapClass\";if(!l[u])l[u]=a;else{if(j(a).test(l[u]))return!1;l[u]+=\" \"+a}return!0})}),removeLineClass:en(function(n,i,a){return Tl(this,n,i==\"gutter\"?\"gutter\":\"class\",function(l){var u=i==\"text\"?\"textClass\":i==\"background\"?\"bgClass\":i==\"gutter\"?\"gutterClass\":\"wrapClass\",m=l[u];if(m)if(a==null)l[u]=null;else{var y=m.match(j(a));if(!y)return!1;var x=y.index+y[0].length;l[u]=m.slice(0,y.index)+(!y.index||x==m.length?\"\":\" \")+m.slice(x)||null}else return!1;return!0})}),addLineWidget:en(function(n,i,a){return Yk(this,n,i,a)}),removeLineWidget:function(n){n.clear()},markText:function(n,i,a){return vs(this,tt(this,n),tt(this,i),a,a&&a.type||\"range\")},setBookmark:function(n,i){var a={replacedWith:i&&(i.nodeType==null?i.widget:i),insertLeft:i&&i.insertLeft,clearWhenEmpty:!1,shared:i&&i.shared,handleMouseEvents:i&&i.handleMouseEvents};return n=tt(this,n),vs(this,n,n,a,\"bookmark\")},findMarksAt:function(n){n=tt(this,n);var i=[],a=qe(this,n.line).markedSpans;if(a)for(var l=0;l<a.length;++l){var u=a[l];(u.from==null||u.from<=n.ch)&&(u.to==null||u.to>=n.ch)&&i.push(u.marker.parent||u.marker)}return i},findMarks:function(n,i,a){n=tt(this,n),i=tt(this,i);var l=[],u=n.line;return this.iter(n.line,i.line+1,function(m){var y=m.markedSpans;if(y)for(var x=0;x<y.length;x++){var S=y[x];!(S.to!=null&&u==n.line&&n.ch>=S.to||S.from==null&&u!=n.line||S.from!=null&&u==i.line&&S.from>=i.ch)&&(!a||a(S.marker))&&l.push(S.marker.parent||S.marker)}++u}),l},getAllMarks:function(){var n=[];return this.iter(function(i){var a=i.markedSpans;if(a)for(var l=0;l<a.length;++l)a[l].from!=null&&n.push(a[l].marker)}),n},posFromIndex:function(n){var i,a=this.first,l=this.lineSeparator().length;return this.iter(function(u){var m=u.text.length+l;if(m>n)return i=n,!0;n-=m,++a}),tt(this,fe(a,i))},indexFromPos:function(n){n=tt(this,n);var i=n.ch;if(n.line<this.first||n.ch<0)return 0;var a=this.lineSeparator().length;return this.iter(this.first,n.line,function(l){i+=l.text.length+a}),i},copy:function(n){var i=new Tn(cl(this,this.first,this.first+this.size),this.modeOption,this.first,this.lineSep,this.direction);return i.scrollTop=this.scrollTop,i.scrollLeft=this.scrollLeft,i.sel=this.sel,i.extend=!1,n&&(i.history.undoDepth=this.history.undoDepth,i.setHistory(this.getHistory())),i},linkedDoc:function(n){n||(n={});var i=this.first,a=this.first+this.size;n.from!=null&&n.from>i&&(i=n.from),n.to!=null&&n.to<a&&(a=n.to);var l=new Tn(cl(this,i,a),n.mode||this.modeOption,i,this.lineSep,this.direction);return n.sharedHist&&(l.history=this.history),(this.linked||(this.linked=[])).push({doc:l,sharedHist:n.sharedHist}),l.linked=[{doc:this,isParent:!0,sharedHist:n.sharedHist}],Jk(l,pm(this)),l},unlinkDoc:function(n){if(n instanceof Ct&&(n=n.doc),this.linked)for(var i=0;i<this.linked.length;++i){var a=this.linked[i];if(a.doc==n){this.linked.splice(i,1),n.unlinkDoc(this),Qk(pm(this));break}}if(n.history==this.history){var l=[n.id];Bi(n,function(u){return l.push(u.id)},!0),n.history=new dc(null),n.history.done=hs(this.history.done,l),n.history.undone=hs(this.history.undone,l)}},iterLinkedDocs:function(n){Bi(this,n)},getMode:function(){return this.mode},getEditor:function(){return this.cm},splitLines:function(n){return this.lineSep?n.split(this.lineSep):cr(n)},lineSeparator:function(){return this.lineSep||`\n`},setDirection:en(function(n){n!=\"rtl\"&&(n=\"ltr\"),n!=this.direction&&(this.direction=n,this.iter(function(i){return i.order=null}),this.cm&&Wk(this.cm))})}),Tn.prototype.eachLine=Tn.prototype.iter;var gm=0;function tS(n){var i=this;if(mm(i),!(Rt(i,n)||li(i.display,n))){cn(n),h&&(gm=+new Date);var a=ko(i,n,!0),l=n.dataTransfer.files;if(!(!a||i.isReadOnly()))if(l&&l.length&&window.FileReader&&window.File)for(var u=l.length,m=Array(u),y=0,x=function(){++y==u&&Qt(i,function(){a=tt(i.doc,a);var te={from:a,to:a,text:i.doc.splitLines(m.filter(function(pe){return pe!=null}).join(i.doc.lineSeparator())),origin:\"paste\"};gs(i.doc,te),em(i.doc,Fi(tt(i.doc,a),tt(i.doc,Hi(te))))})()},S=function(te,pe){if(i.options.allowDropFileTypes&&ae(i.options.allowDropFileTypes,te.type)==-1){x();return}var we=new FileReader;we.onerror=function(){return x()},we.onload=function(){var Te=we.result;if(/[\\x00-\\x08\\x0e-\\x1f]{2}/.test(Te)){x();return}m[pe]=Te,x()},we.readAsText(te)},T=0;T<l.length;T++)S(l[T],T);else{if(i.state.draggingText&&i.doc.sel.contains(a)>-1){i.state.draggingText(n),setTimeout(function(){return i.display.input.focus()},20);return}try{var H=n.dataTransfer.getData(\"Text\");if(H){var V;if(i.state.draggingText&&!i.state.draggingText.copy&&(V=i.listSelections()),gc(i.doc,Fi(a,a)),V)for(var se=0;se<V.length;++se)ms(i.doc,\"\",V[se].anchor,V[se].head,\"drag\");i.replaceSelection(H,\"around\",\"paste\"),i.display.input.focus()}}catch{}}}}function nS(n,i){if(h&&(!n.state.draggingText||+new Date-gm<100)){Oi(i);return}if(!(Rt(n,i)||li(n.display,i))&&(i.dataTransfer.setData(\"Text\",n.getSelection()),i.dataTransfer.effectAllowed=\"copyMove\",i.dataTransfer.setDragImage&&!L)){var a=k(\"img\",null,null,\"position: fixed; left: 0; top: 0;\");a.src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\",E&&(a.width=a.height=1,n.display.wrapper.appendChild(a),a._top=a.offsetTop),i.dataTransfer.setDragImage(a,0,0),E&&a.parentNode.removeChild(a)}}function rS(n,i){var a=ko(n,i);if(a){var l=document.createDocumentFragment();If(n,a,l),n.display.dragCursor||(n.display.dragCursor=k(\"div\",null,\"CodeMirror-cursors CodeMirror-dragcursors\"),n.display.lineSpace.insertBefore(n.display.dragCursor,n.display.cursorDiv)),C(n.display.dragCursor,l)}}function mm(n){n.display.dragCursor&&(n.display.lineSpace.removeChild(n.display.dragCursor),n.display.dragCursor=null)}function vm(n){if(document.getElementsByClassName){for(var i=document.getElementsByClassName(\"CodeMirror\"),a=[],l=0;l<i.length;l++){var u=i[l].CodeMirror;u&&a.push(u)}a.length&&a[0].operation(function(){for(var m=0;m<a.length;m++)n(a[m])})}}var ym=!1;function iS(){ym||(oS(),ym=!0)}function oS(){var n;Xe(window,\"resize\",function(){n==null&&(n=setTimeout(function(){n=null,vm(sS)},100))}),Xe(window,\"blur\",function(){return vm(us)})}function sS(n){var i=n.display;i.cachedCharWidth=i.cachedTextHeight=i.cachedPaddingH=null,i.scrollbarsClipped=!1,n.setSize()}for(var qi={3:\"Pause\",8:\"Backspace\",9:\"Tab\",13:\"Enter\",16:\"Shift\",17:\"Ctrl\",18:\"Alt\",19:\"Pause\",20:\"CapsLock\",27:\"Esc\",32:\"Space\",33:\"PageUp\",34:\"PageDown\",35:\"End\",36:\"Home\",37:\"Left\",38:\"Up\",39:\"Right\",40:\"Down\",44:\"PrintScrn\",45:\"Insert\",46:\"Delete\",59:\";\",61:\"=\",91:\"Mod\",92:\"Mod\",93:\"Mod\",106:\"*\",107:\"=\",109:\"-\",110:\".\",111:\"/\",145:\"ScrollLock\",173:\"-\",186:\";\",187:\"=\",188:\",\",189:\"-\",190:\".\",191:\"/\",192:\"`\",219:\"[\",220:\"\\\\\",221:\"]\",222:\"'\",224:\"Mod\",63232:\"Up\",63233:\"Down\",63234:\"Left\",63235:\"Right\",63272:\"Delete\",63273:\"Home\",63275:\"End\",63276:\"PageUp\",63277:\"PageDown\",63302:\"Insert\"},Ml=0;Ml<10;Ml++)qi[Ml+48]=qi[Ml+96]=String(Ml);for(var yc=65;yc<=90;yc++)qi[yc]=String.fromCharCode(yc);for(var Nl=1;Nl<=12;Nl++)qi[Nl+111]=qi[Nl+63235]=\"F\"+Nl;var ci={};ci.basic={Left:\"goCharLeft\",Right:\"goCharRight\",Up:\"goLineUp\",Down:\"goLineDown\",End:\"goLineEnd\",Home:\"goLineStartSmart\",PageUp:\"goPageUp\",PageDown:\"goPageDown\",Delete:\"delCharAfter\",Backspace:\"delCharBefore\",\"Shift-Backspace\":\"delCharBefore\",Tab:\"defaultTab\",\"Shift-Tab\":\"indentAuto\",Enter:\"newlineAndIndent\",Insert:\"toggleOverwrite\",Esc:\"singleSelection\"},ci.pcDefault={\"Ctrl-A\":\"selectAll\",\"Ctrl-D\":\"deleteLine\",\"Ctrl-Z\":\"undo\",\"Shift-Ctrl-Z\":\"redo\",\"Ctrl-Y\":\"redo\",\"Ctrl-Home\":\"goDocStart\",\"Ctrl-End\":\"goDocEnd\",\"Ctrl-Up\":\"goLineUp\",\"Ctrl-Down\":\"goLineDown\",\"Ctrl-Left\":\"goGroupLeft\",\"Ctrl-Right\":\"goGroupRight\",\"Alt-Left\":\"goLineStart\",\"Alt-Right\":\"goLineEnd\",\"Ctrl-Backspace\":\"delGroupBefore\",\"Ctrl-Delete\":\"delGroupAfter\",\"Ctrl-S\":\"save\",\"Ctrl-F\":\"find\",\"Ctrl-G\":\"findNext\",\"Shift-Ctrl-G\":\"findPrev\",\"Shift-Ctrl-F\":\"replace\",\"Shift-Ctrl-R\":\"replaceAll\",\"Ctrl-[\":\"indentLess\",\"Ctrl-]\":\"indentMore\",\"Ctrl-U\":\"undoSelection\",\"Shift-Ctrl-U\":\"redoSelection\",\"Alt-U\":\"redoSelection\",fallthrough:\"basic\"},ci.emacsy={\"Ctrl-F\":\"goCharRight\",\"Ctrl-B\":\"goCharLeft\",\"Ctrl-P\":\"goLineUp\",\"Ctrl-N\":\"goLineDown\",\"Ctrl-A\":\"goLineStart\",\"Ctrl-E\":\"goLineEnd\",\"Ctrl-V\":\"goPageDown\",\"Shift-Ctrl-V\":\"goPageUp\",\"Ctrl-D\":\"delCharAfter\",\"Ctrl-H\":\"delCharBefore\",\"Alt-Backspace\":\"delWordBefore\",\"Ctrl-K\":\"killLine\",\"Ctrl-T\":\"transposeChars\",\"Ctrl-O\":\"openLine\"},ci.macDefault={\"Cmd-A\":\"selectAll\",\"Cmd-D\":\"deleteLine\",\"Cmd-Z\":\"undo\",\"Shift-Cmd-Z\":\"redo\",\"Cmd-Y\":\"redo\",\"Cmd-Home\":\"goDocStart\",\"Cmd-Up\":\"goDocStart\",\"Cmd-End\":\"goDocEnd\",\"Cmd-Down\":\"goDocEnd\",\"Alt-Left\":\"goGroupLeft\",\"Alt-Right\":\"goGroupRight\",\"Cmd-Left\":\"goLineLeft\",\"Cmd-Right\":\"goLineRight\",\"Alt-Backspace\":\"delGroupBefore\",\"Ctrl-Alt-Backspace\":\"delGroupAfter\",\"Alt-Delete\":\"delGroupAfter\",\"Cmd-S\":\"save\",\"Cmd-F\":\"find\",\"Cmd-G\":\"findNext\",\"Shift-Cmd-G\":\"findPrev\",\"Cmd-Alt-F\":\"replace\",\"Shift-Cmd-Alt-F\":\"replaceAll\",\"Cmd-[\":\"indentLess\",\"Cmd-]\":\"indentMore\",\"Cmd-Backspace\":\"delWrappedLineLeft\",\"Cmd-Delete\":\"delWrappedLineRight\",\"Cmd-U\":\"undoSelection\",\"Shift-Cmd-U\":\"redoSelection\",\"Ctrl-Up\":\"goDocStart\",\"Ctrl-Down\":\"goDocEnd\",fallthrough:[\"basic\",\"emacsy\"]},ci.default=$?ci.macDefault:ci.pcDefault;function lS(n){var i=n.split(/-(?!$)/);n=i[i.length-1];for(var a,l,u,m,y=0;y<i.length-1;y++){var x=i[y];if(/^(cmd|meta|m)$/i.test(x))m=!0;else if(/^a(lt)?$/i.test(x))a=!0;else if(/^(c|ctrl|control)$/i.test(x))l=!0;else if(/^s(hift)?$/i.test(x))u=!0;else throw new Error(\"Unrecognized modifier name: \"+x)}return a&&(n=\"Alt-\"+n),l&&(n=\"Ctrl-\"+n),m&&(n=\"Cmd-\"+n),u&&(n=\"Shift-\"+n),n}function aS(n){var i={};for(var a in n)if(n.hasOwnProperty(a)){var l=n[a];if(/^(name|fallthrough|(de|at)tach)$/.test(a))continue;if(l==\"...\"){delete n[a];continue}for(var u=ye(a.split(\" \"),lS),m=0;m<u.length;m++){var y=void 0,x=void 0;m==u.length-1?(x=u.join(\" \"),y=l):(x=u.slice(0,m+1).join(\" \"),y=\"...\");var S=i[x];if(!S)i[x]=y;else if(S!=y)throw new Error(\"Inconsistent bindings for \"+x)}delete n[a]}for(var T in i)n[T]=i[T];return n}function ys(n,i,a,l){i=bc(i);var u=i.call?i.call(n,l):i[n];if(u===!1)return\"nothing\";if(u===\"...\")return\"multi\";if(u!=null&&a(u))return\"handled\";if(i.fallthrough){if(Object.prototype.toString.call(i.fallthrough)!=\"[object Array]\")return ys(n,i.fallthrough,a,l);for(var m=0;m<i.fallthrough.length;m++){var y=ys(n,i.fallthrough[m],a,l);if(y)return y}}}function bm(n){var i=typeof n==\"string\"?n:qi[n.keyCode];return i==\"Ctrl\"||i==\"Alt\"||i==\"Shift\"||i==\"Mod\"}function wm(n,i,a){var l=n;return i.altKey&&l!=\"Alt\"&&(n=\"Alt-\"+n),(Z?i.metaKey:i.ctrlKey)&&l!=\"Ctrl\"&&(n=\"Ctrl-\"+n),(Z?i.ctrlKey:i.metaKey)&&l!=\"Mod\"&&(n=\"Cmd-\"+n),!a&&i.shiftKey&&l!=\"Shift\"&&(n=\"Shift-\"+n),n}function xm(n,i){if(E&&n.keyCode==34&&n.char)return!1;var a=qi[n.keyCode];return a==null||n.altGraphKey?!1:(n.keyCode==3&&n.code&&(a=n.code),wm(a,n,i))}function bc(n){return typeof n==\"string\"?ci[n]:n}function bs(n,i){for(var a=n.doc.sel.ranges,l=[],u=0;u<a.length;u++){for(var m=i(a[u]);l.length&&Ie(m.from,xe(l).to)<=0;){var y=l.pop();if(Ie(y.from,m.from)<0){m.from=y.from;break}}l.push(m)}Wn(n,function(){for(var x=l.length-1;x>=0;x--)ms(n.doc,\"\",l[x].from,l[x].to,\"+delete\");fs(n)})}function Qf(n,i,a){var l=Yt(n.text,i+a,a);return l<0||l>n.text.length?null:l}function ed(n,i,a){var l=Qf(n,i.ch,a);return l==null?null:new fe(i.line,l,a<0?\"after\":\"before\")}function td(n,i,a,l,u){if(n){i.doc.direction==\"rtl\"&&(u=-u);var m=lt(a,i.doc.direction);if(m){var y=u<0?xe(m):m[0],x=u<0==(y.level==1),S=x?\"after\":\"before\",T;if(y.level>0||i.doc.direction==\"rtl\"){var H=ls(i,a);T=u<0?a.text.length-1:0;var V=jr(i,H,T).top;T=jt(function(se){return jr(i,H,se).top==V},u<0==(y.level==1)?y.from:y.to-1,T),S==\"before\"&&(T=Qf(a,T,1))}else T=u<0?y.to:y.from;return new fe(l,T,S)}}return new fe(l,u<0?a.text.length:0,u<0?\"before\":\"after\")}function cS(n,i,a,l){var u=lt(i,n.doc.direction);if(!u)return ed(i,a,l);a.ch>=i.text.length?(a.ch=i.text.length,a.sticky=\"before\"):a.ch<=0&&(a.ch=0,a.sticky=\"after\");var m=Bt(u,a.ch,a.sticky),y=u[m];if(n.doc.direction==\"ltr\"&&y.level%2==0&&(l>0?y.to>a.ch:y.from<a.ch))return ed(i,a,l);var x=function(Le,De){return Qf(i,Le instanceof fe?Le.ch:Le,De)},S,T=function(Le){return n.options.lineWrapping?(S=S||ls(n,i),Cg(n,i,S,Le)):{begin:0,end:i.text.length}},H=T(a.sticky==\"before\"?x(a,-1):a.ch);if(n.doc.direction==\"rtl\"||y.level==1){var V=y.level==1==l<0,se=x(a,V?1:-1);if(se!=null&&(V?se<=y.to&&se<=H.end:se>=y.from&&se>=H.begin)){var te=V?\"before\":\"after\";return new fe(a.line,se,te)}}var pe=function(Le,De,Me){for(var ze=function(St,tn){return tn?new fe(a.line,x(St,1),\"before\"):new fe(a.line,St,\"after\")};Le>=0&&Le<u.length;Le+=De){var Ye=u[Le],Ue=De>0==(Ye.level!=1),st=Ue?Me.begin:x(Me.end,-1);if(Ye.from<=st&&st<Ye.to||(st=Ue?Ye.from:x(Ye.to,-1),Me.begin<=st&&st<Me.end))return ze(st,Ue)}},we=pe(m+l,l,H);if(we)return we;var Te=l>0?H.end:x(H.begin,-1);return Te!=null&&!(l>0&&Te==i.text.length)&&(we=pe(l>0?0:u.length-1,l,T(Te)),we)?we:null}var Ol={selectAll:om,singleSelection:function(n){return n.setSelection(n.getCursor(\"anchor\"),n.getCursor(\"head\"),Q)},killLine:function(n){return bs(n,function(i){if(i.empty()){var a=qe(n.doc,i.head.line).text.length;return i.head.ch==a&&i.head.line<n.lastLine()?{from:i.head,to:fe(i.head.line+1,0)}:{from:i.head,to:fe(i.head.line,a)}}else return{from:i.from(),to:i.to()}})},deleteLine:function(n){return bs(n,function(i){return{from:fe(i.from().line,0),to:tt(n.doc,fe(i.to().line+1,0))}})},delLineLeft:function(n){return bs(n,function(i){return{from:fe(i.from().line,0),to:i.from()}})},delWrappedLineLeft:function(n){return bs(n,function(i){var a=n.charCoords(i.head,\"div\").top+5,l=n.coordsChar({left:0,top:a},\"div\");return{from:l,to:i.from()}})},delWrappedLineRight:function(n){return bs(n,function(i){var a=n.charCoords(i.head,\"div\").top+5,l=n.coordsChar({left:n.display.lineDiv.offsetWidth+100,top:a},\"div\");return{from:i.from(),to:l}})},undo:function(n){return n.undo()},redo:function(n){return n.redo()},undoSelection:function(n){return n.undoSelection()},redoSelection:function(n){return n.redoSelection()},goDocStart:function(n){return n.extendSelection(fe(n.firstLine(),0))},goDocEnd:function(n){return n.extendSelection(fe(n.lastLine()))},goLineStart:function(n){return n.extendSelectionsBy(function(i){return km(n,i.head.line)},{origin:\"+move\",bias:1})},goLineStartSmart:function(n){return n.extendSelectionsBy(function(i){return Sm(n,i.head)},{origin:\"+move\",bias:1})},goLineEnd:function(n){return n.extendSelectionsBy(function(i){return uS(n,i.head.line)},{origin:\"+move\",bias:-1})},goLineRight:function(n){return n.extendSelectionsBy(function(i){var a=n.cursorCoords(i.head,\"div\").top+5;return n.coordsChar({left:n.display.lineDiv.offsetWidth+100,top:a},\"div\")},de)},goLineLeft:function(n){return n.extendSelectionsBy(function(i){var a=n.cursorCoords(i.head,\"div\").top+5;return n.coordsChar({left:0,top:a},\"div\")},de)},goLineLeftSmart:function(n){return n.extendSelectionsBy(function(i){var a=n.cursorCoords(i.head,\"div\").top+5,l=n.coordsChar({left:0,top:a},\"div\");return l.ch<n.getLine(l.line).search(/\\S/)?Sm(n,i.head):l},de)},goLineUp:function(n){return n.moveV(-1,\"line\")},goLineDown:function(n){return n.moveV(1,\"line\")},goPageUp:function(n){return n.moveV(-1,\"page\")},goPageDown:function(n){return n.moveV(1,\"page\")},goCharLeft:function(n){return n.moveH(-1,\"char\")},goCharRight:function(n){return n.moveH(1,\"char\")},goColumnLeft:function(n){return n.moveH(-1,\"column\")},goColumnRight:function(n){return n.moveH(1,\"column\")},goWordLeft:function(n){return n.moveH(-1,\"word\")},goGroupRight:function(n){return n.moveH(1,\"group\")},goGroupLeft:function(n){return n.moveH(-1,\"group\")},goWordRight:function(n){return n.moveH(1,\"word\")},delCharBefore:function(n){return n.deleteH(-1,\"codepoint\")},delCharAfter:function(n){return n.deleteH(1,\"char\")},delWordBefore:function(n){return n.deleteH(-1,\"word\")},delWordAfter:function(n){return n.deleteH(1,\"word\")},delGroupBefore:function(n){return n.deleteH(-1,\"group\")},delGroupAfter:function(n){return n.deleteH(1,\"group\")},indentAuto:function(n){return n.indentSelection(\"smart\")},indentMore:function(n){return n.indentSelection(\"add\")},indentLess:function(n){return n.indentSelection(\"subtract\")},insertTab:function(n){return n.replaceSelection(\"\t\")},insertSoftTab:function(n){for(var i=[],a=n.listSelections(),l=n.options.tabSize,u=0;u<a.length;u++){var m=a[u].from(),y=re(n.getLine(m.line),m.ch,l);i.push(Ee(l-y%l))}n.replaceSelections(i)},defaultTab:function(n){n.somethingSelected()?n.indentSelection(\"add\"):n.execCommand(\"insertTab\")},transposeChars:function(n){return Wn(n,function(){for(var i=n.listSelections(),a=[],l=0;l<i.length;l++)if(i[l].empty()){var u=i[l].head,m=qe(n.doc,u.line).text;if(m){if(u.ch==m.length&&(u=new fe(u.line,u.ch-1)),u.ch>0)u=new fe(u.line,u.ch+1),n.replaceRange(m.charAt(u.ch-1)+m.charAt(u.ch-2),fe(u.line,u.ch-2),u,\"+transpose\");else if(u.line>n.doc.first){var y=qe(n.doc,u.line-1).text;y&&(u=new fe(u.line,1),n.replaceRange(m.charAt(0)+n.doc.lineSeparator()+y.charAt(y.length-1),fe(u.line-1,y.length-1),u,\"+transpose\"))}}a.push(new gt(u,u))}n.setSelections(a)})},newlineAndIndent:function(n){return Wn(n,function(){for(var i=n.listSelections(),a=i.length-1;a>=0;a--)n.replaceRange(n.doc.lineSeparator(),i[a].anchor,i[a].head,\"+input\");i=n.listSelections();for(var l=0;l<i.length;l++)n.indentLine(i[l].from().line,null,!0);fs(n)})},openLine:function(n){return n.replaceSelection(`\n`,\"start\")},toggleOverwrite:function(n){return n.toggleOverwrite()}};function km(n,i){var a=qe(n.doc,i),l=Sr(a);return l!=a&&(i=A(l)),td(!0,n,l,i,1)}function uS(n,i){var a=qe(n.doc,i),l=G1(a);return l!=a&&(i=A(l)),td(!0,n,a,i,-1)}function Sm(n,i){var a=km(n,i.line),l=qe(n.doc,a.line),u=lt(l,n.doc.direction);if(!u||u[0].level==0){var m=Math.max(a.ch,l.text.search(/\\S/)),y=i.line==a.line&&i.ch<=m&&i.ch;return fe(a.line,y?0:m,a.sticky)}return a}function wc(n,i,a){if(typeof i==\"string\"&&(i=Ol[i],!i))return!1;n.display.input.ensurePolled();var l=n.display.shift,u=!1;try{n.isReadOnly()&&(n.state.suppressEdits=!0),a&&(n.display.shift=!1),u=i(n)!=q}finally{n.display.shift=l,n.state.suppressEdits=!1}return u}function fS(n,i,a){for(var l=0;l<n.state.keyMaps.length;l++){var u=ys(i,n.state.keyMaps[l],a,n);if(u)return u}return n.options.extraKeys&&ys(i,n.options.extraKeys,a,n)||ys(i,n.options.keyMap,a,n)}var dS=new le;function Pl(n,i,a,l){var u=n.state.keySeq;if(u){if(bm(i))return\"handled\";if(/\\'$/.test(i)?n.state.keySeq=null:dS.set(50,function(){n.state.keySeq==u&&(n.state.keySeq=null,n.display.input.reset())}),_m(n,u+\" \"+i,a,l))return!0}return _m(n,i,a,l)}function _m(n,i,a,l){var u=fS(n,i,l);return u==\"multi\"&&(n.state.keySeq=i),u==\"handled\"&&Jt(n,\"keyHandled\",n,i,a),(u==\"handled\"||u==\"multi\")&&(cn(a),Df(n)),!!u}function Tm(n,i){var a=xm(i,!0);return a?i.shiftKey&&!n.state.keySeq?Pl(n,\"Shift-\"+a,i,function(l){return wc(n,l,!0)})||Pl(n,a,i,function(l){if(typeof l==\"string\"?/^go[A-Z]/.test(l):l.motion)return wc(n,l)}):Pl(n,a,i,function(l){return wc(n,l)}):!1}function hS(n,i,a){return Pl(n,\"'\"+a+\"'\",i,function(l){return wc(n,l,!0)})}var nd=null;function Cm(n){var i=this;if(!(n.target&&n.target!=i.display.input.getField())&&(i.curOp.focus=be(je(i)),!Rt(i,n))){h&&p<11&&n.keyCode==27&&(n.returnValue=!1);var a=n.keyCode;i.display.shift=a==16||n.shiftKey;var l=Tm(i,n);E&&(nd=l?a:null,!l&&a==88&&!Ka&&($?n.metaKey:n.ctrlKey)&&i.replaceSelection(\"\",null,\"cut\")),s&&!$&&!l&&a==46&&n.shiftKey&&!n.ctrlKey&&document.execCommand&&document.execCommand(\"cut\"),a==18&&!/\\bCodeMirror-crosshair\\b/.test(i.display.lineDiv.className)&&pS(i)}}function pS(n){var i=n.display.lineDiv;Se(i,\"CodeMirror-crosshair\");function a(l){(l.keyCode==18||!l.altKey)&&(N(i,\"CodeMirror-crosshair\"),an(document,\"keyup\",a),an(document,\"mouseover\",a))}Xe(document,\"keyup\",a),Xe(document,\"mouseover\",a)}function Em(n){n.keyCode==16&&(this.doc.sel.shift=!1),Rt(this,n)}function Am(n){var i=this;if(!(n.target&&n.target!=i.display.input.getField())&&!(li(i.display,n)||Rt(i,n)||n.ctrlKey&&!n.altKey||$&&n.metaKey)){var a=n.keyCode,l=n.charCode;if(E&&a==nd){nd=null,cn(n);return}if(!(E&&(!n.which||n.which<10)&&Tm(i,n))){var u=String.fromCharCode(l??a);u!=\"\\b\"&&(hS(i,n,u)||i.display.input.onKeyPress(n))}}}var gS=400,rd=function(n,i,a){this.time=n,this.pos=i,this.button=a};rd.prototype.compare=function(n,i,a){return this.time+gS>n&&Ie(i,this.pos)==0&&a==this.button};var Rl,$l;function mS(n,i){var a=+new Date;return $l&&$l.compare(a,n,i)?(Rl=$l=null,\"triple\"):Rl&&Rl.compare(a,n,i)?($l=new rd(a,n,i),Rl=null,\"double\"):(Rl=new rd(a,n,i),$l=null,\"single\")}function Lm(n){var i=this,a=i.display;if(!(Rt(i,n)||a.activeTouch&&a.input.supportsTouch())){if(a.input.ensurePolled(),a.shift=n.shiftKey,li(a,n)){g||(a.scroller.draggable=!1,setTimeout(function(){return a.scroller.draggable=!0},100));return}if(!id(i,n)){var l=ko(i,n),u=br(n),m=l?mS(l,u):\"single\";Pe(i).focus(),u==1&&i.state.selectingText&&i.state.selectingText(n),!(l&&vS(i,u,l,m,n))&&(u==1?l?bS(i,l,m,n):sl(n)==a.scroller&&cn(n):u==2?(l&&pc(i.doc,l),setTimeout(function(){return a.input.focus()},20)):u==3&&(G?i.display.input.onContextMenu(n):zf(i)))}}}function vS(n,i,a,l,u){var m=\"Click\";return l==\"double\"?m=\"Double\"+m:l==\"triple\"&&(m=\"Triple\"+m),m=(i==1?\"Left\":i==2?\"Middle\":\"Right\")+m,Pl(n,wm(m,u),u,function(y){if(typeof y==\"string\"&&(y=Ol[y]),!y)return!1;var x=!1;try{n.isReadOnly()&&(n.state.suppressEdits=!0),x=y(n,a)!=q}finally{n.state.suppressEdits=!1}return x})}function yS(n,i,a){var l=n.getOption(\"configureMouse\"),u=l?l(n,i,a):{};if(u.unit==null){var m=W?a.shiftKey&&a.metaKey:a.altKey;u.unit=m?\"rectangle\":i==\"single\"?\"char\":i==\"double\"?\"word\":\"line\"}return(u.extend==null||n.doc.extend)&&(u.extend=n.doc.extend||a.shiftKey),u.addNew==null&&(u.addNew=$?a.metaKey:a.ctrlKey),u.moveOnDrag==null&&(u.moveOnDrag=!($?a.altKey:a.ctrlKey)),u}function bS(n,i,a,l){h?setTimeout(F(Mg,n),0):n.curOp.focus=be(je(n));var u=yS(n,a,l),m=n.doc.sel,y;n.options.dragDrop&&mf&&!n.isReadOnly()&&a==\"single\"&&(y=m.contains(i))>-1&&(Ie((y=m.ranges[y]).from(),i)<0||i.xRel>0)&&(Ie(y.to(),i)>0||i.xRel<0)?wS(n,l,i,u):xS(n,l,i,u)}function wS(n,i,a,l){var u=n.display,m=!1,y=Qt(n,function(T){g&&(u.scroller.draggable=!1),n.state.draggingText=!1,n.state.delayingBlurEvent&&(n.hasFocus()?n.state.delayingBlurEvent=!1:zf(n)),an(u.wrapper.ownerDocument,\"mouseup\",y),an(u.wrapper.ownerDocument,\"mousemove\",x),an(u.scroller,\"dragstart\",S),an(u.scroller,\"drop\",y),m||(cn(T),l.addNew||pc(n.doc,a,null,null,l.extend),g&&!L||h&&p==9?setTimeout(function(){u.wrapper.ownerDocument.body.focus({preventScroll:!0}),u.input.focus()},20):u.input.focus())}),x=function(T){m=m||Math.abs(i.clientX-T.clientX)+Math.abs(i.clientY-T.clientY)>=10},S=function(){return m=!0};g&&(u.scroller.draggable=!0),n.state.draggingText=y,y.copy=!l.moveOnDrag,Xe(u.wrapper.ownerDocument,\"mouseup\",y),Xe(u.wrapper.ownerDocument,\"mousemove\",x),Xe(u.scroller,\"dragstart\",S),Xe(u.scroller,\"drop\",y),n.state.delayingBlurEvent=!0,setTimeout(function(){return u.input.focus()},20),u.scroller.dragDrop&&u.scroller.dragDrop()}function Mm(n,i,a){if(a==\"char\")return new gt(i,i);if(a==\"word\")return n.findWordAt(i);if(a==\"line\")return new gt(fe(i.line,0),tt(n.doc,fe(i.line+1,0)));var l=a(n,i);return new gt(l.from,l.to)}function xS(n,i,a,l){h&&zf(n);var u=n.display,m=n.doc;cn(i);var y,x,S=m.sel,T=S.ranges;if(l.addNew&&!l.extend?(x=m.sel.contains(a),x>-1?y=T[x]:y=new gt(a,a)):(y=m.sel.primary(),x=m.sel.primIndex),l.unit==\"rectangle\")l.addNew||(y=new gt(a,a)),a=ko(n,i,!0,!0),x=-1;else{var H=Mm(n,a,l.unit);l.extend?y=Zf(y,H.anchor,H.head,l.extend):y=H}l.addNew?x==-1?(x=T.length,un(m,Tr(n,T.concat([y]),x),{scroll:!1,origin:\"*mouse\"})):T.length>1&&T[x].empty()&&l.unit==\"char\"&&!l.extend?(un(m,Tr(n,T.slice(0,x).concat(T.slice(x+1)),0),{scroll:!1,origin:\"*mouse\"}),S=m.sel):Jf(m,x,y,he):(x=0,un(m,new er([y],0),he),S=m.sel);var V=a;function se(Me){if(Ie(V,Me)!=0)if(V=Me,l.unit==\"rectangle\"){for(var ze=[],Ye=n.options.tabSize,Ue=re(qe(m,a.line).text,a.ch,Ye),st=re(qe(m,Me.line).text,Me.ch,Ye),St=Math.min(Ue,st),tn=Math.max(Ue,st),Ot=Math.min(a.line,Me.line),qn=Math.min(n.lastLine(),Math.max(a.line,Me.line));Ot<=qn;Ot++){var Cn=qe(m,Ot).text,Ut=ge(Cn,St,Ye);St==tn?ze.push(new gt(fe(Ot,Ut),fe(Ot,Ut))):Cn.length>Ut&&ze.push(new gt(fe(Ot,Ut),fe(Ot,ge(Cn,tn,Ye))))}ze.length||ze.push(new gt(a,a)),un(m,Tr(n,S.ranges.slice(0,x).concat(ze),x),{origin:\"*mouse\",scroll:!1}),n.scrollIntoView(Me)}else{var En=y,sn=Mm(n,Me,l.unit),Kt=En.anchor,Vt;Ie(sn.anchor,Kt)>0?(Vt=sn.head,Kt=is(En.from(),sn.anchor)):(Vt=sn.anchor,Kt=Sn(En.to(),sn.head));var It=S.ranges.slice(0);It[x]=kS(n,new gt(tt(m,Kt),Vt)),un(m,Tr(n,It,x),he)}}var te=u.wrapper.getBoundingClientRect(),pe=0;function we(Me){var ze=++pe,Ye=ko(n,Me,!0,l.unit==\"rectangle\");if(Ye)if(Ie(Ye,V)!=0){n.curOp.focus=be(je(n)),se(Ye);var Ue=ac(u,m);(Ye.line>=Ue.to||Ye.line<Ue.from)&&setTimeout(Qt(n,function(){pe==ze&&we(Me)}),150)}else{var st=Me.clientY<te.top?-20:Me.clientY>te.bottom?20:0;st&&setTimeout(Qt(n,function(){pe==ze&&(u.scroller.scrollTop+=st,we(Me))}),50)}}function Te(Me){n.state.selectingText=!1,pe=1/0,Me&&(cn(Me),u.input.focus()),an(u.wrapper.ownerDocument,\"mousemove\",Le),an(u.wrapper.ownerDocument,\"mouseup\",De),m.history.lastSelOrigin=null}var Le=Qt(n,function(Me){Me.buttons===0||!br(Me)?Te(Me):we(Me)}),De=Qt(n,Te);n.state.selectingText=De,Xe(u.wrapper.ownerDocument,\"mousemove\",Le),Xe(u.wrapper.ownerDocument,\"mouseup\",De)}function kS(n,i){var a=i.anchor,l=i.head,u=qe(n.doc,a.line);if(Ie(a,l)==0&&a.sticky==l.sticky)return i;var m=lt(u);if(!m)return i;var y=Bt(m,a.ch,a.sticky),x=m[y];if(x.from!=a.ch&&x.to!=a.ch)return i;var S=y+(x.from==a.ch==(x.level!=1)?0:1);if(S==0||S==m.length)return i;var T;if(l.line!=a.line)T=(l.line-a.line)*(n.doc.direction==\"ltr\"?1:-1)>0;else{var H=Bt(m,l.ch,l.sticky),V=H-y||(l.ch-a.ch)*(x.level==1?-1:1);H==S-1||H==S?T=V<0:T=V>0}var se=m[S+(T?-1:0)],te=T==(se.level==1),pe=te?se.from:se.to,we=te?\"after\":\"before\";return a.ch==pe&&a.sticky==we?i:new gt(new fe(a.line,pe,we),l)}function Nm(n,i,a,l){var u,m;if(i.touches)u=i.touches[0].clientX,m=i.touches[0].clientY;else try{u=i.clientX,m=i.clientY}catch{return!1}if(u>=Math.floor(n.display.gutters.getBoundingClientRect().right))return!1;l&&cn(i);var y=n.display,x=y.lineDiv.getBoundingClientRect();if(m>x.bottom||!Bn(n,a))return kn(i);m-=x.top-y.viewOffset;for(var S=0;S<n.display.gutterSpecs.length;++S){var T=y.gutters.childNodes[S];if(T&&T.getBoundingClientRect().right>=u){var H=U(n.doc,m),V=n.display.gutterSpecs[S];return Pt(n,a,n,H,V.className,i),kn(i)}}}function id(n,i){return Nm(n,i,\"gutterClick\",!0)}function Om(n,i){li(n.display,i)||SS(n,i)||Rt(n,i,\"contextmenu\")||G||n.display.input.onContextMenu(i)}function SS(n,i){return Bn(n,\"gutterContextMenu\")?Nm(n,i,\"gutterContextMenu\",!1):!1}function Pm(n){n.display.wrapper.className=n.display.wrapper.className.replace(/\\s*cm-s-\\S+/g,\"\")+n.options.theme.replace(/(^|\\s)\\s*/g,\" cm-s-\"),gl(n)}var ws={toString:function(){return\"CodeMirror.Init\"}},Rm={},xc={};function _S(n){var i=n.optionHandlers;function a(l,u,m,y){n.defaults[l]=u,m&&(i[l]=y?function(x,S,T){T!=ws&&m(x,S,T)}:m)}n.defineOption=a,n.Init=ws,a(\"value\",\"\",function(l,u){return l.setValue(u)},!0),a(\"mode\",null,function(l,u){l.doc.modeOption=u,Kf(l)},!0),a(\"indentUnit\",2,Kf,!0),a(\"indentWithTabs\",!1),a(\"smartIndent\",!0),a(\"tabSize\",4,function(l){Sl(l),gl(l),_n(l)},!0),a(\"lineSeparator\",null,function(l,u){if(l.doc.lineSep=u,!!u){var m=[],y=l.doc.first;l.doc.iter(function(S){for(var T=0;;){var H=S.text.indexOf(u,T);if(H==-1)break;T=H+u.length,m.push(fe(y,H))}y++});for(var x=m.length-1;x>=0;x--)ms(l.doc,u,m[x],fe(m[x].line,m[x].ch+u.length))}}),a(\"specialChars\",/[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u061c\\u200b\\u200e\\u200f\\u2028\\u2029\\u202d\\u202e\\u2066\\u2067\\u2069\\ufeff\\ufff9-\\ufffc]/g,function(l,u,m){l.state.specialChars=new RegExp(u.source+(u.test(\"\t\")?\"\":\"|\t\"),\"g\"),m!=ws&&l.refresh()}),a(\"specialCharPlaceholder\",Q1,function(l){return l.refresh()},!0),a(\"electricChars\",!0),a(\"inputStyle\",_?\"contenteditable\":\"textarea\",function(){throw new Error(\"inputStyle can not (yet) be changed in a running editor\")},!0),a(\"spellcheck\",!1,function(l,u){return l.getInputField().spellcheck=u},!0),a(\"autocorrect\",!1,function(l,u){return l.getInputField().autocorrect=u},!0),a(\"autocapitalize\",!1,function(l,u){return l.getInputField().autocapitalize=u},!0),a(\"rtlMoveVisually\",!ne),a(\"wholeLineUpdateBefore\",!0),a(\"theme\",\"default\",function(l){Pm(l),kl(l)},!0),a(\"keyMap\",\"default\",function(l,u,m){var y=bc(u),x=m!=ws&&bc(m);x&&x.detach&&x.detach(l,y),y.attach&&y.attach(l,x||null)}),a(\"extraKeys\",null),a(\"configureMouse\",null),a(\"lineWrapping\",!1,CS,!0),a(\"gutters\",[],function(l,u){l.display.gutterSpecs=Vf(u,l.options.lineNumbers),kl(l)},!0),a(\"fixedGutter\",!0,function(l,u){l.display.gutters.style.left=u?Rf(l.display)+\"px\":\"0\",l.refresh()},!0),a(\"coverGutterNextToScrollbar\",!1,function(l){return ds(l)},!0),a(\"scrollbarStyle\",\"native\",function(l){Ig(l),ds(l),l.display.scrollbars.setScrollTop(l.doc.scrollTop),l.display.scrollbars.setScrollLeft(l.doc.scrollLeft)},!0),a(\"lineNumbers\",!1,function(l,u){l.display.gutterSpecs=Vf(l.options.gutters,u),kl(l)},!0),a(\"firstLineNumber\",1,kl,!0),a(\"lineNumberFormatter\",function(l){return l},kl,!0),a(\"showCursorWhenSelecting\",!1,ml,!0),a(\"resetSelectionOnContextMenu\",!0),a(\"lineWiseCopyCut\",!0),a(\"pasteLinesPerSelection\",!0),a(\"selectionsMayTouch\",!1),a(\"readOnly\",!1,function(l,u){u==\"nocursor\"&&(us(l),l.display.input.blur()),l.display.input.readOnlyChanged(u)}),a(\"screenReaderLabel\",null,function(l,u){u=u===\"\"?null:u,l.display.input.screenReaderLabelChanged(u)}),a(\"disableInput\",!1,function(l,u){u||l.display.input.reset()},!0),a(\"dragDrop\",!0,TS),a(\"allowDropFileTypes\",null),a(\"cursorBlinkRate\",530),a(\"cursorScrollMargin\",0),a(\"cursorHeight\",1,ml,!0),a(\"singleCursorHeightPerLine\",!0,ml,!0),a(\"workTime\",100),a(\"workDelay\",100),a(\"flattenSpans\",!0,Sl,!0),a(\"addModeClass\",!1,Sl,!0),a(\"pollInterval\",100),a(\"undoDepth\",200,function(l,u){return l.doc.history.undoDepth=u}),a(\"historyEventDelay\",1250),a(\"viewportMargin\",10,function(l){return l.refresh()},!0),a(\"maxHighlightLength\",1e4,Sl,!0),a(\"moveInputWithCursor\",!0,function(l,u){u||l.display.input.resetPosition()}),a(\"tabindex\",null,function(l,u){return l.display.input.getField().tabIndex=u||\"\"}),a(\"autofocus\",null),a(\"direction\",\"ltr\",function(l,u){return l.doc.setDirection(u)},!0),a(\"phrases\",null)}function TS(n,i,a){var l=a&&a!=ws;if(!i!=!l){var u=n.display.dragFunctions,m=i?Xe:an;m(n.display.scroller,\"dragstart\",u.start),m(n.display.scroller,\"dragenter\",u.enter),m(n.display.scroller,\"dragover\",u.over),m(n.display.scroller,\"dragleave\",u.leave),m(n.display.scroller,\"drop\",u.drop)}}function CS(n){n.options.lineWrapping?(Se(n.display.wrapper,\"CodeMirror-wrap\"),n.display.sizer.style.minWidth=\"\",n.display.sizerWidth=null):(N(n.display.wrapper,\"CodeMirror-wrap\"),_f(n)),$f(n),_n(n),gl(n),setTimeout(function(){return ds(n)},100)}function Ct(n,i){var a=this;if(!(this instanceof Ct))return new Ct(n,i);this.options=i=i?Y(i):{},Y(Rm,i,!1);var l=i.value;typeof l==\"string\"?l=new Tn(l,i.mode,null,i.lineSeparator,i.direction):i.mode&&(l.modeOption=i.mode),this.doc=l;var u=new Ct.inputStyles[i.inputStyle](this),m=this.display=new Fk(n,l,u,i);m.wrapper.CodeMirror=this,Pm(this),i.lineWrapping&&(this.display.wrapper.className+=\" CodeMirror-wrap\"),Ig(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new le,keySeq:null,specialChars:null},i.autofocus&&!_&&m.input.focus(),h&&p<11&&setTimeout(function(){return a.display.input.reset(!0)},20),ES(this),iS(),Co(this),this.curOp.forceUpdate=!0,Vg(this,l),i.autofocus&&!_||this.hasFocus()?setTimeout(function(){a.hasFocus()&&!a.state.focused&&Ff(a)},20):us(this);for(var y in xc)xc.hasOwnProperty(y)&&xc[y](this,i[y],ws);Fg(this),i.finishInit&&i.finishInit(this);for(var x=0;x<od.length;++x)od[x](this);Eo(this),g&&i.lineWrapping&&getComputedStyle(m.lineDiv).textRendering==\"optimizelegibility\"&&(m.lineDiv.style.textRendering=\"auto\")}Ct.defaults=Rm,Ct.optionHandlers=xc;function ES(n){var i=n.display;Xe(i.scroller,\"mousedown\",Qt(n,Lm)),h&&p<11?Xe(i.scroller,\"dblclick\",Qt(n,function(S){if(!Rt(n,S)){var T=ko(n,S);if(!(!T||id(n,S)||li(n.display,S))){cn(S);var H=n.findWordAt(T);pc(n.doc,H.anchor,H.head)}}})):Xe(i.scroller,\"dblclick\",function(S){return Rt(n,S)||cn(S)}),Xe(i.scroller,\"contextmenu\",function(S){return Om(n,S)}),Xe(i.input.getField(),\"contextmenu\",function(S){i.scroller.contains(S.target)||Om(n,S)});var a,l={end:0};function u(){i.activeTouch&&(a=setTimeout(function(){return i.activeTouch=null},1e3),l=i.activeTouch,l.end=+new Date)}function m(S){if(S.touches.length!=1)return!1;var T=S.touches[0];return T.radiusX<=1&&T.radiusY<=1}function y(S,T){if(T.left==null)return!0;var H=T.left-S.left,V=T.top-S.top;return H*H+V*V>400}Xe(i.scroller,\"touchstart\",function(S){if(!Rt(n,S)&&!m(S)&&!id(n,S)){i.input.ensurePolled(),clearTimeout(a);var T=+new Date;i.activeTouch={start:T,moved:!1,prev:T-l.end<=300?l:null},S.touches.length==1&&(i.activeTouch.left=S.touches[0].pageX,i.activeTouch.top=S.touches[0].pageY)}}),Xe(i.scroller,\"touchmove\",function(){i.activeTouch&&(i.activeTouch.moved=!0)}),Xe(i.scroller,\"touchend\",function(S){var T=i.activeTouch;if(T&&!li(i,S)&&T.left!=null&&!T.moved&&new Date-T.start<300){var H=n.coordsChar(i.activeTouch,\"page\"),V;!T.prev||y(T,T.prev)?V=new gt(H,H):!T.prev.prev||y(T,T.prev.prev)?V=n.findWordAt(H):V=new gt(fe(H.line,0),tt(n.doc,fe(H.line+1,0))),n.setSelection(V.anchor,V.head),n.focus(),cn(S)}u()}),Xe(i.scroller,\"touchcancel\",u),Xe(i.scroller,\"scroll\",function(){i.scroller.clientHeight&&(yl(n,i.scroller.scrollTop),_o(n,i.scroller.scrollLeft,!0),Pt(n,\"scroll\",n))}),Xe(i.scroller,\"mousewheel\",function(S){return Wg(n,S)}),Xe(i.scroller,\"DOMMouseScroll\",function(S){return Wg(n,S)}),Xe(i.wrapper,\"scroll\",function(){return i.wrapper.scrollTop=i.wrapper.scrollLeft=0}),i.dragFunctions={enter:function(S){Rt(n,S)||Oi(S)},over:function(S){Rt(n,S)||(rS(n,S),Oi(S))},start:function(S){return nS(n,S)},drop:Qt(n,tS),leave:function(S){Rt(n,S)||mm(n)}};var x=i.input.getField();Xe(x,\"keyup\",function(S){return Em.call(n,S)}),Xe(x,\"keydown\",Qt(n,Cm)),Xe(x,\"keypress\",Qt(n,Am)),Xe(x,\"focus\",function(S){return Ff(n,S)}),Xe(x,\"blur\",function(S){return us(n,S)})}var od=[];Ct.defineInitHook=function(n){return od.push(n)};function Il(n,i,a,l){var u=n.doc,m;a==null&&(a=\"add\"),a==\"smart\"&&(u.mode.indent?m=ul(n,i).state:a=\"prev\");var y=n.options.tabSize,x=qe(u,i),S=re(x.text,null,y);x.stateAfter&&(x.stateAfter=null);var T=x.text.match(/^\\s*/)[0],H;if(!l&&!/\\S/.test(x.text))H=0,a=\"not\";else if(a==\"smart\"&&(H=u.mode.indent(m,x.text.slice(T.length),x.text),H==q||H>150)){if(!l)return;a=\"prev\"}a==\"prev\"?i>u.first?H=re(qe(u,i-1).text,null,y):H=0:a==\"add\"?H=S+n.options.indentUnit:a==\"subtract\"?H=S-n.options.indentUnit:typeof a==\"number\"&&(H=S+a),H=Math.max(0,H);var V=\"\",se=0;if(n.options.indentWithTabs)for(var te=Math.floor(H/y);te;--te)se+=y,V+=\"\t\";if(se<H&&(V+=Ee(H-se)),V!=T)return ms(u,V,fe(i,0),fe(i,T.length),\"+input\"),x.stateAfter=null,!0;for(var pe=0;pe<u.sel.ranges.length;pe++){var we=u.sel.ranges[pe];if(we.head.line==i&&we.head.ch<T.length){var Te=fe(i,T.length);Jf(u,pe,new gt(Te,Te));break}}}var Cr=null;function kc(n){Cr=n}function sd(n,i,a,l,u){var m=n.doc;n.display.shift=!1,l||(l=m.sel);var y=+new Date-200,x=u==\"paste\"||n.state.pasteIncoming>y,S=cr(i),T=null;if(x&&l.ranges.length>1)if(Cr&&Cr.text.join(`\n`)==i){if(l.ranges.length%Cr.text.length==0){T=[];for(var H=0;H<Cr.text.length;H++)T.push(m.splitLines(Cr.text[H]))}}else S.length==l.ranges.length&&n.options.pasteLinesPerSelection&&(T=ye(S,function(Le){return[Le]}));for(var V=n.curOp.updateInput,se=l.ranges.length-1;se>=0;se--){var te=l.ranges[se],pe=te.from(),we=te.to();te.empty()&&(a&&a>0?pe=fe(pe.line,pe.ch-a):n.state.overwrite&&!x?we=fe(we.line,Math.min(qe(m,we.line).text.length,we.ch+xe(S).length)):x&&Cr&&Cr.lineWise&&Cr.text.join(`\n`)==S.join(`\n`)&&(pe=we=fe(pe.line,0)));var Te={from:pe,to:we,text:T?T[se%T.length]:S,origin:u||(x?\"paste\":n.state.cutIncoming>y?\"cut\":\"+input\")};gs(n.doc,Te),Jt(n,\"inputRead\",n,Te)}i&&!x&&Im(n,i),fs(n),n.curOp.updateInput<2&&(n.curOp.updateInput=V),n.curOp.typing=!0,n.state.pasteIncoming=n.state.cutIncoming=-1}function $m(n,i){var a=n.clipboardData&&n.clipboardData.getData(\"Text\");if(a)return n.preventDefault(),!i.isReadOnly()&&!i.options.disableInput&&i.hasFocus()&&Wn(i,function(){return sd(i,a,0,null,\"paste\")}),!0}function Im(n,i){if(!(!n.options.electricChars||!n.options.smartIndent))for(var a=n.doc.sel,l=a.ranges.length-1;l>=0;l--){var u=a.ranges[l];if(!(u.head.ch>100||l&&a.ranges[l-1].head.line==u.head.line)){var m=n.getModeAt(u.head),y=!1;if(m.electricChars){for(var x=0;x<m.electricChars.length;x++)if(i.indexOf(m.electricChars.charAt(x))>-1){y=Il(n,u.head.line,\"smart\");break}}else m.electricInput&&m.electricInput.test(qe(n.doc,u.head.line).text.slice(0,u.head.ch))&&(y=Il(n,u.head.line,\"smart\"));y&&Jt(n,\"electricInput\",n,u.head.line)}}}function Dm(n){for(var i=[],a=[],l=0;l<n.doc.sel.ranges.length;l++){var u=n.doc.sel.ranges[l].head.line,m={anchor:fe(u,0),head:fe(u+1,0)};a.push(m),i.push(n.getRange(m.anchor,m.head))}return{text:i,ranges:a}}function ld(n,i,a,l){n.setAttribute(\"autocorrect\",a?\"on\":\"off\"),n.setAttribute(\"autocapitalize\",l?\"on\":\"off\"),n.setAttribute(\"spellcheck\",!!i)}function zm(){var n=k(\"textarea\",null,null,\"position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; min-height: 1em; outline: none\"),i=k(\"div\",[n],null,\"overflow: hidden; position: relative; width: 3px; height: 0px;\");return g?n.style.width=\"1000px\":n.setAttribute(\"wrap\",\"off\"),R&&(n.style.border=\"1px solid black\"),i}function AS(n){var i=n.optionHandlers,a=n.helpers={};n.prototype={constructor:n,focus:function(){Pe(this).focus(),this.display.input.focus()},setOption:function(l,u){var m=this.options,y=m[l];m[l]==u&&l!=\"mode\"||(m[l]=u,i.hasOwnProperty(l)&&Qt(this,i[l])(this,u,y),Pt(this,\"optionChange\",this,l))},getOption:function(l){return this.options[l]},getDoc:function(){return this.doc},addKeyMap:function(l,u){this.state.keyMaps[u?\"push\":\"unshift\"](bc(l))},removeKeyMap:function(l){for(var u=this.state.keyMaps,m=0;m<u.length;++m)if(u[m]==l||u[m].name==l)return u.splice(m,1),!0},addOverlay:vn(function(l,u){var m=l.token?l:n.getMode(this.options,l);if(m.startState)throw new Error(\"Overlays may not be stateful.\");J(this.state.overlays,{mode:m,modeSpec:l,opaque:u&&u.opaque,priority:u&&u.priority||0},function(y){return y.priority}),this.state.modeGen++,_n(this)}),removeOverlay:vn(function(l){for(var u=this.state.overlays,m=0;m<u.length;++m){var y=u[m].modeSpec;if(y==l||typeof l==\"string\"&&y.name==l){u.splice(m,1),this.state.modeGen++,_n(this);return}}}),indentLine:vn(function(l,u,m){typeof u!=\"string\"&&typeof u!=\"number\"&&(u==null?u=this.options.smartIndent?\"smart\":\"prev\":u=u?\"add\":\"subtract\"),me(this.doc,l)&&Il(this,l,u,m)}),indentSelection:vn(function(l){for(var u=this.doc.sel.ranges,m=-1,y=0;y<u.length;y++){var x=u[y];if(x.empty())x.head.line>m&&(Il(this,x.head.line,l,!0),m=x.head.line,y==this.doc.sel.primIndex&&fs(this));else{var S=x.from(),T=x.to(),H=Math.max(m,S.line);m=Math.min(this.lastLine(),T.line-(T.ch?0:1))+1;for(var V=H;V<m;++V)Il(this,V,l);var se=this.doc.sel.ranges;S.ch==0&&u.length==se.length&&se[y].from().ch>0&&Jf(this.doc,y,new gt(S,se[y].to()),Q)}}}),getTokenAt:function(l,u){return Kp(this,l,u)},getLineTokens:function(l,u){return Kp(this,fe(l),u,!0)},getTokenTypeAt:function(l){l=tt(this.doc,l);var u=Up(this,qe(this.doc,l.line)),m=0,y=(u.length-1)/2,x=l.ch,S;if(x==0)S=u[2];else for(;;){var T=m+y>>1;if((T?u[T*2-1]:0)>=x)y=T;else if(u[T*2+1]<x)m=T+1;else{S=u[T*2+2];break}}var H=S?S.indexOf(\"overlay \"):-1;return H<0?S:H==0?null:S.slice(0,H-1)},getModeAt:function(l){var u=this.doc.mode;return u.innerMode?n.innerMode(u,this.getTokenAt(l).state).mode:u},getHelper:function(l,u){return this.getHelpers(l,u)[0]},getHelpers:function(l,u){var m=[];if(!a.hasOwnProperty(u))return m;var y=a[u],x=this.getModeAt(l);if(typeof x[u]==\"string\")y[x[u]]&&m.push(y[x[u]]);else if(x[u])for(var S=0;S<x[u].length;S++){var T=y[x[u][S]];T&&m.push(T)}else x.helperType&&y[x.helperType]?m.push(y[x.helperType]):y[x.name]&&m.push(y[x.name]);for(var H=0;H<y._global.length;H++){var V=y._global[H];V.pred(x,this)&&ae(m,V.val)==-1&&m.push(V.val)}return m},getStateAfter:function(l,u){var m=this.doc;return l=Wp(m,l??m.first+m.size-1),ul(this,l+1,u).state},cursorCoords:function(l,u){var m,y=this.doc.sel.primary();return l==null?m=y.head:typeof l==\"object\"?m=tt(this.doc,l):m=l?y.from():y.to(),_r(this,m,u||\"page\")},charCoords:function(l,u){return ic(this,tt(this.doc,l),u||\"page\")},coordsChar:function(l,u){return l=Sg(this,l,u||\"page\"),Nf(this,l.left,l.top)},lineAtHeight:function(l,u){return l=Sg(this,{top:l,left:0},u||\"page\").top,U(this.doc,l+this.display.viewOffset)},heightAtLine:function(l,u,m){var y=!1,x;if(typeof l==\"number\"){var S=this.doc.first+this.doc.size-1;l<this.doc.first?l=this.doc.first:l>S&&(l=S,y=!0),x=qe(this.doc,l)}else x=l;return rc(this,x,{top:0,left:0},u||\"page\",m||y).top+(y?this.doc.height-si(x):0)},defaultTextHeight:function(){return as(this.display)},defaultCharWidth:function(){return cs(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(l,u,m,y,x){var S=this.display;l=_r(this,tt(this.doc,l));var T=l.bottom,H=l.left;if(u.style.position=\"absolute\",u.setAttribute(\"cm-ignore-events\",\"true\"),this.display.input.setUneditable(u),S.sizer.appendChild(u),y==\"over\")T=l.top;else if(y==\"above\"||y==\"near\"){var V=Math.max(S.wrapper.clientHeight,this.doc.height),se=Math.max(S.sizer.clientWidth,S.lineSpace.clientWidth);(y==\"above\"||l.bottom+u.offsetHeight>V)&&l.top>u.offsetHeight?T=l.top-u.offsetHeight:l.bottom+u.offsetHeight<=V&&(T=l.bottom),H+u.offsetWidth>se&&(H=se-u.offsetWidth)}u.style.top=T+\"px\",u.style.left=u.style.right=\"\",x==\"right\"?(H=S.sizer.clientWidth-u.offsetWidth,u.style.right=\"0px\"):(x==\"left\"?H=0:x==\"middle\"&&(H=(S.sizer.clientWidth-u.offsetWidth)/2),u.style.left=H+\"px\"),m&&Tk(this,{left:H,top:T,right:H+u.offsetWidth,bottom:T+u.offsetHeight})},triggerOnKeyDown:vn(Cm),triggerOnKeyPress:vn(Am),triggerOnKeyUp:Em,triggerOnMouseDown:vn(Lm),execCommand:function(l){if(Ol.hasOwnProperty(l))return Ol[l].call(null,this)},triggerElectric:vn(function(l){Im(this,l)}),findPosH:function(l,u,m,y){var x=1;u<0&&(x=-1,u=-u);for(var S=tt(this.doc,l),T=0;T<u&&(S=ad(this.doc,S,x,m,y),!S.hitSide);++T);return S},moveH:vn(function(l,u){var m=this;this.extendSelectionsBy(function(y){return m.display.shift||m.doc.extend||y.empty()?ad(m.doc,y.head,l,u,m.options.rtlMoveVisually):l<0?y.from():y.to()},de)}),deleteH:vn(function(l,u){var m=this.doc.sel,y=this.doc;m.somethingSelected()?y.replaceSelection(\"\",null,\"+delete\"):bs(this,function(x){var S=ad(y,x.head,l,u,!1);return l<0?{from:S,to:x.head}:{from:x.head,to:S}})}),findPosV:function(l,u,m,y){var x=1,S=y;u<0&&(x=-1,u=-u);for(var T=tt(this.doc,l),H=0;H<u;++H){var V=_r(this,T,\"div\");if(S==null?S=V.left:V.left=S,T=Fm(this,V,x,m),T.hitSide)break}return T},moveV:vn(function(l,u){var m=this,y=this.doc,x=[],S=!this.display.shift&&!y.extend&&y.sel.somethingSelected();if(y.extendSelectionsBy(function(H){if(S)return l<0?H.from():H.to();var V=_r(m,H.head,\"div\");H.goalColumn!=null&&(V.left=H.goalColumn),x.push(V.left);var se=Fm(m,V,l,u);return u==\"page\"&&H==y.sel.primary()&&Bf(m,ic(m,se,\"div\").top-V.top),se},de),x.length)for(var T=0;T<y.sel.ranges.length;T++)y.sel.ranges[T].goalColumn=x[T]}),findWordAt:function(l){var u=this.doc,m=qe(u,l.line).text,y=l.ch,x=l.ch;if(m){var S=this.getHelper(l,\"wordChars\");(l.sticky==\"before\"||x==m.length)&&y?--y:++x;for(var T=m.charAt(y),H=ct(T,S)?function(V){return ct(V,S)}:/\\s/.test(T)?function(V){return/\\s/.test(V)}:function(V){return!/\\s/.test(V)&&!ct(V)};y>0&&H(m.charAt(y-1));)--y;for(;x<m.length&&H(m.charAt(x));)++x}return new gt(fe(l.line,y),fe(l.line,x))},toggleOverwrite:function(l){l!=null&&l==this.state.overwrite||((this.state.overwrite=!this.state.overwrite)?Se(this.display.cursorDiv,\"CodeMirror-overwrite\"):N(this.display.cursorDiv,\"CodeMirror-overwrite\"),Pt(this,\"overwriteToggle\",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==be(je(this))},isReadOnly:function(){return!!(this.options.readOnly||this.doc.cantEdit)},scrollTo:vn(function(l,u){vl(this,l,u)}),getScrollInfo:function(){var l=this.display.scroller;return{left:l.scrollLeft,top:l.scrollTop,height:l.scrollHeight-qr(this)-this.display.barHeight,width:l.scrollWidth-qr(this)-this.display.barWidth,clientHeight:Ef(this),clientWidth:wo(this)}},scrollIntoView:vn(function(l,u){l==null?(l={from:this.doc.sel.primary().head,to:null},u==null&&(u=this.options.cursorScrollMargin)):typeof l==\"number\"?l={from:fe(l,0),to:null}:l.from==null&&(l={from:l,to:null}),l.to||(l.to=l.from),l.margin=u||0,l.from.line!=null?Ck(this,l):Og(this,l.from,l.to,l.margin)}),setSize:vn(function(l,u){var m=this,y=function(S){return typeof S==\"number\"||/^\\d+$/.test(String(S))?S+\"px\":S};l!=null&&(this.display.wrapper.style.width=y(l)),u!=null&&(this.display.wrapper.style.height=y(u)),this.options.lineWrapping&&wg(this);var x=this.display.viewFrom;this.doc.iter(x,this.display.viewTo,function(S){if(S.widgets){for(var T=0;T<S.widgets.length;T++)if(S.widgets[T].noHScroll){Di(m,x,\"widget\");break}}++x}),this.curOp.forceUpdate=!0,Pt(this,\"refresh\",this)}),operation:function(l){return Wn(this,l)},startOperation:function(){return Co(this)},endOperation:function(){return Eo(this)},refresh:vn(function(){var l=this.display.cachedTextHeight;_n(this),this.curOp.forceUpdate=!0,gl(this),vl(this,this.doc.scrollLeft,this.doc.scrollTop),jf(this.display),(l==null||Math.abs(l-as(this.display))>.5||this.options.lineWrapping)&&$f(this),Pt(this,\"refresh\",this)}),swapDoc:vn(function(l){var u=this.doc;return u.cm=null,this.state.selectingText&&this.state.selectingText(),Vg(this,l),gl(this),this.display.input.reset(),vl(this,l.scrollLeft,l.scrollTop),this.curOp.forceScroll=!0,Jt(this,\"swapDoc\",this,u),u}),phrase:function(l){var u=this.options.phrases;return u&&Object.prototype.hasOwnProperty.call(u,l)?u[l]:l},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},yr(n),n.registerHelper=function(l,u,m){a.hasOwnProperty(l)||(a[l]=n[l]={_global:[]}),a[l][u]=m},n.registerGlobalHelper=function(l,u,m,y){n.registerHelper(l,u,y),a[l]._global.push({pred:m,val:y})}}function ad(n,i,a,l,u){var m=i,y=a,x=qe(n,i.line),S=u&&n.direction==\"rtl\"?-a:a;function T(){var De=i.line+S;return De<n.first||De>=n.first+n.size?!1:(i=new fe(De,i.ch,i.sticky),x=qe(n,De))}function H(De){var Me;if(l==\"codepoint\"){var ze=x.text.charCodeAt(i.ch+(a>0?0:-1));if(isNaN(ze))Me=null;else{var Ye=a>0?ze>=55296&&ze<56320:ze>=56320&&ze<57343;Me=new fe(i.line,Math.max(0,Math.min(x.text.length,i.ch+a*(Ye?2:1))),-a)}}else u?Me=cS(n.cm,x,i,a):Me=ed(x,i,a);if(Me==null)if(!De&&T())i=td(u,n.cm,x,i.line,S);else return!1;else i=Me;return!0}if(l==\"char\"||l==\"codepoint\")H();else if(l==\"column\")H(!0);else if(l==\"word\"||l==\"group\")for(var V=null,se=l==\"group\",te=n.cm&&n.cm.getHelper(i,\"wordChars\"),pe=!0;!(a<0&&!H(!pe));pe=!1){var we=x.text.charAt(i.ch)||`\n`,Te=ct(we,te)?\"w\":se&&we==`\n`?\"n\":!se||/\\s/.test(we)?null:\"p\";if(se&&!pe&&!Te&&(Te=\"s\"),V&&V!=Te){a<0&&(a=1,H(),i.sticky=\"after\");break}if(Te&&(V=Te),a>0&&!H(!pe))break}var Le=mc(n,i,m,y,!0);return pt(m,Le)&&(Le.hitSide=!0),Le}function Fm(n,i,a,l){var u=n.doc,m=i.left,y;if(l==\"page\"){var x=Math.min(n.display.wrapper.clientHeight,Pe(n).innerHeight||u(n).documentElement.clientHeight),S=Math.max(x-.5*as(n.display),3);y=(a>0?i.bottom:i.top)+a*S}else l==\"line\"&&(y=a>0?i.bottom+3:i.top-3);for(var T;T=Nf(n,m,y),!!T.outside;){if(a<0?y<=0:y>=u.height){T.hitSide=!0;break}y+=a*5}return T}var yt=function(n){this.cm=n,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new le,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};yt.prototype.init=function(n){var i=this,a=this,l=a.cm,u=a.div=n.lineDiv;u.contentEditable=!0,ld(u,l.options.spellcheck,l.options.autocorrect,l.options.autocapitalize);function m(x){for(var S=x.target;S;S=S.parentNode){if(S==u)return!0;if(/\\bCodeMirror-(?:line)?widget\\b/.test(S.className))break}return!1}Xe(u,\"paste\",function(x){!m(x)||Rt(l,x)||$m(x,l)||p<=11&&setTimeout(Qt(l,function(){return i.updateFromDOM()}),20)}),Xe(u,\"compositionstart\",function(x){i.composing={data:x.data,done:!1}}),Xe(u,\"compositionupdate\",function(x){i.composing||(i.composing={data:x.data,done:!1})}),Xe(u,\"compositionend\",function(x){i.composing&&(x.data!=i.composing.data&&i.readFromDOMSoon(),i.composing.done=!0)}),Xe(u,\"touchstart\",function(){return a.forceCompositionEnd()}),Xe(u,\"input\",function(){i.composing||i.readFromDOMSoon()});function y(x){if(!(!m(x)||Rt(l,x))){if(l.somethingSelected())kc({lineWise:!1,text:l.getSelections()}),x.type==\"cut\"&&l.replaceSelection(\"\",null,\"cut\");else if(l.options.lineWiseCopyCut){var S=Dm(l);kc({lineWise:!0,text:S.text}),x.type==\"cut\"&&l.operation(function(){l.setSelections(S.ranges,0,Q),l.replaceSelection(\"\",null,\"cut\")})}else return;if(x.clipboardData){x.clipboardData.clearData();var T=Cr.text.join(`\n`);if(x.clipboardData.setData(\"Text\",T),x.clipboardData.getData(\"Text\")==T){x.preventDefault();return}}var H=zm(),V=H.firstChild;ld(V),l.display.lineSpace.insertBefore(H,l.display.lineSpace.firstChild),V.value=Cr.text.join(`\n`);var se=be(Fe(u));Ae(V),setTimeout(function(){l.display.lineSpace.removeChild(H),se.focus(),se==u&&a.showPrimarySelection()},50)}}Xe(u,\"copy\",y),Xe(u,\"cut\",y)},yt.prototype.screenReaderLabelChanged=function(n){n?this.div.setAttribute(\"aria-label\",n):this.div.removeAttribute(\"aria-label\")},yt.prototype.prepareSelection=function(){var n=Lg(this.cm,!1);return n.focus=be(Fe(this.div))==this.div,n},yt.prototype.showSelection=function(n,i){!n||!this.cm.display.view.length||((n.focus||i)&&this.showPrimarySelection(),this.showMultipleSelections(n))},yt.prototype.getSelection=function(){return this.cm.display.wrapper.ownerDocument.getSelection()},yt.prototype.showPrimarySelection=function(){var n=this.getSelection(),i=this.cm,a=i.doc.sel.primary(),l=a.from(),u=a.to();if(i.display.viewTo==i.display.viewFrom||l.line>=i.display.viewTo||u.line<i.display.viewFrom){n.removeAllRanges();return}var m=Sc(i,n.anchorNode,n.anchorOffset),y=Sc(i,n.focusNode,n.focusOffset);if(!(m&&!m.bad&&y&&!y.bad&&Ie(is(m,y),l)==0&&Ie(Sn(m,y),u)==0)){var x=i.display.view,S=l.line>=i.display.viewFrom&&Hm(i,l)||{node:x[0].measure.map[2],offset:0},T=u.line<i.display.viewTo&&Hm(i,u);if(!T){var H=x[x.length-1].measure,V=H.maps?H.maps[H.maps.length-1]:H.map;T={node:V[V.length-1],offset:V[V.length-2]-V[V.length-3]}}if(!S||!T){n.removeAllRanges();return}var se=n.rangeCount&&n.getRangeAt(0),te;try{te=B(S.node,S.offset,T.offset,T.node)}catch{}te&&(!s&&i.state.focused?(n.collapse(S.node,S.offset),te.collapsed||(n.removeAllRanges(),n.addRange(te))):(n.removeAllRanges(),n.addRange(te)),se&&n.anchorNode==null?n.addRange(se):s&&this.startGracePeriod()),this.rememberSelection()}},yt.prototype.startGracePeriod=function(){var n=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){n.gracePeriod=!1,n.selectionChanged()&&n.cm.operation(function(){return n.cm.curOp.selectionChanged=!0})},20)},yt.prototype.showMultipleSelections=function(n){C(this.cm.display.cursorDiv,n.cursors),C(this.cm.display.selectionDiv,n.selection)},yt.prototype.rememberSelection=function(){var n=this.getSelection();this.lastAnchorNode=n.anchorNode,this.lastAnchorOffset=n.anchorOffset,this.lastFocusNode=n.focusNode,this.lastFocusOffset=n.focusOffset},yt.prototype.selectionInEditor=function(){var n=this.getSelection();if(!n.rangeCount)return!1;var i=n.getRangeAt(0).commonAncestorContainer;return ce(this.div,i)},yt.prototype.focus=function(){this.cm.options.readOnly!=\"nocursor\"&&((!this.selectionInEditor()||be(Fe(this.div))!=this.div)&&this.showSelection(this.prepareSelection(),!0),this.div.focus())},yt.prototype.blur=function(){this.div.blur()},yt.prototype.getField=function(){return this.div},yt.prototype.supportsTouch=function(){return!0},yt.prototype.receivedFocus=function(){var n=this,i=this;this.selectionInEditor()?setTimeout(function(){return n.pollSelection()},20):Wn(this.cm,function(){return i.cm.curOp.selectionChanged=!0});function a(){i.cm.state.focused&&(i.pollSelection(),i.polling.set(i.cm.options.pollInterval,a))}this.polling.set(this.cm.options.pollInterval,a)},yt.prototype.selectionChanged=function(){var n=this.getSelection();return n.anchorNode!=this.lastAnchorNode||n.anchorOffset!=this.lastAnchorOffset||n.focusNode!=this.lastFocusNode||n.focusOffset!=this.lastFocusOffset},yt.prototype.pollSelection=function(){if(!(this.readDOMTimeout!=null||this.gracePeriod||!this.selectionChanged())){var n=this.getSelection(),i=this.cm;if(I&&b&&this.cm.display.gutterSpecs.length&&LS(n.anchorNode)){this.cm.triggerOnKeyDown({type:\"keydown\",keyCode:8,preventDefault:Math.abs}),this.blur(),this.focus();return}if(!this.composing){this.rememberSelection();var a=Sc(i,n.anchorNode,n.anchorOffset),l=Sc(i,n.focusNode,n.focusOffset);a&&l&&Wn(i,function(){un(i.doc,Fi(a,l),Q),(a.bad||l.bad)&&(i.curOp.selectionChanged=!0)})}}},yt.prototype.pollContent=function(){this.readDOMTimeout!=null&&(clearTimeout(this.readDOMTimeout),this.readDOMTimeout=null);var n=this.cm,i=n.display,a=n.doc.sel.primary(),l=a.from(),u=a.to();if(l.ch==0&&l.line>n.firstLine()&&(l=fe(l.line-1,qe(n.doc,l.line-1).length)),u.ch==qe(n.doc,u.line).text.length&&u.line<n.lastLine()&&(u=fe(u.line+1,0)),l.line<i.viewFrom||u.line>i.viewTo-1)return!1;var m,y,x;l.line==i.viewFrom||(m=So(n,l.line))==0?(y=A(i.view[0].line),x=i.view[0].node):(y=A(i.view[m].line),x=i.view[m-1].node.nextSibling);var S=So(n,u.line),T,H;if(S==i.view.length-1?(T=i.viewTo-1,H=i.lineDiv.lastChild):(T=A(i.view[S+1].line)-1,H=i.view[S+1].node.previousSibling),!x)return!1;for(var V=n.doc.splitLines(MS(n,x,H,y,T)),se=ii(n.doc,fe(y,0),fe(T,qe(n.doc,T).text.length));V.length>1&&se.length>1;)if(xe(V)==xe(se))V.pop(),se.pop(),T--;else if(V[0]==se[0])V.shift(),se.shift(),y++;else break;for(var te=0,pe=0,we=V[0],Te=se[0],Le=Math.min(we.length,Te.length);te<Le&&we.charCodeAt(te)==Te.charCodeAt(te);)++te;for(var De=xe(V),Me=xe(se),ze=Math.min(De.length-(V.length==1?te:0),Me.length-(se.length==1?te:0));pe<ze&&De.charCodeAt(De.length-pe-1)==Me.charCodeAt(Me.length-pe-1);)++pe;if(V.length==1&&se.length==1&&y==l.line)for(;te&&te>l.ch&&De.charCodeAt(De.length-pe-1)==Me.charCodeAt(Me.length-pe-1);)te--,pe++;V[V.length-1]=De.slice(0,De.length-pe).replace(/^\\u200b+/,\"\"),V[0]=V[0].slice(te).replace(/\\u200b+$/,\"\");var Ye=fe(y,te),Ue=fe(T,se.length?xe(se).length-pe:0);if(V.length>1||V[0]||Ie(Ye,Ue))return ms(n.doc,V,Ye,Ue,\"+input\"),!0},yt.prototype.ensurePolled=function(){this.forceCompositionEnd()},yt.prototype.reset=function(){this.forceCompositionEnd()},yt.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},yt.prototype.readFromDOMSoon=function(){var n=this;this.readDOMTimeout==null&&(this.readDOMTimeout=setTimeout(function(){if(n.readDOMTimeout=null,n.composing)if(n.composing.done)n.composing=null;else return;n.updateFromDOM()},80))},yt.prototype.updateFromDOM=function(){var n=this;(this.cm.isReadOnly()||!this.pollContent())&&Wn(this.cm,function(){return _n(n.cm)})},yt.prototype.setUneditable=function(n){n.contentEditable=\"false\"},yt.prototype.onKeyPress=function(n){n.charCode==0||this.composing||(n.preventDefault(),this.cm.isReadOnly()||Qt(this.cm,sd)(this.cm,String.fromCharCode(n.charCode==null?n.keyCode:n.charCode),0))},yt.prototype.readOnlyChanged=function(n){this.div.contentEditable=String(n!=\"nocursor\")},yt.prototype.onContextMenu=function(){},yt.prototype.resetPosition=function(){},yt.prototype.needsContentAttribute=!0;function Hm(n,i){var a=Af(n,i.line);if(!a||a.hidden)return null;var l=qe(n.doc,i.line),u=gg(a,l,i.line),m=lt(l,n.doc.direction),y=\"left\";if(m){var x=Bt(m,i.ch);y=x%2?\"right\":\"left\"}var S=yg(u.map,i.ch,y);return S.offset=S.collapse==\"right\"?S.end:S.start,S}function LS(n){for(var i=n;i;i=i.parentNode)if(/CodeMirror-gutter-wrapper/.test(i.className))return!0;return!1}function xs(n,i){return i&&(n.bad=!0),n}function MS(n,i,a,l,u){var m=\"\",y=!1,x=n.doc.lineSeparator(),S=!1;function T(te){return function(pe){return pe.id==te}}function H(){y&&(m+=x,S&&(m+=x),y=S=!1)}function V(te){te&&(H(),m+=te)}function se(te){if(te.nodeType==1){var pe=te.getAttribute(\"cm-text\");if(pe){V(pe);return}var we=te.getAttribute(\"cm-marker\"),Te;if(we){var Le=n.findMarks(fe(l,0),fe(u+1,0),T(+we));Le.length&&(Te=Le[0].find(0))&&V(ii(n.doc,Te.from,Te.to).join(x));return}if(te.getAttribute(\"contenteditable\")==\"false\")return;var De=/^(pre|div|p|li|table|br)$/i.test(te.nodeName);if(!/^br$/i.test(te.nodeName)&&te.textContent.length==0)return;De&&H();for(var Me=0;Me<te.childNodes.length;Me++)se(te.childNodes[Me]);/^(pre|p)$/i.test(te.nodeName)&&(S=!0),De&&(y=!0)}else te.nodeType==3&&V(te.nodeValue.replace(/\\u200b/g,\"\").replace(/\\u00a0/g,\" \"))}for(;se(i),i!=a;)i=i.nextSibling,S=!1;return m}function Sc(n,i,a){var l;if(i==n.display.lineDiv){if(l=n.display.lineDiv.childNodes[a],!l)return xs(n.clipPos(fe(n.display.viewTo-1)),!0);i=null,a=0}else for(l=i;;l=l.parentNode){if(!l||l==n.display.lineDiv)return null;if(l.parentNode&&l.parentNode==n.display.lineDiv)break}for(var u=0;u<n.display.view.length;u++){var m=n.display.view[u];if(m.node==l)return NS(m,i,a)}}function NS(n,i,a){var l=n.text.firstChild,u=!1;if(!i||!ce(l,i))return xs(fe(A(n.line),0),!0);if(i==l&&(u=!0,i=l.childNodes[a],a=0,!i)){var m=n.rest?xe(n.rest):n.line;return xs(fe(A(m),m.text.length),u)}var y=i.nodeType==3?i:null,x=i;for(!y&&i.childNodes.length==1&&i.firstChild.nodeType==3&&(y=i.firstChild,a&&(a=y.nodeValue.length));x.parentNode!=l;)x=x.parentNode;var S=n.measure,T=S.maps;function H(Te,Le,De){for(var Me=-1;Me<(T?T.length:0);Me++)for(var ze=Me<0?S.map:T[Me],Ye=0;Ye<ze.length;Ye+=3){var Ue=ze[Ye+2];if(Ue==Te||Ue==Le){var st=A(Me<0?n.line:n.rest[Me]),St=ze[Ye]+De;return(De<0||Ue!=Te)&&(St=ze[Ye+(De?1:0)]),fe(st,St)}}}var V=H(y,x,a);if(V)return xs(V,u);for(var se=x.nextSibling,te=y?y.nodeValue.length-a:0;se;se=se.nextSibling){if(V=H(se,se.firstChild,0),V)return xs(fe(V.line,V.ch-te),u);te+=se.textContent.length}for(var pe=x.previousSibling,we=a;pe;pe=pe.previousSibling){if(V=H(pe,pe.firstChild,-1),V)return xs(fe(V.line,V.ch+we),u);we+=pe.textContent.length}}var Wt=function(n){this.cm=n,this.prevInput=\"\",this.pollingFast=!1,this.polling=new le,this.hasSelection=!1,this.composing=null,this.resetting=!1};Wt.prototype.init=function(n){var i=this,a=this,l=this.cm;this.createField(n);var u=this.textarea;n.wrapper.insertBefore(this.wrapper,n.wrapper.firstChild),R&&(u.style.width=\"0px\"),Xe(u,\"input\",function(){h&&p>=9&&i.hasSelection&&(i.hasSelection=null),a.poll()}),Xe(u,\"paste\",function(y){Rt(l,y)||$m(y,l)||(l.state.pasteIncoming=+new Date,a.fastPoll())});function m(y){if(!Rt(l,y)){if(l.somethingSelected())kc({lineWise:!1,text:l.getSelections()});else if(l.options.lineWiseCopyCut){var x=Dm(l);kc({lineWise:!0,text:x.text}),y.type==\"cut\"?l.setSelections(x.ranges,null,Q):(a.prevInput=\"\",u.value=x.text.join(`\n`),Ae(u))}else return;y.type==\"cut\"&&(l.state.cutIncoming=+new Date)}}Xe(u,\"cut\",m),Xe(u,\"copy\",m),Xe(n.scroller,\"paste\",function(y){if(!(li(n,y)||Rt(l,y))){if(!u.dispatchEvent){l.state.pasteIncoming=+new Date,a.focus();return}var x=new Event(\"paste\");x.clipboardData=y.clipboardData,u.dispatchEvent(x)}}),Xe(n.lineSpace,\"selectstart\",function(y){li(n,y)||cn(y)}),Xe(u,\"compositionstart\",function(){var y=l.getCursor(\"from\");a.composing&&a.composing.range.clear(),a.composing={start:y,range:l.markText(y,l.getCursor(\"to\"),{className:\"CodeMirror-composing\"})}}),Xe(u,\"compositionend\",function(){a.composing&&(a.poll(),a.composing.range.clear(),a.composing=null)})},Wt.prototype.createField=function(n){this.wrapper=zm(),this.textarea=this.wrapper.firstChild;var i=this.cm.options;ld(this.textarea,i.spellcheck,i.autocorrect,i.autocapitalize)},Wt.prototype.screenReaderLabelChanged=function(n){n?this.textarea.setAttribute(\"aria-label\",n):this.textarea.removeAttribute(\"aria-label\")},Wt.prototype.prepareSelection=function(){var n=this.cm,i=n.display,a=n.doc,l=Lg(n);if(n.options.moveInputWithCursor){var u=_r(n,a.sel.primary().head,\"div\"),m=i.wrapper.getBoundingClientRect(),y=i.lineDiv.getBoundingClientRect();l.teTop=Math.max(0,Math.min(i.wrapper.clientHeight-10,u.top+y.top-m.top)),l.teLeft=Math.max(0,Math.min(i.wrapper.clientWidth-10,u.left+y.left-m.left))}return l},Wt.prototype.showSelection=function(n){var i=this.cm,a=i.display;C(a.cursorDiv,n.cursors),C(a.selectionDiv,n.selection),n.teTop!=null&&(this.wrapper.style.top=n.teTop+\"px\",this.wrapper.style.left=n.teLeft+\"px\")},Wt.prototype.reset=function(n){if(!(this.contextMenuPending||this.composing&&n)){var i=this.cm;if(this.resetting=!0,i.somethingSelected()){this.prevInput=\"\";var a=i.getSelection();this.textarea.value=a,i.state.focused&&Ae(this.textarea),h&&p>=9&&(this.hasSelection=a)}else n||(this.prevInput=this.textarea.value=\"\",h&&p>=9&&(this.hasSelection=null));this.resetting=!1}},Wt.prototype.getField=function(){return this.textarea},Wt.prototype.supportsTouch=function(){return!1},Wt.prototype.focus=function(){if(this.cm.options.readOnly!=\"nocursor\"&&(!_||be(Fe(this.textarea))!=this.textarea))try{this.textarea.focus()}catch{}},Wt.prototype.blur=function(){this.textarea.blur()},Wt.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Wt.prototype.receivedFocus=function(){this.slowPoll()},Wt.prototype.slowPoll=function(){var n=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){n.poll(),n.cm.state.focused&&n.slowPoll()})},Wt.prototype.fastPoll=function(){var n=!1,i=this;i.pollingFast=!0;function a(){var l=i.poll();!l&&!n?(n=!0,i.polling.set(60,a)):(i.pollingFast=!1,i.slowPoll())}i.polling.set(20,a)},Wt.prototype.poll=function(){var n=this,i=this.cm,a=this.textarea,l=this.prevInput;if(this.contextMenuPending||this.resetting||!i.state.focused||Ri(a)&&!l&&!this.composing||i.isReadOnly()||i.options.disableInput||i.state.keySeq)return!1;var u=a.value;if(u==l&&!i.somethingSelected())return!1;if(h&&p>=9&&this.hasSelection===u||$&&/[\\uf700-\\uf7ff]/.test(u))return i.display.input.reset(),!1;if(i.doc.sel==i.display.selForContextMenu){var m=u.charCodeAt(0);if(m==8203&&!l&&(l=\"​\"),m==8666)return this.reset(),this.cm.execCommand(\"undo\")}for(var y=0,x=Math.min(l.length,u.length);y<x&&l.charCodeAt(y)==u.charCodeAt(y);)++y;return Wn(i,function(){sd(i,u.slice(y),l.length-y,null,n.composing?\"*compose\":null),u.length>1e3||u.indexOf(`\n`)>-1?a.value=n.prevInput=\"\":n.prevInput=u,n.composing&&(n.composing.range.clear(),n.composing.range=i.markText(n.composing.start,i.getCursor(\"to\"),{className:\"CodeMirror-composing\"}))}),!0},Wt.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Wt.prototype.onKeyPress=function(){h&&p>=9&&(this.hasSelection=null),this.fastPoll()},Wt.prototype.onContextMenu=function(n){var i=this,a=i.cm,l=a.display,u=i.textarea;i.contextMenuPending&&i.contextMenuPending();var m=ko(a,n),y=l.scroller.scrollTop;if(!m||E)return;var x=a.options.resetSelectionOnContextMenu;x&&a.doc.sel.contains(m)==-1&&Qt(a,un)(a.doc,Fi(m),Q);var S=u.style.cssText,T=i.wrapper.style.cssText,H=i.wrapper.offsetParent.getBoundingClientRect();i.wrapper.style.cssText=\"position: static\",u.style.cssText=`position: absolute; width: 30px; height: 30px;\n      top: `+(n.clientY-H.top-5)+\"px; left: \"+(n.clientX-H.left-5)+`px;\n      z-index: 1000; background: `+(h?\"rgba(255, 255, 255, .05)\":\"transparent\")+`;\n      outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);`;var V;g&&(V=u.ownerDocument.defaultView.scrollY),l.input.focus(),g&&u.ownerDocument.defaultView.scrollTo(null,V),l.input.reset(),a.somethingSelected()||(u.value=i.prevInput=\" \"),i.contextMenuPending=te,l.selForContextMenu=a.doc.sel,clearTimeout(l.detectingSelectAll);function se(){if(u.selectionStart!=null){var we=a.somethingSelected(),Te=\"​\"+(we?u.value:\"\");u.value=\"⇚\",u.value=Te,i.prevInput=we?\"\":\"​\",u.selectionStart=1,u.selectionEnd=Te.length,l.selForContextMenu=a.doc.sel}}function te(){if(i.contextMenuPending==te&&(i.contextMenuPending=!1,i.wrapper.style.cssText=T,u.style.cssText=S,h&&p<9&&l.scrollbars.setScrollTop(l.scroller.scrollTop=y),u.selectionStart!=null)){(!h||h&&p<9)&&se();var we=0,Te=function(){l.selForContextMenu==a.doc.sel&&u.selectionStart==0&&u.selectionEnd>0&&i.prevInput==\"​\"?Qt(a,om)(a):we++<10?l.detectingSelectAll=setTimeout(Te,500):(l.selForContextMenu=null,l.input.reset())};l.detectingSelectAll=setTimeout(Te,200)}}if(h&&p>=9&&se(),G){Oi(n);var pe=function(){an(window,\"mouseup\",pe),setTimeout(te,20)};Xe(window,\"mouseup\",pe)}else setTimeout(te,50)},Wt.prototype.readOnlyChanged=function(n){n||this.reset(),this.textarea.disabled=n==\"nocursor\",this.textarea.readOnly=!!n},Wt.prototype.setUneditable=function(){},Wt.prototype.needsContentAttribute=!1;function OS(n,i){if(i=i?Y(i):{},i.value=n.value,!i.tabindex&&n.tabIndex&&(i.tabindex=n.tabIndex),!i.placeholder&&n.placeholder&&(i.placeholder=n.placeholder),i.autofocus==null){var a=be(Fe(n));i.autofocus=a==n||n.getAttribute(\"autofocus\")!=null&&a==document.body}function l(){n.value=x.getValue()}var u;if(n.form&&(Xe(n.form,\"submit\",l),!i.leaveSubmitMethodAlone)){var m=n.form;u=m.submit;try{var y=m.submit=function(){l(),m.submit=u,m.submit(),m.submit=y}}catch{}}i.finishInit=function(S){S.save=l,S.getTextArea=function(){return n},S.toTextArea=function(){S.toTextArea=isNaN,l(),n.parentNode.removeChild(S.getWrapperElement()),n.style.display=\"\",n.form&&(an(n.form,\"submit\",l),!i.leaveSubmitMethodAlone&&typeof n.form.submit==\"function\"&&(n.form.submit=u))}},n.style.display=\"none\";var x=Ct(function(S){return n.parentNode.insertBefore(S,n.nextSibling)},i);return x}function PS(n){n.off=an,n.on=Xe,n.wheelEventPixels=Hk,n.Doc=Tn,n.splitLines=cr,n.countColumn=re,n.findColumn=ge,n.isWordChar=Je,n.Pass=q,n.signal=Pt,n.Line=os,n.changeEnd=Hi,n.scrollbarModel=$g,n.Pos=fe,n.cmpPos=Ie,n.modes=Qo,n.mimeModes=xr,n.resolveMode=es,n.getMode=ts,n.modeExtensions=$i,n.extendMode=ns,n.copyState=Br,n.startState=rs,n.innerMode=al,n.commands=Ol,n.keyMap=ci,n.keyName=xm,n.isModifierKey=bm,n.lookupKey=ys,n.normalizeKeyMap=aS,n.StringStream=$t,n.SharedTextMarker=Ll,n.TextMarker=Wi,n.LineWidget=Al,n.e_preventDefault=cn,n.e_stopPropagation=Zo,n.e_stop=Oi,n.addClass=Se,n.contains=ce,n.rmClass=N,n.keyNames=qi}_S(Ct),AS(Ct);var RS=\"iter insert remove copy getEditor constructor\".split(\" \");for(var _c in Tn.prototype)Tn.prototype.hasOwnProperty(_c)&&ae(RS,_c)<0&&(Ct.prototype[_c]=(function(n){return function(){return n.apply(this.doc,arguments)}})(Tn.prototype[_c]));return yr(Tn),Ct.inputStyles={textarea:Wt,contenteditable:yt},Ct.defineMode=function(n){!Ct.defaults.mode&&n!=\"null\"&&(Ct.defaults.mode=n),kr.apply(this,arguments)},Ct.defineMIME=bo,Ct.defineMode(\"null\",function(){return{token:function(n){return n.skipToEnd()}}}),Ct.defineMIME(\"text/plain\",\"null\"),Ct.defineExtension=function(n,i){Ct.prototype[n]=i},Ct.defineDocExtension=function(n,i){Tn.prototype[n]=i},Ct.fromTextArea=OS,PS(Ct),Ct.version=\"5.65.18\",Ct}))})(Yc)),Yc.exports}var ML=vo();const NL=ax(ML);var Ad={},Er={};const OL=\"Á\",PL=\"á\",RL=\"Ă\",$L=\"ă\",IL=\"∾\",DL=\"∿\",zL=\"∾̳\",FL=\"Â\",HL=\"â\",BL=\"´\",WL=\"А\",qL=\"а\",jL=\"Æ\",UL=\"æ\",VL=\"⁡\",GL=\"𝔄\",KL=\"𝔞\",XL=\"À\",YL=\"à\",ZL=\"ℵ\",JL=\"ℵ\",QL=\"Α\",eM=\"α\",tM=\"Ā\",nM=\"ā\",rM=\"⨿\",iM=\"&\",oM=\"&\",sM=\"⩕\",lM=\"⩓\",aM=\"∧\",cM=\"⩜\",uM=\"⩘\",fM=\"⩚\",dM=\"∠\",hM=\"⦤\",pM=\"∠\",gM=\"⦨\",mM=\"⦩\",vM=\"⦪\",yM=\"⦫\",bM=\"⦬\",wM=\"⦭\",xM=\"⦮\",kM=\"⦯\",SM=\"∡\",_M=\"∟\",TM=\"⊾\",CM=\"⦝\",EM=\"∢\",AM=\"Å\",LM=\"⍼\",MM=\"Ą\",NM=\"ą\",OM=\"𝔸\",PM=\"𝕒\",RM=\"⩯\",$M=\"≈\",IM=\"⩰\",DM=\"≊\",zM=\"≋\",FM=\"'\",HM=\"⁡\",BM=\"≈\",WM=\"≊\",qM=\"Å\",jM=\"å\",UM=\"𝒜\",VM=\"𝒶\",GM=\"≔\",KM=\"*\",XM=\"≈\",YM=\"≍\",ZM=\"Ã\",JM=\"ã\",QM=\"Ä\",eN=\"ä\",tN=\"∳\",nN=\"⨑\",rN=\"≌\",iN=\"϶\",oN=\"‵\",sN=\"∽\",lN=\"⋍\",aN=\"∖\",cN=\"⫧\",uN=\"⊽\",fN=\"⌅\",dN=\"⌆\",hN=\"⌅\",pN=\"⎵\",gN=\"⎶\",mN=\"≌\",vN=\"Б\",yN=\"б\",bN=\"„\",wN=\"∵\",xN=\"∵\",kN=\"∵\",SN=\"⦰\",_N=\"϶\",TN=\"ℬ\",CN=\"ℬ\",EN=\"Β\",AN=\"β\",LN=\"ℶ\",MN=\"≬\",NN=\"𝔅\",ON=\"𝔟\",PN=\"⋂\",RN=\"◯\",$N=\"⋃\",IN=\"⨀\",DN=\"⨁\",zN=\"⨂\",FN=\"⨆\",HN=\"★\",BN=\"▽\",WN=\"△\",qN=\"⨄\",jN=\"⋁\",UN=\"⋀\",VN=\"⤍\",GN=\"⧫\",KN=\"▪\",XN=\"▴\",YN=\"▾\",ZN=\"◂\",JN=\"▸\",QN=\"␣\",e2=\"▒\",t2=\"░\",n2=\"▓\",r2=\"█\",i2=\"=⃥\",o2=\"≡⃥\",s2=\"⫭\",l2=\"⌐\",a2=\"𝔹\",c2=\"𝕓\",u2=\"⊥\",f2=\"⊥\",d2=\"⋈\",h2=\"⧉\",p2=\"┐\",g2=\"╕\",m2=\"╖\",v2=\"╗\",y2=\"┌\",b2=\"╒\",w2=\"╓\",x2=\"╔\",k2=\"─\",S2=\"═\",_2=\"┬\",T2=\"╤\",C2=\"╥\",E2=\"╦\",A2=\"┴\",L2=\"╧\",M2=\"╨\",N2=\"╩\",O2=\"⊟\",P2=\"⊞\",R2=\"⊠\",$2=\"┘\",I2=\"╛\",D2=\"╜\",z2=\"╝\",F2=\"└\",H2=\"╘\",B2=\"╙\",W2=\"╚\",q2=\"│\",j2=\"║\",U2=\"┼\",V2=\"╪\",G2=\"╫\",K2=\"╬\",X2=\"┤\",Y2=\"╡\",Z2=\"╢\",J2=\"╣\",Q2=\"├\",eO=\"╞\",tO=\"╟\",nO=\"╠\",rO=\"‵\",iO=\"˘\",oO=\"˘\",sO=\"¦\",lO=\"𝒷\",aO=\"ℬ\",cO=\"⁏\",uO=\"∽\",fO=\"⋍\",dO=\"⧅\",hO=\"\\\\\",pO=\"⟈\",gO=\"•\",mO=\"•\",vO=\"≎\",yO=\"⪮\",bO=\"≏\",wO=\"≎\",xO=\"≏\",kO=\"Ć\",SO=\"ć\",_O=\"⩄\",TO=\"⩉\",CO=\"⩋\",EO=\"∩\",AO=\"⋒\",LO=\"⩇\",MO=\"⩀\",NO=\"ⅅ\",OO=\"∩︀\",PO=\"⁁\",RO=\"ˇ\",$O=\"ℭ\",IO=\"⩍\",DO=\"Č\",zO=\"č\",FO=\"Ç\",HO=\"ç\",BO=\"Ĉ\",WO=\"ĉ\",qO=\"∰\",jO=\"⩌\",UO=\"⩐\",VO=\"Ċ\",GO=\"ċ\",KO=\"¸\",XO=\"¸\",YO=\"⦲\",ZO=\"¢\",JO=\"·\",QO=\"·\",eP=\"𝔠\",tP=\"ℭ\",nP=\"Ч\",rP=\"ч\",iP=\"✓\",oP=\"✓\",sP=\"Χ\",lP=\"χ\",aP=\"ˆ\",cP=\"≗\",uP=\"↺\",fP=\"↻\",dP=\"⊛\",hP=\"⊚\",pP=\"⊝\",gP=\"⊙\",mP=\"®\",vP=\"Ⓢ\",yP=\"⊖\",bP=\"⊕\",wP=\"⊗\",xP=\"○\",kP=\"⧃\",SP=\"≗\",_P=\"⨐\",TP=\"⫯\",CP=\"⧂\",EP=\"∲\",AP=\"”\",LP=\"’\",MP=\"♣\",NP=\"♣\",OP=\":\",PP=\"∷\",RP=\"⩴\",$P=\"≔\",IP=\"≔\",DP=\",\",zP=\"@\",FP=\"∁\",HP=\"∘\",BP=\"∁\",WP=\"ℂ\",qP=\"≅\",jP=\"⩭\",UP=\"≡\",VP=\"∮\",GP=\"∯\",KP=\"∮\",XP=\"𝕔\",YP=\"ℂ\",ZP=\"∐\",JP=\"∐\",QP=\"©\",eR=\"©\",tR=\"℗\",nR=\"∳\",rR=\"↵\",iR=\"✗\",oR=\"⨯\",sR=\"𝒞\",lR=\"𝒸\",aR=\"⫏\",cR=\"⫑\",uR=\"⫐\",fR=\"⫒\",dR=\"⋯\",hR=\"⤸\",pR=\"⤵\",gR=\"⋞\",mR=\"⋟\",vR=\"↶\",yR=\"⤽\",bR=\"⩈\",wR=\"⩆\",xR=\"≍\",kR=\"∪\",SR=\"⋓\",_R=\"⩊\",TR=\"⊍\",CR=\"⩅\",ER=\"∪︀\",AR=\"↷\",LR=\"⤼\",MR=\"⋞\",NR=\"⋟\",OR=\"⋎\",PR=\"⋏\",RR=\"¤\",$R=\"↶\",IR=\"↷\",DR=\"⋎\",zR=\"⋏\",FR=\"∲\",HR=\"∱\",BR=\"⌭\",WR=\"†\",qR=\"‡\",jR=\"ℸ\",UR=\"↓\",VR=\"↡\",GR=\"⇓\",KR=\"‐\",XR=\"⫤\",YR=\"⊣\",ZR=\"⤏\",JR=\"˝\",QR=\"Ď\",e$=\"ď\",t$=\"Д\",n$=\"д\",r$=\"‡\",i$=\"⇊\",o$=\"ⅅ\",s$=\"ⅆ\",l$=\"⤑\",a$=\"⩷\",c$=\"°\",u$=\"∇\",f$=\"Δ\",d$=\"δ\",h$=\"⦱\",p$=\"⥿\",g$=\"𝔇\",m$=\"𝔡\",v$=\"⥥\",y$=\"⇃\",b$=\"⇂\",w$=\"´\",x$=\"˙\",k$=\"˝\",S$=\"`\",_$=\"˜\",T$=\"⋄\",C$=\"⋄\",E$=\"⋄\",A$=\"♦\",L$=\"♦\",M$=\"¨\",N$=\"ⅆ\",O$=\"ϝ\",P$=\"⋲\",R$=\"÷\",$$=\"÷\",I$=\"⋇\",D$=\"⋇\",z$=\"Ђ\",F$=\"ђ\",H$=\"⌞\",B$=\"⌍\",W$=\"$\",q$=\"𝔻\",j$=\"𝕕\",U$=\"¨\",V$=\"˙\",G$=\"⃜\",K$=\"≐\",X$=\"≑\",Y$=\"≐\",Z$=\"∸\",J$=\"∔\",Q$=\"⊡\",eI=\"⌆\",tI=\"∯\",nI=\"¨\",rI=\"⇓\",iI=\"⇐\",oI=\"⇔\",sI=\"⫤\",lI=\"⟸\",aI=\"⟺\",cI=\"⟹\",uI=\"⇒\",fI=\"⊨\",dI=\"⇑\",hI=\"⇕\",pI=\"∥\",gI=\"⤓\",mI=\"↓\",vI=\"↓\",yI=\"⇓\",bI=\"⇵\",wI=\"̑\",xI=\"⇊\",kI=\"⇃\",SI=\"⇂\",_I=\"⥐\",TI=\"⥞\",CI=\"⥖\",EI=\"↽\",AI=\"⥟\",LI=\"⥗\",MI=\"⇁\",NI=\"↧\",OI=\"⊤\",PI=\"⤐\",RI=\"⌟\",$I=\"⌌\",II=\"𝒟\",DI=\"𝒹\",zI=\"Ѕ\",FI=\"ѕ\",HI=\"⧶\",BI=\"Đ\",WI=\"đ\",qI=\"⋱\",jI=\"▿\",UI=\"▾\",VI=\"⇵\",GI=\"⥯\",KI=\"⦦\",XI=\"Џ\",YI=\"џ\",ZI=\"⟿\",JI=\"É\",QI=\"é\",eD=\"⩮\",tD=\"Ě\",nD=\"ě\",rD=\"Ê\",iD=\"ê\",oD=\"≖\",sD=\"≕\",lD=\"Э\",aD=\"э\",cD=\"⩷\",uD=\"Ė\",fD=\"ė\",dD=\"≑\",hD=\"ⅇ\",pD=\"≒\",gD=\"𝔈\",mD=\"𝔢\",vD=\"⪚\",yD=\"È\",bD=\"è\",wD=\"⪖\",xD=\"⪘\",kD=\"⪙\",SD=\"∈\",_D=\"⏧\",TD=\"ℓ\",CD=\"⪕\",ED=\"⪗\",AD=\"Ē\",LD=\"ē\",MD=\"∅\",ND=\"∅\",OD=\"◻\",PD=\"∅\",RD=\"▫\",$D=\" \",ID=\" \",DD=\" \",zD=\"Ŋ\",FD=\"ŋ\",HD=\" \",BD=\"Ę\",WD=\"ę\",qD=\"𝔼\",jD=\"𝕖\",UD=\"⋕\",VD=\"⧣\",GD=\"⩱\",KD=\"ε\",XD=\"Ε\",YD=\"ε\",ZD=\"ϵ\",JD=\"≖\",QD=\"≕\",ez=\"≂\",tz=\"⪖\",nz=\"⪕\",rz=\"⩵\",iz=\"=\",oz=\"≂\",sz=\"≟\",lz=\"⇌\",az=\"≡\",cz=\"⩸\",uz=\"⧥\",fz=\"⥱\",dz=\"≓\",hz=\"ℯ\",pz=\"ℰ\",gz=\"≐\",mz=\"⩳\",vz=\"≂\",yz=\"Η\",bz=\"η\",wz=\"Ð\",xz=\"ð\",kz=\"Ë\",Sz=\"ë\",_z=\"€\",Tz=\"!\",Cz=\"∃\",Ez=\"∃\",Az=\"ℰ\",Lz=\"ⅇ\",Mz=\"ⅇ\",Nz=\"≒\",Oz=\"Ф\",Pz=\"ф\",Rz=\"♀\",$z=\"ﬃ\",Iz=\"ﬀ\",Dz=\"ﬄ\",zz=\"𝔉\",Fz=\"𝔣\",Hz=\"ﬁ\",Bz=\"◼\",Wz=\"▪\",qz=\"fj\",jz=\"♭\",Uz=\"ﬂ\",Vz=\"▱\",Gz=\"ƒ\",Kz=\"𝔽\",Xz=\"𝕗\",Yz=\"∀\",Zz=\"∀\",Jz=\"⋔\",Qz=\"⫙\",eF=\"ℱ\",tF=\"⨍\",nF=\"½\",rF=\"⅓\",iF=\"¼\",oF=\"⅕\",sF=\"⅙\",lF=\"⅛\",aF=\"⅔\",cF=\"⅖\",uF=\"¾\",fF=\"⅗\",dF=\"⅜\",hF=\"⅘\",pF=\"⅚\",gF=\"⅝\",mF=\"⅞\",vF=\"⁄\",yF=\"⌢\",bF=\"𝒻\",wF=\"ℱ\",xF=\"ǵ\",kF=\"Γ\",SF=\"γ\",_F=\"Ϝ\",TF=\"ϝ\",CF=\"⪆\",EF=\"Ğ\",AF=\"ğ\",LF=\"Ģ\",MF=\"Ĝ\",NF=\"ĝ\",OF=\"Г\",PF=\"г\",RF=\"Ġ\",$F=\"ġ\",IF=\"≥\",DF=\"≧\",zF=\"⪌\",FF=\"⋛\",HF=\"≥\",BF=\"≧\",WF=\"⩾\",qF=\"⪩\",jF=\"⩾\",UF=\"⪀\",VF=\"⪂\",GF=\"⪄\",KF=\"⋛︀\",XF=\"⪔\",YF=\"𝔊\",ZF=\"𝔤\",JF=\"≫\",QF=\"⋙\",eH=\"⋙\",tH=\"ℷ\",nH=\"Ѓ\",rH=\"ѓ\",iH=\"⪥\",oH=\"≷\",sH=\"⪒\",lH=\"⪤\",aH=\"⪊\",cH=\"⪊\",uH=\"⪈\",fH=\"≩\",dH=\"⪈\",hH=\"≩\",pH=\"⋧\",gH=\"𝔾\",mH=\"𝕘\",vH=\"`\",yH=\"≥\",bH=\"⋛\",wH=\"≧\",xH=\"⪢\",kH=\"≷\",SH=\"⩾\",_H=\"≳\",TH=\"𝒢\",CH=\"ℊ\",EH=\"≳\",AH=\"⪎\",LH=\"⪐\",MH=\"⪧\",NH=\"⩺\",OH=\">\",PH=\">\",RH=\"≫\",$H=\"⋗\",IH=\"⦕\",DH=\"⩼\",zH=\"⪆\",FH=\"⥸\",HH=\"⋗\",BH=\"⋛\",WH=\"⪌\",qH=\"≷\",jH=\"≳\",UH=\"≩︀\",VH=\"≩︀\",GH=\"ˇ\",KH=\" \",XH=\"½\",YH=\"ℋ\",ZH=\"Ъ\",JH=\"ъ\",QH=\"⥈\",e3=\"↔\",t3=\"⇔\",n3=\"↭\",r3=\"^\",i3=\"ℏ\",o3=\"Ĥ\",s3=\"ĥ\",l3=\"♥\",a3=\"♥\",c3=\"…\",u3=\"⊹\",f3=\"𝔥\",d3=\"ℌ\",h3=\"ℋ\",p3=\"⤥\",g3=\"⤦\",m3=\"⇿\",v3=\"∻\",y3=\"↩\",b3=\"↪\",w3=\"𝕙\",x3=\"ℍ\",k3=\"―\",S3=\"─\",_3=\"𝒽\",T3=\"ℋ\",C3=\"ℏ\",E3=\"Ħ\",A3=\"ħ\",L3=\"≎\",M3=\"≏\",N3=\"⁃\",O3=\"‐\",P3=\"Í\",R3=\"í\",$3=\"⁣\",I3=\"Î\",D3=\"î\",z3=\"И\",F3=\"и\",H3=\"İ\",B3=\"Е\",W3=\"е\",q3=\"¡\",j3=\"⇔\",U3=\"𝔦\",V3=\"ℑ\",G3=\"Ì\",K3=\"ì\",X3=\"ⅈ\",Y3=\"⨌\",Z3=\"∭\",J3=\"⧜\",Q3=\"℩\",eB=\"Ĳ\",tB=\"ĳ\",nB=\"Ī\",rB=\"ī\",iB=\"ℑ\",oB=\"ⅈ\",sB=\"ℐ\",lB=\"ℑ\",aB=\"ı\",cB=\"ℑ\",uB=\"⊷\",fB=\"Ƶ\",dB=\"⇒\",hB=\"℅\",pB=\"∞\",gB=\"⧝\",mB=\"ı\",vB=\"⊺\",yB=\"∫\",bB=\"∬\",wB=\"ℤ\",xB=\"∫\",kB=\"⊺\",SB=\"⋂\",_B=\"⨗\",TB=\"⨼\",CB=\"⁣\",EB=\"⁢\",AB=\"Ё\",LB=\"ё\",MB=\"Į\",NB=\"į\",OB=\"𝕀\",PB=\"𝕚\",RB=\"Ι\",$B=\"ι\",IB=\"⨼\",DB=\"¿\",zB=\"𝒾\",FB=\"ℐ\",HB=\"∈\",BB=\"⋵\",WB=\"⋹\",qB=\"⋴\",jB=\"⋳\",UB=\"∈\",VB=\"⁢\",GB=\"Ĩ\",KB=\"ĩ\",XB=\"І\",YB=\"і\",ZB=\"Ï\",JB=\"ï\",QB=\"Ĵ\",e5=\"ĵ\",t5=\"Й\",n5=\"й\",r5=\"𝔍\",i5=\"𝔧\",o5=\"ȷ\",s5=\"𝕁\",l5=\"𝕛\",a5=\"𝒥\",c5=\"𝒿\",u5=\"Ј\",f5=\"ј\",d5=\"Є\",h5=\"є\",p5=\"Κ\",g5=\"κ\",m5=\"ϰ\",v5=\"Ķ\",y5=\"ķ\",b5=\"К\",w5=\"к\",x5=\"𝔎\",k5=\"𝔨\",S5=\"ĸ\",_5=\"Х\",T5=\"х\",C5=\"Ќ\",E5=\"ќ\",A5=\"𝕂\",L5=\"𝕜\",M5=\"𝒦\",N5=\"𝓀\",O5=\"⇚\",P5=\"Ĺ\",R5=\"ĺ\",$5=\"⦴\",I5=\"ℒ\",D5=\"Λ\",z5=\"λ\",F5=\"⟨\",H5=\"⟪\",B5=\"⦑\",W5=\"⟨\",q5=\"⪅\",j5=\"ℒ\",U5=\"«\",V5=\"⇤\",G5=\"⤟\",K5=\"←\",X5=\"↞\",Y5=\"⇐\",Z5=\"⤝\",J5=\"↩\",Q5=\"↫\",e8=\"⤹\",t8=\"⥳\",n8=\"↢\",r8=\"⤙\",i8=\"⤛\",o8=\"⪫\",s8=\"⪭\",l8=\"⪭︀\",a8=\"⤌\",c8=\"⤎\",u8=\"❲\",f8=\"{\",d8=\"[\",h8=\"⦋\",p8=\"⦏\",g8=\"⦍\",m8=\"Ľ\",v8=\"ľ\",y8=\"Ļ\",b8=\"ļ\",w8=\"⌈\",x8=\"{\",k8=\"Л\",S8=\"л\",_8=\"⤶\",T8=\"“\",C8=\"„\",E8=\"⥧\",A8=\"⥋\",L8=\"↲\",M8=\"≤\",N8=\"≦\",O8=\"⟨\",P8=\"⇤\",R8=\"←\",$8=\"←\",I8=\"⇐\",D8=\"⇆\",z8=\"↢\",F8=\"⌈\",H8=\"⟦\",B8=\"⥡\",W8=\"⥙\",q8=\"⇃\",j8=\"⌊\",U8=\"↽\",V8=\"↼\",G8=\"⇇\",K8=\"↔\",X8=\"↔\",Y8=\"⇔\",Z8=\"⇆\",J8=\"⇋\",Q8=\"↭\",eW=\"⥎\",tW=\"↤\",nW=\"⊣\",rW=\"⥚\",iW=\"⋋\",oW=\"⧏\",sW=\"⊲\",lW=\"⊴\",aW=\"⥑\",cW=\"⥠\",uW=\"⥘\",fW=\"↿\",dW=\"⥒\",hW=\"↼\",pW=\"⪋\",gW=\"⋚\",mW=\"≤\",vW=\"≦\",yW=\"⩽\",bW=\"⪨\",wW=\"⩽\",xW=\"⩿\",kW=\"⪁\",SW=\"⪃\",_W=\"⋚︀\",TW=\"⪓\",CW=\"⪅\",EW=\"⋖\",AW=\"⋚\",LW=\"⪋\",MW=\"⋚\",NW=\"≦\",OW=\"≶\",PW=\"≶\",RW=\"⪡\",$W=\"≲\",IW=\"⩽\",DW=\"≲\",zW=\"⥼\",FW=\"⌊\",HW=\"𝔏\",BW=\"𝔩\",WW=\"≶\",qW=\"⪑\",jW=\"⥢\",UW=\"↽\",VW=\"↼\",GW=\"⥪\",KW=\"▄\",XW=\"Љ\",YW=\"љ\",ZW=\"⇇\",JW=\"≪\",QW=\"⋘\",e4=\"⌞\",t4=\"⇚\",n4=\"⥫\",r4=\"◺\",i4=\"Ŀ\",o4=\"ŀ\",s4=\"⎰\",l4=\"⎰\",a4=\"⪉\",c4=\"⪉\",u4=\"⪇\",f4=\"≨\",d4=\"⪇\",h4=\"≨\",p4=\"⋦\",g4=\"⟬\",m4=\"⇽\",v4=\"⟦\",y4=\"⟵\",b4=\"⟵\",w4=\"⟸\",x4=\"⟷\",k4=\"⟷\",S4=\"⟺\",_4=\"⟼\",T4=\"⟶\",C4=\"⟶\",E4=\"⟹\",A4=\"↫\",L4=\"↬\",M4=\"⦅\",N4=\"𝕃\",O4=\"𝕝\",P4=\"⨭\",R4=\"⨴\",$4=\"∗\",I4=\"_\",D4=\"↙\",z4=\"↘\",F4=\"◊\",H4=\"◊\",B4=\"⧫\",W4=\"(\",q4=\"⦓\",j4=\"⇆\",U4=\"⌟\",V4=\"⇋\",G4=\"⥭\",K4=\"‎\",X4=\"⊿\",Y4=\"‹\",Z4=\"𝓁\",J4=\"ℒ\",Q4=\"↰\",eq=\"↰\",tq=\"≲\",nq=\"⪍\",rq=\"⪏\",iq=\"[\",oq=\"‘\",sq=\"‚\",lq=\"Ł\",aq=\"ł\",cq=\"⪦\",uq=\"⩹\",fq=\"<\",dq=\"<\",hq=\"≪\",pq=\"⋖\",gq=\"⋋\",mq=\"⋉\",vq=\"⥶\",yq=\"⩻\",bq=\"◃\",wq=\"⊴\",xq=\"◂\",kq=\"⦖\",Sq=\"⥊\",_q=\"⥦\",Tq=\"≨︀\",Cq=\"≨︀\",Eq=\"¯\",Aq=\"♂\",Lq=\"✠\",Mq=\"✠\",Nq=\"↦\",Oq=\"↦\",Pq=\"↧\",Rq=\"↤\",$q=\"↥\",Iq=\"▮\",Dq=\"⨩\",zq=\"М\",Fq=\"м\",Hq=\"—\",Bq=\"∺\",Wq=\"∡\",qq=\" \",jq=\"ℳ\",Uq=\"𝔐\",Vq=\"𝔪\",Gq=\"℧\",Kq=\"µ\",Xq=\"*\",Yq=\"⫰\",Zq=\"∣\",Jq=\"·\",Qq=\"⊟\",ej=\"−\",tj=\"∸\",nj=\"⨪\",rj=\"∓\",ij=\"⫛\",oj=\"…\",sj=\"∓\",lj=\"⊧\",aj=\"𝕄\",cj=\"𝕞\",uj=\"∓\",fj=\"𝓂\",dj=\"ℳ\",hj=\"∾\",pj=\"Μ\",gj=\"μ\",mj=\"⊸\",vj=\"⊸\",yj=\"∇\",bj=\"Ń\",wj=\"ń\",xj=\"∠⃒\",kj=\"≉\",Sj=\"⩰̸\",_j=\"≋̸\",Tj=\"ŉ\",Cj=\"≉\",Ej=\"♮\",Aj=\"ℕ\",Lj=\"♮\",Mj=\" \",Nj=\"≎̸\",Oj=\"≏̸\",Pj=\"⩃\",Rj=\"Ň\",$j=\"ň\",Ij=\"Ņ\",Dj=\"ņ\",zj=\"≇\",Fj=\"⩭̸\",Hj=\"⩂\",Bj=\"Н\",Wj=\"н\",qj=\"–\",jj=\"⤤\",Uj=\"↗\",Vj=\"⇗\",Gj=\"↗\",Kj=\"≠\",Xj=\"≐̸\",Yj=\"​\",Zj=\"​\",Jj=\"​\",Qj=\"​\",eU=\"≢\",tU=\"⤨\",nU=\"≂̸\",rU=\"≫\",iU=\"≪\",oU=`\n`,sU=\"∄\",lU=\"∄\",aU=\"𝔑\",cU=\"𝔫\",uU=\"≧̸\",fU=\"≱\",dU=\"≱\",hU=\"≧̸\",pU=\"⩾̸\",gU=\"⩾̸\",mU=\"⋙̸\",vU=\"≵\",yU=\"≫⃒\",bU=\"≯\",wU=\"≯\",xU=\"≫̸\",kU=\"↮\",SU=\"⇎\",_U=\"⫲\",TU=\"∋\",CU=\"⋼\",EU=\"⋺\",AU=\"∋\",LU=\"Њ\",MU=\"њ\",NU=\"↚\",OU=\"⇍\",PU=\"‥\",RU=\"≦̸\",$U=\"≰\",IU=\"↚\",DU=\"⇍\",zU=\"↮\",FU=\"⇎\",HU=\"≰\",BU=\"≦̸\",WU=\"⩽̸\",qU=\"⩽̸\",jU=\"≮\",UU=\"⋘̸\",VU=\"≴\",GU=\"≪⃒\",KU=\"≮\",XU=\"⋪\",YU=\"⋬\",ZU=\"≪̸\",JU=\"∤\",QU=\"⁠\",e6=\" \",t6=\"𝕟\",n6=\"ℕ\",r6=\"⫬\",i6=\"¬\",o6=\"≢\",s6=\"≭\",l6=\"∦\",a6=\"∉\",c6=\"≠\",u6=\"≂̸\",f6=\"∄\",d6=\"≯\",h6=\"≱\",p6=\"≧̸\",g6=\"≫̸\",m6=\"≹\",v6=\"⩾̸\",y6=\"≵\",b6=\"≎̸\",w6=\"≏̸\",x6=\"∉\",k6=\"⋵̸\",S6=\"⋹̸\",_6=\"∉\",T6=\"⋷\",C6=\"⋶\",E6=\"⧏̸\",A6=\"⋪\",L6=\"⋬\",M6=\"≮\",N6=\"≰\",O6=\"≸\",P6=\"≪̸\",R6=\"⩽̸\",$6=\"≴\",I6=\"⪢̸\",D6=\"⪡̸\",z6=\"∌\",F6=\"∌\",H6=\"⋾\",B6=\"⋽\",W6=\"⊀\",q6=\"⪯̸\",j6=\"⋠\",U6=\"∌\",V6=\"⧐̸\",G6=\"⋫\",K6=\"⋭\",X6=\"⊏̸\",Y6=\"⋢\",Z6=\"⊐̸\",J6=\"⋣\",Q6=\"⊂⃒\",eV=\"⊈\",tV=\"⊁\",nV=\"⪰̸\",rV=\"⋡\",iV=\"≿̸\",oV=\"⊃⃒\",sV=\"⊉\",lV=\"≁\",aV=\"≄\",cV=\"≇\",uV=\"≉\",fV=\"∤\",dV=\"∦\",hV=\"∦\",pV=\"⫽⃥\",gV=\"∂̸\",mV=\"⨔\",vV=\"⊀\",yV=\"⋠\",bV=\"⊀\",wV=\"⪯̸\",xV=\"⪯̸\",kV=\"⤳̸\",SV=\"↛\",_V=\"⇏\",TV=\"↝̸\",CV=\"↛\",EV=\"⇏\",AV=\"⋫\",LV=\"⋭\",MV=\"⊁\",NV=\"⋡\",OV=\"⪰̸\",PV=\"𝒩\",RV=\"𝓃\",$V=\"∤\",IV=\"∦\",DV=\"≁\",zV=\"≄\",FV=\"≄\",HV=\"∤\",BV=\"∦\",WV=\"⋢\",qV=\"⋣\",jV=\"⊄\",UV=\"⫅̸\",VV=\"⊈\",GV=\"⊂⃒\",KV=\"⊈\",XV=\"⫅̸\",YV=\"⊁\",ZV=\"⪰̸\",JV=\"⊅\",QV=\"⫆̸\",eG=\"⊉\",tG=\"⊃⃒\",nG=\"⊉\",rG=\"⫆̸\",iG=\"≹\",oG=\"Ñ\",sG=\"ñ\",lG=\"≸\",aG=\"⋪\",cG=\"⋬\",uG=\"⋫\",fG=\"⋭\",dG=\"Ν\",hG=\"ν\",pG=\"#\",gG=\"№\",mG=\" \",vG=\"≍⃒\",yG=\"⊬\",bG=\"⊭\",wG=\"⊮\",xG=\"⊯\",kG=\"≥⃒\",SG=\">⃒\",_G=\"⤄\",TG=\"⧞\",CG=\"⤂\",EG=\"≤⃒\",AG=\"<⃒\",LG=\"⊴⃒\",MG=\"⤃\",NG=\"⊵⃒\",OG=\"∼⃒\",PG=\"⤣\",RG=\"↖\",$G=\"⇖\",IG=\"↖\",DG=\"⤧\",zG=\"Ó\",FG=\"ó\",HG=\"⊛\",BG=\"Ô\",WG=\"ô\",qG=\"⊚\",jG=\"О\",UG=\"о\",VG=\"⊝\",GG=\"Ő\",KG=\"ő\",XG=\"⨸\",YG=\"⊙\",ZG=\"⦼\",JG=\"Œ\",QG=\"œ\",e9=\"⦿\",t9=\"𝔒\",n9=\"𝔬\",r9=\"˛\",i9=\"Ò\",o9=\"ò\",s9=\"⧁\",l9=\"⦵\",a9=\"Ω\",c9=\"∮\",u9=\"↺\",f9=\"⦾\",d9=\"⦻\",h9=\"‾\",p9=\"⧀\",g9=\"Ō\",m9=\"ō\",v9=\"Ω\",y9=\"ω\",b9=\"Ο\",w9=\"ο\",x9=\"⦶\",k9=\"⊖\",S9=\"𝕆\",_9=\"𝕠\",T9=\"⦷\",C9=\"“\",E9=\"‘\",A9=\"⦹\",L9=\"⊕\",M9=\"↻\",N9=\"⩔\",O9=\"∨\",P9=\"⩝\",R9=\"ℴ\",$9=\"ℴ\",I9=\"ª\",D9=\"º\",z9=\"⊶\",F9=\"⩖\",H9=\"⩗\",B9=\"⩛\",W9=\"Ⓢ\",q9=\"𝒪\",j9=\"ℴ\",U9=\"Ø\",V9=\"ø\",G9=\"⊘\",K9=\"Õ\",X9=\"õ\",Y9=\"⨶\",Z9=\"⨷\",J9=\"⊗\",Q9=\"Ö\",eK=\"ö\",tK=\"⌽\",nK=\"‾\",rK=\"⏞\",iK=\"⎴\",oK=\"⏜\",sK=\"¶\",lK=\"∥\",aK=\"∥\",cK=\"⫳\",uK=\"⫽\",fK=\"∂\",dK=\"∂\",hK=\"П\",pK=\"п\",gK=\"%\",mK=\".\",vK=\"‰\",yK=\"⊥\",bK=\"‱\",wK=\"𝔓\",xK=\"𝔭\",kK=\"Φ\",SK=\"φ\",_K=\"ϕ\",TK=\"ℳ\",CK=\"☎\",EK=\"Π\",AK=\"π\",LK=\"⋔\",MK=\"ϖ\",NK=\"ℏ\",OK=\"ℎ\",PK=\"ℏ\",RK=\"⨣\",$K=\"⊞\",IK=\"⨢\",DK=\"+\",zK=\"∔\",FK=\"⨥\",HK=\"⩲\",BK=\"±\",WK=\"±\",qK=\"⨦\",jK=\"⨧\",UK=\"±\",VK=\"ℌ\",GK=\"⨕\",KK=\"𝕡\",XK=\"ℙ\",YK=\"£\",ZK=\"⪷\",JK=\"⪻\",QK=\"≺\",e7=\"≼\",t7=\"⪷\",n7=\"≺\",r7=\"≼\",i7=\"≺\",o7=\"⪯\",s7=\"≼\",l7=\"≾\",a7=\"⪯\",c7=\"⪹\",u7=\"⪵\",f7=\"⋨\",d7=\"⪯\",h7=\"⪳\",p7=\"≾\",g7=\"′\",m7=\"″\",v7=\"ℙ\",y7=\"⪹\",b7=\"⪵\",w7=\"⋨\",x7=\"∏\",k7=\"∏\",S7=\"⌮\",_7=\"⌒\",T7=\"⌓\",C7=\"∝\",E7=\"∝\",A7=\"∷\",L7=\"∝\",M7=\"≾\",N7=\"⊰\",O7=\"𝒫\",P7=\"𝓅\",R7=\"Ψ\",$7=\"ψ\",I7=\" \",D7=\"𝔔\",z7=\"𝔮\",F7=\"⨌\",H7=\"𝕢\",B7=\"ℚ\",W7=\"⁗\",q7=\"𝒬\",j7=\"𝓆\",U7=\"ℍ\",V7=\"⨖\",G7=\"?\",K7=\"≟\",X7='\"',Y7='\"',Z7=\"⇛\",J7=\"∽̱\",Q7=\"Ŕ\",eX=\"ŕ\",tX=\"√\",nX=\"⦳\",rX=\"⟩\",iX=\"⟫\",oX=\"⦒\",sX=\"⦥\",lX=\"⟩\",aX=\"»\",cX=\"⥵\",uX=\"⇥\",fX=\"⤠\",dX=\"⤳\",hX=\"→\",pX=\"↠\",gX=\"⇒\",mX=\"⤞\",vX=\"↪\",yX=\"↬\",bX=\"⥅\",wX=\"⥴\",xX=\"⤖\",kX=\"↣\",SX=\"↝\",_X=\"⤚\",TX=\"⤜\",CX=\"∶\",EX=\"ℚ\",AX=\"⤍\",LX=\"⤏\",MX=\"⤐\",NX=\"❳\",OX=\"}\",PX=\"]\",RX=\"⦌\",$X=\"⦎\",IX=\"⦐\",DX=\"Ř\",zX=\"ř\",FX=\"Ŗ\",HX=\"ŗ\",BX=\"⌉\",WX=\"}\",qX=\"Р\",jX=\"р\",UX=\"⤷\",VX=\"⥩\",GX=\"”\",KX=\"”\",XX=\"↳\",YX=\"ℜ\",ZX=\"ℛ\",JX=\"ℜ\",QX=\"ℝ\",eY=\"ℜ\",tY=\"▭\",nY=\"®\",rY=\"®\",iY=\"∋\",oY=\"⇋\",sY=\"⥯\",lY=\"⥽\",aY=\"⌋\",cY=\"𝔯\",uY=\"ℜ\",fY=\"⥤\",dY=\"⇁\",hY=\"⇀\",pY=\"⥬\",gY=\"Ρ\",mY=\"ρ\",vY=\"ϱ\",yY=\"⟩\",bY=\"⇥\",wY=\"→\",xY=\"→\",kY=\"⇒\",SY=\"⇄\",_Y=\"↣\",TY=\"⌉\",CY=\"⟧\",EY=\"⥝\",AY=\"⥕\",LY=\"⇂\",MY=\"⌋\",NY=\"⇁\",OY=\"⇀\",PY=\"⇄\",RY=\"⇌\",$Y=\"⇉\",IY=\"↝\",DY=\"↦\",zY=\"⊢\",FY=\"⥛\",HY=\"⋌\",BY=\"⧐\",WY=\"⊳\",qY=\"⊵\",jY=\"⥏\",UY=\"⥜\",VY=\"⥔\",GY=\"↾\",KY=\"⥓\",XY=\"⇀\",YY=\"˚\",ZY=\"≓\",JY=\"⇄\",QY=\"⇌\",eZ=\"‏\",tZ=\"⎱\",nZ=\"⎱\",rZ=\"⫮\",iZ=\"⟭\",oZ=\"⇾\",sZ=\"⟧\",lZ=\"⦆\",aZ=\"𝕣\",cZ=\"ℝ\",uZ=\"⨮\",fZ=\"⨵\",dZ=\"⥰\",hZ=\")\",pZ=\"⦔\",gZ=\"⨒\",mZ=\"⇉\",vZ=\"⇛\",yZ=\"›\",bZ=\"𝓇\",wZ=\"ℛ\",xZ=\"↱\",kZ=\"↱\",SZ=\"]\",_Z=\"’\",TZ=\"’\",CZ=\"⋌\",EZ=\"⋊\",AZ=\"▹\",LZ=\"⊵\",MZ=\"▸\",NZ=\"⧎\",OZ=\"⧴\",PZ=\"⥨\",RZ=\"℞\",$Z=\"Ś\",IZ=\"ś\",DZ=\"‚\",zZ=\"⪸\",FZ=\"Š\",HZ=\"š\",BZ=\"⪼\",WZ=\"≻\",qZ=\"≽\",jZ=\"⪰\",UZ=\"⪴\",VZ=\"Ş\",GZ=\"ş\",KZ=\"Ŝ\",XZ=\"ŝ\",YZ=\"⪺\",ZZ=\"⪶\",JZ=\"⋩\",QZ=\"⨓\",eJ=\"≿\",tJ=\"С\",nJ=\"с\",rJ=\"⊡\",iJ=\"⋅\",oJ=\"⩦\",sJ=\"⤥\",lJ=\"↘\",aJ=\"⇘\",cJ=\"↘\",uJ=\"§\",fJ=\";\",dJ=\"⤩\",hJ=\"∖\",pJ=\"∖\",gJ=\"✶\",mJ=\"𝔖\",vJ=\"𝔰\",yJ=\"⌢\",bJ=\"♯\",wJ=\"Щ\",xJ=\"щ\",kJ=\"Ш\",SJ=\"ш\",_J=\"↓\",TJ=\"←\",CJ=\"∣\",EJ=\"∥\",AJ=\"→\",LJ=\"↑\",MJ=\"­\",NJ=\"Σ\",OJ=\"σ\",PJ=\"ς\",RJ=\"ς\",$J=\"∼\",IJ=\"⩪\",DJ=\"≃\",zJ=\"≃\",FJ=\"⪞\",HJ=\"⪠\",BJ=\"⪝\",WJ=\"⪟\",qJ=\"≆\",jJ=\"⨤\",UJ=\"⥲\",VJ=\"←\",GJ=\"∘\",KJ=\"∖\",XJ=\"⨳\",YJ=\"⧤\",ZJ=\"∣\",JJ=\"⌣\",QJ=\"⪪\",eQ=\"⪬\",tQ=\"⪬︀\",nQ=\"Ь\",rQ=\"ь\",iQ=\"⌿\",oQ=\"⧄\",sQ=\"/\",lQ=\"𝕊\",aQ=\"𝕤\",cQ=\"♠\",uQ=\"♠\",fQ=\"∥\",dQ=\"⊓\",hQ=\"⊓︀\",pQ=\"⊔\",gQ=\"⊔︀\",mQ=\"√\",vQ=\"⊏\",yQ=\"⊑\",bQ=\"⊏\",wQ=\"⊑\",xQ=\"⊐\",kQ=\"⊒\",SQ=\"⊐\",_Q=\"⊒\",TQ=\"□\",CQ=\"□\",EQ=\"⊓\",AQ=\"⊏\",LQ=\"⊑\",MQ=\"⊐\",NQ=\"⊒\",OQ=\"⊔\",PQ=\"▪\",RQ=\"□\",$Q=\"▪\",IQ=\"→\",DQ=\"𝒮\",zQ=\"𝓈\",FQ=\"∖\",HQ=\"⌣\",BQ=\"⋆\",WQ=\"⋆\",qQ=\"☆\",jQ=\"★\",UQ=\"ϵ\",VQ=\"ϕ\",GQ=\"¯\",KQ=\"⊂\",XQ=\"⋐\",YQ=\"⪽\",ZQ=\"⫅\",JQ=\"⊆\",QQ=\"⫃\",eee=\"⫁\",tee=\"⫋\",nee=\"⊊\",ree=\"⪿\",iee=\"⥹\",oee=\"⊂\",see=\"⋐\",lee=\"⊆\",aee=\"⫅\",cee=\"⊆\",uee=\"⊊\",fee=\"⫋\",dee=\"⫇\",hee=\"⫕\",pee=\"⫓\",gee=\"⪸\",mee=\"≻\",vee=\"≽\",yee=\"≻\",bee=\"⪰\",wee=\"≽\",xee=\"≿\",kee=\"⪰\",See=\"⪺\",_ee=\"⪶\",Tee=\"⋩\",Cee=\"≿\",Eee=\"∋\",Aee=\"∑\",Lee=\"∑\",Mee=\"♪\",Nee=\"¹\",Oee=\"²\",Pee=\"³\",Ree=\"⊃\",$ee=\"⋑\",Iee=\"⪾\",Dee=\"⫘\",zee=\"⫆\",Fee=\"⊇\",Hee=\"⫄\",Bee=\"⊃\",Wee=\"⊇\",qee=\"⟉\",jee=\"⫗\",Uee=\"⥻\",Vee=\"⫂\",Gee=\"⫌\",Kee=\"⊋\",Xee=\"⫀\",Yee=\"⊃\",Zee=\"⋑\",Jee=\"⊇\",Qee=\"⫆\",ete=\"⊋\",tte=\"⫌\",nte=\"⫈\",rte=\"⫔\",ite=\"⫖\",ote=\"⤦\",ste=\"↙\",lte=\"⇙\",ate=\"↙\",cte=\"⤪\",ute=\"ß\",fte=\"\t\",dte=\"⌖\",hte=\"Τ\",pte=\"τ\",gte=\"⎴\",mte=\"Ť\",vte=\"ť\",yte=\"Ţ\",bte=\"ţ\",wte=\"Т\",xte=\"т\",kte=\"⃛\",Ste=\"⌕\",_te=\"𝔗\",Tte=\"𝔱\",Cte=\"∴\",Ete=\"∴\",Ate=\"∴\",Lte=\"Θ\",Mte=\"θ\",Nte=\"ϑ\",Ote=\"ϑ\",Pte=\"≈\",Rte=\"∼\",$te=\"  \",Ite=\" \",Dte=\" \",zte=\"≈\",Fte=\"∼\",Hte=\"Þ\",Bte=\"þ\",Wte=\"˜\",qte=\"∼\",jte=\"≃\",Ute=\"≅\",Vte=\"≈\",Gte=\"⨱\",Kte=\"⊠\",Xte=\"×\",Yte=\"⨰\",Zte=\"∭\",Jte=\"⤨\",Qte=\"⌶\",ene=\"⫱\",tne=\"⊤\",nne=\"𝕋\",rne=\"𝕥\",ine=\"⫚\",one=\"⤩\",sne=\"‴\",lne=\"™\",ane=\"™\",cne=\"▵\",une=\"▿\",fne=\"◃\",dne=\"⊴\",hne=\"≜\",pne=\"▹\",gne=\"⊵\",mne=\"◬\",vne=\"≜\",yne=\"⨺\",bne=\"⃛\",wne=\"⨹\",xne=\"⧍\",kne=\"⨻\",Sne=\"⏢\",_ne=\"𝒯\",Tne=\"𝓉\",Cne=\"Ц\",Ene=\"ц\",Ane=\"Ћ\",Lne=\"ћ\",Mne=\"Ŧ\",Nne=\"ŧ\",One=\"≬\",Pne=\"↞\",Rne=\"↠\",$ne=\"Ú\",Ine=\"ú\",Dne=\"↑\",zne=\"↟\",Fne=\"⇑\",Hne=\"⥉\",Bne=\"Ў\",Wne=\"ў\",qne=\"Ŭ\",jne=\"ŭ\",Une=\"Û\",Vne=\"û\",Gne=\"У\",Kne=\"у\",Xne=\"⇅\",Yne=\"Ű\",Zne=\"ű\",Jne=\"⥮\",Qne=\"⥾\",ere=\"𝔘\",tre=\"𝔲\",nre=\"Ù\",rre=\"ù\",ire=\"⥣\",ore=\"↿\",sre=\"↾\",lre=\"▀\",are=\"⌜\",cre=\"⌜\",ure=\"⌏\",fre=\"◸\",dre=\"Ū\",hre=\"ū\",pre=\"¨\",gre=\"_\",mre=\"⏟\",vre=\"⎵\",yre=\"⏝\",bre=\"⋃\",wre=\"⊎\",xre=\"Ų\",kre=\"ų\",Sre=\"𝕌\",_re=\"𝕦\",Tre=\"⤒\",Cre=\"↑\",Ere=\"↑\",Are=\"⇑\",Lre=\"⇅\",Mre=\"↕\",Nre=\"↕\",Ore=\"⇕\",Pre=\"⥮\",Rre=\"↿\",$re=\"↾\",Ire=\"⊎\",Dre=\"↖\",zre=\"↗\",Fre=\"υ\",Hre=\"ϒ\",Bre=\"ϒ\",Wre=\"Υ\",qre=\"υ\",jre=\"↥\",Ure=\"⊥\",Vre=\"⇈\",Gre=\"⌝\",Kre=\"⌝\",Xre=\"⌎\",Yre=\"Ů\",Zre=\"ů\",Jre=\"◹\",Qre=\"𝒰\",eie=\"𝓊\",tie=\"⋰\",nie=\"Ũ\",rie=\"ũ\",iie=\"▵\",oie=\"▴\",sie=\"⇈\",lie=\"Ü\",aie=\"ü\",cie=\"⦧\",uie=\"⦜\",fie=\"ϵ\",die=\"ϰ\",hie=\"∅\",pie=\"ϕ\",gie=\"ϖ\",mie=\"∝\",vie=\"↕\",yie=\"⇕\",bie=\"ϱ\",wie=\"ς\",xie=\"⊊︀\",kie=\"⫋︀\",Sie=\"⊋︀\",_ie=\"⫌︀\",Tie=\"ϑ\",Cie=\"⊲\",Eie=\"⊳\",Aie=\"⫨\",Lie=\"⫫\",Mie=\"⫩\",Nie=\"В\",Oie=\"в\",Pie=\"⊢\",Rie=\"⊨\",$ie=\"⊩\",Iie=\"⊫\",Die=\"⫦\",zie=\"⊻\",Fie=\"∨\",Hie=\"⋁\",Bie=\"≚\",Wie=\"⋮\",qie=\"|\",jie=\"‖\",Uie=\"|\",Vie=\"‖\",Gie=\"∣\",Kie=\"|\",Xie=\"❘\",Yie=\"≀\",Zie=\" \",Jie=\"𝔙\",Qie=\"𝔳\",eoe=\"⊲\",toe=\"⊂⃒\",noe=\"⊃⃒\",roe=\"𝕍\",ioe=\"𝕧\",ooe=\"∝\",soe=\"⊳\",loe=\"𝒱\",aoe=\"𝓋\",coe=\"⫋︀\",uoe=\"⊊︀\",foe=\"⫌︀\",doe=\"⊋︀\",hoe=\"⊪\",poe=\"⦚\",goe=\"Ŵ\",moe=\"ŵ\",voe=\"⩟\",yoe=\"∧\",boe=\"⋀\",woe=\"≙\",xoe=\"℘\",koe=\"𝔚\",Soe=\"𝔴\",_oe=\"𝕎\",Toe=\"𝕨\",Coe=\"℘\",Eoe=\"≀\",Aoe=\"≀\",Loe=\"𝒲\",Moe=\"𝓌\",Noe=\"⋂\",Ooe=\"◯\",Poe=\"⋃\",Roe=\"▽\",$oe=\"𝔛\",Ioe=\"𝔵\",Doe=\"⟷\",zoe=\"⟺\",Foe=\"Ξ\",Hoe=\"ξ\",Boe=\"⟵\",Woe=\"⟸\",qoe=\"⟼\",joe=\"⋻\",Uoe=\"⨀\",Voe=\"𝕏\",Goe=\"𝕩\",Koe=\"⨁\",Xoe=\"⨂\",Yoe=\"⟶\",Zoe=\"⟹\",Joe=\"𝒳\",Qoe=\"𝓍\",ese=\"⨆\",tse=\"⨄\",nse=\"△\",rse=\"⋁\",ise=\"⋀\",ose=\"Ý\",sse=\"ý\",lse=\"Я\",ase=\"я\",cse=\"Ŷ\",use=\"ŷ\",fse=\"Ы\",dse=\"ы\",hse=\"¥\",pse=\"𝔜\",gse=\"𝔶\",mse=\"Ї\",vse=\"ї\",yse=\"𝕐\",bse=\"𝕪\",wse=\"𝒴\",xse=\"𝓎\",kse=\"Ю\",Sse=\"ю\",_se=\"ÿ\",Tse=\"Ÿ\",Cse=\"Ź\",Ese=\"ź\",Ase=\"Ž\",Lse=\"ž\",Mse=\"З\",Nse=\"з\",Ose=\"Ż\",Pse=\"ż\",Rse=\"ℨ\",$se=\"​\",Ise=\"Ζ\",Dse=\"ζ\",zse=\"𝔷\",Fse=\"ℨ\",Hse=\"Ж\",Bse=\"ж\",Wse=\"⇝\",qse=\"𝕫\",jse=\"ℤ\",Use=\"𝒵\",Vse=\"𝓏\",Gse=\"‍\",Kse=\"‌\",cx={Aacute:OL,aacute:PL,Abreve:RL,abreve:$L,ac:IL,acd:DL,acE:zL,Acirc:FL,acirc:HL,acute:BL,Acy:WL,acy:qL,AElig:jL,aelig:UL,af:VL,Afr:GL,afr:KL,Agrave:XL,agrave:YL,alefsym:ZL,aleph:JL,Alpha:QL,alpha:eM,Amacr:tM,amacr:nM,amalg:rM,amp:iM,AMP:oM,andand:sM,And:lM,and:aM,andd:cM,andslope:uM,andv:fM,ang:dM,ange:hM,angle:pM,angmsdaa:gM,angmsdab:mM,angmsdac:vM,angmsdad:yM,angmsdae:bM,angmsdaf:wM,angmsdag:xM,angmsdah:kM,angmsd:SM,angrt:_M,angrtvb:TM,angrtvbd:CM,angsph:EM,angst:AM,angzarr:LM,Aogon:MM,aogon:NM,Aopf:OM,aopf:PM,apacir:RM,ap:$M,apE:IM,ape:DM,apid:zM,apos:FM,ApplyFunction:HM,approx:BM,approxeq:WM,Aring:qM,aring:jM,Ascr:UM,ascr:VM,Assign:GM,ast:KM,asymp:XM,asympeq:YM,Atilde:ZM,atilde:JM,Auml:QM,auml:eN,awconint:tN,awint:nN,backcong:rN,backepsilon:iN,backprime:oN,backsim:sN,backsimeq:lN,Backslash:aN,Barv:cN,barvee:uN,barwed:fN,Barwed:dN,barwedge:hN,bbrk:pN,bbrktbrk:gN,bcong:mN,Bcy:vN,bcy:yN,bdquo:bN,becaus:wN,because:xN,Because:kN,bemptyv:SN,bepsi:_N,bernou:TN,Bernoullis:CN,Beta:EN,beta:AN,beth:LN,between:MN,Bfr:NN,bfr:ON,bigcap:PN,bigcirc:RN,bigcup:$N,bigodot:IN,bigoplus:DN,bigotimes:zN,bigsqcup:FN,bigstar:HN,bigtriangledown:BN,bigtriangleup:WN,biguplus:qN,bigvee:jN,bigwedge:UN,bkarow:VN,blacklozenge:GN,blacksquare:KN,blacktriangle:XN,blacktriangledown:YN,blacktriangleleft:ZN,blacktriangleright:JN,blank:QN,blk12:e2,blk14:t2,blk34:n2,block:r2,bne:i2,bnequiv:o2,bNot:s2,bnot:l2,Bopf:a2,bopf:c2,bot:u2,bottom:f2,bowtie:d2,boxbox:h2,boxdl:p2,boxdL:g2,boxDl:m2,boxDL:v2,boxdr:y2,boxdR:b2,boxDr:w2,boxDR:x2,boxh:k2,boxH:S2,boxhd:_2,boxHd:T2,boxhD:C2,boxHD:E2,boxhu:A2,boxHu:L2,boxhU:M2,boxHU:N2,boxminus:O2,boxplus:P2,boxtimes:R2,boxul:$2,boxuL:I2,boxUl:D2,boxUL:z2,boxur:F2,boxuR:H2,boxUr:B2,boxUR:W2,boxv:q2,boxV:j2,boxvh:U2,boxvH:V2,boxVh:G2,boxVH:K2,boxvl:X2,boxvL:Y2,boxVl:Z2,boxVL:J2,boxvr:Q2,boxvR:eO,boxVr:tO,boxVR:nO,bprime:rO,breve:iO,Breve:oO,brvbar:sO,bscr:lO,Bscr:aO,bsemi:cO,bsim:uO,bsime:fO,bsolb:dO,bsol:hO,bsolhsub:pO,bull:gO,bullet:mO,bump:vO,bumpE:yO,bumpe:bO,Bumpeq:wO,bumpeq:xO,Cacute:kO,cacute:SO,capand:_O,capbrcup:TO,capcap:CO,cap:EO,Cap:AO,capcup:LO,capdot:MO,CapitalDifferentialD:NO,caps:OO,caret:PO,caron:RO,Cayleys:$O,ccaps:IO,Ccaron:DO,ccaron:zO,Ccedil:FO,ccedil:HO,Ccirc:BO,ccirc:WO,Cconint:qO,ccups:jO,ccupssm:UO,Cdot:VO,cdot:GO,cedil:KO,Cedilla:XO,cemptyv:YO,cent:ZO,centerdot:JO,CenterDot:QO,cfr:eP,Cfr:tP,CHcy:nP,chcy:rP,check:iP,checkmark:oP,Chi:sP,chi:lP,circ:aP,circeq:cP,circlearrowleft:uP,circlearrowright:fP,circledast:dP,circledcirc:hP,circleddash:pP,CircleDot:gP,circledR:mP,circledS:vP,CircleMinus:yP,CirclePlus:bP,CircleTimes:wP,cir:xP,cirE:kP,cire:SP,cirfnint:_P,cirmid:TP,cirscir:CP,ClockwiseContourIntegral:EP,CloseCurlyDoubleQuote:AP,CloseCurlyQuote:LP,clubs:MP,clubsuit:NP,colon:OP,Colon:PP,Colone:RP,colone:$P,coloneq:IP,comma:DP,commat:zP,comp:FP,compfn:HP,complement:BP,complexes:WP,cong:qP,congdot:jP,Congruent:UP,conint:VP,Conint:GP,ContourIntegral:KP,copf:XP,Copf:YP,coprod:ZP,Coproduct:JP,copy:QP,COPY:eR,copysr:tR,CounterClockwiseContourIntegral:nR,crarr:rR,cross:iR,Cross:oR,Cscr:sR,cscr:lR,csub:aR,csube:cR,csup:uR,csupe:fR,ctdot:dR,cudarrl:hR,cudarrr:pR,cuepr:gR,cuesc:mR,cularr:vR,cularrp:yR,cupbrcap:bR,cupcap:wR,CupCap:xR,cup:kR,Cup:SR,cupcup:_R,cupdot:TR,cupor:CR,cups:ER,curarr:AR,curarrm:LR,curlyeqprec:MR,curlyeqsucc:NR,curlyvee:OR,curlywedge:PR,curren:RR,curvearrowleft:$R,curvearrowright:IR,cuvee:DR,cuwed:zR,cwconint:FR,cwint:HR,cylcty:BR,dagger:WR,Dagger:qR,daleth:jR,darr:UR,Darr:VR,dArr:GR,dash:KR,Dashv:XR,dashv:YR,dbkarow:ZR,dblac:JR,Dcaron:QR,dcaron:e$,Dcy:t$,dcy:n$,ddagger:r$,ddarr:i$,DD:o$,dd:s$,DDotrahd:l$,ddotseq:a$,deg:c$,Del:u$,Delta:f$,delta:d$,demptyv:h$,dfisht:p$,Dfr:g$,dfr:m$,dHar:v$,dharl:y$,dharr:b$,DiacriticalAcute:w$,DiacriticalDot:x$,DiacriticalDoubleAcute:k$,DiacriticalGrave:S$,DiacriticalTilde:_$,diam:T$,diamond:C$,Diamond:E$,diamondsuit:A$,diams:L$,die:M$,DifferentialD:N$,digamma:O$,disin:P$,div:R$,divide:$$,divideontimes:I$,divonx:D$,DJcy:z$,djcy:F$,dlcorn:H$,dlcrop:B$,dollar:W$,Dopf:q$,dopf:j$,Dot:U$,dot:V$,DotDot:G$,doteq:K$,doteqdot:X$,DotEqual:Y$,dotminus:Z$,dotplus:J$,dotsquare:Q$,doublebarwedge:eI,DoubleContourIntegral:tI,DoubleDot:nI,DoubleDownArrow:rI,DoubleLeftArrow:iI,DoubleLeftRightArrow:oI,DoubleLeftTee:sI,DoubleLongLeftArrow:lI,DoubleLongLeftRightArrow:aI,DoubleLongRightArrow:cI,DoubleRightArrow:uI,DoubleRightTee:fI,DoubleUpArrow:dI,DoubleUpDownArrow:hI,DoubleVerticalBar:pI,DownArrowBar:gI,downarrow:mI,DownArrow:vI,Downarrow:yI,DownArrowUpArrow:bI,DownBreve:wI,downdownarrows:xI,downharpoonleft:kI,downharpoonright:SI,DownLeftRightVector:_I,DownLeftTeeVector:TI,DownLeftVectorBar:CI,DownLeftVector:EI,DownRightTeeVector:AI,DownRightVectorBar:LI,DownRightVector:MI,DownTeeArrow:NI,DownTee:OI,drbkarow:PI,drcorn:RI,drcrop:$I,Dscr:II,dscr:DI,DScy:zI,dscy:FI,dsol:HI,Dstrok:BI,dstrok:WI,dtdot:qI,dtri:jI,dtrif:UI,duarr:VI,duhar:GI,dwangle:KI,DZcy:XI,dzcy:YI,dzigrarr:ZI,Eacute:JI,eacute:QI,easter:eD,Ecaron:tD,ecaron:nD,Ecirc:rD,ecirc:iD,ecir:oD,ecolon:sD,Ecy:lD,ecy:aD,eDDot:cD,Edot:uD,edot:fD,eDot:dD,ee:hD,efDot:pD,Efr:gD,efr:mD,eg:vD,Egrave:yD,egrave:bD,egs:wD,egsdot:xD,el:kD,Element:SD,elinters:_D,ell:TD,els:CD,elsdot:ED,Emacr:AD,emacr:LD,empty:MD,emptyset:ND,EmptySmallSquare:OD,emptyv:PD,EmptyVerySmallSquare:RD,emsp13:$D,emsp14:ID,emsp:DD,ENG:zD,eng:FD,ensp:HD,Eogon:BD,eogon:WD,Eopf:qD,eopf:jD,epar:UD,eparsl:VD,eplus:GD,epsi:KD,Epsilon:XD,epsilon:YD,epsiv:ZD,eqcirc:JD,eqcolon:QD,eqsim:ez,eqslantgtr:tz,eqslantless:nz,Equal:rz,equals:iz,EqualTilde:oz,equest:sz,Equilibrium:lz,equiv:az,equivDD:cz,eqvparsl:uz,erarr:fz,erDot:dz,escr:hz,Escr:pz,esdot:gz,Esim:mz,esim:vz,Eta:yz,eta:bz,ETH:wz,eth:xz,Euml:kz,euml:Sz,euro:_z,excl:Tz,exist:Cz,Exists:Ez,expectation:Az,exponentiale:Lz,ExponentialE:Mz,fallingdotseq:Nz,Fcy:Oz,fcy:Pz,female:Rz,ffilig:$z,fflig:Iz,ffllig:Dz,Ffr:zz,ffr:Fz,filig:Hz,FilledSmallSquare:Bz,FilledVerySmallSquare:Wz,fjlig:qz,flat:jz,fllig:Uz,fltns:Vz,fnof:Gz,Fopf:Kz,fopf:Xz,forall:Yz,ForAll:Zz,fork:Jz,forkv:Qz,Fouriertrf:eF,fpartint:tF,frac12:nF,frac13:rF,frac14:iF,frac15:oF,frac16:sF,frac18:lF,frac23:aF,frac25:cF,frac34:uF,frac35:fF,frac38:dF,frac45:hF,frac56:pF,frac58:gF,frac78:mF,frasl:vF,frown:yF,fscr:bF,Fscr:wF,gacute:xF,Gamma:kF,gamma:SF,Gammad:_F,gammad:TF,gap:CF,Gbreve:EF,gbreve:AF,Gcedil:LF,Gcirc:MF,gcirc:NF,Gcy:OF,gcy:PF,Gdot:RF,gdot:$F,ge:IF,gE:DF,gEl:zF,gel:FF,geq:HF,geqq:BF,geqslant:WF,gescc:qF,ges:jF,gesdot:UF,gesdoto:VF,gesdotol:GF,gesl:KF,gesles:XF,Gfr:YF,gfr:ZF,gg:JF,Gg:QF,ggg:eH,gimel:tH,GJcy:nH,gjcy:rH,gla:iH,gl:oH,glE:sH,glj:lH,gnap:aH,gnapprox:cH,gne:uH,gnE:fH,gneq:dH,gneqq:hH,gnsim:pH,Gopf:gH,gopf:mH,grave:vH,GreaterEqual:yH,GreaterEqualLess:bH,GreaterFullEqual:wH,GreaterGreater:xH,GreaterLess:kH,GreaterSlantEqual:SH,GreaterTilde:_H,Gscr:TH,gscr:CH,gsim:EH,gsime:AH,gsiml:LH,gtcc:MH,gtcir:NH,gt:OH,GT:PH,Gt:RH,gtdot:$H,gtlPar:IH,gtquest:DH,gtrapprox:zH,gtrarr:FH,gtrdot:HH,gtreqless:BH,gtreqqless:WH,gtrless:qH,gtrsim:jH,gvertneqq:UH,gvnE:VH,Hacek:GH,hairsp:KH,half:XH,hamilt:YH,HARDcy:ZH,hardcy:JH,harrcir:QH,harr:e3,hArr:t3,harrw:n3,Hat:r3,hbar:i3,Hcirc:o3,hcirc:s3,hearts:l3,heartsuit:a3,hellip:c3,hercon:u3,hfr:f3,Hfr:d3,HilbertSpace:h3,hksearow:p3,hkswarow:g3,hoarr:m3,homtht:v3,hookleftarrow:y3,hookrightarrow:b3,hopf:w3,Hopf:x3,horbar:k3,HorizontalLine:S3,hscr:_3,Hscr:T3,hslash:C3,Hstrok:E3,hstrok:A3,HumpDownHump:L3,HumpEqual:M3,hybull:N3,hyphen:O3,Iacute:P3,iacute:R3,ic:$3,Icirc:I3,icirc:D3,Icy:z3,icy:F3,Idot:H3,IEcy:B3,iecy:W3,iexcl:q3,iff:j3,ifr:U3,Ifr:V3,Igrave:G3,igrave:K3,ii:X3,iiiint:Y3,iiint:Z3,iinfin:J3,iiota:Q3,IJlig:eB,ijlig:tB,Imacr:nB,imacr:rB,image:iB,ImaginaryI:oB,imagline:sB,imagpart:lB,imath:aB,Im:cB,imof:uB,imped:fB,Implies:dB,incare:hB,in:\"∈\",infin:pB,infintie:gB,inodot:mB,intcal:vB,int:yB,Int:bB,integers:wB,Integral:xB,intercal:kB,Intersection:SB,intlarhk:_B,intprod:TB,InvisibleComma:CB,InvisibleTimes:EB,IOcy:AB,iocy:LB,Iogon:MB,iogon:NB,Iopf:OB,iopf:PB,Iota:RB,iota:$B,iprod:IB,iquest:DB,iscr:zB,Iscr:FB,isin:HB,isindot:BB,isinE:WB,isins:qB,isinsv:jB,isinv:UB,it:VB,Itilde:GB,itilde:KB,Iukcy:XB,iukcy:YB,Iuml:ZB,iuml:JB,Jcirc:QB,jcirc:e5,Jcy:t5,jcy:n5,Jfr:r5,jfr:i5,jmath:o5,Jopf:s5,jopf:l5,Jscr:a5,jscr:c5,Jsercy:u5,jsercy:f5,Jukcy:d5,jukcy:h5,Kappa:p5,kappa:g5,kappav:m5,Kcedil:v5,kcedil:y5,Kcy:b5,kcy:w5,Kfr:x5,kfr:k5,kgreen:S5,KHcy:_5,khcy:T5,KJcy:C5,kjcy:E5,Kopf:A5,kopf:L5,Kscr:M5,kscr:N5,lAarr:O5,Lacute:P5,lacute:R5,laemptyv:$5,lagran:I5,Lambda:D5,lambda:z5,lang:F5,Lang:H5,langd:B5,langle:W5,lap:q5,Laplacetrf:j5,laquo:U5,larrb:V5,larrbfs:G5,larr:K5,Larr:X5,lArr:Y5,larrfs:Z5,larrhk:J5,larrlp:Q5,larrpl:e8,larrsim:t8,larrtl:n8,latail:r8,lAtail:i8,lat:o8,late:s8,lates:l8,lbarr:a8,lBarr:c8,lbbrk:u8,lbrace:f8,lbrack:d8,lbrke:h8,lbrksld:p8,lbrkslu:g8,Lcaron:m8,lcaron:v8,Lcedil:y8,lcedil:b8,lceil:w8,lcub:x8,Lcy:k8,lcy:S8,ldca:_8,ldquo:T8,ldquor:C8,ldrdhar:E8,ldrushar:A8,ldsh:L8,le:M8,lE:N8,LeftAngleBracket:O8,LeftArrowBar:P8,leftarrow:R8,LeftArrow:$8,Leftarrow:I8,LeftArrowRightArrow:D8,leftarrowtail:z8,LeftCeiling:F8,LeftDoubleBracket:H8,LeftDownTeeVector:B8,LeftDownVectorBar:W8,LeftDownVector:q8,LeftFloor:j8,leftharpoondown:U8,leftharpoonup:V8,leftleftarrows:G8,leftrightarrow:K8,LeftRightArrow:X8,Leftrightarrow:Y8,leftrightarrows:Z8,leftrightharpoons:J8,leftrightsquigarrow:Q8,LeftRightVector:eW,LeftTeeArrow:tW,LeftTee:nW,LeftTeeVector:rW,leftthreetimes:iW,LeftTriangleBar:oW,LeftTriangle:sW,LeftTriangleEqual:lW,LeftUpDownVector:aW,LeftUpTeeVector:cW,LeftUpVectorBar:uW,LeftUpVector:fW,LeftVectorBar:dW,LeftVector:hW,lEg:pW,leg:gW,leq:mW,leqq:vW,leqslant:yW,lescc:bW,les:wW,lesdot:xW,lesdoto:kW,lesdotor:SW,lesg:_W,lesges:TW,lessapprox:CW,lessdot:EW,lesseqgtr:AW,lesseqqgtr:LW,LessEqualGreater:MW,LessFullEqual:NW,LessGreater:OW,lessgtr:PW,LessLess:RW,lesssim:$W,LessSlantEqual:IW,LessTilde:DW,lfisht:zW,lfloor:FW,Lfr:HW,lfr:BW,lg:WW,lgE:qW,lHar:jW,lhard:UW,lharu:VW,lharul:GW,lhblk:KW,LJcy:XW,ljcy:YW,llarr:ZW,ll:JW,Ll:QW,llcorner:e4,Lleftarrow:t4,llhard:n4,lltri:r4,Lmidot:i4,lmidot:o4,lmoustache:s4,lmoust:l4,lnap:a4,lnapprox:c4,lne:u4,lnE:f4,lneq:d4,lneqq:h4,lnsim:p4,loang:g4,loarr:m4,lobrk:v4,longleftarrow:y4,LongLeftArrow:b4,Longleftarrow:w4,longleftrightarrow:x4,LongLeftRightArrow:k4,Longleftrightarrow:S4,longmapsto:_4,longrightarrow:T4,LongRightArrow:C4,Longrightarrow:E4,looparrowleft:A4,looparrowright:L4,lopar:M4,Lopf:N4,lopf:O4,loplus:P4,lotimes:R4,lowast:$4,lowbar:I4,LowerLeftArrow:D4,LowerRightArrow:z4,loz:F4,lozenge:H4,lozf:B4,lpar:W4,lparlt:q4,lrarr:j4,lrcorner:U4,lrhar:V4,lrhard:G4,lrm:K4,lrtri:X4,lsaquo:Y4,lscr:Z4,Lscr:J4,lsh:Q4,Lsh:eq,lsim:tq,lsime:nq,lsimg:rq,lsqb:iq,lsquo:oq,lsquor:sq,Lstrok:lq,lstrok:aq,ltcc:cq,ltcir:uq,lt:fq,LT:dq,Lt:hq,ltdot:pq,lthree:gq,ltimes:mq,ltlarr:vq,ltquest:yq,ltri:bq,ltrie:wq,ltrif:xq,ltrPar:kq,lurdshar:Sq,luruhar:_q,lvertneqq:Tq,lvnE:Cq,macr:Eq,male:Aq,malt:Lq,maltese:Mq,Map:\"⤅\",map:Nq,mapsto:Oq,mapstodown:Pq,mapstoleft:Rq,mapstoup:$q,marker:Iq,mcomma:Dq,Mcy:zq,mcy:Fq,mdash:Hq,mDDot:Bq,measuredangle:Wq,MediumSpace:qq,Mellintrf:jq,Mfr:Uq,mfr:Vq,mho:Gq,micro:Kq,midast:Xq,midcir:Yq,mid:Zq,middot:Jq,minusb:Qq,minus:ej,minusd:tj,minusdu:nj,MinusPlus:rj,mlcp:ij,mldr:oj,mnplus:sj,models:lj,Mopf:aj,mopf:cj,mp:uj,mscr:fj,Mscr:dj,mstpos:hj,Mu:pj,mu:gj,multimap:mj,mumap:vj,nabla:yj,Nacute:bj,nacute:wj,nang:xj,nap:kj,napE:Sj,napid:_j,napos:Tj,napprox:Cj,natural:Ej,naturals:Aj,natur:Lj,nbsp:Mj,nbump:Nj,nbumpe:Oj,ncap:Pj,Ncaron:Rj,ncaron:$j,Ncedil:Ij,ncedil:Dj,ncong:zj,ncongdot:Fj,ncup:Hj,Ncy:Bj,ncy:Wj,ndash:qj,nearhk:jj,nearr:Uj,neArr:Vj,nearrow:Gj,ne:Kj,nedot:Xj,NegativeMediumSpace:Yj,NegativeThickSpace:Zj,NegativeThinSpace:Jj,NegativeVeryThinSpace:Qj,nequiv:eU,nesear:tU,nesim:nU,NestedGreaterGreater:rU,NestedLessLess:iU,NewLine:oU,nexist:sU,nexists:lU,Nfr:aU,nfr:cU,ngE:uU,nge:fU,ngeq:dU,ngeqq:hU,ngeqslant:pU,nges:gU,nGg:mU,ngsim:vU,nGt:yU,ngt:bU,ngtr:wU,nGtv:xU,nharr:kU,nhArr:SU,nhpar:_U,ni:TU,nis:CU,nisd:EU,niv:AU,NJcy:LU,njcy:MU,nlarr:NU,nlArr:OU,nldr:PU,nlE:RU,nle:$U,nleftarrow:IU,nLeftarrow:DU,nleftrightarrow:zU,nLeftrightarrow:FU,nleq:HU,nleqq:BU,nleqslant:WU,nles:qU,nless:jU,nLl:UU,nlsim:VU,nLt:GU,nlt:KU,nltri:XU,nltrie:YU,nLtv:ZU,nmid:JU,NoBreak:QU,NonBreakingSpace:e6,nopf:t6,Nopf:n6,Not:r6,not:i6,NotCongruent:o6,NotCupCap:s6,NotDoubleVerticalBar:l6,NotElement:a6,NotEqual:c6,NotEqualTilde:u6,NotExists:f6,NotGreater:d6,NotGreaterEqual:h6,NotGreaterFullEqual:p6,NotGreaterGreater:g6,NotGreaterLess:m6,NotGreaterSlantEqual:v6,NotGreaterTilde:y6,NotHumpDownHump:b6,NotHumpEqual:w6,notin:x6,notindot:k6,notinE:S6,notinva:_6,notinvb:T6,notinvc:C6,NotLeftTriangleBar:E6,NotLeftTriangle:A6,NotLeftTriangleEqual:L6,NotLess:M6,NotLessEqual:N6,NotLessGreater:O6,NotLessLess:P6,NotLessSlantEqual:R6,NotLessTilde:$6,NotNestedGreaterGreater:I6,NotNestedLessLess:D6,notni:z6,notniva:F6,notnivb:H6,notnivc:B6,NotPrecedes:W6,NotPrecedesEqual:q6,NotPrecedesSlantEqual:j6,NotReverseElement:U6,NotRightTriangleBar:V6,NotRightTriangle:G6,NotRightTriangleEqual:K6,NotSquareSubset:X6,NotSquareSubsetEqual:Y6,NotSquareSuperset:Z6,NotSquareSupersetEqual:J6,NotSubset:Q6,NotSubsetEqual:eV,NotSucceeds:tV,NotSucceedsEqual:nV,NotSucceedsSlantEqual:rV,NotSucceedsTilde:iV,NotSuperset:oV,NotSupersetEqual:sV,NotTilde:lV,NotTildeEqual:aV,NotTildeFullEqual:cV,NotTildeTilde:uV,NotVerticalBar:fV,nparallel:dV,npar:hV,nparsl:pV,npart:gV,npolint:mV,npr:vV,nprcue:yV,nprec:bV,npreceq:wV,npre:xV,nrarrc:kV,nrarr:SV,nrArr:_V,nrarrw:TV,nrightarrow:CV,nRightarrow:EV,nrtri:AV,nrtrie:LV,nsc:MV,nsccue:NV,nsce:OV,Nscr:PV,nscr:RV,nshortmid:$V,nshortparallel:IV,nsim:DV,nsime:zV,nsimeq:FV,nsmid:HV,nspar:BV,nsqsube:WV,nsqsupe:qV,nsub:jV,nsubE:UV,nsube:VV,nsubset:GV,nsubseteq:KV,nsubseteqq:XV,nsucc:YV,nsucceq:ZV,nsup:JV,nsupE:QV,nsupe:eG,nsupset:tG,nsupseteq:nG,nsupseteqq:rG,ntgl:iG,Ntilde:oG,ntilde:sG,ntlg:lG,ntriangleleft:aG,ntrianglelefteq:cG,ntriangleright:uG,ntrianglerighteq:fG,Nu:dG,nu:hG,num:pG,numero:gG,numsp:mG,nvap:vG,nvdash:yG,nvDash:bG,nVdash:wG,nVDash:xG,nvge:kG,nvgt:SG,nvHarr:_G,nvinfin:TG,nvlArr:CG,nvle:EG,nvlt:AG,nvltrie:LG,nvrArr:MG,nvrtrie:NG,nvsim:OG,nwarhk:PG,nwarr:RG,nwArr:$G,nwarrow:IG,nwnear:DG,Oacute:zG,oacute:FG,oast:HG,Ocirc:BG,ocirc:WG,ocir:qG,Ocy:jG,ocy:UG,odash:VG,Odblac:GG,odblac:KG,odiv:XG,odot:YG,odsold:ZG,OElig:JG,oelig:QG,ofcir:e9,Ofr:t9,ofr:n9,ogon:r9,Ograve:i9,ograve:o9,ogt:s9,ohbar:l9,ohm:a9,oint:c9,olarr:u9,olcir:f9,olcross:d9,oline:h9,olt:p9,Omacr:g9,omacr:m9,Omega:v9,omega:y9,Omicron:b9,omicron:w9,omid:x9,ominus:k9,Oopf:S9,oopf:_9,opar:T9,OpenCurlyDoubleQuote:C9,OpenCurlyQuote:E9,operp:A9,oplus:L9,orarr:M9,Or:N9,or:O9,ord:P9,order:R9,orderof:$9,ordf:I9,ordm:D9,origof:z9,oror:F9,orslope:H9,orv:B9,oS:W9,Oscr:q9,oscr:j9,Oslash:U9,oslash:V9,osol:G9,Otilde:K9,otilde:X9,otimesas:Y9,Otimes:Z9,otimes:J9,Ouml:Q9,ouml:eK,ovbar:tK,OverBar:nK,OverBrace:rK,OverBracket:iK,OverParenthesis:oK,para:sK,parallel:lK,par:aK,parsim:cK,parsl:uK,part:fK,PartialD:dK,Pcy:hK,pcy:pK,percnt:gK,period:mK,permil:vK,perp:yK,pertenk:bK,Pfr:wK,pfr:xK,Phi:kK,phi:SK,phiv:_K,phmmat:TK,phone:CK,Pi:EK,pi:AK,pitchfork:LK,piv:MK,planck:NK,planckh:OK,plankv:PK,plusacir:RK,plusb:$K,pluscir:IK,plus:DK,plusdo:zK,plusdu:FK,pluse:HK,PlusMinus:BK,plusmn:WK,plussim:qK,plustwo:jK,pm:UK,Poincareplane:VK,pointint:GK,popf:KK,Popf:XK,pound:YK,prap:ZK,Pr:JK,pr:QK,prcue:e7,precapprox:t7,prec:n7,preccurlyeq:r7,Precedes:i7,PrecedesEqual:o7,PrecedesSlantEqual:s7,PrecedesTilde:l7,preceq:a7,precnapprox:c7,precneqq:u7,precnsim:f7,pre:d7,prE:h7,precsim:p7,prime:g7,Prime:m7,primes:v7,prnap:y7,prnE:b7,prnsim:w7,prod:x7,Product:k7,profalar:S7,profline:_7,profsurf:T7,prop:C7,Proportional:E7,Proportion:A7,propto:L7,prsim:M7,prurel:N7,Pscr:O7,pscr:P7,Psi:R7,psi:$7,puncsp:I7,Qfr:D7,qfr:z7,qint:F7,qopf:H7,Qopf:B7,qprime:W7,Qscr:q7,qscr:j7,quaternions:U7,quatint:V7,quest:G7,questeq:K7,quot:X7,QUOT:Y7,rAarr:Z7,race:J7,Racute:Q7,racute:eX,radic:tX,raemptyv:nX,rang:rX,Rang:iX,rangd:oX,range:sX,rangle:lX,raquo:aX,rarrap:cX,rarrb:uX,rarrbfs:fX,rarrc:dX,rarr:hX,Rarr:pX,rArr:gX,rarrfs:mX,rarrhk:vX,rarrlp:yX,rarrpl:bX,rarrsim:wX,Rarrtl:xX,rarrtl:kX,rarrw:SX,ratail:_X,rAtail:TX,ratio:CX,rationals:EX,rbarr:AX,rBarr:LX,RBarr:MX,rbbrk:NX,rbrace:OX,rbrack:PX,rbrke:RX,rbrksld:$X,rbrkslu:IX,Rcaron:DX,rcaron:zX,Rcedil:FX,rcedil:HX,rceil:BX,rcub:WX,Rcy:qX,rcy:jX,rdca:UX,rdldhar:VX,rdquo:GX,rdquor:KX,rdsh:XX,real:YX,realine:ZX,realpart:JX,reals:QX,Re:eY,rect:tY,reg:nY,REG:rY,ReverseElement:iY,ReverseEquilibrium:oY,ReverseUpEquilibrium:sY,rfisht:lY,rfloor:aY,rfr:cY,Rfr:uY,rHar:fY,rhard:dY,rharu:hY,rharul:pY,Rho:gY,rho:mY,rhov:vY,RightAngleBracket:yY,RightArrowBar:bY,rightarrow:wY,RightArrow:xY,Rightarrow:kY,RightArrowLeftArrow:SY,rightarrowtail:_Y,RightCeiling:TY,RightDoubleBracket:CY,RightDownTeeVector:EY,RightDownVectorBar:AY,RightDownVector:LY,RightFloor:MY,rightharpoondown:NY,rightharpoonup:OY,rightleftarrows:PY,rightleftharpoons:RY,rightrightarrows:$Y,rightsquigarrow:IY,RightTeeArrow:DY,RightTee:zY,RightTeeVector:FY,rightthreetimes:HY,RightTriangleBar:BY,RightTriangle:WY,RightTriangleEqual:qY,RightUpDownVector:jY,RightUpTeeVector:UY,RightUpVectorBar:VY,RightUpVector:GY,RightVectorBar:KY,RightVector:XY,ring:YY,risingdotseq:ZY,rlarr:JY,rlhar:QY,rlm:eZ,rmoustache:tZ,rmoust:nZ,rnmid:rZ,roang:iZ,roarr:oZ,robrk:sZ,ropar:lZ,ropf:aZ,Ropf:cZ,roplus:uZ,rotimes:fZ,RoundImplies:dZ,rpar:hZ,rpargt:pZ,rppolint:gZ,rrarr:mZ,Rrightarrow:vZ,rsaquo:yZ,rscr:bZ,Rscr:wZ,rsh:xZ,Rsh:kZ,rsqb:SZ,rsquo:_Z,rsquor:TZ,rthree:CZ,rtimes:EZ,rtri:AZ,rtrie:LZ,rtrif:MZ,rtriltri:NZ,RuleDelayed:OZ,ruluhar:PZ,rx:RZ,Sacute:$Z,sacute:IZ,sbquo:DZ,scap:zZ,Scaron:FZ,scaron:HZ,Sc:BZ,sc:WZ,sccue:qZ,sce:jZ,scE:UZ,Scedil:VZ,scedil:GZ,Scirc:KZ,scirc:XZ,scnap:YZ,scnE:ZZ,scnsim:JZ,scpolint:QZ,scsim:eJ,Scy:tJ,scy:nJ,sdotb:rJ,sdot:iJ,sdote:oJ,searhk:sJ,searr:lJ,seArr:aJ,searrow:cJ,sect:uJ,semi:fJ,seswar:dJ,setminus:hJ,setmn:pJ,sext:gJ,Sfr:mJ,sfr:vJ,sfrown:yJ,sharp:bJ,SHCHcy:wJ,shchcy:xJ,SHcy:kJ,shcy:SJ,ShortDownArrow:_J,ShortLeftArrow:TJ,shortmid:CJ,shortparallel:EJ,ShortRightArrow:AJ,ShortUpArrow:LJ,shy:MJ,Sigma:NJ,sigma:OJ,sigmaf:PJ,sigmav:RJ,sim:$J,simdot:IJ,sime:DJ,simeq:zJ,simg:FJ,simgE:HJ,siml:BJ,simlE:WJ,simne:qJ,simplus:jJ,simrarr:UJ,slarr:VJ,SmallCircle:GJ,smallsetminus:KJ,smashp:XJ,smeparsl:YJ,smid:ZJ,smile:JJ,smt:QJ,smte:eQ,smtes:tQ,SOFTcy:nQ,softcy:rQ,solbar:iQ,solb:oQ,sol:sQ,Sopf:lQ,sopf:aQ,spades:cQ,spadesuit:uQ,spar:fQ,sqcap:dQ,sqcaps:hQ,sqcup:pQ,sqcups:gQ,Sqrt:mQ,sqsub:vQ,sqsube:yQ,sqsubset:bQ,sqsubseteq:wQ,sqsup:xQ,sqsupe:kQ,sqsupset:SQ,sqsupseteq:_Q,square:TQ,Square:CQ,SquareIntersection:EQ,SquareSubset:AQ,SquareSubsetEqual:LQ,SquareSuperset:MQ,SquareSupersetEqual:NQ,SquareUnion:OQ,squarf:PQ,squ:RQ,squf:$Q,srarr:IQ,Sscr:DQ,sscr:zQ,ssetmn:FQ,ssmile:HQ,sstarf:BQ,Star:WQ,star:qQ,starf:jQ,straightepsilon:UQ,straightphi:VQ,strns:GQ,sub:KQ,Sub:XQ,subdot:YQ,subE:ZQ,sube:JQ,subedot:QQ,submult:eee,subnE:tee,subne:nee,subplus:ree,subrarr:iee,subset:oee,Subset:see,subseteq:lee,subseteqq:aee,SubsetEqual:cee,subsetneq:uee,subsetneqq:fee,subsim:dee,subsub:hee,subsup:pee,succapprox:gee,succ:mee,succcurlyeq:vee,Succeeds:yee,SucceedsEqual:bee,SucceedsSlantEqual:wee,SucceedsTilde:xee,succeq:kee,succnapprox:See,succneqq:_ee,succnsim:Tee,succsim:Cee,SuchThat:Eee,sum:Aee,Sum:Lee,sung:Mee,sup1:Nee,sup2:Oee,sup3:Pee,sup:Ree,Sup:$ee,supdot:Iee,supdsub:Dee,supE:zee,supe:Fee,supedot:Hee,Superset:Bee,SupersetEqual:Wee,suphsol:qee,suphsub:jee,suplarr:Uee,supmult:Vee,supnE:Gee,supne:Kee,supplus:Xee,supset:Yee,Supset:Zee,supseteq:Jee,supseteqq:Qee,supsetneq:ete,supsetneqq:tte,supsim:nte,supsub:rte,supsup:ite,swarhk:ote,swarr:ste,swArr:lte,swarrow:ate,swnwar:cte,szlig:ute,Tab:fte,target:dte,Tau:hte,tau:pte,tbrk:gte,Tcaron:mte,tcaron:vte,Tcedil:yte,tcedil:bte,Tcy:wte,tcy:xte,tdot:kte,telrec:Ste,Tfr:_te,tfr:Tte,there4:Cte,therefore:Ete,Therefore:Ate,Theta:Lte,theta:Mte,thetasym:Nte,thetav:Ote,thickapprox:Pte,thicksim:Rte,ThickSpace:$te,ThinSpace:Ite,thinsp:Dte,thkap:zte,thksim:Fte,THORN:Hte,thorn:Bte,tilde:Wte,Tilde:qte,TildeEqual:jte,TildeFullEqual:Ute,TildeTilde:Vte,timesbar:Gte,timesb:Kte,times:Xte,timesd:Yte,tint:Zte,toea:Jte,topbot:Qte,topcir:ene,top:tne,Topf:nne,topf:rne,topfork:ine,tosa:one,tprime:sne,trade:lne,TRADE:ane,triangle:cne,triangledown:une,triangleleft:fne,trianglelefteq:dne,triangleq:hne,triangleright:pne,trianglerighteq:gne,tridot:mne,trie:vne,triminus:yne,TripleDot:bne,triplus:wne,trisb:xne,tritime:kne,trpezium:Sne,Tscr:_ne,tscr:Tne,TScy:Cne,tscy:Ene,TSHcy:Ane,tshcy:Lne,Tstrok:Mne,tstrok:Nne,twixt:One,twoheadleftarrow:Pne,twoheadrightarrow:Rne,Uacute:$ne,uacute:Ine,uarr:Dne,Uarr:zne,uArr:Fne,Uarrocir:Hne,Ubrcy:Bne,ubrcy:Wne,Ubreve:qne,ubreve:jne,Ucirc:Une,ucirc:Vne,Ucy:Gne,ucy:Kne,udarr:Xne,Udblac:Yne,udblac:Zne,udhar:Jne,ufisht:Qne,Ufr:ere,ufr:tre,Ugrave:nre,ugrave:rre,uHar:ire,uharl:ore,uharr:sre,uhblk:lre,ulcorn:are,ulcorner:cre,ulcrop:ure,ultri:fre,Umacr:dre,umacr:hre,uml:pre,UnderBar:gre,UnderBrace:mre,UnderBracket:vre,UnderParenthesis:yre,Union:bre,UnionPlus:wre,Uogon:xre,uogon:kre,Uopf:Sre,uopf:_re,UpArrowBar:Tre,uparrow:Cre,UpArrow:Ere,Uparrow:Are,UpArrowDownArrow:Lre,updownarrow:Mre,UpDownArrow:Nre,Updownarrow:Ore,UpEquilibrium:Pre,upharpoonleft:Rre,upharpoonright:$re,uplus:Ire,UpperLeftArrow:Dre,UpperRightArrow:zre,upsi:Fre,Upsi:Hre,upsih:Bre,Upsilon:Wre,upsilon:qre,UpTeeArrow:jre,UpTee:Ure,upuparrows:Vre,urcorn:Gre,urcorner:Kre,urcrop:Xre,Uring:Yre,uring:Zre,urtri:Jre,Uscr:Qre,uscr:eie,utdot:tie,Utilde:nie,utilde:rie,utri:iie,utrif:oie,uuarr:sie,Uuml:lie,uuml:aie,uwangle:cie,vangrt:uie,varepsilon:fie,varkappa:die,varnothing:hie,varphi:pie,varpi:gie,varpropto:mie,varr:vie,vArr:yie,varrho:bie,varsigma:wie,varsubsetneq:xie,varsubsetneqq:kie,varsupsetneq:Sie,varsupsetneqq:_ie,vartheta:Tie,vartriangleleft:Cie,vartriangleright:Eie,vBar:Aie,Vbar:Lie,vBarv:Mie,Vcy:Nie,vcy:Oie,vdash:Pie,vDash:Rie,Vdash:$ie,VDash:Iie,Vdashl:Die,veebar:zie,vee:Fie,Vee:Hie,veeeq:Bie,vellip:Wie,verbar:qie,Verbar:jie,vert:Uie,Vert:Vie,VerticalBar:Gie,VerticalLine:Kie,VerticalSeparator:Xie,VerticalTilde:Yie,VeryThinSpace:Zie,Vfr:Jie,vfr:Qie,vltri:eoe,vnsub:toe,vnsup:noe,Vopf:roe,vopf:ioe,vprop:ooe,vrtri:soe,Vscr:loe,vscr:aoe,vsubnE:coe,vsubne:uoe,vsupnE:foe,vsupne:doe,Vvdash:hoe,vzigzag:poe,Wcirc:goe,wcirc:moe,wedbar:voe,wedge:yoe,Wedge:boe,wedgeq:woe,weierp:xoe,Wfr:koe,wfr:Soe,Wopf:_oe,wopf:Toe,wp:Coe,wr:Eoe,wreath:Aoe,Wscr:Loe,wscr:Moe,xcap:Noe,xcirc:Ooe,xcup:Poe,xdtri:Roe,Xfr:$oe,xfr:Ioe,xharr:Doe,xhArr:zoe,Xi:Foe,xi:Hoe,xlarr:Boe,xlArr:Woe,xmap:qoe,xnis:joe,xodot:Uoe,Xopf:Voe,xopf:Goe,xoplus:Koe,xotime:Xoe,xrarr:Yoe,xrArr:Zoe,Xscr:Joe,xscr:Qoe,xsqcup:ese,xuplus:tse,xutri:nse,xvee:rse,xwedge:ise,Yacute:ose,yacute:sse,YAcy:lse,yacy:ase,Ycirc:cse,ycirc:use,Ycy:fse,ycy:dse,yen:hse,Yfr:pse,yfr:gse,YIcy:mse,yicy:vse,Yopf:yse,yopf:bse,Yscr:wse,yscr:xse,YUcy:kse,yucy:Sse,yuml:_se,Yuml:Tse,Zacute:Cse,zacute:Ese,Zcaron:Ase,zcaron:Lse,Zcy:Mse,zcy:Nse,Zdot:Ose,zdot:Pse,zeetrf:Rse,ZeroWidthSpace:$se,Zeta:Ise,zeta:Dse,zfr:zse,Zfr:Fse,ZHcy:Hse,zhcy:Bse,zigrarr:Wse,zopf:qse,Zopf:jse,Zscr:Use,zscr:Vse,zwj:Gse,zwnj:Kse},Xse=\"Á\",Yse=\"á\",Zse=\"Â\",Jse=\"â\",Qse=\"´\",ele=\"Æ\",tle=\"æ\",nle=\"À\",rle=\"à\",ile=\"&\",ole=\"&\",sle=\"Å\",lle=\"å\",ale=\"Ã\",cle=\"ã\",ule=\"Ä\",fle=\"ä\",dle=\"¦\",hle=\"Ç\",ple=\"ç\",gle=\"¸\",mle=\"¢\",vle=\"©\",yle=\"©\",ble=\"¤\",wle=\"°\",xle=\"÷\",kle=\"É\",Sle=\"é\",_le=\"Ê\",Tle=\"ê\",Cle=\"È\",Ele=\"è\",Ale=\"Ð\",Lle=\"ð\",Mle=\"Ë\",Nle=\"ë\",Ole=\"½\",Ple=\"¼\",Rle=\"¾\",$le=\">\",Ile=\">\",Dle=\"Í\",zle=\"í\",Fle=\"Î\",Hle=\"î\",Ble=\"¡\",Wle=\"Ì\",qle=\"ì\",jle=\"¿\",Ule=\"Ï\",Vle=\"ï\",Gle=\"«\",Kle=\"<\",Xle=\"<\",Yle=\"¯\",Zle=\"µ\",Jle=\"·\",Qle=\" \",eae=\"¬\",tae=\"Ñ\",nae=\"ñ\",rae=\"Ó\",iae=\"ó\",oae=\"Ô\",sae=\"ô\",lae=\"Ò\",aae=\"ò\",cae=\"ª\",uae=\"º\",fae=\"Ø\",dae=\"ø\",hae=\"Õ\",pae=\"õ\",gae=\"Ö\",mae=\"ö\",vae=\"¶\",yae=\"±\",bae=\"£\",wae='\"',xae='\"',kae=\"»\",Sae=\"®\",_ae=\"®\",Tae=\"§\",Cae=\"­\",Eae=\"¹\",Aae=\"²\",Lae=\"³\",Mae=\"ß\",Nae=\"Þ\",Oae=\"þ\",Pae=\"×\",Rae=\"Ú\",$ae=\"ú\",Iae=\"Û\",Dae=\"û\",zae=\"Ù\",Fae=\"ù\",Hae=\"¨\",Bae=\"Ü\",Wae=\"ü\",qae=\"Ý\",jae=\"ý\",Uae=\"¥\",Vae=\"ÿ\",Gae={Aacute:Xse,aacute:Yse,Acirc:Zse,acirc:Jse,acute:Qse,AElig:ele,aelig:tle,Agrave:nle,agrave:rle,amp:ile,AMP:ole,Aring:sle,aring:lle,Atilde:ale,atilde:cle,Auml:ule,auml:fle,brvbar:dle,Ccedil:hle,ccedil:ple,cedil:gle,cent:mle,copy:vle,COPY:yle,curren:ble,deg:wle,divide:xle,Eacute:kle,eacute:Sle,Ecirc:_le,ecirc:Tle,Egrave:Cle,egrave:Ele,ETH:Ale,eth:Lle,Euml:Mle,euml:Nle,frac12:Ole,frac14:Ple,frac34:Rle,gt:$le,GT:Ile,Iacute:Dle,iacute:zle,Icirc:Fle,icirc:Hle,iexcl:Ble,Igrave:Wle,igrave:qle,iquest:jle,Iuml:Ule,iuml:Vle,laquo:Gle,lt:Kle,LT:Xle,macr:Yle,micro:Zle,middot:Jle,nbsp:Qle,not:eae,Ntilde:tae,ntilde:nae,Oacute:rae,oacute:iae,Ocirc:oae,ocirc:sae,Ograve:lae,ograve:aae,ordf:cae,ordm:uae,Oslash:fae,oslash:dae,Otilde:hae,otilde:pae,Ouml:gae,ouml:mae,para:vae,plusmn:yae,pound:bae,quot:wae,QUOT:xae,raquo:kae,reg:Sae,REG:_ae,sect:Tae,shy:Cae,sup1:Eae,sup2:Aae,sup3:Lae,szlig:Mae,THORN:Nae,thorn:Oae,times:Pae,Uacute:Rae,uacute:$ae,Ucirc:Iae,ucirc:Dae,Ugrave:zae,ugrave:Fae,uml:Hae,Uuml:Bae,uuml:Wae,Yacute:qae,yacute:jae,yen:Uae,yuml:Vae},Kae=\"&\",Xae=\"'\",Yae=\">\",Zae=\"<\",Jae='\"',ux={amp:Kae,apos:Xae,gt:Yae,lt:Zae,quot:Jae};var Ts={};const Qae={0:65533,128:8364,130:8218,131:402,132:8222,133:8230,134:8224,135:8225,136:710,137:8240,138:352,139:8249,140:338,142:381,145:8216,146:8217,147:8220,148:8221,149:8226,150:8211,151:8212,152:732,153:8482,154:353,155:8250,156:339,158:382,159:376};var fy;function ece(){if(fy)return Ts;fy=1;var e=Ts&&Ts.__importDefault||function(s){return s&&s.__esModule?s:{default:s}};Object.defineProperty(Ts,\"__esModule\",{value:!0});var t=e(Qae),r=String.fromCodePoint||function(s){var c=\"\";return s>65535&&(s-=65536,c+=String.fromCharCode(s>>>10&1023|55296),s=56320|s&1023),c+=String.fromCharCode(s),c};function o(s){return s>=55296&&s<=57343||s>1114111?\"�\":(s in t.default&&(s=t.default[s]),r(s))}return Ts.default=o,Ts}var dy;function hy(){if(dy)return Er;dy=1;var e=Er&&Er.__importDefault||function(p){return p&&p.__esModule?p:{default:p}};Object.defineProperty(Er,\"__esModule\",{value:!0}),Er.decodeHTML=Er.decodeHTMLStrict=Er.decodeXML=void 0;var t=e(cx),r=e(Gae),o=e(ux),s=e(ece()),c=/&(?:[a-zA-Z0-9]+|#[xX][\\da-fA-F]+|#\\d+);/g;Er.decodeXML=f(o.default),Er.decodeHTMLStrict=f(t.default);function f(p){var g=h(p);return function(v){return String(v).replace(c,g)}}var d=function(p,g){return p<g?1:-1};Er.decodeHTML=(function(){for(var p=Object.keys(r.default).sort(d),g=Object.keys(t.default).sort(d),v=0,b=0;v<g.length;v++)p[b]===g[v]?(g[v]+=\";?\",b++):g[v]+=\";\";var w=new RegExp(\"&(?:\"+g.join(\"|\")+\"|#[xX][\\\\da-fA-F]+;?|#\\\\d+;?)\",\"g\"),E=h(t.default);function L(P){return P.substr(-1)!==\";\"&&(P+=\";\"),E(P)}return function(P){return String(P).replace(w,L)}})();function h(p){return function(v){if(v.charAt(1)===\"#\"){var b=v.charAt(2);return b===\"X\"||b===\"x\"?s.default(parseInt(v.substr(3),16)):s.default(parseInt(v.substr(2),10))}return p[v.slice(1,-1)]||v}}return Er}var Ln={},py;function gy(){if(py)return Ln;py=1;var e=Ln&&Ln.__importDefault||function(M){return M&&M.__esModule?M:{default:M}};Object.defineProperty(Ln,\"__esModule\",{value:!0}),Ln.escapeUTF8=Ln.escape=Ln.encodeNonAsciiHTML=Ln.encodeHTML=Ln.encodeXML=void 0;var t=e(ux),r=d(t.default),o=h(r);Ln.encodeXML=P(r);var s=e(cx),c=d(s.default),f=h(c);Ln.encodeHTML=b(c,f),Ln.encodeNonAsciiHTML=P(c);function d(M){return Object.keys(M).sort().reduce(function(R,I){return R[M[I]]=\"&\"+I+\";\",R},{})}function h(M){for(var R=[],I=[],_=0,$=Object.keys(M);_<$.length;_++){var W=$[_];W.length===1?R.push(\"\\\\\"+W):I.push(W)}R.sort();for(var ne=0;ne<R.length-1;ne++){for(var ee=ne;ee<R.length-1&&R[ee].charCodeAt(1)+1===R[ee+1].charCodeAt(1);)ee+=1;var Z=1+ee-ne;Z<3||R.splice(ne,Z,R[ne]+\"-\"+R[ee])}return I.unshift(\"[\"+R.join(\"\")+\"]\"),new RegExp(I.join(\"|\"),\"g\")}var p=/(?:[\\x80-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF])/g,g=String.prototype.codePointAt!=null?function(M){return M.codePointAt(0)}:function(M){return(M.charCodeAt(0)-55296)*1024+M.charCodeAt(1)-56320+65536};function v(M){return\"&#x\"+(M.length>1?g(M):M.charCodeAt(0)).toString(16).toUpperCase()+\";\"}function b(M,R){return function(I){return I.replace(R,function(_){return M[_]}).replace(p,v)}}var w=new RegExp(o.source+\"|\"+p.source,\"g\");function E(M){return M.replace(w,v)}Ln.escape=E;function L(M){return M.replace(o,v)}Ln.escapeUTF8=L;function P(M){return function(R){return R.replace(w,function(I){return M[I]||v(I)})}}return Ln}var my;function tce(){return my||(my=1,(function(e){Object.defineProperty(e,\"__esModule\",{value:!0}),e.decodeXMLStrict=e.decodeHTML5Strict=e.decodeHTML4Strict=e.decodeHTML5=e.decodeHTML4=e.decodeHTMLStrict=e.decodeHTML=e.decodeXML=e.encodeHTML5=e.encodeHTML4=e.escapeUTF8=e.escape=e.encodeNonAsciiHTML=e.encodeHTML=e.encodeXML=e.encode=e.decodeStrict=e.decode=void 0;var t=hy(),r=gy();function o(h,p){return(!p||p<=0?t.decodeXML:t.decodeHTML)(h)}e.decode=o;function s(h,p){return(!p||p<=0?t.decodeXML:t.decodeHTMLStrict)(h)}e.decodeStrict=s;function c(h,p){return(!p||p<=0?r.encodeXML:r.encodeHTML)(h)}e.encode=c;var f=gy();Object.defineProperty(e,\"encodeXML\",{enumerable:!0,get:function(){return f.encodeXML}}),Object.defineProperty(e,\"encodeHTML\",{enumerable:!0,get:function(){return f.encodeHTML}}),Object.defineProperty(e,\"encodeNonAsciiHTML\",{enumerable:!0,get:function(){return f.encodeNonAsciiHTML}}),Object.defineProperty(e,\"escape\",{enumerable:!0,get:function(){return f.escape}}),Object.defineProperty(e,\"escapeUTF8\",{enumerable:!0,get:function(){return f.escapeUTF8}}),Object.defineProperty(e,\"encodeHTML4\",{enumerable:!0,get:function(){return f.encodeHTML}}),Object.defineProperty(e,\"encodeHTML5\",{enumerable:!0,get:function(){return f.encodeHTML}});var d=hy();Object.defineProperty(e,\"decodeXML\",{enumerable:!0,get:function(){return d.decodeXML}}),Object.defineProperty(e,\"decodeHTML\",{enumerable:!0,get:function(){return d.decodeHTML}}),Object.defineProperty(e,\"decodeHTMLStrict\",{enumerable:!0,get:function(){return d.decodeHTMLStrict}}),Object.defineProperty(e,\"decodeHTML4\",{enumerable:!0,get:function(){return d.decodeHTML}}),Object.defineProperty(e,\"decodeHTML5\",{enumerable:!0,get:function(){return d.decodeHTML}}),Object.defineProperty(e,\"decodeHTML4Strict\",{enumerable:!0,get:function(){return d.decodeHTMLStrict}}),Object.defineProperty(e,\"decodeHTML5Strict\",{enumerable:!0,get:function(){return d.decodeHTMLStrict}}),Object.defineProperty(e,\"decodeXMLStrict\",{enumerable:!0,get:function(){return d.decodeXML}})})(Ad)),Ad}var Ld,vy;function nce(){if(vy)return Ld;vy=1;function e(N,O){if(!(N instanceof O))throw new TypeError(\"Cannot call a class as a function\")}function t(N,O){for(var C=0;C<O.length;C++){var k=O[C];k.enumerable=k.enumerable||!1,k.configurable=!0,\"value\"in k&&(k.writable=!0),Object.defineProperty(N,k.key,k)}}function r(N,O,C){return O&&t(N.prototype,O),N}function o(N,O){var C=typeof Symbol<\"u\"&&N[Symbol.iterator]||N[\"@@iterator\"];if(!C){if(Array.isArray(N)||(C=s(N))||O){C&&(N=C);var k=0,z=function(){};return{s:z,n:function(){return k>=N.length?{done:!0}:{done:!1,value:N[k++]}},e:function(Be){throw Be},f:z}}throw new TypeError(`Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var B=!0,ce=!1,be;return{s:function(){C=C.call(N)},n:function(){var Be=C.next();return B=Be.done,Be},e:function(Be){ce=!0,be=Be},f:function(){try{!B&&C.return!=null&&C.return()}finally{if(ce)throw be}}}}function s(N,O){if(N){if(typeof N==\"string\")return c(N,O);var C=Object.prototype.toString.call(N).slice(8,-1);if(C===\"Object\"&&N.constructor&&(C=N.constructor.name),C===\"Map\"||C===\"Set\")return Array.from(N);if(C===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(C))return c(N,O)}}function c(N,O){(O==null||O>N.length)&&(O=N.length);for(var C=0,k=new Array(O);C<O;C++)k[C]=N[C];return k}var f=tce(),d={fg:\"#FFF\",bg:\"#000\",newline:!1,escapeXML:!1,stream:!1,colors:h()};function h(){var N={0:\"#000\",1:\"#A00\",2:\"#0A0\",3:\"#A50\",4:\"#00A\",5:\"#A0A\",6:\"#0AA\",7:\"#AAA\",8:\"#555\",9:\"#F55\",10:\"#5F5\",11:\"#FF5\",12:\"#55F\",13:\"#F5F\",14:\"#5FF\",15:\"#FFF\"};return P(0,5).forEach(function(O){P(0,5).forEach(function(C){P(0,5).forEach(function(k){return p(O,C,k,N)})})}),P(0,23).forEach(function(O){var C=O+232,k=g(O*10+8);N[C]=\"#\"+k+k+k}),N}function p(N,O,C,k){var z=16+N*36+O*6+C,B=N>0?N*40+55:0,ce=O>0?O*40+55:0,be=C>0?C*40+55:0;k[z]=v([B,ce,be])}function g(N){for(var O=N.toString(16);O.length<2;)O=\"0\"+O;return O}function v(N){var O=[],C=o(N),k;try{for(C.s();!(k=C.n()).done;){var z=k.value;O.push(g(z))}}catch(B){C.e(B)}finally{C.f()}return\"#\"+O.join(\"\")}function b(N,O,C,k){var z;return O===\"text\"?z=I(C,k):O===\"display\"?z=E(N,C,k):O===\"xterm256Foreground\"?z=W(N,k.colors[C]):O===\"xterm256Background\"?z=ne(N,k.colors[C]):O===\"rgb\"&&(z=w(N,C)),z}function w(N,O){O=O.substring(2).slice(0,-1);var C=+O.substr(0,2),k=O.substring(5).split(\";\"),z=k.map(function(B){return(\"0\"+Number(B).toString(16)).substr(-2)}).join(\"\");return $(N,(C===38?\"color:#\":\"background-color:#\")+z)}function E(N,O,C){O=parseInt(O,10);var k={\"-1\":function(){return\"<br/>\"},0:function(){return N.length&&L(N)},1:function(){return _(N,\"b\")},3:function(){return _(N,\"i\")},4:function(){return _(N,\"u\")},8:function(){return $(N,\"display:none\")},9:function(){return _(N,\"strike\")},22:function(){return $(N,\"font-weight:normal;text-decoration:none;font-style:normal\")},23:function(){return ee(N,\"i\")},24:function(){return ee(N,\"u\")},39:function(){return W(N,C.fg)},49:function(){return ne(N,C.bg)},53:function(){return $(N,\"text-decoration:overline\")}},z;return k[O]?z=k[O]():4<O&&O<7?z=_(N,\"blink\"):29<O&&O<38?z=W(N,C.colors[O-30]):39<O&&O<48?z=ne(N,C.colors[O-40]):89<O&&O<98?z=W(N,C.colors[8+(O-90)]):99<O&&O<108&&(z=ne(N,C.colors[8+(O-100)])),z}function L(N){var O=N.slice(0);return N.length=0,O.reverse().map(function(C){return\"</\"+C+\">\"}).join(\"\")}function P(N,O){for(var C=[],k=N;k<=O;k++)C.push(k);return C}function M(N){return function(O){return(N===null||O.category!==N)&&N!==\"all\"}}function R(N){N=parseInt(N,10);var O=null;return N===0?O=\"all\":N===1?O=\"bold\":2<N&&N<5?O=\"underline\":4<N&&N<7?O=\"blink\":N===8?O=\"hide\":N===9?O=\"strike\":29<N&&N<38||N===39||89<N&&N<98?O=\"foreground-color\":(39<N&&N<48||N===49||99<N&&N<108)&&(O=\"background-color\"),O}function I(N,O){return O.escapeXML?f.encodeXML(N):N}function _(N,O,C){return C||(C=\"\"),N.push(O),\"<\".concat(O).concat(C?' style=\"'.concat(C,'\"'):\"\",\">\")}function $(N,O){return _(N,\"span\",O)}function W(N,O){return _(N,\"span\",\"color:\"+O)}function ne(N,O){return _(N,\"span\",\"background-color:\"+O)}function ee(N,O){var C;if(N.slice(-1)[0]===O&&(C=N.pop()),C)return\"</\"+O+\">\"}function Z(N,O,C){var k=!1,z=3;function B(){return\"\"}function ce(q,Q){return C(\"xterm256Foreground\",Q),\"\"}function be(q,Q){return C(\"xterm256Background\",Q),\"\"}function Se(q){return O.newline?C(\"display\",-1):C(\"text\",q),\"\"}function Be(q,Q){k=!0,Q.trim().length===0&&(Q=\"0\"),Q=Q.trimRight(\";\").split(\";\");var he=o(Q),de;try{for(he.s();!(de=he.n()).done;){var ge=de.value;C(\"display\",ge)}}catch(Ce){he.e(Ce)}finally{he.f()}return\"\"}function Ae(q){return C(\"text\",q),\"\"}function Ke(q){return C(\"rgb\",q),\"\"}var je=[{pattern:/^\\x08+/,sub:B},{pattern:/^\\x1b\\[[012]?K/,sub:B},{pattern:/^\\x1b\\[\\(B/,sub:B},{pattern:/^\\x1b\\[[34]8;2;\\d+;\\d+;\\d+m/,sub:Ke},{pattern:/^\\x1b\\[38;5;(\\d+)m/,sub:ce},{pattern:/^\\x1b\\[48;5;(\\d+)m/,sub:be},{pattern:/^\\n/,sub:Se},{pattern:/^\\r+\\n/,sub:Se},{pattern:/^\\r/,sub:Se},{pattern:/^\\x1b\\[((?:\\d{1,3};?)+|)m/,sub:Be},{pattern:/^\\x1b\\[\\d?J/,sub:B},{pattern:/^\\x1b\\[\\d{0,3};\\d{0,3}f/,sub:B},{pattern:/^\\x1b\\[?[\\d;]{0,3}/,sub:B},{pattern:/^(([^\\x1b\\x08\\r\\n])+)/,sub:Ae}];function Fe(q,Q){Q>z&&k||(k=!1,N=N.replace(q.pattern,q.sub))}var Pe=[],F=N,Y=F.length;e:for(;Y>0;){for(var re=0,le=0,ae=je.length;le<ae;re=++le){var D=je[re];if(Fe(D,re),N.length!==Y){Y=N.length;continue e}}if(N.length===Y)break;Pe.push(0),Y=N.length}return Pe}function G(N,O,C){return O!==\"text\"&&(N=N.filter(M(R(C))),N.push({token:O,data:C,category:R(C)})),N}var j=(function(){function N(O){e(this,N),O=O||{},O.colors&&(O.colors=Object.assign({},d.colors,O.colors)),this.options=Object.assign({},d,O),this.stack=[],this.stickyStack=[]}return r(N,[{key:\"toHtml\",value:function(C){var k=this;C=typeof C==\"string\"?[C]:C;var z=this.stack,B=this.options,ce=[];return this.stickyStack.forEach(function(be){var Se=b(z,be.token,be.data,B);Se&&ce.push(Se)}),Z(C.join(\"\"),B,function(be,Se){var Be=b(z,be,Se,B);Be&&ce.push(Be),B.stream&&(k.stickyStack=G(k.stickyStack,be,Se))}),z.length&&ce.push(L(z)),ce.join(\"\")}}]),N})();return Ld=j,Ld}var rce=nce();const ice=ax(rce);function oa(e){return e.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\")}function oce(e,t){return t&&e.endsWith(t)}async function bp(e,t,r){const o=encodeURI(`${e}:${t}:${r}`);await fetch(`/__open-in-editor?file=${o}`)}function wp(e){return new ice({fg:e?\"#FFF\":\"#000\",bg:e?\"#000\":\"#FFF\"})}function sce(e){return e===null||typeof e!=\"function\"&&typeof e!=\"object\"}function fx(e){let t=e;if(sce(e)&&(t={message:String(t).split(/\\n/g)[0],stack:String(t),name:\"\",stacks:[]}),!e){const r=new Error(\"unknown error\");t={message:r.message,stack:r.stack,name:\"\",stacks:[]}}return t.stacks=wA(t.stack||\"\",{ignoreStackEntries:[]}),t}function lce(e,t){let r=\"\";return t.message?.includes(\"\\x1B\")&&(r=`<b>${t.name}</b>: ${e.toHtml(oa(t.message))}`),t.stack?.includes(\"\\x1B\")&&(r.length>0?r+=e.toHtml(oa(t.stack)):r=`<b>${t.name}</b>: ${t.message}${e.toHtml(oa(t.stack))}`),r.length>0?r:null}function dx(e,t){const r=wp(e);return t.map(o=>{const s=o.result;if(!s||s.htmlError)return o;const c=s.errors?.map(f=>lce(r,f)).filter(f=>f!=null).join(\"<br><br>\");return c?.length&&(s.htmlError=c),o})}const Wa=jE(\"hash\",{initialValue:{file:\"\",view:null,line:null,test:null,column:null}}),po=Yo(Wa,\"file\"),hn=Yo(Wa,\"view\"),hx=Yo(Wa,\"line\"),px=Yo(Wa,\"column\"),Bs=Yo(Wa,\"test\");var yy={exports:{}},by;function xp(){return by||(by=1,(function(e,t){(function(r){r(vo())})(function(r){r.defineMode(\"javascript\",function(o,s){var c=o.indentUnit,f=s.statementIndent,d=s.jsonld,h=s.json||d,p=s.trackScope!==!1,g=s.typescript,v=s.wordCharacters||/[\\w$\\xa1-\\uffff]/,b=(function(){function A(Zt){return{type:Zt,style:\"keyword\"}}var U=A(\"keyword a\"),me=A(\"keyword b\"),_e=A(\"keyword c\"),fe=A(\"keyword d\"),Ie=A(\"operator\"),pt={type:\"atom\",style:\"atom\"};return{if:A(\"if\"),while:U,with:U,else:me,do:me,try:me,finally:me,return:fe,break:fe,continue:fe,new:A(\"new\"),delete:_e,void:_e,throw:_e,debugger:A(\"debugger\"),var:A(\"var\"),const:A(\"var\"),let:A(\"var\"),function:A(\"function\"),catch:A(\"catch\"),for:A(\"for\"),switch:A(\"switch\"),case:A(\"case\"),default:A(\"default\"),in:Ie,typeof:Ie,instanceof:Ie,true:pt,false:pt,null:pt,undefined:pt,NaN:pt,Infinity:pt,this:A(\"this\"),class:A(\"class\"),super:A(\"atom\"),yield:_e,export:A(\"export\"),import:A(\"import\"),extends:_e,await:_e}})(),w=/[+\\-*&%=<>!?|~^@]/,E=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)\"/;function L(A){for(var U=!1,me,_e=!1;(me=A.next())!=null;){if(!U){if(me==\"/\"&&!_e)return;me==\"[\"?_e=!0:_e&&me==\"]\"&&(_e=!1)}U=!U&&me==\"\\\\\"}}var P,M;function R(A,U,me){return P=A,M=me,U}function I(A,U){var me=A.next();if(me=='\"'||me==\"'\")return U.tokenize=_(me),U.tokenize(A,U);if(me==\".\"&&A.match(/^\\d[\\d_]*(?:[eE][+\\-]?[\\d_]+)?/))return R(\"number\",\"number\");if(me==\".\"&&A.match(\"..\"))return R(\"spread\",\"meta\");if(/[\\[\\]{}\\(\\),;\\:\\.]/.test(me))return R(me);if(me==\"=\"&&A.eat(\">\"))return R(\"=>\",\"operator\");if(me==\"0\"&&A.match(/^(?:x[\\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/))return R(\"number\",\"number\");if(/\\d/.test(me))return A.match(/^[\\d_]*(?:n|(?:\\.[\\d_]*)?(?:[eE][+\\-]?[\\d_]+)?)?/),R(\"number\",\"number\");if(me==\"/\")return A.eat(\"*\")?(U.tokenize=$,$(A,U)):A.eat(\"/\")?(A.skipToEnd(),R(\"comment\",\"comment\")):Qn(A,U,1)?(L(A),A.match(/^\\b(([gimyus])(?![gimyus]*\\2))+\\b/),R(\"regexp\",\"string-2\")):(A.eat(\"=\"),R(\"operator\",\"operator\",A.current()));if(me==\"`\")return U.tokenize=W,W(A,U);if(me==\"#\"&&A.peek()==\"!\")return A.skipToEnd(),R(\"meta\",\"meta\");if(me==\"#\"&&A.eatWhile(v))return R(\"variable\",\"property\");if(me==\"<\"&&A.match(\"!--\")||me==\"-\"&&A.match(\"->\")&&!/\\S/.test(A.string.slice(0,A.start)))return A.skipToEnd(),R(\"comment\",\"comment\");if(w.test(me))return(me!=\">\"||!U.lexical||U.lexical.type!=\">\")&&(A.eat(\"=\")?(me==\"!\"||me==\"=\")&&A.eat(\"=\"):/[<>*+\\-|&?]/.test(me)&&(A.eat(me),me==\">\"&&A.eat(me))),me==\"?\"&&A.eat(\".\")?R(\".\"):R(\"operator\",\"operator\",A.current());if(v.test(me)){A.eatWhile(v);var _e=A.current();if(U.lastType!=\".\"){if(b.propertyIsEnumerable(_e)){var fe=b[_e];return R(fe.type,fe.style,_e)}if(_e==\"async\"&&A.match(/^(\\s|\\/\\*([^*]|\\*(?!\\/))*?\\*\\/)*[\\[\\(\\w]/,!1))return R(\"async\",\"keyword\",_e)}return R(\"variable\",\"variable\",_e)}}function _(A){return function(U,me){var _e=!1,fe;if(d&&U.peek()==\"@\"&&U.match(E))return me.tokenize=I,R(\"jsonld-keyword\",\"meta\");for(;(fe=U.next())!=null&&!(fe==A&&!_e);)_e=!_e&&fe==\"\\\\\";return _e||(me.tokenize=I),R(\"string\",\"string\")}}function $(A,U){for(var me=!1,_e;_e=A.next();){if(_e==\"/\"&&me){U.tokenize=I;break}me=_e==\"*\"}return R(\"comment\",\"comment\")}function W(A,U){for(var me=!1,_e;(_e=A.next())!=null;){if(!me&&(_e==\"`\"||_e==\"$\"&&A.eat(\"{\"))){U.tokenize=I;break}me=!me&&_e==\"\\\\\"}return R(\"quasi\",\"string-2\",A.current())}var ne=\"([{}])\";function ee(A,U){U.fatArrowAt&&(U.fatArrowAt=null);var me=A.string.indexOf(\"=>\",A.start);if(!(me<0)){if(g){var _e=/:\\s*(?:\\w+(?:<[^>]*>|\\[\\])?|\\{[^}]*\\})\\s*$/.exec(A.string.slice(A.start,me));_e&&(me=_e.index)}for(var fe=0,Ie=!1,pt=me-1;pt>=0;--pt){var Zt=A.string.charAt(pt),Sn=ne.indexOf(Zt);if(Sn>=0&&Sn<3){if(!fe){++pt;break}if(--fe==0){Zt==\"(\"&&(Ie=!0);break}}else if(Sn>=3&&Sn<6)++fe;else if(v.test(Zt))Ie=!0;else if(/[\"'\\/`]/.test(Zt))for(;;--pt){if(pt==0)return;var is=A.string.charAt(pt-1);if(is==Zt&&A.string.charAt(pt-2)!=\"\\\\\"){pt--;break}}else if(Ie&&!fe){++pt;break}}Ie&&!fe&&(U.fatArrowAt=pt)}}var Z={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,this:!0,import:!0,\"jsonld-keyword\":!0};function G(A,U,me,_e,fe,Ie){this.indented=A,this.column=U,this.type=me,this.prev=fe,this.info=Ie,_e!=null&&(this.align=_e)}function j(A,U){if(!p)return!1;for(var me=A.localVars;me;me=me.next)if(me.name==U)return!0;for(var _e=A.context;_e;_e=_e.prev)for(var me=_e.vars;me;me=me.next)if(me.name==U)return!0}function N(A,U,me,_e,fe){var Ie=A.cc;for(O.state=A,O.stream=fe,O.marked=null,O.cc=Ie,O.style=U,A.lexical.hasOwnProperty(\"align\")||(A.lexical.align=!0);;){var pt=Ie.length?Ie.pop():h?ae:re;if(pt(me,_e)){for(;Ie.length&&Ie[Ie.length-1].lex;)Ie.pop()();return O.marked?O.marked:me==\"variable\"&&j(A,_e)?\"variable-2\":U}}}var O={state:null,marked:null,cc:null};function C(){for(var A=arguments.length-1;A>=0;A--)O.cc.push(arguments[A])}function k(){return C.apply(null,arguments),!0}function z(A,U){for(var me=U;me;me=me.next)if(me.name==A)return!0;return!1}function B(A){var U=O.state;if(O.marked=\"def\",!!p){if(U.context){if(U.lexical.info==\"var\"&&U.context&&U.context.block){var me=ce(A,U.context);if(me!=null){U.context=me;return}}else if(!z(A,U.localVars)){U.localVars=new Be(A,U.localVars);return}}s.globalVars&&!z(A,U.globalVars)&&(U.globalVars=new Be(A,U.globalVars))}}function ce(A,U){if(U)if(U.block){var me=ce(A,U.prev);return me?me==U.prev?U:new Se(me,U.vars,!0):null}else return z(A,U.vars)?U:new Se(U.prev,new Be(A,U.vars),!1);else return null}function be(A){return A==\"public\"||A==\"private\"||A==\"protected\"||A==\"abstract\"||A==\"readonly\"}function Se(A,U,me){this.prev=A,this.vars=U,this.block=me}function Be(A,U){this.name=A,this.next=U}var Ae=new Be(\"this\",new Be(\"arguments\",null));function Ke(){O.state.context=new Se(O.state.context,O.state.localVars,!1),O.state.localVars=Ae}function je(){O.state.context=new Se(O.state.context,O.state.localVars,!0),O.state.localVars=null}Ke.lex=je.lex=!0;function Fe(){O.state.localVars=O.state.context.vars,O.state.context=O.state.context.prev}Fe.lex=!0;function Pe(A,U){var me=function(){var _e=O.state,fe=_e.indented;if(_e.lexical.type==\"stat\")fe=_e.lexical.indented;else for(var Ie=_e.lexical;Ie&&Ie.type==\")\"&&Ie.align;Ie=Ie.prev)fe=Ie.indented;_e.lexical=new G(fe,O.stream.column(),A,null,_e.lexical,U)};return me.lex=!0,me}function F(){var A=O.state;A.lexical.prev&&(A.lexical.type==\")\"&&(A.indented=A.lexical.indented),A.lexical=A.lexical.prev)}F.lex=!0;function Y(A){function U(me){return me==A?k():A==\";\"||me==\"}\"||me==\")\"||me==\"]\"?C():k(U)}return U}function re(A,U){return A==\"var\"?k(Pe(\"vardef\",U),Zo,Y(\";\"),F):A==\"keyword a\"?k(Pe(\"form\"),q,re,F):A==\"keyword b\"?k(Pe(\"form\"),re,F):A==\"keyword d\"?O.stream.match(/^\\s*$/,!1)?k():k(Pe(\"stat\"),he,Y(\";\"),F):A==\"debugger\"?k(Y(\";\")):A==\"{\"?k(Pe(\"}\"),je,jt,F,Fe):A==\";\"?k():A==\"if\"?(O.state.lexical.info==\"else\"&&O.state.cc[O.state.cc.length-1]==F&&O.state.cc.pop()(),k(Pe(\"form\"),q,re,F,Jo)):A==\"function\"?k(cr):A==\"for\"?k(Pe(\"form\"),je,Ga,re,Fe,F):A==\"class\"||g&&U==\"interface\"?(O.marked=\"keyword\",k(Pe(\"form\",A==\"class\"?A:U),Qo,F)):A==\"variable\"?g&&U==\"declare\"?(O.marked=\"keyword\",k(re)):g&&(U==\"module\"||U==\"enum\"||U==\"type\")&&O.stream.match(/^\\s*\\w/,!1)?(O.marked=\"keyword\",U==\"enum\"?k(qe):U==\"type\"?k(Ka,Y(\"operator\"),lt,Y(\";\")):k(Pe(\"form\"),kn,Y(\"{\"),Pe(\"}\"),jt,F,F)):g&&U==\"namespace\"?(O.marked=\"keyword\",k(Pe(\"form\"),ae,re,F)):g&&U==\"abstract\"?(O.marked=\"keyword\",k(re)):k(Pe(\"stat\"),$e):A==\"switch\"?k(Pe(\"form\"),q,Y(\"{\"),Pe(\"}\",\"switch\"),je,jt,F,F,Fe):A==\"case\"?k(ae,Y(\":\")):A==\"default\"?k(Y(\":\")):A==\"catch\"?k(Pe(\"form\"),Ke,le,re,F,Fe):A==\"export\"?k(Pe(\"stat\"),es,F):A==\"import\"?k(Pe(\"stat\"),$i,F):A==\"async\"?k(re):U==\"@\"?k(ae,re):C(Pe(\"stat\"),ae,Y(\";\"),F)}function le(A){if(A==\"(\")return k(wr,Y(\")\"))}function ae(A,U){return Q(A,U,!1)}function D(A,U){return Q(A,U,!0)}function q(A){return A!=\"(\"?C():k(Pe(\")\"),he,Y(\")\"),F)}function Q(A,U,me){if(O.state.fatArrowAt==O.stream.start){var _e=me?ye:xe;if(A==\"(\")return k(Ke,Pe(\")\"),ut(wr,\")\"),F,Y(\"=>\"),_e,Fe);if(A==\"variable\")return C(Ke,kn,Y(\"=>\"),_e,Fe)}var fe=me?ge:de;return Z.hasOwnProperty(A)?k(fe):A==\"function\"?k(cr,fe):A==\"class\"||g&&U==\"interface\"?(O.marked=\"keyword\",k(Pe(\"form\"),vf,F)):A==\"keyword c\"||A==\"async\"?k(me?D:ae):A==\"(\"?k(Pe(\")\"),he,Y(\")\"),F,fe):A==\"operator\"||A==\"spread\"?k(me?D:ae):A==\"[\"?k(Pe(\"]\"),$t,F,fe):A==\"{\"?Yt(ct,\"}\",null,fe):A==\"quasi\"?C(Ce,fe):A==\"new\"?k(J(me)):k()}function he(A){return A.match(/[;\\}\\)\\],]/)?C():C(ae)}function de(A,U){return A==\",\"?k(he):ge(A,U,!1)}function ge(A,U,me){var _e=me==!1?de:ge,fe=me==!1?ae:D;if(A==\"=>\")return k(Ke,me?ye:xe,Fe);if(A==\"operator\")return/\\+\\+|--/.test(U)||g&&U==\"!\"?k(_e):g&&U==\"<\"&&O.stream.match(/^([^<>]|<[^<>]*>)*>\\s*\\(/,!1)?k(Pe(\">\"),ut(lt,\">\"),F,_e):U==\"?\"?k(ae,Y(\":\"),fe):k(fe);if(A==\"quasi\")return C(Ce,_e);if(A!=\";\"){if(A==\"(\")return Yt(D,\")\",\"call\",_e);if(A==\".\")return k(Je,_e);if(A==\"[\")return k(Pe(\"]\"),he,Y(\"]\"),F,_e);if(g&&U==\"as\")return O.marked=\"keyword\",k(lt,_e);if(A==\"regexp\")return O.state.lastType=O.marked=\"operator\",O.stream.backUp(O.stream.pos-O.stream.start-1),k(fe)}}function Ce(A,U){return A!=\"quasi\"?C():U.slice(U.length-2)!=\"${\"?k(Ce):k(he,Ee)}function Ee(A){if(A==\"}\")return O.marked=\"string-2\",O.state.tokenize=W,k(Ce)}function xe(A){return ee(O.stream,O.state),C(A==\"{\"?re:ae)}function ye(A){return ee(O.stream,O.state),C(A==\"{\"?re:D)}function J(A){return function(U){return U==\".\"?k(A?oe:ue):U==\"variable\"&&g?k(Bn,A?ge:de):C(A?D:ae)}}function ue(A,U){if(U==\"target\")return O.marked=\"keyword\",k(de)}function oe(A,U){if(U==\"target\")return O.marked=\"keyword\",k(ge)}function $e(A){return A==\":\"?k(F,re):C(de,Y(\";\"),F)}function Je(A){if(A==\"variable\")return O.marked=\"property\",k()}function ct(A,U){if(A==\"async\")return O.marked=\"property\",k(ct);if(A==\"variable\"||O.style==\"keyword\"){if(O.marked=\"property\",U==\"get\"||U==\"set\")return k(dt);var me;return g&&O.state.fatArrowAt==O.stream.start&&(me=O.stream.match(/^\\s*:\\s*/,!1))&&(O.state.fatArrowAt=O.stream.pos+me[0].length),k(Nt)}else{if(A==\"number\"||A==\"string\")return O.marked=d?\"property\":O.style+\" property\",k(Nt);if(A==\"jsonld-keyword\")return k(Nt);if(g&&be(U))return O.marked=\"keyword\",k(ct);if(A==\"[\")return k(ae,Fn,Y(\"]\"),Nt);if(A==\"spread\")return k(D,Nt);if(U==\"*\")return O.marked=\"keyword\",k(ct);if(A==\":\")return C(Nt)}}function dt(A){return A!=\"variable\"?C(Nt):(O.marked=\"property\",k(cr))}function Nt(A){if(A==\":\")return k(D);if(A==\"(\")return C(cr)}function ut(A,U,me){function _e(fe,Ie){if(me?me.indexOf(fe)>-1:fe==\",\"){var pt=O.state.lexical;return pt.info==\"call\"&&(pt.pos=(pt.pos||0)+1),k(function(Zt,Sn){return Zt==U||Sn==U?C():C(A)},_e)}return fe==U||Ie==U?k():me&&me.indexOf(\";\")>-1?C(A):k(Y(U))}return function(fe,Ie){return fe==U||Ie==U?k():C(A,_e)}}function Yt(A,U,me){for(var _e=3;_e<arguments.length;_e++)O.cc.push(arguments[_e]);return k(Pe(U,me),ut(A,U),F)}function jt(A){return A==\"}\"?k():C(re,jt)}function Fn(A,U){if(g){if(A==\":\")return k(lt);if(U==\"?\")return k(Fn)}}function Hr(A,U){if(g&&(A==\":\"||U==\"in\"))return k(lt)}function Bt(A){if(g&&A==\":\")return O.stream.match(/^\\s*\\w+\\s+is\\b/,!1)?k(ae,Hn,lt):k(lt)}function Hn(A,U){if(U==\"is\")return O.marked=\"keyword\",k()}function lt(A,U){if(U==\"keyof\"||U==\"typeof\"||U==\"infer\"||U==\"readonly\")return O.marked=\"keyword\",k(U==\"typeof\"?D:lt);if(A==\"variable\"||U==\"void\")return O.marked=\"type\",k(ar);if(U==\"|\"||U==\"&\")return k(lt);if(A==\"string\"||A==\"number\"||A==\"atom\")return k(ar);if(A==\"[\")return k(Pe(\"]\"),ut(lt,\"]\",\",\"),F,ar);if(A==\"{\")return k(Pe(\"}\"),Xe,F,ar);if(A==\"(\")return k(ut(Rt,\")\"),yo,ar);if(A==\"<\")return k(ut(lt,\">\"),lt);if(A==\"quasi\")return C(an,ar)}function yo(A){if(A==\"=>\")return k(lt)}function Xe(A){return A.match(/[\\}\\)\\]]/)?k():A==\",\"||A==\";\"?k(Xe):C(ri,Xe)}function ri(A,U){if(A==\"variable\"||O.style==\"keyword\")return O.marked=\"property\",k(ri);if(U==\"?\"||A==\"number\"||A==\"string\")return k(ri);if(A==\":\")return k(lt);if(A==\"[\")return k(Y(\"variable\"),Hr,Y(\"]\"),ri);if(A==\"(\")return C(Ri,ri);if(!A.match(/[;\\}\\)\\],]/))return k()}function an(A,U){return A!=\"quasi\"?C():U.slice(U.length-2)!=\"${\"?k(an):k(lt,Pt)}function Pt(A){if(A==\"}\")return O.marked=\"string-2\",O.state.tokenize=W,k(an)}function Rt(A,U){return A==\"variable\"&&O.stream.match(/^\\s*[?:]/,!1)||U==\"?\"?k(Rt):A==\":\"?k(lt):A==\"spread\"?k(Rt):C(lt)}function ar(A,U){if(U==\"<\")return k(Pe(\">\"),ut(lt,\">\"),F,ar);if(U==\"|\"||A==\".\"||U==\"&\")return k(lt);if(A==\"[\")return k(lt,Y(\"]\"),ar);if(U==\"extends\"||U==\"implements\")return O.marked=\"keyword\",k(lt);if(U==\"?\")return k(lt,Y(\":\"),lt)}function Bn(A,U){if(U==\"<\")return k(Pe(\">\"),ut(lt,\">\"),F,ar)}function yr(){return C(lt,cn)}function cn(A,U){if(U==\"=\")return k(lt)}function Zo(A,U){return U==\"enum\"?(O.marked=\"keyword\",k(qe)):C(kn,Fn,br,mf)}function kn(A,U){if(g&&be(U))return O.marked=\"keyword\",k(kn);if(A==\"variable\")return B(U),k();if(A==\"spread\")return k(kn);if(A==\"[\")return Yt(sl,\"]\");if(A==\"{\")return Yt(Oi,\"}\")}function Oi(A,U){return A==\"variable\"&&!O.stream.match(/^\\s*:/,!1)?(B(U),k(br)):(A==\"variable\"&&(O.marked=\"property\"),A==\"spread\"?k(kn):A==\"}\"?C():A==\"[\"?k(ae,Y(\"]\"),Y(\":\"),Oi):k(Y(\":\"),kn,br))}function sl(){return C(kn,br)}function br(A,U){if(U==\"=\")return k(D)}function mf(A){if(A==\",\")return k(Zo)}function Jo(A,U){if(A==\"keyword b\"&&U==\"else\")return k(Pe(\"form\",\"else\"),re,F)}function Ga(A,U){if(U==\"await\")return k(Ga);if(A==\"(\")return k(Pe(\")\"),ll,F)}function ll(A){return A==\"var\"?k(Zo,Pi):A==\"variable\"?k(Pi):C(Pi)}function Pi(A,U){return A==\")\"?k():A==\";\"?k(Pi):U==\"in\"||U==\"of\"?(O.marked=\"keyword\",k(ae,Pi)):C(ae,Pi)}function cr(A,U){if(U==\"*\")return O.marked=\"keyword\",k(cr);if(A==\"variable\")return B(U),k(cr);if(A==\"(\")return k(Ke,Pe(\")\"),ut(wr,\")\"),F,Bt,re,Fe);if(g&&U==\"<\")return k(Pe(\">\"),ut(yr,\">\"),F,cr)}function Ri(A,U){if(U==\"*\")return O.marked=\"keyword\",k(Ri);if(A==\"variable\")return B(U),k(Ri);if(A==\"(\")return k(Ke,Pe(\")\"),ut(wr,\")\"),F,Bt,Fe);if(g&&U==\"<\")return k(Pe(\">\"),ut(yr,\">\"),F,Ri)}function Ka(A,U){if(A==\"keyword\"||A==\"variable\")return O.marked=\"type\",k(Ka);if(U==\"<\")return k(Pe(\">\"),ut(yr,\">\"),F)}function wr(A,U){return U==\"@\"&&k(ae,wr),A==\"spread\"?k(wr):g&&be(U)?(O.marked=\"keyword\",k(wr)):g&&A==\"this\"?k(Fn,br):C(kn,Fn,br)}function vf(A,U){return A==\"variable\"?Qo(A,U):xr(A,U)}function Qo(A,U){if(A==\"variable\")return B(U),k(xr)}function xr(A,U){if(U==\"<\")return k(Pe(\">\"),ut(yr,\">\"),F,xr);if(U==\"extends\"||U==\"implements\"||g&&A==\",\")return U==\"implements\"&&(O.marked=\"keyword\"),k(g?lt:ae,xr);if(A==\"{\")return k(Pe(\"}\"),kr,F)}function kr(A,U){if(A==\"async\"||A==\"variable\"&&(U==\"static\"||U==\"get\"||U==\"set\"||g&&be(U))&&O.stream.match(/^\\s+#?[\\w$\\xa1-\\uffff]/,!1))return O.marked=\"keyword\",k(kr);if(A==\"variable\"||O.style==\"keyword\")return O.marked=\"property\",k(bo,kr);if(A==\"number\"||A==\"string\")return k(bo,kr);if(A==\"[\")return k(ae,Fn,Y(\"]\"),bo,kr);if(U==\"*\")return O.marked=\"keyword\",k(kr);if(g&&A==\"(\")return C(Ri,kr);if(A==\";\"||A==\",\")return k(kr);if(A==\"}\")return k();if(U==\"@\")return k(ae,kr)}function bo(A,U){if(U==\"!\"||U==\"?\")return k(bo);if(A==\":\")return k(lt,br);if(U==\"=\")return k(D);var me=O.state.lexical.prev,_e=me&&me.info==\"interface\";return C(_e?Ri:cr)}function es(A,U){return U==\"*\"?(O.marked=\"keyword\",k(rs,Y(\";\"))):U==\"default\"?(O.marked=\"keyword\",k(ae,Y(\";\"))):A==\"{\"?k(ut(ts,\"}\"),rs,Y(\";\")):C(re)}function ts(A,U){if(U==\"as\")return O.marked=\"keyword\",k(Y(\"variable\"));if(A==\"variable\")return C(D,ts)}function $i(A){return A==\"string\"?k():A==\"(\"?C(ae):A==\".\"?C(de):C(ns,Br,rs)}function ns(A,U){return A==\"{\"?Yt(ns,\"}\"):(A==\"variable\"&&B(U),U==\"*\"&&(O.marked=\"keyword\"),k(al))}function Br(A){if(A==\",\")return k(ns,Br)}function al(A,U){if(U==\"as\")return O.marked=\"keyword\",k(ns)}function rs(A,U){if(U==\"from\")return O.marked=\"keyword\",k(ae)}function $t(A){return A==\"]\"?k():C(ut(D,\"]\"))}function qe(){return C(Pe(\"form\"),kn,Y(\"{\"),Pe(\"}\"),ut(ii,\"}\"),F,F)}function ii(){return C(kn,br)}function cl(A,U){return A.lastType==\"operator\"||A.lastType==\",\"||w.test(U.charAt(0))||/[,.]/.test(U.charAt(0))}function Qn(A,U,me){return U.tokenize==I&&/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\\[{}\\(,;:]|=>)$/.test(U.lastType)||U.lastType==\"quasi\"&&/\\{\\s*$/.test(A.string.slice(0,A.pos-(me||0)))}return{startState:function(A){var U={tokenize:I,lastType:\"sof\",cc:[],lexical:new G((A||0)-c,0,\"block\",!1),localVars:s.localVars,context:s.localVars&&new Se(null,null,!1),indented:A||0};return s.globalVars&&typeof s.globalVars==\"object\"&&(U.globalVars=s.globalVars),U},token:function(A,U){if(A.sol()&&(U.lexical.hasOwnProperty(\"align\")||(U.lexical.align=!1),U.indented=A.indentation(),ee(A,U)),U.tokenize!=$&&A.eatSpace())return null;var me=U.tokenize(A,U);return P==\"comment\"?me:(U.lastType=P==\"operator\"&&(M==\"++\"||M==\"--\")?\"incdec\":P,N(U,me,P,M,A))},indent:function(A,U){if(A.tokenize==$||A.tokenize==W)return r.Pass;if(A.tokenize!=I)return 0;var me=U&&U.charAt(0),_e=A.lexical,fe;if(!/^\\s*else\\b/.test(U))for(var Ie=A.cc.length-1;Ie>=0;--Ie){var pt=A.cc[Ie];if(pt==F)_e=_e.prev;else if(pt!=Jo&&pt!=Fe)break}for(;(_e.type==\"stat\"||_e.type==\"form\")&&(me==\"}\"||(fe=A.cc[A.cc.length-1])&&(fe==de||fe==ge)&&!/^[,\\.=+\\-*:?[\\(]/.test(U));)_e=_e.prev;f&&_e.type==\")\"&&_e.prev.type==\"stat\"&&(_e=_e.prev);var Zt=_e.type,Sn=me==Zt;return Zt==\"vardef\"?_e.indented+(A.lastType==\"operator\"||A.lastType==\",\"?_e.info.length+1:0):Zt==\"form\"&&me==\"{\"?_e.indented:Zt==\"form\"?_e.indented+c:Zt==\"stat\"?_e.indented+(cl(A,U)?f||c:0):_e.info==\"switch\"&&!Sn&&s.doubleIndentSwitch!=!1?_e.indented+(/^(?:case|default)\\b/.test(U)?c:2*c):_e.align?_e.column+(Sn?0:1):_e.indented+(Sn?0:c)},electricInput:/^\\s*(?:case .*?:|default:|\\{|\\})$/,blockCommentStart:h?null:\"/*\",blockCommentEnd:h?null:\"*/\",blockCommentContinue:h?null:\" * \",lineComment:h?null:\"//\",fold:\"brace\",closeBrackets:\"()[]{}''\\\"\\\"``\",helperType:h?\"json\":\"javascript\",jsonldMode:d,jsonMode:h,expressionAllowed:Qn,skipExpression:function(A){N(A,\"atom\",\"atom\",\"true\",new r.StringStream(\"\",2,null))}}}),r.registerHelper(\"wordChars\",\"javascript\",/[\\w$]/),r.defineMIME(\"text/javascript\",\"javascript\"),r.defineMIME(\"text/ecmascript\",\"javascript\"),r.defineMIME(\"application/javascript\",\"javascript\"),r.defineMIME(\"application/x-javascript\",\"javascript\"),r.defineMIME(\"application/ecmascript\",\"javascript\"),r.defineMIME(\"application/json\",{name:\"javascript\",json:!0}),r.defineMIME(\"application/x-json\",{name:\"javascript\",json:!0}),r.defineMIME(\"application/manifest+json\",{name:\"javascript\",json:!0}),r.defineMIME(\"application/ld+json\",{name:\"javascript\",jsonld:!0}),r.defineMIME(\"text/typescript\",{name:\"javascript\",typescript:!0}),r.defineMIME(\"application/typescript\",{name:\"javascript\",typescript:!0})})})()),yy.exports}xp();var wy={exports:{}},xy;function kp(){return xy||(xy=1,(function(e,t){(function(r){r(vo())})(function(r){var o={autoSelfClosers:{area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,frame:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0,menuitem:!0},implicitlyClosed:{dd:!0,li:!0,optgroup:!0,option:!0,p:!0,rp:!0,rt:!0,tbody:!0,td:!0,tfoot:!0,th:!0,tr:!0},contextGrabbers:{dd:{dd:!0,dt:!0},dt:{dd:!0,dt:!0},li:{li:!0},option:{option:!0,optgroup:!0},optgroup:{optgroup:!0},p:{address:!0,article:!0,aside:!0,blockquote:!0,dir:!0,div:!0,dl:!0,fieldset:!0,footer:!0,form:!0,h1:!0,h2:!0,h3:!0,h4:!0,h5:!0,h6:!0,header:!0,hgroup:!0,hr:!0,menu:!0,nav:!0,ol:!0,p:!0,pre:!0,section:!0,table:!0,ul:!0},rp:{rp:!0,rt:!0},rt:{rp:!0,rt:!0},tbody:{tbody:!0,tfoot:!0},td:{td:!0,th:!0},tfoot:{tbody:!0},th:{td:!0,th:!0},thead:{tbody:!0,tfoot:!0},tr:{tr:!0}},doNotIndent:{pre:!0},allowUnquoted:!0,allowMissing:!0,caseFold:!0},s={autoSelfClosers:{},implicitlyClosed:{},contextGrabbers:{},doNotIndent:{},allowUnquoted:!1,allowMissing:!1,allowMissingTagName:!1,caseFold:!1};r.defineMode(\"xml\",function(c,f){var d=c.indentUnit,h={},p=f.htmlMode?o:s;for(var g in p)h[g]=p[g];for(var g in f)h[g]=f[g];var v,b;function w(k,z){function B(Se){return z.tokenize=Se,Se(k,z)}var ce=k.next();if(ce==\"<\")return k.eat(\"!\")?k.eat(\"[\")?k.match(\"CDATA[\")?B(P(\"atom\",\"]]>\")):null:k.match(\"--\")?B(P(\"comment\",\"-->\")):k.match(\"DOCTYPE\",!0,!0)?(k.eatWhile(/[\\w\\._\\-]/),B(M(1))):null:k.eat(\"?\")?(k.eatWhile(/[\\w\\._\\-]/),z.tokenize=P(\"meta\",\"?>\"),\"meta\"):(v=k.eat(\"/\")?\"closeTag\":\"openTag\",z.tokenize=E,\"tag bracket\");if(ce==\"&\"){var be;return k.eat(\"#\")?k.eat(\"x\")?be=k.eatWhile(/[a-fA-F\\d]/)&&k.eat(\";\"):be=k.eatWhile(/[\\d]/)&&k.eat(\";\"):be=k.eatWhile(/[\\w\\.\\-:]/)&&k.eat(\";\"),be?\"atom\":\"error\"}else return k.eatWhile(/[^&<]/),null}w.isInText=!0;function E(k,z){var B=k.next();if(B==\">\"||B==\"/\"&&k.eat(\">\"))return z.tokenize=w,v=B==\">\"?\"endTag\":\"selfcloseTag\",\"tag bracket\";if(B==\"=\")return v=\"equals\",null;if(B==\"<\"){z.tokenize=w,z.state=W,z.tagName=z.tagStart=null;var ce=z.tokenize(k,z);return ce?ce+\" tag error\":\"tag error\"}else return/[\\'\\\"]/.test(B)?(z.tokenize=L(B),z.stringStartCol=k.column(),z.tokenize(k,z)):(k.match(/^[^\\s\\u00a0=<>\\\"\\']*[^\\s\\u00a0=<>\\\"\\'\\/]/),\"word\")}function L(k){var z=function(B,ce){for(;!B.eol();)if(B.next()==k){ce.tokenize=E;break}return\"string\"};return z.isInAttribute=!0,z}function P(k,z){return function(B,ce){for(;!B.eol();){if(B.match(z)){ce.tokenize=w;break}B.next()}return k}}function M(k){return function(z,B){for(var ce;(ce=z.next())!=null;){if(ce==\"<\")return B.tokenize=M(k+1),B.tokenize(z,B);if(ce==\">\")if(k==1){B.tokenize=w;break}else return B.tokenize=M(k-1),B.tokenize(z,B)}return\"meta\"}}function R(k){return k&&k.toLowerCase()}function I(k,z,B){this.prev=k.context,this.tagName=z||\"\",this.indent=k.indented,this.startOfLine=B,(h.doNotIndent.hasOwnProperty(z)||k.context&&k.context.noIndent)&&(this.noIndent=!0)}function _(k){k.context&&(k.context=k.context.prev)}function $(k,z){for(var B;;){if(!k.context||(B=k.context.tagName,!h.contextGrabbers.hasOwnProperty(R(B))||!h.contextGrabbers[R(B)].hasOwnProperty(R(z))))return;_(k)}}function W(k,z,B){return k==\"openTag\"?(B.tagStart=z.column(),ne):k==\"closeTag\"?ee:W}function ne(k,z,B){return k==\"word\"?(B.tagName=z.current(),b=\"tag\",j):h.allowMissingTagName&&k==\"endTag\"?(b=\"tag bracket\",j(k,z,B)):(b=\"error\",ne)}function ee(k,z,B){if(k==\"word\"){var ce=z.current();return B.context&&B.context.tagName!=ce&&h.implicitlyClosed.hasOwnProperty(R(B.context.tagName))&&_(B),B.context&&B.context.tagName==ce||h.matchClosing===!1?(b=\"tag\",Z):(b=\"tag error\",G)}else return h.allowMissingTagName&&k==\"endTag\"?(b=\"tag bracket\",Z(k,z,B)):(b=\"error\",G)}function Z(k,z,B){return k!=\"endTag\"?(b=\"error\",Z):(_(B),W)}function G(k,z,B){return b=\"error\",Z(k,z,B)}function j(k,z,B){if(k==\"word\")return b=\"attribute\",N;if(k==\"endTag\"||k==\"selfcloseTag\"){var ce=B.tagName,be=B.tagStart;return B.tagName=B.tagStart=null,k==\"selfcloseTag\"||h.autoSelfClosers.hasOwnProperty(R(ce))?$(B,ce):($(B,ce),B.context=new I(B,ce,be==B.indented)),W}return b=\"error\",j}function N(k,z,B){return k==\"equals\"?O:(h.allowMissing||(b=\"error\"),j(k,z,B))}function O(k,z,B){return k==\"string\"?C:k==\"word\"&&h.allowUnquoted?(b=\"string\",j):(b=\"error\",j(k,z,B))}function C(k,z,B){return k==\"string\"?C:j(k,z,B)}return{startState:function(k){var z={tokenize:w,state:W,indented:k||0,tagName:null,tagStart:null,context:null};return k!=null&&(z.baseIndent=k),z},token:function(k,z){if(!z.tagName&&k.sol()&&(z.indented=k.indentation()),k.eatSpace())return null;v=null;var B=z.tokenize(k,z);return(B||v)&&B!=\"comment\"&&(b=null,z.state=z.state(v||B,k,z),b&&(B=b==\"error\"?B+\" error\":b)),B},indent:function(k,z,B){var ce=k.context;if(k.tokenize.isInAttribute)return k.tagStart==k.indented?k.stringStartCol+1:k.indented+d;if(ce&&ce.noIndent)return r.Pass;if(k.tokenize!=E&&k.tokenize!=w)return B?B.match(/^(\\s*)/)[0].length:0;if(k.tagName)return h.multilineTagIndentPastTag!==!1?k.tagStart+k.tagName.length+2:k.tagStart+d*(h.multilineTagIndentFactor||1);if(h.alignCDATA&&/<!\\[CDATA\\[/.test(z))return 0;var be=z&&/^<(\\/)?([\\w_:\\.-]*)/.exec(z);if(be&&be[1])for(;ce;)if(ce.tagName==be[2]){ce=ce.prev;break}else if(h.implicitlyClosed.hasOwnProperty(R(ce.tagName)))ce=ce.prev;else break;else if(be)for(;ce;){var Se=h.contextGrabbers[R(ce.tagName)];if(Se&&Se.hasOwnProperty(R(be[2])))ce=ce.prev;else break}for(;ce&&ce.prev&&!ce.startOfLine;)ce=ce.prev;return ce?ce.indent+d:k.baseIndent||0},electricInput:/<\\/[\\s\\w:]+>$/,blockCommentStart:\"<!--\",blockCommentEnd:\"-->\",configuration:h.htmlMode?\"html\":\"xml\",helperType:h.htmlMode?\"html\":\"xml\",skipAttribute:function(k){k.state==O&&(k.state=j)},xmlCurrentTag:function(k){return k.tagName?{name:k.tagName,close:k.type==\"closeTag\"}:null},xmlCurrentContext:function(k){for(var z=[],B=k.context;B;B=B.prev)z.push(B.tagName);return z.reverse()}}}),r.defineMIME(\"text/xml\",\"xml\"),r.defineMIME(\"application/xml\",\"xml\"),r.mimeModes.hasOwnProperty(\"text/html\")||r.defineMIME(\"text/html\",{name:\"xml\",htmlMode:!0})})})()),wy.exports}kp();var ky={exports:{}},Sy={exports:{}},_y;function ace(){return _y||(_y=1,(function(e,t){(function(r){r(vo())})(function(r){r.defineMode(\"css\",function(G,j){var N=j.inline;j.propertyKeywords||(j=r.resolveMode(\"text/css\"));var O=G.indentUnit,C=j.tokenHooks,k=j.documentTypes||{},z=j.mediaTypes||{},B=j.mediaFeatures||{},ce=j.mediaValueKeywords||{},be=j.propertyKeywords||{},Se=j.nonStandardPropertyKeywords||{},Be=j.fontProperties||{},Ae=j.counterDescriptors||{},Ke=j.colorKeywords||{},je=j.valueKeywords||{},Fe=j.allowNested,Pe=j.lineComment,F=j.supportsAtComponent===!0,Y=G.highlightNonStandardPropertyKeywords!==!1,re,le;function ae(J,ue){return re=ue,J}function D(J,ue){var oe=J.next();if(C[oe]){var $e=C[oe](J,ue);if($e!==!1)return $e}if(oe==\"@\")return J.eatWhile(/[\\w\\\\\\-]/),ae(\"def\",J.current());if(oe==\"=\"||(oe==\"~\"||oe==\"|\")&&J.eat(\"=\"))return ae(null,\"compare\");if(oe=='\"'||oe==\"'\")return ue.tokenize=q(oe),ue.tokenize(J,ue);if(oe==\"#\")return J.eatWhile(/[\\w\\\\\\-]/),ae(\"atom\",\"hash\");if(oe==\"!\")return J.match(/^\\s*\\w*/),ae(\"keyword\",\"important\");if(/\\d/.test(oe)||oe==\".\"&&J.eat(/\\d/))return J.eatWhile(/[\\w.%]/),ae(\"number\",\"unit\");if(oe===\"-\"){if(/[\\d.]/.test(J.peek()))return J.eatWhile(/[\\w.%]/),ae(\"number\",\"unit\");if(J.match(/^-[\\w\\\\\\-]*/))return J.eatWhile(/[\\w\\\\\\-]/),J.match(/^\\s*:/,!1)?ae(\"variable-2\",\"variable-definition\"):ae(\"variable-2\",\"variable\");if(J.match(/^\\w+-/))return ae(\"meta\",\"meta\")}else return/[,+>*\\/]/.test(oe)?ae(null,\"select-op\"):oe==\".\"&&J.match(/^-?[_a-z][_a-z0-9-]*/i)?ae(\"qualifier\",\"qualifier\"):/[:;{}\\[\\]\\(\\)]/.test(oe)?ae(null,oe):J.match(/^[\\w-.]+(?=\\()/)?(/^(url(-prefix)?|domain|regexp)$/i.test(J.current())&&(ue.tokenize=Q),ae(\"variable callee\",\"variable\")):/[\\w\\\\\\-]/.test(oe)?(J.eatWhile(/[\\w\\\\\\-]/),ae(\"property\",\"word\")):ae(null,null)}function q(J){return function(ue,oe){for(var $e=!1,Je;(Je=ue.next())!=null;){if(Je==J&&!$e){J==\")\"&&ue.backUp(1);break}$e=!$e&&Je==\"\\\\\"}return(Je==J||!$e&&J!=\")\")&&(oe.tokenize=null),ae(\"string\",\"string\")}}function Q(J,ue){return J.next(),J.match(/^\\s*[\\\"\\')]/,!1)?ue.tokenize=null:ue.tokenize=q(\")\"),ae(null,\"(\")}function he(J,ue,oe){this.type=J,this.indent=ue,this.prev=oe}function de(J,ue,oe,$e){return J.context=new he(oe,ue.indentation()+($e===!1?0:O),J.context),oe}function ge(J){return J.context.prev&&(J.context=J.context.prev),J.context.type}function Ce(J,ue,oe){return ye[oe.context.type](J,ue,oe)}function Ee(J,ue,oe,$e){for(var Je=$e||1;Je>0;Je--)oe.context=oe.context.prev;return Ce(J,ue,oe)}function xe(J){var ue=J.current().toLowerCase();je.hasOwnProperty(ue)?le=\"atom\":Ke.hasOwnProperty(ue)?le=\"keyword\":le=\"variable\"}var ye={};return ye.top=function(J,ue,oe){if(J==\"{\")return de(oe,ue,\"block\");if(J==\"}\"&&oe.context.prev)return ge(oe);if(F&&/@component/i.test(J))return de(oe,ue,\"atComponentBlock\");if(/^@(-moz-)?document$/i.test(J))return de(oe,ue,\"documentTypes\");if(/^@(media|supports|(-moz-)?document|import)$/i.test(J))return de(oe,ue,\"atBlock\");if(/^@(font-face|counter-style)/i.test(J))return oe.stateArg=J,\"restricted_atBlock_before\";if(/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(J))return\"keyframes\";if(J&&J.charAt(0)==\"@\")return de(oe,ue,\"at\");if(J==\"hash\")le=\"builtin\";else if(J==\"word\")le=\"tag\";else{if(J==\"variable-definition\")return\"maybeprop\";if(J==\"interpolation\")return de(oe,ue,\"interpolation\");if(J==\":\")return\"pseudo\";if(Fe&&J==\"(\")return de(oe,ue,\"parens\")}return oe.context.type},ye.block=function(J,ue,oe){if(J==\"word\"){var $e=ue.current().toLowerCase();return be.hasOwnProperty($e)?(le=\"property\",\"maybeprop\"):Se.hasOwnProperty($e)?(le=Y?\"string-2\":\"property\",\"maybeprop\"):Fe?(le=ue.match(/^\\s*:(?:\\s|$)/,!1)?\"property\":\"tag\",\"block\"):(le+=\" error\",\"maybeprop\")}else return J==\"meta\"?\"block\":!Fe&&(J==\"hash\"||J==\"qualifier\")?(le=\"error\",\"block\"):ye.top(J,ue,oe)},ye.maybeprop=function(J,ue,oe){return J==\":\"?de(oe,ue,\"prop\"):Ce(J,ue,oe)},ye.prop=function(J,ue,oe){if(J==\";\")return ge(oe);if(J==\"{\"&&Fe)return de(oe,ue,\"propBlock\");if(J==\"}\"||J==\"{\")return Ee(J,ue,oe);if(J==\"(\")return de(oe,ue,\"parens\");if(J==\"hash\"&&!/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(ue.current()))le+=\" error\";else if(J==\"word\")xe(ue);else if(J==\"interpolation\")return de(oe,ue,\"interpolation\");return\"prop\"},ye.propBlock=function(J,ue,oe){return J==\"}\"?ge(oe):J==\"word\"?(le=\"property\",\"maybeprop\"):oe.context.type},ye.parens=function(J,ue,oe){return J==\"{\"||J==\"}\"?Ee(J,ue,oe):J==\")\"?ge(oe):J==\"(\"?de(oe,ue,\"parens\"):J==\"interpolation\"?de(oe,ue,\"interpolation\"):(J==\"word\"&&xe(ue),\"parens\")},ye.pseudo=function(J,ue,oe){return J==\"meta\"?\"pseudo\":J==\"word\"?(le=\"variable-3\",oe.context.type):Ce(J,ue,oe)},ye.documentTypes=function(J,ue,oe){return J==\"word\"&&k.hasOwnProperty(ue.current())?(le=\"tag\",oe.context.type):ye.atBlock(J,ue,oe)},ye.atBlock=function(J,ue,oe){if(J==\"(\")return de(oe,ue,\"atBlock_parens\");if(J==\"}\"||J==\";\")return Ee(J,ue,oe);if(J==\"{\")return ge(oe)&&de(oe,ue,Fe?\"block\":\"top\");if(J==\"interpolation\")return de(oe,ue,\"interpolation\");if(J==\"word\"){var $e=ue.current().toLowerCase();$e==\"only\"||$e==\"not\"||$e==\"and\"||$e==\"or\"?le=\"keyword\":z.hasOwnProperty($e)?le=\"attribute\":B.hasOwnProperty($e)?le=\"property\":ce.hasOwnProperty($e)?le=\"keyword\":be.hasOwnProperty($e)?le=\"property\":Se.hasOwnProperty($e)?le=Y?\"string-2\":\"property\":je.hasOwnProperty($e)?le=\"atom\":Ke.hasOwnProperty($e)?le=\"keyword\":le=\"error\"}return oe.context.type},ye.atComponentBlock=function(J,ue,oe){return J==\"}\"?Ee(J,ue,oe):J==\"{\"?ge(oe)&&de(oe,ue,Fe?\"block\":\"top\",!1):(J==\"word\"&&(le=\"error\"),oe.context.type)},ye.atBlock_parens=function(J,ue,oe){return J==\")\"?ge(oe):J==\"{\"||J==\"}\"?Ee(J,ue,oe,2):ye.atBlock(J,ue,oe)},ye.restricted_atBlock_before=function(J,ue,oe){return J==\"{\"?de(oe,ue,\"restricted_atBlock\"):J==\"word\"&&oe.stateArg==\"@counter-style\"?(le=\"variable\",\"restricted_atBlock_before\"):Ce(J,ue,oe)},ye.restricted_atBlock=function(J,ue,oe){return J==\"}\"?(oe.stateArg=null,ge(oe)):J==\"word\"?(oe.stateArg==\"@font-face\"&&!Be.hasOwnProperty(ue.current().toLowerCase())||oe.stateArg==\"@counter-style\"&&!Ae.hasOwnProperty(ue.current().toLowerCase())?le=\"error\":le=\"property\",\"maybeprop\"):\"restricted_atBlock\"},ye.keyframes=function(J,ue,oe){return J==\"word\"?(le=\"variable\",\"keyframes\"):J==\"{\"?de(oe,ue,\"top\"):Ce(J,ue,oe)},ye.at=function(J,ue,oe){return J==\";\"?ge(oe):J==\"{\"||J==\"}\"?Ee(J,ue,oe):(J==\"word\"?le=\"tag\":J==\"hash\"&&(le=\"builtin\"),\"at\")},ye.interpolation=function(J,ue,oe){return J==\"}\"?ge(oe):J==\"{\"||J==\";\"?Ee(J,ue,oe):(J==\"word\"?le=\"variable\":J!=\"variable\"&&J!=\"(\"&&J!=\")\"&&(le=\"error\"),\"interpolation\")},{startState:function(J){return{tokenize:null,state:N?\"block\":\"top\",stateArg:null,context:new he(N?\"block\":\"top\",J||0,null)}},token:function(J,ue){if(!ue.tokenize&&J.eatSpace())return null;var oe=(ue.tokenize||D)(J,ue);return oe&&typeof oe==\"object\"&&(re=oe[1],oe=oe[0]),le=oe,re!=\"comment\"&&(ue.state=ye[ue.state](re,J,ue)),le},indent:function(J,ue){var oe=J.context,$e=ue&&ue.charAt(0),Je=oe.indent;return oe.type==\"prop\"&&($e==\"}\"||$e==\")\")&&(oe=oe.prev),oe.prev&&($e==\"}\"&&(oe.type==\"block\"||oe.type==\"top\"||oe.type==\"interpolation\"||oe.type==\"restricted_atBlock\")?(oe=oe.prev,Je=oe.indent):($e==\")\"&&(oe.type==\"parens\"||oe.type==\"atBlock_parens\")||$e==\"{\"&&(oe.type==\"at\"||oe.type==\"atBlock\"))&&(Je=Math.max(0,oe.indent-O))),Je},electricChars:\"}\",blockCommentStart:\"/*\",blockCommentEnd:\"*/\",blockCommentContinue:\" * \",lineComment:Pe,fold:\"brace\"}});function o(G){for(var j={},N=0;N<G.length;++N)j[G[N].toLowerCase()]=!0;return j}var s=[\"domain\",\"regexp\",\"url\",\"url-prefix\"],c=o(s),f=[\"all\",\"aural\",\"braille\",\"handheld\",\"print\",\"projection\",\"screen\",\"tty\",\"tv\",\"embossed\"],d=o(f),h=[\"width\",\"min-width\",\"max-width\",\"height\",\"min-height\",\"max-height\",\"device-width\",\"min-device-width\",\"max-device-width\",\"device-height\",\"min-device-height\",\"max-device-height\",\"aspect-ratio\",\"min-aspect-ratio\",\"max-aspect-ratio\",\"device-aspect-ratio\",\"min-device-aspect-ratio\",\"max-device-aspect-ratio\",\"color\",\"min-color\",\"max-color\",\"color-index\",\"min-color-index\",\"max-color-index\",\"monochrome\",\"min-monochrome\",\"max-monochrome\",\"resolution\",\"min-resolution\",\"max-resolution\",\"scan\",\"grid\",\"orientation\",\"device-pixel-ratio\",\"min-device-pixel-ratio\",\"max-device-pixel-ratio\",\"pointer\",\"any-pointer\",\"hover\",\"any-hover\",\"prefers-color-scheme\",\"dynamic-range\",\"video-dynamic-range\"],p=o(h),g=[\"landscape\",\"portrait\",\"none\",\"coarse\",\"fine\",\"on-demand\",\"hover\",\"interlace\",\"progressive\",\"dark\",\"light\",\"standard\",\"high\"],v=o(g),b=[\"align-content\",\"align-items\",\"align-self\",\"alignment-adjust\",\"alignment-baseline\",\"all\",\"anchor-point\",\"animation\",\"animation-delay\",\"animation-direction\",\"animation-duration\",\"animation-fill-mode\",\"animation-iteration-count\",\"animation-name\",\"animation-play-state\",\"animation-timing-function\",\"appearance\",\"azimuth\",\"backdrop-filter\",\"backface-visibility\",\"background\",\"background-attachment\",\"background-blend-mode\",\"background-clip\",\"background-color\",\"background-image\",\"background-origin\",\"background-position\",\"background-position-x\",\"background-position-y\",\"background-repeat\",\"background-size\",\"baseline-shift\",\"binding\",\"bleed\",\"block-size\",\"bookmark-label\",\"bookmark-level\",\"bookmark-state\",\"bookmark-target\",\"border\",\"border-bottom\",\"border-bottom-color\",\"border-bottom-left-radius\",\"border-bottom-right-radius\",\"border-bottom-style\",\"border-bottom-width\",\"border-collapse\",\"border-color\",\"border-image\",\"border-image-outset\",\"border-image-repeat\",\"border-image-slice\",\"border-image-source\",\"border-image-width\",\"border-left\",\"border-left-color\",\"border-left-style\",\"border-left-width\",\"border-radius\",\"border-right\",\"border-right-color\",\"border-right-style\",\"border-right-width\",\"border-spacing\",\"border-style\",\"border-top\",\"border-top-color\",\"border-top-left-radius\",\"border-top-right-radius\",\"border-top-style\",\"border-top-width\",\"border-width\",\"bottom\",\"box-decoration-break\",\"box-shadow\",\"box-sizing\",\"break-after\",\"break-before\",\"break-inside\",\"caption-side\",\"caret-color\",\"clear\",\"clip\",\"color\",\"color-profile\",\"column-count\",\"column-fill\",\"column-gap\",\"column-rule\",\"column-rule-color\",\"column-rule-style\",\"column-rule-width\",\"column-span\",\"column-width\",\"columns\",\"contain\",\"content\",\"counter-increment\",\"counter-reset\",\"crop\",\"cue\",\"cue-after\",\"cue-before\",\"cursor\",\"direction\",\"display\",\"dominant-baseline\",\"drop-initial-after-adjust\",\"drop-initial-after-align\",\"drop-initial-before-adjust\",\"drop-initial-before-align\",\"drop-initial-size\",\"drop-initial-value\",\"elevation\",\"empty-cells\",\"fit\",\"fit-content\",\"fit-position\",\"flex\",\"flex-basis\",\"flex-direction\",\"flex-flow\",\"flex-grow\",\"flex-shrink\",\"flex-wrap\",\"float\",\"float-offset\",\"flow-from\",\"flow-into\",\"font\",\"font-family\",\"font-feature-settings\",\"font-kerning\",\"font-language-override\",\"font-optical-sizing\",\"font-size\",\"font-size-adjust\",\"font-stretch\",\"font-style\",\"font-synthesis\",\"font-variant\",\"font-variant-alternates\",\"font-variant-caps\",\"font-variant-east-asian\",\"font-variant-ligatures\",\"font-variant-numeric\",\"font-variant-position\",\"font-variation-settings\",\"font-weight\",\"gap\",\"grid\",\"grid-area\",\"grid-auto-columns\",\"grid-auto-flow\",\"grid-auto-rows\",\"grid-column\",\"grid-column-end\",\"grid-column-gap\",\"grid-column-start\",\"grid-gap\",\"grid-row\",\"grid-row-end\",\"grid-row-gap\",\"grid-row-start\",\"grid-template\",\"grid-template-areas\",\"grid-template-columns\",\"grid-template-rows\",\"hanging-punctuation\",\"height\",\"hyphens\",\"icon\",\"image-orientation\",\"image-rendering\",\"image-resolution\",\"inline-box-align\",\"inset\",\"inset-block\",\"inset-block-end\",\"inset-block-start\",\"inset-inline\",\"inset-inline-end\",\"inset-inline-start\",\"isolation\",\"justify-content\",\"justify-items\",\"justify-self\",\"left\",\"letter-spacing\",\"line-break\",\"line-height\",\"line-height-step\",\"line-stacking\",\"line-stacking-ruby\",\"line-stacking-shift\",\"line-stacking-strategy\",\"list-style\",\"list-style-image\",\"list-style-position\",\"list-style-type\",\"margin\",\"margin-bottom\",\"margin-left\",\"margin-right\",\"margin-top\",\"marks\",\"marquee-direction\",\"marquee-loop\",\"marquee-play-count\",\"marquee-speed\",\"marquee-style\",\"mask-clip\",\"mask-composite\",\"mask-image\",\"mask-mode\",\"mask-origin\",\"mask-position\",\"mask-repeat\",\"mask-size\",\"mask-type\",\"max-block-size\",\"max-height\",\"max-inline-size\",\"max-width\",\"min-block-size\",\"min-height\",\"min-inline-size\",\"min-width\",\"mix-blend-mode\",\"move-to\",\"nav-down\",\"nav-index\",\"nav-left\",\"nav-right\",\"nav-up\",\"object-fit\",\"object-position\",\"offset\",\"offset-anchor\",\"offset-distance\",\"offset-path\",\"offset-position\",\"offset-rotate\",\"opacity\",\"order\",\"orphans\",\"outline\",\"outline-color\",\"outline-offset\",\"outline-style\",\"outline-width\",\"overflow\",\"overflow-style\",\"overflow-wrap\",\"overflow-x\",\"overflow-y\",\"padding\",\"padding-bottom\",\"padding-left\",\"padding-right\",\"padding-top\",\"page\",\"page-break-after\",\"page-break-before\",\"page-break-inside\",\"page-policy\",\"pause\",\"pause-after\",\"pause-before\",\"perspective\",\"perspective-origin\",\"pitch\",\"pitch-range\",\"place-content\",\"place-items\",\"place-self\",\"play-during\",\"position\",\"presentation-level\",\"punctuation-trim\",\"quotes\",\"region-break-after\",\"region-break-before\",\"region-break-inside\",\"region-fragment\",\"rendering-intent\",\"resize\",\"rest\",\"rest-after\",\"rest-before\",\"richness\",\"right\",\"rotate\",\"rotation\",\"rotation-point\",\"row-gap\",\"ruby-align\",\"ruby-overhang\",\"ruby-position\",\"ruby-span\",\"scale\",\"scroll-behavior\",\"scroll-margin\",\"scroll-margin-block\",\"scroll-margin-block-end\",\"scroll-margin-block-start\",\"scroll-margin-bottom\",\"scroll-margin-inline\",\"scroll-margin-inline-end\",\"scroll-margin-inline-start\",\"scroll-margin-left\",\"scroll-margin-right\",\"scroll-margin-top\",\"scroll-padding\",\"scroll-padding-block\",\"scroll-padding-block-end\",\"scroll-padding-block-start\",\"scroll-padding-bottom\",\"scroll-padding-inline\",\"scroll-padding-inline-end\",\"scroll-padding-inline-start\",\"scroll-padding-left\",\"scroll-padding-right\",\"scroll-padding-top\",\"scroll-snap-align\",\"scroll-snap-type\",\"shape-image-threshold\",\"shape-inside\",\"shape-margin\",\"shape-outside\",\"size\",\"speak\",\"speak-as\",\"speak-header\",\"speak-numeral\",\"speak-punctuation\",\"speech-rate\",\"stress\",\"string-set\",\"tab-size\",\"table-layout\",\"target\",\"target-name\",\"target-new\",\"target-position\",\"text-align\",\"text-align-last\",\"text-combine-upright\",\"text-decoration\",\"text-decoration-color\",\"text-decoration-line\",\"text-decoration-skip\",\"text-decoration-skip-ink\",\"text-decoration-style\",\"text-emphasis\",\"text-emphasis-color\",\"text-emphasis-position\",\"text-emphasis-style\",\"text-height\",\"text-indent\",\"text-justify\",\"text-orientation\",\"text-outline\",\"text-overflow\",\"text-rendering\",\"text-shadow\",\"text-size-adjust\",\"text-space-collapse\",\"text-transform\",\"text-underline-position\",\"text-wrap\",\"top\",\"touch-action\",\"transform\",\"transform-origin\",\"transform-style\",\"transition\",\"transition-delay\",\"transition-duration\",\"transition-property\",\"transition-timing-function\",\"translate\",\"unicode-bidi\",\"user-select\",\"vertical-align\",\"visibility\",\"voice-balance\",\"voice-duration\",\"voice-family\",\"voice-pitch\",\"voice-range\",\"voice-rate\",\"voice-stress\",\"voice-volume\",\"volume\",\"white-space\",\"widows\",\"width\",\"will-change\",\"word-break\",\"word-spacing\",\"word-wrap\",\"writing-mode\",\"z-index\",\"clip-path\",\"clip-rule\",\"mask\",\"enable-background\",\"filter\",\"flood-color\",\"flood-opacity\",\"lighting-color\",\"stop-color\",\"stop-opacity\",\"pointer-events\",\"color-interpolation\",\"color-interpolation-filters\",\"color-rendering\",\"fill\",\"fill-opacity\",\"fill-rule\",\"image-rendering\",\"marker\",\"marker-end\",\"marker-mid\",\"marker-start\",\"paint-order\",\"shape-rendering\",\"stroke\",\"stroke-dasharray\",\"stroke-dashoffset\",\"stroke-linecap\",\"stroke-linejoin\",\"stroke-miterlimit\",\"stroke-opacity\",\"stroke-width\",\"text-rendering\",\"baseline-shift\",\"dominant-baseline\",\"glyph-orientation-horizontal\",\"glyph-orientation-vertical\",\"text-anchor\",\"writing-mode\"],w=o(b),E=[\"accent-color\",\"aspect-ratio\",\"border-block\",\"border-block-color\",\"border-block-end\",\"border-block-end-color\",\"border-block-end-style\",\"border-block-end-width\",\"border-block-start\",\"border-block-start-color\",\"border-block-start-style\",\"border-block-start-width\",\"border-block-style\",\"border-block-width\",\"border-inline\",\"border-inline-color\",\"border-inline-end\",\"border-inline-end-color\",\"border-inline-end-style\",\"border-inline-end-width\",\"border-inline-start\",\"border-inline-start-color\",\"border-inline-start-style\",\"border-inline-start-width\",\"border-inline-style\",\"border-inline-width\",\"content-visibility\",\"margin-block\",\"margin-block-end\",\"margin-block-start\",\"margin-inline\",\"margin-inline-end\",\"margin-inline-start\",\"overflow-anchor\",\"overscroll-behavior\",\"padding-block\",\"padding-block-end\",\"padding-block-start\",\"padding-inline\",\"padding-inline-end\",\"padding-inline-start\",\"scroll-snap-stop\",\"scrollbar-3d-light-color\",\"scrollbar-arrow-color\",\"scrollbar-base-color\",\"scrollbar-dark-shadow-color\",\"scrollbar-face-color\",\"scrollbar-highlight-color\",\"scrollbar-shadow-color\",\"scrollbar-track-color\",\"searchfield-cancel-button\",\"searchfield-decoration\",\"searchfield-results-button\",\"searchfield-results-decoration\",\"shape-inside\",\"zoom\"],L=o(E),P=[\"font-display\",\"font-family\",\"src\",\"unicode-range\",\"font-variant\",\"font-feature-settings\",\"font-stretch\",\"font-weight\",\"font-style\"],M=o(P),R=[\"additive-symbols\",\"fallback\",\"negative\",\"pad\",\"prefix\",\"range\",\"speak-as\",\"suffix\",\"symbols\",\"system\"],I=o(R),_=[\"aliceblue\",\"antiquewhite\",\"aqua\",\"aquamarine\",\"azure\",\"beige\",\"bisque\",\"black\",\"blanchedalmond\",\"blue\",\"blueviolet\",\"brown\",\"burlywood\",\"cadetblue\",\"chartreuse\",\"chocolate\",\"coral\",\"cornflowerblue\",\"cornsilk\",\"crimson\",\"cyan\",\"darkblue\",\"darkcyan\",\"darkgoldenrod\",\"darkgray\",\"darkgreen\",\"darkgrey\",\"darkkhaki\",\"darkmagenta\",\"darkolivegreen\",\"darkorange\",\"darkorchid\",\"darkred\",\"darksalmon\",\"darkseagreen\",\"darkslateblue\",\"darkslategray\",\"darkslategrey\",\"darkturquoise\",\"darkviolet\",\"deeppink\",\"deepskyblue\",\"dimgray\",\"dimgrey\",\"dodgerblue\",\"firebrick\",\"floralwhite\",\"forestgreen\",\"fuchsia\",\"gainsboro\",\"ghostwhite\",\"gold\",\"goldenrod\",\"gray\",\"grey\",\"green\",\"greenyellow\",\"honeydew\",\"hotpink\",\"indianred\",\"indigo\",\"ivory\",\"khaki\",\"lavender\",\"lavenderblush\",\"lawngreen\",\"lemonchiffon\",\"lightblue\",\"lightcoral\",\"lightcyan\",\"lightgoldenrodyellow\",\"lightgray\",\"lightgreen\",\"lightgrey\",\"lightpink\",\"lightsalmon\",\"lightseagreen\",\"lightskyblue\",\"lightslategray\",\"lightslategrey\",\"lightsteelblue\",\"lightyellow\",\"lime\",\"limegreen\",\"linen\",\"magenta\",\"maroon\",\"mediumaquamarine\",\"mediumblue\",\"mediumorchid\",\"mediumpurple\",\"mediumseagreen\",\"mediumslateblue\",\"mediumspringgreen\",\"mediumturquoise\",\"mediumvioletred\",\"midnightblue\",\"mintcream\",\"mistyrose\",\"moccasin\",\"navajowhite\",\"navy\",\"oldlace\",\"olive\",\"olivedrab\",\"orange\",\"orangered\",\"orchid\",\"palegoldenrod\",\"palegreen\",\"paleturquoise\",\"palevioletred\",\"papayawhip\",\"peachpuff\",\"peru\",\"pink\",\"plum\",\"powderblue\",\"purple\",\"rebeccapurple\",\"red\",\"rosybrown\",\"royalblue\",\"saddlebrown\",\"salmon\",\"sandybrown\",\"seagreen\",\"seashell\",\"sienna\",\"silver\",\"skyblue\",\"slateblue\",\"slategray\",\"slategrey\",\"snow\",\"springgreen\",\"steelblue\",\"tan\",\"teal\",\"thistle\",\"tomato\",\"turquoise\",\"violet\",\"wheat\",\"white\",\"whitesmoke\",\"yellow\",\"yellowgreen\"],$=o(_),W=[\"above\",\"absolute\",\"activeborder\",\"additive\",\"activecaption\",\"afar\",\"after-white-space\",\"ahead\",\"alias\",\"all\",\"all-scroll\",\"alphabetic\",\"alternate\",\"always\",\"amharic\",\"amharic-abegede\",\"antialiased\",\"appworkspace\",\"arabic-indic\",\"armenian\",\"asterisks\",\"attr\",\"auto\",\"auto-flow\",\"avoid\",\"avoid-column\",\"avoid-page\",\"avoid-region\",\"axis-pan\",\"background\",\"backwards\",\"baseline\",\"below\",\"bidi-override\",\"binary\",\"bengali\",\"blink\",\"block\",\"block-axis\",\"blur\",\"bold\",\"bolder\",\"border\",\"border-box\",\"both\",\"bottom\",\"break\",\"break-all\",\"break-word\",\"brightness\",\"bullets\",\"button\",\"buttonface\",\"buttonhighlight\",\"buttonshadow\",\"buttontext\",\"calc\",\"cambodian\",\"capitalize\",\"caps-lock-indicator\",\"caption\",\"captiontext\",\"caret\",\"cell\",\"center\",\"checkbox\",\"circle\",\"cjk-decimal\",\"cjk-earthly-branch\",\"cjk-heavenly-stem\",\"cjk-ideographic\",\"clear\",\"clip\",\"close-quote\",\"col-resize\",\"collapse\",\"color\",\"color-burn\",\"color-dodge\",\"column\",\"column-reverse\",\"compact\",\"condensed\",\"conic-gradient\",\"contain\",\"content\",\"contents\",\"content-box\",\"context-menu\",\"continuous\",\"contrast\",\"copy\",\"counter\",\"counters\",\"cover\",\"crop\",\"cross\",\"crosshair\",\"cubic-bezier\",\"currentcolor\",\"cursive\",\"cyclic\",\"darken\",\"dashed\",\"decimal\",\"decimal-leading-zero\",\"default\",\"default-button\",\"dense\",\"destination-atop\",\"destination-in\",\"destination-out\",\"destination-over\",\"devanagari\",\"difference\",\"disc\",\"discard\",\"disclosure-closed\",\"disclosure-open\",\"document\",\"dot-dash\",\"dot-dot-dash\",\"dotted\",\"double\",\"down\",\"drop-shadow\",\"e-resize\",\"ease\",\"ease-in\",\"ease-in-out\",\"ease-out\",\"element\",\"ellipse\",\"ellipsis\",\"embed\",\"end\",\"ethiopic\",\"ethiopic-abegede\",\"ethiopic-abegede-am-et\",\"ethiopic-abegede-gez\",\"ethiopic-abegede-ti-er\",\"ethiopic-abegede-ti-et\",\"ethiopic-halehame-aa-er\",\"ethiopic-halehame-aa-et\",\"ethiopic-halehame-am-et\",\"ethiopic-halehame-gez\",\"ethiopic-halehame-om-et\",\"ethiopic-halehame-sid-et\",\"ethiopic-halehame-so-et\",\"ethiopic-halehame-ti-er\",\"ethiopic-halehame-ti-et\",\"ethiopic-halehame-tig\",\"ethiopic-numeric\",\"ew-resize\",\"exclusion\",\"expanded\",\"extends\",\"extra-condensed\",\"extra-expanded\",\"fantasy\",\"fast\",\"fill\",\"fill-box\",\"fixed\",\"flat\",\"flex\",\"flex-end\",\"flex-start\",\"footnotes\",\"forwards\",\"from\",\"geometricPrecision\",\"georgian\",\"grayscale\",\"graytext\",\"grid\",\"groove\",\"gujarati\",\"gurmukhi\",\"hand\",\"hangul\",\"hangul-consonant\",\"hard-light\",\"hebrew\",\"help\",\"hidden\",\"hide\",\"higher\",\"highlight\",\"highlighttext\",\"hiragana\",\"hiragana-iroha\",\"horizontal\",\"hsl\",\"hsla\",\"hue\",\"hue-rotate\",\"icon\",\"ignore\",\"inactiveborder\",\"inactivecaption\",\"inactivecaptiontext\",\"infinite\",\"infobackground\",\"infotext\",\"inherit\",\"initial\",\"inline\",\"inline-axis\",\"inline-block\",\"inline-flex\",\"inline-grid\",\"inline-table\",\"inset\",\"inside\",\"intrinsic\",\"invert\",\"italic\",\"japanese-formal\",\"japanese-informal\",\"justify\",\"kannada\",\"katakana\",\"katakana-iroha\",\"keep-all\",\"khmer\",\"korean-hangul-formal\",\"korean-hanja-formal\",\"korean-hanja-informal\",\"landscape\",\"lao\",\"large\",\"larger\",\"left\",\"level\",\"lighter\",\"lighten\",\"line-through\",\"linear\",\"linear-gradient\",\"lines\",\"list-item\",\"listbox\",\"listitem\",\"local\",\"logical\",\"loud\",\"lower\",\"lower-alpha\",\"lower-armenian\",\"lower-greek\",\"lower-hexadecimal\",\"lower-latin\",\"lower-norwegian\",\"lower-roman\",\"lowercase\",\"ltr\",\"luminosity\",\"malayalam\",\"manipulation\",\"match\",\"matrix\",\"matrix3d\",\"media-play-button\",\"media-slider\",\"media-sliderthumb\",\"media-volume-slider\",\"media-volume-sliderthumb\",\"medium\",\"menu\",\"menulist\",\"menulist-button\",\"menutext\",\"message-box\",\"middle\",\"min-intrinsic\",\"mix\",\"mongolian\",\"monospace\",\"move\",\"multiple\",\"multiple_mask_images\",\"multiply\",\"myanmar\",\"n-resize\",\"narrower\",\"ne-resize\",\"nesw-resize\",\"no-close-quote\",\"no-drop\",\"no-open-quote\",\"no-repeat\",\"none\",\"normal\",\"not-allowed\",\"nowrap\",\"ns-resize\",\"numbers\",\"numeric\",\"nw-resize\",\"nwse-resize\",\"oblique\",\"octal\",\"opacity\",\"open-quote\",\"optimizeLegibility\",\"optimizeSpeed\",\"oriya\",\"oromo\",\"outset\",\"outside\",\"outside-shape\",\"overlay\",\"overline\",\"padding\",\"padding-box\",\"painted\",\"page\",\"paused\",\"persian\",\"perspective\",\"pinch-zoom\",\"plus-darker\",\"plus-lighter\",\"pointer\",\"polygon\",\"portrait\",\"pre\",\"pre-line\",\"pre-wrap\",\"preserve-3d\",\"progress\",\"push-button\",\"radial-gradient\",\"radio\",\"read-only\",\"read-write\",\"read-write-plaintext-only\",\"rectangle\",\"region\",\"relative\",\"repeat\",\"repeating-linear-gradient\",\"repeating-radial-gradient\",\"repeating-conic-gradient\",\"repeat-x\",\"repeat-y\",\"reset\",\"reverse\",\"rgb\",\"rgba\",\"ridge\",\"right\",\"rotate\",\"rotate3d\",\"rotateX\",\"rotateY\",\"rotateZ\",\"round\",\"row\",\"row-resize\",\"row-reverse\",\"rtl\",\"run-in\",\"running\",\"s-resize\",\"sans-serif\",\"saturate\",\"saturation\",\"scale\",\"scale3d\",\"scaleX\",\"scaleY\",\"scaleZ\",\"screen\",\"scroll\",\"scrollbar\",\"scroll-position\",\"se-resize\",\"searchfield\",\"searchfield-cancel-button\",\"searchfield-decoration\",\"searchfield-results-button\",\"searchfield-results-decoration\",\"self-start\",\"self-end\",\"semi-condensed\",\"semi-expanded\",\"separate\",\"sepia\",\"serif\",\"show\",\"sidama\",\"simp-chinese-formal\",\"simp-chinese-informal\",\"single\",\"skew\",\"skewX\",\"skewY\",\"skip-white-space\",\"slide\",\"slider-horizontal\",\"slider-vertical\",\"sliderthumb-horizontal\",\"sliderthumb-vertical\",\"slow\",\"small\",\"small-caps\",\"small-caption\",\"smaller\",\"soft-light\",\"solid\",\"somali\",\"source-atop\",\"source-in\",\"source-out\",\"source-over\",\"space\",\"space-around\",\"space-between\",\"space-evenly\",\"spell-out\",\"square\",\"square-button\",\"start\",\"static\",\"status-bar\",\"stretch\",\"stroke\",\"stroke-box\",\"sub\",\"subpixel-antialiased\",\"svg_masks\",\"super\",\"sw-resize\",\"symbolic\",\"symbols\",\"system-ui\",\"table\",\"table-caption\",\"table-cell\",\"table-column\",\"table-column-group\",\"table-footer-group\",\"table-header-group\",\"table-row\",\"table-row-group\",\"tamil\",\"telugu\",\"text\",\"text-bottom\",\"text-top\",\"textarea\",\"textfield\",\"thai\",\"thick\",\"thin\",\"threeddarkshadow\",\"threedface\",\"threedhighlight\",\"threedlightshadow\",\"threedshadow\",\"tibetan\",\"tigre\",\"tigrinya-er\",\"tigrinya-er-abegede\",\"tigrinya-et\",\"tigrinya-et-abegede\",\"to\",\"top\",\"trad-chinese-formal\",\"trad-chinese-informal\",\"transform\",\"translate\",\"translate3d\",\"translateX\",\"translateY\",\"translateZ\",\"transparent\",\"ultra-condensed\",\"ultra-expanded\",\"underline\",\"unidirectional-pan\",\"unset\",\"up\",\"upper-alpha\",\"upper-armenian\",\"upper-greek\",\"upper-hexadecimal\",\"upper-latin\",\"upper-norwegian\",\"upper-roman\",\"uppercase\",\"urdu\",\"url\",\"var\",\"vertical\",\"vertical-text\",\"view-box\",\"visible\",\"visibleFill\",\"visiblePainted\",\"visibleStroke\",\"visual\",\"w-resize\",\"wait\",\"wave\",\"wider\",\"window\",\"windowframe\",\"windowtext\",\"words\",\"wrap\",\"wrap-reverse\",\"x-large\",\"x-small\",\"xor\",\"xx-large\",\"xx-small\"],ne=o(W),ee=s.concat(f).concat(h).concat(g).concat(b).concat(E).concat(_).concat(W);r.registerHelper(\"hintWords\",\"css\",ee);function Z(G,j){for(var N=!1,O;(O=G.next())!=null;){if(N&&O==\"/\"){j.tokenize=null;break}N=O==\"*\"}return[\"comment\",\"comment\"]}r.defineMIME(\"text/css\",{documentTypes:c,mediaTypes:d,mediaFeatures:p,mediaValueKeywords:v,propertyKeywords:w,nonStandardPropertyKeywords:L,fontProperties:M,counterDescriptors:I,colorKeywords:$,valueKeywords:ne,tokenHooks:{\"/\":function(G,j){return G.eat(\"*\")?(j.tokenize=Z,Z(G,j)):!1}},name:\"css\"}),r.defineMIME(\"text/x-scss\",{mediaTypes:d,mediaFeatures:p,mediaValueKeywords:v,propertyKeywords:w,nonStandardPropertyKeywords:L,colorKeywords:$,valueKeywords:ne,fontProperties:M,allowNested:!0,lineComment:\"//\",tokenHooks:{\"/\":function(G,j){return G.eat(\"/\")?(G.skipToEnd(),[\"comment\",\"comment\"]):G.eat(\"*\")?(j.tokenize=Z,Z(G,j)):[\"operator\",\"operator\"]},\":\":function(G){return G.match(/^\\s*\\{/,!1)?[null,null]:!1},$:function(G){return G.match(/^[\\w-]+/),G.match(/^\\s*:/,!1)?[\"variable-2\",\"variable-definition\"]:[\"variable-2\",\"variable\"]},\"#\":function(G){return G.eat(\"{\")?[null,\"interpolation\"]:!1}},name:\"css\",helperType:\"scss\"}),r.defineMIME(\"text/x-less\",{mediaTypes:d,mediaFeatures:p,mediaValueKeywords:v,propertyKeywords:w,nonStandardPropertyKeywords:L,colorKeywords:$,valueKeywords:ne,fontProperties:M,allowNested:!0,lineComment:\"//\",tokenHooks:{\"/\":function(G,j){return G.eat(\"/\")?(G.skipToEnd(),[\"comment\",\"comment\"]):G.eat(\"*\")?(j.tokenize=Z,Z(G,j)):[\"operator\",\"operator\"]},\"@\":function(G){return G.eat(\"{\")?[null,\"interpolation\"]:G.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\\b/i,!1)?!1:(G.eatWhile(/[\\w\\\\\\-]/),G.match(/^\\s*:/,!1)?[\"variable-2\",\"variable-definition\"]:[\"variable-2\",\"variable\"])},\"&\":function(){return[\"atom\",\"atom\"]}},name:\"css\",helperType:\"less\"}),r.defineMIME(\"text/x-gss\",{documentTypes:c,mediaTypes:d,mediaFeatures:p,propertyKeywords:w,nonStandardPropertyKeywords:L,fontProperties:M,counterDescriptors:I,colorKeywords:$,valueKeywords:ne,supportsAtComponent:!0,tokenHooks:{\"/\":function(G,j){return G.eat(\"*\")?(j.tokenize=Z,Z(G,j)):!1}},name:\"css\",helperType:\"gss\"})})})()),Sy.exports}var Ty;function cce(){return Ty||(Ty=1,(function(e,t){(function(r){r(vo(),kp(),xp(),ace())})(function(r){var o={script:[[\"lang\",/(javascript|babel)/i,\"javascript\"],[\"type\",/^(?:text|application)\\/(?:x-)?(?:java|ecma)script$|^module$|^$/i,\"javascript\"],[\"type\",/./,\"text/plain\"],[null,null,\"javascript\"]],style:[[\"lang\",/^css$/i,\"css\"],[\"type\",/^(text\\/)?(x-)?(stylesheet|css)$/i,\"css\"],[\"type\",/./,\"text/plain\"],[null,null,\"css\"]]};function s(v,b,w){var E=v.current(),L=E.search(b);return L>-1?v.backUp(E.length-L):E.match(/<\\/?$/)&&(v.backUp(E.length),v.match(b,!1)||v.match(E)),w}var c={};function f(v){var b=c[v];return b||(c[v]=new RegExp(\"\\\\s+\"+v+`\\\\s*=\\\\s*('|\")?([^'\"]+)('|\")?\\\\s*`))}function d(v,b){var w=v.match(f(b));return w?/^\\s*(.*?)\\s*$/.exec(w[2])[1]:\"\"}function h(v,b){return new RegExp((b?\"^\":\"\")+\"</\\\\s*\"+v+\"\\\\s*>\",\"i\")}function p(v,b){for(var w in v)for(var E=b[w]||(b[w]=[]),L=v[w],P=L.length-1;P>=0;P--)E.unshift(L[P])}function g(v,b){for(var w=0;w<v.length;w++){var E=v[w];if(!E[0]||E[1].test(d(b,E[0])))return E[2]}}r.defineMode(\"htmlmixed\",function(v,b){var w=r.getMode(v,{name:\"xml\",htmlMode:!0,multilineTagIndentFactor:b.multilineTagIndentFactor,multilineTagIndentPastTag:b.multilineTagIndentPastTag,allowMissingTagName:b.allowMissingTagName}),E={},L=b&&b.tags,P=b&&b.scriptTypes;if(p(o,E),L&&p(L,E),P)for(var M=P.length-1;M>=0;M--)E.script.unshift([\"type\",P[M].matches,P[M].mode]);function R(I,_){var $=w.token(I,_.htmlState),W=/\\btag\\b/.test($),ne;if(W&&!/[<>\\s\\/]/.test(I.current())&&(ne=_.htmlState.tagName&&_.htmlState.tagName.toLowerCase())&&E.hasOwnProperty(ne))_.inTag=ne+\" \";else if(_.inTag&&W&&/>$/.test(I.current())){var ee=/^([\\S]+) (.*)/.exec(_.inTag);_.inTag=null;var Z=I.current()==\">\"&&g(E[ee[1]],ee[2]),G=r.getMode(v,Z),j=h(ee[1],!0),N=h(ee[1],!1);_.token=function(O,C){return O.match(j,!1)?(C.token=R,C.localState=C.localMode=null,null):s(O,N,C.localMode.token(O,C.localState))},_.localMode=G,_.localState=r.startState(G,w.indent(_.htmlState,\"\",\"\"))}else _.inTag&&(_.inTag+=I.current(),I.eol()&&(_.inTag+=\" \"));return $}return{startState:function(){var I=r.startState(w);return{token:R,inTag:null,localMode:null,localState:null,htmlState:I}},copyState:function(I){var _;return I.localState&&(_=r.copyState(I.localMode,I.localState)),{token:I.token,inTag:I.inTag,localMode:I.localMode,localState:_,htmlState:r.copyState(w,I.htmlState)}},token:function(I,_){return _.token(I,_)},indent:function(I,_,$){return!I.localMode||/^\\s*<\\//.test(_)?w.indent(I.htmlState,_,$):I.localMode.indent?I.localMode.indent(I.localState,_,$):r.Pass},innerMode:function(I){return{state:I.localState||I.htmlState,mode:I.localMode||w}}}},\"xml\",\"javascript\",\"css\"),r.defineMIME(\"text/html\",\"htmlmixed\")})})()),ky.exports}cce();var Cy={exports:{}},Ey;function uce(){return Ey||(Ey=1,(function(e,t){(function(r){r(vo(),kp(),xp())})(function(r){function o(c,f,d,h){this.state=c,this.mode=f,this.depth=d,this.prev=h}function s(c){return new o(r.copyState(c.mode,c.state),c.mode,c.depth,c.prev&&s(c.prev))}r.defineMode(\"jsx\",function(c,f){var d=r.getMode(c,{name:\"xml\",allowMissing:!0,multilineTagIndentPastTag:!1,allowMissingTagName:!0}),h=r.getMode(c,f&&f.base||\"javascript\");function p(w){var E=w.tagName;w.tagName=null;var L=d.indent(w,\"\",\"\");return w.tagName=E,L}function g(w,E){return E.context.mode==d?v(w,E,E.context):b(w,E,E.context)}function v(w,E,L){if(L.depth==2)return w.match(/^.*?\\*\\//)?L.depth=1:w.skipToEnd(),\"comment\";if(w.peek()==\"{\"){d.skipAttribute(L.state);var P=p(L.state),M=L.state.context;if(M&&w.match(/^[^>]*>\\s*$/,!1)){for(;M.prev&&!M.startOfLine;)M=M.prev;M.startOfLine?P-=c.indentUnit:L.prev.state.lexical&&(P=L.prev.state.lexical.indented)}else L.depth==1&&(P+=c.indentUnit);return E.context=new o(r.startState(h,P),h,0,E.context),null}if(L.depth==1){if(w.peek()==\"<\")return d.skipAttribute(L.state),E.context=new o(r.startState(d,p(L.state)),d,0,E.context),null;if(w.match(\"//\"))return w.skipToEnd(),\"comment\";if(w.match(\"/*\"))return L.depth=2,g(w,E)}var R=d.token(w,L.state),I=w.current(),_;return/\\btag\\b/.test(R)?/>$/.test(I)?L.state.context?L.depth=0:E.context=E.context.prev:/^</.test(I)&&(L.depth=1):!R&&(_=I.indexOf(\"{\"))>-1&&w.backUp(I.length-_),R}function b(w,E,L){if(w.peek()==\"<\"&&!w.match(/^<([^<>]|<[^>]*>)+,\\s*>/,!1)&&h.expressionAllowed(w,L.state))return E.context=new o(r.startState(d,h.indent(L.state,\"\",\"\")),d,0,E.context),h.skipExpression(L.state),null;var P=h.token(w,L.state);if(!P&&L.depth!=null){var M=w.current();M==\"{\"?L.depth++:M==\"}\"&&--L.depth==0&&(E.context=E.context.prev)}return P}return{startState:function(){return{context:new o(r.startState(h),h)}},copyState:function(w){return{context:s(w.context)}},token:g,indent:function(w,E,L){return w.context.mode.indent(w.context.state,E,L)},innerMode:function(w){return w.context}}},\"xml\",\"javascript\"),r.defineMIME(\"text/jsx\",\"jsx\"),r.defineMIME(\"text/typescript-jsx\",{name:\"jsx\",base:{name:\"javascript\",typescript:!0}})})})()),Cy.exports}uce();var Ay={exports:{}},Ly;function fce(){return Ly||(Ly=1,(function(e,t){(function(r){r(vo())})(function(r){r.defineOption(\"placeholder\",\"\",function(p,g,v){var b=v&&v!=r.Init;if(g&&!b)p.on(\"blur\",f),p.on(\"change\",d),p.on(\"swapDoc\",d),r.on(p.getInputField(),\"compositionupdate\",p.state.placeholderCompose=function(){c(p)}),d(p);else if(!g&&b){p.off(\"blur\",f),p.off(\"change\",d),p.off(\"swapDoc\",d),r.off(p.getInputField(),\"compositionupdate\",p.state.placeholderCompose),o(p);var w=p.getWrapperElement();w.className=w.className.replace(\" CodeMirror-empty\",\"\")}g&&!p.hasFocus()&&f(p)});function o(p){p.state.placeholder&&(p.state.placeholder.parentNode.removeChild(p.state.placeholder),p.state.placeholder=null)}function s(p){o(p);var g=p.state.placeholder=document.createElement(\"pre\");g.style.cssText=\"height: 0; overflow: visible\",g.style.direction=p.getOption(\"direction\"),g.className=\"CodeMirror-placeholder CodeMirror-line-like\";var v=p.getOption(\"placeholder\");typeof v==\"string\"&&(v=document.createTextNode(v)),g.appendChild(v),p.display.lineSpace.insertBefore(g,p.display.lineSpace.firstChild)}function c(p){setTimeout(function(){var g=!1;if(p.lineCount()==1){var v=p.getInputField();g=v.nodeName==\"TEXTAREA\"?!p.getLine(0).length:!/[^\\u200b]/.test(v.querySelector(\".CodeMirror-line\").textContent)}g?s(p):o(p)},20)}function f(p){h(p)&&s(p)}function d(p){var g=p.getWrapperElement(),v=h(p);g.className=g.className.replace(\" CodeMirror-empty\",\"\")+(v?\" CodeMirror-empty\":\"\"),v?s(p):o(p)}function h(p){return p.lineCount()===1&&p.getLine(0)===\"\"}})})()),Ay.exports}fce();var My={exports:{}},Ny;function dce(){return Ny||(Ny=1,(function(e,t){(function(r){r(vo())})(function(r){function o(f,d,h){this.orientation=d,this.scroll=h,this.screen=this.total=this.size=1,this.pos=0,this.node=document.createElement(\"div\"),this.node.className=f+\"-\"+d,this.inner=this.node.appendChild(document.createElement(\"div\"));var p=this;r.on(this.inner,\"mousedown\",function(v){if(v.which!=1)return;r.e_preventDefault(v);var b=p.orientation==\"horizontal\"?\"pageX\":\"pageY\",w=v[b],E=p.pos;function L(){r.off(document,\"mousemove\",P),r.off(document,\"mouseup\",L)}function P(M){if(M.which!=1)return L();p.moveTo(E+(M[b]-w)*(p.total/p.size))}r.on(document,\"mousemove\",P),r.on(document,\"mouseup\",L)}),r.on(this.node,\"click\",function(v){r.e_preventDefault(v);var b=p.inner.getBoundingClientRect(),w;p.orientation==\"horizontal\"?w=v.clientX<b.left?-1:v.clientX>b.right?1:0:w=v.clientY<b.top?-1:v.clientY>b.bottom?1:0,p.moveTo(p.pos+w*p.screen)});function g(v){var b=r.wheelEventPixels(v)[p.orientation==\"horizontal\"?\"x\":\"y\"],w=p.pos;p.moveTo(p.pos+b),p.pos!=w&&r.e_preventDefault(v)}r.on(this.node,\"mousewheel\",g),r.on(this.node,\"DOMMouseScroll\",g)}o.prototype.setPos=function(f,d){return f<0&&(f=0),f>this.total-this.screen&&(f=this.total-this.screen),!d&&f==this.pos?!1:(this.pos=f,this.inner.style[this.orientation==\"horizontal\"?\"left\":\"top\"]=f*(this.size/this.total)+\"px\",!0)},o.prototype.moveTo=function(f){this.setPos(f)&&this.scroll(f,this.orientation)};var s=10;o.prototype.update=function(f,d,h){var p=this.screen!=d||this.total!=f||this.size!=h;p&&(this.screen=d,this.total=f,this.size=h);var g=this.screen*(this.size/this.total);g<s&&(this.size-=s-g,g=s),this.inner.style[this.orientation==\"horizontal\"?\"width\":\"height\"]=g+\"px\",this.setPos(this.pos,p)};function c(f,d,h){this.addClass=f,this.horiz=new o(f,\"horizontal\",h),d(this.horiz.node),this.vert=new o(f,\"vertical\",h),d(this.vert.node),this.width=null}c.prototype.update=function(f){if(this.width==null){var d=window.getComputedStyle?window.getComputedStyle(this.horiz.node):this.horiz.node.currentStyle;d&&(this.width=parseInt(d.height))}var h=this.width||0,p=f.scrollWidth>f.clientWidth+1,g=f.scrollHeight>f.clientHeight+1;return this.vert.node.style.display=g?\"block\":\"none\",this.horiz.node.style.display=p?\"block\":\"none\",g&&(this.vert.update(f.scrollHeight,f.clientHeight,f.viewHeight-(p?h:0)),this.vert.node.style.bottom=p?h+\"px\":\"0\"),p&&(this.horiz.update(f.scrollWidth,f.clientWidth,f.viewWidth-(g?h:0)-f.barLeft),this.horiz.node.style.right=g?h+\"px\":\"0\",this.horiz.node.style.left=f.barLeft+\"px\"),{right:g?h:0,bottom:p?h:0}},c.prototype.setScrollTop=function(f){this.vert.setPos(f)},c.prototype.setScrollLeft=function(f){this.horiz.setPos(f)},c.prototype.clear=function(){var f=this.horiz.node.parentNode;f.removeChild(this.horiz.node),f.removeChild(this.vert.node)},r.scrollbarModel.simple=function(f,d){return new c(\"CodeMirror-simplescroll\",f,d)},r.scrollbarModel.overlay=function(f,d){return new c(\"CodeMirror-overlayscroll\",f,d)}})})()),My.exports}dce();const Nn=Ft();function hce(e,t,r={}){const o=NL.fromTextArea(e.value,{theme:\"vars\",...r,scrollbarStyle:\"simple\"});let s=!1;return o.on(\"change\",()=>{if(s){s=!1;return}t.value=o.getValue()}),xt(t,c=>{if(c!==o.getValue()){s=!0;const f=o.listSelections();o.replaceRange(c,o.posFromIndex(0),o.posFromIndex(Number.POSITIVE_INFINITY)),o.setSelections(f)}},{immediate:!0}),Ia(()=>{Nn.value=void 0}),Uu(o)}async function gx(e){_a({file:e.file.id,line:e.location?.line??1,view:\"editor\",test:e.id,column:null})}function pce(e,t){_a({file:e,column:t.column-1,line:t.line,view:\"editor\",test:Bs.value})}function gce(e,t){if(!t)return;const{line:r,column:o,file:s}=t;if(e.file.filepath!==s)return bp(s,r,o);_a({file:e.file.id,column:o-1,line:r,view:\"editor\",test:Bs.value})}const pr=Ge(),Ws=Ge(!0),go=Ge(!1),Cu=Ge(!0),Ns=ke(()=>ei.value?.coverage),mh=ke(()=>Ns.value?.enabled),Os=ke(()=>mh.value&&!!Ns.value.htmlReporter),qs=sf(\"vitest-ui_splitpanes-mainSizes\",[33,67]),co=sf(\"vitest-ui_splitpanes-detailSizes\",[window.__vitest_browser_runner__?.provider===\"webdriverio\"?tr.value[0]/window.outerWidth*100:33,67]),At=ir({navigation:qs.value[0],details:{size:qs.value[1],browser:co.value[0],main:co.value[1]}}),Oy=ke(()=>{if(Os.value){const e=Ns.value.reportsDirectory.lastIndexOf(\"/\"),t=Ns.value.htmlReporter?.subdir;return t?`/${Ns.value.reportsDirectory.slice(e+1)}/${t}/index.html`:`/${Ns.value.reportsDirectory.slice(e+1)}/index.html`}});xt(uf,e=>{Cu.value=e===\"running\"},{immediate:!0});function mce(){const e=po.value;if(e&&e.length>0){const t=mr(e);t?(pr.value=t,Ws.value=!1,go.value=!1):_E(()=>ft.state.getFiles(),()=>{pr.value=mr(e),Ws.value=!1,go.value=!1})}return Ws}function Eu(e){Ws.value=e,go.value=!1,e&&(pr.value=void 0,po.value=\"\")}function _a({file:e,line:t,view:r,test:o,column:s}){po.value=e,hx.value=t,px.value=s,hn.value=r,Bs.value=o,pr.value=mr(e),Eu(!1)}function vce(e){e.type===\"test\"?hn.value===\"editor\"?gx(e):_a({file:e.file.id,line:null,column:null,view:hn.value,test:e.id}):_a({file:e.file.id,test:null,line:null,view:hn.value,column:null})}function yce(){go.value=!0,Ws.value=!1,pr.value=void 0,po.value=\"\"}function bce(){At.details.browser=100,At.details.main=0,co.value=[100,0]}function mx(){if(Zn?.provider===\"webdriverio\"){const e=window.outerWidth*(At.details.size/100);return(tr.value[0]+20)/e*100}return 33}function wce(){At.details.browser=mx(),At.details.main=100-At.details.browser,co.value=[At.details.browser,At.details.main]}function xce(){At.navigation=33,At.details.size=67,qs.value=[33,67]}function vx(){At.details.main!==0&&(At.details.browser=mx(),At.details.main=100-At.details.browser,co.value=[At.details.browser,At.details.main])}const kce={setCurrentFileId(e){po.value=e,pr.value=mr(e),Eu(!1)},async setIframeViewport(e,t){tr.value=[e,t],Zn?.provider===\"webdriverio\"&&vx(),await new Promise(r=>requestAnimationFrame(r))}},Sce=location.port,_ce=[location.hostname,Sce].filter(Boolean).join(\":\"),Tce=`${location.protocol===\"https:\"?\"wss:\":\"ws:\"}//${_ce}/__vitest_api__?token=${window.VITEST_API_TOKEN||\"0\"}`,gr=!!window.METADATA_PATH;var rr=Uint8Array,Ps=Uint16Array,Cce=Int32Array,yx=new rr([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),bx=new rr([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Ece=new rr([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),wx=function(e,t){for(var r=new Ps(31),o=0;o<31;++o)r[o]=t+=1<<e[o-1];for(var s=new Cce(r[30]),o=1;o<30;++o)for(var c=r[o];c<r[o+1];++c)s[c]=c-r[o]<<5|o;return{b:r,r:s}},xx=wx(yx,2),kx=xx.b,Ace=xx.r;kx[28]=258,Ace[258]=28;var Lce=wx(bx,0),Mce=Lce.b,vh=new Ps(32768);for(var Lt=0;Lt<32768;++Lt){var Vi=(Lt&43690)>>1|(Lt&21845)<<1;Vi=(Vi&52428)>>2|(Vi&13107)<<2,Vi=(Vi&61680)>>4|(Vi&3855)<<4,vh[Lt]=((Vi&65280)>>8|(Vi&255)<<8)>>1}var sa=(function(e,t,r){for(var o=e.length,s=0,c=new Ps(t);s<o;++s)e[s]&&++c[e[s]-1];var f=new Ps(t);for(s=1;s<t;++s)f[s]=f[s-1]+c[s-1]<<1;var d;if(r){d=new Ps(1<<t);var h=15-t;for(s=0;s<o;++s)if(e[s])for(var p=s<<4|e[s],g=t-e[s],v=f[e[s]-1]++<<g,b=v|(1<<g)-1;v<=b;++v)d[vh[v]>>h]=p}else for(d=new Ps(o),s=0;s<o;++s)e[s]&&(d[s]=vh[f[e[s]-1]++]>>15-e[s]);return d}),qa=new rr(288);for(var Lt=0;Lt<144;++Lt)qa[Lt]=8;for(var Lt=144;Lt<256;++Lt)qa[Lt]=9;for(var Lt=256;Lt<280;++Lt)qa[Lt]=7;for(var Lt=280;Lt<288;++Lt)qa[Lt]=8;var Sx=new rr(32);for(var Lt=0;Lt<32;++Lt)Sx[Lt]=5;var Nce=sa(qa,9,1),Oce=sa(Sx,5,1),Md=function(e){for(var t=e[0],r=1;r<e.length;++r)e[r]>t&&(t=e[r]);return t},Ar=function(e,t,r){var o=t/8|0;return(e[o]|e[o+1]<<8)>>(t&7)&r},Nd=function(e,t){var r=t/8|0;return(e[r]|e[r+1]<<8|e[r+2]<<16)>>(t&7)},Pce=function(e){return(e+7)/8|0},_x=function(e,t,r){return(t==null||t<0)&&(t=0),(r==null||r>e.length)&&(r=e.length),new rr(e.subarray(t,r))},Rce=[\"unexpected EOF\",\"invalid block type\",\"invalid length/literal\",\"invalid distance\",\"stream finished\",\"no stream handler\",,\"no callback\",\"invalid UTF-8 data\",\"extra field too long\",\"date not in range 1980-2099\",\"filename too long\",\"stream finishing\",\"invalid zip data\"],Un=function(e,t,r){var o=new Error(t||Rce[e]);if(o.code=e,Error.captureStackTrace&&Error.captureStackTrace(o,Un),!r)throw o;return o},Sp=function(e,t,r,o){var s=e.length,c=0;if(!s||t.f&&!t.l)return r||new rr(0);var f=!r,d=f||t.i!=2,h=t.i;f&&(r=new rr(s*3));var p=function(ae){var D=r.length;if(ae>D){var q=new rr(Math.max(D*2,ae));q.set(r),r=q}},g=t.f||0,v=t.p||0,b=t.b||0,w=t.l,E=t.d,L=t.m,P=t.n,M=s*8;do{if(!w){g=Ar(e,v,1);var R=Ar(e,v+1,3);if(v+=3,R)if(R==1)w=Nce,E=Oce,L=9,P=5;else if(R==2){var W=Ar(e,v,31)+257,ne=Ar(e,v+10,15)+4,ee=W+Ar(e,v+5,31)+1;v+=14;for(var Z=new rr(ee),G=new rr(19),j=0;j<ne;++j)G[Ece[j]]=Ar(e,v+j*3,7);v+=ne*3;for(var N=Md(G),O=(1<<N)-1,C=sa(G,N,1),j=0;j<ee;){var k=C[Ar(e,v,O)];v+=k&15;var I=k>>4;if(I<16)Z[j++]=I;else{var z=0,B=0;for(I==16?(B=3+Ar(e,v,3),v+=2,z=Z[j-1]):I==17?(B=3+Ar(e,v,7),v+=3):I==18&&(B=11+Ar(e,v,127),v+=7);B--;)Z[j++]=z}}var ce=Z.subarray(0,W),be=Z.subarray(W);L=Md(ce),P=Md(be),w=sa(ce,L,1),E=sa(be,P,1)}else Un(1);else{var I=Pce(v)+4,_=e[I-4]|e[I-3]<<8,$=I+_;if($>s){h&&Un(0);break}d&&p(b+_),r.set(e.subarray(I,$),b),t.b=b+=_,t.p=v=$*8,t.f=g;continue}if(v>M){h&&Un(0);break}}d&&p(b+131072);for(var Se=(1<<L)-1,Be=(1<<P)-1,Ae=v;;Ae=v){var z=w[Nd(e,v)&Se],Ke=z>>4;if(v+=z&15,v>M){h&&Un(0);break}if(z||Un(2),Ke<256)r[b++]=Ke;else if(Ke==256){Ae=v,w=null;break}else{var je=Ke-254;if(Ke>264){var j=Ke-257,Fe=yx[j];je=Ar(e,v,(1<<Fe)-1)+kx[j],v+=Fe}var Pe=E[Nd(e,v)&Be],F=Pe>>4;Pe||Un(3),v+=Pe&15;var be=Mce[F];if(F>3){var Fe=bx[F];be+=Nd(e,v)&(1<<Fe)-1,v+=Fe}if(v>M){h&&Un(0);break}d&&p(b+131072);var Y=b+je;if(b<be){var re=c-be,le=Math.min(be,Y);for(re+b<0&&Un(3);b<le;++b)r[b]=o[re+b]}for(;b<Y;++b)r[b]=r[b-be]}}t.l=w,t.p=Ae,t.b=b,t.f=g,w&&(g=1,t.m=L,t.d=E,t.n=P)}while(!g);return b!=r.length&&f?_x(r,0,b):r.subarray(0,b)},$ce=new rr(0),Ice=function(e){(e[0]!=31||e[1]!=139||e[2]!=8)&&Un(6,\"invalid gzip data\");var t=e[3],r=10;t&4&&(r+=(e[10]|e[11]<<8)+2);for(var o=(t>>3&1)+(t>>4&1);o>0;o-=!e[r++]);return r+(t&2)},Dce=function(e){var t=e.length;return(e[t-4]|e[t-3]<<8|e[t-2]<<16|e[t-1]<<24)>>>0},zce=function(e,t){return((e[0]&15)!=8||e[0]>>4>7||(e[0]<<8|e[1])%31)&&Un(6,\"invalid zlib data\"),(e[1]>>5&1)==1&&Un(6,\"invalid zlib data: \"+(e[1]&32?\"need\":\"unexpected\")+\" dictionary\"),(e[1]>>3&4)+2};function Fce(e,t){return Sp(e,{i:2},t,t)}function Hce(e,t){var r=Ice(e);return r+8>e.length&&Un(6,\"invalid gzip data\"),Sp(e.subarray(r,-8),{i:2},new rr(Dce(e)),t)}function Bce(e,t){return Sp(e.subarray(zce(e),-4),{i:2},t,t)}function Wce(e,t){return e[0]==31&&e[1]==139&&e[2]==8?Hce(e,t):(e[0]&15)!=8||e[0]>>4>7||(e[0]<<8|e[1])%31?Fce(e,t):Bce(e,t)}var yh=typeof TextDecoder<\"u\"&&new TextDecoder,qce=0;try{yh.decode($ce,{stream:!0}),qce=1}catch{}var jce=function(e){for(var t=\"\",r=0;;){var o=e[r++],s=(o>127)+(o>223)+(o>239);if(r+s>e.length)return{s:t,r:_x(e,r-1)};s?s==3?(o=((o&15)<<18|(e[r++]&63)<<12|(e[r++]&63)<<6|e[r++]&63)-65536,t+=String.fromCharCode(55296|o>>10,56320|o&1023)):s&1?t+=String.fromCharCode((o&31)<<6|e[r++]&63):t+=String.fromCharCode((o&15)<<12|(e[r++]&63)<<6|e[r++]&63):t+=String.fromCharCode(o)}};function Py(e,t){var r;if(yh)return yh.decode(e);var o=jce(e),s=o.s,r=o.r;return r.length&&Un(8),s}const Od=()=>{},dn=()=>Promise.resolve();function Uce(){const e=ir({state:new Xw,waitForConnection:f,reconnect:s,ws:new EventTarget});e.state.filesMap=ir(e.state.filesMap),e.state.idMap=ir(e.state.idMap);let t;const r={getFiles:()=>t.files,getPaths:()=>t.paths,getConfig:()=>t.config,getResolvedProjectNames:()=>t.projects,getResolvedProjectLabels:()=>[],getModuleGraph:async(d,h)=>t.moduleGraph[d]?.[h],getUnhandledErrors:()=>t.unhandledErrors,getExternalResult:dn,getTransformResult:dn,onDone:Od,onTaskUpdate:Od,writeFile:dn,rerun:dn,rerunTask:dn,updateSnapshot:dn,resolveSnapshotPath:dn,snapshotSaved:dn,onAfterSuiteRun:dn,onCancel:dn,getCountOfFailedTests:()=>0,sendLog:dn,resolveSnapshotRawPath:dn,readSnapshotFile:dn,saveSnapshotFile:dn,readTestFile:async d=>t.sources[d],removeSnapshotFile:dn,onUnhandledError:Od,saveTestFile:dn,getProvidedContext:()=>({}),getTestFiles:dn};e.rpc=r;const o=Promise.resolve();function s(){c()}async function c(){const d=await fetch(window.METADATA_PATH),h=new Uint8Array(await d.arrayBuffer());if(h.length>=2&&h[0]===31&&h[1]===139){const g=Py(Wce(h));t=fh(g)}else t=fh(Py(h));const p=new Event(\"open\");e.ws.dispatchEvent(p)}c();function f(){return o}return e}const ft=(function(){return gr?Uce():XA(Tce,{reactive:(t,r)=>r===\"state\"?ir(t):Ft(t),handlers:{onTestAnnotate(t,r){Oe.recordTestArtifact(t,{type:\"internal:annotation\",annotation:r,location:r.location})},onTestArtifactRecord(t,r){Oe.recordTestArtifact(t,r)},onTaskUpdate(t,r){Oe.resumeRun(t,r),uf.value=\"running\"},onSpecsCollected(t,r){Oe.startTime=r||performance.now()},onFinished(t,r,o,s){Oe.endRun(s),eo.value=(r||[]).map(fx)},onFinishedReportCoverage(){const t=document.querySelector(\"iframe#vitest-ui-coverage\");t instanceof HTMLIFrameElement&&t.contentWindow&&t.contentWindow.location.reload()}}})})(),ei=Ft({}),Ho=Ge(\"CONNECTING\"),Gt=ke(()=>{const e=po.value;return e?mr(e):void 0}),Tx=ke(()=>gp(Gt.value).map(e=>e?.logs||[]).flat()||[]);function mr(e){const t=ft.state.idMap.get(e);return t||void 0}const Vce=ke(()=>Ho.value===\"OPEN\"),Pd=ke(()=>Ho.value===\"CONNECTING\");ke(()=>Ho.value===\"CLOSED\");function Gce(){return _p(ft.state.getFiles())}function Cx(e){delete e.result;const t=Oe.nodes.get(e.id);if(t&&(t.state=void 0,t.duration=void 0,Ha(e)))for(const r of e.tasks)Cx(r)}function Kce(e){const t=Oe.nodes;e.forEach(r=>{delete r.result,gp(r).forEach(s=>{if(delete s.result,t.has(s.id)){const c=t.get(s.id);c&&(c.state=void 0,c.duration=void 0)}});const o=t.get(r.id);o&&(o.state=void 0,o.duration=void 0,In(o)&&(o.collectDuration=void 0))})}function _p(e){return Kce(e),Oe.startRun(),ft.rpc.rerun(e.map(t=>t.filepath),!0)}function Xce(e){return Cx(e),Oe.startRun(),ft.rpc.rerunTask(e.id)}const Zn=window.__vitest_browser_runner__;window.__vitest_ui_api__=kce;xt(()=>ft.ws,e=>{Ho.value=gr?\"OPEN\":\"CONNECTING\",e.addEventListener(\"open\",async()=>{Ho.value=\"OPEN\",ft.state.filesMap.clear();let[t,r,o,s]=await Promise.all([ft.rpc.getFiles(),ft.rpc.getConfig(),ft.rpc.getUnhandledErrors(),ft.rpc.getResolvedProjectLabels()]);r.standalone&&(t=(await ft.rpc.getTestFiles()).map(([{name:f,root:d},h])=>{const p=Bw(h,d,f);return p.mode=\"skip\",p})),Oe.loadFiles(t,s),ft.state.collectFiles(t),Oe.startRun(),eo.value=(o||[]).map(fx),ei.value=r}),e.addEventListener(\"close\",()=>{setTimeout(()=>{Ho.value===\"CONNECTING\"&&(Ho.value=\"CLOSED\")},1e3)})},{immediate:!0});const Yce=[\"aria-label\",\"opacity\",\"disabled\",\"hover\"],_t=rt({__name:\"IconButton\",props:{icon:{},title:{},disabled:{type:Boolean},active:{type:Boolean}},setup(e){return(t,r)=>(ie(),ve(\"button\",{\"aria-label\":e.title,role:\"button\",opacity:e.disabled?10:70,rounded:\"\",disabled:e.disabled,hover:e.disabled||e.active?\"\":\"bg-active op100\",class:ot([\"w-1.4em h-1.4em flex\",[{\"bg-gray-500:35 op100\":e.active}]])},[Dt(t.$slots,\"default\",{},()=>[X(\"span\",{class:ot(e.icon),ma:\"\",block:\"\"},null,2)])],10,Yce))}}),Zce={h:\"full\",flex:\"~ col\"},Jce={p:\"3\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},Qce={p:\"l3 y2 r2\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b-2 base\"},eue={class:\"pointer-events-none\",\"text-sm\":\"\"},tue={key:0},nue={id:\"tester-container\",relative:\"\"},rue=[\"data-scale\"],Ry=20,iue=100,oue=rt({__name:\"BrowserIframe\",setup(e){const t={\"small-mobile\":[320,568],\"large-mobile\":[414,896],tablet:[834,1112]};function r(p){const g=t[p];return tr.value[0]===g[0]&&tr.value[1]===g[1]}const{width:o,height:s}=Pw();async function c(p){tr.value=t[p],Zn?.provider===\"webdriverio\"&&vx()}const f=ke(()=>{if(Zn?.provider===\"webdriverio\"){const[w,E]=tr.value;return{width:w,height:E}}const v=o.value*(At.details.size/100)*(At.details.browser/100)-Ry,b=s.value-iue;return{width:v,height:b}}),d=ke(()=>{if(Zn?.provider===\"webdriverio\")return 1;const[p,g]=tr.value,{width:v,height:b}=f.value,w=v>p?1:v/p,E=b>g?1:b/g;return Math.min(1,w,E)}),h=ke(()=>{const p=f.value.width,g=tr.value[0];return`${Math.trunc((p+Ry-g)/2)}px`});return(p,g)=>{const v=vr(\"tooltip\");return ie(),ve(\"div\",Zce,[X(\"div\",Jce,[at(Ne(_t,{title:\"Show Navigation Panel\",\"rotate-180\":\"\",icon:\"i-carbon:side-panel-close\",onClick:g[0]||(g[0]=b=>K(xce)())},null,512),[[ro,K(At).navigation<=15],[v,\"Show Navigation Panel\",void 0,{bottom:!0}]]),g[6]||(g[6]=X(\"div\",{class:\"i-carbon-content-delivery-network\"},null,-1)),g[7]||(g[7]=X(\"span\",{\"pl-1\":\"\",\"font-bold\":\"\",\"text-sm\":\"\",\"flex-auto\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",truncate:\"\"},\"Browser UI\",-1)),at(Ne(_t,{title:\"Hide Right Panel\",icon:\"i-carbon:side-panel-close\",\"rotate-180\":\"\",onClick:g[1]||(g[1]=b=>K(bce)())},null,512),[[ro,K(At).details.main>0],[v,\"Hide Right Panel\",void 0,{bottom:!0}]]),at(Ne(_t,{title:\"Show Right Panel\",icon:\"i-carbon:side-panel-close\",onClick:g[2]||(g[2]=b=>K(wce)())},null,512),[[ro,K(At).details.main===0],[v,\"Show Right Panel\",void 0,{bottom:!0}]])]),X(\"div\",Qce,[at(Ne(_t,{title:\"Small mobile\",icon:\"i-carbon:mobile\",active:r(\"small-mobile\"),onClick:g[3]||(g[3]=b=>c(\"small-mobile\"))},null,8,[\"active\"]),[[v,\"Small mobile\",void 0,{bottom:!0}]]),at(Ne(_t,{title:\"Large mobile\",icon:\"i-carbon:mobile-add\",active:r(\"large-mobile\"),onClick:g[4]||(g[4]=b=>c(\"large-mobile\"))},null,8,[\"active\"]),[[v,\"Large mobile\",void 0,{bottom:!0}]]),at(Ne(_t,{title:\"Tablet\",icon:\"i-carbon:tablet\",active:r(\"tablet\"),onClick:g[5]||(g[5]=b=>c(\"tablet\"))},null,8,[\"active\"]),[[v,\"Tablet\",void 0,{bottom:!0}]]),X(\"span\",eue,[Qe(Re(K(tr)[0])+\"x\"+Re(K(tr)[1])+\"px \",1),d.value<1?(ie(),ve(\"span\",tue,\"(\"+Re((d.value*100).toFixed(0))+\"%)\",1)):He(\"\",!0)])]),X(\"div\",nue,[X(\"div\",{id:\"tester-ui\",class:\"flex h-full justify-center items-center font-light op70\",\"data-scale\":d.value,style:zt({\"--viewport-width\":`${K(tr)[0]}px`,\"--viewport-height\":`${K(tr)[1]}px`,\"--tester-transform\":`scale(${d.value})`,\"--tester-margin-left\":h.value})},\" Select a test to run \",12,rue)])])}}}),sue=Ni(oue,[[\"__scopeId\",\"data-v-2e86b8c3\"]]),lue={\"text-2xl\":\"\"},aue={\"text-lg\":\"\",op50:\"\"},cue=rt({__name:\"ConnectionOverlay\",setup(e){return(t,r)=>K(Vce)?He(\"\",!0):(ie(),ve(\"div\",{key:0,fixed:\"\",\"inset-0\":\"\",p2:\"\",\"z-10\":\"\",\"select-none\":\"\",text:\"center sm\",bg:\"overlay\",\"backdrop-blur-sm\":\"\",\"backdrop-saturate-0\":\"\",onClick:r[0]||(r[0]=(...o)=>K(ft).reconnect&&K(ft).reconnect(...o))},[X(\"div\",{\"h-full\":\"\",flex:\"~ col gap-2\",\"items-center\":\"\",\"justify-center\":\"\",class:ot(K(Pd)?\"animate-pulse\":\"\")},[X(\"div\",{text:\"5xl\",class:ot(K(Pd)?\"i-carbon:renew animate-spin animate-reverse\":\"i-carbon-wifi-off\")},null,2),X(\"div\",lue,Re(K(Pd)?\"Connecting...\":\"Disconnected\"),1),X(\"div\",aue,\" Check your terminal or start a new server with `\"+Re(K(Zn)?`vitest --browser=${K(Zn).config.browser.name}`:\"vitest --ui\")+\"` \",1)],2)]))}}),uue={h:\"full\",flex:\"~ col\"},fue={\"flex-auto\":\"\",\"py-1\":\"\",\"bg-white\":\"\"},due=[\"src\"],$y=rt({__name:\"Coverage\",props:{src:{}},setup(e){return(t,r)=>(ie(),ve(\"div\",uue,[r[0]||(r[0]=X(\"div\",{p:\"3\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},[X(\"div\",{class:\"i-carbon:folder-details-reference\"}),X(\"span\",{\"pl-1\":\"\",\"font-bold\":\"\",\"text-sm\":\"\",\"flex-auto\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",truncate:\"\"},\"Coverage\")],-1)),X(\"div\",fue,[X(\"iframe\",{id:\"vitest-ui-coverage\",src:e.src},null,8,due)])]))}}),hue={bg:\"red500/10\",\"p-1\":\"\",\"mb-1\":\"\",\"mt-2\":\"\",rounded:\"\"},pue={\"font-bold\":\"\"},gue={key:0,class:\"scrolls\",text:\"xs\",\"font-mono\":\"\",\"mx-1\":\"\",\"my-2\":\"\",\"pb-2\":\"\",\"overflow-auto\":\"\"},mue=[\"font-bold\"],vue={text:\"red500/70\"},yue={key:1,text:\"sm\",\"mb-2\":\"\"},bue={\"font-bold\":\"\"},wue={key:2,text:\"sm\",\"mb-2\":\"\"},xue={\"font-bold\":\"\"},kue=rt({__name:\"ErrorEntry\",props:{error:{}},setup(e){return(t,r)=>(ie(),ve(nt,null,[X(\"h4\",hue,[X(\"span\",pue,[Qe(Re(e.error.name||e.error.nameStr||\"Unknown Error\"),1),e.error.message?(ie(),ve(nt,{key:0},[Qe(\":\")],64)):He(\"\",!0)]),Qe(\" \"+Re(e.error.message),1)]),e.error.stacks?.length?(ie(),ve(\"p\",gue,[(ie(!0),ve(nt,null,$n(e.error.stacks,(o,s)=>(ie(),ve(\"span\",{key:s,\"whitespace-pre\":\"\",\"font-bold\":s===0?\"\":null},[Qe(\"❯ \"+Re(o.method)+\" \"+Re(o.file)+\":\",1),X(\"span\",vue,Re(o.line)+\":\"+Re(o.column),1),r[0]||(r[0]=X(\"br\",null,null,-1))],8,mue))),128))])):He(\"\",!0),e.error.VITEST_TEST_PATH?(ie(),ve(\"p\",yue,[r[1]||(r[1]=Qe(\" This error originated in \",-1)),X(\"span\",bue,Re(e.error.VITEST_TEST_PATH),1),r[2]||(r[2]=Qe(\" test file. It doesn't mean the error was thrown inside the file itself, but while it was running. \",-1))])):He(\"\",!0),e.error.VITEST_TEST_NAME?(ie(),ve(\"div\",wue,[r[3]||(r[3]=Qe(\" The latest test that might've caused the error is \",-1)),X(\"span\",xue,Re(e.error.VITEST_TEST_NAME),1),r[4]||(r[4]=Qe(\". It might mean one of the following:\",-1)),r[5]||(r[5]=X(\"br\",null,null,-1)),r[6]||(r[6]=X(\"ul\",null,[X(\"li\",null,\" The error was thrown, while Vitest was running this test. \"),X(\"li\",null,\" If the error occurred after the test had been completed, this was the last documented test before it was thrown. \")],-1))])):He(\"\",!0)],64))}}),Sue={\"data-testid\":\"test-files-entry\",grid:\"~ cols-[min-content_1fr_min-content]\",\"items-center\":\"\",gap:\"x-2 y-3\",p:\"x4\",relative:\"\",\"font-light\":\"\",\"w-80\":\"\",op80:\"\"},_ue={class:\"number\",\"data-testid\":\"num-files\"},Tue={class:\"number\"},Cue={class:\"number\",\"text-red5\":\"\"},Eue={class:\"number\",\"text-red5\":\"\"},Aue={class:\"number\",\"text-red5\":\"\"},Lue={class:\"number\",\"data-testid\":\"run-time\"},Mue={key:0,bg:\"red500/10\",text:\"red500\",p:\"x3 y2\",\"max-w-xl\":\"\",\"m-2\":\"\",rounded:\"\"},Nue={text:\"sm\",\"font-thin\":\"\",\"mb-2\":\"\",\"data-testid\":\"unhandled-errors\"},Oue={\"data-testid\":\"unhandled-errors-details\",class:\"scrolls unhandled-errors\",text:\"sm\",\"font-thin\":\"\",\"pe-2.5\":\"\",\"open:max-h-52\":\"\",\"overflow-auto\":\"\"},Pue=rt({__name:\"TestFilesEntry\",setup(e){return(t,r)=>(ie(),ve(nt,null,[X(\"div\",Sue,[r[8]||(r[8]=X(\"div\",{\"i-carbon-document\":\"\"},null,-1)),r[9]||(r[9]=X(\"div\",null,\"Files\",-1)),X(\"div\",_ue,Re(K(Oe).summary.files),1),K(Oe).summary.filesSuccess?(ie(),ve(nt,{key:0},[r[0]||(r[0]=X(\"div\",{\"i-carbon-checkmark\":\"\"},null,-1)),r[1]||(r[1]=X(\"div\",null,\"Pass\",-1)),X(\"div\",Tue,Re(K(Oe).summary.filesSuccess),1)],64)):He(\"\",!0),K(Oe).summary.filesFailed?(ie(),ve(nt,{key:1},[r[2]||(r[2]=X(\"div\",{\"i-carbon-close\":\"\"},null,-1)),r[3]||(r[3]=X(\"div\",null,\" Fail \",-1)),X(\"div\",Cue,Re(K(Oe).summary.filesFailed),1)],64)):He(\"\",!0),K(Oe).summary.filesSnapshotFailed?(ie(),ve(nt,{key:2},[r[4]||(r[4]=X(\"div\",{\"i-carbon-compare\":\"\"},null,-1)),r[5]||(r[5]=X(\"div\",null,\" Snapshot Fail \",-1)),X(\"div\",Eue,Re(K(Oe).summary.filesSnapshotFailed),1)],64)):He(\"\",!0),K(eo).length?(ie(),ve(nt,{key:3},[r[6]||(r[6]=X(\"div\",{\"i-carbon-checkmark-outline-error\":\"\"},null,-1)),r[7]||(r[7]=X(\"div\",null,\" Errors \",-1)),X(\"div\",Aue,Re(K(eo).length),1)],64)):He(\"\",!0),r[10]||(r[10]=X(\"div\",{\"i-carbon-timer\":\"\"},null,-1)),r[11]||(r[11]=X(\"div\",null,\"Time\",-1)),X(\"div\",Lue,Re(K(Oe).summary.time),1)]),K(eo).length?(ie(),ve(\"div\",Mue,[r[15]||(r[15]=X(\"h3\",{\"text-center\":\"\",\"mb-2\":\"\"},\" Unhandled Errors \",-1)),X(\"p\",Nue,[Qe(\" Vitest caught \"+Re(K(eo).length)+\" error\"+Re(K(eo).length>1?\"s\":\"\")+\" during the test run.\",1),r[12]||(r[12]=X(\"br\",null,null,-1)),r[13]||(r[13]=Qe(\" This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected. \",-1))]),X(\"details\",Oue,[r[14]||(r[14]=X(\"summary\",{\"font-bold\":\"\",\"cursor-pointer\":\"\"},\" Errors \",-1)),(ie(!0),ve(nt,null,$n(K(eo),(o,s)=>(ie(),Ve(kue,{key:s,error:o},null,8,[\"error\"]))),128))])])):He(\"\",!0)],64))}}),Rue=Ni(Pue,[[\"__scopeId\",\"data-v-1bd0f2ea\"]]),$ue={\"p-2\":\"\",\"text-center\":\"\",flex:\"\"},Iue={\"text-4xl\":\"\",\"min-w-2em\":\"\"},Due={\"text-md\":\"\"},Bl=rt({__name:\"DashboardEntry\",setup(e){return(t,r)=>(ie(),ve(\"div\",$ue,[X(\"div\",null,[X(\"div\",Iue,[Dt(t.$slots,\"body\")]),X(\"div\",Due,[Dt(t.$slots,\"header\")])])]))}}),zue={flex:\"~ wrap\",\"justify-evenly\":\"\",\"gap-2\":\"\",p:\"x-4\",relative:\"\"},Fue=rt({__name:\"TestsEntry\",setup(e){function t(r){it.success=!1,it.failed=!1,it.skipped=!1,r!==\"total\"&&(it[r]=!0)}return(r,o)=>(ie(),ve(\"div\",zue,[Ne(Bl,{\"text-green5\":\"\",\"data-testid\":\"pass-entry\",\"cursor-pointer\":\"\",hover:\"op80\",onClick:o[0]||(o[0]=s=>t(\"success\"))},{header:We(()=>[...o[4]||(o[4]=[Qe(\" Pass \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.testsSuccess),1)]),_:1}),Ne(Bl,{class:ot({\"text-red5\":K(Oe).summary.testsFailed,op50:!K(Oe).summary.testsFailed}),\"data-testid\":\"fail-entry\",\"cursor-pointer\":\"\",hover:\"op80\",onClick:o[1]||(o[1]=s=>t(\"failed\"))},{header:We(()=>[...o[5]||(o[5]=[Qe(\" Fail \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.testsFailed),1)]),_:1},8,[\"class\"]),K(Oe).summary.testsSkipped?(ie(),Ve(Bl,{key:0,op50:\"\",\"data-testid\":\"skipped-entry\",\"cursor-pointer\":\"\",hover:\"op80\",onClick:o[2]||(o[2]=s=>t(\"skipped\"))},{header:We(()=>[...o[6]||(o[6]=[Qe(\" Skip \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.testsSkipped),1)]),_:1})):He(\"\",!0),K(Oe).summary.testsTodo?(ie(),Ve(Bl,{key:1,op50:\"\",\"data-testid\":\"todo-entry\"},{header:We(()=>[...o[7]||(o[7]=[Qe(\" Todo \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.testsTodo),1)]),_:1})):He(\"\",!0),Ne(Bl,{tail:!0,\"data-testid\":\"total-entry\",\"cursor-pointer\":\"\",hover:\"op80\",onClick:o[3]||(o[3]=s=>t(\"total\"))},{header:We(()=>[...o[8]||(o[8]=[Qe(\" Total \",-1)])]),body:We(()=>[Qe(Re(K(Oe).summary.totalTests),1)]),_:1})]))}}),Hue={\"gap-0\":\"\",flex:\"~ col gap-4\",\"h-full\":\"\",\"justify-center\":\"\",\"items-center\":\"\"},Bue={key:0,class:\"text-gray-5\"},Wue={\"aria-labelledby\":\"tests\",m:\"y-4 x-2\"},que=rt({__name:\"TestsFilesContainer\",setup(e){return(t,r)=>(ie(),ve(\"div\",Hue,[K(Oe).summary.files===0&&K(Ms)?(ie(),ve(\"div\",Bue,\" No tests found \")):He(\"\",!0),X(\"section\",Wue,[Ne(Fue)]),Ne(Rue)]))}}),jue={h:\"full\",flex:\"~ col\"},Uue={class:\"scrolls\",\"flex-auto\":\"\",\"py-1\":\"\"},Iy=rt({__name:\"Dashboard\",setup(e){return(t,r)=>(ie(),ve(\"div\",jue,[r[0]||(r[0]=X(\"div\",{p:\"3\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},[X(\"div\",{class:\"i-carbon-dashboard\"}),X(\"span\",{\"pl-1\":\"\",\"font-bold\":\"\",\"text-sm\":\"\",\"flex-auto\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",truncate:\"\"},\"Dashboard\")],-1)),X(\"div\",Uue,[Ne(que)])]))}});function Vue(e,t){let r;return(...o)=>{r!==void 0&&clearTimeout(r),r=setTimeout(()=>e(...o),t)}}var bh=\"http://www.w3.org/1999/xhtml\";const Dy={svg:\"http://www.w3.org/2000/svg\",xhtml:bh,xlink:\"http://www.w3.org/1999/xlink\",xml:\"http://www.w3.org/XML/1998/namespace\",xmlns:\"http://www.w3.org/2000/xmlns/\"};function ff(e){var t=e+=\"\",r=t.indexOf(\":\");return r>=0&&(t=e.slice(0,r))!==\"xmlns\"&&(e=e.slice(r+1)),Dy.hasOwnProperty(t)?{space:Dy[t],local:e}:e}function Gue(e){return function(){var t=this.ownerDocument,r=this.namespaceURI;return r===bh&&t.documentElement.namespaceURI===bh?t.createElement(e):t.createElementNS(r,e)}}function Kue(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function Ex(e){var t=ff(e);return(t.local?Kue:Gue)(t)}function Xue(){}function Tp(e){return e==null?Xue:function(){return this.querySelector(e)}}function Yue(e){typeof e!=\"function\"&&(e=Tp(e));for(var t=this._groups,r=t.length,o=new Array(r),s=0;s<r;++s)for(var c=t[s],f=c.length,d=o[s]=new Array(f),h,p,g=0;g<f;++g)(h=c[g])&&(p=e.call(h,h.__data__,g,c))&&(\"__data__\"in h&&(p.__data__=h.__data__),d[g]=p);return new lr(o,this._parents)}function Zue(e){return e==null?[]:Array.isArray(e)?e:Array.from(e)}function Jue(){return[]}function Ax(e){return e==null?Jue:function(){return this.querySelectorAll(e)}}function Que(e){return function(){return Zue(e.apply(this,arguments))}}function efe(e){typeof e==\"function\"?e=Que(e):e=Ax(e);for(var t=this._groups,r=t.length,o=[],s=[],c=0;c<r;++c)for(var f=t[c],d=f.length,h,p=0;p<d;++p)(h=f[p])&&(o.push(e.call(h,h.__data__,p,f)),s.push(h));return new lr(o,s)}function Lx(e){return function(){return this.matches(e)}}function Mx(e){return function(t){return t.matches(e)}}var tfe=Array.prototype.find;function nfe(e){return function(){return tfe.call(this.children,e)}}function rfe(){return this.firstElementChild}function ife(e){return this.select(e==null?rfe:nfe(typeof e==\"function\"?e:Mx(e)))}var ofe=Array.prototype.filter;function sfe(){return Array.from(this.children)}function lfe(e){return function(){return ofe.call(this.children,e)}}function afe(e){return this.selectAll(e==null?sfe:lfe(typeof e==\"function\"?e:Mx(e)))}function cfe(e){typeof e!=\"function\"&&(e=Lx(e));for(var t=this._groups,r=t.length,o=new Array(r),s=0;s<r;++s)for(var c=t[s],f=c.length,d=o[s]=[],h,p=0;p<f;++p)(h=c[p])&&e.call(h,h.__data__,p,c)&&d.push(h);return new lr(o,this._parents)}function Nx(e){return new Array(e.length)}function ufe(){return new lr(this._enter||this._groups.map(Nx),this._parents)}function Au(e,t){this.ownerDocument=e.ownerDocument,this.namespaceURI=e.namespaceURI,this._next=null,this._parent=e,this.__data__=t}Au.prototype={constructor:Au,appendChild:function(e){return this._parent.insertBefore(e,this._next)},insertBefore:function(e,t){return this._parent.insertBefore(e,t)},querySelector:function(e){return this._parent.querySelector(e)},querySelectorAll:function(e){return this._parent.querySelectorAll(e)}};function ffe(e){return function(){return e}}function dfe(e,t,r,o,s,c){for(var f=0,d,h=t.length,p=c.length;f<p;++f)(d=t[f])?(d.__data__=c[f],o[f]=d):r[f]=new Au(e,c[f]);for(;f<h;++f)(d=t[f])&&(s[f]=d)}function hfe(e,t,r,o,s,c,f){var d,h,p=new Map,g=t.length,v=c.length,b=new Array(g),w;for(d=0;d<g;++d)(h=t[d])&&(b[d]=w=f.call(h,h.__data__,d,t)+\"\",p.has(w)?s[d]=h:p.set(w,h));for(d=0;d<v;++d)w=f.call(e,c[d],d,c)+\"\",(h=p.get(w))?(o[d]=h,h.__data__=c[d],p.delete(w)):r[d]=new Au(e,c[d]);for(d=0;d<g;++d)(h=t[d])&&p.get(b[d])===h&&(s[d]=h)}function pfe(e){return e.__data__}function gfe(e,t){if(!arguments.length)return Array.from(this,pfe);var r=t?hfe:dfe,o=this._parents,s=this._groups;typeof e!=\"function\"&&(e=ffe(e));for(var c=s.length,f=new Array(c),d=new Array(c),h=new Array(c),p=0;p<c;++p){var g=o[p],v=s[p],b=v.length,w=mfe(e.call(g,g&&g.__data__,p,o)),E=w.length,L=d[p]=new Array(E),P=f[p]=new Array(E),M=h[p]=new Array(b);r(g,v,L,P,M,w,t);for(var R=0,I=0,_,$;R<E;++R)if(_=L[R]){for(R>=I&&(I=R+1);!($=P[I])&&++I<E;);_._next=$||null}}return f=new lr(f,o),f._enter=d,f._exit=h,f}function mfe(e){return typeof e==\"object\"&&\"length\"in e?e:Array.from(e)}function vfe(){return new lr(this._exit||this._groups.map(Nx),this._parents)}function yfe(e,t,r){var o=this.enter(),s=this,c=this.exit();return typeof e==\"function\"?(o=e(o),o&&(o=o.selection())):o=o.append(e+\"\"),t!=null&&(s=t(s),s&&(s=s.selection())),r==null?c.remove():r(c),o&&s?o.merge(s).order():s}function bfe(e){for(var t=e.selection?e.selection():e,r=this._groups,o=t._groups,s=r.length,c=o.length,f=Math.min(s,c),d=new Array(s),h=0;h<f;++h)for(var p=r[h],g=o[h],v=p.length,b=d[h]=new Array(v),w,E=0;E<v;++E)(w=p[E]||g[E])&&(b[E]=w);for(;h<s;++h)d[h]=r[h];return new lr(d,this._parents)}function wfe(){for(var e=this._groups,t=-1,r=e.length;++t<r;)for(var o=e[t],s=o.length-1,c=o[s],f;--s>=0;)(f=o[s])&&(c&&f.compareDocumentPosition(c)^4&&c.parentNode.insertBefore(f,c),c=f);return this}function xfe(e){e||(e=kfe);function t(v,b){return v&&b?e(v.__data__,b.__data__):!v-!b}for(var r=this._groups,o=r.length,s=new Array(o),c=0;c<o;++c){for(var f=r[c],d=f.length,h=s[c]=new Array(d),p,g=0;g<d;++g)(p=f[g])&&(h[g]=p);h.sort(t)}return new lr(s,this._parents).order()}function kfe(e,t){return e<t?-1:e>t?1:e>=t?0:NaN}function Sfe(){var e=arguments[0];return arguments[0]=this,e.apply(null,arguments),this}function _fe(){return Array.from(this)}function Tfe(){for(var e=this._groups,t=0,r=e.length;t<r;++t)for(var o=e[t],s=0,c=o.length;s<c;++s){var f=o[s];if(f)return f}return null}function Cfe(){let e=0;for(const t of this)++e;return e}function Efe(){return!this.node()}function Afe(e){for(var t=this._groups,r=0,o=t.length;r<o;++r)for(var s=t[r],c=0,f=s.length,d;c<f;++c)(d=s[c])&&e.call(d,d.__data__,c,s);return this}function Lfe(e){return function(){this.removeAttribute(e)}}function Mfe(e){return function(){this.removeAttributeNS(e.space,e.local)}}function Nfe(e,t){return function(){this.setAttribute(e,t)}}function Ofe(e,t){return function(){this.setAttributeNS(e.space,e.local,t)}}function Pfe(e,t){return function(){var r=t.apply(this,arguments);r==null?this.removeAttribute(e):this.setAttribute(e,r)}}function Rfe(e,t){return function(){var r=t.apply(this,arguments);r==null?this.removeAttributeNS(e.space,e.local):this.setAttributeNS(e.space,e.local,r)}}function $fe(e,t){var r=ff(e);if(arguments.length<2){var o=this.node();return r.local?o.getAttributeNS(r.space,r.local):o.getAttribute(r)}return this.each((t==null?r.local?Mfe:Lfe:typeof t==\"function\"?r.local?Rfe:Pfe:r.local?Ofe:Nfe)(r,t))}function Ox(e){return e.ownerDocument&&e.ownerDocument.defaultView||e.document&&e||e.defaultView}function Ife(e){return function(){this.style.removeProperty(e)}}function Dfe(e,t,r){return function(){this.style.setProperty(e,t,r)}}function zfe(e,t,r){return function(){var o=t.apply(this,arguments);o==null?this.style.removeProperty(e):this.style.setProperty(e,o,r)}}function Ffe(e,t,r){return arguments.length>1?this.each((t==null?Ife:typeof t==\"function\"?zfe:Dfe)(e,t,r??\"\")):el(this.node(),e)}function el(e,t){return e.style.getPropertyValue(t)||Ox(e).getComputedStyle(e,null).getPropertyValue(t)}function Hfe(e){return function(){delete this[e]}}function Bfe(e,t){return function(){this[e]=t}}function Wfe(e,t){return function(){var r=t.apply(this,arguments);r==null?delete this[e]:this[e]=r}}function qfe(e,t){return arguments.length>1?this.each((t==null?Hfe:typeof t==\"function\"?Wfe:Bfe)(e,t)):this.node()[e]}function Px(e){return e.trim().split(/^|\\s+/)}function Cp(e){return e.classList||new Rx(e)}function Rx(e){this._node=e,this._names=Px(e.getAttribute(\"class\")||\"\")}Rx.prototype={add:function(e){var t=this._names.indexOf(e);t<0&&(this._names.push(e),this._node.setAttribute(\"class\",this._names.join(\" \")))},remove:function(e){var t=this._names.indexOf(e);t>=0&&(this._names.splice(t,1),this._node.setAttribute(\"class\",this._names.join(\" \")))},contains:function(e){return this._names.indexOf(e)>=0}};function $x(e,t){for(var r=Cp(e),o=-1,s=t.length;++o<s;)r.add(t[o])}function Ix(e,t){for(var r=Cp(e),o=-1,s=t.length;++o<s;)r.remove(t[o])}function jfe(e){return function(){$x(this,e)}}function Ufe(e){return function(){Ix(this,e)}}function Vfe(e,t){return function(){(t.apply(this,arguments)?$x:Ix)(this,e)}}function Gfe(e,t){var r=Px(e+\"\");if(arguments.length<2){for(var o=Cp(this.node()),s=-1,c=r.length;++s<c;)if(!o.contains(r[s]))return!1;return!0}return this.each((typeof t==\"function\"?Vfe:t?jfe:Ufe)(r,t))}function Kfe(){this.textContent=\"\"}function Xfe(e){return function(){this.textContent=e}}function Yfe(e){return function(){var t=e.apply(this,arguments);this.textContent=t??\"\"}}function Zfe(e){return arguments.length?this.each(e==null?Kfe:(typeof e==\"function\"?Yfe:Xfe)(e)):this.node().textContent}function Jfe(){this.innerHTML=\"\"}function Qfe(e){return function(){this.innerHTML=e}}function ede(e){return function(){var t=e.apply(this,arguments);this.innerHTML=t??\"\"}}function tde(e){return arguments.length?this.each(e==null?Jfe:(typeof e==\"function\"?ede:Qfe)(e)):this.node().innerHTML}function nde(){this.nextSibling&&this.parentNode.appendChild(this)}function rde(){return this.each(nde)}function ide(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function ode(){return this.each(ide)}function sde(e){var t=typeof e==\"function\"?e:Ex(e);return this.select(function(){return this.appendChild(t.apply(this,arguments))})}function lde(){return null}function ade(e,t){var r=typeof e==\"function\"?e:Ex(e),o=t==null?lde:typeof t==\"function\"?t:Tp(t);return this.select(function(){return this.insertBefore(r.apply(this,arguments),o.apply(this,arguments)||null)})}function cde(){var e=this.parentNode;e&&e.removeChild(this)}function ude(){return this.each(cde)}function fde(){var e=this.cloneNode(!1),t=this.parentNode;return t?t.insertBefore(e,this.nextSibling):e}function dde(){var e=this.cloneNode(!0),t=this.parentNode;return t?t.insertBefore(e,this.nextSibling):e}function hde(e){return this.select(e?dde:fde)}function pde(e){return arguments.length?this.property(\"__data__\",e):this.node().__data__}function gde(e){return function(t){e.call(this,t,this.__data__)}}function mde(e){return e.trim().split(/^|\\s+/).map(function(t){var r=\"\",o=t.indexOf(\".\");return o>=0&&(r=t.slice(o+1),t=t.slice(0,o)),{type:t,name:r}})}function vde(e){return function(){var t=this.__on;if(t){for(var r=0,o=-1,s=t.length,c;r<s;++r)c=t[r],(!e.type||c.type===e.type)&&c.name===e.name?this.removeEventListener(c.type,c.listener,c.options):t[++o]=c;++o?t.length=o:delete this.__on}}}function yde(e,t,r){return function(){var o=this.__on,s,c=gde(t);if(o){for(var f=0,d=o.length;f<d;++f)if((s=o[f]).type===e.type&&s.name===e.name){this.removeEventListener(s.type,s.listener,s.options),this.addEventListener(s.type,s.listener=c,s.options=r),s.value=t;return}}this.addEventListener(e.type,c,r),s={type:e.type,name:e.name,value:t,listener:c,options:r},o?o.push(s):this.__on=[s]}}function bde(e,t,r){var o=mde(e+\"\"),s,c=o.length,f;if(arguments.length<2){var d=this.node().__on;if(d){for(var h=0,p=d.length,g;h<p;++h)for(s=0,g=d[h];s<c;++s)if((f=o[s]).type===g.type&&f.name===g.name)return g.value}return}for(d=t?yde:vde,s=0;s<c;++s)this.each(d(o[s],t,r));return this}function Dx(e,t,r){var o=Ox(e),s=o.CustomEvent;typeof s==\"function\"?s=new s(t,r):(s=o.document.createEvent(\"Event\"),r?(s.initEvent(t,r.bubbles,r.cancelable),s.detail=r.detail):s.initEvent(t,!1,!1)),e.dispatchEvent(s)}function wde(e,t){return function(){return Dx(this,e,t)}}function xde(e,t){return function(){return Dx(this,e,t.apply(this,arguments))}}function kde(e,t){return this.each((typeof t==\"function\"?xde:wde)(e,t))}function*Sde(){for(var e=this._groups,t=0,r=e.length;t<r;++t)for(var o=e[t],s=0,c=o.length,f;s<c;++s)(f=o[s])&&(yield f)}var zx=[null];function lr(e,t){this._groups=e,this._parents=t}function ja(){return new lr([[document.documentElement]],zx)}function _de(){return this}lr.prototype=ja.prototype={constructor:lr,select:Yue,selectAll:efe,selectChild:ife,selectChildren:afe,filter:cfe,data:gfe,enter:ufe,exit:vfe,join:yfe,merge:bfe,selection:_de,order:wfe,sort:xfe,call:Sfe,nodes:_fe,node:Tfe,size:Cfe,empty:Efe,each:Afe,attr:$fe,style:Ffe,property:qfe,classed:Gfe,text:Zfe,html:tde,raise:rde,lower:ode,append:sde,insert:ade,remove:ude,clone:hde,datum:pde,on:bde,dispatch:kde,[Symbol.iterator]:Sde};function Kn(e){return typeof e==\"string\"?new lr([[document.querySelector(e)]],[document.documentElement]):new lr([[e]],zx)}function Tde(e){let t;for(;t=e.sourceEvent;)e=t;return e}function vi(e,t){if(e=Tde(e),t===void 0&&(t=e.currentTarget),t){var r=t.ownerSVGElement||t;if(r.createSVGPoint){var o=r.createSVGPoint();return o.x=e.clientX,o.y=e.clientY,o=o.matrixTransform(t.getScreenCTM().inverse()),[o.x,o.y]}if(t.getBoundingClientRect){var s=t.getBoundingClientRect();return[e.clientX-s.left-t.clientLeft,e.clientY-s.top-t.clientTop]}}return[e.pageX,e.pageY]}var tl=class gi{x;y;static of([t,r]){return new gi(t,r)}constructor(t,r){this.x=t,this.y=r}add(t){return new gi(this.x+t.x,this.y+t.y)}subtract(t){return new gi(this.x-t.x,this.y-t.y)}multiply(t){return new gi(this.x*t,this.y*t)}divide(t){return new gi(this.x/t,this.y/t)}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-t.x*this.y}hadamard(t){return new gi(this.x*t.x,this.y*t.y)}length(){return Math.sqrt(this.x**2+this.y**2)}normalize(){const t=this.length();return new gi(this.x/t,this.y/t)}rotateByRadians(t){const r=Math.cos(t),o=Math.sin(t);return new gi(this.x*r-this.y*o,this.x*o+this.y*r)}rotateByDegrees(t){return this.rotateByRadians(t*Math.PI/180)}},Cde={value:()=>{}};function Ua(){for(var e=0,t=arguments.length,r={},o;e<t;++e){if(!(o=arguments[e]+\"\")||o in r||/[\\s.]/.test(o))throw new Error(\"illegal type: \"+o);r[o]=[]}return new Zc(r)}function Zc(e){this._=e}function Ede(e,t){return e.trim().split(/^|\\s+/).map(function(r){var o=\"\",s=r.indexOf(\".\");if(s>=0&&(o=r.slice(s+1),r=r.slice(0,s)),r&&!t.hasOwnProperty(r))throw new Error(\"unknown type: \"+r);return{type:r,name:o}})}Zc.prototype=Ua.prototype={constructor:Zc,on:function(e,t){var r=this._,o=Ede(e+\"\",r),s,c=-1,f=o.length;if(arguments.length<2){for(;++c<f;)if((s=(e=o[c]).type)&&(s=Ade(r[s],e.name)))return s;return}if(t!=null&&typeof t!=\"function\")throw new Error(\"invalid callback: \"+t);for(;++c<f;)if(s=(e=o[c]).type)r[s]=zy(r[s],e.name,t);else if(t==null)for(s in r)r[s]=zy(r[s],e.name,null);return this},copy:function(){var e={},t=this._;for(var r in t)e[r]=t[r].slice();return new Zc(e)},call:function(e,t){if((s=arguments.length-2)>0)for(var r=new Array(s),o=0,s,c;o<s;++o)r[o]=arguments[o+2];if(!this._.hasOwnProperty(e))throw new Error(\"unknown type: \"+e);for(c=this._[e],o=0,s=c.length;o<s;++o)c[o].value.apply(t,r)},apply:function(e,t,r){if(!this._.hasOwnProperty(e))throw new Error(\"unknown type: \"+e);for(var o=this._[e],s=0,c=o.length;s<c;++s)o[s].value.apply(t,r)}};function Ade(e,t){for(var r=0,o=e.length,s;r<o;++r)if((s=e[r]).name===t)return s.value}function zy(e,t,r){for(var o=0,s=e.length;o<s;++o)if(e[o].name===t){e[o]=Cde,e=e.slice(0,o).concat(e.slice(o+1));break}return r!=null&&e.push({name:t,value:r}),e}const Lde={passive:!1},Ta={capture:!0,passive:!1};function Rd(e){e.stopImmediatePropagation()}function js(e){e.preventDefault(),e.stopImmediatePropagation()}function Fx(e){var t=e.document.documentElement,r=Kn(e).on(\"dragstart.drag\",js,Ta);\"onselectstart\"in t?r.on(\"selectstart.drag\",js,Ta):(t.__noselect=t.style.MozUserSelect,t.style.MozUserSelect=\"none\")}function Hx(e,t){var r=e.document.documentElement,o=Kn(e).on(\"dragstart.drag\",null);t&&(o.on(\"click.drag\",js,Ta),setTimeout(function(){o.on(\"click.drag\",null)},0)),\"onselectstart\"in r?o.on(\"selectstart.drag\",null):(r.style.MozUserSelect=r.__noselect,delete r.__noselect)}const Ic=e=>()=>e;function wh(e,{sourceEvent:t,subject:r,target:o,identifier:s,active:c,x:f,y:d,dx:h,dy:p,dispatch:g}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},subject:{value:r,enumerable:!0,configurable:!0},target:{value:o,enumerable:!0,configurable:!0},identifier:{value:s,enumerable:!0,configurable:!0},active:{value:c,enumerable:!0,configurable:!0},x:{value:f,enumerable:!0,configurable:!0},y:{value:d,enumerable:!0,configurable:!0},dx:{value:h,enumerable:!0,configurable:!0},dy:{value:p,enumerable:!0,configurable:!0},_:{value:g}})}wh.prototype.on=function(){var e=this._.on.apply(this._,arguments);return e===this._?this:e};function Mde(e){return!e.ctrlKey&&!e.button}function Nde(){return this.parentNode}function Ode(e,t){return t??{x:e.x,y:e.y}}function Pde(){return navigator.maxTouchPoints||\"ontouchstart\"in this}function Rde(){var e=Mde,t=Nde,r=Ode,o=Pde,s={},c=Ua(\"start\",\"drag\",\"end\"),f=0,d,h,p,g,v=0;function b(_){_.on(\"mousedown.drag\",w).filter(o).on(\"touchstart.drag\",P).on(\"touchmove.drag\",M,Lde).on(\"touchend.drag touchcancel.drag\",R).style(\"touch-action\",\"none\").style(\"-webkit-tap-highlight-color\",\"rgba(0,0,0,0)\")}function w(_,$){if(!(g||!e.call(this,_,$))){var W=I(this,t.call(this,_,$),_,$,\"mouse\");W&&(Kn(_.view).on(\"mousemove.drag\",E,Ta).on(\"mouseup.drag\",L,Ta),Fx(_.view),Rd(_),p=!1,d=_.clientX,h=_.clientY,W(\"start\",_))}}function E(_){if(js(_),!p){var $=_.clientX-d,W=_.clientY-h;p=$*$+W*W>v}s.mouse(\"drag\",_)}function L(_){Kn(_.view).on(\"mousemove.drag mouseup.drag\",null),Hx(_.view,p),js(_),s.mouse(\"end\",_)}function P(_,$){if(e.call(this,_,$)){var W=_.changedTouches,ne=t.call(this,_,$),ee=W.length,Z,G;for(Z=0;Z<ee;++Z)(G=I(this,ne,_,$,W[Z].identifier,W[Z]))&&(Rd(_),G(\"start\",_,W[Z]))}}function M(_){var $=_.changedTouches,W=$.length,ne,ee;for(ne=0;ne<W;++ne)(ee=s[$[ne].identifier])&&(js(_),ee(\"drag\",_,$[ne]))}function R(_){var $=_.changedTouches,W=$.length,ne,ee;for(g&&clearTimeout(g),g=setTimeout(function(){g=null},500),ne=0;ne<W;++ne)(ee=s[$[ne].identifier])&&(Rd(_),ee(\"end\",_,$[ne]))}function I(_,$,W,ne,ee,Z){var G=c.copy(),j=vi(Z||W,$),N,O,C;if((C=r.call(_,new wh(\"beforestart\",{sourceEvent:W,target:b,identifier:ee,active:f,x:j[0],y:j[1],dx:0,dy:0,dispatch:G}),ne))!=null)return N=C.x-j[0]||0,O=C.y-j[1]||0,function k(z,B,ce){var be=j,Se;switch(z){case\"start\":s[ee]=k,Se=f++;break;case\"end\":delete s[ee],--f;case\"drag\":j=vi(ce||B,$),Se=f;break}G.call(z,_,new wh(z,{sourceEvent:B,subject:C,target:b,identifier:ee,active:Se,x:j[0]+N,y:j[1]+O,dx:j[0]-be[0],dy:j[1]-be[1],dispatch:G}),ne)}}return b.filter=function(_){return arguments.length?(e=typeof _==\"function\"?_:Ic(!!_),b):e},b.container=function(_){return arguments.length?(t=typeof _==\"function\"?_:Ic(_),b):t},b.subject=function(_){return arguments.length?(r=typeof _==\"function\"?_:Ic(_),b):r},b.touchable=function(_){return arguments.length?(o=typeof _==\"function\"?_:Ic(!!_),b):o},b.on=function(){var _=c.on.apply(c,arguments);return _===c?b:_},b.clickDistance=function(_){return arguments.length?(v=(_=+_)*_,b):Math.sqrt(v)},b}function Ep(e,t,r){e.prototype=t.prototype=r,r.constructor=e}function Bx(e,t){var r=Object.create(e.prototype);for(var o in t)r[o]=t[o];return r}function Va(){}var Ca=.7,Lu=1/Ca,Us=\"\\\\s*([+-]?\\\\d+)\\\\s*\",Ea=\"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)\\\\s*\",Jr=\"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)%\\\\s*\",$de=/^#([0-9a-f]{3,8})$/,Ide=new RegExp(`^rgb\\\\(${Us},${Us},${Us}\\\\)$`),Dde=new RegExp(`^rgb\\\\(${Jr},${Jr},${Jr}\\\\)$`),zde=new RegExp(`^rgba\\\\(${Us},${Us},${Us},${Ea}\\\\)$`),Fde=new RegExp(`^rgba\\\\(${Jr},${Jr},${Jr},${Ea}\\\\)$`),Hde=new RegExp(`^hsl\\\\(${Ea},${Jr},${Jr}\\\\)$`),Bde=new RegExp(`^hsla\\\\(${Ea},${Jr},${Jr},${Ea}\\\\)$`),Fy={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};Ep(Va,Aa,{copy(e){return Object.assign(new this.constructor,this,e)},displayable(){return this.rgb().displayable()},hex:Hy,formatHex:Hy,formatHex8:Wde,formatHsl:qde,formatRgb:By,toString:By});function Hy(){return this.rgb().formatHex()}function Wde(){return this.rgb().formatHex8()}function qde(){return Wx(this).formatHsl()}function By(){return this.rgb().formatRgb()}function Aa(e){var t,r;return e=(e+\"\").trim().toLowerCase(),(t=$de.exec(e))?(r=t[1].length,t=parseInt(t[1],16),r===6?Wy(t):r===3?new Yn(t>>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):r===8?Dc(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):r===4?Dc(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=Ide.exec(e))?new Yn(t[1],t[2],t[3],1):(t=Dde.exec(e))?new Yn(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=zde.exec(e))?Dc(t[1],t[2],t[3],t[4]):(t=Fde.exec(e))?Dc(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=Hde.exec(e))?Uy(t[1],t[2]/100,t[3]/100,1):(t=Bde.exec(e))?Uy(t[1],t[2]/100,t[3]/100,t[4]):Fy.hasOwnProperty(e)?Wy(Fy[e]):e===\"transparent\"?new Yn(NaN,NaN,NaN,0):null}function Wy(e){return new Yn(e>>16&255,e>>8&255,e&255,1)}function Dc(e,t,r,o){return o<=0&&(e=t=r=NaN),new Yn(e,t,r,o)}function jde(e){return e instanceof Va||(e=Aa(e)),e?(e=e.rgb(),new Yn(e.r,e.g,e.b,e.opacity)):new Yn}function xh(e,t,r,o){return arguments.length===1?jde(e):new Yn(e,t,r,o??1)}function Yn(e,t,r,o){this.r=+e,this.g=+t,this.b=+r,this.opacity=+o}Ep(Yn,xh,Bx(Va,{brighter(e){return e=e==null?Lu:Math.pow(Lu,e),new Yn(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?Ca:Math.pow(Ca,e),new Yn(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new Yn(Vo(this.r),Vo(this.g),Vo(this.b),Mu(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:qy,formatHex:qy,formatHex8:Ude,formatRgb:jy,toString:jy}));function qy(){return`#${Bo(this.r)}${Bo(this.g)}${Bo(this.b)}`}function Ude(){return`#${Bo(this.r)}${Bo(this.g)}${Bo(this.b)}${Bo((isNaN(this.opacity)?1:this.opacity)*255)}`}function jy(){const e=Mu(this.opacity);return`${e===1?\"rgb(\":\"rgba(\"}${Vo(this.r)}, ${Vo(this.g)}, ${Vo(this.b)}${e===1?\")\":`, ${e})`}`}function Mu(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function Vo(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function Bo(e){return e=Vo(e),(e<16?\"0\":\"\")+e.toString(16)}function Uy(e,t,r,o){return o<=0?e=t=r=NaN:r<=0||r>=1?e=t=NaN:t<=0&&(e=NaN),new Mr(e,t,r,o)}function Wx(e){if(e instanceof Mr)return new Mr(e.h,e.s,e.l,e.opacity);if(e instanceof Va||(e=Aa(e)),!e)return new Mr;if(e instanceof Mr)return e;e=e.rgb();var t=e.r/255,r=e.g/255,o=e.b/255,s=Math.min(t,r,o),c=Math.max(t,r,o),f=NaN,d=c-s,h=(c+s)/2;return d?(t===c?f=(r-o)/d+(r<o)*6:r===c?f=(o-t)/d+2:f=(t-r)/d+4,d/=h<.5?c+s:2-c-s,f*=60):d=h>0&&h<1?0:f,new Mr(f,d,h,e.opacity)}function Vde(e,t,r,o){return arguments.length===1?Wx(e):new Mr(e,t,r,o??1)}function Mr(e,t,r,o){this.h=+e,this.s=+t,this.l=+r,this.opacity=+o}Ep(Mr,Vde,Bx(Va,{brighter(e){return e=e==null?Lu:Math.pow(Lu,e),new Mr(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?Ca:Math.pow(Ca,e),new Mr(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,r=this.l,o=r+(r<.5?r:1-r)*t,s=2*r-o;return new Yn($d(e>=240?e-240:e+120,s,o),$d(e,s,o),$d(e<120?e+240:e-120,s,o),this.opacity)},clamp(){return new Mr(Vy(this.h),zc(this.s),zc(this.l),Mu(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const e=Mu(this.opacity);return`${e===1?\"hsl(\":\"hsla(\"}${Vy(this.h)}, ${zc(this.s)*100}%, ${zc(this.l)*100}%${e===1?\")\":`, ${e})`}`}}));function Vy(e){return e=(e||0)%360,e<0?e+360:e}function zc(e){return Math.max(0,Math.min(1,e||0))}function $d(e,t,r){return(e<60?t+(r-t)*e/60:e<180?r:e<240?t+(r-t)*(240-e)/60:t)*255}const qx=e=>()=>e;function Gde(e,t){return function(r){return e+r*t}}function Kde(e,t,r){return e=Math.pow(e,r),t=Math.pow(t,r)-e,r=1/r,function(o){return Math.pow(e+o*t,r)}}function Xde(e){return(e=+e)==1?jx:function(t,r){return r-t?Kde(t,r,e):qx(isNaN(t)?r:t)}}function jx(e,t){var r=t-e;return r?Gde(e,r):qx(isNaN(e)?t:e)}const Gy=(function e(t){var r=Xde(t);function o(s,c){var f=r((s=xh(s)).r,(c=xh(c)).r),d=r(s.g,c.g),h=r(s.b,c.b),p=jx(s.opacity,c.opacity);return function(g){return s.r=f(g),s.g=d(g),s.b=h(g),s.opacity=p(g),s+\"\"}}return o.gamma=e,o})(1);function to(e,t){return e=+e,t=+t,function(r){return e*(1-r)+t*r}}var kh=/[-+]?(?:\\d+\\.?\\d*|\\.?\\d+)(?:[eE][-+]?\\d+)?/g,Id=new RegExp(kh.source,\"g\");function Yde(e){return function(){return e}}function Zde(e){return function(t){return e(t)+\"\"}}function Jde(e,t){var r=kh.lastIndex=Id.lastIndex=0,o,s,c,f=-1,d=[],h=[];for(e=e+\"\",t=t+\"\";(o=kh.exec(e))&&(s=Id.exec(t));)(c=s.index)>r&&(c=t.slice(r,c),d[f]?d[f]+=c:d[++f]=c),(o=o[0])===(s=s[0])?d[f]?d[f]+=s:d[++f]=s:(d[++f]=null,h.push({i:f,x:to(o,s)})),r=Id.lastIndex;return r<t.length&&(c=t.slice(r),d[f]?d[f]+=c:d[++f]=c),d.length<2?h[0]?Zde(h[0].x):Yde(t):(t=h.length,function(p){for(var g=0,v;g<t;++g)d[(v=h[g]).i]=v.x(p);return d.join(\"\")})}var Ky=180/Math.PI,Sh={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function Ux(e,t,r,o,s,c){var f,d,h;return(f=Math.sqrt(e*e+t*t))&&(e/=f,t/=f),(h=e*r+t*o)&&(r-=e*h,o-=t*h),(d=Math.sqrt(r*r+o*o))&&(r/=d,o/=d,h/=d),e*o<t*r&&(e=-e,t=-t,h=-h,f=-f),{translateX:s,translateY:c,rotate:Math.atan2(t,e)*Ky,skewX:Math.atan(h)*Ky,scaleX:f,scaleY:d}}var Fc;function Qde(e){const t=new(typeof DOMMatrix==\"function\"?DOMMatrix:WebKitCSSMatrix)(e+\"\");return t.isIdentity?Sh:Ux(t.a,t.b,t.c,t.d,t.e,t.f)}function ehe(e){return e==null||(Fc||(Fc=document.createElementNS(\"http://www.w3.org/2000/svg\",\"g\")),Fc.setAttribute(\"transform\",e),!(e=Fc.transform.baseVal.consolidate()))?Sh:(e=e.matrix,Ux(e.a,e.b,e.c,e.d,e.e,e.f))}function Vx(e,t,r,o){function s(p){return p.length?p.pop()+\" \":\"\"}function c(p,g,v,b,w,E){if(p!==v||g!==b){var L=w.push(\"translate(\",null,t,null,r);E.push({i:L-4,x:to(p,v)},{i:L-2,x:to(g,b)})}else(v||b)&&w.push(\"translate(\"+v+t+b+r)}function f(p,g,v,b){p!==g?(p-g>180?g+=360:g-p>180&&(p+=360),b.push({i:v.push(s(v)+\"rotate(\",null,o)-2,x:to(p,g)})):g&&v.push(s(v)+\"rotate(\"+g+o)}function d(p,g,v,b){p!==g?b.push({i:v.push(s(v)+\"skewX(\",null,o)-2,x:to(p,g)}):g&&v.push(s(v)+\"skewX(\"+g+o)}function h(p,g,v,b,w,E){if(p!==v||g!==b){var L=w.push(s(w)+\"scale(\",null,\",\",null,\")\");E.push({i:L-4,x:to(p,v)},{i:L-2,x:to(g,b)})}else(v!==1||b!==1)&&w.push(s(w)+\"scale(\"+v+\",\"+b+\")\")}return function(p,g){var v=[],b=[];return p=e(p),g=e(g),c(p.translateX,p.translateY,g.translateX,g.translateY,v,b),f(p.rotate,g.rotate,v,b),d(p.skewX,g.skewX,v,b),h(p.scaleX,p.scaleY,g.scaleX,g.scaleY,v,b),p=g=null,function(w){for(var E=-1,L=b.length,P;++E<L;)v[(P=b[E]).i]=P.x(w);return v.join(\"\")}}}var the=Vx(Qde,\"px, \",\"px)\",\"deg)\"),nhe=Vx(ehe,\", \",\")\",\")\"),rhe=1e-12;function Xy(e){return((e=Math.exp(e))+1/e)/2}function ihe(e){return((e=Math.exp(e))-1/e)/2}function ohe(e){return((e=Math.exp(2*e))-1)/(e+1)}const she=(function e(t,r,o){function s(c,f){var d=c[0],h=c[1],p=c[2],g=f[0],v=f[1],b=f[2],w=g-d,E=v-h,L=w*w+E*E,P,M;if(L<rhe)M=Math.log(b/p)/t,P=function(ne){return[d+ne*w,h+ne*E,p*Math.exp(t*ne*M)]};else{var R=Math.sqrt(L),I=(b*b-p*p+o*L)/(2*p*r*R),_=(b*b-p*p-o*L)/(2*b*r*R),$=Math.log(Math.sqrt(I*I+1)-I),W=Math.log(Math.sqrt(_*_+1)-_);M=(W-$)/t,P=function(ne){var ee=ne*M,Z=Xy($),G=p/(r*R)*(Z*ohe(t*ee+$)-ihe($));return[d+G*w,h+G*E,p*Z/Xy(t*ee+$)]}}return P.duration=M*1e3*t/Math.SQRT2,P}return s.rho=function(c){var f=Math.max(.001,+c),d=f*f,h=d*d;return e(f,d,h)},s})(Math.SQRT2,2,4);var nl=0,Vl=0,Wl=0,Gx=1e3,Nu,Gl,Ou=0,Ko=0,df=0,La=typeof performance==\"object\"&&performance.now?performance:Date,Kx=typeof window==\"object\"&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(e){setTimeout(e,17)};function Ap(){return Ko||(Kx(lhe),Ko=La.now()+df)}function lhe(){Ko=0}function Pu(){this._call=this._time=this._next=null}Pu.prototype=Lp.prototype={constructor:Pu,restart:function(e,t,r){if(typeof e!=\"function\")throw new TypeError(\"callback is not a function\");r=(r==null?Ap():+r)+(t==null?0:+t),!this._next&&Gl!==this&&(Gl?Gl._next=this:Nu=this,Gl=this),this._call=e,this._time=r,_h()},stop:function(){this._call&&(this._call=null,this._time=1/0,_h())}};function Lp(e,t,r){var o=new Pu;return o.restart(e,t,r),o}function ahe(){Ap(),++nl;for(var e=Nu,t;e;)(t=Ko-e._time)>=0&&e._call.call(void 0,t),e=e._next;--nl}function Yy(){Ko=(Ou=La.now())+df,nl=Vl=0;try{ahe()}finally{nl=0,uhe(),Ko=0}}function che(){var e=La.now(),t=e-Ou;t>Gx&&(df-=t,Ou=e)}function uhe(){for(var e,t=Nu,r,o=1/0;t;)t._call?(o>t._time&&(o=t._time),e=t,t=t._next):(r=t._next,t._next=null,t=e?e._next=r:Nu=r);Gl=e,_h(o)}function _h(e){if(!nl){Vl&&(Vl=clearTimeout(Vl));var t=e-Ko;t>24?(e<1/0&&(Vl=setTimeout(Yy,e-La.now()-df)),Wl&&(Wl=clearInterval(Wl))):(Wl||(Ou=La.now(),Wl=setInterval(che,Gx)),nl=1,Kx(Yy))}}function Zy(e,t,r){var o=new Pu;return t=t==null?0:+t,o.restart(s=>{o.stop(),e(s+t)},t,r),o}var fhe=Ua(\"start\",\"end\",\"cancel\",\"interrupt\"),dhe=[],Xx=0,Jy=1,Th=2,Jc=3,Qy=4,Ch=5,Qc=6;function hf(e,t,r,o,s,c){var f=e.__transition;if(!f)e.__transition={};else if(r in f)return;hhe(e,r,{name:t,index:o,group:s,on:fhe,tween:dhe,time:c.time,delay:c.delay,duration:c.duration,ease:c.ease,timer:null,state:Xx})}function Mp(e,t){var r=Fr(e,t);if(r.state>Xx)throw new Error(\"too late; already scheduled\");return r}function ni(e,t){var r=Fr(e,t);if(r.state>Jc)throw new Error(\"too late; already running\");return r}function Fr(e,t){var r=e.__transition;if(!r||!(r=r[t]))throw new Error(\"transition not found\");return r}function hhe(e,t,r){var o=e.__transition,s;o[t]=r,r.timer=Lp(c,0,r.time);function c(p){r.state=Jy,r.timer.restart(f,r.delay,r.time),r.delay<=p&&f(p-r.delay)}function f(p){var g,v,b,w;if(r.state!==Jy)return h();for(g in o)if(w=o[g],w.name===r.name){if(w.state===Jc)return Zy(f);w.state===Qy?(w.state=Qc,w.timer.stop(),w.on.call(\"interrupt\",e,e.__data__,w.index,w.group),delete o[g]):+g<t&&(w.state=Qc,w.timer.stop(),w.on.call(\"cancel\",e,e.__data__,w.index,w.group),delete o[g])}if(Zy(function(){r.state===Jc&&(r.state=Qy,r.timer.restart(d,r.delay,r.time),d(p))}),r.state=Th,r.on.call(\"start\",e,e.__data__,r.index,r.group),r.state===Th){for(r.state=Jc,s=new Array(b=r.tween.length),g=0,v=-1;g<b;++g)(w=r.tween[g].value.call(e,e.__data__,r.index,r.group))&&(s[++v]=w);s.length=v+1}}function d(p){for(var g=p<r.duration?r.ease.call(null,p/r.duration):(r.timer.restart(h),r.state=Ch,1),v=-1,b=s.length;++v<b;)s[v].call(e,g);r.state===Ch&&(r.on.call(\"end\",e,e.__data__,r.index,r.group),h())}function h(){r.state=Qc,r.timer.stop(),delete o[t];for(var p in o)return;delete e.__transition}}function eu(e,t){var r=e.__transition,o,s,c=!0,f;if(r){t=t==null?null:t+\"\";for(f in r){if((o=r[f]).name!==t){c=!1;continue}s=o.state>Th&&o.state<Ch,o.state=Qc,o.timer.stop(),o.on.call(s?\"interrupt\":\"cancel\",e,e.__data__,o.index,o.group),delete r[f]}c&&delete e.__transition}}function phe(e){return this.each(function(){eu(this,e)})}function ghe(e,t){var r,o;return function(){var s=ni(this,e),c=s.tween;if(c!==r){o=r=c;for(var f=0,d=o.length;f<d;++f)if(o[f].name===t){o=o.slice(),o.splice(f,1);break}}s.tween=o}}function mhe(e,t,r){var o,s;if(typeof r!=\"function\")throw new Error;return function(){var c=ni(this,e),f=c.tween;if(f!==o){s=(o=f).slice();for(var d={name:t,value:r},h=0,p=s.length;h<p;++h)if(s[h].name===t){s[h]=d;break}h===p&&s.push(d)}c.tween=s}}function vhe(e,t){var r=this._id;if(e+=\"\",arguments.length<2){for(var o=Fr(this.node(),r).tween,s=0,c=o.length,f;s<c;++s)if((f=o[s]).name===e)return f.value;return null}return this.each((t==null?ghe:mhe)(r,e,t))}function Np(e,t,r){var o=e._id;return e.each(function(){var s=ni(this,o);(s.value||(s.value={}))[t]=r.apply(this,arguments)}),function(s){return Fr(s,o).value[t]}}function Yx(e,t){var r;return(typeof t==\"number\"?to:t instanceof Aa?Gy:(r=Aa(t))?(t=r,Gy):Jde)(e,t)}function yhe(e){return function(){this.removeAttribute(e)}}function bhe(e){return function(){this.removeAttributeNS(e.space,e.local)}}function whe(e,t,r){var o,s=r+\"\",c;return function(){var f=this.getAttribute(e);return f===s?null:f===o?c:c=t(o=f,r)}}function xhe(e,t,r){var o,s=r+\"\",c;return function(){var f=this.getAttributeNS(e.space,e.local);return f===s?null:f===o?c:c=t(o=f,r)}}function khe(e,t,r){var o,s,c;return function(){var f,d=r(this),h;return d==null?void this.removeAttribute(e):(f=this.getAttribute(e),h=d+\"\",f===h?null:f===o&&h===s?c:(s=h,c=t(o=f,d)))}}function She(e,t,r){var o,s,c;return function(){var f,d=r(this),h;return d==null?void this.removeAttributeNS(e.space,e.local):(f=this.getAttributeNS(e.space,e.local),h=d+\"\",f===h?null:f===o&&h===s?c:(s=h,c=t(o=f,d)))}}function _he(e,t){var r=ff(e),o=r===\"transform\"?nhe:Yx;return this.attrTween(e,typeof t==\"function\"?(r.local?She:khe)(r,o,Np(this,\"attr.\"+e,t)):t==null?(r.local?bhe:yhe)(r):(r.local?xhe:whe)(r,o,t))}function The(e,t){return function(r){this.setAttribute(e,t.call(this,r))}}function Che(e,t){return function(r){this.setAttributeNS(e.space,e.local,t.call(this,r))}}function Ehe(e,t){var r,o;function s(){var c=t.apply(this,arguments);return c!==o&&(r=(o=c)&&Che(e,c)),r}return s._value=t,s}function Ahe(e,t){var r,o;function s(){var c=t.apply(this,arguments);return c!==o&&(r=(o=c)&&The(e,c)),r}return s._value=t,s}function Lhe(e,t){var r=\"attr.\"+e;if(arguments.length<2)return(r=this.tween(r))&&r._value;if(t==null)return this.tween(r,null);if(typeof t!=\"function\")throw new Error;var o=ff(e);return this.tween(r,(o.local?Ehe:Ahe)(o,t))}function Mhe(e,t){return function(){Mp(this,e).delay=+t.apply(this,arguments)}}function Nhe(e,t){return t=+t,function(){Mp(this,e).delay=t}}function Ohe(e){var t=this._id;return arguments.length?this.each((typeof e==\"function\"?Mhe:Nhe)(t,e)):Fr(this.node(),t).delay}function Phe(e,t){return function(){ni(this,e).duration=+t.apply(this,arguments)}}function Rhe(e,t){return t=+t,function(){ni(this,e).duration=t}}function $he(e){var t=this._id;return arguments.length?this.each((typeof e==\"function\"?Phe:Rhe)(t,e)):Fr(this.node(),t).duration}function Ihe(e,t){if(typeof t!=\"function\")throw new Error;return function(){ni(this,e).ease=t}}function Dhe(e){var t=this._id;return arguments.length?this.each(Ihe(t,e)):Fr(this.node(),t).ease}function zhe(e,t){return function(){var r=t.apply(this,arguments);if(typeof r!=\"function\")throw new Error;ni(this,e).ease=r}}function Fhe(e){if(typeof e!=\"function\")throw new Error;return this.each(zhe(this._id,e))}function Hhe(e){typeof e!=\"function\"&&(e=Lx(e));for(var t=this._groups,r=t.length,o=new Array(r),s=0;s<r;++s)for(var c=t[s],f=c.length,d=o[s]=[],h,p=0;p<f;++p)(h=c[p])&&e.call(h,h.__data__,p,c)&&d.push(h);return new Ei(o,this._parents,this._name,this._id)}function Bhe(e){if(e._id!==this._id)throw new Error;for(var t=this._groups,r=e._groups,o=t.length,s=r.length,c=Math.min(o,s),f=new Array(o),d=0;d<c;++d)for(var h=t[d],p=r[d],g=h.length,v=f[d]=new Array(g),b,w=0;w<g;++w)(b=h[w]||p[w])&&(v[w]=b);for(;d<o;++d)f[d]=t[d];return new Ei(f,this._parents,this._name,this._id)}function Whe(e){return(e+\"\").trim().split(/^|\\s+/).every(function(t){var r=t.indexOf(\".\");return r>=0&&(t=t.slice(0,r)),!t||t===\"start\"})}function qhe(e,t,r){var o,s,c=Whe(t)?Mp:ni;return function(){var f=c(this,e),d=f.on;d!==o&&(s=(o=d).copy()).on(t,r),f.on=s}}function jhe(e,t){var r=this._id;return arguments.length<2?Fr(this.node(),r).on.on(e):this.each(qhe(r,e,t))}function Uhe(e){return function(){var t=this.parentNode;for(var r in this.__transition)if(+r!==e)return;t&&t.removeChild(this)}}function Vhe(){return this.on(\"end.remove\",Uhe(this._id))}function Ghe(e){var t=this._name,r=this._id;typeof e!=\"function\"&&(e=Tp(e));for(var o=this._groups,s=o.length,c=new Array(s),f=0;f<s;++f)for(var d=o[f],h=d.length,p=c[f]=new Array(h),g,v,b=0;b<h;++b)(g=d[b])&&(v=e.call(g,g.__data__,b,d))&&(\"__data__\"in g&&(v.__data__=g.__data__),p[b]=v,hf(p[b],t,r,b,p,Fr(g,r)));return new Ei(c,this._parents,t,r)}function Khe(e){var t=this._name,r=this._id;typeof e!=\"function\"&&(e=Ax(e));for(var o=this._groups,s=o.length,c=[],f=[],d=0;d<s;++d)for(var h=o[d],p=h.length,g,v=0;v<p;++v)if(g=h[v]){for(var b=e.call(g,g.__data__,v,h),w,E=Fr(g,r),L=0,P=b.length;L<P;++L)(w=b[L])&&hf(w,t,r,L,b,E);c.push(b),f.push(g)}return new Ei(c,f,t,r)}var Xhe=ja.prototype.constructor;function Yhe(){return new Xhe(this._groups,this._parents)}function Zhe(e,t){var r,o,s;return function(){var c=el(this,e),f=(this.style.removeProperty(e),el(this,e));return c===f?null:c===r&&f===o?s:s=t(r=c,o=f)}}function Zx(e){return function(){this.style.removeProperty(e)}}function Jhe(e,t,r){var o,s=r+\"\",c;return function(){var f=el(this,e);return f===s?null:f===o?c:c=t(o=f,r)}}function Qhe(e,t,r){var o,s,c;return function(){var f=el(this,e),d=r(this),h=d+\"\";return d==null&&(h=d=(this.style.removeProperty(e),el(this,e))),f===h?null:f===o&&h===s?c:(s=h,c=t(o=f,d))}}function epe(e,t){var r,o,s,c=\"style.\"+t,f=\"end.\"+c,d;return function(){var h=ni(this,e),p=h.on,g=h.value[c]==null?d||(d=Zx(t)):void 0;(p!==r||s!==g)&&(o=(r=p).copy()).on(f,s=g),h.on=o}}function tpe(e,t,r){var o=(e+=\"\")==\"transform\"?the:Yx;return t==null?this.styleTween(e,Zhe(e,o)).on(\"end.style.\"+e,Zx(e)):typeof t==\"function\"?this.styleTween(e,Qhe(e,o,Np(this,\"style.\"+e,t))).each(epe(this._id,e)):this.styleTween(e,Jhe(e,o,t),r).on(\"end.style.\"+e,null)}function npe(e,t,r){return function(o){this.style.setProperty(e,t.call(this,o),r)}}function rpe(e,t,r){var o,s;function c(){var f=t.apply(this,arguments);return f!==s&&(o=(s=f)&&npe(e,f,r)),o}return c._value=t,c}function ipe(e,t,r){var o=\"style.\"+(e+=\"\");if(arguments.length<2)return(o=this.tween(o))&&o._value;if(t==null)return this.tween(o,null);if(typeof t!=\"function\")throw new Error;return this.tween(o,rpe(e,t,r??\"\"))}function ope(e){return function(){this.textContent=e}}function spe(e){return function(){var t=e(this);this.textContent=t??\"\"}}function lpe(e){return this.tween(\"text\",typeof e==\"function\"?spe(Np(this,\"text\",e)):ope(e==null?\"\":e+\"\"))}function ape(e){return function(t){this.textContent=e.call(this,t)}}function cpe(e){var t,r;function o(){var s=e.apply(this,arguments);return s!==r&&(t=(r=s)&&ape(s)),t}return o._value=e,o}function upe(e){var t=\"text\";if(arguments.length<1)return(t=this.tween(t))&&t._value;if(e==null)return this.tween(t,null);if(typeof e!=\"function\")throw new Error;return this.tween(t,cpe(e))}function fpe(){for(var e=this._name,t=this._id,r=Jx(),o=this._groups,s=o.length,c=0;c<s;++c)for(var f=o[c],d=f.length,h,p=0;p<d;++p)if(h=f[p]){var g=Fr(h,t);hf(h,e,r,p,f,{time:g.time+g.delay+g.duration,delay:0,duration:g.duration,ease:g.ease})}return new Ei(o,this._parents,e,r)}function dpe(){var e,t,r=this,o=r._id,s=r.size();return new Promise(function(c,f){var d={value:f},h={value:function(){--s===0&&c()}};r.each(function(){var p=ni(this,o),g=p.on;g!==e&&(t=(e=g).copy(),t._.cancel.push(d),t._.interrupt.push(d),t._.end.push(h)),p.on=t}),s===0&&c()})}var hpe=0;function Ei(e,t,r,o){this._groups=e,this._parents=t,this._name=r,this._id=o}function Jx(){return++hpe}var hi=ja.prototype;Ei.prototype={constructor:Ei,select:Ghe,selectAll:Khe,selectChild:hi.selectChild,selectChildren:hi.selectChildren,filter:Hhe,merge:Bhe,selection:Yhe,transition:fpe,call:hi.call,nodes:hi.nodes,node:hi.node,size:hi.size,empty:hi.empty,each:hi.each,on:jhe,attr:_he,attrTween:Lhe,style:tpe,styleTween:ipe,text:lpe,textTween:upe,remove:Vhe,tween:vhe,delay:Ohe,duration:$he,ease:Dhe,easeVarying:Fhe,end:dpe,[Symbol.iterator]:hi[Symbol.iterator]};function ppe(e){return((e*=2)<=1?e*e*e:(e-=2)*e*e+2)/2}var gpe={time:null,delay:0,duration:250,ease:ppe};function mpe(e,t){for(var r;!(r=e.__transition)||!(r=r[t]);)if(!(e=e.parentNode))throw new Error(`transition ${t} not found`);return r}function vpe(e){var t,r;e instanceof Ei?(t=e._id,e=e._name):(t=Jx(),(r=gpe).time=Ap(),e=e==null?null:e+\"\");for(var o=this._groups,s=o.length,c=0;c<s;++c)for(var f=o[c],d=f.length,h,p=0;p<d;++p)(h=f[p])&&hf(h,e,t,p,f,r||mpe(h,t));return new Ei(o,this._parents,e,t)}ja.prototype.interrupt=phe;ja.prototype.transition=vpe;const Hc=e=>()=>e;function ype(e,{sourceEvent:t,target:r,transform:o,dispatch:s}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},transform:{value:o,enumerable:!0,configurable:!0},_:{value:s}})}function xi(e,t,r){this.k=e,this.x=t,this.y=r}xi.prototype={constructor:xi,scale:function(e){return e===1?this:new xi(this.k*e,this.x,this.y)},translate:function(e,t){return e===0&t===0?this:new xi(this.k,this.x+this.k*e,this.y+this.k*t)},apply:function(e){return[e[0]*this.k+this.x,e[1]*this.k+this.y]},applyX:function(e){return e*this.k+this.x},applyY:function(e){return e*this.k+this.y},invert:function(e){return[(e[0]-this.x)/this.k,(e[1]-this.y)/this.k]},invertX:function(e){return(e-this.x)/this.k},invertY:function(e){return(e-this.y)/this.k},rescaleX:function(e){return e.copy().domain(e.range().map(this.invertX,this).map(e.invert,e))},rescaleY:function(e){return e.copy().domain(e.range().map(this.invertY,this).map(e.invert,e))},toString:function(){return\"translate(\"+this.x+\",\"+this.y+\") scale(\"+this.k+\")\"}};var Op=new xi(1,0,0);xi.prototype;function Dd(e){e.stopImmediatePropagation()}function ql(e){e.preventDefault(),e.stopImmediatePropagation()}function bpe(e){return(!e.ctrlKey||e.type===\"wheel\")&&!e.button}function wpe(){var e=this;return e instanceof SVGElement?(e=e.ownerSVGElement||e,e.hasAttribute(\"viewBox\")?(e=e.viewBox.baseVal,[[e.x,e.y],[e.x+e.width,e.y+e.height]]):[[0,0],[e.width.baseVal.value,e.height.baseVal.value]]):[[0,0],[e.clientWidth,e.clientHeight]]}function e0(){return this.__zoom||Op}function xpe(e){return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*(e.ctrlKey?10:1)}function kpe(){return navigator.maxTouchPoints||\"ontouchstart\"in this}function Spe(e,t,r){var o=e.invertX(t[0][0])-r[0][0],s=e.invertX(t[1][0])-r[1][0],c=e.invertY(t[0][1])-r[0][1],f=e.invertY(t[1][1])-r[1][1];return e.translate(s>o?(o+s)/2:Math.min(0,o)||Math.max(0,s),f>c?(c+f)/2:Math.min(0,c)||Math.max(0,f))}function _pe(){var e=bpe,t=wpe,r=Spe,o=xpe,s=kpe,c=[0,1/0],f=[[-1/0,-1/0],[1/0,1/0]],d=250,h=she,p=Ua(\"start\",\"zoom\",\"end\"),g,v,b,w=500,E=150,L=0,P=10;function M(C){C.property(\"__zoom\",e0).on(\"wheel.zoom\",ee,{passive:!1}).on(\"mousedown.zoom\",Z).on(\"dblclick.zoom\",G).filter(s).on(\"touchstart.zoom\",j).on(\"touchmove.zoom\",N).on(\"touchend.zoom touchcancel.zoom\",O).style(\"-webkit-tap-highlight-color\",\"rgba(0,0,0,0)\")}M.transform=function(C,k,z,B){var ce=C.selection?C.selection():C;ce.property(\"__zoom\",e0),C!==ce?$(C,k,z,B):ce.interrupt().each(function(){W(this,arguments).event(B).start().zoom(null,typeof k==\"function\"?k.apply(this,arguments):k).end()})},M.scaleBy=function(C,k,z,B){M.scaleTo(C,function(){var ce=this.__zoom.k,be=typeof k==\"function\"?k.apply(this,arguments):k;return ce*be},z,B)},M.scaleTo=function(C,k,z,B){M.transform(C,function(){var ce=t.apply(this,arguments),be=this.__zoom,Se=z==null?_(ce):typeof z==\"function\"?z.apply(this,arguments):z,Be=be.invert(Se),Ae=typeof k==\"function\"?k.apply(this,arguments):k;return r(I(R(be,Ae),Se,Be),ce,f)},z,B)},M.translateBy=function(C,k,z,B){M.transform(C,function(){return r(this.__zoom.translate(typeof k==\"function\"?k.apply(this,arguments):k,typeof z==\"function\"?z.apply(this,arguments):z),t.apply(this,arguments),f)},null,B)},M.translateTo=function(C,k,z,B,ce){M.transform(C,function(){var be=t.apply(this,arguments),Se=this.__zoom,Be=B==null?_(be):typeof B==\"function\"?B.apply(this,arguments):B;return r(Op.translate(Be[0],Be[1]).scale(Se.k).translate(typeof k==\"function\"?-k.apply(this,arguments):-k,typeof z==\"function\"?-z.apply(this,arguments):-z),be,f)},B,ce)};function R(C,k){return k=Math.max(c[0],Math.min(c[1],k)),k===C.k?C:new xi(k,C.x,C.y)}function I(C,k,z){var B=k[0]-z[0]*C.k,ce=k[1]-z[1]*C.k;return B===C.x&&ce===C.y?C:new xi(C.k,B,ce)}function _(C){return[(+C[0][0]+ +C[1][0])/2,(+C[0][1]+ +C[1][1])/2]}function $(C,k,z,B){C.on(\"start.zoom\",function(){W(this,arguments).event(B).start()}).on(\"interrupt.zoom end.zoom\",function(){W(this,arguments).event(B).end()}).tween(\"zoom\",function(){var ce=this,be=arguments,Se=W(ce,be).event(B),Be=t.apply(ce,be),Ae=z==null?_(Be):typeof z==\"function\"?z.apply(ce,be):z,Ke=Math.max(Be[1][0]-Be[0][0],Be[1][1]-Be[0][1]),je=ce.__zoom,Fe=typeof k==\"function\"?k.apply(ce,be):k,Pe=h(je.invert(Ae).concat(Ke/je.k),Fe.invert(Ae).concat(Ke/Fe.k));return function(F){if(F===1)F=Fe;else{var Y=Pe(F),re=Ke/Y[2];F=new xi(re,Ae[0]-Y[0]*re,Ae[1]-Y[1]*re)}Se.zoom(null,F)}})}function W(C,k,z){return!z&&C.__zooming||new ne(C,k)}function ne(C,k){this.that=C,this.args=k,this.active=0,this.sourceEvent=null,this.extent=t.apply(C,k),this.taps=0}ne.prototype={event:function(C){return C&&(this.sourceEvent=C),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit(\"start\")),this},zoom:function(C,k){return this.mouse&&C!==\"mouse\"&&(this.mouse[1]=k.invert(this.mouse[0])),this.touch0&&C!==\"touch\"&&(this.touch0[1]=k.invert(this.touch0[0])),this.touch1&&C!==\"touch\"&&(this.touch1[1]=k.invert(this.touch1[0])),this.that.__zoom=k,this.emit(\"zoom\"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit(\"end\")),this},emit:function(C){var k=Kn(this.that).datum();p.call(C,this.that,new ype(C,{sourceEvent:this.sourceEvent,target:M,transform:this.that.__zoom,dispatch:p}),k)}};function ee(C,...k){if(!e.apply(this,arguments))return;var z=W(this,k).event(C),B=this.__zoom,ce=Math.max(c[0],Math.min(c[1],B.k*Math.pow(2,o.apply(this,arguments)))),be=vi(C);if(z.wheel)(z.mouse[0][0]!==be[0]||z.mouse[0][1]!==be[1])&&(z.mouse[1]=B.invert(z.mouse[0]=be)),clearTimeout(z.wheel);else{if(B.k===ce)return;z.mouse=[be,B.invert(be)],eu(this),z.start()}ql(C),z.wheel=setTimeout(Se,E),z.zoom(\"mouse\",r(I(R(B,ce),z.mouse[0],z.mouse[1]),z.extent,f));function Se(){z.wheel=null,z.end()}}function Z(C,...k){if(b||!e.apply(this,arguments))return;var z=C.currentTarget,B=W(this,k,!0).event(C),ce=Kn(C.view).on(\"mousemove.zoom\",Ae,!0).on(\"mouseup.zoom\",Ke,!0),be=vi(C,z),Se=C.clientX,Be=C.clientY;Fx(C.view),Dd(C),B.mouse=[be,this.__zoom.invert(be)],eu(this),B.start();function Ae(je){if(ql(je),!B.moved){var Fe=je.clientX-Se,Pe=je.clientY-Be;B.moved=Fe*Fe+Pe*Pe>L}B.event(je).zoom(\"mouse\",r(I(B.that.__zoom,B.mouse[0]=vi(je,z),B.mouse[1]),B.extent,f))}function Ke(je){ce.on(\"mousemove.zoom mouseup.zoom\",null),Hx(je.view,B.moved),ql(je),B.event(je).end()}}function G(C,...k){if(e.apply(this,arguments)){var z=this.__zoom,B=vi(C.changedTouches?C.changedTouches[0]:C,this),ce=z.invert(B),be=z.k*(C.shiftKey?.5:2),Se=r(I(R(z,be),B,ce),t.apply(this,k),f);ql(C),d>0?Kn(this).transition().duration(d).call($,Se,B,C):Kn(this).call(M.transform,Se,B,C)}}function j(C,...k){if(e.apply(this,arguments)){var z=C.touches,B=z.length,ce=W(this,k,C.changedTouches.length===B).event(C),be,Se,Be,Ae;for(Dd(C),Se=0;Se<B;++Se)Be=z[Se],Ae=vi(Be,this),Ae=[Ae,this.__zoom.invert(Ae),Be.identifier],ce.touch0?!ce.touch1&&ce.touch0[2]!==Ae[2]&&(ce.touch1=Ae,ce.taps=0):(ce.touch0=Ae,be=!0,ce.taps=1+!!g);g&&(g=clearTimeout(g)),be&&(ce.taps<2&&(v=Ae[0],g=setTimeout(function(){g=null},w)),eu(this),ce.start())}}function N(C,...k){if(this.__zooming){var z=W(this,k).event(C),B=C.changedTouches,ce=B.length,be,Se,Be,Ae;for(ql(C),be=0;be<ce;++be)Se=B[be],Be=vi(Se,this),z.touch0&&z.touch0[2]===Se.identifier?z.touch0[0]=Be:z.touch1&&z.touch1[2]===Se.identifier&&(z.touch1[0]=Be);if(Se=z.that.__zoom,z.touch1){var Ke=z.touch0[0],je=z.touch0[1],Fe=z.touch1[0],Pe=z.touch1[1],F=(F=Fe[0]-Ke[0])*F+(F=Fe[1]-Ke[1])*F,Y=(Y=Pe[0]-je[0])*Y+(Y=Pe[1]-je[1])*Y;Se=R(Se,Math.sqrt(F/Y)),Be=[(Ke[0]+Fe[0])/2,(Ke[1]+Fe[1])/2],Ae=[(je[0]+Pe[0])/2,(je[1]+Pe[1])/2]}else if(z.touch0)Be=z.touch0[0],Ae=z.touch0[1];else return;z.zoom(\"touch\",r(I(Se,Be,Ae),z.extent,f))}}function O(C,...k){if(this.__zooming){var z=W(this,k).event(C),B=C.changedTouches,ce=B.length,be,Se;for(Dd(C),b&&clearTimeout(b),b=setTimeout(function(){b=null},w),be=0;be<ce;++be)Se=B[be],z.touch0&&z.touch0[2]===Se.identifier?delete z.touch0:z.touch1&&z.touch1[2]===Se.identifier&&delete z.touch1;if(z.touch1&&!z.touch0&&(z.touch0=z.touch1,delete z.touch1),z.touch0)z.touch0[1]=this.__zoom.invert(z.touch0[0]);else if(z.end(),z.taps===2&&(Se=vi(Se,this),Math.hypot(v[0]-Se[0],v[1]-Se[1])<P)){var Be=Kn(this).on(\"dblclick.zoom\");Be&&Be.apply(this,arguments)}}}return M.wheelDelta=function(C){return arguments.length?(o=typeof C==\"function\"?C:Hc(+C),M):o},M.filter=function(C){return arguments.length?(e=typeof C==\"function\"?C:Hc(!!C),M):e},M.touchable=function(C){return arguments.length?(s=typeof C==\"function\"?C:Hc(!!C),M):s},M.extent=function(C){return arguments.length?(t=typeof C==\"function\"?C:Hc([[+C[0][0],+C[0][1]],[+C[1][0],+C[1][1]]]),M):t},M.scaleExtent=function(C){return arguments.length?(c[0]=+C[0],c[1]=+C[1],M):[c[0],c[1]]},M.translateExtent=function(C){return arguments.length?(f[0][0]=+C[0][0],f[1][0]=+C[1][0],f[0][1]=+C[0][1],f[1][1]=+C[1][1],M):[[f[0][0],f[0][1]],[f[1][0],f[1][1]]]},M.constrain=function(C){return arguments.length?(r=C,M):r},M.duration=function(C){return arguments.length?(d=+C,M):d},M.interpolate=function(C){return arguments.length?(h=C,M):h},M.on=function(){var C=p.on.apply(p,arguments);return C===p?M:C},M.clickDistance=function(C){return arguments.length?(L=(C=+C)*C,M):Math.sqrt(L)},M.tapDistance=function(C){return arguments.length?(P=+C,M):P},M}function Tpe(e){const t=+this._x.call(null,e),r=+this._y.call(null,e);return Qx(this.cover(t,r),t,r,e)}function Qx(e,t,r,o){if(isNaN(t)||isNaN(r))return e;var s,c=e._root,f={data:o},d=e._x0,h=e._y0,p=e._x1,g=e._y1,v,b,w,E,L,P,M,R;if(!c)return e._root=f,e;for(;c.length;)if((L=t>=(v=(d+p)/2))?d=v:p=v,(P=r>=(b=(h+g)/2))?h=b:g=b,s=c,!(c=c[M=P<<1|L]))return s[M]=f,e;if(w=+e._x.call(null,c.data),E=+e._y.call(null,c.data),t===w&&r===E)return f.next=c,s?s[M]=f:e._root=f,e;do s=s?s[M]=new Array(4):e._root=new Array(4),(L=t>=(v=(d+p)/2))?d=v:p=v,(P=r>=(b=(h+g)/2))?h=b:g=b;while((M=P<<1|L)===(R=(E>=b)<<1|w>=v));return s[R]=c,s[M]=f,e}function Cpe(e){var t,r,o=e.length,s,c,f=new Array(o),d=new Array(o),h=1/0,p=1/0,g=-1/0,v=-1/0;for(r=0;r<o;++r)isNaN(s=+this._x.call(null,t=e[r]))||isNaN(c=+this._y.call(null,t))||(f[r]=s,d[r]=c,s<h&&(h=s),s>g&&(g=s),c<p&&(p=c),c>v&&(v=c));if(h>g||p>v)return this;for(this.cover(h,p).cover(g,v),r=0;r<o;++r)Qx(this,f[r],d[r],e[r]);return this}function Epe(e,t){if(isNaN(e=+e)||isNaN(t=+t))return this;var r=this._x0,o=this._y0,s=this._x1,c=this._y1;if(isNaN(r))s=(r=Math.floor(e))+1,c=(o=Math.floor(t))+1;else{for(var f=s-r||1,d=this._root,h,p;r>e||e>=s||o>t||t>=c;)switch(p=(t<o)<<1|e<r,h=new Array(4),h[p]=d,d=h,f*=2,p){case 0:s=r+f,c=o+f;break;case 1:r=s-f,c=o+f;break;case 2:s=r+f,o=c-f;break;case 3:r=s-f,o=c-f;break}this._root&&this._root.length&&(this._root=d)}return this._x0=r,this._y0=o,this._x1=s,this._y1=c,this}function Ape(){var e=[];return this.visit(function(t){if(!t.length)do e.push(t.data);while(t=t.next)}),e}function Lpe(e){return arguments.length?this.cover(+e[0][0],+e[0][1]).cover(+e[1][0],+e[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]}function Rn(e,t,r,o,s){this.node=e,this.x0=t,this.y0=r,this.x1=o,this.y1=s}function Mpe(e,t,r){var o,s=this._x0,c=this._y0,f,d,h,p,g=this._x1,v=this._y1,b=[],w=this._root,E,L;for(w&&b.push(new Rn(w,s,c,g,v)),r==null?r=1/0:(s=e-r,c=t-r,g=e+r,v=t+r,r*=r);E=b.pop();)if(!(!(w=E.node)||(f=E.x0)>g||(d=E.y0)>v||(h=E.x1)<s||(p=E.y1)<c))if(w.length){var P=(f+h)/2,M=(d+p)/2;b.push(new Rn(w[3],P,M,h,p),new Rn(w[2],f,M,P,p),new Rn(w[1],P,d,h,M),new Rn(w[0],f,d,P,M)),(L=(t>=M)<<1|e>=P)&&(E=b[b.length-1],b[b.length-1]=b[b.length-1-L],b[b.length-1-L]=E)}else{var R=e-+this._x.call(null,w.data),I=t-+this._y.call(null,w.data),_=R*R+I*I;if(_<r){var $=Math.sqrt(r=_);s=e-$,c=t-$,g=e+$,v=t+$,o=w.data}}return o}function Npe(e){if(isNaN(g=+this._x.call(null,e))||isNaN(v=+this._y.call(null,e)))return this;var t,r=this._root,o,s,c,f=this._x0,d=this._y0,h=this._x1,p=this._y1,g,v,b,w,E,L,P,M;if(!r)return this;if(r.length)for(;;){if((E=g>=(b=(f+h)/2))?f=b:h=b,(L=v>=(w=(d+p)/2))?d=w:p=w,t=r,!(r=r[P=L<<1|E]))return this;if(!r.length)break;(t[P+1&3]||t[P+2&3]||t[P+3&3])&&(o=t,M=P)}for(;r.data!==e;)if(s=r,!(r=r.next))return this;return(c=r.next)&&delete r.next,s?(c?s.next=c:delete s.next,this):t?(c?t[P]=c:delete t[P],(r=t[0]||t[1]||t[2]||t[3])&&r===(t[3]||t[2]||t[1]||t[0])&&!r.length&&(o?o[M]=r:this._root=r),this):(this._root=c,this)}function Ope(e){for(var t=0,r=e.length;t<r;++t)this.remove(e[t]);return this}function Ppe(){return this._root}function Rpe(){var e=0;return this.visit(function(t){if(!t.length)do++e;while(t=t.next)}),e}function $pe(e){var t=[],r,o=this._root,s,c,f,d,h;for(o&&t.push(new Rn(o,this._x0,this._y0,this._x1,this._y1));r=t.pop();)if(!e(o=r.node,c=r.x0,f=r.y0,d=r.x1,h=r.y1)&&o.length){var p=(c+d)/2,g=(f+h)/2;(s=o[3])&&t.push(new Rn(s,p,g,d,h)),(s=o[2])&&t.push(new Rn(s,c,g,p,h)),(s=o[1])&&t.push(new Rn(s,p,f,d,g)),(s=o[0])&&t.push(new Rn(s,c,f,p,g))}return this}function Ipe(e){var t=[],r=[],o;for(this._root&&t.push(new Rn(this._root,this._x0,this._y0,this._x1,this._y1));o=t.pop();){var s=o.node;if(s.length){var c,f=o.x0,d=o.y0,h=o.x1,p=o.y1,g=(f+h)/2,v=(d+p)/2;(c=s[0])&&t.push(new Rn(c,f,d,g,v)),(c=s[1])&&t.push(new Rn(c,g,d,h,v)),(c=s[2])&&t.push(new Rn(c,f,v,g,p)),(c=s[3])&&t.push(new Rn(c,g,v,h,p))}r.push(o)}for(;o=r.pop();)e(o.node,o.x0,o.y0,o.x1,o.y1);return this}function Dpe(e){return e[0]}function zpe(e){return arguments.length?(this._x=e,this):this._x}function Fpe(e){return e[1]}function Hpe(e){return arguments.length?(this._y=e,this):this._y}function Pp(e,t,r){var o=new Rp(t??Dpe,r??Fpe,NaN,NaN,NaN,NaN);return e==null?o:o.addAll(e)}function Rp(e,t,r,o,s,c){this._x=e,this._y=t,this._x0=r,this._y0=o,this._x1=s,this._y1=c,this._root=void 0}function t0(e){for(var t={data:e.data},r=t;e=e.next;)r=r.next={data:e.data};return t}var zn=Pp.prototype=Rp.prototype;zn.copy=function(){var e=new Rp(this._x,this._y,this._x0,this._y0,this._x1,this._y1),t=this._root,r,o;if(!t)return e;if(!t.length)return e._root=t0(t),e;for(r=[{source:t,target:e._root=new Array(4)}];t=r.pop();)for(var s=0;s<4;++s)(o=t.source[s])&&(o.length?r.push({source:o,target:t.target[s]=new Array(4)}):t.target[s]=t0(o));return e};zn.add=Tpe;zn.addAll=Cpe;zn.cover=Epe;zn.data=Ape;zn.extent=Lpe;zn.find=Mpe;zn.remove=Npe;zn.removeAll=Ope;zn.root=Ppe;zn.size=Rpe;zn.visit=$pe;zn.visitAfter=Ipe;zn.x=zpe;zn.y=Hpe;function Dn(e){return function(){return e}}function io(e){return(e()-.5)*1e-6}function Bpe(e){return e.x+e.vx}function Wpe(e){return e.y+e.vy}function qpe(e){var t,r,o,s=1,c=1;typeof e!=\"function\"&&(e=Dn(e==null?1:+e));function f(){for(var p,g=t.length,v,b,w,E,L,P,M=0;M<c;++M)for(v=Pp(t,Bpe,Wpe).visitAfter(d),p=0;p<g;++p)b=t[p],L=r[b.index],P=L*L,w=b.x+b.vx,E=b.y+b.vy,v.visit(R);function R(I,_,$,W,ne){var ee=I.data,Z=I.r,G=L+Z;if(ee){if(ee.index>b.index){var j=w-ee.x-ee.vx,N=E-ee.y-ee.vy,O=j*j+N*N;O<G*G&&(j===0&&(j=io(o),O+=j*j),N===0&&(N=io(o),O+=N*N),O=(G-(O=Math.sqrt(O)))/O*s,b.vx+=(j*=O)*(G=(Z*=Z)/(P+Z)),b.vy+=(N*=O)*G,ee.vx-=j*(G=1-G),ee.vy-=N*G)}return}return _>w+G||W<w-G||$>E+G||ne<E-G}}function d(p){if(p.data)return p.r=r[p.data.index];for(var g=p.r=0;g<4;++g)p[g]&&p[g].r>p.r&&(p.r=p[g].r)}function h(){if(t){var p,g=t.length,v;for(r=new Array(g),p=0;p<g;++p)v=t[p],r[v.index]=+e(v,p,t)}}return f.initialize=function(p,g){t=p,o=g,h()},f.iterations=function(p){return arguments.length?(c=+p,f):c},f.strength=function(p){return arguments.length?(s=+p,f):s},f.radius=function(p){return arguments.length?(e=typeof p==\"function\"?p:Dn(+p),h(),f):e},f}function jpe(e){return e.index}function n0(e,t){var r=e.get(t);if(!r)throw new Error(\"node not found: \"+t);return r}function Upe(e){var t=jpe,r=v,o,s=Dn(30),c,f,d,h,p,g=1;e==null&&(e=[]);function v(P){return 1/Math.min(d[P.source.index],d[P.target.index])}function b(P){for(var M=0,R=e.length;M<g;++M)for(var I=0,_,$,W,ne,ee,Z,G;I<R;++I)_=e[I],$=_.source,W=_.target,ne=W.x+W.vx-$.x-$.vx||io(p),ee=W.y+W.vy-$.y-$.vy||io(p),Z=Math.sqrt(ne*ne+ee*ee),Z=(Z-c[I])/Z*P*o[I],ne*=Z,ee*=Z,W.vx-=ne*(G=h[I]),W.vy-=ee*G,$.vx+=ne*(G=1-G),$.vy+=ee*G}function w(){if(f){var P,M=f.length,R=e.length,I=new Map(f.map(($,W)=>[t($,W,f),$])),_;for(P=0,d=new Array(M);P<R;++P)_=e[P],_.index=P,typeof _.source!=\"object\"&&(_.source=n0(I,_.source)),typeof _.target!=\"object\"&&(_.target=n0(I,_.target)),d[_.source.index]=(d[_.source.index]||0)+1,d[_.target.index]=(d[_.target.index]||0)+1;for(P=0,h=new Array(R);P<R;++P)_=e[P],h[P]=d[_.source.index]/(d[_.source.index]+d[_.target.index]);o=new Array(R),E(),c=new Array(R),L()}}function E(){if(f)for(var P=0,M=e.length;P<M;++P)o[P]=+r(e[P],P,e)}function L(){if(f)for(var P=0,M=e.length;P<M;++P)c[P]=+s(e[P],P,e)}return b.initialize=function(P,M){f=P,p=M,w()},b.links=function(P){return arguments.length?(e=P,w(),b):e},b.id=function(P){return arguments.length?(t=P,b):t},b.iterations=function(P){return arguments.length?(g=+P,b):g},b.strength=function(P){return arguments.length?(r=typeof P==\"function\"?P:Dn(+P),E(),b):r},b.distance=function(P){return arguments.length?(s=typeof P==\"function\"?P:Dn(+P),L(),b):s},b}const Vpe=1664525,Gpe=1013904223,r0=4294967296;function Kpe(){let e=1;return()=>(e=(Vpe*e+Gpe)%r0)/r0}function Xpe(e){return e.x}function Ype(e){return e.y}var Zpe=10,Jpe=Math.PI*(3-Math.sqrt(5));function Qpe(e){var t,r=1,o=.001,s=1-Math.pow(o,1/300),c=0,f=.6,d=new Map,h=Lp(v),p=Ua(\"tick\",\"end\"),g=Kpe();e==null&&(e=[]);function v(){b(),p.call(\"tick\",t),r<o&&(h.stop(),p.call(\"end\",t))}function b(L){var P,M=e.length,R;L===void 0&&(L=1);for(var I=0;I<L;++I)for(r+=(c-r)*s,d.forEach(function(_){_(r)}),P=0;P<M;++P)R=e[P],R.fx==null?R.x+=R.vx*=f:(R.x=R.fx,R.vx=0),R.fy==null?R.y+=R.vy*=f:(R.y=R.fy,R.vy=0);return t}function w(){for(var L=0,P=e.length,M;L<P;++L){if(M=e[L],M.index=L,M.fx!=null&&(M.x=M.fx),M.fy!=null&&(M.y=M.fy),isNaN(M.x)||isNaN(M.y)){var R=Zpe*Math.sqrt(.5+L),I=L*Jpe;M.x=R*Math.cos(I),M.y=R*Math.sin(I)}(isNaN(M.vx)||isNaN(M.vy))&&(M.vx=M.vy=0)}}function E(L){return L.initialize&&L.initialize(e,g),L}return w(),t={tick:b,restart:function(){return h.restart(v),t},stop:function(){return h.stop(),t},nodes:function(L){return arguments.length?(e=L,w(),d.forEach(E),t):e},alpha:function(L){return arguments.length?(r=+L,t):r},alphaMin:function(L){return arguments.length?(o=+L,t):o},alphaDecay:function(L){return arguments.length?(s=+L,t):+s},alphaTarget:function(L){return arguments.length?(c=+L,t):c},velocityDecay:function(L){return arguments.length?(f=1-L,t):1-f},randomSource:function(L){return arguments.length?(g=L,d.forEach(E),t):g},force:function(L,P){return arguments.length>1?(P==null?d.delete(L):d.set(L,E(P)),t):d.get(L)},find:function(L,P,M){var R=0,I=e.length,_,$,W,ne,ee;for(M==null?M=1/0:M*=M,R=0;R<I;++R)ne=e[R],_=L-ne.x,$=P-ne.y,W=_*_+$*$,W<M&&(ee=ne,M=W);return ee},on:function(L,P){return arguments.length>1?(p.on(L,P),t):p.on(L)}}}function ege(){var e,t,r,o,s=Dn(-30),c,f=1,d=1/0,h=.81;function p(w){var E,L=e.length,P=Pp(e,Xpe,Ype).visitAfter(v);for(o=w,E=0;E<L;++E)t=e[E],P.visit(b)}function g(){if(e){var w,E=e.length,L;for(c=new Array(E),w=0;w<E;++w)L=e[w],c[L.index]=+s(L,w,e)}}function v(w){var E=0,L,P,M=0,R,I,_;if(w.length){for(R=I=_=0;_<4;++_)(L=w[_])&&(P=Math.abs(L.value))&&(E+=L.value,M+=P,R+=P*L.x,I+=P*L.y);w.x=R/M,w.y=I/M}else{L=w,L.x=L.data.x,L.y=L.data.y;do E+=c[L.data.index];while(L=L.next)}w.value=E}function b(w,E,L,P){if(!w.value)return!0;var M=w.x-t.x,R=w.y-t.y,I=P-E,_=M*M+R*R;if(I*I/h<_)return _<d&&(M===0&&(M=io(r),_+=M*M),R===0&&(R=io(r),_+=R*R),_<f&&(_=Math.sqrt(f*_)),t.vx+=M*w.value*o/_,t.vy+=R*w.value*o/_),!0;if(w.length||_>=d)return;(w.data!==t||w.next)&&(M===0&&(M=io(r),_+=M*M),R===0&&(R=io(r),_+=R*R),_<f&&(_=Math.sqrt(f*_)));do w.data!==t&&(I=c[w.data.index]*o/_,t.vx+=M*I,t.vy+=R*I);while(w=w.next)}return p.initialize=function(w,E){e=w,r=E,g()},p.strength=function(w){return arguments.length?(s=typeof w==\"function\"?w:Dn(+w),g(),p):s},p.distanceMin=function(w){return arguments.length?(f=w*w,p):Math.sqrt(f)},p.distanceMax=function(w){return arguments.length?(d=w*w,p):Math.sqrt(d)},p.theta=function(w){return arguments.length?(h=w*w,p):Math.sqrt(h)},p}function tge(e){var t=Dn(.1),r,o,s;typeof e!=\"function\"&&(e=Dn(e==null?0:+e));function c(d){for(var h=0,p=r.length,g;h<p;++h)g=r[h],g.vx+=(s[h]-g.x)*o[h]*d}function f(){if(r){var d,h=r.length;for(o=new Array(h),s=new Array(h),d=0;d<h;++d)o[d]=isNaN(s[d]=+e(r[d],d,r))?0:+t(r[d],d,r)}}return c.initialize=function(d){r=d,f()},c.strength=function(d){return arguments.length?(t=typeof d==\"function\"?d:Dn(+d),f(),c):t},c.x=function(d){return arguments.length?(e=typeof d==\"function\"?d:Dn(+d),f(),c):e},c}function nge(e){var t=Dn(.1),r,o,s;typeof e!=\"function\"&&(e=Dn(e==null?0:+e));function c(d){for(var h=0,p=r.length,g;h<p;++h)g=r[h],g.vy+=(s[h]-g.y)*o[h]*d}function f(){if(r){var d,h=r.length;for(o=new Array(h),s=new Array(h),d=0;d<h;++d)o[d]=isNaN(s[d]=+e(r[d],d,r))?0:+t(r[d],d,r)}}return c.initialize=function(d){r=d,f()},c.strength=function(d){return arguments.length?(t=typeof d==\"function\"?d:Dn(+d),f(),c):t},c.y=function(d){return arguments.length?(e=typeof d==\"function\"?d:Dn(+d),f(),c):e},c}function rge(){return{drag:{end:0,start:.1},filter:{link:1,type:.1,unlinked:{include:.1,exclude:.1}},focus:{acquire:()=>.1,release:()=>.1},initialize:1,labels:{links:{hide:0,show:0},nodes:{hide:0,show:0}},resize:.5}}function i0(e){if(typeof e==\"object\"&&e!==null){if(typeof Object.getPrototypeOf==\"function\"){const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}return Object.prototype.toString.call(e)===\"[object Object]\"}return!1}function oo(...e){return e.reduce((t,r)=>{if(Array.isArray(r))throw new TypeError(\"Arguments provided to deepmerge must be objects, not arrays.\");return Object.keys(r).forEach(o=>{[\"__proto__\",\"constructor\",\"prototype\"].includes(o)||(Array.isArray(t[o])&&Array.isArray(r[o])?t[o]=oo.options.mergeArrays?Array.from(new Set(t[o].concat(r[o]))):r[o]:i0(t[o])&&i0(r[o])?t[o]=oo(t[o],r[o]):t[o]=r[o])}),t},{})}const e1={mergeArrays:!0};oo.options=e1;oo.withOptions=(e,...t)=>{oo.options={mergeArrays:!0,...e};const r=oo(...t);return oo.options=e1,r};var ige=oo;function oge(){return{centering:{enabled:!0,strength:.1},charge:{enabled:!0,strength:-1},collision:{enabled:!0,strength:1,radiusMultiplier:2},link:{enabled:!0,strength:1,length:128}}}function sge(){return{includeUnlinked:!0,linkFilter:()=>!0,nodeTypeFilter:void 0,showLinkLabels:!0,showNodeLabels:!0}}function t1(e){e.preventDefault(),e.stopPropagation()}function n1(e){return typeof e==\"number\"}function mo(e,t){return n1(e.nodeRadius)?e.nodeRadius:e.nodeRadius(t)}function lge(e){return`${e.source.id}-${e.target.id}`}function r1(e){return`link-arrow-${e}`.replace(/[()]/g,\"~\")}function age(e){return`url(#${r1(e.color)})`}function cge(e){return{size:e,padding:(t,r)=>mo(r,t)+2*e,ref:[e/2,e/2],path:[[0,0],[0,e],[e,e/2]],viewBox:[0,0,e,e].join(\",\")}}const i1={Arrow:e=>cge(e)},uge=(e,t,r)=>[t/2,r/2],fge=(e,t,r)=>[o0(0,t),o0(0,r)];function o0(e,t){return Math.random()*(t-e)+e}const Eh={Centered:uge,Randomized:fge};function dge(){return{autoResize:!1,callbacks:{},hooks:{},initial:sge(),nodeRadius:16,marker:i1.Arrow(4),modifiers:{},positionInitializer:Eh.Centered,simulation:{alphas:rge(),forces:oge()},zoom:{initial:1,min:.1,max:2}}}function hge(e={}){return ige.withOptions({mergeArrays:!1},dge(),e)}function pge({applyZoom:e,container:t,onDoubleClick:r,onPointerMoved:o,onPointerUp:s,offset:[c,f],scale:d,zoom:h}){const p=t.classed(\"graph\",!0).append(\"svg\").attr(\"height\",\"100%\").attr(\"width\",\"100%\").call(h).on(\"contextmenu\",g=>t1(g)).on(\"dblclick\",g=>r?.(g)).on(\"dblclick.zoom\",null).on(\"pointermove\",g=>o?.(g)).on(\"pointerup\",g=>s?.(g)).style(\"cursor\",\"grab\");return e&&p.call(h.transform,Op.translate(c,f).scale(d)),p.append(\"g\")}function gge({canvas:e,scale:t,xOffset:r,yOffset:o}){e?.attr(\"transform\",`translate(${r},${o})scale(${t})`)}function mge({config:e,onDragStart:t,onDragEnd:r}){const o=Rde().filter(s=>s.type===\"mousedown\"?s.button===0:s.type===\"touchstart\"?s.touches.length===1:!1).on(\"start\",(s,c)=>{s.active===0&&t(s,c),Kn(s.sourceEvent.target).classed(\"grabbed\",!0),c.fx=c.x,c.fy=c.y}).on(\"drag\",(s,c)=>{c.fx=s.x,c.fy=s.y}).on(\"end\",(s,c)=>{s.active===0&&r(s,c),Kn(s.sourceEvent.target).classed(\"grabbed\",!1),c.fx=void 0,c.fy=void 0});return e.modifiers.drag?.(o),o}function vge({graph:e,filter:t,focusedNode:r,includeUnlinked:o,linkFilter:s}){const c=e.links.filter(h=>t.includes(h.source.type)&&t.includes(h.target.type)&&s(h)),f=h=>c.find(p=>p.source.id===h.id||p.target.id===h.id)!==void 0,d=e.nodes.filter(h=>t.includes(h.type)&&(o||f(h)));return r===void 0||!t.includes(r.type)?{nodes:d,links:c}:yge({links:c},r)}function yge(e,t){const r=[...bge(e,t),...wge(e,t)],o=r.flatMap(s=>[s.source,s.target]);return{nodes:[...new Set([...o,t])],links:[...new Set(r)]}}function bge(e,t){return o1(e,t,(r,o)=>r.target.id===o.id)}function wge(e,t){return o1(e,t,(r,o)=>r.source.id===o.id)}function o1(e,t,r){const o=new Set(e.links),s=new Set([t]),c=[];for(;o.size>0;){const f=[...o].filter(d=>[...s].some(h=>r(d,h)));if(f.length===0)return c;f.forEach(d=>{s.add(d.source),s.add(d.target),c.push(d),o.delete(d)})}return c}function Ah(e){return e.x??0}function Lh(e){return e.y??0}function $p({source:e,target:t}){const r=new tl(Ah(e),Lh(e)),o=new tl(Ah(t),Lh(t)),s=o.subtract(r),c=s.length(),f=s.normalize();return{s:r,t:o,dist:c,norm:f,endNorm:f.multiply(-1)}}function s1({center:e,node:t}){const r=new tl(Ah(t),Lh(t));let o=e;return r.x===o.x&&r.y===o.y&&(o=o.add(new tl(0,1))),{n:r,c:o}}function l1({config:e,source:t,target:r}){const{s:o,t:s,norm:c}=$p({source:t,target:r});return{start:o.add(c.multiply(mo(e,t)-1)),end:s.subtract(c.multiply(e.marker.padding(r,e)))}}function xge(e){const{start:t,end:r}=l1(e);return`M${t.x},${t.y}\n          L${r.x},${r.y}`}function kge(e){const{start:t,end:r}=l1(e),o=r.subtract(t).multiply(.5),s=t.add(o);return`translate(${s.x-8},${s.y-4})`}function Sge({config:e,source:t,target:r}){const{s:o,t:s,dist:c,norm:f,endNorm:d}=$p({source:t,target:r}),h=10,p=f.rotateByDegrees(-h).multiply(mo(e,t)-1).add(o),g=d.rotateByDegrees(h).multiply(mo(e,r)).add(s).add(d.rotateByDegrees(h).multiply(2*e.marker.size)),v=1.2*c;return`M${p.x},${p.y}\n          A${v},${v},0,0,1,${g.x},${g.y}`}function _ge({center:e,config:t,node:r}){const{n:o,c:s}=s1({center:e,node:r}),c=mo(t,r),f=o.subtract(s),d=f.multiply(1/f.length()),h=40,p=d.rotateByDegrees(h).multiply(c-1).add(o),g=d.rotateByDegrees(-h).multiply(c).add(o).add(d.rotateByDegrees(-h).multiply(2*t.marker.size));return`M${p.x},${p.y}\n          A${c},${c},0,1,0,${g.x},${g.y}`}function Tge({config:e,source:t,target:r}){const{t:o,dist:s,endNorm:c}=$p({source:t,target:r}),f=c.rotateByDegrees(10).multiply(.5*s).add(o);return`translate(${f.x},${f.y})`}function Cge({center:e,config:t,node:r}){const{n:o,c:s}=s1({center:e,node:r}),c=o.subtract(s),f=c.multiply(1/c.length()).multiply(3*mo(t,r)+8).add(o);return`translate(${f.x},${f.y})`}const Vs={line:{labelTransform:kge,path:xge},arc:{labelTransform:Tge,path:Sge},reflexive:{labelTransform:Cge,path:_ge}};function Ege(e){return e.append(\"g\").classed(\"links\",!0).selectAll(\"path\")}function Age({config:e,graph:t,selection:r,showLabels:o}){const s=r?.data(t.links,c=>lge(c)).join(c=>{const f=c.append(\"g\"),d=f.append(\"path\").classed(\"link\",!0).style(\"marker-end\",p=>age(p)).style(\"stroke\",p=>p.color);e.modifiers.link?.(d);const h=f.append(\"text\").classed(\"link__label\",!0).style(\"fill\",p=>p.label?p.label.color:null).style(\"font-size\",p=>p.label?p.label.fontSize:null).text(p=>p.label?p.label.text:null);return e.modifiers.linkLabel?.(h),f});return s?.select(\".link__label\").attr(\"opacity\",c=>c.label&&o?1:0),s}function Lge(e){Mge(e),Nge(e)}function Mge({center:e,config:t,graph:r,selection:o}){o?.selectAll(\"path\").attr(\"d\",s=>s.source.x===void 0||s.source.y===void 0||s.target.x===void 0||s.target.y===void 0?\"\":s.source.id===s.target.id?Vs.reflexive.path({config:t,node:s.source,center:e}):a1(r,s.source,s.target)?Vs.arc.path({config:t,source:s.source,target:s.target}):Vs.line.path({config:t,source:s.source,target:s.target}))}function Nge({config:e,center:t,graph:r,selection:o}){o?.select(\".link__label\").attr(\"transform\",s=>s.source.x===void 0||s.source.y===void 0||s.target.x===void 0||s.target.y===void 0?\"translate(0, 0)\":s.source.id===s.target.id?Vs.reflexive.labelTransform({config:e,node:s.source,center:t}):a1(r,s.source,s.target)?Vs.arc.labelTransform({config:e,source:s.source,target:s.target}):Vs.line.labelTransform({config:e,source:s.source,target:s.target}))}function a1(e,t,r){return t.id!==r.id&&e.links.some(o=>o.target.id===t.id&&o.source.id===r.id)&&e.links.some(o=>o.target.id===r.id&&o.source.id===t.id)}function Oge(e){return e.append(\"defs\").selectAll(\"marker\")}function Pge({config:e,graph:t,selection:r}){return r?.data(Rge(t),o=>o).join(o=>{const s=o.append(\"marker\").attr(\"id\",c=>r1(c)).attr(\"markerHeight\",4*e.marker.size).attr(\"markerWidth\",4*e.marker.size).attr(\"markerUnits\",\"userSpaceOnUse\").attr(\"orient\",\"auto\").attr(\"refX\",e.marker.ref[0]).attr(\"refY\",e.marker.ref[1]).attr(\"viewBox\",e.marker.viewBox).style(\"fill\",c=>c);return s.append(\"path\").attr(\"d\",$ge(e.marker.path)),s})}function Rge(e){return[...new Set(e.links.map(t=>t.color))]}function $ge(e){const[t,...r]=e;if(!t)return\"M0,0\";const[o,s]=t;return r.reduce((c,[f,d])=>`${c}L${f},${d}`,`M${o},${s}`)}function Ige(e){return e.append(\"g\").classed(\"nodes\",!0).selectAll(\"circle\")}function Dge({config:e,drag:t,graph:r,onNodeContext:o,onNodeSelected:s,selection:c,showLabels:f}){const d=c?.data(r.nodes,h=>h.id).join(h=>{const p=h.append(\"g\");t!==void 0&&p.call(t);const g=p.append(\"circle\").classed(\"node\",!0).attr(\"r\",b=>mo(e,b)).on(\"contextmenu\",(b,w)=>{t1(b),o(w)}).on(\"pointerdown\",(b,w)=>Fge(b,w,s??o)).style(\"fill\",b=>b.color);e.modifiers.node?.(g);const v=p.append(\"text\").classed(\"node__label\",!0).attr(\"dy\",\"0.33em\").style(\"fill\",b=>b.label?b.label.color:null).style(\"font-size\",b=>b.label?b.label.fontSize:null).style(\"stroke\",\"none\").text(b=>b.label?b.label.text:null);return e.modifiers.nodeLabel?.(v),p});return d?.select(\".node\").classed(\"focused\",h=>h.isFocused),d?.select(\".node__label\").attr(\"opacity\",f?1:0),d}const zge=500;function Fge(e,t,r){if(e.button!==void 0&&e.button!==0)return;const o=t.lastInteractionTimestamp,s=Date.now();if(o===void 0||s-o>zge){t.lastInteractionTimestamp=s;return}t.lastInteractionTimestamp=void 0,r(t)}function Hge(e){e?.attr(\"transform\",t=>`translate(${t.x??0},${t.y??0})`)}function Bge({center:e,config:t,graph:r,onTick:o}){const s=Qpe(r.nodes),c=t.simulation.forces.centering;if(c&&c.enabled){const p=c.strength;s.force(\"x\",tge(()=>e().x).strength(p)).force(\"y\",nge(()=>e().y).strength(p))}const f=t.simulation.forces.charge;f&&f.enabled&&s.force(\"charge\",ege().strength(f.strength));const d=t.simulation.forces.collision;d&&d.enabled&&s.force(\"collision\",qpe().radius(p=>d.radiusMultiplier*mo(t,p)));const h=t.simulation.forces.link;return h&&h.enabled&&s.force(\"link\",Upe(r.links).id(p=>p.id).distance(t.simulation.forces.link.length).strength(h.strength)),s.on(\"tick\",()=>o()),t.modifiers.simulation?.(s),s}function Wge({canvasContainer:e,config:t,min:r,max:o,onZoom:s}){const c=_pe().scaleExtent([r,o]).filter(f=>f.button===0||f.touches?.length>=2).on(\"start\",()=>e().classed(\"grabbed\",!0)).on(\"zoom\",f=>s(f)).on(\"end\",()=>e().classed(\"grabbed\",!1));return t.modifiers.zoom?.(c),c}var qge=class{nodeTypes;_nodeTypeFilter;_includeUnlinked=!0;_linkFilter=()=>!0;_showLinkLabels=!0;_showNodeLabels=!0;filteredGraph;width=0;height=0;simulation;canvas;linkSelection;nodeSelection;markerSelection;zoom;drag;xOffset=0;yOffset=0;scale;focusedNode=void 0;resizeObserver;container;graph;config;constructor(e,t,r){if(this.container=e,this.graph=t,this.config=r,this.scale=r.zoom.initial,this.resetView(),this.graph.nodes.forEach(o=>{const[s,c]=r.positionInitializer(o,this.effectiveWidth,this.effectiveHeight);o.x=o.x??s,o.y=o.y??c}),this.nodeTypes=[...new Set(t.nodes.map(o=>o.type))],this._nodeTypeFilter=[...this.nodeTypes],r.initial){const{includeUnlinked:o,nodeTypeFilter:s,linkFilter:c,showLinkLabels:f,showNodeLabels:d}=r.initial;this._includeUnlinked=o??this._includeUnlinked,this._showLinkLabels=f??this._showLinkLabels,this._showNodeLabels=d??this._showNodeLabels,this._nodeTypeFilter=s??this._nodeTypeFilter,this._linkFilter=c??this._linkFilter}this.filterGraph(void 0),this.initGraph(),this.restart(r.simulation.alphas.initialize),r.autoResize&&(this.resizeObserver=new ResizeObserver(Vue(()=>this.resize())),this.resizeObserver.observe(this.container))}get nodeTypeFilter(){return this._nodeTypeFilter}get includeUnlinked(){return this._includeUnlinked}set includeUnlinked(e){this._includeUnlinked=e,this.filterGraph(this.focusedNode);const{include:t,exclude:r}=this.config.simulation.alphas.filter.unlinked,o=e?t:r;this.restart(o)}set linkFilter(e){this._linkFilter=e,this.filterGraph(this.focusedNode),this.restart(this.config.simulation.alphas.filter.link)}get linkFilter(){return this._linkFilter}get showNodeLabels(){return this._showNodeLabels}set showNodeLabels(e){this._showNodeLabels=e;const{hide:t,show:r}=this.config.simulation.alphas.labels.nodes,o=e?r:t;this.restart(o)}get showLinkLabels(){return this._showLinkLabels}set showLinkLabels(e){this._showLinkLabels=e;const{hide:t,show:r}=this.config.simulation.alphas.labels.links,o=e?r:t;this.restart(o)}get effectiveWidth(){return this.width/this.scale}get effectiveHeight(){return this.height/this.scale}get effectiveCenter(){return tl.of([this.width,this.height]).divide(2).subtract(tl.of([this.xOffset,this.yOffset])).divide(this.scale)}resize(){const e=this.width,t=this.height,r=this.container.getBoundingClientRect().width,o=this.container.getBoundingClientRect().height,s=e.toFixed()!==r.toFixed(),c=t.toFixed()!==o.toFixed();if(!s&&!c)return;this.width=this.container.getBoundingClientRect().width,this.height=this.container.getBoundingClientRect().height;const f=this.config.simulation.alphas.resize;this.restart(n1(f)?f:f({oldWidth:e,oldHeight:t,newWidth:r,newHeight:o}))}restart(e){this.markerSelection=Pge({config:this.config,graph:this.filteredGraph,selection:this.markerSelection}),this.linkSelection=Age({config:this.config,graph:this.filteredGraph,selection:this.linkSelection,showLabels:this._showLinkLabels}),this.nodeSelection=Dge({config:this.config,drag:this.drag,graph:this.filteredGraph,onNodeContext:t=>this.toggleNodeFocus(t),onNodeSelected:this.config.callbacks.nodeClicked,selection:this.nodeSelection,showLabels:this._showNodeLabels}),this.simulation?.stop(),this.simulation=Bge({center:()=>this.effectiveCenter,config:this.config,graph:this.filteredGraph,onTick:()=>this.onTick()}).alpha(e).restart()}filterNodesByType(e,t){e?this._nodeTypeFilter.push(t):this._nodeTypeFilter=this._nodeTypeFilter.filter(r=>r!==t),this.filterGraph(this.focusedNode),this.restart(this.config.simulation.alphas.filter.type)}shutdown(){this.focusedNode!==void 0&&(this.focusedNode.isFocused=!1,this.focusedNode=void 0),this.resizeObserver?.unobserve(this.container),this.simulation?.stop()}initGraph(){this.zoom=Wge({config:this.config,canvasContainer:()=>Kn(this.container).select(\"svg\"),min:this.config.zoom.min,max:this.config.zoom.max,onZoom:e=>this.onZoom(e)}),this.canvas=pge({applyZoom:this.scale!==1,container:Kn(this.container),offset:[this.xOffset,this.yOffset],scale:this.scale,zoom:this.zoom}),this.applyZoom(),this.linkSelection=Ege(this.canvas),this.nodeSelection=Ige(this.canvas),this.markerSelection=Oge(this.canvas),this.drag=mge({config:this.config,onDragStart:()=>this.simulation?.alphaTarget(this.config.simulation.alphas.drag.start).restart(),onDragEnd:()=>this.simulation?.alphaTarget(this.config.simulation.alphas.drag.end).restart()})}onTick(){Hge(this.nodeSelection),Lge({config:this.config,center:this.effectiveCenter,graph:this.filteredGraph,selection:this.linkSelection})}resetView(){this.simulation?.stop(),Kn(this.container).selectChildren().remove(),this.zoom=void 0,this.canvas=void 0,this.linkSelection=void 0,this.nodeSelection=void 0,this.markerSelection=void 0,this.simulation=void 0,this.width=this.container.getBoundingClientRect().width,this.height=this.container.getBoundingClientRect().height}onZoom(e){this.xOffset=e.transform.x,this.yOffset=e.transform.y,this.scale=e.transform.k,this.applyZoom(),this.config.hooks.afterZoom?.(this.scale,this.xOffset,this.yOffset),this.simulation?.restart()}applyZoom(){gge({canvas:this.canvas,scale:this.scale,xOffset:this.xOffset,yOffset:this.yOffset})}toggleNodeFocus(e){e.isFocused?(this.filterGraph(void 0),this.restart(this.config.simulation.alphas.focus.release(e))):this.focusNode(e)}focusNode(e){this.filterGraph(e),this.restart(this.config.simulation.alphas.focus.acquire(e))}filterGraph(e){this.focusedNode!==void 0&&(this.focusedNode.isFocused=!1,this.focusedNode=void 0),e!==void 0&&this._nodeTypeFilter.includes(e.type)&&(e.isFocused=!0,this.focusedNode=e),this.filteredGraph=vge({graph:this.graph,filter:this._nodeTypeFilter,focusedNode:this.focusedNode,includeUnlinked:this._includeUnlinked,linkFilter:this._linkFilter})}};function s0({nodes:e,links:t}){return{nodes:e??[],links:t??[]}}function jge(e){return{...e}}function Ip(e){return{...e,isFocused:!1,lastInteractionTimestamp:void 0}}function Uge(e){const t=e.map(o=>Jw(o)),r=eL(t);return t.map(({raw:o,id:s,splits:c})=>Ip({color:\"var(--color-node-external)\",label:{color:\"var(--color-node-external)\",fontSize:\"0.875rem\",text:s.includes(\"node_modules\")?r.get(o)??o:c.pop()},isFocused:!1,id:s,type:\"external\"}))}function Vge(e,t){return Ip({color:t?\"var(--color-node-root)\":\"var(--color-node-inline)\",label:{color:t?\"var(--color-node-root)\":\"var(--color-node-inline)\",fontSize:\"0.875rem\",text:e.split(/\\//g).pop()},isFocused:!1,id:e,type:\"inline\"})}function Gge(e,t){if(!e)return s0({});const r=Uge(e.externalized),o=e.inlined.map(d=>Vge(d,d===t))??[],s=[...r,...o],c=Object.fromEntries(s.map(d=>[d.id,d])),f=Object.entries(e.graph).flatMap(([d,h])=>h.map(p=>{const g=c[d],v=c[p];if(!(g===void 0||v===void 0))return jge({source:g,target:v,color:\"var(--color-link)\",label:!1})}).filter(p=>p!==void 0));return s0({nodes:s,links:f})}const Kge={key:0,\"text-green-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:checkmark\":\"\"},Xge={key:1,\"text-red-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:compare\":\"\"},Yge={key:2,\"text-red-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:close\":\"\"},Zge={key:3,\"text-gray-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:document-blank\":\"\"},Jge={key:4,\"text-gray-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:redo\":\"\",\"rotate-90\":\"\"},Qge={key:5,\"text-yellow-500\":\"\",\"flex-shrink-0\":\"\",\"i-carbon:circle-dash\":\"\",\"animate-spin\":\"\"},c1=rt({__name:\"StatusIcon\",props:{state:{},mode:{},failedSnapshot:{type:Boolean}},setup(e){return(t,r)=>{const o=vr(\"tooltip\");return e.state===\"pass\"?(ie(),ve(\"div\",Kge)):e.failedSnapshot?at((ie(),ve(\"div\",Xge,null,512)),[[o,\"Contains failed snapshot\",void 0,{right:!0}]]):e.state===\"fail\"?(ie(),ve(\"div\",Yge)):e.mode===\"todo\"?at((ie(),ve(\"div\",Zge,null,512)),[[o,\"Todo\",void 0,{right:!0}]]):e.mode===\"skip\"||e.state===\"skip\"?at((ie(),ve(\"div\",Jge,null,512)),[[o,\"Skipped\",void 0,{right:!0}]]):(ie(),ve(\"div\",Qge))}}}),ol=zE(),eme=xE(ol),tme={border:\"b base\",\"p-4\":\"\"},nme=[\"innerHTML\"],rme=rt({__name:\"ViewConsoleOutputEntry\",props:{taskName:{},type:{},time:{},content:{}},setup(e){function t(r){return new Date(r).toLocaleTimeString()}return(r,o)=>(ie(),ve(\"div\",tme,[X(\"div\",{\"text-xs\":\"\",\"mb-1\":\"\",class:ot(e.type===\"stderr\"?\"text-red-600 dark:text-red-300\":\"op30\")},Re(t(e.time))+\" | \"+Re(e.taskName)+\" | \"+Re(e.type),3),X(\"pre\",{\"data-type\":\"html\",innerHTML:e.content},null,8,nme)]))}}),ime={key:0,\"h-full\":\"\",class:\"scrolls\",flex:\"\",\"flex-col\":\"\",\"data-testid\":\"logs\"},ome={key:1,p6:\"\"},sme=rt({__name:\"ViewConsoleOutput\",setup(e){const t=ke(()=>{const o=Tx.value;if(o){const s=wp(ol.value);return o.map(({taskId:c,type:f,time:d,content:h})=>({taskId:c,type:f,time:d,content:s.toHtml(oa(h))}))}});function r(o){const s=o&&ft.state.idMap.get(o);return s&&\"filepath\"in s?s.name:(s?$A(s).slice(1).join(\" > \"):\"-\")||\"-\"}return(o,s)=>t.value?.length?(ie(),ve(\"div\",ime,[(ie(!0),ve(nt,null,$n(t.value,({taskId:c,type:f,time:d,content:h})=>(ie(),ve(\"div\",{key:c,\"font-mono\":\"\"},[Ne(rme,{\"task-name\":r(c),type:f,time:d,content:h},null,8,[\"task-name\",\"type\",\"time\",\"content\"])]))),128))])):(ie(),ve(\"div\",ome,[...s[0]||(s[0]=[Qe(\" Log something in your test and it would print here. (e.g. \",-1),X(\"pre\",{inline:\"\"},\"console.log(foo)\",-1),Qe(\") \",-1)])]))}}),u1={\"application/andrew-inset\":[\"ez\"],\"application/appinstaller\":[\"appinstaller\"],\"application/applixware\":[\"aw\"],\"application/appx\":[\"appx\"],\"application/appxbundle\":[\"appxbundle\"],\"application/atom+xml\":[\"atom\"],\"application/atomcat+xml\":[\"atomcat\"],\"application/atomdeleted+xml\":[\"atomdeleted\"],\"application/atomsvc+xml\":[\"atomsvc\"],\"application/atsc-dwd+xml\":[\"dwd\"],\"application/atsc-held+xml\":[\"held\"],\"application/atsc-rsat+xml\":[\"rsat\"],\"application/automationml-aml+xml\":[\"aml\"],\"application/automationml-amlx+zip\":[\"amlx\"],\"application/bdoc\":[\"bdoc\"],\"application/calendar+xml\":[\"xcs\"],\"application/ccxml+xml\":[\"ccxml\"],\"application/cdfx+xml\":[\"cdfx\"],\"application/cdmi-capability\":[\"cdmia\"],\"application/cdmi-container\":[\"cdmic\"],\"application/cdmi-domain\":[\"cdmid\"],\"application/cdmi-object\":[\"cdmio\"],\"application/cdmi-queue\":[\"cdmiq\"],\"application/cpl+xml\":[\"cpl\"],\"application/cu-seeme\":[\"cu\"],\"application/cwl\":[\"cwl\"],\"application/dash+xml\":[\"mpd\"],\"application/dash-patch+xml\":[\"mpp\"],\"application/davmount+xml\":[\"davmount\"],\"application/dicom\":[\"dcm\"],\"application/docbook+xml\":[\"dbk\"],\"application/dssc+der\":[\"dssc\"],\"application/dssc+xml\":[\"xdssc\"],\"application/ecmascript\":[\"ecma\"],\"application/emma+xml\":[\"emma\"],\"application/emotionml+xml\":[\"emotionml\"],\"application/epub+zip\":[\"epub\"],\"application/exi\":[\"exi\"],\"application/express\":[\"exp\"],\"application/fdf\":[\"fdf\"],\"application/fdt+xml\":[\"fdt\"],\"application/font-tdpfr\":[\"pfr\"],\"application/geo+json\":[\"geojson\"],\"application/gml+xml\":[\"gml\"],\"application/gpx+xml\":[\"gpx\"],\"application/gxf\":[\"gxf\"],\"application/gzip\":[\"gz\"],\"application/hjson\":[\"hjson\"],\"application/hyperstudio\":[\"stk\"],\"application/inkml+xml\":[\"ink\",\"inkml\"],\"application/ipfix\":[\"ipfix\"],\"application/its+xml\":[\"its\"],\"application/java-archive\":[\"jar\",\"war\",\"ear\"],\"application/java-serialized-object\":[\"ser\"],\"application/java-vm\":[\"class\"],\"application/javascript\":[\"*js\"],\"application/json\":[\"json\",\"map\"],\"application/json5\":[\"json5\"],\"application/jsonml+json\":[\"jsonml\"],\"application/ld+json\":[\"jsonld\"],\"application/lgr+xml\":[\"lgr\"],\"application/lost+xml\":[\"lostxml\"],\"application/mac-binhex40\":[\"hqx\"],\"application/mac-compactpro\":[\"cpt\"],\"application/mads+xml\":[\"mads\"],\"application/manifest+json\":[\"webmanifest\"],\"application/marc\":[\"mrc\"],\"application/marcxml+xml\":[\"mrcx\"],\"application/mathematica\":[\"ma\",\"nb\",\"mb\"],\"application/mathml+xml\":[\"mathml\"],\"application/mbox\":[\"mbox\"],\"application/media-policy-dataset+xml\":[\"mpf\"],\"application/mediaservercontrol+xml\":[\"mscml\"],\"application/metalink+xml\":[\"metalink\"],\"application/metalink4+xml\":[\"meta4\"],\"application/mets+xml\":[\"mets\"],\"application/mmt-aei+xml\":[\"maei\"],\"application/mmt-usd+xml\":[\"musd\"],\"application/mods+xml\":[\"mods\"],\"application/mp21\":[\"m21\",\"mp21\"],\"application/mp4\":[\"*mp4\",\"*mpg4\",\"mp4s\",\"m4p\"],\"application/msix\":[\"msix\"],\"application/msixbundle\":[\"msixbundle\"],\"application/msword\":[\"doc\",\"dot\"],\"application/mxf\":[\"mxf\"],\"application/n-quads\":[\"nq\"],\"application/n-triples\":[\"nt\"],\"application/node\":[\"cjs\"],\"application/octet-stream\":[\"bin\",\"dms\",\"lrf\",\"mar\",\"so\",\"dist\",\"distz\",\"pkg\",\"bpk\",\"dump\",\"elc\",\"deploy\",\"exe\",\"dll\",\"deb\",\"dmg\",\"iso\",\"img\",\"msi\",\"msp\",\"msm\",\"buffer\"],\"application/oda\":[\"oda\"],\"application/oebps-package+xml\":[\"opf\"],\"application/ogg\":[\"ogx\"],\"application/omdoc+xml\":[\"omdoc\"],\"application/onenote\":[\"onetoc\",\"onetoc2\",\"onetmp\",\"onepkg\",\"one\",\"onea\"],\"application/oxps\":[\"oxps\"],\"application/p2p-overlay+xml\":[\"relo\"],\"application/patch-ops-error+xml\":[\"xer\"],\"application/pdf\":[\"pdf\"],\"application/pgp-encrypted\":[\"pgp\"],\"application/pgp-keys\":[\"asc\"],\"application/pgp-signature\":[\"sig\",\"*asc\"],\"application/pics-rules\":[\"prf\"],\"application/pkcs10\":[\"p10\"],\"application/pkcs7-mime\":[\"p7m\",\"p7c\"],\"application/pkcs7-signature\":[\"p7s\"],\"application/pkcs8\":[\"p8\"],\"application/pkix-attr-cert\":[\"ac\"],\"application/pkix-cert\":[\"cer\"],\"application/pkix-crl\":[\"crl\"],\"application/pkix-pkipath\":[\"pkipath\"],\"application/pkixcmp\":[\"pki\"],\"application/pls+xml\":[\"pls\"],\"application/postscript\":[\"ai\",\"eps\",\"ps\"],\"application/provenance+xml\":[\"provx\"],\"application/pskc+xml\":[\"pskcxml\"],\"application/raml+yaml\":[\"raml\"],\"application/rdf+xml\":[\"rdf\",\"owl\"],\"application/reginfo+xml\":[\"rif\"],\"application/relax-ng-compact-syntax\":[\"rnc\"],\"application/resource-lists+xml\":[\"rl\"],\"application/resource-lists-diff+xml\":[\"rld\"],\"application/rls-services+xml\":[\"rs\"],\"application/route-apd+xml\":[\"rapd\"],\"application/route-s-tsid+xml\":[\"sls\"],\"application/route-usd+xml\":[\"rusd\"],\"application/rpki-ghostbusters\":[\"gbr\"],\"application/rpki-manifest\":[\"mft\"],\"application/rpki-roa\":[\"roa\"],\"application/rsd+xml\":[\"rsd\"],\"application/rss+xml\":[\"rss\"],\"application/rtf\":[\"rtf\"],\"application/sbml+xml\":[\"sbml\"],\"application/scvp-cv-request\":[\"scq\"],\"application/scvp-cv-response\":[\"scs\"],\"application/scvp-vp-request\":[\"spq\"],\"application/scvp-vp-response\":[\"spp\"],\"application/sdp\":[\"sdp\"],\"application/senml+xml\":[\"senmlx\"],\"application/sensml+xml\":[\"sensmlx\"],\"application/set-payment-initiation\":[\"setpay\"],\"application/set-registration-initiation\":[\"setreg\"],\"application/shf+xml\":[\"shf\"],\"application/sieve\":[\"siv\",\"sieve\"],\"application/smil+xml\":[\"smi\",\"smil\"],\"application/sparql-query\":[\"rq\"],\"application/sparql-results+xml\":[\"srx\"],\"application/sql\":[\"sql\"],\"application/srgs\":[\"gram\"],\"application/srgs+xml\":[\"grxml\"],\"application/sru+xml\":[\"sru\"],\"application/ssdl+xml\":[\"ssdl\"],\"application/ssml+xml\":[\"ssml\"],\"application/swid+xml\":[\"swidtag\"],\"application/tei+xml\":[\"tei\",\"teicorpus\"],\"application/thraud+xml\":[\"tfi\"],\"application/timestamped-data\":[\"tsd\"],\"application/toml\":[\"toml\"],\"application/trig\":[\"trig\"],\"application/ttml+xml\":[\"ttml\"],\"application/ubjson\":[\"ubj\"],\"application/urc-ressheet+xml\":[\"rsheet\"],\"application/urc-targetdesc+xml\":[\"td\"],\"application/voicexml+xml\":[\"vxml\"],\"application/wasm\":[\"wasm\"],\"application/watcherinfo+xml\":[\"wif\"],\"application/widget\":[\"wgt\"],\"application/winhlp\":[\"hlp\"],\"application/wsdl+xml\":[\"wsdl\"],\"application/wspolicy+xml\":[\"wspolicy\"],\"application/xaml+xml\":[\"xaml\"],\"application/xcap-att+xml\":[\"xav\"],\"application/xcap-caps+xml\":[\"xca\"],\"application/xcap-diff+xml\":[\"xdf\"],\"application/xcap-el+xml\":[\"xel\"],\"application/xcap-ns+xml\":[\"xns\"],\"application/xenc+xml\":[\"xenc\"],\"application/xfdf\":[\"xfdf\"],\"application/xhtml+xml\":[\"xhtml\",\"xht\"],\"application/xliff+xml\":[\"xlf\"],\"application/xml\":[\"xml\",\"xsl\",\"xsd\",\"rng\"],\"application/xml-dtd\":[\"dtd\"],\"application/xop+xml\":[\"xop\"],\"application/xproc+xml\":[\"xpl\"],\"application/xslt+xml\":[\"*xsl\",\"xslt\"],\"application/xspf+xml\":[\"xspf\"],\"application/xv+xml\":[\"mxml\",\"xhvml\",\"xvml\",\"xvm\"],\"application/yang\":[\"yang\"],\"application/yin+xml\":[\"yin\"],\"application/zip\":[\"zip\"],\"application/zip+dotlottie\":[\"lottie\"],\"audio/3gpp\":[\"*3gpp\"],\"audio/aac\":[\"adts\",\"aac\"],\"audio/adpcm\":[\"adp\"],\"audio/amr\":[\"amr\"],\"audio/basic\":[\"au\",\"snd\"],\"audio/midi\":[\"mid\",\"midi\",\"kar\",\"rmi\"],\"audio/mobile-xmf\":[\"mxmf\"],\"audio/mp3\":[\"*mp3\"],\"audio/mp4\":[\"m4a\",\"mp4a\",\"m4b\"],\"audio/mpeg\":[\"mpga\",\"mp2\",\"mp2a\",\"mp3\",\"m2a\",\"m3a\"],\"audio/ogg\":[\"oga\",\"ogg\",\"spx\",\"opus\"],\"audio/s3m\":[\"s3m\"],\"audio/silk\":[\"sil\"],\"audio/wav\":[\"wav\"],\"audio/wave\":[\"*wav\"],\"audio/webm\":[\"weba\"],\"audio/xm\":[\"xm\"],\"font/collection\":[\"ttc\"],\"font/otf\":[\"otf\"],\"font/ttf\":[\"ttf\"],\"font/woff\":[\"woff\"],\"font/woff2\":[\"woff2\"],\"image/aces\":[\"exr\"],\"image/apng\":[\"apng\"],\"image/avci\":[\"avci\"],\"image/avcs\":[\"avcs\"],\"image/avif\":[\"avif\"],\"image/bmp\":[\"bmp\",\"dib\"],\"image/cgm\":[\"cgm\"],\"image/dicom-rle\":[\"drle\"],\"image/dpx\":[\"dpx\"],\"image/emf\":[\"emf\"],\"image/fits\":[\"fits\"],\"image/g3fax\":[\"g3\"],\"image/gif\":[\"gif\"],\"image/heic\":[\"heic\"],\"image/heic-sequence\":[\"heics\"],\"image/heif\":[\"heif\"],\"image/heif-sequence\":[\"heifs\"],\"image/hej2k\":[\"hej2\"],\"image/ief\":[\"ief\"],\"image/jaii\":[\"jaii\"],\"image/jais\":[\"jais\"],\"image/jls\":[\"jls\"],\"image/jp2\":[\"jp2\",\"jpg2\"],\"image/jpeg\":[\"jpg\",\"jpeg\",\"jpe\"],\"image/jph\":[\"jph\"],\"image/jphc\":[\"jhc\"],\"image/jpm\":[\"jpm\",\"jpgm\"],\"image/jpx\":[\"jpx\",\"jpf\"],\"image/jxl\":[\"jxl\"],\"image/jxr\":[\"jxr\"],\"image/jxra\":[\"jxra\"],\"image/jxrs\":[\"jxrs\"],\"image/jxs\":[\"jxs\"],\"image/jxsc\":[\"jxsc\"],\"image/jxsi\":[\"jxsi\"],\"image/jxss\":[\"jxss\"],\"image/ktx\":[\"ktx\"],\"image/ktx2\":[\"ktx2\"],\"image/pjpeg\":[\"jfif\"],\"image/png\":[\"png\"],\"image/sgi\":[\"sgi\"],\"image/svg+xml\":[\"svg\",\"svgz\"],\"image/t38\":[\"t38\"],\"image/tiff\":[\"tif\",\"tiff\"],\"image/tiff-fx\":[\"tfx\"],\"image/webp\":[\"webp\"],\"image/wmf\":[\"wmf\"],\"message/disposition-notification\":[\"disposition-notification\"],\"message/global\":[\"u8msg\"],\"message/global-delivery-status\":[\"u8dsn\"],\"message/global-disposition-notification\":[\"u8mdn\"],\"message/global-headers\":[\"u8hdr\"],\"message/rfc822\":[\"eml\",\"mime\",\"mht\",\"mhtml\"],\"model/3mf\":[\"3mf\"],\"model/gltf+json\":[\"gltf\"],\"model/gltf-binary\":[\"glb\"],\"model/iges\":[\"igs\",\"iges\"],\"model/jt\":[\"jt\"],\"model/mesh\":[\"msh\",\"mesh\",\"silo\"],\"model/mtl\":[\"mtl\"],\"model/obj\":[\"obj\"],\"model/prc\":[\"prc\"],\"model/step\":[\"step\",\"stp\",\"stpnc\",\"p21\",\"210\"],\"model/step+xml\":[\"stpx\"],\"model/step+zip\":[\"stpz\"],\"model/step-xml+zip\":[\"stpxz\"],\"model/stl\":[\"stl\"],\"model/u3d\":[\"u3d\"],\"model/vrml\":[\"wrl\",\"vrml\"],\"model/x3d+binary\":[\"*x3db\",\"x3dbz\"],\"model/x3d+fastinfoset\":[\"x3db\"],\"model/x3d+vrml\":[\"*x3dv\",\"x3dvz\"],\"model/x3d+xml\":[\"x3d\",\"x3dz\"],\"model/x3d-vrml\":[\"x3dv\"],\"text/cache-manifest\":[\"appcache\",\"manifest\"],\"text/calendar\":[\"ics\",\"ifb\"],\"text/coffeescript\":[\"coffee\",\"litcoffee\"],\"text/css\":[\"css\"],\"text/csv\":[\"csv\"],\"text/html\":[\"html\",\"htm\",\"shtml\"],\"text/jade\":[\"jade\"],\"text/javascript\":[\"js\",\"mjs\"],\"text/jsx\":[\"jsx\"],\"text/less\":[\"less\"],\"text/markdown\":[\"md\",\"markdown\"],\"text/mathml\":[\"mml\"],\"text/mdx\":[\"mdx\"],\"text/n3\":[\"n3\"],\"text/plain\":[\"txt\",\"text\",\"conf\",\"def\",\"list\",\"log\",\"in\",\"ini\"],\"text/richtext\":[\"rtx\"],\"text/rtf\":[\"*rtf\"],\"text/sgml\":[\"sgml\",\"sgm\"],\"text/shex\":[\"shex\"],\"text/slim\":[\"slim\",\"slm\"],\"text/spdx\":[\"spdx\"],\"text/stylus\":[\"stylus\",\"styl\"],\"text/tab-separated-values\":[\"tsv\"],\"text/troff\":[\"t\",\"tr\",\"roff\",\"man\",\"me\",\"ms\"],\"text/turtle\":[\"ttl\"],\"text/uri-list\":[\"uri\",\"uris\",\"urls\"],\"text/vcard\":[\"vcard\"],\"text/vtt\":[\"vtt\"],\"text/wgsl\":[\"wgsl\"],\"text/xml\":[\"*xml\"],\"text/yaml\":[\"yaml\",\"yml\"],\"video/3gpp\":[\"3gp\",\"3gpp\"],\"video/3gpp2\":[\"3g2\"],\"video/h261\":[\"h261\"],\"video/h263\":[\"h263\"],\"video/h264\":[\"h264\"],\"video/iso.segment\":[\"m4s\"],\"video/jpeg\":[\"jpgv\"],\"video/jpm\":[\"*jpm\",\"*jpgm\"],\"video/mj2\":[\"mj2\",\"mjp2\"],\"video/mp2t\":[\"ts\",\"m2t\",\"m2ts\",\"mts\"],\"video/mp4\":[\"mp4\",\"mp4v\",\"mpg4\"],\"video/mpeg\":[\"mpeg\",\"mpg\",\"mpe\",\"m1v\",\"m2v\"],\"video/ogg\":[\"ogv\"],\"video/quicktime\":[\"qt\",\"mov\"],\"video/webm\":[\"webm\"]};Object.freeze(u1);var fr=function(e,t,r,o){if(r===\"a\"&&!o)throw new TypeError(\"Private accessor was defined without a getter\");if(typeof t==\"function\"?e!==t||!o:!t.has(e))throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");return r===\"m\"?o:r===\"a\"?o.call(e):o?o.value:t.get(e)},As,Kl,Do;class lme{constructor(...t){As.set(this,new Map),Kl.set(this,new Map),Do.set(this,new Map);for(const r of t)this.define(r)}define(t,r=!1){for(let[o,s]of Object.entries(t)){o=o.toLowerCase(),s=s.map(d=>d.toLowerCase()),fr(this,Do,\"f\").has(o)||fr(this,Do,\"f\").set(o,new Set);const c=fr(this,Do,\"f\").get(o);let f=!0;for(let d of s){const h=d.startsWith(\"*\");if(d=h?d.slice(1):d,c?.add(d),f&&fr(this,Kl,\"f\").set(o,d),f=!1,h)continue;const p=fr(this,As,\"f\").get(d);if(p&&p!=o&&!r)throw new Error(`\"${o} -> ${d}\" conflicts with \"${p} -> ${d}\". Pass \\`force=true\\` to override this definition.`);fr(this,As,\"f\").set(d,o)}}return this}getType(t){if(typeof t!=\"string\")return null;const r=t.replace(/^.*[/\\\\]/s,\"\").toLowerCase(),o=r.replace(/^.*\\./s,\"\").toLowerCase(),s=r.length<t.length;return!(o.length<r.length-1)&&s?null:fr(this,As,\"f\").get(o)??null}getExtension(t){return typeof t!=\"string\"?null:(t=t?.split?.(\";\")[0],(t&&fr(this,Kl,\"f\").get(t.trim().toLowerCase()))??null)}getAllExtensions(t){return typeof t!=\"string\"?null:fr(this,Do,\"f\").get(t.toLowerCase())??null}_freeze(){this.define=()=>{throw new Error(\"define() not allowed for built-in Mime objects. See https://github.com/broofa/mime/blob/main/README.md#custom-mime-instances\")},Object.freeze(this);for(const t of fr(this,Do,\"f\").values())Object.freeze(t);return this}_getTestState(){return{types:fr(this,As,\"f\"),extensions:fr(this,Kl,\"f\")}}}As=new WeakMap,Kl=new WeakMap,Do=new WeakMap;const ame=new lme(u1)._freeze();function Ma(e){if(gr)return`/data/${e.path}`;const t=e.contentType??\"application/octet-stream\";return e.path?`/__vitest_attachment__?path=${encodeURIComponent(e.path)}&contentType=${t}&token=${window.VITEST_API_TOKEN}`:`data:${t};base64,${e.body}`}function f1(e,t){const r=t?ame.getExtension(t):null;return e.replace(/[\\x00-\\x2C\\x2E\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7F]+/g,\"-\")+(r?`.${r}`:\"\")}function d1(e){const t=e.path||e.body;return typeof t==\"string\"&&(t.startsWith(\"http://\")||t.startsWith(\"https://\"))}function Mh(e){const t=e.path||e.body;return typeof t==\"string\"&&(t.startsWith(\"http://\")||t.startsWith(\"https://\"))?t:Ma(e)}const tu=rt({__name:\"CodeMirrorContainer\",props:da({mode:{},readOnly:{type:Boolean},saving:{type:Boolean}},{modelValue:{},modelModifiers:{}}),emits:da([\"save\",\"codemirror\"],[\"update:modelValue\"]),setup(e,{emit:t}){const r=t,o=Yu(e,\"modelValue\"),s=U_(),c={html:\"htmlmixed\",vue:\"htmlmixed\",svelte:\"htmlmixed\",js:\"javascript\",mjs:\"javascript\",cjs:\"javascript\",ts:{name:\"javascript\",typescript:!0},mts:{name:\"javascript\",typescript:!0},cts:{name:\"javascript\",typescript:!0},jsx:{name:\"javascript\",jsx:!0},tsx:{name:\"javascript\",typescript:!0,jsx:!0}},f=Ge();return Mi(async()=>{const d=hce(f,o,{...s,mode:c[e.mode||\"\"]||e.mode,readOnly:e.readOnly?!0:void 0,extraKeys:{\"Cmd-S\":function(h){h.getOption(\"readOnly\")||r(\"save\",h.getValue())},\"Ctrl-S\":function(h){h.getOption(\"readOnly\")||r(\"save\",h.getValue())}}});d.on(\"refresh\",()=>{r(\"codemirror\",d)}),d.on(\"change\",()=>{r(\"codemirror\",d)}),d.setSize(\"100%\",\"100%\"),d.clearHistory(),Nn.value=d,setTimeout(()=>Nn.value?.refresh(),100)}),(d,h)=>(ie(),ve(\"div\",{relative:\"\",\"font-mono\":\"\",\"text-sm\":\"\",class:ot([\"codemirror-scrolls\",e.saving?\"codemirror-busy\":void 0])},[X(\"textarea\",{ref_key:\"el\",ref:f},null,512)],2))}}),cme=rt({__name:\"ViewEditor\",props:{file:{}},emits:[\"draft\"],setup(e,{emit:t}){const r=e,o=t,s=Ge(\"\"),c=Ft(void 0),f=Ge(!1),d=Ge(!0),h=Ge(!1),p=Ge();xt(()=>r.file,async()=>{if(!h.value){d.value=!0;try{if(!r.file||!r.file?.filepath){s.value=\"\",c.value=s.value,f.value=!1,d.value=!1;return}s.value=await ft.rpc.readTestFile(r.file.filepath)||\"\",c.value=s.value,f.value=!1}catch(Z){console.error(\"cannot fetch file\",Z)}await Et(),d.value=!1}},{immediate:!0}),xt(()=>[d.value,h.value,r.file,hx.value,px.value],([Z,G,j,N,O])=>{!Z&&!G&&(N!=null?Et(()=>{const C=p.value,k=C??{line:(N??1)-1,ch:O??0};C?p.value=void 0:(Nn.value?.scrollIntoView(k,100),Et(()=>{Nn.value?.focus(),Nn.value?.setCursor(k)}))}):Et(()=>{Nn.value?.focus()}))},{flush:\"post\"});const g=ke(()=>r.file?.filepath?.split(/\\./g).pop()||\"js\"),v=Ge(),b=ke(()=>{const Z=[];function G(j){j.result?.errors&&Z.push(...j.result.errors),j.type===\"suite\"&&j.tasks.forEach(G)}return r.file?.tasks.forEach(G),Z}),w=ke(()=>{const Z=[];function G(j){j.type===\"test\"&&Z.push(...j.annotations),j.type===\"suite\"&&j.tasks.forEach(G)}return r.file?.tasks.forEach(G),Z}),E=[],L=[],P=[],M=Ge(!1);function R(){P.forEach(([Z,G,j])=>{Z.removeEventListener(\"click\",G),j()}),P.length=0}Ow(v,()=>{Nn.value?.refresh()});function I(){f.value=c.value!==Nn.value.getValue()}xt(f,Z=>{o(\"draft\",Z)},{immediate:!0});function _(Z){const j=(Z?.stacks||[]).filter(z=>z.file&&z.file===r.file?.filepath)?.[0];if(!j)return;const N=document.createElement(\"div\");N.className=\"op80 flex gap-x-2 items-center\";const O=document.createElement(\"pre\");O.className=\"c-red-600 dark:c-red-400\",O.textContent=`${\" \".repeat(j.column)}^ ${Z.name}: ${Z?.message||\"\"}`,N.appendChild(O);const C=document.createElement(\"span\");C.className=\"i-carbon-launch c-red-600 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em\",C.tabIndex=0,C.ariaLabel=\"Open in Editor\",bw(C,{content:\"Open in Editor\",placement:\"bottom\"},!1);const k=async()=>{await bp(j.file,j.line,j.column)};C.addEventListener(\"click\",k),N.appendChild(C),P.push([C,k,()=>ap(C)]),L.push(Nn.value.addLineClass(j.line-1,\"wrap\",\"bg-red-500/10\")),E.push(Nn.value.addLineWidget(j.line-1,N))}function $(Z){if(!Z.location)return;const{line:G,file:j}=Z.location;if(j!==r.file?.filepath)return;const N=document.createElement(\"div\");N.classList.add(\"wrap\",\"bg-active\",\"py-3\",\"px-6\",\"my-1\"),N.role=\"note\";const O=document.createElement(\"div\");O.classList.add(\"block\",\"text-black\",\"dark:text-white\");const C=document.createElement(\"span\");C.textContent=`${Z.type}: `,C.classList.add(\"font-bold\");const k=document.createElement(\"span\");k.classList.add(\"whitespace-pre\"),k.textContent=Z.message.replace(/[^\\r]\\n/,`\\r\n`),O.append(C,k),N.append(O);const z=Z.attachment;if(z?.path||z?.body)if(z.contentType?.startsWith(\"image/\")){const B=document.createElement(\"a\"),ce=document.createElement(\"img\");B.classList.add(\"inline-block\",\"mt-3\"),B.style.maxWidth=\"50vw\";const be=z.path||z.body;typeof be==\"string\"&&(be.startsWith(\"http://\")||be.startsWith(\"https://\"))?(ce.setAttribute(\"src\",be),B.referrerPolicy=\"no-referrer\"):ce.setAttribute(\"src\",Ma(z)),B.target=\"_blank\",B.href=ce.src,B.append(ce),N.append(B)}else{const B=document.createElement(\"a\");B.href=Ma(z),B.download=f1(Z.message,z.contentType),B.classList.add(\"flex\",\"w-min\",\"gap-2\",\"items-center\",\"font-sans\",\"underline\",\"cursor-pointer\");const ce=document.createElement(\"div\");ce.classList.add(\"i-carbon:download\",\"block\");const be=document.createElement(\"span\");be.textContent=\"Download\",B.append(ce,be),N.append(B)}E.push(Nn.value.addLineWidget(G-1,N))}const{pause:W,resume:ne}=xt([Nn,b,w,Ms],([Z,G,j,N])=>{if(!Z){E.length=0,L.length=0,R();return}N&&(Z.off(\"changes\",I),R(),E.forEach(O=>O.clear()),L.forEach(O=>Z?.removeLineClass(O,\"wrap\")),E.length=0,L.length=0,setTimeout(()=>{G.forEach(_),j.forEach($),M.value||Z.clearHistory(),Z.on(\"changes\",I)},100))},{flush:\"post\"});hp(()=>[Ms.value,h.value,p.value],([Z,G],j)=>{Z&&!G&&j&&j[2]&&Nn.value?.setCursor(j[2])},{debounce:100,flush:\"post\"});async function ee(Z){if(h.value)return;W(),h.value=!0,await Et();const G=Nn.value;G&&(G.setOption(\"readOnly\",!0),await Et(),G.refresh()),p.value=G?.getCursor(),G?.off(\"changes\",I),R(),E.forEach(j=>j.clear()),L.forEach(j=>G?.removeLineClass(j,\"wrap\")),E.length=0,L.length=0;try{M.value=!0,await ft.rpc.saveTestFile(r.file.filepath,Z),c.value=Z,f.value=!1}catch(j){console.error(\"error saving file\",j)}M.value||G?.clearHistory();try{await Uv(Ms).toBe(!1,{flush:\"sync\",timeout:1e3,throwOnTimeout:!0}),await Uv(Ms).toBe(!0,{flush:\"sync\",timeout:1e3,throwOnTimeout:!1})}catch{}b.value.forEach(_),w.value.forEach($),G?.on(\"changes\",I),h.value=!1,await Et(),G&&(G.setOption(\"readOnly\",!1),await Et(),G.refresh()),ne()}return $a(R),(Z,G)=>(ie(),Ve(tu,ki({ref_key:\"editor\",ref:v,modelValue:s.value,\"onUpdate:modelValue\":G[0]||(G[0]=j=>s.value=j),\"h-full\":\"\"},{lineNumbers:!0,readOnly:K(gr),saving:h.value},{mode:g.value,\"data-testid\":\"code-mirror\",onSave:ee}),null,16,[\"modelValue\",\"mode\"]))}}),Dp=rt({__name:\"Modal\",props:da({direction:{default:\"bottom\"}},{modelValue:{type:Boolean,default:!1},modelModifiers:{}}),emits:[\"update:modelValue\"],setup(e){const t=Yu(e,\"modelValue\"),r=ke(()=>{switch(e.direction){case\"bottom\":return\"bottom-0 left-0 right-0 border-t\";case\"top\":return\"top-0 left-0 right-0 border-b\";case\"left\":return\"bottom-0 left-0 top-0 border-r\";case\"right\":return\"bottom-0 top-0 right-0 border-l\";default:return\"\"}}),o=ke(()=>{switch(e.direction){case\"bottom\":return\"translateY(100%)\";case\"top\":return\"translateY(-100%)\";case\"left\":return\"translateX(-100%)\";case\"right\":return\"translateX(100%)\";default:return\"\"}}),s=()=>t.value=!1;return(c,f)=>(ie(),ve(\"div\",{class:ot([\"fixed inset-0 z-40\",t.value?\"\":\"pointer-events-none\"])},[X(\"div\",{class:ot([\"bg-base inset-0 absolute transition-opacity duration-500 ease-out\",t.value?\"opacity-50\":\"opacity-0\"]),onClick:s},null,2),X(\"div\",{class:ot([\"bg-base border-base absolute transition-all duration-200 ease-out scrolls\",[r.value]]),style:zt(t.value?{}:{transform:o.value})},[Dt(c.$slots,\"default\")],6)],2))}}),ume={class:\"overflow-auto max-h-120\"},fme={\"my-2\":\"\",\"mx-4\":\"\"},dme={\"op-70\":\"\"},hme={\"my-2\":\"\",\"mx-4\":\"\",\"text-sm\":\"\",\"font-light\":\"\",\"op-90\":\"\"},pme=[\"onClick\"],gme=rt({__name:\"ModuleGraphImportBreakdown\",emits:[\"select\"],setup(e,{emit:t}){const r=t,o=Ge(10),s=ke(()=>{const h=pr.value?.importDurations;if(!h)return[];const p=ei.value.root,g=[];for(const b in h){const w=h[b],E=w.external?tL(b):af(p,b);g.push({importedFile:b,relativeFile:f(E),selfTime:w.selfTime,totalTime:w.totalTime,formattedSelfTime:Fo(w.selfTime),formattedTotalTime:Fo(w.totalTime),selfTimeClass:_u(w.selfTime),totalTimeClass:_u(w.totalTime),external:w.external})}return g.sort((b,w)=>w.totalTime-b.totalTime)}),c=ke(()=>s.value.slice(0,o.value));function f(d){return d.length<=45?d:`...${d.slice(-45)}`}return(d,h)=>(ie(),ve(\"div\",ume,[X(\"h1\",fme,[h[1]||(h[1]=Qe(\" Import Duration Breakdown \",-1)),X(\"span\",dme,\"(ordered by Total Time) (Top \"+Re(Math.min(o.value,c.value.length))+\")\",1)]),X(\"table\",hme,[h[2]||(h[2]=X(\"thead\",null,[X(\"tr\",null,[X(\"th\",null,\" Module \"),X(\"th\",null,\" Self \"),X(\"th\",null,\" Total \"),X(\"th\",null,\" % \")])],-1)),X(\"tbody\",null,[(ie(!0),ve(nt,null,$n(c.value,p=>(ie(),ve(\"tr\",{key:p.importedFile},[X(\"td\",{class:\"cursor-pointer pr-2\",style:zt({color:p.external?\"var(--color-node-external)\":void 0}),onClick:g=>r(\"select\",p.importedFile,p.external?\"external\":\"inline\")},Re(p.relativeFile),13,pme),X(\"td\",{\"pr-2\":\"\",class:ot(p.selfTimeClass)},Re(p.formattedSelfTime),3),X(\"td\",{\"pr-2\":\"\",class:ot(p.totalTimeClass)},Re(p.formattedTotalTime),3),X(\"td\",{\"pr-2\":\"\",class:ot(p.totalTimeClass)},Re(Math.round(p.totalTime/s.value[0].totalTime*100))+\"% \",3)]))),128))])]),o.value<s.value.length?(ie(),ve(\"button\",{key:0,class:\"flex w-full justify-center h-8 text-sm z-10 relative font-light\",onClick:h[0]||(h[0]=p=>o.value+=5)},\" Show more \")):He(\"\",!0)]))}}),Cs=rt({__name:\"Badge\",props:{type:{default:\"info\"}},setup(e){return(t,r)=>(ie(),ve(\"span\",{class:ot([\"rounded-full py-0.5 px-2 text-xs text-white select-none\",{\"bg-red\":e.type===\"danger\",\"bg-orange\":e.type===\"warning\",\"bg-gray\":e.type===\"info\",\"bg-indigo/60\":e.type===\"tip\"}])},[Dt(t.$slots,\"default\")],2))}}),mme={\"w-350\":\"\",\"max-w-screen\":\"\",\"h-full\":\"\",flex:\"\",\"flex-col\":\"\"},vme={\"p-4\":\"\",relative:\"\"},yme={flex:\"\",\"justify-between\":\"\"},bme={\"mr-8\":\"\",flex:\"\",\"gap-2\":\"\",\"items-center\":\"\"},wme={op50:\"\",\"font-mono\":\"\",\"text-sm\":\"\"},xme={key:0,\"p-5\":\"\"},kme={key:0,p:\"x3 y-1\",\"bg-overlay\":\"\",border:\"base b t\"},Sme={key:0},_me={p:\"x3 y-1\",\"bg-overlay\":\"\",border:\"base b t\"},Tme=rt({__name:\"ModuleTransformResultView\",props:{id:{},projectName:{},type:{},canUndo:{type:Boolean}},emits:[\"close\",\"select\",\"back\"],setup(e,{emit:t}){const r=e,o=t,s=TE(()=>{if(pr.value?.id){if(r.type===\"inline\")return ft.rpc.getTransformResult(r.projectName,r.id,pr.value.id,!!Zn);if(r.type===\"external\")return ft.rpc.getExternalResult(r.id,pr.value.id)}}),c=ke(()=>{const I=pr.value?.importDurations||{};return I[r.id]||I[NA(\"/@fs/\",r.id)]||{}}),f=ke(()=>r.id?.split(/\\./g).pop()||\"js\"),d=ke(()=>s.value?.source?.trim()||\"\"),h=ke(()=>!s.value||!(\"code\"in s.value)||!ei.value.experimental?.fsModuleCache?void 0:s.value.code.lastIndexOf(\"vitestCache=\")!==-1),p=ke(()=>!s.value||!(\"code\"in s.value)?null:s.value.code.replace(/\\/\\/# sourceMappingURL=.*\\n/,\"\").replace(/\\/\\/# sourceMappingSource=.*\\n/,\"\").replace(/\\/\\/# vitestCache=.*\\n?/,\"\").trim()||\"\"),g=ke(()=>!s.value||!(\"map\"in s.value)?{mappings:\"\"}:{mappings:s.value?.map?.mappings??\"\",version:s.value?.map?.version}),v=[],b=[],w=[];function E(I,_){const $=I.coordsChar({left:_.clientX,top:_.clientY}),W=I.findMarksAt($);if(W.length!==1)return;const ne=W[0].title;if(ne){const ee=W[0].attributes?.[\"data-external\"]===\"true\"?\"external\":\"inline\";o(\"select\",ne,ee)}}function L(I){const _=document.createElement(\"div\");return _.classList.add(\"mb-5\"),I.forEach(({resolvedId:$,totalTime:W,external:ne})=>{const ee=document.createElement(\"div\");ee.append(document.createTextNode(\"import \"));const Z=document.createElement(\"span\"),G=af(ei.value.root,$);Z.textContent=`\"/${G}\"`,Z.className=\"hover:underline decoration-gray cursor-pointer select-none\",ee.append(Z),Z.addEventListener(\"click\",()=>{o(\"select\",$,ne?\"external\":\"inline\")});const j=document.createElement(\"span\");j.textContent=` ${Fo(W)}`;const N=_u(W);N&&j.classList.add(N),ee.append(j),_.append(ee)}),_}function P(I){const _=document.createElement(\"div\");_.className=\"flex ml-2\",_.textContent=Fo(I);const $=_u(I);return $&&_.classList.add($),_}function M(I){if(w.forEach(_=>_.clear()),w.length=0,v.forEach(_=>_.remove()),v.length=0,b.forEach(_=>_.clear()),b.length=0,s.value&&\"modules\"in s.value){I.off(\"mousedown\",E),I.on(\"mousedown\",E);const _=s.value.untrackedModules;if(_?.length){const $=L(_);v.push($),w.push(I.addLineWidget(0,$,{above:!0}))}s.value.modules?.forEach($=>{const W={line:$.start.line-1,ch:$.start.column},ne={line:$.end.line-1,ch:$.end.column},ee=I.markText(W,ne,{title:$.resolvedId,attributes:{\"data-external\":String($.external===!0)},className:\"hover:underline decoration-red cursor-pointer select-none\"});b.push(ee);const Z=P($.totalTime+($.transformTime||0));_?.length||Z.classList.add(\"-mt-5\"),v.push(Z),I.addWidget({line:$.end.line-1,ch:$.end.column+1},Z,!1)})}}function R(){o(\"back\")}return Cw(\"Escape\",()=>{o(\"close\")}),(I,_)=>{const $=vr(\"tooltip\");return ie(),ve(\"div\",mme,[X(\"div\",vme,[X(\"div\",yme,[X(\"p\",null,[e.canUndo?at((ie(),Ve(_t,{key:0,icon:\"i-carbon-arrow-left\",class:\"flex-inline\",onClick:_[0]||(_[0]=W=>R())},null,512)),[[$,\"Go Back\",void 0,{bottom:!0}]]):He(\"\",!0),_[7]||(_[7]=Qe(\" Module Info \",-1)),Ne(K(Qi),{class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[Qe(\" This is module is \"+Re(e.type===\"external\"?\"externalized\":\"inlined\")+\". \",1),e.type===\"external\"?(ie(),ve(nt,{key:0},[Qe(\" It means that the module was not processed by Vite plugins, but instead was directly imported by the environment. \")],64)):(ie(),ve(nt,{key:1},[Qe(\" It means that the module was processed by Vite plugins. \")],64))]),default:We(()=>[Ne(Cs,{type:\"custom\",\"ml-1\":\"\",style:zt({backgroundColor:`var(--color-node-${e.type})`})},{default:We(()=>[Qe(Re(e.type),1)]),_:1},8,[\"style\"])]),_:1}),h.value===!0?(ie(),Ve(K(Qi),{key:1,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[..._[4]||(_[4]=[Qe(' This module is cached on the file system under `experimental.fsModuleCachePath` (\"node_modules/.exprtimental-vitest-cache\" by default). ',-1)])]),default:We(()=>[Ne(Cs,{type:\"tip\",\"ml-2\":\"\"},{default:We(()=>[..._[3]||(_[3]=[Qe(\" cached \",-1)])]),_:1})]),_:1})):He(\"\",!0),h.value===!1?(ie(),Ve(K(Qi),{key:2,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[..._[6]||(_[6]=[X(\"p\",null,\"This module is not cached on the file system. It might be the first test run after cache invalidation or\",-1),X(\"p\",null,\"it was excluded manually via `experimental_defineCacheKeyGenerator`, or it cannot be cached (modules with `import.meta.glob`, for example).\",-1)])]),default:We(()=>[Ne(Cs,{type:\"warning\",\"ml-2\":\"\"},{default:We(()=>[..._[5]||(_[5]=[Qe(\" not cached \",-1)])]),_:1})]),_:1})):He(\"\",!0)]),X(\"div\",bme,[c.value.selfTime!=null&&c.value.external!==!0?(ie(),Ve(K(Qi),{key:0,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[Qe(\" It took \"+Re(K(Ed)(c.value.selfTime))+\" to import this module, excluding static imports. \",1)]),default:We(()=>[Ne(Cs,{type:K(Xc)(c.value.selfTime)},{default:We(()=>[Qe(\" self: \"+Re(K(Fo)(c.value.selfTime)),1)]),_:1},8,[\"type\"])]),_:1})):He(\"\",!0),c.value.totalTime!=null?(ie(),Ve(K(Qi),{key:1,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[Qe(\" It took \"+Re(K(Ed)(c.value.totalTime))+\" to import the whole module, including static imports. \",1)]),default:We(()=>[Ne(Cs,{type:K(Xc)(c.value.totalTime)},{default:We(()=>[Qe(\" total: \"+Re(K(Fo)(c.value.totalTime)),1)]),_:1},8,[\"type\"])]),_:1})):He(\"\",!0),K(s)&&\"transformTime\"in K(s)&&K(s).transformTime?(ie(),Ve(K(Qi),{key:2,class:\"inline\",\"cursor-help\":\"\"},{popper:We(()=>[Qe(\" It took \"+Re(K(Ed)(K(s).transformTime))+\" to transform this module by Vite plugins. \",1)]),default:We(()=>[Ne(Cs,{type:K(Xc)(K(s).transformTime)},{default:We(()=>[Qe(\" transform: \"+Re(K(Fo)(K(s).transformTime)),1)]),_:1},8,[\"type\"])]),_:1})):He(\"\",!0)])]),X(\"p\",wme,Re(e.id),1),Ne(_t,{icon:\"i-carbon-close\",absolute:\"\",\"top-5px\":\"\",\"right-5px\":\"\",\"text-2xl\":\"\",onClick:_[1]||(_[1]=W=>o(\"close\"))})]),K(s)?(ie(),ve(nt,{key:1},[X(\"div\",{grid:\"~ rows-[min-content_auto]\",\"overflow-hidden\":\"\",\"flex-auto\":\"\",class:ot({\"cols-2\":p.value!=null})},[_[8]||(_[8]=X(\"div\",{p:\"x3 y-1\",\"bg-overlay\":\"\",border:\"base b t r\"},\" Source \",-1)),p.value!=null?(ie(),ve(\"div\",kme,\" Transformed \")):He(\"\",!0),(ie(),Ve(tu,ki({key:e.id,\"h-full\":\"\",\"model-value\":d.value,\"read-only\":\"\"},{lineNumbers:!0},{mode:f.value,onCodemirror:_[2]||(_[2]=W=>M(W))}),null,16,[\"model-value\",\"mode\"])),p.value!=null?(ie(),Ve(tu,ki({key:1,\"h-full\":\"\",\"model-value\":p.value,\"read-only\":\"\"},{lineNumbers:!0},{mode:\"js\"}),null,16,[\"model-value\"])):He(\"\",!0)],2),g.value.mappings!==\"\"?(ie(),ve(\"div\",Sme,[X(\"div\",_me,\" Source map (v\"+Re(g.value.version)+\") \",1),Ne(tu,ki({\"model-value\":g.value.mappings,\"read-only\":\"\"},{lineNumbers:!0}),null,16,[\"model-value\"])])):He(\"\",!0)],64)):(ie(),ve(\"div\",xme,\" No transform result found for this module. \"))])}}}),Cme={\"h-full\":\"\",\"min-h-75\":\"\",\"flex-1\":\"\",overflow:\"hidden\"},Eme={flex:\"\",\"items-center\":\"\",\"gap-2\":\"\",\"px-3\":\"\",\"py-2\":\"\"},Ame={flex:\"~ gap-1\",\"items-center\":\"\",\"select-none\":\"\"},Lme={class:\"pr-2\"},Mme=[\"id\",\"checked\",\"onChange\"],Nme=[\"for\"],Ome={key:0,class:\"absolute bg-[#eee] dark:bg-[#222] border-base right-0 mr-2 rounded-xl mt-2\"},Pme=rt({__name:\"ViewModuleGraph\",props:da({graph:{},projectName:{}},{modelValue:{type:Boolean,required:!0},modelModifiers:{}}),emits:[\"update:modelValue\"],setup(e){const t=e,r=Yu(e,\"modelValue\"),{graph:o}=v_(t),s=Ge(),c=Ge(!1),f=Ge(),d=qE(f),h=Ge(),p=Ge(null),g=Ft(o.value),v=ke(()=>{let j=\"\";const N=pr.value?.importDurations||{};for(const O in N){const{totalTime:C}=N[O];if(C>=500){j=\"text-red\";break}else C>=100&&(j=\"text-orange\")}return j}),b=Ge(ei.value?.experimental?.printImportBreakdown??v.value===\"text-red\");Mi(()=>{g.value=L(o.value,null,2),ne()}),Ia(()=>{h.value?.shutdown()}),xt(o,()=>{g.value=L(o.value,p.value,2),ne()});function w(){g.value=o.value,ne()}function E(){b.value=!b.value}function L(j,N,O=2){if(!j.nodes.length||j.nodes.length<=50)return j;const C=new Map;j.nodes.forEach(Ae=>C.set(Ae.id,new Set)),j.links.forEach(Ae=>{const Ke=typeof Ae.source==\"object\"?Ae.source.id:String(Ae.source),je=typeof Ae.target==\"object\"?Ae.target.id:String(Ae.target);C.get(Ke)?.add(je),C.get(je)?.add(Ke)});let k;if(N)k=[N];else{const Ae=new Set(j.links.map(je=>typeof je.target==\"object\"?je.target.id:String(je.target))),Ke=j.nodes.filter(je=>je.type===\"inline\"&&!Ae.has(je.id));k=Ke.length>0?[Ke[0].id]:[j.nodes[0].id]}const z=new Set,B=k.map(Ae=>({id:Ae,level:0}));for(;B.length>0;){const{id:Ae,level:Ke}=B.shift();z.has(Ae)||Ke>O||(z.add(Ae),Ke<O&&(C.get(Ae)||new Set).forEach(Fe=>{z.has(Fe)||B.push({id:Fe,level:Ke+1})}))}const ce=new Map(j.nodes.map(Ae=>[Ae.id,Ae])),be=Array.from(z).map(Ae=>ce.get(Ae)).filter(Ae=>Ae!==void 0),Se=new Map(be.map(Ae=>[Ae.id,Ae])),Be=j.links.map(Ae=>{const Ke=typeof Ae.source==\"object\"?Ae.source.id:String(Ae.source),je=typeof Ae.target==\"object\"?Ae.target.id:String(Ae.target);if(z.has(Ke)&&z.has(je)){const Fe=Se.get(Ke),Pe=Se.get(je);if(Fe&&Pe)return{...Ae,source:Fe,target:Pe}}return null}).filter(Ae=>Ae!==null);return{nodes:be,links:Be}}function P(j,N){h.value?.filterNodesByType(N,j)}function M(j,N){f.value={id:j,type:N},c.value=!0}function R(){d.undo()}function I(){c.value=!1,d.clear()}function _(j){p.value=j,g.value=L(o.value,j,2),W(),ne()}function $(){p.value=null,g.value=L(o.value,null,2),W(),ne()}function W(){const j=g.value.nodes.map(C=>{let k,z;return C.id===p.value?(k=\"var(--color-node-focused)\",z=\"var(--color-node-focused)\"):C.type===\"inline\"?(k=C.color===\"var(--color-node-root)\"?\"var(--color-node-root)\":\"var(--color-node-inline)\",z=k):(k=\"var(--color-node-external)\",z=\"var(--color-node-external)\"),Ip({...C,color:k,label:C.label?{...C.label,color:z}:C.label})}),N=new Map(j.map(C=>[C.id,C])),O=g.value.links.map(C=>{const k=typeof C.source==\"object\"?C.source.id:String(C.source),z=typeof C.target==\"object\"?C.target.id:String(C.target);return{...C,source:N.get(k),target:N.get(z)}});g.value={nodes:j,links:O}}function ne(j=!1){if(h.value?.shutdown(),j&&!r.value){r.value=!0;return}if(!g.value||!s.value)return;const N=g.value.nodes.length;let O=1,C=.5;N>300?(O=.3,C=.2):N>200?(O=.4,C=.3):N>100?(O=.5,C=.3):N>50&&(O=.7,O=.4),h.value=new qge(s.value,g.value,hge({nodeRadius:10,autoResize:!0,simulation:{alphas:{initialize:1,resize:({newHeight:k,newWidth:z})=>k===0&&z===0?0:.05},forces:{collision:{radiusMultiplier:10},link:{length:140}}},marker:i1.Arrow(2),modifiers:{node:G},positionInitializer:o.value.nodes.length===1?Eh.Centered:Eh.Randomized,zoom:{initial:O,min:C,max:1.5}}))}const ee=j=>j.button===0,Z=j=>j.button===2;function G(j){if(gr)return;let N=0,O=0,C=0,k=!1;j.on(\"pointerdown\",(z,B)=>{!B.x||!B.y||(k=Z(z),!(!ee(z)&&!k)&&(N=B.x,O=B.y,C=Date.now()))}).on(\"pointerup\",(z,B)=>{if(!B.x||!B.y)return;const ce=Z(z);if(!ee(z)&&!ce||Date.now()-C>500)return;const be=B.x-N,Se=B.y-O;be**2+Se**2<100&&(!ce&&!z.shiftKey?M(B.id,B.type):(ce||z.shiftKey)&&(z.preventDefault(),B.type===\"inline\"&&_(B.id)))}).on(\"contextmenu\",z=>{z.preventDefault()})}return(j,N)=>{const O=vr(\"tooltip\");return ie(),ve(\"div\",Cme,[X(\"div\",null,[X(\"div\",Eme,[X(\"div\",Ame,[X(\"div\",Lme,Re(g.value.nodes.length)+\"/\"+Re(K(o).nodes.length)+\" \"+Re(g.value.nodes.length===1?\"module\":\"modules\"),1),at(X(\"input\",{id:\"hide-node-modules\",\"onUpdate:modelValue\":N[0]||(N[0]=C=>r.value=C),type:\"checkbox\"},null,512),[[Zb,r.value]]),N[9]||(N[9]=X(\"label\",{\"font-light\":\"\",\"text-sm\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",\"select-none\":\"\",truncate:\"\",for:\"hide-node-modules\",\"border-b-2\":\"\",border:\"$cm-namespace\"},\"Hide node_modules\",-1))]),(ie(!0),ve(nt,null,$n(h.value?.nodeTypes.sort(),C=>(ie(),ve(\"div\",{key:C,flex:\"~ gap-1\",\"items-center\":\"\",\"select-none\":\"\"},[X(\"input\",{id:`type-${C}`,type:\"checkbox\",checked:h.value?.nodeTypeFilter.includes(C),onChange:k=>P(C,k.target.checked)},null,40,Mme),X(\"label\",{\"font-light\":\"\",\"text-sm\":\"\",\"ws-nowrap\":\"\",\"overflow-hidden\":\"\",capitalize:\"\",\"select-none\":\"\",truncate:\"\",for:`type-${C}`,\"border-b-2\":\"\",style:zt({\"border-color\":`var(--color-node-${C})`})},Re(C)+\" Modules\",13,Nme)]))),128)),N[10]||(N[10]=X(\"div\",{\"flex-auto\":\"\"},null,-1)),N[11]||(N[11]=X(\"div\",{flex:\"~ gap-2\",\"items-center\":\"\",\"text-xs\":\"\",\"opacity-60\":\"\"},[X(\"span\",null,\"Click on node: details • Right-click/Shift: expand graph\")],-1)),X(\"div\",null,[at(Ne(_t,{icon:\"i-carbon-notebook\",class:ot(v.value),onClick:N[1]||(N[1]=C=>E())},null,8,[\"class\"]),[[O,`${b.value?\"Hide\":\"Show\"} Import Breakdown`,void 0,{bottom:!0}]])]),X(\"div\",null,[at(Ne(_t,{icon:\"i-carbon-ibm-cloud-direct-link-2-connect\",onClick:N[2]||(N[2]=C=>w())},null,512),[[O,\"Show Full Graph\",void 0,{bottom:!0}]])]),X(\"div\",null,[at(Ne(_t,{icon:\"i-carbon-reset\",onClick:N[3]||(N[3]=C=>$())},null,512),[[O,\"Reset\",void 0,{bottom:!0}]])])])]),b.value?(ie(),ve(\"div\",Ome,[Ne(gme,{onSelect:N[4]||(N[4]=(C,k)=>M(C,k))})])):He(\"\",!0),X(\"div\",{ref_key:\"el\",ref:s},null,512),Ne(Dp,{modelValue:c.value,\"onUpdate:modelValue\":N[8]||(N[8]=C=>c.value=C),direction:\"right\"},{default:We(()=>[f.value?(ie(),Ve(np,{key:0},{default:We(()=>[Ne(Tme,{id:f.value.id,\"project-name\":e.projectName,type:f.value.type,\"can-undo\":K(d).undoStack.value.length>1,onClose:N[5]||(N[5]=C=>I()),onSelect:N[6]||(N[6]=(C,k)=>M(C,k)),onBack:N[7]||(N[7]=C=>R())},null,8,[\"id\",\"project-name\",\"type\",\"can-undo\"])]),_:1})):He(\"\",!0)]),_:1},8,[\"modelValue\"])])}}});function h1(e){const t=e.meta?.failScreenshotPath;t&&fetch(`/__open-in-editor?file=${encodeURIComponent(t)}`)}function p1(){const e=Ge(!1),t=Ge(Date.now()),r=Ge(),o=ke(()=>{const c=r.value?.id,f=t.value;return c?`/__screenshot-error?id=${encodeURIComponent(c)}&t=${f}`:void 0});function s(c){r.value=c,t.value=Date.now(),e.value=!0}return{currentTask:r,showScreenshot:e,currentScreenshotUrl:o,showScreenshotModal:s}}const Rme={\"w-350\":\"\",\"max-w-screen\":\"\",\"h-full\":\"\",flex:\"\",\"flex-col\":\"\"},$me={\"p-4\":\"\",relative:\"\",border:\"base b\"},Ime={op50:\"\",\"font-mono\":\"\",\"text-sm\":\"\"},Dme={op50:\"\",\"font-mono\":\"\",\"text-sm\":\"\"},zme={class:\"scrolls\",grid:\"~ cols-1 rows-[min-content]\",\"p-4\":\"\"},Fme=[\"src\",\"alt\"],Hme={key:1},Bme=rt({__name:\"ScreenshotError\",props:{file:{},name:{},url:{}},emits:[\"close\"],setup(e,{emit:t}){const r=t;return Cw(\"Escape\",()=>{r(\"close\")}),(o,s)=>(ie(),ve(\"div\",Rme,[X(\"div\",$me,[s[1]||(s[1]=X(\"p\",null,\"Screenshot error\",-1)),X(\"p\",Ime,Re(e.file),1),X(\"p\",Dme,Re(e.name),1),Ne(_t,{icon:\"i-carbon:close\",title:\"Close\",absolute:\"\",\"top-5px\":\"\",\"right-5px\":\"\",\"text-2xl\":\"\",onClick:s[0]||(s[0]=c=>r(\"close\"))})]),X(\"div\",zme,[e.url?(ie(),ve(\"img\",{key:0,src:e.url,alt:`Screenshot error for '${e.name}' test in file '${e.file}'`,border:\"base t r b l dotted red-500\"},null,8,Fme)):(ie(),ve(\"div\",Hme,\" Something was wrong, the image cannot be resolved. \"))])]))}}),g1=Ni(Bme,[[\"__scopeId\",\"data-v-08ce44b7\"]]),Wme={class:\"scrolls scrolls-rounded task-error\"},qme=[\"onClickPassive\"],jme=[\"innerHTML\"],Ume=rt({__name:\"ViewReportError\",props:{fileId:{},root:{},filename:{},error:{}},setup(e){const t=e;function r(d){return d.startsWith(t.root)?d.slice(t.root.length):d}const o=ke(()=>wp(ol.value)),s=ke(()=>!!t.error?.diff),c=ke(()=>t.error.diff?o.value.toHtml(oa(t.error.diff)):void 0);function f(d){return oce(d.file,t.filename)?pce(t.fileId,d):bp(d.file,d.line,d.column)}return(d,h)=>{const p=vr(\"tooltip\");return ie(),ve(\"div\",Wme,[X(\"pre\",null,[X(\"b\",null,Re(e.error.name),1),Qe(\": \"+Re(e.error.message),1)]),(ie(!0),ve(nt,null,$n(e.error.stacks,(g,v)=>(ie(),ve(\"div\",{key:v,class:\"op80 flex gap-x-2 items-center\",\"data-testid\":\"stack\"},[X(\"pre\",null,\" - \"+Re(r(g.file))+\":\"+Re(g.line)+\":\"+Re(g.column),1),at(X(\"div\",{class:\"i-carbon-launch c-red-600 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em\",tabindex:\"0\",\"aria-label\":\"Open in Editor\",onClickPassive:b=>f(g)},null,40,qme),[[p,\"Open in Editor\",void 0,{bottom:!0}]])]))),128)),s.value?(ie(),ve(\"pre\",{key:0,\"data-testid\":\"diff\",innerHTML:c.value},null,8,jme)):He(\"\",!0)])}}}),m1=Ni(Ume,[[\"__scopeId\",\"data-v-1fcfe7a4\"]]),Vme={\"h-full\":\"\",class:\"scrolls\"},Gme=[\"id\"],Kme={flex:\"~ gap-2 items-center\"},Xme={key:0,class:\"scrolls scrolls-rounded task-error\",\"data-testid\":\"task-error\"},Yme=[\"innerHTML\"],Zme={key:1,bg:\"green-500/10\",text:\"green-500 sm\",p:\"x4 y2\",\"m-2\":\"\",rounded:\"\"},Jme=rt({__name:\"ViewReport\",props:{file:{}},setup(e){const t=e;function r(h,p){return h.result?.state!==\"fail\"?[]:h.type===\"test\"?[{...h,level:p}]:[{...h,level:p},...h.tasks.flatMap(g=>r(g,p+1))]}const o=ke(()=>{const h=t.file,p=h.tasks?.flatMap(b=>r(b,0))??[],g=h.result;if(g?.errors?.[0]){const b={id:h.id,file:h,name:h.name,fullName:h.name,level:0,type:\"suite\",mode:\"run\",meta:{},tasks:[],result:g};p.unshift(b)}return p.length>0?dx(ol.value,p):p}),{currentTask:s,showScreenshot:c,showScreenshotModal:f,currentScreenshotUrl:d}=p1();return(h,p)=>{const g=vr(\"tooltip\");return ie(),ve(\"div\",Vme,[o.value.length?(ie(!0),ve(nt,{key:0},$n(o.value,v=>(ie(),ve(\"div\",{id:v.id,key:v.id},[X(\"div\",{bg:\"red-500/10\",text:\"red-500 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\",style:zt({\"margin-left\":`${v.result?.htmlError?.5:2*v.level+.5}rem`})},[X(\"div\",Kme,[X(\"span\",null,Re(v.name),1),K(Zn)&&v.meta?.failScreenshotPath?(ie(),ve(nt,{key:0},[at(Ne(_t,{class:\"!op-100\",icon:\"i-carbon:image\",title:\"View screenshot error\",onClick:b=>K(f)(v)},null,8,[\"onClick\"]),[[g,\"View screenshot error\",void 0,{bottom:!0}]]),at(Ne(_t,{class:\"!op-100\",icon:\"i-carbon:image-reference\",title:\"Open screenshot error in editor\",onClick:b=>K(h1)(v)},null,8,[\"onClick\"]),[[g,\"Open screenshot error in editor\",void 0,{bottom:!0}]])],64)):He(\"\",!0)]),v.result?.htmlError?(ie(),ve(\"div\",Xme,[X(\"pre\",{innerHTML:v.result.htmlError},null,8,Yme)])):v.result?.errors?(ie(!0),ve(nt,{key:1},$n(v.result.errors,(b,w)=>(ie(),Ve(m1,{key:w,error:b,filename:e.file.name,root:K(ei).root,\"file-id\":e.file.id},null,8,[\"error\",\"filename\",\"root\",\"file-id\"]))),128)):He(\"\",!0)],4)],8,Gme))),128)):(ie(),ve(\"div\",Zme,\" All tests passed in this file \")),K(Zn)?(ie(),Ve(Dp,{key:2,modelValue:K(c),\"onUpdate:modelValue\":p[1]||(p[1]=v=>Mt(c)?c.value=v:null),direction:\"right\"},{default:We(()=>[K(s)?(ie(),Ve(np,{key:0},{default:We(()=>[Ne(g1,{file:K(s).file.filepath,name:K(s).name,url:K(d),onClose:p[0]||(p[0]=v=>c.value=!1)},null,8,[\"file\",\"name\",\"url\"])]),_:1})):He(\"\",!0)]),_:1},8,[\"modelValue\"])):He(\"\",!0)])}}}),Qme=Ni(Jme,[[\"__scopeId\",\"data-v-9d875d6e\"]]),eve=[\"href\",\"referrerPolicy\"],tve=[\"src\"],nve=rt({__name:\"AnnotationAttachmentImage\",props:{annotation:{}},setup(e){const t=e,r=ke(()=>{const o=t.annotation.attachment,s=o.path||o.body;return typeof s==\"string\"&&(s.startsWith(\"http://\")||s.startsWith(\"https://\"))?s:Ma(o)});return(o,s)=>e.annotation.attachment&&e.annotation.attachment.contentType?.startsWith(\"image/\")?(ie(),ve(\"a\",{key:0,target:\"_blank\",class:\"inline-block mt-2\",style:{maxWidth:\"600px\"},href:r.value,referrerPolicy:K(d1)(e.annotation.attachment)?\"no-referrer\":void 0},[X(\"img\",{src:r.value},null,8,tve)],8,eve)):He(\"\",!0)}}),rve={class:\"flex flex-col gap-4\"},ive={key:0},ove=rt({__name:\"ArtifactTemplate\",setup(e){const t=yb();return(r,o)=>(ie(),ve(\"article\",rve,[X(\"h1\",null,[Dt(r.$slots,\"title\")]),K(t).message?(ie(),ve(\"p\",ive,[Dt(r.$slots,\"message\")])):He(\"\",!0),Dt(r.$slots,\"default\")]))}}),v1=Symbol(\"tabContext\"),Ru={tab:(e,t)=>`${t}-${e}-tab`,tabpanel:(e,t)=>`${t}-${e}-tabpanel`},sve={class:\"flex flex-col items-center gap-6\"},lve={role:\"tablist\",\"aria-orientation\":\"horizontal\",class:\"flex gap-4\"},ave=[\"id\",\"aria-selected\",\"aria-controls\",\"onClick\"],cve=rt({__name:\"SmallTabs\",setup(e){const t=Ge(null),r=Ge([]),o=Yh();return dr(v1,{id:o,activeTab:t,registerTab:s=>{r.value.some(({id:c})=>c===s.id)||r.value.push(s),r.value.length===1&&(t.value=s.id)},unregisterTab:s=>{const c=r.value.findIndex(({id:f})=>f===s.id);c>-1&&r.value.splice(c,1),t.value===s.id&&(t.value=r.value[0]?.id??null)}}),(s,c)=>(ie(),ve(\"div\",sve,[X(\"div\",lve,[(ie(!0),ve(nt,null,$n(r.value,f=>(ie(),ve(\"button\",{id:K(Ru).tab(f.id,K(o)),key:f.id,role:\"tab\",\"aria-selected\":t.value===f.id,\"aria-controls\":K(Ru).tabpanel(f.id,K(o)),type:\"button\",class:\"aria-[selected=true]:underline underline-offset-4\",onClick:d=>t.value=f.id},Re(f.title),9,ave))),128))]),Dt(s.$slots,\"default\")]))}}),uve=[\"id\",\"aria-labelledby\",\"hidden\"],Bc=rt({__name:\"SmallTabsPane\",props:{title:{}},setup(e){const t=e,r=pn(v1);if(!r)throw new Error(\"TabPane must be used within Tabs\");const o=Yh(),s=ke(()=>r.activeTab.value===o);return Mi(()=>{r.registerTab({...t,id:o})}),Ia(()=>{r.unregisterTab({...t,id:o})}),(c,f)=>(ie(),ve(\"div\",{id:K(Ru).tabpanel(K(o),K(r).id),role:\"tabpanel\",\"aria-labelledby\":K(Ru).tab(K(o),K(r).id),hidden:!s.value,class:\"max-w-full\"},[Dt(c.$slots,\"default\")],8,uve))}}),y1=rt({__name:\"VisualRegressionImageContainer\",setup(e){const t=`url(\"${CSS.escape('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 2 2\"><path d=\"M1 2V0h1v1H0v1z\" fill-opacity=\".05\"/></svg>')}\")`;return(r,o)=>(ie(),ve(\"div\",{class:\"max-w-full w-fit mx-auto bg-[size:16px_16px] bg-[#fafafa] dark:bg-[#3a3a3a] bg-center p-4 rounded user-select-none outline-0 outline-black dark:outline-white outline-offset-4 outline-solid focus-within:has-focus-visible:outline-2\",style:zt({backgroundImage:t})},[Dt(r.$slots,\"default\")],4))}}),fve=[\"href\",\"referrerPolicy\"],dve=[\"src\"],zd=rt({__name:\"VisualRegressionImage\",props:{attachment:{}},setup(e){const t=ke(()=>Mh(e.attachment));return(r,o)=>(ie(),Ve(y1,null,{default:We(()=>[X(\"a\",{target:\"_blank\",href:t.value,referrerPolicy:K(d1)(e.attachment)?\"no-referrer\":void 0},[X(\"img\",{src:t.value},null,8,dve)],8,fve)]),_:1}))}}),hve={class:\"absolute w-full h-full place-content-center place-items-center [clip-path:polygon(0%_0%,var(--split)_0%,var(--split)_100%,0%_100%)]\",\"aria-hidden\":\"true\",role:\"presentation\"},pve=[\"src\"],gve={class:\"absolute w-full h-full place-content-center place-items-center [clip-path:polygon(var(--split)_0%,100%_0%,100%_100%,var(--split)_100%)]\",\"aria-hidden\":\"true\",role:\"presentation\"},mve=[\"src\"],vve=[\"id\"],yve=[\"for\"],bve=rt({__name:\"VisualRegressionSlider\",props:{reference:{},actual:{}},setup(e){const t=ke(()=>Mh(e.reference)),r=ke(()=>Mh(e.actual)),o=ke(()=>Math.max(e.reference.width,e.actual.width)),s=ke(()=>Math.max(e.reference.height,e.actual.height)),c=Ge(50),f=Yh();return(d,h)=>(ie(),Ve(y1,null,{default:We(()=>[X(\"div\",{\"aria-label\":\"Image comparison slider showing reference and actual screenshots\",class:\"relative max-w-full h-full overflow-hidden\",style:zt({\"--split\":`${c.value}%`,aspectRatio:`${o.value} / ${s.value}`,width:`${o.value}px`})},[X(\"div\",hve,[X(\"img\",{src:t.value},null,8,pve)]),X(\"div\",gve,[X(\"img\",{src:r.value},null,8,mve)]),h[1]||(h[1]=X(\"div\",{class:\"absolute left-[--split] h-full w-[2px] -translate-x-1/2 bg-white shadow-[0_0_3px_rgb(0_0_0/.2),0_0_10px_rgb(0_0_0/.5)] before:content-[''] before:absolute before:top-1/2 before:size-[16px] before:bg-white before:border-[2px] before:border-black before:rounded-full before:-translate-y-1/2 before:translate-x-[calc(-50%+1px)]\",\"aria-hidden\":\"true\",role:\"presentation\"},null,-1)),at(X(\"input\",{id:K(f),\"onUpdate:modelValue\":h[0]||(h[0]=p=>c.value=p),type:\"range\",min:\"0\",max:\"100\",step:\"0.1\",\"aria-label\":\"Adjust slider to compare reference and actual images\",class:\"absolute inset-0 opacity-0 cursor-col-resize\"},null,8,vve),[[Yb,c.value]]),X(\"output\",{for:K(f),class:\"sr-only\"},\" Showing \"+Re(c.value)+\"% reference, \"+Re(100-c.value)+\"% actual \",9,yve)],4)]),_:1}))}}),wve=rt({__name:\"VisualRegression\",props:{regression:{}},setup(e){const t=ke(()=>({diff:e.regression.attachments.find(r=>r.name===\"diff\"),reference:e.regression.attachments.find(r=>r.name===\"reference\"),actual:e.regression.attachments.find(r=>r.name===\"actual\")}));return(r,o)=>(ie(),Ve(ove,null,{title:We(()=>[...o[0]||(o[0]=[Qe(\" Visual Regression \",-1)])]),message:We(()=>[Qe(Re(e.regression.message),1)]),default:We(()=>[Ne(cve,null,{default:We(()=>[t.value.diff?(ie(),Ve(Bc,{key:t.value.diff.path,title:\"Diff\"},{default:We(()=>[Ne(zd,{attachment:t.value.diff},null,8,[\"attachment\"])]),_:1})):He(\"\",!0),t.value.reference?(ie(),Ve(Bc,{key:t.value.reference.path,title:\"Reference\"},{default:We(()=>[Ne(zd,{attachment:t.value.reference},null,8,[\"attachment\"])]),_:1})):He(\"\",!0),t.value.actual?(ie(),Ve(Bc,{key:t.value.actual.path,title:\"Actual\"},{default:We(()=>[Ne(zd,{attachment:t.value.actual},null,8,[\"attachment\"])]),_:1})):He(\"\",!0),t.value.reference&&t.value.actual?(ie(),Ve(Bc,{key:(t.value.reference.path??\"\")+(t.value.actual.path??\"\"),title:\"Slider\"},{default:We(()=>[Ne(bve,{actual:t.value.actual,reference:t.value.reference},null,8,[\"actual\",\"reference\"])]),_:1})):He(\"\",!0)]),_:1})]),_:1}))}}),xve={\"h-full\":\"\",class:\"scrolls\"},kve={key:0},Sve={bg:\"red-500/10\",text:\"red-500 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\"},_ve={flex:\"~ gap-2 items-center\"},Tve={key:0,class:\"scrolls scrolls-rounded task-error\",\"data-testid\":\"task-error\"},Cve=[\"innerHTML\"],Eve={key:1,bg:\"green-500/10\",text:\"green-500 sm\",p:\"x4 y2\",\"m-2\":\"\",rounded:\"\"},Ave={flex:\"~ gap-2 items-center justify-between\",\"overflow-hidden\":\"\"},Lve={class:\"flex gap-2\",\"overflow-hidden\":\"\"},Mve={class:\"font-bold\",\"ws-nowrap\":\"\",truncate:\"\"},Nve=[\"href\",\"download\"],Ove=[\"onClick\"],Pve={key:1,class:\"flex gap-1 text-yellow-500/80\",\"ws-nowrap\":\"\"},Rve={class:\"scrolls scrolls-rounded task-error\",\"data-testid\":\"task-error\"},$ve={flex:\"~ gap-2 items-center justify-between\",\"overflow-hidden\":\"\"},Ive=[\"onClick\"],Dve={key:1,class:\"flex gap-1 text-yellow-500/80\",\"ws-nowrap\":\"\"},zve={bg:\"gray/10\",text:\"black-100 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\",class:\"grid grid-cols-1 md:grid-cols-[200px_1fr] gap-2\",\"overflow-hidden\":\"\"},Fve={\"font-bold\":\"\",\"ws-nowrap\":\"\",truncate:\"\",\"py-2\":\"\"},Hve={\"overflow-auto\":\"\",bg:\"gray/30\",rounded:\"\",\"p-2\":\"\"},Bve=rt({__name:\"ViewTestReport\",props:{test:{}},setup(e){const t=e,r=ke(()=>!t.test.result||!t.test.result.errors?.length?null:dx(ol.value,[t.test])[0]);function o(v){return gce(t.test,v)}const{currentTask:s,showScreenshot:c,showScreenshotModal:f,currentScreenshotUrl:d}=p1();function h(v){return`${af(ei.value.root,v.file)}:${v.line}:${v.column}`}const p=new Set([\"benchmark\",\"typecheck\",\"failScreenshotPath\"]),g=ke(()=>Object.entries(t.test.meta).filter(([v])=>!p.has(v)));return(v,b)=>{const w=vr(\"tooltip\");return ie(),ve(\"div\",xve,[r.value?(ie(),ve(\"div\",kve,[X(\"div\",Sve,[X(\"div\",_ve,[K(Zn)&&e.test.meta?.failScreenshotPath?(ie(),ve(nt,{key:0},[at(Ne(_t,{class:\"!op-100\",icon:\"i-carbon:image\",title:\"View screenshot error\",onClick:b[0]||(b[0]=E=>K(f)(e.test))},null,512),[[w,\"View screenshot error\",void 0,{bottom:!0}]]),at(Ne(_t,{class:\"!op-100\",icon:\"i-carbon:image-reference\",title:\"Open screenshot error in editor\",onClick:b[1]||(b[1]=E=>K(h1)(e.test))},null,512),[[w,\"Open screenshot error in editor\",void 0,{bottom:!0}]])],64)):He(\"\",!0)]),e.test.result?.htmlError?(ie(),ve(\"div\",Tve,[X(\"pre\",{innerHTML:e.test.result.htmlError},null,8,Cve)])):e.test.result?.errors?(ie(!0),ve(nt,{key:1},$n(e.test.result.errors,(E,L)=>(ie(),Ve(m1,{key:L,\"file-id\":e.test.file.id,error:E,filename:e.test.file.name,root:K(ei).root},null,8,[\"file-id\",\"error\",\"filename\",\"root\"]))),128)):He(\"\",!0)])])):(ie(),ve(\"div\",Eve,\" All tests passed in this file \")),e.test.annotations.length?(ie(),ve(nt,{key:2},[b[5]||(b[5]=X(\"h1\",{\"m-2\":\"\"},\" Test Annotations \",-1)),(ie(!0),ve(nt,null,$n(e.test.annotations,E=>(ie(),ve(\"div\",{key:E.type+E.message,bg:\"yellow-500/10\",text:\"yellow-500 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\",role:\"note\"},[X(\"div\",Ave,[X(\"div\",Lve,[X(\"span\",Mve,Re(E.type),1),E.attachment&&!E.attachment.contentType?.startsWith(\"image/\")?(ie(),ve(\"a\",{key:0,class:\"flex gap-1 items-center text-yellow-500/80 cursor-pointer\",href:K(Ma)(E.attachment),download:K(f1)(E.message,E.attachment.contentType)},[...b[4]||(b[4]=[X(\"span\",{class:\"i-carbon:download block\"},null,-1),Qe(\" Download \",-1)])],8,Nve)):He(\"\",!0)]),X(\"div\",null,[E.location&&E.location.file===e.test.file.filepath?at((ie(),ve(\"span\",{key:0,title:\"Open in Editor\",class:\"flex gap-1 text-yellow-500/80 cursor-pointer\",\"ws-nowrap\":\"\",onClick:L=>o(E.location)},[Qe(Re(h(E.location)),1)],8,Ove)),[[w,\"Open in Editor\",void 0,{bottom:!0}]]):E.location&&E.location.file!==e.test.file.filepath?(ie(),ve(\"span\",Pve,Re(h(E.location)),1)):He(\"\",!0)])]),X(\"div\",Rve,Re(E.message),1),Ne(nve,{annotation:E},null,8,[\"annotation\"])]))),128))],64)):He(\"\",!0),e.test.artifacts.length?(ie(),ve(nt,{key:3},[b[6]||(b[6]=X(\"h1\",{\"m-2\":\"\"},\" Test Artifacts \",-1)),(ie(!0),ve(nt,null,$n(e.test.artifacts,(E,L)=>(ie(),ve(\"div\",{key:E.type+L,bg:\"yellow-500/10\",text:\"yellow-500 sm\",p:\"x3 y2\",\"m-2\":\"\",rounded:\"\",role:\"note\"},[X(\"div\",$ve,[X(\"div\",null,[E.location&&E.location.file===e.test.file.filepath?at((ie(),ve(\"span\",{key:0,title:\"Open in Editor\",class:\"flex gap-1 text-yellow-500/80 cursor-pointer\",\"ws-nowrap\":\"\",onClick:P=>o(E.location)},[Qe(Re(h(E.location)),1)],8,Ive)),[[w,\"Open in Editor\",void 0,{bottom:!0}]]):E.location&&E.location.file!==e.test.file.filepath?(ie(),ve(\"span\",Dve,Re(h(E.location)),1)):He(\"\",!0)])]),E.type===\"internal:toMatchScreenshot\"&&E.kind===\"visual-regression\"?(ie(),Ve(wve,{key:0,regression:E},null,8,[\"regression\"])):He(\"\",!0)]))),128))],64)):He(\"\",!0),g.value.length?(ie(),ve(nt,{key:4},[b[7]||(b[7]=X(\"h1\",{\"m-2\":\"\"},\" Test Meta \",-1)),X(\"div\",zve,[(ie(!0),ve(nt,null,$n(g.value,([E,L])=>(ie(),ve(nt,{key:E},[X(\"div\",Fve,Re(E),1),X(\"pre\",Hve,Re(L),1)],64))),128))])],64)):He(\"\",!0),K(Zn)?(ie(),Ve(Dp,{key:5,modelValue:K(c),\"onUpdate:modelValue\":b[3]||(b[3]=E=>Mt(c)?c.value=E:null),direction:\"right\"},{default:We(()=>[K(s)?(ie(),Ve(np,{key:0},{default:We(()=>[Ne(g1,{file:K(s).file.filepath,name:K(s).name,url:K(d),onClose:b[2]||(b[2]=E=>c.value=!1)},null,8,[\"file\",\"name\",\"url\"])]),_:1})):He(\"\",!0)]),_:1},8,[\"modelValue\"])):He(\"\",!0)])}}}),Wve=Ni(Bve,[[\"__scopeId\",\"data-v-1a68630b\"]]),qve={key:0,flex:\"\",\"flex-col\":\"\",\"h-full\":\"\",\"max-h-full\":\"\",\"overflow-hidden\":\"\",\"data-testid\":\"file-detail\"},jve={p:\"2\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},Uve={key:0,class:\"i-logos:typescript-icon\",\"flex-shrink-0\":\"\"},Vve={\"flex-1\":\"\",\"font-light\":\"\",\"op-50\":\"\",\"ws-nowrap\":\"\",truncate:\"\",\"text-sm\":\"\"},Gve={class:\"flex text-lg\"},Kve={flex:\"~\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b-2 base\",\"text-sm\":\"\",\"h-41px\":\"\"},Xve={key:0,class:\"block w-1.4em h-1.4em i-carbon:circle-dash animate-spin animate-2s\"},Yve={key:1,class:\"block w-1.4em h-1.4em i-carbon:chart-relationship\"},Zve={flex:\"\",\"flex-col\":\"\",\"flex-1\":\"\",overflow:\"hidden\"},Jve=[\"flex-1\"],l0=rt({__name:\"FileDetails\",setup(e){const t=Ge({nodes:[],links:[]}),r=Ge(!1),o=Ge(!1),s=Ge(!1),c=Ge(void 0),f=Ge(!0),d=ke(()=>Bs.value?ft.state.idMap.get(Bs.value):void 0),h=ke(()=>{const _=Gt.value;if(!(!_||!_.filepath))return{filepath:_.filepath,projectName:_.file.projectName||\"\"}}),p=ke(()=>Gt.value&&yp(Gt.value)),g=ke(()=>!!Gt.value?.meta?.typecheck);function v(){const _=Gt.value?.filepath;_&&fetch(`/__open-in-editor?file=${encodeURIComponent(_)}`)}function b(_){_===\"graph\"&&(o.value=!0),hn.value=_}const w=ke(()=>Tx.value?.reduce((_,{size:$})=>_+$,0)??0);function E(_){r.value=_}const L=/[/\\\\]node_modules[/\\\\]/;async function P(_=!1){if(!(s.value||h.value?.filepath===c.value&&!_)){s.value=!0,await Et();try{const $=h.value;if(!$){s.value=!1;return}if(_||!c.value||$.filepath!==c.value||!t.value.nodes.length&&!t.value.links.length){let W=await ft.rpc.getModuleGraph($.projectName,$.filepath,!!Zn);f.value&&(gr&&(W=typeof window.structuredClone<\"u\"?window.structuredClone(W):KA(W)),W.inlined=W.inlined.filter(ne=>!L.test(ne)),W.externalized=W.externalized.filter(ne=>!L.test(ne))),t.value=Gge(W,$.filepath),c.value=$.filepath}b(\"graph\")}finally{await new Promise($=>setTimeout($,100)),s.value=!1}}}hp(()=>[h.value,hn.value,f.value],([,_,$],W)=>{_===\"graph\"&&P(W&&$!==W[2])},{debounce:100,immediate:!0});const M=ke(()=>{const _=Gt.value?.file.projectName||\"\";return Oe.colors.get(_)||Qw(Gt.value?.file.projectName)}),R=ke(()=>ex(M.value)),I=ke(()=>{const _=Bs.value;if(!_)return Gt.value?.name;const $=[];let W=ft.state.idMap.get(_);for(;W;)$.push(W.name),W=W.suite?W.suite:W===W.file?void 0:W.file;return $.reverse().join(\" > \")});return(_,$)=>{const W=vr(\"tooltip\");return K(Gt)?(ie(),ve(\"div\",qve,[X(\"div\",null,[X(\"div\",jve,[Ne(c1,{state:K(Gt).result?.state,mode:K(Gt).mode,\"failed-snapshot\":p.value},null,8,[\"state\",\"mode\",\"failed-snapshot\"]),g.value?at((ie(),ve(\"div\",Uve,null,512)),[[W,\"This is a typecheck test. It won't report results of the runtime tests\",void 0,{bottom:!0}]]):He(\"\",!0),K(Gt)?.file.projectName?(ie(),ve(\"span\",{key:1,class:\"rounded-full py-0.5 px-2 text-xs font-light\",style:zt({backgroundColor:M.value,color:R.value})},Re(K(Gt).file.projectName),5)):He(\"\",!0),X(\"div\",Vve,Re(I.value),1),X(\"div\",Gve,[K(gr)?He(\"\",!0):at((ie(),Ve(_t,{key:0,title:\"Open in editor\",icon:\"i-carbon-launch\",disabled:!K(Gt)?.filepath,onClick:v},null,8,[\"disabled\"])),[[W,\"Open in editor\",void 0,{bottom:!0}]])])]),X(\"div\",Kve,[X(\"button\",{\"tab-button\":\"\",class:ot([\"flex items-center gap-2\",{\"tab-button-active\":K(hn)==null}]),\"data-testid\":\"btn-report\",onClick:$[0]||($[0]=ne=>b(null))},[...$[5]||($[5]=[X(\"span\",{class:\"block w-1.4em h-1.4em i-carbon:report\"},null,-1),Qe(\" Report \",-1)])],2),X(\"button\",{\"tab-button\":\"\",\"data-testid\":\"btn-graph\",class:ot([\"flex items-center gap-2\",{\"tab-button-active\":K(hn)===\"graph\"}]),onClick:$[1]||($[1]=ne=>b(\"graph\"))},[s.value?(ie(),ve(\"span\",Xve)):(ie(),ve(\"span\",Yve)),$[6]||($[6]=Qe(\" Module Graph \",-1))],2),X(\"button\",{\"tab-button\":\"\",\"data-testid\":\"btn-code\",class:ot([\"flex items-center gap-2\",{\"tab-button-active\":K(hn)===\"editor\"}]),onClick:$[2]||($[2]=ne=>b(\"editor\"))},[$[7]||($[7]=X(\"span\",{class:\"block w-1.4em h-1.4em i-carbon:code\"},null,-1)),Qe(\" \"+Re(r.value?\"* \":\"\")+\"Code \",1)],2),X(\"button\",{\"tab-button\":\"\",\"data-testid\":\"btn-console\",class:ot([\"flex items-center gap-2\",{\"tab-button-active\":K(hn)===\"console\",op20:K(hn)!==\"console\"&&w.value===0}]),onClick:$[3]||($[3]=ne=>b(\"console\"))},[$[8]||($[8]=X(\"span\",{class:\"block w-1.4em h-1.4em i-carbon:terminal-3270\"},null,-1)),Qe(\" Console (\"+Re(w.value)+\") \",1)],2)])]),X(\"div\",Zve,[o.value?(ie(),ve(\"div\",{key:0,\"flex-1\":K(hn)===\"graph\"&&\"\"},[at(Ne(Pme,{modelValue:f.value,\"onUpdate:modelValue\":$[4]||($[4]=ne=>f.value=ne),graph:t.value,\"data-testid\":\"graph\",\"project-name\":K(Gt).file.projectName||\"\"},null,8,[\"modelValue\",\"graph\",\"project-name\"]),[[ro,K(hn)===\"graph\"&&!s.value]])],8,Jve)):He(\"\",!0),K(hn)===\"editor\"?(ie(),Ve(cme,{key:K(Gt).id,file:K(Gt),\"data-testid\":\"editor\",onDraft:E},null,8,[\"file\"])):K(hn)===\"console\"?(ie(),Ve(sme,{key:2,file:K(Gt),\"data-testid\":\"console\"},null,8,[\"file\"])):!K(hn)&&!d.value&&K(Gt)?(ie(),Ve(Qme,{key:3,file:K(Gt),\"data-testid\":\"report\"},null,8,[\"file\"])):!K(hn)&&d.value?(ie(),Ve(Wve,{key:4,test:d.value,\"data-testid\":\"report\"},null,8,[\"test\"])):He(\"\",!0)])])):He(\"\",!0)}}}),Qve=\"\"+new URL(\"../favicon.svg\",import.meta.url).href;function eye(){var e=window.navigator.userAgent,t=e.indexOf(\"MSIE \");if(t>0)return parseInt(e.substring(t+5,e.indexOf(\".\",t)),10);var r=e.indexOf(\"Trident/\");if(r>0){var o=e.indexOf(\"rv:\");return parseInt(e.substring(o+3,e.indexOf(\".\",o)),10)}var s=e.indexOf(\"Edge/\");return s>0?parseInt(e.substring(s+5,e.indexOf(\".\",s)),10):-1}let nu;function Nh(){Nh.init||(Nh.init=!0,nu=eye()!==-1)}var pf={name:\"ResizeObserver\",props:{emitOnMount:{type:Boolean,default:!1},ignoreWidth:{type:Boolean,default:!1},ignoreHeight:{type:Boolean,default:!1}},emits:[\"notify\"],mounted(){Nh(),Et(()=>{this._w=this.$el.offsetWidth,this._h=this.$el.offsetHeight,this.emitOnMount&&this.emitSize()});const e=document.createElement(\"object\");this._resizeObject=e,e.setAttribute(\"aria-hidden\",\"true\"),e.setAttribute(\"tabindex\",-1),e.onload=this.addResizeHandlers,e.type=\"text/html\",nu&&this.$el.appendChild(e),e.data=\"about:blank\",nu||this.$el.appendChild(e)},beforeUnmount(){this.removeResizeHandlers()},methods:{compareAndNotify(){(!this.ignoreWidth&&this._w!==this.$el.offsetWidth||!this.ignoreHeight&&this._h!==this.$el.offsetHeight)&&(this._w=this.$el.offsetWidth,this._h=this.$el.offsetHeight,this.emitSize())},emitSize(){this.$emit(\"notify\",{width:this._w,height:this._h})},addResizeHandlers(){this._resizeObject.contentDocument.defaultView.addEventListener(\"resize\",this.compareAndNotify),this.compareAndNotify()},removeResizeHandlers(){this._resizeObject&&this._resizeObject.onload&&(!nu&&this._resizeObject.contentDocument&&this._resizeObject.contentDocument.defaultView.removeEventListener(\"resize\",this.compareAndNotify),this.$el.removeChild(this._resizeObject),this._resizeObject.onload=null,this._resizeObject=null)}}};const tye=lb();ob(\"data-v-b329ee4c\");const nye={class:\"resize-observer\",tabindex:\"-1\"};sb();const rye=tye((e,t,r,o,s,c)=>(ie(),Ve(\"div\",nye)));pf.render=rye;pf.__scopeId=\"data-v-b329ee4c\";pf.__file=\"src/components/ResizeObserver.vue\";function ru(e){\"@babel/helpers - typeof\";return typeof Symbol==\"function\"&&typeof Symbol.iterator==\"symbol\"?ru=function(t){return typeof t}:ru=function(t){return t&&typeof Symbol==\"function\"&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},ru(e)}function iye(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}function oye(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,\"value\"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}function sye(e,t,r){return t&&oye(e.prototype,t),e}function a0(e){return lye(e)||aye(e)||cye(e)||uye()}function lye(e){if(Array.isArray(e))return Oh(e)}function aye(e){if(typeof Symbol<\"u\"&&Symbol.iterator in Object(e))return Array.from(e)}function cye(e,t){if(e){if(typeof e==\"string\")return Oh(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if(r===\"Object\"&&e.constructor&&(r=e.constructor.name),r===\"Map\"||r===\"Set\")return Array.from(e);if(r===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return Oh(e,t)}}function Oh(e,t){(t==null||t>e.length)&&(t=e.length);for(var r=0,o=new Array(t);r<t;r++)o[r]=e[r];return o}function uye(){throw new TypeError(`Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function fye(e){var t;return typeof e==\"function\"?t={callback:e}:t=e,t}function dye(e,t){var r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},o,s,c,f=function(h){for(var p=arguments.length,g=new Array(p>1?p-1:0),v=1;v<p;v++)g[v-1]=arguments[v];if(c=g,!(o&&h===s)){var b=r.leading;typeof b==\"function\"&&(b=b(h,s)),(!o||h!==s)&&b&&e.apply(void 0,[h].concat(a0(c))),s=h,clearTimeout(o),o=setTimeout(function(){e.apply(void 0,[h].concat(a0(c))),o=0},t)}};return f._clear=function(){clearTimeout(o),o=null},f}function b1(e,t){if(e===t)return!0;if(ru(e)===\"object\"){for(var r in e)if(!b1(e[r],t[r]))return!1;return!0}return!1}var hye=(function(){function e(t,r,o){iye(this,e),this.el=t,this.observer=null,this.frozen=!1,this.createObserver(r,o)}return sye(e,[{key:\"createObserver\",value:function(r,o){var s=this;if(this.observer&&this.destroyObserver(),!this.frozen){if(this.options=fye(r),this.callback=function(d,h){s.options.callback(d,h),d&&s.options.once&&(s.frozen=!0,s.destroyObserver())},this.callback&&this.options.throttle){var c=this.options.throttleOptions||{},f=c.leading;this.callback=dye(this.callback,this.options.throttle,{leading:function(h){return f===\"both\"||f===\"visible\"&&h||f===\"hidden\"&&!h}})}this.oldResult=void 0,this.observer=new IntersectionObserver(function(d){var h=d[0];if(d.length>1){var p=d.find(function(v){return v.isIntersecting});p&&(h=p)}if(s.callback){var g=h.isIntersecting&&h.intersectionRatio>=s.threshold;if(g===s.oldResult)return;s.oldResult=g,s.callback(g,h)}},this.options.intersection),Et(function(){s.observer&&s.observer.observe(s.el)})}}},{key:\"destroyObserver\",value:function(){this.observer&&(this.observer.disconnect(),this.observer=null),this.callback&&this.callback._clear&&(this.callback._clear(),this.callback=null)}},{key:\"threshold\",get:function(){return this.options.intersection&&typeof this.options.intersection.threshold==\"number\"?this.options.intersection.threshold:0}}]),e})();function w1(e,t,r){var o=t.value;if(o)if(typeof IntersectionObserver>\"u\")console.warn(\"[vue-observe-visibility] IntersectionObserver API is not available in your browser. Please install this polyfill: https://github.com/w3c/IntersectionObserver/tree/master/polyfill\");else{var s=new hye(e,o,r);e._vue_visibilityState=s}}function pye(e,t,r){var o=t.value,s=t.oldValue;if(!b1(o,s)){var c=e._vue_visibilityState;if(!o){x1(e);return}c?c.createObserver(o,r):w1(e,{value:o},r)}}function x1(e){var t=e._vue_visibilityState;t&&(t.destroyObserver(),delete e._vue_visibilityState)}var gye={beforeMount:w1,updated:pye,unmounted:x1},mye={itemsLimit:1e3},vye=/(auto|scroll)/;function k1(e,t){return e.parentNode===null?t:k1(e.parentNode,t.concat([e]))}var Fd=function(t,r){return getComputedStyle(t,null).getPropertyValue(r)},yye=function(t){return Fd(t,\"overflow\")+Fd(t,\"overflow-y\")+Fd(t,\"overflow-x\")},bye=function(t){return vye.test(yye(t))};function c0(e){if(e instanceof HTMLElement||e instanceof SVGElement){for(var t=k1(e.parentNode,[]),r=0;r<t.length;r+=1)if(bye(t[r]))return t[r];return document.scrollingElement||document.documentElement}}function Ph(e){\"@babel/helpers - typeof\";return Ph=typeof Symbol==\"function\"&&typeof Symbol.iterator==\"symbol\"?function(t){return typeof t}:function(t){return t&&typeof Symbol==\"function\"&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},Ph(e)}var wye={items:{type:Array,required:!0},keyField:{type:String,default:\"id\"},direction:{type:String,default:\"vertical\",validator:function(t){return[\"vertical\",\"horizontal\"].includes(t)}},listTag:{type:String,default:\"div\"},itemTag:{type:String,default:\"div\"}};function xye(){return this.items.length&&Ph(this.items[0])!==\"object\"}var Rh=!1;if(typeof window<\"u\"){Rh=!1;try{var kye=Object.defineProperty({},\"passive\",{get:function(){Rh=!0}});window.addEventListener(\"test\",null,kye)}catch{}}let Sye=0;var zp={name:\"RecycleScroller\",components:{ResizeObserver:pf},directives:{ObserveVisibility:gye},props:{...wye,itemSize:{type:Number,default:null},gridItems:{type:Number,default:void 0},itemSecondarySize:{type:Number,default:void 0},minItemSize:{type:[Number,String],default:null},sizeField:{type:String,default:\"size\"},typeField:{type:String,default:\"type\"},buffer:{type:Number,default:200},pageMode:{type:Boolean,default:!1},prerender:{type:Number,default:0},emitUpdate:{type:Boolean,default:!1},updateInterval:{type:Number,default:0},skipHover:{type:Boolean,default:!1},listTag:{type:String,default:\"div\"},itemTag:{type:String,default:\"div\"},listClass:{type:[String,Object,Array],default:\"\"},itemClass:{type:[String,Object,Array],default:\"\"}},emits:[\"resize\",\"visible\",\"hidden\",\"update\",\"scroll-start\",\"scroll-end\"],data(){return{pool:[],totalSize:0,ready:!1,hoverKey:null}},computed:{sizes(){if(this.itemSize===null){const e={\"-1\":{accumulator:0}},t=this.items,r=this.sizeField,o=this.minItemSize;let s=1e4,c=0,f;for(let d=0,h=t.length;d<h;d++)f=t[d][r]||o,f<s&&(s=f),c+=f,e[d]={accumulator:c,size:f};return this.$_computedMinItemSize=s,e}return[]},simpleArray:xye,itemIndexByKey(){const{keyField:e,items:t}=this,r={};for(let o=0,s=t.length;o<s;o++)r[t[o][e]]=o;return r}},watch:{items(){this.updateVisibleItems(!0)},pageMode(){this.applyPageMode(),this.updateVisibleItems(!1)},sizes:{handler(){this.updateVisibleItems(!1)},deep:!0},gridItems(){this.updateVisibleItems(!0)},itemSecondarySize(){this.updateVisibleItems(!0)}},created(){this.$_startIndex=0,this.$_endIndex=0,this.$_views=new Map,this.$_unusedViews=new Map,this.$_scrollDirty=!1,this.$_lastUpdateScrollPosition=0,this.prerender&&(this.$_prerender=!0,this.updateVisibleItems(!1)),this.gridItems&&!this.itemSize&&console.error(\"[vue-recycle-scroller] You must provide an itemSize when using gridItems\")},mounted(){this.applyPageMode(),this.$nextTick(()=>{this.$_prerender=!1,this.updateVisibleItems(!0),this.ready=!0})},activated(){const e=this.$_lastUpdateScrollPosition;typeof e==\"number\"&&this.$nextTick(()=>{this.scrollToPosition(e)})},beforeUnmount(){this.removeListeners()},methods:{addView(e,t,r,o,s){const c=Uu({id:Sye++,index:t,used:!0,key:o,type:s}),f=Gh({item:r,position:0,nr:c});return e.push(f),f},unuseView(e,t=!1){const r=this.$_unusedViews,o=e.nr.type;let s=r.get(o);s||(s=[],r.set(o,s)),s.push(e),t||(e.nr.used=!1,e.position=-9999)},handleResize(){this.$emit(\"resize\"),this.ready&&this.updateVisibleItems(!1)},handleScroll(e){if(!this.$_scrollDirty){if(this.$_scrollDirty=!0,this.$_updateTimeout)return;const t=()=>requestAnimationFrame(()=>{this.$_scrollDirty=!1;const{continuous:r}=this.updateVisibleItems(!1,!0);r||(clearTimeout(this.$_refreshTimout),this.$_refreshTimout=setTimeout(this.handleScroll,this.updateInterval+100))});t(),this.updateInterval&&(this.$_updateTimeout=setTimeout(()=>{this.$_updateTimeout=0,this.$_scrollDirty&&t()},this.updateInterval))}},handleVisibilityChange(e,t){this.ready&&(e||t.boundingClientRect.width!==0||t.boundingClientRect.height!==0?(this.$emit(\"visible\"),requestAnimationFrame(()=>{this.updateVisibleItems(!1)})):this.$emit(\"hidden\"))},updateVisibleItems(e,t=!1){const r=this.itemSize,o=this.gridItems||1,s=this.itemSecondarySize||r,c=this.$_computedMinItemSize,f=this.typeField,d=this.simpleArray?null:this.keyField,h=this.items,p=h.length,g=this.sizes,v=this.$_views,b=this.$_unusedViews,w=this.pool,E=this.itemIndexByKey;let L,P,M,R,I;if(!p)L=P=R=I=M=0;else if(this.$_prerender)L=R=0,P=I=Math.min(this.prerender,h.length),M=null;else{const G=this.getScroll();if(t){let O=G.start-this.$_lastUpdateScrollPosition;if(O<0&&(O=-O),r===null&&O<c||O<r)return{continuous:!0}}this.$_lastUpdateScrollPosition=G.start;const j=this.buffer;G.start-=j,G.end+=j;let N=0;if(this.$refs.before&&(N=this.$refs.before.scrollHeight,G.start-=N),this.$refs.after){const O=this.$refs.after.scrollHeight;G.end+=O}if(r===null){let O,C=0,k=p-1,z=~~(p/2),B;do B=z,O=g[z].accumulator,O<G.start?C=z:z<p-1&&g[z+1].accumulator>G.start&&(k=z),z=~~((C+k)/2);while(z!==B);for(z<0&&(z=0),L=z,M=g[p-1].accumulator,P=z;P<p&&g[P].accumulator<G.end;P++);for(P===-1?P=h.length-1:(P++,P>p&&(P=p)),R=L;R<p&&N+g[R].accumulator<G.start;R++);for(I=R;I<p&&N+g[I].accumulator<G.end;I++);}else{L=~~(G.start/r*o);const O=L%o;L-=O,P=Math.ceil(G.end/r*o),R=Math.max(0,Math.floor((G.start-N)/r*o)),I=Math.floor((G.end-N)/r*o),L<0&&(L=0),P>p&&(P=p),R<0&&(R=0),I>p&&(I=p),M=Math.ceil(p/o)*r}}P-L>mye.itemsLimit&&this.itemsLimitError(),this.totalSize=M;let _;const $=L<=this.$_endIndex&&P>=this.$_startIndex;if($)for(let G=0,j=w.length;G<j;G++)_=w[G],_.nr.used&&(e&&(_.nr.index=E[_.item[d]]),(_.nr.index==null||_.nr.index<L||_.nr.index>=P)&&this.unuseView(_));const W=$?null:new Map;let ne,ee,Z;for(let G=L;G<P;G++){ne=h[G];const j=d?ne[d]:ne;if(j==null)throw new Error(`Key is ${j} on item (keyField is '${d}')`);if(_=v.get(j),!r&&!g[G].size){_&&this.unuseView(_);continue}ee=ne[f];let N=b.get(ee),O=!1;if(!_)$?N&&N.length?_=N.pop():_=this.addView(w,G,ne,j,ee):(Z=W.get(ee)||0,(!N||Z>=N.length)&&(_=this.addView(w,G,ne,j,ee),this.unuseView(_,!0),N=b.get(ee)),_=N[Z],W.set(ee,Z+1)),v.delete(_.nr.key),_.nr.used=!0,_.nr.index=G,_.nr.key=j,_.nr.type=ee,v.set(j,_),O=!0;else if(!_.nr.used&&(_.nr.used=!0,O=!0,N)){const C=N.indexOf(_);C!==-1&&N.splice(C,1)}_.item=ne,O&&(G===h.length-1&&this.$emit(\"scroll-end\"),G===0&&this.$emit(\"scroll-start\")),r===null?(_.position=g[G-1].accumulator,_.offset=0):(_.position=Math.floor(G/o)*r,_.offset=G%o*s)}return this.$_startIndex=L,this.$_endIndex=P,this.emitUpdate&&this.$emit(\"update\",L,P,R,I),clearTimeout(this.$_sortTimer),this.$_sortTimer=setTimeout(this.sortViews,this.updateInterval+300),{continuous:$}},getListenerTarget(){let e=c0(this.$el);return window.document&&(e===window.document.documentElement||e===window.document.body)&&(e=window),e},getScroll(){const{$el:e,direction:t}=this,r=t===\"vertical\";let o;if(this.pageMode){const s=e.getBoundingClientRect(),c=r?s.height:s.width;let f=-(r?s.top:s.left),d=r?window.innerHeight:window.innerWidth;f<0&&(d+=f,f=0),f+d>c&&(d=c-f),o={start:f,end:f+d}}else r?o={start:e.scrollTop,end:e.scrollTop+e.clientHeight}:o={start:e.scrollLeft,end:e.scrollLeft+e.clientWidth};return o},applyPageMode(){this.pageMode?this.addListeners():this.removeListeners()},addListeners(){this.listenerTarget=this.getListenerTarget(),this.listenerTarget.addEventListener(\"scroll\",this.handleScroll,Rh?{passive:!0}:!1),this.listenerTarget.addEventListener(\"resize\",this.handleResize)},removeListeners(){this.listenerTarget&&(this.listenerTarget.removeEventListener(\"scroll\",this.handleScroll),this.listenerTarget.removeEventListener(\"resize\",this.handleResize),this.listenerTarget=null)},scrollToItem(e){let t;const r=this.gridItems||1;this.itemSize===null?t=e>0?this.sizes[e-1].accumulator:0:t=Math.floor(e/r)*this.itemSize,this.scrollToPosition(t)},scrollToPosition(e){const t=this.direction===\"vertical\"?{scroll:\"scrollTop\",start:\"top\"}:{scroll:\"scrollLeft\",start:\"left\"};let r,o,s;if(this.pageMode){const c=c0(this.$el),f=c.tagName===\"HTML\"?0:c[t.scroll],d=c.getBoundingClientRect(),p=this.$el.getBoundingClientRect()[t.start]-d[t.start];r=c,o=t.scroll,s=e+f+p}else r=this.$el,o=t.scroll,s=e;r[o]=s},itemsLimitError(){throw setTimeout(()=>{console.log(\"It seems the scroller element isn't scrolling, so it tries to render all the items at once.\",\"Scroller:\",this.$el),console.log(\"Make sure the scroller has a fixed height (or width) and 'overflow-y' (or 'overflow-x') set to 'auto' so it can scroll correctly and only render the items visible in the scroll viewport.\")}),new Error(\"Rendered items limit reached\")},sortViews(){this.pool.sort((e,t)=>e.nr.index-t.nr.index)}}};const _ye={key:0,ref:\"before\",class:\"vue-recycle-scroller__slot\"},Tye={key:1,ref:\"after\",class:\"vue-recycle-scroller__slot\"};function Cye(e,t,r,o,s,c){const f=Go(\"ResizeObserver\"),d=vr(\"observe-visibility\");return at((ie(),ve(\"div\",{class:ot([\"vue-recycle-scroller\",{ready:s.ready,\"page-mode\":r.pageMode,[`direction-${e.direction}`]:!0}]),onScrollPassive:t[0]||(t[0]=(...h)=>c.handleScroll&&c.handleScroll(...h))},[e.$slots.before?(ie(),ve(\"div\",_ye,[Dt(e.$slots,\"before\")],512)):He(\"v-if\",!0),(ie(),Ve(Xd(r.listTag),{ref:\"wrapper\",style:zt({[e.direction===\"vertical\"?\"minHeight\":\"minWidth\"]:s.totalSize+\"px\"}),class:ot([\"vue-recycle-scroller__item-wrapper\",r.listClass])},{default:We(()=>[(ie(!0),ve(nt,null,$n(s.pool,h=>(ie(),Ve(Xd(r.itemTag),ki({key:h.nr.id,style:s.ready?{transform:`translate${e.direction===\"vertical\"?\"Y\":\"X\"}(${h.position}px) translate${e.direction===\"vertical\"?\"X\":\"Y\"}(${h.offset}px)`,width:r.gridItems?`${e.direction===\"vertical\"&&r.itemSecondarySize||r.itemSize}px`:void 0,height:r.gridItems?`${e.direction===\"horizontal\"&&r.itemSecondarySize||r.itemSize}px`:void 0}:null,class:[\"vue-recycle-scroller__item-view\",[r.itemClass,{hover:!r.skipHover&&s.hoverKey===h.nr.key}]]},q_(r.skipHover?{}:{mouseenter:()=>{s.hoverKey=h.nr.key},mouseleave:()=>{s.hoverKey=null}})),{default:We(()=>[Dt(e.$slots,\"default\",{item:h.item,index:h.nr.index,active:h.nr.used})]),_:2},1040,[\"style\",\"class\"]))),128)),Dt(e.$slots,\"empty\")]),_:3},8,[\"style\",\"class\"])),e.$slots.after?(ie(),ve(\"div\",Tye,[Dt(e.$slots,\"after\")],512)):He(\"v-if\",!0),Ne(f,{onNotify:c.handleResize},null,8,[\"onNotify\"])],34)),[[d,c.handleVisibilityChange]])}zp.render=Cye;zp.__file=\"src/components/RecycleScroller.vue\";function Eye(e){const t=ke(()=>hh.value?!1:!it.onlyTests),r=ke(()=>Vn.value===\"\"),o=Ge(Vn.value);hp(()=>Vn.value,h=>{o.value=h?.trim()??\"\"},{debounce:256});function s(h){Vn.value=\"\",h&&e.value?.focus()}function c(h){it.failed=!1,it.success=!1,it.skipped=!1,it.onlyTests=!1,h&&e.value?.focus()}function f(){c(!1),s(!0)}function d(h,p,g,v,b){Qs.value&&(gn.value.search=h?.trim()??\"\",gn.value.failed=p,gn.value.success=g,gn.value.skipped=v,gn.value.onlyTests=b)}return xt(()=>[o.value,it.failed,it.success,it.skipped,it.onlyTests],([h,p,g,v,b])=>{d(h,p,g,v,b),Oe.filterNodes()},{flush:\"post\"}),xt(()=>Dr.value.length,h=>{h&&(gn.value.expandAll=void 0)},{flush:\"post\"}),{initialized:Qs,filter:it,search:Vn,disableFilter:t,isFiltered:Zw,isFilteredByStatus:hh,disableClearSearch:r,clearAll:f,clearSearch:s,clearFilter:c,filteredFiles:cf,testsTotal:JA,uiEntries:Jn}}const Aye=[\"open\"],Lye=rt({__name:\"DetailsPanel\",props:{color:{}},setup(e){const t=Ge(!0);return(r,o)=>(ie(),ve(\"div\",{open:t.value,class:\"details-panel\",\"data-testid\":\"details-panel\",onToggle:o[0]||(o[0]=s=>t.value=s.target.open)},[X(\"div\",{p:\"y1\",\"text-sm\":\"\",\"bg-base\":\"\",\"items-center\":\"\",\"z-5\":\"\",\"gap-2\":\"\",class:ot(e.color),\"w-full\":\"\",flex:\"\",\"select-none\":\"\",sticky:\"\",top:\"-1\"},[o[1]||(o[1]=X(\"div\",{\"flex-1\":\"\",\"h-1px\":\"\",border:\"base b\",op80:\"\"},null,-1)),Dt(r.$slots,\"summary\",{open:t.value}),o[2]||(o[2]=X(\"div\",{\"flex-1\":\"\",\"h-1px\":\"\",border:\"base b\",op80:\"\"},null,-1))],2),Dt(r.$slots,\"default\")],40,Aye))}}),Mye={\"flex-1\":\"\",\"ms-2\":\"\",\"select-none\":\"\"},Wc=rt({__name:\"FilterStatus\",props:da({label:{}},{modelValue:{type:[Boolean,null]},modelModifiers:{}}),emits:[\"update:modelValue\"],setup(e){const t=Yu(e,\"modelValue\");return(r,o)=>(ie(),ve(\"label\",ki({class:\"font-light text-sm checkbox flex items-center cursor-pointer py-1 text-sm w-full gap-y-1 mb-1px\"},r.$attrs,{onClick:o[1]||(o[1]=Gc(s=>t.value=!t.value,[\"prevent\"]))}),[X(\"span\",{class:ot([t.value?\"i-carbon:checkbox-checked-filled\":\"i-carbon:checkbox\"]),\"text-lg\":\"\",\"aria-hidden\":\"true\"},null,2),at(X(\"input\",{\"onUpdate:modelValue\":o[0]||(o[0]=s=>t.value=s),type:\"checkbox\",\"sr-only\":\"\"},null,512),[[Zb,t.value]]),X(\"span\",Mye,Re(e.label),1)],16))}}),Nye={type:\"button\",dark:\"op75\",bg:\"gray-200 dark:#111\",hover:\"op100\",\"rounded-1\":\"\",\"p-0.5\":\"\"},Oye=rt({__name:\"IconAction\",props:{icon:{}},setup(e){return(t,r)=>(ie(),ve(\"button\",Nye,[X(\"span\",{block:\"\",class:ot([e.icon,\"dark:op85 hover:op100\"]),op65:\"\"},null,2)]))}}),Pye=[\"aria-label\",\"data-current\"],Rye={key:1,\"w-4\":\"\"},$ye={flex:\"\",\"items-end\":\"\",\"gap-2\":\"\",\"overflow-hidden\":\"\"},Iye={key:0,class:\"i-logos:typescript-icon\",\"flex-shrink-0\":\"\"},Dye={\"text-sm\":\"\",truncate:\"\",\"font-light\":\"\"},zye=[\"text\",\"innerHTML\"],Fye={key:1,text:\"xs\",op20:\"\",style:{\"white-space\":\"nowrap\"}},Hye={\"gap-1\":\"\",\"justify-end\":\"\",\"flex-grow-1\":\"\",\"pl-1\":\"\",class:\"test-actions\"},Bye={key:0,class:\"op100 gap-1 p-y-1\",grid:\"~ items-center cols-[1.5em_1fr]\"},Wye={key:1},qye=rt({__name:\"ExplorerItem\",props:{taskId:{},name:{},indent:{},typecheck:{type:Boolean},duration:{},state:{},current:{type:Boolean},type:{},opened:{type:Boolean},expandable:{type:Boolean},search:{},projectName:{},projectNameColor:{},disableTaskLocation:{type:Boolean},onItemClick:{type:Function}},setup(e){const t=ke(()=>ft.state.idMap.get(e.taskId)),r=ke(()=>{if(gr)return!1;const P=t.value;return P&&yp(P)});function o(){if(!e.expandable){e.onItemClick?.(t.value);return}e.opened?Oe.collapseNode(e.taskId):Oe.expandNode(e.taskId)}async function s(P){e.onItemClick?.(P),Os.value&&(Cu.value=!0,await Et()),e.type===\"file\"?await _p([P.file]):await Xce(P)}function c(P){return ft.rpc.updateSnapshot(P.file)}const f=ke(()=>e.indent<=0?[]:Array.from({length:e.indent},(P,M)=>`${e.taskId}-${M}`)),d=ke(()=>{const P=f.value,M=[];return(e.type===\"file\"||e.type===\"suite\")&&M.push(\"min-content\"),M.push(\"min-content\"),e.type===\"suite\"&&e.typecheck&&M.push(\"min-content\"),M.push(\"minmax(0, 1fr)\"),M.push(\"min-content\"),`grid-template-columns: ${P.map(()=>\"1rem\").join(\" \")} ${M.join(\" \")};`}),h=ke(()=>e.type===\"file\"?\"Run current file\":e.type===\"suite\"?\"Run all tests in this suite\":\"Run current test\"),p=ke(()=>Yw(e.name)),g=ke(()=>{const P=ZA.value,M=p.value;return P?M.replace(P,R=>`<span class=\"highlight\">${R}</span>`):M}),v=ke(()=>e.type!==\"file\"&&e.disableTaskLocation),b=ke(()=>e.type===\"file\"?\"Open test details\":e.type===\"suite\"?\"View Suite Source Code\":\"View Test Source Code\"),w=ke(()=>v.value?\"color-red5 dark:color-#f43f5e\":null);function E(){const P=t.value;e.type===\"file\"?e.onItemClick?.(P):gx(P)}const L=ke(()=>ex(e.projectNameColor));return(P,M)=>{const R=vr(\"tooltip\");return t.value?(ie(),ve(\"div\",{key:0,\"items-center\":\"\",p:\"x-2 y-1\",grid:\"~ rows-1 items-center gap-x-2\",\"w-full\":\"\",\"h-28px\":\"\",\"border-rounded\":\"\",hover:\"bg-active\",\"cursor-pointer\":\"\",class:\"item-wrapper\",style:zt(d.value),\"aria-label\":e.name,\"data-current\":e.current,onClick:M[2]||(M[2]=I=>o())},[e.indent>0?(ie(!0),ve(nt,{key:0},$n(f.value,I=>(ie(),ve(\"div\",{key:I,border:\"solid gray-500 dark:gray-400\",class:\"vertical-line\",\"h-28px\":\"\",\"inline-flex\":\"\",\"mx-2\":\"\",op20:\"\"}))),128)):He(\"\",!0),e.type===\"file\"||e.type===\"suite\"?(ie(),ve(\"div\",Rye,[X(\"div\",{class:ot(e.opened?\"i-carbon:chevron-down\":\"i-carbon:chevron-right op20\"),op20:\"\"},null,2)])):He(\"\",!0),Ne(c1,{state:e.state,mode:t.value.mode,\"failed-snapshot\":r.value,\"w-4\":\"\"},null,8,[\"state\",\"mode\",\"failed-snapshot\"]),X(\"div\",$ye,[e.type===\"file\"&&e.typecheck?at((ie(),ve(\"div\",Iye,null,512)),[[R,\"This is a typecheck test. It won't report results of the runtime tests\",void 0,{bottom:!0}]]):He(\"\",!0),X(\"span\",Dye,[e.type===\"file\"&&e.projectName?(ie(),ve(\"span\",{key:0,class:\"rounded-full py-0.5 px-2 mr-1 text-xs\",style:zt({backgroundColor:e.projectNameColor,color:L.value})},Re(e.projectName),5)):He(\"\",!0),X(\"span\",{text:e.state===\"fail\"?\"red-500\":\"\",innerHTML:g.value},null,8,zye)]),typeof e.duration==\"number\"?(ie(),ve(\"span\",Fye,Re(e.duration>0?e.duration:\"< 1\")+\"ms \",1)):He(\"\",!0)]),X(\"div\",Hye,[!K(gr)&&r.value?at((ie(),Ve(Oye,{key:0,\"data-testid\":\"btn-fix-snapshot\",title:\"Fix failed snapshot(s)\",icon:\"i-carbon:result-old\",onClick:M[0]||(M[0]=Gc(I=>c(t.value),[\"prevent\",\"stop\"]))},null,512)),[[R,\"Fix failed snapshot(s)\",void 0,{bottom:!0}]]):He(\"\",!0),Ne(K(Qi),{placement:\"bottom\",class:ot([\"w-1.4em h-1.4em op100 rounded flex\",w.value])},{popper:We(()=>[v.value?(ie(),ve(\"div\",Bye,[M[5]||(M[5]=X(\"div\",{class:\"i-carbon:information-square w-1.5em h-1.5em\"},null,-1)),X(\"div\",null,[Qe(Re(b.value)+\": this feature is not available, you have disabled \",1),M[3]||(M[3]=X(\"span\",{class:\"text-[#add467]\"},\"includeTaskLocation\",-1)),M[4]||(M[4]=Qe(\" in your configuration file.\",-1))]),M[6]||(M[6]=X(\"div\",{style:{\"grid-column\":\"2\"}},\" Clicking this button the code tab will position the cursor at first line in the source code since the UI doesn't have the information available. \",-1))])):(ie(),ve(\"div\",Wye,Re(b.value),1))]),default:We(()=>[Ne(_t,{\"data-testid\":\"btn-open-details\",icon:e.type===\"file\"?\"i-carbon:intrusion-prevention\":\"i-carbon:code-reference\",onClick:Gc(E,[\"prevent\",\"stop\"])},null,8,[\"icon\"])]),_:1},8,[\"class\"]),K(gr)?He(\"\",!0):at((ie(),Ve(_t,{key:1,\"data-testid\":\"btn-run-test\",title:h.value,icon:\"i-carbon:play-filled-alt\",\"text-green5\":\"\",onClick:M[1]||(M[1]=Gc(I=>s(t.value),[\"prevent\",\"stop\"]))},null,8,[\"title\"])),[[R,h.value,void 0,{bottom:!0}]])])],12,Pye)):He(\"\",!0)}}}),jye=Ni(qye,[[\"__scopeId\",\"data-v-58d301d8\"]]),Uye={p:\"2\",\"h-10\":\"\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b base\"},Vye={p:\"l3 y2 r2\",flex:\"~ gap-2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b-2 base\"},Gye=[\"op\"],Kye={grid:\"~ items-center gap-x-1 cols-[auto_min-content_auto] rows-[min-content_min-content]\"},Xye={\"text-red5\":\"\"},Yye={\"text-yellow5\":\"\"},Zye={\"text-green5\":\"\"},Jye={class:\"text-purple5:50\"},Qye={key:0,flex:\"~ col\",\"items-center\":\"\",p:\"x4 y4\",\"font-light\":\"\"},e0e=[\"disabled\"],t0e=[\"disabled\"],n0e={key:1,flex:\"~ col\",\"items-center\":\"\",p:\"x4 y4\",\"font-light\":\"\"},r0e=rt({inheritAttrs:!1,__name:\"Explorer\",props:{onItemClick:{type:Function}},emits:[\"item-click\",\"run\"],setup(e,{emit:t}){const r=t,o=ke(()=>ei.value.includeTaskLocation),s=Ge(),{initialized:c,filter:f,search:d,disableFilter:h,isFiltered:p,isFilteredByStatus:g,disableClearSearch:v,clearAll:b,clearSearch:w,clearFilter:E,filteredFiles:L,testsTotal:P,uiEntries:M}=Eye(s),R=Ge(\"grid-cols-2\"),I=Ge(\"grid-col-span-2\"),_=Ge();return Ow(()=>_.value,([{contentRect:$}])=>{$.width<420?(R.value=\"grid-cols-2\",I.value=\"grid-col-span-2\"):(R.value=\"grid-cols-4\",I.value=\"grid-col-span-4\")}),($,W)=>{const ne=vr(\"tooltip\");return ie(),ve(\"div\",{ref_key:\"testExplorerRef\",ref:_,h:\"full\",flex:\"~ col\"},[X(\"div\",null,[X(\"div\",Uye,[Dt($.$slots,\"header\",{filteredFiles:K(p)||K(g)?K(L):void 0})]),X(\"div\",Vye,[W[13]||(W[13]=X(\"div\",{class:\"i-carbon:search\",\"flex-shrink-0\":\"\"},null,-1)),at(X(\"input\",{ref_key:\"searchBox\",ref:s,\"onUpdate:modelValue\":W[0]||(W[0]=ee=>Mt(d)?d.value=ee:null),placeholder:\"Search...\",outline:\"none\",bg:\"transparent\",font:\"light\",text:\"sm\",\"flex-1\":\"\",\"pl-1\":\"\",op:K(d).length?\"100\":\"50\",onKeydown:[W[1]||(W[1]=ih(ee=>K(w)(!1),[\"esc\"])),W[2]||(W[2]=ih(ee=>r(\"run\",K(p)||K(g)?K(L):void 0),[\"enter\"]))]},null,40,Gye),[[Yb,K(d)]]),at(Ne(_t,{disabled:K(v),title:\"Clear search\",icon:\"i-carbon:filter-remove\",onClickPassive:W[3]||(W[3]=ee=>K(w)(!0))},null,8,[\"disabled\"]),[[ne,\"Clear search\",void 0,{bottom:!0}]])]),X(\"div\",{p:\"l3 y2 r2\",\"items-center\":\"\",\"bg-header\":\"\",border:\"b-2 base\",grid:\"~ items-center gap-x-2 rows-[auto_auto]\",class:ot(R.value)},[X(\"div\",{class:ot(I.value),flex:\"~ gap-2 items-center\"},[W[14]||(W[14]=X(\"div\",{\"aria-hidden\":\"true\",class:\"i-carbon:filter\"},null,-1)),W[15]||(W[15]=X(\"div\",{\"flex-grow-1\":\"\",\"text-sm\":\"\"},\" Filter \",-1)),at(Ne(_t,{disabled:K(h),title:\"Clear search\",icon:\"i-carbon:filter-remove\",onClickPassive:W[4]||(W[4]=ee=>K(E)(!1))},null,8,[\"disabled\"]),[[ne,\"Clear Filter\",void 0,{bottom:!0}]])],2),Ne(Wc,{modelValue:K(f).failed,\"onUpdate:modelValue\":W[5]||(W[5]=ee=>K(f).failed=ee),label:\"Fail\"},null,8,[\"modelValue\"]),Ne(Wc,{modelValue:K(f).success,\"onUpdate:modelValue\":W[6]||(W[6]=ee=>K(f).success=ee),label:\"Pass\"},null,8,[\"modelValue\"]),Ne(Wc,{modelValue:K(f).skipped,\"onUpdate:modelValue\":W[7]||(W[7]=ee=>K(f).skipped=ee),label:\"Skip\"},null,8,[\"modelValue\"]),Ne(Wc,{modelValue:K(f).onlyTests,\"onUpdate:modelValue\":W[8]||(W[8]=ee=>K(f).onlyTests=ee),label:\"Only Tests\"},null,8,[\"modelValue\"])],2)]),X(\"div\",{class:\"scrolls\",\"flex-auto\":\"\",\"py-1\":\"\",onScrollPassive:W[12]||(W[12]=(...ee)=>K(Bv)&&K(Bv)(...ee))},[Ne(Lye,null,W_({default:We(()=>[(K(p)||K(g))&&K(M).length===0?(ie(),ve(nt,{key:0},[K(c)?(ie(),ve(\"div\",Qye,[W[18]||(W[18]=X(\"div\",{op30:\"\"},\" No matched test \",-1)),X(\"button\",{type:\"button\",\"font-light\":\"\",\"text-sm\":\"\",border:\"~ gray-400/50 rounded\",p:\"x2 y0.5\",m:\"t2\",op:\"50\",class:ot(K(v)?null:\"hover:op100\"),disabled:K(v),onClickPassive:W[9]||(W[9]=ee=>K(w)(!0))},\" Clear Search \",42,e0e),X(\"button\",{type:\"button\",\"font-light\":\"\",\"text-sm\":\"\",border:\"~ gray-400/50 rounded\",p:\"x2 y0.5\",m:\"t2\",op:\"50\",class:ot(K(h)?null:\"hover:op100\"),disabled:K(h),onClickPassive:W[10]||(W[10]=ee=>K(E)(!0))},\" Clear Filter \",42,t0e),X(\"button\",{type:\"button\",\"font-light\":\"\",op:\"50 hover:100\",\"text-sm\":\"\",border:\"~ gray-400/50 rounded\",p:\"x2 y0.5\",m:\"t2\",onClickPassive:W[11]||(W[11]=(...ee)=>K(b)&&K(b)(...ee))},\" Clear All \",32)])):(ie(),ve(\"div\",n0e,[...W[19]||(W[19]=[X(\"div\",{class:\"i-carbon:circle-dash animate-spin\"},null,-1),X(\"div\",{op30:\"\"},\" Loading... \",-1)])]))],64)):(ie(),Ve(K(zp),{key:1,\"page-mode\":\"\",\"key-field\":\"id\",\"item-size\":28,items:K(M),buffer:100},{default:We(({item:ee})=>[Ne(jye,{class:ot([\"h-28px m-0 p-0\",K(po)===ee.id?\"bg-active\":\"\"]),\"task-id\":ee.id,expandable:ee.expandable,type:ee.type,current:K(po)===ee.id,indent:ee.indent,name:ee.name,typecheck:ee.typecheck===!0,\"project-name\":ee.projectName??\"\",\"project-name-color\":ee.projectNameColor??\"\",state:ee.state,duration:ee.duration,opened:ee.expanded,\"disable-task-location\":!o.value,\"on-item-click\":e.onItemClick},null,8,[\"task-id\",\"expandable\",\"type\",\"current\",\"indent\",\"name\",\"typecheck\",\"project-name\",\"project-name-color\",\"state\",\"duration\",\"opened\",\"disable-task-location\",\"class\",\"on-item-click\"])]),_:1},8,[\"items\"]))]),_:2},[K(c)?{name:\"summary\",fn:We(()=>[X(\"div\",Kye,[X(\"span\",Xye,\" FAIL (\"+Re(K(P).failed)+\") \",1),W[16]||(W[16]=X(\"span\",null,\"/\",-1)),X(\"span\",Yye,\" RUNNING (\"+Re(K(P).running)+\") \",1),X(\"span\",Zye,\" PASS (\"+Re(K(P).success)+\") \",1),W[17]||(W[17]=X(\"span\",null,\"/\",-1)),X(\"span\",Jye,\" SKIP (\"+Re(K(f).onlyTests?K(P).skipped:\"--\")+\") \",1)])]),key:\"0\"}:void 0]),1024)],32)],512)}}}),i0e={class:\"flex text-lg\"},o0e=rt({__name:\"Navigation\",setup(e){function t(){return ft.rpc.updateSnapshot()}const r=ke(()=>ol.value?\"light\":\"dark\");async function o(f){Os.value&&(Cu.value=!0,await Et(),go.value&&(Eu(!0),await Et())),f?.length?await _p(f):await Gce()}function s(){Oe.collapseAllNodes()}function c(){Oe.expandAllNodes()}return(f,d)=>{const h=vr(\"tooltip\");return ie(),Ve(r0e,{border:\"r base\",\"on-item-click\":K(vce),nested:!0,onRun:o},{header:We(({filteredFiles:p})=>[d[8]||(d[8]=X(\"img\",{\"w-6\":\"\",\"h-6\":\"\",src:Qve,alt:\"Vitest logo\"},null,-1)),d[9]||(d[9]=X(\"span\",{\"font-light\":\"\",\"text-sm\":\"\",\"flex-1\":\"\"},\"Vitest\",-1)),X(\"div\",i0e,[at(Ne(_t,{title:\"Collapse tests\",disabled:!K(Qs),\"data-testid\":\"collapse-all\",icon:\"i-carbon:collapse-all\",onClick:d[0]||(d[0]=g=>s())},null,8,[\"disabled\"]),[[ro,!K(sy)],[h,\"Collapse tests\",void 0,{bottom:!0}]]),at(Ne(_t,{disabled:!K(Qs),title:\"Expand tests\",\"data-testid\":\"expand-all\",icon:\"i-carbon:expand-all\",onClick:d[1]||(d[1]=g=>c())},null,8,[\"disabled\"]),[[ro,K(sy)],[h,\"Expand tests\",void 0,{bottom:!0}]]),at(Ne(_t,{title:\"Show dashboard\",class:\"!animate-100ms\",\"animate-count-1\":\"\",icon:\"i-carbon:dashboard\",onClick:d[2]||(d[2]=g=>K(Eu)(!0))},null,512),[[ro,K(mh)&&!K(Os)||!K(Ws)],[h,\"Dashboard\",void 0,{bottom:!0}]]),K(mh)&&!K(Os)?(ie(),Ve(K(Qi),{key:0,title:\"Coverage enabled but missing html reporter\",class:\"w-1.4em h-1.4em op100 rounded flex color-red5 dark:color-#f43f5e cursor-help\"},{popper:We(()=>[...d[6]||(d[6]=[X(\"div\",{class:\"op100 gap-1 p-y-1\",grid:\"~ items-center cols-[1.5em_1fr]\"},[X(\"div\",{class:\"i-carbon:information-square w-1.5em h-1.5em\"}),X(\"div\",null,\"Coverage enabled but missing html reporter.\"),X(\"div\",{style:{\"grid-column\":\"2\"}},\" Add html reporter to your configuration to see coverage here. \")],-1)])]),default:We(()=>[d[7]||(d[7]=X(\"div\",{class:\"i-carbon:folder-off ma\"},null,-1))]),_:1})):He(\"\",!0),K(Os)?at((ie(),Ve(_t,{key:1,disabled:K(Cu),title:\"Show coverage\",class:\"!animate-100ms\",\"animate-count-1\":\"\",icon:\"i-carbon:folder-details-reference\",onClick:d[3]||(d[3]=g=>K(yce)())},null,8,[\"disabled\"])),[[ro,!K(go)],[h,\"Coverage\",void 0,{bottom:!0}]]):He(\"\",!0),K(Oe).summary.failedSnapshot&&!K(gr)?at((ie(),Ve(_t,{key:2,icon:\"i-carbon:result-old\",disabled:!K(Oe).summary.failedSnapshotEnabled,onClick:d[4]||(d[4]=g=>K(Oe).summary.failedSnapshotEnabled&&t())},null,8,[\"disabled\"])),[[h,\"Update all failed snapshot(s)\",void 0,{bottom:!0}]]):He(\"\",!0),K(gr)?He(\"\",!0):at((ie(),Ve(_t,{key:3,disabled:p?.length===0,icon:\"i-carbon:play\",onClick:g=>o(p)},null,8,[\"disabled\",\"onClick\"])),[[h,p?p.length===0?\"No test to run (clear filter)\":\"Rerun filtered\":\"Rerun all\",void 0,{bottom:!0}]]),at(Ne(_t,{icon:\"dark:i-carbon-moon i-carbon:sun\",onClick:d[5]||(d[5]=g=>K(eme)())},null,512),[[h,`Toggle to ${r.value} mode`,void 0,{bottom:!0}]])])]),_:1},8,[\"on-item-click\"])}}}),s0e={\"h-3px\":\"\",relative:\"\",\"overflow-hidden\":\"\",class:\"px-0\",\"w-screen\":\"\"},l0e=rt({__name:\"ProgressBar\",setup(e){const{width:t}=Pw(),r=ke(()=>[Oe.summary.files===0&&\"!bg-gray-4 !dark:bg-gray-7\",!Ms.value&&\"in-progress\"].filter(Boolean).join(\" \")),o=ke(()=>{const d=Oe.summary.files;return d>0?t.value*Oe.summary.filesSuccess/d:0}),s=ke(()=>{const d=Oe.summary.files;return d>0?t.value*Oe.summary.filesFailed/d:0}),c=ke(()=>Oe.summary.files-Oe.summary.filesFailed-Oe.summary.filesSuccess),f=ke(()=>{const d=Oe.summary.files;return d>0?t.value*c.value/d:0});return(d,h)=>(ie(),ve(\"div\",{absolute:\"\",\"t-0\":\"\",\"l-0\":\"\",\"r-0\":\"\",\"z-index-1031\":\"\",\"pointer-events-none\":\"\",\"p-0\":\"\",\"h-3px\":\"\",grid:\"~ auto-cols-max\",\"justify-items-center\":\"\",\"w-screen\":\"\",class:ot(r.value)},[X(\"div\",s0e,[X(\"div\",{absolute:\"\",\"l-0\":\"\",\"t-0\":\"\",\"bg-red5\":\"\",\"h-3px\":\"\",class:ot(r.value),style:zt(`width: ${s.value}px;`)},\"   \",6),X(\"div\",{absolute:\"\",\"l-0\":\"\",\"t-0\":\"\",\"bg-green5\":\"\",\"h-3px\":\"\",class:ot(r.value),style:zt(`left: ${s.value}px; width: ${o.value}px;`)},\"   \",6),X(\"div\",{absolute:\"\",\"l-0\":\"\",\"t-0\":\"\",\"bg-yellow5\":\"\",\"h-3px\":\"\",class:ot(r.value),style:zt(`left: ${o.value+s.value}px; width: ${f.value}px;`)},\"   \",6)])],2))}}),a0e=Ni(l0e,[[\"__scopeId\",\"data-v-5320005b\"]]),c0e={\"h-screen\":\"\",\"w-screen\":\"\",overflow:\"hidden\"},u0e=rt({__name:\"index\",setup(e){const t=mce(),r=Nc(({panes:g})=>{h(),d(g)},0),o=Nc(({panes:g})=>{g.forEach((v,b)=>{qs.value[b]=v.size}),f(g),p()},0),s=Nc(({panes:g})=>{g.forEach((v,b)=>{co.value[b]=v.size}),d(g),p()},0),c=Nc(({panes:g})=>{f(g),h()},0);function f(g){At.navigation=g[0].size,At.details.size=g[1].size}function d(g){At.details.browser=g[0].size,At.details.main=g[1].size}function h(){const g=document.querySelector(\"#tester-ui\");g&&(g.style.pointerEvents=\"none\")}function p(){const g=document.querySelector(\"#tester-ui\");g&&(g.style.pointerEvents=\"\")}return(g,v)=>(ie(),ve(nt,null,[Ne(a0e),X(\"div\",c0e,[Ne(K(Gv),{class:\"pt-4px\",onResized:K(o),onResize:K(c)},{default:We(()=>[Ne(K(Rc),{size:K(qs)[0]},{default:We(()=>[Ne(o0e)]),_:1},8,[\"size\"]),Ne(K(Rc),{size:K(qs)[1]},{default:We(()=>[K(Zn)?(ie(),Ve(K(Gv),{id:\"details-splitpanes\",key:\"browser-detail\",onResize:K(r),onResized:K(s)},{default:We(()=>[Ne(K(Rc),{size:K(co)[0],\"min-size\":\"10\"},{default:We(()=>[v[0]||(Ys(-1,!0),(v[0]=Ne(sue)).cacheIndex=0,Ys(1),v[0])]),_:1},8,[\"size\"]),Ne(K(Rc),{size:K(co)[1]},{default:We(()=>[K(t)?(ie(),Ve(Iy,{key:\"summary\"})):K(go)?(ie(),Ve($y,{key:\"coverage\",src:K(Oy)},null,8,[\"src\"])):(ie(),Ve(l0,{key:\"details\"}))]),_:1},8,[\"size\"])]),_:1},8,[\"onResize\",\"onResized\"])):(ie(),Ve(BT,{key:\"ui-detail\"},{default:We(()=>[K(t)?(ie(),Ve(Iy,{key:\"summary\"})):K(go)?(ie(),Ve($y,{key:\"coverage\",src:K(Oy)},null,8,[\"src\"])):(ie(),Ve(l0,{key:\"details\"}))]),_:1}))]),_:1},8,[\"size\"])]),_:1},8,[\"onResized\",\"onResize\"])]),Ne(cue)],64))}}),f0e=[{name:\"index\",path:\"/\",component:u0e,props:!0}];/*!\n * vue-router v4.6.3\n * (c) 2025 Eduardo San Martin Morote\n * @license MIT\n */const Ls=typeof document<\"u\";function S1(e){return typeof e==\"object\"||\"displayName\"in e||\"props\"in e||\"__vccOpts\"in e}function d0e(e){return e.__esModule||e[Symbol.toStringTag]===\"Module\"||e.default&&S1(e.default)}const bt=Object.assign;function Hd(e,t){const r={};for(const o in t){const s=t[o];r[o]=zr(s)?s.map(e):e(s)}return r}const la=()=>{},zr=Array.isArray;function u0(e,t){const r={};for(const o in e)r[o]=o in t?t[o]:e[o];return r}const _1=/#/g,h0e=/&/g,p0e=/\\//g,g0e=/=/g,m0e=/\\?/g,T1=/\\+/g,v0e=/%5B/g,y0e=/%5D/g,C1=/%5E/g,b0e=/%60/g,E1=/%7B/g,w0e=/%7C/g,A1=/%7D/g,x0e=/%20/g;function Fp(e){return e==null?\"\":encodeURI(\"\"+e).replace(w0e,\"|\").replace(v0e,\"[\").replace(y0e,\"]\")}function k0e(e){return Fp(e).replace(E1,\"{\").replace(A1,\"}\").replace(C1,\"^\")}function $h(e){return Fp(e).replace(T1,\"%2B\").replace(x0e,\"+\").replace(_1,\"%23\").replace(h0e,\"%26\").replace(b0e,\"`\").replace(E1,\"{\").replace(A1,\"}\").replace(C1,\"^\")}function S0e(e){return $h(e).replace(g0e,\"%3D\")}function _0e(e){return Fp(e).replace(_1,\"%23\").replace(m0e,\"%3F\")}function T0e(e){return _0e(e).replace(p0e,\"%2F\")}function Na(e){if(e==null)return null;try{return decodeURIComponent(\"\"+e)}catch{}return\"\"+e}const C0e=/\\/$/,E0e=e=>e.replace(C0e,\"\");function Bd(e,t,r=\"/\"){let o,s={},c=\"\",f=\"\";const d=t.indexOf(\"#\");let h=t.indexOf(\"?\");return h=d>=0&&h>d?-1:h,h>=0&&(o=t.slice(0,h),c=t.slice(h,d>0?d:t.length),s=e(c.slice(1))),d>=0&&(o=o||t.slice(0,d),f=t.slice(d,t.length)),o=N0e(o??t,r),{fullPath:o+c+f,path:o,query:s,hash:Na(f)}}function A0e(e,t){const r=t.query?e(t.query):\"\";return t.path+(r&&\"?\")+r+(t.hash||\"\")}function f0(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||\"/\"}function L0e(e,t,r){const o=t.matched.length-1,s=r.matched.length-1;return o>-1&&o===s&&rl(t.matched[o],r.matched[s])&&L1(t.params,r.params)&&e(t.query)===e(r.query)&&t.hash===r.hash}function rl(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function L1(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const r in e)if(!M0e(e[r],t[r]))return!1;return!0}function M0e(e,t){return zr(e)?d0(e,t):zr(t)?d0(t,e):e===t}function d0(e,t){return zr(t)?e.length===t.length&&e.every((r,o)=>r===t[o]):e.length===1&&e[0]===t}function N0e(e,t){if(e.startsWith(\"/\"))return e;if(!e)return t;const r=t.split(\"/\"),o=e.split(\"/\"),s=o[o.length-1];(s===\"..\"||s===\".\")&&o.push(\"\");let c=r.length-1,f,d;for(f=0;f<o.length;f++)if(d=o[f],d!==\".\")if(d===\"..\")c>1&&c--;else break;return r.slice(0,c).join(\"/\")+\"/\"+o.slice(f).join(\"/\")}const Gi={path:\"/\",name:void 0,params:{},query:{},hash:\"\",fullPath:\"/\",matched:[],meta:{},redirectedFrom:void 0};let Ih=(function(e){return e.pop=\"pop\",e.push=\"push\",e})({}),Wd=(function(e){return e.back=\"back\",e.forward=\"forward\",e.unknown=\"\",e})({});function O0e(e){if(!e)if(Ls){const t=document.querySelector(\"base\");e=t&&t.getAttribute(\"href\")||\"/\",e=e.replace(/^\\w+:\\/\\/[^\\/]+/,\"\")}else e=\"/\";return e[0]!==\"/\"&&e[0]!==\"#\"&&(e=\"/\"+e),E0e(e)}const P0e=/^[^#]+#/;function R0e(e,t){return e.replace(P0e,\"#\")+t}function $0e(e,t){const r=document.documentElement.getBoundingClientRect(),o=e.getBoundingClientRect();return{behavior:t.behavior,left:o.left-r.left-(t.left||0),top:o.top-r.top-(t.top||0)}}const gf=()=>({left:window.scrollX,top:window.scrollY});function I0e(e){let t;if(\"el\"in e){const r=e.el,o=typeof r==\"string\"&&r.startsWith(\"#\"),s=typeof r==\"string\"?o?document.getElementById(r.slice(1)):document.querySelector(r):r;if(!s)return;t=$0e(s,e)}else t=e;\"scrollBehavior\"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function h0(e,t){return(history.state?history.state.position-t:-1)+e}const Dh=new Map;function D0e(e,t){Dh.set(e,t)}function z0e(e){const t=Dh.get(e);return Dh.delete(e),t}function F0e(e){return typeof e==\"string\"||e&&typeof e==\"object\"}function M1(e){return typeof e==\"string\"||typeof e==\"symbol\"}let qt=(function(e){return e[e.MATCHER_NOT_FOUND=1]=\"MATCHER_NOT_FOUND\",e[e.NAVIGATION_GUARD_REDIRECT=2]=\"NAVIGATION_GUARD_REDIRECT\",e[e.NAVIGATION_ABORTED=4]=\"NAVIGATION_ABORTED\",e[e.NAVIGATION_CANCELLED=8]=\"NAVIGATION_CANCELLED\",e[e.NAVIGATION_DUPLICATED=16]=\"NAVIGATION_DUPLICATED\",e})({});const N1=Symbol(\"\");qt.MATCHER_NOT_FOUND+\"\",qt.NAVIGATION_GUARD_REDIRECT+\"\",qt.NAVIGATION_ABORTED+\"\",qt.NAVIGATION_CANCELLED+\"\",qt.NAVIGATION_DUPLICATED+\"\";function il(e,t){return bt(new Error,{type:e,[N1]:!0},t)}function pi(e,t){return e instanceof Error&&N1 in e&&(t==null||!!(e.type&t))}const H0e=[\"params\",\"query\",\"hash\"];function B0e(e){if(typeof e==\"string\")return e;if(e.path!=null)return e.path;const t={};for(const r of H0e)r in e&&(t[r]=e[r]);return JSON.stringify(t,null,2)}function W0e(e){const t={};if(e===\"\"||e===\"?\")return t;const r=(e[0]===\"?\"?e.slice(1):e).split(\"&\");for(let o=0;o<r.length;++o){const s=r[o].replace(T1,\" \"),c=s.indexOf(\"=\"),f=Na(c<0?s:s.slice(0,c)),d=c<0?null:Na(s.slice(c+1));if(f in t){let h=t[f];zr(h)||(h=t[f]=[h]),h.push(d)}else t[f]=d}return t}function p0(e){let t=\"\";for(let r in e){const o=e[r];if(r=S0e(r),o==null){o!==void 0&&(t+=(t.length?\"&\":\"\")+r);continue}(zr(o)?o.map(s=>s&&$h(s)):[o&&$h(o)]).forEach(s=>{s!==void 0&&(t+=(t.length?\"&\":\"\")+r,s!=null&&(t+=\"=\"+s))})}return t}function q0e(e){const t={};for(const r in e){const o=e[r];o!==void 0&&(t[r]=zr(o)?o.map(s=>s==null?null:\"\"+s):o==null?o:\"\"+o)}return t}const j0e=Symbol(\"\"),g0=Symbol(\"\"),Hp=Symbol(\"\"),O1=Symbol(\"\"),zh=Symbol(\"\");function jl(){let e=[];function t(o){return e.push(o),()=>{const s=e.indexOf(o);s>-1&&e.splice(s,1)}}function r(){e=[]}return{add:t,list:()=>e.slice(),reset:r}}function no(e,t,r,o,s,c=f=>f()){const f=o&&(o.enterCallbacks[s]=o.enterCallbacks[s]||[]);return()=>new Promise((d,h)=>{const p=b=>{b===!1?h(il(qt.NAVIGATION_ABORTED,{from:r,to:t})):b instanceof Error?h(b):F0e(b)?h(il(qt.NAVIGATION_GUARD_REDIRECT,{from:t,to:b})):(f&&o.enterCallbacks[s]===f&&typeof b==\"function\"&&f.push(b),d())},g=c(()=>e.call(o&&o.instances[s],t,r,p));let v=Promise.resolve(g);e.length<3&&(v=v.then(p)),v.catch(b=>h(b))})}function qd(e,t,r,o,s=c=>c()){const c=[];for(const f of e)for(const d in f.components){let h=f.components[d];if(!(t!==\"beforeRouteEnter\"&&!f.instances[d]))if(S1(h)){const p=(h.__vccOpts||h)[t];p&&c.push(no(p,r,o,f,d,s))}else{let p=h();c.push(()=>p.then(g=>{if(!g)throw new Error(`Couldn't resolve component \"${d}\" at \"${f.path}\"`);const v=d0e(g)?g.default:g;f.mods[d]=g,f.components[d]=v;const b=(v.__vccOpts||v)[t];return b&&no(b,r,o,f,d,s)()}))}}return c}function U0e(e,t){const r=[],o=[],s=[],c=Math.max(t.matched.length,e.matched.length);for(let f=0;f<c;f++){const d=t.matched[f];d&&(e.matched.find(p=>rl(p,d))?o.push(d):r.push(d));const h=e.matched[f];h&&(t.matched.find(p=>rl(p,h))||s.push(h))}return[r,o,s]}/*!\n * vue-router v4.6.3\n * (c) 2025 Eduardo San Martin Morote\n * @license MIT\n */let V0e=()=>location.protocol+\"//\"+location.host;function P1(e,t){const{pathname:r,search:o,hash:s}=t,c=e.indexOf(\"#\");if(c>-1){let f=s.includes(e.slice(c))?e.slice(c).length:1,d=s.slice(f);return d[0]!==\"/\"&&(d=\"/\"+d),f0(d,\"\")}return f0(r,e)+o+s}function G0e(e,t,r,o){let s=[],c=[],f=null;const d=({state:b})=>{const w=P1(e,location),E=r.value,L=t.value;let P=0;if(b){if(r.value=w,t.value=b,f&&f===E){f=null;return}P=L?b.position-L.position:0}else o(w);s.forEach(M=>{M(r.value,E,{delta:P,type:Ih.pop,direction:P?P>0?Wd.forward:Wd.back:Wd.unknown})})};function h(){f=r.value}function p(b){s.push(b);const w=()=>{const E=s.indexOf(b);E>-1&&s.splice(E,1)};return c.push(w),w}function g(){if(document.visibilityState===\"hidden\"){const{history:b}=window;if(!b.state)return;b.replaceState(bt({},b.state,{scroll:gf()}),\"\")}}function v(){for(const b of c)b();c=[],window.removeEventListener(\"popstate\",d),window.removeEventListener(\"pagehide\",g),document.removeEventListener(\"visibilitychange\",g)}return window.addEventListener(\"popstate\",d),window.addEventListener(\"pagehide\",g),document.addEventListener(\"visibilitychange\",g),{pauseListeners:h,listen:p,destroy:v}}function m0(e,t,r,o=!1,s=!1){return{back:e,current:t,forward:r,replaced:o,position:window.history.length,scroll:s?gf():null}}function K0e(e){const{history:t,location:r}=window,o={value:P1(e,r)},s={value:t.state};s.value||c(o.value,{back:null,current:o.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function c(h,p,g){const v=e.indexOf(\"#\"),b=v>-1?(r.host&&document.querySelector(\"base\")?e:e.slice(v))+h:V0e()+e+h;try{t[g?\"replaceState\":\"pushState\"](p,\"\",b),s.value=p}catch(w){console.error(w),r[g?\"replace\":\"assign\"](b)}}function f(h,p){c(h,bt({},t.state,m0(s.value.back,h,s.value.forward,!0),p,{position:s.value.position}),!0),o.value=h}function d(h,p){const g=bt({},s.value,t.state,{forward:h,scroll:gf()});c(g.current,g,!0),c(h,bt({},m0(o.value,h,null),{position:g.position+1},p),!1),o.value=h}return{location:o,state:s,push:d,replace:f}}function X0e(e){e=O0e(e);const t=K0e(e),r=G0e(e,t.state,t.location,t.replace);function o(c,f=!0){f||r.pauseListeners(),history.go(c)}const s=bt({location:\"\",base:e,go:o,createHref:R0e.bind(null,e)},t,r);return Object.defineProperty(s,\"location\",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(s,\"state\",{enumerable:!0,get:()=>t.state.value}),s}function Y0e(e){return e=location.host?e||location.pathname+location.search:\"\",e.includes(\"#\")||(e+=\"#\"),X0e(e)}let Wo=(function(e){return e[e.Static=0]=\"Static\",e[e.Param=1]=\"Param\",e[e.Group=2]=\"Group\",e})({});var rn=(function(e){return e[e.Static=0]=\"Static\",e[e.Param=1]=\"Param\",e[e.ParamRegExp=2]=\"ParamRegExp\",e[e.ParamRegExpEnd=3]=\"ParamRegExpEnd\",e[e.EscapeNext=4]=\"EscapeNext\",e})(rn||{});const Z0e={type:Wo.Static,value:\"\"},J0e=/[a-zA-Z0-9_]/;function Q0e(e){if(!e)return[[]];if(e===\"/\")return[[Z0e]];if(!e.startsWith(\"/\"))throw new Error(`Invalid path \"${e}\"`);function t(w){throw new Error(`ERR (${r})/\"${p}\": ${w}`)}let r=rn.Static,o=r;const s=[];let c;function f(){c&&s.push(c),c=[]}let d=0,h,p=\"\",g=\"\";function v(){p&&(r===rn.Static?c.push({type:Wo.Static,value:p}):r===rn.Param||r===rn.ParamRegExp||r===rn.ParamRegExpEnd?(c.length>1&&(h===\"*\"||h===\"+\")&&t(`A repeatable param (${p}) must be alone in its segment. eg: '/:ids+.`),c.push({type:Wo.Param,value:p,regexp:g,repeatable:h===\"*\"||h===\"+\",optional:h===\"*\"||h===\"?\"})):t(\"Invalid state to consume buffer\"),p=\"\")}function b(){p+=h}for(;d<e.length;){if(h=e[d++],h===\"\\\\\"&&r!==rn.ParamRegExp){o=r,r=rn.EscapeNext;continue}switch(r){case rn.Static:h===\"/\"?(p&&v(),f()):h===\":\"?(v(),r=rn.Param):b();break;case rn.EscapeNext:b(),r=o;break;case rn.Param:h===\"(\"?r=rn.ParamRegExp:J0e.test(h)?b():(v(),r=rn.Static,h!==\"*\"&&h!==\"?\"&&h!==\"+\"&&d--);break;case rn.ParamRegExp:h===\")\"?g[g.length-1]==\"\\\\\"?g=g.slice(0,-1)+h:r=rn.ParamRegExpEnd:g+=h;break;case rn.ParamRegExpEnd:v(),r=rn.Static,h!==\"*\"&&h!==\"?\"&&h!==\"+\"&&d--,g=\"\";break;default:t(\"Unknown state\");break}}return r===rn.ParamRegExp&&t(`Unfinished custom RegExp for param \"${p}\"`),v(),f(),s}const v0=\"[^/]+?\",ebe={sensitive:!1,strict:!1,start:!0,end:!0};var On=(function(e){return e[e._multiplier=10]=\"_multiplier\",e[e.Root=90]=\"Root\",e[e.Segment=40]=\"Segment\",e[e.SubSegment=30]=\"SubSegment\",e[e.Static=40]=\"Static\",e[e.Dynamic=20]=\"Dynamic\",e[e.BonusCustomRegExp=10]=\"BonusCustomRegExp\",e[e.BonusWildcard=-50]=\"BonusWildcard\",e[e.BonusRepeatable=-20]=\"BonusRepeatable\",e[e.BonusOptional=-8]=\"BonusOptional\",e[e.BonusStrict=.7000000000000001]=\"BonusStrict\",e[e.BonusCaseSensitive=.25]=\"BonusCaseSensitive\",e})(On||{});const tbe=/[.+*?^${}()[\\]/\\\\]/g;function nbe(e,t){const r=bt({},ebe,t),o=[];let s=r.start?\"^\":\"\";const c=[];for(const p of e){const g=p.length?[]:[On.Root];r.strict&&!p.length&&(s+=\"/\");for(let v=0;v<p.length;v++){const b=p[v];let w=On.Segment+(r.sensitive?On.BonusCaseSensitive:0);if(b.type===Wo.Static)v||(s+=\"/\"),s+=b.value.replace(tbe,\"\\\\$&\"),w+=On.Static;else if(b.type===Wo.Param){const{value:E,repeatable:L,optional:P,regexp:M}=b;c.push({name:E,repeatable:L,optional:P});const R=M||v0;if(R!==v0){w+=On.BonusCustomRegExp;try{`${R}`}catch(_){throw new Error(`Invalid custom RegExp for param \"${E}\" (${R}): `+_.message)}}let I=L?`((?:${R})(?:/(?:${R}))*)`:`(${R})`;v||(I=P&&p.length<2?`(?:/${I})`:\"/\"+I),P&&(I+=\"?\"),s+=I,w+=On.Dynamic,P&&(w+=On.BonusOptional),L&&(w+=On.BonusRepeatable),R===\".*\"&&(w+=On.BonusWildcard)}g.push(w)}o.push(g)}if(r.strict&&r.end){const p=o.length-1;o[p][o[p].length-1]+=On.BonusStrict}r.strict||(s+=\"/?\"),r.end?s+=\"$\":r.strict&&!s.endsWith(\"/\")&&(s+=\"(?:/|$)\");const f=new RegExp(s,r.sensitive?\"\":\"i\");function d(p){const g=p.match(f),v={};if(!g)return null;for(let b=1;b<g.length;b++){const w=g[b]||\"\",E=c[b-1];v[E.name]=w&&E.repeatable?w.split(\"/\"):w}return v}function h(p){let g=\"\",v=!1;for(const b of e){(!v||!g.endsWith(\"/\"))&&(g+=\"/\"),v=!1;for(const w of b)if(w.type===Wo.Static)g+=w.value;else if(w.type===Wo.Param){const{value:E,repeatable:L,optional:P}=w,M=E in p?p[E]:\"\";if(zr(M)&&!L)throw new Error(`Provided param \"${E}\" is an array but it is not repeatable (* or + modifiers)`);const R=zr(M)?M.join(\"/\"):M;if(!R)if(P)b.length<2&&(g.endsWith(\"/\")?g=g.slice(0,-1):v=!0);else throw new Error(`Missing required param \"${E}\"`);g+=R}}return g||\"/\"}return{re:f,score:o,keys:c,parse:d,stringify:h}}function rbe(e,t){let r=0;for(;r<e.length&&r<t.length;){const o=t[r]-e[r];if(o)return o;r++}return e.length<t.length?e.length===1&&e[0]===On.Static+On.Segment?-1:1:e.length>t.length?t.length===1&&t[0]===On.Static+On.Segment?1:-1:0}function R1(e,t){let r=0;const o=e.score,s=t.score;for(;r<o.length&&r<s.length;){const c=rbe(o[r],s[r]);if(c)return c;r++}if(Math.abs(s.length-o.length)===1){if(y0(o))return 1;if(y0(s))return-1}return s.length-o.length}function y0(e){const t=e[e.length-1];return e.length>0&&t[t.length-1]<0}const ibe={strict:!1,end:!0,sensitive:!1};function obe(e,t,r){const o=nbe(Q0e(e.path),r),s=bt(o,{record:e,parent:t,children:[],alias:[]});return t&&!s.record.aliasOf==!t.record.aliasOf&&t.children.push(s),s}function sbe(e,t){const r=[],o=new Map;t=u0(ibe,t);function s(v){return o.get(v)}function c(v,b,w){const E=!w,L=w0(v);L.aliasOf=w&&w.record;const P=u0(t,v),M=[L];if(\"alias\"in v){const _=typeof v.alias==\"string\"?[v.alias]:v.alias;for(const $ of _)M.push(w0(bt({},L,{components:w?w.record.components:L.components,path:$,aliasOf:w?w.record:L})))}let R,I;for(const _ of M){const{path:$}=_;if(b&&$[0]!==\"/\"){const W=b.record.path,ne=W[W.length-1]===\"/\"?\"\":\"/\";_.path=b.record.path+($&&ne+$)}if(R=obe(_,b,P),w?w.alias.push(R):(I=I||R,I!==R&&I.alias.push(R),E&&v.name&&!x0(R)&&f(v.name)),$1(R)&&h(R),L.children){const W=L.children;for(let ne=0;ne<W.length;ne++)c(W[ne],R,w&&w.children[ne])}w=w||R}return I?()=>{f(I)}:la}function f(v){if(M1(v)){const b=o.get(v);b&&(o.delete(v),r.splice(r.indexOf(b),1),b.children.forEach(f),b.alias.forEach(f))}else{const b=r.indexOf(v);b>-1&&(r.splice(b,1),v.record.name&&o.delete(v.record.name),v.children.forEach(f),v.alias.forEach(f))}}function d(){return r}function h(v){const b=cbe(v,r);r.splice(b,0,v),v.record.name&&!x0(v)&&o.set(v.record.name,v)}function p(v,b){let w,E={},L,P;if(\"name\"in v&&v.name){if(w=o.get(v.name),!w)throw il(qt.MATCHER_NOT_FOUND,{location:v});P=w.record.name,E=bt(b0(b.params,w.keys.filter(I=>!I.optional).concat(w.parent?w.parent.keys.filter(I=>I.optional):[]).map(I=>I.name)),v.params&&b0(v.params,w.keys.map(I=>I.name))),L=w.stringify(E)}else if(v.path!=null)L=v.path,w=r.find(I=>I.re.test(L)),w&&(E=w.parse(L),P=w.record.name);else{if(w=b.name?o.get(b.name):r.find(I=>I.re.test(b.path)),!w)throw il(qt.MATCHER_NOT_FOUND,{location:v,currentLocation:b});P=w.record.name,E=bt({},b.params,v.params),L=w.stringify(E)}const M=[];let R=w;for(;R;)M.unshift(R.record),R=R.parent;return{name:P,path:L,params:E,matched:M,meta:abe(M)}}e.forEach(v=>c(v));function g(){r.length=0,o.clear()}return{addRoute:c,resolve:p,removeRoute:f,clearRoutes:g,getRoutes:d,getRecordMatcher:s}}function b0(e,t){const r={};for(const o of t)o in e&&(r[o]=e[o]);return r}function w0(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:lbe(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:\"components\"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,\"mods\",{value:{}}),t}function lbe(e){const t={},r=e.props||!1;if(\"component\"in e)t.default=r;else for(const o in e.components)t[o]=typeof r==\"object\"?r[o]:r;return t}function x0(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function abe(e){return e.reduce((t,r)=>bt(t,r.meta),{})}function cbe(e,t){let r=0,o=t.length;for(;r!==o;){const c=r+o>>1;R1(e,t[c])<0?o=c:r=c+1}const s=ube(e);return s&&(o=t.lastIndexOf(s,o-1)),o}function ube(e){let t=e;for(;t=t.parent;)if($1(t)&&R1(e,t)===0)return t}function $1({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function k0(e){const t=pn(Hp),r=pn(O1),o=ke(()=>{const h=K(e.to);return t.resolve(h)}),s=ke(()=>{const{matched:h}=o.value,{length:p}=h,g=h[p-1],v=r.matched;if(!g||!v.length)return-1;const b=v.findIndex(rl.bind(null,g));if(b>-1)return b;const w=S0(h[p-2]);return p>1&&S0(g)===w&&v[v.length-1].path!==w?v.findIndex(rl.bind(null,h[p-2])):b}),c=ke(()=>s.value>-1&&gbe(r.params,o.value.params)),f=ke(()=>s.value>-1&&s.value===r.matched.length-1&&L1(r.params,o.value.params));function d(h={}){if(pbe(h)){const p=t[K(e.replace)?\"replace\":\"push\"](K(e.to)).catch(la);return e.viewTransition&&typeof document<\"u\"&&\"startViewTransition\"in document&&document.startViewTransition(()=>p),p}return Promise.resolve()}return{route:o,href:ke(()=>o.value.href),isActive:c,isExactActive:f,navigate:d}}function fbe(e){return e.length===1?e[0]:e}const dbe=rt({name:\"RouterLink\",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:\"page\"},viewTransition:Boolean},useLink:k0,setup(e,{slots:t}){const r=ir(k0(e)),{options:o}=pn(Hp),s=ke(()=>({[_0(e.activeClass,o.linkActiveClass,\"router-link-active\")]:r.isActive,[_0(e.exactActiveClass,o.linkExactActiveClass,\"router-link-exact-active\")]:r.isExactActive}));return()=>{const c=t.default&&fbe(t.default(r));return e.custom?c:za(\"a\",{\"aria-current\":r.isExactActive?e.ariaCurrentValue:null,href:r.href,onClick:r.navigate,class:s.value},c)}}}),hbe=dbe;function pbe(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute(\"target\");if(/\\b_blank\\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function gbe(e,t){for(const r in t){const o=t[r],s=e[r];if(typeof o==\"string\"){if(o!==s)return!1}else if(!zr(s)||s.length!==o.length||o.some((c,f)=>c!==s[f]))return!1}return!0}function S0(e){return e?e.aliasOf?e.aliasOf.path:e.path:\"\"}const _0=(e,t,r)=>e??t??r,mbe=rt({name:\"RouterView\",inheritAttrs:!1,props:{name:{type:String,default:\"default\"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:r}){const o=pn(zh),s=ke(()=>e.route||o.value),c=pn(g0,0),f=ke(()=>{let p=K(c);const{matched:g}=s.value;let v;for(;(v=g[p])&&!v.components;)p++;return p}),d=ke(()=>s.value.matched[f.value]);dr(g0,ke(()=>f.value+1)),dr(j0e,d),dr(zh,s);const h=Ge();return xt(()=>[h.value,d.value,e.name],([p,g,v],[b,w,E])=>{g&&(g.instances[v]=p,w&&w!==g&&p&&p===b&&(g.leaveGuards.size||(g.leaveGuards=w.leaveGuards),g.updateGuards.size||(g.updateGuards=w.updateGuards))),p&&g&&(!w||!rl(g,w)||!b)&&(g.enterCallbacks[v]||[]).forEach(L=>L(p))},{flush:\"post\"}),()=>{const p=s.value,g=e.name,v=d.value,b=v&&v.components[g];if(!b)return T0(r.default,{Component:b,route:p});const w=v.props[g],E=w?w===!0?p.params:typeof w==\"function\"?w(p):w:null,P=za(b,bt({},E,t,{onVnodeUnmounted:M=>{M.component.isUnmounted&&(v.instances[g]=null)},ref:h}));return T0(r.default,{Component:P,route:p})||P}}});function T0(e,t){if(!e)return null;const r=e(t);return r.length===1?r[0]:r}const vbe=mbe;function ybe(e){const t=sbe(e.routes,e),r=e.parseQuery||W0e,o=e.stringifyQuery||p0,s=e.history,c=jl(),f=jl(),d=jl(),h=Ft(Gi);let p=Gi;Ls&&e.scrollBehavior&&\"scrollRestoration\"in history&&(history.scrollRestoration=\"manual\");const g=Hd.bind(null,F=>\"\"+F),v=Hd.bind(null,T0e),b=Hd.bind(null,Na);function w(F,Y){let re,le;return M1(F)?(re=t.getRecordMatcher(F),le=Y):le=F,t.addRoute(le,re)}function E(F){const Y=t.getRecordMatcher(F);Y&&t.removeRoute(Y)}function L(){return t.getRoutes().map(F=>F.record)}function P(F){return!!t.getRecordMatcher(F)}function M(F,Y){if(Y=bt({},Y||h.value),typeof F==\"string\"){const Q=Bd(r,F,Y.path),he=t.resolve({path:Q.path},Y),de=s.createHref(Q.fullPath);return bt(Q,he,{params:b(he.params),hash:Na(Q.hash),redirectedFrom:void 0,href:de})}let re;if(F.path!=null)re=bt({},F,{path:Bd(r,F.path,Y.path).path});else{const Q=bt({},F.params);for(const he in Q)Q[he]==null&&delete Q[he];re=bt({},F,{params:v(Q)}),Y.params=v(Y.params)}const le=t.resolve(re,Y),ae=F.hash||\"\";le.params=g(b(le.params));const D=A0e(o,bt({},F,{hash:k0e(ae),path:le.path})),q=s.createHref(D);return bt({fullPath:D,hash:ae,query:o===p0?q0e(F.query):F.query||{}},le,{redirectedFrom:void 0,href:q})}function R(F){return typeof F==\"string\"?Bd(r,F,h.value.path):bt({},F)}function I(F,Y){if(p!==F)return il(qt.NAVIGATION_CANCELLED,{from:Y,to:F})}function _(F){return ne(F)}function $(F){return _(bt(R(F),{replace:!0}))}function W(F,Y){const re=F.matched[F.matched.length-1];if(re&&re.redirect){const{redirect:le}=re;let ae=typeof le==\"function\"?le(F,Y):le;return typeof ae==\"string\"&&(ae=ae.includes(\"?\")||ae.includes(\"#\")?ae=R(ae):{path:ae},ae.params={}),bt({query:F.query,hash:F.hash,params:ae.path!=null?{}:F.params},ae)}}function ne(F,Y){const re=p=M(F),le=h.value,ae=F.state,D=F.force,q=F.replace===!0,Q=W(re,le);if(Q)return ne(bt(R(Q),{state:typeof Q==\"object\"?bt({},ae,Q.state):ae,force:D,replace:q}),Y||re);const he=re;he.redirectedFrom=Y;let de;return!D&&L0e(o,le,re)&&(de=il(qt.NAVIGATION_DUPLICATED,{to:he,from:le}),Be(le,le,!0,!1)),(de?Promise.resolve(de):G(he,le)).catch(ge=>pi(ge)?pi(ge,qt.NAVIGATION_GUARD_REDIRECT)?ge:Se(ge):ce(ge,he,le)).then(ge=>{if(ge){if(pi(ge,qt.NAVIGATION_GUARD_REDIRECT))return ne(bt({replace:q},R(ge.to),{state:typeof ge.to==\"object\"?bt({},ae,ge.to.state):ae,force:D}),Y||he)}else ge=N(he,le,!0,q,ae);return j(he,le,ge),ge})}function ee(F,Y){const re=I(F,Y);return re?Promise.reject(re):Promise.resolve()}function Z(F){const Y=je.values().next().value;return Y&&typeof Y.runWithContext==\"function\"?Y.runWithContext(F):F()}function G(F,Y){let re;const[le,ae,D]=U0e(F,Y);re=qd(le.reverse(),\"beforeRouteLeave\",F,Y);for(const Q of le)Q.leaveGuards.forEach(he=>{re.push(no(he,F,Y))});const q=ee.bind(null,F,Y);return re.push(q),Pe(re).then(()=>{re=[];for(const Q of c.list())re.push(no(Q,F,Y));return re.push(q),Pe(re)}).then(()=>{re=qd(ae,\"beforeRouteUpdate\",F,Y);for(const Q of ae)Q.updateGuards.forEach(he=>{re.push(no(he,F,Y))});return re.push(q),Pe(re)}).then(()=>{re=[];for(const Q of D)if(Q.beforeEnter)if(zr(Q.beforeEnter))for(const he of Q.beforeEnter)re.push(no(he,F,Y));else re.push(no(Q.beforeEnter,F,Y));return re.push(q),Pe(re)}).then(()=>(F.matched.forEach(Q=>Q.enterCallbacks={}),re=qd(D,\"beforeRouteEnter\",F,Y,Z),re.push(q),Pe(re))).then(()=>{re=[];for(const Q of f.list())re.push(no(Q,F,Y));return re.push(q),Pe(re)}).catch(Q=>pi(Q,qt.NAVIGATION_CANCELLED)?Q:Promise.reject(Q))}function j(F,Y,re){d.list().forEach(le=>Z(()=>le(F,Y,re)))}function N(F,Y,re,le,ae){const D=I(F,Y);if(D)return D;const q=Y===Gi,Q=Ls?history.state:{};re&&(le||q?s.replace(F.fullPath,bt({scroll:q&&Q&&Q.scroll},ae)):s.push(F.fullPath,ae)),h.value=F,Be(F,Y,re,q),Se()}let O;function C(){O||(O=s.listen((F,Y,re)=>{if(!Fe.listening)return;const le=M(F),ae=W(le,Fe.currentRoute.value);if(ae){ne(bt(ae,{replace:!0,force:!0}),le).catch(la);return}p=le;const D=h.value;Ls&&D0e(h0(D.fullPath,re.delta),gf()),G(le,D).catch(q=>pi(q,qt.NAVIGATION_ABORTED|qt.NAVIGATION_CANCELLED)?q:pi(q,qt.NAVIGATION_GUARD_REDIRECT)?(ne(bt(R(q.to),{force:!0}),le).then(Q=>{pi(Q,qt.NAVIGATION_ABORTED|qt.NAVIGATION_DUPLICATED)&&!re.delta&&re.type===Ih.pop&&s.go(-1,!1)}).catch(la),Promise.reject()):(re.delta&&s.go(-re.delta,!1),ce(q,le,D))).then(q=>{q=q||N(le,D,!1),q&&(re.delta&&!pi(q,qt.NAVIGATION_CANCELLED)?s.go(-re.delta,!1):re.type===Ih.pop&&pi(q,qt.NAVIGATION_ABORTED|qt.NAVIGATION_DUPLICATED)&&s.go(-1,!1)),j(le,D,q)}).catch(la)}))}let k=jl(),z=jl(),B;function ce(F,Y,re){Se(F);const le=z.list();return le.length?le.forEach(ae=>ae(F,Y,re)):console.error(F),Promise.reject(F)}function be(){return B&&h.value!==Gi?Promise.resolve():new Promise((F,Y)=>{k.add([F,Y])})}function Se(F){return B||(B=!F,C(),k.list().forEach(([Y,re])=>F?re(F):Y()),k.reset()),F}function Be(F,Y,re,le){const{scrollBehavior:ae}=e;if(!Ls||!ae)return Promise.resolve();const D=!re&&z0e(h0(F.fullPath,0))||(le||!re)&&history.state&&history.state.scroll||null;return Et().then(()=>ae(F,Y,D)).then(q=>q&&I0e(q)).catch(q=>ce(q,F,Y))}const Ae=F=>s.go(F);let Ke;const je=new Set,Fe={currentRoute:h,listening:!0,addRoute:w,removeRoute:E,clearRoutes:t.clearRoutes,hasRoute:P,getRoutes:L,resolve:M,options:e,push:_,replace:$,go:Ae,back:()=>Ae(-1),forward:()=>Ae(1),beforeEach:c.add,beforeResolve:f.add,afterEach:d.add,onError:z.add,isReady:be,install(F){F.component(\"RouterLink\",hbe),F.component(\"RouterView\",vbe),F.config.globalProperties.$router=Fe,Object.defineProperty(F.config.globalProperties,\"$route\",{enumerable:!0,get:()=>K(h)}),Ls&&!Ke&&h.value===Gi&&(Ke=!0,_(s.location).catch(le=>{}));const Y={};for(const le in Gi)Object.defineProperty(Y,le,{get:()=>h.value[le],enumerable:!0});F.provide(Hp,Fe),F.provide(O1,Gh(Y)),F.provide(zh,h);const re=F.unmount;je.add(F),F.unmount=function(){je.delete(F),je.size<1&&(p=Gi,O&&O(),O=null,h.value=Gi,Ke=!1,B=!1),re()}}};function Pe(F){return F.reduce((Y,re)=>Y.then(()=>Z(re)),Promise.resolve())}return Fe}const bbe={tooltip:pE};ww.options.instantMove=!0;ww.options.distance=10;function wbe(){return ybe({history:Y0e(),routes:f0e})}const xbe=[wbe],Bp=Qb(vC);xbe.forEach(e=>{Bp.use(e())});Object.entries(bbe).forEach(([e,t])=>{Bp.directive(e,t)});Bp.mount(\"#app\");\n"
  },
  {
    "path": "test/cli/test/fixtures/reporters/html/fail/assets/index-DlhE0rqZ.css",
    "content": ".CodeMirror-simplescroll-horizontal div,.CodeMirror-simplescroll-vertical div{position:absolute;background:#ccc;-moz-box-sizing:border-box;box-sizing:border-box;border:1px solid #bbb;border-radius:2px}.CodeMirror-simplescroll-horizontal,.CodeMirror-simplescroll-vertical{position:absolute;z-index:6;background:#eee}.CodeMirror-simplescroll-horizontal{bottom:0;left:0;height:8px}.CodeMirror-simplescroll-horizontal div{bottom:0;height:100%}.CodeMirror-simplescroll-vertical{right:0;top:0;width:8px}.CodeMirror-simplescroll-vertical div{right:0;width:100%}.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler,.CodeMirror-overlayscroll .CodeMirror-gutter-filler{display:none}.CodeMirror-overlayscroll-horizontal div,.CodeMirror-overlayscroll-vertical div{position:absolute;background:#bcd;border-radius:3px}.CodeMirror-overlayscroll-horizontal,.CodeMirror-overlayscroll-vertical{position:absolute;z-index:6}.CodeMirror-overlayscroll-horizontal{bottom:0;left:0;height:6px}.CodeMirror-overlayscroll-horizontal div{bottom:0;height:100%}.CodeMirror-overlayscroll-vertical{right:0;top:0;width:6px}.CodeMirror-overlayscroll-vertical div{right:0;width:100%}#tester-container[data-v-2e86b8c3]:not([data-ready]){width:100%;height:100%;display:flex;align-items:center;justify-content:center}[data-ready] #tester-ui[data-v-2e86b8c3]{width:var(--viewport-width);height:var(--viewport-height);transform:var(--tester-transform);margin-left:var(--tester-margin-left)}#vitest-ui-coverage{width:100%;height:calc(100vh - 42px);border:none}.number[data-v-1bd0f2ea]{font-weight:400;text-align:right}.unhandled-errors[data-v-1bd0f2ea]{--cm-ttc-c-thumb: #ccc}html.dark .unhandled-errors[data-v-1bd0f2ea]{--cm-ttc-c-thumb: #444}:root{--color-link-label: var(--color-text);--color-link: #ddd;--color-node-external: #6C5C33;--color-node-inline: #8bc4a0;--color-node-root: #6e9aa5;--color-node-focused: #e67e22;--color-node-label: var(--color-text);--color-node-stroke: var(--color-text)}html.dark{--color-text: #fff;--color-link: #333;--color-node-external: #c0ad79;--color-node-inline: #468b60;--color-node-root: #467d8b;--color-node-focused: #f39c12}.graph{height:calc(100% - 39px)!important}.graph .node{stroke-width:2px;stroke-opacity:.5}.graph .link{stroke-width:2px}.graph .node:hover:not(.focused){filter:none!important}.graph .node__label{transform:translateY(20px);font-weight:100;filter:brightness(.5)}html.dark .graph .node__label{filter:brightness(1.2)}.scrolls[data-v-08ce44b7]{place-items:center}.task-error[data-v-1fcfe7a4]{--cm-ttc-c-thumb: #ccc}html.dark .task-error[data-v-1fcfe7a4]{--cm-ttc-c-thumb: #444}.task-error[data-v-9d875d6e]{--cm-ttc-c-thumb: #ccc}html.dark .task-error[data-v-9d875d6e]{--cm-ttc-c-thumb: #444}.task-error[data-v-1a68630b]{--cm-ttc-c-thumb: #ccc}html.dark .task-error[data-v-1a68630b]{--cm-ttc-c-thumb: #444}.details-panel{-webkit-user-select:none;user-select:none;width:100%}.checkbox:focus-within{outline:none;margin-bottom:0!important;border-bottom-width:1px}.vertical-line[data-v-58d301d8]:first-of-type{border-left-width:2px}.vertical-line+.vertical-line[data-v-58d301d8]{border-right-width:1px}.test-actions[data-v-58d301d8]{display:none}.item-wrapper:hover .test-actions[data-v-58d301d8]{display:flex}.vue-recycle-scroller{position:relative}.vue-recycle-scroller.direction-vertical:not(.page-mode){overflow-y:auto}.vue-recycle-scroller.direction-horizontal:not(.page-mode){overflow-x:auto}.vue-recycle-scroller.direction-horizontal{display:flex}.vue-recycle-scroller__slot{flex:auto 0 0}.vue-recycle-scroller__item-wrapper{flex:1;box-sizing:border-box;overflow:hidden;position:relative}.vue-recycle-scroller.ready .vue-recycle-scroller__item-view{position:absolute;top:0;left:0;will-change:transform}.vue-recycle-scroller.direction-vertical .vue-recycle-scroller__item-wrapper{width:100%}.vue-recycle-scroller.direction-horizontal .vue-recycle-scroller__item-wrapper{height:100%}.vue-recycle-scroller.ready.direction-vertical .vue-recycle-scroller__item-view{width:100%}.vue-recycle-scroller.ready.direction-horizontal .vue-recycle-scroller__item-view{height:100%}.in-progress[data-v-5320005b]{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px;animation:in-progress-stripes-5320005b 2s linear infinite}@keyframes in-progress-stripes-5320005b{0%{background-position:40px 0}to{background-position:0 0}}.graph,.graph>svg{display:block}.graph{height:100%;touch-action:none;width:100%}.graph *{-webkit-touch-callout:none!important;-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.link{fill:none;stroke-width:4px}.node{--color-stroke: var(--color-node-stroke, rgba(0, 0, 0, .5));cursor:pointer;stroke:none;stroke-width:2px;transition:filter .25s ease,stroke .25s ease,stroke-dasharray .25s ease}.node:hover:not(.focused){filter:brightness(80%);stroke:var(--color-stroke);stroke-dasharray:4px}.node.focused{stroke:var(--color-stroke)}.link__label,.node__label{pointer-events:none;text-anchor:middle}.grabbed{cursor:grabbing!important}.splitpanes{display:flex;width:100%;height:100%}.splitpanes--vertical{flex-direction:row}.splitpanes--horizontal{flex-direction:column}.splitpanes--dragging .splitpanes__pane,*:has(.splitpanes--dragging){-webkit-user-select:none;user-select:none;pointer-events:none}.splitpanes__pane{width:100%;height:100%;overflow:hidden}.splitpanes--vertical .splitpanes__pane{transition:width .2s ease-out;will-change:width}.splitpanes--horizontal .splitpanes__pane{transition:height .2s ease-out;will-change:height}.splitpanes--dragging .splitpanes__pane{transition:none}.splitpanes__splitter{touch-action:none}.splitpanes--vertical>.splitpanes__splitter{min-width:1px;cursor:col-resize}.splitpanes--horizontal>.splitpanes__splitter{min-height:1px;cursor:row-resize}.default-theme.splitpanes .splitpanes__pane{background-color:#f2f2f2}.default-theme.splitpanes .splitpanes__splitter{background-color:#fff;box-sizing:border-box;position:relative;flex-shrink:0}.default-theme.splitpanes .splitpanes__splitter:before,.default-theme.splitpanes .splitpanes__splitter:after{content:\"\";position:absolute;top:50%;left:50%;background-color:#00000026;transition:background-color .3s}.default-theme.splitpanes .splitpanes__splitter:hover:before,.default-theme.splitpanes .splitpanes__splitter:hover:after{background-color:#00000040}.default-theme.splitpanes .splitpanes__splitter:first-child{cursor:auto}.default-theme.splitpanes .splitpanes .splitpanes__splitter{z-index:1}.default-theme.splitpanes--vertical>.splitpanes__splitter,.default-theme .splitpanes--vertical>.splitpanes__splitter{width:7px;border-left:1px solid #eee;margin-left:-1px}.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:after{transform:translateY(-50%);width:1px;height:30px}.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:before{margin-left:-2px}.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:after{margin-left:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter,.default-theme .splitpanes--horizontal>.splitpanes__splitter{height:7px;border-top:1px solid #eee;margin-top:-1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after{transform:translate(-50%);width:30px;height:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before{margin-top:-2px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after{margin-top:1px}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color, #e5e7eb)}:before,:after{--un-content: \"\"}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid black;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor .CodeMirror-line::selection,.cm-fat-cursor .CodeMirror-line>span::selection,.cm-fat-cursor .CodeMirror-line>span>span::selection{background:transparent}.cm-fat-cursor .CodeMirror-line::-moz-selection,.cm-fat-cursor .CodeMirror-line>span::-moz-selection,.cm-fat-cursor .CodeMirror-line>span>span::-moz-selection{background:transparent}.cm-fat-cursor{caret-color:transparent}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;inset:-50px 0 0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3,.cm-s-default .cm-type{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error,.cm-invalidchar{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:#ff96004d}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative;z-index:0}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none;outline:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;inset:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:none}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}div.CodeMirror-dragcursors,.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:#ff06}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:\"\"}span.CodeMirror-selectedtext{background:none}:root{--cm-scheme: light;--cm-foreground: #6e6e6e;--cm-background: #f4f4f4;--cm-comment: #a8a8a8;--cm-string: #555555;--cm-literal: #333333;--cm-keyword: #000000;--cm-function: #4f4f4f;--cm-deleted: #333333;--cm-class: #333333;--cm-builtin: #757575;--cm-property: #333333;--cm-namespace: #4f4f4f;--cm-punctuation: #ababab;--cm-decorator: var(--cm-class);--cm-operator: var(--cm-punctuation);--cm-number: var(--cm-literal);--cm-boolean: var(--cm-literal);--cm-variable: var(--cm-literal);--cm-constant: var(--cm-literal);--cm-symbol: var(--cm-literal);--cm-interpolation: var(--cm-literal);--cm-selector: var(--cm-keyword);--cm-keyword-control: var(--cm-keyword);--cm-regex: var(--cm-string);--cm-json-property: var(--cm-property);--cm-inline-background: var(--cm-background);--cm-comment-style: italic;--cm-url-decoration: underline;--cm-line-number: #a5a5a5;--cm-line-number-gutter: #333333;--cm-line-highlight-background: #eeeeee;--cm-selection-background: #aaaaaa;--cm-marker-color: var(--cm-foreground);--cm-marker-opacity: .4;--cm-marker-font-size: .8em;--cm-font-size: 1em;--cm-line-height: 1.5em;--cm-font-family: monospace;--cm-inline-font-size: var(--cm-font-size);--cm-block-font-size: var(--cm-font-size);--cm-tab-size: 2;--cm-block-padding-x: 1em;--cm-block-padding-y: 1em;--cm-block-margin-x: 0;--cm-block-margin-y: .5em;--cm-block-radius: .3em;--cm-inline-padding-x: .3em;--cm-inline-padding-y: .1em;--cm-inline-radius: .3em}.cm-s-vars.CodeMirror{background-color:var(--cm-background);color:var(--cm-foreground)}.cm-s-vars .CodeMirror-gutters{background:var(--cm-line-number-gutter);color:var(--cm-line-number);border:none}.cm-s-vars .CodeMirror-guttermarker,.cm-s-vars .CodeMirror-guttermarker-subtle,.cm-s-vars .CodeMirror-linenumber{color:var(--cm-line-number)}.cm-s-vars div.CodeMirror-selected,.cm-s-vars.CodeMirror-focused div.CodeMirror-selected{background:var(--cm-selection-background)}.cm-s-vars .CodeMirror-line::selection,.cm-s-vars .CodeMirror-line>span::selection,.cm-s-vars .CodeMirror-line>span>span::selection{background:var(--cm-selection-background)}.cm-s-vars .CodeMirror-line::-moz-selection,.cm-s-vars .CodeMirror-line>span::-moz-selection,.cm-s-vars .CodeMirror-line>span>span::-moz-selection{background:var(--cm-selection-background)}.cm-s-vars .CodeMirror-activeline-background{background:var(--cm-line-highlight-background)}.cm-s-vars .cm-keyword{color:var(--cm-keyword)}.cm-s-vars .cm-variable,.cm-s-vars .cm-variable-2,.cm-s-vars .cm-variable-3,.cm-s-vars .cm-type{color:var(--cm-variable)}.cm-s-vars .cm-builtin{color:var(--cm-builtin)}.cm-s-vars .cm-atom{color:var(--cm-literal)}.cm-s-vars .cm-number{color:var(--cm-number)}.cm-s-vars .cm-def{color:var(--cm-decorator)}.cm-s-vars .cm-string,.cm-s-vars .cm-string-2{color:var(--cm-string)}.cm-s-vars .cm-comment{color:var(--cm-comment)}.cm-s-vars .cm-tag{color:var(--cm-builtin)}.cm-s-vars .cm-meta{color:var(--cm-namespace)}.cm-s-vars .cm-attribute,.cm-s-vars .cm-property{color:var(--cm-property)}.cm-s-vars .cm-qualifier{color:var(--cm-keyword)}.cm-s-vars .cm-error{color:var(--prism-deleted)}.cm-s-vars .cm-operator,.cm-s-vars .cm-bracket{color:var(--cm-punctuation)}.cm-s-vars .CodeMirror-matchingbracket{text-decoration:underline}.cm-s-vars .CodeMirror-cursor{border-left:1px solid currentColor}html,body{height:100%;font-family:Readex Pro,sans-serif;scroll-behavior:smooth}:root{--color-text-light: #000;--color-text-dark: #ddd;--color-text: var(--color-text-light);--background-color: #e4e4e4}html.dark{--color-text: var(--color-text-dark);--background-color: #141414;color:var(--color-text);background-color:var(--background-color);color-scheme:dark}.CodeMirror{height:100%!important;width:100%!important;font-family:inherit}.cm-s-vars .cm-tag{color:var(--cm-keyword)}:root{--cm-foreground: #393a3480;--cm-background: transparent;--cm-comment: #a0ada0;--cm-string: #b56959;--cm-literal: #2f8a89;--cm-number: #296aa3;--cm-keyword: #1c6b48;--cm-function: #6c7834;--cm-boolean: #1c6b48;--cm-constant: #a65e2b;--cm-deleted: #a14f55;--cm-class: #2993a3;--cm-builtin: #ab5959;--cm-property: #b58451;--cm-namespace: #b05a78;--cm-punctuation: #8e8f8b;--cm-decorator: #bd8f8f;--cm-regex: #ab5e3f;--cm-json-property: #698c96;--cm-line-number-gutter: #f8f8f8;--cm-ttc-c-thumb: #eee;--cm-ttc-c-track: white}html.dark{--cm-scheme: dark;--cm-foreground: #d4cfbf80;--cm-background: transparent;--cm-comment: #758575;--cm-string: #d48372;--cm-literal: #429988;--cm-keyword: #4d9375;--cm-boolean: #1c6b48;--cm-number: #6394bf;--cm-variable: #c2b36e;--cm-function: #a1b567;--cm-deleted: #a14f55;--cm-class: #54b1bf;--cm-builtin: #e0a569;--cm-property: #dd8e6e;--cm-namespace: #db889a;--cm-punctuation: #858585;--cm-decorator: #bd8f8f;--cm-regex: #ab5e3f;--cm-json-property: #6b8b9e;--cm-line-number: #888888;--cm-line-number-gutter: #161616;--cm-line-highlight-background: #444444;--cm-selection-background: #44444450;--cm-ttc-c-thumb: #222;--cm-ttc-c-track: #111}.splitpanes__pane{background-color:unset!important}.splitpanes__splitter{position:relative;background-color:#7d7d7d1a;z-index:10}.splitpanes__splitter:before{content:\"\";position:absolute;left:0;top:0;transition:opacity .4s;background-color:#7d7d7d1a;opacity:0;z-index:1}.splitpanes__splitter:hover:before{opacity:1}.splitpanes--vertical>.splitpanes__splitter:before{left:0;right:-10px;height:100%}.splitpanes--horizontal>.splitpanes__splitter:before{top:0;bottom:-10px;width:100%}.splitpanes.loading .splitpanes__pane{transition:none!important;height:100%}.CodeMirror-scroll{scrollbar-width:none}.CodeMirror-scroll::-webkit-scrollbar,.codemirror-scrolls::-webkit-scrollbar{display:none}.codemirror-scrolls{overflow:auto!important;scrollbar-width:thin;scrollbar-color:var(--cm-ttc-c-thumb) var(--cm-ttc-c-track)}.CodeMirror-simplescroll-horizontal,.CodeMirror-simplescroll-vertical{background-color:var(--cm-ttc-c-track)!important;border:none!important}.CodeMirror-simplescroll-horizontal div,.CodeMirror-simplescroll-vertical div{background-color:var(--cm-ttc-c-thumb)!important;border:none!important}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:var(--cm-ttc-c-track)!important}.CodeMirror{overflow:unset!important}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar{display:none!important}.CodeMirror-scroll{margin-bottom:unset!important;margin-right:unset!important;padding-bottom:unset!important}.scrolls::-webkit-scrollbar{width:8px;height:8px}.scrolls{overflow:auto!important;scrollbar-width:thin;scrollbar-color:var(--cm-ttc-c-thumb) var(--cm-ttc-c-track)}.scrolls::-webkit-scrollbar-track{background:var(--cm-ttc-c-track)}.scrolls::-webkit-scrollbar-thumb{background-color:var(--cm-ttc-c-thumb);border:2px solid var(--cm-ttc-c-thumb)}.scrolls::-webkit-scrollbar-thumb,.scrolls-rounded::-webkit-scrollbar-track{border-radius:3px}.scrolls::-webkit-scrollbar-corner{background-color:var(--cm-ttc-c-track)}.v-popper__popper .v-popper__inner{font-size:12px;padding:4px 6px;border-radius:4px;background-color:var(--background-color);color:var(--color-text)}.v-popper__popper .v-popper__arrow-outer{border-color:var(--background-color)}.codemirror-busy>.CodeMirror>.CodeMirror-scroll>.CodeMirror-sizer .CodeMirror-lines{cursor:wait!important}.resize-observer[data-v-b329ee4c]{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;border:none;background-color:transparent;pointer-events:none;display:block;overflow:hidden;opacity:0}.resize-observer[data-v-b329ee4c] object{display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1}.v-popper__popper{z-index:10000;top:0;left:0;outline:none}.v-popper__popper.v-popper__popper--hidden{visibility:hidden;opacity:0;transition:opacity .15s,visibility .15s;pointer-events:none}.v-popper__popper.v-popper__popper--shown{visibility:visible;opacity:1;transition:opacity .15s}.v-popper__popper.v-popper__popper--skip-transition,.v-popper__popper.v-popper__popper--skip-transition>.v-popper__wrapper{transition:none!important}.v-popper__backdrop{position:absolute;top:0;left:0;width:100%;height:100%;display:none}.v-popper__inner{position:relative;box-sizing:border-box;overflow-y:auto}.v-popper__inner>div{position:relative;z-index:1;max-width:inherit;max-height:inherit}.v-popper__arrow-container{position:absolute;width:10px;height:10px}.v-popper__popper--arrow-overflow .v-popper__arrow-container,.v-popper__popper--no-positioning .v-popper__arrow-container{display:none}.v-popper__arrow-inner,.v-popper__arrow-outer{border-style:solid;position:absolute;top:0;left:0;width:0;height:0}.v-popper__arrow-inner{visibility:hidden;border-width:7px}.v-popper__arrow-outer{border-width:6px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner{left:-2px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{left:-1px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer{border-bottom-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-container{top:0}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{border-top-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-top-color:transparent!important}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner{top:-4px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{top:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{top:-1px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{border-left-width:0;border-left-color:transparent!important;border-top-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{left:-4px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{left:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-container{right:-10px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer{border-right-width:0;border-top-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner{left:-2px}.v-popper--theme-tooltip .v-popper__inner{background:#000c;color:#fff;border-radius:6px;padding:7px 12px 6px}.v-popper--theme-tooltip .v-popper__arrow-outer{border-color:#000c}.v-popper--theme-dropdown .v-popper__inner{background:#fff;color:#000;border-radius:6px;border:1px solid #ddd;box-shadow:0 6px 30px #0000001a}.v-popper--theme-dropdown .v-popper__arrow-inner{visibility:visible;border-color:#fff}.v-popper--theme-dropdown .v-popper__arrow-outer{border-color:#ddd}*,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }.dark .dark\\:i-carbon-moon{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M13.503 5.414a15.076 15.076 0 0 0 11.593 18.194a11.1 11.1 0 0 1-7.975 3.39c-.138 0-.278.005-.418 0a11.094 11.094 0 0 1-3.2-21.584M14.98 3a1 1 0 0 0-.175.016a13.096 13.096 0 0 0 1.825 25.981c.164.006.328 0 .49 0a13.07 13.07 0 0 0 10.703-5.555a1.01 1.01 0 0 0-.783-1.565A13.08 13.08 0 0 1 15.89 4.38A1.015 1.015 0 0 0 14.98 3'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-arrow-left{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m14 26l1.41-1.41L7.83 17H28v-2H7.83l7.58-7.59L14 6L4 16z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-checkmark,.i-carbon\\:checkmark,[i-carbon-checkmark=\"\"],[i-carbon\\:checkmark=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m13 24l-9-9l1.414-1.414L13 21.171L26.586 7.586L28 9z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-checkmark-outline-error,[i-carbon-checkmark-outline-error=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M14 24a10 10 0 1 1 10-10h2a12 12 0 1 0-12 12Z'/%3E%3Cpath fill='currentColor' d='M12 15.59L9.41 13L8 14.41l4 4l7-7L17.59 10zM30 24a6 6 0 1 0-6 6a6.007 6.007 0 0 0 6-6m-2 0a3.95 3.95 0 0 1-.567 2.019l-5.452-5.452A3.95 3.95 0 0 1 24 20a4.005 4.005 0 0 1 4 4m-8 0a3.95 3.95 0 0 1 .567-2.019l5.452 5.452A3.95 3.95 0 0 1 24 28a4.005 4.005 0 0 1-4-4'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-close,.i-carbon\\:close,[i-carbon-close=\"\"],[i-carbon\\:close=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M17.414 16L24 9.414L22.586 8L16 14.586L9.414 8L8 9.414L14.586 16L8 22.586L9.414 24L16 17.414L22.586 24L24 22.586z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-compare,.i-carbon\\:compare,[i-carbon-compare=\"\"],[i-carbon\\:compare=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M28 6H18V4a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h10v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2M4 15h6.17l-2.58 2.59L9 19l5-5l-5-5l-1.41 1.41L10.17 13H4V4h12v20H4Zm12 13v-2a2 2 0 0 0 2-2V8h10v9h-6.17l2.58-2.59L23 13l-5 5l5 5l1.41-1.41L21.83 19H28v9Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-content-delivery-network{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Ccircle cx='21' cy='21' r='2' fill='currentColor'/%3E%3Ccircle cx='7' cy='7' r='2' fill='currentColor'/%3E%3Cpath fill='currentColor' d='M27 31a4 4 0 1 1 4-4a4.01 4.01 0 0 1-4 4m0-6a2 2 0 1 0 2 2a2.006 2.006 0 0 0-2-2'/%3E%3Cpath fill='currentColor' d='M30 16A14.04 14.04 0 0 0 16 2a13.04 13.04 0 0 0-6.8 1.8l1.1 1.7a24 24 0 0 1 2.4-1A25.1 25.1 0 0 0 10 15H4a11.15 11.15 0 0 1 1.4-4.7L3.9 9A13.84 13.84 0 0 0 2 16a14 14 0 0 0 14 14a13.4 13.4 0 0 0 5.2-1l-.6-1.9a11.44 11.44 0 0 1-5.2.9A21.07 21.07 0 0 1 12 17h17.9a3.4 3.4 0 0 0 .1-1M12.8 27.6a13 13 0 0 1-5.3-3.1A12.5 12.5 0 0 1 4 17h6a25 25 0 0 0 2.8 10.6M12 15a21.45 21.45 0 0 1 3.3-11h1.4A21.45 21.45 0 0 1 20 15Zm10 0a23.3 23.3 0 0 0-2.8-10.6A12.09 12.09 0 0 1 27.9 15Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-dashboard,.i-carbon\\:dashboard{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M24 21h2v5h-2zm-4-5h2v10h-2zm-9 10a5.006 5.006 0 0 1-5-5h2a3 3 0 1 0 3-3v-2a5 5 0 0 1 0 10'/%3E%3Cpath fill='currentColor' d='M28 2H4a2 2 0 0 0-2 2v24a2 2 0 0 0 2 2h24a2.003 2.003 0 0 0 2-2V4a2 2 0 0 0-2-2m0 9H14V4h14ZM12 4v7H4V4ZM4 28V13h24l.002 15Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-document,[i-carbon-document=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m25.7 9.3l-7-7c-.2-.2-.4-.3-.7-.3H8c-1.1 0-2 .9-2 2v24c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V10c0-.3-.1-.5-.3-.7M18 4.4l5.6 5.6H18zM24 28H8V4h8v6c0 1.1.9 2 2 2h6z'/%3E%3Cpath fill='currentColor' d='M10 22h12v2H10zm0-6h12v2H10z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-ibm-cloud-direct-link-2-connect{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M17.2 13c.4 1.2 1.5 2 2.8 2c1.7 0 3-1.3 3-3s-1.3-3-3-3c-1.3 0-2.4.8-2.8 2H5c-1.1 0-2 .9-2 2v6H0v2h3v6c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-4h-2v4H5V13zm2.8-2c.6 0 1 .4 1 1s-.4 1-1 1s-1-.4-1-1s.4-1 1-1'/%3E%3Cpath fill='currentColor' d='M29 11V5c0-1.1-.9-2-2-2H13c-1.1 0-2 .9-2 2v4h2V5h14v14H14.8c-.4-1.2-1.5-2-2.8-2c-1.7 0-3 1.3-3 3s1.3 3 3 3c1.3 0 2.4-.8 2.8-2H27c1.1 0 2-.9 2-2v-6h3v-2zM12 21c-.6 0-1-.4-1-1s.4-1 1-1s1 .4 1 1s-.4 1-1 1'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-launch{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 28H6a2.003 2.003 0 0 1-2-2V6a2.003 2.003 0 0 1 2-2h10v2H6v20h20V16h2v10a2.003 2.003 0 0 1-2 2'/%3E%3Cpath fill='currentColor' d='M20 2v2h6.586L18 12.586L19.414 14L28 5.414V12h2V2z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-notebook{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 10h7v2h-7zm0 5h7v2h-7zm0 5h7v2h-7z'/%3E%3Cpath fill='currentColor' d='M28 5H4a2 2 0 0 0-2 2v18a2 2 0 0 0 2 2h24a2.003 2.003 0 0 0 2-2V7a2 2 0 0 0-2-2M4 7h11v18H4Zm13 18V7h11l.002 18Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-reset{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M18 28A12 12 0 1 0 6 16v6.2l-3.6-3.6L1 20l6 6l6-6l-1.4-1.4L8 22.2V16a10 10 0 1 1 10 10Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-timer,[i-carbon-timer=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M15 11h2v9h-2zm-2-9h6v2h-6z'/%3E%3Cpath fill='currentColor' d='m28 9l-1.42-1.41l-2.25 2.25a10.94 10.94 0 1 0 1.18 1.65ZM16 26a9 9 0 1 1 9-9a9 9 0 0 1-9 9'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon-wifi-off{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Ccircle cx='16' cy='25' r='2' fill='currentColor'/%3E%3Cpath fill='currentColor' d='M30 3.414L28.586 2L2 28.586L3.414 30l10.682-10.682a5.94 5.94 0 0 1 6.01 1.32l1.414-1.414a7.97 7.97 0 0 0-5.125-2.204l3.388-3.388a12 12 0 0 1 4.564 2.765l1.413-1.414a14 14 0 0 0-4.426-2.903l2.997-2.997a18 18 0 0 1 4.254 3.075L30 10.743v-.002a20 20 0 0 0-4.19-3.138zm-15.32 9.664l2.042-2.042C16.48 11.023 16.243 11 16 11a13.95 13.95 0 0 0-9.771 3.993l1.414 1.413a11.97 11.97 0 0 1 7.037-3.328M16 7a18 18 0 0 1 4.232.525l1.643-1.642A19.95 19.95 0 0 0 2 10.74v.023l1.404 1.404A17.92 17.92 0 0 1 16 7'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:chart-relationship{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 6a3.996 3.996 0 0 0-3.858 3H17.93A7.996 7.996 0 1 0 9 17.93v4.212a4 4 0 1 0 2 0v-4.211a7.95 7.95 0 0 0 3.898-1.62l3.669 3.67A3.95 3.95 0 0 0 18 22a4 4 0 1 0 4-4a3.95 3.95 0 0 0-2.019.567l-3.67-3.67A7.95 7.95 0 0 0 17.932 11h4.211A3.993 3.993 0 1 0 26 6M12 26a2 2 0 1 1-2-2a2 2 0 0 1 2 2m-2-10a6 6 0 1 1 6-6a6.007 6.007 0 0 1-6 6m14 6a2 2 0 1 1-2-2a2 2 0 0 1 2 2m2-10a2 2 0 1 1 2-2a2 2 0 0 1-2 2'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:checkbox{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2M6 26V6h20v20Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:checkbox-checked-filled{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2M14 21.5l-5-4.957L10.59 15L14 18.346L21.409 11L23 12.577Z'/%3E%3Cpath fill='none' d='m14 21.5l-5-4.957L10.59 15L14 18.346L21.409 11L23 12.577Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:chevron-down{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M16 22L6 12l1.4-1.4l8.6 8.6l8.6-8.6L26 12z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:chevron-right{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M22 16L12 26l-1.4-1.4l8.6-8.6l-8.6-8.6L12 6z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:circle-dash,[i-carbon\\:circle-dash=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M7.7 4.7a14.7 14.7 0 0 0-3 3.1L6.3 9a13.3 13.3 0 0 1 2.6-2.7zm-3.1 7.6l-1.9-.6A12.5 12.5 0 0 0 2 16h2a11.5 11.5 0 0 1 .6-3.7m-1.9 8.1a14.4 14.4 0 0 0 2 3.9l1.6-1.2a12.9 12.9 0 0 1-1.7-3.3zm5.1 6.9a14.4 14.4 0 0 0 3.9 2l.6-1.9A12.9 12.9 0 0 1 9 25.7zm3.9-24.6l.6 1.9A11.5 11.5 0 0 1 16 4V2a12.5 12.5 0 0 0-4.3.7m12.5 24.6a15.2 15.2 0 0 0 3.1-3.1L25.7 23a11.5 11.5 0 0 1-2.7 2.7zm3.2-7.6l1.9.6A15.5 15.5 0 0 0 30 16h-2a11.5 11.5 0 0 1-.6 3.7m1.8-8.1a14.4 14.4 0 0 0-2-3.9l-1.6 1.2a12.9 12.9 0 0 1 1.7 3.3zm-5.1-7a14.4 14.4 0 0 0-3.9-2l-.6 1.9a12.9 12.9 0 0 1 3.3 1.7zm-3.8 24.7l-.6-1.9a11.5 11.5 0 0 1-3.7.6v2a21.4 21.4 0 0 0 4.3-.7'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:code{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m31 16l-7 7l-1.41-1.41L28.17 16l-5.58-5.59L24 9zM1 16l7-7l1.41 1.41L3.83 16l5.58 5.59L8 23zm11.42 9.484L17.64 6l1.932.517L14.352 26z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:code-reference,[i-carbon\\:code-reference=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M4 20v2h4.586L2 28.586L3.414 30L10 23.414V28h2v-8zm26-10l-6-6l-1.414 1.414L27.172 10l-4.586 4.586L24 16zm-16.08 7.484l4.15-15.483l1.932.517l-4.15 15.484zM4 10l6-6l1.414 1.414L6.828 10l4.586 4.586L10 16z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:collapse-all{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M30 15h-2V7H13V5h15a2 2 0 0 1 2 2Z'/%3E%3Cpath fill='currentColor' d='M25 20h-2v-8H8v-2h15a2 2 0 0 1 2 2Z'/%3E%3Cpath fill='currentColor' d='M18 27H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2M4 17v8h14.001L18 17Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:document-blank,[i-carbon\\:document-blank=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m25.7 9.3l-7-7A.9.9 0 0 0 18 2H8a2.006 2.006 0 0 0-2 2v24a2.006 2.006 0 0 0 2 2h16a2.006 2.006 0 0 0 2-2V10a.9.9 0 0 0-.3-.7M18 4.4l5.6 5.6H18ZM24 28H8V4h8v6a2.006 2.006 0 0 0 2 2h6Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:download{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M26 24v4H6v-4H4v4a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2v-4zm0-10l-1.41-1.41L17 20.17V2h-2v18.17l-7.59-7.58L6 14l10 10z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:expand-all{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 10h14a2.003 2.003 0 0 0 2-2V4a2.003 2.003 0 0 0-2-2H12a2.003 2.003 0 0 0-2 2v1H6V2H4v23a2.003 2.003 0 0 0 2 2h4v1a2.003 2.003 0 0 0 2 2h14a2.003 2.003 0 0 0 2-2v-4a2.003 2.003 0 0 0-2-2H12a2.003 2.003 0 0 0-2 2v1H6v-8h4v1a2.003 2.003 0 0 0 2 2h14a2.003 2.003 0 0 0 2-2v-4a2.003 2.003 0 0 0-2-2H12a2.003 2.003 0 0 0-2 2v1H6V7h4v1a2.003 2.003 0 0 0 2 2m0-6h14l.001 4H12Zm0 20h14l.001 4H12Zm0-10h14l.001 4H12Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:filter{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M18 28h-4a2 2 0 0 1-2-2v-7.59L4.59 11A2 2 0 0 1 4 9.59V6a2 2 0 0 1 2-2h20a2 2 0 0 1 2 2v3.59a2 2 0 0 1-.59 1.41L20 18.41V26a2 2 0 0 1-2 2M6 6v3.59l8 8V26h4v-8.41l8-8V6Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:filter-remove{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M30 11.414L28.586 10L24 14.586L19.414 10L18 11.414L22.586 16L18 20.585L19.415 22L24 17.414L28.587 22L30 20.587L25.414 16z'/%3E%3Cpath fill='currentColor' d='M4 4a2 2 0 0 0-2 2v3.17a2 2 0 0 0 .586 1.415L10 18v8a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-2h-2v2h-4v-8.83l-.586-.585L4 9.171V6h20v2h2V6a2 2 0 0 0-2-2Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:folder-details-reference{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M16 28h7v2h-7zm0-4h14v2H16zm0-4h14v2H16zM4 20v2h4.586L2 28.586L3.414 30L10 23.414V28h2v-8zM28 8H16l-3.414-3.414A2 2 0 0 0 11.172 4H4a2 2 0 0 0-2 2v12h2V6h7.172l3.414 3.414l.586.586H28v8h2v-8a2 2 0 0 0-2-2'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:folder-off{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M28 8h-2.586L30 3.414L28.586 2L2 28.586L3.414 30l2-2H28a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2m0 18H7.414l16-16H28zM4 6h7.172l3.414 3.414l.586.586H18V8h-2l-3.414-3.414A2 2 0 0 0 11.172 4H4a2 2 0 0 0-2 2v18h2z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:image{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 14a3 3 0 1 0-3-3a3 3 0 0 0 3 3m0-4a1 1 0 1 1-1 1a1 1 0 0 1 1-1'/%3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2m0 22H6v-6l5-5l5.59 5.59a2 2 0 0 0 2.82 0L21 19l5 5Zm0-4.83l-3.59-3.59a2 2 0 0 0-2.82 0L18 19.17l-5.59-5.59a2 2 0 0 0-2.82 0L6 17.17V6h20Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:image-reference{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M4 20v2h4.586L2 28.586L3.414 30L10 23.414V28h2v-8zm15-6a3 3 0 1 0-3-3a3 3 0 0 0 3 3m0-4a1 1 0 1 1-1 1a1 1 0 0 1 1-1'/%3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v10h2V6h20v15.17l-3.59-3.59a2 2 0 0 0-2.82 0L18 19.17L11.83 13l-1.414 1.416L14 18l2.59 2.59a2 2 0 0 0 2.82 0L21 19l5 5v2H16v2h10a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:information-square,[i-carbon\\:information-square=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M17 22v-8h-4v2h2v6h-3v2h8v-2zM16 8a1.5 1.5 0 1 0 1.5 1.5A1.5 1.5 0 0 0 16 8'/%3E%3Cpath fill='currentColor' d='M26 28H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h20a2 2 0 0 1 2 2v20a2 2 0 0 1-2 2M6 6v20h20V6Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:intrusion-prevention{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Ccircle cx='22' cy='23.887' r='2' fill='currentColor'/%3E%3Cpath fill='currentColor' d='M29.777 23.479A8.64 8.64 0 0 0 22 18a8.64 8.64 0 0 0-7.777 5.479L14 24l.223.522A8.64 8.64 0 0 0 22 30a8.64 8.64 0 0 0 7.777-5.478L30 24zM22 28a4 4 0 1 1 4-4a4.005 4.005 0 0 1-4 4m3-18H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h21a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2M4 4v4h21V4zm8 24H4v-4h8v-2H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h8z'/%3E%3Cpath fill='currentColor' d='M28 12H7a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h5v-2H7v-4h21v2h2v-2a2 2 0 0 0-2-2'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:mobile{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M22 4H10a2 2 0 0 0-2 2v22a2 2 0 0 0 2 2h12a2.003 2.003 0 0 0 2-2V6a2 2 0 0 0-2-2m0 2v2H10V6ZM10 28V10h12v18Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:mobile-add{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M28 24h-4v-4h-2v4h-4v2h4v4h2v-4h4z'/%3E%3Cpath fill='currentColor' d='M10 28V10h12v7h2V6a2 2 0 0 0-2-2H10a2 2 0 0 0-2 2v22a2 2 0 0 0 2 2h6v-2Zm0-22h12v2H10Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:play{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M7 28a1 1 0 0 1-1-1V5a1 1 0 0 1 1.482-.876l20 11a1 1 0 0 1 0 1.752l-20 11A1 1 0 0 1 7 28M8 6.69v18.62L24.925 16Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:play-filled-alt{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M7 28a1 1 0 0 1-1-1V5a1 1 0 0 1 1.482-.876l20 11a1 1 0 0 1 0 1.752l-20 11A1 1 0 0 1 7 28'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:redo,[i-carbon\\:redo=\"\"]{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 10h12.185l-3.587-3.586L22 5l6 6l-6 6l-1.402-1.415L24.182 12H12a6 6 0 0 0 0 12h8v2h-8a8 8 0 0 1 0-16'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:renew{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 10H6.78A11 11 0 0 1 27 16h2A13 13 0 0 0 6 7.68V4H4v8h8zm8 12h5.22A11 11 0 0 1 5 16H3a13 13 0 0 0 23 8.32V28h2v-8h-8z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:report{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M10 18h8v2h-8zm0-5h12v2H10zm0 10h5v2h-5z'/%3E%3Cpath fill='currentColor' d='M25 5h-3V4a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v1H7a2 2 0 0 0-2 2v21a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2M12 4h8v4h-8Zm13 24H7V7h3v3h12V7h3Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:result-old{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M10 13h2v2h-2zm4 0h8v2h-8zm-4 5h2v2h-2zm0 5h2v2h-2z'/%3E%3Cpath fill='currentColor' d='M7 28V7h3v3h12V7h3v8h2V7a2 2 0 0 0-2-2h-3V4a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v1H7a2 2 0 0 0-2 2v21a2 2 0 0 0 2 2h9v-2Zm5-24h8v4h-8Z'/%3E%3Cpath fill='currentColor' d='M18 19v2.413A6.996 6.996 0 1 1 24 32v-2a5 5 0 1 0-4.576-7H22v2h-6v-6Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:search{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m29 27.586l-7.552-7.552a11.018 11.018 0 1 0-1.414 1.414L27.586 29ZM4 13a9 9 0 1 1 9 9a9.01 9.01 0 0 1-9-9'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:side-panel-close{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M28 4H4c-1.1 0-2 .9-2 2v20c0 1.1.9 2 2 2h24c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2M10 26H4V6h6zm18-11H17.8l3.6-3.6L20 10l-6 6l6 6l1.4-1.4l-3.6-3.6H28v9H12V6h16z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:sun{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M16 12.005a4 4 0 1 1-4 4a4.005 4.005 0 0 1 4-4m0-2a6 6 0 1 0 6 6a6 6 0 0 0-6-6M5.394 6.813L6.81 5.399l3.505 3.506L8.9 10.319zM2 15.005h5v2H2zm3.394 10.193L8.9 21.692l1.414 1.414l-3.505 3.506zM15 25.005h2v5h-2zm6.687-1.9l1.414-1.414l3.506 3.506l-1.414 1.414zm3.313-8.1h5v2h-5zm-3.313-6.101l3.506-3.506l1.414 1.414l-3.506 3.506zM15 2.005h2v5h-2z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:tablet{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M19 24v2h-6v-2z'/%3E%3Cpath fill='currentColor' d='M25 30H7a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h18a2 2 0 0 1 2 2v24a2.003 2.003 0 0 1-2 2M7 4v24h18V4Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-carbon\\:terminal-3270{--un-icon:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 32 32' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M10 21h6v2h-6z'/%3E%3Cpath fill='currentColor' d='M26 4H6a2 2 0 0 0-2 2v20a2 2 0 0 0 2 2h20a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2m0 2v4H6V6ZM6 26V12h20v14Z'/%3E%3C/svg%3E\");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em}.i-logos\\:typescript-icon{background:url(\"data:image/svg+xml;utf8,%3Csvg viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='%233178C6' d='M20 0h216c11.046 0 20 8.954 20 20v216c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20V20C0 8.954 8.954 0 20 0'/%3E%3Cpath fill='%23FFF' d='M150.518 200.475v27.62q6.738 3.453 15.938 5.179T185.849 235q9.934 0 18.874-1.899t15.678-6.257q6.738-4.359 10.669-11.394q3.93-7.033 3.93-17.391q0-7.51-2.246-13.163a30.8 30.8 0 0 0-6.479-10.055q-4.232-4.402-10.149-7.898t-13.347-6.602q-5.442-2.245-9.761-4.359t-7.342-4.316q-3.024-2.2-4.665-4.661t-1.641-5.567q0-2.848 1.468-5.135q1.469-2.288 4.147-3.927t6.565-2.547q3.887-.906 8.638-.906q3.456 0 7.299.518q3.844.517 7.732 1.597a54 54 0 0 1 7.558 2.719a41.7 41.7 0 0 1 6.781 3.797v-25.807q-6.306-2.417-13.778-3.582T198.633 107q-9.847 0-18.658 2.115q-8.811 2.114-15.506 6.602q-6.694 4.49-10.582 11.437Q150 134.102 150 143.769q0 12.342 7.127 21.06t21.638 14.759a292 292 0 0 1 10.625 4.575q4.924 2.244 8.509 4.66t5.658 5.265t2.073 6.474a9.9 9.9 0 0 1-1.296 4.963q-1.295 2.287-3.93 3.97t-6.565 2.632t-9.2.95q-8.983 0-17.794-3.151t-16.327-9.451m-46.036-68.733H140V109H41v22.742h35.345V233h28.137z'/%3E%3C/svg%3E\") no-repeat;background-size:100% 100%;background-color:transparent;width:1em;height:1em}.container{width:100%}.tab-button,[tab-button=\"\"]{height:100%;padding-left:1rem;padding-right:1rem;font-weight:300;opacity:.5}.border-base,[border~=base]{border-color:#6b72801a}.bg-active{background-color:#6b728014}.bg-base,[bg-base=\"\"]{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity))}.dark .bg-base,.dark [bg-base=\"\"]{--un-bg-opacity:1;background-color:rgb(17 17 17 / var(--un-bg-opacity))}.bg-header,[bg-header=\"\"]{background-color:#6b72800d}.bg-overlay,[bg-overlay=\"\"],[bg~=overlay]{background-color:#eeeeee80}.dark .bg-overlay,.dark [bg-overlay=\"\"],.dark [bg~=overlay]{background-color:#22222280}.dark .highlight{--un-bg-opacity:1;background-color:rgb(50 50 56 / var(--un-bg-opacity));--un-text-opacity:1;color:rgb(234 179 6 / var(--un-text-opacity))}.highlight{--un-bg-opacity:1;background-color:rgb(234 179 6 / var(--un-bg-opacity));--un-text-opacity:1;color:rgb(50 50 56 / var(--un-text-opacity))}.tab-button-active{background-color:#6b72801a;opacity:1}[hover~=bg-active]:hover{background-color:#6b728014}.tab-button:hover,[tab-button=\"\"]:hover{opacity:.8}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.\\[clip-path\\:polygon\\(0\\%_0\\%\\,var\\(--split\\)_0\\%\\,var\\(--split\\)_100\\%\\,0\\%_100\\%\\)\\]{clip-path:polygon(0% 0%,var(--split) 0%,var(--split) 100%,0% 100%)}.\\[clip-path\\:polygon\\(var\\(--split\\)_0\\%\\,100\\%_0\\%\\,100\\%_100\\%\\,var\\(--split\\)_100\\%\\)\\]{clip-path:polygon(var(--split) 0%,100% 0%,100% 100%,var(--split) 100%)}.sr-only,[sr-only=\"\"]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none,[pointer-events-none=\"\"]{pointer-events:none}.absolute,[absolute=\"\"]{position:absolute}.fixed,[fixed=\"\"]{position:fixed}.relative,[relative=\"\"]{position:relative}.sticky,[sticky=\"\"]{position:sticky}.before\\:absolute:before{position:absolute}.static{position:static}.inset-0,[inset-0=\"\"]{inset:0}.bottom-0{bottom:0}.left-\\[--split\\]{left:var(--split)}.left-0{left:0}.right-0,[right~=\"0\"]{right:0}.right-5px,[right-5px=\"\"]{right:5px}.top-0{top:0}.top-5px,[top-5px=\"\"]{top:5px}[top~=\"-1\"]{top:-.25rem}.before\\:top-1\\/2:before{top:50%}.z-10,[z-10=\"\"]{z-index:10}.z-40{z-index:40}.z-5,[z-5=\"\"]{z-index:5}.grid,[grid~=\"~\"]{display:grid}.grid-col-span-2{grid-column:span 2/span 2}.grid-col-span-4,[grid-col-span-4=\"\"],[grid-col-span-4~=\"~\"]{grid-column:span 4/span 4}[grid-col-span-4~=\"placeholder:\"]::placeholder{grid-column:span 4/span 4}.auto-cols-max,[grid~=auto-cols-max]{grid-auto-columns:max-content}.cols-\\[1\\.5em_1fr\\],[grid~=\"cols-[1.5em_1fr]\"]{grid-template-columns:1.5em 1fr}.cols-\\[auto_min-content_auto\\],[grid~=\"cols-[auto_min-content_auto]\"]{grid-template-columns:auto min-content auto}.cols-\\[min-content_1fr_min-content\\],[grid~=\"cols-[min-content_1fr_min-content]\"]{grid-template-columns:min-content 1fr min-content}.rows-\\[auto_auto\\],[grid~=\"rows-[auto_auto]\"]{grid-template-rows:auto auto}.rows-\\[min-content_auto\\],[grid~=\"rows-[min-content_auto]\"]{grid-template-rows:min-content auto}.rows-\\[min-content_min-content\\],[grid~=\"rows-[min-content_min-content]\"]{grid-template-rows:min-content min-content}.rows-\\[min-content\\],[grid~=\"rows-[min-content]\"]{grid-template-rows:min-content}.cols-1,.grid-cols-1,[grid~=cols-1]{grid-template-columns:repeat(1,minmax(0,1fr))}.cols-2,.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.rows-1,[grid~=rows-1]{grid-template-rows:repeat(1,minmax(0,1fr))}.m-0{margin:0}.m-2,[m-2=\"\"]{margin:.5rem}.ma,[ma=\"\"]{margin:auto}.mx-1,[mx-1=\"\"]{margin-left:.25rem;margin-right:.25rem}.mx-2,[m~=x-2],[mx-2=\"\"]{margin-left:.5rem;margin-right:.5rem}.mx-4,[mx-4=\"\"]{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0,[my-0=\"\"]{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2,[my-2=\"\"]{margin-top:.5rem;margin-bottom:.5rem}[m~=y-4]{margin-top:1rem;margin-bottom:1rem}.-mt-5{margin-top:-1.25rem}.\\!mb-none{margin-bottom:0!important}.mb-1,[mb-1=\"\"]{margin-bottom:.25rem}.mb-1px{margin-bottom:1px}.mb-2,[mb-2=\"\"]{margin-bottom:.5rem}.mb-5{margin-bottom:1.25rem}.ml-1,[ml-1=\"\"]{margin-left:.25rem}.ml-2,[ml-2=\"\"]{margin-left:.5rem}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-8,[mr-8=\"\"]{margin-right:2rem}.ms,[ms=\"\"]{margin-inline-start:1rem}.ms-2,[ms-2=\"\"]{margin-inline-start:.5rem}.mt-\\[8px\\]{margin-top:8px}.mt-2,[m~=t2],[mt-2=\"\"]{margin-top:.5rem}.mt-3{margin-top:.75rem}.inline,[inline=\"\"]{display:inline}.block,[block=\"\"]{display:block}.inline-block{display:inline-block}.hidden{display:none}.before\\:size-\\[16px\\]:before{width:16px;height:16px}.h-1\\.4em,[h-1\\.4em=\"\"]{height:1.4em}.h-1\\.5em{height:1.5em}.h-10,[h-10=\"\"]{height:2.5rem}.h-1px,[h-1px=\"\"]{height:1px}.h-28px,[h-28px=\"\"]{height:28px}.h-3px,[h-3px=\"\"]{height:3px}.h-41px,[h-41px=\"\"]{height:41px}.h-6,[h-6=\"\"]{height:1.5rem}.h-8,[h-8=\"\"]{height:2rem}.h-full,[h-full=\"\"],[h~=full]{height:100%}.h-screen,[h-screen=\"\"]{height:100vh}.h1{height:.25rem}.h3{height:.75rem}.h4{height:1rem}.max-h-120{max-height:30rem}.max-h-full,[max-h-full=\"\"]{max-height:100%}.max-w-full{max-width:100%}.max-w-screen,[max-w-screen=\"\"]{max-width:100vw}.max-w-xl,[max-w-xl=\"\"]{max-width:36rem}.min-h-1em{min-height:1em}.min-h-75,[min-h-75=\"\"]{min-height:18.75rem}.min-w-1em{min-width:1em}.min-w-2em,[min-w-2em=\"\"]{min-width:2em}.w-\\[2px\\],.w-2px,[w-2px=\"\"]{width:2px}.w-1\\.4em,[w-1\\.4em=\"\"]{width:1.4em}.w-1\\.5em,[w-1\\.5em=\"\"]{width:1.5em}.w-350,[w-350=\"\"]{width:87.5rem}.w-4,[w-4=\"\"]{width:1rem}.w-6,[w-6=\"\"]{width:1.5rem}.w-80,[w-80=\"\"]{width:20rem}.w-fit{width:fit-content}.w-full,[w-full=\"\"]{width:100%}.w-min{width:min-content}.w-screen,[w-screen=\"\"]{width:100vw}.open\\:max-h-52[open],[open\\:max-h-52=\"\"][open]{max-height:13rem}.flex,[flex=\"\"],[flex~=\"~\"]{display:flex}.flex-inline,.inline-flex,[inline-flex=\"\"]{display:inline-flex}.flex-1,[flex-1=\"\"]{flex:1 1 0%}.flex-auto,[flex-auto=\"\"]{flex:1 1 auto}.flex-shrink-0,[flex-shrink-0=\"\"]{flex-shrink:0}.flex-grow-1,[flex-grow-1=\"\"]{flex-grow:1}.flex-col,[flex-col=\"\"],[flex~=col]{flex-direction:column}[flex~=wrap]{flex-wrap:wrap}.table{display:table}.origin-center,[origin-center=\"\"]{transform-origin:center}.origin-top{transform-origin:top}.-translate-x-1\\/2{--un-translate-x:-50%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.translate-x-3,[translate-x-3=\"\"]{--un-translate-x:.75rem;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.before\\:-translate-y-1\\/2:before{--un-translate-y:-50%;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.before\\:translate-x-\\[calc\\(-50\\%\\+1px\\)\\]:before{--un-translate-x: calc(-50% + 1px) ;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.rotate-0,[rotate-0=\"\"]{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:0deg;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.rotate-180,[rotate-180=\"\"]{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:180deg;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.rotate-90,[rotate-90=\"\"]{--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-rotate:90deg;transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.transform{transform:translate(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotate(var(--un-rotate-z)) skew(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.animate-spin,[animate-spin=\"\"]{animation:spin 1s linear infinite}.animate-reverse{animation-direction:reverse}.animate-count-1,[animate-count-1=\"\"]{animation-iteration-count:1}.cursor-help,[cursor-help=\"\"]{cursor:help}.cursor-pointer,[cursor-pointer=\"\"],.hover\\:cursor-pointer:hover{cursor:pointer}.cursor-col-resize{cursor:col-resize}.select-none,[select-none=\"\"]{-webkit-user-select:none;user-select:none}.resize{resize:both}.place-content-center{place-content:center}.place-items-center{place-items:center}.items-end,[items-end=\"\"]{align-items:flex-end}.items-center,[flex~=items-center],[grid~=items-center],[items-center=\"\"]{align-items:center}.justify-end,[justify-end=\"\"]{justify-content:flex-end}.justify-center,[justify-center=\"\"]{justify-content:center}.justify-between,[flex~=justify-between],[justify-between=\"\"]{justify-content:space-between}.justify-evenly,[justify-evenly=\"\"]{justify-content:space-evenly}.justify-items-center,[justify-items-center=\"\"]{justify-items:center}.gap-0,[gap-0=\"\"]{gap:0}.gap-1,[flex~=gap-1],[gap-1=\"\"]{gap:.25rem}.gap-2,[flex~=gap-2],[gap-2=\"\"]{gap:.5rem}.gap-4,[flex~=gap-4]{gap:1rem}.gap-6{gap:1.5rem}.gap-x-1,[grid~=gap-x-1]{column-gap:.25rem}.gap-x-2,[gap-x-2=\"\"],[gap~=x-2],[grid~=gap-x-2]{column-gap:.5rem}.gap-y-1{row-gap:.25rem}[gap~=y-3]{row-gap:.75rem}.overflow-auto,[overflow-auto=\"\"]{overflow:auto}.overflow-hidden,[overflow-hidden=\"\"],[overflow~=hidden]{overflow:hidden}.truncate,[truncate=\"\"]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre,[whitespace-pre=\"\"]{white-space:pre}.ws-nowrap,[ws-nowrap=\"\"]{white-space:nowrap}.b,.border,[border~=\"~\"]{border-width:1px}.b-2,[b-2=\"\"]{border-width:2px}.before\\:border-\\[2px\\]:before{border-width:2px}.border-b,.border-b-1,[border~=b]{border-bottom-width:1px}.border-b-2,[border-b-2=\"\"],[border~=b-2]{border-bottom-width:2px}.border-l,[border~=l]{border-left-width:1px}.border-l-2px{border-left-width:2px}.border-r,.border-r-1px,[border~=r]{border-right-width:1px}.border-t,[border~=t]{border-top-width:1px}.dark [border~=\"dark:gray-400\"]{--un-border-opacity:1;border-color:rgb(156 163 175 / var(--un-border-opacity))}[border~=\"$cm-namespace\"]{border-color:var(--cm-namespace)}[border~=\"gray-400/50\"]{border-color:#9ca3af80}[border~=gray-500]{--un-border-opacity:1;border-color:rgb(107 114 128 / var(--un-border-opacity))}[border~=red-500]{--un-border-opacity:1;border-color:rgb(239 68 68 / var(--un-border-opacity))}.before\\:border-black:before{--un-border-opacity:1;border-color:rgb(0 0 0 / var(--un-border-opacity))}.border-rounded,.rounded,.rounded-1,[border-rounded=\"\"],[border~=rounded],[rounded-1=\"\"],[rounded=\"\"]{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-xl{border-radius:.75rem}.before\\:rounded-full:before{border-radius:9999px}[border~=dotted]{border-style:dotted}[border~=solid]{border-style:solid}.\\!bg-gray-4{--un-bg-opacity:1 !important;background-color:rgb(156 163 175 / var(--un-bg-opacity))!important}.bg-\\[\\#eee\\]{--un-bg-opacity:1;background-color:rgb(238 238 238 / var(--un-bg-opacity))}.bg-\\[\\#fafafa\\]{--un-bg-opacity:1;background-color:rgb(250 250 250 / var(--un-bg-opacity))}.bg-\\[size\\:16px_16px\\]{background-size:16px 16px}.bg-current,[bg-current=\"\"]{background-color:currentColor}.bg-gray{--un-bg-opacity:1;background-color:rgb(156 163 175 / var(--un-bg-opacity))}.bg-gray-500\\:35{background-color:#6b728059}.bg-green5,[bg-green5=\"\"]{--un-bg-opacity:1;background-color:rgb(34 197 94 / var(--un-bg-opacity))}.bg-indigo\\/60{background-color:#818cf899}.bg-orange{--un-bg-opacity:1;background-color:rgb(251 146 60 / var(--un-bg-opacity))}.bg-red{--un-bg-opacity:1;background-color:rgb(248 113 113 / var(--un-bg-opacity))}.bg-red-500\\/10,[bg~=\"red-500/10\"],[bg~=\"red500/10\"]{background-color:#ef44441a}.bg-red5,[bg-red5=\"\"]{--un-bg-opacity:1;background-color:rgb(239 68 68 / var(--un-bg-opacity))}.bg-white,[bg-white=\"\"]{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity))}.bg-yellow5,[bg-yellow5=\"\"]{--un-bg-opacity:1;background-color:rgb(234 179 8 / var(--un-bg-opacity))}.dark .\\!dark\\:bg-gray-7{--un-bg-opacity:1 !important;background-color:rgb(55 65 81 / var(--un-bg-opacity))!important}.dark .dark\\:bg-\\[\\#222\\]{--un-bg-opacity:1;background-color:rgb(34 34 34 / var(--un-bg-opacity))}.dark .dark\\:bg-\\[\\#3a3a3a\\]{--un-bg-opacity:1;background-color:rgb(58 58 58 / var(--un-bg-opacity))}.dark [bg~=\"dark:#111\"]{--un-bg-opacity:1;background-color:rgb(17 17 17 / var(--un-bg-opacity))}[bg~=gray-200]{--un-bg-opacity:1;background-color:rgb(229 231 235 / var(--un-bg-opacity))}[bg~=\"gray/10\"]{background-color:#9ca3af1a}[bg~=\"gray/30\"]{background-color:#9ca3af4d}[bg~=\"green-500/10\"]{background-color:#22c55e1a}[bg~=transparent]{background-color:transparent}[bg~=\"yellow-500/10\"]{background-color:#eab3081a}.before\\:bg-white:before{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity))}.bg-center{background-position:center}[fill-opacity~=\".05\"]{--un-fill-opacity:.0005}.p-0,[p-0=\"\"]{padding:0}.p-0\\.5,[p-0\\.5=\"\"]{padding:.125rem}.p-1,[p-1=\"\"]{padding:.25rem}.p-2,.p2,[p-2=\"\"],[p~=\"2\"],[p2=\"\"]{padding:.5rem}.p-4,[p-4=\"\"]{padding:1rem}.p-5,[p-5=\"\"]{padding:1.25rem}.p6,[p6=\"\"]{padding:1.5rem}[p~=\"3\"]{padding:.75rem}.p-y-1,.py-1,[p~=y-1],[p~=y1],[py-1=\"\"]{padding-top:.25rem;padding-bottom:.25rem}.px,[p~=x-4],[p~=x4]{padding-left:1rem;padding-right:1rem}.px-0{padding-left:0;padding-right:0}.px-2,[p~=x-2],[p~=x2]{padding-left:.5rem;padding-right:.5rem}.px-3,[p~=x3],[px-3=\"\"]{padding-left:.75rem;padding-right:.75rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py,[p~=y4]{padding-top:1rem;padding-bottom:1rem}.py-0\\.5,[p~=\"y0.5\"]{padding-top:.125rem;padding-bottom:.125rem}.py-2,[p~=y2],[py-2=\"\"]{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pb-2,[pb-2=\"\"]{padding-bottom:.5rem}.pe-2\\.5,[pe-2\\.5=\"\"]{padding-inline-end:.625rem}.pl-1,[pl-1=\"\"]{padding-left:.25rem}.pr-2,[p~=r2],[pr-2=\"\"]{padding-right:.5rem}.pt{padding-top:1rem}.pt-4px{padding-top:4px}[p~=l3]{padding-left:.75rem}.text-center,[text-center=\"\"],[text~=center]{text-align:center}.indent,[indent=\"\"]{text-indent:1.5rem}.text-2xl,[text-2xl=\"\"]{font-size:1.5rem;line-height:2rem}.text-4xl,[text-4xl=\"\"]{font-size:2.25rem;line-height:2.5rem}.text-lg,[text-lg=\"\"]{font-size:1.125rem;line-height:1.75rem}.text-sm,[text-sm=\"\"],[text~=sm]{font-size:.875rem;line-height:1.25rem}.text-xs,[text-xs=\"\"],[text~=xs]{font-size:.75rem;line-height:1rem}[text~=\"5xl\"]{font-size:3rem;line-height:1}.dark .dark\\:text-red-300{--un-text-opacity:1;color:rgb(252 165 165 / var(--un-text-opacity))}.dark .dark\\:text-white,.text-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity))}.text-\\[\\#add467\\]{--un-text-opacity:1;color:rgb(173 212 103 / var(--un-text-opacity))}.text-black{--un-text-opacity:1;color:rgb(0 0 0 / var(--un-text-opacity))}.text-gray-5,.text-gray-500,[text-gray-500=\"\"]{--un-text-opacity:1;color:rgb(107 114 128 / var(--un-text-opacity))}.text-green-500,.text-green5,[text-green-500=\"\"],[text-green5=\"\"],[text~=green-500]{--un-text-opacity:1;color:rgb(34 197 94 / var(--un-text-opacity))}.text-orange{--un-text-opacity:1;color:rgb(251 146 60 / var(--un-text-opacity))}.text-purple5\\:50{color:#a855f780}.dark .dark\\:c-red-400,.text-red{--un-text-opacity:1;color:rgb(248 113 113 / var(--un-text-opacity))}.color-red5,.text-red-500,.text-red5,[text-red-500=\"\"],[text-red5=\"\"],[text~=red-500],[text~=red500]{--un-text-opacity:1;color:rgb(239 68 68 / var(--un-text-opacity))}.c-red-600,.text-red-600{--un-text-opacity:1;color:rgb(220 38 38 / var(--un-text-opacity))}.text-yellow-500,.text-yellow5,[text-yellow-500=\"\"],[text-yellow5=\"\"],[text~=yellow-500]{--un-text-opacity:1;color:rgb(234 179 8 / var(--un-text-opacity))}.text-yellow-500\\/80{color:#eab308cc}[text~=\"red500/70\"]{color:#ef4444b3}.dark .dark\\:color-\\#f43f5e{--un-text-opacity:1;color:rgb(244 63 94 / var(--un-text-opacity))}.font-bold,[font-bold=\"\"]{font-weight:700}.font-light,[font-light=\"\"],[font~=light]{font-weight:300}.font-thin,[font-thin=\"\"]{font-weight:100}.font-mono,[font-mono=\"\"]{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",Segoe UI Symbol,\"Noto Color Emoji\"}.capitalize,[capitalize=\"\"]{text-transform:capitalize}.aria-\\[selected\\=true\\]\\:underline[aria-selected=true],.underline,.hover\\:underline:hover{text-decoration-line:underline}.decoration-gray{-webkit-text-decoration-color:rgb(156 163 175 / var(--un-line-opacity));--un-line-opacity:1;text-decoration-color:rgb(156 163 175 / var(--un-line-opacity))}.decoration-red{-webkit-text-decoration-color:rgb(248 113 113 / var(--un-line-opacity));--un-line-opacity:1;text-decoration-color:rgb(248 113 113 / var(--un-line-opacity))}.underline-offset-4{text-underline-offset:4px}.tab,[tab=\"\"]{-moz-tab-size:4;-o-tab-size:4;tab-size:4}.\\!op-100{opacity:1!important}.dark .dark\\:op85{opacity:.85}.dark [dark~=op75],.op75{opacity:.75}.op-50,.op50,.opacity-50,[op-50=\"\"],[op~=\"50\"],[op50=\"\"]{opacity:.5}.op-70,.op70,[op-70=\"\"],[opacity~=\"70\"]{opacity:.7}.op-90,[op-90=\"\"]{opacity:.9}.op100,[op~=\"100\"],[op100=\"\"]{opacity:1}.op20,[op20=\"\"]{opacity:.2}.op30,[op30=\"\"]{opacity:.3}.op65,[op65=\"\"]{opacity:.65}.op80,[op80=\"\"]{opacity:.8}.opacity-0{opacity:0}.opacity-60,[opacity-60=\"\"]{opacity:.6}[opacity~=\"10\"]{opacity:.1}[hover\\:op100~=\"default:\"]:hover:default{opacity:1}.hover\\:op100:hover,[hover\\:op100~=\"~\"]:hover,[hover~=op100]:hover{opacity:1}[hover~=op80]:hover{opacity:.8}[op~=\"hover:100\"]:hover{opacity:1}[hover\\:op100~=\"disabled:\"]:hover:disabled{opacity:1}.shadow-\\[0_0_3px_rgb\\(0_0_0\\/\\.2\\)\\,0_0_10px_rgb\\(0_0_0\\/\\.5\\)\\]{--un-shadow:0 0 3px rgb(0 0 0/.2),0 0 10px rgb(0 0 0/.5);box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.outline-0{outline-width:0px}.focus-within\\:has-focus-visible\\:outline-2:has(:focus-visible):focus-within{outline-width:2px}.dark .dark\\:outline-white{--un-outline-color-opacity:1;outline-color:rgb(255 255 255 / var(--un-outline-color-opacity))}.outline-black{--un-outline-color-opacity:1;outline-color:rgb(0 0 0 / var(--un-outline-color-opacity))}.outline-offset-4{outline-offset:4px}.outline,.outline-solid{outline-style:solid}[outline~=none]{outline:2px solid transparent;outline-offset:2px}.backdrop-blur-sm,[backdrop-blur-sm=\"\"]{--un-backdrop-blur:blur(4px);-webkit-backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia)}.backdrop-saturate-0,[backdrop-saturate-0=\"\"]{--un-backdrop-saturate:saturate(0);-webkit-backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia)}.filter,[filter=\"\"]{filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-500{transition-duration:.5s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.before\\:content-\\[\\'\\'\\]:before{content:\"\"}@media (min-width: 768px){.md\\:grid-cols-\\[200px_1fr\\]{grid-template-columns:200px 1fr}}\n"
  },
  {
    "path": "test/cli/test/fixtures/reporters/html/fail/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"./favicon.ico\" sizes=\"48x48\">\n    <link rel=\"icon\" href=\"./favicon.svg\" sizes=\"any\" type=\"image/svg+xml\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vitest</title>\n    <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n    <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n    <link\n      href=\"https://fonts.googleapis.com/css2?family=Readex+Pro:wght@300;400&display=swap\"\n      rel=\"stylesheet\"\n    />\n    <script>\n      (function () {\n        const prefersDark =\n          window.matchMedia &&\n          window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n        const setting = localStorage.getItem(\"vueuse-color-scheme\") || \"auto\";\n        if (setting === \"dark\" || (prefersDark && setting !== \"light\"))\n          document.documentElement.classList.toggle(\"dark\", true);\n      })();\n    </script>\n    <script>window.METADATA_PATH=\"html.meta.json.gz\"</script>\n    <script type=\"module\" src=\"./assets/index-BUCFJtth.js\"></script>\n    <link rel=\"stylesheet\" href=\"./assets/index-DlhE0rqZ.css\">\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "test/cli/test/fs-cached-check.test.ts",
    "content": "import { runInlineTests } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest('import a generated file', async () => {\n  const { stderr, stdout, testTree } = await runInlineTests({\n    'basic.test.js': /* js */ `\n      import { expect, test } from \"vitest\"\n      import fs from \"node:fs\"\n      import path from \"node:path\"\n      test(\"import a generated file\", async () => {\n        const dist = path.join(import.meta.dirname, \"dist\");\n        await fs.promises.mkdir(dist, { recursive: true });\n        await fs.promises.writeFile(path.join(dist, \"generated.js\"), \"export default 'ok'\");\n\n        // this file was just generated\n        const mod = await import(\"./dist/generated.js\")\n\n        expect(mod.default).toBe(\"ok\");\n      })\n    `,\n  })\n  expect(stdout).not.toContain('generated.js')\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"import a generated file\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/get-state.test.ts",
    "content": "import type { TestUserConfig } from 'vitest/node'\nimport { runInlineTests } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest.for([\n  { isolate: true },\n  { isolate: false, maxWorkers: 1 },\n  { isolate: false, maxWorkers: 3 },\n  { isolate: false, fileParallelism: false },\n] satisfies TestUserConfig[])(`getState().testPath during collection %s`, async (config) => {\n  const result = await runInlineTests(\n    {\n      'a.test.ts': createTest('a.test.ts'),\n      'b.test.ts': createTest('b.test.ts'),\n      'c.test.ts': createTest('c.test.ts'),\n    },\n    config,\n  )\n  expect(result.stderr).toBe('')\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    {\n      \"a.test.ts\": {\n        \"a.test.ts\": \"passed\",\n      },\n      \"b.test.ts\": {\n        \"b.test.ts\": \"passed\",\n      },\n      \"c.test.ts\": {\n        \"c.test.ts\": \"passed\",\n      },\n    }\n  `)\n})\n\nfunction createTest(fileName: string) {\n  return /* ts */`\n    import { expect, test } from 'vitest'\n\n    const testPath = expect.getState().testPath;\n\n    test(\"${fileName}\", () => {\n      expect(testPath).toContain(\"${fileName}\")\n    })\n`\n}\n"
  },
  {
    "path": "test/cli/test/git-changed.test.ts",
    "content": "import { join } from 'node:path'\nimport { describe, expect, it } from 'vitest'\n\nimport { createFile, editFile, resolvePath, runVitest } from '../../test-utils'\n\nconst fileName = 'fixtures/git-changed/related/rerun.temp'\n\n// NOTE: if there are any changes in fixtures/git-changed,\n// most tests will probably fail\n\n// ecosystem-ci updated package.json and make this test fail\ndescribe.skipIf(process.env.ECOSYSTEM_CI)('forceRerunTrigger', () => {\n  async function run() {\n    return runVitest({\n      root: join(process.cwd(), 'fixtures/git-changed/related'),\n      include: ['related.test.ts'],\n      forceRerunTriggers: ['**/rerun.temp/**'],\n      changed: true,\n    })\n  }\n\n  it('should run the whole test suite if file exists', async () => {\n    createFile(fileName, '')\n    const { stdout, stderr } = await run()\n    expect(stderr).toBe('')\n    expect(stdout).toContain('1 passed')\n    expect(stdout).toContain('related.test.ts')\n    expect(stdout).not.toContain('not-related.test.ts')\n  })\n\n  it('should run no tests if file does not exist', async () => {\n    const { stdout } = await run()\n    expect(stdout).toContain('No test files found, exiting with code 0')\n  })\n})\n\nit.skipIf(process.env.ECOSYSTEM_CI)('related correctly runs only related tests', async () => {\n  const { stdout, stderr } = await runVitest({\n    related: 'src/sourceA.ts',\n    root: './fixtures/git-changed/related',\n    globals: true,\n  })\n\n  expect(stderr).toBe('')\n  expect(stdout).toContain('3 passed')\n  expect(stdout).toContain('related.test.ts')\n  expect(stdout).toContain('deep-related-imports.test.ts')\n  expect(stdout).toContain('deep-related-exports.test.ts')\n  expect(stdout).not.toContain('not-related.test.ts')\n})\n\nit.skipIf(process.env.ECOSYSTEM_CI)('doesn\\'t run any test in a workspace because there are no changes', async () => {\n  const { stdout } = await runVitest({\n    changed: true,\n    root: './fixtures/git-changed/workspace',\n  })\n\n  expect(stdout).toContain('No test files found, exiting with code 0')\n})\n\n// Fixes #4674\nit.skipIf(process.env.ECOSYSTEM_CI)('related correctly runs only related tests inside a workspace', async () => {\n  editFile(\n    resolvePath(import.meta.url, '../fixtures/git-changed/workspace/packages/packageA/index.js'),\n    content => `${content}\\n`,\n  )\n\n  const { stdout, stderr } = await runVitest({\n    changed: true,\n    root: './fixtures/git-changed/workspace',\n  })\n\n  expect(stderr).toBe('')\n  expect(stdout).toContain('1 passed')\n  expect(stdout).toContain('packageA')\n  expect(stdout).not.toContain('packageB')\n})\n"
  },
  {
    "path": "test/cli/test/global-setup.test.ts",
    "content": "import { resolve } from 'pathe'\nimport { expect, it } from 'vitest'\n\nimport { runVitest } from '../../test-utils'\n\nit('should fail', async () => {\n  const root = resolve(import.meta.dirname, '../fixtures/global-setup-fail')\n  const { stderr } = await runVitest({ root })\n\n  expect(stderr).toBeTruthy()\n  const msg = String(stderr)\n    .split(/\\n/g)\n    .reverse()\n    .find(i => i.includes('Error: '))\n    ?.trim()\n  expect(msg).toBe('Error: error')\n  expect(stderr).not.toContain('__vite_ssr_export_default__')\n  expect(stderr).toContain('globalSetup/error.ts:6:9')\n})\n\nit('runs global setup/teardown', async () => {\n  const { stderr, errorTree } = await runVitest({\n    root: './fixtures/global-setup',\n    config: false,\n    globalSetup: [\n      './globalSetup/default-export.js',\n      './globalSetup/named-exports.js',\n      './globalSetup/ts-with-imports.ts',\n      './globalSetup/another-vite-instance.ts',\n      './globalSetup/update-env.ts',\n    ],\n    $viteConfig: {\n      plugins: [\n        {\n          name: 'a-vitest-plugin-that-changes-config',\n          config: () => ({\n            test: {\n              setupFiles: [\n                './setupFiles/add-something-to-global.ts',\n                'setupFiles/without-relative-path-prefix.ts',\n              ],\n            },\n          }),\n        },\n      ],\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"test/global-setup.test.ts\": {\n        \"server running\": \"passed\",\n        \"vite instance running\": \"passed\",\n      },\n      \"test/setup-files.test.ts\": {\n        \"setup file has been loaded without relative path prefix\": \"passed\",\n        \"something has been added to global by setupFiles entry\": \"passed\",\n        \"the process.env is injected correctly\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/group-order.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\ntest('tests run according to the group order', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'example.1.test.ts': `test('1', () => {})`,\n    'example.2.test.ts': `test('2', () => {})`,\n    'example.2-2.test.ts': `test('2-2', () => {})`,\n    'example.3.test.ts': `test('3', () => {})`,\n  }, {\n    $cliOptions: { globals: true },\n    // run projects in the opposite order!\n    projects: [\n      {\n        test: {\n          name: '3',\n          include: ['./example.3.test.ts'],\n          sequence: {\n            groupOrder: 1,\n          },\n        },\n      },\n      {\n        test: {\n          include: ['./example.2.test.ts', './example.2-2.test.ts'],\n          name: '2',\n          sequence: {\n            groupOrder: 2,\n          },\n        },\n      },\n      {\n        test: {\n          name: '1',\n          include: ['./example.1.test.ts'],\n          sequence: {\n            groupOrder: 3,\n          },\n        },\n      },\n    ],\n  })\n  expect(stderr).toBe('')\n\n  const tests = stdout.split('\\n').filter(c => c.startsWith(' ✓')).join('\\n').replace(/\\d+ms/g, '<time>')\n\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ |3| example.3.test.ts > 3 <time>\n     ✓ |2| example.2-2.test.ts > 2-2 <time>\n     ✓ |2| example.2.test.ts > 2 <time>\n     ✓ |1| example.1.test.ts > 1 <time>\"\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/init.test.ts",
    "content": "import { readdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { beforeEach, expect, test } from 'vitest'\nimport { runVitestCli } from '../../test-utils'\n\nconst ARROW_DOWN = '\\u001B[B'\nconst ENTER = '\\n'\n\nconst cwd = 'fixtures/browser-init'\n\nbeforeEach(async () => {\n  await cleanup()\n  return cleanup\n\n  async function cleanup() {\n    for (const file of await getFiles()) {\n      if (file !== 'package.json') {\n        await rm(`${cwd}/${file}`, { recursive: true })\n      }\n    }\n    await writeFile(`${cwd}/vitest.config.ts`, '{}', 'utf8')\n  }\n})\n\ntest('initializes project', async () => {\n  const { vitest } = await runVitestCli({ nodeOptions: { cwd } }, 'init', 'browser')\n\n  await vitest.waitForStdout('This utility will help you set up a browser testing environment.')\n  await vitest.waitForStdout('? Choose a language for your tests')\n  vitest.write(ENTER)\n\n  await vitest.waitForStdout('Choose a browser provider')\n  vitest.write(`${ARROW_DOWN}${ARROW_DOWN}${ENTER}`)\n\n  await vitest.waitForStdout('Choose a browser')\n  vitest.write(ENTER)\n\n  await vitest.waitForStdout('Choose your framework')\n  vitest.write(ENTER)\n\n  await vitest.waitForStdout('✔ All packages are already installed.')\n  await vitest.waitForStdout('✔ Added \"test:browser\" script to your package.json.')\n  await vitest.waitForStdout(`✔ Created example test file in ${join('vitest-example', 'HelloWorld.test.ts')}`)\n  await vitest.waitForStdout('All done! Run your tests with pnpm test:browser')\n\n  expect(await getFiles()).toMatchInlineSnapshot(`\n    [\n      \"package.json\",\n      \"vitest-example\",\n      \"vitest.browser.config.ts\",\n      \"vitest.config.ts\",\n    ]\n  `)\n\n  expect(await getFileContent('/vitest.browser.config.ts')).toMatchInlineSnapshot(`\n    \"import { defineConfig } from 'vitest/config'\n    import { preview } from '@vitest/browser-preview'\n\n    export default defineConfig({\n      test: {\n        browser: {\n          enabled: true,\n          provider: preview(),\n          instances: [\n          ],\n        },\n      },\n    })\n    \"\n  `)\n\n  expect(await getFiles('/vitest-example')).toMatchInlineSnapshot(`\n    [\n      \"HelloWorld.test.ts\",\n      \"HelloWorld.ts\",\n    ]\n  `)\n})\n\nasync function getFiles(subDir = '') {\n  return await readdir(cwd + subDir)\n}\n\nasync function getFileContent(subDir = '') {\n  return await readFile(cwd + subDir, 'utf8')\n}\n"
  },
  {
    "path": "test/cli/test/inspect.test.ts",
    "content": "import type { InspectorNotification } from 'node:inspector'\nimport { version as viteVersion } from 'vite'\nimport { expect, test } from 'vitest'\nimport WebSocket from 'ws'\n\nimport { runVitestCli } from '../../test-utils'\n\ntype Message = Partial<InspectorNotification<any>>\n\ntest('--inspect-brk stops at test file', async () => {\n  const { vitest, waitForClose } = await runVitestCli(\n    '--root',\n    'fixtures/inspect',\n    '--inspect-brk',\n    '9232',\n    '--no-file-parallelism',\n  )\n\n  await vitest.waitForStderr('Debugger listening on ')\n  const url = vitest.stderr.split('\\n')[0].replace('Debugger listening on ', '')\n\n  const { receive, send } = await createChannel(url)\n\n  send({ method: 'Debugger.enable' })\n  send({ method: 'Runtime.enable' })\n  await receive('Runtime.executionContextCreated')\n\n  const paused = receive('Debugger.paused')\n  send({ method: 'Runtime.runIfWaitingForDebugger' })\n\n  const { params } = await paused\n  const scriptId = params.callFrames[0].functionLocation.scriptId\n\n  // Verify that debugger paused on test file\n  const response = receive()\n  send({ method: 'Debugger.getScriptSource', params: { scriptId } })\n  const { result } = await response as any\n\n  if (viteVersion[0] >= '6') {\n    // vite ssr transform wraps import by\n    //   (0, __vite_ssr_import_0__.test)(...)\n    expect(result.scriptSource).toContain('test)(\"sum\", () => {')\n    expect(result.scriptSource).toContain('expect)(1 + 1).toBe(2)')\n  }\n  else {\n    expect(result.scriptSource).toContain('test(\"sum\", () => {')\n    expect(result.scriptSource).toContain('expect(1 + 1).toBe(2)')\n  }\n\n  send({ method: 'Debugger.resume' })\n\n  await vitest.waitForStdout('Test Files  1 passed (1)')\n  await waitForClose()\n}, 5_000)\n\nasync function createChannel(url: string) {\n  const ws = new WebSocket(url, { allowSynchronousEvents: false })\n\n  let id = 1\n  let receiver = defer()\n\n  ws.onerror = receiver.reject\n  ws.onmessage = (message) => {\n    const response = JSON.parse(message.data.toString())\n    receiver.resolve(response)\n  }\n\n  async function receive(filter?: string) {\n    const message = await receiver.promise\n    receiver = defer()\n\n    if (filter && message.method !== filter) {\n      return receive(filter)\n    }\n\n    return message\n  }\n\n  function send(message: Message) {\n    ws.send(JSON.stringify({ ...message, id: id++ }))\n  }\n\n  await new Promise(r => ws.on('open', r))\n\n  return { receive, send }\n}\n\nfunction defer(): {\n  promise: Promise<Message>\n  resolve: (response: Message) => void\n  reject: (error: unknown) => void\n} {\n  const pr = {} as ReturnType<typeof defer>\n\n  pr.promise = new Promise((resolve, reject) => {\n    pr.resolve = resolve\n    pr.reject = reject\n  })\n\n  return pr\n}\n"
  },
  {
    "path": "test/cli/test/list-changed.test.ts",
    "content": "import { editFile, resolvePath, runVitestCli } from '#test-utils'\nimport { test as baseTest, expect } from 'vitest'\n\n// ecosystem-ci updated package.json and make this test fail\nconst test = baseTest.skipIf(!!process.env.ECOSYSTEM_CI)\n\ntest('list command with --changed flag shows only changed tests', async () => {\n  const sourceFile = resolvePath(import.meta.url, '../fixtures/git-changed/related/src/sourceA.ts')\n\n  // First, run list without --changed to see all tests\n  const { stdout: allTests } = await runVitestCli('list', '-r=./fixtures/git-changed/related')\n  expect(allTests).toContain('related.test.ts')\n  expect(allTests).toContain('not-related.test.ts')\n\n  // Now modify the source file to trigger --changed behavior\n  editFile(sourceFile, content => `${content}\\n// modified for test`)\n\n  // Run list with --changed flag\n  const { stdout: changedTests } = await runVitestCli('list', '-r=./fixtures/git-changed/related', '--changed')\n  expect(changedTests).toContain('related.test.ts')\n  expect(changedTests).not.toContain('not-related.test.ts')\n})\n\ntest('list command with --changed flag and --filesOnly shows only changed test files', async () => {\n  const sourceFile = resolvePath(import.meta.url, '../fixtures/git-changed/related/src/sourceA.ts')\n  editFile(sourceFile, content => `${content}\\n// modified for filesOnly test`)\n\n  const { stdout: changedFiles } = await runVitestCli('list', '-r=./fixtures/git-changed/related', '--changed', '--filesOnly')\n  expect(changedFiles).toContain('related.test.ts')\n  expect(changedFiles).not.toContain('not-related.test.ts')\n})\n\ntest('list command with --changed flag and --json outputs changed tests in JSON format', async () => {\n  const sourceFile = resolvePath(import.meta.url, '../fixtures/git-changed/related/src/sourceA.ts')\n  editFile(sourceFile, content => `${content}\\n// modified for json test`)\n\n  const { stdout: changedJson } = await runVitestCli('list', '-r=./fixtures/git-changed/related', '--changed', '--json')\n  const jsonOutput = JSON.parse(changedJson)\n  expect(Array.isArray(jsonOutput)).toBe(true)\n  const relatedTest = jsonOutput.find((test: any) => test.file?.includes('related.test.ts'))\n  expect(relatedTest).toBeDefined()\n})\n\ntest('list command with --changed flag when no changes exist should show no tests', async () => {\n  const { stdout: noChangesOutput } = await runVitestCli('list', '-r=./fixtures/git-changed/related', '--changed')\n  expect(noChangesOutput.trim()).toBe('')\n})\n"
  },
  {
    "path": "test/cli/test/list.test.ts",
    "content": "import { readFileSync, rmSync } from 'node:fs'\nimport { expect, onTestFinished, test } from 'vitest'\nimport { runVitestCli } from '../../test-utils'\n\ntest.each([\n  ['--pool=threads'],\n  ['--pool=forks'],\n  ['--pool=vmForks'],\n  ['--browser.enabled'],\n  ['--typecheck'],\n  ['--typecheck.only'],\n  ['--static-parse'],\n])('correctly outputs all tests with args: \"%s\"', async (...args) => {\n  const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', ...args)\n  expect(stdout).toMatchSnapshot()\n  expect(exitCode).toBe(0)\n})\n\ntest.each([\n  ['basic'],\n  ['json', '--json'],\n  ['json with a file', '--json=./list.json'],\n])('%s output shows error', async (_, ...args) => {\n  const { stderr, stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '-c=fail.config.ts', ...args)\n  expect(stdout).toBe('')\n  expect(stderr).toMatchSnapshot()\n  expect(exitCode).toBe(1)\n})\n\ntest('correctly outputs json', async () => {\n  const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json')\n  expect(relative(stdout)).toMatchInlineSnapshot(`\n    \"[\n      {\n        \"name\": \"basic suite > inner suite > some test\",\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"name\": \"basic suite > inner suite > another test\",\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"name\": \"basic suite > basic test\",\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"name\": \"outside test\",\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"name\": \"1 plus 1\",\n        \"file\": \"<root>/fixtures/list/math.test.ts\"\n      },\n      {\n        \"name\": \"failing test\",\n        \"file\": \"<root>/fixtures/list/math.test.ts\"\n      }\n    ]\n    \"\n  `)\n  expect(exitCode).toBe(0)\n})\n\ntest('correctly outputs files only json', async () => {\n  const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json', '--filesOnly')\n  expect(relative(stdout)).toMatchInlineSnapshot(`\n    \"[\n      {\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"file\": \"<root>/fixtures/list/math.test.ts\"\n      }\n    ]\n    \"\n  `)\n  expect(exitCode).toBe(0)\n})\n\ntest('correctly saves json', async () => {\n  const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json=./list.json')\n  onTestFinished(() => {\n    rmSync('./fixtures/list/list.json')\n  })\n  const json = readFileSync('./fixtures/list/list.json', 'utf-8')\n  expect(stdout).toBe('')\n  expect(relative(json)).toMatchInlineSnapshot(`\n    \"[\n      {\n        \"name\": \"basic suite > inner suite > some test\",\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"name\": \"basic suite > inner suite > another test\",\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"name\": \"basic suite > basic test\",\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"name\": \"outside test\",\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"name\": \"1 plus 1\",\n        \"file\": \"<root>/fixtures/list/math.test.ts\"\n      },\n      {\n        \"name\": \"failing test\",\n        \"file\": \"<root>/fixtures/list/math.test.ts\"\n      }\n    ]\"\n  `)\n  expect(exitCode).toBe(0)\n})\n\ntest('correctly saves files only json', async () => {\n  const { stdout, exitCode } = await runVitestCli('list', '-r=./fixtures/list', '--json=./list.json', '--filesOnly')\n  onTestFinished(() => {\n    rmSync('./fixtures/list/list.json')\n  })\n  const json = readFileSync('./fixtures/list/list.json', 'utf-8')\n  expect(stdout).toBe('')\n  expect(relative(json)).toMatchInlineSnapshot(`\n    \"[\n      {\n        \"file\": \"<root>/fixtures/list/basic.test.ts\"\n      },\n      {\n        \"file\": \"<root>/fixtures/list/math.test.ts\"\n      }\n    ]\"\n  `)\n  expect(exitCode).toBe(0)\n})\n\ntest('correctly filters by file', async () => {\n  const { stdout, exitCode } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list')\n  expect(stdout).toMatchInlineSnapshot(`\n    \"math.test.ts > 1 plus 1\n    math.test.ts > failing test\n    \"\n  `)\n  expect(exitCode).toBe(0)\n})\n\ntest('correctly filters by file when using --filesOnly', async () => {\n  const { stdout, exitCode } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--filesOnly')\n  expect(stdout).toMatchInlineSnapshot(`\n    \"math.test.ts\n    \"\n  `)\n  expect(exitCode).toBe(0)\n})\n\ntest('correctly prints project name in basic report', async () => {\n  const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--config=./custom.config.ts')\n  expect(stdout).toMatchInlineSnapshot(`\n    \"[custom] math.test.ts > 1 plus 1\n    [custom] math.test.ts > failing test\n    \"\n  `)\n})\n\ntest('correctly prints project name in basic report when using --filesOnly', async () => {\n  const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--config=./custom.config.ts', '--filesOnly')\n  expect(stdout).toMatchInlineSnapshot(`\n    \"[custom] math.test.ts\n    \"\n  `)\n})\n\ntest('correctly prints project name and locations in json report', async () => {\n  const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--json', '--config=./custom.config.ts')\n  expect(relative(stdout)).toMatchInlineSnapshot(`\n    \"[\n      {\n        \"name\": \"1 plus 1\",\n        \"file\": \"<root>/fixtures/list/math.test.ts\",\n        \"projectName\": \"custom\",\n        \"location\": {\n          \"line\": 5,\n          \"column\": 1\n        }\n      },\n      {\n        \"name\": \"failing test\",\n        \"file\": \"<root>/fixtures/list/math.test.ts\",\n        \"projectName\": \"custom\",\n        \"location\": {\n          \"line\": 9,\n          \"column\": 1\n        }\n      }\n    ]\n    \"\n  `)\n})\n\ntest('correctly prints project name in json report when using --filesOnly', async () => {\n  const { stdout } = await runVitestCli('list', 'math.test.ts', '-r=./fixtures/list', '--json', '--config=./custom.config.ts', '--filesOnly')\n  expect(relative(stdout)).toMatchInlineSnapshot(`\n    \"[\n      {\n        \"file\": \"<root>/fixtures/list/math.test.ts\",\n        \"projectName\": \"custom\"\n      }\n    ]\n    \"\n  `)\n})\n\ntest('correctly filters by test name', async () => {\n  const { stdout } = await runVitestCli('list', '-t=inner', '-r=./fixtures/list')\n  expect(stdout).toMatchInlineSnapshot(`\n    \"basic.test.ts > basic suite > inner suite > some test\n    basic.test.ts > basic suite > inner suite > another test\n    \"\n  `)\n})\n\ntest('ignores watch flag', async () => {\n  // if it ends, it works - otherwise it will hang\n  const { stdout } = await runVitestCli('list', '-r=./fixtures/list', '--watch')\n  expect(stdout).toMatchInlineSnapshot(`\n    \"basic.test.ts > basic suite > inner suite > some test\n    basic.test.ts > basic suite > inner suite > another test\n    basic.test.ts > basic suite > basic test\n    basic.test.ts > outside test\n    math.test.ts > 1 plus 1\n    math.test.ts > failing test\n    \"\n  `)\n})\n\nfunction relative(stdout: string) {\n  return stdout.replace(new RegExp(slash(process.cwd()), 'gi'), '<root>')\n}\n\nfunction slash(stdout: string) {\n  return stdout.replace(/\\\\/g, '/')\n}\n"
  },
  {
    "path": "test/cli/test/location-filters.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { runVitestCli } from '../../test-utils'\n\nconst fixturePath = './fixtures/location-filters'\n\ndescribe('location filter with list command', () => {\n  test('finds test at correct line number', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:5`,\n    )\n\n    expect(stdout).toMatchInlineSnapshot(`\n      \"basic.test.ts > basic suite > inner suite > some test\n      \"\n    `)\n    expect(stderr).toEqual('')\n  })\n\n  test('finds \"basic suite\" at correct line number', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:3`,\n    )\n\n    expect(stdout).toMatchInlineSnapshot(`\n      \"basic.test.ts > basic suite > inner suite > some test\n      basic.test.ts > basic suite > inner suite > another test\n      basic.test.ts > basic suite > basic test\n      \"\n    `)\n    expect(stderr).toEqual('')\n  })\n\n  test('finds \"inner suite\" at correct line number', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:4`,\n    )\n\n    expect(stdout).toMatchInlineSnapshot(`\n      \"basic.test.ts > basic suite > inner suite > some test\n      basic.test.ts > basic suite > inner suite > another test\n      \"\n    `)\n    expect(stderr).toEqual('')\n  })\n\n  test('handles matching test inside a suite', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:3`,\n      `${fixturePath}/basic.test.ts:9`,\n    )\n\n    expect(stdout).toMatchInlineSnapshot(`\n      \"basic.test.ts > basic suite > inner suite > some test\n      basic.test.ts > basic suite > inner suite > another test\n      basic.test.ts > basic suite > basic test\n      \"\n    `)\n    expect(stderr).toEqual('')\n  })\n\n  test('handles file with a dash in the name', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `${fixturePath}/math-with-dashes-in-name.test.ts:3`,\n    )\n\n    expect(stdout).toMatchInlineSnapshot(`\n      \"math-with-dashes-in-name.test.ts > 1 plus 1\n      \"\n    `)\n    expect(stderr).toEqual('')\n  })\n\n  test('reports not found test', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:99`,\n    )\n\n    expect(stdout).toEqual('')\n    expect(stderr).toMatchInlineSnapshot(`\n      \"Error: No test found in basic.test.ts in line 99\n      \"\n    `)\n  })\n\n  test('reports multiple not found tests', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:5`,\n      `${fixturePath}/basic.test.ts:12`,\n      `${fixturePath}/basic.test.ts:99`,\n    )\n\n    expect(stdout).toEqual('')\n    expect(stderr).toMatchInlineSnapshot(`\n      \"Error: No test found in basic.test.ts in lines 12, 99\n      \"\n    `)\n  })\n\n  test('errors if range location is provided', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `${fixturePath}/a/file/that/doesnt/exit:10-15`,\n    )\n\n    expect(stdout).toEqual('')\n    expect(stderr).toContain('Collect Error')\n    expect(stderr).toContain('RangeLocationFilterProvidedError')\n  })\n\n  test('parses file with a colon and dash in the name correctly', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `${fixturePath}/:a/file/that/doesn-t/exit:10`,\n    )\n\n    expect(stdout).toEqual('')\n    // shouldn't get a range location error\n    expect(stderr).not.toContain('Error: Found \"-\"')\n  })\n\n  test('fails on part of filename with location filter', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'list',\n      `-r=${fixturePath}`,\n      `math:999`,\n    )\n\n    expect(stdout).toEqual('')\n    expect(stderr).toContain('Collect Error')\n    expect(stderr).toContain('LocationFilterFileNotFoundError')\n  })\n})\n\ndescribe('location filter with run command', () => {\n  test('finds test at correct line number', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `${fixturePath}/math.test.ts:3`,\n    )\n\n    expect(stdout).contain('1 passed')\n    expect(stdout).contain('1 skipped')\n    expect(stderr).toEqual('')\n  })\n\n  test('finds \"basic suite\" at correct line number', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:3`,\n    )\n\n    expect(stdout).contain('3 passed')\n    expect(stdout).contain('1 skipped')\n    expect(stderr).toEqual('')\n  })\n\n  test('finds \"inner suite\" at correct line number', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:4`,\n    )\n\n    expect(stdout).contain('2 passed')\n    expect(stdout).contain('2 skipped')\n    expect(stderr).toEqual('')\n  })\n\n  test('handles matching test inside a suite', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:3`,\n      `${fixturePath}/basic.test.ts:9`,\n    )\n\n    expect(stdout).contain('3 passed')\n    expect(stdout).contain('1 skipped')\n    expect(stderr).toEqual('')\n  })\n\n  test('handles file with a dash in the name', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `${fixturePath}/math-with-dashes-in-name.test.ts:3`,\n    )\n\n    expect(stdout).contain('1 passed')\n    expect(stdout).contain('1 skipped')\n    expect(stderr).toEqual('')\n  })\n\n  test('reports not found test', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:99`,\n    )\n\n    expect(stdout).toContain('4 skipped')\n    expect(stderr).toContain('Error: No test found in basic.test.ts in line 99')\n  })\n\n  test('reports multiple not found tests', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `${fixturePath}/basic.test.ts:5`,\n      `${fixturePath}/basic.test.ts:12`,\n      `${fixturePath}/basic.test.ts:99`,\n    )\n\n    expect(stdout).toContain('4 skipped')\n    expect(stderr).toContain('Error: No test found in basic.test.ts in lines 12, 99')\n  })\n\n  test('errors if range location is provided', async () => {\n    const { stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `${fixturePath}/a/file/that/doesnt/exit:10-15`,\n    )\n\n    expect(stderr).toContain('Error: Found \"-\"')\n  })\n\n  test('parses file with a colon and dash in the name correctly', async () => {\n    const { stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `${fixturePath}/:a/file/that/doesn-t/exit:10`,\n    )\n\n    // shouldn't get a range location error\n    expect(stderr).not.toContain('Error: Found \"-\"')\n  })\n\n  test('fails on part of filename with location filter', async () => {\n    const { stdout, stderr } = await runVitestCli(\n      'run',\n      `-r=${fixturePath}`,\n      `math:999`,\n    )\n\n    expect(stdout).not.contain('math.test.ts')\n    expect(stdout).not.contain('math-with-dashes-in-name.test.ts')\n    expect(stderr).toMatchInlineSnapshot(`\n      \"Error: Couldn't find file math. Note when specifying the test location you have to specify the full test filename.\n      \"\n    `)\n  })\n})\n"
  },
  {
    "path": "test/cli/test/mocking.test.ts",
    "content": "import type { RunVitestConfig } from '../../test-utils'\nimport { setDefaultResultOrder } from 'node:dns'\nimport path from 'node:path'\nimport { playwright } from '@vitest/browser-playwright'\nimport { webdriverio } from '@vitest/browser-webdriverio'\nimport { afterAll, expect, test } from 'vitest'\nimport { rolldownVersion } from 'vitest/node'\nimport { runInlineTests, runVitest } from '../../test-utils'\n\n// webdriver@9 sets dns.setDefaultResultOrder(\"ipv4first\") on import,\n// which makes Vite resolve localhost to 127.0.0.1 and breaks other tests asserting \"localhost\"\nafterAll(() => setDefaultResultOrder('verbatim'))\n\ntest('setting resetMocks works if restoreMocks is also set', async () => {\n  const { stderr, testTree } = await runInlineTests({\n    'vitest.config.js': {\n      test: {\n        restoreMocks: true,\n        mockReset: true,\n      },\n    },\n    './mocked.js': `\nexport function spy() {}\n    `,\n    './basic.test.js': `\nimport { vi, test, expect } from 'vitest'\nimport { spy } from './mocked.js'\n\nvi.mock('./mocked.js', { spy: true })\n\ntest('spy is called here', () => {\n  spy()\n  expect(spy).toHaveBeenCalled()\n})\n\ntest('spy is not called here', () => {\n  expect(spy).not.toHaveBeenCalled()\n})\n    `,\n  })\n\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"spy is called here\": \"passed\",\n        \"spy is not called here\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('invalid packages', async () => {\n  const { stderr, errorTree } = await runVitest({\n    root: path.join(import.meta.dirname, '../fixtures/invalid-package'),\n  })\n\n  // requires Vite 8 for relaxed import analysis validataion\n  // https://github.com/vitejs/vite/pull/21601\n  if (rolldownVersion) {\n    expect(stderr).toMatchInlineSnapshot(`\"\"`)\n    expect(errorTree()).toMatchInlineSnapshot(`\n      {\n        \"mock-bad-dep.test.ts\": {\n          \"basic\": \"passed\",\n        },\n        \"mock-wrapper-and-bad-dep.test.ts\": {\n          \"basic\": \"passed\",\n        },\n        \"mock-wrapper.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n  }\n  else {\n    expect(errorTree()).toMatchInlineSnapshot(`\n      {\n        \"mock-bad-dep.test.ts\": {\n          \"__module_errors__\": [\n            \"Failed to resolve entry for package \"test-dep-invalid\". The package may have incorrect main/module/exports specified in its package.json.\",\n          ],\n        },\n        \"mock-wrapper-and-bad-dep.test.ts\": {\n          \"__module_errors__\": [\n            \"Failed to resolve entry for package \"test-dep-invalid\". The package may have incorrect main/module/exports specified in its package.json.\",\n          ],\n        },\n        \"mock-wrapper.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n  }\n})\n\ntest('mocking modules with syntax error', async () => {\n  const { errorTree } = await runInlineTests({\n    './syntax-error.js': `syntax error`,\n    './basic.test.js': /* ts */ `\nimport { test, expect, vi } from 'vitest'\nimport * as dep from './syntax-error.js'\n\nvi.mock('./syntax-error.js', () => {\n  return { mocked: 'ok' }\n})\n\ntest('can mock invalid module', () => {\n  expect(dep).toMatchObject({ mocked: 'ok' })\n})\n    `,\n  })\n\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"can mock invalid module\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('redirect mock with syntax error in original does not load original', async () => {\n  const { errorTree, stderr } = await runInlineTests({\n    './broken.js': `syntax error`,\n    './__mocks__/broken.js': `export const value = 'mocked'`,\n    './basic.test.js': `\nimport { test, expect, vi } from 'vitest'\nimport { value } from './broken.js'\n\nvi.mock('./broken.js')\n\ntest('redirect mock works without loading broken original', () => {\n  expect(value).toBe('mocked')\n})\n    `,\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"redirect mock works without loading broken original\": \"passed\",\n      },\n    }\n  `)\n})\n\nfunction replaceRoot(tree: any, root: string): any {\n  for (const child of Object.values(tree) as any[]) {\n    if (child?.__module_errors__) {\n      child.__module_errors__ = child.__module_errors__.map((e: string) => e.replace(root, '<root>'))\n    }\n  }\n  return tree\n}\n\nfunction modeToConfig(mode: string): RunVitestConfig {\n  if (mode === 'playwright') {\n    return {\n      browser: {\n        enabled: true,\n        provider: playwright(),\n        instances: [{ browser: 'chromium' }],\n        headless: true,\n      },\n    }\n  }\n  if (mode === 'webdriverio') {\n    return {\n      browser: {\n        enabled: true,\n        provider: webdriverio(),\n        instances: [{ browser: 'chrome' }],\n        headless: true,\n      },\n    }\n  }\n  return {}\n}\n\ntest.for(['node', 'playwright', 'webdriverio'])('importOriginal for virtual modules (%s)', async (mode) => {\n  const { stderr, errorTree, root } = await runInlineTests({\n    'vitest.config.js': `\nimport { defineConfig } from 'vitest/config'\nexport default defineConfig({\n  plugins: [{\n    name: 'virtual-test',\n    resolveId(source) {\n      if (source === 'virtual:my-module') {\n        return \"\\\\0\" + source\n      }\n    },\n    load(id) {\n      if (id === '\\\\0virtual:my-module') {\n        return 'export const value = \"original\"'\n      }\n    },\n  }],\n})\n    `,\n    './basic.test.js': `\nimport { test, expect, vi } from 'vitest'\nimport { value } from 'virtual:my-module'\n\nvi.mock('virtual:my-module', async (importOriginal) => {\n  const original = await importOriginal()\n  return { value: original.value + '-modified' }\n})\n\ntest('importOriginal returns original virtual module exports', () => {\n  expect(value).toBe('original-modified')\n})\n    `,\n  }, modeToConfig(mode))\n\n  // webdriverio uses a server-side interceptor plugin whose load hook\n  // intercepts the clean id, so importActual returns the mock instead\n  // of the original module. This is a known limitation.\n  if (mode === 'webdriverio') {\n    expect(replaceRoot(errorTree(), root)).toMatchInlineSnapshot(`\n      {\n        \"__unhandled_errors__\": [\n          \"[vitest] There was an error when mocking a module. If you are using \"vi.mock\" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock\",\n        ],\n        \"basic.test.js\": {\n          \"__module_errors__\": [\n            \"Failed to import test file <root>/basic.test.js\",\n          ],\n        },\n      }\n    `)\n  }\n  else {\n    expect(stderr).toBe('')\n    expect(errorTree()).toMatchInlineSnapshot(`\n      {\n        \"basic.test.js\": {\n          \"importOriginal returns original virtual module exports\": \"passed\",\n        },\n      }\n    `)\n  }\n})\n\ntest.for(['node', 'playwright', 'webdriverio'])('mocking virtual module without importOriginal skips loading original (%s)', async (mode) => {\n  const { stderr, testTree } = await runInlineTests({\n    'vitest.config.js': `\nimport { defineConfig } from 'vitest/config'\nexport default defineConfig({\n  plugins: [{\n    name: 'virtual-test',\n    resolveId(source) {\n      if (source === 'virtual:my-module') {\n        return \"\\\\0\" + source\n      }\n    },\n    load(id) {\n      if (id === '\\\\0virtual:my-module') {\n        throw new Error('virtual module load should not be called')\n      }\n    },\n  }],\n})\n    `,\n    './basic.test.js': `\nimport { test, expect, vi } from 'vitest'\nimport { value } from 'virtual:my-module'\n\nvi.mock('virtual:my-module', () => {\n  return { value: 'mocked' }\n})\n\ntest('mock works without loading original', () => {\n  expect(value).toBe('mocked')\n})\n    `,\n  }, modeToConfig(mode))\n\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"mock works without loading original\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest.for(['node', 'playwright', 'webdriverio'])('mocking actual module with factory skips loading original (%s)', async (mode) => {\n  const { stderr, errorTree, root } = await runInlineTests({\n    'vitest.config.js': `\nimport { defineConfig } from 'vitest/config'\nexport default defineConfig({\n  plugins: [{\n    name: 'guard-load',\n    transform(code, id) {\n      if (id.includes('do-not-load')) {\n        throw new Error('original module should not be transformed')\n      }\n    },\n  }],\n})\n    `,\n    './do-not-load.js': `export const value = 'original'`,\n    './basic.test.js': `\nimport { test, expect, vi } from 'vitest'\nimport * as dep from './do-not-load.js'\n\nvi.mock('./do-not-load.js', () => {\n  return { value: 'mocked' }\n})\n\ntest('mock works without loading original', () => {\n  expect(dep).toMatchObject({ value: 'mocked' })\n})\n    `,\n  }, modeToConfig(mode))\n\n  if (mode === 'webdriverio') {\n    expect(replaceRoot(errorTree(), root)).toMatchInlineSnapshot(`\n      {\n        \"basic.test.js\": {\n          \"__module_errors__\": [\n            \"Failed to import test file <root>/basic.test.js\",\n          ],\n        },\n      }\n    `)\n    return\n  }\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"mock works without loading original\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest.for(['node', 'playwright', 'webdriverio'])('mocking actual module via __mocks__ skips loading original (%s)', async (mode) => {\n  const { stderr, errorTree, root } = await runInlineTests({\n    'vitest.config.js': `\nimport { defineConfig } from 'vitest/config'\nexport default defineConfig({\n  plugins: [{\n    name: 'guard-load',\n    transform(code, id) {\n      if (id.includes('do-not-load') && !id.includes('__mocks__')) {\n        throw new Error('original module should not be transformed')\n      }\n    },\n  }],\n})\n    `,\n    './do-not-load.js': `export const value = 'original'`,\n    './__mocks__/do-not-load.js': `export const value = 'mocked'`,\n    './basic.test.js': `\nimport { test, expect, vi } from 'vitest'\nimport { value } from './do-not-load.js'\n\nvi.mock('./do-not-load.js')\n\ntest('mock works without loading original', () => {\n  expect(value).toBe('mocked')\n})\n    `,\n  }, modeToConfig(mode))\n\n  if (mode === 'webdriverio') {\n    expect(replaceRoot(errorTree(), root)).toMatchInlineSnapshot(`\n      {\n        \"basic.test.js\": {\n          \"__module_errors__\": [\n            \"Failed to import test file <root>/basic.test.js\",\n          ],\n        },\n      }\n    `)\n    return\n  }\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"mock works without loading original\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest.for([\n  'node',\n  'playwright',\n  'webdriverio',\n])('repeating mock, importActual, and resetModules (%s)', async (mode) => {\n  const { stderr, errorTree } = await runInlineTests({\n    // external\n    './external.test.ts': `\nimport { expect, test, vi } from \"vitest\"\n\ntest(\"external\", async () => {\n  vi.doMock(import(\"test-dep-simple\"), async (importActual) => {\n    const lib = await importActual();\n    return lib;\n  })\n  const lib1: any = await import(\"test-dep-simple\")\n  expect(lib1.default).toBe(\"test-dep-simple\")\n\n  vi.resetModules();\n  vi.doMock(import(\"test-dep-simple\"), async (importActual) => {\n    const lib = await importActual();\n    return lib;\n  })\n  const lib2: any = await import(\"test-dep-simple\")\n  expect(lib2.default).toBe(\"test-dep-simple\")\n  expect.soft(lib1 !== lib2).toBe(true)\n\n  vi.resetModules();\n  vi.doMock(import(\"test-dep-simple\"), async () => ({ mocked: true }));\n  const lib3 = await import(\"test-dep-simple\");\n  expect(lib3).toMatchObject({ mocked: true })\n\n  const lib4 = await vi.importActual(\"test-dep-simple\");\n  expect(lib4.default).toBe(\"test-dep-simple\")\n  const lib5 = await vi.importActual(\"test-dep-simple\");\n  expect(lib4).toBe(lib5)\n});\n    `,\n    // builtin module\n    './builtin.test.ts': `\nimport { expect, test, vi } from \"vitest\"\n\ntest(\"builtin\", async () => {\n  vi.doMock(import(\"node:path\"), async (importActual) => {\n    const lib = await importActual();\n    return lib;\n  })\n  const lib1: any = await import(\"node:path\")\n  expect(lib1).toHaveProperty('join')\n\n  vi.resetModules();\n  vi.doMock(import(\"node:path\"), async (importActual) => {\n    const lib = await importActual();\n    return lib;\n  })\n  const lib2: any = await import(\"node:path\")\n  expect(lib2).toHaveProperty('join')\n  expect.soft(lib1 !== lib2).toBe(true)\n\n  vi.resetModules();\n  vi.doMock(import(\"node:path\"), async () => ({ mocked: true }));\n  const lib3 = await import(\"node:path\");\n  expect(lib3).toMatchObject({ mocked: true })\n\n  const lib4 = await vi.importActual(\"node:path\");\n  expect(lib4).toHaveProperty('join')\n  const lib5 = await vi.importActual(\"node:path\");\n  expect(lib4).toBe(lib5)\n});\n    `,\n    // local module\n    './local.test.ts': `\nimport { expect, test, vi } from \"vitest\"\n\ntest(\"local\", async () => {\n  vi.doMock(import(\"./local.js\"), async (importActual) => {\n    const lib = await importActual();\n    return lib;\n  })\n  const lib1: any = await import(\"./local.js\")\n  expect(lib1).toHaveProperty('local')\n\n  vi.resetModules();\n  vi.doMock(import(\"./local.js\"), async (importActual) => {\n    const lib = await importActual();\n    return lib;\n  })\n  const lib2: any = await import(\"./local.js\")\n  expect(lib2).toHaveProperty('local')\n  expect.soft(lib1 !== lib2).toBe(true)\n\n  vi.resetModules();\n  vi.doMock(import(\"./local.js\"), async () => ({ mocked: true }));\n  const lib3 = await import(\"./local.js\");\n  expect(lib3).toMatchObject({ mocked: true })\n\n  const lib4 = await vi.importActual(\"./local.js\");\n  expect(lib4).toHaveProperty('local')\n  const lib5 = await vi.importActual(\"./local.js\");\n  expect(lib4).toBe(lib5)\n});\n    `,\n    './local.js': `export const local = 'local'`,\n  }, modeToConfig(mode))\n\n  if (mode === 'webdriverio' || mode === 'playwright') {\n    // browser mode doesn't support resetModules nor node builtin\n    expect(errorTree()).toMatchInlineSnapshot(`\n      {\n        \"builtin.test.ts\": {\n          \"builtin\": [\n            \"Cannot convert a Symbol value to a string\",\n          ],\n        },\n        \"external.test.ts\": {\n          \"external\": [\n            \"expected false to be true // Object.is equality\",\n            \"expected { default: 'test-dep-simple', …(1) } to match object { mocked: true }\n      (1 matching property omitted from actual)\",\n          ],\n        },\n        \"local.test.ts\": {\n          \"local\": [\n            \"expected false to be true // Object.is equality\",\n            \"expected { local: 'local', …(1) } to match object { mocked: true }\n      (1 matching property omitted from actual)\",\n          ],\n        },\n      }\n    `)\n    return\n  }\n\n  expect(stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"builtin.test.ts\": {\n        \"builtin\": \"passed\",\n      },\n      \"external.test.ts\": {\n        \"external\": \"passed\",\n      },\n      \"local.test.ts\": {\n        \"local\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/network-imports.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nconst config = {\n  execArgv: ['--experimental-network-imports'],\n  // let vite serve public/slash@3.0.0.js\n  api: 9602,\n}\n\nconst [major] = process.version.slice(1).split('.')\n\n// TODO: remove when we drop support for Node 20\n// --experimental-network-imports was removed in Node 22 in favor of module loaders\nit.runIf(Number(major) <= 20).each([\n  'threads',\n  'forks',\n  'vmThreads',\n])('importing from network in %s', async (pool) => {\n  const { ctx, stderr, exitCode } = await runVitest({\n    ...config,\n    root: './fixtures/network-imports',\n    pool,\n  }, [], { printExitCode: true })\n  expect([...ctx!.state.errorsSet]).toStrictEqual([])\n  expect(stderr.replace(/\\(node:\\d+\\)/, '(node:\\d+)')).toBe(`(node:d+) ExperimentalWarning: Network Imports is an experimental feature and might change at any time\n(Use \\`node --trace-warnings ...\\` to show where the warning was created)\n`)\n  expect(ctx!.state.getTestModules()).toHaveLength(1)\n  expect(ctx!.state.getTestModules()[0].state()).toBe('passed')\n  expect(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/cli/test/no-module-runner.test.ts",
    "content": "import type { RunVitestConfig, TestFsStructure, VitestRunnerCLIOptions } from '#test-utils'\nimport { rmSync } from 'node:fs'\nimport module from 'node:module'\nimport { replaceRoot, runInlineTests, runVitest } from '#test-utils'\nimport { describe, expect, onTestFinished, test } from 'vitest'\nimport { readCoverageJson } from '../../coverage-test/utils'\n\ndescribe.runIf(module.registerHooks)('supported', () => {\n  test.for([\n    {\n      isolate: false,\n      maxWorkers: 1,\n    },\n    {\n      isolate: false,\n      maxWorkers: 4,\n      fileParallelism: true, // default\n    },\n    {\n      isolate: true,\n      maxWorkers: 1,\n    },\n  ] satisfies RunVitestConfig[])('runs tests inside correctly with %o', async (options) => {\n    const { stderr, testTree } = await runVitest({\n      root: './fixtures/no-module-runner',\n      ...options,\n    })\n    expect(stderr).toBe('')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"src/in-source/add.ts\": {\n          \"add\": \"passed\",\n        },\n        \"src/in-source/fibonacci.ts\": {\n          \"fibonacci\": \"passed\",\n        },\n        \"test/automock.test.ts\": {\n          \"fs is mocked\": \"passed\",\n          \"squared is mocked\": \"passed\",\n        },\n        \"test/autospy.test.ts\": {\n          \"fs is mocked\": \"passed\",\n          \"squared is mocked\": \"passed\",\n        },\n        \"test/basic.test.ts\": {\n          \"JSON\": \"passed\",\n          \"Math.sqrt()\": \"passed\",\n          \"Squared\": \"passed\",\n          \"add\": \"passed\",\n        },\n        \"test/manual-mock.test.ts\": {\n          \"builtin node modules are mocked\": \"passed\",\n          \"deps in node_modules are mocked\": \"passed\",\n          \"exports are mocked\": \"passed\",\n          \"importMock works\": \"passed\",\n        },\n        \"test/mock-async-factory.test.ts\": {\n          \"imported value is defined\": \"passed\",\n        },\n        \"test/redirect-mock.test.ts\": {\n          \"squared is mocked\": \"passed\",\n        },\n        \"test/suite.test.ts\": {\n          \"suite name\": {\n            \"foo\": \"passed\",\n            \"inline snapshot\": \"passed\",\n            \"setups work\": \"passed\",\n            \"snapshot\": \"passed\",\n          },\n        },\n      }\n    `)\n  })\n\n  // TODO: move to coverage-test project\n  test.skip('v8 coverage works', async () => {\n    const { stderr } = await runVitest({\n      root: './fixtures/no-module-runner',\n      isolate: false,\n      maxWorkers: 1,\n      coverage: {\n        enabled: true,\n        reporter: [['json', { file: './coverage-final.json' }]],\n      },\n    })\n    onTestFinished(() => {\n      rmSync('./fixtures/no-module-runner/coverage', { recursive: true, force: true })\n    })\n    expect(stderr).toBe('')\n    expect(await readCoverageJson('./fixtures/no-module-runner/coverage/coverage-final.json')).toMatchSnapshot()\n  })\n\n  test('istanbul coverage throws an error', async () => {\n    const { stderr } = await runNoViteModuleRunnerTests(\n      { 'base.test.js': `` },\n      { coverage: { provider: 'istanbul', enabled: true } },\n      { fails: true },\n    )\n    expect(stderr).toContain('\"Istanbul\" coverage provider is not compatible with \"experimental.viteModuleRunner: false\". Please, enable \"viteModuleRunner\" or switch to \"v8\" coverage provider.')\n  })\n\n  test('editing test file in watch mode triggers rerun', async () => {\n    const { fs, vitest } = await runNoViteModuleRunnerTests({\n      'base.test.js': `\n        test('hello world', () => {})\n      `,\n    }, { watch: true })\n\n    await vitest.waitForStdout('1 passed')\n\n    fs.editFile('base.test.js', code => code.replace('hello world', 'hello vitest'))\n\n    await vitest.waitForStdout('RERUN  ../base.test.js')\n    await vitest.waitForStdout('hello vitest')\n    await vitest.waitForStdout('1 passed')\n  })\n\n  test('editing imported file in watch mode triggers rerun', async () => {\n    const { fs, vitest } = await runNoViteModuleRunnerTests({\n      'imported.js': `\n        export function greet() { return 'hello world' }\n      `,\n      'base.test.js': `\n        import { greet } from './imported.js'\n        test(greet(), () => {})\n      `,\n    }, { watch: true })\n\n    await vitest.waitForStdout('1 passed')\n\n    fs.editFile('imported.js', code => code.replace('hello world', 'hello vitest'))\n\n    await vitest.waitForStdout('RERUN  ../imported.js')\n    await vitest.waitForStdout('hello vitest')\n    await vitest.waitForStdout('1 passed')\n  })\n\n  test('editing mocked imported file in watch mode triggers rerun', async () => {\n    const { fs, vitest } = await runNoViteModuleRunnerTests({\n      'imported.js': `\n        export function greet() { return 'hello world' }\n      `,\n      'base.test.js': `\n        import { greet } from './imported.js'\n        vi.mock('./imported.js', { spy: true })\n        test(greet(), () => {\n          expect(greet).toHaveBeenCalledOnce()\n        })\n      `,\n    }, { watch: true })\n\n    await vitest.waitForStdout('1 passed')\n\n    fs.editFile('imported.js', code => code.replace('hello world', 'hello vitest'))\n\n    await vitest.waitForStdout('RERUN  ../imported.js')\n    await vitest.waitForStdout('hello vitest')\n    await vitest.waitForStdout('1 passed')\n  })\n\n  test('updating inline snapshots works', async () => {\n    const { fs, stdout } = await runNoViteModuleRunnerTests({\n      'base.test.ts': `\n        interface HelloWorld {\n          hello: string\n        }\n\n        test('inline snapshot', (context: any) => {\n          expect({ hello: 'world' }).toMatchInlineSnapshot()\n        })\n\n        test('second snapshot', () => {\n          expect({\n            hello: 'vitest',\n          }).toMatchInlineSnapshot()\n        })\n      `,\n    }, { update: true })\n    const updatedContent = fs.readFile('base.test.ts')\n    expect(stdout).toContain('Snapshots  2 written')\n    expect(updatedContent).toMatchInlineSnapshot(`\n      \"\n              interface HelloWorld {\n                hello: string\n              }\n\n              test('inline snapshot', (context: any) => {\n                expect({ hello: 'world' }).toMatchInlineSnapshot(\\`\n                  {\n                    \"hello\": \"world\",\n                  }\n                \\`)\n              })\n\n              test('second snapshot', () => {\n                expect({\n                  hello: 'vitest',\n                }).toMatchInlineSnapshot(\\`\n                  {\n                    \"hello\": \"vitest\",\n                  }\n                \\`)\n              })\n            \"\n    `)\n  })\n\n  test('cannot run viteModuleRunner: false in \"vmForks\"', async () => {\n    const { stderr } = await runNoViteModuleRunnerTests(\n      { 'base.test.js': `` },\n      { pool: 'vmForks' },\n    )\n\n    expect(stderr).toContain(`Pool \"vmForks\" cannot run with \"experimental.viteModuleRunner: false\". Please, use \"threads\" or \"forks\" instead.`)\n  })\n\n  test('cannot run viteModuleRunner: false in \"vmThreads\"', async () => {\n    const { stderr } = await runNoViteModuleRunnerTests(\n      { 'base.test.js': `` },\n      { pool: 'vmThreads' },\n    )\n\n    expect(stderr).toContain(`Pool \"vmThreads\" cannot run with \"experimental.viteModuleRunner: false\". Please, use \"threads\" or \"forks\" instead.`)\n  })\n\n  test('can run tests in threads worker', async () => {\n    const { stderr, testTree } = await runNoViteModuleRunnerTests(\n      {\n        'base1.test.js': `test('hello world', () => {})`,\n        'base2.test.js': `test('hello world', () => {})`,\n      },\n      { pool: 'threads' },\n    )\n\n    expect(stderr).toBe('')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"base1.test.js\": {\n          \"hello world\": \"passed\",\n        },\n        \"base2.test.js\": {\n          \"hello world\": \"passed\",\n        },\n      }\n    `)\n  })\n\n  test('can run tests in forks worker', async () => {\n    const { stderr, testTree } = await runNoViteModuleRunnerTests(\n      {\n        'base1.test.js': `test('hello world', () => {})`,\n        'base2.test.js': `test('hello world', () => {})`,\n      },\n      { pool: 'forks' },\n    )\n\n    expect(stderr).toBe('')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"base1.test.js\": {\n          \"hello world\": \"passed\",\n        },\n        \"base2.test.js\": {\n          \"hello world\": \"passed\",\n        },\n      }\n    `)\n  })\n\n  test('ESM files don\\'t have access to CJS globals', async () => {\n    const { stderr, testTree } = await runNoViteModuleRunnerTests({\n      'base.test.js': `\ntest('no globals', () => {\n  expect(typeof __dirname).toBe('undefined')\n  expect(typeof __filename).toBe('undefined')\n  expect(typeof exports).toBe('undefined')\n  expect(typeof module).toBe('undefined')\n})\n\ntest('no vite globals', () => {\n  expect(typeof import.meta).toBe('object')\n  expect(typeof import.meta.env).toBe('undefined')\n})\n    `,\n      'package.json': JSON.stringify({\n        name: '@test/no-globals-cjs-esm-native-module-runner',\n        type: 'module',\n      }),\n    })\n\n    expect(stderr).toBe('')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"base.test.js\": {\n          \"no globals\": \"passed\",\n          \"no vite globals\": \"passed\",\n        },\n      }\n    `)\n  })\n\n  test('CJS files don\\'t have access to ESM globals', async () => {\n    const { stderr, testTree } = await runNoViteModuleRunnerTests({\n      'base.test.js': `\ntest('has CJS globals', () => {\n  expect(typeof __dirname).toBe('string')\n  expect(typeof __filename).toBe('string')\n  expect(typeof exports).toBe('object')\n  expect(typeof module).toBe('object')\n})\n    `,\n      'esm.test.js': `\ntest('no esm globals', () => {\n  expect(typeof import.meta).toBe('undefined')\n})\n    `,\n      'package.json': JSON.stringify({\n        name: '@test/no-globals-esm-cjs-native-module-runner',\n        type: 'commonjs',\n      }),\n    })\n\n    expect(stderr).toContain('Cannot use \\'import.meta\\' outside a module')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"base.test.js\": {\n          \"has CJS globals\": \"passed\",\n        },\n        \"esm.test.js\": {},\n      }\n    `)\n  })\n\n  test('in-source tests in CJS work', async () => {\n    const { stderr, testTree } = await runNoViteModuleRunnerTests(\n      {\n        'in-source.js': /* js */`\nif (import.meta.vitest) {\n  const { test, expect } = import.meta.vitest\n  test('works', () => {\n    expect(import.meta.vitest).toBeDefined()\n  })\n}\n    `,\n        'package.json': JSON.stringify({\n          name: '@test/no-globals-esm-cjs-native-module-runner',\n          type: 'commonjs',\n        }),\n      },\n      {\n        includeSource: ['./in-source.js'],\n      },\n    )\n    expect(stderr).toBe('')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"in-source.js\": {\n          \"works\": \"passed\",\n        },\n      }\n    `)\n  })\n\n  test('in-source tests in ESM work', async () => {\n    const { stderr, testTree } = await runNoViteModuleRunnerTests(\n      {\n        'in-source.js': `\nif (import.meta.vitest) {\n  const { test, expect } = import.meta.vitest\n  test('works', () => {\n    expect(import.meta.vitest).toBeDefined()\n  })\n}\n    `,\n        'package.json': JSON.stringify({\n          name: '@test/no-globals-cjs-esm-native-module-runner',\n          type: 'module',\n        }),\n      },\n      {\n        includeSource: ['./in-source.js'],\n      },\n    )\n    expect(stderr).toBe('')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"in-source.js\": {\n          \"works\": \"passed\",\n        },\n      }\n    `)\n  })\n\n  test('in-source test doesn\\'t run when imported by actual test', async () => {\n    const { stderr, testTree } = await runNoViteModuleRunnerTests(\n      {\n        'add.js': /* js */`\nexport function add(a, b) {\n  return a + b\n}\n\nif (import.meta.vitest) {\n  const { test, expect } = import.meta.vitest\n  test('adds', () => {\n    expect(add(1, 1)).toBe(2)\n  })\n}\n    `,\n        'add.test.js': /* js */`\nimport { add } from './add.js'\nimport { test, expect } from 'vitest'\ntest('add is only once', () => {\n  expect(add(1, 1)).toBe(2)\n})\n    `,\n        'package.json': JSON.stringify({\n          name: '@test/native-module-runner',\n          type: 'module',\n        }),\n      },\n      {\n        includeSource: ['./in-source.js'],\n      },\n    )\n    expect(stderr).toBe('')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"add.test.js\": {\n          \"add is only once\": \"passed\",\n        },\n      }\n    `)\n  })\n\n  test('cannot import JS file without extension in ESM', async () => {\n    const { stderr, root } = await runNoViteModuleRunnerTests({\n      'add.js': /* js */`\nexport function add(a, b) {\n  return a + b\n}\n    `,\n      'add.test.js': /* js */`\nimport { add } from './add' // [!] no extension\ntest('not reported')\n    `,\n    })\n    expect(replaceRoot(stderr, root)).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  add.test.js [ add.test.js ]\n      Error: Cannot find module '<root>/add' imported from <root>/add.test.js\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\n      Serialized Error: { code: 'ERR_MODULE_NOT_FOUND', url: '<urlRoot>/add' }\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('cannot import TS without extension in ESM', async () => {\n    const { stderr, root } = await runNoViteModuleRunnerTests({\n      'add.ts': /* ts */`\nexport function add(a: number, b: number): number {\n  return a + b\n}\n    `,\n      'add.test.js': /* js */`\nimport { add } from './add.js' // [!] JS extension is NOT valid\ntest('not reported')\n    `,\n    })\n    expect(replaceRoot(stderr, root)).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  add.test.js [ add.test.js ]\n      Error: Cannot find module '<root>/add.js' imported from <root>/add.test.js\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\n      Serialized Error: { code: 'ERR_MODULE_NOT_FOUND', url: '<urlRoot>/add.js' }\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test.runIf(process.features.typescript)('an error in in-source tests is shown correctly', async () => {\n    const { stderr, errorTree } = await runNoViteModuleRunnerTests(\n      {\n        'in-source.ts': `\ninterface HelloWorld {\n  isStripped: true\n}\n\nif (import.meta.vitest) {\n  const {\n    test,\n    expect\n  } = import.meta.vitest\n\n  test('works', () => {\n    throw new Error('test throws correctly')\n  })\n}\n    `,\n        'package.json': JSON.stringify({\n          name: '@test/no-globals-cjs-esm-native-module-runner',\n          type: 'module',\n        }),\n      },\n      {\n        includeTaskLocation: true,\n        includeSource: ['./in-source.ts'],\n      },\n    )\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  in-source.ts:12:3 > works\n      Error: test throws correctly\n       ❯ <anonymous> in-source.ts:13:11\n           11|\n           12|   test('works', () => {\n           13|     throw new Error('test throws correctly')\n             |           ^\n           14|   })\n           15| }\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n    expect(errorTree()).toMatchInlineSnapshot(`\n      {\n        \"in-source.ts\": {\n          \"works\": [\n            \"test throws correctly\",\n          ],\n        },\n      }\n    `)\n  })\n\n  test('error in the sync mock factory is reported', async () => {\n    const { stderr } = await runNoViteModuleRunnerTests({\n      'add.js': /* js */`\nexport function add(a, b) {\n  return a + b\n}\n    `,\n      'add.test.js': /* js */`\nimport { add } from './add.js'\nvi.mock('./add.js', () => {\n  throw new Error('error from factory')\n})\ntest('not reported')\n    `,\n    })\n\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  add.test.js [ add.test.js ]\n      Error: [vitest] There was an error when mocking a module. If you are using \"vi.mock\" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock\n       ❯ add.js?mock=manual:2:65\n       ❯ <anonymous> add.test.js:2:1\n            1|\n            2| import { add } from './add.js'\n             | ^\n            3| vi.mock('./add.js', () => {\n            4|   throw new Error('error from factory')\n\n      Caused by: Error: error from factory\n       ❯ <anonymous> add.test.js:4:9\n       ❯ add.js?mock=manual:2:65\n       ❯ <anonymous> add.test.js:2:1\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('error in the async mock factory is reported', async () => {\n    // async error is reported also as unhandled exception\n    // I wasn't able to figure out what doesn't handle it properly\n    // and assume it is something internal in Node.js\n    // If it wasn't caught by us, we wouldn't have gotten the \"suite\" issue\n    const { stderr } = await runNoViteModuleRunnerTests({\n      'add.js': /* js */`\nexport function add(a, b) {\n  return a + b\n}\n    `,\n      'add.test.js': /* js */`\nimport { add } from './add.js'\nvi.mock('./add.js', async () => {\n  await Promise.resolve()\n  throw new Error('error from factory')\n})\ntest('not reported')\n    `,\n    })\n\n    // \"slice\" removes the stack from unhandled error because it references built artifacts\n    expect(stderr.split('\\n').slice(0, 17).join('\\n')).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  add.test.js [ add.test.js ]\n      Error: [vitest] There was an error when mocking a module. If you are using \"vi.mock\" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock\n      Caused by: Error: error from factory\n       ❯ <anonymous> add.test.js:5:9\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      ⎯⎯⎯⎯⎯⎯ Unhandled Errors ⎯⎯⎯⎯⎯⎯\n\n      Vitest caught 1 unhandled error during the test run.\n      This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.\n\n      ⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯\n      Error: [vitest] There was an error when mocking a module. If you are using \"vi.mock\" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock\"\n    `)\n  })\n\n  test('can load a custom environment', async () => {\n    const { stderr, testTree } = await runNoViteModuleRunnerTests(\n      {\n        './env.js': /* js */`\nexport default {\n  name: 'custom',\n  viteEnvironment: 'client', // this is actually not used, but kept for consistency\n  setup() {\n    if (typeof __vite_ssr_import__ !== 'undefined') {\n      throw new Error('expected no module runner')\n    }\n    globalThis.CUSTOM_ENV = true\n    return {\n      teardown() {\n        delete globalThis.CUSTOM_ENV\n      }\n    }\n  }\n}\n      `,\n        'basic.test.js': /* js */ `\ntest('custom env is set', () => {\n  expect(globalThis.CUSTOM_ENV).toBe(true)\n})\n      `,\n      },\n      {\n        environment: './env.js',\n      },\n    )\n    expect(stderr).toBe('')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"basic.test.js\": {\n          \"custom env is set\": \"passed\",\n        },\n      }\n    `)\n  })\n\n  describe('.cts', () => {\n    test('as esm is not supported', async () => {\n      const { stderr } = await runNoViteModuleRunnerTests({\n        'add.cts': /* ts */`\nexport function add(a: number, b: number): number {\n  return a + b\n}\n      `,\n        'add.test.cts': /* ts */`\nimport * as _ from './add.cts'\ntest('2+2=4', () => {\n  expect(_.add(2, 2)).toBe(4)\n})\n`,\n      })\n      expect(stderr).toContain('Cannot use import statement outside a module')\n    })\n\n    test('by default with type stripping is not supported', async () => {\n      const { stderr } = await runNoViteModuleRunnerTests({\n        'add.cts': /* ts */`\nexport = function add(a: number, b: number): number {\n  return a + b\n}\n      `,\n        'add.test.cts': /* ts */`\nimport _ = require('./add.cts')\ntest('2+2=4', () => {\n  expect(_.add(2, 2)).toBe(4)\n})\n`,\n      })\n      expect(stderr).toMatchInlineSnapshot(`\n        \"\n        ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n         FAIL  add.test.cts [ add.test.cts ]\n        SyntaxError: TypeScript import equals declaration is not supported in strip-only mode\n        ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\n        Serialized Error: { code: 'ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX' }\n        ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n        \"\n      `)\n    })\n\n    test('with --experimental-transform-types is supported', async () => {\n      const { errorTree } = await runNoViteModuleRunnerTests(\n        {\n          'add.cts': /* ts */`\nexport = function add(a: number, b: number): number {\n  return a + b\n}\n      `,\n          'add.test.mts': /* ts */`\nimport add from './add.cts'\ntest('2+2=4', () => {\n  expect(add(2, 2)).toBe(4)\n})\n`,\n        },\n        {\n          execArgv: ['--experimental-transform-types'],\n        },\n      )\n      expect(errorTree()).toMatchInlineSnapshot(`\n        {\n          \"add.test.mts\": {\n            \"2+2=4\": \"passed\",\n          },\n        }\n      `)\n    })\n  })\n})\n\ndescribe.runIf(!module.registerHooks)('unsupported', () => {\n  test('prints a warning if nodeLoader is not enabled', async () => {\n    const { stderr } = await runNoViteModuleRunnerTests(\n      { 'basic.test.js': `test('skip')` },\n    )\n    expect(stderr).toContain(`WARNING  \"module.registerHooks\" is not supported in Node.js ${process.version}. This means that some features like module mocking or in-source testing are not supported. Upgrade your Node.js version to at least 22.15 or disable \"experimental.nodeLoader\" flag manually.`)\n  })\n})\n\nfunction runNoViteModuleRunnerTests(structure: TestFsStructure, vitestConfig?: RunVitestConfig, options?: VitestRunnerCLIOptions) {\n  return runInlineTests(structure, {\n    globals: true,\n    ...vitestConfig,\n    experimental: {\n      ...vitestConfig?.experimental,\n      viteModuleRunner: false,\n    },\n  }, options)\n}\n"
  },
  {
    "path": "test/cli/test/no-unexpected-logging.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { runVitest, StableTestFileOrderSorter } from '../../test-utils'\n\n// Test to detect that there are no unexpected logs, like NodeJS MaxListenersExceededWarning\n\ndescribe.each(['forks', 'threads', 'vmForks', 'vmThreads'] as const)('%s', (pool) => {\n  test.each([true, false])(`should not log anything unexpected { isolate: %s }`, async (isolate) => {\n    const { stdout, stderr } = await runVitest({\n      root: './fixtures/no-unexpected-logging',\n      pool,\n      isolate,\n      sequence: { sequencer: StableTestFileOrderSorter },\n    })\n\n    expect(stderr).toBe('')\n\n    expect(normalizeOutput(stdout)).toBe(`\n RUN  v[...]\n\n ✓ fixture-1.test.ts > test 1 [...]ms\n ✓ fixture-10.test.ts > test 10 [...]ms\n ✓ fixture-11.test.ts > test 11 [...]ms\n ✓ fixture-12.test.ts > test 12 [...]ms\n ✓ fixture-2.test.ts > test 2 [...]ms\n ✓ fixture-3.test.ts > test 3 [...]ms\n ✓ fixture-4.test.ts > test 4 [...]ms\n ✓ fixture-5.test.ts > test 5 [...]ms\n ✓ fixture-6.test.ts > test 6 [...]ms\n ✓ fixture-7.test.ts > test 7 [...]ms\n ✓ fixture-8.test.ts > test 8 [...]ms\n ✓ fixture-9.test.ts > test 9 [...]ms\n\n Test Files  12 passed (12)\n      Tests  12 passed (12)\n   Start at  [...]\n   Duration  [...]ms (transform [...]ms, setup [...]ms, import [...]ms, tests [...]ms, environment [...]ms)\n\n   `.trim())\n  })\n})\n\nfunction normalizeOutput(stdtout: string) {\n  const rows = stdtout.replace(/\\d?\\.?\\d+m?s/g, '[...]ms').split('\\n').map((row) => {\n    if (row.includes('RUN  v')) {\n      return `${row.split('RUN  v')[0]}RUN  v[...]`\n    }\n\n    if (row.includes('Start at')) {\n      return row.replace(/\\d+:\\d+:\\d+/, '[...]')\n    }\n    return row\n  })\n\n  return rows.join('\\n').trim()\n}\n"
  },
  {
    "path": "test/cli/test/node-builtins.test.ts",
    "content": "import { runInlineTests } from '#test-utils'\nimport { expect, test } from 'vitest'\n\nconst nodeMajor = Number(process.version.slice(1).split('.')[0])\n\ntest.runIf(nodeMajor >= 22)('can import node:sqlite', async () => {\n  const { vitest, results } = await runInlineTests({\n    'vitest.config.ts': {\n      test: {\n        pool: 'forks',\n        execArgv: ['--experimental-sqlite', '--no-warnings=ExperimentalWarning'],\n      },\n    },\n    'basic.test.ts': /* ts */`\n      import { test, expect } from 'vitest'\n      import sqlite from 'node:sqlite'\n\n      test('sqlite', () => {\n        console.log(sqlite)\n      })\n    `,\n  })\n  expect(vitest.stderr).toBe('')\n  expect(results[0].ok()).toBe(true)\n})\n"
  },
  {
    "path": "test/cli/test/open-telemetry.test.ts",
    "content": "import type { TestUserConfig } from 'vitest/node'\nimport { playwright } from '@vitest/browser-playwright'\nimport { describe, expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ndescribe.for([\n  'root',\n  'project',\n])('as a %s config', (type) => {\n  test.for([\n    { name: 'forks', pool: 'forks' },\n    { name: 'threads', pool: 'threads' },\n    { name: 'vmForks', pool: 'vmForks' },\n    { name: 'vmThreads', pool: 'vmThreads' },\n    {\n      name: 'browser',\n      browser: {\n        enabled: true,\n        provider: playwright(),\n        headless: true,\n        instances: [{ browser: 'chromium' as const }],\n      },\n    },\n    {\n      name: 'browser-sdk',\n      browser: {\n        enabled: true,\n        provider: playwright(),\n        headless: true,\n        instances: [{ browser: 'chromium' as const }],\n      },\n    },\n  ])('$name doesn\\'t crash vitest', async (custom) => {\n    const config: TestUserConfig = {\n      ...custom,\n      experimental: {\n        openTelemetry: {\n          enabled: true,\n          sdkPath: './otel.sdk.js',\n          browserSdkPath: custom.name === 'browser-sdk'\n            ? './otel.browser.sdk.js'\n            : undefined,\n        },\n      },\n    }\n\n    const { testTree, stderr } = await runVitest({\n      // root needs to be set before vitest sets up,\n      // but browser options need to be in the config already\n      root: './fixtures/otel-tests',\n      ...(type === 'root'\n        ? config\n        : { projects: [{ test: config }] }),\n    })\n    expect(stderr).toBe('')\n    expect(testTree()).toMatchInlineSnapshot(`\n      {\n        \"basic.test.ts\": {\n          \"passes\": \"passed\",\n        },\n      }\n    `)\n  })\n})\n"
  },
  {
    "path": "test/cli/test/optimize-deps.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('optimize deps optimizes them into node_modules/.vite', async () => {\n  const { errorTree, stderr } = await runVitest({\n    root: './fixtures/optimize-deps',\n    deps: {\n      optimizer: {\n        client: {\n          enabled: true,\n        },\n        ssr: {\n          enabled: true,\n        },\n      },\n    },\n    $viteConfig: {\n      optimizeDeps: {\n        include: ['@test/test-dep-url'],\n      },\n      ssr: {\n        optimizeDeps: {\n          include: ['@test/test-dep-url'],\n        },\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"ssr.test.ts\": {\n        \"import.meta.url\": \"passed\",\n      },\n      \"web.test.ts\": {\n        \"import.meta.url\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/oxc.test.ts",
    "content": "import { runInlineTests } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest('oxc config on browser', async () => {\n  const result = await runInlineTests({\n    // needs a config file to reproduce\n    // https://github.com/vitest-dev/vitest/issues/9800\n    'vitest.config.ts': `\nimport { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    browser: {\n      enabled: true,\n      headless: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n      ],\n    },\n  },\n  oxc: {\n    jsx: {\n      refresh: false,\n    }\n  }\n})\n`,\n    'basic.test.ts': `\nimport { test } from \"vitest\";\ntest('basic', () => {});\n`,\n  })\n\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"basic\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/path-filter.test.ts",
    "content": "import { test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('test path is shown when filtering', async () => {\n  const { vitest } = await runVitest({\n    root: 'fixtures/path-filter',\n    watch: true,\n  })\n\n  await vitest.waitForStdout('press h to show help, press q to quit')\n  vitest.write('t')\n  await vitest.waitForStdout(`? Input test name pattern (RegExp)`)\n  vitest.write('foo')\n  await vitest.waitForStdout('Pattern matches 1 result')\n  await vitest.waitForStdout('basic.test.ts > basic path filter > foo')\n})\n"
  },
  {
    "path": "test/cli/test/plugin.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nit('plugin hooks', async () => {\n  await runVitest({ root: './fixtures/plugin' })\n  expect((globalThis as any).__testHooks.slice(0, 5)).toEqual(\n    [\n      'configureServer(pre)',\n      'configureServer(default)',\n      'buildStart(pre)',\n      'buildStart(default)',\n      'resolveId(pre)',\n    ],\n  )\n})\n"
  },
  {
    "path": "test/cli/test/print-error.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\ntest('prints a custom error stack', async () => {\n  const { stderr } = await runInlineTests({\n    'basic.test.ts': `\n    test('failed test', () => {\n      throw {\n        message: 'from failed test',\n        stack: ['stack 1', 'stack 2'],\n      }\n    })\n\n    test('fails toJson', () => {\n      class CustomError extends Error {\n        name = 'CustomError'\n        toJSON() {\n          return {\n            message: this.message,\n            stack: ['custom stack 1', 'custom stack 2']\n          }\n        }\n      }\n\n      throw new CustomError('custom error')\n    })\n    `,\n  }, { globals: true })\n\n  expect(stderr).toContain(`\n FAIL  basic.test.ts > failed test\nUnknown Error: from failed test\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\nSerialized Error: { stack: [ 'stack 1', 'stack 2' ] }\n    `.trim())\n\n  expect(stderr).toContain(`\n FAIL  basic.test.ts > fails toJson\nCustomError: custom error\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\nSerialized Error: { stack: [ 'custom stack 1', 'custom stack 2' ] }\n    `.trim())\n})\n\ntest('prints buffer and UintArray', async () => {\n  const { stderr } = await runInlineTests({\n    'basic.test.ts': `\n    test('failed test', () => {\n      throw {\n        buffer: Buffer.from([1, 2, 3]),\n        uintarray: Uint8Array.from([1, 2, 3]),\n      }\n    })\n    `,\n  }, { globals: true })\n\n  expect(stderr).toContain(`buffer: '<Buffer(3) ...>'`)\n  expect(stderr).toContain(`uintarray: '<Uint8Array(3) ...>'`)\n})\n"
  },
  {
    "path": "test/cli/test/projects.test.ts",
    "content": "import { runInlineTests, runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { describe, expect, it } from 'vitest'\n\nit('runs the workspace if there are several vitest config files', async () => {\n  const { stderr, stdout } = await runVitest({\n    root: 'fixtures/workspace/several-configs',\n  })\n  expect(stderr).toBe('')\n  expect(stdout).toContain('workspace/several-configs')\n  expect(stdout).toContain('| 1_test')\n  expect(stdout).toContain('| 2_test')\n  expect(stdout).toContain('1 + 1 = 2')\n  expect(stdout).toContain('2 + 2 = 4')\n})\n\nit('correctly resolves workspace projects with a several folder globs', async () => {\n  const { stderr, stdout } = await runVitest({\n    root: 'fixtures/workspace/several-folders',\n  })\n  expect(stderr).toBe('')\n  expect(stdout).toContain('test - a')\n  expect(stdout).toContain('test - b')\n})\n\nit('supports glob negation pattern', async () => {\n  const { stderr, stdout } = await runVitest({\n    root: 'fixtures/workspace/negated',\n  })\n  expect(stderr).toBe('')\n  expect(stdout).toContain('test - a')\n  expect(stdout).toContain('test - c')\n  expect(stdout).not.toContain('test - b')\n})\n\nit('fails if project names are identical with a nice error message', async () => {\n  const { stderr } = await runVitest({\n    root: 'fixtures/workspace/invalid-duplicate-configs',\n  }, [], { fails: true })\n  expect(stderr).toContain(\n    `Project name \"test\" from \"vitest.config.two.js\" is not unique. The project is already defined by \"vitest.config.one.js\".\n\nYour config matched these files:\n - vitest.config.one.js\n - vitest.config.two.js\n\nAll projects should have unique names. Make sure your configuration is correct.`,\n  )\n})\n\nit('fails if project names are identical inside the inline config', async () => {\n  const { stderr } = await runVitest({\n    root: 'fixtures/workspace/invalid-duplicate-inline',\n  }, [], { fails: true })\n  expect(stderr).toContain(\n    'Project name \"test\" is not unique. All projects should have unique names. Make sure your configuration is correct.',\n  )\n})\n\nit('fails if referenced file doesnt exist', async () => {\n  const { stderr } = await runVitest({\n    root: 'fixtures/workspace/invalid-non-existing-config',\n  }, [], { fails: true })\n  expect(stderr).toContain(\n    `Projects definition references a non-existing file or a directory: ${resolve('fixtures/workspace/invalid-non-existing-config/vitest.config.js')}`,\n  )\n})\n\nit('vite import analysis is applied when loading workspace config', async () => {\n  const { stderr, stdout } = await runVitest({\n    root: 'fixtures/workspace/config-import-analysis',\n  })\n  expect(stderr).toBe('')\n  expect(stdout).toContain('test - a')\n})\n\nit('can define inline workspace config programmatically', async () => {\n  const { stderr, stdout } = await runVitest({\n    root: 'fixtures/workspace/api',\n    env: {\n      TEST_ROOT: '1',\n    },\n    projects: [\n      {\n        extends: true,\n        test: {\n          name: 'project-1',\n        },\n      },\n      {\n        test: {\n          name: 'project-2',\n          env: {\n            TEST_ROOT: '2',\n          },\n        },\n      },\n      {\n        extends: './vite.custom.config.js',\n        test: {\n          name: 'project-3',\n        },\n      },\n    ],\n  })\n  expect(stderr).toBe('')\n  expect(stdout).toContain('project-1')\n  expect(stdout).toContain('project-2')\n  expect(stdout).toContain('project-3')\n  expect(stdout).toContain('3 passed')\n})\n\nit('correctly inherits the root config', async () => {\n  const { stderr, stdout } = await runVitest({\n    root: 'fixtures/workspace/config-extends',\n  })\n  expect(stderr).toBe('')\n  expect(stdout).toContain('repro.test.js > importing a virtual module')\n})\n\nit('fails if workspace is empty', async () => {\n  const { stderr } = await runVitest({\n    projects: [],\n  }, [], { fails: true })\n  expect(stderr).toContain('No projects were found. Make sure your configuration is correct. The projects definition: [].')\n})\n\nit('fails if workspace is filtered by the project', async () => {\n  const { stderr } = await runVitest({\n    project: 'non-existing',\n    root: 'fixtures/workspace/config-empty',\n    config: './vitest.config.js',\n    projects: [\n      './vitest.config.js',\n    ],\n  }, [], { fails: true })\n  expect(stderr).toContain(`No projects were found. Make sure your configuration is correct. The filter matched no projects: non-existing. The projects definition: [\n    \"./vitest.config.js\"\n].`)\n})\n\ndescribe('the config file names', () => {\n  it('[glob] the name has \"unit\" between \"vitest\" and \"config\" and works', async () => {\n    const { exitCode } = await runInlineTests({\n      'vitest.unit.config.js': {},\n      'vitest.config.js': {\n        test: {\n          passWithNoTests: true,\n          projects: ['./vitest.*.config.js'],\n        },\n      },\n    })\n\n    expect(exitCode).toBe(0)\n  })\n\n  it('[glob] the name does not start with \"vite\"/\"vitest\" and throws an error', async () => {\n    const { stderr } = await runInlineTests({\n      'unit.config.js': {},\n      'vitest.config.js': {\n        test: {\n          projects: ['./*.config.js'],\n        },\n      },\n    }, {}, { fails: true })\n\n    expect(stderr).toContain('The projects glob matched a file \"unit.config.js\", but it should also either start with \"vitest.config\"/\"vite.config\" or match the pattern \"(vitest|vite).*.config.*\".')\n  })\n\n  it('[file] the name has \"unit\" between \"vitest\" and \"config\" and works', async () => {\n    const { exitCode } = await runInlineTests({\n      'vitest.unit.config.js': {},\n      'vitest.config.js': {\n        test: {\n          passWithNoTests: true,\n          projects: ['./vitest.unit.config.js'],\n        },\n      },\n    })\n\n    expect(exitCode).toBe(0)\n  })\n\n  it('[glob] the name has \"unit-test\" (with hyphen) between \"vitest\" and \"config\" and works', async () => {\n    const { exitCode } = await runInlineTests({\n      'vitest.unit-test.config.js': {},\n      'vitest.config.js': {\n        test: {\n          passWithNoTests: true,\n          projects: ['./vitest.*.config.js'],\n        },\n      },\n    })\n\n    expect(exitCode).toBe(0)\n  })\n\n  it('[file] the name has \"unit-test\" (with hyphen) between \"vitest\" and \"config\" and works', async () => {\n    const { exitCode } = await runInlineTests({\n      'vitest.unit-test.config.js': {},\n      'vitest.config.js': {\n        test: {\n          passWithNoTests: true,\n          projects: ['./vitest.unit-test.config.js'],\n        },\n      },\n    })\n\n    expect(exitCode).toBe(0)\n  })\n\n  it('[file] the name does not start with \"vite\"/\"vitest\" and throws an error', async () => {\n    const { stderr } = await runInlineTests({\n      'unit.config.js': {},\n      'vitest.config.js': {\n        test: {\n          passWithNoTests: true,\n          projects: ['./unit.config.js'],\n        },\n      },\n    }, {}, { fails: true })\n\n    expect(stderr).toContain('The file \"unit.config.js\" must start with \"vitest.config\"/\"vite.config\" or match the pattern \"(vitest|vite).*.config.*\" to be a valid project config.')\n  })\n})\n\ndescribe('project filtering', () => {\n  const allProjects = ['project_1', 'project_2', 'space_1']\n\n  it.for([\n    { pattern: 'project_1', expected: ['project_1'] },\n    { pattern: '*', expected: allProjects },\n    { pattern: '*j*', expected: ['project_1', 'project_2'] },\n    { pattern: 'project*', expected: ['project_1', 'project_2'] },\n    { pattern: 'space*', expected: ['space_1'] },\n    { pattern: '!project_1', expected: ['project_2', 'space_1'] },\n    { pattern: '!project*', expected: ['space_1'] },\n    { pattern: '!project', expected: allProjects },\n  ])('should match projects correctly: $pattern', async ({ pattern, expected }) => {\n    const { ctx, stderr, stdout } = await runVitest({\n      root: 'fixtures/project',\n      reporters: ['default'],\n      project: pattern,\n    })\n\n    expect(stderr).toBeFalsy()\n    expect(stdout).toBeTruthy()\n\n    for (const project of allProjects) {\n      if (expected.includes(project)) {\n        expect(stdout).toContain(project)\n      }\n      else {\n        expect(stdout).not.toContain(project)\n      }\n    }\n\n    expect(ctx?.projects.map(p => p.name).sort()).toEqual(expected)\n  })\n})\n"
  },
  {
    "path": "test/cli/test/public-api.test.ts",
    "content": "import type { TaskMeta } from '@vitest/runner'\nimport type { TestModule, TestUserConfig } from 'vitest/node'\nimport { resolve } from 'pathe'\nimport { expect, it } from 'vitest'\nimport { rolldownVersion } from 'vitest/node'\nimport { runVitest } from '../../test-utils'\n\nit.each([\n  { name: 'threads are enabled', pool: 'threads' },\n  { name: 'threads are disabled', pool: 'forks' },\n  {\n    name: 'running in the browser',\n    browser: {\n      enabled: true,\n    },\n  },\n] as TestUserConfig[])('passes down metadata when $name', { timeout: 60_000, retry: 1 }, async (config) => {\n  const finishedTestCaseMetas: TaskMeta[] = []\n  const finishedTestModuleMetas: TaskMeta[] = []\n\n  const finishedTestModules: TestModule[] = []\n  const collectedTestModules: TestModule[] = []\n  const { ctx, stdout, stderr } = await runVitest({\n    root: resolve(__dirname, '..', 'fixtures', 'public-api'),\n    include: ['**/*.spec.ts'],\n    reporters: [\n      ['verbose', { isTTY: false }],\n      {\n        onTestCaseResult(testCase) {\n          finishedTestCaseMetas.push(testCase.meta())\n        },\n        onTestModuleEnd(testModule) {\n          finishedTestModuleMetas.push(testModule.meta())\n        },\n        onTestRunEnd(testModules) {\n          finishedTestModules.push(...testModules)\n        },\n        onTestModuleCollected(testModule) {\n          collectedTestModules.push(testModule)\n        },\n      },\n    ],\n    includeTaskLocation: true,\n    ...config,\n  })\n\n  expect(stderr).toBe('')\n\n  expect(stdout).toContain('custom.spec.ts:14:1 > custom')\n\n  const suiteMeta = { done: true }\n  const testMeta = { custom: 'some-custom-hanlder' }\n\n  expect(finishedTestCaseMetas).toHaveLength(3)\n  expect(finishedTestModuleMetas).toHaveLength(1)\n  expect(finishedTestModules).toHaveLength(1)\n\n  const files = ctx?.state.getFiles() || []\n  expect(files).toHaveLength(1)\n\n  expect(finishedTestModuleMetas).toContainEqual(suiteMeta)\n\n  expect(finishedTestCaseMetas).toContainEqual(testMeta)\n\n  const test = finishedTestModules[0].children.tests().next().value!\n\n  expect(finishedTestModules[0].meta()).toEqual(suiteMeta)\n  expect(test.meta()).toEqual(testMeta)\n\n  expect(files[0].meta).toEqual(suiteMeta)\n  expect(files[0].tasks[0].meta).toEqual(testMeta)\n\n  expect(test.location).toEqual({\n    line: 14,\n    column: 1,\n  })\n  expect(collectedTestModules[0].task.tasks[0].location).toEqual({\n    line: 14,\n    column: 1,\n  })\n  expect(files[0].tasks[0].location).toEqual({\n    line: 14,\n    column: 1,\n  })\n\n  const eachTests = [1, 2]\n  eachTests.forEach((name, index) => {\n    expect(files[0].tasks[index + 1].name).toBe(`custom ${name}`)\n    expect(files[0].tasks[index + 1].location).toEqual({\n      line: 18,\n      // TODO: rolldown is more correct, but regular vite's source map is\n      // a little bit wrong with the boundaries (maybe because of the SSR transform?)\n      column: rolldownVersion || config.browser?.enabled ? 18 : 17,\n    })\n  })\n})\n\nit('can modify the global test name pattern', async () => {\n  const { ctx } = await runVitest({\n    standalone: true,\n    watch: true,\n    testNamePattern: 'custom',\n  })\n\n  expect(ctx?.getGlobalTestNamePattern()).toEqual(/custom/)\n\n  // reset just removes the override, user config is not touched\n  ctx?.resetGlobalTestNamePattern()\n  expect(ctx?.getGlobalTestNamePattern()).toEqual(/custom/)\n\n  ctx?.setGlobalTestNamePattern(/new pattern/)\n  expect(ctx?.getGlobalTestNamePattern()).toEqual(/new pattern/)\n\n  ctx?.resetGlobalTestNamePattern()\n  expect(ctx?.getGlobalTestNamePattern()).toEqual(/custom/)\n})\n"
  },
  {
    "path": "test/cli/test/public-mocker.test.ts",
    "content": "import type { Browser } from 'playwright'\nimport type { UserConfig } from 'vite'\nimport { mockerPlugin } from '@vitest/mocker/node'\nimport { chromium } from 'playwright'\nimport { createServer } from 'vite'\nimport { beforeAll, expect, it, onTestFinished } from 'vitest'\n\nlet browser: Browser\nbeforeAll(async () => {\n  browser = await chromium.launch()\n  return async () => {\n    await browser.close()\n    browser = null as any\n  }\n})\n\nit('default server manual mocker works correctly', async () => {\n  const { page } = await createTestServer({\n    root: './fixtures/mocker/manual-mock',\n  })\n\n  await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('true')\n})\n\nit('automock works correctly', async () => {\n  const { page } = await createTestServer({\n    root: './fixtures/mocker/automock',\n  })\n\n  await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('42')\n})\n\nit('autospy works correctly', async () => {\n  const { page } = await createTestServer({\n    root: './fixtures/mocker/autospy',\n  })\n\n  await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('3, 42')\n})\n\nit('redirect works correctly', async () => {\n  const { page } = await createTestServer({\n    root: './fixtures/mocker/redirect',\n  })\n\n  await expect.poll(() => page.locator('css=#mocked').textContent()).toBe('42')\n})\n\nasync function createTestServer(config: UserConfig) {\n  const server = await createServer({\n    ...config,\n    cacheDir: '.cache',\n    plugins: [\n      mockerPlugin({\n        globalThisAccessor: 'Symbol.for(\"vitest.mocker\")',\n        hoistMocks: {\n          utilsObjectNames: ['mocker'],\n          hoistedModule: 'virtual:mocker',\n          hoistableMockMethodNames: ['customMock'],\n          dynamicImportMockMethodNames: ['customMock'],\n          hoistedMethodNames: ['customHoisted'],\n        },\n      }),\n      {\n        name: 'vi:resolver',\n        enforce: 'pre',\n        resolveId(id) {\n          if (id === 'virtual:mocker') {\n            return id\n          }\n        },\n        load(id) {\n          if (id === 'virtual:mocker') {\n            return `\nimport { registerModuleMocker } from '@vitest/mocker/register'\nimport { ModuleMockerServerInterceptor } from '@vitest/mocker/browser'\n\nconst _mocker = registerModuleMocker(\n  () => new ModuleMockerServerInterceptor()\n)\n\nexport const mocker = {\n  customMock: _mocker.mock,\n  customHoisted: _mocker.hoisted,\n}\n            `\n          }\n        },\n      },\n    ],\n  })\n  await server.listen()\n  onTestFinished(async () => {\n    await server.close()\n  })\n  const page = await browser.newPage()\n  onTestFinished(async () => {\n    await page.close()\n  })\n  await page.goto(server.resolvedUrls!.local[0])\n\n  return {\n    server,\n    page,\n  }\n}\n"
  },
  {
    "path": "test/cli/test/reported-tasks.test.ts",
    "content": "import type { RunnerTestFile } from 'vitest'\nimport type { TestCase, TestCollection, TestModule, TestProject, Vitest } from 'vitest/node'\nimport { resolve } from 'pathe'\nimport { it as baseTest, expect } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nconst root = resolve(__dirname, '..', 'fixtures', 'reported-tasks')\n\nconst it = baseTest.extend<{\n  ctx: Vitest\n  files: RunnerTestFile[]\n  testModule: TestModule\n  project: TestProject\n}>({\n  ctx: [\n    async ({}, use) => {\n      const collectedTestModules: TestModule[] = []\n      const { ctx } = await runVitest({\n        root,\n        include: ['**/*.test.ts'],\n        reporters: [\n          'verbose',\n          {\n            onTestModuleCollected(testModule) {\n              collectedTestModules.push(testModule)\n            },\n          },\n        ],\n        includeTaskLocation: true,\n        logHeapUsage: true,\n        experimental: { importDurations: { limit: 10 } },\n      })\n      expect(collectedTestModules).toHaveLength(1)\n      await use(ctx!)\n    },\n    { scope: 'file' },\n  ],\n  files: [\n    async ({ ctx }, use) => {\n      const state = ctx!.state\n      const files = state.getFiles()\n      await use(files)\n    },\n    { scope: 'file' },\n  ],\n  testModule: [\n    async ({ ctx, files }, use) => {\n      const state = ctx!.state\n      const testModule = state.getReportedEntity(files[0])! as TestModule\n      await use(testModule)\n    },\n    { scope: 'file' },\n  ],\n  project: [\n    async ({ ctx }, use) => {\n      const project = ctx!.getRootProject()\n      await use(project)\n    },\n    { scope: 'file' },\n  ],\n})\n\nconst now = new Date()\n\nit('correctly reports a file', ({ testModule, files, project }) => {\n  // suite properties not available on file\n  expect(testModule).not.toHaveProperty('parent')\n  expect(testModule).not.toHaveProperty('options')\n  expect(testModule).not.toHaveProperty('module')\n  expect(testModule).not.toHaveProperty('fullName')\n  expect(testModule).not.toHaveProperty('name')\n\n  expect(testModule.type).toBe('module')\n  expect(testModule.task).toBe(files[0])\n  expect(testModule.id).toBe(files[0].id)\n  expect(testModule.location).toBeUndefined()\n  expect(testModule.moduleId).toBe(resolve(root, './1_first.test.ts'))\n  expect(testModule.project).toBe(project)\n  expect(testModule.children.size).toBe(18)\n\n  const tests = [...testModule.children.tests()]\n  expect(tests).toHaveLength(13)\n  const deepTests = [...testModule.children.allTests()]\n  expect(deepTests).toHaveLength(23)\n\n  expect.soft([...testModule.children.allTests('skipped')]).toHaveLength(8)\n  expect.soft([...testModule.children.allTests('passed')]).toHaveLength(10)\n  expect.soft([...testModule.children.allTests('failed')]).toHaveLength(5)\n  expect.soft([...testModule.children.allTests('pending')]).toHaveLength(0)\n\n  const suites = [...testModule.children.suites()]\n  expect(suites).toHaveLength(5)\n  const deepSuites = [...testModule.children.allSuites()]\n  expect(deepSuites).toHaveLength(6)\n\n  const diagnostic = testModule.diagnostic()\n  expect(diagnostic).toBeDefined()\n  expect(diagnostic.environmentSetupDuration).toBeGreaterThan(0)\n  expect(diagnostic.prepareDuration).toBeGreaterThan(0)\n  expect(diagnostic.collectDuration).toBeGreaterThan(0)\n  expect(diagnostic.duration).toBeGreaterThan(0)\n  // doesn't have a setup file\n  expect(diagnostic.setupDuration).toBe(0)\n})\n\nit('correctly reports a passed test', ({ testModule, files }) => {\n  const passedTest = findTest(testModule.children, 'runs a test')\n  expect(passedTest.type).toBe('test')\n  expect(passedTest.task).toBe(files[0].tasks[0])\n  expect(passedTest.name).toBe('runs a test')\n  expect(passedTest.fullName).toBe('runs a test')\n  expect(passedTest.module).toBe(testModule)\n  expect(passedTest.parent).toBe(testModule)\n  expect(passedTest.options).toEqual({\n    each: undefined,\n    concurrent: undefined,\n    shuffle: undefined,\n    fails: undefined,\n    retry: undefined,\n    repeats: undefined,\n    mode: 'run',\n    tags: [],\n    timeout: 5000,\n  })\n  expect(passedTest.meta()).toEqual({})\n\n  const result = passedTest.result()!\n  expect(result).toBeDefined()\n  expect(result.state).toBe('passed')\n  expect(result.errors).toBeUndefined()\n\n  const diagnostic = passedTest.diagnostic()!\n  expect(diagnostic).toBeDefined()\n  expect(diagnostic.heap).toBeGreaterThan(0)\n  expect(diagnostic.duration).toBeGreaterThan(0)\n  expect(date(new Date(diagnostic.startTime))).toBe(date(now))\n  expect(diagnostic.flaky).toBe(false)\n  expect(diagnostic.repeatCount).toBe(0)\n  expect(diagnostic.repeatCount).toBe(0)\n})\n\nit('correctly reports failed test', ({ testModule, files }) => {\n  const passedTest = findTest(testModule.children, 'fails a test')\n  expect(passedTest.type).toBe('test')\n  expect(passedTest.task).toBe(files[0].tasks[1])\n  expect(passedTest.name).toBe('fails a test')\n  expect(passedTest.fullName).toBe('fails a test')\n  expect(passedTest.module).toBe(testModule)\n  expect(passedTest.parent).toBe(testModule)\n  expect(passedTest.options).toEqual({\n    each: undefined,\n    concurrent: undefined,\n    shuffle: undefined,\n    retry: undefined,\n    repeats: undefined,\n    mode: 'run',\n    fails: undefined,\n    tags: [],\n    timeout: 5000,\n  })\n  expect(passedTest.meta()).toEqual({})\n\n  const result = passedTest.result()!\n  expect(result).toBeDefined()\n  expect(result.state).toBe('failed')\n  expect(result.errors).toHaveLength(1)\n  expect(result.errors![0]).toMatchObject({\n    diff: expect.any(String),\n    message: 'expected 1 to be 2 // Object.is equality',\n    ok: false,\n    stack: expect.stringContaining('expected 1 to be 2 // Object.is equality'),\n    stacks: [\n      {\n        column: 13,\n        file: resolve(root, './1_first.test.ts'),\n        line: 10,\n        method: '',\n      },\n    ],\n  })\n\n  const diagnostic = passedTest.diagnostic()!\n  expect(diagnostic).toBeDefined()\n  expect(diagnostic.heap).toBeGreaterThan(0)\n  expect(diagnostic.duration).toBeGreaterThan(0)\n  expect(date(new Date(diagnostic.startTime))).toBe(date(now))\n  expect(diagnostic.flaky).toBe(false)\n  expect(diagnostic.repeatCount).toBe(0)\n  expect(diagnostic.repeatCount).toBe(0)\n})\n\nit('correctly reports a skipped test', ({ testModule }) => {\n  const optionTestCase = findTest(testModule.children, 'skips an option test')\n  expect(optionTestCase.result()).toEqual({\n    state: 'skipped',\n    note: undefined,\n    errors: undefined,\n  })\n\n  const modifierTestCase = findTest(testModule.children, 'skips a .modifier test')\n  expect(modifierTestCase.result()).toEqual({\n    state: 'skipped',\n    note: undefined,\n    errors: undefined,\n  })\n\n  const ctxSkippedTestCase = findTest(testModule.children, 'skips an ctx.skip() test')\n  expect(ctxSkippedTestCase.result()).toEqual({\n    state: 'skipped',\n    note: undefined,\n    errors: undefined,\n  })\n\n  const testOptionTodo = findTest(testModule.children, 'todos an option test')\n  expect(testOptionTodo.result()).toEqual({\n    state: 'skipped',\n    note: undefined,\n    errors: undefined,\n  })\n\n  const testModifierTodo = findTest(testModule.children, 'todos a .modifier test')\n  expect(testModifierTodo.result()).toEqual({\n    state: 'skipped',\n    note: undefined,\n    errors: undefined,\n  })\n})\n\nit('correctly reports multiple failures', ({ testModule }) => {\n  const testCase = findTest(testModule.children, 'fails multiple times')\n  const result = testCase.result()!\n  expect(result).toBeDefined()\n  expect(result.state).toBe('failed')\n  expect(result.errors).toHaveLength(2)\n  expect(result.errors![0]).toMatchObject({\n    message: 'expected 1 to be 2 // Object.is equality',\n  })\n  expect(result.errors![1]).toMatchObject({\n    message: 'expected 2 to be 3 // Object.is equality',\n  })\n})\n\nit('correctly reports test assigned options', ({ testModule }) => {\n  const testOptionSkip = findTest(testModule.children, 'skips an option test')\n  expect(testOptionSkip.options.mode).toBe('skip')\n  const testModifierSkip = findTest(testModule.children, 'skips a .modifier test')\n  expect(testModifierSkip.options.mode).toBe('skip')\n\n  const testOptionTodo = findTest(testModule.children, 'todos an option test')\n  expect(testOptionTodo.options.mode).toBe('todo')\n  const testModifierTodo = findTest(testModule.children, 'todos a .modifier test')\n  expect(testModifierTodo.options.mode).toBe('todo')\n\n  const testInsideTodoDescribe = findTest(testModule.children, 'test inside todo group')\n  expect(testInsideTodoDescribe.options.mode).toBe('todo')\n\n  const testInsideSkippedDescribe = findTest(testModule.children, 'test inside skipped group')\n  expect(testInsideSkippedDescribe.options.mode).toBe('skip')\n})\n\nit('correctly reports retried tests', ({ testModule }) => {\n  const testRetry = findTest(testModule.children, 'retries a test')\n  expect(testRetry.options.retry).toBe(5)\n  expect(testRetry.options.repeats).toBeUndefined()\n  expect(testRetry.result()!.state).toBe('failed')\n})\n\nit('correctly reports flaky tests', ({ testModule }) => {\n  const testFlaky = findTest(testModule.children, 'retries a test with success')\n  const diagnostic = testFlaky.diagnostic()!\n  expect(diagnostic.flaky).toBe(true)\n  expect(diagnostic.retryCount).toBe(2)\n  expect(diagnostic.repeatCount).toBe(0)\n  const result = testFlaky.result()!\n  expect(result.state).toBe('passed')\n  expect(result.errors).toHaveLength(2)\n})\n\nit('correctly reports repeated tests', ({ testModule }) => {\n  const testRepeated = findTest(testModule.children, 'repeats a test')\n  const diagnostic = testRepeated.diagnostic()!\n  expect(diagnostic.flaky).toBe(false)\n  expect(diagnostic.retryCount).toBe(0)\n  expect(diagnostic.repeatCount).toBe(5)\n  const result = testRepeated.result()!\n  expect(result.state).toBe('failed')\n  expect(result.errors).toHaveLength(6)\n})\n\nit('correctly passed down metadata', ({ testModule }) => {\n  const testMetadata = findTest(testModule.children, 'registers a metadata')\n  const meta = testMetadata.meta()\n  expect(meta).toHaveProperty('key', 'value')\n})\n\nit('correctly builds the full name', ({ testModule }) => {\n  const suiteTopLevel = testModule.children.suites().next().value!\n  const suiteSecondLevel = suiteTopLevel.children.suites().next().value!\n  const test = suiteSecondLevel.children.at(0) as TestCase\n  expect(test.fullName).toBe('a group > a nested group > runs a test in a nested group')\n  expect(suiteTopLevel.fullName).toBe('a group')\n  expect(suiteSecondLevel.fullName).toBe('a group > a nested group')\n})\n\nit('correctly reports import durations', ({ testModule }) => {\n  const diagnostic = testModule.diagnostic()\n\n  const filePath = resolve(root, './1_first.test.ts')\n  const importDuration = diagnostic.importDurations[filePath]\n  expect(importDuration.selfTime).toBeGreaterThan(0)\n  expect(importDuration.totalTime).toBeGreaterThan(0)\n})\n\nit('can create new test specifications', ({ testModule }) => {\n  const moduleSpec = testModule.toTestSpecification()\n  expect(moduleSpec.moduleId).toBe(testModule.moduleId)\n  expect(moduleSpec.testIds).toBeUndefined()\n  expect(moduleSpec.project).toBe(testModule.project)\n\n  const testSuite = [...testModule.children.suites()][0]\n  const suiteSpec = testSuite.toTestSpecification()\n  expect(suiteSpec.moduleId).toBe(testModule.moduleId)\n  expect(suiteSpec.testIds).toEqual([\n    '-1008553841_11_0',\n    '-1008553841_11_1',\n    '-1008553841_11_2_0',\n    '-1008553841_11_2_1',\n    '-1008553841_11_2_2',\n    '-1008553841_11_2_3',\n  ])\n  expect(suiteSpec.project).toBe(testModule.project)\n\n  const testCase = testSuite.children.at(0) as TestCase\n  const caseSpec = testCase.toTestSpecification()\n  expect(caseSpec.moduleId).toBe(testModule.moduleId)\n  expect(caseSpec.testIds).toEqual(['-1008553841_11_0'])\n  expect(caseSpec.project).toBe(testModule.project)\n})\n\nfunction date(time: Date) {\n  return `${time.getDate()}/${time.getMonth() + 1}/${time.getFullYear()}`\n}\n\nfunction deepFind(children: TestCollection, name: string): TestCase | undefined {\n  for (const task of children) {\n    if (task.type === 'test') {\n      if (task.name === name) {\n        return task\n      }\n    }\n    if (task.type === 'suite') {\n      const result = deepFind(task.children, name)\n      if (result) {\n        return result\n      }\n    }\n  }\n}\n\nfunction findTest(children: TestCollection, name: string): TestCase {\n  const testCase = deepFind(children, name)\n  if (!testCase) {\n    throw new Error(`Test \"${name}\" not found`)\n  }\n  return testCase\n}\n"
  },
  {
    "path": "test/cli/test/reporters/__snapshots__/default.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`default reporter > merge identical errors 1`] = `\n\"\n⎯⎯⎯⎯⎯⎯⎯ Failed Tests 6 ⎯⎯⎯⎯⎯⎯⎯\n\n FAIL  basic.test.ts > test-a 1\nAssertionError: expected 1 to be +0 // Object.is equality\n\n- Expected\n+ Received\n\n- 0\n+ 1\n\n ❯ basic.test.ts:5:13\n      3| // not merged\n      4| test.for([1, 2])(\"test-a %$\", (n) => {\n      5|   expect(n).toBe(0);\n       |             ^\n      6| });\n      7|\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/6]⎯\n\n FAIL  basic.test.ts > test-a 2\nAssertionError: expected 2 to be +0 // Object.is equality\n\n- Expected\n+ Received\n\n- 0\n+ 2\n\n ❯ basic.test.ts:5:13\n      3| // not merged\n      4| test.for([1, 2])(\"test-a %$\", (n) => {\n      5|   expect(n).toBe(0);\n       |             ^\n      6| });\n      7|\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/6]⎯\n\n FAIL  basic.test.ts > test-b 1\n FAIL  basic.test.ts > test-b 2\nAssertionError: expected 1 to be +0 // Object.is equality\n\n- Expected\n+ Received\n\n- 0\n+ 1\n\n ❯ basic.test.ts:10:13\n      8| // merged\n      9| test.for([1, 2])(\"test-b %$\", (n) => {\n     10|   expect(1).toBe(0);\n       |             ^\n     11| });\n     12|\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/6]⎯\n\n FAIL  basic.test.ts > test-c 1\nAssertionError: expected [ Array(1) ] to deeply equal ArrayContaining{…}\n\n- Expected\n+ Received\n\n- ArrayContaining [\n-   \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\n+ [\n+   \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n  ]\n\n ❯ basic.test.ts:24:18\n     22|   },\n     23| ])(\"test-c %$\", async ({ actual, expected }) => {\n     24|   expect(actual).toEqual(expect.arrayContaining(expected));\n       |                  ^\n     25| });\n     26|\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/6]⎯\n\n FAIL  basic.test.ts > test-c 2\nAssertionError: expected [ Array(1) ] to deeply equal ArrayContaining{…}\n\n- Expected\n+ Received\n\n- ArrayContaining [\n-   \"dddddddddddddddddddddddddddddddddddddddddddddddddd\",\n+ [\n+   \"cccccccccccccccccccccccccccccccccccccccccccccccccc\",\n  ]\n\n ❯ basic.test.ts:24:18\n     22|   },\n     23| ])(\"test-c %$\", async ({ actual, expected }) => {\n     24|   expect(actual).toEqual(expect.arrayContaining(expected));\n       |                  ^\n     25| });\n     26|\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/6]⎯\n\n\"\n`;\n"
  },
  {
    "path": "test/cli/test/reporters/__snapshots__/html.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`html reporter > resolves to \"failing\" status for test file \"json-fail\" > tests are failing 1`] = `\n{\n  \"config\": {},\n  \"files\": [\n    {\n      \"collectDuration\": 0,\n      \"environmentLoad\": 0,\n      \"file\": [Circular],\n      \"filepath\": \"<rootDir>/test/cli/fixtures/reporters/json-fail.test.ts\",\n      \"fullName\": \"json-fail.test.ts\",\n      \"id\": 0,\n      \"importDurations\": {},\n      \"meta\": {},\n      \"mode\": \"run\",\n      \"name\": \"json-fail.test.ts\",\n      \"pool\": \"forks\",\n      \"prepareDuration\": 0,\n      \"projectName\": \"\",\n      \"result\": {\n        \"duration\": 0,\n        \"startTime\": 0,\n        \"state\": \"fail\",\n      },\n      \"setupDuration\": 0,\n      \"tags\": [],\n      \"tasks\": [\n        {\n          \"annotations\": [],\n          \"artifacts\": [],\n          \"file\": [Circular],\n          \"fullName\": \"json-fail.test.ts > should fail\",\n          \"fullTestName\": \"should fail\",\n          \"id\": 0,\n          \"location\": {\n            \"column\": 1,\n            \"line\": 5,\n          },\n          \"logs\": [\n            {\n              \"content\": \"json-fail>should fail\n\",\n              \"size\": 1,\n              \"taskId\": 0,\n              \"time\": 0,\n              \"type\": \"stdout\",\n            },\n          ],\n          \"meta\": {},\n          \"mode\": \"run\",\n          \"name\": \"should fail\",\n          \"result\": {\n            \"duration\": 0,\n            \"errors\": [\n              {\n                \"actual\": \"2\",\n                \"diff\": \"- Expected\n+ Received\n\n- 1\n+ 2\",\n                \"expected\": \"1\",\n                \"message\": \"expected 2 to deeply equal 1\",\n                \"name\": \"AssertionError\",\n                \"ok\": false,\n                \"operator\": \"strictEqual\",\n                \"showDiff\": true,\n                \"stack\": \"AssertionError: expected 2 to deeply equal 1\",\n                \"stacks\": [\n                  {\n                    \"column\": 13,\n                    \"file\": \"<rootDir>/test/cli/fixtures/reporters/json-fail.test.ts\",\n                    \"line\": 8,\n                    \"method\": \"\",\n                  },\n                ],\n              },\n            ],\n            \"repeatCount\": 0,\n            \"retryCount\": 0,\n            \"startTime\": 0,\n            \"state\": \"fail\",\n          },\n          \"tags\": [\n            \"fail\",\n          ],\n          \"timeout\": 5000,\n          \"type\": \"test\",\n        },\n      ],\n      \"type\": \"suite\",\n      \"viteEnvironment\": \"ssr\",\n    },\n  ],\n  \"moduleGraph\": {\n    \"\": {\n      \"<rootDir>/test/cli/fixtures/reporters/json-fail.test.ts\": {\n        \"externalized\": [],\n        \"graph\": {\n          \"<rootDir>/test/cli/fixtures/reporters/json-fail.test.ts\": [],\n        },\n        \"inlined\": [\n          \"<rootDir>/test/cli/fixtures/reporters/json-fail.test.ts\",\n        ],\n      },\n    },\n  },\n  \"paths\": [\n    \"<rootDir>/test/cli/fixtures/reporters/json-fail.test.ts\",\n  ],\n  \"projects\": [\n    \"\",\n  ],\n  \"sources\": {\n    \"<rootDir>/test/cli/fixtures/reporters/json-fail.test.ts\": \"import { expect, test } from 'vitest'\n\n// I am comment1\n// I am comment2\ntest('should fail', { tags: ['fail'] }, () => {\n  // eslint-disable-next-line no-console\n  console.log('json-fail>should fail')\n  expect(2).toEqual(1)\n})\n\",\n  },\n  \"unhandledErrors\": [],\n}\n`;\n\nexports[`html reporter > resolves to \"passing\" status for test file \"all-passing-or-skipped\" > tests are passing 1`] = `\n{\n  \"config\": {},\n  \"files\": [\n    {\n      \"collectDuration\": 0,\n      \"environmentLoad\": 0,\n      \"file\": [Circular],\n      \"filepath\": \"<rootDir>/test/cli/fixtures/reporters/all-passing-or-skipped.test.ts\",\n      \"fullName\": \"all-passing-or-skipped.test.ts\",\n      \"id\": 0,\n      \"importDurations\": {},\n      \"meta\": {},\n      \"mode\": \"run\",\n      \"name\": \"all-passing-or-skipped.test.ts\",\n      \"pool\": \"forks\",\n      \"prepareDuration\": 0,\n      \"projectName\": \"\",\n      \"result\": {\n        \"duration\": 0,\n        \"startTime\": 0,\n        \"state\": \"pass\",\n      },\n      \"setupDuration\": 0,\n      \"tags\": [],\n      \"tasks\": [\n        {\n          \"annotations\": [],\n          \"artifacts\": [],\n          \"file\": [Circular],\n          \"fullName\": \"all-passing-or-skipped.test.ts > 2 + 3 = 5\",\n          \"fullTestName\": \"2 + 3 = 5\",\n          \"id\": 0,\n          \"location\": {\n            \"column\": 1,\n            \"line\": 3,\n          },\n          \"meta\": {},\n          \"mode\": \"run\",\n          \"name\": \"2 + 3 = 5\",\n          \"result\": {\n            \"duration\": 0,\n            \"repeatCount\": 0,\n            \"retryCount\": 0,\n            \"startTime\": 0,\n            \"state\": \"pass\",\n          },\n          \"tags\": [],\n          \"timeout\": 5000,\n          \"type\": \"test\",\n        },\n        {\n          \"annotations\": [],\n          \"artifacts\": [],\n          \"file\": [Circular],\n          \"fullName\": \"all-passing-or-skipped.test.ts > 3 + 3 = 6\",\n          \"fullTestName\": \"3 + 3 = 6\",\n          \"id\": \"1111755131_1\",\n          \"location\": {\n            \"column\": 6,\n            \"line\": 7,\n          },\n          \"meta\": {},\n          \"mode\": \"skip\",\n          \"name\": \"3 + 3 = 6\",\n          \"tags\": [],\n          \"timeout\": 5000,\n          \"type\": \"test\",\n        },\n      ],\n      \"type\": \"suite\",\n      \"viteEnvironment\": \"ssr\",\n    },\n  ],\n  \"moduleGraph\": {\n    \"\": {\n      \"<rootDir>/test/cli/fixtures/reporters/all-passing-or-skipped.test.ts\": {\n        \"externalized\": [],\n        \"graph\": {\n          \"<rootDir>/test/cli/fixtures/reporters/all-passing-or-skipped.test.ts\": [],\n        },\n        \"inlined\": [\n          \"<rootDir>/test/cli/fixtures/reporters/all-passing-or-skipped.test.ts\",\n        ],\n      },\n    },\n  },\n  \"paths\": [\n    \"<rootDir>/test/cli/fixtures/reporters/all-passing-or-skipped.test.ts\",\n  ],\n  \"projects\": [\n    \"\",\n  ],\n  \"sources\": {\n    \"<rootDir>/test/cli/fixtures/reporters/all-passing-or-skipped.test.ts\": \"import { expect, test } from 'vitest'\n\ntest('2 + 3 = 5', () => {\n  expect(2 + 3).toBe(5)\n})\n\ntest.skip('3 + 3 = 6', () => {\n  expect(3 + 3).toBe(6)\n})\n\",\n  },\n  \"unhandledErrors\": [],\n}\n`;\n"
  },
  {
    "path": "test/cli/test/reporters/__snapshots__/json.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`json reporter > generates correct report 1`] = `\n{\n  \"ancestorTitles\": [],\n  \"failureMessages\": [\n    \"AssertionError: expected 2 to deeply equal 1\n    at <root>/test/cli/fixtures/reporters/json-fail.test.ts:8:13\",\n  ],\n  \"fullName\": \"should fail\",\n  \"location\": {\n    \"column\": 1,\n    \"line\": 5,\n  },\n  \"meta\": {},\n  \"status\": \"failed\",\n  \"tags\": [\n    \"fail\",\n  ],\n  \"title\": \"should fail\",\n}\n`;\n"
  },
  {
    "path": "test/cli/test/reporters/__snapshots__/junit.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`addFileAttribute false 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"...\">\n    <testsuite name=\"ok.test.ts\" timestamp=\"...\" hostname=\"...\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"...\">\n        <testcase classname=\"ok.test.ts\" name=\"ok\" time=\"...\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`addFileAttribute true 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"...\">\n    <testsuite name=\"ok.test.ts\" timestamp=\"...\" hostname=\"...\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"...\">\n        <testcase classname=\"ok.test.ts\" file=\"ok.test.ts\" name=\"ok\" time=\"...\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`emits <failure> when beforeAll/afterAll failed 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"8\" failures=\"2\" errors=\"0\" time=\"...\">\n    <testsuite name=\"basic.test.ts\" timestamp=\"...\" hostname=\"...\" tests=\"8\" failures=\"2\" errors=\"0\" skipped=\"4\" time=\"...\">\n        <testcase classname=\"basic.test.ts\" name=\"suite with beforeAll &gt; ok 1\" time=\"...\">\n            <skipped/>\n        </testcase>\n        <testcase classname=\"basic.test.ts\" name=\"suite with beforeAll &gt; ok 2\" time=\"...\">\n            <skipped/>\n        </testcase>\n        <testcase classname=\"basic.test.ts\" name=\"suite with beforeAll &gt; skip 1\" time=\"...\">\n            <skipped/>\n        </testcase>\n        <testcase classname=\"basic.test.ts\" name=\"suite with afterAll &gt; ok 1\" time=\"...\">\n        </testcase>\n        <testcase classname=\"basic.test.ts\" name=\"suite with afterAll &gt; ok 2\" time=\"...\">\n        </testcase>\n        <testcase classname=\"basic.test.ts\" name=\"suite with afterAll &gt; skip 1\" time=\"...\">\n            <skipped/>\n        </testcase>\n        <testcase classname=\"basic.test.ts\" name=\"suite with beforeAll\" time=\"...\">\n            <failure message=\"beforeAll error\" type=\"Error\">\nError: beforeAll error\n ❯ basic.test.ts:10:11\n            </failure>\n        </testcase>\n        <testcase classname=\"basic.test.ts\" name=\"suite with afterAll\" time=\"...\">\n            <failure message=\"afterAll error\" type=\"Error\">\nError: afterAll error\n ❯ basic.test.ts:20:11\n            </failure>\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`format error 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"9\" failures=\"8\" errors=\"0\" time=\"...\">\n    <testsuite name=\"error.test.ts\" timestamp=\"...\" hostname=\"...\" tests=\"9\" failures=\"8\" errors=\"0\" skipped=\"0\" time=\"...\">\n        <testcase classname=\"error.test.ts\" name=\"stack\" time=\"...\">\n            <failure message=\"throwSimple\" type=\"Error\">\nError: throwSimple\n ❯ throwSimple error.test.ts:44:9\n ❯ throwDeep error.test.ts:40:3\n ❯ error.test.ts:8:3\n            </failure>\n        </testcase>\n        <testcase classname=\"error.test.ts\" name=\"diff\" time=\"...\">\n            <failure message=\"expected { hello: &apos;x&apos; } to deeply equal { hello: &apos;y&apos; }\" type=\"AssertionError\">\nAssertionError: expected { hello: &apos;x&apos; } to deeply equal { hello: &apos;y&apos; }\n\n- Expected\n+ Received\n\n  {\n-   &quot;hello&quot;: &quot;y&quot;,\n+   &quot;hello&quot;: &quot;x&quot;,\n  }\n\n ❯ error.test.ts:12:26\n            </failure>\n        </testcase>\n        <testcase classname=\"error.test.ts\" name=\"unhandled\" time=\"...\">\n        </testcase>\n        <testcase classname=\"error.test.ts\" name=\"no name object\" time=\"...\">\n            <failure>\n{ noName: &apos;hi&apos;, stacks: [] }\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\nSerialized Error: { noName: &apos;hi&apos; }\n            </failure>\n        </testcase>\n        <testcase classname=\"error.test.ts\" name=\"string\" time=\"...\">\n            <failure message=\"hi\">\nUnknown Error: hi\n            </failure>\n        </testcase>\n        <testcase classname=\"error.test.ts\" name=\"number\" time=\"...\">\n            <failure message=\"1234\">\nUnknown Error: 1234\n            </failure>\n        </testcase>\n        <testcase classname=\"error.test.ts\" name=\"number name object\" time=\"...\">\n            <failure type=\"1234\">\n{ name: 1234, stacks: [] }\n            </failure>\n        </testcase>\n        <testcase classname=\"error.test.ts\" name=\"xml\" time=\"...\">\n            <failure message=\"error message that has XML in it &lt;div&gt;&lt;input/&gt;&lt;/div&gt;\" type=\"Error\">\nError: error message that has XML in it &lt;div&gt;&lt;input/&gt;&lt;/div&gt;\n ❯ error.test.ts:36:9\n            </failure>\n        </testcase>\n        <testcase classname=\"error.test.ts\" name=\"error.test.ts\" time=\"...\">\n            <failure message=\"throwSuite\" type=\"Error\">\nError: throwSuite\n ❯ throwSuite error.test.ts:48:9\n ❯ error.test.ts:4:3\n            </failure>\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`includeConsoleOutput false 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"...\">\n    <testsuite name=\"console-simple.test.ts\" timestamp=\"...\" hostname=\"...\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"...\">\n        <testcase classname=\"console-simple.test.ts\" name=\"test\" time=\"...\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`includeConsoleOutput true 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"...\">\n    <testsuite name=\"console-simple.test.ts\" timestamp=\"...\" hostname=\"...\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"...\">\n        <testcase classname=\"console-simple.test.ts\" name=\"test\" time=\"...\">\n            <system-out>\n__test_stdout__\n\n            </system-out>\n            <system-err>\n__test_stderr__\n\n            </system-err>\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n"
  },
  {
    "path": "test/cli/test/reporters/__snapshots__/reporters.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`JUnit reporter (no outputFile entry) 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with custom function classnameTemplate 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.145992842\">\n    <testsuite name=\"test/core/test/basic.test.ts\" timestamp=\"2022-01-19T10:10:01.759Z\" hostname=\"hostname\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0.145992842\">\n        <testcase classname=\"filename:basic.test.ts - filepath:/vitest/test/core/test/basic.test.ts\" name=\"Math.sqrt()\" time=\"0.001442286\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with custom string classname 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.145992842\">\n    <testsuite name=\"test/core/test/basic.test.ts\" timestamp=\"2022-01-19T10:10:01.759Z\" hostname=\"hostname\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0.145992842\">\n        <testcase classname=\"my-custom-classname\" name=\"Math.sqrt()\" time=\"0.001442286\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with custom string classnameTemplate 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.145992842\">\n    <testsuite name=\"test/core/test/basic.test.ts\" timestamp=\"2022-01-19T10:10:01.759Z\" hostname=\"hostname\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0.145992842\">\n        <testcase classname=\"filename:basic.test.ts - filepath:/vitest/test/core/test/basic.test.ts\" name=\"Math.sqrt()\" time=\"0.001442286\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with outputFile 1`] = `\n\"JUNIT report written to <process-cwd>/report.xml\n\"\n`;\n\nexports[`JUnit reporter with outputFile 2`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with outputFile in non-existing directory 1`] = `\n\"JUNIT report written to <process-cwd>/junitReportDirectory/deeply/nested/report.xml\n\"\n`;\n\nexports[`JUnit reporter with outputFile in non-existing directory 2`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with outputFile object 1`] = `\n\"JUNIT report written to <process-cwd>/report_object.xml\n\"\n`;\n\nexports[`JUnit reporter with outputFile object 2`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with outputFile object in non-existing directory 1`] = `\n\"JUNIT report written to <process-cwd>/junitReportDirectory_object/deeply/nested/report.xml\n\"\n`;\n\nexports[`JUnit reporter with outputFile object in non-existing directory 2`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter without classname 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.145992842\">\n    <testsuite name=\"test/core/test/basic.test.ts\" timestamp=\"2022-01-19T10:10:01.759Z\" hostname=\"hostname\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0.145992842\">\n        <testcase classname=\"test/core/test/basic.test.ts\" name=\"Math.sqrt()\" time=\"0.001442286\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`json reporter (no outputFile entry) 1`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter 1`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter with outputFile 1`] = `\n\"JSON report written to <process-cwd>/report.json\n\"\n`;\n\nexports[`json reporter with outputFile 2`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter with outputFile in non-existing directory 1`] = `\n\"JSON report written to <process-cwd>/jsonReportDirectory/deeply/nested/report.json\n\"\n`;\n\nexports[`json reporter with outputFile in non-existing directory 2`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter with outputFile object 1`] = `\n\"JSON report written to <process-cwd>/report_object.json\n\"\n`;\n\nexports[`json reporter with outputFile object 2`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter with outputFile object in non-existing directory 1`] = `\n\"JSON report written to <process-cwd>/jsonReportDirectory_object/deeply/nested/report.json\n\"\n`;\n\nexports[`json reporter with outputFile object in non-existing directory 2`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`tap reporter 1`] = `\n\"TAP version 13\n1..1\nnot ok 1 - basic.test.ts # time=145.99ms {\n    1..1\n    ok 1 - suite # time=1.90ms {\n        1..9\n        not ok 1 - Math.sqrt() # time=1.44ms\n            ---\n            error:\n                name: \"AssertionError\"\n                message: \"expected 2.23606797749979 to equal 2\"\n            at: \"/vitest/test/core/test/basic.test.ts:8:32\"\n            actual: \"2.23606797749979\"\n            expected: \"2\"\n            ...\n        ok 2 - JSON # time=1.02ms\n        ok 3 - async with timeout # SKIP\n        ok 4 - timeout # time=100.51ms\n        ok 5 - callback setup success  # time=20.18ms\n        ok 6 - callback test success  # time=0.33ms\n        ok 7 - callback setup success done(false) # time=19.74ms\n        ok 8 - callback test success done(false) # time=0.19ms\n        ok 9 - todo test # TODO\n    }\n}\n\"\n`;\n\nexports[`tap-flat reporter 1`] = `\n\"TAP version 13\n1..9\nnot ok 1 - basic.test.ts > suite > Math.sqrt() # time=1.44ms\n    ---\n    error:\n        name: \"AssertionError\"\n        message: \"expected 2.23606797749979 to equal 2\"\n    at: \"/vitest/test/core/test/basic.test.ts:8:32\"\n    actual: \"2.23606797749979\"\n    expected: \"2\"\n    ...\nok 2 - basic.test.ts > suite > JSON # time=1.02ms\nok 3 - basic.test.ts > suite > async with timeout # SKIP\nok 4 - basic.test.ts > suite > timeout # time=100.51ms\nok 5 - basic.test.ts > suite > callback setup success  # time=20.18ms\nok 6 - basic.test.ts > suite > callback test success  # time=0.33ms\nok 7 - basic.test.ts > suite > callback setup success done(false) # time=19.74ms\nok 8 - basic.test.ts > suite > callback test success done(false) # time=0.19ms\nok 9 - basic.test.ts > suite > todo test # TODO\n\"\n`;\n"
  },
  {
    "path": "test/cli/test/reporters/__snapshots__/reporters.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`JUnit reporter (no outputFile entry) 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with custom function classnameTemplate 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.145992842\">\n    <testsuite name=\"test/core/test/basic.test.ts\" timestamp=\"2022-01-19T10:10:01.759Z\" hostname=\"hostname\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0.145992842\">\n        <testcase classname=\"filename:basic.test.ts - filepath:/vitest/test/core/test/basic.test.ts\" name=\"Math.sqrt()\" time=\"0.001442286\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with custom string classname 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.145992842\">\n    <testsuite name=\"test/core/test/basic.test.ts\" timestamp=\"2022-01-19T10:10:01.759Z\" hostname=\"hostname\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0.145992842\">\n        <testcase classname=\"my-custom-classname\" name=\"Math.sqrt()\" time=\"0.001442286\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with custom string classnameTemplate 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.145992842\">\n    <testsuite name=\"test/core/test/basic.test.ts\" timestamp=\"2022-01-19T10:10:01.759Z\" hostname=\"hostname\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0.145992842\">\n        <testcase classname=\"filename:basic.test.ts - filepath:/vitest/test/core/test/basic.test.ts\" name=\"Math.sqrt()\" time=\"0.001442286\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with outputFile 1`] = `\n\"JUNIT report written to <process-cwd>/report.xml\n\"\n`;\n\nexports[`JUnit reporter with outputFile 2`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with outputFile in non-existing directory 1`] = `\n\"JUNIT report written to <process-cwd>/junitReportDirectory/deeply/nested/report.xml\n\"\n`;\n\nexports[`JUnit reporter with outputFile in non-existing directory 2`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with outputFile object 1`] = `\n\"JUNIT report written to <process-cwd>/report_object.xml\n\"\n`;\n\nexports[`JUnit reporter with outputFile object 2`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter with outputFile object in non-existing directory 1`] = `\n\"JUNIT report written to <process-cwd>/junitReportDirectory_object/deeply/nested/report.xml\n\"\n`;\n\nexports[`JUnit reporter with outputFile object in non-existing directory 2`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"0\" failures=\"0\" errors=\"0\" time=\"0\">\n</testsuites>\n\"\n`;\n\nexports[`JUnit reporter without classname 1`] = `\n\"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<testsuites name=\"vitest tests\" tests=\"1\" failures=\"0\" errors=\"0\" time=\"0.145992842\">\n    <testsuite name=\"test/core/test/basic.test.ts\" timestamp=\"2022-01-19T10:10:01.759Z\" hostname=\"hostname\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"0.145992842\">\n        <testcase classname=\"test/core/test/basic.test.ts\" name=\"Math.sqrt()\" time=\"0.001442286\">\n        </testcase>\n    </testsuite>\n</testsuites>\n\"\n`;\n\nexports[`json reporter (no outputFile entry) 1`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"tags\": [],\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"tags\": [],\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"tags\": [],\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter 1`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"tags\": [],\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"tags\": [],\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"tags\": [],\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter with outputFile 1`] = `\n\"JSON report written to <process-cwd>/report.json\n\"\n`;\n\nexports[`json reporter with outputFile 2`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"tags\": [],\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"tags\": [],\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"tags\": [],\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter with outputFile in non-existing directory 1`] = `\n\"JSON report written to <process-cwd>/jsonReportDirectory/deeply/nested/report.json\n\"\n`;\n\nexports[`json reporter with outputFile in non-existing directory 2`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"tags\": [],\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"tags\": [],\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"tags\": [],\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter with outputFile object 1`] = `\n\"JSON report written to <process-cwd>/report_object.json\n\"\n`;\n\nexports[`json reporter with outputFile object 2`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"tags\": [],\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"tags\": [],\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"tags\": [],\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`json reporter with outputFile object in non-existing directory 1`] = `\n\"JSON report written to <process-cwd>/jsonReportDirectory_object/deeply/nested/report.json\n\"\n`;\n\nexports[`json reporter with outputFile object in non-existing directory 2`] = `\n{\n  \"numFailedTestSuites\": 1,\n  \"numFailedTests\": 1,\n  \"numPassedTestSuites\": 1,\n  \"numPassedTests\": 6,\n  \"numPendingTestSuites\": 0,\n  \"numPendingTests\": 1,\n  \"numTodoTests\": 1,\n  \"numTotalTestSuites\": 2,\n  \"numTotalTests\": 9,\n  \"snapshot\": {\n    \"_test\": true,\n    \"added\": 100,\n  },\n  \"startTime\": 1642587001759,\n  \"success\": false,\n  \"testResults\": [\n    {\n      \"assertionResults\": [\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.4422860145568848,\n          \"failureMessages\": [\n            \"AssertionError: expected 2.23606797749979 to equal 2\n    at /vitest/test/core/test/basic.test.ts:8:32\n    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\n    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\n    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\n    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\n    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\n    at async /vitest/packages/vitest/dist/entry.js:1798:7\n    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\n    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\n    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20\",\n          ],\n          \"fullName\": \"suite Math.sqrt()\",\n          \"location\": {\n            \"column\": 32,\n            \"line\": 8,\n          },\n          \"meta\": {},\n          \"status\": \"failed\",\n          \"tags\": [],\n          \"title\": \"Math.sqrt()\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 1.0237109661102295,\n          \"failureMessages\": [],\n          \"fullName\": \"suite JSON\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"JSON\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite async with timeout\",\n          \"meta\": {},\n          \"status\": \"skipped\",\n          \"tags\": [],\n          \"title\": \"async with timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 100.50598406791687,\n          \"failureMessages\": [],\n          \"fullName\": \"suite timeout\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"timeout\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 20.184875011444092,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.33245420455932617,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success \",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success \",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 19.738605976104736,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback setup success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback setup success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"duration\": 0.1923508644104004,\n          \"failureMessages\": [],\n          \"fullName\": \"suite callback test success done(false)\",\n          \"meta\": {},\n          \"status\": \"passed\",\n          \"tags\": [],\n          \"title\": \"callback test success done(false)\",\n        },\n        {\n          \"ancestorTitles\": [\n            \"suite\",\n          ],\n          \"failureMessages\": [],\n          \"fullName\": \"suite todo test\",\n          \"meta\": {},\n          \"status\": \"todo\",\n          \"tags\": [],\n          \"title\": \"todo test\",\n        },\n      ],\n      \"endTime\": 1642587001759,\n      \"message\": \"\",\n      \"name\": \"/vitest/test/core/test/basic.test.ts\",\n      \"startTime\": 1642587001759,\n      \"status\": \"failed\",\n    },\n  ],\n}\n`;\n\nexports[`tap reporter 1`] = `\n\"TAP version 13\n1..1\nnot ok 1 - basic.test.ts # time=145.99ms {\n    1..1\n    ok 1 - suite # time=1.90ms {\n        1..9\n        not ok 1 - Math.sqrt() # time=1.44ms\n            ---\n            error:\n                name: \"AssertionError\"\n                message: \"expected 2.23606797749979 to equal 2\"\n            at: \"/vitest/test/core/test/basic.test.ts:8:32\"\n            actual: \"2.23606797749979\"\n            expected: \"2\"\n            ...\n        ok 2 - JSON # time=1.02ms\n        ok 3 - async with timeout # SKIP\n        ok 4 - timeout # time=100.51ms\n        ok 5 - callback setup success  # time=20.18ms\n        ok 6 - callback test success  # time=0.33ms\n        ok 7 - callback setup success done(false) # time=19.74ms\n        ok 8 - callback test success done(false) # time=0.19ms\n        ok 9 - todo test # TODO\n    }\n}\n\"\n`;\n\nexports[`tap-flat reporter 1`] = `\n\"TAP version 13\n1..9\nnot ok 1 - basic.test.ts > suite > Math.sqrt() # time=1.44ms\n    ---\n    error:\n        name: \"AssertionError\"\n        message: \"expected 2.23606797749979 to equal 2\"\n    at: \"/vitest/test/core/test/basic.test.ts:8:32\"\n    actual: \"2.23606797749979\"\n    expected: \"2\"\n    ...\nok 2 - basic.test.ts > suite > JSON # time=1.02ms\nok 3 - basic.test.ts > suite > async with timeout # SKIP\nok 4 - basic.test.ts > suite > timeout # time=100.51ms\nok 5 - basic.test.ts > suite > callback setup success  # time=20.18ms\nok 6 - basic.test.ts > suite > callback test success  # time=0.33ms\nok 7 - basic.test.ts > suite > callback setup success done(false) # time=19.74ms\nok 8 - basic.test.ts > suite > callback test success done(false) # time=0.19ms\nok 9 - basic.test.ts > suite > todo test # TODO\n\"\n`;\n"
  },
  {
    "path": "test/cli/test/reporters/agent.test.ts",
    "content": "import { runVitest, StableTestFileOrderSorter } from '#test-utils'\nimport { describe, expect, test } from 'vitest'\nimport { DefaultReporter } from 'vitest/node'\nimport { trimReporterOutput } from './utils'\n\ndescribe('agent reporter', async () => {\n  test('hides passed module headers, shows only failed tests, and prints end summary', async () => {\n    const { stdout } = await runVitest({\n      include: ['b1.test.ts', 'b2.test.ts'],\n      root: 'fixtures/reporters/default',\n      reporters: [['agent', {}]],\n      fileParallelism: false,\n      sequence: {\n        sequencer: StableTestFileOrderSorter,\n      },\n    })\n\n    const output = trimReporterOutput(stdout)\n    expect(output).toMatchInlineSnapshot(`\n      \"❯ b1.test.ts (13 tests | 1 failed) [...]ms\n           × b failed test [...]ms\n       ❯ b2.test.ts (13 tests | 1 failed) [...]ms\n           × b failed test [...]ms\"\n    `)\n\n    const summary = stdout.replace(/\\d+ms/g, '[...]ms').split('\\n').filter(line => /Test Files|^\\s*Tests\\b/.test(line)).map(line => line.trim()).join('\\n')\n    expect(summary).toMatchInlineSnapshot(`\n      \"Test Files  2 failed (2)\n      Tests  2 failed | 24 passed (26)\"\n    `)\n  })\n\n  test('hides all output for passed-only modules', async () => {\n    const { stdout } = await runVitest({\n      include: ['b1.test.ts', 'b2.test.ts'],\n      root: 'fixtures/reporters/default',\n      reporters: [['agent', {}]],\n      fileParallelism: false,\n      testNamePattern: 'passed',\n      sequence: {\n        sequencer: StableTestFileOrderSorter,\n      },\n    })\n\n    const output = trimReporterOutput(stdout)\n    expect(output).toMatchInlineSnapshot(`\"\"`)\n  })\n\n  test('shows console logs only from failed file, suite, and tests', async () => {\n    const { stdout } = await runVitest({\n      config: false,\n      include: ['./fixtures/reporters/console-some-failing.test.ts'],\n      reporters: [['agent', { isTTY: true }]],\n    })\n\n    const logs = stdout.split('\\n').filter(line => line.includes('Log from')).join('\\n')\n    expect(logs).toMatchInlineSnapshot(`\n      \"Log from failed test\n      Log from failed test\n      Log from failed suite\n      Log from failed file\"\n    `)\n  })\n\n  test('does not change silent behavior for other reporters', async () => {\n    const { stdout } = await runVitest({\n      config: false,\n      include: ['./fixtures/reporters/console-some-failing.test.ts'],\n      reporters: [new LogReporter(), ['agent', { isTTY: true }]],\n    })\n\n    const logs = stdout.split('\\n').filter(line => line.includes('Log from')).join('\\n')\n    expect(logs).toMatchInlineSnapshot(`\n      \"Log from failed file\n      Log from passed test\n      Log from failed test\n      Log from failed suite\n      Log from passed test\n      Log from failed test\n      Log from passed suite\n      Log from passed test\n      Log from failed test\n      Log from failed test\n      Log from failed suite\n      Log from failed file\"\n    `)\n  })\n}, 120000)\n\nclass LogReporter extends DefaultReporter {\n  isTTY = true\n}\n"
  },
  {
    "path": "test/cli/test/reporters/code-frame-line-limit.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { expect, test } from 'vitest'\n\ntest('show code frame', async () => {\n  const filename = resolve('./fixtures/reporters/code-frame-line-limit.test.ts')\n  const { stderr } = await runVitest({ root: './fixtures/reporters' }, [filename])\n  expect(stderr).toContain('5|   expect([{ prop: 7 },')\n})\n"
  },
  {
    "path": "test/cli/test/reporters/configuration-options.test-d.ts",
    "content": "import type { defineConfig } from 'vitest/config'\nimport { assertType, test } from 'vitest'\n\ntype NarrowToTestConfig<T> = T extends { test?: any } ? NonNullable<T['test']> : never\ntype Configuration = NonNullable<NarrowToTestConfig<(Parameters<typeof defineConfig>[0])>>\n\ntest('reporters, single', () => {\n  assertType<Configuration>({ reporters: 'default' })\n  assertType<Configuration>({ reporters: 'dot' })\n  assertType<Configuration>({ reporters: 'hanging-process' })\n  assertType<Configuration>({ reporters: 'html' })\n  assertType<Configuration>({ reporters: 'json' })\n  assertType<Configuration>({ reporters: 'junit' })\n  assertType<Configuration>({ reporters: 'tap' })\n  assertType<Configuration>({ reporters: 'tap-flat' })\n  assertType<Configuration>({ reporters: 'verbose' })\n\n  assertType<Configuration>({ reporters: 'custom-reporter' })\n  assertType<Configuration>({ reporters: './reporter.mjs' })\n  assertType<Configuration>({ reporters: { onTestRunEnd() {} } })\n})\n\ntest('reporters, multiple', () => {\n  assertType<Configuration>({\n    reporters: [\n      'default',\n      'dot',\n      'hanging-process',\n      'html',\n      'json',\n      'junit',\n      'tap',\n      'tap-flat',\n      'verbose',\n    ],\n  })\n  assertType<Configuration>({ reporters: ['custom-reporter'] })\n  assertType<Configuration>({ reporters: ['html', 'json', 'custom-reporter'] })\n})\n\ntest('reporters, with options', () => {\n  assertType<Configuration>({\n    reporters: [\n      ['json', { outputFile: 'test.json' }],\n      ['junit', { classname: 'something', suiteName: 'Suite name', outputFile: 'test.json' }],\n      ['vitest-sonar-reporter', { outputFile: 'report.xml' }],\n    ],\n  })\n})\n\ntest('reporters, mixed variations', () => {\n  assertType<Configuration>({\n    reporters: [\n      'default',\n      ['verbose'],\n      ['json', { outputFile: 'test.json' }],\n    ],\n  })\n})\n"
  },
  {
    "path": "test/cli/test/reporters/console.test.ts",
    "content": "import type { UserConsoleLog } from 'vitest'\nimport type { Reporter } from 'vitest/node'\nimport { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { expect, test } from 'vitest'\nimport { DefaultReporter } from 'vitest/node'\n\nclass LogReporter extends DefaultReporter {\n  isTTY = true\n}\n\ntest('should print logs correctly', async () => {\n  const filename = resolve('./fixtures/reporters/console.test.ts')\n\n  const { stdout, stderr } = await runVitest({\n    root: './fixtures/reporters',\n    reporters: [new LogReporter() as any],\n  }, [filename])\n\n  expect(stdout).toBeTruthy()\n  expect(stderr).toBeTruthy()\n\n  expect(stdout).toContain(\n    `stdout | console.test.ts\nglobal stdin beforeAll\n\nstdout | console.test.ts > suite\nsuite stdin beforeAll\n\nstdout | console.test.ts > suite > nested suite\nnested suite stdin beforeAll`,\n  )\n\n  expect(stdout).toContain(\n    `stdout | console.test.ts > suite > nested suite\nnested suite stdin afterAll\n\nstdout | console.test.ts > suite\nsuite stdin afterAll\n\nstdout | console.test.ts\nglobal stdin afterAll`,\n  )\n\n  expect(stderr).toContain(\n    `stderr | console.test.ts\nglobal stderr beforeAll\n\nstderr | console.test.ts > suite\nsuite stderr beforeAll\n\nstderr | console.test.ts > suite > nested suite\nnested suite stderr beforeAll\n\nstderr | console.test.ts > suite > nested suite\nnested suite stderr afterAll\n\nstderr | console.test.ts > suite\nsuite stderr afterAll\n\nstderr | console.test.ts\nglobal stderr afterAll`,\n  )\n})\n\ntest.for(['forks', 'threads'])('interleave (pool = %s)', async (pool) => {\n  const logs: UserConsoleLog[] = []\n  const { stderr } = await runVitest({\n    root: './fixtures/reporters',\n    pool,\n    reporters: [\n      {\n        onUserConsoleLog(log) {\n          logs.push(log)\n        },\n      } satisfies Reporter,\n    ],\n  }, [resolve('./fixtures/reporters/console-interleave.test.ts')])\n  expect(stderr).toBe('')\n  expect(logs).toMatchObject([\n    {\n      type: 'stdout',\n      content: expect.stringContaining('1'),\n    },\n    {\n      type: 'stderr',\n      content: expect.stringContaining('2'),\n    },\n    {\n      type: 'stdout',\n      content: expect.stringContaining('3'),\n    },\n  ])\n})\n"
  },
  {
    "path": "test/cli/test/reporters/custom-diff-config.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { expect, test } from 'vitest'\n\ntest('custom diff config', async () => {\n  const filename = resolve('./fixtures/reporters/custom-diff-config.test.ts')\n  const diff = resolve('./fixtures/reporters/custom-diff-config.ts')\n  const { stderr } = await runVitest({ root: './fixtures/reporters', diff }, [filename])\n\n  expect(stderr).toBeTruthy()\n  expect(stderr).toContain('Expected to be')\n  expect(stderr).toContain('But got')\n})\n\ntest('invalid diff config file', async () => {\n  const filename = resolve('./fixtures/reporters/custom-diff-config.test.ts')\n  const diff = resolve('./fixtures/reporters/invalid-diff-config.ts')\n  const { stderr } = await runVitest({ root: './fixtures/reporters', diff }, [filename])\n\n  expect(stderr).toBeTruthy()\n  expect(stderr).toContain('invalid diff config file')\n  expect(stderr).toContain('Must have a default export with config object')\n})\n"
  },
  {
    "path": "test/cli/test/reporters/custom-reporter.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { describe, expect, test } from 'vitest'\nimport TestReporter from '../../fixtures/reporters/implementations/custom-reporter'\n\nconst reportersDir = resolve(import.meta.dirname, '../../fixtures/reporters/implementations')\n\ndescribe('custom reporters', () => {\n  test('custom reporter instances works', async () => {\n    const { stdout } = await runVitest({\n      config: false,\n      root: './fixtures/reporters/basic',\n      reporters: [new TestReporter()],\n    })\n    expect(stdout).includes('hello from custom reporter')\n  })\n\n  test('load no base on root custom reporter instances defined in configuration works', async () => {\n    const { stdout, stderr } = await runVitest({\n      config: false,\n      root: './fixtures/reporters/basic',\n      reporters: [\n        resolve(reportersDir, './custom-reporter.ts'),\n      ],\n    })\n    expect(stderr).toBe('')\n    expect(stdout).includes('hello from custom reporter')\n  })\n\n  test('package.json dependencies reporter instances defined in configuration works', async () => {\n    const { stdout } = await runVitest({\n      config: false,\n      root: './fixtures/reporters/basic',\n      reporters: ['@test/pkg-reporter', 'vitest-sonar-reporter'],\n      outputFile: './sonar-config.xml',\n    })\n    expect(stdout).includes('hello from package reporter')\n  })\n\n  test('a path to a custom reporter defined in configuration works', async () => {\n    const { stdout } = await runVitest({\n      root: './fixtures/reporters/basic',\n      config: false,\n      reporters: [\n        resolve(reportersDir, './custom-reporter.js'),\n      ],\n    })\n    expect(stdout).includes('hello from custom reporter')\n  })\n\n  test('overrides reporters by given a CLI argument --reporter works', async () => {\n    const { stdout } = await runVitest({\n      root: './fixtures/reporters/basic',\n      config: './vitest.config.override.js',\n      $cliOptions: {\n        // @ts-expect-error reporter is not defined in types\n        reporter: resolve(reportersDir, './custom-reporter.js'),\n      },\n    })\n    expect(stdout).not.includes('hello from override')\n    expect(stdout).includes('hello from custom reporter')\n  })\n\n  test('custom reporter with options', async () => {\n    const { stdout } = await runVitest({\n      root: './fixtures/reporters/basic',\n      config: false,\n      reporters: [\n        [resolve(reportersDir, './custom-reporter.ts'), { some: { custom: 'option here' } }],\n      ],\n    })\n    expect(stdout).includes('hello from custom reporter')\n    expect(stdout).includes('custom reporter options {\"some\":{\"custom\":\"option here\"}}')\n  })\n})\n"
  },
  {
    "path": "test/cli/test/reporters/default.test.ts",
    "content": "import type { RunnerTask } from 'vitest/node'\nimport { runVitest, runVitestCli, StableTestFileOrderSorter } from '#test-utils'\nimport { describe, expect, test } from 'vitest'\nimport { DefaultReporter } from 'vitest/node'\nimport { trimReporterOutput } from './utils'\n\ndescribe('default reporter', async () => {\n  test('normal', async () => {\n    const { stdout } = await runVitest({\n      include: ['b1.test.ts', 'b2.test.ts'],\n      root: 'fixtures/reporters/default',\n      reporters: ['default'],\n      fileParallelism: false,\n      sequence: {\n        sequencer: StableTestFileOrderSorter,\n      },\n    })\n\n    expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n      \"❯ b1.test.ts (13 tests | 1 failed) [...]ms\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n           × b failed test [...]ms\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\n       ❯ b2.test.ts (13 tests | 1 failed) [...]ms\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n           × b failed test [...]ms\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\"\n    `)\n  })\n\n  test('normal without fails', async () => {\n    const { stdout } = await runVitest({\n      include: ['b1.test.ts', 'b2.test.ts'],\n      root: 'fixtures/reporters/default',\n      reporters: ['default'],\n      fileParallelism: false,\n      testNamePattern: 'passed',\n      sequence: {\n        sequencer: StableTestFileOrderSorter,\n      },\n    })\n\n    expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n      \"✓ b1.test.ts (13 tests | 7 skipped) [...]ms\n       ✓ b2.test.ts (13 tests | 7 skipped) [...]ms\"\n    `)\n  })\n\n  test('show full test suite when only one file', async () => {\n    const { stdout } = await runVitest({\n      include: ['a.test.ts'],\n      root: 'fixtures/reporters/default',\n      reporters: 'none',\n    })\n\n    expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n      \"❯ a.test.ts (16 tests | 1 failed | 3 skipped) [...]ms\n         ✓ a passed (6)\n           ✓ a1 test [...]ms\n           ✓ a2 test [...]ms\n           ✓ a3 test [...]ms\n           ✓ nested a (3)\n             ✓ nested a1 test [...]ms\n             ✓ nested a2 test [...]ms\n             ✓ nested a3 test [...]ms\n         ❯ a failed (7)\n           ✓ a failed 1 test [...]ms\n           ✓ a failed 2 test [...]ms\n           ✓ a failed 3 test [...]ms\n           × a failed test [...]ms\n           ✓ nested a failed (3)\n             ✓ nested a failed 1 test [...]ms\n             ✓ nested a failed 2 test [...]ms\n             ✓ nested a failed 3 test [...]ms\n         ✓ a skipped (3)\n           ↓ skipped with note [...]ms [reason]\n           ↓ condition [...]ms\n           ↓ condition with note [...]ms [note]\"\n    `)\n  })\n\n  test('rerun should undo', async () => {\n    const { vitest } = await runVitest({\n      root: 'fixtures/reporters/default',\n      watch: true,\n      testNamePattern: 'passed',\n      reporters: 'none',\n    })\n\n    // one file\n    vitest.write('p')\n    await vitest.waitForStdout('Input filename pattern')\n    vitest.write('a')\n    await vitest.waitForStdout('a.test.ts')\n    vitest.write('\\n')\n    await vitest.waitForStdout('Filename pattern: a')\n    await vitest.waitForStdout('Waiting for file changes...')\n\n    expect(vitest.stdout).toContain('✓ a passed')\n    expect(vitest.stdout).toContain('✓ a1 test')\n    expect(vitest.stdout).toContain('✓ nested a')\n    expect(vitest.stdout).toContain('✓ nested a3 test')\n\n    // rerun and two files\n    vitest.write('p')\n    await vitest.waitForStdout('Input filename pattern')\n    vitest.write('b\\n')\n    await vitest.waitForStdout('Waiting for file changes...')\n    expect(vitest.stdout).toContain('✓ b1.test.ts')\n    expect(vitest.stdout).toContain('✓ b2.test.ts')\n    expect(vitest.stdout).not.toContain('✓ b2 failed')\n  })\n\n  test('doesn\\'t print error properties', async () => {\n    const result = await runVitest({\n      root: 'fixtures/reporters/error-props',\n      reporters: 'default',\n      env: { CI: '1' },\n    })\n\n    expect(result.stderr).not.toContain(`Serialized Error`)\n    expect(result.stderr).not.toContain(`status: 'not found'`)\n  })\n\n  test('prints queued tests as soon as they are added', async () => {\n    const { stdout, vitest } = await runVitest({\n      include: ['fixtures/reporters/long-loading-task.test.ts'],\n      reporters: [['default', { isTTY: true, summary: true }]],\n      config: 'fixtures/reporters/vitest.config.ts',\n      watch: true,\n    })\n\n    await vitest.waitForStdout('❯ fixtures/reporters/long-loading-task.test.ts [queued]')\n    await vitest.waitForStdout('Waiting for file changes...')\n\n    expect(stdout).toContain('✓ fixtures/reporters/long-loading-task.test.ts (1 test)')\n  })\n\n  test('prints skipped tests by default when a single file is run', async () => {\n    const { stdout } = await runVitest({\n      include: ['fixtures/reporters/pass-and-skip-test-suites.test.ts'],\n      reporters: [['default', { isTTY: true, summary: false }]],\n      config: 'fixtures/reporters/vitest.config.ts',\n    })\n\n    expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n      \"✓ fixtures/reporters/pass-and-skip-test-suites.test.ts (5 tests | 2 skipped | 1 todo) [...]ms\n         ✓ passing test #1 [...]ms\n         ✓ passing suite (1)\n           ✓ passing test #2 [...]ms\n         ↓ skipped test #1\n         □ todo test #1\n         ↓ skipped suite (1)\n           ↓ skipped test #2\"\n    `)\n  })\n\n  test('hides skipped tests when --hideSkippedTests and a single file is run', async () => {\n    const { stdout } = await runVitest({\n      include: ['fixtures/reporters/pass-and-skip-test-suites.test.ts'],\n      reporters: [['default', { isTTY: true, summary: false }]],\n      hideSkippedTests: true,\n      config: false,\n    })\n\n    expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n      \"✓ fixtures/reporters/pass-and-skip-test-suites.test.ts (5 tests | 2 skipped | 1 todo) [...]ms\n         ✓ passing test #1 [...]ms\n         ✓ passing suite (1)\n           ✓ passing test #2 [...]ms\n         □ todo test #1\"\n    `)\n  })\n\n  test('prints retry count', async () => {\n    const { stdout } = await runVitest({\n      include: ['fixtures/reporters/retry.test.ts'],\n      reporters: [['default', { isTTY: true, summary: false }]],\n      retry: 3,\n      config: false,\n    })\n\n    expect(stdout).toContain('1 passed')\n    expect(trimReporterOutput(stdout)).toContain('✓ pass after retries [...]ms (retry x3)')\n  })\n\n  test('prints repeat count', async () => {\n    const { stdout } = await runVitest({\n      include: ['fixtures/reporters/repeats.test.ts'],\n      reporters: [['default', { isTTY: true, summary: false }]],\n      config: false,\n    })\n\n    expect(stdout).toContain('1 passed')\n    expect(trimReporterOutput(stdout)).toContain('✓ repeat couple of times [...]ms (repeat x3)')\n  })\n\n  test('prints 0-based index and 1-based index of the test case', async () => {\n    const { stdout } = await runVitest({\n      include: ['print-index.test.ts'],\n      root: 'fixtures/reporters/default',\n      reporters: 'none',\n    })\n\n    expect(stdout).toContain('✓ 0-based index of the test case is 0')\n    expect(stdout).toContain('✓ 0-based index of the test case is 1')\n    expect(stdout).toContain('✓ 0-based index of the test case is 2')\n\n    expect(stdout).toContain('✓ 1-based index of the test case is 1')\n    expect(stdout).toContain('✓ 1-based index of the test case is 2')\n    expect(stdout).toContain('✓ 1-based index of the test case is 3')\n  })\n\n  test('test.each/for title format', async () => {\n    const { stdout } = await runVitest({\n      include: ['fixtures/reporters/test-for-title.test.ts'],\n      reporters: [['default', { isTTY: true, summary: false }]],\n      config: false,\n    })\n\n    expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n      \"✓ fixtures/reporters/test-for-title.test.ts (24 tests) [...]ms\n         ✓ test.for object : 0 = 'a', 2 = { te: 'st' } [...]ms\n         ✓ test.for object : 0 = 'b', 2 = [ 'test' ] [...]ms\n         ✓ test.each object : 0 = 'a', 2 = { te: 'st' }  [...]ms\n         ✓ test.each object : 0 = 'b', 2 = [ 'test' ]  [...]ms\n         ✓ test.for array : 0 = 'a', 2 = { te: 'st' } [...]ms\n         ✓ test.for array : 0 = 'b', 2 = [ 'test' ] [...]ms\n         ✓ test.each array : 0 = 'a', 2 = { te: 'st' } [...]ms\n         ✓ test.each array : 0 = 'b', 2 = [ 'test' ] [...]ms\n         ✓ object : add(1, 1) -> 2 [...]ms\n         ✓ object : add(1, 2) -> 3 [...]ms\n         ✓ object : add(2, 1) -> 3 [...]ms\n         ✓ array : add(1, 1) -> 2 [...]ms\n         ✓ array : add(1, 2) -> 3 [...]ms\n         ✓ array : add(2, 1) -> 3 [...]ms\n         ✓ first array element is object: 0 = { k1: 'v1' }, 1 = { k2: 'v2' }, k1 = 'v1', k2 = undefined [...]ms\n         ✓ first array element is not object: 0 = 'foo', 1 = 'bar', k = $k [...]ms\n         ✓ not array: 0 = { k: 'v1' }, 1 = undefined, k = 'v1' [...]ms\n         ✓ not array: 0 = { k: 'v2' }, 1 = undefined, k = 'v2' [...]ms\n         ✓ handles whole numbers: 343434 as $343,434.00 [...]ms\n         ✓ { a: '$b', b: 'yay' } [...]ms\n         ✓ '%o' [...]ms\n         ✓ { a: '%o' } [...]ms\n         ✓ '%o' { a: '%o' } [...]ms\n         ✓ { a: '%o' } '%o' [...]ms\"\n    `)\n  })\n\n  test('project name color', async () => {\n    const { stdout } = await runVitestCli(\n      { preserveAnsi: true },\n      '--root',\n      'fixtures/reporters/project-name',\n    )\n\n    expect(stdout).toContain('Example project')\n    expect(stdout).toContain('\\x1B[30m\\x1B[45m Example project \\x1B[49m\\x1B[39m')\n  })\n\n  test('extended reporter can override getFullName', async () => {\n    class Custom extends DefaultReporter {\n      getFullName(test: RunnerTask, separator?: string): string {\n        return `${separator}{ name: ${test.name}, meta: ${test.meta.custom} } (Custom getFullName here)`\n      }\n    }\n\n    const { stderr } = await runVitest({\n      root: 'fixtures/reporters/metadata',\n      reporters: new Custom(),\n    })\n\n    expect(stderr).toMatch('FAIL   > { name: fails, meta: Failing test added this } (Custom getFullName here')\n  })\n\n  test('merge identical errors', async () => {\n    const { stderr } = await runVitest({\n      root: 'fixtures/reporters/merge-errors',\n      reporters: [['default', { isTTY: true, summary: false }]],\n      config: false,\n    })\n    expect(stderr).toMatchSnapshot()\n  })\n}, 120000)\n"
  },
  {
    "path": "test/cli/test/reporters/dot.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { describe, expect, test } from 'vitest'\n\ndescribe.each([true, false])('{ isTTY: %s }', (isTTY) => {\n  test('renders successful tests', async () => {\n    const { stdout, stderr } = await runVitest({\n      root: './fixtures/reporters',\n      include: ['./ok.test.ts'],\n      reporters: [['dot', { isTTY }]],\n    })\n\n    expect(stdout).toContain('\\n·\\n')\n    expect(stdout).toContain('Test Files  1 passed (1)')\n\n    expect(stderr).toBe('')\n  })\n\n  test('renders failing tests', async () => {\n    const { stdout, stderr } = await runVitest({\n      root: './fixtures/reporters',\n      include: ['./some-failing.test.ts'],\n      reporters: [['dot', { isTTY }]],\n    })\n\n    expect(stdout).toContain('\\n·x\\n')\n    expect(stdout).toContain('Test Files  1 failed (1)')\n    expect(stdout).toContain('Tests  1 failed | 1 passed')\n\n    expect(stderr).toContain('AssertionError: expected 6 to be 7 // Object.is equality')\n  })\n\n  test('renders skipped tests', async () => {\n    const { stdout, stderr } = await runVitest({\n      root: './fixtures/reporters',\n      include: ['./all-skipped.test.ts'],\n      reporters: [['dot', { isTTY }]],\n    })\n\n    expect(stdout).toContain('\\n--\\n')\n    expect(stdout).toContain('Test Files  1 skipped (1)')\n    expect(stdout).toContain('Tests  1 skipped | 1 todo')\n\n    expect(stderr).toContain('')\n  })\n})\n"
  },
  {
    "path": "test/cli/test/reporters/error-to-json.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest('should print logs correctly', async () => {\n  const result = await runVitest({ root: './fixtures/reporters' }, ['error-to-json.test.ts'])\n  expect(result.stderr).toContain(`Serialized Error: { date: '1970-01-01T00:00:00.000Z' }`)\n})\n"
  },
  {
    "path": "test/cli/test/reporters/function-as-name.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { expect, test } from 'vitest'\n\ntest('should print function name', async () => {\n  const filename = resolve('./fixtures/reporters/function-as-name.test.ts')\n  const { stdout } = await runVitest({ root: './fixtures/reporters' }, [filename])\n\n  expect(stdout).toBeTruthy()\n  expect(stdout).toContain('function-as-name.test.ts > foo > Bar')\n  expect(stdout).toContain('function-as-name.test.ts > Bar > foo')\n  expect(stdout).toContain('function-as-name.test.ts > <anonymous> > foo')\n  expect(stdout).toContain('function-as-name.test.ts > foo > <anonymous>')\n  expect(stdout).toContain('function-as-name.test.ts > foo > foo')\n  expect(stdout).toContain('function-as-name.test.ts > Bar > Bar')\n})\n\ntest('should print function name in benchmark', async () => {\n  const filename = resolve('./fixtures/reporters/function-as-name.bench.ts')\n  const { stdout } = await runVitest({ root: './fixtures/reporters' }, [filename], { mode: 'benchmark' })\n\n  expect(stdout).toBeTruthy()\n  expect(stdout).toContain('Bar')\n  expect(stdout).toContain('foo')\n  expect(stdout).toContain('<anonymous>')\n})\n"
  },
  {
    "path": "test/cli/test/reporters/github-actions.test.ts",
    "content": "import { randomUUID } from 'node:crypto'\nimport { access, readFile, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { sep } from 'node:path'\nimport { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { describe, expect, it } from 'vitest'\nimport { GithubActionsReporter } from 'vitest/node'\n\ndescribe(GithubActionsReporter, () => {\n  it('uses absolute path by default', async () => {\n    let { stdout, stderr } = await runVitest(\n      { reporters: new GithubActionsReporter(), root: './fixtures/reporters', include: ['**/some-failing.test.ts'] },\n    )\n    stdout = stdout.replace(resolve(import.meta.dirname, '../..').replace(/:/g, '%3A'), '__TEST_DIR__')\n    expect(stdout).toMatchInlineSnapshot(`\n    \"\n    ::error file=__TEST_DIR__/fixtures/reporters/some-failing.test.ts,title=some-failing.test.ts > 3 + 3 = 7,line=8,column=17::AssertionError: expected 6 to be 7 // Object.is equality%0A%0A- Expected%0A+ Received%0A%0A- 7%0A+ 6%0A%0A ❯ some-failing.test.ts:8:17%0A%0A\n    \"\n  `)\n    expect(stderr).toBe('')\n  })\n\n  it('prints the project name when there is one', async () => {\n    let { stdout, stderr } = await runVitest(\n      {\n        name: 'test-project',\n        reporters: new GithubActionsReporter(),\n        root: './fixtures/reporters',\n        include: ['**/some-failing.test.ts'],\n      },\n    )\n    stdout = stdout.replace(resolve(import.meta.dirname, '../..').replace(/:/g, '%3A'), '__TEST_DIR__')\n    expect(stdout).toMatchInlineSnapshot(`\n      \"\n      ::error file=__TEST_DIR__/fixtures/reporters/some-failing.test.ts,title=[test-project] some-failing.test.ts > 3 + 3 = 7,line=8,column=17::AssertionError: expected 6 to be 7 // Object.is equality%0A%0A- Expected%0A+ Received%0A%0A- 7%0A+ 6%0A%0A ❯ some-failing.test.ts:8:17%0A%0A\n      \"\n    `)\n    expect(stderr).toBe('')\n  })\n\n  it('uses onWritePath to format path', async () => {\n    const { stdout, stderr } = await runVitest(\n      {\n        reporters: new GithubActionsReporter({\n          onWritePath(path) {\n            const normalized = path\n              .replace(resolve(import.meta.dirname, '../..'), '')\n              .replaceAll(sep, '/')\n\n            return `/some-custom-path${normalized}`\n          },\n        }),\n        root: './fixtures/reporters',\n        include: ['**/some-failing.test.ts'],\n      },\n    )\n    expect(stdout).toMatchInlineSnapshot(`\n      \"\n      ::error file=/some-custom-path/fixtures/reporters/some-failing.test.ts,title=some-failing.test.ts > 3 + 3 = 7,line=8,column=17::AssertionError: expected 6 to be 7 // Object.is equality%0A%0A- Expected%0A+ Received%0A%0A- 7%0A+ 6%0A%0A ❯ some-failing.test.ts:8:17%0A%0A\n      \"\n    `)\n    expect(stderr).toBe('')\n  })\n\n  describe('summary', () => {\n    it('writes one when enabled', async ({ onTestFinished }) => {\n      const outputPath = resolve(tmpdir(), randomUUID())\n\n      onTestFinished(async () => {\n        await rm(outputPath).catch(() => {\n          console.error(`Could not remove ${outputPath}`)\n        })\n      })\n\n      const workspacePath = resolve(import.meta.dirname, '..', '..', '..', '..')\n\n      await runVitest({\n        reporters: new GithubActionsReporter({\n          jobSummary: {\n            outputPath,\n            fileLinks: {\n              commitHash: 'aaa',\n              repository: 'owner/repo',\n              workspacePath,\n            },\n          },\n        }),\n        root: './fixtures/reporters/github-actions',\n      })\n\n      const summary = await readFile(outputPath, 'utf8')\n\n      expect(summary).toMatchInlineSnapshot(`\n        \"## Vitest Test Report\n\n        ### Summary\n\n        - **Test Files**: ❌ **1 failure** · ✅ **1 pass** · 2 total\n        - **Test Results**: ❌ **1 failure** · ✅ **9 passes** · 🔵 **1 expected failure** · 11 total\n        - **Other**: 1 skip · 1 todo · 2 total\n\n        ### Flaky Tests\n\n        These tests passed only after one or more retries, indicating potential instability.\n\n        ##### \\`flaky/math.spec.ts\\` (5 flaky tests)\n\n        - [\\`should multiply numbers correctly\\`](https://github.com/owner/repo/blob/aaa/test/cli/fixtures/reporters/github-actions/flaky/math.spec.ts) (**passed on retry 5 out of 5**)\n        - [\\`should handle edge cases\\`](https://github.com/owner/repo/blob/aaa/test/cli/fixtures/reporters/github-actions/flaky/math.spec.ts) (**passed on retry 4 out of 5**)\n        - [\\`should validate input properly\\`](https://github.com/owner/repo/blob/aaa/test/cli/fixtures/reporters/github-actions/flaky/math.spec.ts) (**passed on retry 4 out of 5**)\n        - [\\`should divide numbers correctly\\`](https://github.com/owner/repo/blob/aaa/test/cli/fixtures/reporters/github-actions/flaky/math.spec.ts) (passed on retry 2 out of 5)\n        - [\\`should subtract numbers correctly\\`](https://github.com/owner/repo/blob/aaa/test/cli/fixtures/reporters/github-actions/flaky/math.spec.ts) (passed on retry 1 out of 5)\n\n        ##### \\`flaky/network.spec.ts\\` (3 flaky tests)\n\n        - [\\`network > should handle network timeouts gracefully\\`](https://github.com/owner/repo/blob/aaa/test/cli/fixtures/reporters/github-actions/flaky/network.spec.ts) (**passed on retry 4 out of 4**)\n        - [\\`network > should fetch user data from API\\`](https://github.com/owner/repo/blob/aaa/test/cli/fixtures/reporters/github-actions/flaky/network.spec.ts) (passed on retry 2 out of 3)\n        - [\\`network > should retry failed requests\\`](https://github.com/owner/repo/blob/aaa/test/cli/fixtures/reporters/github-actions/flaky/network.spec.ts) (passed on retry 1 out of 3)\n        \"\n      `)\n    })\n\n    it.for([{ enabled: false }, { outputPath: undefined }] as const)('does not write one when disabled or without `outputPath`', async (options) => {\n      const outputPath = resolve(tmpdir(), randomUUID())\n\n      const workspacePath = resolve(import.meta.dirname, '..', '..', '..', '..')\n\n      await runVitest({\n        reporters: new GithubActionsReporter({\n          jobSummary: {\n            outputPath,\n            ...options,\n            fileLinks: {\n              commitHash: 'aaa',\n              repository: 'owner/repo',\n              workspacePath,\n            },\n          },\n        }),\n        root: './fixtures/reporters/github-actions',\n      })\n\n      const summary = await access(outputPath).then(() => true).catch(() => false)\n\n      expect(summary).toBe(false)\n    })\n\n    it.for([\n      { commitHash: undefined },\n      { repository: undefined },\n      { workspacePath: undefined },\n    ] as const)('writes one without links when one of `commitHash`, `repository` or `workspacePath` are not provided', async (options, { onTestFinished }) => {\n      const outputPath = resolve(tmpdir(), randomUUID())\n\n      onTestFinished(async () => {\n        await rm(outputPath).catch(() => {\n          console.error(`Could not remove ${outputPath}`)\n        })\n      })\n\n      const workspacePath = resolve(import.meta.dirname, '..', '..', '..', '..')\n\n      await runVitest({\n        reporters: new GithubActionsReporter({\n          jobSummary: {\n            outputPath,\n            fileLinks: {\n              commitHash: 'aaa',\n              repository: 'owner/repo',\n              workspacePath,\n              ...options,\n            },\n          },\n        }),\n        root: './fixtures/reporters/github-actions',\n      })\n\n      const summary = await readFile(outputPath, 'utf8')\n\n      expect(summary).toMatchInlineSnapshot(`\n        \"## Vitest Test Report\n\n        ### Summary\n\n        - **Test Files**: ❌ **1 failure** · ✅ **1 pass** · 2 total\n        - **Test Results**: ❌ **1 failure** · ✅ **9 passes** · 🔵 **1 expected failure** · 11 total\n        - **Other**: 1 skip · 1 todo · 2 total\n\n        ### Flaky Tests\n\n        These tests passed only after one or more retries, indicating potential instability.\n\n        ##### \\`flaky/math.spec.ts\\` (5 flaky tests)\n\n        - \\`should multiply numbers correctly\\` (**passed on retry 5 out of 5**)\n        - \\`should handle edge cases\\` (**passed on retry 4 out of 5**)\n        - \\`should validate input properly\\` (**passed on retry 4 out of 5**)\n        - \\`should divide numbers correctly\\` (passed on retry 2 out of 5)\n        - \\`should subtract numbers correctly\\` (passed on retry 1 out of 5)\n\n        ##### \\`flaky/network.spec.ts\\` (3 flaky tests)\n\n        - \\`network > should handle network timeouts gracefully\\` (**passed on retry 4 out of 4**)\n        - \\`network > should fetch user data from API\\` (passed on retry 2 out of 3)\n        - \\`network > should retry failed requests\\` (passed on retry 1 out of 3)\n        \"\n      `)\n    })\n  })\n})\n"
  },
  {
    "path": "test/cli/test/reporters/html.test.ts",
    "content": "import fs from 'node:fs'\nimport zlib from 'node:zlib'\nimport { runInlineTests, runVitest } from '#test-utils'\nimport { playwright } from '@vitest/browser-playwright'\nimport { parse } from 'flatted'\nimport { resolve } from 'pathe'\nimport { describe, expect, it } from 'vitest'\n\ndescribe('html reporter', async () => {\n  const vitestRoot = resolve(import.meta.dirname, '../../../..')\n  const root = resolve(import.meta.dirname, '../../fixtures/reporters')\n\n  it('resolves to \"passing\" status for test file \"all-passing-or-skipped\"', async () => {\n    const basePath = 'html/all-passing-or-skipped'\n\n    const { stderr } = await runVitest(\n      {\n        reporters: 'html',\n        outputFile: `${basePath}/index.html`,\n        root,\n        env: { NO_COLOR: '1' },\n      },\n      ['all-passing-or-skipped'],\n    )\n\n    expect(stderr).toBe('')\n\n    const metaJsonGzipped = fs.readFileSync(resolve(root, `${basePath}/html.meta.json.gz`))\n    const metaJson = zlib.gunzipSync(metaJsonGzipped).toString('utf-8')\n    const indexHtml = fs.readFileSync(resolve(root, `${basePath}/index.html`), { encoding: 'utf-8' })\n    const resultJson = parse(metaJson.replace(new RegExp(vitestRoot, 'g'), '<rootDir>'))\n    resultJson.config = {} // doesn't matter for a test\n    const file = resultJson.files[0]\n    // reset durations and id\n    file.id = 0\n    file.collectDuration = 0\n    file.environmentLoad = 0\n    file.prepareDuration = 0\n    file.setupDuration = 0\n    file.importDurations = {}\n    file.result.duration = 0\n    file.result.startTime = 0\n\n    const task = file.tasks[0]\n    task.id = 0\n    task.result.duration = 0\n    task.result.startTime = 0\n\n    expect(task.result.errors).not.toBeDefined()\n    expect(task.result.logs).not.toBeDefined()\n\n    expect(resultJson).toMatchSnapshot(`tests are passing`)\n    expect(indexHtml).toMatch('window.METADATA_PATH=\"html.meta.json.gz\"')\n  }, 120000)\n\n  it('resolves to \"failing\" status for test file \"json-fail\"', async () => {\n    const basePath = 'html/fail'\n\n    const { stderr } = await runVitest(\n      {\n        reporters: 'html',\n        outputFile: `${basePath}/index.html`,\n        root,\n        env: { NO_COLOR: '1' },\n      },\n      ['json-fail.test'],\n    )\n\n    expect(stderr).toBe('')\n\n    const metaJsonGzipped = fs.readFileSync(resolve(root, `${basePath}/html.meta.json.gz`))\n    const metaJson = zlib.gunzipSync(metaJsonGzipped).toString('utf-8')\n    const indexHtml = fs.readFileSync(resolve(root, `${basePath}/index.html`), { encoding: 'utf-8' })\n    const resultJson = parse(metaJson.replace(new RegExp(vitestRoot, 'g'), '<rootDir>'))\n    resultJson.config = {} // doesn't matter for a test\n    const file = resultJson.files[0]\n    // reset durations and id\n    file.id = 0\n    file.collectDuration = 0\n    file.environmentLoad = 0\n    file.prepareDuration = 0\n    file.setupDuration = 0\n    file.importDurations = {}\n    file.result.duration = 0\n    file.result.startTime = 0\n\n    const task = file.tasks[0]\n    task.id = 0\n    task.result.duration = 0\n    task.result.startTime = 0\n\n    expect(task.result.errors).toBeDefined()\n    task.result.errors[0].stack = task.result.errors[0].stack.split('\\n')[0]\n    expect(task.logs).toBeDefined()\n    expect(task.logs).toHaveLength(1)\n    task.logs[0].taskId = 0\n    task.logs[0].time = 0\n\n    expect(resultJson).toMatchSnapshot(`tests are failing`)\n    expect(indexHtml).toMatch('window.METADATA_PATH=\"html.meta.json.gz\"')\n  }, 120000)\n})\n\nit('browser mode headless', async () => {\n  const result = await runInlineTests({\n    'basic.test.ts': /* ts */`\nimport { test } from \"vitest\";\ntest('basic', () => {});\n`,\n  }, {\n    reporters: ['default', 'html'],\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      headless: true,\n      instances: [\n        { browser: 'chromium' as const },\n      ],\n    },\n  })\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"basic\": \"passed\",\n      },\n    }\n  `)\n  expect(result.fs.statFile('html/index.html').isFile()).toBe(true)\n})\n\nit('html and coverage already next each other', async () => {\n  const result = await runInlineTests({\n    'basic.ts': `\nexport const add = (a: number, b: number) => a + b;\n`,\n    'basic.test.ts': `\nimport { test, expect } from \"vitest\";\nimport { add } from \"./basic\";\ntest('add', () => {\n  expect(add(1, 2)).toBe(3);\n});\n`,\n  }, {\n    reporters: [\n      'default',\n      ['html', { outputFile: './custom-dir/index.html' }],\n    ],\n    coverage: {\n      enabled: true,\n      reporter: ['html'],\n      reportsDirectory: './custom-dir/coverage',\n    },\n  })\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"add\": \"passed\",\n      },\n    }\n  `)\n  expect({\n    html: result.fs.statFile('custom-dir/index.html').isFile(),\n    coverage: result.fs.statFile('custom-dir/coverage/index.html').isFile(),\n  }).toMatchInlineSnapshot(`\n    {\n      \"coverage\": true,\n      \"html\": true,\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/reporters/import-durations.test.ts",
    "content": "import { stripVTControlCharacters } from 'node:util'\nimport { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { describe, expect, it } from 'vitest'\n\n/**\n * Extract import durations section and normalize variable values for snapshot testing.\n * Replaces timing values and bar characters with placeholders.\n */\nfunction normalizeImportDurationsOutput(stdout: string): string {\n  const plain = stripVTControlCharacters(stdout)\n  const start = plain.indexOf('Import Duration Breakdown')\n  const end = plain.indexOf('Total import time (self/total):')\n  if (start === -1 || end === -1) {\n    return ''\n  }\n  const endOfLine = plain.indexOf('\\n', end)\n  const section = plain.slice(start, endOfLine === -1 ? undefined : endOfLine)\n  return section\n    // Normalize time values (e.g., \"88ms\", \"1.01s\") to \"XXX\"\n    // Negative lookahead to avoid matching times in filenames (e.g., \"import-durations-50ms.ts\")\n    .replace(/\\d+(\\.\\d+)?(ms|s)(?![\\w.])/g, 'XXX')\n    // Normalize bar characters to \"[BAR]\"\n    .replace(/[█░]+/g, '[BAR]')\n    // Normalize multiple spaces (from column padding) to single space\n    .replace(/ {2,}/g, ' ')\n}\n\ndescribe('import durations', () => {\n  const root = resolve(import.meta.dirname, '..', '..', 'fixtures', 'reporters')\n\n  it('should populate importDurations on File with import durations during execution', async () => {\n    const { ctx, stderr } = await runVitest({\n      root,\n      include: ['**/import-durations.test.ts'],\n      experimental: { importDurations: { limit: 10 } },\n    })\n\n    expect(stderr).toBe('')\n    expect(ctx?.state.errorsSet).toHaveLength(0)\n\n    const capturedFiles = ctx!.state.getFiles()\n\n    expect(capturedFiles).toHaveLength(1)\n\n    const file = capturedFiles[0]\n\n    expect(file.importDurations).toBeDefined()\n\n    // The main file should be >=75ms because 50ms+25ms\n    expect(file.importDurations?.[file.filepath]?.totalTime).toBeGreaterThanOrEqual(75)\n\n    // The 50ms file imports the 25ms file, so the self time should be >=50ms and the total time should be >=75ms\n    const utilsFile = resolve(root, 'import-durations-50ms.ts')\n\n    expect(file.importDurations?.[utilsFile]?.selfTime).toBeGreaterThanOrEqual(49)\n    expect(file.importDurations?.[utilsFile]?.totalTime).toBeGreaterThanOrEqual(74)\n\n    // The 25ms file should have a self time >25ms and a total time >25ms\n    const helperFile = resolve(root, 'import-durations-25ms.ts')\n\n    expect(file.importDurations?.[helperFile]?.selfTime).toBeGreaterThanOrEqual(24)\n    expect(file.importDurations?.[helperFile]?.totalTime).toBeGreaterThanOrEqual(24)\n  }, 40000)\n\n  it('should handle tests with no imports gracefully', async () => {\n    const { exitCode, ctx } = await runVitest({\n      root,\n      include: ['**/ok.test.ts'],\n      experimental: { importDurations: { limit: 10 } },\n    })\n\n    expect(exitCode).toBe(0)\n\n    const capturedFiles = ctx!.state.getFiles()\n\n    expect(capturedFiles).toHaveLength(1)\n\n    const file = capturedFiles[0]\n    expect(file.importDurations).toBeDefined()\n    expect(file.importDurations?.[file.filepath].totalTime).toBeGreaterThanOrEqual(0)\n    expect(file.importDurations?.[file.filepath].selfTime).toBeGreaterThanOrEqual(0)\n  }, 40000)\n\n  it('should still record times for throwing imports', async () => {\n    const { exitCode, ctx } = await runVitest({\n      root,\n      include: ['**/import-durations-throws.test.ts'],\n      experimental: { importDurations: { limit: 10 } },\n    })\n\n    expect(exitCode).toBe(1)\n\n    const capturedFiles = ctx!.state.getFiles()\n\n    expect(capturedFiles).toHaveLength(1)\n\n    const file = capturedFiles[0]\n\n    const throwsFile = resolve(root, 'import-durations-25ms-throws.ts')\n\n    expect(file.importDurations?.[throwsFile]?.totalTime).toBeGreaterThanOrEqual(24)\n    expect(file.importDurations?.[throwsFile]?.selfTime).toBeGreaterThanOrEqual(24)\n  })\n\n  it('should print import breakdown when print is enabled', async () => {\n    const { stdout } = await runVitest({\n      root,\n      include: ['**/import-durations.test.ts'],\n      experimental: {\n        importDurations: {\n          print: true,\n          limit: 5,\n        },\n      },\n    })\n\n    expect(normalizeImportDurationsOutput(stdout)).toMatchInlineSnapshot(`\n      \"Import Duration Breakdown (Top 5)\n\n      Module Self Total\n      import-durations.test.ts XXX XXX [BAR]\n      import-durations-50ms.ts XXX XXX [BAR]\n      import-durations-25ms.ts XXX XXX [BAR]\n      ../../../../packages/vitest/dist/index.js XXX XXX [BAR]\n\n      Total imports: 4\n      Slowest import (total-time): XXX\n      Total import time (self/total): XXX / XXX\"\n    `)\n  })\n\n  it('should not collect importDurations by default', async () => {\n    const { ctx } = await runVitest({\n      root,\n      include: ['**/import-durations.test.ts'],\n    })\n\n    const file = ctx!.state.getFiles()[0]\n    expect(file.importDurations).toEqual({})\n  })\n\n  it('should print on-warn only when threshold exceeded', async () => {\n    // With high threshold (500ms), should NOT print (imports are ~75-120ms depending on CI)\n    const { stdout: stdoutHigh } = await runVitest({\n      root,\n      include: ['**/import-durations.test.ts'],\n      experimental: {\n        importDurations: {\n          print: 'on-warn',\n          thresholds: { warn: 500 },\n        },\n      },\n    })\n\n    expect(stdoutHigh).not.toContain('Import Duration Breakdown')\n\n    // With lower threshold (50ms), should print (imports are ~75ms > 50ms)\n    const { stdout: stdoutLow } = await runVitest({\n      root,\n      include: ['**/import-durations.test.ts'],\n      experimental: {\n        importDurations: {\n          print: 'on-warn',\n          thresholds: { warn: 50 },\n        },\n      },\n    })\n\n    expect(stdoutLow).toContain('Import Duration Breakdown')\n  })\n\n  it('should fail when failOnDanger is enabled and threshold exceeded', async () => {\n    // With default danger threshold (500ms), should NOT fail (imports are ~75ms)\n    const { exitCode: exitCodeDefault, stderr: stderrDefault } = await runVitest({\n      root,\n      include: ['**/import-durations.test.ts'],\n      experimental: {\n        importDurations: {\n          failOnDanger: true,\n        },\n      },\n    })\n\n    expect(exitCodeDefault).toBe(0)\n    expect(stderrDefault).not.toContain('exceeded the danger threshold')\n\n    // With lower danger threshold (50ms), should fail (imports are ~75ms > 50ms)\n    const { exitCode: exitCodeLow, stderr: stderrLow, stdout: stdoutLow } = await runVitest({\n      root,\n      include: ['**/import-durations.test.ts'],\n      experimental: {\n        importDurations: {\n          failOnDanger: true,\n          thresholds: { danger: 50 },\n        },\n      },\n    })\n\n    expect(exitCodeLow).toBe(1)\n    expect(stderrLow).toContain('exceeded the danger threshold')\n    expect(stdoutLow).toContain('Import Duration Breakdown')\n  })\n})\n"
  },
  {
    "path": "test/cli/test/reporters/indicator-position.test.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { expect, test } from 'vitest'\n\ntest('should print correct indicator position', async () => {\n  const filename = resolve('./fixtures/reporters/indicator-position.test.js')\n  const code = readFileSync(filename, 'utf-8')\n  expect(code).toMatch(/\\r\\n/)\n\n  const { stderr } = await runVitest({ root: './fixtures/reporters' }, [filename])\n\n  expect(stderr).toBeTruthy()\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  indicator-position.test.js > \n    AssertionError: expected 2 to be 3 // Object.is equality\n\n    - Expected\n    + Received\n\n    - 3\n    + 2\n\n     ❯ indicator-position.test.js:12:17\n         10|\n         11| test('', async () => {\n         12|   expect(1 + 1).toBe(3)\n           |                 ^\n         13|   expect(1 + 1).toBe(2)\n         14|   expect(2 + 2).toBe(4)\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/reporters/json.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\n\nimport { describe, expect, it } from 'vitest'\n\ndescribe('json reporter', async () => {\n  const root = resolve(import.meta.dirname, '..', '..', 'fixtures', 'reporters')\n  const projectRoot = resolve(import.meta.dirname, '..', '..', '..', '..')\n\n  it('generates correct report', async () => {\n    const { stdout } = await runVitest({\n      reporters: 'json',\n      root,\n      include: ['**/json-fail-import.test.ts', '**/json-fail.test.ts'],\n      includeTaskLocation: true,\n    }, ['json-fail'])\n\n    const data = JSON.parse(stdout)\n\n    expect(data.testResults).toHaveLength(2)\n\n    const failedImport = data.testResults.find((r: any) => r.name.includes('json-fail-import.test'))!\n    const failedTest = data.testResults.find((r: any) => r.name.includes('json-fail.test'))!\n\n    expect(failedTest.assertionResults).toHaveLength(1)\n    expect(failedImport.assertionResults).toHaveLength(0)\n\n    expect(failedTest.status).toBe('failed')\n    expect(failedImport.status).toBe('failed')\n\n    const result = failedTest.assertionResults[0]\n    delete result.duration\n    const rootRegexp = new RegExp(projectRoot, 'g')\n    result.failureMessages = result.failureMessages\n      .map((m: string) => {\n        const errorStack = m.split('\\n').slice(0, 2).join('\\n')\n        return errorStack.replace(/\\\\/g, '/').replace(rootRegexp, '<root>')\n      })\n    expect(result).toMatchSnapshot()\n  })\n\n  it('generates empty json with success: false', async () => {\n    const { stdout } = await runVitest({\n      reporters: 'json',\n      root,\n      includeTaskLocation: true,\n    }, ['json-non-existing-files'])\n\n    const json = JSON.parse(stdout)\n    json.startTime = 0\n    expect(json).toMatchInlineSnapshot(`\n      {\n        \"numFailedTestSuites\": 0,\n        \"numFailedTests\": 0,\n        \"numPassedTestSuites\": 0,\n        \"numPassedTests\": 0,\n        \"numPendingTestSuites\": 0,\n        \"numPendingTests\": 0,\n        \"numTodoTests\": 0,\n        \"numTotalTestSuites\": 0,\n        \"numTotalTests\": 0,\n        \"snapshot\": {\n          \"added\": 0,\n          \"didUpdate\": false,\n          \"failure\": false,\n          \"filesAdded\": 0,\n          \"filesRemoved\": 0,\n          \"filesRemovedList\": [],\n          \"filesUnmatched\": 0,\n          \"filesUpdated\": 0,\n          \"matched\": 0,\n          \"total\": 0,\n          \"unchecked\": 0,\n          \"uncheckedKeysByFile\": [],\n          \"unmatched\": 0,\n          \"updated\": 0,\n        },\n        \"startTime\": 0,\n        \"success\": false,\n        \"testResults\": [],\n      }\n    `)\n  })\n\n  it('generates empty json with success: true', async () => {\n    const { stdout } = await runVitest({\n      reporters: 'json',\n      root,\n      includeTaskLocation: true,\n      passWithNoTests: true,\n    }, ['json-non-existing-files'])\n\n    const json = JSON.parse(stdout)\n    json.startTime = 0\n    expect(json).toMatchInlineSnapshot(`\n      {\n        \"numFailedTestSuites\": 0,\n        \"numFailedTests\": 0,\n        \"numPassedTestSuites\": 0,\n        \"numPassedTests\": 0,\n        \"numPendingTestSuites\": 0,\n        \"numPendingTests\": 0,\n        \"numTodoTests\": 0,\n        \"numTotalTestSuites\": 0,\n        \"numTotalTests\": 0,\n        \"snapshot\": {\n          \"added\": 0,\n          \"didUpdate\": false,\n          \"failure\": false,\n          \"filesAdded\": 0,\n          \"filesRemoved\": 0,\n          \"filesRemovedList\": [],\n          \"filesUnmatched\": 0,\n          \"filesUpdated\": 0,\n          \"matched\": 0,\n          \"total\": 0,\n          \"unchecked\": 0,\n          \"uncheckedKeysByFile\": [],\n          \"unmatched\": 0,\n          \"updated\": 0,\n        },\n        \"startTime\": 0,\n        \"success\": true,\n        \"testResults\": [],\n      }\n    `)\n  })\n\n  it.each([\n    ['passed', 'all-passing-or-skipped.test.ts'],\n    ['passed', 'all-skipped.test.ts'],\n    ['failed', 'some-failing.test.ts'],\n  ])('resolves to \"%s\" status for test file \"%s\"', async (expected, file) => {\n    const { stdout } = await runVitest({ reporters: 'json', root, include: [`**/${file}`] })\n\n    const data = JSON.parse(stdout)\n\n    expect(data.testResults).toHaveLength(1)\n    expect(data.testResults[0].status).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "test/cli/test/reporters/junit.test.ts",
    "content": "import type { Task } from '@vitest/runner'\nimport type { RunnerTaskResult, RunnerTestCase, RunnerTestFile, RunnerTestSuite } from 'vitest'\nimport { runVitest, runVitestCli } from '#test-utils'\nimport { createFileTask } from '@vitest/runner/utils'\nimport { resolve } from 'pathe'\nimport { expect, test } from 'vitest'\n\nconst root = resolve(import.meta.dirname, '../../fixtures/reporters')\n\ntest('calc the duration used by junit', () => {\n  const result: RunnerTaskResult = { state: 'pass', duration: 0 }\n  const file: RunnerTestFile = createFileTask('/test.ts', '/', 'test')\n  const suiteName\n    = 'suite'\n  const suite: RunnerTestSuite = {\n    id: '1_0',\n    type: 'suite',\n    name: suiteName,\n    fullName: `${file.fullName} > ${suiteName}`,\n    fullTestName: `${file.fullTestName} > ${suiteName}`,\n    mode: 'run',\n    tasks: [],\n    file,\n    meta: {},\n  }\n  const taskName = 'timeout'\n  const task: RunnerTestCase = {\n    id: '1_0_0',\n    type: 'test',\n    name: taskName,\n    fullName: `${suite.fullName} > ${suiteName}`,\n    fullTestName: `${suite.fullTestName} > ${suiteName}`,\n    mode: 'run',\n    result,\n    annotations: [],\n    artifacts: [],\n    file,\n    timeout: 0,\n    context: null as any,\n    suite,\n    meta: {},\n  }\n  file.tasks = [suite]\n  suite.tasks = [task]\n  expect(getDuration(task)).toBe('0')\n  result.duration = 0.12\n  expect(getDuration(task)).toBe('0.00012')\n  result.duration = 12\n  expect(getDuration(task)).toBe('0.012')\n  result.duration = 12.01\n  expect(getDuration(task)).toBe('0.01201')\n  result.duration = 12000\n  expect(getDuration(task)).toBe('12')\n  result.duration = 12001\n  expect(getDuration(task)).toBe('12.001')\n})\n\ntest('emits <failure> if a test has a syntax error', async () => {\n  const { stdout } = await runVitest({ reporters: 'junit', root }, ['with-syntax-error'])\n\n  const xml = stabilizeReport(stdout)\n\n  expect(xml).toContain('<testsuite name=\"with-syntax-error.test.js\" timestamp=\"...\" hostname=\"...\" tests=\"1\" failures=\"1\" errors=\"0\" skipped=\"0\" time=\"...\">')\n  expect(xml).toContain('<failure')\n})\n\ntest('emits <failure> when beforeAll/afterAll failed', async () => {\n  const { stdout } = await runVitest({ reporters: 'junit', root: './fixtures/reporters/suite-hook-failure' })\n\n  const xml = stabilizeReport(stdout)\n\n  expect(xml).toMatchSnapshot()\n})\n\ntest('time', async () => {\n  const { stdout } = await runVitest({ reporters: 'junit', root: './fixtures/reporters/duration' })\n\n  const xml = stabilizeReportWOTime(stdout)\n\n  const fastTestRegex = /<testcase classname=\"basic\\.test\\.ts\" name=\"fast\" time=\"(?<floatNumber>[\\d.]+)\">/\n  const fastTestTime = matchJunitTime(xml, fastTestRegex)\n  expect(fastTestTime).toBeGreaterThan(0)\n\n  const slowTestRegex = /<testcase classname=\"basic\\.test\\.ts\" name=\"slow\" time=\"(?<floatNumber>[\\d.]+)\">/\n  const slowTestTime = matchJunitTime(xml, slowTestRegex)\n  expect(slowTestTime).toBeGreaterThan(0.2)\n\n  const testsuiteRegex = /<testsuite name=\"basic\\.test\\.ts\" timestamp=\"\\.\\.\\.\" hostname=\"\\.\\.\\.\" tests=\"2\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"(?<floatNumber>[\\d.]+)\">/\n  const testsuiteTime = matchJunitTime(xml, testsuiteRegex)\n  expect(testsuiteTime).toBeCloseTo(fastTestTime + slowTestTime, 1)\n\n  const testsuitesRegex = /<testsuites name=\"vitest tests\" tests=\"2\" failures=\"0\" errors=\"0\" time=\"(?<floatNumber>[\\d.]+)\">/\n  const testsuitesTime = matchJunitTime(xml, testsuitesRegex)\n  expect(testsuitesTime).toBeCloseTo(testsuiteTime, 1)\n})\n\ntest('format error', async () => {\n  const { stdout } = await runVitest({ reporters: 'junit', root }, ['error.test.ts'])\n  expect(stabilizeReport(stdout)).toMatchSnapshot()\n})\n\ntest('write testsuite name relative to root config', async () => {\n  const { stdout } = await runVitest({ reporters: 'junit', root: './fixtures/reporters/better-testsuite-name' })\n\n  const xml = stabilizeReport(stdout)\n\n  expect(xml).toContain('<testsuite name=\"space-1/test/base.test.ts\" timestamp=\"...\" hostname=\"...\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"...\">')\n  expect(xml).toContain('<testsuite name=\"space-2/test/base.test.ts\" timestamp=\"...\" hostname=\"...\" tests=\"1\" failures=\"0\" errors=\"0\" skipped=\"0\" time=\"...\">')\n})\n\ntest('options.suiteName changes name property', async () => {\n  const { stdout } = await runVitest({\n    reporters: [['junit', { suiteName: 'some-custom-suiteName' }]],\n    root: './fixtures/reporters/default',\n    include: ['a.test.ts'],\n  })\n\n  const xml = stabilizeReport(stdout)\n\n  expect(xml).not.toContain('<testsuites name=\"vitest tests\"')\n  expect(xml).toContain('<testsuites name=\"some-custom-suiteName\"')\n})\n\nfunction stabilizeReport(report: string) {\n  return report.replaceAll(/(timestamp|hostname|time)=\".*?\"/g, '$1=\"...\"')\n}\n\nfunction stabilizeReportWOTime(report: string) {\n  return report.replaceAll(/(timestamp|hostname)=\".*?\"/g, '$1=\"...\"')\n}\n\nfunction matchJunitTime(xml: string, regex: RegExp) {\n  const match = xml.match(regex)\n  expect(match).not.toBeNull()\n  const time = Number.parseFloat(match!.groups!.floatNumber)\n  expect(time).toBeGreaterThanOrEqual(0)\n  return time\n}\n\ntest.each([true, false])('includeConsoleOutput %s', async (t) => {\n  const { stdout } = await runVitest({\n    reporters: [['junit', { includeConsoleOutput: t }]],\n    root,\n    include: ['console-simple.test.ts'],\n  })\n  expect(stabilizeReport(stdout)).matchSnapshot()\n})\n\ntest.each([true, false])('addFileAttribute %s', async (t) => {\n  const { stdout } = await runVitest({\n    reporters: [['junit', { addFileAttribute: t }]],\n    root,\n    include: ['ok.test.ts'],\n  })\n  expect(stabilizeReport(stdout)).matchSnapshot()\n})\n\ntest('many errors without warning', async () => {\n  const { stderr } = await runVitestCli(\n    'run',\n    '--reporter=junit',\n    '--root',\n    resolve(import.meta.dirname, '../fixtures/reporters/many-errors'),\n  )\n  expect(stderr).not.toContain('MaxListenersExceededWarning')\n})\n\ntest('CLI reporter option preserves config file options', async () => {\n  const { stdout } = await runVitestCli(\n    'run',\n    '--reporter=junit',\n    '--root',\n    resolve(import.meta.dirname, '../../fixtures/reporters/junit-cli-options'),\n  )\n\n  const xml = stabilizeReport(stdout)\n\n  // Verify that suiteName from config is preserved\n  expect(xml).not.toContain('<testsuites name=\"vitest tests\"')\n  expect(xml).toContain('<testsuites name=\"custom-suite-name\"')\n\n  // Verify that addFileAttribute from config is preserved\n  expect(xml).toContain('file=\"')\n})\n\nfunction executionTime(durationMS: number) {\n  return (durationMS / 1000).toLocaleString('en-US', {\n    useGrouping: false,\n    maximumFractionDigits: 10,\n  })\n}\n\nexport function getDuration(task: Task): string | undefined {\n  const duration = task.result?.duration ?? 0\n  return executionTime(duration)\n}\n"
  },
  {
    "path": "test/cli/test/reporters/logger.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest('cursor is hidden during test run in TTY', async () => {\n  const { stdout } = await runVitest({\n    include: ['b1.test.ts'],\n    root: 'fixtures/reporters/default',\n    reporters: 'none',\n    watch: false,\n  }, [], { tty: true, preserveAnsi: true })\n\n  expect(stdout).toContain('\\x1B[?25l')\n  expect(stdout).toContain('\\x1B[?25h')\n})\n\ntest('cursor is not hidden during test run in non-TTY', async () => {\n  const { stdout } = await runVitest({\n    include: ['b1.test.ts'],\n    root: 'fixtures/default',\n    reporters: 'none',\n    watch: false,\n  }, [], { preserveAnsi: true })\n\n  expect(stdout).not.toContain('\\x1B[?25l')\n  expect(stdout).not.toContain('\\x1B[?25h')\n})\n"
  },
  {
    "path": "test/cli/test/reporters/merge-reports.test.ts",
    "content": "import type { File, Test } from '@vitest/runner/types'\nimport type { TestUserConfig, Vitest } from 'vitest/node'\nimport { rmSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { runVitest } from '#test-utils'\nimport { playwright } from '@vitest/browser-playwright'\nimport { createFileTask } from '@vitest/runner/utils'\nimport { beforeEach, expect, test } from 'vitest'\nimport { version } from 'vitest/package.json'\nimport { writeBlob } from 'vitest/src/node/reporters/blob.js'\nimport { getModuleGraph } from '../../../../packages/vitest/src/utils/graph'\n\n// always relative to CWD because it's used only from the CLI,\n// so we need to correctly resolve it here\nconst reportsDir = resolve('./fixtures/reporters/merge-reports/.vitest-reports')\n\nbeforeEach(() => {\n  rmSync(reportsDir, { force: true, recursive: true })\n})\n\ntest('merge reports', async () => {\n  await runVitest({\n    root: './fixtures/reporters/merge-reports',\n    include: ['first.test.ts'],\n    reporters: [['blob', { outputFile: './.vitest-reports/first-run.json' }]],\n  })\n\n  await runVitest({\n    root: './fixtures/reporters/merge-reports',\n    include: ['second.test.ts'],\n    reporters: [['blob', { outputFile: './.vitest-reports/second-run.json' }]],\n  })\n\n  const { stdout: reporterDefault, stderr: stderrDefault, exitCode } = await runVitest({\n    root: './fixtures/reporters/merge-reports',\n    mergeReports: reportsDir,\n    reporters: [['default', { isTTY: false }]],\n  })\n\n  expect(exitCode).toBe(1)\n\n  const stdoutCheck = trimReporterOutput(reporterDefault)\n  const stderrArr = stderrDefault.split('\\n')\n  const stderrCheck = [\n    ...stderrArr.slice(4, 19),\n    ...stderrArr.slice(21, -3),\n  ]\n\n  expect(stderrDefault).toMatch('Failed Tests 2')\n\n  expect(stderrCheck.join('\\n')).toMatchInlineSnapshot(`\n    \"AssertionError: expected 1 to be 2 // Object.is equality\n\n    - Expected\n    + Received\n\n    - 2\n    + 1\n\n     ❯ first.test.ts:15:13\n         13| test('test 1-2', () => {\n         14|   console.log('test 1-2')\n         15|   expect(1).toBe(2)\n           |             ^\n         16| })\n         17|\n\n     FAIL  second.test.ts > test 2-1\n    AssertionError: expected 1 to be 2 // Object.is equality\n\n    - Expected\n    + Received\n\n    - 2\n    + 1\n\n     ❯ second.test.ts:5:13\n          3| test('test 2-1', () => {\n          4|   console.log('test 2-1')\n          5|   expect(1).toBe(2)\n           |             ^\n          6| })\n          7|\n    \"\n  `)\n\n  expect(stdoutCheck).toMatchInlineSnapshot(`\n    \"stdout | first.test.ts\n    global scope\n\n    stdout | first.test.ts > test 1-1\n    beforeEach\n\n    stdout | first.test.ts > test 1-2\n    beforeEach\n\n    stdout | first.test.ts > test 1-2\n    test 1-2\n\n     ❯ first.test.ts (2 tests | 1 failed) <time>\n       ✓ test 1-1 <time>\n       × test 1-2 <time>\n    stdout | second.test.ts > test 2-1\n    test 2-1\n\n     ❯ second.test.ts (3 tests | 1 failed) <time>\n       × test 2-1 <time>\n         ✓ test 2-2 <time>\n         ✓ test 2-3 <time>\n\n     Test Files  2 failed (2)\n          Tests  2 failed | 3 passed (5)\n       Duration  <time> (transform <time>, setup <time>, import <time>, tests <time>, environment <time>)\n       Per blob  <time> <time>\"\n  `)\n\n  const { stdout: reporterJson } = await runVitest({\n    root: './fixtures/reporters/merge-reports',\n    mergeReports: reportsDir,\n    reporters: [['json', { outputFile: /** so it outputs into stdout */ null }]],\n  })\n\n  const slash = (r: string) => r.replace(/\\\\/g, '/')\n  const path = (r: string) => slash(r)\n    .replace(new RegExp(slash(process.cwd()), 'gi'), '<root>')\n\n  const json = JSON.parse(reporterJson)\n  json.testResults.forEach((result: any) => {\n    result.startTime = '<time>'\n    result.endTime = '<time>'\n    result.name = path(result.name)\n    result.assertionResults.forEach((assertion: any) => {\n      delete assertion.duration\n      assertion.failureMessages = assertion.failureMessages.map((m: string) => {\n        return m.split('\\n').slice(0, 2).map(path).join('\\n')\n      })\n    })\n  })\n  json.startTime = '<time>'\n\n  expect(json).toMatchInlineSnapshot(`\n    {\n      \"numFailedTestSuites\": 2,\n      \"numFailedTests\": 2,\n      \"numPassedTestSuites\": 1,\n      \"numPassedTests\": 3,\n      \"numPendingTestSuites\": 0,\n      \"numPendingTests\": 0,\n      \"numTodoTests\": 0,\n      \"numTotalTestSuites\": 3,\n      \"numTotalTests\": 5,\n      \"snapshot\": {\n        \"added\": 0,\n        \"didUpdate\": false,\n        \"failure\": false,\n        \"filesAdded\": 0,\n        \"filesRemoved\": 0,\n        \"filesRemovedList\": [],\n        \"filesUnmatched\": 0,\n        \"filesUpdated\": 0,\n        \"matched\": 0,\n        \"total\": 0,\n        \"unchecked\": 0,\n        \"uncheckedKeysByFile\": [],\n        \"unmatched\": 0,\n        \"updated\": 0,\n      },\n      \"startTime\": \"<time>\",\n      \"success\": false,\n      \"testResults\": [\n        {\n          \"assertionResults\": [\n            {\n              \"ancestorTitles\": [],\n              \"failureMessages\": [],\n              \"fullName\": \"test 1-1\",\n              \"meta\": {},\n              \"status\": \"passed\",\n              \"tags\": [],\n              \"title\": \"test 1-1\",\n            },\n            {\n              \"ancestorTitles\": [],\n              \"failureMessages\": [\n                \"AssertionError: expected 1 to be 2 // Object.is equality\n        at <root>/fixtures/reporters/merge-reports/first.test.ts:15:13\",\n              ],\n              \"fullName\": \"test 1-2\",\n              \"meta\": {},\n              \"status\": \"failed\",\n              \"tags\": [],\n              \"title\": \"test 1-2\",\n            },\n          ],\n          \"endTime\": \"<time>\",\n          \"message\": \"\",\n          \"name\": \"<root>/fixtures/reporters/merge-reports/first.test.ts\",\n          \"startTime\": \"<time>\",\n          \"status\": \"failed\",\n        },\n        {\n          \"assertionResults\": [\n            {\n              \"ancestorTitles\": [],\n              \"failureMessages\": [\n                \"AssertionError: expected 1 to be 2 // Object.is equality\n        at <root>/fixtures/reporters/merge-reports/second.test.ts:5:13\",\n              ],\n              \"fullName\": \"test 2-1\",\n              \"meta\": {},\n              \"status\": \"failed\",\n              \"tags\": [],\n              \"title\": \"test 2-1\",\n            },\n            {\n              \"ancestorTitles\": [\n                \"group\",\n              ],\n              \"failureMessages\": [],\n              \"fullName\": \"group test 2-2\",\n              \"meta\": {},\n              \"status\": \"passed\",\n              \"tags\": [],\n              \"title\": \"test 2-2\",\n            },\n            {\n              \"ancestorTitles\": [\n                \"group\",\n              ],\n              \"failureMessages\": [],\n              \"fullName\": \"group test 2-3\",\n              \"meta\": {},\n              \"status\": \"passed\",\n              \"tags\": [],\n              \"title\": \"test 2-3\",\n            },\n          ],\n          \"endTime\": \"<time>\",\n          \"message\": \"\",\n          \"name\": \"<root>/fixtures/reporters/merge-reports/second.test.ts\",\n          \"startTime\": \"<time>\",\n          \"status\": \"failed\",\n        },\n      ],\n    }\n  `)\n})\n\ntest('total and merged execution times are shown', async () => {\n  for (const [_index, name] of ['first.test.ts', 'second.test.ts'].entries()) {\n    const index = 1 + _index\n    const file = createFileTask(\n      resolve('./fixtures/reporters/merge-reports', name),\n      resolve('./fixtures/reporters/merge-reports'),\n      '',\n    )\n    file.tasks.push(createTest('some test', file))\n\n    await writeBlob(\n      [version, [file], [], undefined, 1500 * index, {}],\n      resolve(`./fixtures/reporters/merge-reports/.vitest-reports/blob-${index}-2.json`),\n    )\n  }\n\n  const { stdout } = await runVitest({\n    root: resolve('./fixtures/reporters/merge-reports'),\n    mergeReports: resolve('./fixtures/reporters/merge-reports/.vitest-reports'),\n    reporters: [['default', { isTTY: false }]],\n  })\n\n  expect(stdout).toContain('✓ first.test.ts (1 test)')\n  expect(stdout).toContain('✓ second.test.ts (1 test)')\n\n  expect(stdout).toContain('Duration  4.50s')\n  expect(stdout).toContain('Per blob  1.50s 3.00s')\n})\n\ntest.for([\n  'node',\n  'browser',\n])('module graph and html reporter $0', async (mode) => {\n  const root = resolve('./fixtures/reporters/merge-reports-module-graph')\n  const reportsDir = resolve(root, '.vitest-reports')\n  rmSync(reportsDir, { force: true, recursive: true })\n\n  const baseConfig: TestUserConfig = {\n    root,\n  }\n  if (mode === 'browser') {\n    baseConfig.browser = {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        {\n          browser: 'chromium',\n        },\n      ],\n      headless: true,\n    }\n  }\n\n  const result = await runVitest({\n    ...baseConfig,\n    reporters: ['blob'],\n  })\n  expect.assert(result.ctx)\n  const generatedModuleGraphJson = await getSerializedModuleGraph(result.ctx)\n  if (mode === 'browser') {\n    expect(generatedModuleGraphJson).toMatchInlineSnapshot(`\n      \"{\n        \"<root>/basic.test.ts\": {\n          \"graph\": {\n            \"<root>/sub/subject.ts\": [],\n            \"<root>/sub/format.ts\": [\n              \"<root>/sub/subject.ts\"\n            ],\n            \"<root>/util.ts\": [\n              \"<root>/sub/subject.ts\"\n            ],\n            \"<root>/basic.test.ts\": [\n              \"<root>/sub/format.ts\",\n              \"<root>/util.ts\"\n            ]\n          },\n          \"externalized\": [],\n          \"inlined\": [\n            \"<root>/basic.test.ts\",\n            \"<root>/sub/format.ts\",\n            \"<root>/sub/subject.ts\",\n            \"<root>/util.ts\"\n          ]\n        },\n        \"<root>/second.test.ts\": {\n          \"graph\": {\n            \"<root>/sub/subject.ts\": [],\n            \"<root>/util.ts\": [\n              \"<root>/sub/subject.ts\"\n            ],\n            \"<root>/second.test.ts\": [\n              \"<root>/util.ts\",\n              \"<optimized-deps>/obug.js\"\n            ]\n          },\n          \"externalized\": [\n            \"<optimized-deps>/obug.js?v=<hash>\"\n          ],\n          \"inlined\": [\n            \"<root>/second.test.ts\",\n            \"<root>/util.ts\",\n            \"<root>/sub/subject.ts\"\n          ]\n        }\n      }\"\n    `)\n  }\n  else {\n    expect(generatedModuleGraphJson).toMatchInlineSnapshot(`\n      \"{\n        \"<root>/basic.test.ts\": {\n          \"graph\": {\n            \"<root>/sub/subject.ts\": [],\n            \"<root>/sub/format.ts\": [\n              \"<root>/sub/subject.ts\"\n            ],\n            \"<root>/util.ts\": [\n              \"<root>/sub/subject.ts\"\n            ],\n            \"<root>/basic.test.ts\": [\n              \"<root>/sub/format.ts\",\n              \"<root>/util.ts\"\n            ]\n          },\n          \"externalized\": [],\n          \"inlined\": [\n            \"<root>/basic.test.ts\",\n            \"<root>/sub/format.ts\",\n            \"<root>/sub/subject.ts\",\n            \"<root>/util.ts\"\n          ]\n        },\n        \"<root>/second.test.ts\": {\n          \"graph\": {\n            \"<root>/sub/subject.ts\": [],\n            \"<root>/util.ts\": [\n              \"<root>/sub/subject.ts\"\n            ],\n            \"<root>/second.test.ts\": [\n              \"<root>/util.ts\",\n              \"<node_modules>/obug/dist/node.js\"\n            ]\n          },\n          \"externalized\": [\n            \"<node_modules>/obug/dist/node.js\"\n          ],\n          \"inlined\": [\n            \"<root>/second.test.ts\",\n            \"<root>/util.ts\",\n            \"<root>/sub/subject.ts\"\n          ]\n        }\n      }\"\n    `)\n  }\n\n  const result2 = await runVitest({\n    ...baseConfig,\n    mergeReports: reportsDir,\n  })\n  expect(result2.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect.assert(result2.ctx)\n  const restoredModuleGraphJson = await getSerializedModuleGraph(result2.ctx)\n  expect(restoredModuleGraphJson).toBe(generatedModuleGraphJson)\n\n  const result3 = await runVitest({\n    ...baseConfig,\n    mergeReports: resolve(root, '.vitest-reports'),\n    reporters: ['html'],\n  })\n  expect(result3.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(result3.stdout).toMatchInlineSnapshot(`\n    \" HTML  Report is generated\n           You can run npx vite preview --outDir html to see the test results.\n    \"\n  `)\n})\n\nasync function getSerializedModuleGraph(ctx: Vitest) {\n  const files = ctx.state.getFiles().slice().sort((a, b) => a.filepath.localeCompare(b.filepath))\n  const moduleGraphs = Object.fromEntries(\n    await Promise.all(\n      files.map(async (file) => {\n        const projectName = file.projectName || ''\n        const project = ctx.getProjectByName(projectName)\n        const graph = await getModuleGraph(\n          ctx,\n          projectName,\n          file.filepath,\n          project.config.browser.enabled,\n        )\n        return [file.filepath, graph] as const\n      }),\n    ),\n  )\n  return JSON.stringify(moduleGraphs, null, 2)\n    .replaceAll(ctx.config.root, '<root>')\n    .replace(/\"[^\"\\n]*\\/node_modules\\//g, '\"<node_modules>/')\n    .replace(/<node_modules>\\/\\.vite\\/vitest\\/[a-f0-9]{40}\\/deps\\/([^\"?]+)/g, '<optimized-deps>/$1')\n    .replace(/\\?v=[a-f0-9]+/g, '?v=<hash>')\n}\n\nfunction trimReporterOutput(report: string) {\n  const rows = report\n    .replace(/\\d+ms/g, '<time>')\n    .replace(/\\d+\\.\\d+s/g, '<time>')\n    .split('\\n')\n\n  // Trim start and end, capture just rendered tree\n  rows.splice(0, 1 + rows.findIndex(row => row.includes('RUN  v')))\n  rows.splice(rows.findIndex(row => row.includes('Start at')), 1)\n\n  return rows.join('\\n').trim()\n}\n\nfunction createTest(name: string, file: File): Test {\n  file.result = { state: 'pass' }\n\n  return {\n    type: 'test',\n    name,\n    fullName: `${file.fullName} > ${name}`,\n    fullTestName: `${file.fullTestName} > ${name}`,\n    id: `${file.id}_0`,\n    mode: 'run',\n    file,\n    suite: file,\n    annotations: [],\n    artifacts: [],\n    timeout: 0,\n    result: { state: 'pass' },\n    meta: {},\n    context: {} as any,\n  }\n}\n"
  },
  {
    "path": "test/cli/test/reporters/reporter-error.test.ts",
    "content": "import { rmSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { runVitest } from '#test-utils'\nimport { beforeEach, describe, expect, test } from 'vitest'\n\nconst root = './fixtures/reporters/reporter-error'\nconst reportsDir = resolve(root, '.vitest-reports')\n\nbeforeEach(() => {\n  rmSync(reportsDir, { force: true, recursive: true })\n})\n\ndescribe('reporter errors', () => {\n  test('onTestRunStart in normal run', async () => {\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      reporters: [\n        {\n          onTestRunStart() {\n            throw new Error('reporter error: onTestRunStart')\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.stderr).toContain('reporter error: onTestRunStart')\n    expect(result.errorTree()).toMatchInlineSnapshot(`{}`)\n    expect(onTestRunEndCalled).toBe(false)\n    expect(result.exitCode).toBe(1)\n  })\n\n  test('onTestRunStart in --merge-reports', async () => {\n    await runVitest({\n      root,\n      reporters: ['blob'],\n    })\n\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      mergeReports: reportsDir,\n      reporters: [\n        {\n          onTestRunStart() {\n            throw new Error('reporter error: onTestRunStart')\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.stderr).toContain('reporter error: onTestRunStart')\n    expect(result.errorTree()).toMatchInlineSnapshot(`{}`)\n    expect(onTestRunEndCalled).toBe(false)\n    expect(result.exitCode).toBe(1)\n  })\n\n  test('onTestModuleQueued in normal run', async () => {\n    let didThrow = false\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      reporters: [\n        {\n          onTestModuleQueued() {\n            didThrow = true\n            throw new Error('reporter error: onTestModuleQueued')\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.errorTree()).toMatchInlineSnapshot(`\n      {\n        \"__unhandled_errors__\": [\n          \"reporter error: onTestModuleQueued\",\n        ],\n        \"basic.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n    expect({ didThrow, onTestRunEndCalled, exitCode: result.exitCode }).toMatchInlineSnapshot(`\n      {\n        \"didThrow\": true,\n        \"exitCode\": 1,\n        \"onTestRunEndCalled\": true,\n      }\n    `)\n  })\n\n  test('onTestModuleQueued in --merge-reports', async () => {\n    await runVitest({\n      root,\n      reporters: ['blob'],\n    })\n\n    let didThrow = false\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      mergeReports: reportsDir,\n      reporters: [\n        {\n          onTestModuleQueued() {\n            didThrow = true\n            throw new Error('reporter error: onTestModuleQueued')\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.errorTree()).toMatchInlineSnapshot(`\n      {\n        \"__unhandled_errors__\": [\n          \"reporter error: onTestModuleQueued\",\n        ],\n        \"basic.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n    expect({ didThrow, onTestRunEndCalled, exitCode: result.exitCode }).toMatchInlineSnapshot(`\n      {\n        \"didThrow\": true,\n        \"exitCode\": 1,\n        \"onTestRunEndCalled\": true,\n      }\n    `)\n  })\n\n  test('onTestModuleCollected in normal run', async () => {\n    let didThrow = false\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      reporters: [\n        {\n          onTestModuleCollected() {\n            didThrow = true\n            throw new Error('reporter error: onTestModuleCollected')\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.errorTree()).toMatchInlineSnapshot(`\n      {\n        \"__unhandled_errors__\": [\n          \"reporter error: onTestModuleCollected\",\n        ],\n        \"basic.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n    expect({ didThrow, onTestRunEndCalled, exitCode: result.exitCode }).toMatchInlineSnapshot(`\n      {\n        \"didThrow\": true,\n        \"exitCode\": 1,\n        \"onTestRunEndCalled\": true,\n      }\n    `)\n  })\n\n  test('onTestModuleCollected in --merge-reports', async () => {\n    await runVitest({\n      root,\n      reporters: ['blob'],\n    })\n\n    let didThrow = false\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      mergeReports: reportsDir,\n      reporters: [\n        {\n          onTestModuleCollected() {\n            didThrow = true\n            throw new Error('reporter error: onTestModuleCollected')\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.errorTree()).toMatchInlineSnapshot(`\n      {\n        \"__unhandled_errors__\": [\n          \"reporter error: onTestModuleCollected\",\n        ],\n        \"basic.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n    expect({ didThrow, onTestRunEndCalled, exitCode: result.exitCode }).toMatchInlineSnapshot(`\n      {\n        \"didThrow\": true,\n        \"exitCode\": 1,\n        \"onTestRunEndCalled\": true,\n      }\n    `)\n  })\n\n  test('onTaskUpdate in normal run', async () => {\n    let didThrow = false\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      reporters: [\n        {\n          onTaskUpdate() {\n            didThrow = true\n            throw new Error('reporter error: onTaskUpdate')\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.errorTree()).toMatchInlineSnapshot(`\n      {\n        \"__unhandled_errors__\": [\n          \"reporter error: onTaskUpdate\",\n        ],\n        \"basic.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n    expect({ didThrow, onTestRunEndCalled, exitCode: result.exitCode }).toMatchInlineSnapshot(`\n      {\n        \"didThrow\": true,\n        \"exitCode\": 1,\n        \"onTestRunEndCalled\": true,\n      }\n    `)\n  })\n\n  test('onTaskUpdate in --merge-reports', async () => {\n    await runVitest({\n      root,\n      reporters: ['blob'],\n    })\n\n    let didThrow = false\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      mergeReports: reportsDir,\n      reporters: [\n        {\n          onTaskUpdate() {\n            didThrow = true\n            throw new Error('reporter error: onTaskUpdate')\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.errorTree()).toMatchInlineSnapshot(`\n      {\n        \"__unhandled_errors__\": [\n          \"reporter error: onTaskUpdate\",\n        ],\n        \"basic.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n    expect({ didThrow, onTestRunEndCalled, exitCode: result.exitCode }).toMatchInlineSnapshot(`\n      {\n        \"didThrow\": true,\n        \"exitCode\": 1,\n        \"onTestRunEndCalled\": true,\n      }\n    `)\n  })\n\n  test('onUserConsoleLog in normal run', async () => {\n    let didThrow = false\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      reporters: [\n        {\n          onUserConsoleLog(log) {\n            if (log.content.includes('trigger-reporter-error')) {\n              didThrow = true\n              throw new Error('reporter error: onUserConsoleLog')\n            }\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.errorTree()).toMatchInlineSnapshot(`\n      {\n        \"__unhandled_errors__\": [\n          \"reporter error: onUserConsoleLog\",\n        ],\n        \"basic.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n    expect({ didThrow, onTestRunEndCalled, exitCode: result.exitCode }).toMatchInlineSnapshot(`\n      {\n        \"didThrow\": true,\n        \"exitCode\": 1,\n        \"onTestRunEndCalled\": true,\n      }\n    `)\n  })\n\n  test('onUserConsoleLog in --merge-reports', async () => {\n    await runVitest({\n      root,\n      reporters: ['blob'],\n    })\n\n    let didThrow = false\n    let onTestRunEndCalled = false\n    const result = await runVitest({\n      root,\n      mergeReports: reportsDir,\n      reporters: [\n        {\n          onUserConsoleLog(log) {\n            if (log.content.includes('trigger-reporter-error')) {\n              didThrow = true\n              throw new Error('reporter error: onUserConsoleLog')\n            }\n          },\n          onTestRunEnd() {\n            onTestRunEndCalled = true\n          },\n        },\n      ],\n    })\n    expect(result.errorTree()).toMatchInlineSnapshot(`\n      {\n        \"__unhandled_errors__\": [\n          \"reporter error: onUserConsoleLog\",\n        ],\n        \"basic.test.ts\": {\n          \"basic\": \"passed\",\n        },\n      }\n    `)\n    expect({ didThrow, onTestRunEndCalled, exitCode: result.exitCode }).toMatchInlineSnapshot(`\n      {\n        \"didThrow\": true,\n        \"exitCode\": 1,\n        \"onTestRunEndCalled\": true,\n      }\n    `)\n  })\n})\n"
  },
  {
    "path": "test/cli/test/reporters/reporters.test.ts",
    "content": "import type { TestModule } from 'vitest/node'\nimport { existsSync, readFileSync, rmSync } from 'node:fs'\nimport { normalize, resolve } from 'pathe'\nimport { beforeEach, expect, test, vi } from 'vitest'\nimport { JsonReporter, JUnitReporter, TapFlatReporter, TapReporter } from 'vitest/node'\nimport { files, getContext, passedFiles } from './utils'\n\nconst beautify = (json: string) => JSON.parse(json)\nfunction getTestModules(_files = files) {\n  return _files.map(task => ({ task }) as TestModule)\n}\n\nbeforeEach(() => {\n  vi.setSystemTime(1642587001759)\n  return () => {\n    vi.useRealTimers()\n  }\n})\n\ntest('tap reporter', async () => {\n  // Arrange\n  const reporter = new TapReporter()\n  const context = getContext()\n  const testModules = getTestModules()\n\n  // Act\n  reporter.onInit(context.vitest)\n  reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(context.output).toMatchSnapshot()\n})\n\ntest('tap-flat reporter', async () => {\n  // Arrange\n  const reporter = new TapFlatReporter()\n  const context = getContext()\n  const testModules = getTestModules()\n\n  // Act\n  reporter.onInit(context.vitest)\n  reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(context.output).toMatchSnapshot()\n})\n\ntest('JUnit reporter', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({ hostname: 'hostname' })\n  const context = getContext()\n\n  // Act\n  await reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd([])\n\n  // Assert\n  expect(context.output).toMatchSnapshot()\n})\n\ntest('JUnit reporter without classname', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({ hostname: 'hostname' })\n  const context = getContext()\n  const testModules = getTestModules(passedFiles)\n\n  // Act\n  await reporter.onInit(context.vitest)\n\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(context.output).toMatchSnapshot()\n})\n\ntest('JUnit reporter with custom string classname', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({ classnameTemplate: 'my-custom-classname', hostname: 'hostname' })\n  const context = getContext()\n  const testModules = getTestModules(passedFiles)\n\n  // Act\n  await reporter.onInit(context.vitest)\n\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(context.output).toMatchSnapshot()\n})\n\ntest('JUnit reporter with custom function classnameTemplate', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({\n    classnameTemplate: task => `filename:${task.filename} - filepath:${task.filepath}`,\n    hostname: 'hostname',\n  })\n  const context = getContext()\n  const testModules = getTestModules(passedFiles)\n\n  // Act\n  await reporter.onInit(context.vitest)\n\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(context.output).toMatchSnapshot()\n})\ntest('JUnit reporter with custom string classnameTemplate', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({\n    classnameTemplate: `filename:{filename} - filepath:{filepath}`,\n    hostname: 'hostname',\n  })\n  const context = getContext()\n  const testModules = getTestModules(passedFiles)\n\n  // Act\n  await reporter.onInit(context.vitest)\n\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(context.output).toMatchSnapshot()\n})\n\ntest('JUnit reporter (no outputFile entry)', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({ hostname: 'hostname' })\n  const context = getContext()\n  context.vitest.config.outputFile = {}\n\n  // Act\n  await reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd([])\n\n  // Assert\n  expect(context.output).toMatchSnapshot()\n})\n\ntest('JUnit reporter with outputFile', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({ hostname: 'hostname' })\n  const outputFile = resolve('report.xml')\n  const context = getContext()\n  context.vitest.config.outputFile = outputFile\n\n  // Act\n  await reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd([])\n\n  // Assert\n  expect(normalizeCwd(context.output)).toMatchSnapshot()\n  expect(existsSync(outputFile)).toBe(true)\n  expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot()\n\n  // Cleanup\n  rmSync(outputFile)\n})\n\ntest('JUnit reporter with outputFile object', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({ hostname: 'hostname' })\n  const outputFile = resolve('report_object.xml')\n  const context = getContext()\n  context.vitest.config.outputFile = {\n    junit: outputFile,\n  }\n\n  // Act\n  await reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd([])\n\n  // Assert\n  expect(normalizeCwd(context.output)).toMatchSnapshot()\n  expect(existsSync(outputFile)).toBe(true)\n  expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot()\n\n  // Cleanup\n  rmSync(outputFile)\n})\n\ntest('JUnit reporter with outputFile in non-existing directory', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({ hostname: 'hostname' })\n  const rootDirectory = resolve('junitReportDirectory')\n  const outputFile = `${rootDirectory}/deeply/nested/report.xml`\n  const context = getContext()\n  context.vitest.config.outputFile = outputFile\n\n  // Act\n  await reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd([])\n\n  // Assert\n  expect(normalizeCwd(context.output)).toMatchSnapshot()\n  expect(existsSync(outputFile)).toBe(true)\n  expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot()\n\n  // Cleanup\n  rmSync(outputFile)\n})\n\ntest('JUnit reporter with outputFile object in non-existing directory', async () => {\n  // Arrange\n  const reporter = new JUnitReporter({ hostname: 'hostname' })\n  const rootDirectory = resolve('junitReportDirectory_object')\n  const outputFile = `${rootDirectory}/deeply/nested/report.xml`\n  const context = getContext()\n  context.vitest.config.outputFile = {\n    junit: outputFile,\n  }\n\n  // Act\n  await reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd([])\n\n  // Assert\n  expect(normalizeCwd(context.output)).toMatchSnapshot()\n  expect(existsSync(outputFile)).toBe(true)\n  expect(readFileSync(outputFile, 'utf8')).toMatchSnapshot()\n\n  // Cleanup\n  rmSync(outputFile)\n})\n\ntest('json reporter', async () => {\n  // Arrange\n  const reporter = new JsonReporter({})\n  const context = getContext()\n  const testModules = getTestModules()\n\n  vi.setSystemTime(1642587001759)\n\n  // Act\n  reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(JSON.parse(context.output)).toMatchSnapshot()\n})\n\ntest('json reporter (no outputFile entry)', async () => {\n  // Arrange\n  const reporter = new JsonReporter({})\n  const context = getContext()\n  context.vitest.config.outputFile = {}\n  const testModules = getTestModules()\n\n  vi.setSystemTime(1642587001759)\n\n  // Act\n  reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(JSON.parse(context.output)).toMatchSnapshot()\n})\n\ntest('json reporter with outputFile', async () => {\n  // Arrange\n  const reporter = new JsonReporter({})\n  const outputFile = resolve('report.json')\n  const context = getContext()\n  context.vitest.config.outputFile = outputFile\n  const testModules = getTestModules()\n\n  vi.setSystemTime(1642587001759)\n\n  // Act\n  reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(normalizeCwd(context.output)).toMatchSnapshot()\n  expect(existsSync(outputFile)).toBe(true)\n  expect(beautify(readFileSync(outputFile, 'utf8'))).toMatchSnapshot()\n\n  // Cleanup\n  rmSync(outputFile)\n})\n\ntest('json reporter with outputFile object', async () => {\n  // Arrange\n  const reporter = new JsonReporter({})\n  const outputFile = resolve('report_object.json')\n  const context = getContext()\n  context.vitest.config.outputFile = {\n    json: outputFile,\n  }\n  const testModules = getTestModules()\n\n  vi.setSystemTime(1642587001759)\n\n  // Act\n  reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(normalizeCwd(context.output)).toMatchSnapshot()\n  expect(existsSync(outputFile)).toBe(true)\n  expect(beautify(readFileSync(outputFile, 'utf8'))).toMatchSnapshot()\n\n  // Cleanup\n  rmSync(outputFile)\n})\n\ntest('json reporter with outputFile in non-existing directory', async () => {\n  // Arrange\n  const reporter = new JsonReporter({})\n  const rootDirectory = resolve('jsonReportDirectory')\n  const outputFile = `${rootDirectory}/deeply/nested/report.json`\n  const context = getContext()\n  context.vitest.config.outputFile = outputFile\n  const testModules = getTestModules()\n\n  vi.setSystemTime(1642587001759)\n\n  // Act\n  reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(normalizeCwd(context.output)).toMatchSnapshot()\n  expect(existsSync(outputFile)).toBe(true)\n  expect(beautify(readFileSync(outputFile, 'utf8'))).toMatchSnapshot()\n\n  // Cleanup\n  rmSync(rootDirectory, { recursive: true })\n})\n\ntest('json reporter with outputFile object in non-existing directory', async () => {\n  // Arrange\n  const reporter = new JsonReporter({})\n  const rootDirectory = resolve('jsonReportDirectory_object')\n  const outputFile = `${rootDirectory}/deeply/nested/report.json`\n  const context = getContext()\n  context.vitest.config.outputFile = {\n    json: outputFile,\n  }\n  const testModules = getTestModules()\n\n  vi.setSystemTime(1642587001759)\n\n  // Act\n  reporter.onInit(context.vitest)\n  await reporter.onTestRunEnd(testModules)\n\n  // Assert\n  expect(normalizeCwd(context.output)).toMatchSnapshot()\n  expect(existsSync(outputFile)).toBe(true)\n  expect(beautify(readFileSync(outputFile, 'utf8'))).toMatchSnapshot()\n\n  // Cleanup\n  rmSync(rootDirectory, { recursive: true })\n})\n\n/**\n * Ensure environment and OS specific paths are consistent in snapshots\n */\nfunction normalizeCwd(text: string) {\n  return text.replace(normalize(process.cwd()), '<process-cwd>')\n}\n"
  },
  {
    "path": "test/cli/test/reporters/silent.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\nimport { DefaultReporter } from 'vitest/node'\n\ntest('{ silent: true } hides all console logs', async () => {\n  const { stdout } = await runVitest({\n    config: false,\n    include: ['./fixtures/reporters/console-some-failing.test.ts'],\n    silent: true,\n    reporters: [new LogReporter()],\n  })\n\n  expect(stdout).not.toContain('stdout')\n  expect(stdout).not.toContain('Log from')\n  expect(stdout).toContain('Test Files  1 failed')\n})\n\ntest('default value of silence shows all console logs', async () => {\n  const { stdout } = await runVitest({\n    config: false,\n    include: ['./fixtures/reporters/console-some-failing.test.ts'],\n    reporters: [new LogReporter()],\n  })\n\n  expect(stdout.match(/stdout/g)).toHaveLength(8)\n\n  expect(stdout).toContain(`\\\nstdout | fixtures/reporters/console-some-failing.test.ts\nLog from failed file\n\nstdout | fixtures/reporters/console-some-failing.test.ts > passed test #1\nLog from passed test\n\nstdout | fixtures/reporters/console-some-failing.test.ts > failed test #1\nLog from failed test\n\nstdout | fixtures/reporters/console-some-failing.test.ts > failed suite #1\nLog from failed suite\n\nstdout | fixtures/reporters/console-some-failing.test.ts > failed suite #1 > passed test #2\nLog from passed test\n\nstdout | fixtures/reporters/console-some-failing.test.ts > failed suite #1 > failed test #2\nLog from failed test\n\nstdout | fixtures/reporters/console-some-failing.test.ts > passed suite #2\nLog from passed suite\n\nstdout | fixtures/reporters/console-some-failing.test.ts > passed suite #2 > passed test #3\nLog from passed test`,\n  )\n})\n\ntest('{ silent: \"passed-only\" } shows all console logs from failed tests only', async () => {\n  const { stdout } = await runVitest({\n    config: false,\n    include: ['./fixtures/reporters/console-some-failing.test.ts'],\n    silent: 'passed-only',\n    reporters: [new LogReporter()],\n  })\n\n  expect(stdout).toContain(`\\\nstdout | fixtures/reporters/console-some-failing.test.ts > failed test #1\nLog from failed test\n\nstdout | fixtures/reporters/console-some-failing.test.ts > failed suite #1 > failed test #2\nLog from failed test\n\nstdout | fixtures/reporters/console-some-failing.test.ts > failed suite #1\nLog from failed suite\n\nstdout | fixtures/reporters/console-some-failing.test.ts\nLog from failed file`,\n  )\n\n  expect(stdout).not.toContain('Log from passed')\n  expect(stdout.match(/stdout/g)).toHaveLength(4)\n})\n\ntest('{ silent: \"passed-only\" } logs are filtered by custom onConsoleLog', async () => {\n  const { stdout } = await runVitest({\n    config: false,\n    include: ['./fixtures/reporters/console-some-failing.test.ts'],\n    silent: 'passed-only',\n    onConsoleLog(log) {\n      if (log.includes('suite')) {\n        return true\n      }\n\n      return false\n    },\n    reporters: [new LogReporter()],\n  })\n\n  expect(stdout).toContain(`\\\nstdout | fixtures/reporters/console-some-failing.test.ts > failed suite #1\nLog from failed suite`,\n  )\n\n  expect(stdout).not.toContain('Log from passed')\n  expect(stdout).not.toContain('Log from failed test')\n  expect(stdout).not.toContain('Log from failed file')\n  expect(stdout.match(/stdout/g)).toHaveLength(1)\n})\n\nclass LogReporter extends DefaultReporter {\n  isTTY = true\n}\n"
  },
  {
    "path": "test/cli/test/reporters/tap.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest('handle custom error without name', async () => {\n  let { stdout, stderr } = await runVitest({ reporters: 'tap', root: './fixtures/reporters/custom-error' })\n  stdout = stdout.replaceAll(/time=(\\S*)/g, 'time=[...]') // strip non-deterministic output\n  expect(stdout).toMatchInlineSnapshot(`\n    \"TAP version 13\n    1..1\n    not ok 1 - basic.test.ts # time=[...] {\n        1..4\n        not ok 1 - no name object # time=[...]\n            ---\n            error:\n                name: \"Unknown Error\"\n                message: \"undefined\"\n            ...\n        not ok 2 - string # time=[...]\n            ---\n            error:\n                name: \"Unknown Error\"\n                message: \"hi\"\n            ...\n        not ok 3 - number # time=[...]\n            ---\n            error:\n                name: \"Unknown Error\"\n                message: \"1234\"\n            ...\n        not ok 4 - number name object # time=[...]\n            ---\n            error:\n                name: \"1234\"\n                message: \"undefined\"\n            ...\n    }\n    \"\n  `)\n  expect(stderr).toBe('')\n})\n\ntest('tap-flat handles custom error without name', async () => {\n  let { stdout, stderr } = await runVitest({ reporters: 'tap-flat', root: './fixtures/reporters/custom-error' })\n  stdout = stdout.replaceAll(/time=(\\S*)/g, 'time=[...]') // strip non-deterministic output\n  expect(stdout).toMatchInlineSnapshot(`\n    \"TAP version 13\n    1..4\n    not ok 1 - basic.test.ts > no name object # time=[...]\n        ---\n        error:\n            name: \"Unknown Error\"\n            message: \"undefined\"\n        ...\n    not ok 2 - basic.test.ts > string # time=[...]\n        ---\n        error:\n            name: \"Unknown Error\"\n            message: \"hi\"\n        ...\n    not ok 3 - basic.test.ts > number # time=[...]\n        ---\n        error:\n            name: \"Unknown Error\"\n            message: \"1234\"\n        ...\n    not ok 4 - basic.test.ts > number name object # time=[...]\n        ---\n        error:\n            name: \"1234\"\n            message: \"undefined\"\n        ...\n    \"\n  `)\n  expect(stderr).toBe('')\n})\n"
  },
  {
    "path": "test/cli/test/reporters/test-run.test.ts",
    "content": "import type { UserConsoleLog } from 'vitest'\nimport type {\n  ReportedHookContext,\n  Reporter,\n  SerializedError,\n  TestCase,\n  TestModule,\n  TestRunEndReason,\n  TestSpecification,\n  TestSuite,\n  TestUserConfig,\n  Vitest,\n} from 'vitest/node'\nimport { rmSync } from 'node:fs'\nimport { resolve, sep } from 'node:path'\nimport { runInlineTests, ts } from '#test-utils'\nimport { describe, expect, onTestFinished, test } from 'vitest'\n\ndescribe('TestRun', () => {\n  test('pass test run without files (no-watch)', async () => {\n    const report = await run(\n      {},\n      {\n        passWithNoTests: true,\n        watch: false,\n      },\n      {\n        printTestRunEvents: true,\n        failed: true,\n      },\n    )\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestRunStart (0 specifications)\n      onTestRunEnd   (passed, 0 modules, 0 errors)\"\n    `)\n  })\n\n  test('pass test run without files (watch)', async () => {\n    const report = await run(\n      {},\n      {\n        passWithNoTests: true,\n        watch: true,\n      },\n      {\n        printTestRunEvents: true,\n        failed: true,\n      },\n    )\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestRunStart (0 specifications)\n      onTestRunEnd   (passed, 0 modules, 0 errors)\"\n    `)\n  })\n\n  test('fail test run without files (no-watch)', async () => {\n    const report = await run(\n      {},\n      {\n        passWithNoTests: false,\n        watch: false,\n      },\n      {\n        printTestRunEvents: true,\n        failed: true,\n      },\n    )\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestRunStart (0 specifications)\n      onTestRunEnd   (failed, 0 modules, 0 errors)\"\n    `)\n  })\n})\n\ndescribe('TestModule', () => {\n  test('single test module', async () => {\n    const report = await run({\n      'test-module.test.ts': ts`\n        test('example', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (test-module.test.ts)\n      onTestModuleCollected (test-module.test.ts)\n      onTestModuleStart     (test-module.test.ts)\n        onTestCaseReady     (test-module.test.ts) |example|\n        onTestCaseResult    (test-module.test.ts) |example|\n      onTestModuleEnd       (test-module.test.ts)\"\n    `)\n  })\n\n  test('multiple test modules', async () => {\n    const report = await run({\n      'first.test.ts': ts`\n        test('first test case', () => {});\n      `,\n      'second.test.ts': ts`\n        test('second test case', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (first.test.ts)\n      onTestModuleCollected (first.test.ts)\n      onTestModuleStart     (first.test.ts)\n        onTestCaseReady     (first.test.ts) |first test case|\n        onTestCaseResult    (first.test.ts) |first test case|\n      onTestModuleEnd       (first.test.ts)\n\n      onTestModuleQueued    (second.test.ts)\n      onTestModuleCollected (second.test.ts)\n      onTestModuleStart     (second.test.ts)\n        onTestCaseReady     (second.test.ts) |second test case|\n        onTestCaseResult    (second.test.ts) |second test case|\n      onTestModuleEnd       (second.test.ts)\"\n    `)\n  })\n\n  test('test modules with delay', async () => {\n    const report = await run({\n      'first.test.ts': ts`\n        ${delay()}\n        test('first test case', async () => { ${delay()} });\n      `,\n      'second.test.ts': ts`\n      ${delay()}\n      test('second test case', async () => { ${delay()} });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (first.test.ts)\n      onTestModuleCollected (first.test.ts)\n      onTestModuleStart     (first.test.ts)\n        onTestCaseReady     (first.test.ts) |first test case|\n        onTestCaseResult    (first.test.ts) |first test case|\n      onTestModuleEnd       (first.test.ts)\n\n      onTestModuleQueued    (second.test.ts)\n      onTestModuleCollected (second.test.ts)\n      onTestModuleStart     (second.test.ts)\n        onTestCaseReady     (second.test.ts) |second test case|\n        onTestCaseResult    (second.test.ts) |second test case|\n      onTestModuleEnd       (second.test.ts)\"\n    `)\n  })\n})\n\ndescribe('TestCase', () => {\n  test('single test case', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        test('single test case', async () => {\n          await new Promise(resolve => setTimeout(resolve, 300))\n          console.log(\"Test running!\")\n        });\n      `,\n    }, {}, { printTestRunEvents: true })\n\n    // console.log is reported outside of the test run cycle\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestRunStart (1 specifications)\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |single test case|\n        onTestCaseResult    (example.test.ts) |single test case|\n      onTestModuleEnd       (example.test.ts)\n\n      onTestRunEnd   (passed, 1 modules, 0 errors)\n\n      onUserConsoleLog (example.test.ts) |single test case| > Test running!\"\n    `)\n  })\n\n  test('multiple test cases', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        test('first', () => {});\n        test('second', () => {});\n        test('third', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |first|\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n        onTestCaseResult    (example.test.ts) |second|\n        onTestCaseReady     (example.test.ts) |third|\n        onTestCaseResult    (example.test.ts) |third|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('multiple test cases with delay', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        ${delay()}\n        test('first', async () => { ${delay()} });\n        test('second', async () => { ${delay()} });\n        test('third', async () => { ${delay()} });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |first|\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n        onTestCaseResult    (example.test.ts) |second|\n        onTestCaseReady     (example.test.ts) |third|\n        onTestCaseResult    (example.test.ts) |third|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('failing test case', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        test('failing test case', () => {\n          expect(1).toBe(2)\n        });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |failing test case|\n        onTestCaseResult    (example.test.ts) |failing test case|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('skipped test case', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        test('running', () => {});\n        test.skip('skipped', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |running|\n        onTestCaseResult    (example.test.ts) |running|\n        onTestCaseReady     (example.test.ts) |skipped|\n        onTestCaseResult    (example.test.ts) |skipped|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('skipped test case in a different order', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        test.skip('skipped', () => {});\n        test('running', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |skipped|\n        onTestCaseResult    (example.test.ts) |skipped|\n        onTestCaseReady     (example.test.ts) |running|\n        onTestCaseResult    (example.test.ts) |running|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('skipped test case in a suite with a different order', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        describe('suite', () => {\n          test.skip('skipped', () => {});\n          test('running', () => {});\n        })\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |suite|\n          onTestCaseReady   (example.test.ts) |skipped|\n          onTestCaseResult  (example.test.ts) |skipped|\n          onTestCaseReady   (example.test.ts) |running|\n          onTestCaseResult  (example.test.ts) |running|\n        onTestSuiteResult   (example.test.ts) |suite|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('dynamically skipped test case', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        test('running', () => {});\n        test('skipped', (ctx) => { ctx.skip() });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |running|\n        onTestCaseResult    (example.test.ts) |running|\n        onTestCaseReady     (example.test.ts) |skipped|\n        onTestCaseResult    (example.test.ts) |skipped|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('skipped all test cases', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        test.skip('first', () => {});\n        test.skip('second', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |first|\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n        onTestCaseResult    (example.test.ts) |second|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n})\n\ndescribe('TestSuite', () => {\n  test('single test suite', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        describe(\"example suite\", () => {\n          test('first test case', () => {});\n        });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |example suite|\n          onTestCaseReady   (example.test.ts) |first test case|\n          onTestCaseResult  (example.test.ts) |first test case|\n        onTestSuiteResult   (example.test.ts) |example suite|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('multiple test suites', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        describe(\"first suite\", () => {\n          test('first test case', () => {});\n        });\n\n        describe(\"second suite\", () => {\n          test('second test case', () => {});\n        });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |first suite|\n          onTestCaseReady   (example.test.ts) |first test case|\n          onTestCaseResult  (example.test.ts) |first test case|\n        onTestSuiteResult   (example.test.ts) |first suite|\n        onTestSuiteReady    (example.test.ts) |second suite|\n          onTestCaseReady   (example.test.ts) |second test case|\n          onTestCaseResult  (example.test.ts) |second test case|\n        onTestSuiteResult   (example.test.ts) |second suite|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('multiple test suites with delay', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        ${delay()}\n        describe(\"first suite\", async () => {\n          ${delay()}\n          test('first test case', async () => { ${delay()} });\n        });\n\n        describe(\"second suite\", async () => {\n          ${delay()}\n          test('second test case', async () => { ${delay()} });\n        });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |first suite|\n          onTestCaseReady   (example.test.ts) |first test case|\n          onTestCaseResult  (example.test.ts) |first test case|\n        onTestSuiteResult   (example.test.ts) |first suite|\n        onTestSuiteReady    (example.test.ts) |second suite|\n          onTestCaseReady   (example.test.ts) |second test case|\n          onTestCaseResult  (example.test.ts) |second test case|\n        onTestSuiteResult   (example.test.ts) |second suite|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('nested test suites', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        describe(\"first suite\", () => {\n          test('first test case', () => {});\n\n          describe(\"second suite\", () => {\n            test('second test case', () => {});\n\n            describe(\"third suite\", () => {\n              test('third test case', () => {});\n            });\n          });\n        });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |first suite|\n          onTestCaseReady   (example.test.ts) |first test case|\n          onTestCaseResult  (example.test.ts) |first test case|\n          onTestSuiteReady  (example.test.ts) |second suite|\n            onTestCaseReady (example.test.ts) |second test case|\n            onTestCaseResult (example.test.ts) |second test case|\n            onTestSuiteReady (example.test.ts) |third suite|\n              onTestCaseReady (example.test.ts) |third test case|\n              onTestCaseResult (example.test.ts) |third test case|\n            onTestSuiteResult (example.test.ts) |third suite|\n          onTestSuiteResult (example.test.ts) |second suite|\n        onTestSuiteResult   (example.test.ts) |first suite|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('skipped test suite', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        describe.skip(\"skipped suite\", () => {\n          test('first test case', () => {});\n        });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |skipped suite|\n          onTestCaseReady   (example.test.ts) |first test case|\n          onTestCaseResult  (example.test.ts) |first test case|\n        onTestSuiteResult   (example.test.ts) |skipped suite|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('skipped double nested test suite', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        describe.skip(\"skipped suite\", () => {\n          describe.skip(\"nested skipped suite\", () => {\n            test('first nested case', () => {});\n          })\n        });\n\n        test('first test case', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |skipped suite|\n          onTestSuiteReady  (example.test.ts) |nested skipped suite|\n            onTestCaseReady (example.test.ts) |first nested case|\n            onTestCaseResult (example.test.ts) |first nested case|\n          onTestSuiteResult (example.test.ts) |nested skipped suite|\n        onTestSuiteResult   (example.test.ts) |skipped suite|\n        onTestCaseReady     (example.test.ts) |first test case|\n        onTestCaseResult    (example.test.ts) |first test case|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('skipped nested test suite', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        describe(\"first suite\", () => {\n          test('first test case', () => {});\n\n          describe.skip(\"skipped suite\", () => {\n            test('second test case', () => {});\n          });\n        });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |first suite|\n          onTestCaseReady   (example.test.ts) |first test case|\n          onTestCaseResult  (example.test.ts) |first test case|\n          onTestSuiteReady  (example.test.ts) |skipped suite|\n            onTestCaseReady (example.test.ts) |second test case|\n            onTestCaseResult (example.test.ts) |second test case|\n          onTestSuiteResult (example.test.ts) |skipped suite|\n        onTestSuiteResult   (example.test.ts) |first suite|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n})\n\ndescribe('hooks', () => {\n  test('beforeEach', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        beforeEach(() => {});\n\n        test('first', () => {});\n        test('second', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |first|\n          onHookStart       (example.test.ts) |first| [beforeEach]\n          onHookEnd         (example.test.ts) |first| [beforeEach]\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n          onHookStart       (example.test.ts) |second| [beforeEach]\n          onHookEnd         (example.test.ts) |second| [beforeEach]\n        onTestCaseResult    (example.test.ts) |second|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('afterEach', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        afterEach(() => {});\n\n        test('first', () => {});\n        test('second', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |first|\n          onHookStart       (example.test.ts) |first| [afterEach]\n          onHookEnd         (example.test.ts) |first| [afterEach]\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n          onHookStart       (example.test.ts) |second| [afterEach]\n          onHookEnd         (example.test.ts) |second| [afterEach]\n        onTestCaseResult    (example.test.ts) |second|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('beforeEach and afterEach', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        beforeEach(() => {});\n        afterEach(() => {});\n\n        test('first', () => {});\n        test('second', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |first|\n          onHookStart       (example.test.ts) |first| [beforeEach]\n          onHookEnd         (example.test.ts) |first| [beforeEach]\n          onHookStart       (example.test.ts) |first| [afterEach]\n          onHookEnd         (example.test.ts) |first| [afterEach]\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n          onHookStart       (example.test.ts) |second| [beforeEach]\n          onHookEnd         (example.test.ts) |second| [beforeEach]\n          onHookStart       (example.test.ts) |second| [afterEach]\n          onHookEnd         (example.test.ts) |second| [afterEach]\n        onTestCaseResult    (example.test.ts) |second|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('beforeAll', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        beforeAll(() => {});\n\n        test('first', () => {});\n        test('second', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onHookStart         (example.test.ts) [beforeAll]\n        onHookEnd           (example.test.ts) [beforeAll]\n        onTestCaseReady     (example.test.ts) |first|\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n        onTestCaseResult    (example.test.ts) |second|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('afterAll', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        afterAll(() => {});\n\n        test('first', () => {});\n        test('second', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |first|\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n        onTestCaseResult    (example.test.ts) |second|\n        onHookStart         (example.test.ts) [afterAll]\n        onHookEnd           (example.test.ts) [afterAll]\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('beforeAll and afterAll', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        beforeAll(() => {});\n        afterAll(() => {});\n\n        test('first', () => {});\n        test('second', () => {});\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onHookStart         (example.test.ts) [beforeAll]\n        onHookEnd           (example.test.ts) [beforeAll]\n        onTestCaseReady     (example.test.ts) |first|\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n        onTestCaseResult    (example.test.ts) |second|\n        onHookStart         (example.test.ts) [afterAll]\n        onHookEnd           (example.test.ts) [afterAll]\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('all hooks with delay', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        ${delay()}\n        beforeAll(async () => { ${delay()} });\n        afterAll(async () => { ${delay()} });\n        beforeEach(async () => { ${delay()} });\n        afterEach(async () => { ${delay()} });\n\n        test('first', async () => { ${delay()} });\n        test('second', async () => { ${delay()} });\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onHookStart         (example.test.ts) [beforeAll]\n        onHookEnd           (example.test.ts) [beforeAll]\n        onTestCaseReady     (example.test.ts) |first|\n          onHookStart       (example.test.ts) |first| [beforeEach]\n          onHookEnd         (example.test.ts) |first| [beforeEach]\n          onHookStart       (example.test.ts) |first| [afterEach]\n          onHookEnd         (example.test.ts) |first| [afterEach]\n        onTestCaseResult    (example.test.ts) |first|\n        onTestCaseReady     (example.test.ts) |second|\n          onHookStart       (example.test.ts) |second| [beforeEach]\n          onHookEnd         (example.test.ts) |second| [beforeEach]\n          onHookStart       (example.test.ts) |second| [afterEach]\n          onHookEnd         (example.test.ts) |second| [afterEach]\n        onTestCaseResult    (example.test.ts) |second|\n        onHookStart         (example.test.ts) [afterAll]\n        onHookEnd           (example.test.ts) [afterAll]\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('beforeAll on suite', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        describe(\"example\", () => {\n          beforeAll(() => {});\n\n          test('first', () => {});\n          test('second', () => {});\n        })\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |example|\n          onHookStart       (example.test.ts) |example| [beforeAll]\n          onHookEnd         (example.test.ts) |example| [beforeAll]\n          onTestCaseReady   (example.test.ts) |first|\n          onTestCaseResult  (example.test.ts) |first|\n          onTestCaseReady   (example.test.ts) |second|\n          onTestCaseResult  (example.test.ts) |second|\n        onTestSuiteResult   (example.test.ts) |example|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('afterAll on suite', async () => {\n    const report = await run({\n      'example.test.ts': ts`\n        describe(\"example\", () => {\n          afterAll(() => {});\n\n          test('first', () => {});\n          test('second', () => {});\n        })\n      `,\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestSuiteReady    (example.test.ts) |example|\n          onTestCaseReady   (example.test.ts) |first|\n          onTestCaseResult  (example.test.ts) |first|\n          onTestCaseReady   (example.test.ts) |second|\n          onTestCaseResult  (example.test.ts) |second|\n          onHookStart       (example.test.ts) |example| [afterAll]\n          onHookEnd         (example.test.ts) |example| [afterAll]\n        onTestSuiteResult   (example.test.ts) |example|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n})\n\ndescribe('merge reports', () => {\n  test('correctly reports events for a single test module', async () => {\n    const blobsOutputDirectory = resolve(import.meta.dirname, 'fixtures-blobs')\n    const blobOutputFile = resolve(blobsOutputDirectory, 'blob.json')\n    onTestFinished(() => {\n      rmSync(blobOutputFile)\n    })\n\n    const { root } = await runInlineTests({\n      'example.test.ts': ts`\n        test('first', () => {});\n        describe('suite', () => {\n          test('second', () => {});\n        });\n      `,\n    }, {\n      globals: true,\n      reporters: [['blob', { outputFile: blobOutputFile }]],\n    })\n\n    const report = await run(\n      {},\n      {\n        mergeReports: blobsOutputDirectory,\n      },\n      {\n        roots: [root],\n      },\n    )\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example.test.ts)\n      onTestModuleCollected (example.test.ts)\n      onTestModuleStart     (example.test.ts)\n        onTestCaseReady     (example.test.ts) |first|\n        onTestCaseResult    (example.test.ts) |first|\n        onTestSuiteReady    (example.test.ts) |suite|\n          onTestCaseReady   (example.test.ts) |second|\n          onTestCaseResult  (example.test.ts) |second|\n        onTestSuiteResult   (example.test.ts) |suite|\n      onTestModuleEnd       (example.test.ts)\"\n    `)\n  })\n\n  test('correctly reports multiple test modules', async () => {\n    const blobsOutputDirectory = resolve(import.meta.dirname, 'fixtures-blobs')\n    const blobOutputFile1 = resolve(blobsOutputDirectory, 'blob-1.json')\n    const blobOutputFile2 = resolve(blobsOutputDirectory, 'blob-2.json')\n    onTestFinished(() => {\n      rmSync(blobOutputFile1)\n      rmSync(blobOutputFile2)\n    })\n\n    const { root: root1 } = await runInlineTests({\n      'example-1.test.ts': ts`\n        test('first', () => {});\n        describe('suite', () => {\n          test('second', () => {});\n        });\n      `,\n    }, {\n      globals: true,\n      reporters: [['blob', { outputFile: blobOutputFile1 }]],\n      watch: false,\n    })\n\n    const { root: root2 } = await runInlineTests({\n      'example-2.test.ts': ts`\n        test('first', () => {});\n        describe.skip('suite', () => {\n          test('second', () => {});\n          test('third', () => {});\n        });\n        test.skip('fourth', () => {});\n        test('fifth', () => {});\n        `,\n    }, {\n      globals: true,\n      reporters: [['blob', { outputFile: blobOutputFile2 }]],\n      watch: false,\n    })\n\n    const report = await run({}, {\n      mergeReports: blobsOutputDirectory,\n      watch: false,\n    }, {\n      roots: [root1, root2],\n    })\n\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestModuleQueued    (example-1.test.ts)\n      onTestModuleCollected (example-1.test.ts)\n      onTestModuleStart     (example-1.test.ts)\n        onTestCaseReady     (example-1.test.ts) |first|\n        onTestCaseResult    (example-1.test.ts) |first|\n        onTestSuiteReady    (example-1.test.ts) |suite|\n          onTestCaseReady   (example-1.test.ts) |second|\n          onTestCaseResult  (example-1.test.ts) |second|\n        onTestSuiteResult   (example-1.test.ts) |suite|\n      onTestModuleEnd       (example-1.test.ts)\n\n      onTestModuleQueued    (example-2.test.ts)\n      onTestModuleCollected (example-2.test.ts)\n      onTestModuleStart     (example-2.test.ts)\n        onTestCaseReady     (example-2.test.ts) |first|\n        onTestCaseResult    (example-2.test.ts) |first|\n        onTestSuiteReady    (example-2.test.ts) |suite|\n          onTestCaseReady   (example-2.test.ts) |second|\n          onTestCaseResult  (example-2.test.ts) |second|\n          onTestCaseReady   (example-2.test.ts) |third|\n          onTestCaseResult  (example-2.test.ts) |third|\n        onTestSuiteResult   (example-2.test.ts) |suite|\n        onTestCaseReady     (example-2.test.ts) |fourth|\n        onTestCaseResult    (example-2.test.ts) |fourth|\n        onTestCaseReady     (example-2.test.ts) |fifth|\n        onTestCaseResult    (example-2.test.ts) |fifth|\n      onTestModuleEnd       (example-2.test.ts)\"\n    `)\n  })\n})\n\ndescribe('type checking', () => {\n  test('typechecking is reported correctly', async () => {\n    const report = await run({\n      'example-1.test-d.ts': ts`\n        test('first', () => {});\n        describe('suite', () => {\n          test('second', () => {});\n        });\n      `,\n      'example-2.test-d.ts': ts`\n        test('first', () => {});\n        describe.skip('suite', () => {\n          test('second', () => {});\n          test('third', () => {});\n        });\n        test.skip('fourth', () => {});\n        test('fifth', () => {});\n      `,\n      'tsconfig.json': JSON.stringify({\n        compilerOptions: {\n          strict: true,\n        },\n        include: ['./*.test-d.ts'],\n      }),\n    }, {\n      typecheck: {\n        enabled: true,\n      },\n    }, { printTestRunEvents: true })\n\n    // NOTE: typechecker reports test modules in bulk, so the order of queued and collect\n    // is different from the normal test run, this is because the typechecker runs everything together\n    // this _might_ need to be changed in the future\n    expect(report).toMatchInlineSnapshot(`\n      \"\n      onTestRunStart (2 specifications)\n      onTestModuleQueued    (example-1.test-d.ts)\n      onTestModuleQueued    (example-2.test-d.ts)\n      onTestModuleCollected (example-1.test-d.ts)\n      onTestModuleCollected (example-2.test-d.ts)\n      onTestModuleStart     (example-1.test-d.ts)\n        onTestCaseReady     (example-1.test-d.ts) |first|\n        onTestCaseResult    (example-1.test-d.ts) |first|\n        onTestSuiteReady    (example-1.test-d.ts) |suite|\n          onTestCaseReady   (example-1.test-d.ts) |second|\n          onTestCaseResult  (example-1.test-d.ts) |second|\n        onTestSuiteResult   (example-1.test-d.ts) |suite|\n      onTestModuleEnd       (example-1.test-d.ts)\n\n      onTestModuleStart     (example-2.test-d.ts)\n        onTestCaseReady     (example-2.test-d.ts) |first|\n        onTestCaseResult    (example-2.test-d.ts) |first|\n        onTestSuiteReady    (example-2.test-d.ts) |suite|\n          onTestCaseReady   (example-2.test-d.ts) |second|\n          onTestCaseResult  (example-2.test-d.ts) |second|\n          onTestCaseReady   (example-2.test-d.ts) |third|\n          onTestCaseResult  (example-2.test-d.ts) |third|\n        onTestSuiteResult   (example-2.test-d.ts) |suite|\n        onTestCaseReady     (example-2.test-d.ts) |fourth|\n        onTestCaseResult    (example-2.test-d.ts) |fourth|\n        onTestCaseReady     (example-2.test-d.ts) |fifth|\n        onTestCaseResult    (example-2.test-d.ts) |fifth|\n      onTestModuleEnd       (example-2.test-d.ts)\n\n      onTestRunEnd   (failed, 2 modules, 0 errors)\"\n    `)\n  })\n})\n\ndescribe('test run result', () => {\n  test('test run is interrupted', async () => {\n    let vitest: Vitest\n    let reason: TestRunEndReason | undefined\n\n    await runInlineTests({\n      'example.test.js': `\n        test('basic', () => new Promise(() => {}))\n      `,\n    }, {\n      globals: true,\n      reporters: [\n        {\n          onInit(ctx) {\n            vitest = ctx\n          },\n          onTestModuleCollected() {\n            vitest.cancelCurrentRun('keyboard-input')\n          },\n          onTestRunEnd(_, __, reason_) {\n            reason = reason_\n          },\n        },\n      ],\n    })\n\n    expect(reason).toBe('interrupted')\n  })\n\n  test('test run failed, but passed afterwards', async () => {\n    let reason: TestRunEndReason | undefined\n\n    const { fs } = await runInlineTests({\n      'example.test.js': `\n        test('basic', () => {\n          expect(1).toBe(2)\n        })\n      `,\n    }, {\n      globals: true,\n      watch: true,\n      reporters: [\n        {\n          onTestRunEnd(_, __, reason_) {\n            reason = reason_\n          },\n        },\n      ],\n    })\n\n    expect(reason).toBe('failed')\n\n    fs.editFile('./example.test.js', c => c.replace('toBe(2)', 'toBe(1)'))\n\n    await expect.poll(() => reason).toBe('passed')\n  })\n\n  test('test run passed', async () => {\n    let reason: TestRunEndReason | undefined\n\n    await runInlineTests({\n      'example.test.js': `\n        test('basic', () => {\n          expect(1).toBe(1)\n        })\n      `,\n    }, {\n      globals: true,\n      watch: true,\n      reporters: [\n        {\n          onTestRunEnd(_, __, reason_) {\n            reason = reason_\n          },\n        },\n      ],\n    })\n\n    expect(reason).toBe('passed')\n  })\n})\n\ninterface ReporterOptions {\n  printTestRunEvents?: boolean\n  roots?: string[]\n  failed?: boolean\n}\n\nasync function run(\n  structure: Parameters<typeof runInlineTests>[0],\n  customConfig?: TestUserConfig,\n  reporterOptions?: ReporterOptions,\n) {\n  const reporter = new CustomReporter(reporterOptions)\n\n  const config: TestUserConfig = {\n    config: false,\n    fileParallelism: false,\n    globals: true,\n    reporters: [reporter],\n    sequence: {\n      sequencer: class Sorter {\n        sort(files: TestSpecification[]) {\n          return files.sort((a, b) => a.moduleId.localeCompare(b.moduleId))\n        }\n\n        shard(files: TestSpecification[]) {\n          return files\n        }\n      },\n    },\n    ...customConfig,\n  }\n\n  const { stdout, stderr } = await runInlineTests(structure, config)\n\n  if (!reporterOptions?.printTestRunEvents && !reporterOptions?.failed) {\n    expect(stdout).toBe('')\n    expect(stderr).toBe('')\n  }\n\n  return `\\n${reporter.calls.join('\\n').trim()}`\n}\n\nclass CustomReporter implements Reporter {\n  calls: string[] = []\n  logs: string[] = []\n  ctx!: Vitest\n\n  constructor(private options: ReporterOptions = {}) {}\n\n  onInit(ctx: Vitest) {\n    this.ctx = ctx\n  }\n\n  onTestRunStart(specifications: ReadonlyArray<TestSpecification>) {\n    if (this.options.printTestRunEvents) {\n      this.calls.push(`onTestRunStart (${specifications.length} specifications)`)\n    }\n  }\n\n  onTestRunEnd(modules: ReadonlyArray<TestModule>, errors: ReadonlyArray<SerializedError>, state: TestRunEndReason) {\n    if (this.options.printTestRunEvents) {\n      this.calls.push(`onTestRunEnd   (${state}, ${modules.length} modules, ${errors.length} errors)`)\n      if (this.logs.length) {\n        this.calls.push('', ...this.logs)\n      }\n    }\n  }\n\n  onTestModuleQueued(module: TestModule) {\n    this.calls.push(`onTestModuleQueued    (${this.normalizeFilename(module)})`)\n  }\n\n  onTestModuleCollected(module: TestModule) {\n    this.calls.push(`onTestModuleCollected (${this.normalizeFilename(module)})`)\n  }\n\n  onTestSuiteReady(testSuite: TestSuite) {\n    this.calls.push(`${padded(testSuite, 'onTestSuiteReady')} (${this.normalizeFilename(testSuite.module)}) |${testSuite.name}|`)\n  }\n\n  onTestSuiteResult(testSuite: TestSuite) {\n    this.calls.push(`${padded(testSuite, 'onTestSuiteResult')} (${this.normalizeFilename(testSuite.module)}) |${testSuite.name}|`)\n  }\n\n  onTestModuleStart(module: TestModule) {\n    this.calls.push(`onTestModuleStart     (${this.normalizeFilename(module)})`)\n  }\n\n  onTestModuleEnd(module: TestModule) {\n    this.calls.push(`onTestModuleEnd       (${this.normalizeFilename(module)})\\n`)\n  }\n\n  onTestCaseReady(test: TestCase) {\n    this.calls.push(`${padded(test, 'onTestCaseReady')} (${this.normalizeFilename(test.module)}) |${test.name}|`)\n  }\n\n  onTestCaseResult(test: TestCase) {\n    this.calls.push(`${padded(test, 'onTestCaseResult')} (${this.normalizeFilename(test.module)}) |${test.name}|`)\n  }\n\n  onUserConsoleLog(log: UserConsoleLog) {\n    const task = this.ctx.state.idMap.get(log.taskId!)\n    const test = task && this.ctx.state.getReportedEntity(task) as TestCase\n\n    this.logs.push(`onUserConsoleLog (${this.normalizeFilename(test!.module)}) |${test!.name}| > ${log.content.replaceAll('\\n', '')}`)\n  }\n\n  onHookStart(hook: ReportedHookContext) {\n    const module = hook.entity.type === 'module' ? hook.entity : hook.entity.module\n    const name = hook.entity.type !== 'module' ? ` |${hook.entity.name}|` : ''\n    this.calls.push(`  ${padded(hook.entity, 'onHookStart', 19)} (${this.normalizeFilename(module)})${name} [${hook.name}]`)\n  }\n\n  onHookEnd(hook: ReportedHookContext) {\n    const module = hook.entity.type === 'module' ? hook.entity : hook.entity.module\n    const name = hook.entity.type !== 'module' ? ` |${hook.entity.name}|` : ''\n    this.calls.push(`  ${padded(hook.entity, 'onHookEnd', 19)} (${this.normalizeFilename(module)})${name} [${hook.name}]`)\n  }\n\n  normalizeFilename(module: TestModule) {\n    return normalizeFilename(module, this.options.roots)\n  }\n}\n\nfunction normalizeFilename(module: TestModule, roots?: string[]) {\n  const relative = (roots || [module.project.config.root]).reduce((acc, root) => {\n    return acc.replace(root, '')\n  }, module.moduleId)\n  return relative.replaceAll(sep, '/')\n    .substring(1)\n}\n\nfunction padded(entity: TestSuite | TestCase | TestModule, name: string, pad = 21) {\n  return (' '.repeat(getDepth(entity)) + name).padEnd(pad)\n}\n\nfunction getDepth(entity: TestSuite | TestCase | TestModule) {\n  if (entity.type === 'module') {\n    return 0\n  }\n\n  let depth = 0\n  let parent = entity.parent\n\n  while (parent) {\n    depth += 2\n    if (parent.type !== 'module') {\n      parent = parent.parent\n    }\n    else {\n      break\n    }\n  }\n\n  return depth\n}\n\nfunction delay() {\n  return `await new Promise(resolve => setTimeout(resolve, 100));`\n}\n"
  },
  {
    "path": "test/cli/test/reporters/tree.test.ts",
    "content": "import { runVitest, StableTestFileOrderSorter } from '#test-utils'\nimport { describe, expect, it } from 'vitest'\nimport { trimReporterOutput } from './utils'\n\ndescribe('tree reporter', () => {\n  it('reports a single test as a tree', async () => {\n    const { stdout } = await runVitest({\n      include: ['a.test.ts'],\n      root: 'fixtures/reporters/default',\n      reporters: ['tree'],\n    })\n\n    expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n      \"❯ a.test.ts (16 tests | 1 failed | 3 skipped) [...]ms\n         ✓ a passed (6)\n           ✓ a1 test [...]ms\n           ✓ a2 test [...]ms\n           ✓ a3 test [...]ms\n           ✓ nested a (3)\n             ✓ nested a1 test [...]ms\n             ✓ nested a2 test [...]ms\n             ✓ nested a3 test [...]ms\n         ❯ a failed (7)\n           ✓ a failed 1 test [...]ms\n           ✓ a failed 2 test [...]ms\n           ✓ a failed 3 test [...]ms\n           × a failed test [...]ms\n           ✓ nested a failed (3)\n             ✓ nested a failed 1 test [...]ms\n             ✓ nested a failed 2 test [...]ms\n             ✓ nested a failed 3 test [...]ms\n         ✓ a skipped (3)\n           ↓ skipped with note [...]ms [reason]\n           ↓ condition [...]ms\n           ↓ condition with note [...]ms [note]\"\n    `)\n  })\n\n  it('reports multiple tests when all passed with testname filter as a tree', async () => {\n    const { stdout } = await runVitest({\n      include: ['b1.test.ts', 'b2.test.ts'],\n      root: 'fixtures/reporters/default',\n      reporters: ['tree'],\n      fileParallelism: false,\n      testNamePattern: 'passed',\n      sequence: {\n        sequencer: StableTestFileOrderSorter,\n      },\n    })\n\n    expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n      \"✓ b1.test.ts (13 tests | 7 skipped) [...]ms\n         ✓ b1 passed (6)\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n           ✓ nested b (3)\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\n         ↓ b1 failed (7)\n           ↓ b1 test\n           ↓ b2 test\n           ↓ b3 test\n           ↓ b failed test\n           ↓ nested b (3)\n             ↓ nested b1 test\n             ↓ nested b2 test\n             ↓ nested b3 test\n       ✓ b2.test.ts (13 tests | 7 skipped) [...]ms\n         ✓ b2 passed (6)\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n           ✓ nested b (3)\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\n         ↓ b2 failed (7)\n           ↓ b1 test\n           ↓ b2 test\n           ↓ b3 test\n           ↓ b failed test\n           ↓ nested b (3)\n             ↓ nested b1 test\n             ↓ nested b2 test\n             ↓ nested b3 test\"\n    `)\n  })\n\n  it('reports multiple tests when some fail as a tree', async () => {\n    const { stdout } = await runVitest({\n      include: ['b1.test.ts', 'b2.test.ts'],\n      root: 'fixtures/reporters/default',\n      reporters: ['tree'],\n      fileParallelism: false,\n      sequence: {\n        sequencer: StableTestFileOrderSorter,\n      },\n    })\n\n    expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n      \"❯ b1.test.ts (13 tests | 1 failed) [...]ms\n         ✓ b1 passed (6)\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n           ✓ nested b (3)\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\n         ❯ b1 failed (7)\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n           × b failed test [...]ms\n           ✓ nested b (3)\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\n       ❯ b2.test.ts (13 tests | 1 failed) [...]ms\n         ✓ b2 passed (6)\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n           ✓ nested b (3)\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\n         ❯ b2 failed (7)\n           ✓ b1 test [...]ms\n           ✓ b2 test [...]ms\n           ✓ b3 test [...]ms\n           × b failed test [...]ms\n           ✓ nested b (3)\n             ✓ nested b1 test [...]ms\n             ✓ nested b2 test [...]ms\n             ✓ nested b3 test [...]ms\"\n    `)\n  })\n})\n"
  },
  {
    "path": "test/cli/test/reporters/utils.ts",
    "content": "import type { ModuleGraph, ViteDevServer } from 'vite'\nimport type { RunnerTestCase, RunnerTestSuite, TestError } from 'vitest'\nimport type { Vitest } from 'vitest/src/node/core.js'\nimport type { Logger } from 'vitest/src/node/logger.js'\nimport type { StateManager } from 'vitest/src/node/state.js'\nimport type { ResolvedConfig } from 'vitest/src/node/types/config.js'\nimport type { RunnerTestFile } from 'vitest/src/public/index.js'\nimport { createFileTask } from '@vitest/runner/utils'\n\nexport function trimReporterOutput(report: string) {\n  const rows = report.replace(/\\d+ms/g, '[...]ms').split('\\n')\n\n  // Trim start and end, capture just rendered tree\n  rows.splice(0, 1 + rows.findIndex(row => row.includes('RUN  v')))\n  rows.splice(rows.findIndex(row => row.includes('Test Files')))\n\n  return rows.join('\\n').trim()\n}\n\ninterface Context {\n  vitest: Vitest\n  output: string\n}\n\nexport function getContext(): Context {\n  let output = ''\n\n  const config: Partial<ResolvedConfig> = {\n    root: '/vitest',\n  }\n\n  const moduleGraph: Partial<ModuleGraph> = {\n    getModuleById: () => undefined,\n  }\n\n  const vite: Partial<ViteDevServer> = {\n    moduleGraph: moduleGraph as ModuleGraph,\n  }\n\n  const state: Partial<StateManager> = {\n    filesMap: new Map<string, RunnerTestFile[]>(),\n  }\n\n  const context: Partial<Vitest> = {\n    state: state as StateManager,\n    config: config as ResolvedConfig,\n    vite: vite as ViteDevServer,\n    getProjectByName: () => ({ getBrowserSourceMapModuleById: () => undefined }) as any,\n    snapshot: {\n      summary: { added: 100, _test: true },\n    } as any,\n  }\n\n  // @ts-expect-error logger is readonly\n  context.logger = {\n    ctx: context as Vitest,\n    log: (text: string) => output += `${text}\\n`,\n    highlight: () => {},\n  } as unknown as Logger\n\n  return {\n    vitest: context as Vitest,\n    get output() {\n      return output\n    },\n  }\n}\n\nconst file = createFileTask(\n  '/vitest/test/core/test/basic.test.ts',\n  '/vitest/test/core/test',\n  '',\n)\nfile.mode = 'run'\nfile.result = {\n  state: 'fail',\n  duration: 145.99284195899963,\n}\n\nconst suiteName = 'suite'\nconst suite: RunnerTestSuite = {\n  id: `${file.id}_0`,\n  type: 'suite',\n  name: suiteName,\n  fullName: `${file.fullName} > ${suiteName}`,\n  fullTestName: `${file.fullTestName} > ${suiteName}`,\n  mode: 'run',\n  meta: {},\n  file,\n  result: { state: 'pass', duration: 1.90183687210083 },\n  tasks: [],\n}\n\nconst passedFile = createFileTask(\n  '/vitest/test/core/test/basic.test.ts',\n  '/vitest/test/core/test',\n  '',\n)\npassedFile.mode = 'run'\npassedFile.result = { state: 'pass', duration: 145.99284195899963 }\npassedFile.tasks.push({\n  id: `${file.id}_1`,\n  type: 'test',\n  name: 'Math.sqrt()',\n  fullName: `${suite.fullName} > Math.sqrt()`,\n  fullTestName: `${suite.fullTestName} > Math.sqrt()`,\n  mode: 'run',\n  fails: undefined,\n  suite,\n  meta: {},\n  file: passedFile,\n  timeout: 0,\n  annotations: [],\n  artifacts: [],\n  result: {\n    state: 'pass',\n    duration: 1.4422860145568848,\n  },\n  context: null as any,\n})\n\nconst error: TestError = {\n  name: 'AssertionError',\n  message: 'expected 2.23606797749979 to equal 2',\n  actual: '2.23606797749979',\n  expected: '2',\n  operator: 'strictEqual',\n  stacks: undefined!,\n}\nerror.showDiff = true\nerror.stack = 'AssertionError: expected 2.23606797749979 to equal 2\\n'\n  + '    at /vitest/test/core/test/basic.test.ts:8:32\\n'\n  + '    at /vitest/packages/vitest/dist/vi-ac0504aa.js:73:26\\n'\n  + '    at runTest (/vitest/packages/vitest/dist/entry.js:1689:40)\\n'\n  + '    at async runSuite (/vitest/packages/vitest/dist/entry.js:1741:13)\\n'\n  + '    at async runSuites (/vitest/packages/vitest/dist/entry.js:1769:5)\\n'\n  + '    at async startTests (/vitest/packages/vitest/dist/entry.js:1774:3)\\n'\n  + '    at async /vitest/packages/vitest/dist/entry.js:1798:7\\n'\n  + '    at async withEnv (/vitest/packages/vitest/dist/entry.js:1481:5)\\n'\n  + '    at async run (/vitest/packages/vitest/dist/entry.js:1797:5)\\n'\n  + '    at async file:///vitest/node_modules/.pnpm/tinypool@0.1.1/node_modules/tinypool/dist/esm/worker.js:96:20'\n\nconst tasks: RunnerTestCase[] = [\n  {\n    id: `${suite.id}_0`,\n    type: 'test',\n    name: 'Math.sqrt()',\n    fullName: `${suite.fullName} > Math.sqrt()`,\n    fullTestName: `${suite.fullTestName} > Math.sqrt()`,\n    mode: 'run',\n    fails: undefined,\n    meta: {},\n    file,\n    suite,\n    annotations: [],\n    artifacts: [],\n    result: {\n      state: 'fail',\n      errors: [error],\n      duration: 1.4422860145568848,\n    },\n    location: {\n      column: 32,\n      line: 8,\n    },\n    timeout: 0,\n    context: null as any,\n  },\n  {\n    id: `${suite.id}_1`,\n    type: 'test',\n    name: 'JSON',\n    fullName: `${suite.fullName} > JSON`,\n    fullTestName: `${suite.fullTestName} > JSON`,\n    mode: 'run',\n    annotations: [],\n    artifacts: [],\n    suite,\n    fails: undefined,\n    timeout: 0,\n    meta: {},\n    file,\n    result: { state: 'pass', duration: 1.0237109661102295 },\n    context: null as any,\n  },\n  {\n    id: `${suite.id}_3`,\n    type: 'test',\n    name: 'async with timeout',\n    fullName: `${suite.fullName} > async with timeout`,\n    fullTestName: `${suite.fullTestName} > async with timeout`,\n    mode: 'skip',\n    suite,\n    fails: undefined,\n    meta: {},\n    timeout: 0,\n    file,\n    annotations: [],\n    artifacts: [],\n    result: undefined,\n    context: null as any,\n  },\n  {\n    id: `${suite.id}_4`,\n    type: 'test',\n    name: 'timeout',\n    fullName: `${suite.fullName} > timeout`,\n    fullTestName: `${suite.fullTestName} > timeout`,\n    annotations: [],\n    artifacts: [],\n    mode: 'run',\n    suite,\n    fails: undefined,\n    meta: {},\n    timeout: 0,\n    file,\n    result: { state: 'pass', duration: 100.50598406791687 },\n    context: null as any,\n  },\n  {\n    id: `${suite.id}_5`,\n    type: 'test',\n    name: 'callback setup success ',\n    fullName: `${suite.fullName} > callback setup success `,\n    fullTestName: `${suite.fullTestName} > callback setup success `,\n    mode: 'run',\n    suite,\n    fails: undefined,\n    annotations: [],\n    artifacts: [],\n    meta: {},\n    timeout: 0,\n    file,\n    result: { state: 'pass', duration: 20.184875011444092 },\n    context: null as any,\n  },\n  {\n    id: `${suite.id}_6`,\n    type: 'test',\n    name: 'callback test success ',\n    fullName: `${suite.fullName} > callback test success `,\n    fullTestName: `${suite.fullTestName} > callback test success `,\n    mode: 'run',\n    suite,\n    fails: undefined,\n    meta: {},\n    timeout: 0,\n    annotations: [],\n    artifacts: [],\n    file,\n    result: { state: 'pass', duration: 0.33245420455932617 },\n    context: null as any,\n  },\n  {\n    id: `${suite.id}_7`,\n    type: 'test',\n    name: 'callback setup success done(false)',\n    fullName: `${suite.fullName} > callback setup success done(false)`,\n    fullTestName: `${suite.fullTestName} > callback setup success done(false)`,\n    mode: 'run',\n    suite,\n    fails: undefined,\n    annotations: [],\n    artifacts: [],\n    meta: {},\n    timeout: 0,\n    file,\n    result: { state: 'pass', duration: 19.738605976104736 },\n    context: null as any,\n  },\n  {\n    id: `${suite.id}_8`,\n    type: 'test',\n    name: 'callback test success done(false)',\n    fullName: `${suite.fullName} > callback test success done(false)`,\n    fullTestName: `${suite.fullTestName} > callback test success done(false)`,\n    mode: 'run',\n    suite,\n    fails: undefined,\n    annotations: [],\n    artifacts: [],\n    meta: {},\n    timeout: 0,\n    file,\n    result: { state: 'pass', duration: 0.1923508644104004 },\n    context: null as any,\n    logs: [\n      {\n        content: '\u001b[33merror\u001b[39m',\n        type: 'stderr',\n        time: 1642587001759,\n        size: 15,\n      },\n    ],\n  },\n  {\n    id: `${suite.id}_9`,\n    type: 'test',\n    name: 'todo test',\n    fullName: `${suite.fullName} > todo test`,\n    fullTestName: `${suite.fullTestName} > todo test`,\n    mode: 'todo',\n    suite,\n    timeout: 0,\n    fails: undefined,\n    annotations: [],\n    artifacts: [],\n    meta: {},\n    file,\n    result: undefined,\n    context: null as any,\n  },\n]\n\nfile.tasks = [suite]\nsuite.tasks = tasks\n\nconst files = [file]\nconst passedFiles = [passedFile]\n\nexport { files, passedFiles }\n"
  },
  {
    "path": "test/cli/test/reporters/verbose.test.ts",
    "content": "import type { TestSpecification } from 'vitest/node'\nimport { runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest('duration', async () => {\n  const { stdout } = await runVitest({\n    root: 'fixtures/reporters/duration',\n    reporters: 'verbose',\n    env: { CI: '1' },\n  })\n\n  expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n    \"✓ basic.test.ts > fast [...]ms\n     ✓ basic.test.ts > slow [...]ms\"\n  `)\n})\n\ntest('prints error properties', async () => {\n  const result = await runVitest({\n    root: 'fixtures/reporters/error-props',\n    reporters: 'verbose',\n    env: { CI: '1' },\n  })\n\n  expect(result.stderr).toContain(`Serialized Error: { code: 404, status: 'not found' }`)\n})\n\ntest('prints skipped tests by default', async () => {\n  const { stdout } = await runVitest({\n    include: ['fixtures/reporters/pass-and-skip-test-suites.test.ts'],\n    reporters: [['verbose', { isTTY: true, summary: false }]],\n    config: false,\n  })\n\n  expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n    \"✓ fixtures/reporters/pass-and-skip-test-suites.test.ts > passing test #1 [...]ms\n     ✓ fixtures/reporters/pass-and-skip-test-suites.test.ts > passing suite > passing test #2 [...]ms\n     ↓ fixtures/reporters/pass-and-skip-test-suites.test.ts > skipped test #1\n     □ fixtures/reporters/pass-and-skip-test-suites.test.ts > todo test #1\n     ↓ fixtures/reporters/pass-and-skip-test-suites.test.ts > skipped suite > skipped test #2\"\n  `)\n})\n\ntest('hides skipped tests when --hideSkippedTests', async () => {\n  const { stdout } = await runVitest({\n    include: ['fixtures/reporters/pass-and-skip-test-suites.test.ts'],\n    reporters: [['verbose', { isTTY: true, summary: false }]],\n    hideSkippedTests: true,\n    config: false,\n  })\n\n  expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n    \"✓ fixtures/reporters/pass-and-skip-test-suites.test.ts > passing test #1 [...]ms\n     ✓ fixtures/reporters/pass-and-skip-test-suites.test.ts > passing suite > passing test #2 [...]ms\n     □ fixtures/reporters/pass-and-skip-test-suites.test.ts > todo test #1\"\n  `)\n})\n\ntest('prints retry count', async () => {\n  const { stdout } = await runVitest({\n    include: ['fixtures/reporters/retry.test.ts'],\n    reporters: [['verbose', { isTTY: true, summary: false }]],\n    retry: 3,\n    config: false,\n  })\n\n  expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\"✓ fixtures/reporters/retry.test.ts > pass after retries [...]ms (retry x3)\"`)\n})\n\ntest('prints repeat count', async () => {\n  const { stdout } = await runVitest({\n    include: ['fixtures/reporters/repeats.test.ts'],\n    reporters: [['verbose', { isTTY: true, summary: false }]],\n    config: false,\n  })\n\n  expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\"✓ fixtures/reporters/repeats.test.ts > repeat couple of times [...]ms (repeat x3)\"`)\n})\n\ntest('renders tests in a list', async () => {\n  const { stdout } = await runVitest({\n    include: ['fixtures/reporters/verbose/*.test.ts'],\n    reporters: [['verbose', { isTTY: false, summary: false }]],\n    config: false,\n    fileParallelism: false,\n    sequence: {\n      sequencer: class StableTestFileOrderSorter {\n        sort(files: TestSpecification[]) {\n          return files.sort((a, b) => a.moduleId.localeCompare(b.moduleId))\n        }\n\n        shard(files: TestSpecification[]) {\n          return files\n        }\n      },\n    },\n  })\n\n  expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n    \"✓ fixtures/reporters/verbose/example-1.test.ts > test pass in root [...]ms\n     ↓ fixtures/reporters/verbose/example-1.test.ts > test skip in root\n     ✓ fixtures/reporters/verbose/example-1.test.ts > suite in root > test pass in 1. suite #1 [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts > suite in root > test pass in 1. suite #2 [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts > suite in root > suite in suite > test pass in nested suite #1 [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts > suite in root > suite in suite > test pass in nested suite #2 [...]ms\n     × fixtures/reporters/verbose/example-1.test.ts > suite in root > suite in suite > suite in nested suite > test failure in 2x nested suite [...]ms\n       → expected 'should fail' to be 'as expected' // Object.is equality\n     ↓ fixtures/reporters/verbose/example-1.test.ts > suite skip in root > test 1.3\n     ↓ fixtures/reporters/verbose/example-1.test.ts > suite skip in root > suite in suite > test in nested suite\n     ↓ fixtures/reporters/verbose/example-1.test.ts > suite skip in root > suite in suite > test failure in nested suite of skipped suite\n     ✓ fixtures/reporters/verbose/example-2.test.ts > test 0.1 [...]ms\n     ↓ fixtures/reporters/verbose/example-2.test.ts > test 0.2\n     ✓ fixtures/reporters/verbose/example-2.test.ts > suite 1.1 > test 1.1 [...]ms\"\n  `)\n})\n\ntest('renders locations if enabled', async () => {\n  const { stdout } = await runVitest({\n    include: ['fixtures/reporters/verbose/*.test.ts'],\n    reporters: [['verbose', { isTTY: false, summary: false }]],\n    config: false,\n    includeTaskLocation: true,\n    fileParallelism: false,\n    sequence: {\n      sequencer: class StableTestFileOrderSorter {\n        sort(files: TestSpecification[]) {\n          return files.sort((a, b) => a.moduleId.localeCompare(b.moduleId))\n        }\n\n        shard(files: TestSpecification[]) {\n          return files\n        }\n      },\n    },\n  })\n\n  expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n    \"✓ fixtures/reporters/verbose/example-1.test.ts:3:1 > test pass in root [...]ms\n     ↓ fixtures/reporters/verbose/example-1.test.ts:5:6 > test skip in root\n     ✓ fixtures/reporters/verbose/example-1.test.ts:8:3 > suite in root > test pass in 1. suite #1 [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts:10:3 > suite in root > test pass in 1. suite #2 [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts:13:5 > suite in root > suite in suite > test pass in nested suite #1 [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts:15:5 > suite in root > suite in suite > test pass in nested suite #2 [...]ms\n     × fixtures/reporters/verbose/example-1.test.ts:18:7 > suite in root > suite in suite > suite in nested suite > test failure in 2x nested suite [...]ms\n       → expected 'should fail' to be 'as expected' // Object.is equality\n     ↓ fixtures/reporters/verbose/example-1.test.ts:26:3 > suite skip in root > test 1.3\n     ↓ fixtures/reporters/verbose/example-1.test.ts:29:5 > suite skip in root > suite in suite > test in nested suite\n     ↓ fixtures/reporters/verbose/example-1.test.ts:31:5 > suite skip in root > suite in suite > test failure in nested suite of skipped suite\n     ✓ fixtures/reporters/verbose/example-2.test.ts:3:1 > test 0.1 [...]ms\n     ↓ fixtures/reporters/verbose/example-2.test.ts:5:6 > test 0.2\n     ✓ fixtures/reporters/verbose/example-2.test.ts:8:3 > suite 1.1 > test 1.1 [...]ms\"\n  `)\n})\n\ntest('hides skipped tests when --hideSkippedTests and in non-TTY', async () => {\n  const { stdout } = await runVitest({\n    include: ['fixtures/reporters/verbose/*.test.ts'],\n    reporters: [['verbose', { isTTY: false, summary: false }]],\n    hideSkippedTests: true,\n    config: false,\n    fileParallelism: false,\n    sequence: {\n      sequencer: class StableTestFileOrderSorter {\n        sort(files: TestSpecification[]) {\n          return files.sort((a, b) => a.moduleId.localeCompare(b.moduleId))\n        }\n\n        shard(files: TestSpecification[]) {\n          return files\n        }\n      },\n    },\n  })\n\n  expect(trimReporterOutput(stdout)).toMatchInlineSnapshot(`\n    \"✓ fixtures/reporters/verbose/example-1.test.ts > test pass in root [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts > suite in root > test pass in 1. suite #1 [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts > suite in root > test pass in 1. suite #2 [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts > suite in root > suite in suite > test pass in nested suite #1 [...]ms\n     ✓ fixtures/reporters/verbose/example-1.test.ts > suite in root > suite in suite > test pass in nested suite #2 [...]ms\n     × fixtures/reporters/verbose/example-1.test.ts > suite in root > suite in suite > suite in nested suite > test failure in 2x nested suite [...]ms\n       → expected 'should fail' to be 'as expected' // Object.is equality\n     ✓ fixtures/reporters/verbose/example-2.test.ts > test 0.1 [...]ms\n     ✓ fixtures/reporters/verbose/example-2.test.ts > suite 1.1 > test 1.1 [...]ms\"\n  `)\n})\n\nfunction trimReporterOutput(report: string) {\n  const rows = report.replace(/\\d+ms/g, '[...]ms').split('\\n')\n\n  // Trim start and end, capture just rendered tree\n  rows.splice(0, 1 + rows.findIndex(row => row.includes('RUN  v')))\n  rows.splice(rows.findIndex(row => row.includes('Test Files')))\n\n  return rows.join('\\n').trim()\n}\n"
  },
  {
    "path": "test/cli/test/restricted-fs.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { runVitest } from '../../test-utils'\n\ntest('importing files in restricted fs works correctly', async () => {\n  const { stderr, exitCode } = await runVitest({\n    root: './fixtures/restricted-fs',\n  })\n\n  // It would fail if setupFile was not added to allowed fs\n  // Failed to load url fixtures/restricted-fs/vitest.setup.js\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/cli/test/retry-clear-mocks.test.ts",
    "content": "import type { TestCase } from 'vitest/node'\nimport { expect, it } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\nit('vitest correctly resets mocks between tests', async () => {\n  const { stderr, results } = await runInlineTests({\n    'basic.test.js': /* js */`\n      import { it, vi, expect } from 'vitest'\n      let i = 0\n      const mock = vi.fn(() => true)\n      it('mock resets', { retry: 3 }, () => {\n        i++\n        expect(mock()).toBe(true)\n        mock.mockImplementation(() => false)\n        if (i !== 4) {\n          throw new Error('retry')\n        }\n        expect(mock).toHaveBeenCalledOnce()\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        mockReset: true,\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  const testCase = results[0].children.at(0) as TestCase\n  expect(testCase.diagnostic()?.retryCount).toBe(3)\n})\n\nit('vitest correctly clears mocks between tests', async () => {\n  const { stderr, results } = await runInlineTests({\n    'basic.test.js': /* js */`\n      import { it, vi, expect } from 'vitest'\n      let i = 0\n      const mock = vi.fn()\n      it('mock resets', { retry: 3 }, () => {\n        i++\n        mock()\n        if (i !== 4) {\n          throw new Error('retry')\n        }\n        expect(mock).toHaveBeenCalledOnce()\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        clearMocks: true,\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  const testCase = results[0].children.at(0) as TestCase\n  expect(testCase.diagnostic()?.retryCount).toBe(3)\n})\n\nit('vitest correctly restores mocks between tests', async () => {\n  const { stderr, results } = await runInlineTests({\n    'basic.test.js': /* js */`\n      import { it, vi, expect } from 'vitest'\n      let i = 0\n      const obj = {\n        mock: () => true\n      }\n      const mock = vi.spyOn(obj, 'mock')\n      it('mock resets', { retry: 3 }, () => {\n        i++\n        expect(obj.mock()).toBe(true)\n        expect(vi.isMockFunction(obj.mock)).toBe(false)\n        mock.mockImplementation(() => false)\n        if (i !== 4) {\n          throw new Error('retry')\n        }\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        restoreMocks: true,\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  const testCase = results[0].children.at(0) as TestCase\n  expect(testCase.diagnostic()?.retryCount).toBe(3)\n})\n"
  },
  {
    "path": "test/cli/test/rollup-error.test.ts",
    "content": "import { runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\nimport { rolldownVersion } from 'vitest/node'\n\ntest('rollup error node', async () => {\n  const { stdout } = await runVitest({\n    root: './fixtures/rollup-error',\n    environment: 'node',\n    reporters: ['junit'],\n  })\n  if (rolldownVersion) {\n    expect(stdout).toContain('&quot;./no-such-export&quot; is not exported')\n    expect(stdout).toContain(`Plugin: builtin:vite-resolve`)\n  }\n  else {\n    expect(stdout).toContain(`Error: Missing &quot;./no-such-export&quot; specifier in &quot;vite&quot; package`)\n    expect(stdout).toContain(`Plugin: vite:import-analysis`)\n  }\n  expect(stdout).toContain(`Error: Cannot find package &apos;@vitejs/no-such-package&apos;`)\n})\n\ntest('rollup error web', async () => {\n  const { stdout } = await runVitest({\n    root: './fixtures/rollup-error',\n    environment: 'jsdom',\n    reporters: ['junit'],\n  })\n  if (rolldownVersion) {\n    expect(stdout).toContain('&quot;./no-such-export&quot; is not exported')\n    expect(stdout).toContain(`Plugin: builtin:vite-resolve`)\n  }\n  else {\n    expect(stdout).toContain(`Error: Missing &quot;./no-such-export&quot; specifier in &quot;vite&quot; package`)\n  }\n  expect(stdout).toContain(`Plugin: vite:import-analysis`)\n  expect(stdout).toContain(`Error: Failed to resolve import &quot;@vitejs/no-such-package&quot; from &quot;fixtures/rollup-error/not-found-package.test.ts&quot;. Does the file exist?`)\n})\n"
  },
  {
    "path": "test/cli/test/run-custom-env.test.ts",
    "content": "import { createRequire } from 'node:module'\nimport { expect, test } from 'vitest'\n\nimport { runVitest } from '../../test-utils'\n\ntest('correctly runs tests if custom env is a file', async () => {\n  const { stderr, exitCode } = await runVitest({\n    root: './fixtures/custom-file-env',\n    config: false,\n    environment: '../../custom.ts',\n    environmentOptions: {\n      custom: {\n        option: 'custom-option',\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n})\n\ntest('correctly runs tests if custom env is an absolute path', async () => {\n  const require = createRequire(import.meta.url)\n\n  const { stderr, exitCode } = await runVitest({\n    root: './fixtures/custom-file-env',\n    config: false,\n    environment: require.resolve('vitest-environment-custom'),\n    environmentOptions: {\n      custom: {\n        option: 'custom-option',\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/cli/test/scoped-fixtures.test.ts",
    "content": "import type { afterAll, beforeAll, ExpectStatic, expectTypeOf as ExpectTypeOfFn, SuiteAPI, TestAPI } from 'vitest'\nimport type { ViteUserConfig } from 'vitest/config'\nimport type { TestSpecification, TestUserConfig } from 'vitest/node'\nimport type { TestFsStructure } from '../../test-utils'\nimport { playwright } from '@vitest/browser-playwright'\nimport { beforeEach, describe, expect, test } from 'vitest'\nimport { rolldownVersion } from 'vitest/node'\nimport { runInlineTests, stripIndent } from '../../test-utils'\n\n// \"it\" is used inside subtests, we can't \"import\" it because vitest will inject __vite_ssr_import__\ndeclare const it: TestAPI\n\nif (rolldownVersion) {\n  beforeEach(({ skip }) => {\n    // TODO: remove skip when we only test against rolldown\n    // oxc has a different output of inlined functions in \"runInlineTests\"\n    // it keeps comments and formats the output\n    skip()\n  })\n}\n\ntest('test fixture cannot import from file fixture', async () => {\n  const { stderr } = await runInlineTests({\n    'basic.test.ts': () => {\n      const extendedTest = it.extend<{\n        file: string\n        local: string\n      }>({\n        local: ({}, use) => use('local'),\n        file: [({ local }, use) => use(local), { scope: 'file' }],\n      })\n\n      extendedTest('not working', ({ file: _file }) => {})\n    },\n  }, { globals: true })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts [ basic.test.ts ]\n    FixtureDependencyError: The file \"file\" fixture cannot depend on a test fixture \"local\".\n     ❯ basic.test.ts:2:27\n          1| await (() => {\n          2|   const extendedTest = it.extend({\n           |                           ^\n          3|     local: ({}, use) => use(\"local\"),\n          4|     file: [({ local }, use) => use(local), { scope: \"file\" }]\n     ❯ basic.test.ts:8:1\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('fixture returned without calling use', async () => {\n  const { stderr } = await runInlineTests({\n    'basic.test.ts': () => {\n      const extendedTest = it.extend<{\n        value: string | undefined\n        setup: void\n      }>({\n        value: undefined,\n        setup: [\n          async ({ value }, use) => {\n            if (!value) {\n              return\n            }\n            await use(undefined)\n          },\n          { auto: true },\n        ],\n      })\n\n      extendedTest('should fail with descriptive error', () => {})\n    },\n  }, { globals: true })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts > should fail with descriptive error\n    Error: Fixture \"setup\" returned without calling \"use\". Make sure to call \"use\" in every code path of the fixture function.\n     ❯ basic.test.ts:2:27\n          1| await (() => {\n          2|   const extendedTest = it.extend({\n           |                           ^\n          3|     value: void 0,\n          4|     setup: [\n     ❯ basic.test.ts:16:1\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('can import file fixture inside the local fixture', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{\n    file: string\n    local: string\n  }>({\n    local: async ({ file }, use) => {\n      log('init local')\n      await use(file)\n      log('teardown local')\n    },\n    file: [\n      async ({}, use) => {\n        log('init file')\n        await use('file')\n        log('teardown file')\n      },\n      { scope: 'file' },\n    ],\n  }), {\n    'basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test1', ({ local: _local }) => {})\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init file | test1\n    >> fixture | init local | test1\n    >> fixture | teardown local | test1\n    >> fixture | teardown file | test1\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > test1 <time>\"`)\n})\n\ntest('can import worker fixture inside the local fixture', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{\n    worker: string\n    local: string\n  }>({\n    local: async ({ worker }, use) => {\n      log('init local')\n      await use(worker)\n      log('teardown local')\n    },\n    worker: [\n      async ({}, use) => {\n        log('init worker')\n        await use('worker')\n        log('teardown worker')\n      },\n      { scope: 'worker' },\n    ],\n  }), {\n    'basic.test.ts': ({ extendedTest, expect }) => {\n      extendedTest('test1', ({ local }) => {\n        expect(local).toBe('worker')\n      })\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init worker | test1\n    >> fixture | init local | test1\n    >> fixture | teardown local | test1\n    >> fixture | teardown worker | test1\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > test1 <time>\"`)\n})\n\ntest('test fixture cannot import from worker fixture', async () => {\n  const { stderr } = await runInlineTests({\n    'basic.test.ts': () => {\n      const extendedTest = it.extend<{\n        worker: string\n        local: string\n      }>({\n        local: ({}, use) => use('local'),\n        worker: [\n          ({ local }, use) => use(local),\n          { scope: 'worker' },\n        ],\n      })\n\n      extendedTest('not working', ({ worker: _worker }) => {})\n    },\n  }, { globals: true })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts [ basic.test.ts ]\n    FixtureDependencyError: The worker \"worker\" fixture cannot depend on a test fixture \"local\".\n     ❯ basic.test.ts:2:27\n          1| await (() => {\n          2|   const extendedTest = it.extend({\n           |                           ^\n          3|     local: ({}, use) => use(\"local\"),\n          4|     worker: [\n     ❯ basic.test.ts:11:1\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('auto worker fixture is initialised always before the first test', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{ worker: string }>({\n    worker: [\n      async ({}, use) => {\n        log('init file')\n        await use('worker')\n        log('teardown file')\n      },\n      { scope: 'worker', auto: true },\n    ],\n  }), {\n    'basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test1', ({}) => {})\n      extendedTest('test2', ({}) => {})\n      extendedTest('test3', ({ worker: _worker }) => {})\n      extendedTest('test4', ({}) => {})\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init file | test1\n    >> fixture | teardown file | test4\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ basic.test.ts > test1 <time>\n     ✓ basic.test.ts > test2 <time>\n     ✓ basic.test.ts > test3 <time>\n     ✓ basic.test.ts > test4 <time>\"\n  `)\n})\n\ntest('worker fixture can import a static value from test fixture', async () => {\n  const { stderr } = await runFixtureTests(() => it.extend<{\n    worker: string\n    local: string\n  }>({\n    local: 'local',\n    worker: [\n      ({ local }, use) => use(local),\n      { scope: 'worker' },\n    ],\n  }), {\n    'basic.test.ts': ({ extendedTest, expect }) => {\n      extendedTest('working', ({ worker, local }) => {\n        expect(worker).toBe(local)\n        expect(worker).toBe('local')\n      })\n    },\n  }, { globals: true })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts [ basic.test.ts ]\n    FixtureDependencyError: The worker \"worker\" fixture cannot depend on a test fixture \"local\".\n     ❯ test.js:5:39\n          3| export const expect = globalThis.expect\n          4| export const expectTypeOf = globalThis.expectTypeOf\n          5| export const extendedTest = (() => it.extend({\n           |                                       ^\n          6|   local: \"local\",\n          7|   worker: [\n     ❯ test.js:11:4\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('file fixture cannot import a static value from test fixture', async () => {\n  const { stderr } = await runFixtureTests(() => it.extend<{\n    file: string\n    local: string\n  }>({\n    local: 'local',\n    file: [\n      ({ local }, use) => use(local),\n      { scope: 'file' },\n    ],\n  }), {\n    'basic.test.ts': ({ extendedTest, expect }) => {\n      extendedTest('working', ({ file, local }) => {\n        expect(file).toBe(local)\n        expect(file).toBe('local')\n      })\n    },\n  }, { globals: true })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts [ basic.test.ts ]\n    FixtureDependencyError: The file \"file\" fixture cannot depend on a test fixture \"local\".\n     ❯ test.js:5:39\n          3| export const expect = globalThis.expect\n          4| export const expectTypeOf = globalThis.expectTypeOf\n          5| export const extendedTest = (() => it.extend({\n           |                                       ^\n          6|   local: \"local\",\n          7|   file: [\n     ❯ test.js:11:4\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('worker fixture works in vmThreads and runs for every file', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{ worker: string }>({\n    worker: [\n      async ({}, use) => {\n        log('init worker')\n        await use('worker')\n        log('teardown worker')\n      },\n      { scope: 'worker' },\n    ],\n  }), {\n    '1-basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test1', ({ worker: _worker }) => {})\n    },\n    '2-basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test1', ({ worker: _worker }) => {})\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init worker | test1\n    >> fixture | teardown worker | test1\n    >> fixture | init worker | test1\n    >> fixture | teardown worker | test1\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ 1-basic.test.ts > test1 <time>\n     ✓ 2-basic.test.ts > test1 <time>\"\n  `)\n})\n\ntest('worker fixtures in isolated tests init and teardown twice', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{ worker: string }>({\n    worker: [\n      async ({}, use) => {\n        log('init worker')\n        await use('worker')\n        log('teardown worker')\n      },\n      { scope: 'worker' },\n    ],\n  }), {\n    '1-basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test1', ({ worker: _worker }) => {})\n    },\n    '2-basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test2', ({ worker: _worker }) => {})\n    },\n  }, {\n    globals: true,\n    maxWorkers: 1,\n    pool: 'vmThreads',\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init worker | test1\n    >> fixture | teardown worker | test1\n    >> fixture | init worker | test2\n    >> fixture | teardown worker | test2\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ 1-basic.test.ts > test1 <time>\n     ✓ 2-basic.test.ts > test2 <time>\"\n  `)\n})\n\ntest('worker fixture initiates and torn down in different workers', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{ worker: string }>({\n    worker: [\n      async ({}, use) => {\n        log('init worker')\n        await use('worker')\n        log('teardown worker')\n      },\n      { scope: 'worker' },\n    ],\n  }), {\n    '1-basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test1', ({ worker: _worker }) => {})\n    },\n    '2-basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test2', ({ worker: _worker }) => {})\n    },\n  }, {\n    globals: true,\n    isolate: false,\n    maxWorkers: 2,\n    pool: 'threads',\n  })\n\n  expect(stderr).toBe('')\n\n  // tests run in parallel so we can't guarantee the order\n  expect(fixtures).toContain(`>> fixture | init worker | test1`)\n  expect(fixtures).toContain(`>> fixture | teardown worker | test1`)\n\n  expect(fixtures).toContain(`>> fixture | init worker | test2`)\n  expect(fixtures).toContain(`>> fixture | teardown worker | test2`)\n\n  expect(tests).toContain(' ✓ 1-basic.test.ts > test1 <time>')\n  expect(tests).toContain(' ✓ 2-basic.test.ts > test2 <time>')\n})\n\ntest('worker fixture initiates and torn down in one non-isolated worker', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{ worker: string }>({\n    worker: [\n      async ({}, use) => {\n        log('init worker')\n        await use('worker')\n        log('teardown worker')\n      },\n      { scope: 'worker' },\n    ],\n  }), {\n    '1-basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test1', ({ worker: _worker }) => {})\n    },\n    '2-basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test1', ({ worker: _worker }) => {})\n    },\n  }, {\n    globals: true,\n    isolate: false,\n    maxWorkers: 1,\n    pool: 'threads',\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init worker | test1\n    >> fixture | teardown worker | test1\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ 1-basic.test.ts > test1 <time>\n     ✓ 2-basic.test.ts > test1 <time>\"\n  `)\n})\n\ntest('worker fixtures are available in beforeEach and afterEach', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{ worker: string }>({\n    worker: [\n      async ({}, use) => {\n        log('init worker')\n        await use('worker')\n        log('teardown worker')\n      },\n      { scope: 'worker' },\n    ],\n  }), {\n    'basic.test.ts': ({ extendedTest }) => {\n      extendedTest.beforeEach(({ worker }) => {\n        console.log('>> fixture | beforeEach |', worker)\n      })\n      extendedTest.afterEach(({ worker }) => {\n        console.log('>> fixture | afterEach |', worker)\n      })\n      extendedTest('test1', ({}) => {})\n      extendedTest('test2', ({}) => {})\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init worker | test1\n    >> fixture | beforeEach | worker\n    >> fixture | afterEach | worker\n    >> fixture | beforeEach | worker\n    >> fixture | afterEach | worker\n    >> fixture | teardown worker | test2\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ basic.test.ts > test1 <time>\n     ✓ basic.test.ts > test2 <time>\"\n  `)\n})\n\ntest('file fixtures are available in beforeEach and afterEach', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{\n    file: string\n  }>({\n    file: [\n      async ({}, use) => {\n        log('init file')\n        await use('file')\n        log('teardown file')\n      },\n      { scope: 'file' },\n    ],\n  }), {\n    'basic.test.ts': ({ extendedTest }) => {\n      extendedTest.beforeEach(({ file }) => {\n        console.log('>> fixture | beforeEach |', file)\n      })\n      extendedTest.afterEach(({ file }) => {\n        console.log('>> fixture | afterEach |', file)\n      })\n      extendedTest('test1', ({}) => {})\n      extendedTest('test2', ({}) => {})\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init file | test1\n    >> fixture | beforeEach | file\n    >> fixture | afterEach | file\n    >> fixture | beforeEach | file\n    >> fixture | afterEach | file\n    >> fixture | teardown file | test2\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ basic.test.ts > test1 <time>\n     ✓ basic.test.ts > test2 <time>\"\n  `)\n})\n\ntest('cannot access test level fixtures in aroundAll hook', async () => {\n  const { stderr } = await runFixtureTests(() => {\n    return it.extend('value', 'extended-value')\n  }, {\n    'basic.test.ts': ({ extendedTest }) => {\n      // @ts-expect-error value is a test fixture\n      extendedTest.aroundAll(async (runSuite, { value }) => {\n        console.log('>> fixture | aroundAll - setup |', value)\n        await runSuite()\n        console.log('>> fixture | aroundAll - teardown |', value)\n      })\n      extendedTest('test1', ({}) => {})\n    },\n  })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts [ basic.test.ts ]\n    FixtureDependencyError: Test-scoped fixtures cannot be used inside aroundAll hook. The following fixtures are test-scoped: \"value\". Use { scope: 'file' } or { scope: 'worker' } fixtures instead, or move the logic to aroundEach hook.\n     ❯ basic.test.ts:4:16\n          2| import { extendedTest, expect, expectTypeOf, describe, beforeAll, afte…\n          3| const results = await (({ extendedTest }) => {\n          4|   extendedTest.aroundAll(async (runSuite, { value }) => {\n           |                ^\n          5|     console.log(\">> fixture | aroundAll - setup |\", value);\n          6|     await runSuite();\n     ❯ basic.test.ts:11:1\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('extend fixtures are available in beforeAll and afterAll', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(() => {\n    return it.extend('value', { scope: 'file' }, 'extended-value')\n  }, {\n    'basic.test.ts': ({ extendedTest }) => {\n      // No need for override - extended fixtures should be available in hooks\n      extendedTest.beforeAll(({ value }) => {\n        console.log('>> fixture | beforeAll |', value)\n      })\n      extendedTest.afterAll(({ value }) => {\n        console.log('>> fixture | afterAll |', value)\n      })\n      extendedTest('test1', ({}) => {})\n      extendedTest('test2', ({}) => {})\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | beforeAll | extended-value\n    >> fixture | afterAll | extended-value\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ basic.test.ts > test1 <time>\n     ✓ basic.test.ts > test2 <time>\"\n  `)\n})\n\ntest('extend fixtures are available in aroundAll', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(() => {\n    return it.extend('value', { scope: 'file' }, 'extended-value')\n  }, {\n    'basic.test.ts': ({ extendedTest }) => {\n      // No need for override - extended fixtures should be available in hooks\n      extendedTest.aroundAll(async (runSuite, { value }) => {\n        console.log('>> fixture | aroundAll before |', value)\n        await runSuite()\n        console.log('>> fixture | aroundAll after |', value)\n      })\n      extendedTest('test1', ({}) => {})\n      extendedTest('test2', ({}) => {})\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | aroundAll before | extended-value\n    >> fixture | aroundAll after | extended-value\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ basic.test.ts > test1 <time>\n     ✓ basic.test.ts > test2 <time>\"\n  `)\n})\n\ntest('beforeAll/afterAll hooks receive file/worker fixtures, not test fixtures', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n    return it\n      .extend('staticValue', 'static-value')\n      .extend('fileValue', { scope: 'file' }, () => {\n        log('fileValue setup')\n        return 'file-scoped'\n      })\n      .extend('testValue', () => {\n        log('testValue setup')\n        return 'test-scoped'\n      })\n  }, {\n    'basic.test.ts': ({ extendedTest }) => {\n      extendedTest.beforeAll(({ fileValue }) => {\n        // staticValue and fileValue should be available\n        console.log('>> fixture | beforeAll | file:', fileValue)\n      })\n      extendedTest.afterAll(({ fileValue }) => {\n        console.log('>> fixture | afterAll | file:', fileValue)\n      })\n      extendedTest('test1', ({ fileValue, staticValue, testValue }) => {\n        console.log('>> fixture | test | static:', staticValue, 'file:', fileValue, 'test:', testValue)\n      })\n    },\n  })\n\n  expect(stderr).toBe('')\n  // Static and file fixtures are available in hooks\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | fileValue setup | undefined\n    >> fixture | beforeAll | file: file-scoped\n    >> fixture | testValue setup | test1\n    >> fixture | test | static: static-value file: file-scoped test: test-scoped\n    >> fixture | afterAll | file: file-scoped\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > test1 <time>\"`)\n})\n\ntest('beforeAll/afterAll hooks throw error when accessing test-scoped fixtures', async () => {\n  const { stderr } = await runFixtureTests(({ log }) => {\n    return it\n      .extend('fileValue', { scope: 'file' }, () => {\n        log('fileValue setup')\n        return 'file-scoped'\n      })\n      .extend('testValue', () => {\n        log('testValue setup')\n        return 'test-scoped'\n      })\n  }, {\n    'basic.test.ts': ({ extendedTest }) => {\n      extendedTest.beforeAll(({\n        fileValue: _fileValue,\n        // @ts-expect-error - test-scoped fixtures are not available in beforeAll\n        testValue: _testValue,\n      }) => {})\n      extendedTest('test1', ({}) => {})\n    },\n  })\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts [ basic.test.ts ]\n    FixtureDependencyError: Test-scoped fixtures cannot be used inside beforeAll hook. The following fixtures are test-scoped: \"testValue\". Use { scope: 'file' } or { scope: 'worker' } fixtures instead, or move the logic to beforeEach hook.\n     ❯ basic.test.ts:4:16\n          2| import { extendedTest, expect, expectTypeOf, describe, beforeAll, afte…\n          3| const results = await (({ extendedTest }) => {\n          4|   extendedTest.beforeAll(({\n           |                ^\n          5|     fileValue: _fileValue,\n          6|     // @ts-expect-error - test-scoped fixtures are not available in be…\n     ❯ basic.test.ts:12:1\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('global beforeAll/afterAll hooks throw error when accessing any fixture', async () => {\n  const { stderr, fixtures } = await runFixtureTests(({ log }) => {\n    return it\n      .extend('fileValue', { scope: 'file' }, () => {\n        log('fileValue setup')\n        return 'file-scoped'\n      })\n  }, {\n    'basic.test.ts': ({ extendedTest, beforeAll }) => {\n      beforeAll<{ fileValue: string }>(({\n        fileValue,\n      }) => {\n        console.log('>> fixture | beforeAll | file:', fileValue)\n      })\n      extendedTest('test1', ({}) => {})\n    },\n  })\n\n  expect(fixtures).toMatchInlineSnapshot(`\"\"`)\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts [ basic.test.ts ]\n    FixtureAccessError: The beforeAll hook uses fixtures \"fileValue\", but has no access to context. Did you forget to call it as \"test.beforeAll()\" instead of \"beforeAll()\"?\n    If you used internal \"suite\" task as the first argument previously, access it in the second argument instead. See https://vitest.dev/guide/test-context#suite-level-hooks\n     ❯ basic.test.ts:4:3\n          2| import { extendedTest, expect, expectTypeOf, describe, beforeAll, afte…\n          3| const results = await (({ extendedTest, beforeAll }) => {\n          4|   beforeAll(({\n           |   ^\n          5|     fileValue\n          6|   }) => {\n     ❯ basic.test.ts:11:1\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('global beforeAll/afterAll hooks throw error when accessing any fixture', async () => {\n  const { stderr, fixtures } = await runFixtureTests(({ log }) => {\n    return it\n      .extend('fileValue', { scope: 'file' }, () => {\n        log('fileValue setup')\n        return 'file-scoped'\n      })\n  }, {\n    'basic.test.ts': ({ extendedTest, beforeAll }) => {\n      beforeAll<{ fileValue: string }>((suite) => {\n        console.log('>> fixture | beforeAll | file:', suite.fileValue)\n      })\n      extendedTest('test1', ({}) => {})\n    },\n  })\n\n  expect(fixtures).toMatchInlineSnapshot(`\"\"`)\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts [ basic.test.ts ]\n    FixtureParseError: The 1st argument inside a fixture must use object destructuring pattern, e.g. ({ task } => {}). Instead, received \"suite\". If you used internal \"suite\" task as the 1st argument previously, access it in the 2nd argument instead.\n     ❯ basic.test.ts:4:3\n          2| import { extendedTest, expect, expectTypeOf, describe, beforeAll, afte…\n          3| const results = await (({ extendedTest, beforeAll }) => {\n          4|   beforeAll((suite) => {\n           |   ^\n          5|     console.log(\">> fixture | beforeAll | file:\", suite.fileValue);\n          6|   });\n     ❯ basic.test.ts:9:1\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('aroundAll hooks receive file/worker fixtures, not test fixtures', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n    return it\n      .extend('staticValue', 'static-value')\n      .extend('workerValue', { scope: 'worker' }, () => {\n        log('workerValue setup')\n        return 'worker-scoped'\n      })\n      .extend('testValue', () => {\n        log('testValue setup')\n        return 'test-scoped'\n      })\n  }, {\n    'basic.test.ts': ({ extendedTest }) => {\n      extendedTest.aroundAll(async (runSuite, { workerValue }) => {\n        // staticValue and workerValue should be available\n        console.log('>> fixture | aroundAll before | worker:', workerValue)\n        await runSuite()\n        console.log('>> fixture | aroundAll after | worker:', workerValue)\n      })\n      extendedTest('test1', ({ workerValue, staticValue, testValue }) => {\n        console.log('>> fixture | test | static:', staticValue, 'worker:', workerValue, 'test:', testValue)\n      })\n    },\n  })\n\n  expect(stderr).toBe('')\n  // Static and worker fixtures are available in hooks\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | workerValue setup | undefined\n    >> fixture | aroundAll before | worker: worker-scoped\n    >> fixture | testValue setup | test1\n    >> fixture | test | static: static-value worker: worker-scoped test: test-scoped\n    >> fixture | aroundAll after | worker: worker-scoped\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > test1 <time>\"`)\n})\n\ntest('test.override fixtures are scoped to their suite in beforeAll/afterAll', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(() => {\n    return it.extend('value', { scope: 'worker' }, 'default')\n  }, {\n    'basic.test.ts': ({ extendedTest, expect }) => {\n      // Override the value for this suite - the extended fixture is already\n      // available in hooks, but override changes the value\n      extendedTest.override('value', 'root')\n\n      extendedTest.beforeAll(({ value }) => {\n        console.log('>> fixture | root beforeAll |', value)\n      })\n      extendedTest.afterAll(({ value }) => {\n        console.log('>> fixture | root afterAll |', value)\n      })\n\n      extendedTest('root test', ({ value }) => {\n        expect(value).toBe('root')\n      })\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | root beforeAll | root\n    >> fixture | root afterAll | root\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > root test <time>\"`)\n})\n\ntest('test.override fixtures are scoped to their suite in beforeAll/afterAll when called after hooks', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(() => {\n    return it.extend('value', { scope: 'worker' }, 'default')\n  }, {\n    'basic.test.ts': ({ extendedTest, expect }) => {\n      extendedTest.beforeAll(({ value }) => {\n        console.log('>> fixture | root beforeAll |', value)\n      })\n      extendedTest.afterAll(({ value }) => {\n        console.log('>> fixture | root afterAll |', value)\n      })\n\n      extendedTest('root test', ({ value }) => {\n        expect(value).toBe('root')\n      })\n\n      // Override the value for this suite - the extended fixture is already\n      // available in hooks, but override changes the value\n      extendedTest.override('value', 'root')\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | root beforeAll | root\n    >> fixture | root afterAll | root\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > root test <time>\"`)\n})\n\ntest('all hooks receive suite as the last argument', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(() => {\n    return it.extend('value', { scope: 'file' }, 'test-value')\n  }, {\n    'basic.test.ts': ({ extendedTest, describe }) => {\n      extendedTest.beforeAll(({ value }, suite) => {\n        console.log('>> fixture | beforeAll suite:', suite.name, '| value:', value)\n      })\n      extendedTest.afterAll(({ value }, suite) => {\n        console.log('>> fixture | afterAll suite:', suite.name, '| value:', value)\n      })\n      extendedTest.aroundAll(async (runSuite, { value }, suite) => {\n        console.log('>> fixture | aroundAll before suite:', suite.name, '| value:', value)\n        await runSuite()\n        console.log('>> fixture | aroundAll after suite:', suite.name, '| value:', value)\n      })\n\n      extendedTest('root test', ({}) => {})\n\n      describe('nested', () => {\n        extendedTest.beforeAll(({ value }, suite) => {\n          console.log('>> fixture | nested beforeAll suite:', suite.name, '| value:', value)\n        })\n        extendedTest.afterAll(({ value }, suite) => {\n          console.log('>> fixture | nested afterAll suite:', suite.name, '| value:', value)\n        })\n        extendedTest('nested test', ({}) => {})\n      })\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | aroundAll before suite: basic.test.ts | value: test-value\n    >> fixture | beforeAll suite: basic.test.ts | value: test-value\n    >> fixture | nested beforeAll suite: nested | value: test-value\n    >> fixture | nested afterAll suite: nested | value: test-value\n    >> fixture | afterAll suite: basic.test.ts | value: test-value\n    >> fixture | aroundAll after suite: basic.test.ts | value: test-value\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ basic.test.ts > root test <time>\n     ✓ basic.test.ts > nested > nested test <time>\"\n  `)\n})\n\ntest('nested fixtures with different scopes work correctly in hooks', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n    return it\n      .extend('workerValue', { scope: 'worker' }, ({}, { onCleanup }) => {\n        log('workerValue init')\n        onCleanup(() => log('workerValue teardown'))\n        return 'worker'\n      })\n      .extend('fileValue', { scope: 'file' }, ({ workerValue }, { onCleanup }) => {\n        log('fileValue init (depends on workerValue:', workerValue, ')')\n        onCleanup(() => log('fileValue teardown'))\n        return `file+${workerValue}`\n      })\n  }, {\n    'basic.test.ts': ({ extendedTest, describe }) => {\n      // All scopes should be available in beforeAll/afterAll\n      extendedTest.beforeAll(({ workerValue, fileValue }) => {\n        console.log('>> fixture | root beforeAll | worker:', workerValue, 'file:', fileValue)\n      })\n      extendedTest.afterAll(({ workerValue, fileValue }) => {\n        console.log('>> fixture | root afterAll | worker:', workerValue, 'file:', fileValue)\n      })\n\n      extendedTest('root test', ({ workerValue, fileValue }) => {\n        console.log('>> fixture | root test | worker:', workerValue, 'file:', fileValue)\n      })\n\n      describe('nested', () => {\n        extendedTest.beforeAll(({ workerValue, fileValue }) => {\n          console.log('>> fixture | nested beforeAll | worker:', workerValue, 'file:', fileValue)\n        })\n        extendedTest('nested test', ({ workerValue, fileValue }) => {\n          console.log('>> fixture | nested test | worker:', workerValue, 'file:', fileValue)\n        })\n      })\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | workerValue init | undefined\n    >> fixture | fileValue init (depends on workerValue: worker ) | undefined\n    >> fixture | root beforeAll | worker: worker file: file+worker\n    >> fixture | root test | worker: worker file: file+worker\n    >> fixture | nested beforeAll | worker: worker file: file+worker\n    >> fixture | nested test | worker: worker file: file+worker\n    >> fixture | root afterAll | worker: worker file: file+worker\n    >> fixture | fileValue teardown | nested > nested test\n    >> fixture | workerValue teardown | nested > nested test\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ basic.test.ts > root test <time>\n     ✓ basic.test.ts > nested > nested test <time>\"\n  `)\n})\n\ntest('auto file fixture is initialised always before the first test', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{\n    file: string\n  }>({\n    file: [\n      async ({}, use) => {\n        log('init file')\n        await use('file')\n        log('teardown file')\n      },\n      { scope: 'file', auto: true },\n    ],\n  }), {\n    'basic.test.ts': ({ extendedTest }) => {\n      extendedTest('test1', ({}) => {})\n      extendedTest('test2', ({}) => {})\n      extendedTest('test3', ({ file: _file }) => {})\n      extendedTest('test4', ({}) => {})\n    },\n  })\n\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init file | test1\n    >> fixture | teardown file | test4\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ basic.test.ts > test1 <time>\n     ✓ basic.test.ts > test2 <time>\n     ✓ basic.test.ts > test3 <time>\n     ✓ basic.test.ts > test4 <time>\"\n  `)\n})\n\ntest.for([\n  true,\n  false,\n])('file fixture is provided as a factory and is initialised once in all suites, teardown is called once per file (isolate %s)', async (isolate) => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{ file: string }>({\n    file: [\n      async ({}, use) => {\n        log('init file')\n        await use('file')\n        log('teardown file')\n      },\n      { scope: 'file' },\n    ],\n  }), {\n    'basic.test.js': ({ extendedTest, expect, describe }) => {\n      extendedTest('[first] test 1', ({ file }) => {\n        expect(file).toBe('file')\n      })\n\n      extendedTest('test 2', ({ file }) => {\n        expect(file).toBe('file')\n      })\n\n      extendedTest('test 3', ({ file }) => {\n        expect(file).toBe('file')\n      })\n\n      describe('suite 1', () => {\n        extendedTest('test 1 1', ({ file }) => {\n          expect(file).toBe('file')\n        })\n\n        extendedTest('test 1 2', ({ file }) => {\n          expect(file).toBe('file')\n        })\n\n        describe('suite 2', () => {\n          extendedTest('[first] test 1 2 1', ({ file }) => {\n            expect(file).toBe('file')\n          })\n        })\n      })\n    },\n\n    'second.test.js': ({ extendedTest, describe }) => {\n      // doesn't access \"file\", not initialised\n      extendedTest('[second] test 0', ({}) => {})\n      // accesses \"file\" for the first time, initialised\n      extendedTest('[second] test 1', ({ file: _file }) => {})\n      extendedTest('[second] test 2', ({ file: _file }) => {})\n\n      describe('suite 1', () => {\n        extendedTest('[second] test 1', ({ file: _file }) => {})\n      })\n    },\n\n    'third.test.js': ({ extendedTest }) => {\n      // doesn't access \"file\" at all\n      extendedTest('[third] test 0', ({}) => {})\n    },\n  }, {\n    globals: true,\n    isolate,\n    maxWorkers: 1,\n  })\n\n  expect(stderr).toBe('')\n\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | init file | [first] test 1\n    >> fixture | teardown file | suite 1 > suite 2 > [first] test 1 2 1\n    >> fixture | init file | [second] test 1\n    >> fixture | teardown file | suite 1 > [second] test 1\"\n  `)\n\n  expect(tests).toMatchInlineSnapshot(`\n    \" ✓ basic.test.js > [first] test 1 <time>\n     ✓ basic.test.js > test 2 <time>\n     ✓ basic.test.js > test 3 <time>\n     ✓ basic.test.js > suite 1 > test 1 1 <time>\n     ✓ basic.test.js > suite 1 > test 1 2 <time>\n     ✓ basic.test.js > suite 1 > suite 2 > [first] test 1 2 1 <time>\n     ✓ second.test.js > [second] test 0 <time>\n     ✓ second.test.js > [second] test 1 <time>\n     ✓ second.test.js > [second] test 2 <time>\n     ✓ second.test.js > suite 1 > [second] test 1 <time>\n     ✓ third.test.js > [third] test 0 <time>\"\n  `)\n})\n\ndescribe.for([\n  { pool: 'forks' },\n  { pool: 'threads' },\n  {\n    pool: 'browser',\n    name: 'core',\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      headless: true,\n      instances: [\n        { browser: 'chromium' as const, name: '' },\n      ],\n    },\n  },\n])('works properly in $pool', (options) => {\n  test('file and worker fixtures are initiated', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{\n      file: string\n      worker: string\n    }>({\n      worker: [\n        async ({}, use) => {\n          log('init worker')\n          await use('worker')\n          log('teardown worker')\n        },\n        { scope: 'worker' },\n      ],\n      file: [\n        async ({}, use) => {\n          log('init file')\n          await use('file')\n          log('teardown file')\n        },\n        { scope: 'file' },\n      ],\n    }), {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('test1', ({ file: _file, worker: _worker }) => {})\n      },\n      'vitest.config.js': { test: options },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | init worker | test1\n      >> fixture | init file | test1\n      >> fixture | teardown file | test1\n      >> fixture | teardown worker | test1\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > test1 <time>\"`)\n  })\n\n  test('file and worker fixtures are initiated with auto', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{\n      file: string\n      worker: string\n    }>({\n      worker: [\n        async ({}, use) => {\n          log('init worker')\n          await use('worker')\n          log('teardown worker')\n        },\n        { scope: 'worker', auto: true },\n      ],\n      file: [\n        async ({}, use) => {\n          log('init file')\n          await use('file')\n          log('teardown file')\n        },\n        { scope: 'file', auto: true },\n      ],\n    }), {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('test1', () => {})\n      },\n      'vitest.config.js': { test: options },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | init worker | test1\n      >> fixture | init file | test1\n      >> fixture | teardown file | test1\n      >> fixture | teardown worker | test1\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > test1 <time>\"`)\n  })\n})\n\ndescribe('browser tests', () => {\n  test('initiates worker scope once for non-isolated tests', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => it.extend<{\n      file: string\n      worker: string\n    }>({\n      worker: [\n        async ({}, use) => {\n          log('init worker')\n          await use('worker')\n          log('teardown worker')\n        },\n        { scope: 'worker' },\n      ],\n      file: [\n        async ({}, use) => {\n          log('init file')\n          await use('file')\n          log('teardown file')\n        },\n        { scope: 'file' },\n      ],\n    }), {\n      '1-basic.test.ts': ({ extendedTest }) => {\n        extendedTest('test1', ({ file: _file, worker: _worker }) => {})\n      },\n      '2-basic.test.ts': ({ extendedTest }) => {\n        extendedTest('test2', ({ file: _file, worker: _worker }) => {})\n      },\n      'vitest.config.js': {\n        test: {\n          browser: {\n            enabled: true,\n            provider: playwright(),\n            headless: true,\n            isolate: false,\n            instances: [\n              { browser: 'chromium' },\n            ],\n          },\n        },\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | init worker | test1\n      >> fixture | init file | test1\n      >> fixture | teardown file | test1\n      >> fixture | init file | test2\n      >> fixture | teardown file | test2\n      >> fixture | teardown worker | test2\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ |chromium| 1-basic.test.ts > test1 <time>\n       ✓ |chromium| 2-basic.test.ts > test2 <time>\"\n    `)\n  })\n})\n\ntest('file fixture cannot access test fixture at runtime', async () => {\n  // This test verifies that the runtime prevents file fixtures from accessing test fixtures\n  const { stderr } = await runInlineTests({\n    'basic.test.ts': () => {\n      const extendedTest = it.extend<\n        {\n          testFixture: string\n          fileFixture: number\n        }\n      >({\n        testFixture: ({}, use) => use('test'),\n        fileFixture: [\n          ({ testFixture }, use) => use(testFixture.length),\n          { scope: 'file' },\n        ],\n      })\n\n      extendedTest('not working', ({ fileFixture: _file }) => {})\n    },\n  }, { globals: true })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts [ basic.test.ts ]\n    FixtureDependencyError: The file \"fileFixture\" fixture cannot depend on a test fixture \"testFixture\".\n     ❯ basic.test.ts:2:27\n          1| await (() => {\n          2|   const extendedTest = it.extend({\n           |                           ^\n          3|     testFixture: ({}, use) => use(\"test\"),\n          4|     fileFixture: [\n     ❯ basic.test.ts:11:1\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('scoped fixtures with tuple syntax work', async () => {\n  const { stderr, fixtures, tests } = await runFixtureTests(({ log, expectTypeOf }) => it.extend<{\n    $test: { testFixture: string }\n    $file: { fileFixture: number }\n    $worker: { workerFixture: boolean }\n  }>({\n    workerFixture: [async ({}, use) => {\n      log('workerFixture setup')\n      await use(true)\n      log('workerFixture teardown')\n    }, { scope: 'worker' }],\n    fileFixture: [async ({ workerFixture }, use) => {\n      // Confirm workerFixture is typed as boolean (file can access worker fixtures)\n      expectTypeOf(workerFixture).toEqualTypeOf<boolean>()\n      log('fileFixture setup', workerFixture)\n      await use(workerFixture ? 42 : 0)\n      log('fileFixture teardown')\n    }, { scope: 'file' }],\n    testFixture: async ({ fileFixture, workerFixture }, use) => {\n      // Confirm fileFixture is typed as number, workerFixture as boolean (test can access all)\n      expectTypeOf(fileFixture).toEqualTypeOf<number>()\n      expectTypeOf(workerFixture).toEqualTypeOf<boolean>()\n      log('testFixture setup', fileFixture, workerFixture)\n      await use(`test-${fileFixture}-${workerFixture}`)\n      log('testFixture teardown')\n    },\n  }), {\n    'basic.test.ts': ({ extendedTest, expect, expectTypeOf }) => {\n      extendedTest('test 1', ({ testFixture, fileFixture, workerFixture }) => {\n        expectTypeOf(workerFixture).toEqualTypeOf<boolean>()\n        expectTypeOf(fileFixture).toEqualTypeOf<number>()\n        expectTypeOf(testFixture).toEqualTypeOf<string>()\n        expect(workerFixture).toBe(true)\n        expect(fileFixture).toBe(42)\n        expect(testFixture).toBe('test-42-true')\n      })\n    },\n  })\n  expect(stderr).toBe('')\n  expect(fixtures).toMatchInlineSnapshot(`\n    \">> fixture | workerFixture setup | test 1\n    >> fixture | fileFixture setup true | test 1\n    >> fixture | testFixture setup 42 true | test 1\n    >> fixture | testFixture teardown | test 1\n    >> fixture | fileFixture teardown | test 1\n    >> fixture | workerFixture teardown | test 1\"\n  `)\n  expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > test 1 <time>\"`)\n})\n\ndescribe('scoped fixtures type safety', () => {\n  test('types are correctly inferred for scoped fixtures', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log, expectTypeOf }) => it.extend<{\n      $worker: { workerValue: boolean }\n      $file: { fileValue: number }\n      $test: { testValue: string }\n    }>({\n      workerValue: [async ({}, use) => {\n        log('workerValue setup')\n        await use(true)\n        log('workerValue teardown')\n      }, { scope: 'worker' }],\n      fileValue: [async ({ workerValue }, use) => {\n        // Confirm file fixture can access worker fixtures (workerValue is typed as boolean)\n        expectTypeOf(workerValue).toEqualTypeOf<boolean>()\n        log('fileValue setup', workerValue)\n        await use(workerValue ? 42 : 0)\n        log('fileValue teardown')\n      }, { scope: 'file' }],\n      testValue: async ({ fileValue, workerValue }, use) => {\n        // Confirm test fixture can access both file and worker fixtures\n        expectTypeOf(fileValue).toEqualTypeOf<number>()\n        expectTypeOf(workerValue).toEqualTypeOf<boolean>()\n        log('testValue setup', fileValue, workerValue)\n        await use(`${fileValue}-${workerValue}`)\n        log('testValue teardown')\n      },\n    }), {\n      'basic.test.ts': ({ extendedTest, expect, expectTypeOf }) => {\n        extendedTest('has correct types', ({ workerValue, fileValue, testValue }) => {\n          // Verify the values and types are correct\n          expectTypeOf(workerValue).toEqualTypeOf<boolean>()\n          expectTypeOf(fileValue).toEqualTypeOf<number>()\n          expectTypeOf(testValue).toEqualTypeOf<string>()\n          expect(workerValue).toBe(true)\n          expect(fileValue).toBe(42)\n          expect(testValue).toBe('42-true')\n        })\n      },\n    })\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | workerValue setup | has correct types\n      >> fixture | fileValue setup true | has correct types\n      >> fixture | testValue setup 42 true | has correct types\n      >> fixture | testValue teardown | has correct types\n      >> fixture | fileValue teardown | has correct types\n      >> fixture | workerValue teardown | has correct types\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > has correct types <time>\"`)\n  })\n\n  test('file fixture cannot access test-scoped fixtures (runtime error)', async () => {\n    const { stderr } = await runFixtureTests(({ log, expectTypeOf: _expectTypeOf }) => it.extend<{\n      $worker: { workerValue: boolean }\n      $file: { fileValue: number }\n      $test: { testValue: string }\n    }>({\n      workerValue: [async ({}, use) => {\n        log('workerValue setup')\n        await use(true)\n        log('workerValue teardown')\n      }, { scope: 'worker' }],\n      // @ts-expect-error - file fixture cannot access test-scoped fixture 'testValue'\n      fileValue: [async ({ testValue }, use) => {\n        log('fileValue setup')\n        await use(testValue.length)\n        log('fileValue teardown')\n      }, { scope: 'file' }],\n      testValue: async ({}, use) => {\n        log('testValue setup')\n        await use('test')\n        log('testValue teardown')\n      },\n    }), {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('should fail', ({ fileValue: _fileValue }) => {})\n      },\n    })\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts [ basic.test.ts ]\n      FixtureDependencyError: The file \"fileValue\" fixture cannot depend on a test fixture \"testValue\".\n       ❯ test.js:5:75\n            3| export const expect = globalThis.expect\n            4| export const expectTypeOf = globalThis.expectTypeOf\n            5| export const extendedTest = (({ log, expectTypeOf: _expectTypeOf }) =>…\n             |                                                                           ^\n            6|   workerValue: [async ({}, use) => {\n            7|     log(\"workerValue setup\");\n       ❯ test.js:22:4\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('worker fixture cannot access file-scoped fixtures (runtime error)', async () => {\n    const { stderr } = await runFixtureTests(({ log, expectTypeOf: _expectTypeOf }) => it.extend<{\n      $worker: { workerValue: boolean }\n      $file: { fileValue: number }\n      $test: { testValue: string }\n    }>({\n      // @ts-expect-error - worker fixture cannot access file-scoped fixture 'fileValue'\n      workerValue: [async ({ fileValue }, use) => {\n        log('workerValue setup')\n        await use(fileValue > 0)\n        log('workerValue teardown')\n      }, { scope: 'worker' }],\n      fileValue: [async ({}, use) => {\n        log('fileValue setup')\n        await use(42)\n        log('fileValue teardown')\n      }, { scope: 'file' }],\n      testValue: async ({}, use) => {\n        log('testValue setup')\n        await use('test')\n        log('testValue teardown')\n      },\n    }), {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('should fail', ({ workerValue: _workerValue }) => {})\n      },\n    })\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts [ basic.test.ts ]\n      FixtureDependencyError: The worker \"workerValue\" fixture cannot depend on a file fixture \"fileValue\".\n       ❯ test.js:5:75\n            3| export const expect = globalThis.expect\n            4| export const expectTypeOf = globalThis.expectTypeOf\n            5| export const extendedTest = (({ log, expectTypeOf: _expectTypeOf }) =>…\n             |                                                                           ^\n            6|   // @ts-expect-error - worker fixture cannot access file-scoped fixtu…\n            7|   workerValue: [async ({ fileValue }, use) => {\n       ❯ test.js:22:4\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('worker fixture cannot access test-scoped fixtures (runtime error)', async () => {\n    const { stderr } = await runFixtureTests(({ log, expectTypeOf: _expectTypeOf }) => it.extend<{\n      $worker: { workerValue: boolean }\n      $file: { fileValue: number }\n      $test: { testValue: string }\n    }>({\n      // @ts-expect-error - worker fixture cannot access test-scoped fixture 'testValue'\n      workerValue: [async ({ testValue }, use) => {\n        log('workerValue setup')\n        await use(testValue.length > 0)\n        log('workerValue teardown')\n      }, { scope: 'worker' }],\n      fileValue: [async ({}, use) => {\n        log('fileValue setup')\n        await use(42)\n        log('fileValue teardown')\n      }, { scope: 'file' }],\n      testValue: async ({}, use) => {\n        log('testValue setup')\n        await use('test')\n        log('testValue teardown')\n      },\n    }), {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('should fail', ({ workerValue: _workerValue }) => {})\n      },\n    })\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts [ basic.test.ts ]\n      FixtureDependencyError: The worker \"workerValue\" fixture cannot depend on a test fixture \"testValue\".\n       ❯ test.js:5:75\n            3| export const expect = globalThis.expect\n            4| export const expectTypeOf = globalThis.expectTypeOf\n            5| export const extendedTest = (({ log, expectTypeOf: _expectTypeOf }) =>…\n             |                                                                           ^\n            6|   // @ts-expect-error - worker fixture cannot access test-scoped fixtu…\n            7|   workerValue: [async ({ testValue }, use) => {\n       ❯ test.js:22:4\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('scoped fixtures accept additional options (auto)', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log, expectTypeOf: _expectTypeOf }) => it.extend<{\n      $worker: { workerValue: boolean }\n      $file: { fileValue: number }\n    }>({\n      workerValue: [async ({}, use) => {\n        log('workerValue setup')\n        await use(true)\n        log('workerValue teardown')\n      }, { scope: 'worker', auto: true }],\n      fileValue: [async ({}, use) => {\n        log('fileValue setup')\n        await use(42)\n        log('fileValue teardown')\n      }, { scope: 'file', auto: true }],\n    }), {\n      'basic.test.ts': ({ extendedTest }) => {\n        // auto fixtures should initialize even without being explicitly requested\n        extendedTest('auto fixtures work', ({}) => {})\n      },\n    })\n    expect(stderr).toBe('')\n    // Auto fixtures initialize even when not explicitly requested\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | workerValue setup | auto fixtures work\n      >> fixture | fileValue setup | auto fixtures work\n      >> fixture | fileValue teardown | auto fixtures work\n      >> fixture | workerValue teardown | auto fixtures work\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > auto fixtures work <time>\"`)\n  })\n\n  test('file fixture cannot access TestContext properties like task (type and runtime error)', async () => {\n    const { stderr } = await runFixtureTests(({ log, expectTypeOf: _expectTypeOf }) => it.extend<{\n      $file: { fileValue: string }\n      $test: { testValue: number }\n    }>({\n      // @ts-expect-error - file fixture cannot access 'task' from TestContext\n      fileValue: [async ({ task }, use) => {\n        log('fileValue setup')\n        await use(task.name)\n        log('fileValue teardown')\n      }, { scope: 'file' }],\n      testValue: async ({}, use) => {\n        log('testValue setup')\n        await use(42)\n        log('testValue teardown')\n      },\n    }), {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('should fail', ({ fileValue: _fileValue }) => {})\n      },\n    })\n    // Runtime error because 'task' is not available in file fixtures\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts > should fail\n      TypeError: Cannot read properties of undefined (reading 'name')\n       ❯ it.extend.fileValue.scope test.js:9:20\n            7|   fileValue: [async ({ task }, use) => {\n            8|     log(\"fileValue setup\");\n            9|     await use(task.name);\n             |                    ^\n           10|     log(\"fileValue teardown\");\n           11|   }, { scope: \"file\" }],\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('worker fixture cannot access TestContext properties like task (type and runtime error)', async () => {\n    const { stderr } = await runFixtureTests(({ log, expectTypeOf: _expectTypeOf }) => it.extend<{\n      $worker: { workerValue: string }\n      $test: { testValue: number }\n    }>({\n      // @ts-expect-error - worker fixture cannot access 'task' from TestContext\n      workerValue: [async ({ task }, use) => {\n        log('workerValue setup')\n        await use(task.name)\n        log('workerValue teardown')\n      }, { scope: 'worker' }],\n      testValue: async ({}, use) => {\n        log('testValue setup')\n        await use(42)\n        log('testValue teardown')\n      },\n    }), {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('should fail', ({ workerValue: _workerValue }) => {})\n      },\n    })\n    // Runtime error because 'task' is not available in worker fixtures\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts > should fail\n      TypeError: Cannot read properties of undefined (reading 'name')\n       ❯ it.extend.workerValue.scope test.js:9:20\n            7|   workerValue: [async ({ task }, use) => {\n            8|     log(\"workerValue setup\");\n            9|     await use(task.name);\n             |                    ^\n           10|     log(\"workerValue teardown\");\n           11|   }, { scope: \"worker\" }],\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n})\n\ndescribe('builder pattern API with automatic type inference', () => {\n  test('types are automatically inferred from return values', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log, expectTypeOf }) => {\n      return it\n        .extend('workerValue', { scope: 'worker' }, async () => {\n          log('workerValue setup')\n          return 123\n        })\n        .extend('fileValue', { scope: 'file' }, async ({ workerValue }) => {\n          // TypeScript automatically knows workerValue is number\n          expectTypeOf(workerValue).toEqualTypeOf<number>()\n          log('fileValue setup', workerValue)\n          return workerValue > 100\n        })\n        .extend('testValue', async ({ workerValue, fileValue }) => {\n          // TypeScript automatically knows both types\n          expectTypeOf(workerValue).toEqualTypeOf<number>()\n          expectTypeOf(fileValue).toEqualTypeOf<boolean>()\n          log('testValue setup', workerValue, fileValue)\n          return { num: workerValue, bool: fileValue }\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, expectTypeOf }) => {\n        extendedTest('builder pattern provides correct types and values', ({ workerValue, fileValue, testValue }) => {\n          // Verify types are automatically inferred\n          expectTypeOf(workerValue).toEqualTypeOf<number>()\n          expectTypeOf(fileValue).toEqualTypeOf<boolean>()\n          expectTypeOf(testValue).toEqualTypeOf<{ num: number; bool: boolean }>()\n\n          // Verify values\n          expect(workerValue).toBe(123)\n          expect(fileValue).toBe(true)\n          expect(testValue).toEqual({ num: 123, bool: true })\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | workerValue setup | builder pattern provides correct types and values\n      >> fixture | fileValue setup 123 | builder pattern provides correct types and values\n      >> fixture | testValue setup 123 true | builder pattern provides correct types and values\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > builder pattern provides correct types and values <time>\"`)\n  })\n\n  test('builder pattern without options defaults to test scope', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log, expectTypeOf }) => {\n      return it\n        // No need to pass {} when not using any dependencies\n        .extend('count', async () => {\n          log('count setup')\n          return 42\n        })\n        .extend('doubled', async ({ count }) => {\n          expectTypeOf(count).toEqualTypeOf<number>()\n          log('doubled setup', count)\n          return count * 2\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, expectTypeOf }) => {\n        extendedTest('test scope fixtures work', ({ count, doubled }) => {\n          expectTypeOf(count).toEqualTypeOf<number>()\n          expectTypeOf(doubled).toEqualTypeOf<number>()\n\n          expect(count).toBe(42)\n          expect(doubled).toBe(84)\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | count setup | test scope fixtures work\n      >> fixture | doubled setup 42 | test scope fixtures work\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > test scope fixtures work <time>\"`)\n  })\n\n  test('can mix builder pattern with object-based extend', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log, expectTypeOf }) => {\n      return it\n        .extend('first', async () => {\n          log('first setup')\n          return 'hello'\n        })\n        .extend<{ second: number }>({\n          second: 100,\n        })\n        .extend('third', async ({ first, second }) => {\n          expectTypeOf(first).toEqualTypeOf<string>()\n          expectTypeOf(second).toEqualTypeOf<number>()\n          log('third setup', first, second)\n          return `${first}-${second}`\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, expectTypeOf }) => {\n        extendedTest('mixed patterns work', ({ first, second, third }) => {\n          expectTypeOf(first).toEqualTypeOf<string>()\n          expectTypeOf(second).toEqualTypeOf<number>()\n          expectTypeOf(third).toEqualTypeOf<string>()\n\n          expect(first).toBe('hello')\n          expect(second).toBe(100)\n          expect(third).toBe('hello-100')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | first setup | mixed patterns work\n      >> fixture | third setup hello 100 | mixed patterns work\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > mixed patterns work <time>\"`)\n  })\n\n  test('non-function values work in builder pattern', async () => {\n    const { stderr, tests } = await runFixtureTests(({ expectTypeOf }) => {\n      return it\n        .extend('stringValue', 'hello')\n        .extend('numberValue', 42)\n        .extend('arrayValue', [1, 2, 3])\n        .extend('objectValue', { key: 'value' })\n        .extend('combined', async ({ stringValue, numberValue }) => {\n          expectTypeOf(stringValue).toEqualTypeOf<string>()\n          expectTypeOf(numberValue).toEqualTypeOf<number>()\n          return `${stringValue}-${numberValue}`\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, expectTypeOf }) => {\n        extendedTest('non-function values work', ({ stringValue, numberValue, arrayValue, objectValue, combined }) => {\n          expectTypeOf(stringValue).toEqualTypeOf<string>()\n          expectTypeOf(numberValue).toEqualTypeOf<number>()\n          expectTypeOf(arrayValue).toEqualTypeOf<number[]>()\n          expectTypeOf(objectValue).toEqualTypeOf<{ key: string }>()\n          expectTypeOf(combined).toEqualTypeOf<string>()\n\n          expect(stringValue).toBe('hello')\n          expect(numberValue).toBe(42)\n          expect(arrayValue).toEqual([1, 2, 3])\n          expect(objectValue).toEqual({ key: 'value' })\n          expect(combined).toBe('hello-42')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > non-function values work <time>\"`)\n  })\n\n  test('non-function values with injected option work', async () => {\n    const { stderr, tests } = await runFixtureTests(({ expectTypeOf }) => {\n      return it\n        // Static values only support 'injected' option\n        .extend('apiUrl', { injected: true }, 'https://api.example.com')\n        .extend('config', { port: 3000, host: 'localhost' })\n        .extend('computed', async ({ apiUrl, config }) => {\n          expectTypeOf(apiUrl).toEqualTypeOf<string>()\n          expectTypeOf(config).toEqualTypeOf<{ port: number; host: string }>()\n          return `${apiUrl}:${config.port}`\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, expectTypeOf }) => {\n        extendedTest('non-function values with injected option work', ({ apiUrl, config, computed }) => {\n          expectTypeOf(apiUrl).toEqualTypeOf<string>()\n          expectTypeOf(config).toEqualTypeOf<{ port: number; host: string }>()\n          expectTypeOf(computed).toEqualTypeOf<string>()\n\n          expect(apiUrl).toBe('https://injected.example.com')\n          expect(config).toEqual({ port: 3000, host: 'localhost' })\n          expect(computed).toBe('https://injected.example.com:3000')\n        })\n      },\n      'vitest.config.js': {\n        test: {\n          provide: {\n            apiUrl: 'https://injected.example.com',\n          } as any, // requires type pollution otherwise\n        },\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > non-function values with injected option work <time>\"`)\n  })\n\n  test('extending the extended', async () => {\n    const { stderr, tests } = await runFixtureTests(() => {\n      return it\n        .extend('apiUrl', 'https://api.example.com')\n        .extend(\n          'apiUrl',\n          // @ts-expect-error false should be string\n          false,\n        )\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, expectTypeOf }) => {\n        extendedTest('onCleanup works', ({ apiUrl }) => {\n          expectTypeOf(apiUrl).toEqualTypeOf<string>()\n          // runtime overrides, but ts shows an error\n          // we don't enforce it because it's possible to provide objects\n          // which are hard to compare at runtime\n          expect(apiUrl).toBe(false)\n        })\n      },\n    })\n    expect(stderr).toBe('')\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > onCleanup works <time>\"`)\n  })\n\n  test('dependencies in extended extend use the new extended value', async () => {\n    const { stderr, tests } = await runFixtureTests(() => {\n      return it\n        .extend('a', () => 1)\n        .extend('b', ({ a }) => a + 1)\n        .extend('a', () => 100)\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('direct access returns new value', ({ a }) => {\n          expect(a).toBe(100)\n        })\n\n        extendedTest('dependent access returns new value', ({ b }) => {\n          expect(b).toBe(101)\n        })\n      },\n    })\n    expect(stderr).toBe('')\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > direct access returns new value <time>\n       ✓ basic.test.ts > dependent access returns new value <time>\"\n    `)\n  })\n\n  test('onCleanup registers teardown function', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it.extend('resource', { scope: 'file' }, async ({}, { onCleanup }) => {\n        const resource = { id: 42, data: 'test' }\n        log('resource setup')\n        onCleanup(() => {\n          log('resource cleanup', resource.id)\n        })\n        return resource\n      })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('onCleanup works', ({ resource }) => {\n          expect(resource).toEqual({ id: 42, data: 'test' })\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | resource setup | onCleanup works\n      >> fixture | resource cleanup 42 | onCleanup works\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > onCleanup works <time>\"`)\n  })\n\n  test('builder pattern with auto option', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('autoValue', { auto: true }, async () => {\n          log('autoValue setup')\n          return 'auto-initialized'\n        })\n        .extend('regularValue', async () => {\n          log('regularValue setup')\n          return 'regular'\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('auto fixture is initialized even when not used', ({ regularValue }) => {\n          expect(regularValue).toBe('regular')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | autoValue setup | auto fixture is initialized even when not used\n      >> fixture | regularValue setup | auto fixture is initialized even when not used\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > auto fixture is initialized even when not used <time>\"`)\n  })\n\n  test('onCleanup can only be called once per fixture', async () => {\n    const { stderr } = await runFixtureTests(({ log }) => {\n      return it.extend('resource', async ({}, { onCleanup }) => {\n        log('resource setup')\n        onCleanup(() => log('cleanup 1'))\n        onCleanup(() => log('cleanup 2')) // This should throw\n        return 'value'\n      })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('should fail because onCleanup called twice', ({ resource }) => {\n          expect(resource).toBe('value')\n        })\n      },\n    })\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts > should fail because onCleanup called twice\n      Error: onCleanup can only be called once per fixture. Define separate fixtures if you need multiple cleanup functions.\n       ❯ test.js:9:5\n            7|     log(\"resource setup\");\n            8|     onCleanup(() => log(\"cleanup 1\"));\n            9|     onCleanup(() => log(\"cleanup 2\"));\n             |     ^\n           10|     return \"value\";\n           11|   });\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('nested fixtures cleanup in correct order (dependent cleaned up first)', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('base', async ({}, { onCleanup }) => {\n          log('base setup')\n          onCleanup(() => log('base cleanup'))\n          return 1\n        })\n        .extend('middle', async ({ base }, { onCleanup }) => {\n          log('middle setup', base)\n          onCleanup(() => log('middle cleanup'))\n          return base + 10\n        })\n        .extend('top', async ({ middle }, { onCleanup }) => {\n          log('top setup', middle)\n          onCleanup(() => log('top cleanup'))\n          return middle + 100\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('fixtures are cleaned up in reverse dependency order', ({ top }) => {\n          expect(top).toBe(111)\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | base setup | fixtures are cleaned up in reverse dependency order\n      >> fixture | middle setup 1 | fixtures are cleaned up in reverse dependency order\n      >> fixture | top setup 11 | fixtures are cleaned up in reverse dependency order\n      >> fixture | top cleanup | fixtures are cleaned up in reverse dependency order\n      >> fixture | middle cleanup | fixtures are cleaned up in reverse dependency order\n      >> fixture | base cleanup | fixtures are cleaned up in reverse dependency order\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > fixtures are cleaned up in reverse dependency order <time>\"`)\n  })\n\n  test('cleanup order across different scopes', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('workerFixture', { scope: 'worker' }, async ({}, { onCleanup }) => {\n          log('worker setup')\n          onCleanup(() => log('worker cleanup'))\n          return 'worker'\n        })\n        .extend('fileFixture', { scope: 'file' }, async ({ workerFixture }, { onCleanup }) => {\n          log('file setup', workerFixture)\n          onCleanup(() => log('file cleanup'))\n          return 'file'\n        })\n        .extend('testFixture', async ({ fileFixture }, { onCleanup }) => {\n          log('test setup', fileFixture)\n          onCleanup(() => log('test cleanup'))\n          return 'test'\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('scoped fixtures cleanup in order', ({ testFixture }) => {\n          expect(testFixture).toBe('test')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | worker setup | scoped fixtures cleanup in order\n      >> fixture | file setup worker | scoped fixtures cleanup in order\n      >> fixture | test setup file | scoped fixtures cleanup in order\n      >> fixture | test cleanup | scoped fixtures cleanup in order\n      >> fixture | file cleanup | scoped fixtures cleanup in order\n      >> fixture | worker cleanup | scoped fixtures cleanup in order\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > scoped fixtures cleanup in order <time>\"`)\n  })\n\n  test('deep fixture chain with all scopes and cleanups', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log, expectTypeOf }) => {\n      return it\n        .extend('config', { scope: 'worker' }, async ({}, { onCleanup }) => {\n          log('config setup')\n          onCleanup(() => log('config cleanup'))\n          return { port: 3000, host: 'localhost' }\n        })\n        .extend('connection', { scope: 'worker' }, async ({ config }, { onCleanup }) => {\n          expectTypeOf(config).toEqualTypeOf<{ port: number; host: string }>()\n          log('connection setup', config.port)\n          onCleanup(() => log('connection cleanup'))\n          return `${config.host}:${config.port}`\n        })\n        .extend('database', { scope: 'file' }, async ({ connection }, { onCleanup }) => {\n          expectTypeOf(connection).toEqualTypeOf<string>()\n          log('database setup', connection)\n          onCleanup(() => log('database cleanup'))\n          return { url: connection, connected: true }\n        })\n        .extend('transaction', async ({ database }, { onCleanup }) => {\n          expectTypeOf(database).toEqualTypeOf<{ url: string; connected: boolean }>()\n          log('transaction setup', database.connected)\n          onCleanup(() => log('transaction rollback'))\n          return { id: 1, db: database }\n        })\n        .extend('query', async ({ transaction }) => {\n          expectTypeOf(transaction).toEqualTypeOf<{ id: number; db: { url: string; connected: boolean } }>()\n          log('query setup', transaction.id)\n          return `SELECT * FROM ${transaction.id}`\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, expectTypeOf }) => {\n        extendedTest('deep chain works correctly', ({ config, connection, database, transaction, query }) => {\n          expectTypeOf(config).toEqualTypeOf<{ port: number; host: string }>()\n          expectTypeOf(connection).toEqualTypeOf<string>()\n          expectTypeOf(database).toEqualTypeOf<{ url: string; connected: boolean }>()\n          expectTypeOf(transaction).toEqualTypeOf<{ id: number; db: { url: string; connected: boolean } }>()\n          expectTypeOf(query).toEqualTypeOf<string>()\n\n          expect(config).toEqual({ port: 3000, host: 'localhost' })\n          expect(connection).toBe('localhost:3000')\n          expect(database).toEqual({ url: 'localhost:3000', connected: true })\n          expect(transaction).toEqual({ id: 1, db: { url: 'localhost:3000', connected: true } })\n          expect(query).toBe('SELECT * FROM 1')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | config setup | deep chain works correctly\n      >> fixture | connection setup 3000 | deep chain works correctly\n      >> fixture | database setup localhost:3000 | deep chain works correctly\n      >> fixture | transaction setup true | deep chain works correctly\n      >> fixture | query setup 1 | deep chain works correctly\n      >> fixture | transaction rollback | deep chain works correctly\n      >> fixture | database cleanup | deep chain works correctly\n      >> fixture | connection cleanup | deep chain works correctly\n      >> fixture | config cleanup | deep chain works correctly\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > deep chain works correctly <time>\"`)\n  })\n\n  test('fixture without onCleanup works correctly', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('noCleanup', async () => {\n          log('noCleanup setup')\n          return 'no cleanup needed'\n        })\n        .extend('withCleanup', async ({ noCleanup }, { onCleanup }) => {\n          log('withCleanup setup', noCleanup)\n          onCleanup(() => log('withCleanup cleanup'))\n          return 'has cleanup'\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('mixed cleanup works', ({ noCleanup, withCleanup }) => {\n          expect(noCleanup).toBe('no cleanup needed')\n          expect(withCleanup).toBe('has cleanup')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | noCleanup setup | mixed cleanup works\n      >> fixture | withCleanup setup no cleanup needed | mixed cleanup works\n      >> fixture | withCleanup cleanup | mixed cleanup works\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > mixed cleanup works <time>\"`)\n  })\n\n  test('fixture reuses value across multiple tests in same scope', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('fileCounter', { scope: 'file' }, async ({}, { onCleanup }) => {\n          log('fileCounter setup')\n          onCleanup(() => log('fileCounter cleanup'))\n          return { count: 0 }\n        })\n        .extend('testValue', async ({ fileCounter }) => {\n          fileCounter.count++\n          log('testValue setup', fileCounter.count)\n          return fileCounter.count\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('first test', ({ testValue }) => {\n          expect(testValue).toBe(1)\n        })\n        extendedTest('second test', ({ testValue }) => {\n          expect(testValue).toBe(2)\n        })\n        extendedTest('third test', ({ testValue }) => {\n          expect(testValue).toBe(3)\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | fileCounter setup | first test\n      >> fixture | testValue setup 1 | first test\n      >> fixture | testValue setup 2 | second test\n      >> fixture | testValue setup 3 | third test\n      >> fixture | fileCounter cleanup | third test\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > first test <time>\n       ✓ basic.test.ts > second test <time>\n       ✓ basic.test.ts > third test <time>\"\n    `)\n  })\n\n  test('async cleanup functions work correctly', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it.extend('asyncResource', async ({}, { onCleanup }) => {\n        log('asyncResource setup')\n        onCleanup(async () => {\n          log('async cleanup start')\n          await new Promise(resolve => setTimeout(resolve, 10))\n          log('async cleanup done')\n        })\n        return 'async'\n      })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('async cleanup works', ({ asyncResource }) => {\n          expect(asyncResource).toBe('async')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | asyncResource setup | async cleanup works\n      >> fixture | async cleanup start | async cleanup works\n      >> fixture | async cleanup done | async cleanup works\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > async cleanup works <time>\"`)\n  })\n\n  test('file fixture cannot access test fixture (runtime and type error)', async () => {\n    const { stderr } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('testValue', async () => {\n          log('testValue setup')\n          return 'test'\n        })\n        // @ts-expect-error - file fixture cannot access test-scoped fixture 'testValue'\n        .extend('fileValue', { scope: 'file' }, async ({ testValue }) => {\n          log('fileValue setup', testValue)\n          return testValue.length\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('should fail', ({ fileValue: _fileValue }) => {})\n      },\n    })\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts [ basic.test.ts ]\n      FixtureDependencyError: The file \"fileValue\" fixture cannot depend on a test fixture \"testValue\".\n       ❯ test.js:9:6\n            7|     log(\"testValue setup\");\n            8|     return \"test\";\n            9|   }).extend(\"fileValue\", { scope: \"file\" }, async ({ testValue }) => {\n             |      ^\n           10|     log(\"fileValue setup\", testValue);\n           11|     return testValue.length;\n       ❯ test.js:13:3\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('worker fixture cannot access file fixture (runtime and type error)', async () => {\n    const { stderr } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('fileValue', { scope: 'file' }, async () => {\n          log('fileValue setup')\n          return 42\n        })\n        // @ts-expect-error - worker fixture cannot access file-scoped fixture 'fileValue'\n        .extend('workerValue', { scope: 'worker' }, async ({ fileValue }) => {\n          log('workerValue setup', fileValue)\n          return fileValue > 0\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('should fail', ({ workerValue: _workerValue }) => {})\n      },\n    })\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts [ basic.test.ts ]\n      FixtureDependencyError: The worker \"workerValue\" fixture cannot depend on a file fixture \"fileValue\".\n       ❯ test.js:9:6\n            7|     log(\"fileValue setup\");\n            8|     return 42;\n            9|   }).extend(\"workerValue\", { scope: \"worker\" }, async ({ fileValue }) …\n             |      ^\n           10|     log(\"workerValue setup\", fileValue);\n           11|     return fileValue > 0;\n       ❯ test.js:13:3\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('worker fixture cannot access test fixture (runtime and type error)', async () => {\n    const { stderr } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('testValue', async () => {\n          log('testValue setup')\n          return 'test'\n        })\n        // @ts-expect-error - worker fixture cannot access test-scoped fixture 'testValue'\n        .extend('workerValue', { scope: 'worker' }, async ({ testValue }) => {\n          log('workerValue setup', testValue)\n          return testValue.length > 0\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest }) => {\n        extendedTest('should fail', ({ workerValue: _workerValue }) => {})\n      },\n    })\n\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts [ basic.test.ts ]\n      FixtureDependencyError: The worker \"workerValue\" fixture cannot depend on a test fixture \"testValue\".\n       ❯ test.js:9:6\n            7|     log(\"testValue setup\");\n            8|     return \"test\";\n            9|   }).extend(\"workerValue\", { scope: \"worker\" }, async ({ testValue }) …\n             |      ^\n           10|     log(\"workerValue setup\", testValue);\n           11|     return testValue.length > 0;\n       ❯ test.js:13:3\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('cleanup error is reported', async () => {\n    const { stderr, fixtures } = await runFixtureTests(({ log }) => {\n      return it.extend('resource', async ({}, { onCleanup }) => {\n        log('resource setup')\n        onCleanup(() => {\n          log('cleanup - throwing')\n          throw new Error('cleanup error')\n        })\n        return 'value'\n      })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        extendedTest('test runs but cleanup fails', ({ resource }) => {\n          expect(resource).toBe('value')\n        })\n      },\n    })\n\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | resource setup | test runs but cleanup fails\n      >> fixture | cleanup - throwing | test runs but cleanup fails\"\n    `)\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts > test runs but cleanup fails\n       FAIL  basic.test.ts > test runs but cleanup fails\n      Error: cleanup error\n       ❯ test.js:10:13\n            8|     onCleanup(() => {\n            9|       log(\"cleanup - throwing\");\n           10|       throw new Error(\"cleanup error\");\n             |             ^\n           11|     });\n           12|     return \"value\";\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯\n\n      \"\n    `)\n  })\n})\n\ndescribe('test.override builder pattern', () => {\n  test('override with static value', async () => {\n    const { stderr, tests } = await runFixtureTests(({ expectTypeOf: _expectTypeOf }) => {\n      return it\n        .extend('config', { port: 3000, host: 'localhost' })\n        .extend('url', ({ config }) => `http://${config.host}:${config.port}`)\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, expectTypeOf, describe }) => {\n        extendedTest('uses default', ({ config, url }) => {\n          expectTypeOf(config).toEqualTypeOf<{ port: number; host: string }>()\n          expect(config.port).toBe(3000)\n          expect(url).toBe('http://localhost:3000')\n        })\n\n        describe('with overwritten port', () => {\n          extendedTest.override('config', { port: 4000, host: 'localhost' })\n\n          extendedTest('uses overwritten value', ({ config, url }) => {\n            expect(config.port).toBe(4000)\n            expect(url).toBe('http://localhost:4000')\n          })\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > uses default <time>\n       ✓ basic.test.ts > with overwritten port > uses overwritten value <time>\"\n    `)\n  })\n\n  test('override with function that uses dependencies from original test', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('config', { port: 3000 })\n        .extend('server', async ({ config }, { onCleanup }) => {\n          log('server setup', config.port)\n          onCleanup(() => log('server cleanup'))\n          return { port: config.port, running: true }\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, describe }) => {\n        extendedTest('uses default server', ({ server }) => {\n          expect(server.port).toBe(3000)\n        })\n\n        describe('with custom server', () => {\n          // override with a function that uses 'config' from the original test\n          extendedTest.override('server', async ({ config }, { onCleanup }) => {\n            console.log('>> fixture | custom server setup', config.port, '|', expect.getState().currentTestName)\n            onCleanup(() => console.log('>> fixture | custom server cleanup |', expect.getState().currentTestName))\n            return { port: config.port + 1000, running: false }\n          })\n\n          extendedTest('uses custom server', ({ server }) => {\n            expect(server.port).toBe(4000)\n            expect(server.running).toBe(false)\n          })\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | server setup 3000 | uses default server\n      >> fixture | server cleanup | uses default server\n      >> fixture | custom server setup 3000 | with custom server > uses custom server\n      >> fixture | custom server cleanup | with custom server > uses custom server\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > uses default server <time>\n       ✓ basic.test.ts > with custom server > uses custom server <time>\"\n    `)\n  })\n\n  test('override with object syntax (backward compatible)', async () => {\n    const { stderr, tests } = await runFixtureTests(() => {\n      return it\n        .extend('value', 'original')\n        .extend('derived', ({ value }) => `derived-${value}`)\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, describe }) => {\n        extendedTest('uses default', ({ value, derived }) => {\n          expect(value).toBe('original')\n          expect(derived).toBe('derived-original')\n        })\n\n        describe('overwritten with object syntax', () => {\n          extendedTest.override({ value: 'overwritten' })\n\n          extendedTest('uses overwritten', ({ value, derived }) => {\n            expect(value).toBe('overwritten')\n            expect(derived).toBe('derived-overwritten')\n          })\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > uses default <time>\n       ✓ basic.test.ts > overwritten with object syntax > uses overwritten <time>\"\n    `)\n  })\n\n  test('scoped is deprecated but still works', async () => {\n    const { stderr, tests } = await runFixtureTests(() => {\n      return it\n        .extend('value', 'original')\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, describe }) => {\n        describe('using deprecated scoped', () => {\n          // scoped is deprecated, use override instead\n          extendedTest.scoped({ value: 'scoped-value' })\n\n          extendedTest('scoped still works', ({ value }) => {\n            expect(value).toBe('scoped-value')\n          })\n        })\n      },\n    })\n\n    expect(stderr).toContain('test.scoped() is deprecated and will be removed in future versions. Please use test.override() instead.')\n    expect(tests).toMatchInlineSnapshot(`\" ✓ basic.test.ts > using deprecated scoped > scoped still works <time>\"`)\n  })\n\n  test('override nested describe inheritance', async () => {\n    const { stderr, tests } = await runFixtureTests(() => {\n      return it\n        .extend('level', 'root')\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, describe }) => {\n        extendedTest('root level', ({ level }) => {\n          expect(level).toBe('root')\n        })\n\n        describe('level 1', () => {\n          extendedTest.override('level', 'one')\n\n          extendedTest('at level 1', ({ level }) => {\n            expect(level).toBe('one')\n          })\n\n          describe('level 2', () => {\n            extendedTest.override('level', 'two')\n\n            extendedTest('at level 2', ({ level }) => {\n              expect(level).toBe('two')\n            })\n          })\n\n          extendedTest('still at level 1', ({ level }) => {\n            expect(level).toBe('one')\n          })\n        })\n\n        extendedTest('back to root', ({ level }) => {\n          expect(level).toBe('root')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > root level <time>\n       ✓ basic.test.ts > level 1 > at level 1 <time>\n       ✓ basic.test.ts > level 1 > level 2 > at level 2 <time>\n       ✓ basic.test.ts > level 1 > still at level 1 <time>\n       ✓ basic.test.ts > back to root <time>\"\n    `)\n  })\n\n  test('override with function that accesses other static fixtures', async () => {\n    const { stderr, tests } = await runFixtureTests(() => {\n      return it\n        .extend('basePort', 3000)\n        .extend('environment', 'development')\n        .extend('config', ({ basePort, environment }) => ({\n          port: basePort,\n          env: environment,\n          debug: environment === 'development',\n        }))\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, describe }) => {\n        extendedTest('default config', ({ config }) => {\n          expect(config).toEqual({ port: 3000, env: 'development', debug: true })\n        })\n\n        describe('production', () => {\n          // Chained overwrites\n          extendedTest\n            .override('environment', 'production')\n            .override('basePort', 8080)\n\n          extendedTest('production config', ({ config }) => {\n            expect(config).toEqual({ port: 8080, env: 'production', debug: false })\n          })\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > default config <time>\n       ✓ basic.test.ts > production > production config <time>\"\n    `)\n  })\n\n  test('throws an error when overriding worker fixtures inside a suite', async () => {\n    const { stderr } = await runFixtureTests(() => {\n      return it\n        .extend('basePort', { scope: 'worker' }, () => 3000)\n        .extend('environment', { scope: 'worker' }, 'development')\n        .extend('config', { scope: 'worker' }, ({ basePort, environment }) => ({\n          port: basePort,\n          env: environment,\n          debug: environment === 'development',\n        }))\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, describe }) => {\n        extendedTest('default config', ({ config }) => {\n          expect(config).toEqual({ port: 3000, env: 'development', debug: true })\n        })\n\n        describe('production', () => {\n          // Chained overwrites\n          extendedTest\n            .override('environment', 'production') // scope automatically inherited\n            .override('basePort', () => 8080)\n\n          extendedTest('production config', ({ config }) => {\n            expect(config).toEqual({ port: 8080, env: 'production', debug: false })\n          })\n        })\n      },\n    })\n\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts [ basic.test.ts ]\n      FixtureDependencyError: The \"environment\" fixture cannot be defined with a worker scope (inherited from the base fixture) inside the describe block. Define it at the top level of the file instead.\n       ❯ basic.test.ts:8:18\n            6|   });\n            7|   describe2(\"production\", () => {\n            8|     extendedTest.override(\"environment\", \"production\").override(\"baseP…\n             |                  ^\n            9|     extendedTest(\"production config\", ({ config }) => {\n           10|       expect2(config).toEqual({ port: 8080, env: \"production\", debug: …\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('throws an error when overriding file fixtures inside a describe', async () => {\n    const { stderr } = await runFixtureTests(() => {\n      return it\n        .extend('basePort', { scope: 'file' }, () => 3000)\n        .extend('environment', { scope: 'file' }, 'development')\n        .extend('config', { scope: 'file' }, ({ basePort, environment }) => ({\n          port: basePort,\n          env: environment,\n          debug: environment === 'development',\n        }))\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, describe }) => {\n        extendedTest('default config', ({ config }) => {\n          expect(config).toEqual({ port: 3000, env: 'development', debug: true })\n        })\n\n        describe('production', () => {\n          // Chained overwrites\n          extendedTest\n            .override('environment', { scope: 'file' }, 'production')\n            .override('basePort', { scope: 'file' }, () => 8080)\n\n          extendedTest('production config', ({ config }) => {\n            expect(config).toEqual({ port: 8080, env: 'production', debug: false })\n          })\n        })\n      },\n    })\n\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  basic.test.ts [ basic.test.ts ]\n      FixtureDependencyError: The \"environment\" fixture cannot be defined with a file scope inside the describe block. Define it at the top level of the file instead.\n       ❯ basic.test.ts:8:18\n            6|   });\n            7|   describe2(\"production\", () => {\n            8|     extendedTest.override(\"environment\", { scope: \"file\" }, \"productio…\n             |                  ^\n            9|     extendedTest(\"production config\", ({ config }) => {\n           10|       expect2(config).toEqual({ port: 8080, env: \"production\", debug: …\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n      \"\n    `)\n  })\n\n  test('top-level override without nested suites', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('staticValue', 'original-static')\n        .extend('functionValue', () => 'original-function')\n        .extend('asyncValue', async ({}, { onCleanup }) => {\n          log('async setup')\n          onCleanup(() => log('async cleanup'))\n          return 'original-async'\n        })\n        .extend('fileScoped', { scope: 'file' }, () => 'original-file')\n        .extend('workerScoped', { scope: 'worker' }, () => 'original-worker')\n    }, {\n      'basic.test.ts': ({ extendedTest, expect }) => {\n        // Override at top level (no describe)\n        extendedTest\n          .override('staticValue', 'overridden-static')\n          .override('functionValue', () => 'overridden-function')\n          .override('asyncValue', async ({}, { onCleanup }) => {\n            console.log('>> fixture | overridden async setup |', expect.getState().currentTestName)\n            onCleanup(() => console.log('>> fixture | overridden async cleanup |', expect.getState().currentTestName))\n            return 'overridden-async'\n          })\n          .override('fileScoped', { scope: 'file' }, () => 'overridden-file')\n          .override('workerScoped', { scope: 'worker' }, () => 'overridden-worker')\n\n        extendedTest('all fixtures are overridden', ({ staticValue, functionValue, asyncValue, fileScoped, workerScoped }) => {\n          expect(staticValue).toBe('overridden-static')\n          expect(functionValue).toBe('overridden-function')\n          expect(asyncValue).toBe('overridden-async')\n          expect(fileScoped).toBe('overridden-file')\n          expect(workerScoped).toBe('overridden-worker')\n        })\n\n        extendedTest('second test uses same overrides', ({ staticValue, functionValue, asyncValue }) => {\n          expect(staticValue).toBe('overridden-static')\n          expect(functionValue).toBe('overridden-function')\n          expect(asyncValue).toBe('overridden-async')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | overridden async setup | all fixtures are overridden\n      >> fixture | overridden async cleanup | all fixtures are overridden\n      >> fixture | overridden async setup | second test uses same overrides\n      >> fixture | overridden async cleanup | second test uses same overrides\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > all fixtures are overridden <time>\n       ✓ basic.test.ts > second test uses same overrides <time>\"\n    `)\n  })\n\n  test('top-level override with nested suites', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('staticValue', 'original-static')\n        .extend('functionValue', () => 'original-function')\n        .extend('asyncValue', async ({}, { onCleanup }) => {\n          log('async setup')\n          onCleanup(() => log('async cleanup'))\n          return 'original-async'\n        })\n        .extend('fileScoped', { scope: 'file' }, () => 'original-file')\n        .extend('workerScoped', { scope: 'worker' }, () => 'original-worker')\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, describe }) => {\n        // Override at top level\n        extendedTest\n          .override('staticValue', 'top-static')\n          .override('functionValue', () => 'top-function')\n          .override('asyncValue', async ({}, { onCleanup }) => {\n            console.log('>> fixture | top async setup |', expect.getState().currentTestName)\n            onCleanup(() => console.log('>> fixture | top async cleanup |', expect.getState().currentTestName))\n            return 'top-async'\n          })\n          .override('fileScoped', { scope: 'file' }, () => 'top-file')\n          .override('workerScoped', { scope: 'worker' }, () => 'top-worker')\n\n        extendedTest('top level uses overrides', ({ staticValue, functionValue, asyncValue, fileScoped, workerScoped }) => {\n          expect(staticValue).toBe('top-static')\n          expect(functionValue).toBe('top-function')\n          expect(asyncValue).toBe('top-async')\n          expect(fileScoped).toBe('top-file')\n          expect(workerScoped).toBe('top-worker')\n        })\n\n        describe('nested suite', () => {\n          // Override only static and function fixtures inside describe\n          extendedTest\n            .override('staticValue', 'nested-static')\n            .override('functionValue', () => 'nested-function')\n\n          extendedTest('nested uses mixed overrides', ({ staticValue, functionValue, asyncValue }) => {\n            expect(staticValue).toBe('nested-static')\n            expect(functionValue).toBe('nested-function')\n            // asyncValue still uses top-level override\n            expect(asyncValue).toBe('top-async')\n          })\n\n          describe('deeply nested suite', () => {\n            extendedTest.override('staticValue', 'deep-static')\n\n            extendedTest('deeply nested override', ({ staticValue, functionValue }) => {\n              expect(staticValue).toBe('deep-static')\n              expect(functionValue).toBe('nested-function')\n            })\n          })\n        })\n\n        extendedTest('back at top level', ({ staticValue, functionValue, asyncValue }) => {\n          expect(staticValue).toBe('top-static')\n          expect(functionValue).toBe('top-function')\n          expect(asyncValue).toBe('top-async')\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | top async setup | top level uses overrides\n      >> fixture | top async cleanup | top level uses overrides\n      >> fixture | top async setup | nested suite > nested uses mixed overrides\n      >> fixture | top async cleanup | nested suite > nested uses mixed overrides\n      >> fixture | top async setup | back at top level\n      >> fixture | top async cleanup | back at top level\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > top level uses overrides <time>\n       ✓ basic.test.ts > nested suite > nested uses mixed overrides <time>\n       ✓ basic.test.ts > nested suite > deeply nested suite > deeply nested override <time>\n       ✓ basic.test.ts > back at top level <time>\"\n    `)\n  })\n\n  test('top-level override with dependency chain', async () => {\n    const { stderr, fixtures, tests } = await runFixtureTests(({ log }) => {\n      return it\n        .extend('basePort', 3000)\n        .extend('config', ({ basePort }) => ({ port: basePort, host: 'localhost' }))\n        .extend('server', async ({ config }, { onCleanup }) => {\n          log('server start', config.port)\n          onCleanup(() => log('server stop'))\n          return { url: `http://${config.host}:${config.port}`, running: true }\n        })\n    }, {\n      'basic.test.ts': ({ extendedTest, expect, describe }) => {\n        // Override at top level\n        extendedTest.override('basePort', 8080)\n\n        extendedTest('top level uses overridden port', ({ config, server }) => {\n          expect(config.port).toBe(8080)\n          expect(server.url).toBe('http://localhost:8080')\n        })\n\n        describe('with custom host', () => {\n          extendedTest.override('config', ({ basePort }) => ({ port: basePort, host: '0.0.0.0' }))\n\n          extendedTest('nested uses custom host with top-level port', ({ config, server }) => {\n            expect(config.port).toBe(8080)\n            expect(config.host).toBe('0.0.0.0')\n            expect(server.url).toBe('http://0.0.0.0:8080')\n          })\n        })\n      },\n    })\n\n    expect(stderr).toBe('')\n    expect(fixtures).toMatchInlineSnapshot(`\n      \">> fixture | server start 8080 | top level uses overridden port\n      >> fixture | server stop | top level uses overridden port\n      >> fixture | server start 8080 | with custom host > nested uses custom host with top-level port\n      >> fixture | server stop | with custom host > nested uses custom host with top-level port\"\n    `)\n    expect(tests).toMatchInlineSnapshot(`\n      \" ✓ basic.test.ts > top level uses overridden port <time>\n       ✓ basic.test.ts > with custom host > nested uses custom host with top-level port <time>\"\n    `)\n  })\n})\n\nasync function runFixtureTests<T>(\n  extendedTest: ({ log, expectTypeOf }: { log: typeof console.log; expectTypeOf: typeof ExpectTypeOfFn }) => TestAPI<T>,\n  fs: Record<string, ((context: {\n    extendedTest: TestAPI<T>\n    expect: ExpectStatic\n    expectTypeOf: typeof ExpectTypeOfFn\n    describe: SuiteAPI\n    beforeAll: typeof beforeAll\n    afterAll: typeof afterAll\n  }) => unknown) | ViteUserConfig>,\n  config?: TestUserConfig,\n) {\n  if (typeof fs['vitest.config.js'] === 'object') {\n    fs['vitest.config.js'].test!.globals = true\n  }\n  const { stderr, stdout, fs: FS } = await runInlineTests({\n    'test.js': `\nexport const describe = globalThis.describe\nexport const expect = globalThis.expect\nexport const expectTypeOf = globalThis.expectTypeOf\nexport const extendedTest = (${stripIndent(extendedTest.toString())})({ log: (...args) => console.log('>> fixture |', ...args, '| ' + expect.getState().currentTestName), expectTypeOf })\nexport const beforeAll = globalThis.beforeAll\nexport const afterAll = globalThis.afterAll\n    `,\n    'vitest.config.js': { test: { globals: true } },\n    ...Object.entries(fs).reduce((acc, [key, value]) => {\n      if (typeof value === 'object' && !Array.isArray(value)) {\n        acc[key] = value\n      }\n      if (typeof value === 'function') {\n        acc[key] = [value, { imports: { './test.js': ['extendedTest', 'expect', 'expectTypeOf', 'describe', 'beforeAll', 'afterAll'] } }]\n      }\n      return acc\n    }, {} as TestFsStructure),\n  }, { ...config, sequence: { sequencer: StableTestFileOrderSorter } })\n\n  return {\n    stderr,\n    stdout,\n    fixtures: getFixtureLogs(stdout),\n    tests: getSuccessTests(stdout),\n    fs: FS,\n  }\n}\n\nfunction getSuccessTests(stdout: string) {\n  return stdout\n    .split('\\n')\n    .filter(f => f.startsWith(' ✓ '))\n    .map(f => f.replace(/\\d+ms/, '<time>'))\n    .join('\\n')\n}\n\nfunction getFixtureLogs(stdout: string) {\n  return stdout\n    .split('\\n')\n    .filter(f => f.startsWith('>> fixture |'))\n    .join('\\n')\n}\n\nclass StableTestFileOrderSorter {\n  sort(files: TestSpecification[]) {\n    return files.sort((a, b) => a.moduleId.localeCompare(b.moduleId))\n  }\n\n  shard(files: TestSpecification[]) {\n    return files\n  }\n}\n"
  },
  {
    "path": "test/cli/test/server-url.test.ts",
    "content": "import basicSsl from '@vitejs/plugin-basic-ssl'\nimport { expect, it } from 'vitest'\n\nimport { runInlineTests } from '../../test-utils'\n\nit('api server-url http', async () => {\n  const { stdout, stderr } = await runInlineTests(\n    { 'basic.test.js': `test(\"basic\")` },\n    {\n      api: true,\n      globals: true,\n    },\n  )\n  expect(stderr).toBe('')\n  expect(stdout).toContain('API started at http://localhost:51204/')\n  expect(stdout).toContain('Test Files  1 skipped')\n})\n\nit('api server-url https', async () => {\n  const { stdout, stderr } = await runInlineTests(\n    { 'basic.test.js': `test(\"basic\")` },\n    {\n      api: true,\n      globals: true,\n      $viteConfig: {\n        plugins: [basicSsl()],\n      },\n    },\n  )\n  expect(stderr).toBe('')\n  expect(stdout).toContain('API started at https://localhost:51204/')\n  expect(stdout).toContain('Test Files  1 skipped')\n})\n\nit.todo('api server-url fallback if resolvedUrls is null')\n"
  },
  {
    "path": "test/cli/test/setup-files.test.ts",
    "content": "import { promises as fs } from 'node:fs'\nimport { describe, expect, it, test } from 'vitest'\nimport { editFile, runVitest } from '../../test-utils'\n\ntest.each(['threads', 'vmThreads'])('%s: print stdout and stderr correctly when called in the setup file', async (pool) => {\n  const { stdout, stderr } = await runVitest({\n    root: 'fixtures/setup-files',\n    include: ['empty.test.ts'],\n    setupFiles: ['./console-setup.ts'],\n    pool,\n  })\n\n  const filepath = 'empty.test.ts'\n  expect(stdout).toContain(`stdout | ${filepath}`)\n  expect(stderr).toContain(`stderr | ${filepath}`)\n})\n\ndescribe('setup files with forceRerunTrigger', () => {\n  const file = './fixtures/setup-files/empty-setup.ts'\n\n  async function run() {\n    return await runVitest({\n      root: 'fixtures/setup-files',\n      include: ['empty.test.ts'],\n      setupFiles: ['./empty-setup.ts'],\n      changed: true,\n    })\n  }\n\n  // Note that this test will fail locally if you have uncommitted changes\n  it.runIf(process.env.GITHUB_ACTIONS && !process.env.ECOSYSTEM_CI)('should run no tests if setup file is not changed', async () => {\n    const { stdout } = await run()\n    expect(stdout).toContain('No test files found, exiting with code 0')\n  })\n\n  it('should run the whole test suite if setup file is changed', async () => {\n    const codes = 'export const a = 1'\n    editFile(file, () => codes)\n    await fs.writeFile(file, codes, 'utf-8')\n    const { stdout } = await run()\n    expect(stdout).toContain('1 passed')\n  })\n})\n"
  },
  {
    "path": "test/cli/test/shared-env.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runInlineTests, StableTestFileOrderSorter } from '../../test-utils'\n\ntest.each([\n  1,\n  2,\n])('the environment is shared between tests with maxWorkers: %s', async (maxWorkers) => {\n  const testCode = `\ntest('document is the same', () => {\n  expect(__vitest_worker__.ctx.config.isolate).toBe(false)\n  expect(__vitest_worker__.ctx.config.maxWorkers).toBe(${maxWorkers})\n  expect(globalThis.__document ??= document).toBe(document)\n})\n    `\n  const { stderr } = await runInlineTests({\n    '1.test.js': testCode,\n    '2.test.js': testCode,\n    '3.test.js': testCode,\n    '4.test.js': testCode,\n    'vitest.config.js': {\n      test: {\n        environment: 'happy-dom',\n        globals: true,\n        isolate: false,\n      },\n    },\n  }, {\n    sequence: { sequencer: StableTestFileOrderSorter },\n    maxWorkers,\n  })\n\n  expect(stderr).toBe('')\n})\n"
  },
  {
    "path": "test/cli/test/signal.test.ts",
    "content": "import type { UserConsoleLog } from 'vitest'\nimport type { Reporter, Vitest } from 'vitest/node'\nimport { expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\ntest('timeout aborts the signal without fixtures', async () => {\n  const { stderr, results } = await runInlineTests({\n    'basic.test.ts': /* ts */`\n      import { test } from 'vitest'\n      import { setTimeout } from 'node:timers/promises'\n      test('timeouts', async ({ signal, task, example }) => {\n        signal.addEventListener('abort', () => {\n          task.meta.aborted = true\n        })\n        await setTimeout(100)\n      }, 10)\n    `,\n  })\n  expect(stderr).toContain('Test timed out in 10ms.')\n  expect(results).toHaveLength(1)\n  expect(results[0].children.at(0)?.meta()).toEqual({\n    aborted: true,\n  })\n})\n\ntest('timeout aborts the signal', async () => {\n  const { stderr, results } = await runInlineTests({\n    'basic.test.ts': /* ts */`\n      import { test } from 'vitest'\n      import { setTimeout } from 'node:timers/promises'\n      test.extend({\n        // .extend to force fixture initialisation\n        example: true,\n      })('timeouts', async ({ signal, task, example }) => {\n        signal.addEventListener('abort', () => {\n          task.meta.aborted = true\n        })\n        await setTimeout(100)\n      }, 10)\n    `,\n  })\n  expect(stderr).toContain('Test timed out in 10ms.')\n  expect(results).toHaveLength(1)\n  expect(results[0].children.at(0)?.meta()).toEqual({\n    aborted: true,\n  })\n})\n\ntest('timeout aborts all signals in concurrent tests', async () => {\n  const { stderr, results } = await runInlineTests({\n    'basic.test.ts': /* ts */`\n      import { test } from 'vitest'\n      import { setTimeout } from 'node:timers/promises'\n      test\n        // .extend to force fixture initialisation\n        .extend({ example: true })\n        .concurrent\n        .for([1, 1, 1])\n      ('timeouts', async (_, { signal, task, example }) => {\n        signal.addEventListener('abort', () => {\n          task.meta.aborted = true\n        })\n        await setTimeout(100)\n      }, 10)\n    `,\n  })\n  expect(stderr).toContain('Test timed out in 10ms.')\n  expect(results).toHaveLength(1)\n  expect(results[0].children.at(0)?.meta()).toEqual({\n    aborted: true,\n  })\n  expect(results[0].children.at(1)?.meta()).toEqual({\n    aborted: true,\n  })\n  expect(results[0].children.at(2)?.meta()).toEqual({\n    aborted: true,\n  })\n})\n\nclass AbortReporter implements Reporter {\n  vitest!: Vitest\n  onInit(vitest: Vitest) {\n    this.vitest = vitest\n  }\n\n  onUserConsoleLog(log: UserConsoleLog) {\n    if (log.content.includes('ready')) {\n      this.vitest.cancelCurrentRun('keyboard-input')\n    }\n  }\n}\n\ntest('cancelling test run aborts the signal', async () => {\n  const { results, stderr } = await runInlineTests({\n    'basic.test.ts': /* ts */ `\n      import { test } from 'vitest'\n      test('aborted', async ({ signal, task }) => {\n        return new Promise(resolve => {\n          signal.addEventListener('abort', () => {\n            task.meta.aborted = true\n            resolve()\n          })\n          console.log('ready')\n        })\n      }, Infinity)\n    `,\n  }, {\n    reporters: [\n      'default',\n      new AbortReporter(),\n    ],\n  })\n  expect(stderr).toBe('')\n  expect(results).toHaveLength(1)\n  expect(results[0].children.at(0)?.meta()).toEqual({\n    aborted: true,\n  })\n})\n\ntest('cancelling test run aborts the signal in all concurrent tests', async () => {\n  const { results, stderr } = await runInlineTests({\n    'basic.test.ts': /* ts */`\n      import { test } from 'vitest'\n      test.concurrent.for([1, 2, 3])(\n        'aborted',\n        { timeout: Infinity },\n         async (number, { signal, task }) => {\n          return new Promise(resolve => {\n            signal.addEventListener('abort', () => {\n              task.meta.aborted = true\n              resolve()\n            })\n            if (number === 3) {\n              console.log('ready')\n            }\n          })\n        })\n    `,\n  }, {\n    reporters: [\n      'default',\n      new AbortReporter(),\n    ],\n  })\n  expect(stderr).toBe('')\n  expect(results).toHaveLength(1)\n  expect(results[0].children.at(0)?.meta()).toEqual({\n    aborted: true,\n  })\n  expect(results[0].children.at(1)?.meta()).toEqual({\n    aborted: true,\n  })\n  expect(results[0].children.at(2)?.meta()).toEqual({\n    aborted: true,\n  })\n})\n"
  },
  {
    "path": "test/cli/test/skip-note.test.ts",
    "content": "import type { TestCase } from 'vitest/node'\nimport { resolve } from 'node:path'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nconst root = resolve(import.meta.dirname, '../fixtures/skip-note')\n\ntest.for([\n  { reporter: 'default', isTTY: true },\n  { reporter: 'verbose', isTTY: false },\n])('can leave a note when skipping in the $reporter reporter', async ({ reporter, isTTY }) => {\n  const { ctx, stdout, stderr } = await runVitest({\n    root,\n    reporters: [\n      [reporter, { isTTY }],\n    ],\n  })\n\n  expect(stderr).toBe('')\n  expect(stdout).toMatch(/my skipped test (?:\\d+ms )?\\[custom message\\]/)\n\n  expect(ctx).toBeDefined()\n  const testTask = ctx!.state.getFiles()[0].tasks[0]\n  const test = ctx!.state.getReportedEntity(testTask) as TestCase\n  const result = test.result()\n  expect(result).toEqual({\n    state: 'skipped',\n    note: 'custom message',\n  })\n})\n"
  },
  {
    "path": "test/cli/test/ssr-runner.test.ts",
    "content": "import { version } from 'vite'\nimport { expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\n// https://github.com/vitest-dev/vitest/issues/9324\nit('ssr runner.import() works in configureServer', async () => {\n  const { stderr } = await runVitest({ root: './fixtures/ssr-runner' })\n  expect(stderr).toBe('')\n  expect((globalThis as any).__testSsrRunner).toBe(version)\n})\n\nit('works in project', async () => {\n  const { stderr } = await runVitest({ root: './fixtures/ssr-runner-project' })\n  expect(stderr).toBe('')\n  expect((globalThis as any).__testSsrRunnerProject).toBe(version)\n})\n"
  },
  {
    "path": "test/cli/test/stacktraces.test.ts",
    "content": "import { resolve } from 'pathe'\nimport { glob } from 'tinyglobby'\nimport { describe, expect, it } from 'vitest'\nimport { rolldownVersion } from 'vitest/node'\nimport { runInlineTests, runVitest } from '../../test-utils'\n\n// To prevent the warning coming up in snapshots\nprocess.setMaxListeners(20)\n\ndescribe('stacktraces should respect sourcemaps', async () => {\n  const root = resolve(import.meta.dirname, '../fixtures/stacktraces')\n  const files = await glob(['*.test.*'], { cwd: root, expandDirectories: false })\n\n  for (const file of files) {\n    it(file, async () => {\n      const { stderr } = await runVitest({ root }, [file])\n\n      expect(stderr).toBeTruthy()\n      const lines = String(stderr).split(/\\n/g)\n      const index = lines.findIndex(val => val.includes(`${file}:`))\n      const msg = lines.slice(index, index + 8).join('\\n')\n      expect(removeLines(msg)).toMatchSnapshot()\n    })\n  }\n})\n\ndescribe('stacktraces should pick error frame if present', async () => {\n  const root = resolve(import.meta.dirname, '../fixtures/stacktraces')\n  const files = ['frame.spec.imba']\n\n  for (const file of files) {\n    it(file, async () => {\n      const { stderr } = await runVitest({ root }, [file])\n\n      expect(stderr).toBeTruthy()\n      const lines = String(stderr).split(/\\n/g)\n      const index = lines.findIndex(val => val.includes('FAIL'))\n      const msg = lines.slice(index, index + 8).join('\\n')\n      expect(msg).toMatchSnapshot()\n    })\n  }\n})\n\ndescribe('stacktrace should print error frame source file correctly', async () => {\n  const root = resolve(import.meta.dirname, '../fixtures/stacktraces')\n  const testFile = resolve(root, './error-in-deps.test.js')\n\n  it('error-in-deps', async () => {\n    const { stderr } = await runVitest({ root }, [testFile])\n\n    // expect to print framestack of foo.js\n    expect(removeLines(stderr)).toMatchSnapshot()\n  })\n})\n\ndescribe('stacktrace filtering', async () => {\n  const root = resolve(import.meta.dirname, '../fixtures/stacktraces')\n  const testFile = resolve(root, './error-with-stack.test.js')\n\n  it('filters stacktraces', async () => {\n    const { stderr } = await runVitest({\n      root,\n      onStackTrace: (_error, { method }) => method !== 'b',\n    }, [testFile])\n\n    expect(removeLines(stderr)).toMatchSnapshot()\n  })\n})\n\ndescribe('stacktrace in dependency package', () => {\n  const root = resolve(import.meta.dirname, '../fixtures/stacktraces')\n  const testFile = resolve(root, './error-in-package.test.js')\n\n  it('external', async () => {\n    const { stderr } = await runVitest({\n      root,\n    }, [testFile])\n    expect(removeNodeModules(removeLines(stderr))).toMatchSnapshot()\n  })\n\n  it('inline', async () => {\n    const { stderr } = await runVitest({\n      root,\n      server: {\n        deps: {\n          inline: [/@test\\/test-dep-error/],\n        },\n      },\n    }, [testFile])\n    expect(removeNodeModules(removeLines(stderr))).toMatchSnapshot()\n  })\n})\n\nit('stacktrace in vmThreads', async () => {\n  const root = resolve(import.meta.dirname, '../fixtures/stacktraces')\n  const testFile = resolve(root, './error-with-stack.test.js')\n  const { stderr } = await runVitest({\n    root,\n    pool: 'vmThreads',\n  }, [testFile])\n\n  expect(removeLines(stderr)).toMatchSnapshot()\n})\n\nfunction removeLines(log: string) {\n  return log.replace(/⎯{2,}/g, '⎯⎯')\n}\n\nfunction removeNodeModules(log: string) {\n  return log.replace(/[^ ]*\\/node_modules\\//g, '(NODE_MODULES)/')\n}\n\nit('custom helper with captureStackTrace', async () => {\n  const { stderr, errorTree } = await runVitest({\n    root: resolve(import.meta.dirname, '../fixtures/stacktraces-custom-helper'),\n  })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts > sync\n    AssertionError: expected 3 to be 4 // Object.is equality\n\n    - Expected\n    + Received\n\n    - 4\n    + 3\n\n     ❯ basic.test.ts:5:3\n          3|\n          4| test(\"sync\", async () => {\n          5|   assertHelper(3, 4);\n           |   ^\n          6| });\n          7|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯\n\n     FAIL  basic.test.ts > async\n    AssertionError: expected 3 to be 4 // Object.is equality\n\n    - Expected\n    + Received\n\n    - 4\n    + 3\n\n     ❯ basic.test.ts:9:3\n          7|\n          8| test(\"async\", async () => {\n          9|   await assertHelperAsync(3, 4)\n           |   ^\n         10| })\n         11|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯\n\n     FAIL  basic.test.ts > bad\n    AssertionError: expected 3 to be 4 // Object.is equality\n\n    - Expected\n    + Received\n\n    - 4\n    + 3\n\n     ❯ assertHelperBad helper.ts:23:20\n         21|\n         22| export function assertHelperBad(expected: any, actual: any) {\n         23|   expect(expected).toBe(actual);\n           |                    ^\n         24| }\n         25|\n     ❯ basic.test.ts:13:3\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯\n\n    \"\n  `)\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"async\": [\n          \"expected 3 to be 4 // Object.is equality\",\n        ],\n        \"bad\": [\n          \"expected 3 to be 4 // Object.is equality\",\n        ],\n        \"sync\": [\n          \"expected 3 to be 4 // Object.is equality\",\n        ],\n      },\n    }\n  `)\n})\n\nit('resolves/rejects', async () => {\n  const { stderr, errorTree } = await runInlineTests({\n    'repro.test.ts': `\n      import { test, expect } from 'vitest'\n\n      test('resolves: resolved promise with mismatched value', async () => {\n        await expect(Promise.resolve(3)).resolves.toBe(4)\n      })\n\n      test('rejects: rejected promise with mismatched value', async () => {\n        await expect(Promise.reject(3)).rejects.toBe(4)\n      })\n\n      test('rejects: resolves when rejection expected', async () => {\n        await expect(Promise.resolve(3)).rejects.toBe(4)\n      })\n\n      test('resolves: rejects when resolve expected', async () => {\n        await expect(Promise.reject(3)).resolves.toBe(4)\n      })\n    `,\n  })\n\n  if (rolldownVersion) {\n    expect(stderr).toMatchInlineSnapshot(`\n      \"\n      ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 4 ⎯⎯⎯⎯⎯⎯⎯\n\n       FAIL  repro.test.ts > resolves: resolved promise with mismatched value\n      AssertionError: expected 3 to be 4 // Object.is equality\n\n      - Expected\n      + Received\n\n      - 4\n      + 3\n\n       ❯ repro.test.ts:5:41\n            3|\n            4|       test('resolves: resolved promise with mismatched value', async (…\n            5|         await expect(Promise.resolve(3)).resolves.toBe(4)\n             |                                         ^\n            6|       })\n            7|\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/4]⎯\n\n       FAIL  repro.test.ts > rejects: rejected promise with mismatched value\n      AssertionError: expected 3 to be 4 // Object.is equality\n\n      - Expected\n      + Received\n\n      - 4\n      + 3\n\n       ❯ repro.test.ts:9:40\n            7|\n            8|       test('rejects: rejected promise with mismatched value', async ()…\n            9|         await expect(Promise.reject(3)).rejects.toBe(4)\n             |                                        ^\n           10|       })\n           11|\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/4]⎯\n\n       FAIL  repro.test.ts > rejects: resolves when rejection expected\n      AssertionError: promise resolved \"3\" instead of rejecting\n\n      - Expected:\n      Error {\n        \"message\": \"rejected promise\",\n      }\n\n      + Received:\n      3\n\n       ❯ repro.test.ts:13:41\n           11|\n           12|       test('rejects: resolves when rejection expected', async () => {\n           13|         await expect(Promise.resolve(3)).rejects.toBe(4)\n             |                                         ^\n           14|       })\n           15|\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/4]⎯\n\n       FAIL  repro.test.ts > resolves: rejects when resolve expected\n      AssertionError: promise rejected \"3\" instead of resolving\n       ❯ repro.test.ts:17:40\n           15|\n           16|       test('resolves: rejects when resolve expected', async () => {\n           17|         await expect(Promise.reject(3)).resolves.toBe(4)\n             |                                        ^\n           18|       })\n           19|\n\n      ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/4]⎯\n\n      \"\n    `)\n  }\n  else {\n    expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 4 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  repro.test.ts > resolves: resolved promise with mismatched value\n    AssertionError: expected 3 to be 4 // Object.is equality\n\n    - Expected\n    + Received\n\n    - 4\n    + 3\n\n     ❯ repro.test.ts:5:40\n          3|\n          4|       test('resolves: resolved promise with mismatched value', async (…\n          5|         await expect(Promise.resolve(3)).resolves.toBe(4)\n           |                                        ^\n          6|       })\n          7|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/4]⎯\n\n     FAIL  repro.test.ts > rejects: rejected promise with mismatched value\n    AssertionError: expected 3 to be 4 // Object.is equality\n\n    - Expected\n    + Received\n\n    - 4\n    + 3\n\n     ❯ repro.test.ts:9:39\n          7|\n          8|       test('rejects: rejected promise with mismatched value', async ()…\n          9|         await expect(Promise.reject(3)).rejects.toBe(4)\n           |                                       ^\n         10|       })\n         11|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/4]⎯\n\n     FAIL  repro.test.ts > rejects: resolves when rejection expected\n    AssertionError: promise resolved \"3\" instead of rejecting\n\n    - Expected:\n    Error {\n      \"message\": \"rejected promise\",\n    }\n\n    + Received:\n    3\n\n     ❯ repro.test.ts:13:40\n         11|\n         12|       test('rejects: resolves when rejection expected', async () => {\n         13|         await expect(Promise.resolve(3)).rejects.toBe(4)\n           |                                        ^\n         14|       })\n         15|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/4]⎯\n\n     FAIL  repro.test.ts > resolves: rejects when resolve expected\n    AssertionError: promise rejected \"3\" instead of resolving\n     ❯ repro.test.ts:17:39\n         15|\n         16|       test('resolves: rejects when resolve expected', async () => {\n         17|         await expect(Promise.reject(3)).resolves.toBe(4)\n           |                                       ^\n         18|       })\n         19|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/4]⎯\n\n    \"\n  `)\n  }\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"repro.test.ts\": {\n        \"rejects: rejected promise with mismatched value\": [\n          \"expected 3 to be 4 // Object.is equality\",\n        ],\n        \"rejects: resolves when rejection expected\": [\n          \"promise resolved \"3\" instead of rejecting\",\n        ],\n        \"resolves: rejects when resolve expected\": [\n          \"promise rejected \"3\" instead of resolving\",\n        ],\n        \"resolves: resolved promise with mismatched value\": [\n          \"expected 3 to be 4 // Object.is equality\",\n        ],\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/standalone.test.ts",
    "content": "import { test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('test run is not started when --standalone', async () => {\n  const { vitest } = await runVitest({\n    root: 'fixtures/standalone',\n    standalone: true,\n    watch: true,\n  })\n\n  await vitest.waitForStdout('Vitest is running in standalone mode. Edit a test file to rerun tests.')\n  await vitest.waitForStdout('PASS  Waiting for file changes...')\n  await vitest.waitForStdout('press h to show help, press q to quit')\n})\n\ntest('test run is started when --standalone and filename filter', async () => {\n  const { vitest } = await runVitest({\n    root: 'fixtures/standalone',\n    standalone: true,\n    watch: true,\n  }, ['basic.test.ts'])\n\n  await vitest.waitForStdout('✓ basic.test.ts > example')\n  await vitest.waitForStdout('Test Files  1 passed (1)')\n  await vitest.waitForStdout('Tests  1 passed (1)')\n\n  await vitest.waitForStdout('PASS  Waiting for file changes...')\n  await vitest.waitForStdout('press h to show help, press q to quit')\n})\n"
  },
  {
    "path": "test/cli/test/static-collect.test.ts",
    "content": "import type { CliOptions, TestCase, TestModule, TestSuite } from 'vitest/node'\nimport { runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { expect, onTestFinished, test } from 'vitest'\nimport { createVitest, rolldownVersion } from 'vitest/node'\n\ntest('correctly collects a simple test', async () => {\n  const testModule = await collectTests(`\n    import { test, expect } from 'vitest'\n\n    describe('math operations', () => {\n      test('adds numbers', () => {\n        expect(1 + 1).toBe(2)\n      })\n\n      test.skip('subtracts numbers', () => {\n        expect(2 - 1).toBe(1)\n      })\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"math operations\": {\n        \"adds numbers\": {\n          \"errors\": [],\n          \"fullName\": \"math operations > adds numbers\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"subtracts numbers\": {\n          \"errors\": [],\n          \"fullName\": \"math operations > subtracts numbers\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"9:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests starting with \"test\"', async () => {\n  const testModule = await collectTests(`\n    import { testSomething, testAnother } from './test-helpers'\n\n    describe('custom test functions', () => {\n      testSomething('works with testSomething', () => {})\n      testAnother('works with testAnother', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"custom test functions\": {\n        \"works with testAnother\": {\n          \"errors\": [],\n          \"fullName\": \"custom test functions > works with testAnother\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"works with testSomething\": {\n          \"errors\": [],\n          \"fullName\": \"custom test functions > works with testSomething\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests ending with \"Test\"', async () => {\n  const testModule = await collectTests(`\n    import { unitTest, integrationTest } from './test-helpers'\n\n    describe('custom test functions', () => {\n      unitTest('works with unitTest', () => {})\n      integrationTest('works with integrationTest', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"custom test functions\": {\n        \"works with integrationTest\": {\n          \"errors\": [],\n          \"fullName\": \"custom test functions > works with integrationTest\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"works with unitTest\": {\n          \"errors\": [],\n          \"fullName\": \"custom test functions > works with unitTest\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with only modifier', async () => {\n  const testModule = await collectTests(`\n    import { test, testFoo, barTest } from 'vitest'\n\n    describe('only tests', () => {\n      test.only('regular test with only', () => {})\n      testFoo.only('testFoo with only', () => {})\n      barTest.only('barTest with only', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"only tests\": {\n        \"barTest with only\": {\n          \"errors\": [],\n          \"fullName\": \"only tests > barTest with only\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"7:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"regular test with only\": {\n          \"errors\": [],\n          \"fullName\": \"only tests > regular test with only\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"testFoo with only\": {\n          \"errors\": [],\n          \"fullName\": \"only tests > testFoo with only\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with skip modifier', async () => {\n  const testModule = await collectTests(`\n    import { test, testFoo, barTest } from 'vitest'\n\n    describe('skip tests', () => {\n      test.skip('regular test with skip', () => {})\n      testFoo.skip('testFoo with skip', () => {})\n      barTest.skip('barTest with skip', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"skip tests\": {\n        \"barTest with skip\": {\n          \"errors\": [],\n          \"fullName\": \"skip tests > barTest with skip\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"7:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"regular test with skip\": {\n          \"errors\": [],\n          \"fullName\": \"skip tests > regular test with skip\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"testFoo with skip\": {\n          \"errors\": [],\n          \"fullName\": \"skip tests > testFoo with skip\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with todo modifier', async () => {\n  const testModule = await collectTests(`\n    import { test, testFoo, barTest } from 'vitest'\n\n    describe('todo tests', () => {\n      test.todo('regular test with todo', () => {})\n      testFoo.todo('testFoo with todo', () => {})\n      barTest.todo('barTest with todo', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"todo tests\": {\n        \"barTest with todo\": {\n          \"errors\": [],\n          \"fullName\": \"todo tests > barTest with todo\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"7:6\",\n          \"mode\": \"todo\",\n          \"state\": \"skipped\",\n        },\n        \"regular test with todo\": {\n          \"errors\": [],\n          \"fullName\": \"todo tests > regular test with todo\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"todo\",\n          \"state\": \"skipped\",\n        },\n        \"testFoo with todo\": {\n          \"errors\": [],\n          \"fullName\": \"todo tests > testFoo with todo\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"todo\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects nested suites with custom test functions', async () => {\n  const testModule = await collectTests(`\n    import { test, testUnit, integrationTest } from 'vitest'\n\n    describe('outer suite', () => {\n      test('regular test', () => {})\n\n      describe('inner suite', () => {\n        testUnit('unit test', () => {})\n\n        describe('deeply nested', () => {\n          integrationTest('integration test', () => {})\n        })\n      })\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"outer suite\": {\n        \"inner suite\": {\n          \"deeply nested\": {\n            \"integration test\": {\n              \"errors\": [],\n              \"fullName\": \"outer suite > inner suite > deeply nested > integration test\",\n              \"id\": \"-1732721377_0_1_1_0\",\n              \"location\": \"11:10\",\n              \"mode\": \"run\",\n              \"state\": \"pending\",\n            },\n          },\n          \"unit test\": {\n            \"errors\": [],\n            \"fullName\": \"outer suite > inner suite > unit test\",\n            \"id\": \"-1732721377_0_1_0\",\n            \"location\": \"8:8\",\n            \"mode\": \"run\",\n            \"state\": \"pending\",\n          },\n        },\n        \"regular test\": {\n          \"errors\": [],\n          \"fullName\": \"outer suite > regular test\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('ignores test.scoped and test.override', async () => {\n  const testModule = await collectTests(`\n    import { test as base } from 'vitest'\n\n    const test = base.extend({\n      fixture: async ({}, use) => {\n        await use('value')\n      },\n    })\n\n    test.scoped({ fixture: 'value' })\n    test.override({ fixture: 'value' })\n\n    describe('extended tests', () => {\n      test('uses extended test', () => {})\n      test.skip('skips extended test', () => {})\n      test.only('only extended test', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"extended tests\": {\n        \"only extended test\": {\n          \"errors\": [],\n          \"fullName\": \"extended tests > only extended test\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"16:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"skips extended test\": {\n          \"errors\": [],\n          \"fullName\": \"extended tests > skips extended test\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"15:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"uses extended test\": {\n          \"errors\": [],\n          \"fullName\": \"extended tests > uses extended test\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"14:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests from test.extend', async () => {\n  const testModule = await collectTests(`\n    import { test as base } from 'vitest'\n\n    const test = base.extend({\n      fixture: async ({}, use) => {\n        await use('value')\n      }\n    })\n\n    describe('extended tests', () => {\n      test('uses extended test', () => {})\n      test.skip('skips extended test', () => {})\n      test.only('only extended test', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"extended tests\": {\n        \"only extended test\": {\n          \"errors\": [],\n          \"fullName\": \"extended tests > only extended test\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"13:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"skips extended test\": {\n          \"errors\": [],\n          \"fullName\": \"extended tests > skips extended test\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"12:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"uses extended test\": {\n          \"errors\": [],\n          \"fullName\": \"extended tests > uses extended test\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"11:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests imported from another file', async () => {\n  const testModule = await collectTests(`\n    import { myTest } from './my-test'\n\n    describe('imported test function', () => {\n      myTest('uses imported test', () => {})\n      myTest.skip('skips imported test', () => {})\n      myTest.only('only imported test', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"imported test function\": {\n        \"only imported test\": {\n          \"errors\": [],\n          \"fullName\": \"imported test function > only imported test\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"7:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"skips imported test\": {\n          \"errors\": [],\n          \"fullName\": \"imported test function > skips imported test\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"uses imported test\": {\n          \"errors\": [],\n          \"fullName\": \"imported test function > uses imported test\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects mixed test function names', async () => {\n  const testModule = await collectTests(`\n    import { it, test, testUnit, integrationTest } from 'vitest'\n\n    describe('mixed tests', () => {\n      it('classic it syntax', () => {})\n      test('standard test', () => {})\n      testUnit('starts with test', () => {})\n      integrationTest('ends with Test', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"mixed tests\": {\n        \"classic it syntax\": {\n          \"errors\": [],\n          \"fullName\": \"mixed tests > classic it syntax\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"ends with Test\": {\n          \"errors\": [],\n          \"fullName\": \"mixed tests > ends with Test\",\n          \"id\": \"-1732721377_0_3\",\n          \"location\": \"8:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"standard test\": {\n          \"errors\": [],\n          \"fullName\": \"mixed tests > standard test\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"starts with test\": {\n          \"errors\": [],\n          \"fullName\": \"mixed tests > starts with test\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"7:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with all modifiers on custom functions', async () => {\n  const testModule = await collectTests(`\n    import { testCustom } from './test-helpers'\n\n    describe('custom test with modifiers', () => {\n      testCustom('normal custom test', () => {})\n      testCustom.skip('skipped custom test', () => {})\n      testCustom.only('only custom test', () => {})\n      testCustom.todo('todo custom test', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"custom test with modifiers\": {\n        \"normal custom test\": {\n          \"errors\": [],\n          \"fullName\": \"custom test with modifiers > normal custom test\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"only custom test\": {\n          \"errors\": [],\n          \"fullName\": \"custom test with modifiers > only custom test\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"7:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"skipped custom test\": {\n          \"errors\": [],\n          \"fullName\": \"custom test with modifiers > skipped custom test\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"todo custom test\": {\n          \"errors\": [],\n          \"fullName\": \"custom test with modifiers > todo custom test\",\n          \"id\": \"-1732721377_0_3\",\n          \"location\": \"8:6\",\n          \"mode\": \"todo\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests in skipped suites', async () => {\n  const testModule = await collectTests(`\n    import { test, testFoo, barTest } from 'vitest'\n\n    describe.skip('skipped suite', () => {\n      test('regular test in skipped suite', () => {})\n      testFoo('testFoo in skipped suite', () => {})\n      barTest('barTest in skipped suite', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"skipped suite\": {\n        \"barTest in skipped suite\": {\n          \"errors\": [],\n          \"fullName\": \"skipped suite > barTest in skipped suite\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"7:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"regular test in skipped suite\": {\n          \"errors\": [],\n          \"fullName\": \"skipped suite > regular test in skipped suite\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"testFoo in skipped suite\": {\n          \"errors\": [],\n          \"fullName\": \"skipped suite > testFoo in skipped suite\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests in only suites', async () => {\n  const testModule = await collectTests(`\n    import { test, testFoo, barTest } from 'vitest'\n\n    describe.only('only suite', () => {\n      test('regular test in only suite', () => {})\n      testFoo('testFoo in only suite', () => {})\n      barTest('barTest in only suite', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"only suite\": {\n        \"barTest in only suite\": {\n          \"errors\": [],\n          \"fullName\": \"only suite > barTest in only suite\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"7:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"regular test in only suite\": {\n          \"errors\": [],\n          \"fullName\": \"only suite > regular test in only suite\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"testFoo in only suite\": {\n          \"errors\": [],\n          \"fullName\": \"only suite > testFoo in only suite\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with each modifier', async () => {\n  const testModule = await collectTests(`\n    import { test, testFoo, barTest } from 'vitest'\n\n    describe('each tests', () => {\n      test.each([1, 2, 3])('test with each %i', (num) => {})\n      testFoo.each([1, 2, 3])('testFoo with each %i', (num) => {})\n      barTest.each([1, 2, 3])('barTest with each %i', (num) => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"each tests\": {\n        \"barTest with each %i\": {\n          \"dynamic\": true,\n          \"each\": true,\n          \"errors\": [],\n          \"fullName\": \"each tests > barTest with each %i\",\n          \"id\": \"-1732721377_0_2-dynamic\",\n          \"location\": \"7:28\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"test with each %i\": {\n          \"dynamic\": true,\n          \"each\": true,\n          \"errors\": [],\n          \"fullName\": \"each tests > test with each %i\",\n          \"id\": \"-1732721377_0_0-dynamic\",\n          \"location\": \"5:25\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"testFoo with each %i\": {\n          \"dynamic\": true,\n          \"each\": true,\n          \"errors\": [],\n          \"fullName\": \"each tests > testFoo with each %i\",\n          \"id\": \"-1732721377_0_1-dynamic\",\n          \"location\": \"6:28\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects complex nested structure with custom functions', async () => {\n  const testModule = await collectTests(`\n    import { test, it, testUnit, integrationTest } from 'vitest'\n\n    describe('root suite', () => {\n      test('root test', () => {})\n\n      describe('unit tests', () => {\n        testUnit('first unit test', () => {})\n        testUnit.skip('skipped unit test', () => {})\n\n        describe.skip('skipped nested', () => {\n          testUnit('test in skipped suite', () => {})\n        })\n      })\n\n      describe.only('integration tests', () => {\n        integrationTest('first integration', () => {})\n        integrationTest.only('focused integration', () => {})\n        integrationTest.todo('planned integration', () => {})\n      })\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"root suite\": {\n        \"integration tests\": {\n          \"first integration\": {\n            \"errors\": [],\n            \"fullName\": \"root suite > integration tests > first integration\",\n            \"id\": \"-1732721377_0_2_0\",\n            \"location\": \"17:8\",\n            \"mode\": \"run\",\n            \"state\": \"pending\",\n          },\n          \"focused integration\": {\n            \"errors\": [],\n            \"fullName\": \"root suite > integration tests > focused integration\",\n            \"id\": \"-1732721377_0_2_1\",\n            \"location\": \"18:8\",\n            \"mode\": \"run\",\n            \"state\": \"pending\",\n          },\n          \"planned integration\": {\n            \"errors\": [],\n            \"fullName\": \"root suite > integration tests > planned integration\",\n            \"id\": \"-1732721377_0_2_2\",\n            \"location\": \"19:8\",\n            \"mode\": \"run\",\n            \"state\": \"pending\",\n          },\n        },\n        \"root test\": {\n          \"errors\": [],\n          \"fullName\": \"root suite > root test\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"unit tests\": {\n          \"first unit test\": {\n            \"errors\": [],\n            \"fullName\": \"root suite > unit tests > first unit test\",\n            \"id\": \"-1732721377_0_1_0\",\n            \"location\": \"8:8\",\n            \"mode\": \"skip\",\n            \"state\": \"skipped\",\n          },\n          \"skipped nested\": {\n            \"test in skipped suite\": {\n              \"errors\": [],\n              \"fullName\": \"root suite > unit tests > skipped nested > test in skipped suite\",\n              \"id\": \"-1732721377_0_1_2_0\",\n              \"location\": \"12:10\",\n              \"mode\": \"skip\",\n              \"state\": \"skipped\",\n            },\n          },\n          \"skipped unit test\": {\n            \"errors\": [],\n            \"fullName\": \"root suite > unit tests > skipped unit test\",\n            \"id\": \"-1732721377_0_1_1\",\n            \"location\": \"9:8\",\n            \"mode\": \"skip\",\n            \"state\": \"skipped\",\n          },\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests when test functions are globals', async () => {\n  const testModule = await collectTests(`\n    describe('global test functions', () => {\n      test('test as global', () => {})\n      it('it as global', () => {})\n      testSomething('testSomething as global', () => {})\n      myTest('myTest as global', () => {})\n\n      describe('nested', () => {\n        test.skip('skipped global test', () => {})\n        testUnit.only('testUnit.only as global', () => {})\n      })\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"global test functions\": {\n        \"it as global\": {\n          \"errors\": [],\n          \"fullName\": \"global test functions > it as global\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"4:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"myTest as global\": {\n          \"errors\": [],\n          \"fullName\": \"global test functions > myTest as global\",\n          \"id\": \"-1732721377_0_3\",\n          \"location\": \"6:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"nested\": {\n          \"skipped global test\": {\n            \"errors\": [],\n            \"fullName\": \"global test functions > nested > skipped global test\",\n            \"id\": \"-1732721377_0_4_0\",\n            \"location\": \"9:8\",\n            \"mode\": \"skip\",\n            \"state\": \"skipped\",\n          },\n          \"testUnit.only as global\": {\n            \"errors\": [],\n            \"fullName\": \"global test functions > nested > testUnit.only as global\",\n            \"id\": \"-1732721377_0_4_1\",\n            \"location\": \"10:8\",\n            \"mode\": \"run\",\n            \"state\": \"pending\",\n          },\n        },\n        \"test as global\": {\n          \"errors\": [],\n          \"fullName\": \"global test functions > test as global\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"3:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"testSomething as global\": {\n          \"errors\": [],\n          \"fullName\": \"global test functions > testSomething as global\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"5:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('remove .name from the function identifiers', async () => {\n  const testModule = await collectTests(`\n    import { test } from 'vitest'\n\n    test(Service.name, () => {\n      // ...\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"Service\": {\n        \"errors\": [],\n        \"fullName\": \"Service\",\n        \"id\": \"-1732721377_0\",\n        \"location\": \"4:4\",\n        \"mode\": \"run\",\n        \"state\": \"pending\",\n      },\n    }\n  `)\n})\n\ntest('collects tests with tags as a string', async () => {\n  const testModule = await collectTests(`\n    import { test } from 'vitest'\n\n    describe('tagged tests', () => {\n      test('test with single tag', { tags: 'slow' }, () => {})\n      test('test without tags', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"tagged tests\": {\n        \"test with single tag\": {\n          \"errors\": [],\n          \"fullName\": \"tagged tests > test with single tag\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n          \"tags\": [\n            \"slow\",\n          ],\n        },\n        \"test without tags\": {\n          \"errors\": [],\n          \"fullName\": \"tagged tests > test without tags\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with tags as an array', async () => {\n  const testModule = await collectTests(`\n    import { test } from 'vitest'\n\n    describe('tagged tests', () => {\n      test('test with multiple tags', { tags: ['slow', 'integration'] }, () => {})\n      test('test with empty tags', { tags: [] }, () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"tagged tests\": {\n        \"test with empty tags\": {\n          \"errors\": [],\n          \"fullName\": \"tagged tests > test with empty tags\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"test with multiple tags\": {\n          \"errors\": [],\n          \"fullName\": \"tagged tests > test with multiple tags\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n          \"tags\": [\n            \"slow\",\n            \"integration\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('collects suites with tags', async () => {\n  const testModule = await collectTests(`\n    import { test, describe } from 'vitest'\n\n    describe('tagged suite', { tags: ['unit'] }, () => {\n      test('test in tagged suite', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"tagged suite\": {\n        \"test in tagged suite\": {\n          \"errors\": [],\n          \"fullName\": \"tagged suite > test in tagged suite\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n          \"tags\": [\n            \"unit\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('inherits tags from parent suites', async () => {\n  const testModule = await collectTests(`\n    import { test, describe } from 'vitest'\n\n    describe('outer suite', { tags: ['slow'] }, () => {\n      test('test inherits parent tag', () => {})\n\n      describe('inner suite', { tags: ['integration'] }, () => {\n        test('test inherits both tags', () => {})\n        test('test with own tag', { tags: ['unit'] }, () => {})\n      })\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"outer suite\": {\n        \"inner suite\": {\n          \"test inherits both tags\": {\n            \"errors\": [],\n            \"fullName\": \"outer suite > inner suite > test inherits both tags\",\n            \"id\": \"-1732721377_0_1_0\",\n            \"location\": \"8:8\",\n            \"mode\": \"run\",\n            \"state\": \"pending\",\n            \"tags\": [\n              \"slow\",\n              \"integration\",\n            ],\n          },\n          \"test with own tag\": {\n            \"errors\": [],\n            \"fullName\": \"outer suite > inner suite > test with own tag\",\n            \"id\": \"-1732721377_0_1_1\",\n            \"location\": \"9:8\",\n            \"mode\": \"run\",\n            \"state\": \"pending\",\n            \"tags\": [\n              \"slow\",\n              \"integration\",\n              \"unit\",\n            ],\n          },\n        },\n        \"test inherits parent tag\": {\n          \"errors\": [],\n          \"fullName\": \"outer suite > test inherits parent tag\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n          \"tags\": [\n            \"slow\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tags with other options', async () => {\n  const testModule = await collectTests(`\n    import { test } from 'vitest'\n\n    describe('tests with options', () => {\n      test('test with tags and timeout', { tags: ['slow'], timeout: 5000 }, () => {})\n      test.skip('skipped test with tags', { tags: ['unit'] }, () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"tests with options\": {\n        \"skipped test with tags\": {\n          \"errors\": [],\n          \"fullName\": \"tests with options > skipped test with tags\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n          \"tags\": [\n            \"unit\",\n          ],\n        },\n        \"test with tags and timeout\": {\n          \"errors\": [],\n          \"fullName\": \"tests with options > test with tags and timeout\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n          \"tags\": [\n            \"slow\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('sequential cancels inherited concurrent', async () => {\n  const testModule = await collectTests(`\n    import { test, describe } from 'vitest'\n\n    describe.concurrent('concurrent suite', () => {\n      test('inherits concurrent', () => {})\n\n      describe.sequential('sequential nested', () => {\n        test('not concurrent', () => {})\n      })\n\n      describe('regular nested', () => {\n        test('still concurrent', () => {})\n      })\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"concurrent suite\": {\n        \"inherits concurrent\": {\n          \"concurrent\": true,\n          \"errors\": [],\n          \"fullName\": \"concurrent suite > inherits concurrent\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"regular nested\": {\n          \"still concurrent\": {\n            \"concurrent\": true,\n            \"errors\": [],\n            \"fullName\": \"concurrent suite > regular nested > still concurrent\",\n            \"id\": \"-1732721377_0_2_0\",\n            \"location\": \"12:8\",\n            \"mode\": \"run\",\n            \"state\": \"pending\",\n          },\n        },\n        \"sequential nested\": {\n          \"not concurrent\": {\n            \"errors\": [],\n            \"fullName\": \"concurrent suite > sequential nested > not concurrent\",\n            \"id\": \"-1732721377_0_1_0\",\n            \"location\": \"8:8\",\n            \"mode\": \"run\",\n            \"state\": \"pending\",\n          },\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with sequential modifier', async () => {\n  const testModule = await collectTests(`\n    import { test, describe } from 'vitest'\n\n    describe.sequential('sequential suite', () => {\n      test('test in sequential suite', () => {})\n    })\n\n    test.sequential('sequential test', () => {})\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"sequential suite\": {\n        \"test in sequential suite\": {\n          \"errors\": [],\n          \"fullName\": \"sequential suite > test in sequential suite\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n      \"sequential test\": {\n        \"errors\": [],\n        \"fullName\": \"sequential test\",\n        \"id\": \"-1732721377_1\",\n        \"location\": \"8:4\",\n        \"mode\": \"run\",\n        \"state\": \"pending\",\n      },\n    }\n  `)\n})\n\ntest('collects tests with concurrent modifier in different order', async () => {\n  const testModule = await collectTests(`\n    import { test, describe } from 'vitest'\n\n    describe.skip.concurrent('concurrent suite', () => {\n      test('test in concurrent suite', () => {})\n    })\n\n    test('test outside concurrent suite', () => {})\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"concurrent suite\": {\n        \"test in concurrent suite\": {\n          \"concurrent\": true,\n          \"errors\": [],\n          \"fullName\": \"concurrent suite > test in concurrent suite\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n      \"test outside concurrent suite\": {\n        \"errors\": [],\n        \"fullName\": \"test outside concurrent suite\",\n        \"id\": \"-1732721377_1\",\n        \"location\": \"8:4\",\n        \"mode\": \"run\",\n        \"state\": \"pending\",\n      },\n    }\n  `)\n})\n\ntest('collects tests with options object modifiers', async () => {\n  const testModule = await collectTests(`\n    import { test, describe } from 'vitest'\n\n    describe('options tests', () => {\n      test('skipped via options', { skip: true }, () => {})\n      test('only via options', { only: true }, () => {})\n      test('todo via options', { todo: true }, () => {})\n      test('concurrent via options', { concurrent: true }, () => {})\n      test('skip and concurrent via options', { skip: true, concurrent: true }, () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"options tests\": {\n        \"concurrent via options\": {\n          \"concurrent\": true,\n          \"errors\": [],\n          \"fullName\": \"options tests > concurrent via options\",\n          \"id\": \"-1732721377_0_3\",\n          \"location\": \"8:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"only via options\": {\n          \"errors\": [],\n          \"fullName\": \"options tests > only via options\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n        \"skip and concurrent via options\": {\n          \"concurrent\": true,\n          \"errors\": [],\n          \"fullName\": \"options tests > skip and concurrent via options\",\n          \"id\": \"-1732721377_0_4\",\n          \"location\": \"9:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"skipped via options\": {\n          \"errors\": [],\n          \"fullName\": \"options tests > skipped via options\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"todo via options\": {\n          \"errors\": [],\n          \"fullName\": \"options tests > todo via options\",\n          \"id\": \"-1732721377_0_2\",\n          \"location\": \"7:6\",\n          \"mode\": \"todo\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with concurrent modifier', async () => {\n  const testModule = await collectTests(`\n    import { test, describe } from 'vitest'\n\n    describe.concurrent('concurrent suite', () => {\n      test('test in concurrent suite', () => {})\n      test.skip('skipped in concurrent suite', () => {})\n    })\n\n    test.concurrent('concurrent test', () => {})\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"concurrent suite\": {\n        \"skipped in concurrent suite\": {\n          \"concurrent\": true,\n          \"errors\": [],\n          \"fullName\": \"concurrent suite > skipped in concurrent suite\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:6\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"test in concurrent suite\": {\n          \"concurrent\": true,\n          \"errors\": [],\n          \"fullName\": \"concurrent suite > test in concurrent suite\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n      \"concurrent test\": {\n        \"concurrent\": true,\n        \"errors\": [],\n        \"fullName\": \"concurrent test\",\n        \"id\": \"-1732721377_1\",\n        \"location\": \"9:4\",\n        \"mode\": \"run\",\n        \"state\": \"pending\",\n      },\n    }\n  `)\n})\n\ntest('collects tests with describe.concurrent.each', async () => {\n  const testModule = await collectTests(`\n    import { test, describe } from 'vitest'\n\n    describe.concurrent.each([1, 2, 3])('concurrent each %i', (num) => {\n      test('test inside concurrent each', () => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"concurrent each %i\": {\n        \"test inside concurrent each\": {\n          \"concurrent\": true,\n          \"errors\": [],\n          \"fullName\": \"concurrent each %i > test inside concurrent each\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:6\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with test.concurrent.each', async () => {\n  const testModule = await collectTests(`\n    import { test } from 'vitest'\n\n    describe('suite', () => {\n      test.concurrent.each([1, 2, 3])('concurrent each test %i', (num) => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"suite\": {\n        \"concurrent each test %i\": {\n          \"concurrent\": true,\n          \"dynamic\": true,\n          \"each\": true,\n          \"errors\": [],\n          \"fullName\": \"suite > concurrent each test %i\",\n          \"id\": \"-1732721377_0_0-dynamic\",\n          \"location\": \"5:36\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('reports error when using undefined tag', async () => {\n  const testModule = await collectTestModule(`\n    import { test } from 'vitest'\n\n    describe('tests with undefined tag', () => {\n      test('test with undefined tag', { tags: ['undefined-tag'] }, () => {})\n    })\n`)\n  expect(testModule.errors()[0].message).toMatchInlineSnapshot(`\n    \"The tag \"undefined-tag\" is not defined in the configuration. Available tags are:\n    - slow\n    - integration\n    - unit\"\n  `)\n})\n\ntest('@module-tag docs inject test tags', async () => {\n  const { ctx } = await runVitest({\n    config: false,\n    root: './fixtures/file-tags',\n    standalone: true,\n    watch: true,\n    tags: [\n      { name: 'file' },\n      { name: 'file-2' },\n      { name: 'file/slash' },\n      { name: 'test' },\n    ],\n  })\n  const testModule = await ctx!.experimental_parseSpecification(\n    ctx!.getRootProject().createSpecification(resolve(ctx!.config.root, './valid-file-tags.test.ts')),\n  )\n  expect(testTree(testModule)).toMatchInlineSnapshot(`\n    {\n      \"suite 1\": {\n        \"test 1\": {\n          \"errors\": [],\n          \"fullName\": \"suite 1 > test 1\",\n          \"id\": \"492646822_0_0\",\n          \"location\": \"10:2\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n          \"tags\": [\n            \"file\",\n            \"file-2\",\n            \"file/slash\",\n            \"test\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('invalid @module-tag throws and error', async () => {\n  const { ctx } = await runVitest({\n    config: false,\n    root: './fixtures/file-tags',\n    include: ['./error-file-tags.test.ts'],\n    tags: [\n      { name: 'file' },\n      { name: 'file-2' },\n      { name: 'file/slash' },\n      { name: 'test' },\n    ],\n  })\n  const testModule = await ctx!.experimental_parseSpecification(\n    ctx!.getRootProject().createSpecification(resolve(ctx!.config.root, './error-file-tags.test.ts')),\n  )\n  expect(testModule.errors()[0].message).toMatchInlineSnapshot(`\n    \"The tag \"invalid\" is not defined in the configuration. Available tags are:\n    - file\n    - file-2\n    - file/slash\n    - test\"\n  `)\n})\n\ntest('collects tests with runIf modifier', async () => {\n  const testModule = await collectTests(`\n    import { test } from 'vitest'\n\n    describe('runIf tests', () => {\n      test.runIf(true)('runs conditionally', () => {})\n      test.runIf(false)('also conditional', () => {})\n    })\n`, { fnFn: true })\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"runIf tests\": {\n        \"also conditional\": {\n          \"errors\": [],\n          \"fullName\": \"runIf tests > also conditional\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:22\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"runs conditionally\": {\n          \"errors\": [],\n          \"fullName\": \"runIf tests > runs conditionally\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:21\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with skipIf modifier', async () => {\n  const testModule = await collectTests(`\n    import { test } from 'vitest'\n\n    describe('skipIf tests', () => {\n      test.skipIf(true)('skips conditionally', () => {})\n      test.skipIf(false)('also conditional skip', () => {})\n    })\n`, { fnFn: true })\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"skipIf tests\": {\n        \"also conditional skip\": {\n          \"errors\": [],\n          \"fullName\": \"skipIf tests > also conditional skip\",\n          \"id\": \"-1732721377_0_1\",\n          \"location\": \"6:23\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"skips conditionally\": {\n          \"errors\": [],\n          \"fullName\": \"skipIf tests > skips conditionally\",\n          \"id\": \"-1732721377_0_0\",\n          \"location\": \"5:22\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n      },\n    }\n  `)\n})\n\ntest('collects tests with for modifier', async () => {\n  const testModule = await collectTests(`\n    import { test } from 'vitest'\n\n    describe('for tests', () => {\n      test.for([1, 2, 3])('test with for %i', (num) => {})\n      test.skip.for([1, 2])('skipped for %i', (num) => {})\n    })\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"for tests\": {\n        \"skipped for %i\": {\n          \"dynamic\": true,\n          \"each\": true,\n          \"errors\": [],\n          \"fullName\": \"for tests > skipped for %i\",\n          \"id\": \"-1732721377_0_1-dynamic\",\n          \"location\": \"6:26\",\n          \"mode\": \"skip\",\n          \"state\": \"skipped\",\n        },\n        \"test with for %i\": {\n          \"dynamic\": true,\n          \"each\": true,\n          \"errors\": [],\n          \"fullName\": \"for tests > test with for %i\",\n          \"id\": \"-1732721377_0_0-dynamic\",\n          \"location\": \"5:24\",\n          \"mode\": \"run\",\n          \"state\": \"pending\",\n        },\n      },\n    }\n  `)\n})\n\ntest('properties on test don\\'t generate tests', async () => {\n  const testModule = await collectTests(`\n    import { test, describe } from 'vitest'\n\n    test('actual test', () => {}).withProp(true).withProp(false)\n    test.for([])('actual 2 test', () => {}).withProp('a2').withProp('a3')\n    testContext('actual 3 test', () => {}).withProp('q4').withProp('q5')\n    test('actual 4 test', () => {}).skip('hello world')\n    testContext().withProp('q6').withProp('q7')\n`)\n  expect(testModule).toMatchInlineSnapshot(`\n    {\n      \"actual 2 test\": {\n        \"dynamic\": true,\n        \"each\": true,\n        \"errors\": [],\n        \"fullName\": \"actual 2 test\",\n        \"id\": \"-1732721377_1-dynamic\",\n        \"location\": \"5:15\",\n        \"mode\": \"run\",\n        \"state\": \"pending\",\n      },\n      \"actual 3 test\": {\n        \"errors\": [],\n        \"fullName\": \"actual 3 test\",\n        \"id\": \"-1732721377_2\",\n        \"location\": \"6:4\",\n        \"mode\": \"run\",\n        \"state\": \"pending\",\n      },\n      \"actual 4 test\": {\n        \"errors\": [],\n        \"fullName\": \"actual 4 test\",\n        \"id\": \"-1732721377_3\",\n        \"location\": \"7:4\",\n        \"mode\": \"run\",\n        \"state\": \"pending\",\n      },\n      \"actual test\": {\n        \"errors\": [],\n        \"fullName\": \"actual test\",\n        \"id\": \"-1732721377_0\",\n        \"location\": \"4:4\",\n        \"mode\": \"run\",\n        \"state\": \"pending\",\n      },\n    }\n  `)\n})\n\nasync function collectTestModule(code: string, options?: CliOptions) {\n  const vitest = await createVitest(\n    'test',\n    {\n      config: false,\n      includeTaskLocation: true,\n      allowOnly: true,\n      ...options,\n      tags: [\n        { name: 'slow' },\n        { name: 'integration' },\n        { name: 'unit' },\n      ],\n    },\n    {\n      plugins: [\n        {\n          name: 'ast-collect-test',\n          load(id) {\n            if (id === 'simple.test.ts') {\n              return code\n            }\n          },\n        },\n      ],\n    },\n  )\n  onTestFinished(() => vitest.close())\n  return vitest.experimental_parseSpecification(\n    vitest.getRootProject().createSpecification('simple.test.ts'),\n  )\n}\n\nasync function collectTests(code: string, options?: CliOptions & { fnFn?: boolean }) {\n  return testTree(await collectTestModule(code, options), {}, options?.fnFn)\n}\n\nfunction testTree(module: TestModule | TestSuite, tree: any = {}, fnFn?: boolean) {\n  for (const item of module.children) {\n    if (item.type === 'test') {\n      tree[item.name] = testItem(item, fnFn)\n    }\n    else {\n      tree[item.name] ??= {}\n      testTree(item, tree[item.name], fnFn)\n    }\n  }\n  return tree\n}\n\nfunction testItem(\n  testCase: TestCase,\n  // A function returning a function (like test.runIf()('name'))\n  // rolldown's column is moved by 1 in that case\n  fnFn?: boolean,\n) {\n  let location: string | undefined\n  const state = testCase.result().state\n  if (testCase.location) {\n    // rolldown's column is moved by 1 when using test.each/test.for\n    const column = rolldownVersion && (testCase.options.each || fnFn)\n      ? testCase.location.column - 1\n      : testCase.location.column\n    location = `${testCase.location.line}:${column}`\n  }\n  return {\n    id: testCase.id,\n    location,\n    mode: testCase.options.mode,\n    fullName: testCase.fullName,\n    state,\n    errors: testCase.result().errors || [],\n    ...(testCase.task.dynamic ? { dynamic: true } : {}),\n    ...(testCase.options.each ? { each: true } : {}),\n    ...(testCase.options.concurrent ? { concurrent: true } : {}),\n    ...(testCase.task.tags?.length ? { tags: testCase.task.tags } : {}),\n  }\n}\n"
  },
  {
    "path": "test/cli/test/test-meta.test.ts",
    "content": "import type { TestCase, TestSuite } from 'vitest/node'\nimport { runInlineTests } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest('meta can be defined on test options', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { meta: { custom: 'value', count: 42 } }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testCase = testModule.children.at(0) as TestCase\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"count\": 42,\n      \"custom\": \"value\",\n    }\n  `)\n})\n\ntest('meta can be defined on suite options', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { meta: { suiteKey: 'suiteValue' } }, () => {\n        test('test 1', () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  expect(testSuite.meta()).toMatchInlineSnapshot(`\n    {\n      \"suiteKey\": \"suiteValue\",\n    }\n  `)\n})\n\ntest('test inherits meta from parent suite', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { meta: { inherited: true, level: 'suite' } }, () => {\n        test('test 1', () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  const testCase = testSuite.children.at(0) as TestCase\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"inherited\": true,\n      \"level\": \"suite\",\n    }\n  `)\n})\n\ntest('test meta overrides inherited suite meta', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { meta: { shared: 'fromSuite', suiteOnly: true } }, () => {\n        test('test 1', { meta: { shared: 'fromTest', testOnly: 123 } }, () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  const testCase = testSuite.children.at(0) as TestCase\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"shared\": \"fromTest\",\n      \"suiteOnly\": true,\n      \"testOnly\": 123,\n    }\n  `)\n})\n\ntest('nested suites inherit meta from parent suites', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('outer', { meta: { outer: true } }, () => {\n        describe('inner', { meta: { inner: true } }, () => {\n          test('test 1', () => {})\n        })\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const outerSuite = testModule.children.at(0) as TestSuite\n  const innerSuite = outerSuite.children.at(0) as TestSuite\n  const testCase = innerSuite.children.at(0) as TestCase\n\n  expect(outerSuite.meta()).toMatchInlineSnapshot(`\n    {\n      \"outer\": true,\n    }\n  `)\n  expect(innerSuite.meta()).toMatchInlineSnapshot(`\n    {\n      \"inner\": true,\n      \"outer\": true,\n    }\n  `)\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"inner\": true,\n      \"outer\": true,\n    }\n  `)\n})\n\ntest('deeply nested meta inheritance with overrides', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('level1', { meta: { level: 1, a: 'first' } }, () => {\n        describe('level2', { meta: { level: 2, b: 'second' } }, () => {\n          describe('level3', { meta: { level: 3, a: 'override' } }, () => {\n            test('test 1', { meta: { level: 4 } }, () => {})\n          })\n        })\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const level1 = testModule.children.at(0) as TestSuite\n  const level2 = level1.children.at(0) as TestSuite\n  const level3 = level2.children.at(0) as TestSuite\n  const testCase = level3.children.at(0) as TestCase\n\n  expect(level1.meta()).toMatchInlineSnapshot(`\n    {\n      \"a\": \"first\",\n      \"level\": 1,\n    }\n  `)\n  expect(level2.meta()).toMatchInlineSnapshot(`\n    {\n      \"a\": \"first\",\n      \"b\": \"second\",\n      \"level\": 2,\n    }\n  `)\n  expect(level3.meta()).toMatchInlineSnapshot(`\n    {\n      \"a\": \"override\",\n      \"b\": \"second\",\n      \"level\": 3,\n    }\n  `)\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"a\": \"override\",\n      \"b\": \"second\",\n      \"level\": 4,\n    }\n  `)\n})\n\ntest('meta is accessible from task.meta inside tests', async () => {\n  const { stderr, stdout } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { meta: { suiteKey: 'inherited' } }, () => {\n        test('test 1', { meta: { testKey: 'own' } }, ({ task }) => {\n          console.log('META:', JSON.stringify(task.meta))\n        })\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const metaLine = stdout.split('\\n').find(line => line.startsWith('META:'))\n  expect(metaLine).toBeDefined()\n  expect(JSON.parse(metaLine!.slice('META:'.length))).toMatchInlineSnapshot(`\n    {\n      \"suiteKey\": \"inherited\",\n      \"testKey\": \"own\",\n    }\n  `)\n})\n\ntest('sibling tests have independent meta', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { meta: { shared: 'parent' } }, () => {\n        test('test 1', { meta: { id: 1 } }, () => {})\n        test('test 2', { meta: { id: 2 } }, () => {})\n        test('test 3', () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  const [test1, test2, test3] = testSuite.children.array() as TestCase[]\n\n  expect(test1.meta()).toMatchInlineSnapshot(`\n    {\n      \"id\": 1,\n      \"shared\": \"parent\",\n    }\n  `)\n  expect(test2.meta()).toMatchInlineSnapshot(`\n    {\n      \"id\": 2,\n      \"shared\": \"parent\",\n    }\n  `)\n  expect(test3.meta()).toMatchInlineSnapshot(`\n    {\n      \"shared\": \"parent\",\n    }\n  `)\n})\n\ntest('sibling suites have independent meta', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite1', { meta: { suite: 1 } }, () => {\n        test('test 1', () => {})\n      })\n      describe('suite2', { meta: { suite: 2 } }, () => {\n        test('test 2', () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const [suite1, suite2] = testModule.children.array() as TestSuite[]\n  const test1 = suite1.children.at(0) as TestCase\n  const test2 = suite2.children.at(0) as TestCase\n\n  expect(suite1.meta()).toMatchInlineSnapshot(`\n    {\n      \"suite\": 1,\n    }\n  `)\n  expect(suite2.meta()).toMatchInlineSnapshot(`\n    {\n      \"suite\": 2,\n    }\n  `)\n  expect(test1.meta()).toMatchInlineSnapshot(`\n    {\n      \"suite\": 1,\n    }\n  `)\n  expect(test2.meta()).toMatchInlineSnapshot(`\n    {\n      \"suite\": 2,\n    }\n  `)\n})\n\ntest('test without parent suite has empty meta', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testCase = testModule.children.at(0) as TestCase\n  expect(testCase.meta()).toMatchInlineSnapshot(`{}`)\n})\n\ntest('test.each works with meta', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { meta: { feature: 'each' } }, () => {\n        test.each([1, 2, 3])('test %i', { meta: { eachTest: true } }, () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  const tests = testSuite.children.array() as TestCase[]\n\n  expect(tests).toHaveLength(3)\n  for (const test of tests) {\n    expect(test.meta()).toMatchInlineSnapshot(`\n      {\n        \"eachTest\": true,\n        \"feature\": \"each\",\n      }\n    `)\n  }\n})\n\ntest('describe.each works with meta', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe.each([1, 2])('suite %i', { meta: { dynamic: true } }, () => {\n        test('test', () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const [suite1, suite2] = testModule.children.array() as TestSuite[]\n\n  expect(suite1.meta()).toMatchInlineSnapshot(`\n    {\n      \"dynamic\": true,\n    }\n  `)\n  expect(suite2.meta()).toMatchInlineSnapshot(`\n    {\n      \"dynamic\": true,\n    }\n  `)\n  expect((suite1.children.at(0) as TestCase).meta()).toMatchInlineSnapshot(`\n    {\n      \"dynamic\": true,\n    }\n  `)\n})\n\ntest('concurrent tests have independent meta', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { meta: { shared: true } }, () => {\n        test.concurrent('test 1', { meta: { id: 1 } }, () => {})\n        test.concurrent('test 2', { meta: { id: 2 } }, () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  const [test1, test2] = testSuite.children.array() as TestCase[]\n\n  expect(test1.meta()).toMatchInlineSnapshot(`\n    {\n      \"id\": 1,\n      \"shared\": true,\n    }\n  `)\n  expect(test2.meta()).toMatchInlineSnapshot(`\n    {\n      \"id\": 2,\n      \"shared\": true,\n    }\n  `)\n})\n\ntest('meta with complex values', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', {\n        meta: {\n          nested: { a: { b: { c: 1 } } },\n          array: [1, 2, 3],\n          nullValue: null,\n          boolTrue: true,\n          boolFalse: false,\n          num: 42.5,\n        }\n      }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testCase = testModule.children.at(0) as TestCase\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"array\": [\n        1,\n        2,\n        3,\n      ],\n      \"boolFalse\": false,\n      \"boolTrue\": true,\n      \"nested\": {\n        \"a\": {\n          \"b\": {\n            \"c\": 1,\n          },\n        },\n      },\n      \"nullValue\": null,\n      \"num\": 42.5,\n    }\n  `)\n})\n\ntest('meta works with test modifiers (skip, only, todo)', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test.skip('skipped test', { meta: { status: 'skipped' } }, () => {})\n      test.todo('todo test', { meta: { status: 'todo' } })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const [skipped, todo] = testModule.children.array() as TestCase[]\n\n  expect(skipped.meta()).toMatchInlineSnapshot(`\n    {\n      \"status\": \"skipped\",\n    }\n  `)\n  expect(todo.meta()).toMatchInlineSnapshot(`\n    {\n      \"status\": \"todo\",\n    }\n  `)\n})\n\ntest('meta works with test.fails', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test.fails('failing test', { meta: { expectFailure: true } }, () => {\n        throw new Error('Expected error')\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testCase = testModule.children.at(0) as TestCase\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"expectFailure\": true,\n    }\n  `)\n  expect(testCase.result().state).toBe('passed')\n})\n\ntest('suite without meta does not inherit to tests', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite without meta', () => {\n        test('test with meta', { meta: { ownMeta: true } }, () => {})\n        test('test without meta', () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  const [withMeta, withoutMeta] = testSuite.children.array() as TestCase[]\n\n  expect(testSuite.meta()).toMatchInlineSnapshot(`{}`)\n  expect(withMeta.meta()).toMatchInlineSnapshot(`\n    {\n      \"ownMeta\": true,\n    }\n  `)\n  expect(withoutMeta.meta()).toMatchInlineSnapshot(`{}`)\n})\n\ntest('meta does not mutate parent when child overrides', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('parent', { meta: { key: 'parent', parentOnly: true } }, () => {\n        describe('child', { meta: { key: 'child', childOnly: true } }, () => {\n          test('test', () => {})\n        })\n        test('sibling test', () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const parent = testModule.children.at(0) as TestSuite\n  const child = parent.children.at(0) as TestSuite\n  const siblingTest = parent.children.at(1) as TestCase\n\n  expect(parent.meta()).toMatchInlineSnapshot(`\n    {\n      \"key\": \"parent\",\n      \"parentOnly\": true,\n    }\n  `)\n  expect(child.meta()).toMatchInlineSnapshot(`\n    {\n      \"childOnly\": true,\n      \"key\": \"child\",\n      \"parentOnly\": true,\n    }\n  `)\n  expect(siblingTest.meta()).toMatchInlineSnapshot(`\n    {\n      \"key\": \"parent\",\n      \"parentOnly\": true,\n    }\n  `)\n})\n\ntest('meta with test.for', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { meta: { fromSuite: true } }, () => {\n        test.for([\n          { input: 1, expected: 2 },\n          { input: 2, expected: 4 },\n        ])('test $input', { meta: { forTest: true } }, ({ input, expected }) => {\n          expect(input * 2).toBe(expected)\n        })\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  const tests = testSuite.children.array() as TestCase[]\n\n  expect(tests).toHaveLength(2)\n  for (const test of tests) {\n    expect(test.meta()).toMatchInlineSnapshot(`\n      {\n        \"forTest\": true,\n        \"fromSuite\": true,\n      }\n    `)\n  }\n})\n\ntest('empty meta object is allowed', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { meta: {} }, () => {\n        test('test', { meta: {} }, () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  const testCase = testSuite.children.at(0) as TestCase\n\n  expect(testSuite.meta()).toMatchInlineSnapshot(`{}`)\n  expect(testCase.meta()).toMatchInlineSnapshot(`{}`)\n})\n\ntest('meta inheritance across multiple files', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'file1.test.js': `\n      describe('suite in file1', { meta: { file: 1 } }, () => {\n        test('test 1', () => {})\n      })\n    `,\n    'file2.test.js': `\n      describe('suite in file2', { meta: { file: 2 } }, () => {\n        test('test 2', () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n  const testModules = ctx!.state.getTestModules()\n  const file1Module = testModules.find(m => m.moduleId.includes('file1'))!\n  const file2Module = testModules.find(m => m.moduleId.includes('file2'))!\n\n  const suite1 = file1Module.children.at(0) as TestSuite\n  const suite2 = file2Module.children.at(0) as TestSuite\n  const test1 = suite1.children.at(0) as TestCase\n  const test2 = suite2.children.at(0) as TestCase\n\n  expect(test1.meta()).toMatchInlineSnapshot(`\n    {\n      \"file\": 1,\n    }\n  `)\n  expect(test2.meta()).toMatchInlineSnapshot(`\n    {\n      \"file\": 2,\n    }\n  `)\n})\n"
  },
  {
    "path": "test/cli/test/test-specifications.test.ts",
    "content": "import type { TestSpecificationOptions } from 'vitest/node'\nimport { expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\ntest.each(\n  [\n    { testNamePattern: /two/ },\n    { testLines: [8] },\n    { testIds: ['-109630875_1'] },\n  ] satisfies TestSpecificationOptions[],\n)('runs with options %o', async (options) => {\n  const { fs, ctx, errorTree } = await runInlineTests({\n    'basic.test.js': /* js */ `\n      import { test, expect } from 'vitest'\n\n      test('one', () => {\n        expect(1).toBe(1)\n      })\n\n      test('two', () => {\n        expect(2).toBe(2)\n      })\n    `,\n  }, { standalone: true, watch: true, includeTaskLocation: true })\n  const vitest = ctx!\n\n  // nothing run yet\n  expect(vitest.state.idMap).toHaveLength(0)\n\n  const specification = vitest.getRootProject().createSpecification(\n    fs.resolveFile('./basic.test.js'),\n    options,\n  )\n\n  await vitest.runTestSpecifications([specification])\n\n  expect(errorTree()).toEqual({\n    'basic.test.js': {\n      one: 'skipped',\n      two: 'passed',\n    },\n  })\n})\n"
  },
  {
    "path": "test/cli/test/test-tags.test.ts",
    "content": "import type { TestCase, TestSuite } from 'vitest/node'\nimport { runInlineTests, runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest('vitest records tags', async () => {\n  const { stderr, buildTree } = await runVitest({\n    root: './fixtures/test-tags',\n    config: false,\n    tags: [\n      { name: 'alone' },\n      { name: 'suite' },\n      { name: 'test' },\n      { name: 'suite_2' },\n      { name: 'test_2' },\n    ],\n  })\n\n  expect(stderr).toBe('')\n  expect(getTestTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"suite 1\": {\n          \"suite 2\": {\n            \"test 3\": [\n              \"suite\",\n              \"alone\",\n              \"suite_2\",\n            ],\n            \"test 4\": [\n              \"suite\",\n              \"alone\",\n              \"suite_2\",\n              \"test_2\",\n            ],\n          },\n          \"test 1\": [\n            \"suite\",\n            \"alone\",\n          ],\n          \"test 2\": [\n            \"suite\",\n            \"alone\",\n            \"test\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('filters tests based on --tags-filter=!ignore', async () => {\n  const { stderr, testTree } = await runVitest({\n    root: './fixtures/test-tags',\n    config: false,\n    tags: [\n      { name: 'alone' },\n      { name: 'suite' },\n      { name: 'test' },\n      { name: 'suite_2' },\n      { name: 'test_2' },\n    ],\n    tagsFilter: ['!suite_2'],\n  })\n\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"suite 1\": {\n          \"suite 2\": {\n            \"test 3\": \"skipped\",\n            \"test 4\": \"skipped\",\n          },\n          \"test 1\": \"passed\",\n          \"test 2\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('filters tests based on --tags-filter=!ignore and --tags-filter=include', async () => {\n  const { stderr, testTree } = await runVitest({\n    root: './fixtures/test-tags',\n    config: false,\n    tags: [\n      { name: 'alone' },\n      { name: 'suite' },\n      { name: 'test' },\n      { name: 'suite_2' },\n      { name: 'test_2' },\n    ],\n    tagsFilter: ['!suite_2', 'test'],\n  })\n\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"suite 1\": {\n          \"suite 2\": {\n            \"test 3\": \"skipped\",\n            \"test 4\": \"skipped\",\n          },\n          \"test 1\": \"skipped\",\n          \"test 2\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('filters tests based on --tags-filter=include', async () => {\n  const { stderr, testTree } = await runVitest({\n    root: './fixtures/test-tags',\n    config: false,\n    tags: [\n      { name: 'alone' },\n      { name: 'suite' },\n      { name: 'test' },\n      { name: 'suite_2' },\n      { name: 'test_2' },\n    ],\n    tagsFilter: ['test*'],\n  })\n\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"suite 1\": {\n          \"suite 2\": {\n            \"test 3\": \"skipped\",\n            \"test 4\": \"passed\",\n          },\n          \"test 1\": \"skipped\",\n          \"test 2\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n\ntest('throws an error if no tags are defined in the config, but in the test', async () => {\n  const { stderr } = await runInlineTests(\n    {\n      'basic.test.js': `\n        test('test 1', { tags: ['unknown'] }, () => {})\n      `,\n    },\n    { globals: true },\n  )\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.js [ basic.test.js ]\n    Error: The Vitest config does't define any \"tags\", cannot apply \"unknown\" tag for this test. See: https://vitest.dev/guide/test-tags\n     ❯ basic.test.js:2:9\n          1|\n          2|         test('test 1', { tags: ['unknown'] }, () => {})\n           |         ^\n          3|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('throws an error if tag is not defined in the config, but in the test', async () => {\n  const { stderr } = await runInlineTests(\n    {\n      'basic.test.js': `\n        test('test 1', { tags: ['unknown'] }, () => {})\n      `,\n    },\n    {\n      globals: true,\n      tags: [{ name: 'known' }],\n    },\n  )\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.js [ basic.test.js ]\n    Error: The tag \"unknown\" is not defined in the configuration. Available tags are:\n    - known\n     ❯ basic.test.js:2:9\n          1|\n          2|         test('test 1', { tags: ['unknown'] }, () => {})\n           |         ^\n          3|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('throws an error if tag is not defined in the config, but in --tags-filter filter', async () => {\n  const { stderr } = await runInlineTests(\n    {\n      'basic.test.js': '',\n    },\n    {\n      tagsFilter: ['unknown'],\n    },\n    { fails: true },\n  )\n  expect(stderr).toContain('The Vitest config does\\'t define any \"tags\", cannot apply \"unknown\" tag pattern for this test. See: https://vitest.dev/guide/test-tags')\n})\n\ntest('defining a tag available only in one project', async () => {\n  const { stderr, buildTree, ctx } = await runInlineTests({\n    'basic-1.test.js': `\n      test('test 1', { tags: ['project-1-tag'] }, () => {})\n    `,\n    'basic-2.test.js': `\n      test('test 2', { tags: ['global-tag', 'project-2-tag'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'global-tag' },\n        ],\n        projects: [\n          {\n            extends: true,\n            test: {\n              name: 'project-1',\n              include: ['basic-1.test.js'],\n              tags: [\n                { name: 'project-1-tag' },\n                { name: 'override', timeout: 100 },\n              ],\n            },\n          },\n          {\n            extends: true,\n            test: {\n              name: 'project-2',\n              include: ['basic-2.test.js'],\n              tags: [\n                { name: 'project-2-tag' },\n                { name: 'override', timeout: 200 },\n              ],\n            },\n          },\n        ],\n      },\n    },\n  }, {\n    tagsFilter: ['project-2-tag'],\n  })\n  expect(stderr).toBe('')\n  expect(Object.fromEntries(ctx!.projects.map(p => [p.name, p.config.tags]))).toMatchInlineSnapshot(`\n    {\n      \"project-1\": [\n        {\n          \"name\": \"project-1-tag\",\n        },\n        {\n          \"name\": \"override\",\n          \"timeout\": 100,\n        },\n        {\n          \"name\": \"global-tag\",\n        },\n        {\n          \"name\": \"project-2-tag\",\n        },\n      ],\n      \"project-2\": [\n        {\n          \"name\": \"project-2-tag\",\n        },\n        {\n          \"name\": \"override\",\n          \"timeout\": 200,\n        },\n        {\n          \"name\": \"global-tag\",\n        },\n        {\n          \"name\": \"project-1-tag\",\n        },\n      ],\n    }\n  `)\n  expect(buildOptionsTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"basic-1.test.js\": {\n        \"test 1\": {\n          \"mode\": \"run\",\n          \"tags\": [\n            \"project-1-tag\",\n          ],\n          \"timeout\": 5000,\n        },\n      },\n      \"basic-2.test.js\": {\n        \"test 2\": {\n          \"mode\": \"run\",\n          \"tags\": [\n            \"global-tag\",\n            \"project-2-tag\",\n          ],\n          \"timeout\": 5000,\n        },\n      },\n    }\n  `)\n})\n\ntest('can specify custom options for tags', async () => {\n  const { stderr, buildTree } = await runVitest({\n    root: './fixtures/test-tags',\n    config: false,\n    tags: [\n      { name: 'alone' },\n      { name: 'suite', timeout: 1000 },\n      { name: 'test', retry: 2, skip: true },\n      { name: 'suite_2', repeats: 3 },\n      { name: 'test_2', timeout: 500, retry: 1 },\n    ],\n  })\n  expect(stderr).toBe('')\n  expect(buildOptionsTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"suite 1\": {\n          \"suite 2\": {\n            \"test 3\": {\n              \"mode\": \"run\",\n              \"repeats\": 3,\n              \"tags\": [\n                \"suite\",\n                \"alone\",\n                \"suite_2\",\n              ],\n              \"timeout\": 1000,\n            },\n            \"test 4\": {\n              \"mode\": \"run\",\n              \"repeats\": 3,\n              \"retry\": 1,\n              \"tags\": [\n                \"suite\",\n                \"alone\",\n                \"suite_2\",\n                \"test_2\",\n              ],\n              \"timeout\": 500,\n            },\n          },\n          \"test 1\": {\n            \"mode\": \"run\",\n            \"tags\": [\n              \"suite\",\n              \"alone\",\n            ],\n            \"timeout\": 1000,\n          },\n          \"test 2\": {\n            \"mode\": \"skip\",\n            \"retry\": 2,\n            \"tags\": [\n              \"suite\",\n              \"alone\",\n              \"test\",\n            ],\n            \"timeout\": 1000,\n          },\n        },\n      },\n    }\n  `)\n})\n\ntest('can specify custom options with priorities for tags', async () => {\n  const { stderr, ctx } = await runVitest({\n    root: './fixtures/test-tags',\n    config: false,\n    tags: [\n      { name: 'alone' },\n      {\n        name: 'test',\n        timeout: 500,\n        skip: false,\n        concurrent: true,\n        fails: false,\n        priority: 1,\n      },\n      {\n        name: 'suite',\n        timeout: 1000,\n        skip: true,\n        concurrent: false,\n        fails: true,\n        priority: 2,\n      },\n      { name: 'suite_2' },\n      { name: 'test_2' },\n    ],\n  })\n\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testSuite = testModule.children.at(0) as TestSuite\n  const testCase = testSuite.children.at(1) as TestCase\n\n  expect(testCase.name).toBe('test 2')\n  expect(testCase.options.tags).toEqual(['suite', 'alone', 'test'])\n  // from 'test' tag (priority 1 is higher)\n  expect(testCase.options.timeout).toBe(500)\n  // concurrent is not set anywhere manually, so\n  // test always gets it from the highest priority tag\n  expect(testCase.options.concurrent).toBe(true)\n  expect(testCase.options.fails).toBe(false)\n  expect(testCase.result().state).toBe('passed')\n})\n\ntest('custom options override tag options', async () => {\n  const { stderr, buildTree } = await runInlineTests({\n    'basic.test.js': `\n      test.fails('test 1', { tags: ['test'], timeout: 2000, skip: false, repeats: 0 }, () => {\n        throw new Error('fail')\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          {\n            name: 'test',\n            timeout: 500,\n            skip: true,\n            concurrent: true,\n            fails: false,\n            retry: 2,\n            repeats: 2,\n          },\n        ],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  expect(buildOptionsTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"test 1\": {\n          \"concurrent\": true,\n          \"fails\": true,\n          \"mode\": \"run\",\n          \"repeats\": 0,\n          \"retry\": 2,\n          \"tags\": [\n            \"test\",\n          ],\n          \"timeout\": 2000,\n        },\n      },\n    }\n  `)\n})\n\ntest('strictFlag: false does not throw an error if test has an undefined tag', async () => {\n  const { stderr } = await runInlineTests(\n    {\n      'basic.test.js': `\n        test('test 1', { tags: ['unknown'] }, () => {})\n      `,\n      'vitest.config.js': {\n        test: {\n          globals: true,\n          strictTags: false,\n          tags: [{ name: 'known' }],\n        },\n      },\n    },\n  )\n\n  expect(stderr).toBe('')\n})\n\ntest('@module-tag docs inject test tags', async () => {\n  const { stderr, buildTree } = await runVitest({\n    config: false,\n    root: './fixtures/file-tags',\n    include: ['./valid-file-tags.test.ts'],\n    tags: [\n      { name: 'file' },\n      { name: 'file-2' },\n      { name: 'file/slash' },\n      { name: 'test' },\n    ],\n  })\n  expect(stderr).toBe('')\n  expect(getTestTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"valid-file-tags.test.ts\": {\n        \"suite 1\": {\n          \"test 1\": [\n            \"file\",\n            \"file-2\",\n            \"file/slash\",\n            \"test\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('invalid @module-tag throws and error', async () => {\n  const { stderr } = await runVitest({\n    config: false,\n    root: './fixtures/file-tags',\n    include: ['./error-file-tags.test.ts'],\n    tags: [\n      { name: 'file' },\n      { name: 'file-2' },\n      { name: 'file/slash' },\n      { name: 'test' },\n    ],\n  })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  error-file-tags.test.ts [ error-file-tags.test.ts ]\n    Error: The tag \"invalid\" is not defined in the configuration. Available tags are:\n    - file\n    - file-2\n    - file/slash\n    - test\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('@module-tag on one line docs inject test tags', async () => {\n  const { stderr, buildTree } = await runVitest({\n    config: false,\n    root: './fixtures/file-tags',\n    include: ['./valid-file-one-line-comment.test.ts'],\n    tags: [\n      { name: 'file' },\n      { name: 'file-2' },\n      { name: 'file/slash' },\n      { name: 'test' },\n    ],\n  })\n  expect(stderr).toBe('')\n  expect(getTestTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"valid-file-one-line-comment.test.ts\": {\n        \"suite 1\": {\n          \"test 1\": [\n            \"file\",\n            \"file-2\",\n            \"file/slash\",\n            \"test\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('invalid @module-tag on one line throws and error', async () => {\n  const { stderr } = await runVitest({\n    config: false,\n    root: './fixtures/file-tags',\n    include: ['./error-file-one-line-comment.test.ts'],\n    tags: [\n      { name: 'file' },\n      { name: 'file-2' },\n      { name: 'file/slash' },\n      { name: 'test' },\n    ],\n  })\n  expect(stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  error-file-one-line-comment.test.ts [ error-file-one-line-comment.test.ts ]\n    Error: The tag \"invalid\" is not defined in the configuration. Available tags are:\n    - file\n    - file-2\n    - file/slash\n    - test\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n})\n\ntest('@module-tag with strictTags: false allows undefined tags', async () => {\n  const { stderr, buildTree } = await runVitest({\n    config: false,\n    root: './fixtures/file-tags',\n    include: ['./error-file-tags.test.ts'],\n    strictTags: false,\n    tags: [\n      { name: 'file' },\n      { name: 'file-2' },\n      { name: 'file/slash' },\n      { name: 'test' },\n    ],\n  })\n  expect(stderr).toBe('')\n  expect(getTestTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"error-file-tags.test.ts\": {\n        \"suite 1\": {\n          \"test 1\": [\n            \"invalid\",\n            \"unknown\",\n            \"test\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('sequential tag option makes tests run sequentially', async () => {\n  const { stderr, buildTree } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['sequential-tag'] }, () => {})\n      test('test 2', { tags: ['sequential-tag'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'sequential-tag', sequential: true },\n        ],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  // sequential is not visible in options, it affect \"concurrent\" only, which is not set if false\n  expect(buildOptionsTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"test 1\": {\n          \"mode\": \"run\",\n          \"tags\": [\n            \"sequential-tag\",\n          ],\n          \"timeout\": 5000,\n        },\n        \"test 2\": {\n          \"mode\": \"run\",\n          \"tags\": [\n            \"sequential-tag\",\n          ],\n          \"timeout\": 5000,\n        },\n      },\n    }\n  `)\n})\n\ntest('only tag option marks tests as only', async () => {\n  const { stderr, buildTree } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['only-tag'] }, () => {})\n      test('test 2', () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'only-tag', only: true },\n        ],\n        allowOnly: true,\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  expect(buildOptionsTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"test 1\": {\n          \"mode\": \"run\",\n          \"tags\": [\n            \"only-tag\",\n          ],\n          \"timeout\": 5000,\n        },\n        \"test 2\": {\n          \"mode\": \"skip\",\n          \"tags\": [],\n          \"timeout\": 5000,\n        },\n      },\n    }\n  `)\n})\n\ntest('tags without explicit priority use definition order (last wins)', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['tag-a', 'tag-b'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'tag-a', timeout: 1000 },\n          { name: 'tag-b', timeout: 2000 },\n        ],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testCase = testModule.children.at(0) as TestCase\n  expect(testCase.options.timeout).toBe(2000)\n})\n\ntest('equal priority tags use definition order (last wins)', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['tag-a', 'tag-b'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'tag-a', timeout: 1000, priority: 1 },\n          { name: 'tag-b', timeout: 2000, priority: 1 },\n        ],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testCase = testModule.children.at(0) as TestCase\n  expect(testCase.options.timeout).toBe(2000)\n})\n\ntest('negative priority values is not allowed', async () => {\n  const { stderr } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['low-priority', 'high-priority'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'low-priority', timeout: 1000, priority: -10 },\n        ],\n      },\n    },\n  }, {}, { fails: true })\n  expect(stderr).toContain('Tag \"low-priority\": priority must be a non-negative number.')\n})\n\ntest.for([\n  '!invalid',\n  'inv*alid',\n  'inv&alid',\n  'inv|alid',\n  'inv(alid',\n  'inv)alid',\n])('tag name \"%s\" containing special character \"%s\" is not allowed', async (tagName) => {\n  const { stderr } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: tagName },\n        ],\n      },\n    },\n  }, {}, { fails: true })\n  expect(stderr).toContain(`Tag name \"${tagName}\" is invalid. Tag names cannot contain \"!\", \"*\", \"&\", \"|\", \"(\", or \")\".`)\n})\n\ntest.for([\n  'and',\n  'or',\n  'not',\n  'AND',\n  'OR',\n  'NOT',\n])('tag name \"%s\" is a reserved keyword and is not allowed', async (tagName) => {\n  const { stderr } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: tagName },\n        ],\n      },\n    },\n  }, {}, { fails: true })\n  expect(stderr).toContain(`Tag name \"${tagName}\" is invalid. Tag names cannot be a logical operator like \"and\", \"or\", \"not\".`)\n})\n\ntest('strictTags: false does not allow undefined tags in filter, it only affects test definition', async () => {\n  const { stderr } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['known'] }, () => {})\n      test('test 2', () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        strictTags: false,\n        tags: [{ name: 'known' }],\n      },\n    },\n  }, {\n    tagsFilter: ['unknown'],\n  })\n  expect(stderr).toContain(`The tag pattern \"unknown\" is not defined in the configuration. Available tags are:\n- known`)\n})\n\ntest('--list-tags prints error if no tags are defined', async () => {\n  const { stdout, stderr, exitCode } = await runVitest({\n    config: false,\n    listTags: true,\n  })\n  expect(stdout).toBe('')\n  expect(exitCode).toBe(1)\n  expect(stderr).toMatchInlineSnapshot(`\n    \" ERROR  No test tags found in any project. Exiting with code 1.\n    \"\n  `)\n})\n\ntest('--list-tags prints tags defined in config', async () => {\n  const { stdout, stderr } = await runVitest({\n    config: false,\n    listTags: true,\n    tags: [\n      { name: 'unit' },\n      { name: 'e2e', description: 'End-to-end tests' },\n      { name: 'slow' },\n    ],\n  })\n  expect(stderr).toBe('')\n  expect(`\\n${stdout}`).toMatchInlineSnapshot(`\n    \"\n      unit\n      e2e: End-to-end tests\n      slow\n    \"\n  `)\n})\n\ntest('--list-tags prints tags from multiple projects', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'vitest.config.js': {\n      test: {\n        tags: [\n          { name: 'global-tag', description: 'Available in all projects' },\n        ],\n        projects: [\n          {\n            extends: true,\n            test: {\n              name: 'project-1',\n              tags: [\n                { name: 'project-1-tag' },\n              ],\n            },\n          },\n          {\n            extends: true,\n            test: {\n              name: 'project-2',\n              tags: [\n                { name: 'project-2-tag', description: 'Only in project 2' },\n                { name: 'project-2-again' },\n              ],\n            },\n          },\n        ],\n      },\n    },\n  }, {\n    listTags: true,\n  })\n  expect(stderr).toBe('')\n  expect(`\\n${stdout}`).toMatchInlineSnapshot(`\n    \"\n      global-tag: Available in all projects\n    |project-1|\n      project-1-tag\n    |project-2|\n      project-2-tag: Only in project 2\n      project-2-again\n    \"\n  `)\n})\n\ntest('--list-tags prints tags with named root project', async () => {\n  const { stdout, stderr } = await runInlineTests({\n    'vitest.config.js': {\n      test: {\n        name: 'root',\n        tags: [\n          { name: 'root-tag' },\n          { name: 'another-tag', description: 'From root' },\n        ],\n        projects: [\n          {\n            extends: true,\n            test: {\n              name: 'child',\n              tags: [\n                { name: 'child-tag' },\n                { name: 'child-2-tag' },\n              ],\n            },\n          },\n        ],\n      },\n    },\n  }, {\n    listTags: true,\n  })\n  expect(stderr).toBe('')\n  expect(`\\n${stdout}`).toMatchInlineSnapshot(`\n    \"\n    |root|\n      root-tag\n      another-tag: From root\n    |child|\n      child-tag\n      child-2-tag\n    \"\n  `)\n})\n\ntest('--list-tags aligns tags with different project name lengths', async () => {\n  const { stdout, stderr } = await runVitest({\n    config: false,\n    listTags: true,\n    projects: [\n      {\n        test: {\n          name: 'a',\n          tags: [\n            { name: 'tag-1' },\n            { name: 'tag-2' },\n          ],\n        },\n      },\n      {\n        test: {\n          name: 'long-project-name',\n          tags: [\n            { name: 'tag-3' },\n            { name: 'tag-4' },\n          ],\n        },\n      },\n      {\n        test: {\n          name: 'medium',\n          tags: [\n            { name: 'tag-5' },\n          ],\n        },\n      },\n    ],\n  })\n  expect(stderr).toBe('')\n  expect(`\\n${stdout}`).toMatchInlineSnapshot(`\n    \"\n    |a|\n      tag-1\n      tag-2\n    |long-project-name|\n      tag-3\n      tag-4\n    |medium|\n      tag-5\n    \"\n  `)\n})\n\ntest('--list-tags=json prints error if no tags are defined', async () => {\n  const { stdout, stderr } = await runVitest({\n    config: false,\n    listTags: 'json',\n  })\n  expect(stdout).toBe('')\n  expect(stderr).toContain('No test tags found in any project. Exiting with code 1.')\n})\n\ntest('--list-tags=json prints tags as JSON', async () => {\n  const { stdout, stderr } = await runVitest({\n    config: false,\n    listTags: 'json',\n    tags: [\n      { name: 'unit' },\n      { name: 'e2e', description: 'End-to-end tests' },\n    ],\n  })\n  expect(stderr).toBe('')\n  const json = JSON.parse(stdout)\n  expect(json).toEqual({\n    tags: [\n      { name: 'unit' },\n      { name: 'e2e', description: 'End-to-end tests' },\n    ],\n    projects: [],\n  })\n})\n\ntest('--list-tags=json prints tags from multiple projects', async () => {\n  const { stdout, stderr } = await runVitest({\n    config: false,\n    listTags: 'json',\n    tags: [\n      { name: 'global-tag' },\n    ],\n    projects: [\n      {\n        test: {\n          name: 'project-1',\n          tags: [\n            { name: 'project-1-tag' },\n          ],\n        },\n      },\n      {\n        test: {\n          name: 'project-2',\n          tags: [\n            { name: 'project-2-tag', description: 'Only in project 2' },\n          ],\n        },\n      },\n    ],\n  })\n  expect(stderr).toBe('')\n  const json = JSON.parse(stdout)\n  expect(json).toEqual({\n    tags: [\n      { name: 'global-tag' },\n    ],\n    projects: [\n      {\n        name: 'project-1',\n        tags: [\n          { name: 'project-1-tag' },\n        ],\n      },\n      {\n        name: 'project-2',\n        tags: [\n          { name: 'project-2-tag', description: 'Only in project 2' },\n        ],\n      },\n    ],\n  })\n})\n\ntest('duplicate tags from suite and test are deduplicated', async () => {\n  const { stderr, buildTree } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { tags: ['shared'] }, () => {\n        test('test 1', { tags: ['shared', 'unique'] }, () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'shared' },\n          { name: 'unique' },\n        ],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  expect(getTestTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"suite\": {\n          \"test 1\": [\n            \"shared\",\n            \"unique\",\n          ],\n        },\n      },\n    }\n  `)\n})\n\ntest('empty tags array on test is handled correctly', async () => {\n  const { stderr, buildTree } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: [] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [{ name: 'unused' }],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  expect(getTestTree(buildTree)).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"test 1\": [],\n      },\n    }\n  `)\n})\n\ntest('filters tests with complex AND/OR expressions', async () => {\n  const { stderr, testTree } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['unit', 'fast'] }, () => {})\n      test('test 2', { tags: ['unit', 'slow'] }, () => {})\n      test('test 3', { tags: ['e2e', 'fast'] }, () => {})\n      test('test 4', { tags: ['e2e', 'slow'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'unit' },\n          { name: 'e2e' },\n          { name: 'fast' },\n          { name: 'slow' },\n        ],\n      },\n    },\n  }, {\n    tagsFilter: ['(unit || e2e) && fast'],\n  })\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"test 1\": \"passed\",\n        \"test 2\": \"skipped\",\n        \"test 3\": \"passed\",\n        \"test 4\": \"skipped\",\n      },\n    }\n  `)\n})\n\ntest('filters tests with NOT and parentheses', async () => {\n  const { stderr, testTree } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['browser', 'chrome'] }, () => {})\n      test('test 2', { tags: ['browser', 'firefox'] }, () => {})\n      test('test 3', { tags: ['browser', 'edge'] }, () => {})\n      test('test 4', { tags: ['node'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'browser' },\n          { name: 'chrome' },\n          { name: 'firefox' },\n          { name: 'edge' },\n          { name: 'node' },\n        ],\n      },\n    },\n  }, {\n    tagsFilter: ['browser && !(edge)'],\n  })\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"test 1\": \"passed\",\n        \"test 2\": \"passed\",\n        \"test 3\": \"skipped\",\n        \"test 4\": \"skipped\",\n      },\n    }\n  `)\n})\n\ntest('throws an error when several tags with the same name are defined', async () => {\n  const { stderr } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'duplicate', timeout: 1000 },\n          { name: 'unique' },\n          { name: 'duplicate', timeout: 2000 },\n        ],\n      },\n    },\n  }, {}, { fails: true })\n  expect(stderr).toContain('Tag name \"duplicate\" is already defined in \"test.tags\". Tag names must be unique.')\n})\n\ntest('multiple filter expressions act as AND', async () => {\n  const { stderr, testTree } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['unit', 'fast'] }, () => {})\n      test('test 2', { tags: ['unit', 'slow'] }, () => {})\n      test('test 3', { tags: ['e2e', 'fast'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'unit' },\n          { name: 'e2e' },\n          { name: 'fast' },\n          { name: 'slow' },\n        ],\n      },\n    },\n  }, {\n    tagsFilter: ['unit || e2e', '!slow'],\n  })\n  expect(stderr).toBe('')\n  expect(testTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.js\": {\n        \"test 1\": \"passed\",\n        \"test 2\": \"skipped\",\n        \"test 3\": \"passed\",\n      },\n    }\n  `)\n})\n\ntest('tags can define meta in config', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test('test 1', { tags: ['unit'] }, () => {})\n      test('test 2', { tags: ['e2e'] }, () => {})\n      test('test 3', { tags: ['unit', 'slow'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'unit', meta: { type: 'unit', priority: 1 } },\n          { name: 'e2e', meta: { type: 'e2e', browser: true } },\n          { name: 'slow', meta: { priority: 2, slow: true } },\n        ],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const [test1, test2, test3] = testModule.children.array() as TestCase[]\n  expect(test1.meta()).toMatchInlineSnapshot(`\n    {\n      \"priority\": 1,\n      \"type\": \"unit\",\n    }\n  `)\n  expect(test2.meta()).toMatchInlineSnapshot(`\n    {\n      \"browser\": true,\n      \"type\": \"e2e\",\n    }\n  `)\n  expect(test3.meta()).toMatchInlineSnapshot(`\n    {\n      \"priority\": 2,\n      \"slow\": true,\n      \"type\": \"unit\",\n    }\n  `)\n})\n\ntest('tag meta is inherited by suite and test meta', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      describe('suite', { tags: ['suite-tag'], meta: { suiteOwn: true } }, () => {\n        test('test', { tags: ['test-tag'], meta: { testOwn: true } }, () => {})\n      })\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'suite-tag', meta: { fromSuiteTag: 'value' } },\n          { name: 'test-tag', meta: { fromTestTag: 'value' } },\n        ],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const suite = testModule.children.at(0) as TestSuite\n  const testCase = suite.children.at(0) as TestCase\n  // suite has a tag with metadata, but tags are only applied to tests,\n  // so suites don't get tag metadata\n  expect(suite.meta()).toMatchInlineSnapshot(`\n    {\n      \"suiteOwn\": true,\n    }\n  `)\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"fromSuiteTag\": \"value\",\n      \"fromTestTag\": \"value\",\n      \"suiteOwn\": true,\n      \"testOwn\": true,\n    }\n  `)\n})\n\ntest('test meta overrides tag meta', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test('test', { tags: ['tagged'], meta: { key: 'fromTest', testOnly: true } }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'tagged', meta: { key: 'fromTag', tagOnly: true } },\n        ],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testCase = testModule.children.at(0) as TestCase\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"key\": \"fromTest\",\n      \"tagOnly\": true,\n      \"testOnly\": true,\n    }\n  `)\n})\n\ntest('multiple tags with meta are merged with priority order', async () => {\n  const { stderr, ctx } = await runInlineTests({\n    'basic.test.js': `\n      test('test', { tags: ['low', 'high'] }, () => {})\n    `,\n    'vitest.config.js': {\n      test: {\n        globals: true,\n        tags: [\n          { name: 'low', priority: 2, meta: { shared: 'low', lowOnly: true } },\n          { name: 'high', priority: 1, meta: { shared: 'high', highOnly: true } },\n        ],\n      },\n    },\n  })\n  expect(stderr).toBe('')\n  const testModule = ctx!.state.getTestModules()[0]\n  const testCase = testModule.children.at(0) as TestCase\n  expect(testCase.meta()).toMatchInlineSnapshot(`\n    {\n      \"highOnly\": true,\n      \"lowOnly\": true,\n      \"shared\": \"high\",\n    }\n  `)\n})\n\nfunction getTestTree(builder: (fn: (test: TestCase) => any) => any) {\n  return builder(test => test.options.tags)\n}\n\nfunction buildOptionsTree(builder: (fn: (test: TestCase) => any) => any) {\n  return builder(test => removeUndefined(test.options))\n}\n\nfunction removeUndefined<T extends Record<string, any>>(obj: T): Partial<T> {\n  const result: Partial<T> = {}\n  for (const key in obj) {\n    if (obj[key] !== undefined) {\n      result[key] = obj[key]\n    }\n  }\n  return result\n}\n\ndeclare module 'vitest' {\n  interface TaskMeta {\n    type?: string\n    priority?: number\n    browser?: boolean\n    slow?: boolean\n    fromSuiteTag?: string\n    fromTestTag?: string\n    suiteOwn?: boolean\n    testOwn?: boolean\n    tagOnly?: boolean\n    shared?: string\n    lowOnly?: boolean\n    highOnly?: boolean\n  }\n}\n"
  },
  {
    "path": "test/cli/test/tty.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitestCli } from '../../test-utils'\n\ntest('run mode does not get stuck when TTY', async () => {\n  const { vitest } = await runVitestCli('--root', 'fixtures/tty')\n\n  await vitest.waitForStdout('✓ example.test.ts')\n  await vitest.waitForStdout('✓ math.test.ts')\n  await vitest.waitForStdout('2 passed')\n\n  // Regression #3642\n  expect(vitest.stderr).not.toContain('close timed out')\n  expect(vitest.stderr).toBe('')\n})\n"
  },
  {
    "path": "test/cli/test/unhandled-ignore.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('run mode does not get stuck when TTY', async () => {\n  const { vitest } = await runVitest({\n    root: './fixtures/fails',\n    include: ['unhandled.test.ts'],\n    onUnhandledError(err) {\n      if (err.message === 'some error') {\n        return false\n      }\n    },\n    // jsdom also prints a warning, but we don't care for our use case\n    onConsoleLog() {\n      return false\n    },\n  })\n\n  // Regression #3642\n  expect(vitest.stderr).toBe('')\n})\n"
  },
  {
    "path": "test/cli/test/unhandled-rejections.test.ts",
    "content": "import type { RunVitestConfig } from '#test-utils'\nimport { runInlineTests } from '#test-utils'\nimport { describe, expect, test } from 'vitest'\n\ndescribe('dangerouslyIgnoreUnhandledErrors', () => {\n  test('{ dangerouslyIgnoreUnhandledErrors: true }', async () => {\n    const { stderr, exitCode } = await runUnhandledTest({\n      dangerouslyIgnoreUnhandledErrors: true,\n    })\n\n    expect(exitCode).toBe(0)\n    expect(stderr).toMatch('Vitest caught 1 unhandled error during the test run')\n    expect(stderr).toMatch('Error: intentional unhandled error')\n  })\n\n  test('{ dangerouslyIgnoreUnhandledErrors: true } without reporter', async () => {\n    const { exitCode } = await runUnhandledTest({\n      dangerouslyIgnoreUnhandledErrors: true,\n      reporters: [{ onInit: () => {} }],\n    })\n\n    expect(exitCode).toBe(0)\n  })\n\n  test('{ dangerouslyIgnoreUnhandledErrors: false }', async () => {\n    const { stderr, exitCode } = await runUnhandledTest({\n      dangerouslyIgnoreUnhandledErrors: false,\n    })\n\n    expect(exitCode).toBe(1)\n    expect(stderr).toMatch('Vitest caught 1 unhandled error during the test run')\n    expect(stderr).toMatch('Error: intentional unhandled error')\n  })\n\n  function runUnhandledTest(config: RunVitestConfig) {\n    return runInlineTests({\n      'throw-errors.test.js': /* js */`\n        import { test } from \"vitest\"\n\n        test(\"Some test\", () => {\n          //\n        })\n\n        new Promise((_, reject) => reject(new Error(\"intentional unhandled error\")))\n      `,\n    }, config, { fails: true })\n  }\n})\n\ntest('unhandled rejections of main thread are reported even when no reporter is used', async () => {\n  const { stderr, exitCode } = await runInlineTests({\n    'setup-unhandled-rejections.js': /* ts */`\n      export function setup() {\n        void new Promise((_, reject) => reject(new Error('intentional unhandled rejection')))\n      }\n    `,\n    'example.test.js': '', // won't run\n  }, {\n    config: false,\n    globalSetup: ['setup-unhandled-rejections.js'],\n    reporters: [{ onInit: () => {} }],\n  }, { fails: true })\n\n  expect(exitCode).toBe(1)\n  expect(stderr).toContain('Unhandled Rejection')\n  expect(stderr).toContain('Error: intentional unhandled rejection')\n  expect(stderr).toContain('setup-unhandled-rejections.js:3:48')\n})\n"
  },
  {
    "path": "test/cli/test/vm-threads.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { createFile, resolvePath, runInlineTests, runVitest } from '../../test-utils'\n\ntest('importing files in restricted fs works correctly', async () => {\n  createFile(\n    resolvePath(import.meta.url, '../fixtures/vm-threads/src/external/package-null/package-null.json'),\n    'null',\n  )\n\n  const { stderr, exitCode } = await runVitest({\n    root: './fixtures/vm-threads',\n  })\n\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n})\n\n// The module-sync condition was added in Node 22.12/20.19 when require(esm)\n// was unflagged. The fix uses the _resolveFilename conditions option which\n// is only available on Node 22.12+. Node 20 is unfixable and reaches EOL\n// April 2026.\nconst nodeMajor = Number(process.versions.node.split('.')[0])\ntest.skipIf(nodeMajor < 22)('can require package with module-sync exports condition', async () => {\n  const { stderr, exitCode } = await runInlineTests({\n    // .mjs module-sync entry\n    'node_modules/module-sync-mjs/package.json': JSON.stringify({\n      name: 'module-sync-mjs',\n      exports: {\n        '.': {\n          'module-sync': './index.mjs',\n          'require': './index.cjs',\n        },\n      },\n    }),\n    'node_modules/module-sync-mjs/index.mjs': 'export const value = \"esm\";',\n    'node_modules/module-sync-mjs/index.cjs': 'module.exports = { value: \"cjs\" };',\n    // .js module-sync entry with \"type\": \"module\"\n    'node_modules/module-sync-js/package.json': JSON.stringify({\n      name: 'module-sync-js',\n      type: 'module',\n      exports: {\n        '.': {\n          'module-sync': './index.js',\n          'require': './index.cjs',\n        },\n      },\n    }),\n    'node_modules/module-sync-js/index.js': 'export const value = \"esm\";',\n    'node_modules/module-sync-js/index.cjs': 'module.exports = { value: \"cjs\" };',\n    'basic.test.js': `\n      import { createRequire } from 'node:module'\n      import { expect, test } from 'vitest'\n\n      const require = createRequire(import.meta.url)\n\n      test('require loads cjs entry for module-sync package (.mjs)', () => {\n        const mod = require('module-sync-mjs')\n        expect(mod.value).toBe('cjs')\n      })\n\n      test('require loads cjs entry for module-sync package (.js with type: module)', () => {\n        const mod = require('module-sync-js')\n        expect(mod.value).toBe('cjs')\n      })\n    `,\n  }, {\n    pool: 'vmThreads',\n  })\n\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/cli/test/watch/change-project.test.ts",
    "content": "import { runInlineTests } from '#test-utils'\nimport { expect, test } from 'vitest'\n\ntest('reruns tests when config changes', async () => {\n  const { vitest, ctx } = await runInlineTests({\n    'vitest.config.ts': `\n\n    process.stdin.isTTY = true\n    process.stdin.setRawMode = () => process.stdin\n\n    export default {\n      test: {\n        projects: [\n          './project-1',\n          './project-2',\n        ],\n      },\n    }`,\n    'project-1/vitest.config.ts': { test: { name: 'project-1' } },\n    'project-1/basic-1.test.ts': /* ts */`\n      import { test } from 'vitest'\n      test('basic test 1', () => {})\n    `,\n    'project-2/vitest.config.ts': { test: { name: 'project-2' } },\n    'project-2/basic-2.test.ts': /* ts */`\n      import { test } from 'vitest'\n      test('basic test 2', () => {})\n    `,\n  }, { watch: true })\n\n  await vitest.waitForStdout('Waiting for file changes')\n\n  expect(vitest.stdout).toContain('2 passed')\n  expect(vitest.stdout).toContain('basic-1.test.ts')\n  expect(vitest.stdout).toContain('basic-2.test.ts')\n  vitest.resetOutput()\n\n  await ctx!.changeProjectName('project-2')\n\n  await vitest.waitForStdout('Waiting for file changes')\n\n  expect(vitest.stdout).toContain('1 passed')\n  expect(vitest.stdout).toContain('basic-2.test.ts')\n})\n"
  },
  {
    "path": "test/cli/test/watch/config-watching.test.ts",
    "content": "import { runInlineTests } from '#test-utils'\nimport { playwright } from '@vitest/browser-playwright'\nimport { expect, test } from 'vitest'\n\nconst ts = String.raw\n\ntest('rerun stops the previous browser server and restarts multiple times without port mismatch', async () => {\n  const { fs, vitest } = await runInlineTests({\n    'vitest.config.js': {\n      test: {\n        projects: ['./project-1'],\n      },\n    },\n    'project-1/vitest.config.js': {\n      test: {\n        browser: {\n          enabled: true,\n          instances: [{ browser: 'chromium' }],\n          provider: playwright(),\n          headless: true,\n        },\n      },\n    },\n    'project-1/basic.test.ts': ts`\n      import { test } from 'vitest'\n      test('basic test 1', () => {})\n    `,\n  }, { watch: true })\n\n  await vitest.waitForStdout('Waiting for file changes')\n  vitest.resetOutput()\n\n  // editing the project config the first time restarts the browser server\n  fs.editFile('./project-1/vitest.config.js', c => `\\n${c}`)\n\n  await vitest.waitForStdout('Restarting due to config changes...')\n  await vitest.waitForStdout('Waiting for file changes')\n\n  expect(vitest.stdout).not.toContain('is in use, trying another one...')\n  expect(vitest.stderr).not.toContain('is in use, trying another one...')\n  vitest.resetOutput()\n\n  // editing the project the second time also restarts the server\n  fs.editFile('./project-1/vitest.config.js', c => `\\n${c}`)\n\n  await vitest.waitForStdout('Restarting due to config changes...')\n  await vitest.waitForStdout('Waiting for file changes')\n\n  expect(vitest.stdout).not.toContain('is in use, trying another one...')\n  expect(vitest.stderr).not.toContain('is in use, trying another one...')\n  vitest.resetOutput()\n})\n"
  },
  {
    "path": "test/cli/test/watch/file-watching.test.ts",
    "content": "import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs'\nimport * as testUtils from '#test-utils'\n\nimport { playwright } from '@vitest/browser-playwright'\nimport { afterEach, describe, expect, onTestFinished, test } from 'vitest'\n\nconst sourceFile = 'fixtures/watch/math.ts'\nconst sourceFileContent = readFileSync(sourceFile, 'utf-8')\n\nconst testFile = 'fixtures/watch/math.test.ts'\nconst testFileContent = readFileSync(testFile, 'utf-8')\n\nconst configFile = 'fixtures/watch/vitest.config.ts'\nconst configFileContent = readFileSync(configFile, 'utf-8')\n\nconst forceTriggerFile = 'fixtures/watch/force-watch/trigger.js'\nconst forceTriggerFileContent = readFileSync(forceTriggerFile, 'utf-8')\n\nconst options = { root: 'fixtures/watch', watch: true }\n\nfunction modifyContent(fileContent: string) {\n  return `// Modified by file-watching.test.ts\n${fileContent}\nconsole.log(\"New code running\"); // This is used to check that edited changes are actually run, and cached files are not run instead\n  `\n}\n\nafterEach(() => {\n  writeFileSync(sourceFile, sourceFileContent, 'utf8')\n  writeFileSync(testFile, testFileContent, 'utf8')\n  writeFileSync(configFile, configFileContent, 'utf8')\n  writeFileSync(forceTriggerFile, forceTriggerFileContent, 'utf8')\n})\n\ntest('editing source file triggers re-run', async () => {\n  const { vitest } = await testUtils.runVitest(options)\n\n  writeFileSync(sourceFile, modifyContent(sourceFileContent), 'utf8')\n\n  await vitest.waitForStdout('New code running')\n  await vitest.waitForStdout('RERUN  ../../math.ts')\n  await vitest.waitForStdout('1 passed')\n})\n\ntest('editing file that was imported with a query reruns suite', async () => {\n  const { vitest } = await testUtils.runVitest(options)\n\n  testUtils.editFile(\n    testUtils.resolvePath(import.meta.url, '../../fixtures/watch/42.txt'),\n    file => `${file}\\n`,\n  )\n\n  await vitest.waitForStdout('RERUN  ../../42.txt')\n  await vitest.waitForStdout('1 passed')\n})\n\ntest('editing force rerun trigger reruns all tests', async () => {\n  const { vitest } = await testUtils.runVitest(options)\n\n  writeFileSync(forceTriggerFile, modifyContent(forceTriggerFileContent), 'utf8')\n\n  await vitest.waitForStdout('Waiting for file changes...')\n  await vitest.waitForStdout('RERUN  ../../force-watch/trigger.js')\n  await vitest.waitForStdout('example.test.ts')\n  await vitest.waitForStdout('math.test.ts')\n  await vitest.waitForStdout('2 passed')\n})\n\ntest('editing test file triggers re-run', async () => {\n  const { vitest } = await testUtils.runVitest(options)\n\n  writeFileSync(testFile, modifyContent(testFileContent), 'utf8')\n\n  await vitest.waitForStdout('New code running')\n  await vitest.waitForStdout('RERUN  ../../math.test.ts')\n  await vitest.waitForStdout('1 passed')\n})\n\ntest('editing config file triggers re-run', async () => {\n  const { vitest } = await testUtils.runVitest(options)\n\n  writeFileSync(configFile, modifyContent(configFileContent), 'utf8')\n\n  await vitest.waitForStdout('Restarting due to config changes')\n  await vitest.waitForStdout('2 passed')\n})\n\ntest('editing config file reloads new changes', async () => {\n  const { vitest } = await testUtils.runVitest({ ...options, reporters: 'none' })\n\n  writeFileSync(configFile, configFileContent.replace('reporters: \\'verbose\\'', 'reporters: \\'tap\\''), 'utf8')\n\n  await vitest.waitForStdout('TAP version')\n  await vitest.waitForStdout('ok 2')\n})\n\ntest('adding a new test file triggers re-run', async () => {\n  const { vitest, fs } = await testUtils.runInlineTests({\n    'base.test.js': /* js */`test(\"base test\", () => {})`,\n  }, { watch: true, globals: true })\n\n  await vitest.waitForStdout('press h to show help')\n\n  const testFileContent = `\nimport { expect, test } from \"vitest\";\n\ntest(\"dynamic test case\", () => {\n  console.log(\"Running added dynamic test\")\n  expect(true).toBeTruthy()\n})\n`\n\n  fs.createFile('new-dynamic.test.ts', testFileContent)\n\n  await vitest.waitForStdout('Running added dynamic test')\n  await vitest.waitForStdout('RERUN  ../new-dynamic.test.ts')\n  await vitest.waitForStdout('1 passed')\n})\n\ntest('renaming an existing test file', { retry: 3 }, async () => {\n  const { vitest, ctx, fs } = await testUtils.runInlineTests({\n    'before.test.js': /* js */`\n      import { expect, test } from \"vitest\";\n\n      test(\"test case\", () => {\n        console.log(\"Running existing test\")\n        expect(true).toBeTruthy()\n      })\n    `,\n  }, { watch: true })\n\n  await vitest.waitForStdout('Running existing test')\n  await vitest.waitForStdout('press h to show help')\n\n  const fileAdded = new Promise<void>((resolve) => {\n    ctx!.vite.watcher.on('add', () => {\n      resolve()\n    })\n  })\n\n  fs.renameFile('before.test.js', 'after.test.js')\n\n  await vitest.waitForStdout('Test removed')\n  await vitest.waitForStdout('Waiting for file changes...')\n  await fileAdded\n\n  vitest.write('p')\n  await vitest.waitForStdout('Input filename pattern')\n  vitest.write('before')\n  await vitest.waitForStdout('Pattern matches no results')\n  vitest.write('\\n')\n  await vitest.waitForStdout('No test files found')\n  await vitest.waitForStdout('Waiting for file changes...')\n  vitest.write('p')\n  await vitest.waitForStdout('Input filename pattern')\n  vitest.write('after')\n  await vitest.waitForStdout('Pattern matches 1 result')\n  vitest.write('\\n')\n  await vitest.waitForStdout('Filename pattern: after')\n  await vitest.waitForStdout('1 passed')\n})\n\ntest('editing source file generates new test report to file system', async () => {\n  const report = 'fixtures/watch/test-results/junit.xml'\n  onTestFinished(() => {\n    if (existsSync(report)) {\n      rmSync(report)\n    }\n  })\n\n  // Test report should not be present before test run\n  expect(existsSync(report)).toBe(false)\n\n  const { vitest } = await testUtils.runVitest({\n    ...options,\n    reporters: ['verbose', 'junit'],\n    outputFile: './test-results/junit.xml',\n  })\n\n  // Test report should be generated on initial test run\n  expect(existsSync(report)).toBe(true)\n\n  // Test report should be re-generated on second test run\n  rmSync(report)\n  expect(existsSync(report)).toBe(false)\n\n  vitest.resetOutput()\n  writeFileSync(sourceFile, modifyContent(sourceFileContent), 'utf8')\n\n  await vitest.waitForStdout('JUNIT report written')\n  await vitest.waitForStdout(report)\n  expect(existsSync(report)).toBe(true)\n})\n\ndescribe('browser', () => {\n  test.runIf((process.platform !== 'win32'))('editing source file triggers re-run', { retry: 3 }, async () => {\n    const { vitest } = await testUtils.runVitest({\n      root: 'fixtures/watch',\n      watch: true,\n      browser: {\n        instances: [{ browser: 'chromium' }],\n        provider: playwright(),\n        enabled: true,\n        headless: true,\n      },\n    })\n\n    writeFileSync(sourceFile, modifyContent(sourceFileContent), 'utf8')\n\n    await vitest.waitForStdout('New code running')\n    await vitest.waitForStdout('RERUN  ../../math.ts')\n    await vitest.waitForStdout('1 passed')\n\n    vitest.write('q')\n  })\n})\n"
  },
  {
    "path": "test/cli/test/watch/global-setup-rerun.test.ts",
    "content": "import { editFile, runVitest } from '#test-utils'\nimport { expect, test } from 'vitest'\n\nconst testFile = 'fixtures/watch/math.test.ts'\n\ntest('global setup calls hooks correctly when file changes', async () => {\n  const { vitest, ctx } = await runVitest({\n    root: 'fixtures/watch',\n    watch: true,\n    include: ['math.test.ts'],\n    globalSetup: ['./global-setup.ts'],\n  })\n\n  await vitest.waitForStdout('Waiting for file changes')\n\n  const calls = (globalThis as any).__CALLS as string[]\n  expect(calls).toEqual(['start'])\n\n  editFile(testFile, testFileContent => `${testFileContent}\\n\\n`)\n\n  await vitest.waitForStdout('RERUN')\n  expect(calls).toEqual(['start', 'rerun'])\n\n  await ctx?.close()\n\n  expect(calls).toEqual(['start', 'rerun', 'end'])\n})\n\ntest('global setup calls hooks correctly with a manual rerun', async () => {\n  const { vitest, ctx } = await runVitest({\n    root: 'fixtures/watch',\n    watch: true,\n    include: ['math.test.ts'],\n    globalSetup: ['./global-setup.ts'],\n  })\n\n  await vitest.waitForStdout('Waiting for file changes')\n\n  const calls = (globalThis as any).__CALLS as string[]\n  expect(calls).toEqual(['start'])\n\n  vitest.write('r')\n\n  await vitest.waitForStdout('RERUN')\n  expect(calls).toEqual(['start', 'rerun'])\n\n  await ctx?.close()\n\n  expect(calls).toEqual(['start', 'rerun', 'end'])\n})\n"
  },
  {
    "path": "test/cli/test/watch/related.test.ts",
    "content": "import { editFile, runVitest } from '#test-utils'\nimport { resolve } from 'pathe'\nimport { test } from 'vitest'\n\ntest('when nothing is changed, run nothing but keep watching', async () => {\n  const { vitest } = await runVitest({\n    root: 'fixtures/watch',\n    watch: true,\n    changed: true,\n  })\n\n  await vitest.waitForStdout('No affected test files found')\n  await vitest.waitForStdout('Waiting for file changes...')\n\n  editFile(resolve(import.meta.dirname, '../../fixtures/watch/math.ts'), content => `${content}\\n\\n`)\n\n  await vitest.waitForStdout('RERUN  ../../math.ts')\n  await vitest.waitForStdout('1 passed')\n\n  editFile(resolve(import.meta.dirname, '../../fixtures/watch/math.test.ts'), content => `${content}\\n\\n`)\n\n  await vitest.waitForStdout('RERUN  ../../math.test.ts')\n  await vitest.waitForStdout('1 passed')\n})\n"
  },
  {
    "path": "test/cli/test/watch/reporter-failed.test.ts",
    "content": "import { runInlineTests } from '#test-utils'\nimport { describe, expect, it } from 'vitest'\n\ndescribe.for([\n  true,\n  false,\n])('%s reporter with %s tty', (isTTY) => {\n  it('prints previously failed tests on rerun', async () => {\n    const { vitest, fs } = await runReporterTests(isTTY)\n\n    expect(vitest.stderr).toContain('failed.test.js > fails')\n    expect(vitest.stdout).toContain('❯ failed.test.js')\n    expect(vitest.stdout).toContain('× fails')\n    expect(vitest.stdout).toContain('1 failed')\n    expect(vitest.stdout).toContain('1 passed')\n\n    vitest.resetOutput()\n\n    fs.editFile('./basic.test.js', code => `${code}\\n`)\n\n    await vitest.waitForStdout('RERUN  ../basic.test.js')\n    await vitest.waitForStdout('Waiting for file changes...')\n\n    expect(vitest.stdout).not.toContain('log fail')\n    expect(vitest.stdout).toContain('❯ failed.test.js')\n    expect(vitest.stdout).toContain('× fails')\n    expect(vitest.stdout).toContain('1 failed')\n    expect(vitest.stdout).toContain('1 passed')\n  })\n\n  it('prints tests once if changed test is the same', async () => {\n    const { vitest, fs } = await runReporterTests(isTTY)\n\n    expect(vitest.stderr).toContain('failed.test.js > fails')\n    expect(vitest.stdout).toContain('❯ failed.test.js')\n    expect(vitest.stdout).toContain('× fails')\n    expect(vitest.stdout).toContain('1 failed')\n\n    vitest.resetOutput()\n\n    fs.editFile('./failed.test.js', code => `${code}\\n`)\n\n    await vitest.waitForStdout('RERUN  ../failed.test.js')\n    await vitest.waitForStdout('Watching for file changes...')\n\n    expect(vitest.stdout).toContain('❯ failed.test.js')\n    expect(vitest.stdout).toContain('× fails')\n    expect(vitest.stdout).toContain('1 failed')\n    expect(vitest.stdout).not.toContain('1 passed')\n  })\n})\n\nasync function runReporterTests(isTTY: boolean) {\n  return await runInlineTests({\n    'basic.test.js': /* js */`\n      import { expect, it } from 'vitest';\n\n      it('works correctly', () => {\n        console.log('log basic')\n        expect(1).toBe(1)\n      })\n    `,\n    'failed.test.js': /* js */`\n      import { it } from 'vitest';\n\n      it('fails', () => {\n        console.log('log fail')\n        throw new Error('failed')\n      })\n    `,\n  }, {\n    config: false,\n    watch: true,\n    fileParallelism: false,\n    reporters: [['default', { isTTY }]],\n  })\n}\n"
  },
  {
    "path": "test/cli/test/watch/stdin.test.ts",
    "content": "import { rmSync, writeFileSync } from 'node:fs'\nimport { runVitest } from '#test-utils'\nimport { describe, expect, onTestFinished, test } from 'vitest'\n\nconst _options = { root: 'fixtures/watch', watch: true }\n\ndescribe.each([true, false])('standalone mode is %s', (standalone) => {\n  const options = { ..._options, standalone }\n\n  test('quit watch mode', async () => {\n    const { vitest, waitForClose } = await runVitest(options)\n\n    vitest.write('q')\n\n    await waitForClose()\n  })\n\n  test('filter by filename', async () => {\n    const { vitest } = await runVitest(options)\n\n    vitest.write('p')\n\n    await vitest.waitForStdout('Input filename pattern')\n\n    vitest.write('math')\n\n    await vitest.waitForStdout('Pattern matches 1 result')\n    await vitest.waitForStdout('› math.test.ts')\n\n    vitest.write('\\n')\n\n    await vitest.waitForStdout('Filename pattern: math')\n    await vitest.waitForStdout('1 passed')\n  })\n\n  test('filter by filename when multiple projects match same file', async () => {\n    const { vitest } = await runVitest({\n      ...options,\n      projects: [\n        {\n          test: {\n            name: 'First',\n            root: options.root,\n          },\n        },\n        {\n          test: {\n            name: 'Second',\n            root: options.root,\n          },\n        },\n      ],\n    })\n\n    vitest.write('p')\n\n    await vitest.waitForStdout('Input filename pattern')\n\n    vitest.write('math')\n\n    await vitest.waitForStdout('Pattern matches 1 result')\n    await vitest.waitForStdout('› math.test.ts')\n\n    vitest.write('\\n')\n\n    // 2 due to count of projects\n    await vitest.waitForStdout('2 passed')\n    await vitest.waitForStdout('Filename pattern: math')\n  })\n\n  test('filter by test name', async () => {\n    const { vitest } = await runVitest(options)\n\n    vitest.write('t')\n\n    await vitest.waitForStdout('Input test name pattern')\n\n    vitest.write('sum')\n    if (standalone) {\n      await vitest.waitForStdout('Pattern matches no results')\n    }\n    else {\n      await vitest.waitForStdout('Pattern matches 1 result')\n    }\n    await vitest.waitForStdout('› sum')\n\n    vitest.write('\\n')\n\n    await vitest.waitForStdout('Test name pattern: /sum/')\n    await vitest.waitForStdout('1 passed')\n  })\n\n  test.skipIf(process.env.GITHUB_ACTIONS)('cancel test run', async () => {\n    const { vitest } = await runVitest(options)\n\n    const testPath = 'fixtures/watch/cancel.test.ts'\n    const testCase = `// Dynamic test case\nimport { afterAll, afterEach, test } from 'vitest'\n\n// These should be called even when test is cancelled\nafterAll(() => console.log('[cancel-test]: afterAll'))\nafterEach(() => console.log('[cancel-test]: afterEach'))\n\ntest('1 - test that finishes', async () => {\n  console.log('[cancel-test]: test')\n\n  await new Promise(resolve => setTimeout(resolve, 1000))\n})\n\ntest('2 - test that is cancelled', async () => {\n  console.log('[cancel-test]: should not run')\n})\n`\n\n    onTestFinished(() => rmSync(testPath))\n    writeFileSync(testPath, testCase, 'utf8')\n\n    // Test case is running, cancel it\n    await vitest.waitForStdout('[cancel-test]: test')\n    vitest.write('c')\n\n    // Test hooks should still be called\n    await vitest.waitForStdout('CANCELLED')\n    await vitest.waitForStdout('[cancel-test]: afterAll')\n    await vitest.waitForStdout('[cancel-test]: afterEach')\n\n    expect(vitest.stdout).not.include('[cancel-test]: should not run')\n  })\n})\n\ntest('rerun current pattern tests', async () => {\n  const { vitest } = await runVitest({ ..._options, testNamePattern: 'sum' })\n\n  vitest.write('r')\n\n  await vitest.waitForStdout('RERUN')\n  await vitest.waitForStdout('Test name pattern: /sum/')\n  await vitest.waitForStdout('1 passed')\n})\n\ntest('cli filter as watch filename pattern', async () => {\n  const { vitest } = await runVitest(_options, ['math'])\n\n  vitest.write('r')\n\n  await vitest.waitForStdout('RERUN')\n  await vitest.waitForStdout('Filename pattern: math')\n  await vitest.waitForStdout('1 passed')\n})\n"
  },
  {
    "path": "test/cli/test/watch/stdout.test.ts",
    "content": "import { readFileSync, writeFileSync } from 'node:fs'\nimport { runVitest } from '#test-utils'\nimport { afterEach, test } from 'vitest'\n\nconst testFile = 'fixtures/watch/math.test.ts'\nconst testFileContent = readFileSync(testFile, 'utf-8')\n\nafterEach(() => {\n  writeFileSync(testFile, testFileContent, 'utf8')\n})\n\ntest('console.log is visible on test re-run', async () => {\n  const { vitest } = await runVitest({ root: 'fixtures/watch', watch: true })\n\n  const testCase = `\ntest('test with logging', () => {\n  console.log('First')\n  console.log('Second')\n  console.log('Third')\n  expect(true).toBe(true)\n})\n`\n\n  writeFileSync(testFile, `${testFileContent}${testCase}`, 'utf8')\n\n  await vitest.waitForStdout('stdout | math.test.ts > test with logging')\n  await vitest.waitForStdout('First')\n  await vitest.waitForStdout('Second')\n  await vitest.waitForStdout('Third')\n})\n"
  },
  {
    "path": "test/cli/test/watch/workspaces.test.ts",
    "content": "import { readFileSync, rmSync, writeFileSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { runInlineTests, runVitestCli } from '#test-utils'\nimport { dirname, resolve } from 'pathe'\n\nimport { afterAll, afterEach, expect, it } from 'vitest'\n\nconst file = fileURLToPath(import.meta.url)\nconst dir = dirname(file)\nconst root = resolve(dir, '..', '..', '..', 'workspaces')\nconst config = resolve(root, 'vitest.config.watch.ts')\nconst cleanups: (() => void)[] = []\n\nconst srcMathFile = resolve(root, 'src', 'math.ts')\nconst specSpace2File = resolve(root, 'space_2', 'test', 'node.spec.ts')\n\nconst srcMathContent = readFileSync(srcMathFile, 'utf-8')\nconst specSpace2Content = readFileSync(specSpace2File, 'utf-8')\n\nconst dynamicTestContent = `// Dynamic test added by test/watch/test/workspaces.test.ts\nimport { expect, test } from \"vitest\";\n\ntest(\"dynamic test case\", () => {\n  console.log(\"Running added dynamic test\")\n  expect(true).toBeTruthy()\n})\n`\n\nasync function startVitest() {\n  const { vitest } = await runVitestCli(\n    { nodeOptions: { cwd: root, env: { TEST_WATCH: 'true', NO_COLOR: 'true' } } },\n    '--root',\n    root,\n    '--config',\n    config,\n    '--watch',\n    '--no-coverage',\n  )\n  vitest.resetOutput()\n  return vitest\n}\n\nafterEach(() => {\n  cleanups.splice(0).forEach(cleanup => cleanup())\n})\n\nafterAll(() => {\n  writeFileSync(srcMathFile, srcMathContent, 'utf8')\n  writeFileSync(specSpace2File, specSpace2Content, 'utf8')\n})\n\nit('editing a test file in a suite with workspaces reruns test', async () => {\n  const vitest = await startVitest()\n\n  writeFileSync(specSpace2File, `${specSpace2Content}\\n`, 'utf8')\n\n  await vitest.waitForStdout('RERUN  space_2/test/node.spec.ts x1')\n  await vitest.waitForStdout('|space_2| test/node.spec.ts')\n  await vitest.waitForStdout('Test Files  1 passed')\n})\n\nit('editing a file that is imported in different workspaces reruns both files', async () => {\n  const vitest = await startVitest()\n\n  writeFileSync(srcMathFile, `${srcMathContent}\\n`, 'utf8')\n\n  await vitest.waitForStdout('RERUN  src/math.ts')\n  await vitest.waitForStdout('|@vitest/space_3| math.space-3-test.ts')\n  await vitest.waitForStdout('|space_1| test/math.spec.ts')\n  await vitest.waitForStdout('Test Files  2 passed')\n})\n\nit('filters by test name inside a workspace', async () => {\n  const vitest = await startVitest()\n\n  vitest.write('t')\n\n  await vitest.waitForStdout('Input test name pattern')\n\n  vitest.write('2 x 2 = 4\\n')\n\n  await vitest.waitForStdout('Test name pattern: /2 x 2 = 4/')\n  await vitest.waitForStdout('Test Files  1 passed')\n})\n\nit('adding a new test file matching core project config triggers re-run', async () => {\n  const vitest = await startVitest()\n\n  const testFile = resolve(root, 'space_2', 'test', 'new-dynamic.test.ts')\n\n  cleanups.push(() => rmSync(testFile))\n  writeFileSync(testFile, dynamicTestContent, 'utf-8')\n\n  await vitest.waitForStdout('Running added dynamic test')\n  await vitest.waitForStdout('RERUN  space_2/test/new-dynamic.test.ts')\n  await vitest.waitForStdout('|space_2| test/new-dynamic.test.ts')\n\n  // Wait for tests to end\n  await vitest.waitForStdout('Waiting for file changes')\n\n  // Test case should not be run by other projects\n  expect(vitest.stdout).not.include('|space_1|')\n  expect(vitest.stdout).not.include('|@vitest/space_3|')\n  expect(vitest.stdout).not.include('|node|')\n  expect(vitest.stdout).not.include('|happy-dom|')\n})\n\nit('adding a new test file matching project specific config triggers re-run', async () => {\n  const vitest = await startVitest()\n\n  const testFile = resolve(root, 'space_3', 'new-dynamic.space-3-test.ts')\n  cleanups.push(() => rmSync(testFile))\n  writeFileSync(testFile, dynamicTestContent, 'utf-8')\n\n  await vitest.waitForStdout('Running added dynamic test')\n  await vitest.waitForStdout('RERUN  space_3/new-dynamic.space-3-test.ts')\n  await vitest.waitForStdout('|@vitest/space_3| new-dynamic.space-3-test.ts')\n\n  // Wait for tests to end\n  await vitest.waitForStdout('Waiting for file changes')\n\n  // Test case should not be run by other projects\n  expect(vitest.stdout).not.include('|space_1|')\n  expect(vitest.stdout).not.include('|space_2|')\n  expect(vitest.stdout).not.include('|node|')\n  expect(vitest.stdout).not.include('|happy-dom|')\n})\n\nit('editing a setup file inside the project reruns tests', async () => {\n  const { fs, vitest } = await runInlineTests({\n    'setupFile.js': '',\n    'project-1/basic.test.js': `test(\"[p1] reruns\", () => {})`,\n    'project-2/basic.test.js': `test(\"[p2] doesn\\'t rerun\", () => {})`,\n    'vitest.config.js': {\n      test: {\n        projects: [\n          {\n            test: {\n              name: 'p1',\n              include: ['./project-1/basic.test.js'],\n              setupFiles: ['./setupFile.js'],\n              globals: true,\n            },\n          },\n          {\n            test: {\n              name: 'p2',\n              include: ['./project-2/basic.test.js'],\n              globals: true,\n            },\n          },\n        ],\n      },\n    },\n  }, { watch: true })\n\n  await vitest.waitForStdout('Waiting for file changes')\n  expect(vitest.stdout).toContain('[p1] reruns')\n  expect(vitest.stdout).toContain('[p2] doesn\\'t rerun')\n\n  fs.editFile('./setupFile.js', () => '// ---edit')\n\n  vitest.resetOutput()\n  await vitest.waitForStdout('Test Files  1 passed')\n\n  expect(vitest.stdout).toContain('[p1] reruns')\n  expect(vitest.stdout).not.toContain('[p2] doesn\\'t rerun')\n})\n"
  },
  {
    "path": "test/cli/test/windows-drive-case.test.ts",
    "content": "import { join } from 'pathe'\nimport { expect, test } from 'vitest'\nimport { runVitestCli } from '../../test-utils'\n\nconst _DRIVE_LETTER_START_RE = /^[A-Z]:\\//i\nconst root = join(import.meta.dirname, '../fixtures/windows-drive-case')\nconst cwd = root.replace(_DRIVE_LETTER_START_RE, r => r.toLowerCase())\n\ntest.runIf(process.platform === 'win32')(`works on windows with a lowercase drive: ${cwd}`, async () => {\n  const { stderr, stdout } = await runVitestCli({\n    nodeOptions: {\n      cwd,\n    },\n  }, '--no-watch')\n\n  expect(cwd[0]).toEqual(cwd[0].toLowerCase())\n  expect(stderr).toBe('')\n  expect(stdout).toContain('1 passed')\n})\n"
  },
  {
    "path": "test/cli/test/workers-option.test.ts",
    "content": "import * as testUtils from '#test-utils'\nimport { describe, expect, test, vi } from 'vitest'\nimport { getWorkersCountByPercentage } from 'vitest/src/utils/workers.js'\n\nvi.mock(import('node:os'), async importOriginal => ({\n  ...(await importOriginal()),\n  default: {\n    ...(await importOriginal()).default,\n    availableParallelism: () => 10,\n  },\n}))\n\ndescribe('workers util', () => {\n  test('percent=50% should return 5', () => {\n    expect(getWorkersCountByPercentage('50%')).toBe(5)\n  })\n\n  test('percent=-10% should return 1', () => {\n    expect(getWorkersCountByPercentage('-10%')).toBe(1)\n  })\n\n  test('percent=110% should return 10', () => {\n    expect(getWorkersCountByPercentage('110%')).toBe(10)\n  })\n})\n\ntest.each([\n  { pool: 'threads' },\n  { poolOption: 'vmThreads' },\n  { poolOption: 'forks' },\n  { poolOption: 'vmForks' },\n] as const)('workers percent argument in $poolOption should not throw error', async ({ pool }) => {\n  const { stderr } = await testUtils.runInlineTests(\n    { 'basic.test.js': 'test(\"defined\")' },\n    { maxWorkers: '100%', pool, globals: true },\n  )\n\n  expect(stderr).toBe('')\n})\n"
  },
  {
    "path": "test/cli/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.build.json\",\n  \"include\": [\"./test/**/*.test-d.ts\"]\n}\n"
  },
  {
    "path": "test/cli/vitest.config.ts",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  test: {\n    include: ['test/**/**.{test,spec}.ts'],\n    includeTaskLocation: true,\n    reporters: ['verbose'],\n    testTimeout: 60_000,\n    isolate: false,\n    fileParallelism: false,\n    // TODO: should enabled when support for older node is dropped?\n    // experimental: {\n    //   viteModuleRunner: false,\n    //   nodeLoader: false,\n    // },\n    chaiConfig: {\n      truncateThreshold: 999,\n    },\n    typecheck: {\n      enabled: true,\n      include: ['./test/reporters/configuration-options.test-d.ts'],\n    },\n    onConsoleLog(log) {\n      if (log.includes('watcher is ready')) {\n        return false\n      }\n    },\n  },\n  server: {\n    watch: {\n      ignored: [\n        '**/fixtures/browser-multiple/**/*',\n        '**/fixtures/browser-init/**/*',\n        '**/package.json',\n      ],\n    },\n  },\n})\n"
  },
  {
    "path": "test/config/deps/optimizer/external/index.js",
    "content": "export default {}\n"
  },
  {
    "path": "test/config/deps/optimizer/external/package.json",
    "content": "{\n  \"name\": \"@vitest/test-dep-optimizer-external\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"main\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/config/deps/optimizer/optimized/index.js",
    "content": "export default {}\n"
  },
  {
    "path": "test/config/deps/optimizer/optimized/package.json",
    "content": "{\n  \"name\": \"@vitest/test-dep-optimizer-optimized\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"main\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/config/deps/test-dep-conditions/false.js",
    "content": "export default false\n"
  },
  {
    "path": "test/config/deps/test-dep-conditions/indirect.js",
    "content": "import conditionCustom from 'test-dep-conditions-indirect/custom'\nimport conditionDevelopment from 'test-dep-conditions-indirect/development'\nimport conditionModule from 'test-dep-conditions-indirect/module'\nimport conditionNode from 'test-dep-conditions-indirect/node'\nimport conditionProductioin from 'test-dep-conditions-indirect/production'\n\nexport default {\n  conditionCustom,\n  conditionModule,\n  conditionNode,\n  conditionDevelopment,\n  conditionProductioin,\n}\n"
  },
  {
    "path": "test/config/deps/test-dep-conditions/inline.js",
    "content": "export default !!import.meta.__IS_INLINE__\n"
  },
  {
    "path": "test/config/deps/test-dep-conditions/package.json",
    "content": "{\n  \"name\": \"test-dep-conditions\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"exports\": {\n    \"./custom\": {\n      \"custom\": \"./true.js\",\n      \"default\": \"./false.js\"\n    },\n    \"./module\": {\n      \"module\": \"./true.js\",\n      \"default\": \"./false.js\"\n    },\n    \"./node\": {\n      \"node\": \"./true.js\",\n      \"default\": \"./false.js\"\n    },\n    \"./development\": {\n      \"development\": \"./true.js\",\n      \"default\": \"./false.js\"\n    },\n    \"./production\": {\n      \"production\": \"./true.js\",\n      \"default\": \"./false.js\"\n    },\n    \"./inline\": \"./inline.js\",\n    \"./indirect\": \"./indirect.js\"\n  },\n  \"dependencies\": {\n    \"test-dep-conditions-indirect\": \"file:../test-dep-conditions-indirect\"\n  }\n}\n"
  },
  {
    "path": "test/config/deps/test-dep-conditions/true.js",
    "content": "export default true\n"
  },
  {
    "path": "test/config/deps/test-dep-conditions-indirect/false.js",
    "content": "export default false\n"
  },
  {
    "path": "test/config/deps/test-dep-conditions-indirect/package.json",
    "content": "{\n  \"name\": \"test-dep-conditions-indirect\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"exports\": {\n    \"./custom\": {\n      \"custom\": \"./true.js\",\n      \"default\": \"./false.js\"\n    },\n    \"./module\": {\n      \"module\": \"./true.js\",\n      \"default\": \"./false.js\"\n    },\n    \"./node\": {\n      \"node\": \"./true.js\",\n      \"default\": \"./false.js\"\n    },\n    \"./development\": {\n      \"development\": \"./true.js\",\n      \"default\": \"./false.js\"\n    },\n    \"./production\": {\n      \"production\": \"./true.js\",\n      \"default\": \"./false.js\"\n    }\n  }\n}\n"
  },
  {
    "path": "test/config/deps/test-dep-conditions-indirect/true.js",
    "content": "export default true\n"
  },
  {
    "path": "test/config/deps/test-dep-config/index.js",
    "content": "export default {}\n"
  },
  {
    "path": "test/config/deps/test-dep-config/package.json",
    "content": "{\n  \"name\": \"@test/test-dep-config\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"main\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/config/deps/test-dep-virtual/index.js",
    "content": "export * from 'virtual:test'\n"
  },
  {
    "path": "test/config/deps/test-dep-virtual/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-virtual\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"exports\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/config/deps/vite-ssr-resolve/inline-dep/index.js",
    "content": ""
  },
  {
    "path": "test/config/deps/vite-ssr-resolve/inline-dep/package.json",
    "content": "{\n  \"name\": \"inline-dep\",\n  \"type\": \"module\",\n  \"exports\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/config/deps/vite-ssr-resolve/other-dep/index.js",
    "content": ""
  },
  {
    "path": "test/config/deps/vite-ssr-resolve/other-dep/package.json",
    "content": "{\n  \"name\": \"other-dep\",\n  \"type\": \"module\",\n  \"exports\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/config/deps/vite-ssr-resolve/ssr-no-external-dep/index.js",
    "content": ""
  },
  {
    "path": "test/config/deps/vite-ssr-resolve/ssr-no-external-dep/package.json",
    "content": "{\n  \"name\": \"ssr-no-external-dep\",\n  \"type\": \"module\",\n  \"exports\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/config/fixtures/allowed-exec-args-fixtures/allowed-exec-argv.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('exec-args', async () => {\n  it('should have the correct flags', () => {\n    // flags that should go through\n    expect(process.execArgv).toContain('--heap-prof')\n    expect(process.execArgv).toContain('--heap-prof-name=heap.prof')\n    expect(process.execArgv).toContain('--diagnostic-dir=/tmp/vitest-diagnostics')\n\n    // added via vitest\n    expect(process.execArgv).toContain('--conditions')\n    expect(process.execArgv).toContain('node')\n  })\n})\n"
  },
  {
    "path": "test/config/fixtures/allowed-exec-args-fixtures/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/config/fixtures/browser-no-config/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    browser: {\n      headless: true,\n      // testing that instances is required\n    },\n  },\n})"
  },
  {
    "path": "test/config/fixtures/browser-persistent-context/basic.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\nconst expectedValue = import.meta.env.TEST_EXPECTED_VALUE || \"0\";\n\ntest(`expectedValue = ${expectedValue}`, () => {\n  // increment localStorage to test persistent context between test runs\n  const value = localStorage.getItem(\"test-persistent-context\") || \"0\";\n  const nextValue = String(Number(value) + 1);\n  console.log(`localStorage: value = ${value}, nextValue = ${nextValue}`);\n  localStorage.setItem(\"test-persistent-context\", nextValue);\n\n  const div = document.createElement(\"div\");\n  div.textContent = `localStorage: value = ${value}, nextValue = ${nextValue}`;\n  document.body.appendChild(div);\n\n  expect(value).toBe(expectedValue)\n});\n"
  },
  {
    "path": "test/config/fixtures/browser-persistent-context/vitest.config.ts",
    "content": "import { playwright } from \"@vitest/browser-playwright\";\nimport path from \"node:path\";\nimport { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  define: {\n    'import.meta.env.TEST_EXPECTED_VALUE': JSON.stringify(String(process.env.TEST_EXPECTED_VALUE)),\n  },\n  test: {\n    browser: {\n      enabled: true,\n      headless: true,\n      provider: playwright({\n        persistentContext: path.join(import.meta.dirname, \"./node_modules/.cache/test-user-data\"),\n      }),\n      instances: [{ browser: \"chromium\" }],\n    },\n    fileParallelism: false,\n  },\n});\n"
  },
  {
    "path": "test/config/fixtures/cache/basic.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest('', () => {\n  expect(true).toBe(true)\n})\n"
  },
  {
    "path": "test/config/fixtures/cache/second.test.ts",
    "content": "import { expect, test } from \"vitest\";\n\ntest('', () => {\n  expect(true).toBe(true)\n})\n"
  },
  {
    "path": "test/config/fixtures/chai-config/test-each-title.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest.each`\n  length | param\n  ${30}  | ${'0123456789'.repeat(3)}\n  ${40}  | ${'0123456789'.repeat(4)}\n  ${50}  | ${'0123456789'.repeat(5)}\n`('$param (length = $length)', () => {});\n\ntest.each`\n  param\n  ${['one', 'two', 'three']}\n  ${['one', 'two', 'three', 'four']}\n  ${['one', 'two', 'three', 'four', 'five']}\n`('$param', () => {});\n\ntest.each`\n  param\n  ${{ one: 1, two: 2, three: 3 }}\n  ${{ one: 1, two: 2, three: 3, four: 4 }}\n  ${{ one: 1, two: 2, three: 3, four: 4, five: 5 }}\n`('$param', () => {});\n"
  },
  {
    "path": "test/config/fixtures/chai-config/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/config/fixtures/conditions/basic.test.js",
    "content": "import { test, expect } from 'vitest';\nimport conditionCustom from 'test-dep-conditions/custom';\nimport conditionModule from 'test-dep-conditions/module';\nimport conditionNode from 'test-dep-conditions/node';\nimport conditionDevelopment from 'test-dep-conditions/development';\nimport conditionProduction from 'test-dep-conditions/production';\nimport inline from 'test-dep-conditions/inline';\nimport indirect from 'test-dep-conditions/indirect';\n\nimport { viteVersion } from 'vitest/node'\nconst viteMajor = Number(viteVersion.split('.')[0])\n\ntest('conditions', () => {\n  expect({\n    conditionCustom,\n    conditionModule,\n    conditionNode,\n    conditionDevelopment,\n    conditionProduction,\n    indirect\n  }).toEqual(\n    {\n      conditionCustom: true,\n      \"conditionDevelopment\": true,\n      \"conditionModule\": viteMajor <= 5,\n      \"conditionNode\": true,\n      \"conditionProduction\": false,\n      \"indirect\": {\n        conditionCustom: true,\n        \"conditionDevelopment\": true,\n        \"conditionModule\": viteMajor <= 5 && inline,\n        \"conditionNode\": true,\n        \"conditionProductioin\": false,\n      },\n    }\n  )\n})\n"
  },
  {
    "path": "test/config/fixtures/conditions/vite.config.ts",
    "content": "import { defineConfig } from \"vitest/config\"\n\nexport default defineConfig({\n  define: {\n    'import.meta.__IS_INLINE__': 'true',\n  },\n  resolve: {\n    conditions: ['custom'],\n  },\n  ssr: {\n    resolve: {\n      conditions: ['custom'],\n    },\n  }\n})\n"
  },
  {
    "path": "test/config/fixtures/conditions-pkg/index.js",
    "content": "export { default as condition } from 'subpackage'\n"
  },
  {
    "path": "test/config/fixtures/conditions-pkg/package.json",
    "content": "{\n  \"name\": \"conditions\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"subpackage\": \"file:../conditions-subpackage\"\n  }\n}"
  },
  {
    "path": "test/config/fixtures/conditions-projects/project-a/basic.test.js",
    "content": "import { test, expect } from \"vitest\";\nimport conditionCustom from \"test-dep-conditions/custom\";\nimport conditionModule from \"test-dep-conditions/module\";\nimport conditionNode from \"test-dep-conditions/node\";\nimport conditionDevelopment from \"test-dep-conditions/development\";\nimport conditionProduction from \"test-dep-conditions/production\";\nimport inline from \"test-dep-conditions/inline\";\nimport indirect from \"test-dep-conditions/indirect\";\n\nimport { viteVersion } from \"vitest/node\";\nconst viteMajor = Number(viteVersion.split(\".\")[0]);\n\ntest(\"conditions\", () => {\n  expect({\n    inline,\n    conditionCustom,\n    conditionModule,\n    conditionNode,\n    conditionDevelopment,\n    conditionProduction,\n    indirect,\n  }).toEqual({\n    inline: false,\n    conditionCustom: true,\n    conditionDevelopment: true,\n    conditionModule: viteMajor <= 5,\n    conditionNode: true,\n    conditionProduction: false,\n    indirect: {\n      conditionCustom: true,\n      conditionDevelopment: true,\n      conditionModule: viteMajor <= 5 && inline,\n      conditionNode: true,\n      conditionProductioin: false,\n    },\n  });\n});\n"
  },
  {
    "path": "test/config/fixtures/conditions-projects/project-a/vitest.config.ts",
    "content": "import { defaultServerConditions } from \"vite\";\nimport { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  define: {\n    \"import.meta.__IS_INLINE__\": \"true\",\n  },\n  ssr: {\n    resolve: {\n      conditions: [\"custom\", ...defaultServerConditions.filter((c) => c !== \"module\")],\n    },\n  },\n});\n"
  },
  {
    "path": "test/config/fixtures/conditions-projects/project-b/basic.test.js",
    "content": "import { test, expect } from \"vitest\";\nimport conditionCustom from \"test-dep-conditions/custom\";\nimport conditionModule from \"test-dep-conditions/module\";\nimport conditionNode from \"test-dep-conditions/node\";\nimport conditionDevelopment from \"test-dep-conditions/development\";\nimport conditionProduction from \"test-dep-conditions/production\";\nimport inline from \"test-dep-conditions/inline\";\nimport indirect from \"test-dep-conditions/indirect\";\n\nimport { viteVersion } from \"vitest/node\";\nconst viteMajor = Number(viteVersion.split(\".\")[0]);\n\ntest(\"conditions\", () => {\n  expect({\n    inline,\n    conditionCustom,\n    conditionModule,\n    conditionNode,\n    conditionDevelopment,\n    conditionProduction,\n    indirect,\n  }).toEqual({\n    inline: false,\n    conditionCustom: false,\n    conditionDevelopment: true,\n    conditionModule: viteMajor <= 5,\n    conditionNode: true,\n    conditionProduction: false,\n    indirect: {\n      conditionCustom: false,\n      conditionDevelopment: true,\n      conditionModule: viteMajor <= 5 && inline,\n      conditionNode: true,\n      conditionProductioin: false,\n    },\n  });\n});\n"
  },
  {
    "path": "test/config/fixtures/conditions-projects/project-b/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  define: {\n    \"import.meta.__IS_INLINE__\": \"true\",\n  },\n});\n"
  },
  {
    "path": "test/config/fixtures/conditions-projects/vite.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    projects: [\"project-a\", \"project-b\"],\n  },\n});\n"
  },
  {
    "path": "test/config/fixtures/conditions-subpackage/custom.js",
    "content": "export default 'custom'\n"
  },
  {
    "path": "test/config/fixtures/conditions-subpackage/default.js",
    "content": "throw new Error('Should not be imported')\n"
  },
  {
    "path": "test/config/fixtures/conditions-subpackage/development.js",
    "content": "export default 'development'\n"
  },
  {
    "path": "test/config/fixtures/conditions-subpackage/package.json",
    "content": "{\n  \"name\": \"subpackage\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"custom\": \"./custom.js\",\n      \"development\": \"./development.js\",\n      \"production\": \"./production.js\",\n      \"default\": \"./default.js\"\n    }\n  }\n}"
  },
  {
    "path": "test/config/fixtures/conditions-subpackage/production.js",
    "content": "export default 'production'\n"
  },
  {
    "path": "test/config/fixtures/conditions-test/conditions.test.js",
    "content": "import { test, expect } from 'vitest';\nimport { condition } from '../conditions-pkg';\n\ntest('condition is correct', () => {\n  expect(condition).toBe(TEST_CONDITION)\n})\n"
  },
  {
    "path": "test/config/fixtures/conditions-test/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/config/fixtures/console/basic.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('basic', () => {\n  console.error(\"__test_console__\");\n})\n"
  },
  {
    "path": "test/config/fixtures/console/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/config/fixtures/console-batch/basic.test.ts",
    "content": "import { afterAll, afterEach, beforeAll, beforeEach, describe, test } from 'vitest'\n\nbeforeAll(() => {\n  console.log('__TEST__ [beforeAll 1]')\n})\nbeforeAll(() => {\n  console.log('__TEST__ [beforeAll 2]')\n})\n\nafterAll(() => {\n  console.log('__TEST__ [afterAll 1]')\n})\nafterAll(() => {\n  console.log('__TEST__ [afterAll 2]')\n})\n\nbeforeEach(() => {\n  console.log('__TEST__ [beforeEach 1]')\n})\nbeforeEach(() => {\n  console.log('__TEST__ [beforeEach 2]')\n})\n\nafterEach(() => {\n  console.log('__TEST__ [afterEach 1]')\n})\nafterEach(() => {\n  console.log('__TEST__ [afterEach 2]')\n})\n\ntest('test', async () => {\n  console.log('__TEST__ [test 1]')\n  console.log('__TEST__ [test 2]')\n  await Promise.resolve()\n  console.log('__TEST__ [test 3]')\n  console.log('__TEST__ [test 4]')\n})\n"
  },
  {
    "path": "test/config/fixtures/console-color/basic.test.ts",
    "content": "import { test } from 'vitest'\n\ntest(\"console color\", () => {\n  console.log(true) // node console highlights primitive\n})\n"
  },
  {
    "path": "test/config/fixtures/console-color/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/config/fixtures/coverage-test/example.ts",
    "content": "export function uncovered(condition: boolean) {\n  return condition ? 1 : 0\n}"
  },
  {
    "path": "test/config/fixtures/css/App.css",
    "content": ".main {\n  display: flex;\n  width: 100px;\n}\n"
  },
  {
    "path": "test/config/fixtures/css/App.module.css",
    "content": ".main {\n  display: flex;\n}\n\n.module {\n  width: 100px;\n}"
  },
  {
    "path": "test/config/fixtures/css/test/default-css.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { useRemoveStyles } from '../utils'\n\ndescribe('don\\'t process css by default', () => {\n  useRemoveStyles()\n\n  test('doesn\\'t apply css', async () => {\n    await import('../App.css')\n\n    const element = document.createElement('div')\n    element.className = 'main'\n    const computed = window.getComputedStyle(element)\n    expect(computed.display).toBe('block')\n    expect(element).toMatchInlineSnapshot(`\n      <div\n        class=\"main\"\n      />\n    `)\n  })\n\n  test('module is not processed', async () => {\n    const { default: styles } = await import('../App.module.css')\n\n    // HASH is static, based on the filepath to root\n    expect(styles.module).toBe('_module_cdbed7')\n    expect(styles.someRandomValue).toBe('_someRandomValue_cdbed7')\n    const element = document.createElement('div')\n    element.className = '_module_cdbed7'\n    const computed = window.getComputedStyle(element)\n    expect(computed.display).toBe('block')\n    expect(computed.width).toBe('')\n    expect(element).toMatchInlineSnapshot(`\n      <div\n        class=\"_module_cdbed7\"\n      />\n    `)\n  })\n})\n"
  },
  {
    "path": "test/config/fixtures/css/test/non-scope-module.spec.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('module is processed', async () => {\n  const { default: styles } = await import('../App.module.css')\n\n  expect(styles.module).toBe('module')\n  expect(styles.someRandomValue).toBeUndefined()\n  const element = document.createElement('div')\n  element.className = `${styles.main} ${styles.module}`\n  const computed = window.getComputedStyle(element)\n  expect(computed.display).toBe('flex')\n  expect(computed.width).toBe('100px')\n  expect(element).toMatchInlineSnapshot(`\n    <div\n      class=\"main module\"\n    />\n  `)\n})\n"
  },
  {
    "path": "test/config/fixtures/css/test/process-css.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { useRemoveStyles } from '../utils'\n\ndescribe('process only css, not module css', () => {\n  useRemoveStyles()\n\n  test('apply css', async () => {\n    await import('../App.css')\n\n    const element = document.createElement('div')\n    element.className = 'main'\n    const computed = window.getComputedStyle(element)\n    expect(computed.display).toBe('flex')\n    expect(element).toMatchInlineSnapshot(`\n      <div\n        class=\"main\"\n      />\n    `)\n  })\n\n  test('module is not processed', async () => {\n    const { default: styles } = await import('../App.module.css')\n\n    expect(styles.module).toBe('_module_cdbed7')\n    expect(styles.someRandomValue).toBe('_someRandomValue_cdbed7')\n    const element = document.createElement('div')\n    element.className = '_module_cdbed7'\n    const computed = window.getComputedStyle(element)\n    expect(computed.display).toBe('block')\n    expect(computed.width).toBe('')\n    expect(element).toMatchInlineSnapshot(`\n      <div\n        class=\"_module_cdbed7\"\n      />\n    `)\n  })\n})\n"
  },
  {
    "path": "test/config/fixtures/css/test/process-inline.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { useRemoveStyles } from '../utils'\n\ndescribe('processing inline css', () => {\n  useRemoveStyles()\n\n  test('doesn\\'t apply css', async () => {\n    await import('../App.module.css?inline')\n\n    const element = document.createElement('div')\n    element.className = 'main'\n    const computed = window.getComputedStyle(element)\n    expect(computed.display, 'css is not processed').toBe('block')\n  })\n\n  test('returns a string', async () => {\n    const { default: style } = await import('../App.module.css?inline')\n    expect(typeof style).toBe('string')\n  })\n})\n"
  },
  {
    "path": "test/config/fixtures/css/test/process-module.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { useRemoveStyles } from '../utils'\n\ndescribe('processing module css', () => {\n  useRemoveStyles()\n\n  test('doesn\\'t apply css', async () => {\n    await import('../App.css')\n\n    const element = document.createElement('div')\n    element.className = 'main'\n    const computed = window.getComputedStyle(element)\n    expect(computed.display, 'css is not processed').toBe('block')\n  })\n\n  test('module is processed', async () => {\n    const { default: styles } = await import('../App.module.css')\n\n    expect(styles.module).toBe('_module_cdbed7')\n    expect(styles.someRandomValue).toBeUndefined()\n    const element = document.createElement('div')\n    element.className = '_main_cdbed7 _module_cdbed7'\n    const computed = window.getComputedStyle(element)\n    expect(computed.display, 'css is processed').toBe('flex')\n    expect(computed.width).toBe('100px')\n    expect(element).toMatchInlineSnapshot(`\n      <div\n        class=\"_main_cdbed7 _module_cdbed7\"\n      />\n    `)\n  })\n})\n"
  },
  {
    "path": "test/config/fixtures/css/test/scope-module.spec.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('module is processed and scoped', async () => {\n  const { default: styles } = await import('../App.module.css')\n\n  expect(styles.module).toMatch(/_module_\\w+_\\w/)\n  expect(styles.someRandomValue).toBeUndefined()\n  const element = document.createElement('div')\n  element.className = 'module main'\n  const computedStatic = window.getComputedStyle(element)\n  expect(computedStatic.display).toBe('block')\n  expect(computedStatic.width).toBe('')\n  expect(element).toMatchInlineSnapshot(`\n    <div\n      class=\"module main\"\n    />\n  `)\n\n  const mangledElement = document.createElement('div')\n\n  mangledElement.className = `${styles.module} ${styles.main}`\n  const computedModules = window.getComputedStyle(mangledElement)\n  expect(computedModules.display).toBe('flex')\n  expect(computedModules.width).toBe('100px')\n  expect(mangledElement).toMatchInlineSnapshot(`\n    <div\n      class=\"_module_19cso_5 _main_19cso_1\"\n    />\n  `)\n})\n"
  },
  {
    "path": "test/config/fixtures/css/utils.ts",
    "content": "import { afterEach, beforeEach } from 'vitest'\n\nfunction removeStyles() {\n  document.head.querySelectorAll('style').forEach(style => style.remove())\n}\nexport function useRemoveStyles() {\n  beforeEach(() => removeStyles())\n  afterEach(() => removeStyles())\n\n  return {\n    removeStyles,\n  }\n}\n"
  },
  {
    "path": "test/config/fixtures/diff/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('large diff', () => {\n  const x = [...Array(30)].map((_, i) => i);\n  const y = [...x];\n  y[0] = 1000;\n  y[15] = 2000;\n  y[29] = 3000;\n  expect(x).toEqual(y)\n})\n\ntest(\"printBasicPrototype\", () => {\n  expect({\n    obj: { k: \"foo\" },\n    arr: [1, 2]\n  }).toEqual({\n    obj: { k: \"bar\" },\n    arr: [1, 3]\n  });\n})\n"
  },
  {
    "path": "test/config/fixtures/diff/vite.config.ts",
    "content": "import {defineConfig} from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    diff: {\n      // expand: false,\n      // printBasicPrototype: false,\n    }\n  }\n})\n"
  },
  {
    "path": "test/config/fixtures/exclude/math.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { add } from './math'\n\ntest('should add two numbers correctly', () => {\n  expect(add(1, 2)).toBe(3)\n})\n"
  },
  {
    "path": "test/config/fixtures/exclude/math.ts",
    "content": "export function add(a: number, b: number): number {\n  return a + b\n}\n"
  },
  {
    "path": "test/config/fixtures/exclude/string.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { capitalize } from './string'\n\ntest('should capitalize strings correctly', () => {\n  expect(capitalize('i Love Vitest')).toBe('I love vitest')\n})\n"
  },
  {
    "path": "test/config/fixtures/exclude/string.ts",
    "content": "export function capitalize(str: string): string {\n  return str.slice(0, 1).toUpperCase() + str.slice(1).toLowerCase()\n}\n"
  },
  {
    "path": "test/config/fixtures/exclude/vitest.exclude.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: ['fixtures/exclude/*.test.ts'],\n  },\n})\n"
  },
  {
    "path": "test/config/fixtures/exec-args-fixtures/forks.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('exec-args', async () => {\n  it('should have the correct flags', () => {\n    expect(process.execArgv).toContain('--hash-seed=1')\n    expect(process.execArgv).toContain('--random-seed=1')\n    expect(process.execArgv).toContain('--no-opt')\n\n    // added via vitest\n    expect(process.execArgv).toContain('--conditions')\n    expect(process.execArgv).toContain('node')\n  })\n})\n"
  },
  {
    "path": "test/config/fixtures/exec-args-fixtures/threads.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('exec-args', async () => {\n  it('should have the correct flags', () => {\n    expect(process.execArgv).toContain('--inspect-brk')\n\n    // added via vitest\n    expect(process.execArgv).toContain('--conditions')\n    expect(process.execArgv).toContain('node')\n  })\n})\n"
  },
  {
    "path": "test/config/fixtures/exec-args-fixtures/vmThreads.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('exec-args', async () => {\n  it('should have the correct flags', () => {\n    const execArgv = process.execArgv.map((arg) => arg.replace(/\\\\/g, '/'))\n    expect(execArgv).toContain('--inspect-brk')\n\n    // added via vitest\n    expect(execArgv).toContain('--experimental-import-meta-resolve')\n    expect(execArgv).toContain('--experimental-vm-modules')\n    expect(execArgv).toContain('--require')\n    expect(execArgv).toContainEqual(expect.stringContaining('/packages/vitest/suppress-warnings.cjs'))\n    expect(execArgv).toContain('--conditions')\n    expect(execArgv).toContain('node')\n  })\n})\n"
  },
  {
    "path": "test/config/fixtures/external/dynamic/basic.test.ts",
    "content": "import { expect, it } from \"vitest\";\n\nit(\"basic\", async () => {\n  const getId = () => \"@vitejs/test-dep-virtual\";\n  const mod = await import(getId());\n  expect(mod.test).toBe(\"ok\");\n});\n"
  },
  {
    "path": "test/config/fixtures/external/dynamic/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  ssr: {\n    noExternal: [\"@vitejs/test-dep-virtual\"],\n  },\n  plugins: [\n    {\n      name: 'test-virtual',\n      resolveId(source) {\n        if (source === 'virtual:test') {\n          return '\\0' + source;\n        }\n      },\n      load(id) {\n        if (id === '\\0virtual:test') {\n          return `export const test = \"ok\";`;\n        }\n      }\n    }\n  ],\n});\n"
  },
  {
    "path": "test/config/fixtures/filters/test/config.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('this will pass', () => {\n  expect('This test should be run').toBeTruthy()\n})\n"
  },
  {
    "path": "test/config/fixtures/filters/test/dont-run-this.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('this will fail', () => {\n  expect('This test should not be run').toBeFalsy()\n})\n"
  },
  {
    "path": "test/config/fixtures/filters/test/example.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('this will pass', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/config/fixtures/filters-slash/test/basic/a.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('example', () => {})\n"
  },
  {
    "path": "test/config/fixtures/filters-slash/test/basic-foo/a.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('example', () => {})\n"
  },
  {
    "path": "test/config/fixtures/filters-slash/test/basic.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('example', () => {})\n"
  },
  {
    "path": "test/config/fixtures/filters-slash/test/foo-basic/a.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('example', () => {})\n"
  },
  {
    "path": "test/config/fixtures/filters-slash/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/config/fixtures/fixture-no-async/basic.test.ts",
    "content": "import { test as base, expect } from \"vitest\";\n\ntype Fixture = {\n  simple: string,\n  nested: string,\n  notArrow1: string,\n  notArrow2: string,\n  notArrow3: string,\n}\n\nconst test = base.extend<Fixture>({\n  simple: async ({}, use) => {\n    await use(\"simple\");\n  },\n  nested: async ({ simple }, use) => {\n    await use(\"nested:\" + simple);\n  },\n  async notArrow1({}, use) {\n    await use(\"notArrow1\");\n  },\n  notArrow2: async function({}, use) {\n    await use(\"notArrow2\");\n  },\n  notArrow3: async function notArrow3({}, use) {\n    await use(\"notArrow3\");\n  }\n});\n\ntest(\"test sync\", ({ simple, nested }) => {\n  expect(simple).toBe(\"simple\");\n  expect(nested).toBe(\"nested:simple\")\n});\n\ntest(\"test async\", async ({ simple, nested }) => {\n  expect(simple).toBe(\"simple\");\n  expect(nested).toBe(\"nested:simple\")\n});\n\ntest.for([1, 2])(\"test.for sync %i\", (i, { expect, simple, nested }) => {\n  expect(i).toBeTypeOf(\"number\")\n  expect(simple).toBe(\"simple\");\n  expect(nested).toBe(\"nested:simple\")\n})\n\ntest.for([1, 2])(\"test.for async %i\", async (i, { expect, simple, nested }) => {\n  expect(i).toBeTypeOf(\"number\")\n  expect(simple).toBe(\"simple\");\n  expect(nested).toBe(\"nested:simple\")\n})\n\ntest(\"test notArrow\", async function ({ notArrow1, notArrow2, notArrow3 }) {\n  expect(notArrow1).toMatchInlineSnapshot(`\"notArrow1\"`)\n  expect(notArrow2).toMatchInlineSnapshot(`\"notArrow2\"`)\n  expect(notArrow3).toMatchInlineSnapshot(`\"notArrow3\"`)\n});\n"
  },
  {
    "path": "test/config/fixtures/fixture-no-async/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  esbuild: {\n    supported: {\n      \"async-await\": false,\n    },\n  },\n});\n"
  },
  {
    "path": "test/config/fixtures/hook-timeout/basic.test.ts",
    "content": "import { describe, it, beforeAll, beforeEach, afterAll, afterEach } from \"vitest\"\n\ndescribe('beforeAll', () => {\n  beforeAll(() => new Promise(() => {}), 10)\n\n  it('ok', () => {})\n})\n\ndescribe('beforeEach', () => {\n  beforeEach(() => new Promise(() => {}), 20)\n\n  it('ok', () => {})\n})\n\ndescribe('afterAll', () => {\n  afterAll(() => new Promise(() => {}), 30)\n\n  it('ok', () => {})\n})\n\ndescribe('afterEach', () => {\n  afterEach(() => new Promise(() => {}), 40)\n\n  it('ok', () => {})\n})\n\ndescribe('cleanup-beforeAll', () => {\n  beforeAll(() => () => new Promise(() => {}), 50)\n\n  it('ok', () => {})\n})\n\ndescribe('cleanup-beforeEach', () => {\n  beforeEach(() => () => new Promise(() => {}), 60)\n\n  it('ok', () => {})\n})\n\ndescribe('onFailed', () => {\n  it('fail', (ctx) => {\n    ctx.onTestFailed(() => new Promise(() => {}), 70)\n    throw new Error('fail')\n  })\n})\n\ndescribe('onFinished', () => {\n  it('ok', (ctx) => {\n    ctx.onTestFinished(() => new Promise(() => {}), 80)\n  })\n})\n\nit(\"test timeout\", () => new Promise(() => {}), 123)\n"
  },
  {
    "path": "test/config/fixtures/inline-setup-file/file-setup.js",
    "content": "if (typeof __vite_ssr_import__ === 'undefined') {\n  throw new Error('Setup file was externalized')\n}\n"
  },
  {
    "path": "test/config/fixtures/inline-setup-file/test.test.js",
    "content": "import { test } from 'vitest'\n\ntest('test', () => {})\n"
  },
  {
    "path": "test/config/fixtures/inline-setup-file/vitest.config.js",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    setupFiles: ['./file-setup'],\n    server: {\n      deps: {\n        // try to force setup file to be external\n        external: [/file-setup/]\n      }\n    }\n  }\n})\n"
  },
  {
    "path": "test/config/fixtures/mixed-environments/project/test/happy-dom.test.ts",
    "content": "/**\n * @vitest-environment happy-dom\n */\n\nimport { expect, test } from 'vitest'\n\ntest('Leaking globals not found', async () => {\n  (globalThis as any).__leaking_from_happy_dom = 'leaking'\n  expect((globalThis as any).__leaking_from_node).toBe(undefined)\n  expect((globalThis as any).__leaking_from_jsdom).toBe(undefined)\n})\n"
  },
  {
    "path": "test/config/fixtures/mixed-environments/project/test/jsdom.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\n\nimport { expect, test } from 'vitest'\n\ntest('Leaking globals not found', async () => {\n  (globalThis as any).__leaking_from_jsdom = 'leaking'\n  expect((globalThis as any).__leaking_from_node).toBe(undefined)\n  expect((globalThis as any).__leaking_from_happy_dom).toBe(undefined)\n})\n"
  },
  {
    "path": "test/config/fixtures/mixed-environments/project/test/node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\n\nimport { expect, test } from 'vitest'\n\ntest('Leaking globals not found', async () => {\n  (globalThis as any).__leaking_from_node = 'leaking'\n  expect((globalThis as any).__leaking_from_jsdom).toBe(undefined)\n  expect((globalThis as any).__leaking_from_happy_dom).toBe(undefined)\n})\n"
  },
  {
    "path": "test/config/fixtures/mixed-environments/project/test/workspace-project.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('Leaking globals not found', async () => {\n  expect((globalThis as any).__leaking_from_workspace_project).toBe(undefined)\n\n  ;(globalThis as any).__leaking_from_workspace_project = 'leaking'\n})\n"
  },
  {
    "path": "test/config/fixtures/mixed-environments/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport { resolve } from 'node:path'\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: 'Project #1',\n          root: resolve(import.meta.dirname, './project'),\n        },\n      },\n      {\n        test: {\n          name: 'Project #2',\n          root: resolve(import.meta.dirname, './project'),\n        },\n      },\n    ]\n  },\n})\n"
  },
  {
    "path": "test/config/fixtures/mode/example.benchmark.ts",
    "content": "import { bench, describe } from 'vitest'\n\ndescribe('example', () => {\n  bench('simple', () => {\n    let _ = 0\n    _ += 1\n  }, { iterations: 1, time: 1, warmupIterations: 0, warmupTime: 0 })\n})\n"
  },
  {
    "path": "test/config/fixtures/mode/example.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('should pass', () => {\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/config/fixtures/mode/vitest.benchmark.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig((env) => {\n  if (env.mode !== 'benchmark') {\n    console.error('env.mode: ', env.mode)\n    throw new Error('env.mode should be equal to \"benchmark\"')\n  }\n\n  return ({})\n})\n"
  },
  {
    "path": "test/config/fixtures/mode/vitest.test.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig((env) => {\n  if (env.mode !== 'test') {\n    console.error('env.mode: ', env.mode)\n    throw new Error('env.mode should be equal to \"test\"')\n  }\n\n  return ({})\n})\n"
  },
  {
    "path": "test/config/fixtures/no-browser-workspace/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    projects: [\n      {\n        test: {\n          name: 'unit',\n        },\n      },\n    ],\n  },\n})"
  },
  {
    "path": "test/config/fixtures/no-exec-args-fixtures/no-exec-argv.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('exec-args', async () => {\n  it('should have the correct flags', () => {\n    // flags should not be passed\n    expect(process.execArgv).not.toContain('--title')\n\n    // added via vitest\n    expect(process.execArgv).toContain('--conditions')\n    expect(process.execArgv).toContain('node')\n  })\n})\n"
  },
  {
    "path": "test/config/fixtures/no-exec-args-fixtures/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/config/fixtures/optimizer/external/basic.test.ts",
    "content": "import { it, expect } from \"vitest\";\n// @ts-ignore\nimport * as testDep from \"@vitest/test-dep-optimizer-external\"\n\nit(\"passes\", () => {\n  expect(testDep.default).toBeDefined();\n});\n"
  },
  {
    "path": "test/config/fixtures/optimizer/external/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    deps: {\n      optimizer: {\n        ssr: {\n          enabled: true,\n          // need at least one to trigger dep optimization\n          include: [\"@vitest/test-dep-optimizer-optimized\"],\n        },\n      },\n    },\n  },\n  plugins: [\n    {\n      name: 'test-external',\n      transform(_code, id, _options) {\n        if (id.includes('test-dep-optimizer-external')) {\n          this.error('\"@vitest/test-dep-optimizer-external\" is expected to be externalized');\n        }\n      },\n    }\n  ]\n});\n"
  },
  {
    "path": "test/config/fixtures/pool/a.test.ts",
    "content": "import { test } from \"vitest\"\n\ntest(\"a\", () => { })\n"
  },
  {
    "path": "test/config/fixtures/pool/b.test.ts",
    "content": "import { test } from \"vitest\"\n\ntest(\"b\", () => { })\n"
  },
  {
    "path": "test/config/fixtures/pool/c.test.ts",
    "content": "import { test } from \"vitest\"\n\ntest(\"c\", () => { })\n"
  },
  {
    "path": "test/config/fixtures/pool/print-config.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('print config', () => {\n  // @ts-expect-error -- internal\n  console.log(JSON.stringify(globalThis.__vitest_worker__.config, null, 2))\n})\n"
  },
  {
    "path": "test/config/fixtures/pool/print-testfiles.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('print config', () => {\n  // @ts-expect-error -- internal\n  console.log(JSON.stringify(globalThis.__vitest_worker__.ctx.files.map(file => file.filepath)))\n})\n"
  },
  {
    "path": "test/config/fixtures/pool/write-to-stdout-and-stderr.test.ts",
    "content": "import { test } from 'vitest'\nimport EventEmitter from 'node:events'\n\ntest('write to streams', () => {\n  process.stdout.write('Worker writing to stdout')\n  process.stderr.write('Worker writing to stderr')\n\n  triggerNodeWarning()\n})\n\nfunction triggerNodeWarning() {\n  const emitter = new TestFixturesCustomEmitter()\n  emitter.setMaxListeners(2)\n  emitter.addListener('message', () => {})\n  emitter.addListener('message', () => {})\n  emitter.addListener('message', () => {})\n}\n\nclass TestFixturesCustomEmitter extends EventEmitter {}"
  },
  {
    "path": "test/config/fixtures/public-config/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    name: 'root config'\n  }\n})"
  },
  {
    "path": "test/config/fixtures/public-config/vitest.custom.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    name: 'custom config'\n  }\n})"
  },
  {
    "path": "test/config/fixtures/retry/retry.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nlet number = 0\ntest('should passed', () => {\n  expect(number++).toBe(3)\n})\n\ntest('retry but still failed', () => {\n  expect(number++).toBe(4)\n})\n"
  },
  {
    "path": "test/config/fixtures/retry/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    retry: 3,\n  },\n})\n"
  },
  {
    "path": "test/config/fixtures/run-mode/example.test.ts",
    "content": "import { test } from \"vitest\";\n\ntest(\"example\", () => {})\n"
  },
  {
    "path": "test/config/fixtures/run-mode/vitest.config.ts",
    "content": "export default {}\n"
  },
  {
    "path": "test/config/fixtures/sequence-concurrent/sequence-concurrent-false-concurrent.test.ts",
    "content": "import { describe, expect, test, vi } from 'vitest'\n\nconst delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout))\n\nlet count = 0\n\ndescribe.concurrent('concurrent suite', () => {\n  test('first test completes last', async ({ task }) => {\n    await delay(40)\n    expect(task.concurrent).toBeTruthy()\n    expect(++count).toBe(4)\n  })\n\n  test('second test completes third', async ({ task }) => {\n    await delay(30)\n    expect(task.concurrent).toBeTruthy()\n    expect(++count).toBe(3)\n  })\n})\n\ntest.concurrent('third test completes second', async ({ task }) => {\n  await delay(20)\n  expect(task.concurrent).toBeTruthy()\n  expect(++count).toBe(2)\n})\n\ntest.concurrent('last test completes first', async ({ task }) => {\n  await delay(10)\n  expect(task.concurrent).toBeTruthy()\n  expect(++count).toBe(1)\n})\n"
  },
  {
    "path": "test/config/fixtures/sequence-concurrent/sequence-concurrent-false-sequential.test.ts",
    "content": "import { describe, expect, test, vi } from 'vitest'\n\nconst delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout))\n\nlet count = 0\n\ndescribe('sequential suite', () => {\n  test('first test completes first', async ({ task }) => {\n    await delay(40)\n    expect(task.concurrent).toBeFalsy()\n    expect(++count).toBe(1)\n  })\n\n  test('second test completes second', async ({ task }) => {\n    await delay(30)\n    expect(task.concurrent).toBeFalsy()\n    expect(++count).toBe(2)\n  })\n})\n\ntest('third test completes third', async ({ task }) => {\n  await delay(20)\n  expect(task.concurrent).toBeFalsy()\n  expect(++count).toBe(3)\n})\n\ntest('last test completes last', async ({ task }) => {\n  await delay(10)\n  expect(task.concurrent).toBeFalsy()\n  expect(++count).toBe(4)\n})\n"
  },
  {
    "path": "test/config/fixtures/sequence-concurrent/sequence-concurrent-true-concurrent.test.ts",
    "content": "import { describe, expect, test, vi } from 'vitest'\n\nconst delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout))\n\nlet count = 0\n\ndescribe('concurrent suite', () => {\n  test('first test completes last', async ({ task }) => {\n    await delay(40)\n    expect(task.concurrent).toBeTruthy()\n    expect(++count).toBe(4)\n  })\n\n  test('second test completes third', async ({ task }) => {\n    await delay(30)\n    expect(task.concurrent).toBeTruthy()\n    expect(++count).toBe(3)\n  })\n})\n\ntest('third test completes second', async ({ task }) => {\n  await delay(20)\n  expect(task.concurrent).toBeTruthy()\n  expect(++count).toBe(2)\n})\n\ntest('last test completes first', async ({ task }) => {\n  await delay(10)\n  expect(task.concurrent).toBeTruthy()\n  expect(++count).toBe(1)\n})\n"
  },
  {
    "path": "test/config/fixtures/sequence-concurrent/sequence-concurrent-true-sequential.test.ts",
    "content": "import { describe, expect, test, vi } from 'vitest'\n\nconst delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout))\n\nlet count = 0\n\ndescribe.sequential('sequential suite', () => {\n  test('first test completes first', async ({ task }) => {\n    await delay(40)\n    expect(task.concurrent).toBeFalsy()\n    expect(++count).toBe(1)\n  })\n\n  test('second test completes second', async ({ task }) => {\n    await delay(30)\n    expect(task.concurrent).toBeFalsy()\n    expect(++count).toBe(2)\n  })\n})\n\ntest.sequential('third test completes third', async ({ task }) => {\n  await delay(20)\n  expect(task.concurrent).toBeFalsy()\n  expect(++count).toBe(3)\n})\n\ntest.sequential('last test completes last', async ({ task }) => {\n  await delay(10)\n  expect(task.concurrent).toBeFalsy()\n  expect(++count).toBe(4)\n})\n"
  },
  {
    "path": "test/config/fixtures/shard/test/1.test.js",
    "content": "import { expect, test } from 'vitest'\n\ntest('1', () => expect(1).toBe(1))\n"
  },
  {
    "path": "test/config/fixtures/shard/test/2.test.js",
    "content": "import { expect, test } from 'vitest'\n\ntest('2', () => expect(1).toBe(1))\n"
  },
  {
    "path": "test/config/fixtures/shard/test/3.test.js",
    "content": "import { expect, test } from 'vitest'\n\ntest('3', () => expect(1).toBe(1))\n"
  },
  {
    "path": "test/config/fixtures/shard/vitest.config.js",
    "content": "export default {}"
  },
  {
    "path": "test/config/fixtures/shard-4-files/test/1.test.js",
    "content": "import { test, expect } from 'vitest'\n\ntest('test file 1', () => {\n  expect(1).toBe(1)\n})"
  },
  {
    "path": "test/config/fixtures/shard-4-files/test/2.test.js",
    "content": "import { test, expect } from 'vitest'\n\ntest('test file 2', () => {\n  expect(2).toBe(2)\n})"
  },
  {
    "path": "test/config/fixtures/shard-4-files/test/3.test.js",
    "content": "import { test, expect } from 'vitest'\n\ntest('test file 3', () => {\n  expect(3).toBe(3)\n})"
  },
  {
    "path": "test/config/fixtures/shard-4-files/test/4.test.js",
    "content": "import { test, expect } from 'vitest'\n\ntest('test file 4', () => {\n  expect(4).toBe(4)\n})"
  },
  {
    "path": "test/config/fixtures/shard-4-files/vitest.config.js",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: ['test/**/*.test.js'],\n  },\n})"
  },
  {
    "path": "test/config/fixtures/snapshot-path-context/__snapshots__/project1/basic.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`basic 1`] = `\"hello\"`;\n"
  },
  {
    "path": "test/config/fixtures/snapshot-path-context/__snapshots__/project2/basic.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`basic 1`] = `\"hello\"`;\n"
  },
  {
    "path": "test/config/fixtures/snapshot-path-context/basic.test.ts",
    "content": "import { test, expect } from 'vitest'\n\ntest('basic', () => {\n  expect('hello').toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/config/fixtures/snapshot-path-context/vitest.config.ts",
    "content": "import { join, dirname, basename } from 'node:path';\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    resolveSnapshotPath(path, extension, context) {\n      return join(\n        dirname(path),\n        '__snapshots__',\n        context.config.name ?? 'na',\n        basename(path) + extension\n      );\n    },\n    projects: [\n      {\n        extends: './vitest.config.ts',\n        test: {\n          name: 'project1',\n          root: import.meta.dirname,\n        }\n      },\n      {\n        extends: './vitest.config.ts',\n        test: {\n          name: 'project2',\n          root: import.meta.dirname,\n        }\n      }\n    ],\n  },\n});\n"
  },
  {
    "path": "test/config/fixtures/test/example.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('it works', () => {\n  expect(true).toBe(true)\n})\n"
  },
  {
    "path": "test/config/fixtures/test/fake-timers.test.ts",
    "content": "import { test, vi } from 'vitest'\n\ntest('uses fake timers', () => {\n  vi.useFakeTimers()\n\n  vi.useRealTimers()\n})\n"
  },
  {
    "path": "test/config/fixtures/test/vitest.config.js",
    "content": "export default {\n  test: {\n    coverage: {\n      reporter: [],\n    },\n  }\n}"
  },
  {
    "path": "test/config/fixtures/vitest.config.js",
    "content": "export default {\n  test: {}\n}"
  },
  {
    "path": "test/config/fixtures/workers-option/example.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('it works', () => {\n  expect(true).toBe(true)\n})\n"
  },
  {
    "path": "test/config/fixtures/workers-option/vitest.config.js",
    "content": "export default {}"
  },
  {
    "path": "test/config/fixtures/workspace-flags/projects/cli-config.test.ts",
    "content": "import { it, expect } from 'vitest';\n\nit('math', () => {\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/config/fixtures/workspace-flags/projects/vitest.config.js",
    "content": "export default {}"
  },
  {
    "path": "test/config/fixtures/workspace-flags/vitest.config.js",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: ['projects'],\n  },\n})"
  },
  {
    "path": "test/config/package.json",
    "content": "{\n  \"name\": \"@vitest/test-config\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"vitest --typecheck.enabled\"\n  },\n  \"devDependencies\": {\n    \"@test/test-dep-config\": \"link:./deps/test-dep-config\",\n    \"@vitejs/test-dep-virtual\": \"file:./deps/test-dep-virtual\",\n    \"@vitest/browser-playwright\": \"workspace:*\",\n    \"@vitest/browser-preview\": \"workspace:*\",\n    \"@vitest/browser-webdriverio\": \"workspace:*\",\n    \"@vitest/test-dep-optimizer-external\": \"file:./deps/optimizer/external\",\n    \"@vitest/test-dep-optimizer-optimized\": \"file:./deps/optimizer/optimized\",\n    \"inline-dep\": \"file:./deps/vite-ssr-resolve/inline-dep\",\n    \"other-dep\": \"file:./deps/vite-ssr-resolve/other-dep\",\n    \"ssr-no-external-dep\": \"file:./deps/vite-ssr-resolve/ssr-no-external-dep\",\n    \"test-dep-conditions\": \"file:./deps/test-dep-conditions\",\n    \"tinyexec\": \"^1.0.2\",\n    \"vite\": \"latest\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/config/test/__snapshots__/diff.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`inline diff options: { expand: true } 1`] = `\n[\n  \"- Expected\n+ Received\n\n  [\n-   1000,\n+   0,\n    1,\n    2,\n    3,\n    4,\n    5,\n    6,\n    7,\n    8,\n    9,\n    10,\n    11,\n    12,\n    13,\n    14,\n-   2000,\n+   15,\n    16,\n    17,\n    18,\n    19,\n    20,\n    21,\n    22,\n    23,\n    24,\n    25,\n    26,\n    27,\n    28,\n-   3000,\n+   29,\n  ]\",\n  \"- Expected\n+ Received\n\n  {\n    \"arr\": [\n      1,\n-     3,\n+     2,\n    ],\n    \"obj\": {\n-     \"k\": \"bar\",\n+     \"k\": \"foo\",\n    },\n  }\",\n]\n`;\n\nexports[`inline diff options: { printBasicPrototype: true } 1`] = `\n[\n  \"- Expected\n+ Received\n\n@@ -1,7 +1,7 @@\n  Array [\n-   1000,\n+   0,\n    1,\n    2,\n    3,\n    4,\n    5,\n@@ -12,11 +12,11 @@\n    10,\n    11,\n    12,\n    13,\n    14,\n-   2000,\n+   15,\n    16,\n    17,\n    18,\n    19,\n    20,\n@@ -26,7 +26,7 @@\n    24,\n    25,\n    26,\n    27,\n    28,\n-   3000,\n+   29,\n  ]\",\n  \"- Expected\n+ Received\n\n  Object {\n    \"arr\": Array [\n      1,\n-     3,\n+     2,\n    ],\n    \"obj\": Object {\n-     \"k\": \"bar\",\n+     \"k\": \"foo\",\n    },\n  }\",\n]\n`;\n"
  },
  {
    "path": "test/config/test/__snapshots__/hook-timeout.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`timeout error with stack trace 1`] = `\n\"\n⎯⎯⎯⎯⎯⎯ Failed Suites 3 ⎯⎯⎯⎯⎯⎯⎯\n\n FAIL  basic.test.ts > beforeAll\nError: Hook timed out in 10ms.\nIf this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\n ❯ basic.test.ts:4:3\n      2|\n      3| describe('beforeAll', () => {\n      4|   beforeAll(() => new Promise(() => {}), 10)\n       |   ^\n      5|\n      6|   it('ok', () => {})\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/10]⎯\n\n FAIL  basic.test.ts > afterAll\nError: Hook timed out in 30ms.\nIf this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\n ❯ basic.test.ts:16:3\n     14|\n     15| describe('afterAll', () => {\n     16|   afterAll(() => new Promise(() => {}), 30)\n       |   ^\n     17|\n     18|   it('ok', () => {})\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/10]⎯\n\n FAIL  basic.test.ts > cleanup-beforeAll\nError: Hook timed out in 50ms.\nIf this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\n ❯ basic.test.ts:28:3\n     26|\n     27| describe('cleanup-beforeAll', () => {\n     28|   beforeAll(() => () => new Promise(() => {}), 50)\n       |   ^\n     29|\n     30|   it('ok', () => {})\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/10]⎯\n\n\n⎯⎯⎯⎯⎯⎯⎯ Failed Tests 6 ⎯⎯⎯⎯⎯⎯⎯\n\n FAIL  basic.test.ts > beforeEach > ok\nError: Hook timed out in 20ms.\nIf this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\n ❯ basic.test.ts:10:3\n      8|\n      9| describe('beforeEach', () => {\n     10|   beforeEach(() => new Promise(() => {}), 20)\n       |   ^\n     11|\n     12|   it('ok', () => {})\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/10]⎯\n\n FAIL  basic.test.ts > afterEach > ok\nError: Hook timed out in 40ms.\nIf this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\n ❯ basic.test.ts:22:3\n     20|\n     21| describe('afterEach', () => {\n     22|   afterEach(() => new Promise(() => {}), 40)\n       |   ^\n     23|\n     24|   it('ok', () => {})\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/10]⎯\n\n FAIL  basic.test.ts > cleanup-beforeEach > ok\nError: Hook timed out in 60ms.\nIf this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\n ❯ basic.test.ts:34:3\n     32|\n     33| describe('cleanup-beforeEach', () => {\n     34|   beforeEach(() => () => new Promise(() => {}), 60)\n       |   ^\n     35|\n     36|   it('ok', () => {})\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/10]⎯\n\n FAIL  basic.test.ts > onFailed > fail\nError: fail\n ❯ basic.test.ts:42:11\n     40|   it('fail', (ctx) => {\n     41|     ctx.onTestFailed(() => new Promise(() => {}), 70)\n     42|     throw new Error('fail')\n       |           ^\n     43|   })\n     44| })\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/10]⎯\n\n FAIL  basic.test.ts > onFailed > fail\nError: Hook timed out in 70ms.\nIf this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\n ❯ basic.test.ts:41:9\n     39| describe('onFailed', () => {\n     40|   it('fail', (ctx) => {\n     41|     ctx.onTestFailed(() => new Promise(() => {}), 70)\n       |         ^\n     42|     throw new Error('fail')\n     43|   })\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/10]⎯\n\n FAIL  basic.test.ts > onFinished > ok\nError: Hook timed out in 80ms.\nIf this is a long-running hook, pass a timeout value as the last argument or configure it globally with \"hookTimeout\".\n ❯ basic.test.ts:48:9\n     46| describe('onFinished', () => {\n     47|   it('ok', (ctx) => {\n     48|     ctx.onTestFinished(() => new Promise(() => {}), 80)\n       |         ^\n     49|   })\n     50| })\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/10]⎯\n\n FAIL  basic.test.ts > test timeout\nError: Test timed out in 123ms.\nIf this is a long-running test, pass a timeout value as the last argument or configure it globally with \"testTimeout\".\n ❯ basic.test.ts:52:1\n     50| })\n     51|\n     52| it(\"test timeout\", () => new Promise(() => {}), 123)\n       | ^\n     53|\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[10/10]⎯\n\n\"\n`;\n"
  },
  {
    "path": "test/config/test/browser-persistent-context.test.ts",
    "content": "import { existsSync, rmSync } from 'node:fs'\nimport { resolve } from 'pathe'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('persistent context works', async () => {\n  // clean user data dir\n  const root = resolve(import.meta.dirname, '../fixtures/browser-persistent-context')\n  const userDataDir = resolve(root, 'node_modules/.cache/test-user-data')\n  rmSync(userDataDir, { recursive: true, force: true })\n\n  // first run\n  process.env.TEST_EXPECTED_VALUE = '0'\n  const result1 = await runVitest({ root })\n  expect(result1.errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"expectedValue = 0\": \"passed\",\n      },\n    }\n  `)\n  // check user data\n  expect(existsSync(userDataDir)).toBe(true)\n\n  // 2nd run\n  // localStorage is incremented during 1st run and\n  // 2nd run should pick that up from persistent context\n  process.env.TEST_EXPECTED_VALUE = '1'\n  const result2 = await runVitest({ root })\n  expect(result2.errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"expectedValue = 1\": \"passed\",\n      },\n    }\n  `)\n  // check user data\n  expect(existsSync(userDataDir)).toBe(true)\n})\n"
  },
  {
    "path": "test/config/test/cache.test.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { resolve } from 'pathe'\nimport { describe, expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nconst root = resolve(import.meta.dirname, '../fixtures/cache')\n\ntest('default', async () => {\n  const { ctx, stdout, stderr } = await runVitest({\n    root,\n    include: ['*.test.ts'],\n    cache: undefined,\n  })\n\n  expect(stdout).toContain('✓ basic.test.ts >')\n  expect(stderr).toBe('')\n\n  const cachePath = ctx!.cache.results.getCachePath()\n  const path = resolve(root, 'node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json')\n  expect(cachePath).toMatch(path)\n})\n\ntest('use cache.dir', async () => {\n  const { ctx, stdout, stderr } = await runVitest(\n    {\n      root,\n      include: ['*.test.ts'],\n      cache: {\n        dir: 'node_modules/.vitest-custom',\n      },\n    },\n  )\n\n  expect(stdout).toContain('✓ basic.test.ts >')\n  expect(stderr).toContain('\"cache.dir\" is deprecated')\n\n  const cachePath = ctx!.cache.results.getCachePath()\n  const path = resolve(root, 'node_modules/.vitest-custom/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json')\n  expect(cachePath).toMatch(path)\n})\n\ntest('use cacheDir', async () => {\n  const { ctx, stdout, stderr } = await runVitest(\n    {\n      root,\n      include: ['*.test.ts'],\n      cache: undefined,\n      $viteConfig: {\n        cacheDir: 'node_modules/.vite-custom',\n      },\n    },\n  )\n\n  expect(stdout).toContain('✓ basic.test.ts >')\n  expect(stderr).toBe('')\n\n  const cachePath = ctx!.cache.results.getCachePath()\n  const path = resolve(root, 'node_modules/.vite-custom/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json')\n  expect(cachePath).toMatch(path)\n})\n\ntest('preserves previous test results', async () => {\n  const firstRun = await runVitest({\n    root,\n    include: ['basic.test.ts'],\n    cache: undefined,\n  })\n\n  expect(firstRun.stdout).toContain('✓ basic.test.ts >')\n  expect(firstRun.stderr).toBe('')\n\n  const cachePath = firstRun.ctx!.cache.results.getCachePath()\n  const firstRunCacheContent = readFileSync(cachePath!, 'utf-8')\n  expect(firstRunCacheContent).toContain('basic.test.ts')\n\n  const secondRun = await runVitest({\n    root,\n    include: ['second.test.ts'],\n    cache: undefined,\n  })\n  expect(secondRun.stdout).toContain('✓ second.test.ts >')\n  expect(secondRun.stderr).toBe('')\n\n  const secondRunCacheContent = readFileSync(cachePath!, 'utf-8')\n  expect(secondRunCacheContent).toContain('basic.test.ts')\n  expect(secondRunCacheContent).toContain('second.test.ts')\n})\n\ndescribe('with optimizer enabled', () => {\n  const deps = {\n    optimizer: {\n      web: {\n        enabled: true,\n      },\n    },\n  }\n\n  test('default', async () => {\n    const { ctx, stdout, stderr } = await runVitest({\n      root,\n      include: ['*.test.ts'],\n      deps,\n      cache: undefined,\n    })\n\n    expect(stdout).toContain('✓ basic.test.ts >')\n    expect(stderr).toBe('')\n\n    const cachePath = ctx!.cache.results.getCachePath()\n    const path = resolve(root, 'node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json')\n    expect(cachePath).toBe(path)\n  })\n\n  test('use cache.dir', async () => {\n    const { ctx, stdout, stderr } = await runVitest(\n      {\n        root,\n        include: ['*.test.ts'],\n        deps,\n        cache: {\n          dir: 'node_modules/.vitest-custom',\n        },\n      },\n    )\n\n    expect(stdout).toContain('✓ basic.test.ts >')\n    expect(stderr).toContain('\"cache.dir\" is deprecated')\n\n    const cachePath = ctx!.cache.results.getCachePath()\n    const path = resolve(root, 'node_modules/.vitest-custom/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json')\n    expect(cachePath).toBe(path)\n  })\n\n  test('use cacheDir', async () => {\n    const { ctx, stdout, stderr } = await runVitest(\n      {\n        root,\n        include: ['*.test.ts'],\n        deps,\n        cache: undefined,\n        $viteConfig: {\n          cacheDir: 'node_modules/.vite-custom',\n        },\n      },\n    )\n\n    expect(stdout).toContain('✓ basic.test.ts >')\n    expect(stderr).toBe('')\n\n    const cachePath = ctx!.cache.results.getCachePath()\n    const path = resolve(root, 'node_modules/.vite-custom/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json')\n    expect(cachePath).toBe(path)\n  })\n})\n"
  },
  {
    "path": "test/config/test/chai-config.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ndescribe('truncateThreshold', () => {\n  it('default', async () => {\n    const result = await runVitest({\n      root: 'fixtures/chai-config',\n      reporters: ['tap-flat'],\n    })\n    expect(cleanOutput(result.stdout)).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..9\n      ok 1 - test-each-title.test.ts > '012345678901234567890123456789' (length = 30)\n      ok 2 - test-each-title.test.ts > '0123456789012345678901234567890123456…' (length = 40)\n      ok 3 - test-each-title.test.ts > '0123456789012345678901234567890123456…' (length = 50)\n      ok 4 - test-each-title.test.ts > [ 'one', 'two', 'three' ]\n      ok 5 - test-each-title.test.ts > [ 'one', 'two', 'three', 'four' ]\n      ok 6 - test-each-title.test.ts > [ 'one', 'two', 'three', 'four', …(1) ]\n      ok 7 - test-each-title.test.ts > { one: 1, two: 2, three: 3 }\n      ok 8 - test-each-title.test.ts > { one: 1, two: 2, three: 3, four: 4 }\n      ok 9 - test-each-title.test.ts > { one: 1, two: 2, three: 3, …(2) }\"\n    `)\n    expect(result.exitCode).toBe(0)\n  })\n\n  it('40', async () => {\n    const result = await runVitest({\n      root: 'fixtures/chai-config',\n      reporters: ['tap-flat'],\n      chaiConfig: {\n        truncateThreshold: 40,\n      },\n    })\n    expect(cleanOutput(result.stdout)).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..9\n      ok 1 - test-each-title.test.ts > '012345678901234567890123456789' (length = 30)\n      ok 2 - test-each-title.test.ts > '0123456789012345678901234567890123456…' (length = 40)\n      ok 3 - test-each-title.test.ts > '0123456789012345678901234567890123456…' (length = 50)\n      ok 4 - test-each-title.test.ts > [ 'one', 'two', 'three' ]\n      ok 5 - test-each-title.test.ts > [ 'one', 'two', 'three', 'four' ]\n      ok 6 - test-each-title.test.ts > [ 'one', 'two', 'three', 'four', …(1) ]\n      ok 7 - test-each-title.test.ts > { one: 1, two: 2, three: 3 }\n      ok 8 - test-each-title.test.ts > { one: 1, two: 2, three: 3, four: 4 }\n      ok 9 - test-each-title.test.ts > { one: 1, two: 2, three: 3, …(2) }\"\n    `)\n    expect(result.exitCode).toBe(0)\n  })\n\n  it('0', async () => {\n    const result = await runVitest({\n      root: 'fixtures/chai-config',\n      reporters: ['tap-flat'],\n      chaiConfig: {\n        truncateThreshold: 0,\n      },\n    })\n    expect(cleanOutput(result.stdout)).toMatchInlineSnapshot(`\n      \"TAP version 13\n      1..9\n      ok 1 - test-each-title.test.ts > '012345678901234567890123456789' (length = 30)\n      ok 2 - test-each-title.test.ts > '0123456789012345678901234567890123456789' (length = 40)\n      ok 3 - test-each-title.test.ts > '01234567890123456789012345678901234567890123456789' (length = 50)\n      ok 4 - test-each-title.test.ts > [ 'one', 'two', 'three' ]\n      ok 5 - test-each-title.test.ts > [ 'one', 'two', 'three', 'four' ]\n      ok 6 - test-each-title.test.ts > [ 'one', 'two', 'three', 'four', 'five' ]\n      ok 7 - test-each-title.test.ts > { one: 1, two: 2, three: 3 }\n      ok 8 - test-each-title.test.ts > { one: 1, two: 2, three: 3, four: 4 }\n      ok 9 - test-each-title.test.ts > { one: 1, two: 2, three: 3, four: 4, five: 5 }\"\n    `)\n    expect(result.exitCode).toBe(0)\n  })\n})\n\nfunction cleanOutput(output: string) {\n  // remove non-deterministic output\n  return output.replaceAll(/\\s*# time=.*/g, '').trim()\n}\n"
  },
  {
    "path": "test/config/test/cli-config.test.ts",
    "content": "import { resolve } from 'pathe'\nimport { expect, it, test } from 'vitest'\nimport { createVitest } from 'vitest/node'\n\nimport { runVitest } from '../../test-utils'\n\ntest('can pass down the config as a module', async () => {\n  const vitest = await createVitest('test', {\n    config: '@test/test-dep-config',\n  })\n\n  expect(vitest.vite.config.configFile).toBe(\n    resolve(import.meta.dirname, '../deps/test-dep-config/index.js'),\n  )\n})\n\nit('correctly inherit from the cli', async () => {\n  const { ctx } = await runVitest({\n    $cliOptions: {\n      root: 'fixtures/workspace-flags',\n      logHeapUsage: true,\n      allowOnly: true,\n      sequence: {\n        seed: 123,\n      },\n      testTimeout: 5321,\n      pool: 'forks',\n      globals: true,\n      expandSnapshotDiff: true,\n      retry: 6,\n      testNamePattern: 'math',\n      passWithNoTests: true,\n      bail: 100,\n      experimental: {\n        importDurations: {\n          print: true,\n        },\n      },\n    },\n  })\n  const project = ctx!.projects[0]\n  const config = project.config\n  expect(config).toMatchObject({\n    logHeapUsage: true,\n    allowOnly: true,\n    sequence: expect.objectContaining({\n      seed: 123,\n    }),\n    testTimeout: 5321,\n    pool: 'forks',\n    globals: true,\n    expandSnapshotDiff: true,\n    retry: 6,\n    passWithNoTests: true,\n    bail: 100,\n    experimental: {\n      importDurations: {\n        print: true,\n        limit: 10,\n      },\n    },\n  })\n  expect(config.testNamePattern?.test('math')).toBe(true)\n})\n"
  },
  {
    "path": "test/config/test/conditions-cli.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('correctly imports external dependencies with a development condition', async () => {\n  // dev condition is the default\n  const { stderr } = await runVitest({\n    root: 'fixtures/conditions-test',\n    server: {\n      deps: {\n        external: [/conditions-pkg/],\n      },\n    },\n    $viteConfig: {\n      define: {\n        TEST_CONDITION: '\"development\"',\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n})\n\ntest('correctly imports external dependencies with a production condition', async () => {\n  // this is the only check in Vite for \"isProduction\" value\n  process.env.NODE_ENV = 'production'\n\n  const { stderr } = await runVitest({\n    root: 'fixtures/conditions-test',\n    server: {\n      deps: {\n        external: [/conditions-pkg/],\n      },\n    },\n    $viteConfig: {\n      define: {\n        TEST_CONDITION: '\"production\"',\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n})\n\ntest('correctly imports external dependencies with a custom condition', async () => {\n  delete process.env.NODE_ENV\n\n  const { stderr } = await runVitest({\n    root: 'fixtures/conditions-test',\n    server: {\n      deps: {\n        external: [/conditions-pkg/],\n      },\n    },\n    $viteConfig: {\n      resolve: {\n        conditions: ['custom'],\n      },\n      ssr: {\n        resolve: {\n          conditions: ['custom'],\n        },\n      },\n      define: {\n        TEST_CONDITION: '\"custom\"',\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n})\n\ntest('conditions (external)', async () => {\n  const { stderr } = await runVitest({\n    root: 'fixtures/conditions',\n  })\n\n  expect(stderr).toBe('')\n})\n\ntest('conditions (inline direct)', async () => {\n  const { stderr } = await runVitest({\n    root: 'fixtures/conditions',\n    server: {\n      deps: {\n        inline: ['test-dep-conditions'],\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n})\n\ntest('conditions (inline indirect)', async () => {\n  const { stderr } = await runVitest({\n    root: 'fixtures/conditions',\n    server: {\n      deps: {\n        inline: ['test-dep-conditions', 'test-dep-conditions-indirect'],\n      },\n    },\n  })\n\n  expect(stderr).toBe('')\n})\n\ntest('project resolve.conditions', async () => {\n  const { stderr, errorTree } = await runVitest({\n    root: 'fixtures/conditions-projects',\n  })\n  expect(stderr).toBe('')\n  expect(errorTree({ project: true })).toMatchInlineSnapshot(`\n    {\n      \"project-a\": {\n        \"basic.test.js\": {\n          \"conditions\": \"passed\",\n        },\n      },\n      \"project-b\": {\n        \"basic.test.js\": {\n          \"conditions\": \"passed\",\n        },\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/config/test/config-types.test-d.ts",
    "content": "import type { TestUserConfig } from 'vitest/config'\nimport { assertType, describe, expectTypeOf, test } from 'vitest'\nimport { defineConfig, defineProject, mergeConfig } from 'vitest/config'\n\nconst expectMainTestConfig = expectTypeOf(defineConfig).parameter(0).resolves.toHaveProperty('test').exclude<undefined>()\nconst expectProjectTestConfig = expectTypeOf(defineProject).parameter(0).resolves.toHaveProperty('test').exclude<undefined>()\n\ndescribe('define project helper', () => {\n  test('cannot define non-project fields on a project config', () => {\n    expectProjectTestConfig.toHaveProperty('name')\n    expectMainTestConfig.toHaveProperty('name')\n\n    expectProjectTestConfig.not.toHaveProperty('coverage')\n    expectMainTestConfig.toHaveProperty('coverage')\n\n    expectProjectTestConfig.not.toHaveProperty('reporters')\n    expectMainTestConfig.toHaveProperty('reporters')\n  })\n\n  test('allows expected project fields on a project config', () => {\n    expectProjectTestConfig.toHaveProperty('pool')\n  })\n})\n\ndescribe('merge config helper', () => {\n  test('types are not conflicting', () => {\n    expectTypeOf(mergeConfig(\n      defineConfig({}),\n      defineProject({ test: { name: 'test' } }),\n    )).toExtend<Record<string, unknown>>()\n  })\n})\n\ndescribe('define workspace helper', () => {\n  type DefineWorkspaceParameter = TestUserConfig['projects']\n\n  test('allows string', () => {\n    assertType<DefineWorkspaceParameter>(['./path/to/workspace'])\n  })\n\n  test('allows config object', () => {\n    assertType<DefineWorkspaceParameter>([{\n      test: {\n        name: 'Workspace Project #1',\n        include: ['string'],\n\n        // @ts-expect-error -- Not allowed here\n        coverage: {},\n      },\n    }])\n  })\n\n  test('allows mixing strings and config objects', () => {\n    assertType<DefineWorkspaceParameter>([\n      './path/to/project',\n      {\n        test: {\n          name: 'Workspace Project #1',\n          include: ['string'],\n\n          // @ts-expect-error -- Not allowed here\n          coverage: {},\n        },\n      },\n      './path/to/another/project',\n      {\n        extends: 'workspace custom field',\n        test: {\n          name: 'Workspace Project #2',\n          include: ['string'],\n\n          // @ts-expect-error -- Not allowed here\n          coverage: {},\n        },\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "test/config/test/console-color.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('with color', async () => {\n  const { stdout } = await runVitest({\n    root: 'fixtures/console-color',\n    env: {\n      CI: '1',\n      FORCE_COLOR: '1',\n      NO_COLOR: undefined,\n      GITHUB_ACTIONS: undefined,\n    },\n  }, [], { preserveAnsi: true })\n\n  expect(stdout).toContain('\\x1B[33mtrue\\x1B[39m\\n')\n})\n\ntest('without color', async () => {\n  const { stdout } = await runVitest({\n    root: 'fixtures/console-color',\n    env: {\n      CI: '1',\n      FORCE_COLOR: undefined,\n      NO_COLOR: '1',\n      GITHUB_ACTIONS: undefined,\n    },\n  }, [], { preserveAnsi: true })\n\n  expect(stdout).toContain('true\\n')\n  expect(stdout).not.toContain('\\x1B[33mtrue\\x1B[39m\\n')\n})\n\ntest.skipIf(process.platform === 'win32')('without color, forks pool in non-TTY parent', async () => {\n  const { stdout } = await runVitest({\n    root: 'fixtures/console-color',\n    env: {\n      CI: undefined,\n      FORCE_COLOR: undefined,\n      NO_COLOR: undefined,\n      GITHUB_ACTIONS: undefined,\n\n      // Overrides current process's value, since we are running Vitest in Vitest here\n      // By default, tinyrainbow doesn't check isatty since version 3, but\n      // FORCE_TTY=false will make the check `false`\n      FORCE_TTY: 'false',\n    },\n  }, [], { preserveAnsi: true })\n\n  expect(stdout).toContain('true\\n')\n  expect(stdout).not.toContain('\\x1B[33mtrue\\x1B[39m\\n')\n})\n\ntest('with color, forks pool in TTY parent', async () => {\n  const { stdout } = await runVitest({\n    root: 'fixtures/console-color',\n    env: {\n      CI: undefined,\n      FORCE_COLOR: undefined,\n      NO_COLOR: undefined,\n      GITHUB_ACTIONS: undefined,\n    },\n  }, [], { preserveAnsi: true })\n\n  expect(stdout).toContain('\\x1B[33mtrue\\x1B[39m\\n')\n})\n"
  },
  {
    "path": "test/config/test/console.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('default intercept', async () => {\n  const { stderr } = await runVitest({\n    root: './fixtures/console',\n  })\n  expect(stderr).toBe('stderr | basic.test.ts > basic\\n__test_console__\\n\\n')\n})\n\ntest.each(['threads', 'vmThreads'] as const)(`disable intercept pool=%s`, async (pool) => {\n  const { stderr } = await runVitest({\n    root: './fixtures/console',\n    disableConsoleIntercept: true,\n    pool,\n  })\n\n  expect(stderr).toBe('__test_console__\\n')\n})\n\ntest('group synchronous console logs', async () => {\n  const { stdout } = await runVitest({\n    root: './fixtures/console-batch',\n  })\n  const logs = stdout\n    .split('\\n')\n    .filter(row => row.length === 0 || row.startsWith('stdout | ') || row.startsWith('__TEST__'))\n    .join('\\n')\n    .trim()\n  expect(logs).toMatchInlineSnapshot(`\n    \"stdout | basic.test.ts\n    __TEST__ [beforeAll 1]\n\n    stdout | basic.test.ts\n    __TEST__ [beforeAll 2]\n\n    stdout | basic.test.ts > test\n    __TEST__ [beforeEach 1]\n\n    stdout | basic.test.ts > test\n    __TEST__ [beforeEach 2]\n\n    stdout | basic.test.ts > test\n    __TEST__ [test 1]\n    __TEST__ [test 2]\n\n    stdout | basic.test.ts > test\n    __TEST__ [test 3]\n    __TEST__ [test 4]\n\n    stdout | basic.test.ts > test\n    __TEST__ [afterEach 2]\n\n    stdout | basic.test.ts > test\n    __TEST__ [afterEach 1]\n\n    stdout | basic.test.ts\n    __TEST__ [afterAll 2]\n\n    stdout | basic.test.ts\n    __TEST__ [afterAll 1]\"\n  `)\n})\n"
  },
  {
    "path": "test/config/test/css-configs.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nit.each([\n  ['test/default-css', {}],\n  ['test/process-css', { include: [/App\\.css/] }],\n  [['test/process-module', 'test/process-inline'], { include: [/App\\.module\\.css/] }],\n  ['test/scope-module', { include: [/App\\.module\\.css/], modules: { classNameStrategy: 'scoped' as const } }],\n  ['test/non-scope-module', { include: [/App\\.module\\.css/], modules: { classNameStrategy: 'non-scoped' as const } }],\n])('testing %s', async (name, config) => {\n  const names = Array.isArray(name) ? name : [name]\n  const { stderr } = await runVitest({\n    config: false,\n    root: './fixtures/css',\n    css: config,\n    update: true,\n    environment: 'jsdom',\n  }, names)\n\n  expect(stderr).toBe('')\n})\n"
  },
  {
    "path": "test/config/test/diff.test.ts",
    "content": "import { stripVTControlCharacters } from 'node:util'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest.for([\n  [{ expand: true }],\n  [{ printBasicPrototype: true }],\n])(`inline diff options: %o`, async ([options]) => {\n  const { ctx } = await runVitest({\n    root: './fixtures/diff',\n    diff: options,\n  })\n  const errors = ctx!.state.getFiles().flatMap(f =>\n    f.tasks.flatMap(t => t.result?.errors ?? []),\n  )\n  expect(\n    errors.map(e => e.diff && stripVTControlCharacters(e.diff)),\n  ).matchSnapshot()\n})\n"
  },
  {
    "path": "test/config/test/exclude.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { runVitest } from '../../test-utils'\n\ntest('should still test math.test.ts', async () => {\n  const { stderr, stdout } = await runVitest({\n    config: 'fixtures/exclude/vitest.exclude.config.ts',\n    exclude: ['fixtures/exclude/string.test.ts'],\n  })\n\n  expect(stdout).toContain(`✓ fixtures/exclude/math.test.ts`)\n  expect(stdout).not.toContain(`string.test.ts`)\n  expect(stderr).toBe('')\n})\n"
  },
  {
    "path": "test/config/test/exec-args.test.ts",
    "content": "import { x } from 'tinyexec'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nconst [nodeMajor, nodeMinor] = process.version.slice(1).split('.').map(Number)\n\ntest.each([\n  { pool: 'forks', execArgv: ['--hash-seed=1', '--random-seed=1', '--no-opt'] },\n  { pool: 'threads', execArgv: ['--inspect-brk'] },\n  { pool: 'vmThreads', execArgv: ['--inspect-brk'] },\n] as const)('should pass execArgv to { pool: $pool } ', async ({ pool, execArgv }) => {\n  const root = './fixtures/exec-args-fixtures'\n  const fileToTest = `${pool}.test.ts`\n\n  // TODO: node.js has a bug that makes --inspect-brk not work on worker threads\n  if (pool !== 'forks') {\n    if ((nodeMajor === 20 && nodeMinor > 14) || (nodeMajor > 20)) {\n      return\n    }\n  }\n\n  const vitest = await runVitest({\n    root,\n    include: [fileToTest],\n    pool,\n    execArgv: [...execArgv],\n  })\n\n  expect(vitest.stdout).toContain(`✓ ${fileToTest}`)\n  expect(vitest.stderr).toBe('')\n})\n\ntest('should not pass execArgv to workers when not specified in the config', async () => {\n  const { stdout, stderr } = await x('node', [\n    '--title',\n    'this-works-only-on-main-thread',\n    '../../../../node_modules/vitest/vitest.mjs',\n    '--run',\n  ], {\n    nodeOptions: {\n      cwd: `${process.cwd()}/fixtures/no-exec-args-fixtures`,\n      env: {\n        VITEST_MODULE_DIRECTORIES: '/node_modules/,/packages/',\n        NO_COLOR: '1',\n      },\n    },\n    throwOnError: false,\n  })\n\n  expect(stderr).not.toContain('Error: Initiated Worker with invalid execArgv flags: --title')\n  expect(stderr).not.toContain('ERR_WORKER_INVALID_EXEC_ARGV')\n  expect(stdout).toContain('✓ no-exec-argv.test.ts')\n})\n\ntest('should let allowed args pass to workers', async () => {\n  const { stdout, stderr } = await x('node', [\n    '--heap-prof',\n    '--diagnostic-dir=/tmp/vitest-diagnostics',\n    '--heap-prof-name=heap.prof',\n    '../../../../node_modules/vitest/vitest.mjs',\n    '--run',\n  ], {\n    nodeOptions: {\n      cwd: `${process.cwd()}/fixtures/allowed-exec-args-fixtures`,\n      env: {\n        VITEST_MODULE_DIRECTORIES: '/node_modules/,/packages/',\n        NO_COLOR: '1',\n      },\n    },\n    throwOnError: false,\n  })\n\n  expect(stderr).toBe('')\n  expect(stdout).toContain('✓ allowed-exec-argv.test.ts')\n})\n"
  },
  {
    "path": "test/config/test/external.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nit('can inline fully dynamic import', async () => {\n  const { errorTree } = await runVitest({\n    root: 'fixtures/external/dynamic',\n  })\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"basic\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/config/test/failures.test.ts",
    "content": "import type { RunVitestConfig, VitestRunnerCLIOptions } from '../../test-utils'\nimport { playwright } from '@vitest/browser-playwright'\nimport { preview } from '@vitest/browser-preview'\nimport { webdriverio } from '@vitest/browser-webdriverio'\nimport { normalize, resolve } from 'pathe'\nimport { beforeEach, expect, test } from 'vitest'\nimport { version } from 'vitest/package.json'\nimport * as testUtils from '../../test-utils'\n\nconst providers = [\n  playwright(),\n  webdriverio(),\n  preview(),\n] as const\nconst names = ['edge', 'chromium', 'webkit', 'chrome', 'firefox', 'safari'] as const\nconst browsers = providers.map(provider => names.map(name => ({ name, provider }))).flat()\n\nfunction runVitest(config: RunVitestConfig, runnerOptions?: VitestRunnerCLIOptions) {\n  return testUtils.runVitest({\n    root: './fixtures/test',\n    include: ['example.test.ts'],\n    ...config,\n  }, [], runnerOptions)\n}\n\nfunction runVitestCli(...cliArgs: string[]) {\n  return testUtils.runVitestCli('run', 'fixtures/test/', ...cliArgs)\n}\n\nbeforeEach((ctx) => {\n  const errors: Parameters<typeof console.error>[] = []\n  const original = console.error\n  console.error = (...args) => errors.push(args)\n\n  ctx.onTestFailed(() => {\n    errors.forEach(args => original(...args))\n  })\n\n  return () => {\n    console.error = original\n  }\n})\n\ntest('shard cannot be used with watch mode', async () => {\n  const { stderr } = await runVitest({ watch: true, shard: '1/2' })\n\n  expect(stderr).toMatch('Error: You cannot use --shard option with enabled watch')\n})\n\ntest('shard must be positive number', async () => {\n  const { stderr } = await runVitest({ shard: '-1' })\n\n  expect(stderr).toMatch('Error: --shard <count> must be a positive number')\n})\n\ntest('shard index must be smaller than count', async () => {\n  const { stderr } = await runVitest({ shard: '2/1' })\n\n  expect(stderr).toMatch('Error: --shard <index> must be a positive number less then <count>')\n})\n\ntest('shard count must be smaller than count of test files', async () => {\n  const { stderr } = await runVitest({ root: './fixtures/shard', shard: '1/4', include: ['**/*.test.js'] })\n\n  expect(stderr).toMatch('Error: --shard <count> must be a smaller than count of test files. Resolved 3 test files for --shard=1/4.')\n})\n\ntest('shard count can be smaller than count of test files when passWithNoTests', async () => {\n  const { stderr } = await runVitest({ root: './fixtures/shard', shard: '1/4', passWithNoTests: true, include: ['**/*.test.js'] })\n\n  expect(stderr).toMatch('')\n})\n\ntest('inspect requires changing pool and singleThread/singleFork', async () => {\n  const { stderr } = await runVitest({ inspect: true, maxWorkers: 4 })\n\n  expect(stderr).toMatch('Error: You cannot use --inspect without \"--no-file-parallelism\"')\n})\n\ntest('inspect cannot be used with multi-threading', async () => {\n  const { stderr } = await runVitest({ inspect: true, pool: 'threads', fileParallelism: true, maxWorkers: 4 })\n\n  expect(stderr).toMatch('Error: You cannot use --inspect without \"--no-file-parallelism\"')\n})\n\ntest('inspect in browser mode requires no-file-parallelism', async () => {\n  const { stderr } = await runVitest({ inspect: true, maxWorkers: 4, browser: { enabled: true, instances: [{ browser: 'chromium' }], provider: playwright() } })\n\n  expect(stderr).toMatch('Error: You cannot use --inspect without \"--no-file-parallelism\"')\n})\n\ntest('inspect-brk cannot be used with multi processing', async () => {\n  const { stderr } = await runVitest({ inspect: true, pool: 'forks', fileParallelism: true, maxWorkers: 4 })\n\n  expect(stderr).toMatch('Error: You cannot use --inspect without \"--no-file-parallelism\"')\n})\n\ntest('inspect-brk in browser mode requires no-file-parallelism', async () => {\n  const { stderr } = await runVitest({ inspectBrk: true, maxWorkers: 4, browser: { enabled: true, instances: [{ browser: 'chromium' }], provider: playwright() } })\n\n  expect(stderr).toMatch('Error: You cannot use --inspect-brk without \"--no-file-parallelism\"')\n})\n\ntest('inspect and --inspect-brk cannot be used when not playwright + chromium', async () => {\n  for (const option of ['inspect', 'inspectBrk']) {\n    const cli = `--inspect${option === 'inspectBrk' ? '-brk' : ''}`\n\n    for (const { provider, name } of browsers) {\n      if (provider.name === 'playwright' && name === 'chromium') {\n        continue\n      }\n      if (provider.name === 'webdriverio' && (name === 'chrome' || name === 'edge')) {\n        continue\n      }\n\n      const { stderr } = await runVitest({\n        [option]: true,\n        fileParallelism: false,\n        browser: {\n          enabled: true,\n          provider,\n          instances: [{ browser: name }],\n        },\n      })\n\n      expect(stderr).toMatch(\n        `Error: ${cli} does not work with\n{\n  browser: {\n    provider: ${provider.name}(),\n    instances: [\n      { browser: '${name}' }\n    ],\n  },\n}\n\nUse either:\n{\n  browser: {\n    provider: ${provider.name === 'preview' ? 'playwright' : provider.name}(),\n    instances: [\n      { browser: '${(provider.name === 'preview' || provider.name === 'playwright') ? 'chromium' : 'chrome'}' }\n    ],\n  },\n}\n\n...or disable ${cli}\n`,\n      )\n    }\n  }\n})\n\ntest.each(\n  browsers.filter(({ provider, name }) => {\n    if (provider.name === 'playwright') {\n      return name !== 'chromium'\n    }\n    if (provider.name === 'webdriverio') {\n      return name !== 'chrome' && name !== 'edge'\n    }\n    return true\n  }),\n)('v8 coverage provider throws when $provider.name + $name', async ({ provider, name }) => {\n  const { stderr } = await runVitest({\n    coverage: {\n      enabled: true,\n    },\n    browser: {\n      enabled: true,\n      provider,\n      instances: [{ browser: name }],\n    },\n  })\n\n  expect(stderr).toMatch(\n    `Error: @vitest/coverage-v8 does not work with\n{\n  browser: {\n    provider: ${provider.name}(),\n    instances: [\n      { browser: '${name}' }\n    ],\n  },\n}\n\nUse either:\n{\n  browser: {\n    provider: ${provider.name === 'preview' ? 'playwright' : provider.name}(),\n    instances: [\n      { browser: '${(provider.name === 'preview' || provider.name === 'playwright') ? 'chromium' : 'chrome'}' }\n    ],\n  },\n}\n\n...or change your coverage provider to:\n{\n  coverage: {\n    provider: 'istanbul',\n  },\n}\n`,\n  )\n})\n\ntest('v8 coverage provider throws when using chromium and other non-chromium browser', async () => {\n  const { stderr } = await runVitest({\n    coverage: {\n      enabled: true,\n    },\n    browser: {\n      enabled: true,\n      headless: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'chromium' },\n        { browser: 'firefox' },\n        { browser: 'webkit' },\n      ],\n    },\n  })\n\n  expect(stderr).toMatch(\n    `Error: @vitest/coverage-v8 does not work with\n{\n  browser: {\n    provider: playwright(),\n    instances: [\n      { browser: 'chromium' },\n      { browser: 'firefox' },\n      { browser: 'webkit' }\n    ],\n  },\n}\n\nUse either:\n{\n  browser: {\n    provider: playwright(),\n    instances: [\n      { browser: 'chromium' }\n    ],\n  },\n}\n\n...or change your coverage provider to:\n{\n  coverage: {\n    provider: 'istanbul',\n  },\n}`,\n  )\n})\n\ntest('v8 coverage provider cannot be used in workspace without chromium', async () => {\n  const { stderr } = await runVitest({\n    coverage: { enabled: true },\n    projects: [\n      {\n        test: {\n          name: 'Browser project',\n          browser: {\n            enabled: true,\n            provider: webdriverio(),\n            instances: [{ browser: 'webkit' }],\n          },\n        },\n      },\n    ],\n  }, { fails: true })\n  expect(stderr).toMatch(\n    `Error: @vitest/coverage-v8 does not work with\n    {\n      browser: {\n        provider: webdriverio(),\n        instances: [\n          { browser: 'webkit' }\n        ],\n      },\n    }`,\n  )\n})\n\ntest('coverage reportsDirectory cannot be current working directory', async () => {\n  const { stderr } = await runVitest({\n    root: undefined,\n    coverage: {\n      enabled: true,\n      reportsDirectory: './',\n\n      // Additional options to make sure this test doesn't accidentally remove whole vitest project\n      clean: false,\n      cleanOnRerun: false,\n      provider: 'custom',\n      customProviderModule: 'non-existing-provider-so-that-reportsDirectory-is-not-removed',\n    },\n  })\n\n  const directory = normalize(resolve('./'))\n  expect(stderr).toMatch(`Error: You cannot set \"coverage.reportsDirectory\" as ${directory}. Vitest needs to be able to remove this directory before test run`)\n})\n\ntest('coverage reportsDirectory cannot be root', async () => {\n  const { stderr } = await runVitest({\n    root: './fixtures/test',\n    coverage: {\n      enabled: true,\n      reportsDirectory: './',\n\n      // Additional options to make sure this test doesn't accidentally remove whole vitest project\n      clean: false,\n      cleanOnRerun: false,\n      provider: 'custom',\n      customProviderModule: 'non-existing-provider-so-that-reportsDirectory-is-not-removed',\n    },\n  })\n\n  const directory = normalize(resolve('./fixtures/test'))\n  expect(stderr).toMatch(`Error: You cannot set \"coverage.reportsDirectory\" as ${directory}. Vitest needs to be able to remove this directory before test run`)\n})\n\ntest('version number is printed when coverage provider fails to load', async () => {\n  const { stderr, stdout } = await runVitest({\n    coverage: {\n      enabled: true,\n      provider: 'custom',\n      customProviderModule: './non-existing-module.ts',\n    },\n  })\n\n  expect(stdout).toMatch(`RUN  v${version}`)\n  expect(stderr).toMatch('Error: Failed to load custom CoverageProviderModule from')\n  expect(stderr).toMatch('non-existing-module.ts')\n})\n\ntest('coverage.autoUpdate cannot update thresholds when configuration file doesnt define them', async () => {\n  const { stderr } = await runVitest({\n    coverage: {\n      enabled: true,\n      thresholds: {\n        autoUpdate: true,\n        lines: 0,\n      },\n    },\n  })\n\n  expect(stderr).toMatch('Error: Unable to parse thresholds from configuration file: Expected config.test.coverage.thresholds to be an object')\n})\n\ntest('boolean flag 100 should not crash CLI', async () => {\n  let { stderr } = await runVitestCli('--coverage.enabled', '--coverage.thresholds.100', '--coverage.include=fixtures/coverage-test', '--passWithNoTests')\n  // non-zero coverage shows up, which is non-deterministic, so strip it.\n  stderr = stderr.replace(/\\([0-9.]+%\\) does/g, '(0%) does')\n\n  expect(stderr).toMatch('ERROR: Coverage for lines (0%) does not meet global threshold (100%)')\n  expect(stderr).toMatch('ERROR: Coverage for functions (0%) does not meet global threshold (100%)')\n  expect(stderr).toMatch('ERROR: Coverage for statements (0%) does not meet global threshold (100%)')\n  expect(stderr).toMatch('ERROR: Coverage for branches (0%) does not meet global threshold (100%)')\n})\n\ntest('nextTick cannot be mocked inside child_process', async () => {\n  const { stderr } = await runVitest({\n    fakeTimers: { toFake: ['nextTick'] },\n    include: ['./fake-timers.test.ts'],\n  })\n\n  expect(stderr).toMatch('Error: vi.useFakeTimers({ toFake: [\"nextTick\"] }) is not supported in node:child_process. Use --pool=threads if mocking nextTick is required.')\n})\n\ntest('nextTick can be mocked inside worker_threads', async () => {\n  const { stderr } = await runVitest({\n    pool: 'threads',\n    fakeTimers: { toFake: ['nextTick'] },\n    include: ['./fixtures/test/fake-timers.test.ts'],\n  })\n\n  expect(stderr).not.toMatch('Error')\n})\n\ntest('mergeReports doesn\\'t work with watch mode enabled', async () => {\n  const { stderr } = await runVitest({ watch: true, mergeReports: '.vitest-reports' })\n\n  expect(stderr).toMatch('Cannot merge reports with --watch enabled')\n})\n\ntest('maxConcurrency 0 prints a warning', async () => {\n  const { stderr, ctx } = await runVitest({ maxConcurrency: 0 })\n\n  expect(ctx?.config.maxConcurrency).toBe(5)\n  expect(stderr).toMatch('The option \"maxConcurrency\" cannot be set to 0. Using default value 5 instead.')\n})\n\ntest('detectAsyncLeaks with browser mode prints a warning', async () => {\n  const { stderr } = await runVitest({\n    include: [],\n    detectAsyncLeaks: true,\n    browser: { enabled: true, instances: [{ browser: 'chromium' }], provider: playwright() },\n  })\n\n  expect(stderr).toMatch('The option \"detectAsyncLeaks\" is not supported in browser mode and will be ignored.')\n})\n\ntest('browser.instances is empty', async () => {\n  const { stderr } = await runVitest({\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [],\n    },\n  })\n  expect(stderr).toMatch(`Vitest wasn't able to resolve any project. Please, check that you specified the \"browser.instances\" option.`)\n})\n\ntest('browser.name or browser.instances are required', async () => {\n  const { stderr, exitCode } = await runVitestCli('--browser.enabled', '--root=./fixtures/browser-no-config')\n  expect(exitCode).toBe(1)\n  expect(stderr).toMatch('Vitest received --browser flag, but no project had a browser configuration.')\n})\n\ntest('--browser flag without browser configuration throws an error', async () => {\n  const { stderr, exitCode } = await runVitestCli('--browser.enabled')\n  expect(exitCode).toBe(1)\n  expect(stderr).toMatch('Vitest received --browser flag, but no project had a browser configuration.')\n})\n\ntest('--browser flag without browser configuration in workspaces throws an error', async () => {\n  const { stderr, exitCode } = await runVitestCli('--browser.enabled', '--root=./fixtures/no-browser-workspace')\n  expect(exitCode).toBe(1)\n  expect(stderr).toMatch('Vitest received --browser flag, but no project had a browser configuration.')\n})\n\ntest('browser.name filters all browser.instances are required', async () => {\n  const { stderr } = await runVitest({\n    browser: {\n      enabled: true,\n      name: 'chromium',\n      provider: playwright(),\n      instances: [\n        { browser: 'firefox' },\n      ],\n    },\n  })\n  expect(stderr).toMatch('\"browser.instances\" was set in the config, but the array is empty. Define at least one browser config. The \"browser.name\" was set to \"chromium\" which filtered all configs (firefox). Did you mean to use another name?')\n})\n\ntest('browser.instances throws an error if no custom name is provided', async () => {\n  const { stderr } = await runVitest({\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'firefox' },\n        { browser: 'firefox' },\n      ],\n    },\n  })\n  expect(stderr).toMatch('Cannot define a nested project for a firefox browser. The project name \"firefox\" was already defined. If you have multiple instances for the same browser, make sure to define a custom \"name\". All projects should have unique names. Make sure your configuration is correct.')\n})\n\ntest('browser.instances throws an error if no custom name is provided, but the config name is inherited', async () => {\n  const { stderr } = await runVitest({\n    name: 'custom',\n    browser: {\n      enabled: true,\n      provider: playwright(),\n      instances: [\n        { browser: 'firefox' },\n        { browser: 'firefox' },\n      ],\n    },\n  })\n  expect(stderr).toMatch('Cannot define a nested project for a firefox browser. The project name \"custom (firefox)\" was already defined. If you have multiple instances for the same browser, make sure to define a custom \"name\". All projects should have unique names. Make sure your configuration is correct.')\n})\n\ntest('throws an error if name conflicts with a workspace name', async () => {\n  const { stderr } = await runVitest({\n    projects: [\n      { test: { name: '1 (firefox)' } },\n      {\n        test: {\n          browser: {\n            enabled: true,\n            provider: playwright(),\n            instances: [\n              { browser: 'firefox' },\n            ],\n          },\n        },\n      },\n    ],\n  })\n  expect(stderr).toMatch('Cannot define a nested project for a firefox browser. The project name \"1 (firefox)\" was already defined. If you have multiple instances for the same browser, make sure to define a custom \"name\". All projects should have unique names. Make sure your configuration is correct.')\n})\n\ntest('non existing project name will throw', async () => {\n  const { stderr } = await runVitest({ project: 'non-existing-project' })\n  expect(stderr).toMatch('No projects matched the filter \"non-existing-project\".')\n})\n\ntest('non existing project name array will throw', async () => {\n  const { stderr } = await runVitest({ project: ['non-existing-project', 'also-non-existing'] })\n  expect(stderr).toMatch('No projects matched the filter \"non-existing-project\", \"also-non-existing\".')\n})\n\ntest('cannot set the `workspace` options', async () => {\n  const { stderr } = await runVitest({\n    // @ts-expect-error workspace was removed in Vitest 4, but we show an error\n    workspace: 'some-options',\n  })\n  expect(stderr).toContain('The `test.workspace` option was removed in Vitest 4. Please, migrate to `test.projects` instead. See https://vitest.dev/guide/projects for examples.')\n})\n\ntest('cannot set environment: browser', async () => {\n  const { stderr } = await runVitest({\n    environment: 'browser',\n  })\n  expect(stderr).toContain('Looks like you set \"test.environment\" to \"browser\". To enable Browser Mode, use \"test.browser.enabled\" instead.')\n})\n"
  },
  {
    "path": "test/config/test/fixture-no-async.test.ts",
    "content": "import path from 'node:path'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('fixture parsing works for lowered async syntax', async () => {\n  const { ctx } = await runVitest({\n    root: path.resolve('fixtures/fixture-no-async'),\n    reporters: ['tap-flat'],\n  })\n  expect(ctx?.state.getFiles().map(f => [f.name, f.result?.state])).toMatchInlineSnapshot(`\n    [\n      [\n        \"basic.test.ts\",\n        \"pass\",\n      ],\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/config/test/hook-timeout.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('timeout error with stack trace', async () => {\n  const { stderr } = await runVitest({\n    root: './fixtures/hook-timeout',\n  })\n  expect(stderr).toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/config/test/inline-setup-file.test.ts",
    "content": "import path from 'node:path'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('import a generated file', async () => {\n  const root = path.resolve(import.meta.dirname, '../fixtures/inline-setup-file')\n\n  const { stderr, exitCode } = await runVitest({ root })\n  expect(stderr).toBe('')\n  expect(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/config/test/mixed-environments.test.ts",
    "content": "import type { TestUserConfig } from 'vitest/node'\nimport { expect, test } from 'vitest'\n\nimport { runVitest } from '../../test-utils'\n\nconst configs: TestUserConfig[] = [\n  { pool: 'threads', isolate: false, fileParallelism: false },\n  { pool: 'threads', isolate: false, fileParallelism: true },\n  { pool: 'threads', isolate: false, maxWorkers: 1 },\n  { pool: 'forks', isolate: true },\n  { pool: 'forks', isolate: false },\n]\n\ntest.each(configs)('should isolate environments when %s', async (config) => {\n  const { stderr, stdout } = await runVitest({\n    root: './fixtures/mixed-environments',\n    ...config,\n  })\n\n  expect(stderr).toBe('')\n\n  expect(stdout).toContain('✓ |Project #1| test/node.test.ts')\n  expect(stdout).toContain('✓ |Project #1| test/jsdom.test.ts')\n  expect(stdout).toContain('✓ |Project #2| test/jsdom.test.ts')\n  expect(stdout).toContain('✓ |Project #1| test/happy-dom.test.ts')\n  expect(stdout).toContain('✓ |Project #2| test/happy-dom.test.ts')\n  expect(stdout).toContain('✓ |Project #1| test/workspace-project.test.ts')\n  expect(stdout).toContain('✓ |Project #2| test/workspace-project.test.ts')\n  expect(stdout).toContain('Test Files  8 passed (8)')\n  expect(stdout).toContain('Tests  8 passed (8)')\n})\n"
  },
  {
    "path": "test/config/test/mode.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport * as testUtils from '../../test-utils'\n\ntest.each([\n  { expectedMode: 'test', command: ['run'] },\n  { expectedMode: 'benchmark', command: ['bench', '--run'] },\n])(`env.mode should have the $expectedMode value when running in $name mode`, async ({ command, expectedMode }) => {\n  const { stdout } = await testUtils.runVitestCli(...(command), 'fixtures/mode', '-c', `fixtures/mode/vitest.${expectedMode}.config.ts`)\n\n  expect(stdout).toContain(`✓ fixtures/mode/example.${expectedMode}.ts`)\n})\n\ntest.each([\n  { expectedMode: 'test', command: ['bench', '--run'], actualMode: 'benchmark' },\n  { expectedMode: 'benchmark', command: ['run'], actualMode: 'test' },\n])(`should return error if actual mode $actualMode is different than expected mode $expectedMode`, async ({ command, expectedMode, actualMode }) => {\n  const { stdout, stderr } = await testUtils.runVitestCli(...(command), 'fixtures/mode', '-c', `fixtures/mode/vitest.${expectedMode}.config.ts`)\n\n  expect(stderr).toContain(`env.mode:  ${actualMode}`)\n  expect(stderr).toContain('Startup Error')\n  expect(stderr).toContain(`Error: env.mode should be equal to \"${expectedMode}\"`)\n  expect(stdout).toBe('')\n})\n\ntest.each([\n  { options: ['run'], expected: 'run' },\n  { options: ['run', '--watch'], expected: 'watch' },\n  { options: ['watch'], expected: 'watch' },\n] as const)(`vitest $options.0 $options.1 resolves to $expected-mode`, async ({ options, expected }) => {\n  const { vitest } = await testUtils.runVitestCli(...options, '--root', 'fixtures/run-mode')\n\n  if (expected === 'watch') {\n    await vitest.waitForStdout('Test Files  1 passed (1)')\n\n    expect(vitest.stdout).not.toContain('RUN')\n    expect(vitest.stdout).toContain('DEV')\n    expect(vitest.stdout).toContain('Waiting for file changes')\n  }\n\n  if (expected === 'run') {\n    expect(vitest.stdout).toContain('RUN')\n    expect(vitest.stdout).not.toContain('DEV')\n    expect(vitest.stdout).not.toContain('Waiting for file changes')\n  }\n})\n"
  },
  {
    "path": "test/config/test/optimizer.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nit('external works with optimizer', async () => {\n  const { errorTree } = await runVitest({\n    root: 'fixtures/optimizer/external',\n  })\n  expect(errorTree()).toMatchInlineSnapshot(`\n    {\n      \"basic.test.ts\": {\n        \"passes\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/config/test/override.test.ts",
    "content": "import type { UserConfig as ViteUserConfig } from 'vite'\nimport type { TestUserConfig } from 'vitest/node'\nimport { resolve } from 'pathe'\nimport { describe, expect, it, onTestFinished } from 'vitest'\nimport { createVitest, parseCLI } from 'vitest/node'\n\ntype VitestOptions = Parameters<typeof createVitest>[3]\n\nasync function vitest(cliOptions: TestUserConfig, configValue: TestUserConfig = {}, viteConfig: ViteUserConfig = {}, vitestOptions: VitestOptions = {}) {\n  const vitest = await createVitest('test', { ...cliOptions, watch: false }, { ...viteConfig, test: configValue as any }, vitestOptions)\n  onTestFinished(() => vitest.close())\n  return vitest\n}\n\nasync function config(cliOptions: TestUserConfig, configValue: TestUserConfig = {}, viteConfig: ViteUserConfig = {}, vitestOptions: VitestOptions = {}) {\n  const v = await vitest(cliOptions, configValue, viteConfig, vitestOptions)\n  return v.config\n}\n\ndescribe('correctly defines api flag', () => {\n  it('CLI overrides disabling api', async () => {\n    const c = await vitest({ api: false }, {\n      api: {\n        port: 1234,\n      },\n      watch: true,\n    })\n    expect(c.vite.config.server.middlewareMode).toBe(true)\n    expect(c.config.api).toEqual({\n      allowExec: true,\n      allowWrite: true,\n      middlewareMode: true,\n      token: expect.any(String),\n    })\n  })\n\n  it('CLI overrides inlined value', async () => {\n    const c = await vitest({ api: { port: 4321 } }, {\n      api: {\n        port: 1234,\n      },\n      watch: true,\n    })\n    expect(c.vite.config.server.port).toBe(4321)\n    expect(c.config.api).toEqual({\n      port: 4321,\n      allowWrite: true,\n      allowExec: true,\n      token: expect.any(String),\n    })\n  })\n\n  it('browser.isolate is inherited', async () => {\n    const c = await vitest({ isolate: false }, {})\n    expect(c.config.isolate).toBe(false)\n    expect(c.config.browser.isolate).toBe(false)\n  })\n\n  it('allowWrite and allowExec default to true when not exposed to network', async () => {\n    const c = await config({ api: { port: 5555 } }, {})\n    expect(c.api.allowWrite).toBe(true)\n    expect(c.api.allowExec).toBe(true)\n  })\n\n  it('allowWrite and allowExec default to true for localhost', async () => {\n    const c = await config({ api: { port: 5555, host: 'localhost' } }, {})\n    expect(c.api.allowWrite).toBe(true)\n    expect(c.api.allowExec).toBe(true)\n  })\n\n  it('allowWrite and allowExec default to true for 127.0.0.1', async () => {\n    const c = await config({ api: { port: 5555, host: '127.0.0.1' } }, {})\n    expect(c.api.allowWrite).toBe(true)\n    expect(c.api.allowExec).toBe(true)\n  })\n\n  it('allowWrite and allowExec default to false when exposed to network', async () => {\n    const c = await config({ api: { port: 5555, host: '0.0.0.0' } }, {})\n    expect(c.api.allowWrite).toBe(false)\n    expect(c.api.allowExec).toBe(false)\n  })\n\n  it('allowWrite and allowExec can be explicitly overridden when exposed to network', async () => {\n    const c = await config({ api: { port: 5555, host: '0.0.0.0', allowWrite: true, allowExec: true } }, {})\n    expect(c.api.allowWrite).toBe(true)\n    expect(c.api.allowExec).toBe(true)\n  })\n\n  it('allowWrite and allowExec can be explicitly disabled', async () => {\n    const c = await config({ api: { port: 5555, allowWrite: false, allowExec: false } }, {})\n    expect(c.api.allowWrite).toBe(false)\n    expect(c.api.allowExec).toBe(false)\n  })\n\n  it('browser.api inherits allowWrite and allowExec from api', async () => {\n    const c = await config({ api: { port: 5555, allowWrite: false, allowExec: false } }, {})\n    expect(c.browser.api.allowWrite).toBe(false)\n    expect(c.browser.api.allowExec).toBe(false)\n  })\n\n  it('browser.api can override inherited allowWrite and allowExec', async () => {\n    const c = await config({\n      api: { port: 5555, allowWrite: false, allowExec: false },\n      browser: { api: { allowWrite: true, allowExec: true } },\n    }, {\n      browser: {},\n    })\n    expect(c.api.allowWrite).toBe(false)\n    expect(c.api.allowExec).toBe(false)\n    expect(c.browser.api.allowWrite).toBe(true)\n    expect(c.browser.api.allowExec).toBe(true)\n  })\n})\n\ndescribe.each([\n  '--inspect',\n  '--inspect-brk',\n])('correctly parses %s flags', (inspectFlagName) => {\n  it.each([\n    ['', { enabled: true }],\n    ['true', { enabled: true }],\n    ['yes', { enabled: true }],\n    ['false', { enabled: false }],\n    ['no', { enabled: false }],\n\n    ['1002', { enabled: true, port: 1002 }],\n    ['www.remote.com:1002', { enabled: true, port: 1002, host: 'www.remote.com' }],\n    ['www.remote.com', { enabled: true, host: 'www.remote.com' }],\n  ])(`parses \"vitest ${inspectFlagName} %s\" value`, async (cliValue, inspect) => {\n    const rawConfig = parseCLI(\n      `vitest --no-file-parallelism ${inspectFlagName} ${cliValue}`,\n    )\n    const c = await config(rawConfig.options)\n    expect(c.inspector).toEqual({\n      ...inspect,\n      waitForDebugger: inspectFlagName === '--inspect-brk' && inspect.enabled,\n    })\n  })\n  it('cannot use URL', async () => {\n    const url = 'https://www.remote.com:1002'\n    const rawConfig = parseCLI([\n      'vitest',\n      '--no-file-parallelism',\n      inspectFlagName,\n      url,\n    ])\n    await expect(async () => {\n      await config(rawConfig.options)\n    }).rejects.toThrow(`Inspector host cannot be a URL. Use \"host:port\" instead of \"${url}\"`)\n  })\n})\n\nit('experimental fsModuleCache is inherited in a project', async () => {\n  const v = await vitest({}, {\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/custom-cache-path',\n    },\n    projects: [\n      {\n        test: {\n          name: 'project',\n        },\n      },\n    ],\n  })\n  expect(v.config.experimental.fsModuleCache).toBe(true)\n  expect(v.projects[0].config.experimental.fsModuleCache).toBe(true)\n\n  expect(v.config.experimental.fsModuleCachePath).toBe(resolve('./node_modules/custom-cache-path'))\n  expect(v.projects[0].config.experimental.fsModuleCachePath).toBe(resolve('./node_modules/custom-cache-path'))\n})\n\nit('project overrides experimental fsModuleCache', async () => {\n  const v = await vitest({}, {\n    experimental: {\n      fsModuleCache: true,\n      fsModuleCachePath: './node_modules/custom-cache-path',\n    },\n    projects: [\n      {\n        test: {\n          name: 'project',\n          experimental: {\n            fsModuleCache: false,\n            fsModuleCachePath: './node_modules/project-cache-path',\n          },\n        },\n      },\n    ],\n  })\n  expect(v.config.experimental.fsModuleCache).toBe(true)\n  expect(v.projects[0].config.experimental.fsModuleCache).toBe(false)\n\n  expect(v.config.experimental.fsModuleCachePath).toBe(resolve('./node_modules/custom-cache-path'))\n  expect(v.projects[0].config.experimental.fsModuleCachePath).toBe(resolve('./node_modules/project-cache-path'))\n})\n"
  },
  {
    "path": "test/config/test/pass-empty-files.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nit('vitest doesnt fail when running empty files', async () => {\n  const { exitCode } = await runVitest({\n    root: './fixtures/pass-empty-files',\n    passWithNoTests: true,\n  })\n  expect(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/config/test/pool.test.ts",
    "content": "import type { SerializedConfig } from 'vitest'\nimport type { TestUserConfig } from 'vitest/node'\nimport { normalize } from 'pathe'\nimport { assert, describe, expect, test, vi } from 'vitest'\nimport { runVitest, StableTestFileOrderSorter } from '../../test-utils'\n\ndescribe.each(['forks', 'threads', 'vmThreads', 'vmForks'])('%s', async (pool) => {\n  test('resolves top-level pool', async () => {\n    const config = await getConfig({ pool })\n\n    expect(config.pool).toBe(pool)\n  })\n\n  test('can capture worker\\'s stdout and stderr', async () => {\n    const { stdout, stderr } = await runVitest({\n      root: './fixtures/pool',\n      include: ['write-to-stdout-and-stderr.test.ts'],\n      pool,\n    })\n\n    expect(stderr).toContain('Worker writing to stderr')\n    expect(stdout).toContain('Worker writing to stdout')\n    expect(stderr).toContain('MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 3 message listeners added to [TestFixturesCustomEmitter]')\n  })\n})\n\ntest('extended project inherits top-level pool related options', async () => {\n  const config = await getConfig({\n    projects: [{\n      extends: true,\n      test: { name: 'example' },\n    }],\n  },\n  // project.extends works weirdly with runVitest(). Need to pass it here in cli options instead.\n  { pool: 'threads', isolate: false })\n\n  expect(config.pool).toBe('threads')\n  expect(config.isolate).toBe(false)\n})\n\ntest('project level pool options overwrites top-level', async () => {\n  const config = await getConfig({\n    pool: 'vmForks',\n    maxWorkers: 4,\n    fileParallelism: true,\n    projects: [{\n      extends: true,\n      test: { pool: 'vmThreads', fileParallelism: false },\n    }],\n  })\n\n  expect(config.pool).toBe('vmThreads')\n  expect(config.maxWorkers).toBe(1)\n})\n\ntest('serialized config includes slowTestThreshold', async () => {\n  const config = await getConfig({})\n\n  expect(config.slowTestThreshold).toBe(300)\n})\n\ntest('isolated single worker pool receives single testfile at once', async () => {\n  const files = await getConfig<string[]>({\n    maxWorkers: 1,\n    isolate: true,\n    sequence: { sequencer: StableTestFileOrderSorter },\n  }, { include: ['print-testfiles.test.ts', 'a.test.ts', 'b.test.ts', 'c.test.ts'] })\n\n  expect(files.map(normalizeFilename)).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/pool/print-testfiles.test.ts\",\n    ]\n  `)\n})\n\ntest('non-isolated single worker pool receives all testfiles at once', async () => {\n  const files = await getConfig<string[]>({\n    maxWorkers: 1,\n    isolate: false,\n    sequence: { sequencer: StableTestFileOrderSorter },\n  }, { include: ['print-testfiles.test.ts', 'a.test.ts', 'b.test.ts', 'c.test.ts'] })\n\n  expect(files.map(normalizeFilename)).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/pool/a.test.ts\",\n      \"<process-cwd>/fixtures/pool/b.test.ts\",\n      \"<process-cwd>/fixtures/pool/c.test.ts\",\n      \"<process-cwd>/fixtures/pool/print-testfiles.test.ts\",\n    ]\n  `)\n})\n\ntest('non-isolated happy-dom worker pool receives all testfiles at once', async () => {\n  const files = await getConfig<string[]>({\n    fileParallelism: false,\n    isolate: false,\n    environment: 'happy-dom',\n    sequence: { sequencer: StableTestFileOrderSorter },\n  }, { include: ['print-testfiles.test.ts', 'a.test.ts', 'b.test.ts', 'c.test.ts'] })\n\n  expect(files.map(normalizeFilename)).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/pool/a.test.ts\",\n      \"<process-cwd>/fixtures/pool/b.test.ts\",\n      \"<process-cwd>/fixtures/pool/c.test.ts\",\n      \"<process-cwd>/fixtures/pool/print-testfiles.test.ts\",\n    ]\n  `)\n})\n\ntest('worker start failure should not hang', async () => {\n  const stop = vi.fn()\n\n  const { stdout, stderr } = await runVitest({\n    root: './fixtures/pool',\n    include: ['a.test.ts'],\n    pool: {\n      name: 'pool-with-crashing-workers',\n      // @ts-expect-error -- intentional\n      createPoolWorker: () => ({\n        start: () => Promise.reject(new Error('Mock')),\n        stop,\n        on() {},\n        off() {},\n        send() {},\n      }),\n    },\n  })\n\n  expect(stderr).toContain('Error: [vitest-pool]: Failed to start pool-with-crashing-workers worker for test files')\n  expect(stderr).toContain('a.test.ts')\n  expect(stderr).toContain('Caused by: Error: Mock')\n  expect(stdout).toContain('Errors  1 error')\n\n  expect(stop).toHaveBeenCalled()\n})\n\nasync function getConfig<T = SerializedConfig>(options: Partial<TestUserConfig>, cliOptions: Partial<TestUserConfig> = {}): Promise<T> {\n  let config: T | undefined\n\n  await runVitest({\n    root: './fixtures/pool',\n    include: ['print-config.test.ts'],\n    $cliOptions: cliOptions,\n    onConsoleLog(log) {\n      config = JSON.parse(log)\n    },\n    ...options,\n  })\n\n  assert(config)\n  return config\n}\n\nfunction normalizeFilename(filename: string) {\n  return normalize(filename)\n    .replace(normalize(process.cwd()), '<process-cwd>')\n}\n"
  },
  {
    "path": "test/config/test/public.test.ts",
    "content": "import type { BaseCoverageOptions } from 'vitest/node'\nimport { resolve } from 'pathe'\nimport { expect, test } from 'vitest'\nimport { resolveConfig } from 'vitest/node'\n\ntest('resolves the test config', async () => {\n  const { viteConfig, vitestConfig } = await resolveConfig()\n  expect(viteConfig.mode).toBe('test')\n  expect(vitestConfig.mode).toBe('test')\n  expect(vitestConfig.reporters).toEqual([['verbose', {}]]) // inherits the root config\n  expect(viteConfig.plugins.find(p => p.name === 'vitest')).toBeDefined()\n})\n\ntest('applies custom options', async () => {\n  const { viteConfig, vitestConfig } = await resolveConfig({\n    mode: 'development',\n    setupFiles: ['/test/setup.ts'],\n  })\n  expect(viteConfig.mode).toBe('development')\n  expect(vitestConfig.mode).toBe('test') // vitest mode is \"test\" or \"benchmark\"\n  expect(vitestConfig.setupFiles).toEqual(['/test/setup.ts'])\n  expect(viteConfig.plugins.find(p => p.name === 'vitest')).toBeDefined()\n})\n\ntest('respects root', async () => {\n  process.env.GITHUB_ACTIONS = 'false'\n  const configRoot = resolve(import.meta.dirname, '../fixtures/public-config')\n  const { viteConfig, vitestConfig } = await resolveConfig({\n    root: configRoot,\n  })\n  expect(viteConfig.configFile).toBe(resolve(configRoot, 'vitest.config.ts'))\n  expect(vitestConfig.name).toBe('root config')\n  expect(vitestConfig.reporters).toEqual([['default', {}]])\n})\n\ntest('respects custom config', async () => {\n  process.env.GITHUB_ACTIONS = 'false'\n  const config = resolve(import.meta.dirname, '../fixtures/public-config/vitest.custom.config.ts')\n  const { viteConfig, vitestConfig } = await resolveConfig({\n    config,\n  })\n  expect(viteConfig.configFile).toBe(config)\n  expect(vitestConfig.name).toBe('custom config')\n  expect(vitestConfig.reporters).toEqual([['default', {}]])\n})\n\ntest('default value changes of coverage.exclude do not reflect to test.exclude', async () => {\n  const exclude = ['**/custom-exclude/**']\n\n  const { vitestConfig } = await resolveConfig({\n    include: ['**/example.test.ts'],\n    exclude,\n    coverage: {\n      exclude,\n    },\n  })\n\n  expect(exclude).toStrictEqual(['**/custom-exclude/**'])\n\n  expect(vitestConfig.include).toStrictEqual(['**/example.test.ts'])\n  expect(vitestConfig.exclude).toStrictEqual(['**/custom-exclude/**'])\n\n  expect(vitestConfig.coverage.exclude).toContain('**/custom-exclude/**')\n  expect(vitestConfig.coverage.exclude).toContain('**/example.test.ts')\n})\n\ntest.for([\n  {\n    options: {},\n    expected: 'coverage',\n  },\n  {\n    options: { reporter: ['html'] },\n    expected: 'coverage',\n  },\n  {\n    options: { reporter: [['html', {}]] },\n    expected: 'coverage',\n  },\n  {\n    options: { reporter: [['html-spa', {}]] },\n    expected: 'coverage',\n  },\n  {\n    options: { reporter: [['html', { subdir: 'custom-subdir' }]] },\n    expected: 'coverage/custom-subdir',\n  },\n  {\n    options: { reporter: [['html', {}]], reportsDirectory: 'my-coverage' },\n    expected: 'my-coverage',\n  },\n  {\n    options: { reporter: [['html', { subdir: 'custom-subdir' }]], reportsDirectory: 'my-coverage' },\n    expected: 'my-coverage/custom-subdir',\n  },\n  {\n    options: { reporter: ['lcov'] },\n    expected: 'coverage/lcov-report',\n  },\n  {\n    options: { reporter: [['text', {}]] },\n    expected: undefined,\n  },\n  {\n    options: { htmlDir: 'custom-html-dir' },\n    expected: 'custom-html-dir',\n  },\n] satisfies {\n  options: BaseCoverageOptions\n  expected?: string\n}[])('coverage.htmlDir inference: $options', async ({ options, expected }) => {\n  const { vitestConfig } = await resolveConfig({\n    config: false,\n    coverage: { enabled: true, ...options },\n  })\n  expect(vitestConfig.coverage.htmlDir).toBe(\n    expected && resolve(vitestConfig.root, expected),\n  )\n})\n\ntest('coverage.changed inherits from test.changed but can be overridden', async () => {\n  const { vitestConfig: inherited } = await resolveConfig({\n    changed: 'HEAD',\n    coverage: {\n      reporter: 'json',\n    },\n  })\n\n  expect(inherited.coverage.changed).toBe('HEAD')\n\n  const { vitestConfig: overridden } = await resolveConfig({\n    changed: 'HEAD',\n    coverage: {\n      changed: false,\n    },\n  })\n\n  expect(overridden.coverage.changed).toBe(false)\n})\n"
  },
  {
    "path": "test/config/test/retry.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nfunction run(testNamePattern: string) {\n  return runVitest({\n    include: ['fixtures/retry/retry.test.ts'],\n    config: 'fixtures/retry/vitest.config.ts',\n    testNamePattern,\n  })\n}\n\ndescribe('retry', () => {\n  test('should passed', async () => {\n    const { stdout } = await run('should passed')\n\n    expect(stdout).toContain('1 passed')\n  })\n\n  test('retry but still failed', async () => {\n    const { stdout } = await run('retry but still failed')\n\n    expect(stdout).toContain('expected 1 to be 4')\n    expect(stdout).toContain('expected 2 to be 4')\n    expect(stdout).toContain('expected 3 to be 4')\n    expect(stdout).toContain('1 failed')\n  })\n})\n"
  },
  {
    "path": "test/config/test/sequence-concurrent.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { runVitest } from '../../test-utils'\n\ntest('should run suites and tests concurrently unless sequential specified when sequence.concurrent is true', async () => {\n  const { stderr, stdout } = await runVitest({\n    root: './fixtures/sequence-concurrent',\n    include: ['sequence-concurrent-true-*.test.ts'],\n    sequence: {\n      concurrent: true,\n    },\n  })\n\n  expect(stderr).toBe('')\n\n  expect(stdout).toContain('✓ sequence-concurrent-true-sequential.test.ts > sequential suite > first test completes first')\n  expect(stdout).toContain('✓ sequence-concurrent-true-sequential.test.ts > sequential suite > second test completes second')\n  expect(stdout).toContain('✓ sequence-concurrent-true-sequential.test.ts > third test completes third')\n  expect(stdout).toContain('✓ sequence-concurrent-true-sequential.test.ts > last test completes last')\n  expect(stdout).toContain('✓ sequence-concurrent-true-concurrent.test.ts > concurrent suite > first test completes last')\n  expect(stdout).toContain('✓ sequence-concurrent-true-concurrent.test.ts > concurrent suite > second test completes third')\n  expect(stdout).toContain('✓ sequence-concurrent-true-concurrent.test.ts > third test completes second')\n  expect(stdout).toContain('✓ sequence-concurrent-true-concurrent.test.ts > last test completes first')\n  expect(stdout).toContain('Test Files  2 passed (2)')\n})\n\ntest('should run suites and tests sequentially unless concurrent specified when sequence.concurrent is false', async () => {\n  const { stderr, stdout } = await runVitest({\n    root: './fixtures/sequence-concurrent',\n    include: ['sequence-concurrent-false-*.test.ts'],\n    sequence: {\n      concurrent: false,\n    },\n  })\n\n  expect(stderr).toBe('')\n\n  expect(stdout).toContain('✓ sequence-concurrent-false-sequential.test.ts > sequential suite > first test completes first')\n  expect(stdout).toContain('✓ sequence-concurrent-false-sequential.test.ts > sequential suite > second test completes second')\n  expect(stdout).toContain('✓ sequence-concurrent-false-sequential.test.ts > third test completes third')\n  expect(stdout).toContain('✓ sequence-concurrent-false-sequential.test.ts > last test completes last')\n  expect(stdout).toContain('✓ sequence-concurrent-false-concurrent.test.ts > concurrent suite > first test completes last')\n  expect(stdout).toContain('✓ sequence-concurrent-false-concurrent.test.ts > concurrent suite > second test completes third')\n  expect(stdout).toContain('✓ sequence-concurrent-false-concurrent.test.ts > third test completes second')\n  expect(stdout).toContain('✓ sequence-concurrent-false-concurrent.test.ts > last test completes first')\n  expect(stdout).toContain('Test Files  2 passed (2)')\n})\n"
  },
  {
    "path": "test/config/test/shard.test.ts",
    "content": "import type { TestUserConfig } from 'vitest/node'\nimport { basename } from 'pathe'\n\nimport { expect, test } from 'vitest'\nimport * as testUtils from '../../test-utils'\n\nfunction runVitest(config: TestUserConfig, root = './fixtures/shard') {\n  return testUtils.runVitest({ ...config, root })\n}\n\nfunction parsePaths(stdout: string) {\n  return Array.from(new Set(stdout\n    .split('\\n')\n    .filter(line => line && line.includes('.test.js'))\n    .map(file => basename(file.trim().split(' ')[1]))\n    .sort()))\n}\n\ntest('--shard=1/1', async () => {\n  const { stdout } = await runVitest({ shard: '1/1' })\n\n  const paths = parsePaths(stdout)\n\n  expect(paths).toEqual(['1.test.js', '2.test.js', '3.test.js'])\n})\n\ntest('--shard=1/2', async () => {\n  const { stdout } = await runVitest({ shard: '1/2' })\n\n  const paths = parsePaths(stdout)\n\n  expect(paths).toEqual(['1.test.js', '2.test.js'])\n})\n\ntest('--shard=2/2', async () => {\n  const { stdout } = await runVitest({ shard: '2/2' })\n\n  const paths = parsePaths(stdout)\n\n  expect(paths).toEqual(['3.test.js'])\n})\n\ntest('--shard=1/3 should distribute files evenly', async () => {\n  const { stdout } = await runVitest({ shard: '1/3' })\n\n  const paths = parsePaths(stdout)\n\n  // With 3 files and 3 shards, should get 1 file per shard\n  expect(paths).toEqual(['1.test.js'])\n})\n\ntest('--shard=2/3 should distribute files evenly', async () => {\n  const { stdout } = await runVitest({ shard: '2/3' })\n\n  const paths = parsePaths(stdout)\n\n  // With 3 files and 3 shards, should get 1 file per shard\n  expect(paths).toEqual(['2.test.js'])\n})\n\ntest('--shard=3/3 should distribute files evenly', async () => {\n  const { stdout } = await runVitest({ shard: '3/3' })\n\n  const paths = parsePaths(stdout)\n\n  // With 3 files and 3 shards, should get 1 file per shard\n  expect(paths).toEqual(['3.test.js'])\n})\n\ntest('4 files with 3 shards should distribute evenly', async () => {\n  const { stdout: stdout1 } = await runVitest({ shard: '1/3' }, './fixtures/shard-4-files')\n  const { stdout: stdout2 } = await runVitest({ shard: '2/3' }, './fixtures/shard-4-files')\n  const { stdout: stdout3 } = await runVitest({ shard: '3/3' }, './fixtures/shard-4-files')\n\n  const paths1 = parsePaths(stdout1)\n  const paths2 = parsePaths(stdout2)\n  const paths3 = parsePaths(stdout3)\n\n  // Should distribute files more evenly: [2,1,1] instead of [2,2,0]\n  expect(paths1.length).toBe(2)\n  expect(paths2.length).toBe(1)\n  expect(paths3.length).toBe(1)\n\n  // All files should be covered exactly once\n  const allFiles = [...paths1, ...paths2, ...paths3].sort()\n  expect(allFiles).toEqual(['1.test.js', '2.test.js', '3.test.js', '4.test.js'])\n})\n\ntest('--shard=4/4', async () => {\n  const { stdout } = await runVitest({ shard: '4/4' })\n\n  const paths = parsePaths(stdout)\n\n  // project only has 3 files\n  // shards > 3 are empty\n  expect(paths).toEqual([])\n})\n"
  },
  {
    "path": "test/config/test/snapshot.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('resolveSnapshotPath context', async () => {\n  const { stderr, ctx } = await runVitest({\n    root: './fixtures/snapshot-path-context',\n  })\n  expect(stderr).toBe('')\n  expect(\n    Object.fromEntries(\n      ctx!.state.getFiles().map(f => [`${f.projectName}|${f.name}`, f.result?.state]),\n    ),\n  ).toMatchInlineSnapshot(`\n    {\n      \"project1|basic.test.ts\": \"pass\",\n      \"project2|basic.test.ts\": \"pass\",\n    }\n  `)\n})\n"
  },
  {
    "path": "test/config/test/testname-pattern.test.ts",
    "content": "import { join, resolve } from 'pathe'\nimport { expect, test } from 'vitest'\n\nimport { runVitest } from '../../test-utils'\n\ntest.each([\n  { filter: 'example' },\n  { filter: '/example' },\n  { filter: resolve('./fixtures/filters/test/example') },\n])('match by partial pattern $filter', async ({ filter }) => {\n  const { stdout } = await runVitest({ root: './fixtures/filters' }, [filter])\n\n  expect(stdout).toMatch('✓ test/example.test.ts > this will pass')\n  expect(stdout).toMatch('Test Files  1 passed (1)')\n  expect(stdout).not.toMatch('test/config.test.ts')\n})\n\ntest('match by full test file name', async () => {\n  const filename = resolve('./fixtures/filters/test/example.test.ts')\n  const { stdout } = await runVitest({ root: './fixtures/filters' }, [filename])\n\n  expect(stdout).toMatch('✓ test/example.test.ts > this will pass')\n  expect(stdout).toMatch('Test Files  1 passed (1)')\n  expect(stdout).not.toMatch('test/filters.test.ts')\n})\n\ntest('match by pattern that also matches current working directory', async () => {\n  const filter = 'config'\n  expect(process.cwd()).toMatch(filter)\n\n  const { stdout } = await runVitest({ root: './fixtures/filters' }, [filter])\n\n  expect(stdout).toMatch('✓ test/config.test.ts > this will pass')\n  expect(stdout).toMatch('Test Files  1 passed (1)')\n  expect(stdout).not.toMatch('test/example.test.ts')\n})\n\ntest.each([\n  ['the parent of CWD', resolve(process.cwd(), '..')],\n  ['the parent of CWD with slash', join(resolve(process.cwd(), '..'), '/')],\n  ['the parent of a parent of CWD', resolve(process.cwd(), '..', '..')],\n])('match by pattern that also matches %s: %s', async (_, filter) => {\n  const { stdout } = await runVitest({ root: './fixtures/filters' }, [filter])\n\n  expect(stdout).toMatch('✓ test/config.test.ts > this will pass')\n  expect(stdout).toMatch('× test/dont-run-this.test.ts > this will fail')\n  expect(stdout).toMatch('✓ test/example.test.ts > this will pass')\n})\n\ntest.each([\n  {\n    filter: 'basic',\n    files: [\n      'test/basic.test.ts',\n      'test/foo-basic/a.test.ts',\n      'test/basic/a.test.ts',\n      'test/basic-foo/a.test.ts',\n    ],\n  },\n  {\n    filter: '/basic',\n    files: [\n      'test/basic.test.ts',\n      'test/basic/a.test.ts',\n      'test/basic-foo/a.test.ts',\n    ],\n  },\n  {\n    filter: 'basic/',\n    files: [\n      'test/foo-basic/a.test.ts',\n      'test/basic/a.test.ts',\n    ],\n  },\n  {\n    filter: '/basic/',\n    files: [\n      'test/basic/a.test.ts',\n    ],\n  },\n])('filter with slash $filter', async ({ filter, files }) => {\n  const { stdout } = await runVitest({ root: './fixtures/filters-slash' }, [filter])\n  expect(stdout).toMatch(`Test Files  ${files.length} passed (${files.length})`)\n  for (const file of files) {\n    expect(stdout).toMatch(`✓ ${file}`)\n  }\n})\n"
  },
  {
    "path": "test/config/test/vite-ssr-resolve.test.ts",
    "content": "import type { Plugin } from 'vite'\nimport type { CliOptions } from 'vitest/node'\nimport { join } from 'pathe'\nimport { describe, expect, onTestFinished, test } from 'vitest'\nimport { createVitest } from 'vitest/node'\n\nconst nodeModulesDir = join(import.meta.dirname, '../../node_modules')\n\ndescribe.each(['deprecated', 'environment'] as const)('VitestResolver with Vite SSR config in %s style', (style) => {\n  test('merges vite ssr.resolve.noExternal with server.deps.inline', async () => {\n    const resolver = await getResolver(style, {\n      server: {\n        deps: {\n          inline: ['inline-dep'],\n        },\n      },\n    }, {\n      noExternal: ['ssr-no-external-dep'],\n    })\n\n    expect(resolver.options.inline).toEqual(['inline-dep', 'ssr-no-external-dep'])\n\n    // Both inline-dep and ssr-no-external-dep should be inlined (return false)\n    expect(await resolver.shouldExternalize(join(nodeModulesDir, 'inline-dep/index.js'))).toBe(false)\n    expect(await resolver.shouldExternalize(join(nodeModulesDir, 'ssr-no-external-dep/index.js'))).toBe(false)\n\n    // Other deps should be externalized\n    expect(await resolver.shouldExternalize(join(nodeModulesDir, 'other-dep/index.js'))).toBeTruthy()\n\n    // hard-coded pattern for external\n    expect(await resolver.shouldExternalize('/usr/a/non-existing/node_modules/non-existing/index.cjs.js')).toBeTruthy()\n    expect(await resolver.shouldExternalize('/usr/a/non-existing/node_modules/non-existing/index.mjs')).toBeTruthy()\n\n    // non-existing files are inlined\n    expect(await resolver.shouldExternalize('/usr/a/non-existing/node_modules/non-existing/index.js')).toBeUndefined()\n  })\n\n  test('merges vite ssr.resolve.external with server.deps.external', async () => {\n    const resolver = await getResolver(style, {\n      server: {\n        deps: {\n          external: ['external-dep'],\n        },\n      },\n    }, {\n      external: ['ssr-external-dep'],\n    })\n\n    expect(resolver.options.external).toEqual(['external-dep', 'ssr-external-dep'])\n\n    // Both external-dep and ssr-external-dep should be externalized (return the ID)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/external-dep/index.js')).toBeTruthy()\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/ssr-external-dep/index.js')).toBeTruthy()\n  })\n\n  test('handles ssr.resolve.noExternal with wildcard patterns', async () => {\n    const resolver = await getResolver(style, {}, {\n      noExternal: ['@org/*'],\n    })\n\n    // Wildcard should match @org/utils, @org/runner, etc.\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@org/utils/index.js')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@org/runner/index.js')).toBe(false)\n\n    // But not other scopes\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@other/utils/index.cjs.js')).toBeTruthy()\n  })\n\n  test('handles ssr.resolve.noExternal as true', async () => {\n    const resolver = await getResolver(style, {}, {\n      noExternal: true,\n    })\n\n    // When noExternal is true, dependencies should be inlined\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-dep/index.js')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/another-dep/index.cjs.js')).toBe(false)\n\n    // Builtins should still be externalized\n    expect(await resolver.shouldExternalize('fs')).toBe('fs')\n    expect(await resolver.shouldExternalize('path')).toBe('path')\n\n    expect(await resolver.shouldExternalize('node:fs')).toBe('node:fs')\n    expect(await resolver.shouldExternalize('node:path')).toBe('node:path')\n  })\n\n  test('handles ssr.resolve.external as true', async () => {\n    const resolver = await getResolver(style, {}, {\n      external: true,\n    })\n\n    // When external is true, node_modules dependencies should be externalized\n    expect(await resolver.shouldExternalize('/node_modules/some-dep/index.cjs.js')).toBeTruthy()\n\n    // TypeScript files match defaultInline pattern and are inlined even with external: true\n    // because default inline patterns are checked before falling through to the end\n    expect(await resolver.shouldExternalize('/usr/a/project/src/my-file.ts')).toBe(false)\n  })\n\n  test('handles server.deps.inline as true with ssr.resolve config', async () => {\n    const resolver = await getResolver(style, {\n      server: {\n        deps: {\n          inline: true,\n        },\n      },\n    }, {\n      noExternal: ['some-dep'],\n    })\n\n    // When inline is true, everything should be inlined (except explicit external)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-dep/index.js')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/other-dep/index.js')).toBe(false)\n  })\n\n  test('merges both vitest and vite configs together', async () => {\n    const resolver = await getResolver(style, {\n      server: {\n        deps: {\n          inline: ['inline-dep-1'],\n          external: ['external-dep-1'],\n        },\n      },\n    }, {\n      noExternal: ['inline-dep-2'],\n      external: ['external-dep-2'],\n    })\n\n    // All inline deps should be inlined\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/inline-dep-1/index.js')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/inline-dep-2/index.js')).toBe(false)\n\n    // All external deps should be externalized\n    // Using .cjs.js extension which matches depsExternal pattern\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/external-dep-1/index.cjs.js')).toBeTruthy()\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/external-dep-2/index.cjs.js')).toBeTruthy()\n  })\n\n  test('respects priority: inline config is checked before external', async () => {\n    const resolver = await getResolver(style, {\n      server: {\n        deps: {\n          inline: ['my-dep'],\n          external: ['my-dep'], // same dep in both\n        },\n      },\n    }, {})\n\n    // In the resolver logic, inline is checked first (line 197) before external (line 203)\n    // So inline takes precedence\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/my-dep/index.js')).toBe(false)\n  })\n\n  test('converts wildcard patterns to regex correctly', async () => {\n    const resolver = await getResolver(style, {}, {\n      noExternal: ['@scope/*/sub', 'prefix-*-suffix'],\n    })\n\n    // Test wildcard expansion\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@scope/package/sub/index.js')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@scope/another/sub/index.js')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/prefix-middle-suffix/index.js')).toBe(false)\n\n    // Should not match incorrect patterns\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@scope/package/other/index.cjs.js')).toBeTruthy()\n  })\n\n  test('handles query parameters like ?vue, ?raw, ?url', async () => {\n    const resolver = await getResolver(style, {}, {})\n\n    // Files with Vite query parameters should be inlined (matched by defaultInline pattern)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-lib/Component.vue?vue&type=script')).toBeUndefined()\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-lib/data.txt?raw')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-lib/image.png?url')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-lib/style.css?inline')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-lib/worker.js?init')).toBe(false)\n\n    // Files without query parameters should follow normal externalization rules\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-lib/index.cjs.js')).toBeTruthy()\n  })\n\n  test('handles custom deps.moduleDirectories', async () => {\n    const resolver = await getResolver(style, {\n      deps: {\n        moduleDirectories: ['/node_modules/', '/custom_modules/'],\n      },\n      server: {\n        deps: {\n          inline: ['inline-dep'],\n        },\n      },\n    }, {})\n\n    // Should inline deps in custom module directory\n    expect(await resolver.shouldExternalize('/usr/a/project/custom_modules/inline-dep/index.js')).toBe(false)\n\n    // Should also work with standard node_modules\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/inline-dep/index.js')).toBe(false)\n\n    // Note: depsExternal pattern only matches /node_modules/, not custom directories\n    // So .cjs.js files in custom directories won't be automatically externalized\n    // Regular .js files in custom directories are inlined by default\n    expect(await resolver.shouldExternalize('/usr/a/project/custom_modules/other-dep/index.js')).toBeUndefined()\n\n    // But .cjs.js in node_modules IS externalized\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/other-dep/index.cjs.js')).toBeTruthy()\n  })\n\n  test('handles deps.moduleDirectories with ssr.resolve.noExternal', async () => {\n    const resolver = await getResolver(style, {\n      deps: {\n        moduleDirectories: ['/node_modules/', '/vendor/'],\n      },\n    }, {\n      noExternal: ['my-lib'],\n    })\n\n    // Should inline 'my-lib' from vendor directory\n    expect(await resolver.shouldExternalize('/usr/a/project/vendor/my-lib/index.js')).toBe(false)\n\n    // Should inline 'my-lib' from node_modules too\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/my-lib/index.js')).toBe(false)\n\n    // Other packages: depsExternal pattern only matches /node_modules/\n    // So regular .js files in /vendor/ are inlined by default\n    expect(await resolver.shouldExternalize('/usr/a/project/vendor/other-lib/index.js')).toBeUndefined()\n    // But .cjs.js in node_modules IS externalized\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/other-lib/index.cjs.js')).toBeTruthy()\n  })\n\n  test('handles deps.moduleDirectories with wildcard patterns', async () => {\n    const resolver = await getResolver(style, {\n      deps: {\n        moduleDirectories: ['/node_modules/', '/packages/'],\n      },\n    }, {\n      noExternal: ['@org/*'],\n    })\n\n    // Should match wildcard in custom module directory (packages)\n    expect(await resolver.shouldExternalize('/usr/a/project/packages/@org/utils/index.js')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/packages/@org/runner/index.js')).toBe(false)\n\n    // Should also match wildcard in standard node_modules\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@org/utils/index.js')).toBe(false)\n\n    // Other scopes: depsExternal pattern only matches /node_modules/\n    // So regular .js files in /packages/ are inlined by default\n    expect(await resolver.shouldExternalize('/usr/a/project/packages/@other/utils/index.js')).toBeUndefined()\n    // But .cjs.js in node_modules IS externalized\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@other/utils/index.cjs.js')).toBeTruthy()\n  })\n\n  test('combines query parameters with ssr.resolve.external', async () => {\n    const resolver = await getResolver(style, {}, {\n      external: ['some-lib'],\n    })\n\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-lib/Component.vue?vue')).toBeTruthy()\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-lib/data.txt?raw')).toBeTruthy()\n\n    // Without query parameter, should be externalized\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/some-lib/index.cjs.js')).toBeTruthy()\n  })\n\n  test('handles multiple query parameters', async () => {\n    const resolver = await getResolver(style, {}, {})\n\n    // Multiple query parameters should still be inlined\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/lib/file.js?url&used')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/lib/style.css?inline&lang=scss')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/lib/Component.vue?vue&type=template&lang=pug')).toBeUndefined()\n  })\n\n  // Test that plugins can set noExternal/external in configEnvironment hook\n  // This simulates frameworks like Astro that add their packages via configEnvironment\n  test('collects noExternal/external from plugin configEnvironment', async () => {\n    const plugin: Plugin = {\n      name: 'test-plugin',\n      configEnvironment(name) {\n        if (name === 'ssr') {\n          return {\n            resolve: {\n              noExternal: ['plugin-inline-dep', '@framework/*'],\n              external: ['plugin-external-dep'],\n            },\n          }\n        }\n      },\n    }\n\n    // Also test merging with user config\n    const resolver = await getResolver(style, {}, {\n      noExternal: ['user-inline-dep'],\n      external: ['user-external-dep'],\n    }, [plugin])\n\n    // user config noExternal: should be inlined\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/user-inline-dep/index.js')).toBe(false)\n\n    // plugin noExternal: should be inlined\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/plugin-inline-dep/index.js')).toBe(false)\n\n    // plugin noExternal with wildcard: should be inlined\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@framework/core/index.js')).toBe(false)\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@framework/utils/index.js')).toBe(false)\n\n    // user config external: should be externalized\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/user-external-dep/index.js')).toBeTruthy()\n\n    // plugin external: should be externalized\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/plugin-external-dep/index.js')).toBeTruthy()\n\n    // other deps: default behavior\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/other-dep/index.cjs.js')).toBeTruthy()\n    expect(await resolver.shouldExternalize('/usr/a/project/node_modules/@other/lib/index.cjs.js')).toBeTruthy()\n  })\n})\n\nasync function getResolver(\n  style: 'environment' | 'deprecated',\n  options: CliOptions,\n  externalOptions: {\n    external?: true | string[]\n    noExternal?: true | string | RegExp | (string | RegExp)[]\n  },\n  plugins: Plugin[] = [],\n) {\n  const ctx = await createVitest('test', {\n    watch: false,\n  }, style === 'environment'\n    ? {\n        plugins,\n        environments: {\n          ssr: {\n            resolve: externalOptions,\n          },\n        },\n        test: options,\n      }\n    : {\n        plugins,\n        ssr: externalOptions,\n        test: options,\n      })\n  onTestFinished(() => ctx.close())\n  return ctx._resolver\n}\n"
  },
  {
    "path": "test/config/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"lib\": [\"DOM\", \"ESNext\"],\n    \"types\": [\"vite/client\"]\n  },\n  \"exclude\": [\n    \"**/dist/**\"\n  ]\n}\n"
  },
  {
    "path": "test/config/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  // Note: One test expects coverage.thresholds not to be defined in here\n  test: {\n    include: ['test/**.test.ts'],\n    reporters: ['verbose'],\n    testTimeout: 60_000,\n    pool: 'forks',\n    fileParallelism: false,\n    chaiConfig: {\n      truncateThreshold: 999,\n    },\n    coverage: {\n      // test that empty reporter does not throw\n      reporter: [],\n    },\n    typecheck: {\n      ignoreSourceErrors: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/core/__mocks__/@vitest/test-fn.ts",
    "content": "import actualCreate from '@vitest/test-fn'\nimport { vi } from 'vitest'\n\n// when creating a store, we get its initial state, create a reset function and add it in the set\nexport default vi.fn((createState) => {\n  return actualCreate(createState)\n})\n"
  },
  {
    "path": "test/core/__mocks__/@vueuse/integrations/useJwt.ts",
    "content": "import { vi } from 'vitest'\nimport { ref } from 'vue'\n\nexport const useJwt = vi.fn(() => ({\n  payload: ref({\n    sub: 'login',\n    given_name: 'firstName',\n    family_name: 'lastName',\n    name: 'completeName',\n    email: 'email',\n  }),\n}))\n"
  },
  {
    "path": "test/core/__mocks__/axios/index.ts",
    "content": "import { vi } from 'vitest'\n\nexport default {\n  get: vi.fn(),\n}\n"
  },
  {
    "path": "test/core/__mocks__/custom-lib.ts",
    "content": "export default function () {\n  return 'mocked'\n}\n"
  },
  {
    "path": "test/core/__mocks__/extension.js.ts",
    "content": "export const mocked = true\n"
  },
  {
    "path": "test/core/__mocks__/fs/promises.cjs",
    "content": "// we can also use `import`, but then\n// every export should be explicitly defined\n\nconst { fs } = require('memfs')\n\nmodule.exports = fs.promises\n"
  },
  {
    "path": "test/core/__mocks__/fs.cjs",
    "content": "// we can also use `import`, but then\n// every export should be explicitly defined\n\nconst { fs } = require('memfs')\n\nmodule.exports = fs\n"
  },
  {
    "path": "test/core/__mocks__/timers.ts",
    "content": "export default {\n  clearInterval: () => 'foo',\n}\n"
  },
  {
    "path": "test/core/__mocks__/virtual-module.ts",
    "content": "export const value = 'folder'\n"
  },
  {
    "path": "test/core/__mocks__/vscode-mocks.ts",
    "content": "export const folder = true\n"
  },
  {
    "path": "test/core/deps/dep-cjs/esm-comment.js",
    "content": "// import x from \"x\"\n/** import x from \"x\" */\n/**\n * import x from \"x\"\n */\nmodule.exports = { test: 'ok' }\n"
  },
  {
    "path": "test/core/deps/dep-cjs/esm-string.js",
    "content": "module.exports = { test: ' import.meta' }\n"
  },
  {
    "path": "test/core/deps/dep-cjs/package.json",
    "content": "{\n  \"name\": \"@vitest/test-dep-cjs\",\n  \"type\": \"commonjs\",\n  \"exports\": {\n    \"./esm-comment\": \"./esm-comment.js\",\n    \"./esm-string\": \"./esm-string.js\"\n  }\n}\n"
  },
  {
    "path": "test/core/deps/dep-esm-non-existing/index.mjs",
    "content": ""
  },
  {
    "path": "test/core/deps/dep-esm-non-existing/index.mts",
    "content": "export type NonExported = true\n"
  },
  {
    "path": "test/core/deps/dep-esm-non-existing/package.json",
    "content": "{\n  \"name\": \"@test/dep-esm-non-existing\",\n  \"type\": \"module\",\n  \"main\": \"./index.mjs\"\n}\n"
  },
  {
    "path": "test/core/deps/dep-fn/index.d.ts",
    "content": "declare function create<T>(arg?: T): T\nexport default create"
  },
  {
    "path": "test/core/deps/dep-fn/index.js",
    "content": "export default function (arg) {\n  return arg ?? function () {}\n}\n"
  },
  {
    "path": "test/core/deps/dep-fn/package.json",
    "content": "{\n  \"name\": \"@vitest/test-fn\",\n  \"type\": \"module\",\n  \"exports\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/core/deps/dep-nested-cjs/index.d.ts",
    "content": "declare class Klass {\n  static clickCancel(): void\n}\nexport default Klass\n"
  },
  {
    "path": "test/core/deps/dep-nested-cjs/index.js",
    "content": "if (typeof __vite_ssr_import__ !== 'undefined') {\n  throw new TypeError('The module should be external')\n}\n\nconst Klass = class Klass {\n  static clickCancel() {\n    // noop\n  }\n}\nKlass.default = Klass\nmodule.exports = Klass\n"
  },
  {
    "path": "test/core/deps/dep-nested-cjs/package.json",
    "content": "{\n  \"name\": \"@vitest/test-dep-nested-cjs\",\n  \"type\": \"commonjs\",\n  \"main\": \"./index.js\"\n}\n"
  },
  {
    "path": "test/core/deps/dep1/esm/index.js",
    "content": "// esm/index.js was detected as isValidNodeImport(id) = false\n// event if package.json has type = module,\n// which causes dual package hazard when other external esm import esm/index.js.\nexport const data = {}\n"
  },
  {
    "path": "test/core/deps/dep1/package.json",
    "content": "{\n  \"name\": \"@vitest/test-dep1\",\n  \"type\": \"module\",\n  \"exports\": \"./esm/index.js\"\n}\n"
  },
  {
    "path": "test/core/deps/dep2/index.js",
    "content": "export { data } from '@vitest/test-dep1'\n"
  },
  {
    "path": "test/core/deps/dep2/package.json",
    "content": "{\n  \"name\": \"@vitest/test-dep2\",\n  \"type\": \"module\",\n  \"exports\": \"./index.js\",\n  \"dependencies\": {\n    \"@vitest/test-dep1\": \"file:../dep1\"\n  }\n}\n"
  },
  {
    "path": "test/core/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Core Tests</title>\n</head>\n<body>\n  Nothing is rendered\n</body>\n</html>"
  },
  {
    "path": "test/core/package.json",
    "content": "{\n  \"name\": \"@vitest/test-core\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"test:html\": \"vitest --reporter=html\",\n    \"test:threads\": \"vitest --project threads\",\n    \"test:forks\": \"vitest --project forks\",\n    \"test:vmThreads\": \"vitest --project vmThreads\",\n    \"dev\": \"vite\",\n    \"coverage\": \"vitest run --coverage\",\n    \"collect\": \"vitest list\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"catalog:\",\n    \"@babel/plugin-proposal-decorators\": \"catalog:\",\n    \"@rolldown/plugin-babel\": \"catalog:\",\n    \"@standard-schema/spec\": \"^1.1.0\",\n    \"@test/dep-esm-non-existing\": \"link:./deps/dep-esm-non-existing\",\n    \"@test/vite-environment-external\": \"link:./projects/vite-environment-external\",\n    \"@test/vite-external\": \"link:./projects/vite-external\",\n    \"@vitest/expect\": \"workspace:*\",\n    \"@vitest/mocker\": \"workspace:*\",\n    \"@vitest/runner\": \"workspace:*\",\n    \"@vitest/test-dep-cjs\": \"file:./deps/dep-cjs\",\n    \"@vitest/test-dep-nested-cjs\": \"file:./deps/dep-nested-cjs\",\n    \"@vitest/test-dep1\": \"file:./deps/dep1\",\n    \"@vitest/test-dep2\": \"file:./deps/dep2\",\n    \"@vitest/test-fn\": \"file:./deps/dep-fn\",\n    \"@vitest/utils\": \"workspace:*\",\n    \"@vitest/web-worker\": \"workspace:^\",\n    \"@vueuse/integrations\": \"^14.2.1\",\n    \"axios\": \"^1.13.4\",\n    \"immutable\": \"5.1.5\",\n    \"memfs\": \"^4.56.11\",\n    \"obug\": \"^2.1.1\",\n    \"react\": \"^19.2.4\",\n    \"react-18\": \"npm:react@18.3.1\",\n    \"temporal-polyfill\": \"~0.3.0\",\n    \"tinyrainbow\": \"catalog:\",\n    \"tinyspy\": \"^4.0.4\",\n    \"url\": \"^0.11.4\",\n    \"vitest\": \"workspace:*\",\n    \"vitest-environment-custom\": \"file:./vitest-environment-custom\",\n    \"vitest-package-exports\": \"^1.2.0\",\n    \"vue\": \"catalog:\"\n  }\n}\n"
  },
  {
    "path": "test/core/projects/custom-lib/index.js",
    "content": "export default function () {\n  // module doesn't exist in Node.js ESM, but exists in vite-node\n  return typeof module\n}\n"
  },
  {
    "path": "test/core/projects/custom-lib/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "test/core/projects/inline-lib/index.js",
    "content": "export default function () {\n  // module doesn't exist in Node.js ESM, but exists in vite-node\n  return typeof module\n}\n"
  },
  {
    "path": "test/core/projects/inline-lib/package.json",
    "content": "{\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "test/core/projects/vite-environment-external/index.d.ts",
    "content": "export declare const external: boolean\n"
  },
  {
    "path": "test/core/projects/vite-environment-external/index.js",
    "content": "export const external = typeof __vite_ssr_import__ === 'undefined'\n"
  },
  {
    "path": "test/core/projects/vite-environment-external/package.json",
    "content": "{\n  \"name\": \"@test/vite-environment-external\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "test/core/projects/vite-external/index.d.ts",
    "content": "export declare const external: boolean\n"
  },
  {
    "path": "test/core/projects/vite-external/index.js",
    "content": "export const external = typeof __vite_ssr_import__ === 'undefined'\n"
  },
  {
    "path": "test/core/projects/vite-external/package.json",
    "content": "{\n  \"name\": \"@test/vite-external\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "test/core/src/__mocks__/submodule.ts",
    "content": "export const two = 1 + 1 + 1\n"
  },
  {
    "path": "test/core/src/aliased-mod.ts",
    "content": "export const isAliased = true\n"
  },
  {
    "path": "test/core/src/circularA.ts",
    "content": "import { circularB } from './circularB'\n\nexport const CalledB: number[] = []\n\nexport function circularA() {\n  return circularB()\n}\n"
  },
  {
    "path": "test/core/src/circularB.ts",
    "content": "import { CalledB } from './circularA'\n\nexport function circularB() {\n  return CalledB.push(CalledB.length)\n}\n"
  },
  {
    "path": "test/core/src/cjs/array-cjs.js",
    "content": "module.exports = [1, '2']\n"
  },
  {
    "path": "test/core/src/cjs/bare-cjs.js",
    "content": "module.exports = { c: 'c' }\nexports.a = 'a'\nexports.b = 'b'\n"
  },
  {
    "path": "test/core/src/cjs/class-cjs.js",
    "content": "class Test {\n  variable = 1\n}\n\nmodule.exports = new Test()\nmodule.exports.Test = Test\n"
  },
  {
    "path": "test/core/src/cjs/default-function.d.ts",
    "content": "declare function format(): string\n\nexport default format\n"
  },
  {
    "path": "test/core/src/cjs/default-function.js",
    "content": "'use strict'\n\nfunction format() {\n  return ''\n}\n\nmodule.exports = format\nmodule.exports.default = format\n"
  },
  {
    "path": "test/core/src/cjs/module-cjs.ts",
    "content": "module.exports.a = 1\nmodule.exports.b = 2\n"
  },
  {
    "path": "test/core/src/cjs/nested-default-cjs.js",
    "content": "exports.default = {\n  a: 'a',\n  b: 'b',\n  object: {\n    h: 'h',\n  },\n}\nObject.defineProperty(exports, '__esModule', { value: true, enumerable: false })\n"
  },
  {
    "path": "test/core/src/cjs/primitive-cjs.js",
    "content": "module.exports = 'string'\nexports.a = 'a'\n"
  },
  {
    "path": "test/core/src/cjs/promise-export.js",
    "content": "module.exports = Promise.resolve({ value: 42 })\n"
  },
  {
    "path": "test/core/src/cjs/prototype-cjs.js",
    "content": "exports.test = () => {\n  // eslint-disable-next-line no-prototype-builtins\n  return exports.hasOwnProperty('test')\n}\nexports.getPrototype = () => {\n  return Object.getPrototypeOf(exports)\n}\n"
  },
  {
    "path": "test/core/src/class-inheritence/bar.ts",
    "content": "import { Foo } from './foo.js'\n\nexport class Bar extends Foo {\n  override doSomething(): boolean {\n    return true\n  }\n\n  doSomethingElse(): boolean {\n    return true\n  }\n}\n"
  },
  {
    "path": "test/core/src/class-inheritence/foo.ts",
    "content": "export class Foo {\n  doSomething(): boolean {\n    return false\n  }\n\n  unused() {\n    //\n  }\n}\n"
  },
  {
    "path": "test/core/src/custom/gardener.ts",
    "content": "export class Gardener {\n  _state = 'wake up'\n\n  states: string[] = [this._state]\n\n  get state() {\n    return this._state\n  }\n\n  set state(state: string) {\n    this._state = state\n    this.states.push(state)\n  }\n\n  putWorkingClothes() {\n    this.state = 'working clothes'\n  }\n\n  weedTheGrass() {\n    this.state = 'weed the grass'\n  }\n\n  mowerTheLawn() {\n    this.state = 'mower the lawn'\n  }\n\n  waterFlowers() {\n    this.state = 'water flowers'\n  }\n\n  rest() {\n    this.state = 'rest'\n  }\n\n  standup() {\n    this.state = 'standup'\n  }\n\n  goHome() {\n    this.state = 'home'\n  }\n}\n"
  },
  {
    "path": "test/core/src/dynamic-import.ts",
    "content": "export async function dynamicImport(name: string) {\n  const pkg = await import(name)\n  return pkg\n}\n"
  },
  {
    "path": "test/core/src/env.ts",
    "content": "export function getAuthToken() {\n  return import.meta.env.AUTH_TOKEN\n}\n"
  },
  {
    "path": "test/core/src/esm/esm.js",
    "content": "export const test = 1\n"
  },
  {
    "path": "test/core/src/esm/internal-esm.mjs",
    "content": "export * from 'tinyspy'\n"
  },
  {
    "path": "test/core/src/esm/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "test/core/src/exec.ts",
    "content": "/* eslint-disable import/no-duplicates */\nimport { exec } from 'node:child_process'\nimport * as child_process from 'node:child_process'\nimport defaultProcess from 'node:child_process'\n\nexport function execHelloWorld() {\n  exec('hello world')\n}\n\nexport function execImportAll() {\n  child_process.exec('import all')\n}\n\nexport function execDefault() {\n  defaultProcess.exec('default')\n}\n"
  },
  {
    "path": "test/core/src/external/default-cjs.js",
    "content": "module.exports = {\n  a: 'a',\n  b: 'b',\n  object: {\n    h: 'h',\n  },\n}\n"
  },
  {
    "path": "test/core/src/external/nested-default-cjs.js",
    "content": "exports.default = {\n  a: 'a',\n  b: 'b',\n  object: {\n    h: 'h',\n  },\n}\nObject.defineProperty(exports, '__esModule', { value: true, enumerable: false })\n"
  },
  {
    "path": "test/core/src/external/package.json",
    "content": "{ \"type\": \"commonjs\" }\n"
  },
  {
    "path": "test/core/src/external/pkg-browser/index.d.ts",
    "content": "export default ''\n"
  },
  {
    "path": "test/core/src/external/pkg-browser/package.json",
    "content": "{\n  \"type\": \"module\",\n  \"exports\": {\n    \"types\": \"./index.d.ts\",\n    \"browser\": \"./web.js\",\n    \"node\": \"./ssr.js\"\n  }\n}\n"
  },
  {
    "path": "test/core/src/external/pkg-browser/ssr.js",
    "content": "export default 'ssr'\n"
  },
  {
    "path": "test/core/src/external/pkg-browser/web.js",
    "content": "export default 'web'\n"
  },
  {
    "path": "test/core/src/external/pkg-node/index.d.ts",
    "content": "export default ''\n"
  },
  {
    "path": "test/core/src/external/pkg-node/package.json",
    "content": "{\n  \"type\": \"module\",\n  \"exports\": {\n    \"types\": \"./index.d.ts\",\n    \"node\": \"./ssr.js\",\n    \"browser\": \"./web.js\"\n  }\n}\n"
  },
  {
    "path": "test/core/src/external/pkg-node/ssr.js",
    "content": "export default 'ssr'\n"
  },
  {
    "path": "test/core/src/external/pkg-node/web.js",
    "content": "export default 'web'\n"
  },
  {
    "path": "test/core/src/file-css.css",
    "content": ".red {\n  color: red;\n}\n"
  },
  {
    "path": "test/core/src/file-less.less",
    "content": "@color: red;\n\n.red {\n  color: @color;\n}"
  },
  {
    "path": "test/core/src/file-sass.sass",
    "content": ".red\n  color: red;\n"
  },
  {
    "path": "test/core/src/file-scss.scss",
    "content": ".red {\n  color: red;\n}\n"
  },
  {
    "path": "test/core/src/file-txt.txt",
    "content": "text\n"
  },
  {
    "path": "test/core/src/global-mock.ts",
    "content": "export const mocked = false\n"
  },
  {
    "path": "test/core/src/in-source/add.ts",
    "content": "export function add(...args: number[]) {\n  return args.reduce((a, b) => a + b, 0)\n}\n\n// in-source test suites\nif (import.meta.vitest) {\n  const { it, expect } = import.meta.vitest\n  it('add', () => {\n    expect(add()).toBe(0)\n    expect(add(1)).toBe(1)\n    expect(add(1, 2, 3)).toBe(6)\n  })\n}\n"
  },
  {
    "path": "test/core/src/in-source/fibonacci.ts",
    "content": "import { add } from './add'\n\nexport function fibonacci(n: number): number {\n  if (n < 2) {\n    return n\n  }\n  return add(fibonacci(n - 1), fibonacci(n - 2))\n}\n\nif (import.meta.vitest) {\n  const { it, expect } = import.meta.vitest\n  it('fibonacci', () => {\n    expect(fibonacci(0)).toBe(0)\n    expect(fibonacci(1)).toBe(1)\n    expect(fibonacci(2)).toBe(1)\n    expect(fibonacci(3)).toBe(2)\n    expect(fibonacci(4)).toBe(3)\n    expect(fibonacci(5)).toBe(5)\n    expect(fibonacci(6)).toBe(8)\n    expect(fibonacci(7)).toBe(13)\n    expect(fibonacci(8)).toBe(21)\n    expect(fibonacci(9)).toMatchInlineSnapshot('34')\n  })\n}\n"
  },
  {
    "path": "test/core/src/in-source/index.ts",
    "content": "export * from './add'\nexport * from './fibonacci'\n"
  },
  {
    "path": "test/core/src/mockedA.ts",
    "content": "export function mockedA() {\n  return 'A'\n}\n"
  },
  {
    "path": "test/core/src/mockedB.ts",
    "content": "import { mockedA } from './mockedA'\n\nexport function mockedB() {\n  return mockedA()\n}\n"
  },
  {
    "path": "test/core/src/mockedC.ts",
    "content": "import { mockedA } from './mockedA'\n\nexport class MockedC {\n  public value: number\n\n  constructor() {\n    this.value = 42\n  }\n\n  public doSomething() {\n    return mockedA()\n  }\n\n  get getOnlyProp(): number {\n    return 42\n  }\n\n  get getSetProp(): number {\n    return 123\n  }\n\n  set getSetProp(_val: number) {}\n\n  get getExpectNotCalled(): number {\n    throw new Error('automocked constructor should not call this getter')\n  }\n}\n\nexport async function asyncFunc(): Promise<string> {\n  await new Promise<void>(resolve => resolve())\n  return '1234'\n}\n\n// This is here because mocking streams previously caused some problems (#1671).\nexport const exportedStream = process.stderr\n"
  },
  {
    "path": "test/core/src/mockedD.ts",
    "content": "import { MockedC } from './mockedC'\n\nexport default MockedC\nexport * from './mockedC'\n"
  },
  {
    "path": "test/core/src/mockedE.ts",
    "content": "export const symbolFn = Symbol.for('symbolFn')\n\nexport class MockedE {\n  public testFn(arg: string) {\n    return arg.repeat(2)\n  }\n\n  public [symbolFn](arg: string) {\n    return arg.repeat(2)\n  }\n}\n"
  },
  {
    "path": "test/core/src/mocks/A.ts",
    "content": "import { funcB } from './B.js'\n\nexport function funcA() {\n  return funcB\n}\n"
  },
  {
    "path": "test/core/src/mocks/B.ts",
    "content": "import { funcA } from './A.js'\n\nexport function funcB() {\n  return funcA\n}\n"
  },
  {
    "path": "test/core/src/mocks/autospying-namespace/index.ts",
    "content": "export * as NamespaceTarget from './namespaceTarget.js'\n"
  },
  {
    "path": "test/core/src/mocks/autospying-namespace/namespaceTarget.ts",
    "content": "export const computeSquare = (n: number) => n * n\n"
  },
  {
    "path": "test/core/src/mocks/cyclic-deps/module-1.mjs",
    "content": "import './module-2'\n"
  },
  {
    "path": "test/core/src/mocks/cyclic-deps/module-2.mjs",
    "content": "import './module-3'\n"
  },
  {
    "path": "test/core/src/mocks/cyclic-deps/module-3.mjs",
    "content": "import './module-4'\n"
  },
  {
    "path": "test/core/src/mocks/cyclic-deps/module-4.mjs",
    "content": "import './module-1'\n"
  },
  {
    "path": "test/core/src/mocks/default.ts",
    "content": "export default 'a default'\n"
  },
  {
    "path": "test/core/src/mocks/dynamic-module.d.ts",
    "content": "export {}\n"
  },
  {
    "path": "test/core/src/mocks/dynamic-module.js",
    "content": "export {}\n"
  },
  {
    "path": "test/core/src/mocks/example.ts",
    "content": "export function square(a: number, b: number) {\n  return a * b\n}\nexport async function asyncSquare(a: number, b: number) {\n  const result = (await a) * b\n  return result\n}\nexport const someClasses = new (class Bar {\n  public array: number[]\n  constructor() {\n    this.array = [1, 2, 3]\n  }\n\n  foo() {}\n})()\nexport const object = {\n  baz: 'foo',\n  bar: {\n    fiz: 1,\n    buzz: [1, 2, 3],\n  },\n}\nexport const array = [1, 2, 3]\nexport const number = 123\nexport const string = 'baz'\nexport const boolean = true\nexport const symbol = Symbol.for('a.b.c')\nexport default 'a default'\n"
  },
  {
    "path": "test/core/src/mocks/export-default-circle-b.ts",
    "content": "import b from './export-default-circle-index.js'\n\nexport default function (): any {\n  return b()\n}\n"
  },
  {
    "path": "test/core/src/mocks/export-default-circle-index.ts",
    "content": "import b from './export-default-circle-b.js'\n\nexport default function (): any {\n  return b()\n}\n"
  },
  {
    "path": "test/core/src/mocks/external/cjs-pseudoesm.cjs",
    "content": "function fn() {}\n\nexports.fn = fn\nObject.defineProperty(exports, '__esModule', { value: true, enumerable: false })\n"
  },
  {
    "path": "test/core/src/mocks/external/default-cjs.cjs",
    "content": "module.exports = require('./cjs-pseudoesm.cjs')\n"
  },
  {
    "path": "test/core/src/mocks/external/default-function.cjs",
    "content": "module.exports = function () {\n  return true\n}\n"
  },
  {
    "path": "test/core/src/mocks/external/external.mjs",
    "content": "import { vi } from 'vitest'\n\nvi.doMock('axios')\n"
  },
  {
    "path": "test/core/src/mocks/has space in path.ts",
    "content": "export const thisIsOk = false\n"
  },
  {
    "path": "test/core/src/mocks/integration.ts",
    "content": "import { useJwt } from '@vueuse/integrations/useJwt'\nimport { ref } from 'vue'\n\nexport function createStore() {\n  const encoded = ref('123')\n  const { payload } = useJwt(encoded)\n\n  return { payload }\n}\n"
  },
  {
    "path": "test/core/src/mocks/log.ts",
    "content": "const writeSym = Symbol('write')\nconst proto = {\n  [writeSym]() {\n    return 'hello'\n  },\n}\nconst logger = {\n  warn() {\n    ;(this as any)[writeSym]()\n  },\n}\nObject.setPrototypeOf(logger, proto)\nexport default logger\n"
  },
  {
    "path": "test/core/src/mocks/main.js",
    "content": "import { funcA } from './A'\nimport { funcB } from './B'\n\nexport function main() {\n  return funcA()\n}\n\nexport function mainB() {\n  return funcB()\n}\n"
  },
  {
    "path": "test/core/src/mocks/moduleA.ts",
    "content": "export const A = 'A'\n"
  },
  {
    "path": "test/core/src/mocks/moduleB.ts",
    "content": "export const A = 'A'\nexport const B = 'B'\n"
  },
  {
    "path": "test/core/src/mocks/moduleWithSymbol.ts",
    "content": "const methodSymbol = Symbol('x')\n\nconst moduleWithSymbol = {\n  warn() {\n    return this[methodSymbol]()\n  },\n  [methodSymbol]() {\n    return 'hello'\n  },\n}\n\nexport { methodSymbol, moduleWithSymbol }\n"
  },
  {
    "path": "test/core/src/mocks/retry-dynamic-import.ts",
    "content": "export async function retryDynamicImport() {\n  let retryTimes = 0\n  const load = async (): Promise<unknown> => {\n    try {\n      return await import('./dynamic-module')\n    }\n    catch {\n      if (retryTimes === 3) {\n        throw new Error('import dynamic module failed.')\n      }\n      retryTimes += 1\n      return await load()\n    }\n  }\n\n  return await load()\n}\n"
  },
  {
    "path": "test/core/src/mocks/set-foo.ts",
    "content": "import { afterEach, beforeEach } from 'vitest'\n\n// eslint-disable-next-line import/no-mutable-exports\nexport let foo: number\n\nbeforeEach(() => {\n  foo = 1\n})\n\nafterEach(() => {\n  foo = 2\n})\n"
  },
  {
    "path": "test/core/src/mocks/squared.js",
    "content": "export function squared() {\n\n}\n"
  },
  {
    "path": "test/core/src/mocks/test-fn-magic.ts",
    "content": "import fn from '@vitest/test-fn'\n\nexport function magic() {\n  return fn()\n}\n"
  },
  {
    "path": "test/core/src/module-esm.ts",
    "content": "const c = 1\nexport default c\nexport const d = 2\n"
  },
  {
    "path": "test/core/src/read-hello-world.ts",
    "content": "// hello-world.js\nimport { readFileSync } from 'node:fs'\n\nexport function readHelloWorld(path: string) {\n  return readFileSync(path, 'utf-8')\n}\n"
  },
  {
    "path": "test/core/src/relative-import.ts",
    "content": "export function dynamicRelativeImport(file: string) {\n  return import(/* @vite-ignore */ `./${file}.ts`)\n}\n"
  },
  {
    "path": "test/core/src/rely-on-hoisted.ts",
    "content": "// @ts-expect-error not typed global\nexport const value = globalThis.someGlobalValue\n"
  },
  {
    "path": "test/core/src/self/foo.ts",
    "content": "/* eslint-disable */\n\nexport function foo(): true {\n  return true;\n}"
  },
  {
    "path": "test/core/src/self/index.ts",
    "content": "/* eslint-disable */\n\nexport * from './foo';\nexport * from './index'; // <-- wrong"
  },
  {
    "path": "test/core/src/submodule.ts",
    "content": "export const two = 1 + 1\n"
  },
  {
    "path": "test/core/src/timeout.ts",
    "content": "export const timeout = 100\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen/README.md",
    "content": "copied from https://github.com/jestjs/jest/tree/28d32c6a1e48f1e4c946a8e6adbe2ae9af4103e3/e2e/native-esm/wasm-bindgen\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen/index.js",
    "content": "/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n// folder source: https://github.com/rustwasm/wasm-bindgen/tree/4f865308afbe8d2463968457711ad356bae63b71/examples/hello_world\n// docs: https://rustwasm.github.io/docs/wasm-bindgen/examples/hello-world.html\n\n// eslint-disable-next-line unused-imports/no-unused-imports, import/newline-after-import, no-unused-vars\nimport * as wasm from './index_bg.wasm'\nexport * from './index_bg.js'\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen/index_bg.js",
    "content": "/* eslint-disable no-alert */\n/* eslint-disable prefer-rest-params */\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport * as wasm from './index_bg.wasm'\n\nconst LTextDecoder\n  = typeof TextDecoder === 'undefined'\n    ? (0, module.require)('util').TextDecoder\n    : TextDecoder\n\nconst cachedTextDecoder = new LTextDecoder('utf-8', {\n  fatal: true,\n  ignoreBOM: true,\n})\n\ncachedTextDecoder.decode()\n\nlet cachedUint8Memory0 = new Uint8Array()\n\nfunction getUint8Memory0() {\n  if (cachedUint8Memory0.byteLength === 0) {\n    cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer)\n  }\n\n  return cachedUint8Memory0\n}\n\nfunction getStringFromWasm0(ptr, len) {\n  return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len))\n}\n\nfunction logError(f, args) {\n  try {\n    return f.apply(this, args)\n  }\n  catch (e) {\n    const error = (function () {\n      try {\n        return e instanceof Error\n          ? `${e.message}\\n\\nStack:\\n${e.stack}`\n          : e.toString()\n      }\n      catch {\n        return '<failed to stringify thrown value>'\n      }\n    })()\n    console.error(\n      'wasm-bindgen: imported JS function that was not marked as `catch` threw an error:',\n      error,\n    )\n    throw e\n  }\n}\n\nlet WASM_VECTOR_LEN = 0\n\nconst LTextEncoder\n  = typeof TextEncoder === 'undefined'\n    ? (0, module.require)('util').TextEncoder\n    : TextEncoder\n\nconst cachedTextEncoder = new LTextEncoder('utf-8')\n\nconst encodeString\n  = typeof cachedTextEncoder.encodeInto === 'function'\n    ? function (arg, view) {\n      return cachedTextEncoder.encodeInto(arg, view)\n    }\n    : function (arg, view) {\n      const buf = cachedTextEncoder.encode(arg)\n      view.set(buf)\n      return {\n        read: arg.length,\n        written: buf.length,\n      }\n    }\n\nfunction passStringToWasm0(arg, malloc, realloc) {\n  if (typeof arg !== 'string') {\n    throw new TypeError('expected a string argument')\n  }\n\n  if (realloc === undefined) {\n    const buf = cachedTextEncoder.encode(arg)\n    const ptr = malloc(buf.length)\n    getUint8Memory0()\n      .subarray(ptr, ptr + buf.length)\n      .set(buf)\n    WASM_VECTOR_LEN = buf.length\n    return ptr\n  }\n\n  let len = arg.length\n  let ptr = malloc(len)\n\n  const mem = getUint8Memory0()\n\n  let offset = 0\n\n  for (; offset < len; offset++) {\n    const code = arg.charCodeAt(offset)\n    if (code > 0x7F) {\n      break\n    }\n    mem[ptr + offset] = code\n  }\n\n  if (offset !== len) {\n    if (offset !== 0) {\n      arg = arg.slice(offset)\n    }\n\n    ptr = realloc(ptr, len, (len = offset + arg.length * 3))\n    const view = getUint8Memory0().subarray(ptr + offset, ptr + len)\n    const ret = encodeString(arg, view)\n    if (ret.read !== arg.length) {\n      throw new Error('failed to pass whole string')\n    }\n    offset += ret.written\n  }\n\n  WASM_VECTOR_LEN = offset\n  return ptr\n}\n/**\n * @param {string} name\n */\nexport function greet(name) {\n  const ptr0 = passStringToWasm0(\n    name,\n    wasm.__wbindgen_malloc,\n    wasm.__wbindgen_realloc,\n  )\n  const len0 = WASM_VECTOR_LEN\n  wasm.greet(ptr0, len0)\n}\n\nexport function __wbg_alert_9ea5a791b0d4c7a3() {\n  return logError((arg0, arg1) => {\n    alert(getStringFromWasm0(arg0, arg1))\n  }, arguments)\n}\n\nexport function __wbindgen_throw(arg0, arg1) {\n  throw new Error(getStringFromWasm0(arg0, arg1))\n}\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen-no-cyclic/README.md",
    "content": "The recent version of the wasm-bindgen bundler output does not use cyclic imports between wasm and js.\n\nFor this non-cyclic version to work, both `index_bg.js` and `index_bg.wasm` need to be externalized\nsince otherwise a dual package hazard on `index_bg.js` would make it non-functional.\n\nThe code is copied from https://github.com/rustwasm/wasm-bindgen/tree/8198d2d25920e1f4fc593e9f8eb9d199e004d731/examples/hello_world\n\n```sh\nnpm i\nnpm run build\n# then\n# 1. copy `examples/hello_world/pkg` to this directory\n# 2. add { \"type\": \"module\" } to `package.json`\n#    (this will be automatically included after https://github.com/rustwasm/wasm-pack/pull/1061)\n```\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen-no-cyclic/index.d.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n/**\n* @param {string} name\n*/\nexport function greet(name: string): void;\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen-no-cyclic/index.js",
    "content": "import * as wasm from \"./index_bg.wasm\";\nimport { __wbg_set_wasm } from \"./index_bg.js\";\n__wbg_set_wasm(wasm);\nexport * from \"./index_bg.js\";\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen-no-cyclic/index_bg.js",
    "content": "let wasm;\nexport function __wbg_set_wasm(val) {\n    wasm = val;\n}\n\n\nconst lTextDecoder = typeof TextDecoder === 'undefined' ? (0, module.require)('util').TextDecoder : TextDecoder;\n\nlet cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true });\n\ncachedTextDecoder.decode();\n\nlet cachedUint8Memory0 = null;\n\nfunction getUint8Memory0() {\n    if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {\n        cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);\n    }\n    return cachedUint8Memory0;\n}\n\nfunction getStringFromWasm0(ptr, len) {\n    ptr = ptr >>> 0;\n    return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));\n}\n\nfunction logError(f, args) {\n    try {\n        return f.apply(this, args);\n    } catch (e) {\n        let error = (function () {\n            try {\n                return e instanceof Error ? `${e.message}\\n\\nStack:\\n${e.stack}` : e.toString();\n            } catch(_) {\n                return \"<failed to stringify thrown value>\";\n            }\n        }());\n        console.error(\"wasm-bindgen: imported JS function that was not marked as `catch` threw an error:\", error);\n        throw e;\n    }\n}\n\nlet WASM_VECTOR_LEN = 0;\n\nconst lTextEncoder = typeof TextEncoder === 'undefined' ? (0, module.require)('util').TextEncoder : TextEncoder;\n\nlet cachedTextEncoder = new lTextEncoder('utf-8');\n\nconst encodeString = (typeof cachedTextEncoder.encodeInto === 'function'\n    ? function (arg, view) {\n    return cachedTextEncoder.encodeInto(arg, view);\n}\n    : function (arg, view) {\n    const buf = cachedTextEncoder.encode(arg);\n    view.set(buf);\n    return {\n        read: arg.length,\n        written: buf.length\n    };\n});\n\nfunction passStringToWasm0(arg, malloc, realloc) {\n\n    if (typeof(arg) !== 'string') throw new Error('expected a string argument');\n\n    if (realloc === undefined) {\n        const buf = cachedTextEncoder.encode(arg);\n        const ptr = malloc(buf.length, 1) >>> 0;\n        getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);\n        WASM_VECTOR_LEN = buf.length;\n        return ptr;\n    }\n\n    let len = arg.length;\n    let ptr = malloc(len, 1) >>> 0;\n\n    const mem = getUint8Memory0();\n\n    let offset = 0;\n\n    for (; offset < len; offset++) {\n        const code = arg.charCodeAt(offset);\n        if (code > 0x7F) break;\n        mem[ptr + offset] = code;\n    }\n\n    if (offset !== len) {\n        if (offset !== 0) {\n            arg = arg.slice(offset);\n        }\n        ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;\n        const view = getUint8Memory0().subarray(ptr + offset, ptr + len);\n        const ret = encodeString(arg, view);\n        if (ret.read !== arg.length) throw new Error('failed to pass whole string');\n        offset += ret.written;\n    }\n\n    WASM_VECTOR_LEN = offset;\n    return ptr;\n}\n/**\n* @param {string} name\n*/\nexport function greet(name) {\n    const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n    const len0 = WASM_VECTOR_LEN;\n    wasm.greet(ptr0, len0);\n}\n\nexport function __wbg_alert_9ea5a791b0d4c7a3() { return logError(function (arg0, arg1) {\n    alert(getStringFromWasm0(arg0, arg1));\n}, arguments) };\n\nexport function __wbindgen_throw(arg0, arg1) {\n    throw new Error(getStringFromWasm0(arg0, arg1));\n};\n\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen-no-cyclic/index_bg.wasm.d.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\nexport const memory: WebAssembly.Memory;\nexport function greet(a: number, b: number): void;\nexport function __wbindgen_malloc(a: number, b: number): number;\nexport function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;\n"
  },
  {
    "path": "test/core/src/wasm/wasm-bindgen-no-cyclic/package.json",
    "content": "{\n  \"type\": \"module\",\n  \"name\": \"hello_world\",\n  \"collaborators\": [\n    \"The wasm-bindgen Developers\"\n  ],\n  \"version\": \"0.1.0\",\n  \"files\": [\n    \"index_bg.wasm\",\n    \"index.js\",\n    \"index_bg.js\",\n    \"index.d.ts\"\n  ],\n  \"module\": \"index.js\",\n  \"types\": \"index.d.ts\",\n  \"sideEffects\": [\n    \"./index.js\",\n    \"./snippets/*\"\n  ]\n}\n"
  },
  {
    "path": "test/core/src/web-worker/eventListenerWorker.ts",
    "content": "function callback(e: MessageEvent) {\n  self.postMessage(`${e.data} world`)\n  self.removeEventListener('message', callback)\n}\n\nself.addEventListener('message', callback)\n"
  },
  {
    "path": "test/core/src/web-worker/mock/worker-dep.ts",
    "content": "export function workerDep() {\n  return 'workerDep'\n}\n"
  },
  {
    "path": "test/core/src/web-worker/mock/worker.ts",
    "content": "import { workerDep } from './worker-dep'\n\nself.postMessage(workerDep())\n"
  },
  {
    "path": "test/core/src/web-worker/objectWorker.ts",
    "content": "self.onmessage = (e) => {\n  self.postMessage(e.data)\n}\n"
  },
  {
    "path": "test/core/src/web-worker/selfWorker.ts",
    "content": "import subSelf from './selfWorkerDep'\n\nself.postMessage(subSelf === self)\n"
  },
  {
    "path": "test/core/src/web-worker/selfWorkerDep.ts",
    "content": "export default self\n"
  },
  {
    "path": "test/core/src/web-worker/sharedWorker.ts",
    "content": "self.addEventListener('connect', (event) => {\n  const e = event as MessageEvent\n  const port = e.ports[0]\n\n  port.onmessage = (e) => {\n    port.postMessage(e.data)\n  }\n\n  port.start()\n})\n"
  },
  {
    "path": "test/core/src/web-worker/worker-globals.ts",
    "content": "self.onmessage = () => {\n  self.postMessage({\n    crypto: !!self.crypto,\n    caches: !!self.caches,\n    location: !!self.location,\n    origin: self.origin,\n  })\n}\n"
  },
  {
    "path": "test/core/src/web-worker/worker.ts",
    "content": "self.onmessage = (e) => {\n  self.postMessage(`${e.data} world`)\n\n  const port = e.ports[0]\n  if (port) {\n    port.postMessage(`${e.data} world via port`)\n  }\n}\n"
  },
  {
    "path": "test/core/test/__snapshots__/injector-mock.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if awaited assigned vi.hoisted is called inside vi.mock 1`] = `\"Cannot call vi.hoisted() inside vi.mock('./mocked'): both methods are hoisted to the top of the file and not actually called inside each other.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if awaited assigned vi.hoisted is called inside vi.mock 2`] = `\n\"      2|\n      3| vi.mock('./mocked', async () => {\n      4|   const variable = await vi.hoisted(() => 1)\n       |                          ^\n      5| })\n      6|\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if awaited vi.hoisted is called inside vi.mock 1`] = `\"Cannot call vi.hoisted() inside vi.mock('./mocked'): both methods are hoisted to the top of the file and not actually called inside each other.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if awaited vi.hoisted is called inside vi.mock 2`] = `\n\"      2|\n      3| vi.mock('./mocked', async () => {\n      4|   await vi.hoisted(() => 1)\n       |         ^\n      5| })\n      6|\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if awaited vi.hoisted is exported as default export 1`] = `\"Cannot export hoisted variable. You can control hoisting behavior by placing the import from this file first.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if awaited vi.hoisted is exported as default export 2`] = `\n\"      1| import { vi } from 'vitest'\n      2|\n      3| export default await vi.hoisted(async () => {\n       | ^\n      4|   return {}\n      5| })\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if awaited vi.hoisted is exported as named export 1`] = `\"Cannot export hoisted variable. You can control hoisting behavior by placing the import from this file first.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if awaited vi.hoisted is exported as named export 2`] = `\n\"      1| import { vi } from 'vitest'\n      2|\n      3| export const values = await vi.hoisted(async () => {\n       | ^\n      4|   return {}\n      5| })\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.hoisted is called inside vi.mock 1`] = `\"Cannot call vi.hoisted() inside vi.mock('./mocked'): both methods are hoisted to the top of the file and not actually called inside each other.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.hoisted is called inside vi.mock 2`] = `\n\"      2|\n      3| vi.mock('./mocked', () => {\n      4|   const variable = vi.hoisted(() => 1)\n       |                    ^\n      5|   console.log(variable)\n      6| })\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.hoisted is exported as a named export 1`] = `\"Cannot export hoisted variable. You can control hoisting behavior by placing the import from this file first.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.hoisted is exported as a named export 2`] = `\n\"      1| import { vi } from 'vitest'\n      2|\n      3| export const values = vi.hoisted(async () => {\n       | ^\n      4|   return {}\n      5| })\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.hoisted is exported as default 1`] = `\"Cannot export hoisted variable. You can control hoisting behavior by placing the import from this file first.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.hoisted is exported as default 2`] = `\n\"      1| import { vi } from 'vitest'\n      2|\n      3| export default vi.hoisted(() => {\n       | ^\n      4|   return {}\n      5| })\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock inside vi.hoisted 1`] = `\"Cannot call vi.mock('./mocked') inside vi.hoisted(): both methods are hoisted to the top of the file and not actually called inside each other.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock inside vi.hoisted 2`] = `\n\"      2|\n      3| vi.hoisted(() => {\n      4|   vi.mock('./mocked')\n       |   ^\n      5| })\n      6|\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is called inside assigned awaited vi.hoisted 1`] = `\"Cannot call vi.mock('./mocked') inside vi.hoisted(): both methods are hoisted to the top of the file and not actually called inside each other.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is called inside assigned awaited vi.hoisted 2`] = `\n\"      2|\n      3| const values = await vi.hoisted(async () => {\n      4|   vi.mock('./mocked')\n       |   ^\n      5| })\n      6|\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is called inside assigned vi.hoisted 1`] = `\"Cannot call vi.mock('./mocked') inside vi.hoisted(): both methods are hoisted to the top of the file and not actually called inside each other.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is called inside assigned vi.hoisted 2`] = `\n\"      2|\n      3| const values = vi.hoisted(() => {\n      4|   vi.mock('./mocked')\n       |   ^\n      5| })\n      6|\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is called inside awaited vi.hoisted 1`] = `\"Cannot call vi.mock('./mocked') inside vi.hoisted(): both methods are hoisted to the top of the file and not actually called inside each other.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is called inside awaited vi.hoisted 2`] = `\n\"      2|\n      3| await vi.hoisted(async () => {\n      4|   vi.mock('./mocked')\n       |   ^\n      5| })\n      6|\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is exported as a named export 1`] = `\"Cannot export the result of \"vi.mock\". Remove export declaration because \"vi.mock\" doesn't return anything.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is exported as a named export 2`] = `\n\"      1| import { vi } from 'vitest'\n      2|\n      3| export const mocked = vi.mock('./mocked')\n       | ^\n      4|\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is exported as default export 1`] = `\"Cannot export the result of \"vi.mock\". Remove export declaration because \"vi.mock\" doesn't return anything.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.mock is exported as default export 2`] = `\n\"      1| import { vi } from 'vitest'\n      2|\n      3| export default vi.mock('./mocked')\n       | ^\n      4|\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.unmock is exported as a named export 1`] = `\"Cannot export the result of \"vi.unmock\". Remove export declaration because \"vi.unmock\" doesn't return anything.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.unmock is exported as a named export 2`] = `\n\"      1| import { vi } from 'vitest'\n      2|\n      3| export const mocked = vi.unmock('./mocked')\n       | ^\n      4|\"\n`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.unmock is exported as default export 1`] = `\"Cannot export the result of \"vi.unmock\". Remove export declaration because \"vi.unmock\" doesn't return anything.\"`;\n\nexports[`throws an error when nodes are incompatible > correctly throws an error if vi.unmock is exported as default export 2`] = `\n\"      1| import { vi } from 'vitest'\n      2|\n      3| export default vi.unmock('./mocked')\n       | ^\n      4|\"\n`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/jest-expect.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`asymmetric matcher error 1`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": undefined,\n  \"expected\": \"StringContaining \"xx\"\",\n  \"message\": \"expected 'hello' to deeply equal StringContaining \"xx\"\",\n}\n`;\n\nexports[`asymmetric matcher error 2`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": undefined,\n  \"expected\": \"StringNotContaining \"ll\"\",\n  \"message\": \"expected 'hello' to deeply equal StringNotContaining \"ll\"\",\n}\n`;\n\nexports[`asymmetric matcher error 3`] = `\n{\n  \"actual\": \"Object {\n  \"foo\": \"hello\",\n}\",\n  \"diff\": \"- Expected\n+ Received\n\n  {\n-   \"foo\": StringContaining \"xx\",\n+   \"foo\": \"hello\",\n  }\",\n  \"expected\": \"Object {\n  \"foo\": StringContaining \"xx\",\n}\",\n  \"message\": \"expected { foo: 'hello' } to deeply equal { foo: StringContaining \"xx\" }\",\n}\n`;\n\nexports[`asymmetric matcher error 4`] = `\n{\n  \"actual\": \"Object {\n  \"foo\": \"hello\",\n}\",\n  \"diff\": \"- Expected\n+ Received\n\n  {\n-   \"foo\": StringNotContaining \"ll\",\n+   \"foo\": \"hello\",\n  }\",\n  \"expected\": \"Object {\n  \"foo\": StringNotContaining \"ll\",\n}\",\n  \"message\": \"expected { foo: 'hello' } to deeply equal { foo: StringNotContaining \"ll\" }\",\n}\n`;\n\nexports[`asymmetric matcher error 5`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": \"- Expected:\nstringContainingCustom<\"xx\">\n\n+ Received:\n\"hello\"\",\n  \"expected\": \"stringContainingCustom<\"xx\">\",\n  \"message\": \"expected 'hello' to deeply equal stringContainingCustom<\"xx\">\",\n}\n`;\n\nexports[`asymmetric matcher error 6`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": \"- Expected:\nnot.stringContainingCustom<\"ll\">\n\n+ Received:\n\"hello\"\",\n  \"expected\": \"not.stringContainingCustom<\"ll\">\",\n  \"message\": \"expected 'hello' to deeply equal not.stringContainingCustom<\"ll\">\",\n}\n`;\n\nexports[`asymmetric matcher error 7`] = `\n{\n  \"actual\": \"Object {\n  \"foo\": \"hello\",\n}\",\n  \"diff\": \"- Expected\n+ Received\n\n  {\n-   \"foo\": stringContainingCustom<\"xx\">,\n+   \"foo\": \"hello\",\n  }\",\n  \"expected\": \"Object {\n  \"foo\": stringContainingCustom<\"xx\">,\n}\",\n  \"message\": \"expected { foo: 'hello' } to deeply equal { foo: stringContainingCustom<\"xx\"> }\",\n}\n`;\n\nexports[`asymmetric matcher error 8`] = `\n{\n  \"actual\": \"Object {\n  \"foo\": \"hello\",\n}\",\n  \"diff\": \"- Expected\n+ Received\n\n  {\n-   \"foo\": not.stringContainingCustom<\"ll\">,\n+   \"foo\": \"hello\",\n  }\",\n  \"expected\": \"Object {\n  \"foo\": not.stringContainingCustom<\"ll\">,\n}\",\n  \"message\": \"expected { foo: 'hello' } to deeply equal { foo: not.stringContainingCustom{…} }\",\n}\n`;\n\nexports[`asymmetric matcher error 9`] = `\n{\n  \"actual\": \"undefined\",\n  \"diff\": undefined,\n  \"expected\": \"undefined\",\n  \"message\": \"expected \"hello\" to contain \"xx\"\",\n}\n`;\n\nexports[`asymmetric matcher error 10`] = `\n{\n  \"actual\": \"undefined\",\n  \"diff\": undefined,\n  \"expected\": \"undefined\",\n  \"message\": \"expected \"hello\" not to contain \"ll\"\",\n}\n`;\n\nexports[`asymmetric matcher error 11`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": \"- Expected:\ntestComplexMatcher<Object {\n  \"x\": \"y\",\n}>\n\n+ Received:\n\"hello\"\",\n  \"expected\": \"testComplexMatcher<Object {\n  \"x\": \"y\",\n}>\",\n  \"message\": \"expected 'hello' to deeply equal testComplexMatcher{…}\",\n}\n`;\n\nexports[`asymmetric matcher error 12`] = `\n{\n  \"actual\": \"Object {\n  \"k\": \"v\",\n  \"k2\": \"v2\",\n}\",\n  \"diff\": \"- Expected\n+ Received\n\n- ObjectContaining {\n+ {\n    \"k\": \"v\",\n-   \"k3\": \"v3\",\n+   \"k2\": \"v2\",\n  }\",\n  \"expected\": \"ObjectContaining {\n  \"k\": \"v\",\n  \"k3\": \"v3\",\n}\",\n  \"message\": \"expected { k: 'v', k2: 'v2' } to deeply equal ObjectContaining {\"k\": \"v\", \"k3\": \"v3\"}\",\n}\n`;\n\nexports[`asymmetric matcher error 13`] = `\n{\n  \"actual\": \"Array [\n  \"a\",\n  \"b\",\n]\",\n  \"diff\": \"- Expected\n+ Received\n\n- ArrayContaining [\n+ [\n    \"a\",\n-   \"c\",\n+   \"b\",\n  ]\",\n  \"expected\": \"ArrayContaining [\n  \"a\",\n  \"c\",\n]\",\n  \"message\": \"expected [ 'a', 'b' ] to deeply equal ArrayContaining [\"a\", \"c\"]\",\n}\n`;\n\nexports[`asymmetric matcher error 14`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": undefined,\n  \"expected\": \"StringMatching /xx/\",\n  \"message\": \"expected 'hello' to deeply equal StringMatching /xx/\",\n}\n`;\n\nexports[`asymmetric matcher error 15`] = `\n{\n  \"actual\": \"2.5\",\n  \"diff\": \"- Expected\n+ Received\n\n- NumberCloseTo 2 (1 digit)\n+ 2.5\",\n  \"expected\": \"NumberCloseTo 2 (1 digit)\",\n  \"message\": \"expected 2.5 to deeply equal NumberCloseTo 2 (1 digit)\",\n}\n`;\n\nexports[`asymmetric matcher error 16`] = `\n{\n  \"actual\": \"foo\",\n  \"diff\": \"- Expected:\ntoBeOneOf<Array [\n  \"bar\",\n  \"baz\",\n]>\n\n+ Received:\n\"foo\"\",\n  \"expected\": \"toBeOneOf<Array [\n  \"bar\",\n  \"baz\",\n]>\",\n  \"message\": \"expected 'foo' to deeply equal toBeOneOf<Array [\n  \"bar\",\n  \"baz\",\n]>\",\n}\n`;\n\nexports[`asymmetric matcher error 17`] = `\n{\n  \"actual\": \"0\",\n  \"diff\": \"- Expected:\ntoBeOneOf<Array [\n  Any<String>,\n  null,\n  undefined,\n]>\n\n+ Received:\n0\",\n  \"expected\": \"toBeOneOf<Array [\n  Any<String>,\n  null,\n  undefined,\n]>\",\n  \"message\": \"expected +0 to deeply equal toBeOneOf{…}\",\n}\n`;\n\nexports[`asymmetric matcher error 18`] = `\n{\n  \"actual\": \"Object {\n  \"k\": \"v\",\n  \"k2\": \"v2\",\n}\",\n  \"diff\": \"- Expected:\ntoBeOneOf<Array [\n  ObjectContaining {\n    \"k\": \"v\",\n    \"k3\": \"v3\",\n  },\n  null,\n  undefined,\n]>\n\n+ Received:\n{\n  \"k\": \"v\",\n  \"k2\": \"v2\",\n}\",\n  \"expected\": \"toBeOneOf<Array [\n  ObjectContaining {\n    \"k\": \"v\",\n    \"k3\": \"v3\",\n  },\n  null,\n  undefined,\n]>\",\n  \"message\": \"expected { k: 'v', k2: 'v2' } to deeply equal toBeOneOf{…}\",\n}\n`;\n\nexports[`asymmetric matcher error 19`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": undefined,\n  \"expected\": \"StringContaining \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\",\n  \"message\": \"expected 'hello' to deeply equal StringContaining{…}\",\n}\n`;\n\nexports[`asymmetric matcher error 20`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": undefined,\n  \"expected\": \"StringContaining \"xx\"\",\n  \"message\": \"expected error to match asymmetric matcher\",\n}\n`;\n\nexports[`asymmetric matcher error 21`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": \"- Expected:\nstringContainingCustom<\"xx\">\n\n+ Received:\n\"hello\"\",\n  \"expected\": \"stringContainingCustom<\"xx\">\",\n  \"message\": \"expected error to match asymmetric matcher\",\n}\n`;\n\nexports[`asymmetric matcher error 22`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": undefined,\n  \"expected\": \"StringContaining \"ll\"\",\n  \"message\": \"expected error not to match asymmetric matcher\",\n}\n`;\n\nexports[`asymmetric matcher error 23`] = `\n{\n  \"actual\": \"hello\",\n  \"diff\": \"- Expected:\nstringContainingCustom<\"ll\">\n\n+ Received:\n\"hello\"\",\n  \"expected\": \"stringContainingCustom<\"ll\">\",\n  \"message\": \"expected error not to match asymmetric matcher\",\n}\n`;\n\nexports[`asymmetric matcher error 24`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected:\nStringContaining \"ll\"\n\n+ Received:\nError {\n  \"message\": \"hello\",\n}\",\n  \"expected\": \"StringContaining \"ll\"\",\n  \"message\": \"expected error to match asymmetric matcher\",\n}\n`;\n\nexports[`asymmetric matcher error 25`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected:\nstringContainingCustom<\"ll\">\n\n+ Received:\nError {\n  \"message\": \"hello\",\n}\",\n  \"expected\": \"stringContainingCustom<\"ll\">\",\n  \"message\": \"expected error to match asymmetric matcher\",\n}\n`;\n\nexports[`asymmetric matcher error 26`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected:\n[Function MyError1]\n\n+ Received:\nMyError2 {\n  \"message\": \"hello\",\n}\",\n  \"expected\": \"[Function MyError1]\",\n  \"message\": \"expected error to be instance of MyError1\",\n}\n`;\n\nexports[`diff 1`] = `\n{\n  \"actual\": \"undefined\",\n  \"diff\": \"- Expected:\ntrue\n\n+ Received:\nundefined\",\n  \"expected\": \"true\",\n  \"message\": \"expected undefined to be truthy\",\n}\n`;\n\nexports[`diff 2`] = `\n{\n  \"actual\": \"Object {\n  \"hello\": \"world\",\n}\",\n  \"diff\": \"- Expected:\nfalse\n\n+ Received:\n{\n  \"hello\": \"world\",\n}\",\n  \"expected\": \"false\",\n  \"message\": \"expected { hello: 'world' } to be falsy\",\n}\n`;\n\nexports[`diff 3`] = `\n{\n  \"actual\": \"Object {\n  \"hello\": \"world\",\n}\",\n  \"diff\": \"- Expected:\nNaN\n\n+ Received:\n{\n  \"hello\": \"world\",\n}\",\n  \"expected\": \"NaN\",\n  \"message\": \"expected { hello: 'world' } to be NaN\",\n}\n`;\n\nexports[`diff 4`] = `\n{\n  \"actual\": \"Object {\n  \"hello\": \"world\",\n}\",\n  \"diff\": \"- Expected:\nundefined\n\n+ Received:\n{\n  \"hello\": \"world\",\n}\",\n  \"expected\": \"undefined\",\n  \"message\": \"expected { hello: 'world' } to be undefined\",\n}\n`;\n\nexports[`diff 5`] = `\n{\n  \"actual\": \"Object {\n  \"hello\": \"world\",\n}\",\n  \"diff\": \"- Expected:\nnull\n\n+ Received:\n{\n  \"hello\": \"world\",\n}\",\n  \"expected\": \"null\",\n  \"message\": \"expected { hello: 'world' } to be null\",\n}\n`;\n\nexports[`error equality 1`] = `\n{\n  \"actual\": \"[Error: hi]\",\n  \"diff\": \"- Expected\n+ Received\n\n  MyError {\n    \"message\": \"hi\",\n-   \"custom\": \"b\",\n+   \"custom\": \"a\",\n  }\",\n  \"expected\": \"[Error: hi]\",\n  \"message\": \"expected Error: hi { custom: 'a' } to deeply equal Error: hi { custom: 'b' }\",\n}\n`;\n\nexports[`error equality 2`] = `\n{\n  \"actual\": \"[Error: hi]\",\n  \"diff\": \"- Expected\n+ Received\n\n  MyError {\n    \"message\": \"hi\",\n-   \"custom\": \"b\",\n+   \"custom\": \"a\",\n  }\",\n  \"expected\": \"[Error: hi]\",\n  \"message\": \"expected a thrown error to be Error: hi { custom: 'b' }\",\n}\n`;\n\nexports[`error equality 3`] = `\n{\n  \"actual\": \"[Error: hi]\",\n  \"diff\": \"- Expected\n+ Received\n\n  MyError {\n-   \"message\": \"hello\",\n+   \"message\": \"hi\",\n    \"custom\": \"a\",\n  }\",\n  \"expected\": \"[Error: hello]\",\n  \"message\": \"expected Error: hi { custom: 'a' } to deeply equal Error: hello { custom: 'a' }\",\n}\n`;\n\nexports[`error equality 4`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected\n+ Received\n\n- YourError {\n+ MyError {\n    \"message\": \"hello\",\n    \"custom\": \"a\",\n  }\",\n  \"expected\": \"[Error: hello]\",\n  \"message\": \"expected Error: hello { custom: 'a' } to strictly equal Error: hello { custom: 'a' }\",\n}\n`;\n\nexports[`error equality 5`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected\n+ Received\n\n  Error {\n    \"message\": \"hello\",\n-   \"cause\": \"y\",\n+   \"cause\": \"x\",\n  }\",\n  \"expected\": \"[Error: hello]\",\n  \"message\": \"expected Error: hello to deeply equal Error: hello\",\n}\n`;\n\nexports[`error equality 6`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected\n+ Received\n\n  Error {\n    \"message\": \"hello\",\n-   \"cause\": \"y\",\n  }\",\n  \"expected\": \"[Error: hello]\",\n  \"message\": \"expected Error: hello to deeply equal Error: hello\",\n}\n`;\n\nexports[`error equality 7`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected\n+ Received\n\n  Error {\n-   \"message\": \"world\",\n+   \"message\": \"hello\",\n  }\",\n  \"expected\": \"[Error: world]\",\n  \"message\": \"expected Error: hello to deeply equal Error: world\",\n}\n`;\n\nexports[`error equality 8`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected\n+ Received\n\n- {\n-   \"something\": \"else\",\n+ Error {\n+   \"message\": \"hello\",\n+   \"cause\": \"x\",\n  }\",\n  \"expected\": \"Object {\n  \"something\": \"else\",\n}\",\n  \"message\": \"expected Error: hello to deeply equal { something: 'else' }\",\n}\n`;\n\nexports[`error equality 9`] = `\n{\n  \"actual\": \"[AggregateError: outer]\",\n  \"diff\": \"- Expected\n+ Received\n\n  AggregateError {\n    \"message\": \"outer\",\n    \"cause\": \"x\",\n    \"errors\": [\n      Error {\n        \"message\": \"inner\",\n-       \"cause\": \"y\",\n+       \"cause\": \"x\",\n      },\n    ],\n  }\",\n  \"expected\": \"[AggregateError: outer]\",\n  \"message\": \"expected AggregateError: outer { …(1) } to deeply equal AggregateError: outer { …(1) }\",\n}\n`;\n\nexports[`error equality 10`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected\n+ Received\n\n  Error {\n-   \"message\": \"world\",\n+   \"message\": \"hello\",\n    \"cause\": [Circular],\n  }\",\n  \"expected\": \"[Error: world]\",\n  \"message\": \"expected Error: hello to deeply equal Error: world\",\n}\n`;\n\nexports[`error equality 11`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected\n+ Received\n\n- ObjectContaining {\n-   \"cause\": \"y\",\n+ Error {\n    \"message\": \"hello\",\n+   \"cause\": \"x\",\n  }\",\n  \"expected\": \"ObjectContaining {\n  \"cause\": \"y\",\n  \"message\": \"hello\",\n}\",\n  \"message\": \"expected Error: hello to deeply equal ObjectContaining{…}\",\n}\n`;\n\nexports[`error equality 12`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected\n+ Received\n\n- ObjectContaining {\n+ Error {\n+   \"message\": \"hello\",\n    \"cause\": \"x\",\n-   \"message\": \"world\",\n  }\",\n  \"expected\": \"ObjectContaining {\n  \"cause\": \"x\",\n  \"message\": \"world\",\n}\",\n  \"message\": \"expected Error: hello to deeply equal ObjectContaining{…}\",\n}\n`;\n\nexports[`error equality 13`] = `\n{\n  \"actual\": \"[Error: hello]\",\n  \"diff\": \"- Expected\n+ Received\n\n- ObjectContaining {\n-   \"cause\": \"y\",\n-   \"message\": \"world\",\n+ Error {\n+   \"message\": \"hello\",\n+   \"cause\": \"x\",\n  }\",\n  \"expected\": \"ObjectContaining {\n  \"cause\": \"y\",\n  \"message\": \"world\",\n}\",\n  \"message\": \"expected Error: hello to deeply equal ObjectContaining{…}\",\n}\n`;\n\nexports[`toBeOneOf() > error message 1`] = `\n{\n  \"actual\": \"undefined\",\n  \"diff\": undefined,\n  \"expected\": \"undefined\",\n  \"message\": \"expect(received).toBeOneOf()\n\nExpected value to be one of:\nArray [\n  0,\n  1,\n  2,\n]\n\nReceived:\n3\",\n}\n`;\n\nexports[`toBeOneOf() > error message 2`] = `\n{\n  \"actual\": \"undefined\",\n  \"diff\": undefined,\n  \"expected\": \"undefined\",\n  \"message\": \"expect(received).toBeOneOf()\n\nExpected value to be one of:\nArray [\n  Any<String>,\n]\n\nReceived:\n3\",\n}\n`;\n\nexports[`toBeOneOf() > error message 3`] = `\n{\n  \"actual\": \"Object {\n  \"a\": 0,\n}\",\n  \"diff\": \"- Expected:\ntoBeOneOf<Array [\n  ObjectContaining {\n    \"b\": 0,\n  },\n  null,\n  undefined,\n]>\n\n+ Received:\n{\n  \"a\": 0,\n}\",\n  \"expected\": \"toBeOneOf<Array [\n  ObjectContaining {\n    \"b\": 0,\n  },\n  null,\n  undefined,\n]>\",\n  \"message\": \"expected { a: +0 } to deeply equal toBeOneOf{…}\",\n}\n`;\n\nexports[`toBeOneOf() > error message 4`] = `\n{\n  \"actual\": \"Object {\n  \"name\": \"mango\",\n}\",\n  \"diff\": \"- Expected\n+ Received\n\n  {\n-   \"name\": toBeOneOf<Array [\n-   \"apple\",\n-   \"banana\",\n-   \"orange\",\n- ]>,\n+   \"name\": \"mango\",\n  }\",\n  \"expected\": \"Object {\n  \"name\": toBeOneOf<Array [\n  \"apple\",\n  \"banana\",\n  \"orange\",\n]>,\n}\",\n  \"message\": \"expected { name: 'mango' } to deeply equal { name: toBeOneOf{…} }\",\n}\n`;\n\nexports[`toHaveBeenNthCalledWith error 1`] = `\n{\n  \"actual\": \"Array [\n  \"Hi\",\n]\",\n  \"diff\": \"- Expected\n+ Received\n\n  [\n-   \"hey\",\n+   \"Hi\",\n  ]\",\n  \"expected\": \"Array [\n  \"hey\",\n]\",\n  \"message\": \"expected 2nd \"vi.fn()\" call to have been called with [ 'hey' ]\",\n}\n`;\n\nexports[`toHaveBeenNthCalledWith error 2`] = `\n{\n  \"actual\": \"undefined\",\n  \"diff\": undefined,\n  \"expected\": \"Array [\n  \"hey\",\n]\",\n  \"message\": \"expected 3rd \"vi.fn()\" call to have been called with [ 'hey' ], but called only 2 times\",\n}\n`;\n\nexports[`toMatch/toContain diff 1`] = `\n{\n  \"actual\": \"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello\",\n  \"diff\": \"Expected: \"world\"\nReceived: \"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello\"\",\n  \"expected\": \"world\",\n  \"message\": \"expected 'hellohellohellohellohellohellohellohe…' to contain 'world'\",\n}\n`;\n\nexports[`toMatch/toContain diff 2`] = `\n{\n  \"actual\": \"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello\",\n  \"diff\": \"Expected: \"world\"\nReceived: \"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello\"\",\n  \"expected\": \"world\",\n  \"message\": \"expected 'hellohellohellohellohellohellohellohe…' to match 'world'\",\n}\n`;\n\nexports[`toMatch/toContain diff 3`] = `\n{\n  \"actual\": \"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello\",\n  \"diff\": \"- Expected:\n/world/\n\n+ Received:\n\"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello\"\",\n  \"expected\": \"/world/\",\n  \"message\": \"expected 'hellohellohellohellohellohellohellohe…' to match /world/\",\n}\n`;\n\nexports[`toSatisfy() > error message 1`] = `\n{\n  \"actual\": \"undefined\",\n  \"diff\": undefined,\n  \"expected\": \"undefined\",\n  \"message\": \"expect(received).toSatisfy()\n\nExpected value to satisfy:\n[Function isOdd]\n\nReceived:\n2\",\n}\n`;\n\nexports[`toSatisfy() > error message 2`] = `\n{\n  \"actual\": \"undefined\",\n  \"diff\": undefined,\n  \"expected\": \"undefined\",\n  \"message\": \"expect(received).toSatisfy()\n\nExpected value to satisfy:\nODD\n\nReceived:\n2\",\n}\n`;\n\nexports[`toSatisfy() > error message 3`] = `\n{\n  \"actual\": \"Object {\n  \"value\": 2,\n}\",\n  \"diff\": \"- Expected\n+ Received\n\n  {\n-   \"value\": toSatisfy<[Function isOdd]>,\n+   \"value\": 2,\n  }\",\n  \"expected\": \"Object {\n  \"value\": toSatisfy<[Function isOdd]>,\n}\",\n  \"message\": \"expected { value: 2 } to deeply equal { value: toSatisfy<[Function isOdd]> }\",\n}\n`;\n\nexports[`toSatisfy() > error message 4`] = `\n{\n  \"actual\": \"Object {\n  \"value\": 2,\n}\",\n  \"diff\": \"- Expected\n+ Received\n\n  {\n-   \"value\": toSatisfy<[Function isOdd], \"ODD\">,\n+   \"value\": 2,\n  }\",\n  \"expected\": \"Object {\n  \"value\": toSatisfy<[Function isOdd], \"ODD\">,\n}\",\n  \"message\": \"expected { value: 2 } to deeply equal { value: toSatisfy{…} }\",\n}\n`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/mocked.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`mocked function which fails on toReturnWith > just one call 1`] = `\n\"expected \"vi.fn()\" to return with: 2 at least once\n\nReceived:\n\n  1st vi.fn() call return:\n\n- 2\n+ 1\n\n\nNumber of calls: 1\n\"\n`;\n\nexports[`mocked function which fails on toReturnWith > multi calls 1`] = `\n\"expected \"vi.fn()\" to return with: 2 at least once\n\nReceived:\n\n  1st vi.fn() call return:\n\n- 2\n+ 1\n\n  2nd vi.fn() call return:\n\n- 2\n+ 1\n\n  3rd vi.fn() call return:\n\n- 2\n+ 1\n\n\nNumber of calls: 3\n\"\n`;\n\nexports[`mocked function which fails on toReturnWith > oject type 1`] = `\n\"expected \"vi.fn()\" to return with: { a: '4' } at least once\n\nReceived:\n\n  1st vi.fn() call return:\n\n  {\n-   \"a\": \"4\",\n+   \"a\": \"1\",\n  }\n\n  2nd vi.fn() call return:\n\n  {\n-   \"a\": \"4\",\n+   \"a\": \"1\",\n  }\n\n  3rd vi.fn() call return:\n\n  {\n-   \"a\": \"4\",\n+   \"a\": \"1\",\n  }\n\n\nNumber of calls: 3\n\"\n`;\n\nexports[`mocked function which fails on toReturnWith > zero call 1`] = `\n\"expected \"vi.fn()\" to return with: 2 at least once\n\nNumber of calls: 0\n\"\n`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/nested-suite.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`a > b > c > d > e > very deep > msg 1`] = `\"hi\"`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/serialize.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`error serialize > Should skip circular references to prevent hit the call stack limit 1`] = `\n{\n  \"toString\": \"Function<toString>\",\n  \"whatever\": [Circular],\n  \"whateverArray\": [\n    [Circular],\n    [Circular],\n  ],\n  \"whateverArrayClone\": [\n    [Circular],\n    [Circular],\n  ],\n}\n`;\n\nexports[`error serialize > works 1`] = `\n{\n  \"array\": [\n    1,\n    ,\n    3,\n  ],\n  \"fn\": \"Function<fn>\",\n  \"foo\": \"hi\",\n  \"nested\": {\n    \"class\": \"Function<class>\",\n    \"false\": false,\n  },\n  \"null\": null,\n  \"promise\": \"Promise\",\n  \"symbol\": \"Symbol(hi)\",\n}\n`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/snapshot-concurrent-sync.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`concurrent suite > snapshot 1`] = `\n{\n  \"foo\": \"bar\",\n}\n`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/snapshot-concurrent.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`four 1`] = `\"four\"`;\n\nexports[`one 1`] = `\"one\"`;\n\nexports[`three 1`] = `\"three\"`;\n\nexports[`two 1`] = `\"two\"`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/snapshot.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`multiline 1`] = `\n\"\n  Hello\n    World\n\"\n`;\n\nexports[`multiline strings  1`] = `\n\"\nexport default function () {\n  function Foo() {\n  }\n\n  return Foo;\n}\n\"\n`;\n\nexports[`object 1`] = `\n{\n  \"this\": {\n    \"is\": Set {\n      \"of\",\n      \"snapshot\",\n    },\n  },\n}\n`;\n\nexports[`properties snapshot 1`] = `\n{\n  \"createdAt\": Any<Date>,\n  \"id\": Any<Number>,\n  \"name\": StringContaining \"LeBron\",\n}\n`;\n\nexports[`renders mock snapshot 1`] = `[MockFunction]`;\n\nexports[`renders mock snapshot 2`] = `\n[MockFunction] {\n  \"calls\": [\n    [\n      \"hello\",\n      \"world\",\n      2,\n    ],\n  ],\n  \"results\": [\n    {\n      \"type\": \"return\",\n      \"value\": undefined,\n    },\n  ],\n}\n`;\n\nexports[`single line snapshot 1`] = `\"some string\"`;\n\nexports[`single line snapshot 2`] = `\"some \"string\"\"`;\n\nexports[`single line snapshot 3`] = `\"some \"string\"`;\n\nexports[`single line snapshot 4`] = `\"som\\`e\\` string\"`;\n\nexports[`single line snapshot 5`] = `\"some string\\`\"`;\n\nexports[`single line snapshot 6`] = `\"some string'\"`;\n\nexports[`single line snapshot 7`] = `\"some 'string'\"`;\n\nexports[`throwing 1`] = `[Error: omega]`;\n\nexports[`throwing 2`] = `\"omega\"`;\n\nexports[`throwing 3`] = `\n{\n  \"error\": \"omega\",\n}\n`;\n\nexports[`throwing 4`] = `[Error: omega]`;\n\nexports[`with big array 1`] = `\n{\n  \"this\": {\n    \"is\": Set {\n      \"one\",\n      [\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n        {},\n      ],\n    },\n  },\n}\n`;\n\nexports[`with big string 1`] = `\n{\n  \"this\": {\n    \"is\": Set {\n      \"one\",\n      \"zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo\",\n    },\n  },\n}\n`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/suite.test.tsx.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`suite name > snapshot 1`] = `\n{\n  \"foo\": \"bar\",\n}\n`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/test-for-suite.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`add(1, 1) > test 1`] = `2`;\n\nexports[`add(1, 2) > test 1`] = `3`;\n\nexports[`add(2, 1) > test 1`] = `3`;\n\nexports[`basic case1 > test 1`] = `\n{\n  \"args\": [\n    \"case1\",\n  ],\n}\n`;\n\nexports[`basic case2 > test 1`] = `\n{\n  \"args\": [\n    \"case2\",\n  ],\n}\n`;\n\nexports[`template 'x' true > test 1`] = `\n{\n  \"args\": [\n    {\n      \"a\": \"x\",\n      \"b\": true,\n    },\n  ],\n}\n`;\n\nexports[`template 'y' false > test 1`] = `\n{\n  \"args\": [\n    {\n      \"a\": \"y\",\n      \"b\": false,\n    },\n  ],\n}\n`;\n"
  },
  {
    "path": "test/core/test/__snapshots__/test-for.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`[docs] add(1, 1) 1`] = `2`;\n\nexports[`[docs] add(1, 2) 1`] = `3`;\n\nexports[`[docs] add(2, 1) 1`] = `3`;\n\nexports[`array case1-x case1-y 1`] = `\n{\n  \"args\": [\n    \"case1-x\",\n    \"case1-y\",\n  ],\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`array case2-x case2-y 1`] = `\n{\n  \"args\": [\n    \"case2-x\",\n    \"case2-y\",\n  ],\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`array destructure case1-x case1-y 1`] = `\n{\n  \"myFixture\": 1234,\n  \"x\": \"case1-x\",\n  \"y\": \"case1-y\",\n}\n`;\n\nexports[`array destructure case2-x case2-y 1`] = `\n{\n  \"myFixture\": 1234,\n  \"x\": \"case2-x\",\n  \"y\": \"case2-y\",\n}\n`;\n\nexports[`basic case1 1`] = `\n{\n  \"args\": \"case1\",\n}\n`;\n\nexports[`basic case2 1`] = `\n{\n  \"args\": \"case2\",\n}\n`;\n\nexports[`concurrent case1 1`] = `\n{\n  \"args\": \"case1\",\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`concurrent case2 1`] = `\n{\n  \"args\": \"case2\",\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`const case1 1`] = `\n{\n  \"args\": \"case1\",\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`const case2 1`] = `\n{\n  \"args\": \"case2\",\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`fixture case1 1`] = `\n{\n  \"args\": \"case1\",\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`fixture case2 1`] = `\n{\n  \"args\": \"case2\",\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`object 'case1' 1`] = `\n{\n  \"args\": {\n    \"k\": \"case1\",\n  },\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`object 'case2' 1`] = `\n{\n  \"args\": {\n    \"k\": \"case2\",\n  },\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`object destructure 'case1' 1`] = `\n{\n  \"myFixture\": 1234,\n  \"v\": \"case1\",\n}\n`;\n\nexports[`object destructure 'case2' 1`] = `\n{\n  \"myFixture\": 1234,\n  \"v\": \"case2\",\n}\n`;\n\nexports[`template 'x' true 1`] = `\n{\n  \"args\": {\n    \"a\": \"x\",\n    \"b\": true,\n  },\n  \"myFixture\": 1234,\n}\n`;\n\nexports[`template 'y' false 1`] = `\n{\n  \"args\": {\n    \"a\": \"y\",\n    \"b\": false,\n  },\n  \"myFixture\": 1234,\n}\n`;\n"
  },
  {
    "path": "test/core/test/alias.test.ts",
    "content": "// @ts-expect-error aliased to ../src/aliased-mod.ts\nimport { isAliased } from 'test-alias'\nimport { expect, test } from 'vitest'\n\ntest('check that test.alias works', () => {\n  expect(isAliased).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/basic.test.ts",
    "content": "import { assert, expect, it, suite, test } from 'vitest'\nimport { two } from '../src/submodule'\nimport { timeout } from '../src/timeout'\n\nconst testPath = expect.getState().testPath\nif (!testPath || !testPath.includes('basic.test.ts')) {\n  throw new Error(`testPath is not correct: ${testPath}`)\n}\n\ntest('Math.sqrt()', () => {\n  assert.equal(Math.sqrt(4), two)\n  assert.equal(Math.sqrt(2), Math.SQRT2)\n  expect(Math.sqrt(144)).toStrictEqual(12)\n  // await new Promise(resolve => setTimeout(resolve, 3000))\n})\n\ntest('JSON', () => {\n  const input = {\n    foo: 'hello',\n    bar: 'world',\n  }\n\n  const output = JSON.stringify(input)\n\n  expect(input).toEqual({\n    foo: 'hello',\n    bar: 'world',\n  })\n  expect(output).toEqual('{\"foo\":\"hello\",\"bar\":\"world\"}')\n  assert.deepEqual(JSON.parse(output), input, 'matches original')\n})\n\ntest('mode and NODE_ENV is test by default', () => {\n  expect(process.env.NODE_ENV).toBe('test')\n  expect(import.meta.env.MODE).toBe('test')\n})\n\ntest('assertion is callable', () => {\n  const str = '13'\n  expect(str).to.be.a('string')\n  expect(str).not.to.be.a('number')\n})\n\nsuite('suite', () => {\n  test('expect truthy', () => {\n    expect({}).toBeTruthy()\n    expect(null).not.toBeTruthy()\n  })\n})\n\n// Remove .skip to test async fail by timeout\ntest.skip('async with timeout', async () => {\n  return new Promise<void>((resolve) => {\n    setTimeout(() => {\n      resolve()\n    }, 200)\n  })\n}, 100)\n\nit('timeout', () => new Promise(resolve => setTimeout(resolve, timeout)))\n\nit.fails('deprecated done callback', (done) => {\n  // @ts-expect-error deprecated done callback is not typed\n  done()\n})\n\ntest('escaping', () => {\n  expect(['\\\\123']).toEqual(['\\\\123'])\n  expect('\\\\123').toEqual('\\\\123')\n})\n"
  },
  {
    "path": "test/core/test/browserAutomocker.test.ts",
    "content": "import { automockModule } from '@vitest/mocker/node'\nimport { parseAst } from 'vite'\nimport { expect, it } from 'vitest'\n\nfunction automock(code: string) {\n  return automockModule(code, 'automock', parseAst).toString()\n}\n\nit('correctly parses function declaration', () => {\n  expect(automock(`\nexport function test() {}\n  `)).toMatchInlineSnapshot(`\n    \"\n    function test() {}\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"test\"]: test,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"test\"]\n    export {\n      __vitest_mocked_0__ as test,\n    }\n    \"\n  `)\n})\n\nit('correctly parses class declaration', () => {\n  expect(automock(`\nexport class Test {}\n  `)).toMatchInlineSnapshot(`\n    \"\n    class Test {}\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"Test\"]: Test,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"Test\"]\n    export {\n      __vitest_mocked_0__ as Test,\n    }\n    \"\n  `)\n})\n\nit('correctly parses default export', () => {\n  expect(automock(`\nexport default class Test {}\n  `)).toMatchInlineSnapshot(`\n    \"\n    const __vitest_default = class Test {}\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"__vitest_default\"]: __vitest_default,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"__vitest_default\"]\n    export {\n      __vitest_mocked_0__ as default,\n    }\n    \"\n  `)\n\n  expect(automock(`\nexport default function test() {}\n  `)).toMatchInlineSnapshot(`\n    \"\n    const __vitest_default = function test() {}\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"__vitest_default\"]: __vitest_default,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"__vitest_default\"]\n    export {\n      __vitest_mocked_0__ as default,\n    }\n    \"\n  `)\n\n  expect(automock(`\nexport default someVariable\n  `)).toMatchInlineSnapshot(`\n    \"\n    const __vitest_default = someVariable\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"__vitest_default\"]: __vitest_default,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"__vitest_default\"]\n    export {\n      __vitest_mocked_0__ as default,\n    }\n    \"\n  `)\n\n  expect(automock(`\nexport default 'test'\n  `)).toMatchInlineSnapshot(`\n    \"\n    const __vitest_default = 'test'\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"__vitest_default\"]: __vitest_default,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"__vitest_default\"]\n    export {\n      __vitest_mocked_0__ as default,\n    }\n    \"\n  `)\n\n  expect(automock(`\nexport default null\n  `)).toMatchInlineSnapshot(`\n    \"\n    const __vitest_default = null\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"__vitest_default\"]: __vitest_default,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"__vitest_default\"]\n    export {\n      __vitest_mocked_0__ as default,\n    }\n    \"\n  `)\n\n  expect(automock(`\nconst test = '123'\nexport default test\n  `)).toMatchInlineSnapshot(`\n    \"\n    const test = '123'\n    const __vitest_default = test\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"__vitest_default\"]: __vitest_default,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"__vitest_default\"]\n    export {\n      __vitest_mocked_0__ as default,\n    }\n    \"\n  `)\n})\n\nit('correctly parses const export', () => {\n  expect(automock(`\nexport const test = 'test'\nexport const test2 = () => {}\nexport const test3 = function test4() {}\n  `)).toMatchInlineSnapshot(`\n    \"\n    const test = 'test'\n    const test2 = () => {}\n    const test3 = function test4() {}\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"test\"]: test,\n      [\"test2\"]: test2,\n      [\"test3\"]: test3,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"test\"]\n    const __vitest_mocked_1__ = __vitest_mocked_module__[\"test2\"]\n    const __vitest_mocked_2__ = __vitest_mocked_module__[\"test3\"]\n    export {\n      __vitest_mocked_0__ as test,\n      __vitest_mocked_1__ as test2,\n      __vitest_mocked_2__ as test3,\n    }\n    \"\n  `)\n})\n\nit('correctly parses const array pattern', () => {\n  expect(automock(`\nexport const [test, ...rest] = []\nexport const [...rest2] = []\n  `)).toMatchInlineSnapshot(`\n    \"\n    const [test, ...rest] = []\n    const [...rest2] = []\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"test\"]: test,\n      [\"rest\"]: rest,\n      [\"rest2\"]: rest2,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"test\"]\n    const __vitest_mocked_1__ = __vitest_mocked_module__[\"rest\"]\n    const __vitest_mocked_2__ = __vitest_mocked_module__[\"rest2\"]\n    export {\n      __vitest_mocked_0__ as test,\n      __vitest_mocked_1__ as rest,\n      __vitest_mocked_2__ as rest2,\n    }\n    \"\n  `)\n})\n\nit('correctly parses several declarations', () => {\n  expect(automock(`\nexport const test = 2, test2 = 3, test4 = () => {}, test5 = function() {};\n  `)).toMatchInlineSnapshot(`\n    \"\n    const test = 2, test2 = 3, test4 = () => {}, test5 = function() {};\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"test\"]: test,\n      [\"test2\"]: test2,\n      [\"test4\"]: test4,\n      [\"test5\"]: test5,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"test\"]\n    const __vitest_mocked_1__ = __vitest_mocked_module__[\"test2\"]\n    const __vitest_mocked_2__ = __vitest_mocked_module__[\"test4\"]\n    const __vitest_mocked_3__ = __vitest_mocked_module__[\"test5\"]\n    export {\n      __vitest_mocked_0__ as test,\n      __vitest_mocked_1__ as test2,\n      __vitest_mocked_2__ as test4,\n      __vitest_mocked_3__ as test5,\n    }\n    \"\n  `)\n})\n\nit('correctly parses object pattern', () => {\n  expect(automock(`\nexport const { test, ...rest } = {}\nexport const { test: alias } = {}\nexport const { ...rest2 } = {}\n  `)).toMatchInlineSnapshot(`\n    \"\n    const { test, ...rest } = {}\n    const { test: alias } = {}\n    const { ...rest2 } = {}\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"test\"]: test,\n      [\"rest\"]: rest,\n      [\"alias\"]: alias,\n      [\"rest2\"]: rest2,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"test\"]\n    const __vitest_mocked_1__ = __vitest_mocked_module__[\"rest\"]\n    const __vitest_mocked_2__ = __vitest_mocked_module__[\"alias\"]\n    const __vitest_mocked_3__ = __vitest_mocked_module__[\"rest2\"]\n    export {\n      __vitest_mocked_0__ as test,\n      __vitest_mocked_1__ as rest,\n      __vitest_mocked_2__ as alias,\n      __vitest_mocked_3__ as rest2,\n    }\n    \"\n  `)\n})\n\nit('correctly parses export specifiers', () => {\n  expect(automock(`\n  export const test = '1'\n  export { test as \"test3\", test as test4 }\n  `)).toMatchInlineSnapshot(`\n    \"\n      const test = '1'\n      \n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"test\"]: test,\n      [\"test\"]: test,\n      [\"test\"]: test,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"test\"]\n    const __vitest_mocked_1__ = __vitest_mocked_module__[\"test\"]\n    const __vitest_mocked_2__ = __vitest_mocked_module__[\"test\"]\n    export {\n      __vitest_mocked_0__ as test,\n      __vitest_mocked_1__ as \"test3\",\n      __vitest_mocked_2__ as test4,\n    }\n    \"\n  `)\n})\n\nit('correctly parses exports from sources', () => {\n  expect(automock(`\nexport { test, test as test3, name as \"name3\" } from './module'\nimport { testing as name4 } from './another-module'\nexport { testing as name4 } from './another-module'\n  `)).toMatchInlineSnapshot(`\n    \"\n    import { test as __vitest_imported_0__, test as __vitest_imported_1__, name as __vitest_imported_2__ } from './module'\n    import { testing as name4 } from './another-module'\n    import { testing as __vitest_imported_3__ } from './another-module'\n      \n    const __vitest_current_es_module__ = {\n      __esModule: true,\n      [\"__vitest_imported_0__\"]: __vitest_imported_0__,\n      [\"__vitest_imported_1__\"]: __vitest_imported_1__,\n      [\"__vitest_imported_2__\"]: __vitest_imported_2__,\n      [\"__vitest_imported_3__\"]: __vitest_imported_3__,\n    }\n    const __vitest_mocked_module__ = globalThis[\"__vitest_mocker__\"].mockObject(__vitest_current_es_module__, \"automock\")\n    const __vitest_mocked_0__ = __vitest_mocked_module__[\"__vitest_imported_0__\"]\n    const __vitest_mocked_1__ = __vitest_mocked_module__[\"__vitest_imported_1__\"]\n    const __vitest_mocked_2__ = __vitest_mocked_module__[\"__vitest_imported_2__\"]\n    const __vitest_mocked_3__ = __vitest_mocked_module__[\"__vitest_imported_3__\"]\n    export {\n      __vitest_mocked_0__ as test,\n      __vitest_mocked_1__ as test3,\n      __vitest_mocked_2__ as \"name3\",\n      __vitest_mocked_3__ as name4,\n    }\n    \"\n  `)\n})\n"
  },
  {
    "path": "test/core/test/builtin.test.ts",
    "content": "import testModule, { run } from 'node:test'\nimport { expect, it } from 'vitest'\n\nit('node:test works correctly', () => {\n  expect(run).toBeTypeOf('function')\n  expect(testModule).toBeTypeOf('function')\n  expect(testModule.run).toBeTypeOf('function')\n})\n"
  },
  {
    "path": "test/core/test/chai-style-assertions.test.ts",
    "content": "/* eslint-disable ts/no-unused-expressions */\nimport { describe, expect, it, vi } from 'vitest'\n\ndescribe('Chai-style assertions', () => {\n  describe('called', () => {\n    it('passes when spy was called', () => {\n      const spy = vi.fn()\n      spy()\n      expect(spy).to.have.been.called\n    })\n\n    it('fails when spy was not called', () => {\n      const spy = vi.fn().mockName('testSpy')\n      expect(() => {\n        expect(spy).to.have.been.called\n      }).toThrow(/expected \"testSpy\" to be called at least once/)\n    })\n\n    it('negated: passes when spy was not called', () => {\n      const spy = vi.fn()\n      expect(spy).to.not.have.been.called\n    })\n\n    it('negated: fails when spy was called', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy()\n      expect(() => {\n        expect(spy).to.not.have.been.called\n      }).toThrow(/expected \"testSpy\" to not be called at all/)\n    })\n  })\n\n  describe('callCount', () => {\n    it('passes when spy was called exact number of times', () => {\n      const spy = vi.fn()\n      spy()\n      spy()\n      spy()\n      expect(spy).to.have.callCount(3)\n    })\n\n    it('fails when spy was called different number of times', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy()\n      spy()\n      expect(() => {\n        expect(spy).to.have.callCount(3)\n      }).toThrow(/expected \"testSpy\" to be called 3 times, but got 2 times/)\n    })\n\n    it('negated: passes when spy was called different number of times', () => {\n      const spy = vi.fn()\n      spy()\n      expect(spy).to.not.have.callCount(3)\n    })\n  })\n\n  describe('calledWith', () => {\n    it('passes when spy was called with specific arguments', () => {\n      const spy = vi.fn()\n      spy('arg1', 'arg2')\n      expect(spy).to.have.been.calledWith('arg1', 'arg2')\n    })\n\n    it('passes when spy was called with arguments among other calls', () => {\n      const spy = vi.fn()\n      spy('other')\n      spy('arg1', 'arg2')\n      spy('another')\n      expect(spy).to.have.been.calledWith('arg1', 'arg2')\n    })\n\n    it('fails when spy was not called with specific arguments', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy('wrong', 'args')\n      expect(() => {\n        expect(spy).to.have.been.calledWith('arg1', 'arg2')\n      }).toThrow(/expected \"testSpy\" to be called with arguments/)\n    })\n\n    it('negated: passes when spy was not called with specific arguments', () => {\n      const spy = vi.fn()\n      spy('other', 'args')\n      expect(spy).to.not.have.been.calledWith('arg1', 'arg2')\n    })\n  })\n\n  describe('calledOnce', () => {\n    it('passes when spy was called exactly once', () => {\n      const spy = vi.fn()\n      spy()\n      expect(spy).to.have.been.calledOnce\n    })\n\n    it('fails when spy was not called', () => {\n      const spy = vi.fn().mockName('testSpy')\n      expect(() => {\n        expect(spy).to.have.been.calledOnce\n      }).toThrow(/expected \"testSpy\" to be called once, but got 0 times/)\n    })\n\n    it('fails when spy was called multiple times', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy()\n      spy()\n      expect(() => {\n        expect(spy).to.have.been.calledOnce\n      }).toThrow(/expected \"testSpy\" to be called once, but got 2 times/)\n    })\n\n    it('negated: passes when spy was not called once', () => {\n      const spy = vi.fn()\n      spy()\n      spy()\n      expect(spy).to.not.have.been.calledOnce\n    })\n  })\n\n  describe('calledOnceWith', () => {\n    it('passes when spy was called exactly once with specific arguments', () => {\n      const spy = vi.fn()\n      spy('arg1', 'arg2')\n      expect(spy).to.have.been.calledOnceWith('arg1', 'arg2')\n    })\n\n    it('fails when spy was called once but with wrong arguments', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy('wrong', 'args')\n      expect(() => {\n        expect(spy).to.have.been.calledOnceWith('arg1', 'arg2')\n      }).toThrow(/expected \"testSpy\" to be called once with arguments/)\n    })\n\n    it('fails when spy was called multiple times with correct arguments', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy('arg1', 'arg2')\n      spy('arg1', 'arg2')\n      expect(() => {\n        expect(spy).to.have.been.calledOnceWith('arg1', 'arg2')\n      }).toThrow(/expected \"testSpy\" to be called once with arguments/)\n    })\n\n    it('negated: passes when spy was not called once with specific arguments', () => {\n      const spy = vi.fn()\n      spy('arg1', 'arg2')\n      spy('arg1', 'arg2')\n      expect(spy).to.not.have.been.calledOnceWith('arg1', 'arg2')\n    })\n  })\n\n  describe('lastCalledWith', () => {\n    it('passes when last call was with specific arguments', () => {\n      const spy = vi.fn()\n      spy('first')\n      spy('second')\n      spy('arg1', 'arg2')\n      expect(spy).to.have.been.lastCalledWith('arg1', 'arg2')\n    })\n\n    it('fails when last call was with different arguments', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy('arg1', 'arg2')\n      spy('different')\n      expect(() => {\n        expect(spy).to.have.been.lastCalledWith('arg1', 'arg2')\n      }).toThrow(/expected last \"testSpy\" call to have been called with/)\n    })\n\n    it('negated: passes when last call was with different arguments', () => {\n      const spy = vi.fn()\n      spy('arg1', 'arg2')\n      spy('different')\n      expect(spy).to.not.have.been.lastCalledWith('arg1', 'arg2')\n    })\n  })\n\n  describe('nthCalledWith', () => {\n    it('passes when nth call was with specific arguments', () => {\n      const spy = vi.fn()\n      spy('first')\n      spy('arg1', 'arg2')\n      spy('third')\n      expect(spy).to.have.been.nthCalledWith(2, 'arg1', 'arg2')\n    })\n\n    it('fails when nth call was with different arguments', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy('first')\n      spy('wrong')\n      spy('third')\n      expect(() => {\n        expect(spy).to.have.been.nthCalledWith(2, 'arg1', 'arg2')\n      }).toThrow(/expected 2nd \"testSpy\" call to have been called with/)\n    })\n\n    it('negated: passes when nth call was with different arguments', () => {\n      const spy = vi.fn()\n      spy('first')\n      spy('wrong')\n      spy('third')\n      expect(spy).to.not.have.been.nthCalledWith(2, 'arg1', 'arg2')\n    })\n  })\n\n  describe('returned', () => {\n    it('passes when spy returned successfully', () => {\n      const spy = vi.fn(() => 'value')\n      spy()\n      expect(spy).to.have.returned\n    })\n\n    it('fails when spy threw an error', () => {\n      const spy = vi.fn(() => {\n        throw new Error('test error')\n      }).mockName('testSpy')\n      try {\n        spy()\n      }\n      catch {}\n      expect(() => {\n        expect(spy).to.have.returned\n      }).toThrow(/expected \"testSpy\" to be successfully called at least once/)\n    })\n\n    it('negated: passes when spy did not return', () => {\n      const spy = vi.fn(() => {\n        throw new Error('test error')\n      })\n      try {\n        spy()\n      }\n      catch {}\n      expect(spy).to.not.have.returned\n    })\n  })\n\n  describe('returnedWith', () => {\n    it('passes when spy returned specific value', () => {\n      const spy = vi.fn(() => 'value')\n      spy()\n      expect(spy).to.have.returnedWith('value')\n    })\n\n    it('passes when spy returned value among other calls', () => {\n      const spy = vi.fn()\n      spy.mockReturnValueOnce('other')\n      spy.mockReturnValueOnce('value')\n      spy.mockReturnValueOnce('another')\n      spy()\n      spy()\n      spy()\n      expect(spy).to.have.returnedWith('value')\n    })\n\n    it('fails when spy did not return specific value', () => {\n      const spy = vi.fn(() => 'wrong').mockName('testSpy')\n      spy()\n      expect(() => {\n        expect(spy).to.have.returnedWith('value')\n      }).toThrow(/expected \"testSpy\"/)\n    })\n\n    it('negated: passes when spy did not return specific value', () => {\n      const spy = vi.fn(() => 'other')\n      spy()\n      expect(spy).to.not.have.returnedWith('value')\n    })\n  })\n\n  describe('calledBefore', () => {\n    it('passes when spy was called before another spy', () => {\n      const spy1 = vi.fn()\n      const spy2 = vi.fn()\n      spy1()\n      spy2()\n      expect(spy1).to.have.been.calledBefore(spy2)\n    })\n\n    it('fails when spy was called after another spy', () => {\n      const spy1 = vi.fn().mockName('spy1')\n      const spy2 = vi.fn().mockName('spy2')\n      spy2()\n      spy1()\n      expect(() => {\n        expect(spy1).to.have.been.calledBefore(spy2)\n      }).toThrow(/expected \"spy1\" to have been called before \"spy2\"/)\n    })\n\n    it('negated: passes when spy was not called before another spy', () => {\n      const spy1 = vi.fn()\n      const spy2 = vi.fn()\n      spy2()\n      spy1()\n      expect(spy1).to.not.have.been.calledBefore(spy2)\n    })\n  })\n\n  describe('calledAfter', () => {\n    it('passes when spy was called after another spy', () => {\n      const spy1 = vi.fn()\n      const spy2 = vi.fn()\n      spy2()\n      spy1()\n      expect(spy1).to.have.been.calledAfter(spy2)\n    })\n\n    it('fails when spy was called before another spy', () => {\n      const spy1 = vi.fn().mockName('spy1')\n      const spy2 = vi.fn().mockName('spy2')\n      spy1()\n      spy2()\n      expect(() => {\n        expect(spy1).to.have.been.calledAfter(spy2)\n      }).toThrow(/expected \"spy1\" to have been called after \"spy2\"/)\n    })\n\n    it('negated: passes when spy was not called after another spy', () => {\n      const spy1 = vi.fn()\n      const spy2 = vi.fn()\n      spy1()\n      spy2()\n      expect(spy1).to.not.have.been.calledAfter(spy2)\n    })\n  })\n\n  describe('returnedTimes', () => {\n    it('passes when spy returned successfully exact number of times', () => {\n      const spy = vi.fn(() => 'value')\n      spy()\n      spy()\n      spy()\n      expect(spy).to.have.returnedTimes(3)\n    })\n\n    it('fails when spy returned different number of times', () => {\n      const spy = vi.fn(() => 'value').mockName('testSpy')\n      spy()\n      spy()\n      expect(() => {\n        expect(spy).to.have.returnedTimes(3)\n      }).toThrow(/expected \"testSpy\"/)\n    })\n\n    it('negated: passes when spy returned different number of times', () => {\n      const spy = vi.fn(() => 'value')\n      spy()\n      expect(spy).to.not.have.returnedTimes(3)\n    })\n\n    it('does not count throws as returns', () => {\n      const spy = vi.fn(() => {\n        throw new Error('error')\n      })\n      expect(() => spy()).toThrow()\n      expect(() => spy()).toThrow()\n      expect(spy).to.have.returnedTimes(0)\n    })\n  })\n\n  describe('lastReturnedWith', () => {\n    it('passes when last return value matches', () => {\n      const spy = vi.fn()\n        .mockReturnValueOnce('first')\n        .mockReturnValueOnce('second')\n        .mockReturnValueOnce('last')\n      spy()\n      spy()\n      spy()\n      expect(spy).to.have.lastReturnedWith('last')\n    })\n\n    it('fails when last return value does not match', () => {\n      const spy = vi.fn(() => 'wrong').mockName('testSpy')\n      spy()\n      expect(() => {\n        expect(spy).to.have.lastReturnedWith('expected')\n      }).toThrow(/expected last \"testSpy\" call to return/)\n    })\n\n    it('negated: passes when last return value does not match', () => {\n      const spy = vi.fn(() => 'actual')\n      spy()\n      expect(spy).to.not.have.lastReturnedWith('different')\n    })\n  })\n\n  describe('nthReturnedWith', () => {\n    it('passes when nth return value matches', () => {\n      const spy = vi.fn()\n        .mockReturnValueOnce('first')\n        .mockReturnValueOnce('second')\n        .mockReturnValueOnce('third')\n      spy()\n      spy()\n      spy()\n      expect(spy).to.have.nthReturnedWith(2, 'second')\n    })\n\n    it('fails when nth return value does not match', () => {\n      const spy = vi.fn(() => 'wrong').mockName('testSpy')\n      spy()\n      spy()\n      expect(() => {\n        expect(spy).to.have.nthReturnedWith(2, 'expected')\n      }).toThrow(/expected 2nd call \"testSpy\" call to return/)\n    })\n\n    it('negated: passes when nth return value does not match', () => {\n      const spy = vi.fn()\n        .mockReturnValueOnce('first')\n        .mockReturnValueOnce('second')\n      spy()\n      spy()\n      expect(spy).to.not.have.nthReturnedWith(2, 'different')\n    })\n  })\n\n  describe('calledTwice', () => {\n    it('passes when spy was called exactly twice', () => {\n      const spy = vi.fn()\n      spy()\n      spy()\n      expect(spy).to.have.been.calledTwice\n    })\n\n    it('fails when spy was not called twice', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy()\n      expect(() => {\n        expect(spy).to.have.been.calledTwice\n      }).toThrow(/expected \"testSpy\" to be called 2 times, but got 1 times/)\n    })\n\n    it('negated: passes when spy was not called twice', () => {\n      const spy = vi.fn()\n      spy()\n      expect(spy).to.not.have.been.calledTwice\n    })\n\n    it('fails when spy was called three times', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy()\n      spy()\n      spy()\n      expect(() => {\n        expect(spy).to.have.been.calledTwice\n      }).toThrow(/expected \"testSpy\" to be called 2 times, but got 3 times/)\n    })\n  })\n\n  describe('calledThrice', () => {\n    it('passes when spy was called exactly three times', () => {\n      const spy = vi.fn()\n      spy()\n      spy()\n      spy()\n      expect(spy).to.have.been.calledThrice\n    })\n\n    it('fails when spy was not called three times', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy()\n      spy()\n      expect(() => {\n        expect(spy).to.have.been.calledThrice\n      }).toThrow(/expected \"testSpy\" to be called 3 times, but got 2 times/)\n    })\n\n    it('negated: passes when spy was not called three times', () => {\n      const spy = vi.fn()\n      spy()\n      spy()\n      expect(spy).to.not.have.been.calledThrice\n    })\n\n    it('fails when spy was called twice', () => {\n      const spy = vi.fn().mockName('testSpy')\n      spy()\n      spy()\n      expect(() => {\n        expect(spy).to.have.been.calledThrice\n      }).toThrow(/expected \"testSpy\" to be called 3 times, but got 2 times/)\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/chainable.test.ts",
    "content": "import { createChainable } from '@vitest/runner/utils'\nimport { describe, expect, it } from 'vitest'\n\ndescribe('chainable', () => {\n  it('creates', () => {\n    const chain = createChainable(['a', 'b'], function () {\n      return this\n    })\n\n    expect(chain()).toEqual({})\n    expect(chain.a()).toEqual({ a: true })\n\n    // eslint-disable-next-line ts/no-unused-expressions\n    chain.a\n\n    expect(chain()).toEqual({})\n    expect(chain.b.a()).toEqual({ a: true, b: true })\n\n    expect(chain.b.a.b.a.b()).toEqual({ a: true, b: true })\n    expect(chain.a.a.a.a.a.a()).toEqual({ a: true })\n  })\n})\n"
  },
  {
    "path": "test/core/test/child-specific.child_process.test.ts",
    "content": "import { isMainThread, threadId } from 'node:worker_threads'\nimport { expect, test } from 'vitest'\n\ntest('has access to child_process API', ({ task, skip }) => {\n  skip(task.file.pool !== 'forks', 'Run only in child_process pool')\n  expect(process.send).toBeDefined()\n})\n\ntest('doesn\\'t have access to threads API', ({ task, skip }) => {\n  skip(task.file.pool !== 'forks', 'Run only in child_process pool')\n  expect(isMainThread).toBe(true)\n  expect(threadId).toBe(0)\n})\n"
  },
  {
    "path": "test/core/test/circular.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { CalledB, circularA } from '../src/circularA'\nimport { timeout } from '../src/timeout'\n\nit('circular', () => {\n  CalledB.length = 0\n\n  circularA()\n\n  expect(CalledB.length).toBe(1)\n\n  circularA()\n  circularA()\n\n  expect(CalledB).toEqual([0, 1, 2])\n})\n\nit('timeout', () => new Promise(resolve => setTimeout(resolve, timeout)))\n"
  },
  {
    "path": "test/core/test/cli-test.test.ts",
    "content": "import { resolveConfig as viteResolveConfig } from 'vite'\nimport { expect, test } from 'vitest'\nimport { ReportersMap, rolldownVersion } from 'vitest/node'\nimport { createCLI, parseCLI } from '../../../packages/vitest/src/node/cli/cac.js'\nimport { resolveConfig } from '../../../packages/vitest/src/node/config/resolveConfig.js'\n\n// @ts-expect-error not typed global\nglobalThis.__VITEST_GENERATE_UI_TOKEN__ = true\n\nconst vitestCli = createCLI()\n\nfunction parseArguments(commands: string, full = false) {\n  const cliArgs = commands.trim().replace(/\\s+/g, ' ').split(' ')\n  const { options, args } = vitestCli.parse(['node', '/index.js', ...cliArgs], {\n    run: false,\n  })\n  // remove -- and color from the options since they are always present\n  if (!full) {\n    delete options['--']\n    delete options.color\n  }\n\n  return { options, args, matchedCommand: vitestCli.matchedCommand }\n}\n\nfunction getCLIOptions(commands: string) {\n  return parseArguments(commands).options\n}\n\nconst enabled = { enabled: true }\nconst disabled = { enabled: false }\n\ntest('top level nested options return boolean', async () => {\n  expect(getCLIOptions('--coverage --browser --typecheck')).toEqual({\n    coverage: enabled,\n    browser: enabled,\n    typecheck: enabled,\n  })\n})\n\ntest('negated top level nested options return boolean', async () => {\n  expect(getCLIOptions('--no-coverage --no-browser --no-typecheck')).toEqual({\n    coverage: disabled,\n    browser: disabled,\n    typecheck: disabled,\n  })\n})\n\ntest('nested coverage options have correct types', async () => {\n  expect(getCLIOptions(`\n    --coverage.enabled=true\n    --coverage.clean false\n    --coverage.cleanOnRerun true\n    --coverage.reportOnFailure\n    --coverage.allowExternal false\n    --coverage.skipFull\n    --coverage.thresholds.autoUpdate true\n    --coverage.thresholds.perFile\n    ${/* even non-boolean should be treated as boolean */ ''}\n    --coverage.thresholds.100 25\n\n    --coverage.provider v8\n    --coverage.changed HEAD\n    --coverage.reporter text\n    --coverage.reportsDirectory .\\\\dist\\\\coverage\n    --coverage.customProviderModule=./folder/coverage.js\n\n    --coverage.ignoreClassMethods method1\n    --coverage.ignoreClassMethods method2\n\n    --coverage.processingConcurrency 2\n    --coverage.thresholds.statements 80\n    --coverage.thresholds.lines 100\n    --coverage.thresholds.functions 30\n    --coverage.thresholds.branches 25\n\n    --coverage.watermarks.statements 50,80\n    --coverage.watermarks.lines=30,40\n    --coverage.watermarks.branches=70,80\n    --coverage.watermarks.functions 20,60\n  `).coverage).toEqual({\n    enabled: true,\n    reporter: ['text'],\n    provider: 'v8',\n    changed: 'HEAD',\n    clean: false,\n    cleanOnRerun: true,\n    reportsDirectory: 'dist/coverage',\n    customProviderModule: 'folder/coverage.js',\n    reportOnFailure: true,\n    allowExternal: false,\n    skipFull: true,\n    ignoreClassMethods: ['method1', 'method2'],\n    processingConcurrency: 2,\n    thresholds: {\n      statements: 80,\n      lines: 100,\n      functions: 30,\n      branches: 25,\n      perFile: true,\n      autoUpdate: true,\n      100: true,\n    },\n    watermarks: {\n      statements: [50, 80],\n      lines: [30, 40],\n      branches: [70, 80],\n      functions: [20, 60],\n    },\n  })\n})\n\ntest('correctly normalizes methods to be an array', async () => {\n  expect(getCLIOptions(`\n    --coverage.ignoreClassMethods method2\n    --coverage.include pattern\n    --coverage.exclude pattern\n  `)).toMatchObject({\n    coverage: {\n      ignoreClassMethods: ['method2'],\n      include: ['pattern'],\n      exclude: ['pattern'],\n    },\n  })\n})\n\ntest('fails when an array is passed down for a single value', async () => {\n  expect(() => getCLIOptions('--coverage.provider v8 --coverage.provider istanbul'))\n    .toThrowErrorMatchingInlineSnapshot(`[Error: Expected a single value for option \"--coverage.provider <name>\", received [\"v8\", \"istanbul\"]]`)\n})\n\ntest('coverage autoUpdate accepts boolean values from CLI', async () => {\n  expect(getCLIOptions('--coverage.thresholds.autoUpdate true').coverage.thresholds.autoUpdate).toBe(true)\n  expect(getCLIOptions('--coverage.thresholds.autoUpdate false').coverage.thresholds.autoUpdate).toBe(false)\n  expect(getCLIOptions('--coverage.thresholds.autoUpdate yes').coverage.thresholds.autoUpdate).toBe(true)\n  expect(getCLIOptions('--coverage.thresholds.autoUpdate no').coverage.thresholds.autoUpdate).toBe(false)\n})\n\ntest('bench only options', async () => {\n  expect(() =>\n    parseArguments('--compare file.json').matchedCommand?.checkUnknownOptions(),\n  ).toThrowErrorMatchingInlineSnapshot(\n    `[CACError: Unknown option \\`--compare\\`]`,\n  )\n\n  expect(() =>\n    parseArguments(\n      'bench --compare file.json',\n    ).matchedCommand?.checkUnknownOptions(),\n  ).not.toThrow()\n\n  expect(parseArguments('bench --compare file.json').options).toEqual({\n    compare: 'file.json',\n  })\n})\n\ntest('even if coverage is boolean, don\\'t fail', () => {\n  expect(getCLIOptions('--coverage --coverage.provider v8').coverage).toEqual({\n    enabled: true,\n    provider: 'v8',\n  })\n})\n\ntest('array options', () => {\n  expect(getCLIOptions('--reporter json --coverage.reporter=html --coverage.exclude utils')).toMatchInlineSnapshot(`\n    {\n      \"coverage\": {\n        \"exclude\": [\n          \"utils\",\n        ],\n        \"reporter\": [\n          \"html\",\n        ],\n      },\n      \"reporter\": [\n        \"json\",\n      ],\n    }\n  `)\n\n  expect(getCLIOptions(`\n  --reporter json\n  --reporter=default\n  --coverage.reporter=json\n  --coverage.reporter html\n  --coverage.exclude=utils\n  --coverage.exclude=components\n  `)).toMatchInlineSnapshot(`\n    {\n      \"coverage\": {\n        \"exclude\": [\n          \"utils\",\n          \"components\",\n        ],\n        \"reporter\": [\n          \"json\",\n          \"html\",\n        ],\n      },\n      \"reporter\": [\n        \"json\",\n        \"default\",\n      ],\n    }\n  `)\n})\n\ntest('hookTimeout is parsed correctly', () => {\n  expect(getCLIOptions('--hookTimeout 1000')).toEqual({ hookTimeout: 1000 })\n  expect(getCLIOptions('--hook-timeout 1000')).toEqual({ hookTimeout: 1000 })\n  expect(getCLIOptions('--hook-timeout=1000')).toEqual({ hookTimeout: 1000 })\n  expect(getCLIOptions('--hookTimeout=1000')).toEqual({ hookTimeout: 1000 })\n})\n\ntest('teardownTimeout is parsed correctly', () => {\n  expect(getCLIOptions('--teardownTimeout 1000')).toEqual({ teardownTimeout: 1000 })\n  expect(getCLIOptions('--teardown-timeout 1000')).toEqual({ teardownTimeout: 1000 })\n  expect(getCLIOptions('--teardownTimeout=1000')).toEqual({ teardownTimeout: 1000 })\n  expect(getCLIOptions('--teardown-timeout=1000')).toEqual({ teardownTimeout: 1000 })\n})\n\ntest('slowTestThreshold is parsed correctly', () => {\n  expect(getCLIOptions('--slowTestThreshold 1000')).toEqual({ slowTestThreshold: 1000 })\n  expect(getCLIOptions('--slow-test-threshold 1000')).toEqual({ slowTestThreshold: 1000 })\n  expect(getCLIOptions('--slowTestThreshold=1000')).toEqual({ slowTestThreshold: 1000 })\n  expect(getCLIOptions('--slow-test-threshold=1000')).toEqual({ slowTestThreshold: 1000 })\n})\n\ntest('maxConcurrency is parsed correctly', () => {\n  expect(getCLIOptions('--maxConcurrency 1000')).toEqual({ maxConcurrency: 1000 })\n  expect(getCLIOptions('--max-concurrency 1000')).toEqual({ maxConcurrency: 1000 })\n  expect(getCLIOptions('--maxConcurrency=1000')).toEqual({ maxConcurrency: 1000 })\n  expect(getCLIOptions('--max-concurrency=1000')).toEqual({ maxConcurrency: 1000 })\n})\n\ntest('cache is parsed correctly', () => {\n  expect(getCLIOptions('--cache')).toEqual({ cache: {} })\n  expect(getCLIOptions('--no-cache')).toEqual({ cache: false })\n  expect(() => getCLIOptions('--cache.dir=./cache')).toThrow('--cache.dir is deprecated')\n})\n\ntest('shuffle is parsed correctly', () => {\n  expect(getCLIOptions('--sequence.shuffle')).toEqual({ sequence: { shuffle: true } })\n  expect(getCLIOptions('--sequence.shuffle=false')).toEqual({ sequence: { shuffle: false } })\n  expect(getCLIOptions('--sequence.shuffle.files --sequence.shuffle.tests')).toEqual({ sequence: { shuffle: { files: true, tests: true } } })\n  expect(getCLIOptions('--sequence.shuffle.files=false --sequence.shuffle.tests=false')).toEqual({ sequence: { shuffle: { files: false, tests: false } } })\n})\n\ntest('typecheck correctly passes down arguments', () => {\n  const { options, args } = parseArguments('--typecheck some.name.ts')\n  expect(options).toEqual({ typecheck: { enabled: true } })\n  expect(args).toEqual(['some.name.ts'])\n})\n\ntest('browser as implicit boolean', () => {\n  const { options, args } = parseArguments('--browser', false)\n  expect(options).toEqual({ browser: { enabled: true } })\n  expect(args).toEqual([])\n})\n\ntest('browser as explicit boolean', () => {\n  const { options, args } = parseArguments('--browser=true', false)\n  expect(options).toEqual({ browser: { enabled: true } })\n  expect(args).toEqual([])\n})\n\ntest('browser as explicit boolean with space', () => {\n  const { options, args } = parseArguments('--browser true', false)\n  expect(options).toEqual({ browser: { enabled: true } })\n  expect(args).toEqual([])\n})\n\ntest('browser by name', () => {\n  const { options, args } = parseArguments('--browser=firefox', false)\n\n  expect(args).toEqual([])\n  expect(options).toEqual({ browser: { name: 'firefox' } })\n})\n\ntest('browser.detailsPanelPosition is parsed correctly', () => {\n  expect(getCLIOptions('--browser.detailsPanelPosition=bottom')).toEqual({\n    browser: { detailsPanelPosition: 'bottom' },\n  })\n  expect(getCLIOptions('--browser.detailsPanelPosition right')).toEqual({\n    browser: { detailsPanelPosition: 'right' },\n  })\n  expect(getCLIOptions('--browser.detailsPanelPosition=bottom')).toEqual({\n    browser: { detailsPanelPosition: 'bottom' },\n  })\n})\n\ntest('clearScreen', async (ctx) => {\n  // skip vm since rolldown native modules break due to RegExp instance\n  // https://github.com/vitest-dev/vitest/issues/8754#issuecomment-3727583957\n  ctx.skip(!!rolldownVersion && ctx.task.file.projectName === 'vmThreads')\n\n  const examples = [\n    // vitest cli | vite clearScreen\n    ['--clearScreen', undefined],\n    ['--clearScreen', true],\n    ['--clearScreen', false],\n    ['--no-clearScreen', undefined],\n    ['--no-clearScreen', true],\n    ['--no-clearScreen', false],\n    ['', undefined],\n    ['', true],\n    ['', false],\n  ] as const\n  const baseViteConfig = await viteResolveConfig({ configFile: false }, 'serve')\n  const results = examples.map(([vitestClearScreen, viteClearScreen]) => {\n    const viteConfig = {\n      ...baseViteConfig,\n      clearScreen: viteClearScreen,\n    }\n    const vitestConfig = getCLIOptions(vitestClearScreen)\n    const config = resolveConfig({\n      logger: undefined,\n      mode: 'test',\n      _cliOptions: {},\n    } as any, vitestConfig, viteConfig)\n    return config.clearScreen\n  })\n  expect(results).toMatchInlineSnapshot(`\n    [\n      true,\n      true,\n      true,\n      false,\n      false,\n      false,\n      true,\n      true,\n      false,\n    ]\n  `)\n})\n\ntest('merge-reports', () => {\n  expect(getCLIOptions('--merge-reports')).toEqual({ mergeReports: '.vitest-reports' })\n  expect(getCLIOptions('--merge-reports=different-folder')).toEqual({ mergeReports: 'different-folder' })\n  expect(getCLIOptions('--merge-reports different-folder')).toEqual({ mergeReports: 'different-folder' })\n})\n\ntest('configure expect', () => {\n  expect(() => getCLIOptions('vitest --expect.poll=1000')).toThrowErrorMatchingInlineSnapshot(`[TypeError: Unexpected value for --expect.poll: true. If you need to configure timeout, use --expect.poll.timeout=<timeout>]`)\n  expect(() => getCLIOptions('vitest --expect=1000')).toThrowErrorMatchingInlineSnapshot(`[TypeError: Unexpected value for --expect: true. If you need to configure expect options, use --expect.{name}=<value> syntax]`)\n  expect(getCLIOptions('vitest --expect.poll.interval=100 --expect.poll.timeout=300')).toEqual({\n    expect: {\n      poll: {\n        interval: 100,\n        timeout: 300,\n      },\n    },\n  })\n  expect(getCLIOptions('vitest --expect.requireAssertions')).toEqual({\n    expect: {\n      requireAssertions: true,\n    },\n  })\n})\n\ntest('silent', () => {\n  expect(getCLIOptions('--silent')).toEqual({ silent: true })\n  expect(getCLIOptions('--silent=true')).toEqual({ silent: true })\n  expect(getCLIOptions('--silent=yes')).toEqual({ silent: true })\n\n  expect(getCLIOptions('--silent=false')).toEqual({ silent: false })\n  expect(getCLIOptions('--silent=no')).toEqual({ silent: false })\n\n  expect(getCLIOptions('--silent=passed-only')).toEqual({ silent: 'passed-only' })\n  expect(getCLIOptions('--silent=true example.test.ts')).toEqual({ silent: true })\n\n  expect(() => getCLIOptions('--silent example.test.ts')).toThrowErrorMatchingInlineSnapshot(`[TypeError: Unexpected value \"--silent=example.test.ts\". Use \"--silent=true example.test.ts\" instead.]`)\n})\n\ntest('public parseCLI works correctly', () => {\n  expect(parseCLI('vitest dev')).toEqual({\n    filter: [],\n    options: {\n      'watch': true,\n      '--': [],\n      'color': true,\n    },\n  })\n  expect(parseCLI('vitest watch')).toEqual({\n    filter: [],\n    options: {\n      'watch': true,\n      '--': [],\n      'color': true,\n    },\n  })\n  expect(parseCLI('vitest run')).toEqual({\n    filter: [],\n    options: {\n      'run': true,\n      '--': [],\n      'color': true,\n    },\n  })\n  expect(parseCLI('vitest run --watch')).toEqual({\n    filter: [],\n    options: {\n      'watch': true,\n      'w': true,\n      '--': [],\n      'color': true,\n    },\n  })\n  expect(parseCLI('vitest related ./some-files.js')).toEqual({\n    filter: [],\n    options: {\n      'passWithNoTests': true,\n      'related': ['./some-files.js'],\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(parseCLI('vitest --coverage --browser=chrome')).toEqual({\n    filter: [],\n    options: {\n      'coverage': { enabled: true },\n      'browser': { name: 'chrome' },\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(parseCLI('vitest ./tests.js --coverage')).toEqual({\n    filter: ['./tests.js'],\n    options: {\n      'coverage': { enabled: true },\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(parseCLI('vitest ./tests.js --coverage --custom-options', { allowUnknownOptions: true })).toEqual({\n    filter: ['./tests.js'],\n    options: {\n      'coverage': { enabled: true },\n      'customOptions': true,\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(() => {\n    parseCLI('node --test --coverage --browser --typecheck')\n  }).toThrow(`Expected \"vitest\" as the first argument, received \"node\"`)\n\n  expect(parseCLI('vitest --project=space_1 --project=space_2')).toEqual({\n    filter: [],\n    options: {\n      'project': ['space_1', 'space_2'],\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(parseCLI('vitest --project=\"space 1\"')).toEqual({\n    filter: [],\n    options: {\n      'project': ['space 1'],\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(parseCLI('vitest \"--project=space 1\"')).toEqual({\n    filter: [],\n    options: {\n      'project': ['space 1'],\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(parseCLI('vitest --project \"space 1\"')).toEqual({\n    filter: [],\n    options: {\n      'project': ['space 1'],\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(parseCLI('vitest --project=\"space 1\" --project=\"space 2\"')).toEqual({\n    filter: [],\n    options: {\n      'project': ['space 1', 'space 2'],\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(parseCLI('vitest ./test-1.js ./test-2.js --project=\"space 1\" --project=\"space 2\" --project=\"space 3\"')).toEqual({\n    filter: ['./test-1.js', './test-2.js'],\n    options: {\n      'project': ['space 1', 'space 2', 'space 3'],\n      '--': [],\n      'color': true,\n    },\n  })\n\n  expect(parseCLI('vitest --exclude=docs --exclude=demo')).toEqual({\n    filter: [],\n    options: {\n      'exclude': ['docs', 'demo'],\n      '--': [],\n      'color': true,\n    },\n  })\n})\n\ntest('should include builtin reporters list', () => {\n  let helpText = ''\n  vitestCli.help((sections) => {\n    for (const section of sections) {\n      helpText += section.body\n    }\n  })\n  vitestCli.parse(['node', '/index.js', '--help'], { run: false })\n  const match = helpText.match(/--reporter[^(]*\\(([^)]+)\\)/)\n  expect(match).not.toBeNull()\n\n  const listed = match![1].split(',').map(s => s.trim()).filter(Boolean)\n  const expected = Object.keys(ReportersMap)\n  expect(new Set(listed)).toEqual(new Set(expected))\n})\n\ntest('execArgv can be passed', async () => {\n  expect(getCLIOptions('--execArgv=--cpu-prof')).toEqual({\n    execArgv: ['--cpu-prof'],\n  })\n\n  expect(getCLIOptions('--execArgv=--cpu-prof --execArgv=--cpu-prof-dir=./cpu')).toEqual({\n    execArgv: ['--cpu-prof', '--cpu-prof-dir=./cpu'],\n  })\n})\n"
  },
  {
    "path": "test/core/test/concurrent-suite.test.ts",
    "content": "import { createDefer } from '@vitest/utils/helpers'\nimport { afterAll, beforeAll, describe, expect, test } from 'vitest'\n\ndescribe('basic', () => {\n  const defers = [\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n  ]\n\n  afterAll(async () => {\n    await defers[3]\n  })\n\n  describe('1st suite', { concurrent: true }, () => {\n    test('0', async () => {\n      defers[0].resolve()\n    })\n\n    test('1', async () => {\n      await defers[2] // this would deadlock if sequential\n      defers[1].resolve()\n    })\n  })\n\n  describe('2nd suite', { concurrent: true }, () => {\n    test('2', async () => {\n      await defers[0]\n      defers[2].resolve()\n    })\n    test('3', async () => {\n      await defers[1]\n      defers[3].resolve()\n    })\n  })\n})\n\ndescribe('inherits option', { concurrent: true }, () => {\n  const defers = [\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n  ]\n\n  afterAll(async () => {\n    await defers[3]\n  })\n\n  describe('1st suite', () => {\n    test('0', async () => {\n      defers[0].resolve()\n    })\n\n    test('1', async () => {\n      await defers[2] // this would deadlock if sequential\n      defers[1].resolve()\n    })\n  })\n\n  describe('2nd suite', () => {\n    test('2', async () => {\n      await defers[0]\n      defers[2].resolve()\n    })\n    test('3', async () => {\n      await defers[1]\n      defers[3].resolve()\n    })\n  })\n})\n\ndescribe('works with describe.each', () => {\n  const defers = [\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n    createDefer<void>(),\n  ]\n\n  afterAll(async () => {\n    await defers[3]\n  })\n\n  describe.each(['1st suite', '2nd suite'])('%s', { concurrent: true }, (s) => {\n    if (s === '1st suite') {\n      test('0', async () => {\n        defers[0].resolve()\n      })\n\n      test('1', async () => {\n        await defers[2] // this would deadlock if sequential\n        defers[1].resolve()\n      })\n    }\n\n    if (s === '2nd suite') {\n      test('2', async () => {\n        await defers[0]\n        defers[2].resolve()\n      })\n      test('3', async () => {\n        await defers[1]\n        defers[3].resolve()\n      })\n    }\n  })\n})\n\ndescribe('override concurrent', { concurrent: true }, () => {\n  checkParallelSuites()\n\n  describe('s-x', { concurrent: false }, () => {\n    checkSequentialTests()\n  })\n\n  describe.sequential('s-x-1', () => {\n    checkSequentialTests()\n  })\n\n  describe('s-x-2', { sequential: true }, () => {\n    checkSequentialTests()\n  })\n\n  describe('s-y', () => {\n    checkParallelTests()\n  })\n})\n\nconst sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))\n\nfunction checkSequentialTests() {\n  let x = 0\n\n  test('t1', async () => {\n    await sleep(200)\n    expect(x).toBe(0)\n    x++\n  })\n\n  test('t2', async () => {\n    expect(x).toBe(1)\n  })\n}\n\nfunction checkParallelTests() {\n  const defers = [\n    createDefer<void>(),\n    createDefer<void>(),\n  ]\n\n  test('t1', async () => {\n    defers[0].resolve()\n    await defers[1]\n  })\n\n  test('t2', async () => {\n    await defers[0]\n    defers[1].resolve()\n  })\n}\n\nfunction checkParallelSuites() {\n  const defers = [\n    createDefer<void>(),\n    createDefer<void>(),\n  ]\n\n  describe('s1', () => {\n    test('t1', async () => {\n      defers[0].resolve()\n      await defers[1]\n    })\n  })\n\n  describe('s2', () => {\n    test('t1', async () => {\n      await defers[0]\n      defers[1].resolve()\n    })\n  })\n}\n\ndescribe('suite hook concurrency', () => {\n  const logs: string[] = []\n\n  afterAll(() => {\n    expect(logs).toEqual(['s2-before', 's2-after', 's1-before', 's1-before-2', 's1-after-2', 's1-after'])\n  })\n\n  describe.concurrent('s1', () => {\n    // before/afterAll inside same suite runs sequentially in stack order\n    beforeAll(async () => {\n      await sleep(200)\n      logs.push('s1-before')\n    })\n\n    beforeAll(async () => {\n      logs.push('s1-before-2')\n    })\n\n    afterAll(async () => {\n      logs.push('s1-after')\n    })\n\n    afterAll(async () => {\n      logs.push('s1-after-2')\n    })\n\n    test('s1-t', () => {})\n  })\n\n  describe.concurrent('s2', () => {\n    // before/afterAll in neighboring concurrent suite runs in parallel\n    beforeAll(async () => {\n      logs.push('s2-before')\n    })\n\n    afterAll(async () => {\n      logs.push('s2-after')\n    })\n\n    test('s2-t', () => {})\n  })\n})\n"
  },
  {
    "path": "test/core/test/concurrent.spec.ts",
    "content": "import { test } from 'vitest'\n\nfunction delay(ms: number) {\n  return new Promise(resolve => setTimeout(resolve, ms))\n}\n\ntest.concurrent('test1', async ({ expect }) => {\n  expect.assertions(1)\n  await delay(10).then(() => {\n    expect(1).eq(1)\n  })\n})\n\ntest.concurrent('test2', async ({ expect }) => {\n  expect.assertions(1)\n  await delay(100).then(() => {\n    expect(2).eq(2)\n  })\n})\n"
  },
  {
    "path": "test/core/test/custom.test.ts",
    "content": "import {\n  afterAll,\n  afterEach,\n  beforeAll,\n  beforeEach,\n  describe,\n  expect,\n  test,\n  TestRunner,\n} from 'vitest'\nimport { Gardener } from '../src/custom/gardener.js'\n\ndeclare module 'vitest' {\n  interface TaskMeta {\n    customPropertyToDifferentiateTask?: boolean\n  }\n}\n\n// this function will be called, when Vitest collects tasks\nconst myCustomTask = TestRunner.createChainable(['todo'], function (name: string, fn: () => void) {\n  TestRunner.getCurrentSuite().task(name, {\n    ...this,\n    meta: {\n      customPropertyToDifferentiateTask: true,\n    },\n    handler: fn,\n  })\n})\n\nconst gardener = new Gardener()\n\ndescribe('take care of the garden', () => {\n  beforeAll(() => {\n    gardener.putWorkingClothes()\n  })\n\n  beforeEach(() => {\n    gardener.standup()\n  })\n\n  afterEach(() => {\n    gardener.rest()\n  })\n\n  myCustomTask('weed the grass', () => {\n    gardener.weedTheGrass()\n  })\n  myCustomTask.todo('mow the lawn', () => {\n    gardener.mowerTheLawn()\n  })\n  myCustomTask('water flowers', () => {\n    gardener.waterFlowers()\n  })\n\n  afterAll(() => {\n    gardener.goHome()\n  })\n})\n\ntest('states are filled correctly', () => {\n  expect(gardener.states).toEqual([\n    'wake up',\n    'working clothes',\n    'standup',\n    'weed the grass',\n    'rest',\n    'standup',\n    'water flowers',\n    'rest',\n    'home',\n  ])\n})\n"
  },
  {
    "path": "test/core/test/date-mock.test.ts",
    "content": "import { afterEach, describe, expect, test, vi } from 'vitest'\n\ndescribe('testing date mock functionality', () => {\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  test('setting time in the past', () => {\n    const date = new Date(2000, 1, 1)\n\n    vi.setSystemTime(date)\n\n    expect(Date.now()).toBe(date.valueOf())\n    expect(vi.getMockedSystemTime()).toBe(date)\n\n    vi.useRealTimers()\n\n    expect(Date.now()).not.toBe(date.valueOf())\n    expect(vi.getMockedSystemTime()).not.toBe(date)\n  })\n\n  test('setting time in different types', () => {\n    const time = 1234567890\n\n    vi.setSystemTime(time)\n\n    expect(Date.now()).toBe(time)\n\n    const timeStr = 'Fri Feb 20 2015 19:29:31 GMT+0530'\n    const timeStrMs = 1424440771000\n\n    vi.setSystemTime(timeStr)\n\n    expect(Date.now()).toBe(timeStrMs)\n  })\n\n  test('date prototype is correct', () => {\n    vi.setSystemTime(new Date(2000, 1, 1))\n\n    expect(new Date()).toBeInstanceOf(Date)\n  })\n})\n"
  },
  {
    "path": "test/core/test/define-ssr.test.ts",
    "content": "import { afterAll, expect, test } from 'vitest'\n\ndeclare let __DEFINE__: string\ndeclare let __JSON__: any\ndeclare let __MODE__: string\ndeclare let __UNDEFINED__: undefined\ndeclare let __NULL__: null\ndeclare let __ZERO__: 0\ndeclare let __FALSE__: false\ndeclare let SOME: {\n  VARIABLE: string\n  SOME: {\n    VARIABLE: string\n  }\n}\n\n// functions to test that they are not statically replaced\nfunction get__DEFINE__() {\n  return __DEFINE__\n}\nfunction get__JSON__() {\n  return __JSON__\n}\nfunction get__MODE__() {\n  return __MODE__\n}\n\nconst MODE = process.env.MODE\n\nafterAll(() => {\n  process.env.MODE = MODE\n})\n\ntest('automatically remove process and global', () => {\n  expect(Object.keys(process).length > 1).toBe(true)\n  expect(Object.keys(globalThis).length > 1).toBe(true)\n})\n\ntest('process.env.HELLO_PROCESS is defined on \"defined\" but exists on process.env', () => {\n  expect('HELLO_PROCESS' in process.env).toBe(true)\n  expect(process.env.HELLO_PROCESS).toBe('hello process')\n})\n\ntest('can redeclare standard define', () => {\n  expect(get__DEFINE__()).toBe('defined')\n  __DEFINE__ = 'new defined'\n  expect(get__DEFINE__()).toBe('new defined')\n})\n\ntest('can redeclare json object', () => {\n  expect(get__JSON__()).toEqual({ hello: 'world' })\n  __JSON__ = { hello: 'test' }\n  const name = '__JSON__'\n  expect(get__JSON__()).toEqual({ hello: 'test' })\n  expect((globalThis as any)[name]).toEqual({ hello: 'test' })\n})\n\ntest('reassigning __MODE__', () => {\n  const env = process.env.MODE\n  expect(get__MODE__()).toBe(env)\n  process.env.MODE = 'development'\n  expect(get__MODE__()).toBe('development')\n})\n\ntest('dotted defines are processed by Vite, but cannot be reassigned', () => {\n  expect(SOME.VARIABLE).toBe('variable')\n  expect(SOME.SOME.VARIABLE).toBe('nested variable')\n  SOME.VARIABLE = 'new variable'\n  expect(SOME.VARIABLE).not.toBe('new variable')\n})\n\ntest('falsy defines are passed', () => {\n  expect(__UNDEFINED__).toBe(undefined)\n  expect(__NULL__).toBe(null)\n  expect(__ZERO__).toBe(0)\n  expect(__FALSE__).toBe(false)\n})\n"
  },
  {
    "path": "test/core/test/define-web.test.ts",
    "content": "// @vitest-environment jsdom\n\nimport { afterAll, expect, test } from 'vitest'\n\ndeclare let __DEFINE__: string\ndeclare let __JSON__: any\ndeclare let __MODE__: string\ndeclare let __UNDEFINED__: undefined\ndeclare let __NULL__: null\ndeclare let __ZERO__: 0\ndeclare let __FALSE__: false\ndeclare let SOME: {\n  VARIABLE: string\n  SOME: {\n    VARIABLE: string\n  }\n}\n\n// functions to test that they are not statically replaced\nfunction get__DEFINE__() {\n  return __DEFINE__\n}\nfunction get__JSON__() {\n  return __JSON__\n}\nfunction get__MODE__() {\n  return __MODE__\n}\n\nconst MODE = process.env.MODE\n\nafterAll(() => {\n  process.env.MODE = MODE\n})\n\ntest('process.env.HELLO_PROCESS is defined on \"defined\" but exists on process.env', () => {\n  expect('HELLO_PROCESS' in process.env).toBe(true)\n  expect(process.env.HELLO_PROCESS).toBe('hello process')\n})\n\ntest('can redeclare standard define', () => {\n  expect(get__DEFINE__()).toBe('defined')\n  __DEFINE__ = 'new defined'\n  expect(get__DEFINE__()).toBe('new defined')\n})\n\ntest('can redeclare json object', () => {\n  expect(get__JSON__()).toEqual({ hello: 'world' })\n  __JSON__ = { hello: 'test' }\n  const name = '__JSON__'\n  expect(get__JSON__()).toEqual({ hello: 'test' })\n  expect((globalThis as any)[name]).toEqual({ hello: 'test' })\n})\n\ntest('reassigning complicated __MODE__', () => {\n  const env = process.env.MODE\n  expect(get__MODE__()).toBe(env)\n  process.env.MODE = 'development'\n  expect(get__MODE__()).not.toBe('development')\n})\n\ntest('dotted defines can be reassigned', () => {\n  expect(SOME.VARIABLE).toBe('variable')\n  expect(SOME.SOME.VARIABLE).toBe('nested variable')\n  SOME.VARIABLE = 'new variable'\n  expect(SOME.VARIABLE).toBe('new variable')\n})\n\ntest('falsy defines are passed', () => {\n  expect(__UNDEFINED__).toBe(undefined)\n  expect(__NULL__).toBe(null)\n  expect(__ZERO__).toBe(0)\n  expect(__FALSE__).toBe(false)\n})\n"
  },
  {
    "path": "test/core/test/diff.test.ts",
    "content": "import type { DiffOptions } from '@vitest/utils/diff'\nimport { stripVTControlCharacters } from 'node:util'\nimport { diff, diffStringsUnified, printDiffOrStringify } from '@vitest/utils/diff'\nimport { processError } from '@vitest/utils/error'\nimport { expect, test } from 'vitest'\n\nfunction wrapDiff(diff?: string) {\n  return diff && stripVTControlCharacters(`\\n${diff}\\n`)\n}\n\ntest('displays string diff', () => {\n  const stringA = 'Hello AWorld'\n  const stringB = 'Hello BWorld'\n  expect(wrapDiff(printDiffOrStringify(stringA, stringB))).toMatchInlineSnapshot(`\n    \"\n    Expected: \"Hello BWorld\"\n    Received: \"Hello AWorld\"\n    \"\n  `)\n})\n\ntest('displays object diff', () => {\n  const objectA = { a: 1, b: 2 }\n  const objectB = { a: 1, b: 3 }\n  expect(wrapDiff(diff(objectA, objectB))).toMatchInlineSnapshot(`\n    \"\n    - Expected\n    + Received\n\n      {\n        \"a\": 1,\n    -   \"b\": 2,\n    +   \"b\": 3,\n      }\n    \"\n  `)\n})\n\ntest('display truncated object diff', () => {\n  const objectA = { a: 1, b: 2, c: 3, d: 4, e: 5 }\n  const objectB = { a: 1, b: 3, c: 4, d: 5, e: 6 }\n  expect(wrapDiff(diff(objectA, objectB, { truncateThreshold: 4 }))).toMatchInlineSnapshot(`\n    \"\n    - Expected\n    + Received\n\n      {\n        \"a\": 1,\n    -   \"b\": 2,\n    -   \"c\": 3,\n    +   \"b\": 3,\n    +   \"c\": 4,\n    ... Diff result is truncated\n    \"\n  `)\n})\n\ntest('display one line string diff', () => {\n  const string1 = 'string1'\n  const string2 = 'string2'\n  expect(wrapDiff(diff(string1, string2))).toMatchInlineSnapshot(`\n    \"\n    - Expected\n    + Received\n\n    - string1\n    + string2\n    \"\n  `)\n})\n\ntest('display one line string diff should not be affected by truncateThreshold', () => {\n  const string1 = 'string1'\n  const string2 = 'string2'\n  expect(wrapDiff(diff(string1, string2, { truncateThreshold: 3 }))).toMatchInlineSnapshot(`\n    \"\n    - Expected\n    + Received\n\n    - string1\n    + string2\n    \"\n  `)\n})\n\ntest('display multiline string diff', () => {\n  const string1 = 'string1\\nstring2\\nstring3'\n  const string2 = 'string2\\nstring2\\nstring1'\n  expect(wrapDiff(diff(string1, string2))).toMatchInlineSnapshot(`\n    \"\n    - Expected\n    + Received\n\n    - string1\n      string2\n    - string3\n    + string2\n    + string1\n    \"\n  `)\n})\n\ntest('display truncated multiline string diff', () => {\n  const string1 = 'string1\\nstring2\\nstring3'\n  const string2 = 'string2\\nstring2\\nstring1'\n  expect(wrapDiff(diff(string1, string2, { truncateThreshold: 2 }))).toMatchInlineSnapshot(`\n    \"\n    - Expected\n    + Received\n\n    - string1\n    + string2\n      string2\n    ... Diff result is truncated\n    \"\n  `)\n})\n\ntest('display truncated multiple items array diff', () => {\n  const array1 = Array.from({ length: 45000 }).fill('foo')\n  const array2 = Array.from({ length: 45000 }).fill('bar')\n  expect(wrapDiff(diff(array1, array2, { truncateThreshold: 3 }))).toMatchInlineSnapshot(`\n    \"\n    - Expected\n    + Received\n\n      [\n    -   \"foo\",\n    -   \"foo\",\n    +   \"bar\",\n    +   \"bar\",\n    ... Diff result is truncated\n    \"\n  `)\n})\n\ntest('asymmetric matcher in object', () => {\n  expect(stripVTControlCharacters(getErrorDiff({ x: 0, y: 'foo' }, { x: 1, y: expect.anything() }))).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n      {\n    -   \"x\": 1,\n    +   \"x\": 0,\n        \"y\": \"foo\",\n      }\"\n  `)\n})\n\ntest('asymmetric matcher in object with truncated diff', () => {\n  expect(\n    stripVTControlCharacters(getErrorDiff(\n      { w: 'foo', x: 0, y: 'bar', z: 'baz' },\n      { w: expect.anything(), x: 1, y: expect.anything(), z: 'bar' },\n      { truncateThreshold: 3 },\n    )),\n  ).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n      {\n        \"w\": \"foo\",\n    -   \"x\": 1,\n    +   \"x\": 0,\n    ... Diff result is truncated\"\n  `)\n})\n\ntest('asymmetric matcher in array', () => {\n  expect(stripVTControlCharacters(getErrorDiff([0, 'foo'], [1, expect.anything()]))).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n      [\n    -   1,\n    +   0,\n        \"foo\",\n      ]\"\n  `)\n})\n\ntest('asymmetric matcher in array  with truncated diff', () => {\n  expect(\n    stripVTControlCharacters(getErrorDiff(\n      [0, 'foo', 2],\n      [1, expect.anything(), 3],\n      { truncateThreshold: 2 },\n    )),\n  ).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n      [\n    -   1,\n    +   0,\n    ... Diff result is truncated\"\n  `)\n})\n\ntest('asymmetric matcher in nested', () => {\n  expect(\n    stripVTControlCharacters(getErrorDiff(\n      [{ x: 0, y: 'foo' }, [0, 'bar']],\n      [{ x: 1, y: expect.anything() }, [1, expect.anything()]],\n    )),\n  ).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n      [\n        {\n    -     \"x\": 1,\n    +     \"x\": 0,\n          \"y\": \"foo\",\n        },\n        [\n    -     1,\n    +     0,\n          \"bar\",\n        ],\n      ]\"\n  `)\n})\n\ntest('asymmetric matcher in nested with truncated diff', () => {\n  expect(\n    stripVTControlCharacters(getErrorDiff(\n      [{ x: 0, y: 'foo', z: 'bar' }, [0, 'bar', 'baz']],\n      [{ x: 1, y: expect.anything(), z: expect.anything() }, [1, expect.anything(), expect.anything()]],\n      { truncateThreshold: 5 },\n    )),\n  ).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n      [\n        {\n    -     \"x\": 1,\n    +     \"x\": 0,\n          \"y\": \"foo\",\n          \"z\": \"bar\",\n    ... Diff result is truncated\"\n  `)\n})\n\ntest('diff for multi-line string compared by characters', () => {\n  const string1 = `\n  foo,\n  bar,\n  `\n  const string2 = `\n  FOO,\n  bar,\n  `\n  expect(\n    stripVTControlCharacters(diffStringsUnified(string1, string2)),\n  ).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n\n    -   foo,\n    +   FOO,\n        bar,\n        \"\n  `)\n})\n\ntest('truncated diff for multi-line string compared by characters', () => {\n  const string1 = `\n  foo,\n  bar,\n  baz,\n  `\n  const string2 = `\n  FOO,\n  bar,\n  BAZ,\n  `\n  expect(\n    stripVTControlCharacters(diffStringsUnified(string1, string2, { truncateThreshold: 3 })),\n  ).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n\n    -   foo,\n    +   FOO,\n        bar,\n    ... Diff result is truncated\"\n  `)\n})\n\ntest('getter only property', () => {\n  const x = { normalProp: 1 }\n  const y = { normalProp: 2 }\n  Object.defineProperty(x, 'getOnlyProp', {\n    enumerable: true,\n    get: () => ({ a: 'b' }),\n  })\n  Object.defineProperty(y, 'getOnlyProp', {\n    enumerable: true,\n    get: () => ({ a: 'b' }),\n  })\n  expect(\n    stripVTControlCharacters(getErrorDiff(x, y)),\n  ).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n      {\n        \"getOnlyProp\": {\n          \"a\": \"b\",\n        },\n    -   \"normalProp\": 2,\n    +   \"normalProp\": 1,\n      }\"\n  `)\n})\n\ntest('truncate large diff', () => {\n  const diff = getErrorDiff(Array.from({ length: 500_000 }).fill(0), 1234)\n  expect(diff.length).lessThan(200_000)\n  expect(diff.trim()).toMatch(/\\.\\.\\.$/)\n}, 60_000)\n\ntest('diff default maxDepth', () => {\n  function generateCycle(n: number) {\n    const nodes = Array.from({ length: n }, (_, i) => ({ i, next: null as any }))\n    nodes.forEach((node, i) => {\n      node.next = nodes[(i + 1) % n]\n    })\n    return nodes\n  }\n\n  // diff only appears in a deeper depth than maxDepth\n  const xs = generateCycle(20)\n  const ys = generateCycle(20)\n  ys[10].i = -1\n  const diff = getErrorDiff(xs[0], ys[0], { maxDepth: 5 })\n  expect(stripVTControlCharacters(diff)).toMatchInlineSnapshot(\n    `\"Compared values have no visual difference.\"`,\n  )\n})\n\nfunction getErrorDiff(actual: unknown, expected: unknown, options?: DiffOptions): string {\n  try {\n    expect(actual).toEqual(expected)\n  }\n  catch (e) {\n    const error = processError(e, options)\n    return error.diff!\n  }\n  return expect.unreachable()\n}\n\ntest('asymmetric matcher with objectContaining - simple case', () => {\n  const actual = {\n    user: {\n      name: 'John',\n      age: 25,\n      email: 'john@example.com',\n    },\n  }\n\n  const expected = {\n    user: expect.objectContaining({\n      name: expect.stringContaining('Jane'),\n      age: expect.any(Number),\n      email: expect.stringContaining('example.com'),\n    }),\n  }\n\n  expect(stripVTControlCharacters(getErrorDiff(actual, expected))).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n      {\n        \"user\": {\n          \"age\": 25,\n          \"email\": \"john@example.com\",\n    -     \"name\": StringContaining \"Jane\",\n    +     \"name\": \"John\",\n        },\n      }\"\n  `)\n})\n\ntest('asymmetric matcher with nested objectContaining and arrayContaining', () => {\n  const actual = {\n    model: 'veo-3.1-generate-preview',\n    instances: [\n      {\n        prompt: 'walk',\n        referenceImages: [\n          {\n            image: {\n              gcsUri: 'gs://example/person1.jpg',\n              mimeType: 'image/png',\n            },\n            referenceType: 'asset',\n          },\n          {\n            image: {\n              gcsUri: 'gs://example/person.jpg',\n              mimeType: 'image/png',\n            },\n            referenceType: 'asset',\n          },\n        ],\n      },\n    ],\n    parameters: {\n      durationSeconds: '8',\n      aspectRatio: '16:9',\n      generateAudio: true,\n    },\n  }\n\n  const expected = {\n    model: expect.stringMatching(/^veo-3\\.1-(fast-)?generate-preview$/),\n    instances: expect.arrayContaining([\n      expect.objectContaining({\n        prompt: expect.stringMatching(/^(?=.*walking)(?=.*together)(?=.*park).*/i),\n        referenceImages: expect.arrayContaining([\n          expect.objectContaining({\n            image: expect.objectContaining({\n              gcsUri: expect.stringContaining('person1.jpg'),\n              mimeType: 'image/jpeg',\n            }),\n            referenceType: expect.stringMatching(/^(asset|style)$/),\n          }),\n          expect.objectContaining({\n            image: expect.objectContaining({\n              gcsUri: expect.stringContaining('person2.png'),\n              mimeType: 'image/png',\n            }),\n            referenceType: expect.stringMatching(/^(asset|style)$/),\n          }),\n        ]),\n      }),\n    ]),\n    parameters: expect.objectContaining({\n      durationSeconds: expect.any(Number),\n      aspectRatio: '16:9',\n      generateAudio: expect.any(Boolean),\n    }),\n  }\n\n  expect(stripVTControlCharacters(getErrorDiff(actual, expected))).toMatchInlineSnapshot(`\n    \"- Expected\n    + Received\n\n      {\n        \"instances\": [\n          {\n    -       \"prompt\": StringMatching /^(?=.*walking)(?=.*together)(?=.*park).*/i,\n    +       \"prompt\": \"walk\",\n            \"referenceImages\": [\n              {\n                \"image\": {\n                  \"gcsUri\": \"gs://example/person1.jpg\",\n    -             \"mimeType\": \"image/jpeg\",\n    +             \"mimeType\": \"image/png\",\n                },\n                \"referenceType\": \"asset\",\n              },\n              {\n                \"image\": {\n    -             \"gcsUri\": StringContaining \"person2.png\",\n    +             \"gcsUri\": \"gs://example/person.jpg\",\n                  \"mimeType\": \"image/png\",\n                },\n                \"referenceType\": \"asset\",\n              },\n            ],\n          },\n        ],\n        \"model\": \"veo-3.1-generate-preview\",\n        \"parameters\": {\n          \"aspectRatio\": \"16:9\",\n    -     \"durationSeconds\": Any<Number>,\n    +     \"durationSeconds\": \"8\",\n          \"generateAudio\": true,\n        },\n      }\"\n  `)\n})\n"
  },
  {
    "path": "test/core/test/do-mock-reset-modules.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\ntest('multiple resetModules and doMock for indirect actual module', async () => {\n  vi.doUnmock('./fixtures/increment')\n\n  const { incrementIndirect: originalIncrement } = await import('./fixtures/increment-indirect')\n  expect(originalIncrement(1)).toBe(2)\n\n  vi.doMock('./fixtures/increment', () => ({\n    increment: (num: number) => num + 10,\n  }))\n  vi.resetModules()\n\n  const { incrementIndirect: incrementWith10 } = await import('./fixtures/increment-indirect')\n  expect(incrementWith10(1)).toBe(11)\n\n  vi.doMock('./fixtures/increment', () => ({\n    increment: (num: number) => num + 20,\n  }))\n  vi.resetModules()\n\n  const { incrementIndirect: incrementWith20 } = await import('./fixtures/increment-indirect')\n  expect(incrementWith20(1)).toBe(21)\n\n  vi.doMock('./fixtures/increment', () => ({\n    increment: (num: number) => num + 30,\n  }))\n\n  const { incrementIndirect: incrementWith20Still } = await import('./fixtures/increment-indirect')\n  expect(incrementWith20Still(1)).toBe(21)\n})\n\ntest('multiple doMock for direct virtual module', async () => {\n  // @ts-expect-error virtual module\n  const { value: originalValue } = await import('virtual-module-direct')\n  expect(originalValue).toBe('original-direct')\n\n  vi.doMock('virtual-module-direct', () => ({\n    value: 'direct-1',\n  }))\n\n  // @ts-expect-error virtual module\n  const { value: mockedValue1 } = await import('virtual-module-direct')\n  expect(mockedValue1).toBe('direct-1')\n\n  vi.doMock('virtual-module-direct', () => ({\n    value: 'direct-2',\n  }))\n\n  // @ts-expect-error virtual module\n  const { value: mockedValue2 } = await import('virtual-module-direct')\n  expect(mockedValue2).toBe('direct-2')\n})\n\ntest('multiple resetModules and doMock for indirect virtual module', async () => {\n  const { getVirtualValue: originalGetVirtualValue } = await import('./fixtures/virtual-module-indirect')\n  expect(originalGetVirtualValue()).toBe('original-indirect')\n\n  vi.doMock('virtual-module-indirect', () => ({ value: 'indirect-1' }))\n  vi.resetModules()\n\n  const { getVirtualValue: mockedGetVirtualValue1 } = await import('./fixtures/virtual-module-indirect')\n  expect(mockedGetVirtualValue1()).toBe('indirect-1')\n\n  vi.resetModules()\n  vi.doMock('virtual-module-indirect', () => ({ value: 'indirect-2' }))\n\n  const { getVirtualValue: mockedGetVirtualValue2 } = await import('./fixtures/virtual-module-indirect')\n  expect(mockedGetVirtualValue2()).toBe('indirect-2')\n})\n"
  },
  {
    "path": "test/core/test/do-mock.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\ntest('doMock works', async () => {\n  const { increment: incrementWith1 } = await import('./fixtures/increment')\n  expect(incrementWith1(1)).toBe(2)\n\n  vi.doMock('./fixtures/increment', () => ({\n    increment: (num: number) => num + 10,\n  }))\n\n  const { increment: incrementWith10 } = await import('./fixtures/increment')\n\n  expect(incrementWith10(1)).toBe(11)\n})\n\ntest('the second doMock can override the first doMock', async () => {\n  vi.doMock('./fixtures/increment', () => ({\n    increment: (num: number) => num + 10,\n  }))\n\n  const { increment: incrementWith1 } = await import('./fixtures/increment')\n\n  expect(incrementWith1(1)).toBe(11)\n\n  vi.doMock('./fixtures/increment', () => ({\n    increment: (num: number) => num + 20,\n  }))\n\n  const { increment: incrementWith20 } = await import('./fixtures/increment')\n\n  expect(incrementWith20(1)).toBe(21)\n})\n\ntest.runIf(Symbol.dispose)('doMock works with using', async () => {\n  vi.doUnmock('./fixtures/increment')\n\n  {\n    const { increment: incrementWith1 } = await import('./fixtures/increment')\n    expect(incrementWith1(1)).toBe(2)\n  }\n\n  {\n    using _incrementMock = vi.doMock('./fixtures/increment', () => ({\n      increment: (num: number) => num + 10,\n    }))\n\n    const { increment: incrementWith10 } = await import('./fixtures/increment')\n\n    expect(incrementWith10(1)).toBe(11)\n  }\n\n  {\n    const { increment: incrementWith1 } = await import('./fixtures/increment')\n    expect(incrementWith1(1)).toBe(2)\n  }\n})\n\ntest.skipIf(Symbol.dispose)('doMock works with using', async () => {\n  const _incrementMock = vi.doMock('./fixtures/increment', () => ({\n    increment: (num: number) => num + 10,\n  }))\n\n  expect(_incrementMock?.[Symbol.dispose]).toBeUndefined()\n})\n"
  },
  {
    "path": "test/core/test/dom-single-line-options.test.ts",
    "content": "/** @vitest-environment jsdom */\n\n/** @vitest-environment-options { \"url\": \"https://example.com/\" } */\n\nimport { expect, it } from 'vitest'\n\nit('parse single line environment options', () => expect(location.href).toBe('https://example.com/'))\n"
  },
  {
    "path": "test/core/test/dom.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n * @vitest-environment-options { \"url\": \"https://example.com/\" }\n */\n\n/* eslint-disable vars-on-top */\n\nimport { expect, it, vi } from 'vitest'\n\ndeclare global {\n\n  var __property_jsdom: unknown\n}\n\nit('jsdom', () => {\n  expect(window).toBeDefined()\n  expect(top).toBeDefined()\n  expect(parent).toBeDefined()\n  expect(self).toBeDefined()\n  expect(location.href).toBe('https://example.com/')\n\n  const dom = document.createElement('a')\n  dom.href = 'https://vitest.dev'\n  dom.textContent = '<Vitest>'\n\n  expect(dom.outerHTML).toEqual('<a href=\"https://vitest.dev\">&lt;Vitest&gt;</a>')\n})\n\nit('dispatchEvent doesn\\'t throw', () => {\n  const target = new EventTarget()\n  const event = new Event('click')\n  expect(() => target.dispatchEvent(event)).not.toThrow()\n})\n\nit('Non-public \"live\" keys work as expected', () => {\n  const img = new Image(100)\n  const audio = new Audio()\n  const option = new Option()\n\n  expect(img.width).toBe(100)\n  expect(audio).toBeInstanceOf(window.Audio)\n  expect(option).toBeInstanceOf(window.Option)\n})\n\nit('defined on self/window are defined on global', () => {\n  expect(self).toBeDefined()\n  expect(window).toBeDefined()\n\n  expect(self.__property_jsdom).not.toBeDefined()\n  expect(window.__property_jsdom).not.toBeDefined()\n  expect(globalThis.__property_jsdom).not.toBeDefined()\n\n  globalThis.__property_jsdom = 'defined_value'\n\n  expect(__property_jsdom).toBe('defined_value')\n  expect(self.__property_jsdom).toBe('defined_value')\n  expect(window.__property_jsdom).toBe('defined_value')\n  expect(globalThis.__property_jsdom).toBe('defined_value')\n\n  self.__property_jsdom = 'test_value'\n\n  expect(__property_jsdom).toBe('test_value')\n  expect(self.__property_jsdom).toBe('test_value')\n  expect(window.__property_jsdom).toBe('test_value')\n  expect(globalThis.__property_jsdom).toBe('test_value')\n\n  window.__property_jsdom = 'new_value'\n\n  expect(__property_jsdom).toBe('new_value')\n  expect(self.__property_jsdom).toBe('new_value')\n  expect(window.__property_jsdom).toBe('new_value')\n  expect(globalThis.__property_jsdom).toBe('new_value')\n\n  globalThis.__property_jsdom = 'global_value'\n\n  expect(__property_jsdom).toBe('global_value')\n  expect(self.__property_jsdom).toBe('global_value')\n  expect(window.__property_jsdom).toBe('global_value')\n  expect(globalThis.__property_jsdom).toBe('global_value')\n\n  const obj = {}\n\n  self.__property_jsdom = obj\n\n  expect(self.__property_jsdom).toBe(obj)\n  expect(window.__property_jsdom).toBe(obj)\n  expect(globalThis.__property_jsdom).toBe(obj)\n})\n\nit('usage with defineProperty', () => {\n  Object.defineProperty(self, '__property_jsdom', {\n    get: () => 'self_property',\n    configurable: true,\n  })\n\n  expect(__property_jsdom).toBe('self_property')\n  expect(self.__property_jsdom).toBe('self_property')\n  expect(globalThis.__property_jsdom).toBe('self_property')\n  expect(window.__property_jsdom).toBe('self_property')\n\n  Object.defineProperty(window, '__property_jsdom', {\n    get: () => 'window_property',\n    configurable: true,\n  })\n\n  expect(__property_jsdom).toBe('window_property')\n  expect(self.__property_jsdom).toBe('window_property')\n  expect(globalThis.__property_jsdom).toBe('window_property')\n  expect(window.__property_jsdom).toBe('window_property')\n\n  Object.defineProperty(globalThis, '__property_jsdom', {\n    get: () => 'global_property',\n    configurable: true,\n  })\n\n  expect(__property_jsdom).toBe('global_property')\n  expect(self.__property_jsdom).toBe('global_property')\n  expect(globalThis.__property_jsdom).toBe('global_property')\n  expect(window.__property_jsdom).toBe('global_property')\n})\n\nit('can call global functions without window works as expected', async () => {\n  const noop = vi.fn()\n\n  expect(() => addEventListener('abort', noop)).not.toThrow()\n  expect(() => requestAnimationFrame(noop)).not.toThrow()\n  expect(() => window.requestAnimationFrame(noop)).not.toThrow()\n  expect(() => self.requestAnimationFrame(noop)).not.toThrow()\n  expect(() => globalThis.requestAnimationFrame(noop)).not.toThrow()\n})\n\nit('globals are the same', () => {\n  expect(window).toBe(globalThis)\n  expect(window).toBe(global)\n  expect(window.globalThis).toBe(globalThis)\n  expect(window.Blob).toBe(globalThis.Blob)\n  expect(window.globalThis.Blob).toBe(globalThis.Blob)\n  expect(Blob).toBe(globalThis.Blob)\n  expect(document.defaultView).toBe(window)\n  const el = document.createElement('div')\n  expect(el.ownerDocument.defaultView).toBe(globalThis)\n})\n\nit('can extend global class', () => {\n  class SuperBlob extends Blob {}\n\n  expect(SuperBlob).toBeDefined()\n})\n\nit('uses jsdom ArrayBuffer', async () => {\n  const blob = new Blob(['Hello'], { type: 'text/plain' })\n\n  const arraybuffer = await new Promise<ArrayBuffer>((resolve, reject) => {\n    const reader = new FileReader()\n    reader.onload = () => resolve(reader.result as ArrayBuffer)\n    reader.onerror = () => reject(reader.error)\n    reader.readAsArrayBuffer(blob)\n  })\n\n  expect(arraybuffer.constructor.name).toBe('ArrayBuffer')\n  expect(arraybuffer instanceof ArrayBuffer).toBeTruthy()\n  expect(arraybuffer.constructor === ArrayBuffer).toBeTruthy()\n})\n\nit.each([\n  'Uint8Array',\n  'Uint16Array',\n  'Uint32Array',\n  'Uint8ClampedArray',\n  'Int16Array',\n  'Int32Array',\n  'Int8Array',\n  'Float32Array',\n  'Float64Array',\n] as const)('%s has buffer as ArrayBuffer', async (constructorName) => {\n  const Constructor = globalThis[constructorName]\n  const typedArray = new Constructor([1])\n  expect(typedArray.constructor.name).toBe(constructorName)\n  expect(typedArray instanceof Constructor).toBeTruthy()\n  expect(ArrayBuffer.isView(typedArray)).toBeTruthy()\n  expect(typedArray.buffer instanceof ArrayBuffer).toBeTruthy()\n})\n\nit('doesn\\'t throw, if listening for error', () => {\n  const spy = vi.fn((e: Event) => e.preventDefault())\n  window.addEventListener('error', spy)\n  addEventListener('custom', () => {\n    throw new Error('some error')\n  })\n  dispatchEvent(new Event('custom'))\n  expect(spy).toHaveBeenCalled()\n})\n"
  },
  {
    "path": "test/core/test/dual-package-hazard.test.ts",
    "content": "import { createRequire } from 'node:module'\n// @ts-expect-error no ts\nimport * as dep1 from '@vitest/test-dep1'\n\n// @ts-expect-error no ts\nimport * as dep2 from '@vitest/test-dep2'\n\n// @ts-expect-error no ts\nimport depEsmComment from '@vitest/test-dep-cjs/esm-comment'\n\n// @ts-expect-error no ts\nimport depEsmString from '@vitest/test-dep-cjs/esm-string'\n\nimport { expect, test } from 'vitest'\n\nconst require = createRequire(import.meta.url)\n\ntest('no dual package hazard by externalizing esm deps by default', async () => {\n  dep1.data.hello = 'world'\n  expect(dep2.data.hello).toBe('world')\n})\n\ntest('externalize cjs with esm comment', async () => {\n  const depEsmCommentRequire = require('@vitest/test-dep-cjs/esm-comment')\n  expect(depEsmComment).toBe(depEsmCommentRequire)\n})\n\ntest('externalize cjs with esm string', async () => {\n  const depEsmStringRequire = require('@vitest/test-dep-cjs/esm-string')\n  expect(depEsmString).toBe(depEsmStringRequire)\n})\n"
  },
  {
    "path": "test/core/test/dynamic-import.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('dynamic import', async () => {\n  try {\n    await import('non-existing-module' as any)\n    expect.unreachable()\n  }\n  catch (err: any) {\n    expect(err.message).toBe(\n      `Cannot find package 'non-existing-module' imported from ${import.meta.filename.replace(/\\\\/g, '/')}`,\n    )\n    expect(err.code).toBe('ERR_MODULE_NOT_FOUND')\n  }\n})\n"
  },
  {
    "path": "test/core/test/each.test.ts",
    "content": "import { afterAll, describe, expect, test } from 'vitest'\n\ntest.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('add(%i, %i) -> %i', (a, b, expected) => {\n  expect(a + b).toBe(expected)\n})\n\ntest.each([\n  ['string', true],\n  ['string', false],\n])('can be parsed', (a, b) => {\n  const typedA: string = a\n  const typedB: boolean = b\n\n  expect(typedA).toBeDefined()\n  expect(typedB).toBeDefined()\n})\n\ndescribe.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('describe add(%i, %i)', (a, b, expected) => {\n  test(`returns ${expected}`, () => {\n    expect(a + b).toBe(expected)\n  })\n\n  test(`returned value not be greater than ${expected}`, () => {\n    expect(a + b).not.toBeGreaterThan(expected)\n  })\n\n  test(`returned value not be less than ${expected}`, () => {\n    expect(a + b).not.toBeLessThan(expected)\n  })\n})\n\ndescribe.each([\n  [1, 'a', '1a'],\n  [1, 'b', '1b'],\n  [2, 'c', '2c'],\n] as const)('describe concatenate(%i, %s)', (a, b, expected) => {\n  test(`returns ${expected}`, () => {\n    // This will fail typechecking if const is not used and/or types for a,b are merged into a union\n    const typedA: number = a\n    const typedB: string = b\n\n    expect(`${typedA}${typedB}`).toBe(expected)\n  })\n})\n\ndescribe.each([\n  { a: 1, b: 1, expected: 2 },\n  { a: 1, b: 2, expected: 3 },\n  { a: 2, b: 1, expected: 3 },\n])('describe object add($a, $b)', ({ a, b, expected }) => {\n  test(`returns ${expected}`, () => {\n    expect(a + b).toBe(expected)\n  })\n\n  test(`returned value not be greater than ${expected}`, () => {\n    expect(a + b).not.toBeGreaterThan(expected)\n  })\n\n  test(`returned value not be less than ${expected}`, () => {\n    expect(a + b).not.toBeLessThan(expected)\n  })\n})\n\n// issue #794\ndescribe.each([1, 2, 0])('%s (describe.each 1d)', (num) => {\n  test(`${num} is a number (describe.each 1d)`, () => {\n    expect(typeof num).toEqual('number')\n  })\n})\n\ntest.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('the index of the test case is %#', (a, b, expected) => {\n  expect(a + b).toBe(expected)\n})\n\ntest.each([\n  [1, 2, 3],\n  [4, 5, 9],\n])('return a promise like result %#', async (a, b, expected) => {\n  const promiseResolver = (first: number, second: number) => {\n    return new Promise((resolve) => {\n      setTimeout(() => resolve(first + second), 1)\n    })\n  }\n\n  const result = await promiseResolver(a, b)\n  expect(result).toBe(expected)\n})\n\ntest.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])('the number of the test case is %$', (a, b, expected) => {\n  expect(a + b).toBe(expected)\n})\n\ntest.each([\n  [1, 2, 3],\n  [4, 5, 9],\n])('return a promise like result %$', async (a, b, expected) => {\n  const promiseResolver = (first: number, second: number) => {\n    return new Promise((resolve) => {\n      setTimeout(() => resolve(first + second), 1)\n    })\n  }\n\n  const result = await promiseResolver(a, b)\n  expect(result).toBe(expected)\n})\n\ndescribe('context on test and describe - todo/skip', () => {\n  let count = 0\n\n  describe.todo.each([1])('todo describe', () => {\n    test('this is todo test', () => {\n      count++\n    })\n  })\n\n  describe.skip.each([1])('todo describe', () => {\n    test('this is todo test', () => {\n      count++\n    })\n  })\n\n  test.skip.each([1])('todo test', () => {\n    count++\n  })\n\n  afterAll(() => {\n    expect(count).toBe(0)\n  })\n})\n\ndescribe('context with each - concurrent', () => {\n  describe.concurrent.each([[1, 1, 2], [1, 2, 3], [1, 3, 4]])('block', (number1, number2, number3) => {\n    test('numbered test', ({ expect }) => {\n      expect(number1 + number2).toBe(number3)\n    })\n  })\n})\n\ndescribe('not all arguments are array describe.each', () => {\n  const results = [null, [null]]\n  let i = 0\n\n  describe.each([null, [null]])('null is null', (value) => {\n    test('null is null', () => {\n      expect(value).toEqual(results[i++])\n    })\n  })\n})\n\ndescribe('not all arguments are array test.each', () => {\n  const results = [\n    null,\n    [null],\n  ]\n  let i = 0\n\n  test.each([\n    null,\n    [null],\n  ])('matches results', (value) => {\n    expect(value).toEqual(results[i++])\n  })\n})\n\ntest.each([\n  null,\n])('value is null', (value) => {\n  expect(value).toBeNull()\n})\n\ntest.each([\n  [null, null],\n  [null, null],\n])('if all cases are arrays of equal length, treats array elements as arguments', (value1, value2) => {\n  expect(value1).toBeNull()\n  expect(value2).toBeNull()\n})\n\ndescribe.each`\na             | b      | expected\n${1}          | ${1}   | ${2}\n${'a'}        | ${'b'} | ${'ab'}\n${[]}         | ${'b'} | ${'b'}\n${{}}         | ${'b'} | ${'[object Object]b'}\n${{ asd: 1 }} | ${'b'} | ${'[object Object]b'}\n`('describe template string add($a, $b)', ({ a, b, expected }) => {\n  test(`returns ${expected}`, () => {\n    expect(a + b).toBe(expected)\n  })\n})\n\ntest.each`\na               | b      | expected\n${1}            | ${1}   | ${2}\n${'a'}          | ${'b'} | ${'ab'}\n${[]}           | ${'b'} | ${'b'}\n${{}}           | ${'b'} | ${'[object Object]b'}\n${{ asd: 1 }}   | ${'b'} | ${'[object Object]b'}\n`('returns $expected when $a is added $b', ({ a, b, expected }) => {\n  expect(a + b).toBe(expected)\n})\n\ntest.each`\na               | b      | expected\n${{ val: 1 }}   | ${'b'} | ${'1b'}\n${{ val: 2 }}   | ${'b'} | ${'2b'}\n${{ val: 3 }}   | ${'b'} | ${'3b'}\n`('returns $expected when $a.val is added $b', ({ a, b, expected }) => {\n  expect(a.val + b).toBe(expected)\n})\n\ntest.each`\na       | b       | expected\n${true} | ${true} | ${true}\n`('($a && $b) -> $expected', ({ a, b, expected }) => {\n  expect(a && b).toBe(expected)\n})\n\ntest.each`\na             | b              | expected\n${{ val: 1 }} | ${{ val: 2 }}} | ${3}\n`('($a && $b) -> $expected', ({ a, b, expected }) => {\n  expect(a.val + b.val).toBe(expected)\n})\n"
  },
  {
    "path": "test/core/test/edge.test.ts",
    "content": "/**\n *  @vitest-environment edge-runtime\n */\nimport { describe, expect, it } from 'vitest'\n\ndescribe('edge runtime api', () => {\n  it('TextEncoder references the same global Uint8Array constructor', () => {\n    expect(new TextEncoder().encode('abc')).toBeInstanceOf(Uint8Array)\n  })\n\n  it('allows to run fetch', async () => {\n    // 3023 is the default port\n    const response = await fetch('http://localhost:3023/')\n    expect(response.status).toEqual(200)\n  })\n\n  it('allows to run crypto', async () => {\n    const array = new Uint32Array(10)\n    expect(crypto.getRandomValues(array)).toHaveLength(array.length)\n  })\n})\n"
  },
  {
    "path": "test/core/test/env-glob.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('default', () => {\n  expect(typeof window).toBe('undefined')\n  expect(expect.getState().environment).toBe('node')\n})\n"
  },
  {
    "path": "test/core/test/env-jsdom.test.ts",
    "content": "// @vitest-environment jsdom\n\nimport { afterAll, expect, test } from 'vitest'\nimport { getAuthToken } from '../src/env'\n\nconst NODE_ENV = process.env.NODE_ENV\n\nafterAll(() => {\n  process.env.NODE_ENV = NODE_ENV\n})\n\ntest('reassigning NODE_ENV', () => {\n  expect(process.env.NODE_ENV).toBeDefined()\n  process.env.NODE_ENV = 'development'\n  expect(process.env.NODE_ENV).toBe('development')\n})\n\ntest('reads envs from .env file', () => {\n  expect(import.meta.env.VITE_TEST_ENV).toBe('local')\n})\n\ntest('can reassign env locally', () => {\n  import.meta.env.VITEST_ENV = 'TEST'\n  expect(import.meta.env.VITEST_ENV).toBe('TEST')\n})\n\ntest('can reassign env everywhere', () => {\n  import.meta.env.AUTH_TOKEN = '123'\n  expect(getAuthToken()).toBe('123')\n  process.env.AUTH_TOKEN = '321'\n  expect(getAuthToken()).toBe('321')\n})\n\ntest('can see env in \"define\"', () => {\n  expect(import.meta.env.TEST_NAME).toBe('hello world')\n  expect(process.env.TEST_NAME).toBe('hello world')\n})\n\ntest('has worker env', () => {\n  expect(process.env.VITEST_WORKER_ID).toBeDefined()\n  expect(process.env.VITEST_POOL_ID).toBeDefined()\n})\n\ntest('custom env', () => {\n  expect(process.env.CUSTOM_ENV).toBe('foo')\n  expect(import.meta.env.CUSTOM_ENV).toBe('foo')\n})\n\ntest('ignores import.meta.env in string literals', () => {\n  expect('import.meta.env').toBe('import' + '.meta.env')\n})\n"
  },
  {
    "path": "test/core/test/env-runtime.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { populateGlobal } from '../../../packages/vitest/src/integrations/env/utils'\n\ntest('returns valid globals', () => {\n  const globalEvent = vi.fn()\n  const winEvent = vi.fn()\n  const global = {\n    Event: globalEvent,\n  }\n  const win = { Event: winEvent }\n  const { originals } = populateGlobal(global, win)\n  expect(originals.get('Event')).toBe(globalEvent)\n  expect(win.Event).toBe(winEvent)\n  expect(global.Event).toBe(winEvent)\n})\n"
  },
  {
    "path": "test/core/test/env.test.ts",
    "content": "import { afterAll, expect, test } from 'vitest'\nimport { getAuthToken } from '../src/env'\n\nconst NODE_ENV = process.env.NODE_ENV\n\nafterAll(() => {\n  process.env.NODE_ENV = NODE_ENV\n})\n\ntest('reassigning NODE_ENV', () => {\n  expect(process.env.NODE_ENV).toBeDefined()\n  process.env.NODE_ENV = 'development'\n  expect(process.env.NODE_ENV).toBe('development')\n})\n\ntest('reads envs from .env file', () => {\n  expect(import.meta.env.VITE_TEST_ENV).toBe('local')\n})\n\ntest('can reassign env locally', () => {\n  import.meta.env.VITEST_ENV = 'TEST'\n  expect(import.meta.env.VITEST_ENV).toBe('TEST')\n})\n\ntest('can reassign env everywhere', () => {\n  import.meta.env.AUTH_TOKEN = '123'\n  expect(getAuthToken()).toBe('123')\n  process.env.AUTH_TOKEN = '321'\n  expect(getAuthToken()).toBe('321')\n})\n\ntest('can see env in \"define\"', () => {\n  expect(import.meta.env.TEST_NAME).toBe('hello world')\n  expect(process.env.TEST_NAME).toBe('hello world')\n})\n\ntest('has worker env', () => {\n  expect(process.env.VITEST_WORKER_ID).toBeDefined()\n  expect(process.env.VITEST_POOL_ID).toBeDefined()\n})\n\ntest('custom env', () => {\n  expect(process.env.CUSTOM_ENV).toBe('foo')\n  expect(import.meta.env.CUSTOM_ENV).toBe('foo')\n})\n\ntest('ignores import.meta.env in string literals', () => {\n  expect('import.meta.env').toBe('import' + '.meta.env')\n})\n\ntest('define process and using import.meta.env together', () => {\n  const process = {}\n  expect(process).toMatchObject({})\n  expect(import.meta.env.MODE).toEqual('test')\n})\n\ntest('PROD, DEV, SSR should be boolean', () => {\n  expect(import.meta.env.PROD).toBe(false)\n  expect(import.meta.env.DEV).toBe(true)\n  expect(process.env.PROD).toBe('')\n  expect(process.env.DEV).toBe('1')\n\n  expect(import.meta.env.SSR).toBe(true)\n  expect(process.env.SSR).toBe('1')\n\n  import.meta.env.SSR = false\n  expect(import.meta.env.SSR).toEqual(false)\n})\n\ntest.runIf(process.platform === 'win32')('main process env variables are case insensitive', () => {\n  expect(process.env.PROGRAMFILES).toBeDefined()\n  expect(process.env['PROGRAMFILES(X86)']).toBeDefined()\n  expect(process.env['ProgramFiles(x86)']).toBeDefined()\n})\n"
  },
  {
    "path": "test/core/test/environments/custom-env.test.ts",
    "content": "// @vitest-environment custom\n\nimport { expect, test } from 'vitest'\n\ntest('custom env is defined', () => {\n  expect(expect.getState().environment).toBe('custom')\n  expect((globalThis as any).testEnvironment).toBe('custom')\n  expect((globalThis as any).option).toBe('config-option')\n\n  expect((global as any).POOL_ID_DURING_ENV_SETUP).toBeDefined()\n  expect(process.env.VITEST_POOL_ID).toBeDefined()\n  expect((global as any).POOL_ID_DURING_ENV_SETUP).toBe(process.env.VITEST_POOL_ID)\n\n  expect((global as any).WORKER_ID_DURING_ENV_SETUP).toBeDefined()\n  expect(process.env.VITEST_WORKER_ID).toBeDefined()\n  expect((global as any).WORKER_ID_DURING_ENV_SETUP).toBe(process.env.VITEST_WORKER_ID)\n})\n"
  },
  {
    "path": "test/core/test/environments/happy-dom.spec.ts",
    "content": "// @vitest-environment happy-dom\n\nimport { afterEach, expect, test, vi } from 'vitest'\n\nafterEach(() => {\n  vi.useRealTimers()\n})\n\ntest('fake timers don\\'t fail when using empty config', () => {\n  vi.useFakeTimers({})\n})\n\ntest('global CSS is injected correctly', () => {\n  expect(CSS).toBeDefined()\n  expect(CSS.escape).toBeDefined()\n  expect(CSS.supports).toBeDefined()\n})\n\ntest('atob and btoa are available', () => {\n  expect(atob('aGVsbG8gd29ybGQ=')).toBe('hello world')\n  expect(btoa('hello world')).toBe('aGVsbG8gd29ybGQ=')\n})\n\ntest('request doesn\\'t fail when using absolute url because it supports it', () => {\n  expect(() => {\n    const _r = new Request('/api', { method: 'GET' })\n  }).not.toThrow()\n})\n\ntest('can pass down a simple form data', async () => {\n  const formData = new FormData()\n  formData.set('hello', 'world')\n\n  await expect((async () => {\n    const req = new Request('http://localhost:3000/', {\n      method: 'POST',\n      body: formData,\n    })\n    await req.formData()\n  })()).resolves.not.toThrow()\n})\n"
  },
  {
    "path": "test/core/test/environments/jsdom.spec.ts",
    "content": "// @vitest-environment jsdom\n\nimport { setMaxListeners } from 'node:events'\nimport { stripVTControlCharacters } from 'node:util'\nimport { processError } from '@vitest/utils/error'\nimport { describe, expect, test, vi } from 'vitest'\n\ntest('MessageChannel and MessagePort are available', () => {\n  expect(MessageChannel).toBeDefined()\n  expect(MessagePort).toBeDefined()\n})\n\ntest('structuredClone is available', () => {\n  expect(structuredClone).toBeDefined()\n})\n\ntest('fetch, Request, Response, and BroadcastChannel are available', () => {\n  expect(fetch).toBeDefined()\n  expect(Request).toBeDefined()\n  expect(Response).toBeDefined()\n  expect(TextEncoder).toBeDefined()\n  expect(TextDecoder).toBeDefined()\n  expect(BroadcastChannel).toBeDefined()\n})\n\ntest('Fetch API accepts other APIs', async () => {\n  expect.soft(() => new Request('http://localhost', { signal: new AbortController().signal })).not.toThrow()\n  expect.soft(() => new Request('http://localhost', { method: 'POST', body: new FormData() })).not.toThrow()\n  expect.soft(() => new Request('http://localhost', { method: 'POST', body: new Blob() })).not.toThrow()\n  expect.soft(() => new Request(new URL('https://localhost'))).not.toThrow()\n\n  const request = new Request('http://localhost')\n  expect.soft(request.headers).toBeInstanceOf(Headers)\n\n  expect.soft(\n    () => new Request('http://localhost', { method: 'POST', body: new URLSearchParams([['key', 'value']]) }),\n  ).not.toThrow()\n\n  const searchParams = new URLSearchParams()\n  searchParams.set('key', 'value')\n  expect.soft(() => new Request('http://localhost', { method: 'POST', body: searchParams })).not.toThrow()\n\n  const clone = request.clone()\n  expect.soft(clone).toBeInstanceOf(Request)\n})\n\ntest('fetch api doesnt override the init object', () => {\n  const body = new FormData()\n  const init: RequestInit = {\n    method: 'post',\n    body,\n  }\n  const _request = new Request('http://localhost', init)\n  expect(init.body).toBe(body)\n})\n\ndescribe('FormData', () => {\n  test('can pass down a simple form data', async () => {\n    const formData = new FormData()\n    formData.set('hello', 'world')\n\n    await expect((async () => {\n      const req = new Request('http://localhost:3000/', {\n        method: 'POST',\n        body: formData,\n      })\n      await req.formData()\n    })()).resolves.not.toThrow()\n  })\n\n  test('can pass down form data from a FORM element', async () => {\n    const form = document.createElement('form')\n    document.body.append(form)\n\n    const hello = document.createElement('input')\n    hello.value = 'world'\n    hello.type = 'text'\n    hello.name = 'hello'\n    form.append(hello)\n\n    const formData = new FormData(form)\n    expect([...formData.entries()]).toEqual([\n      ['hello', 'world'],\n    ])\n\n    await expect((async () => {\n      const req = new Request('http://localhost:3000/', {\n        method: 'POST',\n        body: formData,\n      })\n      await req.formData()\n    })()).resolves.not.toThrow()\n  })\n\n  test('can pass down form data from a FORM element with a submitter', async () => {\n    const form = document.createElement('form')\n    document.body.append(form)\n\n    const hello = document.createElement('input')\n    hello.value = 'world'\n    hello.type = 'text'\n    hello.name = 'hello'\n    form.append(hello)\n\n    const submitter = document.createElement('button')\n    submitter.type = 'submit'\n    submitter.name = 'include'\n    submitter.value = 'submitter'\n    form.append(submitter)\n\n    const formData = new FormData(form, submitter)\n    expect([...formData.entries()]).toEqual([\n      ['hello', 'world'],\n      ['include', 'submitter'],\n    ])\n\n    await expect((async () => {\n      const req = new Request('http://localhost:3000/', {\n        method: 'POST',\n        body: formData,\n      })\n      await req.formData()\n    })()).resolves.not.toThrow()\n  })\n\n  // https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData#exceptions\n  test('cannot pass down form data from a FORM element with a non-sumbit sumbitter', async () => {\n    const form = document.createElement('form')\n    document.body.append(form)\n    const submitter = document.createElement('button')\n    submitter.type = 'button'\n    form.append(submitter)\n\n    expect(() => new FormData(form, submitter)).toThrow(\n      new TypeError('The specified element is not a submit button'),\n    )\n  })\n\n  test('cannot pass down form data from a FORM element with a sumbitter from a wrong form', async () => {\n    const form1 = document.createElement('form')\n    const form2 = document.createElement('form')\n    document.body.append(form1, form2)\n    const submitter = document.createElement('button')\n    submitter.type = 'submit'\n    form2.append(submitter)\n\n    try {\n      // can't use toThrow here because DOMException is not an Error\n      const _ = new FormData(form1, submitter)\n    }\n    catch (error: any) {\n      const expectedError = new DOMException(\n        'The specified element is not owned by this form element',\n        'NotFoundError',\n      )\n      expect(error).toEqual(expectedError)\n    }\n  })\n\n  test('supports Blob', () => {\n    const form = new FormData()\n    const key = 'prop'\n\n    const data = new Blob()\n\n    form.set(key, data)\n\n    const retrievedBlob = form.get(key)\n\n    expect(retrievedBlob).toBeInstanceOf(Blob)\n  })\n\n  test('supports File', () => {\n    const form = new FormData()\n    const key = 'prop'\n\n    const data = new File([], 'name')\n\n    form.set(key, data)\n\n    const retrievedBlob = form.get(key)\n\n    expect(retrievedBlob).toBeInstanceOf(File)\n  })\n})\n\ntest('DOM APIs accept AbortController', () => {\n  const element = document.createElement('div')\n  document.body.append(element)\n  const controller = new AbortController()\n  const spy = vi.fn()\n  element.addEventListener('click', spy, {\n    signal: controller.signal,\n  })\n\n  element.click()\n\n  expect(spy).toHaveBeenCalledTimes(1)\n\n  controller.abort()\n\n  element.click()\n\n  expect(spy).toHaveBeenCalledTimes(1)\n})\n\ntest('can pass down the same abort signal many times without a warning', ({ onTestFinished }) => {\n  const controller = new AbortController()\n  const signal = controller.signal\n  setMaxListeners(5, signal)\n\n  const emitWarning = vi.spyOn(process, 'emitWarning').mockImplementation(() => {})\n  onTestFinished(() => emitWarning.mockRestore())\n\n  const element = document.createElement('div')\n  document.body.append(element)\n\n  for (let i = 0; i < 20; i++) {\n    element.addEventListener('click', () => {}, {\n      signal,\n    })\n  }\n\n  expect(emitWarning).not.toHaveBeenCalledWith(expect.objectContaining({\n    message: expect.stringContaining('Possible EventTarget memory leak detected.'),\n  }))\n})\n\ntest('DOM APIs addEventListener allow null as third parameter', () => {\n  const element = document.createElement('div')\n  document.body.append(element)\n  const spy = vi.fn()\n\n  // eslint-disable-next-line ts/ban-ts-comment\n  // @ts-expect-error\n  element.addEventListener('click', spy, null)\n\n  element.click()\n\n  expect(spy).toHaveBeenCalledTimes(1)\n})\n\ntest('atob and btoa are available', () => {\n  expect(atob('aGVsbG8gd29ybGQ=')).toBe('hello world')\n  expect(btoa('hello world')).toBe('aGVsbG8gd29ybGQ=')\n})\n\ntest('toContain correctly handles DOM nodes', () => {\n  const wrapper = document.createElement('div')\n  const child = document.createElement('div')\n  const external = document.createElement('div')\n  wrapper.appendChild(child)\n\n  const parent = document.createElement('div')\n  parent.appendChild(wrapper)\n  parent.appendChild(external)\n\n  document.body.appendChild(parent)\n  const divs = document.querySelectorAll('div')\n\n  expect(divs).toContain(wrapper)\n  expect(divs).toContain(parent)\n  expect(divs).toContain(external)\n\n  expect(wrapper).toContain(child)\n  expect(wrapper).not.toContain(external)\n\n  wrapper.classList.add('flex', 'flex-col')\n\n  expect(wrapper.classList).toContain('flex-col')\n  expect(wrapper.classList).not.toContain('flex-row')\n\n  expect(() => {\n    expect(wrapper).toContain('some-element')\n  }).toThrowErrorMatchingInlineSnapshot(`[TypeError: toContain() expected a DOM node as the argument, but got string]`)\n\n  expect(() => {\n    expect(wrapper.classList).toContain('flex-row')\n  }).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected \"flex flex-col\" to contain \"flex-row\"]`)\n  expect(() => {\n    expect(wrapper.classList).toContain(2)\n  }).toThrowErrorMatchingInlineSnapshot(`[TypeError: class name value must be string, received \"number\"]`)\n\n  try {\n    expect(wrapper.classList).toContain('flex-row')\n    expect.unreachable()\n  }\n  catch (err: any) {\n    expect(stripVTControlCharacters(processError(err).diff!)).toMatchInlineSnapshot(`\n      \"Expected: \"flex flex-col flex-row\"\n      Received: \"flex flex-col\"\"\n    `)\n  }\n\n  try {\n    expect(wrapper.classList).not.toContain('flex')\n    expect.unreachable()\n  }\n  catch (err: any) {\n    expect(stripVTControlCharacters(processError(err).diff!)).toMatchInlineSnapshot(`\n      \"Expected: \"flex-col\"\n      Received: \"flex flex-col\"\"\n    `)\n  }\n})\n\ntest('request doesn\\'t support absolute URL because jsdom doesn\\'t provide compatible Request so Vitest is using Node.js Request', () => {\n  expect(() => {\n    const _r = new Request('/api', { method: 'GET' })\n  }).toThrow(/Failed to parse URL/)\n})\n\ntest('URL.createObjectUrl works properly', () => {\n  expect(() => {\n    URL.createObjectURL(new Blob())\n  }).not.toThrow()\n  expect(() => {\n    URL.createObjectURL(new File([], 'name.js'))\n  }).not.toThrow()\n})\n\ntest('compat classes preserve their .name property', () => {\n  expect(URL.name).toBe('URL')\n  expect(Request.name).toBe('Request')\n})\n\ntest('jsdom global is exposed', () => {\n  // @ts-expect-error -- jsdom is not exposed in our types because we use a single tsconfig for all\n  const dom = jsdom\n  expect(dom).toBeDefined()\n  dom.reconfigure({ url: 'https://examples.new.com' })\n  expect(location.href).toBe('https://examples.new.com/')\n})\n\ntest('ssr is disabled', () => {\n  expect(import.meta.env.SSR).toBe(false)\n})\n"
  },
  {
    "path": "test/core/test/environments/node.spec.ts",
    "content": "// @vitest-environment node\n\nimport { expect, test } from 'vitest'\n\nconst nodeMajor = Number(process.version.slice(1).split('.')[0])\n\ntest.runIf(nodeMajor > 16)('url correctly creates an object', () => {\n  expect(() => {\n    URL.createObjectURL(new Blob([]))\n  }).not.toThrow()\n})\n\ntest('ssr is enabled', () => {\n  expect(import.meta.env.SSR).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/error.test.ts",
    "content": "import { processError } from '@vitest/utils/error'\nimport { expect, test } from 'vitest'\n\ntest('Can correctly process error where actual and expected contains non writable properties', () => {\n  const actual = {}\n  const expected = {}\n\n  Object.defineProperty(actual, 'root', {\n    value: {\n      foo: Object.defineProperty({}, 'sub_properties', {\n        value: { bar: 'baz' },\n        writable: false,\n        enumerable: true,\n      }),\n    },\n    writable: false,\n    enumerable: true,\n  })\n  Object.defineProperty(expected, 'root', {\n    value: {\n      foo: Object.defineProperty({}, 'sub_properties', {\n        value: { bar: 'not baz' },\n        writable: false,\n        enumerable: true,\n      }),\n    },\n    writable: false,\n    enumerable: true,\n  })\n\n  const err = {\n    actual,\n    expected,\n  }\n\n  expect(() => processError(err)).not.toThrow(TypeError)\n})\n\ntest('Can correctly process error where cause is a non writable property', () => {\n  const err = new Error('My error')\n\n  Object.defineProperty(err, 'cause', {\n    value: new Error('My cause'),\n    writable: false,\n    enumerable: true,\n  })\n\n  expect(() => processError(err)).not.toThrow(TypeError)\n})\n\ntest('Can correctly process error where cause leads to an infinite recursion', () => {\n  const err = new Error('My error')\n\n  Object.defineProperty(err, 'cause', {\n    value: err,\n    writable: true,\n    enumerable: true,\n    configurable: true,\n  })\n\n  const serialisedError = processError(err)\n\n  expect(serialisedError.name).toBeTypeOf('string')\n  expect(serialisedError.stack).toBeTypeOf('string')\n  expect(serialisedError.message).toBeTypeOf('string')\n\n  expect(serialisedError.cause?.name).toBeTypeOf('string')\n  expect(serialisedError.cause?.stack).toBeTypeOf('string')\n  expect(serialisedError.cause?.message).toBeTypeOf('string')\n})\n\ntest('simple error has message, stack and name', () => {\n  const error = new Error('My error')\n  const serialisedError = processError(error)\n\n  expect(error.message).toBe(serialisedError.message)\n  expect(error.name).toBe(serialisedError.name)\n  expect(error.stack).toBe(serialisedError.stack)\n})\n\ntest('error with toJSON has message, stack and name', () => {\n  class SerializableError extends Error {\n    toJSON() {\n      return { ...this }\n    }\n  }\n\n  const error = new SerializableError('My error')\n  const serialisedError = processError(error)\n\n  expect(error.message).toBe(serialisedError.message)\n  expect(error.name).toBe(serialisedError.name)\n  expect(error.stack).toBe(serialisedError.stack)\n})\n\ntest('error with toJSON doesn\\'t override nessage, stack and name if it\\'s there already', () => {\n  class SerializableError extends Error {\n    toJSON() {\n      return {\n        name: 'custom',\n        stack: 'custom stack',\n        message: 'custom message',\n      }\n    }\n  }\n\n  const error = new SerializableError('My error')\n  const serialisedError = processError(error)\n\n  expect(serialisedError.name).toBe('custom')\n  expect(serialisedError.stack).toBe('custom stack')\n  expect(serialisedError.message).toBe('custom message')\n})\n"
  },
  {
    "path": "test/core/test/esnext-decorator.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('decorators work', () => {\n  expect(Sut.mocked).toBe(true)\n  expect(new Sut()).toBeInstanceOf(Sut)\n})\nfunction exampleDecorator(ClassExample: any, context: ClassDecoratorContext): any {\n  if (context.kind !== 'class') {\n    throw new Error('not a class to decorate')\n  }\n  // https://github.com/babel/babel/issues/17875#issuecomment-4072950690\n  context.addInitializer(() => {\n    ClassExample.mocked = true\n  })\n  return ClassExample\n}\n\n@exampleDecorator\nclass Sut {\n  static mocked = false\n}\n"
  },
  {
    "path": "test/core/test/esnext.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nconst [version] = process.version.slice(1).split('.')\n\nit.skipIf(Number(version) < 20)('\"v\" flag in regexp', () => {\n  const regexp = /\\p{RGI_Emoji}|\\P{Mark}\\p{Mark}*/gv\n  expect('👍🏼👍🏼👍🏼'.match(regexp)).toEqual(['👍🏼', '👍🏼', '👍🏼'])\n})\n\nit('new \"using\" feature', () => {\n  let getResource = (): any => {\n    throw new Error('don\\'t call me')\n  }\n  {\n    using resource = resourceful('foo')\n    getResource = () => resource.resource\n  }\n  expect(getResource()).toBe(null)\n})\n\n// @ts-expect-error - readonly symbol, but might not be assigned\nSymbol.dispose ??= Symbol('dispose')\n\nfunction resourceful(resourceDefault: string) {\n  let resource: string | null = resourceDefault\n  return {\n    get resource() {\n      return resource\n    },\n    [Symbol.dispose]: () => {\n      resource = null\n    },\n  }\n}\n"
  },
  {
    "path": "test/core/test/execution-order.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\nlet v = 0\n\nfunction bumpSync() {\n  v += 1\n}\n\nfunction bump() {\n  return new Promise<void>((resolve) => {\n    setTimeout(() => {\n      v += 1\n      resolve()\n    }, 1)\n  })\n}\n\nit('one', () => {\n  bumpSync()\n  expect(v).toBe(1)\n})\n\nit('two', async () => {\n  expect(v).toBe(1)\n  await bump()\n  expect(v).toBe(2)\n})\n\ndescribe('suite', () => {\n  it('three', () => {\n    bumpSync()\n    expect(v).toBe(3)\n  })\n\n  it('four', async () => {\n    expect(v).toBe(3)\n    await bump()\n    expect(v).toBe(4)\n  })\n\n  it('four', () => {\n    expect(v).toBe(4)\n  })\n\n  it('five', () => {\n    bumpSync()\n    expect(v).toBe(5)\n  })\n})\n"
  },
  {
    "path": "test/core/test/expect-circular.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\ndescribe('circular equality', () => {\n  test('object, set, map', () => {\n    // https://github.com/vitest-dev/vitest/issues/5533\n    function gen() {\n      const obj = {\n        a: new Set<any>(),\n        b: new Map<any, any>(),\n      }\n      obj.a.add(obj)\n      obj.b.set('k', obj)\n      return obj\n    }\n    expect(gen()).toEqual(gen())\n    expect(gen()).toMatchObject(gen())\n  })\n\n  test('object, set', () => {\n    function gen() {\n      const obj = {\n        a: new Set<any>(),\n        b: new Set<any>(),\n      }\n      obj.a.add(obj)\n      obj.b.add(obj)\n      return obj\n    }\n    expect(gen()).toEqual(gen())\n    expect(gen()).toMatchObject(gen())\n  })\n\n  test('array, set', () => {\n    function gen() {\n      const obj = [new Set<any>(), new Set<any>()]\n      obj[0].add(obj)\n      obj[1].add(obj)\n      return obj\n    }\n    expect(gen()).toEqual(gen())\n    expect(gen()).toMatchObject(gen())\n  })\n\n  test('object, array', () => {\n    // https://github.com/jestjs/jest/issues/14734\n    function gen() {\n      const a: any = {\n        v: 1,\n      }\n      const c1: any = {\n        ref: [],\n      }\n      c1.ref.push(c1)\n      a.ref = c1\n      return a\n    }\n    expect(gen()).toEqual(gen())\n    expect(gen()).toMatchObject(gen())\n  })\n})\n"
  },
  {
    "path": "test/core/test/expect-poll.test.ts",
    "content": "import { chai, expect, test, vi } from 'vitest'\n\ntest('simple usage', async () => {\n  await expect.poll(() => false).toBe(false)\n  await expect.poll(() => false).not.toBe(true)\n  // .resolves allowed after .poll\n  await expect(Promise.resolve(1)).resolves.toBe(1)\n\n  await expect(async () => {\n    await expect.poll(() => Promise.resolve(1)).resolves.toBe(1)\n  }).rejects.toThrow('expect.poll() is not supported in combination with .resolves')\n  await expect(async () => {\n    await expect.poll(() => Promise.reject(new Error('empty'))).rejects.toThrow('empty')\n  }).rejects.toThrow('expect.poll() is not supported in combination with .rejects')\n\n  const unsupported = [\n    'matchSnapshot',\n    'toMatchSnapshot',\n    'toMatchInlineSnapshot',\n    'throws',\n    'Throw',\n    'throw',\n    'toThrow',\n    'toThrowError',\n    'toThrowErrorMatchingSnapshot',\n    'toThrowErrorMatchingInlineSnapshot',\n  ] as const\n\n  for (const key of unsupported) {\n    await expect(async () => {\n      await expect.poll(() => Promise.resolve(1))[key as 'matchSnapshot']()\n    }).rejects.toThrow(`expect.poll() is not supported in combination with .${key}(). Use vi.waitFor() if your assertion condition is unstable.`)\n  }\n})\n\ntest('timeout', async () => {\n  await expect(async () => {\n    await expect.poll(() => false, { timeout: 100, interval: 10 }).toBe(true)\n  }).rejects.toThrow(expect.objectContaining({\n    message: 'expected false to be true // Object.is equality',\n    stack: expect.stringContaining('expect-poll.test.ts:38:68'),\n    cause: expect.objectContaining({\n      message: 'Matcher did not succeed in time.',\n    }),\n  }))\n})\n\ntest('interval', async () => {\n  const fn = vi.fn(() => true)\n  await expect(async () => {\n    // using big values because CI can be slow\n    await expect.poll(fn, { interval: 100, timeout: 500 }).toBe(false)\n  }).rejects.toThrow()\n  // CI can be unstable, but there should be always at least 5 calls\n  expect(fn.mock.calls.length >= 4).toBe(true)\n})\n\ntest('fake timers don\\'t break it', async () => {\n  const now = Date.now()\n  vi.useFakeTimers()\n  await expect(async () => {\n    await expect.poll(() => false, { timeout: 100 }).toBe(true)\n  }).rejects.toThrow('expected false to be true // Object.is equality')\n  vi.useRealTimers()\n  const diff = Date.now() - now\n  expect(diff >= 100).toBe(true)\n})\n\ntest('custom matcher works correctly', async () => {\n  const fn = vi.fn()\n  let idx = 0\n  expect.extend({\n    toBeJestCompatible() {\n      idx++\n      fn({ poll: this.poll })\n      return {\n        pass: idx > 2,\n        message: () => 'ok',\n      }\n    },\n  })\n  await expect.poll(() => 1, { interval: 10 }).toBeJestCompatible()\n  expect(fn).toHaveBeenCalledTimes(3)\n  expect(fn).toHaveBeenCalledWith({ poll: true })\n})\n\ntest('toBeDefined', async () => {\n  await expect.poll(() => 1).toBeDefined()\n  await expect.poll(() => undefined).not.toBeDefined()\n\n  await expect(() =>\n    expect.poll(() => 1, { timeout: 100, interval: 10 }).not.toBeDefined(),\n  ).rejects.toThrow(expect.objectContaining({\n    message: 'expected 1 to be undefined',\n    cause: expect.objectContaining({\n      message: 'Matcher did not succeed in time.',\n    }),\n  }))\n\n  await expect(() =>\n    expect.poll(() => undefined, { timeout: 100, interval: 10 }).toBeDefined(),\n  ).rejects.toThrow(expect.objectContaining({\n    message: 'expected undefined to be defined',\n    cause: expect.objectContaining({\n      message: 'Matcher did not succeed in time.',\n    }),\n  }))\n})\n\ntest('should set _isLastPollAttempt flag on last call', async () => {\n  const fn = vi.fn(function (this: object) {\n    return chai.util.flag(this, '_isLastPollAttempt')\n  })\n  await expect(async () => {\n    await expect.poll(fn, { interval: 100, timeout: 500 }).toBe(false)\n  }).rejects.toThrow()\n  fn.mock.results.forEach((result, index) => {\n    const isLastCall = index === fn.mock.results.length - 1\n    expect(result.value).toBe(isLastCall ? true : undefined)\n  })\n})\n\ntest('should handle success on last attempt', async () => {\n  const fn = vi.fn(function (this: object) {\n    if (chai.util.flag(this, '_isLastPollAttempt')) {\n      return 1\n    }\n    return undefined\n  })\n  await expect.poll(fn, { interval: 100, timeout: 500 }).toBe(1)\n})\n\ntest('should handle failure on last attempt', async () => {\n  const fn = vi.fn(function (this: object) {\n    if (chai.util.flag(this, '_isLastPollAttempt')) {\n      return 3\n    }\n    return 2\n  })\n  await expect(async () => {\n    await expect.poll(fn, { interval: 10, timeout: 100 }).toBe(1)\n  }).rejects.toThrow(expect.objectContaining({\n    // makes sure cause message reflects the last attempt value\n    message: 'expected 3 to be 1 // Object.is equality',\n    cause: expect.objectContaining({\n      message: 'Matcher did not succeed in time.',\n    }),\n  }))\n})\n"
  },
  {
    "path": "test/core/test/expect.test-d.ts",
    "content": "/* eslint-disable no-lone-blocks */\n\nimport { expect, test } from 'vitest'\n\ntest('expect.* allows asymmetrict mattchers with different types', () => {\n  // types.ts examples: stringContaining\n  expect('I have an apple').toEqual(expect.stringContaining('apple'))\n  expect('I have an apple').toEqual<string>(expect.stringContaining('apple'))\n\n  expect({ a: 'test string' }).toEqual({ a: expect.stringContaining('test') })\n  expect({ a: 'test string' }).toEqual<{ a: string }>({ a: expect.stringContaining('test') })\n\n  // types.ts examples: objectContaining\n  expect({ a: '1', b: 2 }).toEqual(expect.objectContaining({ a: '1' }))\n  expect({ a: '1', b: 2 }).toEqual<{ a: string; b: string }>(expect.objectContaining({ a: '1' }))\n\n  // types.ts examples: arrayContaining\n  expect(['a', 'b', 'c']).toEqual(expect.arrayContaining(['b', 'a']))\n  expect(['a', 'b', 'c']).toEqual<string[]>(expect.arrayContaining(['b', 'a']))\n\n  // types.ts examples: stringMatching\n  expect('hello world').toEqual(expect.stringMatching(/^hello/))\n  expect('hello world').toEqual<string>(expect.stringMatching(/^hello/))\n\n  expect('hello world').toEqual(expect.stringMatching('hello'))\n  expect('hello world').toEqual<string>(expect.stringMatching('hello'))\n\n  // types.ts examples: closeTo\n  expect(10.45).toEqual(expect.closeTo(10.5, 1))\n  expect(10.45).toEqual<number>(expect.closeTo(10.5, 1))\n\n  expect(5.11).toEqual(expect.closeTo(5.12))\n  expect(5.11).toEqual<number>(expect.closeTo(5.12))\n\n  // expect.any(String)\n  // https://github.com/vitest-dev/vitest/pull/7016#issuecomment-2517674066\n  {\n    const obj = {\n      id: '',\n      name: '',\n    }\n\n    expect(obj).toEqual({\n      id: expect.any(String),\n      name: 'Amelia',\n    })\n\n    expect(obj).toEqual<{\n      id: string\n      name: string\n    }>({\n      id: expect.any(String),\n      name: 'Amelia',\n    })\n  }\n\n  // expect.any(Date)\n  // https://github.com/vitest-dev/vitest/issues/4543#issuecomment-1817960296\n  // https://github.com/vitest-dev/vitest/issues/4543#issuecomment-1817967628\n  // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/62831#issue-1418959169\n  {\n    const actual = {} as {\n      foo: string\n      bar: string\n      createdAt: Date\n    }\n\n    expect(actual).toEqual({\n      foo: 'foo',\n      bar: 'bar',\n      createdAt: expect.any(Date),\n    })\n\n    expect(actual).toEqual<{\n      foo: string\n      bar: string\n      createdAt: Date\n    }>({\n      foo: 'foo',\n      bar: 'bar',\n      createdAt: expect.any(Date),\n    })\n\n    expect(actual).toEqual<{\n      foo: string\n      bar: string\n      createdAt: Date\n    }[]>([\n      {\n        foo: 'foo',\n        bar: 'bar',\n        createdAt: expect.any(Date),\n      },\n    ])\n  }\n\n  // expect.arrayContaining\n  // https://github.com/jestjs/jest/issues/13812#issue-1555843276\n  {\n    expect([1, 2, 3]).toEqual(expect.arrayContaining(['a']))\n    expect([1, 2, 3]).toEqual<number[]>(expect.arrayContaining(['a']))\n\n    expect([1, 2, 3]).toEqual(expect.arrayContaining([expect.any(Number)]))\n    expect([1, 2, 3]).toEqual<number[]>(expect.arrayContaining([expect.any(Number)]))\n\n    expect([1, 2, 3]).toEqual(expect.arrayContaining([expect.anything()]))\n    expect([1, 2, 3]).toEqual<number[]>(expect.arrayContaining([expect.anything()]))\n  }\n\n  // expect.any(Array)\n  // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/62831/files#diff-ff7b882e4a29e7fe0e348a6bdf8b11774d606eaa221009b166b01389576d921fR1237\n  expect({ list: [1, 2, 3] }).toMatchObject({ list: expect.any(Array) })\n  expect({ list: [1, 2, 3] }).toMatchObject<{ list: number[] }>({ list: expect.any(Array) })\n\n  // expect<T>\n  // https://github.com/vitest-dev/vitest/issues/8081\n  function expectMany<T>(value: ({ enabled: false } | { enabled: true; data: T })) {\n    expect(value).toEqual(value)\n    expect(value).toMatchObject(value)\n  }\n  expectMany({ enabled: true, data: 'ok' })\n})\n"
  },
  {
    "path": "test/core/test/expect.test.ts",
    "content": "import type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type { Tester } from '@vitest/expect'\nimport { stripVTControlCharacters } from 'node:util'\nimport { getCurrentTest } from '@vitest/runner'\nimport { processError } from '@vitest/utils/error'\nimport { Temporal } from 'temporal-polyfill'\nimport { describe, expect, expectTypeOf, test, vi } from 'vitest'\n\ndescribe('expect.soft', () => {\n  test('types', () => {\n    expectTypeOf(expect.soft(7)).toEqualTypeOf(expect(7))\n    expectTypeOf(expect.soft(5)).toHaveProperty('toBe')\n    expectTypeOf(expect.soft(7)).not.toHaveProperty('toCustom')\n  })\n\n  test('return value', () => {\n    expect(expect.soft('test')).toHaveProperty('toBe')\n    expect(expect.soft('test')).toHaveProperty('toEqual')\n  })\n\n  test('with extend', () => {\n    expect.extend({\n      toBeFoo(received) {\n        const { isNot } = this\n        return {\n          // do not alter your \"pass\" based on isNot. Vitest does it for you\n          pass: received === 'foo',\n          message: () => `${received} is${isNot ? ' not' : ''} foo`,\n        }\n      },\n    })\n    expect(expect.soft('test')).toHaveProperty('toBeFoo')\n  })\n\n  test('should have multiple error', () => {\n    expect.soft(1).toBe(2)\n    expect.soft(2).toBe(3)\n    getCurrentTest()!.result!.state = 'run'\n    expect(getCurrentTest()?.result?.errors).toHaveLength(2)\n  })\n\n  test.fails('should be a failure', () => {\n    expect.soft('test1').toBe('test res')\n    expect.soft('test2').toBe('test res')\n    expect.soft('test3').toBe('test res')\n  })\n})\n\ndescribe('expect.addEqualityTesters', () => {\n  class AnagramComparator {\n    public word: string\n\n    constructor(word: string) {\n      this.word = word\n    }\n\n    equals(other: AnagramComparator): boolean {\n      const cleanStr1 = this.word.replace(/ /g, '').toLowerCase()\n      const cleanStr2 = other.word.replace(/ /g, '').toLowerCase()\n\n      const sortedStr1 = cleanStr1.split('').sort().join('')\n      const sortedStr2 = cleanStr2.split('').sort().join('')\n\n      return sortedStr1 === sortedStr2\n    }\n  }\n\n  function createAnagramComparator(word: string) {\n    return new AnagramComparator(word)\n  }\n\n  function isAnagramComparator(a: unknown): a is AnagramComparator {\n    return a instanceof AnagramComparator\n  }\n\n  const areObjectsEqual: Tester = (\n    a: unknown,\n    b: unknown,\n  ): boolean | undefined => {\n    const isAAnagramComparator = isAnagramComparator(a)\n    const isBAnagramComparator = isAnagramComparator(b)\n\n    if (isAAnagramComparator && isBAnagramComparator) {\n      return a.equals(b)\n    }\n\n    else if (isAAnagramComparator === isBAnagramComparator) {\n      return undefined\n    }\n\n    else {\n      return false\n    }\n  }\n\n  function* toIterator<T>(array: Array<T>): Iterator<T> {\n    for (const obj of array) {\n      yield obj\n    }\n  }\n\n  const customObject1 = createAnagramComparator('listen')\n  const customObject2 = createAnagramComparator('silent')\n\n  expect.addEqualityTesters([areObjectsEqual])\n\n  test('AnagramComparator objects are unique and not contained within arrays of AnagramComparator objects', () => {\n    expect(customObject1).not.toBe(customObject2)\n    expect([customObject1]).not.toContain(customObject2)\n  })\n\n  test('basic matchers pass different AnagramComparator objects', () => {\n    expect(customObject1).toEqual(customObject2)\n    expect([customObject1, customObject2]).toEqual([customObject2, customObject1])\n    expect(new Map([['key', customObject1]])).toEqual(new Map([['key', customObject2]]))\n    expect(new Set([customObject1])).toEqual(new Set([customObject2]))\n    expect(toIterator([customObject1, customObject2])).toEqual(\n      toIterator([customObject2, customObject1]),\n    )\n    expect([customObject1]).toContainEqual(customObject2)\n    expect({ a: customObject1 }).toHaveProperty('a', customObject2)\n    expect({ a: customObject2, b: undefined }).toStrictEqual({\n      a: customObject1,\n      b: undefined,\n    })\n    expect({ a: 1, b: { c: customObject1 } }).toMatchObject({\n      a: 1,\n      b: { c: customObject2 },\n    })\n  })\n\n  test('asymmetric matchers pass different AnagramComparator objects', () => {\n    expect([customObject1]).toEqual(expect.arrayContaining([customObject1]))\n    expect({ a: 1, b: { c: customObject1 } }).toEqual(\n      expect.objectContaining({ b: { c: customObject2 } }),\n    )\n  })\n\n  test('toBe recommends toStrictEqual even with different objects', () => {\n    expect(() => expect(customObject1).toBe(customObject2)).toThrow('toStrictEqual')\n  })\n\n  test('toBe recommends toEqual even with different AnagramComparator objects', () => {\n    expect(() => expect({ a: undefined, b: customObject1 }).toBe({ b: customObject2 })).toThrow(\n      'toEqual',\n    )\n  })\n\n  test('iterableEquality still properly detects cycles', () => {\n    const a = new Set()\n    a.add(customObject1)\n    a.add(a)\n\n    const b = new Set()\n    b.add(customObject2)\n    b.add(b)\n\n    expect(a).toEqual(b)\n  })\n})\n\ndescribe('recursive custom equality tester for numeric values', () => {\n  const areNumbersEqual: Tester = (a, b) => typeof b === 'number' ? a === b : undefined\n\n  expect.addEqualityTesters([areNumbersEqual])\n\n  test('within objects', () => {\n    expect({ foo: -0, bar: 0, baz: 0 }).toStrictEqual({ foo: 0, bar: -0, baz: 0 })\n  })\n\n  test('within arrays', () => {\n    expect([-0, 0, 0]).toStrictEqual([0, -0, 0])\n  })\n\n  test('within typed arrays', () => {\n    expect(Float64Array.of(-0, 0, 0)).toStrictEqual(Float64Array.of(0, -0, 0))\n  })\n\n  test('within deeply nested structures', () => {\n    expect({ foo: { bar: [1, [2, 0, [3, -0, 4]]] }, baz: 0 }).toStrictEqual({ foo: { bar: [1, [2, -0, [3, 0, 4]]] }, baz: -0 })\n  })\n})\n\ndescribe('recursive custom equality tester', () => {\n  let personId = 0\n\n  class Address {\n    public address: string\n\n    constructor(address: string) {\n      this.address = address\n    }\n  }\n  class Person {\n    public name: string\n    public address: Address\n    public personId: string\n\n    constructor(name: string, address: Address) {\n      this.name = name\n      this.address = address\n      this.personId = `${personId++}`\n    }\n  }\n\n  const arePersonsEqual: Tester = function (a, b, customTesters) {\n    const isAPerson = a instanceof Person\n    const isBPerson = b instanceof Person\n\n    if (isAPerson && isBPerson) {\n      return a.name === b.name && this.equals(a.address, b.address, customTesters)\n    }\n\n    else if (isAPerson === isBPerson) {\n      return undefined\n    }\n\n    else {\n      return false\n    }\n  }\n\n  const areAddressesEqual: Tester = (a, b) => {\n    const isAAddress = a instanceof Address\n    const isBAddress = b instanceof Address\n\n    if (isAAddress && isBAddress) {\n      return a.address === b.address\n    }\n\n    else if (isAAddress === isBAddress) {\n      return undefined\n    }\n\n    else { return false }\n  }\n\n  const person1 = new Person('Luke Skywalker', new Address('Tatooine'))\n  const person2 = new Person('Luke Skywalker', new Address('Tatooine'))\n\n  expect.addEqualityTesters([areAddressesEqual, arePersonsEqual])\n\n  test('basic matchers pass different Address objects', () => {\n    expect(person1).not.toBe(person2)\n    expect([person1]).not.toContain(person2)\n    expect(person1).toEqual(person1)\n    expect(person1).toEqual(person2)\n    expect([person1, person2]).toEqual([person2, person1])\n    expect(new Map([['key', person1]])).toEqual(new Map([['key', person2]]))\n    expect(new Set([person1])).toEqual(new Set([person2]))\n    expect([person1]).toContainEqual(person2)\n    expect({ a: person1 }).toHaveProperty('a', person2)\n    expect({ a: person1, b: undefined }).toStrictEqual({\n      a: person2,\n      b: undefined,\n    })\n    expect({ a: 1, b: { c: person1 } }).toMatchObject({\n      a: 1,\n      b: { c: person2 },\n    })\n  })\n\n  test('asymmetric matchers pass different Address objects', () => {\n    expect([person1]).toEqual(expect.arrayContaining([person2]))\n    expect({ a: 1, b: { c: person1 } }).toEqual(\n      expect.objectContaining({ b: { c: person2 } }),\n    )\n  })\n\n  test('toBe recommends toStrictEqual even with different Address objects', () => {\n    expect(() => expect(person1).toBe(person2)).toThrow('toStrictEqual')\n  })\n\n  test('toBe recommends toEqual even with different Address objects', () => {\n    expect(() => expect({ a: undefined, b: person1 }).toBe({ b: person2 })).toThrow(\n      'toEqual',\n    )\n  })\n\n  test('iterableEquality still properly detects cycles', () => {\n    const a = new Set()\n    a.add(person1)\n    a.add(a)\n\n    const b = new Set()\n    b.add(person2)\n    b.add(b)\n\n    expect(a).toEqual(b)\n  })\n\n  test('spy matchers pass different Person objects', () => {\n    const mockFn = vi.fn(\n      (person: Person) => [person, person2],\n    )\n    mockFn(person1)\n\n    expect(mockFn).toHaveBeenCalledWith(person1)\n    expect(mockFn).toHaveBeenCalledWith(person1)\n    expect(mockFn).toHaveBeenLastCalledWith(person1)\n    expect(mockFn).toHaveBeenNthCalledWith(1, person1)\n\n    expect(mockFn).toHaveReturnedWith([person1, person2])\n    expect(mockFn).toHaveLastReturnedWith([person1, person2])\n    expect(mockFn).to.have.lastReturnedWith([person1, person2])\n    expect(mockFn).toHaveNthReturnedWith(1, [person1, person2])\n  })\n})\n\ndescribe('iterator', () => {\n  test('returns true when given iterator within equal objects', () => {\n    const a = {\n      [Symbol.iterator]: () => ({ next: () => ({ done: true }) }),\n      a: [],\n    }\n    const b = {\n      [Symbol.iterator]: () => ({ next: () => ({ done: true }) }),\n      a: [],\n    }\n\n    expect(a).toStrictEqual(b)\n  })\n\n  test('returns false when given iterator within inequal objects', () => {\n    const a = {\n      [Symbol.iterator]: () => ({ next: () => ({ done: true }) }),\n      a: [1],\n    }\n    const b = {\n      [Symbol.iterator]: () => ({ next: () => ({ done: true }) }),\n      a: [],\n    }\n\n    expect(a).not.toStrictEqual(b)\n  })\n\n  test('returns false when given iterator within inequal nested objects', () => {\n    const a = {\n      [Symbol.iterator]: () => ({ next: () => ({ done: true }) }),\n      a: {\n        b: [1],\n      },\n    }\n    const b = {\n      [Symbol.iterator]: () => ({ next: () => ({ done: true }) }),\n      a: {\n        b: [],\n      },\n    }\n\n    expect(a).not.toStrictEqual(b)\n  })\n})\n\ndescribe('Temporal equality', () => {\n  describe.each([\n    ['Instant', ['2025-01-01T00:00:00.000Z', '2026-01-01T00:00:00.000Z']],\n    ['ZonedDateTime', ['2025-01-01T00:00:00+01:00[Europe/Amsterdam]', '2025-01-01T00:00:00+01:00[Europe/Paris]']],\n    ['PlainDateTime', ['2025-01-01T00:00:00.000', '2026-01-01T00:00:00.000']],\n    ['PlainDate', ['2025-01-01', '2026-01-01']],\n    ['PlainTime', ['15:00:00.000', '16:00:00.000']],\n    ['PlainYearMonth', ['2025-01', '2026-01']],\n    ['PlainMonthDay', ['01-01', '02-01']],\n  ] as const)('of $className', (className, [first, second]) => {\n    test('returns true when equal', () => {\n      const a = Temporal[className].from(first)\n      const b = Temporal[className].from(first)\n\n      expect(a).toStrictEqual(b)\n    })\n\n    test('returns false when not equal', () => {\n      const a = Temporal[className].from(first)\n      const b = Temporal[className].from(second)\n\n      expect(a).not.toStrictEqual(b)\n    })\n  })\n\n  describe('of Duration', () => {\n    test('returns true when .toString() is equal', () => {\n      const a = Temporal.Duration.from('P1M')\n      const b = Temporal.Duration.from('P1M')\n\n      expect(a).toStrictEqual(b)\n    })\n\n    test('returns true when .toString() is not equal', () => {\n      const a = Temporal.Duration.from('PT1M')\n      const b = Temporal.Duration.from('PT60S')\n\n      expect(a).not.toStrictEqual(b)\n    })\n  })\n})\n\ndescribe('expect with custom message', () => {\n  describe('built-in matchers', () => {\n    test('sync matcher throws custom message on failure', () => {\n      expect(() => expect(1, 'custom message').toBe(2)).toThrow('custom message')\n    })\n\n    test('async rejects matcher throws custom message on failure', async ({ expect }) => {\n      const asyncAssertion = expect(Promise.reject(new Error('test error')), 'custom async message').rejects.toBe(2)\n      await expect(asyncAssertion).rejects.toThrow('custom async message')\n    })\n\n    test('async resolves matcher throws custom message on failure', async ({ expect }) => {\n      const asyncAssertion = expect(Promise.resolve(1), 'custom async message').resolves.toBe(2)\n      await expect(asyncAssertion).rejects.toThrow('custom async message')\n    })\n\n    test('not matcher throws custom message on failure', () => {\n      expect(() => expect(1, 'custom message').not.toBe(1)).toThrow('custom message')\n    })\n  })\n\n  describe('custom matchers with expect.extend', () => {\n    test('sync custom matcher throws custom message on failure', ({ expect }) => {\n      expect.extend({\n        toBeFoo(actual) {\n          const { isNot } = this\n          return {\n            pass: actual === 'foo',\n            message: () => `${actual} is${isNot ? ' not' : ''} foo`,\n          }\n        },\n      })\n      expect(() => (expect('bar', 'custom message') as any).toBeFoo()).toThrow('custom message')\n    })\n\n    test('sync custom matcher passes with custom message when assertion succeeds', ({ expect }) => {\n      expect.extend({\n        toBeFoo(actual) {\n          const { isNot } = this\n          return {\n            pass: actual === 'foo',\n            message: () => `${actual} is${isNot ? ' not' : ''} foo`,\n          }\n        },\n      })\n      expect(() => (expect('foo', 'custom message') as any).toBeFoo()).not.toThrow()\n    })\n\n    test('async custom matcher throws custom message on failure', async ({ expect }) => {\n      expect.extend({\n        async toBeFoo(actual) {\n          const resolvedValue = await actual\n          return {\n            pass: resolvedValue === 'foo',\n            message: () => `${resolvedValue} is not foo`,\n          }\n        },\n      })\n      const asyncAssertion = (expect(Promise.resolve('bar'), 'custom async message') as any).toBeFoo()\n      await expect(asyncAssertion).rejects.toThrow('custom async message')\n    })\n\n    test('async custom matcher with not throws custom message on failure', async ({ expect }) => {\n      expect.extend({\n        async toBeFoo(actual) {\n          const resolvedValue = await actual\n          return {\n            pass: resolvedValue === 'foo',\n            message: () => `${resolvedValue} is not foo`,\n          }\n        },\n      })\n      const asyncAssertion = (expect(Promise.resolve('foo'), 'custom async message') as any).not.toBeFoo()\n      await expect(asyncAssertion).rejects.toThrow('custom async message')\n    })\n  })\n\n  describe('edge cases', () => {\n    test('empty custom message falls back to default matcher message', () => {\n      expect(() => expect(1, '').toBe(2)).toThrow('expected 1 to be 2 // Object.is equality')\n    })\n\n    test('undefined custom message falls back to default matcher message', () => {\n      expect(() => expect(1, undefined as any).toBe(2)).toThrow('expected 1 to be 2 // Object.is equality')\n    })\n  })\n})\n\ndescribe('Standard Schema', () => {\n  function createMockSchema(validate: StandardSchemaV1['~standard']['validate']): StandardSchemaV1 {\n    return {\n      '~standard': {\n        version: 1,\n        vendor: 'mock',\n        validate,\n      },\n    }\n  }\n\n  function createAsyncMockSchema(validate: StandardSchemaV1['~standard']['validate']): StandardSchemaV1 {\n    return {\n      '~standard': {\n        version: 1,\n        vendor: 'mock-async',\n        validate: value => Promise.resolve(validate(value)),\n      },\n    }\n  }\n\n  const stringSchema = createMockSchema(value =>\n    typeof value === 'string' ? { issues: undefined, value } : { issues: [{ message: 'Expected string' }] },\n  )\n  const numberSchema = createMockSchema(value =>\n    typeof value === 'number' ? { issues: undefined, value } : { issues: [{ message: 'Expected number' }] },\n  )\n  const emailSchema = createMockSchema(value =>\n    typeof value === 'string' && /^[\\w%+.-]+@[\\d.A-Z-]+\\.[A-Z]{2,}$/i.test(value) ? { issues: undefined, value } : { issues: [{ message: 'Expected email' }] },\n  )\n  const objectSchema = createMockSchema(value =>\n    typeof value === 'object' && value !== null && 'name' in value && 'age' in value && typeof value.name === 'string' && typeof value.age === 'number' ? { issues: undefined, value } : { issues: [{ message: 'Expected object' }] },\n  )\n  const asyncStringSchema = createAsyncMockSchema(value =>\n    typeof value === 'string' ? { issues: undefined, value } : { issues: [{ message: 'Expected string' }] },\n  )\n\n  describe('schemaMatching()', () => {\n    test('should work with primitive values', () => {\n      expect('hello').toEqual(expect.schemaMatching(stringSchema))\n      expect(42).toEqual(expect.schemaMatching(numberSchema))\n\n      expect(() => expect(123).toEqual(expect.schemaMatching(stringSchema))).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected 123 to deeply equal SchemaMatching{…}]`)\n      expect(() => expect('hello').toEqual(expect.schemaMatching(numberSchema))).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected 'hello' to deeply equal SchemaMatching{…}]`)\n\n      try {\n        expect(123).toEqual(expect.schemaMatching(stringSchema))\n        expect.unreachable()\n      }\n      catch (err) {\n        const error = processError(err)\n        const diff = stripVTControlCharacters(error.diff!)\n        expect(diff).toMatchInlineSnapshot(`\n          \"- Expected:\n          SchemaMatching {\n            \"issues\": [\n              {\n                \"message\": \"Expected string\",\n              },\n            ],\n          }\n\n          + Received:\n          123\"\n        `)\n      }\n    })\n\n    test('should work with objects', () => {\n      expect({\n        email: 'john@example.com',\n      }).toEqual({\n        email: expect.schemaMatching(emailSchema),\n      })\n\n      expect(() => expect({\n        email: 123,\n      }).toEqual({\n        email: expect.schemaMatching(emailSchema),\n      })).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected { email: 123 } to deeply equal { email: SchemaMatching{…} }]`)\n\n      try {\n        expect({\n          email: 'not-an-email',\n        }).toEqual({\n          email: expect.schemaMatching(emailSchema),\n        })\n        expect.unreachable()\n      }\n      catch (err) {\n        const error = processError(err)\n        const diff = stripVTControlCharacters(error.diff!)\n        expect(diff).toMatchInlineSnapshot(`\n          \"- Expected\n          + Received\n\n            {\n          -   \"email\": SchemaMatching {\n          -   \"issues\": [\n          -     {\n          -       \"message\": \"Expected email\",\n          -     },\n          -   ],\n          - },\n          +   \"email\": \"not-an-email\",\n            }\"\n        `)\n      }\n    })\n\n    test('should work with objectContaining', () => {\n      expect({\n        name: 'John',\n        age: 30,\n      }).toEqual(expect.objectContaining({\n        age: expect.schemaMatching(numberSchema),\n      }))\n\n      try {\n        expect({\n          user: {\n            name: 'John',\n            age: 'thirty',\n          },\n        }).toEqual({\n          user: {\n            name: expect.schemaMatching(stringSchema),\n            age: expect.schemaMatching(numberSchema),\n          },\n        })\n        expect.unreachable()\n      }\n      catch (err) {\n        const error = processError(err)\n        const diff = stripVTControlCharacters(error.diff!)\n        expect(diff).toMatchInlineSnapshot(`\n          \"- Expected\n          + Received\n\n            {\n              \"user\": {\n          -     \"age\": SchemaMatching {\n          -   \"issues\": [\n          -     {\n          -       \"message\": \"Expected number\",\n          -     },\n          -   ],\n          - },\n          +     \"age\": \"thirty\",\n                \"name\": \"John\",\n              },\n            }\"\n        `)\n      }\n    })\n\n    test('should work with arrayContaining', () => {\n      expect([{\n        name: 'John',\n        age: 30,\n      }]).toEqual(expect.arrayContaining([expect.schemaMatching(objectSchema)]))\n\n      try {\n        expect([{\n          name: 'John',\n          age: 'thirty',\n        }]).toEqual(expect.arrayContaining([expect.schemaMatching(objectSchema)]))\n        expect.unreachable()\n      }\n      catch (err) {\n        const error = processError(err)\n        const diff = stripVTControlCharacters(error.diff!)\n        expect(diff).toContain('SchemaMatching')\n        expect(diff).toContain('ArrayContaining')\n      }\n    })\n\n    test('should work with negation', () => {\n      expect(123).not.toEqual(expect.schemaMatching(stringSchema))\n      expect('hello').not.toEqual(expect.schemaMatching(numberSchema))\n\n      expect(() => expect('hello').not.toEqual(expect.schemaMatching(stringSchema))).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected 'hello' to not deeply equal SchemaMatching]`)\n\n      try {\n        expect('hello').not.toEqual(expect.schemaMatching(stringSchema))\n        expect.unreachable()\n      }\n      catch (err) {\n        const error = processError(err)\n        const diff = stripVTControlCharacters(error.diff!)\n        expect(diff).toMatchInlineSnapshot(`\n          \"- Expected:\n          SchemaMatching\n\n          + Received:\n          \"hello\"\"\n        `)\n      }\n    })\n\n    test('should throw error for async schemas', () => {\n      expect(() => expect('hello').toEqual(expect.schemaMatching(asyncStringSchema))).toThrowErrorMatchingInlineSnapshot(`[TypeError: Async schema validation is not supported in asymmetric matchers.]`)\n    })\n\n    test('should throw error for non-schema argument', () => {\n      expect(() => expect.schemaMatching('not-a-schema')).toThrowErrorMatchingInlineSnapshot(`[TypeError: SchemaMatching expected to receive a Standard Schema.]`)\n    })\n\n    test('should work with toMatchObject', () => {\n      const data = {\n        user: {\n          name: 'John',\n          age: 30,\n        },\n        extra: 'data',\n      }\n\n      expect(data).toMatchObject({\n        user: {\n          name: expect.schemaMatching(stringSchema),\n          age: expect.schemaMatching(numberSchema),\n        },\n      })\n\n      try {\n        expect({\n          user: {\n            name: 123,\n            age: 30,\n          },\n        }).toMatchObject({\n          user: {\n            name: expect.schemaMatching(stringSchema),\n          },\n        })\n        expect.unreachable()\n      }\n      catch (err) {\n        const error = processError(err)\n        const diff = stripVTControlCharacters(error.diff!)\n        expect(diff).toMatchInlineSnapshot(`\n          \"- Expected\n          + Received\n\n            {\n              \"user\": {\n          -     \"name\": SchemaMatching {\n          -   \"issues\": [\n          -     {\n          -       \"message\": \"Expected string\",\n          -     },\n          -   ],\n          - },\n          +     \"name\": 123,\n              },\n            }\"\n        `)\n      }\n\n      try {\n        expect({\n          name: 123,\n          email: 'invalid',\n          age: 'thirty',\n        }).toEqual({\n          name: expect.schemaMatching(stringSchema),\n          email: expect.schemaMatching(emailSchema),\n          age: expect.schemaMatching(numberSchema),\n        })\n        expect.unreachable()\n      }\n      catch (err) {\n        const error = processError(err)\n        const diff = stripVTControlCharacters(error.diff!)\n        expect(diff).toMatchInlineSnapshot(`\n          \"- Expected\n          + Received\n\n            {\n          -   \"age\": SchemaMatching {\n          -   \"issues\": [\n          -     {\n          -       \"message\": \"Expected number\",\n          -     },\n          -   ],\n          - },\n          -   \"email\": SchemaMatching {\n          -   \"issues\": [\n          -     {\n          -       \"message\": \"Expected email\",\n          -     },\n          -   ],\n          - },\n          -   \"name\": SchemaMatching {\n          -   \"issues\": [\n          -     {\n          -       \"message\": \"Expected string\",\n          -     },\n          -   ],\n          - },\n          +   \"age\": \"thirty\",\n          +   \"email\": \"invalid\",\n          +   \"name\": 123,\n            }\"\n        `)\n      }\n    })\n\n    test('function', () => {\n      const stringSchemaFn = Object.assign(() => {}, stringSchema)\n      expect('hello').toEqual(expect.schemaMatching(stringSchemaFn))\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/exports.test.ts",
    "content": "import { resolve } from 'node:path'\nimport { expect, it } from 'vitest'\nimport { getPackageExportsManifest } from 'vitest-package-exports'\n\nit('exports snapshot', async ({ skip, task }) => {\n  skip(task.file.pool !== 'threads', 'run only once inside threads')\n\n  const manifest = await getPackageExportsManifest({\n    importMode: 'package', // or 'dist' or 'package'\n    cwd: resolve(import.meta.dirname, '../../../packages/vitest'),\n    resolveExportEntries(entries) {\n      return entries.filter(([key]) => key !== './browser')\n    },\n  })\n  manifest.exports['./node'].rolldownVersion = 'conditional'\n\n  expect(manifest.exports).toMatchInlineSnapshot(`\n    {\n      \".\": {\n        \"BenchmarkRunner\": \"function\",\n        \"EvaluatedModules\": \"function\",\n        \"TestRunner\": \"function\",\n        \"afterAll\": \"function\",\n        \"afterEach\": \"function\",\n        \"aroundAll\": \"function\",\n        \"aroundEach\": \"function\",\n        \"assert\": \"function\",\n        \"assertType\": \"function\",\n        \"beforeAll\": \"function\",\n        \"beforeEach\": \"function\",\n        \"bench\": \"function\",\n        \"chai\": \"object\",\n        \"createExpect\": \"function\",\n        \"describe\": \"function\",\n        \"expect\": \"function\",\n        \"expectTypeOf\": \"function\",\n        \"inject\": \"function\",\n        \"it\": \"function\",\n        \"onTestFailed\": \"function\",\n        \"onTestFinished\": \"function\",\n        \"recordArtifact\": \"function\",\n        \"should\": \"function\",\n        \"suite\": \"function\",\n        \"test\": \"function\",\n        \"vi\": \"object\",\n        \"vitest\": \"object\",\n      },\n      \"./config\": {\n        \"configDefaults\": \"object\",\n        \"coverageConfigDefaults\": \"object\",\n        \"defaultBrowserPort\": \"number\",\n        \"defaultExclude\": \"object\",\n        \"defaultInclude\": \"object\",\n        \"defineConfig\": \"function\",\n        \"defineProject\": \"function\",\n        \"mergeConfig\": \"function\",\n      },\n      \"./coverage\": {\n        \"BaseCoverageProvider\": \"function\",\n      },\n      \"./environments\": {\n        \"builtinEnvironments\": \"object\",\n        \"populateGlobal\": \"function\",\n      },\n      \"./internal/browser\": {\n        \"DecodedMap\": \"function\",\n        \"SpyModule\": \"object\",\n        \"Traces\": \"function\",\n        \"__INTERNAL\": \"object\",\n        \"browserFormat\": \"function\",\n        \"collectTests\": \"function\",\n        \"format\": \"function\",\n        \"getOriginalPosition\": \"function\",\n        \"getSafeTimers\": \"function\",\n        \"getType\": \"function\",\n        \"inspect\": \"function\",\n        \"loadDiffConfig\": \"function\",\n        \"loadSnapshotSerializers\": \"function\",\n        \"processError\": \"function\",\n        \"setSafeTimers\": \"function\",\n        \"setupCommonEnv\": \"function\",\n        \"startCoverageInsideWorker\": \"function\",\n        \"startTests\": \"function\",\n        \"stopCoverageInsideWorker\": \"function\",\n        \"stringify\": \"function\",\n        \"takeCoverageInsideWorker\": \"function\",\n      },\n      \"./node\": {\n        \"AgentReporter\": \"function\",\n        \"BaseCoverageProvider\": \"function\",\n        \"BaseSequencer\": \"function\",\n        \"BenchmarkReporter\": \"function\",\n        \"BenchmarkReportsMap\": \"object\",\n        \"DefaultReporter\": \"function\",\n        \"DotReporter\": \"function\",\n        \"ForksPoolWorker\": \"function\",\n        \"GitNotFoundError\": \"function\",\n        \"GithubActionsReporter\": \"function\",\n        \"HangingProcessReporter\": \"function\",\n        \"JUnitReporter\": \"function\",\n        \"JsonReporter\": \"function\",\n        \"ReportersMap\": \"object\",\n        \"TapFlatReporter\": \"function\",\n        \"TapReporter\": \"function\",\n        \"TestsNotFoundError\": \"function\",\n        \"ThreadsPoolWorker\": \"function\",\n        \"TypecheckPoolWorker\": \"function\",\n        \"VerboseBenchmarkReporter\": \"function\",\n        \"VerboseReporter\": \"function\",\n        \"VitestPackageInstaller\": \"function\",\n        \"VitestPlugin\": \"function\",\n        \"VmForksPoolWorker\": \"function\",\n        \"VmThreadsPoolWorker\": \"function\",\n        \"createDebugger\": \"function\",\n        \"createMethodsRPC\": \"function\",\n        \"createViteLogger\": \"function\",\n        \"createViteServer\": \"function\",\n        \"createVitest\": \"function\",\n        \"distDir\": \"string\",\n        \"esbuildVersion\": \"string\",\n        \"escapeTestName\": \"function\",\n        \"experimental_getRunnerTask\": \"function\",\n        \"generateFileHash\": \"function\",\n        \"getFilePoolName\": \"function\",\n        \"isCSSRequest\": \"function\",\n        \"isFileLoadingAllowed\": \"function\",\n        \"isFileServingAllowed\": \"function\",\n        \"isValidApiRequest\": \"function\",\n        \"parseAst\": \"function\",\n        \"parseAstAsync\": \"function\",\n        \"parseCLI\": \"function\",\n        \"registerConsoleShortcuts\": \"function\",\n        \"resolveApiServerConfig\": \"function\",\n        \"resolveConfig\": \"function\",\n        \"resolveFsAllow\": \"function\",\n        \"rolldownVersion\": \"conditional\",\n        \"rollupVersion\": \"string\",\n        \"rootDir\": \"string\",\n        \"startVitest\": \"function\",\n        \"version\": \"string\",\n        \"viteVersion\": \"string\",\n      },\n      \"./reporters\": {\n        \"AgentReporter\": \"function\",\n        \"BenchmarkReporter\": \"function\",\n        \"BenchmarkReportsMap\": \"object\",\n        \"DefaultReporter\": \"function\",\n        \"DotReporter\": \"function\",\n        \"GithubActionsReporter\": \"function\",\n        \"HangingProcessReporter\": \"function\",\n        \"JUnitReporter\": \"function\",\n        \"JsonReporter\": \"function\",\n        \"ReportersMap\": \"object\",\n        \"TapFlatReporter\": \"function\",\n        \"TapReporter\": \"function\",\n        \"VerboseBenchmarkReporter\": \"function\",\n        \"VerboseReporter\": \"function\",\n      },\n      \"./runners\": {\n        \"NodeBenchmarkRunner\": \"function\",\n        \"VitestTestRunner\": \"function\",\n      },\n      \"./runtime\": {\n        \"VitestSnapshotEnvironment\": \"function\",\n        \"__INTERNAL\": \"object\",\n        \"builtinEnvironments\": \"object\",\n        \"populateGlobal\": \"function\",\n      },\n      \"./snapshot\": {\n        \"VitestSnapshotEnvironment\": \"function\",\n      },\n      \"./suite\": {\n        \"createChainable\": \"function\",\n        \"createTaskCollector\": \"function\",\n        \"getBenchFn\": \"function\",\n        \"getBenchOptions\": \"function\",\n        \"getCurrentSuite\": \"function\",\n        \"getCurrentTest\": \"function\",\n        \"getFn\": \"function\",\n        \"getHooks\": \"function\",\n        \"setFn\": \"function\",\n        \"setHooks\": \"function\",\n      },\n      \"./worker\": {\n        \"init\": \"function\",\n        \"runBaseTests\": \"function\",\n        \"setupEnvironment\": \"function\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/core/test/external-module-directory.test.ts",
    "content": "// @ts-expect-error not typed aliased import\nimport getModuleType from 'custom-lib'\nimport { expect, it } from 'vitest'\n\nit('custom-lib is externalized because it\\'s a valid esm file in module directory', () => {\n  expect(getModuleType()).toBe('undefined')\n})\n"
  },
  {
    "path": "test/core/test/file-path.test.ts",
    "content": "import { describe, expect, it, vi } from 'vitest'\n\nvi.mock('fs', () => {\n  return {\n    existsSync: vi.fn(),\n  }\n})\n\nconst isWindows = process.platform === 'win32'\n\ndescribe('current url', () => {\n  it('__filename is equal to import.meta.url', () => {\n    expect(__filename).toEqual(import.meta.filename)\n  })\n\n  it('__dirname is equal to import.meta.dirname', () => {\n    expect(__dirname).toEqual(import.meta.dirname)\n  })\n\n  describe.runIf(!isWindows)('unix', () => {\n    it('__filename', () => {\n      expect(__filename.startsWith('file://')).toBe(false)\n      expect(__filename.endsWith('test/core/test/file-path.test.ts')).toBe(true)\n    })\n\n    it('__dirname', () => {\n      expect(__dirname.startsWith('file://')).toBe(false)\n      expect(__dirname.endsWith('test/core/test')).toBe(true)\n    })\n\n    it('import.meta.url', () => {\n      expect(import.meta.url.startsWith('file://')).toBe(true)\n      expect(import.meta.url.endsWith('test/core/test/file-path.test.ts')).toBe(true)\n    })\n  })\n\n  describe.runIf(isWindows)('windows', () => {\n    // consistently inconsistent with Node, CJS has \\, ESM has /\n    const cwd = process.cwd()\n    const windowsDrive = `${cwd[0].toUpperCase()}:\\\\`\n    const drivePosix = `${cwd[0].toUpperCase()}:/`\n\n    it('__filename', () => {\n      expect(__filename.startsWith('file://')).toBe(false)\n      expect(__filename.startsWith(windowsDrive + windowsDrive)).toBe(false)\n      expect(__filename.startsWith(windowsDrive)).toBe(true)\n      expect(__filename.endsWith('\\\\test\\\\core\\\\test\\\\file-path.test.ts')).toBe(true)\n    })\n\n    it('__dirname', () => {\n      expect(__dirname.startsWith('file://')).toBe(false)\n      expect(__dirname.startsWith(windowsDrive + windowsDrive)).toBe(false)\n      expect(__dirname.startsWith(windowsDrive)).toBe(true)\n      expect(__dirname.endsWith('\\\\test\\\\core\\\\test')).toBe(true)\n    })\n\n    it('import.meta.url', () => {\n      expect(import.meta.url.startsWith(`file:///${drivePosix}`)).toBe(true)\n      expect(import.meta.url.endsWith('test/core/test/file-path.test.ts')).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/fixture-comments-between-destructure.test.ts",
    "content": "/* eslint-disable style/spaced-comment */\nimport { test as base, expect } from 'vitest'\n\nconst test = base.extend<{\n  one: 1\n  two: 2\n}>({\n  one: 1,\n  two: 2,\n})\n\ntest('no comments', ({ one, two }) => {\n  expect(one).toBe(1)\n  expect(two).toBe(2)\n})\n\ntest('inline comment', ({\n  one,\n  // comment\n  two,\n}) => {\n  expect(one).toBe(1)\n  expect(two).toBe(2)\n})\n\ntest('multiline comment', ({\n  one,\n  /**\n   * comment\n   */\n  two,\n}) => {\n  expect(one).toBe(1)\n  expect(two).toBe(2)\n})\n\ntest('inline legal comment', ({\n  one,\n  //! comment\n  two,\n}) => {\n  expect(one).toBe(1)\n  expect(two).toBe(2)\n})\n\ntest('multiline legal comment', ({\n  one,\n  /*! comment */\n  two,\n}) => {\n  expect(one).toBe(1)\n  expect(two).toBe(2)\n})\n"
  },
  {
    "path": "test/core/test/fixture-concurrent-beforeEach.test.ts",
    "content": "import { afterAll, beforeEach, expect, test } from 'vitest'\n\n// this test case might look exotic, but a few conditions were required to reproduce the reported bug.\n// such particular conditions are marked with \"[repro]\" in the comments.\n\nlet globalA = 0\nlet globalB = 0\n\ninterface MyFixtures {\n  a: number\n  b: number\n}\n\nexport const myTest = test.extend<MyFixtures>({\n  // [repro] fixture order must be { a, b } and not { b, a }\n  a: async ({}, use) => {\n    globalA++\n    await new Promise<void>(resolve => setTimeout(resolve, 200)) // [repro] async fixture\n    await use(globalA)\n  },\n  b: async ({}, use) => {\n    globalB++\n    await use(globalB)\n  },\n})\n\n// [repro] beforeEach uses only \"b\"\nbeforeEach<MyFixtures>(({ b }) => {\n  expect(b).toBeTypeOf('number')\n})\n\nafterAll(() => {\n  expect([globalA, globalB]).toEqual([2, 2])\n})\n\n// [repro] concurrent test uses both \"a\" and \"b\"\nmyTest.concurrent('test1', async ({ a, b }) => {\n  expect(a).toBeTypeOf('number')\n  expect(b).toBeTypeOf('number')\n})\n\nmyTest.concurrent('test2', async ({ a, b }) => {\n  expect(a).toBeTypeOf('number')\n  expect(b).toBeTypeOf('number')\n})\n"
  },
  {
    "path": "test/core/test/fixture-concurrent.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nexport const myTest = test.extend<{\n  a: string\n  b: string\n}>({\n  a: async ({ task }: any, use) => {\n    await new Promise<void>(resolve => setTimeout(resolve, 200))\n    await use(task.id)\n  },\n  b: async ({ a }, use) => {\n    await use(a)\n  },\n})\n\nmyTest.concurrent('fixture - concurrent test 1', ({ a, b, task }) => {\n  expect(a).toBe(task.id)\n  expect(b).toBe(task.id)\n})\n\nmyTest.concurrent('fixture - concurrent test 2', ({ a, b, task }) => {\n  expect(a).toBe(task.id)\n  expect(b).toBe(task.id)\n})\n"
  },
  {
    "path": "test/core/test/fixture-initialization.test.ts",
    "content": "import type { Use } from '@vitest/runner'\nimport { beforeEach, describe, expect, expectTypeOf, test, vi } from 'vitest'\n\ninterface Fixtures {\n  a: number\n  b: number\n  c: number\n  d: number\n}\n\nconst fnB = vi.fn()\nconst myTest = test.extend<Pick<Fixtures, 'a' | 'b'>>({\n  a: 1,\n  b: async ({ a }, use) => {\n    fnB()\n    await use (a * 2) // 2\n    fnB.mockClear()\n  },\n})\n\nconst fnA = vi.fn()\nconst fnB2 = vi.fn()\nconst fnC = vi.fn()\nconst fnD = vi.fn()\nconst myTest2 = myTest.extend<Pick<Fixtures, 'c' | 'd'> & { a: string; b: string }>({\n  // override origin a\n  a: async ({ a: originA }, use) => {\n    expectTypeOf(originA).toEqualTypeOf<number>()\n    fnA()\n    await use(String(originA)) // '1'\n    fnA.mockClear()\n  },\n  b: async ({ a }, use) => {\n    expectTypeOf(a).toEqualTypeOf<string>()\n    fnB2()\n    await use(String(Number(a) * 2)) // '2'\n    fnB2.mockClear()\n  },\n  c: async ({ a, b }, use) => {\n    expectTypeOf(b).toEqualTypeOf<string>()\n    fnC()\n    await use(Number(a) + Number(b)) // 3\n    fnC.mockClear()\n  },\n  d: async ({ a, b, c }, use) => {\n    fnD()\n    await use(Number(a) + Number(b) + c) // 6\n    fnD.mockClear()\n  },\n})\n\ndescribe('fixture initialization', () => {\n  describe('fixture override', () => {\n    myTest('origin a and b', ({ a, b }) => {\n      expect(a).toBe(1)\n      expect(b).toBe(2)\n\n      expectTypeOf(a).toEqualTypeOf<number>()\n      expectTypeOf(b).toEqualTypeOf<number>()\n\n      expect(fnB).toBeCalledTimes(1)\n\n      expect(fnB2).not.toBeCalled()\n      expect(fnA).not.toBeCalled()\n      expect(fnC).not.toBeCalled()\n      expect(fnD).not.toBeCalled()\n    })\n\n    myTest2('overriding a and b', ({ a, b }) => {\n      expect(a).toBe('1')\n      expect(b).toBe('2')\n\n      expectTypeOf(a).toEqualTypeOf<string>()\n      expectTypeOf(b).toEqualTypeOf<string>()\n\n      expect(fnA).toBeCalledTimes(1)\n      expect(fnB).toBeCalledTimes(0)\n      expect(fnB2).toBeCalledTimes(1)\n\n      expect(fnC).not.toBeCalled()\n      expect(fnD).not.toBeCalled()\n    })\n  })\n\n  myTest.runIf(true)('fixtures work with runIf', ({ a }) => {\n    expect(a).toBe(1)\n  })\n\n  myTest.skipIf(false)('fixtures work with skipIf', ({ a }) => {\n    expect(a).toBe(1)\n  })\n\n  describe('fixture dependency', () => {\n    myTest2('b => a', ({ b }) => {\n      expect(b).toBe('2')\n\n      expect(fnA).toBeCalledTimes(1)\n      expect(fnB).toBeCalledTimes(0)\n      expect(fnB2).toBeCalledTimes(1)\n\n      expect(fnC).not.toBeCalled()\n      expect(fnD).not.toBeCalled()\n    })\n\n    myTest2('c => [a, b]', ({ c }) => {\n      expect(c).toBe(3)\n\n      expect(fnA).toBeCalledTimes(1)\n      expect(fnB).toBeCalledTimes(0)\n      expect(fnB2).toBeCalledTimes(1)\n      expect(fnC).toBeCalledTimes(1)\n\n      expect(fnD).not.toBeCalled()\n    })\n\n    myTest2('d => c', ({ d }) => {\n      expect(d).toBe(6)\n\n      expect(fnA).toBeCalledTimes(1)\n      expect(fnB).toBeCalledTimes(0)\n      expect(fnB2).toBeCalledTimes(1)\n      expect(fnC).toBeCalledTimes(1)\n      expect(fnD).toBeCalledTimes(1)\n    })\n\n    myTest2('should only call once for each fixture fn', ({ a, b, c, d }) => {\n      expect(a).toBe('1')\n      expect(b).toBe('2')\n      expect(c).toBe(3)\n      expect(d).toBe(6)\n\n      expect(fnA).toBeCalledTimes(1)\n      expect(fnB).toBeCalledTimes(0)\n      expect(fnB2).toBeCalledTimes(1)\n      expect(fnC).toBeCalledTimes(1)\n      expect(fnD).toBeCalledTimes(1)\n    })\n  })\n\n  describe('fixture dependency', () => {\n    const myTest = test\n      .extend({ a: 1 })\n      .extend({\n        b: async ({ a }, use: Use<number>) => {\n          expectTypeOf(a).toEqualTypeOf<number>()\n          await use(a * 2)\n        },\n      })\n\n    myTest('b => a', ({ b }) => {\n      expectTypeOf(b).toEqualTypeOf<number>()\n      expect(b).toBe(2)\n    })\n  })\n\n  describe('fixture todos', () => {\n    const todos: number[] = []\n    const archive: number[] = []\n\n    const myTest = test.extend<{ todos: number[]; archive: number[] }>({\n      todos: async ({}, use) => {\n        // setup the fixture before each test function\n        todos.push(1, 2, 3)\n\n        // use the fixture value\n        await use(todos)\n\n        // cleanup the fixture after each test function\n        todos.length = 0\n      },\n      archive,\n    })\n\n    myTest('add items to todos', ({ todos }) => {\n      expect(todos.length).toBe(3)\n\n      todos.push(4)\n      expect(todos.length).toBe(4)\n    })\n\n    myTest('move items from todos to archive', ({ todos, archive }) => {\n      expect(todos.length).toBe(3)\n      expect(archive.length).toBe(0)\n\n      archive.push(todos.pop() as number)\n      expect(todos.length).toBe(2)\n      expect(archive.length).toBe(1)\n    })\n  })\n\n  describe('accessing non-fixture context', () => {\n    const myTest = test.extend({ a: 1 })\n\n    beforeEach(async ({ task }) => {\n      expect(task).toBeTruthy()\n    })\n\n    myTest('non-fixture context can be accessed without accessing fixtures', ({ task }) => {\n      expect(task).toBeTruthy()\n    })\n  })\n})\n\nconst myTest3 = test.extend<{ value: string }>({\n  value: [async ({}, use) => { await use('first-value') }, { scope: 'file' }],\n})\n\nconst myTest4 = test.extend<{ value: string }>({\n  value: [async ({}, use) => { await use('second-value') }, { scope: 'file' }],\n})\n\nmyTest3('test1', ({ value }) => {\n  expect(value).toBe('first-value')\n})\n\nmyTest4('test2', ({ value }) => {\n  expect(value).toBe('second-value')\n})\n"
  },
  {
    "path": "test/core/test/fixture-options.test.ts",
    "content": "import { afterAll, beforeEach, describe, expect, test, vi } from 'vitest'\n\nconst mockServer = { setup: vi.fn(), teardown: vi.fn() }\nconst FnA = vi.fn()\n\nconst myTest = test.extend<{\n  autoFixture: void\n  normalFixture: any[]\n}>({\n  autoFixture: [async ({}, use) => {\n    await mockServer.setup()\n    await use()\n    await mockServer.teardown()\n  }, { auto: true }],\n\n  normalFixture: [async () => {\n    await FnA()\n  }, {}],\n})\n\ndescribe('fixture with options', () => {\n  describe('automatic fixture', () => {\n    beforeEach(() => {\n      expect(mockServer.setup).toBeCalledTimes(1)\n    })\n\n    afterAll(() => {\n      expect(mockServer.setup).toBeCalledTimes(1)\n      expect(mockServer.teardown).toBeCalledTimes(1)\n    })\n\n    myTest('should setup mock server', () => {\n      expect(mockServer.setup).toBeCalledTimes(1)\n    })\n  })\n\n  describe('normal fixture', () => {\n    myTest('it is not a fixture with options', ({ normalFixture }) => {\n      expect(FnA).not.toBeCalled()\n      expect(normalFixture).toBeInstanceOf(Array)\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/fixtures/hello-mock.ts",
    "content": "export class HelloWorld {\n  hello() {\n    return 'Hello World!'\n  }\n}\n"
  },
  {
    "path": "test/core/test/fixtures/hi.txt",
    "content": "Hello, World!\n"
  },
  {
    "path": "test/core/test/fixtures/increment-indirect.ts",
    "content": "import { increment } from './increment'\n\nexport function incrementIndirect(num: number) {\n  return increment(num)\n}\n"
  },
  {
    "path": "test/core/test/fixtures/increment.ts",
    "content": "export function increment(num: number) {\n  return num + 1\n}\n"
  },
  {
    "path": "test/core/test/fixtures/mocked-dependency.ts",
    "content": "export function helloWorld(): void {\n  throw new Error('not implemented')\n}\n"
  },
  {
    "path": "test/core/test/fixtures/named-overwrite-all/dep1.js",
    "content": "export const a = 'dep1-a'\nexport const b = 'dep1-b'\nexport const c = 'dep1-c'\nexport const d = 'dep1-d'\n"
  },
  {
    "path": "test/core/test/fixtures/named-overwrite-all/dep2.js",
    "content": "export const d = 'dep2-d'\n"
  },
  {
    "path": "test/core/test/fixtures/named-overwrite-all/main.js",
    "content": "export const a = 'main-a'\nexport * from './dep1.js'\nexport const c = 'main-c'\nexport * from './dep2.js'\n"
  },
  {
    "path": "test/core/test/fixtures/snapshot-empty.txt",
    "content": ""
  },
  {
    "path": "test/core/test/fixtures/snapshots/basic/input.json",
    "content": "[\n  [\n    \".name\",\n    {\n      \"color\": \"red\"\n    }\n  ]\n]\n"
  },
  {
    "path": "test/core/test/fixtures/snapshots/basic/output.css",
    "content": ".name {\n  color: red;\n}"
  },
  {
    "path": "test/core/test/fixtures/snapshots/multiple/input.json",
    "content": "[\n  [\n    \".text-red\",\n    {\n      \"color\": \"red\"\n    }\n  ],\n  [\n    \".text-lg\",\n    {\n      \"font-size\": \"1.25rem\",\n      \"line-height\": \"1.75rem\"\n    }\n  ]\n]\n"
  },
  {
    "path": "test/core/test/fixtures/snapshots/multiple/output.css",
    "content": ".text-red {\n  color: red;\n}\n.text-lg {\n  font-size: 1.25rem;\n  line-height: 1.75rem;\n}"
  },
  {
    "path": "test/core/test/fixtures/timers.suite.ts",
    "content": "/* eslint-disable no-restricted-globals */\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck taken from Jest, but tsconfig doesn't allow most of the code\n\n/**\n * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of https://github.com/facebook/jest.\n */\n\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport { FakeTimers } from '../../../../packages/vitest/src/integrations/mock/timers'\n\nclass FakeDate extends Date {}\n\nconst isChildProcess = !!process.send\n\ndescribe('FakeTimers', () => {\n  afterEach(() => {\n    vi.useRealTimers()\n  })\n\n  describe('construction', () => {\n    it('installs setTimeout mock', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      expect(global.setTimeout).not.toBe(undefined)\n    })\n\n    it('installs clearTimeout mock', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      expect(global.clearTimeout).not.toBe(undefined)\n    })\n\n    it('installs setInterval mock', () => {\n      const global = { Date: FakeDate, clearTimeout, clearInterval, process, setTimeout, setInterval }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      expect(global.setInterval).not.toBe(undefined)\n    })\n\n    it('installs clearInterval mock', () => {\n      const global = { Date: FakeDate, clearTimeout, clearInterval, process, setTimeout, setInterval }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      expect(global.clearInterval).not.toBe(undefined)\n    })\n\n    it.skipIf(isChildProcess)('mocks process.nextTick if it exists on global', () => {\n      const origNextTick = () => {}\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process: {\n          nextTick: origNextTick,\n        },\n        setTimeout,\n      }\n      const timers = new FakeTimers({ global, config: { toFake: ['nextTick'] } })\n      timers.useFakeTimers()\n      expect(global.process.nextTick).not.toBe(origNextTick)\n    })\n\n    it.runIf(isChildProcess)('does not mock process.nextTick if it exists on global and is child_process', () => {\n      const origNextTick = () => {}\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process: {\n          nextTick: origNextTick,\n        },\n        setTimeout,\n      }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      expect(global.process.nextTick).toBe(origNextTick)\n    })\n\n    it.runIf(isChildProcess)('throws when is child_process and tries to mock nextTick', () => {\n      const global = { Date: FakeDate, process, setTimeout, clearTimeout }\n      const timers = new FakeTimers({ global, config: { toFake: ['nextTick'] } })\n\n      expect(() => timers.useFakeTimers()).toThrow(\n        'process.nextTick cannot be mocked inside child_process',\n      )\n    })\n\n    it('mocks setImmediate if it exists on global', () => {\n      const origSetImmediate = () => {}\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process,\n        setImmediate: origSetImmediate,\n        setTimeout,\n      }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      expect(global.setImmediate).not.toBe(origSetImmediate)\n    })\n\n    it('mocks clearImmediate if setImmediate is on global', () => {\n      const origSetImmediate = () => {}\n      const origClearImmediate = () => {}\n      const global = {\n        Date: FakeDate,\n        clearImmediate: origClearImmediate,\n        clearTimeout,\n        process,\n        setImmediate: origSetImmediate,\n        setTimeout,\n      }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      expect(global.clearImmediate).not.toBe(origClearImmediate)\n    })\n\n    it('mocks requestIdleCallback if it exists on global', () => {\n      const origRequestIdleCallback = () => {}\n      const global = { Date: FakeDate, clearTimeout, setTimeout, requestIdleCallback: origRequestIdleCallback }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      expect(global.requestIdleCallback).not.toBe(origRequestIdleCallback)\n    })\n\n    it('cannot mock setImmediate and clearImmediate if not on global', () => {\n      const global = { Date: FakeDate, clearTimeout, setTimeout };\n      const timers = new FakeTimers({ global, config: { toFake: [\"setImmediate\", \"clearImmediate\"] }})\n      timers.useFakeTimers()\n      expect(global.setImmediate).toBeUndefined();\n      expect(global.clearImmediate).toBeUndefined();\n    })\n  })\n\n  describe('runAllTicks', () => {\n    it.skipIf(isChildProcess)('runs all ticks, in order', () => {\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process: {\n          nextTick: () => {},\n        },\n        setTimeout,\n      }\n\n      const timers = new FakeTimers({ global, config: { toFake: ['nextTick'] } })\n      timers.useFakeTimers()\n\n      const runOrder = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n\n      global.process.nextTick(mock1)\n      global.process.nextTick(mock2)\n\n      expect(mock1).toHaveBeenCalledTimes(0)\n      expect(mock2).toHaveBeenCalledTimes(0)\n\n      timers.runAllTicks()\n\n      expect(mock1).toHaveBeenCalledTimes(1)\n      expect(mock2).toHaveBeenCalledTimes(1)\n      expect(runOrder).toEqual(['mock1', 'mock2'])\n    })\n\n    it('does nothing when no ticks have been scheduled', () => {\n      const nextTick = vi.fn()\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process: {\n          nextTick,\n        },\n        setTimeout,\n      }\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      timers.runAllTicks()\n\n      expect(nextTick).toHaveBeenCalledTimes(0)\n    })\n\n    it.skipIf(isChildProcess)('only runs a scheduled callback once', () => {\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process: {\n          nextTick: () => {},\n        },\n        setTimeout,\n      }\n\n      const timers = new FakeTimers({ global, config: { toFake: ['nextTick'] } })\n      timers.useFakeTimers()\n\n      const mock1 = vi.fn()\n      global.process.nextTick(mock1)\n      expect(mock1).toHaveBeenCalledTimes(0)\n\n      timers.runAllTicks()\n      expect(mock1).toHaveBeenCalledTimes(1)\n\n      timers.runAllTicks()\n      expect(mock1).toHaveBeenCalledTimes(1)\n    })\n\n    it.skipIf(isChildProcess)('throws before allowing infinite recursion', () => {\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process: {\n          nextTick: () => {},\n        },\n        setTimeout,\n      }\n\n      const timers = new FakeTimers({ global, config: { loopLimit: 100, toFake: ['nextTick'] } })\n\n      timers.useFakeTimers()\n\n      global.process.nextTick(function infinitelyRecursingCallback() {\n        global.process.nextTick(infinitelyRecursingCallback)\n      })\n\n      expect(() => {\n        timers.runAllTicks()\n      }).toThrow(\n        'Aborting after running 100 timers, assuming an infinite loop!',\n      )\n    })\n  })\n\n  describe('runAllTimers', () => {\n    it('runs all timers in order', () => {\n      const global = { Date: FakeDate, clearTimeout, clearInterval, process, setTimeout, setInterval }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n      const mock5 = vi.fn(() => runOrder.push('mock5'))\n      const mock6 = vi.fn(() => runOrder.push('mock6'))\n\n      global.setTimeout(mock1, 100)\n      global.setTimeout(mock2, Number.NaN)\n      global.setTimeout(mock3, 0)\n      const intervalHandler = global.setInterval(() => {\n        mock4()\n        global.clearInterval(intervalHandler)\n      }, 200)\n      global.setTimeout(mock5, Number.POSITIVE_INFINITY)\n      global.setTimeout(mock6, Number.NEGATIVE_INFINITY)\n\n      timers.runAllTimers()\n      expect(runOrder).toEqual([\n        'mock2',\n        'mock3',\n        'mock5',\n        'mock6',\n        'mock1',\n        'mock4',\n      ])\n    })\n\n    it('warns when trying to advance timers while real timers are used', () => {\n      const timers = new FakeTimers({\n        config: {\n          rootDir: import.meta.dirname,\n        },\n        global,\n      })\n      expect(() => timers.runAllTimers()).toThrow(/A function to advance timers was called but the timers APIs are not mocked/)\n    })\n\n    it('does nothing when no timers have been scheduled', () => {\n      const nativeSetTimeout = vi.fn()\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process,\n        setTimeout: nativeSetTimeout,\n      }\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n      timers.runAllTimers()\n    })\n\n    it('only runs a setTimeout callback once (ever)', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const fn = vi.fn()\n      global.setTimeout(fn, 0)\n      expect(fn).toHaveBeenCalledTimes(0)\n\n      timers.runAllTimers()\n      expect(fn).toHaveBeenCalledTimes(1)\n\n      timers.runAllTimers()\n      expect(fn).toHaveBeenCalledTimes(1)\n    })\n\n    it('runs callbacks with arguments after the interval', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const fn = vi.fn()\n      global.setTimeout(fn, 0, 'mockArg1', 'mockArg2')\n\n      timers.runAllTimers()\n      expect(fn).toHaveBeenCalledTimes(1)\n      expect(fn).toHaveBeenCalledWith('mockArg1', 'mockArg2')\n    })\n\n    it('doesn\\'t pass the callback to native setTimeout', () => {\n      const nativeSetTimeout = vi.fn()\n\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process,\n        setTimeout: nativeSetTimeout,\n      }\n\n      const timers = new FakeTimers({ global })\n      // @sinonjs/fake-timers uses `setTimeout` during init to figure out if it's in Node or\n      // browser env. So clear its calls before we install them into the env\n      nativeSetTimeout.mockClear()\n      timers.useFakeTimers()\n\n      const mock1 = vi.fn()\n      global.setTimeout(mock1, 0)\n\n      timers.runAllTimers()\n      expect(mock1).toHaveBeenCalledTimes(1)\n      expect(nativeSetTimeout).toHaveBeenCalledTimes(0)\n    })\n\n    it('throws before allowing infinite recursion', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global, config: { loopLimit: 100 } })\n      timers.useFakeTimers()\n\n      global.setTimeout(function infinitelyRecursingCallback() {\n        global.setTimeout(infinitelyRecursingCallback, 0)\n      }, 0)\n\n      expect(() => {\n        timers.runAllTimers()\n      }).toThrow(\n        'Aborting after running 100 timers, assuming an infinite loop!',\n      )\n    })\n\n    it.skipIf(isChildProcess)('also clears ticks', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global, config: { toFake: ['nextTick', 'setTimeout'] } })\n      timers.useFakeTimers()\n\n      const fn = vi.fn()\n      global.setTimeout(() => {\n        process.nextTick(fn)\n      }, 0)\n      expect(fn).toHaveBeenCalledTimes(0)\n\n      timers.runAllTimers()\n      expect(fn).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  describe('runAllTimersAsync', () => {\n    it('runs all timers in order', async () => {\n      const global = { Date: FakeDate, clearTimeout, clearInterval, process, setTimeout, setInterval, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n      const mock5 = vi.fn(() => runOrder.push('mock5'))\n      const mock6 = vi.fn(() => runOrder.push('mock6'))\n\n      global.setTimeout(mock1, 100)\n      global.setTimeout(mock2, Number.NaN)\n      global.setTimeout(mock3, 0)\n      const intervalHandler = global.setInterval(() => {\n        mock4()\n        global.clearInterval(intervalHandler)\n      }, 200)\n      global.setTimeout(mock5, Number.POSITIVE_INFINITY)\n      global.setTimeout(mock6, Number.NEGATIVE_INFINITY)\n\n      await timers.runAllTimersAsync()\n      expect(runOrder).toEqual([\n        'mock2',\n        'mock3',\n        'mock5',\n        'mock6',\n        'mock1',\n        'mock4',\n      ])\n    })\n\n    it('warns when trying to advance timers while real timers are used', async () => {\n      const timers = new FakeTimers({\n        config: {\n          rootDir: import.meta.dirname,\n        },\n        global,\n      })\n      await expect(timers.runAllTimersAsync()).rejects.toThrow(/A function to advance timers was called but the timers APIs are not mocked/)\n    })\n\n    it('only runs a setTimeout callback once (ever)', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const fn = vi.fn()\n      global.setTimeout(fn, 0)\n      expect(fn).toHaveBeenCalledTimes(0)\n\n      await timers.runAllTimersAsync()\n      expect(fn).toHaveBeenCalledTimes(1)\n\n      await timers.runAllTimersAsync()\n      expect(fn).toHaveBeenCalledTimes(1)\n    })\n\n    it('runs callbacks with arguments after the interval', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const fn = vi.fn()\n      global.setTimeout(fn, 0, 'mockArg1', 'mockArg2')\n\n      await timers.runAllTimersAsync()\n      expect(fn).toHaveBeenCalledTimes(1)\n      expect(fn).toHaveBeenCalledWith('mockArg1', 'mockArg2')\n    })\n\n    it('throws before allowing infinite recursion', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, Promise }\n      const timers = new FakeTimers({ global, config: { loopLimit: 20 } })\n      timers.useFakeTimers()\n\n      global.setTimeout(function infinitelyRecursingCallback() {\n        global.setTimeout(infinitelyRecursingCallback, 0)\n      }, 0)\n\n      await expect(\n        timers.runAllTimersAsync(),\n      ).rejects.toThrow(\n        'Aborting after running 20 timers, assuming an infinite loop!',\n      )\n    })\n\n    it.skipIf(isChildProcess)('also clears ticks', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, Promise }\n      const timers = new FakeTimers({ global, config: { toFake: ['setTimeout', 'nextTick'] } })\n      timers.useFakeTimers()\n\n      const fn = vi.fn()\n      global.setTimeout(() => {\n        process.nextTick(fn)\n      }, 0)\n      expect(fn).toHaveBeenCalledTimes(0)\n\n      await timers.runAllTimersAsync()\n      expect(fn).toHaveBeenCalledTimes(1)\n    })\n\n    it('all callbacks are called when setTimeout calls asynchronous method', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder = []\n      const mock2 = vi.fn(async () => {\n        runOrder.push('mock2')\n        return global.Promise.resolve(true)\n      })\n      const mock1 = vi.fn(async () => {\n        await mock2()\n        runOrder.push('mock1')\n      })\n\n      global.setTimeout(mock1, 100)\n      await timers.runAllTimersAsync()\n\n      expect(runOrder).toEqual([\n        'mock2',\n        'mock1',\n      ])\n    })\n  })\n\n  describe('advanceTimersByTime', () => {\n    it('runs timers in order', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, setInterval }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n\n      global.setTimeout(mock1, 100)\n      global.setTimeout(mock2, 0)\n      global.setTimeout(mock3, 0)\n      global.setInterval(() => {\n        mock4()\n      }, 200)\n\n      // Move forward to t=50\n      timers.advanceTimersByTime(50)\n      expect(runOrder).toEqual(['mock2', 'mock3'])\n\n      // Move forward to t=60\n      timers.advanceTimersByTime(10)\n      expect(runOrder).toEqual(['mock2', 'mock3'])\n\n      // Move forward to t=100\n      timers.advanceTimersByTime(40)\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1'])\n\n      // Move forward to t=200\n      timers.advanceTimersByTime(100)\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4'])\n\n      // Move forward to t=400\n      timers.advanceTimersByTime(200)\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4', 'mock4'])\n    })\n\n    it('does nothing when no timers have been scheduled', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      timers.advanceTimersByTime(100)\n    })\n  })\n\n  describe('advanceTimersByTimeAsync', () => {\n    it('runs timers in order', async () => {\n      const global = { Date: FakeDate, clearTimeout, clearInterval, process, setTimeout, setInterval, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n\n      global.setTimeout(mock1, 100)\n      global.setTimeout(mock2, 0)\n      global.setTimeout(mock3, 0)\n      global.setInterval(() => {\n        mock4()\n      }, 200)\n\n      // Move forward to t=50\n      await timers.advanceTimersByTimeAsync(50)\n      expect(runOrder).toEqual(['mock2', 'mock3'])\n\n      // Move forward to t=60\n      await timers.advanceTimersByTimeAsync(10)\n      expect(runOrder).toEqual(['mock2', 'mock3'])\n\n      // Move forward to t=100\n      await timers.advanceTimersByTimeAsync(40)\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1'])\n\n      // Move forward to t=200\n      await timers.advanceTimersByTimeAsync(100)\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4'])\n\n      // Move forward to t=400\n      await timers.advanceTimersByTimeAsync(200)\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4', 'mock4'])\n    })\n\n    it('does nothing when no timers have been scheduled', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      await timers.advanceTimersByTimeAsync(100)\n    })\n  })\n\n  describe('advanceTimersToNextTimer', () => {\n    it('runs timers in order', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, setInterval }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n\n      global.setTimeout(mock1, 100)\n      global.setTimeout(mock2, 0)\n      global.setTimeout(mock3, 0)\n      global.setInterval(() => {\n        mock4()\n      }, 200)\n\n      timers.advanceTimersToNextTimer()\n      // Move forward to t=0\n      expect(runOrder).toEqual(['mock2', 'mock3'])\n\n      timers.advanceTimersToNextTimer()\n      // Move forward to t=100\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1'])\n\n      timers.advanceTimersToNextTimer()\n      // Move forward to t=200\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4'])\n\n      timers.advanceTimersToNextTimer()\n      // Move forward to t=400\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4', 'mock4'])\n    })\n\n    it('run correct amount of steps', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, setInterval }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n\n      global.setTimeout(mock1, 100)\n      global.setTimeout(mock2, 0)\n      global.setTimeout(mock3, 0)\n      global.setInterval(() => {\n        mock4()\n      }, 200)\n\n      // Move forward to t=100\n      timers.advanceTimersToNextTimer(2)\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1'])\n\n      // Move forward to t=600\n      timers.advanceTimersToNextTimer(3)\n      expect(runOrder).toEqual([\n        'mock2',\n        'mock3',\n        'mock1',\n        'mock4',\n        'mock4',\n        'mock4',\n      ])\n    })\n\n    it('setTimeout inside setTimeout', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n\n      global.setTimeout(mock1, 0)\n      global.setTimeout(() => {\n        mock2()\n        global.setTimeout(mock3, 50)\n      }, 25)\n      global.setTimeout(mock4, 100)\n\n      // Move forward to t=75\n      timers.advanceTimersToNextTimer(3)\n      expect(runOrder).toEqual(['mock1', 'mock2', 'mock3'])\n    })\n\n    it('does nothing when no timers have been scheduled', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      timers.advanceTimersToNextTimer()\n    })\n  })\n\n  describe('advanceTimersToNextTimerAsync', () => {\n    it('runs timers in order', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, setInterval, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n\n      global.setTimeout(mock1, 100)\n      global.setTimeout(mock2, 0)\n      global.setTimeout(mock3, 0)\n      global.setInterval(() => {\n        mock4()\n      }, 200)\n\n      await timers.advanceTimersToNextTimer()\n      // Move forward to t=0\n      expect(runOrder).toEqual(['mock2', 'mock3'])\n\n      await timers.advanceTimersToNextTimer()\n      // Move forward to t=100\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1'])\n\n      await timers.advanceTimersToNextTimer()\n      // Move forward to t=200\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4'])\n\n      await timers.advanceTimersToNextTimer()\n      // Move forward to t=400\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1', 'mock4', 'mock4'])\n    })\n\n    it('run correct amount of steps', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, setInterval, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n\n      global.setTimeout(mock1, 100)\n      global.setTimeout(mock2, 0)\n      global.setTimeout(mock3, 0)\n      global.setInterval(() => {\n        mock4()\n      }, 200)\n\n      // Move forward to t=100\n      await timers.advanceTimersToNextTimer(2)\n      expect(runOrder).toEqual(['mock2', 'mock3', 'mock1'])\n\n      // Move forward to t=600\n      await timers.advanceTimersToNextTimer(3)\n      expect(runOrder).toEqual([\n        'mock2',\n        'mock3',\n        'mock1',\n        'mock4',\n        'mock4',\n        'mock4',\n      ])\n    })\n\n    it('setTimeout inside setTimeout', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n      const mock4 = vi.fn(() => runOrder.push('mock4'))\n\n      global.setTimeout(mock1, 0)\n      global.setTimeout(() => {\n        mock2()\n        global.setTimeout(mock3, 50)\n      }, 25)\n      global.setTimeout(mock4, 100)\n\n      // Move forward to t=75\n      await timers.advanceTimersToNextTimer(3)\n      expect(runOrder).toEqual(['mock1', 'mock2', 'mock3'])\n    })\n\n    it('does nothing when no timers have been scheduled', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      await timers.advanceTimersToNextTimer()\n    })\n  })\n\n  describe('advanceTimersToNextFrame', () => {\n    it('runs scheduled animation frame callbacks in order', () => {\n      const global = {\n        Date,\n        clearTimeout,\n        process,\n        requestAnimationFrame: () => -1,\n        setTimeout,\n      } as unknown as typeof globalThis\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n      const mock1 = vi.fn(() => runOrder.push('mock1'))\n      const mock2 = vi.fn(() => runOrder.push('mock2'))\n      const mock3 = vi.fn(() => runOrder.push('mock3'))\n\n      global.requestAnimationFrame(mock1)\n      global.requestAnimationFrame(mock2)\n      global.requestAnimationFrame(mock3)\n\n      timers.advanceTimersToNextFrame()\n\n      expect(runOrder).toEqual(['mock1', 'mock2', 'mock3'])\n    })\n\n    it('should only run currently scheduled animation frame callbacks', () => {\n      const global = {\n        Date,\n        clearTimeout,\n        process,\n        requestAnimationFrame: () => -1,\n        setTimeout,\n      } as unknown as typeof globalThis\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n      function run() {\n        runOrder.push('first-frame')\n\n        // scheduling another animation frame in the first frame\n        global.requestAnimationFrame(() => runOrder.push('second-frame'))\n      }\n\n      global.requestAnimationFrame(run)\n\n      // only the first frame should be executed\n      timers.advanceTimersToNextFrame()\n\n      expect(runOrder).toEqual(['first-frame'])\n\n      timers.advanceTimersToNextFrame()\n\n      expect(runOrder).toEqual(['first-frame', 'second-frame'])\n    })\n\n    it('should allow cancelling of scheduled animation frame callbacks', () => {\n      const global = {\n        Date,\n        cancelAnimationFrame: () => {},\n        clearTimeout,\n        process,\n        requestAnimationFrame: () => -1,\n        setTimeout,\n      } as unknown as typeof globalThis\n\n      const timers = new FakeTimers({ global })\n      const callback = vi.fn()\n      timers.useFakeTimers()\n\n      const timerId = global.requestAnimationFrame(callback)\n      global.cancelAnimationFrame(timerId)\n\n      timers.advanceTimersToNextFrame()\n\n      expect(callback).not.toHaveBeenCalled()\n    })\n\n    it('should only advance as much time is needed to get to the next frame', () => {\n      const global = {\n        Date,\n        cancelAnimationFrame: () => {},\n        clearTimeout,\n        process,\n        requestAnimationFrame: () => -1,\n        setTimeout,\n      } as unknown as typeof globalThis\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n      const start = global.Date.now()\n\n      const callback = () => runOrder.push('frame')\n      global.requestAnimationFrame(callback)\n\n      // Advancing timers less than a frame (which is 16ms)\n      timers.advanceTimersByTime(6)\n      expect(global.Date.now()).toEqual(start + 6)\n\n      // frame not yet executed\n      expect(runOrder).toEqual([])\n\n      // move timers forward to execute frame\n      timers.advanceTimersToNextFrame()\n\n      // frame has executed as time has moved forward 10ms to get to the 16ms frame time\n      expect(runOrder).toEqual(['frame'])\n      expect(global.Date.now()).toEqual(start + 16)\n    })\n\n    it('should execute any timers on the way to the animation frame', () => {\n      const global = {\n        Date,\n        cancelAnimationFrame: () => {},\n        clearTimeout,\n        process,\n        requestAnimationFrame: () => -1,\n        setTimeout,\n      } as unknown as typeof globalThis\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n\n      global.requestAnimationFrame(() => runOrder.push('frame'))\n\n      // scheduling a timeout that will be executed on the way to the frame\n      global.setTimeout(() => runOrder.push('timeout'), 10)\n\n      // move timers forward to execute frame\n      timers.advanceTimersToNextFrame()\n\n      expect(runOrder).toEqual(['timeout', 'frame'])\n    })\n\n    it('should not execute any timers scheduled inside of an animation frame callback', () => {\n      const global = {\n        Date,\n        cancelAnimationFrame: () => {},\n        clearTimeout,\n        process,\n        requestAnimationFrame: () => -1,\n        setTimeout,\n      } as unknown as typeof globalThis\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder: Array<string> = []\n\n      global.requestAnimationFrame(() => {\n        runOrder.push('frame')\n        // scheduling a timer inside of a frame\n        global.setTimeout(() => runOrder.push('timeout'), 1)\n      })\n\n      timers.advanceTimersToNextFrame()\n\n      // timeout not yet executed\n      expect(runOrder).toEqual(['frame'])\n\n      // validating that the timer will still be executed\n      timers.advanceTimersByTime(1)\n      expect(runOrder).toEqual(['frame', 'timeout'])\n    })\n\n    it('should call animation frame callbacks with the latest system time', () => {\n      const global = {\n        Date,\n        clearTimeout,\n        performance,\n        process,\n        requestAnimationFrame: () => -1,\n        setTimeout,\n      } as unknown as typeof globalThis\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const callback = vi.fn()\n\n      global.requestAnimationFrame(callback)\n\n      timers.advanceTimersToNextFrame()\n\n      // `requestAnimationFrame` callbacks are called with a `DOMHighResTimeStamp`\n      expect(callback).toHaveBeenCalledWith(global.performance.now())\n    })\n  })\n\n  describe('reset', () => {\n    it('resets all pending setTimeouts', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const mock1 = vi.fn()\n      global.setTimeout(mock1, 100)\n\n      timers.reset()\n      timers.runAllTimers()\n      expect(mock1).toHaveBeenCalledTimes(0)\n    })\n\n    it('resets all pending setIntervals', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, setInterval }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const mock1 = vi.fn()\n      global.setInterval(mock1, 200)\n\n      timers.reset()\n      timers.runAllTimers()\n      expect(mock1).toHaveBeenCalledTimes(0)\n    })\n\n    it('resets all pending ticks callbacks', () => {\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process: {\n          nextTick: () => {},\n        },\n        setImmediate: () => {},\n        setTimeout,\n      }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const mock1 = vi.fn()\n      global.process.nextTick(mock1)\n      global.setImmediate(mock1)\n\n      timers.reset()\n      timers.runAllTicks()\n      expect(mock1).toHaveBeenCalledTimes(0)\n    })\n\n    it('resets current advanceTimersByTime time cursor', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const mock1 = vi.fn()\n      global.setTimeout(mock1, 100)\n      timers.advanceTimersByTime(50)\n\n      timers.reset()\n      global.setTimeout(mock1, 100)\n\n      timers.advanceTimersByTime(50)\n      expect(mock1).toHaveBeenCalledTimes(0)\n    })\n  })\n\n  describe('runOnlyPendingTimers', () => {\n    it('runs all timers in order', () => {\n      const nativeSetImmediate = vi.fn()\n\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process,\n        setImmediate: nativeSetImmediate,\n        setTimeout,\n        setInterval,\n      }\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder = []\n\n      global.setTimeout(function cb() {\n        runOrder.push('mock1')\n        global.setTimeout(cb, 100)\n      }, 100)\n\n      global.setTimeout(function cb() {\n        runOrder.push('mock2')\n        global.setTimeout(cb, 50)\n      }, 0)\n\n      global.setInterval(() => {\n        runOrder.push('mock3')\n      }, 200)\n\n      global.setImmediate(() => {\n        runOrder.push('mock4')\n      })\n\n      global.setImmediate(function cb() {\n        runOrder.push('mock5')\n        global.setTimeout(cb, 400)\n      })\n\n      timers.runOnlyPendingTimers()\n      const firsRunOrder = [\n        'mock4',\n        'mock5',\n        'mock2',\n        'mock2',\n        'mock1',\n        'mock2',\n        'mock2',\n        'mock3',\n        'mock1',\n        'mock2',\n      ]\n\n      expect(runOrder).toEqual(firsRunOrder)\n\n      timers.runOnlyPendingTimers()\n      expect(runOrder).toEqual([\n        ...firsRunOrder,\n        'mock2',\n        'mock1',\n        'mock2',\n        'mock2',\n        'mock3',\n        'mock5',\n        'mock1',\n        'mock2',\n      ])\n    })\n\n    it('does not run timers that were cleared in another timer', () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const fn = vi.fn()\n      const timer = global.setTimeout(fn, 10)\n      global.setTimeout(() => {\n        global.clearTimeout(timer)\n      }, 0)\n\n      timers.runOnlyPendingTimers()\n      expect(fn).not.toBeCalled()\n    })\n  })\n\n  describe('runOnlyPendingTimersAsync', () => {\n    it('runs all existing timers', async () => {\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process,\n        setTimeout,\n        Promise,\n      }\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const spies = [vi.fn(), vi.fn()]\n      global.setTimeout(spies[0], 10)\n      global.setTimeout(spies[1], 50)\n\n      await timers.runOnlyPendingTimersAsync()\n\n      expect(spies[0]).toBeCalled()\n      expect(spies[1]).toBeCalled()\n    })\n\n    it('runs all timers in order', async () => {\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process,\n        setImmediate,\n        setTimeout,\n        setInterval,\n        Promise,\n      }\n\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const runOrder = []\n\n      global.setTimeout(function cb() {\n        runOrder.push('mock1')\n        global.setTimeout(cb, 100)\n      }, 100)\n\n      global.setTimeout(function cb() {\n        runOrder.push('mock2')\n        global.setTimeout(cb, 50)\n      }, 0)\n\n      global.setInterval(() => {\n        runOrder.push('mock3')\n      }, 200)\n\n      global.setImmediate(() => {\n        runOrder.push('mock4')\n      })\n\n      global.setImmediate(function cb() {\n        runOrder.push('mock5')\n        global.setTimeout(cb, 400)\n      })\n\n      await timers.runOnlyPendingTimersAsync()\n      const firsRunOrder = [\n        'mock4',\n        'mock5',\n        'mock2',\n        'mock2',\n        'mock1',\n        'mock2',\n        'mock2',\n        'mock3',\n        'mock1',\n        'mock2',\n      ]\n\n      expect(runOrder).toEqual(firsRunOrder)\n\n      await timers.runOnlyPendingTimersAsync()\n      expect(runOrder).toEqual([\n        ...firsRunOrder,\n        'mock2',\n        'mock1',\n        'mock2',\n        'mock2',\n        'mock3',\n        'mock5',\n        'mock1',\n        'mock2',\n      ])\n    })\n\n    it('does not run timers that were cleared in another timer', async () => {\n      const global = { Date: FakeDate, clearTimeout, process, setTimeout, Promise }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      const fn = vi.fn()\n      const timer = global.setTimeout(fn, 10)\n      global.setTimeout(() => {\n        global.clearTimeout(timer)\n      }, 0)\n\n      await timers.runOnlyPendingTimersAsync()\n      expect(fn).not.toBeCalled()\n    })\n  })\n\n  describe('useRealTimers', () => {\n    it('resets native timer APIs', () => {\n      const nativeSetTimeout = vi.fn()\n      const nativeSetInterval = vi.fn()\n      const nativeClearTimeout = vi.fn()\n      const nativeClearInterval = vi.fn()\n\n      const global = {\n        Date: FakeDate,\n        clearInterval: nativeClearInterval,\n        clearTimeout: nativeClearTimeout,\n        process,\n        setInterval: nativeSetInterval,\n        setTimeout: nativeSetTimeout,\n      }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      // Ensure that timers has overridden the native timer APIs\n      // (because if it didn't, this test might pass when it shouldn't)\n      expect(global.setTimeout).not.toBe(nativeSetTimeout)\n      expect(global.setInterval).not.toBe(nativeSetInterval)\n      expect(global.clearTimeout).not.toBe(nativeClearTimeout)\n      expect(global.clearInterval).not.toBe(nativeClearInterval)\n\n      timers.useRealTimers()\n\n      expect(global.setTimeout).toBe(nativeSetTimeout)\n      expect(global.setInterval).toBe(nativeSetInterval)\n      expect(global.clearTimeout).toBe(nativeClearTimeout)\n      expect(global.clearInterval).toBe(nativeClearInterval)\n    })\n\n    it.skipIf(isChildProcess)('resets native process.nextTick when present', () => {\n      const nativeProcessNextTick = vi.fn()\n\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process: { nextTick: nativeProcessNextTick },\n        setTimeout,\n      }\n      const timers = new FakeTimers({ global, config: { toFake: ['nextTick'] } })\n      timers.useFakeTimers()\n\n      // Ensure that timers has overridden the native timer APIs\n      // (because if it didn't, this test might pass when it shouldn't)\n      expect(global.process.nextTick).not.toBe(nativeProcessNextTick)\n\n      timers.useRealTimers()\n\n      expect(global.process.nextTick).toBe(nativeProcessNextTick)\n    })\n\n    it('resets native setImmediate when present', () => {\n      const nativeSetImmediate = vi.fn()\n      const nativeClearImmediate = vi.fn()\n\n      const global = {\n        Date: FakeDate,\n        clearImmediate: nativeClearImmediate,\n        clearTimeout,\n        process,\n        setImmediate: nativeSetImmediate,\n        setTimeout,\n      }\n      const timers = new FakeTimers({ global })\n      timers.useFakeTimers()\n\n      // Ensure that timers has overridden the native timer APIs\n      // (because if it didn't, this test might pass when it shouldn't)\n      expect(global.setImmediate).not.toBe(nativeSetImmediate)\n      expect(global.clearImmediate).not.toBe(nativeClearImmediate)\n\n      timers.useRealTimers()\n\n      expect(global.setImmediate).toBe(nativeSetImmediate)\n      expect(global.clearImmediate).toBe(nativeClearImmediate)\n    })\n  })\n\n  describe('useFakeTimers', () => {\n    it('resets mock timer APIs', () => {\n      const nativeSetTimeout = vi.fn()\n      const nativeSetInterval = vi.fn()\n      const nativeClearTimeout = vi.fn()\n      const nativeClearInterval = vi.fn()\n\n      const global = {\n        Date: FakeDate,\n        clearInterval: nativeClearInterval,\n        clearTimeout: nativeClearTimeout,\n        process,\n        setInterval: nativeSetInterval,\n        setTimeout: nativeSetTimeout,\n      }\n      const timers = new FakeTimers({ global })\n      timers.useRealTimers()\n\n      // Ensure that the real timers are installed at this point\n      // (because if they aren't, this test might pass when it shouldn't)\n      expect(global.setTimeout).toBe(nativeSetTimeout)\n      expect(global.setInterval).toBe(nativeSetInterval)\n      expect(global.clearTimeout).toBe(nativeClearTimeout)\n      expect(global.clearInterval).toBe(nativeClearInterval)\n\n      timers.useFakeTimers()\n\n      expect(global.setTimeout).not.toBe(nativeSetTimeout)\n      expect(global.setInterval).not.toBe(nativeSetInterval)\n      expect(global.clearTimeout).not.toBe(nativeClearTimeout)\n      expect(global.clearInterval).not.toBe(nativeClearInterval)\n    })\n\n    it.skipIf(isChildProcess)('resets mock process.nextTick when present', () => {\n      const nativeProcessNextTick = vi.fn()\n\n      const global = {\n        Date: FakeDate,\n        clearTimeout,\n        process: { nextTick: nativeProcessNextTick },\n        setTimeout,\n      }\n      const timers = new FakeTimers({ global, config: { toFake: ['nextTick'] } })\n      timers.useRealTimers()\n\n      // Ensure that the real timers are installed at this point\n      // (because if they aren't, this test might pass when it shouldn't)\n      expect(global.process.nextTick).toBe(nativeProcessNextTick)\n\n      timers.useFakeTimers()\n\n      expect(global.process.nextTick).not.toBe(nativeProcessNextTick)\n    })\n\n    it('resets mock setImmediate when present', () => {\n      const nativeSetImmediate = vi.fn()\n      const nativeClearImmediate = vi.fn()\n\n      const global = {\n        Date: FakeDate,\n        clearImmediate: nativeClearImmediate,\n        clearTimeout,\n        process,\n        setImmediate: nativeSetImmediate,\n        setTimeout,\n      }\n      const fakeTimers = new FakeTimers({ global })\n      fakeTimers.useRealTimers()\n\n      // Ensure that the real timers are installed at this point\n      // (because if they aren't, this test might pass when it shouldn't)\n      expect(global.setImmediate).toBe(nativeSetImmediate)\n      expect(global.clearImmediate).toBe(nativeClearImmediate)\n\n      fakeTimers.useFakeTimers()\n\n      expect(global.setImmediate).not.toBe(nativeSetImmediate)\n      expect(global.clearImmediate).not.toBe(nativeClearImmediate)\n\n      fakeTimers.useRealTimers()\n    })\n  })\n\n  describe('getTimerCount', () => {\n    it('returns the correct count', () => {\n      const timers = new FakeTimers({ global })\n\n      timers.useFakeTimers()\n\n      global.setTimeout(() => {}, 0)\n      global.setTimeout(() => {}, 0)\n      global.setTimeout(() => {}, 10)\n\n      expect(timers.getTimerCount()).toEqual(3)\n\n      timers.advanceTimersByTime(5)\n\n      expect(timers.getTimerCount()).toEqual(1)\n\n      timers.advanceTimersByTime(5)\n\n      expect(timers.getTimerCount()).toEqual(0)\n\n      timers.useRealTimers()\n    })\n\n    it.skipIf(isChildProcess)('includes immediates and ticks', () => {\n      const timers = new FakeTimers({ global, config: { toFake: ['setTimeout', 'setImmediate', 'nextTick'] } })\n\n      timers.useFakeTimers()\n\n      global.setTimeout(() => {}, 0)\n      global.setImmediate(() => {})\n      process.nextTick(() => {})\n\n      expect(timers.getTimerCount()).toEqual(3)\n\n      timers.useRealTimers()\n    })\n\n    it('not includes cancelled immediates', () => {\n      const timers = new FakeTimers({ global })\n\n      timers.useFakeTimers()\n\n      global.setImmediate(() => {})\n      expect(timers.getTimerCount()).toEqual(1)\n      timers.clearAllTimers()\n\n      expect(timers.getTimerCount()).toEqual(0)\n\n      timers.useRealTimers()\n    })\n\n    it('throws when using useFakeTimers after setSystemTime', () => {\n      const timers = new FakeTimers({ global })\n\n      const timeStr = 'Fri Feb 20 2015 19:29:31 GMT+0530'\n      const timeStrMs = 1424440771000\n\n      timers.setSystemTime(timeStr)\n\n      expect(Date.now()).toBe(timeStrMs)\n\n      expect(() => timers.useFakeTimers()).not.toThrow()\n\n      expect(Date.now()).toBe(timeStrMs)\n\n      // Some test\n\n      timers.useRealTimers()\n    })\n  })\n\n  describe('setTimerTickMode', () => {\n    const realTimeout = setTimeout;\n    let timers: FakeTimers;\n\n    beforeEach(() => {\n      timers = new FakeTimers({ global })\n      timers.useFakeTimers();\n    })\n    afterEach(() => {\n      timers.useRealTimers();\n    })\n\n    it('can be set to manual', async () => {\n      const spy = vi.fn()\n      setTimeout(spy, 10)\n\n      timers.setTimerTickMode('manual')\n      await new Promise(resolve => realTimeout(resolve, 20))\n\n      expect(spy).not.toHaveBeenCalled()\n\n      timers.advanceTimersByTime(100)\n      expect(spy).toHaveBeenCalledOnce()\n    })\n\n    it('can be set to nextTimerAsync', async () => {\n      const spy = vi.fn()\n      setTimeout(spy, 10_000_000)\n\n      timers.setTimerTickMode('nextTimerAsync')\n      await new Promise(resolve => setTimeout(resolve, 20_000_000))\n\n      expect(spy).toHaveBeenCalledOnce()\n    })\n\n    it('can be set to interval', async () => {\n      const spy = vi.fn()\n      setTimeout(spy, 10)\n\n      timers.setTimerTickMode('interval', 5)\n      await new Promise(resolve => setTimeout(resolve, 15))\n\n      expect(spy).toHaveBeenCalledOnce()\n    })\n\n    it('can switch from nextTimerAsync to manual', async () => {\n      const spy = vi.fn()\n      setTimeout(spy, 10)\n\n      timers.setTimerTickMode('nextTimerAsync')\n\n      // Let one macrotask run, but the timer is not due yet.\n      await new Promise(resolve => setTimeout(resolve, 5))\n      expect(spy).not.toHaveBeenCalled()\n\n      timers.setTimerTickMode('manual')\n\n      await new Promise(resolve => realTimeout(resolve, 10))\n\n      expect(spy).not.toHaveBeenCalled()\n\n      timers.advanceTimersByTime(100)\n      expect(spy).toHaveBeenCalledOnce()\n    })\n\n    it('nextTimerAsync advances timers scheduled inside other timers', async () => {\n      const nestedSpy = vi.fn()\n      const spy = vi.fn(() => {\n        setTimeout(nestedSpy, 50)\n      })\n      setTimeout(spy, 100)\n\n      timers.setTimerTickMode('nextTimerAsync')\n\n      // Wait long enough for both timers to have a chance to run\n      await new Promise(resolve => setTimeout(resolve, 300))\n\n      expect(spy).toHaveBeenCalledOnce()\n      expect(nestedSpy).toHaveBeenCalledOnce()\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/fixtures/virtual-module-indirect.ts",
    "content": "// @ts-expect-error virtual module\nimport { value } from 'virtual-module-indirect'\n\nexport function getVirtualValue() {\n  return value\n}\n"
  },
  {
    "path": "test/core/test/fn.test.ts",
    "content": "import { assert, describe, expect, it, vitest } from 'vitest'\n\ndescribe('mock', () => {\n  it('basic', () => {\n    const fn = vitest.fn()\n\n    expect(fn).not.toHaveBeenCalled()\n\n    fn()\n\n    expect(fn).toHaveBeenCalled()\n    expect(fn).toHaveBeenCalledOnce()\n    expect(fn).toHaveBeenCalledTimes(1)\n\n    fn.mockReset()\n\n    expect(fn).not.toHaveBeenCalled()\n\n    fn('World', 2)\n    fn('Hi', 1)\n\n    expect(fn.mock.calls[1]).toEqual(['Hi', 1])\n\n    expect(fn).toHaveBeenNthCalledWith(1, 'World', 2)\n    expect(fn).toHaveBeenNthCalledWith(2, 'Hi', 1)\n    expect(fn).toHaveBeenLastCalledWith('Hi', 1)\n    expect(fn).toHaveBeenCalledWith('Hi', 1)\n  })\n\n  it('toHaveBeenCalledWith', () => {\n    const fn = vitest.fn()\n\n    fn('Hi', 2)\n\n    expect(fn).toHaveBeenCalledWith('Hi', 2)\n  })\n\n  it('returns', () => {\n    let i = 0\n\n    const fn = vitest.fn(() => String(++i))\n\n    expect(fn).not.toHaveReturned()\n\n    fn()\n\n    expect(fn).toHaveReturned()\n    expect(fn).toHaveReturnedTimes(1)\n    expect(fn).toHaveReturnedWith('1')\n\n    fn()\n    fn()\n\n    expect(fn).toHaveReturnedTimes(3)\n    expect(fn).toHaveNthReturnedWith(2, '2')\n    expect(fn).toHaveLastReturnedWith('3')\n  })\n\n  it('resolved', async () => {\n    let i = 0\n\n    const fn = vitest.fn(() => Promise.resolve(String(++i)))\n\n    expect(fn).not.toHaveResolved()\n\n    await fn()\n\n    expect(fn).toHaveResolved()\n    expect(fn).toHaveResolvedTimes(1)\n    expect(fn).toHaveResolvedWith('1')\n\n    await fn()\n    await fn()\n\n    expect(fn).toHaveResolvedTimes(3)\n    expect(fn).toHaveNthResolvedWith(2, '2')\n    expect(fn).toHaveLastResolvedWith('3')\n  })\n\n  it('throws', () => {\n    let i = 0\n\n    const fn = vitest.fn(() => {\n      if (i === 0) {\n        ++i\n        throw new Error('error')\n      }\n\n      return String(++i)\n    })\n\n    try {\n      fn()\n    }\n    catch {}\n    expect(fn).not.toHaveReturned()\n\n    fn()\n    expect(fn).toHaveReturned()\n\n    fn()\n\n    try {\n      expect(fn).toHaveNthReturnedWith(1, '1')\n      assert.fail('expect should throw, since 1st call is thrown')\n    }\n    catch {}\n\n    // not throws\n    expect(fn).not.toHaveNthReturnedWith(1, '1')\n\n    expect(fn).toHaveReturnedTimes(2)\n    expect(fn).toHaveNthReturnedWith(3, '3')\n  })\n\n  it('rejects', async () => {\n    let i = 0\n\n    const fn = vitest.fn(async () => {\n      if (i === 0) {\n        ++i\n        throw new Error('error')\n      }\n\n      return String(++i)\n    })\n\n    try {\n      await fn()\n    }\n    catch {}\n    expect(fn).not.toHaveResolved()\n\n    await fn()\n    expect(fn).toHaveResolved()\n\n    await fn()\n\n    try {\n      expect(fn).toHaveNthResolvedWith(1, '1')\n      assert.fail('expect should throw, since 1st call is thrown')\n    }\n    catch {}\n\n    // not throws\n    expect(fn).not.toHaveNthResolvedWith(1, '1')\n\n    expect(fn).toHaveResolvedTimes(2)\n    expect(fn).toHaveNthResolvedWith(3, '3')\n  })\n})\n"
  },
  {
    "path": "test/core/test/fs.test.ts",
    "content": "import fs from 'node:fs/promises'\nimport { fileURLToPath } from 'node:url'\nimport { resolve } from 'pathe'\nimport { describe, expect, it } from 'vitest'\nimport { timeout } from '../src/timeout'\n\nconst content = 'Hello, World!'\nconst filename = 'fixtures/hi.txt'\n\ndescribe('fs', () => {\n  it('import.meta.dirname', async () => {\n    const raw = await fs.readFile(resolve(import.meta.dirname, filename), 'utf-8')\n\n    expect(raw.trim()).toEqual(content)\n  })\n\n  it('import.meta.filename', async () => {\n    const raw = await fs.readFile(resolve(import.meta.filename, '..', filename), 'utf-8')\n\n    expect(raw.trim()).toEqual(content)\n  })\n\n  it('import.meta.url', async () => {\n    const raw = await fs.readFile(resolve(fileURLToPath(import.meta.url), '..', filename), 'utf-8')\n\n    expect(raw.trim()).toEqual(content)\n  })\n})\n\nit('timeout', () => new Promise(resolve => setTimeout(resolve, timeout)))\n"
  },
  {
    "path": "test/core/test/handled-unhandled.test.ts",
    "content": "import { nextTick } from 'node:process'\nimport { expect, test, vi } from 'vitest'\n\ntest('can test unhandled rejection', async () => {\n  const fn = vi.fn()\n\n  const promise = new Promise<void>((resolve) => {\n    process.on('unhandledRejection', () => {\n      fn()\n      resolve()\n    })\n  })\n\n  Promise.resolve().then(() => {\n    throw new Error('unhandled rejection')\n  })\n\n  await promise\n\n  expect(fn).toHaveBeenCalledTimes(1)\n})\n\ntest('can test unhandled exception', async () => {\n  const fn = vi.fn()\n\n  const promise = new Promise<void>((resolve) => {\n    process.on('uncaughtException', () => {\n      fn()\n      resolve()\n    })\n  })\n\n  nextTick(() => {\n    throw new Error('unhandled exception')\n  })\n\n  await promise\n\n  expect(fn).toHaveBeenCalledTimes(1)\n})\n"
  },
  {
    "path": "test/core/test/happy-dom-custom.test.ts",
    "content": "/**\n * @vitest-environment happy-dom\n * @vitest-environment-options { \"url\": \"http://my-website:5435\", \"settings\": { \"disableCSSFileLoading\": true } }\n */\n\n/* eslint-disable vars-on-top */\n\nimport { expect, it } from 'vitest'\n\ndeclare global {\n\n  var happyDOM: any\n}\n\nit('custom URL is changed to my-website:5435', () => {\n  expect(location.href).toBe('http://my-website:5435/')\n})\n\nit('accepts custom environment options', () => {\n  // default is false\n  expect(window.happyDOM?.settings.disableCSSFileLoading).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/happy-dom.test.ts",
    "content": "/**\n * @vitest-environment happy-dom\n */\n\n/* eslint-disable vars-on-top */\n\nimport { expect, it, vi } from 'vitest'\n\ndeclare global {\n\n  var __property_dom: unknown\n\n  var happyDOM: any\n}\n\nit('defaults URL to localhost:3000', () => {\n  expect(location.href).toBe('http://localhost:3000/')\n})\n\nit('disableCSSFileLoading is false by default because we didn\\'t change options', () => {\n  expect(window.happyDOM?.settings.disableCSSFileLoading).toBe(false)\n})\n\nit('defined on self/window are defined on global', () => {\n  expect(self).toBeDefined()\n  expect(window).toBeDefined()\n  expect(top).toBeDefined()\n  expect(parent).toBeDefined()\n\n  expect(self.__property_dom).not.toBeDefined()\n  expect(window.__property_dom).not.toBeDefined()\n  expect(globalThis.__property_dom).not.toBeDefined()\n\n  globalThis.__property_dom = 'defined_value'\n\n  expect(__property_dom).toBe('defined_value')\n  expect(self.__property_dom).toBe('defined_value')\n  expect(window.__property_dom).toBe('defined_value')\n  expect(globalThis.__property_dom).toBe('defined_value')\n\n  self.__property_dom = 'test_value'\n\n  expect(__property_dom).toBe('test_value')\n  expect(self.__property_dom).toBe('test_value')\n  expect(window.__property_dom).toBe('test_value')\n  expect(globalThis.__property_dom).toBe('test_value')\n\n  window.__property_dom = 'new_value'\n\n  expect(__property_dom).toBe('new_value')\n  expect(self.__property_dom).toBe('new_value')\n  expect(window.__property_dom).toBe('new_value')\n  expect(globalThis.__property_dom).toBe('new_value')\n\n  globalThis.__property_dom = 'global_value'\n\n  expect(__property_dom).toBe('global_value')\n  expect(self.__property_dom).toBe('global_value')\n  expect(window.__property_dom).toBe('global_value')\n  expect(globalThis.__property_dom).toBe('global_value')\n\n  const obj = {}\n\n  self.__property_dom = obj\n\n  expect(self.__property_dom).toBe(obj)\n  expect(window.__property_dom).toBe(obj)\n  expect(globalThis.__property_dom).toBe(obj)\n})\n\nit('usage with defineProperty', () => {\n  Object.defineProperty(self, '__property_dom', {\n    get: () => 'self_property',\n    configurable: true,\n  })\n\n  expect(__property_dom).toBe('self_property')\n  expect(self.__property_dom).toBe('self_property')\n  expect(globalThis.__property_dom).toBe('self_property')\n  expect(window.__property_dom).toBe('self_property')\n\n  Object.defineProperty(window, '__property_dom', {\n    get: () => 'window_property',\n    configurable: true,\n  })\n\n  expect(__property_dom).toBe('window_property')\n  expect(self.__property_dom).toBe('window_property')\n  expect(globalThis.__property_dom).toBe('window_property')\n  expect(window.__property_dom).toBe('window_property')\n\n  Object.defineProperty(globalThis, '__property_dom', {\n    get: () => 'global_property',\n    configurable: true,\n  })\n\n  expect(__property_dom).toBe('global_property')\n  expect(self.__property_dom).toBe('global_property')\n  expect(globalThis.__property_dom).toBe('global_property')\n  expect(window.__property_dom).toBe('global_property')\n})\n\nit('can call global functions without window works as expected', async () => {\n  const noop = vi.fn()\n\n  expect(() => addEventListener('abort', noop)).not.toThrow()\n  expect(() => scrollTo()).not.toThrow()\n  expect(() => requestAnimationFrame(noop)).not.toThrow()\n  expect(() => window.requestAnimationFrame(noop)).not.toThrow()\n  expect(() => self.requestAnimationFrame(noop)).not.toThrow()\n  expect(() => globalThis.requestAnimationFrame(noop)).not.toThrow()\n})\n\nit('globals are the same', () => {\n  expect(window).toBe(globalThis)\n  expect(window).toBe(global)\n  expect(window.globalThis).toBe(globalThis)\n  expect(window.Blob).toBe(globalThis.Blob)\n  expect(window.globalThis.Blob).toBe(globalThis.Blob)\n  expect(Blob).toBe(globalThis.Blob)\n})\n\nit('fetch globals work', () => {\n  const file = new File([window.Buffer.from('<foo />')], 'a.xml')\n  expect(() => URL.createObjectURL(file)).not.toThrow()\n\n  expect(new File([], 'test.txt')).toBeInstanceOf(Blob)\n\n  const response = new Response('', {\n    headers: new Headers({\n      'Content-Type': 'application/json',\n    }),\n  })\n  expect(response.headers.get('content-type')).toBe('application/json')\n})\n\nit.skipIf(import.meta.env.VITEST_VM_POOL)('default view references global object', () => {\n  expect(document.defaultView).toBe(window)\n  expect(document.defaultView).toBe(globalThis)\n  const el = document.createElement('div')\n  expect(el.ownerDocument.defaultView).toBe(globalThis)\n})\n"
  },
  {
    "path": "test/core/test/hoist-import.test.ts",
    "content": "import { assert, expect, test, vi } from 'vitest'\n\n// @ts-expect-error timeout doesn't have fn, mock factory adds it\nimport { fn, timeout } from '../src/timeout'\n\nvi.mock('../src/timeout.ts', () => {\n  assert.isEmpty([])\n\n  return {\n    timeout: 10_000,\n    fn: vi.fn(),\n  }\n})\n\ntest('\"vi\" can be used inside factory with empty lines', () => {\n  // @ts-expect-error no types\n  expect(globalThis.vi).toBeUndefined()\n  expect(timeout).toBe(10_000)\n  expect(vi.isMockFunction(fn)).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/hoisted-async-simple.test.ts",
    "content": "// this test checks only vi.hoisted because vi.mock affects the regexp to find this\n\nimport { afterAll, expect, it, vi } from 'vitest'\nimport { value } from '../src/rely-on-hoisted'\n\nconst globalValue = await vi.hoisted(async () => {\n  // @ts-expect-error not typed global\n  globalThis.someGlobalValue = 'globalValue'\n  // @ts-expect-error not typed global\n  ;(globalThis._order ??= []).push(1)\n  return 'globalValue'\n})\n\nafterAll(() => {\n  // @ts-expect-error not typed global\n  delete globalThis.someGlobalValue\n})\n\n// _order is set in the hoisted function before tests are collected\n// @ts-expect-error not typed global\nexpect(globalThis._order).toEqual([1, 2, 3])\n\nit('imported value is equal to returned from hoisted', () => {\n  expect(value).toBe(globalValue)\n})\n\nit('hoists async \"vi.hoisted\", but leaves the wrapper alone', async () => {\n  expect.assertions(1)\n  await (async () => {\n    expect(1).toBe(1)\n    vi.hoisted(() => {\n      // @ts-expect-error not typed global\n      ;(globalThis._order ??= []).push(2)\n    })\n  })()\n})\n\nawait vi.hoisted(async () => {\n  // @ts-expect-error not typed global\n  ;(globalThis._order ??= []).push(3)\n})\n"
  },
  {
    "path": "test/core/test/hoisted-simple.test.ts",
    "content": "// this test checks only vi.hoisted because vi.mock affects the regexp to find this\n\nimport { afterAll, expect, it, vi } from 'vitest'\nimport { value } from '../src/rely-on-hoisted'\n\nconst globalValue = vi.hoisted(() => {\n  // @ts-expect-error not typed global\n  globalThis.someGlobalValue = 'globalValue'\n  return 'globalValue'\n})\n\nafterAll(() => {\n  // @ts-expect-error not typed global\n  delete globalThis.someGlobalValue\n})\n\nit('imported value is equal to returned from hoisted', () => {\n  expect(value).toBe(globalValue)\n})\n"
  },
  {
    "path": "test/core/test/hooks-list.test.ts",
    "content": "import * as vitest from 'vitest'\nimport { describe, expect, test, vi } from 'vitest'\n\nvi.setConfig({\n  sequence: {\n    hooks: 'list',\n  },\n})\n\nconst hookOrder: number[] = []\nfunction callHook(hook: 'beforeAll' | 'beforeEach' | 'afterAll' | 'afterEach', order: number) {\n  vitest[hook](() => {\n    hookOrder.push(order)\n  })\n}\n\ndescribe('hooks are called as list', () => {\n  callHook('beforeAll', 1)\n  callHook('beforeAll', 2)\n  callHook('beforeAll', 3)\n\n  callHook('afterAll', 4)\n  // will wait for it\n  vitest.afterAll(async () => {\n    await Promise.resolve()\n    hookOrder.push(5)\n  })\n  callHook('afterAll', 6)\n\n  callHook('beforeEach', 7)\n  callHook('beforeEach', 8)\n  callHook('beforeEach', 9)\n\n  callHook('afterEach', 10)\n  callHook('afterEach', 11)\n  callHook('afterEach', 12)\n\n  test('before hooks pushed in order', () => {\n    expect(hookOrder).toEqual([1, 2, 3, 7, 8, 9])\n  })\n})\n\ndescribe('previous suite run all hooks', () => {\n  test('after all hooks run in defined order', () => {\n    expect(hookOrder).toEqual([1, 2, 3, 7, 8, 9, 10, 11, 12, 4, 5, 6])\n  })\n})\n"
  },
  {
    "path": "test/core/test/hooks-parallel.test.ts",
    "content": "import * as vitest from 'vitest'\nimport { describe, expect, test, vi } from 'vitest'\n\nvi.setConfig({\n  sequence: {\n    hooks: 'parallel',\n  },\n})\n\nconst hookOrder: number[] = []\nfunction callHook(hook: 'beforeAll' | 'beforeEach' | 'afterAll' | 'afterEach', order: number) {\n  vitest[hook](() => {\n    hookOrder.push(order)\n  })\n}\n\ndescribe('hooks are called in parallel', () => {\n  callHook('beforeAll', 1)\n  callHook('beforeAll', 2)\n  callHook('beforeAll', 3)\n\n  callHook('afterAll', 4)\n  // will always be last\n  vitest.afterAll(async () => {\n    await Promise.resolve()\n    hookOrder.push(5)\n  })\n  callHook('afterAll', 6)\n\n  callHook('beforeEach', 7)\n  callHook('beforeEach', 8)\n  callHook('beforeEach', 9)\n\n  callHook('afterEach', 10)\n  callHook('afterEach', 11)\n  callHook('afterEach', 12)\n\n  test('before hooks pushed in order', () => {\n    expect(hookOrder).toEqual([1, 2, 3, 7, 8, 9])\n  })\n})\n\ndescribe('previous suite run all hooks', () => {\n  test('after all hooks run in defined order', () => {\n    expect(hookOrder).toEqual([1, 2, 3, 7, 8, 9, 10, 11, 12, 4, 6, 5])\n  })\n})\n"
  },
  {
    "path": "test/core/test/hooks-stack.test.ts",
    "content": "import * as vitest from 'vitest'\nimport { describe, expect, test, vi } from 'vitest'\n\nvi.setConfig({\n  sequence: {\n    hooks: 'stack',\n  },\n})\n\nconst hookOrder: number[] = []\nfunction callHook(hook: 'beforeAll' | 'beforeEach' | 'afterAll' | 'afterEach', order: number) {\n  vitest[hook](() => {\n    hookOrder.push(order)\n  })\n}\n\ndescribe('hooks are called sequentially', () => {\n  callHook('beforeAll', 1)\n  callHook('afterAll', 4)\n\n  callHook('beforeAll', 2)\n  // will wait for it\n  vitest.afterAll(async () => {\n    await Promise.resolve()\n    hookOrder.push(5)\n  })\n\n  callHook('beforeEach', 7)\n  callHook('afterEach', 10)\n\n  callHook('beforeEach', 8)\n  callHook('afterEach', 11)\n\n  test('before hooks pushed in order', () => {\n    expect(hookOrder).toEqual([1, 2, 7, 8])\n  })\n})\n\ndescribe('previous suite run all hooks', () => {\n  test('after all hooks run in reverse order', () => {\n    expect(hookOrder).toEqual([1, 2, 7, 8, 11, 10, 5, 4])\n  })\n})\n"
  },
  {
    "path": "test/core/test/hooks.test.js",
    "content": "import { afterAll, afterEach, assert, beforeAll, beforeEach, describe, it } from 'vitest'\n\ndescribe('before and after hooks', () => {\n  let eachState = 'start'\n  let eachCount = 0\n  let allState = 'start'\n  let allCount = 0\n\n  beforeAll(() => {\n    allState = 'running'\n  })\n  afterAll(() => {\n    allState = 'done'\n    allCount++\n  })\n\n  beforeEach(() => {\n    eachState = 'running'\n  })\n  afterEach(() => {\n    eachState = 'done'\n    eachCount++\n  })\n\n  // Hooks accepting a timeout\n  beforeAll(async () => { }, 1000)\n  afterAll(async () => { }, 1000)\n  beforeEach(async () => { }, 1000)\n  afterEach(async () => { }, 1000)\n\n  beforeAll(async () => {\n    return new Promise((resolve) => {\n      setTimeout(() => {\n        resolve()\n      }, 100)\n    })\n  }, 1000)\n\n  it('beforeEach works', () => {\n    assert.equal(eachState, 'running')\n  })\n\n  // It should work if tests are run in serial, skip for now\n  it.skip('afterEach called', () => {\n    assert.equal(eachState, 'running')\n    assert.equal(eachCount, 1)\n  })\n\n  it('beforeAll works', () => {\n    assert.equal(allState, 'running')\n  })\n\n  it('afterAll not called', () => {\n    assert.equal(allState, 'running')\n    assert.equal(allCount, 0)\n  })\n})\n"
  },
  {
    "path": "test/core/test/hooks.test.ts",
    "content": "import { afterAll, afterEach, beforeAll, beforeEach, expect, it, onTestFinished, suite } from 'vitest'\n\nlet count = -1\n\nbeforeAll(() => {\n  count += 1\n})\n\nbeforeEach(() => {\n  count += 1\n})\n\nit('one', () => {\n  expect(count).toBe(1)\n})\n\nsuite('level1', () => {\n  it('two', () => {\n    expect(count).toBe(2)\n  })\n\n  it('three', () => {\n    expect(count).toBe(3)\n  })\n\n  suite('level 2', () => {\n    beforeEach(() => {\n      count += 1\n    })\n\n    it('five', () => {\n      expect(count).toBe(5)\n    })\n\n    suite('level 3', () => {\n      it('seven', () => {\n        expect(count).toBe(7)\n      })\n    })\n  })\n\n  suite('level 2 with nested beforeAll', () => {\n    beforeAll(() => {\n      count = 0\n    })\n\n    it('one', () => {\n      expect(count).toBe(1)\n    })\n  })\n\n  it('two', () => {\n    expect(count).toBe(2)\n  })\n})\n\nsuite('hooks cleanup', () => {\n  let cleanUpCount = 0\n  suite('run', () => {\n    beforeAll(() => {\n      cleanUpCount += 10\n      return () => {\n        cleanUpCount -= 10\n      }\n    })\n    beforeEach(() => {\n      cleanUpCount += 1\n      return () => {\n        cleanUpCount -= 1\n      }\n    })\n\n    it('one', () => {\n      expect(cleanUpCount).toBe(11)\n    })\n    it('two', () => {\n      expect(cleanUpCount).toBe(11)\n    })\n  })\n  it('end', () => {\n    expect(cleanUpCount).toBe(0)\n  })\n\n  suite('do nothing when given a non-function value as cleanupCallback', () => {\n    beforeAll(() => {\n      return 1\n    })\n    beforeEach(() => {\n      return null\n    })\n    afterAll(() => {\n      return '1'\n    })\n    afterEach(() => {\n      return {}\n    })\n\n    it('one', () => {\n      expect(cleanUpCount).toBe(0)\n    })\n  })\n  it('end', () => {\n    expect(cleanUpCount).toBe(0)\n  })\n})\n\nsuite('hooks cleanup order', () => {\n  const order: string[] = []\n\n  beforeEach(() => {\n    order.push('[a] beforeEach')\n    return () => {\n      order.push('[a] cleanup')\n    }\n  })\n\n  beforeEach(() => {\n    order.push('[b] beforeEach')\n    return () => {\n      order.push('[b] cleanup')\n    }\n  })\n\n  it('one', () => {\n    expect(order).toEqual([\n      '[a] beforeEach',\n      '[b] beforeEach',\n    ])\n  })\n\n  afterAll(() => {\n    expect(order).toEqual([\n      '[a] beforeEach',\n      '[b] beforeEach',\n      '[b] cleanup',\n      '[a] cleanup',\n    ])\n  })\n})\n\nsuite('hooks are called for dynamically skipped tests', () => {\n  const order: string[] = []\n\n  suite('tests', () => {\n    beforeEach(() => {\n      order.push('beforeEach')\n      return () => {\n        order.push('beforeEach cleanup')\n      }\n    })\n    afterEach(() => {\n      order.push('afterEach')\n    })\n\n    beforeAll(() => {\n      order.push('beforeAll')\n      return () => {\n        order.push('beforeAll cleanup')\n      }\n    })\n\n    afterAll(() => {\n      order.push('afterAll')\n    })\n\n    it('skipped', (ctx) => {\n      onTestFinished(() => {\n        order.push('onTestFinished')\n      })\n      ctx.skip()\n    })\n  })\n\n  it('order is correct', () => {\n    expect(order).toEqual([\n      'beforeAll',\n      'beforeEach',\n      'afterEach',\n      'beforeEach cleanup',\n      'onTestFinished',\n      'afterAll',\n      'beforeAll cleanup',\n    ])\n  })\n})\n"
  },
  {
    "path": "test/core/test/immutable.test.ts",
    "content": "import im from 'immutable'\nimport { expect, test } from 'vitest'\n\ntest('basic', () => {\n  expect(im.List([{ x: 1 }])).toEqual(im.List([{ x: 1 }]))\n  expect(im.List([{ x: 1 }])).toEqual(im.List([1]).map(i => ({ x: i })))\n  expect(im.List([{ x: 1 }])).not.toEqual(im.List([{ x: 2 }]))\n  expect(im.List([{ x: 1 }])).not.toEqual(im.List([]))\n})\n"
  },
  {
    "path": "test/core/test/import-client.test.ts",
    "content": "import { expect, test } from 'vitest'\n// @ts-expect-error not typed import\nimport * as client from '/@vite/client'\n\ntest('client is imported', () => {\n  expect(client).toHaveProperty('createHotContext')\n})\n"
  },
  {
    "path": "test/core/test/import-meta-resolve.test.ts",
    "content": "import { createRequire } from 'node:module'\nimport { pathToFileURL } from 'node:url'\nimport * as vite from 'vite'\nimport { expect, test } from 'vitest'\n\nconst require = createRequire(import.meta.url)\n\n// requires Vite 7.1\nconst [major, minor] = vite.version.split('.').map(Number)\nconst supported = (major > 7 || (major === 7 && minor >= 1))\n\ntest('import.meta.resolve relative', () => {\n  try {\n    expect(import.meta.resolve('./import-meta-resolve.test.ts')).toBe(import.meta.url)\n    expect(supported).toBe(true)\n  }\n  catch (e: any) {\n    expect(e.message).toContain(`\"import.meta.resolve\" is not supported`)\n    expect(supported).toBe(false)\n  }\n})\n\ntest('import.meta.resolve package', () => {\n  try {\n    const expected = pathToFileURL(require.resolve('react')).href\n    expect(import.meta.resolve('react')).toBe(expected)\n    expect(supported).toBe(true)\n  }\n  catch (e: any) {\n    expect(e.message).toContain(`\"import.meta.resolve\" is not supported`)\n    expect(supported).toBe(false)\n  }\n})\n"
  },
  {
    "path": "test/core/test/imports.test.ts",
    "content": "import { mkdir, writeFile } from 'node:fs/promises'\nimport { fileURLToPath } from 'node:url'\nimport { NonExported } from '@test/dep-esm-non-existing'\nimport { resolve } from 'pathe'\nimport { describe, expect, test, vi } from 'vitest'\n// @ts-expect-error module is not typed\nimport promiseExport from '../src/cjs/promise-export'\n\nimport { dynamicRelativeImport } from '../src/relative-import'\n\ntest('can import type from an ESM dependency', () => {\n  // @ts-expect-error NonExported is type\n  expect(NonExported).toBe(undefined)\n})\n\ntest('promise export works correctly', async () => {\n  await expect(promiseExport).resolves.toEqual({ value: 42 })\n})\n\ntest('dynamic relative import works', async () => {\n  const stringTimeoutMod = await import('./../src/timeout')\n\n  const timeoutPath = './../src/timeout'\n  const variableTimeoutMod = await import(timeoutPath)\n\n  expect(stringTimeoutMod).toBe(variableTimeoutMod)\n})\n\ntest('Relative imports in imported modules work', async () => {\n  const relativeImportFromFile = await dynamicRelativeImport('timeout')\n  const directImport = await import('./../src/timeout')\n\n  expect(relativeImportFromFile).toBe(directImport)\n})\n\ntest('dynamic aliased import works', async () => {\n  const stringTimeoutMod = await import('./../src/timeout')\n\n  const timeoutPath = '#/timeout'\n  const variableTimeoutMod = await import(timeoutPath)\n\n  expect(stringTimeoutMod).toBe(variableTimeoutMod)\n})\n\ntest('dynamic absolute from root import works', async () => {\n  const stringTimeoutMod = await import('./../src/timeout')\n\n  const timeoutPath = '/src/timeout'\n  const variableTimeoutMod = await import(timeoutPath)\n\n  expect(stringTimeoutMod).toBe(variableTimeoutMod)\n})\n\ntest('dynamic absolute with extension import works', async () => {\n  const stringTimeoutMod = await import('./../src/timeout')\n\n  const timeoutPath = '/src/timeout.ts'\n  const variableTimeoutMod = await import(timeoutPath)\n\n  expect(stringTimeoutMod).toBe(variableTimeoutMod)\n})\n\ntest('data with dynamic import works', async () => {\n  const dataUri = 'data:text/javascript;charset=utf-8,export default \"hi\"'\n  const { default: hi } = await import(dataUri)\n  expect(hi).toBe('hi')\n})\n\ntest('dynamic import coerces to string', async () => {\n  const dataUri = 'data:text/javascript;charset=utf-8,export default \"hi\"'\n  const { default: hi } = await import({ toString: () => dataUri } as string)\n  expect(hi).toBe('hi')\n})\n\ntest('dynamic import has Module symbol', async () => {\n  const stringTimeoutMod = await import('./../src/timeout')\n\n  // @ts-expect-error The symbol won't exist on the import type\n  expect(stringTimeoutMod[Symbol.toStringTag]).toBe('Module')\n})\n\ntest('dynamic import has null prototype', async () => {\n  const stringTimeoutMod = await import('./../src/timeout')\n\n  expect(Object.getPrototypeOf(stringTimeoutMod)).toBe(null)\n})\n\ntest('dynamic import throws an error', async () => {\n  const path = './some-unknown-path'\n  const imported = import(path)\n  await expect(imported).rejects.toThrow(`Cannot find module '/test/some-unknown-path' imported from ${resolve(import.meta.filename)}`)\n  // @ts-expect-error path does not exist\n  await expect(() => import('./some-unknown-path')).rejects.toThrow(`Cannot find module '/test/some-unknown-path' imported from ${resolve(import.meta.filename)}`)\n})\n\ntest('can import @vite/client', async () => {\n  const name = '@vite/client'\n  await expect(import(name)).resolves.not.toThrow()\n  await expect(import(/* @vite-ignore */ `/${name}`)).resolves.not.toThrow()\n})\n\ndescribe('importing special files from node_modules', async () => {\n  const dir = resolve(import.meta.dirname, '../src/node_modules')\n  const wasm = resolve(dir, 'file.wasm')\n  const css = resolve(dir, 'file.css')\n  const mp3 = resolve(dir, 'file.mp3')\n  await mkdir(dir, { recursive: true })\n  await Promise.all([\n    writeFile(wasm, '(module)'),\n    writeFile(css, '.foo { color: red; }'),\n    writeFile(mp3, ''),\n  ])\n  const importModule = (path: string) => import(path)\n\n  test('importing wasm with ?url query', async () => {\n    const mod = await importModule('../src/node_modules/file.wasm?url')\n    expect(mod.default).toBe('/src/node_modules/file.wasm')\n  })\n\n  test('importing wasm with ?raw query', async () => {\n    const mod = await importModule('../src/node_modules/file.wasm?raw')\n    expect(mod.default).toBe('(module)')\n  })\n\n  test('importing wasm with ?init query', async () => {\n    const mod = await importModule('../src/node_modules/file.wasm?init')\n    expect(mod.default).toBeTypeOf('function')\n  })\n\n  test('importing css with ?inline query', async () => {\n    const mod = await importModule('../src/node_modules/file.css?inline')\n    expect(mod.default).toBeTypeOf('string')\n  })\n\n  test('importing asset returns a string', async () => {\n    const mod = await importModule('../src/node_modules/file.mp3')\n    expect(mod.default).toBe('/src/node_modules/file.mp3')\n  })\n})\n\ndescribe.runIf(process.platform === 'win32')('importing files with different drive casing', async () => {\n  test('importing a local file with different drive casing works', async () => {\n    const path = new URL('./../src/timeout', import.meta.url)\n    const filepath = fileURLToPath(path)\n    const drive = filepath[0].toLowerCase()\n    const upperDrive = drive.toUpperCase()\n    const lowercasePath = filepath.replace(`${upperDrive}:`, `${drive}:`)\n    const uppercasePath = filepath.replace(`${drive}:`, `${upperDrive}:`)\n    expect(lowercasePath).not.toBe(uppercasePath)\n    const mod1 = await import(lowercasePath)\n    const mod2 = await import(uppercasePath)\n    const mod3 = await import('./../src/timeout')\n    expect(mod1).toBe(mod2)\n    expect(mod1).toBe(mod3)\n  })\n\n  test('importing an external file with different drive casing works', async () => {\n    const path = new URL('./../src/esm/esm.js', import.meta.url)\n    const filepath = fileURLToPath(path)\n    const drive = filepath[0].toLowerCase()\n    const upperDrive = drive.toUpperCase()\n    const lowercasePath = filepath.replace(`${upperDrive}:`, `${drive}:`)\n    const uppercasePath = filepath.replace(`${drive}:`, `${upperDrive}:`)\n    expect(lowercasePath).not.toBe(uppercasePath)\n    const mod1 = await import(lowercasePath)\n    vi.resetModules() // since they reference the same global ESM cache, it should not matter\n    const mod2 = await import(uppercasePath)\n    expect(mod1).toBe(mod2)\n  })\n})\n"
  },
  {
    "path": "test/core/test/injector-esm.test.ts",
    "content": "import { parseAst } from 'vite'\nimport { expect, test } from 'vitest'\nimport { injectDynamicImport } from '../../../packages/mocker/src/node/dynamicImportPlugin'\n\nfunction parse(code: string, options: any): any {\n  return parseAst(code, options)\n}\n\nfunction injectSimpleCode(code: string) {\n  return injectDynamicImport(code, '/test.js', parse)?.code\n}\n\ntest('dynamic import', async () => {\n  const result = injectSimpleCode(\n    'export const i = () => import(\\'./foo\\')',\n  )\n  expect(result).toMatchInlineSnapshot(`\"export const i = () => globalThis[\"__vitest_mocker__\"].wrapDynamicImport(() => import('./foo'))\"`)\n})\n"
  },
  {
    "path": "test/core/test/injector-mock.test.ts",
    "content": "import type { HoistMocksPluginOptions } from '../../../packages/mocker/src/node/hoistMocksPlugin'\nimport { stripVTControlCharacters } from 'node:util'\nimport { parseAst } from 'vite'\nimport { describe, expect, it, test, vi } from 'vitest'\nimport { hoistMockAndResolve } from '../../../packages/mocker/src/node/hoistMocksPlugin'\nimport { generateCodeFrame } from '../../../packages/vitest/src/node/printError.js'\n\nfunction parse(code: string, options: any): any {\n  return parseAst(code, options)\n}\n\nconst hoistMocksOptions: HoistMocksPluginOptions = {\n  codeFrameGenerator(node: any, id: string, code: string) {\n    return generateCodeFrame(\n      code,\n      4,\n      node.start + 1,\n    )\n  },\n}\n\nfunction hoistSimple(code: string, url = '') {\n  return hoistMockAndResolve(code, url, parse, hoistMocksOptions)\n}\n\nfunction hoistSimpleCode(code: string) {\n  return hoistMockAndResolve(code, '/test.js', parse, hoistMocksOptions)?.code.trim()\n}\n\ntest('hoists mock, unmock, hoisted', () => {\n  expect(hoistSimpleCode(`\n  vi.mock('path', () => {})\n  vi.unmock('path')\n  vi.hoisted(() => {})\n  `)).toMatchInlineSnapshot(`\n    \"import { vi } from \"vitest\"\n    vi.mock('path', () => {})\n    vi.unmock('path')\n    vi.hoisted(() => {})\"\n  `)\n})\n\ntest('always hoists import from vitest', () => {\n  expect(hoistSimpleCode(`\nimport { vi } from 'vitest'\nvi.mock('path', () => {})\nvi.unmock('path')\nvi.hoisted(() => {})\nimport { test } from 'vitest'\n  `)).toMatchInlineSnapshot(`\n    \"vi.mock('path', () => {})\n    vi.unmock('path')\n    vi.hoisted(() => {})\n\n    import { vi } from 'vitest'\n    import { test } from 'vitest'\"\n  `)\n})\n\ntest('always hoists all imports but they are under mocks', () => {\n  expect(hoistSimpleCode(`\n  import { vi } from 'vitest'\n  import { someValue } from './path.js'\n  import { someValue2 } from './path2.js'\n  vi.mock('path', () => {})\n  vi.unmock('path')\n  vi.hoisted(() => {})\n  import { test } from 'vitest'\n  `)).toMatchInlineSnapshot(`\n    \"vi.mock('path', () => {})\n    vi.unmock('path')\n    vi.hoisted(() => {})\n    const __vi_import_0__ = await import(\"./path.js\");\n    const __vi_import_1__ = await import(\"./path2.js\");\n\n      import { vi } from 'vitest'\n      \n      \n            import { test } from 'vitest'\"\n  `)\n})\n\ntest('correctly mocks namespaced', () => {\n  expect(hoistSimpleCode(`\n  import { vi } from 'vitest'\n  import add, * as AddModule from '../src/add'\n  vi.mock('../src/add', () => {})\n  `)).toMatchInlineSnapshot(`\n    \"vi.mock('../src/add', () => {})\n    const __vi_import_0__ = await import(\"../src/add\");\n\n      import { vi } from 'vitest'\"\n  `)\n})\n\ntest('correctly access import', () => {\n  expect(hoistSimpleCode(`\n  import { vi } from 'vitest'\n  import add from '../src/add'\n  add();\n  vi.mock('../src/add', () => {})\n  `)).toMatchInlineSnapshot(`\n    \"vi.mock('../src/add', () => {})\n    const __vi_import_0__ = await import(\"../src/add\");\n\n      import { vi } from 'vitest'\n      \n      __vi_import_0__.default();\"\n  `)\n})\n\ndescribe('transform', () => {\n  const hoistSimpleCodeWithoutMocks = (code: string) => {\n    return hoistMockAndResolve(`import {vi} from \"vitest\";\\n${code}\\nvi.mock('faker');\\n`, '/test.js', parse, hoistMocksOptions)?.code.trim()\n  }\n  test('default import', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`import foo from 'vue';console.log(foo.bar)`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      console.log(__vi_import_0__.default.bar)\"\n    `)\n  })\n\n  test('can use imported variables inside the mock', () => {\n    expect(\n      hoistMockAndResolve(`\nimport { vi } from 'vitest'\nimport user from './user'\nimport { admin } from './admin'\nvi.mock('./mock.js', () => ({\n  getSession: vi.fn().mockImplementation(() => ({\n    user,\n    admin: admin,\n  }))\n}))\n`, './test.js', parse, hoistMocksOptions)?.code.trim(),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('./mock.js', () => ({\n        getSession: vi.fn().mockImplementation(() => ({\n          user: __vi_import_0__.default,\n          admin: __vi_import_1__.admin,\n        }))\n      }))\n      const __vi_import_0__ = await import(\"./user\");\n      const __vi_import_1__ = await import(\"./admin\");\n\n      import { vi } from 'vitest'\"\n    `)\n  })\n\n  test('can use hoisted variables inside the mock', () => {\n    expect(\n      hoistMockAndResolve(`\nimport { vi } from 'vitest'\nconst { user, admin } = await vi.hoisted(async () => {\n  const { default: user } = await import('./user')\n  const { admin } = await import('./admin')\n  return { user, admin }\n})\nvi.mock('./mock.js', () => {\n  getSession: vi.fn().mockImplementation(() => ({\n    user,\n    admin: admin,\n  }))\n})\n`, './test.js', parse, hoistMocksOptions)?.code.trim(),\n    ).toMatchInlineSnapshot(`\n      \"const { user, admin } = await vi.hoisted(async () => {\n        const { default: user } = await import('./user')\n        const { admin } = await import('./admin')\n        return { user, admin }\n      })\n      vi.mock('./mock.js', () => {\n        getSession: vi.fn().mockImplementation(() => ({\n          user,\n          admin: admin,\n        }))\n      })\n\n      import { vi } from 'vitest'\"\n    `)\n  })\n\n  test('named import', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `import { ref } from 'vue';function foo() { return ref(0) }`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      function foo() { return __vi_import_0__.ref(0) }\"\n    `)\n  })\n\n  test('namespace import', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `import * as vue from 'vue';function foo() { return vue.ref(0) }`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      function foo() { return __vi_import_0__.ref(0) }\"\n    `)\n  })\n\n  test('export function declaration', () => {\n    expect(hoistSimpleCodeWithoutMocks(`export function foo() {}`))\n      .toMatchInlineSnapshot(`\n        \"vi.mock('faker');\n        import {vi} from \"vitest\";\n        export function foo() {}\"\n      `)\n  })\n\n  test('export class declaration', () => {\n    expect(hoistSimpleCodeWithoutMocks(`export class foo {}`))\n      .toMatchInlineSnapshot(`\n        \"vi.mock('faker');\n        import {vi} from \"vitest\";\n        export class foo {}\"\n      `)\n  })\n\n  test('export var declaration', () => {\n    expect(hoistSimpleCodeWithoutMocks(`export const a = 1, b = 2`))\n      .toMatchInlineSnapshot(`\n        \"vi.mock('faker');\n        import {vi} from \"vitest\";\n        export const a = 1, b = 2\"\n      `)\n  })\n\n  test('export named', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`const a = 1, b = 2; export { a, b as c }`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      const a = 1, b = 2; export { a, b as c }\"\n    `)\n  })\n\n  test('export named from', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`export { ref, computed as c } from 'vue'`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      export { ref, computed as c } from 'vue'\"\n    `)\n  })\n\n  test('named exports of imported binding', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `import {createApp} from 'vue';export {createApp}`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      export {createApp}\"\n    `)\n  })\n\n  test('export * from', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `export * from 'vue'\\n` + `export * from 'react'`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      export * from 'vue'\n      export * from 'react'\"\n    `)\n  })\n\n  test('export * as from', () => {\n    expect(hoistSimpleCodeWithoutMocks(`export * as foo from 'vue'`))\n      .toMatchInlineSnapshot(`\n        \"vi.mock('faker');\n        import {vi} from \"vitest\";\n        export * as foo from 'vue'\"\n      `)\n  })\n\n  test('export default', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`export default {}`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      export default {}\"\n    `)\n  })\n\n  test('export then import minified', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `export * from 'vue';import {createApp} from 'vue';`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      export * from 'vue';\"\n    `)\n  })\n\n  test('hoist import to top', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `path.resolve('server.js');import path from 'node:path';`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"node:path\");\n      import {vi} from \"vitest\";\n      __vi_import_0__.default.resolve('server.js');\"\n    `)\n  })\n\n  test('import.meta', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`console.log(import.meta.url)`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      console.log(import.meta.url)\"\n    `)\n  })\n\n  test('dynamic import', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `export const i = () => import('./foo')`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      export const i = () => import('./foo')\"\n    `)\n  })\n\n  test('do not rewrite method definition', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `import { fn } from 'vue';class A { fn() { fn() } }`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      class A { fn() { __vi_import_0__.fn() } }\"\n    `)\n  })\n\n  test('do not rewrite when variable is in scope', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `import { fn } from 'vue';function A(){ const fn = () => {}; return { fn }; }`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      function A(){ const fn = () => {}; return { fn }; }\"\n    `)\n  })\n\n  // #5472\n  test('do not rewrite when variable is in scope with object destructuring', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `import { fn } from 'vue';function A(){ let {fn, test} = {fn: 'foo', test: 'bar'}; return { fn }; }`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      function A(){ let {fn, test} = {fn: 'foo', test: 'bar'}; return { fn }; }\"\n    `)\n  })\n\n  // #5472\n  test('do not rewrite when variable is in scope with array destructuring', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `import { fn } from 'vue';function A(){ let [fn, test] = ['foo', 'bar']; return { fn }; }`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      function A(){ let [fn, test] = ['foo', 'bar']; return { fn }; }\"\n    `)\n  })\n\n  // #5727\n  test('rewrite variable in string interpolation in function nested arguments', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `import { fn } from 'vue';function A({foo = \\`test\\${fn}\\`} = {}){ return {}; }`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      function A({foo = \\`test\\${__vi_import_0__.fn}\\`} = {}){ return {}; }\"\n    `)\n  })\n\n  // #6520\n  test('rewrite variables in default value of destructuring params', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `import { fn } from 'vue';function A({foo = fn}){ return {}; }`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      function A({foo = __vi_import_0__.fn}){ return {}; }\"\n    `)\n  })\n\n  test('do not rewrite when function declaration is in scope', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `import { fn } from 'vue';function A(){ function fn() {}; return { fn }; }`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      function A(){ function fn() {}; return { fn }; }\"\n    `)\n  })\n\n  test('do not rewrite catch clause', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `import {error} from './dependency';try {} catch(error) {}`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"./dependency\");\n      import {vi} from \"vitest\";\n      try {} catch(error) {}\"\n    `)\n  })\n\n  // #2221\n  test('should declare variable for imported super class', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `import { Foo } from './dependency';` + `class A extends Foo {}`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"./dependency\");\n      import {vi} from \"vitest\";\n      const Foo = __vi_import_0__.Foo;\n      class A extends Foo {}\"\n    `)\n\n    // exported classes: should prepend the declaration at root level, before the\n    // first class that uses the binding\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `import { Foo } from './dependency';`\n        + `export default class A extends Foo {}\\n`\n        + `export class B extends Foo {}`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"./dependency\");\n      import {vi} from \"vitest\";\n      const Foo = __vi_import_0__.Foo;\n      export default class A extends Foo {}\n      export class B extends Foo {}\"\n    `)\n  })\n\n  // #4049\n  test('should handle default export variants', () => {\n  // default anonymous functions\n    expect(hoistSimpleCodeWithoutMocks(`export default function() {}\\n`))\n      .toMatchInlineSnapshot(`\n        \"vi.mock('faker');\n        import {vi} from \"vitest\";\n        export default function() {}\"\n      `)\n    // default anonymous class\n    expect(hoistSimpleCodeWithoutMocks(`export default class {}\\n`))\n      .toMatchInlineSnapshot(`\n        \"vi.mock('faker');\n        import {vi} from \"vitest\";\n        export default class {}\"\n      `)\n    // default named functions\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `export default function foo() {}\\n`\n        + `foo.prototype = Object.prototype;`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      export default function foo() {}\n      foo.prototype = Object.prototype;\"\n    `)\n    // default named classes\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `export default class A {}\\n` + `export class B extends A {}`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      export default class A {}\n      export class B extends A {}\"\n    `)\n  })\n\n  test('sourcemap source', () => {\n    const map = (\n      (hoistSimple(\n        `vi.mock(any);\n      export const a = 1`,\n        'input.js',\n      ))?.map\n    )\n    expect(map?.sources).toStrictEqual(['input.js'])\n  })\n\n  test('overwrite bindings', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `import { inject } from 'vue';`\n        + `const a = { inject }\\n`\n        + `const b = { test: inject }\\n`\n        + `function c() { const { test: inject } = { test: true }; console.log(inject) }\\n`\n        + `const d = inject\\n`\n        + `function f() {  console.log(inject) }\\n`\n        + `function e() { const { inject } = { inject: true } }\\n`\n        + `function g() { const f = () => { const inject = true }; console.log(inject) }\\n`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n      const a = { inject: __vi_import_0__.inject }\n      const b = { test: __vi_import_0__.inject }\n      function c() { const { test: inject } = { test: true }; console.log(inject) }\n      const d = __vi_import_0__.inject\n      function f() {  console.log(__vi_import_0__.inject) }\n      function e() { const { inject } = { inject: true } }\n      function g() { const f = () => { const inject = true }; console.log(__vi_import_0__.inject) }\"\n    `)\n  })\n\n  test('Empty array pattern', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`const [, LHS, RHS] = inMatch;`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      const [, LHS, RHS] = inMatch;\"\n    `)\n  })\n\n  test('function argument destructure', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `\nimport { foo, bar } from 'foo'\nconst a = ({ _ = foo() }) => {}\nfunction b({ _ = bar() }) {}\nfunction c({ _ = bar() + foo() }) {}\n`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"foo\");\n      import {vi} from \"vitest\";\n\n\n      const a = ({ _ = __vi_import_0__.foo() }) => {}\n      function b({ _ = __vi_import_0__.bar() }) {}\n      function c({ _ = __vi_import_0__.bar() + __vi_import_0__.foo() }) {}\"\n    `)\n  })\n\n  test('object destructure alias', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `\nimport { n } from 'foo'\nconst a = () => {\n  const { type: n = 'bar' } = {}\n  console.log(n)\n}\n`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"foo\");\n      import {vi} from \"vitest\";\n\n\n      const a = () => {\n        const { type: n = 'bar' } = {}\n        console.log(n)\n      }\"\n    `)\n\n    // #9585\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `\nimport { n, m } from 'foo'\nconst foo = {}\n\n{\n  const { [n]: m } = foo\n}\n`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"foo\");\n      import {vi} from \"vitest\";\n\n\n      const foo = {}\n\n      {\n        const { [__vi_import_0__.n]: m } = foo\n      }\"\n    `)\n  })\n\n  test('nested object destructure alias', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `\nimport { remove, add, get, set, rest, objRest } from 'vue'\n\nfunction a() {\n  const {\n    o: { remove },\n    a: { b: { c: [ add ] }},\n    d: [{ get }, set, ...rest],\n    ...objRest\n  } = foo\n\n  remove()\n  add()\n  get()\n  set()\n  rest()\n  objRest()\n}\n\nremove()\nadd()\nget()\nset()\nrest()\nobjRest()\n`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n\n\n\n      function a() {\n        const {\n          o: { remove },\n          a: { b: { c: [ add ] }},\n          d: [{ get }, set, ...rest],\n          ...objRest\n        } = foo\n\n        remove()\n        add()\n        get()\n        set()\n        rest()\n        objRest()\n      }\n\n      __vi_import_0__.remove()\n      __vi_import_0__.add()\n      __vi_import_0__.get()\n      __vi_import_0__.set()\n      __vi_import_0__.rest()\n      __vi_import_0__.objRest()\"\n    `)\n  })\n\n  test('object props and methods', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `\nimport foo from 'foo'\n\nconst bar = 'bar'\n\nconst obj = {\n  foo() {},\n  [foo]() {},\n  [bar]() {},\n  foo: () => {},\n  [foo]: () => {},\n  [bar]: () => {},\n  bar(foo) {}\n}\n`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"foo\");\n      import {vi} from \"vitest\";\n\n\n\n      const bar = 'bar'\n\n      const obj = {\n        foo() {},\n        [__vi_import_0__.default]() {},\n        [bar]() {},\n        foo: () => {},\n        [__vi_import_0__.default]: () => {},\n        [bar]: () => {},\n        bar(foo) {}\n      }\"\n    `)\n  })\n\n  test('class props', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `\nimport { remove, add } from 'vue'\n\nclass A {\n  remove = 1\n  add = null\n}\n`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n\n\n\n      const add = __vi_import_0__.add;\n      const remove = __vi_import_0__.remove;\n      class A {\n        remove = 1\n        add = null\n      }\"\n    `)\n  })\n\n  test('class methods', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `\nimport foo from 'foo'\n\nconst bar = 'bar'\n\nclass A {\n  foo() {}\n  [foo]() {}\n  [bar]() {}\n  #foo() {}\n  bar(foo) {}\n}\n`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"foo\");\n      import {vi} from \"vitest\";\n\n\n\n      const bar = 'bar'\n\n      class A {\n        foo() {}\n        [__vi_import_0__.default]() {}\n        [bar]() {}\n        #foo() {}\n        bar(foo) {}\n      }\"\n    `)\n  })\n\n  test('declare scope', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `\nimport { aaa, bbb, ccc, ddd } from 'vue'\n\nfunction foobar() {\n  ddd()\n\n  const aaa = () => {\n    bbb(ccc)\n    ddd()\n  }\n  const bbb = () => {\n    console.log('hi')\n  }\n  const ccc = 1\n  function ddd() {}\n\n  aaa()\n  bbb()\n  ccc()\n}\n\naaa()\nbbb()\n`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"vue\");\n      import {vi} from \"vitest\";\n\n\n\n      function foobar() {\n        ddd()\n\n        const aaa = () => {\n          bbb(ccc)\n          ddd()\n        }\n        const bbb = () => {\n          console.log('hi')\n        }\n        const ccc = 1\n        function ddd() {}\n\n        aaa()\n        bbb()\n        ccc()\n      }\n\n      __vi_import_0__.aaa()\n      __vi_import_0__.bbb()\"\n    `)\n  })\n\n  test('continuous exports', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(\n        `\nexport function fn1() {\n}export function fn2() {\n}\n        `,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n\n      export function fn1() {\n      }export function fn2() {\n      }\"\n    `)\n  })\n\n  // https://github.com/vitest-dev/vitest/issues/1141\n  test('export default expression', () => {\n  // esbuild transform result of following TS code\n  // export default <MyFn> function getRandom() {\n  //   return Math.random()\n  // }\n    const code = `\nexport default (function getRandom() {\n  return Math.random();\n});\n`.trim()\n\n    expect(hoistSimpleCodeWithoutMocks(code)).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      export default (function getRandom() {\n        return Math.random();\n      });\"\n    `)\n\n    expect(\n      hoistSimpleCodeWithoutMocks(`export default (class A {});`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      import {vi} from \"vitest\";\n      export default (class A {});\"\n    `)\n  })\n\n  // #8002\n  test('with hashbang', () => {\n    expect(\n      hoistSimpleCode(\n        `#!/usr/bin/env node\nvi.mock('foo');\nconsole.log(\"it can parse the hashbang\")`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"#!/usr/bin/env node\n      import { vi } from \"vitest\"\n      vi.mock('foo');\n      console.log(\"it can parse the hashbang\")\"\n    `)\n  })\n\n  test('import hoisted after hashbang', () => {\n    expect(\n      hoistSimpleCode(\n        `#!/usr/bin/env node\nvi.mock('foo');\nconsole.log(foo);\nimport foo from \"foo\"`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"#!/usr/bin/env node\n      import { vi } from \"vitest\"\n      vi.mock('foo');\n      const __vi_import_0__ = await import(\"foo\");\n      console.log(__vi_import_0__.default);\"\n    `)\n  })\n\n  test('import hoisted after hashbang', () => {\n    expect(\n      hoistSimpleCode(\n        `#!/usr/bin/env node\nimport { vi } from './proxy'\nvi.mock('foo');\nconsole.log(foo);\nimport foo from \"foo\"`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"#!/usr/bin/env node\n\n      if (typeof globalThis[\"vi\"] === \"undefined\") { throw new Error(\"There are some problems in resolving the mocks API.\\\\nYou may encounter this issue when importing the mocks API from another module other than 'vitest'.\\\\nTo fix this issue you can either:\\\\n- import the mocks API directly from 'vitest'\\\\n- enable the 'globals' option\") }\n      __vi_import_0__.vi.mock('foo');\n      const __vi_import_0__ = await import(\"./proxy\");\n      const __vi_import_1__ = await import(\"foo\");\n\n      console.log(__vi_import_1__.default);\"\n    `)\n  })\n\n  // #10289\n  test('track scope by class, function, condition blocks', () => {\n    const code = `\nimport { foo, bar } from 'foobar'\nif (false) {\n  const foo = 'foo'\n  console.log(foo)\n} else if (false) {\n  const [bar] = ['bar']\n  console.log(bar)\n} else {\n  console.log(foo)\n  console.log(bar)\n}\nexport class Test {\n  constructor() {\n    if (false) {\n      const foo = 'foo'\n      console.log(foo)\n    } else if (false) {\n      const [bar] = ['bar']\n      console.log(bar)\n    } else {\n      console.log(foo)\n      console.log(bar)\n    }\n  }\n};`.trim()\n\n    expect(hoistSimpleCodeWithoutMocks(code)).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"foobar\");\n      import {vi} from \"vitest\";\n\n      if (false) {\n        const foo = 'foo'\n        console.log(foo)\n      } else if (false) {\n        const [bar] = ['bar']\n        console.log(bar)\n      } else {\n        console.log(__vi_import_0__.foo)\n        console.log(__vi_import_0__.bar)\n      }\n      export class Test {\n        constructor() {\n          if (false) {\n            const foo = 'foo'\n            console.log(foo)\n          } else if (false) {\n            const [bar] = ['bar']\n            console.log(bar)\n          } else {\n            console.log(__vi_import_0__.foo)\n            console.log(__vi_import_0__.bar)\n          }\n        }\n      };\"\n    `)\n  })\n\n  // #10386\n  test('track var scope by function', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`\nimport { foo, bar } from 'foobar'\nfunction test() {\n  if (true) {\n    var foo = () => { var why = 'would' }, bar = 'someone'\n  }\n  return [foo, bar]\n}`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"foobar\");\n      import {vi} from \"vitest\";\n\n\n      function test() {\n        if (true) {\n          var foo = () => { var why = 'would' }, bar = 'someone'\n        }\n        return [foo, bar]\n      }\"\n    `)\n  })\n\n  // #11806\n  test('track scope by blocks', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`\nimport { foo, bar, baz } from 'foobar'\nfunction test() {\n  [foo];\n  {\n    let foo = 10;\n    let bar = 10;\n  }\n  try {} catch (baz){ baz };\n  return bar;\n}`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"foobar\");\n      import {vi} from \"vitest\";\n\n\n      function test() {\n        [__vi_import_0__.foo];\n        {\n          let foo = 10;\n          let bar = 10;\n        }\n        try {} catch (baz){ baz };\n        return __vi_import_0__.bar;\n      }\"\n    `)\n  })\n\n  test('track scope in for loops', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`\nimport { test } from './test.js'\n\nfor (const test of tests) {\n  console.log(test)\n}\n\nfor (let test = 0; test < 10; test++) {\n  console.log(test)\n}\n\nfor (const test in tests) {\n  console.log(test)\n}`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"./test.js\");\n      import {vi} from \"vitest\";\n\n\n\n      for (const test of tests) {\n        console.log(test)\n      }\n\n      for (let test = 0; test < 10; test++) {\n        console.log(test)\n      }\n\n      for (const test in tests) {\n        console.log(test)\n      }\"\n    `)\n  })\n\n  test('avoid binding ClassExpression', () => {\n    const result = hoistSimpleCodeWithoutMocks(\n      `\nimport Foo, { Bar } from './foo';\n\nconsole.log(Foo, Bar);\nconst obj = {\n  foo: class Foo {},\n  bar: class Bar {}\n}\nconst Baz = class extends Foo {}\n`,\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"./foo\");\n      import {vi} from \"vitest\";\n\n\n\n      console.log(__vi_import_0__.default, __vi_import_0__.Bar);\n      const obj = {\n        foo: class Foo {},\n        bar: class Bar {}\n      }\n      const Baz = class extends __vi_import_0__.default {}\"\n    `)\n  })\n\n  test('classDeclaration shadowing import', () => {\n    const input = `\\\nimport { Bar } from \"./repro.js\"\n{\n  class Bar {\n    test() {}\n  }\n  const Zoo = class Zoo extends Bar {}\n}\n`\n    expect(hoistSimpleCodeWithoutMocks(input)).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"./repro.js\");\n      import {vi} from \"vitest\";\n\n      {\n        class Bar {\n          test() {}\n        }\n        const Zoo = class Zoo extends Bar {}\n      }\"\n    `)\n  })\n\n  test('classExpression name shadowing import', () => {\n    const input = `\\\nimport { Foo } from \"./foo.js\"\nconst Bar = class Foo {\n  static create() {\n    return new Foo()\n  }\n}\n`\n    expect(hoistSimpleCodeWithoutMocks(input)).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"./foo.js\");\n      import {vi} from \"vitest\";\n\n      const Bar = class Foo {\n        static create() {\n          return new Foo()\n        }\n      }\"\n    `)\n  })\n\n  test('import assertion attribute', () => {\n    expect(\n      hoistSimpleCodeWithoutMocks(`\n  import * as foo from './foo.json' with { type: 'json' };\n  import('./bar.json', { with: { type: 'json' } });\n  `),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"./foo.json\");\n      import {vi} from \"vitest\";\n\n        \n        import('./bar.json', { with: { type: 'json' } });\"\n    `)\n  })\n\n  test('import and export ordering', () => {\n  // Given all imported modules logs `mod ${mod}` on execution,\n  // and `foo` is `bar`, the logging order should be:\n  // \"mod a\", \"mod foo\", \"mod b\", \"bar1\", \"bar2\"\n    expect(\n      hoistSimpleCodeWithoutMocks(`\nconsole.log(foo + 1)\nexport * from './a'\nimport { foo } from './foo'\nexport * from './b'\nconsole.log(foo + 2)\n  `),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('faker');\n      const __vi_import_0__ = await import(\"./foo\");\n      import {vi} from \"vitest\";\n\n      console.log(__vi_import_0__.foo + 1)\n      export * from './a'\n\n      export * from './b'\n      console.log(__vi_import_0__.foo + 2)\"\n    `)\n  })\n\n  test('handle single \"await vi.hoisted\"', () => {\n    expect(\n      hoistSimpleCode(`\nimport { vi } from 'vitest';\n1234;\nawait vi\n  .hoisted(() => {});\n    `),\n    ).toMatchInlineSnapshot(`\n      \"await vi\n        .hoisted(() => {});\n\n      import { vi } from 'vitest';\n      1234;\"\n    `)\n  })\n\n  test('handles dynamic import as the first argument', () => {\n    expect(\n      hoistSimpleCode(`\n    vi.mock(import('./path'))\n    vi.mock(import(somePath))\n    vi.mock(import(\\`./path\\`))\n\n    vi.mock(import('./path'));\n    vi.mock(import(somePath));\n    vi.mock(import(\\`./path\\`));\n\n    vi.mock(await import('./path'))\n    vi.mock(await import(somePath))\n    vi.mock(await import(\\`./path\\`))\n\n    vi.mock(await import('./path'));\n    vi.mock(await import(somePath));\n    vi.mock(await import(\\`./path\\`));\n\n    vi.mock(import('./path'), () => {})\n    vi.mock(import(somePath), () => {})\n    vi.mock(import(\\`./path\\`), () => {})\n\n    vi.mock(await import('./path'), () => {})\n    vi.mock(await import(somePath), () => {})\n    vi.mock(await import(\\`./path\\`), () => {})\n\n    vi.mock(import('./path'), () => {});\n    vi.mock(import(somePath), () => {});\n    vi.mock(import(\\`./path\\`), () => {});\n\n    vi.mock(await import('./path'), () => {});\n    vi.mock(await import(somePath), () => {});\n    vi.mock(await import(\\`./path\\`), () => {});\n    `),\n    ).toMatchInlineSnapshot(`\n      \"import { vi } from \"vitest\"\n      vi.mock('./path')\n      vi.mock(somePath)\n      vi.mock(\\`./path\\`)\n      vi.mock('./path');\n      vi.mock(somePath);\n      vi.mock(\\`./path\\`);\n      vi.mock('./path')\n      vi.mock(somePath)\n      vi.mock(\\`./path\\`)\n      vi.mock('./path');\n      vi.mock(somePath);\n      vi.mock(\\`./path\\`);\n      vi.mock('./path', () => {})\n      vi.mock(somePath, () => {})\n      vi.mock(\\`./path\\`, () => {})\n      vi.mock('./path', () => {})\n      vi.mock(somePath, () => {})\n      vi.mock(\\`./path\\`, () => {})\n      vi.mock('./path', () => {});\n      vi.mock(somePath, () => {});\n      vi.mock(\\`./path\\`, () => {});\n      vi.mock('./path', () => {});\n      vi.mock(somePath, () => {});\n      vi.mock(\\`./path\\`, () => {});\"\n    `)\n  })\n\n  test('handles import in vi.do* methods', () => {\n    expect(\n      hoistSimpleCode(`\nvi.doMock(import('./path'))\nvi.doMock(import(\\`./path\\`))\nvi.doMock(import('./path'));\n\nbeforeEach(() => {\n  vi.doUnmock(import('./path'))\n  vi.doMock(import('./path'))\n})\n\ntest('test', async () => {\n  vi.doMock(import(dynamicName))\n  await import(dynamicName)\n})\n      `),\n    ).toMatchInlineSnapshot(`\n      \"vi.doMock('./path')\n      vi.doMock(\\`./path\\`)\n      vi.doMock('./path');\n\n      beforeEach(() => {\n        vi.doUnmock('./path')\n        vi.doMock('./path')\n      })\n\n      test('test', async () => {\n        vi.doMock(dynamicName)\n        await import(dynamicName)\n      })\"\n    `)\n  })\n\n  test('vi.mock already hoisted at the top', () => {\n    expect(\n      hoistSimpleCode(`\\\nvi.mock('node:path', () => ({ mocked: true }));\n\nimport { test, vi } from 'vitest';\n\nimport * as path from 'node:path';\n\nconsole.log(path.mocked);\n`),\n    ).toMatchInlineSnapshot(`\n      \"vi.mock('node:path', () => ({ mocked: true }));\n      const __vi_import_0__ = await import(\"node:path\");\n\n      import { test, vi } from 'vitest';\n\n\n\n      console.log(__vi_import_0__.mocked);\"\n    `)\n  })\n\n  test('correctly hoists when import.meta is used', () => {\n    expect(hoistSimpleCode(`\nimport { calc } from './calc'\nfunction sum(a, b) {\n  return calc(\"+\", 1, 2);\n}\n\nif (import.meta.vitest) {\n  const { vi, test, expect } = import.meta.vitest\n  vi.mock('faker')\n  test('sum', () => {\n    expect(sum(1, 2)).toBe(3)\n  })\n}\n      `)).toMatchInlineSnapshot(`\n        \"import { vi } from \"vitest\"\n        vi.mock('faker')\n        const __vi_import_0__ = await import(\"./calc\");\n\n\n        function sum(a, b) {\n          return __vi_import_0__.calc(\"+\", 1, 2);\n        }\n\n        if (import.meta.vitest) {\n          const { vi, test, expect } = import.meta.vitest\n            test('sum', () => {\n            expect(sum(1, 2)).toBe(3)\n          })\n        }\"\n      `)\n  })\n\n  test('injects an error if a utility import is imported from an external module', () => {\n    expect(hoistSimpleCode(`\nimport { expect, test, vi } from './proxy-module'\nvi.mock('vite')\ntest('hi', () => {\n  expect(1 + 1).toEqual(2)\n})\n      `)).toMatchInlineSnapshot(`\n        \"if (typeof globalThis[\"vi\"] === \"undefined\") { throw new Error(\"There are some problems in resolving the mocks API.\\\\nYou may encounter this issue when importing the mocks API from another module other than 'vitest'.\\\\nTo fix this issue you can either:\\\\n- import the mocks API directly from 'vitest'\\\\n- enable the 'globals' option\") }\n        __vi_import_0__.vi.mock('vite')\n        const __vi_import_0__ = await import(\"./proxy-module\");\n\n\n        __vi_import_0__.test('hi', () => {\n          __vi_import_0__.expect(1 + 1).toEqual(2)\n        })\"\n      `)\n  })\n})\n\ndescribe('throws an error when nodes are incompatible', () => {\n  const getErrorWhileHoisting = (code: string) => {\n    try {\n      hoistMockAndResolve(code, '/test.js', parse, hoistMocksOptions)?.code.trim()\n    }\n    catch (err: any) {\n      return err\n    }\n  }\n\n  it.each([\n    [\n      'vi.hoisted is called inside vi.mock',\n      `\\\nimport { vi } from 'vitest'\n\nvi.mock('./mocked', () => {\n  const variable = vi.hoisted(() => 1)\n  console.log(variable)\n})\n`,\n    ],\n    [\n      'awaited vi.hoisted is called inside vi.mock',\n      `\\\nimport { vi } from 'vitest'\n\nvi.mock('./mocked', async () => {\n  await vi.hoisted(() => 1)\n})\n`,\n    ],\n    [\n      'awaited assigned vi.hoisted is called inside vi.mock',\n      `\\\nimport { vi } from 'vitest'\n\nvi.mock('./mocked', async () => {\n  const variable = await vi.hoisted(() => 1)\n})\n`,\n    ],\n    [\n      'vi.mock inside vi.hoisted',\n      `\\\nimport { vi } from 'vitest'\n\nvi.hoisted(() => {\n  vi.mock('./mocked')\n})\n`,\n    ],\n    [\n      'vi.mock is called inside assigned vi.hoisted',\n      `\\\nimport { vi } from 'vitest'\n\nconst values = vi.hoisted(() => {\n  vi.mock('./mocked')\n})\n`,\n    ],\n    [\n      'vi.mock is called inside awaited vi.hoisted',\n      `\\\nimport { vi } from 'vitest'\n\nawait vi.hoisted(async () => {\n  vi.mock('./mocked')\n})\n`,\n    ],\n    [\n      'vi.mock is called inside assigned awaited vi.hoisted',\n      `\\\nimport { vi } from 'vitest'\n\nconst values = await vi.hoisted(async () => {\n  vi.mock('./mocked')\n})\n`,\n    ],\n    [\n      'vi.hoisted is exported as a named export',\n      `\\\nimport { vi } from 'vitest'\n\nexport const values = vi.hoisted(async () => {\n  return {}\n})\n`,\n    ],\n    [\n      'vi.hoisted is exported as default',\n      `\\\nimport { vi } from 'vitest'\n\nexport default vi.hoisted(() => {\n  return {}\n})\n`,\n    ],\n    [\n      'awaited vi.hoisted is exported as named export',\n      `\\\nimport { vi } from 'vitest'\n\nexport const values = await vi.hoisted(async () => {\n  return {}\n})\n`,\n    ],\n    [\n      'awaited vi.hoisted is exported as default export',\n      `\\\nimport { vi } from 'vitest'\n\nexport default await vi.hoisted(async () => {\n  return {}\n})\n`,\n    ],\n    [\n      'vi.mock is exported as default export',\n      `\\\nimport { vi } from 'vitest'\n\nexport default vi.mock('./mocked')\n`,\n    ],\n    [\n      'vi.unmock is exported as default export',\n      `\\\nimport { vi } from 'vitest'\n\nexport default vi.unmock('./mocked')\n`,\n    ],\n    [\n      'vi.mock is exported as a named export',\n      `\\\nimport { vi } from 'vitest'\n\nexport const mocked = vi.mock('./mocked')\n`,\n    ],\n    [\n      'vi.unmock is exported as a named export',\n      `\\\nimport { vi } from 'vitest'\n\nexport const mocked = vi.unmock('./mocked')\n`,\n    ],\n  ])('correctly throws an error if %s', (_, code) => {\n    const error = getErrorWhileHoisting(code)\n    expect(error.message).toMatchSnapshot()\n    expect(stripVTControlCharacters(error.frame)).toMatchSnapshot()\n  })\n\n  it('shows an error when hoisted methods are used outside the top level scope', ({ onTestFinished }) => {\n    const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})\n    onTestFinished(() => warn.mockRestore())\n    const result = hoistSimpleCode(`\n// correct\nvi.mock('./hello-world-1')\n\nif (condition) {\n  vi.mock('./hello-world-2')\n}\n\ntest('some test', () => {\n  vi.mock('./hello-world-3')\n})\n\ntest('some test', () => {\n  if (condition) {\n    vi.mock('./hello-world-4')\n    vi.hoisted(() => {})\n    vi.mock(import('./hello-world-5'))\n    const variable = vi.hoisted(() => {})\n  }\n})\n\ndescribe('some suite', () => {\n  if (condition) {\n    vi.mock('./hello-world-6')\n  }\n})\n      `)\n    expect(result).toMatchInlineSnapshot(`\n      \"import { vi } from \"vitest\"\n      vi.mock('./hello-world-1')\n      vi.mock('./hello-world-2')\n      vi.mock('./hello-world-3')\n      vi.mock('./hello-world-4')\n      vi.hoisted(() => {})\n      vi.mock('./hello-world-5')\n      const variable = vi.hoisted(() => {})\n      vi.mock('./hello-world-6')\n\n      // correct\n\n      if (condition) {\n        }\n\n      test('some test', () => {\n        })\n\n      test('some test', () => {\n        if (condition) {\n                        }\n      })\n\n      describe('some suite', () => {\n        if (condition) {\n            }\n      })\"\n    `)\n    expect(warn).toMatchInlineSnapshot(`\n      [MockFunction warn] {\n        \"calls\": [\n          [\n            \"Warning: A vi.mock('./hello-world-2') call in \"/test.js\" is not at the top level of the module. Although it appears nested, it will be hoisted and executed before any tests run. Move it to the top level to reflect its actual execution order. This will become an error in a future version.\n      See: https://vitest.dev/guide/mocking/modules#how-it-works\",\n          ],\n          [\n            \"Warning: A vi.mock('./hello-world-3') call in \"/test.js\" is not at the top level of the module. Although it appears nested, it will be hoisted and executed before any tests run. Move it to the top level to reflect its actual execution order. This will become an error in a future version.\n      See: https://vitest.dev/guide/mocking/modules#how-it-works\",\n          ],\n          [\n            \"Warning: A vi.mock('./hello-world-4') call in \"/test.js\" is not at the top level of the module. Although it appears nested, it will be hoisted and executed before any tests run. Move it to the top level to reflect its actual execution order. This will become an error in a future version.\n      See: https://vitest.dev/guide/mocking/modules#how-it-works\",\n          ],\n          [\n            \"Warning: A vi.hoisted() call in \"/test.js\" is not at the top level of the module. Although it appears nested, it will be hoisted and executed before any tests run. Move it to the top level to reflect its actual execution order. This will become an error in a future version.\n      See: https://vitest.dev/guide/mocking/modules#how-it-works\",\n          ],\n          [\n            \"Warning: A vi.mock(import('./hello-world-5')) call in \"/test.js\" is not at the top level of the module. Although it appears nested, it will be hoisted and executed before any tests run. Move it to the top level to reflect its actual execution order. This will become an error in a future version.\n      See: https://vitest.dev/guide/mocking/modules#how-it-works\",\n          ],\n          [\n            \"Warning: A vi.hoisted() call in \"/test.js\" is not at the top level of the module. Although it appears nested, it will be hoisted and executed before any tests run. Move it to the top level to reflect its actual execution order. This will become an error in a future version.\n      See: https://vitest.dev/guide/mocking/modules#how-it-works\",\n          ],\n          [\n            \"Warning: A vi.mock('./hello-world-6') call in \"/test.js\" is not at the top level of the module. Although it appears nested, it will be hoisted and executed before any tests run. Move it to the top level to reflect its actual execution order. This will become an error in a future version.\n      See: https://vitest.dev/guide/mocking/modules#how-it-works\",\n          ],\n        ],\n        \"results\": [\n          {\n            \"type\": \"return\",\n            \"value\": undefined,\n          },\n          {\n            \"type\": \"return\",\n            \"value\": undefined,\n          },\n          {\n            \"type\": \"return\",\n            \"value\": undefined,\n          },\n          {\n            \"type\": \"return\",\n            \"value\": undefined,\n          },\n          {\n            \"type\": \"return\",\n            \"value\": undefined,\n          },\n          {\n            \"type\": \"return\",\n            \"value\": undefined,\n          },\n          {\n            \"type\": \"return\",\n            \"value\": undefined,\n          },\n        ],\n      }\n    `)\n  })\n\n  it('ignores vi.mock position if import.meta.vitest is present', ({ onTestFinished }) => {\n    const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})\n    onTestFinished(() => warn.mockRestore())\n    const result = hoistSimpleCode(`\nif (import.meta.vitest) {\n  vi.mock('./hello-world-1')\n}\n      `)\n    expect(result).toMatchInlineSnapshot(`\n      \"import { vi } from \"vitest\"\n      vi.mock('./hello-world-1')\n\n      if (import.meta.vitest) {\n        }\"\n    `)\n    expect(warn).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "test/core/test/inline-snap.test.ts",
    "content": "import MagicString from 'magic-string'\nimport { describe, expect, it } from 'vitest'\nimport { replaceInlineSnap } from '../../../packages/snapshot/src/port/inlineSnapshot'\n\ndescribe('inline-snap utils', () => {\n  it('replaceInlineSnap', async () => {\n    const code = `\nexpect('foo').toMatchInlineSnapshot('\"foo\"')\nexpect('foo').toMatchInlineSnapshot(\\`{\n  \"foo\": \\\\\\`\\\\\\`,\n}\\`)\n`\n    const s = new MagicString(code)\n    replaceInlineSnap(code, s, 3, '\"bar\"')\n    replaceInlineSnap(code, s, 40, '\"bar\\nfoo\"')\n    expect(s.toString()).toMatchInlineSnapshot(`\n      \"\n      expect('foo').toMatchInlineSnapshot(\\`\"bar\"\\`)\n      expect('foo').toMatchInlineSnapshot(\\`\n        \"bar\n        foo\"\n      \\`)\n      \"\n    `)\n  })\n\n  it('replaceInlineSnap with indentation', async () => {\n    const indent = '  '\n    const code = `\n${indent}expect('foo').toMatchInlineSnapshot('\"foo\"')\n${indent}expect('foo').toMatchInlineSnapshot(\\`{\n${indent}  \"foo\": \\\\\\`\\\\\\`,\n${indent}}\\`)\n`\n    const s = new MagicString(code)\n    replaceInlineSnap(code, s, 3, '\"bar\"')\n    replaceInlineSnap(code, s, 60, '\"bar\\nfoo\"')\n    expect(s.toString()).toMatchInlineSnapshot(`\n      \"\n        expect('foo').toMatchInlineSnapshot(\\`\"bar\"\\`)\n        expect('foo').toMatchInlineSnapshot(\\`\n          \"bar\n          foo\"\n        \\`)\n      \"\n    `)\n  })\n\n  it('replaceInlineSnap(string) with block comment(in same line)', async () => {\n    const code = `\n  expect('foo').toMatchInlineSnapshot(/* comment1 */'\"foo\"')\n  `\n    const s = new MagicString(code)\n    replaceInlineSnap(code, s, 0, '\"bar\"')\n    expect(s.toString()).toMatchInlineSnapshot(`\n      \"\n        expect('foo').toMatchInlineSnapshot(/* comment1 */\\`\"bar\"\\`)\n        \"\n    `)\n  })\n\n  it('replaceInlineSnap(string) with block comment(new line)', async () => {\n    const code = `\n  expect('foo').toMatchInlineSnapshot(\n    /* comment1\n       comment2\n    */\n\n    '\"foo\"')\n  `\n    const s = new MagicString(code)\n    replaceInlineSnap(code, s, 0, '\"bar\"')\n    expect(s.toString()).toMatchInlineSnapshot(`\n      \"\n        expect('foo').toMatchInlineSnapshot(\n          /* comment1\n             comment2\n          */\n\n          \\`\"bar\"\\`)\n        \"\n    `)\n  })\n\n  it('replaceInlineSnap(string) with single line comment', async () => {\n    const code = `\n  expect('foo').toMatchInlineSnapshot(\n    // comment1\n    // comment2\n    '\"foo\"')\n  `\n    const s = new MagicString(code)\n    replaceInlineSnap(code, s, 0, '\"bar\"')\n    expect(s.toString()).toMatchInlineSnapshot(`\n      \"\n        expect('foo').toMatchInlineSnapshot(\n          // comment1\n          // comment2\n          \\`\"bar\"\\`)\n        \"\n    `)\n  })\n\n  it('replaceInlineSnap(object) comments', async () => {\n    const code = `\n  expect({}).toMatchInlineSnapshot(\n    // comment1\n    // comment2\n    /*\n      comment3\n      comment4\n    */\n    \\`{\n        \"foo\": {\n          \"map\": Map {},\n          \"type\": \"object\",\n        },\n      }\\`)\n  `\n    const s = new MagicString(code)\n    replaceInlineSnap(code, s, 0, `\n    {\n      \"bar\": {\n        \"map2\": Map {},\n        \"type\": \"object1\",\n      },\n    }\n  `)\n    expect(s.toString()).toMatchInlineSnapshot(`\n      \"\n        expect({}).toMatchInlineSnapshot(\n          // comment1\n          // comment2\n          /*\n            comment3\n            comment4\n          */\n          \\`\n        {\n              \"bar\": {\n                \"map2\": Map {},\n                \"type\": \"object1\",\n              },\n            }\n      \\`)\n        \"\n    `)\n  })\n\n  describe('replaceObjectSnap()', () => {\n    it('without snapshot', async () => {\n      const code = 'expect({ foo: \\'bar\\' }).toMatchInlineSnapshot({ foo: expect.any(String) })'\n\n      const s = new MagicString(code)\n      replaceInlineSnap(code, s, 23, `\n      {\n        \"foo\": Any<String>,\n      }\n    `)\n\n      expect(s.toString()).toMatchInlineSnapshot(`\n        \"expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, \\`\n          {\n                  \"foo\": Any<String>,\n                }\n        \\`)\"\n      `)\n    })\n\n    it('with snapshot', async () => {\n      const code = 'expect({ foo: \\'bar\\' }).toMatchInlineSnapshot({ foo: expect.any(String) }, `{ }`)'\n\n      const s = new MagicString(code)\n      replaceInlineSnap(code, s, 23, `\n      {\n        \"foo\": Any<String>,\n      }\n    `)\n\n      expect(s.toString()).toMatchInlineSnapshot(`\n        \"expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, \\`\n          {\n                  \"foo\": Any<String>,\n                }\n        \\`)\"\n      `)\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/inlined.test.ts",
    "content": "// @ts-expect-error not typed lib\nimport typeOfModule from 'inline-lib'\nimport { expect, test } from 'vitest'\n\ntest('inline lib has exports injected even though it is ESM', () => {\n  expect(typeOfModule()).toBe('object')\n})\n"
  },
  {
    "path": "test/core/test/isolate.test.ts",
    "content": "import { expect, it } from 'vitest'\n\n// this should keep working after reloads\nit('isolate', () => {\n  const g = globalThis as any\n  expect(g.fooooo).toBe(undefined)\n  g.fooooo = true\n  expect(g.fooooo).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/jest-expect-no-url.test.ts",
    "content": "import { expect, it } from 'vitest'\n\n// simulate odd environment where URL is monkey-patched or not available\nit('jest-expect-no-url', () => {\n  (globalThis as any).URL = {}\n  expect('hello').toEqual('hello')\n\n  delete (globalThis as any).URL\n  expect('hello').toEqual('hello')\n})\n"
  },
  {
    "path": "test/core/test/jest-expect.test.ts",
    "content": "/* eslint-disable no-sparse-arrays */\nimport nodeAssert, { AssertionError } from 'node:assert'\nimport { stripVTControlCharacters } from 'node:util'\nimport { generateToBeMessage } from '@vitest/expect'\nimport { processError } from '@vitest/utils/error'\nimport { assert, beforeAll, describe, expect, it, vi } from 'vitest'\n\nclass TestError extends Error {}\n\n// For expect.extend\ninterface CustomMatchers<R = unknown> {\n  toBeDividedBy: (divisor: number) => R\n  toBeTestedAsync: () => Promise<R>\n  toBeTestedSync: () => R\n  toBeTestedPromise: () => R\n}\n\ndeclare module 'vitest' {\n  interface Assertion<T = any> extends CustomMatchers<T> {}\n  interface AsymmetricMatchersContaining extends CustomMatchers {}\n}\n\ndeclare global {\n  // eslint-disable-next-line ts/no-namespace\n  namespace jest {\n    interface Matchers<R> {\n      toBeJestCompatible: () => R\n    }\n  }\n}\n\ndescribe('jest-expect', () => {\n  it('basic', () => {\n    expect(1).toBe(1)\n    expect(null).toBeNull()\n    expect(1).not.toBeNull()\n    expect(null).toBeNullable()\n    expect(undefined).toBeNullable()\n    expect(0).not.toBeNullable()\n    expect(null).toBeDefined()\n    expect(undefined).not.toBeDefined()\n    expect(undefined).toBeUndefined()\n    expect(null).not.toBeUndefined()\n    expect([]).toBeTruthy()\n    expect(0).toBeFalsy()\n    expect('Hello').toMatch(/llo/)\n    expect('Hello').toMatch('llo')\n    expect('Hello').toContain('llo')\n    expect(['Hello']).toContain('Hello')\n    expect([{ text: 'Hello' }]).toContainEqual({ text: 'Hello' })\n    expect([{ text: 'Bye' }]).not.toContainEqual({ text: 'Hello' })\n    expect(1).toBeGreaterThan(0)\n\n    expect(new Date(0)).toEqual(new Date(0))\n    expect(new Date('inValId')).toEqual(new Date('inValId'))\n\n    expect(new Error('message')).toEqual(new Error('message'))\n    expect(new Error('message')).not.toEqual(new Error('different message'))\n\n    expect(new URL('https://example.org')).toEqual(new URL('https://example.org'))\n    expect(new URL('https://example.org')).not.toEqual(new URL('https://different-example.org'))\n    expect(new URL('https://example.org?query=value')).toEqual(new URL('https://example.org?query=value'))\n    expect(new URL('https://example.org?query=one')).not.toEqual(new URL('https://example.org?query=two'))\n    expect(new URL('https://subdomain.example.org/path?query=value#fragment-identifier')).toEqual(new URL('https://subdomain.example.org/path?query=value#fragment-identifier'))\n    expect(new URL('https://subdomain.example.org/path?query=value#fragment-identifier')).not.toEqual(new URL('https://subdomain.example.org/path?query=value#different-fragment-identifier'))\n    expect(new URL('https://example.org/path')).toEqual(new URL('/path', 'https://example.org'))\n    expect(new URL('https://example.org/path')).not.toEqual(new URL('/path', 'https://example.com'))\n\n    expect(BigInt(1)).toBeGreaterThan(BigInt(0))\n    expect(1).toBeGreaterThan(BigInt(0))\n    expect(BigInt(1)).toBeGreaterThan(0)\n\n    expect(1).toBeGreaterThanOrEqual(1)\n    expect(1).toBeGreaterThanOrEqual(0)\n\n    expect(BigInt(1)).toBeGreaterThanOrEqual(BigInt(1))\n    expect(BigInt(1)).toBeGreaterThanOrEqual(BigInt(0))\n    expect(BigInt(1)).toBeGreaterThanOrEqual(1)\n    expect(1).toBeGreaterThanOrEqual(BigInt(1))\n\n    expect(0).toBeLessThan(1)\n    expect(BigInt(0)).toBeLessThan(BigInt(1))\n    expect(BigInt(0)).toBeLessThan(1)\n\n    expect(1).toBeLessThanOrEqual(1)\n    expect(0).toBeLessThanOrEqual(1)\n    expect(BigInt(1)).toBeLessThanOrEqual(BigInt(1))\n    expect(BigInt(0)).toBeLessThanOrEqual(BigInt(1))\n    expect(BigInt(1)).toBeLessThanOrEqual(1)\n    expect(1).toBeLessThanOrEqual(BigInt(1))\n\n    expect(() => {\n      throw new Error('this is the error message')\n    }).toThrow('this is the error message')\n    expect(() => {}).not.toThrow()\n    expect(() => {\n      throw new TestError('error')\n    }).toThrow(TestError)\n    const err = new Error('hello world')\n    expect(() => {\n      throw err\n    }).toThrow(err)\n    expect(() => {\n      throw new Error('message')\n    }).toThrow(expect.objectContaining({\n      message: expect.stringContaining('mes'),\n    }))\n    expect(() => {\n      // eslint-disable-next-line no-throw-literal\n      throw ''\n    }).toThrow(/^$/)\n    expect(() => {\n      // eslint-disable-next-line no-throw-literal\n      throw ''\n    }).toThrow('')\n    expect(() => {\n      throw new Error('error')\n    }).not.toThrow('')\n    expect([1, 2, 3]).toHaveLength(3)\n    expect('abc').toHaveLength(3)\n    expect('').not.toHaveLength(5)\n    expect({ length: 3 }).toHaveLength(3)\n    expect(0.2 + 0.1).not.toBe(0.3)\n    expect(0.2 + 0.1).toBeCloseTo(0.3, 5)\n    expect(0.2 + 0.1).not.toBeCloseTo(0.3, 100) // expect.closeTo will fail in chai\n\n    expect(() => expect(1).toMatch(/\\d/)).toThrowErrorMatchingInlineSnapshot(`[TypeError: .toMatch() expects to receive a string, but got number]`)\n  })\n\n  it('asymmetric matchers (jest style)', () => {\n    expect({ foo: 'bar' }).toEqual({ foo: expect.stringContaining('ba') })\n    expect('bar').toEqual(expect.stringContaining('ba'))\n    expect(['bar']).toEqual([expect.stringContaining('ba')])\n    expect(new Set(['bar'])).toEqual(new Set([expect.stringContaining('ba')]))\n    expect(new Set(['bar'])).not.toEqual(new Set([expect.stringContaining('zoo')]))\n\n    expect({ foo: 'bar' }).not.toEqual({ foo: expect.stringContaining('zoo') })\n    expect('bar').not.toEqual(expect.stringContaining('zoo'))\n    expect(['bar']).not.toEqual([expect.stringContaining('zoo')])\n\n    expect({ foo: 'bar', bar: 'foo', hi: 'hello' }).toEqual({\n      foo: expect.stringContaining('ba'),\n      bar: expect.stringContaining('fo'),\n      hi: 'hello',\n    })\n    expect(0).toEqual(expect.anything())\n    expect({}).toEqual(expect.anything())\n    expect('string').toEqual(expect.anything())\n    expect(null).not.toEqual(expect.anything())\n    expect(undefined).not.toEqual(expect.anything())\n    expect({ a: 0, b: 0 }).toEqual(expect.objectContaining({ a: 0 }))\n    expect({ a: 0, b: 0 }).not.toEqual(expect.objectContaining({ z: 0 }))\n    // objectContaining with symbol key\n    const symbolForObjectContaining = Symbol('symbolForObjectContaining')\n    expect({ [symbolForObjectContaining]: 0 }).toEqual(expect.objectContaining({ [symbolForObjectContaining]: 0 }))\n    expect({ [symbolForObjectContaining]: 0 }).not.toEqual(expect.objectContaining({ [symbolForObjectContaining]: 1 }))\n    expect(0).toEqual(expect.any(Number))\n    expect('string').toEqual(expect.any(String))\n    expect('string').not.toEqual(expect.any(Number))\n\n    expect(['Bob', 'Eve']).toEqual(expect.arrayContaining(['Bob']))\n    expect(['Bob', 'Eve']).not.toEqual(expect.arrayContaining(['Mohammad']))\n\n    expect([\n      { name: 'Bob' },\n      { name: 'Eve' },\n    ]).toEqual(expect.arrayContaining<{ name: string }>([\n      { name: 'Bob' },\n    ]))\n    expect([\n      { name: 'Bob' },\n      { name: 'Eve' },\n    ]).not.toEqual(expect.arrayContaining<{ name: string }>([\n      { name: 'Mohammad' },\n    ]))\n\n    expect('Mohammad').toEqual(expect.stringMatching(/Moh/))\n    expect('Mohammad').not.toEqual(expect.stringMatching(/jack/))\n    expect({\n      sum: 0.1 + 0.2,\n    }).toEqual({\n      sum: expect.closeTo(0.3, 5),\n    })\n\n    expect({\n      sum: 0.1 + 0.2,\n    }).not.toEqual({\n      sum: expect.closeTo(0.4, 5),\n    })\n\n    expect({\n      sum: 0.1 + 0.2,\n    }).toEqual({\n      sum: expect.not.closeTo(0.4, 5),\n    })\n\n    expect(() => {\n      expect({\n        sum: 0.1 + 0.2,\n      }).toEqual({\n        sum: expect.closeTo(0.4),\n      })\n    }).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected { sum: 0.30000000000000004 } to deeply equal { sum: NumberCloseTo 0.4 (2 digits) }]`)\n  })\n\n  it('asymmetric matchers and equality testers', () => {\n    // iterable equality testers\n    expect([new Set(['x'])]).toEqual(\n      expect.arrayContaining([new Set(['x'])]),\n    )\n    expect([new Set()]).not.toEqual(\n      expect.arrayContaining([new Set(['x'])]),\n    )\n    expect({ foo: new Set(['x']) }).toEqual(\n      expect.objectContaining({ foo: new Set(['x']) }),\n    )\n    expect({ foo: new Set() }).not.toEqual(\n      expect.objectContaining({ foo: new Set(['x']) }),\n    )\n\n    // `toStrictEqual` testers\n    class Stock {\n      constructor(public type: string) {}\n    }\n    expect([new Stock('x')]).toEqual(\n      expect.arrayContaining([{ type: 'x' }]),\n    )\n    expect([new Stock('x')]).not.toStrictEqual(\n      expect.arrayContaining([{ type: 'x' }]),\n    )\n    expect([new Stock('x')]).toStrictEqual(\n      expect.arrayContaining([new Stock('x')]),\n    )\n  })\n\n  it('asymmetric matchers negate', () => {\n    expect('bar').toEqual(expect.not.stringContaining('zoo'))\n    expect('bar').toEqual(expect.not.stringMatching(/zoo/))\n    expect({ bar: 'zoo' }).toEqual(expect.not.objectContaining({ zoo: 'bar' }))\n    expect(['Bob', 'Eve']).toEqual(expect.not.arrayContaining(['Steve']))\n  })\n\n  it('expect.extend', async () => {\n    expect.extend({\n      toBeDividedBy(received, divisor) {\n        const pass = received % divisor === 0\n        if (pass) {\n          return {\n            message: () =>\n              `expected ${received} not to be divisible by ${divisor}`,\n            pass: true,\n          }\n        }\n        else {\n          return {\n            message: () =>\n              `expected ${received} to be divisible by ${divisor}`,\n            pass: false,\n          }\n        }\n      },\n      async toBeTestedAsync() {\n        return {\n          pass: false,\n          message: () => 'toBeTestedAsync',\n        }\n      },\n      toBeTestedSync() {\n        return {\n          pass: false,\n          message: () => 'toBeTestedSync',\n        }\n      },\n      toBeTestedPromise() {\n        return Promise.resolve({\n          pass: false,\n          message: () => 'toBeTestedPromise',\n        })\n      },\n      toBeJestCompatible() {\n        return {\n          pass: true,\n          message: () => '',\n        }\n      },\n      toBeTestedMatcherContext<T>(received: unknown, expected: T) {\n        if (typeof this.utils?.stringify !== 'function') {\n          throw new TypeError('this.utils.stringify is not available.')\n        }\n        return {\n          pass: received === expected,\n          message: () => 'toBeTestedMatcherContext',\n        }\n      },\n    })\n\n    expect(5).toBeDividedBy(5)\n    expect(5).not.toBeDividedBy(4)\n    expect({ one: 1, two: 2 }).toEqual({\n      one: expect.toBeDividedBy(1),\n      two: expect.not.toBeDividedBy(5),\n    })\n    expect(() => expect(2).toBeDividedBy(5)).toThrow()\n\n    expect(() => expect(null).toBeTestedSync()).toThrow('toBeTestedSync')\n    await expect(async () => await expect(null).toBeTestedAsync()).rejects.toThrow('toBeTestedAsync')\n    await expect(async () => await expect(null).toBeTestedPromise()).rejects.toThrow('toBeTestedPromise')\n\n    expect(expect).toBeJestCompatible()\n  })\n\n  it('object', () => {\n    expect({}).toEqual({})\n    expect({ apples: 13 }).toEqual({ apples: 13 })\n    expect({}).toStrictEqual({})\n    expect({}).not.toBe({})\n\n    const foo = {}\n    const complex = {\n      '0': 'zero',\n      'foo': 1,\n      'foo.bar[0]': 'baz',\n      'a-b': true,\n      'a-b-1.0.0': true,\n      'bar': {\n        foo: 'foo',\n        bar: 100,\n        arr: ['first', { zoo: 'monkey' }],\n      },\n    }\n\n    expect(foo).toBe(foo)\n    expect(foo).toStrictEqual(foo)\n    expect(complex).toMatchObject({})\n    expect(complex).toMatchObject({ foo: 1 })\n    expect([complex]).toMatchObject([{ foo: 1 }])\n    expect(complex).not.toMatchObject({ foo: 2 })\n    expect(complex).toMatchObject({ bar: { bar: 100 } })\n    expect(complex).toMatchObject({ foo: expect.any(Number) })\n\n    expect(complex).toHaveProperty('a-b')\n    expect(complex).toHaveProperty('a-b-1.0.0')\n    expect(complex).toHaveProperty('0')\n    expect(complex).toHaveProperty('0', 'zero')\n    expect(complex).toHaveProperty(['0'])\n    expect(complex).toHaveProperty(['0'], 'zero')\n    expect(complex).toHaveProperty([0])\n    expect(complex).toHaveProperty([0], 'zero')\n    expect(complex).toHaveProperty('foo')\n    expect(complex).toHaveProperty('foo', 1)\n    expect(complex).toHaveProperty('bar.foo', 'foo')\n    expect(complex).toHaveProperty('bar.arr[0]')\n    expect(complex).toHaveProperty('bar.arr[1].zoo', 'monkey')\n    expect(complex).toHaveProperty('bar.arr.0')\n    expect(complex).toHaveProperty(['bar', 'arr', '0'])\n    expect(complex).toHaveProperty(['bar', 'arr', '0'], 'first')\n    expect(complex).toHaveProperty(['bar', 'arr', 0])\n    expect(complex).toHaveProperty(['bar', 'arr', 0], 'first')\n    expect(complex).toHaveProperty('bar.arr.1.zoo', 'monkey')\n    expect(complex).toHaveProperty(['bar', 'arr', '1', 'zoo'], 'monkey')\n    expect(complex).toHaveProperty(['foo.bar[0]'], 'baz')\n\n    expect(complex).toHaveProperty('foo', expect.any(Number))\n    expect(complex).toHaveProperty('bar', expect.any(Object))\n    expect(complex).toHaveProperty('bar.arr', expect.any(Array))\n    expect(complex).toHaveProperty('bar.arr.0', expect.anything())\n\n    expect(() => {\n      expect(complex).toHaveProperty('some-unknown-property')\n    }).toThrow()\n\n    expect(() => {\n      expect(complex).toHaveProperty('a-b', false)\n    }).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected { '0': 'zero', foo: 1, …(4) } to have property \"a-b\" with value false]`)\n\n    expect(() => {\n      const x = { a: { b: { c: 1 } } }\n      const y = { a: { b: { c: 2 } } }\n      Object.freeze(x.a)\n      expect(x).toEqual(y)\n    }).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected { a: { b: { c: 1 } } } to deeply equal { a: { b: { c: 2 } } }]`)\n  })\n\n  it('assertions', () => {\n    expect(1).toBe(1)\n    expect(1).toBe(1)\n    expect(1).toBe(1)\n    expect.assertions(3)\n  })\n\n  it('assertions with different order', () => {\n    expect.assertions(3)\n    expect(1).toBe(1)\n    expect(1).toBe(1)\n    expect(1).toBe(1)\n  })\n\n  it('assertions when asynchronous code', async () => {\n    expect.assertions(3)\n    await Promise.all([\n      expect(1).toBe(1),\n      expect(1).toBe(1),\n      expect(1).toBe(1),\n    ])\n  })\n\n  it.fails('assertions when asynchronous code', async () => {\n    // Error: expected number of assertions to be 2, but got 3\n    expect.assertions(2)\n    await Promise.all([\n      expect(1).toBe(1),\n      expect(1).toBe(1),\n      expect(1).toBe(1),\n    ])\n  })\n\n  it.fails('has assertions', () => {\n    expect.hasAssertions()\n  })\n\n  it('has assertions', () => {\n    expect(1).toBe(1)\n    expect.hasAssertions()\n  })\n\n  it('has assertions with different order', () => {\n    expect.hasAssertions()\n    expect(1).toBe(1)\n  })\n\n  it.fails('toBe with null/undefined values', () => {\n    expect(undefined).toBe(true)\n    expect(null).toBe(true)\n  })\n\n  // https://jestjs.io/docs/expect#tostrictequalvalue\n\n  class LaCroix {\n    constructor(public flavor: any) {}\n  }\n\n  describe('the La Croix cans on my desk', () => {\n    it('are not semantically the same', () => {\n      expect(new LaCroix('lemon')).toEqual({ flavor: 'lemon' })\n      expect(new LaCroix('lemon')).not.toStrictEqual({ flavor: 'lemon' })\n    })\n  })\n\n  it('array', () => {\n    expect([]).toEqual([])\n    expect([]).not.toBe([])\n    expect([]).toStrictEqual([])\n\n    const foo: any[] = []\n\n    expect(foo).toBe(foo)\n    expect(foo).toStrictEqual(foo)\n\n    const complex = [\n      {\n        foo: 1,\n        bar: { foo: 'foo', bar: 100, arr: ['first', { zoo: 'monkey' }] },\n      },\n    ]\n    expect(complex).toStrictEqual([\n      {\n        foo: 1,\n        bar: { foo: 'foo', bar: 100, arr: ['first', { zoo: 'monkey' }] },\n      },\n    ])\n  })\n\n  describe('toThrow', () => {\n    it('error wasn\\'t thrown', () => {\n      expect(() => {\n        expect(() => {\n        }).toThrow(Error)\n      }).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected function to throw an error, but it didn't]`)\n    })\n\n    it('async wasn\\'t awaited', () => {\n      expect(() => {\n        expect(async () => {\n        }).toThrow(Error)\n      }).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected function to throw an error, but it didn't]`)\n    })\n\n    it('custom error class', () => {\n      class Error1 extends Error {};\n      class Error2 extends Error {};\n\n      // underlying `toEqual` doesn't require constructor/prototype equality\n      expect(() => {\n        throw new Error1('hi')\n      }).toThrow(new Error2('hi'))\n      expect(new Error1('hi')).toEqual(new Error2('hi'))\n      expect(new Error1('hi')).not.toStrictEqual(new Error2('hi'))\n    })\n\n    it('non Error instance', () => {\n      // primitives\n      expect(() => {\n        // eslint-disable-next-line no-throw-literal\n        throw 42\n      }).toThrow(42)\n      expect(() => {\n        // eslint-disable-next-line no-throw-literal\n        throw 42\n      }).not.toThrow(43)\n\n      expect(() => {\n        expect(() => {\n        // eslint-disable-next-line no-throw-literal\n          throw 42\n        }).toThrow(43)\n      }).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected a thrown value to equal 43]`)\n\n      // deep equality\n      expect(() => {\n        // eslint-disable-next-line no-throw-literal\n        throw { foo: 'hello world' }\n      }).toThrow({ foo: expect.stringContaining('hello') })\n      expect(() => {\n        // eslint-disable-next-line no-throw-literal\n        throw { foo: 'bar' }\n      }).not.toThrow({ foo: expect.stringContaining('hello') })\n\n      expect(() => {\n        expect(() => {\n        // eslint-disable-next-line no-throw-literal\n          throw { foo: 'bar' }\n        }).toThrow({ foo: expect.stringContaining('hello') })\n      }).toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected a thrown value to equal { foo: StringContaining \"hello\" }]`)\n    })\n\n    it('error from different realm', async () => {\n      const vm = await import('node:vm')\n      const context: any = {}\n      vm.createContext(context)\n      new vm.Script('fn = () => { throw new TypeError(\"oops\") }; globalObject = this').runInContext(context)\n      const { fn, globalObject } = context\n\n      // constructor\n      expect(fn).toThrow(globalObject.TypeError)\n      expect(fn).not.toThrow(globalObject.ReferenceError)\n      expect(fn).not.toThrow(globalObject.EvalError)\n\n      // instance\n      expect(fn).toThrow(new globalObject.TypeError('oops'))\n      expect(fn).not.toThrow(new globalObject.TypeError('message'))\n      expect(fn).not.toThrow(new globalObject.ReferenceError('oops'))\n      expect(fn).not.toThrow(new globalObject.EvalError('no way'))\n    })\n  })\n})\n\ndescribe('.toStrictEqual()', () => {\n  class TestClassA {\n    constructor(public a: any, public b: any) {}\n  }\n\n  class TestClassB {\n    constructor(public a: any, public b: any) {}\n  }\n\n  const TestClassC = class Child extends TestClassA {\n    constructor(a: any, b: any) {\n      super(a, b)\n    }\n  }\n\n  const TestClassD = class Child extends TestClassB {\n    constructor(a: any, b: any) {\n      super(a, b)\n    }\n  }\n\n  it('does not ignore keys with undefined values', () => {\n    expect({\n      a: undefined,\n      b: 2,\n    }).not.toStrictEqual({ b: 2 })\n  })\n\n  it('does not ignore keys with undefined values inside an array', () => {\n    expect([{ a: undefined }]).not.toStrictEqual([{}])\n  })\n\n  it('does not ignore keys with undefined values deep inside an object', () => {\n    expect([{ a: [{ a: undefined }] }]).not.toStrictEqual([{ a: [{}] }])\n  })\n\n  it('does not consider holes as undefined in sparse arrays', () => {\n    expect([, , , 1, , ,]).not.toStrictEqual([, , , 1, undefined, ,])\n  })\n\n  it('passes when comparing same type', () => {\n    expect({\n      test: new TestClassA(1, 2),\n    }).toStrictEqual({ test: new TestClassA(1, 2) })\n  })\n\n  it('does not pass for different types', () => {\n    expect({\n      test: new TestClassA(1, 2),\n    }).not.toStrictEqual({ test: new TestClassB(1, 2) })\n  })\n\n  it('does not simply compare constructor names', () => {\n    const c = new TestClassC(1, 2)\n    const d = new TestClassD(1, 2)\n    expect(c.constructor.name).toEqual(d.constructor.name)\n    expect({ test: c }).not.toStrictEqual({ test: d })\n  })\n\n  it('passes for matching sparse arrays', () => {\n    expect([, 1]).toStrictEqual([, 1])\n  })\n\n  it('does not pass when sparseness of arrays do not match', () => {\n    expect([, 1]).not.toStrictEqual([undefined, 1])\n    expect([undefined, 1]).not.toStrictEqual([, 1])\n    expect([, , , 1]).not.toStrictEqual([, 1])\n  })\n\n  it('does not pass when equally sparse arrays have different values', () => {\n    expect([, 1]).not.toStrictEqual([, 2])\n  })\n\n  it('does not pass when ArrayBuffers are not equal', () => {\n    expect(Uint8Array.from([1, 2]).buffer).not.toStrictEqual(\n      Uint8Array.from([0, 0]).buffer,\n    )\n    expect(Uint8Array.from([2, 1]).buffer).not.toStrictEqual(\n      Uint8Array.from([2, 2]).buffer,\n    )\n    expect(Uint8Array.from([]).buffer).not.toStrictEqual(\n      Uint8Array.from([1]).buffer,\n    )\n  })\n\n  it('passes for matching buffers', () => {\n    expect(Uint8Array.from([1]).buffer).toStrictEqual(\n      Uint8Array.from([1]).buffer,\n    )\n    expect(Uint8Array.from([]).buffer).toStrictEqual(\n      Uint8Array.from([]).buffer,\n    )\n    expect(Uint8Array.from([9, 3]).buffer).toStrictEqual(\n      Uint8Array.from([9, 3]).buffer,\n    )\n  })\n\n  it('does not pass for DataView', () => {\n    expect(new DataView(Uint8Array.from([1, 2, 3]).buffer)).not.toStrictEqual(\n      new DataView(Uint8Array.from([3, 2, 1]).buffer),\n    )\n\n    expect(new DataView(Uint16Array.from([1, 2]).buffer)).not.toStrictEqual(\n      new DataView(Uint16Array.from([2, 1]).buffer),\n    )\n  })\n\n  it('passes for matching DataView', () => {\n    expect(new DataView(Uint8Array.from([1, 2, 3]).buffer)).toStrictEqual(\n      new DataView(Uint8Array.from([1, 2, 3]).buffer),\n    )\n    expect(new DataView(Uint8Array.from([]).buffer)).toStrictEqual(\n      new DataView(Uint8Array.from([]).buffer),\n    )\n  })\n})\n\ndescribe('toBeTypeOf()', () => {\n  it.each([\n    [1n, 'bigint'],\n    [true, 'boolean'],\n    [false, 'boolean'],\n    [(() => {}) as () => void, 'function'],\n    [function () {} as () => void, 'function'],\n    [1, 'number'],\n    [Number.POSITIVE_INFINITY, 'number'],\n    [Number.NaN, 'number'],\n    [0, 'number'],\n    [{}, 'object'],\n    [[], 'object'],\n    [null, 'object'],\n    ['', 'string'],\n    ['test', 'string'],\n    [Symbol('test'), 'symbol'],\n    [undefined, 'undefined'],\n  ] as const)('pass with typeof %s === %s', (actual, expected) => {\n    expect(actual).toBeTypeOf(expected)\n  })\n\n  it('pass with negotiation', () => {\n    expect('test').not.toBeTypeOf('number')\n  })\n})\n\ndescribe('toBeOneOf()', () => {\n  it('pass with assertion', () => {\n    expect(0).toBeOneOf([0, 1, 2])\n    expect(0).toBeOneOf([expect.any(Number)])\n    expect('apple').toBeOneOf(['apple', 'banana', 'orange'])\n    expect('apple').toBeOneOf(new Set(['apple', 'banana', 'orange']))\n    expect('apple').toBeOneOf([expect.any(String)])\n    expect('apple').toBeOneOf(new Set([expect.any(String)]))\n    expect(true).toBeOneOf([true, false])\n    expect(true).toBeOneOf([expect.any(Boolean)])\n    expect(null).toBeOneOf([expect.any(Object)])\n    expect(undefined).toBeOneOf([undefined])\n  })\n\n  it('pass with negotiation', () => {\n    expect(3).not.toBeOneOf([0, 1, 2])\n    expect(3).not.toBeOneOf([expect.any(String)])\n    expect('mango').not.toBeOneOf(['apple', 'banana', 'orange'])\n    expect('mango').not.toBeOneOf(new Set(['apple', 'banana', 'orange']))\n    expect('mango').not.toBeOneOf([expect.any(Number)])\n    expect('mango').not.toBeOneOf(new Set([expect.any(Number)]))\n    expect(null).not.toBeOneOf([undefined])\n  })\n\n  it.fails('fail with missing negotiation', () => {\n    expect(3).toBeOneOf([0, 1, 2])\n    expect(3).toBeOneOf([expect.any(String)])\n    expect('mango').toBeOneOf(['apple', 'banana', 'orange'])\n    expect('mango').toBeOneOf(new Set(['apple', 'banana', 'orange']))\n    expect('mango').toBeOneOf([expect.any(Number)])\n    expect('mango').toBeOneOf(new Set([expect.any(Number)]))\n    expect(null).toBeOneOf([undefined])\n  })\n\n  it('asymmetric matcher', () => {\n    expect({ a: 0 }).toEqual(expect.toBeOneOf([expect.objectContaining({ a: 0 }), null]))\n    expect({\n      name: 'apple',\n      count: 1,\n    }).toEqual({\n      name: expect.toBeOneOf(['apple', 'banana', 'orange']),\n      count: expect.toBeOneOf([expect.any(Number)]),\n    })\n  })\n\n  it('error message', () => {\n    snapshotError(() => expect(3).toBeOneOf([0, 1, 2]))\n    snapshotError(() => expect(3).toBeOneOf([expect.any(String)]))\n    snapshotError(() => expect({ a: 0 }).toEqual(expect.toBeOneOf([expect.objectContaining({ b: 0 }), null, undefined])))\n    snapshotError(() => expect({ name: 'mango' }).toEqual({ name: expect.toBeOneOf(['apple', 'banana', 'orange']) }))\n  })\n})\n\ndescribe('toSatisfy()', () => {\n  const isOdd = (value: number) => value % 2 !== 0\n\n  it('pass with 0', () => {\n    expect(1).toSatisfy(isOdd)\n  })\n\n  it('pass with negotiation', () => {\n    expect(2).not.toSatisfy(isOdd)\n  })\n\n  it.fails('fail with missing negotiation', () => {\n    expect(2).toSatisfy(isOdd)\n  })\n\n  it('calls the function', () => {\n    const isOddMock = vi.fn(isOdd)\n    expect(isOddMock).not.toBeCalled()\n    expect(1).toSatisfy(isOddMock)\n    expect(isOddMock).toBeCalled()\n  })\n\n  it('asymmetric matcher', () => {\n    expect({ value: 1 }).toEqual({ value: expect.toSatisfy(isOdd) })\n    expect(() => {\n      expect({ value: 2 }).toEqual({ value: expect.toSatisfy(isOdd, 'odd') })\n    }).toThrowErrorMatchingInlineSnapshot(\n      `[AssertionError: expected { value: 2 } to deeply equal { value: toSatisfy{…} }]`,\n    )\n\n    expect(() => {\n      throw new Error('1')\n    }).toThrow(\n      expect.toSatisfy((e) => {\n        assert(e instanceof Error)\n        expect(e).toMatchObject({ message: expect.toSatisfy(isOdd) })\n        return true\n      }),\n    )\n\n    expect(() => {\n      expect(() => {\n        throw new Error('2')\n      }).toThrow(\n        expect.toSatisfy((e) => {\n          assert(e instanceof Error)\n          expect(e).toMatchObject({ message: expect.toSatisfy(isOdd) })\n          return true\n        }),\n      )\n    }).toThrowErrorMatchingInlineSnapshot(\n      `[AssertionError: expected Error: 2 to match object { Object (message) }]`,\n    )\n  })\n\n  it('error message', () => {\n    snapshotError(() => expect(2).toSatisfy(isOdd))\n    snapshotError(() => expect(2).toSatisfy(isOdd, 'ODD'))\n    snapshotError(() => expect({ value: 2 }).toEqual({ value: expect.toSatisfy(isOdd) }))\n    snapshotError(() => expect({ value: 2 }).toEqual({ value: expect.toSatisfy(isOdd, 'ODD') }))\n  })\n})\n\ndescribe('toHaveBeenCalled', () => {\n  describe('negated', () => {\n    it('fails if called', () => {\n      const mock = vi.fn().mockName('spy')\n      mock()\n\n      expect(() => {\n        expect(mock).not.toHaveBeenCalled()\n      }).toThrow(/^expected \"spy\" to not be called at all[^e]/)\n    })\n  })\n\n  it('undefined argument', () => {\n    const fn = vi.fn()\n    fn(undefined)\n    expect(fn).not.toHaveBeenCalledWith()\n    expect(fn).toHaveBeenCalledWith(undefined)\n    expect(fn).toHaveBeenCalledWith(expect.toSatisfy(() => true))\n    expect(fn).toHaveBeenCalledWith(expect.not.toSatisfy(() => false))\n    expect(fn).toHaveBeenCalledWith(expect.toBeOneOf([undefined, null]))\n  })\n\n  it('no argument', () => {\n    const fn = vi.fn()\n    fn()\n    expect(fn).toHaveBeenCalledWith()\n    expect(fn).not.toHaveBeenCalledWith(undefined)\n    expect(fn).not.toHaveBeenCalledWith(expect.toSatisfy(() => true))\n    expect(fn).not.toHaveBeenCalledWith(expect.not.toSatisfy(() => false))\n    expect(fn).not.toHaveBeenCalledWith(expect.toBeOneOf([undefined, null]))\n  })\n\n  it('no strict equal check for each argument', () => {\n    const fn = vi.fn()\n    fn({ x: undefined, z: 123 })\n    expect(fn).toHaveBeenCalledWith({ y: undefined, z: 123 })\n  })\n})\n\ndescribe('toHaveBeenCalledWith', () => {\n  describe('negated', () => {\n    it('fails if called', () => {\n      const mock = vi.fn().mockName('spy')\n      mock(3)\n\n      expect(() => {\n        expect(mock).not.toHaveBeenCalledWith(3)\n      }).toThrow(/^expected \"spy\" to not be called with arguments: \\[ 3 \\][^e]/)\n    })\n  })\n})\n\ndescribe('toHaveBeenCalledExactlyOnceWith', () => {\n  describe('negated', () => {\n    it('fails if called', () => {\n      const mock = vi.fn().mockName('spy')\n      mock(3)\n\n      expect(() => {\n        expect(mock).not.toHaveBeenCalledExactlyOnceWith(3)\n      }).toThrow(/^expected \"spy\" to not be called once with arguments: \\[ 3 \\][^e]/)\n    })\n\n    it('passes if called multiple times with args', () => {\n      const mock = vi.fn()\n      mock(3)\n      mock(3)\n\n      expect(mock).not.toHaveBeenCalledExactlyOnceWith(3)\n    })\n\n    it('passes if not called', () => {\n      const mock = vi.fn()\n      expect(mock).not.toHaveBeenCalledExactlyOnceWith(3)\n    })\n\n    it('passes if called with a different argument', () => {\n      const mock = vi.fn()\n      mock(4)\n\n      expect(mock).not.toHaveBeenCalledExactlyOnceWith(3)\n    })\n  })\n\n  it('fails if not called or called too many times', () => {\n    const mock = vi.fn().mockName('spy')\n\n    expect(() => {\n      expect(mock).toHaveBeenCalledExactlyOnceWith(3)\n    }).toThrow(/^expected \"spy\" to be called once with arguments: \\[ 3 \\][^e]/)\n\n    mock(3)\n    mock(3)\n\n    expect(() => {\n      expect(mock).toHaveBeenCalledExactlyOnceWith(3)\n    }).toThrow(/^expected \"spy\" to be called once with arguments: \\[ 3 \\][^e]/)\n  })\n\n  it('fails if called with wrong args', () => {\n    const mock = vi.fn()\n    mock(4)\n\n    expect(() => {\n      expect(mock).toHaveBeenCalledExactlyOnceWith(3)\n    }).toThrow(/^expected \"vi\\.fn\\(\\)\" to be called once with arguments: \\[ 3 \\][^e]/)\n  })\n\n  it('passes if called exactly once with args', () => {\n    const mock = vi.fn()\n    mock(3)\n\n    expect(mock).toHaveBeenCalledExactlyOnceWith(3)\n  })\n})\n\ndescribe('toHaveBeenCalledBefore', () => {\n  it('success if expect mock is called before result mock', () => {\n    const expectMock = vi.fn().mockName('expectMock')\n    const resultMock = vi.fn().mockName('resultMock')\n\n    expectMock()\n    resultMock()\n\n    expect(expectMock).toHaveBeenCalledBefore(resultMock)\n  })\n\n  it('throws if expect is not a spy', () => {\n    expect(() => {\n      expect(1).toHaveBeenCalledBefore(vi.fn())\n    }).toThrow(/^1 is not a spy or a call to a spy/)\n  })\n\n  it('throws if result is not a spy', () => {\n    expect(() => {\n      expect(vi.fn()).toHaveBeenCalledBefore(1 as any)\n    }).toThrow(/^1 is not a spy or a call to a spy/)\n  })\n\n  it('throws if expect mock is called after result mock', () => {\n    const expectMock = vi.fn()\n    const resultMock = vi.fn()\n\n    resultMock()\n    expectMock()\n\n    expect(() => {\n      expect(expectMock).toHaveBeenCalledBefore(resultMock)\n    }).toThrow(/^expected \"vi\\.fn\\(\\)\" to have been called before \"vi\\.fn\\(\\)\"/)\n  })\n\n  it('throws with correct mock name if failed', () => {\n    const mock1 = vi.fn().mockName('mock1')\n    const mock2 = vi.fn().mockName('mock2')\n\n    mock2()\n    mock1()\n\n    expect(() => {\n      expect(mock1).toHaveBeenCalledBefore(mock2)\n    }).toThrow(/^expected \"mock1\" to have been called before \"mock2\"/)\n  })\n\n  it('fails if expect mock is not called', () => {\n    const resultMock = vi.fn().mockName('resultMock')\n\n    resultMock()\n\n    expect(() => {\n      expect(vi.fn()).toHaveBeenCalledBefore(resultMock)\n    }).toThrow(/^expected \"vi\\.fn\\(\\)\" to have been called before \"resultMock\"/)\n  })\n\n  it('not fails if expect mock is not called with option `failIfNoFirstInvocation` set to false', () => {\n    const resultMock = vi.fn()\n\n    resultMock()\n\n    expect(vi.fn()).toHaveBeenCalledBefore(resultMock, false)\n  })\n\n  it('fails if result mock is not called', () => {\n    const expectMock = vi.fn().mockName('expectMock')\n\n    expectMock()\n\n    expect(() => {\n      expect(expectMock).toHaveBeenCalledBefore(vi.fn())\n    }).toThrow(/^expected \"expectMock\" to have been called before \"vi\\.fn\\(\\)\"/)\n  })\n})\n\ndescribe('toHaveBeenCalledAfter', () => {\n  it('success if expect mock is called after result mock', () => {\n    const resultMock = vi.fn()\n    const expectMock = vi.fn()\n\n    resultMock()\n    expectMock()\n\n    expect(expectMock).toHaveBeenCalledAfter(resultMock)\n  })\n\n  it('throws if expect is not a spy', () => {\n    expect(() => {\n      expect(1).toHaveBeenCalledAfter(vi.fn())\n    }).toThrow(/^1 is not a spy or a call to a spy/)\n  })\n\n  it('throws if result is not a spy', () => {\n    expect(() => {\n      expect(vi.fn()).toHaveBeenCalledAfter(1 as any)\n    }).toThrow(/^1 is not a spy or a call to a spy/)\n  })\n\n  it('throws if expect mock is called before result mock', () => {\n    const resultMock = vi.fn()\n    const expectMock = vi.fn()\n\n    expectMock()\n    resultMock()\n\n    expect(() => {\n      expect(expectMock).toHaveBeenCalledAfter(resultMock)\n    }).toThrow(/^expected \"vi\\.fn\\(\\)\" to have been called after \"vi\\.fn\\(\\)\"/)\n  })\n\n  it('throws with correct mock name if failed', () => {\n    const mock1 = vi.fn().mockName('mock1')\n    const mock2 = vi.fn().mockName('mock2')\n\n    mock1()\n    mock2()\n\n    expect(() => {\n      expect(mock1).toHaveBeenCalledAfter(mock2)\n    }).toThrow(/^expected \"mock1\" to have been called after \"mock2\"/)\n  })\n\n  it('fails if result mock is not called', () => {\n    const expectMock = vi.fn().mockName('expectMock')\n\n    expectMock()\n\n    expect(() => {\n      expect(expectMock).toHaveBeenCalledAfter(vi.fn())\n    }).toThrow(/^expected \"expectMock\" to have been called after \"vi\\.fn\\(\\)\"/)\n  })\n\n  it('not fails if result mock is not called with option `failIfNoFirstInvocation` set to false', () => {\n    const expectMock = vi.fn()\n\n    expectMock()\n\n    expect(expectMock).toHaveBeenCalledAfter(vi.fn(), false)\n  })\n\n  it('fails if expect mock is not called', () => {\n    const resultMock = vi.fn().mockName('resultMock')\n\n    resultMock()\n\n    expect(() => {\n      expect(vi.fn()).toHaveBeenCalledAfter(resultMock)\n    }).toThrow(/^expected \"vi\\.fn\\(\\)\" to have been called after \"resultMock\"/)\n  })\n})\n\ndescribe('async expect', () => {\n  it('resolves', async () => {\n    await expect((async () => 'true')()).resolves.toBe('true')\n    await expect((async () => 'true')()).resolves.not.toBe('true22')\n    await expect((async () => 'true')()).resolves.not.toThrow()\n    await expect((async () => new Error('msg'))()).resolves.not.toThrow() // calls chai assertion\n    await expect((async () => new Error('msg'))()).resolves.not.toThrow(Error) // calls our assertion\n    await expect((async () => () => {\n      throw new Error('msg')\n    })()).resolves.toThrow()\n    await expect((async () => () => {\n      return new Error('msg')\n    })()).resolves.not.toThrow()\n    await expect((async () => () => {\n      return new Error('msg')\n    })()).resolves.not.toThrow(Error)\n  })\n\n  it('resolves throws chai', async () => {\n    const assertion = async () => {\n      await expect((async () => new Error('msg'))()).resolves.toThrow()\n    }\n\n    await expect(assertion).rejects.toThrow('expected promise to throw an error, but it didn\\'t')\n  })\n\n  it('resolves throws jest', async () => {\n    const assertion = async () => {\n      await expect((async () => new Error('msg'))()).resolves.toThrow(Error)\n    }\n\n    await expect(assertion).rejects.toThrow('expected promise to throw an error, but it didn\\'t')\n  })\n\n  it('throws an error on .resolves when the argument is not a promise', () => {\n    expect.assertions(2)\n\n    const expectedError = new TypeError('You must provide a Promise to expect() when using .resolves, not \\'number\\'.')\n\n    try {\n      expect(1).resolves.toEqual(2)\n      expect.unreachable()\n    }\n    catch (error) {\n      expect(error).toEqual(expectedError)\n    }\n  })\n\n  it.fails('failed to resolve', async () => {\n    await expect((async () => {\n      throw new Error('err')\n    })()).resolves.toBe('true')\n  })\n\n  it.fails('failed to throw', async () => {\n    await expect((async () => {\n      throw new Error('err')\n    })()).resolves.not.toThrow()\n  })\n\n  it('rejects', async () => {\n    await expect((async () => {\n      throw new Error('err')\n    })()).rejects.toStrictEqual(new Error('err'))\n    await expect((async () => {\n      throw new Error('err')\n    })()).rejects.toThrow('err')\n    await expect((async () => {\n      throw new TestError('error')\n    })()).rejects.toThrow(TestError)\n    const err = new Error('hello world')\n    await expect((async () => {\n      throw err\n    })()).rejects.toThrow(err)\n    await expect((async () => {\n      throw new Error('message')\n    })()).rejects.toThrow(expect.objectContaining({\n      message: expect.stringContaining('mes'),\n    }))\n\n    await expect((async () => {\n      throw new Error('err')\n    })()).rejects.not.toStrictEqual(new Error('fake err'))\n  })\n\n  it.fails('failed to reject', async () => {\n    await expect((async () => 'test')()).rejects.toBe('test')\n  })\n\n  it('throws an error on .rejects when the argument (or function result) is not a promise', () => {\n    expect.assertions(4)\n\n    const expectedError = new TypeError('You must provide a Promise to expect() when using .rejects, not \\'number\\'.')\n\n    try {\n      expect(1).rejects.toEqual(2)\n      expect.unreachable()\n    }\n    catch (error) {\n      expect(error).toEqual(expectedError)\n    }\n\n    try {\n      expect(() => 1).rejects.toEqual(2)\n      expect.unreachable()\n    }\n    catch (error) {\n      expect(error).toEqual(expectedError)\n    }\n  })\n\n  it('reminds users to use deep equality checks if they are comparing objects', () => {\n    const generatedToBeMessage = (\n      deepEqualityName: string,\n      expected: string,\n      actual: string,\n    ) => new AssertionError({\n      message: generateToBeMessage(deepEqualityName, expected, actual),\n    })\n\n    const actual = { key: 'value' }\n    class FakeClass {}\n\n    const toStrictEqualError1 = generatedToBeMessage('toStrictEqual', '{ key: \\'value\\' }', '{ key: \\'value\\' }')\n    try {\n      expect(actual).toBe({ ...actual })\n      expect.unreachable()\n    }\n    catch (error: any) {\n      expect(error.message).toBe(toStrictEqualError1.message)\n    }\n\n    const toStrictEqualError2 = generatedToBeMessage('toStrictEqual', 'FakeClass{}', 'FakeClass{}')\n    try {\n      expect(new FakeClass()).toBe(new FakeClass())\n      expect.unreachable()\n    }\n    catch (error: any) {\n      expect(error.message).toBe(toStrictEqualError2.message)\n    }\n\n    const toEqualError1 = generatedToBeMessage('toEqual', '{}', 'FakeClass{}')\n    try {\n      expect({}).toBe(new FakeClass())\n      expect.unreachable()\n    }\n    catch (error: any) {\n      expect(error.message).toBe(toEqualError1.message)\n    }\n\n    const toEqualError2 = generatedToBeMessage('toEqual', 'FakeClass{}', '{}')\n    try {\n      expect(new FakeClass()).toBe({})\n      expect.unreachable()\n    }\n    catch (error: any) {\n      expect(error.message).toBe(toEqualError2.message)\n    }\n  })\n\n  describe('promise auto queuing', () => {\n    // silence warning\n    beforeAll(() => {\n      const spy = vi.spyOn(console, 'warn').mockImplementation(() => {})\n      return () => spy.mockRestore()\n    })\n\n    it.fails('fails', () => {\n      expect(new Promise((resolve, reject) => setTimeout(reject, 500)))\n        .resolves\n        .toBe('true')\n    })\n\n    let value = 0\n\n    it('pass first', () => {\n      expect((async () => {\n        await new Promise(resolve => setTimeout(resolve, 500))\n        value += 1\n        return value\n      })())\n        .resolves\n        .toBe(1)\n    })\n\n    it('pass second', () => {\n    // even if 'pass first' is sync, we will still wait the expect to resolve\n      expect(value).toBe(1)\n    })\n  })\n\n  it('printing error message', async () => {\n    try {\n      await expect(Promise.resolve({ foo: { bar: 42 } })).rejects.toThrow()\n      expect.unreachable()\n    }\n    catch (err: any) {\n      expect(err.message).toMatchInlineSnapshot(`\"promise resolved \"{ foo: { bar: 42 } }\" instead of rejecting\"`)\n      expect(err.stack).toContain('jest-expect.test.ts')\n    }\n\n    try {\n      const error = new Error('some error')\n      Object.assign(error, { foo: { bar: 42 } })\n      await expect(Promise.reject(error)).resolves.toBe(1)\n      expect.unreachable()\n    }\n    catch (err: any) {\n      expect(err.message).toMatchInlineSnapshot(`\"promise rejected \"Error: some error { foo: { bar: 42 } }\" instead of resolving\"`)\n      expect(err.cause).toBeDefined()\n      expect(err.cause.message).toMatchInlineSnapshot(`\"some error\"`)\n      expect(err.stack).toContain('jest-expect.test.ts')\n    }\n  })\n\n  it('handle thenable objects', async () => {\n    await expect({ then: (resolve: any) => resolve(0) }).resolves.toBe(0)\n    await expect({ then: (_: any, reject: any) => reject(0) }).rejects.toBe(0)\n\n    try {\n      await expect({ then: (resolve: any) => resolve(0) }).rejects.toBe(0)\n      expect.unreachable()\n    }\n    catch (error) {\n      expect(error).toMatchObject({ message: 'promise resolved \"+0\" instead of rejecting' })\n    }\n\n    try {\n      await expect({ then: (_: any, reject: any) => reject(0) }).resolves.toBe(0)\n      expect.unreachable()\n    }\n    catch (error) {\n      expect(error).toMatchObject({ message: 'promise rejected \"+0\" instead of resolving' })\n    }\n  })\n\n  it('chainable types', async () => {\n    /* eslint-disable prefer-promise-reject-errors */\n    await expect(Promise.resolve(1)).resolves.toBeOneOf([1])\n    await expect(Promise.resolve(1)).resolves.not.toBeOneOf([2])\n    await expect(Promise.reject(1)).rejects.toBeOneOf([1])\n    await expect(Promise.reject(1)).rejects.not.toBeOneOf([2])\n    await expect(Promise.resolve(1)).resolves.toSatisfy(v => v === 1)\n    await expect(Promise.reject(2)).rejects.toSatisfy(v => v === 2)\n    await (expect(Promise.resolve(1)).resolves.to.equal(1) satisfies Promise<any>)\n    await (expect(Promise.resolve(1)).resolves.not.to.equal(2) satisfies Promise<any>)\n    /* eslint-enable prefer-promise-reject-errors */\n  })\n})\n\nit('compatible with jest', () => {\n  expect.extend({\n    someObject() {\n      return { pass: true, message: () => '' }\n    },\n  })\n  const { matchers, state } = (globalThis as any)[Symbol.for('$$jest-matchers-object')]\n  expect(matchers).toHaveProperty('someObject')\n  expect(matchers).toHaveProperty('toBe')\n  expect(state.assertionCalls).toBe(2)\n})\n\nit('correctly prints diff', () => {\n  try {\n    expect({ a: 1 }).toEqual({ a: 2 })\n    expect.unreachable()\n  }\n  catch (err) {\n    const error = processError(err)\n    const diff = stripVTControlCharacters(error.diff!)\n    expect(diff).toContain('-   \"a\": 2')\n    expect(diff).toContain('+   \"a\": 1')\n  }\n})\n\nit('correctly prints diff for the cause', () => {\n  try {\n    expect({ a: 1 }).toEqual({ a: 2 })\n    expect.unreachable()\n  }\n  catch (err) {\n    const error = processError(new Error('wrapper', { cause: err }))\n    const diff = stripVTControlCharacters(error.cause!.diff!)\n    expect(diff).toContain('-   \"a\": 2')\n    expect(diff).toContain('+   \"a\": 1')\n  }\n})\n\nit('correctly prints diff with asymmetric matchers', () => {\n  try {\n    expect({ a: 1, b: 'string' }).toEqual({\n      a: expect.any(Number),\n      b: expect.any(Function),\n    })\n    expect.unreachable()\n  }\n  catch (err) {\n    const error = processError(err)\n    expect(stripVTControlCharacters(error.diff!)).toMatchInlineSnapshot(`\n      \"- Expected\n      + Received\n\n        {\n          \"a\": 1,\n      -   \"b\": Any<Function>,\n      +   \"b\": \"string\",\n        }\"\n    `)\n  }\n})\n\n// make it easy for dev who trims trailing whitespace on IDE\nfunction trim(s: string): string {\n  return s.replaceAll(/ *$/gm, '')\n}\n\nfunction getError(f: () => unknown) {\n  try {\n    f()\n  }\n  catch (error) {\n    const processed = processError(error)\n    return [stripVTControlCharacters(processed.message), stripVTControlCharacters(trim(processed.diff!))]\n  }\n  return expect.unreachable()\n}\n\nit('toMatchObject', () => {\n  expect(() => expect(null).toMatchObject(new Set()))\n    .toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected null to match object Set{}]`)\n  expect(() => expect(undefined).toMatchObject(new Set()))\n    .toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected undefined to match object Set{}]`)\n  expect(() => expect(1234).toMatchObject(new Set()))\n    .toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected 1234 to match object Set{}]`)\n  expect(() => expect('hello').toMatchObject(new Set()))\n    .toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected 'hello' to match object Set{}]`)\n  expect(() => expect({}).toMatchObject(new Set()))\n    .toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected {} to match object Set{}]`)\n  expect(() => expect({}).toMatchObject(new Map()))\n    .toThrowErrorMatchingInlineSnapshot(`[AssertionError: expected {} to match object Map{}]`)\n\n  // subset equality works inside Set/Map\n  expect(new Set([{ x: 1 }])).toMatchObject(new Set([{}]))\n  expect(new Map([[1, { a: 1 }]])).toMatchObject(new Map([[1, {}]]))\n\n  // Set/Map matches against empty object shape\n  expect(new Set()).toMatchObject({})\n  expect(new Map()).toMatchObject({})\n})\n\nit('proxy equality', () => {\n  // { intercepted: 'original', passthrough: 'original' } => { intercepted: 'proxied', passthrough: 'original' }\n  const proxyActual = new Proxy({ intercepted: 'original', passthrough: 'original' }, {\n    get(target, prop, receiver) {\n      if (prop === 'intercepted') {\n        return 'proxied'\n      }\n      return Reflect.get(target, prop, receiver)\n    },\n  })\n  // { intercepted: 'original' } => { intercepted: 'proxied' }\n  const proxyExpected = new Proxy({ intercepted: 'original' }, {\n    get(target, prop, receiver) {\n      if (prop === 'intercepted') {\n        return 'proxied'\n      }\n      return Reflect.get(target, prop, receiver)\n    },\n  })\n\n  // objectContaining\n  expect(proxyActual).toEqual(expect.objectContaining({ intercepted: 'proxied', passthrough: 'original' }))\n  expect(proxyActual).not.toEqual(expect.objectContaining({ intercepted: 'original' }))\n  expect({ intercepted: 'proxied', extra: 'ignored' }).toEqual(expect.objectContaining(proxyExpected))\n  expect({ intercepted: 'original' }).not.toEqual(expect.objectContaining(proxyExpected))\n\n  // toMatchObject\n  expect(proxyActual).toMatchObject({ intercepted: 'proxied', passthrough: 'original' })\n  expect(proxyActual).not.toMatchObject({ intercepted: 'original' })\n  expect({ intercepted: 'proxied', extra: 'ignored' }).toMatchObject(proxyExpected)\n  expect({ intercepted: 'original' }).not.toMatchObject(proxyExpected)\n\n  // toEqual\n  expect(proxyActual).toEqual({ intercepted: 'proxied', passthrough: 'original' })\n  expect(proxyActual).not.toEqual({ intercepted: 'original', passthrough: 'original' })\n  expect({ intercepted: 'proxied' }).toEqual(proxyExpected)\n  expect({ intercepted: 'original' }).not.toEqual(proxyExpected)\n\n  // empty target proxy with only `get` trap\n  const proxyBad = new Proxy({} as any, {\n    get(target, prop, receiver) {\n      if (prop === 'virtual') {\n        return 'value'\n      }\n      return Reflect.get(target, prop, receiver)\n    },\n  })\n  expect(proxyBad).not.toEqual(expect.objectContaining({ virtual: 'value' }))\n  expect(proxyBad).not.toMatchObject({ virtual: 'value' })\n  expect(proxyBad).not.toEqual({ virtual: 'value' })\n  expect({ virtual: 'value' }).not.toEqual(proxyBad)\n\n  // empty target proxy with required traps\n  const proxyGood = new Proxy({}, {\n    get(target, prop, receiver) {\n      if (prop === 'virtual') {\n        return 'value'\n      }\n      return Reflect.get(target, prop, receiver)\n    },\n    ownKeys: () => ['virtual'],\n    getOwnPropertyDescriptor(target, prop) {\n      if (prop === 'virtual') {\n        return { enumerable: true, configurable: true, value: 'value' }\n      }\n      return Reflect.getOwnPropertyDescriptor(target, prop)\n    },\n  })\n  expect(proxyGood).toEqual({ virtual: 'value' })\n  expect(proxyGood).toMatchObject({ virtual: 'value' })\n  expect(proxyGood).toEqual(expect.objectContaining({ virtual: 'value' }))\n  expect({ virtual: 'value' }).toEqual(proxyGood)\n})\n\nit('toMatchObject error diff', () => {\n  // single property on root (3 total properties, 1 expected)\n  expect(getError(() => expect({ a: 1, b: 2, c: 3 }).toMatchObject({ c: 4 }))).toMatchInlineSnapshot(`\n    [\n      \"expected { a: 1, b: 2, c: 3 } to match object { c: 4 }\n    (2 matching properties omitted from actual)\",\n      \"- Expected\n    + Received\n\n      {\n    -   \"c\": 4,\n    +   \"c\": 3,\n      }\",\n    ]\n  `)\n\n  // single property on root (4 total properties, 1 expected)\n  expect(getError(() => expect({ a: 1, b: 2, c: { d: 4 } }).toMatchObject({ b: 3 }))).toMatchInlineSnapshot(`\n    [\n      \"expected { a: 1, b: 2, c: { d: 4 } } to match object { b: 3 }\n    (3 matching properties omitted from actual)\",\n      \"- Expected\n    + Received\n\n      {\n    -   \"b\": 3,\n    +   \"b\": 2,\n      }\",\n    ]\n  `)\n\n  // nested property (7 total properties, 2 expected)\n  expect(getError(() => expect({ a: 1, b: 2, c: { d: 4, e: 5 }, f: { g: 6 } }).toMatchObject({ c: { d: 5 } }))).toMatchInlineSnapshot(`\n    [\n      \"expected { a: 1, b: 2, c: { d: 4, e: 5 }, …(1) } to match object { c: { d: 5 } }\n    (5 matching properties omitted from actual)\",\n      \"- Expected\n    + Received\n\n      {\n        \"c\": {\n    -     \"d\": 5,\n    +     \"d\": 4,\n        },\n      }\",\n    ]\n  `)\n\n  // 3 total properties, 3 expected (0 stripped)\n  expect(getError(() => expect({ a: 1, b: 2, c: 3 }).toMatchObject({ a: 1, b: 2, c: 4 }))).toMatchInlineSnapshot(`\n    [\n      \"expected { a: 1, b: 2, c: 3 } to match object { a: 1, b: 2, c: 4 }\",\n      \"- Expected\n    + Received\n\n      {\n        \"a\": 1,\n        \"b\": 2,\n    -   \"c\": 4,\n    +   \"c\": 3,\n      }\",\n    ]\n  `)\n\n  // 4 total properties, 3 expected\n  expect(getError(() => expect({ a: 1, b: 2, c: { d: 3 } }).toMatchObject({ a: 1, c: { d: 4 } }))).toMatchInlineSnapshot(`\n    [\n      \"expected { a: 1, b: 2, c: { d: 3 } } to match object { a: 1, c: { d: 4 } }\n    (1 matching property omitted from actual)\",\n      \"- Expected\n    + Received\n\n      {\n        \"a\": 1,\n        \"c\": {\n    -     \"d\": 4,\n    +     \"d\": 3,\n        },\n      }\",\n    ]\n  `)\n\n  // 8 total properties, 4 expected\n  expect(getError(() => expect({ a: 1, b: 2, c: { d: 4 }, foo: { value: 'bar' }, bar: { value: 'foo' } }).toMatchObject({ c: { d: 5 }, foo: { value: 'biz' } }))).toMatchInlineSnapshot(`\n    [\n      \"expected { a: 1, b: 2, c: { d: 4 }, …(2) } to match object { c: { d: 5 }, foo: { value: 'biz' } }\n    (4 matching properties omitted from actual)\",\n      \"- Expected\n    + Received\n\n      {\n        \"c\": {\n    -     \"d\": 5,\n    +     \"d\": 4,\n        },\n        \"foo\": {\n    -     \"value\": \"biz\",\n    +     \"value\": \"bar\",\n        },\n      }\",\n    ]\n  `)\n\n  // 8 total properties, 3 expected\n  const characters = { firstName: 'Vladimir', lastName: 'Harkonnen', family: 'House Harkonnen', colors: ['red', 'blue'], children: [{ firstName: 'Jessica', lastName: 'Atreides', colors: ['red', 'green', 'black'] }] }\n  expect(getError(() => expect(characters).toMatchObject({ family: 'House Atreides', children: [{ firstName: 'Paul' }] }))).toMatchInlineSnapshot(`\n    [\n      \"expected { firstName: 'Vladimir', …(4) } to match object { family: 'House Atreides', …(1) }\n    (5 matching properties omitted from actual)\",\n      \"- Expected\n    + Received\n\n      {\n        \"children\": [\n          {\n    -       \"firstName\": \"Paul\",\n    +       \"firstName\": \"Jessica\",\n          },\n        ],\n    -   \"family\": \"House Atreides\",\n    +   \"family\": \"House Harkonnen\",\n      }\",\n    ]\n  `)\n\n  // https://github.com/vitest-dev/vitest/issues/6543\n  class Foo {\n    constructor(public value: any) {}\n  }\n\n  class Bar {\n    constructor(public value: any) {}\n  }\n\n  expect(new Foo(0)).toMatchObject(new Bar(0))\n  expect(new Foo(0)).toMatchObject({ value: 0 })\n  expect({ value: 0 }).toMatchObject(new Bar(0))\n\n  expect(getError(() => expect(new Foo(0)).toMatchObject(new Bar(1)))).toMatchInlineSnapshot(`\n    [\n      \"expected Foo{ value: +0 } to match object Bar{ value: 1 }\",\n      \"- Expected\n    + Received\n\n    - Bar {\n    -   \"value\": 1,\n    + Foo {\n    +   \"value\": 0,\n      }\",\n    ]\n  `)\n\n  expect(getError(() => expect(new Foo(0)).toMatchObject({ value: 1 }))).toMatchInlineSnapshot(`\n    [\n      \"expected Foo{ value: +0 } to match object { value: 1 }\",\n      \"- Expected\n    + Received\n\n    - {\n    -   \"value\": 1,\n    + Foo {\n    +   \"value\": 0,\n      }\",\n    ]\n  `)\n\n  expect(getError(() => expect({ value: 0 }).toMatchObject(new Bar(1)))).toMatchInlineSnapshot(`\n    [\n      \"expected { value: +0 } to match object Bar{ value: 1 }\",\n      \"- Expected\n    + Received\n\n    - Bar {\n    -   \"value\": 1,\n    + {\n    +   \"value\": 0,\n      }\",\n    ]\n  `)\n\n  expect(getError(() =>\n    expect({\n      bad: new Foo(1),\n      good: new Foo(0),\n    }).toMatchObject({\n      bad: new Bar(2),\n      good: new Bar(0),\n    }),\n  )).toMatchInlineSnapshot(`\n    [\n      \"expected { bad: Foo{ value: 1 }, …(1) } to match object { bad: Bar{ value: 2 }, …(1) }\",\n      \"- Expected\n    + Received\n\n      {\n    -   \"bad\": Bar {\n    -     \"value\": 2,\n    +   \"bad\": Foo {\n    +     \"value\": 1,\n        },\n        \"good\": Bar {\n          \"value\": 0,\n        },\n      }\",\n    ]\n  `)\n\n  expect(getError(() =>\n    expect(new Foo(new Foo(1))).toMatchObject(new Bar(new Bar(0))),\n  )).toMatchInlineSnapshot(`\n    [\n      \"expected Foo{ value: Foo{ value: 1 } } to match object Bar{ value: Bar{ value: +0 } }\",\n      \"- Expected\n    + Received\n\n    - Bar {\n    -   \"value\": Bar {\n    -     \"value\": 0,\n    + Foo {\n    +   \"value\": Foo {\n    +     \"value\": 1,\n        },\n      }\",\n    ]\n  `)\n\n  expect(new Foo(new Foo(1))).toMatchObject(new Bar(new Foo(1)))\n  expect(getError(() =>\n    expect(new Foo(new Foo(1))).toMatchObject(new Bar(new Foo(2))),\n  )).toMatchInlineSnapshot(`\n    [\n      \"expected Foo{ value: Foo{ value: 1 } } to match object Bar{ value: Foo{ value: 2 } }\",\n      \"- Expected\n    + Received\n\n    - Bar {\n    + Foo {\n        \"value\": Foo {\n    -     \"value\": 2,\n    +     \"value\": 1,\n        },\n      }\",\n    ]\n  `)\n})\n\nit('toHaveProperty error diff', () => {\n  // non match value\n  expect(getError(() => expect({ name: 'foo' }).toHaveProperty('name', 'bar'))).toMatchInlineSnapshot(`\n    [\n      \"expected { name: 'foo' } to have property \"name\" with value 'bar'\",\n      \"Expected: \"bar\"\n    Received: \"foo\"\",\n    ]\n  `)\n\n  // non match key\n  expect(getError(() => expect({ noName: 'foo' }).toHaveProperty('name', 'bar'))).toMatchInlineSnapshot(`\n    [\n      \"expected { noName: 'foo' } to have property \"name\" with value 'bar'\",\n      \"- Expected:\n    \"bar\"\n\n    + Received:\n    undefined\",\n    ]\n  `)\n\n  // non match value (with asymmetric matcher)\n  expect(getError(() => expect({ name: 'foo' }).toHaveProperty('name', expect.any(Number)))).toMatchInlineSnapshot(`\n    [\n      \"expected { name: 'foo' } to have property \"name\" with value Any<Number>\",\n      \"- Expected:\n    Any<Number>\n\n    + Received:\n    \"foo\"\",\n    ]\n  `)\n\n  // non match key (with asymmetric matcher)\n  expect(getError(() => expect({ noName: 'foo' }).toHaveProperty('name', expect.any(Number)))).toMatchInlineSnapshot(`\n    [\n      \"expected { noName: 'foo' } to have property \"name\" with value Any<Number>\",\n      \"- Expected:\n    Any<Number>\n\n    + Received:\n    undefined\",\n    ]\n  `)\n\n  // non match value (deep key)\n  expect(getError(() => expect({ parent: { name: 'foo' } }).toHaveProperty('parent.name', 'bar'))).toMatchInlineSnapshot(`\n    [\n      \"expected { parent: { name: 'foo' } } to have property \"parent.name\" with value 'bar'\",\n      \"Expected: \"bar\"\n    Received: \"foo\"\",\n    ]\n  `)\n\n  // non match key (deep key)\n  expect(getError(() => expect({ parent: { noName: 'foo' } }).toHaveProperty('parent.name', 'bar'))).toMatchInlineSnapshot(`\n    [\n      \"expected { parent: { noName: 'foo' } } to have property \"parent.name\" with value 'bar'\",\n      \"- Expected:\n    \"bar\"\n\n    + Received:\n    undefined\",\n    ]\n  `)\n})\n\nfunction snapshotError(f: () => unknown) {\n  try {\n    f()\n  }\n  catch (error) {\n    const e = processError(error, { expand: true })\n    expect({\n      message: stripVTControlCharacters(e.message),\n      diff: e.diff ? stripVTControlCharacters(e.diff) : e.diff,\n      expected: e.expected,\n      actual: e.actual,\n    }).toMatchSnapshot()\n    return\n  }\n  expect.unreachable()\n}\n\nit('asymmetric matcher error', () => {\n  expect.extend({\n    stringContainingCustom(received: unknown, other: string) {\n      return {\n        pass: typeof received === 'string' && received.includes(other),\n        message: () => `expected ${this.utils.printReceived(received)} ${this.isNot ? 'not ' : ''}to contain ${this.utils.printExpected(other)}`,\n      }\n    },\n  })\n\n  // builtin: stringContaining\n  snapshotError(() => expect('hello').toEqual(expect.stringContaining('xx')))\n  snapshotError(() => expect('hello').toEqual(expect.not.stringContaining('ll')))\n  snapshotError(() => expect({ foo: 'hello' }).toEqual({ foo: expect.stringContaining('xx') }))\n  snapshotError(() => expect({ foo: 'hello' }).toEqual({ foo: expect.not.stringContaining('ll') }))\n\n  // custom\n  snapshotError(() => expect('hello').toEqual((expect as any).stringContainingCustom('xx')))\n  snapshotError(() => expect('hello').toEqual((expect as any).not.stringContainingCustom('ll')))\n  snapshotError(() => expect({ foo: 'hello' }).toEqual({ foo: (expect as any).stringContainingCustom('xx') }))\n  snapshotError(() => expect({ foo: 'hello' }).toEqual({ foo: (expect as any).not.stringContainingCustom('ll') }))\n\n  // assertion form\n  snapshotError(() => (expect('hello') as any).stringContainingCustom('xx'))\n  snapshotError(() => (expect('hello') as any).not.stringContainingCustom('ll'))\n\n  // matcher with complex argument\n  // (serialized by `String` so it becomes \"testComplexMatcher<[object Object]>\", which is same as jest's asymmetric matcher and pretty-format)\n  expect.extend({\n    testComplexMatcher(_received: unknown, _arg: unknown) {\n      return {\n        pass: false,\n        message: () => `NA`,\n      }\n    },\n  })\n  snapshotError(() => expect('hello').toEqual((expect as any).testComplexMatcher({ x: 'y' })))\n\n  // more builtins\n  snapshotError(() => expect({ k: 'v', k2: 'v2' }).toEqual(expect.objectContaining({ k: 'v', k3: 'v3' })))\n  snapshotError(() => expect(['a', 'b']).toEqual(expect.arrayContaining(['a', 'c'])))\n  snapshotError(() => expect('hello').toEqual(expect.stringMatching(/xx/)))\n  snapshotError(() => expect(2.5).toEqual(expect.closeTo(2, 1)))\n  snapshotError(() => expect('foo').toEqual(expect.toBeOneOf(['bar', 'baz'])))\n  snapshotError(() => expect(0).toEqual(expect.toBeOneOf([expect.any(String), null, undefined])))\n  snapshotError(() => expect({ k: 'v', k2: 'v2' }).toEqual(expect.toBeOneOf([expect.objectContaining({ k: 'v', k3: 'v3' }), null, undefined])))\n\n  // simple truncation if pretty-format is too long\n  snapshotError(() => expect('hello').toEqual(expect.stringContaining('a'.repeat(40))))\n\n  // error message on `toThrow(asymmetricMatcher)` failure\n  function throwError() {\n    // eslint-disable-next-line no-throw-literal\n    throw 'hello'\n  }\n  snapshotError(() => expect(throwError).toThrow(expect.stringContaining('xx')))\n  snapshotError(() => expect(throwError).toThrow((expect as any).stringContainingCustom('xx')))\n  snapshotError(() => expect(throwError).not.toThrow(expect.stringContaining('ll')))\n  snapshotError(() => expect(throwError).not.toThrow((expect as any).stringContainingCustom('ll')))\n\n  snapshotError(() => expect(() => {\n    throw new Error('hello')\n  }).toThrow(expect.stringContaining('ll')))\n  snapshotError(() => expect(() => {\n    throw new Error('hello')\n  }).toThrow((expect as any).stringContainingCustom('ll')))\n\n  // error constructor\n  class MyError1 extends Error {}\n  class MyError2 extends Error {}\n\n  snapshotError(() => expect(() => {\n    throw new MyError2('hello')\n  }).toThrow(MyError1))\n})\n\nit('error equality', () => {\n  class MyError extends Error {\n    constructor(message: string, public custom: string) {\n      super(message)\n    }\n  }\n\n  class YourError extends Error {\n    constructor(message: string, public custom: string) {\n      super(message)\n    }\n  }\n\n  {\n    // different custom property\n    const e1 = new MyError('hi', 'a')\n    const e2 = new MyError('hi', 'b')\n    snapshotError(() => expect(e1).toEqual(e2))\n    expect(e1).not.toEqual(e2)\n    expect(e1).not.toStrictEqual(e2)\n    assert.deepEqual(e1, e2)\n    nodeAssert.notDeepStrictEqual(e1, e2)\n\n    // toThrowError also compare errors similar to toEqual\n    snapshotError(() =>\n      expect(() => {\n        throw e1\n      }).toThrow(e2),\n    )\n  }\n\n  {\n    // different message\n    const e1 = new MyError('hi', 'a')\n    const e2 = new MyError('hello', 'a')\n    snapshotError(() => expect(e1).toEqual(e2))\n    expect(e1).not.toEqual(e2)\n    expect(e1).not.toStrictEqual(e2)\n    assert.notDeepEqual(e1, e2)\n    nodeAssert.notDeepStrictEqual(e1, e2)\n  }\n\n  {\n    // different class\n    const e1 = new MyError('hello', 'a')\n    const e2 = new YourError('hello', 'a')\n    snapshotError(() => expect(e1).toStrictEqual(e2))\n    expect(e1).toEqual(e2)\n    assert.deepEqual(e1, e2)\n    nodeAssert.notDeepStrictEqual(e1, e2)\n  }\n\n  {\n    // same\n    const e1 = new MyError('hi', 'a')\n    const e2 = new MyError('hi', 'a')\n    expect(e1).toEqual(e2)\n    expect(e1).toStrictEqual(e2)\n    assert.deepEqual(e1, e2)\n    nodeAssert.deepStrictEqual(e1, e2)\n\n    expect(() => {\n      throw e1\n    }).toThrow(e2)\n  }\n\n  {\n    // same\n    const e1 = new MyError('hi', 'a')\n    const e2 = new MyError('hi', 'a')\n    expect(e1).toEqual(e2)\n    expect(e1).toStrictEqual(e2)\n    assert.deepEqual(e1, e2)\n    nodeAssert.deepStrictEqual(e1, e2)\n  }\n\n  {\n    // different cause\n    const e1 = new Error('hello', { cause: 'x' })\n    const e2 = new Error('hello', { cause: 'y' })\n    snapshotError(() => expect(e1).toEqual(e2))\n    expect(e1).not.toEqual(e2)\n  }\n\n  {\n    // different cause (asymmetric fail)\n    const e1 = new Error('hello')\n    const e2 = new Error('hello', { cause: 'y' })\n    snapshotError(() => expect(e1).toEqual(e2))\n    expect(e1).not.toEqual(e2)\n  }\n\n  {\n    // different cause (asymmetric pass)\n    const e1 = new Error('hello', { cause: 'x' })\n    const e2 = new Error('hello')\n    expect(e1).toEqual(e2)\n  }\n\n  {\n    // different cause (fail by other props)\n    const e1 = new Error('hello', { cause: 'x' })\n    const e2 = new Error('world')\n    snapshotError(() => expect(e1).toEqual(e2))\n  }\n\n  {\n    // different cause\n    const e1 = new Error('hello', { cause: 'x' })\n    const e2 = { something: 'else' }\n    snapshotError(() => expect(e1).toEqual(e2))\n  }\n\n  {\n    // AggregateError (pass)\n    const e1 = new AggregateError([new Error('inner')], 'outer', { cause: 'x' })\n    const e2 = new AggregateError([new Error('inner')], 'outer', { cause: 'x' })\n    expect(e1).toEqual(e2)\n  }\n\n  {\n    // AggregateError (fail)\n    const e1 = new AggregateError([new Error('inner', { cause: 'x' })], 'outer', { cause: 'x' })\n    const e2 = new AggregateError([new Error('inner', { cause: 'y' })], 'outer', { cause: 'x' })\n    snapshotError(() => expect(e1).toEqual(e2))\n  }\n\n  {\n    // cyclic (pass)\n    const e1 = new Error('hi')\n    e1.cause = e1\n    const e2 = new Error('hi')\n    e2.cause = e2\n    expect(e1).toEqual(e2)\n  }\n\n  {\n    // cyclic (fail)\n    const e1 = new Error('hello')\n    e1.cause = e1\n    const e2 = new Error('world')\n    e2.cause = e2\n    snapshotError(() => expect(e1).toEqual(e2))\n  }\n\n  {\n    // asymmetric matcher\n    const e1 = new Error('hello', { cause: 'x' })\n    expect(e1).toEqual(expect.objectContaining({\n      message: 'hello',\n      cause: 'x',\n    }))\n    snapshotError(() => expect(e1).toEqual(expect.objectContaining({\n      message: 'hello',\n      cause: 'y',\n    })))\n    snapshotError(() => expect(e1).toEqual(expect.objectContaining({\n      message: 'world',\n      cause: 'x',\n    })))\n    snapshotError(() => expect(e1).toEqual(expect.objectContaining({\n      message: 'world',\n      cause: 'y',\n    })))\n  }\n})\n\nit('toHaveBeenNthCalledWith error', () => {\n  const fn = vi.fn()\n  fn('World')\n  fn('Hi')\n  snapshotError(() => expect(fn).toHaveBeenNthCalledWith(2, 'hey'))\n  snapshotError(() => expect(fn).toHaveBeenNthCalledWith(3, 'hey'))\n})\n\nit('toMatch/toContain diff', () => {\n  snapshotError(() => expect('hello'.repeat(20)).toContain('world'))\n  snapshotError(() => expect('hello'.repeat(20)).toMatch('world'))\n  snapshotError(() => expect('hello'.repeat(20)).toMatch(/world/))\n})\n\nit('timeout', () => new Promise(resolve => setTimeout(resolve, 500)))\n\nit('diff', () => {\n  snapshotError(() => expect(undefined).toBeTruthy())\n  snapshotError(() => expect({ hello: 'world' }).toBeFalsy())\n  snapshotError(() => expect({ hello: 'world' }).toBeNaN())\n  snapshotError(() => expect({ hello: 'world' }).toBeUndefined())\n  snapshotError(() => expect({ hello: 'world' }).toBeNull())\n})\n"
  },
  {
    "path": "test/core/test/jest-matcher-utils.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('jest-matcher-utils', () => {\n  expect.extend({\n    toBeJestEqual(received: any, expected: any) {\n      return {\n        message: () => this.utils.diff(expected, received) || '',\n        pass: received === expected,\n      }\n    },\n  })\n\n  it('diff', () => {\n    let error!: Error\n    try {\n      // @ts-expect-error \"toBeJestEqual\" is a custom matcher we just created\n      expect('a').toBeJestEqual('b')\n      expect.unreachable()\n    }\n    catch (err: any) {\n      error = err\n    }\n    expect(error.message).toMatch(/- b.*\\+ a/s)\n  })\n})\n"
  },
  {
    "path": "test/core/test/jest-mock.test.ts",
    "content": "import { describe, expect, expectTypeOf, it, vi } from 'vitest'\n\ndescribe('jest mock compat layer', () => {\n  const returnFactory = (type: string) => (value: any) => ({ type, value })\n\n  const r = returnFactory('return')\n  const e = returnFactory('throw')\n  const f = returnFactory('fulfilled')\n  const h = returnFactory('rejected')\n\n  it('works with name', () => {\n    const spy = vi.fn()\n    spy.mockName('spy test name')\n    expect(spy.getMockName()).toBe('spy test name')\n  })\n\n  it('clearing', () => {\n    const spy = vi.fn()\n\n    spy('hello')\n\n    expect(spy.mock.calls).toHaveLength(1)\n    expect(spy.mock.calls[0]).toEqual(['hello'])\n\n    spy('world')\n    expect(spy.mock.calls).toEqual([['hello'], ['world']])\n\n    spy.mockReset() // same as mockClear()\n\n    expect(spy.mock.calls).toEqual([])\n  })\n\n  it('clearing instances', () => {\n    const Spy = vi.fn()\n\n    expect(Spy.mock.instances).toHaveLength(0)\n    const _result = new Spy()\n    expect(Spy.mock.instances).toHaveLength(1)\n\n    Spy.mockReset() // same as mockClear()\n\n    expect(Spy.mock.instances).toHaveLength(0)\n  })\n\n  it('collects contexts', () => {\n    // eslint-disable-next-line prefer-arrow-callback\n    const Spy = vi.fn(function () {})\n\n    expect(Spy.mock.contexts).toHaveLength(0)\n    const ctx = new Spy()\n    expect(Spy.mock.contexts).toHaveLength(1)\n    expect(Spy.mock.contexts[0]).toBe(ctx)\n\n    Spy.mockReset()\n\n    expect(Spy.mock.contexts).toHaveLength(0)\n\n    const ctx2 = {}\n    Spy.call(ctx2)\n    expect(Spy.mock.contexts).toHaveLength(1)\n    expect(Spy.mock.contexts[0]).toBe(ctx2)\n\n    Spy.bind(ctx2)()\n\n    expect(Spy.mock.contexts).toHaveLength(2)\n    expect(Spy.mock.contexts[1]).toBe(ctx2)\n\n    Spy.apply(ctx2)\n\n    expect(Spy.mock.contexts).toHaveLength(3)\n    expect(Spy.mock.contexts[2]).toBe(ctx2)\n  })\n\n  it('tracks spied class contexts and instances', () => {\n    interface SpyClass {}\n    interface SpyConstructor {\n      (): SpyClass\n      new (): SpyClass\n    }\n    const Spy = (function () {}) as SpyConstructor\n    const obj = { Spy }\n    const spy = vi.spyOn(obj, 'Spy')\n    const instance = new obj.Spy()\n\n    expectTypeOf(spy.mock.contexts[0]).toEqualTypeOf<SpyClass>()\n    expect(spy.mock.instances).toEqual([instance])\n    expect(spy.mock.contexts).toEqual([instance])\n  })\n\n  it('implementation is set correctly on init', () => {\n    const impl = () => 1\n    const mock1 = vi.fn(impl)\n\n    expect(mock1.getMockImplementation()).toEqual(impl)\n\n    const mock2 = vi.fn()\n\n    expect(mock2.getMockImplementation()).toBeUndefined()\n  })\n\n  it('implementation types allow only function returned types', () => {\n    function fn() {\n      return 1\n    }\n\n    function asyncFn() {\n      return Promise.resolve(1)\n    }\n\n    const mock1 = vi.fn(fn)\n    const mock2 = vi.fn(asyncFn)\n\n    mock1.mockImplementation(() => 2)\n    // @ts-expect-error promise is not allowed\n    mock1.mockImplementation(() => Promise.resolve(2))\n\n    // @ts-expect-error non-promise is not allowed\n    mock2.mockImplementation(() => 2)\n    mock2.mockImplementation(() => Promise.resolve(2))\n  })\n\n  it('implementation sync fn', () => {\n    const originalFn = function () {\n      return 'original'\n    }\n    const spy = vi.fn(originalFn)\n\n    spy() // returns 'original'\n\n    expect(spy.getMockImplementation()).toBe(originalFn)\n\n    spy.mockReturnValueOnce('2-once').mockReturnValueOnce('3-once')\n\n    spy() // returns '2-once'\n    spy() // returns '3-once'\n    spy() // returns 'original'\n\n    const implOnce = () => 'once'\n\n    spy.mockImplementationOnce(implOnce)\n\n    spy() // returns 'once'\n    spy() // returns 'original'\n\n    expect(spy.getMockImplementation() === implOnce).toBe(false) // jest doesn't store Once implementations\n\n    const impl = () => 'unlimited'\n\n    spy.mockImplementation(impl)\n\n    spy() // returns 'unlimited'\n    spy()\n    spy()\n\n    expect(spy.getMockImplementation() === impl).toBe(true)\n\n    spy.mockReturnValue('return-unlimited')\n\n    spy()\n    spy()\n\n    expect(spy.mock.results).toEqual([\n      r('original'),\n      r('2-once'),\n      r('3-once'),\n      r('original'),\n      r('once'),\n      r('original'),\n      r('unlimited'),\n      r('unlimited'),\n      r('unlimited'),\n      r('return-unlimited'),\n      r('return-unlimited'),\n    ])\n\n    spy.mockRestore()\n\n    // Sicne Vitest 4 this is a special case where\n    // vi.fn(impl) will always return impl, unless overridden\n    expect(spy.getMockImplementation()).toBe(originalFn)\n\n    expect(spy.mock.results).toEqual([])\n  })\n\n  it('implementation async fn', async () => {\n    const originalFn = async function () {\n      return 'original'\n    }\n    const spy = vi.fn(originalFn)\n\n    await spy() // returns 'original'\n\n    spy\n      .mockResolvedValue('unlimited')\n      .mockResolvedValueOnce('3-once')\n      .mockResolvedValueOnce('4-once')\n\n    await spy()\n    await spy()\n    await spy()\n    await spy()\n\n    expect(spy.mock.settledResults).toEqual([\n      f('original'),\n      f('3-once'),\n      f('4-once'),\n      f('unlimited'),\n      f('unlimited'),\n    ])\n  })\n\n  it('invocationOrder', () => {\n    const a = vi.fn()\n    const b = vi.fn()\n\n    a()\n    b()\n\n    expect(a.mock.invocationCallOrder[0]).toBeLessThan(b.mock.invocationCallOrder[0])\n  })\n\n  it('should spy on property getter, and mockRestore should restore original descriptor', () => {\n    const obj = {\n      get getter() {\n        return 'original'\n      },\n    }\n\n    const spy = vi.spyOn(obj, 'getter', 'get')\n\n    expect(obj.getter).toBe('original')\n\n    spy.mockImplementation(() => 'mocked').mockImplementationOnce(() => 'once')\n\n    expect(obj.getter).toBe('once')\n    expect(obj.getter).toBe('mocked')\n    expect(obj.getter).toBe('mocked')\n\n    spy.mockReturnValue('returned').mockReturnValueOnce('returned-once')\n\n    expect(obj.getter).toBe('returned-once')\n    expect(obj.getter).toBe('returned')\n    expect(obj.getter).toBe('returned')\n\n    spy.mockRestore()\n\n    expect(obj.getter).toBe('original')\n    expect(spy).not.toHaveBeenCalled()\n  })\n\n  it('should spy on property getter, and mockReset should not restore original descriptor', () => {\n    const obj = {\n      get getter() {\n        return 'original'\n      },\n    }\n\n    const spy = vi.spyOn(obj, 'getter', 'get')\n\n    expect(obj.getter).toBe('original')\n\n    spy.mockImplementation(() => 'mocked').mockImplementationOnce(() => 'once')\n\n    expect(obj.getter).toBe('once')\n    expect(obj.getter).toBe('mocked')\n    expect(obj.getter).toBe('mocked')\n\n    spy.mockReturnValue('returned').mockReturnValueOnce('returned-once')\n\n    expect(obj.getter).toBe('returned-once')\n    expect(obj.getter).toBe('returned')\n    expect(obj.getter).toBe('returned')\n\n    spy.mockReset()\n\n    expect(obj.getter).toBe('original')\n    expect(spy).toHaveBeenCalled()\n  })\n\n  it('should spy on function returned from property getter', () => {\n    const obj = {\n      get getter() {\n        return function () {\n          return 'original'\n        }\n      },\n    }\n\n    const spy = vi.spyOn(obj, 'getter')\n\n    expect(obj.getter()).toBe('original')\n\n    spy.mockImplementation(() => 'mocked').mockImplementationOnce(() => 'once')\n\n    expect(obj.getter()).toBe('once')\n    expect(obj.getter()).toBe('mocked')\n    expect(obj.getter()).toBe('mocked')\n  })\n\n  it('should spy on property setter (1)', () => {\n    let setValue = 'original'\n    let mockedValue = 'none'\n\n    const obj = {\n      get setter() {\n        return setValue\n      },\n      set setter(v: any) {\n        setValue = v\n      },\n    }\n\n    const spy = vi.spyOn(obj, 'setter', 'set')\n\n    obj.setter = 'first'\n\n    expect(setValue).toBe('first')\n    expect(mockedValue).toBe('none')\n\n    spy.mockImplementation(() => (mockedValue = 'mocked')).mockImplementationOnce(() => (mockedValue = 'once'))\n\n    obj.setter = 'i can do whatever'\n    expect(mockedValue).toBe('once')\n    expect(setValue).toBe('first')\n\n    obj.setter = 'does nothing'\n    expect(mockedValue).toBe('mocked')\n    expect(setValue).toBe('first')\n\n    obj.setter = 'since setter is mocked'\n    expect(mockedValue).toBe('mocked')\n    expect(setValue).toBe('first')\n\n    spy.mockRestore()\n\n    obj.setter = 'last'\n\n    expect(spy.getMockImplementation()).toBe(undefined)\n\n    expect(setValue).toBe('last')\n  })\n\n  it('should spy on property setter (2), and mockRestore should restore original descriptor', () => {\n    const obj = {\n      _property: false,\n      set property(value) {\n        this._property = value\n      },\n      get property() {\n        return this._property\n      },\n    }\n\n    const spy = vi.spyOn(obj, 'property', 'set')\n    obj.property = true\n    expect(spy).toHaveBeenCalled()\n    expect(obj.property).toBe(true)\n    obj.property = false\n    spy.mockRestore()\n    obj.property = true\n    // like jest, mockRestore restores the original descriptor,\n    // we are not spying on the setter any more\n    expect(spy).not.toHaveBeenCalled()\n    expect(obj.property).toBe(true)\n  })\n\n  it('respyin on a spy resets the counter', () => {\n    const obj = {\n      method() {\n        return 'original'\n      },\n    }\n    vi.spyOn(obj, 'method')\n    obj.method()\n    expect(obj.method).toHaveBeenCalledTimes(1)\n    vi.spyOn(obj, 'method')\n    obj.method()\n    expect(obj.method).toHaveBeenCalledTimes(2)\n  })\n\n  it('spyOn on the getter multiple times', () => {\n    const obj = {\n      get getter() {\n        return 'original'\n      },\n    }\n\n    vi.spyOn(obj, 'getter', 'get').mockImplementation(() => 'mocked')\n    vi.spyOn(obj, 'getter', 'get')\n\n    expect(obj.getter).toBe('mocked')\n  })\n\n  it('spyOn multiple times', () => {\n    const obj = {\n      method() {\n        return 'original'\n      },\n    }\n\n    const spy1 = vi.spyOn(obj, 'method').mockImplementation(() => 'mocked')\n    const spy2 = vi.spyOn(obj, 'method')\n\n    expect(vi.isMockFunction(obj.method)).toBe(true)\n    expect(obj.method()).toBe('mocked')\n    expect(spy1).toBe(spy2)\n\n    spy2.mockImplementation(() => 'mocked2')\n\n    expect(obj.method()).toBe('mocked2')\n\n    spy2.mockRestore()\n\n    expect(obj.method()).toBe('original')\n    expect(vi.isMockFunction(obj.method)).toBe(false)\n    expect(obj.method).not.toBe(spy1)\n\n    spy1.mockRestore()\n    expect(vi.isMockFunction(obj.method)).toBe(false)\n    expect(obj.method).not.toBe(spy1)\n  })\n\n  it('restoreAllMocks in stack order', () => {\n    const obj = { foo: () => 'foo' }\n\n    vi.spyOn(obj, 'foo').mockImplementation(() => 'mocked1')\n    expect(obj.foo()).toBe('mocked1')\n    expect(vi.isMockFunction(obj.foo)).toBe(true)\n\n    vi.spyOn(obj, 'foo').mockImplementation(() => 'mocked2')\n    expect(obj.foo()).toBe('mocked2')\n    expect(vi.isMockFunction(obj.foo)).toBe(true)\n\n    vi.restoreAllMocks()\n\n    expect(obj.foo()).toBe('foo')\n    expect(vi.isMockFunction(obj.foo)).toBe(false)\n  })\n\n  it('should spy on property setter (2), and mockReset should not restore original descriptor', () => {\n    const obj = {\n      _property: false,\n      set property(value) {\n        this._property = value\n      },\n      get property() {\n        return this._property\n      },\n    }\n\n    const spy = vi.spyOn(obj, 'property', 'set')\n    obj.property = true\n    expect(spy).toHaveBeenCalled()\n    expect(obj.property).toBe(true)\n    obj.property = false\n    spy.mockReset()\n    obj.property = true\n    // unlike jest, vitest's mockReset will restore original implementation without restoring the original descriptor.\n    // We are still spying on the setter\n    expect(spy).toHaveBeenCalled()\n    expect(obj.property).toBe(true)\n  })\n\n  it('throwing', async () => {\n    const fn = vi.fn(() => {\n      // eslint-disable-next-line no-throw-literal\n      throw 'error'\n    })\n\n    try {\n      fn()\n    }\n    catch {}\n\n    expect(fn.mock.results).toEqual([\n      e('error'),\n    ])\n  })\n\n  it('mockRejectedValue', async () => {\n    const safeCall = async (fn: () => void) => {\n      try {\n        await fn()\n      }\n      catch {}\n    }\n\n    const spy = vi.fn()\n      .mockRejectedValue(new Error('error'))\n      .mockRejectedValueOnce(new Error('once'))\n\n    await safeCall(spy)\n    await safeCall(spy)\n\n    expect(spy.mock.results[0]).toEqual({\n      type: 'return',\n      value: expect.any(Promise),\n    })\n    expect(spy.mock.settledResults[0]).toEqual(h(new Error('once')))\n    expect(spy.mock.settledResults[1]).toEqual(h(new Error('error')))\n  })\n  it('mockResolvedValue', async () => {\n    const spy = vi.fn()\n      .mockResolvedValue('resolved')\n      .mockResolvedValueOnce('once')\n\n    await spy()\n    await spy()\n\n    expect(spy.mock.results[0]).toEqual({\n      type: 'return',\n      value: expect.any(Promise),\n    })\n    expect(spy.mock.settledResults[0]).toEqual(f('once'))\n    expect(spy.mock.settledResults[1]).toEqual(f('resolved'))\n  })\n\n  it('tracks instances made by mocks', () => {\n    const Fn = vi.fn()\n    expect(Fn.mock.instances).toEqual([])\n\n    const instance1 = new Fn()\n    expect(Fn.mock.instances[0]).toBe(instance1)\n\n    const instance2 = new Fn()\n    expect(Fn.mock.instances[1]).toBe(instance2)\n  })\n\n  it('.mockRestore() should restore initial implementation', () => {\n    const testFn = vi.fn(() => true)\n    expect(testFn()).toBe(true)\n\n    testFn.mockReturnValue(false)\n    expect(testFn()).toBe(false)\n\n    testFn.mockRestore()\n    expect(testFn()).toBe(true)\n  })\n\n  abstract class Dog_ {\n    public name: string\n\n    constructor(name: string) {\n      this.name = name\n    }\n\n    abstract speak(): string\n    abstract feed(): void\n  }\n\n  it('mocks constructors', () => {\n    const Dog = vi.fn<(name: string) => Dog_>(function Dog_(name: string) {\n      this.name = name\n    } as (this: any, name: string) => Dog_)\n\n    ;(Dog as any).getType = vi.fn(() => 'mocked animal')\n\n    Dog.prototype.speak = vi.fn(() => 'loud bark!')\n    Dog.prototype.feed = vi.fn()\n\n    const dogMax = new Dog('Max')\n    expect(dogMax.name).toBe('Max')\n\n    expect(dogMax.speak()).toBe('loud bark!')\n    expect(dogMax.speak).toHaveBeenCalled()\n\n    vi.mocked(dogMax.speak).mockReturnValue('woof woof')\n    expect(dogMax.speak()).toBe('woof woof')\n  })\n\n  it('mock classes', () => {\n    const Dog = vi.fn(class Dog {\n      constructor(public name: string) {\n        this.name = name\n      }\n\n      static getType: () => string = vi.fn(() => 'mocked animal')\n      speak = vi.fn(() => 'loud bark!')\n      feed = vi.fn()\n    })\n\n    const dogMax = new Dog('Max')\n    expect(dogMax.name).toBe('Max')\n\n    expect(dogMax.speak()).toBe('loud bark!')\n    expect(dogMax.speak).toHaveBeenCalled()\n\n    vi.mocked(dogMax.speak).mockReturnValue('woof woof')\n    expect(dogMax.speak()).toBe('woof woof')\n  })\n\n  it('spies on classes', () => {\n    class Example {\n      test() {}\n    }\n\n    const obj = {\n      Example,\n    }\n\n    const Spy = vi.spyOn(obj, 'Example')\n\n    Spy.mockImplementation(() => {})\n\n    expect(() => new Spy()).toThrow(TypeError)\n\n    Spy.mockImplementation(function () {\n      expectTypeOf(this.test).toEqualTypeOf<() => void>()\n      this.test = () => {}\n    })\n\n    expect(new Spy()).toBeInstanceOf(Spy)\n\n    class MockExample {\n      test() {}\n    }\n    Spy.mockImplementation(MockExample)\n\n    expect(new Spy()).toBeInstanceOf(Spy)\n    expect(new Spy()).not.toBeInstanceOf(MockExample)\n\n    const instance = new Spy()\n    expectTypeOf(instance).toEqualTypeOf<Example>()\n  })\n\n  it('returns temporary implementations from getMockImplementation()', () => {\n    const fn = vi.fn()\n\n    const temporaryMockImplementation = () => 'mocked value'\n    fn.mockImplementationOnce(temporaryMockImplementation)\n    expect(fn.getMockImplementation()).toBe(temporaryMockImplementation)\n\n    // After calling it, it should be back to undefined\n    fn()\n    expect(fn.getMockImplementation()).toBe(undefined)\n\n    const mockImplementation = () => 'other mocked value'\n    fn.mockImplementation(mockImplementation)\n    expect(fn.getMockImplementation()).toBe(mockImplementation)\n\n    // It should also overwrite permanent implementations\n    fn.mockImplementationOnce(temporaryMockImplementation)\n    expect(fn.getMockImplementation()).toBe(temporaryMockImplementation)\n  })\n\n  it('keeps the descriptor the same as the original one when restoring', () => {\n    class Foo {\n      f() {\n        return 'original'\n      }\n    }\n\n    // initially there's no own properties\n    const foo = new Foo()\n    expect(foo.f()).toMatchInlineSnapshot(`\"original\"`)\n    expect(Object.getOwnPropertyDescriptors(foo)).toMatchInlineSnapshot(`{}`)\n\n    // mocked function in own property\n    const spy = vi.spyOn(foo, 'f').mockImplementation(() => 'mocked')\n    expect(foo.f()).toMatchInlineSnapshot(`\"mocked\"`)\n    expect(Object.getOwnPropertyDescriptors(foo)).toMatchInlineSnapshot(`\n    {\n      \"f\": {\n        \"configurable\": true,\n        \"enumerable\": false,\n        \"value\": [MockFunction f] {\n          \"calls\": [\n            [],\n          ],\n          \"results\": [\n            {\n              \"type\": \"return\",\n              \"value\": \"mocked\",\n            },\n          ],\n        },\n        \"writable\": true,\n      },\n    }\n  `)\n\n    // probably original prototype method is not moved to own property\n    spy.mockRestore()\n    expect(foo.f()).toMatchInlineSnapshot(`\"original\"`)\n    expect(Object.getOwnPropertyDescriptors(foo)).toMatchInlineSnapshot(`{}`)\n  })\n\n  it('mocks inherited methods', () => {\n    class Bar {\n      _bar = 'bar'\n      get bar(): string {\n        return this._bar\n      }\n\n      set bar(bar: string) {\n        this._bar = bar\n      }\n    }\n    class Foo extends Bar {}\n    const foo = new Foo()\n    vi.spyOn(foo, 'bar', 'get').mockImplementation(() => 'foo')\n    expect(foo.bar).toEqual('foo')\n    // foo.bar setter is inherited from Bar, so we can set it\n    expect(() => {\n      foo.bar = 'baz'\n    }).not.toThrow()\n    expect(foo.bar).toEqual('foo')\n  })\n\n  it('mocks inherited overridden methods', () => {\n    class Bar {\n      _bar = 'bar'\n      get bar(): string {\n        return this._bar\n      }\n\n      set bar(bar: string) {\n        this._bar = bar\n      }\n    }\n    class Foo extends Bar {\n      get bar(): string {\n        return `${super.bar}-foo`\n      }\n    }\n    const foo = new Foo()\n    expect(foo.bar).toEqual('bar-foo')\n    vi.spyOn(foo, 'bar', 'get').mockImplementation(() => 'foo')\n    expect(foo.bar).toEqual('foo')\n    // foo.bar setter is not inherited from Bar\n    expect(() => {\n      // @ts-expect-error bar is readonly\n      foo.bar = 'baz'\n    }).toThrow()\n    expect(foo.bar).toEqual('foo')\n  })\n\n  describe('is disposable', () => {\n    describe.runIf(Symbol.dispose)('in environments supporting it', () => {\n      it('has dispose property', () => {\n        expect(vi.fn()[Symbol.dispose]).toBeTypeOf('function')\n      })\n\n      it('calls mockRestore when disposing', () => {\n        const fn = vi.fn()\n        const restoreSpy = vi.spyOn(fn, 'mockRestore')\n        {\n          using _fn2 = fn\n        }\n        expect(restoreSpy).toHaveBeenCalled()\n      })\n\n      it('allows disposal when using mockImplementation', () => {\n        expect(vi.fn().mockImplementation(() => {})[Symbol.dispose]).toBeTypeOf('function')\n      })\n    })\n\n    describe.skipIf(Symbol.dispose)('in environments not supporting it', () => {\n      it('does not have dispose property', () => {\n        expect(vi.fn()[Symbol.dispose]).toBeUndefined()\n      })\n    })\n  })\n\n  it('can spy on a partial type', () => {\n    interface Person {\n      greet?: (name: string) => string\n    }\n    const person: Person = {\n      greet: (name: string) => `Hello ${name}`,\n    }\n    vi.spyOn(person, 'greet').mockImplementation(() => 'mocked')\n    expect(person.greet!('Alice')).toBe('mocked')\n  })\n\n  describe('docs example', () => {\n    it('mockClear', () => {\n      const person = {\n        greet: (name: string) => `Hello ${name}`,\n      }\n      const spy = vi.spyOn(person, 'greet').mockImplementation(() => 'mocked')\n      expect(person.greet('Alice')).toBe('mocked')\n      expect(spy.mock.calls).toEqual([['Alice']])\n\n      // clear call history but keep mock implementation\n      spy.mockClear()\n      expect(spy.mock.calls).toEqual([])\n      expect(person.greet('Bob')).toBe('mocked')\n      expect(spy.mock.calls).toEqual([['Bob']])\n    })\n\n    it('mockReset', () => {\n      const person = {\n        greet: (name: string) => `Hello ${name}`,\n      }\n      const spy = vi.spyOn(person, 'greet').mockImplementation(() => 'mocked')\n      expect(person.greet('Alice')).toBe('mocked')\n      expect(spy.mock.calls).toEqual([['Alice']])\n\n      // clear call history and reset implementation, but method is still spied\n      spy.mockReset()\n      expect(spy.mock.calls).toEqual([])\n      expect(person.greet).toBe(spy)\n      expect(person.greet('Bob')).toBe('Hello Bob')\n      expect(spy.mock.calls).toEqual([['Bob']])\n    })\n\n    it('mockRestore', () => {\n      const person = {\n        greet: (name: string) => `Hello ${name}`,\n      }\n      const spy = vi.spyOn(person, 'greet').mockImplementation(() => 'mocked')\n      expect(person.greet('Alice')).toBe('mocked')\n      expect(spy.mock.calls).toEqual([['Alice']])\n\n      // clear call history and restore spied object method\n      spy.mockRestore()\n      expect(spy.mock.calls).toEqual([])\n      expect(person.greet).not.toBe(spy)\n      expect(person.greet('Bob')).toBe('Hello Bob')\n      expect(spy.mock.calls).toEqual([])\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/local-context.test.ts",
    "content": "import { beforeEach, describe, expect, it } from 'vitest'\n\ndescribe('local test context works with explicit type', () => {\n  interface LocalTestContext {\n    foo: string\n  }\n  beforeEach<LocalTestContext>((context) => {\n    context.foo = 'foo'\n  })\n  it<LocalTestContext>('works with explicit type', (context) => {\n    expect(context.foo).toBe('foo')\n  })\n  it.todo.skip<LocalTestContext>('is chainable with explicit type', (context) => {\n    expect(context.foo).toBe('foo')\n  })\n})\n\ndescribe('local test context works with implicit type', () => {\n  interface LocalTestContext {\n    bar: string\n  }\n  beforeEach((context: LocalTestContext) => {\n    context.bar = 'bar'\n  })\n  it('works with implicit type', (context: LocalTestContext) => {\n    expect(context.bar).toBe('bar')\n  })\n  it('is chainable with implicit type', (context: LocalTestContext) => {\n    expect(context.bar).toBe('bar')\n  })\n})\n\ndescribe('context expect', () => {\n  it('has snapshotState', ({ expect: localExpect }) => {\n    expect(expect.getState().snapshotState).toBeDefined()\n    expect(localExpect.getState().snapshotState).toBeDefined()\n  })\n})\n\ndescribe('custom matcher are inherited by local context', () => {\n  expect.extend({\n    toEqual_testCustom(received, expected) {\n      return {\n        pass: received === expected,\n        message: () => `test`,\n      }\n    },\n  })\n\n  it('basic', ({ expect: localExpect }) => {\n    // as assertion\n    expect(expect('test')).toHaveProperty('toEqual_testCustom')\n    expect(expect.soft('test')).toHaveProperty('toEqual_testCustom')\n    expect(localExpect('test')).toHaveProperty('toEqual_testCustom')\n    expect(localExpect.soft('test')).toHaveProperty('toEqual_testCustom')\n\n    // as asymmetric matcher\n    expect(expect).toHaveProperty('toEqual_testCustom')\n    expect(expect.not).toHaveProperty('toEqual_testCustom')\n    expect(localExpect).toHaveProperty('toEqual_testCustom')\n    expect(localExpect.not).toHaveProperty('toEqual_testCustom');\n\n    (expect(0) as any).toEqual_testCustom(0);\n    (expect(0) as any).not.toEqual_testCustom(1);\n    (localExpect(0) as any).toEqual_testCustom(0);\n    (localExpect(0) as any).not.toEqual_testCustom(1)\n\n    expect(0).toEqual((expect as any).toEqual_testCustom(0))\n    localExpect(0).toEqual((localExpect as any).toEqual_testCustom(0))\n    expect(0).toEqual((expect.not as any).toEqual_testCustom(1))\n    localExpect(0).toEqual((localExpect.not as any).toEqual_testCustom(1))\n\n    // asymmetric matcher function is identical\n    expect((expect as any).toEqual_testCustom).toBe((localExpect as any).toEqual_testCustom)\n    expect((expect.not as any).toEqual_testCustom).toBe((localExpect.not as any).toEqual_testCustom)\n  })\n})\n"
  },
  {
    "path": "test/core/test/lot-of-tests.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\nconst SUITES = 50\nconst TASKS = 10\n\ndescribe(`Suite of ${SUITES * TASKS} tests for UI performance tests`, () => {\n  if (!process.env.CI) {\n    for (let i = 1; i <= SUITES; i++) {\n      describe(`Test UI nested describe ${i}`, () => {\n        for (let j = 1; j <= TASKS; j++) {\n          it(`Test UI it ${i}-${j}`, () => {\n            expect(true).toBe(true)\n          })\n        }\n      })\n    }\n  }\n  else {\n    it('skipped in ci', () => {})\n  }\n})\n"
  },
  {
    "path": "test/core/test/math.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('sum', () => {\n  expect(1 + 1).toBe(2)\n})\n\ntest('multiply', () => {\n  expect(1 * 2).toBe(2)\n})\n"
  },
  {
    "path": "test/core/test/memory-limit.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { getWorkerMemoryLimit } from 'vitest/src/utils/memory-limit.js'\n\ndescribe('getWorkerMemoryLimit', () => {\n  it('should prioritize vmMemoryLimit', () => {\n    expect(getWorkerMemoryLimit({ vmMemoryLimit: '512MB', maxWorkers: 1, watch: false })).toBe('512MB')\n  })\n\n  it('should calculate 1/maxWorkers', () => {\n    expect(getWorkerMemoryLimit({ maxWorkers: 4, watch: false })).toBe(1 / 4)\n  })\n\n  it('should calculate maxWorkers/2 when in watch-mode', () => {\n    expect(getWorkerMemoryLimit({ maxWorkers: 14, watch: true })).toBe(1 / 14)\n  })\n})\n"
  },
  {
    "path": "test/core/test/mock-fs.test.ts",
    "content": "import { fs, vol } from 'memfs'\n// hello-world.test.js\nimport { beforeEach, expect, it, vi } from 'vitest'\nimport { readHelloWorld } from '../src/read-hello-world'\n\n// tell vitest to use fs mock from __mocks__ folder\n// this can be done in a setup file if fs should always be mocked\nvi.mock('node:fs')\nvi.mock('node:fs/promises')\n\nbeforeEach(() => {\n  // reset the state of in-memory fs\n  vol.reset()\n})\n\nit('should return correct text', () => {\n  const path = '/hello-world.txt'\n  fs.writeFileSync(path, 'hello world')\n\n  const text = readHelloWorld(path)\n  expect(text).toBe('hello world')\n})\n\nit('can return a value multiple times', () => {\n  // you can use vol.fromJSON to define several files\n  vol.fromJSON(\n    {\n      './dir1/hw.txt': 'hello dir1',\n      './dir2/hw.txt': 'hello dir2',\n    },\n    // default cwd\n    '/tmp',\n  )\n\n  expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1')\n  expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2')\n})\n"
  },
  {
    "path": "test/core/test/mock-internals.test.ts",
    "content": "import type { MockInstance } from 'vitest'\nimport childProcess, { exec } from 'node:child_process'\nimport timers from 'node:timers'\nimport { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { dynamicImport } from '../src/dynamic-import'\nimport { execDefault, execHelloWorld, execImportAll } from '../src/exec'\n\nvi.mock('child_process')\nvi.mock('timers') // node built in inside __mocks__\n\ntest('node internal is mocked', () => {\n  execHelloWorld()\n  expect(exec).toHaveBeenCalledWith('hello world')\n\n  execImportAll()\n  expect(exec).toHaveBeenCalledWith('import all')\n\n  execDefault()\n  expect(childProcess.exec).toHaveBeenCalledWith('default')\n})\n\ntest('builtin is mocked with __mocks__ folder', () => {\n  expect(timers.clearInterval(undefined)).toBe('foo')\n})\n\ntest('mocked dynamically imported packages', async () => {\n  const mod = await dynamicImport('timers')\n  expect(mod).toHaveProperty('default')\n  expect(mod.default).toHaveProperty('clearInterval')\n  expect(mod.default.clearInterval()).toBe('foo')\n})\n\ndescribe('Math.random', () => {\n  describe('mock is restored', () => {\n    let spy: MockInstance\n\n    beforeEach(() => {\n      spy = vi.spyOn(Math, 'random').mockReturnValue(0.1)\n    })\n    afterEach(() => {\n      spy.mockRestore()\n    })\n\n    test('is mocked', () => {\n      expect(Math.random()).toBe(0.1)\n    })\n  })\n\n  // This used to make dependencies stuck, e.g. birpc\n  describe('mock is not restored and leaks', () => {\n    beforeEach(() => {\n      vi.spyOn(Math, 'random').mockReturnValue(0.1)\n    })\n\n    test('is mocked', () => {\n      expect(Math.random()).toBe(0.1)\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/mocked-circular.test.ts",
    "content": "import { expect, it, vi } from 'vitest'\n\nimport { circularA } from '../src/circularA'\n// The order of the two imports here matters: B before A\nimport { circularB } from '../src/circularB'\n\nvi.mock('../src/circularB')\n\nit('circular', () => {\n  circularA()\n\n  expect(circularB).toHaveBeenCalledOnce()\n})\n"
  },
  {
    "path": "test/core/test/mocked-class-restore-all.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\nimport { MockedE } from '../src/mockedE'\n\nvi.mock('../src/mockedE')\n\ntest(`mocked class are not affected by restoreAllMocks`, () => {\n  const instance0 = new MockedE()\n  expect(instance0.testFn('a')).toMatchInlineSnapshot(`undefined`)\n  expect(vi.mocked(instance0.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n    ]\n  `)\n\n  vi.restoreAllMocks()\n\n  // reset only history after restoreAllMocks\n  expect(instance0.testFn('b')).toMatchInlineSnapshot(`undefined`)\n  expect(vi.mocked(instance0.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n      [\n        \"b\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n      [\n        \"b\",\n      ],\n    ]\n  `)\n\n  // mocked constructor is still effective after restoreAllMocks\n  const instance1 = new MockedE()\n  const instance2 = new MockedE()\n  expect(instance1).not.toBe(instance2)\n  expect(instance1.testFn).not.toBe(instance2.testFn)\n  expect(instance1.testFn).not.toBe(MockedE.prototype.testFn)\n  expect(vi.mocked(instance1.testFn).mock).not.toBe(vi.mocked(instance2.testFn).mock)\n\n  expect(instance1.testFn('c')).toMatchInlineSnapshot(`undefined`)\n  expect(vi.mocked(instance0.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n      [\n        \"b\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"c\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(instance2.testFn).mock.calls).toMatchInlineSnapshot(`[]`)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n      [\n        \"b\",\n      ],\n      [\n        \"c\",\n      ],\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/core/test/mocked-class-restore-explicit.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\nimport { MockedE } from '../src/mockedE'\n\nvi.mock('../src/mockedE')\n\n// this behavior looks odd but jest also doesn't seem to support this use case properly\ntest(`mocked class methods are not restorable by explicit mockRestore calls`, () => {\n  const instance1 = new MockedE()\n\n  expect(instance1.testFn('a')).toMatchInlineSnapshot(`undefined`)\n  expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n    ]\n  `)\n\n  // restoring instance method\n  vi.mocked(instance1.testFn).mockRestore()\n  expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(`[]`)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n    ]\n  `)\n\n  expect(instance1.testFn('b')).toMatchInlineSnapshot(`undefined`)\n  expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"b\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n      [\n        \"b\",\n      ],\n    ]\n  `)\n\n  // restoring prototype method\n  vi.mocked(MockedE.prototype.testFn).mockRestore()\n  expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"b\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`[]`)\n\n  expect(instance1.testFn('c')).toMatchInlineSnapshot(`undefined`)\n  expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"b\",\n      ],\n      [\n        \"c\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"c\",\n      ],\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/core/test/mocked-class.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\nimport { MockedE, symbolFn } from '../src/mockedE'\n\nvi.mock('../src/mockedE')\n\ntest(`each instance's methods of mocked class should have independent mock function state`, () => {\n  const instance1 = new MockedE()\n  const instance2 = new MockedE()\n  expect(instance1).not.toBe(instance2)\n  expect(instance1.testFn).not.toBe(instance2.testFn)\n  expect(instance1.testFn).not.toBe(MockedE.prototype.testFn)\n  expect(vi.mocked(instance1.testFn).mock).not.toBe(vi.mocked(instance2.testFn).mock)\n\n  expect(instance1.testFn('a')).toMatchInlineSnapshot(`undefined`)\n  expect(instance1.testFn).toBeCalledTimes(1)\n  expect(instance2.testFn).toBeCalledTimes(0)\n  expect(MockedE.prototype.testFn).toBeCalledTimes(1)\n  expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n    ]\n  `)\n\n  expect(instance2.testFn('b')).toMatchInlineSnapshot(`undefined`)\n  expect(instance1.testFn).toBeCalledTimes(1)\n  expect(instance2.testFn).toBeCalledTimes(1)\n  expect(MockedE.prototype.testFn).toBeCalledTimes(2)\n  expect(vi.mocked(instance2.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"b\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n      [\n        \"b\",\n      ],\n    ]\n  `)\n\n  expect(instance1.testFn('c')).toMatchInlineSnapshot(`undefined`)\n  expect(instance1.testFn).toBeCalledTimes(2)\n  expect(instance2.testFn).toBeCalledTimes(1)\n  expect(MockedE.prototype.testFn).toBeCalledTimes(3)\n  expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n      [\n        \"c\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(instance2.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"b\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"a\",\n      ],\n      [\n        \"b\",\n      ],\n      [\n        \"c\",\n      ],\n    ]\n  `)\n\n  // test same things for symbol key method\n  expect(instance1[symbolFn]).not.toBe(instance2[symbolFn])\n  expect(instance1[symbolFn]).not.toBe(MockedE.prototype[symbolFn])\n  expect(vi.mocked(instance1[symbolFn]).mock).not.toBe(vi.mocked(instance2[symbolFn]).mock)\n\n  expect(instance1[symbolFn]('d')).toMatchInlineSnapshot(`undefined`)\n  expect(instance1[symbolFn]).toBeCalledTimes(1)\n  expect(instance2[symbolFn]).toBeCalledTimes(0)\n  expect(MockedE.prototype[symbolFn]).toBeCalledTimes(1)\n  expect(vi.mocked(instance1[symbolFn]).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"d\",\n      ],\n    ]\n  `)\n  expect(vi.mocked(instance2[symbolFn]).mock.calls).toMatchInlineSnapshot(`[]`)\n  expect(vi.mocked(MockedE.prototype[symbolFn]).mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"d\",\n      ],\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/core/test/mocked-import-circular.test.ts",
    "content": "import { expect, it, vi } from 'vitest'\n\nimport { circularA } from '../src/circularA'\n// The order of the two imports here matters: B before A\nimport { circularB } from '../src/circularB'\n\nvi.mock(import('../src/circularB'))\n\nit('circular', () => {\n  circularA()\n\n  expect(circularB).toHaveBeenCalledOnce()\n})\n"
  },
  {
    "path": "test/core/test/mocked-no-mocks-same.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { mockedA } from '../src/mockedA'\n\nvi.mock('../src/mockedA.ts')\n\ntest('testing mocking module without __mocks__ - suites don\\'t conflict', () => {\n  mockedA()\n\n  expect(mockedA).toHaveBeenCalledTimes(1)\n})\n"
  },
  {
    "path": "test/core/test/mocked-no-mocks.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { mockedA } from '../src/mockedA'\nimport { mockedB } from '../src/mockedB'\n\nvi.mock('../src/mockedA.ts')\nvi.mock('../src/mockedB.ts')\n\ntest('testing mocking module without __mocks__', () => {\n  mockedA()\n  expect(mockedA).toHaveBeenCalledTimes(1)\n})\n\ntest('mocking several modules work', () => {\n  vi.mocked(mockedB).mockRestore()\n\n  mockedB()\n\n  // mockedA is not called because mockedB is restored to be undefined\n  expect(mockedA).toHaveBeenCalledTimes(1)\n  expect(mockedB).toHaveBeenCalledTimes(1)\n})\n"
  },
  {
    "path": "test/core/test/mocked-node-module.test.ts",
    "content": "/* eslint-disable unicorn/prefer-node-protocol */\n\nimport fs from 'fs/promises'\nimport { expect, test, vi } from 'vitest'\n\nvi.mock(import('fs/promises'), async (importOriginal) => {\n  const { default: original } = await importOriginal()\n  return {\n    default: {\n      ...original,\n      readFile: vi.fn(),\n    },\n  }\n})\n\ntest('fs is defined when node: prefix is not used', () => {\n  expect(vi.isMockFunction(fs.readFile)).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/mocked-public-key.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { dynamicImport } from '../src/dynamic-import'\n\nvi.mock('test', () => {\n  return {\n    foo: 'foo',\n  }\n})\n\ntest('testing toMatchObject for mocking module', async () => {\n  const result = await dynamicImport('test')\n  expect(result).toMatchObject({\n    foo: 'foo',\n  })\n})\n"
  },
  {
    "path": "test/core/test/mocked.test.js",
    "content": "/* eslint-disable no-unused-vars */\n// this file should not be converted to ts\n// so it won't be transformed by esbuild\n\nimport { assert, test, vi } from 'vitest'\nimport { two } from '../src/submodule'\nimport { timeout } from '../src/timeout'\n\n/*\n    vi.mock('../src/timeout', () => ({ timeout: 0 }))\n /* */\n\n// vi.mock('../src/timeout', () => ({ timeout: 0 }))\n\nconst _text = `\n  vi.mock('../src/timeout', () => ({ timeout: 0 }))\n`\n\nconst _textComment = `\n  vi.mock('../src/timeout', () => ({ timeout: 0 }))\n  /**\n    vi.mock('../src/timeout', () => ({ timeout: 0 }))\n    vi.mock('../src/timeout', () => ({ timeout: 0 }))\n  */\n`\n\nvi.mock(\n  '../src/submodule',\n  () => ({\n    two: 55,\n  }),\n)\n\n// vi.mock('../src/submodule')\n\ntest('vitest correctly passes multiline vi.mock syntax', () => {\n  assert.equal(55, two)\n  assert.equal(100, timeout)\n})\n"
  },
  {
    "path": "test/core/test/mocked.test.ts",
    "content": "import { stripVTControlCharacters } from 'node:util'\n// @ts-expect-error not typed module\nimport { value as virtualValue } from 'virtual-module'\nimport { assert, describe, expect, test, vi, vitest } from 'vitest'\nimport * as globalMock from '../src/global-mock'\nimport * as mocked from '../src/mockedA'\nimport { mockedB } from '../src/mockedB'\nimport { asyncFunc, exportedStream, MockedC } from '../src/mockedC'\nimport MockedDefault, { MockedC as MockedD } from '../src/mockedD'\nimport { two } from '../src/submodule'\n\nvitest.mock('../src/submodule')\nvitest.mock('virtual-module', () => ({ value: 'mock' }))\nvitest.mock('../src/mockedC')\nvitest.mock('../src/mockedD')\n\n/**\n * Get a property descriptor from an object.\n *\n * This is different from `Object.getOwnPropertyDescriptor` because it recurses\n * into the prototype chain until it either finds a match or reaches the end.\n *\n * @param object The object that contains the property.\n * @param property The property.\n * @returns The property's descriptor, or undefined if no matching property was found.\n */\nfunction getPropertyDescriptor(object: any, property: PropertyKey) {\n  for (let o = object; o; o = Object.getPrototypeOf(o)) {\n    const descriptor = Object.getOwnPropertyDescriptor(o, property)\n    if (descriptor) {\n      return descriptor\n    }\n  }\n  return undefined\n}\n\ntest('submodule is mocked to return \"two\" as 3', () => {\n  assert.equal(3, two)\n})\n\ntest('globally mocked files are mocked', () => {\n  // Mocked in setup.ts\n  expect(globalMock.mocked).toBe(true)\n})\n\ntest('can mock esm', () => {\n  const spy = vi.spyOn(mocked, 'mockedA')\n\n  mockedB()\n\n  expect(spy).toHaveBeenCalled()\n  expect(spy).toHaveReturnedWith('A')\n})\n\ntest('mocked exports should override original exports', () => {\n  expect(virtualValue).toBe('mock')\n})\n\ndescribe('mocked classes', () => {\n  test('should not delete the prototype', () => {\n    expect(MockedC).toBeTypeOf('function')\n    expect(MockedC.prototype.doSomething).toBeTypeOf('function')\n    expect(MockedC.prototype.constructor).toBe(MockedC)\n  })\n\n  test('should mock the constructor', () => {\n    const instance = new MockedC()\n\n    expect(instance.value).not.toBe(42)\n    expect(MockedC).toHaveBeenCalledOnce()\n  })\n\n  test('should mock functions in the prototype', () => {\n    const instance = new MockedC()\n\n    expect(instance.doSomething).toBeTypeOf('function')\n    expect(instance.doSomething()).not.toBe('A')\n\n    expect(MockedC.prototype.doSomething).toHaveBeenCalledOnce()\n    expect(MockedC.prototype.doSomething).not.toHaveReturnedWith('A')\n\n    vi.mocked(instance.doSomething).mockRestore()\n    expect(instance.doSomething()).not.toBe('A')\n  })\n\n  test('should mock getters', () => {\n    const instance = new MockedC()\n\n    expect(instance).toHaveProperty('getOnlyProp')\n    const descriptor = getPropertyDescriptor(instance, 'getOnlyProp')\n    expect(descriptor?.get).toBeDefined()\n    expect(descriptor?.set).not.toBeDefined()\n\n    expect(instance.getOnlyProp).toBe(undefined)\n    // @ts-expect-error Assign to the read-only prop to ensure it errors.\n    expect(() => instance.getOnlyProp = 4).toThrow()\n\n    const getterSpy = vi.spyOn(instance, 'getOnlyProp', 'get').mockReturnValue(456)\n    expect(instance.getOnlyProp).toEqual(456)\n    expect(getterSpy).toHaveBeenCalledOnce()\n  })\n\n  test('should mock getters and setters', () => {\n    const instance = new MockedC()\n\n    expect(instance).toHaveProperty('getSetProp')\n    const descriptor = getPropertyDescriptor(instance, 'getSetProp')\n    expect(descriptor?.get).toBeDefined()\n    expect(descriptor?.set).toBeDefined()\n\n    expect(instance.getSetProp).toBe(undefined)\n    expect(() => instance.getSetProp = 4).not.toThrow()\n\n    const getterSpy = vi.spyOn(instance, 'getSetProp', 'get').mockReturnValue(789)\n    expect(instance.getSetProp).toEqual(789)\n    expect(getterSpy).toHaveBeenCalledOnce()\n\n    const setterSpy = vi.spyOn(instance, 'getSetProp', 'set')\n    instance.getSetProp = 159\n    expect(setterSpy).toHaveBeenCalledWith(159)\n  })\n})\n\ndescribe('default exported classes', () => {\n  test('should preserve equality for re-exports', () => {\n    expect(MockedDefault).toEqual(MockedD)\n  })\n\n  test('should preserve prototype', () => {\n    expect(MockedDefault.prototype.constructor).toBe(MockedDefault)\n    expect(MockedD.prototype.constructor).toBe(MockedD)\n  })\n})\n\ntest('async functions should be mocked', async () => {\n  expect(asyncFunc()).toBeUndefined()\n  expect(vi.mocked(asyncFunc).mockResolvedValue).toBeDefined()\n  vi.mocked(asyncFunc).mockResolvedValue('foo')\n  await expect(asyncFunc()).resolves.toBe('foo')\n})\n\nfunction getError(cb: () => void): string {\n  try {\n    cb()\n  }\n  catch (e: any) {\n    return stripVTControlCharacters(e.message)\n  }\n  expect.unreachable()\n  return 'unreachable'\n}\n\ndescribe('mocked function which fails on toReturnWith', () => {\n  test('zero call', () => {\n    const mock = vi.fn(() => 1)\n    expect(getError(() => expect(mock).toReturnWith(2))).toMatchSnapshot()\n  })\n\n  test('just one call', () => {\n    const mock = vi.fn(() => 1)\n    mock()\n    expect(getError(() => expect(mock).toReturnWith(2))).toMatchSnapshot()\n  })\n\n  test('multi calls', () => {\n    const mock = vi.fn(() => 1)\n    mock()\n    mock()\n    mock()\n    expect(getError(() => expect(mock).toReturnWith(2))).toMatchSnapshot()\n  })\n\n  test('oject type', () => {\n    const mock = vi.fn(() => {\n      return { a: '1' }\n    })\n    mock()\n    mock()\n    mock()\n    expect(getError(() => expect(mock).toReturnWith({ a: '4' }))).toMatchSnapshot()\n  })\n})\n\n// This is here because mocking streams previously caused some problems (#1671).\ntest('streams', () => {\n  expect(exportedStream).toBeDefined()\n})\n\ndescribe('temporary mock implementation', () => {\n  test('temporary mock implementation works as expected', () => {\n    const mock = vi.fn(() => 1)\n\n    expect.assertions(3)\n\n    mock.withImplementation(() => 2, () => {\n      expect(mock()).toBe(2)\n      expect(mock()).toBe(2)\n    })\n\n    expect(mock()).toBe(1)\n  })\n\n  test('original implementation restored as undefined, when there is none', () => {\n    const mock = vi.fn()\n\n    expect.assertions(5)\n\n    mock.withImplementation(() => 2, () => {\n      expect(mock.getMockImplementation()).toBeTypeOf('function')\n      expect(mock()).toBe(2)\n      expect(mock()).toBe(2)\n    })\n\n    expect(mock()).toBe(undefined)\n    expect(mock.getMockImplementation()).toBe(undefined)\n  })\n\n  test('temporary mock implementation return value can be of different type than the original', async () => {\n    const mock = vi.fn(() => 1)\n\n    expect.assertions(3)\n\n    mock.withImplementation(() => 2, () => {\n      expect(mock()).toBe(2)\n      expect(mock()).toBe(2)\n    })\n\n    expect(mock()).toBe(1)\n  })\n\n  test('temporary mock implementation with async callback works as expected', async () => {\n    const mock = vi.fn(() => 1)\n\n    expect.assertions(3)\n\n    await mock.withImplementation(() => 2, async () => {\n      await Promise.resolve()\n\n      expect(mock()).toBe(2)\n      expect(mock()).toBe(2)\n    })\n\n    expect(mock()).toBe(1)\n  })\n\n  test('temporary mock implementation can be async', async () => {\n    const mock = vi.fn(async () => 1)\n\n    expect.assertions(3)\n\n    await mock.withImplementation(async () => 2, async () => {\n      expect(await mock()).toBe(2)\n      expect(await mock()).toBe(2)\n    })\n\n    expect(await mock()).toBe(1)\n  })\n\n  test('temporary mock implementation takes precedence over mockImplementationOnce', () => {\n    const mock = vi.fn(() => 1)\n\n    expect.assertions(3)\n\n    mock.mockImplementationOnce(() => 2)\n    mock.withImplementation(() => 3, () => {\n      expect(mock()).toBe(3)\n      expect(mock()).toBe(3)\n    })\n\n    expect(mock()).toBe(2)\n  })\n})\n"
  },
  {
    "path": "test/core/test/mocking/already-hoisted.test.ts",
    "content": "vi.mock('node:path', () => ({ mocked: true }))\n\nimport { expect, test, vi } from 'vitest'\n\nimport * as path from 'node:path'\n\ntest('already hoisted', () => {\n  expect(path).toHaveProperty('mocked', true)\n})\n"
  },
  {
    "path": "test/core/test/mocking/automocking-class-inheritence.test.ts",
    "content": "// bar.spec.ts\nimport { describe, expect, it, vi } from 'vitest'\nimport { Bar } from '../../src/class-inheritence/bar'\n\nvi.mock(import('./../../src/class-inheritence/foo'))\n\ndescribe('not mocking class when parent is mocked', () => {\n  describe('doSomething', () => {\n    it('returns true', () => {\n      const bar = new Bar()\n      expect(bar.doSomething()).toBe(true)\n    })\n\n    it('should match the prototype', () => {\n      const bar = new Bar()\n      expect(bar.doSomething).toBe(Bar.prototype.doSomething)\n    })\n\n    it('should not be mocked', () => {\n      const bar = new Bar()\n      expect(bar.doSomething).not.toHaveProperty('mock')\n    })\n  })\n\n  describe('doSomethingElse', () => {\n    it('returns true', () => {\n      const bar = new Bar()\n      expect(bar.doSomethingElse()).toBe(true)\n    })\n\n    it('should match the prototype', () => {\n      const bar = new Bar()\n      expect(bar.doSomethingElse).toBe(Bar.prototype.doSomethingElse)\n    })\n\n    it('should not be mocked', () => {\n      const bar = new Bar()\n      expect(bar.doSomethingElse).not.toHaveProperty('mock')\n    })\n  })\n})\n\ndescribe('mocking class when parent is not mocked', () => {\n  it('mocks correctly', () => {\n    class Bar {\n      doSomething() {}\n    }\n\n    const Zoo = vi.mockObject(class Zoo extends Bar {\n      ownMethod() {}\n    })\n\n    const zoo = new Zoo()\n    expect(vi.isMockFunction(zoo.doSomething)).toBe(true)\n    expect(vi.isMockFunction(zoo.ownMethod)).toBe(true)\n  })\n})\n"
  },
  {
    "path": "test/core/test/mocking/automocking.spec.ts",
    "content": "import type * as exampleModule from '../../src/mocks/example'\nimport { expect, test, vi } from 'vitest'\nimport log from '../../src/mocks/log'\nimport { A } from '../../src/mocks/moduleA'\nimport { methodSymbol, moduleWithSymbol } from '../../src/mocks/moduleWithSymbol'\n\nvi.mock('../../src/mocks/log')\nvi.mock('../../src/mocks/moduleA')\nvi.mock('../../src/mocks/moduleWithSymbol')\n\ntest('all mocked are valid', async () => {\n  const example = await vi.importMock<typeof exampleModule>('../../src/mocks/example')\n\n  // creates a new mocked function with no formal arguments.\n  expect(example.square.name).toEqual('square')\n  expect(example.square.length).toEqual(2)\n\n  // async functions get the same treatment as standard synchronous functions.\n  expect(example.asyncSquare.name).toEqual('asyncSquare')\n  expect(example.asyncSquare.length).toEqual(2)\n\n  // creates a new class with the same interface, member functions and properties are mocked.\n  expect(example.someClasses.constructor.name).toEqual('Bar')\n  expect(example.someClasses.foo.name).toEqual('foo')\n  expect(vi.isMockFunction(example.someClasses.foo)).toBe(true)\n  expect(example.someClasses.array.length).toEqual(0)\n\n  // creates a deeply cloned version of the original object.\n  expect(example.object).toEqual({\n    baz: 'foo',\n    bar: {\n      fiz: 1,\n      buzz: [],\n    },\n  })\n\n  // creates a new empty array, ignoring the original array.\n  expect(example.array.length).toEqual(0)\n\n  // creates a new property with the same primitive value as the original property.\n  expect(example.number).toEqual(123)\n  expect(example.string).toEqual('baz')\n  expect(example.boolean).toEqual(true)\n  expect(example.symbol).toEqual(Symbol.for('a.b.c'))\n})\n\ntest('automock properly restores mock', async () => {\n  expect(log.warn()).toBeUndefined()\n  expect(moduleWithSymbol.warn()).toBeUndefined()\n  expect(moduleWithSymbol[methodSymbol]()).toBeUndefined()\n\n  expect(log.warn).toHaveProperty('mockImplementation')\n\n  vi.restoreAllMocks()\n\n  expect(() => {\n    log.warn()\n  }).not.toThrow()\n\n  expect(moduleWithSymbol[methodSymbol]()).toBe(undefined)\n  expect(moduleWithSymbol.warn()).toBe(undefined)\n\n  expect(log.warn).toHaveProperty('mockImplementation')\n})\n\ntest('automock has a getter', () => {\n  expect(A).toBe('A')\n})\n"
  },
  {
    "path": "test/core/test/mocking/autospying.test.ts",
    "content": "import axios from 'axios'\nimport { expect, test, vi } from 'vitest'\nimport { getAuthToken } from '../../src/env'\nimport * as NamespaceModule from '../../src/mocks/autospying-namespace/index.js'\n\nvi.mock(import('../../src/env'), { spy: true })\n\nvi.mock('axios', { spy: true })\nvi.mock('../../src/mocks/autospying-namespace/index.js', { spy: true })\n\ntest('getAuthToken is spied', async () => {\n  import.meta.env.AUTH_TOKEN = '123'\n  const token = getAuthToken()\n  expect(token).toBe('123')\n  expect(getAuthToken).toHaveBeenCalledTimes(1)\n  vi.mocked(getAuthToken).mockRestore()\n  // module mocks cannot be restored\n  expect(vi.isMockFunction(getAuthToken)).toBe(true)\n})\n\ntest('package in __mocks__ has lower priority', async () => {\n  expect(vi.isMockFunction(axios.get)).toBe(true)\n\n  // isAxiosError is not defined in __mocks__\n  expect(axios.isAxiosError(new Error('test'))).toBe(false)\n  expect(axios.isAxiosError).toHaveBeenCalled()\n})\n\ntest('spies on namespace re-exports', async () => {\n  expect(vi.isMockFunction(NamespaceModule.NamespaceTarget.computeSquare)).toBe(true)\n  expect(NamespaceModule.NamespaceTarget.computeSquare(5)).toBe(25)\n  expect(NamespaceModule.NamespaceTarget.computeSquare).toHaveBeenCalledTimes(1)\n})\n"
  },
  {
    "path": "test/core/test/mocking/axios-mocked.test.ts",
    "content": "import axios from 'axios'\nimport { expect, test, vi } from 'vitest'\n\nvi.mock('axios')\n\ntest('mocked axios', async () => {\n  await axios.get('string')\n\n  expect(axios.get).toHaveBeenCalledWith('string')\n  expect(axios.post).toBeUndefined()\n})\n\ntest('can get actual axios', async () => {\n  const ax = await vi.importActual<typeof axios>('axios')\n\n  expect(vi.isMockFunction(ax.get)).toBe(false)\n})\n"
  },
  {
    "path": "test/core/test/mocking/axios-not-mocked.test.ts",
    "content": "import axios from 'axios'\nimport { expect, test, vi } from 'vitest'\n\ntest('mocked axios', async () => {\n  const { default: ax } = await vi.importMock<any>('axios')\n\n  await ax.get('string')\n\n  expect(ax.get).toHaveBeenCalledWith('string')\n})\n\ntest('actual axios is not mocked', async () => {\n  expect(vi.isMockFunction(axios.get)).toBe(false)\n})\n"
  },
  {
    "path": "test/core/test/mocking/circular-mocks.spec.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport x from '../../src/mocks/export-default-circle-index.js'\n// @ts-expect-error not typed\nimport { main, mainB } from '../../src/mocks/main.js'\n\nvi.mock('../../src/mocks/A', async () => ({\n  ...(await vi.importActual<any>('../../src/mocks/A')),\n  funcA: () => 'mockedA',\n}))\n\nvi.mock('../../src/mocks/B', async () => ({\n  ...(await vi.importActual<any>('../../src/mocks/B')),\n  funcB: () => 'mockedB',\n}))\n\nvi.mock('../../src/mocks/export-default-circle-b')\n\ntest('can import actual inside mock factory', () => {\n  expect(main()).toBe('mockedA')\n})\n\ntest('can import in top level and inside mock factory', () => {\n  expect(mainB()).toBe('mockedB')\n})\n\ntest('can mock a circular dependency', () => {\n  expect(x()).toBe(undefined)\n})\n"
  },
  {
    "path": "test/core/test/mocking/custom-module-directory.spec.ts",
    "content": "// @ts-expect-error not typed aliased import\nimport getState from 'custom-lib'\nimport { expect, it, vi } from 'vitest'\n\nvi.mock('custom-lib')\n\nit('state is mocked', () => {\n  expect(getState()).toBe('mocked')\n})\n"
  },
  {
    "path": "test/core/test/mocking/cyclic-import-actual.spec.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\nimport '../../src/mocks/cyclic-deps/module-1'\n\nvi.mock('../../src/mocks/cyclic-deps/module-2', async () => {\n  await vi.importActual('../../src/mocks/cyclic-deps/module-2')\n\n  return { default: () => {} }\n})\n\ntest('some test', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/core/test/mocking/cyclic-import-original.spec.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\nimport '../../src/mocks/cyclic-deps/module-1'\n\nvi.mock('../../src/mocks/cyclic-deps/module-2', async (importOriginal) => {\n  await importOriginal()\n\n  return { default: () => {} }\n})\n\ntest('some test', () => {\n  expect(1 + 1).toBe(2)\n})\n"
  },
  {
    "path": "test/core/test/mocking/destructured.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { foo } from '../../src/mocks/set-foo.js'\n// @ts-expect-error mocked module\nimport * as squaredModule from '../../src/mocks/squared'\n// @ts-expect-error mocked module\nimport { squared } from '../../src/mocks/squared'\n\nvi.mock('any')\n\ntest('spyOn entire module', () => {\n  vi.spyOn(squaredModule, 'squared')\n  expect(squared).not.toHaveBeenCalled()\n})\n\ntest('foo should be 1', () => {\n  expect(foo).toBe(1)\n})\n"
  },
  {
    "path": "test/core/test/mocking/error-mock.spec.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\nvi.mock('../../src/mocks/default', () => {\n  throw new Error('some error')\n})\n\ntest('when using top level variable, gives helpful message', async () => {\n  await expect(() => import('../../src/mocks/default').then(m => m.default)).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: [vitest] There was an error when mocking a module. If you are using \"vi.mock\" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock]`)\n})\n"
  },
  {
    "path": "test/core/test/mocking/external.test.ts",
    "content": "/* eslint-disable perfectionist/sort-imports */\nimport { expect, test, vi } from 'vitest'\nimport '../../src/mocks/external/external.mjs'\nimport axios from 'axios'\n// @ts-expect-error mocked module\nimport defaultFunc from '../../src/mocks/external/default-function.cjs'\n\nvi.mock('../../src/mocks/external/default-function.cjs')\n\ntest('axios is mocked', () => {\n  expect(vi.isMockFunction(axios.get)).toBe(true)\n})\n\ntest('defaultFunc is mocked', () => {\n  expect(vi.isMockFunction(defaultFunc)).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/mocking/factory.test.ts",
    "content": "import axios from 'axios'\nimport { describe, expect, it, test, vi } from 'vitest'\nimport * as example from '../../src/mocks/example'\nimport logger from '../../src/mocks/log'\nimport * as moduleA from '../../src/mocks/moduleA'\nimport * as moduleB from '../../src/mocks/moduleB'\n\nvi\n  .mock('../../src/mocks/example', () => ({\n    mocked: true,\n    then: 'a then export',\n    ok: undefined,\n    square: (a: any, b: any) => a + b,\n    asyncSquare: async (a: any, b: any) => Promise.resolve(a + b),\n  }))\n\n// doesn't think comments are mocks\n// vi.mock('../../src/mocks/example', () => ({\n//   mocked: false,\n// }))\n\nvi.mock('../../src/mocks/moduleA', async () => {\n  const actual = await vi.importActual<any>('../../src/mocks/moduleA')\n  return {\n    B: 'B',\n    ...actual,\n  }\n})\n\nvi.mock('../../src/mocks/moduleB', async (importOriginal) => {\n  const actual = await importOriginal<any>()\n  return {\n    ...actual,\n    B: 'mockedB',\n    C: 'addedC',\n  }\n})\n\nvi.mock('axios', () => {\n  return {\n    default: {\n      get: vi.fn(),\n    },\n  }\n})\n\nvi.mock('../../src/mocks/log.ts', async () => {\n  // can import the same module inside and does not go into an infinite loop\n  const log = await import('../../src/mocks/log')\n  return {\n    default: {\n      ...log.default,\n      info: vi.fn(),\n    },\n  }\n})\n// @ts-expect-error null is not allowed to mocked implementation\nvi.mock('../../src/mocks/default.ts', () => null)\n\ndescribe('mocking with factory', () => {\n  test('missing exports on mock', () => {\n    expect(() => example.default).toThrow('[vitest] No \"default\" export is defined on the \"../../src/mocks/example\" mock')\n    expect(() => example.boolean).toThrow('[vitest] No \"boolean\" export is defined on the \"../../src/mocks/example\" mock')\n    expect(() => example.object).toThrow('[vitest] No \"object\" export is defined on the \"../../src/mocks/example\" mock')\n    expect(() => example.array).toThrow('[vitest] No \"array\" export is defined on the \"../../src/mocks/example\" mock')\n    expect(() => example.someClasses).toThrow('[vitest] No \"someClasses\" export is defined on the \"../../src/mocks/example\" mock')\n  })\n\n  it('non-object return on factory gives error', async () => {\n    await expect(() => import('../../src/mocks/default.js').then(m => m.default)).rejects.toThrow('[vitest] vi.mock(\"../../src/mocks/default.ts\", factory?: () => unknown) is not returning an object. Did you mean to return an object with a \"default\" key?')\n  })\n\n  test('defined exports on mock', async () => {\n    expect((example as any).ok).toBe(undefined)\n    expect((example as any).then).toBe('a then export')\n    expect((example as any).mocked).toBe(true)\n    expect(example.square(2, 3)).toBe(5)\n    await expect(example.asyncSquare(2, 3)).resolves.toBe(5)\n  })\n\n  test('successfully with actual', () => {\n    expect(moduleA.A).toBe('A')\n    expect((moduleA as any).B).toBe('B')\n  })\n\n  test('successfully with factory helper', () => {\n    expect(moduleB.A).toBe('A')\n    expect(moduleB.B).toBe('mockedB')\n    expect((moduleB as any).C).toBe('addedC')\n  })\n\n  test('mocks node_modules', () => {\n    axios.get('./path')\n\n    expect(axios.get).toHaveBeenCalledTimes(1)\n  })\n\n  test('logger extended', () => {\n    expect(logger.warn).toBeTypeOf('function')\n    // @ts-expect-error extending module\n    expect(logger.info).toBeTypeOf('function')\n  })\n})\n"
  },
  {
    "path": "test/core/test/mocking/has-extension.spec.ts",
    "content": "// @ts-expect-error mocked module\nimport { mocked } from 'extension.js'\nimport { expect, test, vi } from 'vitest'\n\nvi.mock('extension.js')\n\ntest('module with extension is mocked', () => {\n  expect(mocked).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/mocking/hoisted.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { asyncSquare as importedAsyncSquare, square as importedSquare } from '../../src/mocks/example'\n\nconst mocks = vi.hoisted(() => {\n  return {\n    square: vi.fn(),\n  }\n})\n\nconst { asyncSquare } = await vi.hoisted(async () => {\n  return {\n    asyncSquare: vi.fn(),\n  }\n})\n\nvi.mock('../../src/mocks/example', () => {\n  return {\n    square: mocks.square,\n    asyncSquare,\n  }\n})\n\ntest('hoisted works', () => {\n  expect(importedSquare).toBe(mocks.square)\n  expect(importedAsyncSquare).toBe(asyncSquare)\n})\n"
  },
  {
    "path": "test/core/test/mocking/integration.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { createStore } from '../../src/mocks/integration'\n\nvi.mock('@vueuse/integrations/useJwt')\n\ntest('Using nested modules works', () => {\n  const { payload } = createStore()\n\n  expect(payload.value.sub).toBe('login')\n})\n"
  },
  {
    "path": "test/core/test/mocking/nested-default.spec.ts",
    "content": "// @vitest-environment jsdom\n\nimport nestedCjs from '@vitest/test-dep-nested-cjs'\nimport { expect, test, vi } from 'vitest'\n// @ts-expect-error mocked module\nimport * as modDefaultCjs from '../../src/mocks/external/default-cjs.cjs'\n\nvi.mock('@vitest/test-dep-nested-cjs')\nvi.mock('../../src/mocks/external/default-cjs.cjs')\n\ntest('default is mocked', () => {\n  expect(vi.isMockFunction(modDefaultCjs.default.fn)).toBe(true)\n  expect(vi.isMockFunction(nestedCjs)).toBe(true)\n  expect(vi.isMockFunction(nestedCjs.clickCancel)).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/mocking/retry-dynamic-import.test.ts",
    "content": "import { describe, expect, it, vi } from 'vitest'\nimport { retryDynamicImport } from '../../src/mocks/retry-dynamic-import.js'\n\nvi.mock('../../src/mocks/dynamic-module', () => {\n  return { foo: 'bar' }\n})\n\ndescribe('retry-dynamic-import', () => {\n  it('should dynamic import module success', async () => {\n    expect(await retryDynamicImport()).toEqual({ foo: 'bar' })\n  })\n  it('should throw when retry over 3 times', async () => {\n    vi.doMock('../../src/mocks/dynamic-module', () => {\n      throw new Error('foobar')\n    })\n    await expect(retryDynamicImport()).rejects.toThrow(new Error('import dynamic module failed.'))\n  })\n})\n"
  },
  {
    "path": "test/core/test/mocking/self-importing.test.ts",
    "content": "import fn from '@vitest/test-fn'\nimport { describe, expect, test, vi } from 'vitest'\nimport { magic } from '../../src/mocks/test-fn-magic'\n\nvi.mock('@vitest/test-fn')\n\ndescribe('fn didn\\'t go into an infinite loop', () => {\n  test('fn is mocked', () => {\n    expect(vi.isMockFunction(fn)).toBe(true)\n  })\n\n  test('magic calls fn', () => {\n    const store = magic()\n    expect(fn).toHaveBeenCalled()\n    expect(store).toBeTypeOf('function')\n  })\n})\n"
  },
  {
    "path": "test/core/test/mocking/spaced.spec.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { thisIsOk } from '../../src/mocks/has space in path'\n\nvi.mock('../../src/mocks/has space in path', () => ({ thisIsOk: true }))\n\ntest('modules with spaces in name is mocked', () => {\n  expect(thisIsOk).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/mocking/tinyspy.test.ts",
    "content": "import type * as tinyspyModule from 'tinyspy'\nimport { expect, test, vi } from 'vitest'\n\ntest('tinyspy is not mocked with __mocks__, but automatically mocked', async () => {\n  const tinyspy = await vi.importMock<typeof tinyspyModule>('tinyspy')\n\n  expect(vi.isMockFunction(tinyspy.spyOn)).toBe(true)\n  expect(vi.isMockFunction(tinyspy.spy)).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/mocking/vi-fn.test-d.ts",
    "content": "import type { Mock, MockResult, MockSettledResult } from 'vitest'\nimport { expectTypeOf, test, vi } from 'vitest'\n\ntype Procedure = (...args: any[]) => any\n\ntest('spy.mock when implementation is a class', () => {\n  class Klass {\n    constructor(_a: string, _b?: number) {\n      // ...\n    }\n\n    static getType() {\n      return 'Klass'\n    }\n  }\n\n  const Mock = vi.fn(Klass)\n\n  expectTypeOf(Mock.mock.calls).toEqualTypeOf<[a: string, b?: number][]>()\n  expectTypeOf(Mock.mock.results).toEqualTypeOf<MockResult<Klass>[]>()\n  expectTypeOf(Mock.mock.contexts).toEqualTypeOf<Klass[]>()\n  expectTypeOf(Mock.mock.instances).toEqualTypeOf<Klass[]>()\n  expectTypeOf(Mock.mock.invocationCallOrder).toEqualTypeOf<number[]>()\n  expectTypeOf(Mock.mock.settledResults).toEqualTypeOf<MockSettledResult<Klass>[]>()\n  expectTypeOf(Mock.mock.lastCall).toEqualTypeOf<[a: string, b?: number] | undefined>()\n\n  // static properties are defined\n  expectTypeOf(Mock.getType).toBeFunction()\n  expectTypeOf(Mock.getType).returns.toBeString()\n\n  expectTypeOf(Mock).constructorParameters.toEqualTypeOf<[a: string, b?: number]>()\n  expectTypeOf(Mock).instance.toEqualTypeOf<Klass>()\n})\n\ntest('spy.mock when implementation is a class-like function', () => {\n  function Klass(this: typeof Klass, _a: string, _b?: number) {\n    // ...\n  }\n\n  const Mock = vi.fn(Klass)\n\n  expectTypeOf(Mock.mock.calls).toEqualTypeOf<[a: string, b?: number][]>()\n  expectTypeOf(Mock.mock.results).toEqualTypeOf<MockResult<void>[]>()\n  expectTypeOf(Mock.mock.contexts).toEqualTypeOf<typeof Klass[]>()\n  expectTypeOf(Mock.mock.instances).toEqualTypeOf<typeof Klass[]>()\n  expectTypeOf(Mock.mock.invocationCallOrder).toEqualTypeOf<number[]>()\n  expectTypeOf(Mock.mock.settledResults).toEqualTypeOf<MockSettledResult<void>[]>()\n  expectTypeOf(Mock.mock.lastCall).toEqualTypeOf<[a: string, b?: number] | undefined>()\n\n  expectTypeOf(Mock).constructorParameters.toEqualTypeOf<[a: string, b?: number]>()\n})\n\ntest('spy.mock when implementation is a normal function', () => {\n  function FN(_a: string, _b?: number) {\n    return 42\n  }\n\n  const Mock = vi.fn(FN)\n\n  expectTypeOf(Mock.mock.calls).toEqualTypeOf<[a: string, b?: number][]>()\n  expectTypeOf(Mock.mock.results).toEqualTypeOf<MockResult<number>[]>()\n  expectTypeOf(Mock.mock.contexts).toEqualTypeOf<unknown[]>()\n  expectTypeOf(Mock.mock.instances).toEqualTypeOf<unknown[]>()\n  expectTypeOf(Mock.mock.invocationCallOrder).toEqualTypeOf<number[]>()\n  expectTypeOf(Mock.mock.settledResults).toEqualTypeOf<MockSettledResult<number>[]>()\n  expectTypeOf(Mock.mock.lastCall).toEqualTypeOf<[a: string, b?: number] | undefined>()\n\n  expectTypeOf(Mock).constructorParameters.toEqualTypeOf<[a: string, b?: number]>()\n})\n\ntest('cann call a function mock with and without new', () => {\n  const Mock = vi.fn(function fn(this: any) {\n    this.test = true\n  })\n\n  const _mockClass = new Mock()\n  const _mockFn = Mock()\n})\n\ntest('cannot call class mock without new', () => {\n  const Mock = vi.fn(class {})\n\n  const _mockClass = new Mock()\n  // @ts-expect-error value is not callable\n  const _mockFn = Mock()\n})\n\ntest('spying on a function that supports new', () => {\n  interface ReturnClass {}\n  interface BothFnAndClass {\n    new (): ReturnClass\n    (): ReturnClass\n  }\n\n  const Mock = vi.fn(function R() {} as BothFnAndClass)\n\n  // supports new\n  const _mockClass = new Mock()\n  // supports T()\n  const _mockFn = Mock()\n})\n\ntest('withImplementation returns correct type', () => {\n  const spy = vi.fn()\n\n  const result42 = spy.withImplementation(() => {}, () => {\n    return 42\n  })\n  expectTypeOf(result42).toEqualTypeOf<Mock<Procedure>>()\n\n  const resultObject = spy.withImplementation(() => {}, () => {\n    return { then: () => 42 }\n  })\n  expectTypeOf(resultObject).toEqualTypeOf<Mock<Procedure>>()\n\n  const resultVoid = spy.withImplementation(() => {}, () => {})\n  expectTypeOf(resultVoid).toEqualTypeOf<Mock<Procedure>>()\n\n  const promise42 = spy.withImplementation(() => {}, async () => {\n    return 42\n  })\n  expectTypeOf(promise42).toEqualTypeOf<Promise<Mock<Procedure>>>()\n\n  const promiseObject = spy.withImplementation(() => {}, async () => {\n    return { hello: () => 42 }\n  })\n  expectTypeOf(promiseObject).toEqualTypeOf<Promise<Mock<Procedure>>>()\n\n  const promiseVoid = spy.withImplementation(() => {}, async () => {})\n  expectTypeOf(promiseVoid).toEqualTypeOf<Promise<Mock<Procedure>>>()\n\n  const promisePromise = spy.withImplementation(() => {}, () => {\n    return Promise.resolve()\n  })\n  expectTypeOf(promisePromise).toEqualTypeOf<Promise<Mock<Procedure>>>()\n})\n"
  },
  {
    "path": "test/core/test/mocking/vi-fn.test.ts",
    "content": "import type { MockContext } from 'vitest'\nimport { describe, expect, test, vi } from 'vitest'\n\ntest('vi.fn() returns undefined by default', () => {\n  const mock = vi.fn()\n  expect(mock()).toBe(undefined)\n})\n\ntest('vi.fn() calls implementation if it was passed down', () => {\n  const mock = vi.fn(() => 3)\n  expect(mock()).toBe(3)\n})\n\ntest('vi.fn().mock cannot be overridden', () => {\n  const mock = vi.fn()\n  expect(() => mock.mock = {} as any).toThrow()\n  expect(() => {\n    // @ts-expect-error mock is not optional\n    delete mock.mock\n  }).toThrow()\n})\n\ndescribe('vi.fn() copies static properties', () => {\n  test('vi.fn() copies static properties from functions', () => {\n    function Example() {}\n    Example.HELLO_WORLD = true\n\n    const spy = vi.fn(Example)\n    expect(Example.HELLO_WORLD).toBe(true)\n    expect(spy.HELLO_WORLD).toBe(true)\n  })\n\n  test('vi.fn() copies static properties from classes', () => {\n    class Example {\n      static HELLO_WORLD = true\n    }\n\n    const spy = vi.fn(Example)\n    expect(Example.HELLO_WORLD).toBe(true)\n    expect(spy.HELLO_WORLD).toBe(true)\n  })\n\n  test('vi.fn() ignores \"node.js.promisify\" symbol', () => {\n    const promisifySymbol = Symbol.for('nodejs.util.promisify.custom')\n    class Example {\n      static [promisifySymbol] = () => Promise.resolve(42)\n    }\n\n    const spy = vi.fn(Example)\n    expect(spy[promisifySymbol]).toBe(undefined)\n  })\n})\n\ndescribe('fn.length is consistent', () => {\n  test('vi.fn() has correct length', () => {\n    const fn0 = vi.fn(() => {})\n    expect(fn0.length).toBe(0)\n\n    const fnArgs = vi.fn((..._args) => {})\n    expect(fnArgs.length).toBe(0)\n\n    const fn1 = vi.fn((_arg1) => {})\n    expect(fn1.length).toBe(1)\n\n    const fn2 = vi.fn((_arg1, _arg2) => {})\n    expect(fn2.length).toBe(2)\n\n    const fn3 = vi.fn((_arg1, _arg2, _arg3) => {})\n    expect(fn3.length).toBe(3)\n  })\n\n  test('vi.fn() always returns length of the initial implementation', () => {\n    const fn = vi.fn<(...args: any[]) => void>((_arg) => {})\n\n    expect(fn.length).toBe(1)\n\n    fn.mockImplementationOnce(() => {})\n\n    expect(fn.length).toBe(1)\n    fn(1)\n    expect(fn.length).toBe(1)\n\n    fn.mockImplementation((_arg1, _arg2) => {})\n\n    expect(fn.length).toBe(1)\n    fn(1)\n    expect(fn.length).toBe(1)\n\n    fn.withImplementation((_arg1, _arg2, _arg3) => {}, () => {\n      expect(fn.length).toBe(1)\n    })\n  })\n})\n\ntest('vi.fn() has overridable length', () => {\n  const fn0 = vi.fn(() => {})\n  // @ts-expect-error TS doesn't allow override\n  fn0.length = 5\n  expect(fn0.length).toBe(5)\n})\n\ndescribe('vi.fn() state', () => {\n  // TODO: test when calls is not empty\n  test('vi.fn() clears calls without a custom implementation', () => {\n    const mock = vi.fn()\n    const state = mock.mock\n\n    assertStateEmpty(state)\n\n    mock()\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: undefined }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: undefined }])\n    expect(state.contexts).toEqual([undefined])\n    expect(state.instances).toEqual([undefined])\n    expect(state.lastCall).toEqual([])\n\n    mock.mockClear()\n\n    assertStateEmpty(state)\n\n    mock()\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: undefined }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: undefined }])\n    expect(state.contexts).toEqual([undefined])\n    expect(state.instances).toEqual([undefined])\n    expect(state.lastCall).toEqual([])\n\n    vi.clearAllMocks()\n\n    assertStateEmpty(state)\n  })\n\n  test('vi.fn() clears calls with a custom sync function implementation', () => {\n    const mock = vi.fn(() => 42)\n    const state = mock.mock\n\n    assertStateEmpty(state)\n\n    mock()\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 42 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 42 }])\n    expect(state.contexts).toEqual([undefined])\n    expect(state.instances).toEqual([undefined])\n    expect(state.lastCall).toEqual([])\n\n    mock.mockClear()\n\n    assertStateEmpty(state)\n\n    mock()\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 42 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 42 }])\n    expect(state.contexts).toEqual([undefined])\n    expect(state.instances).toEqual([undefined])\n    expect(state.lastCall).toEqual([])\n\n    vi.clearAllMocks()\n\n    assertStateEmpty(state)\n  })\n\n  test('vi.fn() clears calls with a custom sync function implementation with context', () => {\n    const mock = vi.fn(() => 42)\n    const state = mock.mock\n\n    assertStateEmpty(state)\n\n    mock.call('context')\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 42 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 42 }])\n    expect(state.contexts).toEqual(['context'])\n    expect(state.instances).toEqual(['context'])\n    expect(state.lastCall).toEqual([])\n\n    mock.mockClear()\n\n    assertStateEmpty(state)\n\n    mock.call('context')\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 42 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 42 }])\n    expect(state.contexts).toEqual(['context'])\n    expect(state.instances).toEqual(['context'])\n    expect(state.lastCall).toEqual([])\n\n    vi.clearAllMocks()\n\n    assertStateEmpty(state)\n  })\n\n  test('vi.fn() clears calls with a custom sync prototype function implementation', () => {\n    const mock = vi.fn(function (this: any) {\n      this.value = 42\n      return 'return-string'\n    })\n    const state = mock.mock\n\n    assertStateEmpty(state)\n\n    mock.call({})\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 'return-string' }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 'return-string' }])\n    expect(state.contexts).toEqual([{ value: 42 }])\n    expect(state.instances).toEqual([{ value: 42 }])\n    expect(state.lastCall).toEqual([])\n\n    mock.mockClear()\n\n    assertStateEmpty(state)\n\n    mock.call({})\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 'return-string' }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 'return-string' }])\n    expect(state.contexts).toEqual([{ value: 42 }])\n    expect(state.instances).toEqual([{ value: 42 }])\n    expect(state.lastCall).toEqual([])\n\n    vi.clearAllMocks()\n\n    assertStateEmpty(state)\n  })\n\n  test('vi.fn() clears calls with a custom sync class implementation', () => {\n    const Mock = vi.fn(class {\n      public value: number\n      constructor() {\n        this.value = 42\n      }\n    })\n    const state = Mock.mock\n\n    assertStateEmpty(state)\n\n    const mock1 = new Mock()\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: expect.any(Mock) }])\n    expect(state.results).toEqual([{ type: 'return', value: { value: 42 } }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: { value: 42 } }])\n    expect(state.contexts).toEqual([mock1])\n    expect(state.instances).toEqual([mock1])\n    expect(state.lastCall).toEqual([])\n\n    Mock.mockClear()\n\n    assertStateEmpty(state)\n\n    const mock2 = new Mock()\n\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: mock2 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: mock2 }])\n    expect(state.contexts).toEqual([mock2])\n    expect(state.instances).toEqual([mock2])\n    expect(state.lastCall).toEqual([])\n\n    vi.clearAllMocks()\n\n    assertStateEmpty(state)\n  })\n\n  test('vi.fn() clears calls with a custom async function implementation', async () => {\n    const mock = vi.fn(() => Promise.resolve(42))\n    const state = mock.mock\n\n    assertStateEmpty(state)\n\n    const promise = mock()\n\n    expect(state.calls).toEqual([[]])\n    expect(state.settledResults).toEqual([{ type: 'incomplete', value: undefined }])\n    expect(state.results).toEqual([{ type: 'return', value: expect.any(Promise) }])\n    expect(state.contexts).toEqual([undefined])\n    expect(state.instances).toEqual([undefined])\n    expect(state.lastCall).toEqual([])\n\n    await promise\n\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 42 }])\n\n    mock.mockClear()\n\n    assertStateEmpty(state)\n\n    const promise2 = mock()\n\n    expect(state.calls).toEqual([[]])\n    expect(state.settledResults).toEqual([{ type: 'incomplete', value: undefined }])\n    expect(state.results).toEqual([{ type: 'return', value: expect.any(Promise) }])\n    expect(state.contexts).toEqual([undefined])\n    expect(state.instances).toEqual([undefined])\n    expect(state.lastCall).toEqual([])\n\n    await promise2\n\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 42 }])\n\n    vi.clearAllMocks()\n\n    assertStateEmpty(state)\n  })\n})\n\ndescribe('vi.fn() configuration', () => {\n  test('vi.fn() resets the original mock implementation', () => {\n    const mock = vi.fn(() => 42)\n    expect(mock()).toBe(42)\n    mock.mockReset()\n    expect(mock()).toBe(42)\n  })\n\n  test('vi.fn() resets the mock implementation', () => {\n    const mock = vi.fn().mockImplementation(() => 42)\n    expect(mock()).toBe(42)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() returns undefined as a mock implementation', () => {\n    const mock = vi.fn()\n    expect(mock.getMockImplementation()).toBe(undefined)\n  })\n\n  test('vi.fn() returns implementation if it was set', () => {\n    const implementation = () => 42\n    const mock = vi.fn(implementation)\n    expect(mock.getMockImplementation()).toBe(implementation)\n  })\n\n  test('vi.fn() returns mockImplementation if it was set', () => {\n    const implementation = () => 42\n    const mock = vi.fn().mockImplementation(implementation)\n    expect(mock.getMockImplementation()).toBe(implementation)\n  })\n\n  test('vi.fn() returns mockOnceImplementation if it was set', () => {\n    const implementation = () => 42\n    const mock = vi.fn().mockImplementationOnce(implementation)\n    expect(mock.getMockImplementation()).toBe(implementation)\n  })\n\n  test('vi.fn() returns withImplementation if it was set', () => {\n    const implementation = () => 42\n    const mock = vi.fn()\n    mock.withImplementation(implementation, () => {\n      expect(mock.getMockImplementation()).toBe(implementation)\n    })\n  })\n\n  test('vi.fn() has a name', () => {\n    const mock = vi.fn()\n    expect(mock.getMockName()).toBe('vi.fn()')\n    mock.mockName('test')\n    expect(mock.getMockName()).toBe('test')\n    mock.mockReset()\n    expect(mock.getMockName()).toBe('vi.fn()')\n    mock.mockName('test')\n    expect(mock.getMockName()).toBe('test')\n    vi.resetAllMocks()\n    expect(mock.getMockName()).toBe('vi.fn()')\n  })\n\n  test('vi.fn() can reassign different implementations', () => {\n    const mock = vi.fn(() => 42)\n    expect(mock()).toBe(42)\n    mock.mockReturnValueOnce(100)\n      .mockReturnValueOnce(55)\n    expect(mock()).toBe(100)\n    expect(mock()).toBe(55)\n    expect(mock()).toBe(42)\n    mock.mockReturnValue(66)\n    expect(mock()).toBe(66)\n  })\n})\n\ndescribe('vi.fn() restoration', () => {\n  test('vi.fn() resets the original implementation in mock.mockRestore()', () => {\n    const mock = vi.fn(() => 'hello')\n    expect(mock()).toBe('hello')\n    mock.mockRestore()\n    expect(mock()).toBe('hello')\n  })\n\n  test('vi.fn() doesn\\'t resets the added implementation in mock.mockRestore()', () => {\n    const mock = vi.fn().mockImplementation(() => 'hello')\n    expect(mock()).toBe('hello')\n    mock.mockRestore()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() doesn\\'t restore the original implementation in vi.restoreAllMocks()', () => {\n    const mock = vi.fn(() => 'hello')\n    expect(mock()).toBe('hello')\n    vi.restoreAllMocks()\n    expect(mock()).toBe('hello')\n  })\n\n  test('vi.fn() doesn\\'t restore the added implementation in vi.restoreAllMocks()', () => {\n    const mock = vi.fn().mockImplementation(() => 'hello')\n    expect(mock()).toBe('hello')\n    vi.restoreAllMocks()\n    expect(mock()).toBe('hello')\n  })\n})\n\ndescribe('vi.fn() implementations', () => {\n  test('vi.fn() can throw an error in original implementation', () => {\n    const mock = vi.fn(() => {\n      throw new Error('hello world')\n    })\n\n    expect(() => mock()).toThrow('hello world')\n    expect(mock.mock.results).toEqual([\n      { type: 'throw', value: new Error('hello world') },\n    ])\n  })\n\n  test('vi.fn() can throw an error in custom implementation', () => {\n    const mock = vi.fn().mockImplementation(() => {\n      throw new Error('hello world')\n    })\n\n    expect(() => mock()).toThrow('hello world')\n    expect(mock.mock.results).toEqual([\n      { type: 'throw', value: new Error('hello world') },\n    ])\n  })\n\n  test('vi.fn() with mockReturnThis on a function', () => {\n    const context = {}\n    const mock = vi.fn()\n    mock.mockReturnThis()\n    expect(mock.call(context)).toBe(context)\n  })\n\n  test('vi.fn() with mockReturnThis on a class', () => {\n    const Mock = vi.fn(class {})\n    Mock.mockReturnThis()\n    const mock = new Mock()\n    expect(mock, 'has no effect on return value').toBeInstanceOf(Mock)\n    expect(Mock.mock.contexts).toEqual([mock])\n    expect(Mock.mock.instances).toEqual([mock])\n  })\n\n  test('vi.fn() with mockReturnValue', () => {\n    const mock = vi.fn()\n    mock.mockReturnValue(42)\n    expect(mock()).toBe(42)\n    expect(mock()).toBe(42)\n    expect(mock()).toBe(42)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockReturnValue overriding original mock', () => {\n    const mock = vi.fn(() => 42)\n    mock.mockReturnValue(100)\n    expect(mock()).toBe(100)\n    expect(mock()).toBe(100)\n    expect(mock()).toBe(100)\n    mock.mockReset()\n    expect(mock()).toBe(42)\n  })\n\n  test('vi.fn() with mockReturnValue overriding another mock', () => {\n    const mock = vi.fn().mockImplementation(() => 42)\n    mock.mockReturnValue(100)\n    expect(mock()).toBe(100)\n    expect(mock()).toBe(100)\n    expect(mock()).toBe(100)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockReturnValueOnce', () => {\n    const mock = vi.fn()\n    mock.mockReturnValueOnce(42)\n    expect(mock()).toBe(42)\n    expect(mock()).toBe(undefined)\n    expect(mock()).toBe(undefined)\n    mock.mockReturnValueOnce(42)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockReturnValueOnce overriding original mock', () => {\n    const mock = vi.fn(() => 42)\n    mock.mockReturnValueOnce(100)\n    expect(mock()).toBe(100)\n    expect(mock()).toBe(42)\n    expect(mock()).toBe(42)\n    mock.mockReset()\n    expect(mock()).toBe(42)\n  })\n\n  test('vi.fn() with mockReturnValueOnce overriding another mock', () => {\n    const mock = vi.fn().mockImplementation(() => 42)\n    mock.mockReturnValueOnce(100)\n    expect(mock()).toBe(100)\n    expect(mock()).toBe(42)\n    expect(mock()).toBe(42)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockThrow', async () => {\n    const mock = vi.fn()\n    mock.mockThrow(new Error('error'))\n    expect(() => mock()).toThrow('error')\n    expect(() => mock()).toThrow('error')\n    expect(() => mock()).toThrow('error')\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn(class) with mockThrow', async () => {\n    const Mock = vi.fn(class {})\n    Mock.mockThrow(new Error('error'))\n    expect(() => new Mock()).toThrow('error')\n    expect(() => new Mock()).toThrow('error')\n    expect(() => new Mock()).toThrow('error')\n    Mock.mockReset()\n    expect(new Mock()).toBeInstanceOf(Mock)\n  })\n\n  test('vi.fn() with mockThrow overriding original mock', async () => {\n    const mock = vi.fn(() => 42)\n    mock.mockThrow(new Error('error'))\n    expect(() => mock()).toThrow('error')\n    expect(() => mock()).toThrow('error')\n    expect(() => mock()).toThrow('error')\n    mock.mockReset()\n    expect(mock()).toBe(42)\n  })\n\n  test('vi.fn() with mockThrow overriding another mock', async () => {\n    const mock = vi.fn().mockImplementation(() => 42)\n    mock.mockThrow(new Error('error'))\n    expect(() => mock()).toThrow('error')\n    expect(() => mock()).toThrow('error')\n    expect(() => mock()).toThrow('error')\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockThrowOnce', async () => {\n    const mock = vi.fn()\n    mock.mockThrowOnce(new Error('error'))\n    expect(() => mock()).toThrow('error')\n    expect(mock()).toBe(undefined)\n    expect(mock()).toBe(undefined)\n    mock.mockThrowOnce(new Error('error'))\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn(class) with mockThrowOnce', async () => {\n    const Mock = vi.fn(class {})\n    Mock.mockThrowOnce(new Error('error'))\n    expect(() => new Mock()).toThrow('error')\n    expect(new Mock()).toBeInstanceOf(Mock)\n    expect(new Mock()).toBeInstanceOf(Mock)\n    Mock.mockThrowOnce(new Error('error'))\n    Mock.mockReset()\n    expect(new Mock()).toBeInstanceOf(Mock)\n  })\n\n  test('vi.fn() with mockThrowOnce overriding original mock', async () => {\n    const mock = vi.fn(() => 42)\n    mock.mockThrowOnce(new Error('error'))\n    expect(() => mock()).toThrow('error')\n    expect(mock()).toBe(42)\n    expect(mock()).toBe(42)\n    mock.mockReset()\n    expect(mock()).toBe(42)\n  })\n\n  test('vi.fn() with mockThrowOnce overriding another mock', async () => {\n    const mock = vi.fn().mockImplementation(() => 42)\n    mock.mockThrowOnce(new Error('error'))\n    expect(() => mock()).toThrow('error')\n    expect(mock()).toBe(42)\n    expect(mock()).toBe(42)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockResolvedValue', async () => {\n    const mock = vi.fn()\n    mock.mockResolvedValue(42)\n    await expect(mock()).resolves.toBe(42)\n    await expect(mock()).resolves.toBe(42)\n    await expect(mock()).resolves.toBe(42)\n    expect(mock.mock.settledResults).toEqual([\n      { type: 'fulfilled', value: 42 },\n      { type: 'fulfilled', value: 42 },\n      { type: 'fulfilled', value: 42 },\n    ])\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockResolvedValue overriding original mock', async () => {\n    const mock = vi.fn(() => Promise.resolve(42))\n    mock.mockResolvedValue(100)\n    await expect(mock()).resolves.toBe(100)\n    await expect(mock()).resolves.toBe(100)\n    await expect(mock()).resolves.toBe(100)\n    expect(mock.mock.settledResults).toEqual([\n      { type: 'fulfilled', value: 100 },\n      { type: 'fulfilled', value: 100 },\n      { type: 'fulfilled', value: 100 },\n    ])\n    mock.mockReset()\n    await expect(mock()).resolves.toBe(42)\n  })\n\n  test('vi.fn() with mockResolvedValue overriding another mock', async () => {\n    const mock = vi.fn().mockImplementation(() => 42)\n    mock.mockResolvedValue(100)\n    await expect(mock()).resolves.toBe(100)\n    await expect(mock()).resolves.toBe(100)\n    await expect(mock()).resolves.toBe(100)\n    expect(mock.mock.settledResults).toEqual([\n      { type: 'fulfilled', value: 100 },\n      { type: 'fulfilled', value: 100 },\n      { type: 'fulfilled', value: 100 },\n    ])\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockResolvedValueOnce', async () => {\n    const mock = vi.fn()\n    mock.mockResolvedValueOnce(42)\n    await expect(mock()).resolves.toBe(42)\n    expect(mock()).toBe(undefined)\n    expect(mock()).toBe(undefined)\n    mock.mockResolvedValueOnce(42)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockResolvedValueOnce overriding original mock', async () => {\n    const mock = vi.fn(() => Promise.resolve(42))\n    mock.mockResolvedValueOnce(100)\n    await expect(mock()).resolves.toBe(100)\n    await expect(mock()).resolves.toBe(42)\n    await expect(mock()).resolves.toBe(42)\n    mock.mockReset()\n    await expect(mock()).resolves.toBe(42)\n  })\n\n  test('vi.fn() with mockResolvedValueOnce overriding another mock', async () => {\n    const mock = vi.fn().mockImplementation(() => Promise.resolve(42))\n    mock.mockResolvedValueOnce(100)\n    await expect(mock()).resolves.toBe(100)\n    await expect(mock()).resolves.toBe(42)\n    await expect(mock()).resolves.toBe(42)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockRejectedValue', async () => {\n    const mock = vi.fn()\n    mock.mockRejectedValue(42)\n    await expect(mock()).rejects.toBe(42)\n    await expect(mock()).rejects.toBe(42)\n    await expect(mock()).rejects.toBe(42)\n    expect(mock.mock.settledResults).toEqual([\n      { type: 'rejected', value: 42 },\n      { type: 'rejected', value: 42 },\n      { type: 'rejected', value: 42 },\n    ])\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockRejectedValue overriding original mock', async () => {\n    const mock = vi.fn(() => Promise.resolve(42))\n    mock.mockRejectedValue(100)\n    await expect(mock()).rejects.toBe(100)\n    await expect(mock()).rejects.toBe(100)\n    await expect(mock()).rejects.toBe(100)\n    expect(mock.mock.settledResults).toEqual([\n      { type: 'rejected', value: 100 },\n      { type: 'rejected', value: 100 },\n      { type: 'rejected', value: 100 },\n    ])\n    mock.mockReset()\n    await expect(mock()).resolves.toBe(42)\n  })\n\n  test('vi.fn() with mockRejectedValue overriding another mock', async () => {\n    const mock = vi.fn().mockImplementation(() => Promise.resolve(42))\n    mock.mockRejectedValue(100)\n    await expect(mock()).rejects.toBe(100)\n    await expect(mock()).rejects.toBe(100)\n    await expect(mock()).rejects.toBe(100)\n    expect(mock.mock.settledResults).toEqual([\n      { type: 'rejected', value: 100 },\n      { type: 'rejected', value: 100 },\n      { type: 'rejected', value: 100 },\n    ])\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockRejectedValueOnce', async () => {\n    const mock = vi.fn()\n    mock.mockRejectedValueOnce(42)\n    await expect(mock()).rejects.toBe(42)\n    expect(mock()).toBe(undefined)\n    expect(mock()).toBe(undefined)\n    mock.mockRejectedValueOnce(42)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() with mockRejectedValueOnce overriding original mock', async () => {\n    const mock = vi.fn(() => Promise.resolve(42))\n    mock.mockRejectedValueOnce(100)\n    await expect(mock()).rejects.toBe(100)\n    await expect(mock()).resolves.toBe(42)\n    await expect(mock()).resolves.toBe(42)\n    mock.mockReset()\n    await expect(mock()).resolves.toBe(42)\n  })\n\n  test('vi.fn() with mockRejectedValueOnce overriding another mock', async () => {\n    const mock = vi.fn().mockImplementation(() => Promise.resolve(42))\n    mock.mockRejectedValueOnce(100)\n    await expect(mock()).rejects.toBe(100)\n    await expect(mock()).resolves.toBe(42)\n    await expect(mock()).resolves.toBe(42)\n    mock.mockReset()\n    expect(mock()).toBe(undefined)\n  })\n\n  test('vi.fn() throws an error if new is called on arrow function', ({ onTestFinished }) => {\n    const log = vi.spyOn(console, 'warn')\n    onTestFinished(() => log.mockRestore())\n    const Mock = vi.fn(() => {})\n    expect(() => new Mock()).toThrow()\n    expect(log).toHaveBeenCalledWith(\n      `[vitest] The vi.fn() mock did not use 'function' or 'class' in its implementation, see https://vitest.dev/api/vi#vi-spyon for examples.`,\n    )\n  })\n\n  test('vi.fn() throws an error if new is not called on a class', () => {\n    const Mock = vi.fn(class _Mock {})\n    // @ts-expect-error value is not callable\n    expect(() => Mock()).toThrow(\n      `Class constructor _Mock cannot be invoked without 'new'`,\n    )\n  })\n\n  test('vi.fn() respects new target in a function', () => {\n    let target!: unknown\n    let callArgs!: unknown[]\n    const Mock = vi.fn(function (this: any, ...args: unknown[]) {\n      target = new.target\n      callArgs = args\n    })\n    const _example = new Mock('test', 42)\n    expect(target).toBeTypeOf('function')\n    expect(callArgs).toEqual(['test', 42])\n    expect(Mock.mock.calls).toEqual([['test', 42]])\n  })\n\n  test('vi.fn() respects new target in a class', () => {\n    let target!: unknown\n    let callArgs!: unknown[]\n    const Mock = vi.fn(class {\n      constructor(...args: any[]) {\n        target = new.target\n        callArgs = args\n      }\n    })\n    const _example = new Mock('test', 42)\n    expect(target).toBeTypeOf('function')\n    expect(callArgs).toEqual(['test', 42])\n    expect(Mock.mock.calls).toEqual([['test', 42]])\n  })\n\n  test('vi.fn() with mockReturnValue throws when called with new', () => {\n    const Mock = vi.fn()\n    Mock.mockReturnValue(42)\n    expect(() => new Mock()).toThrow(\n      'Cannot use `mockReturnValue` when called with `new`. Use `mockImplementation` with a `class` keyword instead.',\n    )\n  })\n\n  test('vi.fn() with mockReturnValueOnce throws when called with new', () => {\n    const Mock = vi.fn()\n    Mock.mockReturnValueOnce(42)\n    expect(() => new Mock()).toThrow(\n      'Cannot use `mockReturnValueOnce` when called with `new`. Use `mockImplementation` with a `class` keyword instead.',\n    )\n  })\n\n  test('vi.fn() with mockResolvedValue throws when called with new', () => {\n    const Mock = vi.fn()\n    Mock.mockResolvedValue(42)\n    expect(() => new Mock()).toThrow(\n      'Cannot use `mockResolvedValue` when called with `new`. Use `mockImplementation` with a `class` keyword instead.',\n    )\n  })\n\n  test('vi.fn() with mockResolvedValueOnce throws when called with new', () => {\n    const Mock = vi.fn()\n    Mock.mockResolvedValueOnce(42)\n    expect(() => new Mock()).toThrow(\n      'Cannot use `mockResolvedValueOnce` when called with `new`. Use `mockImplementation` with a `class` keyword instead.',\n    )\n  })\n\n  test('vi.fn() with mockRejectedValue throws when called with new', () => {\n    const Mock = vi.fn()\n    Mock.mockRejectedValue(new Error('test'))\n    expect(() => new Mock()).toThrow(\n      'Cannot use `mockRejectedValue` when called with `new`. Use `mockImplementation` with a `class` keyword instead.',\n    )\n  })\n\n  test('vi.fn() with mockRejectedValueOnce throws when called with new', () => {\n    const Mock = vi.fn()\n    Mock.mockRejectedValueOnce(new Error('test'))\n    expect(() => new Mock()).toThrow(\n      'Cannot use `mockRejectedValueOnce` when called with `new`. Use `mockImplementation` with a `class` keyword instead.',\n    )\n  })\n})\n\nfunction assertStateEmpty(state: MockContext<any>) {\n  expect(state.calls).toHaveLength(0)\n  expect(state.results).toHaveLength(0)\n  expect(state.settledResults).toHaveLength(0)\n  expect(state.contexts).toHaveLength(0)\n  expect(state.instances).toHaveLength(0)\n  expect(state.lastCall).toBe(undefined)\n  expect(state.invocationCallOrder).toEqual([])\n}\n"
  },
  {
    "path": "test/core/test/mocking/vi-mockObject.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\n\ntest('vi.mockObject() mocks methods', () => {\n  const mocked = mockModule()\n\n  expect(mocked.method.name).toBe('method')\n  expect(mocked.Class.name).toBe('Class')\n  expect(mocked.method()).toBe(undefined)\n  expect(new mocked.Class()).toBeInstanceOf(mocked.Class)\n})\n\ntest('when properties are spied, they keep the implementation', () => {\n  const module = mockModule('autospy')\n  expect(module.method()).toBe(42)\n  expect(module.method).toHaveBeenCalled()\n\n  const instance = new module.Class()\n  expect(instance.method()).toBe(42)\n  expect(instance.method).toHaveBeenCalled()\n  expect(module.Class.prototype.method).toHaveBeenCalledTimes(1)\n\n  vi.mocked(instance.method).mockReturnValue(100)\n  expect(instance.method()).toBe(100)\n  expect(module.Class.prototype.method).toHaveBeenCalledTimes(2)\n\n  vi.mocked(instance.method).mockReset()\n  expect(instance.method()).toBe(42)\n  expect(module.Class.prototype.method).toHaveBeenCalledTimes(3)\n})\n\ntest('vi.restoreAllMocks() does not affect mocks', () => {\n  const mocked = mockModule()\n\n  vi.restoreAllMocks()\n\n  expect(mocked.method()).toBe(undefined)\n  expect(new mocked.Class()).toBeInstanceOf(mocked.Class)\n})\n\ntest('vi.mockRestore() does not affect mocks', () => {\n  const mocked = mockModule()\n\n  vi.mocked(mocked.method).mockRestore()\n\n  expect(mocked.method()).toBe(undefined)\n  expect(new mocked.Class()).toBeInstanceOf(mocked.Class)\n})\n\ntest('vi.mockRestore() on respied method does not restore it to the original', async ({ annotate }) => {\n  await annotate('https://github.com/vitest-dev/vitest/issues/8319', 'issue')\n\n  const mocked = mockModule()\n  const spy = vi.spyOn(mocked, 'method')\n\n  expect(mocked.method()).toBe(undefined)\n\n  spy.mockRestore()\n\n  expect(mocked.method()).toBe(undefined)\n})\n\ntest('instance mocks are independently tracked, but prototype shares the state', () => {\n  const { Class } = mockModule()\n  const t1 = new Class()\n  const t2 = new Class()\n  t1.method()\n  expect(t1.method).toHaveBeenCalledTimes(1)\n  t2.method()\n  expect(t1.method).toHaveBeenCalledTimes(1)\n  expect(t2.method).toHaveBeenCalledTimes(1)\n  expect(Class.prototype.method).toHaveBeenCalledTimes(2)\n\n  vi.resetAllMocks()\n  t1.method()\n  expect(t1.method).toHaveBeenCalledTimes(1)\n  t2.method()\n  expect(t1.method).toHaveBeenCalledTimes(1)\n  expect(t2.method).toHaveBeenCalledTimes(1)\n  expect(Class.prototype.method).toHaveBeenCalledTimes(2)\n\n  vi.mocked(t1.method).mockReturnValue(100)\n  t1.method()\n  expect(t1.method).toHaveBeenCalledTimes(2)\n  // tracks methods even when t1.method implementation is overridden\n  expect(Class.prototype.method).toHaveBeenCalledTimes(3)\n})\n\ntest('instance methods and prototype method share the state', () => {\n  const { Class } = mockModule()\n  const t1 = vi.mocked(new Class())\n\n  expect(t1.method.mock).toEqual(Class.prototype.method.mock)\n\n  t1.method('hello world', Symbol.for('example'))\n\n  expect(t1.method.mock.calls[0][0]).toBe('hello world')\n  expect(t1.method.mock.calls[0][1]).toBe(Symbol.for('example'))\n\n  expect(t1.method.mock.instances[0]).toBe(t1)\n  expect(t1.method.mock.contexts[0]).toBe(t1)\n  expect(t1.method.mock.results[0]).toEqual({\n    type: 'return',\n    value: undefined,\n  })\n\n  expect(Class.prototype.method.mock.calls[0][0]).toBe('hello world')\n  expect(Class.prototype.method.mock.calls[0][1]).toBe(Symbol.for('example'))\n\n  expect(t1.method.mock).toEqual(Class.prototype.method.mock)\n\n  const t2 = vi.mocked(new Class())\n\n  t2.method('bye world')\n\n  expect(t1.method).toHaveBeenCalledTimes(1)\n  expect(t2.method).toHaveBeenCalledTimes(1)\n\n  expect(t2.method.mock.calls[0][0]).toBe('bye world')\n  // note that Class.prototype.method keeps accumulating state\n  expect(Class.prototype.method.mock.calls[1][0]).toBe('bye world')\n})\n\ntest('instance methods inherit the implementation, but can override the local ones', () => {\n  const { Class } = mockModule()\n  const t1 = vi.mocked(new Class())\n  const t2 = vi.mocked(new Class())\n\n  t1.method.mockReturnValue(100)\n  expect(t1.method()).toBe(100)\n  expect(t1.method).toHaveBeenCalled()\n  expect(t2.method).not.toHaveBeenCalled()\n\n  expect(Class.prototype.method).toHaveBeenCalledTimes(1)\n\n  Class.prototype.method.mockReturnValue(200)\n  expect(t1.method()).toBe(100)\n  expect(t2.method()).toBe(200)\n\n  expect(Class.prototype.method).toHaveBeenCalledTimes(3)\n\n  vi.resetAllMocks()\n\n  expect(t1.method()).toBe(undefined)\n  expect(t2.method()).toBe(undefined)\n\n  Class.prototype.method.mockReturnValue(300)\n\n  expect(t1.method()).toBe(300)\n  expect(t2.method()).toBe(300)\n})\n\ntest('vi.mockReset() does not break inherited properties', () => {\n  const { Class } = mockModule()\n  const instance1 = new Class()\n\n  expect(instance1.method()).toBe(undefined)\n\n  expect(instance1.method).toHaveBeenCalledTimes(1)\n  expect(Class.prototype.method).toHaveBeenCalledTimes(1)\n\n  vi.mocked(instance1.method).mockReturnValue(100)\n\n  expect(instance1.method()).toBe(100)\n\n  expect(instance1.method).toHaveBeenCalledTimes(2)\n  expect(Class.prototype.method).toHaveBeenCalledTimes(2)\n\n  vi.resetAllMocks()\n\n  expect(instance1.method()).toBe(undefined)\n\n  expect(instance1.method).toHaveBeenCalledTimes(1)\n  expect(Class.prototype.method).toHaveBeenCalledTimes(1)\n\n  const instance2 = new Class()\n  const instance3 = new Class()\n\n  instance2.method()\n\n  expect(instance2.method).not.toBe(instance3.method)\n\n  expect(instance2.method).toHaveBeenCalledTimes(1)\n  expect(instance3.method).toHaveBeenCalledTimes(0)\n})\n\ntest('the array is empty by default', () => {\n  const { array } = vi.mockObject({\n    array: [1, 2, 3],\n  })\n  expect(array).toEqual([])\n})\n\ntest('the array is not empty when spying', () => {\n  const { array } = vi.mockObject(\n    {\n      array: [\n        1,\n        'text',\n        () => 42,\n        {\n          property: 'static',\n          answer() {\n            return 42\n          },\n          array: [1],\n        },\n      ] as const,\n    },\n    { spy: true },\n  )\n\n  expect(array).toHaveLength(4)\n  expect(array[0]).toBe(1)\n  expect(array[1]).toBe('text')\n  expect(vi.isMockFunction(array[2])).toBe(true)\n  expect(array[2]()).toBe(42)\n  expect(array[3].property).toBe('static')\n  expect(array[3].answer()).toBe(42)\n  expect(array[3].answer).toHaveBeenCalled()\n  expect(array[3].array).toEqual([1])\n})\n\nfunction mockModule(type: 'automock' | 'autospy' = 'automock') {\n  return vi.mockObject({\n    [Symbol.toStringTag]: 'Module',\n    __esModule: true,\n    method(..._args: any[]) {\n      return 42\n    },\n    Class: class {\n      method(..._args: any[]) {\n        return 42\n      }\n    },\n  }, { spy: type === 'autospy' })\n}\n"
  },
  {
    "path": "test/core/test/mocking/vi-spyOn.test.ts",
    "content": "import type { MockContext } from 'vitest'\nimport { describe, expect, test, vi } from 'vitest'\n\ndescribe('vi.spyOn() edge cases', () => {\n  test('vi.spyOn() has correct length', () => {\n    const fn0 = vi.spyOn({ fn: () => {} }, 'fn')\n    expect(fn0.length).toBe(0)\n\n    const fnArgs = vi.spyOn({ fn: (..._args: any[]) => {} }, 'fn')\n    expect(fnArgs.length).toBe(0)\n\n    const fn1 = vi.spyOn({ fn: (_arg1: any) => {} }, 'fn')\n    expect(fn1.length).toBe(1)\n\n    const fn2 = vi.spyOn({ fn: (_arg1: any, _arg2: any) => {} }, 'fn')\n    expect(fn2.length).toBe(2)\n\n    const fn3 = vi.spyOn({ fn: (_arg1: any, _arg2: any, _arg3: any) => {} }, 'fn')\n    expect(fn3.length).toBe(3)\n  })\n\n  test('can spy on a proxy with undefined descriptor\\'s value', () => {\n    const obj = new Proxy<{ fn: () => number }>({} as any, {\n      get(_, prop) {\n        if (prop === 'fn') {\n          return () => 42\n        }\n      },\n      getOwnPropertyDescriptor(_, prop) {\n        if (prop === 'fn') {\n          return {\n            configurable: true,\n            enumerable: true,\n            value: undefined,\n            writable: true,\n          }\n        }\n      },\n    })\n    const spy = vi.spyOn(obj, 'fn')\n    expect(spy()).toBe(42)\n  })\n\n  describe('vi.spyOn() copies static properties', () => {\n    test('vi.spyOn() copies properties from functions', () => {\n      function a() {}\n      a.HELLO_WORLD = true\n      const obj = {\n        a,\n      }\n\n      const spy = vi.spyOn(obj, 'a')\n\n      expect(obj.a.HELLO_WORLD).toBe(true)\n      expect(spy.HELLO_WORLD).toBe(true)\n    })\n\n    test('vi.spyOn() copies properties from classes', () => {\n      class A {\n        static HELLO_WORLD = true\n      }\n      const obj = {\n        A,\n      }\n\n      const spy = vi.spyOn(obj, 'A')\n\n      expect(obj.A.HELLO_WORLD).toBe(true)\n      expect(spy.HELLO_WORLD).toBe(true)\n    })\n\n    test('vi.spyOn() ignores node.js.promisify symbol', () => {\n      const promisifySymbol = Symbol.for('nodejs.util.promisify.custom')\n      class Example {\n        static [promisifySymbol] = () => Promise.resolve(42)\n      }\n      const obj = { Example }\n\n      const spy = vi.spyOn(obj, 'Example')\n\n      expect(spy[promisifySymbol]).toBe(undefined)\n    })\n  })\n})\n\ndescribe('vi.spyOn() state', () => {\n  test('vi.spyOn() spies on an object and tracks the calls', () => {\n    const object = createObject()\n    const mock = vi.spyOn(object, 'method')\n\n    expect(object.method).toBe(mock)\n    expect(vi.isMockFunction(object.method)).toBe(true)\n\n    const state = mock.mock\n\n    assertStateEmpty(state)\n\n    object.method()\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 42 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 42 }])\n    expect(state.instances).toEqual([object])\n    expect(state.contexts).toEqual([object])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    mock.mockClear()\n    assertStateEmpty(state)\n\n    object.method()\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 42 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 42 }])\n    expect(state.instances).toEqual([object])\n    expect(state.contexts).toEqual([object])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    vi.clearAllMocks()\n    assertStateEmpty(state)\n  })\n\n  test('vi.spyOn() spies and tracks overridden sync calls', () => {\n    const object = createObject()\n    const mock = vi.spyOn(object, 'method')\n    mock.mockImplementation(() => 100)\n    const state = mock.mock\n\n    assertStateEmpty(state)\n\n    object.method()\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 100 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 100 }])\n    expect(state.instances).toEqual([object])\n    expect(state.contexts).toEqual([object])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    mock.mockClear()\n    assertStateEmpty(state)\n\n    object.method()\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 100 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 100 }])\n    expect(state.instances).toEqual([object])\n    expect(state.contexts).toEqual([object])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    vi.clearAllMocks()\n    assertStateEmpty(state)\n  })\n\n  test('vi.spyOn() spies and tracks overridden sync calls with context', () => {\n    const object = createObject()\n    const mock = vi.spyOn(object, 'method')\n    mock.mockImplementation(() => 100)\n    const state = mock.mock\n    const context = {}\n\n    assertStateEmpty(state)\n\n    object.method.call(context)\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 100 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 100 }])\n    expect(state.instances).toEqual([context])\n    expect(state.contexts).toEqual([context])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    mock.mockClear()\n    assertStateEmpty(state)\n\n    object.method.call(context)\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 100 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 100 }])\n    expect(state.instances).toEqual([context])\n    expect(state.contexts).toEqual([context])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    vi.clearAllMocks()\n    assertStateEmpty(state)\n  })\n\n  test('vi.spyOn() spies and tracks overridden sync prototype calls with context', () => {\n    const object = createObject()\n    const mock = vi.spyOn(object, 'method')\n    mock.mockImplementation(function (this: any) {\n      this.value = 42\n      return 100\n    })\n    const state = mock.mock\n    const context = {}\n\n    assertStateEmpty(state)\n\n    object.method.call(context)\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 100 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 100 }])\n    expect(state.instances).toEqual([{ value: 42 }])\n    expect(state.contexts).toEqual([{ value: 42 }])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    mock.mockClear()\n    assertStateEmpty(state)\n\n    object.method.call(context)\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: 100 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 100 }])\n    expect(state.instances).toEqual([{ value: 42 }])\n    expect(state.contexts).toEqual([{ value: 42 }])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    vi.clearAllMocks()\n    assertStateEmpty(state)\n  })\n\n  test('vi.spyOn() spies and tracks overridden sync class calls with context', () => {\n    const object = createObject()\n    const mock = vi.spyOn(object, 'Class')\n    mock.mockImplementation(class {\n      public value: number\n      constructor() {\n        this.value = 42\n      }\n    })\n    const state = mock.mock\n\n    assertStateEmpty(state)\n\n    const instance1 = new object.Class()\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: instance1 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: instance1 }])\n    expect(state.instances).toEqual([instance1])\n    expect(state.contexts).toEqual([instance1])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    mock.mockClear()\n    assertStateEmpty(state)\n\n    const instance2 = new object.Class()\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: instance2 }])\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: instance2 }])\n    expect(state.instances).toEqual([instance2])\n    expect(state.contexts).toEqual([instance2])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    vi.clearAllMocks()\n    assertStateEmpty(state)\n  })\n\n  test('vi.spyOn() spies and tracks overridden async calls', async () => {\n    const object = createObject()\n    const mock = vi.spyOn(object, 'async')\n    mock.mockImplementation(() => Promise.resolve(100))\n    const state = mock.mock\n\n    assertStateEmpty(state)\n\n    const promise1 = object.async()\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: expect.any(Promise) }])\n    expect(state.settledResults).toEqual([{ type: 'incomplete', value: undefined }])\n    expect(state.instances).toEqual([object])\n    expect(state.contexts).toEqual([object])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    await promise1\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 100 }])\n\n    mock.mockClear()\n    assertStateEmpty(state)\n\n    const promise2 = object.async()\n    expect(state.calls).toEqual([[]])\n    expect(state.results).toEqual([{ type: 'return', value: expect.any(Promise) }])\n    expect(state.settledResults).toEqual([{ type: 'incomplete', value: undefined }])\n    expect(state.instances).toEqual([object])\n    expect(state.contexts).toEqual([object])\n    expect(state.lastCall).toEqual([])\n    expect(state.invocationCallOrder).toEqual([expect.any(Number)])\n\n    await promise2\n    expect(state.settledResults).toEqual([{ type: 'fulfilled', value: 100 }])\n\n    vi.clearAllMocks()\n    assertStateEmpty(state)\n  })\n\n  test('vi.spyOn() doesn\\'t loose context', () => {\n    const instances: any[] = []\n    const Names = function Names(this: any) {\n      instances.push(this)\n      this.array = [1]\n    } as {\n      (): void\n      new (): typeof obj\n    }\n    const obj = {\n      array: [],\n      Names,\n    }\n\n    vi.spyOn(obj, 'Names')\n\n    const s = new obj.Names()\n\n    expect(obj.array).toEqual([])\n    expect(s.array).toEqual([1])\n    expect(instances[0]).toEqual({ array: [1] })\n\n    obj.Names()\n\n    expect(obj.array).toEqual([1])\n  })\n})\n\ndescribe('vi.spyOn() settings', () => {\n  test('vi.spyOn() when spying on a method spy returns the same spy', () => {\n    const object = createObject()\n    const spy1 = vi.spyOn(object, 'method')\n    const spy2 = vi.spyOn(object, 'method')\n    expect(spy1).toBe(spy2)\n\n    object.method()\n    expect(spy2.mock.calls).toEqual(spy2.mock.calls)\n  })\n\n  test('vi.spyOn() when spying on a getter spy returns the same spy', () => {\n    const object = createObject()\n    const spy1 = vi.spyOn(object, 'getter', 'get')\n    const spy2 = vi.spyOn(object, 'getter', 'get')\n    expect(spy1).toBe(spy2)\n\n    const _example = object.getter\n    expect(spy2).toHaveBeenCalledTimes(1)\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2.mock.calls).toEqual(spy1.mock.calls)\n  })\n\n  test('vi.spyOn() when spying on a setter spy returns the same spy', () => {\n    const object = createObject()\n    const spy1 = vi.spyOn(object, 'getter', 'set')\n    const spy2 = vi.spyOn(object, 'getter', 'set')\n    expect(spy1).toBe(spy2)\n\n    object.getter = 33\n    expect(spy2).toHaveBeenCalledTimes(1)\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2.mock.calls).toEqual(spy1.mock.calls)\n  })\n\n  test('vi.spyOn() when spying on a static getter spy returns the same spy', () => {\n    const object = createObject()\n    const spy1 = vi.spyOn(object, 'static', 'get')\n    const spy2 = vi.spyOn(object, 'static', 'get')\n    expect(spy1).toBe(spy2)\n\n    const _example = object.static\n    expect(spy2).toHaveBeenCalledTimes(1)\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2.mock.calls).toEqual(spy1.mock.calls)\n  })\n\n  test('vi.spyOn() when spying on a static setter spy returns the same spy', () => {\n    const object = createObject()\n    const spy1 = vi.spyOn(object, 'static', 'set')\n    const spy2 = vi.spyOn(object, 'static', 'set')\n    expect(spy1).toBe(spy2)\n\n    object.static = 33\n    expect(spy2).toHaveBeenCalledTimes(1)\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2.mock.calls).toEqual(spy1.mock.calls)\n  })\n\n  test('vi.spyOn() can spy on multiple class instances without intervention', () => {\n    class Example {\n      method() {\n        return 42\n      }\n    }\n\n    const example1 = new Example()\n    const example2 = new Example()\n\n    const mock1 = vi.spyOn(example1, 'method')\n    const mock2 = vi.spyOn(example2, 'method')\n\n    example1.method()\n    expect(mock1.mock.calls).toHaveLength(1)\n    expect(mock2.mock.calls).toHaveLength(0)\n\n    example1.method()\n    expect(mock1.mock.calls).toHaveLength(2)\n    expect(mock2.mock.calls).toHaveLength(0)\n\n    example2.method()\n    expect(mock1.mock.calls).toHaveLength(2)\n    expect(mock2.mock.calls).toHaveLength(1)\n  })\n\n  test('vi.spyOn() can spy on a prototype', () => {\n    class Example {\n      method() {\n        return 42\n      }\n    }\n\n    const example = new Example()\n    const spy = vi.spyOn(example, 'method')\n    expect(example.method()).toBe(42)\n    expect(spy.mock.calls).toEqual([[]])\n    expect(vi.isMockFunction(Example.prototype.method)).toBe(false)\n  })\n\n  test('vi.spyOn() can spy on inherited methods', () => {\n    class Bar {\n      _bar = 'bar'\n      get bar(): string {\n        return this._bar\n      }\n\n      set bar(bar: string) {\n        this._bar = bar\n      }\n    }\n    class Foo extends Bar {}\n    const foo = new Foo()\n    vi.spyOn(foo, 'bar', 'get').mockImplementation(() => 'foo')\n    expect(foo.bar).toEqual('foo')\n    // foo.bar setter is inherited from Bar, so we can set it\n    expect(() => {\n      foo.bar = 'baz'\n    }).not.toThrow()\n    expect(foo.bar).toEqual('foo')\n  })\n\n  test('vi.spyOn() inherits overridden methods', () => {\n    class Bar {\n      _bar = 'bar'\n      get bar(): string {\n        return this._bar\n      }\n\n      set bar(bar: string) {\n        this._bar = bar\n      }\n    }\n    class Foo extends Bar {\n      get bar(): string {\n        return `${super.bar}-foo`\n      }\n    }\n    const foo = new Foo()\n    expect(foo.bar).toEqual('bar-foo')\n    vi.spyOn(foo, 'bar', 'get').mockImplementation(() => 'foo')\n    expect(foo.bar).toEqual('foo')\n    // foo.bar setter is not inherited from Bar\n    expect(() => {\n      // @ts-expect-error bar cannot be overridden\n      foo.bar = 'baz'\n    }).toThrow()\n    expect(foo.bar).toEqual('foo')\n  })\n\n  test('vi.spyOn().mockReset() resets the implementation', () => {\n    const object = createObject()\n    const spy = vi.spyOn(object, 'method').mockImplementation(() => 100)\n    expect(object.method()).toBe(100)\n    spy.mockReset()\n    expect(object.method()).toBe(42)\n  })\n\n  test('vi.spyOn() resets the implementation in resetAllMocks', () => {\n    const object = createObject()\n    vi.spyOn(object, 'method').mockImplementation(() => 100)\n    expect(object.method()).toBe(100)\n    vi.resetAllMocks()\n    expect(object.method()).toBe(42)\n  })\n\n  test('vi.spyOn() returns undefined as mockImplementation', () => {\n    const object = createObject()\n    const spy = vi.spyOn(object, 'method')\n    expect(spy.getMockImplementation()).toBe(undefined)\n  })\n\n  test('vi.spyOn() returns implementation if it was set', () => {\n    const implementation = () => 42\n    const object = createObject()\n    const spy = vi.spyOn(object, 'method').mockImplementation(implementation)\n    expect(spy.getMockImplementation()).toBe(implementation)\n    spy.mockReset()\n    expect(spy.getMockImplementation()).toBe(undefined)\n  })\n\n  test('vi.spyOn() returns mockOnceImplementation if it was set', () => {\n    const implementation = () => 42\n    const object = createObject()\n    const spy = vi.spyOn(object, 'method').mockImplementationOnce(implementation)\n    expect(spy.getMockImplementation()).toBe(implementation)\n  })\n\n  test('vi.spyOn() returns withImplementation if it was set', () => {\n    const implementation = () => 42\n    const object = createObject()\n    const spy = vi.spyOn(object, 'method')\n    spy.withImplementation(implementation, () => {\n      expect(spy.getMockImplementation()).toBe(implementation)\n    })\n  })\n\n  test('vi.spyOn() has a name', () => {\n    const object = createObject()\n    const spy = vi.spyOn(object, 'method')\n    expect(spy.getMockName()).toBe('method')\n    spy.mockName('test')\n    expect(spy.getMockName()).toBe('test')\n    spy.mockReset()\n    expect(spy.getMockName()).toBe('method')\n    spy.mockName('test')\n    expect(spy.getMockName()).toBe('test')\n    vi.resetAllMocks()\n    expect(spy.getMockName()).toBe('method')\n  })\n})\n\ndescribe('vi.spyOn() restoration', () => {\n  test('vi.spyOn() cannot spy on undefined or null', () => {\n    expect(() => vi.spyOn(undefined as any, 'test')).toThrow('The vi.spyOn() function could not find an object to spy upon. The first argument must be defined.')\n    expect(() => vi.spyOn(null as any, 'test')).toThrow('The vi.spyOn() function could not find an object to spy upon. The first argument must be defined.')\n  })\n\n  test('vi.spyOn() cannot spy on a primitive value', () => {\n    expect(() => vi.spyOn('string' as any, 'toString')).toThrow('Vitest cannot spy on a primitive value.')\n    expect(() => vi.spyOn(0 as any, 'toString')).toThrow('Vitest cannot spy on a primitive value.')\n    expect(() => vi.spyOn(true as any, 'toString')).toThrow('Vitest cannot spy on a primitive value.')\n    expect(() => vi.spyOn(1n as any, 'toString')).toThrow('Vitest cannot spy on a primitive value.')\n    expect(() => vi.spyOn(Symbol.toStringTag as any, 'toString')).toThrow('Vitest cannot spy on a primitive value.')\n  })\n\n  test('vi.spyOn() cannot spy on non-existing property', () => {\n    expect(() => vi.spyOn({} as any, 'never')).toThrow('The property \"never\" is not defined on the object.')\n  })\n\n  test('vi.spyOn() restores the original method when .mockRestore() is called', () => {\n    const object = createObject()\n    const spy = vi.spyOn(object, 'method')\n    object.method()\n    expect(vi.isMockFunction(object.method)).toBe(true)\n    expect(spy.mock.calls).toHaveLength(1)\n    spy.mockRestore()\n    expect(vi.isMockFunction(object.method)).toBe(false)\n    expect(spy.mock.calls).toHaveLength(0)\n  })\n\n  test('vi.spyOn() restores the original method when vi.restoreAllMocks() is called', () => {\n    const object = createObject()\n    const spy = vi.spyOn(object, 'method')\n    object.method()\n    expect(vi.isMockFunction(object.method)).toBe(true)\n    expect(spy.mock.calls).toHaveLength(1)\n    vi.restoreAllMocks()\n    expect(vi.isMockFunction(object.method)).toBe(false)\n    // unlike vi.mockRestore(), the state is not cleared\n    // this is important for module mocking\n    expect(spy.mock.calls).toHaveLength(1)\n  })\n\n  test('vi.spyOn() can respy the metthod with new state when vi.restoreAllMocks() is called', () => {\n    const object = createObject()\n    const spy1 = vi.spyOn(object, 'method').mockImplementation(() => 100)\n\n    expect(object.method()).toBe(100)\n    expect(spy1.mock.calls).toHaveLength(1)\n    vi.restoreAllMocks()\n\n    const spy2 = vi.spyOn(object, 'method').mockImplementation(() => 33)\n    expect(object.method()).toBe(33)\n    expect(spy2.mock.calls).toHaveLength(1)\n  })\n\n  test('vi.spyOn() restores the original getter when .mockRestore() is called', () => {\n    const object = createObject()\n    const spy = vi.spyOn(object, 'getter', 'get').mockImplementation(() => 100)\n\n    expect(object.getter).toBe(100)\n    expect(spy.mock.calls).toHaveLength(1)\n    spy.mockRestore()\n\n    expect(spy.mock.calls).toHaveLength(0)\n    expect(object.getter).toBe(42)\n  })\n\n  test('vi.spyOn() restores the original getter when vi.restoreAllMocks() is called', () => {\n    const object = createObject()\n    const spy = vi.spyOn(object, 'getter', 'get').mockImplementation(() => 100)\n\n    expect(object.getter).toBe(100)\n    expect(spy.mock.calls).toHaveLength(1)\n    vi.restoreAllMocks()\n\n    // unlike vi.mockRestore(), the state is not cleared\n    // this is important for module mocking\n    expect(spy.mock.calls).toHaveLength(1)\n    expect(object.getter).toBe(42)\n  })\n\n  test('vi.spyOn() can respy the getter with new state when vi.restoreAllMocks() is called', () => {\n    const object = createObject()\n    const spy1 = vi.spyOn(object, 'getter', 'get').mockImplementation(() => 100)\n\n    expect(object.getter).toBe(100)\n    expect(spy1.mock.calls).toHaveLength(1)\n    vi.restoreAllMocks()\n\n    const spy2 = vi.spyOn(object, 'getter', 'get').mockImplementation(() => 33)\n    expect(object.getter).toBe(33)\n    expect(spy2.mock.calls).toHaveLength(1)\n  })\n\n  test('vi.spyOn() restores the original setter when .mockRestore() is called', () => {\n    const object = createObject()\n    const spy = vi.spyOn(object, 'getter', 'set').mockImplementation(() => {\n      // do nothing\n    })\n\n    object.getter = 100\n\n    expect(object.getter).toBe(42) // getter was not overridden\n    expect(spy.mock.calls).toHaveLength(1)\n    spy.mockRestore()\n\n    object.getter = 33\n\n    expect(spy.mock.calls).toHaveLength(0)\n    expect(object.getter).toBe(33)\n  })\n\n  test('vi.spyOn() restores the original getter when vi.restoreAllMocks() is called', () => {\n    const object = createObject()\n    const spy = vi.spyOn(object, 'getter', 'set').mockImplementation(() => {\n      // do nothing\n    })\n\n    object.getter = 100\n\n    expect(object.getter).toBe(42) // getter was not overridden\n    expect(spy.mock.calls).toHaveLength(1)\n    vi.restoreAllMocks()\n\n    // unlike vi.mockRestore(), the state is not cleared\n    // this is important for module mocking\n    expect(spy.mock.calls).toHaveLength(1)\n\n    object.getter = 33\n\n    expect(object.getter).toBe(33)\n  })\n\n  test('vi.spyOn() can respy the getter with new state when vi.restoreAllMocks() is called', () => {\n    const object = createObject()\n    const spy1 = vi.spyOn(object, 'getter', 'set').mockImplementation(() => {\n      // do nothing\n    })\n\n    object.getter = 100\n\n    expect(object.getter).toBe(42)\n    expect(spy1.mock.calls).toHaveLength(1)\n    vi.restoreAllMocks()\n\n    let called = false\n    const spy2 = vi.spyOn(object, 'getter', 'set').mockImplementation(() => {\n      called = true\n    })\n\n    object.getter = 84\n\n    expect(called).toBe(true)\n    expect(object.getter).toBe(42)\n    expect(spy2.mock.calls).toHaveLength(1)\n  })\n})\n\ndescribe('vi.spyOn() on Vite SSR', () => {\n  test('vi.spyOn() throws an error if a getter returns a non-function value in SSR', () => {\n    const module = {\n      get primitive() {\n        return 42\n      },\n    }\n    expect(() => {\n      // @ts-expect-error types recognize it's not a function\n      vi.spyOn(module, 'primitive')\n    }).toThrow('vi.spyOn() can only spy on a function. Received number.')\n  })\n\n  test('vi.spyOn() assigns the method on a getter', () => {\n    const method = () => {}\n    const module = {\n      get method() {\n        return method\n      },\n    }\n    const spy = vi.spyOn(module, 'method')\n    expect(spy.getMockImplementation()).toBe(undefined)\n\n    module.method()\n    expect(spy.mock.calls).toEqual([[]])\n    expect(module.method).toBe(spy)\n\n    spy.mockRestore()\n    expect(module.method).toBe(method)\n  })\n\n  test('vi.spyOn() can reassign the SSR getter method', () => {\n    const method = () => {}\n    const module = {\n      get method() {\n        return method\n      },\n    }\n    const spy1 = vi.spyOn(module, 'method')\n    const spy2 = vi.spyOn(module, 'method')\n    expect(vi.isMockFunction(spy1)).toBe(true)\n    expect(vi.isMockFunction(spy2)).toBe(true)\n    expect(spy1).toBe(spy2)\n\n    module.method()\n    expect(spy1.mock.calls).toEqual([[]])\n    expect(spy2.mock.calls).toEqual([[]])\n  })\n})\n\nfunction assertStateEmpty(state: MockContext<any>) {\n  expect(state.calls).toHaveLength(0)\n  expect(state.results).toHaveLength(0)\n  expect(state.settledResults).toHaveLength(0)\n  expect(state.contexts).toHaveLength(0)\n  expect(state.instances).toHaveLength(0)\n  expect(state.lastCall).toBe(undefined)\n  expect(state.invocationCallOrder).toEqual([])\n}\n\nfunction createObject() {\n  let getterValue = 42\n  return {\n    Class: class {},\n    method() {\n      return 42\n    },\n    async() {\n      return Promise.resolve(42)\n    },\n    get getter() {\n      return getterValue\n    },\n    set getter(value: number) {\n      getterValue = value\n    },\n    static: 42,\n  }\n}\n"
  },
  {
    "path": "test/core/test/mocking/virtual.test.ts",
    "content": "// @ts-expect-error virtual module\nimport * as virtual from 'virtual-module'\n\nimport { expect, it, vi } from 'vitest'\n\n// @ts-expect-error vscode is not installed\nimport * as vscodeFactory from 'vscode-factory'\n// @ts-expect-error vscode is not installed\nimport * as vscodeMocks from 'vscode-mocks'\n\nvi.mock('vscode-mocks')\nvi.mock('vscode-factory', () => {\n  return { factory: true }\n})\nvi.mock('virtual-module')\n\nit('mocks not installed in mocks folder', () => {\n  expect(vscodeMocks.folder).toBe(true)\n})\n\nit('mocks not installed in mocks factory', () => {\n  expect(vscodeFactory.factory).toBe(true)\n})\n\nit('mocks virtual modules in mocks folder', () => {\n  expect(virtual.value).toBe('folder')\n})\n"
  },
  {
    "path": "test/core/test/modes.test.ts",
    "content": "import { afterAll, afterEach, assert, beforeAll, beforeEach, describe, expect, it } from 'vitest'\nimport { timeout } from '../src/timeout'\n\ndescribe.skip('skipped suite', () => {\n  beforeAll(() => {\n    throw new Error('should not run')\n  })\n\n  beforeEach(() => {\n    throw new Error('should not run')\n  })\n\n  afterEach(() => {\n    throw new Error('should not run')\n  })\n\n  afterAll(() => {\n    throw new Error('should not run')\n  })\n\n  it('no fail as suite is skipped', () => {\n    assert.equal(Math.sqrt(4), 3)\n  })\n})\n\ndescribe.todo('unimplemented suite')\n\ndescribe('test modes', () => {\n  it.skip('no fail as it test is skipped', () => {\n    assert.equal(Math.sqrt(4), 3)\n  })\n\n  it.todo('unimplemented test')\n})\n\nfunction delay(ms: number) {\n  return new Promise(resolve => setTimeout(resolve, ms))\n}\n\ndescribe('concurrent tests', () => {\n  let count = 0\n\n  const counterTest = (c: number) => async () => {\n    assert.equal(count, c)\n    await delay(20)\n    count++\n  }\n\n  it('s1', counterTest(0))\n\n  it.concurrent.skip('concurrent-skip', counterTest(-1))\n  it.skip.concurrent('skip-concurrent', counterTest(-1))\n\n  it.concurrent('c1', counterTest(1))\n  it.concurrent('c2', counterTest(1))\n  it.concurrent('c3', counterTest(1))\n\n  it('s2', counterTest(4))\n  it('s2', counterTest(5))\n\n  it.concurrent('c4', counterTest(6))\n  it.concurrent('c5', counterTest(6))\n\n  it.concurrent.todo('concurrent-todo')\n  it.todo.concurrent('todo-concurrent')\n})\n\ndescribe.concurrent('concurrent suite', () => {\n  let count = 0\n\n  const counterTest = (c: number) => async () => {\n    assert.equal(count, c)\n    await delay(20)\n    count++\n  }\n\n  it('s1', counterTest(0))\n\n  it.concurrent.skip('concurrent-skip', counterTest(-1))\n  it.skip.concurrent('skip-concurrent', counterTest(-1))\n\n  it.concurrent('c1', counterTest(0))\n  it.concurrent('c2', counterTest(0))\n  it.concurrent('c3', counterTest(0))\n\n  it('s2', counterTest(0))\n  it('s2', counterTest(0))\n\n  it.concurrent('c4', counterTest(0))\n  it.concurrent('c5', counterTest(0))\n\n  it.concurrent.todo('concurrent-todo')\n  it.todo.concurrent('todo-concurrent')\n})\n\nit('timeout', () => new Promise(resolve => setTimeout(resolve, timeout)))\n\ndescribe('test.only in nested described', () => {\n  describe('nested describe', () => {\n    it('skipped test', () => {\n      assert.equal(Math.sqrt(4), 3) // doesn't fails, as the next is it.only\n    })\n    it.only('focus test. Should fails', () => {\n      assert.equal(Math.sqrt(4), 2)\n    })\n  })\n})\n\nit.fails('should fails', () => {\n  expect(1).toBe(2)\n})\n"
  },
  {
    "path": "test/core/test/module-diagnostic.test.ts",
    "content": "import type { File } from '@vitest/runner/types'\nimport type { TestModule } from 'vitest/node'\nimport { expect, test } from 'vitest'\nimport { runInlineTests } from '../../test-utils'\n\n// TODO: write comprehensive tests\ntest.skip('123', async () => {\n  const source = `\nimport {} from './hello-world'\nimport { test } from 'vitest'\n// import 'side-effect'\n// import * as m from 'module-import'\n// import * as m2 from \"module-import-2\"\ntest('hello world')\n    `\n  const { fs, ctx } = await runInlineTests({\n    'source.test.js': source,\n    'hello-world': '',\n  })\n  const file = fs.resolveFile('./source.test.js')\n\n  const testFile = ctx!.state.filesMap.get(file) as File[] | undefined\n  const testModule = testFile?.length ? ctx!.state.getReportedEntity(testFile[0]) as TestModule : undefined\n  const diagnostic = await ctx!.experimental_getSourceModuleDiagnostic(file, testModule)\n  expect(diagnostic).toBeDefined()\n})\n"
  },
  {
    "path": "test/core/test/module.test.ts",
    "content": "import { external as viteEnvironmentExternal } from '@test/vite-environment-external'\nimport { external as viteExternal } from '@test/vite-external'\n\nimport { describe, expect, it } from 'vitest'\n\n// @ts-expect-error is not typed with imports\nimport * as arrayCjs from '../src/cjs/array-cjs'\n\n// @ts-expect-error is not typed with imports\nimport bareCjs, { a as bareA, b as bareB } from '../src/cjs/bare-cjs'\n\n// @ts-expect-error is not typed with imports\nimport * as classCjs from '../src/cjs/class-cjs'\n\nimport format from '../src/cjs/default-function'\n\n// @ts-expect-error is not typed\nimport cjs, { a, b } from '../src/cjs/module-cjs'\n\n// @ts-expect-error is not typed with imports\nimport * as nestedDefaultCjs from '../src/cjs/nested-default-cjs'\n\n// @ts-expect-error is not typed with imports\nimport primitiveCjs, { a as primitiveA } from '../src/cjs/primitive-cjs'\n\n// @ts-expect-error is not typed with imports\nimport * as primitiveAll from '../src/cjs/primitive-cjs'\n\n// @ts-expect-error is not typed with imports\nimport * as prototypeCjs from '../src/cjs/prototype-cjs'\n\n// @ts-expect-error is not typed with imports\nimport * as prototypeEsm from '../src/esm/esm.js'\n\n// @ts-expect-error is not typed with imports\nimport * as internalEsm from '../src/esm/internal-esm.mjs'\n\n// @ts-expect-error is not typed with imports\nimport * as moduleDefaultCjs from '../src/external/default-cjs'\n\n// @ts-expect-error is not typed with imports\nimport * as nestedDefaultExternalCjs from '../src/external/nested-default-cjs'\nimport c, { d } from '../src/module-esm'\n\nimport * as timeout from '../src/timeout'\n\nit('extect vite.noExternal to be respected', () => {\n  expect(viteExternal).toBe(false)\n  expect(viteEnvironmentExternal).toBe(false)\n})\n\nit('doesn\\'t when extending module', () => {\n  expect(() => Object.assign(globalThis, timeout)).not.toThrow()\n})\n\ndescribe('validating nested defaults in isolation', () => {\n  it.each([\n    nestedDefaultCjs,\n    nestedDefaultExternalCjs,\n  ])('nested default should be resolved', (mod) => {\n    expect(mod).toHaveProperty('default')\n    expect(mod.default).not.toHaveProperty('default')\n    expect(mod.default.a).toBe('a')\n    expect(mod.default.b).toBe('b')\n    expect(mod.a).toBe('a')\n    expect(mod.b).toBe('b')\n  })\n\n  it('externalized \"module.exports\" CJS module interops default', () => {\n    expect(moduleDefaultCjs).toHaveProperty('default')\n    expect(moduleDefaultCjs.default).toHaveProperty('a')\n    expect(moduleDefaultCjs.default.a).toBe('a')\n    expect(moduleDefaultCjs).toHaveProperty('a')\n    expect(moduleDefaultCjs.a).toBe('a')\n  })\n})\n\nit('should work when using module.exports cjs', () => {\n  expect(cjs.a).toBe(1)\n  expect(cjs.b).toBe(2)\n  expect(a).toBe(1)\n  expect(b).toBe(2)\n})\n\nit('works with bare exports cjs', () => {\n  expect(bareCjs.a).toBe('a')\n  expect(bareCjs.b).toBe('b')\n  expect(bareCjs.c).toBe('c')\n  expect(bareA).toBe('a')\n  expect(bareB).toBe('b')\n})\n\nit('primitive cjs retains its logic', () => {\n  expect(primitiveA).toBeUndefined()\n  expect(primitiveCjs).toBe('string')\n  expect(primitiveAll.default).toBe('string')\n  expect(primitiveAll, 'doesn\\'t put chars from \"string\" on exports').not.toHaveProperty('0')\n})\n\nit('arrays-cjs', () => {\n  expect(arrayCjs.default).toEqual([1, '2'])\n  expect(arrayCjs).not.toHaveProperty('0')\n})\n\nit('class-cjs', () => {\n  expect(classCjs.default).toEqual({ variable: 1, Test: expect.any(Function) })\n  expect(classCjs.default).toBeInstanceOf(classCjs.Test)\n  expect(classCjs, 'for compat with ESM it also defines props on Module').toHaveProperty('variable')\n})\n\nit('should work when using esm module', () => {\n  expect(c).toBe(1)\n  expect(d).toBe(2)\n})\n\nit('exports all from native ESM module', () => {\n  expect(internalEsm).toHaveProperty('restoreAll')\n})\n\nit('cjs has object prototype', () => {\n  expect(prototypeCjs.getPrototype()).toBe(Object.prototype)\n  expect(() => prototypeCjs.test()).not.toThrow()\n  expect(prototypeCjs.test()).toBe(true)\n})\n\nit('esm prototype is null', () => {\n  expect(Object.getPrototypeOf(prototypeEsm)).toBe(null)\n  expect({}.hasOwnProperty).toBeTypeOf('function')\n\n  expect(prototypeEsm.hasOwnProperty).toBeTypeOf('undefined')\n})\n\ndescribe('correctly puts default on default', () => {\n  it('works on default function', () => {\n    expect(format()).toBe('')\n  })\n\n  it('works on nested default function', () => {\n    // @ts-expect-error types defined only default\n    expect(format.default).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "test/core/test/moved-snapshot.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('snapshot is stored close to file', () => {\n  expect('moved snapshot').toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/core/test/moved-snapshot.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`snapshot is stored close to file 1`] = `\"moved snapshot\"`;\n"
  },
  {
    "path": "test/core/test/named-overwrite-all.test.ts",
    "content": "import { expect, test } from 'vitest'\n// @ts-expect-error no type\nimport * as lib from './fixtures/named-overwrite-all/main.js'\n\ntest('named exports overwrite export all', async () => {\n  expect(lib).toMatchInlineSnapshot(`\n    {\n      \"a\": \"main-a\",\n      \"b\": \"dep1-b\",\n      \"c\": \"main-c\",\n      \"d\": \"dep1-d\",\n    }\n  `)\n})\n"
  },
  {
    "path": "test/core/test/nested-only.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('nested only behavior', () => {\n  describe.only('describe.only with nested test.only', () => {\n    it.only('should be the only test that runs', () => {\n      expect(true).toBe(true)\n    })\n\n    it('should NOT run because the previous test has test.only', () => {\n      throw new Error('This test should not run')\n    })\n  })\n\n  describe('another suite', () => {\n    it('should not run - outside describe.only', () => {\n      throw new Error('This test should not run')\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/nested-suite.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\nlet visited = false\n\nit('visited before', () => {\n  expect(visited).toBe(false)\n})\n\ndescribe('a', () => {\n  describe('b', () => {\n    describe('c', () => {\n      describe('d', () => {\n        describe('e', () => {\n          it('very deep', () => {\n            expect(true).toBe(true)\n            visited = true\n            expect('hi').toMatchSnapshot('msg')\n          })\n        })\n      })\n    })\n  })\n})\n\nit('visited', () => {\n  expect(visited).toBe(true)\n})\n\nit('suite inside test should throw', () => {\n  expect(() => {\n    describe('inside test', () => {})\n  }).toThrowErrorMatchingInlineSnapshot(`[Error: Calling the suite function inside test function is not allowed. It can be only called at the top level or inside another suite function.]`)\n})\n"
  },
  {
    "path": "test/core/test/nested-test.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\ntest('nested test should throw error', () => {\n  expect(() => {\n    test('test inside test', () => {})\n  }).toThrowErrorMatchingInlineSnapshot(`[Error: Calling the test function inside another test function is not allowed. Please put it inside \"describe\" or \"suite\" so it can be properly collected.]`)\n\n  expect(() => {\n    test.each([1, 2, 3])('test.each inside test %d', () => {})\n  }).toThrowErrorMatchingInlineSnapshot(`[Error: Calling the test function inside another test function is not allowed. Please put it inside \"describe\" or \"suite\" so it can be properly collected.]`)\n\n  expect(() => {\n    test.skipIf(false)('test.skipIf inside test', () => {})\n  }).toThrowErrorMatchingInlineSnapshot(`[Error: Calling the test function inside another test function is not allowed. Please put it inside \"describe\" or \"suite\" so it can be properly collected.]`)\n})\n\ndescribe('parallel tests', () => {\n  test.concurrent('parallel test 1 with nested test', () => {\n    expect(() => {\n      test('test inside test', () => {})\n    }).toThrowErrorMatchingInlineSnapshot(`[Error: Calling the test function inside another test function is not allowed. Please put it inside \"describe\" or \"suite\" so it can be properly collected.]`)\n  })\n  test.concurrent('parallel test 2 without nested test', () => {})\n  test.concurrent('parallel test 3 without nested test', () => {})\n  test.concurrent('parallel test 4 with nested test', () => {\n    expect(() => {\n      test('test inside test', () => {})\n    }).toThrowErrorMatchingInlineSnapshot(`[Error: Calling the test function inside another test function is not allowed. Please put it inside \"describe\" or \"suite\" so it can be properly collected.]`)\n  })\n})\n"
  },
  {
    "path": "test/core/test/node-protocol-jsdom.spec.ts",
    "content": "// @vitest-environment jsdom\n\nimport nodeUrl from 'node:url'\n// outdated url package, which Vite will resolve to, if \"url\" import is used\n// this should help catch bugs in source code\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport packageUrl from 'url'\nimport { expect, it } from 'vitest'\n\nit('vitest resolves url to installed url package, but node:url to internal Node module', () => {\n  expect(packageUrl).not.toHaveProperty('URL')\n  expect(packageUrl).not.toHaveProperty('URLSearchParams')\n  expect(packageUrl).not.toHaveProperty('fileURLToPath')\n  expect(nodeUrl).toHaveProperty('URL')\n  expect(nodeUrl).toHaveProperty('URLSearchParams')\n  expect(nodeUrl).toHaveProperty('fileURLToPath')\n\n  // eslint-disable-next-line node/no-deprecated-api\n  expect(packageUrl.parse !== nodeUrl.parse).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/node-protocol-node.spec.ts",
    "content": "// @vitest-environment node\n\nimport nodeUrl from 'node:url'\n// eslint-disable-next-line unicorn/prefer-node-protocol\nimport packageUrl from 'url'\nimport { expect, it } from 'vitest'\n\nit('vitest resolves both \"url\" and \"node:url\" to internal URL module in Node environment', () => {\n  expect(packageUrl).toHaveProperty('URL')\n  expect(packageUrl).toHaveProperty('URLSearchParams')\n  expect(packageUrl).toHaveProperty('fileURLToPath')\n  expect(nodeUrl).toHaveProperty('URL')\n  expect(nodeUrl).toHaveProperty('URLSearchParams')\n  expect(nodeUrl).toHaveProperty('fileURLToPath')\n  expect(packageUrl.URL === nodeUrl.URL).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/on-failed.test.ts",
    "content": "import { expect, it, onTestFailed } from 'vitest'\n\nconst collected: any[] = []\n\nit.fails('on-failed', () => {\n  const square3 = 3 ** 2\n  const square4 = 4 ** 2\n\n  onTestFailed(() => {\n    collected.push({ square3, square4 })\n  })\n\n  expect(Math.sqrt(square3 + square4)).toBe(4)\n})\n\nit('after', () => {\n  expect(collected).toMatchInlineSnapshot(`\n    [\n      {\n        \"square3\": 9,\n        \"square4\": 16,\n      },\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/core/test/on-finished.test.ts",
    "content": "import { describe, expect, it, onTestFailed, onTestFinished } from 'vitest'\n\nconst collected: any[] = []\nconst multiple: any[] = []\n\nit('on-finished regular', () => {\n  collected.push(1)\n  onTestFinished(() => {\n    collected.push(3)\n  })\n  collected.push(2)\n})\n\nit('on-finished context', ({ onTestFinished }) => {\n  collected.push(4)\n  onTestFinished(() => {\n    collected.push(6)\n  })\n  collected.push(5)\n})\n\nit.fails('failed finish', () => {\n  collected.push(7)\n  onTestFinished(() => {\n    collected.push(9)\n  })\n  collected.push(8)\n  expect.fail('failed')\n  collected.push(null)\n})\n\nit.fails('failed finish context', ({ onTestFinished }) => {\n  collected.push(10)\n  onTestFinished(() => {\n    collected.push(12)\n  })\n  collected.push(11)\n  expect.fail('failed')\n  collected.push(null)\n})\n\nit('multiple on-finished', () => {\n  onTestFinished(() => {\n    multiple.push(1)\n  })\n  onTestFinished(() => {\n    multiple.push(2)\n  })\n  onTestFinished(async () => {\n    await new Promise(r => setTimeout(r, 100))\n    multiple.push(3)\n  })\n  onTestFinished(() => {\n    multiple.push(4)\n  })\n})\n\nit('after', () => {\n  expect(collected).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])\n  expect(multiple).toEqual([4, 3, 2, 1])\n})\n\ndescribe('repeats pass', () => {\n  const state: string[] = []\n\n  it('run', { repeats: 2 }, (t) => {\n    const tag = `(${t.task.result?.retryCount}, ${t.task.result?.repeatCount}) `\n    state.push(`${tag}run`)\n\n    onTestFinished(() => {\n      state.push(`${tag}finish`)\n    })\n\n    onTestFailed(() => {\n      state.push(`${tag}fail`)\n    })\n  })\n\n  it('assert', () => {\n    expect(state).toMatchInlineSnapshot(`\n      [\n        \"(0, 0) run\",\n        \"(0, 0) finish\",\n        \"(0, 1) run\",\n        \"(0, 1) finish\",\n        \"(0, 2) run\",\n        \"(0, 2) finish\",\n      ]\n    `)\n  })\n})\n\ndescribe('repeats fail', () => {\n  const state: string[] = []\n\n  it.fails('run', { repeats: 2 }, (t) => {\n    const tag = `(${t.task.result?.retryCount}, ${t.task.result?.repeatCount}) `\n    state.push(`${tag}run`)\n\n    onTestFinished(() => {\n      state.push(`${tag}finish`)\n    })\n\n    onTestFailed(() => {\n      state.push(`${tag}fail`)\n    })\n\n    if (t.task.result?.repeatCount === 1) {\n      throw new Error('fail')\n    }\n  })\n\n  it('assert', () => {\n    expect(state).toMatchInlineSnapshot(`\n      [\n        \"(0, 0) run\",\n        \"(0, 0) finish\",\n        \"(0, 1) run\",\n        \"(0, 1) finish\",\n        \"(0, 1) fail\",\n        \"(0, 2) run\",\n        \"(0, 2) finish\",\n        \"(0, 2) fail\",\n      ]\n    `)\n  })\n})\n\ndescribe('retry pass', () => {\n  const state: string[] = []\n\n  it('run', { retry: 2 }, (t) => {\n    const tag = `(${t.task.result?.retryCount}, ${t.task.result?.repeatCount}) `\n    state.push(`${tag}run`)\n\n    onTestFinished(() => {\n      state.push(`${tag}finish`)\n    })\n\n    onTestFailed(() => {\n      state.push(`${tag}fail`)\n    })\n\n    if (t.task.result?.retryCount && t.task.result?.retryCount > 1) {\n      return\n    }\n    throw new Error('fail')\n  })\n\n  it('assert', () => {\n    expect(state).toMatchInlineSnapshot(`\n      [\n        \"(0, 0) run\",\n        \"(0, 0) finish\",\n        \"(0, 0) fail\",\n        \"(1, 0) run\",\n        \"(1, 0) finish\",\n        \"(1, 0) fail\",\n        \"(2, 0) run\",\n        \"(2, 0) finish\",\n      ]\n    `)\n  })\n})\n\ndescribe('retry fail', () => {\n  const state: string[] = []\n\n  it.fails('run', { retry: 2 }, (t) => {\n    const tag = `(${t.task.result?.retryCount}, ${t.task.result?.repeatCount}) `\n    state.push(`${tag}run`)\n\n    onTestFinished(() => {\n      state.push(`${tag}finish`)\n    })\n\n    onTestFailed(() => {\n      state.push(`${tag}fail`)\n    })\n\n    throw new Error('fail')\n  })\n\n  it('assert', () => {\n    expect(state).toMatchInlineSnapshot(`\n      [\n        \"(0, 0) run\",\n        \"(0, 0) finish\",\n        \"(0, 0) fail\",\n        \"(1, 0) run\",\n        \"(1, 0) finish\",\n        \"(1, 0) fail\",\n        \"(2, 0) run\",\n        \"(2, 0) finish\",\n        \"(2, 0) fail\",\n      ]\n    `)\n  })\n})\n"
  },
  {
    "path": "test/core/test/only.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\nconst run = [false, false, false, false]\n\nit.only('visited before', () => {\n  expect(run.some(Boolean)).toBe(false)\n})\n\ndescribe('a0', () => {\n  it.only('0', () => {\n    run[0] = true\n  })\n  it('s0', () => {\n    expect(true).toBe(false)\n  })\n})\n\ndescribe('a1', () => {\n  describe('b1', () => {\n    describe('c1', () => {\n      it.only('1', () => {\n        run[1] = true\n      })\n    })\n    it('s1', () => {\n      expect(true).toBe(false)\n    })\n  })\n})\n\ndescribe.only('a2', () => {\n  it('2', () => {\n    run[2] = true\n  })\n})\n\nit('s2', () => {\n  expect(true).toBe(false)\n})\n\ndescribe.only('a3', () => {\n  describe('b3', () => {\n    it('3', () => {\n      run[3] = true\n    })\n  })\n  it.skip('s3', () => {\n    expect(true).toBe(false)\n  })\n})\n\ndescribe('a4', () => {\n  describe.only('b4', () => {\n    it('4', () => {\n      run[4] = true\n    })\n  })\n  describe('sb4', () => {\n    it('s4', () => {\n      expect(true).toBe(false)\n    })\n  })\n})\n\nit.only('visited', () => {\n  expect(run.every(Boolean)).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/parse-cjs-conditions.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { parseCjsConditions } from '../../../packages/vitest/src/runtime/vm/commonjs-executor'\n\ndescribe('parseCjsConditions', () => {\n  it('returns default conditions with no arguments', () => {\n    const result = parseCjsConditions([], undefined)\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons']))\n  })\n\n  it('parses --conditions=value from execArgv', () => {\n    const result = parseCjsConditions(['--conditions=custom'], undefined)\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons', 'custom']))\n  })\n\n  it('parses --conditions value (space-separated) from execArgv', () => {\n    const result = parseCjsConditions(['--conditions', 'custom'], undefined)\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons', 'custom']))\n  })\n\n  it('parses -C=value from execArgv', () => {\n    const result = parseCjsConditions(['-C=custom'], undefined)\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons', 'custom']))\n  })\n\n  it('parses -C value (space-separated) from execArgv', () => {\n    const result = parseCjsConditions(['-C', 'custom'], undefined)\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons', 'custom']))\n  })\n\n  it('parses conditions from NODE_OPTIONS', () => {\n    const result = parseCjsConditions([], '--conditions=custom')\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons', 'custom']))\n  })\n\n  it('parses space-separated conditions from NODE_OPTIONS', () => {\n    const result = parseCjsConditions([], '--conditions custom')\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons', 'custom']))\n  })\n\n  it('handles multiple conditions from both sources', () => {\n    const result = parseCjsConditions(\n      ['--conditions=from-cli', '-C', 'another'],\n      '--conditions=from-env',\n    )\n    expect(result).toEqual(new Set([\n      'node',\n      'require',\n      'node-addons',\n      'from-cli',\n      'another',\n      'from-env',\n    ]))\n  })\n\n  it('filters out module-sync', () => {\n    const result = parseCjsConditions(['--conditions=module-sync'], undefined)\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons']))\n  })\n\n  it('filters out module-sync but keeps other conditions', () => {\n    const result = parseCjsConditions(\n      ['--conditions=module-sync', '--conditions=custom'],\n      undefined,\n    )\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons', 'custom']))\n  })\n\n  it('ignores unrelated execArgv entries', () => {\n    const result = parseCjsConditions(\n      ['--experimental-vm-modules', '-e', 'console.log(\"hi\")'],\n      undefined,\n    )\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons']))\n  })\n\n  it('ignores trailing --conditions with no value', () => {\n    const result = parseCjsConditions(['--conditions'], undefined)\n    expect(result).toEqual(new Set(['node', 'require', 'node-addons']))\n  })\n})\n"
  },
  {
    "path": "test/core/test/pattern.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('pattern', () => {\n  const size = 10\n  const g = '🟩'\n  const r = '🟥'\n\n  function pattern() {\n    return Array.from({ length: size })\n      .map((_, y) => Array.from({ length: size })\n        .map((__, x) => {\n          return (x * y) % 3 ? g : r\n        }))\n      .map(i => i.join(' '))\n      .join('\\n')\n  }\n\n  expect(`\\n${pattern()}`).toMatchInlineSnapshot(`\n\"\n🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥\n🟥 🟩 🟩 🟥 🟩 🟩 🟥 🟩 🟩 🟥\n🟥 🟩 🟩 🟥 🟩 🟩 🟥 🟩 🟩 🟥\n🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥\n🟥 🟩 🟩 🟥 🟩 🟩 🟥 🟩 🟩 🟥\n🟥 🟩 🟩 🟥 🟩 🟩 🟥 🟩 🟩 🟥\n🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥\n🟥 🟩 🟩 🟥 🟩 🟩 🟥 🟩 🟩 🟥\n🟥 🟩 🟩 🟥 🟩 🟩 🟥 🟩 🟩 🟥\n🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥 🟥\"`)\n})\n"
  },
  {
    "path": "test/core/test/propagate-options-nested-suite.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('suite name', { retry: 9 }, () => {\n  let outerCount = 0\n\n  it('should retry until success', () => {\n    outerCount++\n    expect(outerCount).toBe(5)\n  })\n\n  describe('nested', () => {\n    let innerCount = 0\n\n    it('should retry until success (nested)', () => {\n      innerCount++\n      expect(innerCount).toBe(5)\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/random.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\n// tests use seed of 101, so they have deterministic random order\nconst numbers: number[] = []\n\ndescribe.shuffle('random tests', () => {\n  describe('suite unshuffle', { shuffle: false }, () => {\n    test('inside 1', () => {\n      numbers.push(1)\n    })\n    test('inside 1.5', () => {\n      numbers.push(1.5)\n    })\n    test('inside 2', () => {\n      numbers.push(2)\n    })\n\n    describe('suite shuffle', { shuffle: true }, () => {\n      test('inside 2.1', () => {\n        numbers.push(2.1)\n      })\n      test('inside 2.2', () => {\n        numbers.push(2.2)\n      })\n      test('inside 2.3', () => {\n        numbers.push(2.3)\n      })\n    })\n  })\n\n  test('test 1', () => {\n    numbers.push(3)\n  })\n  test('test 2', () => {\n    numbers.push(4)\n  })\n  test('test 3', () => {\n    numbers.push(5)\n  })\n})\n\ntest('assert', () => {\n  expect(numbers).toMatchInlineSnapshot(`\n      [\n        4,\n        5,\n        3,\n        1,\n        1.5,\n        2,\n        2.2,\n        2.3,\n        2.1,\n      ]\n    `)\n})\n"
  },
  {
    "path": "test/core/test/repeats.test.ts",
    "content": "import { getCurrentTest } from '@vitest/runner'\nimport { afterAll, describe, expect, test } from 'vitest'\n\nconst testNumbers: number[] = []\n\ndescribe('testing it/test', () => {\n  const result = [1, 1, 1, 1, 1, 2, 2, 2]\n\n  test('test 1', { repeats: 4 }, () => {\n    testNumbers.push(1)\n  })\n\n  test('test 2', { repeats: 2 }, () => {\n    testNumbers.push(2)\n  })\n\n  test.fails('test 3', { repeats: 0 }, () => {\n    testNumbers.push(3)\n    expect(testNumbers).toStrictEqual(result)\n  })\n\n  afterAll(() => {\n    result.push(3)\n    expect(testNumbers).toStrictEqual(result)\n  })\n})\n\nconst describeNumbers: number[] = []\n\ndescribe('testing describe', { repeats: 2 }, () => {\n  test('test 1', () => {\n    describeNumbers.push(1)\n  })\n})\n\nafterAll(() => {\n  expect(describeNumbers).toStrictEqual([1, 1, 1])\n})\n\nconst retryNumbers: number[] = []\n\ndescribe('testing repeats with retry', () => {\n  describe('normal test', () => {\n    const result = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]\n    test.fails('test 1', { repeats: 4, retry: 1 }, () => {\n      retryNumbers.push(1)\n      expect(1).toBe(2)\n    })\n\n    afterAll(() => {\n      expect(retryNumbers).toStrictEqual(result)\n    })\n  })\n\n  test('should not reset retry count', { repeats: 2, retry: 1 }, () => {\n    expect(getCurrentTest()!.result?.retryCount).toBe(3)\n  })\n})\n\nconst nestedDescribeNumbers: number[] = []\n\ndescribe('testing nested describe', { repeats: 1 }, () => {\n  test ('test 1', () => {\n    nestedDescribeNumbers.push(1)\n  })\n\n  describe('nested 1', () => {\n    test('test 2', () => {\n      nestedDescribeNumbers.push(2)\n    })\n\n    describe('nested 2', { repeats: 2 }, () => {\n      test('test 3', () => {\n        nestedDescribeNumbers.push(3)\n      })\n\n      describe('nested 3', () => {\n        test('test 4', () => {\n          nestedDescribeNumbers.push(4)\n        })\n      }, 100)\n    })\n  })\n\n  afterAll(() => {\n    expect(nestedDescribeNumbers).toStrictEqual([1, 1, 2, 2, 3, 3, 3, 4, 4, 4])\n  })\n})\n"
  },
  {
    "path": "test/core/test/replace-matcher.test.ts",
    "content": "import { replaceAsymmetricMatcher } from '@vitest/utils/diff'\nimport { describe, expect, it } from 'vitest'\n\ndescribe('replace asymmetric matcher', () => {\n  const expectReplaceAsymmetricMatcher = (actual: any, expected: any) => {\n    const replaced = replaceAsymmetricMatcher(actual, expected)\n    expect(replaced.replacedActual).toEqual(replaced.replacedExpected)\n  }\n  it('should work when various types are passed in', () => {\n    expectReplaceAsymmetricMatcher(null, null)\n    expectReplaceAsymmetricMatcher(undefined, undefined)\n    expectReplaceAsymmetricMatcher({}, {})\n    expectReplaceAsymmetricMatcher([1, 2], [1, 2])\n    expectReplaceAsymmetricMatcher({}, expect.any(Object))\n    expectReplaceAsymmetricMatcher(() => {}, expect.any(Function))\n    expectReplaceAsymmetricMatcher(Promise, expect.any(Function))\n    expectReplaceAsymmetricMatcher(false, expect.any(Boolean))\n    expectReplaceAsymmetricMatcher([1, 2], [1, expect.any(Number)])\n    expectReplaceAsymmetricMatcher(false, expect.anything())\n    expectReplaceAsymmetricMatcher({}, expect.anything())\n    expectReplaceAsymmetricMatcher(Symbol, expect.anything())\n    expectReplaceAsymmetricMatcher(Promise, expect.anything())\n    expectReplaceAsymmetricMatcher(new Map([['a', 1]]), expect.anything())\n    expectReplaceAsymmetricMatcher(new Set([1, 2]), expect.anything())\n    expectReplaceAsymmetricMatcher(new ArrayBuffer(8), expect.anything())\n    expectReplaceAsymmetricMatcher([1, 2], [1, expect.anything()])\n    expectReplaceAsymmetricMatcher({\n      str: 'a',\n      arr: [1, 2],\n    }, {\n      str: expect.any(String),\n      arr: expect.anything(),\n    })\n    expectReplaceAsymmetricMatcher({\n      str: expect.any(String),\n      arr: expect.anything(),\n    }, {\n      str: expect.any(String),\n      arr: expect.anything(),\n    })\n    expectReplaceAsymmetricMatcher({\n      str: 'a',\n      arr: [1, 2],\n    }, {\n      str: expect.any(String),\n      arr: [1, expect.anything()],\n    })\n    const circleObj: any = { name: 'circle', ref: null }\n    circleObj.ref = circleObj\n    expectReplaceAsymmetricMatcher(circleObj, circleObj)\n  })\n})\n"
  },
  {
    "path": "test/core/test/require.test.ts",
    "content": "// @vitest-environment jsdom\n\nimport { describe, expect, it } from 'vitest'\n\nconst _require = require\n\ndescribe('using \"require\" to import a module', () => {\n  it('importing css files works, but doesn\\'t process them', () => {\n    const css = _require('./../src/file-css.css')\n    const sass = _require('./../src/file-sass.sass')\n    const scss = _require('./../src/file-scss.scss')\n    const less = _require('./../src/file-less.less')\n\n    expect(css).toEqual('')\n    expect(sass).toEqual('')\n    expect(scss).toEqual('')\n    expect(less).toEqual('')\n  })\n\n  it('importing assets works', () => {\n    const path = _require.resolve('./../src/file-txt.txt')\n    expect(_require('./../src/file-txt.txt')).toBe(path)\n  })\n})\n"
  },
  {
    "path": "test/core/test/resolve-file-url.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('resolve file url', async () => {\n  const fileUrl = new URL('./resolve-file-url%7Edep.js', import.meta.url).href\n  const mod = await import(fileUrl)\n  expect(mod.default).toMatchInlineSnapshot(`\"[ok]\"`)\n\n  const mod2 = await import(`${fileUrl}#hash=test`)\n  expect(mod2).toEqual(mod)\n  expect(mod2).not.toBe(mod)\n\n  const mod3 = await import(`${fileUrl}?query=test`)\n  expect(mod3).toEqual(mod)\n  expect(mod3).not.toBe(mod)\n})\n"
  },
  {
    "path": "test/core/test/resolve-file-url~dep.js",
    "content": "export default '[ok]'\n"
  },
  {
    "path": "test/core/test/resolve-ssr.test.ts",
    "content": "// @vitest-environment node\n\nimport { expect, test } from 'vitest'\nimport pkgBrowser from '../src/external/pkg-browser'\nimport pkgNode from '../src/external/pkg-node'\n\ntest('[ssr] resolves to ssr, when node is first in conditions', () => {\n  expect(pkgNode).toBe('ssr')\n})\n\ntest('[ssr] resolves to ssr, when browser is first in conditions', () => {\n  expect(pkgBrowser).toBe('ssr')\n})\n"
  },
  {
    "path": "test/core/test/resolve-web.test.ts",
    "content": "// @vitest-environment happy-dom\n\nimport { expect, test } from 'vitest'\nimport pkgBrowser from '../src/external/pkg-browser'\nimport pkgNode from '../src/external/pkg-node'\n\ntest('[web] resolves to ssr, when node is first in conditions', () => {\n  expect(pkgNode).toBe('ssr')\n})\n\ntest('[web] resolves to ssr, when browser is first in conditions', () => {\n  expect(pkgBrowser).toBe('ssr')\n})\n"
  },
  {
    "path": "test/core/test/retry-condition.test.ts",
    "content": "import type { TestError } from 'vitest'\nimport { describe, expect, it } from 'vitest'\n\n// Test with RegExp condition that eventually passes\nlet matchingCount = 0\nit('retry with matching condition', {\n  retry: {\n    count: 5,\n    condition: /retry/i,\n  },\n}, () => {\n  matchingCount += 1\n  if (matchingCount < 3) {\n    throw new Error('Please retry this test')\n  }\n  // Third attempt succeeds\n})\n\nit('verify matching condition retried', () => {\n  expect(matchingCount).toBe(3)\n})\n\n// Test with no condition (should retry all errors)\nlet noConditionCount = 0\nit('retry without condition', { retry: 2 }, () => {\n  noConditionCount += 1\n  expect(noConditionCount).toBe(3)\n})\n\nit('verify no condition retried all attempts', () => {\n  expect(noConditionCount).toBe(3)\n})\n\n// Test with function condition\nlet functionCount = 0\nconst condition = (error: TestError) => error.name === 'TimeoutError'\n\nit('retry with function condition', {\n  retry: {\n    count: 5,\n    condition,\n  },\n}, () => {\n  functionCount += 1\n  const err: any = new Error('Test failed')\n  err.name = 'TimeoutError'\n  if (functionCount < 3) {\n    throw err\n  }\n  // Third attempt succeeds\n})\n\nit('verify function condition worked', () => {\n  expect(functionCount).toBe(3)\n})\n\ndescribe('retry condition with describe', {\n  retry: {\n    count: 2,\n    condition: /flaky/i,\n  },\n}, () => {\n  let describeCount = 0\n  it('test should inherit retryCondition from describe block', () => {\n    describeCount += 1\n    if (describeCount === 1) {\n      throw new Error('Flaky test error')\n    }\n    // Second attempt succeeds\n  })\n})\n"
  },
  {
    "path": "test/core/test/retry-delay.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\nlet delayCount = 0\nlet delayStart = 0\n\nit('retry with delay', {\n  retry: {\n    count: 2,\n    delay: 100,\n  },\n}, () => {\n  if (delayCount === 0) {\n    delayStart = Date.now()\n  }\n  delayCount += 1\n  expect(delayCount).toBe(3)\n})\n\nit('verify delay was applied', () => {\n  const duration = Date.now() - delayStart\n  expect(delayCount).toBe(3)\n  // With 2 retries and 100ms delay each, should take at least 200ms\n  expect(duration).toBeGreaterThanOrEqual(200)\n})\n\nlet zeroDelayCount = 0\n\nit('retry with zero delay', {\n  retry: {\n    count: 2,\n    delay: 0,\n  },\n}, () => {\n  zeroDelayCount += 1\n  expect(zeroDelayCount).toBe(3)\n})\n\nit('verify zero delay test passed', () => {\n  expect(zeroDelayCount).toBe(3)\n})\n\ndescribe('retry delay with describe', {\n  retry: {\n    count: 2,\n    delay: 50,\n  },\n}, () => {\n  let describeCount = 0\n  it('test should inherit retryDelay from describe block', () => {\n    describeCount += 1\n    expect(describeCount).toBe(2)\n  })\n})\n"
  },
  {
    "path": "test/core/test/retry-only.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe.only('description.only retry', { retry: 1 }, () => {\n  let count4 = 0\n  let count5 = 0\n  it('test should inherit options from the description block if missing', () => {\n    count4 += 1\n    expect(count4).toBe(2)\n  })\n\n  it('test should not inherit options from the description block if exists', { retry: 4 }, () => {\n    count5 += 1\n    expect(count5).toBe(5)\n  })\n})\n"
  },
  {
    "path": "test/core/test/retry.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\nlet count1 = 0\nit('retry test', { retry: 2 }, () => {\n  count1 += 1\n  expect(count1).toBe(3)\n})\n\nlet count2 = 0\nit.fails('retry test fails', { retry: 1 }, () => {\n  count2 += 1\n  expect(count2).toBe(3)\n})\n\nlet count3 = 0\nit('retry test fails', { retry: 10 }, () => {\n  count3 += 1\n  expect(count3).toBe(3)\n})\n\nit('result', () => {\n  expect(count1).toEqual(3)\n  expect(count2).toEqual(2)\n  expect(count3).toEqual(3)\n})\n\ndescribe('description retry', { retry: 2 }, () => {\n  let count4 = 0\n  let count5 = 0\n  it('test should inherit options from the description block if missing', () => {\n    count4 += 1\n    expect(count4).toBe(2)\n  })\n\n  it('test should not inherit options from the description block if exists', { retry: 5 }, () => {\n    count5 += 1\n    expect(count5).toBe(5)\n  })\n})\n\ndescribe.each([\n  { a: 1, b: 1, expected: 2 },\n  { a: 1, b: 2, expected: 3 },\n  { a: 2, b: 1, expected: 3 },\n])('describe object add($a, $b)', { retry: 2 }, ({ a, b, expected }) => {\n  let flag1 = false\n  let flag2 = false\n  let flag3 = false\n  it(`returns ${expected}`, () => {\n    flag1 = !flag1\n    expect(a + b).toBe(expected)\n    expect(flag1).toBe(false)\n  })\n\n  it(`returned value not be greater than ${expected}`, () => {\n    flag2 = !flag2\n    expect(a + b).not.toBeGreaterThan(expected)\n    expect(flag2).toBe(false)\n  })\n\n  it(`returned value not be less than ${expected}`, () => {\n    flag3 = !flag3\n    expect(a + b).not.toBeLessThan(expected)\n    expect(flag3).toBe(false)\n  })\n})\n\ndescribe('extended tests keep the options', () => {\n  const test$ = it.extend({\n    extended: true,\n  })\n\n  test$('inherits all options', { retry: 2, repeats: 1, timeout: 3456 }, ({ task, extended }) => {\n    expect(task.retry).toBe(2)\n    expect(task.repeats).toBe(1)\n    expect(task.timeout).toBe(3456)\n    expect(extended).toBe(true)\n  })\n})\n"
  },
  {
    "path": "test/core/test/rpc.spec.ts",
    "content": "import { afterAll, beforeAll, describe, test, vi } from 'vitest'\n\nconst { setTimeout } = globalThis\n\nfunction delay(timeout: number) {\n  return new Promise((resolve) => {\n    setTimeout(resolve, timeout)\n  })\n}\n\nfunction checkExtraTimers(location: string) {\n  const count = vi.getTimerCount()\n  if (count > 0) {\n    throw new Error(`got extra timers (${location}): ${count}`)\n  }\n}\n\nbeforeAll(() => {\n  vi.useFakeTimers()\n})\n\nafterAll(() => {\n  vi.useRealTimers()\n})\n\ndescribe.each([1, 2])('group %d', (group) => {\n  test('test', async () => {\n    checkExtraTimers(`group ${group}a`)\n    vi.advanceTimersByTime(60000 + 1)\n\n    await delay(10)\n\n    checkExtraTimers(`group ${group}b`)\n    vi.advanceTimersByTime(60000 + 1)\n  })\n})\n"
  },
  {
    "path": "test/core/test/run-if.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\ndescribe('runIf', () => {\n  const shouldSkip = true\n\n  it.skipIf(shouldSkip)('skipped', () => {\n    throw new Error('foo')\n  })\n\n  it.skipIf(!shouldSkip)('not skipped', () => {\n    expect(1).toBe(1)\n  })\n\n  it.runIf(!shouldSkip)('skipped 2', () => {\n    throw new Error('foo')\n  })\n\n  it.runIf(shouldSkip)('not skipped 2', () => {\n    expect(1).toBe(1)\n  })\n\n  /*\n  it.runIf(!shouldSkip).each([1, 2, 3])('works with each skipped', (num) => {\n    expect(Number.isInteger(num)).toBe(true)\n  })\n\n  it.runIf(shouldSkip).each([1, 2, 3])('works with each not skipped', (num) => {\n    expect(Number.isInteger(num)).toBe(true)\n  })\n  */\n})\n"
  },
  {
    "path": "test/core/test/self.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { foo } from '../src/self'\n\n// #1220 self export module\nit('self export', () => {\n  expect(foo()).toBe(true)\n})\n"
  },
  {
    "path": "test/core/test/sequencers.test.ts",
    "content": "import type { TestProject, Vitest } from 'vitest/node'\nimport { describe, expect, test, vi } from 'vitest'\nimport { BaseSequencer } from '../../../packages/vitest/src/node/sequencers/BaseSequencer'\nimport { RandomSequencer } from '../../../packages/vitest/src/node/sequencers/RandomSequencer'\nimport { TestSpecification } from '../../../packages/vitest/src/node/test-specification'\n\nfunction buildCtx(config?: Partial<Vitest['config']>) {\n  return {\n    config: {\n      sequence: { groupOrder: 0 },\n      ...config,\n    },\n    cache: {\n      getFileTestResults: vi.fn(),\n      getFileStats: vi.fn(),\n    },\n  } as unknown as Vitest\n}\n\nfunction buildWorkspace() {\n  return {\n    name: 'test',\n    config: {\n      root: import.meta.dirname,\n      sequence: { groupOrder: 0 },\n    },\n  } as any as TestProject\n}\n\nconst workspace = buildWorkspace()\n\nfunction workspaced(files: string[]) {\n  return files.map(file => new TestSpecification(workspace, file, 'forks'))\n}\n\ndescribe('base sequencer', () => {\n  test('sorting when no info is available', async () => {\n    const sequencer = new BaseSequencer(buildCtx())\n    const files = workspaced(['a', 'b', 'c'])\n    const sorted = await sequencer.sort(files)\n    expect(sorted).toStrictEqual(files)\n  })\n\n  test('prioritize unknown files', async () => {\n    const ctx = buildCtx()\n    vi.spyOn(ctx.cache, 'getFileStats').mockImplementation((file) => {\n      if (file === 'test:b') {\n        return { size: 2 }\n      }\n    })\n    const sequencer = new BaseSequencer(ctx)\n    const files = workspaced(['b', 'a', 'c'])\n    const sorted = await sequencer.sort(files)\n    expect(sorted).toStrictEqual(workspaced(['a', 'c', 'b']))\n  })\n\n  test('sort by size, larger first', async () => {\n    const ctx = buildCtx()\n    vi.spyOn(ctx.cache, 'getFileStats').mockImplementation((file) => {\n      if (file === 'test:a') {\n        return { size: 1 }\n      }\n      if (file === 'test:b') {\n        return { size: 2 }\n      }\n      if (file === 'test:c') {\n        return { size: 3 }\n      }\n    })\n    const sequencer = new BaseSequencer(ctx)\n    const files = workspaced(['b', 'a', 'c'])\n    const sorted = await sequencer.sort(files)\n    expect(sorted).toStrictEqual(workspaced(['c', 'b', 'a']))\n  })\n\n  test('sort by results, failed first', async () => {\n    const ctx = buildCtx()\n    vi.spyOn(ctx.cache, 'getFileTestResults').mockImplementation((file) => {\n      if (file === 'test:a') {\n        return { failed: false, duration: 1 }\n      }\n      if (file === 'test:b') {\n        return { failed: true, duration: 1 }\n      }\n      if (file === 'test:c') {\n        return { failed: true, duration: 1 }\n      }\n    })\n    const sequencer = new BaseSequencer(ctx)\n    const files = workspaced(['b', 'a', 'c'])\n    const sorted = await sequencer.sort(files)\n    expect(sorted).toStrictEqual(workspaced(['b', 'c', 'a']))\n  })\n\n  test('sort by results, long first', async () => {\n    const ctx = buildCtx()\n    vi.spyOn(ctx.cache, 'getFileTestResults').mockImplementation((file) => {\n      if (file === 'test:a') {\n        return { failed: true, duration: 1 }\n      }\n      if (file === 'test:b') {\n        return { failed: true, duration: 2 }\n      }\n      if (file === 'test:c') {\n        return { failed: true, duration: 3 }\n      }\n    })\n    const sequencer = new BaseSequencer(ctx)\n    const files = workspaced(['b', 'a', 'c'])\n    const sorted = await sequencer.sort(files)\n    expect(sorted).toStrictEqual(workspaced(['c', 'b', 'a']))\n  })\n\n  test('sort by results, long and failed first', async () => {\n    const ctx = buildCtx()\n    vi.spyOn(ctx.cache, 'getFileTestResults').mockImplementation((file) => {\n      if (file === 'test:a') {\n        return { failed: false, duration: 1 }\n      }\n      if (file === 'test:b') {\n        return { failed: false, duration: 6 }\n      }\n      if (file === 'test:c') {\n        return { failed: true, duration: 3 }\n      }\n    })\n    const sequencer = new BaseSequencer(ctx)\n    const files = workspaced(['b', 'a', 'c'])\n    const sorted = await sequencer.sort(files)\n    expect(sorted).toStrictEqual(workspaced(['c', 'b', 'a']))\n  })\n\n  test.each([\n    { files: 4, count: 3, expected: [2, 1, 1] },\n    { files: 5, count: 4, expected: [2, 1, 1, 1] },\n    { files: 9, count: 4, expected: [3, 2, 2, 2] },\n  ])('shard x/$count distributes $files files as $expected', async ({ count, files, expected }) => {\n    const specs = Array.from({ length: files }, (_, id) => ({ moduleId: `file-${id}.test.ts` } as TestSpecification))\n    const slices = []\n\n    for (const index of Array.from({ length: count }).keys()) {\n      const ctx = buildCtx({ root: '/example/root', shard: { index: 1 + index, count } })\n      const sequencer = new BaseSequencer(ctx)\n      const shard = await sequencer.shard(specs)\n\n      slices.push(shard.length)\n    }\n\n    expect(slices).toEqual(expected)\n\n    const sum = slices.reduce((total, current) => total + current, 0)\n    expect(sum).toBe(files)\n  })\n})\n\ndescribe('random sequencer', () => {\n  test('sorting is the same when seed is defined', async () => {\n    const ctx = buildCtx()\n    ctx.config.sequence.seed = 101\n    const sequencer = new RandomSequencer(ctx)\n    const files = workspaced(['b', 'a', 'c'])\n    const sorted = await sequencer.sort(files)\n    expect(sorted).toStrictEqual(workspaced(['a', 'c', 'b']))\n  })\n})\n"
  },
  {
    "path": "test/core/test/sequential.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\nconst delay = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout))\n\nfunction assertSequential() {\n  let count = 0\n\n  test('first test completes first', async ({ task }) => {\n    await delay(50)\n    expect(task.concurrent).toBeFalsy()\n    expect(++count).toBe(1)\n  })\n\n  test('second test completes second', ({ task }) => {\n    expect(task.concurrent).toBeFalsy()\n    expect(++count).toBe(2)\n  })\n\n  test.concurrent('third test completes fourth', async ({ task }) => {\n    await delay(50)\n    expect(task.concurrent).toBe(true)\n    expect(++count).toBe(4)\n  })\n\n  test.concurrent('fourth test completes third', ({ task }) => {\n    expect(task.concurrent).toBe(true)\n    expect(++count).toBe(3)\n  })\n}\n\nfunction assertConcurrent() {\n  let count = 0\n\n  test('first test completes second', async ({ task }) => {\n    await delay(50)\n    expect(task.concurrent).toBe(true)\n    expect(++count).toBe(2)\n  })\n\n  test('second test completes first', ({ task }) => {\n    expect(task.concurrent).toBe(true)\n    expect(++count).toBe(1)\n  })\n\n  test.sequential('third test completes third', async ({ task }) => {\n    await delay(50)\n    expect(task.concurrent).toBeFalsy()\n    expect(++count).toBe(3)\n  })\n\n  test.sequential('fourth test completes fourth', ({ task }) => {\n    expect(task.concurrent).toBeFalsy()\n    expect(++count).toBe(4)\n  })\n}\n\nassertSequential()\n\ndescribe.concurrent('describe.concurrent', () => {\n  assertConcurrent()\n\n  describe('describe', assertConcurrent)\n\n  describe.sequential('describe.sequential', () => {\n    assertSequential()\n\n    describe('describe', assertSequential)\n\n    describe.concurrent('describe.concurrent', assertConcurrent)\n  })\n})\n"
  },
  {
    "path": "test/core/test/serialize.test.ts",
    "content": "// @vitest-environment jsdom\n\nimport { serializeValue } from '@vitest/utils/serialize'\nimport { describe, expect, it } from 'vitest'\n\ndescribe('error serialize', () => {\n  it('works', () => {\n    expect(serializeValue(undefined)).toEqual(undefined)\n    expect(serializeValue(null)).toEqual(null)\n    expect(serializeValue('hi')).toEqual('hi')\n\n    expect(serializeValue({\n      foo: 'hi',\n      promise: new Promise(() => {}),\n      fn: () => {},\n      null: null,\n      symbol: Symbol('hi'),\n      nested: {\n        false: false,\n        class: class {},\n      },\n      // Intentionally test with a sparse array to verify it remains sparse during serialization.\n      // eslint-disable-next-line no-sparse-arrays\n      array: [1,, 3],\n    })).toMatchSnapshot()\n  })\n\n  it('Should skip circular references to prevent hit the call stack limit', () => {\n    const error: Record<string, any> = {\n      toString: () => {\n        return 'ops something went wrong'\n      },\n    }\n    error.whatever = error\n    error.whateverArray = [error, error]\n    error.whateverArrayClone = error.whateverArray\n\n    expect(serializeValue(error)).toMatchSnapshot()\n  })\n\n  it('Should handle object with getter/setter correctly', () => {\n    const user = {\n      name: 'John',\n      surname: 'Smith',\n\n      get fullName() {\n        return `${this.name} ${this.surname}`\n      },\n      set fullName(value) {\n        [this.name, this.surname] = value.split(' ')\n      },\n    }\n\n    expect(serializeValue(user)).toEqual({\n      name: 'John',\n      surname: 'Smith',\n      fullName: 'John Smith',\n    })\n  })\n\n  it('Should copy the full prototype chain including non-enumerable properties', () => {\n    const user = {\n      name: 'John',\n      surname: 'Smith',\n    }\n    Object.setPrototypeOf(user, {\n      name: 'Mr',\n      base: true,\n    })\n\n    Object.defineProperty(user, 'fullName', { enumerable: false, value: 'John Smith' })\n\n    const serialized = serializeValue(user)\n    expect(serialized).not.toBe(user)\n    expect(serialized).toEqual({\n      name: 'John',\n      surname: 'Smith',\n      fullName: 'John Smith',\n      base: true,\n    })\n  })\n\n  it('Should not retain the constructor of an object', () => {\n    // https://github.com/vitest-dev/vitest/issues/374\n    // Objects with `Error` constructors appear to cause problems during worker communication using\n    // `MessagePort`, so the serialized error object should have been recreated as plain object.\n    const error = new Error('test')\n\n    const serialized = serializeValue(error)\n    expect(Object.getPrototypeOf(serialized)).toBe(null)\n    expect(serialized).toEqual({\n      constructor: 'Function<Error>',\n      name: 'Error',\n      message: 'test',\n      stack: expect.any(String),\n      toString: 'Function<toString>',\n    })\n  })\n\n  it('Should not fail on errored getters/setters', () => {\n    const error = new Error('test')\n    Object.defineProperty(error, 'unserializable', {\n      get() {\n        throw new Error('I am unserializable')\n      },\n      set() {\n        throw new Error('I am unserializable')\n      },\n    })\n    Object.defineProperty(error, 'array', {\n      value: [{\n        get name() {\n          throw new Error('name cannot be accessed')\n        },\n      }],\n    })\n    expect(serializeValue(error)).toEqual({\n      array: [\n        {\n          name: '<unserializable>: name cannot be accessed',\n        },\n      ],\n      constructor: 'Function<Error>',\n      message: 'test',\n      name: 'Error',\n      stack: expect.stringContaining('Error: test'),\n      toString: 'Function<toString>',\n      unserializable: '<unserializable>: I am unserializable',\n    })\n  })\n\n  it('can serialize DOMException', () => {\n    const err = new DOMException('You failed', 'InvalidStateError')\n    expect(serializeValue(err)).toMatchObject({\n      NETWORK_ERR: 19,\n      name: 'InvalidStateError',\n      message: 'You failed',\n      stack: expect.stringContaining('InvalidStateError: You failed'),\n    })\n  })\n\n  it('correctly serialized immutables', () => {\n    const immutableList = {\n      '@@__IMMUTABLE_ITERABLE__@@': true,\n      toJSON() {\n        return ['foo']\n      },\n    }\n\n    const immutableRecord = {\n      '@@__IMMUTABLE_RECORD__@@': true,\n      toJSON() {\n        return { foo: 'bar' }\n      },\n    }\n\n    const error = new Error('test')\n    Object.assign(error, {\n      immutableList,\n      immutableRecord,\n    })\n\n    expect(serializeValue(error)).toMatchObject({\n      stack: expect.stringContaining('Error: test'),\n      immutableList: ['foo'],\n      immutableRecord: { foo: 'bar' },\n      name: 'Error',\n      message: 'test',\n    })\n  })\n\n  it('should serialize when toJSON does not return JSON-compatible object', () => {\n    class TestClass {}\n\n    const error = {\n      key: 'value',\n      // Still not serialized, thus second round of serialization is needed\n      toJSON() {\n        return {\n          key: 'value',\n          obj: {\n            fn: () => {},\n            class: TestClass,\n          },\n        }\n      },\n    }\n\n    const serialized = serializeValue(error)\n\n    expect(serialized).toEqual({\n      key: 'value',\n      obj: {\n        fn: 'Function<fn>',\n        class: 'Function<TestClass>',\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/setup.ts",
    "content": "import { vi } from 'vitest'\n\nvi.mock('../src/global-mock', () => ({ mocked: true }))\n"
  },
  {
    "path": "test/core/test/skip-reset-state.test.ts",
    "content": "import { getCurrentTest } from '@vitest/runner'\nimport { afterAll, expect, test } from 'vitest'\n\nafterAll(() => {\n  // verify \"current test\" resets after \"skip\"\n  expect(getCurrentTest()).toBeUndefined()\n})\n\ntest('single skipped test', ({ skip }) => {\n  skip()\n})\n"
  },
  {
    "path": "test/core/test/skip.test.ts",
    "content": "import EventEmitter from 'node:events'\nimport { expect, it } from 'vitest'\n\nconst sleep = (ms?: number) => new Promise(resolve => setTimeout(resolve, ms))\n\nit('correctly skips sync tests', ({ skip }) => {\n  skip()\n  expect(1).toBe(2)\n})\n\nit('correctly skips async tests with skip before async', async ({ skip }) => {\n  await sleep(100)\n  skip()\n  expect(1).toBe(2)\n})\n\nit('correctly skips async tests with async after skip', async ({ skip }) => {\n  skip()\n  await sleep(100)\n  expect(1).toBe(2)\n})\n\nit('correctly skips tests with callback', ({ skip }) => {\n  const emitter = new EventEmitter()\n  emitter.on('test', () => {\n    skip()\n  })\n  emitter.emit('test')\n  expect(1).toBe(2)\n})\n\nit('correctly skips tests with async callback', ({ skip }) => {\n  const emitter = new EventEmitter()\n  emitter.on('test', async () => {\n    skip()\n  })\n  emitter.emit('test')\n  expect(1).toBe(2)\n})\n"
  },
  {
    "path": "test/core/test/snapshot-1.txt",
    "content": "\n  white space\n"
  },
  {
    "path": "test/core/test/snapshot-2.txt",
    "content": "example: |\n  {\n    echo \"hello\"\n  }\nsome:\n  nesting:\n    - \"hello world\"\neven:\n  more:\n    nesting: true\n"
  },
  {
    "path": "test/core/test/snapshot-async.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nfunction resolve() {\n  return Promise.resolve('foo')\n}\nfunction reject() {\n  return Promise.reject(new Error('foo'))\n}\n\ntest('resolved inline', async () => {\n  await expect(resolve()).resolves.toMatchInlineSnapshot('\"foo\"')\n})\n\ntest('rejected inline', async () => {\n  await expect(reject()).rejects.toMatchInlineSnapshot('[Error: foo]')\n  await expect(reject()).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: foo]`)\n})\n"
  },
  {
    "path": "test/core/test/snapshot-concurrent-sync.test.ts",
    "content": "import { describe, it } from 'vitest'\n\n// from https://github.com/vitest-dev/vitest/issues/3361\ndescribe.concurrent('concurrent suite', () => {\n  it('snapshot', ({ expect }) => {\n    expect({ foo: 'bar' }).toMatchSnapshot()\n  })\n\n  it('empty test')\n})\n"
  },
  {
    "path": "test/core/test/snapshot-concurrent.test.ts",
    "content": "import { test } from 'vitest'\n\nconst data = [\n  'one',\n  'two',\n  'three',\n  'four',\n]\n\ndata.forEach((i) => {\n  test.concurrent(i, async ({ expect }) => {\n    await new Promise(resolve => setTimeout(resolve, Math.random() * 100))\n    expect(i).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "test/core/test/snapshot-custom-serializer.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('basic', () => {\n  // example from docs/guide/snapshot.md\n\n  const bar = {\n    foo: {\n      x: 1,\n      y: 2,\n    },\n  }\n\n  // without custom serializer\n  expect(bar).toMatchInlineSnapshot(`\n    {\n      \"foo\": {\n        \"x\": 1,\n        \"y\": 2,\n      },\n    }\n  `)\n\n  // with custom serializer\n  expect.addSnapshotSerializer({\n    serialize(val, config, indentation, depth, refs, printer) {\n      return `Pretty foo: ${printer(\n        val.foo,\n        config,\n        indentation,\n        depth,\n        refs,\n      )}`\n    },\n    test(val) {\n      return val && Object.prototype.hasOwnProperty.call(val, 'foo')\n    },\n  })\n\n  expect(bar).toMatchInlineSnapshot(`\n    Pretty foo: {\n      \"x\": 1,\n      \"y\": 2,\n    }\n  `)\n})\n\ntest('throwing snapshot', () => {\n  // example from https://github.com/vitest-dev/vitest/issues/3655\n\n  class ErrorWithDetails extends Error {\n    readonly details: unknown\n\n    constructor(message: string, options: ErrorOptions & { details: unknown }) {\n      super(message, options)\n      this.details = options.details\n    }\n  }\n\n  // without custom serializer\n  const error = new ErrorWithDetails('some-error', {\n    details: 'some-detail',\n  })\n  expect(error).toMatchInlineSnapshot(`[Error: some-error]`)\n  expect(() => {\n    throw error\n  }).toThrowErrorMatchingInlineSnapshot(`[Error: some-error]`)\n\n  // with custom serializer\n  expect.addSnapshotSerializer({\n    serialize(val, config, indentation, depth, refs, printer) {\n      const error = val as ErrorWithDetails\n      return `Pretty ${error.message}: ${printer(\n        error.details,\n        config,\n        indentation,\n        depth,\n        refs,\n      )}`\n    },\n    test(val) {\n      return val && val instanceof ErrorWithDetails\n    },\n  })\n  expect(error).toMatchInlineSnapshot(`Pretty some-error: \"some-detail\"`)\n  expect(() => {\n    throw error\n  }).toThrowErrorMatchingInlineSnapshot(`Pretty some-error: \"some-detail\"`)\n})\n"
  },
  {
    "path": "test/core/test/snapshot-file.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\nfunction objectToCSS(selector: string, obj: Record<string, string>) {\n  const body = Object.entries(obj)\n    .map(([key, value]) => `  ${key}: ${value};`)\n    .join('\\n')\n  return `${selector} {\\n${body}\\n}`\n}\n\ndescribe('snapshots', () => {\n  const files = import.meta.glob('./fixtures/snapshots/**/input.json', {\n    query: '?raw',\n    import: 'default',\n  })\n\n  for (const [path, file] of Object.entries(files)) {\n    test(path, async () => {\n      const entries = JSON.parse(await file() as string) as any[]\n      await expect(entries.map(i => objectToCSS(i[0], i[1])).join('\\n'))\n        .toMatchFileSnapshot(path.replace('input.json', 'output.css'))\n    })\n  }\n})\n\ntest('handle empty file', async () => {\n  await expect('').toMatchFileSnapshot('./fixtures/snapshot-empty.txt')\n})\n"
  },
  {
    "path": "test/core/test/snapshot-inline-(parentheses).test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('object', () => {\n  expect({\n    foo: {\n      type: 'object',\n      map: new Map(),\n    },\n  })\n    .toMatchInlineSnapshot(`\n        {\n          \"foo\": {\n            \"map\": Map {},\n            \"type\": \"object\",\n          },\n        }\n      `)\n})\n"
  },
  {
    "path": "test/core/test/snapshot-inline.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('object', () => {\n  expect({\n    foo: {\n      type: 'object',\n      map: new Map(),\n    },\n  })\n    .toMatchInlineSnapshot(`\n      {\n        \"foo\": {\n          \"map\": Map {},\n          \"type\": \"object\",\n        },\n      }\n    `)\n})\n\ntest('single line', () => {\n  expect('inline string').toMatchInlineSnapshot('\"inline string\"')\n  expect('inline $ string').toMatchInlineSnapshot('\"inline $ string\"')\n  expect('inline multiline\\n $string').toMatchInlineSnapshot(`\n    \"inline multiline\n     $string\"\n  `)\n  // eslint-disable-next-line no-template-curly-in-string\n  expect('inline multiline\\n ${string}').toMatchInlineSnapshot(`\n    \"inline multiline\n     \\${string}\"\n  `)\n})\n\ntest('multiline', () => {\n  const indent = `\n()=>\n  array\n    .map(fn)\n    .filter(fn)\n`\n  expect(indent).toMatchInlineSnapshot(`\n    \"\n    ()=>\n      array\n        .map(fn)\n        .filter(fn)\n    \"\n  `)\n})\n\ntest('template literal', () => {\n  const literal = `\n  Hello \\${world}\n`\n  expect(literal).toMatchInlineSnapshot(`\n    \"\n      Hello \\${world}\n    \"\n  `)\n})\n\ntest('throwing inline snapshots', async () => {\n  expect(() => {\n    throw new Error('omega')\n  }).toThrowErrorMatchingInlineSnapshot(`[Error: omega]`)\n\n  expect(() => {\n    // eslint-disable-next-line no-throw-literal\n    throw 'omega'\n  }).toThrowErrorMatchingInlineSnapshot('\"omega\"')\n\n  expect(() => {\n    // eslint-disable-next-line no-throw-literal\n    throw { error: 'omega' }\n  }).toThrowErrorMatchingInlineSnapshot(`\n    {\n      \"error\": \"omega\",\n    }\n  `)\n\n  expect(() => {\n    // eslint-disable-next-line no-throw-literal\n    throw { some: { nested: { error: 'object' } } }\n  }).toThrowErrorMatchingInlineSnapshot(`\n    {\n      \"some\": {\n        \"nested\": {\n          \"error\": \"object\",\n        },\n      },\n    }\n  `)\n\n  expect(() => {\n    throw ['Inline', 'snapshot', 'with', 'newlines'].join('\\n')\n  }).toThrowErrorMatchingInlineSnapshot(`\n    \"Inline\n    snapshot\n    with\n    newlines\"\n  `)\n\n  expect(() => {\n    throw new Error(['Inline', 'snapshot', 'with', 'newlines'].join('\\n'))\n  }).toThrowErrorMatchingInlineSnapshot(`\n    [Error: Inline\n    snapshot\n    with\n    newlines]\n  `)\n\n  expect(new Error(['Inline', 'snapshot', 'with', 'newlines'].join('\\n'))).toMatchInlineSnapshot(`\n    [Error: Inline\n    snapshot\n    with\n    newlines]\n  `)\n\n  await expect(async () => {\n    throw new Error('omega')\n  }).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: omega]`)\n})\n\ntest('throwing expect should be a function', async () => {\n  expect(() => {\n    expect(new Error('omega')).toThrowErrorMatchingInlineSnapshot()\n  }).toThrow(/expected must be a function/)\n})\n\ntest('properties inline snapshot', () => {\n  const user = {\n    createdAt: new Date(),\n    id: Math.floor(Math.random() * 20),\n    name: 'LeBron James',\n  }\n\n  expect(user).toMatchInlineSnapshot({\n    createdAt: expect.any(Date),\n    id: expect.any(Number),\n  }, `\n    {\n      \"createdAt\": Any<Date>,\n      \"id\": Any<Number>,\n      \"name\": \"LeBron James\",\n    }\n  `)\n})\n\ntest('literal tag', () => {\n  const html = String.raw\n  const text = `\n<body>\n  <h1>My First Heading.</h1>\n  <p>My first paragraph.</p>\n</body>\n`\n\n  expect(text).toMatchInlineSnapshot(html`\n    \"\n    <body>\n      <h1>My First Heading.</h1>\n      <p>My first paragraph.</p>\n    </body>\n    \"\n  `)\n})\n\ntest('resolves', async () => {\n  const getText = async () => 'text'\n  await expect(getText()).resolves.toMatchInlineSnapshot('\"text\"')\n})\n\ntest('rejects', async () => {\n  const getText = async () => {\n    throw new Error('error')\n  }\n  await expect(getText()).rejects.toMatchInlineSnapshot('[Error: error]')\n})\n"
  },
  {
    "path": "test/core/test/snapshot-react-18.test.jsx",
    "content": "// @jsxRuntime automatic\n// @jsxImportSource react-18\n\nimport { expect, test } from 'vitest'\n\ntest('react 18', () => {\n  expect(<div>hello</div>).toMatchInlineSnapshot(`\n    <div>\n      hello\n    </div>\n  `)\n})\n"
  },
  {
    "path": "test/core/test/snapshot-react.test.jsx",
    "content": "// @jsxRuntime automatic\n// @jsxImportSource react\n\nimport { expect, test } from 'vitest'\n\ntest('react 19', () => {\n  expect(<div>hello</div>).toMatchInlineSnapshot(`\n    <div>\n      hello\n    </div>\n  `)\n})\n"
  },
  {
    "path": "test/core/test/snapshot.test.ts",
    "content": "/* eslint-disable style/quotes */\n\nimport { expect, test, vi } from 'vitest'\nimport { testOutsideInlineSnapshot } from './snapshots-outside'\n\ntest('object', () => {\n  expect({\n    this: { is: new Set(['of', 'snapshot']) },\n  }).toMatchSnapshot()\n})\n\ntest('single line inline', () => {\n  expect('some string').toMatchInlineSnapshot(`\"some string\"`)\n  expect('some \"string\"').toMatchInlineSnapshot(`\"some \"string\"\"`)\n  expect('some \"string').toMatchInlineSnapshot(`\"some \"string\"`)\n  expect('som`e` string').toMatchInlineSnapshot(`\"som\\`e\\` string\"`)\n  expect('some string`').toMatchInlineSnapshot(`\"some string\\`\"`)\n  expect(\"some string'\").toMatchInlineSnapshot(`\"some string'\"`)\n  expect(\"some 'string'\").toMatchInlineSnapshot(`\"some 'string'\"`)\n})\n\ntest('single line snapshot', () => {\n  expect('some string').toMatchSnapshot()\n  expect('some \"string\"').toMatchSnapshot()\n  expect('some \"string').toMatchSnapshot()\n  expect('som`e` string').toMatchSnapshot()\n  expect('some string`').toMatchSnapshot()\n  expect(\"some string'\").toMatchSnapshot()\n  expect(\"some 'string'\").toMatchSnapshot()\n})\n\ntest('multiline', () => {\n  expect(`\n  Hello\n    World\n`).toMatchSnapshot()\n})\n\ntest('from outside', () => {\n  testOutsideInlineSnapshot()\n})\n\ntest('with big array', () => {\n  expect({\n    this: { is: new Set(['one', Array.from({ length: 30 }).fill({})]) },\n  }).toMatchSnapshot()\n})\n\ntest('with big string', () => {\n  expect({\n    this: { is: new Set(['one', Array.from({ length: 30 }).fill('zoo').join()]) },\n  }).toMatchSnapshot()\n})\n\ntest('throwing', async () => {\n  expect(() => {\n    throw new Error('omega')\n  }).toThrowErrorMatchingSnapshot()\n\n  expect(() => {\n    // eslint-disable-next-line no-throw-literal\n    throw 'omega'\n  }).toThrowErrorMatchingSnapshot()\n\n  expect(() => {\n    // eslint-disable-next-line no-throw-literal\n    throw { error: 'omega' }\n  }).toThrowErrorMatchingSnapshot()\n\n  await expect(async () => {\n    throw new Error('omega')\n  }).rejects.toThrowErrorMatchingSnapshot()\n})\n\ntest('throwing expect should be a function', async () => {\n  expect(() => {\n    expect(new Error('omega')).toThrowErrorMatchingSnapshot()\n  }).toThrow(/expected must be a function/)\n})\n\ntest('properties snapshot', () => {\n  const user = {\n    createdAt: new Date(),\n    id: Math.floor(Math.random() * 20),\n    name: 'LeBron James',\n  }\n\n  expect(user).toMatchSnapshot({\n    createdAt: expect.any(Date),\n    id: expect.any(Number),\n    name: expect.stringContaining('LeBron'),\n  })\n})\n\ntest.fails('properties snapshot fails', () => {\n  const user = {\n    createdAt: new Date(),\n    id: Math.floor(Math.random() * 20),\n    name: 'LeBron James',\n  }\n\n  expect(user).toMatchSnapshot({\n    createdAt: expect.any(Date),\n    id: expect.any(String),\n  })\n})\n\ntest('renders mock snapshot', () => {\n  const fn = vi.fn()\n  expect(fn).toMatchSnapshot()\n  fn('hello', 'world', 2)\n  expect(fn).toMatchSnapshot()\n})\n\ntest('renders inline mock snapshot', () => {\n  const fn = vi.fn()\n  expect(fn).toMatchInlineSnapshot('[MockFunction]')\n  fn('hello', 'world', 2)\n  expect(fn).toMatchInlineSnapshot(`\n    [MockFunction] {\n      \"calls\": [\n        [\n          \"hello\",\n          \"world\",\n          2,\n        ],\n      ],\n      \"results\": [\n        {\n          \"type\": \"return\",\n          \"value\": undefined,\n        },\n      ],\n    }\n  `)\n})\n\nfunction println() {\n  const message = `\nexport default function () {\n  function Foo() {\n  }\n\n  return Foo;\n}\n`\n  return message\n}\n\ntest('multiline strings ', () => {\n  expect(println()).toMatchSnapshot()\n})\n\ntest('updateInlineSnapshot should not remove end whitespace', () => {\n  // issue #922\n  expect(`\nmy string\n`).toMatchInlineSnapshot(`\n  \"\n  my string\n  \"\n`)\n})\n"
  },
  {
    "path": "test/core/test/snapshots-outside.ts",
    "content": "import { expect } from 'vitest'\n\nexport function testOutsideInlineSnapshot() {\n  return (() => {\n    expect({ foo: 'bar' }).toMatchInlineSnapshot(`\n    {\n      \"foo\": \"bar\",\n    }\n    `)\n  })()\n}\n"
  },
  {
    "path": "test/core/test/sourcemap.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('should have sourcemaps', () => {\n  expect('\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9').toBeTruthy()\n  // eslint-disable-next-line style/quotes\n  expect(\"\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9\").toBeTruthy()\n  expect(`\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9`).toBeTruthy()\n})\n"
  },
  {
    "path": "test/core/test/spy.test.ts",
    "content": "import { describe, expect, test, vi } from 'vitest'\nimport * as mock from './fixtures/hello-mock'\n\n/**\n * @vitest-environment happy-dom\n */\n\ndescribe('spyOn', () => {\n  const hw = new mock.HelloWorld()\n\n  test('correctly infers method types', async () => {\n    vi.spyOn(localStorage, 'getItem').mockReturnValue('world')\n    expect(window.localStorage.getItem('hello')).toEqual('world')\n  })\n\n  test('infers a class correctly', () => {\n    // eslint-disable-next-line prefer-arrow-callback\n    vi.spyOn(mock, 'HelloWorld').mockImplementationOnce(function () {\n      const Mock = vi.fn()\n      Mock.prototype.hello = vi.fn(() => 'hello world')\n      return new Mock()\n    })\n\n    const mockedHelloWorld = new mock.HelloWorld()\n    expect(mockedHelloWorld.hello()).toEqual('hello world')\n  })\n\n  test('infers a method correctly', () => {\n    vi.spyOn(hw, 'hello').mockImplementationOnce(() => 'hello world')\n\n    expect(hw.hello()).toEqual('hello world')\n  })\n})\n"
  },
  {
    "path": "test/core/test/strict.test.js",
    "content": "import { describe, expect, test } from 'vitest'\n\ndescribe('vitest runs code in strict mode', () => {\n  test('throws as defined in spec', () => {\n    const o = { id: 1 }\n    Object.defineProperty(o, 'id', { writable: false, configurable: false })\n\n    expect(() => o.id = 42).toThrow(TypeError)\n  })\n\n  test('cannot defined non existing variable', () => {\n    expect(() => {\n      someGlobalVariableICameUpWith = 22\n    }).toThrow()\n  })\n\n  test('cannot redefine getter', () => {\n    const obj2 = {\n      get x() {\n        return 17\n      },\n    }\n    expect(() => {\n      obj2.x = 5\n    }).toThrow(TypeError)\n  })\n\n  test('cannot declare properties on primitives', () => {\n    expect(() => false.true = '').toThrow(TypeError)\n    expect(() => (14).sailing = 'home').toThrow(TypeError)\n    expect(() => 'with'.you = 'far away').toThrow(TypeError)\n  })\n})\n"
  },
  {
    "path": "test/core/test/stubbed-process.test.ts",
    "content": "import { expect, it, vi } from 'vitest'\n\nvi.stubGlobal('process', { badMock: true })\n\nit('should not hang', () => {\n  expect(1).toBe(1)\n})\n\nit('should not crash (#9173)', async () => {\n  await import('./fixtures/increment')\n})\n"
  },
  {
    "path": "test/core/test/stubs.test.ts",
    "content": "/* eslint-disable vars-on-top */\n\nimport { beforeEach, describe, expect, it, vi } from 'vitest'\n\ndeclare global {\n\n  var __defined__: unknown\n\n  var __setter__: unknown\n}\n\ndescribe('stubbing globals', () => {\n  beforeEach(() => {\n    delete globalThis.__defined__\n    if (globalThis.__setter__) {\n      delete globalThis.__setter__\n    }\n    vi.unstubAllGlobals()\n  })\n\n  it('overwrites setter', () => {\n    const descriptor = {\n      get: () => 'getter',\n      set: () => {},\n      configurable: true,\n    }\n    Object.defineProperty(globalThis, '__setter__', descriptor)\n    expect(__setter__).toBe('getter')\n    vi.stubGlobal('__setter__', 'stubbed')\n    expect(__setter__).toBe('stubbed')\n    expect(globalThis.__setter__).toBe('stubbed')\n    expect(Object.getOwnPropertyDescriptor(globalThis, '__setter__')).not.toBe(descriptor)\n    vi.unstubAllGlobals()\n    expect(__setter__).toBe('getter')\n  })\n\n  it('stubs and restores already defined value', () => {\n    globalThis.__defined__ = 'true'\n    vi.stubGlobal('__defined__', 'false')\n    expect(__defined__).toBe('false')\n    expect(globalThis.__defined__).toBe('false')\n    vi.unstubAllGlobals()\n    expect(__defined__).toBe('true')\n    expect(globalThis.__defined__).toBe('true')\n  })\n\n  it('stubs and removes undefined value', () => {\n    vi.stubGlobal('__defined__', 'false')\n    expect(__defined__).toBe('false')\n    expect(globalThis.__defined__).toBe('false')\n    vi.unstubAllGlobals()\n    expect('__defined__' in globalThis).toBe(false)\n    expect(() => __defined__).toThrow(ReferenceError)\n    expect(globalThis.__defined__).toBeUndefined()\n  })\n\n  it('restores the first available value', () => {\n    globalThis.__defined__ = 'true'\n    vi.stubGlobal('__defined__', 'false')\n    vi.stubGlobal('__defined__', false)\n    vi.stubGlobal('__defined__', null)\n    expect(__defined__).toBe(null)\n    expect(globalThis.__defined__).toBe(null)\n    vi.unstubAllGlobals()\n    expect(__defined__).toBe('true')\n    expect(globalThis.__defined__).toBe('true')\n  })\n})\n\ndescribe('stubbing envs', () => {\n  beforeEach(() => {\n    process.env.VITE_TEST_UPDATE_ENV = 'development'\n    vi.unstubAllEnvs()\n  })\n\n  it('stubs and restores env', () => {\n    vi.stubEnv('VITE_TEST_UPDATE_ENV', 'production')\n    expect(import.meta.env.VITE_TEST_UPDATE_ENV).toBe('production')\n    expect(process.env.VITE_TEST_UPDATE_ENV).toBe('production')\n    vi.unstubAllEnvs()\n    expect(import.meta.env.VITE_TEST_UPDATE_ENV).toBe('development')\n    expect(process.env.VITE_TEST_UPDATE_ENV).toBe('development')\n  })\n\n  it('stubs and restores previously not defined env', () => {\n    delete process.env.VITE_TEST_UPDATE_ENV\n    vi.stubEnv('VITE_TEST_UPDATE_ENV', 'production')\n    expect(import.meta.env.VITE_TEST_UPDATE_ENV).toBe('production')\n    expect(process.env.VITE_TEST_UPDATE_ENV).toBe('production')\n    vi.unstubAllEnvs()\n    expect('VITE_TEST_UPDATE_ENV' in process.env).toBe(false)\n    expect('VITE_TEST_UPDATE_ENV' in import.meta.env).toBe(false)\n    expect(import.meta.env.VITE_TEST_UPDATE_ENV).toBeUndefined()\n    expect(process.env.VITE_TEST_UPDATE_ENV).toBeUndefined()\n  })\n\n  it('restores the first available value', () => {\n    globalThis.__defined__ = 'true'\n    vi.stubEnv('VITE_TEST_UPDATE_ENV', 'production')\n    vi.stubEnv('VITE_TEST_UPDATE_ENV', 'staging')\n    vi.stubEnv('VITE_TEST_UPDATE_ENV', 'test')\n    expect(import.meta.env.VITE_TEST_UPDATE_ENV).toBe('test')\n    expect(process.env.VITE_TEST_UPDATE_ENV).toBe('test')\n    vi.unstubAllEnvs()\n    expect(import.meta.env.VITE_TEST_UPDATE_ENV).toBe('development')\n    expect(process.env.VITE_TEST_UPDATE_ENV).toBe('development')\n  })\n\n  it.each(['PROD', 'DEV', 'SSR'] as const)('requires boolean for env.%s', (name) => {\n    vi.stubEnv(name as 'PROD', false)\n    expect(import.meta.env[name]).toBe(false)\n    expect(process.env[name]).toBe('')\n\n    vi.stubEnv(name as 'PROD', true)\n    expect(import.meta.env[name]).toBe(true)\n    expect(process.env[name]).toBe('1')\n\n    // @ts-expect-error PROD, DEV, SSR expect a boolean\n    vi.stubEnv(name as 'PROD', 'string')\n    // @ts-expect-error PROD, DEV, SSR expect a boolean\n    vi.stubEnv(name, 'string')\n  })\n\n  it('setting boolean casts the value to string', () => {\n    // @ts-expect-error value should be a string\n    vi.stubEnv('MY_TEST_ENV', true)\n    expect(import.meta.env.MY_TEST_ENV).toBe('true')\n  })\n\n  it('stubs to undefined and restores env', () => {\n    vi.stubEnv('VITE_TEST_UPDATE_ENV', undefined)\n    expect(import.meta.env.VITE_TEST_UPDATE_ENV).toBeUndefined()\n    expect(process.env.VITE_TEST_UPDATE_ENV).toBeUndefined()\n    vi.unstubAllEnvs()\n    expect(import.meta.env.VITE_TEST_UPDATE_ENV).toBe('development')\n    expect(process.env.VITE_TEST_UPDATE_ENV).toBe('development')\n  })\n})\n"
  },
  {
    "path": "test/core/test/suite.test.tsx",
    "content": "import { assert, describe, expect, it } from 'vitest'\n\ndescribe('suite name', () => {\n  it('foo', () => {\n    assert.equal(Math.sqrt(4), 2)\n  })\n\n  it('bar', () => {\n    expect(1 + 1).eq(2)\n  })\n\n  it('snapshot', () => {\n    expect({ foo: 'bar' }).toMatchSnapshot()\n  })\n})\n\nit('timeout', () => new Promise(resolve => setTimeout(resolve, 500)))\n"
  },
  {
    "path": "test/core/test/tab-effect.spec.mjs",
    "content": "/* eslint-disable */\nimport { expect, test, vi } from 'vitest'\nimport { join as joinPath } from 'node:path'\n\nconst helloWorld = () => {\nreturn joinPath('hello', 'world')\n}\n\n// note there are NO indents in this file\n// except the next line\n// test pass with spaces, test fails with tab\n\tvi.mock ('node:path', () => {\nreturn {\njoin: vi.fn().mockReturnValue('goodbye world')\n}\n})\n\ntest('Are you mocking me?', () => {\nexpect(helloWorld()).toBe('goodbye world')\n})\n"
  },
  {
    "path": "test/core/test/task-collector.test.ts",
    "content": "import type { RunnerTestCase, RunnerTestSuite } from 'vitest'\nimport { assert, describe, expect, test, TestRunner, vi } from 'vitest'\n\ntest('collector keeps the order of arguments', () => {\n  const fn = vi.fn()\n  const collector = TestRunner.createTaskCollector(fn)\n  const cb = vi.fn()\n  const options = { timeout: 100 }\n\n  collector('a', cb, options.timeout)\n\n  expect(fn).toHaveBeenNthCalledWith(1, 'a', cb, options.timeout)\n\n  collector('a', options, cb)\n\n  expect(fn).toHaveBeenNthCalledWith(2, 'a', options, cb)\n\n  collector.each([1])('a', cb, options.timeout)\n\n  expect(fn).toHaveBeenNthCalledWith(3, 'a', expect.any(Function), options.timeout)\n\n  collector.each([1])('a', options, cb)\n\n  expect(fn).toHaveBeenNthCalledWith(4, 'a', options, expect.any(Function))\n})\n\ndescribe('collector.extend should preserve handler wrapping', () => {\n  let flag = false\n\n  const flagTest = TestRunner.createTaskCollector(function (\n    this: object,\n    name: string,\n    fn: () => void,\n  ) {\n    const handler = async () => {\n      flag = false\n      await fn()\n      assert(flag)\n    }\n    TestRunner.getCurrentSuite().task(name, { ...this, handler })\n  })\n\n  const extendedTest = flagTest.extend({})\n\n  extendedTest.fails('should fail when flag is never set', {}, () => {})\n\n  flagTest('should pass when flag is set', () => {\n    flag = true\n    expect(flag).toBe(true)\n  })\n})\n\ndescribe('empty tests and suites are todos', () => {\n  describe('suite should be todo')\n  test('test should be todo')\n\n  test('this suite has correct modes', ({ task }) => {\n    const todoSuite = task.suite!.tasks[0] as RunnerTestSuite\n    const todoTest = task.suite!.tasks[0] as RunnerTestCase\n\n    expect(todoSuite.name).toBe('suite should be todo')\n    expect(todoSuite.mode).toBe('todo')\n\n    expect(todoTest.name).toBe('suite should be todo')\n    expect(todoTest.mode).toBe('todo')\n  })\n})\n"
  },
  {
    "path": "test/core/test/task-names.test.ts",
    "content": "/**\n * This test is self-referential - it validates its own structure and the structure of the tests defined below.\n *\n * The order and nesting of these test definitions MUST match the assertions, or the test will fail. The assertions use array indices (e.g., `task.file.tasks[0]`) to access specific tests, so reordering will break the test.\n *\n * If you need to modify this structure, update both the setup below AND the corresponding assertions above to maintain consistency.\n */\nimport type { RunnerTestSuite } from 'vitest'\nimport { describe, test } from 'vitest'\n\ntest('tasks have correct `fullName` and `fullTestName` properties', ({ expect, task }) => {\n  // this test validates the structure defined at the bottom of this file.\n  //\n  // structure (must match setup at bottom):\n  //\n  // task-names.test.ts\n  // ├─ [0] tasks have correct `fullName` and `fullTestName` properties (this test)\n  // ├─ [1] creates new recipe\n  // ├─ [2] searches by ingredient\n  // ├─ [3] recipe management/\n  // │  ├─ [0] saves recipe\n  // │  └─ [1] deletes recipe\n  // └─ [4] meal planning/\n  //    ├─ [0] generates weekly plan\n  //    ├─ [1] grocery lists/\n  //    │  ├─ [0] calculates ingredients\n  //    │  ├─ [1] combines duplicate items\n  //    │  └─ [2] shopping/\n  //    │     ├─ [0] marks items as purchased\n  //    │     └─ [1] estimates total cost\n  //    ├─ [2] exports calendar\n  //    └─ [3] nutrition tracking/\n  //       ├─ [0] calculates daily calories\n  //       └─ [1] tracks macros\n\n  // validate this test itself (task.file.tasks[0])\n  expect(task.suite).toBe(undefined)\n  expect(\n    task.fullName,\n  ).toBe('test/task-names.test.ts > tasks have correct `fullName` and `fullTestName` properties')\n  expect(\n    task.fullTestName,\n  ).toBe('tasks have correct `fullName` and `fullTestName` properties')\n\n  expect(task.file.fullName).toBe('test/task-names.test.ts')\n  expect(task.file.fullTestName).toBe(undefined)\n\n  const thisTest = task.file.tasks[0]\n  expect(thisTest.suite).toBe(undefined)\n  expect(thisTest.fullName).toBe(\n    'test/task-names.test.ts > tasks have correct `fullName` and `fullTestName` properties',\n  )\n  expect(thisTest.fullTestName).toBe(\n    'tasks have correct `fullName` and `fullTestName` properties',\n  )\n\n  expect(\n    task.file.tasks,\n  ).toHaveLength(5)\n\n  // top-level tests\n  const createsRecipe = task.file.tasks[1]\n  expect(createsRecipe.suite).toBe(undefined)\n  expect(createsRecipe.fullName).toBe(\n    'test/task-names.test.ts > creates new recipe',\n  )\n  expect(createsRecipe.fullTestName).toBe(\n    'creates new recipe',\n  )\n\n  const searchIngredient = task.file.tasks[2]\n  expect(searchIngredient.suite).toBe(undefined)\n  expect(searchIngredient.fullName).toBe(\n    'test/task-names.test.ts > searches by ingredient',\n  )\n  expect(searchIngredient.fullTestName).toBe(\n    'searches by ingredient',\n  )\n\n  // single-level suite\n  const recipeManagement = task.file.tasks[3] as RunnerTestSuite\n  expect(recipeManagement.suite).toBe(undefined)\n  expect(recipeManagement.fullName).toBe(\n    'test/task-names.test.ts > recipe management',\n  )\n  expect(recipeManagement.fullTestName).toBe(\n    'recipe management',\n  )\n\n  expect(recipeManagement.tasks).toHaveLength(2)\n\n  const savesRecipe = recipeManagement.tasks[0]\n  expect(savesRecipe.suite?.fullName).toBe(\n    'test/task-names.test.ts > recipe management',\n  )\n  expect(savesRecipe.suite?.fullTestName).toBe(\n    'recipe management',\n  )\n  expect(savesRecipe.fullName).toBe(\n    'test/task-names.test.ts > recipe management > saves recipe',\n  )\n  expect(savesRecipe.fullTestName).toBe(\n    'recipe management > saves recipe',\n  )\n\n  const deletesRecipe = recipeManagement.tasks[1]\n  expect(deletesRecipe.suite?.fullName).toBe(\n    'test/task-names.test.ts > recipe management',\n  )\n  expect(deletesRecipe.suite?.fullTestName).toBe(\n    'recipe management',\n  )\n  expect(deletesRecipe.fullName).toBe(\n    'test/task-names.test.ts > recipe management > deletes recipe',\n  )\n  expect(deletesRecipe.fullTestName).toBe(\n    'recipe management > deletes recipe',\n  )\n\n  // nested suites with mixed patterns\n  const mealPlanning = task.file.tasks[4] as RunnerTestSuite\n  expect(mealPlanning.suite).toBe(undefined)\n  expect(mealPlanning.fullName).toBe(\n    'test/task-names.test.ts > meal planning',\n  )\n  expect(mealPlanning.fullTestName).toBe(\n    'meal planning',\n  )\n\n  expect(mealPlanning.tasks).toHaveLength(4)\n\n  const generatesPlan = mealPlanning.tasks[0]\n  expect(generatesPlan.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning',\n  )\n  expect(generatesPlan.suite?.fullTestName).toBe(\n    'meal planning',\n  )\n  expect(generatesPlan.fullName).toBe(\n    'test/task-names.test.ts > meal planning > generates weekly plan',\n  )\n  expect(generatesPlan.fullTestName).toBe(\n    'meal planning > generates weekly plan',\n  )\n\n  const groceryList = mealPlanning.tasks[1] as RunnerTestSuite\n  expect(groceryList.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning',\n  )\n  expect(groceryList.suite?.fullTestName).toBe(\n    'meal planning',\n  )\n  expect(groceryList.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists',\n  )\n  expect(groceryList.fullTestName).toBe(\n    'meal planning > grocery lists',\n  )\n\n  expect(groceryList.tasks).toHaveLength(3)\n\n  const calculatesIngredients = groceryList.tasks[0]\n  expect(calculatesIngredients.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists',\n  )\n  expect(calculatesIngredients.suite?.fullTestName).toBe(\n    'meal planning > grocery lists',\n  )\n  expect(calculatesIngredients.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists > calculates ingredients',\n  )\n  expect(calculatesIngredients.fullTestName).toBe(\n    'meal planning > grocery lists > calculates ingredients',\n  )\n\n  const combinesItems = groceryList.tasks[1]\n  expect(combinesItems.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists',\n  )\n  expect(combinesItems.suite?.fullTestName).toBe(\n    'meal planning > grocery lists',\n  )\n  expect(combinesItems.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists > combines duplicate items',\n  )\n  expect(combinesItems.fullTestName).toBe(\n    'meal planning > grocery lists > combines duplicate items',\n  )\n\n  const shopping = groceryList.tasks[2] as RunnerTestSuite\n  expect(shopping.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists',\n  )\n  expect(shopping.suite?.fullTestName).toBe(\n    'meal planning > grocery lists',\n  )\n  expect(shopping.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists > shopping',\n  )\n  expect(shopping.fullTestName).toBe(\n    'meal planning > grocery lists > shopping',\n  )\n\n  expect(shopping.tasks).toHaveLength(2)\n\n  const marksItemsPurchased = shopping.tasks[0]\n  expect(marksItemsPurchased.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists > shopping',\n  )\n  expect(marksItemsPurchased.suite?.fullTestName).toBe(\n    'meal planning > grocery lists > shopping',\n  )\n  expect(marksItemsPurchased.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists > shopping > marks items as purchased',\n  )\n  expect(marksItemsPurchased.fullTestName).toBe(\n    'meal planning > grocery lists > shopping > marks items as purchased',\n  )\n\n  const estimatesTotalCost = shopping.tasks[1]\n  expect(estimatesTotalCost.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists > shopping',\n  )\n  expect(estimatesTotalCost.suite?.fullTestName).toBe(\n    'meal planning > grocery lists > shopping',\n  )\n  expect(estimatesTotalCost.fullName).toBe(\n    'test/task-names.test.ts > meal planning > grocery lists > shopping > estimates total cost',\n  )\n  expect(estimatesTotalCost.fullTestName).toBe(\n    'meal planning > grocery lists > shopping > estimates total cost',\n  )\n\n  const exportsCalendar = mealPlanning.tasks[2]\n  expect(exportsCalendar.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning',\n  )\n  expect(exportsCalendar.suite?.fullTestName).toBe(\n    'meal planning',\n  )\n  expect(exportsCalendar.fullName).toBe(\n    'test/task-names.test.ts > meal planning > exports calendar',\n  )\n  expect(exportsCalendar.fullTestName).toBe(\n    'meal planning > exports calendar',\n  )\n\n  const nutritionTracking = mealPlanning.tasks[3] as RunnerTestSuite\n  expect(nutritionTracking.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning',\n  )\n  expect(nutritionTracking.suite?.fullTestName).toBe(\n    'meal planning',\n  )\n  expect(nutritionTracking.fullName).toBe(\n    'test/task-names.test.ts > meal planning > nutrition tracking',\n  )\n  expect(nutritionTracking.fullTestName).toBe(\n    'meal planning > nutrition tracking',\n  )\n\n  expect(nutritionTracking.tasks).toHaveLength(2)\n\n  const calculatesCalories = nutritionTracking.tasks[0]\n  expect(calculatesCalories.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning > nutrition tracking',\n  )\n  expect(calculatesCalories.suite?.fullTestName).toBe(\n    'meal planning > nutrition tracking',\n  )\n  expect(calculatesCalories.fullName).toBe(\n    'test/task-names.test.ts > meal planning > nutrition tracking > calculates daily calories',\n  )\n  expect(calculatesCalories.fullTestName).toBe(\n    'meal planning > nutrition tracking > calculates daily calories',\n  )\n\n  const tracksMacros = nutritionTracking.tasks[1]\n  expect(tracksMacros.suite?.fullName).toBe(\n    'test/task-names.test.ts > meal planning > nutrition tracking',\n  )\n  expect(tracksMacros.suite?.fullTestName).toBe(\n    'meal planning > nutrition tracking',\n  )\n  expect(tracksMacros.fullName).toBe(\n    'test/task-names.test.ts > meal planning > nutrition tracking > tracks macros',\n  )\n  expect(tracksMacros.fullTestName).toBe(\n    'meal planning > nutrition tracking > tracks macros',\n  )\n})\n\n// setup\n\n// top-level tests\ntest('creates new recipe')\ntest('searches by ingredient')\n\n// single-level suite\ndescribe('recipe management', () => {\n  test('saves recipe')\n  test('deletes recipe')\n})\n\n// nested suites with mixed patterns\ndescribe('meal planning', () => {\n  test('generates weekly plan')\n\n  describe('grocery lists', () => {\n    test('calculates ingredients')\n    test('combines duplicate items')\n\n    describe('shopping', () => {\n      test('marks items as purchased')\n      test('estimates total cost')\n    })\n  })\n\n  test('exports calendar')\n\n  describe('nutrition tracking', () => {\n    test('calculates daily calories')\n    test('tracks macros')\n  })\n})\n"
  },
  {
    "path": "test/core/test/test-extend-with-top-level-hooks.test.ts",
    "content": "import { afterEach, beforeEach, expect, test } from 'vitest'\n\ninterface Fixture { foo: number }\n\nconst test1 = test.extend<Fixture>({\n  foo: 1,\n})\n\nconst test2 = test.extend<Fixture>({\n  foo: 2,\n})\n\ntest1('the foo should be 1', ({ foo }) => {\n  expect(foo).toBe(1)\n})\n\ntest2('the foo should be 2', ({ foo }) => {\n  expect(foo).toBe(2)\n})\n\nlet nextFoo = 1\nbeforeEach<Fixture>(({ foo }) => {\n  expect(foo).toBe(nextFoo)\n})\n\nafterEach<Fixture>(({ foo }) => {\n  expect(foo).toBe(nextFoo)\n  nextFoo++\n})\n"
  },
  {
    "path": "test/core/test/test-extend.test.ts",
    "content": "/* eslint-disable prefer-rest-params */\n\nimport type { InferFixturesTypes } from '@vitest/runner'\nimport type { TestAPI } from 'vitest'\nimport { afterAll, afterEach, beforeEach, describe, expect, expectTypeOf, test, vi } from 'vitest'\n\ninterface Fixtures {\n  todoList: number[]\n  doneList: number[]\n  archiveList: number[]\n}\n\nconst todoList: number[] = [1, 2, 3]\nconst doneList: number[] = []\nconst archiveList: number[] = []\n\nconst todoFn = vi.fn()\nconst doneFn = vi.fn()\n\nconst myTest = test\n  .extend<Pick<Fixtures, 'todoList'>>({\n    todoList: async ({}, use) => {\n      todoFn()\n      await use(todoList)\n      // cleanup\n      todoFn.mockClear()\n      todoList.length = 0\n      todoList.push(1, 2, 3)\n    },\n  })\n  .extend<Pick<Fixtures, 'doneList' | 'archiveList'>>({\n    doneList: async ({}, use) => {\n      doneFn()\n      await use(doneList)\n      // cleanup\n      doneFn.mockClear()\n      doneList.length = 0\n    },\n    archiveList,\n  })\n\ndescribe('test.extend()', () => {\n  test('types', () => {\n    interface TypesContext {\n      number: number\n      array: number[]\n      string: string\n      any: any\n      boolean: boolean\n      func: (a: number, b: string) => void\n    }\n\n    const typesTest = test.extend<TypesContext>({\n      number: 1,\n      array: [1, 2, 3],\n      async string({ }, use) {\n        await use('string')\n      },\n      async any({}, use) {\n        await use({})\n      },\n      boolean: true,\n      func: async ({}, use): Promise<void> => {\n        await use(() => undefined)\n      },\n    })\n\n    expectTypeOf(typesTest).toEqualTypeOf<TestAPI<InferFixturesTypes<typeof typesTest>>>()\n  })\n\n  describe('basic', () => {\n    myTest('todoList and doneList', ({ todoList, doneList, archiveList }) => {\n      expect(todoFn).toBeCalledTimes(1)\n      expect(doneFn).toBeCalledTimes(1)\n\n      expectTypeOf(todoList).toEqualTypeOf<number[]>()\n      expectTypeOf(doneList).toEqualTypeOf<number[]>()\n      expectTypeOf(doneList).toEqualTypeOf<number[]>()\n\n      expect(todoList).toEqual([1, 2, 3])\n      expect(doneList).toEqual([])\n      expect(archiveList).toEqual([])\n\n      doneList.push(todoList.shift()!)\n      expect(todoList).toEqual([2, 3])\n      expect(doneList).toEqual([1])\n\n      doneList.push(todoList.shift()!)\n      expect(todoList).toEqual([3])\n      expect(doneList).toEqual([1, 2])\n\n      archiveList.push(todoList.shift()!)\n      expect(todoList).toEqual([])\n      expect(archiveList).toEqual([3])\n\n      archiveList.pop()\n    })\n  })\n\n  describe('smartly init fixtures', () => {\n    myTest('should not init any fixtures', function () {\n      expect(todoFn).not.toBeCalled()\n      expect(doneFn).not.toBeCalled()\n\n      expectTypeOf(arguments[0].todoList).not.toEqualTypeOf<number[]>()\n      expectTypeOf(arguments[0].doneList).not.toEqualTypeOf<number[]>()\n      expectTypeOf(arguments[0].archiveList).not.toEqualTypeOf<number[]>()\n\n      expect(arguments[0].todoList).toBeUndefined()\n      expect(arguments[0].doneList).toBeUndefined()\n      expect(arguments[0].archiveList).toBeUndefined()\n    })\n\n    myTest('should not init any fixtures', function ({}) {\n      expect(todoFn).not.toBeCalled()\n      expect(doneFn).not.toBeCalled()\n\n      expectTypeOf(arguments[0].todoList).not.toEqualTypeOf<number[]>()\n      expectTypeOf(arguments[0].doneList).not.toEqualTypeOf<number[]>()\n      expectTypeOf(arguments[0].archiveList).not.toEqualTypeOf<number[]>()\n\n      expect(arguments[0].todoList).toBeUndefined()\n      expect(arguments[0].doneList).toBeUndefined()\n      expect(arguments[0].archiveList).toBeUndefined()\n    })\n\n    myTest('should only init todoList', function ({ todoList }) {\n      expect(todoFn).toBeCalledTimes(1)\n      expect(doneFn).not.toBeCalled()\n\n      expectTypeOf(todoList).toEqualTypeOf<number[]>()\n      expectTypeOf(arguments[0].doneList).not.toEqualTypeOf<number[]>()\n      expectTypeOf(arguments[0].archiveList).not.toEqualTypeOf<number[]>()\n\n      expect(arguments[0].doneList).toBeUndefined()\n      expect(arguments[0].archiveList).toBeUndefined()\n    })\n\n    myTest('should only init todoList and doneList', function ({ todoList, doneList }) {\n      expect(todoFn).toBeCalledTimes(1)\n      expect(doneFn).toBeCalledTimes(1)\n\n      expectTypeOf(todoList).toEqualTypeOf<number[]>()\n      expectTypeOf(doneList).toEqualTypeOf<number[]>()\n      expectTypeOf(arguments[0].archiveList).not.toEqualTypeOf<number[]>()\n\n      expect(todoList).toEqual([1, 2, 3])\n      expect(doneList).toEqual([])\n      expect(arguments[0].archiveList).toBeUndefined()\n    })\n\n    myTest('should only init doneList and archiveList', function ({ doneList, archiveList }) {\n      expect(doneFn).toBeCalledTimes(1)\n\n      expectTypeOf(doneList).toEqualTypeOf<number[]>()\n      expectTypeOf(archiveList).toEqualTypeOf<number[]>()\n      expectTypeOf(arguments[0].todoList).not.toEqualTypeOf<number[]>()\n\n      expect(doneList).toEqual([])\n      expect(archiveList).toEqual([])\n      expect(arguments[0].todoList).toBeUndefined()\n    })\n  })\n\n  describe('test function', () => {\n    myTest('prop alias', ({ todoList: todos, doneList: done, archiveList: archive }) => {\n      expect(todoFn).toBeCalledTimes(1)\n      expect(doneFn).toBeCalledTimes(1)\n\n      expectTypeOf(todos).toEqualTypeOf<number[]>()\n      expectTypeOf(done).toEqualTypeOf<number[]>()\n      expectTypeOf(archive).toEqualTypeOf<number[]>()\n\n      expect(todos).toEqual([1, 2, 3])\n      expect(done).toEqual([])\n      expect(archive).toEqual([])\n    })\n  })\n\n  describe('fixture only in beforeEach', () => {\n    beforeEach<Fixtures>(({ todoList }) => {\n      expect(todoList).toEqual([1, 2, 3])\n      expect(todoFn).toBeCalledTimes(1)\n    })\n\n    myTest('no fixture in test', () => {\n      expect(todoFn).toBeCalledTimes(1)\n    })\n  })\n\n  describe('fixture only in afterEach', () => {\n    afterEach<Fixtures>(({ todoList }) => {\n      expect(todoList).toEqual([1, 2, 3])\n      expect(todoFn).toBeCalledTimes(1)\n    })\n\n    myTest('no fixture in test', () => {\n      expect(todoFn).toBeCalledTimes(0)\n    })\n  })\n\n  describe('fixture call times', () => {\n    const apiFn = vi.fn(() => true)\n    const serviceFn = vi.fn(() => true)\n    const teardownFn = vi.fn()\n\n    interface APIFixture {\n      api: boolean\n      service: boolean\n    }\n\n    const testAPI = test.extend<APIFixture>({\n      api: async ({}, use) => {\n        await use(apiFn())\n        apiFn.mockClear()\n        teardownFn()\n      },\n      service: async ({}, use) => {\n        await use(serviceFn())\n        serviceFn.mockClear()\n        teardownFn()\n      },\n    })\n\n    beforeEach<APIFixture>(({ api, service }) => {\n      expect(api).toBe(true)\n      expect(service).toBe(true)\n      expect(apiFn).toBeCalledTimes(1)\n      expect(serviceFn).toBeCalledTimes(1)\n    })\n\n    testAPI('Should init 1 time', ({ api }) => {\n      expect(api).toBe(true)\n      expect(apiFn).toBeCalledTimes(1)\n    })\n\n    testAPI('Should init 1 time has multiple fixture', ({ api, service }) => {\n      expect(api).toBe(true)\n      expect(service).toBe(true)\n      expect(serviceFn).toBeCalledTimes(1)\n      expect(apiFn).toBeCalledTimes(1)\n    })\n\n    afterEach<APIFixture>(({ api, service }) => {\n      expect(api).toBe(true)\n      expect(service).toBe(true)\n      expect(apiFn).toBeCalledTimes(1)\n      expect(serviceFn).toBeCalledTimes(1)\n    })\n\n    afterAll(() => {\n      expect(serviceFn).toBeCalledTimes(0)\n      expect(apiFn).toBeCalledTimes(0)\n      expect(teardownFn).toBeCalledTimes(4)\n    })\n  })\n\n  describe('fixture in nested describe', () => {\n    interface Fixture {\n      foo: number\n      bar: number\n    }\n\n    const fooFn = vi.fn(() => 0)\n    const fooCleanup = vi.fn()\n\n    const barFn = vi.fn(() => 0)\n    const barCleanup = vi.fn()\n\n    const nestedTest = test.extend<Fixture>({\n      async foo({}, use) {\n        await use(fooFn())\n        fooCleanup()\n      },\n      async bar({}, use) {\n        await use(barFn())\n        barCleanup()\n      },\n    })\n\n    beforeEach<Fixture>(({ foo }) => {\n      expect(foo).toBe(0)\n    })\n\n    nestedTest('should only initialize foo', ({ foo }) => {\n      expect(foo).toBe(0)\n      expect(fooFn).toBeCalledTimes(1)\n      expect(barFn).toBeCalledTimes(0)\n    })\n\n    describe('level 2, using both foo and bar together', () => {\n      beforeEach<Fixture>(({ foo, bar }) => {\n        expect(foo).toBe(0)\n        expect(bar).toBe(0)\n      })\n\n      nestedTest('should initialize foo and bar', ({ foo, bar }) => {\n        expect(foo).toBe(0)\n        expect(bar).toBe(0)\n        expect(fooFn).toBeCalledTimes(2)\n        expect(barFn).toBeCalledTimes(1)\n      })\n\n      afterEach<Fixture>(({ foo, bar }) => {\n        expect(foo).toBe(0)\n        expect(bar).toBe(0)\n      })\n\n      afterAll(() => {\n        expect(barFn).toHaveBeenCalledTimes(1)\n        expect(barCleanup).toHaveBeenCalledTimes(1)\n        expect(fooFn).toHaveBeenCalledTimes(2)\n        expect(barCleanup).toHaveBeenCalledTimes(1)\n      })\n    })\n\n    nestedTest('should initialize foo again', ({ foo }) => {\n      expect(foo).toBe(0)\n      expect(fooFn).toBeCalledTimes(3)\n    })\n\n    afterEach<Fixture>(({ foo }) => {\n      expect(foo).toBe(0)\n    })\n\n    afterAll(() => {\n      expect(fooFn).toHaveBeenCalledTimes(3)\n      expect(fooCleanup).toHaveBeenCalledTimes(3)\n      expect(barFn).toHaveBeenCalledTimes(1)\n      expect(barCleanup).toHaveBeenCalledTimes(1)\n    })\n  })\n})\n\n// test extend with top level test\nconst numbers: number[] = []\nconst teardownFn = vi.fn()\nconst teardownTest = test.extend<{\n  numbers: number[]\n}>({\n  numbers: async ({}, use) => {\n    numbers.push(1, 2, 3)\n    await use(numbers)\n    numbers.splice(0, numbers.length)\n    teardownFn()\n  },\n})\n\nteardownTest('test without describe', ({ numbers }) => {\n  expect(numbers).toHaveLength(3)\n})\n\ntest('teardown should be called once time', () => {\n  expect(numbers).toHaveLength(0)\n  expect(teardownFn).toBeCalledTimes(1)\n})\n\ndescribe('asynchronous setup/teardown', () => {\n  const trackFn = vi.fn()\n\n  const myTest = test.extend<{ a: string }>({\n    a: async ({}, use) => {\n      trackFn('setup-sync')\n      await new Promise(resolve => setTimeout(resolve, 200))\n      trackFn('setup-async')\n      await use('ok')\n      trackFn('teardown-sync')\n      await new Promise(resolve => setTimeout(resolve, 200))\n      trackFn('teardown-async')\n    },\n  })\n\n  myTest('quick test', ({ a }) => {\n    expect(a).toBe('ok')\n    expect(trackFn.mock.calls).toEqual([['setup-sync'], ['setup-async']])\n  })\n\n  afterAll(() => {\n    expect(trackFn.mock.calls).toEqual([\n      ['setup-sync'],\n      ['setup-async'],\n      ['teardown-sync'],\n      ['teardown-async'],\n    ])\n  })\n})\n\ndescribe('scoping variables to suite', () => {\n  const testAPI = test.extend<{\n    dependency: string\n    pkg: { dependency: string }\n  }>({\n    dependency: 'default',\n    pkg: ({ dependency }, use) => use({ dependency }),\n  })\n\n  testAPI('uses default values', ({ pkg }) => {\n    expect(pkg).toEqual({ dependency: 'default' })\n  })\n\n  describe('override dependency', () => {\n    testAPI.override({ dependency: 'new' })\n\n    testAPI('uses new values', ({ pkg }) => {\n      expect(pkg).toEqual({ dependency: 'new' })\n    })\n\n    describe('nested keeps parent scope', () => {\n      testAPI('keeps using new values', ({ pkg }) => {\n        expect(pkg).toEqual({ dependency: 'new' })\n      })\n    })\n\n    describe('override nested overridden scope', () => {\n      testAPI.override({ dependency: 'override' })\n\n      testAPI('keeps using new values', ({ pkg }) => {\n        expect(pkg).toEqual({ dependency: 'override' })\n      })\n    })\n\n    testAPI('uses new values', ({ pkg }) => {\n      expect(pkg).toEqual({ dependency: 'new' })\n    })\n  })\n\n  testAPI('keeps using default values', ({ pkg }) => {\n    expect(pkg).toEqual({ dependency: 'default' })\n  })\n\n  describe('override the pkg too', () => {\n    testAPI.override({ pkg: { dependency: 'override' } })\n\n    testAPI('uses new values', ({ pkg }) => {\n      expect(pkg).toEqual({ dependency: 'override' })\n    })\n  })\n\n  describe('override as dynamic', () => {\n    testAPI.override({ dependency: ({}, use) => use('override') })\n\n    testAPI('uses new values', ({ pkg }) => {\n      expect(pkg).toEqual({ dependency: 'override' })\n    })\n  })\n\n  describe.skip('type only', () => {\n    testAPI.override({\n      // @ts-expect-error nonExisting is not defined on the testAPI\n      nonExisting: false,\n    })\n  })\n})\n\ndescribe('test.scoped repro #7793', () => {\n  const extendedTest = test.extend<{ foo: boolean }>({\n    foo: false,\n  })\n\n  describe('top level', () => {\n    extendedTest.override({ foo: true })\n\n    describe('second level', () => {\n      extendedTest('foo is true', ({ foo }) => {\n        expect(foo).toBe(true)\n      })\n    })\n  })\n})\n\ndescribe('test.scoped repro #7813', () => {\n  const extendedTest = test.extend<{ foo?: boolean }>({\n    foo: false,\n  })\n\n  describe('foo is scoped to true', () => {\n    extendedTest.override({ foo: true })\n\n    extendedTest('foo is true', ({ foo }) => {\n      expect(foo).toBe(true)\n    })\n  })\n\n  describe('foo is left as default of false', () => {\n    extendedTest('foo is false', ({ foo }) => {\n      expect(foo).toBe(false)\n    })\n  })\n})\n\ndescribe('test.scoped repro #9305', () => {\n  const extendedTest = test.extend<{\n    a: number\n    b: number\n    numbers: number[]\n  }>({\n    a: 1,\n    b: 2,\n    numbers: async ({ a }, use) => use([a]),\n  })\n\n  describe('suite with overwritten fixture', () => {\n    extendedTest.override({\n      numbers: async ({ a, b }, use) => use([a, b]),\n    })\n\n    extendedTest('scoped fixture can access dependencies from original test', async ({\n      numbers,\n    }) => {\n      expect(numbers).toStrictEqual([1, 2])\n    })\n  })\n})\n\ndescribe('suite with timeout', () => {\n  test.extend({})('timeout is inherited from suite', ({ task }) => {\n    expect(task.timeout).toBe(100)\n  })\n\n  test.extend({})('timeout is inherited from options', { timeout: 1_000 }, ({ task }) => {\n    expect(task.timeout).toBe(1_000)\n  })\n}, 100)\n\nconst counterTest = test.extend<{\n  counter: { value: number }\n  fileCounter: { value: number }\n}>({\n  counter: async ({}, use) => { await use({ value: 0 }) },\n  fileCounter: [async ({}, use) => { await use({ value: 0 }) }, { scope: 'file' }],\n})\n\ncounterTest.describe('type-safe fixture hooks', () => {\n  counterTest.beforeEach(({ counter }) => {\n    // shouldn't have typescript error because of 'counter' here\n    counter.value += 1\n  })\n\n  counterTest.afterEach(({ fileCounter }) => {\n    // shouldn't have typescript error because of 'fileCounter' here\n    fileCounter.value += 2\n  })\n\n  // beforeAll and afterAll hooks are not tested here, because they don't provide an extra context\n\n  counterTest('beforeEach fixture hook can adapt type-safe context', ({ counter }) => {\n    expect(counter.value).toBe(1)\n  })\n\n  counterTest('afterEach fixture hook can adapt type-safe context', ({ fileCounter }) => {\n    expect(fileCounter.value).toBe(2)\n  })\n})\n\n// Use the scoped fixtures approach with { $test, $file, $worker } structure\nconst helperTest = test.extend<{\n  $worker: { workerFixture: boolean }\n  $file: { fileFixture: number }\n  $test: { testFixture: string }\n}>({\n  workerFixture: [async ({}, use) => {\n    await use(true)\n  }, { scope: 'worker' }],\n  fileFixture: [async ({ workerFixture }, use) => {\n    expectTypeOf(workerFixture).toEqualTypeOf<boolean>()\n    await use(workerFixture ? 42 : 0)\n  }, { scope: 'file' }],\n  testFixture: async ({ fileFixture, workerFixture }, use) => {\n    expectTypeOf(fileFixture).toEqualTypeOf<number>()\n    expectTypeOf(workerFixture).toEqualTypeOf<boolean>()\n    await use(`test-${fileFixture}-${workerFixture}`)\n  },\n})\n\nhelperTest.describe('scoped fixtures with tuple syntax', () => {\n  helperTest('fixtures should have correct types', ({ testFixture, fileFixture, workerFixture }) => {\n    expectTypeOf(workerFixture).toEqualTypeOf<boolean>()\n    expectTypeOf(fileFixture).toEqualTypeOf<number>()\n    expectTypeOf(testFixture).toEqualTypeOf<string>()\n\n    expect(workerFixture).toBe(true)\n    expect(fileFixture).toBe(42)\n    expect(testFixture).toBe('test-42-true')\n  })\n})\n\ndescribe('builder pattern with non-function values', () => {\n  const nonFnTest = test\n    .extend('stringValue', 'hello')\n    .extend('numberValue', 42)\n    .extend('arrayValue', [1, 2, 3])\n    .extend('objectValue', { key: 'value', nested: { a: 1 } })\n\n  nonFnTest('non-function values are provided correctly', ({ stringValue, numberValue, arrayValue, objectValue }) => {\n    expectTypeOf(stringValue).toEqualTypeOf<string>()\n    expectTypeOf(numberValue).toEqualTypeOf<number>()\n    expectTypeOf(arrayValue).toEqualTypeOf<number[]>()\n    expectTypeOf(objectValue).toEqualTypeOf<{ key: string; nested: { a: number } }>()\n\n    expect(stringValue).toBe('hello')\n    expect(numberValue).toBe(42)\n    expect(arrayValue).toEqual([1, 2, 3])\n    expect(objectValue).toEqual({ key: 'value', nested: { a: 1 } })\n  })\n\n  const mixedTest = test\n    .extend('config', { port: 3000, host: 'localhost' })\n    .extend('url', async ({ config }) => {\n      expectTypeOf(config).toEqualTypeOf<{ port: number; host: string }>()\n      return `http://${config.host}:${config.port}`\n    })\n\n  mixedTest('non-function values can be used by function fixtures', ({ config, url }) => {\n    expectTypeOf(config).toEqualTypeOf<{ port: number; host: string }>()\n    expectTypeOf(url).toEqualTypeOf<string>()\n\n    expect(config).toEqual({ port: 3000, host: 'localhost' })\n    expect(url).toBe('http://localhost:3000')\n  })\n\n  // Test that synchronous (non-async) functions work in the builder pattern\n  const syncTest = test\n    .extend('prefix', 'hello')\n    .extend('syncValue', ({ prefix }) => {\n      // This is a synchronous function - no async/await needed\n      return `${prefix} world`\n    })\n    .extend('chainedSync', ({ syncValue }) => {\n      // Another sync function that depends on the previous one\n      return syncValue.toUpperCase()\n    })\n\n  syncTest('synchronous functions work in builder pattern', ({ prefix, syncValue, chainedSync }) => {\n    expectTypeOf(prefix).toEqualTypeOf<string>()\n    expectTypeOf(syncValue).toEqualTypeOf<string>()\n    expectTypeOf(chainedSync).toEqualTypeOf<string>()\n\n    expect(prefix).toBe('hello')\n    expect(syncValue).toBe('hello world')\n    expect(chainedSync).toBe('HELLO WORLD')\n  })\n})\n\n// https://github.com/vitest-dev/vitest/issues/9810\ndescribe('override auto fixture with outer beforeEach', () => {\n  const myTest = test\n    .extend('base', { auto: true }, () => 'base:default')\n    .extend('derived', { auto: true }, ({ base }) => {\n      return `derived:${base}`\n    })\n\n  beforeEach(({ task }) => {\n    expect(task).toBeTruthy()\n  })\n\n  describe('with override', () => {\n    myTest.override('base', 'base:override')\n\n    myTest('auto fixture sees overridden dependency', ({ base, derived }) => {\n      expect(base).toBe('base:override')\n      expect(derived).toBe('derived:base:override')\n    })\n  })\n})\n\ndescribe('override auto fixture with co-located beforeEach', () => {\n  const myTest = test\n    .extend('base', { auto: true }, () => 'base:default')\n    .extend('derived', { auto: true }, ({ base }) => {\n      return `derived:${base}`\n    })\n\n  myTest.override('base', 'base:override')\n\n  beforeEach(({ task }) => {\n    expect(task).toBeTruthy()\n  })\n\n  myTest('override applies when beforeEach is co-located', ({ base, derived }) => {\n    expect(base).toBe('base:override')\n    expect(derived).toBe('derived:base:override')\n  })\n})\n\ndescribe('override non-auto fixture with outer beforeEach', () => {\n  const myTest = test\n    .extend('base', () => 'base:default')\n    .extend('derived', ({ base }) => `derived:${base}`)\n\n  beforeEach(({ task }) => {\n    expect(task).toBeTruthy()\n  })\n\n  describe('with override', () => {\n    myTest.override('base', 'base:override')\n\n    myTest('override applies to non-auto dependency', ({ base, derived }) => {\n      expect(base).toBe('base:override')\n      expect(derived).toBe('derived:base:override')\n    })\n  })\n})\n\ndescribe('override fixture accessed in outer beforeEach', () => {\n  const myTest = test\n    .extend('base', () => 'base:default')\n    .extend('derived', ({ base }) => `derived:${base}`)\n\n  const hookValues: string[] = []\n\n  myTest.beforeEach(({ base }) => {\n    hookValues.push(base)\n  })\n\n  describe('with override', () => {\n    myTest.override('base', 'base:override')\n\n    myTest('beforeEach sees overridden fixture', ({ derived }) => {\n      expect(hookValues).toEqual(['base:override'])\n      expect(derived).toBe('derived:base:override')\n    })\n  })\n})\n\ndescribe('nested overrides with outer beforeEach', () => {\n  const myTest = test\n    .extend('base', { auto: true }, () => 'base:default')\n    .extend('derived', { auto: true }, ({ base }) => {\n      return `derived:${base}`\n    })\n\n  beforeEach(({ task }) => {\n    expect(task).toBeTruthy()\n  })\n\n  describe('outer', () => {\n    myTest.override('base', 'base:outer')\n\n    myTest('outer override', ({ base, derived }) => {\n      expect(base).toBe('base:outer')\n      expect(derived).toBe('derived:base:outer')\n    })\n\n    describe('inner', () => {\n      myTest.override('base', 'base:inner')\n\n      myTest('inner override wins', ({ base, derived }) => {\n        expect(base).toBe('base:inner')\n        expect(derived).toBe('derived:base:inner')\n      })\n    })\n  })\n})\n\ndescribe('override fixture accessed in aroundEach', () => {\n  const myTest = test\n    .extend('base', () => 'base:default')\n    .extend('derived', ({ base }) => `derived:${base}`)\n\n  const hookValues: string[] = []\n\n  myTest.aroundEach(async (runTest, { base }) => {\n    hookValues.push(base)\n    await runTest()\n  })\n\n  describe('with override', () => {\n    myTest.override('base', 'base:override')\n\n    myTest('aroundEach sees overridden fixture', ({ derived }) => {\n      expect(hookValues).toEqual(['base:override'])\n      expect(derived).toBe('derived:base:override')\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/test-for-suite.test.ts",
    "content": "import { describe, expect, expectTypeOf, test } from 'vitest'\n\ndescribe.for(['case1', 'case2'])(\n  'basic %s',\n  (...args) => {\n    test('test', () => {\n      expectTypeOf(args).toEqualTypeOf<[string]>()\n      expect({ args }).matchSnapshot()\n    })\n  },\n)\n\ndescribe.for`\n  a         | b\n  ${'x'}    | ${true}\n  ${'y'}    | ${false}\n`(\n  'template $a $b',\n  (...args) => {\n    test('test', () => {\n      expectTypeOf(args).toEqualTypeOf<any[]>()\n      expect({ args }).toMatchSnapshot()\n    })\n  },\n)\n\ndescribe.for([\n  [1, 1],\n  [1, 2],\n  [2, 1],\n])('add(%i, %i)', ([a, b]) => {\n  test('test', () => {\n    expect(a + b).matchSnapshot()\n  })\n})\n"
  },
  {
    "path": "test/core/test/test-for.test.ts",
    "content": "import { expect, expectTypeOf, test } from 'vitest'\n\nconst myTest = test.extend<{ myFixture: number }>({\n  myFixture: async ({}, use) => {\n    await use(1234)\n  },\n})\n\ntest.for(['case1', 'case2'])(\n  'basic %s',\n  (args) => {\n    expectTypeOf(args).toEqualTypeOf<string>()\n    expect({ args }).matchSnapshot()\n  },\n)\n\nmyTest.for(['case1', 'case2'])(\n  'fixture %s',\n  (args, { myFixture }) => {\n    expectTypeOf(args).toEqualTypeOf<string>()\n    expectTypeOf(myFixture).toEqualTypeOf<number>()\n    expect({ args, myFixture }).matchSnapshot()\n  },\n)\n\nmyTest.concurrent.for(['case1', 'case2'])(\n  'concurrent %s',\n  (args, { expect, myFixture }) => {\n    expectTypeOf(args).toEqualTypeOf<string>()\n    expectTypeOf(myFixture).toEqualTypeOf<number>()\n    expect({ args, myFixture }).matchSnapshot()\n  },\n)\n\nmyTest.concurrent.for(['case1', 'case2'] as const)(\n  'const %s',\n  (args, { expect, myFixture }) => {\n    expectTypeOf(args).toEqualTypeOf<'case1' | 'case2'>()\n    expectTypeOf(myFixture).toEqualTypeOf<number>()\n    expect({ args, myFixture }).matchSnapshot()\n  },\n)\n\nmyTest.concurrent.for([['case1-x', 'case1-y'], ['case2-x', 'case2-y']])(\n  'array %s %s',\n  (args, { expect, myFixture }) => {\n    expectTypeOf(args).toEqualTypeOf<string[]>()\n    expectTypeOf(myFixture).toEqualTypeOf<number>()\n    expect({ args, myFixture }).matchSnapshot()\n  },\n)\n\nmyTest.concurrent.for([['case1-x', 'case1-y'], ['case2-x', 'case2-y']])(\n  'array destructure %s %s',\n  ([x, y], { expect, myFixture }) => {\n    expectTypeOf(myFixture).toEqualTypeOf<number>()\n    expect({ x, y, myFixture }).matchSnapshot()\n  },\n)\n\nmyTest.concurrent.for([{ k: 'case1' }, { k: 'case2' }])(\n  'object $k',\n  (args, { expect, myFixture }) => {\n    expectTypeOf(args).toEqualTypeOf<{ k: string }>()\n    expectTypeOf(myFixture).toEqualTypeOf<number>()\n    expect({ args, myFixture }).matchSnapshot()\n  },\n)\n\nmyTest.concurrent.for([{ k: 'case1' }, { k: 'case2' }])(\n  'object destructure $k',\n  ({ k: v }, { expect, myFixture }) => {\n    expectTypeOf(myFixture).toEqualTypeOf<number>()\n    expect({ v, myFixture }).matchSnapshot()\n  },\n)\n\nmyTest.concurrent.for`\n  a         | b\n  ${'x'}    | ${true}\n  ${'y'}    | ${false}\n`(\n  'template $a $b',\n  (args, { expect, myFixture }) => {\n    expectTypeOf(args).toEqualTypeOf<any>()\n    expectTypeOf(myFixture).toEqualTypeOf<number>()\n    expect({ args, myFixture }).toMatchSnapshot()\n  },\n)\n\ntest.concurrent.for([\n  [1, 1],\n  [1, 2],\n  [2, 1],\n])('[docs] add(%i, %i)', ([a, b], { expect }) => {\n  expect(a + b).matchSnapshot()\n})\n"
  },
  {
    "path": "test/core/test/test-name-pattern.test.ts",
    "content": "import { assert, describe, it } from 'vitest'\n\nit('does include root test', () => {\n  assert.equal(Math.sqrt(4), 2)\n})\n\nit('does not include test that is root and unmatched', () => {\n  assert.fail('unmatched test was included')\n})\n\ndescribe('testNamePattern', () => {\n  it('does include test in describe', () => {\n    assert.equal(Math.sqrt(4), 2)\n  })\n\n  it('does not include test that is in describe and unmatched', () => {\n    assert.fail('unmatched test was included')\n  })\n\n  describe('nested describe', () => {\n    it('does include nested test', () => {\n      assert.equal(Math.sqrt(4), 2)\n    })\n\n    it('does not include test that is nested and unmatched', () => {\n      assert.fail('unmatched test was included')\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/test-options.test.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\nconst fail = () => expect.fail('expected to be skipped')\n\ndescribe('all test variations are allowed', () => {\n  test('skipped by default')\n\n  test.skip('skipped explicitly', fail)\n  test.skip('skipped explicitly', fail, 1000)\n  test('skipped explicitly via options', { skip: true }, fail)\n\n  test.todo('todo explicitly', fail)\n  test.todo('todo explicitly', fail, 1000)\n  test('todo explicitly via options', { todo: true }, fail)\n\n  test.fails('fails by default', fail)\n  test.fails('fails by default', fail, 1000)\n  test('fails explicitly via options', { fails: true }, fail)\n})\n\ndescribe('only is allowed explicitly', () => {\n  test('not only by default', fail)\n  test.only('only explicitly', () => {})\n})\n\ndescribe('only is allowed via options', () => {\n  test('not only by default', fail)\n  test('only via options', { only: true }, () => {})\n})\n"
  },
  {
    "path": "test/core/test/test-tags-filter.test.ts",
    "content": "import type { TestTagDefinition } from '@vitest/runner'\nimport { createTagsFilter } from '@vitest/runner/utils'\nimport { describe, expect, test } from 'vitest'\n\nfunction tags(...names: string[]): TestTagDefinition[] {\n  return names.map(name => ({ name }))\n}\n\ndescribe('createTagsFilter', () => {\n  describe('simple tag matching', () => {\n    test('matches a single tag', () => {\n      const filter = createTagsFilter(['foo'], tags('foo', 'bar'))\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar'])).toBe(false)\n      expect(filter(['foo', 'bar'])).toBe(true)\n      expect(filter([])).toBe(false)\n    })\n\n    test('matches multiple expressions (AND between expressions)', () => {\n      const filter = createTagsFilter(['foo', 'bar'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo', 'bar'])).toBe(true)\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['bar'])).toBe(false)\n      expect(filter(['foo', 'bar', 'baz'])).toBe(true)\n    })\n  })\n\n  describe('NOT operator', () => {\n    test('negates with ! prefix', () => {\n      const filter = createTagsFilter(['!foo'], tags('foo', 'bar'))\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['bar'])).toBe(true)\n      expect(filter(['foo', 'bar'])).toBe(false)\n      expect(filter([])).toBe(true)\n    })\n\n    test('negates with \"not\" keyword', () => {\n      const filter = createTagsFilter(['not foo'], tags('foo', 'bar'))\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['bar'])).toBe(true)\n      expect(filter(['foo', 'bar'])).toBe(false)\n      expect(filter([])).toBe(true)\n    })\n\n    test('double negation', () => {\n      const filter = createTagsFilter(['!!foo'], tags('foo', 'bar'))\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar'])).toBe(false)\n    })\n\n    test('double negation with \"not not\"', () => {\n      const filter = createTagsFilter(['not not foo'], tags('foo', 'bar'))\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar'])).toBe(false)\n    })\n  })\n\n  describe('AND operator', () => {\n    test('matches with \"and\" keyword', () => {\n      const filter = createTagsFilter(['foo and bar'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo', 'bar'])).toBe(true)\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['bar'])).toBe(false)\n      expect(filter(['foo', 'bar', 'baz'])).toBe(true)\n    })\n\n    test('matches with && operator', () => {\n      const filter = createTagsFilter(['foo && bar'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo', 'bar'])).toBe(true)\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['bar'])).toBe(false)\n    })\n\n    test('chained AND operators', () => {\n      const filter = createTagsFilter(['foo and bar and baz'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo', 'bar', 'baz'])).toBe(true)\n      expect(filter(['foo', 'bar'])).toBe(false)\n      expect(filter(['foo', 'baz'])).toBe(false)\n    })\n\n    test('chained && operators', () => {\n      const filter = createTagsFilter(['foo && bar && baz'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo', 'bar', 'baz'])).toBe(true)\n      expect(filter(['foo', 'bar'])).toBe(false)\n    })\n  })\n\n  describe('OR operator', () => {\n    test('matches with \"or\" keyword', () => {\n      const filter = createTagsFilter(['foo or bar'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar'])).toBe(true)\n      expect(filter(['baz'])).toBe(false)\n      expect(filter(['foo', 'bar'])).toBe(true)\n    })\n\n    test('matches with || operator', () => {\n      const filter = createTagsFilter(['foo || bar'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar'])).toBe(true)\n      expect(filter(['baz'])).toBe(false)\n    })\n\n    test('chained OR operators', () => {\n      const filter = createTagsFilter(['foo or bar or baz'], tags('foo', 'bar', 'baz', 'qux'))\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar'])).toBe(true)\n      expect(filter(['baz'])).toBe(true)\n      expect(filter(['qux'])).toBe(false)\n    })\n\n    test('chained || operators', () => {\n      const filter = createTagsFilter(['foo || bar || baz'], tags('foo', 'bar', 'baz', 'qux'))\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar'])).toBe(true)\n      expect(filter(['baz'])).toBe(true)\n      expect(filter(['qux'])).toBe(false)\n    })\n  })\n\n  describe('operator precedence', () => {\n    test('AND has higher precedence than OR', () => {\n      const filter = createTagsFilter(['foo or bar and baz'], tags('foo', 'bar', 'baz'))\n      // Parsed as: foo or (bar and baz)\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar', 'baz'])).toBe(true)\n      expect(filter(['bar'])).toBe(false)\n      expect(filter(['baz'])).toBe(false)\n    })\n\n    test('&& has higher precedence than ||', () => {\n      const filter = createTagsFilter(['foo || bar && baz'], tags('foo', 'bar', 'baz'))\n      // Parsed as: foo || (bar && baz)\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar', 'baz'])).toBe(true)\n      expect(filter(['bar'])).toBe(false)\n    })\n\n    test('NOT has highest precedence', () => {\n      const filter = createTagsFilter(['!foo and bar'], tags('foo', 'bar'))\n      // Parsed as: (!foo) and bar\n      expect(filter(['bar'])).toBe(true)\n      expect(filter(['foo', 'bar'])).toBe(false)\n      expect(filter(['foo'])).toBe(false)\n    })\n  })\n\n  describe('parentheses', () => {\n    test('overrides precedence with parentheses', () => {\n      const filter = createTagsFilter(['(foo or bar) and baz'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo', 'baz'])).toBe(true)\n      expect(filter(['bar', 'baz'])).toBe(true)\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['baz'])).toBe(false)\n    })\n\n    test('nested parentheses', () => {\n      const filter = createTagsFilter(['((foo or bar) and baz) or qux'], tags('foo', 'bar', 'baz', 'qux'))\n      expect(filter(['foo', 'baz'])).toBe(true)\n      expect(filter(['bar', 'baz'])).toBe(true)\n      expect(filter(['qux'])).toBe(true)\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['baz'])).toBe(false)\n    })\n\n    test('negation with parentheses', () => {\n      const filter = createTagsFilter(['!(foo or bar)'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['bar'])).toBe(false)\n      expect(filter(['baz'])).toBe(true)\n      expect(filter([])).toBe(true)\n    })\n\n    test('complex expression with parentheses', () => {\n      const filter = createTagsFilter(['(foo && bar) || (baz && !qux)'], tags('foo', 'bar', 'baz', 'qux'))\n      expect(filter(['foo', 'bar'])).toBe(true)\n      expect(filter(['baz'])).toBe(true)\n      expect(filter(['baz', 'qux'])).toBe(false)\n      expect(filter(['foo'])).toBe(false)\n    })\n  })\n\n  describe('wildcard patterns', () => {\n    test('matches with * wildcard', () => {\n      const filter = createTagsFilter(['test*'], tags('test', 'test-unit', 'test-e2e', 'other'))\n      expect(filter(['test-unit'])).toBe(true)\n      expect(filter(['test-e2e'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('wildcard matches zero or more characters', () => {\n      const filter = createTagsFilter(['test*'], tags('test', 'test-unit'))\n      // * matches zero or more characters\n      expect(filter(['test'])).toBe(true)\n      expect(filter(['test-unit'])).toBe(true)\n    })\n\n    test('wildcard at start', () => {\n      const filter = createTagsFilter(['*-unit'], tags('test-unit', 'e2e-unit', 'integration'))\n      expect(filter(['test-unit'])).toBe(true)\n      expect(filter(['e2e-unit'])).toBe(true)\n      expect(filter(['integration'])).toBe(false)\n    })\n\n    test('wildcard in middle', () => {\n      const filter = createTagsFilter(['test-*-fast'], tags('test-unit-fast', 'test-e2e-fast', 'test-slow'))\n      expect(filter(['test-unit-fast'])).toBe(true)\n      expect(filter(['test-e2e-fast'])).toBe(true)\n      expect(filter(['test-slow'])).toBe(false)\n    })\n\n    test('multiple wildcards', () => {\n      const filter = createTagsFilter(['*test*'], tags('unit-test-fast', 'test-e2e', 'other'))\n      expect(filter(['unit-test-fast'])).toBe(true)\n      expect(filter(['test-e2e'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('wildcard with negation', () => {\n      const filter = createTagsFilter(['!test*'], tags('test-unit', 'other'))\n      expect(filter(['test-unit'])).toBe(false)\n      expect(filter(['other'])).toBe(true)\n    })\n\n    test('wildcard with AND', () => {\n      const filter = createTagsFilter(['test* and fast'], tags('test-unit', 'fast', 'slow'))\n      expect(filter(['test-unit', 'fast'])).toBe(true)\n      expect(filter(['test-unit', 'slow'])).toBe(false)\n      expect(filter(['fast'])).toBe(false)\n    })\n\n    test('wildcard with OR', () => {\n      const filter = createTagsFilter(['test* or fast'], tags('test-unit', 'fast', 'slow'))\n      expect(filter(['test-unit'])).toBe(true)\n      expect(filter(['fast'])).toBe(true)\n      expect(filter(['slow'])).toBe(false)\n    })\n  })\n\n  describe('mixed operators', () => {\n    test('mixing \"and\" and &&', () => {\n      const filter = createTagsFilter(['foo and bar && baz'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo', 'bar', 'baz'])).toBe(true)\n      expect(filter(['foo', 'bar'])).toBe(false)\n    })\n\n    test('mixing \"or\" and ||', () => {\n      const filter = createTagsFilter(['foo or bar || baz'], tags('foo', 'bar', 'baz', 'qux'))\n      expect(filter(['foo'])).toBe(true)\n      expect(filter(['bar'])).toBe(true)\n      expect(filter(['baz'])).toBe(true)\n      expect(filter(['qux'])).toBe(false)\n    })\n\n    test('mixing ! and \"not\"', () => {\n      const filter = createTagsFilter(['!foo and not bar'], tags('foo', 'bar', 'baz'))\n      expect(filter(['baz'])).toBe(true)\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['bar'])).toBe(false)\n    })\n  })\n\n  describe('case sensitivity', () => {\n    test('operators are case-insensitive', () => {\n      const filter = createTagsFilter(['foo AND bar OR baz'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo', 'bar'])).toBe(true)\n      expect(filter(['baz'])).toBe(true)\n    })\n\n    test('NOT is case-insensitive', () => {\n      const filter = createTagsFilter(['NOT foo'], tags('foo', 'bar'))\n      expect(filter(['foo'])).toBe(false)\n      expect(filter(['bar'])).toBe(true)\n    })\n\n    test('tag names are case-sensitive', () => {\n      const filter = createTagsFilter(['Foo'], tags('Foo', 'foo'))\n      expect(filter(['Foo'])).toBe(true)\n      expect(filter(['foo'])).toBe(false)\n    })\n  })\n\n  describe('whitespace handling', () => {\n    test('handles extra whitespace', () => {\n      const filter = createTagsFilter(['  foo   and   bar  '], tags('foo', 'bar'))\n      expect(filter(['foo', 'bar'])).toBe(true)\n    })\n\n    test('handles tabs', () => {\n      const filter = createTagsFilter(['foo\\tand\\tbar'], tags('foo', 'bar'))\n      expect(filter(['foo', 'bar'])).toBe(true)\n    })\n\n    test('handles no whitespace with && and ||', () => {\n      const filter = createTagsFilter(['foo&&bar||baz'], tags('foo', 'bar', 'baz'))\n      expect(filter(['foo', 'bar'])).toBe(true)\n      expect(filter(['baz'])).toBe(true)\n    })\n  })\n\n  describe('tags with special characters', () => {\n    test('tags with hyphens', () => {\n      const filter = createTagsFilter(['test-unit'], tags('test-unit', 'test-e2e'))\n      expect(filter(['test-unit'])).toBe(true)\n      expect(filter(['test-e2e'])).toBe(false)\n    })\n\n    test('tags with underscores', () => {\n      const filter = createTagsFilter(['test_unit'], tags('test_unit', 'test_e2e'))\n      expect(filter(['test_unit'])).toBe(true)\n      expect(filter(['test_e2e'])).toBe(false)\n    })\n\n    test('tags with slashes', () => {\n      const filter = createTagsFilter(['scope/tag'], tags('scope/tag', 'other'))\n      expect(filter(['scope/tag'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('tags with dots', () => {\n      const filter = createTagsFilter(['v1.0'], tags('v1.0', 'v2.0'))\n      expect(filter(['v1.0'])).toBe(true)\n      expect(filter(['v2.0'])).toBe(false)\n    })\n\n    test('tags with @ symbol and non-alphanumeric characters', () => {\n      const filter = createTagsFilter(['@scope/tag'], tags('@scope/tag', '@other/tag'))\n      expect(filter(['@scope/tag'])).toBe(true)\n      expect(filter(['@other/tag'])).toBe(false)\n    })\n\n    test('tags with UTF-8 characters', () => {\n      const filter = createTagsFilter(['测试'], tags('测试', '测试2', 'test'))\n      expect(filter(['测试'])).toBe(true)\n      expect(filter(['测试2'])).toBe(false)\n      expect(filter(['test'])).toBe(false)\n    })\n\n    test('tags with @ followed by UTF-8 characters', () => {\n      const filter = createTagsFilter(['@日本語'], tags('@日本語', '@中文', 'english'))\n      expect(filter(['@日本語'])).toBe(true)\n      expect(filter(['@中文'])).toBe(false)\n      expect(filter(['english'])).toBe(false)\n    })\n\n    test('tags with mixed special characters and UTF-8', () => {\n      const filter = createTagsFilter(['@tag-名前_v1.0'], tags('@tag-名前_v1.0', '@tag-other_v1.0'))\n      expect(filter(['@tag-名前_v1.0'])).toBe(true)\n      expect(filter(['@tag-other_v1.0'])).toBe(false)\n    })\n\n    test('tags with emoji characters', () => {\n      const filter = createTagsFilter(['test-🚀'], tags('test-🚀', 'test-💚', 'test'))\n      expect(filter(['test-🚀'])).toBe(true)\n      expect(filter(['test-💚'])).toBe(false)\n    })\n\n    test('tags with special chars containing operator keywords', () => {\n      const filter = createTagsFilter(['or@tag || and@test || not@feature'], tags('or@tag', 'and@test', 'not@feature', 'other'))\n      expect(filter(['or@tag'])).toBe(true)\n      expect(filter(['and@test'])).toBe(true)\n      expect(filter(['not@feature'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('tags with UTF-8 chars containing operator keywords', () => {\n      const filter = createTagsFilter(['or日本語 || and中文 || not한국어'], tags('or日本語', 'and中文', 'not한국어', 'english'))\n      expect(filter(['or日本語'])).toBe(true)\n      expect(filter(['and中文'])).toBe(true)\n      expect(filter(['not한국어'])).toBe(true)\n      expect(filter(['english'])).toBe(false)\n    })\n\n    test('operator keywords with @ and UTF-8 in complex expressions', () => {\n      const filter = createTagsFilter(['(or@tag || and@test) && not@feature'], tags('or@tag', 'and@test', 'not@feature', 'other'))\n      expect(filter(['or@tag', 'not@feature'])).toBe(true)\n      expect(filter(['and@test', 'not@feature'])).toBe(true)\n      expect(filter(['or@tag'])).toBe(false)\n      expect(filter(['other'])).toBe(false)\n    })\n  })\n\n  describe('edge cases', () => {\n    test('empty test tags array', () => {\n      const filter = createTagsFilter(['foo'], tags('foo'))\n      expect(filter([])).toBe(false)\n    })\n\n    test('empty expressions array returns true for any tags', () => {\n      const filter = createTagsFilter([], tags('foo'))\n      expect(filter(['foo'])).toBe(true)\n      expect(filter([])).toBe(true)\n    })\n\n    test('tag that looks like an operator but is not', () => {\n      const filter = createTagsFilter(['android'], tags('android', 'ios'))\n      expect(filter(['android'])).toBe(true)\n      expect(filter(['ios'])).toBe(false)\n    })\n\n    test('tag that starts with \"or\" but is not OR', () => {\n      const filter = createTagsFilter(['orange'], tags('orange', 'apple'))\n      expect(filter(['orange'])).toBe(true)\n      expect(filter(['apple'])).toBe(false)\n    })\n\n    test('tag that starts with \"and\" but is not AND', () => {\n      const filter = createTagsFilter(['android'], tags('android', 'ios'))\n      expect(filter(['android'])).toBe(true)\n    })\n\n    test('tag that starts with \"not\" but is not NOT', () => {\n      const filter = createTagsFilter(['nothing'], tags('nothing', 'something'))\n      expect(filter(['nothing'])).toBe(true)\n      expect(filter(['something'])).toBe(false)\n    })\n\n    test('tag containing \"and\" in the middle', () => {\n      const filter = createTagsFilter(['standalone'], tags('standalone', 'other'))\n      expect(filter(['standalone'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('tag containing \"or\" in the middle', () => {\n      const filter = createTagsFilter(['priority'], tags('priority', 'other'))\n      expect(filter(['priority'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('tag containing \"not\" in the middle', () => {\n      const filter = createTagsFilter(['annotation'], tags('annotation', 'other'))\n      expect(filter(['annotation'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('tag ending with \"and\"', () => {\n      const filter = createTagsFilter(['demand'], tags('demand', 'other'))\n      expect(filter(['demand'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('tag ending with \"or\"', () => {\n      const filter = createTagsFilter(['editor'], tags('editor', 'other'))\n      expect(filter(['editor'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('tag ending with \"not\"', () => {\n      const filter = createTagsFilter(['cannot'], tags('cannot', 'other'))\n      expect(filter(['cannot'])).toBe(true)\n      expect(filter(['other'])).toBe(false)\n    })\n\n    test('complex expression with tags containing operator substrings', () => {\n      const filter = createTagsFilter(['android and editor or nothing'], tags('android', 'editor', 'nothing'))\n      // Parsed as: android AND editor OR nothing\n      expect(filter(['android', 'editor'])).toBe(true)\n      expect(filter(['nothing'])).toBe(true)\n      expect(filter(['android'])).toBe(false)\n      expect(filter(['editor'])).toBe(false)\n    })\n  })\n\n  describe('validation errors', () => {\n    test('throws error for unknown tag', () => {\n      expect(() => createTagsFilter(['unknown'], tags('foo', 'bar'))).toThrow(\n        'The tag pattern \"unknown\" is not defined in the configuration',\n      )\n    })\n\n    test('throws error for unknown tag in expression', () => {\n      expect(() => createTagsFilter(['foo and unknown'], tags('foo', 'bar'))).toThrow(\n        'The tag pattern \"unknown\" is not defined in the configuration',\n      )\n    })\n\n    test('throws error when no tags defined', () => {\n      expect(() => createTagsFilter(['foo'], [])).toThrow(\n        'The Vitest config does\\'t define any \"tags\"',\n      )\n    })\n\n    test('throws error for wildcard pattern that matches nothing', () => {\n      expect(() => createTagsFilter(['xyz*'], tags('foo', 'bar'))).toThrow(\n        'The tag pattern \"xyz*\" is not defined in the configuration',\n      )\n    })\n  })\n\n  describe('parser errors', () => {\n    test('throws error for unclosed parenthesis', () => {\n      expect(() => createTagsFilter(['(foo and bar'], tags('foo', 'bar'))).toThrowErrorMatchingInlineSnapshot(`[Error: Invalid tags expression: missing closing \")\" in \"(foo and bar\"]`)\n    })\n\n    test('throws error for unexpected closing parenthesis', () => {\n      expect(() => createTagsFilter(['foo and bar)'], tags('foo', 'bar'))).toThrowErrorMatchingInlineSnapshot(`[Error: Invalid tags expression: unexpected \")\" in \"foo and bar)\"]`)\n    })\n\n    test('throws error for empty parentheses', () => {\n      expect(() => createTagsFilter(['()'], tags('foo'))).toThrowErrorMatchingInlineSnapshot(`[Error: Invalid tags expression: unexpected \")\" in \"()\"]`)\n    })\n\n    test('throws error for operator without operand', () => {\n      expect(() => createTagsFilter(['foo and'], tags('foo', 'bar'))).toThrowErrorMatchingInlineSnapshot(`[Error: Invalid tags expression: unexpected end of expression in \"foo and\"]`)\n    })\n\n    test('throws error for leading operator', () => {\n      expect(() => createTagsFilter(['and foo'], tags('foo'))).toThrowErrorMatchingInlineSnapshot(`[Error: Invalid tags expression: unexpected \"and\" in \"and foo\"]`)\n    })\n  })\n\n  describe('complex real-world scenarios', () => {\n    test('filter slow tests but include critical', () => {\n      const filter = createTagsFilter(['!slow or critical'], tags('slow', 'fast', 'critical'))\n      expect(filter(['fast'])).toBe(true)\n      expect(filter(['slow'])).toBe(false)\n      expect(filter(['slow', 'critical'])).toBe(true)\n    })\n\n    test('run only unit tests that are not flaky', () => {\n      const filter = createTagsFilter(['unit && !flaky'], tags('unit', 'e2e', 'flaky'))\n      expect(filter(['unit'])).toBe(true)\n      expect(filter(['unit', 'flaky'])).toBe(false)\n      expect(filter(['e2e'])).toBe(false)\n    })\n\n    test('run browser tests for chrome or firefox but not edge', () => {\n      const filter = createTagsFilter(['browser && (chrome || firefox) && !edge'], tags('browser', 'chrome', 'firefox', 'edge'))\n      expect(filter(['browser', 'chrome'])).toBe(true)\n      expect(filter(['browser', 'firefox'])).toBe(true)\n      expect(filter(['browser', 'edge'])).toBe(false)\n      expect(filter(['chrome'])).toBe(false)\n    })\n\n    test('multiple filter expressions act as AND', () => {\n      const filter = createTagsFilter(['unit || e2e', '!slow'], tags('unit', 'e2e', 'slow', 'fast'))\n      expect(filter(['unit'])).toBe(true)\n      expect(filter(['e2e'])).toBe(true)\n      expect(filter(['unit', 'slow'])).toBe(false)\n      expect(filter(['e2e', 'slow'])).toBe(false)\n      expect(filter(['fast'])).toBe(false)\n    })\n  })\n})\n"
  },
  {
    "path": "test/core/test/threads-specific.threads.test.ts",
    "content": "import { isMainThread, threadId } from 'node:worker_threads'\nimport { expect, test } from 'vitest'\n\ntest('has access access to worker API', ({ task, skip }) => {\n  skip(task.file.pool !== 'threads', 'Run only in child_process pool')\n  expect(isMainThread).toBe(false)\n  expect(threadId).toBeGreaterThan(0)\n})\n\ntest('doesn\\'t have access access to child_process API', ({ task, skip }) => {\n  skip(task.file.pool !== 'threads', 'Run only in child_process pool')\n  expect(process.send).toBeUndefined()\n})\n"
  },
  {
    "path": "test/core/test/timeout.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\n\ndescribe('suite timeout', { timeout: 100 }, () => {\n  test('timeout is inherited', async ({ task }) => {\n    expect(task.timeout).toBe(100)\n  })\n})\n\ndescribe('suite timeout simple input', () => {\n  test('timeout is inherited', async ({ task }) => {\n    expect(task.timeout).toBe(100)\n  })\n}, 100)\n"
  },
  {
    "path": "test/core/test/timers-getMockedSystemTime.test.ts",
    "content": "import { afterEach, expect, it, vi } from 'vitest'\n\nafterEach(() => {\n  vi.useRealTimers()\n})\n\nit('with fake timers', () => {\n  expect(vi.getMockedSystemTime()).toBe(null)\n\n  vi.useFakeTimers()\n  expect(vi.getMockedSystemTime()).toEqual(new Date())\n\n  vi.setSystemTime(0)\n  expect(vi.getMockedSystemTime()).toEqual(new Date())\n  expect(vi.getMockedSystemTime()).toEqual(new Date(0))\n\n  vi.advanceTimersByTime(1234)\n  expect(vi.getMockedSystemTime()).toEqual(new Date())\n  expect(vi.getMockedSystemTime()).toEqual(new Date(1234))\n\n  vi.useRealTimers()\n  expect(vi.getMockedSystemTime()).toBe(null)\n  expect(new Date()).not.toEqual(new Date(1234))\n\n  vi.useFakeTimers({ now: 12345 })\n  expect(vi.getMockedSystemTime()).toEqual(new Date())\n  expect(vi.getMockedSystemTime()).toEqual(new Date(12345))\n})\n\nit('without fake timers', () => {\n  expect(vi.getMockedSystemTime()).toBe(null)\n\n  vi.setSystemTime(0)\n  expect(vi.getMockedSystemTime()).toEqual(new Date())\n  expect(vi.getMockedSystemTime()).toEqual(new Date(0))\n\n  vi.setSystemTime(1234)\n  expect(vi.getMockedSystemTime()).toEqual(new Date())\n  expect(vi.getMockedSystemTime()).toEqual(new Date(1234))\n\n  vi.useRealTimers()\n  expect(vi.getMockedSystemTime()).toBe(null)\n  expect(new Date()).not.toEqual(new Date(1234))\n\n  vi.setSystemTime(12345)\n  expect(vi.getMockedSystemTime()).toEqual(new Date())\n  expect(vi.getMockedSystemTime()).toEqual(new Date(12345))\n})\n"
  },
  {
    "path": "test/core/test/timers-jsdom.test.ts",
    "content": "// @vitest-environment jsdom\n\nimport './fixtures/timers.suite'\n"
  },
  {
    "path": "test/core/test/timers-node.test.ts",
    "content": "// @vitest-environment node\n\nimport './fixtures/timers.suite'\n"
  },
  {
    "path": "test/core/test/timers-queueMicrotask.test.ts",
    "content": "import { expect, onTestFinished, test, vi } from 'vitest'\n\ntest(`node fetch works without fake timers`, async () => {\n  expect(await Response.json('ok').json()).toBe('ok')\n})\n\ntest(`node fetch works with fake timers`, async () => {\n  vi.useFakeTimers()\n  onTestFinished(() => {\n    vi.useRealTimers()\n  })\n  expect(await Response.json('ok').json()).toBe('ok')\n})\n\n// skipped since this might cause a weird OOM on CI\ntest.skip(`node fetch timeouts with fake queueMicrotask`, async () => {\n  vi.useFakeTimers({ toFake: ['queueMicrotask'] })\n  onTestFinished(() => {\n    vi.useRealTimers()\n  })\n  expect(\n    await Promise.race([\n      new Promise(r => setTimeout(() => r('timeout'), 200)),\n      Response.json('ok').json(),\n    ]),\n  ).toBe('timeout')\n})\n"
  },
  {
    "path": "test/core/test/unhandled.test.ts",
    "content": "import { test } from 'vitest'\n\nprocess.on('unhandledRejection', () => {\n  // ignore errors\n})\n\ntest('throws unhandled but not reported', () => {\n  // eslint-disable-next-line no-new\n  new Promise((resolve, reject) => {\n    reject(new Error('promise error'))\n  })\n})\n"
  },
  {
    "path": "test/core/test/unmock-import.test.ts",
    "content": "import { afterEach, beforeEach, expect, test, vi } from 'vitest'\n\n// https://github.com/vitest-dev/vitest/issues/1940\nbeforeEach(() => {\n  vi.doMock('/data', () => ({\n    data: {\n      state: 'STARTED',\n    },\n  }))\n})\n\nafterEach(() => {\n  vi.doUnmock('/data')\n})\n\ntest('first import', async () => {\n  // @ts-expect-error I know this\n  const { data } = await import('/data')\n  data.state = 'STOPPED'\n  expect(data.state).toBe('STOPPED')\n})\n\ntest('second import should have been re-mocked', async () => {\n  // @ts-expect-error I know this\n  const { data } = await import('/data')\n  expect(data.state).toBe('STARTED')\n})\n\ntest('unmock should clear modules replaced with imitation', async () => {\n  vi.doMock('./fixtures/mocked-dependency')\n  const { helloWorld } = await import('./fixtures/mocked-dependency')\n  expect(vi.isMockFunction(helloWorld)).toBe(true)\n\n  vi.doUnmock('./fixtures/mocked-dependency')\n  const { helloWorld: unmocked } = await import('./fixtures/mocked-dependency')\n  expect(vi.isMockFunction(unmocked)).toBe(false)\n})\n"
  },
  {
    "path": "test/core/test/url-ssr.test.ts",
    "content": "// @vitest-environment node\n\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { dirname, resolve } from 'pathe'\nimport { expect, it } from 'vitest'\n\nit('correctly resolves new assets URL paths', () => {\n  const urlCss = new URL('../src/file-css.css', import.meta.url)\n  expect(urlCss.toString()).toBe(\n    pathToFileURL(resolve(dirname(fileURLToPath(import.meta.url)), '../src/file-css.css')).toString(),\n  )\n})\n\nit('doesn\\'t resolve aliases for new URL in SSR', () => {\n  const urlAlias = new URL('#/file-css.css', import.meta.url)\n  expect(urlAlias.toString()).toBe(\n    pathToFileURL(`${fileURLToPath(import.meta.url)}#/file-css.css`).toString().replace('%23', '#'),\n  )\n})\n"
  },
  {
    "path": "test/core/test/url-web.test.ts",
    "content": "// @vitest-environment jsdom\n\nimport { expect, it } from 'vitest'\n\nit('correctly resolves new assets URL paths', () => {\n  const urlCss = new URL('../src/file-css.css', import.meta.url)\n  expect(urlCss.toString()).toBe('http://localhost:3000/src/file-css.css')\n})\n\nit('correctly resolves aliased URL paths', () => {\n  const urlAlias = new URL('#/file-css.css', import.meta.url)\n  expect(urlAlias.toString()).toBe('http://localhost:3000/src/file-css.css')\n})\n"
  },
  {
    "path": "test/core/test/utils-display.spec.ts",
    "content": "import util from 'node:util'\nimport { format } from '@vitest/utils/display'\nimport { describe, expect, test } from 'vitest'\n\ndescribe('format', () => {\n  const obj = {} as any\n  obj.obj = obj\n\n  test.each([\n    [''],\n    ['test'],\n    [{ obj: { nested: true }, value: 1 }],\n    ['test %s', 'test'],\n    ['test %s %s', 'test', 'test'],\n    ['test %s %s', 'test', 'test', 'test'],\n    ['%s', 100],\n    ['%s', 100n],\n    ['%s', -0],\n    ['%s', null],\n    ['%s', null, 'next'],\n    [\n      '%s',\n      new (class {\n        constructor(public value: string) {}\n        toString() {\n          return this.value\n        }\n      })('string value'),\n    ],\n    ['%s', Symbol('test')],\n    ['%d', 100],\n    ['%d', 100n],\n    ['%d', null],\n    ['%d', {}],\n    ['%d', {}, 'next'],\n    ['%d', Symbol('test')],\n    ['%i', 100],\n    ['%i', 100n],\n    ['%i', null],\n    ['%i', {}],\n    ['%i', {}, 'next'],\n    ['%i', Symbol('test')],\n    ['%f', 100],\n    ['%f', 100n],\n    ['%f', null],\n    ['%f', {}],\n    ['%f', {}, 'next'],\n    ['%f', Symbol('test')],\n    ['%o', 'string'],\n    ['%o', 100],\n    ['%o', 100n],\n    ['%o', null],\n    ['%o', {}],\n    ['%o', {}, 'next'],\n    ['%o', Symbol('test')],\n    ['%O', 'string'],\n    ['%O', 100],\n    ['%O', 100n],\n    ['%O', null],\n    ['%O', {}],\n    ['%O', {}, 'next'],\n    ['%O', Symbol('test')],\n    ['%c', 'css value'],\n    ['%c', 'css value', 'some other value'],\n    ['%c %f', 'css value', '100.00'],\n    ['%j', 'string'],\n    ['%j', 100],\n    ['%j', null],\n    ['%j', {}],\n    ['%j', {}, 'next'],\n    ['%j', { obj }],\n    ['%j', { fn: () => {} }],\n    ['%j', Symbol('test')],\n    ['%%', 'string'],\n    ['prefix', Symbol('test')],\n  ])('format(%s)', (formatString, ...args) => {\n    expect(format(formatString, ...args), `failed ${formatString}`).toBe(util.format(formatString, ...args))\n  })\n\n  test('cannot serialize some values', () => {\n    expect(() => format('%j', 100n)).toThrowErrorMatchingInlineSnapshot(`[TypeError: Do not know how to serialize a BigInt]`)\n  })\n\n  test.each(\n    [\n      {\n        name: 'without format',\n        args: [{ n: { a: { b: { c: { d: { e: '3' } } } } } }],\n        result: '{ n: { a: { b: { c: { d: { e: \\'3\\' } } } } } }',\n      },\n      {\n        name: 'as an object',\n        args: ['%o', {}, { n: { a: { b: { c: '3' } } } }],\n        result: '{} { n: { a: { b: { c: \\'3\\' } } } }',\n      },\n      {\n        name: 'as a full object',\n        args: ['%O', {}, { n: { a: { b: { c: '3' } } } }],\n        result: '{} { n: { a: { b: { c: \\'3\\' } } } }',\n      },\n      {\n        name: 'as a json',\n        args: ['%j', {}, { n: { a: { b: { c: '3' } } } }],\n        result: '{} { n: { a: { b: { c: \\'3\\' } } } }',\n      },\n    ],\n  )('formats objects $name (loupe doesn\\'t respect depth)', ({ args, result }) => {\n    expect(format(...args)).toBe(result)\n  })\n})\n"
  },
  {
    "path": "test/core/test/utils.spec.ts",
    "content": "import { objDisplay } from '@vitest/utils/display'\nimport { assertTypes, deepClone, deepMerge, isNegativeNaN, objectAttr, toArray } from '@vitest/utils/helpers'\nimport { parseSingleFFOrSafariStack } from '@vitest/utils/source-map'\nimport { EvaluatedModules } from 'vite/module-runner'\nimport { beforeAll, describe, expect, test } from 'vitest'\nimport { deepMergeSnapshot } from '../../../packages/snapshot/src/port/utils'\nimport { resetModules } from '../../../packages/vitest/src/runtime/utils'\n\ndescribe('assertTypes', () => {\n  test('the type of value should be number', () => {\n    const value = 5\n    const value_string = '5'\n    assertTypes(value, 'value', ['number'])\n    expect(() => assertTypes(value_string, 'value_string', ['number'])).toThrow()\n  })\n\n  test('the type of value should be number or BigInt', () => {\n    const value_number = 5\n    const value_bigint = BigInt(5)\n    const value_string = '5'\n    assertTypes(value_number, 'value_number', ['number', 'bigint'])\n    assertTypes(value_bigint, 'value_bigint', ['number', 'bigint'])\n    expect(() => assertTypes(value_string, 'value_string', ['number', 'bigint'])).toThrow()\n  })\n})\n\ndescribe('deepMerge', () => {\n  test('non plain objects retain their prototype, arrays are not merging, plain objects are merging', () => {\n    class TestA {\n      baz = 'baz'\n\n      get foo() {\n        return 'foo'\n      }\n    }\n    class TestB {\n      bar = 'bar'\n    }\n\n    const testA = new TestA()\n    const testB = new TestB()\n\n    const a = {\n      test: testA,\n      num: 30,\n      array: [1, 2],\n      obj: {\n        foo: 'foo',\n      },\n    }\n\n    const b = {\n      test: testB,\n      num: 40,\n      array: [3, 4],\n      obj: {\n        baz: 'baz',\n      },\n    }\n\n    const merged = deepMerge(a, b)\n\n    expect(merged.test instanceof TestB).toBe(true)\n    expect(merged.test.baz).toBeUndefined()\n    expect(merged.num).toBe(40)\n    expect(merged.array).toEqual([3, 4])\n    expect(merged.obj).toEqual({\n      foo: 'foo',\n      baz: 'baz',\n    })\n  })\n\n  test('deepMergeSnapshot considers asymmetric matcher', () => {\n    class Test {\n      zoo = 'zoo'\n      get bar() {\n        return 'name'\n      }\n    }\n\n    const obj = deepMergeSnapshot({\n      regexp: /test/,\n      test: new Test(),\n      name: 'name',\n      foo: 5,\n      array: [/test/, 'test'],\n    }, {\n      name: expect.stringContaining('name'),\n      foo: 88,\n      array: [/test2/],\n      test: { baz: 'baz' },\n    })\n\n    expect(obj.regexp instanceof RegExp).toBe(true)\n    expect(obj.test instanceof Test).toBe(false)\n    expect(obj.array[0] instanceof RegExp).toBe(false)\n\n    expect(obj).toEqual({\n      regexp: /test/,\n      test: { baz: 'baz', zoo: 'zoo' },\n      name: expect.stringContaining('name'),\n      foo: 88,\n      array: [{}, 'test'],\n    })\n  })\n})\n\ndescribe('toArray', () => {\n  test('number should be converted to array correctly', () => {\n    expect(toArray(0)).toEqual([0])\n    expect(toArray(1)).toEqual([1])\n    expect(toArray(2)).toEqual([2])\n  })\n\n  test('return empty array when given null or undefined', () => {\n    expect(toArray(null)).toEqual([])\n    expect(toArray(undefined)).toEqual([])\n  })\n\n  test('return the value as is when given the array', () => {\n    expect(toArray([1, 1, 2])).toEqual([1, 1, 2])\n  })\n\n  test('object should be stored in the array correctly', () => {\n    expect(toArray({ a: 1, b: 1, expected: 2 })).toEqual([{ a: 1, b: 1, expected: 2 }])\n  })\n})\n\ndescribe('deepClone', () => {\n  test('various types should be cloned correctly', () => {\n    expect(deepClone(1)).toBe(1)\n    expect(deepClone(true)).toBe(true)\n    expect(deepClone(undefined)).toBe(undefined)\n    expect(deepClone(null)).toBe(null)\n    expect(deepClone({ a: 1 })).toEqual({ a: 1 })\n    expect(deepClone([1, 2])).toEqual([1, 2])\n    const symbolA = Symbol('a')\n    expect(deepClone(symbolA)).toBe(symbolA)\n    const objB: any = {}\n    Object.defineProperty(objB, 'value', {\n      configurable: false,\n      enumerable: false,\n      value: 1,\n      writable: false,\n    })\n    Object.defineProperty(objB, 'writableValue', {\n      configurable: false,\n      enumerable: false,\n      value: 1,\n      writable: true,\n    })\n    expect(deepClone(objB).value).toEqual(objB.value)\n    expect(Object.getOwnPropertyDescriptor(deepClone(objB), 'value')?.writable).toEqual(false)\n    expect(\n      Object.getOwnPropertyDescriptor(deepClone(objB), 'writableValue')?.writable,\n    ).toEqual(true)\n    expect(\n      Object.getOwnPropertyDescriptor(deepClone(objB, { forceWritable: true }), 'value')?.writable,\n    ).toEqual(true)\n    const objC = Object.create(objB)\n    expect(deepClone(objC).value).toEqual(objC.value)\n    const objD: any = { name: 'd', ref: null }\n    objD.ref = objD\n    expect(deepClone(objD)).toEqual(objD)\n  })\n\n  test('can clone classes with proxied enumerable getters', () => {\n    const obj = Symbol.for('aClass')\n    interface TestShape { a: number; b: string }\n    class A {\n      [obj]: TestShape\n      constructor(data: TestShape) {\n        this[obj] = data\n        return new Proxy(this, {\n          ownKeys() {\n            return Reflect.ownKeys(data)\n          },\n          getOwnPropertyDescriptor(target, p) {\n            return {\n              ...Reflect.getOwnPropertyDescriptor(data, p),\n              enumerable: true,\n            }\n          },\n        })\n      }\n\n      get a() {\n        return this[obj].a\n      }\n\n      get b() {\n        return this[obj].b\n      }\n    }\n    const shape = { a: 1 } as TestShape\n    Object.defineProperty(shape, 'b', {\n      configurable: true,\n      enumerable: true,\n      get: () => 'B',\n    })\n    const aClass = new A(shape)\n    expect(aClass.a).toEqual(1)\n    expect(aClass.b).toEqual('B')\n    expect(Object.keys(aClass)).toEqual(['a', 'b'])\n    expect(deepClone({ aClass })).toEqual({ aClass: new A({ a: 1, b: 'B' }) })\n  })\n})\n\ndescribe('resetModules doesn\\'t resets only user modules', () => {\n  const moduleCache = new EvaluatedModules()\n  const modules = [\n    ['/some-module.ts', true],\n    ['/@fs/some-path.ts', true],\n    ['/node_modules/vitest/dist/index.js', false],\n    ['/node_modules/vitest-virtual-da9876a/dist/index.js', false],\n    ['/node_modules/some-module@vitest/dist/index.js', false],\n    ['/packages/vitest/dist/index.js', false],\n    ['mock:/some-module.ts', false],\n    ['mock:/@fs/some-path.ts', false],\n  ] as const\n\n  beforeAll(() => {\n    modules.forEach(([path]) => {\n      const exports = {}\n      moduleCache.idToModuleMap.set(path, {\n        id: path,\n        url: path,\n        file: path,\n        importers: new Set(),\n        imports: new Set(),\n        evaluated: true,\n        meta: undefined,\n        exports,\n        promise: Promise.resolve(exports),\n        map: undefined,\n      })\n    })\n    resetModules(moduleCache)\n  })\n\n  test.each(modules)('Cache for %s is reset (%s)', (path, reset) => {\n    const cached = moduleCache.idToModuleMap.get(path)\n\n    if (reset) {\n      expect(cached).toHaveProperty('exports', undefined)\n      expect(cached).toHaveProperty('promise', undefined)\n    }\n    else {\n      expect(cached).toHaveProperty('exports')\n      expect(cached).toHaveProperty('promise')\n    }\n\n    expect(cached).toHaveProperty('map')\n  })\n})\n\ndescribe('objectAttr', () => {\n  const arrow = (a: number) => a * 3\n  const func = function (a: number) {\n    return a * 3\n  }\n\n  test.each`\n    value                         | path            | expected\n    ${{ foo: 'bar' }}             | ${'foo'}        | ${'bar'}\n    ${{ foo: { bar: 'baz' } }}    | ${'foo'}        | ${{ bar: 'baz' }}\n    ${{ foo: { bar: 'baz' } }}    | ${'foo.bar'}    | ${'baz'}\n    ${{ foo: [{ bar: 'baz' }] }}  | ${'foo.0.bar'}  | ${'baz'}\n    ${{ foo: [1, 2, ['a']] }}     | ${'foo'}        | ${[1, 2, ['a']]}\n    ${{ foo: [1, 2, ['a']] }}     | ${'foo.2'}      | ${['a']}\n    ${{ foo: [1, 2, ['a']] }}     | ${'foo.2.0'}    | ${'a'}\n    ${{ foo: [[1]] }}             | ${'foo.0.0'}    | ${1}\n    ${{ deep: [[[1]]] }}          | ${'deep.0.0.0'} | ${1}\n    ${{ a: 1, b: 2, c: 3, d: 4 }} | ${'a'}          | ${1}\n    ${{ arrow }}                  | ${'arrow'}      | ${arrow}\n    ${{ func }}                   | ${'func'}       | ${func}\n  `('objectAttr($value, $path) -> $expected', ({ value, path, expected }) => {\n    expect(objectAttr(value, path)).toEqual(expected)\n  })\n})\n\ndescribe('objDisplay', () => {\n  test.each`\n  value | expected\n  ${'a'.repeat(100)} | ${`'${'a'.repeat(37)}…'`}\n  ${'🐱'.repeat(100)} | ${`'${'🐱'.repeat(18)}…'`}\n  ${`a${'🐱'.repeat(100)}…`} | ${`'a${'🐱'.repeat(18)}…'`}\n  `('Do not truncate strings anywhere but produce valid unicode strings for $value', ({ value, expected }) => {\n    // encodeURI can be used to detect invalid strings including invalid code-points\n    // note: our code should not split surrogate pairs, but may split graphemes\n    expect(() => encodeURI(objDisplay(value))).not.toThrow()\n    expect(objDisplay(value)).toEqual(expected)\n  })\n})\n\ndescribe('isNegativeNaN', () => {\n  test.each`\n  value | expected\n  ${Number.NaN} | ${false}\n  ${-Number.NaN} | ${true}\n  ${0} | ${false}\n  ${-0} | ${false}\n  ${1} | ${false}\n  ${-1} | ${false}\n  ${Number.POSITIVE_INFINITY} | ${false}\n  ${Number.NEGATIVE_INFINITY} | ${false}\n  `('isNegativeNaN($value) -> $expected', ({ value, expected }) => {\n    expect(isNegativeNaN(value)).toBe(expected)\n  })\n})\n\ndescribe('parseSingleFFOrSafariStack', () => {\n  test('should parse valid Firefox/Safari stack traces with file protocol', () => {\n    const validStackLine = 'functionName@file:///path/to/file.js:123:45'\n\n    const result = parseSingleFFOrSafariStack(validStackLine)\n\n    expect(result).toEqual({\n      file: 'file:///path/to/file.js',\n      method: 'functionName',\n      line: 123,\n      column: 45,\n    })\n  })\n\n  test('should parse valid Firefox/Safari stack traces with https protocol', () => {\n    const validStackLine = 'functionName@https://example.com/path/to/file.js:123:45'\n\n    const result = parseSingleFFOrSafariStack(validStackLine)\n\n    expect(result).toEqual({\n      file: '/path/to/file.js',\n      method: 'functionName',\n      line: 123,\n      column: 45,\n    })\n  })\n\n  test('should handle stack lines without function names', () => {\n    const stackLineWithoutFunction = '@file:///path/to/file.js:123:45'\n\n    const result = parseSingleFFOrSafariStack(stackLineWithoutFunction)\n\n    expect(result).toEqual({\n      file: 'file:///path/to/file.js',\n      method: '',\n      line: 123,\n      column: 45,\n    })\n  })\n\n  test('should parse https URLs with @fs prefix without function name', () => {\n    const stackLine = '@https://@fs/path/to/file.js:123:4'\n\n    const result = parseSingleFFOrSafariStack(stackLine)\n\n    expect(result).toEqual({\n      file: '/path/to/file.js',\n      method: '',\n      line: 123,\n      column: 4,\n    })\n  })\n\n  test('should parse https URLs with @fs prefix with function name', () => {\n    const stackLine = 'functionName@https://@fs/path/to/file.js:123:4'\n\n    const result = parseSingleFFOrSafariStack(stackLine)\n\n    expect(result).toEqual({\n      file: '/path/to/file.js',\n      method: 'functionName',\n      line: 123,\n      column: 4,\n    })\n  })\n\n  test('should not hang when `Error.stackTraceLimit = 0` (#6039)', { timeout: 5_000 }, async () => {\n    // 40 takes ~30s on M2 CPU when fix is reverted\n    const size = 40\n\n    const obj = Object.fromEntries(\n      [...Array.from({ length: size }).keys()].map(i => [`prop${i}`, i]),\n    )\n\n    class PrettyError extends globalThis.Error {\n      constructor(e: unknown) {\n        Error.stackTraceLimit = 0\n        super(JSON.stringify(e))\n      }\n    }\n\n    parseSingleFFOrSafariStack(new PrettyError(obj).stack!)\n  })\n})\n"
  },
  {
    "path": "test/core/test/vi.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\n\nimport type { Mock, Mocked, MockedFunction, MockedObject, MockInstance } from 'vitest'\nimport { describe, expect, expectTypeOf, test, vi } from 'vitest'\nimport { getWorkerState } from '../../../packages/vitest/src/runtime/utils'\n\nfunction expectType<T>(obj: T) {\n  return obj\n}\n\ndescribe('testing vi utils', () => {\n  test('global scope has variable', () => {\n    const IntersectionObserverMock = vi.fn()\n    vi.stubGlobal('IntersectionObserver', IntersectionObserverMock)\n    expect(globalThis.IntersectionObserver).toBe(IntersectionObserverMock)\n    expect(window.IntersectionObserver).toBe(IntersectionObserverMock)\n    expect(IntersectionObserver).toBe(IntersectionObserverMock)\n  })\n\n  test('resetting modules', async () => {\n    const mod1 = await import('../src/env')\n    vi.resetModules()\n    const mod2 = await import('../src/env')\n    const mod3 = await import('../src/env')\n    expect(mod1).not.toBe(mod2)\n    expect(mod2).toBe(mod3)\n  })\n\n  test('resetting modules doesn\\'t reset vitest', async () => {\n    const v1 = await import('vitest')\n    vi.resetModules()\n    const v2 = await import('vitest')\n    expect(v1).toBe(v2)\n  })\n\n  test('vi mocked', () => {\n    expectType<MockedObject<{ bar: () => boolean }>>({\n      bar: vi.fn(() => true),\n    })\n    expectType<MockedFunction<() => boolean>>(vi.fn(() => true))\n    expectType<MockedFunction<() => boolean>>(vi.fn())\n\n    expectType<MockedFunction<() => boolean>>(vi.fn<() => boolean>(() => true))\n    expectType<Mock<() => boolean>>(vi.fn<() => boolean>(() => true))\n    expectType<() => boolean>(vi.fn(() => true))\n\n    expectType<(v: number) => boolean>(vi.fn())\n  })\n\n  test('vi partial mocked', () => {\n    interface FooBar {\n      foo: () => void\n      bar: () => boolean\n      baz: string\n    }\n\n    const mockFnFactory = vi.fn<() => FooBar>()\n\n    vi.mocked(mockFnFactory, { partial: true }).mockReturnValue({\n      foo: vi.fn(),\n    })\n\n    vi.mocked(mockFnFactory, { partial: true, deep: false }).mockReturnValue({\n      bar: vi.fn<FooBar['bar']>(),\n    })\n\n    vi.mocked(mockFnFactory, { partial: true, deep: true }).mockReturnValue({\n      baz: 'baz',\n    })\n\n    if (0) {\n      const mockFactory = (): FooBar => ({} as FooBar)\n\n      vi.mocked(mockFactory, { partial: true }).mockReturnValue({\n        foo: vi.fn(),\n      })\n\n      vi.mocked(mockFactory, { partial: true, deep: false }).mockReturnValue({\n        bar: vi.fn<FooBar['bar']>(),\n      })\n\n      vi.mocked(mockFactory, { partial: true, deep: true }).mockReturnValue({\n        baz: 'baz',\n      })\n\n      const mockFactoryAsync = async (): Promise<FooBar> => ({} as FooBar)\n\n      vi.mocked(mockFactoryAsync, { partial: true }).mockResolvedValue({\n        foo: vi.fn(),\n      })\n\n      vi.mocked(mockFactoryAsync, { partial: true, deep: false }).mockResolvedValue({\n        bar: vi.fn<FooBar['bar']>(),\n      })\n\n      vi.mocked(mockFactoryAsync, { partial: true, deep: true }).mockResolvedValue({\n        baz: 'baz',\n      })\n    }\n\n    function fetchSomething(): Promise<Response> {\n      return fetch('https://vitest.dev/')\n    };\n    if (0) {\n      // type check only\n      vi.mocked(fetchSomething).mockResolvedValue(new Response(null))\n      vi.mocked(fetchSomething, { partial: true }).mockResolvedValue({ ok: false })\n    }\n\n    // #8152\n    if (0) {\n      interface NestedObject {\n        level1: {\n          level2: {\n            value: string\n            count: number\n          }\n          name: string\n        }\n        items: string[]\n      }\n\n      const mockNestedFactory = vi.fn<() => NestedObject>()\n\n      vi.mocked(mockNestedFactory, { partial: true, deep: true }).mockReturnValue({\n        level1: { level2: {} },\n      })\n      vi.mocked(mockNestedFactory, { partial: true, deep: true }).mockReturnValue({\n        level1: {},\n      })\n      vi.mocked(mockNestedFactory, { partial: true, deep: true }).mockReturnValue({})\n      vi.mocked(mockNestedFactory, { partial: true, deep: true }).mockReturnValue({\n        items: ['a', 'b'],\n      })\n\n      const mockNestedAsyncFactory = vi.fn<() => Promise<NestedObject>>()\n\n      vi.mocked(mockNestedAsyncFactory, { partial: true, deep: true }).mockResolvedValue({\n        level1: { level2: {} },\n      })\n      vi.mocked(mockNestedAsyncFactory, { partial: true, deep: true }).mockResolvedValue({})\n    }\n  })\n\n  test('vi.mocked with classes', () => {\n    class Foo {\n      constructor(public readonly bar: string) {}\n\n      public getBar(): string {\n        return this.bar\n      }\n\n      static getBaz(): string {\n        return 'baz'\n      }\n    }\n    class FooMock implements Mocked<Foo> {\n      readonly barMock: Mock<() => string> = vi.fn()\n\n      public get bar(): string {\n        return this.barMock()\n      }\n\n      public getBar: Mock<() => string> = vi\n        .fn()\n        .mockImplementation(() => this.barMock())\n    }\n\n    // type check only\n    if (0) {\n      vi.mocked(Foo).mockImplementation(FooMock)\n      vi.mocked(Foo).mockImplementation(Foo)\n      vi.mocked(Foo).getBaz.mockImplementation(() => 'baz')\n      vi.mocked(Foo, { partial: true }).getBaz.mockImplementation(() => 'baz')\n    }\n  })\n\n  test('vi.fn and Mock type', () => {\n    // use case from https://github.com/vitest-dev/vitest/issues/4723#issuecomment-1851034249\n\n    // hypothetical library to be tested\n    type SomeFn = (v: string) => number\n    function acceptSomeFn(f: SomeFn) {\n      f('hi')\n    }\n\n    // SETUP\n    // no args are allowed even though it's not type safe\n    const someFn1: Mock<SomeFn> = vi.fn()\n\n    // argument types are inferred\n    const someFn2: Mock<SomeFn> = vi.fn((v) => {\n      expectTypeOf(v).toEqualTypeOf<string>()\n      return 0\n    })\n\n    // arguments are not necessary\n    const someFn3: Mock<SomeFn> = vi.fn(() => 0)\n\n    // @ts-expect-error wrong return type will be caught\n    const someFn4: Mock<SomeFn> = vi.fn(() => '0')\n\n    // TEST\n    acceptSomeFn(someFn1)\n    expect(someFn1).toBeCalledWith('hi')\n    expect(someFn2).not.toBeCalled()\n    expect(someFn3).not.toBeCalled()\n    expect(someFn4).not.toBeCalled()\n  })\n\n  test(`vi.spyOn for function overload types`, () => {\n    class MyElement {\n      scrollTo(options?: ScrollToOptions): void\n      scrollTo(x: number, y: number): void\n      scrollTo() {}\n    }\n\n    // verify `spyOn` is assignable to `MockInstance` with overload\n    const spy: MockInstance<MyElement['scrollTo']> = vi.spyOn(\n      MyElement.prototype,\n      'scrollTo',\n    )\n\n    // however `Parameters` only picks up the last overload\n    // due to typescript limitation\n    expectTypeOf(spy.mock.calls).toEqualTypeOf<\n      [x: number, y: number][]\n    >()\n  })\n\n  test(`mock.contexts types`, () => {\n    class TestClass {\n      f(this: TestClass) {}\n      g() {}\n    }\n\n    const fSpy = vi.spyOn(TestClass.prototype, 'f')\n    const gSpy = vi.spyOn(TestClass.prototype, 'g')\n\n    // contexts inferred only when `this` is explicitly annotated\n    expectTypeOf(fSpy.mock.contexts).toEqualTypeOf<TestClass[]>()\n    expectTypeOf(gSpy.mock.contexts).toEqualTypeOf<unknown[]>()\n  })\n\n  test('mockImplementation types', async () => {\n    // overload\n    const fs = { readFileSync() {} } as any as typeof import('node:fs')\n    vi.spyOn(fs, 'readFileSync').mockImplementation(() => 'str')\n    vi.spyOn(fs, 'readFileSync').mockImplementation(() => Buffer.from('buf'))\n    vi.fn(fs.readFileSync).mockImplementation(() => 'str')\n    vi.fn(fs.readFileSync).mockImplementation(() => Buffer.from('buf'))\n\n    // union\n    interface Handler {\n      (v: number): number\n      other: (v: number) => number\n    }\n    vi.fn<Handler>().mockImplementation(v => v + 1)\n  })\n\n  test('can change config', () => {\n    const state = getWorkerState()\n    expect(state.config.hookTimeout).toBe(10000)\n    expect(state.config.clearMocks).toBe(false)\n    vi.setConfig({ hookTimeout: 6000, clearMocks: true })\n    expect(state.config.hookTimeout).toBe(6000)\n    expect(state.config.clearMocks).toBe(true)\n    vi.resetConfig()\n    expect(state.config.hookTimeout).toBe(10000)\n    expect(state.config.clearMocks).toBe(false)\n  })\n\n  test('loads unloaded module', async () => {\n    let mod: any\n    import('../src/timeout').then(m => mod = m)\n\n    expect(mod).toBeUndefined()\n\n    await vi.dynamicImportSettled()\n\n    expect(mod).toBeDefined()\n    expect(mod.timeout).toBe(100)\n  })\n\n  test('mockObject', () => {\n    const original = {\n      simple: () => 'value',\n      nested: {\n        method: () => 'real',\n      },\n      prop: 'foo',\n    }\n\n    const mocked = vi.mockObject(original)\n    expect(mocked.simple()).toBe(undefined)\n    expect(mocked.nested.method()).toBe(undefined)\n    expect(mocked.prop).toBe('foo')\n    mocked.simple.mockReturnValue('mocked')\n    mocked.nested.method.mockReturnValue('mocked nested')\n    expect(mocked.simple()).toBe('mocked')\n    expect(mocked.nested.method()).toBe('mocked nested')\n\n    const spied = vi.mockObject(original, { spy: true })\n    expect(spied.simple()).toBe('value')\n    expect(spied.simple).toHaveBeenCalled()\n    expect(spied.simple.mock.results).toEqual([{ type: 'return', value: 'value' }])\n    spied.simple.mockReturnValue('still mocked')\n    expect(spied.simple()).toBe('still mocked')\n\n    class OriginalClass {\n      constructor() {\n        throw new Error('should be mocked!')\n      }\n\n      someFn() {\n        return 'value'\n      }\n    }\n    const MockedClass = vi.mockObject(OriginalClass)\n    const mockedInstance = new MockedClass()\n    expect(MockedClass).toHaveBeenCalled()\n    vi.mocked(mockedInstance).someFn.mockImplementation(() => 'mocked')\n    expect(mockedInstance.someFn()).toBe('mocked')\n  })\n})\n"
  },
  {
    "path": "test/core/test/vi.test-d.ts",
    "content": "import { expectTypeOf, test, vi } from 'vitest'\n\ntest('vi.waitUntil correctly resolves return type', () => {\n  expectTypeOf(vi.waitUntil(() => 'string')).resolves.toEqualTypeOf<string>()\n  expectTypeOf(vi.waitUntil(() => 1)).resolves.toEqualTypeOf<number>()\n\n  expectTypeOf(vi.waitUntil(() => false as const)).resolves.toEqualTypeOf<never>()\n  expectTypeOf(vi.waitUntil(() => '' as const)).resolves.toEqualTypeOf<never>()\n  expectTypeOf(vi.waitUntil(() => 0 as const)).resolves.toEqualTypeOf<never>()\n\n  expectTypeOf(vi.waitUntil(() => '' as '' | number)).resolves.toEqualTypeOf<number>()\n  expectTypeOf(vi.waitUntil(() => null as null | number)).resolves.toEqualTypeOf<number>()\n  expectTypeOf(vi.waitUntil(() => undefined as undefined | number)).resolves.toEqualTypeOf<number>()\n  expectTypeOf(vi.waitUntil(() => false as false | number)).resolves.toEqualTypeOf<number>()\n  expectTypeOf(vi.waitUntil(() => 0 as 0 | string)).resolves.toEqualTypeOf<string>()\n})\n"
  },
  {
    "path": "test/core/test/wait.test.ts",
    "content": "import { describe, expect, test, vi } from 'vitest'\n\ndescribe('waitFor', () => {\n  describe('options', () => {\n    test('timeout', async () => {\n      await expect(async () => {\n        await vi.waitFor(() => {\n          return new Promise((resolve) => {\n            setTimeout(() => {\n              resolve(true)\n            }, 1000)\n          })\n        }, 50)\n      }).rejects.toThrow('Timed out in waitFor!')\n    })\n\n    test('interval', async () => {\n      const callback = vi.fn(() => {\n        throw new Error('interval error')\n      })\n\n      await expect(\n        vi.waitFor(callback, {\n          timeout: 60,\n          interval: 30,\n        }),\n      ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: interval error]`)\n\n      expect(callback).toHaveBeenCalledTimes(2)\n    })\n  })\n\n  test('basic', async () => {\n    let throwError = false\n    await vi.waitFor(() => {\n      if (!throwError) {\n        throwError = true\n        throw new Error('basic error')\n      }\n    })\n    expect(throwError).toBe(true)\n  })\n\n  test('async function', async () => {\n    let finished = false\n    setTimeout(() => {\n      finished = true\n    }, 50)\n    await vi.waitFor(async () => {\n      if (finished) {\n        return Promise.resolve(true)\n      }\n      else {\n        return Promise.reject(new Error('async function error'))\n      }\n    })\n  })\n\n  test('stacktrace correctly', async () => {\n    const check = () => {\n      throw new Error('Fail.')\n    }\n    try {\n      await vi.waitFor(check, 100)\n    }\n    catch (error) {\n      expect((error as Error).message).toMatchInlineSnapshot('\"Fail.\"')\n      expect.soft((error as Error).stack).toMatch(/at check/)\n    }\n  })\n\n  test('stacktrace point to waitFor', async () => {\n    const check = async () => {\n      return new Promise((resolve) => {\n        setTimeout(resolve, 60)\n      })\n    }\n    try {\n      await vi.waitFor(check, 50)\n    }\n    catch (error) {\n      expect(error).toMatchInlineSnapshot('[Error: Timed out in waitFor!]')\n      expect((error as Error).stack?.split('\\n')[1]).toMatch(/waitFor\\s*\\(.*/)\n    }\n  })\n\n  test('fakeTimer works', async () => {\n    setTimeout(() => {\n      vi.advanceTimersByTime(200)\n    }, 50)\n\n    vi.useFakeTimers()\n\n    await vi.waitFor(() => {\n      return new Promise<void>((resolve) => {\n        setTimeout(() => {\n          resolve()\n        }, 150)\n      })\n    }, 200)\n\n    vi.useRealTimers()\n  })\n\n  test('callback stops running after timeout', async () => {\n    let timedOut = false\n    let callbackRanAfterTimeout = false\n    try {\n      await vi.waitFor(() => {\n        callbackRanAfterTimeout = timedOut\n        throw new Error('waitFor error')\n      }, {\n        interval: 10,\n        timeout: 50,\n      })\n    }\n    catch {\n      timedOut = true\n    }\n    expect(timedOut).toBe(true)\n    expect(callbackRanAfterTimeout).toBe(false)\n  })\n})\n\ndescribe('waitUntil', () => {\n  describe('options', () => {\n    test('timeout', async () => {\n      await expect(async () => {\n        await vi.waitUntil(() => {\n          return new Promise((resolve) => {\n            setTimeout(() => {\n              resolve(true)\n            }, 1000)\n          })\n        }, 50)\n      }).rejects.toThrow('Timed out in waitUntil!')\n    })\n\n    test('interval', async () => {\n      const callback = vi.fn(() => {\n        return false\n      })\n\n      await expect(\n        vi.waitUntil(callback, {\n          timeout: 500,\n          interval: 400,\n        }),\n      ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: Timed out in waitUntil!]`)\n\n      expect(callback).toHaveBeenCalledTimes(2)\n    })\n  })\n\n  test('basic', async () => {\n    let result = true\n    await vi.waitUntil(() => {\n      result = !result\n      return result\n    })\n    expect(result).toBe(true)\n  })\n\n  test('async function', async () => {\n    let finished = false\n    setTimeout(() => {\n      finished = true\n    }, 50)\n    await vi.waitUntil(async () => {\n      return Promise.resolve(finished)\n    })\n  })\n\n  test('stacktrace correctly when callback throw error', async () => {\n    const check = () => {\n      throw new Error('Fail.')\n    }\n    try {\n      await vi.waitUntil(check, 20)\n    }\n    catch (error) {\n      expect((error as Error).message).toMatchInlineSnapshot('\"Fail.\"')\n      expect.soft((error as Error).stack).toMatch(/at check/)\n    }\n  })\n\n  test('fakeTimer works', async () => {\n    setTimeout(() => {\n      vi.advanceTimersByTime(200)\n    }, 50)\n\n    vi.useFakeTimers()\n\n    await vi.waitUntil(() => {\n      return new Promise<boolean>((resolve) => {\n        setTimeout(() => {\n          resolve(true)\n        }, 150)\n      })\n    }, 200)\n\n    vi.useRealTimers()\n  })\n\n  test('callback stops running after timeout', async () => {\n    let timedOut = false\n    let callbackRanAfterTimeout = false\n    try {\n      await vi.waitUntil(() => {\n        callbackRanAfterTimeout = timedOut\n        return false\n      }, {\n        interval: 10,\n        timeout: 50,\n      })\n    }\n    catch {\n      timedOut = true\n    }\n    expect(timedOut).toBe(true)\n    expect(callbackRanAfterTimeout).toBe(false)\n  })\n})\n"
  },
  {
    "path": "test/core/test/wasm.test.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { expect, test, vi } from 'vitest'\n\n// @ts-expect-error wasm is not typed\nimport { add } from '../src/wasm/add.wasm'\n\nconst wasmFileBuffer = readFileSync(resolve(import.meta.dirname, '../src/wasm/add.wasm'))\n\ntest('supports native wasm imports', () => {\n  expect(add(1, 2)).toBe(3)\n\n  // because arguments are i32 (signed), fractional part is truncated\n  expect(add(0.99, 1.01)).toBe(1)\n\n  // because return value is i32 (signed), (2^31 - 1) + 1 overflows and becomes -2^31\n  expect(add(2 ** 31 - 1, 1)).toBe(-(2 ** 31))\n\n  // invalid or missing arguments are treated as 0\n  expect(add('hello', 'world')).toBe(0)\n  expect(add()).toBe(0)\n  expect(add(null)).toBe(0)\n  expect(add({}, [])).toBe(0)\n\n  // redundant arguments are silently ignored\n  expect(add(1, 2, 3)).toBe(3)\n})\n\ntest('supports dynamic wasm imports', async () => {\n  // @ts-expect-error wasm is not typed\n  const { add: dynamicAdd } = await import('../src/wasm/add.wasm')\n  expect(dynamicAdd(1, 2)).toBe(3)\n})\n\ntest('supports imports from \"data:application/wasm\" URI with base64 encoding', async () => {\n  const importedWasmModule = await import(\n    `data:application/wasm;base64,${wasmFileBuffer.toString('base64')}`,\n  )\n  expect(importedWasmModule.add(0, 42)).toBe(42)\n})\n\n// TODO: error message is different on vm\nconst isVm = process.execArgv.includes('--experimental-vm-modules')\n\ntest('imports from \"data:application/wasm\" URI without explicit encoding fail', async () => {\n  const error = await getError(() => import(`data:application/wasm,${wasmFileBuffer.toString('base64')}`))\n  if (isVm) {\n    expect(error).toMatchInlineSnapshot(`[Error: Missing data URI encoding]`)\n  }\n  else {\n    expect(error).toMatchObject({ name: 'CompileError' })\n  }\n})\n\ntest('imports from \"data:application/wasm\" URI with invalid encoding fail', async () => {\n  // @ts-expect-error import is not typed\n  const error = await getError(() => import('data:application/wasm;charset=utf-8,oops'))\n  if (isVm) {\n    expect(error).toMatchInlineSnapshot(`[Error: Invalid data URI encoding: charset=utf-8]`)\n  }\n  else {\n    expect(error).toMatchObject({ name: 'CompileError' })\n  }\n})\n\nasync function getError(f: () => unknown) {\n  try {\n    await f()\n  }\n  catch (e) {\n    return e\n  }\n  expect.unreachable()\n}\n\ntest('supports wasm/js cyclic import (old wasm-bindgen output)', async () => {\n  globalThis.alert = vi.fn()\n\n  // @ts-expect-error not typed\n  const { greet } = await import('../src/wasm/wasm-bindgen/index.js')\n  greet('World')\n\n  expect(globalThis.alert).toHaveBeenCalledWith('Hello, World!')\n})\n\ntest('supports wasm-bindgen', async () => {\n  globalThis.alert = vi.fn()\n\n  const { greet } = await import('../src/wasm/wasm-bindgen-no-cyclic/index.js')\n  greet('No Cyclic')\n\n  expect(globalThis.alert).toHaveBeenCalledWith('Hello, No Cyclic!')\n})\n"
  },
  {
    "path": "test/core/test/web-worker-jsdom.test.ts",
    "content": "// @vitest-environment jsdom\n\nimport { expect, it } from 'vitest'\n\nimport GlobalsWorker from '../src/web-worker/worker-globals?worker'\nimport '@vitest/web-worker'\n\nit('worker with invalid url throws an error', async () => {\n  const url = import.meta.url\n  const worker = new Worker(new URL('../src/web-worker/workerInvalid-path.ts', url))\n  const event = await new Promise<ErrorEvent>((resolve) => {\n    worker.onerror = (e) => {\n      resolve(e)\n    }\n  })\n  expect(event).toBeInstanceOf(ErrorEvent)\n  // Error is in different context when running in VM. This is consistent with jest.\n  if (!import.meta.env.VITEST_VM_POOL) {\n    expect(event.error).toBeInstanceOf(Error)\n  }\n  expect(event.error.message).toContain('Cannot find module')\n})\n\nit('throws an error on invalid path', async () => {\n  expect(SharedWorker).toBeDefined()\n  const worker = new SharedWorker('./web-worker/some-invalid-path')\n  const event = await new Promise<ErrorEvent>((resolve) => {\n    worker.onerror = (e) => {\n      resolve(e)\n    }\n  })\n  expect(event).toBeInstanceOf(ErrorEvent)\n  // Error is in different context when running in VM. This is consistent with jest.\n  if (!import.meta.env.VITEST_VM_POOL) {\n    expect(event.error).toBeInstanceOf(Error)\n  }\n  expect(event.error.message).toContain('Cannot find module')\n})\n\nit('returns globals on self correctly', async () => {\n  const worker = new GlobalsWorker()\n  await new Promise<void>((resolve, reject) => {\n    worker.onmessage = (e) => {\n      try {\n        expect(e.data).toEqual({\n          crypto: !!globalThis.crypto,\n          location: !!globalThis.location,\n          caches: !!globalThis.caches,\n          origin: 'http://localhost:3000',\n        })\n        resolve()\n      }\n      catch (err) {\n        reject(err)\n      }\n    }\n    worker.onerror = reject\n    worker.postMessage(null)\n  })\n})\n"
  },
  {
    "path": "test/core/test/web-worker-mock.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { workerDep } from '../src/web-worker/mock/worker-dep'\nimport '@vitest/web-worker'\n\nvi.mock(import('../src/web-worker/mock/worker-dep'), () => ({ workerDep: () => 'mocked' }))\n\ntest('mock', async () => {\n  expect(workerDep()).toMatchInlineSnapshot(`\"mocked\"`)\n  const worker = new Worker(new URL('../src/web-worker/mock/worker', import.meta.url))\n  const data = await new Promise((resolve) => {\n    worker.addEventListener('message', (e) => {\n      resolve(e.data)\n    })\n  })\n  expect(data).toMatchInlineSnapshot(`\"mocked\"`)\n})\n"
  },
  {
    "path": "test/core/test/web-worker-node.test.ts",
    "content": "// @vitest-environment node\n\nimport type { defineWebWorkers } from '@vitest/web-worker/pure'\n\nimport { version } from 'node:process'\n\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\nimport MyEventListenerWorker from '../src/web-worker/eventListenerWorker?worker'\nimport MyObjectWorker from '../src/web-worker/objectWorker?worker'\nimport MySelfWorker from '../src/web-worker/selfWorker?worker'\nimport MySharedWorker from '../src/web-worker/sharedWorker?sharedworker'\nimport GlobalsWorker from '../src/web-worker/worker-globals?worker'\nimport MyWorker from '../src/web-worker/worker?worker'\nimport '@vitest/web-worker'\n\nconst major = Number(version.split('.')[0].slice(1))\n\ndescribe.runIf(major >= 17)('when node supports structuredClone', () => {\n  it('uses native structure clone', () => {\n    expect.assertions(4)\n\n    expect(structuredClone).toBeDefined()\n\n    const worker = new MyObjectWorker()\n    const buffer = new ArrayBuffer(1)\n    const obj = { hello: 'world', buffer }\n    worker.postMessage(obj, [buffer])\n\n    return new Promise<void>((resolve, reject) => {\n      worker.onmessage = (e) => {\n        try {\n          expect(e).toBeInstanceOf(MessageEvent)\n          expect(e.data, 'doesn\\'t keep reference').not.toBe(obj)\n          expect(e.data, 'shape is equal').toEqual(obj)\n          resolve()\n        }\n        catch (err) {\n          reject(err)\n        }\n        finally {\n          worker.terminate()\n        }\n      }\n    })\n  })\n\n  it('throws error, if passing down unserializable data', () => {\n    expect.assertions(4)\n\n    expect(structuredClone).toBeDefined()\n\n    const worker = new MyObjectWorker()\n    const obj = { hello: 'world', name() {} }\n    worker.postMessage(obj)\n\n    return new Promise<void>((resolve, reject) => {\n      worker.onmessageerror = (e) => {\n        try {\n          expect(e.type).toBe('messageerror')\n          expect(e).toBeInstanceOf(MessageEvent)\n          expect(e.data.message).toContain(\n            'could not be cloned.',\n          )\n          resolve()\n        }\n        catch (err) {\n          reject(err)\n        }\n      }\n    })\n  })\n})\n\ndescribe('when passing down custom clone', () => {\n  const { warn } = console\n\n  beforeEach(() => {\n    console.warn = warn\n    process.env.VITEST_WEB_WORKER_CLONE = undefined\n  })\n\n  it('uses ponyfill clone', () => {\n    expect.assertions(4)\n\n    console.warn = vi.fn()\n    process.env.VITEST_WEB_WORKER_CLONE = 'ponyfill'\n\n    const worker = new MyObjectWorker()\n    const buffer = new ArrayBuffer(1)\n    const obj = { hello: 'world' }\n    worker.postMessage(obj, [buffer])\n\n    return new Promise<void>((resolve, reject) => {\n      worker.onmessageerror = (e) => {\n        reject(e.data)\n      }\n      worker.onmessage = (e) => {\n        try {\n          expect(e).toBeInstanceOf(MessageEvent)\n          expect(e.data, 'doesn\\'t keep reference').not.toBe(obj)\n          expect(e.data, 'shape is not equal, don\\'t transfer buffer').toEqual({ hello: 'world' })\n          expect(console.warn).toBeCalledWith(expect.stringContaining('[@vitest/web-worker] `structuredClone` is not supported in this'))\n          resolve()\n        }\n        catch (err) {\n          reject(err)\n        }\n        finally {\n          worker.terminate()\n        }\n      }\n    })\n  })\n\n  it('doesn\\'t clone, if asked to', () => {\n    expect.assertions(3)\n\n    console.warn = vi.fn()\n    process.env.VITEST_WEB_WORKER_CLONE = 'none'\n\n    const worker = new MyObjectWorker()\n    const buffer = new ArrayBuffer(1)\n    const obj = { hello: 'world', buffer }\n    worker.postMessage(obj, [buffer])\n\n    return new Promise<void>((resolve, reject) => {\n      worker.onmessageerror = (e) => {\n        reject(e.data)\n      }\n      worker.onmessage = (e) => {\n        try {\n          expect(e).toBeInstanceOf(MessageEvent)\n          expect(e.data, 'keeps reference').toBe(obj)\n          expect(console.warn).not.toHaveBeenCalled()\n          resolve()\n        }\n        catch (err) {\n          reject(err)\n        }\n        finally {\n          worker.terminate()\n        }\n      }\n    })\n  })\n})\n\nfunction sleep(time: number) {\n  return new Promise(resolve => setTimeout(resolve, time))\n}\n\nfunction testWorker(worker: Worker) {\n  return new Promise<void>((resolve) => {\n    worker.postMessage('hello')\n    worker.onmessage = (e) => {\n      expect(e.data).toBe('hello world')\n\n      resolve()\n    }\n  })\n}\n\nfunction testSelfWorker(worker: Worker) {\n  return new Promise<boolean>((resolve) => {\n    worker.onmessage = (e) => {\n      resolve(e.data)\n    }\n  })\n}\n\nit('worker exists', async () => {\n  expect(Worker).toBeDefined()\n})\n\nit('simple worker', async () => {\n  expect.assertions(1)\n\n  await testWorker(new MyWorker())\n})\n\nit('event listener worker', async () => {\n  expect.assertions(1)\n\n  await testWorker(new MyEventListenerWorker())\n})\n\nit('can test workers several times', async () => {\n  expect.assertions(1)\n\n  await testWorker(new MyWorker())\n})\n\nit('worker with url', async () => {\n  expect.assertions(1)\n  const url = import.meta.url\n\n  await testWorker(new Worker(new URL('../src/web-worker/worker.ts', url)))\n})\n\nit('self injected into worker and its deps should be equal', async () => {\n  expect.assertions(4)\n  expect(await testSelfWorker(new MySelfWorker())).toBeTruthy()\n  // wait for clear worker mod cache\n  await sleep(0)\n  expect(await testSelfWorker(new MySelfWorker())).toBeTruthy()\n\n  await sleep(0)\n\n  expect(await testSelfWorker(new Worker(new URL('../src/web-worker/selfWorker.ts', import.meta.url)))).toBeTruthy()\n  // wait for clear worker mod cache\n  await sleep(0)\n  expect(await testSelfWorker(new Worker(new URL('../src/web-worker/selfWorker.ts', import.meta.url)))).toBeTruthy()\n})\n\nconst cloneTypes = [\n  'native',\n  'ponyfill',\n  'none',\n] satisfies Array<NonNullable<Parameters<typeof defineWebWorkers>[0]>['clone']>\ncloneTypes.forEach((clone) => {\n  describe(`defineWebWorkers with clone=${clone}`, () => {\n    beforeEach(() => {\n      process.env.VITEST_WEB_WORKER_CLONE = clone\n    })\n    afterEach(() => {\n      process.env.VITEST_WEB_WORKER_CLONE = undefined\n    })\n\n    it('transfers MessagePort objects to worker as event.ports', async () => {\n      expect.assertions(1)\n\n      const worker = new MyWorker()\n      const channel = new MessageChannel()\n      const promise = new Promise<string>((resolve, reject) => {\n        channel.port1.onmessage = e => resolve(e.data as string)\n        channel.port1.onmessageerror = reject\n      })\n      worker.postMessage('hello', [channel.port2])\n      await expect(promise).resolves.toBe('hello world via port')\n    })\n  })\n})\n\nit('throws syntax error if no arguments are provided', () => {\n  const worker = new MyWorker()\n\n  // @ts-expect-error requires at least one argument\n  expect(() => worker.postMessage()).toThrow(SyntaxError)\n  expect(() => worker.postMessage(undefined)).not.toThrow()\n  expect(() => worker.postMessage(null)).not.toThrow()\n})\n\nfunction sendEventMessage(worker: SharedWorker, msg: any) {\n  return new Promise<string>((resolve, reject) => {\n    const timeout = setTimeout(() => {\n      reject(new Error(`Failed to send the message ${msg} to the SharedWorker.`))\n    }, 5_000)\n    worker.port.addEventListener('message', function onmessage(e) {\n      worker.port.removeEventListener('message', onmessage)\n      clearTimeout(timeout)\n      resolve(e.data as string)\n    })\n    worker.port.postMessage(msg)\n  })\n}\n\nfunction sendOnMessage(worker: SharedWorker, msg: any) {\n  return new Promise<string>((resolve, reject) => {\n    const timeout = setTimeout(() => {\n      reject(new Error(`Failed to send the message ${msg} to the SharedWorker.`))\n    }, 5_000)\n    worker.port.onmessage = function onmessage(e) {\n      worker.port.onmessage = null\n      clearTimeout(timeout)\n      resolve(e.data as string)\n    }\n    worker.port.postMessage(msg)\n  })\n}\n\nit('vite shared worker works', async () => {\n  expect(MySharedWorker).toBeDefined()\n  expect(SharedWorker).toBeDefined()\n  const worker = new MySharedWorker()\n  expect(worker).toBeInstanceOf(SharedWorker)\n\n  await expect(sendEventMessage(worker, 'event')).resolves.toBe('event')\n  await expect(sendOnMessage(worker, 'event')).resolves.toBe('event')\n})\n\nit('shared worker with path works', async () => {\n  expect(SharedWorker).toBeDefined()\n  const worker = new SharedWorker(new URL('../src/web-worker/sharedWorker.ts', import.meta.url))\n  expect(worker).toBeTruthy()\n\n  await expect(sendEventMessage(worker, 'event')).resolves.toBe('event')\n  await expect(sendOnMessage(worker, 'event')).resolves.toBe('event')\n})\n\nit('doesn\\'t trigger events, if closed', async () => {\n  const worker = new MySharedWorker()\n  worker.port.close()\n  await new Promise((resolve) => {\n    worker.port.addEventListener('message', () => {\n      expect.unreachable('should not trigger message')\n    })\n    worker.port.postMessage('event')\n    setTimeout(resolve, 100)\n  })\n})\n\nit('returns globals on self correctly', async () => {\n  const worker = new GlobalsWorker()\n  await new Promise<void>((resolve, reject) => {\n    worker.onmessage = (e) => {\n      try {\n        expect(e.data).toEqual({\n          crypto: !!globalThis.crypto,\n          location: !!globalThis.location,\n          caches: !!globalThis.caches,\n          origin: 'http://localhost:3000',\n        })\n        resolve()\n      }\n      catch (err) {\n        reject(err)\n      }\n    }\n    worker.onerror = reject\n    worker.postMessage(null)\n  })\n})\n"
  },
  {
    "path": "test/core/test/write-file-dynamic-import.test.ts",
    "content": "import type { ViteUserConfig } from 'vitest/config'\nimport { unlinkSync, writeFileSync } from 'node:fs'\nimport { pathToFileURL } from 'node:url'\nimport { expect, it, onTestFinished } from 'vitest'\n\nit('write file and import created file it should return created content.', async () => {\n  // @ts-expect-error -- internal\n  const config: NonNullable<ViteUserConfig['test']> = globalThis.__vitest_worker__.config\n\n  // This test can run parallel on multiple projects - namespace the file to avoid conflicts\n  const filename = `${config.name}-bar.js`\n\n  onTestFinished(() => unlinkSync(filename))\n\n  writeFileSync(filename, 'export default 123')\n\n  const mod = await import(pathToFileURL(filename).href)\n\n  expect(mod.default).toBe(123)\n})\n"
  },
  {
    "path": "test/core/tsconfig.typecheck.json",
    "content": "{\n  \"extends\": \"../../tsconfig.build.json\",\n  \"include\": [\"./**/*.test-d.ts\"]\n}\n"
  },
  {
    "path": "test/core/types/env.d.ts",
    "content": "interface ImportMeta {\n  readonly env: ImportMetaEnv\n}\n\ninterface ImportMetaEnv {\n  [key: string]: string | boolean | undefined\n  BASE_URL: string\n  MODE: string\n  DEV: boolean\n  PROD: boolean\n  SSR: boolean\n}\n"
  },
  {
    "path": "test/core/types/vite.d.ts",
    "content": "interface ImportMeta {\n  readonly env: ImportMetaEnv\n}\n\ninterface ImportMetaEnv {\n  [key: string]: string | boolean | undefined\n  BASE_URL: string\n  MODE: string\n  DEV: boolean\n  PROD: boolean\n  SSR: boolean\n}\n\ndeclare module '*?worker' {\n  const workerConstructor: {\n    new (): Worker\n  }\n  export default workerConstructor\n}\n"
  },
  {
    "path": "test/core/vite.config.ts",
    "content": "import type { LabelColor } from 'vitest'\nimport type { Pool } from 'vitest/node'\nimport { basename, dirname, join, resolve } from 'pathe'\nimport { defaultExclude, defineConfig } from 'vitest/config'\nimport { rolldownVersion } from 'vitest/node'\n\nexport default defineConfig({\n  // tests should not fail when base is set\n  base: '/some-url/',\n  plugins: [\n    {\n      name: 'example',\n      resolveId(source) {\n        if (source === 'virtual-module' || source === 'virtual-module-direct' || source === 'virtual-module-indirect') {\n          return source\n        }\n      },\n      load(id) {\n        if (id === 'virtual-module') {\n          return `\n            export const value = 'original';\n          `\n        }\n        if (id === 'virtual-module-direct') {\n          return `\n            export const value = 'original-direct';\n          `\n        }\n        if (id === 'virtual-module-indirect') {\n          return `\n            export const value = 'original-indirect';\n          `\n        }\n      },\n    },\n    // Use babel plugin since Oxc (Vite 8) doens't support ecma decorators out of the box\n    // https://github.com/oxc-project/oxc/issues/9170#issuecomment-4072166491\n    !!rolldownVersion\n    && (import('@rolldown/plugin-babel').then(({ default: babel }) =>\n      babel({\n        presets: [\n          {\n            preset: ({\n              plugins: [['@babel/plugin-proposal-decorators', { version: '2023-11' }]],\n            }),\n            rolldown: {\n              filter: {\n                id: ['**/esnext-decorator.test.ts'],\n              },\n            },\n          },\n        ],\n      }),\n    ) as any),\n  ],\n  define: {\n    'process': {},\n    'global': {},\n    'import.meta.env.TEST_NAME': '\"hello world\"',\n    'process.env.HELLO_PROCESS': '\"hello process\"',\n    // can reassign\n    '__DEFINE__': '\"defined\"',\n    '__JSON__': JSON.stringify({ hello: 'world' }),\n    // edge cases\n    // should not be available for reassigning as __MODE__ = 'test2'\n    // but can reassign with process.env.MODE = 'test2'\n    '__MODE__': 'process.env.MODE',\n    'SOME.VARIABLE': '\"variable\"',\n    'SOME.SOME.VARIABLE': '\"nested variable\"',\n    '__UNDEFINED__': undefined,\n    '__NULL__': null,\n    '__ZERO__': 0,\n    '__FALSE__': false,\n    'import.meta.vitest': false,\n  },\n  resolve: {\n    alias: [\n      { find: /^#/, replacement: resolve(import.meta.dirname, 'src') },\n      { find: /^custom-lib$/, replacement: resolve(import.meta.dirname, 'projects', 'custom-lib') },\n      { find: /^inline-lib$/, replacement: resolve(import.meta.dirname, 'projects', 'inline-lib') },\n    ],\n    noExternal: [/projects\\/vite-external/],\n  },\n  environments: {\n    ssr: {\n      resolve: {\n        noExternal: [/projects\\/vite-environment-external/],\n      },\n    },\n  },\n  server: {\n    port: 3022,\n  },\n  test: {\n    api: {\n      port: 3023,\n      allowExec: false,\n      allowWrite: false,\n    },\n    name: 'core',\n    includeSource: [\n      'src/in-source/*.ts',\n    ],\n    exclude: [\n      '**/fixtures/**',\n      ...defaultExclude,\n    ],\n    slowTestThreshold: 1000,\n    testTimeout: process.env.CI ? 10_000 : 5_000,\n    setupFiles: [\n      './test/setup.ts',\n    ],\n    server: {\n      deps: {\n        external: [\n          'tinyspy',\n          /src\\/external/,\n          /esm\\/esm/,\n          /packages\\/web-worker/,\n          /\\.wasm$/,\n          /\\/wasm-bindgen-no-cyclic\\/index_bg.js/,\n          /dep-esm-non-existing/,\n        ],\n        inline: ['inline-lib'],\n      },\n    },\n    includeTaskLocation: true,\n    reporters: process.env.GITHUB_ACTIONS\n      ? ['default', ['github-actions', { displayAnnotations: false }]]\n      : [['default', { summary: true }], 'hanging-process'],\n    testNamePattern: '^((?!does not include test that).)*$',\n    coverage: {\n      provider: 'istanbul',\n      reporter: ['text', 'html'],\n    },\n    typecheck: {\n      enabled: true,\n      tsconfig: './tsconfig.typecheck.json',\n    },\n    environmentOptions: {\n      custom: {\n        option: 'config-option',\n      },\n    },\n    execArgv: ['--experimental-wasm-modules'],\n    env: {\n      CUSTOM_ENV: 'foo',\n    },\n    resolveSnapshotPath: (path, extension) => {\n      if (path.includes('moved-snapshot')) {\n        return path + extension\n      }\n      return join(dirname(path), '__snapshots__', `${basename(path)}${extension}`)\n    },\n    sequence: {\n      seed: 101,\n    },\n    allowOnly: true,\n    deps: {\n      moduleDirectories: ['node_modules', 'projects', 'packages'],\n    },\n    alias: [\n      {\n        find: 'test-alias',\n        replacement: '',\n        // vitest doesn't crash because function is defined\n        customResolver: () => resolve(import.meta.dirname, 'src', 'aliased-mod.ts'),\n      },\n    ],\n    onConsoleLog(log) {\n      if (log.includes('Failed to load url') && log.includes('web-worker')) {\n        return false\n      }\n      if (log.includes('Importing WebAssembly ')) {\n        return false\n      }\n      if (log.includes('run [...filters]')) {\n        return false\n      }\n      if (log.includes('Cannot find module') && log.includes('/web-worker/some-invalid-path')) {\n        return false\n      }\n      if (log.includes('Cannot find module') && log.includes('/web-worker/workerInvalid-path.ts')) {\n        return false\n      }\n      if (log.startsWith(`[vitest]`) && log.includes(`did not use 'function' or 'class' in its implementation`)) {\n        return false\n      }\n      if (log.startsWith('Importing from') && log.includes('is deprecated since Vitest 4.1')) {\n        return false\n      }\n    },\n    projects: [\n      project('threads', 'red'),\n      project('forks', 'green'),\n      project('vmThreads', 'blue'),\n    ],\n  },\n})\n\nfunction project(pool: Pool, color: LabelColor) {\n  return {\n    extends: './vite.config.ts',\n    test: {\n      name: { label: pool, color },\n      pool,\n    },\n  }\n}\n"
  },
  {
    "path": "test/core/vitest-environment-custom/index.ts",
    "content": "import type { Environment } from 'vitest/runtime'\nimport vm from 'node:vm'\nimport { createDebug } from 'obug'\n\n// test that external packages (obug) are loaded correctly\nconst log = createDebug('test:env')\n\nexport default <Environment>{\n  name: 'custom',\n  viteEnvironment: 'ssr',\n  setupVM({ custom }) {\n    const context = vm.createContext({\n      testEnvironment: 'custom',\n      option: custom.option,\n      POOL_ID_DURING_ENV_SETUP: process.env.VITEST_POOL_ID,\n      WORKER_ID_DURING_ENV_SETUP: process.env.VITEST_WORKER_ID,\n      setTimeout,\n      clearTimeout,\n      AbortController,\n      EventTarget,\n      Event,\n    })\n    return {\n      getVmContext() {\n        return context\n      },\n      teardown() {\n        delete context.testEnvironment\n        delete context.option\n      },\n    }\n  },\n  setup(global, { custom }) {\n    global.testEnvironment = 'custom'\n    global.option = custom.option\n    global.POOL_ID_DURING_ENV_SETUP = process.env.VITEST_POOL_ID\n    global.WORKER_ID_DURING_ENV_SETUP = process.env.VITEST_WORKER_ID\n\n    return {\n      teardown() {\n        delete global.testEnvironment\n        delete global.option\n\n        if (global.__exists) {\n          log('should not log')\n        }\n      },\n    }\n  },\n}\n"
  },
  {
    "path": "test/core/vitest-environment-custom/package.json",
    "content": "{\n  \"name\": \"vitest-environment-custom\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"exports\": {\n    \".\": \"./index.ts\"\n  },\n  \"main\": \"index.ts\"\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.conditional.ts",
    "content": "import { resolve } from 'node:path'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'test-resolve-conditional',\n      resolveId: {\n        order: 'pre',\n        handler(source) {\n          if (source.includes(\"fixtures/src/conditional\")) {\n            if (this.environment.config.consumer === 'server') {\n              return resolve('fixtures/src/conditional/ssr.ts')\n            }\n            return resolve('fixtures/src/conditional/web.ts')\n          }\n        }\n      },\n    }\n  ]\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.configure-vitest-hook.ts",
    "content": "import assert from 'node:assert';\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [{\n    name: \"coverage-options-by-runtime-plugin\",\n    configureVitest(context) {\n      const coverage = context.vitest.config.coverage\n      assert(coverage.provider === \"v8\" || coverage.provider === \"istanbul\")\n\n      coverage.include ||= []\n      coverage.include.push(\"**/even.ts\");\n      coverage.include.push(\"**/untested-file.ts\");\n\n      coverage.exclude.push(\"**/math.ts\");\n    },\n  }],\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.decorators.ts",
    "content": "import { defineConfig, mergeConfig } from \"vitest/config\";\nimport swc from \"unplugin-swc\";\nimport type { Plugin } from \"vite\";\n\nimport base from \"./vitest.config\";\n\nexport default mergeConfig(\n  base,\n  defineConfig({\n    plugins: process.env.TEST_OXC_DECORATOR ? [] : [DecoratorsPlugin()],\n    test: {},\n  })\n);\n\nfunction DecoratorsPlugin(): Plugin {\n  const plugin = swc.vite({\n    jsc: {\n      target: \"esnext\",\n      parser: {\n        syntax: \"typescript\",\n        decorators: true,\n      },\n      transform: {\n        legacyDecorator: true,\n        decoratorMetadata: true,\n      },\n    },\n  });\n\n  return {\n    name: \"custom-swc-decorator\",\n    enforce: \"pre\",\n    transform(code, id, options) {\n      if (id.endsWith(\"decorators.ts\")) {\n        // @ts-expect-error -- Ignore complex type\n        return plugin.transform(code, id, options);\n      }\n    },\n  };\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.multi-transform.ts",
    "content": "import { defineConfig, mergeConfig } from 'vitest/config'\nimport MagicString from 'magic-string'\nimport remapping from '@jridgewell/remapping'\nimport type { Plugin } from 'vite'\n\nimport base from './vitest.config'\n\nexport default mergeConfig(\n  base,\n  defineConfig({\n    plugins: [MultiTransformPlugin()],\n    test: {}\n  })\n)\n\n/*\n * Transforms `multi-environment.ts` differently based on test environment (JSDOM/Node)\n * so that there are multiple different source maps for a single file.\n * This causes a case where coverage report is incorrect if sourcemaps are not picked based on transform mode.\n */\nfunction MultiTransformPlugin(): Plugin {\n  return {\n    name: 'vitest-custom-multi-transform',\n    enforce: 'pre',\n    transform(code, id, options) {\n      if (id.includes('src/multi-environment')) {\n        const ssr = options?.ssr || false\n        const transformMode = `transformMode is ${ssr ? 'ssr' : 'csr'}`\n        const padding = '\\n*****'.repeat(ssr ? 0 : 15)\n\n        const transformed = new MagicString(code)\n        transformed.replace('\\'default-padding\\'', `\\`${transformMode} ${padding}\\``)\n\n        const map = remapping(\n          [transformed.generateMap({ hires: true }), this.getCombinedSourcemap() as any],\n          () => null,\n        ) as any\n\n        return { code: transformed.toString(), map }\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.multi-transforms.ts",
    "content": "import { readFileSync } from \"node:fs\";\nimport { Plugin, defineConfig } from \"vitest/config\";\nimport MagicString from \"magic-string\";\n\nexport default defineConfig({\n  test: {\n    projects: [\n      // Project that uses its own \"root\" and custom transform plugin\n      {\n        test: {\n          name: \"custom-with-root\",\n          root: \"fixtures/workspaces/custom-2\",\n        },\n        plugins: [customFilePlugin(\"2\")],\n      },\n\n      // Project that cannot transform \"*.custom-x\" files\n      {\n        test: {\n          name: \"normal\",\n          include: [\"fixtures/test/math.test.ts\"],\n        },\n      },\n\n      // Project that uses default \"root\" and has custom transform plugin\n      {\n        test: {\n          name: \"custom\",\n          include: [\"fixtures/test/custom-1-syntax.test.ts\"],\n        },\n        plugins: [customFilePlugin(\"1\")],\n      },\n    ]\n  }\n});\n\n/**\n * Plugin for transforming `.custom-1` and/or `.custom-2` files to Javascript\n */\nexport function customFilePlugin(postfix: \"1\" | \"2\"): Plugin {\n  function transform(code: MagicString) {\n    code.replaceAll(\n      \"<function covered>\",\n      `\nfunction covered() {\n  return \"Custom-${postfix} file loaded!\"\n}\n  `.trim()\n    );\n\n    code.replaceAll(\n      \"<function uncovered>\",\n      `\nfunction uncovered() {\n  return \"This should be uncovered!\"\n}\n    `.trim()\n    );\n\n    code.replaceAll(\"<default export covered>\", \"export default covered()\");\n    code.replaceAll(\"<default export uncovered>\", \"export default uncovered()\");\n  }\n\n  return {\n    name: `custom-${postfix}-file-plugin`,\n    transform(_, id) {\n      const filename = id.split(\"?\")[0];\n\n      if (filename.endsWith(`.custom-${postfix}`)) {\n        const content = readFileSync(filename, \"utf8\");\n\n        const s = new MagicString(content);\n        transform(s);\n\n        return {\n          code: s.toString(),\n          map: s.generateMap({ hires: \"boundary\" }),\n        };\n      }\n    },\n  };\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.query-param-transform.ts",
    "content": "import { defineConfig, mergeConfig } from 'vitest/config'\nimport MagicString from 'magic-string'\nimport remapping from '@jridgewell/remapping'\nimport type { Plugin } from 'vite'\n\nimport base from './vitest.config'\n\nexport default mergeConfig(\n  base,\n  defineConfig({\n    plugins: [QueryParamTransforms()],\n    test: {}\n  })\n)\n\n/**\n * Attempts to do Vue-like query param based transforms\n */\nfunction QueryParamTransforms(): Plugin {\n  return {\n    name: 'vitest-custom-query-param-based-transform',\n    enforce: 'pre',\n    transform(code, id) {\n      if (id.includes('src/query-param-transformed')) {\n        const transformed = new MagicString(code)\n        const query = id.split(\"?query=\").pop()\n\n        if(query === \"first\") {\n          transformed.remove(\n            code.indexOf(\"/* QUERY_PARAM FIRST START */\"),\n            code.indexOf(\"/* QUERY_PARAM FIRST END */\") + \"/* QUERY_PARAM FIRST END */\".length,\n          )\n        } else if(query === \"second\") {\n          transformed.remove(\n            code.indexOf(\"/* QUERY_PARAM SECOND START */\"),\n            code.indexOf(\"/* QUERY_PARAM SECOND END */\") + \"/* QUERY_PARAM SECOND END */\".length,\n          )\n        } else {\n          transformed.remove(\n            code.indexOf(\"/* QUERY_PARAM FIRST START */\"),\n            code.length,\n          )\n        }\n\n        const map = remapping(\n          [transformed.generateMap({ hires: true }), this.getCombinedSourcemap() as any],\n          () => null,\n        ) as any\n\n        return { code: transformed.toString(), map }\n      }\n    },\n  }\n}"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.thresholds-auto-update.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      thresholds: {\n        autoUpdate: true,\n\n        // Global ones\n        lines: 0.1,\n        functions: 0.2,\n        branches: -1000,\n        statements: -2000,\n\n        '**/src/math.ts': {\n          branches: 0.1,\n          functions: 0.2,\n          lines: -1000,\n          statements: -2000,\n        }\n      }\n    }\n  },\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.ts",
    "content": "import vue from \"@vitejs/plugin-vue\";\nimport {  defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [vue()],\n  optimizeDeps: {\n    include: [\"vue\", \"@vitest/cjs-lib\"]\n  }\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.virtual-files.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { Plugin, defineConfig, mergeConfig } from 'vitest/config'\nimport { transformWithEsbuild } from 'vite'\n\nimport base from './vitest.config'\n\nexport default mergeConfig(\n  base,\n  defineConfig({\n    plugins: [VirtualFilesPlugin()],\n    test: {}\n  })\n)\n\n// Simulates Vite's virtual files: https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention\nfunction VirtualFilesPlugin(): Plugin {\n  return {\n    name: 'vitest-custom-virtual-files',\n    resolveId(id) {\n      if (id === 'virtual:vitest-custom-virtual-file-1') {\n        return 'src/virtual:vitest-custom-virtual-file-1.ts'\n      }\n\n      if (id === '\\0vitest-custom-virtual-file-2') {\n        return 'src/\\0vitest-custom-virtual-file-2.ts'\n      }\n\n      if (id.includes('vitest-custom-virtual:math')) {\n        return resolve(import.meta.dirname, \"../src/vitest-custom-virtual:math\")\n      }\n    },\n    load(id) {\n      if (id === 'src/virtual:vitest-custom-virtual-file-1.ts') {\n        return `\n          const virtualFile = \"This file should be excluded from coverage report #1\"\n          export default virtualFile;\n        `\n      }\n\n      // Vitest browser resolves this as \"\\x00\", Node as \"__x00__\"\n      if (id === 'src/__x00__vitest-custom-virtual-file-2.ts' || id === 'src/\\x00vitest-custom-virtual-file-2.ts') {\n        return `\n          const virtualFile = \"This file should be excluded from coverage report #2\"\n          export default virtualFile;\n        `\n      }\n\n      if(id.includes(\"vitest-custom-virtual:math\")) {\n        const filename = resolve(import.meta.dirname, \"../src/math.ts\");\n        const sources = readFileSync(filename, \"utf8\")\n\n        return transformWithEsbuild(sources, filename)\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/configs/vitest.config.workspace.ts",
    "content": "import { resolve } from \"node:path\";\nimport { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    setupFiles: [resolve(import.meta.dirname, \"../../setup.native.ts\")],\n\n    projects: [\n      {\n        extends: true,\n        test: {\n          name: \"project1\",\n          root: \"fixtures/workspaces/project/project1\",\n        },\n      },\n      {\n        extends: true,\n        test: {\n          name: \"project2\",\n          root: \"fixtures/workspaces/project/project2\",\n        },\n      },\n      {\n        extends: true,\n        test: {\n          name: 'project-shared',\n          root: 'fixtures/workspaces/project/shared',\n        }\n      }\n    ]\n  }\n});\n"
  },
  {
    "path": "test/coverage-test/fixtures/custom-provider.ts",
    "content": "import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'\nimport { normalize, resolve, sep } from 'node:path'\nimport { AfterSuiteRunMeta } from 'vitest'\nimport type { CoverageProvider, CoverageProviderModule, ReportContext, ResolvedCoverageOptions, Vitest } from 'vitest/node'\n\nconst CustomCoverageProviderModule: CoverageProviderModule = {\n  getProvider(): CoverageProvider {\n    return new CustomCoverageProvider()\n  },\n\n  takeCoverage() {\n    // @ts-expect-error -- untyped\n    globalThis.CUSTOM_PROVIDER_TAKE_COVERAGE = true\n\n    // @ts-expect-error -- untyped\n    if (!globalThis.CUSTOM_PROVIDER_START_COVERAGE) {\n      throw new Error('takeCoverage was called before startCoverage!')\n    }\n\n    return { customCoverage: 'Coverage report passed from workers to main thread' }\n  },\n\n  startCoverage() {\n    // @ts-expect-error -- untyped\n    globalThis.CUSTOM_PROVIDER_START_COVERAGE = true\n  },\n\n  stopCoverage() {\n    // @ts-expect-error -- untyped\n    if (!globalThis.CUSTOM_PROVIDER_START_COVERAGE) {\n      throw new Error('stopCoverage was called before startCoverage!')\n    }\n\n    // @ts-expect-error -- untyped\n    if (!globalThis.CUSTOM_PROVIDER_TAKE_COVERAGE) {\n      throw new Error('stopCoverage was called before takeCoverage!')\n    }\n  },\n}\n\n/**\n * Provider that simply keeps track of the functions that were called\n */\nclass CustomCoverageProvider implements CoverageProvider {\n  name = 'custom-coverage-provider'\n\n  options!: ResolvedCoverageOptions\n  calls: Set<string> = new Set()\n  coverageReports: Set<string> = new Set()\n  transformedFiles: Set<string> = new Set()\n\n  initialize(ctx: Vitest) {\n    this.options = ctx.config.coverage\n\n    this.calls.add(`initialized ${ctx ? 'with' : 'without'} context`)\n  }\n\n  clean(force?: boolean) {\n    this.calls.add(`clean ${force ? 'with' : 'without'} force`)\n  }\n\n  onAfterSuiteRun(meta: AfterSuiteRunMeta) {\n    // Do not include coverage info here, as order of tests is not guaranteed\n    this.calls.add('onAfterSuiteRun')\n\n    // Keep coverage info separate from calls and ignore its order\n    this.coverageReports.add(JSON.stringify({\n      ...meta,\n\n      // Project name keeps changing so let's simply check that its present\n      projectName: meta.projectName && typeof meta.projectName === 'string',\n    }))\n  }\n\n  generateCoverage(_reportContext: ReportContext) {\n    return {}\n  }\n\n  reportCoverage(coverage: unknown, reportContext?: ReportContext) {\n    this.calls.add(`reportCoverage with ${JSON.stringify(reportContext)}`)\n\n    const jsonReport = JSON.stringify({\n      calls: Array.from(this.calls.values()),\n      coverageReports: Array.from(this.coverageReports.values()).sort(),\n      transformedFiles: Array.from(this.transformedFiles.values()).sort(),\n    }, null, 2)\n\n    if (existsSync('./coverage')) {\n      rmSync('./coverage', { maxRetries: 10, recursive: true })\n    }\n\n    mkdirSync('./coverage')\n    writeFileSync('./coverage/custom-coverage-provider-report.json', jsonReport, 'utf-8')\n  }\n\n  onFileTransform(code: string, id: string) {\n    const filename = normalizeFilename(id).split('?')[0]\n\n    if (/\\/fixtures\\/src\\//.test(filename)) {\n      this.transformedFiles.add(filename)\n    }\n\n    return { code }\n  }\n\n  resolveOptions(): ResolvedCoverageOptions {\n    this.calls.add('resolveOptions')\n\n    return this.options\n  }\n}\n\nexport default CustomCoverageProviderModule\n\n\nfunction normalizeFilename(filename: string) {\n  return normalize(filename)\n    .replace(normalize(process.cwd()), '<process-cwd>')\n    .replace(normalize(resolve(process.cwd(), '../../')), '<project-root>')\n    .replaceAll(sep, \"/\")\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/custom-reporter.cjs",
    "content": "/* Istanbul uses `require`: https://github.com/istanbuljs/istanbuljs/blob/5584b50305a6a17d3573aea25c84e254d4a08b65/packages/istanbul-reports/index.js#L19 */\n\n'use strict'\nconst { ReportBase } = require('istanbul-lib-report')\n\nmodule.exports = class CustomReporter extends ReportBase {\n  constructor(opts) {\n    super()\n\n    if (!opts.file) {\n      throw new Error('File is required as custom reporter parameter')\n    }\n\n    this.file = opts.file\n  }\n\n  onStart(root, context) {\n    this.contentWriter = context.writer.writeFile(this.file)\n    this.contentWriter.println('Start of custom coverage report')\n  }\n\n  onEnd() {\n    this.contentWriter.println('End of custom coverage report')\n    this.contentWriter.close()\n  }\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/setup.isolation.ts",
    "content": "import { beforeAll } from \"vitest\";\nimport { branch } from \"./src/branch\";\n\nbeforeAll(() => {\n  branch(1);\n});\n"
  },
  {
    "path": "test/coverage-test/fixtures/setup.ts",
    "content": "console.log('Running setup in fixtures root')\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/.should-be-excluded-from-coverage/excluded-from-coverage.ts",
    "content": "// This file should be excluded from coverage report\n\nexport function uncoveredFile() {\n  return 0\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/Vue/Counter/Counter.component.ts",
    "content": "import { defineComponent, ref } from 'vue'\n\nexport default defineComponent({\n  name: 'Counter',\n\n  setup() {\n    const count = ref(0)\n    return { count }\n  },\n\n  methods: {\n    uncoveredMethod() {\n      return 'This line should not be covered'\n    },\n\n    coveredMethod() {\n      return 'This line should be covered'\n    },\n\n    uncoveredMethodUsingImportMeta() {\n      return `Source maps tend to break when import meta is used: ${import.meta.env.BASE_URL}`\n    },\n  },\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/Vue/Counter/Counter.vue",
    "content": "<script lang=\"ts\" src=\"./Counter.component.ts\"></script>\n\n<template>\n  <button @click=\"count++\">\n    {{ count }}\n  </button>\n\n  <div v-if=\"count > 10\">\n    {{ uncoveredMethod() }}\n  </div>\n  <div v-else>\n    {{ coveredMethod() }}\n  </div>\n</template>\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/Vue/Counter/index.ts",
    "content": "import CounterVue from './Counter.vue'\n\nexport { CounterVue }\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/Vue/Defined.vue",
    "content": "<script setup lang=\"ts\">\nconst defined = 'hello'\n\n/* eslint-disable no-console */\nif (defined) {\n  console.log('Covered condition')\n}\nelse {\n  console.log('Uncovered condition')\n}\n</script>\n\n<template>\n  {{ defined }}\n</template>\n\n<!-- Style block triggers a specific condition where sourcemaps used to break randomly -->\n<style lang=\"css\" scoped>\nbody {\n  background-color: #FFF;\n}\n</style>\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/Vue/Hello.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\n\nconst props = defineProps<{ count: number }>()\n\nconst times = ref(2)\nconst result = computed(() => props.count * times.value)\n\ndefineExpose(props)\n</script>\n\n<template>\n  <div>{{ count }} x {{ times }} = {{ result }}</div>\n  <button @click=\"times += 1\">\n    x1\n  </button>\n</template>\n\n<!-- Style block triggers a specific condition where sourcemaps used to break randomly -->\n<!-- https://github.com/vitest-dev/vitest/issues/8154 -->\n<style lang=\"scss\">\nbody {\n  background-color: #FFF;\n}\n</style>\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/Vue/vue.shim.d.ts",
    "content": "declare const MY_CONSTANT: string\n\ndeclare module '*.vue' {\n  import type { DefineComponent } from 'vue'\n\n  const component: DefineComponent<{}, {}, any>\n  export default component\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/another-setup.ts",
    "content": "console.log('Running another setup in fixtures src')\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/branch.ts",
    "content": "export const branch = async (a: number) => {\n  if (a === 15) {\n    return true;\n  }\n\n  return false;\n};\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/circularA.ts",
    "content": "import { circularB } from './circularB'\n\nexport const CalledB: number[] = []\n\nexport function circularA() {\n  return circularB()\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/circularB.ts",
    "content": "import { CalledB } from './circularA'\n\nexport function circularB() {\n  return CalledB.push(CalledB.length)\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/cjs-dependency.ts",
    "content": "// @ts-expect-error -- types not picked up for some reason\nimport cjsDefault from '@vitest/cjs-lib'\n\nexport default function getA() {\n  return cjsDefault.a\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/conditional/ssr.ts",
    "content": "export function ssr() {\n  return \"This is for ssr transform\"\n}"
  },
  {
    "path": "test/coverage-test/fixtures/src/conditional/web.ts",
    "content": "export function web() {\n  return \"This is for web transform\"\n}"
  },
  {
    "path": "test/coverage-test/fixtures/src/covered.custom-1",
    "content": "<function covered>\n\n<function uncovered>\n\n<default export covered>\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/decorators.ts",
    "content": "// eslint-disable-next-line ts/ban-ts-comment -- so that typecheck doesn't include it\n// @ts-nocheck\nexport class DecoratorsTester {\n  method(@SomeDecorator parameter: Something) {\n    if (parameter) {\n      // Covered line\n      noop(parameter)\n    }\n\n    if (parameter === 'uncovered') {\n      // Uncovered line\n      noop(parameter)\n    }\n  }\n}\n\nfunction SomeDecorator(\n  _target: Object,\n  _propertyKey: string | symbol,\n  _parameterIndex: number,\n) {}\n\ntype Something = unknown\n\nfunction noop(..._args: unknown[]) {\n\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/dynamic-files.ts",
    "content": "import { existsSync, rmSync, writeFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { onTestFinished } from 'vitest'\n\nexport async function runDynamicFileESM() {\n  const fileUrl = new URL('./dynamic-file-esm.ignore.js', import.meta.url)\n  const filename = fileURLToPath(fileUrl)\n  onTestFinished(() => {\n    if(existsSync(filename)) {\n      rmSync(filename)\n    }\n  })\n\n  if (existsSync(filename)) {\n    rmSync(filename)\n  }\n\n  writeFileSync(filename, `\n// File created by coverage/fixtures/src/dynamic-files.ts\nexport function run() {\n  return \"Import works\"\n}\nfunction uncovered() {}\n  `.trim(), 'utf-8')\n\n  const { run } = await import(/* @vite-ignore */ fileUrl.href)\n\n  if (run() !== 'Import works') {\n    throw new Error(`Failed to run ${filename}`)\n  }\n\n  return \"Done\"\n}\n\nexport async function runDynamicFileCJS() {\n  const filename = fileURLToPath(new URL('./dynamic-file-cjs.ignore.cjs', import.meta.url))\n\n  if (existsSync(filename)) {\n    rmSync(filename)\n  }\n  onTestFinished(() => {\n    if(existsSync(filename)) {\n      rmSync(filename)\n    }\n  })\n\n  writeFileSync(filename, `\n// File created by coverage/fixtures/src/dynamic-files.ts\nmodule.exports.run = function run() {\n  return \"Import works\"\n}\nfunction uncovered() {}\n  `.trim(), 'utf-8')\n\n  const { run } = createRequire(import.meta.url)(filename)\n\n  if (run() !== 'Import works') {\n    throw new Error(`Failed to run ${filename}`)\n  }\n\n  return \"Done\"\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/empty-lines.ts",
    "content": "/* eslint-disable unused-imports/no-unused-vars -- intentional */\nexport function add(a: number, b: number) {\n  /**\n   * Multi\n   * line\n   * comment\n   */\n  if (a === 2 && b === 3) {\n    // This line should NOT be covered\n    return 5\n  }\n\n  type TypescriptTypings = 1 | 2\n\n  if (a === 1 && b === 1) {\n    // This line should NOT be covered\n    return 2\n  }\n\n  interface MoreCompileTimeCode {\n    should: {\n      be: {\n        excluded: true\n      }\n    }\n  }\n\n  return a + b\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/even.ts",
    "content": "export function isEven(a: number) {\n  return a % 2 === 0\n}\n\nexport function isOdd(a: number) {\n  return !isEven(a)\n}"
  },
  {
    "path": "test/coverage-test/fixtures/src/file-to-change.ts",
    "content": "export function run() {\n  return 'This file will be modified by test cases'\n}\n\nexport function uncoveredFunction() {\n  return 1 + 2\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/ignore-hints.ts",
    "content": "// padding\n/* istanbul ignore next -- @preserve */\nexport function first() {\n  return \"First\"\n}\n\nexport function second() {\n  return \"Second\"\n}\n\n/* istanbul ignore start */\nexport function third() {\n  return \"Third\"\n}\n\nexport function fourth() {\n  return \"fourh\"\n}\n/* istanbul ignore stop */\n\n// Covered line\nsecond()\n\n/* v8 ignore next -- @preserve, Uncovered line v8 */\nsecond()\n\n/* istanbul ignore next -- @preserve, Uncovered line istanbul */\nsecond()\n\nfourth()\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/implicit-else.ts",
    "content": "export function implicitElse(condition: boolean) {\n  let a = 1\n\n  if (condition) {\n    a = 2\n  }\n\n  return a\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/import-meta-env.ts",
    "content": "// @ts-nocheck -- untyped\nexport function useImportEnv() {\n  return import.meta.env.SOME_VARIABLE\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/in-source.ts",
    "content": "/// <reference types=\"vitest/importMeta\" />\n\nexport function add(a: number, b: number) {\n  if(a === 5  && b === 7) {\n    return 12;\n  }\n\n  return a + b\n}\n\nif (import.meta.vitest) {\n  const { test, expect } = import.meta.vitest\n\n  // Name of the callback test function is checked in tests\n  test('in source test running add function', function customNamedTestFunction() {\n    expect(add(10, 19)).toBe(29)\n  })\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/json-data-import.ts",
    "content": "import data from \"./json-data.json\" with { \"type\": \"json\" };\n\nexport function getJSON() {\n  return data\n};\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/json-data.json",
    "content": "{\n  \"foo\": false,\n  \"bar\": \"baz\"\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/load-outside-vite.cjs",
    "content": "module.exports = function noop() {}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/math.ts",
    "content": "export function sum(a: number, b: number) {\n  return a + b\n}\n\nexport function subtract(a: number, b: number) {\n  return a - b\n}\n\nexport function multiply(a: number, b: number) {\n  return a * b\n}\n\nexport function remainder(a: number, b:number) {\n  return a % b\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/mock-target.ts",
    "content": "export function double(value: number): number {\n  return value * 2\n}\n\nexport function triple(value: number): number {\n  return value * 3\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/multi-environment.ts",
    "content": "/**\n * The variable below is modified by custom Vite plugin\n */\nexport const padding = 'default-padding'\n\nexport function sum(a: number, b: number) {\n  /*\n   * These if-branches should show correctly on coverage report.\n   * Otherwise source maps are off.\n   */\n  if (a === 8 && b === 9) {\n    // This is not covered by any test\n    return 17\n  }\n  // Comment\n  else if (a === 2 && b === 2) {\n    // This is covered by SSR test\n    return 4\n  }\n  else if (a === 11 && b === 22) {\n    // This is not covered by any test\n    return 33\n  }\n  else if (a === 10 && b === 23) {\n    // This is covered by Web test\n    return 33\n  }\n\n  // This is covered by SSR and Web test, should show 2x hits\n  return a + b\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/multi-suite.ts",
    "content": "export default {\n  func1(data: any[]) {\n    return data\n  },\n\n  func2(data: any[]) {\n    return data\n  },\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/pre-bundle/bundle.js",
    "content": "function covered$1() {\n  return \"First\";\n}\n\nfunction uncovered$1() {\n  return \"Uncovered\";\n}\n\nvar first = /*#__PURE__*/Object.freeze({\n  __proto__: null,\n  covered: covered$1,\n  uncovered: uncovered$1\n});\n\nfunction covered() {\n  return \"Second\";\n}\n\nfunction uncovered() {\n  return \"Uncovered\";\n}\n\nvar second = /*#__PURE__*/Object.freeze({\n  __proto__: null,\n  covered: covered,\n  uncovered: uncovered\n});\n\nexport { first, second };\n//# sourceMappingURL=bundle.js.map\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/pre-bundle/bundle.ts",
    "content": "export * as first from \"./first\";\nexport * as second from \"./second\";\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/pre-bundle/first.ts",
    "content": "export function covered() {\n  return \"First\";\n}\n\nexport function uncovered() {\n  return \"Uncovered\";\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/pre-bundle/second.ts",
    "content": "export function covered() {\n  return \"Second\";\n}\n\nexport function uncovered() {\n  return \"Uncovered\";\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/pre-transpiled/original.ts",
    "content": "export const hello = (arg?: unknown) => {\n  if (arg) {\n    // Uncovered\n    noop();\n  }\n\n  // Covered\n  noop();\n\n  if (arg === 3) {\n    // Uncovered\n    noop();\n  }\n\n  if (arg === undefined) {\n    // Covered\n    noop();\n  }\n};\n\nfunction noop() {}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/pre-transpiled/transpiled.d.ts",
    "content": "export * from './original'\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/pre-transpiled/transpiled.js",
    "content": "export var hello = function (arg) {\n    if (arg) {\n        // Uncovered\n        noop();\n    }\n    // Covered\n    noop();\n    if (arg === 3) {\n        // Uncovered\n        noop();\n    }\n    if (arg === undefined) {\n        // Covered\n        noop();\n    }\n};\nfunction noop() { }\n//# sourceMappingURL=transpiled.js.map"
  },
  {
    "path": "test/coverage-test/fixtures/src/query-param-transformed.ts",
    "content": "export function initial() {\n  return \"Always present\"\n}\n\n/* QUERY_PARAM FIRST START */\nexport function first() {\n  return \"Removed when ?query=first\"\n}\n/* QUERY_PARAM FIRST END */\n\n/* QUERY_PARAM SECOND START */\nexport function second() {\n  return \"Removed when ?query=second\"\n}\n/* QUERY_PARAM SECOND END */\n\nexport function uncovered() {\n  return \"Always present\"\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/should-be-excluded-by-default.cts",
    "content": "/*\n * Vite does not transform `*.cts` files.\n * If this file is picked by Istanbul provider, it will make Babel crash on TS syntax.\n */\ninterface Props {\n  name: string;\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/test-that-looks-like-source-file.ts",
    "content": "import { test, expect } from 'vitest'\nimport { sum } from \"./math\"\n\ntest(\"run tests on file that looks like source file\", () => {\n  expect(sum(1,2)).toBe(3)\n})"
  },
  {
    "path": "test/coverage-test/fixtures/src/tested-with-]-in-filename.ts",
    "content": "export default function covered(a: number, b: number) {\n  if(a === 2 && b === 3) {\n    return 5\n  }\n\n  return a + b\n}\n\nexport function uncovered(a: number, b: number) {\n  if(a === 2 && b === 3) {\n    return 5\n  }\n\n  return a + b\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/throws-error.ts",
    "content": "/**\n * Some padding\n */\nexport function uncovered() {\n  return \"uncoverd\";\n}\n\n/**\n * Some padding\n */\n\nexport function throwsError(condition: Boolean) {\n  /**\n   * Some padding\n   */\n\n  if(condition === false) {\n    /**\n     * Some padding\n     */\n\n    return;\n  }\n\n  /**\n   * Some padding\n   */\n   function throws() {\n     throw new Error(\"Expected error\")\n   }\n  /**\n   * Some padding\n   */\n   throws()\n}\n\n/**\n * Some padding\n */\nexport function uncovered2() {\n  return \"uncoverd\";\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/types-only.ts",
    "content": "export type First = 'This' | 'file' | 'should'\n\nexport type Second = 'be' | 'excluded' | 'from' | 'report'\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/uncovered.custom-1",
    "content": "<function uncovered>\n\n<default export uncovered>\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/untested-file.ts",
    "content": "/*\n * Some top level comment which adds some padding. This helps us see\n * if sourcemaps are off.\n*/\n\n/* eslint-disable unused-imports/no-unused-vars -- intentional */\n\nexport default function untestedFile() {\n  return 'This file should end up in report when {\"all\": true} is given'\n}\n\nfunction add(a: number, b: number) {\n  // This line should NOT be covered\n  return a + b\n}\n\ntype TypescriptTypings = 1 | 2\n\nfunction multiply(a: number, b: number) {\n  // This line should NOT be covered\n  return a * b\n}\n\nexport function math(a: number, b: number, operator: '*' | '+') {\n  interface MoreCompileTimeCode {\n    should: {\n      be: {\n        excluded: true\n      }\n    }\n  }\n\n  if (operator === '*') {\n    // This line should NOT be covered\n    return multiply(a, b)\n  }\n\n  /* istanbul ignore start */\n  if (operator === '+') {\n  // This line should be excluded\n    return add(a, b)\n  }\n  /* istanbul ignore stop */\n\n  // This line should NOT be covered\n  throw new Error('Unsupported operator')\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/untested-with-]-in-filename.ts",
    "content": "/*\n * Some top level comment which adds some padding. This helps us see\n * if sourcemaps are off.\n*/\n\n/* eslint-disable unused-imports/no-unused-vars -- intentional */\n\nexport default function untestedFile() {\n  return 'Untetsted'\n}\n\nfunction add(a: number, b: number) {\n  // This line should NOT be covered\n  return a + b\n}\n\ntype TypescriptTypings = 1 | 2\n\nfunction multiply(a: number, b: number) {\n  // This line should NOT be covered\n  return a * b\n}\n\nexport function math(a: number, b: number, operator: '*' | '+') {\n  interface MoreCompileTimeCode {\n    should: {\n      be: {\n        excluded: true\n      }\n    }\n  }\n\n  if (operator === '*') {\n    // This line should NOT be covered\n    return multiply(a, b)\n  }\n\n  /* v8 ignore start */\n  if (operator === '+') {\n  // This line should be excluded\n    return add(a, b)\n  }\n  /* v8 ignore stop */\n\n  // This line should NOT be covered\n  throw new Error('Unsupported operator')\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/virtual-files.ts",
    "content": "// @ts-expect-error -- untyped virtual file provided by custom plugin\nimport virtualFile1 from 'virtual:vitest-custom-virtual-file-1'\n\n// @ts-expect-error -- untyped virtual file provided by custom plugin\nimport virtualFile2 from '\\0vitest-custom-virtual-file-2'\n\n// @ts-expect-error -- untyped virtual file provided by custom plugin\nimport * as virtualMath from 'vitest-custom-virtual:math'\n\nexport function getVirtualFileImports() {\n  return { virtualFile1, virtualFile2, virtualMath }\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/worker-wrapper.ts",
    "content": "export async function sumInBackground(a: number, b: number) {\n  const worker = new Worker(new URL(\"./worker?with-some-query=123\", import.meta.url), {\n    type: \"module\",\n  });\n\n  const promise = new Promise<MessageEvent>(resolve => {\n    worker.onmessage = resolve;\n  });\n\n  function uncovered() {\n    return \"This is uncovered\"\n  }\n\n  worker.postMessage({ a, b });\n\n  const result = await promise;\n  covered();\n  worker.terminate();\n\n  return result.data;\n}\n\nfunction covered() {\n  return \"This is covered\"\n}\n\nexport function uncovered() {\n  return \"This is uncovered\"\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/src/worker.ts",
    "content": "self.onmessage = (ev: MessageEvent) => {\n  const {a, b} = ev.data;\n\n  if (a === 5) {\n    uncovered()\n    throw new Error(\"uncovered\");\n  }\n\n  if(b === 6) {\n    uncovered()\n    throw new Error(\"uncovered\");\n\n  }\n\n  covered();\n  postMessage(a + b);\n};\n\nexport function uncovered() {\n  return \"This is uncovered\"\n}\n\nfunction covered() {\n  return \"This is covered\"\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/allow-external-fixture.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { multiply } from '../src/math'\nimport * as ExternalMath from '../../../test-utils/fixtures/external-math'\n\ntest('calling files outside project root', () => {\n  expect(ExternalMath.sum(2, 3)).toBe(5)\n})\n\ntest('multiply - add some files to report', () => {\n  expect(multiply(2, 3)).toBe(6)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/circular.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { CalledB, circularA } from '../src/circularA'\n\nit('circular', () => {\n  CalledB.length = 0\n\n  circularA()\n\n  expect(CalledB.length).toBe(1)\n\n  circularA()\n  circularA()\n\n  expect(CalledB).toEqual([0, 1, 2])\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/cjs-dependency.test.ts",
    "content": "import { test } from \"vitest\";\nimport cjsDependency from \"../src/cjs-dependency\";\n\ntest(\"cjs dependency vite transforms\", () => {\n  cjsDependency()\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/clean-on-rerun-fixture.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport * as math from '../src/math'\n\n// This line will be changed by clean-on-rerun.test.ts\nconst methodToTest = 'sum'\n\ntest(`run ${methodToTest}`, () => {\n  expect(() => math[methodToTest](1, 2)).not.toThrow()\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/custom-1-syntax.test.ts",
    "content": "import { expect, test } from 'vitest'\n\n// @ts-expect-error -- untyped\nimport output from '../src/covered.custom-1'\n\ntest('custom file loads fine', () => {\n  expect(output).toMatch('Custom-1 file loaded!')\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/error-location.test.ts",
    "content": "import { test } from \"vitest\"\nimport { throwsError } from \"../src/throws-error\"\n\ntest(\"throws error\", async () => {\n  throwsError(true)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/even.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isEven } from '../src/even'\n\ntest('isEven', () => {\n  expect(isEven(6)).toBe(true)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/file-to-change.test.ts",
    "content": "import { test } from 'vitest'\nimport { run } from '../src/file-to-change'\n\ntest('test case for changed file', () => {\n  run()\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/ignore-hints-fixture.test.ts",
    "content": "import { test, expect} from \"vitest\";\nimport { first, second } from '../src/ignore-hints';\n\ntest(\"cover some lines\", () => {\n  expect(first()).toBe(\"First\")\n  expect(second()).toBe(\"Second\")\n})"
  },
  {
    "path": "test/coverage-test/fixtures/test/import-attributes-fixture.test.ts",
    "content": "import { expect, test } from \"vitest\";\nimport {getJSON} from \"../src/json-data-import\";\nimport json from \"../src/json-data.json\";\n\ntest(\"JSON data\", () => {\n  expect(getJSON()).toEqual(json);\n});\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/isolation-1-fixture.test.ts",
    "content": "import { test } from \"vitest\";\nimport { multiply, remainder, subtract, sum } from \"../src/math\";\n\ntest(\"Should run function successfully\", async () => {\n  sum(1, 1);\n  subtract(1,2)\n  multiply(3,4)\n  remainder(6,7)\n});\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/isolation-2-fixture.test.ts",
    "content": "import { test } from \"vitest\";\nimport { branch } from \"../src/branch\";\n\ntest(\"cover some lines\", async () => {\n  branch(15);\n});\n\ntest(\"cover lines\", async () => {\n  branch(2);\n});\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/math.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { sum } from '../src/math'\n\ntest('sum', () => {\n  expect(sum(1, 2)).toBe(3)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/merge-fixture-1.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { sum } from '../src/math'\n\ntest('cover sum', () => {\n  expect(sum(1, 2)).toBe(3)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/merge-fixture-2.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { multiply } from '../src/math'\n\ntest('cover multiply', () => {\n expect(multiply(3, 2)).toBe(6)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/merge-fixture-3.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isEven } from '../src/even'\nimport { multiply } from '../src/math'\n\ntest('cover multiply again', () => {\n  expect(multiply(20, 2)).toBe(40)\n})\n\ntest('also cover another file', () => {\n  expect(isEven(4)).toBe(true)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/mock-autospy-fixture.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { double, triple } from '../src/mock-target'\n\nvi.mock(import('../src/mock-target'), { spy: true })\n\ntest('autospy calls original and can be spied on', () => {\n  expect(double(5)).toBe(10)\n  expect(double).toHaveBeenCalledWith(5)\n  expect(triple).not.toHaveBeenCalled()\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/mock-importActual-fixture.test.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { double, triple } from '../src/mock-target'\n\n// Manual spy approach using importOriginal callback - this collects coverage\nvi.mock(import('../src/mock-target'), async (importOriginal) => {\n  const actual = await importOriginal()\n  return {\n    double: vi.fn(actual.double),\n    triple: vi.fn(actual.triple),\n  }\n})\n\ntest('importActual calls original and can be spied on', () => {\n  expect(double(5)).toBe(10)\n  expect(double).toHaveBeenCalledWith(5)\n  expect(triple).not.toHaveBeenCalled()\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/mocking-in-js-file.test.js",
    "content": "import { expect, test, vi } from 'vitest'\nimport { sum } from '../src/math'\n\nvi.mock('../src/math', async () => ({\n  sum: vi.fn().mockReturnValue('mocked'),\n}))\n\ntest('mocking in Javascript test should not break sourcemaps', () => {\n  expect(sum(1, 2)).toBe('mocked')\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/multi-environment-fixture-ssr.test.ts",
    "content": "// @vitest-environment node\n\nimport { expect, test } from 'vitest'\nimport { sum } from '../src/multi-environment'\n\ntest('runs on server', () => {\n  expect(sum(2, 2)).toBe(4)\n  expect(sum(100, 200)).toBe(300)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/multi-environment-fixture-web.test.ts",
    "content": "// @vitest-environment jsdom\n\nimport { expect, test } from 'vitest'\nimport { sum } from '../src/multi-environment'\n\ntest('runs on client', () => {\n  expect(sum(1, 2)).toBe(3)\n  expect(sum(10, 23)).toBe(33)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/multi-suite-fixture.test.ts",
    "content": "import { describe, expect, test } from \"vitest\"\nimport MultiSuite from '../src/multi-suite'\n\ndescribe('Multiple test suites', () => {\n  describe('suite for func1', () => {\n    test('func1', () => {\n      const data = ['a', 'b']\n      const val = MultiSuite.func1(data)\n      expect(val).toEqual(data)\n    })\n  })\n\n  describe('suite for func2', () => {\n    test('func2', () => {\n      const data = ['c', 'd']\n      const val = MultiSuite.func2(data)\n      expect(val).toEqual(data)\n    })\n  })\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/pre-transpiled-fixture.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport * as transpiled from '../src/pre-transpiled/transpiled.js'\n\ntest('run pre-transpiled sources', () => {\n  expect(transpiled.hello).toBeTypeOf('function')\n  expect(transpiled.hello()).toBeUndefined()\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/query-param.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('run initial', async () => {\n  const initial = await import('../src/query-param-transformed')\n\n  // Check that custom plugin works\n  expect(initial.initial()).toBe(\"Always present\")\n  expect(initial.first).toBeUndefined()\n  expect(initial.second).toBeUndefined()\n})\n\ntest('run first', async () => {\n  const initial = await import('../src/query-param-transformed?query=first' as '../src/query-param-transformed')\n\n  // Check that custom plugin works\n  expect(initial.initial()).toBe(\"Always present\")\n  expect(initial.first).toBeUndefined()\n  expect(initial.second()).toBe(\"Removed when ?query=second\")\n})\n\ntest('run second', async () => {\n  const initial = await import('../src/query-param-transformed?query=second' as '../src/query-param-transformed')\n\n  // Check that custom plugin works\n  expect(initial.initial()).toBe(\"Always present\")\n  expect(initial.first()).toBe(\"Removed when ?query=first\")\n  expect(initial.second).toBeUndefined()\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/sources-with-]-in-filenames.test.ts",
    "content": "import { expect, test } from \"vitest\"\n\ntest(\"cover lines\", async () => {\n  const mod = await import(\"../src/tested-with-]-in-filename\")\n\n  expect(mod.default(100, 2)).toBe(102)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/virtual-files-fixture.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { getVirtualFileImports} from '../src/virtual-files'\n\ntest(\"verify virtual files work\", () => {\n  const {virtualFile1, virtualFile2, virtualMath} = getVirtualFileImports()\n\n  expect(virtualFile1).toBe('This file should be excluded from coverage report #1')\n  expect(virtualFile2).toBe('This file should be excluded from coverage report #2')\n\n  expect(virtualMath).toHaveProperty('sum')\n  expect(virtualMath.sum(50, 65)).toBe(115)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/vue-fixture.test.ts",
    "content": "/**\n * @vitest-environment happy-dom\n */\n\nimport { expect, test, vi } from 'vitest'\nimport { mount } from '@vue/test-utils'\nimport Hello from '../src/Vue/Hello.vue'\nimport Defined from '../src/Vue/Defined.vue'\nimport { CounterVue } from '../src/Vue/Counter'\n\ntest('vue 3 coverage', async () => {\n  expect(Hello).toBeTruthy()\n\n  const wrapper = mount(Hello, {\n    props: {\n      count: 4,\n    },\n  })\n\n  expect(wrapper.text()).toContain('4 x 2 = 8')\n  expect(wrapper.html()).toMatchInlineSnapshot(`\n    \"<div>4 x 2 = 8</div>\n    <button> x1 </button>\"\n  `)\n\n  await wrapper.get('button').trigger('click')\n\n  await vi.waitFor(() => {\n    expect(wrapper.text()).toContain('4 x 3 = 12')\n  })\n\n  await wrapper.get('button').trigger('click')\n\n  await vi.waitFor(() => {\n    expect(wrapper.text()).toContain('4 x 4 = 16')\n  })\n})\n\ntest('define package in vm', () => {\n  expect(Defined).toBeTruthy()\n\n  const wrapper = mount(Defined)\n\n  expect(wrapper.text()).toContain('hello')\n})\n\ntest('vue non-SFC, uses query parameters in file imports', async () => {\n  const wrapper = mount(CounterVue)\n\n  await wrapper.find('button').trigger('click')\n  expect(wrapper.text()).contain(1)\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/test/web-worker.test.ts",
    "content": "import { expect, test } from 'vitest';\nimport { sumInBackground } from '../src/worker-wrapper';\n\ntest('run a Worker', async () => {\n  const result = await sumInBackground(15, 7);\n\n  expect(result).toBe(22);\n});\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/custom-2/src/covered.custom-2",
    "content": "<function covered>\n\n<function uncovered>\n\n<default export covered>\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/custom-2/src/uncovered.custom-2",
    "content": "<function uncovered>\n\n<default export uncovered>\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/custom-2/test/custom-2-syntax.test.ts",
    "content": "import { expect, test } from 'vitest'\n\n// @ts-expect-error -- untyped\nimport output from '../src/covered.custom-2'\n\ntest('custom-2 file loads fine', () => {\n  expect(output).toMatch('Custom-2 file loaded!')\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/project/project1/src/id.ts",
    "content": "import { raise } from \"../../shared/src/utils\"\n\nexport const id = <T>(value: T) =>\n  value ?? raise(\"Value cannot be undefined\")\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/project/project1/src/untested.ts",
    "content": "export function untested() {\n\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/project/project1/test/id.test.ts",
    "content": "import { expect, test } from 'vitest';\nimport { id } from '../src/id';\n\ntest('returns identity value', () => {\n  expect(id(1)).toBe(1);\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/project/project2/src/konst.ts",
    "content": "import { raise } from \"../../shared/src/utils\"\n\nexport const konst = <T>(value: T) => {\n  value ??= raise(\"Value cannot be undefined\")\n  return () => value\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/project/project2/src/untested.ts",
    "content": "export function untested() {\n\n}\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/project/project2/test/konst.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { konst } from '../src/konst'\n\ntest('returns function that returns constant value', () => {\n  const fn = konst(1)\n\n  expect(fn()).toBe(1);\n})\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/project/shared/src/utils.ts",
    "content": "function raise(error: string): never\nfunction raise(error: Error): never\nfunction raise(error: Error | string): never {\n  if (typeof error === 'string') {\n    throw new Error(error)\n  } else {\n    throw error\n  }\n}\n\nexport { raise }\n"
  },
  {
    "path": "test/coverage-test/fixtures/workspaces/project/shared/test/utils.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { raise } from '../src/utils'\n\ntest('raise throws error', () => {\n  const message = 'Value cannot be undefined'\n  expect(() => raise(message)).toThrow(message)\n})\n"
  },
  {
    "path": "test/coverage-test/package.json",
    "content": "{\n  \"name\": \"@vitest/test-coverage\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"vitest\"\n  },\n  \"devDependencies\": {\n    \"@jridgewell/remapping\": \"catalog:\",\n    \"@types/istanbul-lib-coverage\": \"catalog:\",\n    \"@types/istanbul-lib-report\": \"catalog:\",\n    \"@vitejs/plugin-vue\": \"latest\",\n    \"@vitest/browser-playwright\": \"workspace:*\",\n    \"@vitest/cjs-lib\": \"file:../browser/cjs-lib\",\n    \"@vitest/coverage-istanbul\": \"workspace:*\",\n    \"@vitest/coverage-v8\": \"workspace:*\",\n    \"@vitest/utils\": \"workspace:*\",\n    \"@vitest/web-worker\": \"workspace:*\",\n    \"@vue/test-utils\": \"latest\",\n    \"happy-dom\": \"latest\",\n    \"istanbul-lib-coverage\": \"catalog:\",\n    \"istanbul-lib-report\": \"catalog:\",\n    \"magic-string\": \"^0.30.21\",\n    \"magicast\": \"^0.5.2\",\n    \"sass-embedded\": \"^1.97.3\",\n    \"unplugin-swc\": \"^1.5.9\",\n    \"vite\": \"latest\",\n    \"vitest\": \"workspace:*\",\n    \"vue\": \"catalog:\"\n  }\n}\n"
  },
  {
    "path": "test/coverage-test/setup.native.ts",
    "content": "if (globalThis.process?.env.VITE_MODULE_RUNNER === 'false') {\n  const { registerHooks } = await import('node:module')\n\n  registerHooks({\n    resolve(specifier, context, nextResolve) {\n      if (context.parentURL && specifier.startsWith('.') && !/\\.[a-z]+$/.test(specifier) && !context.parentURL.includes('/node_modules/')) {\n        specifier += '.ts'\n      }\n\n      return nextResolve(specifier, context)\n    },\n  })\n}\n\nexport {}\n"
  },
  {
    "path": "test/coverage-test/setup.ts",
    "content": "import type { CoverageMap, FileCoverage } from 'istanbul-lib-coverage'\nimport { expect } from 'vitest'\nimport { formatSummary } from './utils'\n\nexpect.addSnapshotSerializer({\n  test: val => val.constructor?.name === 'CoverageMap',\n  serialize: (val: CoverageMap, config, indentation, depth, refs, printer) => {\n    return printer(formatSummary(val.getCoverageSummary()), config, indentation, depth, refs)\n  },\n})\n\nexpect.addSnapshotSerializer({\n  test: val => val.constructor?.name === 'FileCoverage',\n  serialize: (val: FileCoverage, config, indentation, depth, refs, printer) => {\n    return printer(formatSummary(val.toSummary()), config, indentation, depth, refs)\n  },\n})\n\nexpect.addSnapshotSerializer({\n  test: val => Array.isArray(val) && val.every(entry => entry.constructor.name === 'FileCoverage'),\n  serialize: (val: FileCoverage[], config, indentation, depth, refs, printer) => {\n    const summary = val.reduce((all, current) => ({\n      ...all,\n      [current.path]: formatSummary(current.toSummary()),\n    }), {})\n\n    return printer(summary, config, indentation, depth, refs)\n  },\n})\n"
  },
  {
    "path": "test/coverage-test/test/allow-external.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('{ allowExternal: true } includes files outside project root', async () => {\n  await runVitest({\n    include: ['fixtures/test/allow-external-fixture.test.ts'],\n    coverage: {\n      allowExternal: true,\n      reporter: 'json',\n      include: [\n        '**/fixtures/src/math.ts',\n        '**/fixtures/external-math.ts',\n      ],\n    },\n  })\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  // File outside project root\n  expect(files).toContain('<project-root>/test/test-utils/fixtures/external-math.ts')\n\n  // Files inside project root should always be included\n  expect(files).toContain('<process-cwd>/fixtures/src/math.ts')\n})\n\ntest('{ allowExternal: false } excludes files outside project root', async () => {\n  await runVitest({\n    include: ['fixtures/test/allow-external-fixture.test.ts'],\n    coverage: {\n      allowExternal: false,\n      reporter: 'json',\n      include: [\n        '**/fixtures/src/math.ts',\n        '**/fixtures/external-math.ts',\n      ],\n    },\n  })\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  // File outside project root\n  expect(files.find(file => file.includes('test-utils/fixtures/external-math.ts'))).toBeFalsy()\n\n  // Files inside project root should always be included\n  expect(files).toContain('<process-cwd>/fixtures/src/math.ts')\n})\n"
  },
  {
    "path": "test/coverage-test/test/bundled-sources.test.ts",
    "content": "import libCoverage from 'istanbul-lib-coverage'\nimport { expect } from 'vitest'\nimport * as transpiled from '../fixtures/src/pre-bundle/bundle.js'\nimport { coverageTest, formatSummary, normalizeURL, readCoverageJson, runVitest, test } from '../utils'\n\ntest('bundled code with source maps to originals', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      reporter: 'json',\n      exclude: ['./utils.ts'],\n    },\n  })\n\n  const coverageJson = await readCoverageJson()\n  const coverageMap = libCoverage.createCoverageMap(coverageJson)\n\n  // bundle.ts/bundle.js should not be included\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/pre-bundle/first.ts\",\n      \"<process-cwd>/fixtures/src/pre-bundle/second.ts\",\n    ]\n  `)\n\n  const first = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/pre-bundle/first.ts')\n  const second = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/pre-bundle/second.ts')\n\n  const summary = {\n    [first.path]: formatSummary(first.toSummary()),\n    [second.path]: formatSummary(second.toSummary()),\n  }\n\n  expect(summary).toMatchInlineSnapshot(`\n    {\n      \"<process-cwd>/fixtures/src/pre-bundle/first.ts\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"1/2 (50%)\",\n        \"lines\": \"1/2 (50%)\",\n        \"statements\": \"1/2 (50%)\",\n      },\n      \"<process-cwd>/fixtures/src/pre-bundle/second.ts\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"1/2 (50%)\",\n        \"lines\": \"1/2 (50%)\",\n        \"statements\": \"1/2 (50%)\",\n      },\n    }\n  `)\n})\n\ncoverageTest('run bundled sources', () => {\n  expect(transpiled.first.covered).toBeTypeOf('function')\n  expect(transpiled.first.covered()).toBe('First')\n\n  expect(transpiled.second.covered).toBeTypeOf('function')\n  expect(transpiled.second.covered()).toBe('Second')\n})\n"
  },
  {
    "path": "test/coverage-test/test/changed.test.ts",
    "content": "import { readFileSync, rmSync, writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { beforeAll, expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\n// Note that this test may fail if you have new files in \"vitest/test/coverage/src\"\n// and have not yet committed those\nconst SKIP = !!process.env.ECOSYSTEM_CI || !process.env.GITHUB_ACTIONS\n\nconst FILE_TO_CHANGE = resolve('./fixtures/src/file-to-change.ts')\nconst NEW_UNCOVERED_FILE = resolve('./fixtures/src/new-uncovered-file.ts')\n\nbeforeAll(() => {\n  const original = readFileSync(FILE_TO_CHANGE, 'utf8')\n  const changed = original.replace('This file will be modified by test cases', 'Changed!')\n  writeFileSync(FILE_TO_CHANGE, changed, 'utf8')\n\n  writeFileSync(NEW_UNCOVERED_FILE, `\n  // This file is not covered by any tests but should be picked by --changed\n  export default function helloworld() {\n    return 'Hello world'\n  }\n  `.trim(), 'utf8')\n\n  return function restore() {\n    writeFileSync(FILE_TO_CHANGE, original, 'utf8')\n    rmSync(NEW_UNCOVERED_FILE)\n  }\n})\n\ntest('{ changed: \"HEAD\" }', { skip: SKIP }, async () => {\n  await runVitest({\n    include: ['fixtures/test/**'],\n    exclude: ['**/custom-1-syntax**'],\n    changed: 'HEAD',\n    coverage: {\n      include: ['fixtures/src/**'],\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/file-to-change.ts\",\n      \"<process-cwd>/fixtures/src/new-uncovered-file.ts\",\n    ]\n  `)\n\n  const uncoveredFile = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/new-uncovered-file.ts')\n  const changedFile = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/file-to-change.ts')\n\n  expect([uncoveredFile, changedFile]).toMatchInlineSnapshot(`\n    {\n      \"<process-cwd>/fixtures/src/file-to-change.ts\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"1/2 (50%)\",\n        \"lines\": \"1/2 (50%)\",\n        \"statements\": \"1/2 (50%)\",\n      },\n      \"<process-cwd>/fixtures/src/new-uncovered-file.ts\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"0/1 (0%)\",\n        \"lines\": \"0/1 (0%)\",\n        \"statements\": \"0/1 (0%)\",\n      },\n    }\n  `)\n})\n\ntest('{ coverage.changed: \"HEAD\" }', async () => {\n  await runVitest({\n    include: [\n      'fixtures/test/file-to-change.test.ts',\n      'fixtures/test/math.test.ts',\n    ],\n    coverage: {\n      include: [\n        'fixtures/src/file-to-change.ts',\n        'fixtures/src/new-uncovered-file.ts',\n\n        // Should not show up\n        'fixtures/src/untested-file.ts',\n        'fixtures/src/math.ts',\n      ],\n      reporter: 'json',\n      changed: 'HEAD',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/file-to-change.ts\",\n      \"<process-cwd>/fixtures/src/new-uncovered-file.ts\",\n    ]\n  `)\n})\n\ntest('{ coverage.changed: \"HEAD\", excludeAfterRemap: true }', async () => {\n  await runVitest({\n    include: [\n      'fixtures/test/file-to-change.test.ts',\n      'fixtures/test/math.test.ts',\n    ],\n    coverage: {\n      include: [\n        'fixtures/src/file-to-change.ts',\n        'fixtures/src/new-uncovered-file.ts',\n\n        // Should not show up\n        'fixtures/src/untested-file.ts',\n        'fixtures/src/math.ts',\n      ],\n      reporter: 'json',\n      changed: 'HEAD',\n      excludeAfterRemap: true,\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/file-to-change.ts\",\n      \"<process-cwd>/fixtures/src/new-uncovered-file.ts\",\n    ]\n  `)\n})\n\ntest('{ changed: \"v0.0.1\", coverage.changed: \"HEAD\" }', async () => {\n  await runVitest({\n    include: [\n      'fixtures/test/file-to-change.test.ts',\n      'fixtures/test/math.test.ts',\n    ],\n\n    // v0.0.1 is an actual git tag in Vitest repository\n    changed: 'v0.0.1',\n\n    coverage: {\n      include: [\n        'fixtures/src/file-to-change.ts',\n        'fixtures/src/new-uncovered-file.ts',\n\n        // Should not show up\n        'fixtures/src/untested-file.ts',\n        'fixtures/src/math.ts',\n      ],\n      reporter: 'json',\n      changed: 'HEAD',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n\n  // Should show changes since HEAD, not v0.0.1\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/file-to-change.ts\",\n      \"<process-cwd>/fixtures/src/new-uncovered-file.ts\",\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/cjs-dependency.test.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('excludes Vite transforms done for CJS dependency', async () => {\n  await runVitest({\n    include: ['fixtures/test/cjs-dependency.test.ts'],\n    coverage: {\n      reporter: 'json',\n    },\n  }, undefined, {\n    cacheDir: fileURLToPath(new URL('./node_modules/.vite', import.meta.url)),\n    optimizeDeps: { include: ['@vitest/cjs-lib', '/Users/ari/Git/vitest/test/browser/cjs-lib'] },\n  })\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/cjs-dependency.ts\",\n    ]\n  `)\n\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/cjs-dependency.ts')\n\n  // There should be 0 branches (#8717)\n  expect(Object.keys(fileCoverage.b)).toHaveLength(0)\n  expect(Object.keys(fileCoverage.branchMap)).toHaveLength(0)\n})\n"
  },
  {
    "path": "test/coverage-test/test/clean-on-rerun.test.ts",
    "content": "import { readFileSync, writeFileSync } from 'node:fs'\nimport { beforeEach, expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\nconst FIXTURE = 'fixtures/test/clean-on-rerun-fixture.test.ts'\n\nbeforeEach(() => {\n  const original = readFileSync(FIXTURE, 'utf8')\n  return () => writeFileSync(FIXTURE, original, 'utf8')\n})\n\ntest('{ cleanOnReRun: false } should invalidate and preserve previous coverage', async () => {\n  const { waitForRun } = await startWatchMode({ cleanOnRerun: false })\n\n  // Initially only \"sum\" should be covered\n  expect(await getFunctionCoverageCounts('math.ts')).toMatchInlineSnapshot(`\n    {\n      \"sum\": 1,\n    }\n  `)\n  expect(await getFunctionCoverageCounts('even.ts')).toMatchInlineSnapshot(`\n    {\n      \"isEven\": 1,\n    }\n  `)\n  expect(await getReportedFiles()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/math.ts\",\n      \"<process-cwd>/fixtures/src/untested-file.ts\",\n    ]\n  `)\n\n  // Change test file to cover \"multiply\" only\n  await waitForRun(() => editTestFile('multiply'))\n\n  // Sum should not be covered. Multiply should be.\n  expect(await getFunctionCoverageCounts('math.ts')).toMatchInlineSnapshot(`\n    {\n      \"multiply\": 1,\n    }\n  `)\n  // Results of non-changed file should preserve\n  expect(await getFunctionCoverageCounts('even.ts')).toMatchInlineSnapshot(`\n    {\n      \"isEven\": 1,\n    }\n  `)\n  // Untested file should still be in the report\n  expect(await getReportedFiles()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/math.ts\",\n      \"<process-cwd>/fixtures/src/untested-file.ts\",\n    ]\n  `)\n\n  // Change test file to cover \"subtract\" only\n  await waitForRun(() => editTestFile('subtract'))\n\n  // Sum and multiply should not be covered. Subtract should be.\n  expect(await getFunctionCoverageCounts('math.ts')).toMatchInlineSnapshot(`\n    {\n      \"subtract\": 1,\n    }\n  `)\n  // Results of non-changed file should preserve\n  expect(await getFunctionCoverageCounts('even.ts')).toMatchInlineSnapshot(`\n    {\n      \"isEven\": 1,\n    }\n  `)\n  // Untested file should still be in the report\n  expect(await getReportedFiles()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/math.ts\",\n      \"<process-cwd>/fixtures/src/untested-file.ts\",\n    ]\n  `)\n})\n\ntest('{ cleanOnReRun: true } remove previous coverage results', async () => {\n  const { waitForRun } = await startWatchMode({ cleanOnRerun: true })\n\n  // Initially only \"sum\" should be covered\n  expect(await getFunctionCoverageCounts('math.ts')).toMatchInlineSnapshot(`\n    {\n      \"sum\": 1,\n    }\n  `)\n  // All files should be in report\n  expect(await getReportedFiles()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/math.ts\",\n      \"<process-cwd>/fixtures/src/untested-file.ts\",\n    ]\n  `)\n\n  // Change test file to cover \"multiply\" only\n  await waitForRun(() => editTestFile('multiply'))\n\n  // Sum should not be covered. Multiply should be.\n  expect(await getFunctionCoverageCounts('math.ts')).toMatchInlineSnapshot(`\n    {\n      \"multiply\": 1,\n    }\n  `)\n  // Previous results should be removed, only math.ts should be present in report\n  expect(await getReportedFiles()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/math.ts\",\n    ]\n  `)\n})\n\nasync function startWatchMode(options: { cleanOnRerun: boolean }) {\n  const { vitest, ctx } = await runVitest({\n    watch: true,\n    include: [FIXTURE, 'fixtures/test/even.test.ts'],\n    coverage: {\n      include: [\n        'fixtures/src/math.ts',\n        'fixtures/src/even.ts',\n        'fixtures/src/untested-file.ts',\n      ],\n      reporter: 'json',\n      ...options,\n    },\n  })\n\n  async function waitForRun(method: () => void) {\n    vitest.resetOutput()\n    method()\n    await vitest.waitForStdout('1 passed')\n    await ctx?.runningPromise\n  }\n\n  return { waitForRun }\n}\n\nasync function getFunctionCoverageCounts(file: 'math.ts' | 'even.ts') {\n  const coverageMap = await readCoverageMap()\n  const fileCoverage = coverageMap.fileCoverageFor(`<process-cwd>/fixtures/src/${file}`)\n\n  return Object.entries(fileCoverage.fnMap).reduce((total, [key, data]) => ({\n    ...total,\n    ...(fileCoverage.f[key] ? { [data.name]: fileCoverage.f[key] } : {}),\n\n  }), {} as Record<'sum' | 'subtract' | 'multiply' | 'remainder', number>)\n}\n\nasync function getReportedFiles() {\n  const coverageMap = await readCoverageMap()\n  return coverageMap.files()\n}\n\nfunction editTestFile(method: 'sum' | 'subtract' | 'multiply' | 'remainder') {\n  let content = readFileSync(FIXTURE, 'utf8')\n  content = content.replace(/(const methodToTest = )'(.*)'/, `$1'${method}'`)\n  writeFileSync(FIXTURE, content, 'utf8')\n}\n"
  },
  {
    "path": "test/coverage-test/test/configuration-options.test-d.ts",
    "content": "import type { defineConfig } from 'vitest/config'\nimport type { CoverageProviderModule, ResolvedCoverageOptions, Vitest } from 'vitest/node'\nimport { assertType, test } from 'vitest'\n\ntype NarrowToTestConfig<T> = T extends { test?: any } ? NonNullable<T['test']> : never\ntype Configuration = NarrowToTestConfig<(Parameters<typeof defineConfig>[0])>\ntype Coverage = NonNullable<Configuration['coverage']>\n\ntest('providers, built-in', () => {\n  assertType<Coverage>({ provider: 'v8' })\n  assertType<Coverage>({ provider: 'istanbul' })\n\n  // @ts-expect-error -- String options must be known ones only\n  assertType<Coverage>({ provider: 'unknown-provider' })\n})\n\ntest('providers, custom', () => {\n  assertType<Coverage>({\n    provider: 'custom',\n    customProviderModule: 'custom-provider-module.ts',\n  })\n})\n\ntest('provider options, generic', () => {\n  assertType<Coverage>({\n    provider: 'v8',\n    enabled: true,\n    include: ['string'],\n    watermarks: {\n      functions: [80, 95],\n      lines: [80, 95],\n    },\n    thresholds: {\n      '100': true,\n      'lines': 1,\n      'autoUpdate': true,\n      'perFile': true,\n      'statements': 100,\n\n      '**/some-file.ts': {\n        100: true,\n        lines: 12,\n        branches: 12,\n        functions: 12,\n        statements: 12,\n      },\n    },\n  })\n\n  assertType<Coverage>({\n    provider: 'istanbul',\n    enabled: true,\n    include: ['string'],\n    watermarks: {\n      statements: [80, 95],\n    },\n    thresholds: {\n      '100': false,\n      'lines': 1,\n      'autoUpdate': true,\n      'perFile': true,\n      'statements': 100,\n\n      '**/some-file.ts': {\n        100: false,\n        lines: 12,\n        branches: 12,\n        functions: 12,\n        statements: 12,\n      },\n    },\n  })\n})\n\ntest('provider specific options, custom', () => {\n  assertType<Coverage>({\n    provider: 'custom',\n    customProviderModule: 'custom-provider-module.ts',\n    enabled: true,\n  })\n\n  // @ts-expect-error --  customProviderModule is required\n  assertType<Coverage>({ provider: 'custom' })\n\n  assertType<Coverage>({\n    provider: 'custom',\n    customProviderModule: 'some-module',\n\n    // @ts-expect-error --  typings of BaseCoverageOptions still apply\n    enabled: 'not boolean',\n  })\n})\n\ntest('provider module', () => {\n  assertType<CoverageProviderModule>({\n    getProvider() {\n      return {\n        name: 'custom-provider',\n        initialize(_: Vitest) {},\n        generateCoverage() {},\n        resolveOptions(): ResolvedCoverageOptions {\n          return {\n            clean: true,\n            cleanOnRerun: true,\n            enabled: true,\n            exclude: ['string'],\n            reporter: [['html', {}], ['json', { file: 'string' }]],\n            reportsDirectory: 'string',\n            reportOnFailure: true,\n            allowExternal: true,\n            processingConcurrency: 1,\n          }\n        },\n        clean(_?: boolean) {},\n        onBeforeFilesRun() {},\n        onAfterSuiteRun({ coverage: _coverage }) {},\n        reportCoverage() {},\n        onFileTransform(_code: string, _id: string, ctx) {\n          ctx.getCombinedSourcemap()\n        },\n      }\n    },\n    takeCoverage() {},\n    startCoverage() {},\n    stopCoverage() {},\n  })\n})\n\ntest('reporters, single', () => {\n  assertType<Coverage>({ reporter: 'clover' })\n  assertType<Coverage>({ reporter: 'cobertura' })\n  assertType<Coverage>({ reporter: 'html-spa' })\n  assertType<Coverage>({ reporter: 'html' })\n  assertType<Coverage>({ reporter: 'json-summary' })\n  assertType<Coverage>({ reporter: 'json' })\n  assertType<Coverage>({ reporter: 'lcov' })\n  assertType<Coverage>({ reporter: 'lcovonly' })\n  assertType<Coverage>({ reporter: 'none' })\n  assertType<Coverage>({ reporter: 'teamcity' })\n  assertType<Coverage>({ reporter: 'text-lcov' })\n  assertType<Coverage>({ reporter: 'text-summary' })\n  assertType<Coverage>({ reporter: 'text' })\n  assertType<Coverage>({ reporter: 'custom-reporter' })\n})\n\ntest('reporters, multiple', () => {\n  assertType<Coverage>({\n    reporter: [\n      'clover',\n      'cobertura',\n      'html-spa',\n      'html',\n      'json-summary',\n      'json',\n      'lcov',\n      'lcovonly',\n      'none',\n      'teamcity',\n      'text-lcov',\n      'text-summary',\n      'text',\n    ],\n  })\n\n  assertType<Coverage>({ reporter: ['custom-reporter'] })\n  assertType<Coverage>({ reporter: ['html', 'json', 'custom-reporter'] })\n})\n\ntest('reporters, with options', () => {\n  assertType<Coverage>({\n    reporter: [\n      ['clover', { projectRoot: 'string', file: 'string' }],\n      ['cobertura', { projectRoot: 'string', file: 'string' }],\n      ['html-spa', { metricsToShow: ['branches', 'functions'], verbose: true, subdir: 'string' }],\n      ['html', { verbose: true, subdir: 'string' }],\n      ['json-summary', { file: 'string' }],\n      ['json', { file: 'string' }],\n      ['lcov', { projectRoot: 'string', file: 'string' }],\n      ['lcovonly', { projectRoot: 'string', file: 'string' }],\n      ['none'],\n      ['teamcity', { blockName: 'string' }],\n      ['text-lcov', { projectRoot: 'string' }],\n      ['text-summary', { file: 'string' }],\n      ['text', { skipEmpty: true, skipFull: true, maxCols: 1 }],\n      ['custom-reporter', { 'someOption': true, 'some-other-custom-option': { width: 123 } }],\n    ],\n  })\n\n  assertType<Coverage>({\n    reporter: [\n      ['html', { subdir: 'string' }],\n      ['json'],\n      ['lcov', { projectRoot: 'string' }],\n    ],\n  })\n\n  assertType<Coverage>({\n    reporter: [\n      // @ts-expect-error -- second value should be object even though TS intellisense prompts types of reporters\n      ['lcov', 'html-spa'],\n    ],\n  })\n})\n\ntest('reporters, mixed variations', () => {\n  assertType<Coverage>({\n    reporter: [\n      'clover',\n      'custom-reporter-1',\n      ['cobertura'],\n      ['custom-reporter-2'],\n      ['html-spa', {}],\n      ['custom-reporter-3', {}],\n      ['html', { verbose: true, subdir: 'string' }],\n      ['custom-reporter-4', { some: 'option', width: 123 }],\n    ],\n  })\n})\n"
  },
  {
    "path": "test/coverage-test/test/custom-provider.custom.test.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { expect } from 'vitest'\nimport { runVitest, test } from '../utils'\n\ntest('custom provider', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n  })\n\n  const report = readFileSync('./coverage/custom-coverage-provider-report.json', 'utf-8')\n\n  expect(report).toMatchInlineSnapshot(`\n    \"{\n      \"calls\": [\n        \"initialized with context\",\n        \"resolveOptions\",\n        \"clean with force\",\n        \"onAfterSuiteRun\",\n        \"reportCoverage with {\\\\\"allTestsRun\\\\\":true}\"\n      ],\n      \"coverageReports\": [\n        \"{\\\\\"coverage\\\\\":{\\\\\"customCoverage\\\\\":\\\\\"Coverage report passed from workers to main thread\\\\\"},\\\\\"testFiles\\\\\":[\\\\\"fixtures/test/even.test.ts\\\\\"],\\\\\"environment\\\\\":\\\\\"ssr\\\\\",\\\\\"projectName\\\\\":\\\\\"\\\\\"}\",\n        \"{\\\\\"coverage\\\\\":{\\\\\"customCoverage\\\\\":\\\\\"Coverage report passed from workers to main thread\\\\\"},\\\\\"testFiles\\\\\":[\\\\\"fixtures/test/math.test.ts\\\\\"],\\\\\"environment\\\\\":\\\\\"ssr\\\\\",\\\\\"projectName\\\\\":\\\\\"\\\\\"}\"\n      ],\n      \"transformedFiles\": [\n        \"<process-cwd>/fixtures/src/even.ts\",\n        \"<process-cwd>/fixtures/src/math.ts\"\n      ]\n    }\"\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/custom-reporter.test.ts",
    "content": "import { readdirSync, readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { expect } from 'vitest'\nimport { sum } from '../fixtures/src/math'\nimport { coverageTest, normalizeURL, runVitest, test } from '../utils'\n\ntest('custom reporter', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      reporter: [\n        [resolve('fixtures/custom-reporter.cjs'), { file: 'custom-reporter-output.md' }],\n      ],\n    },\n  })\n\n  const coveragePath = resolve('./coverage')\n  const files = readdirSync(coveragePath)\n\n  expect(files).toContain('custom-reporter-output.md')\n\n  const content = readFileSync(resolve(coveragePath, 'custom-reporter-output.md'), 'utf-8')\n  expect(content).toMatchInlineSnapshot(`\n    \"Start of custom coverage report\n    End of custom coverage report\n    \"\n  `)\n})\n\ncoverageTest('cover some lines', () => {\n  expect(sum(2, 5)).toBe(7)\n})\n"
  },
  {
    "path": "test/coverage-test/test/decorators.test.ts",
    "content": "import { expect, vi } from 'vitest'\nimport { rolldownVersion } from 'vitest/node'\nimport { DecoratorsTester } from '../fixtures/src/decorators'\nimport { coverageTest, normalizeURL, readCoverageMap, runVitest, test } from '../utils'\n\ntest('decorators generated metadata is ignored', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    config: 'fixtures/configs/vitest.config.decorators.ts',\n    coverage: { reporter: 'json' },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/decorators.ts')\n  const lineCoverage = fileCoverage.getLineCoverage()\n  const branchCoverage = fileCoverage.getBranchCoverageByLine()\n\n  expect.soft(lineCoverage['4']).toBeUndefined()\n  expect.soft(branchCoverage['4']).toBeUndefined()\n\n  // Covered branch should be marked correctly\n  expect.soft(lineCoverage['7']).toBe(1)\n\n  // Uncovered branch should be marked correctly\n  expect.soft(lineCoverage['12']).toBe(0)\n})\n\ntest('decorators generated metadata is covered with OXC decorators', async ({ onTestFinished }) => {\n  if (!rolldownVersion) {\n    return\n  }\n\n  vi.stubEnv('TEST_OXC_DECORATOR', 'true')\n  onTestFinished(() => {\n    vi.unstubAllEnvs()\n  })\n\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    config: 'fixtures/configs/vitest.config.decorators.ts',\n    coverage: { reporter: ['json', 'html'] },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/decorators.ts')\n  const lineCoverage = fileCoverage.getLineCoverage()\n  const branchCoverage = fileCoverage.getBranchCoverageByLine()\n\n  expect.soft(lineCoverage['4']).toBe(1) // this is different from SWC case above\n  expect.soft(branchCoverage['4']).toBeUndefined()\n\n  // Covered branch should be marked correctly\n  expect.soft(lineCoverage['7']).toBe(1)\n\n  // Uncovered branch should be marked correctly\n  expect.soft(lineCoverage['12']).toBe(0)\n})\n\ncoverageTest('cover decorators', () => {\n  new DecoratorsTester().method('cover line')\n})\n"
  },
  {
    "path": "test/coverage-test/test/dynamic-files.test.ts",
    "content": "import { expect } from 'vitest'\nimport { runDynamicFileCJS, runDynamicFileESM } from '../fixtures/src/dynamic-files'\nimport { coverageTest, normalizeURL, readCoverageMap, runVitest, test } from '../utils'\n\ntest('does not crash when files are created and removed during test run (#3657)', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: { reporter: 'json' },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).toContain('<process-cwd>/fixtures/src/dynamic-files.ts')\n})\n\ncoverageTest('run dynamic ESM file', async () => {\n  await expect(runDynamicFileESM()).resolves.toBe('Done')\n})\n\ncoverageTest('run dynamic CJS file', async () => {\n  await expect(runDynamicFileCJS()).resolves.toBe('Done')\n})\n"
  },
  {
    "path": "test/coverage-test/test/empty-coverage-directory.test.ts",
    "content": "import { existsSync } from 'node:fs'\nimport { beforeEach, expect } from 'vitest'\nimport { sum } from '../fixtures/src/math'\nimport { captureStdout, coverageTest, normalizeURL, runVitest, test } from '../utils'\n\nbeforeEach(() => {\n  return captureStdout()\n})\n\ntest('empty coverage directory is cleaned after tests', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    testNamePattern: 'passing test',\n    coverage: { reporter: 'text' },\n  })\n\n  expect(existsSync('./coverage')).toBe(false)\n})\n\ntest('empty coverage directory is cleaned after failing test run', async () => {\n  const { exitCode } = await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    testNamePattern: 'failing test',\n    coverage: { reporter: 'text' },\n  }, { throwOnError: false })\n\n  expect(existsSync('./coverage')).toBe(false)\n  expect(exitCode).toBe(1)\n})\n\ncoverageTest('passing test', () => {\n  expect(sum(2, 3)).toBe(5)\n})\n\ncoverageTest('failing test', () => {\n  expect(sum(2, 3)).toBe(6)\n})\n"
  },
  {
    "path": "test/coverage-test/test/exclude-after-remap.test.ts",
    "content": "import { expect } from 'vitest'\nimport * as transpiled from '../fixtures/src/pre-bundle/bundle.js'\nimport { coverageTest, normalizeURL, readCoverageMap, runVitest, test } from '../utils'\n\ntest('{ excludeAfterRemap: true } should exclude files that come up after remapping', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      exclude: ['fixtures/src/pre-bundle/second.ts', './utils.ts'],\n      excludeAfterRemap: true,\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/pre-bundle/first.ts\",\n    ]\n  `)\n})\n\ntest('{ excludeAfterRemap: false } should not exclude files that come up after remapping', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      exclude: ['fixtures/src/pre-bundle/second.ts', './utils.ts'],\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/pre-bundle/first.ts\",\n      \"<process-cwd>/fixtures/src/pre-bundle/second.ts\",\n    ]\n  `)\n})\n\ntest('{ excludeAfterRemap: true } should exclude uncovered files that come up after remapping', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts'],\n    coverage: {\n      include: ['fixtures/src/pre-bundle/**.ts'],\n      exclude: ['fixtures/src/pre-bundle/second.ts'],\n      excludeAfterRemap: true,\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).contains('<process-cwd>/fixtures/src/pre-bundle/first.ts')\n  expect(files).not.contains('<process-cwd>/fixtures/src/pre-bundle/second.ts')\n})\n\ncoverageTest('run bundled sources', () => {\n  expect(transpiled.first.covered()).toBe('First')\n  expect(transpiled.second.covered()).toBe('Second')\n})\n"
  },
  {
    "path": "test/coverage-test/test/file-outside-vite.test.ts",
    "content": "import { createRequire } from 'node:module'\nimport { expect } from 'vitest'\nimport { coverageTest, isV8Provider, normalizeURL, readCoverageMap, runVitest, test } from '../utils'\n\ntest('does not crash when file outside Vite is loaded (#5639)', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: { reporter: 'json', include: ['fixtures/src/load-outside-vite.cjs'] },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/load-outside-vite.cjs')\n\n  if (isV8Provider()) {\n    expect(fileCoverage).toMatchInlineSnapshot(`\n      {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"0/1 (0%)\",\n        \"lines\": \"1/1 (100%)\",\n        \"statements\": \"1/1 (100%)\",\n      }\n    `)\n  }\n  else {\n    // On istanbul the instrumentation happens on Vite plugin, so files\n    // loaded outsite Vite should have 0% coverage\n    expect(fileCoverage).toMatchInlineSnapshot(`\n      {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"0/1 (0%)\",\n        \"lines\": \"0/1 (0%)\",\n        \"statements\": \"0/1 (0%)\",\n      }\n    `)\n  }\n})\n\ncoverageTest('load file using require so it\\'s not intercepted by Vite', () => {\n  const noop = createRequire(import.meta.url)('../fixtures/src/load-outside-vite.cjs')\n\n  expect(noop).toBeTypeOf('function')\n})\n"
  },
  {
    "path": "test/coverage-test/test/ignore-hints.test.ts",
    "content": "/*\n * Ignore hints are implemented by 3rd party packages but there's\n * Vitest related logic (esbuild) that makes them work.\n*/\n\nimport { expect } from 'vitest'\nimport { isV8Provider, readCoverageMap, runVitest, test } from '../utils'\n\ntest('ignore hints work', async () => {\n  await runVitest({\n    include: ['fixtures/test/ignore-hints-fixture.test.ts'],\n    coverage: { reporter: 'json' },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/ignore-hints.ts')\n  const lines = fileCoverage.getLineCoverage()\n\n  // Covered\n  expect(lines[8]).toBeGreaterThanOrEqual(1)\n  expect(lines[22]).toBeGreaterThanOrEqual(1)\n  expect(lines[30]).toBeGreaterThanOrEqual(1)\n\n  // Ignored start+end lines\n  expect(lines[11]).toBeUndefined()\n  expect(lines[12]).toBeUndefined()\n  expect(lines[13]).toBeUndefined()\n  expect(lines[14]).toBeUndefined()\n  expect(lines[15]).toBeUndefined()\n  expect(lines[16]).toBeUndefined()\n  expect(lines[17]).toBeUndefined()\n  expect(lines[18]).toBeUndefined()\n  expect(lines[19]).toBeUndefined()\n\n  // Ignore istanbul\n  expect(lines[28]).toBeUndefined()\n\n  // Line 25 = Ignore v8\n  if (isV8Provider()) {\n    expect(lines[25]).toBeUndefined()\n  }\n  else {\n    expect(lines[25]).toBeGreaterThanOrEqual(1)\n  }\n})\n"
  },
  {
    "path": "test/coverage-test/test/implicit-else.istanbul.test.ts",
    "content": "import { expect } from 'vitest'\nimport { implicitElse } from '../fixtures/src/implicit-else'\nimport { coverageTest, normalizeURL, readCoverageMap, runVitest, test } from '../utils'\n\ntest('implicit else is included in branch count', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: { reporter: 'json' },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/implicit-else.ts')\n\n  expect(fileCoverage.b).toHaveProperty('0')\n  expect(fileCoverage.b['0']).toHaveLength(2)\n})\n\ncoverageTest('cover if branch', () => {\n  expect(implicitElse(true)).toBe(2)\n})\n"
  },
  {
    "path": "test/coverage-test/test/import-attributes.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('import attributes work', async () => {\n  await runVitest({\n    include: ['fixtures/test/import-attributes-fixture.test.ts'],\n    coverage: { reporter: 'json', exclude: ['**.json'] },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/json-data-import.ts\",\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/import-meta-env.test.ts",
    "content": "import { expect } from 'vitest'\nimport { useImportEnv } from '../fixtures/src/import-meta-env'\nimport { coverageTest, normalizeURL, readCoverageMap, runVitest, test } from '../utils'\n\ntest('file using import.meta.env is included in report (#2332)', async () => {\n  await runVitest(\n    {\n      include: [normalizeURL(import.meta.url)],\n      coverage: { reporter: 'json' },\n      env: { SOME_VARIABLE: 'some variable set here' },\n    },\n  )\n\n  const coverageMap = await readCoverageMap()\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/import-meta-env.ts')\n  const lines = fileCoverage.getLineCoverage()\n\n  expect(lines[3]).toBe(1)\n})\n\ncoverageTest('cover file that uses import.meta.env', () => {\n  expect(useImportEnv()).toBe('some variable set here')\n})\n"
  },
  {
    "path": "test/coverage-test/test/in-source.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('in-source tests work', async () => {\n  const { stdout } = await runVitest({\n    include: [],\n    includeSource: ['fixtures/src/in-source.ts'],\n    coverage: { reporter: 'json' },\n  })\n\n  expect(stdout).toContain('in source test running add function')\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/in-source.ts\",\n    ]\n  `)\n\n  const fileCoverage = coverageMap.fileCoverageFor(files[0])\n  const functions = Object.values(fileCoverage.fnMap).map(fn => fn.name)\n\n  // If-branch is not taken - makes sure source maps are correct in in-source testing too\n  expect(fileCoverage.getUncoveredLines()).toContain('5')\n\n  expect(fileCoverage).toMatchInlineSnapshot(`\n    {\n      \"branches\": \"2/4 (50%)\",\n      \"functions\": \"1/1 (100%)\",\n      \"lines\": \"2/3 (66.66%)\",\n      \"statements\": \"2/3 (66.66%)\",\n    }\n  `)\n\n  // The \"customNamedTestFunction\" should be excluded by auto-generated ignore hints\n  expect(functions).toMatchInlineSnapshot(`\n    [\n      \"add\",\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/include-exclude.test.ts",
    "content": "import assert from 'node:assert'\nimport { expect, onTestFinished, vi } from 'vitest'\nimport { cleanupCoverageJson, isBrowser, isNativeRunner, readCoverageMap, runVitest, test } from '../utils'\n\ntest('default include should show only covered files', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    coverage: {\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/math.ts\",\n    ]\n  `)\n})\n\ntest('changed include picks uncovered files', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts'],\n    coverage: {\n      reporter: 'json',\n      include: ['fixtures/src/math.ts', 'fixtures/src/untested-file.ts'],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/math.ts\",\n      \"<process-cwd>/fixtures/src/untested-file.ts\",\n    ]\n  `)\n})\n\ntest('include as glob', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    coverage: {\n      reporter: 'json',\n      include: ['**/{math,even}.ts'],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/math.ts\",\n    ]\n  `)\n})\n\ntest('changed include can exclude covered files', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    coverage: {\n      reporter: 'json',\n      include: ['fixtures/src/even.ts'],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n    ]\n  `)\n})\n\ntest('exclude can exclude covered files', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    coverage: {\n      reporter: 'json',\n      exclude: ['fixtures/src/math.ts'],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n    ]\n  `)\n})\n\ntest('exclude can exclude covered files #2', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    coverage: {\n      reporter: 'json',\n      include: ['fixtures/src/{math,even}.ts'],\n\n      // pattern that's recognized by picomatch but not by tinyglobby\n      exclude: ['math'],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n    ]\n  `)\n})\n\ntest('uncovered files are included after watch-mode re-run', async () => {\n  // to avoid printing coverage report to stdout\n  const stdout = vi.spyOn(process.stdout, 'write').mockImplementation(() => true)\n  onTestFinished(() => stdout.mockRestore())\n  const { vitest } = await runVitest({\n    watch: true,\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    coverage: {\n      include: [\n        'fixtures/src/math.ts',\n        'fixtures/src/even.ts',\n        'fixtures/src/untested-file.ts',\n      ],\n      reporter: ['json', 'text-summary'],\n    },\n  })\n\n  {\n    const coverageMap = await readCoverageMap()\n    const files = coverageMap.files()\n\n    expect(files).toContain('<process-cwd>/fixtures/src/untested-file.ts')\n    expect(files.length).toBeGreaterThanOrEqual(3)\n  }\n\n  await cleanupCoverageJson()\n\n  vitest.write('a')\n\n  await vitest.waitForStdout('RERUN')\n  await vitest.waitForStdout('rerun all tests')\n  await vitest.waitForStdout('Waiting for file changes')\n\n  // make sure coverage report is done, we need text output for this message to appear\n  await vitest.waitForStdout('Coverage report from')\n\n  {\n    const coverageMap = await vi.waitFor(() => readCoverageMap())\n    const files = coverageMap.files()\n\n    expect(files).toContain('<process-cwd>/fixtures/src/untested-file.ts')\n    expect(files.length).toBeGreaterThanOrEqual(3)\n  }\n})\n\ntest('test, setup and configuration files should never be shown', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts'],\n    setupFiles: ['fixtures/setup.ts'],\n    coverage: {\n      reporter: 'json',\n      include: [\n        'fixtures/src/math.ts',\n\n        // Should not appear on report even when defined\n        '**/fixtures/setup.ts',\n        '**/math.test.ts',\n        '**/vitest.config.ts',\n      ],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/math.ts\",\n    ]\n  `)\n})\n\ntest('workspace projects test, setup and configuration files should never be shown', async () => {\n  await runVitest({\n    coverage: {\n      reporter: 'json',\n      include: [\n        'fixtures/src/math.ts',\n        'fixtures/src/even.ts',\n\n        // Should not appear on report even when defined\n        '**/fixtures/setup.ts',\n        '**/math.test.ts',\n        '**/vitest.config.ts',\n      ],\n    },\n    projects: [\n      {\n        test: {\n          name: 'First',\n          include: ['fixtures/test/math.test.ts'],\n          setupFiles: ['fixtures/setup.ts'],\n        },\n      },\n      {\n        test: {\n          name: 'Second',\n          include: ['fixtures/test/even.test.ts'],\n        },\n      },\n    ],\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/math.ts\",\n    ]\n  `)\n})\n\ntest('overridden exclude should still apply defaults', async () => {\n  await runVitest({\n    include: [\n      'fixtures/test/math.test.ts',\n      'fixtures/src/test-that-looks-like-source-file.ts',\n    ],\n    coverage: {\n      reporter: 'json',\n      include: ['fixtures/test/math.test.ts'],\n      exclude: ['dont-match-anything'],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`{}`)\n})\n\ntest('uncovered files are transformed correctly (node and browser)', async ({ skip }) => {\n  skip(isNativeRunner(), 'native runner does not support plugins')\n\n  await runVitest({\n    config: 'fixtures/configs/vitest.config.conditional.ts',\n    include: ['fixtures/test/math.test.ts'],\n    coverage: {\n      include: ['fixtures/src/math.ts', 'fixtures/src/conditional/*'],\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  if (isBrowser()) {\n    expect(files).toMatchInlineSnapshot(`\n      [\n        \"<process-cwd>/fixtures/src/math.ts\",\n        \"<process-cwd>/fixtures/src/conditional/web.ts\",\n      ]\n    `)\n  }\n  else {\n    expect(files).toMatchInlineSnapshot(`\n      [\n        \"<process-cwd>/fixtures/src/math.ts\",\n        \"<process-cwd>/fixtures/src/conditional/ssr.ts\",\n      ]\n    `)\n  }\n})\n\ntest('uncovered files are transformed correctly (jsdom)', async ({ skip }) => {\n  skip(isBrowser(), 'node relevant test')\n  skip(isNativeRunner(), 'native runner does not support plugins')\n\n  await runVitest({\n    config: 'fixtures/configs/vitest.config.conditional.ts',\n    include: ['fixtures/test/math.test.ts'],\n    environment: 'jsdom',\n    coverage: {\n      include: ['fixtures/src/math.ts', 'fixtures/src/conditional/*'],\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).toMatchInlineSnapshot(`\n      [\n        \"<process-cwd>/fixtures/src/math.ts\",\n        \"<process-cwd>/fixtures/src/conditional/web.ts\",\n      ]\n    `)\n})\n\ntest('files included and excluded in plugin\\'s configureVitest are excluded', async ({ skip }) => {\n  skip(isNativeRunner(), 'native runner does not support plugins')\n\n  await runVitest({\n    config: 'fixtures/configs/vitest.config.configure-vitest-hook.ts',\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    coverage: {\n      // Include math.ts by default, exclude it in plugin config\n      include: ['**/math.ts'],\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/untested-file.ts\",\n    ]\n  `)\n})\n\ntest('files included and excluded in project\\'s plugin\\'s configureVitest are excluded', async ({ skip }) => {\n  skip(isNativeRunner(), 'native runner does not support plugins')\n\n  await runVitest({\n    coverage: {\n      // Include math.ts by default, exclude it in plugin config\n      include: ['**/math.ts'],\n      reporter: 'json',\n    },\n    projects: [\n      {\n        test: {\n          name: 'first',\n          include: ['fixtures/test/math.test.ts'],\n        },\n        plugins: [{\n          name: 'coverage-options-by-runtime-plugin',\n          configureVitest(context) {\n            const coverage = context.vitest.config.coverage\n            assert(coverage.provider === 'v8' || coverage.provider === 'istanbul')\n\n            coverage.include ||= []\n            coverage.include.push('**/even.ts')\n          },\n        }],\n      },\n      {\n        test: {\n          name: 'second',\n          include: ['fixtures/test/even.test.ts'],\n        },\n        plugins: [{\n          name: 'coverage-options-by-runtime-plugin',\n          configureVitest(context) {\n            const coverage = context.vitest.config.coverage\n            assert(coverage.provider === 'v8' || coverage.provider === 'istanbul')\n\n            coverage.include ||= []\n            coverage.include.push('**/untested-file.ts')\n            coverage.exclude.push('**/math.ts')\n          },\n        }],\n      },\n    ],\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/untested-file.ts\",\n    ]\n  `)\n})\n\ntest('includes covered and uncovered with ] in filenames', async () => {\n  await runVitest({\n    include: ['fixtures/test/sources-with-]-in-filenames.test.ts'],\n    coverage: {\n      reporter: 'json',\n      include: ['**/untested-with-*', '**/tested-with-*'],\n\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/tested-with-]-in-filename.ts\",\n      \"<process-cwd>/fixtures/src/untested-with-]-in-filename.ts\",\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/isolation.test.ts",
    "content": "import type { TestSpecification } from 'vitest/node'\nimport { expect, test } from 'vitest'\nimport { formatSummary, readCoverageMap, runVitest } from '../utils'\n\nconst pools = ['forks']\n\nif (!process.env.COVERAGE_BROWSER) {\n  pools.push('threads')\n\n  if (process.env.VITE_MODULE_RUNNER !== 'false') {\n    pools.push('vmForks', 'vmThreads')\n  }\n}\n\nfor (const isolate of [true, false]) {\n  for (const pool of pools) {\n    test(`{ isolate: ${isolate}, pool: \"${pool}\" }`, async () => {\n      await runVitest({\n        include: ['fixtures/test/isolation-*.test.ts'],\n        setupFiles: ['fixtures/setup.isolation.ts'],\n        sequence: { sequencer: Sorter },\n\n        pool,\n        isolate,\n        fileParallelism: false,\n\n        coverage: {\n          reporter: 'json',\n        },\n      })\n\n      const coverageMap = await readCoverageMap()\n      const branches = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/branch.ts')\n      const math = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/math.ts')\n\n      const summary = {\n        [branches.path]: formatSummary(branches.toSummary()),\n        [math.path]: formatSummary(math.toSummary()),\n      }\n\n      expect(summary).toStrictEqual({\n        '<process-cwd>/fixtures/src/branch.ts': {\n          branches: '2/2 (100%)',\n          functions: '1/1 (100%)',\n          lines: '4/4 (100%)',\n          statements: '4/4 (100%)',\n        },\n        '<process-cwd>/fixtures/src/math.ts': {\n          branches: '0/0 (100%)',\n          functions: '4/4 (100%)',\n          lines: '4/4 (100%)',\n          statements: '4/4 (100%)',\n        },\n      })\n    })\n  }\n}\n\nclass Sorter {\n  sort(files: TestSpecification[]) {\n    return files.sort((a) => {\n      if (a.moduleId.includes('isolation-1')) {\n        return -1\n      }\n      return 1\n    })\n  }\n\n  shard(files: TestSpecification[]) {\n    return files\n  }\n}\n"
  },
  {
    "path": "test/coverage-test/test/merge-reports.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('--merge-reports', async () => {\n  for (const index of [1, 2, 3]) {\n    await runVitest({\n      include: ['fixtures/test/merge-fixture-*.test.ts'],\n      reporters: 'blob',\n      shard: `${index}/3`,\n    })\n  }\n\n  await runVitest({\n    // Pass default value - this option is publicly only available via CLI so it's a bit hacky usage here\n    mergeReports: '.vitest-reports',\n    coverage: {\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  // Two files were covered: 3/3 cases covered math.ts, 1/3 covered even.ts\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/even.ts\",\n      \"<process-cwd>/fixtures/src/math.ts\",\n    ]\n  `)\n\n  const mathCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/math.ts')\n  const mathLines = mathCoverage.getLineCoverage()\n\n  // sum() should be covered by one test file\n  expect(mathLines[2]).toBe(1)\n\n  // multiply() should be covered by two test files\n  expect(mathLines[10]).toBe(2)\n\n  const evenCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/even.ts')\n  const evenLines = evenCoverage.getLineCoverage()\n\n  // isEven() should be covered by one test file\n  expect(evenLines[2]).toBe(1)\n})\n"
  },
  {
    "path": "test/coverage-test/test/mixed-versions-warning.unit.test.ts",
    "content": "import { stripVTControlCharacters } from 'node:util'\nimport IstanbulProvider from '@vitest/coverage-istanbul'\nimport V8Provider from '@vitest/coverage-v8'\nimport packageJson from '@vitest/coverage-v8/package.json'\nimport { expect, test, vi } from 'vitest'\nimport { configDefaults } from 'vitest/config'\n\nconst version = packageJson.version\n\ntest('v8 provider logs warning if versions do not match', async () => {\n  const provider = await V8Provider.getProvider()\n  const warn = vi.fn()\n\n  provider.initialize({\n    version: '1.0.0',\n    logger: { warn },\n    config: configDefaults,\n    _coverageOptions: configDefaults.coverage,\n  } as any)\n\n  expect(warn).toHaveBeenCalled()\n\n  const message = warn.mock.calls[0][0]\n\n  expect(stripVTControlCharacters(message)).toMatchInlineSnapshot(`\n    \"Loaded  vitest@1.0.0  and  @vitest/coverage-v8@${version} .\n    Running mixed versions is not supported and may lead into bugs\n    Update your dependencies and make sure the versions match.\"\n  `)\n})\n\ntest('istanbul provider logs warning if versions do not match', async () => {\n  const provider = await IstanbulProvider.getProvider()\n  const warn = vi.fn()\n\n  provider.initialize({\n    version: '1.0.0',\n    logger: { warn },\n    config: configDefaults,\n    _coverageOptions: configDefaults.coverage,\n  } as any)\n\n  expect(warn).toHaveBeenCalled()\n\n  const message = warn.mock.calls[0][0]\n\n  expect(stripVTControlCharacters(message)).toMatchInlineSnapshot(`\n    \"Loaded  vitest@1.0.0  and  @vitest/coverage-istanbul@${version} .\n    Running mixed versions is not supported and may lead into bugs\n    Update your dependencies and make sure the versions match.\"\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/mock-autospy.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('vi.mock({ spy: true }) collects coverage of original module', async () => {\n  await runVitest({\n    include: ['fixtures/test/mock-autospy-fixture.test.ts'],\n    coverage: {\n      reporter: 'json',\n      include: ['fixtures/src/mock-target.ts'],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap).toMatchInlineSnapshot(`\n    {\n      \"branches\": \"0/0 (100%)\",\n      \"functions\": \"1/2 (50%)\",\n      \"lines\": \"1/2 (50%)\",\n      \"statements\": \"1/2 (50%)\",\n    }\n  `)\n\n  const coverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/mock-target.ts')\n  const functionCoverage = Object.keys(coverage.fnMap)\n    .map(index => ({ name: coverage.fnMap[index].name, hits: coverage.f[index] }))\n    .sort((a, b) => a.name.localeCompare(b.name))\n\n  expect(functionCoverage).toMatchInlineSnapshot(`\n    [\n      {\n        \"hits\": 1,\n        \"name\": \"double\",\n      },\n      {\n        \"hits\": 0,\n        \"name\": \"triple\",\n      },\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/mock-importActual.test.ts",
    "content": "import { expect } from 'vitest'\nimport { isBrowser, isNativeRunner, isV8Provider, readCoverageMap, runVitest, test } from '../utils'\n\ntest('vi.importActual() collects coverage of original module', async () => {\n  await runVitest({\n    include: ['fixtures/test/mock-importActual-fixture.test.ts'],\n    coverage: {\n      reporter: 'json',\n      include: ['fixtures/src/mock-target.ts'],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n\n  // v8-browser and native runner report 100% due to different coverage collection behavior\n  if ((isBrowser() && isV8Provider()) || isNativeRunner()) {\n    expect(coverageMap).toMatchInlineSnapshot(`\n      {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"2/2 (100%)\",\n        \"lines\": \"2/2 (100%)\",\n        \"statements\": \"2/2 (100%)\",\n      }\n    `)\n  }\n  else {\n    expect(coverageMap).toMatchInlineSnapshot(`\n      {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"1/2 (50%)\",\n        \"lines\": \"1/2 (50%)\",\n        \"statements\": \"1/2 (50%)\",\n      }\n    `)\n\n    const coverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/mock-target.ts')\n    const functionCoverage = Object.keys(coverage.fnMap)\n      .map(index => ({ name: coverage.fnMap[index].name, hits: coverage.f[index] }))\n      .sort((a, b) => a.name.localeCompare(b.name))\n\n    expect(functionCoverage).toMatchInlineSnapshot(`\n      [\n        {\n          \"hits\": 1,\n          \"name\": \"double\",\n        },\n        {\n          \"hits\": 0,\n          \"name\": \"triple\",\n        },\n      ]\n    `)\n  }\n})\n"
  },
  {
    "path": "test/coverage-test/test/mocking-in-js-file.test.ts",
    "content": "import { expect } from 'vitest'\nimport { runVitest, test } from '../utils'\n\ntest('mocking in JS test file should not crash source map lookup (#3514)', async () => {\n  const { exitCode } = await runVitest({\n    include: ['fixtures/test/mocking-in-js-file.test.js'],\n    coverage: {\n      reporter: 'json',\n    },\n  })\n\n  expect(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/coverage-test/test/multi-environment.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('files transformed with multiple transform modes work (#3251)', async () => {\n  await runVitest({\n    include: ['fixtures/test/multi-environment-fixture-**'],\n    config: 'fixtures/configs/vitest.config.multi-transform.ts',\n    coverage: { reporter: 'json' },\n  })\n\n  const coverageMap = await readCoverageMap()\n\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/multi-environment.ts')\n  const lineCoverage = fileCoverage.getLineCoverage()\n\n  // Condition not covered by any test\n  expect(lineCoverage[13]).toBe(0)\n\n  // Condition covered by SSR test but not by Web\n  expect(lineCoverage[18]).toBe(1)\n\n  // Condition not covered by any test\n  expect(lineCoverage[22]).toBe(0)\n\n  // Condition covered by Web test but not by SSR\n  expect(lineCoverage[26]).toBe(1)\n\n  // Condition covered by both tests\n  expect(lineCoverage[30]).toBe(2)\n})\n"
  },
  {
    "path": "test/coverage-test/test/multi-suite.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('tests with multiple suites are covered (#3514)', async () => {\n  await runVitest({\n    include: ['fixtures/test/multi-suite-fixture.test.ts'],\n    coverage: { reporter: 'json' },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/multi-suite.ts')\n\n  // Assert that all functions are covered\n  expect(fileCoverage.f).toMatchObject({\n    0: 1,\n    1: 1,\n  })\n})\n"
  },
  {
    "path": "test/coverage-test/test/on-failure.test.ts",
    "content": "import { expect } from 'vitest'\nimport { sum } from '../fixtures/src/math'\nimport { captureStdout, coverageTest, normalizeURL, runVitest, test } from '../utils'\n\ntest('report is not generated when tests fail', async () => {\n  const stdout = captureStdout()\n\n  const { exitCode } = await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      include: ['**/fixtures/src/math.ts'],\n      reporter: 'text',\n    },\n  }, { throwOnError: false })\n\n  expect(stdout()).toBe('')\n  expect(exitCode).toBe(1)\n})\n\ntest('report is generated when tests fail and { reportOnFailure: true }', async () => {\n  const stdout = captureStdout()\n\n  const { exitCode } = await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      include: ['**/fixtures/src/math.ts'],\n      reporter: 'text',\n      reportOnFailure: true,\n    },\n  }, { throwOnError: false })\n\n  expect(stdout()).toMatchInlineSnapshot(`\n    \"----------|---------|----------|---------|---------|-------------------\n    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n    ----------|---------|----------|---------|---------|-------------------\n    All files |      25 |      100 |      25 |      25 |                   \n     math.ts  |      25 |      100 |      25 |      25 | 6-14              \n    ----------|---------|----------|---------|---------|-------------------\n    \"\n  `)\n\n  expect(exitCode).toBe(1)\n})\n\ncoverageTest('failing test', () => {\n  expect(sum(1, 2)).toBe(4)\n})\n"
  },
  {
    "path": "test/coverage-test/test/pre-transpiled-source.test.ts",
    "content": "import libCoverage from 'istanbul-lib-coverage'\nimport { expect } from 'vitest'\nimport { readCoverageJson, runVitest, test } from '../utils'\n\ntest('pre-transpiled code with source maps to original (#5341)', async () => {\n  await runVitest({\n    include: ['fixtures/test/pre-transpiled-fixture.test.ts'],\n    coverage: {\n      reporter: 'json',\n    },\n  })\n\n  const coverageJson = await readCoverageJson()\n  const coverageMap = libCoverage.createCoverageMap(coverageJson)\n\n  // transpiled.ts/transpiled.js should not be included\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/pre-transpiled/original.ts\",\n    ]\n  `)\n\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/pre-transpiled/original.ts')\n\n  expect(fileCoverage).toMatchInlineSnapshot(`\n    {\n      \"branches\": \"3/6 (50%)\",\n      \"functions\": \"2/2 (100%)\",\n      \"lines\": \"6/8 (75%)\",\n      \"statements\": \"6/8 (75%)\",\n    }\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/query-param-transforms.test.ts",
    "content": "import { readFileSync, writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { expect, onTestFinished } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('query param based transforms are resolved properly', async () => {\n  await runVitest({\n    config: 'fixtures/configs/vitest.config.query-param-transform.ts',\n    include: ['fixtures/test/query-param.test.ts'],\n    coverage: { reporter: 'json' },\n  })\n\n  const coverageMap = await readCoverageMap()\n\n  // Query params should not be present in final report\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/query-param-transformed.ts\",\n    ]\n  `)\n\n  const coverage = coverageMap.fileCoverageFor(coverageMap.files()[0])\n\n  // Query params change which functions end up in transform result,\n  // verify that all functions are present\n  const functionCoverage = Object.keys(coverage.fnMap)\n    .map(index => ({ name: coverage.fnMap[index].name, hits: coverage.f[index] }))\n    .sort((a, b) => a.name.localeCompare(b.name))\n\n  expect(functionCoverage).toMatchInlineSnapshot(`\n    [\n      {\n        \"hits\": 1,\n        \"name\": \"first\",\n      },\n      {\n        \"hits\": 3,\n        \"name\": \"initial\",\n      },\n      {\n        \"hits\": 1,\n        \"name\": \"second\",\n      },\n      {\n        \"hits\": 0,\n        \"name\": \"uncovered\",\n      },\n    ]\n  `)\n})\n\ntest.each([{ changed: 'HEAD' }, { coverage: { changed: 'HEAD' } }])('query param transforms respect %s', async (options) => {\n  const filePath = resolve('./fixtures/src/query-param-transformed.ts')\n  const original = readFileSync(filePath, 'utf8')\n\n  onTestFinished(() => writeFileSync(filePath, original, 'utf8'))\n  writeFileSync(filePath, `${original}\\nexport const changedMarker = true\\n`, 'utf8')\n\n  await runVitest({\n    config: 'fixtures/configs/vitest.config.query-param-transform.ts',\n    include: ['fixtures/test/query-param.test.ts'],\n    ...options,\n    coverage: { reporter: 'json', ...options.coverage },\n  })\n\n  const coverageMap = await readCoverageMap()\n\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/query-param-transformed.ts\",\n    ]\n  `)\n\n  const coverage = coverageMap.fileCoverageFor(coverageMap.files()[0])\n\n  const functionCoverage = Object.keys(coverage.fnMap)\n    .map(index => ({ name: coverage.fnMap[index].name, hits: coverage.f[index] }))\n    .sort((a, b) => a.name.localeCompare(b.name))\n\n  expect(functionCoverage).toMatchInlineSnapshot(`\n    [\n      {\n        \"hits\": 1,\n        \"name\": \"first\",\n      },\n      {\n        \"hits\": 3,\n        \"name\": \"initial\",\n      },\n      {\n        \"hits\": 1,\n        \"name\": \"second\",\n      },\n      {\n        \"hits\": 0,\n        \"name\": \"uncovered\",\n      },\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/reporters.test.ts",
    "content": "import { existsSync, readdirSync } from 'node:fs'\nimport { rm } from 'node:fs/promises'\nimport { expect } from 'vitest'\nimport { runVitest, test } from '../utils'\n\nconst include = ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts']\n\ntest('reporter as string', async () => {\n  await runVitest({\n    include,\n    coverage: {\n      reporter: 'json',\n    },\n  })\n\n  const files = readdirSync('./coverage')\n  expect(files).toContain('coverage-final.json')\n})\n\ntest('reporter as string when coverage is disabled', async () => {\n  if (existsSync('./coverage')) {\n    await rm('./coverage', { recursive: true, force: true })\n  }\n\n  await runVitest({\n    include,\n    coverage: {\n      enabled: false,\n      reporter: 'json',\n    },\n  })\n\n  expect(existsSync('./coverage')).toBe(false)\n})\n\ntest('reporter as list of strings', async () => {\n  await runVitest({\n    include,\n    coverage: {\n      reporter: ['json', 'lcov'],\n    },\n  })\n\n  const files = readdirSync('./coverage')\n  expect(files).toContain('coverage-final.json')\n  expect(files).toContain('lcov.info')\n  expect(files).toContain('lcov-report')\n})\n\ntest('reporter as list of lists', async () => {\n  await runVitest({\n    include,\n    coverage: {\n      reporter: [['json'], ['text', { file: 'custom-text-report' }]],\n    },\n  })\n\n  const files = readdirSync('./coverage')\n  expect(files).toContain('coverage-final.json')\n  expect(files).toContain('custom-text-report')\n})\n\ntest('all reporter variants mixed', async () => {\n  await runVitest({\n    include,\n    coverage: {\n      reporter: [\n        'json',\n        ['lcov'],\n        ['text', { file: 'custom-text-report' }],\n      ],\n    },\n  })\n\n  const files = readdirSync('./coverage')\n  expect(files).toContain('coverage-final.json')\n  expect(files).toContain('lcov.info')\n  expect(files).toContain('lcov-report')\n  expect(files).toContain('custom-text-report')\n})\n"
  },
  {
    "path": "test/coverage-test/test/results-snapshot.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('coverage results matches snapshot', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    coverage: {\n      reporter: 'json',\n      include: [\n        'fixtures/src/math.ts',\n        'fixtures/src/even.ts',\n        'fixtures/src/untested-file.ts',\n      ],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const fileCoverages = coverageMap.files().map(file => coverageMap.fileCoverageFor(file))\n\n  expect(fileCoverages).toMatchInlineSnapshot(`\n    {\n      \"<process-cwd>/fixtures/src/even.ts\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"1/2 (50%)\",\n        \"lines\": \"1/2 (50%)\",\n        \"statements\": \"1/2 (50%)\",\n      },\n      \"<process-cwd>/fixtures/src/math.ts\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"1/4 (25%)\",\n        \"lines\": \"1/4 (25%)\",\n        \"statements\": \"1/4 (25%)\",\n      },\n      \"<process-cwd>/fixtures/src/untested-file.ts\": {\n        \"branches\": \"0/2 (0%)\",\n        \"functions\": \"0/4 (0%)\",\n        \"lines\": \"0/6 (0%)\",\n        \"statements\": \"0/6 (0%)\",\n      },\n    }\n  `)\n\n  const lineCoverages = coverageMap.files().reduce((all, file) => ({\n    [file]: coverageMap.fileCoverageFor(file).getLineCoverage(),\n    ...all,\n  }), {})\n\n  expect(lineCoverages).toMatchInlineSnapshot(`\n    {\n      \"<process-cwd>/fixtures/src/even.ts\": {\n        \"2\": 1,\n        \"6\": 0,\n      },\n      \"<process-cwd>/fixtures/src/math.ts\": {\n        \"10\": 0,\n        \"14\": 0,\n        \"2\": 1,\n        \"6\": 0,\n      },\n      \"<process-cwd>/fixtures/src/untested-file.ts\": {\n        \"14\": 0,\n        \"21\": 0,\n        \"33\": 0,\n        \"35\": 0,\n        \"46\": 0,\n        \"9\": 0,\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/run-dynamic-coverage.test.ts",
    "content": "import { expect } from 'vitest'\nimport { cleanupCoverageJson, readCoverageMap, runVitest, test } from '../utils'\n\ntest('enableCoverage() collects coverage after being called', async () => {\n  await cleanupCoverageJson()\n\n  // Run a minimal suite where coverage starts disabled, then enable it and rerun.\n  const { ctx } = await runVitest({\n    include: ['fixtures/test/math.test.ts'],\n    watch: true,\n    coverage: {\n      // start disabled and turn on dynamically\n      enabled: false,\n      reporter: 'json',\n    },\n  })\n\n  await expect(readCoverageMap(), 'coverage map should not be on the disk').rejects.toThrow(/no such file/)\n\n  await ctx!.enableCoverage()\n  expect(ctx!.coverageProvider).toBeTruthy()\n\n  await ctx!.rerunFiles()\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toContain('<process-cwd>/fixtures/src/math.ts')\n})\n\ntest('enableCoverage() invalidates circular modules', async () => {\n  await cleanupCoverageJson()\n\n  await expect(readCoverageMap(), 'coverage map should not be on the disk').rejects.toThrow(/no such file/)\n\n  // Simulating user actions in the VSCode Vitest extension:\n  // 1. User clicks \"Run Test with Coverage\" to generate coverage files normally\n  const { ctx } = await runVitest({\n    include: ['fixtures/test/circular.test.ts'],\n    watch: false,\n    coverage: {\n      enabled: true,\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toEqual([\n    '<process-cwd>/fixtures/src/circularA.ts',\n    '<process-cwd>/fixtures/src/circularB.ts',\n  ])\n\n  // 2. User reruns tests with coverage\n  await ctx!.enableCoverage()\n  await ctx!.rerunFiles()\n\n  const coverageMap2 = await readCoverageMap()\n  expect(coverageMap2.files()).toEqual([\n    '<process-cwd>/fixtures/src/circularA.ts',\n    '<process-cwd>/fixtures/src/circularB.ts',\n  ])\n})\n\ntest('disableCoverage() stops collecting coverage going forward', async () => {\n  const { ctx } = await runVitest({\n    include: ['fixtures/test/math.test.ts'],\n    watch: true,\n    coverage: {\n      enabled: true,\n      reporter: 'json',\n    },\n  })\n\n  // Initial run collects coverage\n  const initialMap = await readCoverageMap()\n  expect(initialMap.files()).toContain('<process-cwd>/fixtures/src/math.ts')\n  expect(ctx!.coverageProvider).toBeTruthy()\n\n  // Disable coverage and rerun\n  ctx!.disableCoverage()\n  expect(ctx!.coverageProvider).toBeNull()\n\n  await cleanupCoverageJson()\n\n  await ctx!.rerunFiles()\n\n  await expect(readCoverageMap(), 'coverage map should not be on the disk').rejects.toThrow(/no such file/)\n  expect(ctx!.coverageProvider).toBeNull()\n})\n"
  },
  {
    "path": "test/coverage-test/test/setup-files.test.ts",
    "content": "import { resolve } from 'node:path'\nimport { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('tests with multiple suites are covered (#3514)', async () => {\n  const { stdout } = await runVitest({\n    include: ['fixtures/test/math.test.ts'],\n    setupFiles: [\n      // Full absolute path\n      resolve('fixtures/setup.ts'),\n      // Relative path\n      'fixtures/src/another-setup.ts',\n    ],\n    coverage: {\n      reporter: 'json',\n    },\n  })\n\n  // Setup files should have run\n  expect(stdout).toContain('Running setup in fixtures root')\n  expect(stdout).toContain('Running another setup in fixtures src')\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  // Setup files should be excluded from report\n  expect(files.find(file => file.includes('setup.ts'))).toBeFalsy()\n\n  // Some valid coverage should be reported\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/math.ts')\n\n  expect(fileCoverage).toMatchInlineSnapshot(`\n    {\n      \"branches\": \"0/0 (100%)\",\n      \"functions\": \"1/4 (25%)\",\n      \"lines\": \"1/4 (25%)\",\n      \"statements\": \"1/4 (25%)\",\n    }\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/shard.test.ts",
    "content": "import { readdirSync } from 'node:fs'\nimport { expect } from 'vitest'\nimport { coverageTest, normalizeURL, runVitest, test } from '../utils'\n\ntest('{ shard: 1/3 }', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url), 'fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    shard: '1/3',\n  })\n})\n\ncoverageTest('temporary directory is postfixed with --shard value', () => {\n  const files = readdirSync('./coverage')\n\n  expect(files).toContain('.tmp-1-3')\n  expect(files).not.toContain('.tmp')\n})\n"
  },
  {
    "path": "test/coverage-test/test/source-maps.test.ts",
    "content": "import { expect } from 'vitest'\nimport { isBrowser, runVitest, test } from '../utils'\n\ntest('errors point to correct location', async () => {\n  const { stderr } = await runVitest({\n    include: ['fixtures/test/error-location.test.ts'],\n    coverage: { reporter: 'json' },\n  }, { throwOnError: false })\n\n  if (isBrowser()) {\n    expect(stderr).toMatch(`\n❯ throws fixtures/src/throws-error.ts:29:11\n     27|    */\n     28|    function throws() {\n     29|      throw new Error(\"Expected error\")\n       |           ^\n     30|    }\n    `.trim())\n  }\n  else {\n    expect(stderr).toMatch(`\n❯ throws fixtures/src/throws-error.ts:29:12\n     27|    */\n     28|    function throws() {\n     29|      throw new Error(\"Expected error\")\n       |            ^\n     30|    }\n    `.trim())\n  }\n})\n"
  },
  {
    "path": "test/coverage-test/test/temporary-files.test.ts",
    "content": "import { readdirSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { expect } from 'vitest'\nimport { runVitest, test } from '../utils'\n\ntest('temporary files are removed after test', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts'],\n    coverage: { reporter: 'json' },\n  })\n\n  const coveragePath = resolve('./coverage')\n  const files = readdirSync(coveragePath)\n\n  expect(files).not.toContain('.tmp')\n\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"coverage-final.json\",\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/test-reporter-conflicts.test.ts",
    "content": "import { readdirSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { expect } from 'vitest'\nimport { runVitest, test } from '../utils'\n\ntest('coverage provider does not conflict with built-in reporter\\'s outputFile (#3330)', async () => {\n  await runVitest({\n    include: ['fixtures/test/math.test.ts'],\n    coverage: { reporter: ['html'] },\n    reporters: ['default', 'junit'],\n    outputFile: { junit: 'coverage/junit.xml' },\n  })\n\n  const coveragePath = resolve('./coverage')\n  const files = readdirSync(coveragePath)\n\n  expect(files).toContain('index.html')\n  expect(files).toContain('junit.xml')\n  expect(files).toContain('math.ts.html')\n})\n"
  },
  {
    "path": "test/coverage-test/test/threshold-100.test.ts",
    "content": "import { assert, expect, inject } from 'vitest'\nimport { coverageTest, normalizeURL, runVitest, test } from '../utils'\n\ndeclare module 'vitest' {\n  export interface ProvidedContext {\n    coverage: {\n      provider: string | undefined\n      thresholds: {\n        [key: string]: any\n      }\n    }\n  }\n}\n\ntest('{ threshold: { 100: true }}', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: { thresholds: { 100: true } },\n    reporters: [\n      'verbose',\n      {\n        onInit(ctx) {\n          ctx.getRootProject().provide('coverage', {\n            provider: ctx.config.coverage.provider,\n            thresholds: (ctx.config.coverage as any).thresholds,\n          })\n        },\n      },\n    ],\n  }, { throwOnError: false })\n})\n\ncoverageTest('thresholds.100 sets global thresholds to 100', () => {\n  const coverage = inject('coverage')\n\n  assert(coverage.provider === 'v8' || coverage.provider === 'istanbul')\n  assert(coverage.thresholds !== undefined)\n\n  expect(coverage.thresholds[100]).toBe(true)\n  expect(coverage.thresholds.lines).toBe(100)\n  expect(coverage.thresholds.branches).toBe(100)\n  expect(coverage.thresholds.functions).toBe(100)\n  expect(coverage.thresholds.statements).toBe(100)\n})\n"
  },
  {
    "path": "test/coverage-test/test/threshold-auto-update.test.ts",
    "content": "import { readFileSync, writeFileSync } from 'node:fs'\nimport { expect, onTestFinished } from 'vitest'\nimport { runVitest, test } from '../utils'\n\nconst config = 'fixtures/configs/vitest.config.thresholds-auto-update.ts'\n\ntest('thresholds.autoUpdate updates thresholds', async () => {\n  const original = readConfig()\n  onTestFinished(() => writeFileSync(config, original))\n\n  expect(original).toMatchInlineSnapshot(`\n    \"import { defineConfig } from 'vitest/config'\n\n    export default defineConfig({\n      test: {\n        coverage: {\n          thresholds: {\n            autoUpdate: true,\n\n            // Global ones\n            lines: 0.1,\n            functions: 0.2,\n            branches: -1000,\n            statements: -2000,\n\n            '**/src/math.ts': {\n              branches: 0.1,\n              functions: 0.2,\n              lines: -1000,\n              statements: -2000,\n            }\n          }\n        }\n      },\n    })\n    \"\n  `)\n\n  await runVitest({\n    include: ['fixtures/test/math.test.ts', 'fixtures/test/even.test.ts'],\n    config,\n  }, { throwOnError: false })\n\n  expect(readConfig()).toMatchInlineSnapshot(`\n    \"import { defineConfig } from 'vitest/config'\n\n    export default defineConfig({\n      test: {\n        coverage: {\n          thresholds: {\n            autoUpdate: true,\n\n            // Global ones\n            lines: 33.33,\n            functions: 33.33,\n            branches: 100,\n            statements: -4,\n\n            '**/src/math.ts': {\n              branches: 100,\n              functions: 25,\n              lines: -3,\n              statements: -3,\n            }\n          }\n        }\n      },\n    })\n    \"\n  `)\n})\n\nfunction readConfig() {\n  return readFileSync(config, 'utf8')\n}\n"
  },
  {
    "path": "test/coverage-test/test/threshold-auto-update.unit.test.ts",
    "content": "import type { CoverageMap } from 'istanbul-lib-coverage'\nimport { createCoverageSummary } from 'istanbul-lib-coverage'\nimport { parseModule } from 'magicast'\n\nimport { expect, test, vi } from 'vitest'\nimport { defineConfig } from 'vitest/config'\nimport { BaseCoverageProvider } from 'vitest/node'\n\nconst initialThresholds = { lines: 1, branches: 2, functions: 3, statements: 4 }\nconst coveredThresholds = { lines: 50, branches: 60, functions: 70, statements: 80 }\nconst initialConfig = JSON.stringify(defineConfig({\n  test: {\n    coverage: {\n      thresholds: initialThresholds,\n    },\n  },\n}), null, 2)\n\ntest('updates thresholds on \"export default {..}\"', async () => {\n  const config = parseModule(`export default ${initialConfig}`)\n\n  const updatedConfig = await updateThresholds(config)\n\n  expect(updatedConfig).toMatchInlineSnapshot(`\n    \"export default {\n      \"test\": {\n        \"coverage\": {\n          \"thresholds\": {\n            \"lines\": 50,\n            \"branches\": 60,\n            \"functions\": 70,\n            \"statements\": 80\n          }\n        }\n      }\n    }\"\n  `)\n})\n\ntest('updates thresholds on \"export default defineConfig({...})\"', async () => {\n  const config = parseModule(`export default defineConfig(${initialConfig})`)\n\n  const updatedConfig = await updateThresholds(config)\n\n  expect(updatedConfig).toMatchInlineSnapshot(`\n    \"export default defineConfig({\n      \"test\": {\n        \"coverage\": {\n          \"thresholds\": {\n            \"lines\": 50,\n            \"branches\": 60,\n            \"functions\": 70,\n            \"statements\": 80\n          }\n        }\n      }\n    })\"\n  `)\n})\n\ntest('updates thresholds on \"export default defineConfig(() => ({...}))\"', async () => {\n  const config = parseModule(`export default defineConfig(() => (${initialConfig}))`)\n\n  const updatedConfig = await updateThresholds(config)\n\n  expect(updatedConfig).toMatchInlineSnapshot(`\n    \"export default defineConfig(() => ({\n      \"test\": {\n        \"coverage\": {\n          \"thresholds\": {\n            \"lines\": 50,\n            \"branches\": 60,\n            \"functions\": 70,\n            \"statements\": 80\n          }\n        }\n      }\n    }))\"\n  `)\n})\n\ntest('updates thresholds on \"export default mergeConfig({...}, defineConfig({...}))\"', async () => {\n  const config = parseModule(`export default mergeConfig(baseConfig, defineConfig(${initialConfig}))`)\n\n  const updatedConfig = await updateThresholds(config)\n\n  expect(updatedConfig).toMatchInlineSnapshot(`\n    \"export default mergeConfig(baseConfig, defineConfig({\n      \"test\": {\n        \"coverage\": {\n          \"thresholds\": {\n            \"lines\": 50,\n            \"branches\": 60,\n            \"functions\": 70,\n            \"statements\": 80\n          }\n        }\n      }\n    }))\"\n  `)\n})\n\ntest('updates thresholds on \"export default defineConfig(() => mergeConfig({...}, defineConfig({...})))\"', async () => {\n  const config = parseModule(`export default defineConfig((configEnv) => mergeConfig(baseConfig, defineConfig(${initialConfig})))`)\n\n  const updatedConfig = await updateThresholds(config)\n\n  expect(updatedConfig).toMatchInlineSnapshot(`\n    \"export default defineConfig((configEnv) => mergeConfig(baseConfig, defineConfig({\n      \"test\": {\n        \"coverage\": {\n          \"thresholds\": {\n            \"lines\": 50,\n            \"branches\": 60,\n            \"functions\": 70,\n            \"statements\": 80\n          }\n        }\n      }\n    })))\"\n  `)\n})\n\ntest('throws when configuration is too complex to analyze', async () => {\n  const config = parseModule(`\nimport config from \"./some-path\"\nexport default config\n  `)\n\n  await expect(updateThresholds(config)).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: Failed to update coverage thresholds. Configuration file is too complex.]`)\n})\n\ntest('formats values with custom formatter', async () => {\n  const config = parseModule(`export default ${initialConfig}`)\n\n  const autoUpdate = vi.fn().mockImplementation(value => value + 10_000)\n  const updatedConfig = await updateThresholds(config, { thresholds: { autoUpdate } })\n\n  expect(updatedConfig).toMatchInlineSnapshot(`\n    \"export default {\n      \"test\": {\n        \"coverage\": {\n          \"thresholds\": {\n            \"lines\": 10050,\n            \"branches\": 10060,\n            \"functions\": 10070,\n            \"statements\": 10080\n          }\n        }\n      }\n    }\"\n  `)\n\n  const calls = autoUpdate.mock.calls.flatMap(call => call[0])\n\n  expect(calls.sort()).toEqual([50, 60, 70, 80])\n})\n\nasync function updateThresholds(configurationFile: ReturnType<typeof parseModule>, _coverageOptions: Partial<(InstanceType<typeof BaseCoverageProvider>)['options']> = {}) {\n  const summaryData = { total: 0, covered: 0, skipped: 0 }\n  const thresholds = [{\n    name: 'global',\n    thresholds: initialThresholds,\n    coverageMap: {\n      getCoverageSummary: () => createCoverageSummary({\n        lines: { pct: coveredThresholds.lines, ...summaryData },\n        statements: { pct: coveredThresholds.statements, ...summaryData },\n        branches: { pct: coveredThresholds.branches, ...summaryData },\n        functions: { pct: coveredThresholds.functions, ...summaryData },\n      }),\n    } as CoverageMap,\n  }]\n\n  return new Promise((resolve, reject) => {\n    const provider = new BaseCoverageProvider()\n\n    provider._initialize({\n      config: { coverage: { } },\n      logger: { log: () => {} },\n      _coverageOptions,\n    } as any)\n\n    provider.updateThresholds({\n      thresholds,\n      configurationFile,\n      onUpdate: () => resolve(configurationFile.generate().code),\n    }).catch(error => reject(error))\n  })\n}\n"
  },
  {
    "path": "test/coverage-test/test/threshold-failure.test.ts",
    "content": "import { expect } from 'vitest'\nimport { sum } from '../fixtures/src/math'\nimport { coverageTest, normalizeURL, runVitest, test } from '../utils'\n\ntest('failing percentage thresholds', async () => {\n  const { exitCode, stderr } = await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      include: ['**/fixtures/src/math.ts'],\n      thresholds: {\n        '**/fixtures/src/math.ts': {\n          branches: 100,\n          functions: 100,\n          lines: 100,\n          statements: 100,\n        },\n      },\n    },\n  }, { throwOnError: false })\n\n  expect(exitCode).toBe(1)\n  expect(stderr).toContain('ERROR: Coverage for lines (25%) does not meet \"**/fixtures/src/math.ts\" threshold (100%)')\n  expect(stderr).toContain('ERROR: Coverage for statements (25%) does not meet \"**/fixtures/src/math.ts\" threshold (100%)')\n  expect(stderr).toContain('ERROR: Coverage for functions (25%) does not meet \"**/fixtures/src/math.ts\" threshold (100%)')\n})\n\ntest('failing absolute thresholds', async () => {\n  const { exitCode, stderr } = await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      include: ['**/fixtures/src/math.ts'],\n      thresholds: {\n        '**/fixtures/src/math.ts': {\n          branches: -1,\n          functions: -2,\n          lines: -2,\n          statements: -1,\n        },\n      },\n    },\n  }, { throwOnError: false })\n\n  expect(exitCode).toBe(1)\n\n  expect(stderr).toContain('ERROR: Uncovered functions (3) exceed \"**/fixtures/src/math.ts\" threshold (2)')\n  expect(stderr).toContain('ERROR: Uncovered statements (3) exceed \"**/fixtures/src/math.ts\" threshold (1)')\n  expect(stderr).toContain('ERROR: Uncovered lines (3) exceed \"**/fixtures/src/math.ts\" threshold (2)')\n})\n\ncoverageTest('cover some lines, but not too much', () => {\n  expect(sum(1, 2)).toBe(3)\n})\n"
  },
  {
    "path": "test/coverage-test/test/threshold-glob.test.ts",
    "content": "import { expect } from 'vitest'\nimport { isEven, isOdd } from '../fixtures/src/even'\nimport { sum } from '../fixtures/src/math'\nimport { coverageTest, normalizeURL, runVitest, test } from '../utils'\n\ntest('threshold glob patterns count in global coverage', async () => {\n  await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      include: [\n        '**/fixtures/src/even.ts',\n        '**/fixtures/src/math.ts',\n      ],\n      thresholds: {\n        'branches': 100,\n        'functions': 50,\n        'lines': 50,\n        'statements': 50,\n\n        '**/fixtures/src/even.ts': {\n          branches: 100,\n          functions: 100,\n          lines: 100,\n          statements: 100,\n        },\n      },\n    },\n  })\n})\n\ntest('{ thresholds: { 100: true } } on glob pattern', async () => {\n  const { stderr, exitCode } = await runVitest({\n    include: [normalizeURL(import.meta.url)],\n    coverage: {\n      include: [\n        '**/fixtures/src/even.ts',\n        '**/fixtures/src/math.ts',\n      ],\n      thresholds: {\n        '**/fixtures/src/even.ts': {\n          100: true,\n        },\n        '**/fixtures/src/math.ts': {\n          100: true,\n        },\n      },\n    },\n  }, { throwOnError: false })\n\n  expect(exitCode).toBe(1)\n\n  expect(stderr).toMatchInlineSnapshot(`\n    \"ERROR: Coverage for lines (25%) does not meet \"**/fixtures/src/math.ts\" threshold (100%)\n    ERROR: Coverage for functions (25%) does not meet \"**/fixtures/src/math.ts\" threshold (100%)\n    ERROR: Coverage for statements (25%) does not meet \"**/fixtures/src/math.ts\" threshold (100%)\n    \"\n  `)\n})\n\ncoverageTest('cover some lines, but not too much', () => {\n  expect(sum(1, 2)).toBe(3)\n  expect(isEven(4)).toBe(true)\n  expect(isOdd(4)).toBe(false)\n})\n"
  },
  {
    "path": "test/coverage-test/test/transform-plugin-order.istanbul.test.ts",
    "content": "import { expect } from 'vitest'\nimport { customFilePlugin } from '../fixtures/configs/vitest.config.multi-transforms'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('custom `viteOverrides.plugins` work with `vitest:coverage-transform` plugin (#8468)', async () => {\n  const viteOverrides = { plugins: [customFilePlugin('1')] }\n\n  await runVitest({\n    include: ['fixtures/test/custom-1-syntax.test.ts'],\n    coverage: { reporter: 'json' },\n  }, undefined, viteOverrides)\n\n  const coverageMap = await readCoverageMap()\n  expect(coverageMap.files()).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/covered.custom-1\",\n    ]\n  `)\n\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/covered.custom-1')\n  expect(fileCoverage).toMatchInlineSnapshot(`\n    {\n      \"branches\": \"0/0 (100%)\",\n      \"functions\": \"1/2 (50%)\",\n      \"lines\": \"1/2 (50%)\",\n      \"statements\": \"1/2 (50%)\",\n    }\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/virtual-files.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('virtual files should be excluded', async () => {\n  const { stdout } = await runVitest({\n    include: ['fixtures/test/virtual-files-fixture.test.ts'],\n    coverage: { reporter: 'json' },\n    config: 'fixtures/configs/vitest.config.virtual-files.ts',\n  })\n\n  expect(stdout).toContain('virtual-files-fixture.test.ts')\n  expect(stdout).toContain('verify virtual files work')\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  expect(files.length).toBeGreaterThan(0)\n\n  for (const file of files) {\n    expect(file).not.toContain('virtual:')\n\n    // Vitest in node\n    expect(file).not.toContain('__x00__')\n    expect(file).not.toContain('\\0')\n\n    // Vitest browser\n    expect(file).not.toContain('\\x00')\n  }\n\n  expect(files).toContain('<process-cwd>/fixtures/src/math.ts')\n\n  const fileCoverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/math.ts')\n  expect(fileCoverage).toMatchInlineSnapshot(`\n    {\n      \"branches\": \"0/0 (100%)\",\n      \"functions\": \"1/4 (25%)\",\n      \"lines\": \"1/4 (25%)\",\n      \"statements\": \"1/4 (25%)\",\n    }\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/vue.test.ts",
    "content": "import { readdirSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { beforeAll, expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\nbeforeAll(async () => {\n  await runVitest({\n    include: ['fixtures/test/vue-fixture.test.ts'],\n    coverage: { reporter: ['json', 'html'] },\n  })\n})\n\ntest('files should not contain query parameters', () => {\n  const coveragePath = resolve('./coverage/Vue/Counter/')\n  const files = readdirSync(coveragePath)\n\n  expect(files).toContain('index.html')\n  expect(files).toContain('Counter.vue.html')\n  expect(files).toContain('Counter.component.ts.html')\n  expect(files).not.toContain('Counter.component.ts?vue&type=script&src=true&lang.ts.html')\n})\n\ntest('coverage results matches snapshot', async () => {\n  const coverageMap = await readCoverageMap()\n\n  expect(coverageMap).toMatchInlineSnapshot(`\n    {\n      \"branches\": \"6/8 (75%)\",\n      \"functions\": \"5/7 (71.42%)\",\n      \"lines\": \"13/16 (81.25%)\",\n      \"statements\": \"14/17 (82.35%)\",\n    }\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/web-worker.test.ts",
    "content": "import { expect } from 'vitest'\nimport { formatSummary, readCoverageMap, runVitest, test } from '../utils'\n\ntest('web worker coverage is correct', async () => {\n  await runVitest({\n    setupFiles: ['@vitest/web-worker'],\n    include: ['fixtures/test/web-worker.test.ts'],\n    environment: 'jsdom',\n    coverage: {\n      include: [\n        // Runs in web-worker's runner with custom context -> execution wrapper ~430 chars\n        'fixtures/src/worker.ts',\n\n        // Runs in default runner -> execution wrapper ~185 chars\n        'fixtures/src/worker-wrapper.ts',\n      ],\n      reporter: 'json',\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const worker = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/worker.ts')\n  const wrapper = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/worker-wrapper.ts')\n\n  const summary = {\n    [worker.path]: formatSummary(worker.toSummary()),\n    [wrapper.path]: formatSummary(wrapper.toSummary()),\n  }\n\n  // Check HTML report if these change unexpectedly\n  expect(summary).toMatchInlineSnapshot(`\n    {\n      \"<process-cwd>/fixtures/src/worker-wrapper.ts\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"3/5 (60%)\",\n        \"lines\": \"9/11 (81.81%)\",\n        \"statements\": \"9/11 (81.81%)\",\n      },\n      \"<process-cwd>/fixtures/src/worker.ts\": {\n        \"branches\": \"2/4 (50%)\",\n        \"functions\": \"2/3 (66.66%)\",\n        \"lines\": \"7/12 (58.33%)\",\n        \"statements\": \"7/12 (58.33%)\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/workspace.multi-transform.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('uncovered files that require custom transform', async () => {\n  await runVitest({\n    config: './fixtures/configs/vitest.config.multi-transforms.ts',\n    coverage: {\n      reporter: ['json', 'html'],\n      include: ['**/*.custom-1', '**/*.custom-2', '**/math.ts'],\n    },\n  })\n\n  const coverageMap = await readCoverageMap()\n  const files = coverageMap.files()\n\n  // All files from workspace should be picked\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/src/covered.custom-1\",\n      \"<process-cwd>/fixtures/src/math.ts\",\n      \"<process-cwd>/fixtures/src/uncovered.custom-1\",\n      \"<process-cwd>/fixtures/workspaces/custom-2/src/covered.custom-2\",\n      \"<process-cwd>/fixtures/workspaces/custom-2/src/uncovered.custom-2\",\n    ]\n  `)\n\n  const fileCoverages = coverageMap.files().map(file => coverageMap.fileCoverageFor(file))\n\n  expect(fileCoverages).toMatchInlineSnapshot(`\n    {\n      \"<process-cwd>/fixtures/src/covered.custom-1\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"1/2 (50%)\",\n        \"lines\": \"1/2 (50%)\",\n        \"statements\": \"1/2 (50%)\",\n      },\n      \"<process-cwd>/fixtures/src/math.ts\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"1/4 (25%)\",\n        \"lines\": \"1/4 (25%)\",\n        \"statements\": \"1/4 (25%)\",\n      },\n      \"<process-cwd>/fixtures/src/uncovered.custom-1\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"0/1 (0%)\",\n        \"lines\": \"0/1 (0%)\",\n        \"statements\": \"0/1 (0%)\",\n      },\n      \"<process-cwd>/fixtures/workspaces/custom-2/src/covered.custom-2\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"1/2 (50%)\",\n        \"lines\": \"1/2 (50%)\",\n        \"statements\": \"1/2 (50%)\",\n      },\n      \"<process-cwd>/fixtures/workspaces/custom-2/src/uncovered.custom-2\": {\n        \"branches\": \"0/0 (100%)\",\n        \"functions\": \"0/1 (0%)\",\n        \"lines\": \"0/1 (0%)\",\n        \"statements\": \"0/1 (0%)\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/test/workspace.project-filter.test.ts",
    "content": "import { expect } from 'vitest'\nimport { readCoverageMap, runVitest, test } from '../utils'\n\ntest('coverage files include all projects', async () => {\n  await runVitest({\n    config: '../../configs/vitest.config.workspace.ts',\n    coverage: {\n      reporter: ['json', 'html'],\n      include: ['**/src/**'],\n    },\n    root: 'fixtures/workspaces/project',\n  })\n\n  const coverageMap = await readCoverageMap('fixtures/workspaces/project/coverage/coverage-final.json')\n  const files = coverageMap.files()\n\n  // All files from workspace should be picked\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/workspaces/project/project1/src/id.ts\",\n      \"<process-cwd>/fixtures/workspaces/project/project1/src/untested.ts\",\n      \"<process-cwd>/fixtures/workspaces/project/project2/src/konst.ts\",\n      \"<process-cwd>/fixtures/workspaces/project/project2/src/untested.ts\",\n      \"<process-cwd>/fixtures/workspaces/project/shared/src/utils.ts\",\n    ]\n  `)\n})\n\ntest('coverage files limited to specified project', async () => {\n  await runVitest({\n    config: '../../configs/vitest.config.workspace.ts',\n    coverage: {\n      reporter: ['json', 'html'],\n      include: ['**/src/**'],\n    },\n    project: 'project2',\n    root: 'fixtures/workspaces/project',\n  })\n\n  const coverageMap = await readCoverageMap('fixtures/workspaces/project/coverage/coverage-final.json')\n  const files = coverageMap.files()\n\n  expect(files).toMatchInlineSnapshot(`\n    [\n      \"<process-cwd>/fixtures/workspaces/project/project2/src/konst.ts\",\n      \"<process-cwd>/fixtures/workspaces/project/project2/src/untested.ts\",\n    ]\n  `)\n})\n"
  },
  {
    "path": "test/coverage-test/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true\n  }\n}\n"
  },
  {
    "path": "test/coverage-test/utils.ts",
    "content": "import type { CoverageSummary, FileCoverageData } from 'istanbul-lib-coverage'\nimport type { UserConfig as ViteUserConfig } from 'vite'\nimport type { SuiteAPI, TestAPI } from 'vitest'\nimport type { TestUserConfig } from 'vitest/node'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { unlink } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { stripVTControlCharacters } from 'node:util'\nimport { playwright } from '@vitest/browser-playwright'\nimport { toArray } from '@vitest/utils/helpers'\nimport libCoverage from 'istanbul-lib-coverage'\nimport { normalize } from 'pathe'\nimport { onTestFailed, TestRunner, vi, describe as vitestDescribe, test as vitestTest } from 'vitest'\nimport * as testUtils from '../test-utils/index'\n\nexport const test: TestAPI = process.env.COVERAGE_TEST !== 'true'\n  ? vitestTest\n  : (() => {}) as any as TestAPI\n\nexport const describe: SuiteAPI = process.env.COVERAGE_TEST !== 'true'\n  ? vitestDescribe\n  : (() => {}) as any as SuiteAPI\n\nexport const coverageTest: TestAPI = process.env.COVERAGE_TEST !== 'true'\n  ? (() => {}) as any as TestAPI\n  : vitestTest\n\nexport async function runVitest(config: TestUserConfig, options = { throwOnError: true }, viteOverrides: ViteUserConfig = {}) {\n  const provider = process.env.COVERAGE_PROVIDER as any\n\n  const result = await testUtils.runVitest({\n    config: 'fixtures/configs/vitest.config.ts',\n    pool: 'threads',\n    ...config,\n    env: {\n      COVERAGE_TEST: 'true',\n      ...config.env,\n    },\n    coverage: {\n      enabled: true,\n      reporter: [],\n      ...config.coverage,\n      provider,\n      customProviderModule: provider === 'custom' ? 'fixtures/custom-provider' : undefined,\n    },\n    browser: {\n      enabled: process.env.COVERAGE_BROWSER === 'true',\n      headless: true,\n      instances: [{ browser: 'chromium' }],\n      provider: playwright(),\n      ...config.browser,\n    },\n    experimental: {\n      ...config.experimental,\n      viteModuleRunner: process.env.VITE_MODULE_RUNNER === 'false' ? false : config.experimental?.viteModuleRunner,\n    },\n    setupFiles: [\n      resolve(import.meta.dirname, 'setup.native.ts'),\n      ...config.setupFiles ?? [],\n    ],\n\n    projects: config.projects?.map((project) => {\n      if (typeof project !== 'string' && 'test' in project) {\n        project.test ||= {}\n        project.test.setupFiles = toArray(project.test.setupFiles)\n        project.test.setupFiles.push(resolve(import.meta.dirname, 'setup.native.ts'))\n      }\n\n      return project\n    }),\n\n    $viteConfig: viteOverrides,\n  })\n\n  if (TestRunner.getCurrentTest()) {\n    onTestFailed(() => {\n      console.error('stderr:', result.stderr)\n      console.error('stdout:', result.stdout)\n    })\n  }\n\n  if (options.throwOnError) {\n    if (result.stderr !== '') {\n      throw new Error(`stderr:\\n${result.stderr}\\n\\nstdout:\\n${result.stdout}`)\n    }\n  }\n\n  return result\n}\n\nexport async function cleanupCoverageJson(name = './coverage/coverage-final.json') {\n  if (existsSync(name)) {\n    await unlink(name)\n  }\n}\n\n/**\n * Read JSON coverage report from file system.\n * Normalizes paths to keep contents consistent between OS's\n */\nexport async function readCoverageJson(name = './coverage/coverage-final.json') {\n  const jsonReport = JSON.parse(readFileSync(name, 'utf8')) as Record<string, FileCoverageData>\n\n  const normalizedReport: typeof jsonReport = {}\n\n  for (const [filename, coverage] of Object.entries(jsonReport)) {\n    coverage.path = normalizeFilename(coverage.path)\n    normalizedReport[normalizeFilename(filename)] = coverage\n  }\n\n  return normalizedReport\n}\n\n/**\n * Read coverage report from file system as Istanbul's `CoverageMap`\n */\nexport async function readCoverageMap(name = './coverage/coverage-final.json') {\n  const coverageJson = await readCoverageJson(name)\n  return libCoverage.createCoverageMap(coverageJson)\n}\n\nexport function formatSummary(summary: CoverageSummary) {\n  return (['branches', 'functions', 'lines', 'statements'] as const).reduce((all, current) => ({\n    ...all,\n    [current]: `${summary[current].covered}/${summary[current].total} (${summary[current].pct}%)`,\n  }), {})\n}\n\nexport function normalizeFilename(filename: string) {\n  return normalize(filename)\n    .replace(normalize(process.cwd()), '<process-cwd>')\n    .replace(normalize(resolve(process.cwd(), '../../')), '<project-root>')\n}\n\nexport function isV8Provider() {\n  return process.env.COVERAGE_PROVIDER === 'v8'\n}\n\nexport function isBrowser() {\n  return process.env.COVERAGE_BROWSER === 'true'\n}\n\nexport function isNativeRunner() {\n  return process.env.VITE_MODULE_RUNNER === 'false'\n}\n\nexport function normalizeURL(importMetaURL: string) {\n  return normalize(fileURLToPath(importMetaURL))\n}\n\nexport function captureStdout() {\n  const spy = vi.fn()\n  const original = process.stdout.write\n  process.stdout.write = spy\n\n  return function collect() {\n    process.stdout.write = original\n    return stripVTControlCharacters(spy.mock.calls.map(call => call[0]).join(''))\n  }\n}\n"
  },
  {
    "path": "test/coverage-test/vitest.config.ts",
    "content": "import type { TestProjectInlineConfiguration } from 'vitest/config'\nimport Module from 'node:module'\nimport { defineConfig } from 'vitest/config'\n\nconst GENERIC_TESTS = 'test/**.test.ts'\nconst V8_TESTS = 'test/**.v8.test.ts'\nconst ISTANBUL_TESTS = 'test/**.istanbul.test.ts'\nconst CUSTOM_TESTS = 'test/**.custom.test.ts'\nconst UNIT_TESTS = 'test/**.unit.test.ts'\nconst BROWSER_TESTS = 'test/**.browser.test.ts'\nconst FIXTURES = '**/fixtures/**'\n\nexport default defineConfig({\n  test: {\n    reporters: 'verbose',\n    isolate: false,\n    setupFiles: ['./setup.ts'],\n    projects: [\n      // Test cases for v8-provider\n      {\n        extends: true,\n        test: {\n          name: { label: 'v8', color: 'green' },\n          env: { COVERAGE_PROVIDER: 'v8' },\n          include: [GENERIC_TESTS, V8_TESTS],\n          exclude: [\n            ISTANBUL_TESTS,\n            UNIT_TESTS,\n            CUSTOM_TESTS,\n            BROWSER_TESTS,\n            FIXTURES,\n          ],\n        },\n      },\n\n      // Test cases for istanbul-provider\n      {\n        extends: true,\n        test: {\n          name: { label: 'istanbul', color: 'magenta' },\n          env: { COVERAGE_PROVIDER: 'istanbul' },\n          include: [GENERIC_TESTS, ISTANBUL_TESTS],\n          exclude: [\n            V8_TESTS,\n            UNIT_TESTS,\n            CUSTOM_TESTS,\n            BROWSER_TESTS,\n            FIXTURES,\n          ],\n        },\n      },\n\n      // Test cases for custom-provider\n      {\n        extends: true,\n        test: {\n          name: { label: 'custom', color: 'yellow' },\n          env: { COVERAGE_PROVIDER: 'custom' },\n          include: [CUSTOM_TESTS],\n          exclude: [FIXTURES],\n        },\n      },\n\n      // Test cases for browser. Browser mode itself is activated by COVERAGE_BROWSER env var.\n      {\n        extends: true,\n        test: {\n          name: { label: 'istanbul-browser', color: 'blue' },\n          env: { COVERAGE_PROVIDER: 'istanbul', COVERAGE_BROWSER: 'true' },\n          testTimeout: 15_000,\n          include: [\n            BROWSER_TESTS,\n\n            // Other non-provider-specific tests that should be run on browser mode as well\n            '**/all.test.ts',\n            '**/isolation.test.ts',\n            '**/include-exclude.test.ts',\n            '**/allow-external.test.ts',\n            '**/ignore-hints.test.ts',\n            '**/import-attributes.test.ts',\n            '**/pre-transpiled-source.test.ts',\n            '**/multi-suite.test.ts',\n            '**/setup-files.test.ts',\n            '**/results-snapshot.test.ts',\n            '**/reporters.test.ts',\n            '**/temporary-files.test.ts',\n            '**/test-reporter-conflicts.test.ts',\n            '**/vue.test.ts',\n            '**/in-source.test.ts',\n            '**/query-param-transforms.test.ts',\n            '**/test/cjs-dependency.test.ts',\n            '**/test/source-maps.test.ts',\n            '**/test/mock-autospy.test.ts',\n            '**/test/mock-importActual.test.ts',\n          ],\n          exclude: [FIXTURES],\n        },\n      },\n      {\n        extends: true,\n        test: {\n          name: { label: 'v8-browser', color: 'red' },\n          env: { COVERAGE_PROVIDER: 'v8', COVERAGE_BROWSER: 'true' },\n          testTimeout: 15_000,\n          include: [\n            BROWSER_TESTS,\n\n            // Other non-provider-specific tests that should be run on browser mode as well\n            '**/all.test.ts',\n            '**/isolation.test.ts',\n            '**/include-exclude.test.ts',\n            '**/allow-external.test.ts',\n            '**/ignore-hints.test.ts',\n            '**/import-attributes.test.ts',\n            '**/pre-transpiled-source.test.ts',\n            '**/multi-suite.test.ts',\n            '**/setup-files.test.ts',\n            '**/results-snapshot.test.ts',\n            '**/reporters.test.ts',\n            '**/temporary-files.test.ts',\n            '**/test-reporter-conflicts.test.ts',\n            '**/vue.test.ts',\n            '**/in-source.test.ts',\n            '**/query-param-transforms.test.ts',\n            '**/test/cjs-dependency.test.ts',\n            '**/test/source-maps.test.ts',\n            '**/test/mock-autospy.test.ts',\n            '**/test/mock-importActual.test.ts',\n          ],\n          exclude: [FIXTURES],\n        },\n      },\n\n      // Test cases for native runner\n      // @ts-expect-error Module.registerHooks is only available in Node.js v21+\n      ...(Module.registerHooks\n        ? [\n            {\n              extends: true,\n              test: {\n                name: { label: 'native', color: 'green' },\n                env: { COVERAGE_PROVIDER: 'v8', VITE_MODULE_RUNNER: 'false' },\n                include: [GENERIC_TESTS, V8_TESTS],\n                exclude: [\n                  ISTANBUL_TESTS,\n                  UNIT_TESTS,\n                  CUSTOM_TESTS,\n                  BROWSER_TESTS,\n                  FIXTURES,\n\n                  // Unsupported features\n                  '**/vue.test.ts',\n                  '**/workspace.multi-transform.test.ts',\n                  '**/web-worker.test.ts',\n                  '**/virtual-files.test.ts',\n                  '**/query-param-transforms.test.ts',\n                  '**/multi-environment.test.ts',\n                  '**/import-meta-env.test.ts',\n                  '**/decorators.test.ts',\n                  '**/import-attributes.test.ts',\n                ],\n              },\n            } satisfies TestProjectInlineConfiguration,\n          ]\n        : []),\n\n      // Test cases that aren't provider specific\n      {\n        extends: true,\n        test: {\n          name: { label: 'unit', color: 'cyan' },\n          include: [UNIT_TESTS],\n          typecheck: {\n            enabled: true,\n            include: ['**/test/*.test-d.ts'],\n            tsconfig: '../../tsconfig.check.json',\n            ignoreSourceErrors: true,\n          },\n        },\n      },\n    ],\n    fileParallelism: false,\n    onConsoleLog(log) {\n      if (log.includes('ERROR: Coverage for')) {\n        // Ignore threshold error messages\n        return false\n      }\n\n      if (log.includes('Updating thresholds to configuration file.')) {\n        // Ignore threshold updating messages\n        return false\n      }\n    },\n  },\n})\n"
  },
  {
    "path": "test/node-runner/fixtures/globalSetup/basic.test.js",
    "content": "import { expect, test } from 'vitest';\n\ntest('basic', () => {\n  expect(1).toBe(1)\n})\n"
  },
  {
    "path": "test/node-runner/fixtures/globalSetup/failing.ts",
    "content": "import assert from 'node:assert'\n// node can import from vitest at any point\nimport { beforeAll } from 'vitest'\n\nassert.throws(() => {\n  // some vitest API cannot be used outside of a test context\n  beforeAll(() => {})\n}, /Vitest failed to find the runner. One of the following is possible/)\n\nexport default () => {}\n"
  },
  {
    "path": "test/node-runner/package.json",
    "content": "{\n  \"name\": \"@test/node-runner\",\n  \"type\": \"module\",\n  \"description\": \"Tests that should have no access to Vitest APIs in the test process.\",\n  \"scripts\": {\n    \"test\": \"node --test './test/*'\"\n  }\n}\n"
  },
  {
    "path": "test/node-runner/test/cli.test.js",
    "content": "import test from 'node:test'\nimport { startVitest } from 'vitest/node'\n\nawait test('importing vitest in the global setup is reported as an error', async (t) => {\n  const vitest = await startVitest('test', [], {\n    root: './fixtures/globalSetup',\n    globalSetup: [\n      './failing.ts',\n    ],\n    reporters: [{}],\n  })\n  const modules = vitest.state.getTestModules()\n  t.assert.equal(modules.length, 1)\n  t.assert.equal(modules[0].state(), 'passed')\n})\n"
  },
  {
    "path": "test/snapshots/README.md",
    "content": "# Snapshot Tests\n\nThis directory contains integration tests for Vitest's snapshot functionality. It uses a meta-testing approach where integration tests programmatically run fixture tests to validate snapshot behavior.\n\n```bash\n# Run all integration tests\npnpm test\n\n# Run one fixture directly\npnpm test --root test/fixtures/summary\n```\n"
  },
  {
    "path": "test/snapshots/package.json",
    "content": "{\n  \"name\": \"@vitest/test-snapshots\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"vitest\"\n  },\n  \"dependencies\": {\n    \"vitest\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"jest-image-snapshot\": \"^6.5.1\"\n  }\n}\n"
  },
  {
    "path": "test/snapshots/test/ci.test.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { expect, test } from 'vitest'\nimport { runVitestCli } from '../../test-utils'\n\ntest('CI behavior', async () => {\n  // cleanup snapshot\n  const root = path.join(import.meta.dirname, 'fixtures/ci')\n  fs.rmSync(path.join(root, '__snapshots__'), { recursive: true, force: true })\n\n  // snapshot fails with CI\n  let result = await runVitestCli({\n    nodeOptions: {\n      env: {\n        CI: 'true',\n        GITHUB_ACTIONS: 'true',\n      },\n    },\n  }, '--root', root)\n  expect(result.stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts > basic\n    Error: Snapshot \\`basic 1\\` mismatched\n     ❯ basic.test.ts:4:16\n          2|\n          3| test(\"basic\", () => {\n          4|   expect(\"ok\").toMatchSnapshot()\n           |                ^\n          5| })\n          6|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n\n  // snapshot created without CI\n  result = await runVitestCli(\n    {\n      nodeOptions: {\n        env: {\n          CI: '',\n          GITHUB_ACTIONS: '',\n        },\n      },\n    },\n    '--root',\n    root,\n  )\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(result.stdout).toContain('Snapshots  1 written')\n})\n"
  },
  {
    "path": "test/snapshots/test/compare-keys.test.ts",
    "content": "import fs from 'node:fs'\nimport { join } from 'node:path'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('compareKeys', async () => {\n  const root = join(import.meta.dirname, 'fixtures/compare-keys')\n  fs.rmSync(join(root, '__snapshots__'), { recursive: true, force: true })\n\n  // compareKeys null\n  let vitest = await runVitest({\n    root,\n    update: true,\n    snapshotFormat: {\n      compareKeys: null,\n    },\n  })\n  expect(vitest.stderr).toBe('')\n  expect(fs.readFileSync(join(root, '__snapshots__/basic.test.ts.snap'), 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`compareKeys 1\\`] = \\`\n    {\n      \"a\": 1,\n      \"b\": 2,\n      \"c\": 3,\n    }\n    \\`;\n\n    exports[\\`compareKeys 2\\`] = \\`\n    {\n      \"c\": 1,\n      \"b\": 2,\n      \"a\": 3,\n    }\n    \\`;\n\n    exports[\\`compareKeys 3\\`] = \\`\n    {\n      \"b\": 1,\n      \"a\": 2,\n      \"c\": 3,\n    }\n    \\`;\n    \"\n  `)\n\n  // compareKeys undefined\n  vitest = await runVitest({\n    root,\n    update: true,\n    snapshotFormat: {\n      compareKeys: undefined,\n    },\n  })\n  expect(vitest.stderr).toBe('')\n  expect(fs.readFileSync(join(root, '__snapshots__/basic.test.ts.snap'), 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`compareKeys 1\\`] = \\`\n    {\n      \"a\": 1,\n      \"b\": 2,\n      \"c\": 3,\n    }\n    \\`;\n\n    exports[\\`compareKeys 2\\`] = \\`\n    {\n      \"a\": 3,\n      \"b\": 2,\n      \"c\": 1,\n    }\n    \\`;\n\n    exports[\\`compareKeys 3\\`] = \\`\n    {\n      \"a\": 2,\n      \"b\": 1,\n      \"c\": 3,\n    }\n    \\`;\n    \"\n  `)\n})\n"
  },
  {
    "path": "test/snapshots/test/custom-environment.test.ts",
    "content": "import { readFileSync, rmSync, writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'pathe'\nimport { afterEach, expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\nconst testFileName = resolve(import.meta.dirname, './fixtures/custom-snapshot-environment/test/snapshots.test.ts')\nconst snapshotFile = resolve(dirname(testFileName), './__snapshots__/snapshots.test.ts.snap')\nconst testFile = readFileSync(testFileName, 'utf-8')\n\nafterEach(() => {\n  writeFileSync(testFileName, testFile)\n  rmSync(snapshotFile)\n})\n\ntest('custom environment resolved correctly', async () => {\n  const { stdout, stderr } = await runVitest({\n    root: 'test/fixtures/custom-snapshot-environment',\n    update: true,\n  })\n\n  const snapshotLogs = stdout.split('\\n').filter(i => i.startsWith('## ')).join('\\n')\n  expect(stderr).toBe('')\n  expect(snapshotLogs).toMatchInlineSnapshot(`\n    \"## resolvePath test/fixtures/custom-snapshot-environment/test/snapshots.test.ts\n    ## readSnapshotFile test/fixtures/custom-snapshot-environment/test/__snapshots__/snapshots.test.ts.snap\n    ## getHeader\n    ## getVersion\n    ## readSnapshotFile test/fixtures/custom-snapshot-environment/test/__snapshots__/snapshots.test.ts.snap\n    ## saveSnapshotFile test/fixtures/custom-snapshot-environment/test/__snapshots__/snapshots.test.ts.snap\n    ## readSnapshotFile test/fixtures/custom-snapshot-environment/test/snapshots.test.ts\n    ## saveSnapshotFile test/fixtures/custom-snapshot-environment/test/snapshots.test.ts\"\n  `)\n})\n"
  },
  {
    "path": "test/snapshots/test/custom-serializers.test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('it should pass', async () => {\n  const { stdout, stderr } = await runVitest({\n    root: 'test/fixtures/custom-serializers',\n  })\n\n  expect(stdout).toContain('✓ custom-serializers.test.ts')\n  expect(stderr).toBe('')\n})\n"
  },
  {
    "path": "test/snapshots/test/file.test.ts",
    "content": "import { join } from 'node:path'\nimport { expect, test } from 'vitest'\nimport { editFile, runVitest } from '../../test-utils'\n\ntest('white space sensitive', async () => {\n  const root = join(import.meta.dirname, 'fixtures/file')\n\n  // check correct snapshot\n  let vitest = await runVitest({ root })\n  expect(vitest.exitCode).toBe(0)\n\n  // check diff of wrong snapshot\n  editFile(join(root, 'snapshot-1.txt'), s => s.trim())\n  editFile(join(root, 'snapshot-2.txt'), s => s.replace('echo', 'ECHO'))\n  vitest = await runVitest({ root })\n  expect(vitest.stderr).toContain(`\n- white space\n+\n+\n+   white space\n+\n`)\n  expect(vitest.stderr).toContain(`\n-     ECHO \"hello\"\n+     echo \"hello\"\n`)\n  expect(vitest.exitCode).toBe(1)\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/ci/.gitignore",
    "content": "__snapshots__\n"
  },
  {
    "path": "test/snapshots/test/fixtures/ci/basic.test.ts",
    "content": "import { test, expect } from \"vitest\"\n\ntest(\"basic\", () => {\n  expect(\"ok\").toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/compare-keys/__snapshots__/basic.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compareKeys 1`] = `\n{\n  \"a\": 1,\n  \"b\": 2,\n  \"c\": 3,\n}\n`;\n\nexports[`compareKeys 2`] = `\n{\n  \"a\": 3,\n  \"b\": 2,\n  \"c\": 1,\n}\n`;\n\nexports[`compareKeys 3`] = `\n{\n  \"a\": 2,\n  \"b\": 1,\n  \"c\": 3,\n}\n`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/compare-keys/basic.test.ts",
    "content": "import { test, expect } from 'vitest';\n\ntest('compareKeys', () => {\n  expect({\n    a: 1,\n    b: 2,\n    c: 3,\n  }).toMatchSnapshot();\n\n  expect({\n    c: 1,\n    b: 2,\n    a: 3,\n  }).toMatchSnapshot();\n\n  expect({\n    b: 1,\n    a: 2,\n    c: 3,\n  }).toMatchSnapshot();\n});\n"
  },
  {
    "path": "test/snapshots/test/fixtures/compare-keys/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    // snapshotFormat: {\n    //   compareKeys: null,\n    // }\n  }\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/custom-serializers/custom-serializers.test.ts",
    "content": "import { test, expect } from \"vitest\";\n\ntest(\"\", () => {\n  expect({foo: {\n    a: 1,\n    b: 2\n  }}).toMatchInlineSnapshot(`\n    Pretty foo: {\n      \"a\": 1,\n      \"b\": 2,\n    }\n  `);\n\n  expect({bar: {\n    a: 1,\n    b: 2\n  }}).toMatchInlineSnapshot(`\n    Pretty bar: {\n      \"a\": 1,\n      \"b\": 2,\n    }\n  `);\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/custom-serializers/serializer-1.js",
    "content": "export default {\n  serialize(val, config, indentation, depth, refs, printer) {\n    return `Pretty foo: ${printer(\n      val.foo,\n      config,\n      indentation,\n      depth,\n      refs,\n    )}`\n  },\n  test(val) {\n    return val && Object.prototype.hasOwnProperty.call(val, 'foo')\n  },\n}\n"
  },
  {
    "path": "test/snapshots/test/fixtures/custom-serializers/serializer-2.ts",
    "content": "import { SnapshotSerializer } from 'vitest'\n\nexport default {\n  serialize(val, config, indentation, depth, refs, printer) {\n    return `Pretty bar: ${printer(\n      val.bar,\n      config,\n      indentation,\n      depth,\n      refs,\n    )}`\n  },\n  test(val) {\n    return val && Object.prototype.hasOwnProperty.call(val, 'bar')\n  },\n} satisfies SnapshotSerializer\n"
  },
  {
    "path": "test/snapshots/test/fixtures/custom-serializers/vitest.config.ts",
    "content": "import { defineConfig } from \"vitest/config\";\n\nexport default defineConfig({\n  test: {\n    snapshotSerializers: ['./serializer-1.js', './serializer-2.ts']\n  }\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/custom-snapshot-environment/snapshot-environment.ts",
    "content": "import { relative as _relative } from 'pathe'\nimport { VitestSnapshotEnvironment } from 'vitest/runtime'\n\nfunction relative(file: string) {\n  return _relative(process.cwd(), file)\n}\n\nclass CustomSnapshotEnvironment extends VitestSnapshotEnvironment {\n  getVersion(): string {\n    console.log('## getVersion')\n    return super.getVersion()\n  }\n\n  getHeader() {\n    console.log('## getHeader')\n    return super.getHeader()\n  }\n\n  resolvePath(filepath: string) {\n    console.log('## resolvePath', relative(filepath))\n    return super.resolvePath(filepath)\n  }\n\n  resolveRawPath(testPath: string, rawPath: string) {\n    console.log('## resolveRawPath', relative(testPath), relative(rawPath))\n    return super.resolveRawPath(testPath, rawPath)\n  }\n\n  saveSnapshotFile(filepath: string, snapshot: string) {\n    console.log('## saveSnapshotFile', relative(filepath))\n    return super.saveSnapshotFile(filepath, snapshot)\n  }\n\n  readSnapshotFile(filepath: string) {\n    console.log('## readSnapshotFile', relative(filepath))\n    return super.readSnapshotFile(filepath)\n  }\n\n  removeSnapshotFile(filepath: string) {\n    console.log('## removeSnapshotFile', relative(filepath))\n    return super.removeSnapshotFile(filepath)\n  }\n}\n\nexport default new CustomSnapshotEnvironment()\n"
  },
  {
    "path": "test/snapshots/test/fixtures/custom-snapshot-environment/test/snapshots.test.ts",
    "content": "import {test, expect} from 'vitest'\n\ntest('regular snapshot', () => {\n  expect({ a: 1 }).toMatchSnapshot()\n})\n\ntest('inline snapshot', () => {\n  expect({ a: 1 }).toMatchInlineSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/custom-snapshot-environment/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    snapshotEnvironment: './snapshot-environment.ts'\n  }\n})"
  },
  {
    "path": "test/snapshots/test/fixtures/file/basic.test.ts",
    "content": "import { test, expect } from \"vitest\"\n\n// pnpm -C test/snapshots test:fixtures --root test/fixtures/file\n\ntest('white space', async () => {\n  await expect(`\n\n  white space\n`).toMatchFileSnapshot('snapshot-1.txt')\n})\n\ntest('indent', async () => {\n  await expect(`\\\nexample: |\n  {\n    echo \"hello\"\n  }\nsome:\n  nesting:\n    - \"hello world\"\neven:\n  more:\n    nesting: true\n`).toMatchFileSnapshot('snapshot-2.txt')\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/file/snapshot-1.txt",
    "content": "\n\n  white space\n"
  },
  {
    "path": "test/snapshots/test/fixtures/file/snapshot-2.txt",
    "content": "example: |\n  {\n    echo \"hello\"\n  }\nsome:\n  nesting:\n    - \"hello world\"\neven:\n  more:\n    nesting: true\n"
  },
  {
    "path": "test/snapshots/test/fixtures/indent/__snapshots__/basic.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`toMatchSnapshot string 1`] = `\n\"\n1111\n    xxxx {\n    }\n\n\"\n`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/indent/basic.test.ts",
    "content": "import { test, expect } from \"vitest\"\n\n// pnpm -C test/snapshots test:fixtures --root test/fixtures/indent\n\ntest('toMatchSnapshot string', () => {\n  expect(`\n1111\n    xxxx {\n    }\n\n`).toMatchSnapshot()\n})\n\ntest('toMatchInlineSnapshot string', () => {\n  expect(`\n2222\n    yyyy {\n    }\n\n`).toMatchInlineSnapshot(`\n  \"\n  2222\n      yyyy {\n      }\n\n  \"\n`)\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/inline-multiple-calls/different.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('single', () => {\n  for (const value of [\"test1\", \"test2\"]) {\n    expect(value).toMatchInlineSnapshot()\n  }\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/inline-multiple-calls/different2.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('a', () => {\n  snap('test1')\n})\n\ntest('b', () => {\n  snap('test2')\n})\n\nfunction snap(value: unknown) {\n  expect(value).toMatchInlineSnapshot()\n}\n"
  },
  {
    "path": "test/snapshots/test/fixtures/inline-multiple-calls/each.test.ts",
    "content": "import { expect, test, describe } from \"vitest\";\n\ntest.for([\"hello\", \"world\"])(\"test %s\", (arg) => {\n  expect(arg.length).toMatchInlineSnapshot(`5`);\n});\n\ndescribe.for([\"hello\", \"world\"])(\"suite %s\", (arg) => {\n  test(\"length\", () => {\n    expect(arg.length).toMatchInlineSnapshot(`5`);\n  });\n});\n\ntest.for([\"hello\", \"world\"])(\"toThrowErrorMatchingInlineSnapshot %s\", (arg) => {\n  expect(() => {\n    throw new Error(`length = ${arg.length}`);\n  }).toThrowErrorMatchingInlineSnapshot(`[Error: length = 5]`)\n});\n"
  },
  {
    "path": "test/snapshots/test/fixtures/inline-multiple-calls/same.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('single', () => {\n  for (const value of [\"test1\", \"test1\"]) {\n    expect(value).toMatchInlineSnapshot(`\"test1\"`)\n  }\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/inline-multiple-calls/same2.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('a', () => {\n  snap('test1')\n})\n\ntest('b', () => {\n  snap('test1')\n})\n\nfunction snap(value: unknown) {\n  expect(value).toMatchInlineSnapshot(`\"test1\"`)\n}\n"
  },
  {
    "path": "test/snapshots/test/fixtures/jest-image-snapshot/basic.test.ts",
    "content": "import { expect, it } from \"vitest\";\nimport fs from \"fs\";\n\n// @ts-expect-error no type\nimport { toMatchImageSnapshot } from \"jest-image-snapshot\";\nexpect.extend({ toMatchImageSnapshot });\n\ndeclare module 'vitest' {\n  interface Assertion<T = any> {\n    toMatchImageSnapshot(): void\n  }\n}\n\n// pnpm -C test/snapshots test:fixtures --root test/fixtures/jest-image-snapshot\n\nit(\"toMatchImageSnapshot\", async () => {\n  const file = new URL(\"./test.png\", import.meta.url)\n  expect(fs.readFileSync(file)).toMatchImageSnapshot();\n});\n"
  },
  {
    "path": "test/snapshots/test/fixtures/obsolete/src/__snapshots__/test1.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`bar 1`] = `\"bar\"`;\n\nexports[`foo 1`] = `\"foo\"`;\n\nexports[`fuu 1`] = `\"fuu\"`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/obsolete/src/__snapshots__/test2.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`bar 1`] = `\"bar\"`;\n\nexports[`foo 1`] = `\"foo\"`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/obsolete/src/test1.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('foo', () => {\n  if (process.env.TEST_OBSOLETE) return\n  expect(\"foo\").toMatchSnapshot();\n})\n\nit('fuu', () => {\n  if (process.env.TEST_OBSOLETE) return\n  expect(\"fuu\").toMatchSnapshot();\n})\n\nit('bar', () => {\n  expect(\"bar\").toMatchSnapshot();\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/obsolete/src/test2.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('foo', () => {\n  expect(\"foo\").toMatchSnapshot();\n})\n\nit('bar', () => {\n  expect(\"bar\").toMatchSnapshot();\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/obsolete/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/skip-test/__snapshots__/repro.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`repro suite > inner case 1`] = `\"hi-1\"`;\n\nexports[`top-level case 1`] = `\"hi-2\"`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/skip-test/repro.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\n\nconst ENABLE_SKIP = process.env.ENABLE_SKIP;\n\ndescribe.skipIf(ENABLE_SKIP)('repro suite', () => {\n  it('inner case', () => {\n    expect('hi-1').toMatchSnapshot()\n  })\n})\n\nit.skipIf(ENABLE_SKIP)('top-level case', () => {\n  expect('hi-2').toMatchSnapshot()\n})\n\n// at least one non-skipped test is needed to reproduce a bug.\n// without this, there will be no SnapshotClient.startCurrentRun,\n// so the code to check skip/obsolete snapshot is not exercised.\nit('normal case', () => {\n  expect(0).toBe(0)\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/skip-test/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/skip-test-custom/__snapshots__/basic.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`custom a > x 1`] = `0`;\n\nexports[`custom a > y 1`] = `0`;\n\nexports[`custom b > w 1`] = `0`;\n\nexports[`custom b > z 1`] = `0`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/skip-test-custom/basic.test.ts",
    "content": "import { expect, test } from 'vitest';\n\ntest('custom a', () => {\n  expect(0).toMatchSnapshot('x');\n  expect(0).toMatchSnapshot('y');\n});\n\ntest('custom b', () => {\n  expect(0).toMatchSnapshot('z');\n  expect(0).toMatchSnapshot('w');\n});\n"
  },
  {
    "path": "test/snapshots/test/fixtures/soft/.gitignore",
    "content": "__snapshots__\n"
  },
  {
    "path": "test/snapshots/test/fixtures/soft/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('toMatchSnapshot', () => {\n  expect.soft('--snap-1--').toMatchSnapshot()\n  expect.soft('--snap-2--').toMatchSnapshot()\n})\n\ntest('toMatchFileSnapshot', async () => {\n  await expect.soft('--file-1--').toMatchFileSnapshot('./__snapshots__/custom1.txt')\n  await expect.soft('--file-2--').toMatchFileSnapshot('./__snapshots__/custom2.txt')\n})\n\ntest('toThrowErrorMatchingSnapshot', () => {\n  expect.soft(() => { throw new Error('--error-1--') }).toThrowErrorMatchingSnapshot()\n  expect.soft(() => { throw new Error('--error-2--') }).toThrowErrorMatchingSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/soft-inline/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('toMatchInlineSnapshot', () => {\n  expect.soft('--snap-1--').toMatchInlineSnapshot(`\"--snap-1--\"`)\n  expect.soft('--snap-2--').toMatchInlineSnapshot(`\"--snap-2--\"`)\n})\n\ntest('toThrowErrorMatchingInlineSnapshot', () => {\n  expect.soft(() => { throw new Error('--error-1--') }).toThrowErrorMatchingInlineSnapshot(`[Error: --error-1--]`)\n  expect.soft(() => { throw new Error('--error-2--') }).toThrowErrorMatchingInlineSnapshot(`[Error: --error-2--]`)\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/summary/__snapshots__/basic.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`file normal 1`] = `\"@SNAP4\"`;\n\nexports[`file repeats 1`] = `\"@SNAP5\"`;\n\nexports[`file repeats many 1`] = `\"@SNAP7\"`;\n\nexports[`file repeats many 2`] = `\"@SNAP8\"`;\n\nexports[`file retry 1`] = `\"@SNAP6\"`;\n\nexports[`file retry many 1`] = `\"@SNAP9\"`;\n\nexports[`file retry many 2`] = `\"@SNAP10\"`;\n\nexports[`file retry partial 1`] = `\"@SNAP11\"`;\n\nexports[`file retry partial 2`] = `\"@SNAP12\"`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/summary/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('inline normal', () => {\n  expect('@SNAP1').toMatchInlineSnapshot(`\"@SNAP1\"`)\n})\n\ntest('inline repeats', { repeats: 1 }, () => {\n  expect('@SNAP2').toMatchInlineSnapshot(`\"@SNAP2\"`)\n})\n\ntest('inline retry', { retry: 1 }, (ctx) => {\n  expect('@SNAP3').toMatchInlineSnapshot(`\"@SNAP3\"`)\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('boom')\n  }\n})\n\ntest('file normal', () => {\n  expect('@SNAP4').toMatchSnapshot()\n})\n\ntest('file repeats', { repeats: 1 }, () => {\n  expect('@SNAP5').toMatchSnapshot()\n})\n\ntest('file retry', { retry: 1 }, (ctx) => {\n  expect('@SNAP6').toMatchSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('@retry')\n  }\n})\n\ntest('file repeats many', { repeats: 1 }, () => {\n  expect('@SNAP7').toMatchSnapshot()\n  expect('@SNAP8').toMatchSnapshot()\n})\n\ntest('file retry many', { retry: 1 }, (ctx) => {\n  expect('@SNAP9').toMatchSnapshot()\n  expect('@SNAP10').toMatchSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('@retry')\n  }\n})\n\ntest('file retry partial', { retry: 1 }, (ctx) => {\n  expect('@SNAP11').toMatchSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('@retry')\n  }\n  expect('@SNAP12').toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/summary/vitest.config.ts",
    "content": "export default {}\n"
  },
  {
    "path": "test/snapshots/test/fixtures/summary-removed/.gitignore",
    "content": "__snapshots__\n"
  },
  {
    "path": "test/snapshots/test/fixtures/summary-removed/basic.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('x', () => {\n  expect(0).toMatchSnapshot()\n})\n\n// REMOVE-START\ntest('y', () => {\n  expect(0).toMatchSnapshot()\n})\n// REMOVE-END\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update/__snapshots__/retry-file.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`file repeats 1`] = `\"foo\"`;\n\nexports[`file repeats many 1`] = `\"foo\"`;\n\nexports[`file repeats many 2`] = `\"bar\"`;\n\nexports[`file retry 1`] = `\"foo\"`;\n\nexports[`file retry many 1`] = `\"foo\"`;\n\nexports[`file retry many 2`] = `\"bar\"`;\n\nexports[`file retry partial 1`] = `\"foo\"`;\n\nexports[`file retry partial 2`] = `\"bar\"`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update/__snapshots__/same-title-file.test.js.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`same title exist 1`] = `\"a\"`;\n\nexports[`same title exist 2`] = `\"wrong\"`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update/inline-concurrent.test.js",
    "content": "import { it } from 'vitest'\n\nit.concurrent('1st', ({ expect }) => {\n  expect('hi1').toMatchInlineSnapshot()\n})\n\nit.concurrent('2nd', ({ expect }) => {\n  expect('hi2').toMatchInlineSnapshot()\n})\n\nit.concurrent('3rd', ({ expect }) => {\n  expect('hi3').toMatchInlineSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update/inline.test.js",
    "content": "import { describe, expect, test } from 'vitest'\n\n// when snapshots are generated Vitest reruns `toMatchInlineSnapshot` checks\n// please, don't commit generated snapshots\ndescribe('snapshots are generated in correct order', async () => {\n  test('first snapshot', () => {\n    expect({ foo: ['bar'] }).toMatchInlineSnapshot()\n  })\n\n  test('second snapshot', () => {\n    expect({ foo: ['zed'] }).toMatchInlineSnapshot()\n  })\n})\n\ndescribe('snapshots with properties', () => {\n  test('without snapshot', () => {\n    expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) })\n  })\n\n  test('with snapshot', () => {\n    expect({ first: { second: { foo: 'bar' } } }).toMatchInlineSnapshot({ first: { second: { foo: expect.any(String) } } }, `\n      Object {\n        \"first\": Object {\n          \"wrong\": Any<String>,\n          \"second\": null,\n        }\n      }\n    `)\n  })\n\n  test('mixed with and without snapshot', () => {\n    expect({ first: { second: { foo: 'bar' } } }).toMatchInlineSnapshot({ first: { second: { foo: expect.any(String) } } }, `\n      Object {\n        \"first\": Object {\n          \"wrong\": Any<String>,\n          \"second\": null,\n        }\n      }\n    `)\n\n    expect({ first: { second: { foo: 'zed' } } }).toMatchInlineSnapshot(`\n      Object {\n        \"first\": Object {\n          \"second\": {\n            \"foo\": \"zed\"\n          }\n        }\n      }\n    `)\n  })\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update/retry-file.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('file repeats', { repeats: 1 }, () => {\n  expect('foo').toMatchSnapshot()\n})\n\ntest('file retry', { retry: 1 }, (ctx) => {\n  expect('foo').toMatchSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('boom')\n  }\n})\n\ntest('file repeats many', { repeats: 1 }, () => {\n  expect('foo').toMatchSnapshot()\n  expect('bar').toMatchSnapshot()\n})\n\ntest('file retry many', { retry: 1 }, (ctx) => {\n  expect('foo').toMatchSnapshot()\n  expect('bar').toMatchSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('boom')\n  }\n})\n\ntest('file retry partial', { retry: 1 }, (ctx) => {\n  expect('foo').toMatchSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('boom')\n  }\n  expect('bar').toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update/retry-inline.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('inline repeats', { repeats: 1 }, () => {\n  expect('foo').toMatchInlineSnapshot()\n})\n\ntest('inline retry', { retry: 1 }, (ctx) => {\n  expect('foo').toMatchInlineSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('boom')\n  }\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update/same-title-file.test.js",
    "content": "import { expect, test } from 'vitest'\n\ntest('same title exist', () => {\n  // correct entry exists in .snap\n  expect('a').toMatchSnapshot()\n})\n\ntest('same title exist', () => {\n  // wrong entry exists in .snap\n  expect('b').toMatchSnapshot()\n})\n\ntest('same title new', () => {\n  expect('a').toMatchSnapshot()\n})\n\ntest('same title new', () => {\n  expect('b').toMatchSnapshot()\n  expect('c').toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update/same-title-inline.test.js",
    "content": "import { expect, test } from 'vitest'\n\ntest('same title', () => {\n  expect('new').toMatchInlineSnapshot()\n  expect('new').toMatchInlineSnapshot()\n})\n\ntest('same title', () => {\n  expect('a').toMatchInlineSnapshot(`\"a\"`)\n  expect('a').toMatchInlineSnapshot(`\"a\"`)\n})\n\ntest('same title', () => {\n  expect('b').toMatchInlineSnapshot(`\"wrong\"`)\n  expect('b').toMatchInlineSnapshot(`\"wrong\"`)\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update-result/__snapshots__/retry-file.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`file repeats 1`] = `\"foo\"`;\n\nexports[`file repeats many 1`] = `\"foo\"`;\n\nexports[`file repeats many 2`] = `\"bar\"`;\n\nexports[`file retry 1`] = `\"foo\"`;\n\nexports[`file retry many 1`] = `\"foo\"`;\n\nexports[`file retry many 2`] = `\"bar\"`;\n\nexports[`file retry partial 1`] = `\"foo\"`;\n\nexports[`file retry partial 2`] = `\"bar\"`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update-result/__snapshots__/same-title-file.test.js.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`same title exist 1`] = `\"a\"`;\n\nexports[`same title exist 2`] = `\"b\"`;\n\nexports[`same title new 1`] = `\"a\"`;\n\nexports[`same title new 2`] = `\"b\"`;\n\nexports[`same title new 3`] = `\"c\"`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update-result/inline-concurrent.test.js",
    "content": "import { it } from 'vitest'\n\nit.concurrent('1st', ({ expect }) => {\n  expect('hi1').toMatchInlineSnapshot(`\"hi1\"`)\n})\n\nit.concurrent('2nd', ({ expect }) => {\n  expect('hi2').toMatchInlineSnapshot(`\"hi2\"`)\n})\n\nit.concurrent('3rd', ({ expect }) => {\n  expect('hi3').toMatchInlineSnapshot(`\"hi3\"`)\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update-result/inline.test.js",
    "content": "import { describe, expect, test } from 'vitest'\n\n// when snapshots are generated Vitest reruns `toMatchInlineSnapshot` checks\n// please, don't commit generated snapshots\ndescribe('snapshots are generated in correct order', async () => {\n  test('first snapshot', () => {\n    expect({ foo: ['bar'] }).toMatchInlineSnapshot(`\n      Object {\n        \"foo\": Array [\n          \"bar\",\n        ],\n      }\n    `)\n  })\n\n  test('second snapshot', () => {\n    expect({ foo: ['zed'] }).toMatchInlineSnapshot(`\n      Object {\n        \"foo\": Array [\n          \"zed\",\n        ],\n      }\n    `)\n  })\n})\n\ndescribe('snapshots with properties', () => {\n  test('without snapshot', () => {\n    expect({ foo: 'bar' }).toMatchInlineSnapshot({ foo: expect.any(String) }, `\n      Object {\n        \"foo\": Any<String>,\n      }\n    `)\n  })\n\n  test('with snapshot', () => {\n    expect({ first: { second: { foo: 'bar' } } }).toMatchInlineSnapshot({ first: { second: { foo: expect.any(String) } } }, `\n      Object {\n        \"first\": Object {\n          \"second\": Object {\n            \"foo\": Any<String>,\n          },\n        },\n      }\n    `)\n  })\n\n  test('mixed with and without snapshot', () => {\n    expect({ first: { second: { foo: 'bar' } } }).toMatchInlineSnapshot({ first: { second: { foo: expect.any(String) } } }, `\n      Object {\n        \"first\": Object {\n          \"second\": Object {\n            \"foo\": Any<String>,\n          },\n        },\n      }\n    `)\n\n    expect({ first: { second: { foo: 'zed' } } }).toMatchInlineSnapshot(`\n      Object {\n        \"first\": Object {\n          \"second\": Object {\n            \"foo\": \"zed\",\n          },\n        },\n      }\n    `)\n  })\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update-result/retry-file.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('file repeats', { repeats: 1 }, () => {\n  expect('foo').toMatchSnapshot()\n})\n\ntest('file retry', { retry: 1 }, (ctx) => {\n  expect('foo').toMatchSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('boom')\n  }\n})\n\ntest('file repeats many', { repeats: 1 }, () => {\n  expect('foo').toMatchSnapshot()\n  expect('bar').toMatchSnapshot()\n})\n\ntest('file retry many', { retry: 1 }, (ctx) => {\n  expect('foo').toMatchSnapshot()\n  expect('bar').toMatchSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('boom')\n  }\n})\n\ntest('file retry partial', { retry: 1 }, (ctx) => {\n  expect('foo').toMatchSnapshot()\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('boom')\n  }\n  expect('bar').toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update-result/retry-inline.test.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('inline repeats', { repeats: 1 }, () => {\n  expect('foo').toMatchInlineSnapshot(`\"foo\"`)\n})\n\ntest('inline retry', { retry: 1 }, (ctx) => {\n  expect('foo').toMatchInlineSnapshot(`\"foo\"`)\n  if (ctx.task.result?.retryCount === 0) {\n    throw new Error('boom')\n  }\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update-result/same-title-file.test.js",
    "content": "import { expect, test } from 'vitest'\n\ntest('same title exist', () => {\n  // correct entry exists in .snap\n  expect('a').toMatchSnapshot()\n})\n\ntest('same title exist', () => {\n  // wrong entry exists in .snap\n  expect('b').toMatchSnapshot()\n})\n\ntest('same title new', () => {\n  expect('a').toMatchSnapshot()\n})\n\ntest('same title new', () => {\n  expect('b').toMatchSnapshot()\n  expect('c').toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/test-update-result/same-title-inline.test.js",
    "content": "import { expect, test } from 'vitest'\n\ntest('same title', () => {\n  expect('new').toMatchInlineSnapshot(`\"new\"`)\n  expect('new').toMatchInlineSnapshot(`\"new\"`)\n})\n\ntest('same title', () => {\n  expect('a').toMatchInlineSnapshot(`\"a\"`)\n  expect('a').toMatchInlineSnapshot(`\"a\"`)\n})\n\ntest('same title', () => {\n  expect('b').toMatchInlineSnapshot(`\"b\"`)\n  expect('b').toMatchInlineSnapshot(`\"b\"`)\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/workspace/packages/space/test/__snapshots__/basic.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`basic 1`] = `1`;\n"
  },
  {
    "path": "test/snapshots/test/fixtures/workspace/packages/space/test/basic.test.ts",
    "content": "import { test, expect } from \"vitest\"\n\ntest(\"basic\", () => {\n  expect(1).toMatchSnapshot()\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/workspace/packages/space/vite.config.ts",
    "content": "import { defineProject } from 'vitest/config'\n\nexport default defineProject({\n  test: {},\n})\n"
  },
  {
    "path": "test/snapshots/test/fixtures/workspace/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    projects: ['packages/*'],\n  },\n})\n"
  },
  {
    "path": "test/snapshots/test/indent.test.ts",
    "content": "import { join } from 'node:path'\nimport { expect, test } from 'vitest'\nimport { editFile, runVitest } from '../../test-utils'\n\ntest('white space sensitive', async () => {\n  const root = join(import.meta.dirname, 'fixtures/indent')\n\n  // ensure correct snapshot\n  let vitest = await runVitest({ root, update: true })\n  expect(vitest.exitCode).toBe(0)\n\n  // check diff of wrong snapshot\n  editFile(join(root, 'basic.test.ts'), s => s.replace('1111', 'aaaa').replace('2222', 'bbbb'))\n  vitest = await runVitest({ root })\n  expect(vitest.stderr).toContain(`\n- 1111\n+ aaaa\n      xxxx {\n      }\n`)\n  expect(vitest.stderr).toContain(`\n- 2222\n+ bbbb\n      yyyy {\n      }\n`)\n  expect(vitest.exitCode).toBe(1)\n})\n"
  },
  {
    "path": "test/snapshots/test/inline-multiple-calls.test.ts",
    "content": "import fs, { readFileSync } from 'node:fs'\nimport { join } from 'pathe'\nimport { expect, test } from 'vitest'\nimport { editFile, runVitest } from '../../test-utils'\n\n// pnpm -C test/snapshots test:snaps inline-multiple-calls\n\ntest('same snapshots in single test', async () => {\n  // pnpm -C test/snapshots test:fixtures --root test/fixtures/inline-multiple-calls same.test\n\n  // reset snapshot\n  const root = join(import.meta.dirname, 'fixtures/inline-multiple-calls')\n  const testFile = join(root, 'same.test.ts')\n  editFile(testFile, s => s.replace(/toMatchInlineSnapshot\\(`.*`\\)/gs, 'toMatchInlineSnapshot()'))\n\n  // initial run (create snapshot)\n  let vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.stderr).toBe('')\n  expect(vitest.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n    Object {\n      \"added\": 2,\n      \"didUpdate\": true,\n      \"failure\": false,\n      \"filesAdded\": 1,\n      \"filesRemoved\": 0,\n      \"filesRemovedList\": Array [],\n      \"filesUnmatched\": 0,\n      \"filesUpdated\": 0,\n      \"matched\": 0,\n      \"total\": 2,\n      \"unchecked\": 0,\n      \"uncheckedKeysByFile\": Array [],\n      \"unmatched\": 0,\n      \"updated\": 0,\n    }\n  `)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n\n  // no-update run\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: false,\n  })\n  expect(vitest.stderr).toBe('')\n  expect(vitest.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n    Object {\n      \"added\": 0,\n      \"didUpdate\": false,\n      \"failure\": false,\n      \"filesAdded\": 0,\n      \"filesRemoved\": 0,\n      \"filesRemovedList\": Array [],\n      \"filesUnmatched\": 0,\n      \"filesUpdated\": 0,\n      \"matched\": 2,\n      \"total\": 2,\n      \"unchecked\": 0,\n      \"uncheckedKeysByFile\": Array [],\n      \"unmatched\": 0,\n      \"updated\": 0,\n    }\n  `)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n\n  // update run\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n    Object {\n      \"added\": 0,\n      \"didUpdate\": true,\n      \"failure\": false,\n      \"filesAdded\": 0,\n      \"filesRemoved\": 0,\n      \"filesRemovedList\": Array [],\n      \"filesUnmatched\": 0,\n      \"filesUpdated\": 0,\n      \"matched\": 2,\n      \"total\": 2,\n      \"unchecked\": 0,\n      \"uncheckedKeysByFile\": Array [],\n      \"unmatched\": 0,\n      \"updated\": 0,\n    }\n  `)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n})\n\ntest('same snapshots in multiple tests', async () => {\n  // pnpm -C test/snapshots test:fixtures --root test/fixtures/inline-multiple-calls same2.test\n\n  // reset snapshot\n  const root = join(import.meta.dirname, 'fixtures/inline-multiple-calls')\n  const testFile = join(root, 'same2.test.ts')\n  editFile(testFile, s => s.replace(/toMatchInlineSnapshot\\(`.*`\\)/gs, 'toMatchInlineSnapshot()'))\n\n  // initial run (create snapshot)\n  let vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.stderr).toBe('')\n  expect(vitest.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n    Object {\n      \"added\": 2,\n      \"didUpdate\": true,\n      \"failure\": false,\n      \"filesAdded\": 1,\n      \"filesRemoved\": 0,\n      \"filesRemovedList\": Array [],\n      \"filesUnmatched\": 0,\n      \"filesUpdated\": 0,\n      \"matched\": 0,\n      \"total\": 2,\n      \"unchecked\": 0,\n      \"uncheckedKeysByFile\": Array [],\n      \"unmatched\": 0,\n      \"updated\": 0,\n    }\n  `)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n\n  // no-update run\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: false,\n  })\n  expect(vitest.stderr).toBe('')\n  expect(vitest.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n    Object {\n      \"added\": 0,\n      \"didUpdate\": false,\n      \"failure\": false,\n      \"filesAdded\": 0,\n      \"filesRemoved\": 0,\n      \"filesRemovedList\": Array [],\n      \"filesUnmatched\": 0,\n      \"filesUpdated\": 0,\n      \"matched\": 2,\n      \"total\": 2,\n      \"unchecked\": 0,\n      \"uncheckedKeysByFile\": Array [],\n      \"unmatched\": 0,\n      \"updated\": 0,\n    }\n  `)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n\n  // update run\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n    Object {\n      \"added\": 0,\n      \"didUpdate\": true,\n      \"failure\": false,\n      \"filesAdded\": 0,\n      \"filesRemoved\": 0,\n      \"filesRemovedList\": Array [],\n      \"filesUnmatched\": 0,\n      \"filesUpdated\": 0,\n      \"matched\": 2,\n      \"total\": 2,\n      \"unchecked\": 0,\n      \"uncheckedKeysByFile\": Array [],\n      \"unmatched\": 0,\n      \"updated\": 0,\n    }\n  `)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n})\n\ntest('different snapshots in single test', async () => {\n  // pnpm -C test/snapshots test:fixtures --root test/fixtures/inline-multiple-calls different.test\n\n  // reset snapshot\n  const root = join(import.meta.dirname, 'fixtures/inline-multiple-calls')\n  const testFile = join(root, 'different.test.ts')\n  editFile(testFile, s => s.replace(/toMatchInlineSnapshot\\(`.*`\\)/gs, 'toMatchInlineSnapshot()'))\n\n  // update run should fail\n  let vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot()')\n  expect(vitest.exitCode).not.toBe(0)\n\n  // no-update run should fail\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: false,\n  })\n  if (process.env.CI) {\n    expect(vitest.stderr).toContain(`\nError: Snapshot \\`single 1\\` mismatched\n`)\n  }\n  else {\n    expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  }\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot()')\n\n  // current snapshot is \"test1\"\n  editFile(testFile, s => s.replace('expect(value).toMatchInlineSnapshot()', 'expect(value).toMatchInlineSnapshot(`\"test1\"`)'))\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: false,\n  })\n  expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n\n  // current snapshot is \"test2\"\n  editFile(testFile, s => s.replace('expect(value).toMatchInlineSnapshot(`\"test1\"`)', 'expect(value).toMatchInlineSnapshot(`\"test2\"`)'))\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test2\"`)')\n\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: false,\n  })\n  expect(vitest.stderr).toContain(`\nError: Snapshot \\`single 1\\` mismatched\n\nExpected: \"\"test2\"\"\nReceived: \"\"test1\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test2\"`)')\n})\n\ntest('different snapshots in multiple tests', async () => {\n  // pnpm -C test/snapshots test:fixtures --root test/fixtures/inline-multiple-calls different2.test\n\n  // reset snapshot\n  const root = join(import.meta.dirname, 'fixtures/inline-multiple-calls')\n  const testFile = join(root, 'different2.test.ts')\n  editFile(testFile, s => s.replace(/toMatchInlineSnapshot\\(`.*`\\)/gs, 'toMatchInlineSnapshot()'))\n\n  // update run should fail\n  let vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot()')\n  expect(vitest.exitCode).not.toBe(0)\n\n  // no-update run should fail\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: false,\n  })\n  if (process.env.CI) {\n    expect(vitest.stderr).toContain(`\nError: Snapshot \\`a 1\\` mismatched\n`)\n  }\n  else {\n    expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  }\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot()')\n\n  // current snapshot is \"test1\"\n  editFile(testFile, s => s.replace('expect(value).toMatchInlineSnapshot()', 'expect(value).toMatchInlineSnapshot(`\"test1\"`)'))\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: false,\n  })\n  expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test1\"`)')\n\n  // current snapshot is \"test2\"\n  editFile(testFile, s => s.replace('expect(value).toMatchInlineSnapshot(`\"test1\"`)', 'expect(value).toMatchInlineSnapshot(`\"test2\"`)'))\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: true,\n  })\n  expect(vitest.stderr).toContain(`\nError: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\nExpected: \"\"test1\"\"\nReceived: \"\"test2\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test2\"`)')\n\n  vitest = await runVitest({\n    root,\n    include: [testFile],\n    update: false,\n  })\n  expect(vitest.stderr).toContain(`\nError: Snapshot \\`a 1\\` mismatched\n\nExpected: \"\"test2\"\"\nReceived: \"\"test1\"\"\n`)\n  expect(fs.readFileSync(testFile, 'utf-8')).toContain('expect(value).toMatchInlineSnapshot(`\"test2\"`)')\n})\n\ntest('test.each/for', async () => {\n  const root = join(import.meta.dirname, 'fixtures/inline-multiple-calls')\n  const testFile = join(root, 'each.test.ts')\n\n  // remove inline snapshots\n  editFile(testFile, s => s\n    .replace(/toMatchInlineSnapshot\\(`[^`]*`\\)/g, 'toMatchInlineSnapshot()')\n    .replace(/toThrowErrorMatchingInlineSnapshot\\(`[^`]*`\\)/g, 'toThrowErrorMatchingInlineSnapshot()'))\n\n  // create snapshots from scratch\n  let result = await runVitest({ root, include: [testFile], update: 'new' })\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(readFileSync(testFile, 'utf-8')).toMatchInlineSnapshot(`\n    \"import { expect, test, describe } from \"vitest\";\n\n    test.for([\"hello\", \"world\"])(\"test %s\", (arg) => {\n      expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n    });\n\n    describe.for([\"hello\", \"world\"])(\"suite %s\", (arg) => {\n      test(\"length\", () => {\n        expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n      });\n    });\n\n    test.for([\"hello\", \"world\"])(\"toThrowErrorMatchingInlineSnapshot %s\", (arg) => {\n      expect(() => {\n        throw new Error(\\`length = \\${arg.length}\\`);\n      }).toThrowErrorMatchingInlineSnapshot(\\`[Error: length = 5]\\`)\n    });\n    \"\n  `)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"each.test.ts\": Object {\n        \"suite hello\": Object {\n          \"length\": \"passed\",\n        },\n        \"suite world\": Object {\n          \"length\": \"passed\",\n        },\n        \"test hello\": \"passed\",\n        \"test world\": \"passed\",\n        \"toThrowErrorMatchingInlineSnapshot hello\": \"passed\",\n        \"toThrowErrorMatchingInlineSnapshot world\": \"passed\",\n      },\n    }\n  `)\n  expect(result.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n    Object {\n      \"added\": 6,\n      \"didUpdate\": false,\n      \"failure\": false,\n      \"filesAdded\": 1,\n      \"filesRemoved\": 0,\n      \"filesRemovedList\": Array [],\n      \"filesUnmatched\": 0,\n      \"filesUpdated\": 0,\n      \"matched\": 0,\n      \"total\": 6,\n      \"unchecked\": 0,\n      \"uncheckedKeysByFile\": Array [],\n      \"unmatched\": 0,\n      \"updated\": 0,\n    }\n  `)\n\n  // edit tests to introduce errors\n  editFile(testFile, s => s.replaceAll(`\"hello\"`, `\"hey\"`))\n\n  // fails with update=false\n  result = await runVitest({ root, include: [testFile], update: false })\n  expect(result.stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 6 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  each.test.ts > test hey\n    Error: Snapshot \\`test hey 1\\` mismatched\n\n    Expected: \"5\"\n    Received: \"3\"\n\n     ❯ each.test.ts:4:22\n          2|\n          3| test.for([\"hey\", \"world\"])(\"test %s\", (arg) => {\n          4|   expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n           |                      ^\n          5| });\n          6|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/6]⎯\n\n     FAIL  each.test.ts > test world\n    Error: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\n    Expected: \"3\"\n    Received: \"5\"\n\n     ❯ each.test.ts:4:22\n          2|\n          3| test.for([\"hey\", \"world\"])(\"test %s\", (arg) => {\n          4|   expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n           |                      ^\n          5| });\n          6|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/6]⎯\n\n     FAIL  each.test.ts > suite hey > length\n    Error: Snapshot \\`suite hey > length 1\\` mismatched\n\n    Expected: \"5\"\n    Received: \"3\"\n\n     ❯ each.test.ts:9:24\n          7| describe.for([\"hey\", \"world\"])(\"suite %s\", (arg) => {\n          8|   test(\"length\", () => {\n          9|     expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n           |                        ^\n         10|   });\n         11| });\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/6]⎯\n\n     FAIL  each.test.ts > suite world > length\n    Error: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\n    Expected: \"3\"\n    Received: \"5\"\n\n     ❯ each.test.ts:9:24\n          7| describe.for([\"hey\", \"world\"])(\"suite %s\", (arg) => {\n          8|   test(\"length\", () => {\n          9|     expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n           |                        ^\n         10|   });\n         11| });\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/6]⎯\n\n     FAIL  each.test.ts > toThrowErrorMatchingInlineSnapshot hey\n    Error: Snapshot \\`toThrowErrorMatchingInlineSnapshot hey 1\\` mismatched\n\n    Expected: \"[Error: length = 5]\"\n    Received: \"[Error: length = 3]\"\n\n     ❯ each.test.ts:16:6\n         14|   expect(() => {\n         15|     throw new Error(\\`length = \\${arg.length}\\`);\n         16|   }).toThrowErrorMatchingInlineSnapshot(\\`[Error: length = 5]\\`)\n           |      ^\n         17| });\n         18|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/6]⎯\n\n     FAIL  each.test.ts > toThrowErrorMatchingInlineSnapshot world\n    Error: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\n    Expected: \"[Error: length = 3]\"\n    Received: \"[Error: length = 5]\"\n\n     ❯ each.test.ts:16:6\n         14|   expect(() => {\n         15|     throw new Error(\\`length = \\${arg.length}\\`);\n         16|   }).toThrowErrorMatchingInlineSnapshot(\\`[Error: length = 5]\\`)\n           |      ^\n         17| });\n         18|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/6]⎯\n\n    \"\n  `)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"each.test.ts\": Object {\n        \"suite hey\": Object {\n          \"length\": Array [\n            \"Snapshot \\`suite hey > length 1\\` mismatched\",\n          ],\n        },\n        \"suite world\": Object {\n          \"length\": Array [\n            \"toMatchInlineSnapshot with different snapshots cannot be called at the same location\",\n          ],\n        },\n        \"test hey\": Array [\n          \"Snapshot \\`test hey 1\\` mismatched\",\n        ],\n        \"test world\": Array [\n          \"toMatchInlineSnapshot with different snapshots cannot be called at the same location\",\n        ],\n        \"toThrowErrorMatchingInlineSnapshot hey\": Array [\n          \"Snapshot \\`toThrowErrorMatchingInlineSnapshot hey 1\\` mismatched\",\n        ],\n        \"toThrowErrorMatchingInlineSnapshot world\": Array [\n          \"toMatchInlineSnapshot with different snapshots cannot be called at the same location\",\n        ],\n      },\n    }\n  `)\n  expect(result.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n      Object {\n        \"added\": 0,\n        \"didUpdate\": false,\n        \"failure\": false,\n        \"filesAdded\": 0,\n        \"filesRemoved\": 0,\n        \"filesRemovedList\": Array [],\n        \"filesUnmatched\": 1,\n        \"filesUpdated\": 0,\n        \"matched\": 0,\n        \"total\": 3,\n        \"unchecked\": 0,\n        \"uncheckedKeysByFile\": Array [],\n        \"unmatched\": 3,\n        \"updated\": 0,\n      }\n    `)\n\n  // fails with update=all\n  result = await runVitest({ root, include: [testFile], update: 'all' })\n  expect(result.stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  each.test.ts > test world\n    Error: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\n    Expected: \"3\"\n    Received: \"5\"\n\n     ❯ each.test.ts:4:22\n          2|\n          3| test.for([\"hey\", \"world\"])(\"test %s\", (arg) => {\n          4|   expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n           |                      ^\n          5| });\n          6|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯\n\n     FAIL  each.test.ts > suite world > length\n    Error: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\n    Expected: \"3\"\n    Received: \"5\"\n\n     ❯ each.test.ts:9:24\n          7| describe.for([\"hey\", \"world\"])(\"suite %s\", (arg) => {\n          8|   test(\"length\", () => {\n          9|     expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n           |                        ^\n         10|   });\n         11| });\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯\n\n     FAIL  each.test.ts > toThrowErrorMatchingInlineSnapshot world\n    Error: toMatchInlineSnapshot with different snapshots cannot be called at the same location\n\n    Expected: \"[Error: length = 3]\"\n    Received: \"[Error: length = 5]\"\n\n     ❯ each.test.ts:16:6\n         14|   expect(() => {\n         15|     throw new Error(\\`length = \\${arg.length}\\`);\n         16|   }).toThrowErrorMatchingInlineSnapshot(\\`[Error: length = 5]\\`)\n           |      ^\n         17| });\n         18|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯\n\n    \"\n  `)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"each.test.ts\": Object {\n        \"suite hey\": Object {\n          \"length\": \"passed\",\n        },\n        \"suite world\": Object {\n          \"length\": Array [\n            \"toMatchInlineSnapshot with different snapshots cannot be called at the same location\",\n          ],\n        },\n        \"test hey\": \"passed\",\n        \"test world\": Array [\n          \"toMatchInlineSnapshot with different snapshots cannot be called at the same location\",\n        ],\n        \"toThrowErrorMatchingInlineSnapshot hey\": \"passed\",\n        \"toThrowErrorMatchingInlineSnapshot world\": Array [\n          \"toMatchInlineSnapshot with different snapshots cannot be called at the same location\",\n        ],\n      },\n    }\n  `)\n  expect(readFileSync(testFile, 'utf-8')).toMatchInlineSnapshot(`\n    \"import { expect, test, describe } from \"vitest\";\n\n    test.for([\"hey\", \"world\"])(\"test %s\", (arg) => {\n      expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n    });\n\n    describe.for([\"hey\", \"world\"])(\"suite %s\", (arg) => {\n      test(\"length\", () => {\n        expect(arg.length).toMatchInlineSnapshot(\\`5\\`);\n      });\n    });\n\n    test.for([\"hey\", \"world\"])(\"toThrowErrorMatchingInlineSnapshot %s\", (arg) => {\n      expect(() => {\n        throw new Error(\\`length = \\${arg.length}\\`);\n      }).toThrowErrorMatchingInlineSnapshot(\\`[Error: length = 5]\\`)\n    });\n    \"\n  `)\n  expect(result.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n      Object {\n        \"added\": 0,\n        \"didUpdate\": true,\n        \"failure\": false,\n        \"filesAdded\": 0,\n        \"filesRemoved\": 0,\n        \"filesRemovedList\": Array [],\n        \"filesUnmatched\": 0,\n        \"filesUpdated\": 1,\n        \"matched\": 0,\n        \"total\": 3,\n        \"unchecked\": 0,\n        \"uncheckedKeysByFile\": Array [],\n        \"unmatched\": 0,\n        \"updated\": 3,\n      }\n    `)\n})\n"
  },
  {
    "path": "test/snapshots/test/jest-image-snapshot.test.ts",
    "content": "import fs from 'node:fs'\nimport { join } from 'node:path'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('jest-image-snapshot', async () => {\n  // cleanup snapshot\n  const root = join(import.meta.dirname, 'fixtures/jest-image-snapshot')\n  fs.rmSync(join(root, '__image_snapshots__'), { recursive: true, force: true })\n\n  // write snapshot\n  let vitest = await runVitest({\n    root,\n    update: true,\n  })\n  expect(vitest.stderr).toBe('')\n  expect(vitest.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n    Object {\n      \"added\": 1,\n      \"didUpdate\": true,\n      \"failure\": false,\n      \"filesAdded\": 1,\n      \"filesRemoved\": 0,\n      \"filesRemovedList\": Array [],\n      \"filesUnmatched\": 0,\n      \"filesUpdated\": 0,\n      \"matched\": 0,\n      \"total\": 1,\n      \"unchecked\": 0,\n      \"uncheckedKeysByFile\": Array [],\n      \"unmatched\": 0,\n      \"updated\": 0,\n    }\n  `)\n  expect(fs.existsSync(join(root, '__image_snapshots__/basic-test-ts-to-match-image-snapshot-1-snap.png'))).toBe(true)\n\n  // match existing snapshot\n  vitest = await runVitest({\n    root,\n    update: false,\n  })\n  expect(vitest.stderr).toBe('')\n  expect(vitest.ctx?.snapshot.summary).toMatchInlineSnapshot(`\n    Object {\n      \"added\": 0,\n      \"didUpdate\": false,\n      \"failure\": false,\n      \"filesAdded\": 0,\n      \"filesRemoved\": 0,\n      \"filesRemovedList\": Array [],\n      \"filesUnmatched\": 0,\n      \"filesUpdated\": 0,\n      \"matched\": 1,\n      \"total\": 1,\n      \"unchecked\": 0,\n      \"uncheckedKeysByFile\": Array [],\n      \"unmatched\": 0,\n      \"updated\": 0,\n    }\n  `)\n  expect(fs.existsSync(join(root, '__image_snapshots__/basic-test-ts-to-match-image-snapshot-1-snap.png'))).toBe(true)\n})\n"
  },
  {
    "path": "test/snapshots/test/obsolete.test.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('obsolete snapshot fails with update:none', async () => {\n  // cleanup snapshot\n  const root = path.join(import.meta.dirname, 'fixtures/obsolete')\n  fs.rmSync(path.join(root, 'src/__snapshots__'), { recursive: true, force: true })\n\n  // initial run to write snapshot\n  let result = await runVitest({ root, update: true })\n  expect(result.stderr).toBe('')\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"src/test1.test.ts\": Object {\n        \"bar\": \"passed\",\n        \"foo\": \"passed\",\n        \"fuu\": \"passed\",\n      },\n      \"src/test2.test.ts\": Object {\n        \"bar\": \"passed\",\n        \"foo\": \"passed\",\n      },\n    }\n  `)\n\n  // test fails with obsolete snapshots\n  result = await runVitest({\n    root,\n    update: 'none',\n    env: {\n      TEST_OBSOLETE: 'true',\n    },\n  })\n  expect(result.stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  src/test1.test.ts [ src/test1.test.ts ]\n    Error: Obsolete snapshots found when no snapshot update is expected.\n    · foo 1\n    · fuu 1\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n    \"\n  `)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"src/test1.test.ts\": Object {\n        \"__module_errors__\": Array [\n          \"Obsolete snapshots found when no snapshot update is expected.\n    · foo 1\n    · fuu 1\n    \",\n        ],\n        \"bar\": \"passed\",\n        \"foo\": \"passed\",\n        \"fuu\": \"passed\",\n      },\n      \"src/test2.test.ts\": Object {\n        \"bar\": \"passed\",\n        \"foo\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/snapshots/test/skip-test.test.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('snapshots in skipped test/suite is not obsolete', async () => {\n  // create snapshot on first run\n  fs.rmSync('test/fixtures/skip-test/__snapshots__', { recursive: true, force: true })\n  let vitest = await runVitest({\n    root: 'test/fixtures/skip-test',\n    update: true,\n  })\n  expect(vitest.stdout).toContain('Snapshots  2 written')\n  expect(fs.readFileSync('test/fixtures/skip-test/__snapshots__/repro.test.ts.snap', 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`repro suite > inner case 1\\`] = \\`\"hi-1\"\\`;\n\n    exports[\\`top-level case 1\\`] = \\`\"hi-2\"\\`;\n    \"\n  `)\n\n  // running with `skipIf` enabled should not show \"obsolete\"\n  vitest = await runVitest({\n    root: 'test/fixtures/skip-test',\n    env: {\n      ENABLE_SKIP: '1',\n    },\n  })\n  expect(vitest.stdout).toContain('2 skipped')\n  expect(vitest.stdout).not.toContain('obsolete')\n\n  // running with `skipIf` and `update` should keep snapshots\n  vitest = await runVitest({\n    root: 'test/fixtures/skip-test',\n    update: true,\n    env: {\n      ENABLE_SKIP: '1',\n    },\n  })\n  expect(fs.readFileSync('test/fixtures/skip-test/__snapshots__/repro.test.ts.snap', 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`repro suite > inner case 1\\`] = \\`\"hi-1\"\\`;\n\n    exports[\\`top-level case 1\\`] = \\`\"hi-2\"\\`;\n    \"\n  `)\n})\n\ntest('handle obsoleteness of toMatchSnapshot(\"custom message\")', async () => {\n  const root = path.join(import.meta.dirname, './fixtures/skip-test-custom')\n\n  // clear snapshots\n  fs.rmSync(path.join(root, '__snapshots__'), { recursive: true, force: true })\n\n  // create snapshot on first run\n  let vitest = await runVitest({\n    root,\n    update: true,\n  })\n  expect(vitest.stdout).toContain('Snapshots  4 written')\n  expect(fs.readFileSync(path.join(root, '__snapshots__/basic.test.ts.snap'), 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`custom a > x 1\\`] = \\`0\\`;\n\n    exports[\\`custom a > y 1\\`] = \\`0\\`;\n\n    exports[\\`custom b > w 1\\`] = \\`0\\`;\n\n    exports[\\`custom b > z 1\\`] = \\`0\\`;\n    \"\n  `)\n\n  // Skipped tests' `toMatchSnapshot(\"...\")` is not considered obsolete\n  vitest = await runVitest({\n    root,\n    testNamePattern: 'custom a',\n  })\n  expect(vitest.stdout).toContain('1 passed')\n  expect(vitest.stdout).toContain('1 skipped')\n  expect(vitest.stdout).not.toContain('obsolete')\n\n  vitest = await runVitest({\n    root,\n    testNamePattern: 'custom b',\n  })\n  expect(vitest.stdout).toContain('1 passed')\n  expect(vitest.stdout).toContain('1 skipped')\n  expect(vitest.stdout).not.toContain('obsolete')\n\n  // check snapshot doesn't change when skip + update\n  vitest = await runVitest({\n    root,\n    update: true,\n    testNamePattern: 'custom a',\n  })\n  expect(vitest.stdout).toContain('1 passed')\n  expect(vitest.stdout).toContain('1 skipped')\n  expect(vitest.stdout).not.toContain('obsolete')\n  expect(fs.readFileSync(path.join(root, '__snapshots__/basic.test.ts.snap'), 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`custom a > x 1\\`] = \\`0\\`;\n\n    exports[\\`custom a > y 1\\`] = \\`0\\`;\n\n    exports[\\`custom b > w 1\\`] = \\`0\\`;\n\n    exports[\\`custom b > z 1\\`] = \\`0\\`;\n    \"\n  `)\n})\n"
  },
  {
    "path": "test/snapshots/test/snapshots.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { editFile, runVitest } from '../../test-utils'\n\ntest('non default snapshot format', () => {\n  expect({ foo: ['bar'] }).toMatchInlineSnapshot(`\n    Object {\n      \"foo\": Array [\n        \"bar\",\n      ],\n    }\n  `)\n})\n\ntest('--update works for workspace project', async () => {\n  // setup wrong snapshot value\n  editFile(\n    'test/fixtures/workspace/packages/space/test/__snapshots__/basic.test.ts.snap',\n    data => data.replace('`1`', '`2`'),\n  )\n\n  // run with --update\n  const { stdout, exitCode } = await runVitest({\n    update: true,\n    root: 'test/fixtures/workspace',\n  })\n  expect.soft(stdout).include('Snapshots  1 updated')\n  expect.soft(exitCode).toBe(0)\n})\n"
  },
  {
    "path": "test/snapshots/test/soft-inline.test.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { expect, test } from 'vitest'\nimport { editFile, runVitest } from '../../test-utils'\n\ntest('soft inline', async () => {\n  const root = join(import.meta.dirname, 'fixtures/soft-inline')\n  const testFile = join(root, 'basic.test.ts')\n\n  // remove inline snapshots\n  editFile(testFile, s => s\n    .replace(/toMatchInlineSnapshot\\(`[^`]*`\\)/g, 'toMatchInlineSnapshot()')\n    .replace(/toThrowErrorMatchingInlineSnapshot\\(`[^`]*`\\)/g, 'toThrowErrorMatchingInlineSnapshot()'))\n\n  // create snapshots from scratch\n  let result = await runVitest({ root, update: 'new' })\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(readFileSync(testFile, 'utf-8')).toMatchInlineSnapshot(`\n    \"import { expect, test } from 'vitest'\n\n    test('toMatchInlineSnapshot', () => {\n      expect.soft('--snap-1--').toMatchInlineSnapshot(\\`\"--snap-1--\"\\`)\n      expect.soft('--snap-2--').toMatchInlineSnapshot(\\`\"--snap-2--\"\\`)\n    })\n\n    test('toThrowErrorMatchingInlineSnapshot', () => {\n      expect.soft(() => { throw new Error('--error-1--') }).toThrowErrorMatchingInlineSnapshot(\\`[Error: --error-1--]\\`)\n      expect.soft(() => { throw new Error('--error-2--') }).toThrowErrorMatchingInlineSnapshot(\\`[Error: --error-2--]\\`)\n    })\n    \"\n  `)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"basic.test.ts\": Object {\n        \"toMatchInlineSnapshot\": \"passed\",\n        \"toThrowErrorMatchingInlineSnapshot\": \"passed\",\n      },\n    }\n  `)\n\n  // edit tests to introduce snapshot errors\n  editFile(testFile, s => s\n    .replace('expect.soft(\\'--snap-1--\\')', 'expect.soft(\\'--snap-1-edit--\\')')\n    .replace('expect.soft(\\'--snap-2--\\')', 'expect.soft(\\'--snap-2-edit--\\')')\n    .replace('new Error(\\'--error-1--\\')', 'new Error(\\'--error-1-edit--\\')')\n    .replace('new Error(\\'--error-2--\\')', 'new Error(\\'--error-2-edit--\\')'))\n\n  result = await runVitest({ root, update: false })\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"basic.test.ts\": Object {\n        \"toMatchInlineSnapshot\": Array [\n          \"Snapshot \\`toMatchInlineSnapshot 1\\` mismatched\",\n          \"Snapshot \\`toMatchInlineSnapshot 2\\` mismatched\",\n        ],\n        \"toThrowErrorMatchingInlineSnapshot\": Array [\n          \"Snapshot \\`toThrowErrorMatchingInlineSnapshot 1\\` mismatched\",\n          \"Snapshot \\`toThrowErrorMatchingInlineSnapshot 2\\` mismatched\",\n        ],\n      },\n    }\n  `)\n\n  // run with update\n  result = await runVitest({ root, update: 'all' })\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(readFileSync(testFile, 'utf-8')).toMatchInlineSnapshot(`\n    \"import { expect, test } from 'vitest'\n\n    test('toMatchInlineSnapshot', () => {\n      expect.soft('--snap-1-edit--').toMatchInlineSnapshot(\\`\"--snap-1-edit--\"\\`)\n      expect.soft('--snap-2-edit--').toMatchInlineSnapshot(\\`\"--snap-2-edit--\"\\`)\n    })\n\n    test('toThrowErrorMatchingInlineSnapshot', () => {\n      expect.soft(() => { throw new Error('--error-1-edit--') }).toThrowErrorMatchingInlineSnapshot(\\`[Error: --error-1-edit--]\\`)\n      expect.soft(() => { throw new Error('--error-2-edit--') }).toThrowErrorMatchingInlineSnapshot(\\`[Error: --error-2-edit--]\\`)\n    })\n    \"\n  `)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"basic.test.ts\": Object {\n        \"toMatchInlineSnapshot\": \"passed\",\n        \"toThrowErrorMatchingInlineSnapshot\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/snapshots/test/soft.test.ts",
    "content": "import fs, { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { expect, test } from 'vitest'\nimport { editFile, runVitest } from '../../test-utils'\n\ntest('soft', async () => {\n  const root = join(import.meta.dirname, 'fixtures/soft')\n  const testFile = join(root, 'basic.test.ts')\n  const snapshotFile = join(root, '__snapshots__/basic.test.ts.snap')\n  const customFile1 = join(root, '__snapshots__/custom1.txt')\n  const customFile2 = join(root, '__snapshots__/custom2.txt')\n\n  // remove snapshots\n  fs.rmSync(join(root, '__snapshots__'), { recursive: true, force: true })\n\n  // create snapshots from scratch\n  let result = await runVitest({ root, update: 'new' })\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(readFileSync(snapshotFile, 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`toMatchSnapshot 1\\`] = \\`\"--snap-1--\"\\`;\n\n    exports[\\`toMatchSnapshot 2\\`] = \\`\"--snap-2--\"\\`;\n\n    exports[\\`toThrowErrorMatchingSnapshot 1\\`] = \\`[Error: --error-1--]\\`;\n\n    exports[\\`toThrowErrorMatchingSnapshot 2\\`] = \\`[Error: --error-2--]\\`;\n    \"\n  `)\n  expect(readFileSync(customFile1, 'utf-8')).toMatchInlineSnapshot(`\"--file-1--\"`)\n  expect(readFileSync(customFile2, 'utf-8')).toMatchInlineSnapshot(`\"--file-2--\"`)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"basic.test.ts\": Object {\n        \"toMatchFileSnapshot\": \"passed\",\n        \"toMatchSnapshot\": \"passed\",\n        \"toThrowErrorMatchingSnapshot\": \"passed\",\n      },\n    }\n  `)\n\n  // edit tests to introduce snapshot errors\n  editFile(testFile, s => s\n    .replace(`--snap-1--`, `--snap-1-edit--`)\n    .replace(`--snap-2--`, `--snap-2-edit--`)\n    .replace(`--file-1--`, `--file-1-edit--`)\n    .replace(`--file-2--`, `--file-2-edit--`)\n    .replace(`--error-1--`, `--error-1-edit--`)\n    .replace(`--error-2--`, `--error-2-edit--`))\n\n  result = await runVitest({ root, update: false })\n  expect(result.stderr).toMatchInlineSnapshot(`\n    \"\n    ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯\n\n     FAIL  basic.test.ts > toMatchSnapshot\n    Error: Snapshot \\`toMatchSnapshot 1\\` mismatched\n\n    Expected: \"\"--snap-1--\"\"\n    Received: \"\"--snap-1-edit--\"\"\n\n     ❯ basic.test.ts:4:34\n          2|\n          3| test('toMatchSnapshot', () => {\n          4|   expect.soft('--snap-1-edit--').toMatchSnapshot()\n           |                                  ^\n          5|   expect.soft('--snap-2-edit--').toMatchSnapshot()\n          6| })\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/6]⎯\n\n     FAIL  basic.test.ts > toMatchSnapshot\n    Error: Snapshot \\`toMatchSnapshot 2\\` mismatched\n\n    Expected: \"\"--snap-2--\"\"\n    Received: \"\"--snap-2-edit--\"\"\n\n     ❯ basic.test.ts:5:34\n          3| test('toMatchSnapshot', () => {\n          4|   expect.soft('--snap-1-edit--').toMatchSnapshot()\n          5|   expect.soft('--snap-2-edit--').toMatchSnapshot()\n           |                                  ^\n          6| })\n          7|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/6]⎯\n\n     FAIL  basic.test.ts > toMatchFileSnapshot\n    Error: Snapshot \\`toMatchFileSnapshot 1\\` mismatched\n\n    Expected: \"--file-1--\"\n    Received: \"--file-1-edit--\"\n\n     ❯ basic.test.ts:9:3\n          7|\n          8| test('toMatchFileSnapshot', async () => {\n          9|   await expect.soft('--file-1-edit--').toMatchFileSnapshot('./__snapsh…\n           |   ^\n         10|   await expect.soft('--file-2-edit--').toMatchFileSnapshot('./__snapsh…\n         11| })\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/6]⎯\n\n     FAIL  basic.test.ts > toMatchFileSnapshot\n    Error: Snapshot \\`toMatchFileSnapshot 2\\` mismatched\n\n    Expected: \"--file-2--\"\n    Received: \"--file-2-edit--\"\n\n     ❯ basic.test.ts:10:3\n          8| test('toMatchFileSnapshot', async () => {\n          9|   await expect.soft('--file-1-edit--').toMatchFileSnapshot('./__snapsh…\n         10|   await expect.soft('--file-2-edit--').toMatchFileSnapshot('./__snapsh…\n           |   ^\n         11| })\n         12|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/6]⎯\n\n     FAIL  basic.test.ts > toThrowErrorMatchingSnapshot\n    Error: Snapshot \\`toThrowErrorMatchingSnapshot 1\\` mismatched\n\n    Expected: \"[Error: --error-1--]\"\n    Received: \"[Error: --error-1-edit--]\"\n\n     ❯ basic.test.ts:14:62\n         12|\n         13| test('toThrowErrorMatchingSnapshot', () => {\n         14|   expect.soft(() => { throw new Error('--error-1-edit--') }).toThrowEr…\n           |                                                              ^\n         15|   expect.soft(() => { throw new Error('--error-2-edit--') }).toThrowEr…\n         16| })\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/6]⎯\n\n     FAIL  basic.test.ts > toThrowErrorMatchingSnapshot\n    Error: Snapshot \\`toThrowErrorMatchingSnapshot 2\\` mismatched\n\n    Expected: \"[Error: --error-2--]\"\n    Received: \"[Error: --error-2-edit--]\"\n\n     ❯ basic.test.ts:15:62\n         13| test('toThrowErrorMatchingSnapshot', () => {\n         14|   expect.soft(() => { throw new Error('--error-1-edit--') }).toThrowEr…\n         15|   expect.soft(() => { throw new Error('--error-2-edit--') }).toThrowEr…\n           |                                                              ^\n         16| })\n         17|\n\n    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/6]⎯\n\n    \"\n  `)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"basic.test.ts\": Object {\n        \"toMatchFileSnapshot\": Array [\n          \"Snapshot \\`toMatchFileSnapshot 1\\` mismatched\",\n          \"Snapshot \\`toMatchFileSnapshot 2\\` mismatched\",\n        ],\n        \"toMatchSnapshot\": Array [\n          \"Snapshot \\`toMatchSnapshot 1\\` mismatched\",\n          \"Snapshot \\`toMatchSnapshot 2\\` mismatched\",\n        ],\n        \"toThrowErrorMatchingSnapshot\": Array [\n          \"Snapshot \\`toThrowErrorMatchingSnapshot 1\\` mismatched\",\n          \"Snapshot \\`toThrowErrorMatchingSnapshot 2\\` mismatched\",\n        ],\n      },\n    }\n  `)\n\n  // run with update\n  result = await runVitest({ root, update: 'all' })\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(readFileSync(snapshotFile, 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`toMatchSnapshot 1\\`] = \\`\"--snap-1-edit--\"\\`;\n\n    exports[\\`toMatchSnapshot 2\\`] = \\`\"--snap-2-edit--\"\\`;\n\n    exports[\\`toThrowErrorMatchingSnapshot 1\\`] = \\`[Error: --error-1-edit--]\\`;\n\n    exports[\\`toThrowErrorMatchingSnapshot 2\\`] = \\`[Error: --error-2-edit--]\\`;\n    \"\n  `)\n  expect(readFileSync(customFile1, 'utf-8')).toMatchInlineSnapshot(`\"--file-1-edit--\"`)\n  expect(readFileSync(customFile2, 'utf-8')).toMatchInlineSnapshot(`\"--file-2-edit--\"`)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"basic.test.ts\": Object {\n        \"toMatchFileSnapshot\": \"passed\",\n        \"toMatchSnapshot\": \"passed\",\n        \"toThrowErrorMatchingSnapshot\": \"passed\",\n      },\n    }\n  `)\n})\n"
  },
  {
    "path": "test/snapshots/test/summary.test.ts",
    "content": "import fs from 'node:fs'\nimport { join } from 'node:path'\nimport { assert, expect, onTestFailed, onTestFinished, test } from 'vitest'\nimport { editFile, runVitest } from '../../test-utils'\n\nfunction fsUpdate(file: string, updateFn: (data: string) => string) {\n  fs.writeFileSync(file, updateFn(fs.readFileSync(file, 'utf-8')))\n}\n\ntest('summary', async () => {\n  // cleanup snapshot\n  const dir = join(import.meta.dirname, 'fixtures/summary')\n  const testFile = join(dir, 'basic.test.ts')\n  const snapshotFile = join(dir, '__snapshots__/basic.test.ts.snap')\n  fsUpdate(testFile, s => s.replace(/`\"@SNAP\\d\"`/g, ''))\n  fs.rmSync(snapshotFile, { recursive: true, force: true })\n\n  // write everything\n  let vitest = await runVitest({\n    root: 'test/fixtures/summary',\n    update: true,\n  })\n  expect(vitest.stdout).toContain('Snapshots  12 written')\n\n  // write partially\n  fsUpdate(testFile, s => s.replace('`\"@SNAP2\"`', ''))\n  fsUpdate(snapshotFile, s => s.replace('exports[`file repeats 1`] = `\"@SNAP5\"`;', ''))\n  vitest = await runVitest({\n    root: 'test/fixtures/summary',\n    update: true,\n  })\n  expect(vitest.stdout).toContain('Snapshots  2 written')\n\n  // update partially\n  fsUpdate(testFile, s => s.replace('`\"@SNAP2\"`', '`\"@WRONG\"`'))\n  fsUpdate(snapshotFile, s => s.replace('`\"@SNAP5\"`', '`\"@WRONG\"`'))\n  vitest = await runVitest({\n    root: 'test/fixtures/summary',\n    update: true,\n  })\n  expect(vitest.stdout).toContain('Snapshots  2 updated')\n})\n\ntest('first obsolete then remove', async () => {\n  const root = join(import.meta.dirname, 'fixtures/summary-removed')\n  const testFile = join(root, 'basic.test.ts')\n  const snapshotFile = join(root, '__snapshots__/basic.test.ts.snap')\n\n  // reset snapshot\n  fs.rmSync(snapshotFile, { recursive: true, force: true })\n  await runVitest({\n    root,\n    update: true,\n  })\n  expect(fs.readFileSync(snapshotFile, 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`x 1\\`] = \\`0\\`;\n\n    exports[\\`y 1\\`] = \\`0\\`;\n    \"\n  `)\n\n  // watch run\n  const { ctx, ...result } = await runVitest(\n    {\n      watch: true,\n      root,\n    },\n  )\n  assert(ctx)\n  onTestFinished(() => {\n    ctx.close()\n  })\n  onTestFailed(() => {\n    console.error(result.vitest.stdout)\n    console.error(result.vitest.stderr)\n  })\n\n  // remove `toMatchSnapshot()` and rerun -> obsolete snapshot\n  editFile(testFile, s => s.replace(/REMOVE-START.*REMOVE-END/s, ''))\n  await result.vitest.waitForStdout('1 obsolete')\n\n  // rerun with update -> remove snapshot\n  await ctx.updateSnapshot()\n  await result.vitest.waitForStdout('1 removed')\n  expect(fs.readFileSync(snapshotFile, 'utf-8')).toMatchInlineSnapshot(`\n    \"// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\n    exports[\\`x 1\\`] = \\`0\\`;\n    \"\n  `)\n})\n"
  },
  {
    "path": "test/snapshots/test/test-update.test.ts",
    "content": "import fs, { rmSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { globSync } from 'tinyglobby'\nimport { expect, test } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ntest('test update', async () => {\n  // copy fixtures/test-update to fixtures/test-update-result\n  const srcDir = join(import.meta.dirname, 'fixtures/test-update')\n  const dstDir = join(import.meta.dirname, 'fixtures/test-update-result')\n  rmSync(dstDir, { recursive: true })\n  fs.cpSync(srcDir, dstDir, { recursive: true })\n\n  // run and update snapshots\n  const result = await runVitest({ root: dstDir, update: true })\n  expect(result.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(result.errorTree()).toMatchInlineSnapshot(`\n    Object {\n      \"inline-concurrent.test.js\": Object {\n        \"1st\": \"passed\",\n        \"2nd\": \"passed\",\n        \"3rd\": \"passed\",\n      },\n      \"inline.test.js\": Object {\n        \"snapshots are generated in correct order\": Object {\n          \"first snapshot\": \"passed\",\n          \"second snapshot\": \"passed\",\n        },\n        \"snapshots with properties\": Object {\n          \"mixed with and without snapshot\": \"passed\",\n          \"with snapshot\": \"passed\",\n          \"without snapshot\": \"passed\",\n        },\n      },\n      \"retry-file.test.ts\": Object {\n        \"file repeats\": \"passed\",\n        \"file repeats many\": \"passed\",\n        \"file retry\": \"passed\",\n        \"file retry many\": \"passed\",\n        \"file retry partial\": \"passed\",\n      },\n      \"retry-inline.test.ts\": Object {\n        \"inline repeats\": \"passed\",\n        \"inline retry\": \"passed\",\n      },\n      \"same-title-file.test.js\": Object {\n        \"same title exist\": \"passed\",\n        \"same title new\": \"passed\",\n      },\n      \"same-title-inline.test.js\": Object {\n        \"same title\": \"passed\",\n      },\n    }\n  `)\n  const resultFiles = readFiles(dstDir)\n  expect(Object.keys(resultFiles)).toMatchInlineSnapshot(`\n    Array [\n      \"__snapshots__/retry-file.test.ts.snap\",\n      \"__snapshots__/same-title-file.test.js.snap\",\n      \"inline-concurrent.test.js\",\n      \"inline.test.js\",\n      \"retry-file.test.ts\",\n      \"retry-inline.test.ts\",\n      \"same-title-file.test.js\",\n      \"same-title-inline.test.js\",\n    ]\n  `)\n\n  // re-run without update and files are unchanged\n  const result2 = await runVitest({ root: dstDir, update: 'none' })\n  expect(result2.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(result2.errorTree()).toEqual(result.errorTree())\n  expect(readFiles(dstDir)).toEqual(resultFiles)\n\n  const result3 = await runVitest({ root: dstDir, update: 'new' })\n  expect(result3.stderr).toMatchInlineSnapshot(`\"\"`)\n  expect(result3.errorTree()).toEqual(result.errorTree())\n  expect(readFiles(dstDir)).toEqual(resultFiles)\n})\n\nfunction readFiles(dir: string) {\n  const files = globSync('**', { cwd: dir, ignore: ['**/node_modules/**'] })\n  return Object.fromEntries(\n    files.sort().map(file => [file, fs.readFileSync(join(dir, file), 'utf-8')]),\n  )\n}\n"
  },
  {
    "path": "test/snapshots/vitest.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport { defaultExclude } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    exclude: [...defaultExclude, '**/fixtures'],\n    snapshotFormat: {\n      printBasicPrototype: true,\n    },\n    testTimeout: process.env.CI ? 60_000 : 5_000,\n  },\n})\n"
  },
  {
    "path": "test/test-utils/cli.ts",
    "content": "import type { Readable, Writable } from 'node:stream'\nimport { stripVTControlCharacters } from 'node:util'\n\ntype Listener = (() => void)\ntype ReadableOrWritable = Readable | Writable\ntype Source = 'stdout' | 'stderr'\n\nexport class Cli {\n  stdout = ''\n  stderr = ''\n\n  private stdoutListeners: Listener[] = []\n  private stderrListeners: Listener[] = []\n  private stdin: ReadableOrWritable\n  private preserveAnsi?: boolean\n\n  constructor(options: { stdin: ReadableOrWritable; stdout: ReadableOrWritable; stderr: ReadableOrWritable; preserveAnsi?: boolean }) {\n    this.stdin = options.stdin\n    this.stdin = options.stdin\n    this.preserveAnsi = options.preserveAnsi\n\n    for (const source of (['stdout', 'stderr'] as const)) {\n      const stream = options[source]\n\n      if ((stream as Readable).readable) {\n        stream.on('data', (data) => {\n          this.capture(source, data)\n        })\n      }\n      else if (isWritable(stream)) {\n        const original = stream.write.bind(stream)\n\n        // @ts-expect-error -- Is there a better way to detect when a Writable is being written into?\n        stream.write = (data, encoding, callback) => {\n          this.capture(source, data)\n          return original(data, encoding, callback)\n        }\n      }\n    }\n  }\n\n  private capture(source: Source, data: any) {\n    const msg = this.preserveAnsi ? data.toString() : stripVTControlCharacters(data.toString())\n    this[source] += msg\n    this[`${source}Listeners`].forEach(fn => fn())\n  }\n\n  write(data: string) {\n    this.resetOutput()\n\n    if (((this.stdin as Readable).readable)) {\n      this.stdin.emit('data', data)\n    }\n    else if (isWritable(this.stdin)) {\n      this.stdin.write(data)\n    }\n  }\n\n  resetOutput() {\n    this.stdout = ''\n    this.stderr = ''\n  }\n\n  waitForStdout(expected: string) {\n    return this.waitForOutput(expected, 'stdout', this.waitForStdout)\n  }\n\n  waitForStderr(expected: string) {\n    return this.waitForOutput(expected, 'stderr', this.waitForStderr)\n  }\n\n  private waitForOutput(expected: string, source: Source, caller: Parameters<typeof Error.captureStackTrace>[1]) {\n    const error = new Error('Timeout')\n    Error.captureStackTrace(error, caller)\n\n    return new Promise<void>((resolve, reject) => {\n      if (this[source].includes(expected)) {\n        return resolve()\n      }\n\n      const timeout = setTimeout(() => {\n        error.message = `Timeout when waiting for error \"${expected}\".\\nReceived:\\nstdout: ${this.stdout}\\nstderr: ${this.stderr}`\n        reject(error)\n      }, process.env.CI ? 20_000 : 4_000)\n\n      const listener = () => {\n        if (this[source].includes(expected)) {\n          if (timeout) {\n            clearTimeout(timeout)\n          }\n\n          resolve()\n        }\n      }\n\n      this[`${source}Listeners`].push(listener)\n    })\n  }\n}\n\nfunction isWritable(stream: any): stream is Writable {\n  return stream && typeof stream.write === 'function'\n}\n"
  },
  {
    "path": "test/test-utils/fixtures/external-math.ts",
    "content": "export function sum(a: number, b: number) {\n  return a + b\n}\n\nexport function multiply(a: number, b: number) {\n  return a * b\n}\n"
  },
  {
    "path": "test/test-utils/index.ts",
    "content": "import type { Options } from 'tinyexec'\nimport type { UserConfig as ViteUserConfig } from 'vite'\nimport type { SerializedConfig, TestContext, WorkerGlobalState } from 'vitest'\nimport type { TestProjectConfiguration } from 'vitest/config'\nimport type {\n  TestCase,\n  CliOptions as TestCliOptions,\n  TestCollection,\n  TestModule,\n  TestSpecification,\n  TestSuite,\n  TestUserConfig,\n  Vitest,\n} from 'vitest/node'\nimport { webcrypto as crypto } from 'node:crypto'\nimport fs from 'node:fs'\nimport { Readable, Writable } from 'node:stream'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { inspect } from 'node:util'\nimport { dirname, relative, resolve } from 'pathe'\nimport { x } from 'tinyexec'\nimport * as tinyrainbow from 'tinyrainbow'\nimport { afterEach, onTestFinished, TestRunner } from 'vitest'\nimport { startVitest } from 'vitest/node'\nimport { Cli } from './cli'\n\n// override default colors to disable them in tests\nObject.assign(tinyrainbow.default, tinyrainbow.getDefaultColors())\n// @ts-expect-error not typed global\nglobalThis.__VITEST_GENERATE_UI_TOKEN__ = true\n\nexport interface VitestRunnerCLIOptions {\n  std?: 'inherit'\n  fails?: boolean\n  printExitCode?: boolean\n  preserveAnsi?: boolean\n  tty?: boolean\n  mode?: 'test' | 'benchmark'\n}\n\nexport interface RunVitestConfig extends TestUserConfig {\n  $viteConfig?: Omit<ViteUserConfig, 'test'>\n  $cliOptions?: TestCliOptions\n}\n\nconst process_ = process\n\n/**\n * The config is assumed to be the config on the fille system, not CLI options\n * (Note that CLI only options like \"standalone\" are passed as CLI options, not config options)\n * - To pass options as CLI, provide `$cliOptions` in the config object.\n * - To pass other Vite config properties, provide `$viteConfig` in the config object.\n *\n * **WARNING**\n * If the fixture in `root` has a config file, its options **WILL TAKE PRIORITY** over the ones provided here,\n * except for the ones provided in `$cliOptions`.\n */\nexport async function runVitest(\n  config: RunVitestConfig,\n  cliFilters: string[] = [],\n  runnerOptions: VitestRunnerCLIOptions = {},\n) {\n  // Reset possible previous runs\n  process.exitCode = 0\n  let exitCode = process.exitCode\n\n  if (runnerOptions.printExitCode) {\n    globalThis.process = new Proxy(process_, {\n      set(target, p, newValue, receiver) {\n        if (p === 'exitCode') {\n          // eslint-disable-next-line no-console\n          console.trace('exitCode was set to', newValue)\n        }\n        return Reflect.set(target, p, newValue, receiver)\n      },\n    })\n  }\n\n  // Prevent possible process.exit() calls, e.g. from --browser\n  const exit = process.exit\n  process.exit = (() => { }) as never\n\n  const stdout = new Writable({\n    write(chunk, __, callback) {\n      if (runnerOptions.std === 'inherit') {\n        process.stdout.write(chunk.toString())\n      }\n      callback()\n    },\n  })\n\n  if (runnerOptions?.tty) {\n    (stdout as typeof process.stdout).isTTY = true\n  }\n\n  const stderr = new Writable({\n    write(chunk, __, callback) {\n      if (runnerOptions.std === 'inherit') {\n        process.stderr.write(chunk.toString())\n      }\n      callback()\n    },\n  })\n\n  // \"node:tty\".ReadStream doesn't work on Github Windows CI, let's simulate it\n  const stdin = new Readable({ read: () => '' }) as NodeJS.ReadStream\n  stdin.isTTY = true\n  stdin.setRawMode = () => stdin\n  const cli = new Cli({ stdin, stdout, stderr, preserveAnsi: runnerOptions.preserveAnsi })\n  // @ts-expect-error not typed global\n  const currentConfig: SerializedConfig = __vitest_worker__.ctx.config\n\n  let ctx: Vitest | undefined\n  let thrown = false\n\n  const {\n    reporters,\n    root,\n    watch,\n    maxWorkers,\n    // #region cli-only options\n    config: configFile,\n    standalone,\n    dom,\n    related,\n    mode,\n    changed,\n    shard,\n    project,\n    cliExclude,\n    clearScreen,\n    compare,\n    outputJson,\n    mergeReports,\n    clearCache,\n    // #endregion\n    $cliOptions: cliOptions,\n    $viteConfig: viteConfig = {},\n    ...rest\n  } = config\n\n  if ((viteConfig as any).test) {\n    throw new Error(`Don't pass down \"viteConfig\" with \"test\" property. Use the rest of the first argument.`)\n  }\n\n  ;(viteConfig as any).test = rest\n\n  try {\n    ctx = await startVitest(runnerOptions.mode || 'test', cliFilters, {\n      root,\n      config: configFile,\n      standalone,\n      dom,\n      related,\n      mode,\n      changed,\n      shard,\n      project,\n      cliExclude,\n      clearScreen,\n      compare,\n      outputJson,\n      mergeReports,\n      clearCache,\n      cache: 'cache' in config ? config.cache : false,\n\n      // Test cases are already run with multiple forks/threads\n      maxWorkers: maxWorkers ?? 1,\n\n      watch: watch ?? false,\n      // \"none\" can be used to disable passing \"reporter\" option so that default value is used (it's not same as reporters: [\"default\"])\n      ...(reporters === 'none' ? {} : reporters ? { reporters } : { reporters: ['verbose'] }),\n      ...cliOptions,\n      env: {\n        NO_COLOR: 'true',\n        AI_AGENT: '',\n        ...rest.env,\n        ...cliOptions?.env,\n      },\n      // override cache config with the one that was used to run `vitest` formt the CLI\n      experimental: {\n        fsModuleCache: rest.experimental?.fsModuleCache ?? currentConfig.experimental.fsModuleCache,\n        ...cliOptions?.experimental,\n      },\n    }, {\n      ...viteConfig,\n      server: {\n        // we never need a websocket connection for the root config because it doesn't connect to the browser\n        // browser mode uses a separate config that doesn't inherit CLI overrides\n        ws: false,\n        watch: {\n          // During tests we edit the files too fast and sometimes chokidar\n          // misses change events, so enforce polling for consistency\n          // https://github.com/vitejs/vite/blob/b723a753ced0667470e72b4853ecda27b17f546a/playground/vitestSetup.ts#L211\n          usePolling: true,\n          interval: 100,\n          ...viteConfig.server?.watch,\n        },\n        ...viteConfig?.server,\n      },\n    }, {\n      stdin,\n      stdout,\n      stderr,\n    })\n  }\n  catch (e: any) {\n    if (runnerOptions.fails !== true) {\n      console.error(e)\n    }\n    thrown = true\n    cli.stderr += inspect(e)\n  }\n  finally {\n    if (runnerOptions.printExitCode) {\n      globalThis.process = process_\n    }\n    exitCode = process.exitCode\n    process.exitCode = 0\n\n    if (TestRunner.getCurrentTest()) {\n      onTestFinished(async () => {\n        await ctx?.close()\n        process.exit = exit\n      })\n    }\n    else {\n      afterEach(async () => {\n        await ctx?.close()\n        process.exit = exit\n      })\n    }\n  }\n\n  return {\n    thrown,\n    ctx,\n    exitCode,\n    vitest: cli,\n    stdout: cli.stdout,\n    stderr: cli.stderr,\n    get results() {\n      return ctx?.state.getTestModules() || []\n    },\n    errorTree(options?: { project?: boolean; stackTrace?: boolean }) {\n      const modules = ctx?.state.getTestModules() || []\n      const tree = options?.project\n        ? buildErrorProjectTree(modules, options)\n        : buildErrorTree(modules, options)\n      const errors = ctx?.state.getUnhandledErrors()\n      if (errors && errors.length > 0) {\n        tree.__unhandled_errors__ = errors.map((e: any) => e.message)\n      }\n      return tree\n    },\n    testTree() {\n      return buildTestTree(ctx?.state.getTestModules() || [])\n    },\n    buildTree(onResult: (testResult: TestCase) => any) {\n      return buildTestTree(ctx?.state.getTestModules() || [], onResult)\n    },\n    waitForClose: async () => {\n      await new Promise<void>(resolve => ctx!.onClose(resolve))\n      return ctx?.closingPromise\n    },\n  }\n}\n\ninterface CliOptions extends Partial<Options> {\n  earlyReturn?: boolean\n  preserveAnsi?: boolean\n}\n\nasync function runCli(command: 'vitest', _options?: CliOptions | string, ...args: string[]) {\n  let options = _options\n\n  if (typeof _options === 'string') {\n    args.unshift(_options)\n    options = undefined\n  }\n\n  if (command === 'vitest') {\n    args.push('--maxWorkers=1')\n  }\n\n  const subprocess = x(command, args, {\n    ...options as Options,\n    nodeOptions: {\n      ...(options as Options)?.nodeOptions,\n      env: { ...process.env, AI_AGENT: '', ...(options as Options)?.nodeOptions?.env },\n    },\n  }).process!\n  const cli = new Cli({\n    stdin: subprocess.stdin!,\n    stdout: subprocess.stdout!,\n    stderr: subprocess.stderr!,\n    preserveAnsi: typeof _options !== 'string' ? _options?.preserveAnsi : false,\n  })\n\n  let setDone: (value?: unknown) => void\n  const isDone = new Promise(resolve => (setDone = resolve))\n  subprocess.on('exit', () => setDone())\n\n  function output() {\n    return {\n      vitest: cli,\n      exitCode: subprocess.exitCode,\n      stdout: cli.stdout || '',\n      stderr: cli.stderr || '',\n      waitForClose: () => isDone,\n    }\n  }\n\n  // Manually stop the processes so that each test don't have to do this themselves\n  onTestFinished(async () => {\n    if (subprocess.exitCode === null) {\n      subprocess.kill()\n    }\n\n    await isDone\n  })\n\n  if ((options as CliOptions)?.earlyReturn || args.includes('--inspect') || args.includes('--inspect-brk')) {\n    return output()\n  }\n\n  if (args[0] === 'init') {\n    return output()\n  }\n\n  if (args[0] !== 'list' && (args.includes('--watch') || args[0] === 'watch')) {\n    if (command === 'vitest') {\n      // Waiting for either success or failure\n      await Promise.race([\n        cli.waitForStdout('Waiting for file changes'),\n        cli.waitForStdout('Tests failed. Watching for file changes'),\n      ])\n    }\n    // make sure watcher is ready\n    await cli.waitForStdout('[debug] watcher is ready')\n    cli.stdout = cli.stdout.replace('[debug] watcher is ready\\n', '')\n  }\n  else {\n    await isDone\n  }\n\n  return output()\n}\n\nexport async function runVitestCli(_options?: CliOptions | string, ...args: string[]) {\n  process.env.VITE_TEST_WATCHER_DEBUG = 'true'\n  return runCli('vitest', _options, ...args)\n}\n\nexport function getInternalState(): WorkerGlobalState {\n  // @ts-expect-error untyped global\n  return globalThis.__vitest_worker__\n}\n\nconst originalFiles = new Map<string, string>()\n\nexport function createFile(file: string, content: string) {\n  fs.mkdirSync(dirname(file), { recursive: true })\n  fs.writeFileSync(file, content, 'utf-8')\n  onTestFinished(() => {\n    if (fs.existsSync(file)) {\n      fs.unlinkSync(file)\n    }\n  })\n}\n\nexport function editFile(file: string, callback: (content: string) => string) {\n  const content = fs.readFileSync(file, 'utf-8')\n  if (!originalFiles.has(file)) {\n    originalFiles.set(file, content)\n  }\n  fs.writeFileSync(file, callback(content), 'utf-8')\n  onTestFinished(() => {\n    const original = originalFiles.get(file)\n    if (original !== undefined) {\n      fs.writeFileSync(file, original, 'utf-8')\n      originalFiles.delete(file)\n    }\n  })\n}\n\nexport function resolvePath(baseUrl: string, path: string) {\n  const filename = fileURLToPath(baseUrl)\n  return resolve(dirname(filename), path)\n}\n\nexport type TestFsStructure = Record<\n  string,\n  | string\n  | ViteUserConfig\n  | TestProjectConfiguration[]\n  | ((...args: any[]) => unknown)\n  | [(...args: any[]) => unknown, { exports?: string[]; imports?: Record<string, string[]> }]\n>\n\nexport function stripIndent(str: string): string {\n  const normalized = str.replace(/\\t/g, '  ')\n  const match = normalized.match(/^[ \\t]*(?=\\S)/gm)\n  if (!match) {\n    return normalized\n  }\n  const indent = match.filter(m => !!m).reduce((min, line) => Math.min(min, line.length), Infinity)\n  if (indent === 0) {\n    return normalized\n  }\n  return normalized.replace(new RegExp(`^[ ]{${indent}}`, 'gm'), '')\n}\n\nfunction getGeneratedFileContent(content: TestFsStructure[string]) {\n  if (typeof content === 'string') {\n    return content\n  }\n  if (typeof content === 'function') {\n    const code = `await (${stripIndent(String(content))})()`\n    return code\n  }\n  if (Array.isArray(content) && typeof content[1] === 'object' && ('exports' in content[1] || 'imports' in content[1])) {\n    const imports = Object.entries(content[1].imports || [])\n    const code = `\n${imports.map(([path, is]) => `import { ${is.join(', ')} } from '${path}'`)}\nconst results = await (${stripIndent(String(content[0]))})({ ${imports.flatMap(([_, is]) => is).join(', ')} })\n${(content[1].exports || []).map(e => `export const ${e} = results[\"${e}\"]`)}\n    `\n    return code\n  }\n  if ('test' in content && content.test?.browser?.enabled && content.test?.browser?.provider?.name) {\n    const name = content.test.browser.provider.name\n    return `\nimport { ${name} } from '@vitest/browser-${name}'\nconst config = ${JSON.stringify(content)}\nconfig.test.browser.provider = ${name}(${JSON.stringify(content.test.browser.provider.options || {})})\nexport default config\n    `\n  }\n  return `export default ${JSON.stringify(content)}`\n}\n\nexport function useFS<T extends TestFsStructure>(root: string, structure: T, ensureConfig = true, task?: TestContext['task']) {\n  const files = new Set<string>()\n  const hasConfig = Object.keys(structure).some(file => file.includes('.config.'))\n  if (ensureConfig && !hasConfig) {\n    ;(structure as any)['./vitest.config.js'] = {}\n  }\n  for (const file in structure) {\n    const filepath = resolve(root, file)\n    files.add(filepath)\n    const content = getGeneratedFileContent(structure[file])\n    fs.mkdirSync(dirname(filepath), { recursive: true })\n    fs.writeFileSync(filepath, String(content), 'utf-8')\n  }\n  (task?.context.onTestFinished ?? onTestFinished)(() => {\n    if (process.env.VITEST_FS_CLEANUP !== 'false') {\n      fs.rmSync(root, { recursive: true, force: true })\n    }\n  })\n  return {\n    root,\n    readFile: (file: string): string => {\n      const filepath = resolve(root, file)\n      if (relative(root, filepath).startsWith('..')) {\n        throw new Error(`file ${file} is outside of the test file system`)\n      }\n      return fs.readFileSync(filepath, 'utf-8')\n    },\n    editFile: (file: string, callback: (content: string) => string) => {\n      const filepath = resolve(root, file)\n      if (!files.has(filepath)) {\n        throw new Error(`file ${file} is outside of the test file system`)\n      }\n      const content = fs.readFileSync(filepath, 'utf-8')\n      fs.writeFileSync(filepath, callback(content))\n    },\n    createFile: (file: string, content: string) => {\n      if (file.startsWith('..')) {\n        throw new Error(`file ${file} is outside of the test file system`)\n      }\n      const filepath = resolve(root, file)\n      if (files.has(filepath)) {\n        throw new Error(`file ${file} already exists in the test file system`)\n      }\n      files.add(filepath)\n      createFile(filepath, content)\n    },\n    statFile: (file: string): fs.Stats => {\n      const filepath = resolve(root, file)\n\n      if (relative(root, filepath).startsWith('..')) {\n        throw new Error(`file ${file} is outside of the test file system`)\n      }\n\n      return fs.statSync(filepath)\n    },\n    resolveFile: (file: string): string => {\n      return resolve(root, file)\n    },\n    renameFile: (oldFile: string, newFile: string) => {\n      const oldFilepath = resolve(root, oldFile)\n      const newFilepath = resolve(root, newFile)\n      return fs.renameSync(oldFilepath, newFilepath)\n    },\n  }\n}\n\nexport async function runInlineTests(\n  structure: TestFsStructure,\n  config?: RunVitestConfig,\n  options?: VitestRunnerCLIOptions,\n  task?: TestContext['task'],\n) {\n  const root = resolve(process.cwd(), `vitest-test-${crypto.randomUUID()}`)\n  const fs = useFS(root, structure, undefined, task)\n  const vitest = await runVitest({\n    root,\n    ...config,\n  }, [], options)\n  return {\n    fs,\n    root,\n    ...vitest,\n    get results() {\n      return vitest.ctx?.state.getTestModules() || []\n    },\n    testTree() {\n      return buildTestTree(vitest.ctx?.state.getTestModules() || [])\n    },\n    buildTree(onResult: (testResult: TestCase) => any) {\n      return buildTestTree(vitest.ctx?.state.getTestModules() || [], onResult)\n    },\n  }\n}\n\nconst isWindows = process.platform === 'win32'\n\nexport function replaceRoot(string: string, root: string) {\n  const schemaRoot = root.startsWith('file://') ? root : pathToFileURL(root).toString()\n  if (!root.endsWith('/') && !isWindows) {\n    root += '?/'\n  }\n  if (!isWindows) {\n    return string\n      .replace(new RegExp(schemaRoot, 'g'), '<urlRoot>')\n      .replace(new RegExp(root, 'g'), '<root>/')\n  }\n  let unixRoot = root.replace(/\\\\/g, '/')\n  let win32Root = root.replaceAll('/', '\\\\\\\\')\n  if (!root.endsWith('/') && !root.endsWith('\\\\')) {\n    unixRoot += '?/'\n    win32Root += '?\\\\\\\\'\n  }\n\n  return string\n    .replace(new RegExp(schemaRoot, 'gi'), '<urlRoot>')\n    .replace(new RegExp(unixRoot, 'gi'), '<root>/')\n    .replace(new RegExp(win32Root, 'gi'), '<root>/')\n}\n\nexport const ts = String.raw\n\nexport class StableTestFileOrderSorter {\n  sort(files: TestSpecification[]) {\n    return files.sort((a, b) => a.moduleId.localeCompare(b.moduleId))\n  }\n\n  shard(files: TestSpecification[]) {\n    return files\n  }\n}\n\nexport function buildErrorTree(testModules: TestModule[], options?: { stackTrace?: boolean }) {\n  const root = testModules[0]?.project.config.root\n\n  function mapError(e: { message: string; stacks?: { file: string; line: number; column: number; method: string }[] }) {\n    if (options?.stackTrace) {\n      const stacks = (e.stacks || []).map((s) => {\n        const loc = `${relative(root, s.file)}:${s.line}:${s.column}`\n        return s.method ? `    at ${s.method} (${loc})` : `    at ${loc}`\n      })\n      return [e.message, ...stacks].join('\\n')\n    }\n    return e.message\n  }\n\n  return buildTestTree(\n    testModules,\n    (testCase) => {\n      const result = testCase.result()\n      if (result.state === 'failed') {\n        return result.errors.map(e => mapError(e))\n      }\n      return result.state\n    },\n    (testSuite, suiteChildren) => {\n      const errors = testSuite.errors()\n      if (errors.length > 0) {\n        return {\n          ...suiteChildren,\n          __suite_errors__: errors.map(e => mapError(e)),\n        }\n      }\n      return suiteChildren\n    },\n    (testModule, moduleChildren) => {\n      const errors = testModule.errors()\n      if (errors.length > 0) {\n        return {\n          ...moduleChildren,\n          __module_errors__: errors.map(e => mapError(e)),\n        }\n      }\n      return moduleChildren\n    },\n  )\n}\n\nexport function buildTestTree(\n  testModules: TestModule[],\n  onTestCase?: (result: TestCase) => unknown,\n  onTestSuite?: (testSuite: TestSuite, suiteChildren: Record<string, any>) => unknown,\n  onTestModule?: (testModule: TestModule, moduleChildren: Record<string, any>) => unknown,\n) {\n  type TestTree = Record<string, any>\n\n  function walkCollection(collection: TestCollection): TestTree {\n    const node: TestTree = {}\n\n    for (const child of collection) {\n      if (child.type === 'suite') {\n        // Recursively walk suite children\n        const suiteChildren = walkCollection(child.children)\n        node[child.name] = onTestSuite ? onTestSuite(child, suiteChildren) : suiteChildren\n      }\n      else if (child.type === 'test') {\n        const result = child.result()\n        if (onTestCase) {\n          node[child.name] = onTestCase(child)\n        }\n        else {\n          node[child.name] = result.state\n        }\n      }\n    }\n\n    return node\n  }\n\n  const tree: TestTree = {}\n\n  for (const module of testModules) {\n    // Use relative module ID for cleaner output\n    const key = module.relativeModuleId\n    const moduleChildren = walkCollection(module.children)\n    tree[key] = onTestModule ? onTestModule(module, moduleChildren) : moduleChildren\n  }\n\n  return tree\n}\n\nexport function buildTestProjectTree(testModules: TestModule[], onTestCase?: (result: TestCase) => unknown) {\n  const projectTree: Record<string, Record<string, any>> = {}\n\n  for (const testModule of testModules) {\n    const projectName = testModule.project.name\n    projectTree[projectName] = {\n      ...projectTree[projectName],\n      ...buildTestTree([testModule], onTestCase),\n    }\n  }\n\n  return projectTree\n}\n\nexport function buildErrorProjectTree(testModules: TestModule[], options?: { stackTrace?: boolean }) {\n  const projectTree: Record<string, Record<string, any>> = {}\n\n  for (const testModule of testModules) {\n    const projectName = testModule.project.name\n    projectTree[projectName] = {\n      ...projectTree[projectName],\n      ...buildErrorTree([testModule], options),\n    }\n  }\n\n  return projectTree\n}\n"
  },
  {
    "path": "test/test-utils/package.json",
    "content": "{\n  \"name\": \"@vitest/internal-testing-helpers\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"main\": \"./index.ts\",\n  \"scripts\": {\n    \"test\": \"echo \\\"No tests\\\"\"\n  },\n  \"devDependencies\": {\n    \"tinyexec\": \"^1.0.2\",\n    \"tinyrainbow\": \"catalog:\",\n    \"vite\": \"latest\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"types\": [\n      \"node\"\n    ]\n  },\n  \"include\": [\n    \"./**/*.ts\"\n  ]\n}\n"
  },
  {
    "path": "test/typescript/failing/expect-error.test-d.ts",
    "content": "import { expectTypeOf, test } from 'vitest'\n\n//\ntest('failing test with expect-error', () => {\n  // @ts-expect-error expect nothing\n  expectTypeOf(1).toEqualTypeOf<number>()\n})\n"
  },
  {
    "path": "test/typescript/failing/fail.test-d.ts",
    "content": "import { describe, expectTypeOf, test } from 'vitest'\n\ntest('failing test', () => {\n  expectTypeOf(1).toEqualTypeOf<string>()\n})\n\ndescribe('nested suite', () => {\n  describe('nested 2', () => {\n    test('failing test 2', () => {\n      expectTypeOf(1).toBeVoid()\n      expectTypeOf(1).toBeUndefined()\n    })\n  })\n\n  expectTypeOf(1).toBeVoid()\n})\n"
  },
  {
    "path": "test/typescript/failing/js-fail.test-d.js",
    "content": "// @ts-check\n\nimport { expectTypeOf, test } from 'vitest'\n\ntest('js test fails', () => {\n  expectTypeOf(1).toBeArray()\n})\n"
  },
  {
    "path": "test/typescript/failing/node-types.test-d.ts",
    "content": "import { test } from 'vitest'\n\ntest('buffer is not available', () => {\n  Buffer.from([])\n})\n"
  },
  {
    "path": "test/typescript/failing/only.test-d.ts",
    "content": "import { expectTypeOf, test } from 'vitest'\n\ntest.only('failing test', () => {\n  expectTypeOf(1).toEqualTypeOf<string>()\n})\n"
  },
  {
    "path": "test/typescript/fixtures/dynamic-title/test/dynamic-title.test-d.ts",
    "content": "import { expectTypeOf, test } from 'vitest'\n\ntest.each(['some-value'])('each: %s', () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n\ntest.for(['some-value'])('for: %s', () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n\ntest.skipIf(false)('dynamic skip', () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n\ntest(`template string`, () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n\ntest(`template ${'some value'} string`, () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n\ntest(`template ${`literal`} string`, () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n\nconst name = 'some value'\ntest(name, () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n\ntest((() => 'some name')(), () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n"
  },
  {
    "path": "test/typescript/fixtures/dynamic-title/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"target\": \"es2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"verbatimModuleSyntax\": true\n  },\n  \"include\": [\"test\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "test/typescript/fixtures/dynamic-title/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    typecheck: {\n      enabled: true,\n      tsconfig: './tsconfig.json',\n    },\n  },\n})\n"
  },
  {
    "path": "test/typescript/fixtures/source-error/src/not-ok.ts",
    "content": "thisIsSourceError\n"
  },
  {
    "path": "test/typescript/fixtures/source-error/test/ok.test-d.ts",
    "content": "import { expectTypeOf, test } from 'vitest'\n\ntest('ok', () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n"
  },
  {
    "path": "test/typescript/fixtures/source-error/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"target\": \"es2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"verbatimModuleSyntax\": true\n  },\n  \"include\": [\"src\", \"test\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "test/typescript/fixtures/source-error/vite.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    typecheck: {\n      enabled: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/typescript/package.json",
    "content": "{\n  \"name\": \"@vitest/test-typescript\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"test\": \"vitest --test-timeout 60000\",\n    \"types\": \"vitest --typecheck.only --typecheck.allowJs --run\",\n    \"tsc\": \"tsc --watch --pretty false --noEmit\"\n  },\n  \"dependencies\": {\n    \"vitest\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5.9.3\",\n    \"vue-tsc\": \"^3.2.5\"\n  }\n}\n"
  },
  {
    "path": "test/typescript/test/__snapshots__/runner.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`should fail > typecheck files 1`] = `\n\"TypeCheckError: Type 'string' does not satisfy the constraint '\"Expected string, Actual number\"'.\nTypeCheckError: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try \\`npm i --save-dev @types/node\\` and then add 'node' to the types field in your tsconfig.\nTypeCheckError: This expression is not callable. Type 'ExpectArray<number>' has no call signatures.\nTypeCheckError: This expression is not callable. Type 'ExpectUndefined<number>' has no call signatures.\nTypeCheckError: This expression is not callable. Type 'ExpectVoid<number>' has no call signatures.\nTypeCheckError: Type 'string' does not satisfy the constraint '\"Expected string, Actual number\"'.\nTypeCheckError: Unused '@ts-expect-error' directive.\nTypeCheckError: This expression is not callable. Type 'ExpectVoid<number>' has no call signatures.\"\n`;\n\nexports[`should fail > typecheck files 2`] = `\n\" FAIL  fail.test-d.ts > nested suite\nTypeCheckError: This expression is not callable. Type 'ExpectVoid<number>' has no call signatures.\n ❯ fail.test-d.ts:15:19\n     13|   })\n     14|\n     15|   expectTypeOf(1).toBeVoid()\n       |                   ^\n     16| })\"\n`;\n\nexports[`should fail > typecheck files 3`] = `\n\" FAIL  expect-error.test-d.ts > failing test with expect-error\nTypeCheckError: Unused '@ts-expect-error' directive.\n ❯ expect-error.test-d.ts:5:3\n      3| //\n      4| test('failing test with expect-error', () => {\n      5|   // @ts-expect-error expect nothing\n       |   ^\n      6|   expectTypeOf(1).toEqualTypeOf<number>()\"\n`;\n\nexports[`should fail > typecheck files 4`] = `\n\" FAIL  fail.test-d.ts > failing test\nTypeCheckError: Type 'string' does not satisfy the constraint '\"Expected string, Actual number\"'.\n ❯ fail.test-d.ts:4:33\n      2|\n      3| test('failing test', () => {\n      4|   expectTypeOf(1).toEqualTypeOf<string>()\n       |                                 ^\n      5| })\"\n`;\n\nexports[`should fail > typecheck files 5`] = `\n\" FAIL  fail.test-d.ts > nested suite > nested 2 > failing test 2\nTypeCheckError: This expression is not callable. Type 'ExpectVoid<number>' has no call signatures.\n ❯ fail.test-d.ts:10:23\n      8|   describe('nested 2', () => {\n      9|     test('failing test 2', () => {\n     10|       expectTypeOf(1).toBeVoid()\n       |                       ^\n     11|       expectTypeOf(1).toBeUndefined()\"\n`;\n\nexports[`should fail > typecheck files 6`] = `\n\" FAIL  fail.test-d.ts > nested suite > nested 2 > failing test 2\nTypeCheckError: This expression is not callable. Type 'ExpectUndefined<number>' has no call signatures.\n ❯ fail.test-d.ts:11:23\n      9|     test('failing test 2', () => {\n     10|       expectTypeOf(1).toBeVoid()\n     11|       expectTypeOf(1).toBeUndefined()\n       |                       ^\n     12|     })\"\n`;\n\nexports[`should fail > typecheck files 7`] = `\n\" FAIL  js-fail.test-d.js > js test fails\nTypeCheckError: This expression is not callable. Type 'ExpectArray<number>' has no call signatures.\n ❯ js-fail.test-d.js:6:19\n      4|\n      5| test('js test fails', () => {\n      6|   expectTypeOf(1).toBeArray()\n       |                   ^\n      7| })\"\n`;\n\nexports[`should fail > typecheck files 8`] = `\n\" FAIL  node-types.test-d.ts > buffer is not available\nTypeCheckError: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try \\`npm i --save-dev @types/node\\` and then add 'node' to the types field in your tsconfig.\n ❯ node-types.test-d.ts:4:3\n      2|\n      3| test('buffer is not available', () => {\n      4|   Buffer.from([])\n       |   ^\n      5| })\"\n`;\n\nexports[`should fail > typecheck files 9`] = `\n\" FAIL  only.test-d.ts > failing test\nTypeCheckError: Type 'string' does not satisfy the constraint '\"Expected string, Actual number\"'.\n ❯ only.test-d.ts:4:33\n      2|\n      3| test.only('failing test', () => {\n      4|   expectTypeOf(1).toEqualTypeOf<string>()\n       |                                 ^\n      5| })\"\n`;\n\nexports[`should fail > typechecks empty \"include\" but with tests 1`] = `\n\"Testing types with tsc and vue-tsc is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest's version when using it.\n⎯⎯ Unhandled Errors ⎯⎯\n\nVitest caught 1 unhandled error during the test run.\nThis might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.\n\n⎯⎯ Typecheck Error ⎯⎯\nError: error TS18003: No inputs were found in config file '<root>/tsconfig.empty.json'. Specified 'include' paths were '[\"src\"]' and 'exclude' paths were '[\"**/dist/**\"]'.\n\n⎯⎯\n\n\"\n`;\n\nexports[`should fail > typechecks with custom tsconfig 1`] = `\n\"TypeCheckError: This expression is not callable. Type 'ExpectUndefined<number>' has no call signatures.\nTypeCheckError: This expression is not callable. Type 'ExpectVoid<number>' has no call signatures.\nTypeCheckError: Type 'string' does not satisfy the constraint '\"Expected string, Actual number\"'.\nTypeCheckError: This expression is not callable. Type 'ExpectVoid<number>' has no call signatures.\"\n`;\n"
  },
  {
    "path": "test/typescript/test/runner.test.ts",
    "content": "import { resolve } from 'pathe'\nimport { glob } from 'tinyglobby'\nimport { describe, expect, it } from 'vitest'\n\nimport { runVitest } from '../../test-utils'\n\ndescribe('should fail', async () => {\n  const root = resolve(import.meta.dirname, '../failing')\n  const files = await glob(['*.test-d.*'], { cwd: root, expandDirectories: false })\n\n  it('typecheck files', async () => {\n    const { stderr } = await runVitest({\n      root,\n      dir: './failing',\n      typecheck: {\n        enabled: true,\n        allowJs: true,\n        include: ['**/*.test-d.*'],\n        tsconfig: resolve(import.meta.dirname, '../tsconfig.fails.json'),\n      },\n    })\n\n    expect(stderr).toBeTruthy()\n    const lines = String(stderr).split(/\\n/g)\n    const msg = lines\n      .filter(i => i.includes('TypeCheckError: '))\n      .reverse()\n      .join('\\n')\n      .trim()\n      .replace(root, '<rootDir>')\n    expect(stderr).not.toMatch('files found, exiting with code')\n    expect(msg).toMatchSnapshot()\n\n    files.forEach((file) => {\n      expect(String(stderr)).toMatch(`${file}:`)\n    })\n\n    lines.forEach((line, idx) => {\n      if (line.includes('TypeCheckError')) {\n        const msg = lines.slice(idx - 1, idx + 7).join('\\n')\n        expect(msg).toMatchSnapshot()\n      }\n    })\n  })\n\n  it('typechecks with custom tsconfig', async () => {\n    const { stderr } = await runVitest({\n      root,\n      dir: resolve(import.meta.dirname, '..', './failing'),\n      config: resolve('./test/vitest.custom.config.ts'),\n      typecheck: { enabled: true },\n    })\n\n    const lines = String(stderr).split(/\\n/g)\n    const msg = lines\n      .filter(i => i.includes('TypeCheckError: '))\n      .reverse()\n      .join('\\n')\n      .trim()\n      .replace(root, '<rootDir>')\n    expect(stderr).not.toMatch('files found, exiting with code')\n    // only one test file is failed, because only one is included in tsconfig\n    // + file with .only modifier\n    expect(msg).toMatchSnapshot()\n\n    expect(stderr).toContain('FAIL  fail.test-d.ts') // included in tsconfig\n\n    // TODO: Why should this be picked as well?\n    // expect(stderr).toContain('FAIL  only.test-d.ts') // .only\n\n    // not included in tsconfig\n    expect(stderr).not.toContain('expect-error.test-d.ts')\n    expect(stderr).not.toContain('js-fail.test-d.js')\n    expect(stderr).not.toContain('js.test-d.js')\n    expect(stderr).not.toContain('test.test-d.ts')\n  })\n\n  it('typechecks empty \"include\" but with tests', async () => {\n    const { stderr } = await runVitest({\n      root,\n      dir: resolve(import.meta.dirname, '..', './failing'),\n      config: resolve(import.meta.dirname, './vitest.empty.config.ts'),\n      typecheck: { enabled: true },\n    })\n\n    const message = removeLines(stderr.replace(resolve(import.meta.dirname, '..'), '<root>'))\n\n    expect(message).toMatchSnapshot()\n  })\n})\n\ndescribe('ignoreSourceErrors', () => {\n  it('disabled', async () => {\n    const vitest = await runVitest({\n      root: resolve(import.meta.dirname, '../fixtures/source-error'),\n    })\n    expect(vitest.stderr).toContain('Unhandled Errors')\n    expect(vitest.stderr).toContain('Unhandled Source Error')\n    expect(vitest.stderr).toContain('TypeCheckError: Cannot find name \\'thisIsSourceError\\'')\n  })\n\n  it('enabled', async () => {\n    const vitest = await runVitest(\n      {\n        root: resolve(import.meta.dirname, '../fixtures/source-error'),\n        typecheck: {\n          ignoreSourceErrors: true,\n          enabled: true,\n        },\n      },\n    )\n    expect(vitest.stdout).not.toContain('Unhandled Errors')\n    expect(vitest.stderr).not.toContain('Unhandled Source Error')\n    expect(vitest.stderr).not.toContain('TypeCheckError: Cannot find name \\'thisIsSourceError\\'')\n  })\n})\n\ndescribe('when the title is dynamic', () => {\n  it('works correctly', async () => {\n    const vitest = await runVitest({\n      root: resolve(import.meta.dirname, '../fixtures/dynamic-title'),\n      reporters: [['default', { isTTY: true }]],\n    })\n\n    expect(vitest.stdout).toContain('✓ for: %s')\n    expect(vitest.stdout).toContain('✓ each: %s')\n    expect(vitest.stdout).toContain('✓ dynamic skip')\n    expect(vitest.stdout).not.toContain('✓ false') // .skipIf is not reported as a separate test\n    expect(vitest.stdout).toContain('✓ template string')\n    // eslint-disable-next-line no-template-curly-in-string\n    expect(vitest.stdout).toContain('✓ template ${\"some value\"} string')\n    // eslint-disable-next-line no-template-curly-in-string\n    expect(vitest.stdout).toContain('✓ template ${`literal`} string')\n    expect(vitest.stdout).toContain('✓ name')\n    expect(vitest.stdout).toContain('✓ (() => \"some name\")()')\n  })\n})\n\nit('throws an error if typechecker process exists', async () => {\n  const { stderr } = await runVitest({\n    root: resolve(import.meta.dirname, '../fixtures/source-error'),\n    typecheck: {\n      enabled: true,\n      checker: 'non-existing-command',\n    },\n  })\n  expect(stderr).toContain('Error: Spawning typechecker failed - is typescript installed?')\n  if (process.platform === 'win32') {\n    expect(stderr).toContain('Error: The non-existing-command command exited with code 1.')\n  }\n  else {\n    expect(stderr).toContain('Error: spawn non-existing-command ENOENT')\n  }\n})\n\nfunction removeLines(log: string) {\n  return log.replace(/⎯{2,}/g, '⎯⎯')\n}\n"
  },
  {
    "path": "test/typescript/test/typecheck-error.test.ts",
    "content": "import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { describe, expect, it } from 'vitest'\nimport { createFile, runInlineTests } from '../../test-utils'\n\ndescribe('Typechecker Error Handling', () => {\n  it('throws helpful error when tsc outputs help text (missing config)', async () => {\n    // TESTING APPROACH:\n    // We cannot reliably trigger tsc's help text output in normal usage because:\n    // 1. tsc only shows help when called with NO arguments or INVALID arguments\n    // 2. Vitest always calls tsc with proper arguments (--noEmit, --pretty, etc.)\n    // 3. Invalid tsconfig causes ERROR output, not help text\n    //\n    // SOLUTION: Use a test executable that mimics tsc help output\n    // This is NOT a mock (no jest.mock or similar), but a real executable script\n    // that Vitest spawns and executes, validating the error handling logic works.\n\n    // Create a temporary directory for our fake tsc\n    const tmpDir = path.join(os.tmpdir(), `vitest-test-${Date.now()}`)\n\n    // Create fake tsc script - cross-platform executable\n    // Using createFile ensures cleanup even if test fails\n    const fakeTscPath = path.join(tmpDir, 'fake-tsc')\n    const scriptContent = '#!/usr/bin/env node\\nconsole.log(\\'Version 5.3.3\\');\\nconsole.log(\\'tsc: The TypeScript Compiler - Version 5.3.3\\');\\nconsole.log(\\'\\');\\nconsole.log(\\'COMMON COMMANDS\\');\\n'\n\n    createFile(fakeTscPath, scriptContent)\n    fs.chmodSync(fakeTscPath, '755')\n\n    const configContent = `import { defineConfig } from 'vitest/config'\nexport default defineConfig({\n  test: {\n    typecheck: {\n      enabled: true,\n      checker: '${fakeTscPath.replace(/\\\\/g, '/')}',\n    },\n  },\n})`\n\n    const { stderr, stdout } = await runInlineTests({\n      'vitest.config.ts': configContent,\n      'example.test-d.ts': 'import { expectTypeOf, test } from \\'vitest\\'\\ntest(\\'dummy type test\\', () => { expectTypeOf(1).toEqualTypeOf<number>() })',\n    })\n\n    // Assert that Vitest caught the help text and threw the descriptive error\n    const output = stderr + stdout\n    expect(output).toContain('TypeScript compiler returned help text instead of type checking results')\n    expect(output).toContain('This usually means the tsconfig file was not found')\n    expect(output).toContain('Ensure \\'tsconfig.json\\' exists in your project root')\n  })\n})\n"
  },
  {
    "path": "test/typescript/test/typechecker.test.ts",
    "content": "import { resolve } from 'pathe'\nimport { describe, expect, it } from 'vitest'\nimport { runVitest } from '../../test-utils'\n\ndescribe('Typechecker', () => {\n  it('handles non-existing typechecker command gracefully', async () => {\n    const { stderr } = await runVitest({\n      root: resolve(import.meta.dirname, '../fixtures/source-error'),\n      typecheck: {\n        enabled: true,\n        checker: 'non-existing-tsc-command',\n      },\n    })\n\n    // Should show proper error when typechecker doesn't exist\n    expect(stderr).toContain('Spawning typechecker failed')\n  })\n})\n"
  },
  {
    "path": "test/typescript/test/vitest.custom.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    typecheck: {\n      enabled: true,\n      allowJs: true,\n      include: ['**/*.test-d.*'],\n      tsconfig: '../tsconfig.custom.json',\n    },\n  },\n})\n"
  },
  {
    "path": "test/typescript/test/vitest.empty.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    typecheck: {\n      enabled: true,\n      include: ['**/fail.test-d.ts'],\n      tsconfig: '../tsconfig.empty.json',\n    },\n  },\n})\n"
  },
  {
    "path": "test/typescript/test-d/expect-extend.test-d.ts",
    "content": "import { expect, expectTypeOf, test } from 'vitest'\n\ninterface CustomMatchers<R = unknown> {\n  toMatchSchema: (schema: { a: string }) => R\n  toEqualMultiple: (a: string, b: number) => R\n}\n\ndeclare module 'vitest' {\n  interface Matchers<T = any> extends CustomMatchers<T> {}\n}\n\ntest('infers matcher declaration type from a custom matcher type', () => {\n  expect.extend({\n    toMatchSchema(received, expected) {\n      expectTypeOf(received).toBeAny()\n      expectTypeOf(expected).toEqualTypeOf<{ a: string }>()\n\n      return { pass: true, message: () => '' }\n    },\n    toEqualMultiple(received, a, b) {\n      expectTypeOf(received).toBeAny()\n      expectTypeOf(a).toBeString()\n      expectTypeOf(b).toBeNumber()\n\n      return { pass: true, message: () => '' }\n    },\n  })\n\n  expect({ a: 1, b: '2' }).toMatchSchema({ a: '1' })\n  expect('a').toEqualMultiple('a', 1)\n})\n\ntest('automatically extends asymmetric matchers', () => {\n  expect({}).toEqual({\n    nestedSchema: expect.toMatchSchema({\n      a: '1',\n      // @ts-expect-error Unknown property.\n      b: 2,\n    }),\n  })\n})\n\ntest('treats matcher declarations as optional', () => {\n  expect.extend(\n    /**\n     * @note Although annotated, you don't have to declare matchers.\n     * You can call `expect.extend()` multiple times or get the matcher\n     * declarations from a third-party library.\n     */\n    {},\n  )\n})\n"
  },
  {
    "path": "test/typescript/test-d/js.test-d.js",
    "content": "// @ts-check\n\nimport { expectTypeOf, test } from 'vitest'\n\ntest('js test also works', () => {\n  expectTypeOf(1).toEqualTypeOf(2)\n})\n"
  },
  {
    "path": "test/typescript/test-d/nested-suite1.test-d.ts",
    "content": "import { describe, test } from 'vitest'\n\ndescribe('suite-A', () => {\n  describe('suite-B', () => {\n    test('case-X', () => {\n    })\n  })\n})\n\ntest('case-Y', () => {\n})\n"
  },
  {
    "path": "test/typescript/test-d/nested-suite2.test-d.ts",
    "content": "import { describe, test } from 'vitest'\n\ndescribe('suite-A', () => {\n  describe('suite-B', () => {\n    test('case-X', () => {\n    })\n\n    describe('suite-C', () => {\n      test('case-Y', () => {\n      })\n    })\n  })\n\n  describe('suite-D', () => {\n    test('case-Z', () => {\n    })\n  })\n})\n"
  },
  {
    "path": "test/typescript/test-d/test.test-d.ts",
    "content": "/* eslint-disable ts/ban-ts-comment */\n\nimport { describe, expectTypeOf, test, vi } from 'vitest'\n\ndescribe('test', () => {\n  test('some-test', () => {\n    expectTypeOf(Date).toBeConstructibleWith(new Date())\n    expectTypeOf(Date).toBeConstructibleWith('01-01-2000')\n\n    type ResponsiveProp<T> = T | T[] | { xs?: T; sm?: T; md?: T }\n    const getResponsiveProp = <T>(_props: T): ResponsiveProp<T> => ({})\n    interface CSSProperties { margin?: string; padding?: string }\n    const cssProperties: CSSProperties = { margin: '1px', padding: '2px' }\n    expectTypeOf(getResponsiveProp(cssProperties))\n      .exclude<unknown[] | { xs?: unknown }>()\n      // .exclude<{ xs?: unknown }>()\n      .toEqualTypeOf<CSSProperties>()\n  })\n\n  describe('test2', () => {\n    test('some-test 2', () => {\n      expectTypeOf(Promise.resolve('string')).resolves.toEqualTypeOf<string>()\n      expectTypeOf(45).toEqualTypeOf(45)\n    })\n  })\n\n  test('ignored error', () => {\n    // @ts-ignore 45 is not a string\n    expectTypeOf(45).toEqualTypeOf<string>()\n  })\n\n  test('expected error', () => {\n    // @ts-expect-error 45 is not a string\n    expectTypeOf(45).toEqualTypeOf<string>()\n  })\n\n  test('spyOn googleapis compiles', () => {\n    // googleapis-like typing to reproduce https://github.com/vitest-dev/vitest/issues/3141\n    let google!: {\n      [key: string]: unknown\n      sheets: () => { foo: string }\n    }\n    vi.spyOn(google, 'sheets').mockReturnValue({ foo: 'bar' })\n    // @ts-expect-error\n    vi.spyOn(google, 'sheets').mockReturnValue({ foo: 1234 })\n  })\n})\n\nexpectTypeOf({ wolk: 'true' }).toHaveProperty('wolk')\n"
  },
  {
    "path": "test/typescript/tsconfig.custom.json",
    "content": "{\n  \"extends\": \"../../tsconfig.build.json\",\n  \"include\": [\n    \"**/fail.test-d.ts\"\n  ],\n  \"exclude\": [\n    \"**/dist/**\"\n  ]\n}\n"
  },
  {
    "path": "test/typescript/tsconfig.empty.json",
    "content": "{\n  \"extends\": \"../../tsconfig.build.json\",\n  \"include\": [\n    \"src\"\n  ],\n  \"exclude\": [\n    \"**/dist/**\"\n  ]\n}\n"
  },
  {
    "path": "test/typescript/tsconfig.fails.json",
    "content": "{\n  \"extends\": \"../../tsconfig.build.json\",\n  \"compilerOptions\": {\n    \"types\": []\n  },\n  \"include\": [\n    \"./failing/*\"\n  ],\n  \"exclude\": [\n    \"**/dist/**\"\n  ]\n}\n"
  },
  {
    "path": "test/typescript/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.build.json\",\n  \"include\": [\n    \"./**/*.ts\",\n    \"./**/*.js\"\n  ],\n  \"exclude\": [\n    \"**/dist/**\",\n    \"**/fixtures/**\"\n  ]\n}\n"
  },
  {
    "path": "test/typescript/vitest.config.fails.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\n// pnpm -C test/typescript test -- -c vitest.config.fails.ts\nexport default defineConfig({\n  test: {\n    dir: './failing',\n    typecheck: {\n      enabled: true,\n      allowJs: true,\n      include: ['**/*.test-d.*'],\n      tsconfig: './tsconfig.fails.json',\n    },\n  },\n})\n"
  },
  {
    "path": "test/ui/.gitignore",
    "content": "html\ntest-results\n"
  },
  {
    "path": "test/ui/fixtures/annotated.test.ts",
    "content": "import { test } from 'vitest'\n\ntest('annotated test', async ({ annotate }) => {\n  await annotate('hello world')\n  await annotate('second annotation')\n})\n\ntest('annotated typed test', async ({ annotate }) => {\n  await annotate('beware!', 'warning')\n})\n\ntest('annotated file test', async ({ annotate }) => {\n  await annotate('file annotation', {\n    path: './fixtures/example.txt'\n  })\n})\n\ntest('annotated image test', async ({ annotate }) => {\n  await annotate('image annotation', {\n    path: './fixtures/cute-puppy.jpg'\n  })\n})\n\ntest('annotated with body', async ({ annotate }) => {\n  await annotate('body annotation', {\n    contentType: 'text/markdown',\n    // requires pre-encoded base64 for raw string\n    // https://github.com/vitest-dev/vitest/issues/9633\n    body: btoa('Hello **markdown**'),\n  })\n})\n"
  },
  {
    "path": "test/ui/fixtures/console.test.ts",
    "content": "/* eslint-disable no-console */\n\nimport { afterAll, beforeAll, it, describe, expect } from \"vitest\";\nimport { prettyDOM } from \"@testing-library/dom\";\n\n// https://github.com/vitest-dev/vitest/issues/2765\nit('regexp', () => {\n  console.log(/(?<char>\\w)/)\n})\n\n// https://github.com/vitest-dev/vitest/issues/3934\nit('html-raw', async () => {\n  console.log(`\n<form>\n  <label for=\"email\">Email Address</label>\n  <input name=\"email\" />\n  <button>Submit</button>\n</form>\n`);\n})\n\n// https://github.com/vitest-dev/vitest/issues/1279\nit('html-pretty', () => {\n  const div = document.createElement(\"div\");\n  div.innerHTML = `\n    <form>\n      <label for=\"email\">Email Address</label>\n      <input name=\"email\" />\n      <button>Submit</button>\n    </form>\n  `.replaceAll(/\\n */gm, \"\"); // strip new lines\n  console.log(prettyDOM(div))\n})\n\n\nbeforeAll(() => {\n  console.log('beforeAll')\n  console.error('beforeAll')\n})\n\nafterAll(() => {\n  console.log('afterAll')\n  console.error('afterAll')\n})\n\ndescribe('suite', () => {\n  beforeAll(() => {\n    console.log('beforeAll')\n    console.error('beforeAll')\n  })\n\n  afterAll(() => {\n    console.log('afterAll')\n    console.error('afterAll')\n  })\n\n  describe('nested suite', () => {\n    beforeAll(() => {\n      console.log('beforeAll')\n      console.error('beforeAll')\n    })\n\n    afterAll(() => {\n      console.log('afterAll')\n      console.error('afterAll')\n    })\n\n    it('test', () => {\n      expect(true).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "test/ui/fixtures/coverage.test.ts",
    "content": "import { expect, it } from 'vitest'\nimport { multiply } from './coverage'\n\nit(multiply, () => {\n  expect(multiply(2, 3)).toEqual(6)\n})\n"
  },
  {
    "path": "test/ui/fixtures/coverage.ts",
    "content": "export function multiply(n: number, m: number) {\n  return n * m;\n}\n"
  },
  {
    "path": "test/ui/fixtures/error.test.ts",
    "content": "import { expect, it } from \"vitest\"\n\n// https://github.com/vitest-dev/vitest/issues/5321\nit('escape html in error diff', () => {\n  expect('<style>* {border: 2px solid green};</style>').toBe(\"\")\n})\n"
  },
  {
    "path": "test/ui/fixtures/example.txt",
    "content": "hello world\n"
  },
  {
    "path": "test/ui/fixtures/sample.test.ts",
    "content": "import { expect, it } from 'vitest'\n\nit('add', () => {\n  // eslint-disable-next-line no-console\n  console.log('log test')\n  setTimeout(() => {\n    throw new Error('error')\n  })\n  setTimeout(() => {\n    throw 1\n  })\n  expect(1 + 1).toEqual(2)\n})\n\nit('has tags', { tags: ['db', 'flaky'] }, () => {\n  // ...\n})\n"
  },
  {
    "path": "test/ui/fixtures/snapshot.test.ts",
    "content": "import { expect, test } from 'vitest';\n\ntest('wrong snapshot', () => {\n  expect(1).toMatchInlineSnapshot(`2`)\n})\n"
  },
  {
    "path": "test/ui/fixtures/task-name.test.ts",
    "content": "import { it, expect} from \"vitest\"\n\nit('<MyComponent />', () => {\n  expect(true).toBe(true)\n})\n\nit('<>\\'\"', () => {\n  expect(true).toBe(true)\n})\n\nit('char () - Square root of nine (9)', () => {\n  expect(Math.sqrt(9)).toBe(3);\n});\n"
  },
  {
    "path": "test/ui/fixtures-browser/visual-regression.test.ts",
    "content": "import { test } from 'vitest'\nimport { server } from 'vitest/browser'\n\ntest('visual regression test', async ({ expect, onTestFinished }) => {\n  const screenshotName = 'visual-regression-screenshot.png'\n\n  onTestFinished(async () => {\n    if (server.config.snapshotOptions.updateSnapshot !== 'none') {\n      await server.commands.removeFile(`fixtures-browser/${screenshotName}`)\n    }\n  })\n\n  await expect(expect(document.body).toMatchScreenshot(screenshotName)).rejects.toThrow(\n    'No existing reference screenshot found',\n  )\n})\n"
  },
  {
    "path": "test/ui/package.json",
    "content": "{\n  \"name\": \"@vitest/test-ui\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"GITHUB_ACTIONS=false playwright test\",\n    \"test-e2e\": \"GITHUB_ACTIONS=false playwright test\",\n    \"test-e2e-ui\": \"GITHUB_ACTIONS=false playwright test --ui\",\n    \"test-fixtures\": \"vitest\"\n  },\n  \"devDependencies\": {\n    \"@testing-library/dom\": \"^10.4.1\",\n    \"@vitest/browser-playwright\": \"workspace:*\",\n    \"happy-dom\": \"latest\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/ui/playwright.config.ts",
    "content": "import { defineConfig, devices } from '@playwright/test'\n\nexport default defineConfig({\n  testDir: './test',\n  projects: [\n    {\n      name: 'chromium',\n      // increase viewport height so virtual scroller renders all explorer items\n      use: { ...devices['Desktop Chrome'], viewport: { width: 1280, height: 900 } },\n    },\n  ],\n  use: {\n    trace: process.env.CI ? 'on-first-retry' : 'on',\n  },\n  forbidOnly: !!process.env.CI,\n  retries: process.env.CI ? 2 : 0,\n})\n"
  },
  {
    "path": "test/ui/test/html-report.spec.ts",
    "content": "import type { PreviewServer } from 'vite'\nimport { readFileSync } from 'node:fs'\nimport { Writable } from 'node:stream'\nimport { expect, test } from '@playwright/test'\nimport { preview } from 'vite'\nimport { startVitest } from 'vitest/node'\n\nconst port = 9001\nconst pageUrl = `http://localhost:${port}/custom/base/`\n\ntest.describe('html report', () => {\n  let previewServer: PreviewServer\n\n  test.beforeAll(async () => {\n    // silence Vitest logs\n    const stdout = new Writable({ write: (_, __, callback) => callback() })\n    const stderr = new Writable({ write: (_, __, callback) => callback() })\n    // generate vitest html report\n    await startVitest(\n      'test',\n      [],\n      {\n        run: true,\n        reporters: 'html',\n        coverage: {\n          enabled: true,\n        },\n      },\n      {},\n      {\n        stdout,\n        stderr,\n      },\n    )\n\n    // run vite preview server\n    previewServer = await preview({\n      base: '/custom/base/',\n      build: { outDir: 'html' },\n      preview: { port, strictPort: true },\n    })\n  })\n\n  test.afterAll(async () => {\n    await previewServer?.close()\n  })\n\n  test('basic', async ({ page }) => {\n    const pageErrors: unknown[] = []\n    page.on('pageerror', error => pageErrors.push(error))\n\n    await page.goto(pageUrl)\n\n    // dashboard\n    await expect(page.getByTestId('pass-entry')).toContainText('16 Pass')\n    await expect(page.getByTestId('fail-entry')).toContainText('2 Fail')\n    await expect(page.getByTestId('total-entry')).toContainText('18 Total')\n\n    // unhandled errors\n    await expect(page.getByTestId('unhandled-errors')).toContainText(\n      'Vitest caught 2 errors during the test run. This might cause false positive tests. '\n      + 'Resolve unhandled errors to make sure your tests are not affected.',\n    )\n\n    await expect(page.getByTestId('unhandled-errors-details')).toContainText('Error: error')\n    await expect(page.getByTestId('unhandled-errors-details')).toContainText('Unknown Error: 1')\n\n    // report\n    const sample = page.getByTestId('results-panel').getByLabel('sample.test.ts')\n    await sample.hover()\n    await sample.getByTestId('btn-open-details').click({ force: true })\n    await page.getByText('All tests passed in this file').click()\n\n    // graph tab\n    await page.getByTestId('btn-graph').click()\n    await expect(page.locator('[data-testid=graph] text')).toContainText('sample.test.ts')\n\n    // console tab\n    await page.getByTestId('btn-console').click()\n    await expect(page.getByTestId('console')).toContainText('log test')\n\n    expect(pageErrors).toEqual([])\n  })\n\n  test('coverage', async ({ page }) => {\n    await page.goto(pageUrl)\n    await page.getByLabel('Show coverage').click()\n    await page.frameLocator('#vitest-ui-coverage').getByRole('heading', { name: 'All files' }).click()\n  })\n\n  test('error', async ({ page }) => {\n    await page.goto(pageUrl)\n    const sample = page.getByTestId('results-panel').getByLabel('fixtures/error.test.ts')\n    await sample.hover()\n    await sample.getByTestId('btn-open-details').click({ force: true })\n    await expect(page.getByTestId('diff')).toContainText('- Expected + Received + <style>* {border: 2px solid green};</style>')\n  })\n\n  test('annotations in the report tab', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    await test.step('annotated test', async () => {\n      const item = page.getByLabel('annotated test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotations = page.getByRole('note')\n      await expect(annotations).toHaveCount(2)\n\n      await expect(annotations.first()).toContainText('hello world')\n      await expect(annotations.first()).toContainText('notice')\n      await expect(annotations.first()).toContainText('fixtures/annotated.test.ts:4:9')\n\n      await expect(annotations.last()).toContainText('second annotation')\n      await expect(annotations.last()).toContainText('notice')\n      await expect(annotations.last()).toContainText('fixtures/annotated.test.ts:5:9')\n    })\n\n    await test.step('annotated typed test', async () => {\n      const item = page.getByLabel('annotated typed test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotation = page.getByRole('note')\n      await expect(annotation).toHaveCount(1)\n\n      await expect(annotation).toContainText('beware!')\n      await expect(annotation).toContainText('warning')\n      await expect(annotation).toContainText('fixtures/annotated.test.ts:9:9')\n    })\n\n    await test.step('annotated file test', async () => {\n      const item = page.getByLabel('annotated file test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotation = page.getByRole('note')\n      await expect(annotation).toHaveCount(1)\n\n      await expect(annotation).toContainText('file annotation')\n      await expect(annotation).toContainText('notice')\n      await expect(annotation).toContainText('fixtures/annotated.test.ts:13:9')\n      await expect(annotation.getByRole('link')).toHaveAttribute('href', /data\\/\\w+/)\n    })\n\n    await test.step('annotated image test', async () => {\n      const item = page.getByLabel('annotated image test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotation = page.getByRole('note')\n      await expect(annotation).toHaveCount(1)\n\n      await expect(annotation).toContainText('image annotation')\n      await expect(annotation).toContainText('notice')\n      await expect(annotation).toContainText('fixtures/annotated.test.ts:19:9')\n      await expect(annotation.getByRole('link')).toHaveAttribute('href', /data\\/\\w+/)\n      const img = annotation.getByRole('img')\n      await expect(img).toHaveAttribute('src', /data\\/\\w+/)\n      await expect(img).not.toHaveJSProperty('naturalWidth', 0)\n    })\n\n    await test.step('annotated with body', async () => {\n      const item = page.getByLabel('annotated with body')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotation = page.getByRole('note')\n      await expect(annotation).toHaveCount(1)\n\n      await expect(annotation).toContainText('body annotation')\n      await expect(annotation).toContainText('notice')\n      await expect(annotation).toContainText('fixtures/annotated.test.ts:25:9')\n\n      const downloadPromise = page.waitForEvent('download')\n      await annotation.getByRole('link').click()\n      const download = await downloadPromise\n      expect(download.suggestedFilename()).toBe('body-annotation.md')\n      const downloadPath = await download.path()\n      const content = readFileSync(downloadPath, 'utf-8')\n      expect(content).toBe('Hello **markdown**')\n    })\n  })\n\n  test('annotations', async ({ page }) => {\n    await page.goto(pageUrl)\n    const item = page.getByLabel('fixtures/annotated.test.ts')\n    await item.hover()\n    await item.getByTestId('btn-open-details').click({ force: true })\n    await page.getByTestId('btn-code').click({ force: true })\n\n    const annotations = page.getByRole('note')\n    await expect(annotations).toHaveCount(6)\n\n    await expect(annotations.first()).toHaveText('notice: hello world')\n    await expect(annotations.nth(1)).toHaveText('notice: second annotation')\n    await expect(annotations.nth(2)).toHaveText('warning: beware!')\n    await expect(annotations.nth(3)).toHaveText(/notice: file annotation/)\n    await expect(annotations.nth(4)).toHaveText('notice: image annotation')\n    await expect(annotations.nth(5)).toHaveText(/notice: body annotation/)\n\n    await expect(annotations.nth(3).getByRole('link')).toHaveAttribute('href', /data\\/\\w+/)\n    await expect(annotations.nth(4).getByRole('link')).toHaveAttribute('href', /data\\/\\w+/)\n    await expect(annotations.nth(5).getByRole('link')).toHaveAttribute('href', /^data:text\\/markdown;base64,/)\n  })\n\n  test('tags filter', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    await page.getByPlaceholder('Search...').fill('tag:db')\n\n    // only one test with the tag \"db\"\n    await expect(page.getByText('PASS (1)')).toBeVisible()\n    await expect(page.getByTestId('explorer-item').filter({ hasText: 'has tags' })).toBeVisible()\n\n    await page.getByPlaceholder('Search...').fill('tag:db && !flaky')\n    await expect(page.getByText('No matched test')).toBeVisible()\n\n    await page.getByPlaceholder('Search...').fill('tag:unknown')\n    await expect(page.getByText('The tag pattern \"unknown\" is not defined in the configuration')).toBeVisible()\n  })\n\n  test('visual regression in the report tab', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    await test.step('attachments get processed', async () => {\n      const item = page.getByLabel('visual regression test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const artifact = page.getByRole('note')\n      await expect(artifact).toHaveCount(1)\n\n      await expect(artifact.getByRole('heading')).toContainText('Visual Regression')\n      await expect(artifact).toContainText('fixtures-browser/visual-regression.test.ts:13:3')\n      await expect(artifact.getByRole('tablist')).toHaveText('Reference')\n      await expect(artifact.getByRole('tabpanel').getByRole('link')).toHaveAttribute('href', /data\\/\\w+\\.png/)\n      const vrImg = artifact.getByRole('tabpanel').getByRole('img')\n      await expect(vrImg).toHaveAttribute('src', /data\\/\\w+\\.png/)\n      await expect(vrImg).not.toHaveJSProperty('naturalWidth', 0)\n    })\n  })\n})\n"
  },
  {
    "path": "test/ui/test/ui-security.spec.ts",
    "content": "import type { Vitest } from 'vitest/node'\nimport { Writable } from 'node:stream'\nimport { expect, test } from '@playwright/test'\nimport { startVitest } from 'vitest/node'\n\nconst port = 9002\nconst pageUrl = `http://localhost:${port}/__vitest__/`\n\ntest.describe('ui', () => {\n  let vitest: Vitest | undefined\n\n  test.beforeAll(async () => {\n    // silence Vitest logs\n    const stdout = new Writable({ write: (_, __, callback) => callback() })\n    const stderr = new Writable({ write: (_, __, callback) => callback() })\n    vitest = await startVitest('test', [], {\n      watch: true,\n      ui: true,\n      open: false,\n      api: {\n        port,\n        allowExec: false,\n        allowWrite: false,\n      },\n      reporters: [],\n    }, {}, {\n      stdout,\n      stderr,\n    })\n    expect(vitest).toBeDefined()\n  })\n\n  test.afterAll(async () => {\n    await vitest?.close()\n  })\n\n  test('cannot execute files from the ui', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    await expect(page.getByTestId('btn-run-all')).toBeDisabled()\n\n    const item = page.getByTestId('explorer-item').nth(0)\n    await item.hover()\n    await expect(item.getByTestId('btn-run-test')).toBeDisabled()\n\n    await page.getByPlaceholder('Search...').fill('snapshot')\n\n    const snapshotItem = page.getByTestId('explorer-item').filter({ hasText: 'snapshot.test.ts' })\n    await snapshotItem.hover()\n    await expect(snapshotItem.getByTestId('btn-fix-snapshot')).not.toBeVisible()\n  })\n\n  test('cannot write files', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    const item = page.getByTestId('explorer-item').nth(0)\n    await item.hover()\n    await item.getByTestId('btn-open-details').click()\n\n    await page.getByText('Code').click()\n\n    const editor = page.getByTestId('btn-code')\n    await expect(editor).toBeVisible()\n\n    await editor.click()\n    await page.keyboard.type('\\n// some comment')\n\n    await expect(editor).not.toContainText('// some comment')\n  })\n})\n"
  },
  {
    "path": "test/ui/test/ui.spec.ts",
    "content": "import type { Vitest } from 'vitest/node'\nimport { readFileSync } from 'node:fs'\nimport { Writable } from 'node:stream'\nimport { expect, test } from '@playwright/test'\nimport { startVitest } from 'vitest/node'\n\nconst port = 9000\nconst pageUrl = `http://localhost:${port}/__vitest__/`\n\ntest.describe('ui', () => {\n  let vitest: Vitest | undefined\n\n  test.beforeAll(async () => {\n    // silence Vitest logs\n    const stdout = new Writable({ write: (_, __, callback) => callback() })\n    const stderr = new Writable({ write: (_, __, callback) => callback() })\n    vitest = await startVitest('test', [], {\n      watch: true,\n      ui: true,\n      open: false,\n      api: { port },\n      coverage: { enabled: true },\n      reporters: [],\n    }, {}, {\n      stdout,\n      stderr,\n    })\n    expect(vitest).toBeDefined()\n  })\n\n  test.afterAll(async () => {\n    await vitest?.close()\n  })\n\n  test('security', async ({ page }, testInfo) => {\n    const response = await page.goto('https://example.com/', { timeout: 5000 }).catch(() => null)\n\n    testInfo.skip(!response, 'External resource is not available')\n\n    // request html\n    const htmlResult = await page.evaluate(async (pageUrl) => {\n      try {\n        const res = await fetch(pageUrl)\n        return res.status\n      }\n      catch (e) {\n        return e instanceof Error ? e.message : e\n      }\n    }, pageUrl)\n    expect(htmlResult).toBe('Failed to fetch')\n\n    // request websocket\n    const wsResult = await page.evaluate(async (pageUrl) => {\n      const ws = new WebSocket(new URL('/__vitest_api__', pageUrl))\n      return new Promise((resolve) => {\n        ws.addEventListener('open', () => {\n          resolve('open')\n        })\n        ws.addEventListener('error', () => {\n          resolve('error')\n        })\n      })\n    }, pageUrl)\n    expect(wsResult).toBe('error')\n  })\n\n  test('basic', async ({ page }) => {\n    const pageErrors: unknown[] = []\n    page.on('pageerror', error => pageErrors.push(error))\n\n    await page.goto(pageUrl)\n\n    // dashboard\n    await expect(page.getByTestId('pass-entry')).toContainText('16 Pass')\n    await expect(page.getByTestId('fail-entry')).toContainText('2 Fail')\n    await expect(page.getByTestId('total-entry')).toContainText('18 Total')\n\n    // unhandled errors\n    await expect(page.getByTestId('unhandled-errors')).toContainText(\n      'Vitest caught 2 errors during the test run. This might cause false positive tests. '\n      + 'Resolve unhandled errors to make sure your tests are not affected.',\n    )\n\n    await expect(page.getByTestId('unhandled-errors-details')).toContainText('Error: error')\n    await expect(page.getByTestId('unhandled-errors-details')).toContainText('Unknown Error: 1')\n\n    // report\n    const sample = page.getByTestId('results-panel').getByLabel('sample.test.ts')\n    await sample.hover()\n    await sample.getByTestId('btn-open-details').click({ force: true })\n    await page.getByText('All tests passed in this file').click()\n\n    // graph tab\n    await page.getByTestId('btn-graph').click()\n    await expect(page.locator('[data-testid=graph] text')).toContainText('sample.test.ts')\n\n    // console tab\n    await page.getByTestId('btn-console').click()\n    await expect(page.getByTestId('console')).toContainText('log test')\n\n    expect(pageErrors).toEqual([])\n  })\n\n  test('coverage', async ({ page }) => {\n    await page.goto(pageUrl)\n    await page.getByLabel('Show coverage').click()\n    await page.frameLocator('#vitest-ui-coverage').getByRole('heading', { name: 'All files' }).click()\n  })\n\n  test('console', async ({ page }) => {\n    await page.goto(pageUrl)\n    const item = page.getByLabel('fixtures/console.test.ts')\n    await item.hover()\n    await item.getByTestId('btn-open-details').click({ force: true })\n    await page.getByTestId('btn-console').click()\n    await page.getByText('/(?<char>\\\\w)/').click()\n\n    expect(await page.getByText('beforeAll').all()).toHaveLength(6)\n    expect(await page.getByText('afterAll').all()).toHaveLength(6)\n  })\n\n  test('annotations in the report tab', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    await test.step('annotated test', async () => {\n      const item = page.getByLabel('annotated test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotations = page.getByRole('note')\n      await expect(annotations).toHaveCount(2)\n\n      await expect(annotations.first()).toContainText('hello world')\n      await expect(annotations.first()).toContainText('notice')\n      await expect(annotations.first()).toContainText('fixtures/annotated.test.ts:4:9')\n\n      await expect(annotations.last()).toContainText('second annotation')\n      await expect(annotations.last()).toContainText('notice')\n      await expect(annotations.last()).toContainText('fixtures/annotated.test.ts:5:9')\n    })\n\n    await test.step('annotated typed test', async () => {\n      const item = page.getByLabel('annotated typed test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotation = page.getByRole('note')\n      await expect(annotation).toHaveCount(1)\n\n      await expect(annotation).toContainText('beware!')\n      await expect(annotation).toContainText('warning')\n      await expect(annotation).toContainText('fixtures/annotated.test.ts:9:9')\n    })\n\n    await test.step('annotated file test', async () => {\n      const item = page.getByLabel('annotated file test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotation = page.getByRole('note')\n      await expect(annotation).toHaveCount(1)\n\n      await expect(annotation).toContainText('file annotation')\n      await expect(annotation).toContainText('notice')\n      await expect(annotation).toContainText('fixtures/annotated.test.ts:13:9')\n      await expect(annotation.getByRole('link')).toHaveAttribute('href', /__vitest_attachment__\\?path=/)\n    })\n\n    await test.step('annotated image test', async () => {\n      const item = page.getByLabel('annotated image test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotation = page.getByRole('note')\n      await expect(annotation).toHaveCount(1)\n\n      await expect(annotation).toContainText('image annotation')\n      await expect(annotation).toContainText('notice')\n      await expect(annotation).toContainText('fixtures/annotated.test.ts:19:9')\n      await expect(annotation.getByRole('link')).toHaveAttribute('href', /__vitest_attachment__\\?path=/)\n      await expect(annotation.getByRole('img')).toHaveAttribute('src', /__vitest_attachment__\\?path=/)\n    })\n\n    await test.step('annotated with body', async () => {\n      const item = page.getByLabel('annotated with body')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const annotation = page.getByRole('note')\n      await expect(annotation).toHaveCount(1)\n\n      await expect(annotation).toContainText('body annotation')\n      await expect(annotation).toContainText('notice')\n      await expect(annotation).toContainText('fixtures/annotated.test.ts:25:9')\n\n      const downloadPromise = page.waitForEvent('download')\n      await annotation.getByRole('link').click()\n      const download = await downloadPromise\n      expect(download.suggestedFilename()).toBe('body-annotation.md')\n      const downloadPath = await download.path()\n      const content = readFileSync(downloadPath, 'utf-8')\n      expect(content).toBe('Hello **markdown**')\n    })\n  })\n\n  test('annotations in the editor tab', async ({ page }) => {\n    await page.goto(pageUrl)\n    const item = page.getByLabel('fixtures/annotated.test.ts')\n    await item.hover()\n    await item.getByTestId('btn-open-details').click({ force: true })\n    await page.getByTestId('btn-code').click({ force: true })\n\n    const annotations = page.getByRole('note')\n    await expect(annotations).toHaveCount(6)\n\n    await expect(annotations.first()).toHaveText('notice: hello world')\n    await expect(annotations.nth(1)).toHaveText('notice: second annotation')\n    await expect(annotations.nth(2)).toHaveText('warning: beware!')\n    await expect(annotations.nth(3)).toHaveText(/notice: file annotation/)\n    await expect(annotations.nth(4)).toHaveText('notice: image annotation')\n    await expect(annotations.nth(5)).toHaveText(/notice: body annotation/)\n\n    await expect(annotations.nth(3).getByRole('link')).toHaveAttribute('href', /__vitest_attachment__\\?path=/)\n    await expect(annotations.nth(4).getByRole('link')).toHaveAttribute('href', /__vitest_attachment__\\?path=/)\n    await expect(annotations.nth(5).getByRole('link')).toHaveAttribute('href', /^data:text\\/markdown;base64,/)\n  })\n\n  test('error', async ({ page }) => {\n    await page.goto(pageUrl)\n    const item = page.getByLabel('fixtures/error.test.ts')\n    await item.hover()\n    await item.getByTestId('btn-open-details').click({ force: true })\n    await expect(page.getByTestId('diff')).toContainText('- Expected + Received + <style>* {border: 2px solid green};</style>')\n  })\n\n  test('file-filter', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    // match all files when no filter\n    await page.getByPlaceholder('Search...').fill('')\n    await page.getByText('PASS (6)').click()\n    await expect(page.getByTestId('results-panel').getByText('fixtures/sample.test.ts', { exact: true })).toBeVisible()\n\n    // match nothing\n    await page.getByPlaceholder('Search...').fill('nothing')\n    await page.getByText('No matched test').click()\n\n    // searching \"add\" will match \"sample.test.ts\" since it includes a test case named \"add\"\n    await page.getByPlaceholder('Search...').fill('add')\n    await page.getByText('PASS (1)').click()\n    await expect(page.getByTestId('results-panel').getByText('fixtures/sample.test.ts', { exact: true })).toBeVisible()\n\n    // match only failing files when fail filter applied\n    await page.getByPlaceholder('Search...').fill('')\n    await page.getByText(/^Fail$/, { exact: true }).click()\n    await page.getByText('FAIL (2)').click()\n    await expect(page.getByTestId('results-panel').getByText('fixtures/error.test.ts', { exact: true })).toBeVisible()\n    await expect(page.getByTestId('results-panel').getByText('fixtures/sample.test.ts', { exact: true })).toBeHidden()\n\n    // match only pass files when fail filter applied\n    await page.getByPlaceholder('Search...').fill('console')\n    await page.getByText(/^Fail$/, { exact: true }).click()\n    await page.locator('span').filter({ hasText: /^Pass$/ }).click()\n    await page.getByText('PASS (1)').click()\n    await expect(page.getByTestId('results-panel').getByText('fixtures/console.test.ts', { exact: true })).toBeVisible()\n    await expect(page.getByTestId('results-panel').getByText('fixtures/sample.test.ts', { exact: true })).toBeHidden()\n\n    // html entities in task names are escaped\n    await page.locator('span').filter({ hasText: /^Pass$/ }).click()\n    await page.getByPlaceholder('Search...').fill('<MyComponent />')\n    // for some reason, the tree is collapsed by default: we need to click on the nav buttons to expand it\n    await page.getByTestId('collapse-all').click()\n    await page.getByTestId('expand-all').click()\n    await expect(page.getByText('<MyComponent />')).toBeVisible()\n    await expect(page.getByTestId('results-panel').getByText('fixtures/task-name.test.ts', { exact: true })).toBeVisible()\n\n    // html entities in task names are escaped\n    await page.getByPlaceholder('Search...').fill('<>\\'\"')\n    await expect(page.getByText('<>\\'\"')).toBeVisible()\n    await expect(page.getByTestId('results-panel').getByText('fixtures/task-name.test.ts', { exact: true })).toBeVisible()\n\n    // pass files with special chars\n    await page.getByPlaceholder('Search...').fill('char () - Square root of nine (9)')\n    await expect(page.getByText('char () - Square root of nine (9)')).toBeVisible()\n    const testItem = page.getByTestId('explorer-item').filter({ hasText: 'char () - Square root of nine (9)' })\n    await testItem.hover()\n    await testItem.getByLabel('Run current test').click()\n    await expect(page.getByText('The test has passed without any errors')).toBeVisible()\n  })\n\n  test('tags filter', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    await page.getByPlaceholder('Search...').fill('tag:db')\n\n    // only one test with the tag \"db\"\n    await expect(page.getByText('PASS (1)')).toBeVisible()\n    await expect(page.getByTestId('explorer-item').filter({ hasText: 'has tags' })).toBeVisible()\n\n    await page.getByPlaceholder('Search...').fill('tag:db && !flaky')\n    await expect(page.getByText('No matched test')).toBeVisible()\n\n    await page.getByPlaceholder('Search...').fill('tag:unknown')\n    await expect(page.getByText('The tag pattern \"unknown\" is not defined in the configuration')).toBeVisible()\n  })\n\n  test('dashboard entries filter tests correctly', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    // Initial state should show all tests\n    await expect(page.getByTestId('pass-entry')).toBeVisible()\n    await expect(page.getByTestId('fail-entry')).toBeVisible()\n    await expect(page.getByTestId('total-entry')).toBeVisible()\n\n    // Click \"Pass\" entry and verify only passing tests are shown\n    await page.getByTestId('pass-entry').click()\n    await expect(page.getByLabel(/pass/i)).toBeChecked()\n\n    // Click \"Fail\" entry and verify only failing tests are shown\n    await page.getByTestId('fail-entry').click()\n    await expect(page.getByLabel(/fail/i)).toBeChecked()\n\n    // Click \"Skip\" entry if there are skipped tests\n    if (await page.getByTestId('skipped-entry').isVisible()) {\n      await page.getByTestId('skipped-entry').click()\n      await expect(page.getByLabel(/skip/i)).toBeChecked()\n    }\n\n    // Click \"Total\" entry to reset filters and show all tests again\n    await page.getByTestId('total-entry').click()\n    await expect(page.getByLabel(/pass/i)).not.toBeChecked()\n    await expect(page.getByLabel(/fail/i)).not.toBeChecked()\n    await expect(page.getByLabel(/skip/i)).not.toBeChecked()\n  })\n\n  test('visual regression in the report tab', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    await test.step('attachments get processed', async () => {\n      const item = page.getByLabel('visual regression test')\n      await item.click({ force: true })\n      await page.getByTestId('btn-report').click({ force: true })\n\n      const artifact = page.getByRole('note')\n      await expect(artifact).toHaveCount(1)\n\n      await expect(artifact.getByRole('heading')).toContainText('Visual Regression')\n      await expect(artifact).toContainText('fixtures-browser/visual-regression.test.ts:13:3')\n      await expect(artifact.getByRole('tablist')).toHaveText('Reference')\n      await expect(artifact.getByRole('tabpanel').getByRole('link')).toHaveAttribute('href', /__vitest_attachment__\\?path=.*?\\.png/)\n      await expect(artifact.getByRole('tabpanel').getByRole('img')).toHaveAttribute('src', /__vitest_attachment__\\?path=.*?\\.png/)\n    })\n  })\n})\n\ntest.describe('standalone', () => {\n  let vitest: Vitest | undefined\n\n  test.beforeAll(async () => {\n    // silence Vitest logs\n    const stdout = new Writable({ write: (_, __, callback) => callback() })\n    const stderr = new Writable({ write: (_, __, callback) => callback() })\n    vitest = await startVitest('test', [], {\n      watch: true,\n      ui: true,\n      standalone: true,\n      open: false,\n      api: { port },\n      reporters: [],\n    }, {}, {\n      stdout,\n      stderr,\n    })\n    expect(vitest).toBeDefined()\n  })\n\n  test.afterAll(async () => {\n    await vitest?.close()\n  })\n\n  test('basic', async ({ page }) => {\n    await page.goto(pageUrl)\n\n    // initially no stats\n    await expect(page.locator('[aria-labelledby=tests]')).toContainText('0 Pass 0 Fail 0 Total')\n\n    // run single file\n    await page.getByText('fixtures/sample.test.ts').hover()\n    await page.getByRole('button', { name: 'Run current file' }).click()\n\n    // check results\n    await page.getByText('PASS (1)').click()\n    expect(vitest?.state.getFiles().map(f => [f.name, f.result?.state])).toEqual([\n      ['fixtures/sample.test.ts', 'pass'],\n    ])\n  })\n})\n"
  },
  {
    "path": "test/ui/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"baseUrl\": \"../..\",\n    \"paths\": {\n      \"vitest/node\": [\n        \"./packages/vitest/node.d.ts\",\n        \"./packages/vitest/dist/node.js\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "test/ui/vitest.config.ts",
    "content": "import { resolve } from 'node:path'\nimport { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    coverage: {\n      reportOnFailure: true,\n    },\n    tags: [\n      { name: 'db' },\n      { name: 'flaky' },\n    ],\n    projects: [{\n      extends: true,\n      test: {\n        name: 'fixtures',\n        dir: './fixtures',\n        environment: 'happy-dom',\n      },\n    }, {\n      extends: true,\n      test: {\n        name: 'browser',\n        dir: './fixtures-browser',\n        browser: {\n          enabled: true,\n          headless: true,\n          provider: playwright(),\n          instances: [{ browser: 'chromium' }],\n          screenshotFailures: false,\n          expect: {\n            toMatchScreenshot: {\n              resolveScreenshotPath: ({ root, testFileDirectory, arg, ext }) => resolve(root, testFileDirectory, `${arg}${ext}`),\n            },\n          },\n        },\n      },\n    }],\n  },\n})\n"
  },
  {
    "path": "test/workspaces/.gitignore",
    "content": "results.json"
  },
  {
    "path": "test/workspaces/coverage-report-tests/check-coverage.test.ts",
    "content": "import { existsSync, readFileSync } from 'node:fs'\nimport libCoverage from 'istanbul-lib-coverage'\nimport { resolve } from 'pathe'\nimport { expect, test } from 'vitest'\n\ntest('coverage exists', () => {\n  expect(existsSync('./coverage')).toBe(true)\n  expect(existsSync('./coverage/index.html')).toBe(true)\n})\n\ntest('file coverage summary matches', () => {\n  const coverageJson = JSON.parse(readFileSync('./coverage/coverage-final.json', 'utf-8'))\n  const coverageMap = libCoverage.createCoverageMap(coverageJson)\n  const fileCoverage = coverageMap.fileCoverageFor(resolve('./src/math.ts'))\n\n  // There should be 1 uncovered branch and 1 uncovered function. See math.ts.\n  const { branches, functions } = fileCoverage.toSummary()\n\n  expect(branches.total - branches.covered).toBe(1)\n  expect(functions.total - functions.covered).toBe(1)\n})\n\ntest('coverage of file transformed by multiple plugins is merged correctly', async () => {\n  const coverageJson = JSON.parse(readFileSync('./coverage/coverage-final.json', 'utf-8'))\n  const coverageMap = libCoverage.createCoverageMap(coverageJson)\n  const fileCoverage = coverageMap.fileCoverageFor(resolve('./space-multi-transform/src/multi-transform.ts'))\n  const lineCoverage = fileCoverage.getLineCoverage()\n\n  // Condition not covered by any test\n  expect(lineCoverage[13]).toBe(0)\n\n  // Condition covered by Project #1 but not by Project #2\n  expect(lineCoverage[18]).toBe(1)\n\n  // Condition not covered by any test\n  expect(lineCoverage[22]).toBe(0)\n\n  // Condition covered by Project #2 but not by Project #1\n  expect(lineCoverage[26]).toBe(1)\n\n  // Condition covered by both tests\n  expect(lineCoverage[30]).toBe(2)\n})\n"
  },
  {
    "path": "test/workspaces/coverage-report-tests/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    include: ['./check-coverage.test.ts'],\n  },\n})\n"
  },
  {
    "path": "test/workspaces/cwdPlugin.d.ts",
    "content": "import type { Plugin } from 'vite'\n\nexport function cwdPlugin(name: string): Plugin\n"
  },
  {
    "path": "test/workspaces/cwdPlugin.js",
    "content": "// @ts-check\n\nexport function cwdPlugin(name) {\n  return {\n    name: `vitest:test:workspace-${name}`,\n    configResolved() {\n      process.env[`${name}_CWD_CONFIG`] = process.cwd()\n    },\n    configureServer() {\n      process.env[`${name}_CWD_SERVER`] = process.cwd()\n    },\n  }\n}\n"
  },
  {
    "path": "test/workspaces/globalTest.ts",
    "content": "import type { TestProject } from 'vitest/node'\nimport assert from 'node:assert/strict'\nimport { readFile } from 'node:fs/promises'\n\ndeclare module 'vitest' {\n  interface ProvidedContext {\n    globalSetup: boolean\n    globalSetupOverridden: boolean\n    invalidValue: unknown\n    projectConfigValue: boolean\n    globalConfigValue: boolean\n\n    providedConfigValue: string\n  }\n}\n\nexport function setup({ provide }: TestProject) {\n  provide('globalSetup', true)\n  provide('globalSetupOverridden', false)\n  try {\n    provide('invalidValue', () => {})\n    throw new Error('Should throw')\n  }\n  catch (err: any) {\n    assert.equal(err.message, 'Cannot provide \"invalidValue\" because it\\'s not serializable.')\n    assert.match(err.cause.message, /could not be cloned/)\n    assert.equal(err.cause.name, 'DataCloneError')\n  }\n}\n\nlet teardownCalled = false\n\nexport async function teardown() {\n  teardownCalled = true\n  const results = JSON.parse(await readFile('./results.json', 'utf-8'))\n\n  try {\n    assert.ok(results.success)\n    assert.equal(results.numTotalTestSuites, 20)\n    assert.equal(results.numTotalTests, 25)\n    assert.equal(results.numPassedTests, 25)\n    assert.ok(results.coverageMap)\n\n    const shared = results.testResults.filter((r: any) => r.name.includes('space_shared/test.spec.ts'))\n\n    assert.equal(shared.length, 2)\n  }\n  catch (err) {\n    console.error(err)\n    // eslint-disable-next-line no-console\n    console.dir(results, { depth: null })\n    process.exit(1)\n  }\n}\n\nprocess.on('beforeExit', () => {\n  if (!teardownCalled) {\n    console.error('teardown was not called')\n    process.exitCode = 1\n  }\n})\n"
  },
  {
    "path": "test/workspaces/package.json",
    "content": "{\n  \"name\": \"@vitest/test-workspaces\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"pnpm test:workspace && pnpm test:coverage\",\n    \"test:workspace\": \"vitest run\",\n    \"test:coverage\": \"vitest run --root coverage-report-tests\"\n  },\n  \"devDependencies\": {\n    \"@jridgewell/remapping\": \"catalog:\",\n    \"@types/istanbul-lib-coverage\": \"catalog:\",\n    \"istanbul-lib-coverage\": \"catalog:\",\n    \"jsdom\": \"latest\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/workspaces/space-multi-transform/src/multi-transform.ts",
    "content": "/**\n * The variable below is modified by custom Vite plugin\n */\nexport const padding = 'default-padding'\n\nexport function run(name: string) {\n  /*\n   * These if-branches should show correctly on coverage report.\n   * Otherwise source maps are off.\n   */\n  if (name === 'not-covered') {\n    // This is not covered by any test\n    return 0\n  }\n  // Comment\n  else if (name === 'project-1') {\n    // This is covered by Project #1\n    return 1\n  }\n  else if (name === 'not-covered-2') {\n    // This is not covered by any test\n    return 0\n  }\n  else if (name === 'project-2') {\n    // This is covered by Project #2\n    return 2\n  }\n\n  // This is covered by both projects, should show 2x hits\n  return 3\n}\n"
  },
  {
    "path": "test/workspaces/space-multi-transform/test/project-1.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { run } from '../src/multi-transform'\n\ntest('cover some branches', () => {\n  expect(run('project-1')).toBe(1)\n\n  expect(run('last branch')).toBe(3)\n})\n"
  },
  {
    "path": "test/workspaces/space-multi-transform/test/project-2.test.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { run } from '../src/multi-transform'\n\ntest('cover some branches', () => {\n  expect(run('project-2')).toBe(2)\n\n  expect(run('last branch')).toBe(3)\n})\n"
  },
  {
    "path": "test/workspaces/space-pools/forks.test.ts",
    "content": "import { isMainThread } from 'node:worker_threads'\nimport { expect, test } from 'vitest'\n\ntest('is run in \"node:child_process\"', () => {\n  expect(isChildProcess()).toBe(true)\n  expect(isMainThread).toBe(true)\n})\n\n// TODO: Use from \"src/utils/base.ts\" after #4441\nfunction isChildProcess(): boolean {\n  return !!process?.send\n}\n"
  },
  {
    "path": "test/workspaces/space-pools/isolate.test.ts",
    "content": "import type { ViteUserConfig } from 'vitest/config'\nimport { expect, test } from 'vitest'\n\ntest('is isolated', () => {\n  // @ts-expect-error -- internal\n  const config: NonNullable<ViteUserConfig['test']> = globalThis.__vitest_worker__.config\n\n  if (config.pool === 'forks') {\n    expect(config.isolate).toBe(true)\n  }\n  else {\n    expect(config.pool).toBe('threads')\n    expect(config.isolate).toBe(true)\n  }\n})\n"
  },
  {
    "path": "test/workspaces/space-pools/no-isolate.test.ts",
    "content": "import type { ViteUserConfig } from 'vitest/config'\nimport { expect, test } from 'vitest'\n\ntest('is not isolated', () => {\n  // @ts-expect-error -- internal\n  const config: NonNullable<ViteUserConfig['test']> = globalThis.__vitest_worker__.config\n\n  if (config.pool === 'forks') {\n    expect(config.isolate).toBe(false)\n  }\n  else {\n    expect(config.pool).toBe('threads')\n    expect(config.isolate).toBe(false)\n  }\n})\n"
  },
  {
    "path": "test/workspaces/space-pools/threads.test.ts",
    "content": "import { isMainThread } from 'node:worker_threads'\nimport { expect, test } from 'vitest'\n\ntest('is run in \"node:worker_threads\"', () => {\n  expect(isChildProcess()).toBe(false)\n  expect(isMainThread).toBe(false)\n})\n\n// TODO: Use from \"src/utils/base.ts\" after #4441\nfunction isChildProcess(): boolean {\n  return !!process?.send\n}\n"
  },
  {
    "path": "test/workspaces/space_1/test/env-injected.spec.ts",
    "content": "import { resolve } from 'node:path'\nimport { expect, test } from 'vitest'\n\ndeclare global {\n  const __DEV__: boolean\n}\n\ntest('dev is injected', () => {\n  expect(__DEV__).toBe(true)\n})\n\ntest('env variable is assigned', () => {\n  // we override it with \"local\" in .env.local, but dotenv prefers the root .env\n  // this is consistent with how Vite works\n  expect(import.meta.env.VITE_MY_TEST_VARIABLE).toBe('core')\n  expect(process.env.VITE_MY_TEST_VARIABLE).toBe('core')\n  expect(import.meta.env.CUSTOM_MY_TEST_VARIABLE).toBe('custom')\n  expect(process.env.CUSTOM_MY_TEST_VARIABLE).toBe('custom')\n\n  expect(process.env.VITE_CORE_VARIABLE).toBe('core')\n  expect(process.env.CUSTOM_ROOT).toBe('custom')\n  expect(process.env.ROOT_VARIABLE).toBe('root')\n  expect(process.env.CONFIG_VAR).toBe('root')\n  expect(process.env.CONFIG_LOCAL).toBe('local')\n  expect(process.env.CONFIG_OVERRIDE).toBe('local')\n})\n\ntest('cwd is resolved correctly', () => {\n  const spaceRoot = resolve(import.meta.dirname, '..')\n  const rootPath = resolve(spaceRoot, '..')\n\n  expect(process.env.ROOT_CWD_CONFIG).toBe(rootPath)\n  expect(process.env.ROOT_CWD_SERVER).toBe(rootPath)\n\n  // ideally, it should be a `spaceRoot`, but support was reverted\n  // in https://github.com/vitest-dev/vitest/pull/6811\n  expect(process.env.SPACE_2_CWD_CONFIG).toBe(rootPath)\n  expect(process.env.SPACE_2_CWD_SERVER).toBe(rootPath)\n})\n"
  },
  {
    "path": "test/workspaces/space_1/test/happy-dom.spec.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('window is defined', () => {\n  expect(window).toBeDefined()\n})\n"
  },
  {
    "path": "test/workspaces/space_1/test/math.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { sum } from '../../src/math'\n\ntest('3 + 3 = 6', () => {\n  expect(sum(3, 3)).toBe(6)\n})\n"
  },
  {
    "path": "test/workspaces/space_1/vite.config.ts",
    "content": "import { defineProject } from 'vitest/config'\nimport { cwdPlugin } from '../cwdPlugin'\n\nexport default defineProject({\n  envPrefix: ['VITE_', 'CUSTOM_'],\n  plugins: [cwdPlugin('SPACE_2')],\n  define: {\n    __DEV__: 'true',\n  },\n  test: {\n    name: 'space_1',\n    environment: 'happy-dom',\n    env: {\n      CONFIG_LOCAL: 'local',\n      CONFIG_OVERRIDE: 'local',\n    },\n  },\n})\n"
  },
  {
    "path": "test/workspaces/space_1/vite.config.ts.timestamp-4345324-324424.mjs",
    "content": "import { defineProject } from 'vitest/config'\n\nexport default defineProject({\n  test: {\n    name: 'space_1',\n    environment: 'happy-dom',\n  },\n})\n"
  },
  {
    "path": "test/workspaces/space_2/test/node.spec.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('window is not defined', () => {\n  expect(typeof window).toBe('undefined')\n})\n"
  },
  {
    "path": "test/workspaces/space_3/fake-vitest/config.js",
    "content": "exports.defineProject = (c) => {\n  return c\n}\n"
  },
  {
    "path": "test/workspaces/space_3/fake-vitest/index.js",
    "content": "throw new Error('should not import from fake vitest')\n"
  },
  {
    "path": "test/workspaces/space_3/fake-vitest/package.json",
    "content": "{\n  \"name\": \"vitest\",\n  \"type\": \"commonjs\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./config\": \"./config.js\"\n  }\n}\n"
  },
  {
    "path": "test/workspaces/space_3/global-provide.space-3-test.ts",
    "content": "import { expect, inject, test } from 'vitest'\n\ntest('global setup provides data correctly', () => {\n  expect(inject('globalSetup')).toBe(true)\n  expect(inject('globalSetupOverridden')).toBe(true)\n  expect(inject('projectConfigValue')).toBe(true)\n  expect(inject('globalConfigValue')).toBe(true)\n  expect(inject('invalidValue')).toBe(undefined)\n})\n"
  },
  {
    "path": "test/workspaces/space_3/localSetup.ts",
    "content": "import type { TestProject } from 'vitest/node'\n\nexport function setup({ provide }: TestProject) {\n  provide('globalSetupOverridden', true)\n}\n"
  },
  {
    "path": "test/workspaces/space_3/math.space-3-test.ts",
    "content": "import { expect, test } from 'vitest'\nimport { sum } from '../src/math'\nimport { multiple } from './src/multiply'\n\ntest('2 x 2 = 4', () => {\n  expect(multiple(2, 2)).toBe(4)\n})\n\ntest('2 + 2 = 4', () => {\n  expect(sum(2, 2)).toBe(4)\n})\n"
  },
  {
    "path": "test/workspaces/space_3/package.json",
    "content": "{\n  \"name\": \"@vitest/space_3\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"vitest\"\n  },\n  \"dependencies\": {\n    \"vitest\": \"link:./fake-vitest\"\n  }\n}\n"
  },
  {
    "path": "test/workspaces/space_3/src/multiply.ts",
    "content": "export function multiple(a: number, b: number) {\n  return a * b\n}\n"
  },
  {
    "path": "test/workspaces/space_3/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'throw-error',\n      config() {\n        throw new Error('This file should not initiate a test project.')\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "test/workspaces/space_3/vitest.config.ts",
    "content": "import { defineProject } from 'vitest/config'\n\nexport default defineProject({\n  test: {\n    include: ['**/*.space-3-test.ts'],\n    environment: 'node',\n    globalSetup: './localSetup.ts',\n    provide: {\n      projectConfigValue: true,\n    },\n  },\n})\n"
  },
  {
    "path": "test/workspaces/space_shared/setup.jsdom.ts",
    "content": "Object.defineProperty(globalThis, 'testValue', { value: 'jsdom' })\n"
  },
  {
    "path": "test/workspaces/space_shared/setup.node.ts",
    "content": "Object.defineProperty(globalThis, 'testValue', { value: 'node' })\n"
  },
  {
    "path": "test/workspaces/space_shared/test.spec.ts",
    "content": "import { expect, it } from 'vitest'\n\ndeclare global {\n  const testValue: string\n}\n\nconst custom = it.extend({\n  providedConfigValue: ['default value', { injected: true }],\n})\n\ncustom('provided config value is injected', ({ providedConfigValue }) => {\n  expect(providedConfigValue).toBe(\n    // happy-dom provides the value in the workspace config\n    expect.getState().environment === 'node'\n      ? 'default value'\n      : 'actual config value',\n  )\n})\n\nit('the same file works with different projects', () => {\n  expect(testValue).toBe(expect.getState().environment === 'node' ? 'node' : 'jsdom')\n})\n"
  },
  {
    "path": "test/workspaces/src/math.ts",
    "content": "/* eslint-disable unused-imports/no-unused-vars */\nexport function sum(a: number, b: number) {\n  if (a === 3 && b === 4) {\n    // This should be uncovered\n    return 7\n  }\n\n  return a + b\n}\n\nfunction uncoveredFunction() {\n  // This should be uncovered\n  return 1\n}\n"
  },
  {
    "path": "test/workspaces/vitest.config.ts",
    "content": "import type { Vite } from 'vitest/node'\nimport remapping from '@jridgewell/remapping'\nimport MagicString from 'magic-string'\nimport { defineConfig } from 'vitest/config'\nimport { cwdPlugin } from './cwdPlugin.js'\n\nexport default defineConfig({\n  envPrefix: ['VITE_', 'CUSTOM_', 'ROOT_'],\n  plugins: [cwdPlugin('ROOT')],\n  test: {\n    coverage: {\n      enabled: true,\n      provider: 'istanbul',\n    },\n    reporters: ['default', 'json'],\n    outputFile: './results.json',\n    globalSetup: './globalTest.ts',\n    env: {\n      CONFIG_VAR: 'root',\n      CONFIG_OVERRIDE: 'root',\n    },\n    provide: {\n      globalConfigValue: true,\n    },\n    projects: [\n      'space_2',\n      './space_*/vitest.config.ts',\n      './space_1/*.config.ts',\n      async () => ({\n        test: {\n          name: 'happy-dom',\n          root: './space_shared',\n          environment: 'happy-dom',\n          setupFiles: ['./setup.jsdom.ts'],\n          provide: {\n            providedConfigValue: 'actual config value',\n          },\n        },\n      }),\n      Promise.resolve({\n        test: {\n          name: 'node',\n          root: './space_shared',\n          environment: 'node',\n          setupFiles: ['./setup.node.ts'],\n        },\n      }),\n\n      // Projects testing pool and poolOptions\n      {\n        test: {\n          name: 'Threads pool',\n          include: [\n            './space-pools/threads.test.ts',\n            './space-pools/isolate.test.ts',\n          ],\n          pool: 'threads',\n        },\n      },\n      {\n        test: {\n          name: 'Non-parallel thread pool',\n          include: [\n            './space-pools/threads.test.ts',\n          ],\n          pool: 'threads',\n          fileParallelism: false,\n        },\n      },\n      {\n        test: {\n          name: 'Non-isolated thread pool',\n          include: [\n            './space-pools/threads.test.ts',\n            './space-pools/no-isolate.test.ts',\n          ],\n          pool: 'threads',\n          isolate: false,\n        },\n      },\n      {\n        test: {\n          name: 'Forks pool',\n          include: [\n            './space-pools/forks.test.ts',\n            './space-pools/isolate.test.ts',\n          ],\n          pool: 'forks',\n        },\n      },\n      {\n        test: {\n          name: 'Non-parallel fork pool',\n          include: [\n            './space-pools/forks.test.ts',\n          ],\n          pool: 'forks',\n          fileParallelism: false,\n        },\n      },\n      {\n        test: {\n          name: 'Non-isolated fork pool',\n          include: [\n            './space-pools/forks.test.ts',\n            './space-pools/no-isolate.test.ts',\n          ],\n          pool: 'forks',\n          isolate: false,\n        },\n      },\n\n      // These two projects run on same environment but still transform\n      // a single file differently due to Vite plugins\n      {\n        plugins: [customPlugin(0)],\n        test: {\n          name: 'Project with custom plugin #1',\n          environment: 'node',\n          include: ['./space-multi-transform/test/project-1.test.ts'],\n        },\n      },\n      {\n        plugins: [customPlugin(15)],\n        test: {\n          name: 'Project with custom plugin #2',\n          environment: 'node',\n          include: ['./space-multi-transform/test/project-2.test.ts'],\n        },\n      },\n    ],\n  },\n})\n\nfunction customPlugin(offset: number): Vite.Plugin {\n  return {\n    name: 'vitest-custom-multi-transform',\n    enforce: 'pre',\n    transform(code, id) {\n      if (id.includes('space-multi-transform/src/multi-transform.ts')) {\n        const padding = '\\n*****'.repeat(offset)\n\n        const transformed = new MagicString(code)\n        transformed.replace('\\'default-padding\\'', `\\`${padding}\\``)\n\n        const map = remapping(\n          [transformed.generateMap({ hires: true }), this.getCombinedSourcemap() as any],\n          () => null,\n        ) as any\n\n        return { code: transformed.toString(), map }\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "test/workspaces/vitest.config.watch.ts",
    "content": "import { defineConfig, mergeConfig } from 'vitest/config'\nimport vitestConfig from './vitest.config'\n\n// Patch stdin on the process so that we can fake it to seem like a real interactive terminal and pass the TTY checks\nprocess.stdin.isTTY = true\nprocess.stdin.setRawMode = () => process.stdin\n\nexport default mergeConfig(vitestConfig, defineConfig({\n  test: {\n    coverage: {\n      enabled: false,\n    },\n    reporters: ['default'],\n    globalSetup: undefined,\n  },\n}))\n"
  },
  {
    "path": "test/workspaces-browser/.gitignore",
    "content": "results.json"
  },
  {
    "path": "test/workspaces-browser/globalTest.ts",
    "content": "import assert from 'node:assert/strict'\nimport { readFile } from 'node:fs/promises'\n\nlet teardownCalled = false\n\nexport async function teardown() {\n  teardownCalled = true\n  const results = JSON.parse(await readFile('./results.json', 'utf-8'))\n\n  try {\n    assert.ok(results.success)\n    assert.equal(results.numTotalTestSuites, 4)\n    assert.equal(results.numTotalTests, 5)\n    assert.equal(results.numPassedTests, 5)\n  }\n  catch (err) {\n    console.error(err)\n    // eslint-disable-next-line no-console\n    console.dir(results, { depth: null })\n    process.exit(1)\n  }\n}\n\nprocess.on('beforeExit', () => {\n  if (!teardownCalled) {\n    console.error('teardown was not called')\n    process.exitCode = 1\n  }\n})\n"
  },
  {
    "path": "test/workspaces-browser/package.json",
    "content": "{\n  \"name\": \"@vitest/test-workspaces-browser\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"test\": \"vitest run\"\n  },\n  \"devDependencies\": {\n    \"@vitest/browser-playwright\": \"workspace:^\",\n    \"vitest\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "test/workspaces-browser/space_1/test/math.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { sum } from '../../src/math'\n\ntest('3 + 3 = 6', () => {\n  expect(sum(3, 3)).toBe(6)\n})\n"
  },
  {
    "path": "test/workspaces-browser/space_1/test/node.spec.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('window is undefined', () => {\n  expect(globalThis.window).toBeUndefined()\n})\n"
  },
  {
    "path": "test/workspaces-browser/space_1/vite.config.ts",
    "content": "import { defineProject } from 'vitest/config'\n\nexport default defineProject({\n  test: {\n    name: 'space_1',\n  },\n})\n"
  },
  {
    "path": "test/workspaces-browser/space_1/vitest.config.ts.timestamp-4345324-324424.mjs",
    "content": "import { defineProject } from 'vitest/config'\n\nexport default defineProject({\n  test: {\n    name: 'space_1',\n    environment: 'happy-dom',\n  },\n})\n"
  },
  {
    "path": "test/workspaces-browser/space_browser/test/browser.spec.ts",
    "content": "import { expect, test } from 'vitest'\n\ntest('window is not defined', () => {\n  expect(typeof window).toBe('object')\n})\n"
  },
  {
    "path": "test/workspaces-browser/space_browser/vitest.config.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\nimport { defineProject } from 'vitest/config'\n\nexport default defineProject({\n  test: {\n    browser: {\n      enabled: true,\n      instances: [{ browser: process.env.BROWSER as 'chromium' || 'chromium' }],\n      headless: true,\n      provider: playwright(),\n    },\n  },\n})\n"
  },
  {
    "path": "test/workspaces-browser/space_browser_inline/test/basic.test.ts",
    "content": "// @ts-expect-error alias\nimport testAliasVite from 'test-alias-from-vite'\n\n// @ts-expect-error alias\nimport testAliasVitest from 'test-alias-from-vitest'\n\nimport { expect, test } from 'vitest'\n\ntest('window is defined', () => {\n  expect(typeof window).toBe('object')\n})\n\ntest('alias from workspace inline config', () => {\n  expect(testAliasVite).toBe('hello')\n  expect(testAliasVitest).toBe('hello')\n})\n"
  },
  {
    "path": "test/workspaces-browser/space_browser_inline/test-alias-to.ts",
    "content": "export default 'hello'\n"
  },
  {
    "path": "test/workspaces-browser/src/math.ts",
    "content": "/* eslint-disable unused-imports/no-unused-vars */\nexport function sum(a: number, b: number) {\n  if (a === 3 && b === 4) {\n    // This should be uncovered\n    return 7\n  }\n\n  return a + b\n}\n\nfunction uncoveredFunction() {\n  // This should be uncovered\n  return 1\n}\n"
  },
  {
    "path": "test/workspaces-browser/vitest.config.ts",
    "content": "import { playwright } from '@vitest/browser-playwright'\nimport { defineConfig } from 'vitest/config'\n\nif (process.env.TEST_WATCH) {\n  // Patch stdin on the process so that we can fake it to seem like a real interactive terminal and pass the TTY checks\n  process.stdin.isTTY = true\n  process.stdin.setRawMode = () => process.stdin\n}\n\nexport default defineConfig({\n  test: {\n    reporters: ['default', 'json'],\n    outputFile: './results.json',\n    globalSetup: './globalTest.ts',\n    projects: [\n      './space_*/*.config.ts',\n      {\n        cacheDir: '.cache/inline',\n        test: {\n          name: 'space_browser_inline',\n          root: './space_browser_inline',\n          browser: {\n            enabled: true,\n            instances: [{ browser: process.env.BROWSER as 'chromium' || 'chromium' }],\n            headless: true,\n            provider: playwright(),\n          },\n          alias: {\n            'test-alias-from-vitest': new URL('./space_browser_inline/test-alias-to.ts', import.meta.url).pathname,\n          },\n        },\n        resolve: {\n          alias: {\n            'test-alias-from-vite': new URL('./space_browser_inline/test-alias-to.ts', import.meta.url).pathname,\n          },\n        },\n      },\n    ],\n  },\n})\n"
  },
  {
    "path": "tsconfig.base.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"lib\": [\"esnext\"],\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"paths\": {\n      \"@vitest/ws-client\": [\"./packages/ws-client/src/index.ts\"],\n      \"@vitest/ui\": [\"./packages/ui/node/index.ts\"],\n      \"@vitest/pretty-format\": [\"./packages/pretty-format/src/index.ts\"],\n      \"@vitest/utils\": [\"./packages/utils/src/index.ts\"],\n      \"@vitest/utils/*\": [\"./packages/utils/src/*\"],\n      \"@vitest/spy\": [\"./packages/spy/src/index.ts\"],\n      \"@vitest/snapshot\": [\"./packages/snapshot/src/index.ts\"],\n      \"@vitest/snapshot/*\": [\"./packages/snapshot/src/*\"],\n      \"@vitest/expect\": [\"./packages/expect/src/index.ts\"],\n      \"@vitest/mocker\": [\"./packages/mocker/src/index.ts\"],\n      \"@vitest/mocker/node\": [\"./packages/mocker/src/node/index.ts\"],\n      \"@vitest/mocker/browser\": [\"./packages/mocker/src/browser/index.ts\"],\n      \"@vitest/mocker/transforms\": [\"./packages/mocker/src/node/transforms.ts\"],\n      \"@vitest/runner\": [\"./packages/runner/src/index.ts\"],\n      \"@vitest/runner/*\": [\"./packages/runner/src/*\"],\n      \"@vitest/browser-playwright\": [\"./packages/browser-playwright/src/index.ts\"],\n      \"@vitest/browser\": [\"./packages/browser/src/node/index.ts\"],\n      \"@vitest/browser/client\": [\"./packages/browser/src/client/client.ts\"],\n      \"~/*\": [\"./packages/ui/client/*\"],\n      \"vitest\": [\"./packages/vitest/src/public/index.ts\"],\n      \"vitest/internal/browser\": [\"./packages/vitest/src/public/browser.ts\"],\n      \"vitest/globals\": [\"./packages/vitest/globals.d.ts\"],\n      \"vitest/browser\": [\"./packages/vitest/browser/context.d.ts\"],\n      \"vitest/*\": [\"./packages/vitest/src/public/*\"],\n      \"#test-utils\": [\"./test/test-utils/index.ts\"]\n    },\n    \"allowImportingTsExtensions\": true,\n    \"strict\": true,\n    \"declaration\": true,\n    \"noEmit\": true,\n    \"stripInternal\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  }\n}\n"
  },
  {
    "path": "tsconfig.build.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"paths\": {\n      \"vitest\": [\"./packages/vitest/dist/index.d.ts\"],\n      \"vitest/*\": [\"./packages/vitest/dist/*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "tsconfig.check.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"types\": [\n      \"node\",\n      \"vite/client\"\n    ]\n  },\n  \"exclude\": [\n    \"**/dist/**\",\n    \"./packages/vitest/dist/**\",\n    \"./packages/ui/**/*.spec.ts\",\n    \"./packages/ui/client/test.ts\",\n    \"./packages/*/*.d.ts\",\n    \"./packages/*/*.d.cts\",\n    \"./examples/**/*.*\",\n    \"./bench/**\",\n    \"./test/cli/**\",\n    \"./test/typescript/**\",\n    \"./test/browser/**\",\n    \"**/coverage/fixtures/**\",\n    \"./test/watch/fixtures/**\"\n  ]\n}\n"
  }
]